summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt19
-rw-r--r--CREDITS.TXT10
-rw-r--r--Makefile14
-rw-r--r--Makefile.config.in35
-rw-r--r--Makefile.rules117
-rw-r--r--README.txt1
-rwxr-xr-xautoconf/AutoRegen.sh4
-rwxr-xr-xautoconf/config.guess249
-rwxr-xr-xautoconf/config.sub186
-rw-r--r--autoconf/configure.ac247
-rw-r--r--bindings/ocaml/llvm/META.llvm.in63
-rw-r--r--bindings/ocaml/llvm/Makefile21
-rw-r--r--bindings/ocaml/llvm/llvm.ml254
-rw-r--r--bindings/ocaml/llvm/llvm.mli213
-rw-r--r--bindings/ocaml/llvm/llvm_ocaml.c292
-rw-r--r--bindings/ocaml/target/llvm_target.ml2
-rw-r--r--bindings/ocaml/target/llvm_target.mli7
-rw-r--r--bindings/ocaml/target/target_ocaml.c7
-rw-r--r--bindings/ocaml/transforms/Makefile2
-rw-r--r--bindings/ocaml/transforms/ipo/Makefile20
-rw-r--r--bindings/ocaml/transforms/ipo/ipo_ocaml.c104
-rw-r--r--bindings/ocaml/transforms/ipo/llvm_ipo.ml65
-rw-r--r--bindings/ocaml/transforms/ipo/llvm_ipo.mli65
-rw-r--r--bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml39
-rw-r--r--bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli46
-rw-r--r--bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c57
-rwxr-xr-xcmake/config-ix.cmake9
-rwxr-xr-xcmake/modules/AddLLVM.cmake28
-rw-r--r--cmake/modules/CMakeLists.txt9
-rw-r--r--cmake/modules/CheckAtomic.cmake4
-rw-r--r--cmake/modules/CrossCompileLLVM.cmake26
-rwxr-xr-xcmake/modules/FindBison.cmake52
-rw-r--r--cmake/modules/HandleLLVMOptions.cmake4
-rwxr-xr-xcmake/modules/LLVM-Config.cmake43
-rw-r--r--cmake/modules/LLVMConfig.cmake.in2
-rw-r--r--cmake/modules/LLVMLibDeps.cmake83
-rw-r--r--cmake/modules/TableGen.cmake85
-rwxr-xr-xconfigure7182
-rw-r--r--docs/Atomics.html569
-rw-r--r--docs/Bugpoint.html14
-rw-r--r--docs/CMake.html7
-rw-r--r--docs/CodeGenerator.html208
-rw-r--r--docs/CodingStandards.html10
-rw-r--r--docs/CommandGuide/index.html24
-rw-r--r--docs/CommandGuide/llvm-extract.pod12
-rw-r--r--docs/CommandGuide/llvmc.pod190
-rw-r--r--docs/CommandGuide/llvmgcc.pod76
-rw-r--r--docs/CommandGuide/llvmgxx.pod85
-rw-r--r--docs/CompilerDriver.html687
-rw-r--r--docs/CompilerDriverTutorial.html125
-rw-r--r--docs/DeveloperPolicy.html13
-rw-r--r--docs/ExceptionHandling.html480
-rw-r--r--docs/FAQ.html20
-rw-r--r--docs/GarbageCollection.html32
-rw-r--r--docs/GettingStarted.html181
-rw-r--r--docs/GoldPlugin.html63
-rw-r--r--docs/HowToReleaseLLVM.html175
-rw-r--r--docs/LangRef.html774
-rw-r--r--docs/Lexicon.html14
-rw-r--r--docs/LinkTimeOptimization.html59
-rw-r--r--docs/Passes.html32
-rw-r--r--docs/ProgrammersManual.html240
-rw-r--r--docs/ReleaseNotes.html769
-rw-r--r--docs/SegmentedStacks.html99
-rw-r--r--docs/SourceLevelDebugging.html48
-rw-r--r--docs/TableGenFundamentals.html2
-rw-r--r--docs/WritingAnLLVMPass.html118
-rw-r--r--docs/doxygen.cfg.in1441
-rw-r--r--docs/index.html16
-rw-r--r--docs/llvm.css8
-rw-r--r--docs/tutorial/LangImpl2.html10
-rw-r--r--docs/tutorial/LangImpl3.html90
-rw-r--r--docs/tutorial/LangImpl4.html66
-rw-r--r--docs/tutorial/LangImpl5.html73
-rw-r--r--docs/tutorial/LangImpl6.html68
-rw-r--r--docs/tutorial/LangImpl7.html166
-rw-r--r--docs/tutorial/Makefile2
-rw-r--r--examples/BrainF/BrainF.cpp7
-rw-r--r--examples/BrainF/BrainFDriver.cpp2
-rw-r--r--examples/ExceptionDemo/ExceptionDemo.cpp301
-rw-r--r--examples/Fibonacci/fibonacci.cpp2
-rw-r--r--examples/HowToUseJIT/HowToUseJIT.cpp2
-rw-r--r--examples/Kaleidoscope/Chapter4/toy.cpp2
-rw-r--r--examples/Kaleidoscope/Chapter5/toy.cpp2
-rw-r--r--examples/Kaleidoscope/Chapter6/toy.cpp2
-rw-r--r--examples/Kaleidoscope/Chapter7/toy.cpp2
-rw-r--r--examples/ParallelJIT/ParallelJIT.cpp2
-rw-r--r--include/llvm-c/Core.h75
-rw-r--r--include/llvm-c/Disassembler.h32
-rw-r--r--include/llvm-c/Object.h8
-rw-r--r--include/llvm-c/Target.h20
-rw-r--r--include/llvm-c/Transforms/IPO.h9
-rw-r--r--include/llvm-c/Transforms/PassManagerBuilder.h90
-rw-r--r--include/llvm-c/Transforms/Scalar.h3
-rw-r--r--include/llvm/ADT/APInt.h30
-rw-r--r--include/llvm/ADT/ArrayRef.h48
-rw-r--r--include/llvm/ADT/DenseMap.h6
-rw-r--r--include/llvm/ADT/DenseMapInfo.h14
-rw-r--r--include/llvm/ADT/DenseSet.h2
-rw-r--r--include/llvm/ADT/ImmutableMap.h157
-rw-r--r--include/llvm/ADT/ImmutableSet.h134
-rw-r--r--include/llvm/ADT/IntervalMap.h3
-rw-r--r--include/llvm/ADT/PointerUnion.h6
-rw-r--r--include/llvm/ADT/PostOrderIterator.h10
-rw-r--r--include/llvm/ADT/SCCIterator.h10
-rw-r--r--include/llvm/ADT/STLExtras.h34
-rw-r--r--include/llvm/ADT/SmallVector.h17
-rw-r--r--include/llvm/ADT/Statistic.h18
-rw-r--r--include/llvm/ADT/StringExtras.h1
-rw-r--r--include/llvm/ADT/TinyPtrVector.h133
-rw-r--r--include/llvm/ADT/Triple.h37
-rw-r--r--include/llvm/ADT/Twine.h108
-rw-r--r--include/llvm/Analysis/AliasAnalysis.h42
-rw-r--r--include/llvm/Analysis/AliasSetTracker.h34
-rw-r--r--include/llvm/Analysis/BlockFrequency.h53
-rw-r--r--include/llvm/Analysis/BlockFrequencyImpl.h76
-rw-r--r--include/llvm/Analysis/BlockFrequencyInfo.h55
-rw-r--r--include/llvm/Analysis/BranchProbabilityInfo.h14
-rw-r--r--include/llvm/Analysis/CodeMetrics.h17
-rw-r--r--include/llvm/Analysis/ConstantFolding.h14
-rw-r--r--include/llvm/Analysis/DIBuilder.h25
-rw-r--r--include/llvm/Analysis/DebugInfo.h80
-rw-r--r--include/llvm/Analysis/FindUsedTypes.h6
-rw-r--r--include/llvm/Analysis/IVUsers.h2
-rw-r--r--include/llvm/Analysis/InlineCost.h9
-rw-r--r--include/llvm/Analysis/InstructionSimplify.h11
-rw-r--r--include/llvm/Analysis/LoopInfo.h78
-rw-r--r--include/llvm/Analysis/LoopIterator.h186
-rw-r--r--include/llvm/Analysis/LoopPass.h2
-rw-r--r--include/llvm/Analysis/MemoryBuiltins.h4
-rw-r--r--include/llvm/Analysis/MemoryDependenceAnalysis.h61
-rw-r--r--include/llvm/Analysis/RegionPass.h2
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h242
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpander.h53
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpressions.h28
-rw-r--r--include/llvm/Argument.h2
-rw-r--r--include/llvm/Attributes.h7
-rw-r--r--include/llvm/AutoUpgrade.h4
-rw-r--r--include/llvm/BasicBlock.h17
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h48
-rw-r--r--include/llvm/CMakeLists.txt2
-rw-r--r--include/llvm/CodeGen/Analysis.h6
-rw-r--r--include/llvm/CodeGen/CalcSpillWeights.h5
-rw-r--r--include/llvm/CodeGen/FastISel.h20
-rw-r--r--include/llvm/CodeGen/FunctionLoweringInfo.h16
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h66
-rw-r--r--include/llvm/CodeGen/LexicalScopes.h248
-rw-r--r--include/llvm/CodeGen/LiveInterval.h18
-rw-r--r--include/llvm/CodeGen/LiveStackAnalysis.h2
-rw-r--r--include/llvm/CodeGen/LiveVariables.h2
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h2
-rw-r--r--include/llvm/CodeGen/MachineBlockFrequency.h53
-rw-r--r--include/llvm/CodeGen/MachineBlockFrequencyInfo.h54
-rw-r--r--include/llvm/CodeGen/MachineConstantPool.h10
-rw-r--r--include/llvm/CodeGen/MachineFrameInfo.h10
-rw-r--r--include/llvm/CodeGen/MachineInstr.h30
-rw-r--r--include/llvm/CodeGen/MachineLocation.h98
-rw-r--r--include/llvm/CodeGen/MachineModuleInfo.h92
-rw-r--r--include/llvm/CodeGen/MachineOperand.h28
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h43
-rw-r--r--include/llvm/CodeGen/Passes.h25
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h48
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h53
-rw-r--r--include/llvm/CodeGen/SlotIndexes.h2
-rw-r--r--include/llvm/CodeGen/TargetLoweringObjectFileImpl.h116
-rw-r--r--include/llvm/CodeGen/ValueTypes.h26
-rw-r--r--include/llvm/CompilerDriver/Action.h54
-rw-r--r--include/llvm/CompilerDriver/AutoGenerated.h40
-rw-r--r--include/llvm/CompilerDriver/BuiltinOptions.h39
-rw-r--r--include/llvm/CompilerDriver/Common.td127
-rw-r--r--include/llvm/CompilerDriver/CompilationGraph.h330
-rw-r--r--include/llvm/CompilerDriver/Error.h29
-rw-r--r--include/llvm/CompilerDriver/Main.h21
-rw-r--r--include/llvm/CompilerDriver/Main.inc23
-rw-r--r--include/llvm/CompilerDriver/Tool.h100
-rw-r--r--include/llvm/Config/config.h.cmake122
-rw-r--r--include/llvm/Config/config.h.in15
-rw-r--r--include/llvm/Config/llvm-config.h.cmake22
-rw-r--r--include/llvm/Config/llvm-config.h.in25
-rw-r--r--include/llvm/Constant.h12
-rw-r--r--include/llvm/Constants.h179
-rw-r--r--include/llvm/DebugInfo/DIContext.h68
-rw-r--r--include/llvm/DerivedTypes.h104
-rw-r--r--include/llvm/ExecutionEngine/ExecutionEngine.h35
-rw-r--r--include/llvm/Function.h4
-rw-r--r--include/llvm/GlobalAlias.h11
-rw-r--r--include/llvm/GlobalValue.h2
-rw-r--r--include/llvm/GlobalVariable.h4
-rw-r--r--include/llvm/InitializePasses.h6
-rw-r--r--include/llvm/InlineAsm.h35
-rw-r--r--include/llvm/InstrTypes.h80
-rw-r--r--include/llvm/Instruction.def120
-rw-r--r--include/llvm/Instruction.h11
-rw-r--r--include/llvm/Instructions.h899
-rw-r--r--include/llvm/IntrinsicInst.h2
-rw-r--r--include/llvm/Intrinsics.h2
-rw-r--r--include/llvm/Intrinsics.td93
-rw-r--r--include/llvm/IntrinsicsXCore.td23
-rw-r--r--include/llvm/LinkAllPasses.h4
-rw-r--r--include/llvm/Linker.h12
-rw-r--r--include/llvm/MC/EDInstInfo.h2
-rw-r--r--include/llvm/MC/MCAsmBackend.h131
-rw-r--r--include/llvm/MC/MCAsmInfo.h76
-rw-r--r--include/llvm/MC/MCAsmInfoDarwin.h5
-rw-r--r--include/llvm/MC/MCAssembler.h12
-rw-r--r--include/llvm/MC/MCAtom.h68
-rw-r--r--include/llvm/MC/MCCodeGenInfo.h41
-rw-r--r--include/llvm/MC/MCContext.h16
-rw-r--r--include/llvm/MC/MCDirectives.h5
-rw-r--r--include/llvm/MC/MCDisassembler.h58
-rw-r--r--include/llvm/MC/MCDwarf.h7
-rw-r--r--include/llvm/MC/MCInst.h10
-rw-r--r--include/llvm/MC/MCInstPrinter.h6
-rw-r--r--include/llvm/MC/MCInstrAnalysis.h61
-rw-r--r--include/llvm/MC/MCInstrDesc.h121
-rw-r--r--include/llvm/MC/MCModule.h58
-rw-r--r--include/llvm/MC/MCObjectFileInfo.h294
-rw-r--r--include/llvm/MC/MCObjectStreamer.h6
-rw-r--r--include/llvm/MC/MCParser/AsmLexer.h2
-rw-r--r--include/llvm/MC/MCParser/MCAsmLexer.h3
-rw-r--r--include/llvm/MC/MCParser/MCAsmParser.h11
-rw-r--r--include/llvm/MC/MCRegisterInfo.h184
-rw-r--r--include/llvm/MC/MCStreamer.h76
-rw-r--r--include/llvm/MC/MCTargetAsmLexer.h89
-rw-r--r--include/llvm/MC/MCTargetAsmParser.h103
-rw-r--r--include/llvm/MC/MCValue.h10
-rw-r--r--include/llvm/MC/MachineLocation.h98
-rw-r--r--include/llvm/Module.h38
-rw-r--r--include/llvm/Object/Archive.h90
-rw-r--r--include/llvm/Object/COFF.h32
-rw-r--r--include/llvm/Object/MachO.h106
-rw-r--r--include/llvm/Object/MachOFormat.h12
-rw-r--r--include/llvm/Object/MachOObject.h4
-rw-r--r--include/llvm/Object/ObjectFile.h250
-rw-r--r--include/llvm/OperandTraits.h41
-rw-r--r--include/llvm/Operator.h4
-rw-r--r--include/llvm/PassManagers.h7
-rw-r--r--include/llvm/Support/BlockFrequency.h63
-rw-r--r--include/llvm/Support/BranchProbability.h6
-rw-r--r--include/llvm/Support/CallSite.h2
-rw-r--r--include/llvm/Support/Capacity.h30
-rw-r--r--include/llvm/Support/CodeGen.h32
-rw-r--r--include/llvm/Support/CommandLine.h31
-rw-r--r--include/llvm/Support/ConstantFolder.h56
-rw-r--r--include/llvm/Support/DataExtractor.h352
-rw-r--r--include/llvm/Support/DataTypes.h.cmake12
-rw-r--r--include/llvm/Support/DataTypes.h.in92
-rw-r--r--include/llvm/Support/Dwarf.h53
-rw-r--r--include/llvm/Support/DynamicLibrary.h75
-rw-r--r--include/llvm/Support/ELF.h347
-rw-r--r--include/llvm/Support/FileSystem.h162
-rw-r--r--include/llvm/Support/Format.h62
-rw-r--r--include/llvm/Support/GCOV.h224
-rw-r--r--include/llvm/Support/GetElementPtrTypeIterator.h34
-rw-r--r--include/llvm/Support/IRBuilder.h148
-rw-r--r--include/llvm/Support/InstVisitor.h5
-rw-r--r--include/llvm/Support/MachO.h11
-rw-r--r--include/llvm/Support/MemoryBuffer.h6
-rw-r--r--include/llvm/Support/NoFolder.h44
-rw-r--r--include/llvm/Support/PassManagerBuilder.h331
-rw-r--r--include/llvm/Support/PathV1.h1
-rw-r--r--include/llvm/Support/PathV2.h13
-rw-r--r--include/llvm/Support/Process.h3
-rw-r--r--include/llvm/Support/SMLoc.h10
-rw-r--r--include/llvm/Support/SourceMgr.h11
-rw-r--r--include/llvm/Support/TargetFolder.h54
-rw-r--r--include/llvm/Support/TargetRegistry.h1124
-rw-r--r--include/llvm/Support/TargetSelect.h154
-rw-r--r--include/llvm/Support/TypeBuilder.h101
-rw-r--r--include/llvm/TableGen/Error.h43
-rw-r--r--include/llvm/TableGen/Main.h26
-rw-r--r--include/llvm/TableGen/Record.h1655
-rw-r--r--include/llvm/TableGen/TableGenAction.h34
-rw-r--r--include/llvm/TableGen/TableGenBackend.h43
-rw-r--r--include/llvm/Target/Target.td7
-rw-r--r--include/llvm/Target/TargetAsmBackend.h131
-rw-r--r--include/llvm/Target/TargetAsmInfo.h103
-rw-r--r--include/llvm/Target/TargetAsmLexer.h89
-rw-r--r--include/llvm/Target/TargetAsmParser.h85
-rw-r--r--include/llvm/Target/TargetData.h44
-rw-r--r--include/llvm/Target/TargetFrameLowering.h17
-rw-r--r--include/llvm/Target/TargetInstrInfo.h55
-rw-r--r--include/llvm/Target/TargetIntrinsicInfo.h4
-rw-r--r--include/llvm/Target/TargetLowering.h246
-rw-r--r--include/llvm/Target/TargetLoweringObjectFile.h124
-rw-r--r--include/llvm/Target/TargetMachine.h44
-rw-r--r--include/llvm/Target/TargetOptions.h2
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h206
-rw-r--r--include/llvm/Target/TargetRegistry.h985
-rw-r--r--include/llvm/Target/TargetSelect.h184
-rw-r--r--include/llvm/Target/TargetSelectionDAG.td44
-rw-r--r--include/llvm/Transforms/IPO.h9
-rw-r--r--include/llvm/Transforms/IPO/PassManagerBuilder.h133
-rw-r--r--include/llvm/Transforms/Scalar.h7
-rw-r--r--include/llvm/Transforms/Utils/AddrModeMatcher.h6
-rw-r--r--include/llvm/Transforms/Utils/BasicBlockUtils.h46
-rw-r--r--include/llvm/Transforms/Utils/FunctionUtils.h14
-rw-r--r--include/llvm/Transforms/Utils/SSAUpdater.h4
-rw-r--r--include/llvm/Transforms/Utils/SimplifyIndVar.h58
-rw-r--r--include/llvm/Transforms/Utils/UnrollLoop.h3
-rw-r--r--include/llvm/Transforms/Utils/ValueMapper.h4
-rw-r--r--include/llvm/Type.h12
-rw-r--r--include/llvm/User.h2
-rw-r--r--include/llvm/Value.h4
-rw-r--r--lib/Analysis/AliasAnalysis.cpp50
-rw-r--r--lib/Analysis/AliasAnalysisEvaluator.cpp6
-rw-r--r--lib/Analysis/AliasSetTracker.cpp107
-rw-r--r--lib/Analysis/Analysis.cpp3
-rw-r--r--lib/Analysis/BasicAliasAnalysis.cpp136
-rw-r--r--lib/Analysis/BlockFrequency.cpp59
-rw-r--r--lib/Analysis/BlockFrequencyInfo.cpp63
-rw-r--r--lib/Analysis/BranchProbabilityInfo.cpp276
-rw-r--r--lib/Analysis/CMakeLists.txt8
-rw-r--r--lib/Analysis/ConstantFolding.cpp126
-rw-r--r--lib/Analysis/DIBuilder.cpp286
-rw-r--r--lib/Analysis/DbgInfoPrinter.cpp2
-rw-r--r--lib/Analysis/DebugInfo.cpp275
-rw-r--r--lib/Analysis/IPA/CMakeLists.txt6
-rw-r--r--lib/Analysis/IPA/CallGraphSCCPass.cpp7
-rw-r--r--lib/Analysis/IPA/FindUsedTypes.cpp4
-rw-r--r--lib/Analysis/IVUsers.cpp3
-rw-r--r--lib/Analysis/InlineCost.cpp124
-rw-r--r--lib/Analysis/InstructionSimplify.cpp173
-rw-r--r--lib/Analysis/LazyValueInfo.cpp6
-rw-r--r--lib/Analysis/Lint.cpp8
-rw-r--r--lib/Analysis/Loads.cpp12
-rw-r--r--lib/Analysis/LoopDependenceAnalysis.cpp8
-rw-r--r--lib/Analysis/LoopInfo.cpp296
-rw-r--r--lib/Analysis/LoopPass.cpp108
-rw-r--r--lib/Analysis/MemDepPrinter.cpp80
-rw-r--r--lib/Analysis/MemoryBuiltins.cpp16
-rw-r--r--lib/Analysis/MemoryDependenceAnalysis.cpp48
-rw-r--r--lib/Analysis/PHITransAddr.cpp8
-rw-r--r--lib/Analysis/PathNumbering.cpp2
-rw-r--r--lib/Analysis/RegionPass.cpp6
-rw-r--r--lib/Analysis/ScalarEvolution.cpp844
-rw-r--r--lib/Analysis/ScalarEvolutionExpander.cpp393
-rw-r--r--lib/Analysis/ScalarEvolutionNormalization.cpp101
-rw-r--r--lib/Analysis/ValueTracking.cpp39
-rw-r--r--lib/Archive/CMakeLists.txt6
-rw-r--r--lib/AsmParser/CMakeLists.txt5
-rw-r--r--lib/AsmParser/LLLexer.cpp30
-rw-r--r--lib/AsmParser/LLParser.cpp352
-rw-r--r--lib/AsmParser/LLParser.h26
-rw-r--r--lib/AsmParser/LLToken.h15
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp316
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.h8
-rw-r--r--lib/Bitcode/Reader/CMakeLists.txt5
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp156
-rw-r--r--lib/Bitcode/Writer/CMakeLists.txt5
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.cpp6
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.h8
-rw-r--r--lib/CMakeLists.txt4
-rw-r--r--lib/CodeGen/Analysis.cpp16
-rw-r--r--lib/CodeGen/AsmPrinter/ARMException.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp155
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp15
-rw-r--r--lib/CodeGen/AsmPrinter/CMakeLists.txt9
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCFIException.cpp5
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp407
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.h20
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp1403
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h133
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.cpp100
-rw-r--r--lib/CodeGen/AsmPrinter/Win64Exception.cpp1
-rw-r--r--lib/CodeGen/BranchFolding.cpp29
-rw-r--r--lib/CodeGen/CMakeLists.txt17
-rw-r--r--lib/CodeGen/CalcSpillWeights.cpp32
-rw-r--r--lib/CodeGen/CodeGen.cpp1
-rw-r--r--lib/CodeGen/DwarfEHPrepare.cpp67
-rw-r--r--lib/CodeGen/ELFCodeEmitter.cpp2
-rw-r--r--lib/CodeGen/ELFCodeEmitter.h4
-rw-r--r--lib/CodeGen/ELFWriter.cpp12
-rw-r--r--lib/CodeGen/ExecutionDepsFix.cpp523
-rw-r--r--lib/CodeGen/ExpandPostRAPseudos.cpp237
-rw-r--r--lib/CodeGen/IfConversion.cpp39
-rw-r--r--lib/CodeGen/InlineSpiller.cpp434
-rw-r--r--lib/CodeGen/InterferenceCache.cpp5
-rw-r--r--lib/CodeGen/InterferenceCache.h3
-rw-r--r--lib/CodeGen/IntrinsicLowering.cpp10
-rw-r--r--lib/CodeGen/LLVMTargetMachine.cpp96
-rw-r--r--lib/CodeGen/LexicalScopes.cpp335
-rw-r--r--lib/CodeGen/LiveDebugVariables.cpp71
-rw-r--r--lib/CodeGen/LiveInterval.cpp35
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp29
-rw-r--r--lib/CodeGen/LiveIntervalUnion.cpp230
-rw-r--r--lib/CodeGen/LiveIntervalUnion.h78
-rw-r--r--lib/CodeGen/LiveRangeCalc.cpp270
-rw-r--r--lib/CodeGen/LiveRangeCalc.h226
-rw-r--r--lib/CodeGen/LiveRangeEdit.cpp5
-rw-r--r--lib/CodeGen/LiveRangeEdit.h2
-rw-r--r--lib/CodeGen/LiveStackAnalysis.cpp5
-rw-r--r--lib/CodeGen/LiveVariables.cpp2
-rw-r--r--lib/CodeGen/LowerSubregs.cpp223
-rw-r--r--lib/CodeGen/MachineBasicBlock.cpp5
-rw-r--r--lib/CodeGen/MachineBlockFrequency.cpp59
-rw-r--r--lib/CodeGen/MachineBlockFrequencyInfo.cpp61
-rw-r--r--lib/CodeGen/MachineCSE.cpp11
-rw-r--r--lib/CodeGen/MachineFunction.cpp2
-rw-r--r--lib/CodeGen/MachineInstr.cpp366
-rw-r--r--lib/CodeGen/MachineLICM.cpp156
-rw-r--r--lib/CodeGen/MachineModuleInfo.cpp37
-rw-r--r--lib/CodeGen/MachineRegisterInfo.cpp44
-rw-r--r--lib/CodeGen/MachineSink.cpp31
-rw-r--r--lib/CodeGen/MachineVerifier.cpp70
-rw-r--r--lib/CodeGen/PHIElimination.cpp3
-rw-r--r--lib/CodeGen/PeepholeOptimizer.cpp17
-rw-r--r--lib/CodeGen/ProcessImplicitDefs.cpp6
-rw-r--r--lib/CodeGen/PrologEpilogInserter.cpp14
-rw-r--r--lib/CodeGen/RegAllocBasic.cpp10
-rw-r--r--lib/CodeGen/RegAllocGreedy.cpp523
-rw-r--r--lib/CodeGen/RegAllocLinearScan.cpp3
-rw-r--r--lib/CodeGen/RegAllocPBQP.cpp2
-rw-r--r--lib/CodeGen/RegisterClassInfo.cpp7
-rw-r--r--lib/CodeGen/RegisterClassInfo.h15
-rw-r--r--lib/CodeGen/RegisterCoalescer.cpp630
-rw-r--r--lib/CodeGen/RegisterCoalescer.h205
-rw-r--r--lib/CodeGen/RegisterScavenging.cpp1
-rw-r--r--lib/CodeGen/ScheduleDAG.cpp3
-rw-r--r--lib/CodeGen/ScheduleDAGInstrs.cpp3
-rw-r--r--lib/CodeGen/ScheduleDAGInstrs.h7
-rw-r--r--lib/CodeGen/ScoreboardHazardRecognizer.cpp1
-rw-r--r--lib/CodeGen/SelectionDAG/CMakeLists.txt10
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp121
-rw-r--r--lib/CodeGen/SelectionDAG/FastISel.cpp48
-rw-r--r--lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp47
-rw-r--r--lib/CodeGen/SelectionDAG/InstrEmitter.cpp186
-rw-r--r--lib/CodeGen/SelectionDAG/InstrEmitter.h6
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp341
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp27
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp184
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypes.cpp33
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypes.h33
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp44
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp46
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp118
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp36
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp184
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp526
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h39
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp37
-rw-r--r--lib/CodeGen/SelectionDAG/TargetLowering.cpp48
-rw-r--r--lib/CodeGen/ShadowStackGC.cpp52
-rw-r--r--lib/CodeGen/SjLjEHPrepare.cpp514
-rw-r--r--lib/CodeGen/SpillPlacement.cpp17
-rw-r--r--lib/CodeGen/SpillPlacement.h14
-rw-r--r--lib/CodeGen/SplitKit.cpp718
-rw-r--r--lib/CodeGen/SplitKit.h171
-rw-r--r--lib/CodeGen/Splitter.cpp4
-rw-r--r--lib/CodeGen/StackProtector.cpp4
-rw-r--r--lib/CodeGen/StrongPHIElimination.cpp3
-rw-r--r--lib/CodeGen/TailDuplication.cpp1
-rw-r--r--lib/CodeGen/TargetInstrInfoImpl.cpp76
-rw-r--r--lib/CodeGen/TargetLoweringObjectFileImpl.cpp535
-rw-r--r--lib/CodeGen/TwoAddressInstructionPass.cpp13
-rw-r--r--lib/CodeGen/VirtRegMap.cpp32
-rw-r--r--lib/CompilerDriver/Action.cpp134
-rw-r--r--lib/CompilerDriver/BuiltinOptions.cpp61
-rw-r--r--lib/CompilerDriver/CMakeLists.txt12
-rw-r--r--lib/CompilerDriver/CompilationGraph.cpp655
-rw-r--r--lib/CompilerDriver/Main.cpp146
-rw-r--r--lib/CompilerDriver/Makefile20
-rw-r--r--lib/CompilerDriver/Tool.cpp95
-rw-r--r--lib/DebugInfo/CMakeLists.txt16
-rw-r--r--lib/DebugInfo/DIContext.cpp24
-rw-r--r--lib/DebugInfo/DWARFAbbreviationDeclaration.cpp83
-rw-r--r--lib/DebugInfo/DWARFAbbreviationDeclaration.h54
-rw-r--r--lib/DebugInfo/DWARFAttribute.h30
-rw-r--r--lib/DebugInfo/DWARFCompileUnit.cpp238
-rw-r--r--lib/DebugInfo/DWARFCompileUnit.h111
-rw-r--r--lib/DebugInfo/DWARFContext.cpp167
-rw-r--r--lib/DebugInfo/DWARFContext.h118
-rw-r--r--lib/DebugInfo/DWARFDebugAbbrev.cpp106
-rw-r--r--lib/DebugInfo/DWARFDebugAbbrev.h73
-rw-r--r--lib/DebugInfo/DWARFDebugArangeSet.cpp150
-rw-r--r--lib/DebugInfo/DWARFDebugArangeSet.h75
-rw-r--r--lib/DebugInfo/DWARFDebugAranges.cpp223
-rw-r--r--lib/DebugInfo/DWARFDebugAranges.h98
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.cpp444
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.h135
-rw-r--r--lib/DebugInfo/DWARFDebugLine.cpp475
-rw-r--r--lib/DebugInfo/DWARFDebugLine.h190
-rw-r--r--lib/DebugInfo/DWARFFormValue.cpp427
-rw-r--r--lib/DebugInfo/DWARFFormValue.h78
-rw-r--r--lib/DebugInfo/Makefile14
-rw-r--r--lib/ExecutionEngine/CMakeLists.txt7
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp34
-rw-r--r--lib/ExecutionEngine/Interpreter/CMakeLists.txt8
-rw-r--r--lib/ExecutionEngine/Interpreter/Execution.cpp133
-rw-r--r--lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp34
-rw-r--r--lib/ExecutionEngine/Interpreter/Interpreter.h30
-rw-r--r--lib/ExecutionEngine/JIT/CMakeLists.txt8
-rw-r--r--lib/ExecutionEngine/JIT/Intercept.cpp1
-rw-r--r--lib/ExecutionEngine/JIT/JIT.cpp8
-rw-r--r--lib/ExecutionEngine/JIT/JIT.h5
-rw-r--r--lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp10
-rw-r--r--lib/ExecutionEngine/JIT/JITDwarfEmitter.h4
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp5
-rw-r--r--lib/ExecutionEngine/MCJIT/CMakeLists.txt8
-rw-r--r--lib/ExecutionEngine/MCJIT/Intercept.cpp1
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.cpp7
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt5
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h2
-rw-r--r--lib/ExecutionEngine/TargetSelect.cpp13
-rw-r--r--lib/Linker/CMakeLists.txt8
-rw-r--r--lib/Linker/LinkModules.cpp112
-rw-r--r--lib/Linker/Linker.cpp8
-rw-r--r--lib/MC/CMakeLists.txt19
-rw-r--r--lib/MC/ELFObjectWriter.cpp124
-rw-r--r--lib/MC/ELFObjectWriter.h32
-rw-r--r--lib/MC/MCAsmBackend.cpp37
-rw-r--r--lib/MC/MCAsmInfo.cpp12
-rw-r--r--lib/MC/MCAsmInfoCOFF.cpp7
-rw-r--r--lib/MC/MCAsmInfoDarwin.cpp8
-rw-r--r--lib/MC/MCAsmStreamer.cpp57
-rw-r--r--lib/MC/MCAssembler.cpp6
-rw-r--r--lib/MC/MCAtom.cpp97
-rw-r--r--lib/MC/MCCodeGenInfo.cpp21
-rw-r--r--lib/MC/MCContext.cpp13
-rw-r--r--lib/MC/MCDisassembler/CMakeLists.txt24
-rw-r--r--lib/MC/MCDisassembler/Disassembler.cpp82
-rw-r--r--lib/MC/MCDisassembler/Disassembler.h25
-rw-r--r--lib/MC/MCDisassembler/EDDisassembler.cpp70
-rw-r--r--lib/MC/MCDisassembler/EDDisassembler.h19
-rw-r--r--lib/MC/MCDisassembler/EDInst.h2
-rw-r--r--lib/MC/MCDisassembler/EDToken.cpp8
-rw-r--r--lib/MC/MCDisassembler/EDToken.h2
-rw-r--r--lib/MC/MCDwarf.cpp95
-rw-r--r--lib/MC/MCELF.cpp1
-rw-r--r--lib/MC/MCELFStreamer.cpp17
-rw-r--r--lib/MC/MCELFStreamer.h7
-rw-r--r--lib/MC/MCExpr.cpp1
-rw-r--r--lib/MC/MCInstPrinter.cpp11
-rw-r--r--lib/MC/MCInstrAnalysis.cpp21
-rw-r--r--lib/MC/MCLoggingStreamer.cpp5
-rw-r--r--lib/MC/MCMachOStreamer.cpp20
-rw-r--r--lib/MC/MCModule.cpp45
-rw-r--r--lib/MC/MCNullStreamer.cpp4
-rw-r--r--lib/MC/MCObjectFileInfo.cpp554
-rw-r--r--lib/MC/MCObjectStreamer.cpp6
-rw-r--r--lib/MC/MCParser/AsmLexer.cpp32
-rw-r--r--lib/MC/MCParser/AsmParser.cpp198
-rw-r--r--lib/MC/MCParser/CMakeLists.txt7
-rw-r--r--lib/MC/MCParser/COFFAsmParser.cpp47
-rw-r--r--lib/MC/MCParser/ELFAsmParser.cpp59
-rw-r--r--lib/MC/MCParser/MCAsmParser.cpp6
-rw-r--r--lib/MC/MCParser/MCTargetAsmParser.cpp19
-rw-r--r--lib/MC/MCParser/TargetAsmParser.cpp19
-rw-r--r--lib/MC/MCPureStreamer.cpp9
-rw-r--r--lib/MC/MCStreamer.cpp113
-rw-r--r--lib/MC/MCTargetAsmLexer.cpp16
-rw-r--r--lib/MC/MCWin64EH.cpp34
-rw-r--r--lib/MC/MachObjectWriter.cpp25
-rw-r--r--lib/MC/TargetAsmBackend.cpp37
-rw-r--r--lib/MC/WinCOFFObjectWriter.cpp2
-rw-r--r--lib/MC/WinCOFFStreamer.cpp22
-rw-r--r--lib/Makefile2
-rw-r--r--lib/Object/Archive.cpp172
-rw-r--r--lib/Object/Binary.cpp11
-rw-r--r--lib/Object/CMakeLists.txt6
-rw-r--r--lib/Object/COFFObjectFile.cpp239
-rw-r--r--lib/Object/ELFObjectFile.cpp773
-rw-r--r--lib/Object/MachOObject.cpp38
-rw-r--r--lib/Object/MachOObjectFile.cpp316
-rw-r--r--lib/Object/Object.cpp4
-rw-r--r--lib/Object/ObjectFile.cpp1
-rw-r--r--lib/Support/APFloat.cpp31
-rw-r--r--lib/Support/APInt.cpp56
-rw-r--r--lib/Support/Atomic.cpp10
-rw-r--r--lib/Support/BlockFrequency.cpp126
-rw-r--r--lib/Support/BranchProbability.cpp3
-rw-r--r--lib/Support/CMakeLists.txt4
-rw-r--r--lib/Support/CommandLine.cpp66
-rw-r--r--lib/Support/ConstantRange.cpp25
-rw-r--r--lib/Support/CrashRecoveryContext.cpp68
-rw-r--r--lib/Support/DataExtractor.cpp175
-rw-r--r--lib/Support/Disassembler.cpp2
-rw-r--r--lib/Support/Dwarf.cpp49
-rw-r--r--lib/Support/DynamicLibrary.cpp99
-rw-r--r--lib/Support/FoldingSet.cpp6
-rw-r--r--lib/Support/Host.cpp4
-rw-r--r--lib/Support/IncludeFile.cpp2
-rw-r--r--lib/Support/Memory.cpp6
-rw-r--r--lib/Support/MemoryBuffer.cpp8
-rw-r--r--lib/Support/MemoryObject.cpp7
-rw-r--r--lib/Support/Mutex.cpp2
-rw-r--r--lib/Support/Path.cpp2
-rw-r--r--lib/Support/PathV2.cpp36
-rw-r--r--lib/Support/PrettyStackTrace.cpp2
-rw-r--r--lib/Support/RWMutex.cpp2
-rw-r--r--lib/Support/SearchForAddressOfSpecialSymbol.cpp15
-rw-r--r--lib/Support/StringExtras.cpp9
-rw-r--r--lib/Support/StringRef.cpp19
-rw-r--r--lib/Support/TargetRegistry.cpp32
-rw-r--r--lib/Support/ThreadLocal.cpp2
-rw-r--r--lib/Support/Threading.cpp41
-rw-r--r--lib/Support/Triple.cpp44
-rw-r--r--lib/Support/Twine.cpp60
-rw-r--r--lib/Support/Unix/Host.inc1
-rw-r--r--lib/Support/Unix/Path.inc4
-rw-r--r--lib/Support/Unix/PathV2.inc22
-rw-r--r--lib/Support/Unix/Process.inc4
-rw-r--r--lib/Support/Windows/DynamicLibrary.inc76
-rw-r--r--lib/Support/Windows/Memory.inc57
-rw-r--r--lib/Support/Windows/PathV2.inc51
-rw-r--r--lib/Support/Windows/Process.inc5
-rw-r--r--lib/Support/Windows/RWMutex.inc98
-rw-r--r--lib/Support/Windows/Signals.inc224
-rw-r--r--lib/Support/Windows/Windows.h6
-rw-r--r--lib/Support/raw_ostream.cpp7
-rw-r--r--lib/TableGen/CMakeLists.txt16
-rw-r--r--lib/TableGen/Error.cpp39
-rw-r--r--lib/TableGen/Main.cpp124
-rw-r--r--lib/TableGen/Makefile18
-rw-r--r--lib/TableGen/Record.cpp2019
-rw-r--r--lib/TableGen/TGLexer.cpp435
-rw-r--r--lib/TableGen/TGLexer.h (renamed from utils/TableGen/TGLexer.h)0
-rw-r--r--lib/TableGen/TGParser.cpp2194
-rw-r--r--lib/TableGen/TGParser.h137
-rw-r--r--lib/TableGen/TableGenBackend.cpp25
-rw-r--r--lib/Target/ARM/ARM.h21
-rw-r--r--lib/Target/ARM/ARM.td23
-rw-r--r--lib/Target/ARM/ARMAddressingModes.h595
-rw-r--r--lib/Target/ARM/ARMAsmBackend.cpp516
-rw-r--r--lib/Target/ARM/ARMAsmPrinter.cpp194
-rw-r--r--lib/Target/ARM/ARMBaseInfo.h294
-rw-r--r--lib/Target/ARM/ARMBaseInstrInfo.cpp522
-rw-r--r--lib/Target/ARM/ARMBaseInstrInfo.h161
-rw-r--r--lib/Target/ARM/ARMBaseRegisterInfo.cpp287
-rw-r--r--lib/Target/ARM/ARMBaseRegisterInfo.h19
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp35
-rw-r--r--lib/Target/ARM/ARMConstantIslandPass.cpp23
-rw-r--r--lib/Target/ARM/ARMConstantPoolValue.cpp317
-rw-r--r--lib/Target/ARM/ARMConstantPoolValue.h189
-rw-r--r--lib/Target/ARM/ARMExpandPseudoInsts.cpp61
-rw-r--r--lib/Target/ARM/ARMFastISel.cpp93
-rw-r--r--lib/Target/ARM/ARMFrameLowering.cpp31
-rw-r--r--lib/Target/ARM/ARMGlobalMerge.cpp10
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp336
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp1295
-rw-r--r--lib/Target/ARM/ARMISelLowering.h47
-rw-r--r--lib/Target/ARM/ARMInstrFormats.td341
-rw-r--r--lib/Target/ARM/ARMInstrInfo.cpp26
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td2748
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td153
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td489
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td1957
-rw-r--r--lib/Target/ARM/ARMInstrVFP.td113
-rw-r--r--lib/Target/ARM/ARMLoadStoreOptimizer.cpp49
-rw-r--r--lib/Target/ARM/ARMMCCodeEmitter.cpp1314
-rw-r--r--lib/Target/ARM/ARMMCInstLower.cpp2
-rw-r--r--lib/Target/ARM/ARMMachObjectWriter.cpp389
-rw-r--r--lib/Target/ARM/ARMRegisterInfo.td24
-rw-r--r--lib/Target/ARM/ARMSelectionDAGInfo.cpp15
-rw-r--r--lib/Target/ARM/ARMSelectionDAGInfo.h17
-rw-r--r--lib/Target/ARM/ARMSubtarget.cpp5
-rw-r--r--lib/Target/ARM/ARMSubtarget.h18
-rw-r--r--lib/Target/ARM/ARMTargetMachine.cpp91
-rw-r--r--lib/Target/ARM/ARMTargetMachine.h16
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmLexer.cpp37
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp4039
-rw-r--r--lib/Target/ARM/AsmParser/CMakeLists.txt9
-rw-r--r--lib/Target/ARM/CMakeLists.txt48
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassembler.cpp4455
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassembler.h99
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp3818
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassemblerCore.h336
-rw-r--r--lib/Target/ARM/Disassembler/CMakeLists.txt11
-rw-r--r--lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h2459
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp399
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.h34
-rw-r--r--lib/Target/ARM/InstPrinter/CMakeLists.txt8
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h667
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp531
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h449
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h (renamed from lib/Target/ARM/ARMFixupKinds.h)0
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp11
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp1468
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp (renamed from lib/Target/ARM/ARMMCExpr.cpp)0
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCExpr.h (renamed from lib/Target/ARM/ARMMCExpr.h)0
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp179
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h21
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp388
-rw-r--r--lib/Target/ARM/MCTargetDesc/CMakeLists.txt14
-rw-r--r--lib/Target/ARM/Makefile5
-rw-r--r--lib/Target/ARM/NEONMoveFix.cpp149
-rw-r--r--lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp2
-rw-r--r--lib/Target/ARM/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/ARM/Thumb1FrameLowering.cpp11
-rw-r--r--lib/Target/ARM/Thumb1RegisterInfo.cpp34
-rw-r--r--lib/Target/ARM/Thumb2ITBlockPass.cpp21
-rw-r--r--lib/Target/ARM/Thumb2InstrInfo.cpp13
-rw-r--r--lib/Target/ARM/Thumb2SizeReduction.cpp21
-rw-r--r--lib/Target/Alpha/AlphaAsmPrinter.cpp2
-rw-r--r--lib/Target/Alpha/AlphaISelDAGToDAG.cpp7
-rw-r--r--lib/Target/Alpha/AlphaISelLowering.cpp8
-rw-r--r--lib/Target/Alpha/AlphaISelLowering.h2
-rw-r--r--lib/Target/Alpha/AlphaInstrInfo.cpp1
-rw-r--r--lib/Target/Alpha/AlphaInstrInfo.td2
-rw-r--r--lib/Target/Alpha/AlphaRegisterInfo.cpp18
-rw-r--r--lib/Target/Alpha/AlphaRegisterInfo.h4
-rw-r--r--lib/Target/Alpha/AlphaSubtarget.cpp1
-rw-r--r--lib/Target/Alpha/AlphaTargetMachine.cpp12
-rw-r--r--lib/Target/Alpha/AlphaTargetMachine.h5
-rw-r--r--lib/Target/Alpha/CMakeLists.txt25
-rw-r--r--lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp35
-rw-r--r--lib/Target/Alpha/MCTargetDesc/CMakeLists.txt7
-rw-r--r--lib/Target/Alpha/TargetInfo/AlphaTargetInfo.cpp2
-rw-r--r--lib/Target/Alpha/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/Blackfin/BlackfinAsmPrinter.cpp2
-rw-r--r--lib/Target/Blackfin/BlackfinFrameLowering.h4
-rw-r--r--lib/Target/Blackfin/BlackfinISelLowering.cpp4
-rw-r--r--lib/Target/Blackfin/BlackfinISelLowering.h2
-rw-r--r--lib/Target/Blackfin/BlackfinInstrInfo.cpp2
-rw-r--r--lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp8
-rw-r--r--lib/Target/Blackfin/BlackfinIntrinsicInfo.h4
-rw-r--r--lib/Target/Blackfin/BlackfinRegisterInfo.cpp18
-rw-r--r--lib/Target/Blackfin/BlackfinRegisterInfo.h4
-rw-r--r--lib/Target/Blackfin/BlackfinSubtarget.cpp2
-rw-r--r--lib/Target/Blackfin/BlackfinTargetMachine.cpp12
-rw-r--r--lib/Target/Blackfin/BlackfinTargetMachine.h5
-rw-r--r--lib/Target/Blackfin/CMakeLists.txt27
-rw-r--r--lib/Target/Blackfin/MCTargetDesc/BlackfinMCTargetDesc.cpp39
-rw-r--r--lib/Target/Blackfin/MCTargetDesc/CMakeLists.txt7
-rw-r--r--lib/Target/Blackfin/TargetInfo/BlackfinTargetInfo.cpp2
-rw-r--r--lib/Target/Blackfin/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/CBackend/CBackend.cpp180
-rw-r--r--lib/Target/CBackend/CMakeLists.txt12
-rw-r--r--lib/Target/CBackend/CTargetMachine.h5
-rw-r--r--lib/Target/CBackend/TargetInfo/CBackendTargetInfo.cpp4
-rw-r--r--lib/Target/CBackend/TargetInfo/CMakeLists.txt5
-rw-r--r--lib/Target/CMakeLists.txt8
-rw-r--r--lib/Target/CellSPU/CMakeLists.txt27
-rw-r--r--lib/Target/CellSPU/MCTargetDesc/CMakeLists.txt7
-rw-r--r--lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.cpp52
-rw-r--r--lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.h4
-rw-r--r--lib/Target/CellSPU/SPUAsmPrinter.cpp2
-rw-r--r--lib/Target/CellSPU/SPUFrameLowering.cpp20
-rw-r--r--lib/Target/CellSPU/SPUFrameLowering.h14
-rw-r--r--lib/Target/CellSPU/SPUISelLowering.cpp16
-rw-r--r--lib/Target/CellSPU/SPUISelLowering.h6
-rw-r--r--lib/Target/CellSPU/SPUInstrInfo.cpp4
-rw-r--r--lib/Target/CellSPU/SPUInstrInfo.td10
-rw-r--r--lib/Target/CellSPU/SPURegisterInfo.cpp19
-rw-r--r--lib/Target/CellSPU/SPURegisterInfo.h6
-rw-r--r--lib/Target/CellSPU/SPUSubtarget.cpp2
-rw-r--r--lib/Target/CellSPU/SPUTargetMachine.cpp25
-rw-r--r--lib/Target/CellSPU/SPUTargetMachine.h5
-rw-r--r--lib/Target/CellSPU/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/CellSPU/TargetInfo/CellSPUTargetInfo.cpp2
-rw-r--r--lib/Target/CppBackend/CMakeLists.txt7
-rw-r--r--lib/Target/CppBackend/CPPBackend.cpp141
-rw-r--r--lib/Target/CppBackend/CPPTargetMachine.h5
-rw-r--r--lib/Target/CppBackend/TargetInfo/CMakeLists.txt4
-rw-r--r--lib/Target/CppBackend/TargetInfo/CppBackendTargetInfo.cpp4
-rw-r--r--lib/Target/MBlaze/AsmParser/CMakeLists.txt8
-rw-r--r--lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp27
-rw-r--r--lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp24
-rw-r--r--lib/Target/MBlaze/AsmParser/Makefile2
-rw-r--r--lib/Target/MBlaze/CMakeLists.txt36
-rw-r--r--lib/Target/MBlaze/Disassembler/CMakeLists.txt10
-rw-r--r--lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp76
-rw-r--r--lib/Target/MBlaze/Disassembler/MBlazeDisassembler.h9
-rw-r--r--lib/Target/MBlaze/InstPrinter/CMakeLists.txt9
-rw-r--r--lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp4
-rw-r--r--lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h2
-rw-r--r--lib/Target/MBlaze/MBlaze.h12
-rw-r--r--lib/Target/MBlaze/MBlazeAsmBackend.cpp162
-rw-r--r--lib/Target/MBlaze/MBlazeAsmPrinter.cpp21
-rw-r--r--lib/Target/MBlaze/MBlazeFrameLowering.cpp2
-rw-r--r--lib/Target/MBlaze/MBlazeISelLowering.cpp13
-rw-r--r--lib/Target/MBlaze/MBlazeISelLowering.h2
-rw-r--r--lib/Target/MBlaze/MBlazeInstrInfo.cpp5
-rw-r--r--lib/Target/MBlaze/MBlazeInstrInfo.h56
-rw-r--r--lib/Target/MBlaze/MBlazeInstrInfo.td21
-rw-r--r--lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp8
-rw-r--r--lib/Target/MBlaze/MBlazeIntrinsicInfo.h4
-rw-r--r--lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp222
-rw-r--r--lib/Target/MBlaze/MBlazeRegisterInfo.cpp172
-rw-r--r--lib/Target/MBlaze/MBlazeRegisterInfo.h12
-rw-r--r--lib/Target/MBlaze/MBlazeSubtarget.cpp2
-rw-r--r--lib/Target/MBlaze/MBlazeTargetMachine.cpp50
-rw-r--r--lib/Target/MBlaze/MBlazeTargetMachine.h5
-rw-r--r--lib/Target/MBlaze/MBlazeTargetObjectFile.cpp2
-rw-r--r--lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt13
-rw-r--r--lib/Target/MBlaze/MCTargetDesc/MBlazeAsmBackend.cpp159
-rw-r--r--lib/Target/MBlaze/MCTargetDesc/MBlazeBaseInfo.h240
-rw-r--r--lib/Target/MBlaze/MCTargetDesc/MBlazeMCCodeEmitter.cpp224
-rw-r--r--lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp93
-rw-r--r--lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h11
-rw-r--r--lib/Target/MBlaze/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp2
-rw-r--r--lib/Target/MSP430/CMakeLists.txt26
-rw-r--r--lib/Target/MSP430/InstPrinter/CMakeLists.txt8
-rw-r--r--lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp4
-rw-r--r--lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h4
-rw-r--r--lib/Target/MSP430/MCTargetDesc/CMakeLists.txt8
-rw-r--r--lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp51
-rw-r--r--lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h4
-rw-r--r--lib/Target/MSP430/MSP430AsmPrinter.cpp14
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.cpp7
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.h4
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.cpp2
-rw-r--r--lib/Target/MSP430/MSP430RegisterInfo.cpp16
-rw-r--r--lib/Target/MSP430/MSP430RegisterInfo.h5
-rw-r--r--lib/Target/MSP430/MSP430Subtarget.cpp2
-rw-r--r--lib/Target/MSP430/MSP430TargetMachine.cpp11
-rw-r--r--lib/Target/MSP430/MSP430TargetMachine.h5
-rw-r--r--lib/Target/MSP430/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/MSP430/TargetInfo/MSP430TargetInfo.cpp2
-rw-r--r--lib/Target/Mangler.cpp4
-rw-r--r--lib/Target/Mips/CMakeLists.txt28
-rw-r--r--lib/Target/Mips/InstPrinter/CMakeLists.txt8
-rw-r--r--lib/Target/Mips/InstPrinter/Makefile2
-rw-r--r--lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp6
-rw-r--r--lib/Target/Mips/InstPrinter/MipsInstPrinter.h4
-rw-r--r--lib/Target/Mips/MCTargetDesc/CMakeLists.txt13
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp117
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h113
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h90
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp3
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp52
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp122
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h21
-rw-r--r--lib/Target/Mips/Mips.h3
-rw-r--r--lib/Target/Mips/Mips.td32
-rw-r--r--lib/Target/Mips/Mips64InstrInfo.td214
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp42
-rw-r--r--lib/Target/Mips/MipsCallingConv.td55
-rw-r--r--lib/Target/Mips/MipsCodeEmitter.cpp245
-rw-r--r--lib/Target/Mips/MipsDelaySlotFiller.cpp204
-rw-r--r--lib/Target/Mips/MipsFrameLowering.cpp19
-rw-r--r--lib/Target/Mips/MipsFrameLowering.h5
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp185
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp848
-rw-r--r--lib/Target/Mips/MipsISelLowering.h16
-rw-r--r--lib/Target/Mips/MipsInstrFPU.td236
-rw-r--r--lib/Target/Mips/MipsInstrFormats.td44
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp210
-rw-r--r--lib/Target/Mips/MipsInstrInfo.h37
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td832
-rw-r--r--lib/Target/Mips/MipsJITInfo.cpp230
-rw-r--r--lib/Target/Mips/MipsJITInfo.h70
-rw-r--r--lib/Target/Mips/MipsMCInstLower.cpp64
-rw-r--r--lib/Target/Mips/MipsMCInstLower.h5
-rw-r--r--lib/Target/Mips/MipsMCSymbolRefExpr.cpp9
-rw-r--r--lib/Target/Mips/MipsMCSymbolRefExpr.h7
-rw-r--r--lib/Target/Mips/MipsMachineFunction.h9
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.cpp205
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.h4
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.td119
-rw-r--r--lib/Target/Mips/MipsRelocations.h41
-rw-r--r--lib/Target/Mips/MipsSubtarget.cpp38
-rw-r--r--lib/Target/Mips/MipsSubtarget.h15
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp73
-rw-r--r--lib/Target/Mips/MipsTargetMachine.h48
-rw-r--r--lib/Target/Mips/MipsTargetObjectFile.cpp2
-rw-r--r--lib/Target/Mips/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp16
-rw-r--r--lib/Target/PTX/CMakeLists.txt32
-rw-r--r--lib/Target/PTX/InstPrinter/CMakeLists.txt13
-rw-r--r--lib/Target/PTX/InstPrinter/Makefile16
-rw-r--r--lib/Target/PTX/InstPrinter/PTXInstPrinter.cpp192
-rw-r--r--lib/Target/PTX/InstPrinter/PTXInstPrinter.h47
-rw-r--r--lib/Target/PTX/MCTargetDesc/CMakeLists.txt9
-rw-r--r--lib/Target/PTX/MCTargetDesc/PTXBaseInfo.h63
-rw-r--r--lib/Target/PTX/MCTargetDesc/PTXMCTargetDesc.cpp53
-rw-r--r--lib/Target/PTX/Makefile3
-rw-r--r--lib/Target/PTX/PTX.h28
-rw-r--r--lib/Target/PTX/PTX.td28
-rw-r--r--lib/Target/PTX/PTXAsmPrinter.cpp500
-rw-r--r--lib/Target/PTX/PTXAsmPrinter.h57
-rw-r--r--lib/Target/PTX/PTXCallingConv.td29
-rw-r--r--lib/Target/PTX/PTXFPRoundingModePass.cpp179
-rw-r--r--lib/Target/PTX/PTXISelDAGToDAG.cpp182
-rw-r--r--lib/Target/PTX/PTXISelLowering.cpp273
-rw-r--r--lib/Target/PTX/PTXISelLowering.h19
-rw-r--r--lib/Target/PTX/PTXInstrFormats.td31
-rw-r--r--lib/Target/PTX/PTXInstrInfo.cpp82
-rw-r--r--lib/Target/PTX/PTXInstrInfo.td1241
-rw-r--r--lib/Target/PTX/PTXInstrLoadStore.td278
-rw-r--r--lib/Target/PTX/PTXIntrinsicInstrInfo.td78
-rw-r--r--lib/Target/PTX/PTXMCAsmStreamer.cpp15
-rw-r--r--lib/Target/PTX/PTXMCInstLower.cpp32
-rw-r--r--lib/Target/PTX/PTXMFInfoExtract.cpp36
-rw-r--r--lib/Target/PTX/PTXMachineFunctionInfo.h163
-rw-r--r--lib/Target/PTX/PTXParamManager.cpp73
-rw-r--r--lib/Target/PTX/PTXParamManager.h86
-rw-r--r--lib/Target/PTX/PTXRegAlloc.cpp58
-rw-r--r--lib/Target/PTX/PTXRegisterInfo.cpp29
-rw-r--r--lib/Target/PTX/PTXRegisterInfo.h18
-rw-r--r--lib/Target/PTX/PTXRegisterInfo.td540
-rw-r--r--lib/Target/PTX/PTXSelectionDAGInfo.cpp149
-rw-r--r--lib/Target/PTX/PTXSelectionDAGInfo.h53
-rw-r--r--lib/Target/PTX/PTXSubtarget.cpp2
-rw-r--r--lib/Target/PTX/PTXSubtarget.h11
-rw-r--r--lib/Target/PTX/PTXTargetMachine.cpp318
-rw-r--r--lib/Target/PTX/PTXTargetMachine.h60
-rw-r--r--lib/Target/PTX/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/PTX/TargetInfo/PTXTargetInfo.cpp2
-rwxr-xr-xlib/Target/PTX/generate-register-td.py163
-rw-r--r--lib/Target/PowerPC/CMakeLists.txt34
-rw-r--r--lib/Target/PowerPC/InstPrinter/CMakeLists.txt8
-rw-r--r--lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp11
-rw-r--r--lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h2
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt12
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp191
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCBaseInfo.h70
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h (renamed from lib/Target/PowerPC/PPCFixupKinds.h)0
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp6
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp193
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp115
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h10
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp (renamed from lib/Target/PowerPC/PPCPredicates.cpp)0
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h37
-rw-r--r--lib/Target/PowerPC/PPC.h11
-rw-r--r--lib/Target/PowerPC/PPC.td4
-rw-r--r--lib/Target/PowerPC/PPCAsmBackend.cpp123
-rw-r--r--lib/Target/PowerPC/PPCAsmPrinter.cpp14
-rw-r--r--lib/Target/PowerPC/PPCBranchSelector.cpp2
-rw-r--r--lib/Target/PowerPC/PPCCodeEmitter.cpp4
-rw-r--r--lib/Target/PowerPC/PPCFrameLowering.cpp17
-rw-r--r--lib/Target/PowerPC/PPCFrameLowering.h1
-rw-r--r--lib/Target/PowerPC/PPCISelDAGToDAG.cpp2
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp65
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.h17
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.cpp36
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td6
-rw-r--r--lib/Target/PowerPC/PPCMCCodeEmitter.cpp194
-rw-r--r--lib/Target/PowerPC/PPCPredicates.h39
-rw-r--r--lib/Target/PowerPC/PPCRegisterInfo.cpp79
-rw-r--r--lib/Target/PowerPC/PPCRegisterInfo.h8
-rw-r--r--lib/Target/PowerPC/PPCSubtarget.cpp2
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.cpp71
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.h16
-rw-r--r--lib/Target/PowerPC/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp2
-rw-r--r--lib/Target/README.txt10
-rw-r--r--lib/Target/Sparc/CMakeLists.txt25
-rw-r--r--lib/Target/Sparc/MCTargetDesc/CMakeLists.txt8
-rw-r--r--lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp36
-rw-r--r--lib/Target/Sparc/SparcAsmPrinter.cpp2
-rw-r--r--lib/Target/Sparc/SparcISelLowering.cpp8
-rw-r--r--lib/Target/Sparc/SparcInstrInfo.cpp2
-rw-r--r--lib/Target/Sparc/SparcRegisterInfo.cpp15
-rw-r--r--lib/Target/Sparc/SparcRegisterInfo.h4
-rw-r--r--lib/Target/Sparc/SparcSubtarget.cpp2
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.cpp27
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.h16
-rw-r--r--lib/Target/Sparc/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp2
-rw-r--r--lib/Target/SystemZ/CMakeLists.txt25
-rw-r--r--lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt7
-rw-r--r--lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp39
-rw-r--r--lib/Target/SystemZ/SystemZAsmPrinter.cpp4
-rw-r--r--lib/Target/SystemZ/SystemZISelLowering.cpp1
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.cpp2
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.td2
-rw-r--r--lib/Target/SystemZ/SystemZRegisterInfo.cpp17
-rw-r--r--lib/Target/SystemZ/SystemZRegisterInfo.h4
-rw-r--r--lib/Target/SystemZ/SystemZSubtarget.cpp2
-rw-r--r--lib/Target/SystemZ/SystemZTargetMachine.cpp13
-rw-r--r--lib/Target/SystemZ/SystemZTargetMachine.h5
-rw-r--r--lib/Target/SystemZ/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/SystemZ/TargetInfo/SystemZTargetInfo.cpp2
-rw-r--r--lib/Target/Target.cpp10
-rw-r--r--lib/Target/TargetAsmInfo.cpp23
-rw-r--r--lib/Target/TargetAsmLexer.cpp14
-rw-r--r--lib/Target/TargetData.cpp53
-rw-r--r--lib/Target/TargetFrameLowering.cpp8
-rw-r--r--lib/Target/TargetLoweringObjectFile.cpp59
-rw-r--r--lib/Target/TargetMachine.cpp67
-rw-r--r--lib/Target/TargetRegisterInfo.cpp49
-rw-r--r--lib/Target/X86/AsmParser/CMakeLists.txt11
-rw-r--r--lib/Target/X86/AsmParser/X86AsmLexer.cpp20
-rw-r--r--lib/Target/X86/AsmParser/X86AsmParser.cpp84
-rw-r--r--lib/Target/X86/CMakeLists.txt41
-rw-r--r--lib/Target/X86/Disassembler/CMakeLists.txt10
-rw-r--r--lib/Target/X86/Disassembler/X86Disassembler.cpp77
-rw-r--r--lib/Target/X86/Disassembler/X86Disassembler.h26
-rw-r--r--lib/Target/X86/Disassembler/X86DisassemblerDecoder.c165
-rw-r--r--lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h8
-rw-r--r--lib/Target/X86/InstPrinter/CMakeLists.txt9
-rw-r--r--lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp10
-rw-r--r--lib/Target/X86/InstPrinter/X86ATTInstPrinter.h2
-rw-r--r--lib/Target/X86/InstPrinter/X86InstComments.cpp31
-rw-r--r--lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp7
-rw-r--r--lib/Target/X86/InstPrinter/X86IntelInstPrinter.h2
-rw-r--r--lib/Target/X86/MCTargetDesc/CMakeLists.txt13
-rw-r--r--lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp458
-rw-r--r--lib/Target/X86/MCTargetDesc/X86BaseInfo.h548
-rw-r--r--lib/Target/X86/MCTargetDesc/X86FixupKinds.h (renamed from lib/Target/X86/X86FixupKinds.h)0
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp1074
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp338
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h45
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp554
-rw-r--r--lib/Target/X86/README-SSE.txt2
-rw-r--r--lib/Target/X86/README.txt38
-rw-r--r--lib/Target/X86/SSEDomainFix.cpp506
-rw-r--r--lib/Target/X86/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/X86/TargetInfo/X86TargetInfo.cpp2
-rw-r--r--lib/Target/X86/Utils/CMakeLists.txt8
-rw-r--r--lib/Target/X86/Utils/X86ShuffleDecode.cpp75
-rw-r--r--lib/Target/X86/Utils/X86ShuffleDecode.h20
-rw-r--r--lib/Target/X86/X86.h30
-rw-r--r--lib/Target/X86/X86.td78
-rw-r--r--lib/Target/X86/X86AsmBackend.cpp453
-rw-r--r--lib/Target/X86/X86AsmPrinter.cpp23
-rw-r--r--lib/Target/X86/X86CodeEmitter.cpp36
-rw-r--r--lib/Target/X86/X86ELFWriterInfo.cpp2
-rw-r--r--lib/Target/X86/X86FastISel.cpp93
-rw-r--r--lib/Target/X86/X86FloatingPoint.cpp34
-rw-r--r--lib/Target/X86/X86FrameLowering.cpp625
-rw-r--r--lib/Target/X86/X86FrameLowering.h7
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp16
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp2940
-rw-r--r--lib/Target/X86/X86ISelLowering.h62
-rw-r--r--lib/Target/X86/X86InstrArithmetic.td96
-rw-r--r--lib/Target/X86/X86InstrCompiler.td102
-rw-r--r--lib/Target/X86/X86InstrExtension.td4
-rw-r--r--lib/Target/X86/X86InstrFormats.td8
-rw-r--r--lib/Target/X86/X86InstrFragmentsSIMD.td84
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp1838
-rw-r--r--lib/Target/X86/X86InstrInfo.h553
-rw-r--r--lib/Target/X86/X86InstrInfo.td209
-rw-r--r--lib/Target/X86/X86InstrSSE.td4104
-rw-r--r--lib/Target/X86/X86InstrSystem.td114
-rw-r--r--lib/Target/X86/X86InstrVMX.td10
-rw-r--r--lib/Target/X86/X86MCCodeEmitter.cpp1044
-rw-r--r--lib/Target/X86/X86MCInstLower.cpp23
-rw-r--r--lib/Target/X86/X86MachObjectWriter.cpp554
-rw-r--r--lib/Target/X86/X86MachineFunctionInfo.h20
-rw-r--r--lib/Target/X86/X86RegisterInfo.cpp165
-rw-r--r--lib/Target/X86/X86RegisterInfo.h25
-rw-r--r--lib/Target/X86/X86RegisterInfo.td11
-rw-r--r--lib/Target/X86/X86SelectionDAGInfo.cpp2
-rw-r--r--lib/Target/X86/X86Subtarget.cpp78
-rw-r--r--lib/Target/X86/X86Subtarget.h36
-rw-r--r--lib/Target/X86/X86TargetMachine.cpp173
-rw-r--r--lib/Target/X86/X86TargetMachine.h22
-rw-r--r--lib/Target/X86/X86TargetObjectFile.cpp76
-rw-r--r--lib/Target/X86/X86TargetObjectFile.h22
-rw-r--r--lib/Target/X86/X86VZeroUpper.cpp105
-rw-r--r--lib/Target/XCore/CMakeLists.txt25
-rw-r--r--lib/Target/XCore/MCTargetDesc/CMakeLists.txt7
-rw-r--r--lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp48
-rw-r--r--lib/Target/XCore/TargetInfo/CMakeLists.txt8
-rw-r--r--lib/Target/XCore/TargetInfo/XCoreTargetInfo.cpp2
-rw-r--r--lib/Target/XCore/XCoreAsmPrinter.cpp60
-rw-r--r--lib/Target/XCore/XCoreFrameLowering.cpp11
-rw-r--r--lib/Target/XCore/XCoreFrameLowering.h2
-rw-r--r--lib/Target/XCore/XCoreISelDAGToDAG.cpp11
-rw-r--r--lib/Target/XCore/XCoreISelLowering.cpp37
-rw-r--r--lib/Target/XCore/XCoreISelLowering.h5
-rw-r--r--lib/Target/XCore/XCoreInstrInfo.cpp12
-rw-r--r--lib/Target/XCore/XCoreInstrInfo.h5
-rw-r--r--lib/Target/XCore/XCoreInstrInfo.td81
-rw-r--r--lib/Target/XCore/XCoreRegisterInfo.cpp15
-rw-r--r--lib/Target/XCore/XCoreRegisterInfo.h5
-rw-r--r--lib/Target/XCore/XCoreSubtarget.cpp2
-rw-r--r--lib/Target/XCore/XCoreTargetMachine.cpp10
-rw-r--r--lib/Target/XCore/XCoreTargetMachine.h5
-rw-r--r--lib/Transforms/IPO/ArgumentPromotion.cpp43
-rw-r--r--lib/Transforms/IPO/CMakeLists.txt12
-rw-r--r--lib/Transforms/IPO/ConstantMerge.cpp49
-rw-r--r--lib/Transforms/IPO/DeadArgumentElimination.cpp12
-rw-r--r--lib/Transforms/IPO/FunctionAttrs.cpp4
-rw-r--r--lib/Transforms/IPO/GlobalOpt.cpp125
-rw-r--r--lib/Transforms/IPO/IPConstantPropagation.cpp2
-rw-r--r--lib/Transforms/IPO/IPO.cpp15
-rw-r--r--lib/Transforms/IPO/InlineAlways.cpp15
-rw-r--r--lib/Transforms/IPO/InlineSimple.cpp26
-rw-r--r--lib/Transforms/IPO/Inliner.cpp4
-rw-r--r--lib/Transforms/IPO/LoopExtractor.cpp73
-rw-r--r--lib/Transforms/IPO/LowerSetJmp.cpp547
-rw-r--r--lib/Transforms/IPO/MergeFunctions.cpp70
-rw-r--r--lib/Transforms/IPO/PassManagerBuilder.cpp343
-rw-r--r--lib/Transforms/IPO/PruneEH.cpp5
-rw-r--r--lib/Transforms/IPO/StripSymbols.cpp2
-rw-r--r--lib/Transforms/InstCombine/CMakeLists.txt8
-rw-r--r--lib/Transforms/InstCombine/InstCombine.h15
-rw-r--r--lib/Transforms/InstCombine/InstCombineAddSub.cpp8
-rw-r--r--lib/Transforms/InstCombine/InstCombineAndOrXor.cpp53
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp192
-rw-r--r--lib/Transforms/InstCombine/InstCombineCasts.cpp112
-rw-r--r--lib/Transforms/InstCombine/InstCombineCompares.cpp495
-rw-r--r--lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp99
-rw-r--r--lib/Transforms/InstCombine/InstCombineMulDivRem.cpp13
-rw-r--r--lib/Transforms/InstCombine/InstCombinePHI.cpp20
-rw-r--r--lib/Transforms/InstCombine/InstCombineSelect.cpp20
-rw-r--r--lib/Transforms/InstCombine/InstCombineShifts.cpp49
-rw-r--r--lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp24
-rw-r--r--lib/Transforms/InstCombine/InstCombineVectorOps.cpp8
-rw-r--r--lib/Transforms/InstCombine/InstructionCombining.cpp630
-rw-r--r--lib/Transforms/Instrumentation/CMakeLists.txt7
-rw-r--r--lib/Transforms/Instrumentation/EdgeProfiling.cpp2
-rw-r--r--lib/Transforms/Instrumentation/GCOVProfiling.cpp372
-rw-r--r--lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp4
-rw-r--r--lib/Transforms/Instrumentation/PathProfiling.cpp29
-rw-r--r--lib/Transforms/Instrumentation/ProfilingUtils.cpp13
-rw-r--r--lib/Transforms/Scalar/ADCE.cpp2
-rw-r--r--lib/Transforms/Scalar/CMakeLists.txt10
-rw-r--r--lib/Transforms/Scalar/CodeGenPrepare.cpp108
-rw-r--r--lib/Transforms/Scalar/DeadStoreElimination.cpp182
-rw-r--r--lib/Transforms/Scalar/EarlyCSE.cpp8
-rw-r--r--lib/Transforms/Scalar/GVN.cpp274
-rw-r--r--lib/Transforms/Scalar/IndVarSimplify.cpp1142
-rw-r--r--lib/Transforms/Scalar/JumpThreading.cpp4
-rw-r--r--lib/Transforms/Scalar/LICM.cpp64
-rw-r--r--lib/Transforms/Scalar/LoopIdiomRecognize.cpp10
-rw-r--r--lib/Transforms/Scalar/LoopStrengthReduce.cpp215
-rw-r--r--lib/Transforms/Scalar/LoopUnrollPass.cpp61
-rw-r--r--lib/Transforms/Scalar/LoopUnswitch.cpp28
-rw-r--r--lib/Transforms/Scalar/LowerAtomic.cpp173
-rw-r--r--lib/Transforms/Scalar/MemCpyOptimizer.cpp14
-rw-r--r--lib/Transforms/Scalar/ObjCARC.cpp440
-rw-r--r--lib/Transforms/Scalar/Reassociate.cpp2
-rw-r--r--lib/Transforms/Scalar/SCCP.cpp250
-rw-r--r--lib/Transforms/Scalar/Scalar.cpp5
-rw-r--r--lib/Transforms/Scalar/ScalarReplAggregates.cpp598
-rw-r--r--lib/Transforms/Scalar/SimplifyLibCalls.cpp111
-rw-r--r--lib/Transforms/Scalar/Sink.cpp13
-rw-r--r--lib/Transforms/Scalar/TailDuplication.cpp373
-rw-r--r--lib/Transforms/Utils/AddrModeMatcher.cpp4
-rw-r--r--lib/Transforms/Utils/BasicBlockUtils.cpp346
-rw-r--r--lib/Transforms/Utils/BreakCriticalEdges.cpp56
-rw-r--r--lib/Transforms/Utils/BuildLibCalls.cpp10
-rw-r--r--lib/Transforms/Utils/CMakeLists.txt8
-rw-r--r--lib/Transforms/Utils/CloneFunction.cpp13
-rw-r--r--lib/Transforms/Utils/CloneModule.cpp27
-rw-r--r--lib/Transforms/Utils/CodeExtractor.cpp45
-rw-r--r--lib/Transforms/Utils/InlineFunction.cpp178
-rw-r--r--lib/Transforms/Utils/Local.cpp25
-rw-r--r--lib/Transforms/Utils/LoopSimplify.cpp47
-rw-r--r--lib/Transforms/Utils/LoopUnroll.cpp186
-rw-r--r--lib/Transforms/Utils/LowerExpectIntrinsic.cpp4
-rw-r--r--lib/Transforms/Utils/LowerInvoke.cpp37
-rw-r--r--lib/Transforms/Utils/LowerSwitch.cpp4
-rw-r--r--lib/Transforms/Utils/PromoteMemoryToRegister.cpp4
-rw-r--r--lib/Transforms/Utils/SSAUpdater.cpp8
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp155
-rw-r--r--lib/Transforms/Utils/SimplifyIndVar.cpp432
-rw-r--r--lib/Transforms/Utils/ValueMapper.cpp5
-rw-r--r--lib/VMCore/AsmWriter.cpp252
-rw-r--r--lib/VMCore/Attributes.cpp6
-rw-r--r--lib/VMCore/AutoUpgrade.cpp395
-rw-r--r--lib/VMCore/BasicBlock.cpp34
-rw-r--r--lib/VMCore/CMakeLists.txt5
-rw-r--r--lib/VMCore/ConstantFold.cpp209
-rw-r--r--lib/VMCore/ConstantFold.h6
-rw-r--r--lib/VMCore/Constants.cpp265
-rw-r--r--lib/VMCore/ConstantsContext.h32
-rw-r--r--lib/VMCore/Core.cpp183
-rw-r--r--lib/VMCore/DebugLoc.cpp4
-rw-r--r--lib/VMCore/Function.cpp43
-rw-r--r--lib/VMCore/GCOV.cpp281
-rw-r--r--lib/VMCore/Globals.cpp8
-rw-r--r--lib/VMCore/IRBuilder.cpp2
-rw-r--r--lib/VMCore/InlineAsm.cpp8
-rw-r--r--lib/VMCore/Instruction.cpp68
-rw-r--r--lib/VMCore/Instructions.cpp674
-rw-r--r--lib/VMCore/LLVMContextImpl.h4
-rw-r--r--lib/VMCore/Makefile4
-rw-r--r--lib/VMCore/Module.cpp48
-rw-r--r--lib/VMCore/PassManager.cpp59
-rw-r--r--lib/VMCore/PassRegistry.cpp1
-rw-r--r--lib/VMCore/Type.cpp95
-rw-r--r--lib/VMCore/Value.cpp8
-rw-r--r--lib/VMCore/ValueTypes.cpp16
-rw-r--r--lib/VMCore/Verifier.cpp284
-rw-r--r--runtime/libprofile/CommonProfiling.c17
-rw-r--r--runtime/libprofile/GCDAProfiling.c6
-rw-r--r--runtime/libprofile/Makefile4
-rw-r--r--test/Analysis/BasicAA/2009-10-13-AtomicModRef.ll4
-rw-r--r--test/Analysis/BasicAA/cas.ll4
-rw-r--r--test/Analysis/BasicAA/gep-alias.ll32
-rw-r--r--test/Analysis/BasicAA/memset_pattern.ll21
-rw-r--r--test/Analysis/BasicAA/modref.ll17
-rw-r--r--test/Analysis/BlockFrequencyInfo/basic.ll92
-rw-r--r--test/Analysis/BlockFrequencyInfo/dg.exp (renamed from test/Transforms/LowerSetJmp/dg.exp)0
-rw-r--r--test/Analysis/ScalarEvolution/2011-10-04-ConstEvolve.ll50
-rw-r--r--test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll56
-rw-r--r--test/Analysis/ScalarEvolution/avoid-smax-1.ll7
-rw-r--r--test/Analysis/ScalarEvolution/max-trip-count.ll28
-rw-r--r--test/Assembler/2003-06-17-InvokeDisassemble.ll10
-rw-r--r--test/Assembler/AutoUpgradeIntrinsics.ll13
-rw-r--r--test/Assembler/atomic.ll26
-rw-r--r--test/Bindings/Ocaml/ipo_opts.ml73
-rw-r--r--test/Bindings/Ocaml/scalar_opts.ml10
-rw-r--r--test/Bindings/Ocaml/target.ml1
-rw-r--r--test/Bindings/Ocaml/vmcore.ml165
-rw-r--r--test/CMakeLists.txt2
-rw-r--r--test/CodeGen/ARM/2009-10-16-Scope.ll4
-rw-r--r--test/CodeGen/ARM/2010-11-30-reloc-movt.ll16
-rw-r--r--test/CodeGen/ARM/2010-12-15-elf-lcomm.ll21
-rw-r--r--test/CodeGen/ARM/2011-06-09-TailCallByVal.ll1
-rw-r--r--test/CodeGen/ARM/2011-08-02-MergedGlobalDbg.ll124
-rw-r--r--test/CodeGen/ARM/2011-08-12-vmovqqqq-pseudo.ll12
-rw-r--r--test/CodeGen/ARM/2011-08-25-ldmia_ret.ll100
-rw-r--r--test/CodeGen/ARM/2011-08-29-SchedCycle.ll45
-rw-r--r--test/CodeGen/ARM/2011-08-29-ldr_pre_imm.ll34
-rw-r--r--test/CodeGen/ARM/2011-09-09-OddVectorDivision.ll23
-rw-r--r--test/CodeGen/ARM/2011-09-19-cpsr.ll54
-rw-r--r--test/CodeGen/ARM/2011-09-28-CMovCombineBug.ll30
-rw-r--r--test/CodeGen/ARM/atomic-64bit.ll128
-rw-r--r--test/CodeGen/ARM/atomic-cmp.ll8
-rw-r--r--test/CodeGen/ARM/atomic-load-store.ll56
-rw-r--r--test/CodeGen/ARM/atomic-op.ll48
-rw-r--r--test/CodeGen/ARM/avoid-cpsr-rmw.ll6
-rw-r--r--test/CodeGen/ARM/call-tc.ll4
-rw-r--r--test/CodeGen/ARM/carry.ll10
-rw-r--r--test/CodeGen/ARM/crash-greedy-v6.ll32
-rw-r--r--test/CodeGen/ARM/crash.ll44
-rw-r--r--test/CodeGen/ARM/debug-info-arg.ll65
-rw-r--r--test/CodeGen/ARM/debug-info-blocks.ll2
-rw-r--r--test/CodeGen/ARM/debug-info-sreg2.ll6
-rw-r--r--test/CodeGen/ARM/divmod.ll58
-rw-r--r--test/CodeGen/ARM/elf-lcomm-align.ll14
-rw-r--r--test/CodeGen/ARM/fabss.ll4
-rw-r--r--test/CodeGen/ARM/fast-isel.ll4
-rw-r--r--test/CodeGen/ARM/fp_convert.ll6
-rw-r--r--test/CodeGen/ARM/fpmem.ll18
-rw-r--r--test/CodeGen/ARM/hidden-vis-2.ll2
-rw-r--r--test/CodeGen/ARM/hidden-vis-3.ll2
-rw-r--r--test/CodeGen/ARM/iabs.ll8
-rw-r--r--test/CodeGen/ARM/ifcvt4.ll10
-rw-r--r--test/CodeGen/ARM/indirectbr.ll1
-rw-r--r--test/CodeGen/ARM/inlineasm3.ll12
-rw-r--r--test/CodeGen/ARM/inlineasm4.ll17
-rw-r--r--test/CodeGen/ARM/lsr-on-unrolled-loops.ll495
-rw-r--r--test/CodeGen/ARM/lsr-unfolded-offset.ll3
-rw-r--r--test/CodeGen/ARM/mulhi.ll44
-rw-r--r--test/CodeGen/ARM/select.ll12
-rw-r--r--test/CodeGen/ARM/shifter_operand.ll9
-rw-r--r--test/CodeGen/ARM/str_pre-2.ll4
-rw-r--r--test/CodeGen/ARM/subreg-remat.ll52
-rw-r--r--test/CodeGen/ARM/sxt_rot.ll41
-rw-r--r--test/CodeGen/ARM/tail-opts.ll2
-rw-r--r--test/CodeGen/ARM/thumb2-it-block.ll20
-rw-r--r--test/CodeGen/ARM/va_arg.ll1
-rw-r--r--test/CodeGen/ARM/vext.ll17
-rw-r--r--test/CodeGen/ARM/widen-vmovs.ll35
-rw-r--r--test/CodeGen/Alpha/2006-04-04-zextload.ll4
-rw-r--r--test/CodeGen/Alpha/mb.ll4
-rw-r--r--test/CodeGen/Alpha/wmb.ll8
-rw-r--r--test/CodeGen/CBackend/X86/dg.exp2
-rw-r--r--test/CodeGen/CellSPU/jumptable.ll12
-rw-r--r--test/CodeGen/CellSPU/or_ops.ll13
-rw-r--r--test/CodeGen/Generic/2004-02-08-UnwindSupport.ll17
-rw-r--r--test/CodeGen/Generic/2007-02-25-invoke.ll6
-rw-r--r--test/CodeGen/Generic/2007-04-30-LandingPadBranchFolding.ll6
-rw-r--r--test/CodeGen/Generic/2007-12-17-InvokeAsm.ll12
-rw-r--r--test/CodeGen/Generic/2007-12-31-UnusedSelector.ll5
-rw-r--r--test/CodeGen/Generic/2009-06-03-UnreachableSplitPad.ll4
-rw-r--r--test/CodeGen/Generic/2009-11-16-BadKillsCrash.ll8
-rw-r--r--test/CodeGen/Generic/2011-07-07-ScheduleDAGCrash.ll3
-rw-r--r--test/CodeGen/Generic/exception-handling.ll29
-rw-r--r--test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll3
-rw-r--r--test/CodeGen/Generic/promote-integers.ll15
-rw-r--r--test/CodeGen/Mips/2008-07-05-ByVal.ll18
-rw-r--r--test/CodeGen/Mips/2008-07-06-fadd64.ll6
-rw-r--r--test/CodeGen/Mips/2008-07-07-FPExtend.ll6
-rw-r--r--test/CodeGen/Mips/2008-07-07-IntDoubleConvertions.ll17
-rw-r--r--test/CodeGen/Mips/2008-07-15-InternalConstant.ll19
-rw-r--r--test/CodeGen/Mips/2008-07-15-SmallSection.ll23
-rw-r--r--test/CodeGen/Mips/2008-07-16-SignExtInReg.ll8
-rw-r--r--test/CodeGen/Mips/2008-08-03-fabs64.ll8
-rw-r--r--test/CodeGen/Mips/2008-08-07-FPRound.ll6
-rw-r--r--test/CodeGen/Mips/2008-08-08-bswap.ll5
-rw-r--r--test/CodeGen/Mips/2010-07-20-Select.ll22
-rw-r--r--test/CodeGen/Mips/2010-11-09-CountLeading.ll2
-rw-r--r--test/CodeGen/Mips/2010-11-09-Mul.ll2
-rw-r--r--test/CodeGen/Mips/alloca.ll2
-rw-r--r--test/CodeGen/Mips/atomic.ll125
-rw-r--r--test/CodeGen/Mips/brdelayslot.ll15
-rwxr-xr-xtest/CodeGen/Mips/cmov.ll4
-rw-r--r--test/CodeGen/Mips/constantfp0.ll11
-rw-r--r--test/CodeGen/Mips/cprestore.ll20
-rw-r--r--test/CodeGen/Mips/double2int.ll2
-rw-r--r--test/CodeGen/Mips/eh.ll15
-rw-r--r--test/CodeGen/Mips/extins.ll21
-rw-r--r--test/CodeGen/Mips/fcopysign.ll4
-rw-r--r--test/CodeGen/Mips/fpcmp.ll15
-rw-r--r--test/CodeGen/Mips/frame-address.ll2
-rw-r--r--test/CodeGen/Mips/i64arg.ll2
-rw-r--r--test/CodeGen/Mips/inlineasmmemop.ll2
-rw-r--r--test/CodeGen/Mips/internalfunc.ll2
-rw-r--r--test/CodeGen/Mips/largeimmprinting.ll6
-rw-r--r--test/CodeGen/Mips/madd-msub.ll14
-rw-r--r--test/CodeGen/Mips/mips64fpldst.ll58
-rw-r--r--test/CodeGen/Mips/mips64instrs.ll143
-rw-r--r--test/CodeGen/Mips/mips64intldst.ll157
-rw-r--r--test/CodeGen/Mips/mips64shift.ll104
-rw-r--r--test/CodeGen/Mips/mipslopat.ll19
-rw-r--r--test/CodeGen/Mips/o32_cc.ll2
-rw-r--r--test/CodeGen/Mips/o32_cc_byval.ll2
-rw-r--r--test/CodeGen/Mips/o32_cc_vararg.ll2
-rw-r--r--test/CodeGen/Mips/rotate.ll2
-rw-r--r--test/CodeGen/Mips/select.ll96
-rw-r--r--test/CodeGen/Mips/tls.ll4
-rw-r--r--test/CodeGen/Mips/unalignedload.ll41
-rw-r--r--test/CodeGen/PTX/20110926-sitofp.ll24
-rw-r--r--test/CodeGen/PTX/add.ll40
-rw-r--r--test/CodeGen/PTX/aggregates.ll1
-rw-r--r--test/CodeGen/PTX/bitwise.ll6
-rw-r--r--test/CodeGen/PTX/bra.ll8
-rw-r--r--test/CodeGen/PTX/cvt.ll186
-rw-r--r--test/CodeGen/PTX/fdiv-sm10.ll8
-rw-r--r--test/CodeGen/PTX/fdiv-sm13.ll8
-rw-r--r--test/CodeGen/PTX/fneg.ll8
-rw-r--r--test/CodeGen/PTX/intrinsic.ll134
-rw-r--r--test/CodeGen/PTX/ld.ll255
-rw-r--r--test/CodeGen/PTX/llvm-intrinsic.ll24
-rw-r--r--test/CodeGen/PTX/mad.ll8
-rw-r--r--test/CodeGen/PTX/mov.ll24
-rw-r--r--test/CodeGen/PTX/mul.ll16
-rw-r--r--test/CodeGen/PTX/parameter-order.ll4
-rw-r--r--test/CodeGen/PTX/selp.ll8
-rw-r--r--test/CodeGen/PTX/setp.ll136
-rw-r--r--test/CodeGen/PTX/shl.ll6
-rw-r--r--test/CodeGen/PTX/shr.ll12
-rw-r--r--test/CodeGen/PTX/simple-call.ll27
-rw-r--r--test/CodeGen/PTX/st.ll235
-rw-r--r--test/CodeGen/PTX/stack-object.ll19
-rw-r--r--test/CodeGen/PTX/sub.ll40
-rw-r--r--test/CodeGen/PowerPC/2007-11-16-landingpad-split.ll17
-rw-r--r--test/CodeGen/PowerPC/2009-01-16-DeclareISelBug.ll7
-rw-r--r--test/CodeGen/PowerPC/2009-08-23-linkerprivate.ll2
-rw-r--r--test/CodeGen/PowerPC/Atomics-32.ll1402
-rw-r--r--test/CodeGen/PowerPC/Atomics-64.ll1433
-rw-r--r--test/CodeGen/PowerPC/atomic-1.ll25
-rw-r--r--test/CodeGen/PowerPC/atomic-2.ll25
-rw-r--r--test/CodeGen/PowerPC/cr1eq.ll18
-rw-r--r--test/CodeGen/PowerPC/trampoline.ll6
-rw-r--r--test/CodeGen/Thumb/2011-05-11-DAGLegalizer.ll6
-rw-r--r--test/CodeGen/Thumb/barrier.ll14
-rw-r--r--test/CodeGen/Thumb/iabs.ll11
-rw-r--r--test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll4
-rw-r--r--test/CodeGen/Thumb2/2010-06-21-TailMergeBug.ll18
-rw-r--r--test/CodeGen/Thumb2/machine-licm.ll2
-rw-r--r--test/CodeGen/Thumb2/thumb2-barrier.ll31
-rw-r--r--test/CodeGen/Thumb2/thumb2-bcc.ll23
-rw-r--r--test/CodeGen/Thumb2/thumb2-branch.ll18
-rw-r--r--test/CodeGen/Thumb2/thumb2-ifcvt1.ll8
-rw-r--r--test/CodeGen/Thumb2/thumb2-ldm.ll2
-rw-r--r--test/CodeGen/Thumb2/thumb2-mls.ll2
-rw-r--r--test/CodeGen/Thumb2/thumb2-mul.ll2
-rw-r--r--test/CodeGen/Thumb2/thumb2-sxt-uxt.ll29
-rw-r--r--test/CodeGen/X86/2006-05-11-InstrSched.ll2
-rw-r--r--test/CodeGen/X86/2006-07-19-ATTAsm.ll49
-rw-r--r--test/CodeGen/X86/2007-05-07-InvokeSRet.ll4
-rw-r--r--test/CodeGen/X86/2008-01-08-SchedulerCrash.ll10
-rw-r--r--test/CodeGen/X86/2008-04-17-CoalescerBug.ll6
-rw-r--r--test/CodeGen/X86/2008-05-28-LocalRegAllocBug.ll6
-rw-r--r--test/CodeGen/X86/2008-08-19-SubAndFetch.ll4
-rw-r--r--test/CodeGen/X86/2008-09-18-inline-asm-2.ll2
-rw-r--r--test/CodeGen/X86/2008-10-02-Atomics32-2.ll969
-rw-r--r--test/CodeGen/X86/2009-03-13-PHIElimBug.ll4
-rw-r--r--test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll4
-rw-r--r--test/CodeGen/X86/2009-06-05-ScalarToVectorByteMMX.ll2
-rw-r--r--test/CodeGen/X86/2009-06-18-movlp-shuffle-register.ll3
-rw-r--r--test/CodeGen/X86/2009-09-10-LoadFoldingBug.ll4
-rw-r--r--test/CodeGen/X86/2009-10-16-Scope.ll4
-rw-r--r--test/CodeGen/X86/2009-10-19-atomic-cmp-eflags.ll6
-rw-r--r--test/CodeGen/X86/2009-11-25-ImpDefBug.ll4
-rw-r--r--test/CodeGen/X86/2010-01-08-Atomic64Bug.ll8
-rw-r--r--test/CodeGen/X86/2010-04-06-SSEDomainFixCrash.ll4
-rw-r--r--test/CodeGen/X86/2010-04-30-LocalAlloc-LandingPad.ll2
-rw-r--r--test/CodeGen/X86/2010-10-08-cmpxchg8b.ll4
-rw-r--r--test/CodeGen/X86/2011-05-31-movmsk.ll79
-rw-r--r--test/CodeGen/X86/2011-08-23-PerformSubCombine128.ll18
-rw-r--r--test/CodeGen/X86/2011-08-23-Trampoline.ll16
-rw-r--r--test/CodeGen/X86/2011-08-29-BlockConstant.ll34
-rw-r--r--test/CodeGen/X86/2011-08-29-InitOrder.ll28
-rw-r--r--test/CodeGen/X86/2011-09-14-valcoalesce.ll174
-rw-r--r--test/CodeGen/X86/2011-09-18-sse2cmp.ll12
-rw-r--r--test/CodeGen/X86/2011-09-21-setcc-bug.ll27
-rw-r--r--test/CodeGen/X86/2011-10-11-SpillDead.ll19
-rw-r--r--test/CodeGen/X86/2011-10-11-srl.ll11
-rw-r--r--test/CodeGen/X86/2011-10-12-MachineCSE.ll116
-rw-r--r--test/CodeGen/X86/Atomics-32.ll818
-rw-r--r--test/CodeGen/X86/Atomics-64.ll1919
-rw-r--r--test/CodeGen/X86/MachineSink-DbgValue.ll49
-rw-r--r--test/CodeGen/X86/MachineSink-eflags.ll74
-rw-r--r--test/CodeGen/X86/SIMD/dg.exp5
-rw-r--r--test/CodeGen/X86/SIMD/notvunpcklpd.ll20
-rw-r--r--test/CodeGen/X86/SIMD/notvunpcklps.ll20
-rw-r--r--test/CodeGen/X86/SIMD/vunpcklpd.ll20
-rw-r--r--test/CodeGen/X86/SIMD/vunpcklps.ll20
-rw-r--r--test/CodeGen/X86/alignment-2.ll28
-rw-r--r--test/CodeGen/X86/alignment.ll2
-rw-r--r--test/CodeGen/X86/asm-label2.ll4
-rw-r--r--test/CodeGen/X86/atomic-load-store-wide.ll19
-rw-r--r--test/CodeGen/X86/atomic-load-store.ll23
-rw-r--r--test/CodeGen/X86/atomic-or.ll12
-rw-r--r--test/CodeGen/X86/atomic_add.ll116
-rw-r--r--test/CodeGen/X86/atomic_op.ll62
-rw-r--r--test/CodeGen/X86/avx-128.ll54
-rw-r--r--test/CodeGen/X86/avx-256-arith.ll116
-rw-r--r--test/CodeGen/X86/avx-256-arith.s0
-rw-r--r--test/CodeGen/X86/avx-256-logic.ll161
-rw-r--r--test/CodeGen/X86/avx-256.ll15
-rw-r--r--test/CodeGen/X86/avx-arith.ll261
-rw-r--r--test/CodeGen/X86/avx-basic.ll107
-rw-r--r--test/CodeGen/X86/avx-bitcast.ll10
-rw-r--r--test/CodeGen/X86/avx-blend.ll104
-rw-r--r--test/CodeGen/X86/avx-cast.ll47
-rw-r--r--test/CodeGen/X86/avx-cmp.ll150
-rw-r--r--test/CodeGen/X86/avx-cvt.ll83
-rw-r--r--test/CodeGen/X86/avx-load-store.ll85
-rw-r--r--test/CodeGen/X86/avx-logic.ll179
-rw-r--r--test/CodeGen/X86/avx-minmax.ll65
-rw-r--r--test/CodeGen/X86/avx-movdup.ll34
-rw-r--r--test/CodeGen/X86/avx-select.ll22
-rw-r--r--test/CodeGen/X86/avx-shift.ll75
-rw-r--r--test/CodeGen/X86/avx-shuffle.ll10
-rw-r--r--test/CodeGen/X86/avx-splat.ll103
-rw-r--r--test/CodeGen/X86/avx-unpack.ll89
-rw-r--r--test/CodeGen/X86/avx-vbroadcast.ll94
-rw-r--r--test/CodeGen/X86/avx-vextractf128.ll18
-rw-r--r--test/CodeGen/X86/avx-vinsertf128.ll58
-rw-r--r--test/CodeGen/X86/avx-vmovddup.ll14
-rw-r--r--test/CodeGen/X86/avx-vperm2f128.ll62
-rw-r--r--test/CodeGen/X86/avx-vpermil.ll45
-rw-r--r--test/CodeGen/X86/avx-vshufp.ll29
-rw-r--r--test/CodeGen/X86/avx-vzeroupper.ll26
-rw-r--r--test/CodeGen/X86/barrier-sse.ll18
-rw-r--r--test/CodeGen/X86/barrier.ll5
-rw-r--r--test/CodeGen/X86/bmi.ll53
-rw-r--r--test/CodeGen/X86/bswap.ll2
-rw-r--r--test/CodeGen/X86/change-compare-stride-0.ll5
-rw-r--r--test/CodeGen/X86/change-compare-stride-1.ll5
-rw-r--r--test/CodeGen/X86/cmov.ll4
-rw-r--r--test/CodeGen/X86/cmpxchg16b.ll13
-rw-r--r--test/CodeGen/X86/coalescer-dce.ll80
-rw-r--r--test/CodeGen/X86/coalescer-remat.ll12
-rw-r--r--test/CodeGen/X86/code_placement_eh.ll10
-rw-r--r--test/CodeGen/X86/crash-nosse.ll27
-rw-r--r--test/CodeGen/X86/crash.ll75
-rw-r--r--test/CodeGen/X86/dbg-at-specficiation.ll20
-rw-r--r--test/CodeGen/X86/dbg-inline.ll140
-rw-r--r--test/CodeGen/X86/dbg-large-unsigned-const.ll61
-rw-r--r--test/CodeGen/X86/dbg-value-isel.ll4
-rw-r--r--test/CodeGen/X86/extractelement-load.ll20
-rw-r--r--test/CodeGen/X86/fast-isel-atomic.ll6
-rw-r--r--test/CodeGen/X86/fast-isel-cmp-branch.ll4
-rw-r--r--test/CodeGen/X86/fast-isel-gep.ll30
-rw-r--r--test/CodeGen/X86/fast-isel-tls.ll18
-rw-r--r--test/CodeGen/X86/fast-isel-x86-64.ll25
-rw-r--r--test/CodeGen/X86/fp-stack-O0-crash.ll21
-rw-r--r--test/CodeGen/X86/global-sections.ll2
-rw-r--r--test/CodeGen/X86/haddsub.ll194
-rw-r--r--test/CodeGen/X86/hidden-vis.ll19
-rw-r--r--test/CodeGen/X86/inline-asm-fpstack.ll11
-rw-r--r--test/CodeGen/X86/iv-users-in-other-loops.ll6
-rw-r--r--test/CodeGen/X86/lfence.ll6
-rw-r--r--test/CodeGen/X86/licm-dominance.ll36
-rw-r--r--test/CodeGen/X86/licm-nested.ll2
-rw-r--r--test/CodeGen/X86/lock-inst-encoding.ll43
-rw-r--r--test/CodeGen/X86/loop-strength-reduce3.ll4
-rw-r--r--test/CodeGen/X86/lzcnt.ll38
-rw-r--r--test/CodeGen/X86/membarrier.ll9
-rw-r--r--test/CodeGen/X86/mfence.ll16
-rw-r--r--test/CodeGen/X86/movbe.ll36
-rw-r--r--test/CodeGen/X86/movgs.ll2
-rw-r--r--test/CodeGen/X86/movmsk.ll110
-rw-r--r--test/CodeGen/X86/nofence.ll27
-rw-r--r--test/CodeGen/X86/norex-subreg.ll80
-rw-r--r--test/CodeGen/X86/opt-shuff-tstore.ll39
-rw-r--r--test/CodeGen/X86/or-address.ll8
-rw-r--r--test/CodeGen/X86/palignr.ll31
-rw-r--r--test/CodeGen/X86/personality.ll10
-rw-r--r--test/CodeGen/X86/pr10420.ll21
-rw-r--r--test/CodeGen/X86/pr3495.ll8
-rw-r--r--test/CodeGen/X86/pr3522.ll4
-rw-r--r--test/CodeGen/X86/ptr-rotate.ll11
-rw-r--r--test/CodeGen/X86/scev-interchange.ll44
-rw-r--r--test/CodeGen/X86/segmented-stacks.ll87
-rw-r--r--test/CodeGen/X86/sfence.ll6
-rw-r--r--test/CodeGen/X86/sink-hoist.ll10
-rw-r--r--test/CodeGen/X86/split-eh-lpad-edges.ll4
-rw-r--r--test/CodeGen/X86/split-vector-bitcast.ll12
-rw-r--r--test/CodeGen/X86/sse-minmax.ll38
-rw-r--r--test/CodeGen/X86/sse2-blend.ll55
-rw-r--r--test/CodeGen/X86/sse41-blend.ll82
-rw-r--r--test/CodeGen/X86/sub.ll11
-rw-r--r--test/CodeGen/X86/tail-call-got.ll24
-rw-r--r--test/CodeGen/X86/tlv-1.ll17
-rw-r--r--test/CodeGen/X86/trunc-ext-ld-st.ll82
-rw-r--r--test/CodeGen/X86/twoaddr-sink-terminator.ll43
-rw-r--r--test/CodeGen/X86/uint64-to-float.ll33
-rw-r--r--test/CodeGen/X86/uint_to_fp-2.ll31
-rw-r--r--test/CodeGen/X86/v2f32.ll2
-rw-r--r--test/CodeGen/X86/vec_compare-sse4.ll35
-rw-r--r--test/CodeGen/X86/vec_set-C.ll6
-rw-r--r--test/CodeGen/X86/vec_shuffle-37.ll24
-rw-r--r--test/CodeGen/X86/vec_shuffle-38.ll59
-rw-r--r--test/CodeGen/X86/widen_shuffle-1.ll8
-rw-r--r--test/CodeGen/XCore/2011-08-01-DynamicAllocBug.ll20
-rw-r--r--test/CodeGen/XCore/2011-08-01-VarargsBug.ll17
-rw-r--r--test/CodeGen/XCore/licm-ldwcp.ll18
-rw-r--r--test/CodeGen/XCore/misc-intrinsics.ll48
-rw-r--r--test/CodeGen/XCore/resources.ll41
-rw-r--r--test/CodeGen/XCore/trampoline.ll6
-rw-r--r--test/DebugInfo/2009-01-15-member.ll30
-rw-r--r--test/DebugInfo/2009-10-08-DebugInfo-NullGlobalVariable.ll72
-rw-r--r--test/DebugInfo/2009-11-05-DeadGlobalVariable.ll29
-rw-r--r--test/DebugInfo/2009-11-06-InvalidDerivedType.ll13
-rw-r--r--test/DebugInfo/2009-11-06-NamelessGlobalVariable.ll15
-rw-r--r--test/DebugInfo/2009-11-10-CurrentFn.ll42
-rw-r--r--test/DebugInfo/2009-11-10-ParentScope.ll26
-rw-r--r--test/DebugInfo/2010-01-05-DbgScope.ll2
-rw-r--r--test/DebugInfo/2010-06-29-InlinedFnLocalVar.ll5
-rw-r--r--test/DebugInfo/2011-09-26-GlobalVarContext.ll47
-rw-r--r--test/ExecutionEngine/2003-01-04-ArgumentBug.ll1
-rw-r--r--test/ExecutionEngine/2003-01-04-LoopTest.ll1
-rw-r--r--test/ExecutionEngine/2003-01-15-AlignmentTest.ll1
-rw-r--r--test/ExecutionEngine/2003-05-06-LivenessClobber.ll1
-rw-r--r--test/ExecutionEngine/2003-05-07-ArgumentTest.ll1
-rw-r--r--test/ExecutionEngine/2003-08-15-AllocaAssertion.ll1
-rw-r--r--test/ExecutionEngine/2003-08-21-EnvironmentTest.ll1
-rw-r--r--test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll1
-rw-r--r--test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll1
-rw-r--r--test/ExecutionEngine/hello.ll1
-rw-r--r--test/ExecutionEngine/hello2.ll1
-rw-r--r--test/ExecutionEngine/simpletest.ll1
-rw-r--r--test/ExecutionEngine/stubs.ll1
-rw-r--r--test/ExecutionEngine/test-loadstore.ll1
-rw-r--r--test/Feature/callingconventions.ll31
-rw-r--r--test/Feature/calltest.ll30
-rw-r--r--test/Feature/exception.ll27
-rw-r--r--test/FrontendAda/Support/element_copy.ads8
-rw-r--r--test/FrontendAda/Support/fat_fields.ads6
-rw-r--r--test/FrontendAda/Support/global_constant.ads4
-rw-r--r--test/FrontendAda/Support/non_lvalue.ads11
-rw-r--r--test/FrontendAda/Support/real_cst.ads4
-rw-r--r--test/FrontendAda/Support/unc_constructor.ads8
-rw-r--r--test/FrontendAda/Support/var_offset.ads9
-rw-r--r--test/FrontendAda/Support/var_size.ads7
-rw-r--r--test/FrontendAda/array_constructor.adb6
-rw-r--r--test/FrontendAda/array_range_ref.adb7
-rw-r--r--test/FrontendAda/array_ref.adb11
-rw-r--r--test/FrontendAda/array_size.adb10
-rw-r--r--test/FrontendAda/asm.adb6
-rw-r--r--test/FrontendAda/constant_fold.ads4
-rw-r--r--test/FrontendAda/debug_var_size.ads8
-rw-r--r--test/FrontendAda/dg.exp6
-rw-r--r--test/FrontendAda/element_copy.adb8
-rw-r--r--test/FrontendAda/emit_var.ads5
-rw-r--r--test/FrontendAda/fat_fields.adb10
-rw-r--r--test/FrontendAda/field_order.ads7
-rw-r--r--test/FrontendAda/global_constant.adb5
-rw-r--r--test/FrontendAda/init_size.ads12
-rw-r--r--test/FrontendAda/negative_field_offset.adb16
-rw-r--r--test/FrontendAda/non_bitfield.ads12
-rw-r--r--test/FrontendAda/non_lvalue.adb7
-rw-r--r--test/FrontendAda/placeholder.adb12
-rw-r--r--test/FrontendAda/real_cst.adb8
-rw-r--r--test/FrontendAda/switch.adb12
-rw-r--r--test/FrontendAda/unc_constructor.adb9
-rw-r--r--test/FrontendAda/var_offset.adb7
-rw-r--r--test/FrontendAda/var_size.adb7
-rw-r--r--test/FrontendAda/vce.adb7
-rw-r--r--test/FrontendAda/vce_lv.adb9
-rw-r--r--test/FrontendC++/2003-11-02-WeakLinkage.cpp13
-rw-r--r--test/FrontendC++/2003-11-18-PtrMemConstantInitializer.cpp14
-rw-r--r--test/FrontendC++/2003-11-25-ReturningOpaqueByValue.cpp12
-rw-r--r--test/FrontendC++/2003-11-27-MultipleInheritanceThunk.cpp28
-rw-r--r--test/FrontendC++/2003-11-29-DuplicatedCleanupTest.cpp41
-rw-r--r--test/FrontendC++/2003-12-08-ArrayOfPtrToMemberFunc.cpp12
-rw-r--r--test/FrontendC++/2004-01-11-DynamicInitializedConstant.cpp6
-rw-r--r--test/FrontendC++/2004-03-08-ReinterpretCastCopy.cpp21
-rw-r--r--test/FrontendC++/2004-03-09-UnmangledBuiltinMethods.cpp8
-rw-r--r--test/FrontendC++/2004-03-15-CleanupsAndGotos.cpp14
-rw-r--r--test/FrontendC++/2004-06-08-LateTemplateInstantiation.cpp19
-rw-r--r--test/FrontendC++/2004-09-27-CompilerCrash.cpp13
-rw-r--r--test/FrontendC++/2004-09-27-DidntEmitTemplate.cpp23
-rw-r--r--test/FrontendC++/2004-11-27-EmitsUnusedInlineFunctions.cpp7
-rw-r--r--test/FrontendC++/2004-11-27-ExceptionCleanupAssertion.cpp14
-rw-r--r--test/FrontendC++/2004-11-27-FriendDefaultArgCrash.cpp9
-rw-r--r--test/FrontendC++/2004-11-27-InlineAsmFunctionRedefinition.cpp26
-rw-r--r--test/FrontendC++/2005-01-03-StaticInitializers.cpp8
-rw-r--r--test/FrontendC++/2005-02-11-AnonymousUnion.cpp32
-rw-r--r--test/FrontendC++/2005-02-13-BadDynamicInit.cpp9
-rw-r--r--test/FrontendC++/2005-02-14-BitFieldOffset.cpp11
-rw-r--r--test/FrontendC++/2005-02-19-BitfieldStructCrash.cpp14
-rw-r--r--test/FrontendC++/2005-02-19-UnnamedVirtualThunkArgument.cpp22
-rw-r--r--test/FrontendC++/2005-02-20-BrokenReferenceTest.cpp11
-rw-r--r--test/FrontendC++/2005-02-27-PlacementArrayNewCrash.cpp8
-rw-r--r--test/FrontendC++/2005-07-21-VirtualBaseAccess.cpp14
-rw-r--r--test/FrontendC++/2006-03-01-GimplifyCrash.cpp14
-rw-r--r--test/FrontendC++/2006-03-06-C++RecurseCrash.cpp24
-rw-r--r--test/FrontendC++/2006-09-08-powi.cpp7
-rw-r--r--test/FrontendC++/2006-09-12-OpaqueStructCrash.cpp28
-rw-r--r--test/FrontendC++/2006-09-27-Debug-Protection.cpp12
-rw-r--r--test/FrontendC++/2006-10-30-ClassBitfield.cpp16
-rw-r--r--test/FrontendC++/2006-11-06-StackTrace.cpp38
-rw-r--r--test/FrontendC++/2006-11-20-GlobalSymbols.cpp10
-rw-r--r--test/FrontendC++/2006-11-30-ConstantExprCrash.cpp27
-rw-r--r--test/FrontendC++/2006-11-30-Pubnames.cpp22
-rw-r--r--test/FrontendC++/2007-01-02-UnboundedArray.cpp14
-rw-r--r--test/FrontendC++/2007-01-06-ELF-Thunk-Sections.cpp49
-rw-r--r--test/FrontendC++/2007-01-06-PtrMethodInit.cpp75
-rw-r--r--test/FrontendC++/2007-03-27-FunctionVarRename.cpp17
-rw-r--r--test/FrontendC++/2007-04-05-PackedBitFields-1.cpp23
-rw-r--r--test/FrontendC++/2007-04-05-PackedBitFieldsOverlap-2.cpp24
-rw-r--r--test/FrontendC++/2007-04-05-PackedBitFieldsOverlap.cpp24
-rw-r--r--test/FrontendC++/2007-04-05-PackedBitFieldsSmall.cpp27
-rw-r--r--test/FrontendC++/2007-04-05-StructPackedFieldUnpacked.cpp25
-rw-r--r--test/FrontendC++/2007-04-10-PackedUnion.cpp41
-rw-r--r--test/FrontendC++/2007-04-11-InlineStorageClassC++.cpp44
-rw-r--r--test/FrontendC++/2007-04-14-FNoBuiltin.cpp7
-rw-r--r--test/FrontendC++/2007-04-31-TryCatch.cpp12
-rw-r--r--test/FrontendC++/2007-05-03-VectorInit.cpp17
-rw-r--r--test/FrontendC++/2007-05-16-ReverseBitFieldCrash.cpp24
-rw-r--r--test/FrontendC++/2007-05-23-TryFinally.cpp16
-rw-r--r--test/FrontendC++/2007-07-04-NestedCatches.cpp32
-rw-r--r--test/FrontendC++/2007-07-29-RestrictPtrArg.cpp6
-rw-r--r--test/FrontendC++/2007-07-29-RestrictRefArg.cpp6
-rw-r--r--test/FrontendC++/2007-08-01-RestrictMethod.cpp13
-rw-r--r--test/FrontendC++/2007-09-10-RecursiveTypeResolution.cpp88
-rw-r--r--test/FrontendC++/2007-10-01-StructResize.cpp14
-rw-r--r--test/FrontendC++/2008-01-11-BadWarning.cpp6
-rw-r--r--test/FrontendC++/2008-01-12-VecInit.cpp6
-rw-r--r--test/FrontendC++/2008-05-07-CrazyOffsetOf.cpp8
-rw-r--r--test/FrontendC++/2008-10-29-WrongOffset.cpp489
-rw-r--r--test/FrontendC++/2009-02-07-VolatileArrayRefHack.cpp7
-rw-r--r--test/FrontendC++/2009-02-16-CtorNames-dbg.cpp10
-rw-r--r--test/FrontendC++/2009-03-17-dbg.cpp16
-rw-r--r--test/FrontendC++/2009-04-21-DtorNames-dbg.cpp32
-rw-r--r--test/FrontendC++/2009-04-23-bool2.cpp15
-rw-r--r--test/FrontendC++/2009-05-04-PureConstNounwind.cpp8
-rw-r--r--test/FrontendC++/2009-06-16-DebugInfoCrash.cpp10
-rw-r--r--test/FrontendC++/2009-06-20-DarwinPPCLayout.cpp32
-rw-r--r--test/FrontendC++/2009-06-30-ByrefBlock.cpp11
-rw-r--r--test/FrontendC++/2009-07-16-PrivateCopyConstructor.cpp15
-rw-r--r--test/FrontendC++/2009-07-16-Using.cpp8
-rw-r--r--test/FrontendC++/2009-08-05-ZeroInitWidth.cpp12
-rw-r--r--test/FrontendC++/2009-08-11-VectorRetTy.cpp13
-rw-r--r--test/FrontendC++/2009-09-04-modify-crash.cpp7
-rw-r--r--test/FrontendC++/2009-09-09-packed-layout.cpp18
-rw-r--r--test/FrontendC++/2009-10-27-crash.cpp43
-rw-r--r--test/FrontendC++/2009-12-23-MissingSext.cpp16
-rw-r--r--test/FrontendC++/2010-02-17-DbgArtificialArg.cpp16
-rw-r--r--test/FrontendC++/2010-03-22-empty-baseclass.cpp134
-rw-r--r--test/FrontendC++/2010-04-30-OptimizedMethod-Dbg.cpp18
-rw-r--r--test/FrontendC++/2010-05-10-Var-DbgInfo.cpp43
-rw-r--r--test/FrontendC++/2010-05-11-alwaysinlineinstantiation.cpp31
-rw-r--r--test/FrontendC++/2010-05-12-PtrToMember-Dbg.cpp17
-rw-r--r--test/FrontendC++/2010-06-21-LocalVarDbg.cpp13
-rw-r--r--test/FrontendC++/2010-06-22-BitfieldInit.cpp20
-rw-r--r--test/FrontendC++/2010-06-22-ZeroBitfield.cpp5
-rw-r--r--test/FrontendC++/2010-07-19-nowarn.cpp21
-rw-r--r--test/FrontendC++/2010-07-23-DeclLoc.cpp86
-rw-r--r--test/FrontendC++/2010-08-31-ByValArg.cpp53
-rw-r--r--test/FrontendC++/alignstack.cpp23
-rw-r--r--test/FrontendC++/dg.exp5
-rw-r--r--test/FrontendC++/integration-O2.cpp19
-rw-r--r--test/FrontendC++/m64-ptr.cpp19
-rw-r--r--test/FrontendC++/member-alignment.cpp20
-rw-r--r--test/FrontendC++/ptr-to-method-devirt.cpp14
-rw-r--r--test/FrontendC++/thunk-linkonce-odr.cpp33
-rw-r--r--test/FrontendC++/varargs.cpp19
-rw-r--r--test/FrontendC++/weak-external.cpp17
-rw-r--r--test/FrontendC++/x86-64-abi-sret-vs-2word-struct-param.cpp27
-rw-r--r--test/FrontendC/2002-01-23-LoadQISIReloadFailure.c11
-rw-r--r--test/FrontendC/2002-01-24-ComplexSpaceInType.c11
-rw-r--r--test/FrontendC/2002-01-24-HandleCallInsnSEGV.c9
-rw-r--r--test/FrontendC/2002-02-13-ConditionalInCall.c11
-rw-r--r--test/FrontendC/2002-02-13-ReloadProblem.c18
-rw-r--r--test/FrontendC/2002-02-13-TypeVarNameCollision.c16
-rw-r--r--test/FrontendC/2002-02-13-UnnamedLocal.c21
-rw-r--r--test/FrontendC/2002-02-14-EntryNodePreds.c37
-rw-r--r--test/FrontendC/2002-02-16-RenamingTest.c18
-rw-r--r--test/FrontendC/2002-02-17-ArgumentAddress.c39
-rw-r--r--test/FrontendC/2002-02-18-64bitConstant.c10
-rw-r--r--test/FrontendC/2002-02-18-StaticData.c13
-rw-r--r--test/FrontendC/2002-03-11-LargeCharInString.c10
-rw-r--r--test/FrontendC/2002-03-12-ArrayInitialization.c19
-rw-r--r--test/FrontendC/2002-03-12-StructInitialize.c14
-rw-r--r--test/FrontendC/2002-03-12-StructInitializer.c18
-rw-r--r--test/FrontendC/2002-03-14-BrokenPHINode.c19
-rw-r--r--test/FrontendC/2002-03-14-BrokenSSA.c17
-rw-r--r--test/FrontendC/2002-03-14-QuotesInStrConst.c10
-rw-r--r--test/FrontendC/2002-04-07-SwitchStmt.c22
-rw-r--r--test/FrontendC/2002-04-08-LocalArray.c14
-rw-r--r--test/FrontendC/2002-04-09-StructRetVal.c12
-rw-r--r--test/FrontendC/2002-04-10-StructParameters.c25
-rw-r--r--test/FrontendC/2002-05-23-StaticValues.c15
-rw-r--r--test/FrontendC/2002-05-23-TypeNameCollision.c19
-rw-r--r--test/FrontendC/2002-05-24-Alloca.c11
-rw-r--r--test/FrontendC/2002-06-25-FWriteInterfaceFailure.c7
-rw-r--r--test/FrontendC/2002-07-14-MiscListTests.c71
-rw-r--r--test/FrontendC/2002-07-14-MiscTests.c57
-rw-r--r--test/FrontendC/2002-07-14-MiscTests2.c13
-rw-r--r--test/FrontendC/2002-07-14-MiscTests3.c187
-rw-r--r--test/FrontendC/2002-07-16-HardStringInit.c8
-rw-r--r--test/FrontendC/2002-07-17-StringConstant.c4
-rw-r--r--test/FrontendC/2002-07-29-Casts.c86
-rw-r--r--test/FrontendC/2002-07-30-SubregSetAssertion.c12
-rw-r--r--test/FrontendC/2002-07-30-UnionTest.c22
-rw-r--r--test/FrontendC/2002-07-30-VarArgsCallFailure.c8
-rw-r--r--test/FrontendC/2002-07-31-BadAssert.c16
-rw-r--r--test/FrontendC/2002-07-31-SubregFailure.c14
-rw-r--r--test/FrontendC/2002-08-02-UnionTest.c19
-rw-r--r--test/FrontendC/2002-08-19-RecursiveLocals.c18
-rw-r--r--test/FrontendC/2002-09-08-PointerShifts.c6
-rw-r--r--test/FrontendC/2002-09-18-UnionProblem.c26
-rw-r--r--test/FrontendC/2002-09-19-StarInLabel.c9
-rw-r--r--test/FrontendC/2002-10-12-TooManyArguments.c8
-rw-r--r--test/FrontendC/2002-12-15-GlobalBoolTest.c5
-rw-r--r--test/FrontendC/2002-12-15-GlobalConstantTest.c8
-rw-r--r--test/FrontendC/2002-12-15-GlobalRedefinition.c5
-rw-r--r--test/FrontendC/2002-12-15-StructParameters.c18
-rw-r--r--test/FrontendC/2003-01-30-UnionInit.c8
-rw-r--r--test/FrontendC/2003-03-03-DeferredType.c12
-rw-r--r--test/FrontendC/2003-06-22-UnionCrash.c13
-rw-r--r--test/FrontendC/2003-06-23-GCC-fold-infinite-recursion.c6
-rw-r--r--test/FrontendC/2003-06-26-CFECrash.c19
-rw-r--r--test/FrontendC/2003-06-29-MultipleFunctionDefinition.c8
-rw-r--r--test/FrontendC/2003-07-22-ArrayAccessTypeSafety.c7
-rw-r--r--test/FrontendC/2003-08-06-BuiltinSetjmpLongjmp.c14
-rw-r--r--test/FrontendC/2003-08-17-DeadCodeShortCircuit.c7
-rw-r--r--test/FrontendC/2003-08-18-SigSetJmp.c10
-rw-r--r--test/FrontendC/2003-08-18-StructAsValue.c11
-rw-r--r--test/FrontendC/2003-08-20-BadBitfieldRef.c8
-rw-r--r--test/FrontendC/2003-08-20-PrototypeMismatch.c15
-rw-r--r--test/FrontendC/2003-08-20-vfork-bug.c6
-rw-r--r--test/FrontendC/2003-08-21-BinOp-Type-Mismatch.c10
-rw-r--r--test/FrontendC/2003-08-21-StmtExpr.c12
-rw-r--r--test/FrontendC/2003-08-21-WideString.c7
-rw-r--r--test/FrontendC/2003-08-23-LocalUnionTest.c11
-rw-r--r--test/FrontendC/2003-08-29-BitFieldStruct.c13
-rw-r--r--test/FrontendC/2003-08-29-HugeCharConst.c5
-rw-r--r--test/FrontendC/2003-08-29-StructLayoutBug.c10
-rw-r--r--test/FrontendC/2003-08-30-AggregateInitializer.c16
-rw-r--r--test/FrontendC/2003-08-30-LargeIntegerBitfieldMember.c9
-rw-r--r--test/FrontendC/2003-09-18-BitfieldTests.c30
-rw-r--r--test/FrontendC/2003-09-30-StructLayout.c18
-rw-r--r--test/FrontendC/2003-10-02-UnionLValueError.c13
-rw-r--r--test/FrontendC/2003-10-06-NegateExprType.c8
-rw-r--r--test/FrontendC/2003-10-09-UnionInitializerBug.c17
-rw-r--r--test/FrontendC/2003-10-28-ident.c4
-rw-r--r--test/FrontendC/2003-10-29-AsmRename.c22
-rw-r--r--test/FrontendC/2003-11-01-C99-CompoundLiteral.c8
-rw-r--r--test/FrontendC/2003-11-01-EmptyStructCrash.c6
-rw-r--r--test/FrontendC/2003-11-01-GlobalUnionInit.c7
-rw-r--r--test/FrontendC/2003-11-03-AddrArrayElement.c11
-rw-r--r--test/FrontendC/2003-11-04-EmptyStruct.c6
-rw-r--r--test/FrontendC/2003-11-04-OutOfMemory.c9
-rw-r--r--test/FrontendC/2003-11-08-PointerSubNotGetelementptr.c9
-rw-r--r--test/FrontendC/2003-11-12-VoidString.c4
-rw-r--r--test/FrontendC/2003-11-13-TypeSafety.c5
-rw-r--r--test/FrontendC/2003-11-16-StaticArrayInit.c8
-rw-r--r--test/FrontendC/2003-11-18-CondExprLValue.c9
-rw-r--r--test/FrontendC/2003-11-19-AddressOfRegister.c12
-rw-r--r--test/FrontendC/2003-11-19-BitFieldArray.c12
-rw-r--r--test/FrontendC/2003-11-20-Bitfields.c12
-rw-r--r--test/FrontendC/2003-11-20-ComplexDivision.c7
-rw-r--r--test/FrontendC/2003-11-20-UnionBitfield.c12
-rw-r--r--test/FrontendC/2003-11-26-PointerShift.c6
-rw-r--r--test/FrontendC/2003-11-27-ConstructorCast.c14
-rw-r--r--test/FrontendC/2003-11-27-UnionCtorInitialization.c16
-rw-r--r--test/FrontendC/2003-12-14-ExternInlineSupport.c3
-rw-r--r--test/FrontendC/2004-01-01-UnknownInitSize.c14
-rw-r--r--test/FrontendC/2004-01-08-ExternInlineRedefine.c14
-rw-r--r--test/FrontendC/2004-02-12-LargeAggregateCopy.c8
-rw-r--r--test/FrontendC/2004-02-13-BuiltinFrameReturnAddress.c8
-rw-r--r--test/FrontendC/2004-02-13-IllegalVararg.c13
-rw-r--r--test/FrontendC/2004-02-13-Memset.c9
-rw-r--r--test/FrontendC/2004-02-14-ZeroInitializer.c4
-rw-r--r--test/FrontendC/2004-02-20-Builtins.c8
-rw-r--r--test/FrontendC/2004-03-07-ComplexDivEquals.c6
-rw-r--r--test/FrontendC/2004-03-07-ExternalConstant.c7
-rw-r--r--test/FrontendC/2004-03-09-LargeArrayInitializers.c32
-rw-r--r--test/FrontendC/2004-03-15-SimpleIndirectGoto.c23
-rw-r--r--test/FrontendC/2004-03-16-AsmRegisterCrash.c10
-rw-r--r--test/FrontendC/2004-05-07-VarArrays.c5
-rw-r--r--test/FrontendC/2004-05-21-IncompleteEnum.c5
-rw-r--r--test/FrontendC/2004-06-08-OpaqueStructArg.c7
-rw-r--r--test/FrontendC/2004-06-17-UnorderedBuiltins.c24
-rw-r--r--test/FrontendC/2004-06-17-UnorderedCompares.c21
-rw-r--r--test/FrontendC/2004-06-18-VariableLengthArrayOfStructures.c10
-rw-r--r--test/FrontendC/2004-07-06-FunctionCast.c10
-rw-r--r--test/FrontendC/2004-08-06-LargeStructTest.c19
-rw-r--r--test/FrontendC/2004-11-25-UnnamedBitfieldPadding.c8
-rw-r--r--test/FrontendC/2004-11-27-InvalidConstantExpr.c10
-rw-r--r--test/FrontendC/2004-11-27-StaticFunctionRedeclare.c15
-rw-r--r--test/FrontendC/2004-11-27-VariableSizeInStructure.c11
-rw-r--r--test/FrontendC/2005-01-02-ConstantInits.c24
-rw-r--r--test/FrontendC/2005-01-02-PointerDifference.c3
-rw-r--r--test/FrontendC/2005-01-02-VAArgError-ICE.c10
-rw-r--r--test/FrontendC/2005-02-20-AggregateSAVEEXPR.c19
-rw-r--r--test/FrontendC/2005-02-27-MarkGlobalConstant.c10
-rw-r--r--test/FrontendC/2005-03-05-OffsetOfHack.c12
-rw-r--r--test/FrontendC/2005-03-06-OffsetOfStructCrash.c14
-rw-r--r--test/FrontendC/2005-03-11-Prefetch.c6
-rw-r--r--test/FrontendC/2005-04-09-ComplexOps.c9
-rw-r--r--test/FrontendC/2005-05-06-CountBuiltins.c17
-rw-r--r--test/FrontendC/2005-05-10-GlobalUnionInit.c6
-rw-r--r--test/FrontendC/2005-06-15-ExpandGotoInternalProblem.c14
-rw-r--r--test/FrontendC/2005-07-20-SqrtNoErrno.c11
-rw-r--r--test/FrontendC/2005-07-26-UnionInitCrash.c3
-rw-r--r--test/FrontendC/2005-07-28-IncorrectWeakGlobal.c5
-rw-r--r--test/FrontendC/2005-09-20-ComplexConstants.c4
-rw-r--r--test/FrontendC/2005-09-24-AsmUserPrefix.c8
-rw-r--r--test/FrontendC/2005-09-24-BitFieldCrash.c33
-rw-r--r--test/FrontendC/2005-10-18-VariableSizedElementCrash.c9
-rw-r--r--test/FrontendC/2005-12-04-AttributeUsed.c8
-rw-r--r--test/FrontendC/2005-12-04-DeclarationLineNumbers.c23
-rw-r--r--test/FrontendC/2006-01-13-Includes.c8
-rw-r--r--test/FrontendC/2006-01-13-StackSave.c11
-rw-r--r--test/FrontendC/2006-01-16-BitCountIntrinsicsUnsigned.c9
-rw-r--r--test/FrontendC/2006-01-23-FileScopeAsm.c8
-rw-r--r--test/FrontendC/2006-03-03-MissingInitializer.c11
-rw-r--r--test/FrontendC/2006-03-16-VectorCtor.c10
-rw-r--r--test/FrontendC/2006-03-17-KnRMismatch.c8
-rw-r--r--test/FrontendC/2006-05-01-AppleAlignmentPragma.c12
-rw-r--r--test/FrontendC/2006-05-19-SingleEltReturn.c23
-rw-r--r--test/FrontendC/2006-07-31-PR854.c11
-rw-r--r--test/FrontendC/2006-09-11-BitfieldRefCrash.c12
-rw-r--r--test/FrontendC/2006-09-18-fwrite-cast-crash.c15
-rw-r--r--test/FrontendC/2006-09-21-IncompleteElementType.c3
-rw-r--r--test/FrontendC/2006-09-25-DebugFilename.c6
-rw-r--r--test/FrontendC/2006-09-25-DebugFilename.h6
-rw-r--r--test/FrontendC/2006-09-28-SimpleAsm.c10
-rw-r--r--test/FrontendC/2006-10-30-ArrayCrash.c17
-rw-r--r--test/FrontendC/2006-12-14-ordered_expr.c6
-rw-r--r--test/FrontendC/2007-01-06-KNR-Proto.c10
-rw-r--r--test/FrontendC/2007-01-20-VectorICE.c11
-rw-r--r--test/FrontendC/2007-01-24-InlineAsmCModifier.c10
-rw-r--r--test/FrontendC/2007-02-04-AddrLValue-2.c13
-rw-r--r--test/FrontendC/2007-02-04-AddrLValue.c23
-rw-r--r--test/FrontendC/2007-02-04-EmptyStruct.c9
-rw-r--r--test/FrontendC/2007-02-04-WITH_SIZE_EXPR.c21
-rw-r--r--test/FrontendC/2007-02-05-nested.c54
-rw-r--r--test/FrontendC/2007-02-07-AddrLabel.c10
-rw-r--r--test/FrontendC/2007-02-16-VariableSizeStructArg.c7
-rw-r--r--test/FrontendC/2007-02-16-VoidPtrDiff.c5
-rw-r--r--test/FrontendC/2007-02-16-WritableStrings.c7
-rw-r--r--test/FrontendC/2007-02-25-C-DotDotDot.c12
-rw-r--r--test/FrontendC/2007-03-01-VarSizeArrayIdx.c7
-rw-r--r--test/FrontendC/2007-03-05-DataLayout.c53
-rw-r--r--test/FrontendC/2007-03-06-VarSizeInStruct1.c8
-rw-r--r--test/FrontendC/2007-03-06-VarSizeInStruct2.c8
-rw-r--r--test/FrontendC/2007-03-26-BitfieldAfterZeroWidth.c6
-rw-r--r--test/FrontendC/2007-03-26-ZeroWidthBitfield.c2
-rw-r--r--test/FrontendC/2007-03-27-ArrayCompatible.c10
-rw-r--r--test/FrontendC/2007-03-27-VarLengthArray.c7
-rw-r--r--test/FrontendC/2007-04-05-PackedBitFields-2.c16
-rw-r--r--test/FrontendC/2007-04-05-PackedBitFields.c16
-rw-r--r--test/FrontendC/2007-04-05-PackedStruct.c18
-rw-r--r--test/FrontendC/2007-04-05-PadBeforeZeroLengthField.c9
-rw-r--r--test/FrontendC/2007-04-05-UnPackedStruct.c16
-rw-r--r--test/FrontendC/2007-04-11-InlineAsmStruct.c9
-rw-r--r--test/FrontendC/2007-04-11-InlineAsmUnion.c7
-rw-r--r--test/FrontendC/2007-04-11-InlineStorageClassC89.c46
-rw-r--r--test/FrontendC/2007-04-11-InlineStorageClassC99.c46
-rw-r--r--test/FrontendC/2007-04-11-PR1321.c12
-rw-r--r--test/FrontendC/2007-04-13-InlineAsmStruct2.c9
-rw-r--r--test/FrontendC/2007-04-13-InlineAsmUnion2.c7
-rw-r--r--test/FrontendC/2007-04-14-FNoBuiltin.c7
-rw-r--r--test/FrontendC/2007-04-17-ZeroSizeBitFields.c4
-rw-r--r--test/FrontendC/2007-04-24-VolatileStructCopy.c10
-rw-r--r--test/FrontendC/2007-04-24-bit-not-expr.c7
-rw-r--r--test/FrontendC/2007-04-24-str-const.c17
-rw-r--r--test/FrontendC/2007-05-07-NestedStructReturn.c13
-rw-r--r--test/FrontendC/2007-05-07-PaddingElements.c12
-rw-r--r--test/FrontendC/2007-05-08-PCH.c7
-rw-r--r--test/FrontendC/2007-05-11-str-const.c5
-rw-r--r--test/FrontendC/2007-05-15-PaddingElement.c23
-rw-r--r--test/FrontendC/2007-05-16-EmptyStruct.c5
-rw-r--r--test/FrontendC/2007-05-29-UnionCopy.c18
-rw-r--r--test/FrontendC/2007-06-05-NoInlineAttribute.c13
-rw-r--r--test/FrontendC/2007-06-15-AnnotateAttribute.c24
-rw-r--r--test/FrontendC/2007-06-18-SextAttrAggregate.c11
-rw-r--r--test/FrontendC/2007-07-29-RestrictPtrArg.c6
-rw-r--r--test/FrontendC/2007-08-01-LoadStoreAlign.c17
-rw-r--r--test/FrontendC/2007-08-21-ComplexCst.c3
-rw-r--r--test/FrontendC/2007-08-22-CTTZ.c6
-rw-r--r--test/FrontendC/2007-09-05-ConstCtor.c14
-rw-r--r--test/FrontendC/2007-09-12-PragmaPack.c30
-rw-r--r--test/FrontendC/2007-09-14-NegatePointer.c7
-rw-r--r--test/FrontendC/2007-09-17-WeakRef.c10
-rw-r--r--test/FrontendC/2007-09-20-GcrootAttribute.c29
-rw-r--r--test/FrontendC/2007-09-26-Alignment.c7
-rw-r--r--test/FrontendC/2007-09-27-ComplexIntCompare.c17
-rw-r--r--test/FrontendC/2007-09-28-PackedUnionMember.c38
-rw-r--r--test/FrontendC/2007-10-01-BuildArrayRef.c20
-rw-r--r--test/FrontendC/2007-10-02-VolatileArray.c7
-rw-r--r--test/FrontendC/2007-10-15-VoidPtr.c4
-rw-r--r--test/FrontendC/2007-10-30-Volatile.c6
-rw-r--r--test/FrontendC/2007-11-07-AlignedMemcpy.c4
-rw-r--r--test/FrontendC/2007-11-07-CopyAggregateAlign.c3
-rw-r--r--test/FrontendC/2007-11-07-ZeroAggregateAlign.c3
-rw-r--r--test/FrontendC/2007-11-27-SExtZExt.c12
-rw-r--r--test/FrontendC/2007-11-28-GlobalInitializer.c8
-rw-r--r--test/FrontendC/2007-12-16-AsmNoUnwind.c3
-rw-r--r--test/FrontendC/2007-12-VarArrayDebug.c18
-rw-r--r--test/FrontendC/2008-01-04-WideBitfield.c13
-rw-r--r--test/FrontendC/2008-01-07-UnusualIntSize.c11
-rw-r--r--test/FrontendC/2008-01-11-ChainConsistency.c3
-rw-r--r--test/FrontendC/2008-01-21-PackedBitFields.c7
-rw-r--r--test/FrontendC/2008-01-21-PackedStructField.c18
-rw-r--r--test/FrontendC/2008-01-24-StructAlignAndBitFields.c4
-rw-r--r--test/FrontendC/2008-01-25-ByValReadNone.c15
-rw-r--r--test/FrontendC/2008-01-25-ZeroSizedAggregate.c39
-rw-r--r--test/FrontendC/2008-01-28-PragmaMark.c6
-rw-r--r--test/FrontendC/2008-01-28-UnionSize.c24
-rw-r--r--test/FrontendC/2008-02-11-AnnotateBuiltin.c7
-rw-r--r--test/FrontendC/2008-03-03-CtorAttrType.c6
-rw-r--r--test/FrontendC/2008-03-05-syncPtr.c27
-rw-r--r--test/FrontendC/2008-03-24-BitField-And-Alloca.c89
-rw-r--r--test/FrontendC/2008-03-26-PackedBitFields.c7
-rw-r--r--test/FrontendC/2008-04-08-NoExceptions.c7
-rw-r--r--test/FrontendC/2008-05-06-CFECrash.c4
-rw-r--r--test/FrontendC/2008-05-12-TempUsedBeforeDef.c10
-rw-r--r--test/FrontendC/2008-05-19-AlwaysInline.c12
-rw-r--r--test/FrontendC/2008-07-08-FAbsAttributes.c4
-rw-r--r--test/FrontendC/2008-08-07-AlignPadding1.c29
-rw-r--r--test/FrontendC/2008-08-07-AlignPadding2.c18
-rw-r--r--test/FrontendC/2008-08-07-GEPIntToPtr.c14
-rw-r--r--test/FrontendC/2008-09-03-WeakAlias.c9
-rw-r--r--test/FrontendC/2008-10-13-FrontendCrash.c9
-rw-r--r--test/FrontendC/2008-10-30-ZeroPlacement.c9
-rw-r--r--test/FrontendC/2008-11-02-WeakAlias.c5
-rw-r--r--test/FrontendC/2008-11-08-InstCombineSelect.c17
-rw-r--r--test/FrontendC/2008-11-11-AnnotateStructFieldAttribute.c18
-rw-r--r--test/FrontendC/2008-12-23-AsmIntPointerTie.c9
-rw-r--r--test/FrontendC/2009-01-05-BlockInlining.c28
-rw-r--r--test/FrontendC/2009-01-20-k8.c4
-rw-r--r--test/FrontendC/2009-01-21-InvalidIterator.c74
-rw-r--r--test/FrontendC/2009-02-13-zerosize-union-field-ppc.c14
-rw-r--r--test/FrontendC/2009-02-13-zerosize-union-field.c14
-rw-r--r--test/FrontendC/2009-02-17-BitField-dbg.c14
-rw-r--r--test/FrontendC/2009-03-01-MallocNoAlias.c3
-rw-r--r--test/FrontendC/2009-03-08-ZeroEltStructCrash.c14
-rw-r--r--test/FrontendC/2009-03-09-WeakDeclarations-1.c22
-rw-r--r--test/FrontendC/2009-03-13-dbg.c5
-rw-r--r--test/FrontendC/2009-04-22-UnknownSize.c4
-rw-r--r--test/FrontendC/2009-04-28-UnionArrayCrash.c11
-rw-r--r--test/FrontendC/2009-05-04-EnumInreg.c18
-rw-r--r--test/FrontendC/2009-05-17-AlwaysInline.c17
-rw-r--r--test/FrontendC/2009-06-14-HighlyAligned.c8
-rw-r--r--test/FrontendC/2009-06-18-StaticInitTailPadPack.c26
-rw-r--r--test/FrontendC/2009-07-14-VoidPtr.c6
-rw-r--r--test/FrontendC/2009-07-15-pad-wchar_t-array.c7
-rw-r--r--test/FrontendC/2009-07-17-VoidParameter.c4
-rw-r--r--test/FrontendC/2009-07-22-StructLayout.c34
-rw-r--r--test/FrontendC/2009-08-11-AsmBlocksComplexJumpTarget.c10
-rw-r--r--test/FrontendC/2009-09-24-SqrtErrno.c12
-rw-r--r--test/FrontendC/2009-12-07-BitFieldAlignment.c15
-rw-r--r--test/FrontendC/2010-01-05-LinkageName.c15
-rw-r--r--test/FrontendC/2010-01-13-MemBarrier.c11
-rw-r--r--test/FrontendC/2010-01-14-FnType-DebugInfo.c4
-rw-r--r--test/FrontendC/2010-01-14-StaticVariable.c12
-rw-r--r--test/FrontendC/2010-01-18-Inlined-Debug.c12
-rw-r--r--test/FrontendC/2010-02-10-PointerName.c7
-rw-r--r--test/FrontendC/2010-02-15-DbgStaticVar.c13
-rw-r--r--test/FrontendC/2010-02-16-DbgVarScope.c30
-rw-r--r--test/FrontendC/2010-02-18-Dbg-VectorType.c9
-rw-r--r--test/FrontendC/2010-03-10-arm-asmreg.c15
-rw-r--r--test/FrontendC/2010-03-5-LexicalScope.c10
-rw-r--r--test/FrontendC/2010-05-14-Optimized-VarType.c23
-rw-r--r--test/FrontendC/2010-05-18-asmsched.c18
-rw-r--r--test/FrontendC/2010-05-18-palignr.c24
-rw-r--r--test/FrontendC/2010-05-26-AsmSideEffect.c12
-rw-r--r--test/FrontendC/2010-05-31-palignr.c24
-rw-r--r--test/FrontendC/2010-06-11-SaveExpr.c8
-rw-r--r--test/FrontendC/2010-06-17-asmcrash.c16
-rw-r--r--test/FrontendC/2010-06-28-DbgLocalVar.c14
-rw-r--r--test/FrontendC/2010-06-28-nowarn.c21
-rw-r--r--test/FrontendC/2010-07-08-DeclDebugLineNo.c10
-rw-r--r--test/FrontendC/2010-07-14-overconservative-align.c14
-rw-r--r--test/FrontendC/2010-07-14-ref-off-end.c27
-rw-r--r--test/FrontendC/2010-07-27-MinNoFoldConst.c18
-rw-r--r--test/FrontendC/2010-08-12-asm-aggr-arg.c16
-rw-r--r--test/FrontendC/2010-11-16-asmblock.c16
-rw-r--r--test/FrontendC/2010-12-01-CommonGlobal.c7
-rw-r--r--test/FrontendC/2011-02-21-DATA-common.c5
-rw-r--r--test/FrontendC/2011-03-02-UnionInitializer.c2
-rw-r--r--test/FrontendC/2011-03-08-ZeroFieldUnionInitializer.c7
-rw-r--r--test/FrontendC/2011-03-31-ArrayRefFolding.c15
-rw-r--r--test/FrontendC/ARM/dg.exp5
-rw-r--r--test/FrontendC/ARM/inline-asm-multichar.c11
-rw-r--r--test/FrontendC/Atomics-no64bit.c190
-rw-r--r--test/FrontendC/Atomics.c236
-rw-r--r--test/FrontendC/BasicInstrs.c26
-rw-r--r--test/FrontendC/alignstack.c23
-rw-r--r--test/FrontendC/always-inline.c12
-rw-r--r--test/FrontendC/arrayderef.c17
-rw-r--r--test/FrontendC/asm-reg-var-local.c32
-rw-r--r--test/FrontendC/attribute_constructor.c6
-rw-r--r--test/FrontendC/block-copy.c20
-rw-r--r--test/FrontendC/crash-invalid-array.c17
-rw-r--r--test/FrontendC/dg.exp5
-rw-r--r--test/FrontendC/exact-div-expr.c6
-rw-r--r--test/FrontendC/extern-weak.c12
-rw-r--r--test/FrontendC/fp-logical.c15
-rw-r--r--test/FrontendC/func-aligned.c7
-rw-r--r--test/FrontendC/funccall.c17
-rw-r--r--test/FrontendC/hidden-visibility.c3
-rw-r--r--test/FrontendC/implicit-arg.c10
-rw-r--r--test/FrontendC/inline-asm-function.c6
-rw-r--r--test/FrontendC/inline-asm-mrv.c12
-rw-r--r--test/FrontendC/libcalls-d.c14
-rw-r--r--test/FrontendC/libcalls-ld.c17
-rw-r--r--test/FrontendC/libcalls.c14
-rw-r--r--test/FrontendC/misaligned-param.c15
-rw-r--r--test/FrontendC/mmx-inline-asm.c24
-rw-r--r--test/FrontendC/nested-functions.c18
-rw-r--r--test/FrontendC/pr2394.c6
-rw-r--r--test/FrontendC/pr3518.c24
-rw-r--r--test/FrontendC/pr4349.c38
-rw-r--r--test/FrontendC/pr5406.c20
-rw-r--r--test/FrontendC/ptr-rotate.c7
-rw-r--r--test/FrontendC/redef-ext-inline.c6
-rw-r--r--test/FrontendC/sret.c15
-rw-r--r--test/FrontendC/sret2.c9
-rw-r--r--test/FrontendC/struct-matching-constraint.c19
-rw-r--r--test/FrontendC/unaligned-memcpy.c5
-rw-r--r--test/FrontendC/union-align.c17
-rw-r--r--test/FrontendC/vla-1.c9
-rw-r--r--test/FrontendC/vla-2.c10
-rw-r--r--test/FrontendC/vla-3.c11
-rw-r--r--test/FrontendC/wchar-const.c9
-rw-r--r--test/FrontendC/weak_constant.c12
-rw-r--r--test/FrontendFortran/2008-11-03-OptionOverride.f904
-rw-r--r--test/FrontendFortran/2009-02-09-FloorDivExpr.f9032
-rw-r--r--test/FrontendFortran/cpow.f9018
-rw-r--r--test/FrontendFortran/dg.exp6
-rw-r--r--test/FrontendObjC++/2007-10-03-MetadataPointers.mm7
-rw-r--r--test/FrontendObjC++/2010-08-02-NonPODObjectValue.mm27
-rw-r--r--test/FrontendObjC++/2010-08-04-Template.mm10
-rw-r--r--test/FrontendObjC++/2010-08-06-X.Y-syntax.mm16
-rw-r--r--test/FrontendObjC++/dg.exp5
-rw-r--r--test/FrontendObjC/2007-04-03-ObjcEH.m29
-rw-r--r--test/FrontendObjC/2007-05-02-Strong.m23
-rw-r--r--test/FrontendObjC/2007-09-25-EH.m27
-rw-r--r--test/FrontendObjC/2007-10-17-SJLJExceptions.m24
-rw-r--r--test/FrontendObjC/2007-10-18-ProDescriptor.m19
-rw-r--r--test/FrontendObjC/2007-10-23-GC-WriteBarrier.m9
-rw-r--r--test/FrontendObjC/2008-10-3-EhValue.m50
-rw-r--r--test/FrontendObjC/2008-11-12-Metadata.m14
-rw-r--r--test/FrontendObjC/2008-11-24-ConstCFStrings.m11
-rw-r--r--test/FrontendObjC/2008-11-25-Blocks.m17
-rw-r--r--test/FrontendObjC/2009-01-26-WriteBarrier-2.m14
-rw-r--r--test/FrontendObjC/2009-02-05-VolatileProp.m11
-rw-r--r--test/FrontendObjC/2009-04-14-AsmSection.m9
-rw-r--r--test/FrontendObjC/2009-04-27-bitfield-vs-ivar.m44
-rw-r--r--test/FrontendObjC/2009-04-28-bitfield-vs-vbc.m127
-rw-r--r--test/FrontendObjC/2009-08-05-utf16.m5
-rw-r--r--test/FrontendObjC/2009-08-17-DebugInfo.m28
-rw-r--r--test/FrontendObjC/2009-11-30-Objc-ID.m14
-rw-r--r--test/FrontendObjC/2010-02-01-utf16-with-null.m5
-rw-r--r--test/FrontendObjC/2010-02-11-fwritable-stringsBug.m17
-rw-r--r--test/FrontendObjC/2010-02-23-DbgInheritance.m9
-rw-r--r--test/FrontendObjC/2010-03-17-StructRef.m43
-rw-r--r--test/FrontendObjC/2010-06-04-UnnamedCFString-dbg.m6
-rw-r--r--test/FrontendObjC/2011-03-02-ConstCFStringLiteralAlign.m11
-rw-r--r--test/FrontendObjC/2011-03-08-IVarLookup.m32
-rw-r--r--test/FrontendObjC/dg.exp5
-rw-r--r--test/LLVMC/Alias.td24
-rw-r--r--test/LLVMC/AppendCmdHook.td29
-rw-r--r--test/LLVMC/C++/dash-x.cpp10
-rw-r--r--test/LLVMC/C++/dg.exp5
-rw-r--r--test/LLVMC/C++/filelist.cpp3
-rw-r--r--test/LLVMC/C++/hello.cpp9
-rw-r--r--test/LLVMC/C++/just-compile.cpp10
-rw-r--r--test/LLVMC/C++/together.cpp10
-rw-r--r--test/LLVMC/C++/unknown_suffix.unk9
-rw-r--r--test/LLVMC/C/dg.exp5
-rw-r--r--test/LLVMC/C/emit-llvm-opt.c9
-rw-r--r--test/LLVMC/C/emit-llvm.c8
-rw-r--r--test/LLVMC/C/hello.c13
-rw-r--r--test/LLVMC/C/include.c10
-rw-r--r--test/LLVMC/C/opt-test.c13
-rw-r--r--test/LLVMC/C/sink.c13
-rw-r--r--test/LLVMC/C/wall.c13
-rw-r--r--test/LLVMC/EmptyCompilationGraph.td8
-rw-r--r--test/LLVMC/EnvParentheses.td18
-rw-r--r--test/LLVMC/ForwardAs.td21
-rw-r--r--test/LLVMC/ForwardTransformedValue.td27
-rw-r--r--test/LLVMC/ForwardValue.td24
-rw-r--r--test/LLVMC/HookWithArguments.td20
-rw-r--r--test/LLVMC/HookWithInFile.td16
-rw-r--r--test/LLVMC/Init.td25
-rw-r--r--test/LLVMC/LanguageMap.td29
-rw-r--r--test/LLVMC/MultiValuedOption.td24
-rw-r--r--test/LLVMC/MultipleCompilationGraphs.td10
-rw-r--r--test/LLVMC/MultipleOutputLanguages.td27
-rw-r--r--test/LLVMC/NoActions.td16
-rw-r--r--test/LLVMC/NoCompilationGraph.td6
-rw-r--r--test/LLVMC/ObjC++/dg.exp5
-rw-r--r--test/LLVMC/ObjC++/hello.mm8
-rw-r--r--test/LLVMC/ObjC/dg.exp5
-rw-r--r--test/LLVMC/ObjC/hello.m12
-rw-r--r--test/LLVMC/OneOrMore.td25
-rw-r--r--test/LLVMC/OptionPreprocessor.td67
-rw-r--r--test/LLVMC/OutputSuffixHook.td24
-rw-r--r--test/LLVMC/TestWarnings.td8
-rw-r--r--test/LLVMC/dg.exp3
-rw-r--r--test/LLVMC/test_data/false.c10
-rw-r--r--test/LLVMC/test_data/false.cpp16
-rw-r--r--test/LLVMC/test_data/false2.cpp5
-rw-r--r--test/LLVMC/test_data/together.c5
-rw-r--r--test/Linker/2003-01-30-LinkerTypeRename.ll6
-rw-r--r--test/Linker/2003-04-26-NullPtrLinkProblem.ll2
-rw-r--r--test/Linker/2003-06-02-TypeResolveProblem.ll2
-rw-r--r--test/Linker/2003-06-02-TypeResolveProblem2.ll2
-rw-r--r--test/Linker/2003-08-23-GlobalVarLinking.ll2
-rw-r--r--test/Linker/2003-11-18-TypeResolution.ll2
-rw-r--r--test/Linker/2011-08-04-DebugLoc.ll26
-rw-r--r--test/Linker/2011-08-04-DebugLoc2.ll23
-rw-r--r--test/Linker/2011-08-04-Metadata.ll29
-rw-r--r--test/Linker/2011-08-04-Metadata2.ll29
-rw-r--r--test/Linker/2011-08-18-unique-class-type.ll35
-rw-r--r--test/Linker/2011-08-18-unique-class-type2.ll35
-rw-r--r--test/Linker/2011-08-18-unique-debug-type.ll26
-rw-r--r--test/Linker/2011-08-18-unique-debug-type2.ll25
-rw-r--r--test/Linker/2011-08-22-ResolveAlias.ll89
-rw-r--r--test/Linker/2011-08-22-ResolveAlias2.ll92
-rw-r--r--test/MC/ARM/arm-memory-instructions.s479
-rw-r--r--test/MC/ARM/arm_addrmode3.s8
-rw-r--r--test/MC/ARM/arm_fixups.s22
-rw-r--r--test/MC/ARM/arm_instructions.s135
-rw-r--r--test/MC/ARM/basic-arm-instructions.s2452
-rw-r--r--test/MC/ARM/basic-thumb-instructions.s623
-rw-r--r--test/MC/ARM/basic-thumb2-instructions.s3213
-rw-r--r--test/MC/ARM/diagnostics.s227
-rw-r--r--test/MC/ARM/elf-movt.s8
-rw-r--r--test/MC/ARM/elf-reloc-01.ll8
-rw-r--r--test/MC/ARM/elf-reloc-02.ll8
-rw-r--r--test/MC/ARM/elf-reloc-03.ll8
-rw-r--r--test/MC/ARM/elf-thumbfunc-reloc.ll10
-rw-r--r--test/MC/ARM/elf-thumbfunc.s6
-rw-r--r--test/MC/ARM/mode-switch.s14
-rw-r--r--test/MC/ARM/neon-bitwise-encoding.s58
-rw-r--r--test/MC/ARM/neon-cmp-encoding.s124
-rw-r--r--test/MC/ARM/neon-dup-encoding.s32
-rw-r--r--test/MC/ARM/neon-mov-encoding.s138
-rw-r--r--test/MC/ARM/neon-mul-accum-encoding.s3
-rw-r--r--test/MC/ARM/neon-mul-encoding.s134
-rw-r--r--test/MC/ARM/neon-vld-encoding.s197
-rw-r--r--test/MC/ARM/neont2-absdiff-encoding.s87
-rw-r--r--test/MC/ARM/neont2-bitcount-encoding.s34
-rw-r--r--test/MC/ARM/neont2-bitwise-encoding.s58
-rw-r--r--test/MC/ARM/neont2-dup-encoding.s66
-rw-r--r--test/MC/ARM/neont2-mul-accum-encoding.s81
-rw-r--r--test/MC/ARM/neont2-pairwise-encoding.s181
-rw-r--r--test/MC/ARM/nop-armv4-padding.s10
-rw-r--r--test/MC/ARM/nop-armv6t2-padding.s10
-rw-r--r--test/MC/ARM/nop-thumb-padding.s12
-rw-r--r--test/MC/ARM/nop-thumb2-padding.s12
-rw-r--r--test/MC/ARM/reg-list.s8
-rw-r--r--test/MC/ARM/simple-encoding.ll236
-rw-r--r--test/MC/ARM/simple-fp-encoding.s43
-rw-r--r--test/MC/ARM/thumb-diagnostics.s139
-rw-r--r--test/MC/ARM/thumb-nop.s9
-rw-r--r--test/MC/ARM/thumb.s48
-rw-r--r--test/MC/ARM/thumb2-diagnostics.s44
-rw-r--r--test/MC/ARM/thumb2-mclass.s74
-rw-r--r--test/MC/ARM/thumb2.s355
-rw-r--r--test/MC/ARM/thumb2_instructions.s12
-rw-r--r--test/MC/ARM/xscale-attributes.ll2
-rw-r--r--test/MC/AsmParser/2011-09-06-NoNewline.s6
-rw-r--r--test/MC/AsmParser/exprs.s15
-rw-r--r--test/MC/AsmParser/labels.s3
-rw-r--r--test/MC/AsmParser/line_with_hash.s15
-rw-r--r--test/MC/Disassembler/ARM/arm-tests.txt50
-rw-r--r--test/MC/Disassembler/ARM/basic-arm-instructions.txt2362
-rw-r--r--test/MC/Disassembler/ARM/fp-encoding.txt213
-rw-r--r--test/MC/Disassembler/ARM/invalid-BFI-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-DMB-thumb.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-DSB-arm.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-IT-CBNZ-thumb.txt5
-rw-r--r--test/MC/Disassembler/ARM/invalid-IT-thumb.txt3
-rw-r--r--test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-LDM-thumb.txt5
-rw-r--r--test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt6
-rw-r--r--test/MC/Disassembler/ARM/invalid-LDRD-arm.txt10
-rw-r--r--test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-LDRT-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt1
-rw-r--r--test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt6
-rw-r--r--test/MC/Disassembler/ARM/invalid-LSL-regform.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-MCR-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-MOVr-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-MOVs-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-MSRi-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-RSC-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-SBFX-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-SRS-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-SSAT-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-SXTB-arm.txt2
-rw-r--r--test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt3
-rw-r--r--test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-VQADD-arm.txt3
-rw-r--r--test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt5
-rw-r--r--test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt3
-rw-r--r--test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-t2PUSH-thumb.txt5
-rw-r--r--test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt3
-rw-r--r--test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt3
-rw-r--r--test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt4
-rw-r--r--test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt4
-rw-r--r--test/MC/Disassembler/ARM/memory-arm-instructions.txt470
-rw-r--r--test/MC/Disassembler/ARM/neon-tests.txt6
-rw-r--r--test/MC/Disassembler/ARM/neon.txt1858
-rw-r--r--test/MC/Disassembler/ARM/neont2.txt1586
-rw-r--r--test/MC/Disassembler/ARM/thumb-MSR-MClass.txt7
-rw-r--r--test/MC/Disassembler/ARM/thumb-printf.txt2
-rw-r--r--test/MC/Disassembler/ARM/thumb-tests.txt56
-rw-r--r--test/MC/Disassembler/ARM/thumb1.txt530
-rw-r--r--test/MC/Disassembler/ARM/thumb2.txt2558
-rw-r--r--test/MC/Disassembler/X86/enhanced.txt4
-rw-r--r--test/MC/Disassembler/X86/intel-syntax.txt79
-rw-r--r--test/MC/Disassembler/X86/invalid-VEX-vvvv.txt4
-rw-r--r--test/MC/Disassembler/X86/simple-tests.txt446
-rw-r--r--test/MC/Disassembler/X86/x86-32.txt471
-rw-r--r--test/MC/ELF/abs.s10
-rw-r--r--test/MC/ELF/alias-reloc.s32
-rw-r--r--test/MC/ELF/alias.s76
-rw-r--r--test/MC/ELF/align-bss.s12
-rw-r--r--test/MC/ELF/align-nops.s16
-rw-r--r--test/MC/ELF/align-size.s8
-rw-r--r--test/MC/ELF/align-text.s12
-rw-r--r--test/MC/ELF/align.s28
-rw-r--r--test/MC/ELF/basic-elf-32.s42
-rw-r--r--test/MC/ELF/basic-elf-64.s50
-rw-r--r--test/MC/ELF/call-abs.s6
-rw-r--r--test/MC/ELF/cfi-adjust-cfa-offset.s34
-rw-r--r--test/MC/ELF/cfi-advance-loc2.s30
-rw-r--r--test/MC/ELF/cfi-def-cfa-offset.s34
-rw-r--r--test/MC/ELF/cfi-def-cfa-register.s30
-rw-r--r--test/MC/ELF/cfi-def-cfa.s30
-rw-r--r--test/MC/ELF/cfi-offset.s30
-rw-r--r--test/MC/ELF/cfi-rel-offset.s34
-rw-r--r--test/MC/ELF/cfi-rel-offset2.s34
-rw-r--r--test/MC/ELF/cfi-remember.s34
-rw-r--r--test/MC/ELF/cfi-same-value.s34
-rw-r--r--test/MC/ELF/cfi-sections.s12
-rw-r--r--test/MC/ELF/cfi-zero-addr-delta.s30
-rw-r--r--test/MC/ELF/cfi.s460
-rw-r--r--test/MC/ELF/comdat.s72
-rw-r--r--test/MC/ELF/common.s48
-rw-r--r--test/MC/ELF/common2.s2
-rw-r--r--test/MC/ELF/debug-line.s12
-rw-r--r--test/MC/ELF/debug-loc.s14
-rw-r--r--test/MC/ELF/diff.s6
-rw-r--r--test/MC/ELF/empty-dwarf-lines.s14
-rw-r--r--test/MC/ELF/empty.s68
-rw-r--r--test/MC/ELF/entsize.ll16
-rw-r--r--test/MC/ELF/entsize.s30
-rw-r--r--test/MC/ELF/file.s20
-rw-r--r--test/MC/ELF/global-offset.s5
-rw-r--r--test/MC/ELF/got.s6
-rw-r--r--test/MC/ELF/ident.s12
-rw-r--r--test/MC/ELF/leb128.s12
-rw-r--r--test/MC/ELF/local-reloc.s14
-rw-r--r--test/MC/ELF/many-section.s93319
-rw-r--r--test/MC/ELF/merge.s32
-rw-r--r--test/MC/ELF/n_bytes.s14
-rw-r--r--test/MC/ELF/noexec.s24
-rw-r--r--test/MC/ELF/norelocation.s12
-rw-r--r--test/MC/ELF/org.s2
-rw-r--r--test/MC/ELF/pic-diff.s16
-rw-r--r--test/MC/ELF/plt.s2
-rw-r--r--test/MC/ELF/pr9292.s18
-rw-r--r--test/MC/ELF/relax.s14
-rw-r--r--test/MC/ELF/relocation-386.s164
-rw-r--r--test/MC/ELF/relocation-pc.s26
-rw-r--r--test/MC/ELF/relocation.s90
-rw-r--r--test/MC/ELF/rename.s30
-rw-r--r--test/MC/ELF/section.s78
-rw-r--r--test/MC/ELF/set.s16
-rw-r--r--test/MC/ELF/symref.s150
-rw-r--r--test/MC/ELF/tls-i386.s68
-rw-r--r--test/MC/ELF/tls.s38
-rw-r--r--test/MC/ELF/type.s20
-rw-r--r--test/MC/ELF/undef.s24
-rw-r--r--test/MC/ELF/undef2.s2
-rw-r--r--test/MC/ELF/weak-relocation.s6
-rw-r--r--test/MC/ELF/weak.s20
-rw-r--r--test/MC/ELF/weakref-plt.s4
-rw-r--r--test/MC/ELF/weakref-reloc.s42
-rw-r--r--test/MC/ELF/weakref.s180
-rw-r--r--test/MC/ELF/x86_64-reloc-sizetest.s13
-rw-r--r--test/MC/ELF/zero.s12
-rw-r--r--test/MC/MachO/darwin-x86_64-nobase-relocs.s58
-rw-r--r--test/MC/MachO/debug_frame.s15
-rw-r--r--test/MC/MachO/x86_64-reloc-arithmetic.s21
-rw-r--r--test/MC/X86/3DNow.s6
-rw-r--r--test/MC/X86/x86-32-avx.s30
-rw-r--r--test/MC/X86/x86-32-coverage.s21
-rw-r--r--test/MC/X86/x86-32.s16
-rw-r--r--test/MC/X86/x86-64.s21
-rw-r--r--test/MC/X86/x86_64-avx-encoding.s30
-rw-r--r--test/MC/X86/x86_errors.s16
-rw-r--r--test/Object/TestObjectFiles/archive-test.a-bitcodebin0 -> 790 bytes
-rw-r--r--test/Object/TestObjectFiles/archive-test.a-coff-i386bin0 -> 658 bytes
-rw-r--r--test/Object/nm-archive.test17
-rw-r--r--test/Object/nm-trivial-object.test (renamed from test/Object/nm-trivial-object.test-broken)0
-rw-r--r--test/Object/objdump-disassembly-inline-relocations.test32
-rw-r--r--test/Object/objdump-relocations.test28
-rw-r--r--test/Object/objdump-sectionheaders.test16
-rw-r--r--test/Object/objdump-trivial-object.test (renamed from test/Object/objdump-trivial-object.test-broken)0
-rw-r--r--test/Other/2008-10-15-MissingSpace.ll7
-rw-r--r--test/Scripts/common_dump.py6
-rwxr-xr-xtest/Scripts/elf-dump98
-rw-r--r--test/TableGen/2003-08-03-PassCode.td2
-rw-r--r--test/TableGen/2006-09-18-LargeInt.td2
-rw-r--r--test/TableGen/2010-03-24-PrematureDefaults.td2
-rw-r--r--test/TableGen/AnonDefinitionOnDemand.td2
-rw-r--r--test/TableGen/BitsInitOverflow.td2
-rw-r--r--test/TableGen/CStyleComment.td3
-rw-r--r--test/TableGen/Dag.td2
-rw-r--r--test/TableGen/DefmInherit.td2
-rw-r--r--test/TableGen/DefmInsideMultiClass.td2
-rw-r--r--test/TableGen/FieldAccess.td2
-rw-r--r--test/TableGen/ForwardRef.td2
-rw-r--r--test/TableGen/GeneralList.td2
-rw-r--r--test/TableGen/Include.td3
-rw-r--r--test/TableGen/IntBitInit.td2
-rw-r--r--test/TableGen/LazyChange.td2
-rw-r--r--test/TableGen/LetInsideMultiClasses.td2
-rw-r--r--test/TableGen/ListArgs.td2
-rw-r--r--test/TableGen/ListArgsSimple.td2
-rw-r--r--test/TableGen/ListConversion.td2
-rw-r--r--test/TableGen/ListManip.td2
-rw-r--r--test/TableGen/ListOfList.td14
-rw-r--r--test/TableGen/ListSlices.td2
-rw-r--r--test/TableGen/LoLoL.td18
-rw-r--r--test/TableGen/MultiClass.td2
-rw-r--r--test/TableGen/MultiClassDefName.td2
-rw-r--r--test/TableGen/MultiClassInherit.td2
-rw-r--r--test/TableGen/MultiPat.td121
-rw-r--r--test/TableGen/SetTheory.td2
-rw-r--r--test/TableGen/Slice.td4
-rw-r--r--test/TableGen/String.td2
-rw-r--r--test/TableGen/SuperSubclassSameName.td2
-rw-r--r--test/TableGen/TargetInstrInfo.td2
-rw-r--r--test/TableGen/TargetInstrSpec.td4
-rw-r--r--test/TableGen/TemplateArgRename.td2
-rw-r--r--test/TableGen/Tree.td2
-rw-r--r--test/TableGen/TreeNames.td2
-rw-r--r--test/TableGen/UnsetBitInit.td2
-rw-r--r--test/TableGen/UnterminatedComment.td2
-rw-r--r--test/TableGen/cast.td2
-rw-r--r--test/TableGen/defmclass.td2
-rw-r--r--test/TableGen/eq.td2
-rw-r--r--test/TableGen/eqbit.td2
-rw-r--r--test/TableGen/foreach.td6
-rw-r--r--test/TableGen/if.td2
-rw-r--r--test/TableGen/ifbit.td2
-rw-r--r--test/TableGen/lisp.td2
-rw-r--r--test/TableGen/nested-comment.td3
-rw-r--r--test/TableGen/strconcat.td2
-rw-r--r--test/TableGen/subst.td12
-rw-r--r--test/TableGen/subst2.td2
-rw-r--r--test/TableGen/usevalname.td2
-rw-r--r--test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll5
-rw-r--r--test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll2
-rw-r--r--test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll9
-rw-r--r--test/Transforms/ADCE/dce_pure_invoke.ll4
-rw-r--r--test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll4
-rw-r--r--test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll5
-rw-r--r--test/Transforms/ConstantMerge/merge-both.ll17
-rw-r--r--test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll6
-rw-r--r--test/Transforms/DeadArgElim/deadexternal.ll2
-rw-r--r--test/Transforms/DeadStoreElimination/2011-09-06-EndOfFunction.ll27
-rw-r--r--test/Transforms/DeadStoreElimination/2011-09-06-MemCpy.ll85
-rw-r--r--test/Transforms/DeadStoreElimination/atomic.ll107
-rw-r--r--test/Transforms/DeadStoreElimination/simple.ll8
-rw-r--r--test/Transforms/EarlyCSE/basic.ll10
-rw-r--r--test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll4
-rw-r--r--test/Transforms/FunctionAttrs/atomic.ll21
-rw-r--r--test/Transforms/GVN/2010-05-08-OneBit.ll4
-rw-r--r--test/Transforms/GVN/2011-09-07-TypeIdFor.ll81
-rw-r--r--test/Transforms/GVN/atomic.ll80
-rw-r--r--test/Transforms/GVN/condprop.ll83
-rw-r--r--test/Transforms/GVN/phi-translate.ll2
-rw-r--r--test/Transforms/GVN/pr10820.ll18
-rw-r--r--test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll2
-rw-r--r--test/Transforms/IPConstantProp/global.ll26
-rw-r--r--test/Transforms/IPConstantProp/return-argument.ll10
-rw-r--r--test/Transforms/IPConstantProp/return-constant.ll4
-rw-r--r--test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll15
-rw-r--r--test/Transforms/IndVarSimplify/2003-12-21-IndVarSize.ll15
-rw-r--r--test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll8
-rw-r--r--test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll10
-rw-r--r--test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll6
-rw-r--r--test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll2
-rw-r--r--test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll2
-rw-r--r--test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll30
-rw-r--r--test/Transforms/IndVarSimplify/2011-09-19-vectoriv.ll16
-rw-r--r--test/Transforms/IndVarSimplify/2011-09-27-hoistsext.ll28
-rw-r--r--test/Transforms/IndVarSimplify/ada-loops.ll9
-rw-r--r--test/Transforms/IndVarSimplify/addrec-gep.ll12
-rw-r--r--test/Transforms/IndVarSimplify/ashr-tripcount.ll2
-rw-r--r--test/Transforms/IndVarSimplify/complex-scev.ll4
-rw-r--r--test/Transforms/IndVarSimplify/crash.ll34
-rw-r--r--test/Transforms/IndVarSimplify/elim-extend.ll2
-rw-r--r--test/Transforms/IndVarSimplify/floating-point-iv.ll8
-rw-r--r--test/Transforms/IndVarSimplify/gep-with-mul-base.ll17
-rw-r--r--test/Transforms/IndVarSimplify/interesting-invoke-use.ll4
-rw-r--r--test/Transforms/IndVarSimplify/iv-fold.ll56
-rw-r--r--test/Transforms/IndVarSimplify/iv-sext.ll2
-rw-r--r--test/Transforms/IndVarSimplify/iv-zext.ll4
-rw-r--r--test/Transforms/IndVarSimplify/lftr-reuse.ll230
-rw-r--r--test/Transforms/IndVarSimplify/max-pointer.ll39
-rw-r--r--test/Transforms/IndVarSimplify/no-iv-rewrite.ll84
-rw-r--r--test/Transforms/IndVarSimplify/pointer-indvars.ll15
-rw-r--r--test/Transforms/IndVarSimplify/pointer.ll38
-rw-r--r--test/Transforms/IndVarSimplify/preserve-gep-loop-variant.ll10
-rw-r--r--test/Transforms/IndVarSimplify/preserve-gep-nested.ll23
-rw-r--r--test/Transforms/IndVarSimplify/preserve-gep-remainder.ll6
-rw-r--r--test/Transforms/IndVarSimplify/preserve-gep.ll10
-rw-r--r--test/Transforms/IndVarSimplify/preserve-signed-wrap.ll2
-rw-r--r--test/Transforms/IndVarSimplify/subtract.ll15
-rw-r--r--test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll2
-rw-r--r--test/Transforms/Inline/2003-09-14-InlineValue.ll4
-rw-r--r--test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll9
-rw-r--r--test/Transforms/Inline/2003-10-26-InlineInvokeExceptionDestPhi.ll20
-rw-r--r--test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll2
-rw-r--r--test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll2
-rw-r--r--test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll20
-rw-r--r--test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll12
-rw-r--r--test/Transforms/Inline/2007-04-15-InlineEH.ll6
-rw-r--r--test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll2
-rw-r--r--test/Transforms/Inline/callgraph-update.ll3
-rw-r--r--test/Transforms/Inline/crash.ll10
-rw-r--r--test/Transforms/Inline/inline_invoke.ll122
-rw-r--r--test/Transforms/Inline/invoke_test-1.ll4
-rw-r--r--test/Transforms/Inline/invoke_test-2.ll6
-rw-r--r--test/Transforms/Inline/invoke_test-3.ll8
-rw-r--r--test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll3
-rw-r--r--test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll3
-rw-r--r--test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll6
-rw-r--r--test/Transforms/InstCombine/2008-04-28-VolatileStore.ll2
-rw-r--r--test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll2
-rw-r--r--test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll2
-rw-r--r--test/Transforms/InstCombine/2008-05-09-SinkOfInvoke.ll4
-rw-r--r--test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll2
-rw-r--r--test/Transforms/InstCombine/2011-09-03-Trampoline.ll87
-rw-r--r--test/Transforms/InstCombine/2011-10-07-AlignPromotion.ll20
-rw-r--r--test/Transforms/InstCombine/LandingPadClauses.ll181
-rw-r--r--test/Transforms/InstCombine/and2.ll7
-rw-r--r--test/Transforms/InstCombine/atomic.ll24
-rw-r--r--test/Transforms/InstCombine/bitcast.ll34
-rw-r--r--test/Transforms/InstCombine/call.ll20
-rw-r--r--test/Transforms/InstCombine/canonicalize_branch.ll31
-rw-r--r--test/Transforms/InstCombine/cast.ll47
-rw-r--r--test/Transforms/InstCombine/crash.ll4
-rw-r--r--test/Transforms/InstCombine/deadcode.ll11
-rw-r--r--test/Transforms/InstCombine/devirt.ll39
-rw-r--r--test/Transforms/InstCombine/extractvalue.ll2
-rw-r--r--test/Transforms/InstCombine/fcmp.ll11
-rw-r--r--test/Transforms/InstCombine/getelementptr.ll20
-rw-r--r--test/Transforms/InstCombine/intrinsics.ll12
-rw-r--r--test/Transforms/InstCombine/malloc-free-delete.ll25
-rw-r--r--test/Transforms/InstCombine/nsw.ll44
-rw-r--r--test/Transforms/InstCombine/ptr-int-cast.ll14
-rw-r--r--test/Transforms/InstCombine/select.ll10
-rw-r--r--test/Transforms/InstCombine/shift.ll19
-rw-r--r--test/Transforms/InstCombine/vec_demanded_elts.ll11
-rw-r--r--test/Transforms/InstCombine/vector-casts.ll2
-rw-r--r--test/Transforms/InstCombine/volatile_store.ll4
-rw-r--r--test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll29
-rw-r--r--test/Transforms/InstSimplify/compare.ll11
-rw-r--r--test/Transforms/JumpThreading/no-irreducible-loops.ll2
-rw-r--r--test/Transforms/LCSSA/invoke-dest.ll8
-rw-r--r--test/Transforms/LICM/2007-05-22-VolatileSink.ll2
-rw-r--r--test/Transforms/LICM/2011-04-06-HoistMissedASTUpdate.ll2
-rw-r--r--test/Transforms/LICM/atomics.ll79
-rw-r--r--test/Transforms/LICM/scalar-promote-memmodel.ll37
-rw-r--r--test/Transforms/LICM/scalar_promote.ll2
-rw-r--r--test/Transforms/LoopDeletion/2008-05-06-Phi.ll2
-rw-r--r--test/Transforms/LoopIdiom/basic.ll4
-rw-r--r--test/Transforms/LoopSimplify/2003-08-15-PreheadersFail.ll2
-rw-r--r--test/Transforms/LoopSimplify/2007-10-28-InvokeCrash.ll887
-rw-r--r--test/Transforms/LoopSimplify/merge-exits.ll2
-rw-r--r--test/Transforms/LoopSimplify/preserve-scev.ll88
-rw-r--r--test/Transforms/LoopSimplify/single-backedge.ll9
-rw-r--r--test/Transforms/LoopStrengthReduce/2011-07-19-CritEdgeBreakCrash.ll52
-rw-r--r--test/Transforms/LoopStrengthReduce/2011-07-20-DoubleIV.ll43
-rw-r--r--test/Transforms/LoopStrengthReduce/2011-10-03-CritEdgeMerge.ll43
-rw-r--r--test/Transforms/LoopStrengthReduce/2011-10-06-ReusePhi.ll53
-rw-r--r--test/Transforms/LoopStrengthReduce/2011-10-13-SCEVChain.ll111
-rw-r--r--test/Transforms/LoopStrengthReduce/2011-10-14-IntPtr.ll27
-rw-r--r--test/Transforms/LoopStrengthReduce/invariant_value_first.ll2
-rw-r--r--test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll2
-rw-r--r--test/Transforms/LoopStrengthReduce/ops_after_indvar.ll2
-rw-r--r--test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll14
-rw-r--r--test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll2
-rw-r--r--test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll103
-rw-r--r--test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll41
-rw-r--r--test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll62
-rw-r--r--test/Transforms/LoopUnroll/2011-10-01-NoopTrunc.ll36
-rw-r--r--test/Transforms/LoopUnroll/pr10813.ll29
-rw-r--r--test/Transforms/LoopUnroll/scevunroll.ll172
-rw-r--r--test/Transforms/LoopUnroll/unloop.ll429
-rw-r--r--test/Transforms/LoopUnswitch/2011-09-26-EHCrash.ll67
-rw-r--r--test/Transforms/LowerAtomic/atomic-load.ll10
-rw-r--r--test/Transforms/LowerAtomic/atomic-swap.ll7
-rw-r--r--test/Transforms/LowerAtomic/barrier.ll4
-rw-r--r--test/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll16
-rw-r--r--test/Transforms/LowerSetJmp/simpletest.ll31
-rw-r--r--test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll2
-rw-r--r--test/Transforms/Mem2Reg/atomic.ll12
-rw-r--r--test/Transforms/Mem2Reg/crash.ll3
-rw-r--r--test/Transforms/MemCpyOpt/atomic.ll41
-rw-r--r--test/Transforms/ObjCARC/basic.ll110
-rw-r--r--test/Transforms/ObjCARC/cfg-hazards.ll329
-rw-r--r--test/Transforms/ObjCARC/contract-storestrong.ll4
-rw-r--r--test/Transforms/ObjCARC/empty-block.ll59
-rw-r--r--test/Transforms/ObjCARC/invoke.ll6
-rw-r--r--test/Transforms/ObjCARC/nested.ll620
-rw-r--r--test/Transforms/ObjCARC/retain-block-alloca.ll54
-rw-r--r--test/Transforms/ObjCARC/retain-block-side-effects.ll39
-rw-r--r--test/Transforms/ObjCARC/retain-not-declared.ll54
-rw-r--r--test/Transforms/ObjCARC/rv.ll11
-rw-r--r--test/Transforms/PhaseOrdering/2010-03-22-empty-baseclass.ll162
-rw-r--r--test/Transforms/PruneEH/2003-09-14-ExternalCall.ll3
-rw-r--r--test/Transforms/SCCP/2003-08-26-InvokeHandling.ll9
-rw-r--r--test/Transforms/SCCP/2004-11-16-DeadInvoke.ll9
-rw-r--r--test/Transforms/SCCP/2007-05-16-InvokeCrash.ll6
-rw-r--r--test/Transforms/SCCP/2009-01-14-IPSCCP-Invoke.ll2
-rw-r--r--test/Transforms/SCCP/atomic-load-store.ll30
-rw-r--r--test/Transforms/SCCP/ipsccp-basic.ll23
-rw-r--r--test/Transforms/SCCP/switch.ll13
-rw-r--r--test/Transforms/SCCP/undef-resolve.ll66
-rw-r--r--test/Transforms/ScalarRepl/2003-10-29-ArrayProblem.ll2
-rw-r--r--test/Transforms/ScalarRepl/2011-09-22-PHISpeculateInvoke.ll40
-rw-r--r--test/Transforms/ScalarRepl/2011-10-11-VectorMemset.ll22
-rw-r--r--test/Transforms/ScalarRepl/lifetime.ll139
-rw-r--r--test/Transforms/ScalarRepl/vector_promote.ll170
-rw-r--r--test/Transforms/ScalarRepl/vectors-with-mismatched-elements.ll27
-rw-r--r--test/Transforms/ScalarRepl/volatile.ll4
-rw-r--r--test/Transforms/SimplifyCFG/2003-08-05-InvokeCrash.ll3
-rw-r--r--test/Transforms/SimplifyCFG/2003-08-05-MishandleInvoke.ll3
-rw-r--r--test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll3
-rw-r--r--test/Transforms/SimplifyCFG/2006-10-29-InvokeCrash.ll14
-rw-r--r--test/Transforms/SimplifyCFG/2009-01-19-UnconditionalTrappingConstantExpr.ll4
-rw-r--r--test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll14
-rw-r--r--test/Transforms/SimplifyCFG/2010-03-30-InvokeCrash.ll6
-rw-r--r--test/Transforms/SimplifyCFG/2011-09-05-TrivialLPad.ll22
-rw-r--r--test/Transforms/SimplifyCFG/BrUnwind.ll2
-rw-r--r--test/Transforms/SimplifyCFG/invoke_unwind.ll20
-rw-r--r--test/Transforms/SimplifyCFG/phi-undef-loadstore.ll87
-rw-r--r--test/Transforms/SimplifyCFG/trapping-load-unreachable.ll51
-rw-r--r--test/Transforms/SimplifyLibCalls/StrCmp.ll73
-rw-r--r--test/Transforms/SimplifyLibCalls/StrNCmp.ll95
-rw-r--r--test/Transforms/SimplifyLibCalls/memcmp.ll22
-rw-r--r--test/Transforms/SimplifyLibCalls/pow-to-sqrt.ll12
-rw-r--r--test/Transforms/Sink/basic.ll16
-rw-r--r--test/Transforms/StripSymbols/block-address.ll23
-rw-r--r--test/Transforms/TailCallElim/dont_reorder_load.ll2
-rw-r--r--test/Transforms/TailCallElim/reorder_load.ll4
-rw-r--r--test/Transforms/TailCallElim/setjmp.ll19
-rw-r--r--test/Transforms/TailDup/2003-06-24-Simpleloop.ll15
-rw-r--r--test/Transforms/TailDup/2003-07-22-InfiniteLoop.ll11
-rw-r--r--test/Transforms/TailDup/2003-08-23-InvalidatedPointers.ll29
-rw-r--r--test/Transforms/TailDup/2003-08-31-UnreachableBlocks.ll17
-rw-r--r--test/Transforms/TailDup/2004-04-01-DemoteRegToStack.ll20
-rw-r--r--test/Transforms/TailDup/2008-05-13-InfiniteLoop.ll26
-rw-r--r--test/Transforms/TailDup/2009-07-31-phicrash.ll14
-rw-r--r--test/Transforms/TailDup/MergeTest.ll27
-rw-r--r--test/Transforms/TailDup/PHIUpdateTest.ll16
-rw-r--r--test/Transforms/TailDup/X86/if-tail-dup.ll49
-rw-r--r--test/Transforms/TailDup/basictest.ll20
-rw-r--r--test/Transforms/TailDup/basictest2.ll15
-rw-r--r--test/lib/llvm.exp30
-rw-r--r--test/lit.cfg13
-rw-r--r--tools/CMakeLists.txt3
-rw-r--r--tools/Makefile5
-rw-r--r--tools/bugpoint/BugDriver.cpp3
-rw-r--r--tools/bugpoint/ExtractFunction.cpp2
-rw-r--r--tools/bugpoint/Miscompilation.cpp21
-rw-r--r--tools/bugpoint/bugpoint.cpp3
-rw-r--r--tools/edis/CMakeLists.txt29
-rw-r--r--tools/edis/EnhancedDisassembly.exports36
-rw-r--r--tools/edis/Makefile1
-rw-r--r--tools/gold/gold-plugin.cpp41
-rw-r--r--tools/llc/llc.cpp47
-rw-r--r--tools/lli/lli.cpp36
-rw-r--r--tools/llvm-config/CMakeLists.txt24
-rw-r--r--tools/llvm-cov/CMakeLists.txt5
-rw-r--r--tools/llvm-cov/Makefile18
-rw-r--r--tools/llvm-cov/llvm-cov.cpp78
-rw-r--r--tools/llvm-diff/DifferenceEngine.cpp4
-rw-r--r--tools/llvm-dwarfdump/CMakeLists.txt8
-rw-r--r--tools/llvm-dwarfdump/Makefile17
-rw-r--r--tools/llvm-dwarfdump/llvm-dwarfdump.cpp116
-rw-r--r--tools/llvm-extract/llvm-extract.cpp77
-rw-r--r--tools/llvm-ld/Optimize.cpp6
-rw-r--r--tools/llvm-link/llvm-link.cpp3
-rw-r--r--tools/llvm-mc/Disassembler.cpp38
-rw-r--r--tools/llvm-mc/Disassembler.h2
-rw-r--r--tools/llvm-mc/llvm-mc.cpp178
-rw-r--r--tools/llvm-nm/llvm-nm.cpp45
-rw-r--r--tools/llvm-objdump/CMakeLists.txt3
-rw-r--r--tools/llvm-objdump/MCFunction.cpp138
-rw-r--r--tools/llvm-objdump/MCFunction.h100
-rw-r--r--tools/llvm-objdump/MachODump.cpp617
-rw-r--r--tools/llvm-objdump/Makefile3
-rw-r--r--tools/llvm-objdump/llvm-objdump.cpp328
-rw-r--r--tools/llvm-objdump/llvm-objdump.h46
-rw-r--r--tools/llvm-shlib/Makefile5
-rw-r--r--tools/llvm-size/CMakeLists.txt5
-rw-r--r--tools/llvm-size/Makefile17
-rw-r--r--tools/llvm-size/llvm-size.cpp311
-rw-r--r--tools/llvmc/CMakeLists.txt4
-rw-r--r--tools/llvmc/Makefile18
-rw-r--r--tools/llvmc/doc/LLVMC-Reference.rst747
-rw-r--r--tools/llvmc/doc/LLVMC-Tutorial.rst127
-rw-r--r--tools/llvmc/doc/Makefile33
-rw-r--r--tools/llvmc/doc/img/lines.gifbin91 -> 0 bytes
-rw-r--r--tools/llvmc/examples/Hello/Hello.cpp29
-rw-r--r--tools/llvmc/examples/Hello/Makefile14
-rw-r--r--tools/llvmc/examples/Makefile14
-rw-r--r--tools/llvmc/examples/Simple/Makefile15
-rw-r--r--tools/llvmc/examples/Simple/Simple.cpp2
-rw-r--r--tools/llvmc/examples/Simple/Simple.td41
-rw-r--r--tools/llvmc/examples/Skeleton/AutoGenerated.td7
-rw-r--r--tools/llvmc/examples/Skeleton/Hooks.cpp12
-rw-r--r--tools/llvmc/examples/Skeleton/Main.cpp15
-rw-r--r--tools/llvmc/examples/Skeleton/Makefile20
-rw-r--r--tools/llvmc/examples/Skeleton/README6
-rw-r--r--tools/llvmc/examples/mcc16/Hooks.cpp109
-rw-r--r--tools/llvmc/examples/mcc16/Main.cpp57
-rw-r--r--tools/llvmc/examples/mcc16/Makefile15
-rw-r--r--tools/llvmc/examples/mcc16/PIC16.td234
-rw-r--r--tools/llvmc/examples/mcc16/README75
-rw-r--r--tools/llvmc/src/AutoGenerated.td17
-rw-r--r--tools/llvmc/src/Base.td.in461
-rw-r--r--tools/llvmc/src/Clang.td87
-rw-r--r--tools/llvmc/src/Hooks.cpp193
-rw-r--r--tools/llvmc/src/Main.cpp16
-rw-r--r--tools/llvmc/src/Makefile14
-rw-r--r--tools/lto/LTOCodeGenerator.cpp30
-rw-r--r--tools/lto/LTOModule.cpp37
-rw-r--r--tools/lto/LTOModule.h5
-rw-r--r--tools/macho-dump/macho-dump.cpp28
-rw-r--r--tools/opt/opt.cpp4
-rw-r--r--unittests/ADT/APFloatTest.cpp15
-rw-r--r--unittests/ADT/APIntTest.cpp38
-rw-r--r--unittests/ADT/DAGDeltaAlgorithmTest.cpp17
-rw-r--r--unittests/ADT/SCCIteratorTest.cpp346
-rw-r--r--unittests/ADT/SmallVectorTest.cpp2
-rw-r--r--unittests/ADT/StringRefTest.cpp6
-rw-r--r--unittests/ADT/TwineTest.cpp8
-rw-r--r--unittests/Analysis/ScalarEvolutionTest.cpp170
-rw-r--r--unittests/ExecutionEngine/ExecutionEngineTest.cpp2
-rw-r--r--unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp4
-rw-r--r--unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp2
-rw-r--r--unittests/ExecutionEngine/JIT/JITTest.cpp20
-rw-r--r--unittests/ExecutionEngine/JIT/MultiJITTest.cpp4
-rw-r--r--unittests/Support/BlockFrequencyTest.cpp56
-rw-r--r--unittests/Support/DataExtractorTest.cpp111
-rw-r--r--unittests/Support/TypeBuilderTest.cpp14
-rw-r--r--unittests/Transforms/Utils/Cloning.cpp2
-rw-r--r--unittests/VMCore/ConstantsTest.cpp8
-rw-r--r--unittests/VMCore/InstructionsTest.cpp60
-rw-r--r--unittests/VMCore/MetadataTest.cpp2
-rw-r--r--unittests/VMCore/VerifierTest.cpp2
-rw-r--r--utils/TableGen/ARMDecoderEmitter.cpp20
-rw-r--r--utils/TableGen/ARMDecoderEmitter.h3
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp69
-rw-r--r--utils/TableGen/AsmMatcherEmitter.h2
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp14
-rw-r--r--utils/TableGen/AsmWriterEmitter.h2
-rw-r--r--utils/TableGen/AsmWriterInst.cpp2
-rw-r--r--utils/TableGen/CMakeLists.txt26
-rw-r--r--utils/TableGen/CallingConvEmitter.cpp2
-rw-r--r--utils/TableGen/CallingConvEmitter.h2
-rw-r--r--utils/TableGen/ClangASTNodesEmitter.cpp168
-rw-r--r--utils/TableGen/ClangASTNodesEmitter.h84
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp756
-rw-r--r--utils/TableGen/ClangAttrEmitter.h101
-rw-r--r--utils/TableGen/ClangDiagnosticsEmitter.cpp362
-rw-r--r--utils/TableGen/ClangDiagnosticsEmitter.h54
-rw-r--r--utils/TableGen/ClangSACheckersEmitter.cpp319
-rw-r--r--utils/TableGen/ClangSACheckersEmitter.h31
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp14
-rw-r--r--utils/TableGen/CodeEmitterGen.h2
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp25
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp21
-rw-r--r--utils/TableGen/CodeGenInstruction.h1
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp294
-rw-r--r--utils/TableGen/CodeGenRegisters.h112
-rw-r--r--utils/TableGen/CodeGenTarget.cpp12
-rw-r--r--utils/TableGen/CodeGenTarget.h6
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp2
-rw-r--r--utils/TableGen/DAGISelEmitter.h2
-rw-r--r--utils/TableGen/DAGISelMatcher.cpp2
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp2
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp6
-rw-r--r--utils/TableGen/DisassemblerEmitter.cpp20
-rw-r--r--utils/TableGen/DisassemblerEmitter.h2
-rw-r--r--utils/TableGen/EDEmitter.cpp76
-rw-r--r--utils/TableGen/EDEmitter.h2
-rw-r--r--utils/TableGen/Error.cpp39
-rw-r--r--utils/TableGen/Error.h43
-rw-r--r--utils/TableGen/FastISelEmitter.cpp6
-rw-r--r--utils/TableGen/FastISelEmitter.h2
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp492
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.h47
-rw-r--r--utils/TableGen/InstrEnumEmitter.cpp2
-rw-r--r--utils/TableGen/InstrEnumEmitter.h2
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp4
-rw-r--r--utils/TableGen/InstrInfoEmitter.h2
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp2
-rw-r--r--utils/TableGen/IntrinsicEmitter.h2
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.cpp3134
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.h34
-rw-r--r--utils/TableGen/Makefile4
-rw-r--r--utils/TableGen/NeonEmitter.cpp1558
-rw-r--r--utils/TableGen/NeonEmitter.h176
-rw-r--r--utils/TableGen/OptParserEmitter.cpp194
-rw-r--r--utils/TableGen/OptParserEmitter.h34
-rw-r--r--utils/TableGen/PseudoLoweringEmitter.cpp4
-rw-r--r--utils/TableGen/PseudoLoweringEmitter.h2
-rw-r--r--utils/TableGen/Record.cpp1575
-rw-r--r--utils/TableGen/Record.h1500
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp566
-rw-r--r--utils/TableGen/RegisterInfoEmitter.h9
-rw-r--r--utils/TableGen/SetTheory.cpp4
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp2
-rw-r--r--utils/TableGen/SubtargetEmitter.h2
-rw-r--r--utils/TableGen/TGLexer.cpp435
-rw-r--r--utils/TableGen/TGParser.cpp2152
-rw-r--r--utils/TableGen/TGParser.h122
-rw-r--r--utils/TableGen/TableGen.cpp289
-rw-r--r--utils/TableGen/TableGenBackend.cpp25
-rw-r--r--utils/TableGen/TableGenBackend.h43
-rw-r--r--utils/TableGen/X86DisassemblerTables.cpp93
-rw-r--r--utils/TableGen/X86DisassemblerTables.h6
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp100
-rw-r--r--utils/TableGen/X86RecognizableInstr.h8
-rwxr-xr-xutils/buildit/build_llvm68
-rw-r--r--utils/lit/lit/LitConfig.py3
-rw-r--r--utils/lit/lit/TestFormats.py4
-rw-r--r--utils/lit/lit/TestRunner.py11
-rw-r--r--utils/lit/lit/TestingConfig.py13
-rwxr-xr-xutils/lit/lit/main.py2
-rw-r--r--utils/llvm.grm2
-rwxr-xr-xutils/llvmbuild29
-rwxr-xr-xutils/release/findRegressions.py141
-rwxr-xr-xutils/release/test-release.sh292
-rw-r--r--utils/unittest/CMakeLists.txt1
-rw-r--r--utils/unittest/googletest/README.LLVM6
-rw-r--r--utils/unittest/googletest/gtest-death-test.cc206
-rw-r--r--utils/unittest/googletest/gtest-filepath.cc36
-rw-r--r--utils/unittest/googletest/gtest-port.cc103
-rw-r--r--utils/unittest/googletest/gtest-printers.cc356
-rw-r--r--utils/unittest/googletest/gtest-test-part.cc2
-rw-r--r--utils/unittest/googletest/gtest-typed-test.cc6
-rw-r--r--utils/unittest/googletest/gtest.cc1132
-rw-r--r--utils/unittest/googletest/include/gtest/gtest-death-test.h44
-rw-r--r--utils/unittest/googletest/include/gtest/gtest-message.h30
-rw-r--r--utils/unittest/googletest/include/gtest/gtest-param-test.h65
-rw-r--r--utils/unittest/googletest/include/gtest/gtest-printers.h796
-rw-r--r--utils/unittest/googletest/include/gtest/gtest-spi.h6
-rw-r--r--utils/unittest/googletest/include/gtest/gtest-test-part.h4
-rw-r--r--utils/unittest/googletest/include/gtest/gtest-typed-test.h30
-rw-r--r--utils/unittest/googletest/include/gtest/gtest.h395
-rw-r--r--utils/unittest/googletest/include/gtest/gtest_pred_impl.h84
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h45
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-filepath.h2
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h194
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-internal.h531
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h12
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h16
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-param-util.h42
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-port.h628
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-string.h10
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-tuple.h4
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-type-util.h69
-rw-r--r--utils/valgrind/x86_64-pc-linux-gnu.supp11
-rw-r--r--utils/vim/llvm.vim4
-rw-r--r--utils/vim/tablegen.vim2
-rw-r--r--website/index.html26
2799 files changed, 226852 insertions, 95056 deletions
diff --git a/.gitignore b/.gitignore
index d7dcc54..5dae434 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,7 @@
# Explicit files to ignore (only matches one).
#==============================================================================#
.gitusers
+autom4te.cache
cscope.files
cscope.out
autoconf/aclocal.m4
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e0404cf..039f619 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -82,7 +82,7 @@ set(LLVM_ALL_TARGETS
)
# List of targets with JIT support:
-set(LLVM_TARGETS_WITH_JIT X86 PowerPC ARM)
+set(LLVM_TARGETS_WITH_JIT X86 PowerPC ARM Mips)
if( MSVC )
set(LLVM_TARGETS_TO_BUILD X86
@@ -181,12 +181,16 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories( ${LLVM_BINARY_DIR}/include ${LLVM_MAIN_INCLUDE_DIR})
if( ${CMAKE_SYSTEM_NAME} MATCHES SunOS )
- SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-include llvm/Support/Solaris.h")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -include llvm/Support/Solaris.h")
endif( ${CMAKE_SYSTEM_NAME} MATCHES SunOS )
include(AddLLVM)
include(TableGen)
+macro(llvm_tablegen)
+ tablegen(LLVM ${ARGN})
+endmacro()
+
if( MINGW )
# People report that -O3 is unreliable on MinGW. The traditional
# build also uses -O2 for that reason:
@@ -195,19 +199,10 @@ endif()
# Put this before tblgen. Else we have a circular dependence.
add_subdirectory(lib/Support)
-
-set(LLVM_TABLEGEN "tblgen" CACHE
- STRING "Native TableGen executable. Saves building one when cross-compiling.")
-# Effective tblgen executable to be used:
-set(LLVM_TABLEGEN_EXE ${LLVM_TABLEGEN})
+add_subdirectory(lib/TableGen)
add_subdirectory(utils/TableGen)
-if( CMAKE_CROSSCOMPILING )
- # This adds a dependency on target `tblgen', so must go after utils/TableGen
- include( CrossCompileLLVM )
-endif( CMAKE_CROSSCOMPILING )
-
add_subdirectory(include/llvm)
add_subdirectory(lib)
diff --git a/CREDITS.TXT b/CREDITS.TXT
index 5ec33be..f201527 100644
--- a/CREDITS.TXT
+++ b/CREDITS.TXT
@@ -32,6 +32,10 @@ E: dberlin@dberlin.org
D: ET-Forest implementation.
D: Sparse bitmap
+N: David Blaikie
+E: dblaikie@gmail.com
+D: General bug fixing/fit & finish, mostly in Clang
+
N: Neil Booth
E: neil@daikokuya.co.uk
D: APFloat implementation.
@@ -241,6 +245,10 @@ E: duraid@octopus.com.au
W: http://kinoko.c.u-tokyo.ac.jp/~duraid/
D: IA64 backend, BigBlock register allocator
+N: John McCall
+E: rjmccall@apple.com
+D: Clang semantic analysis and IR generation
+
N: Michael McCracken
E: michael.mccracken@gmail.com
D: Line number support for llvmgcc
@@ -274,6 +282,8 @@ N: Jakob Stoklund Olesen
E: stoklund@2pi.dk
D: Machine code verifier
D: Blackfin backend
+D: Fast register allocator
+D: Greedy register allocator
N: Richard Osborne
E: richard@xmos.com
diff --git a/Makefile b/Makefile
index 88e63e9..a350cb1 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@
LEVEL := .
# Top-Level LLVM Build Stages:
-# 1. Build lib/Support, which is used by utils (tblgen).
+# 1. Build lib/Support and lib/TableGen, which are used by utils (tblgen).
# 2. Build utils, which is used by VMCore.
# 3. Build VMCore, which builds the Intrinsics.inc file used by libs.
# 4. Build libs, which are needed by llvm-config.
@@ -27,10 +27,10 @@ LEVEL := .
ifneq ($(findstring llvmCore, $(RC_ProjectName)),llvmCore) # Normal build (not "Apple-style").
ifeq ($(BUILD_DIRS_ONLY),1)
- DIRS := lib/Support utils
- OPTIONAL_DIRS :=
+ DIRS := lib/Support lib/TableGen utils
+ OPTIONAL_DIRS := tools/clang/utils/TableGen
else
- DIRS := lib/Support utils lib/VMCore lib tools/llvm-shlib \
+ DIRS := lib/Support lib/TableGen utils lib/VMCore lib tools/llvm-shlib \
tools/llvm-config tools runtime docs unittests
OPTIONAL_DIRS := projects bindings
endif
@@ -118,7 +118,8 @@ cross-compile-build-tools:
unset CFLAGS ; \
unset CXXFLAGS ; \
$(PROJ_SRC_DIR)/configure --build=$(BUILD_TRIPLE) \
- --host=$(BUILD_TRIPLE) --target=$(BUILD_TRIPLE); \
+ --host=$(BUILD_TRIPLE) --target=$(BUILD_TRIPLE) \
+ --disable-polly ; \
cd .. ; \
fi; \
(unset SDKROOT; \
@@ -187,8 +188,7 @@ FilesToConfig := \
include/llvm/Config/AsmPrinters.def \
include/llvm/Config/AsmParsers.def \
include/llvm/Config/Disassemblers.def \
- include/llvm/Support/DataTypes.h \
- tools/llvmc/src/Base.td
+ include/llvm/Support/DataTypes.h
FilesToConfigPATH := $(addprefix $(LLVM_OBJ_ROOT)/,$(FilesToConfig))
all-local:: $(FilesToConfigPATH)
diff --git a/Makefile.config.in b/Makefile.config.in
index 9bdb075..fff482e 100644
--- a/Makefile.config.in
+++ b/Makefile.config.in
@@ -188,30 +188,6 @@ LIBS := @LIBS@
# Targets that we should build
TARGETS_TO_BUILD=@TARGETS_TO_BUILD@
-# Path to location for LLVM C/C++ front-end. You can modify this if you
-# want to override the value set by configure.
-LLVMGCCDIR := @LLVMGCCDIR@
-
-# Full pathnames of LLVM C/C++ front-end 'cc1' and 'cc1plus' binaries:
-LLVMGCC := @LLVMGCC@
-LLVMGXX := @LLVMGXX@
-LLVMCC1 := @LLVMCC1@
-LLVMCC1PLUS := @LLVMCC1PLUS@
-LLVMGCC_LANGS := @LLVMGCC_LANGS@
-LLVMGCC_DRAGONEGG := @LLVMGCC_DRAGONEGG@
-
-# Information on Clang, if configured.
-CLANGPATH := @CLANGPATH@
-CLANGXXPATH := @CLANGXXPATH@
-ENABLE_BUILT_CLANG := @ENABLE_BUILT_CLANG@
-
-# The LLVM capable compiler to use.
-LLVMCC_OPTION := @LLVMCC_OPTION@
-
-# The flag used to emit LLVM IR.
-LLVMCC_EMITIR_FLAG = @LLVMCC_EMITIR_FLAG@
-LLVMCC_DISABLEOPT_FLAGS := @LLVMCC_DISABLEOPT_FLAGS@
-
# Path to directory where object files should be stored during a build.
# Set OBJ_ROOT to "." if you do not want to use a separate place for
# object files.
@@ -338,17 +314,6 @@ endif
# Location of the plugin header file for gold.
BINUTILS_INCDIR := @BINUTILS_INCDIR@
-# When ENABLE_LLVMC_DYNAMIC is enabled, LLVMC will link libCompilerDriver
-# dynamically. This is needed to make dynamic plugins work on some targets
-# (Windows).
-ENABLE_LLVMC_DYNAMIC = 0
-#@ENABLE_LLVMC_DYNAMIC@
-
-# When ENABLE_LLVMC_DYNAMIC_PLUGINS is enabled, LLVMC will have dynamic plugin
-# support (via the -load option).
-ENABLE_LLVMC_DYNAMIC_PLUGINS = 1
-#@ENABLE_LLVMC_DYNAMIC_PLUGINS@
-
# Optional flags supported by the compiler
# -Wno-missing-field-initializers
NO_MISSING_FIELD_INITIALIZERS = @NO_MISSING_FIELD_INITIALIZERS@
diff --git a/Makefile.rules b/Makefile.rules
index 228fd73..d057f04 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -191,19 +191,6 @@ install-local:: all-local
install-bytecode:: install-bytecode-local
###############################################################################
-# LLVMC: Provide rules for compiling llvmc-based driver
-###############################################################################
-
-ifdef LLVMC_BASED_DRIVER
-
-TOOLNAME = $(LLVMC_BASED_DRIVER)
-
-LLVMLIBS = CompilerDriver.a
-LINK_COMPONENTS = support
-
-endif # LLVMC_BASED_DRIVER
-
-###############################################################################
# VARIABLES: Set up various variables based on configuration data
###############################################################################
@@ -463,11 +450,11 @@ Echo = @$(EchoCmd)
ifndef LLVMAS
LLVMAS := $(LLVMToolDir)/llvm-as$(EXEEXT)
endif
-ifndef TBLGEN
+ifndef LLVM_TBLGEN
ifeq ($(LLVM_CROSS_COMPILING),1)
- TBLGEN := $(BuildLLVMToolDir)/tblgen$(BUILD_EXEEXT)
+ LLVM_TBLGEN := $(BuildLLVMToolDir)/llvm-tblgen$(BUILD_EXEEXT)
else
- TBLGEN := $(LLVMToolDir)/tblgen$(EXEEXT)
+ LLVM_TBLGEN := $(LLVMToolDir)/llvm-tblgen$(EXEEXT)
endif
endif
LLVM_CONFIG := $(LLVMToolDir)/llvm-config
@@ -636,7 +623,7 @@ CPP.BaseFlags += -include llvm/Support/Solaris.h
endif # !HOST_OS - AuroraUX.
LD.Flags += -L$(LibDir) -L$(LLVMLibDir)
-CPP.BaseFlags += -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS
+CPP.BaseFlags += -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
# All -I flags should go here, so that they don't confuse llvm-config.
CPP.Flags += $(sort -I$(PROJ_OBJ_DIR) -I$(PROJ_SRC_DIR) \
$(patsubst %,-I%/include,\
@@ -697,10 +684,11 @@ DataInstall = $(INSTALL) -m 0644
# When compiling under Mingw/Cygwin, the tblgen tool expects Windows
# paths. In this case, the SYSPATH function (defined in
# Makefile.config) transforms Unix paths into Windows paths.
-TableGen = $(TBLGEN) -I $(call SYSPATH, $(PROJ_SRC_DIR)) \
+TableGen.Flags= -I $(call SYSPATH, $(PROJ_SRC_DIR)) \
-I $(call SYSPATH, $(LLVM_SRC_ROOT)/include) \
-I $(call SYSPATH, $(PROJ_SRC_ROOT)/include) \
-I $(call SYSPATH, $(PROJ_SRC_ROOT)/lib/Target)
+LLVMTableGen = $(LLVM_TBLGEN) $(TableGen.Flags)
Archive = $(AR) $(AR.Flags)
LArchive = $(LLVMToolDir)/llvm-ar rcsf
@@ -1686,10 +1674,6 @@ ifdef TARGET
TABLEGEN_INC_FILES_COMMON = 1
endif
-ifdef LLVMC_BASED_DRIVER
-TABLEGEN_INC_FILES_COMMON = 1
-endif
-
ifdef TABLEGEN_INC_FILES_COMMON
INCFiles := $(filter %.inc,$(BUILT_SOURCES))
@@ -1717,87 +1701,87 @@ TDFiles := $(strip $(wildcard $(PROJ_SRC_DIR)/*.td) \
$(LLVM_SRC_ROOT)/include/llvm/CodeGen/ValueTypes.td) \
$(wildcard $(LLVM_SRC_ROOT)/include/llvm/Intrinsics*.td)
-# All of these files depend on tblgen and the .td files.
-$(INCTMPFiles) : $(TBLGEN) $(TDFiles)
+# All .inc.tmp files depend on the .td files.
+$(INCTMPFiles) : $(TDFiles)
$(TARGET:%=$(ObjDir)/%GenRegisterInfo.inc.tmp): \
-$(ObjDir)/%GenRegisterInfo.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenRegisterInfo.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) register info implementation with tblgen"
- $(Verb) $(TableGen) -gen-register-info -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-register-info -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenInstrInfo.inc.tmp): \
-$(ObjDir)/%GenInstrInfo.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenInstrInfo.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) instruction information with tblgen"
- $(Verb) $(TableGen) -gen-instr-info -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-instr-info -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenAsmWriter.inc.tmp): \
-$(ObjDir)/%GenAsmWriter.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenAsmWriter.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) assembly writer with tblgen"
- $(Verb) $(TableGen) -gen-asm-writer -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-asm-writer -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenAsmWriter1.inc.tmp): \
-$(ObjDir)/%GenAsmWriter1.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenAsmWriter1.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) assembly writer #1 with tblgen"
- $(Verb) $(TableGen) -gen-asm-writer -asmwriternum=1 -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-asm-writer -asmwriternum=1 -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenAsmMatcher.inc.tmp): \
-$(ObjDir)/%GenAsmMatcher.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenAsmMatcher.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) assembly matcher with tblgen"
- $(Verb) $(TableGen) -gen-asm-matcher -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-asm-matcher -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenMCCodeEmitter.inc.tmp): \
-$(ObjDir)/%GenMCCodeEmitter.inc.tmp: %.td $(ObjDir)/.dir
+$(ObjDir)/%GenMCCodeEmitter.inc.tmp: %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) MC code emitter with tblgen"
- $(Verb) $(TableGen) -gen-emitter -mc-emitter -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-emitter -mc-emitter -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenMCPseudoLowering.inc.tmp): \
-$(ObjDir)/%GenMCPseudoLowering.inc.tmp: %.td $(ObjDir)/.dir
+$(ObjDir)/%GenMCPseudoLowering.inc.tmp: %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) MC Pseudo instruction expander with tblgen"
- $(Verb) $(TableGen) -gen-pseudo-lowering -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-pseudo-lowering -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenCodeEmitter.inc.tmp): \
-$(ObjDir)/%GenCodeEmitter.inc.tmp: %.td $(ObjDir)/.dir
+$(ObjDir)/%GenCodeEmitter.inc.tmp: %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) code emitter with tblgen"
- $(Verb) $(TableGen) -gen-emitter -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-emitter -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenDAGISel.inc.tmp): \
-$(ObjDir)/%GenDAGISel.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenDAGISel.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) DAG instruction selector implementation with tblgen"
- $(Verb) $(TableGen) -gen-dag-isel -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-dag-isel -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenDisassemblerTables.inc.tmp): \
-$(ObjDir)/%GenDisassemblerTables.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenDisassemblerTables.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) disassembly tables with tblgen"
- $(Verb) $(TableGen) -gen-disassembler -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-disassembler -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenEDInfo.inc.tmp): \
-$(ObjDir)/%GenEDInfo.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenEDInfo.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) enhanced disassembly information with tblgen"
- $(Verb) $(TableGen) -gen-enhanced-disassembly-info -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-enhanced-disassembly-info -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenFastISel.inc.tmp): \
-$(ObjDir)/%GenFastISel.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenFastISel.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) \"fast\" instruction selector implementation with tblgen"
- $(Verb) $(TableGen) -gen-fast-isel -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-fast-isel -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenSubtargetInfo.inc.tmp): \
-$(ObjDir)/%GenSubtargetInfo.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenSubtargetInfo.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) subtarget information with tblgen"
- $(Verb) $(TableGen) -gen-subtarget -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-subtarget -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenCallingConv.inc.tmp): \
-$(ObjDir)/%GenCallingConv.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenCallingConv.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) calling convention information with tblgen"
- $(Verb) $(TableGen) -gen-callingconv -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-callingconv -o $(call SYSPATH, $@) $<
$(TARGET:%=$(ObjDir)/%GenIntrinsics.inc.tmp): \
-$(ObjDir)/%GenIntrinsics.inc.tmp : %.td $(ObjDir)/.dir
+$(ObjDir)/%GenIntrinsics.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) intrinsics information with tblgen"
- $(Verb) $(TableGen) -gen-tgt-intrinsic -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-tgt-intrinsic -o $(call SYSPATH, $@) $<
-$(ObjDir)/ARMGenDecoderTables.inc.tmp : ARM.td $(ObjDir)/.dir
+$(ObjDir)/ARMGenDecoderTables.inc.tmp : ARM.td $(ObjDir)/.dir $(LLVM_TBLGEN)
$(Echo) "Building $(<F) decoder tables with tblgen"
- $(Verb) $(TableGen) -gen-arm-decoder -o $(call SYSPATH, $@) $<
+ $(Verb) $(LLVMTableGen) -gen-arm-decoder -o $(call SYSPATH, $@) $<
clean-local::
@@ -1805,27 +1789,6 @@ clean-local::
endif # TARGET
-ifdef LLVMC_BASED_DRIVER
-
-TDSrc := $(sort $(strip $(wildcard $(PROJ_SRC_DIR)/*.td)) \
- $(strip $(wildcard $(PROJ_OBJ_DIR)/*.td)))
-
-TDCommon := $(strip $(wildcard \
- $(LLVM_SRC_ROOT)/include/llvm/CompilerDriver/*.td))
-
-TDFiles := $(TDSrc) $(TDCommon)
-
-$(INCTMPFiles) : $(TBLGEN) $(TDFiles)
-
-$(ObjDir)/%.inc.tmp: %.td $(ObjDir)/.dir
- $(Echo) "Building LLVMC compilation graph description with tblgen"
- $(Verb) $(TableGen) -gen-llvmc -o $(call SYSPATH, $@) $<
-
-clean-local::
- -$(Verb) $(RM) -f $(INCFiles)
-
-endif # LLVMC_BASED_DRIVER
-
###############################################################################
# OTHER RULES: Other rules needed
###############################################################################
diff --git a/README.txt b/README.txt
index 0dad9f5..2ebe271 100644
--- a/README.txt
+++ b/README.txt
@@ -13,4 +13,3 @@ assistance with LLVM.
If you're writing a package for LLVM, see docs/Packaging.html for our
suggestions.
-
diff --git a/autoconf/AutoRegen.sh b/autoconf/AutoRegen.sh
index 7809667..5102aeb 100755
--- a/autoconf/AutoRegen.sh
+++ b/autoconf/AutoRegen.sh
@@ -14,9 +14,9 @@ clean() {
### Periods should be escaped with backslash for use by grep.
###
### If you update these, please also update docs/GettingStarted.html
-want_autoconf_version='2\.60'
+want_autoconf_version='2\.61'
want_autoheader_version=$want_autoconf_version
-want_aclocal_version='1\.9\.6'
+want_aclocal_version='1\.10'
want_libtool_version='1\.5\.22'
### END NOTE #########################################################
diff --git a/autoconf/config.guess b/autoconf/config.guess
index 9807c91..f7dd69e 100755
--- a/autoconf/config.guess
+++ b/autoconf/config.guess
@@ -1,10 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-# Free Software Foundation, Inc.
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+# 2011 Free Software Foundation, Inc.
-timestamp='2009-09-18'
+timestamp='2011-08-20'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -56,8 +56,9 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
+Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -180,7 +181,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
fi
;;
*)
- os=netbsd
+ os=netbsd
;;
esac
# The OS release
@@ -223,7 +224,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
@@ -269,7 +270,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- exit ;;
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ exitcode=$?
+ trap '' 0
+ exit $exitcode ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
@@ -295,7 +299,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo s390-ibm-zvmoe
exit ;;
*:OS400:*:*)
- echo powerpc-ibm-os400
+ echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
@@ -334,8 +338,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
- AUX_ARCH="i386"
- echo ${AUX_ARCH}-pc-auroraux`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo i386-pc-auroraux${UNAME_RELEASE}
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
eval $set_cc_for_build
@@ -395,23 +398,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
+ echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
+ exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
+ echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
- exit ;;
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
- exit ;;
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
- exit ;;
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
m68k:machten:*:*)
echo m68k-apple-machten${UNAME_RELEASE}
exit ;;
@@ -481,8 +484,8 @@ EOF
echo m88k-motorola-sysv3
exit ;;
AViiON:dgux:*:*)
- # DG/UX returns AViiON for all architectures
- UNAME_PROCESSOR=`/usr/bin/uname -p`
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
@@ -495,7 +498,7 @@ EOF
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
- exit ;;
+ exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
@@ -552,7 +555,7 @@ EOF
echo rs6000-ibm-aix3.2
fi
exit ;;
- *:AIX:*:[456])
+ *:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
@@ -595,52 +598,52 @@ EOF
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
- 532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
- esac ;;
- esac
+ esac ;;
+ esac
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ sed 's/^ //' << EOF >$dummy.c
- #define _HPUX_SOURCE
- #include <stdlib.h>
- #include <unistd.h>
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
- int main ()
- {
- #if defined(_SC_KERNEL_BITS)
- long bits = sysconf(_SC_KERNEL_BITS);
- #endif
- long cpu = sysconf (_SC_CPU_VERSION);
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
- case CPU_PA_RISC2_0:
- #if defined(_SC_KERNEL_BITS)
- switch (bits)
- {
- case 64: puts ("hppa2.0w"); break;
- case 32: puts ("hppa2.0n"); break;
- default: puts ("hppa2.0"); break;
- } break;
- #else /* !defined(_SC_KERNEL_BITS) */
- puts ("hppa2.0"); break;
- #endif
- default: puts ("hppa1.0"); break;
- }
- exit (0);
- }
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
EOF
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
@@ -731,22 +734,22 @@ EOF
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
- exit ;;
+ exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
- exit ;;
+ exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
- exit ;;
+ exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
- exit ;;
+ exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
- exit ;;
+ exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
@@ -770,14 +773,14 @@ EOF
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
@@ -789,8 +792,8 @@ EOF
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:FreeBSD:*:*)
- UNAME_PROCESSOR=`/usr/bin/uname -p`
- case ${UNAME_MACHINE} in
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case ${UNAME_PROCESSOR} in
amd64)
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
*)
@@ -804,18 +807,18 @@ EOF
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
i*:windows32*:*)
- # uname -m includes "-pc" on this system.
- echo ${UNAME_MACHINE}-mingw32
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
exit ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
- *:Interix*:[3456]*)
- case ${UNAME_MACHINE} in
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
x86)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
- EM64T | authenticamd | genuineintel)
+ authenticamd | genuineintel | EM64T)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
IA64)
@@ -866,7 +869,7 @@ EOF
EV6) UNAME_MACHINE=alphaev6 ;;
EV67) UNAME_MACHINE=alphaev67 ;;
EV68*) UNAME_MACHINE=alphaev68 ;;
- esac
+ esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
@@ -878,7 +881,13 @@ EOF
then
echo ${UNAME_MACHINE}-unknown-linux-gnu
else
- echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+ fi
fi
exit ;;
avr32*:Linux:*:*)
@@ -891,10 +900,18 @@ EOF
echo crisv32-axis-linux-gnu
exit ;;
frv:Linux:*:*)
- echo frv-unknown-linux-gnu
+ echo frv-unknown-linux-gnu
exit ;;
i*86:Linux:*:*)
- echo ${UNAME_MACHINE}-pc-linux-gnu
+ LIBC=gnu
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
@@ -921,11 +938,7 @@ EOF
#endif
#endif
EOF
- eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
- /^CPU/{
- s: ::g
- p
- }'`"
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
or32:Linux:*:*)
@@ -955,7 +968,7 @@ EOF
echo ${UNAME_MACHINE}-ibm-linux
exit ;;
sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
@@ -963,6 +976,9 @@ EOF
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
+ tile*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-gnu
exit ;;
@@ -970,7 +986,7 @@ EOF
echo x86_64-unknown-linux-gnu
exit ;;
xtensa*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -979,11 +995,11 @@ EOF
echo i386-sequent-sysv4
exit ;;
i*86:UNIX_SV:4.2MP:2.*)
- # Unixware is an offshoot of SVR4, but it has its own version
- # number series starting with 2...
- # I am not positive that other SVR4 systems won't match this,
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
- # Use sysv4.2uw... so that sysv4* matches it.
+ # Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit ;;
i*86:OS/2:*:*)
@@ -1015,7 +1031,7 @@ EOF
fi
exit ;;
i*86:*:5:[678]*)
- # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
@@ -1043,13 +1059,13 @@ EOF
exit ;;
pc:*:*:*)
# Left here for compatibility:
- # uname -m prints for DJGPP always 'pc', but it prints nothing about
- # the processor, so we play safe by assuming i586.
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configury will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
- exit ;;
+ exit ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit ;;
@@ -1084,8 +1100,8 @@ EOF
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4; exit; } ;;
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
test -r /etc/.relid \
@@ -1128,10 +1144,10 @@ EOF
echo ns32k-sni-sysv
fi
exit ;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
- # says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
@@ -1157,11 +1173,11 @@ EOF
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
+ echo mips-nec-sysv${UNAME_RELEASE}
else
- echo mips-unknown-sysv${UNAME_RELEASE}
+ echo mips-unknown-sysv${UNAME_RELEASE}
fi
- exit ;;
+ exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit ;;
@@ -1226,6 +1242,9 @@ EOF
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
+ NEO-?:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk${UNAME_RELEASE}
+ exit ;;
NSE-?:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
@@ -1271,13 +1290,13 @@ EOF
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
+ echo mips-sei-seiux${UNAME_RELEASE}
exit ;;
*:DragonFly:*:*)
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit ;;
*:*VMS:*:*)
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
case "${UNAME_MACHINE}" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
@@ -1317,11 +1336,11 @@ main ()
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
- "4"
+ "4"
#else
- ""
+ ""
#endif
- ); exit (0);
+ ); exit (0);
#endif
#endif
diff --git a/autoconf/config.sub b/autoconf/config.sub
index 183976a..da19a88 100755
--- a/autoconf/config.sub
+++ b/autoconf/config.sub
@@ -1,10 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-# Free Software Foundation, Inc.
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+# 2011 Free Software Foundation, Inc.
-timestamp='2009-08-19'
+timestamp='2011-08-23'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -75,8 +75,9 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
+Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -123,8 +124,9 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
- nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
- uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
@@ -156,8 +158,8 @@ case $os in
os=
basic_machine=$1
;;
- -bluegene*)
- os=-cnk
+ -bluegene*)
+ os=-cnk
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
@@ -173,10 +175,10 @@ case $os in
os=-chorusos
basic_machine=$1
;;
- -chorusrdb)
- os=-chorusrdb
+ -chorusrdb)
+ os=-chorusrdb
basic_machine=$1
- ;;
+ ;;
-hiux*)
os=-hiuxwe2
;;
@@ -249,6 +251,7 @@ case $basic_machine in
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | be32 | be64 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
@@ -256,6 +259,7 @@ case $basic_machine in
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
+ | le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore | mep | metag \
@@ -281,26 +285,39 @@ case $basic_machine in
| moxie \
| mt \
| msp430 \
+ | nds32 | nds32le | nds32be \
| nios | nios2 \
| ns16k | ns32k \
+ | open8 \
| or32 \
| pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
+ | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
- | spu | strongarm \
- | tahoe | thumb | tic4x | tic80 | tron \
- | v850 | v850e \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
- | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
- m6811 | m68hc11 | m6812 | m68hc12)
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | picochip)
# Motorola 68HC11/12.
basic_machine=$basic_machine-unknown
os=-none
@@ -311,6 +328,18 @@ case $basic_machine in
basic_machine=mt-unknown
;;
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
@@ -330,8 +359,9 @@ case $basic_machine in
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
+ | be32-* | be64-* \
| bfin-* | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
@@ -340,6 +370,7 @@ case $basic_machine in
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
+ | le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
@@ -365,24 +396,29 @@ case $basic_machine in
| mmix-* \
| mt-* \
| msp430-* \
+ | nds32-* | nds32le-* | nds32be-* \
| nios-* | nios2-* \
| none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
- | romp-* | rs6000-* \
+ | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
- | tahoe-* | thumb-* \
- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+ | tahoe-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
| tron-* \
- | v850-* | v850e-* | vax-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
| we32k-* \
- | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-* | z80-*)
@@ -407,7 +443,7 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
- abacus)
+ abacus)
basic_machine=abacus-unknown
;;
adobe68k)
@@ -477,11 +513,20 @@ case $basic_machine in
basic_machine=powerpc-ibm
os=-cnk
;;
+ c54x-*)
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
c90)
basic_machine=c90-cray
os=-unicos
;;
- cegcc)
+ cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
@@ -513,7 +558,7 @@ case $basic_machine in
basic_machine=craynv-cray
os=-unicosmp
;;
- cr16)
+ cr16 | cr16-*)
basic_machine=cr16-unknown
os=-elf
;;
@@ -729,7 +774,7 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
- microblaze)
+ microblaze)
basic_machine=microblaze-xilinx
;;
mingw32)
@@ -772,6 +817,10 @@ case $basic_machine in
basic_machine=i370-ibm
os=-mvs
;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
@@ -836,6 +885,12 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@@ -918,9 +973,10 @@ case $basic_machine in
;;
power) basic_machine=power-ibm
;;
- ppc) basic_machine=powerpc-unknown
+ ppc | ppcbe) basic_machine=powerpc-unknown
;;
- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
@@ -1014,6 +1070,9 @@ case $basic_machine in
basic_machine=i860-stratus
os=-sysv4
;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
sun2)
basic_machine=m68000-sun
;;
@@ -1070,20 +1129,8 @@ case $basic_machine in
basic_machine=t90-cray
os=-unicos
;;
- tic54x | c54x*)
- basic_machine=tic54x-unknown
- os=-coff
- ;;
- tic55x | c55x*)
- basic_machine=tic55x-unknown
- os=-coff
- ;;
- tic6x | c6x*)
- basic_machine=tic6x-unknown
- os=-coff
- ;;
tile*)
- basic_machine=tile-unknown
+ basic_machine=$basic_machine-unknown
os=-linux-gnu
;;
tx39)
@@ -1153,6 +1200,9 @@ case $basic_machine in
xps | xps100)
basic_machine=xps100-honeywell
;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ;;
ymp)
basic_machine=ymp-cray
os=-unicos
@@ -1250,15 +1300,15 @@ esac
if [ x"$os" != x"" ]
then
case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
+ # First match some system type aliases
+ # that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
- -solaris1 | -solaris1.*)
- os=`echo $os | sed -e 's|solaris1|sunos4|'`
- ;;
-auroraux)
os=-auroraux
;;
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
-solaris)
os=-solaris2
;;
@@ -1277,8 +1327,8 @@ case $os in
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* | -sym* \
- | -kopensolaris* \
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
@@ -1291,7 +1341,8 @@ case $os in
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -mingw32* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
@@ -1299,7 +1350,7 @@ case $os in
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1338,7 +1389,7 @@ case $os in
-opened*)
os=-openedition
;;
- -os400*)
+ -os400*)
os=-os400
;;
-wince*)
@@ -1387,7 +1438,7 @@ case $os in
-sinix*)
os=-sysv4
;;
- -tpf*)
+ -tpf*)
os=-tpf
;;
-triton*)
@@ -1432,6 +1483,8 @@ case $os in
-dicos*)
os=-dicos
;;
+ -nacl*)
+ ;;
-none)
;;
*)
@@ -1454,10 +1507,10 @@ else
# system, and we'll never get to this point.
case $basic_machine in
- score-*)
+ score-*)
os=-elf
;;
- spu-*)
+ spu-*)
os=-elf
;;
*-acorn)
@@ -1469,8 +1522,17 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
- c4x-* | tic4x-*)
- os=-coff
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1497,7 +1559,7 @@ case $basic_machine in
m68*-cisco)
os=-aout
;;
- mep-*)
+ mep-*)
os=-elf
;;
mips*-cisco)
@@ -1524,7 +1586,7 @@ case $basic_machine in
*-ibm)
os=-aix
;;
- *-knuth)
+ *-knuth)
os=-mmixware
;;
*-wec)
diff --git a/autoconf/configure.ac b/autoconf/configure.ac
index 3c3ddaa..a4ccfcd 100644
--- a/autoconf/configure.ac
+++ b/autoconf/configure.ac
@@ -31,16 +31,15 @@ dnl===
dnl===-----------------------------------------------------------------------===
dnl Initialize autoconf and define the package name, version number and
dnl email address for reporting bugs.
-AC_INIT([[llvm]],[[3.0svn]],[llvmbugs@cs.uiuc.edu])
+AC_INIT([[llvm]],[[3.0]],[llvmbugs@cs.uiuc.edu])
dnl Provide a copyright substitution and ensure the copyright notice is included
dnl in the output of --version option of the generated configure script.
AC_SUBST(LLVM_COPYRIGHT,["Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign."])
AC_COPYRIGHT([Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign.])
-dnl Indicate that we require autoconf 2.59 or later. Ths is needed because we
-dnl use some autoconf macros only available in 2.59.
-AC_PREREQ(2.59)
+dnl Indicate that we require autoconf 2.60 or later.
+AC_PREREQ(2.60)
dnl Verify that the source directory is valid. This makes sure that we are
dnl configuring LLVM and not some other package (it validates --srcdir argument)
@@ -58,6 +57,12 @@ if test ${srcdir} != "." ; then
fi
fi
+dnl We need to check for the compiler up here to avoid anything else
+dnl starting with a different one.
+AC_PROG_CC(clang llvm-gcc gcc)
+AC_PROG_CXX(clang++ llvm-g++ g++)
+AC_PROG_CPP
+
dnl Configure all of the projects present in our source tree. While we could
dnl just AC_CONFIG_SUBDIRS on the set of directories in projects that have a
dnl configure script, that usage of the AC_CONFIG_SUBDIRS macro is deprecated.
@@ -299,6 +304,8 @@ AC_CACHE_CHECK([type of operating system we're going to target],
llvm_cv_target_os_type="Haiku" ;;
*-*-rtems*)
llvm_cv_target_os_type="RTEMS" ;;
+ *-*-nacl*)
+ llvm_cv_target_os_type="NativeClient" ;;
*-unknown-eabi*)
llvm_cv_target_os_type="Freestanding" ;;
*)
@@ -413,7 +420,7 @@ dnl===-----------------------------------------------------------------------===
dnl --enable-optimized : check whether they want to do an optimized build:
AC_ARG_ENABLE(optimized, AS_HELP_STRING(
- --enable-optimized,[Compile with optimizations enabled (default is NO)]),,enableval=$optimize)
+ --enable-optimized,[Compile with optimizations enabled (default is YES)]),,enableval=$optimize)
if test ${enableval} = "no" ; then
AC_SUBST(ENABLE_OPTIMIZED,[[]])
else
@@ -431,7 +438,7 @@ fi
dnl --enable-assertions : check whether they want to turn on assertions or not:
AC_ARG_ENABLE(assertions,AS_HELP_STRING(
- --enable-assertions,[Compile with assertion checks enabled (default is YES)]),, enableval="yes")
+ --enable-assertions,[Compile with assertion checks enabled (default is NO)]),, enableval="no")
if test ${enableval} = "yes" ; then
AC_SUBST(DISABLE_ASSERTIONS,[[]])
else
@@ -484,7 +491,7 @@ else
x86_64) AC_SUBST(TARGET_HAS_JIT,1) ;;
Alpha) AC_SUBST(TARGET_HAS_JIT,0) ;;
ARM) AC_SUBST(TARGET_HAS_JIT,1) ;;
- Mips) AC_SUBST(TARGET_HAS_JIT,0) ;;
+ Mips) AC_SUBST(TARGET_HAS_JIT,1) ;;
XCore) AC_SUBST(TARGET_HAS_JIT,0) ;;
MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;;
SystemZ) AC_SUBST(TARGET_HAS_JIT,0) ;;
@@ -573,12 +580,12 @@ esac
dnl Allow libstdc++ is embedded in LLVM.dll.
AC_ARG_ENABLE(embed-stdcxx,
AS_HELP_STRING([--enable-embed-stdcxx],
- [Build a shared library with embedded libstdc++ for Win32 DLL (default is YES)]),,
+ [Build a shared library with embedded libstdc++ for Win32 DLL (default is NO)]),,
enableval=default)
case "$enableval" in
yes) AC_SUBST(ENABLE_EMBED_STDCXX,[1]) ;;
no) AC_SUBST(ENABLE_EMBED_STDCXX,[0]) ;;
- default) AC_SUBST(ENABLE_EMBED_STDCXX,[1]) ;;
+ default) AC_SUBST(ENABLE_EMBED_STDCXX,[0]) ;;
*) AC_MSG_ERROR([Invalid setting for --enable-embed-stdcxx. Use "yes" or "no"]) ;;
esac
@@ -658,7 +665,7 @@ for a_target in $TARGETS_TO_BUILD; do
[LLVM architecture name for the native architecture, if available])
LLVM_NATIVE_TARGET="LLVMInitialize${LLVM_NATIVE_ARCH}Target"
LLVM_NATIVE_TARGETINFO="LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo"
- LLVM_NATIVE_MCASMINFO="LLVMInitialize${LLVM_NATIVE_ARCH}MCAsmInfo"
+ LLVM_NATIVE_TARGETMC="LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC"
LLVM_NATIVE_ASMPRINTER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter"
if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/AsmParser/Makefile ; then
LLVM_NATIVE_ASMPARSER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser"
@@ -667,8 +674,8 @@ for a_target in $TARGETS_TO_BUILD; do
[LLVM name for the native Target init function, if available])
AC_DEFINE_UNQUOTED(LLVM_NATIVE_TARGETINFO, $LLVM_NATIVE_TARGETINFO,
[LLVM name for the native TargetInfo init function, if available])
- AC_DEFINE_UNQUOTED(LLVM_NATIVE_MCASMINFO, $LLVM_NATIVE_MCASMINFO,
- [LLVM name for the native MCAsmInfo init function, if available])
+ AC_DEFINE_UNQUOTED(LLVM_NATIVE_TARGETMC, $LLVM_NATIVE_TARGETMC,
+ [LLVM name for the native target MC init function, if available])
AC_DEFINE_UNQUOTED(LLVM_NATIVE_ASMPRINTER, $LLVM_NATIVE_ASMPRINTER,
[LLVM name for the native AsmPrinter init function, if available])
if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/AsmParser/Makefile ; then
@@ -716,97 +723,6 @@ esac
AC_DEFINE_UNQUOTED([ENABLE_CBE_PRINTF_A],$ENABLE_CBE_PRINTF_A,
[Define if CBE is enabled for printf %a output])
-dnl Allow a specific llvm-gcc/llvm-g++ pair to be used with this LLVM config.
-AC_ARG_WITH(llvmgccdir,
- AS_HELP_STRING([--with-llvmgccdir],
- [Specify location of llvm-gcc install dir (default searches PATH)]),,
- withval=default)
-case "$withval" in
- default) WITH_LLVMGCCDIR=default ;;
- /* | [[A-Za-z]]:[[\\/]]*) WITH_LLVMGCCDIR=$withval ;;
- *) AC_MSG_ERROR([Invalid path for --with-llvmgccdir. Provide full path]) ;;
-esac
-
-dnl Allow a specific llvm-gcc compiler to be used with this LLVM config.
-AC_ARG_WITH(llvmgcc,
- AS_HELP_STRING([--with-llvmgcc],
- [Specify location of llvm-gcc driver (default searches PATH)]),
- LLVMGCC=$with_llvmgcc
- WITH_LLVMGCCDIR="",)
-
-dnl Allow a specific llvm-g++ compiler to be used with this LLVM config.
-AC_ARG_WITH(llvmgxx,
- AS_HELP_STRING([--with-llvmgxx],
- [Specify location of llvm-g++ driver (default searches PATH)]),
- LLVMGXX=$with_llvmgxx
- WITH_LLVMGCCDIR="",)
-
-if test -n "$LLVMGCC"; then
- LLVMGCCCOMMAND="$LLVMGCC"
-fi
-
-if test -n "$LLVMGXX"; then
- LLVMGXXCOMMAND="$LLVMGXX"
-fi
-
-if test -n "$LLVMGCC" && test -z "$LLVMGXX"; then
- AC_MSG_ERROR([Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used]);
-fi
-
-if test -n "$LLVMGXX" && test -z "$LLVMGCC"; then
- AC_MSG_ERROR([Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is used]);
-fi
-
-dnl Allow a specific Clang compiler to be used with this LLVM config.
-AC_ARG_WITH(clang,
- AS_HELP_STRING([--with-clang],
- [Specify location of clang compiler (default is --with-built-clang)]),
- [],[with_clang=default])
-
-dnl Enable use of the built Clang.
-AC_ARG_WITH(built-clang,
- AS_HELP_STRING([--with-built-clang],
- [Use the compiled Clang as the LLVM compiler (default=check)]),
- [],[with_built_clang=check])
-
-dnl Select the Clang compiler option.
-dnl
-dnl If --with-clang is given, always honor that; otherwise honor
-dnl --with-built-clang, or check if we have the clang sources.
-AC_MSG_CHECKING([clang compiler])
-WITH_CLANGPATH=""
-WITH_BUILT_CLANG=0
-if test "$with_clang" != "default"; then
- WITH_CLANGPATH="$with_clang"
- if ! test -x "$WITH_CLANGPATH"; then
- AC_MSG_ERROR([invalid --with-clang, path does not specify an executable])
- fi
-elif test "$with_built_clang" = "yes"; then
- WITH_BUILT_CLANG=1
-elif test "$with_built_clang" = "no"; then
- WITH_BUILT_CLANG=0
-else
- if test "$with_built_clang" != "check"; then
- AC_MSG_ERROR([invalid value for --with-built-clang.])
- fi
-
- if test -f ${srcdir}/tools/clang/README.txt; then
- WITH_BUILT_CLANG=1
- fi
-fi
-
-if ! test -z "$WITH_CLANGPATH"; then
- AC_MSG_RESULT([$WITH_CLANGPATH])
- WITH_CLANGXXPATH=`"$WITH_CLANGPATH" --print-prog-name=clang++`
-elif test "$WITH_BUILT_CLANG" = "1"; then
- AC_MSG_RESULT([built])
-else
- AC_MSG_RESULT([none])
-fi
-AC_SUBST(CLANGPATH,$WITH_CLANGPATH)
-AC_SUBST(CLANGXXPATH,$WITH_CLANGXXPATH)
-AC_SUBST(ENABLE_BUILT_CLANG,$WITH_BUILT_CLANG)
-
dnl Override the option to use for optimized builds.
AC_ARG_WITH(optimize-option,
AS_HELP_STRING([--with-optimize-option],
@@ -942,8 +858,8 @@ fi
dnl Specify the URL where bug reports should be submitted.
AC_ARG_WITH(bug-report-url,
AS_HELP_STRING([--with-bug-report-url],
- [Specify the URL where bug reports should be submitted (default=http://llvm.org)]),,
- withval="http://llvm.org")
+ [Specify the URL where bug reports should be submitted (default=http://llvm.org/bugs/)]),,
+ withval="http://llvm.org/bugs/")
AC_DEFINE_UNQUOTED(BUG_REPORT_URL,"$withval",
[Bug report URL.])
@@ -963,11 +879,6 @@ dnl=== SECTION 4: Check for programs we need and that they are the right version
dnl===
dnl===-----------------------------------------------------------------------===
-dnl Check for compilation tools
-AC_PROG_CPP
-AC_PROG_CC(gcc)
-AC_PROG_CXX(g++)
-
AC_PROG_NM
AC_SUBST(NM)
@@ -1139,55 +1050,6 @@ dnl libtool).
AC_LIBTOOL_DLOPEN
AC_LIB_LTDL
-if test "$WITH_LLVMGCCDIR" = "default" ; then
- LLVMGCC="llvm-gcc${EXEEXT}"
- LLVMGXX="llvm-g++${EXEEXT}"
- LLVMGCCCOMMAND="$LLVMGCC"
- LLVMGXXCOMMAND="$LLVMGXX"
- AC_SUBST(LLVMGCCCOMMAND,$LLVMGCCCOMMAND)
- AC_SUBST(LLVMGXXCOMMAND,$LLVMGXXCOMMAND)
- AC_PATH_PROG(LLVMGCC, $LLVMGCC, [])
- AC_PATH_PROG(LLVMGXX, $LLVMGXX, [])
-else
- if test -z "$LLVMGCC"; then
- LLVMGCC="$WITH_LLVMGCCDIR/bin/llvm-gcc${EXEEXT}"
- LLVMGCCCOMMAND="$LLVMGCC"
- fi
- if test -z "$LLVMGXX"; then
- LLVMGXX="$WITH_LLVMGCCDIR/bin/llvm-g++${EXEEXT}"
- LLVMGXXCOMMAND="$LLVMGXX"
- fi
-
- AC_SUBST(LLVMGCC,$LLVMGCC)
- AC_SUBST(LLVMGXX,$LLVMGXX)
- AC_SUBST(LLVMGCCCOMMAND,$LLVMGCCCOMMAND)
- AC_SUBST(LLVMGXXCOMMAND,$LLVMGXXCOMMAND)
-fi
-
-dnl Select the LLVM capable compiler to use, we default to using llvm-gcc if
-dnl found, otherwise clang if available.
-AC_ARG_WITH(llvmcc,
- AS_HELP_STRING([--with-llvmcc=<name>],
- [Choose the LLVM capable compiler to use (llvm-gcc, clang, or none; default=check)]),
- [],[with_llvmcc=check])
-AC_MSG_CHECKING([LLVM capable compiler])
-if test "$with_llvmcc" != "check"; then
- if (test "$with_llvmcc" != "llvm-gcc" &&
- test "$with_llvmcc" != "clang" &&
- test "$with_llvmcc" != "none"); then
- AC_MSG_ERROR([invalid value for --with-llvmcc, expected 'llvm-gcc', 'clang', or 'none'.])
- fi
- WITH_LLVMCC="$with_llvmcc"
-elif test -n "$LLVMGCC"; then
- WITH_LLVMCC=llvm-gcc
-elif test -n "$WITH_CLANGPATH" || test "$WITH_BUILT_CLANG" -ne "0"; then
- WITH_LLVMCC=clang
-else
- WITH_LLVMCC=none
-fi
-AC_MSG_RESULT([$WITH_LLVMCC])
-AC_SUBST(LLVMCC_OPTION,$WITH_LLVMCC)
-
AC_MSG_CHECKING([tool compatibility])
dnl Ensure that compilation tools are GCC or a GNU compatible compiler such as
@@ -1352,7 +1214,6 @@ dnl Generally we're looking for POSIX headers.
AC_HEADER_DIRENT
AC_HEADER_MMAP_ANONYMOUS
AC_HEADER_STAT
-AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_HEADER_TIME
@@ -1512,9 +1373,9 @@ AC_LINK_IFELSE(
]]),
AC_LANG_POP([C++])
AC_MSG_RESULT(yes)
- AC_DEFINE(LLVM_MULTITHREADED, 1, Build multithreading support into LLVM),
+ AC_DEFINE(LLVM_HAS_ATOMICS, 1, Has gcc/MSVC atomic intrinsics),
AC_MSG_RESULT(no)
- AC_DEFINE(LLVM_MULTITHREADED, 0, Build multithreading support into LLVM)
+ AC_DEFINE(LLVM_HAS_ATOMICS, 0, Has gcc/MSVC atomic intrinsics)
AC_MSG_WARN([LLVM will be built thread-unsafe because atomic builtins are missing]))
dnl===-----------------------------------------------------------------------===
@@ -1533,63 +1394,9 @@ if test "$llvm_cv_os_type" = "Linux" -a "$llvm_cv_target_arch" = "x86_64" ; then
fi
fi
-dnl Check, whether __dso_handle is present
+dnl Check whether __dso_handle is present
AC_CHECK_FUNCS([__dso_handle])
-dnl Check wether llvm-gcc is based on dragonegg
-AC_CACHE_CHECK([whether llvm-gcc is dragonegg],[llvm_cv_llvmgcc_dragonegg],
-[llvm_cv_llvmgcc_dragonegg="no"
-if test -n "$LLVMGCC" ; then
- cp /dev/null conftest.c
- $LLVMGCC -fplugin-arg-dragonegg-emit-ir -S -o - conftest.c > /dev/null 2>&1
- if test $? -eq 0 ; then
- llvm_cv_llvmgcc_dragonegg="yes"
- fi
- rm conftest.c
-fi])
-
-dnl Set the flags needed to emit LLVM IR and to disable optimizations
-dnl in llvmgcc
-if test "$llvm_cv_llvmgcc_dragonegg" = "yes" ; then
- LLVMCC_EMITIR_FLAG="-fplugin-arg-dragonegg-emit-ir"
- LLVMCC_DISABLEOPT_FLAGS="-fplugin-arg-dragonegg-llvm-ir-optimize=0"
-else
- LLVMCC_EMITIR_FLAG="-emit-llvm"
- LLVMCC_DISABLEOPT_FLAGS="-mllvm -disable-llvm-optzns"
-fi
-
-AC_SUBST(LLVMCC_EMITIR_FLAG)
-
-dnl See if the llvm-gcc executable can compile to LLVM assembly
-AC_CACHE_CHECK([whether llvm-gcc is sane],[llvm_cv_llvmgcc_sanity],
-[llvm_cv_llvmgcc_sanity="no"
-if test -n "$LLVMGCC" ; then
- cp /dev/null conftest.c
- $LLVMGCC "$LLVMCC_EMITIR_FLAG" -S -o - conftest.c | \
- grep 'target datalayout =' > /dev/null 2>&1
- if test $? -eq 0 ; then
- llvm_cv_llvmgcc_sanity="yes"
- fi
- rm conftest.c
-fi])
-
-dnl Since we have a sane llvm-gcc, identify it and its sub-tools
-dnl Furthermore, add some information about the tools
-if test "$llvm_cv_llvmgcc_sanity" = "yes" ; then
- AC_MSG_CHECKING([llvm-gcc component support])
- llvmcc1path=`$LLVMGCC --print-prog-name=cc1`
- AC_SUBST(LLVMCC1,$llvmcc1path)
- llvmcc1pluspath=`$LLVMGCC --print-prog-name=cc1plus`
- AC_SUBST(LLVMCC1PLUS,$llvmcc1pluspath)
- llvmgccdir=`echo "$llvmcc1path" | sed 's,/libexec/.*,,'`
- AC_SUBST(LLVMGCCDIR,$llvmgccdir)
- llvmgcclangs=[`$LLVMGCC -v --help 2>&1 | grep '^Configured with:' | sed 's/^.*--enable-languages=\([^ ]*\).*/\1/'`]
- AC_SUBST(LLVMGCC_LANGS,$llvmgcclangs)
- AC_SUBST(LLVMGCC_DRAGONEGG,$llvm_cv_llvmgcc_dragonegg)
- AC_SUBST(LLVMCC_DISABLEOPT_FLAGS)
- AC_MSG_RESULT([ok])
-fi
-
dnl Propagate the shared library extension that the libltdl checks did to
dnl the Makefiles so we can use it there too
AC_SUBST(SHLIBEXT,$libltdl_cv_shlibext)
@@ -1753,12 +1560,12 @@ if test -f ${srcdir}/tools/clang/README.txt; then
AC_CONFIG_FILES([tools/clang/docs/doxygen.cfg])
fi
-dnl Configure llvmc's Base plugin
-AC_CONFIG_FILES([tools/llvmc/src/Base.td])
-
dnl Do the first stage of configuration for llvm-config.in.
AC_CONFIG_FILES([tools/llvm-config/llvm-config.in])
+dnl OCaml findlib META file
+AC_CONFIG_FILES([bindings/ocaml/llvm/META.llvm])
+
dnl Do special configuration of Makefiles
AC_CONFIG_COMMANDS([setup],,[llvm_src="${srcdir}"])
AC_CONFIG_MAKEFILE(Makefile)
diff --git a/bindings/ocaml/llvm/META.llvm.in b/bindings/ocaml/llvm/META.llvm.in
new file mode 100644
index 0000000..29e7eb4
--- /dev/null
+++ b/bindings/ocaml/llvm/META.llvm.in
@@ -0,0 +1,63 @@
+name = "llvm"
+version = "@PACKAGE_VERSION@"
+description = "Low Level Virtual Machine OCaml bindings"
+archive(byte) = "llvm.cma"
+archive(native) = "llvm.cmxa"
+directory = "."
+linkopts = "-ccopt -lstdc++"
+
+package "analysis" (
+ requires = "llvm"
+ version = "@PACKAGE_VERSION@"
+ description = "Intermediate representation analysis for LLVM"
+ archive(byte) = "llvm_analysis.cma"
+ archive(native) = "llvm_analysis.cmxa"
+)
+
+package "bitreader" (
+ requires = "llvm"
+ version = "@PACKAGE_VERSION@"
+ description = "Bitcode reader for LLVM"
+ archive(byte) = "llvm_bitreader.cma"
+ archive(native) = "llvm_bitreader.cmxa"
+)
+
+package "bitwriter" (
+ requires = "llvm,unix"
+ version = "@PACKAGE_VERSION@"
+ description = "Bitcode writer for LLVM"
+ archive(byte) = "llvm_bitwriter.cma"
+ archive(native) = "llvm_bitwriter.cmxa"
+)
+
+package "executionengine" (
+ requires = "llvm,llvm.target"
+ version = "@PACKAGE_VERSION@"
+ description = "JIT and Interpreter for LLVM"
+ archive(byte) = "llvm_executionengine.cma"
+ archive(native) = "llvm_executionengine.cmxa"
+)
+
+package "ipo" (
+ requires = "llvm"
+ version = "@PACKAGE_VERSION@"
+ description = "IPO Transforms for LLVM"
+ archive(byte) = "llvm_ipo.cma"
+ archive(native) = "llvm_ipo.cmxa"
+)
+
+package "scalar_opts" (
+ requires = "llvm"
+ version = "@PACKAGE_VERSION@"
+ description = "Scalar Transforms for LLVM"
+ archive(byte) = "llvm_scalar_opts.cma"
+ archive(native) = "llvm_scalar_opts.cmxa"
+)
+
+package "target" (
+ requires = "llvm"
+ version = "@PACKAGE_VERSION@"
+ description = "Target Information for LLVM"
+ archive(byte) = "llvm_target.cma"
+ archive(native) = "llvm_target.cmxa"
+)
diff --git a/bindings/ocaml/llvm/Makefile b/bindings/ocaml/llvm/Makefile
index 99e347b..673eaa2 100644
--- a/bindings/ocaml/llvm/Makefile
+++ b/bindings/ocaml/llvm/Makefile
@@ -17,3 +17,24 @@ UsedComponents := core
UsedOcamLibs := llvm
include ../Makefile.ocaml
+
+all-local:: copy-meta
+install-local:: install-meta
+uninstall-local:: uninstall-meta
+
+DestMETA := $(PROJ_libocamldir)/META.llvm
+
+# Easy way of generating META in the objdir
+copy-meta: $(OcamlDir)/META.llvm
+
+$(OcamlDir)/META.llvm: META.llvm
+ $(Verb) $(CP) -f $< $@
+
+install-meta:: $(ObjDir)/META.llvm
+ $(Echo) "Install $(BuildMode) $(DestMETA)"
+ $(Verb) $(MKDIR) $(PROJ_libocamldir)
+ $(Verb) $(DataInstall) META.llvm "$(DestMETA)"
+
+uninstall-meta::
+ $(Echo) "Uninstalling $(DestMETA)"
+ -$(Verb) $(RM) -f "$(DestMETA)"
diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml
index a62ba37..40b0138 100644
--- a/bindings/ocaml/llvm/llvm.ml
+++ b/bindings/ocaml/llvm/llvm.ml
@@ -94,6 +94,9 @@ module Attribute = struct
| Naked
| Inlinehint
| Stackalignment of int
+ | ReturnsTwice
+ | UWTable
+ | NonLazyBind
end
module Icmp = struct
@@ -130,6 +133,101 @@ module Fcmp = struct
| True
end
+module Opcode = struct
+ type t =
+ | Invalid (* not an instruction *)
+ (* Terminator Instructions *)
+ | Ret
+ | Br
+ | Switch
+ | IndirectBr
+ | Invoke
+ | Invalid2
+ | Unreachable
+ (* Standard Binary Operators *)
+ | Add
+ | FAdd
+ | Sub
+ | FSub
+ | Mul
+ | FMul
+ | UDiv
+ | SDiv
+ | FDiv
+ | URem
+ | SRem
+ | FRem
+ (* Logical Operators *)
+ | Shl
+ | LShr
+ | AShr
+ | And
+ | Or
+ | Xor
+ (* Memory Operators *)
+ | Alloca
+ | Load
+ | Store
+ | GetElementPtr
+ (* Cast Operators *)
+ | Trunc
+ | ZExt
+ | SExt
+ | FPToUI
+ | FPToSI
+ | UIToFP
+ | SIToFP
+ | FPTrunc
+ | FPExt
+ | PtrToInt
+ | IntToPtr
+ | BitCast
+ (* Other Operators *)
+ | ICmp
+ | FCmp
+ | PHI
+ | Call
+ | Select
+ | UserOp1
+ | UserOp2
+ | VAArg
+ | ExtractElement
+ | InsertElement
+ | ShuffleVector
+ | ExtractValue
+ | InsertValue
+ | Fence
+ | AtomicCmpXchg
+ | AtomicRMW
+ | Resume
+ | LandingPad
+ | Unwind
+end
+
+module ValueKind = struct
+ type t =
+ | NullValue
+ | Argument
+ | BasicBlock
+ | InlineAsm
+ | MDNode
+ | MDString
+ | BlockAddress
+ | ConstantAggregateZero
+ | ConstantArray
+ | ConstantExpr
+ | ConstantFP
+ | ConstantInt
+ | ConstantPointerNull
+ | ConstantStruct
+ | ConstantVector
+ | Function
+ | GlobalAlias
+ | GlobalVariable
+ | UndefValue
+ | Instruction of Opcode.t
+end
+
exception IoError of string
external register_exns : exn -> unit = "llvm_register_core_exns"
@@ -163,10 +261,12 @@ external set_data_layout: string -> llmodule -> unit
external dump_module : llmodule -> unit = "llvm_dump_module"
external set_module_inline_asm : llmodule -> string -> unit
= "llvm_set_module_inline_asm"
+external module_context : llmodule -> llcontext = "LLVMGetModuleContext"
(*===-- Types -------------------------------------------------------------===*)
external classify_type : lltype -> TypeKind.t = "llvm_classify_type"
external type_context : lltype -> llcontext = "llvm_type_context"
+external type_is_sized : lltype -> bool = "llvm_type_is_sized"
(*--... Operations on integer types ........................................--*)
external i1_type : llcontext -> lltype = "llvm_i1_type"
@@ -197,9 +297,15 @@ external param_types : lltype -> lltype array = "llvm_param_types"
external struct_type : llcontext -> lltype array -> lltype = "llvm_struct_type"
external packed_struct_type : llcontext -> lltype array -> lltype
= "llvm_packed_struct_type"
+external struct_name : lltype -> string option = "llvm_struct_name"
+external named_struct_type : llcontext -> string -> lltype =
+ "llvm_named_struct_type"
+external struct_set_body : lltype -> lltype array -> bool -> unit =
+ "llvm_struct_set_body"
external struct_element_types : lltype -> lltype array
= "llvm_struct_element_types"
external is_packed : lltype -> bool = "llvm_is_packed"
+external is_opaque : lltype -> bool = "llvm_is_opaque"
(*--... Operations on pointer, vector, and array types .....................--*)
external array_type : lltype -> int -> lltype = "llvm_array_type"
@@ -216,7 +322,9 @@ external vector_size : lltype -> int = "llvm_vector_size"
(*--... Operations on other types ..........................................--*)
external void_type : llcontext -> lltype = "llvm_void_type"
external label_type : llcontext -> lltype = "llvm_label_type"
+external type_by_name : llmodule -> string -> lltype option = "llvm_type_by_name"
+external classify_value : llvalue -> ValueKind.t = "llvm_classify_value"
(*===-- Values ------------------------------------------------------------===*)
external type_of : llvalue -> lltype = "llvm_type_of"
external value_name : llvalue -> string = "llvm_value_name"
@@ -270,6 +378,7 @@ external const_pointer_null : lltype -> llvalue = "LLVMConstPointerNull"
external undef : lltype -> llvalue = "LLVMGetUndef"
external is_null : llvalue -> bool = "llvm_is_null"
external is_undef : llvalue -> bool = "llvm_is_undef"
+external constexpr_opcode : llvalue -> Opcode.t = "llvm_constexpr_get_opcode"
(*--... Operations on instructions .........................................--*)
external has_metadata : llvalue -> bool = "llvm_has_metadata"
@@ -280,11 +389,15 @@ external clear_metadata : llvalue -> int -> unit = "llvm_clear_metadata"
(*--... Operations on metadata .......,.....................................--*)
external mdstring : llcontext -> string -> llvalue = "llvm_mdstring"
external mdnode : llcontext -> llvalue array -> llvalue = "llvm_mdnode"
+external get_mdstring : llvalue -> string option = "llvm_get_mdstring"
+external get_named_metadata : llmodule -> string -> llvalue array = "llvm_get_namedmd"
(*--... Operations on scalar constants .....................................--*)
external const_int : lltype -> int -> llvalue = "llvm_const_int"
external const_of_int64 : lltype -> Int64.t -> bool -> llvalue
= "llvm_const_of_int64"
+external int64_of_const : llvalue -> Int64.t option
+ = "llvm_int64_of_const"
external const_int_of_string : lltype -> string -> int -> llvalue
= "llvm_const_int_of_string"
external const_float : lltype -> float -> llvalue = "llvm_const_float"
@@ -297,6 +410,8 @@ external const_stringz : llcontext -> string -> llvalue = "llvm_const_stringz"
external const_array : lltype -> llvalue array -> llvalue = "llvm_const_array"
external const_struct : llcontext -> llvalue array -> llvalue
= "llvm_const_struct"
+external const_named_struct : lltype -> llvalue array -> llvalue
+ = "llvm_const_named_struct"
external const_packed_struct : llcontext -> llvalue array -> llvalue
= "llvm_const_packed_struct"
external const_vector : llvalue array -> llvalue = "llvm_const_vector"
@@ -530,36 +645,81 @@ let rec fold_right_function_range f i e init =
let fold_right_functions f m init =
fold_right_function_range f (function_end m) (At_start m) init
-external llvm_add_function_attr : llvalue -> int -> unit
+external llvm_add_function_attr : llvalue -> int32 -> unit
= "llvm_add_function_attr"
-external llvm_remove_function_attr : llvalue -> int -> unit
+external llvm_remove_function_attr : llvalue -> int32 -> unit
= "llvm_remove_function_attr"
+external llvm_function_attr : llvalue -> int32 = "llvm_function_attr"
-let pack_attr (attr:Attribute.t) : int =
+let pack_attr (attr:Attribute.t) : int32 =
match attr with
- Attribute.Zext -> 1 lsl 0
- | Attribute.Sext -> 1 lsl 1
- | Attribute.Noreturn -> 1 lsl 2
- | Attribute.Inreg -> 1 lsl 3
- | Attribute.Structret -> 1 lsl 4
- | Attribute.Nounwind -> 1 lsl 5
- | Attribute.Noalias -> 1 lsl 6
- | Attribute.Byval -> 1 lsl 7
- | Attribute.Nest -> 1 lsl 8
- | Attribute.Readnone -> 1 lsl 9
- | Attribute.Readonly -> 1 lsl 10
- | Attribute.Noinline -> 1 lsl 11
- | Attribute.Alwaysinline -> 1 lsl 12
- | Attribute.Optsize -> 1 lsl 13
- | Attribute.Ssp -> 1 lsl 14
- | Attribute.Sspreq -> 1 lsl 15
- | Attribute.Alignment n -> n lsl 16
- | Attribute.Nocapture -> 1 lsl 21
- | Attribute.Noredzone -> 1 lsl 22
- | Attribute.Noimplicitfloat -> 1 lsl 23
- | Attribute.Naked -> 1 lsl 24
- | Attribute.Inlinehint -> 1 lsl 25
- | Attribute.Stackalignment n -> n lsl 26
+ Attribute.Zext -> Int32.shift_left 1l 0
+ | Attribute.Sext -> Int32.shift_left 1l 1
+ | Attribute.Noreturn -> Int32.shift_left 1l 2
+ | Attribute.Inreg -> Int32.shift_left 1l 3
+ | Attribute.Structret -> Int32.shift_left 1l 4
+ | Attribute.Nounwind -> Int32.shift_left 1l 5
+ | Attribute.Noalias -> Int32.shift_left 1l 6
+ | Attribute.Byval -> Int32.shift_left 1l 7
+ | Attribute.Nest -> Int32.shift_left 1l 8
+ | Attribute.Readnone -> Int32.shift_left 1l 9
+ | Attribute.Readonly -> Int32.shift_left 1l 10
+ | Attribute.Noinline -> Int32.shift_left 1l 11
+ | Attribute.Alwaysinline -> Int32.shift_left 1l 12
+ | Attribute.Optsize -> Int32.shift_left 1l 13
+ | Attribute.Ssp -> Int32.shift_left 1l 14
+ | Attribute.Sspreq -> Int32.shift_left 1l 15
+ | Attribute.Alignment n -> Int32.shift_left (Int32.of_int n) 16
+ | Attribute.Nocapture -> Int32.shift_left 1l 21
+ | Attribute.Noredzone -> Int32.shift_left 1l 22
+ | Attribute.Noimplicitfloat -> Int32.shift_left 1l 23
+ | Attribute.Naked -> Int32.shift_left 1l 24
+ | Attribute.Inlinehint -> Int32.shift_left 1l 25
+ | Attribute.Stackalignment n -> Int32.shift_left (Int32.of_int n) 26
+ | Attribute.ReturnsTwice -> Int32.shift_left 1l 29
+ | Attribute.UWTable -> Int32.shift_left 1l 30
+ | Attribute.NonLazyBind -> Int32.shift_left 1l 31
+
+let unpack_attr (a : int32) : Attribute.t list =
+ let l = ref [] in
+ let check attr =
+ Int32.logand (pack_attr attr) a in
+ let checkattr attr =
+ if (check attr) <> 0l then begin
+ l := attr :: !l
+ end
+ in
+ checkattr Attribute.Zext;
+ checkattr Attribute.Sext;
+ checkattr Attribute.Noreturn;
+ checkattr Attribute.Inreg;
+ checkattr Attribute.Structret;
+ checkattr Attribute.Nounwind;
+ checkattr Attribute.Noalias;
+ checkattr Attribute.Byval;
+ checkattr Attribute.Nest;
+ checkattr Attribute.Readnone;
+ checkattr Attribute.Readonly;
+ checkattr Attribute.Noinline;
+ checkattr Attribute.Alwaysinline;
+ checkattr Attribute.Optsize;
+ checkattr Attribute.Ssp;
+ checkattr Attribute.Sspreq;
+ let align = Int32.logand (Int32.shift_right_logical a 16) 31l in
+ if align <> 0l then
+ l := Attribute.Alignment (Int32.to_int align) :: !l;
+ checkattr Attribute.Nocapture;
+ checkattr Attribute.Noredzone;
+ checkattr Attribute.Noimplicitfloat;
+ checkattr Attribute.Naked;
+ checkattr Attribute.Inlinehint;
+ let stackalign = Int32.logand (Int32.shift_right_logical a 26) 7l in
+ if stackalign <> 0l then
+ l := Attribute.Stackalignment (Int32.to_int stackalign) :: !l;
+ checkattr Attribute.ReturnsTwice;
+ checkattr Attribute.UWTable;
+ checkattr Attribute.NonLazyBind;
+ !l;;
let add_function_attr llval attr =
llvm_add_function_attr llval (pack_attr attr)
@@ -567,9 +727,13 @@ let add_function_attr llval attr =
let remove_function_attr llval attr =
llvm_remove_function_attr llval (pack_attr attr)
+let function_attr f = unpack_attr (llvm_function_attr f)
+
(*--... Operations on params ...............................................--*)
external params : llvalue -> llvalue array = "llvm_params"
external param : llvalue -> int -> llvalue = "llvm_param"
+external llvm_param_attr : llvalue -> int32 = "llvm_param_attr"
+let param_attr p = unpack_attr (llvm_param_attr p)
external param_parent : llvalue -> llvalue = "LLVMGetParamParent"
external param_begin : llvalue -> (llvalue, llvalue) llpos = "llvm_param_begin"
external param_succ : llvalue -> (llvalue, llvalue) llpos = "llvm_param_succ"
@@ -616,9 +780,9 @@ let rec fold_right_param_range f init i e =
let fold_right_params f fn init =
fold_right_param_range f init (param_end fn) (At_start fn)
-external llvm_add_param_attr : llvalue -> int -> unit
+external llvm_add_param_attr : llvalue -> int32 -> unit
= "llvm_add_param_attr"
-external llvm_remove_param_attr : llvalue -> int -> unit
+external llvm_remove_param_attr : llvalue -> int32 -> unit
= "llvm_remove_param_attr"
let add_param_attr llval attr =
@@ -650,6 +814,8 @@ external block_end : llvalue -> (llvalue, llbasicblock) llrev_pos
= "llvm_block_end"
external block_pred : llbasicblock -> (llvalue, llbasicblock) llrev_pos
= "llvm_block_pred"
+external block_terminator : llbasicblock -> llvalue option =
+ "llvm_block_terminator"
let rec iter_block_range f i e =
if i = e then () else
@@ -702,6 +868,11 @@ external instr_end : llbasicblock -> (llbasicblock, llvalue) llrev_pos
external instr_pred : llvalue -> (llbasicblock, llvalue) llrev_pos
= "llvm_instr_pred"
+external instr_opcode : llvalue -> Opcode.t = "llvm_instr_get_opcode"
+external icmp_predicate : llvalue -> Icmp.t option = "llvm_instr_icmp_predicate"
+
+external icmp_predicate : llvalue -> Icmp.t option = "llvm_instr_icmp_predicate"
+
let rec iter_instrs_range f i e =
if i = e then () else
match i with
@@ -749,9 +920,9 @@ external instruction_call_conv: llvalue -> int
external set_instruction_call_conv: int -> llvalue -> unit
= "llvm_set_instruction_call_conv"
-external llvm_add_instruction_param_attr : llvalue -> int -> int -> unit
+external llvm_add_instruction_param_attr : llvalue -> int -> int32 -> unit
= "llvm_add_instruction_param_attr"
-external llvm_remove_instruction_param_attr : llvalue -> int -> int -> unit
+external llvm_remove_instruction_param_attr : llvalue -> int -> int32 -> unit
= "llvm_remove_instruction_param_attr"
let add_instruction_param_attr llval i attr =
@@ -769,6 +940,7 @@ external add_incoming : (llvalue * llbasicblock) -> llvalue -> unit
= "llvm_add_incoming"
external incoming : llvalue -> (llvalue * llbasicblock) list = "llvm_incoming"
+external delete_instruction : llvalue -> unit = "llvm_delete_instruction"
(*===-- Instruction builders ----------------------------------------------===*)
external builder : llcontext -> llbuilder = "llvm_builder"
@@ -811,8 +983,15 @@ external build_cond_br : llvalue -> llbasicblock -> llbasicblock -> llbuilder ->
llvalue = "llvm_build_cond_br"
external build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue
= "llvm_build_switch"
+external build_malloc : lltype -> string -> llbuilder -> llvalue =
+ "llvm_build_malloc"
+external build_array_malloc : lltype -> llvalue -> string -> llbuilder ->
+ llvalue = "llvm_build_array_malloc"
+external build_free : llvalue -> llbuilder -> llvalue = "llvm_build_free"
external add_case : llvalue -> llvalue -> llbasicblock -> unit
= "llvm_add_case"
+external switch_default_dest : llvalue -> llbasicblock =
+ "LLVMGetSwitchDefaultDest"
external build_indirect_br : llvalue -> int -> llbuilder -> llvalue
= "llvm_build_indirect_br"
external add_destination : llvalue -> llbasicblock -> unit
@@ -820,7 +999,11 @@ external add_destination : llvalue -> llbasicblock -> unit
external build_invoke : llvalue -> llvalue array -> llbasicblock ->
llbasicblock -> string -> llbuilder -> llvalue
= "llvm_build_invoke_bc" "llvm_build_invoke_nat"
-external build_unwind : llbuilder -> llvalue = "llvm_build_unwind"
+external build_landingpad : lltype -> llvalue -> int -> string -> llbuilder ->
+ llvalue = "llvm_build_landingpad"
+external set_cleanup : llvalue -> bool -> unit = "llvm_set_cleanup"
+external add_clause : llvalue -> llvalue -> unit = "llvm_add_clause"
+external build_resume : llvalue -> llbuilder -> llvalue = "llvm_build_resume"
external build_unreachable : llbuilder -> llvalue = "llvm_build_unreachable"
(*--... Arithmetic .........................................................--*)
@@ -1022,7 +1205,14 @@ let rec string_of_lltype ty =
(* FIXME: stop infinite recursion! :) *)
match classify_type ty with
TypeKind.Integer -> "i" ^ string_of_int (integer_bitwidth ty)
- | TypeKind.Pointer -> (string_of_lltype (element_type ty)) ^ "*"
+ | TypeKind.Pointer ->
+ (let ety = element_type ty in
+ match classify_type ety with
+ | TypeKind.Struct ->
+ (match struct_name ety with
+ | None -> (string_of_lltype ety)
+ | Some s -> s) ^ "*"
+ | _ -> (string_of_lltype (element_type ty)) ^ "*")
| TypeKind.Struct ->
let s = "{ " ^ (concat2 ", " (
Array.map string_of_lltype (struct_element_types ty)
diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli
index 44f345f..33bbc74 100644
--- a/bindings/ocaml/llvm/llvm.mli
+++ b/bindings/ocaml/llvm/llvm.mli
@@ -139,6 +139,9 @@ module Attribute : sig
| Naked
| Inlinehint
| Stackalignment of int
+ | ReturnsTwice
+ | UWTable
+ | NonLazyBind
end
(** The predicate for an integer comparison ([icmp]) instruction.
@@ -179,6 +182,103 @@ module Fcmp : sig
| True
end
+(** The opcodes for LLVM instructions and constant expressions. *)
+module Opcode : sig
+ type t =
+ | Invalid (* not an instruction *)
+ (* Terminator Instructions *)
+ | Ret
+ | Br
+ | Switch
+ | IndirectBr
+ | Invoke
+ | Invalid2
+ | Unreachable
+ (* Standard Binary Operators *)
+ | Add
+ | FAdd
+ | Sub
+ | FSub
+ | Mul
+ | FMul
+ | UDiv
+ | SDiv
+ | FDiv
+ | URem
+ | SRem
+ | FRem
+ (* Logical Operators *)
+ | Shl
+ | LShr
+ | AShr
+ | And
+ | Or
+ | Xor
+ (* Memory Operators *)
+ | Alloca
+ | Load
+ | Store
+ | GetElementPtr
+ (* Cast Operators *)
+ | Trunc
+ | ZExt
+ | SExt
+ | FPToUI
+ | FPToSI
+ | UIToFP
+ | SIToFP
+ | FPTrunc
+ | FPExt
+ | PtrToInt
+ | IntToPtr
+ | BitCast
+ (* Other Operators *)
+ | ICmp
+ | FCmp
+ | PHI
+ | Call
+ | Select
+ | UserOp1
+ | UserOp2
+ | VAArg
+ | ExtractElement
+ | InsertElement
+ | ShuffleVector
+ | ExtractValue
+ | InsertValue
+ | Fence
+ | AtomicCmpXchg
+ | AtomicRMW
+ | Resume
+ | LandingPad
+ | Unwind
+end
+
+(** The kind of an [llvalue], the result of [classify_value v].
+ * See the various [LLVMIsA*] functions. *)
+module ValueKind : sig
+ type t =
+ | NullValue
+ | Argument
+ | BasicBlock
+ | InlineAsm
+ | MDNode
+ | MDString
+ | BlockAddress
+ | ConstantAggregateZero
+ | ConstantArray
+ | ConstantExpr
+ | ConstantFP
+ | ConstantInt
+ | ConstantPointerNull
+ | ConstantStruct
+ | ConstantVector
+ | Function
+ | GlobalAlias
+ | GlobalVariable
+ | UndefValue
+ | Instruction of Opcode.t
+end
(** {6 Iteration} *)
@@ -263,7 +363,9 @@ val dump_module : llmodule -> unit
the method [llvm::Module::setModuleInlineAsm]. *)
val set_module_inline_asm : llmodule -> string -> unit
-
+(** [module_context m] returns the context of the specified module.
+ * See the method [llvm::Module::getContext] *)
+val module_context : llmodule -> llcontext
(** {6 Types} *)
@@ -271,6 +373,11 @@ val set_module_inline_asm : llmodule -> string -> unit
See the method [llvm::Type::getTypeID]. *)
val classify_type : lltype -> TypeKind.t
+(** [type_is_sized ty] returns whether the type has a size or not.
+ * If it doesn't then it is not safe to call the [TargetData::] methods on it.
+ * *)
+val type_is_sized : lltype -> bool
+
(** [type_context ty] returns the {!llcontext} corresponding to the type [ty].
See the method [llvm::Type::getContext]. *)
val type_context : lltype -> llcontext
@@ -339,7 +446,7 @@ val ppc_fp128_type : llcontext -> lltype
See the method [llvm::FunctionType::get]. *)
val function_type : lltype -> lltype array -> lltype
-(** [va_arg_function_type ret_ty param_tys] is just like
+(** [var_arg_function_type ret_ty param_tys] is just like
[function_type ret_ty param_tys] except that it returns the function type
which also takes a variable number of arguments.
See the method [llvm::FunctionType::get]. *)
@@ -372,6 +479,19 @@ val struct_type : llcontext -> lltype array -> lltype
[llvm::StructType::get]. *)
val packed_struct_type : llcontext -> lltype array -> lltype
+(** [struct_name ty] returns the name of the named structure type [ty],
+ * or None if the structure type is not named *)
+val struct_name : lltype -> string option
+
+(** [named_struct_type context name] returns the named structure type [name]
+ * in the context [context].
+ * See the method [llvm::StructType::get]. *)
+val named_struct_type : llcontext -> string -> lltype
+
+(** [struct_set_body ty elts ispacked] sets the body of the named struct [ty]
+ * to the [elts] elements.
+ * See the moethd [llvm::StructType::setBody]. *)
+val struct_set_body : lltype -> lltype array -> bool -> unit
(** [struct_element_types sty] returns the constituent types of the struct type
[sty]. See the method [llvm::StructType::getElementType]. *)
@@ -382,6 +502,9 @@ val struct_element_types : lltype -> lltype array
[false] otherwise. See the method [llvm::StructType::isPacked]. *)
val is_packed : lltype -> bool
+(** [is_opaque sty] returns [true] if the structure type [sty] is opaque.
+ [false] otherwise. See the method [llvm::StructType::isOpaque]. *)
+val is_opaque : lltype -> bool
(** {7 Operations on pointer, vector, and array types} *)
@@ -431,12 +554,19 @@ val void_type : llcontext -> lltype
[llvm::Type::LabelTy]. *)
val label_type : llcontext -> lltype
+(** [type_by_name m name] returns the specified type from the current module
+ * if it exists.
+ * See the method [llvm::Module::getTypeByName] *)
+val type_by_name : llmodule -> string -> lltype option
+
(* {6 Values} *)
(** [type_of v] returns the type of the value [v].
See the method [llvm::Value::getType]. *)
val type_of : llvalue -> lltype
+val classify_value : llvalue -> ValueKind.t
+
(** [value_name v] returns the name of the value [v]. For global values, this is
the symbol name. For instructions and basic blocks, it is the SSA register
name. It is meaningless for constants.
@@ -534,7 +664,7 @@ val is_null : llvalue -> bool
otherwise. Similar to [llvm::isa<UndefValue>]. *)
val is_undef : llvalue -> bool
-
+val constexpr_opcode : llvalue -> Opcode.t
(** {7 Operations on instructions} *)
(** [has_metadata i] returns whether or not the instruction [i] has any
@@ -567,6 +697,14 @@ val mdstring : llcontext -> string -> llvalue
See the method [llvm::MDNode::get]. *)
val mdnode : llcontext -> llvalue array -> llvalue
+(** [get_mdstring v] returns the MDString.
+ * See the method [llvm::MDString::getString] *)
+val get_mdstring : llvalue -> string option
+
+(** [get_named_metadata m name] return all the MDNodes belonging to the named
+ * metadata (if any).
+ * See the method [llvm::NamedMDNode::getOperand]. *)
+val get_named_metadata : llmodule -> string -> llvalue array
(** {7 Operations on scalar constants} *)
@@ -578,6 +716,10 @@ val const_int : lltype -> int -> llvalue
[i]. See the method [llvm::ConstantInt::get]. *)
val const_of_int64 : lltype -> Int64.t -> bool -> llvalue
+(** [int64_of_const c] returns the int64 value of the [c] constant integer.
+ * None is returned if this is not an integer constant, or bitwidth exceeds 64.
+ * See the method [llvm::ConstantInt::getSExtValue].*)
+val int64_of_const : llvalue -> Int64.t option
(** [const_int_of_string ty s r] returns the integer constant of type [ty] and
* value [s], with the radix [r]. See the method [llvm::ConstantInt::get]. *)
@@ -618,9 +760,14 @@ val const_array : lltype -> llvalue array -> llvalue
(** [const_struct context elts] returns the structured constant of type
[struct_type (Array.map type_of elts)] and containing the values [elts]
in the context [context]. This value can in turn be used as the initializer
- for a global variable. See the method [llvm::ConstantStruct::get]. *)
+ for a global variable. See the method [llvm::ConstantStruct::getAnon]. *)
val const_struct : llcontext -> llvalue array -> llvalue
+(** [const_named_struct namedty elts] returns the structured constant of type
+ [namedty] (which must be a named structure type) and containing the values [elts].
+ This value can in turn be used as the initializer
+ for a global variable. See the method [llvm::ConstantStruct::get]. *)
+val const_named_struct : lltype -> llvalue array -> llvalue
(** [const_packed_struct context elts] returns the structured constant of
type {!packed_struct_type} [(Array.map type_of elts)] and containing the
@@ -1231,6 +1378,10 @@ val set_gc : string option -> llvalue -> unit
[f]. *)
val add_function_attr : llvalue -> Attribute.t -> unit
+(** [function_attr f] returns the function attribute for the function [f].
+ * See the method [llvm::Function::getAttributes] *)
+val function_attr : llvalue -> Attribute.t list
+
(** [remove_function_attr f a] removes attribute [a] from the return type of
function [f]. *)
val remove_function_attr : llvalue -> Attribute.t -> unit
@@ -1245,6 +1396,11 @@ val params : llvalue -> llvalue array
See the method [llvm::Function::getArgumentList]. *)
val param : llvalue -> int -> llvalue
+(** [param_attr p] returns the attributes of parameter [p].
+ * See the methods [llvm::Function::getAttributes] and
+ * [llvm::Attributes::getParamAttributes] *)
+val param_attr : llvalue -> Attribute.t list
+
(** [param_parent p] returns the parent function that owns the parameter.
See the method [llvm::Argument::getParent]. *)
val param_parent : llvalue -> llvalue
@@ -1359,6 +1515,7 @@ val block_end : llvalue -> (llvalue, llbasicblock) llrev_pos
See the method [llvm::Function::iterator::operator--]. *)
val block_pred : llbasicblock -> (llvalue, llbasicblock) llrev_pos
+val block_terminator : llbasicblock -> llvalue option
(** [rev_iter_blocks f fn] applies function [f] to each of the basic blocks
of function [fn] in reverse order. Tail recursive. *)
@@ -1422,6 +1579,9 @@ val instr_pred : llvalue -> (llbasicblock, llvalue) llrev_pos
[f1,...,fN] are the instructions of basic block [bb]. Tail recursive. *)
val fold_right_instrs: (llvalue -> 'a -> 'a) -> llbasicblock -> 'a -> 'a
+val instr_opcode : llvalue -> Opcode.t
+
+val icmp_predicate : llvalue -> Icmp.t option
(** {7 Operations on call sites} *)
@@ -1473,7 +1633,9 @@ val add_incoming : (llvalue * llbasicblock) -> llvalue -> unit
See the method [llvm::PHINode::getIncomingValue]. *)
val incoming : llvalue -> (llvalue * llbasicblock) list
-
+(** [delete_instruction i] deletes the instruction [i].
+ * See the method [llvm::Instruction::eraseFromParent]. *)
+val delete_instruction : llvalue -> unit
(** {6 Instruction builders} *)
@@ -1587,12 +1749,30 @@ val build_cond_br : llvalue -> llbasicblock -> llbasicblock -> llbuilder ->
See the method [llvm::LLVMBuilder::CreateSwitch]. *)
val build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue
+(** [build_malloc ty name b] creates an [malloc]
+ instruction at the position specified by the instruction builder [b].
+ See the method [llvm::CallInst::CreateMalloc]. *)
+val build_malloc : lltype -> string -> llbuilder -> llvalue
+
+(** [build_array_malloc ty val name b] creates an [array malloc]
+ instruction at the position specified by the instruction builder [b].
+ See the method [llvm::CallInst::CreateArrayMalloc]. *)
+val build_array_malloc : lltype -> llvalue -> string -> llbuilder -> llvalue
+
+(** [build_free p b] creates a [free]
+ instruction at the position specified by the instruction builder [b].
+ See the method [llvm::LLVMBuilder::CreateFree]. *)
+val build_free : llvalue -> llbuilder -> llvalue
(** [add_case sw onval bb] causes switch instruction [sw] to branch to [bb]
when its input matches the constant [onval].
See the method [llvm::SwitchInst::addCase]. **)
val add_case : llvalue -> llvalue -> llbasicblock -> unit
+(** [switch_default_dest sw] returns the default destination of the [switch]
+ * instruction.
+ * See the method [llvm:;SwitchInst::getDefaultDest]. **)
+val switch_default_dest : llvalue -> llbasicblock
(** [build_indirect_br addr count b] creates a
[indirectbr %addr]
@@ -1615,12 +1795,25 @@ val add_destination : llvalue -> llbasicblock -> unit
val build_invoke : llvalue -> llvalue array -> llbasicblock ->
llbasicblock -> string -> llbuilder -> llvalue
-
-(** [build_unwind b] creates an
- [unwind]
+(** [build_landingpad ty persfn numclauses name b] creates an
+ [landingpad]
instruction at the position specified by the instruction builder [b].
- See the method [llvm::LLVMBuilder::CreateUnwind]. *)
-val build_unwind : llbuilder -> llvalue
+ See the method [llvm::LLVMBuilder::CreateLandingPad]. *)
+val build_landingpad : lltype -> llvalue -> int -> string -> llbuilder ->
+ llvalue
+
+(** [set_cleanup lp] sets the cleanup flag in the [landingpad]instruction.
+ See the method [llvm::LandingPadInst::setCleanup]. *)
+val set_cleanup : llvalue -> bool -> unit
+
+(** [add_clause lp clause] adds the clause to the [landingpad]instruction.
+ See the method [llvm::LandingPadInst::addClause]. *)
+val add_clause : llvalue -> llvalue -> unit
+
+(* [build_resume exn b] builds a [resume exn] instruction
+ * at the position specified by the instruction builder [b].
+ * See the method [llvm::LLVMBuilder::CreateResume] *)
+val build_resume : llvalue -> llbuilder -> llvalue
(** [build_unreachable b] creates an
[unreachable]
diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c
index 455e191..86cc4bd 100644
--- a/bindings/ocaml/llvm/llvm_ocaml.c
+++ b/bindings/ocaml/llvm/llvm_ocaml.c
@@ -24,6 +24,7 @@
#include "llvm/Config/config.h"
#include <assert.h>
#include <stdlib.h>
+#include <string.h>
/* Can't use the recommended caml_named_value mechanism for backwards
@@ -171,6 +172,10 @@ CAMLprim value llvm_classify_type(LLVMTypeRef Ty) {
return Val_int(LLVMGetTypeKind(Ty));
}
+CAMLprim value llvm_type_is_sized(LLVMTypeRef Ty) {
+ return Val_bool(LLVMTypeIsSized(Ty));
+}
+
/* lltype -> llcontext */
CAMLprim LLVMContextRef llvm_type_context(LLVMTypeRef Ty) {
return LLVMGetTypeContext(Ty);
@@ -287,6 +292,34 @@ CAMLprim LLVMTypeRef llvm_packed_struct_type(LLVMContextRef C,
Wosize_val(ElementTypes), 1);
}
+/* llcontext -> string -> lltype */
+CAMLprim LLVMTypeRef llvm_named_struct_type(LLVMContextRef C,
+ value Name) {
+ return LLVMStructCreateNamed(C, String_val(Name));
+}
+
+CAMLprim value llvm_struct_set_body(LLVMTypeRef Ty,
+ value ElementTypes,
+ value Packed) {
+ LLVMStructSetBody(Ty, (LLVMTypeRef *) ElementTypes,
+ Wosize_val(ElementTypes), Bool_val(Packed));
+ return Val_unit;
+}
+
+/* lltype -> string option */
+CAMLprim value llvm_struct_name(LLVMTypeRef Ty)
+{
+ CAMLparam0();
+ const char *C = LLVMGetStructName(Ty);
+ if (C) {
+ CAMLlocal1(result);
+ result = caml_alloc_small(1, 0);
+ Store_field(result, 0, caml_copy_string(C));
+ CAMLreturn(result);
+ }
+ CAMLreturn(Val_int(0));
+}
+
/* lltype -> lltype array */
CAMLprim value llvm_struct_element_types(LLVMTypeRef StructTy) {
value Tys = alloc(LLVMCountStructElementTypes(StructTy), 0);
@@ -299,6 +332,11 @@ CAMLprim value llvm_is_packed(LLVMTypeRef StructTy) {
return Val_bool(LLVMIsPackedStruct(StructTy));
}
+/* lltype -> bool */
+CAMLprim value llvm_is_opaque(LLVMTypeRef StructTy) {
+ return Val_bool(LLVMIsOpaqueStruct(StructTy));
+}
+
/*--... Operations on array, pointer, and vector types .....................--*/
/* lltype -> int -> lltype */
@@ -349,6 +387,18 @@ CAMLprim LLVMTypeRef llvm_label_type(LLVMContextRef Context) {
return LLVMLabelTypeInContext(Context);
}
+CAMLprim value llvm_type_by_name(LLVMModuleRef M, value Name)
+{
+ CAMLparam1(Name);
+ LLVMTypeRef Ty = LLVMGetTypeByName(M, String_val(Name));
+ if (Ty) {
+ value Option = alloc(1, 0);
+ Field(Option, 0) = (value) Ty;
+ CAMLreturn(Option);
+ }
+ CAMLreturn(Val_int(0));
+}
+
/*===-- VALUES ------------------------------------------------------------===*/
/* llvalue -> lltype */
@@ -356,6 +406,69 @@ CAMLprim LLVMTypeRef llvm_type_of(LLVMValueRef Val) {
return LLVMTypeOf(Val);
}
+/* keep in sync with ValueKind.t */
+enum ValueKind {
+ NullValue=0,
+ Argument,
+ BasicBlock,
+ InlineAsm,
+ MDNode,
+ MDString,
+ BlockAddress,
+ ConstantAggregateZero,
+ ConstantArray,
+ ConstantExpr,
+ ConstantFP,
+ ConstantInt,
+ ConstantPointerNull,
+ ConstantStruct,
+ ConstantVector,
+ Function,
+ GlobalAlias,
+ GlobalVariable,
+ UndefValue,
+ Instruction
+};
+
+/* llvalue -> ValueKind.t */
+#define DEFINE_CASE(Val, Kind) \
+ do {if (LLVMIsA##Kind(Val)) CAMLreturn(Val_int(Kind));} while(0)
+
+CAMLprim value llvm_classify_value(LLVMValueRef Val) {
+ CAMLparam0();
+ if (!Val)
+ CAMLreturn(Val_int(NullValue));
+ if (LLVMIsAConstant(Val)) {
+ DEFINE_CASE(Val, BlockAddress);
+ DEFINE_CASE(Val, ConstantAggregateZero);
+ DEFINE_CASE(Val, ConstantArray);
+ DEFINE_CASE(Val, ConstantExpr);
+ DEFINE_CASE(Val, ConstantFP);
+ DEFINE_CASE(Val, ConstantInt);
+ DEFINE_CASE(Val, ConstantPointerNull);
+ DEFINE_CASE(Val, ConstantStruct);
+ DEFINE_CASE(Val, ConstantVector);
+ }
+ if (LLVMIsAInstruction(Val)) {
+ CAMLlocal1(result);
+ result = caml_alloc_small(1, 0);
+ Store_field(result, 0, Val_int(LLVMGetInstructionOpcode(Val)));
+ CAMLreturn(result);
+ }
+ if (LLVMIsAGlobalValue(Val)) {
+ DEFINE_CASE(Val, Function);
+ DEFINE_CASE(Val, GlobalAlias);
+ DEFINE_CASE(Val, GlobalVariable);
+ }
+ DEFINE_CASE(Val, Argument);
+ DEFINE_CASE(Val, BasicBlock);
+ DEFINE_CASE(Val, InlineAsm);
+ DEFINE_CASE(Val, MDNode);
+ DEFINE_CASE(Val, MDString);
+ DEFINE_CASE(Val, UndefValue);
+ failwith("Unknown Value class");
+}
+
/* llvalue -> string */
CAMLprim value llvm_value_name(LLVMValueRef Val) {
return copy_string(LLVMGetValueName(Val));
@@ -408,6 +521,12 @@ CAMLprim value llvm_is_undef(LLVMValueRef Val) {
return Val_bool(LLVMIsUndef(Val));
}
+/* llvalue -> Opcode.t */
+CAMLprim value llvm_constexpr_get_opcode(LLVMValueRef Val) {
+ return LLVMIsAConstantExpr(Val) ?
+ Val_int(LLVMGetConstOpcode(Val)) : Val_int(0);
+}
+
/*--... Operations on instructions .........................................--*/
/* llvalue -> bool */
@@ -454,6 +573,32 @@ CAMLprim LLVMValueRef llvm_mdnode(LLVMContextRef C, value ElementVals) {
Wosize_val(ElementVals));
}
+/* llvalue -> string option */
+CAMLprim value llvm_get_mdstring(LLVMValueRef V) {
+ CAMLparam0();
+ const char *S;
+ unsigned Len;
+
+ if ((S = LLVMGetMDString(V, &Len))) {
+ CAMLlocal2(Option, Str);
+
+ Str = caml_alloc_string(Len);
+ memcpy(String_val(Str), S, Len);
+ Option = alloc(1,0);
+ Store_field(Option, 0, Str);
+ CAMLreturn(Option);
+ }
+ CAMLreturn(Val_int(0));
+}
+
+CAMLprim value llvm_get_namedmd(LLVMModuleRef M, value name)
+{
+ CAMLparam1(name);
+ CAMLlocal1(Nodes);
+ Nodes = alloc(LLVMGetNamedMetadataNumOperands(M, String_val(name)), 0);
+ LLVMGetNamedMetadataOperands(M, String_val(name), (LLVMValueRef *) Nodes);
+ CAMLreturn(Nodes);
+}
/*--... Operations on scalar constants .....................................--*/
/* lltype -> int -> llvalue */
@@ -467,6 +612,19 @@ CAMLprim LLVMValueRef llvm_const_of_int64(LLVMTypeRef IntTy, value N,
return LLVMConstInt(IntTy, Int64_val(N), Bool_val(SExt));
}
+/* llvalue -> Int64.t */
+CAMLprim value llvm_int64_of_const(LLVMValueRef Const)
+{
+ CAMLparam0();
+ if (LLVMIsAConstantInt(Const) &&
+ LLVMGetIntTypeWidth(LLVMTypeOf(Const)) <= 64) {
+ value Option = alloc(1, 0);
+ Field(Option, 0) = caml_copy_int64(LLVMConstIntGetSExtValue(Const));
+ CAMLreturn(Option);
+ }
+ CAMLreturn(Val_int(0));
+}
+
/* lltype -> string -> int -> llvalue */
CAMLprim LLVMValueRef llvm_const_int_of_string(LLVMTypeRef IntTy, value S,
value Radix) {
@@ -514,6 +672,11 @@ CAMLprim LLVMValueRef llvm_const_struct(LLVMContextRef C, value ElementVals) {
Wosize_val(ElementVals), 0);
}
+/* lltype -> llvalue array -> llvalue */
+CAMLprim LLVMValueRef llvm_const_named_struct(LLVMTypeRef Ty, value ElementVals) {
+ return LLVMConstNamedStruct(Ty, (LLVMValueRef *) Op_val(ElementVals), Wosize_val(ElementVals));
+}
+
/* llcontext -> llvalue array -> llvalue */
CAMLprim LLVMValueRef llvm_const_packed_struct(LLVMContextRef C,
value ElementVals) {
@@ -883,15 +1046,22 @@ CAMLprim value llvm_set_gc(value GC, LLVMValueRef Fn) {
return Val_unit;
}
-/* llvalue -> Attribute.t -> unit */
+/* llvalue -> int32 -> unit */
CAMLprim value llvm_add_function_attr(LLVMValueRef Arg, value PA) {
- LLVMAddFunctionAttr(Arg, Int_val(PA));
+ LLVMAddFunctionAttr(Arg, Int32_val(PA));
return Val_unit;
}
-/* llvalue -> Attribute.t -> unit */
+/* llvalue -> int32 */
+CAMLprim value llvm_function_attr(LLVMValueRef Fn)
+{
+ CAMLparam0();
+ CAMLreturn(caml_copy_int32(LLVMGetFunctionAttr(Fn)));
+}
+
+/* llvalue -> int32 -> unit */
CAMLprim value llvm_remove_function_attr(LLVMValueRef Arg, value PA) {
- LLVMRemoveFunctionAttr(Arg, Int_val(PA));
+ LLVMRemoveFunctionAttr(Arg, Int32_val(PA));
return Val_unit;
}
/*--... Operations on parameters ...........................................--*/
@@ -903,6 +1073,13 @@ CAMLprim LLVMValueRef llvm_param(LLVMValueRef Fn, value Index) {
return LLVMGetParam(Fn, Int_val(Index));
}
+/* llvalue -> int */
+CAMLprim value llvm_param_attr(LLVMValueRef Param)
+{
+ CAMLparam0();
+ CAMLreturn(caml_copy_int32(LLVMGetAttribute(Param)));
+}
+
/* llvalue -> llvalue */
CAMLprim value llvm_params(LLVMValueRef Fn) {
value Params = alloc(LLVMCountParams(Fn), 0);
@@ -910,15 +1087,15 @@ CAMLprim value llvm_params(LLVMValueRef Fn) {
return Params;
}
-/* llvalue -> Attribute.t -> unit */
+/* llvalue -> int32 -> unit */
CAMLprim value llvm_add_param_attr(LLVMValueRef Arg, value PA) {
- LLVMAddAttribute(Arg, Int_val(PA));
+ LLVMAddAttribute(Arg, Int32_val(PA));
return Val_unit;
}
-/* llvalue -> Attribute.t -> unit */
+/* llvalue -> int32 -> unit */
CAMLprim value llvm_remove_param_attr(LLVMValueRef Arg, value PA) {
- LLVMRemoveAttribute(Arg, Int_val(PA));
+ LLVMRemoveAttribute(Arg, Int32_val(PA));
return Val_unit;
}
@@ -933,6 +1110,19 @@ CAMLprim value llvm_set_param_alignment(LLVMValueRef Arg, value align) {
DEFINE_ITERATORS(
block, BasicBlock, LLVMValueRef, LLVMBasicBlockRef, LLVMGetBasicBlockParent)
+/* llbasicblock -> llvalue option */
+CAMLprim value llvm_block_terminator(LLVMBasicBlockRef Block)
+{
+ CAMLparam0();
+ LLVMValueRef Term = LLVMGetBasicBlockTerminator(Block);
+ if (Term) {
+ value Option = alloc(1, 0);
+ Field(Option, 0) = (value) Term;
+ CAMLreturn(Option);
+ }
+ CAMLreturn(Val_int(0));
+}
+
/* llvalue -> llbasicblock array */
CAMLprim value llvm_basic_blocks(LLVMValueRef Fn) {
value MLArray = alloc(LLVMCountBasicBlocks(Fn), 0);
@@ -968,6 +1158,28 @@ CAMLprim value llvm_value_is_block(LLVMValueRef Val) {
DEFINE_ITERATORS(instr, Instruction, LLVMBasicBlockRef, LLVMValueRef,
LLVMGetInstructionParent)
+/* llvalue -> Opcode.t */
+CAMLprim value llvm_instr_get_opcode(LLVMValueRef Inst) {
+ LLVMOpcode o;
+ if (!LLVMIsAInstruction(Inst))
+ failwith("Not an instruction");
+ o = LLVMGetInstructionOpcode(Inst);
+ assert (o <= LLVMUnwind );
+ return Val_int(o);
+}
+
+/* llvalue -> ICmp.t */
+CAMLprim value llvm_instr_icmp_predicate(LLVMValueRef Val) {
+ CAMLparam0();
+ int x = LLVMGetICmpPredicate(Val);
+ if (x) {
+ value Option = alloc(1, 0);
+ Field(Option, 0) = Val_int(x - LLVMIntEQ);
+ CAMLreturn(Option);
+ }
+ CAMLreturn(Val_int(0));
+}
+
/*--... Operations on call sites ...........................................--*/
@@ -982,19 +1194,19 @@ CAMLprim value llvm_set_instruction_call_conv(value CC, LLVMValueRef Inst) {
return Val_unit;
}
-/* llvalue -> int -> Attribute.t -> unit */
+/* llvalue -> int -> int32 -> unit */
CAMLprim value llvm_add_instruction_param_attr(LLVMValueRef Instr,
value index,
value PA) {
- LLVMAddInstrAttribute(Instr, Int_val(index), Int_val(PA));
+ LLVMAddInstrAttribute(Instr, Int_val(index), Int32_val(PA));
return Val_unit;
}
-/* llvalue -> int -> Attribute.t -> unit */
+/* llvalue -> int -> int32 -> unit */
CAMLprim value llvm_remove_instruction_param_attr(LLVMValueRef Instr,
value index,
value PA) {
- LLVMRemoveInstrAttribute(Instr, Int_val(index), Int_val(PA));
+ LLVMRemoveInstrAttribute(Instr, Int_val(index), Int32_val(PA));
return Val_unit;
}
@@ -1045,6 +1257,11 @@ CAMLprim value llvm_incoming(LLVMValueRef PhiNode) {
CAMLreturn(Tl);
}
+/* llvalue -> unit */
+CAMLprim value llvm_delete_instruction(LLVMValueRef Instruction) {
+ LLVMInstructionEraseFromParent(Instruction);
+ return Val_unit;
+}
/*===-- Instruction builders ----------------------------------------------===*/
@@ -1172,6 +1389,27 @@ CAMLprim LLVMValueRef llvm_build_switch(LLVMValueRef Of,
return LLVMBuildSwitch(Builder_val(B), Of, Else, Int_val(EstimatedCount));
}
+/* lltype -> string -> llbuilder -> llvalue */
+CAMLprim LLVMValueRef llvm_build_malloc(LLVMTypeRef Ty, value Name,
+ value B)
+{
+ return LLVMBuildMalloc(Builder_val(B), Ty, String_val(Name));
+}
+
+/* lltype -> llvalue -> string -> llbuilder -> llvalue */
+CAMLprim LLVMValueRef llvm_build_array_malloc(LLVMTypeRef Ty,
+ LLVMValueRef Val,
+ value Name, value B)
+{
+ return LLVMBuildArrayMalloc(Builder_val(B), Ty, Val, String_val(Name));
+}
+
+/* llvalue -> llbuilder -> llvalue */
+CAMLprim LLVMValueRef llvm_build_free(LLVMValueRef P, value B)
+{
+ return LLVMBuildFree(Builder_val(B), P);
+}
+
/* llvalue -> llvalue -> llbasicblock -> unit */
CAMLprim value llvm_add_case(LLVMValueRef Switch, LLVMValueRef OnVal,
LLVMBasicBlockRef Dest) {
@@ -1212,9 +1450,33 @@ CAMLprim LLVMValueRef llvm_build_invoke_bc(value Args[], int NumArgs) {
Args[4], Args[5]);
}
-/* llbuilder -> llvalue */
-CAMLprim LLVMValueRef llvm_build_unwind(value B) {
- return LLVMBuildUnwind(Builder_val(B));
+/* lltype -> llvalue -> int -> string -> llbuilder -> llvalue */
+CAMLprim LLVMValueRef llvm_build_landingpad(LLVMTypeRef Ty, LLVMValueRef PersFn,
+ value NumClauses, value Name,
+ value B) {
+ return LLVMBuildLandingPad(Builder_val(B), Ty, PersFn, Int_val(NumClauses),
+ String_val(Name));
+}
+
+/* llvalue -> llvalue -> unit */
+CAMLprim value llvm_add_clause(LLVMValueRef LandingPadInst, LLVMValueRef ClauseVal)
+{
+ LLVMAddClause(LandingPadInst, ClauseVal);
+ return Val_unit;
+}
+
+
+/* llvalue -> bool -> unit */
+CAMLprim value llvm_set_cleanup(LLVMValueRef LandingPadInst, value flag)
+{
+ LLVMSetCleanup(LandingPadInst, Bool_val(flag));
+ return Val_unit;
+}
+
+/* llvalue -> llbuilder -> llvalue */
+CAMLprim LLVMValueRef llvm_build_resume(LLVMValueRef Exn, value B)
+{
+ return LLVMBuildResume(Builder_val(B), Exn);
}
/* llbuilder -> llvalue */
diff --git a/bindings/ocaml/target/llvm_target.ml b/bindings/ocaml/target/llvm_target.ml
index ea5341d..49940ee 100644
--- a/bindings/ocaml/target/llvm_target.ml
+++ b/bindings/ocaml/target/llvm_target.ml
@@ -20,8 +20,6 @@ module TargetData = struct
external add : t -> [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
= "llvm_targetdata_add"
external as_string : t -> string = "llvm_targetdata_as_string"
- external invalidate_struct_layout : t -> Llvm.lltype -> unit
- = "llvm_targetdata_invalidate_struct_layout"
external dispose : t -> unit = "llvm_targetdata_dispose"
end
diff --git a/bindings/ocaml/target/llvm_target.mli b/bindings/ocaml/target/llvm_target.mli
index a82e1b6..c288b9a 100644
--- a/bindings/ocaml/target/llvm_target.mli
+++ b/bindings/ocaml/target/llvm_target.mli
@@ -35,13 +35,6 @@ module TargetData : sig
See the constructor llvm::TargetData::TargetData. *)
external as_string : t -> string = "llvm_targetdata_as_string"
- (** Struct layouts are speculatively cached. If a TargetDataRef is alive when
- types are being refined and removed, this method must be called whenever a
- struct type is removed to avoid a dangling pointer in this cache.
- See the method llvm::TargetData::InvalidateStructLayoutInfo. *)
- external invalidate_struct_layout : t -> Llvm.lltype -> unit
- = "llvm_targetdata_invalidate_struct_layout"
-
(** Deallocates a TargetData.
See the destructor llvm::TargetData::~TargetData. *)
external dispose : t -> unit = "llvm_targetdata_dispose"
diff --git a/bindings/ocaml/target/target_ocaml.c b/bindings/ocaml/target/target_ocaml.c
index cc20e81..ca01e77 100644
--- a/bindings/ocaml/target/target_ocaml.c
+++ b/bindings/ocaml/target/target_ocaml.c
@@ -37,13 +37,6 @@ CAMLprim value llvm_targetdata_as_string(LLVMTargetDataRef TD) {
return Copy;
}
-/* TargetData.t -> Llvm.lltype -> unit */
-CAMLprim value llvm_targetdata_invalidate_struct_layout(LLVMTargetDataRef TD,
- LLVMTypeRef Ty) {
- LLVMInvalidateStructLayout(TD, Ty);
- return Val_unit;
-}
-
/* TargetData.t -> unit */
CAMLprim value llvm_targetdata_dispose(LLVMTargetDataRef TD) {
LLVMDisposeTargetData(TD);
diff --git a/bindings/ocaml/transforms/Makefile b/bindings/ocaml/transforms/Makefile
index 95b00c8..05fcd90 100644
--- a/bindings/ocaml/transforms/Makefile
+++ b/bindings/ocaml/transforms/Makefile
@@ -8,7 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL := ../../..
-DIRS = scalar
+DIRS = scalar ipo
ocamldoc:
$(Verb) for i in $(DIRS) ; do \
diff --git a/bindings/ocaml/transforms/ipo/Makefile b/bindings/ocaml/transforms/ipo/Makefile
new file mode 100644
index 0000000..130d74c
--- /dev/null
+++ b/bindings/ocaml/transforms/ipo/Makefile
@@ -0,0 +1,20 @@
+##===- bindings/ocaml/transforms/scalar/Makefile -----------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This is the makefile for the Objective Caml Llvm_scalar_opts interface.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL := ../../../..
+LIBRARYNAME := llvm_ipo
+DONT_BUILD_RELINKED := 1
+UsedComponents := ipo
+UsedOcamlInterfaces := llvm
+
+include ../../Makefile.ocaml
diff --git a/bindings/ocaml/transforms/ipo/ipo_ocaml.c b/bindings/ocaml/transforms/ipo/ipo_ocaml.c
new file mode 100644
index 0000000..612015c
--- /dev/null
+++ b/bindings/ocaml/transforms/ipo/ipo_ocaml.c
@@ -0,0 +1,104 @@
+/*===-- ipo_ocaml.c - LLVM Ocaml Glue -------------------*- C++ -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This file glues LLVM's ocaml interface to its C interface. These functions *|
+|* are by and large transparent wrappers to the corresponding C functions. *|
+|* *|
+|* Note that these functions intentionally take liberties with the CAMLparamX *|
+|* macros, since most of the parameters are not GC heap objects. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#include "llvm-c/Transforms/IPO.h"
+#include "caml/mlvalues.h"
+#include "caml/misc.h"
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_argument_promotion(LLVMPassManagerRef PM) {
+ LLVMAddArgumentPromotionPass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_constant_merge(LLVMPassManagerRef PM) {
+ LLVMAddConstantMergePass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_dead_arg_elimination(LLVMPassManagerRef PM) {
+ LLVMAddDeadArgEliminationPass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_function_attrs(LLVMPassManagerRef PM) {
+ LLVMAddFunctionAttrsPass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_function_inlining(LLVMPassManagerRef PM) {
+ LLVMAddFunctionInliningPass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_always_inliner_pass(LLVMPassManagerRef PM) {
+ LLVMAddAlwaysInlinerPass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_global_dce(LLVMPassManagerRef PM) {
+ LLVMAddGlobalDCEPass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_global_optimizer(LLVMPassManagerRef PM) {
+ LLVMAddGlobalOptimizerPass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_ipc_propagation(LLVMPassManagerRef PM) {
+ LLVMAddIPConstantPropagationPass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_prune_eh(LLVMPassManagerRef PM) {
+ LLVMAddPruneEHPass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_ipsccp(LLVMPassManagerRef PM) {
+ LLVMAddIPSCCPPass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> bool -> unit */
+CAMLprim value llvm_add_internalize(LLVMPassManagerRef PM, value AllButMain) {
+ LLVMAddInternalizePass(PM, Bool_val(AllButMain));
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_strip_dead_prototypes(LLVMPassManagerRef PM) {
+ LLVMAddStripDeadPrototypesPass(PM);
+ return Val_unit;
+}
+
+/* [`Module] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_strip_symbols(LLVMPassManagerRef PM) {
+ LLVMAddStripSymbolsPass(PM);
+ return Val_unit;
+}
diff --git a/bindings/ocaml/transforms/ipo/llvm_ipo.ml b/bindings/ocaml/transforms/ipo/llvm_ipo.ml
new file mode 100644
index 0000000..1562d10
--- /dev/null
+++ b/bindings/ocaml/transforms/ipo/llvm_ipo.ml
@@ -0,0 +1,65 @@
+(*===-- llvm_ipo.mli - LLVM Ocaml Interface ------------*- OCaml -*-===*
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is distributed under the University of Illinois Open Source
+ * License. See LICENSE.TXT for details.
+ *
+ *===----------------------------------------------------------------------===*)
+
+(** IPO Transforms.
+
+ This interface provides an ocaml API for LLVM interprocedural optimizations, the
+ classes in the [LLVMIPO] library. *)
+
+(** See llvm::createAddArgumentPromotionPass *)
+external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_argument_promotion"
+
+(** See llvm::createConstantMergePass function. *)
+external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_constant_merge"
+
+(** See llvm::createDeadArgEliminationPass function. *)
+external add_dead_arg_elimination :
+ [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_dead_arg_elimination"
+
+(** See llvm::createFunctionAttrsPass function. *)
+external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_function_attrs"
+
+(** See llvm::createFunctionInliningPass function. *)
+external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_function_inlining"
+
+(** See llvm::createGlobalDCEPass function. *)
+external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_global_dce"
+
+(** See llvm::createGlobalOptimizerPass function. *)
+external add_global_optimizer : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_global_optimizer"
+
+(** See llvm::createIPConstantPropagationPass function. *)
+external add_ipc_propagation : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_ipc_propagation"
+
+(** See llvm::createPruneEHPass function. *)
+external add_prune_eh : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_prune_eh"
+
+(** See llvm::createIPSCCPPass function. *)
+external add_ipsccp : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_ipsccp"
+
+(** See llvm::createInternalizePass function. *)
+external add_internalize : [ | `Module ] Llvm.PassManager.t -> bool -> unit =
+ "llvm_add_internalize"
+
+(** See llvm::createStripDeadPrototypesPass function. *)
+external add_strip_dead_prototypes :
+ [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_dead_prototypes"
+
+(** See llvm::createStripSymbolsPass function. *)
+external add_strip_symbols : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_strip_symbols"
diff --git a/bindings/ocaml/transforms/ipo/llvm_ipo.mli b/bindings/ocaml/transforms/ipo/llvm_ipo.mli
new file mode 100644
index 0000000..636103d
--- /dev/null
+++ b/bindings/ocaml/transforms/ipo/llvm_ipo.mli
@@ -0,0 +1,65 @@
+(*===-- llvm_ipo.mli - LLVM Ocaml Interface ------------*- OCaml -*-===*
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is distributed under the University of Illinois Open Source
+ * License. See LICENSE.TXT for details.
+ *
+ *===----------------------------------------------------------------------===*)
+
+(** IPO Transforms.
+
+ This interface provides an ocaml API for LLVM interprocedural optimizations, the
+ classes in the [LLVMIPO] library. *)
+
+(** See llvm::createAddArgumentPromotionPass *)
+external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit =
+
+ "llvm_add_argument_promotion"
+(** See llvm::createConstantMergePass function. *)
+external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_constant_merge"
+
+(** See llvm::createDeadArgEliminationPass function. *)
+external add_dead_arg_elimination :
+ [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_dead_arg_elimination"
+
+(** See llvm::createFunctionAttrsPass function. *)
+external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_function_attrs"
+
+(** See llvm::createFunctionInliningPass function. *)
+external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_function_inlining"
+
+(** See llvm::createGlobalDCEPass function. *)
+external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_global_dce"
+
+(** See llvm::createGlobalOptimizerPass function. *)
+external add_global_optimizer : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_global_optimizer"
+
+(** See llvm::createIPConstantPropagationPass function. *)
+external add_ipc_propagation : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_ipc_propagation"
+
+(** See llvm::createPruneEHPass function. *)
+external add_prune_eh : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_prune_eh"
+
+(** See llvm::createIPSCCPPass function. *)
+external add_ipsccp : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_ipsccp"
+
+(** See llvm::createInternalizePass function. *)
+external add_internalize : [ | `Module ] Llvm.PassManager.t -> bool -> unit =
+ "llvm_add_internalize"
+
+(** See llvm::createStripDeadPrototypesPass function. *)
+external add_strip_dead_prototypes :
+ [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_dead_prototypes"
+
+(** See llvm::createStripSymbolsPass function. *)
+external add_strip_symbols : [ | `Module ] Llvm.PassManager.t -> unit =
+ "llvm_add_strip_symbols"
diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml
index 276e118..93ab1de 100644
--- a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml
+++ b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml
@@ -20,6 +20,15 @@ external add_aggressive_dce : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
external
add_scalar_repl_aggregation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
= "llvm_add_scalar_repl_aggregation"
+
+external
+add_scalar_repl_aggregation_ssa : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_scalar_repl_aggregation_ssa"
+
+external
+add_scalar_repl_aggregation_with_threshold : int -> [<Llvm.PassManager.any] Llvm.PassManager.t
+ -> unit
+ = "llvm_add_scalar_repl_aggregation_with_threshold"
external add_ind_var_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t
-> unit
= "llvm_add_ind_var_simplification"
@@ -67,6 +76,36 @@ external add_memcpy_opt : [<Llvm.PassManager.any] Llvm.PassManager.t
external add_loop_deletion : [<Llvm.PassManager.any] Llvm.PassManager.t
-> unit
= "llvm_add_loop_deletion"
+
+external add_loop_idiom : [<Llvm.PassManager.any] Llvm.PassManager.t
+ -> unit
+ = "llvm_add_loop_idiom"
+
external
add_lib_call_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
= "llvm_add_lib_call_simplification"
+
+external
+add_verifier : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_verifier"
+
+external
+add_correlated_value_propagation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_correlated_value_propagation"
+
+external
+add_early_cse : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_early_cse"
+
+external
+add_lower_expect_intrinsic : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_lower_expect_intrinsic"
+
+external
+add_type_based_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_type_based_alias_analysis"
+
+external
+add_basic_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_basic_alias_analysis"
+
diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli
index d7162c7..121b376 100644
--- a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli
+++ b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli
@@ -35,6 +35,17 @@ external
add_scalar_repl_aggregation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
= "llvm_add_scalar_repl_aggregation"
+(** See the [llvm::createScalarReplAggregatesPassSSA] function. *)
+external
+add_scalar_repl_aggregation_ssa : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_scalar_repl_aggregation_ssa"
+
+(** See the [llvm::createScalarReplAggregatesWithThreshold] function. *)
+external
+add_scalar_repl_aggregation_with_threshold : int -> [<Llvm.PassManager.any] Llvm.PassManager.t
+ -> unit
+ = "llvm_add_scalar_repl_aggregation_with_threshold"
+
(** See the [llvm::createIndVarSimplifyPass] function. *)
external add_ind_var_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t
-> unit
@@ -112,7 +123,42 @@ external add_loop_deletion : [<Llvm.PassManager.any] Llvm.PassManager.t
-> unit
= "llvm_add_loop_deletion"
+external add_loop_idiom : [<Llvm.PassManager.any] Llvm.PassManager.t
+ -> unit
+ = "llvm_add_loop_idiom"
+
(** See the [llvm::createSimplifyLibCallsPass] function. *)
external
add_lib_call_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
= "llvm_add_lib_call_simplification"
+
+(** See the [llvm::createVerifierPass] function. *)
+external
+add_verifier : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_verifier"
+
+(** See the [llvm::createCorrelatedValuePropagationPass] function. *)
+external
+add_correlated_value_propagation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_correlated_value_propagation"
+
+(** See the [llvm::createEarlyCSE] function. *)
+external
+add_early_cse : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_early_cse"
+
+(** See the [llvm::createLowerExpectIntrinsicPass] function. *)
+external
+add_lower_expect_intrinsic : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_lower_expect_intrinsic"
+
+(** See the [llvm::createTypeBasedAliasAnalysisPass] function. *)
+external
+add_type_based_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_type_based_alias_analysis"
+
+(** See the [llvm::createBasicAliasAnalysisPass] function. *)
+external
+add_basic_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
+ = "llvm_add_basic_alias_analysis"
+
diff --git a/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c b/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c
index df44807..2db6456 100644
--- a/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c
+++ b/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c
@@ -50,6 +50,19 @@ CAMLprim value llvm_add_scalar_repl_aggregation(LLVMPassManagerRef PM) {
}
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_scalar_repl_aggregation_ssa(LLVMPassManagerRef PM) {
+ LLVMAddScalarReplAggregatesPassSSA(PM);
+ return Val_unit;
+}
+
+/* [<Llvm.PassManager.any] Llvm.PassManager.t -> int -> unit */
+CAMLprim value llvm_add_scalar_repl_aggregation_with_threshold(value threshold,
+ LLVMPassManagerRef PM) {
+ LLVMAddScalarReplAggregatesPassWithThreshold(PM, Int_val(threshold));
+ return Val_unit;
+}
+
+/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
CAMLprim value llvm_add_ind_var_simplification(LLVMPassManagerRef PM) {
LLVMAddIndVarSimplifyPass(PM);
return Val_unit;
@@ -69,7 +82,7 @@ CAMLprim value llvm_add_licm(LLVMPassManagerRef PM) {
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
CAMLprim value llvm_add_loop_unswitch(LLVMPassManagerRef PM) {
- LLVMAddLoopUnrollPass(PM);
+ LLVMAddLoopUnswitchPass(PM);
return Val_unit;
}
@@ -140,7 +153,49 @@ CAMLprim value llvm_add_loop_deletion(LLVMPassManagerRef PM) {
}
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_loop_idiom(LLVMPassManagerRef PM) {
+ LLVMAddLoopIdiomPass(PM);
+ return Val_unit;
+}
+
+/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
CAMLprim value llvm_add_lib_call_simplification(LLVMPassManagerRef PM) {
LLVMAddSimplifyLibCallsPass(PM);
return Val_unit;
}
+
+/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_verifier(LLVMPassManagerRef PM) {
+ LLVMAddVerifierPass(PM);
+ return Val_unit;
+}
+
+/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_correlated_value_propagation(LLVMPassManagerRef PM) {
+ LLVMAddCorrelatedValuePropagationPass(PM);
+ return Val_unit;
+}
+
+/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_early_cse(LLVMPassManagerRef PM) {
+ LLVMAddEarlyCSEPass(PM);
+ return Val_unit;
+}
+
+/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_lower_expect_intrinsic(LLVMPassManagerRef PM) {
+ LLVMAddLowerExpectIntrinsicPass(PM);
+ return Val_unit;
+}
+
+/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_type_based_alias_analysis(LLVMPassManagerRef PM) {
+ LLVMAddTypeBasedAliasAnalysisPass(PM);
+ return Val_unit;
+}
+
+/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
+CAMLprim value llvm_add_basic_alias_analysis(LLVMPassManagerRef PM) {
+ LLVMAddBasicAliasAnalysisPass(PM);
+ return Val_unit;
+}
diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake
index 46f33de..0381dbf 100755
--- a/cmake/config-ix.cmake
+++ b/cmake/config-ix.cmake
@@ -198,11 +198,6 @@ if( LLVM_USING_GLIBC )
add_llvm_definitions( -D_GNU_SOURCE )
endif()
-# Type checks
-check_type_exists(std::bidirectional_iterator<int,int> "iterator;iostream" HAVE_BI_ITERATOR)
-check_type_exists(std::iterator<int,int,int> iterator HAVE_STD_ITERATOR)
-check_type_exists(std::forward_iterator<int,int> iterator HAVE_FWD_ITERATOR)
-
set(headers "")
if (HAVE_SYS_TYPES_H)
set(headers ${headers} "sys/types.h")
@@ -277,7 +272,7 @@ else()
unset(HAVE_FFI_CALL CACHE)
endif( LLVM_ENABLE_FFI )
-# Define LLVM_MULTITHREADED if gcc atomic builtins exists.
+# Define LLVM_HAS_ATOMICS if gcc or MSVC atomic builtins are supported.
include(CheckAtomic)
if( LLVM_ENABLE_PIC )
@@ -336,7 +331,7 @@ else ()
message(STATUS "Native target architecture is ${LLVM_NATIVE_ARCH}")
set(LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target)
set(LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo)
- set(LLVM_NATIVE_MCASMINFO LLVMInitialize${LLVM_NATIVE_ARCH}MCAsmInfo)
+ set(LLVM_NATIVE_TARGETMC LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC)
set(LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter)
endif ()
diff --git a/cmake/modules/AddLLVM.cmake b/cmake/modules/AddLLVM.cmake
index c13143b..b486fe4 100755
--- a/cmake/modules/AddLLVM.cmake
+++ b/cmake/modules/AddLLVM.cmake
@@ -24,16 +24,17 @@ macro(add_llvm_library name)
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
endif()
- # The LLVM Target library shall be built before its sublibraries
- # (asmprinter, etc) because those may use tablegenned files which
- # generation is triggered by the main LLVM target library. Necessary
- # for parallel builds:
- if( CURRENT_LLVM_TARGET )
- add_dependencies(${name} ${CURRENT_LLVM_TARGET})
- endif()
set_target_properties(${name} PROPERTIES FOLDER "Libraries")
endmacro(add_llvm_library name)
+macro(add_llvm_library_dependencies name)
+ # Save the dependencies of the LLVM library in a variable so that we can
+ # query it when resolve llvm-config-style component -> library mappings.
+ set_property(GLOBAL PROPERTY LLVM_LIB_DEPS_${name} ${ARGN})
+
+ # Then add the actual dependencies to the library target.
+ target_link_libraries(${name} ${ARGN})
+endmacro(add_llvm_library_dependencies name)
macro(add_llvm_loadable_module name)
if( NOT LLVM_ON_UNIX OR CYGWIN )
@@ -124,16 +125,9 @@ endmacro(add_llvm_utility name)
macro(add_llvm_target target_name)
- if( TABLEGEN_OUTPUT )
- add_custom_target(${target_name}Table_gen
- DEPENDS ${TABLEGEN_OUTPUT})
- add_dependencies(${target_name}Table_gen ${LLVM_COMMON_DEPENDS})
- endif( TABLEGEN_OUTPUT )
- include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
+ include_directories(BEFORE
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR})
add_llvm_library(LLVM${target_name} ${ARGN} ${TABLEGEN_OUTPUT})
- if ( TABLEGEN_OUTPUT )
- add_dependencies(LLVM${target_name} ${target_name}Table_gen)
- set_target_properties(${target_name}Table_gen PROPERTIES FOLDER "Tablegenning")
- endif (TABLEGEN_OUTPUT)
set( CURRENT_LLVM_TARGET LLVM${target_name} )
endmacro(add_llvm_target)
diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt
index 257deb6..2dcfa14 100644
--- a/cmake/modules/CMakeLists.txt
+++ b/cmake/modules/CMakeLists.txt
@@ -3,6 +3,12 @@ set(LLVM_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
get_property(llvm_libs GLOBAL PROPERTY LLVM_LIBS)
+foreach(lib ${llvm_libs})
+ get_property(llvm_lib_deps GLOBAL PROPERTY LLVM_LIB_DEPS_${lib})
+ set(all_llvm_lib_deps
+ "${all_llvm_lib_deps}\nset_property(GLOBAL PROPERTY LLVM_LIB_DEPS_${lib} ${llvm_lib_deps})")
+endforeach(lib)
+
configure_file(
LLVMConfig.cmake.in
${llvm_cmake_builddir}/LLVMConfig.cmake
@@ -17,7 +23,6 @@ install(FILES
${llvm_cmake_builddir}/LLVMConfig.cmake
${llvm_cmake_builddir}/LLVMConfigVersion.cmake
LLVM-Config.cmake
- LLVMLibDeps.cmake
DESTINATION share/llvm/cmake)
install(DIRECTORY .
@@ -27,8 +32,6 @@ install(DIRECTORY .
PATTERN LLVMConfig.cmake EXCLUDE
PATTERN LLVMConfigVersion.cmake EXCLUDE
PATTERN LLVM-Config.cmake EXCLUDE
- PATTERN LLVMLibDeps.cmake EXCLUDE
- PATTERN FindBison.cmake EXCLUDE
PATTERN GetTargetTriple.cmake EXCLUDE
PATTERN VersionFromVCS.cmake EXCLUDE
PATTERN CheckAtomic.cmake EXCLUDE)
diff --git a/cmake/modules/CheckAtomic.cmake b/cmake/modules/CheckAtomic.cmake
index f40ff4d..0d63a82 100644
--- a/cmake/modules/CheckAtomic.cmake
+++ b/cmake/modules/CheckAtomic.cmake
@@ -22,8 +22,8 @@ int main() {
#endif
return 0;
}
-" LLVM_MULTITHREADED)
+" LLVM_HAS_ATOMICS)
-if( NOT LLVM_MULTITHREADED )
+if( NOT LLVM_HAS_ATOMICS )
message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing")
endif()
diff --git a/cmake/modules/CrossCompileLLVM.cmake b/cmake/modules/CrossCompileLLVM.cmake
deleted file mode 100644
index 98e60a5..0000000
--- a/cmake/modules/CrossCompileLLVM.cmake
+++ /dev/null
@@ -1,26 +0,0 @@
-
-if( ${LLVM_TABLEGEN} STREQUAL "tblgen" )
- set(CX_NATIVE_TG_DIR "${CMAKE_BINARY_DIR}/native")
- set(LLVM_TABLEGEN_EXE "${CX_NATIVE_TG_DIR}/bin/tblgen")
-
- add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}
- COMMAND ${CMAKE_COMMAND} -E make_directory ${CX_NATIVE_TG_DIR}
- COMMENT "Creating ${CX_NATIVE_TG_DIR}...")
-
- add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}/CMakeCache.txt
- COMMAND ${CMAKE_COMMAND} -UMAKE_TOOLCHAIN_FILE -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}
- WORKING_DIRECTORY ${CX_NATIVE_TG_DIR}
- DEPENDS ${CX_NATIVE_TG_DIR}
- COMMENT "Configuring native TableGen...")
-
- add_custom_command(OUTPUT ${LLVM_TABLEGEN_EXE}
- COMMAND ${CMAKE_BUILD_TOOL}
- DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt
- WORKING_DIRECTORY ${CX_NATIVE_TG_DIR}/utils/TableGen
- COMMENT "Building native TableGen...")
- add_custom_target(NativeTableGen DEPENDS ${LLVM_TABLEGEN_EXE})
-
- add_dependencies(tblgen NativeTableGen)
-
- set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CX_NATIVE_TG_DIR})
-endif()
diff --git a/cmake/modules/FindBison.cmake b/cmake/modules/FindBison.cmake
deleted file mode 100755
index 0320ae3..0000000
--- a/cmake/modules/FindBison.cmake
+++ /dev/null
@@ -1,52 +0,0 @@
-# - Try to find Bison
-# Once done this will define
-#
-# BISON_FOUND - system has Bison
-# BISON_EXECUTABLE - path of the bison executable
-# BISON_VERSION - the version string, like "2.5.31"
-#
-
-MACRO(FIND_BISON)
- FIND_PROGRAM(BISON_EXECUTABLE NAMES bison)
-
- IF(BISON_EXECUTABLE)
- SET(BISON_FOUND TRUE)
-
- EXECUTE_PROCESS(COMMAND ${BISON_EXECUTABLE} --version
- OUTPUT_VARIABLE _BISON_VERSION
- )
- string (REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" BISON_VERSION "${_bison_VERSION}")
- ENDIF(BISON_EXECUTABLE)
-
- IF(BISON_FOUND)
- IF(NOT Bison_FIND_QUIETLY)
- MESSAGE(STATUS "Found Bison: ${BISON_EXECUTABLE}")
- ENDIF(NOT Bison_FIND_QUIETLY)
- ELSE(BISON_FOUND)
- IF(Bison_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "Could not find Bison")
- ENDIF(Bison_FIND_REQUIRED)
- ENDIF(BISON_FOUND)
-ENDMACRO(FIND_BISON)
-
-MACRO(BISON_GENERATOR _PREFIX _Y_INPUT _H_OUTPUT _CPP_OUTPUT)
- IF(BISON_EXECUTABLE)
- GET_FILENAME_COMPONENT(_Y_DIR ${_Y_INPUT} PATH)
- ADD_CUSTOM_COMMAND(
- OUTPUT ${_CPP_OUTPUT}
- OUTPUT ${_H_OUTPUT}
- DEPENDS ${_Y_INPUT}
- COMMAND ${BISON_EXECUTABLE}
- ARGS
- -p ${_PREFIX} -o"${_CPP_OUTPUT}"
- --defines="${_H_OUTPUT}" ${_Y_INPUT}
- WORKING_DIRECTORY ${_Y_DIR}
- )
- SET_SOURCE_FILES_PROPERTIES(
- ${_CPP_OUTPUT} ${_H_OUTPUT}
- GENERATED
- )
- ELSE(BISON_EXECUTABLE)
- MESSAGE(SEND_ERROR "Can't find bison program, and it's required")
- ENDIF(BISON_EXECUTABLE)
-ENDMACRO(BISON_GENERATOR)
diff --git a/cmake/modules/HandleLLVMOptions.cmake b/cmake/modules/HandleLLVMOptions.cmake
index d0427ac..9dc1624 100644
--- a/cmake/modules/HandleLLVMOptions.cmake
+++ b/cmake/modules/HandleLLVMOptions.cmake
@@ -155,6 +155,7 @@ if( MSVC )
-wd4351 # Suppress 'new behavior: elements of array 'array' will be default initialized'
-wd4355 # Suppress ''this' : used in base member initializer list'
-wd4503 # Suppress ''identifier' : decorated name length exceeded, name was truncated'
+ -wd4551 # Suppress 'function call missing argument list'
-wd4624 # Suppress ''derived class' : destructor could not be generated because a base class destructor is inaccessible'
-wd4715 # Suppress ''function' : not all control paths return a value'
-wd4800 # Suppress ''type' : forcing value to bool 'true' or 'false' (performance warning)'
@@ -185,7 +186,8 @@ elseif( LLVM_COMPILER_IS_GCC_COMPATIBLE )
endif (LLVM_ENABLE_WERROR)
endif( MSVC )
-add_llvm_definitions( -D__STDC_LIMIT_MACROS )
add_llvm_definitions( -D__STDC_CONSTANT_MACROS )
+add_llvm_definitions( -D__STDC_FORMAT_MACROS )
+add_llvm_definitions( -D__STDC_LIMIT_MACROS )
option(LLVM_INCLUDE_TESTS "Generate build targets for the LLVM unit tests." ON)
diff --git a/cmake/modules/LLVM-Config.cmake b/cmake/modules/LLVM-Config.cmake
index a6286fe..b5f262a 100755
--- a/cmake/modules/LLVM-Config.cmake
+++ b/cmake/modules/LLVM-Config.cmake
@@ -135,14 +135,14 @@ function(explicit_map_components_to_libraries out_libs)
string(TOUPPER "${c}" capitalized)
list(FIND capitalized_libs LLVM${capitalized} lib_idx)
if( lib_idx LESS 0 )
- # The component is unknown. Maybe is an omitted target?
- is_llvm_target_library(${c} iltl_result)
- if( NOT iltl_result )
- message(FATAL_ERROR "Library `${c}' not found in list of llvm libraries.")
- endif()
+ # The component is unknown. Maybe is an omitted target?
+ is_llvm_target_library(${c} iltl_result)
+ if( NOT iltl_result )
+ message(FATAL_ERROR "Library `${c}' not found in list of llvm libraries.")
+ endif()
else( lib_idx LESS 0 )
- list(GET llvm_libs ${lib_idx} canonical_lib)
- list(APPEND expanded_components ${canonical_lib})
+ list(GET llvm_libs ${lib_idx} canonical_lib)
+ list(APPEND expanded_components ${canonical_lib})
endif( lib_idx LESS 0 )
endif( NOT idx LESS 0 )
endforeach(c)
@@ -152,7 +152,8 @@ function(explicit_map_components_to_libraries out_libs)
set(processed)
while( cursor LESS lst_size )
list(GET expanded_components ${cursor} lib)
- list(APPEND expanded_components ${MSVC_LIB_DEPS_${lib}})
+ get_property(lib_deps GLOBAL PROPERTY LLVM_LIB_DEPS_${lib})
+ list(APPEND expanded_components ${lib_deps})
# Remove duplicates at the front:
list(REVERSE expanded_components)
list(REMOVE_DUPLICATES expanded_components)
@@ -175,29 +176,3 @@ function(explicit_map_components_to_libraries out_libs)
endforeach(c)
set(${out_libs} ${result} PARENT_SCOPE)
endfunction(explicit_map_components_to_libraries)
-
-
-# The library dependency data is contained in the file
-# LLVMLibDeps.cmake on this directory. It is automatically generated
-# by tools/llvm-config/CMakeLists.txt when the build comprises all the
-# targets and we are on a environment Posix enough to build the
-# llvm-config script. This, in practice, just excludes MSVC.
-
-# When you remove or rename a library from the build, be sure to
-# remove its file from lib/ as well, or the GenLibDeps.pl script will
-# include it on its analysis!
-
-# The format generated by GenLibDeps.pl
-
-# LLVMARMAsmPrinter.o: LLVMARMCodeGen.o libLLVMAsmPrinter.a libLLVMCodeGen.a libLLVMCore.a libLLVMSupport.a libLLVMTarget.a
-
-# is translated to:
-
-# set(MSVC_LIB_DEPS_LLVMARMAsmPrinter LLVMARMCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMSupport LLVMTarget)
-
-# It is necessary to remove the `lib' prefix and the `.a'.
-
-# This 'sed' script should do the trick:
-# sed -e s'#\.a##g' -e 's#libLLVM#LLVM#g' -e 's#: # #' -e 's#\(.*\)#set(MSVC_LIB_DEPS_\1)#' ~/llvm/tools/llvm-config/LibDeps.txt
-
-include(LLVMLibDeps)
diff --git a/cmake/modules/LLVMConfig.cmake.in b/cmake/modules/LLVMConfig.cmake.in
index 5a048b7..6b202b2 100644
--- a/cmake/modules/LLVMConfig.cmake.in
+++ b/cmake/modules/LLVMConfig.cmake.in
@@ -12,6 +12,8 @@ set(LLVM_TARGETS_TO_BUILD @LLVM_TARGETS_TO_BUILD@)
set(LLVM_TARGETS_WITH_JIT @LLVM_TARGETS_WITH_JIT@)
+@all_llvm_lib_deps@
+
set(TARGET_TRIPLE "@TARGET_TRIPLE@")
set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@)
diff --git a/cmake/modules/LLVMLibDeps.cmake b/cmake/modules/LLVMLibDeps.cmake
deleted file mode 100644
index 14575e5..0000000
--- a/cmake/modules/LLVMLibDeps.cmake
+++ /dev/null
@@ -1,83 +0,0 @@
-set(MSVC_LIB_DEPS_LLVMARMAsmParser LLVMARMCodeGen LLVMARMInfo LLVMMC LLVMMCParser LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMARMAsmPrinter LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMARMCodeGen LLVMARMAsmPrinter LLVMARMDesc LLVMARMInfo LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMARMDesc LLVMARMInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMARMDisassembler LLVMARMCodeGen LLVMARMDesc LLVMARMInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMARMInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMAlphaCodeGen LLVMAlphaDesc LLVMAlphaInfo LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMAlphaDesc LLVMAlphaInfo LLVMMC)
-set(MSVC_LIB_DEPS_LLVMAlphaInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMAnalysis LLVMCore LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMArchive LLVMBitReader LLVMCore LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMAsmParser LLVMCore LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMAsmPrinter LLVMAnalysis LLVMCodeGen LLVMCore LLVMMC LLVMMCParser LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMBitReader LLVMCore LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMBitWriter LLVMCore LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMBlackfinCodeGen LLVMAsmPrinter LLVMBlackfinDesc LLVMBlackfinInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMBlackfinDesc LLVMBlackfinInfo LLVMMC)
-set(MSVC_LIB_DEPS_LLVMBlackfinInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMCBackend LLVMAnalysis LLVMCBackendInfo LLVMCodeGen LLVMCore LLVMMC LLVMScalarOpts LLVMSupport LLVMTarget LLVMTransformUtils)
-set(MSVC_LIB_DEPS_LLVMCBackendInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMCellSPUCodeGen LLVMAsmPrinter LLVMCellSPUDesc LLVMCellSPUInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMCellSPUDesc LLVMCellSPUInfo LLVMMC)
-set(MSVC_LIB_DEPS_LLVMCellSPUInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMCodeGen LLVMAnalysis LLVMCore LLVMMC LLVMScalarOpts LLVMSupport LLVMTarget LLVMTransformUtils)
-set(MSVC_LIB_DEPS_LLVMCore LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMCppBackend LLVMCore LLVMCppBackendInfo LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMCppBackendInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMExecutionEngine LLVMCore LLVMMC LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMInstCombine LLVMAnalysis LLVMCore LLVMSupport LLVMTarget LLVMTransformUtils)
-set(MSVC_LIB_DEPS_LLVMInstrumentation LLVMAnalysis LLVMCore LLVMSupport LLVMTransformUtils)
-set(MSVC_LIB_DEPS_LLVMInterpreter LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMJIT LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMMC LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMLinker LLVMArchive LLVMBitReader LLVMCore LLVMSupport LLVMTransformUtils)
-set(MSVC_LIB_DEPS_LLVMMBlazeAsmParser LLVMMBlazeCodeGen LLVMMBlazeInfo LLVMMC LLVMMCParser LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMMBlazeAsmPrinter LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMMBlazeCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMBlazeAsmPrinter LLVMMBlazeDesc LLVMMBlazeInfo LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMMBlazeDesc LLVMMBlazeInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMMBlazeDisassembler LLVMMBlazeCodeGen LLVMMBlazeDesc LLVMMBlazeInfo LLVMMC)
-set(MSVC_LIB_DEPS_LLVMMBlazeInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMMCDisassembler LLVMARMAsmParser LLVMARMCodeGen LLVMARMDesc LLVMARMDisassembler LLVMARMInfo LLVMAlphaCodeGen LLVMAlphaDesc LLVMAlphaInfo LLVMBlackfinCodeGen LLVMBlackfinDesc LLVMBlackfinInfo LLVMCBackend LLVMCBackendInfo LLVMCellSPUCodeGen LLVMCellSPUDesc LLVMCellSPUInfo LLVMCppBackend LLVMCppBackendInfo LLVMMBlazeAsmParser LLVMMBlazeCodeGen LLVMMBlazeDesc LLVMMBlazeDisassembler LLVMMBlazeInfo LLVMMC LLVMMCParser LLVMMSP430CodeGen LLVMMSP430Desc LLVMMSP430Info LLVMMipsCodeGen LLVMMipsDesc LLVMMipsInfo LLVMPTXCodeGen LLVMPTXDesc LLVMPTXInfo LLVMPowerPCCodeGen LLVMPowerPCDesc LLVMPowerPCInfo LLVMSparcCodeGen LLVMSparcDesc LLVMSparcInfo LLVMSupport LLVMSystemZCodeGen LLVMSystemZDesc LLVMSystemZInfo LLVMTarget LLVMX86AsmParser LLVMX86CodeGen LLVMX86Desc LLVMX86Disassembler LLVMX86Info LLVMXCoreCodeGen LLVMXCoreDesc LLVMXCoreInfo)
-set(MSVC_LIB_DEPS_LLVMMCJIT LLVMCore LLVMExecutionEngine LLVMRuntimeDyld LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMMCParser LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMMSP430AsmPrinter LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMMSP430CodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMSP430AsmPrinter LLVMMSP430Desc LLVMMSP430Info LLVMSelectionDAG LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMMSP430Desc LLVMMC LLVMMSP430Info)
-set(MSVC_LIB_DEPS_LLVMMSP430Info LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMMipsAsmPrinter LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMMipsCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMipsAsmPrinter LLVMMipsDesc LLVMMipsInfo LLVMSelectionDAG LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMMipsDesc LLVMMC LLVMMipsInfo LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMMipsInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMObject LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMPTXCodeGen LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPTXDesc LLVMPTXInfo LLVMSelectionDAG LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMPTXDesc LLVMMC LLVMPTXInfo LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMPTXInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMPowerPCAsmPrinter LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMPowerPCCodeGen LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPowerPCAsmPrinter LLVMPowerPCDesc LLVMPowerPCInfo LLVMSelectionDAG LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMPowerPCDesc LLVMMC LLVMPowerPCInfo LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMPowerPCInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMRuntimeDyld LLVMObject LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMScalarOpts LLVMAnalysis LLVMCore LLVMInstCombine LLVMSupport LLVMTarget LLVMTransformUtils)
-set(MSVC_LIB_DEPS_LLVMSelectionDAG LLVMAnalysis LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMTarget LLVMTransformUtils)
-set(MSVC_LIB_DEPS_LLVMSparcCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSparcDesc LLVMSparcInfo LLVMSupport LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMSparcDesc LLVMMC LLVMSparcInfo LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMSparcInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMSupport )
-set(MSVC_LIB_DEPS_LLVMSystemZCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystemZDesc LLVMSystemZInfo LLVMTarget)
-set(MSVC_LIB_DEPS_LLVMSystemZDesc LLVMMC LLVMSystemZInfo)
-set(MSVC_LIB_DEPS_LLVMSystemZInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMTarget LLVMCore LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMTransformUtils LLVMAnalysis LLVMCore LLVMSupport LLVMTarget LLVMipa)
-set(MSVC_LIB_DEPS_LLVMX86AsmParser LLVMMC LLVMMCParser LLVMSupport LLVMTarget LLVMX86Info)
-set(MSVC_LIB_DEPS_LLVMX86AsmPrinter LLVMMC LLVMSupport LLVMX86Utils)
-set(MSVC_LIB_DEPS_LLVMX86CodeGen LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget LLVMX86AsmPrinter LLVMX86Desc LLVMX86Info LLVMX86Utils)
-set(MSVC_LIB_DEPS_LLVMX86Desc LLVMMC LLVMSupport LLVMX86Info)
-set(MSVC_LIB_DEPS_LLVMX86Disassembler LLVMMC LLVMSupport LLVMX86Info)
-set(MSVC_LIB_DEPS_LLVMX86Info LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMX86Utils LLVMCore LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMXCoreCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget LLVMXCoreDesc LLVMXCoreInfo)
-set(MSVC_LIB_DEPS_LLVMXCoreDesc LLVMMC LLVMXCoreInfo)
-set(MSVC_LIB_DEPS_LLVMXCoreInfo LLVMMC LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMipa LLVMAnalysis LLVMCore LLVMSupport)
-set(MSVC_LIB_DEPS_LLVMipo LLVMAnalysis LLVMCore LLVMScalarOpts LLVMSupport LLVMTarget LLVMTransformUtils LLVMipa)
diff --git a/cmake/modules/TableGen.cmake b/cmake/modules/TableGen.cmake
index 9d67137..3dc820b 100644
--- a/cmake/modules/TableGen.cmake
+++ b/cmake/modules/TableGen.cmake
@@ -2,7 +2,7 @@
# Extra parameters for `tblgen' may come after `ofn' parameter.
# Adds the name of the generated file to TABLEGEN_OUTPUT.
-macro(tablegen ofn)
+macro(tablegen project ofn)
file(GLOB local_tds "*.td")
file(GLOB_RECURSE global_tds "${LLVM_MAIN_SRC_DIR}/include/llvm/*.td")
@@ -14,14 +14,14 @@ macro(tablegen ofn)
endif()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
# Generate tablegen output in a temporary file.
- COMMAND ${LLVM_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR}
-I ${LLVM_MAIN_SRC_DIR}/lib/Target -I ${LLVM_MAIN_INCLUDE_DIR}
${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
-o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
# The file in LLVM_TARGET_DEFINITIONS may be not in the current
# directory and local_tds may not contain it, so we must
# explicitly list it here:
- DEPENDS ${LLVM_TABLEGEN_EXE} ${local_tds} ${global_tds}
+ DEPENDS ${${project}_TABLEGEN_EXE} ${local_tds} ${global_tds}
${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
COMMENT "Building ${ofn}..."
)
@@ -44,3 +44,82 @@ macro(tablegen ofn)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${ofn}
PROPERTIES GENERATED 1)
endmacro(tablegen)
+
+function(add_public_tablegen_target target)
+ # Creates a target for publicly exporting tablegen dependencies.
+ if( TABLEGEN_OUTPUT )
+ add_custom_target(${target}
+ DEPENDS ${TABLEGEN_OUTPUT})
+ add_dependencies(${target} ${LLVM_COMMON_DEPENDS})
+ endif( TABLEGEN_OUTPUT )
+endfunction()
+
+if(CMAKE_CROSSCOMPILING)
+ set(CX_NATIVE_TG_DIR "${CMAKE_BINARY_DIR}/native")
+
+ add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${CX_NATIVE_TG_DIR}
+ COMMENT "Creating ${CX_NATIVE_TG_DIR}...")
+
+ add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}/CMakeCache.txt
+ COMMAND ${CMAKE_COMMAND} -UMAKE_TOOLCHAIN_FILE -DCMAKE_BUILD_TYPE=Release
+ -DLLVM_BUILD_POLLY=OFF ${CMAKE_SOURCE_DIR}
+ WORKING_DIRECTORY ${CX_NATIVE_TG_DIR}
+ DEPENDS ${CX_NATIVE_TG_DIR}
+ COMMENT "Configuring native TableGen...")
+
+ add_custom_target(ConfigureNativeTableGen DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt)
+
+ set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CX_NATIVE_TG_DIR})
+endif()
+
+macro(add_tablegen target project)
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR})
+
+ add_llvm_utility(${target} ${ARGN})
+
+ set(${project}_TABLEGEN "${target}" CACHE
+ STRING "Native TableGen executable. Saves building one when cross-compiling.")
+
+ # Upgrade existing LLVM_TABLEGEN setting.
+ if(${project} STREQUAL LLVM)
+ if(${LLVM_TABLEGEN} STREQUAL tblgen)
+ set(LLVM_TABLEGEN "${target}" CACHE
+ STRING "Native TableGen executable. Saves building one when cross-compiling."
+ FORCE)
+ endif()
+ endif()
+
+ # Effective tblgen executable to be used:
+ set(${project}_TABLEGEN_EXE ${${project}_TABLEGEN} PARENT_SCOPE)
+
+ if(CMAKE_CROSSCOMPILING)
+ if( ${${project}_TABLEGEN} STREQUAL "${target}" )
+ set(${project}_TABLEGEN_EXE "${CX_NATIVE_TG_DIR}/bin/${target}")
+ set(${project}_TABLEGEN_EXE ${${project}_TABLEGEN_EXE} PARENT_SCOPE)
+
+ add_custom_command(OUTPUT ${${project}_TABLEGEN_EXE}
+ COMMAND ${CMAKE_BUILD_TOOL} ${target}
+ DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt
+ WORKING_DIRECTORY ${CX_NATIVE_TG_DIR}
+ COMMENT "Building native TableGen...")
+ add_custom_target(${project}NativeTableGen DEPENDS ${${project}_TABLEGEN_EXE})
+ add_dependencies(${project}NativeTableGen ConfigureNativeTableGen)
+
+ add_dependencies(${target} ${project}NativeTableGen)
+ endif()
+ endif()
+
+ target_link_libraries(${target} LLVMSupport LLVMTableGen)
+ if( MINGW )
+ target_link_libraries(${target} imagehlp psapi)
+ if(CMAKE_SIZEOF_VOID_P MATCHES "8")
+ set_target_properties(${target} PROPERTIES LINK_FLAGS -Wl,--stack,16777216)
+ endif(CMAKE_SIZEOF_VOID_P MATCHES "8")
+ endif( MINGW )
+ if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD AND NOT BEOS )
+ target_link_libraries(${target} pthread)
+ endif()
+
+ install(TARGETS ${target} RUNTIME DESTINATION bin)
+endmacro()
diff --git a/configure b/configure
index ae7fcd7..fbd95ca 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.60 for llvm 3.0svn.
+# Generated by GNU Autoconf 2.61 for llvm 3.0.
#
# Report bugs to <llvmbugs@cs.uiuc.edu>.
#
@@ -14,7 +14,8 @@
## M4sh Initialization. ##
## --------------------- ##
-# Be Bourne compatible
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
@@ -23,10 +24,13 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
- case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
+
+
# PATH needs CR
@@ -219,7 +223,7 @@ test \$exitcode = 0) || { (exit 1); exit 1; }
else
as_candidate_shells=
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
@@ -237,7 +241,6 @@ IFS=$as_save_IFS
# Try only shells that exist, to save several forks.
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
{ ("$as_shell") 2> /dev/null <<\_ASEOF
-# Be Bourne compatible
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
@@ -246,10 +249,12 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
- case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
+
:
_ASEOF
@@ -257,7 +262,6 @@ _ASEOF
CONFIG_SHELL=$as_shell
as_have_required=yes
if { "$as_shell" 2> /dev/null <<\_ASEOF
-# Be Bourne compatible
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
@@ -266,10 +270,12 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
- case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
+
:
(as_func_return () {
@@ -516,19 +522,28 @@ else
as_mkdir_p=false
fi
-# Find out whether ``test -x'' works. Don't use a zero-byte file, as
-# systems may use methods other than mode bits to determine executability.
-cat >conf$$.file <<_ASEOF
-#! /bin/sh
-exit 0
-_ASEOF
-chmod +x conf$$.file
-if test -x conf$$.file >/dev/null 2>&1; then
- as_executable_p="test -x"
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
else
- as_executable_p=:
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
fi
-rm -f conf$$.file
+as_executable_p=$as_test_x
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -561,44 +576,44 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='llvm'
PACKAGE_TARNAME='-llvm-'
-PACKAGE_VERSION='3.0svn'
-PACKAGE_STRING='llvm 3.0svn'
+PACKAGE_VERSION='3.0'
+PACKAGE_STRING='llvm 3.0'
PACKAGE_BUGREPORT='llvmbugs@cs.uiuc.edu'
ac_unique_file="lib/VMCore/Module.cpp"
# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
-#if HAVE_SYS_TYPES_H
+#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_STAT_H
+#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
-#if STDC_HEADERS
+#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
-# if HAVE_STDLIB_H
+# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
-#if HAVE_STRING_H
-# if !STDC_HEADERS && HAVE_MEMORY_H
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
# include <memory.h>
# endif
# include <string.h>
#endif
-#if HAVE_STRINGS_H
+#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
-#if HAVE_INTTYPES_H
+#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
-#if HAVE_STDINT_H
+#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
-#if HAVE_UNISTD_H
+#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
@@ -640,6 +655,17 @@ build_alias
host_alias
target_alias
LLVM_COPYRIGHT
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+CXX
+CXXFLAGS
+ac_ct_CXX
+CPP
subdirs
ENABLE_POLLY
LLVM_HAS_POLLY
@@ -664,14 +690,6 @@ LLVM_ON_UNIX
LLVM_ON_WIN32
ARCH
ENDIAN
-CC
-CFLAGS
-LDFLAGS
-CPPFLAGS
-ac_ct_CC
-EXEEXT
-OBJEXT
-CPP
GREP
EGREP
LLVM_CROSS_COMPILING
@@ -702,16 +720,10 @@ LLVM_ENUM_ASM_PRINTERS
LLVM_ENUM_ASM_PARSERS
LLVM_ENUM_DISASSEMBLERS
ENABLE_CBE_PRINTF_A
-CLANGPATH
-CLANGXXPATH
-ENABLE_BUILT_CLANG
OPTIMIZE_OPTION
EXTRA_OPTIONS
EXTRA_LD_OPTIONS
BINUTILS_INCDIR
-CXX
-CXXFLAGS
-ac_ct_CXX
NM
ifGNUmake
LN_S
@@ -763,11 +775,6 @@ INSTALL_LTDL_FALSE
CONVENIENCE_LTDL_TRUE
CONVENIENCE_LTDL_FALSE
LIBADD_DL
-LLVMGCCCOMMAND
-LLVMGXXCOMMAND
-LLVMGCC
-LLVMGXX
-LLVMCC_OPTION
NO_VARIADIC_MACROS
NO_MISSING_FIELD_INITIALIZERS
USE_UDIS86
@@ -775,13 +782,6 @@ USE_OPROFILE
HAVE_PTHREAD
HUGE_VAL_SANITY
MMAP_FILE
-LLVMCC_EMITIR_FLAG
-LLVMCC1
-LLVMCC1PLUS
-LLVMGCCDIR
-LLVMGCC_LANGS
-LLVMGCC_DRAGONEGG
-LLVMCC_DISABLEOPT_FLAGS
SHLIBEXT
SHLIBPATH_VAR
LLVM_PREFIX
@@ -809,11 +809,12 @@ target_alias
CC
CFLAGS
LDFLAGS
+LIBS
CPPFLAGS
-CPP
CXX
CXXFLAGS
-CCC'
+CCC
+CPP'
ac_subdirs_all='projects/llvm-gcc
projects/test-suite
projects/llvm-test
@@ -932,10 +933,10 @@ do
-disable-* | --disable-*)
ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
{ echo "$as_me: error: invalid feature name: $ac_feature" >&2
{ (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
eval enable_$ac_feature=no ;;
-docdir | --docdir | --docdi | --doc | --do)
@@ -951,10 +952,10 @@ do
-enable-* | --enable-*)
ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
{ echo "$as_me: error: invalid feature name: $ac_feature" >&2
{ (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
eval enable_$ac_feature=\$ac_optarg ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
@@ -1148,19 +1149,19 @@ do
-with-* | --with-*)
ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
{ echo "$as_me: error: invalid package name: $ac_package" >&2
{ (exit 1); exit 1; }; }
- ac_package=`echo $ac_package| sed 's/-/_/g'`
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
eval with_$ac_package=\$ac_optarg ;;
-without-* | --without-*)
ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
{ echo "$as_me: error: invalid package name: $ac_package" >&2
{ (exit 1); exit 1; }; }
- ac_package=`echo $ac_package | sed 's/-/_/g'`
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
eval with_$ac_package=no ;;
--x)
@@ -1329,7 +1330,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures llvm 3.0svn to adapt to many kinds of systems.
+\`configure' configures llvm 3.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1395,7 +1396,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of llvm 3.0svn:";;
+ short | recursive ) echo "Configuration of llvm 3.0:";;
esac
cat <<\_ACEOF
@@ -1403,10 +1404,10 @@ Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-polly Use polly if available (default is YES)
- --enable-optimized Compile with optimizations enabled (default is NO)
+ --enable-optimized Compile with optimizations enabled (default is YES)
--enable-profiling Compile with profiling enabled (default is NO)
--enable-assertions Compile with assertion checks enabled (default is
- YES)
+ NO)
--enable-expensive-checks
Compile with expensive debug checks enabled (default
is NO)
@@ -1424,7 +1425,7 @@ Optional Features:
--enable-shared Build a shared library and link tools against it
(default is NO)
--enable-embed-stdcxx Build a shared library with embedded libstdc++ for
- Win32 DLL (default is YES)
+ Win32 DLL (default is NO)
--enable-timestamps Enable embedding timestamp information in build
(default is YES)
--enable-targets Build specific host targets: all or
@@ -1442,16 +1443,6 @@ Optional Features:
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --with-llvmgccdir Specify location of llvm-gcc install dir (default
- searches PATH)
- --with-llvmgcc Specify location of llvm-gcc driver (default
- searches PATH)
- --with-llvmgxx Specify location of llvm-g++ driver (default
- searches PATH)
- --with-clang Specify location of clang compiler (default is
- --with-built-clang)
- --with-built-clang Use the compiled Clang as the LLVM compiler
- (default=check)
--with-optimize-option Select the compiler options to use for optimized
builds
--with-extra-options Specify additional options to compile LLVM with
@@ -1471,9 +1462,9 @@ Optional Packages:
64 bit multilib directory.
--with-binutils-include Specify path to binutils/include/ containing
plugin-api.h file for gold plugin.
+ --with-bug-report-url Specify the URL where bug reports should be
+ submitted (default=http://llvm.org/bugs/)
--with-tclinclude directory where tcl headers are
- --with-llvmcc=<name> Choose the LLVM capable compiler to use (llvm-gcc,
- clang, or none; default=check)
--with-udis86=<path> Use udis86 external x86 disassembler library
--with-oprofile=<prefix>
Tell OProfile >= 0.9.4 how to symbolize JIT output
@@ -1483,11 +1474,12 @@ Some influential environment variables:
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
- CPP C preprocessor
CXX C++ compiler command
CXXFLAGS C++ compiler flags
+ CPP C preprocessor
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -1553,8 +1545,8 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-llvm configure 3.0svn
-generated by GNU Autoconf 2.60
+llvm configure 3.0
+generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@@ -1569,8 +1561,8 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by llvm $as_me 3.0svn, which was
-generated by GNU Autoconf 2.60. Invocation command line was
+It was created by llvm $as_me 3.0, which was
+generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -1971,667 +1963,13 @@ echo "$as_me: error: Already configured in ${srcdir}" >&2;}
fi
fi
-
-
-if test -d ${srcdir}/projects/llvm-gcc ; then
- subdirs="$subdirs projects/llvm-gcc"
-
-fi
-
-if test -d ${srcdir}/projects/test-suite ; then
- subdirs="$subdirs projects/test-suite"
-
-fi
-
-if test -d ${srcdir}/projects/llvm-test ; then
- subdirs="$subdirs projects/llvm-test"
-
-fi
-
-if test -d ${srcdir}/projects/poolalloc ; then
- subdirs="$subdirs projects/poolalloc"
-
-fi
-
-if test -d ${srcdir}/projects/llvm-poolalloc ; then
- subdirs="$subdirs projects/llvm-poolalloc"
-
-fi
-
-for i in `ls ${srcdir}/projects`
-do
- if test -d ${srcdir}/projects/${i} ; then
- case ${i} in
- sample) subdirs="$subdirs projects/sample"
- ;;
- privbracket) subdirs="$subdirs projects/privbracket"
- ;;
- llvm-stacker) subdirs="$subdirs projects/llvm-stacker"
- ;;
- llvm-reopt) subdirs="$subdirs projects/llvm-reopt"
-;;
- llvm-java) subdirs="$subdirs projects/llvm-java"
- ;;
- llvm-tv) subdirs="$subdirs projects/llvm-tv"
- ;;
- safecode) subdirs="$subdirs projects/safecode"
- ;;
- llvm-kernel) subdirs="$subdirs projects/llvm-kernel"
- ;;
- llvm-gcc) ;;
- test-suite) ;;
- llvm-test) ;;
- poolalloc) ;;
- llvm-poolalloc) ;;
- *)
- { echo "$as_me:$LINENO: WARNING: Unknown project (${i}) won't be configured automatically" >&5
-echo "$as_me: WARNING: Unknown project (${i}) won't be configured automatically" >&2;}
- ;;
- esac
- fi
-done
-
-# Check whether --enable-polly was given.
-if test "${enable_polly+set}" = set; then
- enableval=$enable_polly;
-else
- enableval=default
-fi
-
-case "$enableval" in
- yes) ENABLE_POLLY=1
- ;;
- no) ENABLE_POLLY=0
- ;;
- default) ENABLE_POLLY=1
- ;;
- *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-polly. Use \"yes\" or \"no\"" >&5
-echo "$as_me: error: Invalid setting for --enable-polly. Use \"yes\" or \"no\"" >&2;}
- { (exit 1); exit 1; }; } ;;
-esac
-
-
-if (test -d ${srcdir}/tools/polly) && (test $ENABLE_POLLY -eq 1) ; then
- LLVM_HAS_POLLY=1
-
- subdirs="$subdirs tools/polly"
-
-fi
-
-
-# Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
-echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
- { (exit 1); exit 1; }; }
-
-{ echo "$as_me:$LINENO: checking build system type" >&5
-echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
-if test "${ac_cv_build+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_build_alias=$build_alias
-test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
-test "x$ac_build_alias" = x &&
- { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
-echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
- { (exit 1); exit 1; }; }
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
-echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
-echo "${ECHO_T}$ac_cv_build" >&6; }
-case $ac_cv_build in
-*-*-*) ;;
-*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
-echo "$as_me: error: invalid value of canonical build" >&2;}
- { (exit 1); exit 1; }; };;
-esac
-build=$ac_cv_build
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_build
-shift
-build_cpu=$1
-build_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-build_os=$*
-IFS=$ac_save_IFS
-case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-
-
-{ echo "$as_me:$LINENO: checking host system type" >&5
-echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
-if test "${ac_cv_host+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test "x$host_alias" = x; then
- ac_cv_host=$ac_cv_build
-else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
-echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
-echo "${ECHO_T}$ac_cv_host" >&6; }
-case $ac_cv_host in
-*-*-*) ;;
-*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
-echo "$as_me: error: invalid value of canonical host" >&2;}
- { (exit 1); exit 1; }; };;
-esac
-host=$ac_cv_host
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_host
-shift
-host_cpu=$1
-host_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-host_os=$*
-IFS=$ac_save_IFS
-case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
-
-{ echo "$as_me:$LINENO: checking target system type" >&5
-echo $ECHO_N "checking target system type... $ECHO_C" >&6; }
-if test "${ac_cv_target+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test "x$target_alias" = x; then
- ac_cv_target=$ac_cv_host
-else
- ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
- { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5
-echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5
-echo "${ECHO_T}$ac_cv_target" >&6; }
-case $ac_cv_target in
-*-*-*) ;;
-*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5
-echo "$as_me: error: invalid value of canonical target" >&2;}
- { (exit 1); exit 1; }; };;
-esac
-target=$ac_cv_target
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_target
-shift
-target_cpu=$1
-target_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-target_os=$*
-IFS=$ac_save_IFS
-case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
-
-
-# The aliases save the names the user supplied, while $host etc.
-# will get canonicalized.
-test -n "$target_alias" &&
- test "$program_prefix$program_suffix$program_transform_name" = \
- NONENONEs,x,x, &&
- program_prefix=${target_alias}-
-
-{ echo "$as_me:$LINENO: checking type of operating system we're going to host on" >&5
-echo $ECHO_N "checking type of operating system we're going to host on... $ECHO_C" >&6; }
-if test "${llvm_cv_os_type+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $host in
- *-*-aix*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="AIX"
- llvm_cv_platform_type="Unix" ;;
- *-*-irix*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="IRIX"
- llvm_cv_platform_type="Unix" ;;
- *-*-cygwin*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="Cygwin"
- llvm_cv_platform_type="Unix" ;;
- *-*-darwin*)
- llvm_cv_link_all_option="-Wl,-all_load"
- llvm_cv_no_link_all_option="-Wl,-noall_load"
- llvm_cv_os_type="Darwin"
- llvm_cv_platform_type="Unix" ;;
- *-*-minix*)
- llvm_cv_link_all_option="-Wl,-all_load"
- llvm_cv_no_link_all_option="-Wl,-noall_load"
- llvm_cv_os_type="Minix"
- llvm_cv_platform_type="Unix" ;;
- *-*-freebsd*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="FreeBSD"
- llvm_cv_platform_type="Unix" ;;
- *-*-openbsd*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="OpenBSD"
- llvm_cv_platform_type="Unix" ;;
- *-*-netbsd*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="NetBSD"
- llvm_cv_platform_type="Unix" ;;
- *-*-dragonfly*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="DragonFly"
- llvm_cv_platform_type="Unix" ;;
- *-*-hpux*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="HP-UX"
- llvm_cv_platform_type="Unix" ;;
- *-*-interix*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="Interix"
- llvm_cv_platform_type="Unix" ;;
- *-*-linux*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="Linux"
- llvm_cv_platform_type="Unix" ;;
- *-*-solaris*)
- llvm_cv_link_all_option="-Wl,-z,allextract"
- llvm_cv_no_link_all_option="-Wl,-z,defaultextract"
- llvm_cv_os_type="SunOS"
- llvm_cv_platform_type="Unix" ;;
- *-*-auroraux*)
- llvm_cv_link_all_option="-Wl,-z,allextract"
- llvm_cv_link_all_option="-Wl,-z,defaultextract"
- llvm_cv_os_type="AuroraUX"
- llvm_cv_platform_type="Unix" ;;
- *-*-win32*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="Win32"
- llvm_cv_platform_type="Win32" ;;
- *-*-mingw*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="MingW"
- llvm_cv_platform_type="Win32" ;;
- *-*-haiku*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="Haiku"
- llvm_cv_platform_type="Unix" ;;
- *-unknown-eabi*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="Freestanding"
- llvm_cv_platform_type="Unix" ;;
- *-unknown-elf*)
- llvm_cv_link_all_option="-Wl,--whole-archive"
- llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
- llvm_cv_os_type="Freestanding"
- llvm_cv_platform_type="Unix" ;;
- *)
- llvm_cv_link_all_option=""
- llvm_cv_no_link_all_option=""
- llvm_cv_os_type="Unknown"
- llvm_cv_platform_type="Unknown" ;;
-esac
-fi
-{ echo "$as_me:$LINENO: result: $llvm_cv_os_type" >&5
-echo "${ECHO_T}$llvm_cv_os_type" >&6; }
-
-{ echo "$as_me:$LINENO: checking type of operating system we're going to target" >&5
-echo $ECHO_N "checking type of operating system we're going to target... $ECHO_C" >&6; }
-if test "${llvm_cv_target_os_type+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $target in
- *-*-aix*)
- llvm_cv_target_os_type="AIX" ;;
- *-*-irix*)
- llvm_cv_target_os_type="IRIX" ;;
- *-*-cygwin*)
- llvm_cv_target_os_type="Cygwin" ;;
- *-*-darwin*)
- llvm_cv_target_os_type="Darwin" ;;
- *-*-minix*)
- llvm_cv_target_os_type="Minix" ;;
- *-*-freebsd*)
- llvm_cv_target_os_type="FreeBSD" ;;
- *-*-openbsd*)
- llvm_cv_target_os_type="OpenBSD" ;;
- *-*-netbsd*)
- llvm_cv_target_os_type="NetBSD" ;;
- *-*-dragonfly*)
- llvm_cv_target_os_type="DragonFly" ;;
- *-*-hpux*)
- llvm_cv_target_os_type="HP-UX" ;;
- *-*-interix*)
- llvm_cv_target_os_type="Interix" ;;
- *-*-linux*)
- llvm_cv_target_os_type="Linux" ;;
- *-*-solaris*)
- llvm_cv_target_os_type="SunOS" ;;
- *-*-auroraux*)
- llvm_cv_target_os_type="AuroraUX" ;;
- *-*-win32*)
- llvm_cv_target_os_type="Win32" ;;
- *-*-mingw*)
- llvm_cv_target_os_type="MingW" ;;
- *-*-haiku*)
- llvm_cv_target_os_type="Haiku" ;;
- *-*-rtems*)
- llvm_cv_target_os_type="RTEMS" ;;
- *-unknown-eabi*)
- llvm_cv_target_os_type="Freestanding" ;;
- *)
- llvm_cv_target_os_type="Unknown" ;;
-esac
-fi
-{ echo "$as_me:$LINENO: result: $llvm_cv_target_os_type" >&5
-echo "${ECHO_T}$llvm_cv_target_os_type" >&6; }
-
-if test "$llvm_cv_os_type" = "Unknown" ; then
- { { echo "$as_me:$LINENO: error: Operating system is unknown, configure can't continue" >&5
-echo "$as_me: error: Operating system is unknown, configure can't continue" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-OS=$llvm_cv_os_type
-
-HOST_OS=$llvm_cv_os_type
-
-TARGET_OS=$llvm_cv_target_os_type
-
-
-LINKALL=$llvm_cv_link_all_option
-
-NOLINKALL=$llvm_cv_no_link_all_option
-
-
-case $llvm_cv_platform_type in
- Unix)
-
-cat >>confdefs.h <<\_ACEOF
-#define LLVM_ON_UNIX 1
-_ACEOF
-
- LLVM_ON_UNIX=1
-
- LLVM_ON_WIN32=0
-
- ;;
- Win32)
-
-cat >>confdefs.h <<\_ACEOF
-#define LLVM_ON_WIN32 1
-_ACEOF
-
- LLVM_ON_UNIX=0
-
- LLVM_ON_WIN32=1
-
- ;;
-esac
-
-{ echo "$as_me:$LINENO: checking target architecture" >&5
-echo $ECHO_N "checking target architecture... $ECHO_C" >&6; }
-if test "${llvm_cv_target_arch+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $target in
- i?86-*) llvm_cv_target_arch="x86" ;;
- amd64-* | x86_64-*) llvm_cv_target_arch="x86_64" ;;
- sparc*-*) llvm_cv_target_arch="Sparc" ;;
- powerpc*-*) llvm_cv_target_arch="PowerPC" ;;
- alpha*-*) llvm_cv_target_arch="Alpha" ;;
- arm*-*) llvm_cv_target_arch="ARM" ;;
- mips-*) llvm_cv_target_arch="Mips" ;;
- xcore-*) llvm_cv_target_arch="XCore" ;;
- msp430-*) llvm_cv_target_arch="MSP430" ;;
- s390x-*) llvm_cv_target_arch="SystemZ" ;;
- bfin-*) llvm_cv_target_arch="Blackfin" ;;
- mblaze-*) llvm_cv_target_arch="MBlaze" ;;
- ptx-*) llvm_cv_target_arch="PTX" ;;
- *) llvm_cv_target_arch="Unknown" ;;
-esac
-fi
-{ echo "$as_me:$LINENO: result: $llvm_cv_target_arch" >&5
-echo "${ECHO_T}$llvm_cv_target_arch" >&6; }
-
-if test "$llvm_cv_target_arch" = "Unknown" ; then
- { echo "$as_me:$LINENO: WARNING: Configuring LLVM for an unknown target archicture" >&5
-echo "$as_me: WARNING: Configuring LLVM for an unknown target archicture" >&2;}
-fi
-
-# Determine the LLVM native architecture for the target
-case "$llvm_cv_target_arch" in
- x86) LLVM_NATIVE_ARCH="X86" ;;
- x86_64) LLVM_NATIVE_ARCH="X86" ;;
- *) LLVM_NATIVE_ARCH="$llvm_cv_target_arch" ;;
-esac
-
-ARCH=$llvm_cv_target_arch
-
-
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_CC="${ac_tool_prefix}gcc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_CC"; then
- ac_ct_CC=$CC
- # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_CC="gcc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
- if test "x$ac_ct_CC" = x; then
- CC=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
- CC=$ac_ct_CC
- fi
-else
- CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_CC="${ac_tool_prefix}cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- fi
-fi
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# != 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
- fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-fi
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- for ac_prog in cl.exe
+ for ac_prog in clang llvm-gcc gcc
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
@@ -2649,7 +1987,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2675,7 +2013,7 @@ fi
fi
if test -z "$CC"; then
ac_ct_CC=$CC
- for ac_prog in cl.exe
+ for ac_prog in clang llvm-gcc gcc
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
@@ -2693,7 +2031,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_CC="$ac_prog"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -2734,8 +2072,6 @@ esac
fi
fi
-fi
-
test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
See \`config.log' for more details." >&5
@@ -2834,7 +2170,7 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
# in a Makefile. We should not override ac_cv_exeext if it was cached,
# so that the user can short-circuit this test for compilers unknown to
# Autoconf.
-for ac_file in $ac_files
+for ac_file in $ac_files ''
do
test -f "$ac_file" || continue
case $ac_file in
@@ -2862,6 +2198,12 @@ done
test "$ac_cv_exeext" = no && ac_cv_exeext=
else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
@@ -2873,8 +2215,6 @@ See \`config.log' for more details." >&2;}
fi
ac_exeext=$ac_cv_exeext
-{ echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6; }
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
@@ -3052,27 +2392,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_compiler_gnu=yes
else
echo "$as_me: failed program was:" >&5
@@ -3127,27 +2450,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_prog_cc_g=yes
else
echo "$as_me: failed program was:" >&5
@@ -3182,27 +2488,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
:
else
echo "$as_me: failed program was:" >&5
@@ -3238,27 +2527,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_prog_cc_g=yes
else
echo "$as_me: failed program was:" >&5
@@ -3374,27 +2646,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_prog_cc_c89=$ac_arg
else
echo "$as_me: failed program was:" >&5
@@ -3431,6 +2686,369 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in clang++ llvm-g++ g++
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in clang++ llvm-g++ g++
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CXXFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -3484,17 +3102,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
:
else
echo "$as_me: failed program was:" >&5
@@ -3528,17 +3139,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
# Broken: success on invalid input.
continue
else
@@ -3603,17 +3207,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
:
else
echo "$as_me: failed program was:" >&5
@@ -3647,17 +3244,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
# Broken: success on invalid input.
continue
else
@@ -3691,6 +3281,470 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+if test -d ${srcdir}/projects/llvm-gcc ; then
+ subdirs="$subdirs projects/llvm-gcc"
+
+fi
+
+if test -d ${srcdir}/projects/test-suite ; then
+ subdirs="$subdirs projects/test-suite"
+
+fi
+
+if test -d ${srcdir}/projects/llvm-test ; then
+ subdirs="$subdirs projects/llvm-test"
+
+fi
+
+if test -d ${srcdir}/projects/poolalloc ; then
+ subdirs="$subdirs projects/poolalloc"
+
+fi
+
+if test -d ${srcdir}/projects/llvm-poolalloc ; then
+ subdirs="$subdirs projects/llvm-poolalloc"
+
+fi
+
+for i in `ls ${srcdir}/projects`
+do
+ if test -d ${srcdir}/projects/${i} ; then
+ case ${i} in
+ sample) subdirs="$subdirs projects/sample"
+ ;;
+ privbracket) subdirs="$subdirs projects/privbracket"
+ ;;
+ llvm-stacker) subdirs="$subdirs projects/llvm-stacker"
+ ;;
+ llvm-reopt) subdirs="$subdirs projects/llvm-reopt"
+;;
+ llvm-java) subdirs="$subdirs projects/llvm-java"
+ ;;
+ llvm-tv) subdirs="$subdirs projects/llvm-tv"
+ ;;
+ safecode) subdirs="$subdirs projects/safecode"
+ ;;
+ llvm-kernel) subdirs="$subdirs projects/llvm-kernel"
+ ;;
+ llvm-gcc) ;;
+ test-suite) ;;
+ llvm-test) ;;
+ poolalloc) ;;
+ llvm-poolalloc) ;;
+ *)
+ { echo "$as_me:$LINENO: WARNING: Unknown project (${i}) won't be configured automatically" >&5
+echo "$as_me: WARNING: Unknown project (${i}) won't be configured automatically" >&2;}
+ ;;
+ esac
+ fi
+done
+
+# Check whether --enable-polly was given.
+if test "${enable_polly+set}" = set; then
+ enableval=$enable_polly;
+else
+ enableval=default
+fi
+
+case "$enableval" in
+ yes) ENABLE_POLLY=1
+ ;;
+ no) ENABLE_POLLY=0
+ ;;
+ default) ENABLE_POLLY=1
+ ;;
+ *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-polly. Use \"yes\" or \"no\"" >&5
+echo "$as_me: error: Invalid setting for --enable-polly. Use \"yes\" or \"no\"" >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+
+
+if (test -d ${srcdir}/tools/polly) && (test $ENABLE_POLLY -eq 1) ; then
+ LLVM_HAS_POLLY=1
+
+ subdirs="$subdirs tools/polly"
+
+fi
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6; }
+if test "${ac_cv_target+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
+else
+ ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5
+echo "$as_me: error: invalid value of canonical target" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+{ echo "$as_me:$LINENO: checking type of operating system we're going to host on" >&5
+echo $ECHO_N "checking type of operating system we're going to host on... $ECHO_C" >&6; }
+if test "${llvm_cv_os_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $host in
+ *-*-aix*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="AIX"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-irix*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="IRIX"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-cygwin*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="Cygwin"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-darwin*)
+ llvm_cv_link_all_option="-Wl,-all_load"
+ llvm_cv_no_link_all_option="-Wl,-noall_load"
+ llvm_cv_os_type="Darwin"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-minix*)
+ llvm_cv_link_all_option="-Wl,-all_load"
+ llvm_cv_no_link_all_option="-Wl,-noall_load"
+ llvm_cv_os_type="Minix"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-freebsd*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="FreeBSD"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-openbsd*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="OpenBSD"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-netbsd*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="NetBSD"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-dragonfly*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="DragonFly"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-hpux*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="HP-UX"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-interix*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="Interix"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-linux*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="Linux"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-solaris*)
+ llvm_cv_link_all_option="-Wl,-z,allextract"
+ llvm_cv_no_link_all_option="-Wl,-z,defaultextract"
+ llvm_cv_os_type="SunOS"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-auroraux*)
+ llvm_cv_link_all_option="-Wl,-z,allextract"
+ llvm_cv_link_all_option="-Wl,-z,defaultextract"
+ llvm_cv_os_type="AuroraUX"
+ llvm_cv_platform_type="Unix" ;;
+ *-*-win32*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="Win32"
+ llvm_cv_platform_type="Win32" ;;
+ *-*-mingw*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="MingW"
+ llvm_cv_platform_type="Win32" ;;
+ *-*-haiku*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="Haiku"
+ llvm_cv_platform_type="Unix" ;;
+ *-unknown-eabi*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="Freestanding"
+ llvm_cv_platform_type="Unix" ;;
+ *-unknown-elf*)
+ llvm_cv_link_all_option="-Wl,--whole-archive"
+ llvm_cv_no_link_all_option="-Wl,--no-whole-archive"
+ llvm_cv_os_type="Freestanding"
+ llvm_cv_platform_type="Unix" ;;
+ *)
+ llvm_cv_link_all_option=""
+ llvm_cv_no_link_all_option=""
+ llvm_cv_os_type="Unknown"
+ llvm_cv_platform_type="Unknown" ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $llvm_cv_os_type" >&5
+echo "${ECHO_T}$llvm_cv_os_type" >&6; }
+
+{ echo "$as_me:$LINENO: checking type of operating system we're going to target" >&5
+echo $ECHO_N "checking type of operating system we're going to target... $ECHO_C" >&6; }
+if test "${llvm_cv_target_os_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $target in
+ *-*-aix*)
+ llvm_cv_target_os_type="AIX" ;;
+ *-*-irix*)
+ llvm_cv_target_os_type="IRIX" ;;
+ *-*-cygwin*)
+ llvm_cv_target_os_type="Cygwin" ;;
+ *-*-darwin*)
+ llvm_cv_target_os_type="Darwin" ;;
+ *-*-minix*)
+ llvm_cv_target_os_type="Minix" ;;
+ *-*-freebsd*)
+ llvm_cv_target_os_type="FreeBSD" ;;
+ *-*-openbsd*)
+ llvm_cv_target_os_type="OpenBSD" ;;
+ *-*-netbsd*)
+ llvm_cv_target_os_type="NetBSD" ;;
+ *-*-dragonfly*)
+ llvm_cv_target_os_type="DragonFly" ;;
+ *-*-hpux*)
+ llvm_cv_target_os_type="HP-UX" ;;
+ *-*-interix*)
+ llvm_cv_target_os_type="Interix" ;;
+ *-*-linux*)
+ llvm_cv_target_os_type="Linux" ;;
+ *-*-solaris*)
+ llvm_cv_target_os_type="SunOS" ;;
+ *-*-auroraux*)
+ llvm_cv_target_os_type="AuroraUX" ;;
+ *-*-win32*)
+ llvm_cv_target_os_type="Win32" ;;
+ *-*-mingw*)
+ llvm_cv_target_os_type="MingW" ;;
+ *-*-haiku*)
+ llvm_cv_target_os_type="Haiku" ;;
+ *-*-rtems*)
+ llvm_cv_target_os_type="RTEMS" ;;
+ *-*-nacl*)
+ llvm_cv_target_os_type="NativeClient" ;;
+ *-unknown-eabi*)
+ llvm_cv_target_os_type="Freestanding" ;;
+ *)
+ llvm_cv_target_os_type="Unknown" ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $llvm_cv_target_os_type" >&5
+echo "${ECHO_T}$llvm_cv_target_os_type" >&6; }
+
+if test "$llvm_cv_os_type" = "Unknown" ; then
+ { { echo "$as_me:$LINENO: error: Operating system is unknown, configure can't continue" >&5
+echo "$as_me: error: Operating system is unknown, configure can't continue" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+OS=$llvm_cv_os_type
+
+HOST_OS=$llvm_cv_os_type
+
+TARGET_OS=$llvm_cv_target_os_type
+
+
+LINKALL=$llvm_cv_link_all_option
+
+NOLINKALL=$llvm_cv_no_link_all_option
+
+
+case $llvm_cv_platform_type in
+ Unix)
+
+cat >>confdefs.h <<\_ACEOF
+#define LLVM_ON_UNIX 1
+_ACEOF
+
+ LLVM_ON_UNIX=1
+
+ LLVM_ON_WIN32=0
+
+ ;;
+ Win32)
+
+cat >>confdefs.h <<\_ACEOF
+#define LLVM_ON_WIN32 1
+_ACEOF
+
+ LLVM_ON_UNIX=0
+
+ LLVM_ON_WIN32=1
+
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking target architecture" >&5
+echo $ECHO_N "checking target architecture... $ECHO_C" >&6; }
+if test "${llvm_cv_target_arch+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $target in
+ i?86-*) llvm_cv_target_arch="x86" ;;
+ amd64-* | x86_64-*) llvm_cv_target_arch="x86_64" ;;
+ sparc*-*) llvm_cv_target_arch="Sparc" ;;
+ powerpc*-*) llvm_cv_target_arch="PowerPC" ;;
+ alpha*-*) llvm_cv_target_arch="Alpha" ;;
+ arm*-*) llvm_cv_target_arch="ARM" ;;
+ mips-*) llvm_cv_target_arch="Mips" ;;
+ xcore-*) llvm_cv_target_arch="XCore" ;;
+ msp430-*) llvm_cv_target_arch="MSP430" ;;
+ s390x-*) llvm_cv_target_arch="SystemZ" ;;
+ bfin-*) llvm_cv_target_arch="Blackfin" ;;
+ mblaze-*) llvm_cv_target_arch="MBlaze" ;;
+ ptx-*) llvm_cv_target_arch="PTX" ;;
+ *) llvm_cv_target_arch="Unknown" ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $llvm_cv_target_arch" >&5
+echo "${ECHO_T}$llvm_cv_target_arch" >&6; }
+
+if test "$llvm_cv_target_arch" = "Unknown" ; then
+ { echo "$as_me:$LINENO: WARNING: Configuring LLVM for an unknown target archicture" >&5
+echo "$as_me: WARNING: Configuring LLVM for an unknown target archicture" >&2;}
+fi
+
+# Determine the LLVM native architecture for the target
+case "$llvm_cv_target_arch" in
+ x86) LLVM_NATIVE_ARCH="X86" ;;
+ x86_64) LLVM_NATIVE_ARCH="X86" ;;
+ *) LLVM_NATIVE_ARCH="$llvm_cv_target_arch" ;;
+esac
+
+ARCH=$llvm_cv_target_arch
+
+
+
+
{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
if test "${ac_cv_path_GREP+set}" = set; then
@@ -3712,7 +3766,7 @@ do
for ac_prog in grep ggrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
# Check for GNU ac_path_GREP and select it if it is found.
# Check for GNU $ac_path_GREP
case `"$ac_path_GREP" --version 2>&1` in
@@ -3794,7 +3848,7 @@ do
for ac_prog in egrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
# Check for GNU ac_path_EGREP and select it if it is found.
# Check for GNU $ac_path_EGREP
case `"$ac_path_EGREP" --version 2>&1` in
@@ -3890,27 +3944,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_header_stdc=yes
else
echo "$as_me: failed program was:" >&5
@@ -3938,7 +3975,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
else
ac_cv_header_stdc=no
fi
-rm -f conftest*
+rm -f -r conftest*
fi
@@ -3959,7 +3996,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
else
ac_cv_header_stdc=no
fi
-rm -f conftest*
+rm -f -r conftest*
fi
@@ -4086,27 +4123,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
eval "$as_ac_Header=yes"
else
echo "$as_me: failed program was:" >&5
@@ -4148,7 +4168,8 @@ cat >>conftest.$ac_ext <<_ACEOF
int
main ()
{
-#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \
+ && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN)
bogus endian macros
#endif
@@ -4169,27 +4190,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
# It does; now see whether it defined to BIG_ENDIAN or not.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
@@ -4224,27 +4228,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_c_bigendian=yes
else
echo "$as_me: failed program was:" >&5
@@ -4295,27 +4282,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
ac_cv_c_bigendian=yes
fi
@@ -4445,7 +4415,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_BUILD_CC="${ac_build_prefix}gcc"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -4483,7 +4453,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_BUILD_CC="gcc"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -4522,7 +4492,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
@@ -4612,7 +4582,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_BUILD_CXX="${ac_build_prefix}g++"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -4650,7 +4620,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_BUILD_CXX="g++"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -4689,7 +4659,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/c++"; then
ac_prog_rejected=yes
continue
@@ -4778,7 +4748,7 @@ fi
if test "${enable_assertions+set}" = set; then
enableval=$enable_assertions;
else
- enableval="yes"
+ enableval="no"
fi
if test ${enableval} = "yes" ; then
@@ -4863,7 +4833,7 @@ else
;;
ARM) TARGET_HAS_JIT=1
;;
- Mips) TARGET_HAS_JIT=0
+ Mips) TARGET_HAS_JIT=1
;;
XCore) TARGET_HAS_JIT=0
;;
@@ -5018,7 +4988,7 @@ case "$enableval" in
;;
no) ENABLE_EMBED_STDCXX=0
;;
- default) ENABLE_EMBED_STDCXX=1
+ default) ENABLE_EMBED_STDCXX=0
;;
*) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-embed-stdcxx. Use \"yes\" or \"no\"" >&5
echo "$as_me: error: Invalid setting for --enable-embed-stdcxx. Use \"yes\" or \"no\"" >&2;}
@@ -5120,7 +5090,7 @@ _ACEOF
LLVM_NATIVE_TARGET="LLVMInitialize${LLVM_NATIVE_ARCH}Target"
LLVM_NATIVE_TARGETINFO="LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo"
- LLVM_NATIVE_MCASMINFO="LLVMInitialize${LLVM_NATIVE_ARCH}MCAsmInfo"
+ LLVM_NATIVE_TARGETMC="LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC"
LLVM_NATIVE_ASMPRINTER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter"
if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/AsmParser/Makefile ; then
LLVM_NATIVE_ASMPARSER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser"
@@ -5137,7 +5107,7 @@ _ACEOF
cat >>confdefs.h <<_ACEOF
-#define LLVM_NATIVE_MCASMINFO $LLVM_NATIVE_MCASMINFO
+#define LLVM_NATIVE_TARGETMC $LLVM_NATIVE_TARGETMC
_ACEOF
@@ -5203,121 +5173,6 @@ _ACEOF
-# Check whether --with-llvmgccdir was given.
-if test "${with_llvmgccdir+set}" = set; then
- withval=$with_llvmgccdir;
-else
- withval=default
-fi
-
-case "$withval" in
- default) WITH_LLVMGCCDIR=default ;;
- /* | [A-Za-z]:[\\/]*) WITH_LLVMGCCDIR=$withval ;;
- *) { { echo "$as_me:$LINENO: error: Invalid path for --with-llvmgccdir. Provide full path" >&5
-echo "$as_me: error: Invalid path for --with-llvmgccdir. Provide full path" >&2;}
- { (exit 1); exit 1; }; } ;;
-esac
-
-
-# Check whether --with-llvmgcc was given.
-if test "${with_llvmgcc+set}" = set; then
- withval=$with_llvmgcc; LLVMGCC=$with_llvmgcc
- WITH_LLVMGCCDIR=""
-fi
-
-
-
-# Check whether --with-llvmgxx was given.
-if test "${with_llvmgxx+set}" = set; then
- withval=$with_llvmgxx; LLVMGXX=$with_llvmgxx
- WITH_LLVMGCCDIR=""
-fi
-
-
-if test -n "$LLVMGCC"; then
- LLVMGCCCOMMAND="$LLVMGCC"
-fi
-
-if test -n "$LLVMGXX"; then
- LLVMGXXCOMMAND="$LLVMGXX"
-fi
-
-if test -n "$LLVMGCC" && test -z "$LLVMGXX"; then
- { { echo "$as_me:$LINENO: error: Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used" >&5
-echo "$as_me: error: Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used" >&2;}
- { (exit 1); exit 1; }; };
-fi
-
-if test -n "$LLVMGXX" && test -z "$LLVMGCC"; then
- { { echo "$as_me:$LINENO: error: Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is used" >&5
-echo "$as_me: error: Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is used" >&2;}
- { (exit 1); exit 1; }; };
-fi
-
-
-# Check whether --with-clang was given.
-if test "${with_clang+set}" = set; then
- withval=$with_clang;
-else
- with_clang=default
-fi
-
-
-
-# Check whether --with-built-clang was given.
-if test "${with_built_clang+set}" = set; then
- withval=$with_built_clang;
-else
- with_built_clang=check
-fi
-
-
-{ echo "$as_me:$LINENO: checking clang compiler" >&5
-echo $ECHO_N "checking clang compiler... $ECHO_C" >&6; }
-WITH_CLANGPATH=""
-WITH_BUILT_CLANG=0
-if test "$with_clang" != "default"; then
- WITH_CLANGPATH="$with_clang"
- if ! test -x "$WITH_CLANGPATH"; then
- { { echo "$as_me:$LINENO: error: invalid --with-clang, path does not specify an executable" >&5
-echo "$as_me: error: invalid --with-clang, path does not specify an executable" >&2;}
- { (exit 1); exit 1; }; }
- fi
-elif test "$with_built_clang" = "yes"; then
- WITH_BUILT_CLANG=1
-elif test "$with_built_clang" = "no"; then
- WITH_BUILT_CLANG=0
-else
- if test "$with_built_clang" != "check"; then
- { { echo "$as_me:$LINENO: error: invalid value for --with-built-clang." >&5
-echo "$as_me: error: invalid value for --with-built-clang." >&2;}
- { (exit 1); exit 1; }; }
- fi
-
- if test -f ${srcdir}/tools/clang/README.txt; then
- WITH_BUILT_CLANG=1
- fi
-fi
-
-if ! test -z "$WITH_CLANGPATH"; then
- { echo "$as_me:$LINENO: result: $WITH_CLANGPATH" >&5
-echo "${ECHO_T}$WITH_CLANGPATH" >&6; }
- WITH_CLANGXXPATH=`"$WITH_CLANGPATH" --print-prog-name=clang++`
-elif test "$WITH_BUILT_CLANG" = "1"; then
- { echo "$as_me:$LINENO: result: built" >&5
-echo "${ECHO_T}built" >&6; }
-else
- { echo "$as_me:$LINENO: result: none" >&5
-echo "${ECHO_T}none" >&6; }
-fi
-CLANGPATH=$WITH_CLANGPATH
-
-CLANGXXPATH=$WITH_CLANGXXPATH
-
-ENABLE_BUILT_CLANG=$WITH_BUILT_CLANG
-
-
-
# Check whether --with-optimize-option was given.
if test "${with_optimize_option+set}" = set; then
withval=$with_optimize_option;
@@ -5520,6 +5375,20 @@ echo "$as_me: error: Invalid path to directory containing plugin-api.h." >&2;}
fi
fi
+
+# Check whether --with-bug-report-url was given.
+if test "${with_bug_report_url+set}" = set; then
+ withval=$with_bug_report_url;
+else
+ withval="http://llvm.org/bugs/"
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define BUG_REPORT_URL "$withval"
+_ACEOF
+
+
# Check whether --enable-libffi was given.
if test "${enable_libffi+set}" = set; then
enableval=$enable_libffi; case "$enableval" in
@@ -5535,1262 +5404,6 @@ fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if test "${ac_cv_prog_CPP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- # Broken: success on invalid input.
-continue
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- # Broken: success on invalid input.
-continue
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- :
-else
- { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
- for ac_prog in gcc
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- test -n "$CC" && break
- done
-fi
-if test -z "$CC"; then
- ac_ct_CC=$CC
- for ac_prog in gcc
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_CC="$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- test -n "$ac_ct_CC" && break
-done
-
- if test "x$ac_ct_CC" = x; then
- CC=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
- CC=$ac_ct_CC
- fi
-fi
-
-
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO: checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (ac_try="$ac_compiler --version >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compiler --version >&5") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compiler -v >&5") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compiler -V >&5") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-
-{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-#ifndef __GNUC__
- choke me
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_compiler_gnu=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_compiler_gnu=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
-GCC=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_save_c_werror_flag=$ac_c_werror_flag
- ac_c_werror_flag=yes
- ac_cv_prog_cc_g=no
- CFLAGS="-g"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cc_g=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- CFLAGS=""
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_c_werror_flag=$ac_save_c_werror_flag
- CFLAGS="-g"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cc_g=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_c_werror_flag=$ac_save_c_werror_flag
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
- if test "$GCC" = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-g"
- fi
-else
- if test "$GCC" = yes; then
- CFLAGS="-O2"
- else
- CFLAGS=
- fi
-fi
-{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
-echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_prog_cc_c89=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
-_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
- CC="$ac_save_CC $ac_arg"
- rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cc_c89=$ac_arg
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext
- test "x$ac_cv_prog_cc_c89" != "xno" && break
-done
-rm -f conftest.$ac_ext
-CC=$ac_save_CC
-
-fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6; } ;;
- xno)
- { echo "$as_me:$LINENO: result: unsupported" >&5
-echo "${ECHO_T}unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-if test -z "$CXX"; then
- if test -n "$CCC"; then
- CXX=$CCC
- else
- if test -n "$ac_tool_prefix"; then
- for ac_prog in g++
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CXX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CXX"; then
- ac_cv_prog_CXX="$CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-CXX=$ac_cv_prog_CXX
-if test -n "$CXX"; then
- { echo "$as_me:$LINENO: result: $CXX" >&5
-echo "${ECHO_T}$CXX" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- test -n "$CXX" && break
- done
-fi
-if test -z "$CXX"; then
- ac_ct_CXX=$CXX
- for ac_prog in g++
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CXX"; then
- ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_CXX="$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
-if test -n "$ac_ct_CXX"; then
- { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
-echo "${ECHO_T}$ac_ct_CXX" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- test -n "$ac_ct_CXX" && break
-done
-
- if test "x$ac_ct_CXX" = x; then
- CXX="g++"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet. If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
- CXX=$ac_ct_CXX
- fi
-fi
-
- fi
-fi
-# Provide some information about the compiler.
-echo "$as_me:$LINENO: checking for C++ compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (ac_try="$ac_compiler --version >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compiler --version >&5") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compiler -v >&5") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compiler -V >&5") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-
-{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
-if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-#ifndef __GNUC__
- choke me
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_compiler_gnu=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_compiler_gnu=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
-GXX=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CXXFLAGS=${CXXFLAGS+set}
-ac_save_CXXFLAGS=$CXXFLAGS
-{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
-echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cxx_g+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_save_cxx_werror_flag=$ac_cxx_werror_flag
- ac_cxx_werror_flag=yes
- ac_cv_prog_cxx_g=no
- CXXFLAGS="-g"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cxx_g=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- CXXFLAGS=""
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cxx_werror_flag=$ac_save_cxx_werror_flag
- CXXFLAGS="-g"
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cxx_g=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_cxx_werror_flag=$ac_save_cxx_werror_flag
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
-if test "$ac_test_CXXFLAGS" = set; then
- CXXFLAGS=$ac_save_CXXFLAGS
-elif test $ac_cv_prog_cxx_g = yes; then
- if test "$GXX" = yes; then
- CXXFLAGS="-g -O2"
- else
- CXXFLAGS="-g"
- fi
-else
- if test "$GXX" = yes; then
- CXXFLAGS="-O2"
- else
- CXXFLAGS=
- fi
-fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; }
if test "${lt_cv_path_NM+set}" = set; then
@@ -6901,7 +5514,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_CMP="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -6942,7 +5555,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_CP="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -6983,7 +5596,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_DATE="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7024,7 +5637,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_FIND="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7065,7 +5678,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_GREP="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7106,7 +5719,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_MKDIR="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7147,7 +5760,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_MV="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7187,7 +5800,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7227,7 +5840,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_RANLIB="ranlib"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7283,7 +5896,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_AR="${ac_tool_prefix}ar"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7323,7 +5936,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_AR="ar"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7380,7 +5993,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7421,7 +6034,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7462,7 +6075,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_TAR="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7503,7 +6116,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_BINPWD="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7545,7 +6158,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_GRAPHVIZ="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7601,7 +6214,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_DOT="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7657,7 +6270,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_FDP="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7713,7 +6326,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_NEATO="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7769,7 +6382,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_TWOPI="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7825,7 +6438,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_CIRCO="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7883,7 +6496,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_GV="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7942,7 +6555,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_DOTTY="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -7998,7 +6611,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_XDOT_PY="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8056,7 +6669,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8140,7 +6753,7 @@ case $as_dir/ in
# by default.
for ac_prog in ginstall scoinst install; do
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
if test $ac_prog = install &&
grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
@@ -8207,7 +6820,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_BZIP2="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8247,7 +6860,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_CAT="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8287,7 +6900,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_DOXYGEN="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8327,7 +6940,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_GROFF="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8367,7 +6980,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_GZIPBIN="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8407,7 +7020,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_POD2HTML="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8447,7 +7060,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_POD2MAN="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8487,7 +7100,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_PDFROFF="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8527,7 +7140,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_RUNTEST="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8602,7 +7215,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_TCLSH="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8657,7 +7270,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_ZIP="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8699,7 +7312,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_OCAMLC="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8744,7 +7357,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_OCAMLOPT="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8789,7 +7402,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_OCAMLDEP="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8834,7 +7447,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_OCAMLDOC="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8879,7 +7492,7 @@ do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_path_GAS="$as_dir/$ac_word$ac_exec_ext"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
@@ -8971,27 +7584,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
llvm_cv_link_use_r=yes
else
echo "$as_me: failed program was:" >&5
@@ -9000,7 +7597,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
llvm_cv_link_use_r=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$oldcflags"
ac_ext=c
@@ -9063,27 +7660,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
llvm_cv_link_use_export_dynamic=yes
else
echo "$as_me: failed program was:" >&5
@@ -9092,7 +7673,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
llvm_cv_link_use_export_dynamic=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$oldcflags"
ac_ext=c
@@ -9177,27 +7758,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
llvm_cv_link_use_version_script=yes
else
echo "$as_me: failed program was:" >&5
@@ -9206,7 +7771,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
llvm_cv_link_use_version_script=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
rm "$tmp/export.map"
rmdir "$tmp"
@@ -9248,10 +7813,10 @@ main ()
#ifndef __cplusplus
/* Ultrix mips cc rejects this. */
typedef int charset[2];
- const charset x;
+ const charset cs;
/* SunOS 4.1.1 cc rejects this. */
- char const *const *ccp;
- char **p;
+ char const *const *pcpcc;
+ char **ppc;
/* NEC SVR4.0.2 mips cc rejects this. */
struct point {int x, y;};
static struct point const zero = {0,0};
@@ -9260,11 +7825,11 @@ main ()
an arm of an if-expression whose if-part is not a constant
expression */
const char *g = "string";
- ccp = &g + (g ? g-g : 0);
+ pcpcc = &g + (g ? g-g : 0);
/* HPUX 7.0 cc rejects these. */
- ++ccp;
- p = (char**) ccp;
- ccp = (char const *const *) p;
+ ++pcpcc;
+ ppc = (char**) pcpcc;
+ pcpcc = (char const *const *) ppc;
{ /* SCO 3.2v4 cc rejects this. */
char *t;
char const *s = 0 ? (char *) 0 : (char const *) 0;
@@ -9291,7 +7856,7 @@ main ()
const int foo = 10;
if (!foo) return 0;
}
- return !x[0] && !zero.x;
+ return !cs[0] && !zero.x;
#endif
;
@@ -9311,27 +7876,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_c_const=yes
else
echo "$as_me: failed program was:" >&5
@@ -9396,27 +7944,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
eval "$as_ac_Header=yes"
else
echo "$as_me: failed program was:" >&5
@@ -9489,27 +8020,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_opendir=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -9518,7 +8033,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_opendir+set}" = set; then
break
@@ -9589,27 +8104,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_opendir=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -9618,7 +8117,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_opendir+set}" = set; then
break
@@ -9681,27 +8180,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -9737,17 +8219,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -9817,9 +8292,7 @@ if test "${enable_ltdl_install+set}" = set; then
fi
-
-
-if test x"${enable_ltdl_install-no}" != xno; then
+ if test x"${enable_ltdl_install-no}" != xno; then
INSTALL_LTDL_TRUE=
INSTALL_LTDL_FALSE='#'
else
@@ -9827,9 +8300,7 @@ else
INSTALL_LTDL_FALSE=
fi
-
-
-if test x"${enable_ltdl_convenience-no}" != xno; then
+ if test x"${enable_ltdl_convenience-no}" != xno; then
CONVENIENCE_LTDL_TRUE=
CONVENIENCE_LTDL_FALSE='#'
else
@@ -10841,27 +9312,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_func_shl_load=yes
else
echo "$as_me: failed program was:" >&5
@@ -10870,7 +9325,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_func_shl_load=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
@@ -10924,27 +9379,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_dld_shl_load=yes
else
echo "$as_me: failed program was:" >&5
@@ -10953,7 +9392,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_dld_shl_load=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -11009,27 +9448,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_dl_dlopen=yes
else
echo "$as_me: failed program was:" >&5
@@ -11038,7 +9461,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_dl_dlopen=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -11083,27 +9506,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_LIBDL 1
@@ -11155,27 +9562,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_svld_dlopen=yes
else
echo "$as_me: failed program was:" >&5
@@ -11184,7 +9575,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_svld_dlopen=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -11240,27 +9631,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_dld_dld_link=yes
else
echo "$as_me: failed program was:" >&5
@@ -11269,7 +9644,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_dld_dld_link=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -11346,27 +9721,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_func__dyld_func_lookup=yes
else
echo "$as_me: failed program was:" >&5
@@ -11375,7 +9734,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_func__dyld_func_lookup=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
{ echo "$as_me:$LINENO: result: $ac_cv_func__dyld_func_lookup" >&5
@@ -11397,7 +9756,7 @@ fi
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
@@ -11480,27 +9839,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -11509,7 +9852,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -11596,7 +9939,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 11591 "configure"
+#line 9942 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11825,27 +10168,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -11881,17 +10207,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -11996,27 +10315,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_type_error_t=yes
else
echo "$as_me: failed program was:" >&5
@@ -12116,27 +10418,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -12145,7 +10431,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -12225,27 +10511,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -12281,17 +10550,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -12397,27 +10659,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -12453,17 +10698,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -12567,27 +10805,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -12623,17 +10844,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -12766,27 +10980,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -12795,7 +10993,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -12877,27 +11075,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -12906,7 +11088,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -12988,27 +11170,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -13017,7 +11183,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -13099,27 +11265,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -13128,7 +11278,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -13211,27 +11361,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -13240,7 +11374,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -13256,146 +11390,6 @@ done
-if test "$WITH_LLVMGCCDIR" = "default" ; then
- LLVMGCC="llvm-gcc${EXEEXT}"
- LLVMGXX="llvm-g++${EXEEXT}"
- LLVMGCCCOMMAND="$LLVMGCC"
- LLVMGXXCOMMAND="$LLVMGXX"
- LLVMGCCCOMMAND=$LLVMGCCCOMMAND
-
- LLVMGXXCOMMAND=$LLVMGXXCOMMAND
-
- # Extract the first word of "$LLVMGCC", so it can be a program name with args.
-set dummy $LLVMGCC; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_LLVMGCC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $LLVMGCC in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_LLVMGCC="$LLVMGCC" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_LLVMGCC="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-LLVMGCC=$ac_cv_path_LLVMGCC
-if test -n "$LLVMGCC"; then
- { echo "$as_me:$LINENO: result: $LLVMGCC" >&5
-echo "${ECHO_T}$LLVMGCC" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
- # Extract the first word of "$LLVMGXX", so it can be a program name with args.
-set dummy $LLVMGXX; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_LLVMGXX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $LLVMGXX in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_LLVMGXX="$LLVMGXX" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_path_LLVMGXX="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-LLVMGXX=$ac_cv_path_LLVMGXX
-if test -n "$LLVMGXX"; then
- { echo "$as_me:$LINENO: result: $LLVMGXX" >&5
-echo "${ECHO_T}$LLVMGXX" >&6; }
-else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-else
- if test -z "$LLVMGCC"; then
- LLVMGCC="$WITH_LLVMGCCDIR/bin/llvm-gcc${EXEEXT}"
- LLVMGCCCOMMAND="$LLVMGCC"
- fi
- if test -z "$LLVMGXX"; then
- LLVMGXX="$WITH_LLVMGCCDIR/bin/llvm-g++${EXEEXT}"
- LLVMGXXCOMMAND="$LLVMGXX"
- fi
-
- LLVMGCC=$LLVMGCC
-
- LLVMGXX=$LLVMGXX
-
- LLVMGCCCOMMAND=$LLVMGCCCOMMAND
-
- LLVMGXXCOMMAND=$LLVMGXXCOMMAND
-
-fi
-
-
-# Check whether --with-llvmcc was given.
-if test "${with_llvmcc+set}" = set; then
- withval=$with_llvmcc;
-else
- with_llvmcc=check
-fi
-
-{ echo "$as_me:$LINENO: checking LLVM capable compiler" >&5
-echo $ECHO_N "checking LLVM capable compiler... $ECHO_C" >&6; }
-if test "$with_llvmcc" != "check"; then
- if (test "$with_llvmcc" != "llvm-gcc" &&
- test "$with_llvmcc" != "clang" &&
- test "$with_llvmcc" != "none"); then
- { { echo "$as_me:$LINENO: error: invalid value for --with-llvmcc, expected 'llvm-gcc', 'clang', or 'none'." >&5
-echo "$as_me: error: invalid value for --with-llvmcc, expected 'llvm-gcc', 'clang', or 'none'." >&2;}
- { (exit 1); exit 1; }; }
- fi
- WITH_LLVMCC="$with_llvmcc"
-elif test -n "$LLVMGCC"; then
- WITH_LLVMCC=llvm-gcc
-elif test -n "$WITH_CLANGPATH" || test "$WITH_BUILT_CLANG" -ne "0"; then
- WITH_LLVMCC=clang
-else
- WITH_LLVMCC=none
-fi
-{ echo "$as_me:$LINENO: result: $WITH_LLVMCC" >&5
-echo "${ECHO_T}$WITH_LLVMCC" >&6; }
-LLVMCC_OPTION=$WITH_LLVMCC
-
-
{ echo "$as_me:$LINENO: checking tool compatibility" >&5
echo $ECHO_N "checking tool compatibility... $ECHO_C" >&6; }
@@ -13445,27 +11439,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
:
else
echo "$as_me: failed program was:" >&5
@@ -13542,27 +11519,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_m_sin=yes
else
echo "$as_me: failed program was:" >&5
@@ -13571,7 +11532,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_m_sin=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -13624,27 +11585,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_imagehlp_main=yes
else
echo "$as_me: failed program was:" >&5
@@ -13653,7 +11598,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_imagehlp_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -13705,27 +11650,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_psapi_main=yes
else
echo "$as_me: failed program was:" >&5
@@ -13734,7 +11663,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_psapi_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -13799,27 +11728,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_dlopen=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -13828,7 +11741,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_dlopen+set}" = set; then
break
@@ -13907,27 +11820,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_ffi_call=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -13936,7 +11833,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_ffi_call+set}" = set; then
break
@@ -14016,27 +11913,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_mallinfo=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -14045,7 +11926,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_mallinfo+set}" = set; then
break
@@ -14116,27 +11997,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_pthread_pthread_mutex_init=yes
else
echo "$as_me: failed program was:" >&5
@@ -14145,7 +12010,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_pthread_pthread_mutex_init=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -14208,27 +12073,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_pthread_mutex_lock=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -14237,7 +12086,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then
break
@@ -14311,27 +12160,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_pthread_rwlock_init=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -14340,7 +12173,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then
break
@@ -14414,27 +12247,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_pthread_getspecific=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -14443,7 +12260,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_pthread_getspecific+set}" = set; then
break
@@ -14524,27 +12341,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_udis86_ud_init=yes
else
echo "$as_me: failed program was:" >&5
@@ -14553,7 +12354,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_udis86_ud_init=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -14649,27 +12450,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_bfd_init=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -14678,7 +12463,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_bfd_init+set}" = set; then
break
@@ -14748,27 +12533,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_op_open_agent=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -14777,7 +12546,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_op_open_agent+set}" = set; then
break
@@ -14838,27 +12607,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -14894,17 +12646,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -15028,27 +12773,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
eval "$as_ac_Header=yes"
else
echo "$as_me: failed program was:" >&5
@@ -15121,27 +12849,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_opendir=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -15150,7 +12862,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_opendir+set}" = set; then
break
@@ -15221,27 +12933,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_search_opendir=$ac_res
else
echo "$as_me: failed program was:" >&5
@@ -15250,7 +12946,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_opendir+set}" = set; then
break
@@ -15315,27 +13011,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_header_mmap_anon=yes
else
echo "$as_me: failed program was:" >&5
@@ -15378,73 +13057,22 @@ cat >>conftest.$ac_ext <<_ACEOF
#include <sys/stat.h>
#if defined S_ISBLK && defined S_IFDIR
-# if S_ISBLK (S_IFDIR)
-You lose.
-# endif
+extern char c1[S_ISBLK (S_IFDIR) ? -1 : 1];
#endif
#if defined S_ISBLK && defined S_IFCHR
-# if S_ISBLK (S_IFCHR)
-You lose.
-# endif
+extern char c2[S_ISBLK (S_IFCHR) ? -1 : 1];
#endif
#if defined S_ISLNK && defined S_IFREG
-# if S_ISLNK (S_IFREG)
-You lose.
-# endif
+extern char c3[S_ISLNK (S_IFREG) ? -1 : 1];
#endif
#if defined S_ISSOCK && defined S_IFREG
-# if S_ISSOCK (S_IFREG)
-You lose.
-# endif
+extern char c4[S_ISSOCK (S_IFREG) ? -1 : 1];
#endif
_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "You lose" >/dev/null 2>&1; then
- ac_cv_header_stat_broken=yes
-else
- ac_cv_header_stat_broken=no
-fi
-rm -f conftest*
-
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_stat_broken" >&5
-echo "${ECHO_T}$ac_cv_header_stat_broken" >&6; }
-if test $ac_cv_header_stat_broken = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define STAT_MACROS_BROKEN 1
-_ACEOF
-
-fi
-
-{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
rm -f conftest.$ac_objext
if { (ac_try="$ac_compile"
case "(($ac_try" in
@@ -15458,156 +13086,26 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_header_stdc=yes
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_stat_broken=no
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
- ac_cv_header_stdc=no
+ ac_cv_header_stat_broken=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then
- :
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then
- :
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then
- :
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stat_broken" >&5
+echo "${ECHO_T}$ac_cv_header_stat_broken" >&6; }
+if test $ac_cv_header_stat_broken = yes; then
cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
+#define STAT_MACROS_BROKEN 1
_ACEOF
fi
@@ -15655,27 +13153,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_header_sys_wait_h=yes
else
echo "$as_me: failed program was:" >&5
@@ -15733,27 +13214,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_header_time=yes
else
echo "$as_me: failed program was:" >&5
@@ -15819,27 +13283,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -15875,17 +13322,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -15993,27 +13433,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -16049,17 +13472,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -16163,27 +13579,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -16219,17 +13618,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -16336,27 +13728,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -16392,17 +13767,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -16508,27 +13876,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -16564,17 +13915,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -16677,27 +14021,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -16733,17 +14060,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -16846,27 +14166,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -16902,17 +14205,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -17016,27 +14312,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -17072,17 +14351,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -17196,27 +14468,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -17252,17 +14507,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -17367,27 +14615,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -17423,17 +14654,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -17526,27 +14750,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
@@ -17567,7 +14775,7 @@ _ACEOF
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
@@ -17689,27 +14897,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_type_pid_t=yes
else
echo "$as_me: failed program was:" >&5
@@ -17769,27 +14960,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_type_size_t=yes
else
echo "$as_me: failed program was:" >&5
@@ -17834,7 +15008,9 @@ cat >>conftest.$ac_ext <<_ACEOF
int
main ()
{
-struct tm *tp; tp->tm_sec;
+struct tm tm;
+ int *p = &tm.tm_sec;
+ return !p;
;
return 0;
}
@@ -17852,27 +15028,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_struct_tm=time.h
else
echo "$as_me: failed program was:" >&5
@@ -17930,27 +15089,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_type_int64_t=yes
else
echo "$as_me: failed program was:" >&5
@@ -18013,27 +15155,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_type_uint64_t=yes
else
echo "$as_me: failed program was:" >&5
@@ -18091,27 +15216,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_type_u_int64_t=yes
else
echo "$as_me: failed program was:" >&5
@@ -18214,27 +15322,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -18243,7 +15335,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -18327,27 +15419,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -18356,7 +15432,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -18441,27 +15517,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -18470,7 +15530,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -18553,27 +15613,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -18582,7 +15626,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -18668,27 +15712,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -18697,7 +15725,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -18780,27 +15808,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -18809,7 +15821,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -18893,27 +15905,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -18922,7 +15918,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -19007,27 +16003,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -19036,7 +16016,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -19184,27 +16164,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_func_rand48=yes
else
echo "$as_me: failed program was:" >&5
@@ -19249,8 +16212,7 @@ int
main ()
{
#ifndef strerror_s
- char *p = (char *) strerror_s;
- return !p;
+ (void) strerror_s;
#endif
;
@@ -19270,27 +16232,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_have_decl_strerror_s=yes
else
echo "$as_me: failed program was:" >&5
@@ -19363,27 +16308,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc__alloca=yes
else
echo "$as_me: failed program was:" >&5
@@ -19392,7 +16321,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc__alloca=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -19448,27 +16377,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___alloca=yes
else
echo "$as_me: failed program was:" >&5
@@ -19477,7 +16390,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___alloca=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -19533,27 +16446,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___chkstk=yes
else
echo "$as_me: failed program was:" >&5
@@ -19562,7 +16459,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___chkstk=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -19618,27 +16515,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc____chkstk=yes
else
echo "$as_me: failed program was:" >&5
@@ -19647,7 +16528,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc____chkstk=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -19704,27 +16585,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___ashldi3=yes
else
echo "$as_me: failed program was:" >&5
@@ -19733,7 +16598,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___ashldi3=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -19789,27 +16654,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___ashrdi3=yes
else
echo "$as_me: failed program was:" >&5
@@ -19818,7 +16667,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___ashrdi3=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -19874,27 +16723,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___divdi3=yes
else
echo "$as_me: failed program was:" >&5
@@ -19903,7 +16736,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___divdi3=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -19959,27 +16792,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___fixdfdi=yes
else
echo "$as_me: failed program was:" >&5
@@ -19988,7 +16805,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___fixdfdi=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -20044,27 +16861,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___fixsfdi=yes
else
echo "$as_me: failed program was:" >&5
@@ -20073,7 +16874,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___fixsfdi=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -20129,27 +16930,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___floatdidf=yes
else
echo "$as_me: failed program was:" >&5
@@ -20158,7 +16943,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___floatdidf=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -20214,27 +16999,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___lshrdi3=yes
else
echo "$as_me: failed program was:" >&5
@@ -20243,7 +17012,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___lshrdi3=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -20299,27 +17068,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___moddi3=yes
else
echo "$as_me: failed program was:" >&5
@@ -20328,7 +17081,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___moddi3=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -20384,27 +17137,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___udivdi3=yes
else
echo "$as_me: failed program was:" >&5
@@ -20413,7 +17150,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___udivdi3=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -20469,27 +17206,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___umoddi3=yes
else
echo "$as_me: failed program was:" >&5
@@ -20498,7 +17219,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___umoddi3=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -20555,27 +17276,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___main=yes
else
echo "$as_me: failed program was:" >&5
@@ -20584,7 +17289,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -20640,27 +17345,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_cv_lib_gcc___cmpdi2=yes
else
echo "$as_me: failed program was:" >&5
@@ -20669,7 +17358,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_gcc___cmpdi2=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
@@ -20707,27 +17396,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
@@ -20792,27 +17464,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_func_isnan_in_math_h=yes
else
echo "$as_me: failed program was:" >&5
@@ -20880,27 +17535,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_func_isnan_in_cmath=yes
else
echo "$as_me: failed program was:" >&5
@@ -20967,27 +17605,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_func_std_isnan_in_cmath=yes
else
echo "$as_me: failed program was:" >&5
@@ -21055,27 +17676,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_func_isinf_in_math_h=yes
else
echo "$as_me: failed program was:" >&5
@@ -21142,27 +17746,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_func_isinf_in_cmath=yes
else
echo "$as_me: failed program was:" >&5
@@ -21229,27 +17816,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_func_std_isinf_in_cmath=yes
else
echo "$as_me: failed program was:" >&5
@@ -21316,27 +17886,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_func_finite_in_ieeefp_h=yes
else
echo "$as_me: failed program was:" >&5
@@ -21407,27 +17960,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
@@ -21463,17 +17999,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
@@ -21604,27 +18133,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -21633,7 +18146,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -21690,21 +18203,21 @@ $ac_includes_default
#include <fcntl.h>
#include <sys/mman.h>
-#if !STDC_HEADERS && !HAVE_STDLIB_H
+#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H
char *malloc ();
#endif
/* This mess was copied from the GNU getpagesize.h. */
-#if !HAVE_GETPAGESIZE
+#ifndef HAVE_GETPAGESIZE
/* Assume that all systems that can run configure have sys/param.h. */
-# if !HAVE_SYS_PARAM_H
+# ifndef HAVE_SYS_PARAM_H
# define HAVE_SYS_PARAM_H 1
# endif
# ifdef _SC_PAGESIZE
# define getpagesize() sysconf(_SC_PAGESIZE)
# else /* no _SC_PAGESIZE */
-# if HAVE_SYS_PARAM_H
+# ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
# ifdef EXEC_PAGESIZE
# define getpagesize() EXEC_PAGESIZE
@@ -21996,27 +18509,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -22027,7 +18524,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
echo "${ECHO_T}yes" >&6; }
cat >>confdefs.h <<\_ACEOF
-#define LLVM_MULTITHREADED 1
+#define LLVM_HAS_ATOMICS 1
_ACEOF
else
@@ -22038,14 +18535,14 @@ sed 's/^/| /' conftest.$ac_ext >&5
echo "${ECHO_T}no" >&6; }
cat >>confdefs.h <<\_ACEOF
-#define LLVM_MULTITHREADED 0
+#define LLVM_HAS_ATOMICS 0
_ACEOF
{ echo "$as_me:$LINENO: WARNING: LLVM will be built thread-unsafe because atomic builtins are missing" >&5
echo "$as_me: WARNING: LLVM will be built thread-unsafe because atomic builtins are missing" >&2;}
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
@@ -22092,27 +18589,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
llvm_cv_linux_mixed=no
else
echo "$as_me: failed program was:" >&5
@@ -22206,27 +18686,11 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
@@ -22235,7 +18699,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_var'}'`
@@ -22250,75 +18714,6 @@ fi
done
-{ echo "$as_me:$LINENO: checking whether llvm-gcc is dragonegg" >&5
-echo $ECHO_N "checking whether llvm-gcc is dragonegg... $ECHO_C" >&6; }
-if test "${llvm_cv_llvmgcc_dragonegg+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- llvm_cv_llvmgcc_dragonegg="no"
-if test -n "$LLVMGCC" ; then
- cp /dev/null conftest.c
- $LLVMGCC -fplugin-arg-dragonegg-emit-ir -S -o - conftest.c > /dev/null 2>&1
- if test $? -eq 0 ; then
- llvm_cv_llvmgcc_dragonegg="yes"
- fi
- rm conftest.c
-fi
-fi
-{ echo "$as_me:$LINENO: result: $llvm_cv_llvmgcc_dragonegg" >&5
-echo "${ECHO_T}$llvm_cv_llvmgcc_dragonegg" >&6; }
-
-if test "$llvm_cv_llvmgcc_dragonegg" = "yes" ; then
- LLVMCC_EMITIR_FLAG="-fplugin-arg-dragonegg-emit-ir"
- LLVMCC_DISABLEOPT_FLAGS="-fplugin-arg-dragonegg-llvm-ir-optimize=0"
-else
- LLVMCC_EMITIR_FLAG="-emit-llvm"
- LLVMCC_DISABLEOPT_FLAGS="-mllvm -disable-llvm-optzns"
-fi
-
-
-
-{ echo "$as_me:$LINENO: checking whether llvm-gcc is sane" >&5
-echo $ECHO_N "checking whether llvm-gcc is sane... $ECHO_C" >&6; }
-if test "${llvm_cv_llvmgcc_sanity+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- llvm_cv_llvmgcc_sanity="no"
-if test -n "$LLVMGCC" ; then
- cp /dev/null conftest.c
- $LLVMGCC "$LLVMCC_EMITIR_FLAG" -S -o - conftest.c | \
- grep 'target datalayout =' > /dev/null 2>&1
- if test $? -eq 0 ; then
- llvm_cv_llvmgcc_sanity="yes"
- fi
- rm conftest.c
-fi
-fi
-{ echo "$as_me:$LINENO: result: $llvm_cv_llvmgcc_sanity" >&5
-echo "${ECHO_T}$llvm_cv_llvmgcc_sanity" >&6; }
-
-if test "$llvm_cv_llvmgcc_sanity" = "yes" ; then
- { echo "$as_me:$LINENO: checking llvm-gcc component support" >&5
-echo $ECHO_N "checking llvm-gcc component support... $ECHO_C" >&6; }
- llvmcc1path=`$LLVMGCC --print-prog-name=cc1`
- LLVMCC1=$llvmcc1path
-
- llvmcc1pluspath=`$LLVMGCC --print-prog-name=cc1plus`
- LLVMCC1PLUS=$llvmcc1pluspath
-
- llvmgccdir=`echo "$llvmcc1path" | sed 's,/libexec/.*,,'`
- LLVMGCCDIR=$llvmgccdir
-
- llvmgcclangs=`$LLVMGCC -v --help 2>&1 | grep '^Configured with:' | sed 's/^.*--enable-languages=\([^ ]*\).*/\1/'`
- LLVMGCC_LANGS=$llvmgcclangs
-
- LLVMGCC_DRAGONEGG=$llvm_cv_llvmgcc_dragonegg
-
-
- { echo "$as_me:$LINENO: result: ok" >&5
-echo "${ECHO_T}ok" >&6; }
-fi
-
SHLIBEXT=$libltdl_cv_shlibext
@@ -22510,27 +18905,10 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
llvm_cv_cxx_visibility_inlines_hidden=yes
else
echo "$as_me: failed program was:" >&5
@@ -22606,10 +18984,10 @@ if test -f ${srcdir}/tools/clang/README.txt; then
fi
-ac_config_files="$ac_config_files tools/llvmc/src/Base.td"
+ac_config_files="$ac_config_files tools/llvm-config/llvm-config.in"
-ac_config_files="$ac_config_files tools/llvm-config/llvm-config.in"
+ac_config_files="$ac_config_files bindings/ocaml/llvm/META.llvm"
ac_config_commands="$ac_config_commands setup"
@@ -22788,7 +19166,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF
## M4sh Initialization. ##
## --------------------- ##
-# Be Bourne compatible
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
@@ -22797,10 +19176,13 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
- case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
+
+
# PATH needs CR
@@ -23024,19 +19406,28 @@ else
as_mkdir_p=false
fi
-# Find out whether ``test -x'' works. Don't use a zero-byte file, as
-# systems may use methods other than mode bits to determine executability.
-cat >conf$$.file <<_ASEOF
-#! /bin/sh
-exit 0
-_ASEOF
-chmod +x conf$$.file
-if test -x conf$$.file >/dev/null 2>&1; then
- as_executable_p="test -x"
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
else
- as_executable_p=:
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
fi
-rm -f conf$$.file
+as_executable_p=$as_test_x
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -23051,8 +19442,8 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by llvm $as_me 3.0svn, which was
-generated by GNU Autoconf 2.60. Invocation command line was
+This file was extended by llvm $as_me 3.0, which was
+generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -23081,7 +19472,7 @@ current configuration.
Usage: $0 [OPTIONS] [FILE]...
-h, --help print this help, then exit
- -V, --version print version number, then exit
+ -V, --version print version number and configuration settings, then exit
-q, --quiet do not print progress messages
-d, --debug don't remove temporary files
--recheck update $as_me by reconfiguring in the same conditions
@@ -23104,8 +19495,8 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-llvm config.status 3.0svn
-configured by $0, generated by GNU Autoconf 2.60,
+llvm config.status 3.0
+configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
Copyright (C) 2006 Free Software Foundation, Inc.
@@ -23228,8 +19619,8 @@ do
"llvm.spec") CONFIG_FILES="$CONFIG_FILES llvm.spec" ;;
"docs/doxygen.cfg") CONFIG_FILES="$CONFIG_FILES docs/doxygen.cfg" ;;
"tools/clang/docs/doxygen.cfg") CONFIG_FILES="$CONFIG_FILES tools/clang/docs/doxygen.cfg" ;;
- "tools/llvmc/src/Base.td") CONFIG_FILES="$CONFIG_FILES tools/llvmc/src/Base.td" ;;
"tools/llvm-config/llvm-config.in") CONFIG_FILES="$CONFIG_FILES tools/llvm-config/llvm-config.in" ;;
+ "bindings/ocaml/llvm/META.llvm") CONFIG_FILES="$CONFIG_FILES bindings/ocaml/llvm/META.llvm" ;;
"setup") CONFIG_COMMANDS="$CONFIG_COMMANDS setup" ;;
"Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS Makefile" ;;
"Makefile.common") CONFIG_COMMANDS="$CONFIG_COMMANDS Makefile.common" ;;
@@ -23344,6 +19735,17 @@ build_alias!$build_alias$ac_delim
host_alias!$host_alias$ac_delim
target_alias!$target_alias$ac_delim
LLVM_COPYRIGHT!$LLVM_COPYRIGHT$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+CPP!$CPP$ac_delim
subdirs!$subdirs$ac_delim
ENABLE_POLLY!$ENABLE_POLLY$ac_delim
LLVM_HAS_POLLY!$LLVM_HAS_POLLY$ac_delim
@@ -23368,14 +19770,6 @@ LLVM_ON_UNIX!$LLVM_ON_UNIX$ac_delim
LLVM_ON_WIN32!$LLVM_ON_WIN32$ac_delim
ARCH!$ARCH$ac_delim
ENDIAN!$ENDIAN$ac_delim
-CC!$CC$ac_delim
-CFLAGS!$CFLAGS$ac_delim
-LDFLAGS!$LDFLAGS$ac_delim
-CPPFLAGS!$CPPFLAGS$ac_delim
-ac_ct_CC!$ac_ct_CC$ac_delim
-EXEEXT!$EXEEXT$ac_delim
-OBJEXT!$OBJEXT$ac_delim
-CPP!$CPP$ac_delim
GREP!$GREP$ac_delim
EGREP!$EGREP$ac_delim
LLVM_CROSS_COMPILING!$LLVM_CROSS_COMPILING$ac_delim
@@ -23400,9 +19794,6 @@ ENABLE_PIC!$ENABLE_PIC$ac_delim
ENABLE_SHARED!$ENABLE_SHARED$ac_delim
ENABLE_EMBED_STDCXX!$ENABLE_EMBED_STDCXX$ac_delim
ENABLE_TIMESTAMPS!$ENABLE_TIMESTAMPS$ac_delim
-TARGETS_TO_BUILD!$TARGETS_TO_BUILD$ac_delim
-LLVM_ENUM_TARGETS!$LLVM_ENUM_TARGETS$ac_delim
-LLVM_ENUM_ASM_PRINTERS!$LLVM_ENUM_ASM_PRINTERS$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -23444,19 +19835,16 @@ _ACEOF
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
cat >conf$$subs.sed <<_ACEOF
+TARGETS_TO_BUILD!$TARGETS_TO_BUILD$ac_delim
+LLVM_ENUM_TARGETS!$LLVM_ENUM_TARGETS$ac_delim
+LLVM_ENUM_ASM_PRINTERS!$LLVM_ENUM_ASM_PRINTERS$ac_delim
LLVM_ENUM_ASM_PARSERS!$LLVM_ENUM_ASM_PARSERS$ac_delim
LLVM_ENUM_DISASSEMBLERS!$LLVM_ENUM_DISASSEMBLERS$ac_delim
ENABLE_CBE_PRINTF_A!$ENABLE_CBE_PRINTF_A$ac_delim
-CLANGPATH!$CLANGPATH$ac_delim
-CLANGXXPATH!$CLANGXXPATH$ac_delim
-ENABLE_BUILT_CLANG!$ENABLE_BUILT_CLANG$ac_delim
OPTIMIZE_OPTION!$OPTIMIZE_OPTION$ac_delim
EXTRA_OPTIONS!$EXTRA_OPTIONS$ac_delim
EXTRA_LD_OPTIONS!$EXTRA_LD_OPTIONS$ac_delim
BINUTILS_INCDIR!$BINUTILS_INCDIR$ac_delim
-CXX!$CXX$ac_delim
-CXXFLAGS!$CXXFLAGS$ac_delim
-ac_ct_CXX!$ac_ct_CXX$ac_delim
NM!$NM$ac_delim
ifGNUmake!$ifGNUmake$ac_delim
LN_S!$LN_S$ac_delim
@@ -23508,11 +19896,6 @@ INSTALL_LTDL_FALSE!$INSTALL_LTDL_FALSE$ac_delim
CONVENIENCE_LTDL_TRUE!$CONVENIENCE_LTDL_TRUE$ac_delim
CONVENIENCE_LTDL_FALSE!$CONVENIENCE_LTDL_FALSE$ac_delim
LIBADD_DL!$LIBADD_DL$ac_delim
-LLVMGCCCOMMAND!$LLVMGCCCOMMAND$ac_delim
-LLVMGXXCOMMAND!$LLVMGXXCOMMAND$ac_delim
-LLVMGCC!$LLVMGCC$ac_delim
-LLVMGXX!$LLVMGXX$ac_delim
-LLVMCC_OPTION!$LLVMCC_OPTION$ac_delim
NO_VARIADIC_MACROS!$NO_VARIADIC_MACROS$ac_delim
NO_MISSING_FIELD_INITIALIZERS!$NO_MISSING_FIELD_INITIALIZERS$ac_delim
USE_UDIS86!$USE_UDIS86$ac_delim
@@ -23520,13 +19903,6 @@ USE_OPROFILE!$USE_OPROFILE$ac_delim
HAVE_PTHREAD!$HAVE_PTHREAD$ac_delim
HUGE_VAL_SANITY!$HUGE_VAL_SANITY$ac_delim
MMAP_FILE!$MMAP_FILE$ac_delim
-LLVMCC_EMITIR_FLAG!$LLVMCC_EMITIR_FLAG$ac_delim
-LLVMCC1!$LLVMCC1$ac_delim
-LLVMCC1PLUS!$LLVMCC1PLUS$ac_delim
-LLVMGCCDIR!$LLVMGCCDIR$ac_delim
-LLVMGCC_LANGS!$LLVMGCC_LANGS$ac_delim
-LLVMGCC_DRAGONEGG!$LLVMGCC_DRAGONEGG$ac_delim
-LLVMCC_DISABLEOPT_FLAGS!$LLVMCC_DISABLEOPT_FLAGS$ac_delim
SHLIBEXT!$SHLIBEXT$ac_delim
SHLIBPATH_VAR!$SHLIBPATH_VAR$ac_delim
LLVM_PREFIX!$LLVM_PREFIX$ac_delim
@@ -23541,47 +19917,6 @@ LLVM_MANDIR!$LLVM_MANDIR$ac_delim
LLVM_CONFIGTIME!$LLVM_CONFIGTIME$ac_delim
BINDINGS_TO_BUILD!$BINDINGS_TO_BUILD$ac_delim
ALL_BINDINGS!$ALL_BINDINGS$ac_delim
-_ACEOF
-
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
- break
- elif $ac_last_try; then
- { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
-echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
- { (exit 1); exit 1; }; }
- else
- ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
- fi
-done
-
-ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
-if test -n "$ac_eof"; then
- ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
- ac_eof=`expr $ac_eof + 1`
-fi
-
-cat >>$CONFIG_STATUS <<_ACEOF
-cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-_ACEOF
-sed '
-s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
-s/^/s,@/; s/!/@,|#_!!_#|/
-:n
-t n
-s/'"$ac_delim"'$/,g/; t
-s/$/\\/; p
-N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
-' >>$CONFIG_STATUS <conf$$subs.sed
-rm -f conf$$subs.sed
-cat >>$CONFIG_STATUS <<_ACEOF
-CEOF$ac_eof
-_ACEOF
-
-
-ac_delim='%!_!# '
-for ac_last_try in false false false false false :; do
- cat >conf$$subs.sed <<_ACEOF
OCAML_LIBDIR!$OCAML_LIBDIR$ac_delim
ENABLE_VISIBILITY_INLINES_HIDDEN!$ENABLE_VISIBILITY_INLINES_HIDDEN$ac_delim
RPATH!$RPATH$ac_delim
@@ -23590,7 +19925,7 @@ LIBOBJS!$LIBOBJS$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 6; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 88; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
@@ -23608,7 +19943,7 @@ if test -n "$ac_eof"; then
fi
cat >>$CONFIG_STATUS <<_ACEOF
-cat >"\$tmp/subs-3.sed" <<\CEOF$ac_eof
+cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
_ACEOF
sed '
@@ -23871,7 +20206,7 @@ s&@abs_builddir@&$ac_abs_builddir&;t t
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
s&@INSTALL@&$ac_INSTALL&;t t
$ac_datarootdir_hack
-" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" | sed -f "$tmp/subs-3.sed" >$tmp/out
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
@@ -23951,7 +20286,7 @@ do
cat >>$CONFIG_STATUS <<_ACEOF
# First, check the format of the line:
cat >"\$tmp/defines.sed" <<\\CEOF
-/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*/b def
/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
b
:def
@@ -24099,7 +20434,12 @@ if test "$no_recursion" != yes; then
case $ac_arg in
*\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
- ac_sub_configure_args="$ac_arg $ac_sub_configure_args"
+ ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args"
+
+ # Pass --silent
+ if test "$silent" = yes; then
+ ac_sub_configure_args="--silent $ac_sub_configure_args"
+ fi
ac_popdir=`pwd`
for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue
diff --git a/docs/Atomics.html b/docs/Atomics.html
new file mode 100644
index 0000000..fc15e27
--- /dev/null
+++ b/docs/Atomics.html
@@ -0,0 +1,569 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>LLVM Atomic Instructions and Concurrency Guide</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" href="llvm.css" type="text/css">
+</head>
+<body>
+
+<h1>
+ LLVM Atomic Instructions and Concurrency Guide
+</h1>
+
+<ol>
+ <li><a href="#introduction">Introduction</a></li>
+ <li><a href="#outsideatomic">Optimization outside atomic</a></li>
+ <li><a href="#atomicinst">Atomic instructions</a></li>
+ <li><a href="#ordering">Atomic orderings</a></li>
+ <li><a href="#iropt">Atomics and IR optimization</a></li>
+ <li><a href="#codegen">Atomics and Codegen</a></li>
+</ol>
+
+<div class="doc_author">
+ <p>Written by Eli Friedman</p>
+</div>
+
+<!-- *********************************************************************** -->
+<h2>
+ <a name="introduction">Introduction</a>
+</h2>
+<!-- *********************************************************************** -->
+
+<div>
+
+<p>Historically, LLVM has not had very strong support for concurrency; some
+minimal intrinsics were provided, and <code>volatile</code> was used in some
+cases to achieve rough semantics in the presence of concurrency. However, this
+is changing; there are now new instructions which are well-defined in the
+presence of threads and asynchronous signals, and the model for existing
+instructions has been clarified in the IR.</p>
+
+<p>The atomic instructions are designed specifically to provide readable IR and
+ optimized code generation for the following:</p>
+<ul>
+ <li>The new C++0x <code>&lt;atomic&gt;</code> header.
+ (<a href="http://www.open-std.org/jtc1/sc22/wg21/">C++0x draft available here</a>.)
+ (<a href="http://www.open-std.org/jtc1/sc22/wg14/">C1x draft available here</a>)</li>
+ <li>Proper semantics for Java-style memory, for both <code>volatile</code> and
+ regular shared variables.
+ (<a href="http://java.sun.com/docs/books/jls/third_edition/html/memory.html">Java Specification</a>)</li>
+ <li>gcc-compatible <code>__sync_*</code> builtins.
+ (<a href="http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html">Description</a>)</li>
+ <li>Other scenarios with atomic semantics, including <code>static</code>
+ variables with non-trivial constructors in C++.</li>
+</ul>
+
+<p>Atomic and volatile in the IR are orthogonal; "volatile" is the C/C++
+ volatile, which ensures that every volatile load and store happens and is
+ performed in the stated order. A couple examples: if a
+ SequentiallyConsistent store is immediately followed by another
+ SequentiallyConsistent store to the same address, the first store can
+ be erased. This transformation is not allowed for a pair of volatile
+ stores. On the other hand, a non-volatile non-atomic load can be moved
+ across a volatile load freely, but not an Acquire load.</p>
+
+<p>This document is intended to provide a guide to anyone either writing a
+ frontend for LLVM or working on optimization passes for LLVM with a guide
+ for how to deal with instructions with special semantics in the presence of
+ concurrency. This is not intended to be a precise guide to the semantics;
+ the details can get extremely complicated and unreadable, and are not
+ usually necessary.</p>
+
+</div>
+
+<!-- *********************************************************************** -->
+<h2>
+ <a name="outsideatomic">Optimization outside atomic</a>
+</h2>
+<!-- *********************************************************************** -->
+
+<div>
+
+<p>The basic <code>'load'</code> and <code>'store'</code> allow a variety of
+ optimizations, but can lead to undefined results in a concurrent environment;
+ see <a href="#o_nonatomic">NonAtomic</a>. This section specifically goes
+ into the one optimizer restriction which applies in concurrent environments,
+ which gets a bit more of an extended description because any optimization
+ dealing with stores needs to be aware of it.</p>
+
+<p>From the optimizer's point of view, the rule is that if there
+ are not any instructions with atomic ordering involved, concurrency does
+ not matter, with one exception: if a variable might be visible to another
+ thread or signal handler, a store cannot be inserted along a path where it
+ might not execute otherwise. Take the following example:</p>
+
+<pre>
+/* C code, for readability; run through clang -O2 -S -emit-llvm to get
+ equivalent IR */
+int x;
+void f(int* a) {
+ for (int i = 0; i &lt; 100; i++) {
+ if (a[i])
+ x += 1;
+ }
+}
+</pre>
+
+<p>The following is equivalent in non-concurrent situations:</p>
+
+<pre>
+int x;
+void f(int* a) {
+ int xtemp = x;
+ for (int i = 0; i &lt; 100; i++) {
+ if (a[i])
+ xtemp += 1;
+ }
+ x = xtemp;
+}
+</pre>
+
+<p>However, LLVM is not allowed to transform the former to the latter: it could
+ indirectly introduce undefined behavior if another thread can access x at
+ the same time. (This example is particularly of interest because before the
+ concurrency model was implemented, LLVM would perform this
+ transformation.)</p>
+
+<p>Note that speculative loads are allowed; a load which
+ is part of a race returns <code>undef</code>, but does not have undefined
+ behavior.</p>
+
+
+</div>
+
+<!-- *********************************************************************** -->
+<h2>
+ <a name="atomicinst">Atomic instructions</a>
+</h2>
+<!-- *********************************************************************** -->
+
+<div>
+
+<p>For cases where simple loads and stores are not sufficient, LLVM provides
+ various atomic instructions. The exact guarantees provided depend on the
+ ordering; see <a href="#ordering">Atomic orderings</a></p>
+
+<p><code>load atomic</code> and <code>store atomic</code> provide the same
+ basic functionality as non-atomic loads and stores, but provide additional
+ guarantees in situations where threads and signals are involved.</p>
+
+<p><code>cmpxchg</code> and <code>atomicrmw</code> are essentially like an
+ atomic load followed by an atomic store (where the store is conditional for
+ <code>cmpxchg</code>), but no other memory operation can happen on any thread
+ between the load and store. Note that LLVM's cmpxchg does not provide quite
+ as many options as the C++0x version.</p>
+
+<p>A <code>fence</code> provides Acquire and/or Release ordering which is not
+ part of another operation; it is normally used along with Monotonic memory
+ operations. A Monotonic load followed by an Acquire fence is roughly
+ equivalent to an Acquire load.</p>
+
+<p>Frontends generating atomic instructions generally need to be aware of the
+ target to some degree; atomic instructions are guaranteed to be lock-free,
+ and therefore an instruction which is wider than the target natively supports
+ can be impossible to generate.</p>
+
+</div>
+
+<!-- *********************************************************************** -->
+<h2>
+ <a name="ordering">Atomic orderings</a>
+</h2>
+<!-- *********************************************************************** -->
+
+<div>
+
+<p>In order to achieve a balance between performance and necessary guarantees,
+ there are six levels of atomicity. They are listed in order of strength;
+ each level includes all the guarantees of the previous level except for
+ Acquire/Release. (See also <a href="LangRef.html#ordering">LangRef</a>.)</p>
+
+<!-- ======================================================================= -->
+<h3>
+ <a name="o_notatomic">NotAtomic</a>
+</h3>
+
+<div>
+
+<p>NotAtomic is the obvious, a load or store which is not atomic. (This isn't
+ really a level of atomicity, but is listed here for comparison.) This is
+ essentially a regular load or store. If there is a race on a given memory
+ location, loads from that location return undef.</p>
+
+<dl>
+ <dt>Relevant standard</dt>
+ <dd>This is intended to match shared variables in C/C++, and to be used
+ in any other context where memory access is necessary, and
+ a race is impossible. (The precise definition is in
+ <a href="LangRef.html#memmodel">LangRef</a>.)
+ <dt>Notes for frontends</dt>
+ <dd>The rule is essentially that all memory accessed with basic loads and
+ stores by multiple threads should be protected by a lock or other
+ synchronization; otherwise, you are likely to run into undefined
+ behavior. If your frontend is for a "safe" language like Java,
+ use Unordered to load and store any shared variable. Note that NotAtomic
+ volatile loads and stores are not properly atomic; do not try to use
+ them as a substitute. (Per the C/C++ standards, volatile does provide
+ some limited guarantees around asynchronous signals, but atomics are
+ generally a better solution.)
+ <dt>Notes for optimizers</dt>
+ <dd>Introducing loads to shared variables along a codepath where they would
+ not otherwise exist is allowed; introducing stores to shared variables
+ is not. See <a href="#outsideatomic">Optimization outside
+ atomic</a>.</dd>
+ <dt>Notes for code generation</dt>
+ <dd>The one interesting restriction here is that it is not allowed to write
+ to bytes outside of the bytes relevant to a store. This is mostly
+ relevant to unaligned stores: it is not allowed in general to convert
+ an unaligned store into two aligned stores of the same width as the
+ unaligned store. Backends are also expected to generate an i8 store
+ as an i8 store, and not an instruction which writes to surrounding
+ bytes. (If you are writing a backend for an architecture which cannot
+ satisfy these restrictions and cares about concurrency, please send an
+ email to llvmdev.)</dd>
+</dl>
+
+</div>
+
+
+<!-- ======================================================================= -->
+<h3>
+ <a name="o_unordered">Unordered</a>
+</h3>
+
+<div>
+
+<p>Unordered is the lowest level of atomicity. It essentially guarantees that
+ races produce somewhat sane results instead of having undefined behavior.
+ It also guarantees the operation to be lock-free, so it do not depend on
+ the data being part of a special atomic structure or depend on a separate
+ per-process global lock. Note that code generation will fail for
+ unsupported atomic operations; if you need such an operation, use explicit
+ locking.</p>
+
+<dl>
+ <dt>Relevant standard</dt>
+ <dd>This is intended to match the Java memory model for shared
+ variables.</dd>
+ <dt>Notes for frontends</dt>
+ <dd>This cannot be used for synchronization, but is useful for Java and
+ other "safe" languages which need to guarantee that the generated
+ code never exhibits undefined behavior. Note that this guarantee
+ is cheap on common platforms for loads of a native width, but can
+ be expensive or unavailable for wider loads, like a 64-bit store
+ on ARM. (A frontend for Java or other "safe" languages would normally
+ split a 64-bit store on ARM into two 32-bit unordered stores.)
+ <dt>Notes for optimizers</dt>
+ <dd>In terms of the optimizer, this prohibits any transformation that
+ transforms a single load into multiple loads, transforms a store
+ into multiple stores, narrows a store, or stores a value which
+ would not be stored otherwise. Some examples of unsafe optimizations
+ are narrowing an assignment into a bitfield, rematerializing
+ a load, and turning loads and stores into a memcpy call. Reordering
+ unordered operations is safe, though, and optimizers should take
+ advantage of that because unordered operations are common in
+ languages that need them.</dd>
+ <dt>Notes for code generation</dt>
+ <dd>These operations are required to be atomic in the sense that if you
+ use unordered loads and unordered stores, a load cannot see a value
+ which was never stored. A normal load or store instruction is usually
+ sufficient, but note that an unordered load or store cannot
+ be split into multiple instructions (or an instruction which
+ does multiple memory operations, like <code>LDRD</code> on ARM).</dd>
+</dl>
+
+</div>
+
+<!-- ======================================================================= -->
+<h3>
+ <a name="o_monotonic">Monotonic</a>
+</h3>
+
+<div>
+
+<p>Monotonic is the weakest level of atomicity that can be used in
+ synchronization primitives, although it does not provide any general
+ synchronization. It essentially guarantees that if you take all the
+ operations affecting a specific address, a consistent ordering exists.
+
+<dl>
+ <dt>Relevant standard</dt>
+ <dd>This corresponds to the C++0x/C1x <code>memory_order_relaxed</code>;
+ see those standards for the exact definition.
+ <dt>Notes for frontends</dt>
+ <dd>If you are writing a frontend which uses this directly, use with caution.
+ The guarantees in terms of synchronization are very weak, so make
+ sure these are only used in a pattern which you know is correct.
+ Generally, these would either be used for atomic operations which
+ do not protect other memory (like an atomic counter), or along with
+ a <code>fence</code>.</dd>
+ <dt>Notes for optimizers</dt>
+ <dd>In terms of the optimizer, this can be treated as a read+write on the
+ relevant memory location (and alias analysis will take advantage of
+ that). In addition, it is legal to reorder non-atomic and Unordered
+ loads around Monotonic loads. CSE/DSE and a few other optimizations
+ are allowed, but Monotonic operations are unlikely to be used in ways
+ which would make those optimizations useful.</dd>
+ <dt>Notes for code generation</dt>
+ <dd>Code generation is essentially the same as that for unordered for loads
+ and stores. No fences are required. <code>cmpxchg</code> and
+ <code>atomicrmw</code> are required to appear as a single operation.</dd>
+</dl>
+
+</div>
+
+<!-- ======================================================================= -->
+<h3>
+ <a name="o_acquire">Acquire</a>
+</h3>
+
+<div>
+
+<p>Acquire provides a barrier of the sort necessary to acquire a lock to access
+ other memory with normal loads and stores.
+
+<dl>
+ <dt>Relevant standard</dt>
+ <dd>This corresponds to the C++0x/C1x <code>memory_order_acquire</code>. It
+ should also be used for C++0x/C1x <code>memory_order_consume</code>.
+ <dt>Notes for frontends</dt>
+ <dd>If you are writing a frontend which uses this directly, use with caution.
+ Acquire only provides a semantic guarantee when paired with a Release
+ operation.</dd>
+ <dt>Notes for optimizers</dt>
+ <dd>Optimizers not aware of atomics can treat this like a nothrow call.
+ It is also possible to move stores from before an Acquire load
+ or read-modify-write operation to after it, and move non-Acquire
+ loads from before an Acquire operation to after it.</dd>
+ <dt>Notes for code generation</dt>
+ <dd>Architectures with weak memory ordering (essentially everything relevant
+ today except x86 and SPARC) require some sort of fence to maintain
+ the Acquire semantics. The precise fences required varies widely by
+ architecture, but for a simple implementation, most architectures provide
+ a barrier which is strong enough for everything (<code>dmb</code> on ARM,
+ <code>sync</code> on PowerPC, etc.). Putting such a fence after the
+ equivalent Monotonic operation is sufficient to maintain Acquire
+ semantics for a memory operation.</dd>
+</dl>
+
+</div>
+
+<!-- ======================================================================= -->
+<h3>
+ <a name="o_acquire">Release</a>
+</h3>
+
+<div>
+
+<p>Release is similar to Acquire, but with a barrier of the sort necessary to
+ release a lock.
+
+<dl>
+ <dt>Relevant standard</dt>
+ <dd>This corresponds to the C++0x/C1x <code>memory_order_release</code>.</dd>
+ <dt>Notes for frontends</dt>
+ <dd>If you are writing a frontend which uses this directly, use with caution.
+ Release only provides a semantic guarantee when paired with a Acquire
+ operation.</dd>
+ <dt>Notes for optimizers</dt>
+ <dd>Optimizers not aware of atomics can treat this like a nothrow call.
+ It is also possible to move loads from after a Release store
+ or read-modify-write operation to before it, and move non-Release
+ stores from after an Release operation to before it.</dd>
+ <dt>Notes for code generation</dt>
+ <dd>See the section on Acquire; a fence before the relevant operation is
+ usually sufficient for Release. Note that a store-store fence is not
+ sufficient to implement Release semantics; store-store fences are
+ generally not exposed to IR because they are extremely difficult to
+ use correctly.</dd>
+</dl>
+
+</div>
+
+<!-- ======================================================================= -->
+<h3>
+ <a name="o_acqrel">AcquireRelease</a>
+</h3>
+
+<div>
+
+<p>AcquireRelease (<code>acq_rel</code> in IR) provides both an Acquire and a
+ Release barrier (for fences and operations which both read and write memory).
+
+<dl>
+ <dt>Relevant standard</dt>
+ <dd>This corresponds to the C++0x/C1x <code>memory_order_acq_rel</code>.
+ <dt>Notes for frontends</dt>
+ <dd>If you are writing a frontend which uses this directly, use with caution.
+ Acquire only provides a semantic guarantee when paired with a Release
+ operation, and vice versa.</dd>
+ <dt>Notes for optimizers</dt>
+ <dd>In general, optimizers should treat this like a nothrow call; the
+ the possible optimizations are usually not interesting.</dd>
+ <dt>Notes for code generation</dt>
+ <dd>This operation has Acquire and Release semantics; see the sections on
+ Acquire and Release.</dd>
+</dl>
+
+</div>
+
+<!-- ======================================================================= -->
+<h3>
+ <a name="o_seqcst">SequentiallyConsistent</a>
+</h3>
+
+<div>
+
+<p>SequentiallyConsistent (<code>seq_cst</code> in IR) provides
+ Acquire semantics for loads and Release semantics for
+ stores. Additionally, it guarantees that a total ordering exists
+ between all SequentiallyConsistent operations.
+
+<dl>
+ <dt>Relevant standard</dt>
+ <dd>This corresponds to the C++0x/C1x <code>memory_order_seq_cst</code>,
+ Java volatile, and the gcc-compatible <code>__sync_*</code> builtins
+ which do not specify otherwise.
+ <dt>Notes for frontends</dt>
+ <dd>If a frontend is exposing atomic operations, these are much easier to
+ reason about for the programmer than other kinds of operations, and using
+ them is generally a practical performance tradeoff.</dd>
+ <dt>Notes for optimizers</dt>
+ <dd>Optimizers not aware of atomics can treat this like a nothrow call.
+ For SequentiallyConsistent loads and stores, the same reorderings are
+ allowed as for Acquire loads and Release stores, except that
+ SequentiallyConsistent operations may not be reordered.</dd>
+ <dt>Notes for code generation</dt>
+ <dd>SequentiallyConsistent loads minimally require the same barriers
+ as Acquire operations and SequentiallyConsistent stores require
+ Release barriers. Additionally, the code generator must enforce
+ ordering between SequentiallyConsistent stores followed by
+ SequentiallyConsistent loads. This is usually done by emitting
+ either a full fence before the loads or a full fence after the
+ stores; which is preferred varies by architecture.</dd>
+</dl>
+
+</div>
+
+</div>
+
+<!-- *********************************************************************** -->
+<h2>
+ <a name="iropt">Atomics and IR optimization</a>
+</h2>
+<!-- *********************************************************************** -->
+
+<div>
+
+<p>Predicates for optimizer writers to query:
+<ul>
+ <li>isSimple(): A load or store which is not volatile or atomic. This is
+ what, for example, memcpyopt would check for operations it might
+ transform.</li>
+ <li>isUnordered(): A load or store which is not volatile and at most
+ Unordered. This would be checked, for example, by LICM before hoisting
+ an operation.</li>
+ <li>mayReadFromMemory()/mayWriteToMemory(): Existing predicate, but note
+ that they return true for any operation which is volatile or at least
+ Monotonic.</li>
+ <li>Alias analysis: Note that AA will return ModRef for anything Acquire or
+ Release, and for the address accessed by any Monotonic operation.</li>
+</ul>
+
+<p>To support optimizing around atomic operations, make sure you are using
+ the right predicates; everything should work if that is done. If your
+ pass should optimize some atomic operations (Unordered operations in
+ particular), make sure it doesn't replace an atomic load or store with
+ a non-atomic operation.</p>
+
+<p>Some examples of how optimizations interact with various kinds of atomic
+ operations:
+<ul>
+ <li>memcpyopt: An atomic operation cannot be optimized into part of a
+ memcpy/memset, including unordered loads/stores. It can pull operations
+ across some atomic operations.
+ <li>LICM: Unordered loads/stores can be moved out of a loop. It just treats
+ monotonic operations like a read+write to a memory location, and anything
+ stricter than that like a nothrow call.
+ <li>DSE: Unordered stores can be DSE'ed like normal stores. Monotonic stores
+ can be DSE'ed in some cases, but it's tricky to reason about, and not
+ especially important.
+ <li>Folding a load: Any atomic load from a constant global can be
+ constant-folded, because it cannot be observed. Similar reasoning allows
+ scalarrepl with atomic loads and stores.
+</ul>
+
+</div>
+
+<!-- *********************************************************************** -->
+<h2>
+ <a name="codegen">Atomics and Codegen</a>
+</h2>
+<!-- *********************************************************************** -->
+
+<div>
+
+<p>Atomic operations are represented in the SelectionDAG with
+ <code>ATOMIC_*</code> opcodes. On architectures which use barrier
+ instructions for all atomic ordering (like ARM), appropriate fences are
+ split out as the DAG is built.</p>
+
+<p>The MachineMemOperand for all atomic operations is currently marked as
+ volatile; this is not correct in the IR sense of volatile, but CodeGen
+ handles anything marked volatile very conservatively. This should get
+ fixed at some point.</p>
+
+<p>Common architectures have some way of representing at least a pointer-sized
+ lock-free <code>cmpxchg</code>; such an operation can be used to implement
+ all the other atomic operations which can be represented in IR up to that
+ size. Backends are expected to implement all those operations, but not
+ operations which cannot be implemented in a lock-free manner. It is
+ expected that backends will give an error when given an operation which
+ cannot be implemented. (The LLVM code generator is not very helpful here
+ at the moment, but hopefully that will change.)</p>
+
+<p>The implementation of atomics on LL/SC architectures (like ARM) is currently
+ a bit of a mess; there is a lot of copy-pasted code across targets, and
+ the representation is relatively unsuited to optimization (it would be nice
+ to be able to optimize loops involving cmpxchg etc.).</p>
+
+<p>On x86, all atomic loads generate a <code>MOV</code>.
+ SequentiallyConsistent stores generate an <code>XCHG</code>, other stores
+ generate a <code>MOV</code>. SequentiallyConsistent fences generate an
+ <code>MFENCE</code>, other fences do not cause any code to be generated.
+ cmpxchg uses the <code>LOCK CMPXCHG</code> instruction.
+ <code>atomicrmw xchg</code> uses <code>XCHG</code>,
+ <code>atomicrmw add</code> and <code>atomicrmw sub</code> use
+ <code>XADD</code>, and all other <code>atomicrmw</code> operations generate
+ a loop with <code>LOCK CMPXCHG</code>. Depending on the users of the
+ result, some <code>atomicrmw</code> operations can be translated into
+ operations like <code>LOCK AND</code>, but that does not work in
+ general.</p>
+
+<p>On ARM, MIPS, and many other RISC architectures, Acquire, Release, and
+ SequentiallyConsistent semantics require barrier instructions
+ for every such operation. Loads and stores generate normal instructions.
+ <code>cmpxchg</code> and <code>atomicrmw</code> can be represented using
+ a loop with LL/SC-style instructions which take some sort of exclusive
+ lock on a cache line (<code>LDREX</code> and <code>STREX</code> on
+ ARM, etc.). At the moment, the IR does not provide any way to represent a
+ weak <code>cmpxchg</code> which would not require a loop.</p>
+</div>
+
+<!-- *********************************************************************** -->
+
+<hr>
+<address>
+ <a href="http://jigsaw.w3.org/css-validator/check/referer"><img
+ src="http://jigsaw.w3.org/css-validator/images/vcss-blue" alt="Valid CSS"></a>
+ <a href="http://validator.w3.org/check/referer"><img
+ src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
+
+ <a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
+ Last modified: $Date: 2011-08-09 02:07:00 -0700 (Tue, 09 Aug 2011) $
+</address>
+
+</body>
+</html>
diff --git a/docs/Bugpoint.html b/docs/Bugpoint.html
index 05c867b..bc78933 100644
--- a/docs/Bugpoint.html
+++ b/docs/Bugpoint.html
@@ -216,18 +216,6 @@ non-obvious ways. Here are some hints and tips:<p>
the list of specified optimizations to be randomized and applied to the
program. This process will repeat until a bug is found or the user
kills <tt>bugpoint</tt>.
-
-<li><p><tt>bugpoint</tt> does not understand the <tt>-O</tt> option
- that is used to specify optimization level to <tt>opt</tt>. You
- can use e.g.</p>
-
-<div class="doc_code">
-<p><tt>opt -O2 -debug-pass=Arguments foo.bc -disable-output</tt></p>
-</div>
-
- <p>to get a list of passes that are used with <tt>-O2</tt> and
- then pass this list to <tt>bugpoint</tt>.</p>
-
</ol>
</div>
@@ -243,7 +231,7 @@ non-obvious ways. Here are some hints and tips:<p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-08-30 20:26:11 +0200 (Tue, 30 Aug 2011) $
</address>
</body>
diff --git a/docs/CMake.html b/docs/CMake.html
index 0d8cf62..6389c7f 100644
--- a/docs/CMake.html
+++ b/docs/CMake.html
@@ -340,7 +340,7 @@
on Visual C++ and Xcode,
<tt>&quot;-sv&quot;</tt> on others.</dd>
- <dt><b>LLVM_LIT_TOOLS_DIR</b>:STRING</dt>
+ <dt><b>LLVM_LIT_TOOLS_DIR</b>:PATH</dt>
<dd>The path to GnuWin32 tools for tests. Valid on Windows host.
Defaults to "", then Lit seeks tools according to %PATH%.
Lit can find tools(eg. grep, sort, &amp;c) on LLVM_LIT_TOOLS_DIR at first,
@@ -423,8 +423,9 @@
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${LLVM_ROOT}/share/llvm/cmake")
include(LLVMConfig)
<b># Now set the header and library paths:</b>
- include_directories( ${LLVM_ROOT}/include )
- link_directories( ${LLVM_ROOT}/lib )
+ include_directories( ${LLVM_INCLUDE_DIRS} )
+ link_directories( ${LLVM_LIBRARY_DIRS} )
+ add_definitions( ${LLVM_DEFINITIONS} )
<b># Let's suppose we want to build a JIT compiler with support for
# binary code (no interpreter):</b>
llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native)
diff --git a/docs/CodeGenerator.html b/docs/CodeGenerator.html
index 29a2cce..e693a22 100644
--- a/docs/CodeGenerator.html
+++ b/docs/CodeGenerator.html
@@ -114,6 +114,7 @@
<li><a href="#ppc_prolog">Prolog/Epilog</a></li>
<li><a href="#ppc_dynamic">Dynamic Allocation</a></li>
</ul></li>
+ <li><a href="#ptx">The PTX backend</a></li>
</ul></li>
</ol>
@@ -1768,22 +1769,28 @@ bool RegMapping_Fer::compatible_class(MachineFunction &amp;mf,
different register allocators:</p>
<ul>
- <li><i>Linear Scan</i> &mdash; <i>The default allocator</i>. This is the
- well-know linear scan register allocator. Whereas the
- <i>Simple</i> and <i>Local</i> algorithms use a direct mapping
- implementation technique, the <i>Linear Scan</i> implementation
- uses a spiller in order to place load and stores.</li>
-
<li><i>Fast</i> &mdash; This register allocator is the default for debug
builds. It allocates registers on a basic block level, attempting to keep
values in registers and reusing registers as appropriate.</li>
+ <li><i>Basic</i> &mdash; This is an incremental approach to register
+ allocation. Live ranges are assigned to registers one at a time in
+ an order that is driven by heuristics. Since code can be rewritten
+ on-the-fly during allocation, this framework allows interesting
+ allocators to be developed as extensions. It is not itself a
+ production register allocator but is a potentially useful
+ stand-alone mode for triaging bugs and as a performance baseline.
+
+ <li><i>Greedy</i> &mdash; <i>The default allocator</i>. This is a
+ highly tuned implementation of the <i>Basic</i> allocator that
+ incorporates global live range splitting. This allocator works hard
+ to minimize the cost of spill code.
+
<li><i>PBQP</i> &mdash; A Partitioned Boolean Quadratic Programming (PBQP)
based register allocator. This allocator works by constructing a PBQP
problem representing the register allocation problem under consideration,
solving this using a PBQP solver, and mapping the solution back to a
register assignment.</li>
-
</ul>
<p>The type of register allocator used in <tt>llc</tt> can be chosen with the
@@ -1805,7 +1812,121 @@ $ llc -regalloc=pbqp file.bc -o pbqp.s;
<h3>
<a name="proepicode">Prolog/Epilog Code Insertion</a>
</h3>
-<div><p>To Be Written</p></div>
+
+<!-- _______________________________________________________________________ -->
+<h4>
+ <a name="compact_unwind">Compact Unwind</a>
+</h4>
+
+<div>
+
+<p>Throwing an exception requires <em>unwinding</em> out of a function. The
+ information on how to unwind a given function is traditionally expressed in
+ DWARF unwind (a.k.a. frame) info. But that format was originally developed
+ for debuggers to backtrace, and each Frame Description Entry (FDE) requires
+ ~20-30 bytes per function. There is also the cost of mapping from an address
+ in a function to the corresponding FDE at runtime. An alternative unwind
+ encoding is called <em>compact unwind</em> and requires just 4-bytes per
+ function.</p>
+
+<p>The compact unwind encoding is a 32-bit value, which is encoded in an
+ architecture-specific way. It specifies which registers to restore and from
+ where, and how to unwind out of the function. When the linker creates a final
+ linked image, it will create a <code>__TEXT,__unwind_info</code>
+ section. This section is a small and fast way for the runtime to access
+ unwind info for any given function. If we emit compact unwind info for the
+ function, that compact unwind info will be encoded in
+ the <code>__TEXT,__unwind_info</code> section. If we emit DWARF unwind info,
+ the <code>__TEXT,__unwind_info</code> section will contain the offset of the
+ FDE in the <code>__TEXT,__eh_frame</code> section in the final linked
+ image.</p>
+
+<p>For X86, there are three modes for the compact unwind encoding:</p>
+
+<dl>
+ <dt><i>Function with a Frame Pointer (<code>EBP</code> or <code>RBP</code>)</i></dt>
+ <dd><p><code>EBP/RBP</code>-based frame, where <code>EBP/RBP</code> is pushed
+ onto the stack immediately after the return address,
+ then <code>ESP/RSP</code> is moved to <code>EBP/RBP</code>. Thus to
+ unwind, <code>ESP/RSP</code> is restored with the
+ current <code>EBP/RBP</code> value, then <code>EBP/RBP</code> is restored
+ by popping the stack, and the return is done by popping the stack once
+ more into the PC. All non-volatile registers that need to be restored must
+ have been saved in a small range on the stack that
+ starts <code>EBP-4</code> to <code>EBP-1020</code> (<code>RBP-8</code>
+ to <code>RBP-1020</code>). The offset (divided by 4 in 32-bit mode and 8
+ in 64-bit mode) is encoded in bits 16-23 (mask: <code>0x00FF0000</code>).
+ The registers saved are encoded in bits 0-14
+ (mask: <code>0x00007FFF</code>) as five 3-bit entries from the following
+ table:</p>
+<table border="1" cellspacing="0">
+ <tr>
+ <th>Compact Number</th>
+ <th>i386 Register</th>
+ <th>x86-64 Regiser</th>
+ </tr>
+ <tr>
+ <td>1</td>
+ <td><code>EBX</code></td>
+ <td><code>RBX</code></td>
+ </tr>
+ <tr>
+ <td>2</td>
+ <td><code>ECX</code></td>
+ <td><code>R12</code></td>
+ </tr>
+ <tr>
+ <td>3</td>
+ <td><code>EDX</code></td>
+ <td><code>R13</code></td>
+ </tr>
+ <tr>
+ <td>4</td>
+ <td><code>EDI</code></td>
+ <td><code>R14</code></td>
+ </tr>
+ <tr>
+ <td>5</td>
+ <td><code>ESI</code></td>
+ <td><code>R15</code></td>
+ </tr>
+ <tr>
+ <td>6</td>
+ <td><code>EBP</code></td>
+ <td><code>RBP</code></td>
+ </tr>
+</table>
+
+</dd>
+
+ <dt><i>Frameless with a Small Constant Stack Size (<code>EBP</code>
+ or <code>RBP</code> is not used as a frame pointer)</i></dt>
+ <dd><p>To return, a constant (encoded in the compact unwind encoding) is added
+ to the <code>ESP/RSP</code>. Then the return is done by popping the stack
+ into the PC. All non-volatile registers that need to be restored must have
+ been saved on the stack immediately after the return address. The stack
+ size (divided by 4 in 32-bit mode and 8 in 64-bit mode) is encoded in bits
+ 16-23 (mask: <code>0x00FF0000</code>). There is a maximum stack size of
+ 1024 bytes in 32-bit mode and 2048 in 64-bit mode. The number of registers
+ saved is encoded in bits 9-12 (mask: <code>0x00001C00</code>). Bits 0-9
+ (mask: <code>0x000003FF</code>) contain which registers were saved and
+ their order. (See
+ the <code>encodeCompactUnwindRegistersWithoutFrame()</code> function
+ in <code>lib/Target/X86FrameLowering.cpp</code> for the encoding
+ algorithm.)</p></dd>
+
+ <dt><i>Frameless with a Large Constant Stack Size (<code>EBP</code>
+ or <code>RBP</code> is not used as a frame pointer)</i></dt>
+ <dd><p>This case is like the "Frameless with a Small Constant Stack Size"
+ case, but the stack size is too large to encode in the compact unwind
+ encoding. Instead it requires that the function contains "<code>subl
+ $nnnnnn, %esp</code>" in its prolog. The compact encoding contains the
+ offset to the <code>$nnnnnn</code> value in the function in bits 9-12
+ (mask: <code>0x00001C00</code>).</p></dd>
+</dl>
+
+</div>
+
<!-- ======================================================================= -->
<h3>
<a name="latemco">Late Machine Code Optimizations</a>
@@ -2165,7 +2286,7 @@ is the key:</p>
<td class="yes"></td> <!-- PowerPC -->
<td class="unknown"></td> <!-- Sparc -->
<td class="unknown"></td> <!-- SystemZ -->
- <td class="yes"><a href="#feat_inlineasm_x86">*</a></td> <!-- X86 -->
+ <td class="yes"></td> <!-- X86 -->
<td class="unknown"></td> <!-- XCore -->
</tr>
@@ -2261,9 +2382,6 @@ disassembling machine opcode bytes into MCInst's.</p>
<p>This box indicates whether the target supports most popular inline assembly
constraints and modifiers.</p>
-<p id="feat_inlineasm_x86">X86 lacks reliable support for inline assembly
-constraints relating to the X86 floating point stack.</p>
-
</div>
<!-- _______________________________________________________________________ -->
@@ -2794,6 +2912,70 @@ MOVSX32rm16 -&gt; movsx, 32-bit register, 16-bit memory
</div>
+<!-- ======================================================================= -->
+<h3>
+ <a name="ptx">The PTX backend</a>
+</h3>
+
+<div>
+
+<p>The PTX code generator lives in the lib/Target/PTX directory. It is
+ currently a work-in-progress, but already supports most of the code
+ generation functionality needed to generate correct PTX kernels for
+ CUDA devices.</p>
+
+<p>The code generator can target PTX 2.0+, and shader model 1.0+. The
+ PTX ISA Reference Manual is used as the primary source of ISA
+ information, though an effort is made to make the output of the code
+ generator match the output of the NVidia nvcc compiler, whenever
+ possible.</p>
+
+<p>Code Generator Options:</p>
+<table border="1" cellspacing="0">
+ <tr>
+ <th>Option</th>
+ <th>Description</th>
+ </tr>
+ <tr>
+ <td><code>double</code></td>
+ <td align="left">If enabled, the map_f64_to_f32 directive is
+ disabled in the PTX output, allowing native double-precision
+ arithmetic</td>
+ </tr>
+ <tr>
+ <td><code>no-fma</code></td>
+ <td align="left">Disable generation of Fused-Multiply Add
+ instructions, which may be beneficial for some devices</td>
+ </tr>
+ <tr>
+ <td><code>smxy / computexy</code></td>
+ <td align="left">Set shader model/compute capability to x.y,
+ e.g. sm20 or compute13</td>
+ </tr>
+</table>
+
+<p>Working:</p>
+<ul>
+ <li>Arithmetic instruction selection (including combo FMA)</li>
+ <li>Bitwise instruction selection</li>
+ <li>Control-flow instruction selection</li>
+ <li>Function calls (only on SM 2.0+ and no return arguments)</li>
+ <li>Addresses spaces (0 = global, 1 = constant, 2 = local, 4 =
+ shared)</li>
+ <li>Thread synchronization (bar.sync)</li>
+ <li>Special register reads ([N]TID, [N]CTAID, PMx, CLOCK, etc.)</li>
+</ul>
+
+<p>In Progress:</p>
+<ul>
+ <li>Robust call instruction selection</li>
+ <li>Stack frame allocation</li>
+ <li>Device-specific instruction scheduling optimizations</li>
+</ul>
+
+
+</div>
+
</div>
<!-- *********************************************************************** -->
@@ -2806,7 +2988,7 @@ MOVSX32rm16 -&gt; movsx, 32-bit register, 16-bit memory
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-05-23 00:28:47 +0200 (Mon, 23 May 2011) $
+ Last modified: $Date: 2011-09-19 20:15:46 +0200 (Mon, 19 Sep 2011) $
</address>
</body>
diff --git a/docs/CodingStandards.html b/docs/CodingStandards.html
index 139bbdb..3153a6e 100644
--- a/docs/CodingStandards.html
+++ b/docs/CodingStandards.html
@@ -854,8 +854,12 @@ rules:</p>
<ul>
<li><p><b>Type names</b> (including classes, structs, enums, typedefs, etc)
- should be nouns and start with an upper-case letter (e.g.
- <tt>TextFileReader</tt>).</p></li>
+ should be nouns and start with an upper-case letter (e.g.
+ <tt>TextFileReader</tt>).</p></li>
+
+<li><p><b>Variable names</b> should be nouns (as they represent state). The
+ name should be camel case, and start with an upper case letter (e.g.
+ <tt>Leader</tt> or <tt>Boats</tt>).</p></li>
<li><p><b>Function names</b> should be verb phrases (as they represent
actions), and command-like function should be imperative. The name should
@@ -1522,7 +1526,7 @@ something.</p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-08-12 21:49:16 +0200 (Fri, 12 Aug 2011) $
</address>
</body>
diff --git a/docs/CommandGuide/index.html b/docs/CommandGuide/index.html
index cb5438f..3e4e220 100644
--- a/docs/CommandGuide/index.html
+++ b/docs/CommandGuide/index.html
@@ -69,9 +69,6 @@ options) arguments to the tool you are interested in.</p>
<li><a href="/cmds/llvm-config.html"><b>llvm-config</b></a> -
print out LLVM compilation options, libraries, etc. as configured</li>
-<li><a href="/cmds/llvmc.html"><b>llvmc</b></a> -
- a generic customizable compiler driver</li>
-
<li><a href="/cmds/llvm-diff.html"><b>llvm-diff</b></a> -
structurally compare two modules</li>
@@ -81,25 +78,6 @@ options) arguments to the tool you are interested in.</p>
<!-- *********************************************************************** -->
<h2>
- <a name="frontend">C and C++ Front-end Commands</a>
-</h2>
-<!-- *********************************************************************** -->
-
-<div>
-<ul>
-
-<li><a href="/cmds/llvmgcc.html"><b>llvm-gcc</b></a> -
- GCC-based C front-end for LLVM
-
-<li><a href="/cmds/llvmgxx.html"><b>llvm-g++</b></a> -
- GCC-based C++ front-end for LLVM</li>
-
-</ul>
-
-</div>
-
-<!-- *********************************************************************** -->
-<h2>
<a name="debug">Debugging Tools</a>
</h2>
<!-- *********************************************************************** -->
@@ -151,7 +129,7 @@ options) arguments to the tool you are interested in.</p>
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-09-20 20:24:04 +0200 (Tue, 20 Sep 2011) $
</address>
</body>
diff --git a/docs/CommandGuide/llvm-extract.pod b/docs/CommandGuide/llvm-extract.pod
index 797e79d..67f00f0 100644
--- a/docs/CommandGuide/llvm-extract.pod
+++ b/docs/CommandGuide/llvm-extract.pod
@@ -37,11 +37,23 @@ B<llvm-extract> will write raw bitcode regardless of the output device.
Extract the function named I<function-name> from the LLVM bitcode. May be
specified multiple times to extract multiple functions at once.
+=item B<--rfunc> I<function-regular-expr>
+
+Extract the function(s) matching I<function-regular-expr> from the LLVM bitcode.
+All functions matching the regular expression will be extracted. May be
+specified multiple times.
+
=item B<--glob> I<global-name>
Extract the global variable named I<global-name> from the LLVM bitcode. May be
specified multiple times to extract multiple global variables at once.
+=item B<--rglob> I<glob-regular-expr>
+
+Extract the global variable(s) matching I<global-regular-expr> from the LLVM
+bitcode. All global variables matching the regular expression will be extracted.
+May be specified multiple times.
+
=item B<-help>
Print a summary of command line options.
diff --git a/docs/CommandGuide/llvmc.pod b/docs/CommandGuide/llvmc.pod
deleted file mode 100644
index 95a9e5e..0000000
--- a/docs/CommandGuide/llvmc.pod
+++ /dev/null
@@ -1,190 +0,0 @@
-=pod
-
-=head1 NAME
-
-llvmc - The LLVM Compiler Driver (WIP)
-
-=head1 SYNOPSIS
-
-B<llvmc> [I<options>] I<filenames...>
-
-=head1 DESCRIPTION
-
-B<llvmc> is a configurable driver for invoking other LLVM (and non-LLVM) tools
-in order to compile, optimize and link software for multiple languages. For
-those familiar with FSF's B<gcc> tool, it is very similar. Please note that
-B<llvmc> is considered an experimental tool.
-
-=head1 OPTIONS
-
-=head2 Built-in Options
-
-LLVMC has some built-in options that can't be overridden in the
-configuration libraries.
-
-=over
-
-=item B<-o> I<filename>
-
-Output file name.
-
-=item B<-x> I<language>
-
-Specify the language of the following input files until the next B<-x>
-option.
-
-=item B<-load> I<plugin_name>
-
-Load the specified plugin DLL. Example:
-S<-load $LLVM_DIR/Release/lib/LLVMCSimple.so>.
-
-=item B<-v> or B<--verbose>
-
-Enable verbose mode, i.e. print out all executed commands.
-
-=item B<--check-graph>
-
-Check the compilation for common errors like mismatched output/input language
-names, multiple default edges and cycles. Because of plugins, these checks can't
-be performed at compile-time. Exit with code zero if no errors were found, and
-return the number of found errors otherwise. Hidden option, useful for debugging
-LLVMC plugins.
-
-=item B<--view-graph>
-
-Show a graphical representation of the compilation graph and exit. Requires that
-you have I<dot> and I<gv> programs installed. Hidden option, useful for
-debugging LLVMC plugins.
-
-=item B<--write-graph>
-
-Write a I<compilation-graph.dot> file in the current directory with the
-compilation graph description in Graphviz format (identical to the file used by
-the B<--view-graph> option). The B<-o> option can be used to set the output file
-name. Hidden option, useful for debugging LLVMC plugins.
-
-=item B<--save-temps>
-
-Write temporary files to the current directory and do not delete them on
-exit. This option can also take an argument: the I<--save-temps=obj> switch will
-write files into the directory specified with the I<-o> option. The
-I<--save-temps=cwd> and I<--save-temps> switches are both synonyms for the
-default behaviour.
-
-=item B<--temp-dir> I<directory>
-
-Store temporary files in the given directory. This directory is deleted on exit
-unless I<--save-temps> is specified. If I<--save-temps=obj> is also specified,
-I<--temp-dir> is given the precedence.
-
-=item B<-help>
-
-Print a summary of command-line options and exit.
-
-=item B<-help-hidden>
-
-Print a summary of command-line options and exit. Print help even for
-options intended for developers.
-
-=item B<--version>
-
-Print version information and exit.
-
-=item B<@>I<file>
-
-Read command-line options from I<file>. The options read are inserted
-in place of the original @I<file> option. If I<file> does not exist, or
-cannot be read, then the option will be treated literally, and not
-removed.
-
-Options in I<file> are separated by whitespace. A whitespace character
-may be included in an option by surrounding the entire option in
-either single or double quotes. Any character (including a backslash)
-may be included by prefixing the character to be included with a
-backslash. The file may itself contain additional @I<file> options;
-any such options will be processed recursively.
-
-
-=back
-
-
-=head2 Control Options
-
-By default, LLVMC is built with some standard configuration libraries
-that define the following options:
-
-=over
-
-=item B<-clang>
-
-Use Clang instead of llvm-gcc.
-
-=item B<-opt>
-
-Enable optimization passes with B<opt>. To pass options to the B<opt> program
-use the B<-Wo,> option.
-
-=item B<-I> I<directory>
-
-Add a directory to the header file search path.
-
-=item B<-L> I<directory>
-
-Add I<directory> to the library search path.
-
-=item B<-F> I<directory>
-
-Add I<directory> to the framework search path.
-
-=item B<-l>I<name>
-
-Link in the library libI<name>.[bc | a | so]. This library should
-be a bitcode library.
-
-=item B<-framework> I<name>
-
-Link in the library libI<name>.[bc | a | so]. This library should
-be a bitcode library.
-
-=item B<-emit-llvm>
-
-Output LLVM bitcode (with B<-c>) or assembly (with B<-S>) instead of native
-object (or assembly). If B<-emit-llvm> is given without either B<-c> or B<-S>
-it has no effect.
-
-=item B<-Wa>
-
-Pass options to assembler.
-
-=item B<-Wl>
-
-Pass options to linker.
-
-=item B<-Wo>
-
-Pass options to opt.
-
-=item B<-Wllc>
-
-Pass options to llc (code generator).
-
-=back
-
-=head1 EXIT STATUS
-
-If B<llvmc> succeeds, it will exit with code 0. Otherwise, if an
-error occurs, it will exit with a non-zero value. If one of the
-compilation tools returns a non-zero status, pending actions will be
-discarded and B<llvmc> will return the same result code as the failing
-compilation tool.
-
-=head1 SEE ALSO
-
-L<llvm-gcc|llvmgcc>, L<llvm-g++|llvmgxx>, L<llvm-as|llvm-as>,
-L<llvm-dis|llvm-dis>, L<llc|llc>, L<llvm-link|llvm-link>
-
-=head1 AUTHORS
-
-Maintained by the LLVM Team (L<http://llvm.org/>).
-
-=cut
diff --git a/docs/CommandGuide/llvmgcc.pod b/docs/CommandGuide/llvmgcc.pod
deleted file mode 100644
index 30af0a06e..0000000
--- a/docs/CommandGuide/llvmgcc.pod
+++ /dev/null
@@ -1,76 +0,0 @@
-=pod
-
-=head1 NAME
-
-llvm-gcc - LLVM C front-end
-
-=head1 SYNOPSIS
-
-B<llvm-gcc> [I<options>] I<filename>
-
-=head1 DESCRIPTION
-
-The B<llvm-gcc> command is the LLVM C front end. It is a modified
-version of gcc that compiles C/ObjC programs into native objects, LLVM
-bitcode or LLVM assembly language, depending upon the options.
-
-By default, B<llvm-gcc> compiles to native objects just like GCC does. If the
-B<-emit-llvm> and B<-c> options are given then it will generate LLVM bitcode files
-instead. If B<-emit-llvm> and B<-S> are given, then it will generate LLVM
-assembly.
-
-Being derived from the GNU Compiler Collection, B<llvm-gcc> has many
-of gcc's features and accepts most of gcc's options. It handles a
-number of gcc's extensions to the C programming language. See the gcc
-documentation for details.
-
-=head1 OPTIONS
-
-=over
-
-=item B<--help>
-
-Print a summary of command line options.
-
-=item B<-o> I<filename>
-
-Specify the output file to be I<filename>.
-
-=item B<-I> I<directory>
-
-Add a directory to the header file search path. This option can be
-repeated.
-
-=item B<-L> I<directory>
-
-Add I<directory> to the library search path. This option can be
-repeated.
-
-=item B<-l>I<name>
-
-Link in the library libI<name>.[bc | a | so]. This library should
-be a bitcode library.
-
-=item B<-emit-llvm>
-
-Make the output be LLVM bitcode (with B<-c>) or assembly (with B<-s>) instead
-of native object (or assembly). If B<-emit-llvm> is given without either B<-c>
-or B<-S> it has no effect.
-
-=back
-
-=head1 EXIT STATUS
-
-If B<llvm-gcc> succeeds, it will exit with 0. Otherwise, if an error
-occurs, it will exit with a non-zero value.
-
-=head1 SEE ALSO
-
-L<llvm-g++|llvmgxx>
-
-=head1 AUTHORS
-
-Maintained by the LLVM Team (L<http://llvm.org/>).
-
-=cut
-
diff --git a/docs/CommandGuide/llvmgxx.pod b/docs/CommandGuide/llvmgxx.pod
deleted file mode 100644
index 1ea3d49..0000000
--- a/docs/CommandGuide/llvmgxx.pod
+++ /dev/null
@@ -1,85 +0,0 @@
-=pod
-
-=head1 NAME
-
-llvm-g++ - LLVM C++ front-end
-
-=head1 SYNOPSIS
-
-B<llvm-g++> [I<options>] I<filename>
-
-=head1 DESCRIPTION
-
-The B<llvm-g++> command is the LLVM C++ front end. It is a modified
-version of g++ that compiles C++/ObjC++ programs into native code,
-LLVM bitcode or assembly language, depending upon the options.
-
-By default, B<llvm-g++> compiles to native objects just like GCC does. If the
-B<-emit-llvm> option is given then it will generate LLVM bitcode files instead.
-If B<-S> (assembly) is also given, then it will generate LLVM assembly.
-
-Being derived from the GNU Compiler Collection, B<llvm-g++> has many
-of g++'s features and accepts most of g++'s options. It handles a
-number of g++'s extensions to the C++ programming language.
-
-=head1 OPTIONS
-
-=over
-
-=item B<--help>
-
-Print a summary of command line options.
-
-=item B<-S>
-
-Do not generate an LLVM bitcode file. Rather, compile the source
-file into an LLVM assembly language file.
-
-=item B<-c>
-
-Do not generate a linked executable. Rather, compile the source
-file into an LLVM bitcode file. This bitcode file can then be
-linked with other bitcode files later on to generate a full LLVM
-executable.
-
-=item B<-o> I<filename>
-
-Specify the output file to be I<filename>.
-
-=item B<-I> I<directory>
-
-Add a directory to the header file search path. This option can be
-repeated.
-
-=item B<-L> I<directory>
-
-Add I<directory> to the library search path. This option can be
-repeated.
-
-=item B<-l>I<name>
-
-Link in the library libI<name>.[bc | a | so]. This library should
-be a bitcode library.
-
-=item B<-emit-llvm>
-
-Make the output be LLVM bitcode (or assembly) instead of native object (or
-assembly).
-
-=back
-
-=head1 EXIT STATUS
-
-If B<llvm-g++> succeeds, it will exit with 0. Otherwise, if an error
-occurs, it will exit with a non-zero value.
-
-=head1 SEE ALSO
-
-L<llvm-gcc|llvmgcc>
-
-=head1 AUTHORS
-
-Maintained by the LLVM Team (L<http://llvm.org/>).
-
-=cut
-
diff --git a/docs/CompilerDriver.html b/docs/CompilerDriver.html
deleted file mode 100644
index 1b2f808..0000000
--- a/docs/CompilerDriver.html
+++ /dev/null
@@ -1,687 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
-<title>Customizing LLVMC: Reference Manual</title>
-<link rel="stylesheet" href="llvm.css" type="text/css" />
-</head>
-<body>
-<div class="document" id="customizing-llvmc-reference-manual">
-<h1 class="title">Customizing LLVMC: Reference Manual</h1>
-
-<!-- This file was automatically generated by rst2html.
-Please do not edit directly!
-The ReST source lives in the directory 'tools/llvmc/doc'. -->
-<div class="contents topic" id="contents">
-<p class="topic-title first">Contents</p>
-<ul class="simple">
-<li><a class="reference internal" href="#introduction" id="id7">Introduction</a></li>
-<li><a class="reference internal" href="#compiling-with-llvmc" id="id8">Compiling with <tt class="docutils literal">llvmc</tt></a></li>
-<li><a class="reference internal" href="#predefined-options" id="id9">Predefined options</a></li>
-<li><a class="reference internal" href="#compiling-llvmc-based-drivers" id="id10">Compiling LLVMC-based drivers</a></li>
-<li><a class="reference internal" href="#customizing-llvmc-the-compilation-graph" id="id11">Customizing LLVMC: the compilation graph</a></li>
-<li><a class="reference internal" href="#describing-options" id="id12">Describing options</a></li>
-<li><a class="reference internal" href="#conditional-evaluation" id="id13">Conditional evaluation</a></li>
-<li><a class="reference internal" href="#writing-a-tool-description" id="id14">Writing a tool description</a><ul>
-<li><a class="reference internal" href="#id4" id="id15">Actions</a></li>
-</ul>
-</li>
-<li><a class="reference internal" href="#language-map" id="id16">Language map</a></li>
-<li><a class="reference internal" href="#option-preprocessor" id="id17">Option preprocessor</a></li>
-<li><a class="reference internal" href="#more-advanced-topics" id="id18">More advanced topics</a><ul>
-<li><a class="reference internal" href="#hooks-and-environment-variables" id="id19">Hooks and environment variables</a></li>
-<li><a class="reference internal" href="#debugging" id="id20">Debugging</a></li>
-<li><a class="reference internal" href="#conditioning-on-the-executable-name" id="id21">Conditioning on the executable name</a></li>
-</ul>
-</li>
-</ul>
-</div>
-<div class="doc_author">
-<p>Written by <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a></p>
-</div><div class="section" id="introduction">
-<h1><a class="toc-backref" href="#id7">Introduction</a></h1>
-<p>LLVMC is a generic compiler driver, designed to be customizable and
-extensible. It plays the same role for LLVM as the <tt class="docutils literal">gcc</tt> program does for
-GCC - LLVMC's job is essentially to transform a set of input files into a set of
-targets depending on configuration rules and user options. What makes LLVMC
-different is that these transformation rules are completely customizable - in
-fact, LLVMC knows nothing about the specifics of transformation (even the
-command-line options are mostly not hard-coded) and regards the transformation
-structure as an abstract graph. The structure of this graph is described in
-high-level TableGen code, from which an efficient C++ representation is
-automatically derived. This makes it possible to adapt LLVMC for other
-purposes - for example, as a build tool for game resources.</p>
-<p>Because LLVMC employs <a class="reference external" href="http://llvm.org/docs/TableGenFundamentals.html">TableGen</a> as its configuration language, you
-need to be familiar with it to customize LLVMC.</p>
-</div>
-<div class="section" id="compiling-with-llvmc">
-<h1><a class="toc-backref" href="#id8">Compiling with <tt class="docutils literal">llvmc</tt></a></h1>
-<p>LLVMC tries hard to be as compatible with <tt class="docutils literal">gcc</tt> as possible,
-although there are some small differences. Most of the time, however,
-you shouldn't be able to notice them:</p>
-<pre class="literal-block">
-$ # This works as expected:
-$ llvmc -O3 -Wall hello.cpp
-$ ./a.out
-hello
-</pre>
-<p>One nice feature of LLVMC is that one doesn't have to distinguish between
-different compilers for different languages (think <tt class="docutils literal">g++</tt> vs. <tt class="docutils literal">gcc</tt>) - the
-right toolchain is chosen automatically based on input language names (which
-are, in turn, determined from file extensions). If you want to force files
-ending with &quot;.c&quot; to compile as C++, use the <tt class="docutils literal"><span class="pre">-x</span></tt> option, just like you would
-do it with <tt class="docutils literal">gcc</tt>:</p>
-<pre class="literal-block">
-$ # hello.c is really a C++ file
-$ llvmc -x c++ hello.c
-$ ./a.out
-hello
-</pre>
-<p>On the other hand, when using LLVMC as a linker to combine several C++
-object files you should provide the <tt class="docutils literal"><span class="pre">--linker</span></tt> option since it's
-impossible for LLVMC to choose the right linker in that case:</p>
-<pre class="literal-block">
-$ llvmc -c hello.cpp
-$ llvmc hello.o
-[A lot of link-time errors skipped]
-$ llvmc --linker=c++ hello.o
-$ ./a.out
-hello
-</pre>
-<p>By default, LLVMC uses <tt class="docutils literal"><span class="pre">llvm-gcc</span></tt> to compile the source code. It is also
-possible to choose the <tt class="docutils literal">clang</tt> compiler with the <tt class="docutils literal"><span class="pre">-clang</span></tt> option.</p>
-</div>
-<div class="section" id="predefined-options">
-<h1><a class="toc-backref" href="#id9">Predefined options</a></h1>
-<p>LLVMC has some built-in options that can't be overridden in the TableGen code:</p>
-<ul class="simple">
-<li><tt class="docutils literal"><span class="pre">-o</span> FILE</tt> - Output file name.</li>
-<li><tt class="docutils literal"><span class="pre">-x</span> LANGUAGE</tt> - Specify the language of the following input files
-until the next -x option.</li>
-<li><tt class="docutils literal"><span class="pre">-v</span></tt> - Enable verbose mode, i.e. print out all executed commands.</li>
-<li><tt class="docutils literal"><span class="pre">--save-temps</span></tt> - Write temporary files to the current directory and do not
-delete them on exit. This option can also take an argument: the
-<tt class="docutils literal"><span class="pre">--save-temps=obj</span></tt> switch will write files into the directory specified with
-the <tt class="docutils literal"><span class="pre">-o</span></tt> option. The <tt class="docutils literal"><span class="pre">--save-temps=cwd</span></tt> and <tt class="docutils literal"><span class="pre">--save-temps</span></tt> switches are
-both synonyms for the default behaviour.</li>
-<li><tt class="docutils literal"><span class="pre">--temp-dir</span> DIRECTORY</tt> - Store temporary files in the given directory. This
-directory is deleted on exit unless <tt class="docutils literal"><span class="pre">--save-temps</span></tt> is specified. If
-<tt class="docutils literal"><span class="pre">--save-temps=obj</span></tt> is also specified, <tt class="docutils literal"><span class="pre">--temp-dir</span></tt> is given the
-precedence.</li>
-<li><tt class="docutils literal"><span class="pre">--check-graph</span></tt> - Check the compilation for common errors like mismatched
-output/input language names, multiple default edges and cycles. Exit with code
-zero if no errors were found, and return the number of found errors
-otherwise. Hidden option, useful for debugging.</li>
-<li><tt class="docutils literal"><span class="pre">--view-graph</span></tt> - Show a graphical representation of the compilation graph
-and exit. Requires that you have <tt class="docutils literal">dot</tt> and <tt class="docutils literal">gv</tt> programs installed. Hidden
-option, useful for debugging.</li>
-<li><tt class="docutils literal"><span class="pre">--write-graph</span></tt> - Write a <tt class="docutils literal"><span class="pre">compilation-graph.dot</span></tt> file in the current
-directory with the compilation graph description in Graphviz format (identical
-to the file used by the <tt class="docutils literal"><span class="pre">--view-graph</span></tt> option). The <tt class="docutils literal"><span class="pre">-o</span></tt> option can be
-used to set the output file name. Hidden option, useful for debugging.</li>
-<li><tt class="docutils literal"><span class="pre">--help</span></tt>, <tt class="docutils literal"><span class="pre">--help-hidden</span></tt>, <tt class="docutils literal"><span class="pre">--version</span></tt> - These options have
-their standard meaning.</li>
-</ul>
-</div>
-<div class="section" id="compiling-llvmc-based-drivers">
-<h1><a class="toc-backref" href="#id10">Compiling LLVMC-based drivers</a></h1>
-<p>It's easiest to start working on your own LLVMC driver by copying the skeleton
-project which lives under <tt class="docutils literal">$LLVMC_DIR/examples/Skeleton</tt>:</p>
-<pre class="literal-block">
-$ cd $LLVMC_DIR/examples
-$ cp -r Skeleton MyDriver
-$ cd MyDriver
-$ ls
-AutoGenerated.td Hooks.cpp Main.cpp Makefile
-</pre>
-<p>As you can see, our basic driver consists of only three files (not counting the
-build script). <tt class="docutils literal">AutoGenerated.td</tt> contains TableGen description of the
-compilation graph; its format is documented in the following
-sections. <tt class="docutils literal">Hooks.cpp</tt> is an empty file that should be used for hook
-definitions (see <a class="reference internal" href="#hooks">below</a>). <tt class="docutils literal">Main.cpp</tt> is just a helper used to compile the
-auto-generated C++ code produced from TableGen source.</p>
-<p>The first thing that you should do is to change the <tt class="docutils literal">LLVMC_BASED_DRIVER</tt>
-variable in the <tt class="docutils literal">Makefile</tt>:</p>
-<pre class="literal-block">
-LLVMC_BASED_DRIVER=MyDriver
-</pre>
-<p>It can also be a good idea to put your TableGen code into a file with a less
-generic name:</p>
-<pre class="literal-block">
-$ touch MyDriver.td
-$ vim AutoGenerated.td
-[...]
-include &quot;MyDriver.td&quot;
-</pre>
-<p>If you have more than one TableGen source file, they all should be included from
-<tt class="docutils literal">AutoGenerated.td</tt>, since this file is used by the build system to generate
-C++ code.</p>
-<p>To build your driver, just <tt class="docutils literal">cd</tt> to its source directory and run <tt class="docutils literal">make</tt>. The
-resulting executable will be put into <tt class="docutils literal"><span class="pre">$LLVM_OBJ_DIR/$(BuildMode)/bin</span></tt>.</p>
-<p>If you're compiling LLVM with different source and object directories, then you
-must perform the following additional steps before running <tt class="docutils literal">make</tt>:</p>
-<pre class="literal-block">
-# LLVMC_SRC_DIR = $LLVM_SRC_DIR/tools/llvmc/
-# LLVMC_OBJ_DIR = $LLVM_OBJ_DIR/tools/llvmc/
-$ mkdir $LLVMC_OBJ_DIR/examples/MyDriver/
-$ cp $LLVMC_SRC_DIR/examples/MyDriver/Makefile \
- $LLVMC_OBJ_DIR/examples/MyDriver/
-$ cd $LLVMC_OBJ_DIR/examples/MyDriver
-$ make
-</pre>
-</div>
-<div class="section" id="customizing-llvmc-the-compilation-graph">
-<h1><a class="toc-backref" href="#id11">Customizing LLVMC: the compilation graph</a></h1>
-<p>Each TableGen configuration file should include the common definitions:</p>
-<pre class="literal-block">
-include &quot;llvm/CompilerDriver/Common.td&quot;
-</pre>
-<p>Internally, LLVMC stores information about possible source transformations in
-form of a graph. Nodes in this graph represent tools, and edges between two
-nodes represent a transformation path. A special &quot;root&quot; node is used to mark
-entry points for the transformations. LLVMC also assigns a weight to each edge
-(more on this later) to choose between several alternative edges.</p>
-<p>The definition of the compilation graph (see file <tt class="docutils literal">llvmc/src/Base.td</tt> for an
-example) is just a list of edges:</p>
-<pre class="literal-block">
-def CompilationGraph : CompilationGraph&lt;[
- Edge&lt;&quot;root&quot;, &quot;llvm_gcc_c&quot;&gt;,
- Edge&lt;&quot;root&quot;, &quot;llvm_gcc_assembler&quot;&gt;,
- ...
-
- Edge&lt;&quot;llvm_gcc_c&quot;, &quot;llc&quot;&gt;,
- Edge&lt;&quot;llvm_gcc_cpp&quot;, &quot;llc&quot;&gt;,
- ...
-
- OptionalEdge&lt;&quot;llvm_gcc_c&quot;, &quot;opt&quot;, (case (switch_on &quot;opt&quot;),
- (inc_weight))&gt;,
- OptionalEdge&lt;&quot;llvm_gcc_cpp&quot;, &quot;opt&quot;, (case (switch_on &quot;opt&quot;),
- (inc_weight))&gt;,
- ...
-
- OptionalEdge&lt;&quot;llvm_gcc_assembler&quot;, &quot;llvm_gcc_cpp_linker&quot;,
- (case (input_languages_contain &quot;c++&quot;), (inc_weight),
- (or (parameter_equals &quot;linker&quot;, &quot;g++&quot;),
- (parameter_equals &quot;linker&quot;, &quot;c++&quot;)), (inc_weight))&gt;,
- ...
-
- ]&gt;;
-</pre>
-<p>As you can see, the edges can be either default or optional, where optional
-edges are differentiated by an additional <tt class="docutils literal">case</tt> expression used to calculate
-the weight of this edge. Notice also that we refer to tools via their names (as
-strings). This makes it possible to add edges to an existing compilation graph
-without having to know about all tool definitions used in the graph.</p>
-<p>The default edges are assigned a weight of 1, and optional edges get a weight of
-0 + 2*N where N is the number of tests that evaluated to true in the <tt class="docutils literal">case</tt>
-expression. It is also possible to provide an integer parameter to
-<tt class="docutils literal">inc_weight</tt> and <tt class="docutils literal">dec_weight</tt> - in this case, the weight is increased (or
-decreased) by the provided value instead of the default 2. Default weight of an
-optional edge can be changed by using the <tt class="docutils literal">default</tt> clause of the <tt class="docutils literal">case</tt>
-construct.</p>
-<p>When passing an input file through the graph, LLVMC picks the edge with the
-maximum weight. To avoid ambiguity, there should be only one default edge
-between two nodes (with the exception of the root node, which gets a special
-treatment - there you are allowed to specify one default edge <em>per language</em>).</p>
-<p>When multiple compilation graphs are defined, they are merged together. Multiple
-edges with the same end nodes are not allowed (i.e. the graph is not a
-multigraph), and will lead to a compile-time error.</p>
-<p>To get a visual representation of the compilation graph (useful for debugging),
-run <tt class="docutils literal">llvmc <span class="pre">--view-graph</span></tt>. You will need <tt class="docutils literal">dot</tt> and <tt class="docutils literal">gsview</tt> installed for
-this to work properly.</p>
-</div>
-<div class="section" id="describing-options">
-<h1><a class="toc-backref" href="#id12">Describing options</a></h1>
-<p>Command-line options supported by the driver are defined by using an
-<tt class="docutils literal">OptionList</tt>:</p>
-<pre class="literal-block">
-def Options : OptionList&lt;[
-(switch_option &quot;E&quot;, (help &quot;Help string&quot;)),
-(alias_option &quot;quiet&quot;, &quot;q&quot;)
-...
-]&gt;;
-</pre>
-<p>As you can see, the option list is just a list of DAGs, where each DAG is an
-option description consisting of the option name and some properties. More than
-one option list can be defined (they are all merged together in the end), which
-can be handy if one wants to separate option groups syntactically.</p>
-<ul>
-<li><p class="first">Possible option types:</p>
-<blockquote>
-<ul class="simple">
-<li><tt class="docutils literal">switch_option</tt> - a simple boolean switch without arguments, for example
-<tt class="docutils literal"><span class="pre">-O2</span></tt> or <tt class="docutils literal"><span class="pre">-time</span></tt>. At most one occurrence is allowed by default.</li>
-<li><tt class="docutils literal">parameter_option</tt> - option that takes one argument, for example
-<tt class="docutils literal"><span class="pre">-std=c99</span></tt>. It is also allowed to use spaces instead of the equality
-sign: <tt class="docutils literal"><span class="pre">-std</span> c99</tt>. At most one occurrence is allowed.</li>
-<li><tt class="docutils literal">parameter_list_option</tt> - same as the above, but more than one option
-occurrence is allowed.</li>
-<li><tt class="docutils literal">prefix_option</tt> - same as the parameter_option, but the option name and
-argument do not have to be separated. Example: <tt class="docutils literal"><span class="pre">-ofile</span></tt>. This can be also
-specified as <tt class="docutils literal"><span class="pre">-o</span> file</tt>; however, <tt class="docutils literal"><span class="pre">-o=file</span></tt> will be parsed incorrectly
-(<tt class="docutils literal">=file</tt> will be interpreted as option value). At most one occurrence is
-allowed.</li>
-<li><tt class="docutils literal">prefix_list_option</tt> - same as the above, but more than one occurrence of
-the option is allowed; example: <tt class="docutils literal"><span class="pre">-lm</span> <span class="pre">-lpthread</span></tt>.</li>
-<li><tt class="docutils literal">alias_option</tt> - a special option type for creating aliases. Unlike other
-option types, aliases are not allowed to have any properties besides the
-aliased option name.
-Usage example: <tt class="docutils literal">(alias_option &quot;preprocess&quot;, &quot;E&quot;)</tt></li>
-<li><tt class="docutils literal">switch_list_option</tt> - like <tt class="docutils literal">switch_option</tt> with the <tt class="docutils literal">zero_or_more</tt>
-property, but remembers how many times the switch was turned on. Useful
-mostly for forwarding. Example: when <tt class="docutils literal"><span class="pre">-foo</span></tt> is a switch option (with the
-<tt class="docutils literal">zero_or_more</tt> property), the command <tt class="docutils literal">driver <span class="pre">-foo</span> <span class="pre">-foo</span></tt> is forwarded
-as <tt class="docutils literal"><span class="pre">some-tool</span> <span class="pre">-foo</span></tt>, but when <tt class="docutils literal"><span class="pre">-foo</span></tt> is a switch list, the same command
-is forwarded as <tt class="docutils literal"><span class="pre">some-tool</span> <span class="pre">-foo</span> <span class="pre">-foo</span></tt>.</li>
-</ul>
-</blockquote>
-</li>
-<li><p class="first">Possible option properties:</p>
-<blockquote>
-<ul class="simple">
-<li><tt class="docutils literal">help</tt> - help string associated with this option. Used for <tt class="docutils literal"><span class="pre">--help</span></tt>
-output.</li>
-<li><tt class="docutils literal">required</tt> - this option must be specified exactly once (or, in case of
-the list options without the <tt class="docutils literal">multi_val</tt> property, at least
-once). Incompatible with <tt class="docutils literal">optional</tt> and <tt class="docutils literal">one_or_more</tt>.</li>
-<li><tt class="docutils literal">optional</tt> - the option can be specified either zero times or exactly
-once. The default for switch options. Useful only for list options in
-conjunction with <tt class="docutils literal">multi_val</tt>. Incompatible with <tt class="docutils literal">required</tt>,
-<tt class="docutils literal">zero_or_more</tt> and <tt class="docutils literal">one_or_more</tt>.</li>
-<li><tt class="docutils literal">one_or_more</tt> - the option must be specified at least once. Can be useful
-to allow switch options be both obligatory and be specified multiple
-times. For list options is useful only in conjunction with <tt class="docutils literal">multi_val</tt>;
-for ordinary it is synonymous with <tt class="docutils literal">required</tt>. Incompatible with
-<tt class="docutils literal">required</tt>, <tt class="docutils literal">optional</tt> and <tt class="docutils literal">zero_or_more</tt>.</li>
-<li><tt class="docutils literal">zero_or_more</tt> - the option can be specified zero or more times. Useful
-to allow a single switch option to be specified more than
-once. Incompatible with <tt class="docutils literal">required</tt>, <tt class="docutils literal">optional</tt> and <tt class="docutils literal">one_or_more</tt>.</li>
-<li><tt class="docutils literal">hidden</tt> - the description of this option will not appear in
-the <tt class="docutils literal"><span class="pre">--help</span></tt> output (but will appear in the <tt class="docutils literal"><span class="pre">--help-hidden</span></tt>
-output).</li>
-<li><tt class="docutils literal">really_hidden</tt> - the option will not be mentioned in any help
-output.</li>
-<li><tt class="docutils literal">comma_separated</tt> - Indicates that any commas specified for an option's
-value should be used to split the value up into multiple values for the
-option. This property is valid only for list options. In conjunction with
-<tt class="docutils literal">forward_value</tt> can be used to implement option forwarding in style of
-gcc's <tt class="docutils literal"><span class="pre">-Wa,</span></tt>.</li>
-<li><tt class="docutils literal">multi_val n</tt> - this option takes <em>n</em> arguments (can be useful in some
-special cases). Usage example: <tt class="docutils literal">(parameter_list_option &quot;foo&quot;, (multi_val
-3))</tt>; the command-line syntax is '-foo a b c'. Only list options can have
-this attribute; you can, however, use the <tt class="docutils literal">one_or_more</tt>, <tt class="docutils literal">optional</tt>
-and <tt class="docutils literal">required</tt> properties.</li>
-<li><tt class="docutils literal">init</tt> - this option has a default value, either a string (if it is a
-parameter), or a boolean (if it is a switch; as in C++, boolean constants
-are called <tt class="docutils literal">true</tt> and <tt class="docutils literal">false</tt>). List options can't have <tt class="docutils literal">init</tt>
-attribute.
-Usage examples: <tt class="docutils literal">(switch_option &quot;foo&quot;, (init true))</tt>; <tt class="docutils literal">(prefix_option
-&quot;bar&quot;, (init <span class="pre">&quot;baz&quot;))</span></tt>.</li>
-</ul>
-</blockquote>
-</li>
-</ul>
-</div>
-<div class="section" id="conditional-evaluation">
-<span id="case"></span><h1><a class="toc-backref" href="#id13">Conditional evaluation</a></h1>
-<p>The 'case' construct is the main means by which programmability is achieved in
-LLVMC. It can be used to calculate edge weights, program actions and modify the
-shell commands to be executed. The 'case' expression is designed after the
-similarly-named construct in functional languages and takes the form <tt class="docutils literal">(case
-(test_1), statement_1, (test_2), statement_2, ... (test_N), statement_N)</tt>. The
-statements are evaluated only if the corresponding tests evaluate to true.</p>
-<p>Examples:</p>
-<pre class="literal-block">
-// Edge weight calculation
-
-// Increases edge weight by 5 if &quot;-A&quot; is provided on the
-// command-line, and by 5 more if &quot;-B&quot; is also provided.
-(case
- (switch_on &quot;A&quot;), (inc_weight 5),
- (switch_on &quot;B&quot;), (inc_weight 5))
-
-
-// Tool command line specification
-
-// Evaluates to &quot;cmdline1&quot; if the option &quot;-A&quot; is provided on the
-// command line; to &quot;cmdline2&quot; if &quot;-B&quot; is provided;
-// otherwise to &quot;cmdline3&quot;.
-
-(case
- (switch_on &quot;A&quot;), &quot;cmdline1&quot;,
- (switch_on &quot;B&quot;), &quot;cmdline2&quot;,
- (default), &quot;cmdline3&quot;)
-</pre>
-<p>Note the slight difference in 'case' expression handling in contexts of edge
-weights and command line specification - in the second example the value of the
-<tt class="docutils literal">&quot;B&quot;</tt> switch is never checked when switch <tt class="docutils literal">&quot;A&quot;</tt> is enabled, and the whole
-expression always evaluates to <tt class="docutils literal">&quot;cmdline1&quot;</tt> in that case.</p>
-<p>Case expressions can also be nested, i.e. the following is legal:</p>
-<pre class="literal-block">
-(case (switch_on &quot;E&quot;), (case (switch_on &quot;o&quot;), ..., (default), ...)
- (default), ...)
-</pre>
-<p>You should, however, try to avoid doing that because it hurts readability. It is
-usually better to split tool descriptions and/or use TableGen inheritance
-instead.</p>
-<ul class="simple">
-<li>Possible tests are:<ul>
-<li><tt class="docutils literal">switch_on</tt> - Returns true if a given command-line switch is provided by
-the user. Can be given multiple arguments, in that case <tt class="docutils literal">(switch_on &quot;foo&quot;,
-&quot;bar&quot;, &quot;baz&quot;)</tt> is equivalent to <tt class="docutils literal">(and (switch_on <span class="pre">&quot;foo&quot;),</span> (switch_on
-<span class="pre">&quot;bar&quot;),</span> (switch_on <span class="pre">&quot;baz&quot;))</span></tt>.
-Example: <tt class="docutils literal">(switch_on &quot;opt&quot;)</tt>.</li>
-<li><tt class="docutils literal">any_switch_on</tt> - Given a number of switch options, returns true if any of
-the switches is turned on.
-Example: <tt class="docutils literal">(any_switch_on &quot;foo&quot;, &quot;bar&quot;, &quot;baz&quot;)</tt> is equivalent to <tt class="docutils literal">(or
-(switch_on <span class="pre">&quot;foo&quot;),</span> (switch_on <span class="pre">&quot;bar&quot;),</span> (switch_on <span class="pre">&quot;baz&quot;))</span></tt>.</li>
-<li><tt class="docutils literal">parameter_equals</tt> - Returns true if a command-line parameter (first
-argument) equals a given value (second argument).
-Example: <tt class="docutils literal">(parameter_equals &quot;W&quot;, &quot;all&quot;)</tt>.</li>
-<li><tt class="docutils literal">element_in_list</tt> - Returns true if a command-line parameter list (first
-argument) contains a given value (second argument).
-Example: <tt class="docutils literal">(element_in_list &quot;l&quot;, &quot;pthread&quot;)</tt>.</li>
-<li><tt class="docutils literal">input_languages_contain</tt> - Returns true if a given language
-belongs to the current input language set.
-Example: <tt class="docutils literal">(input_languages_contain <span class="pre">&quot;c++&quot;)</span></tt>.</li>
-<li><tt class="docutils literal">in_language</tt> - Evaluates to true if the input file language is equal to
-the argument. At the moment works only with <tt class="docutils literal">command</tt> and <tt class="docutils literal">actions</tt> (on
-non-join nodes).
-Example: <tt class="docutils literal">(in_language <span class="pre">&quot;c++&quot;)</span></tt>.</li>
-<li><tt class="docutils literal">not_empty</tt> - Returns true if a given option (which should be either a
-parameter or a parameter list) is set by the user. Like <tt class="docutils literal">switch_on</tt>, can
-be also given multiple arguments.
-Examples: <tt class="docutils literal">(not_empty &quot;o&quot;)</tt>, <tt class="docutils literal">(not_empty &quot;o&quot;, &quot;l&quot;)</tt>.</li>
-<li><tt class="docutils literal">any_not_empty</tt> - Returns true if <tt class="docutils literal">not_empty</tt> returns true for any of
-the provided options.
-Example: <tt class="docutils literal">(any_not_empty &quot;foo&quot;, &quot;bar&quot;, &quot;baz&quot;)</tt> is equivalent to <tt class="docutils literal">(or
-(not_empty <span class="pre">&quot;foo&quot;),</span> (not_empty <span class="pre">&quot;bar&quot;),</span> (not_empty <span class="pre">&quot;baz&quot;))</span></tt>.</li>
-<li><tt class="docutils literal">empty</tt> - The opposite of <tt class="docutils literal">not_empty</tt>. Equivalent to <tt class="docutils literal">(not (not_empty
-X))</tt>. Can be given multiple arguments.</li>
-<li><tt class="docutils literal">any_not_empty</tt> - Returns true if <tt class="docutils literal">not_empty</tt> returns true for any of
-the provided options.
-Example: <tt class="docutils literal">(any_empty &quot;foo&quot;, &quot;bar&quot;, &quot;baz&quot;)</tt> is equivalent to <tt class="docutils literal">(or
-(not_empty <span class="pre">&quot;foo&quot;),</span> (not_empty <span class="pre">&quot;bar&quot;),</span> (not_empty <span class="pre">&quot;baz&quot;))</span></tt>.</li>
-<li><tt class="docutils literal">single_input_file</tt> - Returns true if there was only one input file
-provided on the command-line. Used without arguments:
-<tt class="docutils literal">(single_input_file)</tt>.</li>
-<li><tt class="docutils literal">multiple_input_files</tt> - Equivalent to <tt class="docutils literal">(not (single_input_file))</tt> (the
-case of zero input files is considered an error).</li>
-<li><tt class="docutils literal">default</tt> - Always evaluates to true. Should always be the last
-test in the <tt class="docutils literal">case</tt> expression.</li>
-<li><tt class="docutils literal">and</tt> - A standard logical combinator that returns true iff all of
-its arguments return true. Used like this: <tt class="docutils literal">(and (test1), (test2),
-... (testN))</tt>. Nesting of <tt class="docutils literal">and</tt> and <tt class="docutils literal">or</tt> is allowed, but not
-encouraged.</li>
-<li><tt class="docutils literal">or</tt> - A logical combinator that returns true iff any of its arguments
-return true.
-Example: <tt class="docutils literal">(or (test1), (test2), ... (testN))</tt>.</li>
-<li><tt class="docutils literal">not</tt> - Standard unary logical combinator that negates its
-argument.
-Example: <tt class="docutils literal">(not (or (test1), (test2), ... <span class="pre">(testN)))</span></tt>.</li>
-</ul>
-</li>
-</ul>
-</div>
-<div class="section" id="writing-a-tool-description">
-<h1><a class="toc-backref" href="#id14">Writing a tool description</a></h1>
-<p>As was said earlier, nodes in the compilation graph represent tools, which are
-described separately. A tool definition looks like this (taken from the
-<tt class="docutils literal">llvmc/src/Base.td</tt> file):</p>
-<pre class="literal-block">
-def llvm_gcc_cpp : Tool&lt;[
- (in_language &quot;c++&quot;),
- (out_language &quot;llvm-assembler&quot;),
- (output_suffix &quot;bc&quot;),
- (command &quot;llvm-g++ -c -emit-llvm&quot;),
- (sink)
- ]&gt;;
-</pre>
-<p>This defines a new tool called <tt class="docutils literal">llvm_gcc_cpp</tt>, which is an alias for
-<tt class="docutils literal"><span class="pre">llvm-g++</span></tt>. As you can see, a tool definition is just a list of properties;
-most of them should be self-explanatory. The <tt class="docutils literal">sink</tt> property means that this
-tool should be passed all command-line options that aren't mentioned in the
-option list.</p>
-<p>The complete list of all currently implemented tool properties follows.</p>
-<ul class="simple">
-<li>Possible tool properties:<ul>
-<li><tt class="docutils literal">in_language</tt> - input language name. Can be given multiple arguments, in
-case the tool supports multiple input languages. Used for typechecking and
-mapping file extensions to tools.</li>
-<li><tt class="docutils literal">out_language</tt> - output language name. Multiple output languages are
-allowed. Used for typechecking the compilation graph.</li>
-<li><tt class="docutils literal">output_suffix</tt> - output file suffix. Can also be changed dynamically, see
-documentation on <a class="reference internal" href="#actions">actions</a>.</li>
-</ul>
-</li>
-</ul>
-<blockquote>
-<ul class="simple">
-<li><tt class="docutils literal">command</tt> - the actual command used to run the tool. You can use output
-redirection with <tt class="docutils literal">&gt;</tt>, hook invocations (<tt class="docutils literal">$CALL</tt>), environment variables
-(via <tt class="docutils literal">$ENV</tt>) and the <tt class="docutils literal">case</tt> construct.</li>
-<li><tt class="docutils literal">join</tt> - this tool is a &quot;join node&quot; in the graph, i.e. it gets a list of
-input files and joins them together. Used for linkers.</li>
-<li><tt class="docutils literal">sink</tt> - all command-line options that are not handled by other tools are
-passed to this tool.</li>
-<li><tt class="docutils literal">actions</tt> - A single big <tt class="docutils literal">case</tt> expression that specifies how this tool
-reacts on command-line options (described in more detail <a class="reference internal" href="#actions">below</a>).</li>
-</ul>
-</blockquote>
-<blockquote>
-<ul class="simple">
-<li><tt class="docutils literal">out_file_option</tt>, <tt class="docutils literal">in_file_option</tt> - Options appended to the
-<tt class="docutils literal">command</tt> string to designate output and input files. Default values are
-<tt class="docutils literal"><span class="pre">&quot;-o&quot;</span></tt> and <tt class="docutils literal">&quot;&quot;</tt>, respectively.</li>
-</ul>
-</blockquote>
-<div class="section" id="id4">
-<span id="actions"></span><h2><a class="toc-backref" href="#id15">Actions</a></h2>
-<p>A tool often needs to react to command-line options, and this is precisely what
-the <tt class="docutils literal">actions</tt> property is for. The next example illustrates this feature:</p>
-<pre class="literal-block">
-def llvm_gcc_linker : Tool&lt;[
- (in_language &quot;object-code&quot;),
- (out_language &quot;executable&quot;),
- (output_suffix &quot;out&quot;),
- (command &quot;llvm-gcc&quot;),
- (join),
- (actions (case (not_empty &quot;L&quot;), (forward &quot;L&quot;),
- (not_empty &quot;l&quot;), (forward &quot;l&quot;),
- (not_empty &quot;dummy&quot;),
- [(append_cmd &quot;-dummy1&quot;), (append_cmd &quot;-dummy2&quot;)])
- ]&gt;;
-</pre>
-<p>The <tt class="docutils literal">actions</tt> tool property is implemented on top of the omnipresent <tt class="docutils literal">case</tt>
-expression. It associates one or more different <em>actions</em> with given
-conditions - in the example, the actions are <tt class="docutils literal">forward</tt>, which forwards a given
-option unchanged, and <tt class="docutils literal">append_cmd</tt>, which appends a given string to the tool
-execution command. Multiple actions can be associated with a single condition by
-using a list of actions (used in the example to append some dummy options). The
-same <tt class="docutils literal">case</tt> construct can also be used in the <tt class="docutils literal">cmd_line</tt> property to modify
-the tool command line.</p>
-<p>The &quot;join&quot; property used in the example means that this tool behaves like a
-linker.</p>
-<p>The list of all possible actions follows.</p>
-<ul>
-<li><p class="first">Possible actions:</p>
-<blockquote>
-<ul class="simple">
-<li><tt class="docutils literal">append_cmd</tt> - Append a string to the tool invocation command.
-Example: <tt class="docutils literal">(case (switch_on <span class="pre">&quot;pthread&quot;),</span> (append_cmd <span class="pre">&quot;-lpthread&quot;))</span></tt>.</li>
-<li><tt class="docutils literal">error</tt> - Exit with error.
-Example: <tt class="docutils literal">(error &quot;Mixing <span class="pre">-c</span> and <span class="pre">-S</span> is not <span class="pre">allowed!&quot;)</span></tt>.</li>
-<li><tt class="docutils literal">warning</tt> - Print a warning.
-Example: <tt class="docutils literal">(warning &quot;Specifying both <span class="pre">-O1</span> and <span class="pre">-O2</span> is <span class="pre">meaningless!&quot;)</span></tt>.</li>
-<li><tt class="docutils literal">forward</tt> - Forward the option unchanged.
-Example: <tt class="docutils literal">(forward &quot;Wall&quot;)</tt>.</li>
-<li><tt class="docutils literal">forward_as</tt> - Change the option's name, but forward the argument
-unchanged.
-Example: <tt class="docutils literal">(forward_as &quot;O0&quot;, <span class="pre">&quot;--disable-optimization&quot;)</span></tt>.</li>
-<li><tt class="docutils literal">forward_value</tt> - Forward only option's value. Cannot be used with switch
-options (since they don't have values), but works fine with lists.
-Example: <tt class="docutils literal">(forward_value <span class="pre">&quot;Wa,&quot;)</span></tt>.</li>
-<li><tt class="docutils literal">forward_transformed_value</tt> - As above, but applies a hook to the
-option's value before forwarding (see <a class="reference internal" href="#hooks">below</a>). When
-<tt class="docutils literal">forward_transformed_value</tt> is applied to a list
-option, the hook must have signature
-<tt class="docutils literal"><span class="pre">std::string</span> <span class="pre">hooks::HookName</span> (const <span class="pre">std::vector&lt;std::string&gt;&amp;)</span></tt>.
-Example: <tt class="docutils literal">(forward_transformed_value &quot;m&quot;, &quot;ConvertToMAttr&quot;)</tt>.</li>
-<li><tt class="docutils literal">output_suffix</tt> - Modify the output suffix of this tool.
-Example: <tt class="docutils literal">(output_suffix &quot;i&quot;)</tt>.</li>
-<li><tt class="docutils literal">stop_compilation</tt> - Stop compilation after this tool processes its
-input. Used without arguments.
-Example: <tt class="docutils literal">(stop_compilation)</tt>.</li>
-</ul>
-</blockquote>
-</li>
-</ul>
-</div>
-</div>
-<div class="section" id="language-map">
-<h1><a class="toc-backref" href="#id16">Language map</a></h1>
-<p>If you are adding support for a new language to LLVMC, you'll need to modify the
-language map, which defines mappings from file extensions to language names. It
-is used to choose the proper toolchain(s) for a given input file set. Language
-map definition looks like this:</p>
-<pre class="literal-block">
-def LanguageMap : LanguageMap&lt;
- [LangToSuffixes&lt;&quot;c++&quot;, [&quot;cc&quot;, &quot;cp&quot;, &quot;cxx&quot;, &quot;cpp&quot;, &quot;CPP&quot;, &quot;c++&quot;, &quot;C&quot;]&gt;,
- LangToSuffixes&lt;&quot;c&quot;, [&quot;c&quot;]&gt;,
- ...
- ]&gt;;
-</pre>
-<p>For example, without those definitions the following command wouldn't work:</p>
-<pre class="literal-block">
-$ llvmc hello.cpp
-llvmc: Unknown suffix: cpp
-</pre>
-<p>The language map entries are needed only for the tools that are linked from the
-root node. A tool can have multiple output languages.</p>
-</div>
-<div class="section" id="option-preprocessor">
-<h1><a class="toc-backref" href="#id17">Option preprocessor</a></h1>
-<p>It is sometimes useful to run error-checking code before processing the
-compilation graph. For example, if optimization options &quot;-O1&quot; and &quot;-O2&quot; are
-implemented as switches, we might want to output a warning if the user invokes
-the driver with both of these options enabled.</p>
-<p>The <tt class="docutils literal">OptionPreprocessor</tt> feature is reserved specially for these
-occasions. Example (adapted from <tt class="docutils literal">llvm/src/Base.td.in</tt>):</p>
-<pre class="literal-block">
-def Preprocess : OptionPreprocessor&lt;
-(case (not (any_switch_on &quot;O0&quot;, &quot;O1&quot;, &quot;O2&quot;, &quot;O3&quot;)),
- (set_option &quot;O2&quot;),
- (and (switch_on &quot;O3&quot;), (any_switch_on &quot;O0&quot;, &quot;O1&quot;, &quot;O2&quot;)),
- (unset_option &quot;O0&quot;, &quot;O1&quot;, &quot;O2&quot;),
- (and (switch_on &quot;O2&quot;), (any_switch_on &quot;O0&quot;, &quot;O1&quot;)),
- (unset_option &quot;O0&quot;, &quot;O1&quot;),
- (and (switch_on &quot;O1&quot;), (switch_on &quot;O0&quot;)),
- (unset_option &quot;O0&quot;))
-&gt;;
-</pre>
-<p>Here, <tt class="docutils literal">OptionPreprocessor</tt> is used to unset all spurious <tt class="docutils literal"><span class="pre">-O</span></tt> options so
-that they are not forwarded to the compiler. If no optimization options are
-specified, <tt class="docutils literal"><span class="pre">-O2</span></tt> is enabled.</p>
-<p><tt class="docutils literal">OptionPreprocessor</tt> is basically a single big <tt class="docutils literal">case</tt> expression, which is
-evaluated only once right after the driver is started. The only allowed actions
-in <tt class="docutils literal">OptionPreprocessor</tt> are <tt class="docutils literal">error</tt>, <tt class="docutils literal">warning</tt>, and two special actions:
-<tt class="docutils literal">unset_option</tt> and <tt class="docutils literal">set_option</tt>. As their names suggest, they can be used to
-set or unset a given option. To set an option with <tt class="docutils literal">set_option</tt>, use the
-two-argument form: <tt class="docutils literal">(set_option &quot;parameter&quot;, VALUE)</tt>. Here, <tt class="docutils literal">VALUE</tt> can be
-either a string, a string list, or a boolean constant.</p>
-<p>For convenience, <tt class="docutils literal">set_option</tt> and <tt class="docutils literal">unset_option</tt> also work with multiple
-arguments. That is, instead of <tt class="docutils literal">[(unset_option <span class="pre">&quot;A&quot;),</span> (unset_option <span class="pre">&quot;B&quot;)]</span></tt> you
-can use <tt class="docutils literal">(unset_option &quot;A&quot;, &quot;B&quot;)</tt>. Obviously, <tt class="docutils literal">(set_option &quot;A&quot;, &quot;B&quot;)</tt> is
-only valid if both <tt class="docutils literal">A</tt> and <tt class="docutils literal">B</tt> are switches.</p>
-</div>
-<div class="section" id="more-advanced-topics">
-<h1><a class="toc-backref" href="#id18">More advanced topics</a></h1>
-<div class="section" id="hooks-and-environment-variables">
-<span id="hooks"></span><h2><a class="toc-backref" href="#id19">Hooks and environment variables</a></h2>
-<p>Normally, LLVMC searches for programs in the system <tt class="docutils literal">PATH</tt>. Sometimes, this is
-not sufficient: for example, we may want to specify tool paths or names in the
-configuration file. This can be achieved via the hooks mechanism. To write your
-own hooks, add their definitions to the <tt class="docutils literal">Hooks.cpp</tt> or drop a <tt class="docutils literal">.cpp</tt> file
-into your driver directory. Hooks should live in the <tt class="docutils literal">hooks</tt> namespace and
-have the signature <tt class="docutils literal"><span class="pre">std::string</span> <span class="pre">hooks::MyHookName</span> ([const char* Arg0 [ const
-char* Arg2 [, <span class="pre">...]]])</span></tt>. They can be used from the <tt class="docutils literal">command</tt> tool property:</p>
-<pre class="literal-block">
-(command &quot;$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)&quot;)
-</pre>
-<p>To pass arguments to hooks, use the following syntax:</p>
-<pre class="literal-block">
-(command &quot;$CALL(MyHook, 'Arg1', 'Arg2', 'Arg # 3')/path/to/file -o1 -o2&quot;)
-</pre>
-<p>It is also possible to use environment variables in the same manner:</p>
-<pre class="literal-block">
-(command &quot;$ENV(VAR1)/path/to/file -o $ENV(VAR2)&quot;)
-</pre>
-<p>To change the command line string based on user-provided options use
-the <tt class="docutils literal">case</tt> expression (documented <a class="reference internal" href="#case">above</a>):</p>
-<pre class="literal-block">
-(command
- (case
- (switch_on &quot;E&quot;),
- &quot;llvm-g++ -E -x c $INFILE -o $OUTFILE&quot;,
- (default),
- &quot;llvm-g++ -c -x c $INFILE -o $OUTFILE -emit-llvm&quot;))
-</pre>
-</div>
-<div class="section" id="debugging">
-<h2><a class="toc-backref" href="#id20">Debugging</a></h2>
-<p>When writing LLVMC-based drivers, it can be useful to get a visual view of the
-resulting compilation graph. This can be achieved via the command line option
-<tt class="docutils literal"><span class="pre">--view-graph</span></tt> (which assumes that <a class="reference external" href="http://www.graphviz.org/">Graphviz</a> and <a class="reference external" href="http://pages.cs.wisc.edu/~ghost/">Ghostview</a> are
-installed). There is also a <tt class="docutils literal"><span class="pre">--write-graph</span></tt> option that creates a Graphviz
-source file (<tt class="docutils literal"><span class="pre">compilation-graph.dot</span></tt>) in the current directory.</p>
-<p>Another useful <tt class="docutils literal">llvmc</tt> option is <tt class="docutils literal"><span class="pre">--check-graph</span></tt>. It checks the compilation
-graph for common errors like mismatched output/input language names, multiple
-default edges and cycles. When invoked with <tt class="docutils literal"><span class="pre">--check-graph</span></tt>, <tt class="docutils literal">llvmc</tt> doesn't
-perform any compilation tasks and returns the number of encountered errors as
-its status code. In the future, these checks will be performed at compile-time
-and this option will disappear.</p>
-</div>
-<div class="section" id="conditioning-on-the-executable-name">
-<h2><a class="toc-backref" href="#id21">Conditioning on the executable name</a></h2>
-<p>For now, the executable name (the value passed to the driver in <tt class="docutils literal">argv[0]</tt>) is
-accessible only in the C++ code (i.e. hooks). Use the following code:</p>
-<pre class="literal-block">
-namespace llvmc {
-extern const char* ProgramName;
-}
-
-namespace hooks {
-
-std::string MyHook() {
-//...
-if (strcmp(ProgramName, &quot;mydriver&quot;) == 0) {
- //...
-
-}
-
-} // end namespace hooks
-</pre>
-<p>In general, you're encouraged not to make the behaviour dependent on the
-executable file name, and use command-line switches instead. See for example how
-the <tt class="docutils literal">llvmc</tt> program behaves when it needs to choose the correct linker options
-(think <tt class="docutils literal">g++</tt> vs. <tt class="docutils literal">gcc</tt>).</p>
-<hr />
-<address>
-<a href="http://jigsaw.w3.org/css-validator/check/referer">
-<img src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
- alt="Valid CSS" /></a>
-<a href="http://validator.w3.org/check?uri=referer">
-<img src="http://www.w3.org/Icons/valid-xhtml10-blue"
- alt="Valid XHTML 1.0 Transitional"/></a>
-
-<a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
-<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
-
-Last modified: $Date: 2011-05-07 00:11:29 +0200 (Sat, 07 May 2011) $
-</address></div>
-</div>
-</div>
-</body>
-</html>
diff --git a/docs/CompilerDriverTutorial.html b/docs/CompilerDriverTutorial.html
deleted file mode 100644
index 4ed373a..0000000
--- a/docs/CompilerDriverTutorial.html
+++ /dev/null
@@ -1,125 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
-<title>Tutorial - Using LLVMC</title>
-<link rel="stylesheet" href="llvm.css" type="text/css" />
-</head>
-<body>
-<div class="document" id="tutorial-using-llvmc">
-<h1 class="title">Tutorial - Using LLVMC</h1>
-
-<!-- This file was automatically generated by rst2html.
-Please do not edit directly!
-The ReST source lives in the directory 'tools/llvmc/doc'. -->
-<div class="contents topic" id="contents">
-<p class="topic-title first">Contents</p>
-<ul class="simple">
-<li><a class="reference internal" href="#introduction" id="id1">Introduction</a></li>
-<li><a class="reference internal" href="#using-the-llvmc-program" id="id2">Using the <tt class="docutils literal">llvmc</tt> program</a></li>
-<li><a class="reference internal" href="#using-llvmc-to-generate-toolchain-drivers" id="id3">Using LLVMC to generate toolchain drivers</a></li>
-</ul>
-</div>
-<div class="doc_author">
-<p>Written by <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a></p>
-</div><div class="section" id="introduction">
-<h1><a class="toc-backref" href="#id1">Introduction</a></h1>
-<p>LLVMC is a generic compiler driver, which plays the same role for LLVM as the
-<tt class="docutils literal">gcc</tt> program does for GCC - the difference being that LLVMC is designed to be
-more adaptable and easier to customize. Most of LLVMC functionality is
-implemented via high-level TableGen code, from which a corresponding C++ source
-file is automatically generated. This tutorial describes the basic usage and
-configuration of LLVMC.</p>
-</div>
-<div class="section" id="using-the-llvmc-program">
-<h1><a class="toc-backref" href="#id2">Using the <tt class="docutils literal">llvmc</tt> program</a></h1>
-<p>In general, <tt class="docutils literal">llvmc</tt> tries to be command-line compatible with <tt class="docutils literal">gcc</tt> as much
-as possible, so most of the familiar options work:</p>
-<pre class="literal-block">
-$ llvmc -O3 -Wall hello.cpp
-$ ./a.out
-hello
-</pre>
-<p>This will invoke <tt class="docutils literal"><span class="pre">llvm-g++</span></tt> under the hood (you can see which commands are
-executed by using the <tt class="docutils literal"><span class="pre">-v</span></tt> option). For further help on command-line LLVMC
-usage, refer to the <tt class="docutils literal">llvmc <span class="pre">--help</span></tt> output.</p>
-</div>
-<div class="section" id="using-llvmc-to-generate-toolchain-drivers">
-<h1><a class="toc-backref" href="#id3">Using LLVMC to generate toolchain drivers</a></h1>
-<p>LLVMC-based drivers are written mostly using <a class="reference external" href="http://llvm.org/docs/TableGenFundamentals.html">TableGen</a>, so you need to be
-familiar with it to get anything done.</p>
-<p>Start by compiling <tt class="docutils literal">example/Simple</tt>, which is a primitive wrapper for
-<tt class="docutils literal">gcc</tt>:</p>
-<pre class="literal-block">
-$ cd $LLVM_OBJ_DIR/tools/examples/Simple
-$ make
-$ cat &gt; hello.c
-#include &lt;stdio.h&gt;
-int main() { printf(&quot;Hello\n&quot;); }
-$ $LLVM_BIN_DIR/Simple -v hello.c
-gcc hello.c -o hello.out
-$ ./hello.out
-Hello
-</pre>
-<p>We have thus produced a simple driver called, appropriately, <tt class="docutils literal">Simple</tt>, from
-the input TableGen file <tt class="docutils literal">Simple.td</tt>. The <tt class="docutils literal">llvmc</tt> program itself is generated
-using a similar process (see <tt class="docutils literal">llvmc/src</tt>). Contents of the file <tt class="docutils literal">Simple.td</tt>
-look like this:</p>
-<pre class="literal-block">
-// Include common definitions
-include &quot;llvm/CompilerDriver/Common.td&quot;
-
-// Tool descriptions
-def gcc : Tool&lt;
-[(in_language &quot;c&quot;),
- (out_language &quot;executable&quot;),
- (output_suffix &quot;out&quot;),
- (command &quot;gcc&quot;),
- (sink),
-
- // -o is what is used by default, out_file_option here is included for
- // instructive purposes.
- (out_file_option &quot;-o&quot;)
-]&gt;;
-
-// Language map
-def LanguageMap : LanguageMap&lt;[(lang_to_suffixes &quot;c&quot;, &quot;c&quot;)]&gt;;
-
-// Compilation graph
-def CompilationGraph : CompilationGraph&lt;[(edge &quot;root&quot;, &quot;gcc&quot;)]&gt;;
-</pre>
-<p>As you can see, this file consists of three parts: tool descriptions, language
-map, and the compilation graph definition.</p>
-<p>At the heart of LLVMC is the idea of a compilation graph: vertices in this graph
-are tools, and edges represent a transformation path between two tools (for
-example, assembly source produced by the compiler can be transformed into
-executable code by an assembler). The compilation graph is basically a list of
-edges; a special node named <tt class="docutils literal">root</tt> is used to mark graph entry points.</p>
-<p>Tool descriptions are represented as property lists: most properties in the
-example above should be self-explanatory; the <tt class="docutils literal">sink</tt> property means that all
-options lacking an explicit description should be forwarded to this tool.</p>
-<p>The <tt class="docutils literal">LanguageMap</tt> associates a language name with a list of suffixes and is
-used for deciding which toolchain corresponds to a given input file.</p>
-<p>To learn more about writing your own drivers with LLVMC, refer to the reference
-manual and examples in the <tt class="docutils literal">examples</tt> directory. Of a particular interest is
-the <tt class="docutils literal">Skeleton</tt> example, which can serve as a template for your LLVMC-based
-drivers.</p>
-<hr />
-<address>
-<a href="http://jigsaw.w3.org/css-validator/check/referer">
-<img src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
- alt="Valid CSS" /></a>
-<a href="http://validator.w3.org/check?uri=referer">
-<img src="http://www.w3.org/Icons/valid-xhtml10-blue"
- alt="Valid XHTML 1.0 Transitional"/></a>
-
-<a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
-<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
-
-Last modified: $Date: 2008-12-11 11:34:48 -0600 (Thu, 11 Dec 2008) $
-</address></div>
-</div>
-</body>
-</html>
diff --git a/docs/DeveloperPolicy.html b/docs/DeveloperPolicy.html
index c121657..7c78016 100644
--- a/docs/DeveloperPolicy.html
+++ b/docs/DeveloperPolicy.html
@@ -207,7 +207,11 @@
<li><b>Chris Lattner</b>: Everything not covered by someone else.</li>
- <li><b>Duncan Sands</b>: llvm-gcc 4.2.</li>
+ <li><b>John McCall</b>: Clang LLVM IR generation.</li>
+
+ <li><b>Jakob Olesen</b>: Register allocators and TableGen.</li>
+
+ <li><b>Duncan Sands</b>: dragonegg and llvm-gcc 4.2.</li>
</ol>
<p>Note that code ownership is completely different than reviewers: anyone can
@@ -492,8 +496,9 @@
<div>
<p>This section addresses the issues of copyright, license and patents for the
- LLVM project. Currently, the University of Illinois is the LLVM copyright
- holder and the terms of its license to LLVM users and developers is the
+ LLVM project. The copyright holder for the code is held by the individual
+ contributors of the code and the terms of its license to LLVM users and
+ developers is the
<a href="http://www.opensource.org/licenses/UoI-NCSA.php">University of
Illinois/NCSA Open Source License</a>.</p>
@@ -611,7 +616,7 @@
Written by the
<a href="mailto:llvm-oversight@cs.uiuc.edu">LLVM Oversight Group</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-10-07 19:26:38 +0200 (Fri, 07 Oct 2011) $
</address>
</body>
</html>
diff --git a/docs/ExceptionHandling.html b/docs/ExceptionHandling.html
index c0f50e3..85ab796 100644
--- a/docs/ExceptionHandling.html
+++ b/docs/ExceptionHandling.html
@@ -33,9 +33,6 @@
</ol></li>
<li><a href="#format_common_intrinsics">Exception Handling Intrinsics</a>
<ol>
- <li><a href="#llvm_eh_exception"><tt>llvm.eh.exception</tt></a></li>
- <li><a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a></li>
- <li><a href="#llvm_eh_resume"><tt>llvm.eh.resume</tt></a></li>
<li><a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a></li>
<li><a href="#llvm_eh_sjlj_setjmp"><tt>llvm.eh.sjlj.setjmp</tt></a></li>
<li><a href="#llvm_eh_sjlj_longjmp"><tt>llvm.eh.sjlj.longjmp</tt></a></li>
@@ -48,7 +45,6 @@
<li><a href="#unwind_tables">Exception Handling Frame</a></li>
<li><a href="#exception_tables">Exception Tables</a></li>
</ol></li>
- <li><a href="#todo">ToDo</a></li>
</ul>
</td>
</tr></table>
@@ -69,7 +65,7 @@
handling information takes, which is useful for those interested in creating
front-ends or dealing directly with the information. Further, this document
provides specific examples of what exception handling information is used for
- in C/C++.</p>
+ in C and C++.</p>
<!-- ======================================================================= -->
<h3>
@@ -96,8 +92,8 @@
Exception Handling</a>. A description of the exception frame format can be
found at
<a href="http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html">Exception
- Frames</a>, with details of the DWARF 3 specification at
- <a href="http://www.eagercon.com/dwarf/dwarf3std.htm">DWARF 3 Standard</a>.
+ Frames</a>, with details of the DWARF 4 specification at
+ <a href="http://dwarfstd.org/Dwarf4Std.php">DWARF 4 Standard</a>.
A description for the C++ exception table formats can be found at
<a href="http://www.codesourcery.com/cxx-abi/exceptions.pdf">Exception Handling
Tables</a>.</p>
@@ -116,10 +112,10 @@
<a href="#llvm_eh_sjlj_longjmp"><tt>llvm.eh.sjlj.longjmp</tt></a> to
handle control flow for exception handling.</p>
-<p>For each function which does exception processing, be it try/catch blocks
- or cleanups, that function registers itself on a global frame list. When
- exceptions are being unwound, the runtime uses this list to identify which
- functions need processing.<p>
+<p>For each function which does exception processing &mdash; be
+ it <tt>try</tt>/<tt>catch</tt> blocks or cleanups &mdash; that function
+ registers itself on a global frame list. When exceptions are unwinding, the
+ runtime uses this list to identify which functions need processing.<p>
<p>Landing pad selection is encoded in the call site entry of the function
context. The runtime returns to the function via
@@ -134,6 +130,7 @@
exceptions are thrown. As exceptions are, by their nature, intended for
uncommon code paths, DWARF exception handling is generally preferred to
SJLJ.</p>
+
</div>
<!-- ======================================================================= -->
@@ -148,19 +145,19 @@
<p>The runtime first attempts to find an <i>exception frame</i> corresponding to
the function where the exception was thrown. If the programming language
- (e.g. C++) supports exception handling, the exception frame contains a
+ supports exception handling (e.g. C++), the exception frame contains a
reference to an exception table describing how to process the exception. If
- the language (e.g. C) does not support exception handling, or if the
+ the language does not support exception handling (e.g. C), or if the
exception needs to be forwarded to a prior activation, the exception frame
contains information about how to unwind the current activation and restore
the state of the prior activation. This process is repeated until the
- exception is handled. If the exception is not handled and no activations
+ exception is handled. If the exception is not handled and no activations
remain, then the application is terminated with an appropriate error
message.</p>
<p>Because different programming languages have different behaviors when
handling exceptions, the exception handling ABI provides a mechanism for
- supplying <i>personalities.</i> An exception handling personality is defined
+ supplying <i>personalities</i>. An exception handling personality is defined
by way of a <i>personality function</i> (e.g. <tt>__gxx_personality_v0</tt>
in C++), which receives the context of the exception, an <i>exception
structure</i> containing the exception object type and value, and a reference
@@ -168,19 +165,20 @@
for the current compile unit is specified in a <i>common exception
frame</i>.</p>
-<p>The organization of an exception table is language dependent. For C++, an
+<p>The organization of an exception table is language dependent. For C++, an
exception table is organized as a series of code ranges defining what to do
- if an exception occurs in that range. Typically, the information associated
+ if an exception occurs in that range. Typically, the information associated
with a range defines which types of exception objects (using C++ <i>type
info</i>) that are handled in that range, and an associated action that
- should take place. Actions typically pass control to a <i>landing
+ should take place. Actions typically pass control to a <i>landing
pad</i>.</p>
-<p>A landing pad corresponds to the code found in the <i>catch</i> portion of
- a <i>try</i>/<i>catch</i> sequence. When execution resumes at a landing
- pad, it receives the exception structure and a selector corresponding to
- the <i>type</i> of exception thrown. The selector is then used to determine
- which <i>catch</i> should actually process the exception.</p>
+<p>A landing pad corresponds roughly to the code found in the <tt>catch</tt>
+ portion of a <tt>try</tt>/<tt>catch</tt> sequence. When execution resumes at
+ a landing pad, it receives an <i>exception structure</i> and a
+ <i>selector value</i> corresponding to the <i>type</i> of exception
+ thrown. The selector is then used to determine which <i>catch</i> should
+ actually process the exception.</p>
</div>
@@ -193,11 +191,8 @@
<div>
-<p>At the time of this writing, only C++ exception handling support is available
- in LLVM. So the remainder of this document will be somewhat C++-centric.</p>
-
-<p>From the C++ developers perspective, exceptions are defined in terms of the
- <tt>throw</tt> and <tt>try</tt>/<tt>catch</tt> statements. In this section
+<p>From a C++ developer's perspective, exceptions are defined in terms of the
+ <tt>throw</tt> and <tt>try</tt>/<tt>catch</tt> statements. In this section
we will describe the implementation of LLVM exception handling in terms of
C++ examples.</p>
@@ -209,17 +204,22 @@
<div>
<p>Languages that support exception handling typically provide a <tt>throw</tt>
- operation to initiate the exception process. Internally, a throw operation
- breaks down into two steps. First, a request is made to allocate exception
- space for an exception structure. This structure needs to survive beyond the
- current activation. This structure will contain the type and value of the
- object being thrown. Second, a call is made to the runtime to raise the
- exception, passing the exception structure as an argument.</p>
-
-<p>In C++, the allocation of the exception structure is done by
- the <tt>__cxa_allocate_exception</tt> runtime function. The exception
- raising is handled by <tt>__cxa_throw</tt>. The type of the exception is
- represented using a C++ RTTI structure.</p>
+ operation to initiate the exception process. Internally, a <tt>throw</tt>
+ operation breaks down into two steps.</p>
+
+<ol>
+ <li>A request is made to allocate exception space for an exception structure.
+ This structure needs to survive beyond the current activation. This
+ structure will contain the type and value of the object being thrown.</li>
+
+ <li>A call is made to the runtime to raise the exception, passing the
+ exception structure as an argument.</li>
+</ol>
+
+<p>In C++, the allocation of the exception structure is done by the
+ <tt>__cxa_allocate_exception</tt> runtime function. The exception raising is
+ handled by <tt>__cxa_throw</tt>. The type of the exception is represented
+ using a C++ RTTI structure.</p>
</div>
@@ -231,81 +231,68 @@
<div>
<p>A call within the scope of a <i>try</i> statement can potentially raise an
- exception. In those circumstances, the LLVM C++ front-end replaces the call
- with an <tt>invoke</tt> instruction. Unlike a call, the <tt>invoke</tt> has
- two potential continuation points: where to continue when the call succeeds
- as per normal; and where to continue if the call raises an exception, either
- by a throw or the unwinding of a throw.</p>
+ exception. In those circumstances, the LLVM C++ front-end replaces the call
+ with an <tt>invoke</tt> instruction. Unlike a call, the <tt>invoke</tt> has
+ two potential continuation points:</p>
+
+<ol>
+ <li>where to continue when the call succeeds as per normal, and</li>
+
+ <li>where to continue if the call raises an exception, either by a throw or
+ the unwinding of a throw</li>
+</ol>
<p>The term used to define a the place where an <tt>invoke</tt> continues after
- an exception is called a <i>landing pad</i>. LLVM landing pads are
+ an exception is called a <i>landing pad</i>. LLVM landing pads are
conceptually alternative function entry points where an exception structure
- reference and a type info index are passed in as arguments. The landing pad
+ reference and a type info index are passed in as arguments. The landing pad
saves the exception structure reference and then proceeds to select the catch
block that corresponds to the type info of the exception object.</p>
-<p>Two LLVM intrinsic functions are used to convey information about the landing
- pad to the back end.</p>
-
-<ol>
- <li><a href="#llvm_eh_exception"><tt>llvm.eh.exception</tt></a> takes no
- arguments and returns a pointer to the exception structure. This only
- returns a sensible value if called after an <tt>invoke</tt> has branched
- to a landing pad. Due to code generation limitations, it must currently
- be called in the landing pad itself.</li>
-
- <li><a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> takes a minimum
- of three arguments. The first argument is the reference to the exception
- structure. The second argument is a reference to the personality function
- to be used for this <tt>try</tt>/<tt>catch</tt> sequence. Each of the
- remaining arguments is either a reference to the type info for
- a <tt>catch</tt> statement, a <a href="#throw_filters">filter</a>
- expression, or the number zero (<tt>0</tt>) representing
- a <a href="#cleanups">cleanup</a>. The exception is tested against the
- arguments sequentially from first to last. The result of
- the <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> is a
- positive number if the exception matched a type info, a negative number if
- it matched a filter, and zero if it matched a cleanup. If nothing is
- matched, the behaviour of the program
- is <a href="#restrictions">undefined</a>. This only returns a sensible
- value if called after an <tt>invoke</tt> has branched to a landing pad.
- Due to codegen limitations, it must currently be called in the landing pad
- itself. If a type info matched, then the selector value is the index of
- the type info in the exception table, which can be obtained using the
- <a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a>
- intrinsic.</li>
-</ol>
+<p>The LLVM <a href="LangRef.html#i_landingpad"><tt>landingpad</tt>
+ instruction</a> is used to convey information about the landing pad to the
+ back end. For C++, the <tt>landingpad</tt> instruction returns a pointer and
+ integer pair corresponding to the pointer to the <i>exception structure</i>
+ and the <i>selector value</i> respectively.</p>
+
+<p>The <tt>landingpad</tt> instruction takes a reference to the personality
+ function to be used for this <tt>try</tt>/<tt>catch</tt> sequence. The
+ remainder of the instruction is a list of <i>cleanup</i>, <i>catch</i>,
+ and <i>filter</i> clauses. The exception is tested against the clauses
+ sequentially from first to last. The selector value is a positive number if
+ the exception matched a type info, a negative number if it matched a filter,
+ and zero if it matched a cleanup. If nothing is matched, the behavior of
+ the program is <a href="#restrictions">undefined</a>. If a type info matched,
+ then the selector value is the index of the type info in the exception table,
+ which can be obtained using the
+ <a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a> intrinsic.</p>
<p>Once the landing pad has the type info selector, the code branches to the
- code for the first catch. The catch then checks the value of the type info
+ code for the first catch. The catch then checks the value of the type info
selector against the index of type info for that catch. Since the type info
- index is not known until all the type info have been gathered in the backend,
- the catch code will call the
- <a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a> intrinsic
- to determine the index for a given type info. If the catch fails to match
- the selector then control is passed on to the next catch. Note: Since the
- landing pad will not be used if there is no match in the list of type info on
- the call to <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>, then
- neither the last catch nor <i>catch all</i> need to perform the check
- against the selector.</p>
-
-<p>Finally, the entry and exit of catch code is bracketed with calls
- to <tt>__cxa_begin_catch</tt> and <tt>__cxa_end_catch</tt>.</p>
+ index is not known until all the type infos have been gathered in the
+ backend, the catch code must call the
+ <a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a> intrinsic to
+ determine the index for a given type info. If the catch fails to match the
+ selector then control is passed on to the next catch.</p>
+
+<p>Finally, the entry and exit of catch code is bracketed with calls to
+ <tt>__cxa_begin_catch</tt> and <tt>__cxa_end_catch</tt>.</p>
<ul>
- <li><tt>__cxa_begin_catch</tt> takes a exception structure reference as an
+ <li><tt>__cxa_begin_catch</tt> takes an exception structure reference as an
argument and returns the value of the exception object.</li>
<li><tt>__cxa_end_catch</tt> takes no arguments. This function:<br><br>
<ol>
<li>Locates the most recently caught exception and decrements its handler
count,</li>
- <li>Removes the exception from the "caught" stack if the handler count
- goes to zero, and</li>
- <li>Destroys the exception if the handler count goes to zero, and the
+ <li>Removes the exception from the <i>caught</i> stack if the handler
+ count goes to zero, and</li>
+ <li>Destroys the exception if the handler count goes to zero and the
exception was not re-thrown by throw.</li>
</ol>
- <p>Note: a rethrow from within the catch may replace this call with
+ <p><b>Note:</b> a rethrow from within the catch may replace this call with
a <tt>__cxa_rethrow</tt>.</p></li>
</ul>
@@ -318,28 +305,26 @@
<div>
-<p>A cleanup is extra code which needs to be run as part of unwinding
- a scope. C++ destructors are a prominent example, but other
- languages and language extensions provide a variety of different
- kinds of cleanup. In general, a landing pad may need to run
- arbitrary amounts of cleanup code before actually entering a catch
- block. To indicate the presence of cleanups, a landing pad's call
- to <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> should
- end with the argument <tt>i32 0</tt>; otherwise, the unwinder will
- not stop at the landing pad if there are no catches or filters that
- require it to.</p>
-
-<p>Do not allow a new exception to propagate out of the execution of a
- cleanup. This can corrupt the internal state of the unwinder.
- Different languages describe different high-level semantics for
- these situations: for example, C++ requires that the process be
- terminated, whereas Ada cancels both exceptions and throws a third.</p>
-
-<p>When all cleanups have completed, if the exception is not handled
- by the current function, resume unwinding by calling the
- <a href="#llvm_eh_resume"><tt>llvm.eh.resume</tt></a> intrinsic,
- passing in the results of <tt>llvm.eh.exception</tt> and
- <tt>llvm.eh.selector</tt> for the original landing pad.</p>
+<p>A cleanup is extra code which needs to be run as part of unwinding a scope.
+ C++ destructors are a typical example, but other languages and language
+ extensions provide a variety of different kinds of cleanups. In general, a
+ landing pad may need to run arbitrary amounts of cleanup code before actually
+ entering a catch block. To indicate the presence of cleanups, a
+ <a href="LangRef.html#i_landingpad"><tt>landingpad</tt> instruction</a>
+ should have a <i>cleanup</i> clause. Otherwise, the unwinder will not stop at
+ the landing pad if there are no catches or filters that require it to.</p>
+
+<p><b>Note:</b> Do not allow a new exception to propagate out of the execution
+ of a cleanup. This can corrupt the internal state of the unwinder.
+ Different languages describe different high-level semantics for these
+ situations: for example, C++ requires that the process be terminated, whereas
+ Ada cancels both exceptions and throws a third.</p>
+
+<p>When all cleanups are finished, if the exception is not handled by the
+ current function, resume unwinding by calling the
+ <a href="LangRef.html#i_resume"><tt>resume</tt> instruction</a>, passing in
+ the result of the <tt>landingpad</tt> instruction for the original landing
+ pad.</p>
</div>
@@ -350,23 +335,21 @@
<div>
-<p>C++ allows the specification of which exception types can be thrown from a
- function. To represent this a top level landing pad may exist to filter out
- invalid types. To express this in LLVM code the landing pad will
- call <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>. The
- arguments are a reference to the exception structure, a reference to the
- personality function, the length of the filter expression (the number of type
- infos plus one), followed by the type infos themselves.
- <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> will return a
- negative value if the exception does not match any of the type infos. If no
- match is found then a call to <tt>__cxa_call_unexpected</tt> should be made,
- otherwise <tt>_Unwind_Resume</tt>. Each of these functions requires a
- reference to the exception structure. Note that the most general form of an
- <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> call can contain
- any number of type infos, filter expressions and cleanups (though having more
- than one cleanup is pointless). The LLVM C++ front-end can generate such
- <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> calls due to
- inlining creating nested exception handling scopes.</p>
+<p>C++ allows the specification of which exception types may be thrown from a
+ function. To represent this, a top level landing pad may exist to filter out
+ invalid types. To express this in LLVM code the
+ <a href="LangRef.html#i_landingpad"><tt>landingpad</tt> instruction</a> will
+ have a filter clause. The clause consists of an array of type infos.
+ <tt>landingpad</tt> will return a negative value if the exception does not
+ match any of the type infos. If no match is found then a call
+ to <tt>__cxa_call_unexpected</tt> should be made, otherwise
+ <tt>_Unwind_Resume</tt>. Each of these functions requires a reference to the
+ exception structure. Note that the most general form of a
+ <a href="LangRef.html#i_landingpad"><tt>landingpad</tt> instruction</a> can
+ have any number of catch, cleanup, and filter clauses (though having more
+ than one cleanup is pointless). The LLVM C++ front-end can generate such
+ <a href="LangRef.html#i_landingpad"><tt>landingpad</tt> instructions</a> due
+ to inlining creating nested exception handling scopes.</p>
</div>
@@ -377,29 +360,23 @@
<div>
-<p>The unwinder delegates the decision of whether to stop in a call
- frame to that call frame's language-specific personality function.
- Not all personalities functions guarantee that they will stop to
- perform cleanups: for example, the GNU C++ personality doesn't do
- so unless the exception is actually caught somewhere further up the
- stack. When using this personality to implement EH for a language
- that guarantees that cleanups will always be run, be sure to
- indicate a catch-all in the
- <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> call
- rather than just cleanups.</p>
-
-<p>In order for inlining to behave correctly, landing pads must be
- prepared to handle selector results that they did not originally
- advertise. Suppose that a function catches exceptions of
- type <tt>A</tt>, and it's inlined into a function that catches
- exceptions of type <tt>B</tt>. The inliner will update the
- selector for the inlined landing pad to include the fact
- that <tt>B</tt> is caught. If that landing pad assumes that it
- will only be entered to catch an <tt>A</tt>, it's in for a rude
- surprise. Consequently, landing pads must test for the selector
- results they understand and then resume exception propagation
- with the <a href="#llvm_eh_resume"><tt>llvm.eh.resume</tt></a>
- intrinsic if none of the conditions match.</p>
+<p>The unwinder delegates the decision of whether to stop in a call frame to
+ that call frame's language-specific personality function. Not all unwinders
+ guarantee that they will stop to perform cleanups. For example, the GNU C++
+ unwinder doesn't do so unless the exception is actually caught somewhere
+ further up the stack.</p>
+
+<p>In order for inlining to behave correctly, landing pads must be prepared to
+ handle selector results that they did not originally advertise. Suppose that
+ a function catches exceptions of type <tt>A</tt>, and it's inlined into a
+ function that catches exceptions of type <tt>B</tt>. The inliner will update
+ the <tt>landingpad</tt> instruction for the inlined landing pad to include
+ the fact that <tt>B</tt> is also caught. If that landing pad assumes that it
+ will only be entered to catch an <tt>A</tt>, it's in for a rude awakening.
+ Consequently, landing pads must test for the selector results they understand
+ and then resume exception propagation with the
+ <a href="LangRef.html#i_resume"><tt>resume</tt> instruction</a> if none of
+ the conditions match.</p>
</div>
@@ -412,109 +389,28 @@
<div>
-<p>LLVM uses several intrinsic functions (name prefixed with "llvm.eh") to
+<p>In addition to the
+ <a href="LangRef.html#i_landingpad"><tt>landingpad</tt></a> and
+ <a href="LangRef.html#i_resume"><tt>resume</tt></a> instructions, LLVM uses
+ several intrinsic functions (name prefixed with <i><tt>llvm.eh</tt></i>) to
provide exception handling information at various points in generated
code.</p>
<!-- ======================================================================= -->
<h4>
- <a name="llvm_eh_exception">llvm.eh.exception</a>
-</h4>
-
-<div>
-
-<pre>
- i8* %<a href="#llvm_eh_exception">llvm.eh.exception</a>()
-</pre>
-
-<p>This intrinsic returns a pointer to the exception structure.</p>
-
-</div>
-
-<!-- ======================================================================= -->
-<h4>
- <a name="llvm_eh_selector">llvm.eh.selector</a>
-</h4>
-
-<div>
-
-<pre>
- i32 %<a href="#llvm_eh_selector">llvm.eh.selector</a>(i8*, i8*, ...)
-</pre>
-
-<p>This intrinsic is used to compare the exception with the given type infos,
- filters and cleanups.</p>
-
-<p><a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> takes a
- minimum of three arguments. The first argument is the reference to
- the exception structure. The second argument is a reference to the
- personality function to be used for this try catch sequence. Each
- of the remaining arguments is either a reference to the type info
- for a catch statement, a <a href="#throw_filters">filter</a>
- expression, or the number zero representing
- a <a href="#cleanups">cleanup</a>. The exception is tested against
- the arguments sequentially from first to last. The result of
- the <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> is a
- positive number if the exception matched a type info, a negative
- number if it matched a filter, and zero if it matched a cleanup.
- If nothing is matched, or if only a cleanup is matched, different
- personality functions may or may not cause control to stop at the
- landing pad; see <a href="#restrictions">the restrictions</a> for
- more information. If a type info matched then the selector value
- is the index of the type info in the exception table, which can be
- obtained using the
- <a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a> intrinsic.</p>
-
-<p>If a landing pad containing a call to <tt>llvm.eh.selector</tt> is
- inlined into an <tt>invoke</tt> instruction, the selector arguments
- for the outer landing pad are appended to those of the inlined
- landing pad. Consequently, landing pads must be written to ignore
- selector values that they did not originally advertise.</p>
-
-</div>
-
-<!-- ======================================================================= -->
-<h4>
<a name="llvm_eh_typeid_for">llvm.eh.typeid.for</a>
</h4>
<div>
<pre>
- i32 %<a href="#llvm_eh_typeid_for">llvm.eh.typeid.for</a>(i8*)
+ i32 @llvm.eh.typeid.for(i8* %type_info)
</pre>
<p>This intrinsic returns the type info index in the exception table of the
current function. This value can be used to compare against the result
- of <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>. The single
- argument is a reference to a type info.</p>
-
-</div>
-
-<!-- ======================================================================= -->
-<h4>
- <a name="llvm_eh_resume">llvm.eh.resume</a>
-</h4>
-
-<div>
-
-<pre>
- void %<a href="#llvm_eh_resume">llvm.eh.resume</a>(i8*, i32) noreturn
-</pre>
-
-<p>This intrinsic is used to resume propagation of an exception after
- landing at a landing pad. The first argument should be the result
- of <a href="#llvm_eh_exception">llvm.eh.exception</a> for that
- landing pad, and the second argument should be the result of
- <a href="#llvm_eh_selector">llvm.eh.selector</a>. When a call to
- this intrinsic is inlined into an invoke, the call is transformed
- into a branch to the invoke's unwind destination, using its
- arguments in place of the calls
- to <a href="#llvm_eh_exception">llvm.eh.exception</a> and
- <a href="#llvm_eh_selector">llvm.eh.selector</a> there.</p>
-
-<p>This intrinsic is not implicitly <tt>nounwind</tt>; calls to it
- will always throw. It may not be invoked.</p>
+ of <a href="LangRef.html#i_landingpad"><tt>landingpad</tt> instruction</a>.
+ The single argument is a reference to a type info.</p>
</div>
@@ -526,16 +422,16 @@
<div>
<pre>
- i32 %<a href="#llvm_eh_sjlj_setjmp">llvm.eh.sjlj.setjmp</a>(i8*)
+ i32 @llvm.eh.sjlj.setjmp(i8* %setjmp_buf)
</pre>
-<p>The SJLJ exception handling uses this intrinsic to force register saving for
- the current function and to store the address of the following instruction
- for use as a destination address by <a href="#llvm_eh_sjlj_longjmp">
- <tt>llvm.eh.sjlj.longjmp</tt></a>. The buffer format and the overall
- functioning of this intrinsic is compatible with the GCC
- <tt>__builtin_setjmp</tt> implementation, allowing code built with the
- two compilers to interoperate.</p>
+<p>For SJLJ based exception handling, this intrinsic forces register saving for
+ the current function and stores the address of the following instruction for
+ use as a destination address
+ by <a href="#llvm_eh_sjlj_longjmp"><tt>llvm.eh.sjlj.longjmp</tt></a>. The
+ buffer format and the overall functioning of this intrinsic is compatible
+ with the GCC <tt>__builtin_setjmp</tt> implementation allowing code built
+ with the clang and GCC to interoperate.</p>
<p>The single parameter is a pointer to a five word buffer in which the calling
context is saved. The front end places the frame pointer in the first word,
@@ -555,16 +451,15 @@
<div>
<pre>
- void %<a href="#llvm_eh_sjlj_longjmp">llvm.eh.sjlj.setjmp</a>(i8*)
+ void @llvm.eh.sjlj.longjmp(i8* %setjmp_buf)
</pre>
-<p>The <a href="#llvm_eh_sjlj_longjmp"><tt>llvm.eh.sjlj.longjmp</tt></a>
- intrinsic is used to implement <tt>__builtin_longjmp()</tt> for SJLJ
- style exception handling. The single parameter is a pointer to a
- buffer populated by <a href="#llvm_eh_sjlj_setjmp">
- <tt>llvm.eh.sjlj.setjmp</tt></a>. The frame pointer and stack pointer
- are restored from the buffer, then control is transferred to the
- destination address.</p>
+<p>For SJLJ based exception handling, the <tt>llvm.eh.sjlj.longjmp</tt>
+ intrinsic is used to implement <tt>__builtin_longjmp()</tt>. The single
+ parameter is a pointer to a buffer populated
+ by <a href="#llvm_eh_sjlj_setjmp"><tt>llvm.eh.sjlj.setjmp</tt></a>. The frame
+ pointer and stack pointer are restored from the buffer, then control is
+ transferred to the destination address.</p>
</div>
<!-- ======================================================================= -->
@@ -575,14 +470,13 @@
<div>
<pre>
- i8* %<a href="#llvm_eh_sjlj_lsda">llvm.eh.sjlj.lsda</a>()
+ i8* @llvm.eh.sjlj.lsda()
</pre>
-<p>Used for SJLJ based exception handling, the <a href="#llvm_eh_sjlj_lsda">
- <tt>llvm.eh.sjlj.lsda</tt></a> intrinsic returns the address of the Language
- Specific Data Area (LSDA) for the current function. The SJLJ front-end code
- stores this address in the exception handling function context for use by the
- runtime.</p>
+<p>For SJLJ based exception handling, the <tt>llvm.eh.sjlj.lsda</tt> intrinsic
+ returns the address of the Language Specific Data Area (LSDA) for the current
+ function. The SJLJ front-end code stores this address in the exception
+ handling function context for use by the runtime.</p>
</div>
@@ -594,13 +488,13 @@
<div>
<pre>
- void %<a href="#llvm_eh_sjlj_callsite">llvm.eh.sjlj.callsite</a>(i32)
+ void @llvm.eh.sjlj.callsite(i32 %call_site_num)
</pre>
-<p>For SJLJ based exception handling, the <a href="#llvm_eh_sjlj_callsite">
- <tt>llvm.eh.sjlj.callsite</tt></a> intrinsic identifies the callsite value
- associated with the following invoke instruction. This is used to ensure
- that landing pad entries in the LSDA are generated in the matching order.</p>
+<p>For SJLJ based exception handling, the <tt>llvm.eh.sjlj.callsite</tt>
+ intrinsic identifies the callsite value associated with the
+ following <tt>invoke</tt> instruction. This is used to ensure that landing
+ pad entries in the LSDA are generated in matching order.</p>
</div>
@@ -612,12 +506,12 @@
<div>
<pre>
- void %<a href="#llvm_eh_sjlj_dispatchsetup">llvm.eh.sjlj.dispatchsetup</a>(i32)
+ void @llvm.eh.sjlj.dispatchsetup(i32 %dispatch_value)
</pre>
-<p>For SJLJ based exception handling, the <a href="#llvm_eh_sjlj_dispatchsetup">
- <tt>llvm.eh.sjlj.dispatchsetup</tt></a> intrinsic is used by targets to do
- any unwind-edge setup they need. By default, no action is taken. </p>
+<p>For SJLJ based exception handling, the <tt>llvm.eh.sjlj.dispatchsetup</tt>
+ intrinsic is used by targets to do any unwind edge setup they need. By
+ default, no action is taken.</p>
</div>
@@ -631,7 +525,7 @@
<div>
<p>There are two tables that are used by the exception handling runtime to
- determine which actions should take place when an exception is thrown.</p>
+ determine which actions should be taken when an exception is thrown.</p>
<!-- ======================================================================= -->
<h3>
@@ -641,13 +535,13 @@
<div>
<p>An exception handling frame <tt>eh_frame</tt> is very similar to the unwind
- frame used by dwarf debug info. The frame contains all the information
+ frame used by DWARF debug info. The frame contains all the information
necessary to tear down the current frame and restore the state of the prior
- frame. There is an exception handling frame for each function in a compile
+ frame. There is an exception handling frame for each function in a compile
unit, plus a common exception handling frame that defines information common
to all functions in the unit.</p>
-<p>Todo - Table details here.</p>
+<!-- Todo - Table details here. -->
</div>
@@ -659,31 +553,17 @@
<div>
<p>An exception table contains information about what actions to take when an
- exception is thrown in a particular part of a function's code. There is one
- exception table per function except leaf routines and functions that have
- only calls to non-throwing functions will not need an exception table.</p>
+ exception is thrown in a particular part of a function's code. There is one
+ exception table per function, except leaf functions and functions that have
+ calls only to non-throwing functions. They do not need an exception
+ table.</p>
-<p>Todo - Table details here.</p>
+<!-- Todo - Table details here. -->
</div>
</div>
-<!-- ======================================================================= -->
-<h2>
- <a name="todo">ToDo</a>
-</h2>
-
-<div>
-
-<ol>
-
- <li>Testing/Testing/Testing.</li>
-
-</ol>
-
-</div>
-
<!-- *********************************************************************** -->
<hr>
@@ -695,7 +575,7 @@
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-05-28 09:45:59 +0200 (Sat, 28 May 2011) $
+ Last modified: $Date: 2011-09-27 22:16:57 +0200 (Tue, 27 Sep 2011) $
</address>
</body>
diff --git a/docs/FAQ.html b/docs/FAQ.html
index 20ba1d5..341f1c9 100644
--- a/docs/FAQ.html
+++ b/docs/FAQ.html
@@ -72,9 +72,6 @@
<li>After Subversion update, rebuilding gives the error "No rule to make
target".</li>
- <li><a href="#llvmc">The <tt>llvmc</tt> program gives me errors/doesn't
- work.</a></li>
-
<li><a href="#srcdir-objdir">When I compile LLVM-GCC with srcdir == objdir,
it fails. Why?</a></li>
</ol></li>
@@ -420,16 +417,6 @@ Stop.
</div>
<div class="question">
-<p><a name="llvmc">The <tt>llvmc</tt> program gives me errors/doesn't
- work.</a></p>
-</div>
-
-<div class="answer">
-<p><tt>llvmc</tt> is experimental and isn't really supported. We suggest
- using <tt>llvm-gcc</tt> instead.</p>
-</div>
-
-<div class="question">
<p><a name="srcdir-objdir">When I compile LLVM-GCC with srcdir == objdir, it
fails. Why?</a></p>
</div>
@@ -540,10 +527,7 @@ Stop.
<p>Currently, there isn't much. LLVM supports an intermediate representation
which is useful for code representation but will not support the high level
(abstract syntax tree) representation needed by most compilers. There are no
- facilities for lexical nor semantic analysis. There is, however, a <i>mostly
- implemented</i> configuration-driven
- <a href="CompilerDriver.html">compiler driver</a> which simplifies the task
- of running optimizations, linking, and executable generation.</p>
+ facilities for lexical nor semantic analysis.</p>
</div>
<div class="question">
@@ -933,7 +917,7 @@ F.i:
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-19 01:59:50 +0200 (Tue, 19 Apr 2011) $
+ Last modified: $Date: 2011-09-20 02:42:28 +0200 (Tue, 20 Sep 2011) $
</address>
</body>
diff --git a/docs/GarbageCollection.html b/docs/GarbageCollection.html
index 13a3714..10bc663 100644
--- a/docs/GarbageCollection.html
+++ b/docs/GarbageCollection.html
@@ -290,10 +290,8 @@ doing so is very simple. (This code is heavily commented to help you
understand the data structure, but there are only 20 lines of meaningful
code.)</p>
-</div>
-
-<div class="doc_code"><pre
->/// @brief The map for a single function's stack frame. One of these is
+<pre class="doc_code">
+/// @brief The map for a single function's stack frame. One of these is
/// compiled as constant data into the executable for each function.
///
/// Storage of metadata values is elided if the %metadata parameter to
@@ -338,7 +336,9 @@ void visitGCRoots(void (*Visitor)(void **Root, const void *Meta)) {
for (unsigned e = R->Map->NumRoots; i != e; ++i)
Visitor(&amp;R->Roots[i], NULL);
}
-}</pre></div>
+}</pre>
+
+</div>
<!-- ======================================================================= -->
<h3>
@@ -395,12 +395,12 @@ program.</p>
<a name="gcattr">Specifying GC code generation: <tt>gc "..."</tt></a>
</h3>
+<div>
+
<div class="doc_code"><tt>
define <i>ty</i> @<i>name</i>(...) <span style="text-decoration: underline">gc "<i>name</i>"</span> { ...
</tt></div>
-<div>
-
<p>The <tt>gc</tt> function attribute is used to specify the desired GC style
to the compiler. Its programmatic equivalent is the <tt>setGC</tt> method of
<tt>Function</tt>.</p>
@@ -420,12 +420,12 @@ programs that use different garbage collection algorithms (or none at all).</p>
<a name="gcroot">Identifying GC roots on the stack: <tt>llvm.gcroot</tt></a>
</h3>
+<div>
+
<div class="doc_code"><tt>
void @llvm.gcroot(i8** %ptrloc, i8* %metadata)
</tt></div>
-<div>
-
<p>The <tt>llvm.gcroot</tt> intrinsic is used to inform LLVM that a stack
variable references an object on the heap and is to be tracked for garbage
collection. The exact impact on generated code is specified by a <a
@@ -453,7 +453,7 @@ the stack frame.</p>
<p>Consider the following fragment of Java code:</p>
-<pre>
+<pre class="doc_code">
{
Object X; // A null-initialized reference to an object
...
@@ -463,7 +463,7 @@ the stack frame.</p>
<p>This block (which may be located in the middle of a function or in a loop
nest), could be compiled to this LLVM code:</p>
-<pre>
+<pre class="doc_code">
Entry:
;; In the entry block for the function, allocate the
;; stack space for X, which is an LLVM pointer.
@@ -537,12 +537,12 @@ are used.</p>
<a name="gcwrite">Write barrier: <tt>llvm.gcwrite</tt></a>
</h4>
+<div>
+
<div class="doc_code"><tt>
void @llvm.gcwrite(i8* %value, i8* %object, i8** %derived)
</tt></div>
-<div>
-
<p>For write barriers, LLVM provides the <tt>llvm.gcwrite</tt> intrinsic
function. It has exactly the same semantics as a non-volatile <tt>store</tt> to
the derived pointer (the third argument). The exact code generated is specified
@@ -559,12 +559,12 @@ implement reference counting.</p>
<a name="gcread">Read barrier: <tt>llvm.gcread</tt></a>
</h4>
+<div>
+
<div class="doc_code"><tt>
i8* @llvm.gcread(i8* %object, i8** %derived)<br>
</tt></div>
-<div>
-
<p>For read barriers, LLVM provides the <tt>llvm.gcread</tt> intrinsic function.
It has exactly the same semantics as a non-volatile <tt>load</tt> from the
derived pointer (the second argument). The exact code generated is specified by
@@ -1379,7 +1379,7 @@ Fergus Henderson. International Symposium on Memory Management 2002.</p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-08-12 08:17:17 +0200 (Fri, 12 Aug 2011) $
</address>
</body>
diff --git a/docs/GettingStarted.html b/docs/GettingStarted.html
index cc5c59e..e198e02 100644
--- a/docs/GettingStarted.html
+++ b/docs/GettingStarted.html
@@ -441,13 +441,13 @@ href="GCCFEBuildInstrs.html">try to compile it</a> on your platform.</p>
<tr>
<td><a href="http://www.gnu.org/software/autoconf/">GNU Autoconf</a></td>
- <td>2.60</td>
+ <td>2.61</td>
<td>Configuration script builder<sup><a href="#sf4">4</a></sup></td>
</tr>
<tr>
<td><a href="http://www.gnu.org/software/automake/">GNU Automake</a></td>
- <td>1.9.6</td>
+ <td>1.10</td>
<td>aclocal macro generator<sup><a href="#sf4">4</a></sup></td>
</tr>
@@ -471,8 +471,8 @@ href="GCCFEBuildInstrs.html">try to compile it</a> on your platform.</p>
<li><a name="sf3">Only needed if you want to run the automated test
suite in the <tt>llvm/test</tt> directory.</a></li>
<li><a name="sf4">If you want to make changes to the configure scripts,
- you will need GNU autoconf (2.60), and consequently, GNU M4 (version 1.4
- or higher). You will also need automake (1.9.6). We only use aclocal
+ you will need GNU autoconf (2.61), and consequently, GNU M4 (version 1.4
+ or higher). You will also need automake (1.10). We only use aclocal
from that package.</a></li>
</ol>
</div>
@@ -747,6 +747,7 @@ revision), you can checkout it from the '<tt>tags</tt>' directory (instead of
subdirectories of the '<tt>tags</tt>' directory:</p>
<ul>
+<li>Release 3.0: <b>RELEASE_30/final</b></li>
<li>Release 2.9: <b>RELEASE_29/final</b></li>
<li>Release 2.8: <b>RELEASE_28</b></li>
<li>Release 2.7: <b>RELEASE_27</b></li>
@@ -802,12 +803,152 @@ instructions</a> to successfully get and build the LLVM GCC front-end.</p>
now mirrors reflect only <tt>trunk</tt> for each project. You can do the
read-only GIT clone of LLVM via:</p>
-<pre>
-% git clone http://llvm.org/git/llvm.git
+<pre class="doc_code">
+git clone http://llvm.org/git/llvm.git
+</pre>
+
+<p>If you want to check out clang too, run:</p>
+
+<pre class="doc_code">
+git clone http://llvm.org/git/llvm.git
+cd llvm/tools
+git clone http://llvm.org/git/clang.git
+</pre>
+
+<p>
+Since the upstream repository is in Subversion, you should use
+<tt>&quot;git pull --rebase&quot;</tt>
+instead of <tt>&quot;git pull&quot;</tt> to avoid generating a non-linear
+history in your clone.
+To configure <tt>&quot;git pull&quot;</tt> to pass <tt>--rebase</tt> by default
+on the master branch, run the following command:
+</p>
+
+<pre class="doc_code">
+git config branch.master.rebase true
+</pre>
+
+<h4>Sending patches with Git</h4>
+<div>
+<p>
+Please read <a href="DeveloperPolicy.html#patches">Developer Policy</a>, too.
+</p>
+
+<p>
+Assume <tt>master</tt> points the upstream and <tt>mybranch</tt> points your
+working branch, and <tt>mybranch</tt> is rebased onto <tt>master</tt>.
+At first you may check sanity of whitespaces:
+</p>
+
+<pre class="doc_code">
+git diff --check master..mybranch
+</pre>
+
+<p>
+The easiest way to generate a patch is as below:
+</p>
+
+<pre class="doc_code">
+git diff master..mybranch &gt; /path/to/mybranch.diff
+</pre>
+
+<p>
+It is a little different from svn-generated diff. git-diff-generated diff has
+prefixes like <tt>a/</tt> and <tt>b/</tt>. Don't worry, most developers might
+know it could be accepted with <tt>patch -p1 -N</tt>.
+</p>
+
+<p>
+But you may generate patchset with git-format-patch. It generates
+by-each-commit patchset. To generate patch files to attach to your article:
+</p>
+
+<pre class="doc_code">
+git format-patch --no-attach master..mybranch -o /path/to/your/patchset
+</pre>
+
+<p>
+If you would like to send patches directly, you may use git-send-email or
+git-imap-send. Here is an example to generate the patchset in Gmail's [Drafts].
+</p>
+
+<pre class="doc_code">
+git format-patch --attach master..mybranch --stdout | git imap-send
+</pre>
+
+<p>
+Then, your .git/config should have [imap] sections.
+</p>
+
+<pre class="doc_code">
+[imap]
+ host = imaps://imap.gmail.com
+ user = <em>your.gmail.account</em>@gmail.com
+ pass = <em>himitsu!</em>
+ port = 993
+ sslverify = false
+; in English
+ folder = "[Gmail]/Drafts"
+; example for Japanese, "Modified UTF-7" encoded.
+ folder = "[Gmail]/&amp;Tgtm+DBN-"
</pre>
</div>
+<h4>For developers to work with git-svn</h4>
+<div>
+
+<p>To set up clone from which you can submit code using
+ <tt>git-svn</tt>, run:</p>
+
+<pre class="doc_code">
+git clone http://llvm.org/git/llvm.git
+cd llvm
+git svn init https://llvm.org/svn/llvm-project/llvm/trunk --username=&lt;username>
+git config svn-remote.svn.fetch :refs/remotes/origin/master
+git svn rebase -l # -l avoids fetching ahead of the git mirror.
+
+# If you have clang too:
+cd tools
+git clone http://llvm.org/git/clang.git
+cd clang
+git svn init https://llvm.org/svn/llvm-project/cfe/trunk --username=&lt;username>
+git config svn-remote.svn.fetch :refs/remotes/origin/master
+git svn rebase -l
+</pre>
+
+<p>To update this clone without generating git-svn tags that conflict
+with the upstream git repo, run:</p>
+
+<pre class="doc_code">
+git fetch && (cd tools/clang && git fetch) # Get matching revisions of both trees.
+git checkout master
+git svn rebase -l
+(cd tools/clang &&
+ git checkout master &&
+ git svn rebase -l)
+</pre>
+
+<p>This leaves your working directories on their master branches, so
+you'll need to <tt>checkout</tt> each working branch individually and
+<tt>rebase</tt> it on top of its parent branch. (Note: This script is
+intended for relative newbies to git. If you have more experience,
+you can likely improve on it.)</p>
+
+<p>The git-svn metadata can get out of sync after you mess around with
+branches and <code>dcommit</code>. When that happens, <code>git svn
+dcommit</code> stops working, complaining about files with uncommitted
+changes. The fix is to rebuild the metadata:</p>
+
+<pre class="doc_code">
+rm -rf .git/svn
+git svn rebase -l
+</pre>
+
+</div>
+
+</div>
+
<!-- ======================================================================= -->
<h3>
<a name="installcf">Install the GCC Front End</a>
@@ -1362,13 +1503,9 @@ different <a href="#tools">tools</a>.</p>
at runtime in both interpreted and JIT compiled fashions.</dd>
<dt><tt><b>llvm/lib/Support/</b></tt></dt>
- <dd> This directory contains the source code that corresponds to the header
- files located in <tt>llvm/include/Support/</tt>.</dd>
-
- <!--FIXME: obsoleted -->
- <dt><tt><b>llvm/lib/System/</b></tt></dt>
- <dd>This directory contains the operating system abstraction layer that
- shields LLVM from platform-specific coding.</dd>
+ <dd> This directory contains the source code that corresponds to the header
+ files located in <tt>llvm/include/ADT/</tt>
+ and <tt>llvm/include/Support/</tt>.</dd>
</dl>
</div>
@@ -1455,16 +1592,6 @@ information is in the <a href="CommandGuide/index.html">Command Guide</a>.</p>
href="HowToSubmitABug.html">HowToSubmitABug.html</a> for more information
on using <tt>bugpoint</tt>.</dd>
- <dt><tt><b>llvmc</b></tt></dt>
- <dd>The LLVM Compiler Driver. This program can
- be configured to utilize both LLVM and non-LLVM compilation tools to enable
- pre-processing, translation, optimization, assembly, and linking of programs
- all from one command line. <tt>llvmc</tt> also takes care of processing the
- dependent libraries found in bitcode. This reduces the need to get the
- traditional <tt>-l&lt;name&gt;</tt> options right on the command line. Please
- note that this tool, while functional, is still experimental and not feature
- complete.</dd>
-
<dt><tt><b>llvm-ar</b></tt></dt>
<dd>The archiver produces an archive containing
the given LLVM bitcode files, optionally with an index for faster
@@ -1480,9 +1607,9 @@ information is in the <a href="CommandGuide/index.html">Command Guide</a>.</p>
<dt><tt><b>llvm-ld</b></tt></dt>
<dd><tt>llvm-ld</tt> is a general purpose and extensible linker for LLVM.
- This is the linker invoked by <tt>llvmc</tt>. It performs standard link time
- optimizations and allows optimization modules to be loaded and run so that
- language specific optimizations can be applied at link time.</dd>
+ It performs standard link time optimizations and allows optimization
+ modules to be loaded and run so that language specific optimizations can
+ be applied at link time.</dd>
<dt><tt><b>llvm-link</b></tt></dt>
<dd><tt>llvm-link</tt>, not surprisingly, links multiple LLVM modules into
@@ -1743,7 +1870,7 @@ out:</p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.x10sys.com/rspencer/">Reid Spencer</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-10-17 08:31:32 +0200 (Mon, 17 Oct 2011) $
</address>
</body>
</html>
diff --git a/docs/GoldPlugin.html b/docs/GoldPlugin.html
index e25c457..92ba411 100644
--- a/docs/GoldPlugin.html
+++ b/docs/GoldPlugin.html
@@ -75,6 +75,7 @@ placed.
<h2><a name="usage">Usage</a></h2>
<!--=========================================================================-->
<div>
+
<p>The linker takes a <tt>-plugin</tt> option that points to the path of
the plugin <tt>.so</tt> file. To find out what link command <tt>gcc</tt>
would run in a given situation, run <tt>gcc -v <em>[...]</em></tt> and look
@@ -82,19 +83,21 @@ placed.
<tt>ld-new -plugin /path/to/LLVMgold.so</tt> to test it out. Once you're
ready to switch to using gold, backup your existing <tt>/usr/bin/ld</tt>
then replace it with <tt>ld-new</tt>.</p>
- <p>You can produce bitcode files from <tt>llvm-gcc</tt> using
+
+ <p>You can produce bitcode files from <tt>clang</tt> using
<tt>-emit-llvm</tt> or <tt>-flto</tt>, or the <tt>-O4</tt> flag which is
synonymous with <tt>-O3 -flto</tt>.</p>
- <p><tt>llvm-gcc</tt> has a <tt>-use-gold-plugin</tt> option which looks
- for the gold plugin in the same directories as it looks for <tt>cc1</tt> and
- passes the <tt>-plugin</tt> option to ld. It will not look for an alternate
+
+ <p><tt>Clang</tt> has a <tt>-use-gold-plugin</tt> option which looks for the
+ gold plugin in the same directories as it looks for <tt>cc1</tt> and passes
+ the <tt>-plugin</tt> option to <tt>ld</tt>. It will not look for an alternate
linker, which is why you need gold to be the installed system linker in your
path.</p>
+
<p>If you want <tt>ar</tt> and <tt>nm</tt> to work seamlessly as well, install
<tt>LLVMgold.so</tt> to <tt>/usr/lib/bfd-plugins</tt>. If you built your
own gold, be sure to install the <tt>ar</tt> and <tt>nm-new</tt> you built to
- <tt>/usr/bin</tt>.
- <p>
+ <tt>/usr/bin</tt>.<p>
<!-- ======================================================================= -->
<h3>
@@ -137,11 +140,12 @@ void foo4(void) {
}
--- command lines ---
-$ llvm-gcc -flto a.c -c -o a.o # &lt;-- a.o is LLVM bitcode file
+$ clang -flto a.c -c -o a.o # &lt;-- a.o is LLVM bitcode file
$ ar q a.a a.o # &lt;-- a.a is an archive with LLVM bitcode
-$ llvm-gcc b.c -c -o b.o # &lt;-- b.o is native object file
-$ llvm-gcc -use-gold-plugin a.a b.o -o main # &lt;-- link with LLVMgold plugin
+$ clang b.c -c -o b.o # &lt;-- b.o is native object file
+$ clang -use-gold-plugin a.a b.o -o main # &lt;-- link with LLVMgold plugin
</pre>
+
<p>Gold informs the plugin that foo3 is never referenced outside the IR,
leading LLVM to delete that function. However, unlike in the
<a href="LinkTimeOptimization.html#example1">libLTO
@@ -158,20 +162,21 @@ $ llvm-gcc -use-gold-plugin a.a b.o -o main # &lt;-- link with LLVMgold plugin
</h2>
<!--=========================================================================-->
<div>
- <p>Once your system <tt>ld</tt>, <tt>ar</tt> and <tt>nm</tt> all support LLVM
- bitcode, everything is in place for an easy to use LTO build of autotooled
- projects:</p>
+ <p>Once your system <tt>ld</tt>, <tt>ar</tt>, and <tt>nm</tt> all support LLVM
+ bitcode, everything is in place for an easy to use LTO build of autotooled
+ projects:</p>
+
<ul>
<li>Follow the instructions <a href="#build">on how to build LLVMgold.so</a>.</li>
<li>Install the newly built binutils to <tt>$PREFIX</tt></li>
<li>Copy <tt>Release/lib/LLVMgold.so</tt> to
- <tt>$PREFIX/libexec/gcc/x86_64-unknown-linux-gnu/4.2.1/</tt> and
- <tt>$PREFIX/lib/bfd-plugins/</tt></li>
- <li>Set environment variables (<tt>$PREFIX</tt> is where you installed llvm-gcc and
- binutils):
- <pre class="doc_code">
-export CC="$PREFIX/bin/llvm-gcc -use-gold-plugin"
-export CXX="$PREFIX/bin/llvm-g++ -use-gold-plugin"
+ <tt>$PREFIX/libexec/gcc/x86_64-unknown-linux-gnu/4.2.1/</tt> and
+ <tt>$PREFIX/lib/bfd-plugins/</tt></li>
+ <li>Set environment variables (<tt>$PREFIX</tt> is where you installed clang and
+ binutils):
+<pre class="doc_code">
+export CC="$PREFIX/bin/clang -use-gold-plugin"
+export CXX="$PREFIX/bin/clang++ -use-gold-plugin"
export AR="$PREFIX/bin/ar"
export NM="$PREFIX/bin/nm"
export RANLIB=/bin/true #ranlib is not needed, and doesn't support .bc files in .a
@@ -179,18 +184,22 @@ export CFLAGS="-O4"
</pre>
</li>
<li>Or you can just set your path:
- <pre class="doc_code">
+<pre class="doc_code">
export PATH="$PREFIX/bin:$PATH"
-export CC="llvm-gcc -use-gold-plugin"
-export CXX="llvm-g++ -use-gold-plugin"
+export CC="clang -use-gold-plugin"
+export CXX="clang++ -use-gold-plugin"
export RANLIB=/bin/true
export CFLAGS="-O4"
-</pre>
- </li>
- <li>Configure &amp; build the project as usual: <tt>./configure &amp;&amp; make &amp;&amp; make check</tt> </li>
+</pre></li>
+ <li>Configure &amp; build the project as usual:
+<pre class="doc_code">
+% ./configure &amp;&amp; make &amp;&amp; make check
+</pre></li>
</ul>
- <p> The environment variable settings may work for non-autotooled projects
- too, but you may need to set the <tt>LD</tt> environment variable as well.</p>
+
+ <p>The environment variable settings may work for non-autotooled projects
+ too, but you may need to set the <tt>LD</tt> environment variable as
+ well.</p>
</div>
<!--=========================================================================-->
diff --git a/docs/HowToReleaseLLVM.html b/docs/HowToReleaseLLVM.html
index f52f326..c46ed5aa 100644
--- a/docs/HowToReleaseLLVM.html
+++ b/docs/HowToReleaseLLVM.html
@@ -29,7 +29,7 @@
<div>
<p>This document contains information about successfully releasing LLVM &mdash;
- including subprojects: e.g., <tt>llvm-gcc</tt> and <tt>clang</tt> &mdash; to
+ including subprojects: e.g., <tt>clang</tt> and <tt>dragonegg</tt> &mdash; to
the public. It is the Release Manager's responsibility to ensure that a high
quality build of LLVM is released.</p>
@@ -92,7 +92,6 @@
<ol>
<li><a href="#dist">Build the LLVM Source Distributions</a></li>
<li><a href="#build">Build LLVM</a></li>
- <li><a href="#llvmgccbin">Build the LLVM-GCC Binary Distribution</a></li>
<li><a href="#clangbin">Build the Clang Binary Distribution</a></li>
<li><a href="#target-build">Target Specific Build Details</a></li>
</ol>
@@ -100,7 +99,6 @@
<li><a href="#release-qualify">Release Qualification Criteria</a>
<ol>
<li><a href="#llvm-qualify">Qualify LLVM</a></li>
- <li><a href="#llvmgcc-qualify">Qualify LLVM-GCC</a></li>
<li><a href="#clang-qualify">Qualify Clang</a></li>
<li><a href="#targets">Specific Target Qualification Details</a></li>
</ol>
@@ -149,25 +147,25 @@
<li><p>Verify that the current Subversion trunk is in decent shape by
examining nightly tester and buildbot results.</p></li>
- <li><p>Create the release branch for <tt>llvm</tt>, <tt>llvm-gcc-4.2</tt>,
- <tt>clang</tt>, and the <tt>test-suite</tt> from the last known good
- revision. The branch's name is <tt>release_XY</tt>, where <tt>X</tt> is
- the major and <tt>Y</tt> the minor release numbers. The branches should be
- created using the following commands:</p>
+ <li><p>Create the release branch for <tt>llvm</tt>, <tt>clang</tt>,
+ the <tt>test-suite</tt>, and <tt>dragonegg</tt> from the last known good
+ revision. The branch's name is <tt>release_<i>XY</i></tt>,
+ where <tt>X</tt> is the major and <tt>Y</tt> the minor release
+ numbers. The branches should be created using the following commands:</p>
<div class="doc_code">
<pre>
$ svn copy https://llvm.org/svn/llvm-project/llvm/trunk \
https://llvm.org/svn/llvm-project/llvm/branches/release_<i>XY</i>
-$ svn copy https://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk \
- https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_<i>XY</i>
+$ svn copy https://llvm.org/svn/llvm-project/cfe/trunk \
+ https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i>
+
+$ svn copy https://llvm.org/svn/llvm-project/dragonegg/trunk \
+ https://llvm.org/svn/llvm-project/dragonegg/branches/release_<i>XY</i>
$ svn copy https://llvm.org/svn/llvm-project/test-suite/trunk \
https://llvm.org/svn/llvm-project/test-suite/branches/release_<i>XY</i>
-
-$ svn copy https://llvm.org/svn/llvm-project/cfe/trunk \
- https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i>
</pre>
</div></li>
@@ -182,11 +180,11 @@ $ svn copy https://llvm.org/svn/llvm-project/cfe/trunk \
<pre>
$ svn co https://llvm.org/svn/llvm-project/llvm/branches/release_<i>XY</i> llvm-<i>X.Y</i>
-$ svn co https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_<i>XY</i> llvm-gcc-4.2-<i>X.Y</i>
+$ svn co https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> clang-<i>X.Y</i>
-$ svn co https://llvm.org/svn/llvm-project/test-suite/branches/release_<i>XY</i> test-suite-<i>X.Y</i>
+$ svn co https://llvm.org/svn/llvm-project/dragonegg/branches/release_<i>XY</i> dragonegg-<i>X.Y</i>
-$ svn co https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> clang-<i>X.Y</i>
+$ svn co https://llvm.org/svn/llvm-project/test-suite/branches/release_<i>XY</i> test-suite-<i>X.Y</i>
</pre>
</div></li>
</ol>
@@ -214,10 +212,10 @@ $ svn co https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> clang-
<div>
-<p>Create release candidates for <tt>llvm</tt>, <tt>llvm-gcc</tt>,
- <tt>clang</tt>, and the LLVM <tt>test-suite</tt> by tagging the branch with
- the respective release candidate number. For instance, to create <b>Release
- Candidate 1</b> you would issue the following commands:</p>
+<p>Create release candidates for <tt>llvm</tt>, <tt>clang</tt>,
+ <tt>dragonegg</tt>, and the LLVM <tt>test-suite</tt> by tagging the branch
+ with the respective release candidate number. For instance, to
+ create <b>Release Candidate 1</b> you would issue the following commands:</p>
<div class="doc_code">
<pre>
@@ -225,17 +223,17 @@ $ svn mkdir https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_<i>XY</i>
$ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_<i>XY</i> \
https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_<i>XY</i>/rc1
-$ svn mkdir https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_<i>XY</i>
-$ svn copy https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_<i>XY</i> \
- https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_<i>XY</i>/rc1
+$ svn mkdir https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>
+$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> \
+ https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>/rc1
+
+$ svn mkdir https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_<i>XY</i>
+$ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_<i>XY</i> \
+ https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_<i>XY</i>/rc1
$ svn mkdir https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_<i>XY</i>
$ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_<i>XY</i> \
https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_<i>XY</i>/rc1
-
-$ svn mkdir https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>
-$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> \
- https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>/rc1
</pre>
</div>
@@ -251,14 +249,14 @@ $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> \
<div class="doc_code">
<pre>
$ svn export https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_<i>XY</i>/rc1 llvm-<i>X.Y</i>rc1
-$ svn export https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_<i>XY</i>/rc1 llvm-gcc4.2-<i>X.Y</i>rc1
-$ svn export https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_<i>XY</i>/rc1 llvm-test-<i>X.Y</i>rc1
$ svn export https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>/rc1 clang-<i>X.Y</i>rc1
+$ svn export https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_<i>XY</i>/rc1 dragonegg-<i>X.Y</i>rc1
+$ svn export https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_<i>XY</i>/rc1 llvm-test-<i>X.Y</i>rc1
$ tar -cvf - llvm-<i>X.Y</i>rc1 | gzip &gt; llvm-<i>X.Y</i>rc1.src.tar.gz
-$ tar -cvf - llvm-test-<i>X.Y</i>rc1 | gzip &gt; llvm-test-<i>X.Y</i>rc1.src.tar.gz
-$ tar -cvf - llvm-gcc4.2-<i>X.Y</i>rc1 | gzip &gt; llvm-gcc-4.2-<i>X.Y</i>rc1.src.tar.gz
$ tar -cvf - clang-<i>X.Y</i>rc1 | gzip &gt; clang-<i>X.Y</i>rc1.src.tar.gz
+$ tar -cvf - dragonegg-<i>X.Y</i>rc1 | gzip &gt; dragonegg-<i>X.Y</i>rc1.src.tar.gz
+$ tar -cvf - llvm-test-<i>X.Y</i>rc1 | gzip &gt; llvm-test-<i>X.Y</i>rc1.src.tar.gz
</pre>
</div>
@@ -271,7 +269,7 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip &gt; clang-<i>X.Y</i>rc1.src.tar.g
<div>
-<p>The builds of <tt>llvm</tt>, <tt>llvm-gcc</tt>, and <tt>clang</tt>
+<p>The builds of <tt>llvm</tt>, <tt>clang</tt>, and <tt>dragonegg</tt>
<em>must</em> be free of errors and warnings in Debug, Release+Asserts, and
Release builds. If all builds are clean, then the release passes Build
Qualification.</p>
@@ -292,35 +290,7 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip &gt; clang-<i>X.Y</i>rc1.src.tar.g
<p>Build <tt>Debug</tt>, <tt>Release+Asserts</tt>, and <tt>Release</tt> versions
of <tt>llvm</tt> on all supported platforms. Directions to build
- <tt>llvm</tt> are
- <a href="GettingStarted.html#quickstart">here</a>.</p>
-
-</div>
-
-<!-- ======================================================================= -->
-<h4><a name="llvmgccbin">Build the LLVM GCC Binary Distribution</a></h4>
-
-<div>
-
-<p>Creating the <tt>llvm-gcc</tt> binary distribution (Release/Optimized)
- requires performing the following steps for each supported platform:</p>
-
-<ol>
- <li><p>Build the <tt>llvm-gcc</tt> front-end by following the directions in
- the <tt>README.LLVM</tt> file. The front-end must be compiled with C, C++,
- Objective-C (Mac only), Objective-C++ (Mac only), and Fortran
- support.</p></li>
-
- <li><p>Boostrapping must be enabled.</p></li>
-
- <li><p>Be sure to build with <tt>LLVM_VERSION_INFO=X.Y</tt>, where <tt>X</tt>
- is the major and <tt>Y</tt> is the minor release numbers.</p></li>
-
- <li><p>Copy the installation directory to a directory named for the specific
- target. For example on Red Hat Enterprise Linux, the directory would be
- named <tt>llvm-gcc4.2-2.6-x86-linux-RHEL4</tt>. Archive and compress the
- new directory.</p></li>
-</ol>
+ <tt>llvm</tt> are <a href="GettingStarted.html#quickstart">here</a>.</p>
</div>
@@ -337,8 +307,8 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip &gt; clang-<i>X.Y</i>rc1.src.tar.g
<li>Build clang according to the directions
<a href="http://clang.llvm.org/get_started.html">here</a>.</li>
- <li>Build both a debug and release version of clang. The binary will be the
- release build.</lI>
+ <li>Build both a Debug and Release version of clang. The binary will be the
+ Release build.</lI>
<li>Package <tt>clang</tt> (details to follow).</li>
</ol>
@@ -351,18 +321,18 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip &gt; clang-<i>X.Y</i>rc1.src.tar.g
<div>
<p>The table below specifies which compilers are used for each Arch/OS
- combination when qualifying the build of <tt>llvm</tt>, <tt>llvm-gcc</tt>,
- and <tt>clang</tt>.</p>
+ combination when qualifying the build of <tt>llvm</tt>, <tt>clang</tt>,
+ and <tt>dragonegg</tt>.</p>
<table>
- <tr><th>Architecture</th><th>OS</th><th>compiler</th></tr>
- <tr><td>x86-32</td><td>Mac OS 10.5</td><td>gcc 4.0.1</td></tr>
- <tr><td>x86-32</td><td>Linux</td><td>gcc 4.2.X, gcc 4.3.X</td></tr>
- <tr><td>x86-32</td><td>FreeBSD</td><td>gcc 4.2.X</td></tr>
- <tr><td>x86-32</td><td>mingw</td><td>gcc 3.4.5</td></tr>
- <tr><td>x86-64</td><td>Mac OS 10.5</td><td>gcc 4.0.1</td></tr>
- <tr><td>x86-64</td><td>Linux</td><td>gcc 4.2.X, gcc 4.3.X</td></tr>
- <tr><td>x86-64</td><td>FreeBSD</td><td>gcc 4.2.X</td></tr>
+ <tr><th>Architecture</th> <th>OS</th> <th>compiler</th></tr>
+ <tr><td>x86-32</td> <td>Mac OS 10.5</td> <td>gcc 4.0.1</td></tr>
+ <tr><td>x86-32</td> <td>Linux</td> <td>gcc 4.2.X, gcc 4.3.X</td></tr>
+ <tr><td>x86-32</td> <td>FreeBSD</td> <td>gcc 4.2.X</td></tr>
+ <tr><td>x86-32</td> <td>mingw</td> <td>gcc 3.4.5</td></tr>
+ <tr><td>x86-64</td> <td>Mac OS 10.5</td> <td>gcc 4.0.1</td></tr>
+ <tr><td>x86-64</td> <td>Linux</td> <td>gcc 4.2.X, gcc 4.3.X</td></tr>
+ <tr><td>x86-64</td> <td>FreeBSD</td> <td>gcc 4.2.X</td></tr>
</table>
</div>
@@ -394,21 +364,8 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip &gt; clang-<i>X.Y</i>rc1.src.tar.g
<div>
<p>LLVM is qualified when it has a clean test run without a front-end. And it
- has no regressions when using either <tt>llvm-gcc</tt> or <tt>clang</tt> with
- the <tt>test-suite</tt> from the previous release.</p>
-
-</div>
-
-<!-- ======================================================================= -->
-<h4><a name="llvmgcc-qualify">Qualify LLVM-GCC</a></h4>
-
-<div>
-
-<p><tt>LLVM-GCC</tt> is qualified when front-end specific tests in the
- <tt>llvm</tt> regression test suite all pass and there are no regressions in
- the <tt>test-suite</tt>.</p>
-
-<p>We do not use the GCC DejaGNU test suite as release criteria.</p>
+ has no regressions when using either <tt>clang</tt> or <tt>dragonegg</tt>
+ with the <tt>test-suite</tt> from the previous release.</p>
</div>
@@ -429,13 +386,13 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip &gt; clang-<i>X.Y</i>rc1.src.tar.g
<div>
<table>
- <tr><th>Architecture</th><th>OS</th><th>llvm-gcc baseline</th><th>clang baseline</th><th>tests</th></tr>
- <tr><td>x86-32</td><td>Linux</td><td>last release</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
- <tr><td>x86-32</td><td>FreeBSD</td><td>none</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite</td></tr>
- <tr><td>x86-32</td><td>mingw</td><td>last release</td><td>none</td><td>QT</td></tr>
- <tr><td>x86-64</td><td>Mac OS 10.X</td><td>last release</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
- <tr><td>x86-64</td><td>Linux</td><td>last release</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
- <tr><td>x86-64</td><td>FreeBSD</td><td>none</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite</td></tr>
+ <tr><th>Architecture</th> <th>OS</th> <th>clang baseline</th> <th>tests</th></tr>
+ <tr><td>x86-32</td> <td>Linux</td> <td>last release</td> <td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
+ <tr><td>x86-32</td> <td>FreeBSD</td> <td>last release</td> <td>llvm dejagnu, clang tests, test-suite</td></tr>
+ <tr><td>x86-32</td> <td>mingw</td> <td>none</td> <td>QT</td></tr>
+ <tr><td>x86-64</td> <td>Mac OS 10.X</td> <td>last release</td> <td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
+ <tr><td>x86-64</td> <td>Linux</td> <td>last release</td> <td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
+ <tr><td>x86-64</td> <td>FreeBSD</td> <td>last release</td> <td>llvm dejagnu, clang tests, test-suite</td></tr>
</table>
</div>
@@ -452,14 +409,12 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip &gt; clang-<i>X.Y</i>rc1.src.tar.g
<ol>
<li>Download <tt>llvm-<i>X.Y</i></tt>, <tt>llvm-test-<i>X.Y</i></tt>, and the
- appropriate <tt>llvm-gcc</tt> and/or <tt>clang</tt> binary. Build
- LLVM. Run <tt>make check</tt> and the full LLVM test suite (<tt>make
- TEST=nightly report</tt>).</li>
+ appropriate <tt>clang</tt> binary. Build LLVM. Run <tt>make check</tt> and
+ the full LLVM test suite (<tt>make TEST=nightly report</tt>).</li>
<li>Download <tt>llvm-<i>X.Y</i></tt>, <tt>llvm-test-<i>X.Y</i></tt>, and the
- <tt>llvm-gcc</tt> and/or <tt>clang</tt> source. Compile everything. Run
- <tt>make check</tt> and the full LLVM test suite (<tt>make TEST=nightly
- report</tt>).</li>
+ <tt>clang</tt> sources. Compile everything. Run <tt>make check</tt> and
+ the full LLVM test suite (<tt>make TEST=nightly report</tt>).</li>
</ol>
<p>Ask LLVM developers to submit the test suite report and <tt>make check</tt>
@@ -538,14 +493,14 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip &gt; clang-<i>X.Y</i>rc1.src.tar.g
$ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \
https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_<i>XY</i>/Final
-$ svn copy https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_XY \
- https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_<i>XY</i>/Final
+$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
+ https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>/Final
+
+$ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY \
+ https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_<i>XY</i>/Final
$ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \
https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_<i>XY</i>/Final
-
-$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
- https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>/Final
</pre>
</div>
@@ -559,7 +514,7 @@ $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
<div>
<p>The LLVM demo page must be updated to use the new release. This consists of
- using the new <tt>llvm-gcc</tt> binary and building LLVM.</p>
+ using the new <tt>clang</tt> binary and building LLVM.</p>
<!-- ======================================================================= -->
<h4><a name="webupdates">Update the LLVM Website</a></h4>
@@ -574,8 +529,8 @@ $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
<li>Create a new subdirectory <tt>X.Y</tt> in the releases directory.</li>
- <li>Commit the <tt>llvm</tt>, <tt>test-suite</tt>, <tt>llvm-gcc</tt> source,
- <tt>clang source</tt>, <tt>clang binaries</tt>, and <tt>llvm-gcc</tt>
+ <li>Commit the <tt>llvm</tt>, <tt>test-suite</tt>, <tt>clang</tt> source,
+ <tt>clang binaries</tt>, <tt>dragonegg</tt> source, and <tt>dragonegg</tt>
binaries in this new directory.</li>
<li>Copy and commit the <tt>llvm/docs</tt> and <tt>LICENSE.txt</tt> files
@@ -619,7 +574,7 @@ $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a>
<br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-10-17 22:32:14 +0200 (Mon, 17 Oct 2011) $
</address>
</body>
</html>
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 8e17243..71e606d 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -35,7 +35,7 @@
<li><a href="#linkage_externweak">'<tt>extern_weak</tt>' Linkage</a></li>
<li><a href="#linkage_linkonce_odr">'<tt>linkonce_odr</tt>' Linkage</a></li>
<li><a href="#linkage_weak">'<tt>weak_odr</tt>' Linkage</a></li>
- <li><a href="#linkage_external">'<tt>externally visible</tt>' Linkage</a></li>
+ <li><a href="#linkage_external">'<tt>external</tt>' Linkage</a></li>
<li><a href="#linkage_dllimport">'<tt>dllimport</tt>' Linkage</a></li>
<li><a href="#linkage_dllexport">'<tt>dllexport</tt>' Linkage</a></li>
</ol>
@@ -53,6 +53,8 @@
<li><a href="#datalayout">Data Layout</a></li>
<li><a href="#pointeraliasing">Pointer Aliasing Rules</a></li>
<li><a href="#volatile">Volatile Memory Accesses</a></li>
+ <li><a href="#memmodel">Memory Model for Concurrent Operations</a></li>
+ <li><a href="#ordering">Atomic Memory Ordering Constraints</a></li>
</ol>
</li>
<li><a href="#typesystem">Type System</a>
@@ -74,7 +76,7 @@
<ol>
<li><a href="#t_array">Array Type</a></li>
<li><a href="#t_struct">Structure Type</a></li>
- <li><a href="#t_opaque">Opaque Type</a></li>
+ <li><a href="#t_opaque">Opaque Structure Types</a></li>
<li><a href="#t_vector">Vector Type</a></li>
</ol>
</li>
@@ -122,6 +124,7 @@
<li><a href="#i_indirectbr">'<tt>indirectbr</tt>' Instruction</a></li>
<li><a href="#i_invoke">'<tt>invoke</tt>' Instruction</a></li>
<li><a href="#i_unwind">'<tt>unwind</tt>' Instruction</a></li>
+ <li><a href="#i_resume">'<tt>resume</tt>' Instruction</a></li>
<li><a href="#i_unreachable">'<tt>unreachable</tt>' Instruction</a></li>
</ol>
</li>
@@ -166,9 +169,12 @@
</li>
<li><a href="#memoryops">Memory Access and Addressing Operations</a>
<ol>
- <li><a href="#i_alloca">'<tt>alloca</tt>' Instruction</a></li>
- <li><a href="#i_load">'<tt>load</tt>' Instruction</a></li>
- <li><a href="#i_store">'<tt>store</tt>' Instruction</a></li>
+ <li><a href="#i_alloca">'<tt>alloca</tt>' Instruction</a></li>
+ <li><a href="#i_load">'<tt>load</tt>' Instruction</a></li>
+ <li><a href="#i_store">'<tt>store</tt>' Instruction</a></li>
+ <li><a href="#i_fence">'<tt>fence</tt>' Instruction</a></li>
+ <li><a href="#i_cmpxchg">'<tt>cmpxchg</tt>' Instruction</a></li>
+ <li><a href="#i_atomicrmw">'<tt>atomicrmw</tt>' Instruction</a></li>
<li><a href="#i_getelementptr">'<tt>getelementptr</tt>' Instruction</a></li>
</ol>
</li>
@@ -196,6 +202,7 @@
<li><a href="#i_select">'<tt>select</tt>' Instruction</a></li>
<li><a href="#i_call">'<tt>call</tt>' Instruction</a></li>
<li><a href="#i_va_arg">'<tt>va_arg</tt>' Instruction</a></li>
+ <li><a href="#i_landingpad">'<tt>landingpad</tt>' Instruction</a></li>
</ol>
</li>
</ol>
@@ -268,9 +275,10 @@
</li>
<li><a href="#int_debugger">Debugger intrinsics</a></li>
<li><a href="#int_eh">Exception Handling intrinsics</a></li>
- <li><a href="#int_trampoline">Trampoline Intrinsic</a>
+ <li><a href="#int_trampoline">Trampoline Intrinsics</a>
<ol>
<li><a href="#int_it">'<tt>llvm.init.trampoline</tt>' Intrinsic</a></li>
+ <li><a href="#int_at">'<tt>llvm.adjust.trampoline</tt>' Intrinsic</a></li>
</ol>
</li>
<li><a href="#int_atomics">Atomic intrinsics</a>
@@ -639,7 +647,7 @@ define i32 @main() { <i>; i32()* </i>&nbsp;
be merged with equivalent globals. These linkage types are otherwise the
same as their non-<tt>odr</tt> versions.</dd>
- <dt><tt><b><a name="linkage_external">externally visible</a></b></tt>:</dt>
+ <dt><tt><b><a name="linkage_external">external</a></b></tt>:</dt>
<dd>If none of the above identifiers are used, the global is externally
visible, meaning that it participates in linkage and can be used to
resolve external symbol references.</dd>
@@ -672,8 +680,8 @@ define i32 @main() { <i>; i32()* </i>&nbsp;
declarations), they are accessible outside of the current module.</p>
<p>It is illegal for a function <i>declaration</i> to have any linkage type
- other than "externally visible", <tt>dllimport</tt>
- or <tt>extern_weak</tt>.</p>
+ other than <tt>external</tt>, <tt>dllimport</tt>
+ or <tt>extern_weak</tt>.</p>
<p>Aliases can have only <tt>external</tt>, <tt>internal</tt>, <tt>weak</tt>
or <tt>weak_odr</tt> linkages.</p>
@@ -1155,14 +1163,6 @@ define void @f() optsize { ... }
function into callers whenever possible, ignoring any active inlining size
threshold for this caller.</dd>
- <dt><tt><b>hotpatch</b></tt></dt>
- <dd>This attribute indicates that the function should be 'hotpatchable',
- meaning the function can be patched and/or hooked even while it is
- loaded into memory. On x86, the function prologue will be preceded
- by six bytes of padding and will begin with a two-byte instruction.
- Most of the functions in the Windows system DLLs in Windows XP SP2 or
- higher were compiled in this fashion.</dd>
-
<dt><tt><b>nonlazybind</b></tt></dt>
<dd>This attribute suppresses lazy symbol binding for the function. This
may make calls to the function faster, at the cost of extra program
@@ -1246,6 +1246,19 @@ define void @f() optsize { ... }
function that doesn't have an <tt>sspreq</tt> attribute or which has
an <tt>ssp</tt> attribute, then the resulting function will have
an <tt>sspreq</tt> attribute.</dd>
+
+ <dt><tt><b><a name="uwtable">uwtable</a></b></tt></dt>
+ <dd>This attribute indicates that the ABI being targeted requires that
+ an unwind table entry be produce for this function even if we can
+ show that no exceptions passes by it. This is normally the case for
+ the ELF x86-64 abi, but it can be disabled for some compilation
+ units.</dd>
+
+ <dt><tt><b><a name="returns_twice">returns_twice</a></b></tt></dt>
+ <dd>This attribute indicates that this function can return
+ twice. The C <code>setjmp</code> is an example of such a function.
+ The compiler disables some optimizations (like tail calls) in the caller of
+ these functions.</dd>
</dl>
</div>
@@ -1306,6 +1319,13 @@ target datalayout = "<i>layout specification</i>"
the bits with the least significance have the lowest address
location.</dd>
+ <dt><tt>S<i>size</i></tt></dt>
+ <dd>Specifies the natural alignment of the stack in bits. Alignment promotion
+ of stack variables is limited to the natural stack alignment to avoid
+ dynamic stack realignment. The stack alignment must be a multiple of
+ 8-bits. If omitted, the natural stack alignment defaults to "unspecified",
+ which does not prevent any alignment promotions.</dd>
+
<dt><tt>p:<i>size</i>:<i>abi</i>:<i>pref</i></tt></dt>
<dd>This specifies the <i>size</i> of a pointer and its <i>abi</i> and
<i>preferred</i> alignments. All sizes are in bits. Specifying
@@ -1386,6 +1406,22 @@ target datalayout = "<i>layout specification</i>"
implemented in terms of 64 &lt;2 x double&gt;, for example.</li>
</ol>
+<p>The function of the data layout string may not be what you expect. Notably,
+ this is not a specification from the frontend of what alignment the code
+ generator should use.</p>
+
+<p>Instead, if specified, the target data layout is required to match what the
+ ultimate <em>code generator</em> expects. This string is used by the
+ mid-level optimizers to
+ improve code, and this only works if it matches what the ultimate code
+ generator uses. If you would like to generate IR that does not embed this
+ target-specific detail into the IR, then you don't have to specify the
+ string. This will disable some optimizations that require precise layout
+ information, but this also prevents those optimizations from introducing
+ target specificity into the IR.</p>
+
+
+
</div>
<!-- ======================================================================= -->
@@ -1470,6 +1506,185 @@ synchronization behavior.</p>
</div>
+<!-- ======================================================================= -->
+<h3>
+ <a name="memmodel">Memory Model for Concurrent Operations</a>
+</h3>
+
+<div>
+
+<p>The LLVM IR does not define any way to start parallel threads of execution
+or to register signal handlers. Nonetheless, there are platform-specific
+ways to create them, and we define LLVM IR's behavior in their presence. This
+model is inspired by the C++0x memory model.</p>
+
+<p>For a more informal introduction to this model, see the
+<a href="Atomics.html">LLVM Atomic Instructions and Concurrency Guide</a>.
+
+<p>We define a <i>happens-before</i> partial order as the least partial order
+that</p>
+<ul>
+ <li>Is a superset of single-thread program order, and</li>
+ <li>When a <i>synchronizes-with</i> <tt>b</tt>, includes an edge from
+ <tt>a</tt> to <tt>b</tt>. <i>Synchronizes-with</i> pairs are introduced
+ by platform-specific techniques, like pthread locks, thread
+ creation, thread joining, etc., and by atomic instructions.
+ (See also <a href="#ordering">Atomic Memory Ordering Constraints</a>).
+ </li>
+</ul>
+
+<p>Note that program order does not introduce <i>happens-before</i> edges
+between a thread and signals executing inside that thread.</p>
+
+<p>Every (defined) read operation (load instructions, memcpy, atomic
+loads/read-modify-writes, etc.) <var>R</var> reads a series of bytes written by
+(defined) write operations (store instructions, atomic
+stores/read-modify-writes, memcpy, etc.). For the purposes of this section,
+initialized globals are considered to have a write of the initializer which is
+atomic and happens before any other read or write of the memory in question.
+For each byte of a read <var>R</var>, <var>R<sub>byte</sub></var> may see
+any write to the same byte, except:</p>
+
+<ul>
+ <li>If <var>write<sub>1</sub></var> happens before
+ <var>write<sub>2</sub></var>, and <var>write<sub>2</sub></var> happens
+ before <var>R<sub>byte</sub></var>, then <var>R<sub>byte</sub></var>
+ does not see <var>write<sub>1</sub></var>.
+ <li>If <var>R<sub>byte</sub></var> happens before
+ <var>write<sub>3</sub></var>, then <var>R<sub>byte</sub></var> does not
+ see <var>write<sub>3</sub></var>.
+</ul>
+
+<p>Given that definition, <var>R<sub>byte</sub></var> is defined as follows:
+<ul>
+ <li>If <var>R</var> is volatile, the result is target-dependent. (Volatile
+ is supposed to give guarantees which can support
+ <code>sig_atomic_t</code> in C/C++, and may be used for accesses to
+ addresses which do not behave like normal memory. It does not generally
+ provide cross-thread synchronization.)
+ <li>Otherwise, if there is no write to the same byte that happens before
+ <var>R<sub>byte</sub></var>, <var>R<sub>byte</sub></var> returns
+ <tt>undef</tt> for that byte.
+ <li>Otherwise, if <var>R<sub>byte</sub></var> may see exactly one write,
+ <var>R<sub>byte</sub></var> returns the value written by that
+ write.</li>
+ <li>Otherwise, if <var>R</var> is atomic, and all the writes
+ <var>R<sub>byte</sub></var> may see are atomic, it chooses one of the
+ values written. See the <a href="#ordering">Atomic Memory Ordering
+ Constraints</a> section for additional constraints on how the choice
+ is made.
+ <li>Otherwise <var>R<sub>byte</sub></var> returns <tt>undef</tt>.</li>
+</ul>
+
+<p><var>R</var> returns the value composed of the series of bytes it read.
+This implies that some bytes within the value may be <tt>undef</tt>
+<b>without</b> the entire value being <tt>undef</tt>. Note that this only
+defines the semantics of the operation; it doesn't mean that targets will
+emit more than one instruction to read the series of bytes.</p>
+
+<p>Note that in cases where none of the atomic intrinsics are used, this model
+places only one restriction on IR transformations on top of what is required
+for single-threaded execution: introducing a store to a byte which might not
+otherwise be stored is not allowed in general. (Specifically, in the case
+where another thread might write to and read from an address, introducing a
+store can change a load that may see exactly one write into a load that may
+see multiple writes.)</p>
+
+<!-- FIXME: This model assumes all targets where concurrency is relevant have
+a byte-size store which doesn't affect adjacent bytes. As far as I can tell,
+none of the backends currently in the tree fall into this category; however,
+there might be targets which care. If there are, we want a paragraph
+like the following:
+
+Targets may specify that stores narrower than a certain width are not
+available; on such a target, for the purposes of this model, treat any
+non-atomic write with an alignment or width less than the minimum width
+as if it writes to the relevant surrounding bytes.
+-->
+
+</div>
+
+<!-- ======================================================================= -->
+<h3>
+ <a name="ordering">Atomic Memory Ordering Constraints</a>
+</h3>
+
+<div>
+
+<p>Atomic instructions (<a href="#i_cmpxchg"><code>cmpxchg</code></a>,
+<a href="#i_atomicrmw"><code>atomicrmw</code></a>,
+<a href="#i_fence"><code>fence</code></a>,
+<a href="#i_load"><code>atomic load</code></a>, and
+<a href="#i_store"><code>atomic store</code></a>) take an ordering parameter
+that determines which other atomic instructions on the same address they
+<i>synchronize with</i>. These semantics are borrowed from Java and C++0x,
+but are somewhat more colloquial. If these descriptions aren't precise enough,
+check those specs (see spec references in the
+<a href="Atomic.html#introduction">atomics guide</a>).
+<a href="#i_fence"><code>fence</code></a> instructions
+treat these orderings somewhat differently since they don't take an address.
+See that instruction's documentation for details.</p>
+
+<p>For a simpler introduction to the ordering constraints, see the
+<a href="Atomics.html">LLVM Atomic Instructions and Concurrency Guide</a>.</p>
+
+<dl>
+<dt><code>unordered</code></dt>
+<dd>The set of values that can be read is governed by the happens-before
+partial order. A value cannot be read unless some operation wrote it.
+This is intended to provide a guarantee strong enough to model Java's
+non-volatile shared variables. This ordering cannot be specified for
+read-modify-write operations; it is not strong enough to make them atomic
+in any interesting way.</dd>
+<dt><code>monotonic</code></dt>
+<dd>In addition to the guarantees of <code>unordered</code>, there is a single
+total order for modifications by <code>monotonic</code> operations on each
+address. All modification orders must be compatible with the happens-before
+order. There is no guarantee that the modification orders can be combined to
+a global total order for the whole program (and this often will not be
+possible). The read in an atomic read-modify-write operation
+(<a href="#i_cmpxchg"><code>cmpxchg</code></a> and
+<a href="#i_atomicrmw"><code>atomicrmw</code></a>)
+reads the value in the modification order immediately before the value it
+writes. If one atomic read happens before another atomic read of the same
+address, the later read must see the same value or a later value in the
+address's modification order. This disallows reordering of
+<code>monotonic</code> (or stronger) operations on the same address. If an
+address is written <code>monotonic</code>ally by one thread, and other threads
+<code>monotonic</code>ally read that address repeatedly, the other threads must
+eventually see the write. This corresponds to the C++0x/C1x
+<code>memory_order_relaxed</code>.</dd>
+<dt><code>acquire</code></dt>
+<dd>In addition to the guarantees of <code>monotonic</code>,
+a <i>synchronizes-with</i> edge may be formed with a <code>release</code>
+operation. This is intended to model C++'s <code>memory_order_acquire</code>.</dd>
+<dt><code>release</code></dt>
+<dd>In addition to the guarantees of <code>monotonic</code>, if this operation
+writes a value which is subsequently read by an <code>acquire</code> operation,
+it <i>synchronizes-with</i> that operation. (This isn't a complete
+description; see the C++0x definition of a release sequence.) This corresponds
+to the C++0x/C1x <code>memory_order_release</code>.</dd>
+<dt><code>acq_rel</code> (acquire+release)</dt><dd>Acts as both an
+<code>acquire</code> and <code>release</code> operation on its address.
+This corresponds to the C++0x/C1x <code>memory_order_acq_rel</code>.</dd>
+<dt><code>seq_cst</code> (sequentially consistent)</dt><dd>
+<dd>In addition to the guarantees of <code>acq_rel</code>
+(<code>acquire</code> for an operation which only reads, <code>release</code>
+for an operation which only writes), there is a global total order on all
+sequentially-consistent operations on all addresses, which is consistent with
+the <i>happens-before</i> partial order and with the modification orders of
+all the affected addresses. Each sequentially-consistent read sees the last
+preceding write to the same address in this global order. This corresponds
+to the C++0x/C1x <code>memory_order_seq_cst</code> and Java volatile.</dd>
+</dl>
+
+<p id="singlethread">If an atomic operation is marked <code>singlethread</code>,
+it only <i>synchronizes with</i> or participates in modification and seq_cst
+total orderings with other operations running in the same thread (for example,
+in signal handlers).</p>
+
+</div>
+
</div>
<!-- *********************************************************************** -->
@@ -1852,20 +2067,22 @@ synchronization behavior.</p>
<p>Structures may optionally be "packed" structures, which indicate that the
alignment of the struct is one byte, and that there is no padding between
- the elements. In non-packed structs, padding between field types is defined
- by the target data string to match the underlying processor.</p>
-
-<p>Structures can either be "anonymous" or "named". An anonymous structure is
- defined inline with other types (e.g. <tt>{i32, i32}*</tt>) and a named types
- are always defined at the top level with a name. Anonmyous types are uniqued
- by their contents and can never be recursive since there is no way to write
- one. Named types can be recursive.
+ the elements. In non-packed structs, padding between field types is inserted
+ as defined by the TargetData string in the module, which is required to match
+ what the underlying code generator expects.</p>
+
+<p>Structures can either be "literal" or "identified". A literal structure is
+ defined inline with other types (e.g. <tt>{i32, i32}*</tt>) whereas identified
+ types are always defined at the top level with a name. Literal types are
+ uniqued by their contents and can never be recursive or opaque since there is
+ no way to write one. Identified types can be recursive, can be opaqued, and are
+ never uniqued.
</p>
<h5>Syntax:</h5>
<pre>
- %T1 = type { &lt;type list&gt; } <i>; Named normal struct type</i>
- %T2 = type &lt;{ &lt;type list&gt; }&gt; <i>; Named packed struct type</i>
+ %T1 = type { &lt;type list&gt; } <i>; Identified normal struct type</i>
+ %T2 = type &lt;{ &lt;type list&gt; }&gt; <i>; Identified packed struct type</i>
</pre>
<h5>Examples:</h5>
@@ -1891,15 +2108,15 @@ synchronization behavior.</p>
<!-- _______________________________________________________________________ -->
<h4>
- <a name="t_opaque">Opaque Type</a>
+ <a name="t_opaque">Opaque Structure Types</a>
</h4>
<div>
<h5>Overview:</h5>
-<p>Opaque types are used to represent named structure types that do not have a
- body specified. This corresponds (for example) to the C notion of a forward
- declared structure.</p>
+<p>Opaque structure types are used to represent named structure types that do
+ not have a body specified. This corresponds (for example) to the C notion of
+ a forward declared structure.</p>
<h5>Syntax:</h5>
<pre>
@@ -2006,6 +2223,8 @@ synchronization behavior.</p>
</div>
+</div>
+
<!-- *********************************************************************** -->
<h2><a name="constants">Constants</a></h2>
<!-- *********************************************************************** -->
@@ -2361,7 +2580,7 @@ b: unreachable
</ul>
<p>Whenever a trap value is generated, all values which depend on it evaluate
- to trap. If they have side effects, the evoke their side effects as if each
+ to trap. If they have side effects, they evoke their side effects as if each
operand with a trap value were undef. If they have externally-visible side
effects, the behavior is undefined.</p>
@@ -2844,14 +3063,15 @@ should not be exposed to source languages.</p>
control flow, not values (the one exception being the
'<a href="#i_invoke"><tt>invoke</tt></a>' instruction).</p>
-<p>There are seven different terminator instructions: the
- '<a href="#i_ret"><tt>ret</tt></a>' instruction, the
- '<a href="#i_br"><tt>br</tt></a>' instruction, the
- '<a href="#i_switch"><tt>switch</tt></a>' instruction, the
- '<a href="#i_indirectbr">'<tt>indirectbr</tt></a>' Instruction, the
- '<a href="#i_invoke"><tt>invoke</tt></a>' instruction, the
- '<a href="#i_unwind"><tt>unwind</tt></a>' instruction, and the
- '<a href="#i_unreachable"><tt>unreachable</tt></a>' instruction.</p>
+<p>The terminator instructions are:
+ '<a href="#i_ret"><tt>ret</tt></a>',
+ '<a href="#i_br"><tt>br</tt></a>',
+ '<a href="#i_switch"><tt>switch</tt></a>',
+ '<a href="#i_indirectbr"><tt>indirectbr</tt></a>',
+ '<a href="#i_invoke"><tt>invoke</tt></a>',
+ '<a href="#i_unwind"><tt>unwind</tt></a>',
+ '<a href="#i_resume"><tt>resume</tt></a>', and
+ '<a href="#i_unreachable"><tt>unreachable</tt></a>'.</p>
<!-- _______________________________________________________________________ -->
<h4>
@@ -2912,7 +3132,8 @@ should not be exposed to source languages.</p>
<h5>Syntax:</h5>
<pre>
- br i1 &lt;cond&gt;, label &lt;iftrue&gt;, label &lt;iffalse&gt;<br> br label &lt;dest&gt; <i>; Unconditional branch</i>
+ br i1 &lt;cond&gt;, label &lt;iftrue&gt;, label &lt;iffalse&gt;
+ br label &lt;dest&gt; <i>; Unconditional branch</i>
</pre>
<h5>Overview:</h5>
@@ -3072,6 +3293,17 @@ IfUnequal:
instruction, control is interrupted and continued at the dynamically nearest
"exception" label.</p>
+<p>The '<tt>exception</tt>' label is a
+ <i><a href="ExceptionHandling.html#overview">landing pad</a></i> for the
+ exception. As such, '<tt>exception</tt>' label is required to have the
+ "<a href="#i_landingpad"><tt>landingpad</tt></a>" instruction, which contains
+ the information about about the behavior of the program after unwinding
+ happens, as its first non-PHI instruction. The restrictions on the
+ "<tt>landingpad</tt>" instruction's tightly couples it to the
+ "<tt>invoke</tt>" instruction, so that the important information contained
+ within the "<tt>landingpad</tt>" instruction can't be lost through normal
+ code motion.</p>
+
<h5>Arguments:</h5>
<p>This instruction requires several arguments:</p>
@@ -3170,6 +3402,40 @@ that the invoke/unwind semantics are likely to change in future versions.</p>
</div>
+ <!-- _______________________________________________________________________ -->
+
+<h4>
+ <a name="i_resume">'<tt>resume</tt>' Instruction</a>
+</h4>
+
+<div>
+
+<h5>Syntax:</h5>
+<pre>
+ resume &lt;type&gt; &lt;value&gt;
+</pre>
+
+<h5>Overview:</h5>
+<p>The '<tt>resume</tt>' instruction is a terminator instruction that has no
+ successors.</p>
+
+<h5>Arguments:</h5>
+<p>The '<tt>resume</tt>' instruction requires one argument, which must have the
+ same type as the result of any '<tt>landingpad</tt>' instruction in the same
+ function.</p>
+
+<h5>Semantics:</h5>
+<p>The '<tt>resume</tt>' instruction resumes propagation of an existing
+ (in-flight) exception whose unwinding was interrupted with
+ a <a href="#i_landingpad"><tt>landingpad</tt></a> instruction.</p>
+
+<h5>Example:</h5>
+<pre>
+ resume { i8*, i32 } %exn
+</pre>
+
+</div>
+
<!-- _______________________________________________________________________ -->
<h4>
@@ -4237,7 +4503,7 @@ that the invoke/unwind semantics are likely to change in future versions.</p>
<h5>Syntax:</h5>
<pre>
- &lt;result&gt; = insertvalue &lt;aggregate type&gt; &lt;val&gt;, &lt;ty&gt; &lt;elt&gt;, &lt;idx&gt;{, <idx>}* <i>; yields &lt;aggregate type&gt;</i>
+ &lt;result&gt; = insertvalue &lt;aggregate type&gt; &lt;val&gt;, &lt;ty&gt; &lt;elt&gt;, &lt;idx&gt;{, &lt;idx&gt;}* <i>; yields &lt;aggregate type&gt;</i>
</pre>
<h5>Overview:</h5>
@@ -4342,8 +4608,8 @@ that the invoke/unwind semantics are likely to change in future versions.</p>
<h5>Syntax:</h5>
<pre>
- &lt;result&gt; = load &lt;ty&gt;* &lt;pointer&gt;[, align &lt;alignment&gt;][, !nontemporal !&lt;index&gt;]
- &lt;result&gt; = volatile load &lt;ty&gt;* &lt;pointer&gt;[, align &lt;alignment&gt;][, !nontemporal !&lt;index&gt;]
+ &lt;result&gt; = load [volatile] &lt;ty&gt;* &lt;pointer&gt;[, align &lt;alignment&gt;][, !nontemporal !&lt;index&gt;]
+ &lt;result&gt; = load atomic [volatile] &lt;ty&gt;* &lt;pointer&gt; [singlethread] &lt;ordering&gt;, align &lt;alignment&gt;
!&lt;index&gt; = !{ i32 1 }
</pre>
@@ -4358,6 +4624,19 @@ that the invoke/unwind semantics are likely to change in future versions.</p>
number or order of execution of this <tt>load</tt> with other <a
href="#volatile">volatile operations</a>.</p>
+<p>If the <code>load</code> is marked as <code>atomic</code>, it takes an extra
+ <a href="#ordering">ordering</a> and optional <code>singlethread</code>
+ argument. The <code>release</code> and <code>acq_rel</code> orderings are
+ not valid on <code>load</code> instructions. Atomic loads produce <a
+ href="#memorymodel">defined</a> results when they may see multiple atomic
+ stores. The type of the pointee must be an integer type whose bit width
+ is a power of two greater than or equal to eight and less than or equal
+ to a target-specific size limit. <code>align</code> must be explicitly
+ specified on atomic loads, and the load has undefined behavior if the
+ alignment is not set to a value which is at least the size in bytes of
+ the pointee. <code>!nontemporal</code> does not have any defined semantics
+ for atomic loads.</p>
+
<p>The optional constant <tt>align</tt> argument specifies the alignment of the
operation (that is, the alignment of the memory address). A value of 0 or an
omitted <tt>align</tt> argument means that the operation has the preferential
@@ -4401,8 +4680,8 @@ that the invoke/unwind semantics are likely to change in future versions.</p>
<h5>Syntax:</h5>
<pre>
- store &lt;ty&gt; &lt;value&gt;, &lt;ty&gt;* &lt;pointer&gt;[, align &lt;alignment&gt;][, !nontemporal !&lt;index&gt;] <i>; yields {void}</i>
- volatile store &lt;ty&gt; &lt;value&gt;, &lt;ty&gt;* &lt;pointer&gt;[, align &lt;alignment&gt;][, !nontemporal !&lt;index&gt;] <i>; yields {void}</i>
+ store [volatile] &lt;ty&gt; &lt;value&gt;, &lt;ty&gt;* &lt;pointer&gt;[, align &lt;alignment&gt;][, !nontemporal !&lt;index&gt;] <i>; yields {void}</i>
+ store atomic [volatile] &lt;ty&gt; &lt;value&gt;, &lt;ty&gt;* &lt;pointer&gt; [singlethread] &lt;ordering&gt;, align &lt;alignment&gt; <i>; yields {void}</i>
</pre>
<h5>Overview:</h5>
@@ -4418,6 +4697,19 @@ that the invoke/unwind semantics are likely to change in future versions.</p>
order of execution of this <tt>store</tt> with other <a
href="#volatile">volatile operations</a>.</p>
+<p>If the <code>store</code> is marked as <code>atomic</code>, it takes an extra
+ <a href="#ordering">ordering</a> and optional <code>singlethread</code>
+ argument. The <code>acquire</code> and <code>acq_rel</code> orderings aren't
+ valid on <code>store</code> instructions. Atomic loads produce <a
+ href="#memorymodel">defined</a> results when they may see multiple atomic
+ stores. The type of the pointee must be an integer type whose bit width
+ is a power of two greater than or equal to eight and less than or equal
+ to a target-specific size limit. <code>align</code> must be explicitly
+ specified on atomic stores, and the store has undefined behavior if the
+ alignment is not set to a value which is at least the size in bytes of
+ the pointee. <code>!nontemporal</code> does not have any defined semantics
+ for atomic stores.</p>
+
<p>The optional constant "align" argument specifies the alignment of the
operation (that is, the alignment of the memory address). A value of 0 or an
omitted "align" argument means that the operation has the preferential
@@ -4456,6 +4748,215 @@ that the invoke/unwind semantics are likely to change in future versions.</p>
<!-- _______________________________________________________________________ -->
<h4>
+<a name="i_fence">'<tt>fence</tt>' Instruction</a>
+</h4>
+
+<div>
+
+<h5>Syntax:</h5>
+<pre>
+ fence [singlethread] &lt;ordering&gt; <i>; yields {void}</i>
+</pre>
+
+<h5>Overview:</h5>
+<p>The '<tt>fence</tt>' instruction is used to introduce happens-before edges
+between operations.</p>
+
+<h5>Arguments:</h5> <p>'<code>fence</code>' instructions take an <a
+href="#ordering">ordering</a> argument which defines what
+<i>synchronizes-with</i> edges they add. They can only be given
+<code>acquire</code>, <code>release</code>, <code>acq_rel</code>, and
+<code>seq_cst</code> orderings.</p>
+
+<h5>Semantics:</h5>
+<p>A fence <var>A</var> which has (at least) <code>release</code> ordering
+semantics <i>synchronizes with</i> a fence <var>B</var> with (at least)
+<code>acquire</code> ordering semantics if and only if there exist atomic
+operations <var>X</var> and <var>Y</var>, both operating on some atomic object
+<var>M</var>, such that <var>A</var> is sequenced before <var>X</var>,
+<var>X</var> modifies <var>M</var> (either directly or through some side effect
+of a sequence headed by <var>X</var>), <var>Y</var> is sequenced before
+<var>B</var>, and <var>Y</var> observes <var>M</var>. This provides a
+<i>happens-before</i> dependency between <var>A</var> and <var>B</var>. Rather
+than an explicit <code>fence</code>, one (but not both) of the atomic operations
+<var>X</var> or <var>Y</var> might provide a <code>release</code> or
+<code>acquire</code> (resp.) ordering constraint and still
+<i>synchronize-with</i> the explicit <code>fence</code> and establish the
+<i>happens-before</i> edge.</p>
+
+<p>A <code>fence</code> which has <code>seq_cst</code> ordering, in addition to
+having both <code>acquire</code> and <code>release</code> semantics specified
+above, participates in the global program order of other <code>seq_cst</code>
+operations and/or fences.</p>
+
+<p>The optional "<a href="#singlethread"><code>singlethread</code></a>" argument
+specifies that the fence only synchronizes with other fences in the same
+thread. (This is useful for interacting with signal handlers.)</p>
+
+<h5>Example:</h5>
+<pre>
+ fence acquire <i>; yields {void}</i>
+ fence singlethread seq_cst <i>; yields {void}</i>
+</pre>
+
+</div>
+
+<!-- _______________________________________________________________________ -->
+<h4>
+<a name="i_cmpxchg">'<tt>cmpxchg</tt>' Instruction</a>
+</h4>
+
+<div>
+
+<h5>Syntax:</h5>
+<pre>
+ cmpxchg [volatile] &lt;ty&gt;* &lt;pointer&gt;, &lt;ty&gt; &lt;cmp&gt;, &lt;ty&gt; &lt;new&gt; [singlethread] &lt;ordering&gt; <i>; yields {ty}</i>
+</pre>
+
+<h5>Overview:</h5>
+<p>The '<tt>cmpxchg</tt>' instruction is used to atomically modify memory.
+It loads a value in memory and compares it to a given value. If they are
+equal, it stores a new value into the memory.</p>
+
+<h5>Arguments:</h5>
+<p>There are three arguments to the '<code>cmpxchg</code>' instruction: an
+address to operate on, a value to compare to the value currently be at that
+address, and a new value to place at that address if the compared values are
+equal. The type of '<var>&lt;cmp&gt;</var>' must be an integer type whose
+bit width is a power of two greater than or equal to eight and less than
+or equal to a target-specific size limit. '<var>&lt;cmp&gt;</var>' and
+'<var>&lt;new&gt;</var>' must have the same type, and the type of
+'<var>&lt;pointer&gt;</var>' must be a pointer to that type. If the
+<code>cmpxchg</code> is marked as <code>volatile</code>, then the
+optimizer is not allowed to modify the number or order of execution
+of this <code>cmpxchg</code> with other <a href="#volatile">volatile
+operations</a>.</p>
+
+<!-- FIXME: Extend allowed types. -->
+
+<p>The <a href="#ordering"><var>ordering</var></a> argument specifies how this
+<code>cmpxchg</code> synchronizes with other atomic operations.</p>
+
+<p>The optional "<code>singlethread</code>" argument declares that the
+<code>cmpxchg</code> is only atomic with respect to code (usually signal
+handlers) running in the same thread as the <code>cmpxchg</code>. Otherwise the
+cmpxchg is atomic with respect to all other code in the system.</p>
+
+<p>The pointer passed into cmpxchg must have alignment greater than or equal to
+the size in memory of the operand.
+
+<h5>Semantics:</h5>
+<p>The contents of memory at the location specified by the
+'<tt>&lt;pointer&gt;</tt>' operand is read and compared to
+'<tt>&lt;cmp&gt;</tt>'; if the read value is the equal,
+'<tt>&lt;new&gt;</tt>' is written. The original value at the location
+is returned.
+
+<p>A successful <code>cmpxchg</code> is a read-modify-write instruction for the
+purpose of identifying <a href="#release_sequence">release sequences</a>. A
+failed <code>cmpxchg</code> is equivalent to an atomic load with an ordering
+parameter determined by dropping any <code>release</code> part of the
+<code>cmpxchg</code>'s ordering.</p>
+
+<!--
+FIXME: Is compare_exchange_weak() necessary? (Consider after we've done
+optimization work on ARM.)
+
+FIXME: Is a weaker ordering constraint on failure helpful in practice?
+-->
+
+<h5>Example:</h5>
+<pre>
+entry:
+ %orig = atomic <a href="#i_load">load</a> i32* %ptr unordered <i>; yields {i32}</i>
+ <a href="#i_br">br</a> label %loop
+
+loop:
+ %cmp = <a href="#i_phi">phi</a> i32 [ %orig, %entry ], [%old, %loop]
+ %squared = <a href="#i_mul">mul</a> i32 %cmp, %cmp
+ %old = cmpxchg i32* %ptr, i32 %cmp, i32 %squared <i>; yields {i32}</i>
+ %success = <a href="#i_icmp">icmp</a> eq i32 %cmp, %old
+ <a href="#i_br">br</a> i1 %success, label %done, label %loop
+
+done:
+ ...
+</pre>
+
+</div>
+
+<!-- _______________________________________________________________________ -->
+<h4>
+<a name="i_atomicrmw">'<tt>atomicrmw</tt>' Instruction</a>
+</h4>
+
+<div>
+
+<h5>Syntax:</h5>
+<pre>
+ atomicrmw [volatile] &lt;operation&gt; &lt;ty&gt;* &lt;pointer&gt;, &lt;ty&gt; &lt;value&gt; [singlethread] &lt;ordering&gt; <i>; yields {ty}</i>
+</pre>
+
+<h5>Overview:</h5>
+<p>The '<tt>atomicrmw</tt>' instruction is used to atomically modify memory.</p>
+
+<h5>Arguments:</h5>
+<p>There are three arguments to the '<code>atomicrmw</code>' instruction: an
+operation to apply, an address whose value to modify, an argument to the
+operation. The operation must be one of the following keywords:</p>
+<ul>
+ <li>xchg</li>
+ <li>add</li>
+ <li>sub</li>
+ <li>and</li>
+ <li>nand</li>
+ <li>or</li>
+ <li>xor</li>
+ <li>max</li>
+ <li>min</li>
+ <li>umax</li>
+ <li>umin</li>
+</ul>
+
+<p>The type of '<var>&lt;value&gt;</var>' must be an integer type whose
+bit width is a power of two greater than or equal to eight and less than
+or equal to a target-specific size limit. The type of the
+'<code>&lt;pointer&gt;</code>' operand must be a pointer to that type.
+If the <code>atomicrmw</code> is marked as <code>volatile</code>, then the
+optimizer is not allowed to modify the number or order of execution of this
+<code>atomicrmw</code> with other <a href="#volatile">volatile
+ operations</a>.</p>
+
+<!-- FIXME: Extend allowed types. -->
+
+<h5>Semantics:</h5>
+<p>The contents of memory at the location specified by the
+'<tt>&lt;pointer&gt;</tt>' operand are atomically read, modified, and written
+back. The original value at the location is returned. The modification is
+specified by the <var>operation</var> argument:</p>
+
+<ul>
+ <li>xchg: <code>*ptr = val</code></li>
+ <li>add: <code>*ptr = *ptr + val</code></li>
+ <li>sub: <code>*ptr = *ptr - val</code></li>
+ <li>and: <code>*ptr = *ptr &amp; val</code></li>
+ <li>nand: <code>*ptr = ~(*ptr &amp; val)</code></li>
+ <li>or: <code>*ptr = *ptr | val</code></li>
+ <li>xor: <code>*ptr = *ptr ^ val</code></li>
+ <li>max: <code>*ptr = *ptr &gt; val ? *ptr : val</code> (using a signed comparison)</li>
+ <li>min: <code>*ptr = *ptr &lt; val ? *ptr : val</code> (using a signed comparison)</li>
+ <li>umax: <code>*ptr = *ptr &gt; val ? *ptr : val</code> (using an unsigned comparison)</li>
+ <li>umin: <code>*ptr = *ptr &lt; val ? *ptr : val</code> (using an unsigned comparison)</li>
+</ul>
+
+<h5>Example:</h5>
+<pre>
+ %old = atomicrmw add i32* %ptr, i32 1 acquire <i>; yields {i32}</i>
+</pre>
+
+</div>
+
+<!-- _______________________________________________________________________ -->
+<h4>
<a name="i_getelementptr">'<tt>getelementptr</tt>' Instruction</a>
</h4>
@@ -4489,7 +4990,7 @@ that the invoke/unwind semantics are likely to change in future versions.</p>
When indexing into a (optionally packed) structure, only <tt>i32</tt>
integer <b>constants</b> are allowed. When indexing into an array, pointer
or vector, integers of any width are allowed, and they are not required to be
- constant.</p>
+ constant. These integers are treated as signed values where relevant.</p>
<p>For example, let's consider a C code fragment and how it gets compiled to
LLVM:</p>
@@ -4555,18 +5056,20 @@ entry:
base pointer is not an <i>in bounds</i> address of an allocated object,
or if any of the addresses that would be formed by successive addition of
the offsets implied by the indices to the base address with infinitely
- precise arithmetic are not an <i>in bounds</i> address of that allocated
- object. The <i>in bounds</i> addresses for an allocated object are all
- the addresses that point into the object, plus the address one byte past
- the end.</p>
+ precise signed arithmetic are not an <i>in bounds</i> address of that
+ allocated object. The <i>in bounds</i> addresses for an allocated object
+ are all the addresses that point into the object, plus the address one
+ byte past the end.</p>
<p>If the <tt>inbounds</tt> keyword is not present, the offsets are added to
- the base address with silently-wrapping two's complement arithmetic, and
- the result value of the <tt>getelementptr</tt> may be outside the object
- pointed to by the base pointer. The result value may not necessarily be
- used to access memory though, even if it happens to point into allocated
- storage. See the <a href="#pointeraliasing">Pointer Aliasing Rules</a>
- section for more information.</p>
+ the base address with silently-wrapping two's complement arithmetic. If the
+ offsets have a different width from the pointer, they are sign-extended or
+ truncated to the width of the pointer. The result value of the
+ <tt>getelementptr</tt> may be outside the object pointed to by the base
+ pointer. The result value may not necessarily be used to access memory
+ though, even if it happens to point into allocated storage. See the
+ <a href="#pointeraliasing">Pointer Aliasing Rules</a> section for more
+ information.</p>
<p>The getelementptr instruction is often confusing. For some more insight into
how it works, see <a href="GetElementPtr.html">the getelementptr FAQ</a>.</p>
@@ -5544,6 +6047,87 @@ freestanding environments and non-C-based languages.</p>
</div>
+<!-- _______________________________________________________________________ -->
+<h4>
+ <a name="i_landingpad">'<tt>landingpad</tt>' Instruction</a>
+</h4>
+
+<div>
+
+<h5>Syntax:</h5>
+<pre>
+ &lt;resultval&gt; = landingpad &lt;somety&gt; personality &lt;type&gt; &lt;pers_fn&gt; &lt;clause&gt;+
+ &lt;resultval&gt; = landingpad &lt;somety&gt; personality &lt;type&gt; &lt;pers_fn&gt; cleanup &lt;clause&gt;*
+
+ &lt;clause&gt; := catch &lt;type&gt; &lt;value&gt;
+ &lt;clause&gt; := filter &lt;array constant type&gt; &lt;array constant&gt;
+</pre>
+
+<h5>Overview:</h5>
+<p>The '<tt>landingpad</tt>' instruction is used by
+ <a href="ExceptionHandling.html#overview">LLVM's exception handling
+ system</a> to specify that a basic block is a landing pad &mdash; one where
+ the exception lands, and corresponds to the code found in the
+ <i><tt>catch</tt></i> portion of a <i><tt>try/catch</tt></i> sequence. It
+ defines values supplied by the personality function (<tt>pers_fn</tt>) upon
+ re-entry to the function. The <tt>resultval</tt> has the
+ type <tt>somety</tt>.</p>
+
+<h5>Arguments:</h5>
+<p>This instruction takes a <tt>pers_fn</tt> value. This is the personality
+ function associated with the unwinding mechanism. The optional
+ <tt>cleanup</tt> flag indicates that the landing pad block is a cleanup.</p>
+
+<p>A <tt>clause</tt> begins with the clause type &mdash; <tt>catch</tt>
+ or <tt>filter</tt> &mdash; and contains the global variable representing the
+ "type" that may be caught or filtered respectively. Unlike the
+ <tt>catch</tt> clause, the <tt>filter</tt> clause takes an array constant as
+ its argument. Use "<tt>[0 x i8**] undef</tt>" for a filter which cannot
+ throw. The '<tt>landingpad</tt>' instruction must contain <em>at least</em>
+ one <tt>clause</tt> or the <tt>cleanup</tt> flag.</p>
+
+<h5>Semantics:</h5>
+<p>The '<tt>landingpad</tt>' instruction defines the values which are set by the
+ personality function (<tt>pers_fn</tt>) upon re-entry to the function, and
+ therefore the "result type" of the <tt>landingpad</tt> instruction. As with
+ calling conventions, how the personality function results are represented in
+ LLVM IR is target specific.</p>
+
+<p>The clauses are applied in order from top to bottom. If two
+ <tt>landingpad</tt> instructions are merged together through inlining, the
+ clauses from the calling function are appended to the list of clauses.</p>
+
+<p>The <tt>landingpad</tt> instruction has several restrictions:</p>
+
+<ul>
+ <li>A landing pad block is a basic block which is the unwind destination of an
+ '<tt>invoke</tt>' instruction.</li>
+ <li>A landing pad block must have a '<tt>landingpad</tt>' instruction as its
+ first non-PHI instruction.</li>
+ <li>There can be only one '<tt>landingpad</tt>' instruction within the landing
+ pad block.</li>
+ <li>A basic block that is not a landing pad block may not include a
+ '<tt>landingpad</tt>' instruction.</li>
+ <li>All '<tt>landingpad</tt>' instructions in a function must have the same
+ personality function.</li>
+</ul>
+
+<h5>Example:</h5>
+<pre>
+ ;; A landing pad which can catch an integer.
+ %res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ catch i8** @_ZTIi
+ ;; A landing pad that is a cleanup.
+ %res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ ;; A landing pad which can catch an integer and can only throw a double.
+ %res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ catch i8** @_ZTIi
+ filter [1 x i8**] [@_ZTId]
+</pre>
+
+</div>
+
</div>
</div>
@@ -5737,6 +6321,8 @@ declare void @llvm.va_end(i8*)
</div>
+</div>
+
<!-- ======================================================================= -->
<h3>
<a name="int_gc">Accurate Garbage Collection Intrinsics</a>
@@ -7115,12 +7701,12 @@ LLVM</a>.</p>
<!-- ======================================================================= -->
<h3>
- <a name="int_trampoline">Trampoline Intrinsic</a>
+ <a name="int_trampoline">Trampoline Intrinsics</a>
</h3>
<div>
-<p>This intrinsic makes it possible to excise one parameter, marked with
+<p>These intrinsics make it possible to excise one parameter, marked with
the <a href="#nest"><tt>nest</tt></a> attribute, from a function.
The result is a callable
function pointer lacking the nest parameter - the caller does not need to
@@ -7137,7 +7723,8 @@ LLVM</a>.</p>
<pre class="doc_code">
%tramp = alloca [10 x i8], align 4 ; size and alignment only correct for X86
%tramp1 = getelementptr [10 x i8]* %tramp, i32 0, i32 0
- %p = call i8* @llvm.init.trampoline(i8* %tramp1, i8* bitcast (i32 (i8* nest , i32, i32)* @f to i8*), i8* %nval)
+ call i8* @llvm.init.trampoline(i8* %tramp1, i8* bitcast (i32 (i8*, i32, i32)* @f to i8*), i8* %nval)
+ %p = call i8* @llvm.adjust.trampoline(i8* %tramp1)
%fp = bitcast i8* %p to i32 (i32, i32)*
</pre>
@@ -7155,12 +7742,12 @@ LLVM</a>.</p>
<h5>Syntax:</h5>
<pre>
- declare i8* @llvm.init.trampoline(i8* &lt;tramp&gt;, i8* &lt;func&gt;, i8* &lt;nval&gt;)
+ declare void @llvm.init.trampoline(i8* &lt;tramp&gt;, i8* &lt;func&gt;, i8* &lt;nval&gt;)
</pre>
<h5>Overview:</h5>
-<p>This fills the memory pointed to by <tt>tramp</tt> with code and returns a
- function pointer suitable for executing it.</p>
+<p>This fills the memory pointed to by <tt>tramp</tt> with executable code,
+ turning it into a trampoline.</p>
<h5>Arguments:</h5>
<p>The <tt>llvm.init.trampoline</tt> intrinsic takes three arguments, all
@@ -7174,17 +7761,50 @@ LLVM</a>.</p>
<h5>Semantics:</h5>
<p>The block of memory pointed to by <tt>tramp</tt> is filled with target
- dependent code, turning it into a function. A pointer to this function is
- returned, but needs to be bitcast to an <a href="#int_trampoline">appropriate
- function pointer type</a> before being called. The new function's signature
- is the same as that of <tt>func</tt> with any arguments marked with
- the <tt>nest</tt> attribute removed. At most one such <tt>nest</tt> argument
- is allowed, and it must be of pointer type. Calling the new function is
- equivalent to calling <tt>func</tt> with the same argument list, but
- with <tt>nval</tt> used for the missing <tt>nest</tt> argument. If, after
- calling <tt>llvm.init.trampoline</tt>, the memory pointed to
- by <tt>tramp</tt> is modified, then the effect of any later call to the
- returned function pointer is undefined.</p>
+ dependent code, turning it into a function. Then <tt>tramp</tt> needs to be
+ passed to <a href="#int_at">llvm.adjust.trampoline</a> to get a pointer
+ which can be <a href="#int_trampoline">bitcast (to a new function) and
+ called</a>. The new function's signature is the same as that of
+ <tt>func</tt> with any arguments marked with the <tt>nest</tt> attribute
+ removed. At most one such <tt>nest</tt> argument is allowed, and it must be of
+ pointer type. Calling the new function is equivalent to calling <tt>func</tt>
+ with the same argument list, but with <tt>nval</tt> used for the missing
+ <tt>nest</tt> argument. If, after calling <tt>llvm.init.trampoline</tt>, the
+ memory pointed to by <tt>tramp</tt> is modified, then the effect of any later call
+ to the returned function pointer is undefined.</p>
+</div>
+
+<!-- _______________________________________________________________________ -->
+<h4>
+ <a name="int_at">
+ '<tt>llvm.adjust.trampoline</tt>' Intrinsic
+ </a>
+</h4>
+
+<div>
+
+<h5>Syntax:</h5>
+<pre>
+ declare i8* @llvm.adjust.trampoline(i8* &lt;tramp&gt;)
+</pre>
+
+<h5>Overview:</h5>
+<p>This performs any required machine-specific adjustment to the address of a
+ trampoline (passed as <tt>tramp</tt>).</p>
+
+<h5>Arguments:</h5>
+<p><tt>tramp</tt> must point to a block of memory which already has trampoline code
+ filled in by a previous call to <a href="#int_it"><tt>llvm.init.trampoline</tt>
+ </a>.</p>
+
+<h5>Semantics:</h5>
+<p>On some architectures the address of the code to be executed needs to be
+ different to the address where the trampoline is actually stored. This
+ intrinsic returns the executable address corresponding to <tt>tramp</tt>
+ after performing the required machine specific adjustments.
+ The pointer returned can then be <a href="#int_trampoline"> bitcast and
+ executed</a>.
+</p>
</div>
@@ -7846,7 +8466,7 @@ LLVM</a>.</p>
<h5>Semantics:</h5>
<p>This intrinsic allows annotation of local variables with arbitrary strings.
This can be useful for special purpose optimizations that want to look for
- these annotations. These have no other defined use, they are ignored by code
+ these annotations. These have no other defined use; they are ignored by code
generation and optimization.</p>
</div>
@@ -7882,7 +8502,7 @@ LLVM</a>.</p>
<h5>Semantics:</h5>
<p>This intrinsic allows annotations to be put on arbitrary expressions with
arbitrary strings. This can be useful for special purpose optimizations that
- want to look for these annotations. These have no other defined use, they
+ want to look for these annotations. These have no other defined use; they
are ignored by code generation and optimization.</p>
</div>
@@ -7995,7 +8615,7 @@ LLVM</a>.</p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-07-09 19:41:24 +0200 (Sat, 09 Jul 2011) $
+ Last modified: $Date: 2011-10-14 01:04:49 +0200 (Fri, 14 Oct 2011) $
</address>
</body>
diff --git a/docs/Lexicon.html b/docs/Lexicon.html
index 449e26e..e12041d 100644
--- a/docs/Lexicon.html
+++ b/docs/Lexicon.html
@@ -35,6 +35,10 @@
<td><a href="#DSA">DSA</a></td>
<td><a href="#DSE">DSE</a></td>
</tr>
+ <tr><th colspan="8"><b>- <a href="#F">F</a> -</b></th></tr>
+ <tr>
+ <td><a href="#FCA">FCA</a></td>
+ </tr>
<tr><th colspan="8"><b>- <a href="#G">G</a> -</b></th></tr>
<tr>
<td><a href="#GC">GC</a></td>
@@ -137,6 +141,14 @@ href="http://www.program-transformation.org/Transform/BURG">BURG</a> tool.</dd>
</dl>
</div>
<!-- _______________________________________________________________________ -->
+<h3><a name="F">- F -</a></h3>
+<div>
+ <dl>
+ <dt><a name="FCA"><b>FCA</b></a></dt>
+ <dd>First Class Aggregate</dd>
+ </dl>
+</div>
+<!-- _______________________________________________________________________ -->
<h3><a name="G">- G -</a></h3>
<div>
<dl>
@@ -272,7 +284,7 @@ href="http://www.program-transformation.org/Transform/BURG">BURG</a> tool.</dd>
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a><a
href="http://llvm.org/">The LLVM Team</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
-Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+Last modified: $Date: 2011-09-27 20:44:01 +0200 (Tue, 27 Sep 2011) $
</address>
<!-- vim: sw=2
-->
diff --git a/docs/LinkTimeOptimization.html b/docs/LinkTimeOptimization.html
index 289da23..a1e8bba 100644
--- a/docs/LinkTimeOptimization.html
+++ b/docs/LinkTimeOptimization.html
@@ -79,7 +79,7 @@ conservative escape analysis.
<p>The following example illustrates the advantages of LTO's integrated
approach and clean interface. This example requires a system linker which
supports LTO through the interface described in this document. Here,
- llvm-gcc transparently invokes system linker. </p>
+ clang transparently invokes system linker. </p>
<ul>
<li> Input source file <tt>a.c</tt> is compiled into LLVM bitcode form.
<li> Input source file <tt>main.c</tt> is compiled into native object code.
@@ -89,27 +89,29 @@ conservative escape analysis.
extern int foo1(void);
extern void foo2(void);
extern void foo4(void);
+
--- a.c ---
#include "a.h"
static signed int i = 0;
void foo2(void) {
- i = -1;
+ i = -1;
}
static int foo3() {
-foo4();
-return 10;
+ foo4();
+ return 10;
}
int foo1(void) {
-int data = 0;
+ int data = 0;
-if (i &lt; 0) { data = foo3(); }
+ if (i &lt; 0)
+ data = foo3();
-data = data + 42;
-return data;
+ data = data + 42;
+ return data;
}
--- main.c ---
@@ -117,30 +119,35 @@ return data;
#include "a.h"
void foo4(void) {
- printf ("Hi\n");
+ printf("Hi\n");
}
int main() {
- return foo1();
+ return foo1();
}
--- command lines ---
-$ llvm-gcc --emit-llvm -c a.c -o a.o # &lt;-- a.o is LLVM bitcode file
-$ llvm-gcc -c main.c -o main.o # &lt;-- main.o is native object file
-$ llvm-gcc a.o main.o -o main # &lt;-- standard link command without any modifications
+$ clang -emit-llvm -c a.c -o a.o # &lt;-- a.o is LLVM bitcode file
+$ clang -c main.c -o main.o # &lt;-- main.o is native object file
+$ clang a.o main.o -o main # &lt;-- standard link command without any modifications
</pre>
- <p>In this example, the linker recognizes that <tt>foo2()</tt> is an
- externally visible symbol defined in LLVM bitcode file. The linker completes
- its usual symbol resolution
- pass and finds that <tt>foo2()</tt> is not used anywhere. This information
- is used by the LLVM optimizer and it removes <tt>foo2()</tt>. As soon as
- <tt>foo2()</tt> is removed, the optimizer recognizes that condition
- <tt>i &lt; 0</tt> is always false, which means <tt>foo3()</tt> is never
- used. Hence, the optimizer removes <tt>foo3()</tt>, also. And this in turn,
- enables linker to remove <tt>foo4()</tt>. This example illustrates the
- advantage of tight integration with the linker. Here, the optimizer can not
- remove <tt>foo3()</tt> without the linker's input.
- </p>
+
+<ul>
+ <li>In this example, the linker recognizes that <tt>foo2()</tt> is an
+ externally visible symbol defined in LLVM bitcode file. The linker
+ completes its usual symbol resolution pass and finds that <tt>foo2()</tt>
+ is not used anywhere. This information is used by the LLVM optimizer and
+ it removes <tt>foo2()</tt>.</li>
+ <li>As soon as <tt>foo2()</tt> is removed, the optimizer recognizes that condition
+ <tt>i &lt; 0</tt> is always false, which means <tt>foo3()</tt> is never
+ used. Hence, the optimizer also removes <tt>foo3()</tt>.</li>
+ <li>And this in turn, enables linker to remove <tt>foo4()</tt>.</li>
+</ul>
+
+<p>This example illustrates the advantage of tight integration with the
+ linker. Here, the optimizer can not remove <tt>foo3()</tt> without the
+ linker's input.</p>
+
</div>
<!-- ======================================================================= -->
@@ -385,7 +392,7 @@ of the native object files.</p>
Devang Patel and Nick Kledzik<br>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-09-18 14:51:05 +0200 (Sun, 18 Sep 2011) $
</address>
</body>
diff --git a/docs/Passes.html b/docs/Passes.html
index ca9602c..eb4a115 100644
--- a/docs/Passes.html
+++ b/docs/Passes.html
@@ -161,7 +161,6 @@ perl -e '$/ = undef; for (split(/\n/, <>)) { s:^ *///? ?::; print " <p>\n" if !
<tr><td><a href="#loop-unswitch">-loop-unswitch</a></td><td>Unswitch loops</td></tr>
<tr><td><a href="#loweratomic">-loweratomic</a></td><td>Lower atomic intrinsics to non-atomic form</td></tr>
<tr><td><a href="#lowerinvoke">-lowerinvoke</a></td><td>Lower invoke and unwind, for unwindless code generators</td></tr>
-<tr><td><a href="#lowersetjmp">-lowersetjmp</a></td><td>Lower Set Jump</td></tr>
<tr><td><a href="#lowerswitch">-lowerswitch</a></td><td>Lower SwitchInst's to branches</td></tr>
<tr><td><a href="#mem2reg">-mem2reg</a></td><td>Promote Memory to Register</td></tr>
<tr><td><a href="#memcpyopt">-memcpyopt</a></td><td>MemCpy Optimization</td></tr>
@@ -1478,35 +1477,6 @@ if (X &lt; 3) {</pre>
<!-------------------------------------------------------------------------- -->
<h3>
- <a name="lowersetjmp">-lowersetjmp: Lower Set Jump</a>
-</h3>
-<div>
- <p>
- Lowers <tt>setjmp</tt> and <tt>longjmp</tt> to use the LLVM invoke and unwind
- instructions as necessary.
- </p>
-
- <p>
- Lowering of <tt>longjmp</tt> is fairly trivial. We replace the call with a
- call to the LLVM library function <tt>__llvm_sjljeh_throw_longjmp()</tt>.
- This unwinds the stack for us calling all of the destructors for
- objects allocated on the stack.
- </p>
-
- <p>
- At a <tt>setjmp</tt> call, the basic block is split and the <tt>setjmp</tt>
- removed. The calls in a function that have a <tt>setjmp</tt> are converted to
- invoke where the except part checks to see if it's a <tt>longjmp</tt>
- exception and, if so, if it's handled in the function. If it is, then it gets
- the value returned by the <tt>longjmp</tt> and goes to where the basic block
- was split. <tt>invoke</tt> instructions are handled in a similar fashion with
- the original except block being executed if it isn't a <tt>longjmp</tt>
- except that is handled by that function.
- </p>
-</div>
-
-<!-------------------------------------------------------------------------- -->
-<h3>
<a name="lowerswitch">-lowerswitch: Lower SwitchInst's to branches</a>
</h3>
<div>
@@ -2071,7 +2041,7 @@ if (X &lt; 3) {</pre>
<a href="mailto:rspencer@x10sys.com">Reid Spencer</a><br>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-08-04 00:18:20 +0200 (Thu, 04 Aug 2011) $
</address>
</body>
diff --git a/docs/ProgrammersManual.html b/docs/ProgrammersManual.html
index ed43f1f..3697dd7 100644
--- a/docs/ProgrammersManual.html
+++ b/docs/ProgrammersManual.html
@@ -59,6 +59,7 @@ option</a></li>
<li><a href="#dss_arrayref">llvm/ADT/ArrayRef.h</a></li>
<li><a href="#dss_fixedarrays">Fixed Size Arrays</a></li>
<li><a href="#dss_heaparrays">Heap Allocated Arrays</a></li>
+ <li><a href="#dss_tinyptrvector">"llvm/ADT/TinyPtrVector.h"</a></li>
<li><a href="#dss_smallvector">"llvm/ADT/SmallVector.h"</a></li>
<li><a href="#dss_vector">&lt;vector&gt;</a></li>
<li><a href="#dss_deque">&lt;deque&gt;</a></li>
@@ -67,6 +68,13 @@ option</a></li>
<li><a href="#dss_packedvector">llvm/ADT/PackedVector.h</a></li>
<li><a href="#dss_other">Other Sequential Container Options</a></li>
</ul></li>
+ <li><a href="#ds_string">String-like containers</a>
+ <ul>
+ <li><a href="#dss_stringref">llvm/ADT/StringRef.h</a></li>
+ <li><a href="#dss_twine">llvm/ADT/Twine.h</a></li>
+ <li><a href="#dss_smallstring">llvm/ADT/SmallString.h</a></li>
+ <li><a href="#dss_stdstring">std::string</a></li>
+ </ul></li>
<li><a href="#ds_set">Set-Like Containers (std::set, SmallSet, SetVector, etc)</a>
<ul>
<li><a href="#dss_sortedvectorset">A sorted 'vector'</a></li>
@@ -91,10 +99,6 @@ option</a></li>
<li><a href="#dss_inteqclasses">"llvm/ADT/IntEqClasses.h"</a></li>
<li><a href="#dss_othermap">Other Map-Like Container Options</a></li>
</ul></li>
- <li><a href="#ds_string">String-like containers</a>
- <!--<ul>
- todo
- </ul>--></li>
<li><a href="#ds_bit">BitVector-like containers</a>
<ul>
<li><a href="#dss_bitvector">A dense bitvector</a></li>
@@ -875,6 +879,9 @@ elements (but could contain many), for example, it's much better to use
. Doing so avoids (relatively) expensive malloc/free calls, which dwarf the
cost of adding the elements to the container. </p>
+</div>
+
+
<!-- ======================================================================= -->
<h3>
<a name="ds_sequential">Sequential Containers (std::vector, std::list, etc)</a>
@@ -883,7 +890,7 @@ cost of adding the elements to the container. </p>
<div>
There are a variety of sequential containers available for you, based on your
needs. Pick the first in this section that will do what you want.
-
+
<!-- _______________________________________________________________________ -->
<h4>
<a name="dss_arrayref">llvm/ADT/ArrayRef.h</a>
@@ -928,6 +935,22 @@ construct those elements actually used).</p>
<!-- _______________________________________________________________________ -->
<h4>
+ <a name="dss_tinyptrvector">"llvm/ADT/TinyPtrVector.h"</a>
+</h4>
+
+
+<div>
+<p><tt>TinyPtrVector&lt;Type&gt;</tt> is a highly specialized collection class
+that is optimized to avoid allocation in the case when a vector has zero or one
+elements. It has two major restrictions: 1) it can only hold values of pointer
+type, and 2) it cannot hold a null pointer.</p>
+
+<p>Since this container is highly specialized, it is rarely used.</p>
+
+</div>
+
+<!-- _______________________________________________________________________ -->
+<h4>
<a name="dss_smallvector">"llvm/ADT/SmallVector.h"</a>
</h4>
@@ -1190,9 +1213,187 @@ std::priority_queue, std::stack, etc. These provide simplified access to an
underlying container but don't affect the cost of the container itself.</p>
</div>
+</div>
+<!-- ======================================================================= -->
+<h3>
+ <a name="ds_string">String-like containers</a>
+</h3>
+
+<div>
+
+<p>
+There are a variety of ways to pass around and use strings in C and C++, and
+LLVM adds a few new options to choose from. Pick the first option on this list
+that will do what you need, they are ordered according to their relative cost.
+</p>
+<p>
+Note that is is generally preferred to <em>not</em> pass strings around as
+"<tt>const char*</tt>"'s. These have a number of problems, including the fact
+that they cannot represent embedded nul ("\0") characters, and do not have a
+length available efficiently. The general replacement for '<tt>const
+char*</tt>' is StringRef.
+</p>
+
+<p>For more information on choosing string containers for APIs, please see
+<a href="#string_apis">Passing strings</a>.</p>
+
+
+<!-- _______________________________________________________________________ -->
+<h4>
+ <a name="dss_stringref">llvm/ADT/StringRef.h</a>
+</h4>
+
+<div>
+<p>
+The StringRef class is a simple value class that contains a pointer to a
+character and a length, and is quite related to the <a
+href="#dss_arrayref">ArrayRef</a> class (but specialized for arrays of
+characters). Because StringRef carries a length with it, it safely handles
+strings with embedded nul characters in it, getting the length does not require
+a strlen call, and it even has very convenient APIs for slicing and dicing the
+character range that it represents.
+</p>
+
+<p>
+StringRef is ideal for passing simple strings around that are known to be live,
+either because they are C string literals, std::string, a C array, or a
+SmallVector. Each of these cases has an efficient implicit conversion to
+StringRef, which doesn't result in a dynamic strlen being executed.
+</p>
+
+<p>StringRef has a few major limitations which make more powerful string
+containers useful:</p>
+
+<ol>
+<li>You cannot directly convert a StringRef to a 'const char*' because there is
+no way to add a trailing nul (unlike the .c_str() method on various stronger
+classes).</li>
+
+
+<li>StringRef doesn't own or keep alive the underlying string bytes.
+As such it can easily lead to dangling pointers, and is not suitable for
+embedding in datastructures in most cases (instead, use an std::string or
+something like that).</li>
+
+<li>For the same reason, StringRef cannot be used as the return value of a
+method if the method "computes" the result string. Instead, use
+std::string.</li>
+
+<li>StringRef's do not allow you to mutate the pointed-to string bytes and it
+doesn't allow you to insert or remove bytes from the range. For editing
+operations like this, it interoperates with the <a
+href="#dss_twine">Twine</a> class.</li>
+</ol>
+
+<p>Because of its strengths and limitations, it is very common for a function to
+take a StringRef and for a method on an object to return a StringRef that
+points into some string that it owns.</p>
+
+</div>
+
+<!-- _______________________________________________________________________ -->
+<h4>
+ <a name="dss_twine">llvm/ADT/Twine.h</a>
+</h4>
+
+<div>
+ <p>
+ The Twine class is used as an intermediary datatype for APIs that want to take
+ a string that can be constructed inline with a series of concatenations.
+ Twine works by forming recursive instances of the Twine datatype (a simple
+ value object) on the stack as temporary objects, linking them together into a
+ tree which is then linearized when the Twine is consumed. Twine is only safe
+ to use as the argument to a function, and should always be a const reference,
+ e.g.:
+ </p>
+
+ <pre>
+ void foo(const Twine &amp;T);
+ ...
+ StringRef X = ...
+ unsigned i = ...
+ foo(X + "." + Twine(i));
+ </pre>
+
+ <p>This example forms a string like "blarg.42" by concatenating the values
+ together, and does not form intermediate strings containing "blarg" or
+ "blarg.".
+ </p>
+
+ <p>Because Twine is constructed with temporary objects on the stack, and
+ because these instances are destroyed at the end of the current statement,
+ it is an inherently dangerous API. For example, this simple variant contains
+ undefined behavior and will probably crash:</p>
+
+ <pre>
+ void foo(const Twine &amp;T);
+ ...
+ StringRef X = ...
+ unsigned i = ...
+ const Twine &amp;Tmp = X + "." + Twine(i);
+ foo(Tmp);
+ </pre>
+
+ <p>... because the temporaries are destroyed before the call. That said,
+ Twine's are much more efficient than intermediate std::string temporaries, and
+ they work really well with StringRef. Just be aware of their limitations.</p>
+
+</div>
+
+
+<!-- _______________________________________________________________________ -->
+<h4>
+ <a name="dss_smallstring">llvm/ADT/SmallString.h</a>
+</h4>
+
+<div>
+
+<p>SmallString is a subclass of <a href="#dss_smallvector">SmallVector</a> that
+adds some convenience APIs like += that takes StringRef's. SmallString avoids
+allocating memory in the case when the preallocated space is enough to hold its
+data, and it calls back to general heap allocation when required. Since it owns
+its data, it is very safe to use and supports full mutation of the string.</p>
+
+<p>Like SmallVector's, the big downside to SmallString is their sizeof. While
+they are optimized for small strings, they themselves are not particularly
+small. This means that they work great for temporary scratch buffers on the
+stack, but should not generally be put into the heap: it is very rare to
+see a SmallString as the member of a frequently-allocated heap data structure
+or returned by-value.
+</p>
+
+</div>
+
+<!-- _______________________________________________________________________ -->
+<h4>
+ <a name="dss_stdstring">std::string</a>
+</h4>
+
+<div>
+
+ <p>The standard C++ std::string class is a very general class that (like
+ SmallString) owns its underlying data. sizeof(std::string) is very reasonable
+ so it can be embedded into heap data structures and returned by-value.
+ On the other hand, std::string is highly inefficient for inline editing (e.g.
+ concatenating a bunch of stuff together) and because it is provided by the
+ standard library, its performance characteristics depend a lot of the host
+ standard library (e.g. libc++ and MSVC provide a highly optimized string
+ class, GCC contains a really slow implementation).
+ </p>
+
+ <p>The major disadvantage of std::string is that almost every operation that
+ makes them larger can allocate memory, which is slow. As such, it is better
+ to use SmallVector or Twine as a scratch buffer, but then use std::string to
+ persist the result.</p>
+
+
+</div>
+
+<!-- end of strings -->
</div>
+
<!-- ======================================================================= -->
<h3>
<a name="ds_set">Set-Like Containers (std::set, SmallSet, SetVector, etc)</a>
@@ -1381,12 +1582,13 @@ elements out of (linear time), unless you use it's "pop_back" method, which is
faster.
</p>
-<p>SetVector is an adapter class that defaults to using std::vector and std::set
-for the underlying containers, so it is quite expensive. However,
-<tt>"llvm/ADT/SetVector.h"</tt> also provides a SmallSetVector class, which
-defaults to using a SmallVector and SmallSet of a specified size. If you use
-this, and if your sets are dynamically smaller than N, you will save a lot of
-heap traffic.</p>
+<p><tt>SetVector</tt> is an adapter class that defaults to
+ using <tt>std::vector</tt> and a size 16 <tt>SmallSet</tt> for the underlying
+ containers, so it is quite expensive. However,
+ <tt>"llvm/ADT/SetVector.h"</tt> also provides a <tt>SmallSetVector</tt>
+ class, which defaults to using a <tt>SmallVector</tt> and <tt>SmallSet</tt>
+ of a specified size. If you use this, and if your sets are dynamically
+ smaller than <tt>N</tt>, you will save a lot of heap traffic.</p>
</div>
@@ -1636,20 +1838,6 @@ always better.</p>
<!-- ======================================================================= -->
<h3>
- <a name="ds_string">String-like containers</a>
-</h3>
-
-<div>
-
-<p>
-TODO: const char* vs stringref vs smallstring vs std::string. Describe twine,
-xref to #string_apis.
-</p>
-
-</div>
-
-<!-- ======================================================================= -->
-<h3>
<a name="ds_bit">Bit storage containers (BitVector, SparseBitVector)</a>
</h3>
@@ -3867,7 +4055,7 @@ arguments. An argument has a pointer to the parent Function.</p>
<a href="mailto:dhurjati@cs.uiuc.edu">Dinakar Dhurjati</a> and
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-07-12 13:37:02 +0200 (Tue, 12 Jul 2011) $
+ Last modified: $Date: 2011-10-11 08:33:56 +0200 (Tue, 11 Oct 2011) $
</address>
</body>
diff --git a/docs/ReleaseNotes.html b/docs/ReleaseNotes.html
index d54698d..b0d4f67 100644
--- a/docs/ReleaseNotes.html
+++ b/docs/ReleaseNotes.html
@@ -44,21 +44,21 @@ Release Notes</a>.</h1>
<div>
<p>This document contains the release notes for the LLVM Compiler
-Infrastructure, release 3.0. Here we describe the status of LLVM, including
-major improvements from the previous release and significant known problems.
-All LLVM releases may be downloaded from the <a
-href="http://llvm.org/releases/">LLVM releases web site</a>.</p>
+ Infrastructure, release 3.0. Here we describe the status of LLVM, including
+ major improvements from the previous release and significant known problems.
+ All LLVM releases may be downloaded from
+ the <a href="http://llvm.org/releases/">LLVM releases web site</a>.</p>
<p>For more information about LLVM, including information about the latest
-release, please check out the <a href="http://llvm.org/">main LLVM
-web site</a>. If you have questions or comments, the <a
-href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVM Developer's
-Mailing List</a> is a good place to send them.</p>
+ release, please check out the <a href="http://llvm.org/">main LLVM web
+ site</a>. If you have questions or comments,
+ the <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVM
+ Developer's Mailing List</a> is a good place to send them.</p>
-<p>Note that if you are reading this file from a Subversion checkout or the
-main LLVM web page, this document applies to the <i>next</i> release, not the
-current one. To see the release notes for a specific release, please see the
-<a href="http://llvm.org/releases/">releases page</a>.</p>
+<p>Note that if you are reading this file from a Subversion checkout or the main
+ LLVM web page, this document applies to the <i>next</i> release, not the
+ current one. To see the release notes for a specific release, please see the
+ <a href="http://llvm.org/releases/">releases page</a>.</p>
</div>
@@ -78,13 +78,12 @@ current one. To see the release notes for a specific release, please see the
<!-- *********************************************************************** -->
<div>
-<p>
-The LLVM 3.0 distribution currently consists of code from the core LLVM
-repository (which roughly includes the LLVM optimizers, code generators
-and supporting tools), the Clang repository and the llvm-gcc repository. In
-addition to this code, the LLVM Project includes other sub-projects that are in
-development. Here we include updates on these subprojects.
-</p>
+
+<p>The LLVM 3.0 distribution currently consists of code from the core LLVM
+ repository (which roughly includes the LLVM optimizers, code generators and
+ supporting tools), the Clang repository and the llvm-gcc repository. In
+ addition to this code, the LLVM Project includes other sub-projects that are
+ in development. Here we include updates on these subprojects.</p>
<!--=========================================================================-->
<h3>
@@ -94,20 +93,47 @@ development. Here we include updates on these subprojects.
<div>
<p><a href="http://clang.llvm.org/">Clang</a> is an LLVM front end for the C,
-C++, and Objective-C languages. Clang aims to provide a better user experience
-through expressive diagnostics, a high level of conformance to language
-standards, fast compilation, and low memory use. Like LLVM, Clang provides a
-modular, library-based architecture that makes it suitable for creating or
-integrating with other development tools. Clang is considered a
-production-quality compiler for C, Objective-C, C++ and Objective-C++ on x86
-(32- and 64-bit), and for darwin/arm targets.</p>
+ C++, and Objective-C languages. Clang aims to provide a better user
+ experience through expressive diagnostics, a high level of conformance to
+ language standards, fast compilation, and low memory use. Like LLVM, Clang
+ provides a modular, library-based architecture that makes it suitable for
+ creating or integrating with other development tools. Clang is considered a
+ production-quality compiler for C, Objective-C, C++ and Objective-C++ on x86
+ (32- and 64-bit), and for darwin/arm targets.</p>
<p>In the LLVM 3.0 time-frame, the Clang team has made many improvements:</p>
+
+<ul>
+ <li>Greatly improved support for building C++ applications, with greater
+ stability and better diagnostics.</li>
+
+ <li><a href="http://clang.llvm.org/cxx_status.html">Improved support</a> for
+ the <a href="http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=50372">C++
+ 2011</a> standard, including implementations of non-static data member
+ initializers, alias templates, delegating constructors, the range-based
+ for loop, and implicitly-generated move constructors and move assignment
+ operators, among others.</li>
+
+ <li>Implemented support for some features of the upcoming C1x standard,
+ including static assertions and generic selections.</li>
+
+ <li>Better detection of include and linking paths for system headers and
+ libraries, especially for Linux distributions.</li>
+
+ <li>Implemented support
+ for <a href="http://clang.llvm.org/docs/AutomaticReferenceCounting.html">Automatic
+ Reference Counting</a> for Objective-C.</li>
+
+ <li>Implemented a number of optimizations in <tt>libclang</tt>, the Clang C
+ interface, to improve the performance of code completion and the mapping
+ from source locations to abstract syntax tree nodes.</li>
+</ul>
+
<p>If Clang rejects your code but another compiler accepts it, please take a
-look at the <a href="http://clang.llvm.org/compatibility.html">language
-compatibility</a> guide to make sure this is not intentional or a known issue.
-</p>
+ look at the <a href="http://clang.llvm.org/compatibility.html">language
+ compatibility</a> guide to make sure this is not intentional or a known
+ issue.</p>
</div>
@@ -117,20 +143,17 @@ compatibility</a> guide to make sure this is not intentional or a known issue.
</h3>
<div>
-<p>
-<a href="http://dragonegg.llvm.org/">DragonEgg</a> is a
-<a href="http://gcc.gnu.org/wiki/plugins">gcc plugin</a> that replaces GCC's
-optimizers and code generators with LLVM's.
-Currently it requires a patched version of gcc-4.5.
-The plugin can target the x86-32 and x86-64 processor families and has been
-used successfully on the Darwin, FreeBSD and Linux platforms.
-The Ada, C, C++ and Fortran languages work well.
-The plugin is capable of compiling plenty of Obj-C, Obj-C++ and Java but it is
-not known whether the compiled code actually works or not!
-</p>
+<p><a href="http://dragonegg.llvm.org/">DragonEgg</a> is a
+ <a href="http://gcc.gnu.org/wiki/plugins">gcc plugin</a> that replaces GCC's
+ optimizers and code generators with LLVM's. Currently it requires a patched
+ version of gcc-4.5. The plugin can target the x86-32 and x86-64 processor
+ families and has been used successfully on the Darwin, FreeBSD and Linux
+ platforms. The Ada, C, C++ and Fortran languages work well. The plugin is
+ capable of compiling plenty of Obj-C, Obj-C++ and Java but it is not known
+ whether the compiled code actually works or not!</p>
+
+<p>The 3.0 release has the following notable changes:</p>
-<p>
-The 3.0 release has the following notable changes:
<ul>
<!--
<li></li>
@@ -145,15 +168,15 @@ The 3.0 release has the following notable changes:
</h3>
<div>
-<p>
-The new LLVM <a href="http://compiler-rt.llvm.org/">compiler-rt project</a>
-is a simple library that provides an implementation of the low-level
-target-specific hooks required by code generation and other runtime components.
-For example, when compiling for a 32-bit target, converting a double to a 64-bit
-unsigned integer is compiled into a runtime call to the "__fixunsdfdi"
-function. The compiler-rt library provides highly optimized implementations of
-this and other low-level routines (some are 3x faster than the equivalent
-libgcc routines).</p>
+
+<p>The new LLVM <a href="http://compiler-rt.llvm.org/">compiler-rt project</a>
+ is a simple library that provides an implementation of the low-level
+ target-specific hooks required by code generation and other runtime
+ components. For example, when compiling for a 32-bit target, converting a
+ double to a 64-bit unsigned integer is compiled into a runtime call to the
+ "__fixunsdfdi" function. The compiler-rt library provides highly optimized
+ implementations of this and other low-level routines (some are 3x faster than
+ the equivalent libgcc routines).</p>
<p>In the LLVM 3.0 timeframe,</p>
@@ -165,19 +188,18 @@ libgcc routines).</p>
</h3>
<div>
-<p>
-<a href="http://lldb.llvm.org/">LLDB</a> is a brand new member of the LLVM
-umbrella of projects. LLDB is a next generation, high-performance debugger. It
-is built as a set of reusable components which highly leverage existing
-libraries in the larger LLVM Project, such as the Clang expression parser, the
-LLVM disassembler and the LLVM JIT.</p>
-<p>
-LLDB is has advanced by leaps and bounds in the 3.0 timeframe. It is
-dramatically more stable and useful, and includes both a new <a
-href="http://lldb.llvm.org/tutorial.html">tutorial</a> and a <a
-href="http://lldb.llvm.org/lldb-gdb.html">side-by-side comparison with
-GDB</a>.</p>
+<p><a href="http://lldb.llvm.org/">LLDB</a> is a brand new member of the LLVM
+ umbrella of projects. LLDB is a next generation, high-performance
+ debugger. It is built as a set of reusable components which highly leverage
+ existing libraries in the larger LLVM Project, such as the Clang expression
+ parser, the LLVM disassembler and the LLVM JIT.</p>
+
+<p>LLDB is has advanced by leaps and bounds in the 3.0 timeframe. It is
+ dramatically more stable and useful, and includes both a
+ new <a href="http://lldb.llvm.org/tutorial.html">tutorial</a> and
+ a <a href="http://lldb.llvm.org/lldb-gdb.html">side-by-side comparison with
+ GDB</a>.</p>
</div>
@@ -187,20 +209,17 @@ GDB</a>.</p>
</h3>
<div>
-<p>
-<a href="http://libcxx.llvm.org/">libc++</a> is another new member of the LLVM
-family. It is an implementation of the C++ standard library, written from the
-ground up to specifically target the forthcoming C++'0X standard and focus on
-delivering great performance.</p>
-<p>
-In the LLVM 3.0 timeframe,</p>
+<p><a href="http://libcxx.llvm.org/">libc++</a> is another new member of the
+ LLVM family. It is an implementation of the C++ standard library, written
+ from the ground up to specifically target the forthcoming C++'0X standard and
+ focus on delivering great performance.</p>
+
+<p>In the LLVM 3.0 timeframe,</p>
-<p>
-Like compiler_rt, libc++ is now <a href="DeveloperPolicy.html#license">dual
- licensed</a> under the MIT and UIUC license, allowing it to be used more
- permissively.
-</p>
+<p>Like compiler_rt, libc++ is now <a href="DeveloperPolicy.html#license">dual
+ licensed</a> under the MIT and UIUC license, allowing it to be used more
+ permissively.</p>
</div>
@@ -211,13 +230,14 @@ Like compiler_rt, libc++ is now <a href="DeveloperPolicy.html#license">dual
</h3>
<div>
-<p>
-<a href="http://llvm.org/svn/llvm-project/llbrowse/trunk/doc/LLBrowse.html">
- LLBrowse</a> is an interactive viewer for LLVM modules. It can load any LLVM
- module and displays its contents as an expandable tree view, facilitating an
- easy way to inspect types, functions, global variables, or metadata nodes. It
- is fully cross-platform, being based on the popular wxWidgets GUI toolkit.
-</p>
+
+<p><a href="http://llvm.org/svn/llvm-project/llbrowse/trunk/doc/LLBrowse.html">
+ LLBrowse</a> is an interactive viewer for LLVM modules. It can load any LLVM
+ module and displays its contents as an expandable tree view, facilitating an
+ easy way to inspect types, functions, global variables, or metadata nodes. It
+ is fully cross-platform, being based on the popular wxWidgets GUI
+ toolkit.</p>
+
</div>
<!--=========================================================================-->
@@ -226,13 +246,14 @@ Like compiler_rt, libc++ is now <a href="DeveloperPolicy.html#license">dual
</h3>
<div>
+
<p>The <a href="http://vmkit.llvm.org/">VMKit project</a> is an implementation
- of a Java Virtual Machine (Java VM or JVM) that uses LLVM for static and
- just-in-time compilation. As of LLVM 3.0, VMKit now supports generational
- garbage collectors. The garbage collectors are provided by the MMTk framework,
- and VMKit can be configured to use one of the numerous implemented collectors
- of MMTk.
-</p>
+ of a Java Virtual Machine (Java VM or JVM) that uses LLVM for static and
+ just-in-time compilation. As of LLVM 3.0, VMKit now supports generational
+ garbage collectors. The garbage collectors are provided by the MMTk
+ framework, and VMKit can be configured to use one of the numerous implemented
+ collectors of MMTk.</p>
+
</div>
@@ -272,125 +293,133 @@ be used to verify some algorithms.
<h3>Crack Programming Language</h3>
<div>
-<p>
-<a href="http://code.google.com/p/crack-language/">Crack</a> aims to provide the
-ease of development of a scripting language with the performance of a compiled
-language. The language derives concepts from C++, Java and Python, incorporating
-object-oriented programming, operator overloading and strong typing.</p>
+
+<p><a href="http://code.google.com/p/crack-language/">Crack</a> aims to provide
+ the ease of development of a scripting language with the performance of a
+ compiled language. The language derives concepts from C++, Java and Python,
+ incorporating object-oriented programming, operator overloading and strong
+ typing.</p>
+
</div>
-
<!--=========================================================================-->
<h3>TTA-based Codesign Environment (TCE)</h3>
<div>
+
<p>TCE is a toolset for designing application-specific processors (ASP) based on
-the Transport triggered architecture (TTA). The toolset provides a complete
-co-design flow from C/C++ programs down to synthesizable VHDL and parallel
-program binaries. Processor customization points include the register files,
-function units, supported operations, and the interconnection network.</p>
+ the Transport triggered architecture (TTA). The toolset provides a complete
+ co-design flow from C/C++ programs down to synthesizable VHDL and parallel
+ program binaries. Processor customization points include the register files,
+ function units, supported operations, and the interconnection network.</p>
<p>TCE uses Clang and LLVM for C/C++ language support, target independent
-optimizations and also for parts of code generation. It generates new LLVM-based
-code generators "on the fly" for the designed TTA processors and loads them in
-to the compiler backend as runtime libraries to avoid per-target recompilation
-of larger parts of the compiler chain.</p>
-</div>
-
+ optimizations and also for parts of code generation. It generates new
+ LLVM-based code generators "on the fly" for the designed TTA processors and
+ loads them in to the compiler backend as runtime libraries to avoid
+ per-target recompilation of larger parts of the compiler chain.</p>
+</div>
<!--=========================================================================-->
<h3>PinaVM</h3>
<div>
+
<p><a href="http://gitorious.org/pinavm/pages/Home">PinaVM</a> is an open
-source, <a href="http://www.systemc.org/">SystemC</a> front-end. Unlike many
-other front-ends, PinaVM actually executes the elaboration of the
-program analyzed using LLVM's JIT infrastructure. It later enriches the
-bitcode with SystemC-specific information.</p>
+ source, <a href="http://www.systemc.org/">SystemC</a> front-end. Unlike many
+ other front-ends, PinaVM actually executes the elaboration of the program
+ analyzed using LLVM's JIT infrastructure. It later enriches the bitcode with
+ SystemC-specific information.</p>
+
</div>
<!--=========================================================================-->
<h3>Pure</h3>
<div>
+
<p><a href="http://pure-lang.googlecode.com/">Pure</a> is an
- algebraic/functional
- programming language based on term rewriting. Programs are collections
- of equations which are used to evaluate expressions in a symbolic
- fashion. The interpreter uses LLVM as a backend to JIT-compile Pure
- programs to fast native code. Pure offers dynamic typing, eager and lazy
- evaluation, lexical closures, a hygienic macro system (also based on
- term rewriting), built-in list and matrix support (including list and
- matrix comprehensions) and an easy-to-use interface to C and other
- programming languages (including the ability to load LLVM bitcode
- modules, and inline C, C++, Fortran and Faust code in Pure programs if
- the corresponding LLVM-enabled compilers are installed).</p>
+ algebraic/functional programming language based on term rewriting. Programs
+ are collections of equations which are used to evaluate expressions in a
+ symbolic fashion. The interpreter uses LLVM as a backend to JIT-compile Pure
+ programs to fast native code. Pure offers dynamic typing, eager and lazy
+ evaluation, lexical closures, a hygienic macro system (also based on term
+ rewriting), built-in list and matrix support (including list and matrix
+ comprehensions) and an easy-to-use interface to C and other programming
+ languages (including the ability to load LLVM bitcode modules, and inline C,
+ C++, Fortran and Faust code in Pure programs if the corresponding
+ LLVM-enabled compilers are installed).</p>
-<p>Pure version 0.47 has been tested and is known to work with LLVM 3.0
- (and continues to work with older LLVM releases &gt;= 2.5).</p>
+<p>Pure version 0.47 has been tested and is known to work with LLVM 3.0 (and
+ continues to work with older LLVM releases &gt;= 2.5).</p>
+
</div>
<!--=========================================================================-->
<h3 id="icedtea">IcedTea Java Virtual Machine Implementation</h3>
<div>
-<p>
-<a href="http://icedtea.classpath.org/wiki/Main_Page">IcedTea</a> provides a
-harness to build OpenJDK using only free software build tools and to provide
-replacements for the not-yet free parts of OpenJDK. One of the extensions that
-IcedTea provides is a new JIT compiler named <a
-href="http://icedtea.classpath.org/wiki/ZeroSharkFaq">Shark</a> which uses LLVM
-to provide native code generation without introducing processor-dependent
-code.
-</p>
-<p> OpenJDK 7 b112, IcedTea6 1.9 and IcedTea7 1.13 and later have been tested
-and are known to work with LLVM 3.0 (and continue to work with older LLVM
-releases &gt;= 2.6 as well).</p>
+<p><a href="http://icedtea.classpath.org/wiki/Main_Page">IcedTea</a> provides a
+ harness to build OpenJDK using only free software build tools and to provide
+ replacements for the not-yet free parts of OpenJDK. One of the extensions
+ that IcedTea provides is a new JIT compiler
+ named <a href="http://icedtea.classpath.org/wiki/ZeroSharkFaq">Shark</a>
+ which uses LLVM to provide native code generation without introducing
+ processor-dependent code.</p>
+
+<p>OpenJDK 7 b112, IcedTea6 1.9 and IcedTea7 1.13 and later have been tested and
+ are known to work with LLVM 3.0 (and continue to work with older LLVM
+ releases &gt;= 2.6 as well).</p>
+
</div>
<!--=========================================================================-->
<h3>Glasgow Haskell Compiler (GHC)</h3>
<div>
-<p>GHC is an open source, state-of-the-art programming suite for Haskell,
-a standard lazy functional programming language. It includes an
-optimizing static compiler generating good code for a variety of
-platforms, together with an interactive system for convenient, quick
-development.</p>
+
+<p>GHC is an open source, state-of-the-art programming suite for Haskell, a
+ standard lazy functional programming language. It includes an optimizing
+ static compiler generating good code for a variety of platforms, together
+ with an interactive system for convenient, quick development.</p>
<p>In addition to the existing C and native code generators, GHC 7.0 now
-supports an LLVM code generator. GHC supports LLVM 2.7 and later.</p>
+ supports an LLVM code generator. GHC supports LLVM 2.7 and later.</p>
+
</div>
<!--=========================================================================-->
<h3>Polly - Polyhedral optimizations for LLVM</h3>
<div>
+
<p>Polly is a project that aims to provide advanced memory access optimizations
-to better take advantage of SIMD units, cache hierarchies, multiple cores or
-even vector accelerators for LLVM. Built around an abstract mathematical
-description based on Z-polyhedra, it provides the infrastructure to develop
-advanced optimizations in LLVM and to connect complex external optimizers. In
-its first year of existence Polly already provides an exact value-based
-dependency analysis as well as basic SIMD and OpenMP code generation support.
-Furthermore, Polly can use PoCC(Pluto) an advanced optimizer for data-locality
-and parallelism.</p>
+ to better take advantage of SIMD units, cache hierarchies, multiple cores or
+ even vector accelerators for LLVM. Built around an abstract mathematical
+ description based on Z-polyhedra, it provides the infrastructure to develop
+ advanced optimizations in LLVM and to connect complex external optimizers. In
+ its first year of existence Polly already provides an exact value-based
+ dependency analysis as well as basic SIMD and OpenMP code generation support.
+ Furthermore, Polly can use PoCC(Pluto) an advanced optimizer for
+ data-locality and parallelism.</p>
+
</div>
<!--=========================================================================-->
<h3>Rubinius</h3>
<div>
- <p><a href="http://github.com/evanphx/rubinius">Rubinius</a> is an environment
- for running Ruby code which strives to write as much of the implementation in
- Ruby as possible. Combined with a bytecode interpreting VM, it uses LLVM to
- optimize and compile ruby code down to machine code. Techniques such as type
- feedback, method inlining, and deoptimization are all used to remove dynamism
- from ruby execution and increase performance.</p>
-</div>
+<p><a href="http://github.com/evanphx/rubinius">Rubinius</a> is an environment
+ for running Ruby code which strives to write as much of the implementation in
+ Ruby as possible. Combined with a bytecode interpreting VM, it uses LLVM to
+ optimize and compile ruby code down to machine code. Techniques such as type
+ feedback, method inlining, and deoptimization are all used to remove dynamism
+ from ruby execution and increase performance.</p>
+
+</div>
<!--=========================================================================-->
<h3>
@@ -398,12 +427,13 @@ and parallelism.</p>
</h3>
<div>
-<p>
-<a href="http://faust.grame.fr">FAUST</a> is a compiled language for real-time
-audio signal processing. The name FAUST stands for Functional AUdio STream. Its
-programming model combines two approaches: functional programming and block
-diagram composition. In addition with the C, C++, JAVA output formats, the
-Faust compiler can now generate LLVM bitcode, and works with LLVM 2.7-3.0.</p>
+
+<p><a href="http://faust.grame.fr">FAUST</a> is a compiled language for
+ real-time audio signal processing. The name FAUST stands for Functional AUdio
+ STream. Its programming model combines two approaches: functional programming
+ and block diagram composition. In addition with the C, C++, JAVA output
+ formats, the Faust compiler can now generate LLVM bitcode, and works with
+ LLVM 2.7-3.0.</p>
</div>
@@ -418,9 +448,8 @@ Faust compiler can now generate LLVM bitcode, and works with LLVM 2.7-3.0.</p>
<div>
<p>This release includes a huge number of bug fixes, performance tweaks and
-minor improvements. Some of the major improvements and new features are listed
-in this section.
-</p>
+ minor improvements. Some of the major improvements and new features are
+ listed in this section.</p>
<!--=========================================================================-->
<h3>
@@ -447,15 +476,121 @@ in this section.
</h3>
<div>
+
<p>LLVM IR has several new features for better support of new targets and that
-expose new optimization opportunities:</p>
+ expose new optimization opportunities:</p>
+
+<p>One of the biggest changes is that 3.0 has a new exception handling
+ system. The old system used LLVM intrinsics to convey the exception handling
+ information to the code generator. It worked in most cases, but not
+ all. Inlining was especially difficult to get right. Also, the intrinsics
+ could be moved away from the <code>invoke</code> instruction, making it hard
+ to recover that information.</p>
+
+<p>The new EH system makes exception handling a first-class member of the IR. It
+ adds two new instructions:</p>
<ul>
-<!--
-<li></li>
--->
+ <li><a href="LangRef.html#i_landingpad"><code>landingpad</code></a> &mdash;
+ this instruction defines a landing pad basic block. It contains all of the
+ information that's needed by the code generator. It's also required to be
+ the first non-PHI instruction in the landing pad. In addition, a landing
+ pad may be jumped to only by the unwind edge of an <code>invoke</code>
+ instruction.</li>
+
+ <li><a href="LangRef.html#i_resume"><code>resume</code></a> &mdash; this
+ instruction causes the current exception to resume traveling up the
+ stack. It replaces the <code>@llvm.eh.resume</code> intrinsic.</li>
</ul>
+<p>Converting from the old EH API to the new EH API is rather simple, because a
+ lot of complexity has been removed. The two intrinsics,
+ <code>@llvm.eh.exception</code> and <code>@llvm.eh.selector</code> have been
+ superceded by the <code>landingpad</code> instruction. Instead of generating
+ a call to <code>@llvm.eh.exception</code> and <code>@llvm.eh.selector</code>:
+
+<div class="doc_code">
+<pre>
+Function *ExcIntr = Intrinsic::getDeclaration(TheModule,
+ Intrinsic::eh_exception);
+Function *SlctrIntr = Intrinsic::getDeclaration(TheModule,
+ Intrinsic::eh_selector);
+
+// The exception pointer.
+Value *ExnPtr = Builder.CreateCall(ExcIntr, "exc_ptr");
+
+std::vector&lt;Value*&gt; Args;
+Args.push_back(ExnPtr);
+Args.push_back(Builder.CreateBitCast(Personality,
+ Type::getInt8PtrTy(Context)));
+
+<i>// Add selector clauses to Args.</i>
+
+// The selector call.
+Builder.CreateCall(SlctrIntr, Args, "exc_sel");
+</pre>
+</div>
+
+<p>You should instead generate a <code>landingpad</code> instruction, that
+ returns an exception object and selector value:</p>
+
+<div class="doc_code">
+<pre>
+LandingPadInst *LPadInst =
+ Builder.CreateLandingPad(StructType::get(Int8PtrTy, Int32Ty, NULL),
+ Personality, 0);
+
+Value *LPadExn = Builder.CreateExtractValue(LPadInst, 0);
+Builder.CreateStore(LPadExn, getExceptionSlot());
+
+Value *LPadSel = Builder.CreateExtractValue(LPadInst, 1);
+Builder.CreateStore(LPadSel, getEHSelectorSlot());
+</pre>
+</div>
+
+<p>It's now trivial to add the individual clauses to the <code>landingpad</code>
+ instruction.</p>
+
+<div class="doc_code">
+<pre>
+<i><b>// Adding a catch clause</b></i>
+Constant *TypeInfo = getTypeInfo();
+LPadInst-&gt;addClause(TypeInfo);
+
+<i><b>// Adding a C++ catch-all</b></i>
+LPadInst-&gt;addClause(Constant::getNullValue(Builder.getInt8PtrTy()));
+
+<i><b>// Adding a cleanup</b></i>
+LPadInst-&gt;setCleanup(true);
+
+<i><b>// Adding a filter clause</b></i>
+std::vector&lt;Constant*&gt; TypeInfos;
+Constant *TypeInfo = getFilterTypeInfo();
+TypeInfos.push_back(Builder.CreateBitCast(TypeInfo, Builder.getInt8PtrTy()));
+
+ArrayType *FilterTy = ArrayType::get(Int8PtrTy, TypeInfos.size());
+LPadInst-&gt;addClause(ConstantArray::get(FilterTy, TypeInfos));
+</pre>
+</div>
+
+<p>Converting from using the <code>@llvm.eh.resume</code> intrinsic to
+ the <code>resume</code> instruction is trivial. It takes the exception
+ pointer and exception selector values returned by
+ the <code>landingpad</code> instruction:</p>
+
+<div class="doc_code">
+<pre>
+Type *UnwindDataTy = StructType::get(Builder.getInt8PtrTy(),
+ Builder.getInt32Ty(), NULL);
+Value *UnwindData = UndefValue::get(UnwindDataTy);
+Value *ExcPtr = Builder.CreateLoad(getExceptionObjSlot());
+Value *ExcSel = Builder.CreateLoad(getExceptionSelSlot());
+UnwindData = Builder.CreateInsertValue(UnwindData, ExcPtr, 0, "exc_ptr");
+UnwindData = Builder.CreateInsertValue(UnwindData, ExcSel, 1, "exc_sel");
+Builder.CreateResume(UnwindData);
+</pre>
+</div>
+
</div>
<!--=========================================================================-->
@@ -466,7 +601,8 @@ expose new optimization opportunities:</p>
<div>
<p>In addition to a large array of minor performance tweaks and bug fixes, this
-release includes a few major enhancements and additions to the optimizers:</p>
+ release includes a few major enhancements and additions to the
+ optimizers:</p>
<ul>
<!--
@@ -484,11 +620,11 @@ release includes a few major enhancements and additions to the optimizers:</p>
</h3>
<div>
-<p>
-The LLVM Machine Code (aka MC) subsystem was created to solve a number
-of problems in the realm of assembly, disassembly, object file format handling,
-and a number of other related areas that CPU instruction-set level tools work
-in.</p>
+
+<p>The LLVM Machine Code (aka MC) subsystem was created to solve a number of
+ problems in the realm of assembly, disassembly, object file format handling,
+ and a number of other related areas that CPU instruction-set level tools work
+ in.</p>
<ul>
<!--
@@ -496,10 +632,9 @@ in.</p>
-->
</ul>
-<p>For more information, please see the <a
-href="http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html">Intro to the
-LLVM MC Project Blog Post</a>.
-</p>
+<p>For more information, please see
+ the <a href="http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html">Intro
+ to the LLVM MC Project Blog Post</a>.</p>
</div>
@@ -511,8 +646,8 @@ LLVM MC Project Blog Post</a>.
<div>
<p>We have put a significant amount of work into the code generator
-infrastructure, which allows us to implement more aggressive algorithms and make
-it run faster:</p>
+ infrastructure, which allows us to implement more aggressive algorithms and
+ make it run faster:</p>
<ul>
<!--
@@ -527,14 +662,16 @@ it run faster:</p>
</h3>
<div>
-<p>New features and major changes in the X86 target include:
-</p>
+
+<p>New features and major changes in the X86 target include:</p>
<ul>
-<li>The CRC32 intrinsics have been renamed. The intrinsics were previously
- @llvm.x86.sse42.crc32.[8|16|32] and @llvm.x86.sse42.crc64.[8|64]. They have
- been renamed to @llvm.x86.sse42.crc32.32.[8|16|32] and
- @llvm.x86.sse42.crc32.64.[8|64].</li>
+
+ <li>The CRC32 intrinsics have been renamed. The intrinsics were previously
+ <code>@llvm.x86.sse42.crc32.[8|16|32]</code>
+ and <code>@llvm.x86.sse42.crc64.[8|64]</code>. They have been renamed to
+ <code>@llvm.x86.sse42.crc32.32.[8|16|32]</code> and
+ <code>@llvm.x86.sse42.crc32.64.[8|64]</code>.</li>
</ul>
@@ -546,8 +683,8 @@ it run faster:</p>
</h3>
<div>
-<p>New features of the ARM target include:
-</p>
+
+<p>New features of the ARM target include:</p>
<ul>
<!--
@@ -562,11 +699,13 @@ it run faster:</p>
</h3>
<div>
+
<ul>
<!--
<li></li>
-->
</ul>
+
</div>
<!--=========================================================================-->
@@ -576,18 +715,35 @@ it run faster:</p>
<div>
-<p>If you're already an LLVM user or developer with out-of-tree changes based
-on LLVM 2.9, this section lists some "gotchas" that you may run into upgrading
-from the previous release.</p>
+<p>If you're already an LLVM user or developer with out-of-tree changes based on
+ LLVM 2.9, this section lists some "gotchas" that you may run into upgrading
+ from the previous release.</p>
<ul>
-<!--
-<li></li>
--->
+ <li>The <code>LLVMC</code> front end code was removed while separating
+ out language independence.</li>
+ <li>The <code>LowerSetJmp</code> pass wasn't used effectively by any
+ target and has been removed.</li>
+ <li>The old <code>TailDup</code> pass was not used in the standard pipeline
+ and was unable to update ssa form, so it has been removed.
+ <li>The syntax of volatile loads and stores in IR has been changed to
+ "<code>load volatile</code>"/"<code>store volatile</code>". The old
+ syntax ("<code>volatile load</code>"/"<code>volatile store</code>")
+ is still accepted, but is now considered deprecated.</li>
+</ul>
+
+<h4>Windows (32-bit)</h4>
+<div>
+
+<ul>
+ <li>On Win32(MinGW32 and MSVC), Windows 2000 will not be supported.
+ Windows XP or higher is required.</li>
</ul>
</div>
+</div>
+
<!--=========================================================================-->
<h3>
<a name="api_changes">Internal API Changes</a>
@@ -596,33 +752,41 @@ from the previous release.</p>
<div>
<p>In addition, many APIs have changed in this release. Some of the major
- LLVM API changes are:</p>
+ LLVM API changes are:</p>
<ul>
-
-<li><code>PHINode::reserveOperandSpace</code> has been removed. Instead, you
- must specify how many operands to reserve space for when you create the
- PHINode, by passing an extra argument into <code>PHINode::Create</code>.</li>
-
-<li>PHINodes no longer store their incoming BasicBlocks as operands. Instead,
- the list of incoming BasicBlocks is stored separately, and can be accessed
- with new functions <code>PHINode::block_begin</code>
- and <code>PHINode::block_end</code>.</li>
-
-<li>Various functions now take an <code>ArrayRef</code> instead of either a pair
- of pointers (or iterators) to the beginning and end of a range, or a pointer
- and a length. Others now return an <code>ArrayRef</code> instead of a
- reference to a <code>SmallVector</code> or <code>std::vector</code>. These
- include:
+ <li>The biggest and most pervasive change is that llvm::Type's are no longer
+ returned or accepted as 'const' values. Instead, just pass around
+ non-const Type's.</li>
+
+ <li><code>PHINode::reserveOperandSpace</code> has been removed. Instead, you
+ must specify how many operands to reserve space for when you create the
+ PHINode, by passing an extra argument
+ into <code>PHINode::Create</code>.</li>
+
+ <li>PHINodes no longer store their incoming BasicBlocks as operands. Instead,
+ the list of incoming BasicBlocks is stored separately, and can be accessed
+ with new functions <code>PHINode::block_begin</code>
+ and <code>PHINode::block_end</code>.</li>
+
+ <li>Various functions now take an <code>ArrayRef</code> instead of either a
+ pair of pointers (or iterators) to the beginning and end of a range, or a
+ pointer and a length. Others now return an <code>ArrayRef</code> instead
+ of a reference to a <code>SmallVector</code>
+ or <code>std::vector</code>. These include:
<ul>
<!-- Please keep this list sorted. -->
<li><code>CallInst::Create</code></li>
<li><code>ComputeLinearIndex</code> (in <code>llvm/CodeGen/Analysis.h</code>)</li>
<li><code>ConstantArray::get</code></li>
<li><code>ConstantExpr::getExtractElement</code></li>
+<li><code>ConstantExpr::getGetElementPtr</code></li>
+<li><code>ConstantExpr::getInBoundsGetElementPtr</code></li>
<li><code>ConstantExpr::getIndices</code></li>
<li><code>ConstantExpr::getInsertElement</code></li>
<li><code>ConstantExpr::getWithOperands</code></li>
+<li><code>ConstantFoldCall</code> (in <code>llvm/Analysis/ConstantFolding.h</code>)</li>
+<li><code>ConstantFoldInstOperands</code> (in <code>llvm/Analysis/ConstantFolding.h</code>)</li>
<li><code>ConstantVector::get</code></li>
<li><code>DIBuilder::createComplexVariable</code></li>
<li><code>DIBuilder::getOrCreateArray</code></li>
@@ -630,23 +794,67 @@ from the previous release.</p>
<li><code>ExtractValueInst::getIndexedType</code></li>
<li><code>ExtractValueInst::getIndices</code></li>
<li><code>FindInsertedValue</code> (in <code>llvm/Analysis/ValueTracking.h</code>)</li>
+<li><code>gep_type_begin</code> (in <code>llvm/Support/GetElementPtrTypeIterator.h</code>)</li>
+<li><code>gep_type_end</code> (in <code>llvm/Support/GetElementPtrTypeIterator.h</code>)</li>
+<li><code>GetElementPtrInst::Create</code></li>
+<li><code>GetElementPtrInst::CreateInBounds</code></li>
+<li><code>GetElementPtrInst::getIndexedType</code></li>
+<li><code>InsertValueInst::Create</code></li>
+<li><code>InsertValueInst::getIndices</code></li>
+<li><code>InvokeInst::Create</code></li>
<li><code>IRBuilder::CreateCall</code></li>
<li><code>IRBuilder::CreateExtractValue</code></li>
+<li><code>IRBuilder::CreateGEP</code></li>
+<li><code>IRBuilder::CreateInBoundsGEP</code></li>
<li><code>IRBuilder::CreateInsertValue</code></li>
<li><code>IRBuilder::CreateInvoke</code></li>
-<li><code>InsertValueInst::Create</code></li>
-<li><code>InsertValueInst::getIndices</code></li>
-<li><code>InvokeInst::Create</code></li>
<li><code>MDNode::get</code></li>
<li><code>MDNode::getIfExists</code></li>
<li><code>MDNode::getTemporary</code></li>
<li><code>MDNode::getWhenValsUnresolved</code></li>
+<li><code>SimplifyGEPInst</code> (in <code>llvm/Analysis/InstructionSimplify.h</code>)</li>
+<li><code>TargetData::getIndexedOffset</code></li>
</ul></li>
-<li>All forms of <code>StringMap::getOrCreateValue</code> have been remove
- except for the one which takes a <code>StringRef</code>.</li>
+ <li>All forms of <code>StringMap::getOrCreateValue</code> have been remove
+ except for the one which takes a <code>StringRef</code>.</li>
+
+ <li>The <code>LLVMBuildUnwind</code> function from the C API was removed. The
+ LLVM <code>unwind</code> instruction has been deprecated for a long time
+ and isn't used by the current front-ends. So this was removed during the
+ exception handling rewrite.</li>
+
+ <li>The <code>LLVMAddLowerSetJmpPass</code> function from the C API was
+ removed because the <code>LowerSetJmp</code> pass was removed.</li>
+
+ <li>The <code>DIBuilder</code> interface used by front ends to encode
+ debugging information in the LLVM IR now expects clients to
+ use <code>DIBuilder::finalize()</code> at the end of translation unit to
+ complete debugging information encoding.</li>
+
+ <li>The way the type system works has been
+ rewritten: <code>PATypeHolder</code> and <code>OpaqueType</code> are gone,
+ and all APIs deal with <code>Type*</code> instead of <code>const
+ Type*</code>. If you need to create recursive structures, then create a
+ named structure, and use <code>setBody()</code> when all its elements are
+ built. Type merging and refining is gone too: named structures are not
+ merged with other structures, even if their layout is identical. (of
+ course anonymous structures are still uniqued by layout).</li>
+
+ <li>TargetSelect.h moved to Support/ from Target/</li>
+ <li>UpgradeIntrinsicCall no longer upgrades pre-2.9 intrinsic calls (for
+ example <code>llvm.memset.i32</code>).</li>
+
+ <li>It is mandatory to initialize all out-of-tree passes too and their dependencies now with
+ <code>INITIALIZE_PASS{BEGIN,END,}</code>
+ and <code>INITIALIZE_{PASS,AG}_DEPENDENCY</code>.</li>
+
+ <li>The interface for MemDepResult in MemoryDependenceAnalysis has been
+ enhanced with new return types Unknown and NonFuncLocal, in addition to
+ the existing types Clobber, Def, and NonLocal.</li>
</ul>
+
</div>
</div>
@@ -659,10 +867,10 @@ from the previous release.</p>
<div>
-<p>This section contains significant known problems with the LLVM system,
-listed by component. If you run into a problem, please check the <a
-href="http://llvm.org/bugs/">LLVM bug database</a> and submit a bug if
-there isn't already one.</p>
+<p>This section contains significant known problems with the LLVM system, listed
+ by component. If you run into a problem, please check
+ the <a href="http://llvm.org/bugs/">LLVM bug database</a> and submit a bug if
+ there isn't already one.</p>
<!-- ======================================================================= -->
<h3>
@@ -672,18 +880,19 @@ there isn't already one.</p>
<div>
<p>The following components of this LLVM release are either untested, known to
-be broken or unreliable, or are in early development. These components should
-not be relied on, and bugs should not be filed against them, but they may be
-useful to some people. In particular, if you would like to work on one of these
-components, please contact us on the <a
-href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVMdev list</a>.</p>
+ be broken or unreliable, or are in early development. These components
+ should not be relied on, and bugs should not be filed against them, but they
+ may be useful to some people. In particular, if you would like to work on
+ one of these components, please contact us on
+ the <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVMdev
+ list</a>.</p>
<ul>
-<li>The Alpha, Blackfin, CellSPU, MicroBlaze, MSP430, MIPS, PTX, SystemZ
- and XCore backends are experimental.</li>
-<li><tt>llc</tt> "<tt>-filetype=obj</tt>" is experimental on all targets
- other than darwin and ELF X86 systems.</li>
-
+ <li>The Alpha, Blackfin, CellSPU, MicroBlaze, MSP430, MIPS, PTX, SystemZ and
+ XCore backends are experimental.</li>
+
+ <li><tt>llc</tt> "<tt>-filetype=obj</tt>" is experimental on all targets other
+ than darwin and ELF X86 systems.</li>
</ul>
</div>
@@ -697,23 +906,28 @@ href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVMdev list</a>.</p>
<ul>
<li>The X86 backend does not yet support
- all <a href="http://llvm.org/PR879">inline assembly that uses the X86
- floating point stack</a>. It supports the 'f' and 't' constraints, but not
- 'u'.</li>
+ all <a href="http://llvm.org/PR879">inline assembly that uses the X86
+ floating point stack</a>. It supports the 'f' and 't' constraints, but
+ not 'u'.</li>
+
<li>The X86-64 backend does not yet support the LLVM IR instruction
- <tt>va_arg</tt>. Currently, front-ends support variadic
- argument constructs on X86-64 by lowering them manually.</li>
+ <tt>va_arg</tt>. Currently, front-ends support variadic argument
+ constructs on X86-64 by lowering them manually.</li>
+
<li>Windows x64 (aka Win64) code generator has a few issues.
<ul>
- <li>llvm-gcc cannot build the mingw-w64 runtime currently
- due to lack of support for the 'u' inline assembly
- constraint and for X87 floating point inline assembly.</li>
- <li>On mingw-w64, you will see unresolved symbol <tt>__chkstk</tt>
- due to <a href="http://llvm.org/bugs/show_bug.cgi?id=8919">Bug 8919</a>.
- It is fixed in <a href="http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20110321/118499.html">r128206</a>.</li>
+ <li>llvm-gcc cannot build the mingw-w64 runtime currently due to lack of
+ support for the 'u' inline assembly constraint and for X87 floating
+ point inline assembly.</li>
+
+ <li>On mingw-w64, you will see unresolved symbol <tt>__chkstk</tt> due
+ to <a href="http://llvm.org/bugs/show_bug.cgi?id=8919">Bug 8919</a>.
+ It is fixed
+ in <a href="http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20110321/118499.html">r128206</a>.</li>
+
<li>Miss-aligned MOVDQA might crash your program. It is due to
- <a href="http://llvm.org/bugs/show_bug.cgi?id=9483">Bug 9483</a>,
- lack of handling aligned internal globals.</li>
+ <a href="http://llvm.org/bugs/show_bug.cgi?id=9483">Bug 9483</a>, lack
+ of handling aligned internal globals.</li>
</ul>
</li>
@@ -729,8 +943,8 @@ href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVMdev list</a>.</p>
<div>
<ul>
-<li>The Linux PPC32/ABI support needs testing for the interpreter and static
-compilation, and lacks support for debug information.</li>
+ <li>The Linux PPC32/ABI support needs testing for the interpreter and static
+ compilation, and lacks support for debug information.</li>
</ul>
</div>
@@ -743,11 +957,12 @@ compilation, and lacks support for debug information.</li>
<div>
<ul>
-<li>Thumb mode works only on ARMv6 or higher processors. On sub-ARMv6
-processors, thumb programs can crash or produce wrong
-results (<a href="http://llvm.org/PR1388">PR1388</a>).</li>
-<li>Compilation for ARM Linux OABI (old ABI) is supported but not fully tested.
-</li>
+ <li>Thumb mode works only on ARMv6 or higher processors. On sub-ARMv6
+ processors, thumb programs can crash or produce wrong results
+ (<a href="http://llvm.org/PR1388">PR1388</a>).</li>
+
+ <li>Compilation for ARM Linux OABI (old ABI) is supported but not fully
+ tested.</li>
</ul>
</div>
@@ -760,8 +975,8 @@ results (<a href="http://llvm.org/PR1388">PR1388</a>).</li>
<div>
<ul>
-<li>The SPARC backend only supports the 32-bit SPARC ABI (-m32); it does not
- support the 64-bit SPARC ABI (-m64).</li>
+ <li>The SPARC backend only supports the 32-bit SPARC ABI (-m32); it does not
+ support the 64-bit SPARC ABI (-m64).</li>
</ul>
</div>
@@ -774,7 +989,7 @@ results (<a href="http://llvm.org/PR1388">PR1388</a>).</li>
<div>
<ul>
-<li>64-bit MIPS targets are not supported yet.</li>
+ <li>64-bit MIPS targets are not supported yet.</li>
</ul>
</div>
@@ -787,11 +1002,10 @@ results (<a href="http://llvm.org/PR1388">PR1388</a>).</li>
<div>
<ul>
-
-<li>On 21164s, some rare FP arithmetic sequences which may trap do not have the
-appropriate nops inserted to ensure restartability.</li>
-
+ <li>On 21164s, some rare FP arithmetic sequences which may trap do not have
+ the appropriate nops inserted to ensure restartability.</li>
</ul>
+
</div>
<!-- ======================================================================= -->
@@ -802,16 +1016,19 @@ appropriate nops inserted to ensure restartability.</li>
<div>
<p>The C backend has numerous problems and is not being actively maintained.
-Depending on it for anything serious is not advised.</p>
+ Depending on it for anything serious is not advised.</p>
<ul>
-<li><a href="http://llvm.org/PR802">The C backend has only basic support for
- inline assembly code</a>.</li>
-<li><a href="http://llvm.org/PR1658">The C backend violates the ABI of common
- C++ programs</a>, preventing intermixing between C++ compiled by the CBE and
- C++ code compiled with <tt>llc</tt> or native compilers.</li>
-<li>The C backend does not support all exception handling constructs.</li>
-<li>The C backend does not support arbitrary precision integers.</li>
+ <li><a href="http://llvm.org/PR802">The C backend has only basic support for
+ inline assembly code</a>.</li>
+
+ <li><a href="http://llvm.org/PR1658">The C backend violates the ABI of common
+ C++ programs</a>, preventing intermixing between C++ compiled by the CBE
+ and C++ code compiled with <tt>llc</tt> or native compilers.</li>
+
+ <li>The C backend does not support all exception handling constructs.</li>
+
+ <li>The C backend does not support arbitrary precision integers.</li>
</ul>
</div>
@@ -824,7 +1041,7 @@ Depending on it for anything serious is not advised.</p>
<div>
-<p><b>LLVM 3.0 will be the last release of llvm-gcc.</b></p>
+<p><b>LLVM 2.9 was the last release of llvm-gcc.</b></p>
<p>llvm-gcc is generally very stable for the C family of languages. The only
major language feature of GCC not supported by llvm-gcc is the
@@ -841,8 +1058,9 @@ Depending on it for anything serious is not advised.</p>
<a href="#dragonegg">dragonegg</a> instead.</p>
<p>The llvm-gcc 4.2 Ada compiler has basic functionality, but is no longer being
-actively maintained. If you are interested in Ada, we recommend that you
-consider using <a href="#dragonegg">dragonegg</a> instead.</p>
+ actively maintained. If you are interested in Ada, we recommend that you
+ consider using <a href="#dragonegg">dragonegg</a> instead.</p>
+
</div>
</div>
@@ -855,17 +1073,16 @@ consider using <a href="#dragonegg">dragonegg</a> instead.</p>
<div>
-<p>A wide variety of additional information is available on the <a
-href="http://llvm.org/">LLVM web page</a>, in particular in the <a
-href="http://llvm.org/docs/">documentation</a> section. The web page also
-contains versions of the API documentation which is up-to-date with the
-Subversion version of the source code.
-You can access versions of these documents specific to this release by going
-into the "<tt>llvm/doc/</tt>" directory in the LLVM tree.</p>
+<p>A wide variety of additional information is available on
+ the <a href="http://llvm.org/">LLVM web page</a>, in particular in
+ the <a href="http://llvm.org/docs/">documentation</a> section. The web page
+ also contains versions of the API documentation which is up-to-date with the
+ Subversion version of the source code. You can access versions of these
+ documents specific to this release by going into the "<tt>llvm/doc/</tt>"
+ directory in the LLVM tree.</p>
<p>If you have any questions or comments about LLVM, please feel free to contact
-us via the <a href="http://llvm.org/docs/#maillist"> mailing
-lists</a>.</p>
+ us via the <a href="http://llvm.org/docs/#maillist"> mailing lists</a>.</p>
</div>
@@ -879,7 +1096,7 @@ lists</a>.</p>
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-07-15 10:37:34 +0200 (Fri, 15 Jul 2011) $
+ Last modified: $Date: 2011-10-17 08:31:58 +0200 (Mon, 17 Oct 2011) $
</address>
</body>
diff --git a/docs/SegmentedStacks.html b/docs/SegmentedStacks.html
new file mode 100644
index 0000000..a91b109
--- /dev/null
+++ b/docs/SegmentedStacks.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <title>Segmented Stacks in LLVM</title>
+ <link rel="stylesheet" href="llvm.css" type="text/css">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+
+ <body>
+ <h1>Segmented Stacks in LLVM</h1>
+ <div class="doc_author">
+ <p>Written by <a href="mailto:sanjoy@playingwithpointers.com">Sanjoy Das</a></p>
+ </div>
+
+ <ol>
+ <li><a href="#intro">Introduction</a></li>
+ <li><a href="#implementation">Implementation Details</a>
+ <ol>
+ <li><a href="#morestack">Allocating Stacklets</a></li>
+ <li><a href="#alloca">Variable Sized Allocas</a></li>
+ </ol>
+ </li>
+ <li><a href="#results">Results</a>
+ <ol>
+ <li><a href="#go">Go on LLVM</a></li>
+ <li><a href="#abi">Runtime ABI</a></li>
+ </ol>
+ </li>
+ </ol>
+
+ <h2><a name="intro">Introduction</a></h2>
+ <div>
+ <p>
+ Segmented stack allows stack space to be allocated incrementally than as a monolithic chunk (of some worst case size) at thread initialization. This is done by allocating stack blocks (henceforth called <em>stacklets</em>) and linking them into a doubly linked list. The function prologue is responsible for checking if the current stacklet has enough space for the function to execute; and if not, call into the libgcc runtime to allocate more stack space. Support for segmented stacks on x86 / Linux is currently being worked on.
+ </p>
+ <p>
+ The runtime functionality is <a href="http://gcc.gnu.org/wiki/SplitStacks">already there in libgcc</a>.
+ </p>
+ </div>
+
+ <h2><a name="implementation">Implementation Details</a></h2>
+ <div>
+ <h3><a name="morestack">Allocating Stacklets</a></h3>
+ <div>
+ <p>
+ As mentioned above, the function prologue checks if the current stacklet has enough space. The current approach is to use a slot in the TCB to store the current stack limit (minus the amount of space needed to allocate a new block) - this slot's offset is again dictated by <code>libgcc</code>. The generated assembly looks like this on x86-64:
+ </p>
+ <pre>
+ leaq -8(%rsp), %r10
+ cmpq %fs:112, %r10
+ jg .LBB0_2
+
+ # More stack space needs to be allocated
+ movabsq $8, %r10 # The amount of space needed
+ movabsq $0, %r11 # The total size of arguments passed on stack
+ callq __morestack
+ ret # The reason for this extra return is explained below
+ .LBB0_2:
+ # Usual prologue continues here
+ </pre>
+ <p>
+ The size of function arguments on the stack needs to be passed to <code> __morestack</code> (this function is implemented in <code>libgcc</code>) since that number of bytes has to be copied from the previous stacklet to the current one. This is so that SP (and FP) relative addressing of function arguments work as expected.
+ </p>
+ <p>
+ The unusual <code>ret</code> is needed to have the function which made a call to <code>__morestack</code> return correctly. <code>__morestack</code>, instead of returning, calls into <code>.LBB0_2</code>. This is possible since both, the size of the <code>ret</code> instruction and the PC of call to <code>__morestack</code> are known. When the function body returns, control is transferred back to <code>__morestack</code>. <code>__morestack</code> then de-allocates the new stacklet, restores the correct SP value, and does a second return, which returns control to the correct caller.
+ </p>
+ </div>
+
+ <h3><a name="alloca">Variable Sized Allocas</a></h3>
+ <div>
+ <p>
+ The section on <a href="#morestack">allocating stacklets</a> automatically assumes that every stack frame will be of fixed size. However, LLVM allows the use of the <code>llvm.alloca</code> intrinsic to allocate dynamically sized blocks of memory on the stack. When faced with such a variable-sized alloca, code is generated to
+ </p>
+ <ul>
+ <li>Check if the current stacklet has enough space. If yes, just bump the SP, like in the normal case.</li>
+ <li>If not, generate a call to <code>libgcc</code>, which allocates the memory from the heap.</li>
+ </ul>
+ <p>
+ The memory allocated from the heap is linked into a list in the current stacklet, and freed along with the same. This prevents a memory leak.
+ </p>
+ </div>
+
+ </div>
+
+ <hr>
+ <address>
+ <a href="http://jigsaw.w3.org/css-validator/check/referer">
+ <img src="http://jigsaw.w3.org/css-validator/images/vcss-blue" alt="Valid CSS">
+ </a>
+ <a href="http://validator.w3.org/check/referer">
+ <img src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01">
+ </a>
+ <a href="mailto:sanjoy@playingwithpointers.com">Sanjoy Das</a><br>
+ <a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
+ Last modified: $Date$
+ </address>
+ </body>
+</html>
+
diff --git a/docs/SourceLevelDebugging.html b/docs/SourceLevelDebugging.html
index bab42a8..75fae6e89 100644
--- a/docs/SourceLevelDebugging.html
+++ b/docs/SourceLevelDebugging.html
@@ -298,8 +298,8 @@ height="369">
of tags are loosely bound to the tag values of DWARF information entries.
However, that does not restrict the use of the information supplied to DWARF
targets. To facilitate versioning of debug information, the tag is augmented
- with the current debug version (LLVMDebugVersion = 8 &lt;&lt; 16 or 0x80000 or
- 524288.)</a></p>
+ with the current debug version (LLVMDebugVersion = 8 &lt;&lt; 16 or
+ 0x80000 or 524288.)</a></p>
<p>The details of the various descriptors follow.</p>
@@ -324,6 +324,10 @@ height="369">
i1, ;; True if this is optimized.
metadata, ;; Flags
i32 ;; Runtime version
+ metadata ;; List of enums types
+ metadata ;; List of retained types
+ metadata ;; List of subprograms
+ metadata ;; List of global variables
}
</pre>
</div>
@@ -337,7 +341,8 @@ height="369">
<p>Compile unit descriptors provide the root context for objects declared in a
specific compilation unit. File descriptors are defined using this context.
These descriptors are collected by a named metadata
- <tt>!llvm.dbg.cu</tt>.
+ <tt>!llvm.dbg.cu</tt>. Compile unit descriptor keeps track of subprograms,
+ global variables and type information.
</div>
@@ -355,7 +360,7 @@ height="369">
;; (DW_TAG_file_type)
metadata, ;; Source file name
metadata, ;; Source file directory (includes trailing slash)
- metadata ;; Reference to compile unit where defined
+ metadata ;; Unused
}
</pre>
</div>
@@ -365,8 +370,7 @@ height="369">
provide context for source line correspondence. </p>
<p>Each input file is encoded as a separate file descriptor in LLVM debugging
- information output. Each file descriptor would be defined using a
- compile unit. </p>
+ information output. </p>
</div>
@@ -434,6 +438,7 @@ global variables are collected by named metadata <tt>!llvm.dbg.gv</tt>.</p>
Function *,;; Pointer to LLVM function
metadata, ;; Lists function template parameters
metadata ;; Function declaration descriptor
+ metadata ;; List of function variables
}
</pre>
</div>
@@ -467,10 +472,23 @@ global variables are collected by named metadata <tt>!llvm.dbg.gv</tt>.</p>
</pre>
</div>
-<p>These descriptors provide debug information about nested blocks within a
+<p>This descriptor provides debug information about nested blocks within a
subprogram. The line number and column numbers are used to dinstinguish
two lexical blocks at same depth. </p>
+<div class="doc_code">
+<pre>
+!3 = metadata !{
+ i32, ;; Tag = 11 + <a href="#LLVMDebugVersion">LLVMDebugVersion</a> (DW_TAG_lexical_block)
+ metadata ;; Reference to the scope we're annotating with a file change
+ metadata,;; Reference to the file the scope is enclosed in.
+}
+</pre>
+</div>
+
+<p>This descriptor provides a wrapper around a lexical scope to handle file
+ changes in the middle of a lexical block.</p>
+
</div>
<!-- ======================================================================= -->
@@ -485,7 +503,7 @@ global variables are collected by named metadata <tt>!llvm.dbg.gv</tt>.</p>
!4 = metadata !{
i32, ;; Tag = 36 + <a href="#LLVMDebugVersion">LLVMDebugVersion</a>
;; (DW_TAG_base_type)
- metadata, ;; Reference to context (typically a compile unit)
+ metadata, ;; Reference to context
metadata, ;; Name (may be "" for anonymous types)
metadata, ;; Reference to file where defined (may be NULL)
i32, ;; Line number where defined (may be 0)
@@ -500,7 +518,7 @@ global variables are collected by named metadata <tt>!llvm.dbg.gv</tt>.</p>
<p>These descriptors define primitive types used in the code. Example int, bool
and float. The context provides the scope of the type, which is usually the
- top level. Since basic types are not usually user defined the compile unit
+ top level. Since basic types are not usually user defined the context
and line number can be left as NULL and 0. The size, alignment and offset
are expressed in bits and can be 64 bit values. The alignment is used to
round the offset when embedded in a
@@ -585,7 +603,7 @@ DW_TAG_restrict_type = 55
the <a href="#format_derived_type">derived type</a>. </p>
<p><a href="#format_derived_type">Derived type</a> location can be determined
- from the compile unit and line number. The size, alignment and offset are
+ from the context and line number. The size, alignment and offset are
expressed in bits and can be 64 bit values. The alignment is used to round
the offset when embedded in a <a href="#format_composite_type">composite
type</a> (example to keep float doubles on 64 bit boundaries.) The offset is
@@ -675,7 +693,7 @@ DW_TAG_inheritance = 28
the formal arguments to the subroutine.</p>
<p><a href="#format_composite_type">Composite type</a> location can be
- determined from the compile unit and line number. The size, alignment and
+ determined from the context and line number. The size, alignment and
offset are expressed in bits and can be 64 bit values. The alignment is used
to round the offset when embedded in
a <a href="#format_composite_type">composite type</a> (as an example, to keep
@@ -750,7 +768,9 @@ DW_TAG_inheritance = 28
metadata, ;; Reference to file where defined
i32, ;; 24 bit - Line number where defined
;; 8 bit - Argument number. 1 indicates 1st argument.
- metadata ;; Type descriptor
+ metadata, ;; Type descriptor
+ i32, ;; flags
+ metadata ;; (optional) Reference to inline location
}
</pre>
</div>
@@ -772,7 +792,7 @@ DW_TAG_return_variable = 258
has no source correspondent.</p>
<p>The context is either the subprogram or block where the variable is defined.
- Name the source variable name. Compile unit and line indicate where the
+ Name the source variable name. Context and line indicate where the
variable was defined. Type descriptor defines the declared type of the
variable.</p>
@@ -1794,7 +1814,7 @@ enum Trees {
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-05-31 20:06:14 +0200 (Tue, 31 May 2011) $
+ Last modified: $Date: 2011-10-12 00:59:11 +0200 (Wed, 12 Oct 2011) $
</address>
</body>
diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html
index 37ca046..f607ef8 100644
--- a/docs/TableGenFundamentals.html
+++ b/docs/TableGenFundamentals.html
@@ -911,7 +911,7 @@ This should highlight the APIs in <tt>TableGen/Record.h</tt>.</p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-10-07 20:25:05 +0200 (Fri, 07 Oct 2011) $
</address>
</body>
diff --git a/docs/WritingAnLLVMPass.html b/docs/WritingAnLLVMPass.html
index 75426e0..adbd691 100644
--- a/docs/WritingAnLLVMPass.html
+++ b/docs/WritingAnLLVMPass.html
@@ -227,11 +227,13 @@ the pass itself.</p>
<p>Now that we have a way to compile our new pass, we just have to write it.
Start out with:</p>
-<div class="doc_code"><pre>
+<div class="doc_code">
+<pre>
<b>#include</b> "<a href="http://llvm.org/doxygen/Pass_8h-source.html">llvm/Pass.h</a>"
<b>#include</b> "<a href="http://llvm.org/doxygen/Function_8h-source.html">llvm/Function.h</a>"
<b>#include</b> "<a href="http://llvm.org/doxygen/raw__ostream_8h.html">llvm/Support/raw_ostream.h</a>"
-</pre></div>
+</pre>
+</div>
<p>Which are needed because we are writing a <tt><a
href="http://llvm.org/doxygen/classllvm_1_1Pass.html">Pass</a></tt>,
@@ -240,53 +242,66 @@ href="http://llvm.org/doxygen/classllvm_1_1Function.html">Function</a></tt>'s,
and we will be doing some printing.</p>
<p>Next we have:</p>
-<div class="doc_code"><pre>
+
+<div class="doc_code">
+<pre>
<b>using namespace llvm;</b>
-</pre></div>
+</pre>
+</div>
+
<p>... which is required because the functions from the include files
-live in the llvm namespace.
-</p>
+live in the llvm namespace.</p>
<p>Next we have:</p>
-<div class="doc_code"><pre>
+<div class="doc_code">
+<pre>
<b>namespace</b> {
-</pre></div>
+</pre>
+</div>
<p>... which starts out an anonymous namespace. Anonymous namespaces are to C++
what the "<tt>static</tt>" keyword is to C (at global scope). It makes the
-things declared inside of the anonymous namespace only visible to the current
+things declared inside of the anonymous namespace visible only to the current
file. If you're not familiar with them, consult a decent C++ book for more
information.</p>
<p>Next, we declare our pass itself:</p>
-<div class="doc_code"><pre>
+<div class="doc_code">
+<pre>
<b>struct</b> Hello : <b>public</b> <a href="#FunctionPass">FunctionPass</a> {
-</pre></div><p>
+</pre>
+</div>
<p>This declares a "<tt>Hello</tt>" class that is a subclass of <tt><a
href="http://llvm.org/doxygen/classllvm_1_1FunctionPass.html">FunctionPass</a></tt>.
The different builtin pass subclasses are described in detail <a
href="#passtype">later</a>, but for now, know that <a
-href="#FunctionPass"><tt>FunctionPass</tt></a>'s operate a function at a
+href="#FunctionPass"><tt>FunctionPass</tt></a>'s operate on a function at a
time.</p>
-<div class="doc_code"><pre>
- static char ID;
- Hello() : FunctionPass(ID) {}
-</pre></div><p>
+<div class="doc_code">
+<pre>
+ static char ID;
+ Hello() : FunctionPass(ID) {}
+</pre>
+</div>
-<p> This declares pass identifier used by LLVM to identify pass. This allows LLVM to
-avoid using expensive C++ runtime information.</p>
+<p>This declares pass identifier used by LLVM to identify pass. This allows LLVM
+to avoid using expensive C++ runtime information.</p>
-<div class="doc_code"><pre>
+<div class="doc_code">
+<pre>
<b>virtual bool</b> <a href="#runOnFunction">runOnFunction</a>(Function &amp;F) {
- errs() &lt;&lt; "<i>Hello: </i>" &lt;&lt; F.getName() &lt;&lt; "\n";
+ errs() &lt;&lt; "<i>Hello: </i>";
+ errs().write_escaped(F.getName()) &lt;&lt; "\n";
<b>return false</b>;
}
}; <i>// end of struct Hello</i>
-</pre></div>
+} <i>// end of anonymous namespace</i>
+</pre>
+</div>
<p>We declare a "<a href="#runOnFunction"><tt>runOnFunction</tt></a>" method,
which overloads an abstract virtual method inherited from <a
@@ -294,31 +309,34 @@ href="#FunctionPass"><tt>FunctionPass</tt></a>. This is where we are supposed
to do our thing, so we just print out our message with the name of each
function.</p>
-<div class="doc_code"><pre>
- char Hello::ID = 0;
-</pre></div>
+<div class="doc_code">
+<pre>
+char Hello::ID = 0;
+</pre>
+</div>
-<p> We initialize pass ID here. LLVM uses ID's address to identify pass so
+<p>We initialize pass ID here. LLVM uses ID's address to identify a pass, so
initialization value is not important.</p>
-<div class="doc_code"><pre>
- static RegisterPass&lt;Hello&gt; X("<i>hello</i>", "<i>Hello World Pass</i>",
- false /* Only looks at CFG */,
- false /* Analysis Pass */);
-} <i>// end of anonymous namespace</i>
-</pre></div>
+<div class="doc_code">
+<pre>
+static RegisterPass&lt;Hello&gt; X("<i>hello</i>", "<i>Hello World Pass</i>",
+ false /* Only looks at CFG */,
+ false /* Analysis Pass */);
+</pre>
+</div>
-<p>Lastly, we <a href="#registration">register our class</a> <tt>Hello</tt>,
-giving it a command line
-argument "<tt>hello</tt>", and a name "<tt>Hello World Pass</tt>".
-Last two arguments describe its behavior.
-If a pass walks CFG without modifying it then third argument is set to true.
-If a pass is an analysis pass, for example dominator tree pass, then true
-is supplied as fourth argument. </p>
+<p>Lastly, we <a href="#registration">register our class</a> <tt>Hello</tt>,
+giving it a command line argument "<tt>hello</tt>", and a name "<tt>Hello World
+Pass</tt>". The last two arguments describe its behavior: if a pass walks CFG
+without modifying it then the third argument is set to <tt>true</tt>; if a pass
+is an analysis pass, for example dominator tree pass, then <tt>true</tt> is
+supplied as the fourth argument.</p>
<p>As a whole, the <tt>.cpp</tt> file looks like:</p>
-<div class="doc_code"><pre>
+<div class="doc_code">
+<pre>
<b>#include</b> "<a href="http://llvm.org/doxygen/Pass_8h-source.html">llvm/Pass.h</a>"
<b>#include</b> "<a href="http://llvm.org/doxygen/Function_8h-source.html">llvm/Function.h</a>"
<b>#include</b> "<a href="http://llvm.org/doxygen/raw__ostream_8h.html">llvm/Support/raw_ostream.h</a>"
@@ -332,24 +350,26 @@ is supplied as fourth argument. </p>
Hello() : FunctionPass(ID) {}
<b>virtual bool</b> <a href="#runOnFunction">runOnFunction</a>(Function &amp;F) {
- errs() &lt;&lt; "<i>Hello: </i>" &lt;&lt; F.getName() &lt;&lt; "\n";
+ errs() &lt;&lt; "<i>Hello: </i>";
+ errs().write_escaped(F.getName()) &lt;&lt; '\n';
<b>return false</b>;
}
+
};
-
- char Hello::ID = 0;
- static RegisterPass&lt;Hello&gt; X("hello", "Hello World Pass", false, false);
}
-
-</pre></div>
+
+char Hello::ID = 0;
+static RegisterPass&lt;Hello&gt; X("hello", "Hello World Pass", false, false);
+</pre>
+</div>
<p>Now that it's all together, compile the file with a simple "<tt>gmake</tt>"
command in the local directory and you should get a new file
"<tt>Debug+Asserts/lib/Hello.so</tt>" under the top level directory of the LLVM
source tree (not in the local directory). Note that everything in this file is
-contained in an anonymous namespace: this reflects the fact that passes are self
-contained units that do not need external interfaces (although they can have
-them) to be useful.</p>
+contained in an anonymous namespace &mdash; this reflects the fact that passes
+are self contained units that do not need external interfaces (although they can
+have them) to be useful.</p>
</div>
@@ -1929,7 +1949,7 @@ Despite that, we have kept the LLVM passes SMP ready, and you should too.</p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-10-11 09:03:52 +0200 (Tue, 11 Oct 2011) $
</address>
</body>
diff --git a/docs/doxygen.cfg.in b/docs/doxygen.cfg.in
index 45b8f42..bc4ab9f 100644
--- a/docs/doxygen.cfg.in
+++ b/docs/doxygen.cfg.in
@@ -1,4 +1,4 @@
-# Doxyfile 1.5.6
+# Doxyfile 1.7.1
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
@@ -11,214 +11,219 @@
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
-# Project related configuration options
+# Project related configuration options
#---------------------------------------------------------------------------
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
# http://www.gnu.org/software/libiconv for the list of possible encodings.
DOXYFILE_ENCODING = UTF-8
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = LLVM
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = @PACKAGE_VERSION@
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = @abs_top_builddir@/docs/doxygen
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
# otherwise cause performance problems for the file system.
-CREATE_SUBDIRS = NO
+CREATE_SUBDIRS = YES
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
-# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
-# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
-# and Ukrainian.
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = YES
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
# "represents" "a" "an" "the"
-ABBREVIATE_BRIEF =
+ABBREVIATE_BRIEF =
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC = NO
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
INLINE_INHERITED_MEMB = NO
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = NO
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
# path to strip.
STRIP_FROM_PATH = ../..
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
# are normally passed to the compiler using the -I flag.
-STRIP_FROM_INC_PATH =
+STRIP_FROM_INC_PATH =
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
# doesn't support long names like on DOS, Mac, or CD-ROM.
SHORT_NAMES = NO
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
# (thus requiring an explicit @brief command for a brief description.)
JAVADOC_AUTOBRIEF = NO
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
# an explicit \brief command for a brief description.)
QT_AUTOBRIEF = NO
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
# description. Set this tag to YES if you prefer the old behaviour instead.
MULTILINE_CPP_IS_BRIEF = NO
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member
-# documentation.
-
-DETAILS_AT_TOP = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
# re-implements.
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
# be part of the file/class/namespace that contains it.
SEPARATE_MEMBER_PAGES = NO
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
TAB_SIZE = 2
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
-ALIASES =
+ALIASES =
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C = NO
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
# scopes will look different, etc.
OPTIMIZE_OUTPUT_JAVA = NO
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
# Fortran.
OPTIMIZE_FOR_FORTRAN = NO
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
# VHDL.
OPTIMIZE_OUTPUT_VHDL = NO
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also make the inheritance and collaboration
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
BUILTIN_STL_SUPPORT = NO
@@ -228,414 +233,459 @@ BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
# instead of private inheritance when no explicit protection keyword is present.
SIP_SUPPORT = NO
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen to replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
# methods anyway, you should set this option to NO.
IDL_PROPERTY_SUPPORT = YES
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC = NO
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
# the \nosubgrouping command.
SUBGROUPING = YES
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
-# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
TYPEDEF_HIDES_STRUCT = NO
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = YES
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.
EXTRACT_LOCAL_CLASSES = YES
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
# If set to NO (the default) only methods in the interface are included.
EXTRACT_LOCAL_METHODS = NO
-# If this flag is set to YES, the members of anonymous namespaces will be
-# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
# anonymous namespace are hidden.
EXTRACT_ANON_NSPACES = NO
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = NO
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
# documentation.
HIDE_FRIEND_COMPOUNDS = NO
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
# function's detailed documentation block.
HIDE_IN_BODY_DOCS = NO
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS = NO
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
CASE_SENSE_NAMES = YES
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO = YES
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
# declaration order.
SORT_BRIEF_DOCS = NO
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
# the group names will appear in their defined order.
SORT_GROUP_NAMES = NO
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
+# Note: This option applies only to the class list, not to the
# alphabetical list.
SORT_BY_SCOPE_NAME = NO
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = YES
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = YES
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
# commands in the documentation.
GENERATE_BUGLIST = YES
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
# \deprecated commands in the documentation.
GENERATE_DEPRECATEDLIST= YES
-# The ENABLED_SECTIONS tag can be used to enable conditional
+# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
-ENABLED_SECTIONS =
+ENABLED_SECTIONS =
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and defines in the
-# documentation can be controlled using \showinitializer or \hideinitializer
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
MAX_INITIALIZER_LINES = 30
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = YES
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
# in the documentation. The default is NO.
SHOW_DIRECTORIES = YES
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
+# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
SHOW_FILES = YES
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
# and from the Folder Tree View (if specified). The default is YES.
SHOW_NAMESPACES = YES
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from
-# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
# is used as the file version. See the manual for examples.
-FILE_VERSION_FILTER =
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
-# The QUIET tag can be used to turn on/off the messages that are generated
+# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = NO
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS = NO
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED = NO
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
# don't exist or using markup commands wrongly.
WARN_IF_DOC_ERROR = YES
-# This WARN_NO_PARAMDOC option can be abled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
# documentation.
WARN_NO_PARAMDOC = NO
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
# be obtained via FILE_VERSION_FILTER)
-WARN_FORMAT =
+WARN_FORMAT =
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
# to stderr.
-WARN_LOGFILE =
+WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = @abs_top_srcdir@/include \
@abs_top_srcdir@/lib \
@abs_top_srcdir@/docs/doxygen.intro
-# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
# the list of possible encodings.
INPUT_ENCODING = UTF-8
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
-FILE_PATTERNS =
+FILE_PATTERNS =
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = YES
-# The EXCLUDE tag can be used to specify files and/or directories that should
-# excluded from the INPUT source files. This way you can easily exclude a
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
-EXCLUDE =
+EXCLUDE =
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix filesystem feature) are excluded
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
# from the input.
EXCLUDE_SYMLINKS = NO
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
-EXCLUDE_PATTERNS =
+EXCLUDE_PATTERNS =
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the
-# output. The symbol name can be a fully qualified name, a word, or if the
-# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
-EXCLUDE_SYMBOLS =
+EXCLUDE_SYMBOLS =
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH = @abs_top_srcdir@/examples
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
-EXAMPLE_PATTERNS =
+EXAMPLE_PATTERNS =
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
# Possible values are YES and NO. If left blank NO is used.
EXAMPLE_RECURSIVE = YES
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH = @abs_top_srcdir@/docs/img
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
# ignored.
-INPUT_FILTER =
+INPUT_FILTER =
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
# is applied to all files.
-FILTER_PATTERNS =
+FILTER_PATTERNS =
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse (i.e. when SOURCE_BROWSER is set to YES).
FILTER_SOURCE_FILES = NO
@@ -644,32 +694,32 @@ FILTER_SOURCE_FILES = NO
# configuration options related to source browsing
#---------------------------------------------------------------------------
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.
SOURCE_BROWSER = YES
-# Setting the INLINE_SOURCES tag to YES will include the body
+# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES = NO
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS = NO
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
# functions referencing it will be listed.
REFERENCED_BY_RELATION = YES
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
# called/used by that function will be listed.
REFERENCES_RELATION = YES
@@ -677,20 +727,21 @@ REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code. Otherwise they will link to the documentstion.
+# link to the source code.
+# Otherwise they will link to the documentation.
REFERENCES_LINK_SOURCE = YES
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
# will need version 4.8.6 or higher.
USE_HTAGS = NO
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS = YES
@@ -699,21 +750,21 @@ VERBATIM_HEADERS = YES
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX = YES
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 4
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
IGNORE_PREFIX = llvm::
@@ -722,106 +773,149 @@ IGNORE_PREFIX = llvm::
# configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
HTML_OUTPUT = html
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
# doxygen will generate files with .html extension.
HTML_FILE_EXTENSION = .html
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
HTML_HEADER = @abs_top_srcdir@/docs/doxygen.header
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER = @abs_top_srcdir@/docs/doxygen.footer
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
# stylesheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET = @abs_top_srcdir@/docs/doxygen.css
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the stylesheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
HTML_ALIGN_MEMBERS = YES
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
-GENERATE_HTMLHELP = NO
+HTML_DYNAMIC_SECTIONS = NO
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
GENERATE_DOCSET = NO
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
# can be grouped.
DOCSET_FEEDNAME = "Doxygen generated docs"
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
# will append .docset to the name.
DOCSET_BUNDLE_ID = org.doxygen.Project
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded. For this to work a browser that supports
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
-# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
-HTML_DYNAMIC_SECTIONS = NO
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
# written to the html output directory.
-CHM_FILE =
+CHM_FILE =
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
# the HTML help compiler on the generated index.hhp.
-HHC_LOCATION =
+HHC_LOCATION =
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
# it should be included in the master .chm file (NO).
GENERATE_CHI = NO
@@ -830,203 +924,314 @@ GENERATE_CHI = NO
# is used to encode HtmlHelp index (hhk), content (hhc) and project file
# content.
-CHM_INDEX_ENCODING =
+CHM_INDEX_ENCODING =
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
# normal table of contents (NO) in the .chm file.
BINARY_TOC = NO
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
# to the contents of the HTML help documentation and to the tree view.
TOC_EXPAND = NO
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
DISABLE_INDEX = NO
-# This tag can be used to set the number of enum values (range [1..20])
+# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
ENUM_VALUES_PER_LINE = 4
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
-# If the tag value is set to FRAME, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
-# probably better off using the HTML help feature. Other possible values
-# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
-# and Class Hiererachy pages using a tree view instead of an ordered list;
-# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
-# disables this behavior completely. For backwards compatibility with previous
-# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
-# respectively.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
GENERATE_TREEVIEW = NO
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
TREEVIEW_WIDTH = 250
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
# to force them to be regenerated.
FORMULA_FONTSIZE = 10
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvances is that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = NO
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
-LATEX_OUTPUT =
+LATEX_OUTPUT =
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
LATEX_CMD_NAME = latex
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
# default command name.
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, a4wide, letter, legal and
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = letter
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
-EXTRA_PACKAGES =
+EXTRA_PACKAGES =
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
-LATEX_HEADER =
+LATEX_HEADER =
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = NO
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = NO
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = NO
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
# in the output.
LATEX_HIDE_INDICES = NO
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
-RTF_OUTPUT =
+RTF_OUTPUT =
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
-RTF_STYLESHEET_FILE =
+RTF_STYLESHEET_FILE =
-# Set optional variables used in the generation of an rtf document.
+# Set optional variables used in the generation of an rtf document.
# Syntax is similar to doxygen's config file.
-RTF_EXTENSIONS_FILE =
+RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = NO
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.
-MAN_OUTPUT =
+MAN_OUTPUT =
-# The MAN_EXTENSION tag determines the extension that is added to
+# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
-MAN_EXTENSION =
+MAN_EXTENSION =
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS = NO
@@ -1035,33 +1240,33 @@ MAN_LINKS = NO
# configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
# the code including all documentation.
GENERATE_XML = NO
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `xml' will be used as the default path.
XML_OUTPUT = xml
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
# syntax of the XML files.
-XML_SCHEMA =
+XML_SCHEMA =
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
# syntax of the XML files.
-XML_DTD =
+XML_DTD =
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
# enabling this will significantly increase the size of the XML output.
XML_PROGRAMLISTING = YES
@@ -1070,10 +1275,10 @@ XML_PROGRAMLISTING = YES
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
# and incomplete at the moment.
GENERATE_AUTOGEN_DEF = NO
@@ -1082,338 +1287,346 @@ GENERATE_AUTOGEN_DEF = NO
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
# moment.
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
# to generate PDF and DVI output from the Perl module output.
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader. This is useful
-# if you want to understand what is going on. On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.
PERLMOD_PRETTY = YES
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
# Makefile don't overwrite each other's variables.
-PERLMOD_MAKEVAR_PREFIX =
+PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
+# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = NO
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
EXPAND_ONLY_PREDEF = NO
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
SEARCH_INCLUDES = YES
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
# the preprocessor.
INCLUDE_PATH = ../include
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
-INCLUDE_FILE_PATTERNS =
+INCLUDE_FILE_PATTERNS =
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED =
+PREDEFINED =
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
-EXPAND_AS_DEFINED =
+EXPAND_AS_DEFINED =
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are alone
-# on a line, have an all uppercase name, and do not end with a semicolon. Such
-# function macros are typically used for boiler-plate code, and will confuse
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
# the parser if not removed.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
-# Configuration::additions related to external references
+# Configuration::additions related to external references
#---------------------------------------------------------------------------
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
# does not have to be run to correct the links.
# Note that each tag file must have a unique name
# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
+# If a tag file is not located in the directory in which doxygen
# is run, you must also specify the path to the tagfile here.
-TAGFILES =
+TAGFILES =
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
-GENERATE_TAGFILE =
+GENERATE_TAGFILE =
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
# will be listed.
ALLEXTERNALS = YES
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
# be listed.
EXTERNAL_GROUPS = YES
-# The PERL_PATH should be the absolute path and name of the perl script
+# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
-PERL_PATH =
+PERL_PATH =
#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
+# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option is superseded by the HAVE_DOT option below. This is only a
-# fallback. It is recommended to install and use dot, since it yields more
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
# powerful graphs.
CLASS_DIAGRAMS = YES
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
-MSCGEN_PATH =
+MSCGEN_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
# or is not a class.
HIDE_UNDOC_RELATIONS = NO
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = YES
-# By default doxygen will write a font called FreeSans.ttf to the output
-# directory and reference it in all dot files that doxygen generates. This
-# font does not include all possible unicode characters however, so when you need
-# these (or just want a differently looking font) you can specify the font name
-# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
-# which can be done by putting it in a standard location or by setting the
-# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
# containing the font.
DOT_FONTNAME = FreeSans
-# By default doxygen will tell dot to use the output directory to look for the
-# FreeSans.ttf font (which doxygen will put there itself). If you specify a
-# different font using DOT_FONTNAME you can set the path where dot
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
# can find it using this tag.
-DOT_FONTPATH =
+DOT_FONTPATH =
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH = YES
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for groups, showing the direct groups dependencies
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
UML_LOOK = NO
-# If set to YES, the inheritance and collaboration graphs will show the
+# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
TEMPLATE_RELATIONS = YES
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
# other documented files.
INCLUDE_GRAPH = YES
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
# indirectly include this file.
INCLUDED_BY_GRAPH = YES
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
# for selected functions only using the \callgraph command.
CALL_GRAPH = NO
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
# graphs for selected functions only using the \callergraph command.
CALLER_GRAPH = NO
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
DIRECTORY_GRAPH = YES
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are png, jpg, or gif
# If left blank png will be used.
DOT_IMAGE_FORMAT = png
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
DOT_PATH = @DOT@
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
# \dotfile command).
-DOTFILE_DIRS =
+DOTFILE_DIRS =
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
DOT_GRAPH_MAX_NODES = 50
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
MAX_DOT_GRAPH_DEPTH = 0
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is enabled by default, which results in a transparent
-# background. Warning: Depending on the platform used, enabling this option
-# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
-# become hard to read).
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
DOT_TRANSPARENT = YES
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
# support this, this feature is disabled by default.
DOT_MULTI_TARGETS = NO
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
# the various graphs.
DOT_CLEANUP = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE = NO
diff --git a/docs/index.html b/docs/index.html
index fc43569..e22d991 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -63,6 +63,11 @@ Discusses how to get up and running quickly with the LLVM infrastructure.
Everything from unpacking and compilation of the distribution to execution of
some tools.</li>
+<li><a href="CMake.html">LLVM CMake guide</a> - An addendum to the main Getting
+Started guide for those using the <a href="http://www.cmake.org/">CMake build
+system</a>.
+</li>
+
<li><a href="GettingStartedVS.html">Getting Started with the LLVM System using
Microsoft Visual Studio</a> - An addendum to the main Getting Started guide for
those using Visual Studio on Windows.</li>
@@ -87,7 +92,6 @@ Current tools:
<a href="/cmds/opt.html">opt</a>,
<a href="/cmds/llc.html">llc</a>,
<a href="/cmds/lli.html">lli</a>,
- <a href="/cmds/llvmc.html">llvmc</a>
<a href="/cmds/llvmgcc.html">llvm-gcc</a>,
<a href="/cmds/llvmgxx.html">llvm-g++</a>,
<a href="/cmds/bugpoint.html">bugpoint</a>,
@@ -216,14 +220,6 @@ in LLVM.</li>
<li><a href="Bugpoint.html">Bugpoint</a> - automatic bug finder and test-case
reducer description and usage information.</li>
-<li><a href="CompilerDriverTutorial.html">Compiler Driver (llvmc) Tutorial</a>
-- This document is a tutorial introduction to the usage and
-configuration of the LLVM compiler driver tool, <tt>llvmc</tt>.</li>
-
-<li><a href="CompilerDriver.html">Compiler Driver (llvmc)
-Reference</a> - This document describes the design and configuration
-of <tt>llvmc</tt> in more detail.</li>
-
<li><a href="BitCodeFormat.html">LLVM Bitcode File Format</a> - This describes
the file format and encoding used for LLVM "bc" files.</li>
@@ -289,7 +285,7 @@ times each day, making it a high volume list.</li>
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-07-06 20:31:02 +0200 (Wed, 06 Jul 2011) $
+ Last modified: $Date: 2011-10-11 18:35:07 +0200 (Tue, 11 Oct 2011) $
</address>
</body></html>
diff --git a/docs/llvm.css b/docs/llvm.css
index 1222cf1..e3e6351 100644
--- a/docs/llvm.css
+++ b/docs/llvm.css
@@ -70,6 +70,14 @@ h4, .doc_subsubsection { margin: 2.0em 0.5em 0.5em 0.5em;
display: table;
}
+blockquote pre {
+ padding: 1em 2em 1em 1em;
+ border: solid 1px gray;
+ background: #eeeeee;
+ margin: 0 1em 0 1em;
+ display: table;
+}
+
h2+div, h2+p {text-align: left; padding-left: 20pt; padding-right: 10pt;}
h3+div, h3+p {text-align: left; padding-left: 20pt; padding-right: 10pt;}
h4+div, h4+p {text-align: left; padding-left: 20pt; padding-right: 10pt;}
diff --git a/docs/tutorial/LangImpl2.html b/docs/tutorial/LangImpl2.html
index c6a9bb1..2696d86 100644
--- a/docs/tutorial/LangImpl2.html
+++ b/docs/tutorial/LangImpl2.html
@@ -801,10 +801,10 @@ course.) To build this, just compile with:</p>
<div class="doc_code">
<pre>
- # Compile
- g++ -g -O3 toy.cpp
- # Run
- ./a.out
+# Compile
+clang++ -g -O3 toy.cpp
+# Run
+./a.out
</pre>
</div>
@@ -1225,7 +1225,7 @@ int main() {
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
</address>
</body>
</html>
diff --git a/docs/tutorial/LangImpl3.html b/docs/tutorial/LangImpl3.html
index 47406ca..c9517a0 100644
--- a/docs/tutorial/LangImpl3.html
+++ b/docs/tutorial/LangImpl3.html
@@ -266,7 +266,7 @@ Value *CallExprAST::Codegen() {
if (ArgsV.back() == 0) return 0;
}
- return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+ return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
</pre>
</div>
@@ -308,11 +308,11 @@ bodies and external function declarations. The code starts with:</p>
<pre>
Function *PrototypeAST::Codegen() {
// Make the function type: double(double,double) etc.
- std::vector&lt;const Type*&gt; Doubles(Args.size(),
- Type::getDoubleTy(getGlobalContext()));
+ std::vector&lt;Type*&gt; Doubles(Args.size(),
+ Type::getDoubleTy(getGlobalContext()));
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
Doubles, false);
-
+
Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
</pre>
</div>
@@ -532,9 +532,9 @@ functions. For example:
<pre>
ready> <b>4+5</b>;
Read top-level expression:
-define double @""() {
+define double @0() {
entry:
- ret double 9.000000e+00
+ ret double 9.000000e+00
}
</pre>
</div>
@@ -553,13 +553,13 @@ ready&gt; <b>def foo(a b) a*a + 2*a*b + b*b;</b>
Read function definition:
define double @foo(double %a, double %b) {
entry:
- %multmp = fmul double %a, %a
- %multmp1 = fmul double 2.000000e+00, %a
- %multmp2 = fmul double %multmp1, %b
- %addtmp = fadd double %multmp, %multmp2
- %multmp3 = fmul double %b, %b
- %addtmp4 = fadd double %addtmp, %multmp3
- ret double %addtmp4
+ %multmp = fmul double %a, %a
+ %multmp1 = fmul double 2.000000e+00, %a
+ %multmp2 = fmul double %multmp1, %b
+ %addtmp = fadd double %multmp, %multmp2
+ %multmp3 = fmul double %b, %b
+ %addtmp4 = fadd double %addtmp, %multmp3
+ ret double %addtmp4
}
</pre>
</div>
@@ -573,10 +573,10 @@ ready&gt; <b>def bar(a) foo(a, 4.0) + bar(31337);</b>
Read function definition:
define double @bar(double %a) {
entry:
- %calltmp = call double @foo(double %a, double 4.000000e+00)
- %calltmp1 = call double @bar(double 3.133700e+04)
- %addtmp = fadd double %calltmp, %calltmp1
- ret double %addtmp
+ %calltmp = call double @foo(double %a, double 4.000000e+00)
+ %calltmp1 = call double @bar(double 3.133700e+04)
+ %addtmp = fadd double %calltmp, %calltmp1
+ ret double %addtmp
}
</pre>
</div>
@@ -593,10 +593,10 @@ declare double @cos(double)
ready&gt; <b>cos(1.234);</b>
Read top-level expression:
-define double @""() {
+define double @1() {
entry:
- %calltmp = call double @cos(double 1.234000e+00)
- ret double %calltmp
+ %calltmp = call double @cos(double 1.234000e+00)
+ ret double %calltmp
}
</pre>
</div>
@@ -609,37 +609,37 @@ entry:
ready&gt; <b>^D</b>
; ModuleID = 'my cool jit'
-define double @""() {
+define double @0() {
entry:
- %addtmp = fadd double 4.000000e+00, 5.000000e+00
- ret double %addtmp
+ %addtmp = fadd double 4.000000e+00, 5.000000e+00
+ ret double %addtmp
}
define double @foo(double %a, double %b) {
entry:
- %multmp = fmul double %a, %a
- %multmp1 = fmul double 2.000000e+00, %a
- %multmp2 = fmul double %multmp1, %b
- %addtmp = fadd double %multmp, %multmp2
- %multmp3 = fmul double %b, %b
- %addtmp4 = fadd double %addtmp, %multmp3
- ret double %addtmp4
+ %multmp = fmul double %a, %a
+ %multmp1 = fmul double 2.000000e+00, %a
+ %multmp2 = fmul double %multmp1, %b
+ %addtmp = fadd double %multmp, %multmp2
+ %multmp3 = fmul double %b, %b
+ %addtmp4 = fadd double %addtmp, %multmp3
+ ret double %addtmp4
}
define double @bar(double %a) {
entry:
- %calltmp = call double @foo(double %a, double 4.000000e+00)
- %calltmp1 = call double @bar(double 3.133700e+04)
- %addtmp = fadd double %calltmp, %calltmp1
- ret double %addtmp
+ %calltmp = call double @foo(double %a, double 4.000000e+00)
+ %calltmp1 = call double @bar(double 3.133700e+04)
+ %addtmp = fadd double %calltmp, %calltmp1
+ ret double %addtmp
}
declare double @cos(double)
-define double @""() {
+define double @1() {
entry:
- %calltmp = call double @cos(double 1.234000e+00)
- ret double %calltmp
+ %calltmp = call double @cos(double 1.234000e+00)
+ ret double %calltmp
}
</pre>
</div>
@@ -670,10 +670,10 @@ our makefile/command line about which options to use:</p>
<div class="doc_code">
<pre>
- # Compile
- g++ -g -O3 toy.cpp `llvm-config --cppflags --ldflags --libs core` -o toy
- # Run
- ./toy
+# Compile
+clang++ -g -O3 toy.cpp `llvm-config --cppflags --ldflags --libs core` -o toy
+# Run
+./toy
</pre>
</div>
@@ -1081,13 +1081,13 @@ Value *CallExprAST::Codegen() {
if (ArgsV.back() == 0) return 0;
}
- return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+ return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
Function *PrototypeAST::Codegen() {
// Make the function type: double(double,double) etc.
- std::vector&lt;const Type*&gt; Doubles(Args.size(),
- Type::getDoubleTy(getGlobalContext()));
+ std::vector&lt;Type*&gt; Doubles(Args.size(),
+ Type::getDoubleTy(getGlobalContext()));
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
Doubles, false);
@@ -1262,7 +1262,7 @@ int main() {
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
</address>
</body>
</html>
diff --git a/docs/tutorial/LangImpl4.html b/docs/tutorial/LangImpl4.html
index 5b8990e4..e910cc1 100644
--- a/docs/tutorial/LangImpl4.html
+++ b/docs/tutorial/LangImpl4.html
@@ -343,9 +343,10 @@ code that is statically linked into your application.</p>
<div class="doc_code">
<pre>
ready&gt; <b>4+5;</b>
-define double @""() {
+Read top-level expression:
+define double @0() {
entry:
- ret double 9.000000e+00
+ ret double 9.000000e+00
}
<em>Evaluated to 9.000000</em>
@@ -363,16 +364,17 @@ ready&gt; <b>def testfunc(x y) x + y*2; </b>
Read function definition:
define double @testfunc(double %x, double %y) {
entry:
- %multmp = fmul double %y, 2.000000e+00
- %addtmp = fadd double %multmp, %x
- ret double %addtmp
+ %multmp = fmul double %y, 2.000000e+00
+ %addtmp = fadd double %multmp, %x
+ ret double %addtmp
}
ready&gt; <b>testfunc(4, 10);</b>
-define double @""() {
+Read top-level expression:
+define double @1() {
entry:
- %calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01)
- ret double %calltmp
+ %calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01)
+ ret double %calltmp
}
<em>Evaluated to 24.000000</em>
@@ -404,21 +406,34 @@ Read extern:
declare double @cos(double)
ready&gt; <b>sin(1.0);</b>
+Read top-level expression:
+define double @2() {
+entry:
+ ret double 0x3FEAED548F090CEE
+}
+
<em>Evaluated to 0.841471</em>
ready&gt; <b>def foo(x) sin(x)*sin(x) + cos(x)*cos(x);</b>
Read function definition:
define double @foo(double %x) {
entry:
- %calltmp = call double @sin(double %x)
- %multmp = fmul double %calltmp, %calltmp
- %calltmp2 = call double @cos(double %x)
- %multmp4 = fmul double %calltmp2, %calltmp2
- %addtmp = fadd double %multmp, %multmp4
- ret double %addtmp
+ %calltmp = call double @sin(double %x)
+ %multmp = fmul double %calltmp, %calltmp
+ %calltmp2 = call double @cos(double %x)
+ %multmp4 = fmul double %calltmp2, %calltmp2
+ %addtmp = fadd double %multmp, %multmp4
+ ret double %addtmp
}
ready&gt; <b>foo(4.0);</b>
+Read top-level expression:
+define double @3() {
+entry:
+ %calltmp = call double @foo(double 4.000000e+00)
+ ret double %calltmp
+}
+
<em>Evaluated to 1.000000</em>
</pre>
</div>
@@ -484,10 +499,10 @@ LLVM JIT and optimizer. To build this example, use:
<div class="doc_code">
<pre>
- # Compile
- g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
- # Run
- ./toy
+# Compile
+clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
+# Run
+./toy
</pre>
</div>
@@ -509,9 +524,9 @@ at runtime.</p>
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/IRBuilder.h"
+#include "llvm/Support/TargetSelect.h"
#include &lt;cstdio&gt;
#include &lt;string&gt;
#include &lt;map&gt;
@@ -905,13 +920,13 @@ Value *CallExprAST::Codegen() {
if (ArgsV.back() == 0) return 0;
}
- return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+ return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
Function *PrototypeAST::Codegen() {
// Make the function type: double(double,double) etc.
- std::vector&lt;const Type*&gt; Doubles(Args.size(),
- Type::getDoubleTy(getGlobalContext()));
+ std::vector&lt;Type*&gt; Doubles(Args.size(),
+ Type::getDoubleTy(getGlobalContext()));
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
Doubles, false);
@@ -1013,6 +1028,9 @@ static void HandleTopLevelExpression() {
// Evaluate a top-level expression into an anonymous function.
if (FunctionAST *F = ParseTopLevelExpr()) {
if (Function *LF = F-&gt;Codegen()) {
+ fprintf(stderr, "Read top-level expression:");
+ LF->dump();
+
// JIT the function, returning a function pointer.
void *FPtr = TheExecutionEngine-&gt;getPointerToFunction(LF);
@@ -1076,7 +1094,7 @@ int main() {
// Create the JIT. This takes ownership of the module.
std::string ErrStr;
-TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&amp;ErrStr).create();
+ TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&amp;ErrStr).create();
if (!TheExecutionEngine) {
fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
exit(1);
@@ -1129,7 +1147,7 @@ TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&amp;ErrStr).create();
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
</address>
</body>
</html>
diff --git a/docs/tutorial/LangImpl5.html b/docs/tutorial/LangImpl5.html
index 4fc23a1..95144dc 100644
--- a/docs/tutorial/LangImpl5.html
+++ b/docs/tutorial/LangImpl5.html
@@ -259,20 +259,20 @@ declare double @bar()
define double @baz(double %x) {
entry:
- %ifcond = fcmp one double %x, 0.000000e+00
- br i1 %ifcond, label %then, label %else
+ %ifcond = fcmp one double %x, 0.000000e+00
+ br i1 %ifcond, label %then, label %else
then: ; preds = %entry
- %calltmp = call double @foo()
- br label %ifcont
+ %calltmp = call double @foo()
+ br label %ifcont
else: ; preds = %entry
- %calltmp1 = call double @bar()
- br label %ifcont
+ %calltmp1 = call double @bar()
+ br label %ifcont
ifcont: ; preds = %else, %then
- %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ]
- ret double %iftmp
+ %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ]
+ ret double %iftmp
}
</pre>
</div>
@@ -660,25 +660,25 @@ declare double @putchard(double)
define double @printstar(double %n) {
entry:
- ; initial value = 1.0 (inlined into phi)
- br label %loop
+ ; initial value = 1.0 (inlined into phi)
+ br label %loop
loop: ; preds = %loop, %entry
- %i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ]
- ; body
- %calltmp = call double @putchard(double 4.200000e+01)
- ; increment
- %nextvar = fadd double %i, 1.000000e+00
-
- ; termination test
- %cmptmp = fcmp ult double %i, %n
- %booltmp = uitofp i1 %cmptmp to double
- %loopcond = fcmp one double %booltmp, 0.000000e+00
- br i1 %loopcond, label %loop, label %afterloop
+ %i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ]
+ ; body
+ %calltmp = call double @putchard(double 4.200000e+01)
+ ; increment
+ %nextvar = fadd double %i, 1.000000e+00
+
+ ; termination test
+ %cmptmp = fcmp ult double %i, %n
+ %booltmp = uitofp i1 %cmptmp to double
+ %loopcond = fcmp one double %booltmp, 0.000000e+00
+ br i1 %loopcond, label %loop, label %afterloop
afterloop: ; preds = %loop
- ; loop always returns 0.0
- ret double 0.000000e+00
+ ; loop always returns 0.0
+ ret double 0.000000e+00
}
</pre>
</div>
@@ -829,10 +829,11 @@ statement.</p>
</div>
<p>With the code for the body of the loop complete, we just need to finish up
-the control flow for it. This code remembers the end block (for the phi node), then creates the block for the loop exit ("afterloop"). Based on the value of the
-exit condition, it creates a conditional branch that chooses between executing
-the loop again and exiting the loop. Any future code is emitted in the
-"afterloop" block, so it sets the insertion position to it.</p>
+the control flow for it. This code remembers the end block (for the phi node),
+then creates the block for the loop exit ("afterloop"). Based on the value of
+the exit condition, it creates a conditional branch that chooses between
+executing the loop again and exiting the loop. Any future code is emitted in
+the "afterloop" block, so it sets the insertion position to it.</p>
<div class="doc_code">
<pre>
@@ -880,10 +881,10 @@ if/then/else and for expressions.. To build this example, use:
<div class="doc_code">
<pre>
- # Compile
- g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
- # Run
- ./toy
+# Compile
+clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
+# Run
+./toy
</pre>
</div>
@@ -900,9 +901,9 @@ if/then/else and for expressions.. To build this example, use:
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/IRBuilder.h"
+#include "llvm/Support/TargetSelect.h"
#include &lt;cstdio&gt;
#include &lt;string&gt;
#include &lt;map&gt;
@@ -1397,7 +1398,7 @@ Value *CallExprAST::Codegen() {
if (ArgsV.back() == 0) return 0;
}
- return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+ return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
Value *IfExprAST::Codegen() {
@@ -1546,8 +1547,8 @@ Value *ForExprAST::Codegen() {
Function *PrototypeAST::Codegen() {
// Make the function type: double(double,double) etc.
- std::vector&lt;const Type*&gt; Doubles(Args.size(),
- Type::getDoubleTy(getGlobalContext()));
+ std::vector&lt;Type*&gt; Doubles(Args.size(),
+ Type::getDoubleTy(getGlobalContext()));
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
Doubles, false);
@@ -1765,7 +1766,7 @@ int main() {
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
</address>
</body>
</html>
diff --git a/docs/tutorial/LangImpl6.html b/docs/tutorial/LangImpl6.html
index 31d7ff4..8876e83 100644
--- a/docs/tutorial/LangImpl6.html
+++ b/docs/tutorial/LangImpl6.html
@@ -293,8 +293,8 @@ Value *BinaryExprAST::Codegen() {
Function *F = TheModule-&gt;getFunction(std::string("binary")+Op);
assert(F &amp;&amp; "binary operator not found!");
- Value *Ops[] = { L, R };
- return Builder.CreateCall(F, Ops, Ops+2, "binop");</b>
+ Value *Ops[2] = { L, R };
+ return Builder.CreateCall(F, Ops, "binop");</b>
}
</pre>
@@ -505,7 +505,9 @@ defined to print out the specified value and a newline):</p>
<div class="doc_code">
<pre>
ready&gt; <b>extern printd(x);</b>
-Read extern: declare double @printd(double)
+Read extern:
+declare double @printd(double)
+
ready&gt; <b>def binary : 1 (x y) 0; # Low-precedence operator that ignores operands.</b>
..
ready&gt; <b>printd(123) : printd(456) : printd(789);</b>
@@ -555,6 +557,9 @@ def binary&amp; 6 (LHS RHS)
def binary = 9 (LHS RHS)
!(LHS &lt; RHS | LHS &gt; RHS);
+# Define ':' for sequencing: as a low-precedence operator that ignores operands
+# and just returns the RHS.
+def binary : 1 (x y) y;
</pre>
</div>
@@ -579,9 +584,10 @@ def printdensity(d)
else
putchard(42); # '*'</b>
...
-ready&gt; <b>printdensity(1): printdensity(2): printdensity(3) :
- printdensity(4): printdensity(5): printdensity(9): putchard(10);</b>
-*++..
+ready&gt; <b>printdensity(1): printdensity(2): printdensity(3):
+ printdensity(4): printdensity(5): printdensity(9):
+ putchard(10);</b>
+**++.
Evaluated to 0.000000
</pre>
</div>
@@ -593,7 +599,7 @@ converge:</p>
<div class="doc_code">
<pre>
-# determine whether the specific location diverges.
+# Determine whether the specific location diverges.
# Solve for z = z^2 + c in the complex plane.
def mandleconverger(real imag iters creal cimag)
if iters &gt; 255 | (real*real + imag*imag &gt; 4) then
@@ -603,25 +609,25 @@ def mandleconverger(real imag iters creal cimag)
2*real*imag + cimag,
iters+1, creal, cimag);
-# return the number of iterations required for the iteration to escape
+# Return the number of iterations required for the iteration to escape
def mandleconverge(real imag)
mandleconverger(real, imag, 0, real, imag);
</pre>
</div>
-<p>This "z = z<sup>2</sup> + c" function is a beautiful little creature that is the basis
-for computation of the <a
-href="http://en.wikipedia.org/wiki/Mandelbrot_set">Mandelbrot Set</a>. Our
-<tt>mandelconverge</tt> function returns the number of iterations that it takes
-for a complex orbit to escape, saturating to 255. This is not a very useful
-function by itself, but if you plot its value over a two-dimensional plane,
-you can see the Mandelbrot set. Given that we are limited to using putchard
-here, our amazing graphical output is limited, but we can whip together
+<p>This "<code>z = z<sup>2</sup> + c</code>" function is a beautiful little
+creature that is the basis for computation of
+the <a href="http://en.wikipedia.org/wiki/Mandelbrot_set">Mandelbrot Set</a>.
+Our <tt>mandelconverge</tt> function returns the number of iterations that it
+takes for a complex orbit to escape, saturating to 255. This is not a very
+useful function by itself, but if you plot its value over a two-dimensional
+plane, you can see the Mandelbrot set. Given that we are limited to using
+putchard here, our amazing graphical output is limited, but we can whip together
something using the density plotter above:</p>
<div class="doc_code">
<pre>
-# compute and plot the mandlebrot set with the specified 2 dimensional range
+# Compute and plot the mandlebrot set with the specified 2 dimensional range
# info.
def mandelhelp(xmin xmax xstep ymin ymax ystep)
for y = ymin, y &lt; ymax, ystep in (
@@ -808,13 +814,19 @@ if/then/else and for expressions.. To build this example, use:
<div class="doc_code">
<pre>
- # Compile
- g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
- # Run
- ./toy
+# Compile
+clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
+# Run
+./toy
</pre>
</div>
+<p>On some platforms, you will need to specify -rdynamic or -Wl,--export-dynamic
+when linking. This ensures that symbols defined in the main executable are
+exported to the dynamic linker and so are available for symbol resolution at
+run time. This is not needed if you compile your support code into a shared
+library, although doing that will cause problems on Windows.</p>
+
<p>Here is the code:</p>
<div class="doc_code">
@@ -828,9 +840,9 @@ if/then/else and for expressions.. To build this example, use:
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/IRBuilder.h"
+#include "llvm/Support/TargetSelect.h"
#include &lt;cstdio&gt;
#include &lt;string&gt;
#include &lt;map&gt;
@@ -1409,8 +1421,8 @@ Value *BinaryExprAST::Codegen() {
Function *F = TheModule-&gt;getFunction(std::string("binary")+Op);
assert(F &amp;&amp; "binary operator not found!");
- Value *Ops[] = { L, R };
- return Builder.CreateCall(F, Ops, Ops+2, "binop");
+ Value *Ops[2] = { L, R };
+ return Builder.CreateCall(F, Ops, "binop");
}
Value *CallExprAST::Codegen() {
@@ -1429,7 +1441,7 @@ Value *CallExprAST::Codegen() {
if (ArgsV.back() == 0) return 0;
}
- return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+ return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
Value *IfExprAST::Codegen() {
@@ -1578,8 +1590,8 @@ Value *ForExprAST::Codegen() {
Function *PrototypeAST::Codegen() {
// Make the function type: double(double,double) etc.
- std::vector&lt;const Type*&gt; Doubles(Args.size(),
- Type::getDoubleTy(getGlobalContext()));
+ std::vector&lt;Type*&gt; Doubles(Args.size(),
+ Type::getDoubleTy(getGlobalContext()));
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
Doubles, false);
@@ -1811,7 +1823,7 @@ int main() {
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
</address>
</body>
</html>
diff --git a/docs/tutorial/LangImpl7.html b/docs/tutorial/LangImpl7.html
index a4a21f1..939987b 100644
--- a/docs/tutorial/LangImpl7.html
+++ b/docs/tutorial/LangImpl7.html
@@ -102,19 +102,19 @@ The LLVM IR that we want for this example looks like this:</p>
define i32 @test(i1 %Condition) {
entry:
- br i1 %Condition, label %cond_true, label %cond_false
+ br i1 %Condition, label %cond_true, label %cond_false
cond_true:
- %X.0 = load i32* @G
- br label %cond_next
+ %X.0 = load i32* @G
+ br label %cond_next
cond_false:
- %X.1 = load i32* @H
- br label %cond_next
+ %X.1 = load i32* @H
+ br label %cond_next
cond_next:
- %X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
- ret i32 %X.2
+ %X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
+ ret i32 %X.2
}
</pre>
</div>
@@ -174,12 +174,12 @@ being declared with global variable definitions, they are declared with the
<pre>
define i32 @example() {
entry:
- %X = alloca i32 ; type of %X is i32*.
- ...
- %tmp = load i32* %X ; load the stack value %X from the stack.
- %tmp2 = add i32 %tmp, 1 ; increment it
- store i32 %tmp2, i32* %X ; store it back
- ...
+ %X = alloca i32 ; type of %X is i32*.
+ ...
+ %tmp = load i32* %X ; load the stack value %X from the stack.
+ %tmp2 = add i32 %tmp, 1 ; increment it
+ store i32 %tmp2, i32* %X ; store it back
+ ...
</pre>
</div>
@@ -196,22 +196,22 @@ example to use the alloca technique to avoid using a PHI node:</p>
define i32 @test(i1 %Condition) {
entry:
- %X = alloca i32 ; type of %X is i32*.
- br i1 %Condition, label %cond_true, label %cond_false
+ %X = alloca i32 ; type of %X is i32*.
+ br i1 %Condition, label %cond_true, label %cond_false
cond_true:
- %X.0 = load i32* @G
- store i32 %X.0, i32* %X ; Update X
- br label %cond_next
+ %X.0 = load i32* @G
+ store i32 %X.0, i32* %X ; Update X
+ br label %cond_next
cond_false:
- %X.1 = load i32* @H
- store i32 %X.1, i32* %X ; Update X
- br label %cond_next
+ %X.1 = load i32* @H
+ store i32 %X.1, i32* %X ; Update X
+ br label %cond_next
cond_next:
- %X.2 = load i32* %X ; Read X
- ret i32 %X.2
+ %X.2 = load i32* %X ; Read X
+ ret i32 %X.2
}
</pre>
</div>
@@ -242,19 +242,19 @@ $ <b>llvm-as &lt; example.ll | opt -mem2reg | llvm-dis</b>
define i32 @test(i1 %Condition) {
entry:
- br i1 %Condition, label %cond_true, label %cond_false
+ br i1 %Condition, label %cond_true, label %cond_false
cond_true:
- %X.0 = load i32* @G
- br label %cond_next
+ %X.0 = load i32* @G
+ br label %cond_next
cond_false:
- %X.1 = load i32* @H
- br label %cond_next
+ %X.1 = load i32* @H
+ br label %cond_next
cond_next:
- %X.01 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
- ret i32 %X.01
+ %X.01 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
+ ret i32 %X.01
}
</pre>
</div>
@@ -542,30 +542,30 @@ recursive fib function. Before the optimization:</p>
<pre>
define double @fib(double %x) {
entry:
- <b>%x1 = alloca double
- store double %x, double* %x1
- %x2 = load double* %x1</b>
- %cmptmp = fcmp ult double %x2, 3.000000e+00
- %booltmp = uitofp i1 %cmptmp to double
- %ifcond = fcmp one double %booltmp, 0.000000e+00
- br i1 %ifcond, label %then, label %else
+ <b>%x1 = alloca double
+ store double %x, double* %x1
+ %x2 = load double* %x1</b>
+ %cmptmp = fcmp ult double %x2, 3.000000e+00
+ %booltmp = uitofp i1 %cmptmp to double
+ %ifcond = fcmp one double %booltmp, 0.000000e+00
+ br i1 %ifcond, label %then, label %else
then: ; preds = %entry
- br label %ifcont
+ br label %ifcont
else: ; preds = %entry
- <b>%x3 = load double* %x1</b>
- %subtmp = fsub double %x3, 1.000000e+00
- %calltmp = call double @fib(double %subtmp)
- <b>%x4 = load double* %x1</b>
- %subtmp5 = fsub double %x4, 2.000000e+00
- %calltmp6 = call double @fib(double %subtmp5)
- %addtmp = fadd double %calltmp, %calltmp6
- br label %ifcont
+ <b>%x3 = load double* %x1</b>
+ %subtmp = fsub double %x3, 1.000000e+00
+ %calltmp = call double @fib(double %subtmp)
+ <b>%x4 = load double* %x1</b>
+ %subtmp5 = fsub double %x4, 2.000000e+00
+ %calltmp6 = call double @fib(double %subtmp5)
+ %addtmp = fadd double %calltmp, %calltmp6
+ br label %ifcont
ifcont: ; preds = %else, %then
- %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
- ret double %iftmp
+ %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
+ ret double %iftmp
}
</pre>
</div>
@@ -584,25 +584,25 @@ PHI node for it, so we still just make the PHI.</p>
<pre>
define double @fib(double %x) {
entry:
- %cmptmp = fcmp ult double <b>%x</b>, 3.000000e+00
- %booltmp = uitofp i1 %cmptmp to double
- %ifcond = fcmp one double %booltmp, 0.000000e+00
- br i1 %ifcond, label %then, label %else
+ %cmptmp = fcmp ult double <b>%x</b>, 3.000000e+00
+ %booltmp = uitofp i1 %cmptmp to double
+ %ifcond = fcmp one double %booltmp, 0.000000e+00
+ br i1 %ifcond, label %then, label %else
then:
- br label %ifcont
+ br label %ifcont
else:
- %subtmp = fsub double <b>%x</b>, 1.000000e+00
- %calltmp = call double @fib(double %subtmp)
- %subtmp5 = fsub double <b>%x</b>, 2.000000e+00
- %calltmp6 = call double @fib(double %subtmp5)
- %addtmp = fadd double %calltmp, %calltmp6
- br label %ifcont
+ %subtmp = fsub double <b>%x</b>, 1.000000e+00
+ %calltmp = call double @fib(double %subtmp)
+ %subtmp5 = fsub double <b>%x</b>, 2.000000e+00
+ %calltmp6 = call double @fib(double %subtmp5)
+ %addtmp = fadd double %calltmp, %calltmp6
+ br label %ifcont
ifcont: ; preds = %else, %then
- %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
- ret double %iftmp
+ %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
+ ret double %iftmp
}
</pre>
</div>
@@ -617,21 +617,21 @@ such blatent inefficiencies :).</p>
<pre>
define double @fib(double %x) {
entry:
- %cmptmp = fcmp ult double %x, 3.000000e+00
- %booltmp = uitofp i1 %cmptmp to double
- %ifcond = fcmp ueq double %booltmp, 0.000000e+00
- br i1 %ifcond, label %else, label %ifcont
+ %cmptmp = fcmp ult double %x, 3.000000e+00
+ %booltmp = uitofp i1 %cmptmp to double
+ %ifcond = fcmp ueq double %booltmp, 0.000000e+00
+ br i1 %ifcond, label %else, label %ifcont
else:
- %subtmp = fsub double %x, 1.000000e+00
- %calltmp = call double @fib(double %subtmp)
- %subtmp5 = fsub double %x, 2.000000e+00
- %calltmp6 = call double @fib(double %subtmp5)
- %addtmp = fadd double %calltmp, %calltmp6
- ret double %addtmp
+ %subtmp = fsub double %x, 1.000000e+00
+ %calltmp = call double @fib(double %subtmp)
+ %subtmp5 = fsub double %x, 2.000000e+00
+ %calltmp6 = call double @fib(double %subtmp5)
+ %addtmp = fadd double %calltmp, %calltmp6
+ ret double %addtmp
ifcont:
- ret double 1.000000e+00
+ ret double 1.000000e+00
}
</pre>
</div>
@@ -988,10 +988,10 @@ variables and var/in support. To build this example, use:
<div class="doc_code">
<pre>
- # Compile
- g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
- # Run
- ./toy
+# Compile
+clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
+# Run
+./toy
</pre>
</div>
@@ -1008,9 +1008,9 @@ variables and var/in support. To build this example, use:
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/IRBuilder.h"
+#include "llvm/Support/TargetSelect.h"
#include &lt;cstdio&gt;
#include &lt;string&gt;
#include &lt;map&gt;
@@ -1686,8 +1686,8 @@ Value *BinaryExprAST::Codegen() {
Function *F = TheModule-&gt;getFunction(std::string("binary")+Op);
assert(F &amp;&amp; "binary operator not found!");
- Value *Ops[] = { L, R };
- return Builder.CreateCall(F, Ops, Ops+2, "binop");
+ Value *Ops[2] = { L, R };
+ return Builder.CreateCall(F, Ops, "binop");
}
Value *CallExprAST::Codegen() {
@@ -1706,7 +1706,7 @@ Value *CallExprAST::Codegen() {
if (ArgsV.back() == 0) return 0;
}
- return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+ return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
Value *IfExprAST::Codegen() {
@@ -1907,8 +1907,8 @@ Value *VarExprAST::Codegen() {
Function *PrototypeAST::Codegen() {
// Make the function type: double(double,double) etc.
- std::vector&lt;const Type*&gt; Doubles(Args.size(),
- Type::getDoubleTy(getGlobalContext()));
+ std::vector&lt;Type*&gt; Doubles(Args.size(),
+ Type::getDoubleTy(getGlobalContext()));
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
Doubles, false);
@@ -2158,7 +2158,7 @@ int main() {
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
+ Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
</address>
</body>
</html>
diff --git a/docs/tutorial/Makefile b/docs/tutorial/Makefile
index 9082ad4..fdf1bb6 100644
--- a/docs/tutorial/Makefile
+++ b/docs/tutorial/Makefile
@@ -11,6 +11,7 @@ LEVEL := ../..
include $(LEVEL)/Makefile.common
HTML := $(wildcard $(PROJ_SRC_DIR)/*.html)
+PNG := $(wildcard $(PROJ_SRC_DIR)/*.png)
EXTRA_DIST := $(HTML) index.html
HTML_DIR := $(DESTDIR)$(PROJ_docsdir)/html/tutorial
@@ -18,6 +19,7 @@ install-local:: $(HTML)
$(Echo) Installing HTML Tutorial Documentation
$(Verb) $(MKDIR) $(HTML_DIR)
$(Verb) $(DataInstall) $(HTML) $(HTML_DIR)
+ $(Verb) $(DataInstall) $(PNG) $(HTML_DIR)
$(Verb) $(DataInstall) $(PROJ_SRC_DIR)/index.html $(HTML_DIR)
uninstall-local::
diff --git a/examples/BrainF/BrainF.cpp b/examples/BrainF/BrainF.cpp
index 67af099..df6687f 100644
--- a/examples/BrainF/BrainF.cpp
+++ b/examples/BrainF/BrainF.cpp
@@ -80,8 +80,8 @@ void BrainF::header(LLVMContext& C) {
//%arr = malloc i8, i32 %d
ConstantInt *val_mem = ConstantInt::get(C, APInt(32, memtotal));
BasicBlock* BB = builder->GetInsertBlock();
- const Type* IntPtrTy = IntegerType::getInt32Ty(C);
- const Type* Int8Ty = IntegerType::getInt8Ty(C);
+ Type* IntPtrTy = IntegerType::getInt32Ty(C);
+ Type* Int8Ty = IntegerType::getInt8Ty(C);
Constant* allocsize = ConstantExpr::getSizeOf(Int8Ty);
allocsize = ConstantExpr::getTruncOrBitCast(allocsize, IntPtrTy);
ptr_arr = CallInst::CreateMalloc(BB, IntPtrTy, Int8Ty, allocsize, val_mem,
@@ -162,8 +162,7 @@ void BrainF::header(LLVMContext& C) {
};
Constant *msgptr = ConstantExpr::
- getGetElementPtr(aberrormsg, gep_params,
- array_lengthof(gep_params));
+ getGetElementPtr(aberrormsg, gep_params);
Value *puts_params[] = {
msgptr
diff --git a/examples/BrainF/BrainFDriver.cpp b/examples/BrainF/BrainFDriver.cpp
index c11a580..cdbf02a 100644
--- a/examples/BrainF/BrainFDriver.cpp
+++ b/examples/BrainF/BrainFDriver.cpp
@@ -31,9 +31,9 @@
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JIT.h"
-#include "llvm/Target/TargetSelect.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include <iostream>
#include <fstream>
diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp
index e5d9451..20516a7 100644
--- a/examples/ExceptionDemo/ExceptionDemo.cpp
+++ b/examples/ExceptionDemo/ExceptionDemo.cpp
@@ -40,7 +40,8 @@
//
// Cases -1 and 7 are caught by a C++ test harness where the validity of
// of a C++ catch(...) clause catching a generated exception with a
-// type info type of 7 is questionable.
+// type info type of 7 is explained by: example in rules 1.6.4 in
+// http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22)
//
// This code uses code from the llvm compiler-rt project and the llvm
// Kaleidoscope project.
@@ -56,11 +57,16 @@
#include "llvm/Intrinsics.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/TargetSelect.h"
+
+#ifdef OLD_EXC_SYSTEM
+// See use of UpgradeExceptionHandling(...) below
+#include "llvm/AutoUpgrade.h"
+#endif
// FIXME: Although all systems tested with (Linux, OS X), do not need this
// header file included. A user on ubuntu reported, undefined symbols
@@ -81,7 +87,7 @@
#endif
// System C++ ABI unwind types from:
-// http://refspecs.freestandards.org/abi-eh-1.21.html
+// http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22)
extern "C" {
@@ -182,6 +188,9 @@ static std::vector<std::string> ourTypeInfoNames;
static std::map<int, std::string> ourTypeInfoNamesIndex;
static llvm::StructType *ourTypeInfoType;
+#ifndef OLD_EXC_SYSTEM
+static llvm::StructType *ourCaughtResultType;
+#endif
static llvm::StructType *ourExceptionType;
static llvm::StructType *ourUnwindExceptionType;
@@ -209,7 +218,7 @@ typedef std::vector<llvm::Type*> ArgTypes;
/// @param isVarArg function uses vararg arguments
/// @returns function instance
llvm::Function *createFunction(llvm::Module &module,
- const llvm::Type *retType,
+ llvm::Type *retType,
const ArgTypes &theArgTypes,
const ArgNames &theArgNames,
const std::string &functName,
@@ -246,7 +255,7 @@ llvm::Function *createFunction(llvm::Module &module,
/// @returns AllocaInst instance
static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function,
const std::string &varName,
- const llvm::Type *type,
+ llvm::Type *type,
llvm::Constant *initWith = 0) {
llvm::BasicBlock &block = function.getEntryBlock();
llvm::IRBuilder<> tmp(&block, block.begin());
@@ -893,9 +902,8 @@ void generateStringPrint(llvm::LLVMContext &context,
builder.CreateStore(stringConstant, stringVar);
}
- llvm::Value *cast =
- builder.CreatePointerCast(stringVar,
- builder.getInt8PtrTy());
+ llvm::Value *cast = builder.CreatePointerCast(stringVar,
+ builder.getInt8PtrTy());
builder.CreateCall(printFunct, cast);
}
@@ -937,9 +945,8 @@ void generateIntegerPrint(llvm::LLVMContext &context,
builder.CreateStore(stringConstant, stringVar);
}
- llvm::Value *cast =
- builder.CreateBitCast(stringVar,
- builder.getInt8PtrTy());
+ llvm::Value *cast = builder.CreateBitCast(stringVar,
+ builder.getInt8PtrTy());
builder.CreateCall2(&printFunct, &toPrint, cast);
}
@@ -962,6 +969,9 @@ void generateIntegerPrint(llvm::LLVMContext &context,
/// @param unwindResumeBlock unwind resume block
/// @param exceptionCaughtFlag reference exception caught/thrown status storage
/// @param exceptionStorage reference to exception pointer storage
+#ifndef OLD_EXC_SYSTEM
+/// @param caughtResultStorage reference to landingpad result storage
+#endif
/// @returns newly created block
static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
llvm::Module &module,
@@ -972,28 +982,42 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
llvm::BasicBlock &terminatorBlock,
llvm::BasicBlock &unwindResumeBlock,
llvm::Value **exceptionCaughtFlag,
- llvm::Value **exceptionStorage) {
+ llvm::Value **exceptionStorage
+#ifndef OLD_EXC_SYSTEM
+ ,llvm::Value **caughtResultStorage
+#endif
+ ) {
assert(exceptionCaughtFlag &&
"ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag "
"is NULL");
assert(exceptionStorage &&
"ExceptionDemo::createFinallyBlock(...):exceptionStorage "
"is NULL");
+
+#ifndef OLD_EXC_SYSTEM
+ assert(caughtResultStorage &&
+ "ExceptionDemo::createFinallyBlock(...):caughtResultStorage "
+ "is NULL");
+#endif
- *exceptionCaughtFlag =
- createEntryBlockAlloca(toAddTo,
- "exceptionCaught",
- ourExceptionNotThrownState->getType(),
- ourExceptionNotThrownState);
-
- const llvm::PointerType *exceptionStorageType =
- builder.getInt8PtrTy();
- *exceptionStorage =
- createEntryBlockAlloca(toAddTo,
- "exceptionStorage",
- exceptionStorageType,
- llvm::ConstantPointerNull::get(
- exceptionStorageType));
+ *exceptionCaughtFlag = createEntryBlockAlloca(toAddTo,
+ "exceptionCaught",
+ ourExceptionNotThrownState->getType(),
+ ourExceptionNotThrownState);
+
+ llvm::PointerType *exceptionStorageType = builder.getInt8PtrTy();
+ *exceptionStorage = createEntryBlockAlloca(toAddTo,
+ "exceptionStorage",
+ exceptionStorageType,
+ llvm::ConstantPointerNull::get(
+ exceptionStorageType));
+#ifndef OLD_EXC_SYSTEM
+ *caughtResultStorage = createEntryBlockAlloca(toAddTo,
+ "caughtResultStorage",
+ ourCaughtResultType,
+ llvm::ConstantAggregateZero::get(
+ ourCaughtResultType));
+#endif
llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
blockName,
@@ -1010,10 +1034,10 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
bufferToPrint.str(),
USE_GLOBAL_STR_CONSTS);
- llvm::SwitchInst *theSwitch =
- builder.CreateSwitch(builder.CreateLoad(*exceptionCaughtFlag),
- &terminatorBlock,
- 2);
+ llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad(
+ *exceptionCaughtFlag),
+ &terminatorBlock,
+ 2);
theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
@@ -1121,29 +1145,35 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
"normal",
ret);
// Unwind block for invoke
- llvm::BasicBlock *exceptionBlock =
- llvm::BasicBlock::Create(context, "exception", ret);
+ llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context,
+ "exception",
+ ret);
// Block which routes exception to correct catch handler block
- llvm::BasicBlock *exceptionRouteBlock =
- llvm::BasicBlock::Create(context, "exceptionRoute", ret);
+ llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context,
+ "exceptionRoute",
+ ret);
// Foreign exception handler
- llvm::BasicBlock *externalExceptionBlock =
- llvm::BasicBlock::Create(context, "externalException", ret);
+ llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context,
+ "externalException",
+ ret);
// Block which calls _Unwind_Resume
- llvm::BasicBlock *unwindResumeBlock =
- llvm::BasicBlock::Create(context, "unwindResume", ret);
+ llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context,
+ "unwindResume",
+ ret);
// Clean up block which delete exception if needed
- llvm::BasicBlock *endBlock =
- llvm::BasicBlock::Create(context, "end", ret);
+ llvm::BasicBlock *endBlock = llvm::BasicBlock::Create(context, "end", ret);
std::string nextName;
std::vector<llvm::BasicBlock*> catchBlocks(numExceptionsToCatch);
llvm::Value *exceptionCaughtFlag = NULL;
llvm::Value *exceptionStorage = NULL;
+#ifndef OLD_EXC_SYSTEM
+ llvm::Value *caughtResultStorage = NULL;
+#endif
// Finally block which will branch to unwindResumeBlock if
// exception is not caught. Initializes/allocates stack locations.
@@ -1156,7 +1186,11 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
*endBlock,
*unwindResumeBlock,
&exceptionCaughtFlag,
- &exceptionStorage);
+ &exceptionStorage
+#ifndef OLD_EXC_SYSTEM
+ ,&caughtResultStorage
+#endif
+ );
for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
@@ -1181,8 +1215,7 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
builder.CreateInvoke(&toInvoke,
normalBlock,
exceptionBlock,
- args.begin(),
- args.end());
+ args);
// End Block
@@ -1193,8 +1226,7 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
builder,
"Gen: In end block: exiting in " + ourId + ".\n",
USE_GLOBAL_STR_CONSTS);
- llvm::Function *deleteOurException =
- module.getFunction("deleteOurException");
+ llvm::Function *deleteOurException = module.getFunction("deleteOurException");
// Note: function handles NULL exceptions
builder.CreateCall(deleteOurException,
@@ -1218,28 +1250,57 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
builder.SetInsertPoint(unwindResumeBlock);
- llvm::Function *resumeOurException =
- module.getFunction("_Unwind_Resume");
+
+#ifndef OLD_EXC_SYSTEM
+ builder.CreateResume(builder.CreateLoad(caughtResultStorage));
+#else
+ llvm::Function *resumeOurException = module.getFunction("_Unwind_Resume");
builder.CreateCall(resumeOurException,
builder.CreateLoad(exceptionStorage));
builder.CreateUnreachable();
+#endif
// Exception Block
builder.SetInsertPoint(exceptionBlock);
- llvm::Function *ehException = module.getFunction("llvm.eh.exception");
+ llvm::Function *personality = module.getFunction("ourPersonality");
+#ifndef OLD_EXC_SYSTEM
+ llvm::LandingPadInst *caughtResult =
+ builder.CreateLandingPad(ourCaughtResultType,
+ personality,
+ numExceptionsToCatch,
+ "landingPad");
+
+ caughtResult->setCleanup(true);
+
+ for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
+ // Set up type infos to be caught
+ caughtResult->addClause(module.getGlobalVariable(
+ ourTypeInfoNames[exceptionTypesToCatch[i]]));
+ }
+
+ llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0);
+ llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1);
+
+ // FIXME: Redundant storage which, beyond utilizing value of
+ // caughtResultStore for unwindException storage, may be alleviated
+ // alltogether with a block rearrangement
+ builder.CreateStore(caughtResult, caughtResultStorage);
+ builder.CreateStore(unwindException, exceptionStorage);
+ builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
+#else
+ llvm::Function *ehException = module.getFunction("llvm.eh.exception");
+
// Retrieve thrown exception
llvm::Value *unwindException = builder.CreateCall(ehException);
// Store exception and flag
builder.CreateStore(unwindException, exceptionStorage);
builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
- llvm::Function *personality = module.getFunction("ourPersonality");
- llvm::Value *functPtr =
- builder.CreatePointerCast(personality,
- builder.getInt8PtrTy());
+ llvm::Value *functPtr = builder.CreatePointerCast(personality,
+ builder.getInt8PtrTy());
args.clear();
args.push_back(unwindException);
@@ -1263,9 +1324,8 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
// handles this call. This landing pad (this exception block), will be
// called either because it nees to cleanup (call finally) or a type
// info was found which matched the thrown exception.
- llvm::Value *retTypeInfoIndex = builder.CreateCall(ehSelector,
- args.begin(),
- args.end());
+ llvm::Value *retTypeInfoIndex = builder.CreateCall(ehSelector, args);
+#endif
// Retrieve exception_class member from thrown exception
// (_Unwind_Exception instance). This member tells us whether or not
@@ -1305,10 +1365,10 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
// (OurException instance).
//
// Note: ourBaseFromUnwindOffset is usually negative
- llvm::Value *typeInfoThrown =
- builder.CreatePointerCast(builder.CreateConstGEP1_64(unwindException,
+ llvm::Value *typeInfoThrown = builder.CreatePointerCast(
+ builder.CreateConstGEP1_64(unwindException,
ourBaseFromUnwindOffset),
- ourExceptionType->getPointerTo());
+ ourExceptionType->getPointerTo());
// Retrieve thrown exception type info type
//
@@ -1331,10 +1391,9 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
USE_GLOBAL_STR_CONSTS);
// Route to matched type info catch block or run cleanup finally block
- llvm::SwitchInst *switchToCatchBlock =
- builder.CreateSwitch(retTypeInfoIndex,
- finallyBlock,
- numExceptionsToCatch);
+ llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex,
+ finallyBlock,
+ numExceptionsToCatch);
unsigned nextTypeToCatch;
@@ -1344,6 +1403,12 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
llvm::Type::getInt32Ty(context), i),
catchBlocks[nextTypeToCatch]);
}
+
+#ifdef OLD_EXC_SYSTEM
+ // Must be run before verifier
+ UpgradeExceptionHandling(&module);
+#endif
+
llvm::verifyFunction(*ret);
fpm.run(*ret);
@@ -1395,15 +1460,13 @@ llvm::Function *createThrowExceptionFunction(llvm::Module &module,
"entry",
ret);
// Throws a foreign exception
- llvm::BasicBlock *nativeThrowBlock =
- llvm::BasicBlock::Create(context,
- "nativeThrow",
- ret);
+ llvm::BasicBlock *nativeThrowBlock = llvm::BasicBlock::Create(context,
+ "nativeThrow",
+ ret);
// Throws one of our Exceptions
- llvm::BasicBlock *generatedThrowBlock =
- llvm::BasicBlock::Create(context,
- "generatedThrow",
- ret);
+ llvm::BasicBlock *generatedThrowBlock = llvm::BasicBlock::Create(context,
+ "generatedThrow",
+ ret);
// Retrieved runtime type info type to throw
llvm::Value *exceptionType = namedValues["exceptTypeToThrow"];
@@ -1445,15 +1508,13 @@ llvm::Function *createThrowExceptionFunction(llvm::Module &module,
builder.SetInsertPoint(generatedThrowBlock);
- llvm::Function *createOurException =
- module.getFunction("createOurException");
- llvm::Function *raiseOurException =
- module.getFunction("_Unwind_RaiseException");
+ llvm::Function *createOurException = module.getFunction("createOurException");
+ llvm::Function *raiseOurException = module.getFunction(
+ "_Unwind_RaiseException");
// Creates exception to throw with runtime type info type.
- llvm::Value *exception =
- builder.CreateCall(createOurException,
- namedValues["exceptTypeToThrow"]);
+ llvm::Value *exception = builder.CreateCall(createOurException,
+ namedValues["exceptTypeToThrow"]);
// Throw generated Exception
builder.CreateCall(raiseOurException, exception);
@@ -1501,32 +1562,29 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module,
createStandardUtilityFunctions(numTypeInfos,
module,
builder);
- llvm::Function *nativeThrowFunct =
- module.getFunction(nativeThrowFunctName);
+ llvm::Function *nativeThrowFunct = module.getFunction(nativeThrowFunctName);
// Create exception throw function using the value ~0 to cause
// foreign exceptions to be thrown.
- llvm::Function *throwFunct =
- createThrowExceptionFunction(module,
- builder,
- fpm,
- "throwFunct",
- ~0,
- *nativeThrowFunct);
+ llvm::Function *throwFunct = createThrowExceptionFunction(module,
+ builder,
+ fpm,
+ "throwFunct",
+ ~0,
+ *nativeThrowFunct);
// Inner function will catch even type infos
unsigned innerExceptionTypesToCatch[] = {6, 2, 4};
size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
- sizeof(unsigned);
+ sizeof(unsigned);
// Generate inner function.
- llvm::Function *innerCatchFunct =
- createCatchWrappedInvokeFunction(module,
- builder,
- fpm,
- *throwFunct,
- "innerCatchFunct",
- numExceptionTypesToCatch,
- innerExceptionTypesToCatch);
+ llvm::Function *innerCatchFunct = createCatchWrappedInvokeFunction(module,
+ builder,
+ fpm,
+ *throwFunct,
+ "innerCatchFunct",
+ numExceptionTypesToCatch,
+ innerExceptionTypesToCatch);
// Outer function will catch odd type infos
unsigned outerExceptionTypesToCatch[] = {3, 1, 5};
@@ -1534,14 +1592,13 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module,
sizeof(unsigned);
// Generate outer function
- llvm::Function *outerCatchFunct =
- createCatchWrappedInvokeFunction(module,
- builder,
- fpm,
- *innerCatchFunct,
- "outerCatchFunct",
- numExceptionTypesToCatch,
- outerExceptionTypesToCatch);
+ llvm::Function *outerCatchFunct = createCatchWrappedInvokeFunction(module,
+ builder,
+ fpm,
+ *innerCatchFunct,
+ "outerCatchFunct",
+ numExceptionTypesToCatch,
+ outerExceptionTypesToCatch);
// Return outer function to run
return(outerCatchFunct);
@@ -1607,12 +1664,12 @@ void runExceptionThrow(llvm::ExecutionEngine *engine,
exc.what());
}
catch (...) {
- // Catch all exceptions including our generated ones. I'm not sure
- // why this latter functionality should work, as it seems that
- // our exceptions should be foreign to C++ (the _Unwind_Exception::
- // exception_class should be different from the one used by C++), and
- // therefore C++ should ignore the generated exceptions.
-
+ // Catch all exceptions including our generated ones. This latter
+ // functionality works according to the example in rules 1.6.4 of
+ // http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22),
+ // given that these will be exceptions foreign to C++
+ // (the _Unwind_Exception::exception_class should be different from
+ // the one used by C++).
fprintf(stderr,
"\nrunExceptionThrow(...):In C++ catch all.\n");
}
@@ -1640,17 +1697,31 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
// Setup exception catch state
ourExceptionNotThrownState =
- llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
+ llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
ourExceptionThrownState =
- llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
+ llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
ourExceptionCaughtState =
- llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
+ llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
// Create our type info type
ourTypeInfoType = llvm::StructType::get(context,
- TypeArray(builder.getInt32Ty()));
+ TypeArray(builder.getInt32Ty()));
+
+#ifndef OLD_EXC_SYSTEM
+
+ llvm::Type *caughtResultFieldTypes[] = {
+ builder.getInt8PtrTy(),
+ builder.getInt32Ty()
+ };
+
+ // Create our landingpad result type
+ ourCaughtResultType = llvm::StructType::get(context,
+ TypeArray(caughtResultFieldTypes));
+
+#endif
+
// Create OurException type
ourExceptionType = llvm::StructType::get(context,
TypeArray(ourTypeInfoType));
@@ -1667,7 +1738,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
// Calculate offset of OurException::unwindException member.
ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
- ((uintptr_t) &(dummyException.unwindException));
+ ((uintptr_t) &(dummyException.unwindException));
#ifdef DEBUG
fprintf(stderr,
@@ -1724,7 +1795,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
// print32Int
- const llvm::Type *retType = builder.getVoidTy();
+ llvm::Type *retType = builder.getVoidTy();
argTypes.clear();
argTypes.push_back(builder.getInt32Ty());
diff --git a/examples/Fibonacci/fibonacci.cpp b/examples/Fibonacci/fibonacci.cpp
index a7bbf8c..a7d1ca8 100644
--- a/examples/Fibonacci/fibonacci.cpp
+++ b/examples/Fibonacci/fibonacci.cpp
@@ -33,7 +33,7 @@
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetSelect.h"
+#include "llvm/Support/TargetSelect.h"
using namespace llvm;
static Function *CreateFibFunction(Module *M, LLVMContext &Context) {
diff --git a/examples/HowToUseJIT/HowToUseJIT.cpp b/examples/HowToUseJIT/HowToUseJIT.cpp
index 2fb2b5e..92b2860 100644
--- a/examples/HowToUseJIT/HowToUseJIT.cpp
+++ b/examples/HowToUseJIT/HowToUseJIT.cpp
@@ -42,7 +42,7 @@
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/GenericValue.h"
-#include "llvm/Target/TargetSelect.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/IRBuilder.h"
diff --git a/examples/Kaleidoscope/Chapter4/toy.cpp b/examples/Kaleidoscope/Chapter4/toy.cpp
index 1bed182..9a28322 100644
--- a/examples/Kaleidoscope/Chapter4/toy.cpp
+++ b/examples/Kaleidoscope/Chapter4/toy.cpp
@@ -7,9 +7,9 @@
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/IRBuilder.h"
+#include "llvm/Support/TargetSelect.h"
#include <cstdio>
#include <string>
#include <map>
diff --git a/examples/Kaleidoscope/Chapter5/toy.cpp b/examples/Kaleidoscope/Chapter5/toy.cpp
index 58ab6f3..adfbad5 100644
--- a/examples/Kaleidoscope/Chapter5/toy.cpp
+++ b/examples/Kaleidoscope/Chapter5/toy.cpp
@@ -7,9 +7,9 @@
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/IRBuilder.h"
+#include "llvm/Support/TargetSelect.h"
#include <cstdio>
#include <string>
#include <map>
diff --git a/examples/Kaleidoscope/Chapter6/toy.cpp b/examples/Kaleidoscope/Chapter6/toy.cpp
index b25e946..c16d6bd 100644
--- a/examples/Kaleidoscope/Chapter6/toy.cpp
+++ b/examples/Kaleidoscope/Chapter6/toy.cpp
@@ -7,9 +7,9 @@
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/IRBuilder.h"
+#include "llvm/Support/TargetSelect.h"
#include <cstdio>
#include <string>
#include <map>
diff --git a/examples/Kaleidoscope/Chapter7/toy.cpp b/examples/Kaleidoscope/Chapter7/toy.cpp
index 63a7bca..87b28c3 100644
--- a/examples/Kaleidoscope/Chapter7/toy.cpp
+++ b/examples/Kaleidoscope/Chapter7/toy.cpp
@@ -7,9 +7,9 @@
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/IRBuilder.h"
+#include "llvm/Support/TargetSelect.h"
#include <cstdio>
#include <string>
#include <map>
diff --git a/examples/ParallelJIT/ParallelJIT.cpp b/examples/ParallelJIT/ParallelJIT.cpp
index 9231abf..3e48327 100644
--- a/examples/ParallelJIT/ParallelJIT.cpp
+++ b/examples/ParallelJIT/ParallelJIT.cpp
@@ -26,7 +26,7 @@
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/GenericValue.h"
-#include "llvm/Target/TargetSelect.h"
+#include "llvm/Support/TargetSelect.h"
#include <iostream>
using namespace llvm;
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h
index a4456dd..d23b91c 100644
--- a/include/llvm-c/Core.h
+++ b/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<Type**>(Tys);
}
- inline LLVMTypeRef *wrap(const Type **Tys) {
+ inline LLVMTypeRef *wrap(Type **Tys) {
return reinterpret_cast<LLVMTypeRef*>(const_cast<Type**>(Tys));
}
diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h
index 3a3eb23..bf2f276 100644
--- a/include/llvm-c/Disassembler.h
+++ b/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/include/llvm-c/Object.h b/include/llvm-c/Object.h
index 6e72b59..7b1cf71 100644
--- a/include/llvm-c/Object.h
+++ b/include/llvm-c/Object.h
@@ -59,14 +59,14 @@ namespace llvm {
return reinterpret_cast<LLVMObjectFileRef>(const_cast<ObjectFile*>(OF));
}
- inline ObjectFile::section_iterator *unwrap(LLVMSectionIteratorRef SI) {
- return reinterpret_cast<ObjectFile::section_iterator*>(SI);
+ inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
+ return reinterpret_cast<section_iterator*>(SI);
}
inline LLVMSectionIteratorRef
- wrap(const ObjectFile::section_iterator *SI) {
+ wrap(const section_iterator *SI) {
return reinterpret_cast<LLVMSectionIteratorRef>
- (const_cast<ObjectFile::section_iterator*>(SI));
+ (const_cast<section_iterator*>(SI));
}
}
}
diff --git a/include/llvm-c/Target.h b/include/llvm-c/Target.h
index d216440..7afaef1 100644
--- a/include/llvm-c/Target.h
+++ b/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<TargetData*>(P);
@@ -165,6 +172,15 @@ namespace llvm {
inline LLVMTargetDataRef wrap(const TargetData *P) {
return reinterpret_cast<LLVMTargetDataRef>(const_cast<TargetData*>(P));
}
+
+ inline TargetLibraryInfo *unwrap(LLVMTargetLibraryInfoRef P) {
+ return reinterpret_cast<TargetLibraryInfo*>(P);
+ }
+
+ inline LLVMTargetLibraryInfoRef wrap(const TargetLibraryInfo *P) {
+ TargetLibraryInfo *X = const_cast<TargetLibraryInfo*>(P);
+ return reinterpret_cast<LLVMTargetLibraryInfoRef>(X);
+ }
}
#endif /* defined(__cplusplus) */
diff --git a/include/llvm-c/Transforms/IPO.h b/include/llvm-c/Transforms/IPO.h
index 89b1298..710bebe 100644
--- a/include/llvm-c/Transforms/IPO.h
+++ b/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/include/llvm-c/Transforms/PassManagerBuilder.h b/include/llvm-c/Transforms/PassManagerBuilder.h
new file mode 100644
index 0000000..fa722c9
--- /dev/null
+++ b/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<PassManagerBuilder*>(P);
+ }
+
+ inline LLVMPassManagerBuilderRef wrap(PassManagerBuilder *P) {
+ return reinterpret_cast<LLVMPassManagerBuilderRef>(P);
+ }
+}
+#endif
+
+#endif
diff --git a/include/llvm-c/Transforms/Scalar.h b/include/llvm-c/Transforms/Scalar.h
index cf8d71f..6015ef9 100644
--- a/include/llvm-c/Transforms/Scalar.h
+++ b/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/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h
index e68e579..707e0db 100644
--- a/include/llvm/ADT/APInt.h
+++ b/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 <cassert>
#include <climits>
@@ -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<uint64_t> 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<uint64_t> bigVal);
+ /// Equivalent to APInt(numBits, ArrayRef<uint64_t>(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<char> &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<char> &Str, unsigned Radix = 10) const {
toString(Str, Radix, true, false);
}
diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h
index 6db866e..33a8c65 100644
--- a/include/llvm/ADT/ArrayRef.h
+++ b/include/llvm/ADT/ArrayRef.h
@@ -147,7 +147,53 @@ namespace llvm {
/// @}
};
-
+
+ /// @name ArrayRef Convenience constructors
+ /// @{
+
+ /// Construct an ArrayRef from a single element.
+ template<typename T>
+ ArrayRef<T> makeArrayRef(const T &OneElt) {
+ return OneElt;
+ }
+
+ /// Construct an ArrayRef from a pointer and length.
+ template<typename T>
+ ArrayRef<T> makeArrayRef(const T *data, size_t length) {
+ return ArrayRef<T>(data, length);
+ }
+
+ /// Construct an ArrayRef from a range.
+ template<typename T>
+ ArrayRef<T> makeArrayRef(const T *begin, const T *end) {
+ return ArrayRef<T>(begin, end);
+ }
+
+ /// Construct an ArrayRef from a SmallVector.
+ template <typename T>
+ ArrayRef<T> makeArrayRef(const SmallVectorImpl<T> &Vec) {
+ return Vec;
+ }
+
+ /// Construct an ArrayRef from a SmallVector.
+ template <typename T, unsigned N>
+ ArrayRef<T> makeArrayRef(const SmallVector<T, N> &Vec) {
+ return Vec;
+ }
+
+ /// Construct an ArrayRef from a std::vector.
+ template<typename T>
+ ArrayRef<T> makeArrayRef(const std::vector<T> &Vec) {
+ return Vec;
+ }
+
+ /// Construct an ArrayRef from a C array.
+ template<typename T, size_t N>
+ ArrayRef<T> makeArrayRef(const T (&Arr)[N]) {
+ return ArrayRef<T>(Arr);
+ }
+
+ /// @}
/// @name ArrayRef Comparison Operators
/// @{
diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h
index 0f1cfeb..e70cacf 100644
--- a/include/llvm/ADT/DenseMap.h
+++ b/include/llvm/ADT/DenseMap.h
@@ -540,6 +540,12 @@ private:
++Ptr;
}
};
+
+template<typename KeyT, typename ValueT, typename KeyInfoT, typename ValueInfoT>
+static inline size_t
+capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT, ValueInfoT> &X) {
+ return X.getMemorySize();
+}
} // end namespace llvm
diff --git a/include/llvm/ADT/DenseMapInfo.h b/include/llvm/ADT/DenseMapInfo.h
index 744b6f4..df4084e 100644
--- a/include/llvm/ADT/DenseMapInfo.h
+++ b/include/llvm/ADT/DenseMapInfo.h
@@ -51,7 +51,7 @@ struct DenseMapInfo<T*> {
template<> struct DenseMapInfo<char> {
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<char> {
template<> struct DenseMapInfo<unsigned> {
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<unsigned long long> {
template<> struct DenseMapInfo<int> {
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<long> {
}
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<long long> {
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<std::pair<T, U> > {
}
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<std::pair<T, U> > {
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/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h
index 67321f5..8ab9a33 100644
--- a/include/llvm/ADT/DenseSet.h
+++ b/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/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h
index d6cce7c..8346ffa 100644
--- a/include/llvm/ADT/ImmutableMap.h
+++ b/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<typename TreeTy::Factory *>(&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 <typename KeyT, typename ValT,
+typename ValInfo = ImutKeyValueInfo<KeyT,ValT> >
+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<ValInfo> 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<TreeTy*>(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<key_type, data_type>(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<KeyT, ValT> asImmutableMap() const {
+ return ImmutableMap<KeyT, ValT>(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 <key,value> 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/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h
index 3ca910c..d597a7c 100644
--- a/include/llvm/ADT/ImmutableSet.h
+++ b/include/llvm/ADT/ImmutableSet.h
@@ -997,6 +997,10 @@ public:
BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
+ typename TreeTy::Factory *getTreeFactory() const {
+ return const_cast<typename TreeTy::Factory *>(&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 <typename ValT, typename ValInfo = ImutContainerInfo<ValT> >
+class ImmutableSetRef {
+public:
+ typedef typename ValInfo::value_type value_type;
+ typedef typename ValInfo::value_type_ref value_type_ref;
+ typedef ImutAVLTree<ValInfo> 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<ValT> asImmutableSet(bool canonicalize = true) const {
+ return ImmutableSet<ValT>(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<ValT,ValInfo>;
+ public:
+ iterator() {}
+ inline value_type_ref operator*() const { return itr->getValue(); }
+ inline iterator& operator++() { ++itr; return *this; }
+ inline iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
+ inline iterator& operator--() { --itr; return *this; }
+ inline iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
+ inline bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
+ inline bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
+ inline value_type *operator->() const { return &(operator*()); }
+ };
+
+ 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/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h
index f28ebf3..1230e8f 100644
--- a/include/llvm/ADT/IntervalMap.h
+++ b/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/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h
index 13b98ce..487096a 100644
--- a/include/llvm/ADT/PointerUnion.h
+++ b/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<PT1>::getFromVoidPointer(Val.getPointer());
+ }
operator bool() const { return !isNull(); }
/// is<T>() return true if the Union currently holds the type matching T.
diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h
index e3b4994..63a2b52 100644
--- a/include/llvm/ADT/PostOrderIterator.h
+++ b/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<class SetType>
+struct DFSetTraits {
+ static void finishPostorder(
+ typename SetType::iterator::value_type, SetType &) {}
+};
+
template<class SetType>
class po_iterator_storage<SetType, true> {
public:
@@ -109,6 +117,8 @@ public:
inline NodeType *operator->() const { return operator*(); }
inline _Self& operator++() { // Preincrement
+ DFSetTraits<SetType>::finishPostorder(VisitStack.back().first,
+ this->Visited);
VisitStack.pop_back();
if (!VisitStack.empty())
traverseChild();
diff --git a/include/llvm/ADT/SCCIterator.h b/include/llvm/ADT/SCCIterator.h
index 3e93cfe..48436c6 100644
--- a/include/llvm/ADT/SCCIterator.h
+++ b/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/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h
index 0b0346b..5da906d 100644
--- a/include/llvm/ADT/STLExtras.h
+++ b/include/llvm/ADT/STLExtras.h
@@ -186,25 +186,21 @@ inline ItTy prior(ItTy it)
// // do stuff
// else
// // do other stuff
-
-namespace
-{
- template <typename T1, typename T2>
- 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<T1, T2>& p) {
- first = p.first;
- second = p.second;
- return *this;
- }
- };
-}
+template <typename T1, typename T2>
+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<T1, T2>& p) {
+ first = p.first;
+ second = p.second;
+ return *this;
+ }
+};
template <typename T1, typename T2>
inline tier<T1, T2> tie(T1& f, T2& s) {
diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h
index 5f0a55b..1c42f29 100644
--- a/include/llvm/ADT/SmallVector.h
+++ b/include/llvm/ADT/SmallVector.h
@@ -78,21 +78,21 @@ protected:
return BeginX == static_cast<const void*>(&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<typename T, unsigned N>
+static inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
+ return X.capacity_in_bytes();
+}
+
} // End llvm namespace
namespace std {
diff --git a/include/llvm/ADT/Statistic.h b/include/llvm/ADT/Statistic.h
index fda99c6..b8a1a2f 100644
--- a/include/llvm/ADT/Statistic.h
+++ b/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/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h
index 5f5c041..d01d3e1 100644
--- a/include/llvm/ADT/StringExtras.h
+++ b/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 <cctype>
#include <cstdio>
diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h
new file mode 100644
index 0000000..ee86d8b
--- /dev/null
+++ b/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 <typename EltTy>
+class TinyPtrVector {
+public:
+ typedef llvm::SmallVector<EltTy, 4> VecTy;
+ llvm::PointerUnion<EltTy, VecTy*> Val;
+
+ TinyPtrVector() {}
+ TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
+ if (VecTy *V = Val.template dyn_cast<VecTy*>())
+ Val = new VecTy(*V);
+ }
+ ~TinyPtrVector() {
+ if (VecTy *V = Val.template dyn_cast<VecTy*>())
+ 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<VecTy*>())
+ return Vec->empty();
+ return false;
+ }
+
+ unsigned size() const {
+ if (empty())
+ return 0;
+ if (Val.template is<EltTy>())
+ return 1;
+ return Val.template get<VecTy*>()->size();
+ }
+
+ typedef const EltTy *iterator;
+ iterator begin() const {
+ if (empty())
+ return 0;
+
+ if (Val.template is<EltTy>())
+ return Val.template getAddrOf<EltTy>();
+
+ return Val.template get<VecTy *>()->begin();
+
+ }
+ iterator end() const {
+ if (empty())
+ return 0;
+
+ if (Val.template is<EltTy>())
+ return begin() + 1;
+
+ return Val.template get<VecTy *>()->end();
+ }
+
+
+ EltTy operator[](unsigned i) const {
+ assert(!Val.isNull() && "can't index into an empty vector");
+ if (EltTy V = Val.template dyn_cast<EltTy>()) {
+ assert(i == 0 && "tinyvector index out of range");
+ return V;
+ }
+
+ assert(i < Val.template get<VecTy*>()->size() &&
+ "tinyvector index out of range");
+ return (*Val.template get<VecTy*>())[i];
+ }
+
+ EltTy front() const {
+ assert(!empty() && "vector empty");
+ if (EltTy V = Val.template dyn_cast<EltTy>())
+ return V;
+ return Val.template get<VecTy*>()->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<EltTy>()) {
+ Val = new VecTy();
+ Val.template get<VecTy*>()->push_back(V);
+ }
+
+ // Add the new value, we know we have a vector.
+ Val.template get<VecTy*>()->push_back(NewVal);
+ }
+
+ void clear() {
+ // If we have a single value, convert to empty.
+ if (Val.template is<EltTy>()) {
+ Val = (EltTy)0;
+ } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
+ // 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/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index fd23608..3503c0f 100644
--- a/include/llvm/ADT/Triple.h
+++ b/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 <string>
+#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/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h
index ab8d365..3a60cab 100644
--- a/include/llvm/ADT/Twine.h
+++ b/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<const Twine*>(LHS)->isBinary())
+ !LHS.twine->isBinary())
return false;
if (getRHSKind() == TwineKind &&
- !static_cast<const Twine*>(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<char>(Val);
+ }
+
+ /// Construct from an unsigned char.
+ explicit Twine(unsigned char Val)
+ : LHSKind(CharKind), RHSKind(EmptyKind) {
+ LHS.character = static_cast<char>(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/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h
index 5d8edd1..d71ba20 100644
--- a/include/llvm/Analysis/AliasAnalysis.h
+++ b/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/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h
index 03149c6..c4ebe40 100644
--- a/include/llvm/Analysis/AliasSetTracker.h
+++ b/include/llvm/Analysis/AliasSetTracker.h
@@ -111,8 +111,8 @@ class AliasSet : public ilist_node<AliasSet> {
AliasSet *Forward; // Forwarding pointer.
AliasSet *Next, *Prev; // Doubly linked list of AliasSets.
- // All calls & invokes in this alias set.
- std::vector<AssertingVH<Instruction> > CallSites;
+ // All instructions without a specific address in this alias set.
+ std::vector<AssertingVH<Instruction> > 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<AliasSet> {
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/include/llvm/Analysis/BlockFrequency.h b/include/llvm/Analysis/BlockFrequency.h
deleted file mode 100644
index c4b1e08..0000000
--- a/include/llvm/Analysis/BlockFrequency.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//========-------- BlockFrequency.h - 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.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_BLOCKFREQUENCY_H
-#define LLVM_ANALYSIS_BLOCKFREQUENCY_H
-
-#include "llvm/Pass.h"
-#include <climits>
-
-namespace llvm {
-
-class BranchProbabilityInfo;
-template<class BlockT, class FunctionT, class BranchProbInfoT>
-class BlockFrequencyImpl;
-
-/// BlockFrequency pass uses BlockFrequencyImpl implementation to estimate
-/// IR basic block frequencies.
-class BlockFrequency : public FunctionPass {
-
- BlockFrequencyImpl<BasicBlock, Function, BranchProbabilityInfo> *BFI;
-
-public:
- static char ID;
-
- BlockFrequency();
-
- ~BlockFrequency();
-
- void getAnalysisUsage(AnalysisUsage &AU) const;
-
- bool runOnFunction(Function &F);
-
- /// 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 the floating
- /// points.
- uint32_t getBlockFreq(BasicBlock *BB);
-};
-
-}
-
-#endif
diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h
index 6580fd1..0fb2bd7 100644
--- a/include/llvm/Analysis/BlockFrequencyImpl.h
+++ b/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 BlockT, class FunctionT, class BlockProbInfoT>
class BlockFrequencyImpl {
- DenseMap<BlockT *, uint32_t> Freqs;
+ DenseMap<BlockT *, BlockFrequency> Freqs;
BlockProbInfoT *BPI;
@@ -48,7 +49,7 @@ class BlockFrequencyImpl {
typedef GraphTraits< Inverse<BlockT *> > 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<BlockT *, 8> 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<BlockT *, uint32_t>::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<BlockT *, BlockFrequency>::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/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h
new file mode 100644
index 0000000..9e698a9
--- /dev/null
+++ b/include/llvm/Analysis/BlockFrequencyInfo.h
@@ -0,0 +1,55 @@
+//========-------- BlockFrequencyInfo.h - 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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
+#define LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
+
+#include "llvm/Pass.h"
+#include "llvm/Support/BlockFrequency.h"
+#include <climits>
+
+namespace llvm {
+
+class BranchProbabilityInfo;
+template<class BlockT, class FunctionT, class BranchProbInfoT>
+class BlockFrequencyImpl;
+
+/// BlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate
+/// IR basic block frequencies.
+class BlockFrequencyInfo : public FunctionPass {
+
+ BlockFrequencyImpl<BasicBlock, Function, BranchProbabilityInfo> *BFI;
+
+public:
+ static char ID;
+
+ BlockFrequencyInfo();
+
+ ~BlockFrequencyInfo();
+
+ void getAnalysisUsage(AnalysisUsage &AU) const;
+
+ bool runOnFunction(Function &F);
+ void print(raw_ostream &O, const Module *M) const;
+
+ /// getblockFreq - Return block frequency. Return 0 if we don't have the
+ /// information. Please note that initial frequency is equal to 1024. It means
+ /// that we should not rely on the value itself, but only on the comparison to
+ /// the other block frequencies. We do this to avoid using of floating points.
+ ///
+ BlockFrequency getBlockFreq(BasicBlock *BB) const;
+};
+
+}
+
+#endif
diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h
index 02ead98..a2c12ab 100644
--- a/include/llvm/Analysis/BranchProbabilityInfo.h
+++ b/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<BasicBlock *, BasicBlock *> Edge;
+ typedef std::pair<const BasicBlock *, const BasicBlock *> Edge;
DenseMap<Edge, uint32_t> 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/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h
index 75edfbb..d96dd82 100644
--- a/include/llvm/Analysis/CodeMetrics.h
+++ b/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/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h
index f6b1f5a..05018fa 100644
--- a/include/llvm/Analysis/ConstantFolding.h
+++ b/include/llvm/Analysis/ConstantFolding.h
@@ -27,6 +27,8 @@ namespace llvm {
class TargetData;
class Function;
class Type;
+ template<typename T>
+ 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<Constant *> 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<unsigned> 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<Constant *> Operands);
}
#endif
diff --git a/include/llvm/Analysis/DIBuilder.h b/include/llvm/Analysis/DIBuilder.h
index a706cc8..ee24226 100644
--- a/include/llvm/Analysis/DIBuilder.h
+++ b/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<Value *, 4> AllEnumTypes;
+ SmallVector<Value *, 4> AllRetainTypes;
+ SmallVector<Value *, 4> AllSubprograms;
+ SmallVector<Value *, 4> 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/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h
index fbee5a6..9a53c4d 100644
--- a/include/llvm/Analysis/DebugInfo.h
+++ b/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<DICompileUnit>(3); }
+ DICompileUnit getCompileUnit() const{
+ assert (getVersion() <= LLVMDebugVersion10 && "Invalid CompileUnit!");
+ return getFieldAs<DICompileUnit>(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<DIScope>(1); }
StringRef getName() const { return getStringField(2); }
DICompileUnit getCompileUnit() const{
+ assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!");
if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(3);
@@ -291,6 +303,9 @@ namespace llvm {
return getFieldAs<DIFile>(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<DICompileUnit>(6);
@@ -545,6 +561,8 @@ namespace llvm {
DISubprogram getFunctionDeclaration() const {
return getFieldAs<DISubprogram>(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<DICompileUnit>(6);
DIFile F = getFieldAs<DIFile>(6);
return F.getCompileUnit();
}
+ StringRef getFilename() const {
+ if (getVersion() <= llvm::LLVMDebugVersion10)
+ return getContext().getFilename();
+ return getFieldAs<DIFile>(6).getFilename();
+ }
+ StringRef getDirectory() const {
+ if (getVersion() <= llvm::LLVMDebugVersion10)
+ return getContext().getDirectory();
+ return getFieldAs<DIFile>(6).getDirectory();
+
+ }
unsigned getLineNumber() const { return getUnsignedField(7); }
DIType getType() const { return getFieldAs<DIType>(8); }
@@ -592,6 +622,7 @@ namespace llvm {
DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getName() const { return getStringField(2); }
DICompileUnit getCompileUnit() const{
+ assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!");
if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(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<DIFile>(2).getDirectory();
+ return !dir.empty() ? dir : getContext().getDirectory();
+ }
+ StringRef getFilename() const {
+ StringRef filename = getFieldAs<DIFile>(2).getFilename();
+ assert(!filename.empty() && "Why'd you create this then?");
+ return filename;
+ }
+ DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(1); }
+ };
+
/// DINameSpace - A wrapper for a C++ style name space.
class DINameSpace : public DIScope {
public:
@@ -678,6 +735,7 @@ namespace llvm {
return getFieldAs<DIFile>(3).getFilename();
}
DICompileUnit getCompileUnit() const{
+ assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!");
if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(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/include/llvm/Analysis/FindUsedTypes.h b/include/llvm/Analysis/FindUsedTypes.h
index 3e5da57..b22cb88 100644
--- a/include/llvm/Analysis/FindUsedTypes.h
+++ b/include/llvm/Analysis/FindUsedTypes.h
@@ -23,7 +23,7 @@ class Type;
class Value;
class FindUsedTypes : public ModulePass {
- SetVector<const Type *> UsedTypes;
+ SetVector<Type *> 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<const Type *> &getTypes() const { return UsedTypes; }
+ const SetVector<Type *> &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/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h
index e56d24d..2fb607c 100644
--- a/include/llvm/Analysis/IVUsers.h
+++ b/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/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h
index a0cce51..36a16e6 100644
--- a/include/llvm/Analysis/InlineCost.h
+++ b/include/llvm/Analysis/InlineCost.h
@@ -29,6 +29,7 @@ namespace llvm {
class CallSite;
template<class PtrType, unsigned SmallSize>
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<const Function *, FunctionInfo> 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/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h
index bc6e55f..c1d87d3 100644
--- a/include/llvm/Analysis/InstructionSimplify.h
+++ b/include/llvm/Analysis/InstructionSimplify.h
@@ -24,6 +24,8 @@ namespace llvm {
class Instruction;
class Value;
class TargetData;
+ template<typename T>
+ 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<Value *> 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<unsigned> Idxs,
+ const TargetData *TD = 0,
+ const DominatorTree *DT = 0);
+
//=== Helper functions for higher up the class hierarchy.
diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h
index 392bdad..12cb6c5 100644
--- a/include/llvm/Analysis/LoopInfo.h
+++ b/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<const LoopT*> *Loops) const {
+ Loops->insert(static_cast<const LoopT *>(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<BasicBlock, Loop>;
explicit Loop(BasicBlock *BB) : LoopBase<BasicBlock, Loop>(BB) {}
@@ -635,13 +642,14 @@ class LoopInfoBase {
DenseMap<BlockT *, LoopT *> BBMap;
std::vector<LoopT *> TopLevelLoops;
friend class LoopBase<BlockT, LoopT>;
+ 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<LoopT *>::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<BlockT*>(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<BlockT *, LoopT *>::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<BlockT> &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<BlockT> &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<Inverse<BlockT*> > 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/include/llvm/Analysis/LoopIterator.h b/include/llvm/Analysis/LoopIterator.h
new file mode 100644
index 0000000..269ac80
--- /dev/null
+++ b/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<BasicBlock*>::const_iterator POIterator;
+ typedef std::vector<BasicBlock*>::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<BasicBlock*, unsigned> PostNumbers;
+ std::vector<BasicBlock*> 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<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
+ return I != PostNumbers.end() && I->second;
+ }
+
+ /// Get a block's postorder number.
+ unsigned getPostorder(BasicBlock *BB) const {
+ DenseMap<BasicBlock*, unsigned>::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<BasicBlock*, LoopBlocksTraversal, true> 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<LoopBlocksTraversal> {
+ static void finishPostorder(BasicBlock *BB, LoopBlocksTraversal& LBT) {
+ LBT.finishPostorder(BB);
+ }
+};
+
+} // End namespace llvm
+
+#endif
diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h
index 1603d2e..e6ed9bc 100644
--- a/include/llvm/Analysis/LoopPass.h
+++ b/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/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h
index 22493f6..865d236 100644
--- a/include/llvm/Analysis/MemoryBuiltins.h
+++ b/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/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h
index 34860e7..e18d937 100644
--- a/include/llvm/Analysis/MemoryDependenceAnalysis.h
+++ b/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<Instruction*, 2, DepType> 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<Instruction*>(NonLocal), Other));
+ }
+ static MemDepResult getNonFuncLocal() {
+ return MemDepResult(
+ PairTy(reinterpret_cast<Instruction*>(NonFuncLocal), Other));
}
static MemDepResult getUnknown() {
- return MemDepResult(PairTy(0, Clobber));
+ return MemDepResult(
+ PairTy(reinterpret_cast<Instruction*>(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<Instruction*>(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<Instruction*>(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<Instruction*>(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/include/llvm/Analysis/RegionPass.h b/include/llvm/Analysis/RegionPass.h
index 1a93859..68f1201 100644
--- a/include/llvm/Analysis/RegionPass.h
+++ b/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/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h
index 554524a..10d933e 100644
--- a/include/llvm/Analysis/ScalarEvolution.h
+++ b/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<SCEVCouldNotCompute>(Exact) ||
+ !isa<SCEVCouldNotCompute>(Max);
+ }
+ };
+
+ /// ExitNotTakenInfo - Information about the number of times a particular
+ /// loop exit may be reached before exiting the loop.
+ struct ExitNotTakenInfo {
+ AssertingVH<BasicBlock> ExitingBlock;
+ const SCEV *ExactNotTaken;
+ PointerIntPair<ExitNotTakenInfo*, 1> 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<BasicBlock *, const SCEV *> > &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<SCEVCouldNotCompute>(Exact) ||
- !isa<SCEVCouldNotCompute>(Max);
+ return ExitNotTaken.ExitingBlock || !isa<SCEVCouldNotCompute>(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<const SCEV *> &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<const SCEV *, 3> 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/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h
index a8c03b2..a4ad145 100644
--- a/include/llvm/Analysis/ScalarEvolutionExpander.h
+++ b/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<true, TargetFolder> BuilderType;
BuilderType Builder;
+#ifndef NDEBUG
+ const char *DebugType;
+#endif
+
friend struct SCEVVisitor<SCEVExpander, Value*>;
public:
/// SCEVExpander - Construct a SCEVExpander in "canonical" mode.
explicit SCEVExpander(ScalarEvolution &se, const char *name)
: SE(se), IVName(name), IVIncInsertLoop(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<WeakVH> &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/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h
index 856d92c..b6f0ae5 100644
--- a/include/llvm/Analysis/ScalarEvolutionExpressions.h
+++ b/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/include/llvm/Argument.h b/include/llvm/Argument.h
index ff86378..cd74882 100644
--- a/include/llvm/Argument.h
+++ b/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/include/llvm/Attributes.h b/include/llvm/Attributes.h
index 233eab8..2d7b33b 100644
--- a/include/llvm/Attributes.h
+++ b/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/include/llvm/AutoUpgrade.h b/include/llvm/AutoUpgrade.h
index 5ce20b6..8ca3548 100644
--- a/include/llvm/AutoUpgrade.h
+++ b/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/include/llvm/BasicBlock.h b/include/llvm/BasicBlock.h
index 3b953c0..1cd8dc5 100644
--- a/include/llvm/BasicBlock.h
+++ b/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<BasicBlock*>(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<BasicBlock*>(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/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index df68bd5..4b0dcc3 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/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/include/llvm/CMakeLists.txt b/include/llvm/CMakeLists.txt
index 0c3ca1c..7956f8c 100644
--- a/include/llvm/CMakeLists.txt
+++ b/include/llvm/CMakeLists.txt
@@ -1,6 +1,6 @@
set(LLVM_TARGET_DEFINITIONS Intrinsics.td)
-tablegen(Intrinsics.gen -gen-intrinsic)
+llvm_tablegen(Intrinsics.gen -gen-intrinsic)
add_custom_target(intrinsics_gen ALL
DEPENDS ${llvm_builded_incs_dir}/Intrinsics.gen)
diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h
index f8a7029..d8e6407 100644
--- a/include/llvm/CodeGen/Analysis.h
+++ b/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<unsigned> 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<EVT> &ValueVTs,
SmallVectorImpl<uint64_t> *Offsets = 0,
uint64_t StartingOffset = 0);
diff --git a/include/llvm/CodeGen/CalcSpillWeights.h b/include/llvm/CodeGen/CalcSpillWeights.h
index 60edcc5..2f76a6c 100644
--- a/include/llvm/CodeGen/CalcSpillWeights.h
+++ b/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/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h
index 962a4e2..18202d9 100644
--- a/include/llvm/CodeGen/FastISel.h
+++ b/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/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h
index 84bbf48..09dac85 100644
--- a/include/llvm/CodeGen/FunctionLoweringInfo.h
+++ b/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/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h
index 459cecd..184e96d 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/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/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h
new file mode 100644
index 0000000..0271c5d
--- /dev/null
+++ b/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 <utility>
+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<const MachineInstr *, const MachineInstr *> 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<const MachineBasicBlock*, 4> &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<LexicalScope *> 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<InsnRange> &MIRanges,
+ DenseMap<const MachineInstr *, LexicalScope *> &M);
+ void constructScopeNest(LexicalScope *Scope);
+ void assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges,
+ DenseMap<const MachineInstr *, LexicalScope *> &M);
+
+private:
+ const MachineFunction *MF;
+
+ /// LexicalScopeMap - Tracks the scopes in the current function. Owns the
+ /// contained LexicalScope*s.
+ DenseMap<const MDNode *, LexicalScope *> LexicalScopeMap;
+
+ /// InlinedLexicalScopeMap - Tracks inlined function scopes in current function.
+ DenseMap<DebugLoc, LexicalScope *> InlinedLexicalScopeMap;
+
+ /// AbstractScopeMap - These scopes are not included LexicalScopeMap.
+ /// AbstractScopes owns its LexicalScope*s.
+ DenseMap<const MDNode *, LexicalScope *> AbstractScopeMap;
+
+ /// AbstractScopesList - Tracks abstract scopes constructed while processing
+ /// a function.
+ SmallVector<LexicalScope *, 4>AbstractScopesList;
+
+ /// 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<LexicalScope *, 4> &getChildren() { return Children; }
+ SmallVector<InsnRange, 4> &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<const MDNode> Desc; // Debug info descriptor.
+ AssertingVH<const MDNode> InlinedAtLocation; // Location at which this
+ // scope is inlined.
+ bool AbstractScope; // Abstract Scope
+ SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope.
+ // Contents not owned.
+ SmallVector<InsnRange, 4> Ranges;
+
+ const MachineInstr *LastInsn; // Last instruction of this scope.
+ const MachineInstr *FirstInsn; // First instruction of this scope.
+ unsigned DFSIn, DFSOut; // In & Out Depth use to determine
+ // scope nesting.
+ mutable unsigned IndentLevel; // Private state for dump()
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h
index 5fd4d3d..2288c1a 100644
--- a/include/llvm/CodeGen/LiveInterval.h
+++ b/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/include/llvm/CodeGen/LiveStackAnalysis.h b/include/llvm/CodeGen/LiveStackAnalysis.h
index 8a8dcaf..86c4d7c 100644
--- a/include/llvm/CodeGen/LiveStackAnalysis.h
+++ b/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/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h
index f9b81b1..7ba901f 100644
--- a/include/llvm/CodeGen/LiveVariables.h
+++ b/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/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h
index 397e59e..5a20e95 100644
--- a/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/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/include/llvm/CodeGen/MachineBlockFrequency.h b/include/llvm/CodeGen/MachineBlockFrequency.h
deleted file mode 100644
index 25bf1f0..0000000
--- a/include/llvm/CodeGen/MachineBlockFrequency.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//====----- MachineBlockFrequency.h - MachineBlock 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.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CODEGEN_MACHINEBLOCKFREQUENCY_H
-#define LLVM_CODEGEN_MACHINEBLOCKFREQUENCY_H
-
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include <climits>
-
-namespace llvm {
-
-class MachineBranchProbabilityInfo;
-template<class BlockT, class FunctionT, class BranchProbInfoT>
-class BlockFrequencyImpl;
-
-/// MachineBlockFrequency pass uses BlockFrequencyImpl implementation to estimate
-/// machine basic block frequencies.
-class MachineBlockFrequency : public MachineFunctionPass {
-
- BlockFrequencyImpl<MachineBasicBlock, MachineFunction, MachineBranchProbabilityInfo> *MBFI;
-
-public:
- static char ID;
-
- MachineBlockFrequency();
-
- ~MachineBlockFrequency();
-
- 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
- /// 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);
-};
-
-}
-
-#endif
diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
new file mode 100644
index 0000000..416d40b
--- /dev/null
+++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
@@ -0,0 +1,54 @@
+//====----- MachineBlockFrequencyInfo.h - MachineBlock 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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
+#define LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
+
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/Support/BlockFrequency.h"
+#include <climits>
+
+namespace llvm {
+
+class MachineBranchProbabilityInfo;
+template<class BlockT, class FunctionT, class BranchProbInfoT>
+class BlockFrequencyImpl;
+
+/// MachineBlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate
+/// machine basic block frequencies.
+class MachineBlockFrequencyInfo : public MachineFunctionPass {
+
+ BlockFrequencyImpl<MachineBasicBlock, MachineFunction, MachineBranchProbabilityInfo> *MBFI;
+
+public:
+ static char ID;
+
+ MachineBlockFrequencyInfo();
+
+ ~MachineBlockFrequencyInfo();
+
+ void getAnalysisUsage(AnalysisUsage &AU) const;
+
+ bool runOnMachineFunction(MachineFunction &F);
+
+ /// 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 getBlockFreq(MachineBasicBlock *MBB) const;
+};
+
+}
+
+#endif
diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h
index beb16a2..29f4f44 100644
--- a/include/llvm/CodeGen/MachineConstantPool.h
+++ b/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/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h
index 4ea6aa3..b347ca8 100644
--- a/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/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/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h
index 5b3d3ea..cae38f3 100644
--- a/include/llvm/CodeGen/MachineInstr.h
+++ b/include/llvm/CodeGen/MachineInstr.h
@@ -32,6 +32,7 @@ namespace llvm {
template <typename T> 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/include/llvm/CodeGen/MachineLocation.h b/include/llvm/CodeGen/MachineLocation.h
deleted file mode 100644
index 21951b6..0000000
--- a/include/llvm/CodeGen/MachineLocation.h
+++ /dev/null
@@ -1,98 +0,0 @@
-//===-- llvm/CodeGen/MachineLocation.h --------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// The MachineLocation class is used to represent a simple location in a machine
-// frame. Locations will be one of two forms; a register or an address formed
-// from a base address plus an offset. Register indirection can be specified by
-// using an offset of zero.
-//
-// The MachineMove class is used to represent abstract move operations in the
-// prolog/epilog of a compiled function. A collection of these objects can be
-// used by a debug consumer to track the location of values when unwinding stack
-// frames.
-//===----------------------------------------------------------------------===//
-
-
-#ifndef LLVM_CODEGEN_MACHINELOCATION_H
-#define LLVM_CODEGEN_MACHINELOCATION_H
-
-namespace llvm {
- class MCSymbol;
-
-class MachineLocation {
-private:
- bool IsRegister; // True if location is a register.
- unsigned Register; // gcc/gdb register number.
- int Offset; // Displacement if not register.
-public:
- enum {
- // The target register number for an abstract frame pointer. The value is
- // an arbitrary value that doesn't collide with any real target register.
- VirtualFP = ~0U
- };
- MachineLocation()
- : IsRegister(false), Register(0), Offset(0) {}
- explicit MachineLocation(unsigned R)
- : IsRegister(true), Register(R), Offset(0) {}
- MachineLocation(unsigned R, int O)
- : IsRegister(false), Register(R), Offset(O) {}
-
- bool operator==(const MachineLocation &Other) const {
- return IsRegister == Other.IsRegister && Register == Other.Register &&
- Offset == Other.Offset;
- }
-
- // Accessors
- bool isReg() const { return IsRegister; }
- unsigned getReg() const { return Register; }
- int getOffset() const { return Offset; }
- void setIsRegister(bool Is) { IsRegister = Is; }
- void setRegister(unsigned R) { Register = R; }
- void setOffset(int O) { Offset = O; }
- void set(unsigned R) {
- IsRegister = true;
- Register = R;
- Offset = 0;
- }
- void set(unsigned R, int O) {
- IsRegister = false;
- Register = R;
- Offset = O;
- }
-
-#ifndef NDEBUG
- void dump();
-#endif
-};
-
-/// MachineMove - This class represents the save or restore of a callee saved
-/// register that exception or debug info needs to know about.
-class MachineMove {
-private:
- /// Label - Symbol for post-instruction address when result of move takes
- /// effect.
- MCSymbol *Label;
-
- // Move to & from location.
- MachineLocation Destination, Source;
-public:
- MachineMove() : Label(0) {}
-
- MachineMove(MCSymbol *label, const MachineLocation &D,
- const MachineLocation &S)
- : Label(label), Destination(D), Source(S) {}
-
- // Accessors
- MCSymbol *getLabel() const { return Label; }
- const MachineLocation &getDestination() const { return Destination; }
- const MachineLocation &getSource() const { return Source; }
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h
index fa185c4..2bf7f17 100644
--- a/include/llvm/CodeGen/MachineModuleInfo.h
+++ b/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<MachineMove> 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<LandingPadInfo> 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<MCSymbol*, SmallVector<unsigned, 4> > LPadToCallSiteMap;
+
+ /// CallSiteMap - Map of invoke call site index values to associated begin
+ /// EH_LABEL for the current function.
DenseMap<MCSymbol*, unsigned> 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<const GlobalVariable *> 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<unsigned> 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<unsigned> 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<const Function *> 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<const Function *, 32> 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<MachineMove> &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<const GlobalVariable *> &TyInfo);
+ ArrayRef<const GlobalVariable *> TyInfo);
/// addFilterTypeInfo - Provide the filter typeinfo for a landing pad.
///
void addFilterTypeInfo(MachineBasicBlock *LandingPad,
- std::vector<const GlobalVariable *> &TyInfo);
+ ArrayRef<const GlobalVariable *> 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<unsigned> Sites);
+
+ /// getCallSiteLandingPad - Get the call site indexes for a landing pad EH
+ /// symbol.
+ SmallVectorImpl<unsigned> &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/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h
index fdef574..5440a63 100644
--- a/include/llvm/CodeGen/MachineOperand.h
+++ b/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 <undef> 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<def> = XOR %vreg2<undef>, %vreg2<undef>
+ ///
+ /// 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 <undef> flag set doesn't read its
+ /// register. A sub-register def implicitly reads the other parts of the
+ /// register being redefined unless the <undef> 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/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h
index 1079726..3866b26 100644
--- a/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/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/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h
index e7928cb..7a03ce9 100644
--- a/include/llvm/CodeGen/Passes.h
+++ b/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/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index 3ec5ada..132983c 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/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/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index a5c4201..6c7be69 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/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/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h
index 6eb3180..2d98864 100644
--- a/include/llvm/CodeGen/SlotIndexes.h
+++ b/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/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 711280e..ca40ccf 100644
--- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/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/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h
index 424721b..cae0bcb 100644
--- a/include/llvm/CodeGen/ValueTypes.h
+++ b/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/include/llvm/CompilerDriver/Action.h b/include/llvm/CompilerDriver/Action.h
deleted file mode 100644
index f2b7965..0000000
--- a/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 <string>
-#include <vector>
-
-namespace llvmc {
-
- typedef std::vector<std::string> 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<std::string> 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/include/llvm/CompilerDriver/AutoGenerated.h b/include/llvm/CompilerDriver/AutoGenerated.h
deleted file mode 100644
index 7b926c6..0000000
--- a/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/include/llvm/CompilerDriver/BuiltinOptions.h b/include/llvm/CompilerDriver/BuiltinOptions.h
deleted file mode 100644
index 7b9c15c..0000000
--- a/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 <string>
-
-namespace llvmc {
-
-namespace SaveTempsEnum { enum Values { Cwd, Obj, Unset }; }
-
-extern llvm::cl::list<std::string> InputFilenames;
-extern llvm::cl::opt<std::string> OutputFilename;
-extern llvm::cl::opt<std::string> TempDirname;
-extern llvm::cl::list<std::string> Languages;
-extern llvm::cl::opt<bool> DryRun;
-extern llvm::cl::opt<bool> Time;
-extern llvm::cl::opt<bool> VerboseMode;
-extern llvm::cl::opt<bool> CheckGraph;
-extern llvm::cl::opt<bool> ViewGraph;
-extern llvm::cl::opt<bool> WriteGraph;
-extern llvm::cl::opt<SaveTempsEnum::Values> SaveTemps;
-
-} // End namespace llvmc.
-
-#endif // LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H
diff --git a/include/llvm/CompilerDriver/Common.td b/include/llvm/CompilerDriver/Common.td
deleted file mode 100644
index 6ba30aa..0000000
--- a/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<list<dag> l> {
- list<dag> 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 val> {
- 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<list<dag> l> {
- list<dag> options = l;
-}
-
-// Option preprocessor - actions taken during plugin loading.
-class OptionPreprocessor<dag d> {
- dag preprocessor = d;
-}
-
-// Map from suffixes to language names
-
-def lang_to_suffixes;
-
-class LanguageMap<list<dag> l> {
- list<dag> map = l;
-}
-
-// Compilation graph
-
-def edge;
-def optional_edge;
-
-class CompilationGraph<list<dag> l> {
- list<dag> edges = l;
-}
diff --git a/include/llvm/CompilerDriver/CompilationGraph.h b/include/llvm/CompilerDriver/CompilationGraph.h
deleted file mode 100644
index 951aff6..0000000
--- a/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 <cassert>
-#include <string>
-
-namespace llvmc {
-
- class CompilationGraph;
- typedef llvm::StringSet<> InputLanguagesSet;
-
- /// LanguageMap - Maps from extensions to language names.
- class LanguageMap : public llvm::StringMap<std::string> {
- 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<llvm::IntrusiveRefCntPtr<Edge>, 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<Tool> 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<Node> 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<llvm::IntrusiveRefCntPtr<Edge>, 3> tools_vector_type;
- typedef llvm::StringMap<tools_vector_type> 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<const Node*>& Out);
- /// TopologicalSortFilterJoinNodes - Call TopologicalSort and filter the
- /// resulting list to include only Join nodes. Returns non-zero value on
- /// error.
- int TopologicalSortFilterJoinNodes(std::vector<const Node*>& 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<std::bidirectional_iterator_tag, Node, ptrdiff_t> {
- 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<llvmc::CompilationGraph*> {
- 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/include/llvm/CompilerDriver/Error.h b/include/llvm/CompilerDriver/Error.h
deleted file mode 100644
index 013094e..0000000
--- a/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/include/llvm/CompilerDriver/Main.h b/include/llvm/CompilerDriver/Main.h
deleted file mode 100644
index d136a5d..0000000
--- a/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/include/llvm/CompilerDriver/Main.inc b/include/llvm/CompilerDriver/Main.inc
deleted file mode 100644
index 4164043..0000000
--- a/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/include/llvm/CompilerDriver/Tool.h b/include/llvm/CompilerDriver/Tool.h
deleted file mode 100644
index 18a2b76..0000000
--- a/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 <string>
-#include <vector>
-#include <utility>
-
-namespace llvmc {
-
- class LanguageMap;
- typedef std::vector<std::pair<unsigned, std::string> > ArgsVector;
- typedef std::vector<llvm::sys::Path> PathVector;
- typedef std::vector<std::string> 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/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake
index 0b8a0ad..e44d429 100644
--- a/include/llvm/Config/config.h.cmake
+++ b/include/llvm/Config/config.h.cmake
@@ -5,6 +5,27 @@
#ifndef CONFIG_H
#define CONFIG_H
+/* Bug report URL. */
+#define BUG_REPORT_URL "${BUG_REPORT_URL}"
+
+/* Relative directory for resource files */
+#define CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}"
+
+/* 32 bit multilib directory. */
+#define CXX_INCLUDE_32BIT_DIR "${CXX_INCLUDE_32BIT_DIR}"
+
+/* 64 bit multilib directory. */
+#define CXX_INCLUDE_64BIT_DIR "${CXX_INCLUDE_64BIT_DIR}"
+
+/* Arch the libstdc++ headers. */
+#define CXX_INCLUDE_ARCH "${CXX_INCLUDE_ARCH}"
+
+/* Directory with the libstdc++ headers. */
+#define CXX_INCLUDE_ROOT "${CXX_INCLUDE_ROOT}"
+
+/* Directories clang will search for headers */
+#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}"
+
/* Define if CBE is enabled for printf %a output */
#cmakedefine ENABLE_CBE_PRINTF_A ${ENABLE_CBE_PRINTF_A}
@@ -196,9 +217,6 @@
/* Define to 1 if you have the `udis86' library (-ludis86). */
#undef HAVE_LIBUDIS86
-/* Type of 1st arg on ELM Callback */
-#cmakedefine WIN32_ELMCB_PCSTR ${WIN32_ELMCB_PCSTR}
-
/* Define to 1 if you have the <limits.h> header file. */
#cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H}
@@ -437,6 +455,12 @@
/* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H}
+/* Define if the neat program is available */
+#cmakedefine HAVE_TWOPI ${HAVE_TWOPI}
+
+/* Define to 1 if the system has the type `uint64_t'. */
+#cmakedefine HAVE_UINT64_T ${HAVE_UINT64_T}
+
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H}
@@ -513,41 +537,44 @@
#undef HOST_LINK_VERSION
/* Installation directory for binary executables */
-#undef LLVM_BINDIR
+#cmakedefine LLVM_BINDIR "${LLVM_BINDIR}"
/* Time at which LLVM was configured */
-#undef LLVM_CONFIGTIME
+#cmakedefine LLVM_CONFIGTIME "${LLVM_CONFIGTIME}"
-/* Installation directory for documentation */
-#undef LLVM_DATADIR
+/* Installation directory for data files */
+#cmakedefine LLVM_DATADIR "${LLVM_DATADIR}"
/* Installation directory for documentation */
-#undef LLVM_DOCSDIR
+#cmakedefine LLVM_DOCSDIR "${LLVM_DOCSDIR}"
/* Installation directory for config files */
-#undef LLVM_ETCDIR
+#cmakedefine LLVM_ETCDIR "${LLVM_ETCDIR}"
+
+/* Has gcc/MSVC atomic intrinsics */
+#cmakedefine01 LLVM_HAS_ATOMICS
/* Host triple we were built on */
#cmakedefine LLVM_HOSTTRIPLE "${LLVM_HOSTTRIPLE}"
/* Installation directory for include files */
-#undef LLVM_INCLUDEDIR
+#cmakedefine LLVM_INCLUDEDIR "${LLVM_INCLUDEDIR}"
/* Installation directory for .info files */
-#undef LLVM_INFODIR
+#cmakedefine LLVM_INFODIR "${LLVM_INFODIR}"
/* Installation directory for libraries */
-#undef LLVM_LIBDIR
+#cmakedefine LLVM_LIBDIR "${LLVM_LIBDIR}"
/* Installation directory for man pages */
-#undef LLVM_MANDIR
-
-/* Build multithreading support into LLVM */
-#cmakedefine LLVM_MULTITHREADED ${LLVM_MULTITHREADED}
+#cmakedefine LLVM_MANDIR "${LLVM_MANDIR}"
/* LLVM architecture name for the native architecture, if available */
#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH}
+/* LLVM name for the native AsmParser init function, if available */
+#cmakedefine LLVM_NATIVE_ASMPARSER LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser
+
/* LLVM name for the native AsmPrinter init function, if available */
#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter
@@ -557,8 +584,8 @@
/* LLVM name for the native TargetInfo init function, if available */
#cmakedefine LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo
-/* LLVM name for the native MCAsmInfo init function, if available */
-#cmakedefine LLVM_NATIVE_MCASMINFO LLVMInitialize${LLVM_NATIVE_ARCH}MCAsmInfo
+/* LLVM name for the native target MC init function, if available */
+#cmakedefine LLVM_NATIVE_TARGETMC LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC
/* Define if this is Unixish platform */
#cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX}
@@ -579,7 +606,7 @@
#cmakedefine LLVM_PATH_FDP "${LLVM_PATH_FDP}"
/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */
-#undef LLVM_PATH_GRAPHVIZ
+#cmakedefine LLVM_PATH_GRAPHVIZ "${LLVM_PATH_GRAPHVIZ}"
/* Define to path to gv program if found or 'echo gv' otherwise */
#cmakedefine LLVM_PATH_GV "${LLVM_PATH_GV}"
@@ -641,20 +668,6 @@
/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
#undef STAT_MACROS_BROKEN
-/* If using the C implementation of alloca, define if you know the
- direction of stack growth for your system; otherwise it will be
- automatically deduced at runtime.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown */
-#undef STACK_DIRECTION
-
-/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
-#undef STAT_MACROS_BROKEN
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
@@ -667,6 +680,9 @@
/* Define if use udis86 library */
#undef USE_UDIS86
+/* Type of 1st arg on ELM Callback */
+#cmakedefine WIN32_ELMCB_PCSTR ${WIN32_ELMCB_PCSTR}
+
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
@@ -679,16 +695,6 @@
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
-/* Define if the neat program is available */
-#cmakedefine HAVE_TWOPI ${HAVE_TWOPI}
-
-/* Define to 1 if the system has the type `uint64_t'. */
-#cmakedefine HAVE_UINT64_T ${HAVE_UINT64_T}
-
-/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
- `char[]'. */
-#undef YYTEXT_POINTER
-
/* Define to a function replacing strtoll */
#cmakedefine strtoll ${strtoll}
@@ -704,36 +710,6 @@
/* Define to 1 if you have the `_chsize_s' function. */
#cmakedefine HAVE__CHSIZE_S ${HAVE__CHSIZE_S}
-/* define if the compiler implements namespaces */
-#undef HAVE_NAMESPACES
-
-/* Does not have std namespace iterator */
-#undef HAVE_STD_ITERATOR
-
-/* Does not have forward iterator */
-#undef HAVE_FWD_ITERATOR
-
-/* Does not have bi-directional iterator */
-#undef HAVE_BI_ITERATOR
-
-/* Does not have <hash_map> */
-#undef HAVE_GLOBAL_HASH_MAP
-
-/* Does not have hash_set in global namespace */
-#undef HAVE_GLOBAL_HASH_SET
-
-/* Does not have ext/hash_map */
-#undef HAVE_GNU_EXT_HASH_MAP
-
-/* Does not have hash_set in gnu namespace */
-#undef HAVE_GNU_EXT_HASH_SET
-
-/* Does not have ext/hash_map> */
-#undef HAVE_STD_EXT_HASH_MAP
-
-/* Does not have hash_set in std namespace */
-#undef HAVE_STD_EXT_HASH_SET
-
/* Added by Kevin -- Maximum path length */
#cmakedefine MAXPATHLEN ${MAXPATHLEN}
diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in
index 0a716ea..3670de5 100644
--- a/include/llvm/Config/config.h.in
+++ b/include/llvm/Config/config.h.in
@@ -3,6 +3,9 @@
#ifndef CONFIG_H
#define CONFIG_H
+/* Bug report URL. */
+#undef BUG_REPORT_URL
+
/* Relative directory for resource files */
#undef CLANG_RESOURCE_DIR
@@ -546,6 +549,9 @@
/* Installation directory for config files */
#undef LLVM_ETCDIR
+/* Has gcc/MSVC atomic intrinsics */
+#undef LLVM_HAS_ATOMICS
+
/* Host triple we were built on */
#undef LLVM_HOSTTRIPLE
@@ -561,9 +567,6 @@
/* Installation directory for man pages */
#undef LLVM_MANDIR
-/* Build multithreading support into LLVM */
-#undef LLVM_MULTITHREADED
-
/* LLVM architecture name for the native architecture, if available */
#undef LLVM_NATIVE_ARCH
@@ -573,15 +576,15 @@
/* LLVM name for the native AsmPrinter init function, if available */
#undef LLVM_NATIVE_ASMPRINTER
-/* LLVM name for the native MCAsmInfo init function, if available */
-#undef LLVM_NATIVE_MCASMINFO
-
/* LLVM name for the native Target init function, if available */
#undef LLVM_NATIVE_TARGET
/* LLVM name for the native TargetInfo init function, if available */
#undef LLVM_NATIVE_TARGETINFO
+/* LLVM name for the native target MC init function, if available */
+#undef LLVM_NATIVE_TARGETMC
+
/* Define if this is Unixish platform */
#undef LLVM_ON_UNIX
diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake
index 5f948a2..4147fd1 100644
--- a/include/llvm/Config/llvm-config.h.cmake
+++ b/include/llvm/Config/llvm-config.h.cmake
@@ -31,6 +31,9 @@
/* Installation directory for config files */
#cmakedefine LLVM_ETCDIR "${LLVM_ETCDIR}"
+/* Has gcc/MSVC atomic intrinsics */
+#cmakedefine01 LLVM_HAS_ATOMICS
+
/* Host triple we were built on */
#cmakedefine LLVM_HOSTTRIPLE "${LLVM_HOSTTRIPLE}"
@@ -46,26 +49,23 @@
/* Installation directory for man pages */
#cmakedefine LLVM_MANDIR "${LLVM_MANDIR}"
-/* Build multithreading support into LLVM */
-#cmakedefine LLVM_MULTITHREADED ${LLVM_MULTITHREADED}
-
/* LLVM architecture name for the native architecture, if available */
#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH}
+/* LLVM name for the native AsmParser init function, if available */
+#cmakedefine LLVM_NATIVE_ASMPARSER LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser
+
+/* LLVM name for the native AsmPrinter init function, if available */
+#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter
+
/* LLVM name for the native Target init function, if available */
#cmakedefine LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target
/* LLVM name for the native TargetInfo init function, if available */
#cmakedefine LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo
-/* LLVM name for the native MCAsmInfo init function, if available */
-#cmakedefine LLVM_NATIVE_MCASMINFO LLVMInitialize${LLVM_NATIVE_ARCH}MCAsmInfo
-
-/* LLVM name for the native AsmPrinter init function, if available */
-#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter
-
-/* LLVM name for the native AsmPrinter init function, if available */
-#cmakedefine LLVM_NATIVE_ASMPARSER LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser
+/* LLVM name for the native target MC init function, if available */
+#cmakedefine LLVM_NATIVE_TARGETMC LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC
/* Define if this is Unixish platform */
#cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX}
diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in
index bc8ddce..b2257f3 100644
--- a/include/llvm/Config/llvm-config.h.in
+++ b/include/llvm/Config/llvm-config.h.in
@@ -31,6 +31,9 @@
/* Installation directory for config files */
#undef LLVM_ETCDIR
+/* Has gcc/MSVC atomic intrinsics */
+#undef LLVM_HAS_ATOMICS
+
/* Host triple we were built on */
#undef LLVM_HOSTTRIPLE
@@ -46,26 +49,23 @@
/* Installation directory for man pages */
#undef LLVM_MANDIR
-/* Build multithreading support into LLVM */
-#undef LLVM_MULTITHREADED
-
/* LLVM architecture name for the native architecture, if available */
#undef LLVM_NATIVE_ARCH
+/* LLVM name for the native AsmParser init function, if available */
+#undef LLVM_NATIVE_ASMPARSER
+
+/* LLVM name for the native AsmPrinter init function, if available */
+#undef LLVM_NATIVE_ASMPRINTER
+
/* LLVM name for the native Target init function, if available */
#undef LLVM_NATIVE_TARGET
/* LLVM name for the native TargetInfo init function, if available */
#undef LLVM_NATIVE_TARGETINFO
-/* LLVM name for the native MCAsmInfo init function, if available */
-#undef LLVM_NATIVE_MCASMINFO
-
-/* LLVM name for the native AsmPrinter init function, if available */
-#undef LLVM_NATIVE_ASMPRINTER
-
-/* LLVM name for the native AsmPrinter init function, if available */
-#undef LLVM_NATIVE_ASMPARSER
+/* LLVM name for the native target MC init function, if available */
+#undef LLVM_NATIVE_TARGETMC
/* Define if this is Unixish platform */
#undef LLVM_ON_UNIX
@@ -97,6 +97,9 @@
/* Define to path to twopi program if found or 'echo twopi' otherwise */
#undef LLVM_PATH_TWOPI
+/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */
+#undef LLVM_PATH_XDOT_PY
+
/* Installation prefix directory */
#undef LLVM_PREFIX
diff --git a/include/llvm/Constant.h b/include/llvm/Constant.h
index 5e351c4..ecc1fe7 100644
--- a/include/llvm/Constant.h
+++ b/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/include/llvm/Constants.h b/include/llvm/Constants.h
index 01fca29..6545a3f 100644
--- a/include/llvm/Constants.h
+++ b/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<const IntegerType*>(Value::getType());
+ inline IntegerType *getType() const {
+ return reinterpret_cast<IntegerType*>(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<Constant*> >;
ConstantArray(const ConstantArray &); // DO NOT IMPLEMENT
protected:
- ConstantArray(const ArrayType *T, const std::vector<Constant*> &Val);
+ ConstantArray(ArrayType *T, ArrayRef<Constant *> Val);
public:
// ConstantArray accessors
- static Constant *get(const ArrayType *T, ArrayRef<Constant*> V);
+ static Constant *get(ArrayType *T, ArrayRef<Constant*> 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<const ArrayType*>(Value::getType());
+ inline ArrayType *getType() const {
+ return reinterpret_cast<ArrayType*>(Value::getType());
}
/// isString - This method returns true if the array is an array of i8 and
@@ -390,7 +390,7 @@ struct OperandTraits<ConstantArray> :
public VariadicOperandTraits<ConstantArray> {
};
-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<Constant*> >;
ConstantStruct(const ConstantStruct &); // DO NOT IMPLEMENT
protected:
- ConstantStruct(const StructType *T, const std::vector<Constant*> &Val);
+ ConstantStruct(StructType *T, ArrayRef<Constant *> Val);
public:
// ConstantStruct accessors
- static Constant *get(const StructType *T, ArrayRef<Constant*> V);
- static Constant *get(const StructType *T, ...) END_WITH_NULL;
+ static Constant *get(StructType *T, ArrayRef<Constant*> 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<const StructType*>(Value::getType());
+ inline StructType *getType() const {
+ return reinterpret_cast<StructType*>(Value::getType());
}
virtual void destroyConstant();
@@ -450,7 +450,7 @@ struct OperandTraits<ConstantStruct> :
public VariadicOperandTraits<ConstantStruct> {
};
-DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantStruct, Constant)
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant)
//===----------------------------------------------------------------------===//
@@ -461,7 +461,7 @@ class ConstantVector : public Constant {
std::vector<Constant*> >;
ConstantVector(const ConstantVector &); // DO NOT IMPLEMENT
protected:
- ConstantVector(const VectorType *T, const std::vector<Constant*> &Val);
+ ConstantVector(VectorType *T, ArrayRef<Constant *> Val);
public:
// ConstantVector accessors
static Constant *get(ArrayRef<Constant*> 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<const VectorType*>(Value::getType());
+ inline VectorType *getType() const {
+ return reinterpret_cast<VectorType*>(Value::getType());
}
/// This function will return true iff every element in this vector constant
@@ -501,7 +501,7 @@ struct OperandTraits<ConstantVector> :
public VariadicOperandTraits<ConstantVector> {
};
-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<const Type*>(T),
+ explicit ConstantPointerNull(PointerType *T)
+ : Constant(reinterpret_cast<Type*>(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<const PointerType*>(Value::getType());
+ inline PointerType *getType() const {
+ return reinterpret_cast<PointerType*>(Value::getType());
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -575,7 +575,7 @@ struct OperandTraits<BlockAddress> :
public FixedNumOperandTraits<BlockAddress, 2> {
};
-DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(BlockAddress, Value)
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value)
//===----------------------------------------------------------------------===//
@@ -591,7 +591,7 @@ class ConstantExpr : public Constant {
friend struct ConvertConstantType<ConstantExpr, Type>;
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<Constant *> 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<Constant *> or
+ // ArrayRef<Value *>.
+ return getGetElementPtr(C, cast<Value>(Idx), InBounds);
+ }
+ static Constant *getGetElementPtr(Constant *C,
+ ArrayRef<Value *> 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<Constant *> 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<Constant *> or
+ // ArrayRef<Value *>.
+ return getGetElementPtr(C, Idx, true);
}
static Constant *getInBoundsGetElementPtr(Constant *C,
- Value* const *IdxList,
- unsigned NumIdx) {
- return getGetElementPtr(C, IdxList, NumIdx, true);
+ ArrayRef<Value *> 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<Constant*> Ops, const Type *Ty) const;
+ Constant *getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const;
virtual void destroyConstant();
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
@@ -869,7 +884,7 @@ struct OperandTraits<ConstantExpr> :
public VariadicOperandTraits<ConstantExpr, 1> {
};
-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/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h
new file mode 100644
index 0000000..64f80c5
--- /dev/null
+++ b/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 <cstring>
+
+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("<invalid>"), 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/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h
index acb28de..445c3de 100644
--- a/include/llvm/DerivedTypes.h
+++ b/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<Type*> Params, bool IsVarArgs);
+ FunctionType(Type *Result, ArrayRef<Type*> 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<Type*> 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<Type*> Elements,
- bool isPacked = false);
- static StructType *createNamed(LLVMContext &Context, StringRef Name,
- ArrayRef<Type*> Elements,
- bool isPacked = false);
- static StructType *createNamed(StringRef Name, Type *elt1, ...) END_WITH_NULL;
+ static StructType *create(ArrayRef<Type*> Elements,
+ StringRef Name,
+ bool isPacked = false);
+ static StructType *create(ArrayRef<Type*> Elements);
+ static StructType *create(LLVMContext &Context,
+ ArrayRef<Type*> Elements,
+ StringRef Name,
+ bool isPacked = false);
+ static StructType *create(LLVMContext &Context, ArrayRef<Type*> 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<Type*> 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<Type*> 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/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h
index 88b21cd..cf85671 100644
--- a/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -18,6 +18,7 @@
#include <vector>
#include <map>
#include <string>
+#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<Module*, 1> 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<std::string>& MAttrs,
+ Reloc::Model RM,
+ CodeModel::Model CM,
std::string *Err);
ExecutionEngine *create();
diff --git a/include/llvm/Function.h b/include/llvm/Function.h
index 0aa5b2a..678651b 100644
--- a/include/llvm/Function.h
+++ b/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/include/llvm/GlobalAlias.h b/include/llvm/GlobalAlias.h
index c3d3c38..164d976 100644
--- a/include/llvm/GlobalAlias.h
+++ b/include/llvm/GlobalAlias.h
@@ -23,7 +23,6 @@
namespace llvm {
class Module;
-class Constant;
template<typename ValueSubClass, typename ItemParentClass>
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<Constant>(getOperand(0));
+ return getOperand(0);
}
Constant *getAliasee() {
- return cast_or_null<Constant>(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<GlobalAlias> :
public FixedNumOperandTraits<GlobalAlias, 1> {
};
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Value)
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Constant)
} // End llvm namespace
diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h
index d0f0888..63dc4ab 100644
--- a/include/llvm/GlobalValue.h
+++ b/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/include/llvm/GlobalVariable.h b/include/llvm/GlobalVariable.h
index bbc09c1..034ade1 100644
--- a/include/llvm/GlobalVariable.h
+++ b/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/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index 4caf8f1..c91fbf8 100644
--- a/include/llvm/InitializePasses.h
+++ b/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/include/llvm/InlineAsm.h b/include/llvm/InlineAsm.h
index a98aff1..de5ce4e 100644
--- a/include/llvm/InlineAsm.h
+++ b/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/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h
index cc9ec3a..a1492f3 100644
--- a/include/llvm/InstrTypes.h
+++ b/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<const VectorType>(opnd_type)) {
+ static Type* makeCmpResultType(Type* opnd_type) {
+ if (VectorType* vt = dyn_cast<VectorType>(opnd_type)) {
return VectorType::get(Type::getInt1Ty(opnd_type->getContext()),
vt->getNumElements());
}
diff --git a/include/llvm/Instruction.def b/include/llvm/Instruction.def
index 205f303..d36e4be 100644
--- a/include/llvm/Instruction.def
+++ b/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/include/llvm/Instruction.h b/include/llvm/Instruction.h
index 89bb9fd..934e890 100644
--- a/include/llvm/Instruction.h
+++ b/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/include/llvm/Instructions.h b/include/llvm/Instructions.h
index 0bc9a3b..3faab35 100644
--- a/include/llvm/Instructions.h
+++ b/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 <iterator>
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<const PointerType*>(Instruction::getType());
+ PointerType *getType() const {
+ return reinterpret_cast<PointerType*>(Instruction::getType());
}
/// getAllocatedType - Return the type that is being allocated by the
@@ -126,11 +143,19 @@ public:
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); }
@@ -269,13 +374,332 @@ struct OperandTraits<StoreInst> : public FixedNumOperandTraits<StoreInst, 2> {
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<Instruction>(V) && classof(cast<Instruction>(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<PointerType>(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<Instruction>(V) && classof(cast<Instruction>(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<AtomicCmpXchgInst> :
+ public FixedNumOperandTraits<AtomicCmpXchgInst, 3> {
+};
+
+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 <signed v ? old : v
+ Min,
+ /// *p = old >unsigned v ? old : v
+ UMax,
+ /// *p = old <unsigned v ? old : v
+ UMin,
+
+ FIRST_BINOP = Xchg,
+ LAST_BINOP = UMin,
+ BAD_BINOP
+ };
+
+ // allocate space for exactly two operands
+ void *operator new(size_t s) {
+ return User::operator new(s, 2);
+ }
+ AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
+ AtomicOrdering Ordering, SynchronizationScope SynchScope,
+ Instruction *InsertBefore = 0);
+ AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
+ AtomicOrdering Ordering, SynchronizationScope SynchScope,
+ BasicBlock *InsertAtEnd);
+
+ BinOp getOperation() const {
+ return static_cast<BinOp>(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<PointerType>(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<Instruction>(V) && classof(cast<Instruction>(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<AtomicRMWInst>
+ : public FixedNumOperandTraits<AtomicRMWInst,2> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicRMWInst, Value)
+
+//===----------------------------------------------------------------------===//
// GetElementPtrInst Class
//===----------------------------------------------------------------------===//
// 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<typename RandomAccessIterator>
- 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<unsigned>(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<typename RandomAccessIterator>
- 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<unsigned>(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<Value *> 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<typename RandomAccessIterator>
- inline GetElementPtrInst(Value *Ptr, RandomAccessIterator IdxBegin,
- RandomAccessIterator IdxEnd,
- unsigned Values,
- const Twine &NameStr,
+ inline GetElementPtrInst(Value *Ptr, ArrayRef<Value *> IdxList,
+ unsigned Values, const Twine &NameStr,
Instruction *InsertBefore);
- template<typename RandomAccessIterator>
- 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<Value *> IdxList,
+ unsigned Values, const Twine &NameStr,
+ BasicBlock *InsertAtEnd);
protected:
virtual GetElementPtrInst *clone_impl() const;
public:
- template<typename RandomAccessIterator>
- static GetElementPtrInst *Create(Value *Ptr, RandomAccessIterator IdxBegin,
- RandomAccessIterator IdxEnd,
+ static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &NameStr = "",
Instruction *InsertBefore = 0) {
- typename std::iterator_traits<RandomAccessIterator>::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<typename RandomAccessIterator>
- static GetElementPtrInst *Create(Value *Ptr,
- RandomAccessIterator IdxBegin,
- RandomAccessIterator IdxEnd,
+ static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &NameStr,
BasicBlock *InsertAtEnd) {
- typename std::iterator_traits<RandomAccessIterator>::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<typename RandomAccessIterator>
static GetElementPtrInst *CreateInBounds(Value *Ptr,
- RandomAccessIterator IdxBegin,
- RandomAccessIterator IdxEnd,
+ ArrayRef<Value *> 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<typename RandomAccessIterator>
static GetElementPtrInst *CreateInBounds(Value *Ptr,
- RandomAccessIterator IdxBegin,
- RandomAccessIterator IdxEnd,
+ ArrayRef<Value *> 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<const PointerType*>(Instruction::getType());
+ PointerType *getType() const {
+ return reinterpret_cast<PointerType*>(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<typename RandomAccessIterator>
- static Type *getIndexedType(const Type *Ptr, RandomAccessIterator IdxBegin,
- RandomAccessIterator IdxEnd) {
- return getIndexedType(Ptr, IdxBegin, IdxEnd,
- typename std::iterator_traits<RandomAccessIterator>::
- 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<Value *> IdxList);
+ static Type *getIndexedType(Type *Ptr, ArrayRef<Constant *> IdxList);
+ static Type *getIndexedType(Type *Ptr, ArrayRef<uint64_t> 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<const PointerType*>(getPointerOperand()->getType());
+ PointerType *getPointerOperandType() const {
+ return reinterpret_cast<PointerType*>(getPointerOperand()->getType());
}
@@ -530,43 +842,33 @@ struct OperandTraits<GetElementPtrInst> :
public VariadicOperandTraits<GetElementPtrInst, 1> {
};
-template<typename RandomAccessIterator>
GetElementPtrInst::GetElementPtrInst(Value *Ptr,
- RandomAccessIterator IdxBegin,
- RandomAccessIterator IdxEnd,
+ ArrayRef<Value *> IdxList,
unsigned Values,
const Twine &NameStr,
Instruction *InsertBefore)
: Instruction(PointerType::get(checkGEPType(
- getIndexedType(Ptr->getType(),
- IdxBegin, IdxEnd)),
+ getIndexedType(Ptr->getType(), IdxList)),
cast<PointerType>(Ptr->getType())
->getAddressSpace()),
GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - Values,
Values, InsertBefore) {
- init(Ptr, IdxBegin, IdxEnd, NameStr,
- typename std::iterator_traits<RandomAccessIterator>
- ::iterator_category());
+ init(Ptr, IdxList, NameStr);
}
-template<typename RandomAccessIterator>
GetElementPtrInst::GetElementPtrInst(Value *Ptr,
- RandomAccessIterator IdxBegin,
- RandomAccessIterator IdxEnd,
+ ArrayRef<Value *> IdxList,
unsigned Values,
const Twine &NameStr,
BasicBlock *InsertAtEnd)
: Instruction(PointerType::get(checkGEPType(
- getIndexedType(Ptr->getType(),
- IdxBegin, IdxEnd)),
+ getIndexedType(Ptr->getType(), IdxList)),
cast<PointerType>(Ptr->getType())
->getAddressSpace()),
GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - Values,
Values, InsertAtEnd) {
- init(Ptr, IdxBegin, IdxEnd, NameStr,
- typename std::iterator_traits<RandomAccessIterator>
- ::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<const VectorType*>(getVectorOperand()->getType());
+ VectorType *getVectorOperandType() const {
+ return reinterpret_cast<VectorType*>(getVectorOperand()->getType());
}
@@ -1286,8 +1597,8 @@ public:
/// getType - Overload to return most specific vector type.
///
- const VectorType *getType() const {
- return reinterpret_cast<const VectorType*>(Instruction::getType());
+ VectorType *getType() const {
+ return reinterpret_cast<VectorType*>(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<const VectorType*>(Instruction::getType());
+ VectorType *getType() const {
+ return reinterpret_cast<VectorType*>(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<unsigned> Idxs);
+ static Type *getIndexedType(Type *Agg, ArrayRef<unsigned> 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<PHINode> : 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<ArrayType>(OperandList[Idx + 1]->getType());
+ }
+
+ /// isFilter - Return 'true' if the clause and index Idx is a filter clause.
+ bool isFilter(unsigned Idx) const {
+ return isa<ArrayType>(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<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+};
+
+template <>
+struct OperandTraits<LandingPadInst> : 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<ConstantInt*>(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<Value*>(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<Value*>(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();
@@ -2492,6 +2926,57 @@ private:
};
//===----------------------------------------------------------------------===//
+// 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<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+private:
+ virtual BasicBlock *getSuccessorV(unsigned idx) const;
+ virtual unsigned getNumSuccessorsV() const;
+ virtual void setSuccessorV(unsigned idx, BasicBlock *B);
+};
+
+template <>
+struct OperandTraits<ResumeInst> :
+ public FixedNumOperandTraits<ResumeInst, 1> {
+};
+
+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/include/llvm/IntrinsicInst.h b/include/llvm/IntrinsicInst.h
index 24e5fe7..4286201 100644
--- a/include/llvm/IntrinsicInst.h
+++ b/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/include/llvm/Intrinsics.h b/include/llvm/Intrinsics.h
index 46361ca..3703825 100644
--- a/include/llvm/Intrinsics.h
+++ b/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<Type*> Tys = ArrayRef<Type*>());
/// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be
diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td
index 947cf1b..d70f915 100644
--- a/include/llvm/Intrinsics.td
+++ b/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>, LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_val_compare_and_swap">;
-def int_atomic_load_add : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>,
- LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_fetch_and_add">;
-def int_atomic_swap : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>,
- LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_lock_test_and_set">;
-def int_atomic_load_sub : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>,
- LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_fetch_and_sub">;
-def int_atomic_load_and : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>,
- LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_fetch_and_and">;
-def int_atomic_load_or : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>,
- LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_fetch_and_or">;
-def int_atomic_load_xor : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>,
- LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_fetch_and_xor">;
-def int_atomic_load_nand : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>,
- LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_fetch_and_nand">;
-def int_atomic_load_min : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>,
- LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_fetch_and_min">;
-def int_atomic_load_max : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>,
- LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_fetch_and_max">;
-def int_atomic_load_umin : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>,
- LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_fetch_and_umin">;
-def int_atomic_load_umax : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>,
- LLVMMatchType<0>],
- [IntrReadWriteArgMem, NoCapture<0>]>,
- GCCBuiltin<"__sync_fetch_and_umax">;
-
//===------------------------- Memory Use Markers -------------------------===//
//
def int_lifetime_start : Intrinsic<[],
diff --git a/include/llvm/IntrinsicsXCore.td b/include/llvm/IntrinsicsXCore.td
index a062fc4..a481313 100644
--- a/include/llvm/IntrinsicsXCore.td
+++ b/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/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h
index 8467d11..f690d04 100644
--- a/include/llvm/LinkAllPasses.h
+++ b/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/include/llvm/Linker.h b/include/llvm/Linker.h
index b402a60..88908fb 100644
--- a/include/llvm/Linker.h
+++ b/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/include/llvm/MC/EDInstInfo.h b/include/llvm/MC/EDInstInfo.h
index 83d9e78..0b9d3f6 100644
--- a/include/llvm/MC/EDInstInfo.h
+++ b/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/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h
new file mode 100644
index 0000000..4a0cf37
--- /dev/null
+++ b/include/llvm/MC/MCAsmBackend.h
@@ -0,0 +1,131 @@
+//===-- llvm/MC/MCAsmBack.h - MC Asm Backend --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCASMBACKEND_H
+#define LLVM_MC_MCASMBACKEND_H
+
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+class MCELFObjectTargetWriter;
+class MCFixup;
+class MCInst;
+class MCObjectWriter;
+class MCSection;
+template<typename T>
+class SmallVectorImpl;
+class raw_ostream;
+
+/// 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.
+ MCAsmBackend();
+
+ unsigned HasReliableSymbolDifference : 1;
+
+public:
+ virtual ~MCAsmBackend();
+
+ /// createObjectWriter - Create a new MCObjectWriter instance for use by the
+ /// assembler backend to emit the final object file.
+ virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0;
+
+ /// createELFObjectTargetWriter - Create a new ELFObjectTargetWriter to enable
+ /// non-standard ELFObjectWriters.
+ virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const {
+ assert(0 && "createELFObjectTargetWriter is not supported by asm backend");
+ return 0;
+ }
+
+ /// hasReliableSymbolDifference - Check whether this target implements
+ /// accurate relocations for differences between symbols. If not, differences
+ /// between symbols will always be relocatable expressions and any references
+ /// to temporary symbols will be assumed to be in the same atom, unless they
+ /// reside in a different section.
+ ///
+ /// This should always be true (since it results in fewer relocations with no
+ /// loss of functionality), but is currently supported as a way to maintain
+ /// exact object compatibility with Darwin 'as' (on non-x86_64). It should
+ /// eventually should be eliminated.
+ bool hasReliableSymbolDifference() const {
+ return HasReliableSymbolDifference;
+ }
+
+ /// doesSectionRequireSymbols - Check whether the given section requires that
+ /// all symbols (even temporaries) have symbol table entries.
+ virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
+ return false;
+ }
+
+ /// isSectionAtomizable - Check whether the given section can be split into
+ /// atoms.
+ ///
+ /// \see MCAssembler::isSymbolLinkerVisible().
+ virtual bool isSectionAtomizable(const MCSection &Section) const {
+ return true;
+ }
+
+ /// @name Target Fixup Interfaces
+ /// @{
+
+ /// getNumFixupKinds - Get the number of target specific fixup kinds.
+ virtual unsigned getNumFixupKinds() const = 0;
+
+ /// getFixupKindInfo - Get information on a fixup kind.
+ virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const;
+
+ /// @}
+
+ /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided
+ /// data fragment, at the offset specified by the fixup and following the
+ /// fixup kind as appropriate.
+ virtual void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
+ uint64_t Value) const = 0;
+
+ /// @}
+
+ /// @name Target Relaxation Interfaces
+ /// @{
+
+ /// MayNeedRelaxation - Check whether the given instruction may need
+ /// relaxation.
+ ///
+ /// \param Inst - The instruction to test.
+ virtual bool MayNeedRelaxation(const MCInst &Inst) const = 0;
+
+ /// RelaxInstruction - Relax the instruction in the given fragment to the next
+ /// wider instruction.
+ ///
+ /// \param Inst - The instruction to relax, which may be the same as the
+ /// output.
+ /// \parm Res [output] - On return, the relaxed instruction.
+ virtual void RelaxInstruction(const MCInst &Inst, MCInst &Res) const = 0;
+
+ /// @}
+
+ /// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given
+ /// output. If the target cannot generate such a sequence, it should return an
+ /// error.
+ ///
+ /// \return - True on success.
+ virtual bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const = 0;
+
+ /// HandleAssemblerFlag - Handle any target-specific assembler flags.
+ /// By default, do nothing.
+ virtual void HandleAssemblerFlag(MCAssemblerFlag Flag) {}
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index 41c1717..c3c296e 100644
--- a/include/llvm/MC/MCAsmInfo.h
+++ b/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 <cassert>
+#include <vector>
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<MachineMove> 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<MachineMove> &getInitialFrameState() const {
+ return InitialFrameState;
+ }
};
}
diff --git a/include/llvm/MC/MCAsmInfoDarwin.h b/include/llvm/MC/MCAsmInfoDarwin.h
index c85aa3d..1f6c499 100644
--- a/include/llvm/MC/MCAsmInfoDarwin.h
+++ b/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/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index fc91966..b8f8cc4 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/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 <vector> // 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<MCFragment> {
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/include/llvm/MC/MCAtom.h b/include/llvm/MC/MCAtom.h
new file mode 100644
index 0000000..682cf7c
--- /dev/null
+++ b/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 <vector>
+
+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<std::pair<uint64_t, MCInst> > Text;
+ std::vector<MCData> 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/include/llvm/MC/MCCodeGenInfo.h b/include/llvm/MC/MCCodeGenInfo.h
new file mode 100644
index 0000000..1c54c47
--- /dev/null
+++ b/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/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h
index 43a9ce6..a49a35c 100644
--- a/include/llvm/MC/MCContext.h
+++ b/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/include/llvm/MC/MCDirectives.h b/include/llvm/MC/MCDirectives.h
index 1df55dc..9180d1b 100644
--- a/include/llvm/MC/MCDirectives.h
+++ b/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/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h
index ce8759a..454277d 100644
--- a/include/llvm/MC/MCDisassembler.h
+++ b/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 &region,
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/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h
index 90c3728..431e3c4 100644
--- a/include/llvm/MC/MCDwarf.h
+++ b/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 <vector>
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<MCCFIInstruction> Instructions;
unsigned PersonalityEncoding;
unsigned LsdaEncoding;
+ uint32_t CompactUnwindEncoding;
};
class MCDwarfFrameEmitter {
diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h
index d6ef7b4..d384764 100644
--- a/include/llvm/MC/MCInst.h
+++ b/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<MCOperand, 8>::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/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h
index 39002da..01ad2d3f 100644
--- a/include/llvm/MC/MCInstPrinter.h
+++ b/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/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h
new file mode 100644
index 0000000..8f3c499
--- /dev/null
+++ b/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/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h
index 4996914..aafa800 100644
--- a/include/llvm/MC/MCInstrDesc.h
+++ b/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 <<MCOI::LookupPtrRegClass);}
-
+ bool isLookupPtrRegClass() const {return Flags&(1 <<MCOI::LookupPtrRegClass);}
+
/// isPredicate - Set if this is one of the operands that made up of
/// the predicate operand that controls an isPredicable() instruction.
bool isPredicate() const { return Flags & (1 << MCOI::Predicate); }
-
+
/// isOptionalDef - Set if this operand is a optional def.
///
bool isOptionalDef() const { return Flags & (1 << MCOI::OptionalDef); }
};
-
+
//===----------------------------------------------------------------------===//
// Machine Instruction Flags and Description
//===----------------------------------------------------------------------===//
@@ -97,6 +97,7 @@ namespace MCID {
enum {
Variadic = 0,
HasOptionalDef,
+ Pseudo,
Return,
Call,
Barrier,
@@ -116,6 +117,7 @@ namespace MCID {
Commutable,
ConvertibleTo3Addr,
UsesCustomInserter,
+ HasPostISelHook,
Rematerializable,
CheapAsAMove,
ExtraSrcRegAllocReq,
@@ -158,13 +160,13 @@ public:
unsigned getOpcode() const {
return Opcode;
}
-
+
/// getName - Return the name of the record in the .td file for this
/// instruction, for example "ADD8ri".
const char *getName() const {
return Name;
}
-
+
/// getNumOperands - Return the number of declared MachineOperands for this
/// MachineInstruction. Note that variadic (isVariadic() returns true)
/// instructions may have additional operands at the end of the list, and note
@@ -173,15 +175,15 @@ public:
unsigned getNumOperands() const {
return NumOperands;
}
-
+
/// getNumDefs - Return the number of MachineOperands that are register
- /// definitions. Register definitions always occur at the start of the
+ /// definitions. Register definitions always occur at the start of the
/// machine operand list. This is the number of "outs" in the .td file,
/// and does not include implicit defs.
unsigned getNumDefs() const {
return NumDefs;
}
-
+
/// isVariadic - Return true if this instruction can have a variable number of
/// operands. In this case, the variable operands will be after the normal
/// operands but before the implicit definitions and uses (if any are
@@ -189,13 +191,13 @@ public:
bool isVariadic() const {
return Flags & (1 << MCID::Variadic);
}
-
+
/// hasOptionalDef - Set if this instruction has an optional definition, e.g.
/// ARM instructions which can set condition code if 's' bit is set.
bool hasOptionalDef() const {
return Flags & (1 << MCID::HasOptionalDef);
}
-
+
/// getImplicitUses - Return a list of registers that are potentially
/// read by any instance of this machine instruction. For example, on X86,
/// the "adc" instruction adds two register operands and adds the carry bit in
@@ -208,7 +210,7 @@ public:
const unsigned *getImplicitUses() const {
return ImplicitUses;
}
-
+
/// getNumImplicitUses - Return the number of implicit uses this instruction
/// has.
unsigned getNumImplicitUses() const {
@@ -231,7 +233,7 @@ public:
const unsigned *getImplicitDefs() const {
return ImplicitDefs;
}
-
+
/// getNumImplicitDefs - Return the number of implicit defs this instruction
/// has.
unsigned getNumImplicitDefs() const {
@@ -240,7 +242,7 @@ public:
for (; ImplicitDefs[i]; ++i) /*empty*/;
return i;
}
-
+
/// hasImplicitUseOfPhysReg - Return true if this instruction implicitly
/// uses the specified physical register.
bool hasImplicitUseOfPhysReg(unsigned Reg) const {
@@ -249,7 +251,7 @@ public:
if (*ImpUses == Reg) return true;
return false;
}
-
+
/// hasImplicitDefOfPhysReg - Return true if this instruction implicitly
/// defines the specified physical register.
bool hasImplicitDefOfPhysReg(unsigned Reg) const {
@@ -267,28 +269,47 @@ public:
unsigned getSchedClass() const {
return SchedClass;
}
-
+
/// getSize - Return the number of bytes in the encoding of this instruction,
/// or zero if the encoding size cannot be known from the opcode.
unsigned getSize() const {
return Size;
}
+ /// isPseudo - Return true if this is a pseudo instruction that doesn't
+ /// correspond to a real machine instruction.
+ ///
+ bool isPseudo() const {
+ return Flags & (1 << MCID::Pseudo);
+ }
+
bool isReturn() const {
return Flags & (1 << MCID::Return);
}
-
+
bool isCall() const {
return Flags & (1 << MCID::Call);
}
-
+
/// isBarrier - Returns true if the specified instruction stops control flow
/// from executing the instruction immediately following it. Examples include
/// unconditional branches and return instructions.
bool isBarrier() const {
return Flags & (1 << MCID::Barrier);
}
-
+
+ /// findFirstPredOperandIdx() - Find the index of the first operand in the
+ /// operand list that is used to represent the predicate. It returns -1 if
+ /// none is found.
+ int findFirstPredOperandIdx() const {
+ if (isPredicable()) {
+ for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
+ if (OpInfo[i].isPredicate())
+ return i;
+ }
+ return -1;
+ }
+
/// isTerminator - Returns true if this instruction part of the terminator for
/// a basic block. Typically this is things like return and branch
/// instructions.
@@ -298,7 +319,7 @@ public:
bool isTerminator() const {
return Flags & (1 << MCID::Terminator);
}
-
+
/// isBranch - Returns true if this is a conditional, unconditional, or
/// indirect branch. Predicates below can be used to discriminate between
/// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to
@@ -320,7 +341,7 @@ public:
bool isConditionalBranch() const {
return isBranch() & !isBarrier() & !isIndirectBranch();
}
-
+
/// isUnconditionalBranch - Return true if this is a branch which always
/// transfers control flow to some other block. The
/// TargetInstrInfo::AnalyzeBranch method can be used to get more information
@@ -328,7 +349,7 @@ public:
bool isUnconditionalBranch() const {
return isBranch() & isBarrier() & !isIndirectBranch();
}
-
+
// isPredicable - Return true if this instruction has a predicate operand that
// controls execution. It may be set to 'always', or may be set to other
/// values. There are various methods in TargetInstrInfo that can be used to
@@ -336,14 +357,14 @@ public:
bool isPredicable() const {
return Flags & (1 << MCID::Predicable);
}
-
+
/// isCompare - Return true if this instruction is a comparison.
bool isCompare() const {
return Flags & (1 << MCID::Compare);
}
-
+
/// isMoveImmediate - Return true if this instruction is a move immediate
- /// (including conditional moves) instruction.
+ /// (including conditional moves) instruction.
bool isMoveImmediate() const {
return Flags & (1 << MCID::MoveImm);
}
@@ -353,20 +374,20 @@ public:
bool isBitcast() const {
return Flags & (1 << MCID::Bitcast);
}
-
+
/// isNotDuplicable - Return true if this instruction cannot be safely
/// duplicated. For example, if the instruction has a unique labels attached
/// to it, duplicating it would cause multiple definition errors.
bool isNotDuplicable() const {
return Flags & (1 << MCID::NotDuplicable);
}
-
+
/// hasDelaySlot - Returns true if the specified instruction has a delay slot
/// which must be filled by the code generator.
bool hasDelaySlot() const {
return Flags & (1 << MCID::DelaySlot);
}
-
+
/// canFoldAsLoad - Return true for instructions that can be folded as
/// memory operands in other instructions. The most common use for this
/// is instructions that are simple loads from memory that don't modify
@@ -378,7 +399,7 @@ public:
bool canFoldAsLoad() const {
return Flags & (1 << MCID::FoldableAsLoad);
}
-
+
//===--------------------------------------------------------------------===//
// Side Effect Analysis
//===--------------------------------------------------------------------===//
@@ -389,8 +410,8 @@ public:
bool mayLoad() const {
return Flags & (1 << MCID::MayLoad);
}
-
-
+
+
/// mayStore - Return true if this instruction could possibly modify memory.
/// Instructions with this flag set are not necessarily simple store
/// instructions, they may store a modified value based on their operands, or
@@ -398,7 +419,7 @@ public:
bool mayStore() const {
return Flags & (1 << MCID::MayStore);
}
-
+
/// hasUnmodeledSideEffects - Return true if this instruction has side
/// effects that are not modeled by other flags. This does not return true
/// for instructions whose effects are captured by:
@@ -415,14 +436,14 @@ public:
bool hasUnmodeledSideEffects() const {
return Flags & (1 << MCID::UnmodeledSideEffects);
}
-
+
//===--------------------------------------------------------------------===//
// Flags that indicate whether an instruction can be modified by a method.
//===--------------------------------------------------------------------===//
-
+
/// isCommutable - Return true if this may be a 2- or 3-address
/// instruction (of the form "X = op Y, Z, ..."), which produces the same
- /// result if Y and Z are exchanged. If this flag is set, then the
+ /// result if Y and Z are exchanged. If this flag is set, then the
/// TargetInstrInfo::commuteInstruction method may be used to hack on the
/// instruction.
///
@@ -433,7 +454,7 @@ public:
bool isCommutable() const {
return Flags & (1 << MCID::Commutable);
}
-
+
/// isConvertibleTo3Addr - Return true if this is a 2-address instruction
/// which can be changed into a 3-address instruction if needed. Doing this
/// transformation can be profitable in the register allocator, because it
@@ -451,11 +472,11 @@ public:
bool isConvertibleTo3Addr() const {
return Flags & (1 << MCID::ConvertibleTo3Addr);
}
-
+
/// usesCustomInsertionHook - Return true if this instruction requires
/// custom insertion support when the DAG scheduler is inserting it into a
/// machine basic block. If this is true for the instruction, it basically
- /// means that it is a pseudo instruction used at SelectionDAG time that is
+ /// means that it is a pseudo instruction used at SelectionDAG time that is
/// expanded out into magic code by the target when MachineInstrs are formed.
///
/// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method
@@ -463,7 +484,15 @@ public:
bool usesCustomInsertionHook() const {
return Flags & (1 << MCID::UsesCustomInserter);
}
-
+
+ /// hasPostISelHook - Return true if this instruction requires *adjustment*
+ /// after instruction selection by calling a target hook. For example, this
+ /// can be used to fill in ARM 's' optional operand depending on whether
+ /// the conditional flag register is used.
+ bool hasPostISelHook() const {
+ return Flags & (1 << MCID::HasPostISelHook);
+ }
+
/// isRematerializable - Returns true if this instruction is a candidate for
/// remat. This flag is deprecated, please don't use it anymore. If this
/// flag is set, the isReallyTriviallyReMaterializable() method is called to
diff --git a/include/llvm/MC/MCModule.h b/include/llvm/MC/MCModule.h
new file mode 100644
index 0000000..755fa02
--- /dev/null
+++ b/include/llvm/MC/MCModule.h
@@ -0,0 +1,58 @@
+//===-- llvm/MC/MCModule.h - MCModule 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 MCModule class, which is used to
+// represent a complete, disassembled object file or executable.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCMODULE_H
+#define LLVM_MC_MCMODULE_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+class MCAtom;
+
+/// MCModule - This class represent a completely disassembled object file or
+/// executable. It comprises a list of MCAtom's, and a branch target table.
+/// Each atom represents a contiguous range of either instructions or data.
+class MCModule {
+ /// AtomAllocationTracker - An MCModule owns its component MCAtom's, so it
+ /// must track them in order to ensure they are properly freed as atoms are
+ /// merged or otherwise manipulated.
+ SmallPtrSet<MCAtom*, 8> AtomAllocationTracker;
+
+ /// OffsetMap - Efficiently maps offset ranges to MCAtom's.
+ IntervalMap<uint64_t, MCAtom*> OffsetMap;
+
+ /// BranchTargetMap - Maps offsets that are determined to be branches and
+ /// can be statically resolved to their target offsets.
+ DenseMap<uint64_t, MCAtom*> 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<uint64_t, MCAtom*>::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/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h
new file mode 100644
index 0000000..060d508
--- /dev/null
+++ b/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/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h
index a89933b..f897e64 100644
--- a/include/llvm/MC/MCObjectStreamer.h
+++ b/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/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h
index ab78799..dcecfb6 100644
--- a/include/llvm/MC/MCParser/AsmLexer.h
+++ b/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/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h
index 47c580f..9bbb755 100644
--- a/include/llvm/MC/MCParser/MCAsmLexer.h
+++ b/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/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h
index 7376693..6ff1753 100644
--- a/include/llvm/MC/MCParser/MCAsmParser.h
+++ b/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/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h
index caf98bb..ada5ae8 100644
--- a/include/llvm/MC/MCRegisterInfo.h
+++ b/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 <cassert>
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<unsigned, int> L2DwarfRegs; // LLVM to Dwarf regs mapping
+ DenseMap<unsigned, int> EHL2DwarfRegs; // LLVM to Dwarf regs mapping EH
+ DenseMap<unsigned, unsigned> Dwarf2LRegs; // Dwarf to LLVM regs mapping
+ DenseMap<unsigned, unsigned> EHDwarf2LRegs; // Dwarf to LLVM regs mapping EH
+ DenseMap<unsigned, int> 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<unsigned, int> &M = isEH ? EHL2DwarfRegs : L2DwarfRegs;
+ const DenseMap<unsigned, int>::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<unsigned, unsigned> &M = isEH ? EHDwarf2LRegs : Dwarf2LRegs;
+ const DenseMap<unsigned, unsigned>::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<unsigned, int>::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/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 7bdba5f..451efbf 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/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<std::pair<const MCSection *,
const MCSection *>, 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<MCDwarfFrameInfo> 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/include/llvm/MC/MCTargetAsmLexer.h b/include/llvm/MC/MCTargetAsmLexer.h
new file mode 100644
index 0000000..acb3d4d
--- /dev/null
+++ b/include/llvm/MC/MCTargetAsmLexer.h
@@ -0,0 +1,89 @@
+//===-- llvm/MC/MCTargetAsmLexer.h - Target Assembly Lexer ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCTARGETASMLEXER_H
+#define LLVM_MC_MCTARGETASMLEXER_H
+
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+
+namespace llvm {
+class Target;
+
+/// MCTargetAsmLexer - Generic interface to target specific assembly lexers.
+class MCTargetAsmLexer {
+ /// The current token
+ AsmToken CurTok;
+
+ /// The location and description of the current error
+ SMLoc ErrLoc;
+ std::string Err;
+
+ MCTargetAsmLexer(const MCTargetAsmLexer &); // DO NOT IMPLEMENT
+ void operator=(const MCTargetAsmLexer &); // DO NOT IMPLEMENT
+protected: // Can only create subclasses.
+ MCTargetAsmLexer(const Target &);
+
+ virtual AsmToken LexToken() = 0;
+
+ void SetError(const SMLoc &errLoc, const std::string &err) {
+ ErrLoc = errLoc;
+ Err = err;
+ }
+
+ /// TheTarget - The Target that this machine was created for.
+ const Target &TheTarget;
+ MCAsmLexer *Lexer;
+
+public:
+ virtual ~MCTargetAsmLexer();
+
+ const Target &getTarget() const { return TheTarget; }
+
+ /// InstallLexer - Set the lexer to get tokens from lower-level lexer \arg L.
+ void InstallLexer(MCAsmLexer &L) {
+ Lexer = &L;
+ }
+
+ MCAsmLexer *getLexer() {
+ return Lexer;
+ }
+
+ /// Lex - Consume the next token from the input stream and return it.
+ const AsmToken &Lex() {
+ return CurTok = LexToken();
+ }
+
+ /// getTok - Get the current (last) lexed token.
+ const AsmToken &getTok() {
+ return CurTok;
+ }
+
+ /// getErrLoc - Get the current error location
+ const SMLoc &getErrLoc() {
+ return ErrLoc;
+ }
+
+ /// getErr - Get the current error string
+ const std::string &getErr() {
+ return Err;
+ }
+
+ /// getKind - Get the kind of current token.
+ AsmToken::TokenKind getKind() const { return CurTok.getKind(); }
+
+ /// is - Check if the current token has kind \arg K.
+ bool is(AsmToken::TokenKind K) const { return CurTok.is(K); }
+
+ /// isNot - Check if the current token has kind \arg K.
+ bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h
new file mode 100644
index 0000000..4e3fd0d
--- /dev/null
+++ b/include/llvm/MC/MCTargetAsmParser.h
@@ -0,0 +1,103 @@
+//===-- llvm/MC/MCTargetAsmParser.h - Target Assembly Parser ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_TARGETPARSER_H
+#define LLVM_MC_TARGETPARSER_H
+
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+
+namespace llvm {
+class MCStreamer;
+class StringRef;
+class SMLoc;
+class AsmToken;
+class MCParsedAsmOperand;
+class MCInst;
+template <typename T> class SmallVectorImpl;
+
+/// 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.
+ MCTargetAsmParser();
+
+ /// AvailableFeatures - The current set of available features.
+ unsigned AvailableFeatures;
+
+public:
+ virtual ~MCTargetAsmParser();
+
+ unsigned getAvailableFeatures() const { return AvailableFeatures; }
+ void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; }
+
+ virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+ SMLoc &EndLoc) = 0;
+
+ /// ParseInstruction - Parse one assembly instruction.
+ ///
+ /// The parser is positioned following the instruction name. The target
+ /// specific instruction parser should parse the entire instruction and
+ /// construct the appropriate MCInst, or emit an error. On success, the entire
+ /// line should be parsed up to and including the end-of-statement token. On
+ /// failure, the parser is not required to read to the end of the line.
+ //
+ /// \param Name - The instruction name.
+ /// \param NameLoc - The source location of the name.
+ /// \param Operands [out] - The list of parsed operands, this returns
+ /// ownership of them to the caller.
+ /// \return True on failure.
+ virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0;
+
+ /// ParseDirective - Parse a target specific assembler directive
+ ///
+ /// The parser is positioned following the directive name. The target
+ /// specific directive parser should parse the entire directive doing or
+ /// recording any target specific work, or return true and do nothing if the
+ /// directive is not target specific. If the directive is specific for
+ /// the target, the entire line is parsed up to and including the
+ /// end-of-statement token and false is returned.
+ ///
+ /// \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
+ MatchAndEmitInstruction(SMLoc IDLoc,
+ SmallVectorImpl<MCParsedAsmOperand*> &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
+
+#endif
diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h
index df8dbd9..8352ed1 100644
--- a/include/llvm/MC/MCValue.h
+++ b/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/include/llvm/MC/MachineLocation.h b/include/llvm/MC/MachineLocation.h
new file mode 100644
index 0000000..8ddfdbc
--- /dev/null
+++ b/include/llvm/MC/MachineLocation.h
@@ -0,0 +1,98 @@
+//===-- llvm/MC/MachineLocation.h -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// The MachineLocation class is used to represent a simple location in a machine
+// frame. Locations will be one of two forms; a register or an address formed
+// from a base address plus an offset. Register indirection can be specified by
+// using an offset of zero.
+//
+// The MachineMove class is used to represent abstract move operations in the
+// prolog/epilog of a compiled function. A collection of these objects can be
+// used by a debug consumer to track the location of values when unwinding stack
+// frames.
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_MC_MACHINELOCATION_H
+#define LLVM_MC_MACHINELOCATION_H
+
+namespace llvm {
+ class MCSymbol;
+
+class MachineLocation {
+private:
+ bool IsRegister; // True if location is a register.
+ unsigned Register; // gcc/gdb register number.
+ int Offset; // Displacement if not register.
+public:
+ enum {
+ // The target register number for an abstract frame pointer. The value is
+ // an arbitrary value that doesn't collide with any real target register.
+ VirtualFP = ~0U
+ };
+ MachineLocation()
+ : IsRegister(false), Register(0), Offset(0) {}
+ explicit MachineLocation(unsigned R)
+ : IsRegister(true), Register(R), Offset(0) {}
+ MachineLocation(unsigned R, int O)
+ : IsRegister(false), Register(R), Offset(O) {}
+
+ bool operator==(const MachineLocation &Other) const {
+ return IsRegister == Other.IsRegister && Register == Other.Register &&
+ Offset == Other.Offset;
+ }
+
+ // Accessors
+ bool isReg() const { return IsRegister; }
+ unsigned getReg() const { return Register; }
+ int getOffset() const { return Offset; }
+ void setIsRegister(bool Is) { IsRegister = Is; }
+ void setRegister(unsigned R) { Register = R; }
+ void setOffset(int O) { Offset = O; }
+ void set(unsigned R) {
+ IsRegister = true;
+ Register = R;
+ Offset = 0;
+ }
+ void set(unsigned R, int O) {
+ IsRegister = false;
+ Register = R;
+ Offset = O;
+ }
+
+#ifndef NDEBUG
+ void dump();
+#endif
+};
+
+/// MachineMove - This class represents the save or restore of a callee saved
+/// register that exception or debug info needs to know about.
+class MachineMove {
+private:
+ /// Label - Symbol for post-instruction address when result of move takes
+ /// effect.
+ MCSymbol *Label;
+
+ // Move to & from location.
+ MachineLocation Destination, Source;
+public:
+ MachineMove() : Label(0) {}
+
+ MachineMove(MCSymbol *label, const MachineLocation &D,
+ const MachineLocation &S)
+ : Label(label), Destination(D), Source(S) {}
+
+ // Accessors
+ MCSymbol *getLabel() const { return Label; }
+ const MachineLocation &getDestination() const { return Destination; }
+ const MachineLocation &getSource() const { return Source; }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Module.h b/include/llvm/Module.h
index 47d23f3..8ce5ec4 100644
--- a/include/llvm/Module.h
+++ b/include/llvm/Module.h
@@ -50,17 +50,35 @@ template<> struct ilist_traits<Function>
private:
mutable ilist_node<Function> Sentinel;
};
+
template<> struct ilist_traits<GlobalVariable>
: public SymbolTableListTraits<GlobalVariable, Module> {
// 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<GlobalVariable*>(&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<GlobalVariable> Sentinel;
};
+
template<> struct ilist_traits<GlobalAlias>
: public SymbolTableListTraits<GlobalAlias, Module> {
// 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<GlobalAlias*>(&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<GlobalAlias> Sentinel;
};
template<> struct ilist_traits<NamedMDNode>
@@ -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/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
new file mode 100644
index 0000000..4f08120
--- /dev/null
+++ b/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<Binary> &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/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index 121f9e8..067bcd4 100644
--- a/include/llvm/Object/COFF.h
+++ b/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<char> &Result) const;
+ virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
+ int64_t &Res) const;
+ virtual error_code getRelocationValueString(DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) const;
public:
COFFObjectFile(MemoryBuffer *Object, error_code &ec);
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
new file mode 100644
index 0000000..f5e7461
--- /dev/null
+++ b/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<char> &Result) const;
+ virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
+ int64_t &Res) const;
+ virtual error_code getRelocationValueString(DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) const;
+
+private:
+ MachOObject *MachOObj;
+ mutable uint32_t RegisteredStringTable;
+ typedef SmallVector<DataRefImpl, 1> SectionList;
+ SectionList Sections;
+
+
+ void moveToNextSection(DataRefImpl &DRI) const;
+ void getSymbolTableEntry(DataRefImpl DRI,
+ InMemoryStruct<macho::SymbolTableEntry> &Res) const;
+ void getSymbol64TableEntry(DataRefImpl DRI,
+ InMemoryStruct<macho::Symbol64TableEntry> &Res) const;
+ void moveToNextSymbol(DataRefImpl &DRI) const;
+ void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const;
+ void getSection64(DataRefImpl DRI,
+ InMemoryStruct<macho::Section64> &Res) const;
+ void getRelocation(DataRefImpl Rel,
+ InMemoryStruct<macho::RelocationEntry> &Res) const;
+ std::size_t getSectionIndex(DataRefImpl Sec) const;
+};
+
+}
+}
+
+#endif
+
diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h
index 31cd523..089cde9 100644
--- a/include/llvm/Object/MachOFormat.h
+++ b/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/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h
index 19a399e..51be847 100644
--- a/include/llvm/Object/MachOObject.h
+++ b/include/llvm/Object/MachOObject.h
@@ -150,6 +150,9 @@ public:
void ReadDysymtabLoadCommand(
const LoadCommandInfo &LCI,
InMemoryStruct<macho::DysymtabLoadCommand> &Res) const;
+ void ReadLinkeditDataLoadCommand(
+ const LoadCommandInfo &LCI,
+ InMemoryStruct<macho::LinkeditDataLoadCommand> &Res) const;
void ReadIndirectSymbolTableEntry(
const macho::DysymtabLoadCommand &DLC,
unsigned Index,
@@ -171,6 +174,7 @@ public:
void ReadSymbol64TableEntry(
uint64_t SymbolTableOffset, unsigned Index,
InMemoryStruct<macho::Symbol64TableEntry> &Res) const;
+ void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
/// @}
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 98ac067..83854a0 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -28,33 +28,56 @@ 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_type>
+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<SymbolRef> 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<char> &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<char> &Result) const;
+};
+typedef content_iterator<RelocationRef> relocation_iterator;
/// SectionRef - This is a value type class that represents a single section in
/// the list of sections in the object file.
@@ -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<SectionRef> 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<char> &Result) const = 0;
+ virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
+ int64_t &Res) const = 0;
+ virtual error_code getRelocationValueString(DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) const = 0;
public:
- template<class content_type>
- 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<SymbolRef> symbol_iterator;
- typedef content_iterator<SectionRef> 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<char> &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<char> &Result)
+ const {
+ return OwningObject->getRelocationValueString(RelocationPimpl, Result);
+}
+
} // end namespace object
} // end namespace llvm
diff --git a/include/llvm/OperandTraits.h b/include/llvm/OperandTraits.h
index f0df5fa..3d8dc32 100644
--- a/include/llvm/OperandTraits.h
+++ b/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<CLASS>::operands(this) \
&& "getOperand() out of range!"); \
- return static_cast<VALUECLASS*>( \
- OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture]); \
-} \
-void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \
- assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
- && "setOperand() out of range!"); \
- OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \
-} \
-unsigned CLASS::getNumOperands() const { \
- return OperandTraits<CLASS>::operands(this); \
-} \
-template <int Idx_nocapture> Use &CLASS::Op() { \
- return this->OpFrom<Idx_nocapture>(this); \
-} \
-template <int Idx_nocapture> const Use &CLASS::Op() const { \
- return this->OpFrom<Idx_nocapture>(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<CLASS>::op_begin(this); \
-} \
-CLASS::const_op_iterator CLASS::op_begin() const { \
- return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \
-} \
-CLASS::op_iterator CLASS::op_end() { \
- return OperandTraits<CLASS>::op_end(this); \
-} \
-CLASS::const_op_iterator CLASS::op_end() const { \
- return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \
-} \
-VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \
- assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
- && "getOperand() out of range!"); \
- return cast<VALUECLASS>( \
- OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture]); \
+ return cast_or_null<VALUECLASS>( \
+ OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \
} \
void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \
assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
diff --git a/include/llvm/Operator.h b/include/llvm/Operator.h
index e9aa499..48a5796 100644
--- a/include/llvm/Operator.h
+++ b/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<const PointerType*>(getPointerOperand()->getType());
+ PointerType *getPointerOperandType() const {
+ return reinterpret_cast<PointerType*>(getPointerOperand()->getType());
}
unsigned getNumIndices() const { // Note: always non-negative
diff --git a/include/llvm/PassManagers.h b/include/llvm/PassManagers.h
index c4f409e..c05347d 100644
--- a/include/llvm/PassManagers.h
+++ b/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/include/llvm/Support/BlockFrequency.h b/include/llvm/Support/BlockFrequency.h
new file mode 100644
index 0000000..554b784
--- /dev/null
+++ b/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/include/llvm/Support/BranchProbability.h b/include/llvm/Support/BranchProbability.h
index 2e81490..05c24d4 100644
--- a/include/llvm/Support/BranchProbability.h
+++ b/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/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h
index 8a998a8..04b8c4e 100644
--- a/include/llvm/Support/CallSite.h
+++ b/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/include/llvm/Support/Capacity.h b/include/llvm/Support/Capacity.h
new file mode 100644
index 0000000..d8cda43
--- /dev/null
+++ b/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 <typename T>
+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/include/llvm/Support/CodeGen.h b/include/llvm/Support/CodeGen.h
new file mode 100644
index 0000000..41351dc
--- /dev/null
+++ b/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/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h
index d609871..c6b62a8 100644
--- a/include/llvm/Support/CommandLine.h
+++ b/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.
@@ -797,6 +806,28 @@ public:
EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned>);
//--------------------------------------------------
+// parser<unsigned long long>
+//
+template<>
+class parser<unsigned long long> : public basic_parser<unsigned long long> {
+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<unsigned long long>);
+
+//--------------------------------------------------
// parser<double>
//
template<>
diff --git a/include/llvm/Support/ConstantFolder.h b/include/llvm/Support/ConstantFolder.h
index 7330235..93aa343 100644
--- a/include/llvm/Support/ConstantFolder.h
+++ b/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<Constant *> 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<Constant *> or
+ // ArrayRef<Value *>.
+ return ConstantExpr::getGetElementPtr(C, Idx);
+ }
+ Constant *CreateGetElementPtr(Constant *C,
+ ArrayRef<Value *> 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<Constant *> 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<Constant *> or
+ // ArrayRef<Value *>.
+ 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<Value *> 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/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h
new file mode 100644
index 0000000..506ec96
--- /dev/null
+++ b/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/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake
index 72c4518..8c0220a 100644
--- a/include/llvm/Support/DataTypes.h.cmake
+++ b/include/llvm/Support/DataTypes.h.cmake
@@ -15,12 +15,14 @@
|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*|
|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *|
|* *|
-|* No library is required when using these functinons. *|
+|* No library is required when using these functions. *|
|* *|
|*===----------------------------------------------------------------------===*/
/* Please leave this file C-compatible. */
+/* Please keep this file in sync with DataTypes.h.in */
+
#ifndef SUPPORT_DATATYPES_H
#define SUPPORT_DATATYPES_H
@@ -131,7 +133,8 @@ typedef signed int ssize_t;
# define INT32_MAX 2147483647
#endif
#ifndef INT32_MIN
-# define INT32_MIN -2147483648
+/* MSC treats -2147483648 as -(2147483648U). */
+# define INT32_MIN (-INT32_MAX - 1)
#endif
#ifndef UINT32_MAX
# define UINT32_MAX 4294967295U
@@ -163,6 +166,11 @@ typedef signed int ssize_t;
#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. */
diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in
index 5965e8c..425805a 100644
--- a/include/llvm/Support/DataTypes.h.in
+++ b/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 <math.h>
#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 <inttypes.h> includes <stdint.h>, 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 <stdlib.h>
+#include <stddef.h>
+#include <sys/types.h>
+#ifdef __cplusplus
+#include <cmath>
+#else
+#include <math.h>
+#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/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h
index 70bac0c..30f9187 100644
--- a/include/llvm/Support/Dwarf.h
+++ b/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/include/llvm/Support/DynamicLibrary.h b/include/llvm/Support/DynamicLibrary.h
index e6d9ff5..288936b 100644
--- a/include/llvm/Support/DynamicLibrary.h
+++ b/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/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h
index be48112..c5b85e2 100644
--- a/include/llvm/Support/ELF.h
+++ b/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/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h
index 4f013f8..a868e5f 100644
--- a/include/llvm/Support/FileSystem.h
+++ b/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<char> &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<char> &result_path);
+ SmallVectorImpl<char> &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/include/llvm/Support/Format.h b/include/llvm/Support/Format.h
index f64e3db..59812d9 100644
--- a/include/llvm/Support/Format.h
+++ b/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 <typename T1, typename T2, typename T3, typename T4>
+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 <typename T1, typename T2, typename T3, typename T4, typename T5>
+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 <typename T>
@@ -149,6 +193,24 @@ template <typename T1, typename T2, typename T3>
return format_object3<T1, T2, T3>(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 <typename T1, typename T2, typename T3, typename T4>
+inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1,
+ const T2 &Val2, const T3 &Val3,
+ const T4 &Val4) {
+ return format_object4<T1, T2, T3, T4>(Fmt, Val1, Val2, Val3, Val4);
+}
+
+/// 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 <typename T1, typename T2, typename T3, typename T4, typename T5>
+inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1,
+ const T2 &Val2, const T3 &Val3,
+ const T4 &Val4, const T5 &Val5) {
+ return format_object5<T1, T2, T3, T4, T5>(Fmt, Val1, Val2, Val3, Val4, Val5);
+}
+
} // end namespace llvm
#endif
diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h
new file mode 100644
index 0000000..49cd87f
--- /dev/null
+++ b/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<GCOVFunction *, 16> 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<GCOVBlock *, 16> 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<uint32_t, 16> Edges;
+ StringMap<GCOVLines *> 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<uint32_t, 4> Lines;
+};
+
+typedef SmallVector<uint32_t, 16> LineCounts;
+class FileInfo {
+public:
+ void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count);
+ void print();
+private:
+ StringMap<LineCounts> LineInfo;
+};
+
+}
+
+#endif
diff --git a/include/llvm/Support/GetElementPtrTypeIterator.h b/include/llvm/Support/GetElementPtrTypeIterator.h
index e5e7fc7..ef92c95 100644
--- a/include/llvm/Support/GetElementPtrTypeIterator.h
+++ b/include/llvm/Support/GetElementPtrTypeIterator.h
@@ -21,16 +21,16 @@
namespace llvm {
template<typename ItTy = User::const_op_iterator>
class generic_gep_type_iterator
- : public std::iterator<std::forward_iterator_tag, const Type *, ptrdiff_t> {
+ : public std::iterator<std::forward_iterator_tag, Type *, ptrdiff_t> {
typedef std::iterator<std::forward_iterator_tag,
- const Type *, ptrdiff_t> 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<CompositeType>(CurTy);
+ Type *getIndexedType() const {
+ CompositeType *CT = cast<CompositeType>(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<CompositeType>(CurTy)) {
+ if (CompositeType *CT = dyn_cast<CompositeType>(CurTy)) {
CurTy = CT->getTypeAtIndex(getOperand());
} else {
CurTy = 0;
@@ -97,16 +97,16 @@ namespace llvm {
return gep_type_iterator::end(GEP.op_end());
}
- template<typename ItTy>
- inline generic_gep_type_iterator<ItTy>
- gep_type_begin(const Type *Op0, ItTy I, ItTy E) {
- return generic_gep_type_iterator<ItTy>::begin(Op0, I);
+ template<typename T>
+ inline generic_gep_type_iterator<const T *>
+ gep_type_begin(Type *Op0, ArrayRef<T> A) {
+ return generic_gep_type_iterator<const T *>::begin(Op0, A.begin());
}
- template<typename ItTy>
- inline generic_gep_type_iterator<ItTy>
- gep_type_end(const Type *Op0, ItTy I, ItTy E) {
- return generic_gep_type_iterator<ItTy>::end(E);
+ template<typename T>
+ inline generic_gep_type_iterator<const T *>
+ gep_type_end(Type *Op0, ArrayRef<T> A) {
+ return generic_gep_type_iterator<const T *>::end(A.end());
}
} // end namespace llvm
diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h
index 91cd78e..7828001 100644
--- a/include/llvm/Support/IRBuilder.h
+++ b/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<typename RandomAccessIterator>
- 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<Value *> IdxList,
const Twine &Name = "") {
if (Constant *PC = dyn_cast<Constant>(Ptr)) {
// Every index must be constant.
- RandomAccessIterator i;
- for (i = IdxBegin; i < IdxEnd; ++i)
- if (!isa<Constant>(*i))
+ size_t i, e;
+ for (i = 0, e = IdxList.size(); i != e; ++i)
+ if (!isa<Constant>(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<typename RandomAccessIterator>
- Value *CreateInBoundsGEP(Value *Ptr, RandomAccessIterator IdxBegin,
- RandomAccessIterator IdxEnd,
+ Value *CreateInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name = "") {
if (Constant *PC = dyn_cast<Constant>(Ptr)) {
// Every index must be constant.
- RandomAccessIterator i;
- for (i = IdxBegin; i < IdxEnd; ++i)
- if (!isa<Constant>(*i))
+ size_t i, e;
+ for (i = 0, e = IdxList.size(); i != e; ++i)
+ if (!isa<Constant>(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<Constant>(Ptr))
if (Constant *IC = dyn_cast<Constant>(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<Constant>(Ptr))
if (Constant *IC = dyn_cast<Constant>(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<Constant>(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<Constant>(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<Constant>(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<Constant>(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<Constant>(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<Constant>(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<Constant>(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<Constant>(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<Constant>(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<Value *> 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/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h
index b2e5d58..a661c4f 100644
--- a/include/llvm/Support/InstVisitor.h
+++ b/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/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h
index 6841a0f..5b68586 100644
--- a/include/llvm/Support/MachO.h
+++ b/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/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h
index 5e55bd9..06816de 100644
--- a/include/llvm/Support/MemoryBuffer.h
+++ b/include/llvm/Support/MemoryBuffer.h
@@ -75,9 +75,9 @@ public:
/// return a MemoryBuffer.
static error_code getOpenFile(int FD, const char *Filename,
OwningPtr<MemoryBuffer> &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/include/llvm/Support/NoFolder.h b/include/llvm/Support/NoFolder.h
index 94359a5..75c1a79 100644
--- a/include/llvm/Support/NoFolder.h
+++ b/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<Constant *> 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<Value *> 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<Constant *> 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<Value *> 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/include/llvm/Support/PassManagerBuilder.h b/include/llvm/Support/PassManagerBuilder.h
deleted file mode 100644
index b0cec6e..0000000
--- a/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<std::pair<ExtensionPointTy, ExtensionFn> > 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/include/llvm/Support/PathV1.h b/include/llvm/Support/PathV1.h
index 024bb39..45165de 100644
--- a/include/llvm/Support/PathV1.h
+++ b/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/include/llvm/Support/PathV2.h b/include/llvm/Support/PathV2.h
index 2515633..6d38c95 100644
--- a/include/llvm/Support/PathV2.h
+++ b/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<char> &result);
+
/// @brief Has root name?
///
/// root_name != ""
diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h
index 3379922..27ef267 100644
--- a/include/llvm/Support/Process.h
+++ b/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/include/llvm/Support/SMLoc.h b/include/llvm/Support/SMLoc.h
index 967bf14..02db327 100644
--- a/include/llvm/Support/SMLoc.h
+++ b/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/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h
index 030db8f..deb8caf 100644
--- a/include/llvm/Support/SourceMgr.h
+++ b/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/include/llvm/Support/TargetFolder.h b/include/llvm/Support/TargetFolder.h
index 3233a98..c65faa6 100644
--- a/include/llvm/Support/TargetFolder.h
+++ b/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<Constant *> 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<Constant *> or
+ // ArrayRef<Value *>.
+ return Fold(ConstantExpr::getGetElementPtr(C, Idx));
+ }
+ Constant *CreateGetElementPtr(Constant *C,
+ ArrayRef<Value *> 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<Constant *> 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<Constant *> or
+ // ArrayRef<Value *>.
+ 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<Value *> 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/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h
new file mode 100644
index 0000000..45f249d
--- /dev/null
+++ b/include/llvm/Support/TargetRegistry.h
@@ -0,0 +1,1124 @@
+//===-- Support/TargetRegistry.h - Target Registration ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file exposes the TargetRegistry interface, which tools can use to access
+// the appropriate target specific classes (TargetMachine, AsmPrinter, etc.)
+// which have been registered.
+//
+// Target specific class implementations should register themselves using the
+// appropriate TargetRegistry interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TARGETREGISTRY_H
+#define LLVM_SUPPORT_TARGETREGISTRY_H
+
+#include "llvm/Support/CodeGen.h"
+#include "llvm/ADT/Triple.h"
+#include <string>
+#include <cassert>
+
+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 MCTargetAsmLexer;
+ class MCTargetAsmParser;
+ class TargetMachine;
+ class raw_ostream;
+ class formatted_raw_ostream;
+
+ MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
+ bool isVerboseAsm,
+ bool useLoc, bool useCFI,
+ MCInstPrinter *InstPrint,
+ MCCodeEmitter *CE,
+ MCAsmBackend *TAB,
+ bool ShowInst);
+
+ /// Target - Wrapper for Target specific information.
+ ///
+ /// For registration purposes, this is a POD type so that targets can be
+ /// registered without the use of static constructors.
+ ///
+ /// Targets should implement a single global instance of this class (which
+ /// will be zero initialized), and pass that instance to the TargetRegistry as
+ /// part of their initialization.
+ class Target {
+ public:
+ friend struct TargetRegistry;
+
+ typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT);
+
+ typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const Target &T,
+ StringRef TT);
+ typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT,
+ Reloc::Model RM,
+ CodeModel::Model CM);
+ typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void);
+ typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo*Info);
+ typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT);
+ typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT,
+ StringRef CPU,
+ StringRef Features);
+ typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T,
+ StringRef TT,
+ StringRef CPU,
+ StringRef Features,
+ Reloc::Model RM,
+ CodeModel::Model CM);
+ typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM,
+ MCStreamer &Streamer);
+ 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,
+ 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,
+ bool useLoc,
+ bool useCFI,
+ MCInstPrinter *InstPrint,
+ MCCodeEmitter *CE,
+ MCAsmBackend *TAB,
+ bool ShowInst);
+
+ private:
+ /// Next - The next registered target in the linked list, maintained by the
+ /// TargetRegistry.
+ Target *Next;
+
+ /// TripleMatchQualityFn - The target function for rating the match quality
+ /// of a triple.
+ TripleMatchQualityFnTy TripleMatchQualityFn;
+
+ /// Name - The target name.
+ const char *Name;
+
+ /// ShortDesc - A short description of the target.
+ const char *ShortDesc;
+
+ /// HasJIT - Whether this target supports the JIT.
+ bool HasJIT;
+
+ /// MCAsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if
+ /// registered.
+ MCAsmInfoCtorFnTy MCAsmInfoCtorFn;
+
+ /// MCCodeGenInfoCtorFn - Constructor function for this target's MCCodeGenInfo,
+ /// if registered.
+ MCCodeGenInfoCtorFnTy MCCodeGenInfoCtorFn;
+
+ /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo,
+ /// if registered.
+ MCInstrInfoCtorFnTy MCInstrInfoCtorFn;
+
+ /// MCInstrAnalysisCtorFn - Constructor function for this target's
+ /// MCInstrAnalysis, if registered.
+ MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn;
+
+ /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo,
+ /// if registered.
+ MCRegInfoCtorFnTy MCRegInfoCtorFn;
+
+ /// MCSubtargetInfoCtorFn - Constructor function for this target's
+ /// MCSubtargetInfo, if registered.
+ MCSubtargetInfoCtorFnTy MCSubtargetInfoCtorFn;
+
+ /// TargetMachineCtorFn - Construction function for this target's
+ /// TargetMachine, if registered.
+ TargetMachineCtorTy TargetMachineCtorFn;
+
+ /// MCAsmBackendCtorFn - Construction function for this target's
+ /// MCAsmBackend, if registered.
+ MCAsmBackendCtorTy MCAsmBackendCtorFn;
+
+ /// MCAsmLexerCtorFn - Construction function for this target's
+ /// MCTargetAsmLexer, if registered.
+ MCAsmLexerCtorTy MCAsmLexerCtorFn;
+
+ /// MCAsmParserCtorFn - Construction function for this target's
+ /// MCTargetAsmParser, if registered.
+ MCAsmParserCtorTy MCAsmParserCtorFn;
+
+ /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter,
+ /// if registered.
+ AsmPrinterCtorTy AsmPrinterCtorFn;
+
+ /// MCDisassemblerCtorFn - Construction function for this target's
+ /// MCDisassembler, if registered.
+ MCDisassemblerCtorTy MCDisassemblerCtorFn;
+
+ /// MCInstPrinterCtorFn - Construction function for this target's
+ /// MCInstPrinter, if registered.
+ MCInstPrinterCtorTy MCInstPrinterCtorFn;
+
+ /// MCCodeEmitterCtorFn - Construction function for this target's
+ /// CodeEmitter, if registered.
+ MCCodeEmitterCtorTy MCCodeEmitterCtorFn;
+
+ /// MCObjectStreamerCtorFn - Construction function for this target's
+ /// MCObjectStreamer, if registered.
+ MCObjectStreamerCtorTy MCObjectStreamerCtorFn;
+
+ /// AsmStreamerCtorFn - Construction function for this target's
+ /// AsmStreamer, if registered (default = llvm::createAsmStreamer).
+ AsmStreamerCtorTy AsmStreamerCtorFn;
+
+ public:
+ Target() : AsmStreamerCtorFn(llvm::createAsmStreamer) {}
+
+ /// @name Target Information
+ /// @{
+
+ // getNext - Return the next registered target.
+ const Target *getNext() const { return Next; }
+
+ /// getName - Get the target name.
+ const char *getName() const { return Name; }
+
+ /// getShortDescription - Get a short description of the target.
+ const char *getShortDescription() const { return ShortDesc; }
+
+ /// @}
+ /// @name Feature Predicates
+ /// @{
+
+ /// hasJIT - Check if this targets supports the just-in-time compilation.
+ bool hasJIT() const { return HasJIT; }
+
+ /// hasTargetMachine - Check if this target supports code generation.
+ bool hasTargetMachine() const { return TargetMachineCtorFn != 0; }
+
+ /// hasMCAsmBackend - Check if this target supports .o generation.
+ bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != 0; }
+
+ /// hasMCAsmLexer - Check if this target supports .s lexing.
+ bool hasMCAsmLexer() const { return MCAsmLexerCtorFn != 0; }
+
+ /// hasAsmParser - Check if this target supports .s parsing.
+ bool hasMCAsmParser() const { return MCAsmParserCtorFn != 0; }
+
+ /// hasAsmPrinter - Check if this target supports .s printing.
+ bool hasAsmPrinter() const { return AsmPrinterCtorFn != 0; }
+
+ /// hasMCDisassembler - Check if this target has a disassembler.
+ bool hasMCDisassembler() const { return MCDisassemblerCtorFn != 0; }
+
+ /// hasMCInstPrinter - Check if this target has an instruction printer.
+ bool hasMCInstPrinter() const { return MCInstPrinterCtorFn != 0; }
+
+ /// hasMCCodeEmitter - Check if this target supports instruction encoding.
+ bool hasMCCodeEmitter() const { return MCCodeEmitterCtorFn != 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; }
+
+ /// @}
+ /// @name Feature Constructors
+ /// @{
+
+ /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified
+ /// target triple.
+ ///
+ /// \arg Triple - This argument is used to determine the target machine
+ /// feature set; it should always be provided. Generally this should be
+ /// either the target triple from the module, or the target triple of the
+ /// host if that does not exist.
+ MCAsmInfo *createMCAsmInfo(StringRef Triple) const {
+ if (!MCAsmInfoCtorFn)
+ return 0;
+ 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 {
+ if (!MCInstrInfoCtorFn)
+ return 0;
+ 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(StringRef Triple) const {
+ if (!MCRegInfoCtorFn)
+ return 0;
+ return MCRegInfoCtorFn(Triple);
+ }
+
+ /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation.
+ ///
+ /// \arg Triple - This argument is used to determine the target machine
+ /// feature set; it should always be provided. Generally this should be
+ /// either the target triple from the module, or the target triple of the
+ /// host if that does not exist.
+ /// \arg CPU - This specifies the name of the target CPU.
+ /// \arg Features - This specifies the string representation of the
+ /// additional target features.
+ MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU,
+ StringRef Features) const {
+ if (!MCSubtargetInfoCtorFn)
+ return 0;
+ return MCSubtargetInfoCtorFn(Triple, CPU, Features);
+ }
+
+ /// createTargetMachine - Create a target specific machine implementation
+ /// for the specified \arg Triple.
+ ///
+ /// \arg Triple - This argument is used to determine the target machine
+ /// feature set; it should always be provided. Generally this should be
+ /// either the target triple from the module, or the target triple of the
+ /// host if that does not exist.
+ TargetMachine *createTargetMachine(StringRef Triple, StringRef CPU,
+ StringRef Features,
+ Reloc::Model RM = Reloc::Default,
+ CodeModel::Model CM = CodeModel::Default) const {
+ if (!TargetMachineCtorFn)
+ return 0;
+ return TargetMachineCtorFn(*this, Triple, CPU, Features, RM, CM);
+ }
+
+ /// createMCAsmBackend - Create a target specific assembly parser.
+ ///
+ /// \arg Triple - The target triple string.
+ /// \arg Backend - The target independent assembler object.
+ MCAsmBackend *createMCAsmBackend(StringRef Triple) const {
+ if (!MCAsmBackendCtorFn)
+ return 0;
+ return MCAsmBackendCtorFn(*this, Triple);
+ }
+
+ /// createMCAsmLexer - Create a target specific assembly lexer.
+ ///
+ MCTargetAsmLexer *createMCAsmLexer(const MCRegisterInfo &MRI,
+ const MCAsmInfo &MAI) const {
+ if (!MCAsmLexerCtorFn)
+ return 0;
+ return MCAsmLexerCtorFn(*this, MRI, MAI);
+ }
+
+ /// createMCAsmParser - Create a target specific assembly parser.
+ ///
+ /// \arg Parser - The target independent parser implementation to use for
+ /// parsing and lexing.
+ MCTargetAsmParser *createMCAsmParser(MCSubtargetInfo &STI,
+ MCAsmParser &Parser) const {
+ if (!MCAsmParserCtorFn)
+ return 0;
+ return MCAsmParserCtorFn(STI, Parser);
+ }
+
+ /// createAsmPrinter - Create a target specific assembly printer pass. This
+ /// takes ownership of the MCStreamer object.
+ AsmPrinter *createAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) const{
+ if (!AsmPrinterCtorFn)
+ return 0;
+ return AsmPrinterCtorFn(TM, Streamer);
+ }
+
+ MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI) const {
+ if (!MCDisassemblerCtorFn)
+ return 0;
+ return MCDisassemblerCtorFn(*this, STI);
+ }
+
+ MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI) const {
+ if (!MCInstPrinterCtorFn)
+ return 0;
+ return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI, STI);
+ }
+
+
+ /// createMCCodeEmitter - Create a target specific code emitter.
+ MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) const {
+ if (!MCCodeEmitterCtorFn)
+ return 0;
+ return MCCodeEmitterCtorFn(II, STI, Ctx);
+ }
+
+ /// createMCObjectStreamer - Create a target specific MCStreamer.
+ ///
+ /// \arg TT - The target triple.
+ /// \arg Ctx - The target context.
+ /// \arg TAB - The target assembler backend object. Takes ownership.
+ /// \arg _OS - The stream object.
+ /// \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 *createMCObjectStreamer(StringRef TT, MCContext &Ctx,
+ MCAsmBackend &TAB,
+ raw_ostream &_OS,
+ MCCodeEmitter *_Emitter,
+ bool RelaxAll,
+ bool NoExecStack) const {
+ if (!MCObjectStreamerCtorFn)
+ return 0;
+ return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter,
+ RelaxAll, NoExecStack);
+ }
+
+ /// createAsmStreamer - Create a target specific MCStreamer.
+ MCStreamer *createAsmStreamer(MCContext &Ctx,
+ formatted_raw_ostream &OS,
+ bool isVerboseAsm,
+ bool useLoc,
+ bool useCFI,
+ MCInstPrinter *InstPrint,
+ MCCodeEmitter *CE,
+ MCAsmBackend *TAB,
+ bool ShowInst) const {
+ // AsmStreamerCtorFn is default to llvm::createAsmStreamer
+ return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, useCFI,
+ InstPrint, CE, TAB, ShowInst);
+ }
+
+ /// @}
+ };
+
+ /// TargetRegistry - Generic interface to target specific features.
+ struct TargetRegistry {
+ class iterator {
+ const Target *Current;
+ explicit iterator(Target *T) : Current(T) {}
+ friend struct TargetRegistry;
+ public:
+ iterator(const iterator &I) : Current(I.Current) {}
+ iterator() : Current(0) {}
+
+ bool operator==(const iterator &x) const {
+ return Current == x.Current;
+ }
+ bool operator!=(const iterator &x) const {
+ return !operator==(x);
+ }
+
+ // Iterator traversal: forward iteration only
+ iterator &operator++() { // Preincrement
+ assert(Current && "Cannot increment end iterator!");
+ Current = Current->getNext();
+ return *this;
+ }
+ iterator operator++(int) { // Postincrement
+ iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ const Target &operator*() const {
+ assert(Current && "Cannot dereference end iterator!");
+ return *Current;
+ }
+
+ const Target *operator->() const {
+ return &operator*();
+ }
+ };
+
+ /// printRegisteredTargetsForVersion - Print the registered targets
+ /// appropriately for inclusion in a tool's version output.
+ static void printRegisteredTargetsForVersion();
+
+ /// @name Registry Access
+ /// @{
+
+ static iterator begin();
+
+ static iterator end() { return iterator(); }
+
+ /// lookupTarget - Lookup a target based on a target triple.
+ ///
+ /// \param Triple - The triple to use for finding a target.
+ /// \param Error - On failure, an error string describing why no target was
+ /// found.
+ static const Target *lookupTarget(const std::string &Triple,
+ std::string &Error);
+
+ /// getClosestTargetForJIT - Pick the best target that is compatible with
+ /// the current host. If no close target can be found, this returns null
+ /// and sets the Error string to a reason.
+ ///
+ /// Maintained for compatibility through 2.6.
+ static const Target *getClosestTargetForJIT(std::string &Error);
+
+ /// @}
+ /// @name Target Registration
+ /// @{
+
+ /// RegisterTarget - Register the given target. Attempts to register a
+ /// target which has already been registered will be ignored.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Name - The target name. This should be a static string.
+ /// @param ShortDesc - A short target description. This should be a static
+ /// string.
+ /// @param TQualityFn - The triple match quality computation function for
+ /// this target.
+ /// @param HasJIT - Whether the target supports JIT code
+ /// generation.
+ static void RegisterTarget(Target &T,
+ const char *Name,
+ const char *ShortDesc,
+ Target::TripleMatchQualityFnTy TQualityFn,
+ bool HasJIT = false);
+
+ /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCAsmInfo for the target.
+ static void RegisterMCAsmInfo(Target &T, Target::MCAsmInfoCtorFnTy Fn) {
+ // Ignore duplicate registration.
+ if (!T.MCAsmInfoCtorFn)
+ 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.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCInstrInfo for the target.
+ static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) {
+ // Ignore duplicate registration.
+ if (!T.MCInstrInfoCtorFn)
+ 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.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCRegisterInfo for the target.
+ static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) {
+ // Ignore duplicate registration.
+ if (!T.MCRegInfoCtorFn)
+ T.MCRegInfoCtorFn = Fn;
+ }
+
+ /// RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for
+ /// the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCSubtargetInfo for the target.
+ static void RegisterMCSubtargetInfo(Target &T,
+ Target::MCSubtargetInfoCtorFnTy Fn) {
+ // Ignore duplicate registration.
+ if (!T.MCSubtargetInfoCtorFn)
+ T.MCSubtargetInfoCtorFn = Fn;
+ }
+
+ /// RegisterTargetMachine - Register a TargetMachine implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a TargetMachine for the target.
+ static void RegisterTargetMachine(Target &T,
+ Target::TargetMachineCtorTy Fn) {
+ // Ignore duplicate registration.
+ if (!T.TargetMachineCtorFn)
+ T.TargetMachineCtorFn = Fn;
+ }
+
+ /// RegisterMCAsmBackend - Register a MCAsmBackend implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an AsmBackend for the target.
+ static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn) {
+ if (!T.MCAsmBackendCtorFn)
+ T.MCAsmBackendCtorFn = Fn;
+ }
+
+ /// RegisterMCAsmLexer - Register a MCTargetAsmLexer 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 MCAsmLexer for the target.
+ static void RegisterMCAsmLexer(Target &T, Target::MCAsmLexerCtorTy Fn) {
+ if (!T.MCAsmLexerCtorFn)
+ T.MCAsmLexerCtorFn = Fn;
+ }
+
+ /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for
+ /// the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCTargetAsmParser for the target.
+ static void RegisterMCAsmParser(Target &T, Target::MCAsmParserCtorTy Fn) {
+ if (!T.MCAsmParserCtorFn)
+ T.MCAsmParserCtorFn = Fn;
+ }
+
+ /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given
+ /// target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an AsmPrinter for the target.
+ static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) {
+ // Ignore duplicate registration.
+ if (!T.AsmPrinterCtorFn)
+ T.AsmPrinterCtorFn = Fn;
+ }
+
+ /// RegisterMCDisassembler - Register a MCDisassembler implementation for
+ /// the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCDisassembler for the target.
+ static void RegisterMCDisassembler(Target &T,
+ Target::MCDisassemblerCtorTy Fn) {
+ if (!T.MCDisassemblerCtorFn)
+ T.MCDisassemblerCtorFn = Fn;
+ }
+
+ /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCInstPrinter for the target.
+ static void RegisterMCInstPrinter(Target &T,
+ Target::MCInstPrinterCtorTy Fn) {
+ if (!T.MCInstPrinterCtorFn)
+ T.MCInstPrinterCtorFn = Fn;
+ }
+
+ /// RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCCodeEmitter for the target.
+ static void RegisterMCCodeEmitter(Target &T,
+ Target::MCCodeEmitterCtorTy Fn) {
+ if (!T.MCCodeEmitterCtorFn)
+ T.MCCodeEmitterCtorFn = Fn;
+ }
+
+ /// RegisterMCObjectStreamer - Register a object code MCStreamer
+ /// implementation for the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCStreamer for the target.
+ static void RegisterMCObjectStreamer(Target &T,
+ Target::MCObjectStreamerCtorTy Fn) {
+ if (!T.MCObjectStreamerCtorFn)
+ T.MCObjectStreamerCtorFn = Fn;
+ }
+
+ /// RegisterAsmStreamer - Register an assembly MCStreamer implementation
+ /// for the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCStreamer for the target.
+ static void RegisterAsmStreamer(Target &T, Target::AsmStreamerCtorTy Fn) {
+ if (T.AsmStreamerCtorFn == createAsmStreamer)
+ T.AsmStreamerCtorFn = Fn;
+ }
+
+ /// @}
+ };
+
+
+ //===--------------------------------------------------------------------===//
+
+ /// RegisterTarget - Helper template for registering a target, for use in the
+ /// target's initialization function. Usage:
+ ///
+ ///
+ /// Target TheFooTarget; // The global target instance.
+ ///
+ /// extern "C" void LLVMInitializeFooTargetInfo() {
+ /// RegisterTarget<Triple::foo> X(TheFooTarget, "foo", "Foo description");
+ /// }
+ template<Triple::ArchType TargetArchType = Triple::InvalidArch,
+ bool HasJIT = false>
+ struct RegisterTarget {
+ RegisterTarget(Target &T, const char *Name, const char *Desc) {
+ TargetRegistry::RegisterTarget(T, Name, Desc,
+ &getTripleMatchQuality,
+ HasJIT);
+ }
+
+ static unsigned getTripleMatchQuality(const std::string &TT) {
+ if (Triple(TT).getArch() == TargetArchType)
+ return 20;
+ return 0;
+ }
+ };
+
+ /// RegisterMCAsmInfo - Helper template for registering a target assembly info
+ /// implementation. This invokes the static "Create" method on the class to
+ /// actually do the construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCAsmInfo<FooMCAsmInfo> X(TheFooTarget);
+ /// }
+ template<class MCAsmInfoImpl>
+ struct RegisterMCAsmInfo {
+ RegisterMCAsmInfo(Target &T) {
+ TargetRegistry::RegisterMCAsmInfo(T, &Allocator);
+ }
+ private:
+ static MCAsmInfo *Allocator(const Target &T, StringRef TT) {
+ return new MCAsmInfoImpl(T, TT);
+ }
+
+ };
+
+ /// RegisterMCAsmInfoFn - Helper template for registering a target assembly info
+ /// implementation. This invokes the specified function to do the
+ /// construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCAsmInfoFn X(TheFooTarget, TheFunction);
+ /// }
+ struct RegisterMCAsmInfoFn {
+ RegisterMCAsmInfoFn(Target &T, Target::MCAsmInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCAsmInfo(T, Fn);
+ }
+ };
+
+ /// RegisterMCCodeGenInfo - Helper template for registering a target codegen info
+ /// implementation. This invokes the static "Create" method on the class
+ /// to actually do the construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCCodeGenInfo<FooMCCodeGenInfo> X(TheFooTarget);
+ /// }
+ template<class MCCodeGenInfoImpl>
+ struct RegisterMCCodeGenInfo {
+ RegisterMCCodeGenInfo(Target &T) {
+ TargetRegistry::RegisterMCCodeGenInfo(T, &Allocator);
+ }
+ private:
+ static MCCodeGenInfo *Allocator(StringRef TT,
+ Reloc::Model RM, CodeModel::Model CM) {
+ return new MCCodeGenInfoImpl();
+ }
+ };
+
+ /// RegisterMCCodeGenInfoFn - Helper template for registering a target codegen
+ /// info implementation. This invokes the specified function to do the
+ /// construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCCodeGenInfoFn X(TheFooTarget, TheFunction);
+ /// }
+ struct RegisterMCCodeGenInfoFn {
+ RegisterMCCodeGenInfoFn(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCCodeGenInfo(T, Fn);
+ }
+ };
+
+ /// RegisterMCInstrInfo - Helper template for registering a target instruction
+ /// info implementation. This invokes the static "Create" method on the class
+ /// to actually do the construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCInstrInfo<FooMCInstrInfo> X(TheFooTarget);
+ /// }
+ template<class MCInstrInfoImpl>
+ struct RegisterMCInstrInfo {
+ RegisterMCInstrInfo(Target &T) {
+ TargetRegistry::RegisterMCInstrInfo(T, &Allocator);
+ }
+ private:
+ static MCInstrInfo *Allocator() {
+ return new MCInstrInfoImpl();
+ }
+ };
+
+ /// RegisterMCInstrInfoFn - Helper template for registering a target
+ /// instruction info implementation. This invokes the specified function to
+ /// do the construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction);
+ /// }
+ struct RegisterMCInstrInfoFn {
+ RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCInstrInfo(T, Fn);
+ }
+ };
+
+ /// RegisterMCInstrAnalysis - Helper template for registering a target
+ /// instruction analyzer implementation. This invokes the static "Create"
+ /// method on the class to actually do the construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCInstrAnalysis<FooMCInstrAnalysis> X(TheFooTarget);
+ /// }
+ template<class MCInstrAnalysisImpl>
+ struct RegisterMCInstrAnalysis {
+ RegisterMCInstrAnalysis(Target &T) {
+ TargetRegistry::RegisterMCInstrAnalysis(T, &Allocator);
+ }
+ private:
+ static MCInstrAnalysis *Allocator(const MCInstrInfo *Info) {
+ return new MCInstrAnalysisImpl(Info);
+ }
+ };
+
+ /// RegisterMCInstrAnalysisFn - Helper template for registering a target
+ /// instruction analyzer implementation. This invokes the specified function
+ /// to do the construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCInstrAnalysisFn X(TheFooTarget, TheFunction);
+ /// }
+ struct RegisterMCInstrAnalysisFn {
+ RegisterMCInstrAnalysisFn(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) {
+ TargetRegistry::RegisterMCInstrAnalysis(T, Fn);
+ }
+ };
+
+ /// RegisterMCRegInfo - Helper template for registering a target register info
+ /// implementation. This invokes the static "Create" method on the class to
+ /// actually do the construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCRegInfo<FooMCRegInfo> X(TheFooTarget);
+ /// }
+ template<class MCRegisterInfoImpl>
+ struct RegisterMCRegInfo {
+ RegisterMCRegInfo(Target &T) {
+ TargetRegistry::RegisterMCRegInfo(T, &Allocator);
+ }
+ private:
+ static MCRegisterInfo *Allocator(StringRef TT) {
+ return new MCRegisterInfoImpl();
+ }
+ };
+
+ /// RegisterMCRegInfoFn - Helper template for registering a target register
+ /// info implementation. This invokes the specified function to do the
+ /// construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCRegInfoFn X(TheFooTarget, TheFunction);
+ /// }
+ struct RegisterMCRegInfoFn {
+ RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCRegInfo(T, Fn);
+ }
+ };
+
+ /// RegisterMCSubtargetInfo - Helper template for registering a target
+ /// subtarget info implementation. This invokes the static "Create" method
+ /// on the class to actually do the construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCSubtargetInfo<FooMCSubtargetInfo> X(TheFooTarget);
+ /// }
+ template<class MCSubtargetInfoImpl>
+ struct RegisterMCSubtargetInfo {
+ RegisterMCSubtargetInfo(Target &T) {
+ TargetRegistry::RegisterMCSubtargetInfo(T, &Allocator);
+ }
+ private:
+ static MCSubtargetInfo *Allocator(StringRef TT, StringRef CPU,
+ StringRef FS) {
+ return new MCSubtargetInfoImpl();
+ }
+ };
+
+ /// RegisterMCSubtargetInfoFn - Helper template for registering a target
+ /// subtarget info implementation. This invokes the specified function to
+ /// do the construction. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCSubtargetInfoFn X(TheFooTarget, TheFunction);
+ /// }
+ struct RegisterMCSubtargetInfoFn {
+ RegisterMCSubtargetInfoFn(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCSubtargetInfo(T, Fn);
+ }
+ };
+
+ /// RegisterTargetMachine - Helper template for registering a target machine
+ /// implementation, for use in the target machine initialization
+ /// function. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooTarget() {
+ /// extern Target TheFooTarget;
+ /// RegisterTargetMachine<FooTargetMachine> X(TheFooTarget);
+ /// }
+ template<class TargetMachineImpl>
+ struct RegisterTargetMachine {
+ RegisterTargetMachine(Target &T) {
+ TargetRegistry::RegisterTargetMachine(T, &Allocator);
+ }
+
+ private:
+ static TargetMachine *Allocator(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM,
+ CodeModel::Model CM) {
+ return new TargetMachineImpl(T, TT, CPU, FS, RM, CM);
+ }
+ };
+
+ /// RegisterMCAsmBackend - Helper template for registering a target specific
+ /// assembler backend. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooMCAsmBackend() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCAsmBackend<FooAsmLexer> X(TheFooTarget);
+ /// }
+ template<class MCAsmBackendImpl>
+ struct RegisterMCAsmBackend {
+ RegisterMCAsmBackend(Target &T) {
+ TargetRegistry::RegisterMCAsmBackend(T, &Allocator);
+ }
+
+ private:
+ static MCAsmBackend *Allocator(const Target &T, StringRef Triple) {
+ return new MCAsmBackendImpl(T, Triple);
+ }
+ };
+
+ /// RegisterMCAsmLexer - Helper template for registering a target specific
+ /// assembly lexer, for use in the target machine initialization
+ /// function. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooMCAsmLexer() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCAsmLexer<FooMCAsmLexer> X(TheFooTarget);
+ /// }
+ template<class MCAsmLexerImpl>
+ struct RegisterMCAsmLexer {
+ RegisterMCAsmLexer(Target &T) {
+ TargetRegistry::RegisterMCAsmLexer(T, &Allocator);
+ }
+
+ private:
+ static MCTargetAsmLexer *Allocator(const Target &T,
+ const MCRegisterInfo &MRI,
+ const MCAsmInfo &MAI) {
+ return new MCAsmLexerImpl(T, MRI, MAI);
+ }
+ };
+
+ /// RegisterMCAsmParser - Helper template for registering a target specific
+ /// assembly parser, for use in the target machine initialization
+ /// function. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooMCAsmParser() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCAsmParser<FooAsmParser> X(TheFooTarget);
+ /// }
+ template<class MCAsmParserImpl>
+ struct RegisterMCAsmParser {
+ RegisterMCAsmParser(Target &T) {
+ TargetRegistry::RegisterMCAsmParser(T, &Allocator);
+ }
+
+ private:
+ static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P) {
+ return new MCAsmParserImpl(STI, P);
+ }
+ };
+
+ /// RegisterAsmPrinter - Helper template for registering a target specific
+ /// assembly printer, for use in the target machine initialization
+ /// function. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooAsmPrinter() {
+ /// extern Target TheFooTarget;
+ /// RegisterAsmPrinter<FooAsmPrinter> X(TheFooTarget);
+ /// }
+ template<class AsmPrinterImpl>
+ struct RegisterAsmPrinter {
+ RegisterAsmPrinter(Target &T) {
+ TargetRegistry::RegisterAsmPrinter(T, &Allocator);
+ }
+
+ private:
+ static AsmPrinter *Allocator(TargetMachine &TM, MCStreamer &Streamer) {
+ return new AsmPrinterImpl(TM, Streamer);
+ }
+ };
+
+ /// RegisterMCCodeEmitter - Helper template for registering a target specific
+ /// machine code emitter, for use in the target initialization
+ /// function. Usage:
+ ///
+ /// extern "C" void LLVMInitializeFooMCCodeEmitter() {
+ /// extern Target TheFooTarget;
+ /// RegisterMCCodeEmitter<FooCodeEmitter> X(TheFooTarget);
+ /// }
+ template<class MCCodeEmitterImpl>
+ struct RegisterMCCodeEmitter {
+ RegisterMCCodeEmitter(Target &T) {
+ TargetRegistry::RegisterMCCodeEmitter(T, &Allocator);
+ }
+
+ private:
+ static MCCodeEmitter *Allocator(const MCInstrInfo &II,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new MCCodeEmitterImpl();
+ }
+ };
+
+}
+
+#endif
diff --git a/include/llvm/Support/TargetSelect.h b/include/llvm/Support/TargetSelect.h
new file mode 100644
index 0000000..83ff68c
--- /dev/null
+++ b/include/llvm/Support/TargetSelect.h
@@ -0,0 +1,154 @@
+//===- TargetSelect.h - Target Selection & Registration ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides utilities to make sure that certain classes of targets are
+// linked into the main application executable, and initialize them as
+// appropriate.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TARGETSELECT_H
+#define LLVM_SUPPORT_TARGETSELECT_H
+
+#include "llvm/Config/llvm-config.h"
+
+extern "C" {
+ // Declare all of the target-initialization functions that are available.
+#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##TargetInfo();
+#include "llvm/Config/Targets.def"
+
+#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##Target();
+#include "llvm/Config/Targets.def"
+
+ // Declare all of the target-MC-initialization functions that are available.
+#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##TargetMC();
+#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"
+
+ // Declare all of the available assembly parser initialization functions.
+#define LLVM_ASM_PARSER(TargetName) void LLVMInitialize##TargetName##AsmParser();
+#include "llvm/Config/AsmParsers.def"
+
+ // Declare all of the available disassembler initialization functions.
+#define LLVM_DISASSEMBLER(TargetName) \
+ void LLVMInitialize##TargetName##Disassembler();
+#include "llvm/Config/Disassemblers.def"
+}
+
+namespace llvm {
+ /// InitializeAllTargetInfos - The main program should call this function if
+ /// it wants access to all available 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 InitializeAllTargetInfos() {
+#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##TargetInfo();
+#include "llvm/Config/Targets.def"
+ }
+
+ /// InitializeAllTargets - The main program should call this function if it
+ /// wants access to all available target machines 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 InitializeAllTargets() {
+ // FIXME: Remove this, clients should do it.
+ InitializeAllTargetInfos();
+
+#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##Target();
+#include "llvm/Config/Targets.def"
+ }
+
+ /// 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 InitializeAllTargetMCs() {
+#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##TargetMC();
+#include "llvm/Config/Targets.def"
+ }
+
+ /// InitializeAllAsmPrinters - The main program should call this function if
+ /// it wants all asm printers that LLVM is configured to support, to make them
+ /// available via the TargetRegistry.
+ ///
+ /// It is legal for a client to make multiple calls to this function.
+ inline void InitializeAllAsmPrinters() {
+#define LLVM_ASM_PRINTER(TargetName) LLVMInitialize##TargetName##AsmPrinter();
+#include "llvm/Config/AsmPrinters.def"
+ }
+
+ /// InitializeAllAsmParsers - The main program should call this function if it
+ /// wants all asm parsers that LLVM is configured to support, to make them
+ /// available via the TargetRegistry.
+ ///
+ /// It is legal for a client to make multiple calls to this function.
+ inline void InitializeAllAsmParsers() {
+#define LLVM_ASM_PARSER(TargetName) LLVMInitialize##TargetName##AsmParser();
+#include "llvm/Config/AsmParsers.def"
+ }
+
+ /// InitializeAllDisassemblers - The main program should call this function if
+ /// it wants all disassemblers that LLVM is configured to support, to make
+ /// them available via the TargetRegistry.
+ ///
+ /// It is legal for a client to make multiple calls to this function.
+ inline void InitializeAllDisassemblers() {
+#define LLVM_DISASSEMBLER(TargetName) LLVMInitialize##TargetName##Disassembler();
+#include "llvm/Config/Disassemblers.def"
+ }
+
+ /// InitializeNativeTarget - The main program should call this function to
+ /// initialize the native target corresponding to the host. This is useful
+ /// for JIT applications to ensure that the target gets linked in correctly.
+ ///
+ /// It is legal for a client to make multiple calls to this function.
+ inline bool InitializeNativeTarget() {
+ // If we have a native target, initialize it to ensure it is linked in.
+#ifdef LLVM_NATIVE_TARGET
+ LLVM_NATIVE_TARGETINFO();
+ LLVM_NATIVE_TARGET();
+ LLVM_NATIVE_TARGETMC();
+ return false;
+#else
+ return true;
+#endif
+ }
+
+ /// InitializeNativeTargetAsmPrinter - The main program should call
+ /// this function to initialize the native target asm printer.
+ inline bool InitializeNativeTargetAsmPrinter() {
+ // If we have a native target, initialize the corresponding asm printer.
+#ifdef LLVM_NATIVE_ASMPRINTER
+ LLVM_NATIVE_ASMPRINTER();
+ return false;
+#else
+ return true;
+#endif
+ }
+
+ /// InitializeNativeTargetAsmParser - The main program should call
+ /// this function to initialize the native target asm parser.
+ inline bool InitializeNativeTargetAsmParser() {
+ // If we have a native target, initialize the corresponding asm parser.
+#ifdef LLVM_NATIVE_ASMPARSER
+ LLVM_NATIVE_ASMPARSER();
+ return false;
+#else
+ return true;
+#endif
+ }
+
+}
+
+#endif
diff --git a/include/llvm/Support/TypeBuilder.h b/include/llvm/Support/TypeBuilder.h
index 1800778..c756069 100644
--- a/include/llvm/Support/TypeBuilder.h
+++ b/include/llvm/Support/TypeBuilder.h
@@ -18,7 +18,6 @@
#include "llvm/DerivedTypes.h"
#include "llvm/LLVMContext.h"
#include <limits.h>
-#include <vector>
namespace llvm {
@@ -254,9 +253,9 @@ public:
template<typename R, typename A1, bool cross> class TypeBuilder<R(A1), cross> {
public:
static FunctionType *get(LLVMContext &Context) {
- std::vector<Type*> params;
- params.reserve(1);
- params.push_back(TypeBuilder<A1, cross>::get(Context));
+ Type *params[] = {
+ TypeBuilder<A1, cross>::get(Context),
+ };
return FunctionType::get(TypeBuilder<R, cross>::get(Context),
params, false);
}
@@ -265,10 +264,10 @@ template<typename R, typename A1, typename A2, bool cross>
class TypeBuilder<R(A1, A2), cross> {
public:
static FunctionType *get(LLVMContext &Context) {
- std::vector<Type*> params;
- params.reserve(2);
- params.push_back(TypeBuilder<A1, cross>::get(Context));
- params.push_back(TypeBuilder<A2, cross>::get(Context));
+ Type *params[] = {
+ TypeBuilder<A1, cross>::get(Context),
+ TypeBuilder<A2, cross>::get(Context),
+ };
return FunctionType::get(TypeBuilder<R, cross>::get(Context),
params, false);
}
@@ -277,11 +276,11 @@ template<typename R, typename A1, typename A2, typename A3, bool cross>
class TypeBuilder<R(A1, A2, A3), cross> {
public:
static FunctionType *get(LLVMContext &Context) {
- std::vector<Type*> params;
- params.reserve(3);
- params.push_back(TypeBuilder<A1, cross>::get(Context));
- params.push_back(TypeBuilder<A2, cross>::get(Context));
- params.push_back(TypeBuilder<A3, cross>::get(Context));
+ Type *params[] = {
+ TypeBuilder<A1, cross>::get(Context),
+ TypeBuilder<A2, cross>::get(Context),
+ TypeBuilder<A3, cross>::get(Context),
+ };
return FunctionType::get(TypeBuilder<R, cross>::get(Context),
params, false);
}
@@ -292,12 +291,12 @@ template<typename R, typename A1, typename A2, typename A3, typename A4,
class TypeBuilder<R(A1, A2, A3, A4), cross> {
public:
static FunctionType *get(LLVMContext &Context) {
- std::vector<Type*> params;
- params.reserve(4);
- params.push_back(TypeBuilder<A1, cross>::get(Context));
- params.push_back(TypeBuilder<A2, cross>::get(Context));
- params.push_back(TypeBuilder<A3, cross>::get(Context));
- params.push_back(TypeBuilder<A4, cross>::get(Context));
+ Type *params[] = {
+ TypeBuilder<A1, cross>::get(Context),
+ TypeBuilder<A2, cross>::get(Context),
+ TypeBuilder<A3, cross>::get(Context),
+ TypeBuilder<A4, cross>::get(Context),
+ };
return FunctionType::get(TypeBuilder<R, cross>::get(Context),
params, false);
}
@@ -308,13 +307,13 @@ template<typename R, typename A1, typename A2, typename A3, typename A4,
class TypeBuilder<R(A1, A2, A3, A4, A5), cross> {
public:
static FunctionType *get(LLVMContext &Context) {
- std::vector<Type*> params;
- params.reserve(5);
- params.push_back(TypeBuilder<A1, cross>::get(Context));
- params.push_back(TypeBuilder<A2, cross>::get(Context));
- params.push_back(TypeBuilder<A3, cross>::get(Context));
- params.push_back(TypeBuilder<A4, cross>::get(Context));
- params.push_back(TypeBuilder<A5, cross>::get(Context));
+ Type *params[] = {
+ TypeBuilder<A1, cross>::get(Context),
+ TypeBuilder<A2, cross>::get(Context),
+ TypeBuilder<A3, cross>::get(Context),
+ TypeBuilder<A4, cross>::get(Context),
+ TypeBuilder<A5, cross>::get(Context),
+ };
return FunctionType::get(TypeBuilder<R, cross>::get(Context),
params, false);
}
@@ -330,9 +329,9 @@ template<typename R, typename A1, bool cross>
class TypeBuilder<R(A1, ...), cross> {
public:
static FunctionType *get(LLVMContext &Context) {
- std::vector<Type*> params;
- params.reserve(1);
- params.push_back(TypeBuilder<A1, cross>::get(Context));
+ Type *params[] = {
+ TypeBuilder<A1, cross>::get(Context),
+ };
return FunctionType::get(TypeBuilder<R, cross>::get(Context), params, true);
}
};
@@ -340,10 +339,10 @@ template<typename R, typename A1, typename A2, bool cross>
class TypeBuilder<R(A1, A2, ...), cross> {
public:
static FunctionType *get(LLVMContext &Context) {
- std::vector<Type*> params;
- params.reserve(2);
- params.push_back(TypeBuilder<A1, cross>::get(Context));
- params.push_back(TypeBuilder<A2, cross>::get(Context));
+ Type *params[] = {
+ TypeBuilder<A1, cross>::get(Context),
+ TypeBuilder<A2, cross>::get(Context),
+ };
return FunctionType::get(TypeBuilder<R, cross>::get(Context),
params, true);
}
@@ -352,11 +351,11 @@ template<typename R, typename A1, typename A2, typename A3, bool cross>
class TypeBuilder<R(A1, A2, A3, ...), cross> {
public:
static FunctionType *get(LLVMContext &Context) {
- std::vector<Type*> params;
- params.reserve(3);
- params.push_back(TypeBuilder<A1, cross>::get(Context));
- params.push_back(TypeBuilder<A2, cross>::get(Context));
- params.push_back(TypeBuilder<A3, cross>::get(Context));
+ Type *params[] = {
+ TypeBuilder<A1, cross>::get(Context),
+ TypeBuilder<A2, cross>::get(Context),
+ TypeBuilder<A3, cross>::get(Context),
+ };
return FunctionType::get(TypeBuilder<R, cross>::get(Context),
params, true);
}
@@ -367,12 +366,12 @@ template<typename R, typename A1, typename A2, typename A3, typename A4,
class TypeBuilder<R(A1, A2, A3, A4, ...), cross> {
public:
static FunctionType *get(LLVMContext &Context) {
- std::vector<Type*> params;
- params.reserve(4);
- params.push_back(TypeBuilder<A1, cross>::get(Context));
- params.push_back(TypeBuilder<A2, cross>::get(Context));
- params.push_back(TypeBuilder<A3, cross>::get(Context));
- params.push_back(TypeBuilder<A4, cross>::get(Context));
+ Type *params[] = {
+ TypeBuilder<A1, cross>::get(Context),
+ TypeBuilder<A2, cross>::get(Context),
+ TypeBuilder<A3, cross>::get(Context),
+ TypeBuilder<A4, cross>::get(Context),
+ };
return FunctionType::get(TypeBuilder<R, cross>::get(Context),
params, true);
}
@@ -383,13 +382,13 @@ template<typename R, typename A1, typename A2, typename A3, typename A4,
class TypeBuilder<R(A1, A2, A3, A4, A5, ...), cross> {
public:
static FunctionType *get(LLVMContext &Context) {
- std::vector<Type*> params;
- params.reserve(5);
- params.push_back(TypeBuilder<A1, cross>::get(Context));
- params.push_back(TypeBuilder<A2, cross>::get(Context));
- params.push_back(TypeBuilder<A3, cross>::get(Context));
- params.push_back(TypeBuilder<A4, cross>::get(Context));
- params.push_back(TypeBuilder<A5, cross>::get(Context));
+ Type *params[] = {
+ TypeBuilder<A1, cross>::get(Context),
+ TypeBuilder<A2, cross>::get(Context),
+ TypeBuilder<A3, cross>::get(Context),
+ TypeBuilder<A4, cross>::get(Context),
+ TypeBuilder<A5, cross>::get(Context),
+ };
return FunctionType::get(TypeBuilder<R, cross>::get(Context),
params, true);
}
diff --git a/include/llvm/TableGen/Error.h b/include/llvm/TableGen/Error.h
new file mode 100644
index 0000000..c01b32b
--- /dev/null
+++ b/include/llvm/TableGen/Error.h
@@ -0,0 +1,43 @@
+//===- llvm/TableGen/Error.h - tblgen error handling helpers ----*- 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 error handling helper routines to pretty-print diagnostic
+// messages from tblgen.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TABLEGEN_ERROR_H
+#define LLVM_TABLEGEN_ERROR_H
+
+#include "llvm/Support/SourceMgr.h"
+
+namespace llvm {
+
+class TGError {
+ SMLoc Loc;
+ std::string Message;
+public:
+ TGError(SMLoc loc, const std::string &message) : Loc(loc), Message(message) {}
+
+ SMLoc getLoc() const { return Loc; }
+ const std::string &getMessage() const { return Message; }
+};
+
+void PrintError(SMLoc ErrorLoc, const Twine &Msg);
+void PrintError(const char *Loc, const Twine &Msg);
+void PrintError(const Twine &Msg);
+void PrintError(const TGError &Error);
+
+
+extern SourceMgr SrcMgr;
+
+
+} // end namespace "llvm"
+
+#endif
diff --git a/include/llvm/TableGen/Main.h b/include/llvm/TableGen/Main.h
new file mode 100644
index 0000000..deaef4a
--- /dev/null
+++ b/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/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h
new file mode 100644
index 0000000..afce760
--- /dev/null
+++ b/include/llvm/TableGen/Record.h
@@ -0,0 +1,1655 @@
+//===- llvm/TableGen/Record.h - Classes for Table Records -------*- 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 main TableGen data structures, including the TableGen
+// types, values, and high-level data structures.
+//
+//===----------------------------------------------------------------------===//
+
+#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"
+#include <map>
+
+namespace llvm {
+class raw_ostream;
+
+// RecTy subclasses.
+class BitRecTy;
+class BitsRecTy;
+class IntRecTy;
+class StringRecTy;
+class ListRecTy;
+class CodeRecTy;
+class DagRecTy;
+class RecordRecTy;
+
+// Init subclasses.
+class Init;
+class UnsetInit;
+class BitInit;
+class BitsInit;
+class IntInit;
+class StringInit;
+class CodeInit;
+class ListInit;
+class UnOpInit;
+class BinOpInit;
+class TernOpInit;
+class DefInit;
+class DagInit;
+class TypedInit;
+class VarInit;
+class FieldInit;
+class VarBitInit;
+class VarListElementInit;
+
+// Other classes.
+class Record;
+class RecordVal;
+struct MultiClass;
+class RecordKeeper;
+
+//===----------------------------------------------------------------------===//
+// Type Classes
+//===----------------------------------------------------------------------===//
+
+class RecTy {
+ ListRecTy *ListTy;
+public:
+ RecTy() : ListTy(0) {}
+ virtual ~RecTy() {}
+
+ virtual std::string getAsString() const = 0;
+ void print(raw_ostream &OS) const { OS << getAsString(); }
+ void dump() const;
+
+ /// typeIsConvertibleTo - Return true if all values of 'this' type can be
+ /// converted to the specified type.
+ virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0;
+
+ /// getListTy - Returns the type representing list<this>.
+ 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; }
+ virtual Init *convertValue( BitsInit *BI) { return 0; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) {
+ return convertValue((TypedInit*)UI);
+ }
+ virtual Init *convertValue( BinOpInit *UI) {
+ return convertValue((TypedInit*)UI);
+ }
+ virtual Init *convertValue( TernOpInit *UI) {
+ return convertValue((TypedInit*)UI);
+ }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( TypedInit *TI) { return 0; }
+ virtual Init *convertValue( VarInit *VI) {
+ return convertValue((TypedInit*)VI);
+ }
+ virtual Init *convertValue( FieldInit *FI) {
+ return convertValue((TypedInit*)FI);
+ }
+
+public: // These methods should only be called by subclasses of RecTy.
+ // baseClassOf - These virtual methods should be overloaded to return true iff
+ // all values of type 'RHS' can be converted to the 'this' type.
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
+ Ty.print(OS);
+ return OS;
+}
+
+
+/// 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);
+ virtual Init *convertValue( IntInit *II);
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return (Init*)VB; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const { return "bit"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const;
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+
+};
+
+
+// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
+/// BitsRecTy - 'bits&lt;n&gt;' - Represent a fixed number of bits
+///
+class BitsRecTy : public RecTy {
+ unsigned Size;
+ explicit BitsRecTy(unsigned Sz) : Size(Sz) {}
+public:
+ static BitsRecTy *get(unsigned Sz);
+
+ unsigned getNumBits() const { return Size; }
+
+ virtual Init *convertValue( UnsetInit *UI);
+ virtual Init *convertValue( BitInit *UI);
+ virtual Init *convertValue( BitsInit *BI);
+ virtual Init *convertValue( IntInit *II);
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const;
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return Size == 1; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const {
+ return RHS->Size == Size;
+ }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+
+};
+
+
+/// 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);
+ virtual Init *convertValue( IntInit *II) { return (Init*)II; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const { return "int"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+
+};
+
+/// 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; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return (Init*)SI; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( UnOpInit *BO);
+ virtual Init *convertValue( BinOpInit *BO);
+ virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
+
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const { return "string"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of
+// the specified type.
+/// ListRecTy - 'list&lt;Ty&gt;' - Represent a list of values, all of which must
+/// be of the specified type.
+///
+class ListRecTy : public RecTy {
+ RecTy *Ty;
+ 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; }
+ virtual Init *convertValue( BitInit *BI) { return 0; }
+ virtual Init *convertValue( BitsInit *BI) { return 0; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI);
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const;
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const {
+ return RHS->getElementType()->typeIsConvertibleTo(Ty);
+ }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+/// 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; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return (Init*)CI; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const { return "code"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+/// 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; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( DefInit *DI) { return 0; }
+ virtual Init *convertValue( UnOpInit *BO);
+ virtual Init *convertValue( BinOpInit *BO);
+ virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
+ virtual Init *convertValue( DagInit *CI) { return (Init*)CI; }
+ virtual Init *convertValue( TypedInit *TI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const { return "dag"; }
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return true; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
+};
+
+
+/// RecordRecTy - '[classname]' - Represent an instance of a class, such as:
+/// (R32 X = EAX).
+///
+class RecordRecTy : public RecTy {
+ Record *Rec;
+ explicit RecordRecTy(Record *R) : Rec(R) {}
+ friend class Record;
+public:
+ static RecordRecTy *get(Record *R);
+
+ Record *getRecord() const { return Rec; }
+
+ virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
+ virtual Init *convertValue( BitInit *BI) { return 0; }
+ virtual Init *convertValue( BitsInit *BI) { return 0; }
+ virtual Init *convertValue( IntInit *II) { return 0; }
+ virtual Init *convertValue(StringInit *SI) { return 0; }
+ virtual Init *convertValue( ListInit *LI) { return 0; }
+ virtual Init *convertValue( CodeInit *CI) { return 0; }
+ virtual Init *convertValue(VarBitInit *VB) { return 0; }
+ virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
+ virtual Init *convertValue( DefInit *DI);
+ virtual Init *convertValue( DagInit *DI) { return 0; }
+ virtual Init *convertValue( TypedInit *VI);
+ virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
+ virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
+
+ std::string getAsString() const;
+
+ bool typeIsConvertibleTo(const RecTy *RHS) const {
+ return RHS->baseClassOf(this);
+ }
+ virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
+ virtual bool baseClassOf(const RecordRecTy *RHS) const;
+};
+
+/// resolveTypes - Find a common type that T1 and T2 convert to.
+/// Return 0 if no such type exists.
+///
+RecTy *resolveTypes(RecTy *T1, RecTy *T2);
+
+//===----------------------------------------------------------------------===//
+// Initializer Classes
+//===----------------------------------------------------------------------===//
+
+class Init {
+ Init(const Init &); // Do not define.
+ Init &operator=(const Init &); // Do not define.
+
+protected:
+ Init(void) {}
+
+public:
+ virtual ~Init() {}
+
+ /// isComplete - This virtual method should be overridden by values that may
+ /// not be completely specified yet.
+ virtual bool isComplete() const { return true; }
+
+ /// print - Print out this value.
+ void print(raw_ostream &OS) const { OS << getAsString(); }
+
+ /// 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.
+ void dump() const;
+
+ /// convertInitializerTo - This virtual function is a simple call-back
+ /// function that should be overridden to call the appropriate
+ /// RecTy::convertValue method.
+ ///
+ 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<unsigned> &Bits) const {
+ return 0;
+ }
+
+ /// convertInitListSlice - This method is used to implement the list slice
+ /// selection operator. Given an initializer, it selects the specified list
+ /// 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<unsigned> &Elements) const {
+ return 0;
+ }
+
+ /// getFieldType - This method is used to implement the FieldInit class.
+ /// Implementors of this method should return the type of the named field if
+ /// they are of record type.
+ ///
+ virtual RecTy *getFieldType(const std::string &FieldName) const { return 0; }
+
+ /// getFieldInit - This method complements getFieldType to return the
+ /// initializer for the specified field. If getFieldType returns non-null
+ /// this method should return non-null, otherwise it returns null.
+ ///
+ virtual Init *getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const {
+ return 0;
+ }
+
+ /// resolveReferences - This method is used by classes that refer to other
+ /// variables which may not be defined at the time the expression is formed.
+ /// 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) const {
+ return const_cast<Init *>(this);
+ }
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
+ I.print(OS); return OS;
+}
+
+/// TypedInit - This is the common super-class of types that have a specific,
+/// explicit, type.
+///
+class TypedInit : public Init {
+ RecTy *Ty;
+
+ 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<unsigned> &Bits) const;
+ virtual Init *
+ convertInitListSlice(const std::vector<unsigned> &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
+ /// they are of record type.
+ ///
+ virtual RecTy *getFieldType(const std::string &FieldName) const;
+
+ /// 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) 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) 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:
+ static UnsetInit *get();
+
+ virtual Init *convertInitializerTo(RecTy *Ty) const {
+ return Ty->convertValue(const_cast<UnsetInit *>(this));
+ }
+
+ virtual bool isComplete() const { return false; }
+ virtual std::string getAsString() const { return "?"; }
+};
+
+
+/// BitInit - true/false - Represent a concrete initializer for a bit.
+///
+class BitInit : public Init {
+ bool Value;
+
+ 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) const {
+ return Ty->convertValue(const_cast<BitInit *>(this));
+ }
+
+ virtual std::string getAsString() const { return Value ? "1" : "0"; }
+};
+
+/// 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, public FoldingSetNode {
+ std::vector<Init*> Bits;
+
+ BitsInit(ArrayRef<Init *> Range) : Bits(Range.begin(), Range.end()) {}
+
+ BitsInit(const BitsInit &Other); // Do not define.
+ BitsInit &operator=(const BitsInit &Other); // Do not define.
+
+public:
+ static BitsInit *get(ArrayRef<Init *> Range);
+
+ void Profile(FoldingSetNodeID &ID) const;
+
+ unsigned getNumBits() const { return Bits.size(); }
+
+ Init *getBit(unsigned Bit) const {
+ assert(Bit < Bits.size() && "Bit index out of range!");
+ return Bits[Bit];
+ }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) const {
+ return Ty->convertValue(const_cast<BitsInit *>(this));
+ }
+ virtual Init *
+ convertInitializerBitRange(const std::vector<unsigned> &Bits) const;
+
+ virtual bool isComplete() const {
+ for (unsigned i = 0; i != getNumBits(); ++i)
+ if (!getBit(i)->isComplete()) return false;
+ return true;
+ }
+ bool allInComplete() const {
+ for (unsigned i = 0; i != getNumBits(); ++i)
+ if (getBit(i)->isComplete()) return false;
+ return true;
+ }
+ virtual std::string getAsString() const;
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
+};
+
+
+/// IntInit - 7 - Represent an initalization by a literal integer value.
+///
+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:
+ static IntInit *get(int64_t V);
+
+ int64_t getValue() const { return Value; }
+
+ virtual Init *convertInitializerTo(RecTy *Ty) const {
+ return Ty->convertValue(const_cast<IntInit *>(this));
+ }
+ virtual Init *
+ convertInitializerBitRange(const std::vector<unsigned> &Bits) const;
+
+ virtual std::string getAsString() const;
+
+ /// 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) const {
+ assert(0 && "Illegal bit reference off int");
+ return 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) const {
+ assert(0 && "Illegal element reference off int");
+ return 0;
+ }
+};
+
+
+/// StringInit - "foo" - Represent an initialization by a string value.
+///
+class StringInit : public TypedInit {
+ std::string Value;
+
+ explicit StringInit(const std::string &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) const {
+ return Ty->convertValue(const_cast<StringInit *>(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) const {
+ assert(0 && "Illegal bit reference off string");
+ return 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) const {
+ assert(0 && "Illegal element reference off string");
+ return 0;
+ }
+};
+
+/// CodeInit - "[{...}]" - Represent a code fragment.
+///
+class CodeInit : public Init {
+ std::string Value;
+
+ 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) const {
+ return Ty->convertValue(const_cast<CodeInit *>(this));
+ }
+
+ virtual std::string getAsString() const { return "[{" + Value + "}]"; }
+};
+
+/// ListInit - [AL, AH, CL] - Represent a list of defs
+///
+class ListInit : public TypedInit, public FoldingSetNode {
+ std::vector<Init*> Values;
+public:
+ typedef std::vector<Init*>::const_iterator const_iterator;
+
+private:
+ explicit ListInit(ArrayRef<Init *> 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<Init *> Range, RecTy *EltTy);
+
+ void Profile(FoldingSetNodeID &ID) const;
+
+ unsigned getSize() const { return Values.size(); }
+ Init *getElement(unsigned i) const {
+ assert(i < Values.size() && "List element index out of range!");
+ return Values[i];
+ }
+
+ Record *getElementAsRecord(unsigned i) const;
+
+ Init *convertInitListSlice(const std::vector<unsigned> &Elements) const;
+
+ virtual Init *convertInitializerTo(RecTy *Ty) const {
+ return Ty->convertValue(const_cast<ListInit *>(this));
+ }
+
+ /// resolveReferences - This method is used by classes that refer to other
+ /// variables which may not be defined at the time they expression is formed.
+ /// 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) const;
+
+ virtual std::string getAsString() const;
+
+ ArrayRef<Init*> getValues() const { return Values; }
+
+ inline const_iterator begin() const { return Values.begin(); }
+ inline const_iterator end () const { return Values.end(); }
+
+ inline size_t size () const { return Values.size(); }
+ inline bool empty() const { return Values.empty(); }
+
+ /// 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) const {
+ assert(0 && "Illegal bit reference off list");
+ return 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) const;
+};
+
+
+/// OpInit - Base class for operators
+///
+class OpInit : public TypedInit {
+ 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<Init *> &Operands) const = 0;
+
+ virtual int getNumOperands() const = 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) const = 0;
+
+ virtual Init *convertInitializerTo(RecTy *Ty) const {
+ return Ty->convertValue(const_cast<OpInit *>(this));
+ }
+
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) const;
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) const;
+};
+
+
+/// UnOpInit - !op (X) - Transform an init.
+///
+class UnOpInit : public OpInit {
+public:
+ enum UnaryOp { CAST, HEAD, TAIL, EMPTY };
+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:
+ static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type);
+
+ // Clone - Clone this operator, replacing arguments with the new list
+ virtual OpInit *clone(std::vector<Init *> &Operands) const {
+ assert(Operands.size() == 1 &&
+ "Wrong number of operands for unary operation");
+ return UnOpInit::get(getOpcode(), *Operands.begin(), getType());
+ }
+
+ int getNumOperands() const { return 1; }
+ Init *getOperand(int i) const {
+ assert(i == 0 && "Invalid operand id for unary operator");
+ return getOperand();
+ }
+
+ UnaryOp getOpcode() const { return Opc; }
+ Init *getOperand() const { return LHS; }
+
+ // Fold - If possible, fold this to a simpler init. Return this if not
+ // possible to fold.
+ Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const;
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
+
+ virtual std::string getAsString() const;
+};
+
+/// BinOpInit - !op (X, Y) - Combine two inits.
+///
+class BinOpInit : public OpInit {
+public:
+ enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, EQ };
+private:
+ BinaryOp Opc;
+ Init *LHS, *RHS;
+
+ BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
+ 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<Init *> &Operands) const {
+ assert(Operands.size() == 2 &&
+ "Wrong number of operands for binary operation");
+ return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType());
+ }
+
+ int getNumOperands() const { return 2; }
+ Init *getOperand(int i) const {
+ assert((i == 0 || i == 1) && "Invalid operand id for binary operator");
+ if (i == 0) {
+ return getLHS();
+ } else {
+ return getRHS();
+ }
+ }
+
+ BinaryOp getOpcode() const { return Opc; }
+ Init *getLHS() const { return LHS; }
+ Init *getRHS() const { return RHS; }
+
+ // Fold - If possible, fold this to a simpler init. Return this if not
+ // possible to fold.
+ Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const;
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
+
+ virtual std::string getAsString() const;
+};
+
+/// TernOpInit - !op (X, Y, Z) - Combine two inits.
+///
+class TernOpInit : public OpInit {
+public:
+ enum TernaryOp { SUBST, FOREACH, IF };
+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:
+ 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<Init *> &Operands) const {
+ assert(Operands.size() == 3 &&
+ "Wrong number of operands for ternary operation");
+ return TernOpInit::get(getOpcode(), Operands[0], Operands[1], Operands[2],
+ getType());
+ }
+
+ int getNumOperands() const { return 3; }
+ Init *getOperand(int i) const {
+ assert((i == 0 || i == 1 || i == 2) &&
+ "Invalid operand id for ternary operator");
+ if (i == 0) {
+ return getLHS();
+ } else if (i == 1) {
+ return getMHS();
+ } else {
+ return getRHS();
+ }
+ }
+
+ TernaryOp getOpcode() const { return Opc; }
+ Init *getLHS() const { return LHS; }
+ Init *getMHS() const { return MHS; }
+ Init *getRHS() const { return RHS; }
+
+ // Fold - If possible, fold this to a simpler init. Return this if not
+ // possible to fold.
+ Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const;
+
+ virtual bool isComplete() const { return false; }
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
+
+ virtual std::string getAsString() const;
+};
+
+
+/// VarInit - 'Opcode' - Represent a reference to an entire variable object.
+///
+class VarInit : public TypedInit {
+ std::string VarName;
+
+ explicit VarInit(const std::string &VN, RecTy *T)
+ : 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) const {
+ return Ty->convertValue(const_cast<VarInit *>(this));
+ }
+
+ const std::string &getName() const { return VarName; }
+
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) const;
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) const;
+
+ virtual RecTy *getFieldType(const std::string &FieldName) const;
+ virtual Init *getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const;
+
+ /// resolveReferences - This method is used by classes that refer to other
+ /// variables which may not be defined at the time they expression is formed.
+ /// 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) const;
+
+ virtual std::string getAsString() const { return VarName; }
+};
+
+
+/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field.
+///
+class VarBitInit : public Init {
+ TypedInit *TI;
+ unsigned Bit;
+
+ VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) {
+ assert(T->getType() && dynamic_cast<BitsRecTy*>(T->getType()) &&
+ ((BitsRecTy*)T->getType())->getNumBits() > B &&
+ "Illegal VarBitInit expression!");
+ }
+
+ 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<VarBitInit *>(this));
+ }
+
+ TypedInit *getVariable() const { return TI; }
+ unsigned getBitNum() const { return Bit; }
+
+ virtual std::string getAsString() const;
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
+};
+
+/// VarListElementInit - List[4] - Represent access to one element of a var or
+/// field.
+class VarListElementInit : public TypedInit {
+ TypedInit *TI;
+ unsigned Element;
+
+ VarListElementInit(TypedInit *T, unsigned E)
+ : TypedInit(dynamic_cast<ListRecTy*>(T->getType())->getElementType()),
+ TI(T), Element(E) {
+ assert(T->getType() && dynamic_cast<ListRecTy*>(T->getType()) &&
+ "Illegal VarBitInit expression!");
+ }
+
+ 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<VarListElementInit *>(this));
+ }
+
+ TypedInit *getVariable() const { return TI; }
+ unsigned getElementNum() const { return Element; }
+
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ 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) const;
+
+ virtual std::string getAsString() const;
+ 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:
+ static DefInit *get(Record*);
+
+ virtual Init *convertInitializerTo(RecTy *Ty) const {
+ return Ty->convertValue(const_cast<DefInit *>(this));
+ }
+
+ Record *getDef() const { return Def; }
+
+ //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
+
+ virtual RecTy *getFieldType(const std::string &FieldName) const;
+ virtual Init *getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const;
+
+ virtual std::string getAsString() const;
+
+ /// 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) const {
+ assert(0 && "Illegal bit reference off def");
+ return 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) const {
+ assert(0 && "Illegal element reference off def");
+ return 0;
+ }
+};
+
+
+/// FieldInit - X.Y - Represent a reference to a subfield of a variable
+///
+class FieldInit : public TypedInit {
+ Init *Rec; // Record we are referring to
+ std::string FieldName; // Field we are accessing
+
+ FieldInit(Init *R, const std::string &FN)
+ : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) {
+ assert(getType() && "FieldInit with non-record type!");
+ }
+
+ 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<FieldInit *>(this));
+ }
+
+ virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
+ unsigned Bit) const;
+ virtual Init *resolveListElementReference(Record &R,
+ const RecordVal *RV,
+ unsigned Elt) const;
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
+
+ virtual std::string getAsString() const {
+ return Rec->getAsString() + "." + FieldName;
+ }
+};
+
+/// DagInit - (v a, b) - Represent a DAG tree value. DAG inits are required
+/// 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, public FoldingSetNode {
+ Init *Val;
+ std::string ValName;
+ std::vector<Init*> Args;
+ std::vector<std::string> ArgNames;
+
+ DagInit(Init *V, const std::string &VN,
+ ArrayRef<Init *> ArgRange,
+ ArrayRef<std::string> 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:
+ static DagInit *get(Init *V, const std::string &VN,
+ ArrayRef<Init *> ArgRange,
+ ArrayRef<std::string> NameRange);
+ static DagInit *get(Init *V, const std::string &VN,
+ const std::vector<
+ std::pair<Init*, std::string> > &args);
+
+ void Profile(FoldingSetNodeID &ID) const;
+
+ virtual Init *convertInitializerTo(RecTy *Ty) const {
+ return Ty->convertValue(const_cast<DagInit *>(this));
+ }
+
+ Init *getOperator() const { return Val; }
+
+ const std::string &getName() const { return ValName; }
+
+ unsigned getNumArgs() const { return Args.size(); }
+ Init *getArg(unsigned Num) const {
+ assert(Num < Args.size() && "Arg number out of range!");
+ return Args[Num];
+ }
+ const std::string &getArgName(unsigned Num) const {
+ assert(Num < ArgNames.size() && "Arg number out of range!");
+ return ArgNames[Num];
+ }
+
+ virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
+
+ virtual std::string getAsString() const;
+
+ typedef std::vector<Init*>::const_iterator const_arg_iterator;
+ typedef std::vector<std::string>::const_iterator const_name_iterator;
+
+ inline const_arg_iterator arg_begin() const { return Args.begin(); }
+ 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 const_name_iterator name_begin() const { return ArgNames.begin(); }
+ 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) const {
+ assert(0 && "Illegal bit reference off dag");
+ return 0;
+ }
+
+ virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) const {
+ assert(0 && "Illegal element reference off dag");
+ return 0;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// High-Level Classes
+//===----------------------------------------------------------------------===//
+
+class RecordVal {
+ 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;
+
+ unsigned getPrefix() const { return Prefix; }
+ RecTy *getType() const { return Ty; }
+ Init *getValue() const { return Value; }
+
+ bool setValue(Init *V) {
+ if (V) {
+ Value = V->convertInitializerTo(Ty);
+ return Value == 0;
+ }
+ Value = 0;
+ return false;
+ }
+
+ void dump() const;
+ void print(raw_ostream &OS, bool PrintSem = true) const;
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) {
+ RV.print(OS << " ");
+ return OS;
+}
+
+class Record {
+ static unsigned LastID;
+
+ // Unique record ID.
+ unsigned ID;
+ Init *Name;
+ SMLoc Loc;
+ std::vector<std::string> TemplateArgs;
+ std::vector<RecordVal> Values;
+ std::vector<Record*> SuperClasses;
+
+ // 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(StringInit::get(N)), Loc(loc), TrackedRecords(records), TheInit(0) {}
+ ~Record() {}
+
+
+ static unsigned getNewUID() { return LastID++; }
+
+
+ unsigned getID() const { return ID; }
+
+ 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<std::string> &getTemplateArgs() const {
+ return TemplateArgs;
+ }
+ const std::vector<RecordVal> &getValues() const { return Values; }
+ const std::vector<Record*> &getSuperClasses() const { return SuperClasses; }
+
+ bool isTemplateArg(StringRef Name) const {
+ for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i)
+ if (TemplateArgs[i] == Name) return true;
+ return false;
+ }
+
+ const RecordVal *getValue(StringRef Name) const {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) return &Values[i];
+ return 0;
+ }
+ RecordVal *getValue(StringRef Name) {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) return &Values[i];
+ return 0;
+ }
+
+ void addTemplateArg(StringRef Name) {
+ assert(!isTemplateArg(Name) && "Template arg already defined!");
+ TemplateArgs.push_back(Name);
+ }
+
+ void addValue(const RecordVal &RV) {
+ assert(getValue(RV.getName()) == 0 && "Value already added!");
+ Values.push_back(RV);
+ }
+
+ void removeValue(StringRef Name) {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ if (Values[i].getName() == Name) {
+ Values.erase(Values.begin()+i);
+ return;
+ }
+ assert(0 && "Cannot remove an entry that does not exist!");
+ }
+
+ bool isSubClassOf(const Record *R) const {
+ for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
+ if (SuperClasses[i] == R)
+ return true;
+ return false;
+ }
+
+ bool isSubClassOf(StringRef Name) const {
+ for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
+ if (SuperClasses[i]->getName() == Name)
+ return true;
+ return false;
+ }
+
+ void addSuperClass(Record *R) {
+ assert(!isSubClassOf(R) && "Already subclassing record!");
+ SuperClasses.push_back(R);
+ }
+
+ /// resolveReferences - If there are any field references that refer to fields
+ /// that have been filled in, we can propagate the values now.
+ ///
+ void resolveReferences() { resolveReferencesTo(0); }
+
+ /// resolveReferencesTo - If anything in this record refers to RV, replace the
+ /// reference to RV with the RHS of RV. If RV is null, we resolve all
+ /// possible references.
+ void resolveReferencesTo(const RecordVal *RV);
+
+ RecordKeeper &getRecords() const {
+ return TrackedRecords;
+ }
+
+ void dump() const;
+
+ //===--------------------------------------------------------------------===//
+ // High-level methods useful to tablegen back-ends
+ //
+
+ /// getValueInit - Return the initializer for a value with the specified name,
+ /// or throw an exception if the field does not exist.
+ ///
+ Init *getValueInit(StringRef FieldName) const;
+
+ /// getValueAsString - This method looks up the specified field and returns
+ /// its value as a string, throwing an exception if the field does not exist
+ /// or if the value is not a string.
+ ///
+ std::string getValueAsString(StringRef FieldName) const;
+
+ /// getValueAsBitsInit - This method looks up the specified field and returns
+ /// its value as a BitsInit, throwing an exception if the field does not exist
+ /// or if the value is not the right type.
+ ///
+ BitsInit *getValueAsBitsInit(StringRef FieldName) const;
+
+ /// getValueAsListInit - This method looks up the specified field and returns
+ /// its value as a ListInit, throwing an exception if the field does not exist
+ /// or if the value is not the right type.
+ ///
+ ListInit *getValueAsListInit(StringRef FieldName) const;
+
+ /// getValueAsListOfDefs - This method looks up the specified field and
+ /// returns its value as a vector of records, throwing an exception if the
+ /// field does not exist or if the value is not the right type.
+ ///
+ std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const;
+
+ /// getValueAsListOfInts - This method looks up the specified field and
+ /// returns its value as a vector of integers, throwing an exception if the
+ /// field does not exist or if the value is not the right type.
+ ///
+ std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
+
+ /// getValueAsListOfStrings - This method looks up the specified field and
+ /// returns its value as a vector of strings, throwing an exception if the
+ /// field does not exist or if the value is not the right type.
+ ///
+ std::vector<std::string> getValueAsListOfStrings(StringRef FieldName) const;
+
+ /// getValueAsDef - This method looks up the specified field and returns its
+ /// value as a Record, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ Record *getValueAsDef(StringRef FieldName) const;
+
+ /// getValueAsBit - This method looks up the specified field and returns its
+ /// value as a bit, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ bool getValueAsBit(StringRef FieldName) const;
+
+ /// getValueAsInt - This method looks up the specified field and returns its
+ /// value as an int64_t, throwing an exception if the field does not exist or
+ /// if the value is not the right type.
+ ///
+ int64_t getValueAsInt(StringRef FieldName) const;
+
+ /// getValueAsDag - This method looks up the specified field and returns its
+ /// value as an Dag, throwing an exception if the field does not exist or if
+ /// the value is not the right type.
+ ///
+ DagInit *getValueAsDag(StringRef FieldName) const;
+
+ /// getValueAsCode - This method looks up the specified field and returns
+ /// its value as the string data in a CodeInit, throwing an exception if the
+ /// field does not exist or if the value is not a code object.
+ ///
+ std::string getValueAsCode(StringRef FieldName) const;
+};
+
+raw_ostream &operator<<(raw_ostream &OS, const Record &R);
+
+struct MultiClass {
+ Record Rec; // Placeholder for template args and Name.
+ typedef std::vector<Record*> RecordVector;
+ RecordVector DefPrototypes;
+
+ void dump() const;
+
+ MultiClass(const std::string &Name, SMLoc Loc, RecordKeeper &Records) :
+ Rec(Name, Loc, Records) {}
+};
+
+class RecordKeeper {
+ std::map<std::string, Record*> Classes, Defs;
+public:
+ ~RecordKeeper() {
+ for (std::map<std::string, Record*>::iterator I = Classes.begin(),
+ E = Classes.end(); I != E; ++I)
+ delete I->second;
+ for (std::map<std::string, Record*>::iterator I = Defs.begin(),
+ E = Defs.end(); I != E; ++I)
+ delete I->second;
+ }
+
+ const std::map<std::string, Record*> &getClasses() const { return Classes; }
+ const std::map<std::string, Record*> &getDefs() const { return Defs; }
+
+ Record *getClass(const std::string &Name) const {
+ std::map<std::string, Record*>::const_iterator I = Classes.find(Name);
+ return I == Classes.end() ? 0 : I->second;
+ }
+ Record *getDef(const std::string &Name) const {
+ std::map<std::string, Record*>::const_iterator I = Defs.find(Name);
+ return I == Defs.end() ? 0 : I->second;
+ }
+ void addClass(Record *R) {
+ assert(getClass(R->getName()) == 0 && "Class already exists!");
+ Classes.insert(std::make_pair(R->getName(), R));
+ }
+ void addDef(Record *R) {
+ assert(getDef(R->getName()) == 0 && "Def already exists!");
+ Defs.insert(std::make_pair(R->getName(), R));
+ }
+
+ /// removeClass - Remove, but do not delete, the specified record.
+ ///
+ void removeClass(const std::string &Name) {
+ assert(Classes.count(Name) && "Class does not exist!");
+ Classes.erase(Name);
+ }
+ /// removeDef - Remove, but do not delete, the specified record.
+ ///
+ void removeDef(const std::string &Name) {
+ assert(Defs.count(Name) && "Def does not exist!");
+ Defs.erase(Name);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // High-level helper methods, useful for tablegen backends...
+
+ /// getAllDerivedDefinitions - This method returns all concrete definitions
+ /// that derive from the specified class name. If a class with the specified
+ /// name does not exist, an exception is thrown.
+ std::vector<Record*>
+ getAllDerivedDefinitions(const std::string &ClassName) const;
+
+ void dump() const;
+};
+
+/// LessRecord - Sorting predicate to sort record pointers by name.
+///
+struct LessRecord {
+ bool operator()(const Record *Rec1, const Record *Rec2) const {
+ return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0;
+ }
+};
+
+/// LessRecordFieldName - Sorting predicate to sort record pointers by their
+/// name field.
+///
+struct LessRecordFieldName {
+ bool operator()(const Record *Rec1, const Record *Rec2) const {
+ return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
+ }
+};
+
+raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK);
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/TableGen/TableGenAction.h b/include/llvm/TableGen/TableGenAction.h
new file mode 100644
index 0000000..9f1c23c
--- /dev/null
+++ b/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/include/llvm/TableGen/TableGenBackend.h b/include/llvm/TableGen/TableGenBackend.h
new file mode 100644
index 0000000..853f92e
--- /dev/null
+++ b/include/llvm/TableGen/TableGenBackend.h
@@ -0,0 +1,43 @@
+//===- llvm/TableGen/TableGenBackend.h - Backend base class -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The TableGenBackend class is provided as a common interface for all TableGen
+// backends. It provides useful services and an standardized interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TABLEGEN_TABLEGENBACKEND_H
+#define LLVM_TABLEGEN_TABLEGENBACKEND_H
+
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace llvm {
+
+class Record;
+class RecordKeeper;
+
+struct TableGenBackend {
+ virtual ~TableGenBackend() {}
+
+ // run - All TableGen backends should implement the run method, which should
+ // be the main entry point.
+ virtual void run(raw_ostream &OS) = 0;
+
+
+public: // Useful helper routines...
+ /// EmitSourceFileHeader - Output a LLVM style file header to the specified
+ /// ostream.
+ void EmitSourceFileHeader(const std::string &Desc, raw_ostream &OS) const;
+
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index 018ccbd..aa9a4f5 100644
--- a/include/llvm/Target/Target.td
+++ b/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/include/llvm/Target/TargetAsmBackend.h b/include/llvm/Target/TargetAsmBackend.h
deleted file mode 100644
index 2111f6b..0000000
--- a/include/llvm/Target/TargetAsmBackend.h
+++ /dev/null
@@ -1,131 +0,0 @@
-//===-- llvm/Target/TargetAsmBackend.h - Target Asm Backend -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TARGET_TARGETASMBACKEND_H
-#define LLVM_TARGET_TARGETASMBACKEND_H
-
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCFixup.h"
-#include "llvm/MC/MCFixupKindInfo.h"
-#include "llvm/Support/DataTypes.h"
-
-namespace llvm {
-class MCELFObjectTargetWriter;
-class MCFixup;
-class MCInst;
-class MCObjectWriter;
-class MCSection;
-template<typename T>
-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
-protected: // Can only create subclasses.
- TargetAsmBackend();
-
- unsigned HasReliableSymbolDifference : 1;
-
-public:
- virtual ~TargetAsmBackend();
-
- /// createObjectWriter - Create a new MCObjectWriter instance for use by the
- /// assembler backend to emit the final object file.
- virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0;
-
- /// createELFObjectTargetWriter - Create a new ELFObjectTargetWriter to enable
- /// non-standard ELFObjectWriters.
- virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const {
- assert(0 && "createELFObjectTargetWriter is not supported by asm backend");
- return 0;
- }
-
- /// hasReliableSymbolDifference - Check whether this target implements
- /// accurate relocations for differences between symbols. If not, differences
- /// between symbols will always be relocatable expressions and any references
- /// to temporary symbols will be assumed to be in the same atom, unless they
- /// reside in a different section.
- ///
- /// This should always be true (since it results in fewer relocations with no
- /// loss of functionality), but is currently supported as a way to maintain
- /// exact object compatibility with Darwin 'as' (on non-x86_64). It should
- /// eventually should be eliminated.
- bool hasReliableSymbolDifference() const {
- return HasReliableSymbolDifference;
- }
-
- /// doesSectionRequireSymbols - Check whether the given section requires that
- /// all symbols (even temporaries) have symbol table entries.
- virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
- return false;
- }
-
- /// isSectionAtomizable - Check whether the given section can be split into
- /// atoms.
- ///
- /// \see MCAssembler::isSymbolLinkerVisible().
- virtual bool isSectionAtomizable(const MCSection &Section) const {
- return true;
- }
-
- /// @name Target Fixup Interfaces
- /// @{
-
- /// getNumFixupKinds - Get the number of target specific fixup kinds.
- virtual unsigned getNumFixupKinds() const = 0;
-
- /// getFixupKindInfo - Get information on a fixup kind.
- virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const;
-
- /// @}
-
- /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided
- /// data fragment, at the offset specified by the fixup and following the
- /// fixup kind as appropriate.
- virtual void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
- uint64_t Value) const = 0;
-
- /// @}
-
- /// @name Target Relaxation Interfaces
- /// @{
-
- /// MayNeedRelaxation - Check whether the given instruction may need
- /// relaxation.
- ///
- /// \param Inst - The instruction to test.
- virtual bool MayNeedRelaxation(const MCInst &Inst) const = 0;
-
- /// RelaxInstruction - Relax the instruction in the given fragment to the next
- /// wider instruction.
- ///
- /// \param Inst - The instruction to relax, which may be the same as the
- /// output.
- /// \parm Res [output] - On return, the relaxed instruction.
- virtual void RelaxInstruction(const MCInst &Inst, MCInst &Res) const = 0;
-
- /// @}
-
- /// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given
- /// output. If the target cannot generate such a sequence, it should return an
- /// error.
- ///
- /// \return - True on success.
- virtual bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const = 0;
-
- /// HandleAssemblerFlag - Handle any target-specific assembler flags.
- /// By default, do nothing.
- virtual void HandleAssemblerFlag(MCAssemblerFlag Flag) {}
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h
deleted file mode 100644
index 5a526dc..0000000
--- a/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 <typename T> class ArrayRef;
- class MCSection;
- class MCContext;
- class MachineFunction;
- class TargetMachine;
- class TargetLoweringObjectFile;
-
-class TargetAsmInfo {
- std::vector<MachineMove> 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<MCCFIInstruction> 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<MachineMove> &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/include/llvm/Target/TargetAsmLexer.h b/include/llvm/Target/TargetAsmLexer.h
deleted file mode 100644
index 9fcf449..0000000
--- a/include/llvm/Target/TargetAsmLexer.h
+++ /dev/null
@@ -1,89 +0,0 @@
-//===-- llvm/Target/TargetAsmLexer.h - Target Assembly Lexer ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TARGET_TARGETASMLEXER_H
-#define LLVM_TARGET_TARGETASMLEXER_H
-
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-
-namespace llvm {
-class Target;
-
-/// TargetAsmLexer - Generic interface to target specific assembly lexers.
-class TargetAsmLexer {
- /// The current token
- AsmToken CurTok;
-
- /// The location and description of the current error
- SMLoc ErrLoc;
- std::string Err;
-
- TargetAsmLexer(const TargetAsmLexer &); // DO NOT IMPLEMENT
- void operator=(const TargetAsmLexer &); // DO NOT IMPLEMENT
-protected: // Can only create subclasses.
- TargetAsmLexer(const Target &);
-
- virtual AsmToken LexToken() = 0;
-
- void SetError(const SMLoc &errLoc, const std::string &err) {
- ErrLoc = errLoc;
- Err = err;
- }
-
- /// TheTarget - The Target that this machine was created for.
- const Target &TheTarget;
- MCAsmLexer *Lexer;
-
-public:
- virtual ~TargetAsmLexer();
-
- const Target &getTarget() const { return TheTarget; }
-
- /// InstallLexer - Set the lexer to get tokens from lower-level lexer \arg L.
- void InstallLexer(MCAsmLexer &L) {
- Lexer = &L;
- }
-
- MCAsmLexer *getLexer() {
- return Lexer;
- }
-
- /// Lex - Consume the next token from the input stream and return it.
- const AsmToken &Lex() {
- return CurTok = LexToken();
- }
-
- /// getTok - Get the current (last) lexed token.
- const AsmToken &getTok() {
- return CurTok;
- }
-
- /// getErrLoc - Get the current error location
- const SMLoc &getErrLoc() {
- return ErrLoc;
- }
-
- /// getErr - Get the current error string
- const std::string &getErr() {
- return Err;
- }
-
- /// getKind - Get the kind of current token.
- AsmToken::TokenKind getKind() const { return CurTok.getKind(); }
-
- /// is - Check if the current token has kind \arg K.
- bool is(AsmToken::TokenKind K) const { return CurTok.is(K); }
-
- /// isNot - Check if the current token has kind \arg K.
- bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); }
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/Target/TargetAsmParser.h b/include/llvm/Target/TargetAsmParser.h
deleted file mode 100644
index df84231..0000000
--- a/include/llvm/Target/TargetAsmParser.h
+++ /dev/null
@@ -1,85 +0,0 @@
-//===-- llvm/Target/TargetAsmParser.h - Target Assembly Parser --*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TARGET_TARGETPARSER_H
-#define LLVM_TARGET_TARGETPARSER_H
-
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-
-namespace llvm {
-class MCStreamer;
-class StringRef;
-class SMLoc;
-class AsmToken;
-class MCParsedAsmOperand;
-template <typename T> 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
-protected: // Can only create subclasses.
- TargetAsmParser();
-
- /// AvailableFeatures - The current set of available features.
- unsigned AvailableFeatures;
-
-public:
- virtual ~TargetAsmParser();
-
- unsigned getAvailableFeatures() const { return AvailableFeatures; }
- void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; }
-
- virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
- SMLoc &EndLoc) = 0;
-
- /// ParseInstruction - Parse one assembly instruction.
- ///
- /// The parser is positioned following the instruction name. The target
- /// specific instruction parser should parse the entire instruction and
- /// construct the appropriate MCInst, or emit an error. On success, the entire
- /// line should be parsed up to and including the end-of-statement token. On
- /// failure, the parser is not required to read to the end of the line.
- //
- /// \param Name - The instruction name.
- /// \param NameLoc - The source location of the name.
- /// \param Operands [out] - The list of parsed operands, this returns
- /// ownership of them to the caller.
- /// \return True on failure.
- virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
- SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0;
-
- /// ParseDirective - Parse a target specific assembler directive
- ///
- /// The parser is positioned following the directive name. The target
- /// specific directive parser should parse the entire directive doing or
- /// recording any target specific work, or return true and do nothing if the
- /// directive is not target specific. If the directive is specific for
- /// the target, the entire line is parsed up to and including the
- /// end-of-statement token and false is returned.
- ///
- /// \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
- MatchAndEmitInstruction(SMLoc IDLoc,
- SmallVectorImpl<MCParsedAsmOperand*> &Operands,
- MCStreamer &Out) = 0;
-
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/Target/TargetData.h b/include/llvm/Target/TargetData.h
index c280810..26fd187 100644
--- a/include/llvm/Target/TargetData.h
+++ b/include/llvm/Target/TargetData.h
@@ -33,6 +33,8 @@ class StructType;
class StructLayout;
class GlobalVariable;
class LLVMContext;
+template<typename T>
+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<unsigned char, 8> 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<Value *> 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/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h
index e3d77cf..4c759b2 100644
--- a/include/llvm/Target/TargetFrameLowering.h
+++ b/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<MachineMove> &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<MCCFIInstruction> Instrs,
- int DataAlignmentFactor,
- bool IsEH) const {
- return 0;
- }
};
} // End llvm namespace
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h
index f663566..07f614d 100644
--- a/include/llvm/Target/TargetInstrInfo.h
+++ b/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<uint16_t, uint16_t>
+ 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<unsigned> &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<MachineOperand> &Pred) const;
virtual void reMaterialize(MachineBasicBlock &MBB,
diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h
index ad8ac92..c44b923 100644
--- a/include/llvm/Target/TargetIntrinsicInfo.h
+++ b/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/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 533c3ac..013e70a 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/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<int> &Mask,
- EVT VT) const {
+ virtual bool isShuffleMaskLegal(const SmallVectorImpl<int> &/*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<int> &Mask,
- EVT VT) const {
+ virtual bool isVectorClearMaskLegal(const SmallVectorImpl<int> &/*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<ISD::InputArg> &Ins,
- DebugLoc dl, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &InVals) const {
+ LowerFormalArguments(SDValue /*Chain*/, CallingConv::ID /*CallConv*/,
+ bool /*isVarArg*/,
+ const SmallVectorImpl<ISD::InputArg> &/*Ins*/,
+ DebugLoc /*dl*/, SelectionDAG &/*DAG*/,
+ SmallVectorImpl<SDValue> &/*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<ArgListEntry> ArgListTy;
std::pair<SDValue, SDValue>
- 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<ISD::OutputArg> &Outs,
- const SmallVectorImpl<SDValue> &OutVals,
- const SmallVectorImpl<ISD::InputArg> &Ins,
- DebugLoc dl, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &InVals) const {
+ LowerCall(SDValue /*Chain*/, SDValue /*Callee*/,
+ CallingConv::ID /*CallConv*/, bool /*isVarArg*/,
+ bool &/*isTailCall*/,
+ const SmallVectorImpl<ISD::OutputArg> &/*Outs*/,
+ const SmallVectorImpl<SDValue> &/*OutVals*/,
+ const SmallVectorImpl<ISD::InputArg> &/*Ins*/,
+ DebugLoc /*dl*/, SelectionDAG &/*DAG*/,
+ SmallVectorImpl<SDValue> &/*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<ISD::OutputArg> &Outs,
- LLVMContext &Context) const
+ virtual bool CanLowerReturn(CallingConv::ID /*CallConv*/,
+ MachineFunction &/*MF*/, bool /*isVarArg*/,
+ const SmallVectorImpl<ISD::OutputArg> &/*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<ISD::OutputArg> &Outs,
- const SmallVectorImpl<SDValue> &OutVals,
- DebugLoc dl, SelectionDAG &DAG) const {
+ LowerReturn(SDValue /*Chain*/, CallingConv::ID /*CallConv*/,
+ bool /*isVarArg*/,
+ const SmallVectorImpl<ISD::OutputArg> &/*Outs*/,
+ const SmallVectorImpl<SDValue> &/*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<SDValue> &Results,
- SelectionDAG &DAG) const {
+ virtual void ReplaceNodeResults(SDNode * /*N*/,
+ SmallVectorImpl<SDValue> &/*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<ISD::OutputArg> &Outs,
const TargetLowering &TLI,
SmallVectorImpl<uint64_t> *Offsets = 0);
diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h
index 2e1d6b9..7d06cec 100644
--- a/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/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/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h
index ac41a58..8a8d142 100644
--- a/include/llvm/Target/TargetMachine.h
+++ b/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 <cassert>
#include <string>
@@ -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/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h
index 55d50d9..e07e8c1 100644
--- a/include/llvm/Target/TargetOptions.h
+++ b/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/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h
index 8d827f1..682aa50 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/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 <cassert>
#include <functional>
@@ -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<unsigned> 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<unsigned> getRawAllocationOrder(const MachineFunction &MF) const {
- return ArrayRef<unsigned>(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<unsigned, unsigned> {
}
};
-/// 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/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h
deleted file mode 100644
index 7e0ce19..0000000
--- a/include/llvm/Target/TargetRegistry.h
+++ /dev/null
@@ -1,985 +0,0 @@
-//===-- Target/TargetRegistry.h - Target Registration -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file exposes the TargetRegistry interface, which tools can use to access
-// the appropriate target specific classes (TargetMachine, AsmPrinter, etc.)
-// which have been registered.
-//
-// Target specific class implementations should register themselves using the
-// appropriate TargetRegistry interfaces.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TARGET_TARGETREGISTRY_H
-#define LLVM_TARGET_TARGETREGISTRY_H
-
-#include "llvm/ADT/Triple.h"
-#include <string>
-#include <cassert>
-
-namespace llvm {
- class AsmPrinter;
- class Module;
- class MCAssembler;
- class MCAsmInfo;
- class MCAsmParser;
- class MCCodeEmitter;
- class MCContext;
- class MCDisassembler;
- class MCInstPrinter;
- class MCInstrInfo;
- class MCRegisterInfo;
- class MCStreamer;
- class MCSubtargetInfo;
- class TargetAsmBackend;
- class TargetAsmLexer;
- class TargetAsmParser;
- class TargetMachine;
- class raw_ostream;
- class formatted_raw_ostream;
-
- MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
- bool isVerboseAsm,
- bool useLoc, bool useCFI,
- MCInstPrinter *InstPrint,
- MCCodeEmitter *CE,
- TargetAsmBackend *TAB,
- bool ShowInst);
-
- /// Target - Wrapper for Target specific information.
- ///
- /// For registration purposes, this is a POD type so that targets can be
- /// registered without the use of static constructors.
- ///
- /// Targets should implement a single global instance of this class (which
- /// will be zero initialized), and pass that instance to the TargetRegistry as
- /// part of their initialization.
- class Target {
- public:
- friend struct TargetRegistry;
-
- typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT);
-
- typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const Target &T,
- StringRef TT);
- typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void);
- typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(void);
- 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);
- 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 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);
- typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx,
- formatted_raw_ostream &OS,
- bool isVerboseAsm,
- bool useLoc,
- bool useCFI,
- MCInstPrinter *InstPrint,
- MCCodeEmitter *CE,
- TargetAsmBackend *TAB,
- bool ShowInst);
-
- private:
- /// Next - The next registered target in the linked list, maintained by the
- /// TargetRegistry.
- Target *Next;
-
- /// TripleMatchQualityFn - The target function for rating the match quality
- /// of a triple.
- TripleMatchQualityFnTy TripleMatchQualityFn;
-
- /// Name - The target name.
- const char *Name;
-
- /// ShortDesc - A short description of the target.
- const char *ShortDesc;
-
- /// HasJIT - Whether this target supports the JIT.
- bool HasJIT;
-
- /// MCAsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if
- /// registered.
- MCAsmInfoCtorFnTy MCAsmInfoCtorFn;
-
- /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo,
- /// if registered.
- MCInstrInfoCtorFnTy MCInstrInfoCtorFn;
-
- /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo,
- /// if registered.
- MCRegInfoCtorFnTy MCRegInfoCtorFn;
-
- /// MCSubtargetInfoCtorFn - Constructor function for this target's
- /// MCSubtargetInfo, if registered.
- MCSubtargetInfoCtorFnTy MCSubtargetInfoCtorFn;
-
- /// TargetMachineCtorFn - Construction function for this target's
- /// TargetMachine, if registered.
- TargetMachineCtorTy TargetMachineCtorFn;
-
- /// AsmBackendCtorFn - Construction function for this target's
- /// TargetAsmBackend, if registered.
- AsmBackendCtorTy AsmBackendCtorFn;
-
- /// AsmLexerCtorFn - Construction function for this target's TargetAsmLexer,
- /// if registered.
- AsmLexerCtorTy AsmLexerCtorFn;
-
- /// AsmParserCtorFn - Construction function for this target's
- /// TargetAsmParser, if registered.
- AsmParserCtorTy AsmParserCtorFn;
-
- /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter,
- /// if registered.
- AsmPrinterCtorTy AsmPrinterCtorFn;
-
- /// MCDisassemblerCtorFn - Construction function for this target's
- /// MCDisassembler, if registered.
- MCDisassemblerCtorTy MCDisassemblerCtorFn;
-
- /// MCInstPrinterCtorFn - Construction function for this target's
- /// MCInstPrinter, if registered.
- MCInstPrinterCtorTy MCInstPrinterCtorFn;
-
- /// CodeEmitterCtorFn - Construction function for this target's CodeEmitter,
- /// if registered.
- CodeEmitterCtorTy CodeEmitterCtorFn;
-
- /// ObjectStreamerCtorFn - Construction function for this target's
- /// ObjectStreamer, if registered.
- ObjectStreamerCtorTy ObjectStreamerCtorFn;
-
- /// AsmStreamerCtorFn - Construction function for this target's
- /// AsmStreamer, if registered (default = llvm::createAsmStreamer).
- AsmStreamerCtorTy AsmStreamerCtorFn;
-
- public:
- Target() : AsmStreamerCtorFn(llvm::createAsmStreamer) {}
-
- /// @name Target Information
- /// @{
-
- // getNext - Return the next registered target.
- const Target *getNext() const { return Next; }
-
- /// getName - Get the target name.
- const char *getName() const { return Name; }
-
- /// getShortDescription - Get a short description of the target.
- const char *getShortDescription() const { return ShortDesc; }
-
- /// @}
- /// @name Feature Predicates
- /// @{
-
- /// hasJIT - Check if this targets supports the just-in-time compilation.
- bool hasJIT() const { return HasJIT; }
-
- /// hasTargetMachine - Check if this target supports code generation.
- bool hasTargetMachine() const { return TargetMachineCtorFn != 0; }
-
- /// hasAsmBackend - Check if this target supports .o generation.
- bool hasAsmBackend() const { return AsmBackendCtorFn != 0; }
-
- /// hasAsmLexer - Check if this target supports .s lexing.
- bool hasAsmLexer() const { return AsmLexerCtorFn != 0; }
-
- /// hasAsmParser - Check if this target supports .s parsing.
- bool hasAsmParser() const { return AsmParserCtorFn != 0; }
-
- /// hasAsmPrinter - Check if this target supports .s printing.
- bool hasAsmPrinter() const { return AsmPrinterCtorFn != 0; }
-
- /// hasMCDisassembler - Check if this target has a disassembler.
- bool hasMCDisassembler() const { return MCDisassemblerCtorFn != 0; }
-
- /// 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; }
-
- /// hasObjectStreamer - Check if this target supports streaming to files.
- bool hasObjectStreamer() const { return ObjectStreamerCtorFn != 0; }
-
- /// hasAsmStreamer - Check if this target supports streaming to files.
- bool hasAsmStreamer() const { return AsmStreamerCtorFn != 0; }
-
- /// @}
- /// @name Feature Constructors
- /// @{
-
- /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified
- /// target triple.
- ///
- /// \arg Triple - This argument is used to determine the target machine
- /// feature set; it should always be provided. Generally this should be
- /// either the target triple from the module, or the target triple of the
- /// host if that does not exist.
- MCAsmInfo *createMCAsmInfo(StringRef Triple) const {
- if (!MCAsmInfoCtorFn)
- return 0;
- return MCAsmInfoCtorFn(*this, Triple);
- }
-
- /// createMCInstrInfo - Create a MCInstrInfo implementation.
- ///
- MCInstrInfo *createMCInstrInfo() const {
- if (!MCInstrInfoCtorFn)
- return 0;
- return MCInstrInfoCtorFn();
- }
-
- /// createMCRegInfo - Create a MCRegisterInfo implementation.
- ///
- MCRegisterInfo *createMCRegInfo() const {
- if (!MCRegInfoCtorFn)
- return 0;
- return MCRegInfoCtorFn();
- }
-
- /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation.
- ///
- /// \arg Triple - This argument is used to determine the target machine
- /// feature set; it should always be provided. Generally this should be
- /// either the target triple from the module, or the target triple of the
- /// host if that does not exist.
- /// \arg CPU - This specifies the name of the target CPU.
- /// \arg Features - This specifies the string representation of the
- /// additional target features.
- MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU,
- StringRef Features) const {
- if (!MCSubtargetInfoCtorFn)
- return 0;
- return MCSubtargetInfoCtorFn(Triple, CPU, Features);
- }
-
- /// createTargetMachine - Create a target specific machine implementation
- /// for the specified \arg Triple.
- ///
- /// \arg Triple - This argument is used to determine the target machine
- /// feature set; it should always be provided. Generally this should be
- /// either the target triple from the module, or the target triple of the
- /// host if that does not exist.
- TargetMachine *createTargetMachine(const std::string &Triple,
- const std::string &CPU,
- const std::string &Features) const {
- if (!TargetMachineCtorFn)
- return 0;
- return TargetMachineCtorFn(*this, Triple, CPU, Features);
- }
-
- /// createAsmBackend - 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)
- return 0;
- return AsmBackendCtorFn(*this, Triple);
- }
-
- /// createAsmLexer - Create a target specific assembly lexer.
- ///
- TargetAsmLexer *createAsmLexer(const MCAsmInfo &MAI) const {
- if (!AsmLexerCtorFn)
- return 0;
- return AsmLexerCtorFn(*this, MAI);
- }
-
- /// createAsmParser - 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)
- return 0;
- return AsmParserCtorFn(STI, Parser);
- }
-
- /// createAsmPrinter - Create a target specific assembly printer pass. This
- /// takes ownership of the MCStreamer object.
- AsmPrinter *createAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) const{
- if (!AsmPrinterCtorFn)
- return 0;
- return AsmPrinterCtorFn(TM, Streamer);
- }
-
- MCDisassembler *createMCDisassembler() const {
- if (!MCDisassemblerCtorFn)
- return 0;
- return MCDisassemblerCtorFn(*this);
- }
-
- MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant,
- const MCAsmInfo &MAI) const {
- if (!MCInstPrinterCtorFn)
- return 0;
- return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI);
- }
-
-
- /// createCodeEmitter - Create a target specific code emitter.
- MCCodeEmitter *createCodeEmitter(const MCInstrInfo &II,
- const MCSubtargetInfo &STI,
- MCContext &Ctx) const {
- if (!CodeEmitterCtorFn)
- return 0;
- return CodeEmitterCtorFn(II, STI, Ctx);
- }
-
- /// createObjectStreamer - Create a target specific MCStreamer.
- ///
- /// \arg TT - The target triple.
- /// \arg Ctx - The target context.
- /// \arg TAB - The target assembler backend object. Takes ownership.
- /// \arg _OS - The stream object.
- /// \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)
- return 0;
- return ObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll,
- NoExecStack);
- }
-
- /// createAsmStreamer - Create a target specific MCStreamer.
- MCStreamer *createAsmStreamer(MCContext &Ctx,
- formatted_raw_ostream &OS,
- bool isVerboseAsm,
- bool useLoc,
- bool useCFI,
- MCInstPrinter *InstPrint,
- MCCodeEmitter *CE,
- TargetAsmBackend *TAB,
- bool ShowInst) const {
- // AsmStreamerCtorFn is default to llvm::createAsmStreamer
- return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, useCFI,
- InstPrint, CE, TAB, ShowInst);
- }
-
- /// @}
- };
-
- /// TargetRegistry - Generic interface to target specific features.
- struct TargetRegistry {
- class iterator {
- const Target *Current;
- explicit iterator(Target *T) : Current(T) {}
- friend struct TargetRegistry;
- public:
- iterator(const iterator &I) : Current(I.Current) {}
- iterator() : Current(0) {}
-
- bool operator==(const iterator &x) const {
- return Current == x.Current;
- }
- bool operator!=(const iterator &x) const {
- return !operator==(x);
- }
-
- // Iterator traversal: forward iteration only
- iterator &operator++() { // Preincrement
- assert(Current && "Cannot increment end iterator!");
- Current = Current->getNext();
- return *this;
- }
- iterator operator++(int) { // Postincrement
- iterator tmp = *this;
- ++*this;
- return tmp;
- }
-
- const Target &operator*() const {
- assert(Current && "Cannot dereference end iterator!");
- return *Current;
- }
-
- const Target *operator->() const {
- return &operator*();
- }
- };
-
- /// @name Registry Access
- /// @{
-
- static iterator begin();
-
- static iterator end() { return iterator(); }
-
- /// lookupTarget - Lookup a target based on a target triple.
- ///
- /// \param Triple - The triple to use for finding a target.
- /// \param Error - On failure, an error string describing why no target was
- /// found.
- static const Target *lookupTarget(const std::string &Triple,
- std::string &Error);
-
- /// getClosestTargetForJIT - Pick the best target that is compatible with
- /// the current host. If no close target can be found, this returns null
- /// and sets the Error string to a reason.
- ///
- /// Maintained for compatibility through 2.6.
- static const Target *getClosestTargetForJIT(std::string &Error);
-
- /// @}
- /// @name Target Registration
- /// @{
-
- /// RegisterTarget - Register the given target. Attempts to register a
- /// target which has already been registered will be ignored.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Name - The target name. This should be a static string.
- /// @param ShortDesc - A short target description. This should be a static
- /// string.
- /// @param TQualityFn - The triple match quality computation function for
- /// this target.
- /// @param HasJIT - Whether the target supports JIT code
- /// generation.
- static void RegisterTarget(Target &T,
- const char *Name,
- const char *ShortDesc,
- Target::TripleMatchQualityFnTy TQualityFn,
- bool HasJIT = false);
-
- /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a MCAsmInfo for the target.
- static void RegisterMCAsmInfo(Target &T, Target::MCAsmInfoCtorFnTy Fn) {
- // Ignore duplicate registration.
- if (!T.MCAsmInfoCtorFn)
- T.MCAsmInfoCtorFn = Fn;
- }
-
- /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a MCInstrInfo for the target.
- static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) {
- // Ignore duplicate registration.
- if (!T.MCInstrInfoCtorFn)
- T.MCInstrInfoCtorFn = Fn;
- }
-
- /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a MCRegisterInfo for the target.
- static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) {
- // Ignore duplicate registration.
- if (!T.MCRegInfoCtorFn)
- T.MCRegInfoCtorFn = Fn;
- }
-
- /// RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for
- /// the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a MCSubtargetInfo for the target.
- static void RegisterMCSubtargetInfo(Target &T,
- Target::MCSubtargetInfoCtorFnTy Fn) {
- // Ignore duplicate registration.
- if (!T.MCSubtargetInfoCtorFn)
- T.MCSubtargetInfoCtorFn = Fn;
- }
-
- /// RegisterTargetMachine - Register a TargetMachine implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct a TargetMachine for the target.
- static void RegisterTargetMachine(Target &T,
- Target::TargetMachineCtorTy Fn) {
- // Ignore duplicate registration.
- if (!T.TargetMachineCtorFn)
- T.TargetMachineCtorFn = Fn;
- }
-
- /// RegisterAsmBackend - Register a TargetAsmBackend implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an AsmBackend for the target.
- static void RegisterAsmBackend(Target &T, Target::AsmBackendCtorTy Fn) {
- if (!T.AsmBackendCtorFn)
- T.AsmBackendCtorFn = Fn;
- }
-
- /// RegisterAsmLexer - Register a TargetAsmLexer 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 AsmLexer for the target.
- static void RegisterAsmLexer(Target &T, Target::AsmLexerCtorTy Fn) {
- if (!T.AsmLexerCtorFn)
- T.AsmLexerCtorFn = Fn;
- }
-
- /// RegisterAsmParser - Register a TargetAsmParser 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;
- }
-
- /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given
- /// target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an AsmPrinter for the target.
- static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) {
- // Ignore duplicate registration.
- if (!T.AsmPrinterCtorFn)
- T.AsmPrinterCtorFn = Fn;
- }
-
- /// RegisterMCDisassembler - Register a MCDisassembler implementation for
- /// the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCDisassembler for the target.
- static void RegisterMCDisassembler(Target &T,
- Target::MCDisassemblerCtorTy Fn) {
- if (!T.MCDisassemblerCtorFn)
- T.MCDisassemblerCtorFn = Fn;
- }
-
- /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCInstPrinter for the target.
- static void RegisterMCInstPrinter(Target &T,
- Target::MCInstPrinterCtorTy Fn) {
- if (!T.MCInstPrinterCtorFn)
- T.MCInstPrinterCtorFn = Fn;
- }
-
- /// RegisterCodeEmitter - Register a MCCodeEmitter implementation for the
- /// given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCCodeEmitter for the target.
- static void RegisterCodeEmitter(Target &T, Target::CodeEmitterCtorTy Fn) {
- if (!T.CodeEmitterCtorFn)
- T.CodeEmitterCtorFn = Fn;
- }
-
- /// RegisterObjectStreamer - Register a object code MCStreamer implementation
- /// for the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCStreamer for the target.
- static void RegisterObjectStreamer(Target &T, Target::ObjectStreamerCtorTy Fn) {
- if (!T.ObjectStreamerCtorFn)
- T.ObjectStreamerCtorFn = Fn;
- }
-
- /// RegisterAsmStreamer - Register an assembly MCStreamer implementation
- /// for the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an MCStreamer for the target.
- static void RegisterAsmStreamer(Target &T, Target::AsmStreamerCtorTy Fn) {
- if (T.AsmStreamerCtorFn == createAsmStreamer)
- T.AsmStreamerCtorFn = Fn;
- }
-
- /// @}
- };
-
-
- //===--------------------------------------------------------------------===//
-
- /// RegisterTarget - Helper template for registering a target, for use in the
- /// target's initialization function. Usage:
- ///
- ///
- /// Target TheFooTarget; // The global target instance.
- ///
- /// extern "C" void LLVMInitializeFooTargetInfo() {
- /// RegisterTarget<Triple::foo> X(TheFooTarget, "foo", "Foo description");
- /// }
- template<Triple::ArchType TargetArchType = Triple::InvalidArch,
- bool HasJIT = false>
- struct RegisterTarget {
- RegisterTarget(Target &T, const char *Name, const char *Desc) {
- TargetRegistry::RegisterTarget(T, Name, Desc,
- &getTripleMatchQuality,
- HasJIT);
- }
-
- static unsigned getTripleMatchQuality(const std::string &TT) {
- if (Triple(TT).getArch() == TargetArchType)
- return 20;
- return 0;
- }
- };
-
- /// RegisterMCAsmInfo - Helper template for registering a target assembly info
- /// implementation. This invokes the static "Create" method on the class to
- /// actually do the construction. Usage:
- ///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCAsmInfo<FooMCAsmInfo> X(TheFooTarget);
- /// }
- template<class MCAsmInfoImpl>
- struct RegisterMCAsmInfo {
- RegisterMCAsmInfo(Target &T) {
- TargetRegistry::RegisterMCAsmInfo(T, &Allocator);
- }
- private:
- static MCAsmInfo *Allocator(const Target &T, StringRef TT) {
- return new MCAsmInfoImpl(T, TT);
- }
-
- };
-
- /// RegisterMCAsmInfoFn - Helper template for registering a target assembly info
- /// implementation. This invokes the specified function to do the
- /// construction. Usage:
- ///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCAsmInfoFn X(TheFooTarget, TheFunction);
- /// }
- struct RegisterMCAsmInfoFn {
- RegisterMCAsmInfoFn(Target &T, Target::MCAsmInfoCtorFnTy Fn) {
- TargetRegistry::RegisterMCAsmInfo(T, Fn);
- }
- };
-
- /// RegisterMCInstrInfo - Helper template for registering a target instruction
- /// info implementation. This invokes the static "Create" method on the class
- /// to actually do the construction. Usage:
- ///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCInstrInfo<FooMCInstrInfo> X(TheFooTarget);
- /// }
- template<class MCInstrInfoImpl>
- struct RegisterMCInstrInfo {
- RegisterMCInstrInfo(Target &T) {
- TargetRegistry::RegisterMCInstrInfo(T, &Allocator);
- }
- private:
- static MCInstrInfo *Allocator() {
- return new MCInstrInfoImpl();
- }
- };
-
- /// RegisterMCInstrInfoFn - Helper template for registering a target
- /// instruction info implementation. This invokes the specified function to
- /// do the construction. Usage:
- ///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction);
- /// }
- struct RegisterMCInstrInfoFn {
- RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) {
- TargetRegistry::RegisterMCInstrInfo(T, Fn);
- }
- };
-
- /// RegisterMCRegInfo - Helper template for registering a target register info
- /// implementation. This invokes the static "Create" method on the class to
- /// actually do the construction. Usage:
- ///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCRegInfo<FooMCRegInfo> X(TheFooTarget);
- /// }
- template<class MCRegisterInfoImpl>
- struct RegisterMCRegInfo {
- RegisterMCRegInfo(Target &T) {
- TargetRegistry::RegisterMCRegInfo(T, &Allocator);
- }
- private:
- static MCRegisterInfo *Allocator() {
- return new MCRegisterInfoImpl();
- }
- };
-
- /// RegisterMCRegInfoFn - Helper template for registering a target register
- /// info implementation. This invokes the specified function to do the
- /// construction. Usage:
- ///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCRegInfoFn X(TheFooTarget, TheFunction);
- /// }
- struct RegisterMCRegInfoFn {
- RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) {
- TargetRegistry::RegisterMCRegInfo(T, Fn);
- }
- };
-
- /// RegisterMCSubtargetInfo - Helper template for registering a target
- /// subtarget info implementation. This invokes the static "Create" method
- /// on the class to actually do the construction. Usage:
- ///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCSubtargetInfo<FooMCSubtargetInfo> X(TheFooTarget);
- /// }
- template<class MCSubtargetInfoImpl>
- struct RegisterMCSubtargetInfo {
- RegisterMCSubtargetInfo(Target &T) {
- TargetRegistry::RegisterMCSubtargetInfo(T, &Allocator);
- }
- private:
- static MCSubtargetInfo *Allocator(StringRef TT, StringRef CPU,
- StringRef FS) {
- return new MCSubtargetInfoImpl();
- }
- };
-
- /// RegisterMCSubtargetInfoFn - Helper template for registering a target
- /// subtarget info implementation. This invokes the specified function to
- /// do the construction. Usage:
- ///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterMCSubtargetInfoFn X(TheFooTarget, TheFunction);
- /// }
- struct RegisterMCSubtargetInfoFn {
- RegisterMCSubtargetInfoFn(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) {
- TargetRegistry::RegisterMCSubtargetInfo(T, Fn);
- }
- };
-
- /// RegisterTargetMachine - Helper template for registering a target machine
- /// implementation, for use in the target machine initialization
- /// function. Usage:
- ///
- /// extern "C" void LLVMInitializeFooTarget() {
- /// extern Target TheFooTarget;
- /// RegisterTargetMachine<FooTargetMachine> X(TheFooTarget);
- /// }
- template<class TargetMachineImpl>
- struct RegisterTargetMachine {
- RegisterTargetMachine(Target &T) {
- TargetRegistry::RegisterTargetMachine(T, &Allocator);
- }
-
- private:
- static TargetMachine *Allocator(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS) {
- return new TargetMachineImpl(T, TT, CPU, FS);
- }
- };
-
- /// RegisterAsmBackend - Helper template for registering a target specific
- /// assembler backend. Usage:
- ///
- /// extern "C" void LLVMInitializeFooAsmBackend() {
- /// extern Target TheFooTarget;
- /// RegisterAsmBackend<FooAsmLexer> X(TheFooTarget);
- /// }
- template<class AsmBackendImpl>
- struct RegisterAsmBackend {
- RegisterAsmBackend(Target &T) {
- TargetRegistry::RegisterAsmBackend(T, &Allocator);
- }
-
- private:
- static TargetAsmBackend *Allocator(const Target &T,
- const std::string &Triple) {
- return new AsmBackendImpl(T, Triple);
- }
- };
-
- /// RegisterAsmLexer - Helper template for registering a target specific
- /// assembly lexer, for use in the target machine initialization
- /// function. Usage:
- ///
- /// extern "C" void LLVMInitializeFooAsmLexer() {
- /// extern Target TheFooTarget;
- /// RegisterAsmLexer<FooAsmLexer> X(TheFooTarget);
- /// }
- template<class AsmLexerImpl>
- struct RegisterAsmLexer {
- RegisterAsmLexer(Target &T) {
- TargetRegistry::RegisterAsmLexer(T, &Allocator);
- }
-
- private:
- static TargetAsmLexer *Allocator(const Target &T, const MCAsmInfo &MAI) {
- return new AsmLexerImpl(T, MAI);
- }
- };
-
- /// RegisterAsmParser - Helper template for registering a target specific
- /// assembly parser, for use in the target machine initialization
- /// function. Usage:
- ///
- /// extern "C" void LLVMInitializeFooAsmParser() {
- /// extern Target TheFooTarget;
- /// RegisterAsmParser<FooAsmParser> X(TheFooTarget);
- /// }
- template<class AsmParserImpl>
- struct RegisterAsmParser {
- RegisterAsmParser(Target &T) {
- TargetRegistry::RegisterAsmParser(T, &Allocator);
- }
-
- private:
- static TargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P) {
- return new AsmParserImpl(STI, P);
- }
- };
-
- /// RegisterAsmPrinter - Helper template for registering a target specific
- /// assembly printer, for use in the target machine initialization
- /// function. Usage:
- ///
- /// extern "C" void LLVMInitializeFooAsmPrinter() {
- /// extern Target TheFooTarget;
- /// RegisterAsmPrinter<FooAsmPrinter> X(TheFooTarget);
- /// }
- template<class AsmPrinterImpl>
- struct RegisterAsmPrinter {
- RegisterAsmPrinter(Target &T) {
- TargetRegistry::RegisterAsmPrinter(T, &Allocator);
- }
-
- private:
- static AsmPrinter *Allocator(TargetMachine &TM, MCStreamer &Streamer) {
- return new AsmPrinterImpl(TM, Streamer);
- }
- };
-
- /// RegisterCodeEmitter - Helper template for registering a target specific
- /// machine code emitter, for use in the target initialization
- /// function. Usage:
- ///
- /// extern "C" void LLVMInitializeFooCodeEmitter() {
- /// extern Target TheFooTarget;
- /// RegisterCodeEmitter<FooCodeEmitter> X(TheFooTarget);
- /// }
- template<class CodeEmitterImpl>
- struct RegisterCodeEmitter {
- RegisterCodeEmitter(Target &T) {
- TargetRegistry::RegisterCodeEmitter(T, &Allocator);
- }
-
- private:
- static MCCodeEmitter *Allocator(const MCInstrInfo &II,
- const MCSubtargetInfo &STI,
- MCContext &Ctx) {
- return new CodeEmitterImpl();
- }
- };
-
-}
-
-#endif
diff --git a/include/llvm/Target/TargetSelect.h b/include/llvm/Target/TargetSelect.h
deleted file mode 100644
index 272ee09..0000000
--- a/include/llvm/Target/TargetSelect.h
+++ /dev/null
@@ -1,184 +0,0 @@
-//===- TargetSelect.h - Target Selection & Registration ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides utilities to make sure that certain classes of targets are
-// linked into the main application executable, and initialize them as
-// appropriate.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TARGET_TARGETSELECT_H
-#define LLVM_TARGET_TARGETSELECT_H
-
-#include "llvm/Config/llvm-config.h"
-
-extern "C" {
- // Declare all of the target-initialization functions that are available.
-#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##TargetInfo();
-#include "llvm/Config/Targets.def"
-
-#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##Target();
-#include "llvm/Config/Targets.def"
-
-#define LLVM_TARGET(TargetName) \
- void LLVMInitialize##TargetName##MCAsmInfo();
-#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"
-
- // Declare all of the available assembly parser initialization functions.
-#define LLVM_ASM_PARSER(TargetName) void LLVMInitialize##TargetName##AsmParser();
-#include "llvm/Config/AsmParsers.def"
-
- // Declare all of the available disassembler initialization functions.
-#define LLVM_DISASSEMBLER(TargetName) \
- void LLVMInitialize##TargetName##Disassembler();
-#include "llvm/Config/Disassemblers.def"
-}
-
-namespace llvm {
- /// InitializeAllTargetInfos - The main program should call this function if
- /// it wants access to all available 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 InitializeAllTargetInfos() {
-#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##TargetInfo();
-#include "llvm/Config/Targets.def"
- }
-
- /// InitializeAllTargets - The main program should call this function if it
- /// wants access to all available target machines 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 InitializeAllTargets() {
- // FIXME: Remove this, clients should do it.
- InitializeAllTargetInfos();
-
-#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##Target();
-#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.
- ///
- /// It is legal for a client to make multiple calls to this function.
- inline void InitializeAllMCSubtargetInfos() {
-#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##MCSubtargetInfo();
-#include "llvm/Config/Targets.def"
- }
-
- /// InitializeAllAsmPrinters - The main program should call this function if
- /// it wants all asm printers that LLVM is configured to support, to make them
- /// available via the TargetRegistry.
- ///
- /// It is legal for a client to make multiple calls to this function.
- inline void InitializeAllAsmPrinters() {
-#define LLVM_ASM_PRINTER(TargetName) LLVMInitialize##TargetName##AsmPrinter();
-#include "llvm/Config/AsmPrinters.def"
- }
-
- /// InitializeAllAsmParsers - The main program should call this function if it
- /// wants all asm parsers that LLVM is configured to support, to make them
- /// available via the TargetRegistry.
- ///
- /// It is legal for a client to make multiple calls to this function.
- inline void InitializeAllAsmParsers() {
-#define LLVM_ASM_PARSER(TargetName) LLVMInitialize##TargetName##AsmParser();
-#include "llvm/Config/AsmParsers.def"
- }
-
- /// InitializeAllDisassemblers - The main program should call this function if
- /// it wants all disassemblers that LLVM is configured to support, to make
- /// them available via the TargetRegistry.
- ///
- /// It is legal for a client to make multiple calls to this function.
- inline void InitializeAllDisassemblers() {
-#define LLVM_DISASSEMBLER(TargetName) LLVMInitialize##TargetName##Disassembler();
-#include "llvm/Config/Disassemblers.def"
- }
-
- /// InitializeNativeTarget - The main program should call this function to
- /// initialize the native target corresponding to the host. This is useful
- /// for JIT applications to ensure that the target gets linked in correctly.
- ///
- /// It is legal for a client to make multiple calls to this function.
- inline bool InitializeNativeTarget() {
- // If we have a native target, initialize it to ensure it is linked in.
-#ifdef LLVM_NATIVE_TARGET
- LLVM_NATIVE_TARGETINFO();
- LLVM_NATIVE_TARGET();
- LLVM_NATIVE_MCASMINFO();
- return false;
-#else
- return true;
-#endif
- }
-
- /// InitializeNativeTargetAsmPrinter - The main program should call
- /// this function to initialize the native target asm printer.
- inline bool InitializeNativeTargetAsmPrinter() {
- // If we have a native target, initialize the corresponding asm printer.
-#ifdef LLVM_NATIVE_ASMPRINTER
- LLVM_NATIVE_ASMPRINTER();
- return false;
-#else
- return true;
-#endif
- }
-
- /// InitializeNativeTargetAsmParser - The main program should call
- /// this function to initialize the native target asm parser.
- inline bool InitializeNativeTargetAsmParser() {
- // If we have a native target, initialize the corresponding asm parser.
-#ifdef LLVM_NATIVE_ASMPARSER
- LLVM_NATIVE_ASMPARSER();
- return false;
-#else
- return true;
-#endif
- }
-
-}
-
-#endif
diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td
index 9d1ef2c..612635e 100644
--- a/include/llvm/Target/TargetSelectionDAG.td
+++ b/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<atomic_load_min>;
defm atomic_load_max : binary_atomic_op<atomic_load_max>;
defm atomic_load_umin : binary_atomic_op<atomic_load_umin>;
defm atomic_load_umax : binary_atomic_op<atomic_load_umax>;
+defm atomic_store : binary_atomic_op<atomic_store>;
+
+def atomic_load_8 :
+ PatFrag<(ops node:$ptr),
+ (atomic_load node:$ptr), [{
+ return cast<AtomicSDNode>(N)->getMemoryVT() == MVT::i8;
+}]>;
+def atomic_load_16 :
+ PatFrag<(ops node:$ptr),
+ (atomic_load node:$ptr), [{
+ return cast<AtomicSDNode>(N)->getMemoryVT() == MVT::i16;
+}]>;
+def atomic_load_32 :
+ PatFrag<(ops node:$ptr),
+ (atomic_load node:$ptr), [{
+ return cast<AtomicSDNode>(N)->getMemoryVT() == MVT::i32;
+}]>;
+def atomic_load_64 :
+ PatFrag<(ops node:$ptr),
+ (atomic_load node:$ptr), [{
+ return cast<AtomicSDNode>(N)->getMemoryVT() == MVT::i64;
+}]>;
//===----------------------------------------------------------------------===//
// Selection DAG CONVERT_RNDSAT patterns
diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h
index f025e180..f9d7f9e 100644
--- a/include/llvm/Transforms/IPO.h
+++ b/include/llvm/Transforms/IPO.h
@@ -50,13 +50,6 @@ ModulePass *createStripDebugDeclarePass();
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.
/// This is useful because some passes (ie TraceValues) insert a lot of string
@@ -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/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h
new file mode 100644
index 0000000..cc74e7f
--- /dev/null
+++ b/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 <vector>
+
+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<std::pair<ExtensionPointTy, ExtensionFn> > 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/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h
index 2187d4e..b1536f9 100644
--- a/include/llvm/Transforms/Scalar.h
+++ b/include/llvm/Transforms/Scalar.h
@@ -176,13 +176,6 @@ 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
// preds always go to some succ.
//
diff --git a/include/llvm/Transforms/Utils/AddrModeMatcher.h b/include/llvm/Transforms/Utils/AddrModeMatcher.h
index 0678ecc..90485eb 100644
--- a/include/llvm/Transforms/Utils/AddrModeMatcher.h
+++ b/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<Instruction*> &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<Instruction*> &AddrModeInsts,
const TargetLowering &TLI) {
diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 90eabef..6fcd160 100644
--- a/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/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 <from,to> edge info.
void FindFunctionBackedges(const Function &F,
SmallVectorImpl<std::pair<const BasicBlock*,const BasicBlock*> > &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<BasicBlock*> Preds,
+ const char *Suffix, const char *Suffix2,
+ Pass *P, SmallVectorImpl<BasicBlock*> &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/include/llvm/Transforms/Utils/FunctionUtils.h b/include/llvm/Transforms/Utils/FunctionUtils.h
index 785b08f..8d71e43 100644
--- a/include/llvm/Transforms/Utils/FunctionUtils.h
+++ b/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 <vector>
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<BasicBlock*> &code,
+ ArrayRef<BasicBlock*> 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<BasicBlock*> BBs,
+ bool AggregateArgs = false);
}
#endif
diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h
index 063d413..064e550 100644
--- a/include/llvm/Transforms/Utils/SSAUpdater.h
+++ b/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/include/llvm/Transforms/Utils/SimplifyIndVar.h b/include/llvm/Transforms/Utils/SimplifyIndVar.h
new file mode 100644
index 0000000..524cf5a
--- /dev/null
+++ b/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<bool> 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<WeakVH> &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<WeakVH> &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<WeakVH> &Dead);
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h
index 3d5ee1a..7212a8c 100644
--- a/include/llvm/Transforms/Utils/UnrollLoop.h
+++ b/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/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h
index 2194373..0384656 100644
--- a/include/llvm/Transforms/Utils/ValueMapper.h
+++ b/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<MDNode>(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<Constant>(MapValue((const Value*)V, VM, Flags, TypeMapper));
}
diff --git a/include/llvm/Type.h b/include/llvm/Type.h
index e4ff3e1..43b7dc5 100644
--- a/include/llvm/Type.h
+++ b/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<const Type*> {
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/include/llvm/User.h b/include/llvm/User.h
index 3f9c28e..62bc9f0 100644
--- a/include/llvm/User.h
+++ b/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/include/llvm/Value.h b/include/llvm/Value.h
index 08fa1c9..a71e2fd 100644
--- a/include/llvm/Value.h
+++ b/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/lib/Analysis/AliasAnalysis.cpp b/lib/Analysis/AliasAnalysis.cpp
index c189a00..bd132c0 100644
--- a/lib/Analysis/AliasAnalysis.cpp
+++ b/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/lib/Analysis/AliasAnalysisEvaluator.cpp b/lib/Analysis/AliasAnalysisEvaluator.cpp
index 1afc1b7..37271b9 100644
--- a/lib/Analysis/AliasAnalysisEvaluator.cpp
+++ b/lib/Analysis/AliasAnalysisEvaluator.cpp
@@ -171,12 +171,12 @@ bool AAEval::runOnFunction(Function &F) {
for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end();
I1 != E; ++I1) {
uint64_t I1Size = AliasAnalysis::UnknownSize;
- const Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType();
+ Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType();
if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy);
for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) {
uint64_t I2Size = AliasAnalysis::UnknownSize;
- const Type *I2ElTy =cast<PointerType>((*I2)->getType())->getElementType();
+ Type *I2ElTy =cast<PointerType>((*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<Value *>::iterator V = Pointers.begin(), Ve = Pointers.end();
V != Ve; ++V) {
uint64_t Size = AliasAnalysis::UnknownSize;
- const Type *ElTy = cast<PointerType>((*V)->getType())->getElementType();
+ Type *ElTy = cast<PointerType>((*V)->getType())->getElementType();
if (ElTy->isSized()) Size = AA.getTypeStoreSize(ElTy);
switch (AA.getModRefInfo(*C, *V, Size)) {
diff --git a/lib/Analysis/AliasSetTracker.cpp b/lib/Analysis/AliasSetTracker.cpp
index 2ed6949..3fcd3b5 100644
--- a/lib/Analysis/AliasSetTracker.cpp
+++ b/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<DbgInfoIntrinsic>(CS.getInstruction()))
+bool AliasSetTracker::addUnknown(Instruction *Inst) {
+ if (isa<DbgInfoIntrinsic>(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<StoreInst>(I))
return add(SI);
- if (CallInst *CI = dyn_cast<CallInst>(I))
- return add(CI);
- if (InvokeInst *II = dyn_cast<InvokeInst>(I))
- return add(II);
if (VAArgInst *VAAI = dyn_cast<VAArgInst>(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<AliasSet&>(*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<StoreInst>(I))
return remove(SI);
- if (CallInst *CI = dyn_cast<CallInst>(I))
- return remove(CI);
if (VAArgInst *VAAI = dyn_cast<VAArgInst>(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<Instruction>(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/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp
index 71e0a83..0ba6af9 100644
--- a/lib/Analysis/Analysis.cpp
+++ b/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 <cstring>
@@ -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/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp
index 8330ea7..af400ba 100644
--- a/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/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<GlobalVariable>(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<StructType>(*GTI++)) {
+ if (StructType *STy = dyn_cast<StructType>(*GTI++)) {
// For a struct, add the member offset.
unsigned FieldNo = cast<ConstantInt>(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<int64_t>(Scale)};
VarIndices.push_back(Entry);
}
}
@@ -467,6 +469,7 @@ namespace {
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<AliasAnalysis>();
+ AU.addRequired<TargetLibraryInfo>();
}
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<Value>(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<TargetLibraryInfo>();
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<PointerType>(MemsetType->getParamType(0)) &&
+ isa<PointerType>(MemsetType->getParamType(1)) &&
+ isa<IntegerType>(MemsetType->getParamType(2))) {
+ uint64_t Len = UnknownSize;
+ if (const ConstantInt *LenCI = dyn_cast<ConstantInt>(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/lib/Analysis/BlockFrequency.cpp b/lib/Analysis/BlockFrequency.cpp
deleted file mode 100644
index 4b86d1d..0000000
--- a/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<BasicBlock, Function, BranchProbabilityInfo>();
-}
-
-BlockFrequency::~BlockFrequency() {
- delete BFI;
-}
-
-void BlockFrequency::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<BranchProbabilityInfo>();
- AU.setPreservesAll();
-}
-
-bool BlockFrequency::runOnFunction(Function &F) {
- BranchProbabilityInfo &BPI = getAnalysis<BranchProbabilityInfo>();
- 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/lib/Analysis/BlockFrequencyInfo.cpp b/lib/Analysis/BlockFrequencyInfo.cpp
new file mode 100644
index 0000000..d16665f
--- /dev/null
+++ b/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<BasicBlock, Function, BranchProbabilityInfo>();
+}
+
+BlockFrequencyInfo::~BlockFrequencyInfo() {
+ delete BFI;
+}
+
+void BlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<BranchProbabilityInfo>();
+ AU.setPreservesAll();
+}
+
+bool BlockFrequencyInfo::runOnFunction(Function &F) {
+ BranchProbabilityInfo &BPI = getAnalysis<BranchProbabilityInfo>();
+ 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/lib/Analysis/BranchProbabilityInfo.cpp b/lib/Analysis/BranchProbabilityInfo.cpp
index e39cd22..bde3b76 100644
--- a/lib/Analysis/BranchProbabilityInfo.cpp
+++ b/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<BasicBlock *, BasicBlock *> Edge;
+ typedef std::pair<const BasicBlock *, const BasicBlock *> Edge;
DenseMap<Edge, uint32_t> *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<BranchInst>(TI) && !isa<SwitchInst>(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<uint32_t, 2> Weights;
+ Weights.reserve(TI->getNumSuccessors());
+ for (unsigned i = 1, e = WeightsNode->getNumOperands(); i != e; ++i) {
+ ConstantInt *Weight = dyn_cast<ConstantInt>(WeightsNode->getOperand(i));
+ if (!Weight)
+ return false;
+ Weights.push_back(
+ std::max<uint32_t>(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<BasicBlock *, 4> ReturningEdges;
+ SmallPtrSet<BasicBlock *, 4> 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<BasicBlock *, 4>::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<BasicBlock *, 4>::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<BranchInst>(BB->getTerminator());
if (!BI || !BI->isConditional())
- return;
+ return false;
Value *Cond = BI->getCondition();
ICmpInst *CI = dyn_cast<ICmpInst>(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<BasicBlock *, 8> BackEdges;
+ SmallPtrSet<BasicBlock *, 8> ExitingEdges;
+ SmallPtrSet<BasicBlock *, 8> InEdges; // Edges from header to the loop.
- SmallVector<BasicBlock *, 8> BackEdges;
- SmallVector<BasicBlock *, 8> 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<BasicBlock *, 8>::iterator EI = BackEdges.begin(),
+ for (SmallPtrSet<BasicBlock *, 8>::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<BasicBlock *, 8>::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<BasicBlock *, 8>::iterator EI = ExitingEdges.begin(),
+ for (SmallPtrSet<BasicBlock *, 8>::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<BranchInst>(BB->getTerminator());
+ if (!BI || !BI->isConditional())
+ return false;
+
+ Value *Cond = BI->getCondition();
+ ICmpInst *CI = dyn_cast<ICmpInst>(Cond);
+ if (!CI)
+ return false;
+
+ Value *RHS = CI->getOperand(1);
+ ConstantInt *CV = dyn_cast<ConstantInt>(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<Edge, uint32_t>::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/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index ab846a2..e79459d 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -6,7 +6,7 @@ add_llvm_library(LLVMAnalysis
AliasSetTracker.cpp
Analysis.cpp
BasicAliasAnalysis.cpp
- BlockFrequency.cpp
+ BlockFrequencyInfo.cpp
BranchProbabilityInfo.cpp
CFGPrinter.cpp
CaptureTracking.cpp
@@ -58,4 +58,10 @@ add_llvm_library(LLVMAnalysis
ValueTracking.cpp
)
+add_llvm_library_dependencies(LLVMAnalysis
+ LLVMCore
+ LLVMSupport
+ LLVMTarget
+ )
+
add_subdirectory(IPA)
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index 7fca17e..df79849 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/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<VectorType>(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<VectorType>(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<StructType>(*GTI)) {
+ if (StructType *ST = dyn_cast<StructType>(*GTI)) {
// N = N + Offset
Offset += TD.getStructLayout(ST)->getElementOffset(CI->getZExtValue());
} else {
- const SequentialType *SQT = cast<SequentialType>(*GTI);
+ SequentialType *SQT = cast<SequentialType>(*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<PointerType>(C->getType())->getElementType();
- const IntegerType *IntType = dyn_cast<IntegerType>(LoadTy);
+ Type *LoadTy = cast<PointerType>(C->getType())->getElementType();
+ IntegerType *IntType = dyn_cast<IntegerType>(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<PointerType>(CE->getType())->getElementType();
+ Type *Ty = cast<PointerType>(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<GlobalVariable>(GetUnderlyingObject(CE, TD))) {
if (GV->isConstant() && GV->hasDefinitiveInitializer()) {
- const Type *ResTy = cast<PointerType>(C->getType())->getElementType();
+ Type *ResTy = cast<PointerType>(C->getType())->getElementType();
if (GV->getInitializer()->isNullValue())
return Constant::getNullValue(ResTy);
if (isa<UndefValue>(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<Constant *> 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<Constant*, 32> NewIdxs;
- for (unsigned i = 1; i != NumOps; ++i) {
+ for (unsigned i = 1, e = Ops.size(); i != e; ++i) {
if ((i == 1 ||
!isa<StructType>(GetElementPtrInst::getIndexedType(Ops[0]->getType(),
- reinterpret_cast<Value *const *>(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<ConstantExpr>(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<Constant *> Ops,
+ Type *ResultTy,
const TargetData *TD) {
Constant *Ptr = Ops[0];
if (!TD || !cast<PointerType>(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<ConstantInt>(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<PointerType>(ResultTy)->getElementType()->isIntegerTy(8)) {
ConstantExpr *CE = dyn_cast<ConstantExpr>(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<Constant>(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<Constant>(GEP->getOperand(0));
Offset += APInt(BitWidth,
- TD->getIndexedOffset(Ptr->getType(),
- (Value**)NestedOps.data(),
- NestedOps.size()));
+ TD->getIndexedOffset(Ptr->getType(), NestedOps));
Ptr = cast<Constant>(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<Constant*, 32> NewIdxs;
do {
- if (const SequentialType *ATy = dyn_cast<SequentialType>(Ty)) {
+ if (SequentialType *ATy = dyn_cast<SequentialType>(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<StructType>(Ty)) {
+ } else if (StructType *STy = dyn_cast<StructType>(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<PointerType>(C->getType())->getElementType() == Ty &&
"Computed GetElementPtr has unexpected type!");
@@ -778,8 +781,7 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) {
cast<Constant>(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<Constant *> 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<Function>(Ops[NumOps - 1]))
+ if (Function *F = dyn_cast<Function>(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<ConstantExpr>(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<ConstantExpr>(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<StructType>(*I)) {
+ if (StructType *STy = dyn_cast<StructType>(*I)) {
ConstantInt *CU = cast<ConstantInt>(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<ConstantInt>(I.getOperand())) {
- if (const ArrayType *ATy = dyn_cast<ArrayType>(*I)) {
+ if (ArrayType *ATy = dyn_cast<ArrayType>(*I)) {
if (CI->getZExtValue() >= ATy->getNumElements())
return 0;
if (ConstantArray *CA = dyn_cast<ConstantArray>(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<VectorType>(*I)) {
+ } else if (VectorType *VTy = dyn_cast<VectorType>(*I)) {
if (CI->getZExtValue() >= VTy->getNumElements())
return 0;
if (ConstantVector *CP = dyn_cast<ConstantVector>(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<Constant *> 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<ConstantFP>(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<ConstantFP>(Operands[0])) {
if (!Ty->isFloatTy() && !Ty->isDoubleTy())
return 0;
diff --git a/lib/Analysis/DIBuilder.cpp b/lib/Analysis/DIBuilder.cpp
index ac5eeeb..bfa429d 100644
--- a/lib/Analysis/DIBuilder.cpp
+++ b/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<Value *, 4> 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<Value *, 15> 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/lib/Analysis/DbgInfoPrinter.cpp b/lib/Analysis/DbgInfoPrinter.cpp
index b23c351..cd832ab 100644
--- a/lib/Analysis/DbgInfoPrinter.cpp
+++ b/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/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp
index b42e946..44457d3 100644
--- a/lib/Analysis/DebugInfo.cpp
+++ b/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<MDNode>(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<MDNode>(DbgNode->getOperand(19)))
+ return dyn_cast_or_null<MDNode>(Temp->getOperand(0));
+ return NULL;
+}
+
+DIArray DISubprogram::getVariables() const {
+ if (!DbgNode || DbgNode->getNumOperands() <= 19)
+ return DIArray();
+ if (MDNode *T = dyn_cast_or_null<MDNode>(DbgNode->getOperand(19)))
+ if (MDNode *A = dyn_cast_or_null<MDNode>(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<MDNode>(DbgNode->getOperand(10)))
+ if (MDNode *A = dyn_cast_or_null<MDNode>(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<MDNode>(DbgNode->getOperand(11)))
+ if (MDNode *A = dyn_cast_or_null<MDNode>(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<MDNode>(DbgNode->getOperand(12)))
+ if (MDNode *A = dyn_cast_or_null<MDNode>(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<MDNode>(DbgNode->getOperand(13)))
+ if (MDNode *A = dyn_cast_or_null<MDNode>(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 << "<unknown>";
+ 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<char> &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<Value *, 16> 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<Value *, 16> 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<MDNode>(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/lib/Analysis/IPA/CMakeLists.txt b/lib/Analysis/IPA/CMakeLists.txt
index 8ffef29..eae83fd 100644
--- a/lib/Analysis/IPA/CMakeLists.txt
+++ b/lib/Analysis/IPA/CMakeLists.txt
@@ -5,3 +5,9 @@ add_llvm_library(LLVMipa
GlobalsModRef.cpp
IPA.cpp
)
+
+add_llvm_library_dependencies(LLVMipa
+ LLVMAnalysis
+ LLVMCore
+ LLVMSupport
+ )
diff --git a/lib/Analysis/IPA/CallGraphSCCPass.cpp b/lib/Analysis/IPA/CallGraphSCCPass.cpp
index 659ffab..963da75 100644
--- a/lib/Analysis/IPA/CallGraphSCCPass.cpp
+++ b/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/lib/Analysis/IPA/FindUsedTypes.cpp b/lib/Analysis/IPA/FindUsedTypes.cpp
index 6535786..e9df3ca 100644
--- a/lib/Analysis/IPA/FindUsedTypes.cpp
+++ b/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 Type *>::const_iterator I = UsedTypes.begin(),
+ for (SetVector<Type *>::const_iterator I = UsedTypes.begin(),
E = UsedTypes.end(); I != E; ++I) {
OS << " " << **I << '\n';
}
diff --git a/lib/Analysis/IVUsers.cpp b/lib/Analysis/IVUsers.cpp
index e5f0a77..d0ca892 100644
--- a/lib/Analysis/IVUsers.cpp
+++ b/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/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp
index efde598..e12e322 100644
--- a/lib/Analysis/InlineCost.cpp
+++ b/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<Instruction>(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<AllocaInst>(II)) {
if (!AI->isStaticAlloca())
this->usesDynamicAlloca = true;
}
if (isa<ExtractElementInst>(II) || II->getType()->isVectorTy())
- ++NumVectorInsts;
-
+ ++NumVectorInsts;
+
if (const CastInst *CI = dyn_cast<CastInst>(II)) {
// Noop casts, including ptr <-> int, don't count.
- if (CI->isLosslessCast() || isa<IntToPtrInst>(CI) ||
+ if (CI->isLosslessCast() || isa<IntToPtrInst>(CI) ||
isa<PtrToIntInst>(CI))
continue;
+ // trunc to a native type is free (assuming the target has compare and
+ // shift-right of the same width).
+ if (isa<TruncInst>(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<ReturnInst>(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<Function>(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<Constant>(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<UnreachableInst>(++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<Constant>(I))
Bonus += CountBonusForConstant(FI, cast<Constant>(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/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp
index 8709f6b..131cc97 100644
--- a/lib/Analysis/InstructionSimplify.cpp
+++ b/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<VectorType>(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<VectorType>(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<Instruction>(V);
@@ -526,7 +546,7 @@ static Value *SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
if (Constant *CRHS = dyn_cast<Constant>(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<Constant>(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<Constant>(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<Constant>(Op0)) {
if (Constant *C1 = dyn_cast<Constant>(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<Constant>(Op0)) {
if (Constant *C1 = dyn_cast<Constant>(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<Constant>(Op0)) {
if (Constant *C1 = dyn_cast<Constant>(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<Constant>(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<Constant>(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<Constant>(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<CastInst>(LHS) && (isa<Constant>(RHS) || isa<CastInst>(RHS))) {
Instruction *LI = cast<CastInst>(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<Value *> Ops,
const TargetData *TD, const DominatorTree *) {
// The type of the GEP pointer operand.
- const PointerType *PtrTy = cast<PointerType>(Ops[0]->getType());
+ PointerType *PtrTy = cast<PointerType>(Ops[0]->getType());
// getelementptr P -> P.
- if (NumOps == 1)
+ if (Ops.size() == 1)
return Ops[0];
if (isa<UndefValue>(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<ConstantInt>(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<Constant>(Ops[i]))
return 0;
- return ConstantExpr::getGetElementPtr(cast<Constant>(Ops[0]),
- (Constant *const*)Ops+1, NumOps-1);
+ return ConstantExpr::getGetElementPtr(cast<Constant>(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<unsigned> Idxs,
+ const TargetData *,
+ const DominatorTree *) {
+ if (Constant *CAgg = dyn_cast<Constant>(Agg))
+ if (Constant *CVal = dyn_cast<Constant>(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<ExtractValueInst>(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<Constant>(LHS))
if (Constant *CRHS = dyn_cast<Constant>(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<Value*, 8> 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<InsertValueInst>(I);
+ Result = SimplifyInsertValueInst(IV->getAggregateOperand(),
+ IV->getInsertedValueOperand(),
+ IV->getIndices(), TD, DT);
break;
}
case Instruction::PHI:
diff --git a/lib/Analysis/LazyValueInfo.cpp b/lib/Analysis/LazyValueInfo.cpp
index 6e27597..f80595c 100644
--- a/lib/Analysis/LazyValueInfo.cpp
+++ b/lib/Analysis/LazyValueInfo.cpp
@@ -630,7 +630,7 @@ bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV,
if (BB == &BB->getParent()->getEntryBlock()) {
assert(isa<Argument>(Val) && "Unknown live-in to the entry block");
if (NotNull) {
- const PointerType *PTy = cast<PointerType>(Val->getType());
+ PointerType *PTy = cast<PointerType>(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<PointerType>(Val->getType());
+ PointerType *PTy = cast<PointerType>(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<IntegerType>(BBI->getType());
+ IntegerType *ResultTy = cast<IntegerType>(BBI->getType());
if (isa<BinaryOperator>(BBI)) {
if (ConstantInt *RHS = dyn_cast<ConstantInt>(BBI->getOperand(1))) {
RHSRange = ConstantRange(RHS->getValue());
diff --git a/lib/Analysis/Lint.cpp b/lib/Analysis/Lint.cpp
index 89755da..38d677d 100644
--- a/lib/Analysis/Lint.cpp
+++ b/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<PointerType>(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/lib/Analysis/Loads.cpp b/lib/Analysis/Loads.cpp
index c5c676b..0e6bcbf 100644
--- a/lib/Analysis/Loads.cpp
+++ b/lib/Analysis/Loads.cpp
@@ -63,7 +63,7 @@ static Value *getUnderlyingObjectWithOffset(Value *V, const TargetData *TD,
return V;
SmallVector<Value*, 8> 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<Operator>(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<AllocaInst>(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<PointerType>(V->getType());
+ PointerType *AddrTy = cast<PointerType>(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<PointerType>(Ptr->getType())->getElementType();
+ Type *AccessTy = cast<PointerType>(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<LoadInst>(Inst))
if (AreEquivalentAddressValues(LI->getOperand(0), Ptr))
return LI;
if (StoreInst *SI = dyn_cast<StoreInst>(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/lib/Analysis/LoopDependenceAnalysis.cpp b/lib/Analysis/LoopDependenceAnalysis.cpp
index c1afe8f..3997ac4 100644
--- a/lib/Analysis/LoopDependenceAnalysis.cpp
+++ b/lib/Analysis/LoopDependenceAnalysis.cpp
@@ -76,7 +76,13 @@ static void GetMemRefInstrs(const Loop *L,
}
static bool IsLoadOrStoreInst(Value *I) {
- return isa<LoadInst>(I) || isa<StoreInst>(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<LoadInst>(I))
+ return LI->isUnordered();
+ else if (StoreInst *SI = dyn_cast<StoreInst>(I))
+ return SI->isUnordered();
+ return false;
}
static Value *GetPointerOperand(Value *I) {
diff --git a/lib/Analysis/LoopInfo.cpp b/lib/Analysis/LoopInfo.cpp
index 0583140..85aacca 100644
--- a/lib/Analysis/LoopInfo.cpp
+++ b/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<LandingPadInst>(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;
@@ -383,6 +387,205 @@ void Loop::dump() const {
}
//===----------------------------------------------------------------------===//
+// 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<Loop*, Loop*> 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
//
bool LoopInfo::runOnFunction(Function &) {
@@ -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<const Loop*> 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<BasicBlock*, Loop*>::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/lib/Analysis/LoopPass.cpp b/lib/Analysis/LoopPass.cpp
index 10e3f29..5ba1f40 100644
--- a/lib/Analysis/LoopPass.cpp
+++ b/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<DebugInfoProbeInfo> 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<Loop *>::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<BasicBlock>(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<Loop *> &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<LoopInfo>();
Info.setPreservesAll();
@@ -255,7 +211,7 @@ bool LPPassManager::runOnFunction(Function &F) {
for (std::deque<Loop *>::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, "<deleted>", 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/lib/Analysis/MemDepPrinter.cpp b/lib/Analysis/MemDepPrinter.cpp
index 2283db0..fde07ea 100644
--- a/lib/Analysis/MemDepPrinter.cpp
+++ b/lib/Analysis/MemDepPrinter.cpp
@@ -25,8 +25,17 @@ namespace {
struct MemDepPrinter : public FunctionPass {
const Function *F;
- typedef PointerIntPair<const Instruction *, 1> InstAndClobberFlag;
- typedef std::pair<InstAndClobberFlag, const BasicBlock *> Dep;
+ enum DepType {
+ Clobber = 0,
+ Def,
+ NonFuncLocal,
+ Unknown
+ };
+
+ static const char* DepTypeStr[];
+
+ typedef PointerIntPair<const Instruction *, 2, DepType> InstTypePair;
+ typedef std::pair<InstTypePair, const BasicBlock *> Dep;
typedef SmallSetVector<Dep, 4> DepSet;
typedef DenseMap<const Instruction *, DepSet> 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<AliasAnalysis>();
@@ -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<BasicBlock *>(0)));
} else if (CallSite CS = cast<Value>(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<NonLocalDepResult, 4> NLDI;
if (LoadInst *LI = dyn_cast<LoadInst>(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<BasicBlock *>(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<StoreInst>(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<BasicBlock *>(0)));
+ continue;
+ }
AliasAnalysis::Location Loc = AA.getLocation(SI);
MDA.getNonLocalPointerDependency(Loc, false, SI->getParent(), NLDI);
} else if (VAArgInst *VI = dyn_cast<VAArgInst>(Inst)) {
@@ -121,11 +149,7 @@ bool MemDepPrinter::runOnFunction(Function &F) {
for (SmallVectorImpl<NonLocalDepResult>::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 << "<unspecified>";
- else
- DepInst->print(OS);
+ DepInst->print(OS);
}
OS << "\n";
}
diff --git a/lib/Analysis/MemoryBuiltins.cpp b/lib/Analysis/MemoryBuiltins.cpp
index 53d4304..8d451c4 100644
--- a/lib/Analysis/MemoryBuiltins.cpp
+++ b/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<StructType>(T))
+ if (StructType *ST = dyn_cast<StructType>(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/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp
index bba4482..92967c0 100644
--- a/lib/Analysis/MemoryDependenceAnalysis.cpp
+++ b/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<LoadInst>(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<StoreInst>(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<VAArgInst>(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<IntegerType>(LI->getType()) || LI->isVolatile()) return 0;
+ // We can only extend simple integer loads.
+ if (!isa<IntegerType>(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<LoadInst>(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<IntegerType>(LI->getType()))
+ if (IntegerType *ITy = dyn_cast<IntegerType>(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<StoreInst>(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/lib/Analysis/PHITransAddr.cpp b/lib/Analysis/PHITransAddr.cpp
index 70dcd0d..7e22ddc 100644
--- a/lib/Analysis/PHITransAddr.cpp
+++ b/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/lib/Analysis/PathNumbering.cpp b/lib/Analysis/PathNumbering.cpp
index 7c584da..0e3b6e6 100644
--- a/lib/Analysis/PathNumbering.cpp
+++ b/lib/Analysis/PathNumbering.cpp
@@ -387,7 +387,7 @@ void BallLarusDag::buildNode(BLBlockNodeMap& inDag, BLNodeStack& dfsStack) {
TerminatorInst* terminator = currentNode->getBlock()->getTerminator();
if(isa<ReturnInst>(terminator) || isa<UnreachableInst>(terminator)
- || isa<UnwindInst>(terminator))
+ || isa<ResumeInst>(terminator) || isa<UnwindInst>(terminator))
addEdge(currentNode, getExit(),0);
currentNode->setColor(BallLarusNode::GRAY);
diff --git a/lib/Analysis/RegionPass.cpp b/lib/Analysis/RegionPass.cpp
index 80eda79..3a3529b 100644
--- a/lib/Analysis/RegionPass.cpp
+++ b/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/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index 025718e..e0ac56c 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -197,7 +197,7 @@ void SCEV::print(raw_ostream &OS) const {
}
case scUnknown: {
const SCEVUnknown *U = cast<SCEVUnknown>(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<SCEVConstant>(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<IntegerType>(getEffectiveSCEVType(Ty));
+ScalarEvolution::getConstant(Type *Ty, uint64_t V, bool isSigned) {
+ IntegerType *ITy = cast<IntegerType>(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<ConstantExpr>(getValue()))
if (VCE->getOpcode() == Instruction::PtrToInt)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(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<ConstantExpr>(getValue()))
if (VCE->getOpcode() == Instruction::PtrToInt)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(VCE->getOperand(0)))
if (CE->getOpcode() == Instruction::GetElementPtr &&
CE->getOperand(0)->isNullValue()) {
- const Type *Ty =
+ Type *Ty =
cast<PointerType>(CE->getOperand(0)->getType())->getElementType();
- if (const StructType *STy = dyn_cast<StructType>(Ty))
+ if (StructType *STy = dyn_cast<StructType>(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<ConstantExpr>(getValue()))
if (VCE->getOpcode() == Instruction::PtrToInt)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(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<PointerType>(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<const SCEV *> &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<SCEVAddExpr>(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<const SCEV *, 4> 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<SCEVAddRecExpr>(
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<const SCEV *> &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<const SCEV *> &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<const SCEV *> &Ops,
// if the contents of the resulting outer trunc fold to something simple.
for (; Idx < Ops.size() && isa<SCEVTruncateExpr>(Ops[Idx]); ++Idx) {
const SCEVTruncateExpr *Trunc = cast<SCEVTruncateExpr>(Ops[Idx]);
- const Type *DstType = Trunc->getType();
- const Type *SrcType = Trunc->getOperand()->getType();
+ Type *DstType = Trunc->getType();
+ Type *SrcType = Trunc->getOperand()->getType();
SmallVector<const SCEV *, 8> 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<const SCEV *> &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<const SCEV *> &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<const SCEV *> &Ops,
@@ -1809,7 +1853,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &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<const SCEV *> &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<const SCEV *> &Ops,
// multiplied together. If so, we can fold them.
for (unsigned OtherIdx = Idx+1;
OtherIdx < Ops.size() && isa<SCEVAddRecExpr>(Ops[OtherIdx]);
- ++OtherIdx)
+ ++OtherIdx) {
if (AddRecLoop == cast<SCEVAddRecExpr>(Ops[OtherIdx])->getLoop()) {
- // F * G, where F = {A,+,B}<L> and G = {C,+,D}<L> -->
- // {A*C,+,F*D + G*B + B*D}<L>
+ // {A1,+,A2,+,...,+,An}<L> * {B1,+,B2,+,...,+,Bn}<L>
+ // = {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<SCEVAddRecExpr>(Ops[OtherIdx]);
++OtherIdx)
if (const SCEVAddRecExpr *OtherAddRec =
dyn_cast<SCEVAddRecExpr>(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<SCEVAddRecExpr>(NewAddRec);
- Ops.erase(Ops.begin() + OtherIdx); --OtherIdx;
+ bool Overflow = false;
+ Type *Ty = AddRec->getType();
+ bool LargerThan64Bits = getTypeSizeInBits(Ty) > 64;
+ SmallVector<const SCEV*, 7> 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<SCEVAddRecExpr>(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<SCEVAddRecExpr>(LHS))
if (const SCEVConstant *Step =
- dyn_cast<SCEVConstant>(AR->getStepRecurrence(*this)))
- if (!Step->getValue()->getValue()
- .urem(RHSC->getValue()->getValue()) &&
+ dyn_cast<SCEVConstant>(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<SCEVConstant>(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<SCEVMulExpr>(LHS)) {
SmallVector<const SCEV *, 4> Operands;
@@ -2151,7 +2246,7 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &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<const SCEV *> &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<const SCEV *> &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<ConstantExpr>(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<ConstantExpr>(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<ConstantExpr>(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<ConstantExpr>(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<ConstantInt>(ConstantExpr::getNeg(VC->getValue())));
- const Type *Ty = V->getType();
+ Type *Ty = V->getType();
Ty = getEffectiveSCEVType(Ty);
return getMulExpr(V,
getConstant(cast<ConstantInt>(Constant::getAllOnesValue(Ty))));
@@ -2640,7 +2735,7 @@ const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) {
return getConstant(
cast<ConstantInt>(ConstantExpr::getNot(VC->getValue())));
- const Type *Ty = V->getType();
+ Type *Ty = V->getType();
Ty = getEffectiveSCEVType(Ty);
const SCEV *AllOnes =
getConstant(cast<ConstantInt>(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<PointerType>(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<StructType>(*GTI++)) {
+ if (StructType *STy = dyn_cast<StructType>(*GTI++)) {
// For a struct, add the member offset.
unsigned FieldNo = cast<ConstantInt>(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<SCEVCouldNotCompute>(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<SCEVCouldNotCompute>(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<OverflowingBinaryOperator>(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<SCEVZeroExtendExpr>(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<SCEVConstant>(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<SCEVMulExpr>(TCMul))
+ TCMul = Mul->getOperand(0);
+
+ const SCEVConstant *MulC = dyn_cast<SCEVConstant>(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<Instruction *> &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<DenseMap<const Loop *, BackedgeTakenInfo>::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<PHINode>(L->getHeader()->begin()))
- // Only count loops that have phi nodes as not being computable.
- ++NumTripCountsNotComputed;
+ }
+ else if (Result.getMax(this) == getCouldNotCompute() &&
+ isa<PHINode>(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<Instruction *, 16> 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<const Loop*, BackedgeTakenInfo>::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<Instruction *, 16> 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<BasicBlock *, const SCEV *> > &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<std::pair<BasicBlock *, const SCEV *>, 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<BinaryOperator>(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<ICmpInst>(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<LoadInst>(ExitCond->getOperand(0)))
if (Constant *RHS = dyn_cast<Constant>(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<Constant>(CA->getOperand(Idx));
} else if (isa<ConstantAggregateZero>(Init)) {
- if (const StructType *STy = dyn_cast<StructType>(Init->getType())) {
+ if (StructType *STy = dyn_cast<StructType>(Init->getType())) {
assert(Idx < STy->getNumElements() && "Bad struct index!");
Init = Constant::getNullValue(STy->getElementType(Idx));
- } else if (const ArrayType *ATy = dyn_cast<ArrayType>(Init->getType())) {
+ } else if (ArrayType *ATy = dyn_cast<ArrayType>(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<Instruction>(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<PHINode>(I)) {
+ if (isa<PHINode>(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<Instruction *, PHINode *> &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<Constant>(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<Constant>(*OpI)) continue;
+
+ Instruction *OpInst = dyn_cast<Instruction>(*OpI);
+ if (!OpInst || !canConstantEvolve(OpInst, L)) return 0;
+
+ PHINode *P = dyn_cast<PHINode>(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<Instruction>(V);
+ if (I == 0 || !canConstantEvolve(I, L)) return 0;
+
+ if (PHINode *PN = dyn_cast<PHINode>(I)) {
+ return PN;
+ }
+
+ // Record non-constant instructions contained by the loop.
+ DenseMap<Instruction *, PHINode *> 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<Instruction *, Constant *> &Vals,
const TargetData *TD) {
- if (isa<PHINode>(V)) return PHIVal;
+ // Convenient constant check, but redundant for recursive calls.
if (Constant *C = dyn_cast<Constant>(V)) return C;
+
Instruction *I = cast<Instruction>(V);
+ if (Constant *C = Vals.lookup(I)) return C;
+
+ assert(!isa<PHINode>(I) && "loop header phis should be mapped to constant");
+ assert(canConstantEvolve(I, L) && "cannot evaluate expression in this loop");
+ (void)L;
std::vector<Constant*> 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<Instruction>(I->getOperand(i));
+ if (!Operand) {
+ Operands[i] = dyn_cast<Constant>(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<CmpInst>(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<Instruction *, Constant *> 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<Constant>(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<Instruction *, Constant *> 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<Instruction *, Constant *> PHIValMap;
+ PHIValMap[PN] = PHIVal;
ConstantInt *CondVal =
- dyn_cast_or_null<ConstantInt>(EvaluateExpression(Cond, PHIVal, TD));
+ dyn_cast_or_null<ConstantInt>(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<SCEVConstant>(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<SCEVCouldNotCompute>(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<const Loop*, BackedgeTakenInfo>::iterator I =
+ BackedgeTakenCounts.begin(), E = BackedgeTakenCounts.end();
+ I != E; ++I) {
+ I->second.clear();
+ }
+
BackedgeTakenCounts.clear();
ConstantEvolutionLoopExitValue.clear();
ValuesAtScopes.clear();
diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp
index befe6d2..47f0f32 100644
--- a/lib/Analysis/ScalarEvolutionExpander.cpp
+++ b/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<BitCastInst>(IP) &&
isa<Argument>(cast<BitCastInst>(IP)->getOperand(0)) &&
cast<BitCastInst>(IP)->getOperand(0) != A) ||
- isa<DbgInfoIntrinsic>(IP))
+ isa<DbgInfoIntrinsic>(IP) ||
+ isa<LandingPadInst>(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<InvokeInst>(I))
IP = II->getNormalDest()->begin();
- while (isa<PHINode>(IP) || isa<DbgInfoIntrinsic>(IP)) ++IP;
+ while (isa<PHINode>(IP) || isa<DbgInfoIntrinsic>(IP) ||
+ isa<LandingPadInst>(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<Instruction>(Builder.CreateBinOp(Opcode, LHS, RHS, "tmp"));
+ Instruction *BO = cast<Instruction>(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<const SCEV *> &Ops,
- const Type *Ty,
+ Type *Ty,
ScalarEvolution &SE) {
unsigned NumAddRecs = 0;
for (unsigned i = Ops.size(); i > 0 && isa<SCEVAddRecExpr>(Ops[i-1]); --i)
@@ -306,7 +310,7 @@ static void SimplifyAddOperands(SmallVectorImpl<const SCEV *> &Ops,
/// into GEP indices.
///
static void SplitAddRecs(SmallVectorImpl<const SCEV *> &Ops,
- const Type *Ty,
+ Type *Ty,
ScalarEvolution &SE) {
// Find the addrecs.
SmallVector<const SCEV *, 8> AddRecs;
@@ -365,10 +369,10 @@ static void SplitAddRecs(SmallVectorImpl<const SCEV *> &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<Value *, 4> GepIndices;
SmallVector<const SCEV *, 8> 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<StructType>(ElTy)) {
+ while (StructType *STy = dyn_cast<StructType>(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<SCEVUnknown>(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<ArrayType>(ElTy))
+ if (ArrayType *ATy = dyn_cast<ArrayType>(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<Constant>(V))
if (Constant *CRHS = dyn_cast<Constant>(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<PointerType>(Sum->getType())) {
+ } else if (PointerType *PTy = dyn_cast<PointerType>(Sum->getType())) {
// The running sum expression is a pointer. Try to form a getelementptr
// at this level with that as the base.
SmallVector<const SCEV *, 4> 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<PointerType>(Op->getType())) {
+ } else if (PointerType *PTy = dyn_cast<PointerType>(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<SCEVConstant>(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<PHINode>(IncV) ||
+ (isa<CastInst>(IncV) && !isa<BitCastInst>(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<Instruction>(OI))
+ if (!SE.DT->dominates(OInst, IVIncInsertPos))
+ return false;
+ }
+ // Advance to the next instruction.
+ IncV = dyn_cast<Instruction>(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<GetElementPtrInst>(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<Constant>(*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<PointerType>(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<Instruction>(OI))
+ if (!SE.DT->dominates(OInst, IVIncInsertPos))
+ return false;
+ }
+ break;
+ }
+ IncV = dyn_cast<Instruction>(IncV->getOperand(0));
+ if (IncV && IncV->getOpcode() == Instruction::BitCast)
+ IncV = dyn_cast<Instruction>(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<PHINode>(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<Instruction>(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<PHINode>(I); ++I) {
+ if (!SE.isSCEVable(PN->getType()) ||
+ (SE.getEffectiveSCEVType(PN->getType()) !=
+ SE.getEffectiveSCEVType(Normalized->getType())) ||
+ SE.getSCEV(PN) != Normalized)
+ continue;
+
+ Instruction *IncV =
+ cast<Instruction>(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<PHINode>(IncV) ||
- (isa<CastInst>(IncV) && !isa<BitCastInst>(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<Instruction>(OI))
- if (!SE.DT->dominates(OInst, IVIncInsertPos)) {
- IncV = 0;
- break;
- }
- }
- if (!IncV)
- break;
- // Advance to the next instruction.
- IncV = dyn_cast<Instruction>(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<Instruction>(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<Instruction>(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<Instruction>(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<PointerType>(ExpandTy);
+ PointerType *GEPPtrTy = cast<PointerType>(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<ConstantInt>(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<Instruction>(Result) ||
+ SE.DT->dominates(cast<Instruction>(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<PointerType>(ExpandTy)) {
+ if (PointerType *PTy = dyn_cast<PointerType>(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<Instruction>(V)));
- while (isa<PHINode>(NewInsertPt) || isa<DbgInfoIntrinsic>(NewInsertPt))
+ while (isa<PHINode>(NewInsertPt) || isa<DbgInfoIntrinsic>(NewInsertPt) ||
+ isa<LandingPadInst>(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<PointerType>(Base->getType())) {
+ if (PointerType *PTy = dyn_cast<PointerType>(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<DbgInfoIntrinsic>(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<DbgInfoIntrinsic>(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}<L>.
@@ -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<Instruction>(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<WeakVH> &DeadInsts) {
+ unsigned NumElim = 0;
+ DenseMap<const SCEV *, PHINode *> ExprToIVMap;
+ for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) {
+ PHINode *Phi = cast<PHINode>(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<Instruction>(OrigPhiRef->getIncomingValueForBlock(LatchBlock));
+ Instruction *IsomorphicInc =
+ cast<Instruction>(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/lib/Analysis/ScalarEvolutionNormalization.cpp b/lib/Analysis/ScalarEvolutionNormalization.cpp
index 60e630a..c66ecd6 100644
--- a/lib/Analysis/ScalarEvolutionNormalization.cpp
+++ b/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<SCEVConstant>(S) || isa<SCEVUnknown>(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<const SCEV*, const SCEV*> 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<SCEVCastExpr>(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<SCEVUDivExpr>(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<SCEVConstant>(S) || isa<SCEVUnknown>(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/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index 455c910..4d94f61 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/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<PointerType>(Ty) && "Expected a pointer type!");
@@ -103,7 +103,7 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask,
if (GlobalValue *GV = dyn_cast<GlobalValue>(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<StructType>(*GTI)) {
+ if (StructType *STy = dyn_cast<StructType>(*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<ConstantInt>(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<unsigned, 10> &Idxs,
unsigned IdxSkip,
Instruction *InsertBefore) {
- const llvm::StructType *STy = llvm::dyn_cast<llvm::StructType>(IndexedType);
+ llvm::StructType *STy = llvm::dyn_cast<llvm::StructType>(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<unsigned>(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<unsigned> 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<unsigned, 10> Idxs(idx_range.begin(), idx_range.end());
@@ -1404,7 +1403,7 @@ Value *llvm::FindInsertedValue(Value *V, ArrayRef<unsigned> idx_range,
&& "Not looking at a struct or array?");
assert(ExtractValueInst::getIndexedType(V->getType(), idx_range)
&& "Invalid indices for type?");
- const CompositeType *PTy = cast<CompositeType>(V->getType());
+ CompositeType *PTy = cast<CompositeType>(V->getType());
if (isa<UndefValue>(V))
return UndefValue::get(ExtractValueInst::getIndexedType(PTy,
@@ -1435,9 +1434,7 @@ Value *llvm::FindInsertedValue(Value *V, ArrayRef<unsigned> 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<unsigned>(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<unsigned> idx_range,
// requested (though possibly only partially). Now we recursively look at
// the inserted value, passing any remaining indices.
return FindInsertedValue(I->getInsertedValueOperand(),
- ArrayRef<unsigned>(req_idx, idx_range.end()),
+ makeArrayRef(req_idx, idx_range.end()),
InsertBefore);
} else if (ExtractValueInst *I = dyn_cast<ExtractValueInst>(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<StructType>(*GTI)) {
+ if (StructType *STy = dyn_cast<StructType>(*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<PointerType>(GEP->getOperand(0)->getType());
- const ArrayType *AT = dyn_cast<ArrayType>(PT->getElementType());
+ PointerType *PT = cast<PointerType>(GEP->getOperand(0)->getType());
+ ArrayType *AT = dyn_cast<ArrayType>(PT->getElementType());
if (AT == 0 || !AT->getElementType()->isIntegerTy(8))
return false;
diff --git a/lib/Archive/CMakeLists.txt b/lib/Archive/CMakeLists.txt
index 7ff478a..b52974e 100644
--- a/lib/Archive/CMakeLists.txt
+++ b/lib/Archive/CMakeLists.txt
@@ -3,3 +3,9 @@ add_llvm_library(LLVMArchive
ArchiveReader.cpp
ArchiveWriter.cpp
)
+
+add_llvm_library_dependencies(LLVMArchive
+ LLVMBitReader
+ LLVMCore
+ LLVMSupport
+ )
diff --git a/lib/AsmParser/CMakeLists.txt b/lib/AsmParser/CMakeLists.txt
index 985ebe2..7496015 100644
--- a/lib/AsmParser/CMakeLists.txt
+++ b/lib/AsmParser/CMakeLists.txt
@@ -4,3 +4,8 @@ add_llvm_library(LLVMAsmParser
LLParser.cpp
Parser.cpp
)
+
+add_llvm_library_dependencies(LLVMAsmParser
+ LLVMCore
+ LLVMSupport
+ )
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index 3c63106..d0dd986 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/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/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index cfc31f3..cafaab0 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/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<PointerType>(Ty);
+ PointerType *PTy = dyn_cast<PointerType>(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<FunctionType>(PTy->getElementType()))
+ if (FunctionType *FT = dyn_cast<FunctionType>(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<PointerType>(Ty);
+GlobalValue *LLParser::GetGlobalVal(unsigned ID, Type *Ty, LocTy Loc) {
+ PointerType *PTy = dyn_cast<PointerType>(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<FunctionType>(PTy->getElementType()))
+ if (FunctionType *FT = dyn_cast<FunctionType>(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<StructType>(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<Constant *> 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<PointerType>(Ty);
- const FunctionType *FTy =
+ PointerType *PTy = dyn_cast<PointerType>(Ty);
+ FunctionType *FTy =
PTy ? dyn_cast<FunctionType>(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<StructType>(Ty)) {
+ if (StructType *ST = dyn_cast<StructType>(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<Constant*>(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<PointerType>(RetType)) ||
!(Ty = dyn_cast<FunctionType>(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<ArrayType>(V->getType()))
+ Error(VLoc, "'catch' clause has an invalid type");
+ } else {
+ if (!isa<ArrayType>(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<PointerType>(RetType)) ||
!(Ty = dyn_cast<FunctionType>(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<PointerType>(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<PointerType>(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<PointerType>(Ptr->getType())->getElementType() != Cmp->getType())
+ return Error(CmpLoc, "compare value and pointer type do not match");
+ if (cast<PointerType>(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<PointerType>(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<GetElementPtrInst>(Inst)->setIsInBounds(true);
return AteExtraComma ? InstExtraComma : InstNormal;
diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index 9630657..cbc3c23 100644
--- a/lib/AsmParser/LLParser.h
+++ b/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<unsigned> &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<Constant*> &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/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index a5f89fc..8f16772 100644
--- a/lib/AsmParser/LLToken.h
+++ b/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/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 24c2994..46565f3 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/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<Type*, 8> 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<Type*> 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<StructType>(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<Value*, 8> 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<uint64_t, 64> 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<IntegerType>(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<Constant*> Elts;
- if (const StructType *STy = dyn_cast<StructType>(CurTy)) {
+ if (StructType *STy = dyn_cast<StructType>(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<ArrayType>(CurTy)) {
- const Type *EltTy = ATy->getElementType();
+ } else if (ArrayType *ATy = dyn_cast<ArrayType>(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<VectorType>(CurTy)) {
- const Type *EltTy = VTy->getElementType();
+ } else if (VectorType *VTy = dyn_cast<VectorType>(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<ArrayType>(CurTy);
- const Type *EltTy = ATy->getElementType();
+ ArrayType *ATy = cast<ArrayType>(CurTy);
+ Type *EltTy = ATy->getElementType();
unsigned Size = Record.size();
std::vector<Constant*> Elts;
@@ -1288,8 +1326,8 @@ bool BitcodeReader::ParseConstants() {
if (Record.empty())
return Error("Invalid CST_AGGREGATE record");
- const ArrayType *ATy = cast<ArrayType>(CurTy);
- const Type *EltTy = ATy->getElementType();
+ ArrayType *ATy = cast<ArrayType>(CurTy);
+ Type *EltTy = ATy->getElementType();
unsigned Size = Record.size();
std::vector<Constant*> 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<Constant*, 16> 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<Constant *> 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<VectorType>(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<VectorType>(CurTy);
+ VectorType *OpTy = dyn_cast<VectorType>(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<VectorType>(CurTy);
+ VectorType *OpTy = dyn_cast<VectorType>(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<VectorType>(CurTy);
- const VectorType *OpTy =
+ VectorType *RTy = dyn_cast<VectorType>(CurTy);
+ VectorType *OpTy =
dyn_cast_or_null<VectorType>(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<PointerType>(CurTy);
+ PointerType *PTy = cast<PointerType>(CurTy);
V = InlineAsm::get(cast<FunctionType>(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<Function>(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<FunctionType>(cast<PointerType>(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<GetElementPtrInst>(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<const VectorType>(Cond->getType())) {
+ if (VectorType* vector_type =
+ dyn_cast<VectorType>(Cond->getType())) {
// expect <n x i1>
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<PointerType>(Callee->getType());
- const FunctionType *FTy = !CalleeTy ? 0 :
+ PointerType *CalleeTy = dyn_cast<PointerType>(Callee->getType());
+ FunctionType *FTy = !CalleeTy ? 0 :
dyn_cast<FunctionType>(CalleeTy->getElementType());
// Check that the right number of fixed parameters are here.
@@ -2472,6 +2508,15 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
cast<InvokeInst>(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<ArrayType>(Val->getType())) &&
+ "Catch clause has a invalid type!");
+ assert((CT != LandingPadInst::Filter ||
+ isa<ArrayType>(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<PointerType>(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<PointerType>(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<PointerType>(Ptr->getType())->getElementType(), Cmp) ||
+ getValue(Record, OpNum,
+ cast<PointerType>(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<AtomicCmpXchgInst>(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<PointerType>(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<AtomicRMWInst>(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<PointerType>(Callee->getType());
- const FunctionType *FTy = 0;
+ PointerType *OpTy = dyn_cast<PointerType>(Callee->getType());
+ FunctionType *FTy = 0;
if (OpTy) FTy = dyn_cast<FunctionType>(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<std::pair<Function*, Function*> >().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/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h
index 1b3bf1a..6e6118c 100644
--- a/lib/Bitcode/Reader/BitcodeReader.h
+++ b/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<uint64_t, 64> &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/lib/Bitcode/Reader/CMakeLists.txt b/lib/Bitcode/Reader/CMakeLists.txt
index 693d431..37bebc4 100644
--- a/lib/Bitcode/Reader/CMakeLists.txt
+++ b/lib/Bitcode/Reader/CMakeLists.txt
@@ -2,3 +2,8 @@ add_llvm_library(LLVMBitReader
BitReader.cpp
BitcodeReader.cpp
)
+
+add_llvm_library_dependencies(LLVMBitReader
+ LLVMCore
+ LLVMSupport
+ )
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index 85d67ce..5b3d969 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/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<unsigned, 64> 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<IntegerType>(T)->getBitWidth());
break;
case Type::PointerTyID: {
- const PointerType *PTy = cast<PointerType>(T);
+ PointerType *PTy = cast<PointerType>(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<FunctionType>(T);
+ FunctionType *FT = cast<FunctionType>(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<StructType>(T);
+ StructType *ST = cast<StructType>(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<ArrayType>(T);
+ ArrayType *AT = cast<ArrayType>(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<VectorType>(T);
+ VectorType *VT = cast<VectorType>(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<uint64_t, 64> 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<ConstantFP>(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<InvokeInst>(&I);
const Value *Callee(II->getCalledValue());
- const PointerType *PTy = cast<PointerType>(Callee->getType());
- const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+ PointerType *PTy = cast<PointerType>(Callee->getType());
+ FunctionType *FTy = cast<FunctionType>(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<LandingPadInst>(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<LoadInst>(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<LoadInst>(I).getAlignment())+1);
Vals.push_back(cast<LoadInst>(I).isVolatile());
+ if (cast<LoadInst>(I).isAtomic()) {
+ Vals.push_back(GetEncodedOrdering(cast<LoadInst>(I).getOrdering()));
+ Vals.push_back(GetEncodedSynchScope(cast<LoadInst>(I).getSynchScope()));
+ }
break;
case Instruction::Store:
- Code = bitc::FUNC_CODE_INST_STORE;
+ if (cast<StoreInst>(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<StoreInst>(I).getAlignment())+1);
Vals.push_back(cast<StoreInst>(I).isVolatile());
+ if (cast<StoreInst>(I).isAtomic()) {
+ Vals.push_back(GetEncodedOrdering(cast<StoreInst>(I).getOrdering()));
+ Vals.push_back(GetEncodedSynchScope(cast<StoreInst>(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<AtomicCmpXchgInst>(I).isVolatile());
+ Vals.push_back(GetEncodedOrdering(
+ cast<AtomicCmpXchgInst>(I).getOrdering()));
+ Vals.push_back(GetEncodedSynchScope(
+ cast<AtomicCmpXchgInst>(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<AtomicRMWInst>(I).getOperation()));
+ Vals.push_back(cast<AtomicRMWInst>(I).isVolatile());
+ Vals.push_back(GetEncodedOrdering(cast<AtomicRMWInst>(I).getOrdering()));
+ Vals.push_back(GetEncodedSynchScope(
+ cast<AtomicRMWInst>(I).getSynchScope()));
+ break;
+ case Instruction::Fence:
+ Code = bitc::FUNC_CODE_INST_FENCE;
+ Vals.push_back(GetEncodedOrdering(cast<FenceInst>(I).getOrdering()));
+ Vals.push_back(GetEncodedSynchScope(cast<FenceInst>(I).getSynchScope()));
break;
case Instruction::Call: {
const CallInst &CI = cast<CallInst>(I);
- const PointerType *PTy = cast<PointerType>(CI.getCalledValue()->getType());
- const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+ PointerType *PTy = cast<PointerType>(CI.getCalledValue()->getType());
+ FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
Code = bitc::FUNC_CODE_INST_CALL;
diff --git a/lib/Bitcode/Writer/CMakeLists.txt b/lib/Bitcode/Writer/CMakeLists.txt
index f097b09..3cf9056 100644
--- a/lib/Bitcode/Writer/CMakeLists.txt
+++ b/lib/Bitcode/Writer/CMakeLists.txt
@@ -4,3 +4,8 @@ add_llvm_library(LLVMBitWriter
BitcodeWriterPass.cpp
ValueEnumerator.cpp
)
+
+add_llvm_library_dependencies(LLVMBitWriter
+ LLVMCore
+ LLVMSupport
+ )
diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp
index b68bf92..9ae9905 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/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<StructType>(Ty))
- if (!STy->isAnonymous())
+ if (StructType *STy = dyn_cast<StructType>(Ty))
+ if (!STy->isLiteral())
*TypeID = ~0U;
// Enumerate all of the subtypes before we enumerate this type. This ensures
diff --git a/lib/Bitcode/Writer/ValueEnumerator.h b/lib/Bitcode/Writer/ValueEnumerator.h
index 6617b60..b6fc920 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.h
+++ b/lib/Bitcode/Writer/ValueEnumerator.h
@@ -35,12 +35,12 @@ class MDSymbolTable;
class ValueEnumerator {
public:
- typedef std::vector<const Type*> TypeList;
+ typedef std::vector<Type*> TypeList;
// For each value, we remember its Value* and occurrence frequency.
typedef std::vector<std::pair<const Value*, unsigned> > ValueList;
private:
- typedef DenseMap<const Type*, unsigned> TypeMapType;
+ typedef DenseMap<Type*, unsigned> 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/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 80118f0..fb63c63 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -1,4 +1,4 @@
-# `Support' library is added on the top-level CMakeLists.txt
+# `Support' and `TableGen' libraries are added on the top-level CMakeLists.txt
add_subdirectory(VMCore)
add_subdirectory(CodeGen)
@@ -7,8 +7,8 @@ add_subdirectory(Transforms)
add_subdirectory(Linker)
add_subdirectory(Analysis)
add_subdirectory(MC)
-add_subdirectory(CompilerDriver)
add_subdirectory(Object)
+add_subdirectory(DebugInfo)
add_subdirectory(ExecutionEngine)
add_subdirectory(Target)
add_subdirectory(AsmParser)
diff --git a/lib/CodeGen/Analysis.cpp b/lib/CodeGen/Analysis.cpp
index 125e641..fafc010 100644
--- a/lib/CodeGen/Analysis.cpp
+++ b/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<StructType>(Ty)) {
+ if (StructType *STy = dyn_cast<StructType>(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<ArrayType>(Ty)) {
- const Type *EltTy = ATy->getElementType();
+ else if (ArrayType *ATy = dyn_cast<ArrayType>(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<EVT> &ValueVTs,
SmallVectorImpl<uint64_t> *Offsets,
uint64_t StartingOffset) {
// Given a struct type, recursively traverse the elements.
- if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+ if (StructType *STy = dyn_cast<StructType>(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<ArrayType>(Ty)) {
- const Type *EltTy = ATy->getElementType();
+ if (ArrayType *ATy = dyn_cast<ArrayType>(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/lib/CodeGen/AsmPrinter/ARMException.cpp b/lib/CodeGen/AsmPrinter/ARMException.cpp
index 5861fa4..3f23873 100644
--- a/lib/CodeGen/AsmPrinter/ARMException.cpp
+++ b/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/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 7f314ee..1999f36 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/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<MachineMove> &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<GlobalValue>(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<MachineBasicBlock*> &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<int, Constant*> 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<ConstantArray>(List)) return;
- const ConstantArray *InitList = cast<ConstantArray>(List);
- for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
- if (ConstantStruct *CS = dyn_cast<ConstantStruct>(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<ConstantArray>(List);
+ if (!InitList) return; // Not an array!
+ StructType *ETy = dyn_cast<StructType>(InitList->getType()->getElementType());
+ if (!ETy || ETy->getNumElements() != 2) return; // Not an array of pairs!
+ if (!isa<IntegerType>(ETy->getTypeAtIndex(0U)) ||
+ !isa<PointerType>(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr).
+
+ // Gather the structors in a form that's convenient for sorting by priority.
+ SmallVector<Structor, 8> Structors;
+ for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
+ ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i));
+ if (!CS) continue; // Malformed.
+ if (CS->getOperand(1)->isNullValue())
+ break; // Found a null terminator, skip the rest.
+ ConstantInt *Priority = dyn_cast<ConstantInt>(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<Value*, 8> 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<ConstantInt>(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<uint8_t>(Value);
+
+ for (unsigned i = 1; i < Size; ++i) {
+ Value >>= 8;
+ if (static_cast<uint8_t>(Value) != Byte) return -1;
+ }
+ return Byte;
+ }
+ if (const ConstantArray *CA = dyn_cast<ConstantArray>(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/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
index dd5b0e2..4d6c281 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
+++ b/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/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 5ac455e..8eda889 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/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<SrcMgrDiagInfo *>(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<ConstantInt>(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<MCAsmParser> Parser(createMCAsmParser(TM.getTarget(), SrcMgr,
+ OwningPtr<MCAsmParser> 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<TargetAsmParser> TAP(TM.getTarget().createAsmParser(*STI, *Parser));
+ OwningPtr<MCTargetAsmParser>
+ 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/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt
index 4da7876..67d9273 100644
--- a/lib/CodeGen/AsmPrinter/CMakeLists.txt
+++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt
@@ -12,3 +12,12 @@ add_llvm_library(LLVMAsmPrinter
Win64Exception.cpp
)
+add_llvm_library_dependencies(LLVMAsmPrinter
+ LLVMAnalysis
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMMCParser
+ LLVMSupport
+ LLVMTarget
+ )
diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp
index 21396ca..9c1ce76 100644
--- a/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/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/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
index 91b7d08..8ed4f4c 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
+++ b/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<TargetLoweringObjectFile&>(TLOF).getEHFrameSection());
}
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 1fe035e..88b7524 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/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<ConstantExpr>(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<GlobalValue>(Ptr) ||
+ !isa<StructType>(cast<PointerType>(Ptr->getType())->getElementType()))
+ return NULL;
+
+ // Second operand is zero.
+ const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CE->getOperand(1));
+ if (!CI || !CI->isZero())
+ return NULL;
+
+ // Third operand is offset.
+ if (!isa<ConstantInt>(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<ConstantInt>(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<GlobalValue>(Ptr)));
+ addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
+ SmallVector<Value*, 3> 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<DIE *, const MDNode *>::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/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index 213c7fc..7859265 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -67,6 +67,11 @@ class CompileUnit {
/// DIEBlocks - A list of all the DIEBlocks in use.
std::vector<DIEBlock *> 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<DIE *, const MDNode *> 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/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 125e1e8..1b7e370 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/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<bool> PrintDbgScope("print-dbgscope", cl::Hidden,
- cl::desc("Print DbgScope information for each machine instruction"));
-
static cl::opt<bool> 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<const MachineInstr *, const MachineInstr *> 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<const MDNode> 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<DbgScope *, 4> Scopes;
- // Variables declared in scope. Contents owned.
- SmallVector<DbgVariable *, 8> Variables;
- SmallVector<DbgRange, 4> 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<DbgScope *, 4> &getScopes() { return Scopes; }
- const SmallVector<DbgVariable *, 8> &getDbgVariables() { return Variables; }
- const SmallVector<DbgRange, 4> &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<DbgRange, 4> &Ranges = Scope->getRanges();
+ const SmallVector<InsnRange, 4> &Ranges = Scope->getRanges();
if (Ranges.empty())
return 0;
- CompileUnit *TheCU = getCompileUnit(Scope->getScopeNode());
- SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin();
+ SmallVector<InsnRange, 4>::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<DbgRange, 4>::const_iterator RI = Ranges.begin(),
+ DebugRangeSymbols.size()
+ * Asm->getTargetData().getPointerSize());
+ for (SmallVector<InsnRange, 4>::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<DbgRange, 4> &Ranges = Scope->getRanges();
+ const SmallVector<InsnRange, 4> &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<DbgRange, 4>::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<InsnRange, 4>::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<InsnRange, 4>::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<const MDNode *, SmallVector<InlineInfoLabels, 4> >::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<const DbgVariable *, const DbgVariable *>::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<const DbgVariable *, const MachineInstr *>::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 <DIE *, 8> 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<DbgVariable *, 8> &Variables = Scope->getDbgVariables();
+ // Collect lexical scope children first.
+ const SmallVector<DbgVariable *, 8> &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<DbgScope *, 4> &Scopes = Scope->getScopes();
+ const SmallVector<LexicalScope *, 4> &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 MDNode *, CompileUnit *>::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<ConstantExpr>(V);
- if (!CE || CE->getNumOperands() != 3 ||
- CE->getOpcode() != Instruction::GetElementPtr)
- return NULL;
-
- // First operand points to a global value.
- if (!isa<GlobalValue>(CE->getOperand(0)))
- return NULL;
-
- // Second operand is zero.
- const ConstantInt *CI =
- dyn_cast_or_null<ConstantInt>(CE->getOperand(1));
- if (!CI || !CI->isZero())
- return NULL;
-
- // Third operand is offset.
- if (!isa<ConstantInt>(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<ConstantInt>(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<GlobalValue>(CE->getOperand(0))));
- ConstantInt *CII = cast<ConstantInt>(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<const MDNode *, DbgScope *> 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<const MDNode *, LexicalScope *> DeadFnScopeMap;
- // Construct subprogram DIE and add variables DIEs.
- constructSubprogramDIE(SP);
- DIE *ScopeDIE = getCompileUnit(SP)->getDIE(SP);
- const SmallVector<DbgVariable *, 8> &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<DIE *, const MDNode *>::iterator CI = ContainingTypeMap.begin(),
- CE = ContainingTypeMap.end(); CI != CE; ++CI) {
- DIE *SPDie = CI->first;
- const MDNode *N = dyn_cast_or_null<MDNode>(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<const MDNode *, CompileUnit *>::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<const MDNode *, CompileUnit *>::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<const MDNode *, 16> &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<unsigned, DebugLoc> &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<const MDNode *, 16> &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<MDNode>(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<MDNode>(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<DbgScope *, 4> WorkStack;
- WorkStack.push_back(Scope);
- unsigned Counter = 0;
- while (!WorkStack.empty()) {
- DbgScope *WS = WorkStack.back();
- const SmallVector<DbgScope *, 4> &Children = WS->getScopes();
- bool visitedChildren = false;
- for (SmallVector<DbgScope *, 4>::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<const MachineInstr *, DbgScope *> &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<const MachineInstr *, DbgScope *>::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<DbgRange, 4> MIRanges;
- DenseMap<const MachineInstr *, DbgScope *> 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<DbgRange, 4>::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<DbgScope *, 4> WorkList;
- WorkList.push_back(CurrentFnDbgScope);
+ SmallVector<LexicalScope *, 4> WorkList;
+ WorkList.push_back(LScopes.getCurrentFunctionScope());
while (!WorkList.empty()) {
- DbgScope *S = WorkList.pop_back_val();
+ LexicalScope *S = WorkList.pop_back_val();
- const SmallVector<DbgScope *, 4> &Children = S->getScopes();
+ const SmallVector<LexicalScope *, 4> &Children = S->getChildren();
if (!Children.empty())
- for (SmallVector<DbgScope *, 4>::const_iterator SI = Children.begin(),
+ for (SmallVector<LexicalScope *, 4>::const_iterator SI = Children.begin(),
SE = Children.end(); SI != SE; ++SI)
WorkList.push_back(*SI);
if (S->isAbstractScope())
continue;
- const SmallVector<DbgRange, 4> &Ranges = S->getRanges();
+ const SmallVector<InsnRange, 4> &Ranges = S->getRanges();
if (Ranges.empty())
continue;
- for (SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(),
+ for (SmallVector<InsnRange, 4>::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<DbgVariable *, 8> &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<const MDNode *, 16> ProcessedVars;
- collectVariableInfo(MF, ProcessedVars);
-
- // Construct abstract scopes.
- for (SmallVector<DbgScope *, 4>::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<MDNode>(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<const MDNode *, 16> 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<LexicalScope *> 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<LexicalScope *, SmallVector<DbgVariable *, 8> >::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<const DbgVariable *, int>::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<DIELabel>(Values[i]);
+ if (DIELabel *L = dyn_cast<DIELabel>(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<DIE*>::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/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index b245006..35653be 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/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 <const MDNode *, CompileUnit *> CUMap;
+ /// Maps subprogram MDNode with its corresponding CompileUnit.
+ DenseMap <const MDNode *, CompileUnit *> SPMap;
+
/// AbbreviationsSet - Used to uniquely define abbreviations.
///
FoldingSet<DIEAbbrev> AbbreviationsSet;
@@ -192,63 +222,27 @@ class DwarfDebug {
///
UniqueVector<const MCSection*> SectionMap;
- /// CurrentFnDbgScope - Top level scope for the current function.
- ///
- DbgScope *CurrentFnDbgScope;
-
/// CurrentFnArguments - List of Arguments (DbgValues) for current function.
SmallVector<DbgVariable *, 8> CurrentFnArguments;
- /// DbgScopeMap - Tracks the scopes in the current function. Owns the
- /// contained DbgScope*s.
- DenseMap<const MDNode *, DbgScope *> DbgScopeMap;
-
- /// InlinedDbgScopeMap - Tracks inlined function scopes in current function.
- DenseMap<DebugLoc, DbgScope *> InlinedDbgScopeMap;
-
- /// AbstractScopes - Tracks the abstract scopes a module. These scopes are
- /// not included DbgScopeMap. AbstractScopes owns its DbgScope*s.
- DenseMap<const MDNode *, DbgScope *> AbstractScopes;
+ LexicalScopes LScopes;
/// AbstractSPDies - Collection of abstract subprogram DIEs.
DenseMap<const MDNode *, DIE *> AbstractSPDies;
- /// AbstractScopesList - Tracks abstract scopes constructed while processing
- /// a function. This list is cleared during endFunction().
- SmallVector<DbgScope *, 4>AbstractScopesList;
+ /// ScopeVariables - Collection of dbg variables of a scope.
+ DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8> > ScopeVariables;
- /// AbstractVariables - Collection on abstract variables. Owned by the
- /// DbgScopes in AbstractScopes.
+ /// AbstractVariables - Collection on abstract variables.
DenseMap<const MDNode *, DbgVariable *> AbstractVariables;
- /// DbgVariableToFrameIndexMap - Tracks frame index used to find
- /// variable's value.
- DenseMap<const DbgVariable *, int> DbgVariableToFrameIndexMap;
-
- /// DbgVariableToDbgInstMap - Maps DbgVariable to corresponding DBG_VALUE
- /// machine instruction.
- DenseMap<const DbgVariable *, const MachineInstr *> DbgVariableToDbgInstMap;
-
/// DotDebugLocEntries - Collection of DotDebugLocEntry.
SmallVector<DotDebugLocEntry, 4> DotDebugLocEntries;
- /// UseDotDebugLocEntry - DW_AT_location attributes for the DIEs in this set
- /// idetifies corresponding .debug_loc entry offset.
- SmallPtrSet<const DIE *, 4> UseDotDebugLocEntry;
-
- /// VarToAbstractVarMap - Maps DbgVariable with corresponding Abstract
- /// DbgVariable, if any.
- DenseMap<const DbgVariable *, const DbgVariable *> VarToAbstractVarMap;
-
/// InliendSubprogramDIEs - Collection of subprgram DIEs that are marked
/// (at the end of the module) as DW_AT_inline.
SmallPtrSet<DIE *, 4> 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<DIE *, const MDNode *> ContainingTypeMap;
-
/// InlineInfo - Keep track of inlined functions and their location. This
/// information is used to populate debug_inlined section.
typedef std::pair<const MCSymbol *, DIE *> 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<const MDNode *, 16> &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/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp
index 1f992fa..18b726b 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.cpp
+++ b/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/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/lib/CodeGen/AsmPrinter/Win64Exception.cpp
index c2ad5eb..b83aa5a 100644
--- a/lib/CodeGen/AsmPrinter/Win64Exception.cpp
+++ b/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/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp
index 99090a8..75288b0 100644
--- a/lib/CodeGen/BranchFolding.cpp
+++ b/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/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 06d2a95..9a5e551 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -13,7 +13,9 @@ add_llvm_library(LLVMCodeGen
EdgeBundles.cpp
ELFCodeEmitter.cpp
ELFWriter.cpp
+ ExecutionDepsFix.cpp
ExpandISelPseudos.cpp
+ ExpandPostRAPseudos.cpp
GCMetadata.cpp
GCMetadataPrinter.cpp
GCStrategy.cpp
@@ -23,17 +25,18 @@ add_llvm_library(LLVMCodeGen
IntrinsicLowering.cpp
LLVMTargetMachine.cpp
LatencyPriorityQueue.cpp
+ LexicalScopes.cpp
LiveDebugVariables.cpp
LiveInterval.cpp
LiveIntervalAnalysis.cpp
LiveIntervalUnion.cpp
LiveStackAnalysis.cpp
LiveVariables.cpp
+ LiveRangeCalc.cpp
LiveRangeEdit.cpp
LocalStackSlotAllocation.cpp
- LowerSubregs.cpp
MachineBasicBlock.cpp
- MachineBlockFrequency.cpp
+ MachineBlockFrequencyInfo.cpp
MachineBranchProbabilityInfo.cpp
MachineCSE.cpp
MachineDominators.cpp
@@ -97,5 +100,15 @@ add_llvm_library(LLVMCodeGen
VirtRegRewriter.cpp
)
+add_llvm_library_dependencies(LLVMCodeGen
+ LLVMAnalysis
+ LLVMCore
+ LLVMMC
+ LLVMScalarOpts
+ LLVMSupport
+ LLVMTarget
+ LLVMTransformUtils
+ )
+
add_subdirectory(SelectionDAG)
add_subdirectory(AsmPrinter)
diff --git a/lib/CodeGen/CalcSpillWeights.cpp b/lib/CodeGen/CalcSpillWeights.cpp
index e6b3bbc..ea16a25 100644
--- a/lib/CodeGen/CalcSpillWeights.cpp
+++ b/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/lib/CodeGen/CodeGen.cpp b/lib/CodeGen/CodeGen.cpp
index 489746c..424535b 100644
--- a/lib/CodeGen/CodeGen.cpp
+++ b/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/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp
index 03604b0..ed9e409 100644
--- a/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/lib/CodeGen/DwarfEHPrepare.cpp
@@ -63,6 +63,8 @@ namespace {
typedef SmallPtrSet<BasicBlock*, 8> 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<ResumeInst*, 16> Resumes;
+ for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
+ TerminatorInst *TI = I->getTerminator();
+ if (ResumeInst *RI = dyn_cast<ResumeInst>(TI))
+ Resumes.push_back(RI);
+ else if (InvokeInst *II = dyn_cast<InvokeInst>(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<ResumeInst*>::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<DominatorTree>();
+ DT = &getAnalysis<DominatorTree>(); // 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/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp
index 3fb087c..660424c3 100644
--- a/lib/CodeGen/ELFCodeEmitter.cpp
+++ b/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/lib/CodeGen/ELFCodeEmitter.h b/lib/CodeGen/ELFCodeEmitter.h
index 2ec1f6e..8671c67 100644
--- a/lib/CodeGen/ELFCodeEmitter.h
+++ b/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/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp
index d977651..f2c2185 100644
--- a/lib/CodeGen/ELFWriter.cpp
+++ b/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<ConstantVector>(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<Value*, 8> 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/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp
new file mode 100644
index 0000000..01dccdb
--- /dev/null
+++ b/lib/CodeGen/ExecutionDepsFix.cpp
@@ -0,0 +1,523 @@
+//===- ExecutionDepsFix.cpp - Fix execution dependecy issues ----*- 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 execution dependency fix pass.
+//
+// Some X86 SSE instructions like mov, and, or, xor are available in different
+// variants for different operand types. These variant instructions are
+// equivalent, but on Nehalem and newer cpus there is extra latency
+// transferring data between integer and floating point domains. ARM cores
+// have similar issues when they are configured with both VFP and NEON
+// pipelines.
+//
+// This pass changes the variant instructions to minimize domain crossings.
+//
+//===----------------------------------------------------------------------===//
+
+#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"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+/// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track
+/// of execution domains.
+///
+/// An open DomainValue represents a set of instructions that can still switch
+/// execution domain. Multiple registers may refer to the same open
+/// DomainValue - they will eventually be collapsed to the same execution
+/// domain.
+///
+/// A collapsed DomainValue represents a single register that has been forced
+/// into one of more execution domains. There is a separate collapsed
+/// DomainValue for each register, but it may contain multiple execution
+/// domains. A register value is initially created in a single execution
+/// domain, but if we were forced to pay the penalty of a domain crossing, we
+/// keep track of the fact the the register is now available in multiple
+/// domains.
+namespace {
+struct DomainValue {
+ // Basic reference counting.
+ unsigned Refs;
+
+ // Bitmask of available domains. For an open DomainValue, it is the still
+ // possible domains for collapsing. For a collapsed DomainValue it is the
+ // domains where the register is available for free.
+ unsigned AvailableDomains;
+
+ // Position of the last defining instruction.
+ unsigned Dist;
+
+ // Twiddleable instructions using or defining these registers.
+ SmallVector<MachineInstr*, 8> Instrs;
+
+ // A collapsed DomainValue has no instructions to twiddle - it simply keeps
+ // track of the domains where the registers are already available.
+ bool isCollapsed() const { return Instrs.empty(); }
+
+ // Is domain available?
+ bool hasDomain(unsigned domain) const {
+ return AvailableDomains & (1u << domain);
+ }
+
+ // Mark domain as available.
+ void addDomain(unsigned domain) {
+ AvailableDomains |= 1u << domain;
+ }
+
+ // Restrict to a single domain available.
+ void setSingleDomain(unsigned domain) {
+ AvailableDomains = 1u << domain;
+ }
+
+ // Return bitmask of domains that are available and in mask.
+ unsigned getCommonDomains(unsigned mask) const {
+ return AvailableDomains & mask;
+ }
+
+ // First domain available.
+ unsigned getFirstDomain() const {
+ return CountTrailingZeros_32(AvailableDomains);
+ }
+
+ DomainValue() { clear(); }
+
+ void clear() {
+ Refs = AvailableDomains = Dist = 0;
+ Instrs.clear();
+ }
+};
+}
+
+namespace {
+class ExeDepsFix : public MachineFunctionPass {
+ static char ID;
+ SpecificBumpPtrAllocator<DomainValue> Allocator;
+ SmallVector<DomainValue*,16> Avail;
+
+ const TargetRegisterClass *const RC;
+ MachineFunction *MF;
+ const TargetInstrInfo *TII;
+ const TargetRegisterInfo *TRI;
+ MachineBasicBlock *MBB;
+ std::vector<int> AliasMap;
+ const unsigned NumRegs;
+ DomainValue **LiveRegs;
+ typedef DenseMap<MachineBasicBlock*,DomainValue**> LiveOutMap;
+ LiveOutMap LiveOuts;
+ unsigned Distance;
+
+public:
+ ExeDepsFix(const TargetRegisterClass *rc)
+ : MachineFunctionPass(ID), RC(rc), NumRegs(RC->getNumRegs()) {}
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ virtual bool runOnMachineFunction(MachineFunction &MF);
+
+ virtual const char *getPassName() const {
+ return "SSE execution domain fixup";
+ }
+
+private:
+ // Register mapping.
+ int RegIndex(unsigned Reg);
+
+ // DomainValue allocation.
+ DomainValue *Alloc(int domain = -1);
+ void Recycle(DomainValue*);
+
+ // LiveRegs manipulations.
+ void SetLiveReg(int rx, DomainValue *DV);
+ void Kill(int rx);
+ void Force(int rx, unsigned domain);
+ void Collapse(DomainValue *dv, unsigned domain);
+ bool Merge(DomainValue *A, DomainValue *B);
+
+ void enterBasicBlock();
+ void visitGenericInstr(MachineInstr*);
+ void visitSoftInstr(MachineInstr*, unsigned mask);
+ void visitHardInstr(MachineInstr*, unsigned domain);
+};
+}
+
+char ExeDepsFix::ID = 0;
+
+/// Translate TRI register number to an index into our smaller tables of
+/// interesting registers. Return -1 for boring registers.
+int ExeDepsFix::RegIndex(unsigned Reg) {
+ assert(Reg < AliasMap.size() && "Invalid register");
+ return AliasMap[Reg];
+}
+
+DomainValue *ExeDepsFix::Alloc(int domain) {
+ DomainValue *dv = Avail.empty() ?
+ new(Allocator.Allocate()) DomainValue :
+ Avail.pop_back_val();
+ dv->Dist = Distance;
+ if (domain >= 0)
+ dv->addDomain(domain);
+ return 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 ExeDepsFix::SetLiveReg(int rx, DomainValue *dv) {
+ assert(unsigned(rx) < NumRegs && "Invalid index");
+ if (!LiveRegs) {
+ LiveRegs = new DomainValue*[NumRegs];
+ std::fill(LiveRegs, LiveRegs+NumRegs, (DomainValue*)0);
+ }
+
+ if (LiveRegs[rx] == dv)
+ return;
+ if (LiveRegs[rx]) {
+ assert(LiveRegs[rx]->Refs && "Bad refcount");
+ if (--LiveRegs[rx]->Refs == 0) Recycle(LiveRegs[rx]);
+ }
+ LiveRegs[rx] = dv;
+ if (dv) ++dv->Refs;
+}
+
+// Kill register rx, recycle or collapse any DomainValue.
+void ExeDepsFix::Kill(int rx) {
+ assert(unsigned(rx) < NumRegs && "Invalid index");
+ if (!LiveRegs || !LiveRegs[rx]) return;
+
+ // Before killing the last reference to an open DomainValue, collapse it to
+ // the first available domain.
+ if (LiveRegs[rx]->Refs == 1 && !LiveRegs[rx]->isCollapsed())
+ Collapse(LiveRegs[rx], LiveRegs[rx]->getFirstDomain());
+ else
+ SetLiveReg(rx, 0);
+}
+
+/// Force register rx into domain.
+void ExeDepsFix::Force(int rx, unsigned domain) {
+ assert(unsigned(rx) < NumRegs && "Invalid index");
+ DomainValue *dv;
+ if (LiveRegs && (dv = LiveRegs[rx])) {
+ if (dv->isCollapsed())
+ dv->addDomain(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.
+ Collapse(dv, dv->getFirstDomain());
+ assert(LiveRegs[rx] && "Not live after collapse?");
+ LiveRegs[rx]->addDomain(domain);
+ }
+ } else {
+ // Set up basic collapsed DomainValue.
+ SetLiveReg(rx, Alloc(domain));
+ }
+}
+
+/// Collapse open DomainValue into given domain. If there are multiple
+/// registers using dv, they each get a unique collapsed DomainValue.
+void ExeDepsFix::Collapse(DomainValue *dv, unsigned domain) {
+ assert(dv->hasDomain(domain) && "Cannot collapse");
+
+ // Collapse all the instructions.
+ while (!dv->Instrs.empty())
+ TII->setExecutionDomain(dv->Instrs.pop_back_val(), domain);
+ dv->setSingleDomain(domain);
+
+ // If there are multiple users, give them new, unique DomainValues.
+ if (LiveRegs && dv->Refs > 1)
+ for (unsigned rx = 0; rx != NumRegs; ++rx)
+ if (LiveRegs[rx] == dv)
+ SetLiveReg(rx, Alloc(domain));
+}
+
+/// Merge - All instructions and registers in B are moved to A, and B is
+/// released.
+bool ExeDepsFix::Merge(DomainValue *A, DomainValue *B) {
+ assert(!A->isCollapsed() && "Cannot merge into collapsed");
+ assert(!B->isCollapsed() && "Cannot merge from collapsed");
+ if (A == B)
+ return true;
+ // Restrict to the domains that A and B have in common.
+ unsigned common = A->getCommonDomains(B->AvailableDomains);
+ if (!common)
+ return false;
+ A->AvailableDomains = common;
+ A->Dist = std::max(A->Dist, B->Dist);
+ A->Instrs.append(B->Instrs.begin(), B->Instrs.end());
+ for (unsigned rx = 0; rx != NumRegs; ++rx)
+ if (LiveRegs[rx] == B)
+ SetLiveReg(rx, A);
+ return true;
+}
+
+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) {
+ int rx = RegIndex(*i);
+ if (rx < 0) continue;
+ for (MachineBasicBlock::const_pred_iterator pi = MBB->pred_begin(),
+ pe = MBB->pred_end(); pi != pe; ++pi) {
+ LiveOutMap::const_iterator fi = LiveOuts.find(*pi);
+ if (fi == LiveOuts.end()) continue;
+ DomainValue *pdv = fi->second[rx];
+ if (!pdv) continue;
+ if (!LiveRegs || !LiveRegs[rx]) {
+ SetLiveReg(rx, pdv);
+ continue;
+ }
+
+ // We have a live DomainValue from more than one predecessor.
+ if (LiveRegs[rx]->isCollapsed()) {
+ // We are already collapsed, but predecessor is not. Force him.
+ unsigned domain = LiveRegs[rx]->getFirstDomain();
+ if (!pdv->isCollapsed() && pdv->hasDomain(domain))
+ Collapse(pdv, domain);
+ continue;
+ }
+
+ // Currently open, merge in predecessor.
+ if (!pdv->isCollapsed())
+ Merge(LiveRegs[rx], pdv);
+ else
+ Force(rx, pdv->getFirstDomain());
+ }
+ }
+}
+
+// A hard instruction only works in one domain. All input registers will be
+// forced into that domain.
+void ExeDepsFix::visitHardInstr(MachineInstr *mi, unsigned domain) {
+ // Collapse all uses.
+ for (unsigned i = mi->getDesc().getNumDefs(),
+ e = mi->getDesc().getNumOperands(); i != e; ++i) {
+ MachineOperand &mo = mi->getOperand(i);
+ if (!mo.isReg()) continue;
+ int rx = RegIndex(mo.getReg());
+ if (rx < 0) continue;
+ Force(rx, domain);
+ }
+
+ // Kill all defs and force them.
+ for (unsigned i = 0, e = mi->getDesc().getNumDefs(); i != e; ++i) {
+ MachineOperand &mo = mi->getOperand(i);
+ if (!mo.isReg()) continue;
+ int rx = RegIndex(mo.getReg());
+ if (rx < 0) continue;
+ Kill(rx);
+ Force(rx, domain);
+ }
+}
+
+// A soft instruction can be changed to work in other domains given by mask.
+void ExeDepsFix::visitSoftInstr(MachineInstr *mi, unsigned mask) {
+ // Bitmask of available domains for this instruction after taking collapsed
+ // operands into account.
+ unsigned available = mask;
+
+ // Scan the explicit use operands for incoming domains.
+ SmallVector<int, 4> used;
+ if (LiveRegs)
+ for (unsigned i = mi->getDesc().getNumDefs(),
+ e = mi->getDesc().getNumOperands(); i != e; ++i) {
+ MachineOperand &mo = mi->getOperand(i);
+ if (!mo.isReg()) continue;
+ int rx = RegIndex(mo.getReg());
+ if (rx < 0) continue;
+ if (DomainValue *dv = LiveRegs[rx]) {
+ // Bitmask of domains that dv and available have in common.
+ unsigned common = dv->getCommonDomains(available);
+ // Is it possible to use this collapsed register for free?
+ if (dv->isCollapsed()) {
+ // Restrict available domains to the ones in common with the operand.
+ // If there are no common domains, we must pay the cross-domain
+ // penalty for this operand.
+ if (common) available = common;
+ } else if (common)
+ // Open DomainValue is compatible, save it for merging.
+ used.push_back(rx);
+ else
+ // Open DomainValue is not compatible with instruction. It is useless
+ // now.
+ Kill(rx);
+ }
+ }
+
+ // If the collapsed operands force a single domain, propagate the collapse.
+ if (isPowerOf2_32(available)) {
+ unsigned domain = CountTrailingZeros_32(available);
+ TII->setExecutionDomain(mi, domain);
+ visitHardInstr(mi, domain);
+ return;
+ }
+
+ // Kill off any remaining uses that don't match available, and build a list of
+ // incoming DomainValues that we want to merge.
+ SmallVector<DomainValue*,4> doms;
+ for (SmallVector<int, 4>::iterator i=used.begin(), e=used.end(); i!=e; ++i) {
+ int rx = *i;
+ DomainValue *dv = LiveRegs[rx];
+ // This useless DomainValue could have been missed above.
+ if (!dv->getCommonDomains(available)) {
+ Kill(*i);
+ continue;
+ }
+ // sorted, uniqued insert.
+ bool inserted = false;
+ for (SmallVector<DomainValue*,4>::iterator i = doms.begin(), e = doms.end();
+ i != e && !inserted; ++i) {
+ if (dv == *i)
+ inserted = true;
+ else if (dv->Dist < (*i)->Dist) {
+ inserted = true;
+ doms.insert(i, dv);
+ }
+ }
+ if (!inserted)
+ doms.push_back(dv);
+ }
+
+ // doms are now sorted in order of appearance. Try to merge them all, giving
+ // priority to the latest ones.
+ DomainValue *dv = 0;
+ while (!doms.empty()) {
+ if (!dv) {
+ dv = doms.pop_back_val();
+ continue;
+ }
+
+ DomainValue *latest = doms.pop_back_val();
+ if (Merge(dv, latest)) continue;
+
+ // If latest didn't merge, it is useless now. Kill all registers using it.
+ for (SmallVector<int,4>::iterator i=used.begin(), e=used.end(); i != e; ++i)
+ if (LiveRegs[*i] == latest)
+ Kill(*i);
+ }
+
+ // dv is the DomainValue we are going to use for this instruction.
+ if (!dv)
+ dv = Alloc();
+ dv->Dist = Distance;
+ dv->AvailableDomains = available;
+ dv->Instrs.push_back(mi);
+
+ // Finally set all defs and non-collapsed uses to dv.
+ for (unsigned i = 0, e = mi->getDesc().getNumOperands(); i != e; ++i) {
+ MachineOperand &mo = mi->getOperand(i);
+ if (!mo.isReg()) continue;
+ int rx = RegIndex(mo.getReg());
+ if (rx < 0) continue;
+ if (!LiveRegs || !LiveRegs[rx] || (mo.isDef() && LiveRegs[rx]!=dv)) {
+ Kill(rx);
+ SetLiveReg(rx, dv);
+ }
+ }
+}
+
+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;
+ int rx = RegIndex(mo.getReg());
+ if (rx < 0) continue;
+ Kill(rx);
+ }
+}
+
+bool ExeDepsFix::runOnMachineFunction(MachineFunction &mf) {
+ MF = &mf;
+ TII = MF->getTarget().getInstrInfo();
+ TRI = MF->getTarget().getRegisterInfo();
+ MBB = 0;
+ LiveRegs = 0;
+ Distance = 0;
+ assert(NumRegs == RC->getNumRegs() && "Bad regclass");
+
+ // If no relevant registers are used in the function, we can skip it
+ // completely.
+ bool anyregs = false;
+ 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<MachineBasicBlock*, 16> Visited;
+ for (df_ext_iterator<MachineBasicBlock*, SmallPtrSet<MachineBasicBlock*, 16> >
+ DFI = df_ext_begin(Entry, Visited), DFE = df_ext_end(Entry, Visited);
+ DFI != DFE; ++DFI) {
+ MBB = *DFI;
+ enterBasicBlock();
+ for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
+ ++I) {
+ MachineInstr *mi = I;
+ if (mi->isDebugValue()) continue;
+ ++Distance;
+ std::pair<uint16_t, uint16_t> domp = TII->getExecutionDomain(mi);
+ if (domp.first)
+ if (domp.second)
+ visitSoftInstr(mi, domp.second);
+ else
+ visitHardInstr(mi, domp.first);
+ else if (LiveRegs)
+ visitGenericInstr(mi);
+ }
+
+ // Save live registers at end of MBB - used by enterBasicBlock().
+ if (LiveRegs)
+ LiveOuts.insert(std::make_pair(MBB, LiveRegs));
+ LiveRegs = 0;
+ }
+
+ // Clear the LiveOuts vectors. Should we also collapse any remaining
+ // DomainValues?
+ for (LiveOutMap::const_iterator i = LiveOuts.begin(), e = LiveOuts.end();
+ i != e; ++i)
+ delete[] i->second;
+ LiveOuts.clear();
+ Avail.clear();
+ Allocator.DestroyAll();
+
+ return false;
+}
+
+FunctionPass *
+llvm::createExecutionDependencyFixPass(const TargetRegisterClass *RC) {
+ return new ExeDepsFix(RC);
+}
diff --git a/lib/CodeGen/ExpandPostRAPseudos.cpp b/lib/CodeGen/ExpandPostRAPseudos.cpp
new file mode 100644
index 0000000..e2a14a8
--- /dev/null
+++ b/lib/CodeGen/ExpandPostRAPseudos.cpp
@@ -0,0 +1,237 @@
+//===-- ExpandPostRAPseudos.cpp - Pseudo instruction expansion pass -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a pass that expands COPY and SUBREG_TO_REG pseudo
+// instructions after register allocation.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "postrapseudos"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Function.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+namespace {
+struct ExpandPostRA : public MachineFunctionPass {
+private:
+ const TargetRegisterInfo *TRI;
+ const TargetInstrInfo *TII;
+
+public:
+ static char ID; // Pass identification, replacement for typeid
+ ExpandPostRA() : MachineFunctionPass(ID) {}
+
+ 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);
+ }
+
+ /// runOnMachineFunction - pass entry point
+ bool runOnMachineFunction(MachineFunction&);
+
+private:
+ bool LowerSubregToReg(MachineInstr *MI);
+ bool LowerCopy(MachineInstr *MI);
+
+ void TransferDeadFlag(MachineInstr *MI, unsigned DstReg,
+ const TargetRegisterInfo *TRI);
+ void TransferImplicitDefs(MachineInstr *MI);
+};
+} // end anonymous namespace
+
+char ExpandPostRA::ID = 0;
+
+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
+ExpandPostRA::TransferDeadFlag(MachineInstr *MI, unsigned DstReg,
+ const TargetRegisterInfo *TRI) {
+ for (MachineBasicBlock::iterator MII =
+ prior(MachineBasicBlock::iterator(MI)); ; --MII) {
+ if (MII->addRegisterDead(DstReg, TRI))
+ break;
+ assert(MII != MI->getParent()->begin() &&
+ "copyPhysReg output doesn't reference destination register!");
+ }
+}
+
+/// TransferImplicitDefs - MI is a pseudo-instruction, and the lowered
+/// replacement instructions immediately precede it. Copy any implicit-def
+/// operands from MI to the replacement instruction.
+void
+ExpandPostRA::TransferImplicitDefs(MachineInstr *MI) {
+ MachineBasicBlock::iterator CopyMI = MI;
+ --CopyMI;
+
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ MachineOperand &MO = MI->getOperand(i);
+ if (!MO.isReg() || !MO.isImplicit() || MO.isUse())
+ continue;
+ CopyMI->addOperand(MachineOperand::CreateReg(MO.getReg(), true, true));
+ }
+}
+
+bool ExpandPostRA::LowerSubregToReg(MachineInstr *MI) {
+ MachineBasicBlock *MBB = MI->getParent();
+ assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) &&
+ MI->getOperand(1).isImm() &&
+ (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) &&
+ MI->getOperand(3).isImm() && "Invalid subreg_to_reg");
+
+ unsigned DstReg = MI->getOperand(0).getReg();
+ unsigned InsReg = MI->getOperand(2).getReg();
+ assert(!MI->getOperand(2).getSubReg() && "SubIdx on physreg?");
+ unsigned SubIdx = MI->getOperand(3).getImm();
+
+ assert(SubIdx != 0 && "Invalid index for insert_subreg");
+ unsigned DstSubReg = TRI->getSubReg(DstReg, SubIdx);
+
+ assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
+ "Insert destination must be in a physical register");
+ assert(TargetRegisterInfo::isPhysicalRegister(InsReg) &&
+ "Inserted value must be in a physical register");
+
+ DEBUG(dbgs() << "subreg: CONVERTING: " << *MI);
+
+ if (DstSubReg == InsReg) {
+ // No need to insert an identify copy instruction.
+ // Watch out for case like this:
+ // %RAX<def> = SUBREG_TO_REG 0, %EAX<kill>, 3
+ // We must leave %RAX live.
+ if (DstReg != InsReg) {
+ MI->setDesc(TII->get(TargetOpcode::KILL));
+ MI->RemoveOperand(3); // SubIdx
+ MI->RemoveOperand(1); // Imm
+ DEBUG(dbgs() << "subreg: replace by: " << *MI);
+ return true;
+ }
+ DEBUG(dbgs() << "subreg: eliminated!");
+ } else {
+ TII->copyPhysReg(*MBB, MI, MI->getDebugLoc(), DstSubReg, InsReg,
+ MI->getOperand(2).isKill());
+ // Transfer the kill/dead flags, if needed.
+ if (MI->getOperand(0).isDead())
+ TransferDeadFlag(MI, DstSubReg, TRI);
+ DEBUG({
+ MachineBasicBlock::iterator dMI = MI;
+ dbgs() << "subreg: " << *(--dMI);
+ });
+ }
+
+ DEBUG(dbgs() << '\n');
+ MBB->erase(MI);
+ return true;
+}
+
+bool ExpandPostRA::LowerCopy(MachineInstr *MI) {
+ MachineOperand &DstMO = MI->getOperand(0);
+ MachineOperand &SrcMO = MI->getOperand(1);
+
+ if (SrcMO.getReg() == DstMO.getReg()) {
+ DEBUG(dbgs() << "identity copy: " << *MI);
+ // No need to insert an identity copy instruction, but replace with a KILL
+ // if liveness is changed.
+ if (DstMO.isDead() || SrcMO.isUndef() || MI->getNumOperands() > 2) {
+ // We must make sure the super-register gets killed. Replace the
+ // instruction with KILL.
+ MI->setDesc(TII->get(TargetOpcode::KILL));
+ DEBUG(dbgs() << "replaced by: " << *MI);
+ return true;
+ }
+ // Vanilla identity copy.
+ MI->eraseFromParent();
+ return true;
+ }
+
+ DEBUG(dbgs() << "real copy: " << *MI);
+ TII->copyPhysReg(*MI->getParent(), MI, MI->getDebugLoc(),
+ DstMO.getReg(), SrcMO.getReg(), SrcMO.isKill());
+
+ if (DstMO.isDead())
+ TransferDeadFlag(MI, DstMO.getReg(), TRI);
+ if (MI->getNumOperands() > 2)
+ TransferImplicitDefs(MI);
+ DEBUG({
+ MachineBasicBlock::iterator dMI = MI;
+ dbgs() << "replaced by: " << *(--dMI);
+ });
+ MI->eraseFromParent();
+ return true;
+}
+
+/// runOnMachineFunction - Reduce subregister inserts and extracts to register
+/// copies.
+///
+bool ExpandPostRA::runOnMachineFunction(MachineFunction &MF) {
+ DEBUG(dbgs() << "Machine Function\n"
+ << "********** EXPANDING POST-RA PSEUDO INSTRS **********\n"
+ << "********** Function: "
+ << MF.getFunction()->getName() << '\n');
+ TRI = MF.getTarget().getRegisterInfo();
+ TII = MF.getTarget().getInstrInfo();
+
+ bool MadeChange = false;
+
+ for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end();
+ mbbi != mbbe; ++mbbi) {
+ for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end();
+ mi != me;) {
+ MachineInstr *MI = mi;
+ // 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);
+ 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.");
+ }
+ }
+ }
+
+ return MadeChange;
+}
diff --git a/lib/CodeGen/IfConversion.cpp b/lib/CodeGen/IfConversion.cpp
index 6cb2277..ce7ed29 100644
--- a/lib/CodeGen/IfConversion.cpp
+++ b/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<MachineLoopInfo>();
+ AU.addRequired<MachineBranchProbabilityInfo>();
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<MachineLoopInfo>();
+ MBPI = &getAnalysis<MachineBranchProbabilityInfo>();
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/lib/CodeGen/InlineSpiller.cpp b/lib/CodeGen/InlineSpiller.cpp
index 5547f73..726af46 100644
--- a/lib/CodeGen/InlineSpiller.cpp
+++ b/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<bool> 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<VNInfo*, 8> 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<VNInfo*> 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<VNInfo*, SibValueInfo> 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<VNInfo*> 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<SibValueMap::iterator, 8> WorkList(1, SVI);
+ SmallPtrSet<VNInfo*, 8> WorkSet;
+
+ do {
+ SVI = WorkList.pop_back_val();
+ WorkSet.erase(SVI->first);
+ TinyPtrVector<VNInfo*> *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<VNInfo*>::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<kill>
+ //
+ // 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<VNInfo*, 8> Visited;
+
+ // List of (Reg, VNI) that have been inserted into SibValues, but need to be
+ // processed.
SmallVector<std::pair<unsigned, VNInfo*>, 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<kill>
- //
- 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<VNInfo*, 8> 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 <undef> 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<unsigned> &Ops,
MachineInstr *LoadMI) {
+ bool WasCopy = MI->isCopy();
// TargetInstrInfo::foldMemoryOperand only expects explicit, non-tied
// operands.
SmallVector<unsigned, 8> 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/lib/CodeGen/InterferenceCache.cpp b/lib/CodeGen/InterferenceCache.cpp
index a09bb39..29b47bd 100644
--- a/lib/CodeGen/InterferenceCache.cpp
+++ b/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/lib/CodeGen/InterferenceCache.h b/lib/CodeGen/InterferenceCache.h
index 7f0a27a..4df0a9e 100644
--- a/lib/CodeGen/InterferenceCache.h
+++ b/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/lib/CodeGen/IntrinsicLowering.cpp b/lib/CodeGen/IntrinsicLowering.cpp
index 611886f..0f92c2d 100644
--- a/lib/CodeGen/IntrinsicLowering.cpp
+++ b/lib/CodeGen/IntrinsicLowering.cpp
@@ -27,7 +27,7 @@ using namespace llvm;
template <class ArgIt>
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<Type *> ParamTys;
for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
@@ -64,7 +64,7 @@ static void EnsureFPIntrinsicsExist(Module &M, Function *Fn,
template <class ArgIt>
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/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp
index f985af8..80ecc22 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/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<bool> DisableCodePlace("disable-code-place", cl::Hidden,
cl::desc("Disable code placement"));
static cl::opt<bool> DisableSSC("disable-ssc", cl::Hidden,
cl::desc("Disable Stack Slot Coloring"));
+static cl::opt<bool> DisableMachineDCE("disable-machine-dce", cl::Hidden,
+ cl::desc("Disable Machine Dead Code Elimination"));
static cl::opt<bool> DisableMachineLICM("disable-machine-licm", cl::Hidden,
cl::desc("Disable Machine LICM"));
+static cl::opt<bool> DisableMachineCSE("disable-machine-cse", cl::Hidden,
+ cl::desc("Disable Machine Common Subexpression Elimination"));
static cl::opt<bool> 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<MCSubtargetInfo>();
OwningPtr<MCStreamer> 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<MCSubtargetInfo>();
- 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<MCSubtargetInfo>();
- 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<MCSubtargetInfo>();
- 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<MCStreamer> 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/lib/CodeGen/LexicalScopes.cpp b/lib/CodeGen/LexicalScopes.cpp
new file mode 100644
index 0000000..a12e1a3
--- /dev/null
+++ b/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<InsnRange, 4> MIRanges;
+ DenseMap<const MachineInstr *, LexicalScope *> 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<InsnRange> &MIRanges,
+ DenseMap<const MachineInstr *, LexicalScope *> &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<LexicalScope *, 4> WorkStack;
+ WorkStack.push_back(Scope);
+ unsigned Counter = 0;
+ while (!WorkStack.empty()) {
+ LexicalScope *WS = WorkStack.back();
+ const SmallVector<LexicalScope *, 4> &Children = WS->getChildren();
+ bool visitedChildren = false;
+ for (SmallVector<LexicalScope *, 4>::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<InsnRange> &MIRanges,
+ DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap)
+{
+
+ LexicalScope *PrevLexicalScope = NULL;
+ for (SmallVectorImpl<InsnRange>::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<const MachineBasicBlock*, 4> &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<InsnRange, 4> &InsnRanges = Scope->getRanges();
+ for (SmallVector<InsnRange, 4>::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/lib/CodeGen/LiveDebugVariables.cpp b/lib/CodeGen/LiveDebugVariables.cpp
index 5d38c83..3dfe4c0 100644
--- a/lib/CodeGen/LiveDebugVariables.cpp
+++ b/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<bool>
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<SlotIndex, unsigned, 4> LocMap;
+namespace {
+/// UserValueScopes - Keeps track of lexical scopes associated with an
+/// user value's source location.
+class UserValueScopes {
+ DebugLoc DL;
+ LexicalScopes &LS;
+ SmallPtrSet<const MachineBasicBlock *, 4> 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<SlotIndex> *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<MDString>(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<SlotIndex> *Kills,
- LiveIntervals &LIS, MachineDominatorTree &MDT) {
+ LiveIntervals &LIS, MachineDominatorTree &MDT,
+ UserValueScopes &UVS) {
SmallVector<SlotIndex, 16> 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<MachineDomTreeNode*> &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<std::pair<SlotIndex, unsigned>, 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<SlotIndex, 16> 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<MachineDominatorTree>();
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/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp
index cfade24..b69945a 100644
--- a/lib/CodeGen/LiveInterval.cpp
+++ b/lib/CodeGen/LiveInterval.cpp
@@ -148,7 +148,6 @@ void LiveInterval::markValNoForDeletion(VNInfo *ValNo) {
/// remaining unused values.
void LiveInterval::RenumberValues(LiveIntervals &lis) {
SmallPtrSet<VNInfo*, 8> 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/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index 9257191..b1e202a 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/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
// <imp-def> 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 <undef> 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 <undef>.
+ 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<std::pair<SlotIndex, VNInfo*>, 16> WorkList;
+ // Blocks that have already been added to WorkList as live-out.
+ SmallPtrSet<MachineBasicBlock*, 16> 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/lib/CodeGen/LiveIntervalUnion.cpp b/lib/CodeGen/LiveIntervalUnion.cpp
index 70003e7..110fe1e 100644
--- a/lib/CodeGen/LiveIntervalUnion.cpp
+++ b/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/lib/CodeGen/LiveIntervalUnion.h b/lib/CodeGen/LiveIntervalUnion.h
index 5e78d5e..5d64d28 100644
--- a/lib/CodeGen/LiveIntervalUnion.h
+++ b/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<LiveInterval*,4> 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/lib/CodeGen/LiveRangeCalc.cpp b/lib/CodeGen/LiveRangeCalc.cpp
new file mode 100644
index 0000000..a7d5af5
--- /dev/null
+++ b/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<LiveInBlock>::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<MachineBasicBlock*, 16> 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<LiveInBlock>::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/lib/CodeGen/LiveRangeCalc.h b/lib/CodeGen/LiveRangeCalc.h
new file mode 100644
index 0000000..b8c8585
--- /dev/null
+++ b/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 NodeT> class DomTreeNodeBase;
+typedef DomTreeNodeBase<MachineBasicBlock> 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<VNInfo*, MachineDomTreeNode*> LiveOutPair;
+
+ /// LiveOutMap - Map basic blocks to the value leaving the block.
+ typedef IndexedMap<LiveOutPair, MBB2NumberFunctor> 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<LiveInBlock, 16> 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/lib/CodeGen/LiveRangeEdit.cpp b/lib/CodeGen/LiveRangeEdit.cpp
index b385fb3..b23f851 100644
--- a/lib/CodeGen/LiveRangeEdit.cpp
+++ b/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/lib/CodeGen/LiveRangeEdit.h b/lib/CodeGen/LiveRangeEdit.h
index db6740c..9b0a671 100644
--- a/lib/CodeGen/LiveRangeEdit.h
+++ b/lib/CodeGen/LiveRangeEdit.h
@@ -115,7 +115,7 @@ public:
LiveInterval *get(unsigned idx) const { return newRegs_[idx+firstNew_]; }
ArrayRef<LiveInterval*> regs() const {
- return ArrayRef<LiveInterval*>(newRegs_).slice(firstNew_);
+ return makeArrayRef(newRegs_).slice(firstNew_);
}
/// FIXME: Temporary accessors until we can get rid of
diff --git a/lib/CodeGen/LiveStackAnalysis.cpp b/lib/CodeGen/LiveStackAnalysis.cpp
index c75196a..939e795 100644
--- a/lib/CodeGen/LiveStackAnalysis.cpp
+++ b/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/lib/CodeGen/LiveVariables.cpp b/lib/CodeGen/LiveVariables.cpp
index 20bad60..2ca90f9 100644
--- a/lib/CodeGen/LiveVariables.cpp
+++ b/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/lib/CodeGen/LowerSubregs.cpp b/lib/CodeGen/LowerSubregs.cpp
deleted file mode 100644
index 7871ba9..0000000
--- a/lib/CodeGen/LowerSubregs.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-//===-- LowerSubregs.cpp - Subregister Lowering instruction pass ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a 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.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "lowersubregs"
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/Function.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-namespace {
- struct LowerSubregsInstructionPass : public MachineFunctionPass {
- private:
- const TargetRegisterInfo *TRI;
- const TargetInstrInfo *TII;
-
- public:
- static char ID; // Pass identification, replacement for typeid
- LowerSubregsInstructionPass() : MachineFunctionPass(ID) {}
-
- const char *getPassName() const {
- return "Subregister lowering instruction pass";
- }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesCFG();
- AU.addPreservedID(MachineLoopInfoID);
- AU.addPreservedID(MachineDominatorsID);
- MachineFunctionPass::getAnalysisUsage(AU);
- }
-
- /// runOnMachineFunction - pass entry point
- bool runOnMachineFunction(MachineFunction&);
-
- private:
- bool LowerSubregToReg(MachineInstr *MI);
- bool LowerCopy(MachineInstr *MI);
-
- void TransferDeadFlag(MachineInstr *MI, unsigned DstReg,
- const TargetRegisterInfo *TRI);
- void TransferImplicitDefs(MachineInstr *MI);
- };
-
- char LowerSubregsInstructionPass::ID = 0;
-}
-
-FunctionPass *llvm::createLowerSubregsPass() {
- return new LowerSubregsInstructionPass();
-}
-
-/// 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) {
- for (MachineBasicBlock::iterator MII =
- prior(MachineBasicBlock::iterator(MI)); ; --MII) {
- if (MII->addRegisterDead(DstReg, TRI))
- break;
- assert(MII != MI->getParent()->begin() &&
- "copyPhysReg output doesn't reference destination register!");
- }
-}
-
-/// TransferImplicitDefs - MI is a pseudo-instruction, and the lowered
-/// replacement instructions immediately precede it. Copy any implicit-def
-/// operands from MI to the replacement instruction.
-void
-LowerSubregsInstructionPass::TransferImplicitDefs(MachineInstr *MI) {
- MachineBasicBlock::iterator CopyMI = MI;
- --CopyMI;
-
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand &MO = MI->getOperand(i);
- if (!MO.isReg() || !MO.isImplicit() || MO.isUse())
- continue;
- CopyMI->addOperand(MachineOperand::CreateReg(MO.getReg(), true, true));
- }
-}
-
-bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) {
- MachineBasicBlock *MBB = MI->getParent();
- assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) &&
- MI->getOperand(1).isImm() &&
- (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) &&
- MI->getOperand(3).isImm() && "Invalid subreg_to_reg");
-
- unsigned DstReg = MI->getOperand(0).getReg();
- unsigned InsReg = MI->getOperand(2).getReg();
- assert(!MI->getOperand(2).getSubReg() && "SubIdx on physreg?");
- unsigned SubIdx = MI->getOperand(3).getImm();
-
- assert(SubIdx != 0 && "Invalid index for insert_subreg");
- unsigned DstSubReg = TRI->getSubReg(DstReg, SubIdx);
-
- assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
- "Insert destination must be in a physical register");
- assert(TargetRegisterInfo::isPhysicalRegister(InsReg) &&
- "Inserted value must be in a physical register");
-
- DEBUG(dbgs() << "subreg: CONVERTING: " << *MI);
-
- if (DstSubReg == InsReg) {
- // No need to insert an identify copy instruction.
- // Watch out for case like this:
- // %RAX<def> = SUBREG_TO_REG 0, %EAX<kill>, 3
- // We must leave %RAX live.
- if (DstReg != InsReg) {
- MI->setDesc(TII->get(TargetOpcode::KILL));
- MI->RemoveOperand(3); // SubIdx
- MI->RemoveOperand(1); // Imm
- DEBUG(dbgs() << "subreg: replace by: " << *MI);
- return true;
- }
- DEBUG(dbgs() << "subreg: eliminated!");
- } else {
- TII->copyPhysReg(*MBB, MI, MI->getDebugLoc(), DstSubReg, InsReg,
- MI->getOperand(2).isKill());
- // Transfer the kill/dead flags, if needed.
- if (MI->getOperand(0).isDead())
- TransferDeadFlag(MI, DstSubReg, TRI);
- DEBUG({
- MachineBasicBlock::iterator dMI = MI;
- dbgs() << "subreg: " << *(--dMI);
- });
- }
-
- DEBUG(dbgs() << '\n');
- MBB->erase(MI);
- return true;
-}
-
-bool LowerSubregsInstructionPass::LowerCopy(MachineInstr *MI) {
- MachineOperand &DstMO = MI->getOperand(0);
- MachineOperand &SrcMO = MI->getOperand(1);
-
- if (SrcMO.getReg() == DstMO.getReg()) {
- DEBUG(dbgs() << "identity copy: " << *MI);
- // No need to insert an identity copy instruction, but replace with a KILL
- // if liveness is changed.
- if (DstMO.isDead() || SrcMO.isUndef() || MI->getNumOperands() > 2) {
- // We must make sure the super-register gets killed. Replace the
- // instruction with KILL.
- MI->setDesc(TII->get(TargetOpcode::KILL));
- DEBUG(dbgs() << "replaced by: " << *MI);
- return true;
- }
- // Vanilla identity copy.
- MI->eraseFromParent();
- return true;
- }
-
- DEBUG(dbgs() << "real copy: " << *MI);
- TII->copyPhysReg(*MI->getParent(), MI, MI->getDebugLoc(),
- DstMO.getReg(), SrcMO.getReg(), SrcMO.isKill());
-
- if (DstMO.isDead())
- TransferDeadFlag(MI, DstMO.getReg(), TRI);
- if (MI->getNumOperands() > 2)
- TransferImplicitDefs(MI);
- DEBUG({
- MachineBasicBlock::iterator dMI = MI;
- dbgs() << "replaced by: " << *(--dMI);
- });
- MI->eraseFromParent();
- return true;
-}
-
-/// runOnMachineFunction - Reduce subregister inserts and extracts to register
-/// copies.
-///
-bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) {
- DEBUG(dbgs() << "Machine Function\n"
- << "********** LOWERING SUBREG INSTRS **********\n"
- << "********** Function: "
- << MF.getFunction()->getName() << '\n');
- TRI = MF.getTarget().getRegisterInfo();
- TII = MF.getTarget().getInstrInfo();
-
- bool MadeChange = false;
-
- for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end();
- 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()) {
- MadeChange |= LowerSubregToReg(MI);
- } else if (MI->isCopy()) {
- MadeChange |= LowerCopy(MI);
- }
- mi = nmi;
- }
- }
-
- return MadeChange;
-}
diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp
index 8f0fb46..4c5fe4c 100644
--- a/lib/CodeGen/MachineBasicBlock.cpp
+++ b/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/lib/CodeGen/MachineBlockFrequency.cpp b/lib/CodeGen/MachineBlockFrequency.cpp
deleted file mode 100644
index 893a320..0000000
--- a/lib/CodeGen/MachineBlockFrequency.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-//====----- MachineBlockFrequency.cpp - Machine 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/CodeGen/MachineBlockFrequency.h"
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
-
-using namespace llvm;
-
-INITIALIZE_PASS_BEGIN(MachineBlockFrequency, "machine-block-freq",
- "Machine Block Frequency Analysis", true, true)
-INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
-INITIALIZE_PASS_END(MachineBlockFrequency, "machine-block-freq",
- "Machine Block Frequency Analysis", true, true)
-
-char MachineBlockFrequency::ID = 0;
-
-
-MachineBlockFrequency::MachineBlockFrequency() : MachineFunctionPass(ID) {
- initializeMachineBlockFrequencyPass(*PassRegistry::getPassRegistry());
- MBFI = new BlockFrequencyImpl<MachineBasicBlock, MachineFunction,
- MachineBranchProbabilityInfo>();
-}
-
-MachineBlockFrequency::~MachineBlockFrequency() {
- delete MBFI;
-}
-
-void MachineBlockFrequency::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<MachineBranchProbabilityInfo>();
- AU.setPreservesAll();
-}
-
-bool MachineBlockFrequency::runOnMachineFunction(MachineFunction &F) {
- MachineBranchProbabilityInfo &MBPI = getAnalysis<MachineBranchProbabilityInfo>();
- 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.
-///
-uint32_t MachineBlockFrequency::getBlockFreq(MachineBasicBlock *MBB) {
- return MBFI->getBlockFreq(MBB);
-}
diff --git a/lib/CodeGen/MachineBlockFrequencyInfo.cpp b/lib/CodeGen/MachineBlockFrequencyInfo.cpp
new file mode 100644
index 0000000..b92cda9
--- /dev/null
+++ b/lib/CodeGen/MachineBlockFrequencyInfo.cpp
@@ -0,0 +1,61 @@
+//====----- MachineBlockFrequencyInfo.cpp - Machine 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/CodeGen/MachineBlockFrequencyInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
+
+using namespace llvm;
+
+INITIALIZE_PASS_BEGIN(MachineBlockFrequencyInfo, "machine-block-freq",
+ "Machine Block Frequency Analysis", true, true)
+INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
+INITIALIZE_PASS_END(MachineBlockFrequencyInfo, "machine-block-freq",
+ "Machine Block Frequency Analysis", true, true)
+
+char MachineBlockFrequencyInfo::ID = 0;
+
+
+MachineBlockFrequencyInfo::MachineBlockFrequencyInfo() : MachineFunctionPass(ID) {
+ initializeMachineBlockFrequencyInfoPass(*PassRegistry::getPassRegistry());
+ MBFI = new BlockFrequencyImpl<MachineBasicBlock, MachineFunction,
+ MachineBranchProbabilityInfo>();
+}
+
+MachineBlockFrequencyInfo::~MachineBlockFrequencyInfo() {
+ delete MBFI;
+}
+
+void MachineBlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<MachineBranchProbabilityInfo>();
+ AU.setPreservesAll();
+ MachineFunctionPass::getAnalysisUsage(AU);
+}
+
+bool MachineBlockFrequencyInfo::runOnMachineFunction(MachineFunction &F) {
+ MachineBranchProbabilityInfo &MBPI = getAnalysis<MachineBranchProbabilityInfo>();
+ MBFI->doFunction(&F, &MBPI);
+ return false;
+}
+
+/// 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 MachineBlockFrequencyInfo::
+getBlockFreq(MachineBasicBlock *MBB) const {
+ return MBFI->getBlockFreq(MBB);
+}
diff --git a/lib/CodeGen/MachineCSE.cpp b/lib/CodeGen/MachineCSE.cpp
index 3a60a37..7eda8c1 100644
--- a/lib/CodeGen/MachineCSE.cpp
+++ b/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/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp
index cd25156..20066a0 100644
--- a/lib/CodeGen/MachineFunction.cpp
+++ b/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/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp
index 143a29b..a240667 100644
--- a/lib/CodeGen/MachineInstr.cpp
+++ b/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 <def,undef> 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/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp
index 722ceb2..a1f80d5 100644
--- a/lib/CodeGen/MachineLICM.cpp
+++ b/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<bool>
+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<unsigned, std::vector<const MachineInstr*> > 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<unsigned, std::vector<const MachineInstr*> >::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<MachineBasicBlock*> 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<MachineBasicBlock*, 8> 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<unsigned, int>::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<unsigned, int>::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<unsigned, int>::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<unsigned, std::vector<const MachineInstr*> >::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/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp
index fadc594..80c4854 100644
--- a/lib/CodeGen/MachineModuleInfo.cpp
+++ b/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<const GlobalVariable *> &TyInfo) {
+void MachineModuleInfo::
+addCatchTypeInfo(MachineBasicBlock *LandingPad,
+ ArrayRef<const GlobalVariable *> 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<const GlobalVariable *> &TyInfo) {
+void MachineModuleInfo::
+addFilterTypeInfo(MachineBasicBlock *LandingPad,
+ ArrayRef<const GlobalVariable *> TyInfo) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
std::vector<unsigned> IdsInFilter(TyInfo.size());
for (unsigned I = 0, E = TyInfo.size(); I != E; ++I)
@@ -496,6 +499,14 @@ void MachineModuleInfo::TidyLandingPads(DenseMap<MCSymbol*, uintptr_t> *LPMap) {
}
}
+/// setCallSiteLandingPad - Map the landing pad's EH symbol to the call site
+/// indexes.
+void MachineModuleInfo::setCallSiteLandingPad(MCSymbol *Sym,
+ ArrayRef<unsigned> 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/lib/CodeGen/MachineRegisterInfo.cpp b/lib/CodeGen/MachineRegisterInfo.cpp
index 4b3e64c..266ebf6 100644
--- a/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/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/lib/CodeGen/MachineSink.cpp b/lib/CodeGen/MachineSink.cpp
index 916dff7..29cfb49 100644
--- a/lib/CodeGen/MachineSink.cpp
+++ b/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<MachineInstr *, 2> & 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<MachineInstr *, 2> DbgValuesToSink;
+ collectDebugValues(MI, DbgValuesToSink);
+
// Move the instruction.
SuccToSinkTo->splice(InsertPos, ParentBlock, MI,
++MachineBasicBlock::iterator(MI));
+ // Move debug values.
+ for (SmallVector<MachineInstr *, 2>::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/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp
index 7a55852..26847d3 100644
--- a/lib/CodeGen/MachineVerifier.cpp
+++ b/lib/CodeGen/MachineVerifier.cpp
@@ -72,6 +72,8 @@ namespace {
typedef DenseSet<unsigned> RegSet;
typedef DenseMap<unsigned, const MachineInstr*> 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<MachineBasicBlock*, 4> 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/lib/CodeGen/PHIElimination.cpp b/lib/CodeGen/PHIElimination.cpp
index af65f13..6994aa5 100644
--- a/lib/CodeGen/PHIElimination.cpp
+++ b/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<LiveVariables>()) {
diff --git a/lib/CodeGen/PeepholeOptimizer.cpp b/lib/CodeGen/PeepholeOptimizer.cpp
index c523e39..bbc7ce2 100644
--- a/lib/CodeGen/PeepholeOptimizer.cpp
+++ b/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/lib/CodeGen/ProcessImplicitDefs.cpp b/lib/CodeGen/ProcessImplicitDefs.cpp
index c04d656..b1d8c97 100644
--- a/lib/CodeGen/ProcessImplicitDefs.cpp
+++ b/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/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp
index a901c5f..32c9325 100644
--- a/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/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/lib/CodeGen/RegAllocBasic.cpp b/lib/CodeGen/RegAllocBasic.cpp
index 5ea26ad..5496d69 100644
--- a/lib/CodeGen/RegAllocBasic.cpp
+++ b/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<LiveDebugVariables>();
if (StrongPHIElim)
AU.addRequiredID(StrongPHIEliminationID);
- AU.addRequiredTransitive<RegisterCoalescer>();
+ AU.addRequiredTransitiveID(RegisterCoalescerPassID);
AU.addRequired<CalculateSpillWeights>();
AU.addRequired<LiveStacks>();
AU.addPreserved<LiveStacks>();
@@ -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/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp
index e235e87..f54a2c8 100644
--- a/lib/CodeGen/RegAllocGreedy.cpp
+++ b/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<SplitEditor::ComplementSpillMode>
+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<unsigned, 8> 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<unsigned> &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<GlobalSplitCandidate, 32> GlobalCand;
+ enum { NoCand = ~0u };
+
+ /// Candidate map. Each edge bundle is assigned to a GlobalCand entry, or to
+ /// NoCand which indicates the stack interval.
+ SmallVector<unsigned, 32> BundleCand;
+
public:
RAGreedy();
@@ -208,8 +258,8 @@ private:
void addThroughConstraints(InterferenceCache::Cursor, ArrayRef<unsigned>);
void growRegion(GlobalSplitCandidate &Cand);
float calcGlobalSplitCost(GlobalSplitCandidate&);
- void splitAroundRegion(LiveInterval&, GlobalSplitCandidate&,
- SmallVectorImpl<LiveInterval*>&);
+ bool calcCompactRegion(GlobalSplitCandidate&);
+ void splitAroundRegion(LiveRangeEdit&, ArrayRef<unsigned>);
void calcGapWeights(unsigned, SmallVectorImpl<float>&);
bool shouldEvict(LiveInterval &A, bool, LiveInterval &B, bool);
bool canEvictInterference(LiveInterval&, unsigned, bool, EvictionCost&);
@@ -222,6 +272,8 @@ private:
SmallVectorImpl<LiveInterval*>&, unsigned = ~0u);
unsigned tryRegionSplit(LiveInterval&, AllocationOrder&,
SmallVectorImpl<LiveInterval*>&);
+ unsigned tryBlockSplit(LiveInterval&, AllocationOrder&,
+ SmallVectorImpl<LiveInterval*>&);
unsigned tryLocalSplit(LiveInterval&, AllocationOrder&,
SmallVectorImpl<LiveInterval*>&);
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<LiveDebugVariables>();
if (StrongPHIElim)
AU.addRequiredID(StrongPHIEliminationID);
- AU.addRequiredTransitive<RegisterCoalescer>();
+ AU.addRequiredTransitiveID(RegisterCoalescerPassID);
AU.addRequired<CalculateSpillWeights>();
AU.addRequired<LiveStacks>();
AU.addPreserved<LiveStacks>();
@@ -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<unsigned>(TBS, T));
+ SpillPlacer->addLinks(makeArrayRef(TBS, T));
T = 0;
}
continue;
@@ -714,7 +772,7 @@ void RAGreedy::addThroughConstraints(InterferenceCache::Cursor Intf,
ArrayRef<SpillPlacement::BlockConstraint> Array(BCS, B);
SpillPlacer->addConstraints(Array);
- SpillPlacer->addLinks(ArrayRef<unsigned>(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<unsigned>(ActiveBlocks).slice(AddedTo));
+
+ // Compute through constraints from the interference, or assume that all
+ // through blocks prefer spilling when forming compact regions.
+ ArrayRef<unsigned> 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<SplitAnalysis::BlockInfo> 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<LiveInterval*> &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<unsigned> 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<SplitAnalysis::BlockInfo> 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<unsigned> 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<unsigned, 8> 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<LiveInterval*> &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<unsigned, 8> 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,15 +1167,94 @@ 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<LiveInterval*> &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<SplitAnalysis::BlockInfo> 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<unsigned, 8> 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<SlotIndex> &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<LiveInterval*>&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/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp
index 0dd3c598..ce3fb90 100644
--- a/lib/CodeGen/RegAllocLinearScan.cpp
+++ b/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<RegisterCoalescer>();
+ AU.addRequiredTransitiveID(RegisterCoalescerPassID);
AU.addRequired<CalculateSpillWeights>();
AU.addRequiredID(LiveStacksID);
AU.addPreservedID(LiveStacksID);
diff --git a/lib/CodeGen/RegAllocPBQP.cpp b/lib/CodeGen/RegAllocPBQP.cpp
index 72230d4..0d2cf2d 100644
--- a/lib/CodeGen/RegAllocPBQP.cpp
+++ b/lib/CodeGen/RegAllocPBQP.cpp
@@ -450,7 +450,7 @@ void RegAllocPBQP::getAnalysisUsage(AnalysisUsage &au) const {
au.addPreserved<SlotIndexes>();
au.addRequired<LiveIntervals>();
//au.addRequiredID(SplitCriticalEdgesID);
- au.addRequired<RegisterCoalescer>();
+ au.addRequiredID(RegisterCoalescerPassID);
if (customPassID)
au.addRequiredID(*customPassID);
au.addRequired<CalculateSpillWeights>();
diff --git a/lib/CodeGen/RegisterClassInfo.cpp b/lib/CodeGen/RegisterClassInfo.cpp
index 5a77e47..786d279 100644
--- a/lib/CodeGen/RegisterClassInfo.cpp
+++ b/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/lib/CodeGen/RegisterClassInfo.h b/lib/CodeGen/RegisterClassInfo.h
index d21fd67..2c14070 100644
--- a/lib/CodeGen/RegisterClassInfo.h
+++ b/lib/CodeGen/RegisterClassInfo.h
@@ -28,11 +28,12 @@ class RegisterClassInfo {
struct RCInfo {
unsigned Tag;
unsigned NumRegs;
+ bool ProperSubClass;
OwningArrayPtr<unsigned> Order;
- RCInfo() : Tag(0), NumRegs(0) {}
+ RCInfo() : Tag(0), NumRegs(0), ProperSubClass(false) {}
operator ArrayRef<unsigned>() const {
- return ArrayRef<unsigned>(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/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp
index b91f92c..9b414d6 100644
--- a/lib/CodeGen/RegisterCoalescer.cpp
+++ b/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<bool>
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<MachineInstr*, 32> JoinedCopies;
+
+ /// ReMatCopies - Keep track of copies eliminated due to remat.
+ ///
+ SmallPtrSet<MachineInstr*, 32> ReMatCopies;
+
+ /// ReMatDefs - Keep track of definition instructions which have
+ /// been remat'ed.
+ SmallPtrSet<MachineInstr*, 8> 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<MachineInstr*> &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 <undef>
+/// values, it only removes local variables. When we have a copy like:
+///
+/// %vreg1 = COPY %vreg2<undef>
+///
+/// We delete the copy and remove the corresponding value number from %vreg1.
+/// Any uses of that value number are marked as <undef>.
+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 <undef> 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<MachineBasicBlock*, 16> 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<MachineInstr*, 8> 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<unsigned, 8>::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<MachineInstr*> 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<std::pair<unsigned, MachineBasicBlock*> > 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<LiveIntervals>();
- ldv_ = &getAnalysis<LiveDebugVariables>();
+ MF = &fn;
+ MRI = &fn.getRegInfo();
+ TM = &fn.getTarget();
+ TRI = TM->getRegisterInfo();
+ TII = TM->getInstrInfo();
+ LIS = &getAnalysis<LiveIntervals>();
+ LDV = &getAnalysis<LiveDebugVariables>();
AA = &getAnalysis<AliasAnalysis>();
- loopInfo = &getAnalysis<MachineLoopInfo>();
+ Loops = &getAnalysis<MachineLoopInfo>();
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<unsigned, 4> DeadDefs;
- for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
+ SmallVector<unsigned, 4> 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/lib/CodeGen/RegisterCoalescer.h b/lib/CodeGen/RegisterCoalescer.h
index 4131d91..472c483 100644
--- a/lib/CodeGen/RegisterCoalescer.h
+++ b/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<MachineInstr*, 32> JoinedCopies;
-
- /// ReMatCopies - Keep track of copies eliminated due to remat.
- ///
- SmallPtrSet<MachineInstr*, 32> ReMatCopies;
-
- /// ReMatDefs - Keep track of definition instructions which have
- /// been remat'ed.
- SmallPtrSet<MachineInstr*, 8> 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<MachineInstr*> &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/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp
index 9e9a145..ca02aa1 100644
--- a/lib/CodeGen/RegisterScavenging.cpp
+++ b/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/lib/CodeGen/ScheduleDAG.cpp b/lib/CodeGen/ScheduleDAG.cpp
index 21375b2..1e9b5c8 100644
--- a/lib/CodeGen/ScheduleDAG.cpp
+++ b/lib/CodeGen/ScheduleDAG.cpp
@@ -26,7 +26,7 @@
using namespace llvm;
#ifndef NDEBUG
-cl::opt<bool> StressSchedOpt(
+static cl::opt<bool> 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/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp
index 446adfc..34b8ab0 100644
--- a/lib/CodeGen/ScheduleDAGInstrs.cpp
+++ b/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/lib/CodeGen/ScheduleDAGInstrs.h b/lib/CodeGen/ScheduleDAGInstrs.h
index 8a4ea85..666bdf5 100644
--- a/lib/CodeGen/ScheduleDAGInstrs.h
+++ b/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<unsigned, 8> LoopLiveIns;
for (MachineBasicBlock::livein_iterator LI = Header->livein_begin(),
@@ -109,7 +110,7 @@ namespace llvm {
/// initialized and destructed for each block.
std::vector<std::vector<SUnit *> > Defs;
std::vector<std::vector<SUnit *> > 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<std::pair<MachineInstr *, MachineInstr *> >
+ typedef std::vector<std::pair<MachineInstr *, MachineInstr *> >
DbgValueVector;
DbgValueVector DbgValues;
MachineInstr *FirstDbgValue;
diff --git a/lib/CodeGen/ScoreboardHazardRecognizer.cpp b/lib/CodeGen/ScoreboardHazardRecognizer.cpp
index 0e005d3..b80c01e 100644
--- a/lib/CodeGen/ScoreboardHazardRecognizer.cpp
+++ b/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/lib/CodeGen/SelectionDAG/CMakeLists.txt b/lib/CodeGen/SelectionDAG/CMakeLists.txt
index 15932c0..2282f0e 100644
--- a/lib/CodeGen/SelectionDAG/CMakeLists.txt
+++ b/lib/CodeGen/SelectionDAG/CMakeLists.txt
@@ -21,3 +21,13 @@ add_llvm_library(LLVMSelectionDAG
TargetLowering.cpp
TargetSelectionDAGInfo.cpp
)
+
+add_llvm_library_dependencies(LLVMSelectionDAG
+ LLVMAnalysis
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ LLVMTransformUtils
+ )
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 4f0d2ca..7b87868 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/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<ConstantSDNode>(N0);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(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<CondCodeSDNode>(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<CondCodeSDNode>(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<CondCodeSDNode>(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<CondCodeSDNode>(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<CondCodeSDNode>(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<CondCodeSDNode>(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<ConstantSDNode>(EltNo)) {
- unsigned Elt = cast<ConstantSDNode>(EltNo)->getZExtValue();
- SmallVector<SDValue, 8> 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<ConstantSDNode>(EltNo)) {
- EVT EltVT = VT.getVectorElementType();
+ // Check that we know which element is being inserted
+ if (!isa<ConstantSDNode>(EltNo))
+ return SDValue();
+ unsigned Elt = cast<ConstantSDNode>(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<SDValue, 8> 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<SDValue, 8> Ops(NElts, DAG.getUNDEF(EltVT));
+ Ops.append(NElts, DAG.getUNDEF(InVal.getValueType()));
+ } else {
+ return SDValue();
+ }
- unsigned Elt = cast<ConstantSDNode>(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<ConstantFP*>(FV->getConstantFPValue()),
const_cast<ConstantFP*>(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/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp
index 54a7d43..e8f8c73 100644
--- a/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/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<StructType>(Ty)) {
+ if (StructType *StTy = dyn_cast<StructType>(Ty)) {
unsigned Field = cast<ConstantInt>(Idx)->getZExtValue();
if (Field) {
// N = N + Offset
@@ -489,7 +494,7 @@ bool FastISel::SelectCall(const User *I) {
const CallInst *Call = cast<CallInst>(I);
// Handle simple inline asms.
- if (const InlineAsm *IA = dyn_cast<InlineAsm>(Call->getArgOperand(0))) {
+ if (const InlineAsm *IA = dyn_cast<InlineAsm>(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<Argument>(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<IntrinsicInst>(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/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index d518b5d..b052740 100644
--- a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/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<AllocaInst>(I))
if (const ConstantInt *CUI = dyn_cast<ConstantInt>(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<EVT, 4> 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<const Argument *, int>::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<Function>(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<GlobalVariable>(Val->stripPointerCasts()));
+ } else {
+ // Add filters in a list.
+ Constant *CVal = cast<Constant>(Val);
+ SmallVector<const GlobalVariable*, 4> FilterList;
+ for (User::op_iterator
+ II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II)
+ FilterList.push_back(cast<GlobalVariable>((*II)->stripPointerCasts()));
+
+ MMI.addFilterTypeInfo(MBB, FilterList);
+ }
+ }
+}
diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
index f0f4743..2ff66f8 100644
--- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
+++ b/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<RegisterSDNode>(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<RegisterSDNode>(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<RegisterSDNode>(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<ConstantPoolSDNode>(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<SDValue, unsigned> &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<RegisterSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<SDValue, unsigned> &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<RegisterSDNode>(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<ExternalSymbolSDNode>(AsmStrV)->getSymbol();
MI->addOperand(MachineOperand::CreateES(AsmStr));
-
+
// Add the HasSideEffect and isAlignStack bits.
int64_t ExtraInfo =
cast<ConstantSDNode>(Node->getOperand(InlineAsm::Op_ExtraInfo))->
@@ -834,10 +854,10 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned,
unsigned Flags =
cast<ConstantSDNode>(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<MDNodeSDNode>(MDV)->getMD();
if (MD)
MI->addOperand(MachineOperand::CreateMetadata(MD));
-
+
MBB->insert(InsertPos, MI);
break;
}
diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.h b/lib/CodeGen/SelectionDAG/InstrEmitter.h
index 19fc044..c081f38 100644
--- a/lib/CodeGen/SelectionDAG/InstrEmitter.h
+++ b/lib/CodeGen/SelectionDAG/InstrEmitter.h
@@ -77,6 +77,12 @@ class InstrEmitter {
DenseMap<SDValue, unsigned> &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<SDValue, unsigned> &VRBaseMap,
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index d06e2bd..63255ae 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/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<SDValue, 8> 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<SDValue> &Results);
void PromoteNode(SDNode *Node, SmallVectorImpl<SDValue> &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<ConstantFP>(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<SDValue, 8> 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<SDValue, SDValue>::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<SDValue, SDValue>::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<LoadSDNode>(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<StoreSDNode>(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<StoreSDNode>(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<SDValue, 8> 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<SDValue, 8> 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<unsigned>(ScalarSize, 8);
- // Store stride
- unsigned Stride = ScalarSize/8;
- assert(isPowerOf2_32(Stride) && "Stride must be a power of two");
-
- for (unsigned Idx=0; Idx<NumElem; Idx++) {
- SDValue Ex = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
- WideScalarVT, Tmp3, DAG.getIntPtrConstant(Idx));
-
-
- EVT NVT = EVT::getIntegerVT(*DAG.getContext(), ScalarSize);
+ Stores.push_back(Store);
+ }
- Ex = DAG.getNode(ISD::TRUNCATE, dl, NVT, Ex);
- Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2,
- DAG.getIntPtrConstant(Stride));
- 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;
- }
- // 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; Idx<WideNumElem*SizeRatio; Idx++) {
- // Extract elment i
- 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);
+ // 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<SDValue, 8> 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<SDValue,SDValue> CallInfo =
TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false,
false, 0, TLI.getLibcallCallingConv(LC), false,
@@ -2231,13 +2272,14 @@ std::pair<SDValue, SDValue>
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<SDValue, SDValue> 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<SDValue, SDValue> 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<AtomicSDNode>(Node)->getMemoryVT(),
+ Node->getOperand(0),
+ Node->getOperand(1), Zero, Zero,
+ cast<AtomicSDNode>(Node)->getMemOperand(),
+ cast<AtomicSDNode>(Node)->getOrdering(),
+ cast<AtomicSDNode>(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<AtomicSDNode>(Node)->getMemoryVT(),
+ Node->getOperand(0),
+ Node->getOperand(1), Node->getOperand(2),
+ cast<AtomicSDNode>(Node)->getMemOperand(),
+ cast<AtomicSDNode>(Node)->getOrdering(),
+ cast<AtomicSDNode>(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/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index e6835d8..7c1cc69 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/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<ConstantFPSDNode>(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<uint64_t> 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/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index e7c77dd..a5c4c2d 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/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<LoadSDNode>(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<AtomicSDNode>(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<AtomicSDNode>(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<AtomicSDNode>(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<AtomicSDNode>(N)->getMemOperand(),
+ cast<AtomicSDNode>(N)->getOrdering(),
+ cast<AtomicSDNode>(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<AtomicSDNode>(N)->getMemoryVT(),
+ N->getOperand(0),
+ N->getOperand(1), N->getOperand(2),
+ cast<AtomicSDNode>(N)->getMemOperand(),
+ cast<AtomicSDNode>(N)->getOrdering(),
+ cast<AtomicSDNode>(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<ShuffleVectorSDNode>(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<SDValue, 8> 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<SDValue, 8> 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/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
index ba658b0..a4bb577 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
+++ b/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<SDValue,SDValue> 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<SDValue, SDValue> 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/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index 952797d..abacdac 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/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<SDValue, SDValue> ExpandChainLibCall(RTLIB::Libcall LC,
- SDNode *Node, bool isSigned);
- std::pair<SDValue, SDValue> ExpandAtomic(SDNode *Node);
+
+ std::pair<SDValue, SDValue> ExpandChainLibCall(RTLIB::Libcall LC,
+ SDNode *Node, bool isSigned);
+ std::pair<SDValue, SDValue> 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/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
index 85ea6b6..8e7e498 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
+++ b/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/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
index ffff10c..f815b00 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
+++ b/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/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index b5698f9..107a42b 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/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<LoadSDNode>(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<ShuffleVectorSDNode>(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<int, 16> MaskOps(WidenNumElts);
- for (unsigned i=0; i < WidenNumElts/2; ++i) {
+ SmallVector<int, 16> 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<SDValue, 16> 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/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
index 12b1838..e757def 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
+++ b/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/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 35ea0bb..20bea8e 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/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<AtomicSDNode>(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<VTSDNode>(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<AtomicSDNode>(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<CondCodeSDNode>(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/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 81b03ee..7ed46a6 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/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<BlockAddress>(C))
return DAG.getBlockAddress(BA, VT);
- const VectorType *VecTy = cast<VectorType>(V->getType());
+ VectorType *VecTy = cast<VectorType>(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<BasicBlock*>(Src->getBasicBlock());
- BasicBlock *DstBB = const_cast<BasicBlock*>(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<EVT, 2> 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<SDValue, SDValue> 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<ConstantInt>(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<Constant>(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<int>(SrcNumElts+1),
+ static_cast<int>(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<UndefValue>(Op0);
bool FromUndef = isa<UndefValue>(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<UndefValue>(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<StructType>(Ty)) {
+ if (StructType *StTy = dyn_cast<StructType>(Ty)) {
unsigned Field = cast<ConstantInt>(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<VectorType>(I.getType())) {
+ if (VectorType *PTy = dyn_cast<VectorType>(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<RegisterSDNode>(N.getOperand(1))->getReg();
else
@@ -4295,7 +4528,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
const DbgDeclareInst &DI = cast<DbgDeclareInst>(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<ConstantInt>(V) || isa<ConstantFP>(V)) {
+ if (isa<ConstantInt>(V) || isa<ConstantFP>(V) || isa<UndefValue>(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<AllocaInst>(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<PointerType>(CS.getCalledValue()->getType());
- const FunctionType *FTy = cast<FunctionType>(PT->getElementType());
- const Type *RetTy = FTy->getReturnType();
+ PointerType *PT = cast<PointerType>(CS.getCalledValue()->getType());
+ FunctionType *FTy = cast<FunctionType>(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<EVT, 1> 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<FunctionType>(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<const Type*> i = po_begin(T), e = po_end(T);
+ Type* T = I.getArgOperand(i)->getType();
+ for (po_iterator<Type*> 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<BasicBlock>(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<PointerType>(OpTy);
+ llvm::PointerType *PtrTy = dyn_cast<PointerType>(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<StructType>(OpTy))
+ if (StructType *STy = dyn_cast<StructType>(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<StructType>(CS.getType())) {
+ assert(!CS.getType()->isVoidTy() && "Bad inline asm!");
+ if (StructType *STy = dyn_cast<StructType>(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<unsigned, const TargetRegisterClass*> MatchRC =
- TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode, OpInfo.ConstraintVT);
+ TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode,
+ OpInfo.ConstraintVT);
std::pair<unsigned, const TargetRegisterClass*> 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<SDValue, SDValue>
-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<PointerType>(Args[i].Ty);
- const Type *ElementTy = Ty->getElementType();
+ PointerType *Ty = cast<PointerType>(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<PointerType>(I->getType());
- const Type *ElementTy = Ty->getElementType();
+ PointerType *Ty = cast<PointerType>(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<FrameIndexSDNode>(ArgValues[0].getNode()))
- FuncInfo->setByValArgumentFrameIndex(I, FI->getIndex());
+ // Note down frame index.
+ if (FrameIndexSDNode *FI =
+ dyn_cast<FrameIndexSDNode>(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<LoadSDNode>(Res.getOperand(0).getNode()))
+ if (FrameIndexSDNode *FI =
+ dyn_cast<FrameIndexSDNode>(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/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index a0884eb..0a21ca3 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/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<ConstantInt>(High)->getValue();
const APInt &rLow = cast<ConstantInt>(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<MachineBasicBlock*, SmallVector<unsigned, 4> > 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/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 87bb296..68b9146 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/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<BranchInst>(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<TerminatorInst>(I) && // Terminators aren't folded.
!isa<DbgInfoIntrinsic>(I) && // Debug instructions aren't folded.
+ !isa<LandingPadInst>(I) && // Landingpad instructions aren't folded.
!FuncInfo->isExportedInst(I); // Exported instrs must be computed.
}
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 2626ac3..907d8d9 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/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<ISD::OutputArg> &Outs,
const TargetLowering &TLI,
SmallVectorImpl<uint64_t> *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<VTSDNode>(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<VTSDNode>(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<StructType>(CS.getType())) {
+ if (StructType *STy = dyn_cast<StructType>(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<PointerType>(OpTy);
+ llvm::PointerType *PtrTy = dyn_cast<PointerType>(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<StructType>(OpTy))
+ if (StructType *STy = dyn_cast<StructType>(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/lib/CodeGen/ShadowStackGC.cpp b/lib/CodeGen/ShadowStackGC.cpp
index 5a253a4..2609256 100644
--- a/lib/CodeGen/ShadowStackGC.cpp
+++ b/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<UnwindInst>(TI) && !isa<ReturnInst>(TI))
+ if (!isa<UnwindInst>(TI) && !isa<ReturnInst>(TI) &&
+ !isa<ResumeInst>(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<Type*> 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<GetElementPtrInst>(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<GetElementPtrInst>(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/lib/CodeGen/SjLjEHPrepare.cpp b/lib/CodeGen/SjLjEHPrepare.cpp
index 65a33da..ded2459d 100644
--- a/lib/CodeGen/SjLjEHPrepare.cpp
+++ b/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 <set>
using namespace llvm;
+static cl::opt<bool> 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<InvokeInst*, BasicBlock*> 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<LandingPadInst*> LPads);
+ void lowerIncomingArguments(Function &F);
+ void lowerAcrossUnwindEdges(Function &F, ArrayRef<InvokeInst*> Invokes);
+
void insertCallSiteStore(Instruction *I, int Number, Value *CallSite);
void markInvokeCallSite(InvokeInst *II, int InvokeNo, Value *CallSite,
SwitchInst *CatchSwitch);
void splitLiveRangesAcrossInvokes(SmallVector<InvokeInst*,16> &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<BasicBlock*, 2> 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<PHINode>(I); ++I) {
+ PHINode *PN = cast<PHINode>(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<PHINode>(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<PHINode>(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<InvokeInst*,16> &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<PHINode>(II->getNormalDest()) &&
!isa<PHINode>(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<InvokeInst*,16> &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<InvokeInst*,16> &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<InvokeInst*,16> &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<Instruction>(Inst->use_back());
+
+ if (PHINode *PN = dyn_cast<PHINode>(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<ReturnInst*,16> Returns;
SmallVector<UnwindInst*,16> Unwinds;
@@ -337,10 +438,23 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
SmallVector<CallInst*,16> EH_Exceptions;
SmallVector<Instruction*,16> 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<InvokeInst>(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<CallInst>(I)) {
if (CI->getCalledFunction() == SelectorFn) {
@@ -353,6 +467,10 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
}
} else if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
JmpbufUpdatePoints.push_back(AI);
+ } else if (InvokeInst *II = dyn_cast<InvokeInst>(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<LandingPadInst*, 16> LandingPads;
+ for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
+ if (InvokeInst *II = dyn_cast<InvokeInst>(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<ResumeInst>(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<LandingPadInst*> 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<AllocaInst>(AfterAllocaInsPt) &&
+ isa<ConstantInt>(cast<AllocaInst>(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<StructType>(Ty) || isa<ArrayType>(Ty) || isa<VectorType>(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<InvokeInst*> 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<Instruction>(Inst->use_back())->getParent() == BB &&
+ !isa<PHINode>(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<AllocaInst>(Inst))
+ if (isa<ConstantInt>(AI->getArraySize()) && BB == F.begin())
+ continue;
+
+ // Avoid iterator invalidation by copying users to a temporary vector.
+ SmallVector<Instruction*, 16> Users;
+ for (Value::use_iterator
+ UI = Inst->use_begin(), E = Inst->use_end(); UI != E; ++UI) {
+ Instruction *User = cast<Instruction>(*UI);
+ if (User->getParent() != BB || isa<PHINode>(User))
+ Users.push_back(User);
+ }
+
+ // Find all of the blocks that this value is live in.
+ std::set<BasicBlock*> LiveBBs;
+ LiveBBs.insert(Inst->getParent());
+ while (!Users.empty()) {
+ Instruction *U = Users.back();
+ Users.pop_back();
+
+ if (!isa<PHINode>(U)) {
+ MarkBlocksLiveIn(U->getParent(), LiveBBs);
+ } else {
+ // Uses for a PHI node occur in their predecessor block.
+ PHINode *PN = cast<PHINode>(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<ReturnInst*, 16> Returns;
+ SmallVector<InvokeInst*, 16> Invokes;
+ SmallVector<LandingPadInst*, 16> 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<InvokeInst>(BB->getTerminator())) {
+ Invokes.push_back(II);
+ LPads.push_back(II->getUnwindDest()->getLandingPadInst());
+ } else if (ReturnInst *RI = dyn_cast<ReturnInst>(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<CallInst>(I)) {
+ if (!CI->doesNotThrow())
+ insertCallSiteStore(CI, -1, CallSite);
+ } else if (ResumeInst *RI = dyn_cast<ResumeInst>(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/lib/CodeGen/SpillPlacement.cpp b/lib/CodeGen/SpillPlacement.cpp
index 6949618..6f33f54 100644
--- a/lib/CodeGen/SpillPlacement.cpp
+++ b/lib/CodeGen/SpillPlacement.cpp
@@ -220,6 +220,7 @@ void SpillPlacement::addConstraints(ArrayRef<BlockConstraint> LiveBlocks) {
0, // DontCare,
1, // PrefReg,
-1, // PrefSpill
+ 0, // PrefBoth
-HUGE_VALF // MustSpill
};
@@ -239,6 +240,22 @@ void SpillPlacement::addConstraints(ArrayRef<BlockConstraint> LiveBlocks) {
}
}
+/// addPrefSpill - Same as addConstraints(PrefSpill)
+void SpillPlacement::addPrefSpill(ArrayRef<unsigned> Blocks, bool Strong) {
+ for (ArrayRef<unsigned>::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<unsigned> Links) {
for (ArrayRef<unsigned>::iterator I = Links.begin(), E = Links.end(); I != E;
++I) {
diff --git a/lib/CodeGen/SpillPlacement.h b/lib/CodeGen/SpillPlacement.h
index 6952ad8..fc412f8 100644
--- a/lib/CodeGen/SpillPlacement.h
+++ b/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<BlockConstraint> 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<unsigned> Blocks, bool Strong);
+
/// addLinks - Add transparent blocks with the given numbers.
void addLinks(ArrayRef<unsigned> Links);
diff --git a/lib/CodeGen/SplitKit.cpp b/lib/CodeGen/SplitKit.cpp
index 761cab7..6362780 100644
--- a/lib/CodeGen/SplitKit.cpp
+++ b/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<ValueMap::iterator, bool> 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<LiveInBlock>::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<MachineBasicBlock*, 16> 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<LiveInBlock>::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<LiveInBlock>::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<VNInfo*> &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<MachineBasicBlock*, SlotIndex> DomPair;
+ SmallVector<DomPair, 8> 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<VNInfo*, 8> 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;
}
- // <undef> 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;
- }
-
+ // <undef> 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<unsigned> *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<unsigned> *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<SplitAnalysis::BlockInfo> 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/lib/CodeGen/SplitKit.h b/lib/CodeGen/SplitKit.h
index 7948b72..d8fc212 100644
--- a/lib/CodeGen/SplitKit.h
+++ b/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 NodeT> class DomTreeNodeBase;
-typedef DomTreeNodeBase<MachineBasicBlock> 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<const MachineBasicBlock*, 16> 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<SlotIndex, unsigned> RegAssignMap;
/// Allocator for the interval map. This will eventually be shared with
@@ -231,65 +261,34 @@ class SplitEditor {
/// Idx.
RegAssignMap RegAssign;
- typedef DenseMap<std::pair<unsigned, unsigned>, VNInfo*> ValueMap;
+ typedef PointerIntPair<VNInfo*, 1> ValueForcePair;
+ typedef DenseMap<std::pair<unsigned, unsigned>, 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<VNInfo*, MachineDomTreeNode*> LiveOutPair;
- typedef IndexedMap<LiveOutPair, MBB2NumberFunctor> 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<LiveInBlock, 16> 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<VNInfo*> &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/lib/CodeGen/Splitter.cpp b/lib/CodeGen/Splitter.cpp
index ec75df4..77973b7 100644
--- a/lib/CodeGen/Splitter.cpp
+++ b/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<MachineDominatorTree>();
au.addRequired<MachineLoopInfo>();
au.addPreserved<MachineLoopInfo>();
- au.addPreserved<RegisterCoalescer>();
+ au.addPreservedID(RegisterCoalescerPassID);
au.addPreserved<CalculateSpillWeights>();
au.addPreserved<LiveStacks>();
au.addRequired<SlotIndexes>();
diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp
index d3cbd15..1f0e5a2 100644
--- a/lib/CodeGen/StackProtector.cpp
+++ b/lib/CodeGen/StackProtector.cpp
@@ -123,7 +123,7 @@ bool StackProtector::RequiresStackProtector() const {
// protectors.
return true;
- if (const ArrayType *AT = dyn_cast<ArrayType>(AI->getAllocatedType())) {
+ if (ArrayType *AT = dyn_cast<ArrayType>(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/lib/CodeGen/StrongPHIElimination.cpp b/lib/CodeGen/StrongPHIElimination.cpp
index 227eb47..260cc0e 100644
--- a/lib/CodeGen/StrongPHIElimination.cpp
+++ b/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/lib/CodeGen/TailDuplication.cpp b/lib/CodeGen/TailDuplication.cpp
index 6b801cb..3a6211a 100644
--- a/lib/CodeGen/TailDuplication.cpp
+++ b/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/lib/CodeGen/TargetInstrInfoImpl.cpp b/lib/CodeGen/TargetInstrInfoImpl.cpp
index 86e71d8..f32678f 100644
--- a/lib/CodeGen/TargetInstrInfoImpl.cpp
+++ b/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<const FixedStackPseudoSourceValue>((*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<const FixedStackPseudoSourceValue>((*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/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index a3c5620..fb87154 100644
--- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/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/lib/CodeGen/TwoAddressInstructionPass.cpp b/lib/CodeGen/TwoAddressInstructionPass.cpp
index 6d6244e..d879378 100644
--- a/lib/CodeGen/TwoAddressInstructionPass.cpp
+++ b/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/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp
index 7557979..8a1cdc0 100644
--- a/lib/CodeGen/VirtRegMap.cpp
+++ b/lib/CodeGen/VirtRegMap.cpp
@@ -41,8 +41,8 @@
#include <algorithm>
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 <imp-use,kill> 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 <imp-use,kill> 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 <def,undef> flag only makes sense for sub-register defs, and
+ // we are substituting a full physreg. An <imp-use,kill> 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/lib/CompilerDriver/Action.cpp b/lib/CompilerDriver/Action.cpp
deleted file mode 100644
index a8d625c..0000000
--- a/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 <stdexcept>
-#include <string>
-
-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<const char*> 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/lib/CompilerDriver/BuiltinOptions.cpp b/lib/CompilerDriver/BuiltinOptions.cpp
deleted file mode 100644
index 3844203..0000000
--- a/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<std::string> InputFilenames(cl::Positional, cl::desc("<input file>"),
- cl::ZeroOrMore);
-cl::opt<std::string> OutputFilename("o", cl::desc("Output file name"),
- cl::value_desc("file"), cl::Prefix);
-cl::opt<std::string> TempDirname("temp-dir", cl::desc("Temp dir name"),
- cl::value_desc("<directory>"), cl::Prefix);
-cl::list<std::string> Languages("x",
- cl::desc("Specify the language of the following input files"),
- cl::ZeroOrMore);
-
-cl::opt<bool> DryRun("dry-run",
- cl::desc("Only pretend to run commands"));
-cl::opt<bool> Time("time", cl::desc("Time individual commands"));
-cl::opt<bool> VerboseMode("v",
- cl::desc("Enable verbose mode"));
-
-cl::opt<bool> CheckGraph("check-graph",
- cl::desc("Check the compilation graph for errors"),
- cl::Hidden);
-cl::opt<bool> WriteGraph("write-graph",
- cl::desc("Write compilation-graph.dot file"),
- cl::Hidden);
-cl::opt<bool> ViewGraph("view-graph",
- cl::desc("Show compilation graph in GhostView"),
- cl::Hidden);
-
-cl::opt<SaveTempsEnum::Values> 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/lib/CompilerDriver/CMakeLists.txt b/lib/CompilerDriver/CMakeLists.txt
deleted file mode 100644
index a12b337..0000000
--- a/lib/CompilerDriver/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-set(LLVM_LINK_COMPONENTS support)
-
-# We don't want this library to appear in `llvm-config --libs` output,
-# so its name doesn't start with "LLVM".
-
-add_llvm_library(CompilerDriver
- Action.cpp
- BuiltinOptions.cpp
- CompilationGraph.cpp
- Main.cpp
- Tool.cpp
- )
diff --git a/lib/CompilerDriver/CompilationGraph.cpp b/lib/CompilerDriver/CompilationGraph.cpp
deleted file mode 100644
index 33c6566..0000000
--- a/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 <algorithm>
-#include <cstring>
-#include <iterator>
-#include <limits>
-#include <queue>
-
-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 <class C>
- 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<Edge>(Edg).swap(*B);
- return;
- }
- }
- OutEdges.push_back(llvm::IntrusiveRefCntPtr<Edge>(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<Edge>(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<JoinTool&>(*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<std::string>::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<std::string>::const_iterator xNext = llvm::next(xIter);
- xPosNext = (xNext == xEnd) ? std::numeric_limits<unsigned>::max()
- : Languages.getPosition(xNext - xBegin);
- xLanguage = (*xIter == "none") ? 0 : &(*xIter);
- }
-
- // For each input file:
- for (cl::list<std::string>::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<std::string>::const_iterator xNext = llvm::next(xIter);
- if (xNext == xEnd)
- xPosNext = std::numeric_limits<unsigned>::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<const Node*>& Out) {
- std::queue<const Node*> 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<const Node*>& Out) {
- std::vector<const Node*> 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<const Node*> JTV;
- if (int ret = TopologicalSortFilterJoinNodes(JTV))
- return ret;
-
- // For all join nodes in topological order:
- for (std::vector<const Node*>::iterator B = JTV.begin(), E = JTV.end();
- B != E; ++B) {
-
- const Node* CurNode = *B;
- JoinTool* JT = &static_cast<JoinTool&>(*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<Node*> 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<llvmc::CompilationGraph*>
- : public DefaultDOTGraphTraits
- {
- DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
-
- template<typename GraphType>
- 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<typename EdgeIter>
- 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/lib/CompilerDriver/Main.cpp b/lib/CompilerDriver/Main.cpp
deleted file mode 100644
index 7120027..0000000
--- a/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 <sstream>
-#include <string>
-
-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/lib/CompilerDriver/Makefile b/lib/CompilerDriver/Makefile
deleted file mode 100644
index 10cfa4f..0000000
--- a/lib/CompilerDriver/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-##===- lib/CompilerDriver/Makefile -------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open
-# Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../..
-
-# We don't want this library to appear in `llvm-config --libs` output, so its
-# name doesn't start with "LLVM" and NO_LLVM_CONFIG is set.
-
-LIBRARYNAME = CompilerDriver
-LINK_COMPONENTS = support
-NO_LLVM_CONFIG = 1
-
-
-include $(LEVEL)/Makefile.common
diff --git a/lib/CompilerDriver/Tool.cpp b/lib/CompilerDriver/Tool.cpp
deleted file mode 100644
index 876759a..0000000
--- a/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 <algorithm>
-
-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 <class A, class B>
- bool CompareFirst (std::pair<A,B> p1, std::pair<A,B> p2) {
- return std::less<A>()(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<unsigned, std::string>);
- for (ArgsVector::iterator B = Args.begin(), E = Args.end(); B != E; ++B) {
- Out.push_back(B->second);
- }
-
- return Out;
-}
diff --git a/lib/DebugInfo/CMakeLists.txt b/lib/DebugInfo/CMakeLists.txt
new file mode 100644
index 0000000..fdffcb6
--- /dev/null
+++ b/lib/DebugInfo/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_llvm_library(LLVMDebugInfo
+ DIContext.cpp
+ DWARFAbbreviationDeclaration.cpp
+ DWARFCompileUnit.cpp
+ DWARFContext.cpp
+ DWARFDebugAbbrev.cpp
+ DWARFDebugArangeSet.cpp
+ DWARFDebugAranges.cpp
+ DWARFDebugInfoEntry.cpp
+ DWARFDebugLine.cpp
+ DWARFFormValue.cpp
+ )
+
+add_llvm_library_dependencies(LLVMDebugInfo
+ LLVMSupport
+ )
diff --git a/lib/DebugInfo/DIContext.cpp b/lib/DebugInfo/DIContext.cpp
new file mode 100644
index 0000000..e2fd55f
--- /dev/null
+++ b/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/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp b/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp
new file mode 100644
index 0000000..0df692c
--- /dev/null
+++ b/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/lib/DebugInfo/DWARFAbbreviationDeclaration.h b/lib/DebugInfo/DWARFAbbreviationDeclaration.h
new file mode 100644
index 0000000..2463a3c
--- /dev/null
+++ b/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<DWARFAttribute, 8> 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<DWARFAttribute> &getAttributes() const {
+ return Attributes;
+ }
+};
+
+}
+
+#endif
diff --git a/lib/DebugInfo/DWARFAttribute.h b/lib/DebugInfo/DWARFAttribute.h
new file mode 100644
index 0000000..6f49b63
--- /dev/null
+++ b/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/lib/DebugInfo/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARFCompileUnit.cpp
new file mode 100644
index 0000000..24bf97f
--- /dev/null
+++ b/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<DWARFDebugInfoEntryMinimal> 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/lib/DebugInfo/DWARFCompileUnit.h b/lib/DebugInfo/DWARFCompileUnit.h
new file mode 100644
index 0000000..d916729
--- /dev/null
+++ b/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 <vector>
+
+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<DWARFDebugInfoEntryMinimal> 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/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp
new file mode 100644
index 0000000..e1ac398
--- /dev/null
+++ b/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 <algorithm>
+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("<invalid>", 0, 0);
+ // Get the line table for this compile unit.
+ const DWARFDebugLine::LineTable *lineTable = getLineTableForCompileUnit(cu);
+ if (!lineTable)
+ return DILineInfo("<invalid>", 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("<invalid>", 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/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h
new file mode 100644
index 0000000..746a463
--- /dev/null
+++ b/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<DWARFCompileUnit, 1> CUs;
+ OwningPtr<DWARFDebugAbbrev> Abbrev;
+ OwningPtr<DWARFDebugAranges> Aranges;
+ OwningPtr<DWARFDebugLine> 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/lib/DebugInfo/DWARFDebugAbbrev.cpp b/lib/DebugInfo/DWARFDebugAbbrev.cpp
new file mode 100644
index 0000000..a11ae3f
--- /dev/null
+++ b/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/lib/DebugInfo/DWARFDebugAbbrev.h b/lib/DebugInfo/DWARFDebugAbbrev.h
new file mode 100644
index 0000000..03189b1
--- /dev/null
+++ b/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 <list>
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+typedef std::vector<DWARFAbbreviationDeclaration>
+ DWARFAbbreviationDeclarationColl;
+typedef DWARFAbbreviationDeclarationColl::iterator
+ DWARFAbbreviationDeclarationCollIter;
+typedef DWARFAbbreviationDeclarationColl::const_iterator
+ DWARFAbbreviationDeclarationCollConstIter;
+
+class DWARFAbbreviationDeclarationSet {
+ uint64_t Offset;
+ uint32_t IdxOffset;
+ std::vector<DWARFAbbreviationDeclaration> 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<uint64_t, DWARFAbbreviationDeclarationSet>
+ 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/lib/DebugInfo/DWARFDebugArangeSet.cpp b/lib/DebugInfo/DWARFDebugArangeSet.cpp
new file mode 100644
index 0000000..b0c0354
--- /dev/null
+++ b/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 <algorithm>
+#include <cassert>
+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/lib/DebugInfo/DWARFDebugArangeSet.h b/lib/DebugInfo/DWARFDebugArangeSet.h
new file mode 100644
index 0000000..9a2a6d0
--- /dev/null
+++ b/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 <vector>
+
+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<Descriptor> 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/lib/DebugInfo/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARFDebugAranges.cpp
new file mode 100644
index 0000000..576d37d
--- /dev/null
+++ b/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 <algorithm>
+#include <cassert>
+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<DWARFDebugArangeSet> 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/lib/DebugInfo/DWARFDebugAranges.h b/lib/DebugInfo/DWARFDebugAranges.h
new file mode 100644
index 0000000..12afb60
--- /dev/null
+++ b/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 <list>
+
+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<Range> RangeColl;
+ typedef RangeColl::const_iterator RangeCollIterator;
+
+private:
+ RangeColl Aranges;
+};
+
+}
+
+#endif
diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp
new file mode 100644
index 0000000..1b089ad
--- /dev/null
+++ b/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; i<numAttributes; ++i) {
+ form = AbbrevDecl->getFormByIndex(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<DWARFCompileUnit*>(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<DWARFCompileUnit*>(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/lib/DebugInfo/DWARFDebugInfoEntry.h b/lib/DebugInfo/DWARFDebugInfoEntry.h
new file mode 100644
index 0000000..aff2e85
--- /dev/null
+++ b/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/lib/DebugInfo/DWARFDebugLine.cpp b/lib/DebugInfo/DWARFDebugLine.cpp
new file mode 100644
index 0000000..fe1ef78
--- /dev/null
+++ b/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 <algorithm>
+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<Row>::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<LineTableIter, bool> 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; i<opcode_length; ++i)
+ debug_line_data.getULEB128(offset_ptr);
+ }
+ break;
+ }
+ } else {
+ // Special Opcodes
+
+ // A special opcode value is chosen based on the amount that needs
+ // to be added to the line and address registers. The maximum line
+ // increment for a special opcode is the value of the line_base
+ // field in the header, plus the value of the line_range field,
+ // minus 1 (line base + line range - 1). If the desired line
+ // increment is greater than the maximum line increment, a standard
+ // opcode must be used instead of a special opcode. The "address
+ // advance" is calculated by dividing the desired address increment
+ // by the minimum_instruction_length field from the header. The
+ // special opcode is then calculated using the following formula:
+ //
+ // opcode = (desired line increment - line_base) +
+ // (line_range * address advance) + opcode_base
+ //
+ // If the resulting opcode is greater than 255, a standard opcode
+ // must be used instead.
+ //
+ // To decode a special opcode, subtract the opcode_base from the
+ // opcode itself to give the adjusted opcode. The amount to
+ // increment the address register is the result of the adjusted
+ // opcode divided by the line_range multiplied by the
+ // minimum_instruction_length field from the header. That is:
+ //
+ // address increment = (adjusted opcode / line_range) *
+ // minimum_instruction_length
+ //
+ // The amount to increment the line register is the line_base plus
+ // the result of the adjusted opcode modulo the line_range. That is:
+ //
+ // line increment = line_base + (adjusted opcode % line_range)
+
+ uint8_t adjust_opcode = opcode - prologue->OpcodeBase;
+ 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<Row>::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/lib/DebugInfo/DWARFDebugLine.h b/lib/DebugInfo/DWARFDebugLine.h
new file mode 100644
index 0000000..bc6a70b
--- /dev/null
+++ b/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 <map>
+#include <string>
+#include <vector>
+
+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<uint8_t> StandardOpcodeLengths;
+ std::vector<std::string> IncludeDirectories;
+ std::vector<FileNameEntry> 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<Row> 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<uint32_t, LineTable> LineTableMapTy;
+ typedef LineTableMapTy::iterator LineTableIter;
+ typedef LineTableMapTy::const_iterator LineTableConstIter;
+
+ LineTableMapTy LineTableMap;
+};
+
+}
+
+#endif
diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp
new file mode 100644
index 0000000..705efe5
--- /dev/null
+++ b/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 <cassert>
+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<const uint8_t *>(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/lib/DebugInfo/DWARFFormValue.h b/lib/DebugInfo/DWARFFormValue.h
new file mode 100644
index 0000000..22ac011
--- /dev/null
+++ b/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/lib/DebugInfo/Makefile b/lib/DebugInfo/Makefile
new file mode 100644
index 0000000..1292b57
--- /dev/null
+++ b/lib/DebugInfo/Makefile
@@ -0,0 +1,14 @@
+##===- lib/DebugInfo/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 = LLVMDebugInfo
+BUILD_ARCHIVE := 1
+
+include $(LEVEL)/Makefile.common
diff --git a/lib/ExecutionEngine/CMakeLists.txt b/lib/ExecutionEngine/CMakeLists.txt
index 58caae8..fb14d41 100644
--- a/lib/ExecutionEngine/CMakeLists.txt
+++ b/lib/ExecutionEngine/CMakeLists.txt
@@ -4,6 +4,13 @@ add_llvm_library(LLVMExecutionEngine
TargetSelect.cpp
)
+add_llvm_library_dependencies(LLVMExecutionEngine
+ LLVMCore
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
add_subdirectory(Interpreter)
add_subdirectory(JIT)
add_subdirectory(MCJIT)
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp
index 7652090..525877b 100644
--- a/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/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<std::string, 1> 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<Value*, 8> 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::pair<std::string, const Type*>,
+ std::map<std::pair<std::string, Type*>,
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/lib/ExecutionEngine/Interpreter/CMakeLists.txt b/lib/ExecutionEngine/Interpreter/CMakeLists.txt
index d331f83..4fb58c2 100644
--- a/lib/ExecutionEngine/Interpreter/CMakeLists.txt
+++ b/lib/ExecutionEngine/Interpreter/CMakeLists.txt
@@ -12,6 +12,14 @@ add_llvm_library(LLVMInterpreter
Interpreter.cpp
)
+add_llvm_library_dependencies(LLVMInterpreter
+ LLVMCodeGen
+ LLVMCore
+ LLVMExecutionEngine
+ LLVMSupport
+ LLVMTarget
+ )
+
if( LLVM_ENABLE_FFI )
target_link_libraries( LLVMInterpreter ${FFI_LIBRARY_PATH} )
endif()
diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp
index 498063b..27917da 100644
--- a/lib/ExecutionEngine/Interpreter/Execution.cpp
+++ b/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<BasicBlock>(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<BasicBlock>(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<StructType>(*I)) {
+ if (StructType *STy = dyn_cast<StructType>(*I)) {
const StructLayout *SLO = TD.getStructLayout(STy);
const ConstantInt *CPU = cast<ConstantInt>(I.getOperand());
@@ -775,7 +778,7 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I,
Total += SLO->getElementOffset(Index);
} else {
- const SequentialType *ST = cast<SequentialType>(*I);
+ SequentialType *ST = cast<SequentialType>(*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<IntegerType>(DstTy);
+ IntegerType *DITy = cast<IntegerType>(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<IntegerType>(DstTy);
+ IntegerType *DITy = cast<IntegerType>(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<IntegerType>(DstTy);
+ IntegerType *DITy = cast<IntegerType>(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<IntegerType>(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<IntegerType>(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<IntegerType>(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/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
index f7e2a4d..055875c 100644
--- a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
+++ b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
@@ -48,7 +48,7 @@ using namespace llvm;
static ManagedStatic<sys::Mutex> FunctionsLock;
-typedef GenericValue (*ExFunc)(const FunctionType *,
+typedef GenericValue (*ExFunc)(FunctionType *,
const std::vector<GenericValue> &);
static ManagedStatic<std::map<const Function *, ExFunc> > ExportedFunctions;
static std::map<std::string, ExFunc> FuncNames;
@@ -60,7 +60,7 @@ static ManagedStatic<std::map<const Function *, RawFunc> > 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<GenericValue> &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<GenericValue> &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<GenericValue> &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<GenericValue> &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<GenericValue> &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<GenericValue> &Args) {
char Buffer[10000];
std::vector<GenericValue> 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<GenericValue> &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<GenericValue> &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<GenericValue> &Args) {
assert(Args.size() >= 2);
char Buffer[10000];
diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h
index bfebe3d..ee2b459 100644
--- a/lib/ExecutionEngine/Interpreter/Interpreter.h
+++ b/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/lib/ExecutionEngine/JIT/CMakeLists.txt b/lib/ExecutionEngine/JIT/CMakeLists.txt
index cefb0ae..598e50e 100644
--- a/lib/ExecutionEngine/JIT/CMakeLists.txt
+++ b/lib/ExecutionEngine/JIT/CMakeLists.txt
@@ -10,3 +10,11 @@ add_llvm_library(LLVMJIT
JITMemoryManager.cpp
OProfileJITEventListener.cpp
)
+
+add_llvm_library_dependencies(LLVMJIT
+ LLVMCore
+ LLVMExecutionEngine
+ LLVMRuntimeDyld
+ LLVMSupport
+ LLVMTarget
+ )
diff --git a/lib/ExecutionEngine/JIT/Intercept.cpp b/lib/ExecutionEngine/JIT/Intercept.cpp
index fa8bee4..2251a8e 100644
--- a/lib/ExecutionEngine/JIT/Intercept.cpp
+++ b/lib/ExecutionEngine/JIT/Intercept.cpp
@@ -52,6 +52,7 @@ static void runAtExitHandlers() {
#include <sys/stat.h>
#endif
#include <fcntl.h>
+#include <unistd.h>
/* 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/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp
index 445d2d0..d773009 100644
--- a/lib/ExecutionEngine/JIT/JIT.cpp
+++ b/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<Value*, 8> 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/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h
index b879fc3..92dcb0e 100644
--- a/lib/ExecutionEngine/JIT/JIT.h
+++ b/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/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp b/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp
index ddb0d54..8f84ac7 100644
--- a/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp
+++ b/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<MachineMove> Moves;
- TFI->getInitialFrameState(Moves);
- EmitFrameMoves(0, Moves);
+ EmitFrameMoves(0, MAI->getInitialFrameState());
JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop);
diff --git a/lib/ExecutionEngine/JIT/JITDwarfEmitter.h b/lib/ExecutionEngine/JIT/JITDwarfEmitter.h
index e1d0045..8dc99ab 100644
--- a/lib/ExecutionEngine/JIT/JITDwarfEmitter.h
+++ b/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/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index d046b8a..24020ee 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/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/lib/ExecutionEngine/MCJIT/CMakeLists.txt b/lib/ExecutionEngine/MCJIT/CMakeLists.txt
index 38fdffa..aae8a1b 100644
--- a/lib/ExecutionEngine/MCJIT/CMakeLists.txt
+++ b/lib/ExecutionEngine/MCJIT/CMakeLists.txt
@@ -2,3 +2,11 @@ add_llvm_library(LLVMMCJIT
MCJIT.cpp
Intercept.cpp
)
+
+add_llvm_library_dependencies(LLVMMCJIT
+ LLVMCore
+ LLVMExecutionEngine
+ LLVMRuntimeDyld
+ LLVMSupport
+ LLVMTarget
+ )
diff --git a/lib/ExecutionEngine/MCJIT/Intercept.cpp b/lib/ExecutionEngine/MCJIT/Intercept.cpp
index e431c84..f83f428 100644
--- a/lib/ExecutionEngine/MCJIT/Intercept.cpp
+++ b/lib/ExecutionEngine/MCJIT/Intercept.cpp
@@ -52,6 +52,7 @@ static void runAtExitHandlers() {
#include <sys/stat.h>
#endif
#include <fcntl.h>
+#include <unistd.h>
/* 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/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp
index 4475f4d..7c8a740 100644
--- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp
+++ b/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/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
index 59bdfee..c236d1d 100644
--- a/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
+++ b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
@@ -2,3 +2,8 @@ add_llvm_library(LLVMRuntimeDyld
RuntimeDyld.cpp
RuntimeDyldMachO.cpp
)
+
+add_llvm_library_dependencies(LLVMRuntimeDyld
+ LLVMObject
+ LLVMSupport
+ )
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
index bcdfb04..7190a3c 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
+++ b/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/lib/ExecutionEngine/TargetSelect.cpp b/lib/ExecutionEngine/TargetSelect.cpp
index f51aff3..004b865 100644
--- a/lib/ExecutionEngine/TargetSelect.cpp
+++ b/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<std::string>& 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/lib/Linker/CMakeLists.txt b/lib/Linker/CMakeLists.txt
index 0b6d2f4..4d8824b 100644
--- a/lib/Linker/CMakeLists.txt
+++ b/lib/Linker/CMakeLists.txt
@@ -4,3 +4,11 @@ add_llvm_library(LLVMLinker
LinkModules.cpp
Linker.cpp
)
+
+add_llvm_library_dependencies(LLVMLinker
+ LLVMArchive
+ LLVMBitReader
+ LLVMCore
+ LLVMSupport
+ LLVMTransformUtils
+ )
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index 55aa9bf..03a962e 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/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<StructType>(DstTy)) {
StructType *SSTy = cast<StructType>(SrcTy);
- if (DSTy->isAnonymous() != SSTy->isAnonymous() ||
+ if (DSTy->isLiteral() != SSTy->isLiteral() ||
DSTy->isPacked() != SSTy->isPacked())
return false;
} else if (ArrayType *DATy = dyn_cast<ArrayType>(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<StructType>(Ty) || cast<StructType>(Ty)->isAnonymous()) {
+ if (!isa<StructType>(Ty) || cast<StructType>(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<PointerType>(Ty)->getAddressSpace());
case Type::FunctionTyID:
return *Entry = FunctionType::get(ElementTypes[0],
- ArrayRef<Type*>(ElementTypes).slice(1),
+ makeArrayRef(ElementTypes).slice(1),
cast<FunctionType>(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<AppendingVarInfo> AppendingVars;
+ unsigned Mode; // Mode to treat source module.
+
+ // Set of items not to link in from source.
+ SmallPtrSet<const Value*, 16> 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<GlobalVariable>(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<ReturnInst*, 8> 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<GlobalAlias>(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<Function>(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/lib/Linker/Linker.cpp b/lib/Linker/Linker.cpp
index fba91da..59fbceb 100644
--- a/lib/Linker/Linker.cpp
+++ b/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/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt
index 22afa7e..a4ac1bf 100644
--- a/lib/MC/CMakeLists.txt
+++ b/lib/MC/CMakeLists.txt
@@ -1,25 +1,31 @@
add_llvm_library(LLVMMC
ELFObjectWriter.cpp
+ MCAsmBackend.cpp
MCAsmInfo.cpp
MCAsmInfoCOFF.cpp
MCAsmInfoDarwin.cpp
MCAsmStreamer.cpp
MCAssembler.cpp
+ MCAtom.cpp
MCCodeEmitter.cpp
+ MCCodeGenInfo.cpp
MCContext.cpp
MCDisassembler.cpp
+ MCDwarf.cpp
MCELF.cpp
MCELFObjectTargetWriter.cpp
MCELFStreamer.cpp
MCExpr.cpp
MCInst.cpp
MCInstPrinter.cpp
+ MCInstrAnalysis.cpp
MCLabel.cpp
- MCDwarf.cpp
MCLoggingStreamer.cpp
MCMachOStreamer.cpp
MCMachObjectTargetWriter.cpp
+ MCModule.cpp
MCNullStreamer.cpp
+ MCObjectFileInfo.cpp
MCObjectStreamer.cpp
MCObjectWriter.cpp
MCPureStreamer.cpp
@@ -30,13 +36,18 @@ add_llvm_library(LLVMMC
MCStreamer.cpp
MCSubtargetInfo.cpp
MCSymbol.cpp
+ MCTargetAsmLexer.cpp
MCValue.cpp
MCWin64EH.cpp
MachObjectWriter.cpp
- WinCOFFStreamer.cpp
- WinCOFFObjectWriter.cpp
SubtargetFeature.cpp
- TargetAsmBackend.cpp
+ WinCOFFObjectWriter.cpp
+ WinCOFFStreamer.cpp
+ )
+
+add_llvm_library_dependencies(LLVMMC
+ LLVMObject
+ LLVMSupport
)
add_subdirectory(MCParser)
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index 59e1b8e..3d16de5 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/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 <vector>
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/lib/MC/ELFObjectWriter.h b/lib/MC/ELFObjectWriter.h
index 7593099..862b085 100644
--- a/lib/MC/ELFObjectWriter.h
+++ b/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/lib/MC/MCAsmBackend.cpp b/lib/MC/MCAsmBackend.cpp
new file mode 100644
index 0000000..2c150f4
--- /dev/null
+++ b/lib/MC/MCAsmBackend.cpp
@@ -0,0 +1,37 @@
+//===-- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmBackend.h"
+using namespace llvm;
+
+MCAsmBackend::MCAsmBackend()
+ : HasReliableSymbolDifference(false)
+{
+}
+
+MCAsmBackend::~MCAsmBackend() {
+}
+
+const MCFixupKindInfo &
+MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
+ static const MCFixupKindInfo Builtins[] = {
+ { "FK_Data_1", 0, 8, 0 },
+ { "FK_Data_2", 0, 16, 0 },
+ { "FK_Data_4", 0, 32, 0 },
+ { "FK_Data_8", 0, 64, 0 },
+ { "FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel },
+ { "FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
+ { "FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
+ { "FK_PCRel_8", 0, 64, MCFixupKindInfo::FKF_IsPCRel }
+ };
+
+ assert((size_t)Kind <= sizeof(Builtins) / sizeof(Builtins[0]) &&
+ "Unknown fixup kind");
+ return Builtins[Kind];
+}
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index 502b60b..95861bc 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/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/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp
index 7fc7d7a..434d910 100644
--- a/lib/MC/MCAsmInfoCOFF.cpp
+++ b/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/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp
index 5851cb0..b20e338 100644
--- a/lib/MC/MCAsmInfoDarwin.cpp
+++ b/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/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index d5d08e8..3fcbb05 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/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 <cctype>
using namespace llvm;
@@ -40,7 +41,7 @@ protected:
private:
OwningPtr<MCInstPrinter> InstPrinter;
OwningPtr<MCCodeEmitter> Emitter;
- OwningPtr<TargetAsmBackend> AsmBackend;
+ OwningPtr<MCAsmBackend> 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/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 527a63c..06c8aec 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/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/lib/MC/MCAtom.cpp b/lib/MC/MCAtom.cpp
new file mode 100644
index 0000000..d714443
--- /dev/null
+++ b/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<MCData>::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<std::pair<uint64_t, MCInst> >::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<std::pair<uint64_t, MCInst> >::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/lib/MC/MCCodeGenInfo.cpp b/lib/MC/MCCodeGenInfo.cpp
new file mode 100644
index 0000000..236e7de
--- /dev/null
+++ b/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/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index 8faa72e..82690ee 100644
--- a/lib/MC/MCContext.cpp
+++ b/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<const MCSectionELF*> ELFUniqueMapTy;
typedef StringMap<const MCSectionCOFF*> 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/lib/MC/MCDisassembler/CMakeLists.txt b/lib/MC/MCDisassembler/CMakeLists.txt
index 0ce359d..4debb28 100644
--- a/lib/MC/MCDisassembler/CMakeLists.txt
+++ b/lib/MC/MCDisassembler/CMakeLists.txt
@@ -1,4 +1,3 @@
-
add_llvm_library(LLVMMCDisassembler
Disassembler.cpp
EDDisassembler.cpp
@@ -6,3 +5,26 @@ add_llvm_library(LLVMMCDisassembler
EDOperand.cpp
EDToken.cpp
)
+
+add_llvm_library_dependencies(LLVMMCDisassembler
+ LLVMMC
+ LLVMMCParser
+ LLVMSupport
+ LLVMTarget
+ )
+
+foreach(t ${LLVM_TARGETS_TO_BUILD})
+ set(td ${LLVM_MAIN_SRC_DIR}/lib/Target/${t})
+ if(EXISTS ${td}/TargetInfo/CMakeLists.txt)
+ add_llvm_library_dependencies(LLVMMCDisassembler "LLVM${t}Info")
+ endif()
+ if(EXISTS ${td}/MCTargetDesc/CMakeLists.txt)
+ add_llvm_library_dependencies(LLVMMCDisassembler "LLVM${t}Desc")
+ endif()
+ if(EXISTS ${td}/AsmParser/CMakeLists.txt)
+ add_llvm_library_dependencies(LLVMMCDisassembler "LLVM${t}AsmParser")
+ endif()
+ if(EXISTS ${td}/Disassembler/CMakeLists.txt)
+ add_llvm_library_dependencies(LLVMMCDisassembler "LLVM${t}Disassembler")
+ endif()
+endforeach(t)
diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp
index 5480b4b..16e66dc 100644
--- a/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/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<char, 64> 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<char, 64> 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/lib/MC/MCDisassembler/Disassembler.h b/lib/MC/MCDisassembler/Disassembler.h
index f0ec42a..238ff7d 100644
--- a/lib/MC/MCDisassembler/Disassembler.h
+++ b/lib/MC/MCDisassembler/Disassembler.h
@@ -20,15 +20,16 @@
#include "llvm-c/Disassembler.h"
#include <string>
#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<const llvm::MCAsmInfo> MAI;
- // The target machine instance.
- llvm::OwningPtr<llvm::TargetMachine> TM;
- // The disassembler for the target architecture.
- // FIXME: using llvm::OwningPtr<const llvm::TargetAsmInfo> causes a malloc
- // error when this LLVMDisasmContext is deleted.
- const TargetAsmInfo *Tai;
+ // The register information for the target architecture.
+ llvm::OwningPtr<const llvm::MCRegisterInfo> MRI;
// The assembly context for creating symbols and MCExprs.
llvm::OwningPtr<const llvm::MCContext> Ctx;
// The disassembler for the target architecture.
@@ -72,22 +69,28 @@ private:
llvm::OwningPtr<llvm::MCInstPrinter> 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/lib/MC/MCDisassembler/EDDisassembler.cpp b/lib/MC/MCDisassembler/EDDisassembler.cpp
index bdd99af..83362a2 100644
--- a/lib/MC/MCDisassembler/EDDisassembler.cpp
+++ b/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 &registerInfo) {
+void EDDisassembler::initMaps(const MCRegisterInfo &registerInfo) {
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<MCParsedAsmOperand*> &operands,
SourceMgr sourceMgr;
sourceMgr.setDiagHandler(diag_handler, static_cast<void*>(this));
sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over
- MCContext context(*AsmInfo, NULL);
+ MCContext context(*AsmInfo, *MRI, NULL);
OwningPtr<MCStreamer> streamer(createNullStreamer(context));
- OwningPtr<MCAsmParser> genericParser(createMCAsmParser(*Tgt, sourceMgr,
+ OwningPtr<MCAsmParser> genericParser(createMCAsmParser(sourceMgr,
context, *streamer,
*AsmInfo));
StringRef triple = tripleFromArch(Key.Arch);
OwningPtr<MCSubtargetInfo> STI(Tgt->createMCSubtargetInfo(triple, "", ""));
- OwningPtr<TargetAsmParser> TargetParser(Tgt->createAsmParser(*STI,
- *genericParser));
+ OwningPtr<MCTargetAsmParser>
+ TargetParser(Tgt->createMCAsmParser(*STI, *genericParser));
AsmToken OpcodeToken = genericParser->Lex();
AsmToken NextToken = genericParser->Lex(); // consume next token, because specificParser expects us to
diff --git a/lib/MC/MCDisassembler/EDDisassembler.h b/lib/MC/MCDisassembler/EDDisassembler.h
index 11d69c1..38c2203 100644
--- a/lib/MC/MCDisassembler/EDDisassembler.h
+++ b/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 <typename T> 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<llvm::TargetMachine> TargetMachine;
/// The assembly information for the target architecture
llvm::OwningPtr<const llvm::MCAsmInfo> AsmInfo;
+ /// The subtarget information for the target architecture
+ llvm::OwningPtr<const llvm::MCSubtargetInfo> STI;
+ // The register information for the target architecture.
+ llvm::OwningPtr<const llvm::MCRegisterInfo> MRI;
/// The disassembler for the target architecture
llvm::OwningPtr<const llvm::MCDisassembler> 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<llvm::AsmLexer> GenericAsmLexer;
- llvm::OwningPtr<llvm::TargetAsmLexer> SpecificAsmLexer;
+ llvm::OwningPtr<llvm::MCTargetAsmLexer> 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 &registerInfo);
+ void initMaps(const llvm::MCRegisterInfo &registerInfo);
/// nameWithRegisterID - Returns the name (owned by the EDDisassembler) of a
/// register for a given register ID, or NULL on failure
///
diff --git a/lib/MC/MCDisassembler/EDInst.h b/lib/MC/MCDisassembler/EDInst.h
index ceb9505..6b78dc8 100644
--- a/lib/MC/MCDisassembler/EDInst.h
+++ b/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/lib/MC/MCDisassembler/EDToken.cpp b/lib/MC/MCDisassembler/EDToken.cpp
index de770b4..5f6c9df 100644
--- a/lib/MC/MCDisassembler/EDToken.cpp
+++ b/lib/MC/MCDisassembler/EDToken.cpp
@@ -87,14 +87,18 @@ int EDToken::registerID(unsigned &registerID) const {
int EDToken::tokenize(std::vector<EDToken*> &tokens,
std::string &str,
- const char *operandOrder,
+ const signed char *operandOrder,
EDDisassembler &disassembler) {
SmallVector<MCParsedAsmOperand*, 5> parsedOperands;
SmallVector<AsmToken, 10> asmTokens;
if (disassembler.parseInst(parsedOperands, asmTokens, str))
+ {
+ for (unsigned i = 0, e = parsedOperands.size(); i != e; ++i)
+ delete parsedOperands[i];
return -1;
-
+ }
+
SmallVectorImpl<MCParsedAsmOperand*>::iterator operandIterator;
unsigned int operandIndex;
SmallVectorImpl<AsmToken>::iterator tokenIterator;
diff --git a/lib/MC/MCDisassembler/EDToken.h b/lib/MC/MCDisassembler/EDToken.h
index ba46707..384079b 100644
--- a/lib/MC/MCDisassembler/EDToken.h
+++ b/lib/MC/MCDisassembler/EDToken.h
@@ -125,7 +125,7 @@ struct EDToken {
// assembly syntax
static int tokenize(std::vector<EDToken*> &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/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index ad86db1..4658a30 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/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<MachineMove> &Moves = TAI.getInitialFrameState();
+ const MCAsmInfo &MAI = context.getAsmInfo();
+ const std::vector<MachineMove> &Moves = MAI.getInitialFrameState();
std::vector<MCCFIInstruction> 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<MCObjectFileInfo*>(Context.getObjectFileInfo());
+ FrameEmitterImpl Emitter(UsingCFI, IsEH);
+ ArrayRef<MCDwarfFrameInfo> 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<CIEKey, const MCSymbol*> 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/lib/MC/MCELF.cpp b/lib/MC/MCELF.cpp
index 2c3f8e8..dad2e7b 100644
--- a/lib/MC/MCELF.cpp
+++ b/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/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index 49340ed..9ada08e 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/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/lib/MC/MCELFStreamer.h b/lib/MC/MCELFStreamer.h
index 855e7e9..10bf775 100644
--- a/lib/MC/MCELFStreamer.h
+++ b/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/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
index fcf1aab..da297fb 100644
--- a/lib/MC/MCExpr.cpp
+++ b/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/lib/MC/MCInstPrinter.cpp b/lib/MC/MCInstPrinter.cpp
index 81a939f..2317a28 100644
--- a/lib/MC/MCInstPrinter.cpp
+++ b/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/lib/MC/MCInstrAnalysis.cpp b/lib/MC/MCInstrAnalysis.cpp
new file mode 100644
index 0000000..7736702
--- /dev/null
+++ b/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/lib/MC/MCLoggingStreamer.cpp b/lib/MC/MCLoggingStreamer.cpp
index 309752e..3fe8ac7 100644
--- a/lib/MC/MCLoggingStreamer.cpp
+++ b/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/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
index 1b21249..aa35815 100644
--- a/lib/MC/MCMachOStreamer.cpp
+++ b/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/lib/MC/MCModule.cpp b/lib/MC/MCModule.cpp
new file mode 100644
index 0000000..b1d09d9
--- /dev/null
+++ b/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<uint64_t, MCAtom*>::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<uint64_t, MCAtom*>::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/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp
index 9577af0..a6c0adb 100644
--- a/lib/MC/MCNullStreamer.cpp
+++ b/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/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp
new file mode 100644
index 0000000..df8b99d
--- /dev/null
+++ b/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/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index 8635aac..a04ae08 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/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/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp
index 0c1f8f0..c76052d 100644
--- a/lib/MC/MCParser/AsmLexer.cpp
+++ b/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/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 0c181f3..1648757 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/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 <cctype>
#include <vector>
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<const AsmParser*>(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<StringRef> &Parameters,
const std::vector<std::vector<AsmToken> > &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/lib/MC/MCParser/CMakeLists.txt b/lib/MC/MCParser/CMakeLists.txt
index eaea9f6..299d281 100644
--- a/lib/MC/MCParser/CMakeLists.txt
+++ b/lib/MC/MCParser/CMakeLists.txt
@@ -7,5 +7,10 @@ add_llvm_library(LLVMMCParser
MCAsmLexer.cpp
MCAsmParser.cpp
MCAsmParserExtension.cpp
- TargetAsmParser.cpp
+ MCTargetAsmParser.cpp
+ )
+
+add_llvm_library_dependencies(LLVMMCParser
+ LLVMMC
+ LLVMSupport
)
diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp
index 66ad384..185b516 100644
--- a/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/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<MCSymbolAttr>(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/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp
index dcf689a..d891126 100644
--- a/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/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<MCSymbolAttr>(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/lib/MC/MCParser/MCAsmParser.cpp b/lib/MC/MCParser/MCAsmParser.cpp
index 4030e41..5239ec7 100644
--- a/lib/MC/MCParser/MCAsmParser.cpp
+++ b/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/lib/MC/MCParser/MCTargetAsmParser.cpp b/lib/MC/MCParser/MCTargetAsmParser.cpp
new file mode 100644
index 0000000..6fb1ba4
--- /dev/null
+++ b/lib/MC/MCParser/MCTargetAsmParser.cpp
@@ -0,0 +1,19 @@
+//===-- MCTargetAsmParser.cpp - Target Assembly Parser ---------------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCTargetAsmParser.h"
+using namespace llvm;
+
+MCTargetAsmParser::MCTargetAsmParser()
+ : AvailableFeatures(0)
+{
+}
+
+MCTargetAsmParser::~MCTargetAsmParser() {
+}
diff --git a/lib/MC/MCParser/TargetAsmParser.cpp b/lib/MC/MCParser/TargetAsmParser.cpp
deleted file mode 100644
index 512f6b0..0000000
--- a/lib/MC/MCParser/TargetAsmParser.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-//===-- TargetAsmParser.cpp - Target Assembly Parser -----------------------==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Target/TargetAsmParser.h"
-using namespace llvm;
-
-TargetAsmParser::TargetAsmParser()
- : AvailableFeatures(0)
-{
-}
-
-TargetAsmParser::~TargetAsmParser() {
-}
diff --git a/lib/MC/MCPureStreamer.cpp b/lib/MC/MCPureStreamer.cpp
index 6098e6b..086c922 100644
--- a/lib/MC/MCPureStreamer.cpp
+++ b/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/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index 6e96b78..3afa22b 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/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 <cstdlib>
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/lib/MC/MCTargetAsmLexer.cpp b/lib/MC/MCTargetAsmLexer.cpp
new file mode 100644
index 0000000..c01c914
--- /dev/null
+++ b/lib/MC/MCTargetAsmLexer.cpp
@@ -0,0 +1,16 @@
+//===-- llvm/MC/MCTargetAsmLexer.cpp - Target Assembly Lexer --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCTargetAsmLexer.h"
+using namespace llvm;
+
+MCTargetAsmLexer::MCTargetAsmLexer(const Target &T)
+ : TheTarget(T), Lexer(NULL) {
+}
+MCTargetAsmLexer::~MCTargetAsmLexer() {}
diff --git a/lib/MC/MCWin64EH.cpp b/lib/MC/MCWin64EH.cpp
index e698384..79e66fc 100644
--- a/lib/MC/MCWin64EH.cpp
+++ b/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/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp
index 69efe23..a9219ad 100644
--- a/lib/MC/MachObjectWriter.cpp
+++ b/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 <vector>
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 <mach-o/nlist.h>.
//
@@ -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/lib/MC/TargetAsmBackend.cpp b/lib/MC/TargetAsmBackend.cpp
deleted file mode 100644
index 1927557..0000000
--- a/lib/MC/TargetAsmBackend.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//===-- TargetAsmBackend.cpp - Target Assembly Backend ---------------------==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Target/TargetAsmBackend.h"
-using namespace llvm;
-
-TargetAsmBackend::TargetAsmBackend()
- : HasReliableSymbolDifference(false)
-{
-}
-
-TargetAsmBackend::~TargetAsmBackend() {
-}
-
-const MCFixupKindInfo &
-TargetAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
- static const MCFixupKindInfo Builtins[] = {
- { "FK_Data_1", 0, 8, 0 },
- { "FK_Data_2", 0, 16, 0 },
- { "FK_Data_4", 0, 32, 0 },
- { "FK_Data_8", 0, 64, 0 },
- { "FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel },
- { "FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
- { "FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
- { "FK_PCRel_8", 0, 64, MCFixupKindInfo::FKF_IsPCRel }
- };
-
- assert((size_t)Kind <= sizeof(Builtins) / sizeof(Builtins[0]) &&
- "Unknown fixup kind");
- return Builtins[Kind];
-}
diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp
index 101237a..b15e225 100644
--- a/lib/MC/WinCOFFObjectWriter.cpp
+++ b/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 <cstdio>
diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp
index 6c36c12..7409daf 100644
--- a/lib/MC/WinCOFFStreamer.cpp
+++ b/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/lib/Makefile b/lib/Makefile
index ed27854..fd575cd 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -11,7 +11,7 @@ LEVEL = ..
include $(LEVEL)/Makefile.config
PARALLEL_DIRS := VMCore AsmParser Bitcode Archive Analysis Transforms CodeGen \
- Target ExecutionEngine Linker MC CompilerDriver Object
+ Target ExecutionEngine Linker MC Object DebugInfo
include $(LEVEL)/Makefile.common
diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp
new file mode 100644
index 0000000..e2eaff5
--- /dev/null
+++ b/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 = "!<arch>\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<const ArchiveMemberHeader *>(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<Binary> &Result) const {
+ OwningPtr<Binary> 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/lib/Object/Binary.cpp b/lib/Object/Binary.cpp
index 4b31c75..4e528d8 100644
--- a/lib/Object/Binary.cpp
+++ b/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<unsigned>(Source->getBufferSize()));
error_code ec;
switch (type) {
+ case sys::Archive_FileType: {
+ OwningPtr<Binary> 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<Binary> &Result) {
OwningPtr<MemoryBuffer> 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/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt
index 68e5e94..86eb51a 100644
--- a/lib/Object/CMakeLists.txt
+++ b/lib/Object/CMakeLists.txt
@@ -1,4 +1,5 @@
add_llvm_library(LLVMObject
+ Archive.cpp
Binary.cpp
COFFObjectFile.cpp
ELFObjectFile.cpp
@@ -8,3 +9,8 @@ add_llvm_library(LLVMObject
Object.cpp
ObjectFile.cpp
)
+
+add_llvm_library_dependencies(LLVMObject
+ LLVMCore
+ LLVMSupport
+ )
diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp
index 07de6bc..750c34d 100644
--- a/lib/Object/COFFObjectFile.cpp
+++ b/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<uintptr_t>(base() +
+ Section->PointerToRawData +
+ symb->Value);
+ else
+ Result = reinterpret_cast<uintptr_t>(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<uintptr_t>(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<uintptr_t>(
+ reinterpret_cast<const coff_relocation*>(
+ 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<const coff_file_header *>(base() + HeaderStart);
if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header)))
return;
-
+
SectionTable =
reinterpret_cast<const coff_section *>( 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<intptr_t>(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<intptr_t>(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<intptr_t>(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<const coff_relocation*>(Rel.p);
+}
+error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel,
+ RelocationRef &Res) const {
+ Rel.p = reinterpret_cast<uintptr_t>(
+ reinterpret_cast<const coff_relocation*>(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<uintptr_t>(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<char> &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<char> &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<uintptr_t>(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/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp
index e2ff4df..257d08c 100644
--- a/lib/Object/ELFObjectFile.cpp
+++ b/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 <algorithm>
#include <limits>
#include <utility>
@@ -176,12 +179,89 @@ struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> {
}
namespace {
+template<support::endianness target_endianness, bool is64Bits, bool isRela>
+struct Elf_Rel_Base;
+
+template<support::endianness target_endianness>
+struct Elf_Rel_Base<target_endianness, false, false> {
+ 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<support::endianness target_endianness>
+struct Elf_Rel_Base<target_endianness, true, false> {
+ 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<support::endianness target_endianness>
+struct Elf_Rel_Base<target_endianness, false, true> {
+ 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<support::endianness target_endianness>
+struct Elf_Rel_Base<target_endianness, true, true> {
+ 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<support::endianness target_endianness, bool is64Bits, bool isRela>
+struct Elf_Rel_Impl;
+
+template<support::endianness target_endianness, bool isRela>
+struct Elf_Rel_Impl<target_endianness, true, isRela>
+ : Elf_Rel_Base<target_endianness, true, isRela> {
+ using Elf_Rel_Base<target_endianness, true, isRela>::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<support::endianness target_endianness, bool isRela>
+struct Elf_Rel_Impl<target_endianness, false, isRela>
+ : Elf_Rel_Base<target_endianness, false, isRela> {
+ using Elf_Rel_Base<target_endianness, false, isRela>::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<support::endianness target_endianness, bool is64Bits>
class ELFObjectFile : public ObjectFile {
LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
+ typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel;
+ typedef Elf_Rel_Impl<target_endianness, is64Bits, true> 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<const Elf_Shdr*, 1> SymbolTableSections_t;
+ typedef SmallVector<const Elf_Shdr*, 1> Sections_t;
+ typedef DenseMap<unsigned, unsigned> IndexMap_t;
+ typedef DenseMap<const Elf_Shdr*, SmallVector<uint32_t, 1> > 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<const Elf_Sym*, ELF::Elf64_Word> 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<typename T>
+ const T *getEntry(uint16_t Section, uint32_t Entry) const;
+ template<typename T>
+ 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<char> &Result) const;
+ virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
+ int64_t &Res) const;
+ virtual error_code getRelocationValueString(DataRefImpl Rel,
+ SmallVectorImpl<char> &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<target_endianness, is64Bits>
::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<support::endianness target_endianness, bool is64Bits>
+ELF::Elf64_Word ELFObjectFile<target_endianness, is64Bits>
+ ::getSymbolTableIndex(const Elf_Sym *symb) const {
+ if (symb->st_shndx == ELF::SHN_XINDEX)
+ return ExtendedSymbolTable.lookup(symb);
+ return symb->st_shndx;
+}
+
+template<support::endianness target_endianness, bool is64Bits>
+const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr *
+ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
error_code ELFObjectFile<target_endianness, is64Bits>
- ::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<target_endianness, is64Bits>
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()) {
@@ -350,6 +487,43 @@ error_code ELFObjectFile<target_endianness, is64Bits>
template<support::endianness target_endianness, bool is64Bits>
error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<uintptr_t>(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<uintptr_t>(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<uintptr_t>(addr);
+ return object_error::success;
+ default:
+ Result = UnknownAddressOrSize;
+ return object_error::success;
+ }
+}
+
+template<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
::getSymbolSize(DataRefImpl Symb,
uint64_t &Result) const {
validateSymbol(Symb);
@@ -366,7 +540,7 @@ error_code ELFObjectFile<target_endianness, is64Bits>
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<target_endianness, is64Bits>
}
}
- switch (symb->st_shndx) {
+ switch (getSymbolTableIndex(symb)) {
case ELF::SHN_UNDEF:
if (ret == '?')
ret = 'U';
@@ -401,7 +575,7 @@ error_code ELFObjectFile<target_endianness, is64Bits>
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<target_endianness, is64Bits>
return ec;
Result = StringSwitch<char>(name)
.StartsWith(".debug", 'N')
- .StartsWith(".note", 'n');
+ .StartsWith(".note", 'n')
+ .Default('?');
return object_error::success;
}
@@ -426,6 +601,43 @@ error_code ELFObjectFile<target_endianness, is64Bits>
template<support::endianness target_endianness, bool is64Bits>
error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
::isSymbolInternal(DataRefImpl Symb,
bool &Result) const {
validateSymbol(Symb);
@@ -487,6 +699,15 @@ error_code ELFObjectFile<target_endianness, is64Bits>
template<support::endianness target_endianness, bool is64Bits>
error_code ELFObjectFile<target_endianness, is64Bits>
+ ::getSectionAlignment(DataRefImpl Sec,
+ uint64_t &Result) const {
+ const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
+ Result = sec->sh_addralign;
+ return object_error::success;
+}
+
+template<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
::isSectionText(DataRefImpl Sec,
bool &Result) const {
const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
@@ -499,6 +720,32 @@ error_code ELFObjectFile<target_endianness, is64Bits>
template<support::endianness target_endianness, bool is64Bits>
error_code ELFObjectFile<target_endianness, is64Bits>
+ ::isSectionData(DataRefImpl Sec,
+ bool &Result) const {
+ const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(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<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::isSectionBSS(DataRefImpl Sec,
+ bool &Result) const {
+ const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(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<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
::sectionContainsSymbol(DataRefImpl Sec,
DataRefImpl Symb,
bool &Result) const {
@@ -508,6 +755,330 @@ error_code ELFObjectFile<target_endianness, is64Bits>
}
template<support::endianness target_endianness, bool is64Bits>
+relocation_iterator ELFObjectFile<target_endianness, is64Bits>
+ ::getSectionRelBegin(DataRefImpl Sec) const {
+ DataRefImpl RelData;
+ memset(&RelData, 0, sizeof(RelData));
+ const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(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<support::endianness target_endianness, bool is64Bits>
+relocation_iterator ELFObjectFile<target_endianness, is64Bits>
+ ::getSectionRelEnd(DataRefImpl Sec) const {
+ DataRefImpl RelData;
+ memset(&RelData, 0, sizeof(RelData));
+ const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(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<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::getRelocationTypeName(DataRefImpl Rel,
+ SmallVectorImpl<char> &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<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::getRelocationValueString(DataRefImpl Rel,
+ SmallVectorImpl<char> &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<Elf_Sym>(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<support::endianness target_endianness, bool is64Bits>
ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object
, error_code &ec)
: ObjectFile(Binary::isELF, Object, ec)
@@ -521,25 +1092,41 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object
SectionHeaderTable =
reinterpret_cast<const Elf_Shdr *>(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<const char *>(SectionHeaderTable),
- *e = i + Header->e_shnum * Header->e_shentsize;
- i != e; i += Header->e_shentsize) {
- const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(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<const Elf_Shdr*>(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<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object
// Merge this into the above loop.
for (const char *i = reinterpret_cast<const char *>(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<const Elf_Shdr*>(i);
if (sh->sh_type == ELF::SHT_STRTAB) {
@@ -567,11 +1154,26 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object
}
}
}
+
+ // Build symbol name side-mapping if there is one.
+ if (SymbolTableSectionHeaderIndex) {
+ const Elf_Word *ShndxTable = reinterpret_cast<const Elf_Word*>(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<support::endianness target_endianness, bool is64Bits>
-ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits>
- ::begin_symbols() const {
+symbol_iterator ELFObjectFile<target_endianness, is64Bits>
+ ::begin_symbols() const {
DataRefImpl SymbolData;
memset(&SymbolData, 0, sizeof(SymbolData));
if (SymbolTableSections.size() == 0) {
@@ -585,8 +1187,8 @@ ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits>
}
template<support::endianness target_endianness, bool is64Bits>
-ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits>
- ::end_symbols() const {
+symbol_iterator ELFObjectFile<target_endianness, is64Bits>
+ ::end_symbols() const {
DataRefImpl SymbolData;
memset(&SymbolData, 0, sizeof(SymbolData));
SymbolData.d.a = std::numeric_limits<uint32_t>::max();
@@ -595,8 +1197,8 @@ ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits>
}
template<support::endianness target_endianness, bool is64Bits>
-ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
- ::begin_sections() const {
+section_iterator ELFObjectFile<target_endianness, is64Bits>
+ ::begin_sections() const {
DataRefImpl ret;
memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff);
@@ -604,13 +1206,13 @@ ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
}
template<support::endianness target_endianness, bool is64Bits>
-ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
- ::end_sections() const {
+section_iterator ELFObjectFile<target_endianness, is64Bits>
+ ::end_sections() const {
DataRefImpl ret;
memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(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<target_endianness, is64Bits>
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<target_endianness, is64Bits>::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<support::endianness target_endianness, bool is64Bits>
+uint64_t ELFObjectFile<target_endianness, is64Bits>::getNumSections() const {
+ if (Header->e_shnum == ELF::SHN_UNDEF)
+ return SectionHeaderTable->sh_size;
+ return Header->e_shnum;
+}
+
+template<support::endianness target_endianness, bool is64Bits>
+uint64_t
+ELFObjectFile<target_endianness, is64Bits>::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<support::endianness target_endianness, bool is64Bits>
+template<typename T>
+inline const T *
+ELFObjectFile<target_endianness, is64Bits>::getEntry(uint16_t Section,
+ uint32_t Entry) const {
+ return getEntry<T>(getSection(Section), Entry);
+}
+
+template<support::endianness target_endianness, bool is64Bits>
+template<typename T>
+inline const T *
+ELFObjectFile<target_endianness, is64Bits>::getEntry(const Elf_Shdr * Section,
+ uint32_t Entry) const {
+ return reinterpret_cast<const T *>(
+ base()
+ + Section->sh_offset
+ + (Entry * Section->sh_entsize));
+}
+
+template<support::endianness target_endianness, bool is64Bits>
const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym *
ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const {
- const Elf_Shdr *sec = SymbolTableSections[Symb.d.b];
- return reinterpret_cast<const Elf_Sym *>(
- base()
- + sec->sh_offset
- + (Symb.d.a * sec->sh_entsize));
+ return getEntry<Elf_Sym>(SymbolTableSections[Symb.d.b], Symb.d.a);
+}
+
+template<support::endianness target_endianness, bool is64Bits>
+const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rel *
+ELFObjectFile<target_endianness, is64Bits>::getRel(DataRefImpl Rel) const {
+ return getEntry<Elf_Rel>(Rel.w.b, Rel.w.c);
+}
+
+template<support::endianness target_endianness, bool is64Bits>
+const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rela *
+ELFObjectFile<target_endianness, is64Bits>::getRela(DataRefImpl Rela) const {
+ return getEntry<Elf_Rela>(Rela.w.b, Rela.w.c);
}
template<support::endianness target_endianness, bool is64Bits>
const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr *
ELFObjectFile<target_endianness, is64Bits>::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<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const {
template<support::endianness target_endianness, bool is64Bits>
const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr *
-ELFObjectFile<target_endianness, is64Bits>::getSection(uint16_t index) const {
- if (index == 0 || index >= ELF::SHN_LORESERVE)
+ELFObjectFile<target_endianness, is64Bits>::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<target_endianness, is64Bits>::getSection(uint16_t index) const {
template<support::endianness target_endianness, bool is64Bits>
const char *ELFObjectFile<target_endianness, is64Bits>
- ::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<target_endianness, is64Bits>
return (const char *)base() + section->sh_offset + offset;
}
+template<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<unsigned char, unsigned char>
getElfArchType(MemoryBuffer *Object) {
diff --git a/lib/Object/MachOObject.cpp b/lib/Object/MachOObject.cpp
index 9890feb..9cdac86 100644
--- a/lib/Object/MachOObject.cpp
+++ b/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"
@@ -244,6 +245,18 @@ void MachOObject::ReadDysymtabLoadCommand(const LoadCommandInfo &LCI,
}
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<macho::LinkeditDataLoadCommand> &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<uint64_t> &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/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index 26a6e13..507df58 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/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 <cctype>
#include <cstring>
@@ -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<uint32_t>::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<macho::SymbolTableEntry> &Res) const;
- void getSymbol64TableEntry(DataRefImpl DRI,
- InMemoryStruct<macho::Symbol64TableEntry> &Res) const;
- void moveToNextSymbol(DataRefImpl &DRI) const;
- void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const;
- void getSection64(DataRefImpl DRI,
- InMemoryStruct<macho::Section64> &Res) const;
-};
+ RegisteredStringTable(std::numeric_limits<uint32_t>::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<macho::Symbol64TableEntry> Entry;
+ getSymbol64TableEntry(DRI, Entry);
+ Result = Entry->Value;
+ SectionIndex = Entry->SectionIndex;
+ } else {
+ InMemoryStruct<macho::SymbolTableEntry> 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<macho::Symbol64TableEntry> Entry;
+ getSymbol64TableEntry(Symb, Entry);
+ Res = Entry->Type & MachO::NlistMaskExternal;
+ } else {
+ InMemoryStruct<macho::SymbolTableEntry> 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<macho::Symbol64TableEntry> Entry;
+ getSymbol64TableEntry(Symb, Entry);
+ n_type = Entry->Type;
+ } else {
+ InMemoryStruct<macho::SymbolTableEntry> 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<macho::Section64> &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<macho::Section64> Sect;
+ getSection64(DRI, Sect);
+ Result = uint64_t(1) << Sect->Align;
+ } else {
+ InMemoryStruct<macho::Section> 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<macho::Symbol64TableEntry> 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<macho::SymbolTableEntry> 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<macho::Section64> Sect;
+ getSection64(Sec, Sect);
+ last_reloc = Sect->NumRelocationTableEntries;
+ } else {
+ InMemoryStruct<macho::Section> 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<macho::RelocationEntry> &Res) const {
+ uint32_t relOffset;
+ if (MachOObj->is64Bit()) {
+ InMemoryStruct<macho::Section64> Sect;
+ getSection64(Sections[Rel.d.b], Sect);
+ relOffset = Sect->RelocationTableOffset;
+ } else {
+ InMemoryStruct<macho::Section> 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<macho::Section64> Sect;
+ getSection64(Sections[Rel.d.b], Sect);
+ sectAddress += Sect->Offset;
+ } else {
+ InMemoryStruct<macho::Section> Sect;
+ getSection(Sections[Rel.d.b], Sect);
+ sectAddress += Sect->Offset;
+ }
+ InMemoryStruct<macho::RelocationEntry> RE;
+ getRelocation(Rel, RE);
+ Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0);
+ return object_error::success;
+}
+error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
+ SymbolRef &Res) const {
+ InMemoryStruct<macho::RelocationEntry> 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<macho::RelocationEntry> RE;
+ getRelocation(Rel, RE);
+ Res = RE->Word1;
+ return object_error::success;
+}
+error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) const {
+ return object_error::success;
+}
+error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
+ int64_t &Res) const {
+ InMemoryStruct<macho::RelocationEntry> RE;
+ getRelocation(Rel, RE);
+ bool isExtern = (RE->Word1 >> 27) & 1;
+ Res = 0;
+ if (!isExtern) {
+ const uint8_t* sectAddress = base();
+ if (MachOObj->is64Bit()) {
+ InMemoryStruct<macho::Section64> Sect;
+ getSection64(Sections[Rel.d.b], Sect);
+ sectAddress += Sect->Offset;
+ } else {
+ InMemoryStruct<macho::Section> Sect;
+ getSection(Sections[Rel.d.b], Sect);
+ sectAddress += Sect->Offset;
+ }
+ Res = reinterpret_cast<uintptr_t>(sectAddress);
+ }
+ return object_error::success;
+}
+error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
+ SmallVectorImpl<char> &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/lib/Object/Object.cpp b/lib/Object/Object.cpp
index 9a373ad..2ea8db9 100644
--- a/lib/Object/Object.cpp
+++ b/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/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp
index a7798df..69d8ed0 100644
--- a/lib/Object/ObjectFile.cpp
+++ b/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/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index c64da6e..f238894 100644
--- a/lib/Support/APFloat.cpp
+++ b/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<char> &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<char> &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/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index 76265d4..3774c52 100644
--- a/lib/Support/APInt.cpp
+++ b/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<uint64_t> 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<unsigned>(numWords, getNumWords());
+ unsigned words = std::min<unsigned>(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<uint64_t> 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<char> &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<char> &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<char> &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<char> &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/lib/Support/Atomic.cpp b/lib/Support/Atomic.cpp
index c7b4bff..94760cc 100644
--- a/lib/Support/Atomic.cpp
+++ b/lib/Support/Atomic.cpp
@@ -22,7 +22,7 @@ using namespace llvm;
#endif
void sys::MemoryFence() {
-#if 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 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 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 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 LLVM_MULTITHREADED==0
+#if LLVM_HAS_ATOMICS == 0
*ptr += val;
return *ptr;
#elif defined(__GNUC__)
diff --git a/lib/Support/BlockFrequency.cpp b/lib/Support/BlockFrequency.cpp
new file mode 100644
index 0000000..a63bf83
--- /dev/null
+++ b/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 <cassert>
+
+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/lib/Support/BranchProbability.cpp b/lib/Support/BranchProbability.cpp
index 97342da..49d04ed 100644
--- a/lib/Support/BranchProbability.cpp
+++ b/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/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt
index 867d930..63a833c 100644
--- a/lib/Support/CMakeLists.txt
+++ b/lib/Support/CMakeLists.txt
@@ -9,11 +9,13 @@ add_llvm_library(LLVMSupport
APInt.cpp
APSInt.cpp
Allocator.cpp
+ BlockFrequency.cpp
BranchProbability.cpp
circular_raw_ostream.cpp
CommandLine.cpp
ConstantRange.cpp
CrashRecoveryContext.cpp
+ DataExtractor.cpp
Debug.cpp
DeltaAlgorithm.cpp
DAGDeltaAlgorithm.cpp
@@ -42,7 +44,6 @@ add_llvm_library(LLVMSupport
StringPool.cpp
StringRef.cpp
SystemUtils.cpp
- TargetRegistry.cpp
Timer.cpp
ToolOutputFile.cpp
Triple.cpp
@@ -72,6 +73,7 @@ add_llvm_library(LLVMSupport
SearchForAddressOfSpecialSymbol.cpp
Signals.cpp
system_error.cpp
+ TargetRegistry.cpp
ThreadLocal.cpp
Threading.cpp
TimeValue.cpp
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index 2914337..238adcc 100644
--- a/lib/Support/CommandLine.cpp
+++ b/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<bool>);
TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>);
TEMPLATE_INSTANTIATION(class basic_parser<int>);
TEMPLATE_INSTANTIATION(class basic_parser<unsigned>);
+TEMPLATE_INSTANTIATION(class basic_parser<unsigned long long>);
TEMPLATE_INSTANTIATION(class basic_parser<double>);
TEMPLATE_INSTANTIATION(class basic_parser<float>);
TEMPLATE_INSTANTIATION(class basic_parser<std::string>);
@@ -63,6 +63,7 @@ void parser<bool>::anchor() {}
void parser<boolOrDefault>::anchor() {}
void parser<int>::anchor() {}
void parser<unsigned>::anchor() {}
+void parser<unsigned long long>::anchor() {}
void parser<double>::anchor() {}
void parser<float>::anchor() {}
void parser<std::string>::anchor() {}
@@ -1006,6 +1007,16 @@ bool parser<unsigned>::parse(Option &O, StringRef ArgName,
return false;
}
+// parser<unsigned long long> implementation
+//
+bool parser<unsigned long long>::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<double>/parser<float> 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<const char *, const Target*> pair_ty;
- return strcmp(((const pair_ty*)LHS)->first, ((const pair_ty*)RHS)->first);
-}
+static std::vector<void (*)()>* ExtraVersionPrinters = 0;
namespace {
class VersionPrinter {
@@ -1361,37 +1370,27 @@ public:
<< " Built " << __DATE__ << " (" << __TIME__ << ").\n"
#endif
<< " Host: " << sys::getHostTriple() << '\n'
- << " Host CPU: " << CPU << '\n'
- << '\n'
- << " Registered Targets:\n";
-
- std::vector<std::pair<const char *, const Target*> > 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<void (*)()>::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<void (*)()>;
+
+ ExtraVersionPrinters->push_back(func);
+}
diff --git a/lib/Support/ConstantRange.cpp b/lib/Support/ConstantRange.cpp
index 81382d0..c29cb53 100644
--- a/lib/Support/ConstantRange.cpp
+++ b/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/lib/Support/CrashRecoveryContext.cpp b/lib/Support/CrashRecoveryContext.cpp
index 899c389..263114c 100644
--- a/lib/Support/CrashRecoveryContext.cpp
+++ b/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 <setjmp.h>
#include <cstdio>
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<CrashRecoveryContextImpl*>(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<const void> 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<PVOID>(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/lib/Support/DataExtractor.cpp b/lib/Support/DataExtractor.cpp
new file mode 100644
index 0000000..b946c1d
--- /dev/null
+++ b/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 <typename T>
+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 <typename T>
+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<T>(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<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data());
+}
+
+uint8_t *
+DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const {
+ return getUs<uint8_t>(offset_ptr, dst, count, this, IsLittleEndian,
+ Data.data());
+}
+
+
+uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
+ return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data());
+}
+
+uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst,
+ uint32_t count) const {
+ return getUs<uint16_t>(offset_ptr, dst, count, this, IsLittleEndian,
+ Data.data());
+}
+
+uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
+ return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data());
+}
+
+uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst,
+ uint32_t count) const {
+ return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
+ Data.data());;
+}
+
+uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
+ return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data());
+}
+
+uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
+ uint32_t count) const {
+ return getUs<uint64_t>(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/lib/Support/Disassembler.cpp b/lib/Support/Disassembler.cpp
index 6362aff..c6d73bc 100644
--- a/lib/Support/Disassembler.cpp
+++ b/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/lib/Support/Dwarf.cpp b/lib/Support/Dwarf.cpp
index 0813321..95a9550 100644
--- a/lib/Support/Dwarf.cpp
+++ b/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/lib/Support/DynamicLibrary.cpp b/lib/Support/DynamicLibrary.cpp
index 455c380..fb02c07 100644
--- a/lib/Support/DynamicLibrary.cpp
+++ b/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 <cstdio>
#include <cstring>
-#include <map>
-#include <vector>
// Collection of symbol name/value pairs to be searched prior to any libraries.
-static std::map<std::string, void*> *ExplicitSymbols = 0;
+static llvm::StringMap<void *> *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<true>& getMutex() {
+ static llvm::sys::SmartMutex<true> HandlesMutex;
+ return HandlesMutex;
+}
+
+void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
void *symbolValue) {
+ SmartScopedLock<true> lock(getMutex());
if (ExplicitSymbols == 0)
- ExplicitSymbols = new std::map<std::string, void*>();
+ ExplicitSymbols = new llvm::StringMap<void*>();
(*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<void *> *OpenedHandles = 0;
-
-
-static SmartMutex<true>& getMutex() {
- static SmartMutex<true> HandlesMutex;
- return HandlesMutex;
-}
+static DenseSet<void *> *OpenedHandles = 0;
+DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
+ std::string *errMsg) {
+ SmartScopedLock<true> 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<true> Lock(getMutex());
+
if (OpenedHandles == 0)
- OpenedHandles = new std::vector<void *>();
- OpenedHandles->push_back(H);
- return false;
+ OpenedHandles = new DenseSet<void *>();
+
+ // 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<true> Lock(getMutex());
+
// First check symbols added via AddSymbol().
if (ExplicitSymbols) {
- std::map<std::string, void *>::iterator I =
- ExplicitSymbols->find(symbolName);
- std::map<std::string, void *>::iterator E = ExplicitSymbols->end();
+ StringMap<void *>::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<true> Lock(getMutex());
if (OpenedHandles) {
- for (std::vector<void *>::iterator I = OpenedHandles->begin(),
+ for (DenseSet<void *>::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/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp
index 1568342..17b8271 100644
--- a/lib/Support/FoldingSet.cpp
+++ b/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<unsigned *>(&Ptr),
+ reinterpret_cast<unsigned *>(&Ptr+1));
}
void FoldingSetNodeID::AddInteger(signed I) {
Bits.push_back(I);
diff --git a/lib/Support/Host.cpp b/lib/Support/Host.cpp
index c525a12..a19e4b4 100644
--- a/lib/Support/Host.cpp
+++ b/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/lib/Support/IncludeFile.cpp b/lib/Support/IncludeFile.cpp
index 5da8826..e67acb3 100644
--- a/lib/Support/IncludeFile.cpp
+++ b/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/lib/Support/Memory.cpp b/lib/Support/Memory.cpp
index a9689b2..2a1642a 100644
--- a/lib/Support/Memory.cpp
+++ b/lib/Support/Memory.cpp
@@ -16,6 +16,10 @@
#include "llvm/Support/Valgrind.h"
#include "llvm/Config/config.h"
+#if defined(__mips__)
+#include <sys/cachectl.h>
+#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/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp
index d264be9..0771af5 100644
--- a/lib/Support/MemoryBuffer.cpp
+++ b/lib/Support/MemoryBuffer.cpp
@@ -275,16 +275,16 @@ static bool shouldUseMmap(int FD,
error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
OwningPtr<MemoryBuffer> &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/lib/Support/MemoryObject.cpp b/lib/Support/MemoryObject.cpp
index 91e3ecd..b20ab89 100644
--- a/lib/Support/MemoryObject.cpp
+++ b/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/lib/Support/Mutex.cpp b/lib/Support/Mutex.cpp
index b408973..8874e94 100644
--- a/lib/Support/Mutex.cpp
+++ b/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/lib/Support/Path.cpp b/lib/Support/Path.cpp
index 8fbaf2d..e5b7cd3 100644
--- a/lib/Support/Path.cpp
+++ b/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/lib/Support/PathV2.cpp b/lib/Support/PathV2.cpp
index 896c94c..bebe442 100644
--- a/lib/Support/PathV2.cpp
+++ b/lib/Support/PathV2.cpp
@@ -490,6 +490,36 @@ bool is_separator(char value) {
}
}
+void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &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/lib/Support/PrettyStackTrace.cpp b/lib/Support/PrettyStackTrace.cpp
index 082b701..ef33073 100644
--- a/lib/Support/PrettyStackTrace.cpp
+++ b/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/lib/Support/RWMutex.cpp b/lib/Support/RWMutex.cpp
index fc02f9c..d0b1e10 100644
--- a/lib/Support/RWMutex.cpp
+++ b/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/lib/Support/SearchForAddressOfSpecialSymbol.cpp b/lib/Support/SearchForAddressOfSpecialSymbol.cpp
index d638301..2d23902 100644
--- a/lib/Support/SearchForAddressOfSpecialSymbol.cpp
+++ b/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/lib/Support/StringExtras.cpp b/lib/Support/StringExtras.cpp
index eb2fa08..49c5ac4 100644
--- a/lib/Support/StringExtras.cpp
+++ b/lib/Support/StringExtras.cpp
@@ -51,11 +51,10 @@ std::pair<StringRef, StringRef> llvm::getToken(StringRef Source,
void llvm::SplitString(StringRef Source,
SmallVectorImpl<StringRef> &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<StringRef, StringRef> S = getToken(Source, Delimiters);
+ while (!S.first.empty()) {
+ OutFragments.push_back(S.first);
+ S = getToken(S.second, Delimiters);
}
}
diff --git a/lib/Support/StringRef.cpp b/lib/Support/StringRef.cpp
index 8c3fc09..b5b4f94 100644
--- a/lib/Support/StringRef.cpp
+++ b/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/lib/Support/TargetRegistry.cpp b/lib/Support/TargetRegistry.cpp
index 293a5d7..7497bfe 100644
--- a/lib/Support/TargetRegistry.cpp
+++ b/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 <cassert>
+#include <vector>
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<StringRef, const Target*> pair_ty;
+ return ((const pair_ty*)LHS)->first.compare(((const pair_ty*)RHS)->first);
+}
+
+void TargetRegistry::printRegisteredTargetsForVersion() {
+ std::vector<std::pair<StringRef, const Target*> > 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/lib/Support/ThreadLocal.cpp b/lib/Support/ThreadLocal.cpp
index 6b43048..fdb251c 100644
--- a/lib/Support/ThreadLocal.cpp
+++ b/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/lib/Support/Threading.cpp b/lib/Support/Threading.cpp
index 2957956..8f0bb93 100644
--- a/lib/Support/Threading.cpp
+++ b/lib/Support/Threading.cpp
@@ -24,7 +24,7 @@ static bool multithreaded_mode = false;
static sys::Mutex* global_lock = 0;
bool llvm::llvm_start_multithreaded() {
-#ifdef LLVM_MULTITHREADED
+#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() {
-#ifdef LLVM_MULTITHREADED
+#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) && defined(HAVE_PTHREAD_H)
+#if ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H)
#include <pthread.h>
struct ThreadInfo {
@@ -102,13 +102,44 @@ 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 <process.h>
-#else
+struct ThreadInfo {
+ void (*func)(void*);
+ void *param;
+};
-// No non-pthread implementation, currently.
+static unsigned __stdcall ThreadCallback(void *param) {
+ struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(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,
+ &param, 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;
Fn(UserData);
}
diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp
index 7e094ee..c61af37 100644
--- a/lib/Support/Triple.cpp
+++ b/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 <cassert>
#include <cstring>
using namespace llvm;
-//
-
const char *Triple::getArchTypeName(ArchType Kind) {
switch (Kind) {
case InvalidArch: return "<invalid>";
@@ -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 "<invalid>";
@@ -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 "<invalid>";
@@ -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/lib/Support/Twine.cpp b/lib/Support/Twine.cpp
index d62123c..3d04bc3 100644
--- a/lib/Support/Twine.cpp
+++ b/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<const std::string*>(LHS);
+ return *LHS.stdString;
// Otherwise, flatten and copy the contents first.
SmallString<256> Vec;
@@ -40,9 +40,9 @@ StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const {
switch (getLHSKind()) {
case CStringKind:
// Already null terminated, yay!
- return StringRef(static_cast<const char*>(LHS));
+ return StringRef(LHS.cString);
case StdStringKind: {
- const std::string *str = static_cast<const std::string*>(LHS);
+ const std::string *str = LHS.stdString;
return StringRef(str->c_str(), str->size());
}
default:
@@ -55,48 +55,51 @@ StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &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<const Twine*>(Ptr)->print(OS);
+ Ptr.twine->print(OS);
break;
case Twine::CStringKind:
- OS << static_cast<const char*>(Ptr);
+ OS << Ptr.cString;
break;
case Twine::StdStringKind:
- OS << *static_cast<const std::string*>(Ptr);
+ OS << *Ptr.stdString;
break;
case Twine::StringRefKind:
- OS << *static_cast<const StringRef*>(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<const unsigned long*>(Ptr);
+ OS << *Ptr.decUL;
break;
case Twine::DecLKind:
- OS << *static_cast<const long*>(Ptr);
+ OS << *Ptr.decL;
break;
case Twine::DecULLKind:
- OS << *static_cast<const unsigned long long*>(Ptr);
+ OS << *Ptr.decULL;
break;
case Twine::DecLLKind:
- OS << *static_cast<const long long*>(Ptr);
+ OS << *Ptr.decLL;
break;
case Twine::UHexKind:
- OS.write_hex(*static_cast<const uint64_t*>(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<const Twine*>(Ptr)->printRepr(OS);
+ Ptr.twine->printRepr(OS);
break;
case Twine::CStringKind:
OS << "cstring:\""
- << static_cast<const char*>(Ptr) << "\"";
+ << Ptr.cString << "\"";
break;
case Twine::StdStringKind:
OS << "std::string:\""
- << static_cast<const std::string*>(Ptr) << "\"";
+ << Ptr.stdString << "\"";
break;
case Twine::StringRefKind:
OS << "stringref:\""
- << static_cast<const StringRef*>(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<const unsigned long*>(Ptr) << "\"";
+ OS << "decUL:\"" << *Ptr.decUL << "\"";
break;
case Twine::DecLKind:
- OS << "decL:\"" << *static_cast<const long*>(Ptr) << "\"";
+ OS << "decL:\"" << *Ptr.decL << "\"";
break;
case Twine::DecULLKind:
- OS << "decULL:\"" << *static_cast<const unsigned long long*>(Ptr) << "\"";
+ OS << "decULL:\"" << *Ptr.decULL << "\"";
break;
case Twine::DecLLKind:
- OS << "decLL:\"" << *static_cast<const long long*>(Ptr) << "\"";
+ OS << "decLL:\"" << *Ptr.decLL << "\"";
break;
case Twine::UHexKind:
- OS << "uhex:\"" << static_cast<const uint64_t*>(Ptr) << "\"";
+ OS << "uhex:\"" << Ptr.uHex << "\"";
break;
}
}
diff --git a/lib/Support/Unix/Host.inc b/lib/Support/Unix/Host.inc
index 5fd0e5e..dda3ce2 100644
--- a/lib/Support/Unix/Host.inc
+++ b/lib/Support/Unix/Host.inc
@@ -22,6 +22,7 @@
#include <sys/utsname.h>
#include <cctype>
#include <string>
+#include <cstdlib> // ::getenv
using namespace llvm;
diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc
index f295b92..85c7c40 100644
--- a/lib/Support/Unix/Path.inc
+++ b/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/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc
index 03ff283..bbbc344 100644
--- a/lib/Support/Unix/PathV2.inc
+++ b/lib/Support/Unix/PathV2.inc
@@ -42,6 +42,9 @@
#if HAVE_STDIO_H
#include <stdio.h>
#endif
+#if HAVE_LIMITS_H
+#include <limits.h>
+#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<char> &result_path) {
+ SmallVectorImpl<char> &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/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc
index 5cdb11c..da440fd 100644
--- a/lib/Support/Unix/Process.inc
+++ b/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/lib/Support/Windows/DynamicLibrary.inc b/lib/Support/Windows/DynamicLibrary.inc
index fc5f580..83da82a 100644
--- a/lib/Support/Windows/DynamicLibrary.inc
+++ b/lib/Support/Windows/DynamicLibrary.inc
@@ -39,7 +39,7 @@ using namespace sys;
//=== and must not be UNIX code.
//===----------------------------------------------------------------------===//
-static std::vector<HMODULE> OpenedHandles;
+static DenseSet<HMODULE> *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<true> 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<HMODULE>();
- 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<HMODULE>();
+
+ // 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<true> Lock(getMutex());
+
// First check symbols added via AddSymbol().
if (ExplicitSymbols) {
- std::map<std::string, void *>::iterator I =
- ExplicitSymbols->find(symbolName);
- std::map<std::string, void *>::iterator E = ExplicitSymbols->end();
- if (I != E)
- return I->second;
+ StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
+
+ if (i != ExplicitSymbols->end())
+ return i->second;
}
// Now search the libraries.
- for (std::vector<HMODULE>::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<HMODULE>::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/lib/Support/Windows/Memory.inc b/lib/Support/Windows/Memory.inc
index 9f69e73..fcc7283 100644
--- a/lib/Support/Windows/Memory.inc
+++ b/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<unsigned char *>(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<LPVOID>(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<LPVOID>(Addr), Size, prot, &oldProt)
+ == TRUE;
}
}
diff --git a/lib/Support/Windows/PathV2.inc b/lib/Support/Windows/PathV2.inc
index af71b73..bc597b2 100644
--- a/lib/Support/Windows/PathV2.inc
+++ b/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<wchar_t, 128> 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<char> &result_path) {
+ SmallVectorImpl<char> &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<wchar_t, 128> 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<wchar_t, 64> 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<wchar_t, 64> 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/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc
index 06a7f00..fe54eb1 100644
--- a/lib/Support/Windows/Process.inc
+++ b/lib/Support/Windows/Process.inc
@@ -15,6 +15,7 @@
#include <psapi.h>
#include <malloc.h>
#include <io.h>
+#include <direct.h>
#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/lib/Support/Windows/RWMutex.inc b/lib/Support/Windows/RWMutex.inc
index 471f8fa..26b9bba 100644
--- a/lib/Support/Windows/RWMutex.inc
+++ b/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<LPCRITICAL_SECTION>(data_));
+ if (loadSRW()) {
+ data_ = calloc(1, sizeof(SRWLOCK));
+ fpInitializeSRWLock(static_cast<PSRWLOCK>(data_));
+ } else {
+ data_ = calloc(1, sizeof(CRITICAL_SECTION));
+ InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ }
}
RWMutexImpl::~RWMutexImpl() {
- DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- free(data_);
+ if (sHasSRW) {
+ // Nothing to do in the case of slim reader/writers
+ } else {
+ DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ free(data_);
+ }
}
bool RWMutexImpl::reader_acquire() {
- EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ if (sHasSRW) {
+ fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_));
+ } else {
+ EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ }
return true;
}
bool RWMutexImpl::reader_release() {
- LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ if (sHasSRW) {
+ fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_));
+ } else {
+ LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ }
return true;
}
bool RWMutexImpl::writer_acquire() {
- EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ if (sHasSRW) {
+ fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_));
+ } else {
+ EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ }
return true;
}
bool RWMutexImpl::writer_release() {
- LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ if (sHasSRW) {
+ fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_));
+ } else {
+ LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ }
return true;
}
diff --git a/lib/Support/Windows/Signals.inc b/lib/Support/Windows/Signals.inc
index 14f3f21..0d4b8a2 100644
--- a/lib/Support/Windows/Signals.inc
+++ b/lib/Support/Windows/Signals.inc
@@ -23,14 +23,133 @@
#endif
#include <psapi.h>
-#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<DWORD>(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<DWORD>(StackFrame.Params[0]),
+ static_cast<DWORD>(StackFrame.Params[1]),
+ static_cast<DWORD>(StackFrame.Params[2]),
+ static_cast<DWORD>(StackFrame.Params[3]));
+#endif
// Verify the PC belongs to a module in this process.
- if (!SymGetModuleBase(hProcess, PC)) {
+ if (!SymGetModuleBase64(hProcess, PC)) {
fputs(" <unknown module>\n", stderr);
continue;
}
// Print the symbol name.
char buffer[512];
- IMAGEHLP_SYMBOL *symbol = reinterpret_cast<IMAGEHLP_SYMBOL *>(buffer);
- memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL));
- symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
- symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL);
+ IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(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/lib/Support/Windows/Windows.h b/lib/Support/Windows/Windows.h
index 4a1553b..67b6f01 100644
--- a/lib/Support/Windows/Windows.h
+++ b/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/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index 5a71fa3..4927e9a 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/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<unsigned long>(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/lib/TableGen/CMakeLists.txt b/lib/TableGen/CMakeLists.txt
new file mode 100644
index 0000000..0db4134
--- /dev/null
+++ b/lib/TableGen/CMakeLists.txt
@@ -0,0 +1,16 @@
+## FIXME: This only requires RTTI because tblgen uses it. Fix that.
+set(LLVM_REQUIRES_RTTI 1)
+set(LLVM_REQUIRES_EH 1)
+
+add_llvm_library(LLVMTableGen
+ Error.cpp
+ Main.cpp
+ Record.cpp
+ TableGenBackend.cpp
+ TGLexer.cpp
+ TGParser.cpp
+ )
+
+add_llvm_library_dependencies(LLVMTableGen
+ LLVMSupport
+ )
diff --git a/lib/TableGen/Error.cpp b/lib/TableGen/Error.cpp
new file mode 100644
index 0000000..5b2cbbf
--- /dev/null
+++ b/lib/TableGen/Error.cpp
@@ -0,0 +1,39 @@
+//===- Error.cpp - tblgen error handling helper routines --------*- 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 error handling helper routines to pretty-print diagnostic
+// messages from tblgen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TableGen/Error.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+SourceMgr SrcMgr;
+
+void PrintError(SMLoc ErrorLoc, const Twine &Msg) {
+ SrcMgr.PrintMessage(ErrorLoc, Msg, "error");
+}
+
+void PrintError(const char *Loc, const Twine &Msg) {
+ SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error");
+}
+
+void PrintError(const Twine &Msg) {
+ errs() << "error:" << Msg << "\n";
+}
+
+void PrintError(const TGError &Error) {
+ PrintError(Error.getLoc(), Error.getMessage());
+}
+
+} // end namespace llvm
diff --git a/lib/TableGen/Main.cpp b/lib/TableGen/Main.cpp
new file mode 100644
index 0000000..01bc55e
--- /dev/null
+++ b/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 <algorithm>
+#include <cstdio>
+using namespace llvm;
+
+namespace {
+ cl::opt<std::string>
+ OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
+ cl::init("-"));
+
+ cl::opt<std::string>
+ DependFilename("d", cl::desc("Dependency filename"), cl::value_desc("filename"),
+ cl::init(""));
+
+ cl::opt<std::string>
+ InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
+
+ cl::list<std::string>
+ 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<MemoryBuffer> 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<std::string> &Dependencies = Parser.getDependencies();
+ for (std::vector<std::string>::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/lib/TableGen/Makefile b/lib/TableGen/Makefile
new file mode 100644
index 0000000..4472438
--- /dev/null
+++ b/lib/TableGen/Makefile
@@ -0,0 +1,18 @@
+##===- lib/TableGen/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 = LLVMTableGen
+BUILD_ARCHIVE = 1
+
+## FIXME: This only requires RTTI because tblgen uses it. Fix that.
+REQUIRES_RTTI = 1
+REQUIRES_EH = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp
new file mode 100644
index 0000000..b7c51ca
--- /dev/null
+++ b/lib/TableGen/Record.cpp
@@ -0,0 +1,2019 @@
+//===- Record.cpp - Record implementation ---------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implement the tablegen record classes.
+//
+//===----------------------------------------------------------------------===//
+
+#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<TableGenStringKey> {
+ static inline TableGenStringKey getEmptyKey() {
+ TableGenStringKey Empty("<<<EMPTY KEY>>>");
+ return Empty;
+ }
+ static inline TableGenStringKey getTombstoneKey() {
+ TableGenStringKey Tombstone("<<<TOMBSTONE KEY>>>");
+ 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);
+}
+
+bool BitRecTy::baseClassOf(const BitsRecTy *RHS) const {
+ return RHS->getNumBits() == 1;
+}
+
+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 BitInit::get(Val != 0);
+}
+
+Init *BitRecTy::convertValue(TypedInit *VI) {
+ if (dynamic_cast<BitRecTy*>(VI->getType()))
+ return VI; // Accept variable if it is already of bit type!
+ return 0;
+}
+
+BitsRecTy *BitsRecTy::get(unsigned Sz) {
+ static std::vector<BitsRecTy*> 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) {
+ SmallVector<Init *, 16> NewBits(Size);
+
+ for (unsigned i = 0; i != Size; ++i)
+ NewBits[i] = UnsetInit::get();
+
+ return BitsInit::get(NewBits);
+}
+
+Init *BitsRecTy::convertValue(BitInit *UI) {
+ if (Size != 1) return 0; // Can only convert single bit.
+ return BitsInit::get(UI);
+}
+
+/// canFitInBitfield - Return true if the number of bits is large enough to hold
+/// the integer value.
+static bool canFitInBitfield(int64_t Value, unsigned NumBits) {
+ // For example, with NumBits == 4, we permit Values from [-7 .. 15].
+ return (NumBits >= sizeof(Value) * 8) ||
+ (Value >> NumBits == 0) || (Value >> (NumBits-1) == -1);
+}
+
+/// convertValue from Int initializer to bits type: Split the integer up into the
+/// appropriate bits.
+///
+Init *BitsRecTy::convertValue(IntInit *II) {
+ int64_t Value = II->getValue();
+ // Make sure this bitfield is large enough to hold the integer value.
+ if (!canFitInBitfield(Value, Size))
+ return 0;
+
+ SmallVector<Init *, 16> NewBits(Size);
+
+ for (unsigned i = 0; i != Size; ++i)
+ NewBits[i] = BitInit::get(Value & (1LL << i));
+
+ return BitsInit::get(NewBits);
+}
+
+Init *BitsRecTy::convertValue(BitsInit *BI) {
+ // If the number of bits is right, return it. Otherwise we need to expand or
+ // truncate.
+ if (BI->getNumBits() == Size) return BI;
+ return 0;
+}
+
+Init *BitsRecTy::convertValue(TypedInit *VI) {
+ if (BitsRecTy *BRT = dynamic_cast<BitsRecTy*>(VI->getType()))
+ if (BRT->Size == Size) {
+ SmallVector<Init *, 16> NewBits(Size);
+
+ for (unsigned i = 0; i != Size; ++i)
+ NewBits[i] = VarBitInit::get(VI, i);
+ return BitsInit::get(NewBits);
+ }
+
+ if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType()))
+ return BitsInit::get(VI);
+
+ if (TernOpInit *Tern = dynamic_cast<TernOpInit*>(VI)) {
+ if (Tern->getOpcode() == TernOpInit::IF) {
+ Init *LHS = Tern->getLHS();
+ Init *MHS = Tern->getMHS();
+ Init *RHS = Tern->getRHS();
+
+ IntInit *MHSi = dynamic_cast<IntInit*>(MHS);
+ IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
+
+ if (MHSi && RHSi) {
+ int64_t MHSVal = MHSi->getValue();
+ int64_t RHSVal = RHSi->getValue();
+
+ if (canFitInBitfield(MHSVal, Size) && canFitInBitfield(RHSVal, Size)) {
+ SmallVector<Init *, 16> NewBits(Size);
+
+ for (unsigned i = 0; i != Size; ++i)
+ NewBits[i] =
+ TernOpInit::get(TernOpInit::IF, LHS,
+ IntInit::get((MHSVal & (1LL << i)) ? 1 : 0),
+ IntInit::get((RHSVal & (1LL << i)) ? 1 : 0),
+ VI->getType());
+
+ return BitsInit::get(NewBits);
+ }
+ } else {
+ BitsInit *MHSbs = dynamic_cast<BitsInit*>(MHS);
+ BitsInit *RHSbs = dynamic_cast<BitsInit*>(RHS);
+
+ if (MHSbs && RHSbs) {
+ SmallVector<Init *, 16> NewBits(Size);
+
+ for (unsigned i = 0; i != Size; ++i)
+ NewBits[i] = TernOpInit::get(TernOpInit::IF, LHS,
+ MHSbs->getBit(i),
+ RHSbs->getBit(i),
+ VI->getType());
+
+ return BitsInit::get(NewBits);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+Init *IntRecTy::convertValue(BitInit *BI) {
+ return IntInit::get(BI->getValue());
+}
+
+Init *IntRecTy::convertValue(BitsInit *BI) {
+ int64_t Result = 0;
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
+ if (BitInit *Bit = dynamic_cast<BitInit*>(BI->getBit(i))) {
+ Result |= Bit->getValue() << i;
+ } else {
+ return 0;
+ }
+ return IntInit::get(Result);
+}
+
+Init *IntRecTy::convertValue(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI; // Accept variable if already of the right type!
+ return 0;
+}
+
+Init *StringRecTy::convertValue(UnOpInit *BO) {
+ if (BO->getOpcode() == UnOpInit::CAST) {
+ Init *L = BO->getOperand()->convertInitializerTo(this);
+ if (L == 0) return 0;
+ if (L != BO->getOperand())
+ return UnOpInit::get(UnOpInit::CAST, L, new StringRecTy);
+ return BO;
+ }
+
+ return convertValue((TypedInit*)BO);
+}
+
+Init *StringRecTy::convertValue(BinOpInit *BO) {
+ if (BO->getOpcode() == BinOpInit::STRCONCAT) {
+ Init *L = BO->getLHS()->convertInitializerTo(this);
+ Init *R = BO->getRHS()->convertInitializerTo(this);
+ if (L == 0 || R == 0) return 0;
+ if (L != BO->getLHS() || R != BO->getRHS())
+ return BinOpInit::get(BinOpInit::STRCONCAT, L, R, new StringRecTy);
+ return BO;
+ }
+
+ return convertValue((TypedInit*)BO);
+}
+
+
+Init *StringRecTy::convertValue(TypedInit *TI) {
+ if (dynamic_cast<StringRecTy*>(TI->getType()))
+ return TI; // Accept variable if already of the right type!
+ return 0;
+}
+
+std::string ListRecTy::getAsString() const {
+ return "list<" + Ty->getAsString() + ">";
+}
+
+Init *ListRecTy::convertValue(ListInit *LI) {
+ std::vector<Init*> Elements;
+
+ // Verify that all of the elements of the list are subclasses of the
+ // appropriate class!
+ for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
+ if (Init *CI = LI->getElement(i)->convertInitializerTo(Ty))
+ Elements.push_back(CI);
+ else
+ return 0;
+
+ ListRecTy *LType = dynamic_cast<ListRecTy*>(LI->getType());
+ if (LType == 0) {
+ return 0;
+ }
+
+ return ListInit::get(Elements, this);
+}
+
+Init *ListRecTy::convertValue(TypedInit *TI) {
+ // Ensure that TI is compatible with our class.
+ if (ListRecTy *LRT = dynamic_cast<ListRecTy*>(TI->getType()))
+ if (LRT->getElementType()->typeIsConvertibleTo(getElementType()))
+ return TI;
+ return 0;
+}
+
+Init *CodeRecTy::convertValue(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI;
+ return 0;
+}
+
+Init *DagRecTy::convertValue(TypedInit *TI) {
+ if (TI->getType()->typeIsConvertibleTo(this))
+ return TI;
+ return 0;
+}
+
+Init *DagRecTy::convertValue(UnOpInit *BO) {
+ if (BO->getOpcode() == UnOpInit::CAST) {
+ Init *L = BO->getOperand()->convertInitializerTo(this);
+ if (L == 0) return 0;
+ if (L != BO->getOperand())
+ return UnOpInit::get(UnOpInit::CAST, L, new DagRecTy);
+ return BO;
+ }
+ return 0;
+}
+
+Init *DagRecTy::convertValue(BinOpInit *BO) {
+ if (BO->getOpcode() == BinOpInit::CONCAT) {
+ Init *L = BO->getLHS()->convertInitializerTo(this);
+ Init *R = BO->getRHS()->convertInitializerTo(this);
+ if (L == 0 || R == 0) return 0;
+ if (L != BO->getLHS() || R != BO->getRHS())
+ return BinOpInit::get(BinOpInit::CONCAT, L, R, new DagRecTy);
+ return BO;
+ }
+ return 0;
+}
+
+RecordRecTy *RecordRecTy::get(Record *R) {
+ return &dynamic_cast<RecordRecTy&>(*R->getDefInit()->getType());
+}
+
+std::string RecordRecTy::getAsString() const {
+ return Rec->getName();
+}
+
+Init *RecordRecTy::convertValue(DefInit *DI) {
+ // Ensure that DI is a subclass of Rec.
+ if (!DI->getDef()->isSubClassOf(Rec))
+ return 0;
+ return DI;
+}
+
+Init *RecordRecTy::convertValue(TypedInit *TI) {
+ // Ensure that TI is compatible with Rec.
+ if (RecordRecTy *RRT = dynamic_cast<RecordRecTy*>(TI->getType()))
+ if (RRT->getRecord()->isSubClassOf(getRecord()) ||
+ RRT->getRecord() == getRecord())
+ return TI;
+ return 0;
+}
+
+bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const {
+ if (Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec))
+ return true;
+
+ const std::vector<Record*> &SC = Rec->getSuperClasses();
+ for (unsigned i = 0, e = SC.size(); i != e; ++i)
+ if (RHS->getRecord()->isSubClassOf(SC[i]))
+ return true;
+
+ return false;
+}
+
+
+/// resolveTypes - Find a common type that T1 and T2 convert to.
+/// Return 0 if no such type exists.
+///
+RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) {
+ if (!T1->typeIsConvertibleTo(T2)) {
+ if (!T2->typeIsConvertibleTo(T1)) {
+ // If one is a Record type, check superclasses
+ RecordRecTy *RecTy1 = dynamic_cast<RecordRecTy*>(T1);
+ if (RecTy1) {
+ // See if T2 inherits from a type T1 also inherits from
+ const std::vector<Record *> &T1SuperClasses =
+ RecTy1->getRecord()->getSuperClasses();
+ for(std::vector<Record *>::const_iterator i = T1SuperClasses.begin(),
+ iend = T1SuperClasses.end();
+ i != iend;
+ ++i) {
+ RecordRecTy *SuperRecTy1 = RecordRecTy::get(*i);
+ RecTy *NewType1 = resolveTypes(SuperRecTy1, T2);
+ if (NewType1 != 0) {
+ if (NewType1 != SuperRecTy1) {
+ delete SuperRecTy1;
+ }
+ return NewType1;
+ }
+ }
+ }
+ RecordRecTy *RecTy2 = dynamic_cast<RecordRecTy*>(T2);
+ if (RecTy2) {
+ // See if T1 inherits from a type T2 also inherits from
+ const std::vector<Record *> &T2SuperClasses =
+ RecTy2->getRecord()->getSuperClasses();
+ for (std::vector<Record *>::const_iterator i = T2SuperClasses.begin(),
+ iend = T2SuperClasses.end();
+ i != iend;
+ ++i) {
+ RecordRecTy *SuperRecTy2 = RecordRecTy::get(*i);
+ RecTy *NewType2 = resolveTypes(T1, SuperRecTy2);
+ if (NewType2 != 0) {
+ if (NewType2 != SuperRecTy2) {
+ delete SuperRecTy2;
+ }
+ return NewType2;
+ }
+ }
+ }
+ return 0;
+ }
+ return T2;
+ }
+ return T1;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Initializer implementations
+//===----------------------------------------------------------------------===//
+
+void Init::dump() const { return print(errs()); }
+
+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<Init *> Range) {
+ ID.AddInteger(Range.size());
+
+ for (ArrayRef<Init *>::iterator i = Range.begin(),
+ iend = Range.end();
+ i != iend;
+ ++i)
+ ID.AddPointer(*i);
+}
+
+BitsInit *BitsInit::get(ArrayRef<Init *> Range) {
+ typedef FoldingSet<BitsInit> 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<unsigned> &Bits) const {
+ SmallVector<Init *, 16> NewBits(Bits.size());
+
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= getNumBits())
+ return 0;
+ NewBits[i] = getBit(Bits[i]);
+ }
+ return BitsInit::get(NewBits);
+}
+
+std::string BitsInit::getAsString() const {
+ std::string Result = "{ ";
+ for (unsigned i = 0, e = getNumBits(); i != e; ++i) {
+ if (i) Result += ", ";
+ if (Init *Bit = getBit(e-i-1))
+ Result += Bit->getAsString();
+ else
+ Result += "*";
+ }
+ return Result + " }";
+}
+
+// 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) const {
+ bool Changed = false;
+ SmallVector<Init *, 16> NewBits(getNumBits());
+
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ Init *B;
+ Init *CurBit = getBit(i);
+
+ do {
+ B = CurBit;
+ CurBit = CurBit->resolveReferences(R, RV);
+ Changed |= B != CurBit;
+ } while (B != CurBit);
+ NewBits[i] = CurBit;
+ }
+
+ if (Changed)
+ return BitsInit::get(NewBits);
+
+ return const_cast<BitsInit *>(this);
+}
+
+IntInit *IntInit::get(int64_t V) {
+ typedef DenseMap<int64_t, IntInit *> 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<unsigned> &Bits) const {
+ SmallVector<Init *, 16> NewBits(Bits.size());
+
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= 64)
+ return 0;
+
+ NewBits[i] = BitInit::get(Value & (INT64_C(1) << Bits[i]));
+ }
+ return BitsInit::get(NewBits);
+}
+
+StringInit *StringInit::get(const std::string &V) {
+ typedef StringMap<StringInit *> 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<CodeInit *> Pool;
+ static Pool ThePool;
+
+ CodeInit *&I = ThePool[V];
+ if (!I) I = new CodeInit(V);
+ return I;
+}
+
+static void ProfileListInit(FoldingSetNodeID &ID,
+ ArrayRef<Init *> Range,
+ RecTy *EltTy) {
+ ID.AddInteger(Range.size());
+ ID.AddPointer(EltTy);
+
+ for (ArrayRef<Init *>::iterator i = Range.begin(),
+ iend = Range.end();
+ i != iend;
+ ++i)
+ ID.AddPointer(*i);
+}
+
+ListInit *ListInit::get(ArrayRef<Init *> Range, RecTy *EltTy) {
+ typedef FoldingSet<ListInit> 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;
+}
+
+void ListInit::Profile(FoldingSetNodeID &ID) const {
+ ListRecTy *ListType = dynamic_cast<ListRecTy *>(getType());
+ assert(ListType && "Bad type for ListInit!");
+ RecTy *EltTy = ListType->getElementType();
+
+ ProfileListInit(ID, Values, EltTy);
+}
+
+Init *
+ListInit::convertInitListSlice(const std::vector<unsigned> &Elements) const {
+ std::vector<Init*> Vals;
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
+ if (Elements[i] >= getSize())
+ return 0;
+ Vals.push_back(getElement(Elements[i]));
+ }
+ return ListInit::get(Vals, getType());
+}
+
+Record *ListInit::getElementAsRecord(unsigned i) const {
+ assert(i < Values.size() && "List element index out of range!");
+ DefInit *DI = dynamic_cast<DefInit*>(Values[i]);
+ if (DI == 0) throw "Expected record in list!";
+ return DI->getDef();
+}
+
+Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) const {
+ std::vector<Init*> Resolved;
+ Resolved.reserve(getSize());
+ bool Changed = false;
+
+ for (unsigned i = 0, e = getSize(); i != e; ++i) {
+ Init *E;
+ Init *CurElt = getElement(i);
+
+ do {
+ E = CurElt;
+ CurElt = CurElt->resolveReferences(R, RV);
+ Changed |= E != CurElt;
+ } while (E != CurElt);
+ Resolved.push_back(E);
+ }
+
+ if (Changed)
+ return ListInit::get(Resolved, getType());
+ return const_cast<ListInit *>(this);
+}
+
+Init *ListInit::resolveListElementReference(Record &R, const RecordVal *IRV,
+ unsigned Elt) const {
+ if (Elt >= getSize())
+ return 0; // Out of range reference.
+ Init *E = getElement(Elt);
+ // If the element is set to some value, or if we are resolving a reference
+ // to a specific variable and that variable is explicitly unset, then
+ // replace the VarListElementInit with it.
+ if (IRV || !dynamic_cast<UnsetInit*>(E))
+ return E;
+ return 0;
+}
+
+std::string ListInit::getAsString() const {
+ std::string Result = "[";
+ for (unsigned i = 0, e = Values.size(); i != e; ++i) {
+ if (i) Result += ", ";
+ Result += Values[i]->getAsString();
+ }
+ return Result + "]";
+}
+
+Init *OpInit::resolveBitReference(Record &R, const RecordVal *IRV,
+ unsigned Bit) const {
+ Init *Folded = Fold(&R, 0);
+
+ if (Folded != this) {
+ TypedInit *Typed = dynamic_cast<TypedInit *>(Folded);
+ if (Typed) {
+ return Typed->resolveBitReference(R, IRV, Bit);
+ }
+ }
+
+ return 0;
+}
+
+Init *OpInit::resolveListElementReference(Record &R, const RecordVal *IRV,
+ unsigned Elt) const {
+ Init *Resolved = resolveReferences(R, IRV);
+ OpInit *OResolved = dynamic_cast<OpInit *>(Resolved);
+ if (OResolved) {
+ Resolved = OResolved->Fold(&R, 0);
+ }
+
+ if (Resolved != this) {
+ TypedInit *Typed = dynamic_cast<TypedInit *>(Resolved);
+ assert(Typed && "Expected typed init for list reference");
+ if (Typed) {
+ Init *New = Typed->resolveListElementReference(R, IRV, Elt);
+ if (New)
+ return New;
+ return VarListElementInit::get(Typed, Elt);
+ }
+ }
+
+ return 0;
+}
+
+UnOpInit *UnOpInit::get(UnaryOp opc, Init *lhs, RecTy *Type) {
+ typedef std::pair<std::pair<unsigned, Init *>, RecTy *> Key;
+
+ typedef DenseMap<Key, UnOpInit *> 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: {
+ if (getType()->getAsString() == "string") {
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ if (LHSs) {
+ return LHSs;
+ }
+
+ DefInit *LHSd = dynamic_cast<DefInit*>(LHS);
+ if (LHSd) {
+ return StringInit::get(LHSd->getDef()->getName());
+ }
+ } else {
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ if (LHSs) {
+ std::string Name = LHSs->getValue();
+
+ // From TGParser::ParseIDValue
+ if (CurRec) {
+ if (const RecordVal *RV = CurRec->getValue(Name)) {
+ if (RV->getType() != getType())
+ throw "type mismatch in cast";
+ return VarInit::get(Name, RV->getType());
+ }
+
+ std::string TemplateArgName = CurRec->getName()+":"+Name;
+ if (CurRec->isTemplateArg(TemplateArgName)) {
+ const RecordVal *RV = CurRec->getValue(TemplateArgName);
+ assert(RV && "Template arg doesn't exist??");
+
+ if (RV->getType() != getType())
+ throw "type mismatch in cast";
+
+ return VarInit::get(TemplateArgName, RV->getType());
+ }
+ }
+
+ if (CurMultiClass) {
+ std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
+ if (CurMultiClass->Rec.isTemplateArg(MCName)) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
+ assert(RV && "Template arg doesn't exist??");
+
+ if (RV->getType() != getType())
+ throw "type mismatch in cast";
+
+ return VarInit::get(MCName, RV->getType());
+ }
+ }
+
+ if (Record *D = (CurRec->getRecords()).getDef(Name))
+ return DefInit::get(D);
+
+ throw TGError(CurRec->getLoc(), "Undefined reference:'" + Name + "'\n");
+ }
+ }
+ break;
+ }
+ case HEAD: {
+ ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+ if (LHSl) {
+ if (LHSl->getSize() == 0) {
+ assert(0 && "Empty list in car");
+ return 0;
+ }
+ return LHSl->getElement(0);
+ }
+ break;
+ }
+ case TAIL: {
+ ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+ if (LHSl) {
+ if (LHSl->getSize() == 0) {
+ assert(0 && "Empty list in cdr");
+ return 0;
+ }
+ // Note the +1. We can't just pass the result of getValues()
+ // directly.
+ ArrayRef<Init *>::iterator begin = LHSl->getValues().begin()+1;
+ ArrayRef<Init *>::iterator end = LHSl->getValues().end();
+ ListInit *Result =
+ ListInit::get(ArrayRef<Init *>(begin, end - begin),
+ LHSl->getType());
+ return Result;
+ }
+ break;
+ }
+ case EMPTY: {
+ ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+ if (LHSl) {
+ if (LHSl->getSize() == 0) {
+ return IntInit::get(1);
+ } else {
+ return IntInit::get(0);
+ }
+ }
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ if (LHSs) {
+ if (LHSs->getValue().empty()) {
+ return IntInit::get(1);
+ } else {
+ return IntInit::get(0);
+ }
+ }
+
+ break;
+ }
+ }
+ return const_cast<UnOpInit *>(this);
+}
+
+Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) const {
+ Init *lhs = LHS->resolveReferences(R, RV);
+
+ if (LHS != lhs)
+ return (UnOpInit::get(getOpcode(), lhs, getType()))->Fold(&R, 0);
+ return Fold(&R, 0);
+}
+
+std::string UnOpInit::getAsString() const {
+ std::string Result;
+ switch (Opc) {
+ case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;
+ case HEAD: Result = "!head"; break;
+ case TAIL: Result = "!tail"; break;
+ case EMPTY: Result = "!empty"; break;
+ }
+ return Result + "(" + LHS->getAsString() + ")";
+}
+
+BinOpInit *BinOpInit::get(BinaryOp opc, Init *lhs,
+ Init *rhs, RecTy *Type) {
+ typedef std::pair<
+ std::pair<std::pair<unsigned, Init *>, Init *>,
+ RecTy *
+ > Key;
+
+ typedef DenseMap<Key, BinOpInit *> 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: {
+ DagInit *LHSs = dynamic_cast<DagInit*>(LHS);
+ DagInit *RHSs = dynamic_cast<DagInit*>(RHS);
+ if (LHSs && RHSs) {
+ DefInit *LOp = dynamic_cast<DefInit*>(LHSs->getOperator());
+ DefInit *ROp = dynamic_cast<DefInit*>(RHSs->getOperator());
+ if (LOp == 0 || ROp == 0 || LOp->getDef() != ROp->getDef())
+ throw "Concated Dag operators do not match!";
+ std::vector<Init*> Args;
+ std::vector<std::string> ArgNames;
+ for (unsigned i = 0, e = LHSs->getNumArgs(); i != e; ++i) {
+ Args.push_back(LHSs->getArg(i));
+ ArgNames.push_back(LHSs->getArgName(i));
+ }
+ for (unsigned i = 0, e = RHSs->getNumArgs(); i != e; ++i) {
+ Args.push_back(RHSs->getArg(i));
+ ArgNames.push_back(RHSs->getArgName(i));
+ }
+ return DagInit::get(LHSs->getOperator(), "", Args, ArgNames);
+ }
+ break;
+ }
+ case STRCONCAT: {
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+ if (LHSs && RHSs)
+ 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<IntInit*>(LHS->convertInitializerTo(IntRecTy::get()));
+ IntInit* R =
+ dynamic_cast<IntInit*>(RHS->convertInitializerTo(IntRecTy::get()));
+
+ if (L && R)
+ return IntInit::get(L->getValue() == R->getValue());
+
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+
+ // Make sure we've resolved
+ if (LHSs && RHSs)
+ return IntInit::get(LHSs->getValue() == RHSs->getValue());
+
+ break;
+ }
+ case SHL:
+ case SRA:
+ case SRL: {
+ IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
+ IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
+ if (LHSi && RHSi) {
+ int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
+ int64_t Result;
+ switch (getOpcode()) {
+ default: assert(0 && "Bad opcode!");
+ case SHL: Result = LHSv << RHSv; break;
+ case SRA: Result = LHSv >> RHSv; break;
+ case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break;
+ }
+ return IntInit::get(Result);
+ }
+ break;
+ }
+ }
+ return const_cast<BinOpInit *>(this);
+}
+
+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 (BinOpInit::get(getOpcode(), lhs, rhs, getType()))->Fold(&R, 0);
+ return Fold(&R, 0);
+}
+
+std::string BinOpInit::getAsString() const {
+ std::string Result;
+ switch (Opc) {
+ case CONCAT: Result = "!con"; break;
+ case SHL: Result = "!shl"; break;
+ case SRA: Result = "!sra"; break;
+ case SRL: Result = "!srl"; break;
+ case EQ: Result = "!eq"; break;
+ case STRCONCAT: Result = "!strconcat"; break;
+ }
+ 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<std::pair<unsigned, RecTy *>, Init *>,
+ Init *
+ >,
+ Init *
+ > Key;
+
+ typedef DenseMap<Key, TernOpInit *> 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);
+
+static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg,
+ RecTy *Type, Record *CurRec,
+ MultiClass *CurMultiClass) {
+ std::vector<Init *> NewOperands;
+
+ TypedInit *TArg = dynamic_cast<TypedInit*>(Arg);
+
+ // If this is a dag, recurse
+ if (TArg && TArg->getType()->getAsString() == "dag") {
+ Init *Result = ForeachHelper(LHS, Arg, RHSo, Type,
+ CurRec, CurMultiClass);
+ if (Result != 0) {
+ return Result;
+ } else {
+ return 0;
+ }
+ }
+
+ for (int i = 0; i < RHSo->getNumOperands(); ++i) {
+ OpInit *RHSoo = dynamic_cast<OpInit*>(RHSo->getOperand(i));
+
+ if (RHSoo) {
+ Init *Result = EvaluateOperation(RHSoo, LHS, Arg,
+ Type, CurRec, CurMultiClass);
+ if (Result != 0) {
+ NewOperands.push_back(Result);
+ } else {
+ NewOperands.push_back(Arg);
+ }
+ } else if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
+ NewOperands.push_back(Arg);
+ } else {
+ NewOperands.push_back(RHSo->getOperand(i));
+ }
+ }
+
+ // Now run the operator and use its result as the new leaf
+ const OpInit *NewOp = RHSo->clone(NewOperands);
+ Init *NewVal = NewOp->Fold(CurRec, CurMultiClass);
+ if (NewVal != NewOp)
+ return NewVal;
+
+ return 0;
+}
+
+static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
+ Record *CurRec, MultiClass *CurMultiClass) {
+ DagInit *MHSd = dynamic_cast<DagInit*>(MHS);
+ ListInit *MHSl = dynamic_cast<ListInit*>(MHS);
+
+ DagRecTy *DagType = dynamic_cast<DagRecTy*>(Type);
+ ListRecTy *ListType = dynamic_cast<ListRecTy*>(Type);
+
+ OpInit *RHSo = dynamic_cast<OpInit*>(RHS);
+
+ if (!RHSo) {
+ throw TGError(CurRec->getLoc(), "!foreach requires an operator\n");
+ }
+
+ TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
+
+ if (!LHSt) {
+ throw TGError(CurRec->getLoc(), "!foreach requires typed variable\n");
+ }
+
+ if ((MHSd && DagType) || (MHSl && ListType)) {
+ if (MHSd) {
+ Init *Val = MHSd->getOperator();
+ Init *Result = EvaluateOperation(RHSo, LHS, Val,
+ Type, CurRec, CurMultiClass);
+ if (Result != 0) {
+ Val = Result;
+ }
+
+ std::vector<std::pair<Init *, std::string> > args;
+ for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) {
+ Init *Arg;
+ std::string ArgName;
+ Arg = MHSd->getArg(i);
+ ArgName = MHSd->getArgName(i);
+
+ // Process args
+ Init *Result = EvaluateOperation(RHSo, LHS, Arg, Type,
+ CurRec, CurMultiClass);
+ if (Result != 0) {
+ Arg = Result;
+ }
+
+ // TODO: Process arg names
+ args.push_back(std::make_pair(Arg, ArgName));
+ }
+
+ return DagInit::get(Val, "", args);
+ }
+ if (MHSl) {
+ std::vector<Init *> NewOperands;
+ std::vector<Init *> NewList(MHSl->begin(), MHSl->end());
+
+ for (std::vector<Init *>::iterator li = NewList.begin(),
+ liend = NewList.end();
+ li != liend;
+ ++li) {
+ Init *Item = *li;
+ NewOperands.clear();
+ for(int i = 0; i < RHSo->getNumOperands(); ++i) {
+ // First, replace the foreach variable with the list item
+ if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
+ NewOperands.push_back(Item);
+ } else {
+ NewOperands.push_back(RHSo->getOperand(i));
+ }
+ }
+
+ // Now run the operator and use its result as the new list item
+ const OpInit *NewOp = RHSo->clone(NewOperands);
+ Init *NewItem = NewOp->Fold(CurRec, CurMultiClass);
+ if (NewItem != NewOp)
+ *li = NewItem;
+ }
+ return ListInit::get(NewList, MHSl->getType());
+ }
+ }
+ return 0;
+}
+
+Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
+ switch (getOpcode()) {
+ default: assert(0 && "Unknown binop");
+ case SUBST: {
+ DefInit *LHSd = dynamic_cast<DefInit*>(LHS);
+ VarInit *LHSv = dynamic_cast<VarInit*>(LHS);
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+
+ DefInit *MHSd = dynamic_cast<DefInit*>(MHS);
+ VarInit *MHSv = dynamic_cast<VarInit*>(MHS);
+ StringInit *MHSs = dynamic_cast<StringInit*>(MHS);
+
+ DefInit *RHSd = dynamic_cast<DefInit*>(RHS);
+ VarInit *RHSv = dynamic_cast<VarInit*>(RHS);
+ StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+
+ if ((LHSd && MHSd && RHSd)
+ || (LHSv && MHSv && RHSv)
+ || (LHSs && MHSs && RHSs)) {
+ if (RHSd) {
+ Record *Val = RHSd->getDef();
+ if (LHSd->getAsString() == RHSd->getAsString()) {
+ Val = MHSd->getDef();
+ }
+ return DefInit::get(Val);
+ }
+ if (RHSv) {
+ std::string Val = RHSv->getName();
+ if (LHSv->getAsString() == RHSv->getAsString()) {
+ Val = MHSv->getName();
+ }
+ return VarInit::get(Val, getType());
+ }
+ if (RHSs) {
+ std::string Val = RHSs->getValue();
+
+ std::string::size_type found;
+ std::string::size_type idx = 0;
+ do {
+ found = Val.find(LHSs->getValue(), idx);
+ if (found != std::string::npos) {
+ Val.replace(found, LHSs->getValue().size(), MHSs->getValue());
+ }
+ idx = found + MHSs->getValue().size();
+ } while (found != std::string::npos);
+
+ return StringInit::get(Val);
+ }
+ }
+ break;
+ }
+
+ case FOREACH: {
+ Init *Result = ForeachHelper(LHS, MHS, RHS, getType(),
+ CurRec, CurMultiClass);
+ if (Result != 0) {
+ return Result;
+ }
+ break;
+ }
+
+ case IF: {
+ IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
+ if (Init *I = LHS->convertInitializerTo(IntRecTy::get()))
+ LHSi = dynamic_cast<IntInit*>(I);
+ if (LHSi) {
+ if (LHSi->getValue()) {
+ return MHS;
+ } else {
+ return RHS;
+ }
+ }
+ break;
+ }
+ }
+
+ return const_cast<TernOpInit *>(this);
+}
+
+Init *TernOpInit::resolveReferences(Record &R,
+ const RecordVal *RV) const {
+ Init *lhs = LHS->resolveReferences(R, RV);
+
+ if (Opc == IF && lhs != LHS) {
+ IntInit *Value = dynamic_cast<IntInit*>(lhs);
+ if (Init *I = lhs->convertInitializerTo(IntRecTy::get()))
+ Value = dynamic_cast<IntInit*>(I);
+ if (Value != 0) {
+ // Short-circuit
+ if (Value->getValue()) {
+ Init *mhs = MHS->resolveReferences(R, RV);
+ return (TernOpInit::get(getOpcode(), lhs, mhs,
+ RHS, getType()))->Fold(&R, 0);
+ } else {
+ Init *rhs = RHS->resolveReferences(R, RV);
+ return (TernOpInit::get(getOpcode(), lhs, MHS,
+ rhs, getType()))->Fold(&R, 0);
+ }
+ }
+ }
+
+ Init *mhs = MHS->resolveReferences(R, RV);
+ Init *rhs = RHS->resolveReferences(R, RV);
+
+ if (LHS != lhs || MHS != mhs || RHS != rhs)
+ return (TernOpInit::get(getOpcode(), lhs, mhs, rhs,
+ getType()))->Fold(&R, 0);
+ return Fold(&R, 0);
+}
+
+std::string TernOpInit::getAsString() const {
+ std::string Result;
+ switch (Opc) {
+ case SUBST: Result = "!subst"; break;
+ case FOREACH: Result = "!foreach"; break;
+ case IF: Result = "!if"; break;
+ }
+ return Result + "(" + LHS->getAsString() + ", " + MHS->getAsString() + ", "
+ + RHS->getAsString() + ")";
+}
+
+RecTy *TypedInit::getFieldType(const std::string &FieldName) const {
+ RecordRecTy *RecordType = dynamic_cast<RecordRecTy *>(getType());
+ if (RecordType) {
+ RecordVal *Field = RecordType->getRecord()->getValue(FieldName);
+ if (Field) {
+ return Field->getType();
+ }
+ }
+ return 0;
+}
+
+Init *
+TypedInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) const {
+ BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
+ if (T == 0) return 0; // Cannot subscript a non-bits variable.
+ unsigned NumBits = T->getNumBits();
+
+ SmallVector<Init *, 16> NewBits(Bits.size());
+ for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
+ if (Bits[i] >= NumBits)
+ return 0;
+
+ NewBits[i] = VarBitInit::get(const_cast<TypedInit *>(this), Bits[i]);
+ }
+ return BitsInit::get(NewBits);
+}
+
+Init *
+TypedInit::convertInitListSlice(const std::vector<unsigned> &Elements) const {
+ ListRecTy *T = dynamic_cast<ListRecTy*>(getType());
+ if (T == 0) return 0; // Cannot subscript a non-list variable.
+
+ if (Elements.size() == 1)
+ return VarListElementInit::get(const_cast<TypedInit *>(this), Elements[0]);
+
+ std::vector<Init*> ListInits;
+ ListInits.reserve(Elements.size());
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i)
+ ListInits.push_back(VarListElementInit::get(const_cast<TypedInit *>(this),
+ Elements[i]));
+ return ListInit::get(ListInits, T);
+}
+
+
+VarInit *VarInit::get(const std::string &VN, RecTy *T) {
+ typedef std::pair<RecTy *, TableGenStringKey> Key;
+ typedef DenseMap<Key, VarInit *> 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) const {
+ if (R.isTemplateArg(getName())) return 0;
+ if (IRV && IRV->getName() != getName()) return 0;
+
+ RecordVal *RV = R.getValue(getName());
+ assert(RV && "Reference to a non-existent variable?");
+ assert(dynamic_cast<BitsInit*>(RV->getValue()));
+ BitsInit *BI = (BitsInit*)RV->getValue();
+
+ assert(Bit < BI->getNumBits() && "Bit reference out of range!");
+ Init *B = BI->getBit(Bit);
+
+ // If the bit is set to some value, or if we are resolving a reference to a
+ // specific variable and that variable is explicitly unset, then replace the
+ // VarBitInit with it.
+ if (IRV || !dynamic_cast<UnsetInit*>(B))
+ return B;
+ return 0;
+}
+
+Init *VarInit::resolveListElementReference(Record &R,
+ const RecordVal *IRV,
+ unsigned Elt) const {
+ if (R.isTemplateArg(getName())) return 0;
+ if (IRV && IRV->getName() != getName()) return 0;
+
+ RecordVal *RV = R.getValue(getName());
+ assert(RV && "Reference to a non-existent variable?");
+ ListInit *LI = dynamic_cast<ListInit*>(RV->getValue());
+ if (!LI) {
+ TypedInit *VI = dynamic_cast<TypedInit*>(RV->getValue());
+ assert(VI && "Invalid list element!");
+ return VarListElementInit::get(VI, Elt);
+ }
+
+ if (Elt >= LI->getSize())
+ return 0; // Out of range reference.
+ Init *E = LI->getElement(Elt);
+ // If the element is set to some value, or if we are resolving a reference
+ // to a specific variable and that variable is explicitly unset, then
+ // replace the VarListElementInit with it.
+ if (IRV || !dynamic_cast<UnsetInit*>(E))
+ return E;
+ return 0;
+}
+
+
+RecTy *VarInit::getFieldType(const std::string &FieldName) const {
+ if (RecordRecTy *RTy = dynamic_cast<RecordRecTy*>(getType()))
+ if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName))
+ return RV->getType();
+ return 0;
+}
+
+Init *VarInit::getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const {
+ if (dynamic_cast<RecordRecTy*>(getType()))
+ if (const RecordVal *Val = R.getValue(VarName)) {
+ if (RV != Val && (RV || dynamic_cast<UnsetInit*>(Val->getValue())))
+ return 0;
+ Init *TheInit = Val->getValue();
+ assert(TheInit != this && "Infinite loop detected!");
+ if (Init *I = TheInit->getFieldInit(R, RV, FieldName))
+ return I;
+ else
+ return 0;
+ }
+ return 0;
+}
+
+/// resolveReferences - This method is used by classes that refer to other
+/// variables which may not be defined at the time the expression is formed.
+/// 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) const {
+ if (RecordVal *Val = R.getValue(VarName))
+ if (RV == Val || (RV == 0 && !dynamic_cast<UnsetInit*>(Val->getValue())))
+ return Val->getValue();
+ return const_cast<VarInit *>(this);
+}
+
+VarBitInit *VarBitInit::get(TypedInit *T, unsigned B) {
+ typedef std::pair<TypedInit *, unsigned> Key;
+ typedef DenseMap<Key, VarBitInit *> 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) const {
+ if (Init *I = getVariable()->resolveBitReference(R, RV, getBitNum()))
+ return I;
+ return const_cast<VarBitInit *>(this);
+}
+
+VarListElementInit *VarListElementInit::get(TypedInit *T,
+ unsigned E) {
+ typedef std::pair<TypedInit *, unsigned> Key;
+ typedef DenseMap<Key, VarListElementInit *> 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) const {
+ if (Init *I = getVariable()->resolveListElementReference(R, RV,
+ getElementNum()))
+ return I;
+ return const_cast<VarListElementInit *>(this);
+}
+
+Init *VarListElementInit::resolveBitReference(Record &R, const RecordVal *RV,
+ 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) const {
+ Init *Result = TI->resolveListElementReference(R, RV, Element);
+
+ if (Result) {
+ TypedInit *TInit = dynamic_cast<TypedInit *>(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();
+ return 0;
+}
+
+Init *DefInit::getFieldInit(Record &R, const RecordVal *RV,
+ const std::string &FieldName) const {
+ return Def->getValue(FieldName)->getValue();
+}
+
+
+std::string DefInit::getAsString() const {
+ return Def->getName();
+}
+
+FieldInit *FieldInit::get(Init *R, const std::string &FN) {
+ typedef std::pair<Init *, TableGenStringKey> Key;
+ typedef DenseMap<Key, FieldInit *> 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) const {
+ if (Init *BitsVal = Rec->getFieldInit(R, RV, FieldName))
+ if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) {
+ assert(Bit < BI->getNumBits() && "Bit reference out of range!");
+ Init *B = BI->getBit(Bit);
+
+ if (dynamic_cast<BitInit*>(B)) // If the bit is set.
+ return B; // Replace the VarBitInit with it.
+ }
+ return 0;
+}
+
+Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV,
+ unsigned Elt) const {
+ if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName))
+ if (ListInit *LI = dynamic_cast<ListInit*>(ListVal)) {
+ if (Elt >= LI->getSize()) return 0;
+ Init *E = LI->getElement(Elt);
+
+ // If the element is set to some value, or if we are resolving a
+ // reference to a specific variable and that variable is explicitly
+ // unset, then replace the VarListElementInit with it.
+ if (RV || !dynamic_cast<UnsetInit*>(E))
+ return E;
+ }
+ return 0;
+}
+
+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 : const_cast<FieldInit *>(this);
+ }
+
+ if (NewRec != Rec) {
+ return FieldInit::get(NewRec, FieldName);
+ }
+ return const_cast<FieldInit *>(this);
+}
+
+void ProfileDagInit(FoldingSetNodeID &ID,
+ Init *V,
+ const std::string &VN,
+ ArrayRef<Init *> ArgRange,
+ ArrayRef<std::string> NameRange) {
+ ID.AddPointer(V);
+ ID.AddString(VN);
+
+ ArrayRef<Init *>::iterator Arg = ArgRange.begin();
+ ArrayRef<std::string>::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<Init *> ArgRange,
+ ArrayRef<std::string> NameRange) {
+ typedef FoldingSet<DagInit> 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<std::pair<Init*, std::string> > &args) {
+ typedef std::pair<Init*, std::string> PairType;
+
+ std::vector<Init *> Args;
+ std::vector<std::string> Names;
+
+ for (std::vector<PairType>::const_iterator i = args.begin(),
+ iend = args.end();
+ i != iend;
+ ++i) {
+ Args.push_back(i->first);
+ Names.push_back(i->second);
+ }
+
+ 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) const {
+ std::vector<Init*> NewArgs;
+ for (unsigned i = 0, e = Args.size(); i != e; ++i)
+ NewArgs.push_back(Args[i]->resolveReferences(R, RV));
+
+ Init *Op = Val->resolveReferences(R, RV);
+
+ if (Args != NewArgs || Op != Val)
+ return DagInit::get(Op, ValName, NewArgs, ArgNames);
+
+ return const_cast<DagInit *>(this);
+}
+
+
+std::string DagInit::getAsString() const {
+ std::string Result = "(" + Val->getAsString();
+ if (!ValName.empty())
+ Result += ":" + ValName;
+ if (Args.size()) {
+ Result += " " + Args[0]->getAsString();
+ if (!ArgNames[0].empty()) Result += ":$" + ArgNames[0];
+ for (unsigned i = 1, e = Args.size(); i != e; ++i) {
+ Result += ", " + Args[i]->getAsString();
+ if (!ArgNames[i].empty()) Result += ":$" + ArgNames[i];
+ }
+ }
+ return Result + ")";
+}
+
+
+//===----------------------------------------------------------------------===//
+// Other implementations
+//===----------------------------------------------------------------------===//
+
+RecordVal::RecordVal(Init *N, RecTy *T, unsigned P)
+ : Name(N), Ty(T), Prefix(P) {
+ 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<StringInit *>(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 {
+ if (getPrefix()) OS << "field ";
+ OS << *getType() << " " << getName();
+
+ if (getValue())
+ OS << " = " << *getValue();
+
+ if (PrintSem) OS << ";\n";
+}
+
+unsigned Record::LastID = 0;
+
+void Record::checkName() {
+ // Ensure the record name has string type.
+ const TypedInit *TypedName = dynamic_cast<const TypedInit *>(Name);
+ assert(TypedName && "Record name is not typed!");
+ RecTy *Type = TypedName->getType();
+ if (dynamic_cast<StringRecTy *>(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<const StringInit *>(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(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
+/// reference to RV with the RHS of RV. If RV is null, we resolve all possible
+/// references.
+void Record::resolveReferencesTo(const RecordVal *RV) {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i) {
+ if (Init *V = Values[i].getValue())
+ Values[i].setValue(V->resolveReferences(*this, RV));
+ }
+}
+
+void Record::dump() const { errs() << *this; }
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) {
+ OS << R.getName();
+
+ const std::vector<std::string> &TArgs = R.getTemplateArgs();
+ if (!TArgs.empty()) {
+ OS << "<";
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ if (i) OS << ", ";
+ const RecordVal *RV = R.getValue(TArgs[i]);
+ assert(RV && "Template argument record not found??");
+ RV->print(OS, false);
+ }
+ OS << ">";
+ }
+
+ OS << " {";
+ const std::vector<Record*> &SC = R.getSuperClasses();
+ if (!SC.empty()) {
+ OS << "\t//";
+ for (unsigned i = 0, e = SC.size(); i != e; ++i)
+ OS << " " << SC[i]->getName();
+ }
+ OS << "\n";
+
+ const std::vector<RecordVal> &Vals = R.getValues();
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
+ OS << Vals[i];
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (!Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
+ OS << Vals[i];
+
+ return OS << "}\n";
+}
+
+/// getValueInit - Return the initializer for a value with the specified name,
+/// or throw an exception if the field does not exist.
+///
+Init *Record::getValueInit(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+ return R->getValue();
+}
+
+
+/// getValueAsString - This method looks up the specified field and returns its
+/// value as a string, throwing an exception if the field does not exist or if
+/// the value is not a string.
+///
+std::string Record::getValueAsString(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (StringInit *SI = dynamic_cast<StringInit*>(R->getValue()))
+ return SI->getValue();
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a string initializer!";
+}
+
+/// getValueAsBitsInit - This method looks up the specified field and returns
+/// its value as a BitsInit, throwing an exception if the field does not exist
+/// or if the value is not the right type.
+///
+BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (BitsInit *BI = dynamic_cast<BitsInit*>(R->getValue()))
+ return BI;
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a BitsInit initializer!";
+}
+
+/// getValueAsListInit - This method looks up the specified field and returns
+/// its value as a ListInit, throwing an exception if the field does not exist
+/// or if the value is not the right type.
+///
+ListInit *Record::getValueAsListInit(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (ListInit *LI = dynamic_cast<ListInit*>(R->getValue()))
+ return LI;
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a list initializer!";
+}
+
+/// getValueAsListOfDefs - This method looks up the specified field and returns
+/// its value as a vector of records, throwing an exception if the field does
+/// not exist or if the value is not the right type.
+///
+std::vector<Record*>
+Record::getValueAsListOfDefs(StringRef FieldName) const {
+ ListInit *List = getValueAsListInit(FieldName);
+ std::vector<Record*> Defs;
+ for (unsigned i = 0; i < List->getSize(); i++) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(List->getElement(i))) {
+ Defs.push_back(DI->getDef());
+ } else {
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' list is not entirely DefInit!";
+ }
+ }
+ return Defs;
+}
+
+/// getValueAsInt - This method looks up the specified field and returns its
+/// value as an int64_t, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+int64_t Record::getValueAsInt(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (IntInit *II = dynamic_cast<IntInit*>(R->getValue()))
+ return II->getValue();
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have an int initializer!";
+}
+
+/// getValueAsListOfInts - This method looks up the specified field and returns
+/// its value as a vector of integers, throwing an exception if the field does
+/// not exist or if the value is not the right type.
+///
+std::vector<int64_t>
+Record::getValueAsListOfInts(StringRef FieldName) const {
+ ListInit *List = getValueAsListInit(FieldName);
+ std::vector<int64_t> Ints;
+ for (unsigned i = 0; i < List->getSize(); i++) {
+ if (IntInit *II = dynamic_cast<IntInit*>(List->getElement(i))) {
+ Ints.push_back(II->getValue());
+ } else {
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a list of ints initializer!";
+ }
+ }
+ return Ints;
+}
+
+/// getValueAsListOfStrings - This method looks up the specified field and
+/// returns its value as a vector of strings, throwing an exception if the
+/// field does not exist or if the value is not the right type.
+///
+std::vector<std::string>
+Record::getValueAsListOfStrings(StringRef FieldName) const {
+ ListInit *List = getValueAsListInit(FieldName);
+ std::vector<std::string> Strings;
+ for (unsigned i = 0; i < List->getSize(); i++) {
+ if (StringInit *II = dynamic_cast<StringInit*>(List->getElement(i))) {
+ Strings.push_back(II->getValue());
+ } else {
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a list of strings initializer!";
+ }
+ }
+ return Strings;
+}
+
+/// getValueAsDef - This method looks up the specified field and returns its
+/// value as a Record, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+Record *Record::getValueAsDef(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (DefInit *DI = dynamic_cast<DefInit*>(R->getValue()))
+ return DI->getDef();
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a def initializer!";
+}
+
+/// getValueAsBit - This method looks up the specified field and returns its
+/// value as a bit, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+bool Record::getValueAsBit(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (BitInit *BI = dynamic_cast<BitInit*>(R->getValue()))
+ return BI->getValue();
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a bit initializer!";
+}
+
+/// getValueAsDag - This method looks up the specified field and returns its
+/// value as an Dag, throwing an exception if the field does not exist or if
+/// the value is not the right type.
+///
+DagInit *Record::getValueAsDag(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (DagInit *DI = dynamic_cast<DagInit*>(R->getValue()))
+ return DI;
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a dag initializer!";
+}
+
+std::string Record::getValueAsCode(StringRef FieldName) const {
+ const RecordVal *R = getValue(FieldName);
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + getName() + "' does not have a field named `" +
+ FieldName.str() + "'!\n";
+
+ if (CodeInit *CI = dynamic_cast<CodeInit*>(R->getValue()))
+ return CI->getValue();
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a code initializer!";
+}
+
+
+void MultiClass::dump() const {
+ errs() << "Record:\n";
+ Rec.dump();
+
+ errs() << "Defs:\n";
+ for (RecordVector::const_iterator r = DefPrototypes.begin(),
+ rend = DefPrototypes.end();
+ r != rend;
+ ++r) {
+ (*r)->dump();
+ }
+}
+
+
+void RecordKeeper::dump() const { errs() << *this; }
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) {
+ OS << "------------- Classes -----------------\n";
+ const std::map<std::string, Record*> &Classes = RK.getClasses();
+ for (std::map<std::string, Record*>::const_iterator I = Classes.begin(),
+ E = Classes.end(); I != E; ++I)
+ OS << "class " << *I->second;
+
+ OS << "------------- Defs -----------------\n";
+ const std::map<std::string, Record*> &Defs = RK.getDefs();
+ for (std::map<std::string, Record*>::const_iterator I = Defs.begin(),
+ E = Defs.end(); I != E; ++I)
+ OS << "def " << *I->second;
+ return OS;
+}
+
+
+/// getAllDerivedDefinitions - This method returns all concrete definitions
+/// that derive from the specified class name. If a class with the specified
+/// name does not exist, an error is printed and true is returned.
+std::vector<Record*>
+RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const {
+ Record *Class = getClass(ClassName);
+ if (!Class)
+ throw "ERROR: Couldn't find the `" + ClassName + "' class!\n";
+
+ std::vector<Record*> Defs;
+ for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(),
+ E = getDefs().end(); I != E; ++I)
+ if (I->second->isSubClassOf(Class))
+ Defs.push_back(I->second);
+
+ return Defs;
+}
+
diff --git a/lib/TableGen/TGLexer.cpp b/lib/TableGen/TGLexer.cpp
new file mode 100644
index 0000000..8c1b429
--- /dev/null
+++ b/lib/TableGen/TGLexer.cpp
@@ -0,0 +1,435 @@
+//===- TGLexer.cpp - Lexer for TableGen -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implement the Lexer for TableGen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TGLexer.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Config/config.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+using namespace llvm;
+
+TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
+ CurBuffer = 0;
+ CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
+ CurPtr = CurBuf->getBufferStart();
+ TokStart = 0;
+}
+
+SMLoc TGLexer::getLoc() const {
+ return SMLoc::getFromPointer(TokStart);
+}
+
+/// ReturnError - Set the error to the specified string at the specified
+/// location. This is defined to always return tgtok::Error.
+tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) {
+ PrintError(Loc, Msg);
+ return tgtok::Error;
+}
+
+int TGLexer::getNextChar() {
+ char CurChar = *CurPtr++;
+ switch (CurChar) {
+ default:
+ return (unsigned char)CurChar;
+ case 0: {
+ // A nul character in the stream is either the end of the current buffer or
+ // a random nul in the file. Disambiguate that here.
+ if (CurPtr-1 != CurBuf->getBufferEnd())
+ return 0; // Just whitespace.
+
+ // If this is the end of an included file, pop the parent file off the
+ // include stack.
+ SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
+ if (ParentIncludeLoc != SMLoc()) {
+ CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
+ CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
+ CurPtr = ParentIncludeLoc.getPointer();
+ return getNextChar();
+ }
+
+ // Otherwise, return end of file.
+ --CurPtr; // Another call to lex will return EOF again.
+ return EOF;
+ }
+ case '\n':
+ case '\r':
+ // Handle the newline character by ignoring it and incrementing the line
+ // count. However, be careful about 'dos style' files with \n\r in them.
+ // Only treat a \n\r or \r\n as a single line.
+ if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
+ *CurPtr != CurChar)
+ ++CurPtr; // Eat the two char newline sequence.
+ return '\n';
+ }
+}
+
+tgtok::TokKind TGLexer::LexToken() {
+ TokStart = CurPtr;
+ // This always consumes at least one character.
+ int CurChar = getNextChar();
+
+ switch (CurChar) {
+ default:
+ // Handle letters: [a-zA-Z_#]
+ if (isalpha(CurChar) || CurChar == '_' || CurChar == '#')
+ return LexIdentifier();
+
+ // Unknown character, emit an error.
+ return ReturnError(TokStart, "Unexpected character");
+ case EOF: return tgtok::Eof;
+ case ':': return tgtok::colon;
+ case ';': return tgtok::semi;
+ case '.': return tgtok::period;
+ case ',': return tgtok::comma;
+ case '<': return tgtok::less;
+ case '>': return tgtok::greater;
+ case ']': return tgtok::r_square;
+ case '{': return tgtok::l_brace;
+ case '}': return tgtok::r_brace;
+ case '(': return tgtok::l_paren;
+ case ')': return tgtok::r_paren;
+ case '=': return tgtok::equal;
+ case '?': return tgtok::question;
+
+ case 0:
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ // Ignore whitespace.
+ return LexToken();
+ case '/':
+ // If this is the start of a // comment, skip until the end of the line or
+ // the end of the buffer.
+ if (*CurPtr == '/')
+ SkipBCPLComment();
+ else if (*CurPtr == '*') {
+ if (SkipCComment())
+ return tgtok::Error;
+ } else // Otherwise, this is an error.
+ return ReturnError(TokStart, "Unexpected character");
+ return LexToken();
+ case '-': case '+':
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ return LexNumber();
+ case '"': return LexString();
+ case '$': return LexVarName();
+ case '[': return LexBracket();
+ case '!': return LexExclaim();
+ }
+}
+
+/// LexString - Lex "[^"]*"
+tgtok::TokKind TGLexer::LexString() {
+ const char *StrStart = CurPtr;
+
+ CurStrVal = "";
+
+ while (*CurPtr != '"') {
+ // If we hit the end of the buffer, report an error.
+ if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd())
+ return ReturnError(StrStart, "End of file in string literal");
+
+ if (*CurPtr == '\n' || *CurPtr == '\r')
+ return ReturnError(StrStart, "End of line in string literal");
+
+ if (*CurPtr != '\\') {
+ CurStrVal += *CurPtr++;
+ continue;
+ }
+
+ ++CurPtr;
+
+ switch (*CurPtr) {
+ case '\\': case '\'': case '"':
+ // These turn into their literal character.
+ CurStrVal += *CurPtr++;
+ break;
+ case 't':
+ CurStrVal += '\t';
+ ++CurPtr;
+ break;
+ case 'n':
+ CurStrVal += '\n';
+ ++CurPtr;
+ break;
+
+ case '\n':
+ case '\r':
+ return ReturnError(CurPtr, "escaped newlines not supported in tblgen");
+
+ // If we hit the end of the buffer, report an error.
+ case '\0':
+ if (CurPtr == CurBuf->getBufferEnd())
+ return ReturnError(StrStart, "End of file in string literal");
+ // FALL THROUGH
+ default:
+ return ReturnError(CurPtr, "invalid escape in string literal");
+ }
+ }
+
+ ++CurPtr;
+ return tgtok::StrVal;
+}
+
+tgtok::TokKind TGLexer::LexVarName() {
+ if (!isalpha(CurPtr[0]) && CurPtr[0] != '_')
+ return ReturnError(TokStart, "Invalid variable name");
+
+ // Otherwise, we're ok, consume the rest of the characters.
+ const char *VarNameStart = CurPtr++;
+
+ while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
+ ++CurPtr;
+
+ CurStrVal.assign(VarNameStart, CurPtr);
+ return tgtok::VarName;
+}
+
+
+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.
+ StringRef Str(IdentStart, CurPtr-IdentStart);
+
+ if (Str == "include") {
+ if (LexInclude()) return tgtok::Error;
+ return Lex();
+ }
+
+ tgtok::TokKind Kind = StringSwitch<tgtok::TokKind>(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
+/// comes next and enter the include.
+bool TGLexer::LexInclude() {
+ // The token after the include must be a string.
+ tgtok::TokKind Tok = LexToken();
+ if (Tok == tgtok::Error) return true;
+ if (Tok != tgtok::StrVal) {
+ PrintError(getLoc(), "Expected filename after include");
+ return true;
+ }
+
+ // Get the string.
+ std::string Filename = CurStrVal;
+ std::string IncludedFile;
+
+
+ CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr),
+ IncludedFile);
+ if (CurBuffer == -1) {
+ PrintError(getLoc(), "Could not find include file '" + Filename + "'");
+ return true;
+ }
+
+ Dependencies.push_back(IncludedFile);
+ // Save the line number and lex buffer of the includer.
+ CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
+ CurPtr = CurBuf->getBufferStart();
+ return false;
+}
+
+void TGLexer::SkipBCPLComment() {
+ ++CurPtr; // skip the second slash.
+ while (1) {
+ switch (*CurPtr) {
+ case '\n':
+ case '\r':
+ return; // Newline is end of comment.
+ case 0:
+ // If this is the end of the buffer, end the comment.
+ if (CurPtr == CurBuf->getBufferEnd())
+ return;
+ break;
+ }
+ // Otherwise, skip the character.
+ ++CurPtr;
+ }
+}
+
+/// SkipCComment - This skips C-style /**/ comments. The only difference from C
+/// is that we allow nesting.
+bool TGLexer::SkipCComment() {
+ ++CurPtr; // skip the star.
+ unsigned CommentDepth = 1;
+
+ while (1) {
+ int CurChar = getNextChar();
+ switch (CurChar) {
+ case EOF:
+ PrintError(TokStart, "Unterminated comment!");
+ return true;
+ case '*':
+ // End of the comment?
+ if (CurPtr[0] != '/') break;
+
+ ++CurPtr; // End the */.
+ if (--CommentDepth == 0)
+ return false;
+ break;
+ case '/':
+ // Start of a nested comment?
+ if (CurPtr[0] != '*') break;
+ ++CurPtr;
+ ++CommentDepth;
+ break;
+ }
+ }
+}
+
+/// LexNumber - Lex:
+/// [-+]?[0-9]+
+/// 0x[0-9a-fA-F]+
+/// 0b[01]+
+tgtok::TokKind TGLexer::LexNumber() {
+ if (CurPtr[-1] == '0') {
+ if (CurPtr[0] == 'x') {
+ ++CurPtr;
+ const char *NumStart = CurPtr;
+ while (isxdigit(CurPtr[0]))
+ ++CurPtr;
+
+ // Requires at least one hex digit.
+ if (CurPtr == NumStart)
+ return ReturnError(TokStart, "Invalid hexadecimal number");
+
+ errno = 0;
+ CurIntVal = strtoll(NumStart, 0, 16);
+ if (errno == EINVAL)
+ return ReturnError(TokStart, "Invalid hexadecimal number");
+ if (errno == ERANGE) {
+ errno = 0;
+ CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
+ if (errno == EINVAL)
+ return ReturnError(TokStart, "Invalid hexadecimal number");
+ if (errno == ERANGE)
+ return ReturnError(TokStart, "Hexadecimal number out of range");
+ }
+ return tgtok::IntVal;
+ } else if (CurPtr[0] == 'b') {
+ ++CurPtr;
+ const char *NumStart = CurPtr;
+ while (CurPtr[0] == '0' || CurPtr[0] == '1')
+ ++CurPtr;
+
+ // Requires at least one binary digit.
+ if (CurPtr == NumStart)
+ return ReturnError(CurPtr-2, "Invalid binary number");
+ CurIntVal = strtoll(NumStart, 0, 2);
+ return tgtok::IntVal;
+ }
+ }
+
+ // Check for a sign without a digit.
+ if (!isdigit(CurPtr[0])) {
+ if (CurPtr[-1] == '-')
+ return tgtok::minus;
+ else if (CurPtr[-1] == '+')
+ return tgtok::plus;
+ }
+
+ while (isdigit(CurPtr[0]))
+ ++CurPtr;
+ CurIntVal = strtoll(TokStart, 0, 10);
+ return tgtok::IntVal;
+}
+
+/// LexBracket - We just read '['. If this is a code block, return it,
+/// otherwise return the bracket. Match: '[' and '[{ ( [^}]+ | }[^]] )* }]'
+tgtok::TokKind TGLexer::LexBracket() {
+ if (CurPtr[0] != '{')
+ return tgtok::l_square;
+ ++CurPtr;
+ const char *CodeStart = CurPtr;
+ while (1) {
+ int Char = getNextChar();
+ if (Char == EOF) break;
+
+ if (Char != '}') continue;
+
+ Char = getNextChar();
+ if (Char == EOF) break;
+ if (Char == ']') {
+ CurStrVal.assign(CodeStart, CurPtr-2);
+ return tgtok::CodeFragment;
+ }
+ }
+
+ return ReturnError(CodeStart-2, "Unterminated Code Block");
+}
+
+/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
+tgtok::TokKind TGLexer::LexExclaim() {
+ if (!isalpha(*CurPtr))
+ return ReturnError(CurPtr - 1, "Invalid \"!operator\"");
+
+ const char *Start = CurPtr++;
+ while (isalpha(*CurPtr))
+ ++CurPtr;
+
+ // Check to see which operator this is.
+ tgtok::TokKind Kind =
+ StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start))
+ .Case("eq", tgtok::XEq)
+ .Case("if", tgtok::XIf)
+ .Case("head", tgtok::XHead)
+ .Case("tail", tgtok::XTail)
+ .Case("con", tgtok::XConcat)
+ .Case("shl", tgtok::XSHL)
+ .Case("sra", tgtok::XSRA)
+ .Case("srl", tgtok::XSRL)
+ .Case("cast", tgtok::XCast)
+ .Case("empty", tgtok::XEmpty)
+ .Case("subst", tgtok::XSubst)
+ .Case("foreach", tgtok::XForEach)
+ .Case("strconcat", tgtok::XStrConcat)
+ .Default(tgtok::Error);
+
+ return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator");
+}
+
diff --git a/utils/TableGen/TGLexer.h b/lib/TableGen/TGLexer.h
index 84d328b..84d328b 100644
--- a/utils/TableGen/TGLexer.h
+++ b/lib/TableGen/TGLexer.h
diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp
new file mode 100644
index 0000000..e7f00ba
--- /dev/null
+++ b/lib/TableGen/TGParser.cpp
@@ -0,0 +1,2194 @@
+//===- TGParser.cpp - Parser for TableGen Files ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implement the Parser for TableGen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TGParser.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include <algorithm>
+#include <sstream>
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/CommandLine.h"
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Support Code for the Semantic Actions.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+struct SubClassReference {
+ SMLoc RefLoc;
+ Record *Rec;
+ std::vector<Init*> TemplateArgs;
+ SubClassReference() : Rec(0) {}
+
+ bool isInvalid() const { return Rec == 0; }
+};
+
+struct SubMultiClassReference {
+ SMLoc RefLoc;
+ MultiClass *MC;
+ std::vector<Init*> TemplateArgs;
+ SubMultiClassReference() : MC(0) {}
+
+ bool isInvalid() const { return MC == 0; }
+ void dump() const;
+};
+
+void SubMultiClassReference::dump() const {
+ errs() << "Multiclass:\n";
+
+ MC->dump();
+
+ errs() << "Template args:\n";
+ for (std::vector<Init *>::const_iterator i = TemplateArgs.begin(),
+ iend = TemplateArgs.end();
+ i != iend;
+ ++i) {
+ (*i)->dump();
+ }
+}
+
+} // end namespace llvm
+
+bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) {
+ if (CurRec == 0)
+ CurRec = &CurMultiClass->Rec;
+
+ if (RecordVal *ERV = CurRec->getValue(RV.getName())) {
+ // The value already exists in the class, treat this as a set.
+ if (ERV->setValue(RV.getValue()))
+ return Error(Loc, "New definition of '" + RV.getName() + "' of type '" +
+ RV.getType()->getAsString() + "' is incompatible with " +
+ "previous definition of type '" +
+ ERV->getType()->getAsString() + "'");
+ } else {
+ CurRec->addValue(RV);
+ }
+ return false;
+}
+
+/// SetValue -
+/// Return true on error, false on success.
+bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName,
+ const std::vector<unsigned> &BitList, Init *V) {
+ if (!V) return false;
+
+ if (CurRec == 0) CurRec = &CurMultiClass->Rec;
+
+ RecordVal *RV = CurRec->getValue(ValName);
+ if (RV == 0)
+ return Error(Loc, "Value '" + ValName + "' unknown!");
+
+ // Do not allow assignments like 'X = X'. This will just cause infinite loops
+ // in the resolution machinery.
+ if (BitList.empty())
+ if (VarInit *VI = dynamic_cast<VarInit*>(V))
+ if (VI->getName() == ValName)
+ return false;
+
+ // If we are assigning to a subset of the bits in the value... then we must be
+ // assigning to a field of BitsRecTy, which must have a BitsInit
+ // initializer.
+ //
+ if (!BitList.empty()) {
+ BitsInit *CurVal = dynamic_cast<BitsInit*>(RV->getValue());
+ if (CurVal == 0)
+ 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(BitsRecTy::get(BitList.size()));
+ if (BI == 0) {
+ V->convertInitializerTo(BitsRecTy::get(BitList.size()));
+ return Error(Loc, "Initializer is not compatible with bit range");
+ }
+
+ // We should have a BitsInit type now.
+ BitsInit *BInit = dynamic_cast<BitsInit*>(BI);
+ assert(BInit != 0);
+
+ SmallVector<Init *, 16> 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 (NewBits[Bit])
+ return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" +
+ ValName + "' more than once");
+ NewBits[Bit] = BInit->getBit(i);
+ }
+
+ for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i)
+ if (NewBits[i] == 0)
+ NewBits[i] = CurVal->getBit(i);
+
+ V = BitsInit::get(NewBits);
+ }
+
+ if (RV->setValue(V))
+ return Error(Loc, "Value '" + ValName + "' of type '" +
+ RV->getType()->getAsString() +
+ "' is incompatible with initializer '" + V->getAsString() +"'");
+ return false;
+}
+
+/// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template
+/// args as SubClass's template arguments.
+bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
+ Record *SC = SubClass.Rec;
+ // Add all of the values in the subclass into the current class.
+ const std::vector<RecordVal> &Vals = SC->getValues();
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i)
+ if (AddValue(CurRec, SubClass.RefLoc, Vals[i]))
+ return true;
+
+ const std::vector<std::string> &TArgs = SC->getTemplateArgs();
+
+ // Ensure that an appropriate number of template arguments are specified.
+ if (TArgs.size() < SubClass.TemplateArgs.size())
+ return Error(SubClass.RefLoc, "More template args specified than expected");
+
+ // 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) {
+ if (i < SubClass.TemplateArgs.size()) {
+ // If a value is specified for this template arg, set it now.
+ if (SetValue(CurRec, SubClass.RefLoc, TArgs[i], std::vector<unsigned>(),
+ SubClass.TemplateArgs[i]))
+ return true;
+
+ // 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(SubClass.RefLoc,"Value not specified for template argument #"
+ + utostr(i) + " (" + TArgs[i] + ") of subclass '" +
+ SC->getName() + "'!");
+ }
+ }
+
+ // Since everything went well, we can now set the "superclass" list for the
+ // current record.
+ const std::vector<Record*> &SCs = SC->getSuperClasses();
+ for (unsigned i = 0, e = SCs.size(); i != e; ++i) {
+ if (CurRec->isSubClassOf(SCs[i]))
+ return Error(SubClass.RefLoc,
+ "Already subclass of '" + SCs[i]->getName() + "'!\n");
+ CurRec->addSuperClass(SCs[i]);
+ }
+
+ if (CurRec->isSubClassOf(SC))
+ return Error(SubClass.RefLoc,
+ "Already subclass of '" + SC->getName() + "'!\n");
+ CurRec->addSuperClass(SC);
+ return false;
+}
+
+/// AddSubMultiClass - Add SubMultiClass as a subclass to
+/// CurMC, resolving its template args as SubMultiClass's
+/// template arguments.
+bool TGParser::AddSubMultiClass(MultiClass *CurMC,
+ SubMultiClassReference &SubMultiClass) {
+ MultiClass *SMC = SubMultiClass.MC;
+ Record *CurRec = &CurMC->Rec;
+
+ const std::vector<RecordVal> &MCVals = CurRec->getValues();
+
+ // Add all of the values in the subclass into the current class.
+ const std::vector<RecordVal> &SMCVals = SMC->Rec.getValues();
+ for (unsigned i = 0, e = SMCVals.size(); i != e; ++i)
+ if (AddValue(CurRec, SubMultiClass.RefLoc, SMCVals[i]))
+ return true;
+
+ int newDefStart = CurMC->DefPrototypes.size();
+
+ // Add all of the defs in the subclass into the current multiclass.
+ for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(),
+ iend = SMC->DefPrototypes.end();
+ i != iend;
+ ++i) {
+ // Clone the def and add it to the current multiclass
+ Record *NewDef = new Record(**i);
+
+ // Add all of the values in the superclass into the current def.
+ for (unsigned i = 0, e = MCVals.size(); i != e; ++i)
+ if (AddValue(NewDef, SubMultiClass.RefLoc, MCVals[i]))
+ return true;
+
+ CurMC->DefPrototypes.push_back(NewDef);
+ }
+
+ const std::vector<std::string> &SMCTArgs = SMC->Rec.getTemplateArgs();
+
+ // Ensure that an appropriate number of template arguments are
+ // specified.
+ if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size())
+ return Error(SubMultiClass.RefLoc,
+ "More template args specified than expected");
+
+ // 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 = SMCTArgs.size(); i != e; ++i) {
+ if (i < SubMultiClass.TemplateArgs.size()) {
+ // If a value is specified for this template arg, set it in the
+ // superclass now.
+ if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i],
+ std::vector<unsigned>(),
+ SubMultiClass.TemplateArgs[i]))
+ return true;
+
+ // Resolve it next.
+ CurRec->resolveReferencesTo(CurRec->getValue(SMCTArgs[i]));
+
+ // Now remove it.
+ CurRec->removeValue(SMCTArgs[i]);
+
+ // If a value is specified for this template arg, set it in the
+ // new defs now.
+ for (MultiClass::RecordVector::iterator j =
+ CurMC->DefPrototypes.begin() + newDefStart,
+ jend = CurMC->DefPrototypes.end();
+ j != jend;
+ ++j) {
+ Record *Def = *j;
+
+ if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i],
+ std::vector<unsigned>(),
+ SubMultiClass.TemplateArgs[i]))
+ return true;
+
+ // Resolve it next.
+ Def->resolveReferencesTo(Def->getValue(SMCTArgs[i]));
+
+ // Now remove it
+ Def->removeValue(SMCTArgs[i]);
+ }
+ } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) {
+ return Error(SubMultiClass.RefLoc,
+ "Value not specified for template argument #"
+ + utostr(i) + " (" + SMCTArgs[i] + ") of subclass '" +
+ SMC->Rec.getName() + "'!");
+ }
+ }
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Parser Code
+//===----------------------------------------------------------------------===//
+
+/// isObjectStart - Return true if this is a valid first token for an Object.
+static bool isObjectStart(tgtok::TokKind K) {
+ return K == tgtok::Class || K == tgtok::Def ||
+ K == tgtok::Defm || K == tgtok::Let || K == tgtok::MultiClass;
+}
+
+static std::string GetNewAnonymousName() {
+ static unsigned AnonCounter = 0;
+ return "anonymous."+utostr(AnonCounter++);
+}
+
+/// ParseObjectName - If an object name is specified, return it. Otherwise,
+/// return an anonymous name.
+/// ObjectName ::= ID
+/// ObjectName ::= /*empty*/
+///
+std::string TGParser::ParseObjectName() {
+ if (Lex.getCode() != tgtok::Id)
+ return GetNewAnonymousName();
+
+ std::string Ret = Lex.getCurStrVal();
+ Lex.Lex();
+ return Ret;
+}
+
+
+/// ParseClassID - Parse and resolve a reference to a class name. This returns
+/// null on error.
+///
+/// ClassID ::= ID
+///
+Record *TGParser::ParseClassID() {
+ if (Lex.getCode() != tgtok::Id) {
+ TokError("expected name for ClassID");
+ return 0;
+ }
+
+ Record *Result = Records.getClass(Lex.getCurStrVal());
+ if (Result == 0)
+ TokError("Couldn't find class '" + Lex.getCurStrVal() + "'");
+
+ Lex.Lex();
+ return Result;
+}
+
+/// ParseMultiClassID - Parse and resolve a reference to a multiclass name.
+/// This returns null on error.
+///
+/// MultiClassID ::= ID
+///
+MultiClass *TGParser::ParseMultiClassID() {
+ if (Lex.getCode() != tgtok::Id) {
+ TokError("expected name for ClassID");
+ return 0;
+ }
+
+ MultiClass *Result = MultiClasses[Lex.getCurStrVal()];
+ if (Result == 0)
+ TokError("Couldn't find class '" + Lex.getCurStrVal() + "'");
+
+ Lex.Lex();
+ return Result;
+}
+
+Record *TGParser::ParseDefmID() {
+ if (Lex.getCode() != tgtok::Id) {
+ TokError("expected multiclass name");
+ return 0;
+ }
+
+ MultiClass *MC = MultiClasses[Lex.getCurStrVal()];
+ if (MC == 0) {
+ TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'");
+ return 0;
+ }
+
+ Lex.Lex();
+ return &MC->Rec;
+}
+
+
+/// ParseSubClassReference - Parse a reference to a subclass or to a templated
+/// subclass. This returns a SubClassRefTy with a null Record* on error.
+///
+/// SubClassRef ::= ClassID
+/// SubClassRef ::= ClassID '<' ValueList '>'
+///
+SubClassReference TGParser::
+ParseSubClassReference(Record *CurRec, bool isDefm) {
+ SubClassReference Result;
+ Result.RefLoc = Lex.getLoc();
+
+ if (isDefm)
+ Result.Rec = ParseDefmID();
+ else
+ Result.Rec = ParseClassID();
+ if (Result.Rec == 0) return Result;
+
+ // If there is no template arg list, we're done.
+ if (Lex.getCode() != tgtok::less)
+ return Result;
+ Lex.Lex(); // Eat the '<'
+
+ if (Lex.getCode() == tgtok::greater) {
+ TokError("subclass reference requires a non-empty list of template values");
+ Result.Rec = 0;
+ return Result;
+ }
+
+ Result.TemplateArgs = ParseValueList(CurRec, Result.Rec);
+ if (Result.TemplateArgs.empty()) {
+ Result.Rec = 0; // Error parsing value list.
+ return Result;
+ }
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' in template value list");
+ Result.Rec = 0;
+ return Result;
+ }
+ Lex.Lex();
+
+ return Result;
+}
+
+/// ParseSubMultiClassReference - Parse a reference to a subclass or to a
+/// templated submulticlass. This returns a SubMultiClassRefTy with a null
+/// Record* on error.
+///
+/// SubMultiClassRef ::= MultiClassID
+/// SubMultiClassRef ::= MultiClassID '<' ValueList '>'
+///
+SubMultiClassReference TGParser::
+ParseSubMultiClassReference(MultiClass *CurMC) {
+ SubMultiClassReference Result;
+ Result.RefLoc = Lex.getLoc();
+
+ Result.MC = ParseMultiClassID();
+ if (Result.MC == 0) return Result;
+
+ // If there is no template arg list, we're done.
+ if (Lex.getCode() != tgtok::less)
+ return Result;
+ Lex.Lex(); // Eat the '<'
+
+ if (Lex.getCode() == tgtok::greater) {
+ TokError("subclass reference requires a non-empty list of template values");
+ Result.MC = 0;
+ return Result;
+ }
+
+ Result.TemplateArgs = ParseValueList(&CurMC->Rec, &Result.MC->Rec);
+ if (Result.TemplateArgs.empty()) {
+ Result.MC = 0; // Error parsing value list.
+ return Result;
+ }
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' in template value list");
+ Result.MC = 0;
+ return Result;
+ }
+ Lex.Lex();
+
+ return Result;
+}
+
+/// ParseRangePiece - Parse a bit/value range.
+/// RangePiece ::= INTVAL
+/// RangePiece ::= INTVAL '-' INTVAL
+/// RangePiece ::= INTVAL INTVAL
+bool TGParser::ParseRangePiece(std::vector<unsigned> &Ranges) {
+ if (Lex.getCode() != tgtok::IntVal) {
+ TokError("expected integer or bitrange");
+ return true;
+ }
+ int64_t Start = Lex.getCurIntVal();
+ int64_t End;
+
+ if (Start < 0)
+ return TokError("invalid range, cannot be negative");
+
+ switch (Lex.Lex()) { // eat first character.
+ default:
+ Ranges.push_back(Start);
+ return false;
+ case tgtok::minus:
+ if (Lex.Lex() != tgtok::IntVal) {
+ TokError("expected integer value as end of range");
+ return true;
+ }
+ End = Lex.getCurIntVal();
+ break;
+ case tgtok::IntVal:
+ End = -Lex.getCurIntVal();
+ break;
+ }
+ if (End < 0)
+ return TokError("invalid range, cannot be negative");
+ Lex.Lex();
+
+ // Add to the range.
+ if (Start < End) {
+ for (; Start <= End; ++Start)
+ Ranges.push_back(Start);
+ } else {
+ for (; Start >= End; --Start)
+ Ranges.push_back(Start);
+ }
+ return false;
+}
+
+/// ParseRangeList - Parse a list of scalars and ranges into scalar values.
+///
+/// RangeList ::= RangePiece (',' RangePiece)*
+///
+std::vector<unsigned> TGParser::ParseRangeList() {
+ std::vector<unsigned> Result;
+
+ // Parse the first piece.
+ if (ParseRangePiece(Result))
+ return std::vector<unsigned>();
+ while (Lex.getCode() == tgtok::comma) {
+ Lex.Lex(); // Eat the comma.
+
+ // Parse the next range piece.
+ if (ParseRangePiece(Result))
+ return std::vector<unsigned>();
+ }
+ return Result;
+}
+
+/// ParseOptionalRangeList - Parse either a range list in <>'s or nothing.
+/// OptionalRangeList ::= '<' RangeList '>'
+/// OptionalRangeList ::= /*empty*/
+bool TGParser::ParseOptionalRangeList(std::vector<unsigned> &Ranges) {
+ if (Lex.getCode() != tgtok::less)
+ return false;
+
+ SMLoc StartLoc = Lex.getLoc();
+ Lex.Lex(); // eat the '<'
+
+ // Parse the range list.
+ Ranges = ParseRangeList();
+ if (Ranges.empty()) return true;
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' at end of range list");
+ return Error(StartLoc, "to match this '<'");
+ }
+ Lex.Lex(); // eat the '>'.
+ return false;
+}
+
+/// ParseOptionalBitList - Parse either a bit list in {}'s or nothing.
+/// OptionalBitList ::= '{' RangeList '}'
+/// OptionalBitList ::= /*empty*/
+bool TGParser::ParseOptionalBitList(std::vector<unsigned> &Ranges) {
+ if (Lex.getCode() != tgtok::l_brace)
+ return false;
+
+ SMLoc StartLoc = Lex.getLoc();
+ Lex.Lex(); // eat the '{'
+
+ // Parse the range list.
+ Ranges = ParseRangeList();
+ if (Ranges.empty()) return true;
+
+ if (Lex.getCode() != tgtok::r_brace) {
+ TokError("expected '}' at end of bit list");
+ return Error(StartLoc, "to match this '{'");
+ }
+ Lex.Lex(); // eat the '}'.
+ return false;
+}
+
+
+/// ParseType - Parse and return a tblgen type. This returns null on error.
+///
+/// Type ::= STRING // string type
+/// Type ::= BIT // bit type
+/// Type ::= BITS '<' INTVAL '>' // bits<x> type
+/// Type ::= INT // int type
+/// Type ::= LIST '<' Type '>' // list<x> type
+/// Type ::= CODE // code type
+/// Type ::= DAG // dag type
+/// Type ::= ClassID // Record Type
+///
+RecTy *TGParser::ParseType() {
+ switch (Lex.getCode()) {
+ default: TokError("Unknown token when expecting a type"); return 0;
+ 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 RecordRecTy::get(R);
+ return 0;
+ case tgtok::Bits: {
+ if (Lex.Lex() != tgtok::less) { // Eat 'bits'
+ TokError("expected '<' after bits type");
+ return 0;
+ }
+ if (Lex.Lex() != tgtok::IntVal) { // Eat '<'
+ TokError("expected integer in bits<n> type");
+ return 0;
+ }
+ uint64_t Val = Lex.getCurIntVal();
+ if (Lex.Lex() != tgtok::greater) { // Eat count.
+ TokError("expected '>' at end of bits<n> type");
+ return 0;
+ }
+ Lex.Lex(); // Eat '>'
+ return BitsRecTy::get(Val);
+ }
+ case tgtok::List: {
+ if (Lex.Lex() != tgtok::less) { // Eat 'bits'
+ TokError("expected '<' after list type");
+ return 0;
+ }
+ Lex.Lex(); // Eat '<'
+ RecTy *SubType = ParseType();
+ if (SubType == 0) return 0;
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' at end of list<ty> type");
+ return 0;
+ }
+ Lex.Lex(); // Eat '>'
+ return ListRecTy::get(SubType);
+ }
+ }
+}
+
+/// ParseIDValue - Parse an ID as a value and decode what it means.
+///
+/// IDValue ::= ID [def local value]
+/// IDValue ::= ID [def template arg]
+/// IDValue ::= ID [multiclass local value]
+/// IDValue ::= ID [multiclass template argument]
+/// IDValue ::= ID [def name]
+///
+Init *TGParser::ParseIDValue(Record *CurRec) {
+ assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue");
+ std::string Name = Lex.getCurStrVal();
+ SMLoc Loc = Lex.getLoc();
+ Lex.Lex();
+ return ParseIDValue(CurRec, Name, Loc);
+}
+
+/// ParseIDValue - This is just like ParseIDValue above, but it assumes the ID
+/// has already been read.
+Init *TGParser::ParseIDValue(Record *CurRec,
+ const std::string &Name, SMLoc NameLoc) {
+ if (CurRec) {
+ if (const RecordVal *RV = CurRec->getValue(Name))
+ 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 VarInit::get(TemplateArgName, RV->getType());
+ }
+ }
+
+ if (CurMultiClass) {
+ std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
+ if (CurMultiClass->Rec.isTemplateArg(MCName)) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
+ assert(RV && "Template arg doesn't exist??");
+ return VarInit::get(MCName, RV->getType());
+ }
+ }
+
+ if (Record *D = Records.getDef(Name))
+ return DefInit::get(D);
+
+ Error(NameLoc, "Variable not defined: '" + Name + "'");
+ return 0;
+}
+
+/// ParseOperation - Parse an operator. This returns null on error.
+///
+/// Operation ::= XOperator ['<' Type '>'] '(' Args ')'
+///
+Init *TGParser::ParseOperation(Record *CurRec) {
+ switch (Lex.getCode()) {
+ default:
+ TokError("unknown operation");
+ return 0;
+ break;
+ case tgtok::XHead:
+ case tgtok::XTail:
+ case tgtok::XEmpty:
+ case tgtok::XCast: { // Value ::= !unop '(' Value ')'
+ UnOpInit::UnaryOp Code;
+ RecTy *Type = 0;
+
+ switch (Lex.getCode()) {
+ default: assert(0 && "Unhandled code!");
+ case tgtok::XCast:
+ Lex.Lex(); // eat the operation
+ Code = UnOpInit::CAST;
+
+ Type = ParseOperatorType();
+
+ if (Type == 0) {
+ TokError("did not get type for unary operator");
+ return 0;
+ }
+
+ break;
+ case tgtok::XHead:
+ Lex.Lex(); // eat the operation
+ Code = UnOpInit::HEAD;
+ break;
+ case tgtok::XTail:
+ Lex.Lex(); // eat the operation
+ Code = UnOpInit::TAIL;
+ break;
+ case tgtok::XEmpty:
+ Lex.Lex(); // eat the operation
+ Code = UnOpInit::EMPTY;
+ Type = IntRecTy::get();
+ break;
+ }
+ if (Lex.getCode() != tgtok::l_paren) {
+ TokError("expected '(' after unary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the '('
+
+ Init *LHS = ParseValue(CurRec);
+ if (LHS == 0) return 0;
+
+ if (Code == UnOpInit::HEAD
+ || Code == UnOpInit::TAIL
+ || Code == UnOpInit::EMPTY) {
+ ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
+ StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
+ TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
+ if (LHSl == 0 && LHSs == 0 && LHSt == 0) {
+ TokError("expected list or string type argument in unary operator");
+ return 0;
+ }
+ if (LHSt) {
+ ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
+ StringRecTy *SType = dynamic_cast<StringRecTy*>(LHSt->getType());
+ if (LType == 0 && SType == 0) {
+ TokError("expected list or string type argumnet in unary operator");
+ return 0;
+ }
+ }
+
+ if (Code == UnOpInit::HEAD
+ || Code == UnOpInit::TAIL) {
+ if (LHSl == 0 && LHSt == 0) {
+ TokError("expected list type argumnet in unary operator");
+ return 0;
+ }
+
+ if (LHSl && LHSl->getSize() == 0) {
+ TokError("empty list argument in unary operator");
+ return 0;
+ }
+ if (LHSl) {
+ Init *Item = LHSl->getElement(0);
+ TypedInit *Itemt = dynamic_cast<TypedInit*>(Item);
+ if (Itemt == 0) {
+ TokError("untyped list element in unary operator");
+ return 0;
+ }
+ if (Code == UnOpInit::HEAD) {
+ Type = Itemt->getType();
+ } else {
+ Type = ListRecTy::get(Itemt->getType());
+ }
+ } else {
+ assert(LHSt && "expected list type argument in unary operator");
+ ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
+ if (LType == 0) {
+ TokError("expected list type argumnet in unary operator");
+ return 0;
+ }
+ if (Code == UnOpInit::HEAD) {
+ Type = LType->getElementType();
+ } else {
+ Type = LType;
+ }
+ }
+ }
+ }
+
+ if (Lex.getCode() != tgtok::r_paren) {
+ TokError("expected ')' in unary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the ')'
+ return (UnOpInit::get(Code, LHS, Type))->Fold(CurRec, CurMultiClass);
+ }
+
+ case tgtok::XConcat:
+ case tgtok::XSRA:
+ case tgtok::XSRL:
+ case tgtok::XSHL:
+ case tgtok::XEq:
+ case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')'
+ tgtok::TokKind OpTok = Lex.getCode();
+ SMLoc OpLoc = Lex.getLoc();
+ Lex.Lex(); // eat the operation
+
+ BinOpInit::BinaryOp Code;
+ RecTy *Type = 0;
+
+ switch (OpTok) {
+ default: assert(0 && "Unhandled code!");
+ 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 = StringRecTy::get();
+ break;
+ }
+
+ if (Lex.getCode() != tgtok::l_paren) {
+ TokError("expected '(' after binary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the '('
+
+ SmallVector<Init*, 2> InitList;
+
+ InitList.push_back(ParseValue(CurRec));
+ if (InitList.back() == 0) return 0;
+
+ while (Lex.getCode() == tgtok::comma) {
+ Lex.Lex(); // eat the ','
+
+ InitList.push_back(ParseValue(CurRec));
+ if (InitList.back() == 0) return 0;
+ }
+
+ if (Lex.getCode() != tgtok::r_paren) {
+ TokError("expected ')' in operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the ')'
+
+ // We allow multiple operands to associative operators like !strconcat as
+ // shorthand for nesting them.
+ if (Code == BinOpInit::STRCONCAT) {
+ while (InitList.size() > 2) {
+ Init *RHS = InitList.pop_back_val();
+ RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))
+ ->Fold(CurRec, CurMultiClass);
+ InitList.back() = RHS;
+ }
+ }
+
+ if (InitList.size() == 2)
+ return (BinOpInit::get(Code, InitList[0], InitList[1], Type))
+ ->Fold(CurRec, CurMultiClass);
+
+ Error(OpLoc, "expected two operands to operator");
+ return 0;
+ }
+
+ case tgtok::XIf:
+ case tgtok::XForEach:
+ case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
+ TernOpInit::TernaryOp Code;
+ RecTy *Type = 0;
+
+ tgtok::TokKind LexCode = Lex.getCode();
+ Lex.Lex(); // eat the operation
+ switch (LexCode) {
+ default: assert(0 && "Unhandled code!");
+ case tgtok::XIf:
+ Code = TernOpInit::IF;
+ break;
+ case tgtok::XForEach:
+ Code = TernOpInit::FOREACH;
+ break;
+ case tgtok::XSubst:
+ Code = TernOpInit::SUBST;
+ break;
+ }
+ if (Lex.getCode() != tgtok::l_paren) {
+ TokError("expected '(' after ternary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the '('
+
+ Init *LHS = ParseValue(CurRec);
+ if (LHS == 0) return 0;
+
+ if (Lex.getCode() != tgtok::comma) {
+ TokError("expected ',' in ternary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the ','
+
+ Init *MHS = ParseValue(CurRec);
+ if (MHS == 0) return 0;
+
+ if (Lex.getCode() != tgtok::comma) {
+ TokError("expected ',' in ternary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the ','
+
+ Init *RHS = ParseValue(CurRec);
+ if (RHS == 0) return 0;
+
+ if (Lex.getCode() != tgtok::r_paren) {
+ TokError("expected ')' in binary operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the ')'
+
+ switch (LexCode) {
+ default: assert(0 && "Unhandled code!");
+ case tgtok::XIf: {
+ // FIXME: The `!if' operator doesn't handle non-TypedInit well at
+ // all. This can be made much more robust.
+ TypedInit *MHSt = dynamic_cast<TypedInit*>(MHS);
+ TypedInit *RHSt = dynamic_cast<TypedInit*>(RHS);
+
+ RecTy *MHSTy = 0;
+ RecTy *RHSTy = 0;
+
+ if (MHSt == 0 && RHSt == 0) {
+ BitsInit *MHSbits = dynamic_cast<BitsInit*>(MHS);
+ BitsInit *RHSbits = dynamic_cast<BitsInit*>(RHS);
+
+ if (MHSbits && RHSbits &&
+ MHSbits->getNumBits() == RHSbits->getNumBits()) {
+ Type = BitRecTy::get();
+ break;
+ } else {
+ BitInit *MHSbit = dynamic_cast<BitInit*>(MHS);
+ BitInit *RHSbit = dynamic_cast<BitInit*>(RHS);
+
+ if (MHSbit && RHSbit) {
+ Type = BitRecTy::get();
+ break;
+ }
+ }
+ } else if (MHSt != 0 && RHSt != 0) {
+ MHSTy = MHSt->getType();
+ RHSTy = RHSt->getType();
+ }
+
+ if (!MHSTy || !RHSTy) {
+ TokError("could not get type for !if");
+ return 0;
+ }
+
+ if (MHSTy->typeIsConvertibleTo(RHSTy)) {
+ Type = RHSTy;
+ } else if (RHSTy->typeIsConvertibleTo(MHSTy)) {
+ Type = MHSTy;
+ } else {
+ TokError("inconsistent types for !if");
+ return 0;
+ }
+ break;
+ }
+ case tgtok::XForEach: {
+ TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS);
+ if (MHSt == 0) {
+ TokError("could not get type for !foreach");
+ return 0;
+ }
+ Type = MHSt->getType();
+ break;
+ }
+ case tgtok::XSubst: {
+ TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS);
+ if (RHSt == 0) {
+ TokError("could not get type for !subst");
+ return 0;
+ }
+ Type = RHSt->getType();
+ break;
+ }
+ }
+ return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec,
+ CurMultiClass);
+ }
+ }
+ TokError("could not parse operation");
+ return 0;
+}
+
+/// ParseOperatorType - Parse a type for an operator. This returns
+/// null on error.
+///
+/// OperatorType ::= '<' Type '>'
+///
+RecTy *TGParser::ParseOperatorType() {
+ RecTy *Type = 0;
+
+ if (Lex.getCode() != tgtok::less) {
+ TokError("expected type name for operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the <
+
+ Type = ParseType();
+
+ if (Type == 0) {
+ TokError("expected type name for operator");
+ return 0;
+ }
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected type name for operator");
+ return 0;
+ }
+ Lex.Lex(); // eat the >
+
+ return Type;
+}
+
+
+/// ParseSimpleValue - Parse a tblgen value. This returns null on error.
+///
+/// SimpleValue ::= IDValue
+/// SimpleValue ::= INTVAL
+/// SimpleValue ::= STRVAL+
+/// SimpleValue ::= CODEFRAGMENT
+/// SimpleValue ::= '?'
+/// SimpleValue ::= '{' ValueList '}'
+/// SimpleValue ::= ID '<' ValueListNE '>'
+/// SimpleValue ::= '[' ValueList ']'
+/// SimpleValue ::= '(' IDValue DagArgList ')'
+/// SimpleValue ::= CONCATTOK '(' Value ',' Value ')'
+/// SimpleValue ::= SHLTOK '(' Value ',' Value ')'
+/// SimpleValue ::= SRATOK '(' Value ',' Value ')'
+/// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
+/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
+///
+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 = IntInit::get(Lex.getCurIntVal()); Lex.Lex(); break;
+ case tgtok::StrVal: {
+ std::string Val = Lex.getCurStrVal();
+ Lex.Lex();
+
+ // Handle multiple consecutive concatenated strings.
+ while (Lex.getCode() == tgtok::StrVal) {
+ Val += Lex.getCurStrVal();
+ Lex.Lex();
+ }
+
+ R = StringInit::get(Val);
+ break;
+ }
+ case tgtok::CodeFragment:
+ R = CodeInit::get(Lex.getCurStrVal());
+ Lex.Lex();
+ break;
+ case tgtok::question:
+ R = UnsetInit::get();
+ Lex.Lex();
+ break;
+ case tgtok::Id: {
+ SMLoc NameLoc = Lex.getLoc();
+ std::string Name = Lex.getCurStrVal();
+ if (Lex.Lex() != tgtok::less) // consume the Id.
+ return ParseIDValue(CurRec, Name, NameLoc); // Value ::= IDValue
+
+ // Value ::= ID '<' ValueListNE '>'
+ if (Lex.Lex() == tgtok::greater) {
+ TokError("expected non-empty value list");
+ return 0;
+ }
+
+ // This is a CLASS<initvalslist> expression. This is supposed to synthesize
+ // a new anonymous definition, deriving from CLASS<initvalslist> with no
+ // body.
+ Record *Class = Records.getClass(Name);
+ if (!Class) {
+ Error(NameLoc, "Expected a class name, got '" + Name + "'");
+ return 0;
+ }
+
+ std::vector<Init*> ValueList = ParseValueList(CurRec, Class);
+ if (ValueList.empty()) return 0;
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' at end of value list");
+ return 0;
+ }
+ Lex.Lex(); // eat the '>'
+
+ // Create the new record, set it as CurRec temporarily.
+ static unsigned AnonCounter = 0;
+ Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++),
+ NameLoc,
+ Records);
+ SubClassReference SCRef;
+ SCRef.RefLoc = NameLoc;
+ SCRef.Rec = Class;
+ SCRef.TemplateArgs = ValueList;
+ // Add info about the subclass to NewRec.
+ if (AddSubClass(NewRec, SCRef))
+ return 0;
+ NewRec->resolveReferences();
+ Records.addDef(NewRec);
+
+ // The result of the expression is a reference to the new record.
+ return DefInit::get(NewRec);
+ }
+ case tgtok::l_brace: { // Value ::= '{' ValueList '}'
+ SMLoc BraceLoc = Lex.getLoc();
+ Lex.Lex(); // eat the '{'
+ std::vector<Init*> Vals;
+
+ if (Lex.getCode() != tgtok::r_brace) {
+ Vals = ParseValueList(CurRec);
+ if (Vals.empty()) return 0;
+ }
+ if (Lex.getCode() != tgtok::r_brace) {
+ TokError("expected '}' at end of bit list value");
+ return 0;
+ }
+ Lex.Lex(); // eat the '}'
+
+ SmallVector<Init *, 16> NewBits(Vals.size());
+
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ 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;
+ }
+ NewBits[Vals.size()-i-1] = Bit;
+ }
+ return BitsInit::get(NewBits);
+ }
+ case tgtok::l_square: { // Value ::= '[' ValueList ']'
+ Lex.Lex(); // eat the '['
+ std::vector<Init*> Vals;
+
+ RecTy *DeducedEltTy = 0;
+ ListRecTy *GivenListTy = 0;
+
+ if (ItemType != 0) {
+ ListRecTy *ListType = dynamic_cast<ListRecTy*>(ItemType);
+ if (ListType == 0) {
+ std::stringstream s;
+ s << "Type mismatch for list, expected list type, got "
+ << ItemType->getAsString();
+ TokError(s.str());
+ return 0;
+ }
+ GivenListTy = ListType;
+ }
+
+ if (Lex.getCode() != tgtok::r_square) {
+ Vals = ParseValueList(CurRec, 0,
+ GivenListTy ? GivenListTy->getElementType() : 0);
+ if (Vals.empty()) return 0;
+ }
+ if (Lex.getCode() != tgtok::r_square) {
+ TokError("expected ']' at end of list value");
+ return 0;
+ }
+ Lex.Lex(); // eat the ']'
+
+ RecTy *GivenEltTy = 0;
+ if (Lex.getCode() == tgtok::less) {
+ // Optional list element type
+ Lex.Lex(); // eat the '<'
+
+ GivenEltTy = ParseType();
+ if (GivenEltTy == 0) {
+ // Couldn't parse element type
+ return 0;
+ }
+
+ if (Lex.getCode() != tgtok::greater) {
+ TokError("expected '>' at end of list element type");
+ return 0;
+ }
+ Lex.Lex(); // eat the '>'
+ }
+
+ // Check elements
+ RecTy *EltTy = 0;
+ for (std::vector<Init *>::iterator i = Vals.begin(), ie = Vals.end();
+ i != ie;
+ ++i) {
+ TypedInit *TArg = dynamic_cast<TypedInit*>(*i);
+ if (TArg == 0) {
+ TokError("Untyped list element");
+ return 0;
+ }
+ if (EltTy != 0) {
+ EltTy = resolveTypes(EltTy, TArg->getType());
+ if (EltTy == 0) {
+ TokError("Incompatible types in list elements");
+ return 0;
+ }
+ } else {
+ EltTy = TArg->getType();
+ }
+ }
+
+ if (GivenEltTy != 0) {
+ if (EltTy != 0) {
+ // Verify consistency
+ if (!EltTy->typeIsConvertibleTo(GivenEltTy)) {
+ TokError("Incompatible types in list elements");
+ return 0;
+ }
+ }
+ EltTy = GivenEltTy;
+ }
+
+ if (EltTy == 0) {
+ if (ItemType == 0) {
+ TokError("No type for list");
+ return 0;
+ }
+ DeducedEltTy = GivenListTy->getElementType();
+ } else {
+ // Make sure the deduced type is compatible with the given type
+ if (GivenListTy) {
+ if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) {
+ TokError("Element type mismatch for list");
+ return 0;
+ }
+ }
+ DeducedEltTy = EltTy;
+ }
+
+ return ListInit::get(Vals, DeducedEltTy);
+ }
+ case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'
+ Lex.Lex(); // eat the '('
+ if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast) {
+ TokError("expected identifier in dag init");
+ return 0;
+ }
+
+ Init *Operator = ParseValue(CurRec);
+ if (Operator == 0) return 0;
+
+ // If the operator name is present, parse it.
+ std::string OperatorName;
+ if (Lex.getCode() == tgtok::colon) {
+ if (Lex.Lex() != tgtok::VarName) { // eat the ':'
+ TokError("expected variable name in dag operator");
+ return 0;
+ }
+ OperatorName = Lex.getCurStrVal();
+ Lex.Lex(); // eat the VarName.
+ }
+
+ std::vector<std::pair<llvm::Init*, std::string> > DagArgs;
+ if (Lex.getCode() != tgtok::r_paren) {
+ DagArgs = ParseDagArgList(CurRec);
+ if (DagArgs.empty()) return 0;
+ }
+
+ if (Lex.getCode() != tgtok::r_paren) {
+ TokError("expected ')' in dag init");
+ return 0;
+ }
+ Lex.Lex(); // eat the ')'
+
+ return DagInit::get(Operator, OperatorName, DagArgs);
+ }
+
+ case tgtok::XHead:
+ case tgtok::XTail:
+ case tgtok::XEmpty:
+ case tgtok::XCast: // Value ::= !unop '(' Value ')'
+ case tgtok::XConcat:
+ case tgtok::XSRA:
+ case tgtok::XSRL:
+ case tgtok::XSHL:
+ case tgtok::XEq:
+ case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')'
+ case tgtok::XIf:
+ case tgtok::XForEach:
+ case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
+ return ParseOperation(CurRec);
+ }
+ }
+
+ return R;
+}
+
+/// ParseValue - Parse a tblgen value. This returns null on error.
+///
+/// Value ::= SimpleValue ValueSuffix*
+/// ValueSuffix ::= '{' BitList '}'
+/// ValueSuffix ::= '[' BitList ']'
+/// ValueSuffix ::= '.' ID
+///
+Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) {
+ Init *Result = ParseSimpleValue(CurRec, ItemType);
+ if (Result == 0) return 0;
+
+ // Parse the suffixes now if present.
+ while (1) {
+ switch (Lex.getCode()) {
+ default: return Result;
+ case tgtok::l_brace: {
+ SMLoc CurlyLoc = Lex.getLoc();
+ Lex.Lex(); // eat the '{'
+ std::vector<unsigned> Ranges = ParseRangeList();
+ if (Ranges.empty()) return 0;
+
+ // Reverse the bitlist.
+ std::reverse(Ranges.begin(), Ranges.end());
+ Result = Result->convertInitializerBitRange(Ranges);
+ if (Result == 0) {
+ Error(CurlyLoc, "Invalid bit range for value");
+ return 0;
+ }
+
+ // Eat the '}'.
+ if (Lex.getCode() != tgtok::r_brace) {
+ TokError("expected '}' at end of bit range list");
+ return 0;
+ }
+ Lex.Lex();
+ break;
+ }
+ case tgtok::l_square: {
+ SMLoc SquareLoc = Lex.getLoc();
+ Lex.Lex(); // eat the '['
+ std::vector<unsigned> Ranges = ParseRangeList();
+ if (Ranges.empty()) return 0;
+
+ Result = Result->convertInitListSlice(Ranges);
+ if (Result == 0) {
+ Error(SquareLoc, "Invalid range for list slice");
+ return 0;
+ }
+
+ // Eat the ']'.
+ if (Lex.getCode() != tgtok::r_square) {
+ TokError("expected ']' at end of list slice");
+ return 0;
+ }
+ Lex.Lex();
+ break;
+ }
+ case tgtok::period:
+ if (Lex.Lex() != tgtok::Id) { // eat the .
+ TokError("expected field identifier after '.'");
+ return 0;
+ }
+ if (!Result->getFieldType(Lex.getCurStrVal())) {
+ TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +
+ Result->getAsString() + "'");
+ return 0;
+ }
+ Result = FieldInit::get(Result, Lex.getCurStrVal());
+ Lex.Lex(); // eat field name
+ break;
+ }
+ }
+}
+
+/// ParseDagArgList - Parse the argument list for a dag literal expression.
+///
+/// ParseDagArgList ::= Value (':' VARNAME)?
+/// ParseDagArgList ::= ParseDagArgList ',' Value (':' VARNAME)?
+std::vector<std::pair<llvm::Init*, std::string> >
+TGParser::ParseDagArgList(Record *CurRec) {
+ std::vector<std::pair<llvm::Init*, std::string> > Result;
+
+ while (1) {
+ Init *Val = ParseValue(CurRec);
+ if (Val == 0) return std::vector<std::pair<llvm::Init*, std::string> >();
+
+ // If the variable name is present, add it.
+ std::string VarName;
+ if (Lex.getCode() == tgtok::colon) {
+ if (Lex.Lex() != tgtok::VarName) { // eat the ':'
+ TokError("expected variable name in dag literal");
+ return std::vector<std::pair<llvm::Init*, std::string> >();
+ }
+ VarName = Lex.getCurStrVal();
+ Lex.Lex(); // eat the VarName.
+ }
+
+ Result.push_back(std::make_pair(Val, VarName));
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat the ','
+ }
+
+ return Result;
+}
+
+
+/// ParseValueList - Parse a comma separated list of values, returning them as a
+/// vector. Note that this always expects to be able to parse at least one
+/// value. It returns an empty list if this is not possible.
+///
+/// ValueList ::= Value (',' Value)
+///
+std::vector<Init*> TGParser::ParseValueList(Record *CurRec, Record *ArgsRec,
+ RecTy *EltTy) {
+ std::vector<Init*> Result;
+ RecTy *ItemType = EltTy;
+ unsigned int ArgN = 0;
+ if (ArgsRec != 0 && EltTy == 0) {
+ const std::vector<std::string> &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;
+ }
+ Result.push_back(ParseValue(CurRec, ItemType));
+ if (Result.back() == 0) return std::vector<Init*>();
+
+ while (Lex.getCode() == tgtok::comma) {
+ Lex.Lex(); // Eat the comma
+
+ if (ArgsRec != 0 && EltTy == 0) {
+ const std::vector<std::string> &TArgs = ArgsRec->getTemplateArgs();
+ if (ArgN >= TArgs.size()) {
+ TokError("too many template arguments");
+ return std::vector<Init*>();
+ }
+ const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]);
+ assert(RV && "Template argument record not found??");
+ ItemType = RV->getType();
+ ++ArgN;
+ }
+ Result.push_back(ParseValue(CurRec, ItemType));
+ if (Result.back() == 0) return std::vector<Init*>();
+ }
+
+ return Result;
+}
+
+
+/// ParseDeclaration - Read a declaration, returning the name of field ID, or an
+/// empty string on error. This can happen in a number of different context's,
+/// including within a def or in the template args for a def (which which case
+/// CurRec will be non-null) and within the template args for a multiclass (in
+/// which case CurRec will be null, but CurMultiClass will be set). This can
+/// also happen within a def that is within a multiclass, which will set both
+/// CurRec and CurMultiClass.
+///
+/// Declaration ::= FIELD? Type ID ('=' Value)?
+///
+std::string TGParser::ParseDeclaration(Record *CurRec,
+ bool ParsingTemplateArgs) {
+ // Read the field prefix if present.
+ bool HasField = Lex.getCode() == tgtok::Field;
+ if (HasField) Lex.Lex();
+
+ RecTy *Type = ParseType();
+ if (Type == 0) return "";
+
+ if (Lex.getCode() != tgtok::Id) {
+ TokError("Expected identifier in declaration");
+ return "";
+ }
+
+ SMLoc IdLoc = Lex.getLoc();
+ std::string DeclName = Lex.getCurStrVal();
+ Lex.Lex();
+
+ if (ParsingTemplateArgs) {
+ if (CurRec) {
+ DeclName = CurRec->getName() + ":" + DeclName;
+ } else {
+ assert(CurMultiClass);
+ }
+ if (CurMultiClass)
+ DeclName = CurMultiClass->Rec.getName() + "::" + DeclName;
+ }
+
+ // Add the value.
+ if (AddValue(CurRec, IdLoc, RecordVal(DeclName, Type, HasField)))
+ return "";
+
+ // If a value is present, parse it.
+ if (Lex.getCode() == tgtok::equal) {
+ Lex.Lex();
+ SMLoc ValLoc = Lex.getLoc();
+ Init *Val = ParseValue(CurRec, Type);
+ if (Val == 0 ||
+ SetValue(CurRec, ValLoc, DeclName, std::vector<unsigned>(), Val))
+ return "";
+ }
+
+ return DeclName;
+}
+
+/// ParseTemplateArgList - Read a template argument list, which is a non-empty
+/// sequence of template-declarations in <>'s. If CurRec is non-null, these are
+/// template args for a def, which may or may not be in a multiclass. If null,
+/// these are the template args for a multiclass.
+///
+/// TemplateArgList ::= '<' Declaration (',' Declaration)* '>'
+///
+bool TGParser::ParseTemplateArgList(Record *CurRec) {
+ assert(Lex.getCode() == tgtok::less && "Not a template arg list!");
+ Lex.Lex(); // eat the '<'
+
+ Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec;
+
+ // Read the first declaration.
+ std::string TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
+ if (TemplArg.empty())
+ return true;
+
+ TheRecToAddTo->addTemplateArg(TemplArg);
+
+ while (Lex.getCode() == tgtok::comma) {
+ Lex.Lex(); // eat the ','
+
+ // Read the following declarations.
+ TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
+ if (TemplArg.empty())
+ return true;
+ TheRecToAddTo->addTemplateArg(TemplArg);
+ }
+
+ if (Lex.getCode() != tgtok::greater)
+ return TokError("expected '>' at end of template argument list");
+ Lex.Lex(); // eat the '>'.
+ return false;
+}
+
+
+/// ParseBodyItem - Parse a single item at within the body of a def or class.
+///
+/// BodyItem ::= Declaration ';'
+/// BodyItem ::= LET ID OptionalBitList '=' Value ';'
+bool TGParser::ParseBodyItem(Record *CurRec) {
+ if (Lex.getCode() != tgtok::Let) {
+ if (ParseDeclaration(CurRec, false).empty())
+ return true;
+
+ if (Lex.getCode() != tgtok::semi)
+ return TokError("expected ';' after declaration");
+ Lex.Lex();
+ return false;
+ }
+
+ // LET ID OptionalRangeList '=' Value ';'
+ if (Lex.Lex() != tgtok::Id)
+ return TokError("expected field identifier after let");
+
+ SMLoc IdLoc = Lex.getLoc();
+ std::string FieldName = Lex.getCurStrVal();
+ Lex.Lex(); // eat the field name.
+
+ std::vector<unsigned> BitList;
+ if (ParseOptionalBitList(BitList))
+ return true;
+ std::reverse(BitList.begin(), BitList.end());
+
+ if (Lex.getCode() != tgtok::equal)
+ return TokError("expected '=' in let expression");
+ Lex.Lex(); // eat the '='.
+
+ RecordVal *Field = CurRec->getValue(FieldName);
+ if (Field == 0)
+ return TokError("Value '" + FieldName + "' unknown!");
+
+ RecTy *Type = Field->getType();
+
+ Init *Val = ParseValue(CurRec, Type);
+ if (Val == 0) return true;
+
+ if (Lex.getCode() != tgtok::semi)
+ return TokError("expected ';' after let expression");
+ Lex.Lex();
+
+ return SetValue(CurRec, IdLoc, FieldName, BitList, Val);
+}
+
+/// ParseBody - Read the body of a class or def. Return true on error, false on
+/// success.
+///
+/// Body ::= ';'
+/// Body ::= '{' BodyList '}'
+/// BodyList BodyItem*
+///
+bool TGParser::ParseBody(Record *CurRec) {
+ // If this is a null definition, just eat the semi and return.
+ if (Lex.getCode() == tgtok::semi) {
+ Lex.Lex();
+ return false;
+ }
+
+ if (Lex.getCode() != tgtok::l_brace)
+ return TokError("Expected ';' or '{' to start body");
+ // Eat the '{'.
+ Lex.Lex();
+
+ while (Lex.getCode() != tgtok::r_brace)
+ if (ParseBodyItem(CurRec))
+ return true;
+
+ // Eat the '}'.
+ Lex.Lex();
+ return false;
+}
+
+/// ParseObjectBody - Parse the body of a def or class. This consists of an
+/// optional ClassList followed by a Body. CurRec is the current def or class
+/// that is being parsed.
+///
+/// ObjectBody ::= BaseClassList Body
+/// BaseClassList ::= /*empty*/
+/// BaseClassList ::= ':' BaseClassListNE
+/// BaseClassListNE ::= SubClassRef (',' SubClassRef)*
+///
+bool TGParser::ParseObjectBody(Record *CurRec) {
+ // If there is a baseclass list, read it.
+ if (Lex.getCode() == tgtok::colon) {
+ Lex.Lex();
+
+ // Read all of the subclasses.
+ SubClassReference SubClass = ParseSubClassReference(CurRec, false);
+ while (1) {
+ // Check for error.
+ if (SubClass.Rec == 0) return true;
+
+ // Add it.
+ if (AddSubClass(CurRec, SubClass))
+ return true;
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat ','.
+ SubClass = ParseSubClassReference(CurRec, false);
+ }
+ }
+
+ // Process any variables on the let stack.
+ 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 true;
+
+ return ParseBody(CurRec);
+}
+
+/// ParseDef - Parse and return a top level or multiclass def, return the record
+/// corresponding to it. This returns null on error.
+///
+/// DefInst ::= DEF ObjectName ObjectBody
+///
+bool TGParser::ParseDef(MultiClass *CurMultiClass) {
+ SMLoc DefLoc = Lex.getLoc();
+ assert(Lex.getCode() == tgtok::Def && "Unknown tok");
+ Lex.Lex(); // Eat the 'def' token.
+
+ // Parse ObjectName and make a record for it.
+ Record *CurRec = new Record(ParseObjectName(), DefLoc, Records);
+
+ if (!CurMultiClass) {
+ // Top-level def definition.
+
+ // Ensure redefinition doesn't happen.
+ if (Records.getDef(CurRec->getName())) {
+ Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
+ return true;
+ }
+ Records.addDef(CurRec);
+ } else {
+ // Otherwise, a def inside a multiclass, add it to the multiclass.
+ for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); i != e; ++i)
+ if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
+ Error(DefLoc, "def '" + CurRec->getName() +
+ "' already defined in this multiclass!");
+ return true;
+ }
+ CurMultiClass->DefPrototypes.push_back(CurRec);
+ }
+
+ if (ParseObjectBody(CurRec))
+ 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.
+ assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
+
+ if (CurMultiClass) {
+ // Copy the template arguments for the multiclass into the def.
+ const std::vector<std::string> &TArgs =
+ CurMultiClass->Rec.getTemplateArgs();
+
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
+ assert(RV && "Template arg doesn't exist?");
+ CurRec->addValue(*RV);
+ }
+ }
+
+ return false;
+}
+
+/// ParseClass - Parse a tblgen class definition.
+///
+/// ClassInst ::= CLASS ID TemplateArgList? ObjectBody
+///
+bool TGParser::ParseClass() {
+ assert(Lex.getCode() == tgtok::Class && "Unexpected token!");
+ Lex.Lex();
+
+ if (Lex.getCode() != tgtok::Id)
+ return TokError("expected class name after 'class' keyword");
+
+ Record *CurRec = Records.getClass(Lex.getCurStrVal());
+ if (CurRec) {
+ // If the body was previously defined, this is an error.
+ if (!CurRec->getValues().empty() ||
+ !CurRec->getSuperClasses().empty() ||
+ !CurRec->getTemplateArgs().empty())
+ return TokError("Class '" + CurRec->getName() + "' already defined");
+ } else {
+ // If this is the first reference to this class, create and add it.
+ CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc(), Records);
+ Records.addClass(CurRec);
+ }
+ Lex.Lex(); // eat the name.
+
+ // If there are template args, parse them.
+ if (Lex.getCode() == tgtok::less)
+ if (ParseTemplateArgList(CurRec))
+ return true;
+
+ // Finally, parse the object body.
+ return ParseObjectBody(CurRec);
+}
+
+/// ParseLetList - Parse a non-empty list of assignment expressions into a list
+/// of LetRecords.
+///
+/// LetList ::= LetItem (',' LetItem)*
+/// LetItem ::= ID OptionalRangeList '=' Value
+///
+std::vector<LetRecord> TGParser::ParseLetList() {
+ std::vector<LetRecord> Result;
+
+ while (1) {
+ if (Lex.getCode() != tgtok::Id) {
+ TokError("expected identifier in let definition");
+ return std::vector<LetRecord>();
+ }
+ std::string Name = Lex.getCurStrVal();
+ SMLoc NameLoc = Lex.getLoc();
+ Lex.Lex(); // Eat the identifier.
+
+ // Check for an optional RangeList.
+ std::vector<unsigned> Bits;
+ if (ParseOptionalRangeList(Bits))
+ return std::vector<LetRecord>();
+ std::reverse(Bits.begin(), Bits.end());
+
+ if (Lex.getCode() != tgtok::equal) {
+ TokError("expected '=' in let expression");
+ return std::vector<LetRecord>();
+ }
+ Lex.Lex(); // eat the '='.
+
+ Init *Val = ParseValue(0);
+ if (Val == 0) return std::vector<LetRecord>();
+
+ // Now that we have everything, add the record.
+ Result.push_back(LetRecord(Name, Bits, Val, NameLoc));
+
+ if (Lex.getCode() != tgtok::comma)
+ return Result;
+ Lex.Lex(); // eat the comma.
+ }
+}
+
+/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
+/// different related productions. This works inside multiclasses too.
+///
+/// Object ::= LET LetList IN '{' ObjectList '}'
+/// Object ::= LET LetList IN Object
+///
+bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
+ assert(Lex.getCode() == tgtok::Let && "Unexpected token");
+ Lex.Lex();
+
+ // Add this entry to the let stack.
+ std::vector<LetRecord> LetInfo = ParseLetList();
+ if (LetInfo.empty()) return true;
+ LetStack.push_back(LetInfo);
+
+ if (Lex.getCode() != tgtok::In)
+ return TokError("expected 'in' at end of top-level 'let'");
+ Lex.Lex();
+
+ // If this is a scalar let, just handle it now
+ if (Lex.getCode() != tgtok::l_brace) {
+ // LET LetList IN Object
+ if (ParseObject(CurMultiClass))
+ return true;
+ } else { // Object ::= LETCommand '{' ObjectList '}'
+ SMLoc BraceLoc = Lex.getLoc();
+ // Otherwise, this is a group let.
+ Lex.Lex(); // eat the '{'.
+
+ // Parse the object list.
+ if (ParseObjectList(CurMultiClass))
+ return true;
+
+ if (Lex.getCode() != tgtok::r_brace) {
+ TokError("expected '}' at end of top level let command");
+ return Error(BraceLoc, "to match this '{'");
+ }
+ Lex.Lex();
+ }
+
+ // Outside this let scope, this let block is not active.
+ LetStack.pop_back();
+ return false;
+}
+
+/// ParseMultiClass - Parse a multiclass definition.
+///
+/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
+/// ':' BaseMultiClassList '{' MultiClassDef+ '}'
+///
+bool TGParser::ParseMultiClass() {
+ assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
+ Lex.Lex(); // Eat the multiclass token.
+
+ if (Lex.getCode() != tgtok::Id)
+ return TokError("expected identifier after multiclass for name");
+ std::string Name = Lex.getCurStrVal();
+
+ if (MultiClasses.count(Name))
+ return TokError("multiclass '" + Name + "' already defined");
+
+ CurMultiClass = MultiClasses[Name] = new MultiClass(Name,
+ Lex.getLoc(), Records);
+ Lex.Lex(); // Eat the identifier.
+
+ // If there are template args, parse them.
+ if (Lex.getCode() == tgtok::less)
+ if (ParseTemplateArgList(0))
+ return true;
+
+ bool inherits = false;
+
+ // If there are submulticlasses, parse them.
+ if (Lex.getCode() == tgtok::colon) {
+ inherits = true;
+
+ Lex.Lex();
+
+ // Read all of the submulticlasses.
+ SubMultiClassReference SubMultiClass =
+ ParseSubMultiClassReference(CurMultiClass);
+ while (1) {
+ // Check for error.
+ if (SubMultiClass.MC == 0) return true;
+
+ // Add it.
+ if (AddSubMultiClass(CurMultiClass, SubMultiClass))
+ return true;
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat ','.
+ SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
+ }
+ }
+
+ if (Lex.getCode() != tgtok::l_brace) {
+ if (!inherits)
+ return TokError("expected '{' in multiclass definition");
+ else if (Lex.getCode() != tgtok::semi)
+ return TokError("expected ';' in multiclass definition");
+ else
+ Lex.Lex(); // eat the ';'.
+ } else {
+ if (Lex.Lex() == tgtok::r_brace) // eat the '{'.
+ return TokError("multiclass must contain at least one def");
+
+ while (Lex.getCode() != tgtok::r_brace) {
+ switch (Lex.getCode()) {
+ default:
+ return TokError("expected 'let', 'def' or 'defm' in multiclass body");
+ case tgtok::Let:
+ case tgtok::Def:
+ case tgtok::Defm:
+ if (ParseObject(CurMultiClass))
+ return true;
+ break;
+ }
+ }
+ Lex.Lex(); // eat the '}'.
+ }
+
+ CurMultiClass = 0;
+ 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<std::string> &TArgs,
+ std::vector<Init *> &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<unsigned>(),
+ 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<std::string> &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 ';'
+///
+bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
+ assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");
+
+ std::string DefmPrefix;
+ if (Lex.Lex() == tgtok::Id) { // eat the defm.
+ DefmPrefix = Lex.getCurStrVal();
+ Lex.Lex(); // Eat the defm prefix.
+ }
+
+ SMLoc DefmPrefixLoc = Lex.getLoc();
+ if (Lex.getCode() != tgtok::colon)
+ return TokError("expected ':' after defm identifier");
+
+ // Keep track of the new generated record definitions.
+ std::vector<Record*> NewRecDefs;
+
+ // This record also inherits from a regular class (non-multiclass)?
+ bool InheritFromClass = false;
+
+ // eat the colon.
+ Lex.Lex();
+
+ SMLoc SubClassLoc = Lex.getLoc();
+ SubClassReference Ref = ParseSubClassReference(0, true);
+
+ while (1) {
+ if (Ref.Rec == 0) return true;
+
+ // To instantiate a multiclass, we need to first get the multiclass, then
+ // instantiate each def contained in the multiclass with the SubClassRef
+ // template parameters.
+ MultiClass *MC = MultiClasses[Ref.Rec->getName()];
+ assert(MC && "Didn't lookup multiclass correctly?");
+ std::vector<Init*> &TemplateVals = Ref.TemplateArgs;
+
+ // Verify that the correct number of template arguments were specified.
+ const std::vector<std::string> &TArgs = MC->Rec.getTemplateArgs();
+ if (TArgs.size() < TemplateVals.size())
+ return Error(SubClassLoc,
+ "more template args specified than multiclass expects");
+
+ // Loop over all the def's in the multiclass, instantiating each one.
+ for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) {
+ Record *DefProto = MC->DefPrototypes[i];
+
+ Record *CurRec = InstantiateMulticlassDef(*MC, DefProto, DefmPrefix, DefmPrefixLoc);
+
+ if (ResolveMulticlassDefArgs(*MC, CurRec, DefmPrefixLoc, SubClassLoc,
+ TArgs, TemplateVals, true/*Delete args*/))
+ return Error(SubClassLoc, "could not instantiate def");
+
+ 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 ','.
+
+ SubClassLoc = Lex.getLoc();
+
+ // A defm can inherit from regular classes (non-multiclass) as
+ // long as they come in the end of the inheritance list.
+ InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != 0);
+
+ if (InheritFromClass)
+ break;
+
+ Ref = ParseSubClassReference(0, true);
+ }
+
+ if (InheritFromClass) {
+ // Process all the classes to inherit as if they were part of a
+ // regular 'def' and inherit all record values.
+ SubClassReference SubClass = ParseSubClassReference(0, false);
+ while (1) {
+ // Check for error.
+ if (SubClass.Rec == 0) return true;
+
+ // Get the expanded definition prototypes and teach them about
+ // the record values the current class to inherit has
+ for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) {
+ Record *CurRec = NewRecDefs[i];
+
+ // Add it.
+ if (AddSubClass(CurRec, SubClass))
+ return true;
+
+ // Process any variables on the let stack.
+ 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 true;
+ }
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat ','.
+ SubClass = ParseSubClassReference(0, false);
+ }
+ }
+
+ 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)
+ return TokError("expected ';' at end of defm");
+ Lex.Lex();
+
+ return false;
+}
+
+/// ParseObject
+/// Object ::= ClassInst
+/// Object ::= DefInst
+/// Object ::= MultiClassInst
+/// Object ::= DefMInst
+/// Object ::= LETCommand '{' ObjectList '}'
+/// Object ::= LETCommand Object
+bool TGParser::ParseObject(MultiClass *MC) {
+ switch (Lex.getCode()) {
+ default:
+ return TokError("Expected class, def, defm, multiclass or let definition");
+ case tgtok::Let: return ParseTopLevelLet(MC);
+ case tgtok::Def: return ParseDef(MC);
+ case tgtok::Defm: return ParseDefm(MC);
+ case tgtok::Class: return ParseClass();
+ case tgtok::MultiClass: return ParseMultiClass();
+ }
+}
+
+/// ParseObjectList
+/// ObjectList :== Object*
+bool TGParser::ParseObjectList(MultiClass *MC) {
+ while (isObjectStart(Lex.getCode())) {
+ if (ParseObject(MC))
+ return true;
+ }
+ return false;
+}
+
+bool TGParser::ParseFile() {
+ Lex.Lex(); // Prime the lexer.
+ if (ParseObjectList()) return true;
+
+ // If we have unread input at the end of the file, report it.
+ if (Lex.getCode() == tgtok::Eof)
+ return false;
+
+ return TokError("Unexpected input at top level");
+}
+
diff --git a/lib/TableGen/TGParser.h b/lib/TableGen/TGParser.h
new file mode 100644
index 0000000..db8a620
--- /dev/null
+++ b/lib/TableGen/TGParser.h
@@ -0,0 +1,137 @@
+//===- TGParser.h - Parser for TableGen Files -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class represents the Parser for tablegen files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TGPARSER_H
+#define TGPARSER_H
+
+#include "TGLexer.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/SourceMgr.h"
+#include <map>
+
+namespace llvm {
+ class Record;
+ class RecordVal;
+ class RecordKeeper;
+ class RecTy;
+ class Init;
+ struct MultiClass;
+ struct SubClassReference;
+ struct SubMultiClassReference;
+
+ struct LetRecord {
+ std::string Name;
+ std::vector<unsigned> Bits;
+ Init *Value;
+ SMLoc Loc;
+ LetRecord(const std::string &N, const std::vector<unsigned> &B, Init *V,
+ SMLoc L)
+ : Name(N), Bits(B), Value(V), Loc(L) {
+ }
+ };
+
+class TGParser {
+ TGLexer Lex;
+ std::vector<std::vector<LetRecord> > LetStack;
+ std::map<std::string, MultiClass*> MultiClasses;
+
+ /// CurMultiClass - If we are parsing a 'multiclass' definition, this is the
+ /// current value.
+ MultiClass *CurMultiClass;
+
+ // Record tracker
+ RecordKeeper &Records;
+public:
+ TGParser(SourceMgr &SrcMgr, RecordKeeper &records) :
+ Lex(SrcMgr), CurMultiClass(0), Records(records) {}
+
+ /// ParseFile - Main entrypoint for parsing a tblgen file. These parser
+ /// routines return true on error, or false on success.
+ bool ParseFile();
+
+ bool Error(SMLoc L, const Twine &Msg) const {
+ PrintError(L, Msg);
+ return true;
+ }
+ bool TokError(const Twine &Msg) const {
+ return Error(Lex.getLoc(), Msg);
+ }
+ const std::vector<std::string> &getDependencies() const {
+ return Lex.getDependencies();
+ }
+private: // Semantic analysis methods.
+ bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV);
+ bool SetValue(Record *TheRec, SMLoc Loc, const std::string &ValName,
+ const std::vector<unsigned> &BitList, Init *V);
+ bool AddSubClass(Record *Rec, SubClassReference &SubClass);
+ bool AddSubMultiClass(MultiClass *CurMC,
+ SubMultiClassReference &SubMultiClass);
+
+private: // Parser methods.
+ bool ParseObjectList(MultiClass *MC = 0);
+ 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<std::string> &TArgs,
+ std::vector<Init *> &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);
+ std::vector<LetRecord> ParseLetList();
+
+ bool ParseObjectBody(Record *CurRec);
+ bool ParseBody(Record *CurRec);
+ bool ParseBodyItem(Record *CurRec);
+
+ bool ParseTemplateArgList(Record *CurRec);
+ std::string ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
+
+ SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
+ SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMC);
+
+ Init *ParseIDValue(Record *CurRec);
+ Init *ParseIDValue(Record *CurRec, const std::string &Name, SMLoc NameLoc);
+ Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = 0);
+ Init *ParseValue(Record *CurRec, RecTy *ItemType = 0);
+ std::vector<Init*> ParseValueList(Record *CurRec, Record *ArgsRec = 0, RecTy *EltTy = 0);
+ std::vector<std::pair<llvm::Init*, std::string> > ParseDagArgList(Record *);
+ bool ParseOptionalRangeList(std::vector<unsigned> &Ranges);
+ bool ParseOptionalBitList(std::vector<unsigned> &Ranges);
+ std::vector<unsigned> ParseRangeList();
+ bool ParseRangePiece(std::vector<unsigned> &Ranges);
+ RecTy *ParseType();
+ Init *ParseOperation(Record *CurRec);
+ RecTy *ParseOperatorType();
+ std::string ParseObjectName();
+ Record *ParseClassID();
+ MultiClass *ParseMultiClassID();
+ Record *ParseDefmID();
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/lib/TableGen/TableGenBackend.cpp b/lib/TableGen/TableGenBackend.cpp
new file mode 100644
index 0000000..29588db
--- /dev/null
+++ b/lib/TableGen/TableGenBackend.cpp
@@ -0,0 +1,25 @@
+//===- TableGenBackend.cpp - Base class for TableGen Backends ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides useful services for TableGen backends...
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TableGen/TableGenBackend.h"
+#include "llvm/TableGen/Record.h"
+using namespace llvm;
+
+void TableGenBackend::EmitSourceFileHeader(const std::string &Desc,
+ raw_ostream &OS) const {
+ OS << "//===- TableGen'erated file -------------------------------------*-"
+ " C++ -*-===//\n//\n// " << Desc << "\n//\n// Automatically generate"
+ "d file, do not edit!\n//\n//===------------------------------------"
+ "----------------------------------===//\n\n";
+}
+
diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h
index 08dc340..16d0da3 100644
--- a/lib/Target/ARM/ARM.h
+++ b/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/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td
index cf333cc..5c727ad 100644
--- a/lib/Target/ARM/ARM.td
+++ b/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/lib/Target/ARM/ARMAddressingModes.h b/lib/Target/ARM/ARMAddressingModes.h
deleted file mode 100644
index 595708f..0000000
--- a/lib/Target/ARM/ARMAddressingModes.h
+++ /dev/null
@@ -1,595 +0,0 @@
-//===- ARMAddressingModes.h - ARM Addressing Modes --------------*- 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 ARM addressing mode implementation stuff.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TARGET_ARM_ARMADDRESSINGMODES_H
-#define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H
-
-#include "llvm/CodeGen/SelectionDAGNodes.h"
-#include "llvm/Support/MathExtras.h"
-#include <cassert>
-
-namespace llvm {
-
-/// ARM_AM - ARM Addressing Mode Stuff
-namespace ARM_AM {
- enum ShiftOpc {
- no_shift = 0,
- asr,
- lsl,
- lsr,
- ror,
- rrx
- };
-
- enum AddrOpc {
- add = '+', sub = '-'
- };
-
- static inline const char *getAddrOpcStr(AddrOpc Op) {
- return Op == sub ? "-" : "";
- }
-
- static inline const char *getShiftOpcStr(ShiftOpc Op) {
- switch (Op) {
- default: assert(0 && "Unknown shift opc!");
- case ARM_AM::asr: return "asr";
- case ARM_AM::lsl: return "lsl";
- case ARM_AM::lsr: return "lsr";
- case ARM_AM::ror: return "ror";
- case ARM_AM::rrx: return "rrx";
- }
- }
-
- static inline unsigned getShiftOpcEncoding(ShiftOpc Op) {
- switch (Op) {
- default: assert(0 && "Unknown shift opc!");
- case ARM_AM::asr: return 2;
- case ARM_AM::lsl: return 0;
- case ARM_AM::lsr: return 1;
- case ARM_AM::ror: return 3;
- }
- }
-
- static inline ShiftOpc getShiftOpcForNode(SDValue N) {
- switch (N.getOpcode()) {
- default: return ARM_AM::no_shift;
- case ISD::SHL: return ARM_AM::lsl;
- case ISD::SRL: return ARM_AM::lsr;
- case ISD::SRA: return ARM_AM::asr;
- case ISD::ROTR: return ARM_AM::ror;
- //case ISD::ROTL: // Only if imm -> turn into ROTR.
- // Can't handle RRX here, because it would require folding a flag into
- // the addressing mode. :( This causes us to miss certain things.
- //case ARMISD::RRX: return ARM_AM::rrx;
- }
- }
-
- enum AMSubMode {
- bad_am_submode = 0,
- ia,
- ib,
- da,
- db
- };
-
- static inline const char *getAMSubModeStr(AMSubMode Mode) {
- switch (Mode) {
- default: assert(0 && "Unknown addressing sub-mode!");
- case ARM_AM::ia: return "ia";
- case ARM_AM::ib: return "ib";
- case ARM_AM::da: return "da";
- case ARM_AM::db: return "db";
- }
- }
-
- /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits.
- ///
- static inline unsigned rotr32(unsigned Val, unsigned Amt) {
- assert(Amt < 32 && "Invalid rotate amount");
- return (Val >> Amt) | (Val << ((32-Amt)&31));
- }
-
- /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits.
- ///
- static inline unsigned rotl32(unsigned Val, unsigned Amt) {
- assert(Amt < 32 && "Invalid rotate amount");
- return (Val << Amt) | (Val >> ((32-Amt)&31));
- }
-
- //===--------------------------------------------------------------------===//
- // Addressing Mode #1: shift_operand with registers
- //===--------------------------------------------------------------------===//
- //
- // This 'addressing mode' is used for arithmetic instructions. It can
- // represent things like:
- // reg
- // reg [asr|lsl|lsr|ror|rrx] reg
- // reg [asr|lsl|lsr|ror|rrx] imm
- //
- // This is stored three operands [rega, regb, opc]. The first is the base
- // reg, the second is the shift amount (or reg0 if not present or imm). The
- // third operand encodes the shift opcode and the imm if a reg isn't present.
- //
- static inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) {
- return ShOp | (Imm << 3);
- }
- static inline unsigned getSORegOffset(unsigned Op) {
- return Op >> 3;
- }
- static inline ShiftOpc getSORegShOp(unsigned Op) {
- return (ShiftOpc)(Op & 7);
- }
-
- /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return
- /// the 8-bit imm value.
- static inline unsigned getSOImmValImm(unsigned Imm) {
- return Imm & 0xFF;
- }
- /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return
- /// the rotate amount.
- static inline unsigned getSOImmValRot(unsigned Imm) {
- return (Imm >> 8) * 2;
- }
-
- /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand,
- /// computing the rotate amount to use. If this immediate value cannot be
- /// handled with a single shifter-op, determine a good rotate amount that will
- /// take a maximal chunk of bits out of the immediate.
- static inline unsigned getSOImmValRotate(unsigned Imm) {
- // 8-bit (or less) immediates are trivially shifter_operands with a rotate
- // of zero.
- if ((Imm & ~255U) == 0) return 0;
-
- // Use CTZ to compute the rotate amount.
- unsigned TZ = CountTrailingZeros_32(Imm);
-
- // Rotate amount must be even. Something like 0x200 must be rotated 8 bits,
- // not 9.
- unsigned RotAmt = TZ & ~1;
-
- // If we can handle this spread, return it.
- if ((rotr32(Imm, RotAmt) & ~255U) == 0)
- return (32-RotAmt)&31; // HW rotates right, not left.
-
- // For values like 0xF000000F, we should ignore the low 6 bits, then
- // retry the hunt.
- if (Imm & 63U) {
- unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U);
- unsigned RotAmt2 = TZ2 & ~1;
- if ((rotr32(Imm, RotAmt2) & ~255U) == 0)
- return (32-RotAmt2)&31; // HW rotates right, not left.
- }
-
- // Otherwise, we have no way to cover this span of bits with a single
- // shifter_op immediate. Return a chunk of bits that will be useful to
- // handle.
- return (32-RotAmt)&31; // HW rotates right, not left.
- }
-
- /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit
- /// into an shifter_operand immediate operand, return the 12-bit encoding for
- /// it. If not, return -1.
- static inline int getSOImmVal(unsigned Arg) {
- // 8-bit (or less) immediates are trivially shifter_operands with a rotate
- // of zero.
- if ((Arg & ~255U) == 0) return Arg;
-
- unsigned RotAmt = getSOImmValRotate(Arg);
-
- // If this cannot be handled with a single shifter_op, bail out.
- if (rotr32(~255U, RotAmt) & Arg)
- return -1;
-
- // Encode this correctly.
- return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8);
- }
-
- /// isSOImmTwoPartVal - Return true if the specified value can be obtained by
- /// or'ing together two SOImmVal's.
- static inline bool isSOImmTwoPartVal(unsigned V) {
- // If this can be handled with a single shifter_op, bail out.
- V = rotr32(~255U, getSOImmValRotate(V)) & V;
- if (V == 0)
- return false;
-
- // If this can be handled with two shifter_op's, accept.
- V = rotr32(~255U, getSOImmValRotate(V)) & V;
- return V == 0;
- }
-
- /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal,
- /// return the first chunk of it.
- static inline unsigned getSOImmTwoPartFirst(unsigned V) {
- return rotr32(255U, getSOImmValRotate(V)) & V;
- }
-
- /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal,
- /// return the second chunk of it.
- static inline unsigned getSOImmTwoPartSecond(unsigned V) {
- // Mask out the first hunk.
- V = rotr32(~255U, getSOImmValRotate(V)) & V;
-
- // Take what's left.
- assert(V == (rotr32(255U, getSOImmValRotate(V)) & V));
- return V;
- }
-
- /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed
- /// by a left shift. Returns the shift amount to use.
- static inline unsigned getThumbImmValShift(unsigned Imm) {
- // 8-bit (or less) immediates are trivially immediate operand with a shift
- // of zero.
- if ((Imm & ~255U) == 0) return 0;
-
- // Use CTZ to compute the shift amount.
- return CountTrailingZeros_32(Imm);
- }
-
- /// isThumbImmShiftedVal - Return true if the specified value can be obtained
- /// by left shifting a 8-bit immediate.
- static inline bool isThumbImmShiftedVal(unsigned V) {
- // If this can be handled with
- V = (~255U << getThumbImmValShift(V)) & V;
- return V == 0;
- }
-
- /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed
- /// by a left shift. Returns the shift amount to use.
- static inline unsigned getThumbImm16ValShift(unsigned Imm) {
- // 16-bit (or less) immediates are trivially immediate operand with a shift
- // of zero.
- if ((Imm & ~65535U) == 0) return 0;
-
- // Use CTZ to compute the shift amount.
- return CountTrailingZeros_32(Imm);
- }
-
- /// isThumbImm16ShiftedVal - Return true if the specified value can be
- /// obtained by left shifting a 16-bit immediate.
- static inline bool isThumbImm16ShiftedVal(unsigned V) {
- // If this can be handled with
- V = (~65535U << getThumbImm16ValShift(V)) & V;
- return V == 0;
- }
-
- /// getThumbImmNonShiftedVal - If V is a value that satisfies
- /// isThumbImmShiftedVal, return the non-shiftd value.
- static inline unsigned getThumbImmNonShiftedVal(unsigned V) {
- return V >> getThumbImmValShift(V);
- }
-
-
- /// getT2SOImmValSplat - Return the 12-bit encoded representation
- /// if the specified value can be obtained by splatting the low 8 bits
- /// into every other byte or every byte of a 32-bit value. i.e.,
- /// 00000000 00000000 00000000 abcdefgh control = 0
- /// 00000000 abcdefgh 00000000 abcdefgh control = 1
- /// abcdefgh 00000000 abcdefgh 00000000 control = 2
- /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3
- /// Return -1 if none of the above apply.
- /// See ARM Reference Manual A6.3.2.
- static inline int getT2SOImmValSplatVal(unsigned V) {
- unsigned u, Vs, Imm;
- // control = 0
- if ((V & 0xffffff00) == 0)
- return V;
-
- // If the value is zeroes in the first byte, just shift those off
- Vs = ((V & 0xff) == 0) ? V >> 8 : V;
- // Any passing value only has 8 bits of payload, splatted across the word
- Imm = Vs & 0xff;
- // Likewise, any passing values have the payload splatted into the 3rd byte
- u = Imm | (Imm << 16);
-
- // control = 1 or 2
- if (Vs == u)
- return (((Vs == V) ? 1 : 2) << 8) | Imm;
-
- // control = 3
- if (Vs == (u | (u << 8)))
- return (3 << 8) | Imm;
-
- return -1;
- }
-
- /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the
- /// specified value is a rotated 8-bit value. Return -1 if no rotation
- /// encoding is possible.
- /// See ARM Reference Manual A6.3.2.
- static inline int getT2SOImmValRotateVal(unsigned V) {
- unsigned RotAmt = CountLeadingZeros_32(V);
- if (RotAmt >= 24)
- return -1;
-
- // If 'Arg' can be handled with a single shifter_op return the value.
- if ((rotr32(0xff000000U, RotAmt) & V) == V)
- return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7);
-
- return -1;
- }
-
- /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit
- /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit
- /// encoding for it. If not, return -1.
- /// See ARM Reference Manual A6.3.2.
- static inline int getT2SOImmVal(unsigned Arg) {
- // If 'Arg' is an 8-bit splat, then get the encoded value.
- int Splat = getT2SOImmValSplatVal(Arg);
- if (Splat != -1)
- return Splat;
-
- // If 'Arg' can be handled with a single shifter_op return the value.
- int Rot = getT2SOImmValRotateVal(Arg);
- if (Rot != -1)
- return Rot;
-
- return -1;
- }
-
- static inline unsigned getT2SOImmValRotate(unsigned V) {
- if ((V & ~255U) == 0) return 0;
- // Use CTZ to compute the rotate amount.
- unsigned RotAmt = CountTrailingZeros_32(V);
- return (32 - RotAmt) & 31;
- }
-
- static inline bool isT2SOImmTwoPartVal (unsigned Imm) {
- unsigned V = Imm;
- // Passing values can be any combination of splat values and shifter
- // values. If this can be handled with a single shifter or splat, bail
- // out. Those should be handled directly, not with a two-part val.
- if (getT2SOImmValSplatVal(V) != -1)
- return false;
- V = rotr32 (~255U, getT2SOImmValRotate(V)) & V;
- if (V == 0)
- return false;
-
- // If this can be handled as an immediate, accept.
- if (getT2SOImmVal(V) != -1) return true;
-
- // Likewise, try masking out a splat value first.
- V = Imm;
- if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1)
- V &= ~0xff00ff00U;
- else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1)
- V &= ~0x00ff00ffU;
- // If what's left can be handled as an immediate, accept.
- if (getT2SOImmVal(V) != -1) return true;
-
- // Otherwise, do not accept.
- return false;
- }
-
- static inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) {
- assert (isT2SOImmTwoPartVal(Imm) &&
- "Immedate cannot be encoded as two part immediate!");
- // Try a shifter operand as one part
- unsigned V = rotr32 (~255, getT2SOImmValRotate(Imm)) & Imm;
- // If the rest is encodable as an immediate, then return it.
- if (getT2SOImmVal(V) != -1) return V;
-
- // Try masking out a splat value first.
- if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1)
- return Imm & 0xff00ff00U;
-
- // The other splat is all that's left as an option.
- assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1);
- return Imm & 0x00ff00ffU;
- }
-
- static inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) {
- // Mask out the first hunk
- Imm ^= getT2SOImmTwoPartFirst(Imm);
- // Return what's left
- assert (getT2SOImmVal(Imm) != -1 &&
- "Unable to encode second part of T2 two part SO immediate");
- return Imm;
- }
-
-
- //===--------------------------------------------------------------------===//
- // Addressing Mode #2
- //===--------------------------------------------------------------------===//
- //
- // This is used for most simple load/store instructions.
- //
- // addrmode2 := reg +/- reg shop imm
- // addrmode2 := reg +/- imm12
- //
- // The first operand is always a Reg. The second operand is a reg if in
- // reg/reg form, otherwise it's reg#0. The third field encodes the operation
- // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The
- // fourth operand 16-17 encodes the index mode.
- //
- // If this addressing mode is a frame index (before prolog/epilog insertion
- // and code rewriting), this operand will have the form: FI#, reg0, <offs>
- // with no shift amount for the frame offset.
- //
- static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO,
- unsigned IdxMode = 0) {
- assert(Imm12 < (1 << 12) && "Imm too large!");
- bool isSub = Opc == sub;
- return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ;
- }
- static inline unsigned getAM2Offset(unsigned AM2Opc) {
- return AM2Opc & ((1 << 12)-1);
- }
- static inline AddrOpc getAM2Op(unsigned AM2Opc) {
- return ((AM2Opc >> 12) & 1) ? sub : add;
- }
- static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) {
- return (ShiftOpc)((AM2Opc >> 13) & 7);
- }
- static inline unsigned getAM2IdxMode(unsigned AM2Opc) {
- return (AM2Opc >> 16);
- }
-
-
- //===--------------------------------------------------------------------===//
- // Addressing Mode #3
- //===--------------------------------------------------------------------===//
- //
- // This is used for sign-extending loads, and load/store-pair instructions.
- //
- // addrmode3 := reg +/- reg
- // addrmode3 := reg +/- imm8
- //
- // The first operand is always a Reg. The second operand is a reg if in
- // reg/reg form, otherwise it's reg#0. The third field encodes the operation
- // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the
- // index mode.
-
- /// getAM3Opc - This function encodes the addrmode3 opc field.
- static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset,
- unsigned IdxMode = 0) {
- bool isSub = Opc == sub;
- return ((int)isSub << 8) | Offset | (IdxMode << 9);
- }
- static inline unsigned char getAM3Offset(unsigned AM3Opc) {
- return AM3Opc & 0xFF;
- }
- static inline AddrOpc getAM3Op(unsigned AM3Opc) {
- return ((AM3Opc >> 8) & 1) ? sub : add;
- }
- static inline unsigned getAM3IdxMode(unsigned AM3Opc) {
- return (AM3Opc >> 9);
- }
-
- //===--------------------------------------------------------------------===//
- // Addressing Mode #4
- //===--------------------------------------------------------------------===//
- //
- // This is used for load / store multiple instructions.
- //
- // addrmode4 := reg, <mode>
- //
- // The four modes are:
- // IA - Increment after
- // IB - Increment before
- // DA - Decrement after
- // DB - Decrement before
- // For VFP instructions, only the IA and DB modes are valid.
-
- static inline AMSubMode getAM4SubMode(unsigned Mode) {
- return (AMSubMode)(Mode & 0x7);
- }
-
- static inline unsigned getAM4ModeImm(AMSubMode SubMode) {
- return (int)SubMode;
- }
-
- //===--------------------------------------------------------------------===//
- // Addressing Mode #5
- //===--------------------------------------------------------------------===//
- //
- // This is used for coprocessor instructions, such as FP load/stores.
- //
- // addrmode5 := reg +/- imm8*4
- //
- // The first operand is always a Reg. The second operand encodes the
- // operation in bit 8 and the immediate in bits 0-7.
-
- /// getAM5Opc - This function encodes the addrmode5 opc field.
- static inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) {
- bool isSub = Opc == sub;
- return ((int)isSub << 8) | Offset;
- }
- static inline unsigned char getAM5Offset(unsigned AM5Opc) {
- return AM5Opc & 0xFF;
- }
- static inline AddrOpc getAM5Op(unsigned AM5Opc) {
- return ((AM5Opc >> 8) & 1) ? sub : add;
- }
-
- //===--------------------------------------------------------------------===//
- // Addressing Mode #6
- //===--------------------------------------------------------------------===//
- //
- // This is used for NEON load / store instructions.
- //
- // addrmode6 := reg with optional alignment
- //
- // This is stored in two operands [regaddr, align]. The first is the
- // address register. The second operand is the value of the alignment
- // specifier in bytes or zero if no explicit alignment.
- // Valid alignments depend on the specific instruction.
-
- //===--------------------------------------------------------------------===//
- // NEON Modified Immediates
- //===--------------------------------------------------------------------===//
- //
- // Several NEON instructions (e.g., VMOV) take a "modified immediate"
- // vector operand, where a small immediate encoded in the instruction
- // specifies a full NEON vector value. These modified immediates are
- // represented here as encoded integers. The low 8 bits hold the immediate
- // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold
- // the "Cmode" field of the instruction. The interfaces below treat the
- // Op and Cmode values as a single 5-bit value.
-
- static inline unsigned createNEONModImm(unsigned OpCmode, unsigned Val) {
- return (OpCmode << 8) | Val;
- }
- static inline unsigned getNEONModImmOpCmode(unsigned ModImm) {
- return (ModImm >> 8) & 0x1f;
- }
- static inline unsigned getNEONModImmVal(unsigned ModImm) {
- return ModImm & 0xff;
- }
-
- /// decodeNEONModImm - Decode a NEON modified immediate value into the
- /// element value and the element size in bits. (If the element size is
- /// smaller than the vector, it is splatted into all the elements.)
- static inline uint64_t decodeNEONModImm(unsigned ModImm, unsigned &EltBits) {
- unsigned OpCmode = getNEONModImmOpCmode(ModImm);
- unsigned Imm8 = getNEONModImmVal(ModImm);
- uint64_t Val = 0;
-
- if (OpCmode == 0xe) {
- // 8-bit vector elements
- Val = Imm8;
- EltBits = 8;
- } else if ((OpCmode & 0xc) == 0x8) {
- // 16-bit vector elements
- unsigned ByteNum = (OpCmode & 0x6) >> 1;
- Val = Imm8 << (8 * ByteNum);
- EltBits = 16;
- } else if ((OpCmode & 0x8) == 0) {
- // 32-bit vector elements, zero with one byte set
- unsigned ByteNum = (OpCmode & 0x6) >> 1;
- Val = Imm8 << (8 * ByteNum);
- EltBits = 32;
- } else if ((OpCmode & 0xe) == 0xc) {
- // 32-bit vector elements, one byte with low bits set
- unsigned ByteNum = 1 + (OpCmode & 0x1);
- Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum)));
- EltBits = 32;
- } else if (OpCmode == 0x1e) {
- // 64-bit vector elements
- for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) {
- if ((ModImm >> ByteNum) & 1)
- Val |= (uint64_t)0xff << (8 * ByteNum);
- }
- EltBits = 64;
- } else {
- assert(false && "Unsupported NEON immediate");
- }
- return Val;
- }
-
- AMSubMode getLoadStoreMultipleSubMode(int Opcode);
-
-} // end namespace ARM_AM
-} // end namespace llvm
-
-#endif
-
diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp
deleted file mode 100644
index 5e438a9..0000000
--- a/lib/Target/ARM/ARMAsmBackend.cpp
+++ /dev/null
@@ -1,516 +0,0 @@
-//===-- ARMAsmBackend.cpp - ARM Assembler Backend -------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ARM.h"
-#include "ARMAddressingModes.h"
-#include "ARMFixupKinds.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCELFObjectWriter.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCMachObjectWriter.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/Object/MachOFormat.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetAsmBackend.h"
-#include "llvm/Target/TargetRegistry.h"
-using namespace llvm;
-
-namespace {
-class ARMELFObjectWriter : public MCELFObjectTargetWriter {
-public:
- ARMELFObjectWriter(Triple::OSType OSType)
- : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSType, ELF::EM_ARM,
- /*HasRelocationAddend*/ false) {}
-};
-
-class ARMAsmBackend : public TargetAsmBackend {
- bool isThumbMode; // Currently emitting Thumb code.
-public:
- ARMAsmBackend(const Target &T) : TargetAsmBackend(), isThumbMode(false) {}
-
- unsigned getNumFixupKinds() const { return ARM::NumTargetFixupKinds; }
-
- const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
- const static MCFixupKindInfo Infos[ARM::NumTargetFixupKinds] = {
-// This table *must* be in the order that the fixup_* kinds are defined in
-// ARMFixupKinds.h.
-//
-// Name Offset (bits) Size (bits) Flags
-{ "fixup_arm_ldst_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
- MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
-{ "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
- MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
-{ "fixup_thumb_adr_pcrel_10",0, 8, MCFixupKindInfo::FKF_IsPCRel |
- MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
-{ "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
- MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
-{ "fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_arm_thumb_blx", 7, 21, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_arm_thumb_cp", 1, 8, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_arm_thumb_bcc", 0, 8, MCFixupKindInfo::FKF_IsPCRel },
-// movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 - 19.
-{ "fixup_arm_movt_hi16", 0, 20, 0 },
-{ "fixup_arm_movw_lo16", 0, 20, 0 },
-{ "fixup_t2_movt_hi16", 0, 20, 0 },
-{ "fixup_t2_movw_lo16", 0, 20, 0 },
-{ "fixup_arm_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_arm_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_t2_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_t2_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
- };
-
- if (Kind < FirstTargetFixupKind)
- return TargetAsmBackend::getFixupKindInfo(Kind);
-
- assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
- "Invalid kind!");
- return Infos[Kind - FirstTargetFixupKind];
- }
-
- bool MayNeedRelaxation(const MCInst &Inst) const;
-
- void RelaxInstruction(const MCInst &Inst, MCInst &Res) const;
-
- bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const;
-
- void HandleAssemblerFlag(MCAssemblerFlag Flag) {
- switch (Flag) {
- default: break;
- case MCAF_Code16:
- setIsThumb(true);
- break;
- case MCAF_Code32:
- setIsThumb(false);
- break;
- }
- }
-
- unsigned getPointerSize() const { return 4; }
- bool isThumb() const { return isThumbMode; }
- void setIsThumb(bool it) { isThumbMode = it; }
-};
-} // end anonymous namespace
-
-bool ARMAsmBackend::MayNeedRelaxation(const MCInst &Inst) const {
- // FIXME: Thumb targets, different move constant targets..
- return false;
-}
-
-void ARMAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
- assert(0 && "ARMAsmBackend::RelaxInstruction() unimplemented");
- return;
-}
-
-bool ARMAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
- if (isThumb()) {
- // FIXME: 0xbf00 is the ARMv7 value. For v6 and before, we'll need to
- // use 0x46c0 (which is a 'mov r8, r8' insn).
- uint64_t NumNops = Count / 2;
- for (uint64_t i = 0; i != NumNops; ++i)
- OW->Write16(0xbf00);
- if (Count & 1)
- OW->Write8(0);
- return true;
- }
- // ARM mode
- uint64_t NumNops = Count / 4;
- for (uint64_t i = 0; i != NumNops; ++i)
- OW->Write32(0xe1a00000);
- switch (Count % 4) {
- default: break; // No leftover bytes to write
- case 1: OW->Write8(0); break;
- case 2: OW->Write16(0); break;
- case 3: OW->Write16(0); OW->Write8(0xa0); break;
- }
-
- return true;
-}
-
-static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown fixup kind!");
- case FK_Data_1:
- case FK_Data_2:
- case FK_Data_4:
- return Value;
- case ARM::fixup_arm_movt_hi16:
- Value >>= 16;
- // Fallthrough
- case ARM::fixup_arm_movw_lo16:
- case ARM::fixup_arm_movt_hi16_pcrel:
- case ARM::fixup_arm_movw_lo16_pcrel: {
- unsigned Hi4 = (Value & 0xF000) >> 12;
- unsigned Lo12 = Value & 0x0FFF;
- assert ((((int64_t)Value) >= -0x8000) && (((int64_t)Value) <= 0x7fff) &&
- "Out of range pc-relative fixup value!");
- // inst{19-16} = Hi4;
- // inst{11-0} = Lo12;
- Value = (Hi4 << 16) | (Lo12);
- return Value;
- }
- case ARM::fixup_t2_movt_hi16:
- Value >>= 16;
- // Fallthrough
- case ARM::fixup_t2_movw_lo16:
- case ARM::fixup_t2_movt_hi16_pcrel: //FIXME: Shouldn't this be shifted like
- // the other hi16 fixup?
- case ARM::fixup_t2_movw_lo16_pcrel: {
- unsigned Hi4 = (Value & 0xF000) >> 12;
- unsigned i = (Value & 0x800) >> 11;
- unsigned Mid3 = (Value & 0x700) >> 8;
- unsigned Lo8 = Value & 0x0FF;
- // inst{19-16} = Hi4;
- // inst{26} = i;
- // inst{14-12} = Mid3;
- // inst{7-0} = Lo8;
- // The value comes in as the whole thing, not just the portion required
- // for this fixup, so we need to mask off the bits not handled by this
- // portion (lo vs. hi).
- Value &= 0xffff;
- Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8);
- uint64_t swapped = (Value & 0xFFFF0000) >> 16;
- swapped |= (Value & 0x0000FFFF) << 16;
- return swapped;
- }
- case ARM::fixup_arm_ldst_pcrel_12:
- // ARM PC-relative values are offset by 8.
- Value -= 4;
- // FALLTHROUGH
- case ARM::fixup_t2_ldst_pcrel_12: {
- // Offset by 4, adjusted by two due to the half-word ordering of thumb.
- Value -= 4;
- bool isAdd = true;
- if ((int64_t)Value < 0) {
- Value = -Value;
- isAdd = false;
- }
- assert ((Value < 4096) && "Out of range pc-relative fixup value!");
- Value |= isAdd << 23;
-
- // Same addressing mode as fixup_arm_pcrel_10,
- // but with 16-bit halfwords swapped.
- if (Kind == ARM::fixup_t2_ldst_pcrel_12) {
- uint64_t swapped = (Value & 0xFFFF0000) >> 16;
- swapped |= (Value & 0x0000FFFF) << 16;
- return swapped;
- }
-
- return Value;
- }
- case ARM::fixup_thumb_adr_pcrel_10:
- return ((Value - 4) >> 2) & 0xff;
- case ARM::fixup_arm_adr_pcrel_12: {
- // ARM PC-relative values are offset by 8.
- Value -= 8;
- unsigned opc = 4; // bits {24-21}. Default to add: 0b0100
- if ((int64_t)Value < 0) {
- Value = -Value;
- opc = 2; // 0b0010
- }
- assert(ARM_AM::getSOImmVal(Value) != -1 &&
- "Out of range pc-relative fixup value!");
- // Encode the immediate and shift the opcode into place.
- return ARM_AM::getSOImmVal(Value) | (opc << 21);
- }
-
- case ARM::fixup_t2_adr_pcrel_12: {
- Value -= 4;
- unsigned opc = 0;
- if ((int64_t)Value < 0) {
- Value = -Value;
- opc = 5;
- }
-
- uint32_t out = (opc << 21);
- out |= (Value & 0x800) << 15;
- out |= (Value & 0x700) << 4;
- out |= (Value & 0x0FF);
-
- uint64_t swapped = (out & 0xFFFF0000) >> 16;
- swapped |= (out & 0x0000FFFF) << 16;
- return swapped;
- }
-
- case ARM::fixup_arm_condbranch:
- case ARM::fixup_arm_uncondbranch:
- // These values don't encode the low two bits since they're always zero.
- // Offset by 8 just as above.
- return 0xffffff & ((Value - 8) >> 2);
- case ARM::fixup_t2_uncondbranch: {
- Value = Value - 4;
- Value >>= 1; // Low bit is not encoded.
-
- uint32_t out = 0;
- bool I = Value & 0x800000;
- bool J1 = Value & 0x400000;
- bool J2 = Value & 0x200000;
- J1 ^= I;
- J2 ^= I;
-
- out |= I << 26; // S bit
- out |= !J1 << 13; // J1 bit
- out |= !J2 << 11; // J2 bit
- out |= (Value & 0x1FF800) << 5; // imm6 field
- out |= (Value & 0x0007FF); // imm11 field
-
- uint64_t swapped = (out & 0xFFFF0000) >> 16;
- swapped |= (out & 0x0000FFFF) << 16;
- return swapped;
- }
- case ARM::fixup_t2_condbranch: {
- Value = Value - 4;
- Value >>= 1; // Low bit is not encoded.
-
- uint64_t out = 0;
- out |= (Value & 0x80000) << 7; // S bit
- out |= (Value & 0x40000) >> 7; // J2 bit
- out |= (Value & 0x20000) >> 4; // J1 bit
- out |= (Value & 0x1F800) << 5; // imm6 field
- out |= (Value & 0x007FF); // imm11 field
-
- uint32_t swapped = (out & 0xFFFF0000) >> 16;
- swapped |= (out & 0x0000FFFF) << 16;
- return swapped;
- }
- case ARM::fixup_arm_thumb_bl: {
- // The value doesn't encode the low bit (always zero) and is offset by
- // four. The value is encoded into disjoint bit positions in the destination
- // opcode. x = unchanged, I = immediate value bit, S = sign extension bit
- //
- // BL: xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII
- //
- // Note that the halfwords are stored high first, low second; so we need
- // to transpose the fixup value here to map properly.
- unsigned isNeg = (int64_t(Value - 4) < 0) ? 1 : 0;
- uint32_t Binary = 0;
- Value = 0x3fffff & ((Value - 4) >> 1);
- Binary = (Value & 0x7ff) << 16; // Low imm11 value.
- Binary |= (Value & 0x1ffc00) >> 11; // High imm10 value.
- Binary |= isNeg << 10; // Sign bit.
- return Binary;
- }
- case ARM::fixup_arm_thumb_blx: {
- // The value doesn't encode the low two bits (always zero) and is offset by
- // four (see fixup_arm_thumb_cp). The value is encoded into disjoint bit
- // positions in the destination opcode. x = unchanged, I = immediate value
- // bit, S = sign extension bit, 0 = zero.
- //
- // BLX: xxxxxSIIIIIIIIII xxxxxIIIIIIIIII0
- //
- // Note that the halfwords are stored high first, low second; so we need
- // to transpose the fixup value here to map properly.
- unsigned isNeg = (int64_t(Value-4) < 0) ? 1 : 0;
- uint32_t Binary = 0;
- Value = 0xfffff & ((Value - 2) >> 2);
- Binary = (Value & 0x3ff) << 17; // Low imm10L value.
- Binary |= (Value & 0xffc00) >> 10; // High imm10H value.
- Binary |= isNeg << 10; // Sign bit.
- return Binary;
- }
- case ARM::fixup_arm_thumb_cp:
- // Offset by 4, and don't encode the low two bits. Two bytes of that
- // 'off by 4' is implicitly handled by the half-word ordering of the
- // Thumb encoding, so we only need to adjust by 2 here.
- return ((Value - 2) >> 2) & 0xff;
- case ARM::fixup_arm_thumb_cb: {
- // Offset by 4 and don't encode the lower bit, which is always 0.
- uint32_t Binary = (Value - 4) >> 1;
- return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3);
- }
- case ARM::fixup_arm_thumb_br:
- // Offset by 4 and don't encode the lower bit, which is always 0.
- return ((Value - 4) >> 1) & 0x7ff;
- case ARM::fixup_arm_thumb_bcc:
- // Offset by 4 and don't encode the lower bit, which is always 0.
- return ((Value - 4) >> 1) & 0xff;
- case ARM::fixup_arm_pcrel_10:
- Value = Value - 4; // ARM fixups offset by an additional word and don't
- // need to adjust for the half-word ordering.
- // Fall through.
- case ARM::fixup_t2_pcrel_10: {
- // Offset by 4, adjusted by two due to the half-word ordering of thumb.
- Value = Value - 4;
- bool isAdd = true;
- if ((int64_t)Value < 0) {
- Value = -Value;
- isAdd = false;
- }
- // These values don't encode the low two bits since they're always zero.
- Value >>= 2;
- assert ((Value < 256) && "Out of range pc-relative fixup value!");
- Value |= isAdd << 23;
-
- // Same addressing mode as fixup_arm_pcrel_10,
- // but with 16-bit halfwords swapped.
- if (Kind == ARM::fixup_t2_pcrel_10) {
- uint32_t swapped = (Value & 0xFFFF0000) >> 16;
- swapped |= (Value & 0x0000FFFF) << 16;
- return swapped;
- }
-
- return Value;
- }
- }
-}
-
-namespace {
-
-// FIXME: This should be in a separate file.
-// ELF is an ELF of course...
-class ELFARMAsmBackend : public ARMAsmBackend {
-public:
- Triple::OSType OSType;
- ELFARMAsmBackend(const Target &T, Triple::OSType _OSType)
- : ARMAsmBackend(T), OSType(_OSType) { }
-
- void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
- uint64_t Value) const;
-
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- return createELFObjectWriter(new ARMELFObjectWriter(OSType), OS,
- /*IsLittleEndian*/ true);
- }
-};
-
-// FIXME: Raise this to share code between Darwin and ELF.
-void ELFARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data,
- unsigned DataSize, uint64_t Value) const {
- unsigned NumBytes = 4; // FIXME: 2 for Thumb
- Value = adjustFixupValue(Fixup.getKind(), Value);
- if (!Value) return; // Doesn't change encoding.
-
- unsigned Offset = Fixup.getOffset();
-
- // For each byte of the fragment that the fixup touches, mask in the bits from
- // the fixup value. The Value has been "split up" into the appropriate
- // bitfields above.
- for (unsigned i = 0; i != NumBytes; ++i)
- Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
-}
-
-// FIXME: This should be in a separate file.
-class DarwinARMAsmBackend : public ARMAsmBackend {
-public:
- const object::mach::CPUSubtypeARM Subtype;
- DarwinARMAsmBackend(const Target &T, object::mach::CPUSubtypeARM st)
- : ARMAsmBackend(T), Subtype(st) { }
-
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- return createARMMachObjectWriter(OS, /*Is64Bit=*/false,
- object::mach::CTM_ARM,
- Subtype);
- }
-
- void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
- uint64_t Value) const;
-
- virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
- return false;
- }
-};
-
-/// getFixupKindNumBytes - The number of bytes the fixup may change.
-static unsigned getFixupKindNumBytes(unsigned Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown fixup kind!");
-
- case FK_Data_1:
- case ARM::fixup_arm_thumb_bcc:
- case ARM::fixup_arm_thumb_cp:
- case ARM::fixup_thumb_adr_pcrel_10:
- return 1;
-
- case FK_Data_2:
- case ARM::fixup_arm_thumb_br:
- case ARM::fixup_arm_thumb_cb:
- return 2;
-
- case ARM::fixup_arm_ldst_pcrel_12:
- case ARM::fixup_arm_pcrel_10:
- case ARM::fixup_arm_adr_pcrel_12:
- case ARM::fixup_arm_condbranch:
- case ARM::fixup_arm_uncondbranch:
- return 3;
-
- case FK_Data_4:
- case ARM::fixup_t2_ldst_pcrel_12:
- case ARM::fixup_t2_condbranch:
- case ARM::fixup_t2_uncondbranch:
- case ARM::fixup_t2_pcrel_10:
- case ARM::fixup_t2_adr_pcrel_12:
- case ARM::fixup_arm_thumb_bl:
- case ARM::fixup_arm_thumb_blx:
- case ARM::fixup_arm_movt_hi16:
- case ARM::fixup_arm_movw_lo16:
- case ARM::fixup_arm_movt_hi16_pcrel:
- case ARM::fixup_arm_movw_lo16_pcrel:
- case ARM::fixup_t2_movt_hi16:
- case ARM::fixup_t2_movw_lo16:
- case ARM::fixup_t2_movt_hi16_pcrel:
- case ARM::fixup_t2_movw_lo16_pcrel:
- return 4;
- }
-}
-
-void DarwinARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data,
- unsigned DataSize, uint64_t Value) const {
- unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
- Value = adjustFixupValue(Fixup.getKind(), Value);
- if (!Value) return; // Doesn't change encoding.
-
- unsigned Offset = Fixup.getOffset();
- assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!");
-
- // For each byte of the fragment that the fixup touches, mask in the
- // bits from the fixup value.
- for (unsigned i = 0; i != NumBytes; ++i)
- Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
-}
-
-} // end anonymous namespace
-
-TargetAsmBackend *llvm::createARMAsmBackend(const Target &T,
- const std::string &TT) {
- Triple TheTriple(TT);
-
- if (TheTriple.isOSDarwin()) {
- if (TheTriple.getArchName() == "armv4t" ||
- TheTriple.getArchName() == "thumbv4t")
- return new DarwinARMAsmBackend(T, object::mach::CSARM_V4T);
- else if (TheTriple.getArchName() == "armv5e" ||
- TheTriple.getArchName() == "thumbv5e")
- return new DarwinARMAsmBackend(T, object::mach::CSARM_V5TEJ);
- else if (TheTriple.getArchName() == "armv6" ||
- TheTriple.getArchName() == "thumbv6")
- return new DarwinARMAsmBackend(T, object::mach::CSARM_V6);
- return new DarwinARMAsmBackend(T, object::mach::CSARM_V7);
- }
-
- if (TheTriple.isOSWindows())
- assert(0 && "Windows not supported on ARM");
-
- return new ELFARMAsmBackend(T, Triple(TT).getOS());
-}
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp
index dbc3ee4..ea3319f 100644
--- a/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/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 <cctype>
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<AttributeItemType, 64> 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<Contents.size(); ++i) {
+ AttributeItemType item = Contents[i];
+ Streamer.EmitULEB128IntValue(item.Tag, 0);
+ switch (item.Type) {
+ case AttributeItemType::NumericAttribute:
+ Streamer.EmitULEB128IntValue(item.IntValue, 0);
+ break;
+ case AttributeItemType::TextAttribute:
+ Streamer.EmitBytes(UppercaseString(item.StringValue), 0);
+ Streamer.EmitIntValue(0, 1); // '\0'
+ break;
+ default:
+ assert(0 && "Invalid attribute type");
+ }
+ }
Contents.clear();
}
@@ -184,7 +240,7 @@ void ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
// S registers are described as bit-pieces of a register
// S[2x] = DW_OP_regx(256 + (x>>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<ARMConstantPoolConstant>(ACPV)->getBlockAddress();
+ MCSym = GetBlockAddressSymbol(BA);
} else if (ACPV->isGlobalValue()) {
- const GlobalValue *GV = ACPV->getGV();
+ const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV();
MCSym = GetARMGVSymbol(GV);
+ } else if (ACPV->isMachineBasicBlock()) {
+ const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB();
+ MCSym = MBB->getSymbol();
} else {
assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
- MCSym = GetExternalSymbolSymbol(ACPV->getSymbol());
+ const char *Sym = cast<ARMConstantPoolSymbol>(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<bool> 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<ARMAsmPrinter> X(TheARMTarget);
RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget);
-
- TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter);
- TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter);
}
diff --git a/lib/Target/ARM/ARMBaseInfo.h b/lib/Target/ARM/ARMBaseInfo.h
deleted file mode 100644
index 458f7dd..0000000
--- a/lib/Target/ARM/ARMBaseInfo.h
+++ /dev/null
@@ -1,294 +0,0 @@
-//===-- ARMBaseInfo.h - Top level definitions for ARM -------- --*- 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 small standalone helper functions and enum definitions for
-// the ARM target useful for the compiler back-end and the MC libraries.
-// As such, it deliberately does not include references to LLVM core
-// code gen types, passes, etc..
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ARMBASEINFO_H
-#define ARMBASEINFO_H
-
-#include "MCTargetDesc/ARMMCTargetDesc.h"
-#include "llvm/Support/ErrorHandling.h"
-
-// Note that the following auto-generated files only defined enum types, and
-// so are safe to include here.
-
-namespace llvm {
-
-// Enums corresponding to ARM condition codes
-namespace ARMCC {
- // The CondCodes constants map directly to the 4-bit encoding of the
- // condition field for predicated instructions.
- enum CondCodes { // Meaning (integer) Meaning (floating-point)
- EQ, // Equal Equal
- NE, // Not equal Not equal, or unordered
- HS, // Carry set >, ==, or unordered
- LO, // Carry clear Less than
- MI, // Minus, negative Less than
- PL, // Plus, positive or zero >, ==, or unordered
- VS, // Overflow Unordered
- VC, // No overflow Not unordered
- HI, // Unsigned higher Greater than, or unordered
- LS, // Unsigned lower or same Less than or equal
- GE, // Greater than or equal Greater than or equal
- LT, // Less than Less than, or unordered
- GT, // Greater than Greater than
- LE, // Less than or equal <, ==, or unordered
- AL // Always (unconditional) Always (unconditional)
- };
-
- inline static CondCodes getOppositeCondition(CondCodes CC) {
- switch (CC) {
- default: llvm_unreachable("Unknown condition code");
- case EQ: return NE;
- case NE: return EQ;
- case HS: return LO;
- case LO: return HS;
- case MI: return PL;
- case PL: return MI;
- case VS: return VC;
- case VC: return VS;
- case HI: return LS;
- case LS: return HI;
- case GE: return LT;
- case LT: return GE;
- case GT: return LE;
- case LE: return GT;
- }
- }
-} // namespace ARMCC
-
-inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) {
- switch (CC) {
- default: llvm_unreachable("Unknown condition code");
- case ARMCC::EQ: return "eq";
- case ARMCC::NE: return "ne";
- case ARMCC::HS: return "hs";
- case ARMCC::LO: return "lo";
- case ARMCC::MI: return "mi";
- case ARMCC::PL: return "pl";
- case ARMCC::VS: return "vs";
- case ARMCC::VC: return "vc";
- case ARMCC::HI: return "hi";
- case ARMCC::LS: return "ls";
- case ARMCC::GE: return "ge";
- case ARMCC::LT: return "lt";
- case ARMCC::GT: return "gt";
- case ARMCC::LE: return "le";
- case ARMCC::AL: return "al";
- }
-}
-
-namespace ARM_PROC {
- enum IMod {
- IE = 2,
- ID = 3
- };
-
- enum IFlags {
- F = 1,
- I = 2,
- A = 4
- };
-
- inline static const char *IFlagsToString(unsigned val) {
- switch (val) {
- default: llvm_unreachable("Unknown iflags operand");
- case F: return "f";
- case I: return "i";
- case A: return "a";
- }
- }
-
- inline static const char *IModToString(unsigned val) {
- switch (val) {
- default: llvm_unreachable("Unknown imod operand");
- case IE: return "ie";
- case ID: return "id";
- }
- }
-}
-
-namespace ARM_MB {
- // The Memory Barrier Option constants map directly to the 4-bit encoding of
- // the option field for memory barrier operations.
- enum MemBOpt {
- SY = 15,
- ST = 14,
- ISH = 11,
- ISHST = 10,
- NSH = 7,
- NSHST = 6,
- OSH = 3,
- OSHST = 2
- };
-
- inline static const char *MemBOptToString(unsigned val) {
- switch (val) {
- default: llvm_unreachable("Unknown memory operation");
- case SY: return "sy";
- case ST: return "st";
- case ISH: return "ish";
- case ISHST: return "ishst";
- case NSH: return "nsh";
- case NSHST: return "nshst";
- case OSH: return "osh";
- case OSHST: return "oshst";
- }
- }
-} // namespace ARM_MB
-
-/// getARMRegisterNumbering - Given the enum value for some register, e.g.
-/// ARM::LR, return the number that it corresponds to (e.g. 14).
-inline static unsigned getARMRegisterNumbering(unsigned Reg) {
- using namespace ARM;
- switch (Reg) {
- default:
- llvm_unreachable("Unknown ARM register!");
- case R0: case S0: case D0: case Q0: return 0;
- case R1: case S1: case D1: case Q1: return 1;
- case R2: case S2: case D2: case Q2: return 2;
- case R3: case S3: case D3: case Q3: return 3;
- case R4: case S4: case D4: case Q4: return 4;
- case R5: case S5: case D5: case Q5: return 5;
- case R6: case S6: case D6: case Q6: return 6;
- case R7: case S7: case D7: case Q7: return 7;
- case R8: case S8: case D8: case Q8: return 8;
- case R9: case S9: case D9: case Q9: return 9;
- case R10: case S10: case D10: case Q10: return 10;
- case R11: case S11: case D11: case Q11: return 11;
- case R12: case S12: case D12: case Q12: return 12;
- case SP: case S13: case D13: case Q13: return 13;
- case LR: case S14: case D14: case Q14: return 14;
- case PC: case S15: case D15: case Q15: return 15;
-
- case S16: case D16: return 16;
- case S17: case D17: return 17;
- case S18: case D18: return 18;
- case S19: case D19: return 19;
- case S20: case D20: return 20;
- case S21: case D21: return 21;
- case S22: case D22: return 22;
- case S23: case D23: return 23;
- case S24: case D24: return 24;
- case S25: case D25: return 25;
- case S26: case D26: return 26;
- case S27: case D27: return 27;
- case S28: case D28: return 28;
- case S29: case D29: return 29;
- case S30: case D30: return 30;
- case S31: case D31: return 31;
- }
-}
-
-namespace ARMII {
-
- /// ARM Index Modes
- enum IndexMode {
- IndexModeNone = 0,
- IndexModePre = 1,
- IndexModePost = 2,
- IndexModeUpd = 3
- };
-
- /// ARM Addressing Modes
- enum AddrMode {
- AddrModeNone = 0,
- AddrMode1 = 1,
- AddrMode2 = 2,
- AddrMode3 = 3,
- AddrMode4 = 4,
- AddrMode5 = 5,
- AddrMode6 = 6,
- AddrModeT1_1 = 7,
- AddrModeT1_2 = 8,
- AddrModeT1_4 = 9,
- AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data
- AddrModeT2_i12 = 11,
- AddrModeT2_i8 = 12,
- AddrModeT2_so = 13,
- AddrModeT2_pc = 14, // +/- i12 for pc relative data
- AddrModeT2_i8s4 = 15, // i8 * 4
- AddrMode_i12 = 16
- };
-
- inline static const char *AddrModeToString(AddrMode addrmode) {
- switch (addrmode) {
- default: llvm_unreachable("Unknown memory operation");
- case AddrModeNone: return "AddrModeNone";
- case AddrMode1: return "AddrMode1";
- case AddrMode2: return "AddrMode2";
- case AddrMode3: return "AddrMode3";
- case AddrMode4: return "AddrMode4";
- case AddrMode5: return "AddrMode5";
- case AddrMode6: return "AddrMode6";
- case AddrModeT1_1: return "AddrModeT1_1";
- case AddrModeT1_2: return "AddrModeT1_2";
- case AddrModeT1_4: return "AddrModeT1_4";
- case AddrModeT1_s: return "AddrModeT1_s";
- case AddrModeT2_i12: return "AddrModeT2_i12";
- case AddrModeT2_i8: return "AddrModeT2_i8";
- case AddrModeT2_so: return "AddrModeT2_so";
- case AddrModeT2_pc: return "AddrModeT2_pc";
- case AddrModeT2_i8s4: return "AddrModeT2_i8s4";
- case AddrMode_i12: return "AddrMode_i12";
- }
- }
-
- /// Target Operand Flag enum.
- enum TOF {
- //===------------------------------------------------------------------===//
- // ARM Specific MachineOperand flags.
-
- MO_NO_FLAG,
-
- /// MO_LO16 - On a symbol operand, this represents a relocation containing
- /// lower 16 bit of the address. Used only via movw instruction.
- MO_LO16,
-
- /// MO_HI16 - On a symbol operand, this represents a relocation containing
- /// higher 16 bit of the address. Used only via movt instruction.
- MO_HI16,
-
- /// MO_LO16_NONLAZY - On a symbol operand "FOO", this represents a
- /// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol,
- /// i.e. "FOO$non_lazy_ptr".
- /// Used only via movw instruction.
- MO_LO16_NONLAZY,
-
- /// MO_HI16_NONLAZY - On a symbol operand "FOO", this represents a
- /// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol,
- /// i.e. "FOO$non_lazy_ptr". Used only via movt instruction.
- MO_HI16_NONLAZY,
-
- /// MO_LO16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
- /// relocation containing lower 16 bit of the PC relative address of the
- /// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
- /// Used only via movw instruction.
- MO_LO16_NONLAZY_PIC,
-
- /// MO_HI16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
- /// relocation containing lower 16 bit of the PC relative address of the
- /// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
- /// Used only via movt instruction.
- MO_HI16_NONLAZY_PIC,
-
- /// MO_PLT - On a symbol operand, this represents an ELF PLT reference on a
- /// call operand.
- MO_PLT
- };
-} // end namespace ARMII
-
-} // end namespace llvm;
-
-#endif
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp
index 649bd7d..408edfc 100644
--- a/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/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<bool>
EnableARM3Addr("enable-arm-3-addr-conv", cl::Hidden,
cl::desc("Enable ARM 2-addr to 3-addr conv"));
+static cl::opt<bool>
+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 <imp-def> 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<ARMConstantPoolConstant>(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<ARMConstantPoolSymbol>(ACPV)->getSymbol(), PCLabelId, 4);
else if (ACPV->isBlockAddress())
- NewCPV = new ARMConstantPoolValue(ACPV->getBlockAddress(), PCLabelId,
- ARMCP::CPBlockAddress, 4);
+ NewCPV = ARMConstantPoolConstant::
+ Create(cast<ARMConstantPoolConstant>(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<ARMConstantPoolMBB>(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<uint16_t, uint16_t>
+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<<ExeVFP) | (1<<ExeNEON));
+
+ // No other instructions can be swizzled, so just determine their domain.
+ unsigned Domain = MI->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/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h
index 507e897..0f9f321 100644
--- a/lib/Target/ARM/ARMBaseInstrInfo.h
+++ b/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<uint16_t, uint16_t>
+ 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/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index ba42295..7c42342 100644
--- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/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<unsigned>(GPREven1);
+ return makeArrayRef(GPREven1);
else
- return ArrayRef<unsigned>(GPREven4);
+ return makeArrayRef(GPREven4);
} else if (FramePtr == ARM::R7) {
if (!STI.isR9Reserved())
- return ArrayRef<unsigned>(GPREven2);
+ return makeArrayRef(GPREven2);
else
- return ArrayRef<unsigned>(GPREven5);
+ return makeArrayRef(GPREven5);
} else { // FramePtr == ARM::R11
if (!STI.isR9Reserved())
- return ArrayRef<unsigned>(GPREven3);
+ return makeArrayRef(GPREven3);
else
- return ArrayRef<unsigned>(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<unsigned>(GPROdd1);
+ return makeArrayRef(GPROdd1);
else
- return ArrayRef<unsigned>(GPROdd4);
+ return makeArrayRef(GPROdd4);
} else if (FramePtr == ARM::R7) {
if (!STI.isR9Reserved())
- return ArrayRef<unsigned>(GPROdd2);
+ return makeArrayRef(GPROdd2);
else
- return ArrayRef<unsigned>(GPROdd5);
+ return makeArrayRef(GPROdd5);
} else { // FramePtr == ARM::R11
if (!STI.isR9Reserved())
- return ArrayRef<unsigned>(GPROdd3);
+ return makeArrayRef(GPROdd3);
else
- return ArrayRef<unsigned>(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/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h
index b4b4059..fee17ff 100644
--- a/lib/Target/ARM/ARMBaseRegisterInfo.h
+++ b/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/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index d6fca62..4148d4a 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/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<ARMConstantPoolConstant>(ACPV)->getGV();
if (GV) {
Reloc::Model RelocM = TM.getRelocationModel();
emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry,
isa<Function>(GV),
Subtarget->GVIsIndirectSymbol(GV, RelocM),
(intptr_t)ACPV);
- } else {
- emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute);
+ } else {
+ const char *Sym = cast<ARMConstantPoolSymbol>(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/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp
index f45ebdc..3e3a413 100644
--- a/lib/Target/ARM/ARMConstantIslandPass.cpp
+++ b/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/lib/Target/ARM/ARMConstantPoolValue.cpp b/lib/Target/ARM/ARMConstantPoolValue.cpp
index 165a1d8..aadfd47 100644
--- a/lib/Target/ARM/ARMConstantPoolValue.cpp
+++ b/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 <cstdlib>
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<GlobalValue>(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<BlockAddress>(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<MachineConstantPoolEntry> 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<GlobalValue>(CVal);
+}
+
+const BlockAddress *ARMConstantPoolConstant::getBlockAddress() const {
+ return dyn_cast_or_null<BlockAddress>(CVal);
+}
+
+int ARMConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
+ unsigned Alignment) {
+ unsigned AlignMask = Alignment - 1;
+ const std::vector<MachineConstantPoolEntry> 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<ARMConstantPoolConstant>(CPV);
+ if (!APC) continue;
+ if (APC->CVal == CVal && equals(APC))
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+bool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) {
+ const ARMConstantPoolConstant *ACPC = dyn_cast<ARMConstantPoolConstant>(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<MachineConstantPoolEntry> 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<ARMConstantPoolSymbol>(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<ARMConstantPoolSymbol>(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<MachineConstantPoolEntry> 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<ARMConstantPoolMBB>(CPV);
+ if (!APMBB) continue;
+
+ if (APMBB->MBB == MBB && equals(APMBB))
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+bool ARMConstantPoolMBB::hasSameValue(ARMConstantPoolValue *ACPV) {
+ const ARMConstantPoolMBB *ACPMBB = dyn_cast<ARMConstantPoolMBB>(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/lib/Target/ARM/ARMConstantPoolValue.h b/lib/Target/ARM/ARMConstantPoolValue.h
index d008811..0d0def3 100644
--- a/lib/Target/ARM/ARMConstantPoolValue.h
+++ b/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/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index 94b72fd..7872cb9 100644
--- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/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<bool>
+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/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp
index f469d7e..9bc7ef2 100644
--- a/lib/Target/ARM/ARMFastISel.cpp
+++ b/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<PointerType>(Obj->getType()))
+ if (PointerType *Ty = dyn_cast<PointerType>(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<StructType>(*GTI)) {
+ if (StructType *STy = dyn_cast<StructType>(*GTI)) {
const StructLayout *SL = TD.getStructLayout(STy);
unsigned Idx = cast<ConstantInt>(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<LoadInst>(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<StoreInst>(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<CmpInst>(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<CmpInst>(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<CCValAssign, 16> 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<PointerType>(CS.getCalledValue()->getType());
- const FunctionType *FTy = cast<FunctionType>(PT->getElementType());
+ PointerType *PT = cast<PointerType>(CS.getCalledValue()->getType());
+ FunctionType *FTy = cast<FunctionType>(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/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp
index 381b404..2d1de6f 100644
--- a/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/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 <rd>, sp, #<imm8>
+ // Use add <rd>, sp, #<imm8>
// ldr <rd>, [sp, #<imm8>]
// 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<ARMFunctionInfo>();
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/lib/Target/ARM/ARMGlobalMerge.cpp b/lib/Target/ARM/ARMGlobalMerge.cpp
index 8d77b2d..5f863ea 100644
--- a/lib/Target/ARM/ARMGlobalMerge.cpp
+++ b/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<PointerType>(GV1->getType())->getElementType();
- const Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType();
+ Type *Ty1 = cast<PointerType>(GV1->getType())->getElementType();
+ Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType();
return (TD->getTypeAllocSize(Ty1) < TD->getTypeAllocSize(Ty2));
}
@@ -123,7 +123,7 @@ bool ARMGlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &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<GlobalVariable*> &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/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index 2c9481b..5ee009c 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/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<bool>
+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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<LoadSDNode>(Op)->getAddressingMode()
+ : cast<StoreSDNode>(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<LoadSDNode>(Op)->getAddressingMode()
+ : cast<StoreSDNode>(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<ConstantSDNode>(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<SDValue, 6> 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<MemSDNode>(Node)->getMemOperand();
+ SDNode *ResNode = CurDAG->getMachineNode(Opc, Node->getDebugLoc(),
+ MVT::i32, MVT::i32, MVT::Other,
+ Ops.data() ,Ops.size());
+ cast<MachineSDNode>(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<ConstantSDNode>(N)->getZExtValue();
bool UseCP = true;
@@ -2269,8 +2451,9 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
int FI = cast<FrameIndexSDNode>(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/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index cf8c5ba..e44e356 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/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<ARMFunctionInfo>();
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<SDValue, SDValue> 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<AtomicSDNode>(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<SDValue>& Results,
+ SelectionDAG &DAG, unsigned NewOp) {
+ DebugLoc dl = Node->getDebugLoc();
+ assert (Node->getValueType(0) == MVT::i64 &&
+ "Only know how to expand i64 atomics");
+
+ SmallVector<SDValue, 6> 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<MemSDNode>(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<def> operand. e.g. ADCS (...) -> ADC (... CPSR<def>).
-//
-// FIXME: Somewhere we should assert that CPSR<def> 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
+ // <binopa> r0, r2, incr
+ // <binopb> 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<const ARMBaseInstrInfo*>(TII);
+ MachineFunction &MF = *MI->getParent()->getParent();
+ ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
+ 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<ARMFunctionInfo>();
+ 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<ARMFunctionInfo>();
+ 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<unsigned, SmallVector<MachineBasicBlock*, 2> > 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<unsigned> &CallSiteIdxs = MMI.getCallSiteLandingPad(Sym);
+ for (SmallVectorImpl<unsigned>::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<MachineBasicBlock*> LPadList;
+ SmallPtrSet<MachineBasicBlock*, 64> InvokeBBs;
+ LPadList.reserve(CallSiteNumToLPad.size());
+ for (unsigned I = 1; I <= MaxCSNum; ++I) {
+ SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[I];
+ for (SmallVectorImpl<MachineBasicBlock*>::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<MachineBasicBlock*>::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<const ARMBaseInstrInfo*>(TII);
+ const ARMBaseRegisterInfo &RI = AII->getRegisterInfo();
+ const unsigned *SavedRegs = RI.getCalleeSavedRegs(MF);
+ for (SmallPtrSet<MachineBasicBlock*, 64>::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<unsigned, bool> 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<imp-def>) -> ADC (... opt:CPSR<def>).
+
+ // Rename pseudo opcodes.
+ unsigned NewOpc = convertAddSubFlagsOpcode(MI->getOpcode());
+ if (NewOpc) {
+ const ARMBaseInstrInfo *TII =
+ static_cast<const ARMBaseInstrInfo*>(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<ConstantSDNode>(ARMcc)->getZExtValue();
+ ARMCC::CondCodes CC =
+ (ARMCC::CondCodes)cast<ConstantSDNode>(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<IntegerType>(CI->getType());
+ IntegerType *Ty = dyn_cast<IntegerType>(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/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h
index 980fb40..5da9b27 100644
--- a/lib/Target/ARM/ARMISelLowering.h
+++ b/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/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td
index 3ccf22f..7cbc911 100644
--- a/lib/Target/ARM/ARMInstrFormats.td
+++ b/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<i32> {
let PrintMethod = "printCPSIMod";
}
+def ProcIFlagsOperand : AsmOperandClass {
+ let Name = "ProcIFlags";
+ let ParserMethod = "parseProcIFlagsOperand";
+}
def iflags_op : Operand<i32> {
let PrintMethod = "printCPSIFlag";
let ParserMatchClass = ProcIFlagsOperand;
@@ -170,17 +147,21 @@ def iflags_op : Operand<i32> {
// ARM Predicate operand. Default to 14 = always (AL). Second part is CC
// register whose default is 0 (no register).
-def pred : PredicateOperand<OtherVT, (ops i32imm, CCR),
+def CondCodeOperand : AsmOperandClass { let Name = "CondCode"; }
+def pred : PredicateOperand<OtherVT, (ops i32imm, i32imm),
(ops (i32 14), (i32 zero_reg))> {
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<OtherVT, (ops CCR), (ops (i32 zero_reg))> {
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<OtherVT, (ops CCR), (ops (i32 CPSR))> {
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<i32> {
let PrintMethod = "printSetendOperand";
+ let ParserMatchClass = SetEndAsmOperand;
}
+def MSRMaskOperand : AsmOperandClass {
+ let Name = "MSRMask";
+ let ParserMethod = "parseMSRMaskOperand";
+}
def msr_mask : Operand<i32> {
let PrintMethod = "printMSRMaskOperand";
+ let DecoderMethod = "DecodeMSRMask";
let ParserMatchClass = MSRMaskOperand;
}
@@ -211,21 +203,40 @@ def msr_mask : Operand<i32> {
// 64 64 - <imm> is encoded in imm6<5:0>
def shr_imm8 : Operand<i32> {
let EncoderMethod = "getShiftRight8Imm";
+ let DecoderMethod = "DecodeShiftRight8Imm";
}
def shr_imm16 : Operand<i32> {
let EncoderMethod = "getShiftRight16Imm";
+ let DecoderMethod = "DecodeShiftRight16Imm";
}
def shr_imm32 : Operand<i32> {
let EncoderMethod = "getShiftRight32Imm";
+ let DecoderMethod = "DecodeShiftRight32Imm";
}
def shr_imm64 : Operand<i32> {
let EncoderMethod = "getShiftRight64Imm";
+ let DecoderMethod = "DecodeShiftRight64Imm";
}
//===----------------------------------------------------------------------===//
+// ARM Assembler alias templates.
+//
+class ARMInstAlias<string Asm, dag Result, bit Emit = 0b1>
+ : InstAlias<Asm, Result, Emit>, Requires<[IsARM]>;
+class tInstAlias<string Asm, dag Result, bit Emit = 0b1>
+ : InstAlias<Asm, Result, Emit>, Requires<[IsThumb]>;
+class t2InstAlias<string Asm, dag Result, bit Emit = 0b1>
+ : InstAlias<Asm, Result, Emit>, Requires<[IsThumb2]>;
+class VFP2InstAlias<string Asm, dag Result, bit Emit = 0b1>
+ : InstAlias<Asm, Result, Emit>, Requires<[HasVFP2]>;
+class VFP3InstAlias<string Asm, dag Result, bit Emit = 0b1>
+ : InstAlias<Asm, Result, Emit>, Requires<[HasVFP3]>;
+
+//===----------------------------------------------------------------------===//
// ARM Instruction templates.
//
+
class InstTemplate<AddrMode am, int sz, IndexMode im,
Format f, Domain d, string cstr, InstrItinClass itin>
: Instruction {
@@ -240,17 +251,22 @@ class InstTemplate<AddrMode am, int sz, IndexMode im,
Domain D = d;
bit isUnaryDataProc = 0;
bit canXformTo16Bit = 0;
+ // The instruction is a 16-bit flag setting Thumb instruction. Used
+ // by the parser to determine whether to require the 'S' suffix on the
+ // mnemonic (when not in an IT block) or preclude it (when in an IT block).
+ bit thumbArithFlagSetting = 0;
// If this is a pseudo instruction, mark it isCodeGenOnly.
let isCodeGenOnly = !eq(!cast<string>(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<AddrMode am, int sz, IndexMode im,
Format f, Domain d, string cstr, InstrItinClass itin>
- : InstTemplate<am, sz, im, f, d, cstr, itin>, Encoding;
+ : InstTemplate<am, sz, im, f, d, cstr, itin>, 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<AddrMode am, int sz, IndexMode im,
Format f, Domain d, string cstr, InstrItinClass itin>
- : InstTemplate<am, sz, im, f, d, cstr, itin>;
+ : InstTemplate<am, sz, im, f, d, cstr, itin> {
+ let DecoderNamespace = "Thumb";
+}
class PseudoInst<dag oops, dag iops, InstrItinClass itin, list<dag> pattern>
: InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo,
@@ -426,11 +446,11 @@ class AIldrex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
: I<oops, iops, AddrModeNone, 4, IndexModeNone, LdStExFrm, itin,
opc, asm, "", pattern> {
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<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
let Inst{3-0} = Rt;
}
class AIswp<bit b, dag oops, dag iops, string opc, list<dag> pattern>
- : AI<oops, iops, MiscFrm, NoItinerary, opc, "\t$Rt, $Rt2, [$Rn]", pattern> {
+ : AI<oops, iops, MiscFrm, NoItinerary, opc, "\t$Rt, $Rt2, $addr", pattern> {
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<bit isLd, bit isByte, bit isPre, dag oops, dag iops,
let Inst{20} = isLd; // L bit
let Inst{15-12} = Rt;
}
-class AI2stridx<bit isByte, bit isPre, dag oops, dag iops,
+class AI2stridx_reg<bit isByte, bit isPre, dag oops, dag iops,
+ IndexMode im, Format f, InstrItinClass itin, string opc,
+ string asm, string cstr, list<dag> 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<bit isByte, bit isPre, dag oops, dag iops,
IndexMode im, Format f, InstrItinClass itin, string opc,
string asm, string cstr, list<dag> 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<bit isByte, bit isPre, dag oops, dag iops,
@@ -568,9 +607,11 @@ class AI3ld<bits<4> 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<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
+class AI3ldstidx<bits<4> op, bit op20, bit isPre, dag oops, dag iops,
IndexMode im, Format f, InstrItinClass itin, string opc,
string asm, string cstr, list<dag> pattern>
: I<oops, iops, AddrMode3, 4, im, f, itin,
@@ -586,48 +627,24 @@ class AI3ldstidx<bits<4> 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<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
+class AI3ldstidxT<bits<4> op, bit isLoad, dag oops, dag iops,
IndexMode im, Format f, InstrItinClass itin, string opc,
string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, 4, im, f, itin,
- opc, asm, cstr, pattern> {
+ : I<oops, iops, AddrMode3, 4, im, f, itin, opc, asm, cstr, pattern> {
// {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<bits<4> op, bit isByte, bit isPre, dag oops, dag iops,
- IndexMode im, Format f, InstrItinClass itin, string opc,
- string asm, string cstr, list<dag> 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<bits<4> 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<dag oops, dag iops, Format f, InstrItinClass itin,
- string opc, string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, 4, IndexModePre, f, itin,
- opc, asm, cstr, pattern> {
- 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<dag oops, dag iops, Format f, InstrItinClass itin,
- string opc, string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, 4, IndexModePre, f, itin,
- opc, asm, cstr, pattern> {
- 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<dag oops, dag iops, Format f, InstrItinClass itin,
- string opc, string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, 4, IndexModePost, f, itin,
- opc, asm, cstr,pattern> {
- // {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<dag oops, dag iops, Format f, InstrItinClass itin,
- string opc, string asm, string cstr, list<dag> pattern>
- : I<oops, iops, AddrMode3, 4, IndexModePost, f, itin,
- opc, asm, cstr, pattern> {
- 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<bits<8> 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<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 32; }]>{
+ let PrintMethod = "printPKHLSLShiftImm";
+ let ParserMatchClass = PKHLSLAsmOperand;
+}
+def PKHASRAsmOperand : AsmOperandClass {
+ let Name = "PKHASRImm";
+ let ParserMethod = "parsePKHASRImm";
+}
+def pkh_asr_amt: Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 32; }]>{
+ let PrintMethod = "printPKHASRShiftImm";
+ let ParserMatchClass = PKHASRAsmOperand;
+}
+
class APKHI<bits<8> opcod, bit tb, dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
: I<oops, iops, AddrModeNone, 4, IndexModeNone, ArithMiscFrm, itin,
@@ -850,11 +816,11 @@ class APKHI<bits<8> 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<dag oops, dag iops, AddrMode am, int sz,
let InOperandList = !con(iops, (ins pred:$p));
let AsmString = !strconcat(opc, "${s}${p}", asm);
let Pattern = pattern;
+ let thumbArithFlagSetting = 1;
list<Predicate> Predicates = [IsThumb, IsThumb1Only];
+ let DecoderNamespace = "ThumbSBit";
}
class T1sI<dag oops, dag iops, InstrItinClass itin,
@@ -1071,6 +1039,7 @@ class Thumb2I<dag oops, dag iops, AddrMode am, int sz,
let AsmString = !strconcat(opc, "${p}", asm);
let Pattern = pattern;
list<Predicate> 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<dag oops, dag iops, AddrMode am, int sz,
let AsmString = !strconcat(opc, "${s}${p}", asm);
let Pattern = pattern;
list<Predicate> Predicates = [IsThumb2];
+ let DecoderNamespace = "Thumb2";
}
// Special cases
@@ -1103,6 +1073,7 @@ class Thumb2XI<dag oops, dag iops, AddrMode am, int sz,
let AsmString = asm;
let Pattern = pattern;
list<Predicate> Predicates = [IsThumb2];
+ let DecoderNamespace = "Thumb2";
}
class ThumbXI<dag oops, dag iops, AddrMode am, int sz,
@@ -1114,6 +1085,7 @@ class ThumbXI<dag oops, dag iops, AddrMode am, int sz,
let AsmString = asm;
let Pattern = pattern;
list<Predicate> Predicates = [IsThumb, IsThumb1Only];
+ let DecoderNamespace = "Thumb";
}
class T2I<dag oops, dag iops, InstrItinClass itin,
@@ -1132,8 +1104,8 @@ class T2Ipc<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
: Thumb2I<oops, iops, AddrModeT2_pc, 4, itin, opc, asm, "", pattern>;
class T2Ii8s4<bit P, bit W, bit isLoad, dag oops, dag iops, InstrItinClass itin,
- string opc, string asm, list<dag> pattern>
- : Thumb2I<oops, iops, AddrModeT2_i8s4, 4, itin, opc, asm, "",
+ string opc, string asm, string cstr, list<dag> pattern>
+ : Thumb2I<oops, iops, AddrModeT2_i8s4, 4, itin, opc, asm, cstr,
pattern> {
bits<4> Rt;
bits<4> Rt2;
@@ -1149,6 +1121,26 @@ class T2Ii8s4<bit P, bit W, bit isLoad, dag oops, dag iops, InstrItinClass itin,
let Inst{11-8} = Rt2{3-0};
let Inst{7-0} = addr{7-0};
}
+class T2Ii8s4post<bit P, bit W, bit isLoad, dag oops, dag iops,
+ InstrItinClass itin, string opc, string asm, string cstr,
+ list<dag> pattern>
+ : Thumb2I<oops, iops, AddrModeT2_i8s4, 4, itin, opc, asm, cstr,
+ pattern> {
+ 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<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
@@ -1172,8 +1164,8 @@ class T2XIt<dag oops, dag iops, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
: Thumb2XI<oops, iops, AddrModeNone, 4, itin, asm, cstr, pattern>;
-// T2Iidxldst - Thumb2 indexed load / store instructions.
-class T2Iidxldst<bit signed, bits<2> opcod, bit load, bit pre,
+// T2Ipreldst - Thumb2 pre-indexed load / store instructions.
+class T2Ipreldst<bit signed, bits<2> opcod, bit load, bit pre,
dag oops, dag iops,
AddrMode am, IndexMode im, InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
@@ -1183,25 +1175,60 @@ class T2Iidxldst<bit signed, bits<2> opcod, bit load, bit pre,
let AsmString = !strconcat(opc, "${p}", asm);
let Pattern = pattern;
list<Predicate> 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<bit signed, bits<2> opcod, bit load, bit pre,
+ dag oops, dag iops,
+ AddrMode am, IndexMode im, InstrItinClass itin,
+ string opc, string asm, string cstr, list<dag> pattern>
+ : InstARM<am, 4, im, ThumbFrm, GenericDomain, cstr, itin> {
+ let OutOperandList = oops;
+ let InOperandList = !con(iops, (ins pred:$p));
+ let AsmString = !strconcat(opc, "${p}", asm);
+ let Pattern = pattern;
+ list<Predicate> 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<dag oops, dag iops, AddrMode am, int sz,
let AsmString = !strconcat(opc, "${p}", asm);
let Pattern = pattern;
let PostEncoderMethod = "VFPThumb2PostEncoder";
+ let DecoderNamespace = "VFP";
list<Predicate> Predicates = [HasVFP2];
}
@@ -1257,6 +1285,7 @@ class VFPXI<dag oops, dag iops, AddrMode am, int sz,
let AsmString = asm;
let Pattern = pattern;
let PostEncoderMethod = "VFPThumb2PostEncoder";
+ let DecoderNamespace = "VFP";
list<Predicate> Predicates = [HasVFP2];
}
@@ -1574,6 +1603,7 @@ class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
let Pattern = pattern;
list<Predicate> Predicates = [HasNEON];
+ let DecoderNamespace = "NEON";
}
// Same as NeonI except it does not have a "data type" specifier.
@@ -1586,6 +1616,7 @@ class NeonXI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
let AsmString = !strconcat(opc, "${p}", "\t", asm);
let Pattern = pattern;
list<Predicate> Predicates = [HasNEON];
+ let DecoderNamespace = "NEON";
}
class NLdSt<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4,
@@ -1600,6 +1631,7 @@ class NLdSt<bit op23, bits<2> 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<dag oops, dag iops, Format f, InstrItinClass itin,
pattern> {
let Inst{31-25} = 0b1111001;
let PostEncoderMethod = "NEONThumb2DataIPostEncoder";
+ let DecoderNamespace = "NEONData";
}
class NDataXI<dag oops, dag iops, Format f, InstrItinClass itin,
@@ -1651,6 +1684,7 @@ class NDataXI<dag oops, dag iops, Format f, InstrItinClass itin,
cstr, pattern> {
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<bit op23, bits<3> 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<bits<8> opcod1, bits<4> opcod2, bits<2> opcod3,
list<Predicate> Predicates = [HasNEON];
let PostEncoderMethod = "NEONThumb2DupPostEncoder";
+ let DecoderNamespace = "NEONDup";
bits<5> V;
bits<4> R;
@@ -1915,7 +1951,6 @@ class NVDupLane<bits<4> 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/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp
index adcbf18..48da03f 100644
--- a/lib/Target/ARM/ARMInstrInfo.cpp
+++ b/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/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index a42dd1a..2cf0f09 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/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<i32>, ImmLeaf<i32, [{
let ParserMatchClass = Imm0_65535AsmOperand;
}
+class BinOpWithFlagFrag<dag res> :
+ PatFrag<(ops node:$LHS, node:$RHS, node:$FLAG), res>;
class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
class UnOpFrag <dag res> : 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<OtherVT> {
let EncoderMethod = "getBranchTargetOpValue";
let OperandType = "OPERAND_PCREL";
+ let DecoderMethod = "DecodeT2BROperand";
}
// FIXME: get rid of this one?
@@ -345,39 +357,35 @@ def bl_target : Operand<i32> {
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<i32> {
+ // 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<i32> {
let EncoderMethod = "getRegisterListOpValue";
let ParserMatchClass = RegListAsmOperand;
let PrintMethod = "printRegisterList";
+ let DecoderMethod = "DecodeRegListOperand";
}
+def DPRRegListAsmOperand : AsmOperandClass { let Name = "DPRRegList"; }
def dpr_reglist : Operand<i32> {
let EncoderMethod = "getRegisterListOpValue";
let ParserMatchClass = DPRRegListAsmOperand;
let PrintMethod = "printRegisterList";
+ let DecoderMethod = "DecodeDPRRegListOperand";
}
+def SPRRegListAsmOperand : AsmOperandClass { let Name = "SPRRegList"; }
def spr_reglist : Operand<i32> {
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<i32> {
def neon_vcvt_imm32 : Operand<i32> {
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<i32>, ImmLeaf<i32, [{
- int32_t v = (int32_t)Imm;
- return v == 8 || v == 16 || v == 24; }]> {
- let EncoderMethod = "getRotImmOpValue";
+def rot_imm_XFORM: SDNodeXForm<imm, [{
+ switch (N->getZExtValue()){
+ 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<i32>, 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<i32> {
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<i32>, // reg reg imm
+ ComplexPattern<i32, 3, "SelectRegShifterOperand",
+ [shl, srl, sra, rotr]> {
+ 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<i32>, // reg reg imm
- ComplexPattern<i32, 3, "SelectShifterOperandReg",
- [shl,srl,sra,rotr]> {
- 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<i32>, // reg imm
+ ComplexPattern<i32, 2, "SelectImmShifterOperand",
+ [shl, srl, sra, rotr]> {
+ 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<i32>, // reg reg imm
+ ComplexPattern<i32, 3, "SelectShiftRegShifterOperand",
+ [shl,srl,sra,rotr]> {
+ 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<i32>, // reg reg imm
- ComplexPattern<i32, 3, "SelectShiftShifterOperandReg",
+def shift_so_reg_imm : Operand<i32>, // reg reg imm
+ ComplexPattern<i32, 2, "SelectShiftImmShifterOperand",
[shl,srl,sra,rotr]> {
- 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<i32>, ImmLeaf<i32, [{
return ARM_AM::getSOImmVal(Imm) != -1;
}]> {
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<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 8;
@@ -472,7 +523,7 @@ def imm0_7 : Operand<i32>, ImmLeaf<i32, [{
let ParserMatchClass = Imm0_7AsmOperand;
}
-/// imm0_15 predicate - Immediate in the range [0,31].
+/// imm0_15 predicate - Immediate in the range [0,15].
def Imm0_15AsmOperand: AsmOperandClass { let Name = "Imm0_15"; }
def imm0_15 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 16;
@@ -481,68 +532,83 @@ def imm0_15 : Operand<i32>, ImmLeaf<i32, [{
}
/// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31].
+def Imm0_31AsmOperand: AsmOperandClass { let Name = "Imm0_31"; }
def imm0_31 : Operand<i32>, ImmLeaf<i32, [{
return Imm >= 0 && Imm < 32;
-}]>;
-
-/// imm0_31_m1 - Matches and prints like imm0_31, but encodes as 'value - 1'.
-def imm0_31_m1 : Operand<i32>, ImmLeaf<i32, [{
- return Imm >= 0 && Imm < 32;
}]> {
- let EncoderMethod = "getImmMinusOneOpValue";
+ let ParserMatchClass = Imm0_31AsmOperand;
+}
+
+/// imm0_255 predicate - Immediate in the range [0,255].
+def Imm0_255AsmOperand : AsmOperandClass { let Name = "Imm0_255"; }
+def imm0_255 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 256; }]> {
+ let ParserMatchClass = Imm0_255AsmOperand;
}
-// i32imm_hilo16 - For movt/movw - sets the MC Encoder method.
-// The imm is split into imm{15-12}, imm{11-0}
+// imm0_65535_expr - For movt/movw - 16-bit immediate that can also reference
+// a relocatable expression.
//
-def i32imm_hilo16 : Operand<i32> {
+// 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<i32> {
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<i32>, ImmLeaf<i32, [{
+ return Imm >= 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<i32>,
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<i32>, ImmLeaf<i32, [{
- return isInt<5>(Imm);
+def imm1_32_XFORM: SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant((int)N->getZExtValue() - 1, MVT::i32);
}]>;
-
-/// width_imm - number of bits to be copied, used by BFI4p and t2BFI4p
-def width_imm : Operand<i32>, ImmLeaf<i32, [{
- return Imm > 0 && Imm <= 32;
-}] > {
- let EncoderMethod = "getMsbOpValue";
-}
-
-def ssat_imm : Operand<i32>, ImmLeaf<i32, [{
- return Imm > 0 && Imm <= 32;
-}]> {
- let EncoderMethod = "getSsatBitPosValue";
+def Imm1_32AsmOperand: AsmOperandClass { let Name = "Imm1_32"; }
+def imm1_32 : Operand<i32>, 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: SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant((int)N->getZExtValue() - 1, MVT::i32);
+}]>;
+def Imm1_16AsmOperand: AsmOperandClass { let Name = "Imm1_16"; }
+def imm1_16 : Operand<i32>, 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<i32>,
ComplexPattern<i32, 2, "SelectAddrModeImm12", []> {
// 12-bit immediate operand. Note that instructions using this encode
@@ -551,53 +617,129 @@ def addrmode_imm12 : Operand<i32>,
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<i32>,
ComplexPattern<i32, 3, "SelectLdStSOReg", []> {
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<i32> {
+ 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<i32> {
+ 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<i32> {
+ 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<i32>,
ComplexPattern<i32, 3, "SelectAddrMode2", []> {
let EncoderMethod = "getAddrMode2OpValue";
let PrintMethod = "printAddrMode2Operand";
- let ParserMatchClass = MemMode2AsmOperand;
+ let ParserMatchClass = AddrMode2AsmOperand;
let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
}
-def am2offset : Operand<i32>,
- ComplexPattern<i32, 2, "SelectAddrMode2Offset",
+def PostIdxRegShiftedAsmOperand : AsmOperandClass {
+ let Name = "PostIdxRegShifted";
+ let ParserMethod = "parsePostIdxReg";
+}
+def am2offset_reg : Operand<i32>,
+ ComplexPattern<i32, 2, "SelectAddrMode2OffsetReg",
+ [], [SDNPWantRoot]> {
+ 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<i32>,
+ ComplexPattern<i32, 2, "SelectAddrMode2OffsetImm",
[], [SDNPWantRoot]> {
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<i32>,
ComplexPattern<i32, 3, "SelectAddrMode3", []> {
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<i32>,
ComplexPattern<i32, 2, "SelectAddrMode3Offset",
[], [SDNPWantRoot]> {
let EncoderMethod = "getAddrMode3OffsetOpValue";
let PrintMethod = "printAddrMode3OffsetOperand";
+ let ParserMatchClass = AM3OffsetAsmOperand;
let MIOperandInfo = (ops GPR, i32imm);
}
@@ -608,28 +750,28 @@ def ldstm_mode : OptionalDefOperand<OtherVT, (ops i32), (ops (i32 1))> {
let PrintMethod = "printLdStmModeOperand";
}
-def MemMode5AsmOperand : AsmOperandClass {
- let Name = "MemMode5";
- let SuperClasses = [];
-}
-
// addrmode5 := reg +/- imm8*4
//
+def AddrMode5AsmOperand : AsmOperandClass { let Name = "AddrMode5"; }
def addrmode5 : Operand<i32>,
ComplexPattern<i32, 2, "SelectAddrMode5", []> {
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<i32>,
ComplexPattern<i32, 2, "SelectAddrMode6", [], [SDNPWantParent]>{
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<i32>,
@@ -638,6 +780,7 @@ def am6offset : Operand<i32>,
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<i32>,
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<i32> {
+def MemNoOffsetAsmOperand : AsmOperandClass { let Name = "MemNoOffset"; }
+def addr_offset_none : Operand<i32>,
+ ComplexPattern<i32, 1, "SelectAddrOffsetNone", []> {
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<i32> {
@@ -687,25 +826,30 @@ def nohash_imm : Operand<i32> {
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<i32> {
let PrintMethod = "printPImmediate";
let ParserMatchClass = CoprocNumAsmOperand;
+ let DecoderMethod = "DecodeCoprocessor";
}
+def CoprocRegAsmOperand : AsmOperandClass {
+ let Name = "CoprocReg";
+ let ParserMethod = "parseCoprocRegOperand";
+}
def c_imm : Operand<i32> {
let PrintMethod = "printCImmediate";
let ParserMatchClass = CoprocRegAsmOperand;
}
+def CoprocOptionAsmOperand : AsmOperandClass {
+ let Name = "CoprocOption";
+ let ParserMethod = "parseCoprocOptionOperand";
+}
+def coproc_option_imm : Operand<i32> {
+ let PrintMethod = "printCoprocOptionImm";
+ let ParserMatchClass = CoprocOptionAsmOperand;
+}
//===----------------------------------------------------------------------===//
@@ -748,16 +892,37 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc,
let Inst{11-4} = 0b00000000;
let Inst{3-0} = Rm;
}
- def rs : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), DPSoRegFrm,
+
+ def rsi : AsI1<opcod, (outs GPR:$Rd),
+ (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm,
+ iis, opc, "\t$Rd, $Rn, $shift",
+ [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$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-5} = shift{11-5};
+ let Inst{4} = 0;
+ let Inst{3-0} = shift{3-0};
+ }
+
+ def rsr : AsI1<opcod, (outs GPR:$Rd),
+ (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm,
iis, opc, "\t$Rd, $Rn, $shift",
- [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]> {
+ [(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,56 +938,172 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc,
cc_out:$s)>,
Requires<[IsARM]>;
def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
- (!cast<Instruction>(!strconcat(baseOpc, "rs")) GPR:$Rdn, GPR:$Rdn,
- so_reg:$shift, pred:$p,
+ (!cast<Instruction>(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn,
+ so_reg_imm:$shift, pred:$p,
cc_out:$s)>,
Requires<[IsARM]>;
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
+ (!cast<Instruction>(!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<bits<4> 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<bits<4> opcod, string opc,
InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
- PatFrag opnode, bit Commutable = 0> {
- def ri : AI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
+ PatFrag opnode, string baseOpc, bit Commutable = 0> {
+ // 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<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
iii, opc, "\t$Rd, $Rn, $imm",
- [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]> {
+ [(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<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
+ }
+ def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
iir, opc, "\t$Rd, $Rn, $Rm",
- [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> {
+ [/* 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<opcod, (outs GPR:$Rd),
+ (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm,
+ iis, opc, "\t$Rd, $Rn, $shift",
+ [(set GPR:$Rd, (opnode so_reg_imm:$shift, GPR:$Rn))]> {
+ 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<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), DPSoRegFrm,
+
+ def rsr : AsI1<opcod, (outs GPR:$Rd),
+ (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm,
iis, opc, "\t$Rd, $Rn, $shift",
- [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]> {
+ [(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{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};
}
+
+ // Assembly aliases for optional destination operand when it's the same
+ // as the source operand.
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $imm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "ri")) GPR:$Rdn, GPR:$Rdn,
+ so_imm:$imm, pred:$p,
+ cc_out:$s)>,
+ Requires<[IsARM]>;
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $Rm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rr")) GPR:$Rdn, GPR:$Rdn,
+ GPR:$Rm, pred:$p,
+ cc_out:$s)>,
+ Requires<[IsARM]>;
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn,
+ so_reg_imm:$shift, pred:$p,
+ cc_out:$s)>,
+ Requires<[IsARM]>;
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
+ (!cast<Instruction>(!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<bits<4> opcod, string opc,
+ InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
+ PatFrag opnode, bit Commutable = 0> {
+ def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
+ iii, opc, "\t$Rd, $Rn, $imm",
+ [(set GPR:$Rd, CPSR, (opnode so_imm:$imm, GPR:$Rn))]>;
+
+ def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
+ iir, opc, "\t$Rd, $Rn, $Rm",
+ [/* pattern left blank */]>;
+
+ def rsi : AsI1<opcod, (outs GPR:$Rd),
+ (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm,
+ iis, opc, "\t$Rd, $Rn, $shift",
+ [(set GPR:$Rd, CPSR, (opnode so_reg_imm:$shift, GPR:$Rn))]>;
+
+ def rsr : AsI1<opcod, (outs GPR:$Rd),
+ (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm,
+ iis, opc, "\t$Rd, $Rn, $shift",
+ [(set GPR:$Rd, CPSR, (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};
+ }
+}
+}
+
+/// 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<bits<4> opcod, string opc,
+ InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
+ PatFrag opnode, bit Commutable = 0> {
+ def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
+ iii, opc, "\t$Rd, $Rn, $imm",
+ [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_imm:$imm))]>;
+ def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
+ iir, opc, "\t$Rd, $Rn, $Rm",
+ [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, GPR:$Rm))]>;
+ def rsi : AsI1<opcod, (outs GPR:$Rd),
+ (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm,
+ iis, opc, "\t$Rd, $Rn, $shift",
+ [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_reg_imm:$shift))]>;
+
+ def rsr : AsI1<opcod, (outs GPR:$Rd),
+ (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm,
+ iis, opc, "\t$Rd, $Rn, $shift",
+ [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_reg_reg:$shift))]>;
}
}
@@ -857,128 +1138,190 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc,
let Inst{11-4} = 0b00000000;
let Inst{3-0} = Rm;
}
- def rs : AI1<opcod, (outs), (ins GPR:$Rn, so_reg:$shift), DPSoRegFrm, iis,
+ def rsi : AI1<opcod, (outs),
+ (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm, iis,
+ opc, "\t$Rn, $shift",
+ [(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-5} = shift{11-5};
+ let Inst{4} = 0;
+ let Inst{3-0} = shift{3-0};
+ }
+ def rsr : AI1<opcod, (outs),
+ (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, iis,
opc, "\t$Rn, $shift",
- [(opnode GPR:$Rn, so_reg:$shift)]> {
+ [(opnode GPR:$Rn, so_reg_reg:$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-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<bits<8> opcod, string opc, PatFrag opnode> {
- def r : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm),
- IIC_iEXTr, opc, "\t$Rd, $Rm",
- [(set GPR:$Rd, (opnode GPR:$Rm))]>,
- 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<opcod, (outs GPR:$Rd), (ins GPR:$Rm, rot_imm:$rot),
- IIC_iEXTr, opc, "\t$Rd, $Rm, ror $rot",
- [(set GPR:$Rd, (opnode (rotr GPR:$Rm, rot_imm:$rot)))]>,
- 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<bits<8> opcod, string opc, PatFrag opnode>
+ : AExtI<opcod, (outs GPRnopc:$Rd), (ins GPRnopc:$Rm, rot_imm:$rot),
+ IIC_iEXTr, opc, "\t$Rd, $Rm$rot",
+ [(set GPRnopc:$Rd, (opnode (rotr GPRnopc:$Rm, rot_imm:$rot)))]>,
+ 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<bits<8> opcod, string opc> {
- def r : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm),
- IIC_iEXTr, opc, "\t$Rd, $Rm",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsARM, HasV6]> {
- let Inst{19-16} = 0b1111;
- let Inst{11-10} = 0b00;
- }
- def r_rot : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rm, rot_imm:$rot),
- IIC_iEXTr, opc, "\t$Rd, $Rm, ror $rot",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsARM, HasV6]> {
- bits<2> rot;
- let Inst{19-16} = 0b1111;
- let Inst{11-10} = rot;
- }
+class AI_ext_rrot_np<bits<8> opcod, string opc>
+ : AExtI<opcod, (outs GPRnopc:$Rd), (ins GPRnopc:$Rm, rot_imm:$rot),
+ IIC_iEXTr, opc, "\t$Rd, $Rm$rot", []>,
+ 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<bits<8> opcod, string opc, PatFrag opnode> {
- def rr : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
- IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm",
- [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]>,
- Requires<[IsARM, HasV6]> {
+class AI_exta_rrot<bits<8> opcod, string opc, PatFrag opnode>
+ : AExtI<opcod, (outs GPRnopc:$Rd), (ins GPR:$Rn, GPRnopc:$Rm, rot_imm:$rot),
+ IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm$rot",
+ [(set GPRnopc:$Rd, (opnode GPR:$Rn,
+ (rotr GPRnopc:$Rm, rot_imm:$rot)))]>,
+ 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<bits<8> opcod, string opc>
+ : AExtI<opcod, (outs GPRnopc:$Rd), (ins GPR:$Rn, GPRnopc:$Rm, rot_imm:$rot),
+ IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm$rot", []>,
+ 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<bits<4> opcod, string opc, PatFrag opnode,
+ string baseOpc, bit Commutable = 0> {
+ let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in {
+ def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
+ DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
+ [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_imm:$imm, CPSR))]>,
+ 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<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm,
- rot_imm:$rot),
- IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm, ror $rot",
- [(set GPR:$Rd, (opnode GPR:$Rn,
- (rotr GPR:$Rm, rot_imm:$rot)))]>,
- Requires<[IsARM, HasV6]> {
+ let Inst{19-16} = Rn;
+ let Inst{11-0} = imm;
+ }
+ def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
+ DPFrm, IIC_iALUr, opc, "\t$Rd, $Rn, $Rm",
+ [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, GPR:$Rm, CPSR))]>,
+ 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<opcod, (outs GPR:$Rd),
+ (ins GPR:$Rn, so_reg_imm:$shift),
+ DPSoRegImmFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
+ [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_reg_imm:$shift, CPSR))]>,
+ 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;
+ let Inst{11-5} = shift{11-5};
+ let Inst{4} = 0;
+ let Inst{3-0} = shift{3-0};
}
-}
-
-// For disassembly only.
-multiclass AI_exta_rrot_np<bits<8> opcod, string opc> {
- def rr : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
- IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsARM, HasV6]> {
- let Inst{11-10} = 0b00;
- }
- def rr_rot : AExtI<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm,
- rot_imm:$rot),
- IIC_iEXTAr, opc, "\t$Rd, $Rn, $Rm, ror $rot",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsARM, HasV6]> {
+ def rsr : AsI1<opcod, (outs GPR:$Rd),
+ (ins GPR:$Rn, so_reg_reg:$shift),
+ DPSoRegRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
+ [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_reg_reg:$shift, CPSR))]>,
+ 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(opc, "${s}${p} $Rdn, $imm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "ri")) GPR:$Rdn, GPR:$Rdn,
+ so_imm:$imm, pred:$p,
+ cc_out:$s)>,
+ Requires<[IsARM]>;
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $Rm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rr")) GPR:$Rdn, GPR:$Rdn,
+ GPR:$Rm, pred:$p,
+ cc_out:$s)>,
+ Requires<[IsARM]>;
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn,
+ so_reg_imm:$shift, pred:$p,
+ cc_out:$s)>,
+ Requires<[IsARM]>;
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
+ (!cast<Instruction>(!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<bits<4> 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<bits<4> opcod, string opc, PatFrag opnode,
+ string baseOpc> {
+ let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in {
def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
- [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>,
+ [(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<bits<4> opcod, string opc, PatFrag opnode,
}
def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
DPFrm, IIC_iALUr, opc, "\t$Rd, $Rn, $Rm",
- [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]>,
- 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<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
- DPSoRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
- [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>,
+ def rsi : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
+ DPSoRegImmFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
+ [(set GPR:$Rd, CPSR, (opnode so_reg_imm:$shift, GPR:$Rn, CPSR))]>,
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<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
+ DPSoRegRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
+ [(set GPR:$Rd, CPSR, (opnode so_reg_reg:$shift, GPR:$Rn, CPSR))]>,
+ 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<!strconcat(opc, "${s}${p} $Rdn, $imm"),
@@ -1028,28 +1388,15 @@ multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
cc_out:$s)>,
Requires<[IsARM]>;
def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
- (!cast<Instruction>(!strconcat(baseOpc, "rs")) GPR:$Rdn, GPR:$Rdn,
- so_reg:$shift, pred:$p,
+ (!cast<Instruction>(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn,
+ so_reg_imm:$shift, pred:$p,
+ cc_out:$s)>,
+ Requires<[IsARM]>;
+ def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
+ (!cast<Instruction>(!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<PatFrag opnode, bit Commutable = 0> {
- 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<bit isByte, string opc, InstrItinClass iii,
}
}
+let canFoldAsLoad = 1, isReMaterializable = 1 in {
+multiclass AI_ldr1nopc<bit isByte, string opc, InstrItinClass iii,
+ InstrItinClass iir, PatFrag opnode> {
+ // 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<bit isByte, string opc, InstrItinClass iii,
InstrItinClass iir, PatFrag opnode> {
// Note: We use the complex addrmode_imm12 rather than just an input
@@ -1110,6 +1488,37 @@ multiclass AI_str1<bit isByte, string opc, InstrItinClass iii,
let Inst{11-0} = shift{11-0};
}
}
+
+multiclass AI_str1nopc<bit isByte, string opc, InstrItinClass iii,
+ InstrItinClass iir, PatFrag opnode> {
+ // 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<dag iops, string asm_ops>
: 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<dag iops, string asm_ops>
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<bits<1> read, bits<1> data, string opc> {
def i12 : AXI<(outs), (ins addrmode_imm12:$addr), MiscFrm, IIC_Preload,
@@ -1271,6 +1701,7 @@ multiclass APreLoad<bits<1> 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<bit wb, string asm>
+ : 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<bit wb, string asm>
+ : 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",
[]> {
@@ -1727,34 +2198,65 @@ def LDRD : AI3ld<0b1101, 0, (outs GPR:$Rd, GPR:$dst2),
// Indexed loads
multiclass AI2_ldridx<bit isByte, string opc, InstrItinClass itin> {
- def _PRE : AI2ldstidx<1, isByte, 1, (outs GPR:$Rt, GPR:$Rn_wb),
- (ins addrmode2:$addr), IndexModePre, LdFrm, itin,
+ 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", []> {
- // {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} = 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", []> {
+ 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<bits<4> op, bit op20, string opc, InstrItinClass itin> {
- def _PRE : AI3ldstidx<op, op20, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
+multiclass AI3_ldridx<bits<4> op, string opc, InstrItinClass itin> {
+ def _PRE : AI3ldstidx<op, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins addrmode3:$addr), IndexModePre,
LdMiscFrm, itin,
opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
@@ -1773,27 +2275,31 @@ multiclass AI3_ldridx<bits<4> 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<op, op20, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
- (ins GPR:$Rn, am3offset:$offset), IndexModePost,
- LdMiscFrm, itin,
- opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> {
+ def _POST : AI3ldstidx<op, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
+ (ins addr_offset_none:$addr, am3offset:$offset),
+ IndexModePost, LdMiscFrm, itin,
+ opc, "\t$Rt, $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";
}
}
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<bits<4> op, string opc> {
+ def i : AI3ldstidxT<op, 1, (outs GPR:$Rt, GPR:$base_wb),
+ (ins addr_offset_none:$addr, postidx_imm8:$offset),
+ IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, opc,
+ "\t$Rt, $addr, $offset", "$addr.base = $base_wb", []> {
+ 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<op, 1, (outs GPR:$Rt, GPR:$base_wb),
+ (ins addr_offset_none:$addr, postidx_reg:$Rm),
+ IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, opc,
+ "\t$Rt, $addr, $Rm", "$addr.base = $base_wb", []> {
+ 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<bit isByte, string opc, InstrItinClass itin> {
+ 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 AsmMatchConverter = "CvtStWriteBackRegAddrMode2";
+ 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 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<bits<4> op, string opc> {
+ def i : AI3ldstidxT<op, 0, (outs GPR:$base_wb),
+ (ins GPR:$Rt, addr_offset_none:$addr, postidx_imm8:$offset),
+ IndexModePost, StMiscFrm, IIC_iStore_bh_ru, opc,
+ "\t$Rt, $addr, $offset", "$addr.base = $base_wb", []> {
+ 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<op, 0, (outs GPR:$base_wb),
+ (ins GPR:$Rt, addr_offset_none:$addr, postidx_reg:$Rm),
+ IndexModePost, StMiscFrm, IIC_iStore_bh_ru, opc,
+ "\t$Rt, $addr, $Rm", "$addr.base = $base_wb", []> {
+ 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<string asm, bit L_bit, Format f,
let Inst{24-23} = 0b01; // Increment After
let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
+
+ let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
}
def DA :
AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
@@ -2012,6 +2782,8 @@ multiclass arm_ldst_mult<string asm, bit L_bit, Format f,
let Inst{24-23} = 0b00; // Decrement After
let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
+
+ let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
}
def DB :
AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
@@ -2028,6 +2800,8 @@ multiclass arm_ldst_mult<string asm, bit L_bit, Format f,
let Inst{24-23} = 0b10; // Decrement Before
let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
+
+ let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
}
def IB :
AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
@@ -2044,6 +2818,8 @@ multiclass arm_ldst_mult<string asm, bit L_bit, Format f,
let Inst{24-23} = 0b11; // Increment Before
let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
+
+ let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
}
}
@@ -2084,6 +2860,9 @@ def MOVr : AsI1<0b1101, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMOVr,
let Inst{15-12} = Rd;
}
+def : ARMInstAlias<"movs${p} $Rd, $Rm",
+ (MOVr GPR:$Rd, GPR:$Rm, pred:$p, CPSR)>;
+
// 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<bits<8> op27_20, bits<8> op11_4, string opc,
- list<dag> 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<dag> 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<bits<8> 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<string opc, PatFrag opnode> {
@@ -2925,92 +3639,95 @@ multiclass AI_smul<string opc, PatFrag opnode> {
multiclass AI_smla<string opc, PatFrag opnode> {
- 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<x><y> -- 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<x><y>.
+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<bit long, bit sub, bit swap, dag oops, dag iops,
InstrItinClass itin, string opc, string asm>
: AI<oops, iops, MulFrm, itin, opc, asm, []>, 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<bit long, bit sub, bit swap, dag oops, dag iops,
@@ -3024,6 +3741,8 @@ class AMulDualIa<bit long, bit sub, bit swap, dag oops, dag iops,
InstrItinClass itin, string opc, string asm>
: AMulDualIbase<long, sub, swap, oops, iops, itin, opc, asm> {
bits<4> Ra;
+ bits<4> Rd;
+ let Inst{19-16} = Rd;
let Inst{15-12} = Ra;
}
class AMulDualI64<bit long, bit sub, bit swap, dag oops, dag iops,
@@ -3037,18 +3756,20 @@ class AMulDualI64<bit long, bit sub, bit swap, dag oops, dag iops,
multiclass AI_smld<bit sub, string opc> {
- 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<bit sub, string opc> {
- 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 : SDNodeXForm<imm, [{
- unsigned Sh = ARM_AM::getSORegOpc(ARM_AM::lsl, N->getZExtValue());
- return CurDAG->getTargetConstant(Sh, MVT::i32);
-}]>;
-
-def lsl_amt : ImmLeaf<i32, [{
- return Imm > 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 : SDNodeXForm<imm, [{
- unsigned Sh = ARM_AM::getSORegOpc(ARM_AM::asr, N->getZExtValue());
- return CurDAG->getTargetConstant(Sh, MVT::i32);
-}]>;
-
-def asr_amt : ImmLeaf<i32, [{
- return Imm > 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<i32> {
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<dag oops, dag iops, string opc, string asm,
IndexMode im = IndexModeNone>
+ : I<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
+ opc, asm, "", []> {
+ let Inst{27-25} = 0b110;
+}
+class ACInoP<dag oops, dag iops, string opc, string asm,
+ IndexMode im = IndexModeNone>
: InoP<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
- opc, asm, "", [/* For disassembly only; pattern left blank */]> {
+ opc, asm, "", []> {
+ let Inst{31-28} = 0b1111;
let Inst{27-25} = 0b110;
}
-
-multiclass LdStCop<bits<4> 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<bit load, bit Dbit, string asm> {
+ 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<bit load, bit Dbit, string asm> {
+ 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<string opc, bit direction, dag oops, dag iops,
@@ -3660,8 +4453,8 @@ def MCR : MovRCopro<"mcr", 0 /* from ARM core register to coprocessor */,
imm:$CRm, imm:$opc2)]>;
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<string opc, bit direction,
- list<dag> pattern = [/* For disassembly only */]>
+class MovRRCopro<string opc, bit direction, list<dag> 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<string opc, bit direction,
- list<dag> pattern = [/* For disassembly only */]>
+class MovRRCopro2<string opc, bit direction, list<dag> 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/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td
index 0df62f4..7aad186 100644
--- a/lib/Target/ARM/ARMInstrNEON.td
+++ b/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<i32>, ImmLeaf<i32, [{
+ return ((uint64_t)Imm) < 8;
+}]> {
+ let ParserMatchClass = VectorIndex8Operand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i32imm);
+}
+def VectorIndex16 : Operand<i32>, ImmLeaf<i32, [{
+ return ((uint64_t)Imm) < 4;
+}]> {
+ let ParserMatchClass = VectorIndex16Operand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i32imm);
+}
+def VectorIndex32 : Operand<i32>, ImmLeaf<i32, [{
+ return ((uint64_t)Imm) < 2;
+}]> {
+ let ParserMatchClass = VectorIndex32Operand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i32imm);
+}
+
//===----------------------------------------------------------------------===//
// NEON-specific DAG Nodes.
//===----------------------------------------------------------------------===//
@@ -175,7 +204,8 @@ class VLDQQWBPseudo<InstrItinClass itin>
(ins addrmode6:$addr, am6offset:$offset), itin,
"$addr.addr = $wb">;
class VLDQQQQPseudo<InstrItinClass itin>
- : PseudoNLdSt<(outs QQQQPR:$dst), (ins addrmode6:$addr, QQQQPR:$src),itin,"">;
+ : PseudoNLdSt<(outs QQQQPR:$dst), (ins addrmode6:$addr, QQQQPR:$src),itin,
+ "$src = $dst">;
class VLDQQQQWBPseudo<InstrItinClass itin>
: PseudoNLdSt<(outs QQQQPR:$dst, GPR:$wb),
(ins addrmode6:$addr, am6offset:$offset, QQQQPR:$src), itin,
@@ -190,6 +220,7 @@ class VLD1D<bits<4> op7_4, string Dt>
"vld1", Dt, "\\{$Vd\\}, $Rn", "", []> {
let Rm = 0b1111;
let Inst{4} = Rn{4};
+ let DecoderMethod = "DecodeVLDInstruction";
}
class VLD1Q<bits<4> op7_4, string Dt>
: NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2),
@@ -197,6 +228,7 @@ class VLD1Q<bits<4> 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<bits<4> op7_4, string Dt>
"vld1", Dt, "\\{$Vd\\}, $Rn$Rm",
"$Rn.addr = $wb", []> {
let Inst{4} = Rn{4};
+ let DecoderMethod = "DecodeVLDInstruction";
}
class VLD1QWB<bits<4> op7_4, string Dt>
: NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb),
@@ -228,6 +261,7 @@ class VLD1QWB<bits<4> 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<bits<4> op7_4, string Dt>
"\\{$Vd, $dst2, $dst3\\}, $Rn", "", []> {
let Rm = 0b1111;
let Inst{4} = Rn{4};
+ let DecoderMethod = "DecodeVLDInstruction";
}
class VLD1D3WB<bits<4> 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<bits<4> op7_4, string Dt>
"\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> {
let Rm = 0b1111;
let Inst{5-4} = Rn{5-4};
+ let DecoderMethod = "DecodeVLDInstruction";
}
class VLD1D4WB<bits<4> op7_4, string Dt>
: NLdSt<0,0b10,0b0010,op7_4,
@@ -288,6 +325,7 @@ class VLD1D4WB<bits<4> 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<bits<4> 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<bits<4> op7_4, string Dt>
: NLdSt<0, 0b10, 0b0011, op7_4,
@@ -318,6 +357,7 @@ class VLD2Q<bits<4> 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<bits<4> 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<bits<4> op7_4, string Dt>
: NLdSt<0, 0b10, 0b0011, op7_4,
@@ -351,6 +392,7 @@ class VLD2QWB<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> op11_8, bits<4> op7_4, string Dt, ValueType Ty,
(i32 (LoadOp addrmode6:$Rn)),
imm:$lane))]> {
let Rm = 0b1111;
+ let DecoderMethod = "DecodeVLD1LN";
}
class VLD1LN32<bits<4> op11_8, bits<4> op7_4, string Dt, ValueType Ty,
PatFrag LoadOp>
@@ -541,6 +588,7 @@ class VLD1LN32<bits<4> op11_8, bits<4> op7_4, string Dt, ValueType Ty,
(i32 (LoadOp addrmode6oneL32:$Rn)),
imm:$lane))]> {
let Rm = 0b1111;
+ let DecoderMethod = "DecodeVLD1LN";
}
class VLD1QLNPseudo<ValueType Ty, PatFrag LoadOp> : VLDQLNPseudo<IIC_VLD1ln> {
let Pattern = [(set QPR:$dst, (vector_insert (Ty QPR:$src),
@@ -580,7 +628,9 @@ class VLD1LNWB<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<ValueType Ty, PatFrag LoadOp> : VLDQPseudo<IIC_VLD1dup> {
let Pattern = [(set QPR:$dst,
@@ -852,6 +910,7 @@ class VLD1QDUP<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> op7_4, string Dt>
IIC_VST1, "vst1", Dt, "\\{$Vd\\}, $Rn", "", []> {
let Rm = 0b1111;
let Inst{4} = Rn{4};
+ let DecoderMethod = "DecodeVSTInstruction";
}
class VST1Q<bits<4> op7_4, string Dt>
: NLdSt<0,0b00,0b1010,op7_4, (outs),
@@ -1052,6 +1120,7 @@ class VST1Q<bits<4> 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<bits<4> 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<bits<4> op7_4, string Dt>
: NLdSt<0, 0b00, 0b1010, op7_4, (outs GPR:$wb),
@@ -1082,6 +1152,7 @@ class VST1QWB<bits<4> 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<bits<4> 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<bits<4> op7_4, string Dt>
: NLdSt<0, 0b00, 0b0110, op7_4, (outs GPR:$wb),
@@ -1114,6 +1186,7 @@ class VST1D3WB<bits<4> 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<bits<4> op7_4, string Dt>
[]> {
let Rm = 0b1111;
let Inst{5-4} = Rn{5-4};
+ let DecoderMethod = "DecodeVSTInstruction";
}
class VST1D4WB<bits<4> op7_4, string Dt>
: NLdSt<0, 0b00, 0b0010, op7_4, (outs GPR:$wb),
@@ -1145,6 +1219,7 @@ class VST1D4WB<bits<4> 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<bits<4> 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<bits<4> op7_4, string Dt>
: NLdSt<0, 0b00, 0b0011, op7_4, (outs),
@@ -1175,6 +1251,7 @@ class VST2Q<bits<4> 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<bits<4> 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<bits<4> op7_4, string Dt>
: NLdSt<0, 0b00, 0b0011, op7_4, (outs GPR:$wb),
@@ -1208,6 +1286,7 @@ class VST2QWB<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> op11_8, bits<4> op7_4, string Dt, ValueType Ty,
PatFrag StoreOp, SDNode ExtractOp>
@@ -1389,6 +1473,7 @@ class VST1LN32<bits<4> 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<ValueType Ty, PatFrag StoreOp, SDNode ExtractOp>
: VSTQLNPseudo<IIC_VST1ln> {
@@ -1429,7 +1514,9 @@ class VST1LNWB<bits<4> 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<ValueType Ty, PatFrag StoreOp, SDNode ExtractOp>
: VSTQLNWBPseudo<IIC_VST1lnu> {
let Pattern = [(set GPR:$wb, (StoreOp (ExtractOp (Ty QPR:$src), imm:$lane),
@@ -1465,6 +1552,7 @@ class VST2LN<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bits<4> 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<bit op24, bit op23, bits<6> op21_16, bits<4> op11_8, bit op7,
: N2VLSh<op24, op23, op11_8, op7, op6, op4, OpcodeStr, Dt,
ResTy, OpTy, OpNode> {
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<bits<4> op19_16, string OpcodeStr, string Dt,
- ValueType Ty>
- : NVDupLane<op19_16, 0, (outs DPR:$Vd), (ins DPR:$Vm, nohash_imm:$lane),
- IIC_VMOVD, OpcodeStr, Dt, "$Vd, $Vm[$lane]",
+ ValueType Ty, Operand IdxTy>
+ : NVDupLane<op19_16, 0, (outs DPR:$Vd), (ins DPR:$Vm, IdxTy:$lane),
+ IIC_VMOVD, OpcodeStr, Dt, "$Vd, $Vm$lane",
[(set DPR:$Vd, (Ty (NEONvduplane (Ty DPR:$Vm), imm:$lane)))]>;
class VDUPLNQ<bits<4> op19_16, string OpcodeStr, string Dt,
- ValueType ResTy, ValueType OpTy>
- : NVDupLane<op19_16, 1, (outs QPR:$Vd), (ins DPR:$Vm, nohash_imm:$lane),
- IIC_VMOVQ, OpcodeStr, Dt, "$Vd, $Vm[$lane]",
+ ValueType ResTy, ValueType OpTy, Operand IdxTy>
+ : NVDupLane<op19_16, 1, (outs QPR:$Vd), (ins DPR:$Vm, IdxTy:$lane),
+ IIC_VMOVQ, OpcodeStr, Dt, "$Vd, $Vm$lane",
[(set QPR:$Vd, (ResTy (NEONvduplane (OpTy DPR:$Vm),
- imm:$lane)))]>;
+ 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/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index bfe83ec..cedb547 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -19,6 +19,19 @@ def ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
SDNPVariadic]>;
+def imm_sr_XFORM: SDNodeXForm<imm, [{
+ unsigned Imm = N->getZExtValue();
+ return CurDAG->getTargetConstant((Imm == 32 ? 0 : Imm), MVT::i32);
+}]>;
+def ThumbSRImmAsmOperand: AsmOperandClass { let Name = "ImmThumbSR"; }
+def imm_sr : Operand<i32>, 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 : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(-(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<i32>, ImmLeaf<i32, [{ return Imm >= 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<i32> {
}
// Scaled 4 immediate.
-def t_imm_s4 : Operand<i32> {
+def t_imm0_1020s4_asmoperand: AsmOperandClass { let Name = "Imm0_1020s4"; }
+def t_imm0_1020s4 : Operand<i32> {
+ 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<i32> {
let PrintMethod = "printThumbS4ImmOperand";
+ let ParserMatchClass = t_imm0_508s4_asmoperand;
let OperandType = "OPERAND_IMMEDIATE";
}
@@ -79,113 +97,129 @@ def t_imm_s4 : Operand<i32> {
let OperandType = "OPERAND_PCREL" in {
def t_brtarget : Operand<OtherVT> {
let EncoderMethod = "getThumbBRTargetOpValue";
+ let DecoderMethod = "DecodeThumbBROperand";
}
def t_bcctarget : Operand<i32> {
let EncoderMethod = "getThumbBCCTargetOpValue";
+ let DecoderMethod = "DecodeThumbBCCTargetOperand";
}
def t_cbtarget : Operand<i32> {
let EncoderMethod = "getThumbCBTargetOpValue";
+ let DecoderMethod = "DecodeThumbCmpBROperand";
}
def t_bltarget : Operand<i32> {
let EncoderMethod = "getThumbBLTargetOpValue";
+ let DecoderMethod = "DecodeThumbBLTargetOperand";
}
def t_blxtarget : Operand<i32> {
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<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> {
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<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S1", []> {
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<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S2", []> {
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<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S4", []> {
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<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S4", []> {
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<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S2", []> {
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<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S1", []> {
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<i32>,
ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> {
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 := <label> => pc + imm8 * 4
//
def t_addrmode_pc : Operand<i32> {
let EncoderMethod = "getAddrModePCOpValue";
- let ParserMatchClass = MemModeImmThumbAsmOperand;
+ let DecoderMethod = "DecodeThumbAddrModePC";
}
//===----------------------------------------------------------------------===//
@@ -207,68 +241,52 @@ def tADJCALLSTACKDOWN :
Requires<[IsThumb, IsThumb1Only]>;
}
-// T1Disassembly - A simple class to make encoding some disassembly patterns
-// easier and less verbose.
-class T1Disassembly<bits<2> op1, bits<8> op2>
+class T1SystemEncoding<bits<8> opc>
: T1Encoding<0b101111> {
- let Inst{9-8} = op1;
- let Inst{7-0} = op2;
+ let Inst{9-8} = 0b11;
+ let Inst{7-0} = opc;
}
-def tNOP : T1pI<(outs), (ins), NoItinerary, "nop", "",
- [/* For disassembly only; pattern left blank */]>,
- T1Disassembly<0b11, 0x00>; // A8.6.110
+def tNOP : T1pI<(outs), (ins), NoItinerary, "nop", "", []>,
+ T1SystemEncoding<0x00>, // A8.6.110
+ Requires<[IsThumb2]>;
-def tYIELD : T1pI<(outs), (ins), NoItinerary, "yield", "",
- [/* For disassembly only; pattern left blank */]>,
- T1Disassembly<0b11, 0x10>; // A8.6.410
+def tYIELD : T1pI<(outs), (ins), NoItinerary, "yield", "", []>,
+ T1SystemEncoding<0x10>; // A8.6.410
-def tWFE : T1pI<(outs), (ins), NoItinerary, "wfe", "",
- [/* For disassembly only; pattern left blank */]>,
- T1Disassembly<0b11, 0x20>; // A8.6.408
+def tWFE : T1pI<(outs), (ins), NoItinerary, "wfe", "", []>,
+ T1SystemEncoding<0x20>; // A8.6.408
-def tWFI : T1pI<(outs), (ins), NoItinerary, "wfi", "",
- [/* For disassembly only; pattern left blank */]>,
- T1Disassembly<0b11, 0x30>; // A8.6.409
+def tWFI : T1pI<(outs), (ins), NoItinerary, "wfi", "", []>,
+ T1SystemEncoding<0x30>; // A8.6.409
-def tSEV : T1pI<(outs), (ins), NoItinerary, "sev", "",
- [/* For disassembly only; pattern left blank */]>,
- T1Disassembly<0b11, 0x40>; // A8.6.157
+def tSEV : T1pI<(outs), (ins), NoItinerary, "sev", "", []>,
+ T1SystemEncoding<0x40>; // A8.6.157
-// The i32imm operand $val can be used by a debugger to store more information
+// The imm operand $val can be used by a debugger to store more information
// about the breakpoint.
-def tBKPT : T1I<(outs), (ins i32imm:$val), NoItinerary, "bkpt\t$val",
- [/* For disassembly only; pattern left blank */]>,
- T1Disassembly<0b10, {?,?,?,?,?,?,?,?}> {
+def tBKPT : T1I<(outs), (ins imm0_255:$val), NoItinerary, "bkpt\t$val",
+ []>,
+ T1Encoding<0b101111> {
+ let Inst{9-8} = 0b10;
// A8.6.22
bits<8> val;
let Inst{7-0} = val;
}
-def tSETENDBE : T1I<(outs), (ins), NoItinerary, "setend\tbe",
- [/* For disassembly only; pattern left blank */]>,
- T1Encoding<0b101101> {
- // A8.6.156
- let Inst{9-5} = 0b10010;
- let Inst{4} = 1;
- let Inst{3} = 1; // Big-Endian
- let Inst{2-0} = 0b000;
-}
-
-def tSETENDLE : T1I<(outs), (ins), NoItinerary, "setend\tle",
- [/* For disassembly only; pattern left blank */]>,
- T1Encoding<0b101101> {
+def tSETEND : T1I<(outs), (ins setend_op:$end), NoItinerary, "setend\t$end",
+ []>, T1Encoding<0b101101> {
+ bits<1> end;
// A8.6.156
let Inst{9-5} = 0b10010;
let Inst{4} = 1;
- let Inst{3} = 0; // Little-Endian
+ let Inst{3} = end;
let Inst{2-0} = 0b000;
}
// Change Processor State is a system instruction -- for disassembly only.
def tCPS : T1I<(outs), (ins imod_op:$imod, iflags_op:$iflags),
- NoItinerary, "cps$imod $iflags",
- [/* For disassembly only; pattern left blank */]>,
+ NoItinerary, "cps$imod $iflags", []>,
T1Misc<0b0110011> {
// A8.6.38 & B6.1.1
bit imod;
@@ -277,6 +295,7 @@ def tCPS : T1I<(outs), (ins imod_op:$imod, iflags_op:$iflags),
let Inst{4} = imod;
let Inst{3} = 0;
let Inst{2-0} = iflags;
+ let DecoderMethod = "DecodeThumbCPS";
}
// For both thumb1 and thumb2.
@@ -290,70 +309,70 @@ def tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, "",
let Inst{2-0} = dst;
}
-// PC relative add (ADR).
-def tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi,
- "add\t$dst, pc, $rhs", []>,
- T1Encoding<{1,0,1,0,0,?}> {
- // A6.2 & A8.6.10
- bits<3> dst;
- bits<8> rhs;
- let Inst{10-8} = dst;
- let Inst{7-0} = rhs;
-}
-
// ADD <Rd>, sp, #<imm8>
-// This is rematerializable, which is particularly useful for taking the
-// address of locals.
-let isReMaterializable = 1 in
-def tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi,
- "add\t$dst, $sp, $rhs", []>,
+// FIXME: This should not be marked as having side effects, and it should be
+// rematerializable. Clearing the side effect bit causes miscompilations,
+// probably because the instruction can be moved around.
+def tADDrSPi : T1pI<(outs tGPR:$dst), (ins GPRsp:$sp, t_imm0_1020s4:$imm),
+ IIC_iALUi, "add", "\t$dst, $sp, $imm", []>,
T1Encoding<{1,0,1,0,1,?}> {
// A6.2 & A8.6.8
bits<3> dst;
- bits<8> rhs;
+ bits<8> imm;
let Inst{10-8} = dst;
- let Inst{7-0} = rhs;
+ let Inst{7-0} = imm;
+ let DecoderMethod = "DecodeThumbAddSpecialReg";
}
// ADD sp, sp, #<imm7>
-def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi,
- "add\t$dst, $rhs", []>,
+def tADDspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm),
+ IIC_iALUi, "add", "\t$Rdn, $imm", []>,
T1Misc<{0,0,0,0,0,?,?}> {
// A6.2.5 & A8.6.8
- bits<7> rhs;
- let Inst{6-0} = rhs;
+ bits<7> imm;
+ let Inst{6-0} = imm;
+ let DecoderMethod = "DecodeThumbAddSPImm";
}
// SUB sp, sp, #<imm7>
// FIXME: The encoding and the ASM string don't match up.
-def tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi,
- "sub\t$dst, $rhs", []>,
+def tSUBspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm),
+ IIC_iALUi, "sub", "\t$Rdn, $imm", []>,
T1Misc<{0,0,0,0,1,?,?}> {
// A6.2.5 & A8.6.214
- bits<7> rhs;
- let Inst{6-0} = rhs;
+ bits<7> imm;
+ let Inst{6-0} = imm;
+ let DecoderMethod = "DecodeThumbAddSPImm";
}
+// Can optionally specify SP as a three operand instruction.
+def : tInstAlias<"add${p} sp, sp, $imm",
+ (tADDspi SP, t_imm0_508s4:$imm, pred:$p)>;
+def : tInstAlias<"sub${p} sp, sp, $imm",
+ (tSUBspi SP, t_imm0_508s4:$imm, pred:$p)>;
+
// ADD <Rm>, sp
-def tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
- "add\t$dst, $rhs", []>,
+def tADDrSP : T1pIt<(outs GPR:$Rdn), (ins GPR:$Rn, GPRsp:$sp), IIC_iALUr,
+ "add", "\t$Rdn, $sp, $Rn", []>,
T1Special<{0,0,?,?}> {
// A8.6.9 Encoding T1
- bits<4> dst;
- let Inst{7} = dst{3};
+ bits<4> Rdn;
+ let Inst{7} = Rdn{3};
let Inst{6-3} = 0b1101;
- let Inst{2-0} = dst{2-0};
+ let Inst{2-0} = Rdn{2-0};
+ let DecoderMethod = "DecodeThumbAddSPReg";
}
// ADD sp, <Rm>
-def tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
- "add\t$dst, $rhs", []>,
+def tADDspr : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, GPR:$Rm), IIC_iALUr,
+ "add", "\t$Rdn, $Rm", []>,
T1Special<{0,0,?,?}> {
// A8.6.9 Encoding T2
- bits<4> dst;
+ bits<4> Rm;
let Inst{7} = 1;
- let Inst{6-3} = dst;
+ let Inst{6-3} = Rm;
let Inst{2-0} = 0b101;
+ let DecoderMethod = "DecodeThumbAddSPReg";
}
//===----------------------------------------------------------------------===//
@@ -390,11 +409,12 @@ let isCall = 1,
Uses = [SP] in {
// Also used for Thumb2
def tBL : TIx2<0b11110, 0b11, 1,
- (outs), (ins t_bltarget:$func, variable_ops), IIC_Br,
- "bl\t$func",
+ (outs), (ins pred:$p, t_bltarget:$func, variable_ops), IIC_Br,
+ "bl${p}\t$func",
[(ARMtcall tglobaladdr:$func)]>,
Requires<[IsThumb, IsNotDarwin]> {
- bits<21> func;
+ bits<22> func;
+ let Inst{26} = func{21};
let Inst{25-16} = func{20-11};
let Inst{13} = 1;
let Inst{11} = 1;
@@ -403,8 +423,8 @@ let isCall = 1,
// ARMv5T and above, also used for Thumb2
def tBLXi : TIx2<0b11110, 0b11, 0,
- (outs), (ins t_blxtarget:$func, variable_ops), IIC_Br,
- "blx\t$func",
+ (outs), (ins pred:$p, t_blxtarget:$func, variable_ops), IIC_Br,
+ "blx${p}\t$func",
[(ARMcall tglobaladdr:$func)]>,
Requires<[IsThumb, HasV5T, IsNotDarwin]> {
bits<21> func;
@@ -416,8 +436,8 @@ let isCall = 1,
}
// Also used for Thumb2
- def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br,
- "blx\t$func",
+ def tBLXr : TI<(outs), (ins pred:$p, GPR:$func, variable_ops), IIC_Br,
+ "blx${p}\t$func",
[(ARMtcall GPR:$func)]>,
Requires<[IsThumb, HasV5T, IsNotDarwin]>,
T1Special<{1,1,1,?}> { // A6.2.3 & A8.6.24;
@@ -440,43 +460,22 @@ let isCall = 1,
Defs = [R0, R1, R2, R3, R9, R12, LR, QQQQ0, QQQQ2, QQQQ3, CPSR, FPSCR],
Uses = [R7, SP] in {
// Also used for Thumb2
- def tBLr9 : TIx2<0b11110, 0b11, 1,
- (outs), (ins pred:$p, t_bltarget:$func, variable_ops),
- IIC_Br, "bl${p}\t$func",
- [(ARMtcall tglobaladdr:$func)]>,
- Requires<[IsThumb, IsDarwin]> {
- bits<21> func;
- let Inst{25-16} = func{20-11};
- let Inst{13} = 1;
- let Inst{11} = 1;
- let Inst{10-0} = func{10-0};
- }
+ def tBLr9 : tPseudoExpand<(outs), (ins pred:$p, t_bltarget:$func, variable_ops),
+ 4, IIC_Br, [(ARMtcall tglobaladdr:$func)],
+ (tBL pred:$p, t_bltarget:$func)>,
+ Requires<[IsThumb, IsDarwin]>;
// ARMv5T and above, also used for Thumb2
- def tBLXi_r9 : TIx2<0b11110, 0b11, 0,
- (outs), (ins pred:$p, t_blxtarget:$func, variable_ops),
- IIC_Br, "blx${p}\t$func",
- [(ARMcall tglobaladdr:$func)]>,
- Requires<[IsThumb, HasV5T, IsDarwin]> {
- bits<21> func;
- let Inst{25-16} = func{20-11};
- let Inst{13} = 1;
- let Inst{11} = 1;
- let Inst{10-1} = func{10-1};
- let Inst{0} = 0; // func{0} is assumed zero
- }
+ def tBLXi_r9 : tPseudoExpand<(outs), (ins pred:$p, t_blxtarget:$func, variable_ops),
+ 4, IIC_Br, [(ARMcall tglobaladdr:$func)],
+ (tBLXi pred:$p, t_blxtarget:$func)>,
+ Requires<[IsThumb, HasV5T, IsDarwin]>;
// Also used for Thumb2
- def tBLXr_r9 : TI<(outs), (ins pred:$p, GPR:$func, variable_ops), IIC_Br,
- "blx${p}\t$func",
- [(ARMtcall GPR:$func)]>,
- Requires<[IsThumb, HasV5T, IsDarwin]>,
- T1Special<{1,1,1,?}> {
- // A6.2.3 & A8.6.24
- bits<4> func;
- let Inst{6-3} = func;
- let Inst{2-0} = 0b000;
- }
+ def tBLXr_r9 : tPseudoExpand<(outs), (ins pred:$p, GPR:$func, variable_ops),
+ 2, IIC_Br, [(ARMtcall GPR:$func)],
+ (tBLXr pred:$p, GPR:$func)>,
+ Requires<[IsThumb, HasV5T, IsDarwin]>;
// ARMv4T
def tBXr9_CALL : tPseudoInst<(outs), (ins tGPR:$func, variable_ops),
@@ -487,8 +486,8 @@ let isCall = 1,
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
let isPredicable = 1 in
- def tB : T1I<(outs), (ins t_brtarget:$target), IIC_Br,
- "b\t$target", [(br bb:$target)]>,
+ def tB : T1pI<(outs), (ins t_brtarget:$target), IIC_Br,
+ "b", "\t$target", [(br bb:$target)]>,
T1Encoding<{1,1,1,0,0,?}> {
bits<11> target;
let Inst{10-0} = target;
@@ -498,8 +497,8 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
// Just a pseudo for a tBL instruction. Needed to let regalloc know about
// the clobber of LR.
let Defs = [LR] in
- def tBfar : tPseudoExpand<(outs), (ins t_bltarget:$target),
- 4, IIC_Br, [], (tBL t_bltarget:$target)>;
+ def tBfar : tPseudoExpand<(outs), (ins t_bltarget:$target, pred:$p),
+ 4, IIC_Br, [], (tBL pred:$p, t_bltarget:$target)>;
def tBR_JTr : tPseudoInst<(outs),
(ins tGPR:$target, i32imm:$jt, i32imm:$id),
@@ -522,31 +521,6 @@ let isBranch = 1, isTerminator = 1 in
let Inst{7-0} = target;
}
-// Compare and branch on zero / non-zero
-let isBranch = 1, isTerminator = 1 in {
- def tCBZ : T1I<(outs), (ins tGPR:$Rn, t_cbtarget:$target), IIC_Br,
- "cbz\t$Rn, $target", []>,
- T1Misc<{0,0,?,1,?,?,?}> {
- // A8.6.27
- bits<6> target;
- bits<3> Rn;
- let Inst{9} = target{5};
- let Inst{7-3} = target{4-0};
- let Inst{2-0} = Rn;
- }
-
- def tCBNZ : T1I<(outs), (ins tGPR:$cmp, t_cbtarget:$target), IIC_Br,
- "cbnz\t$cmp, $target", []>,
- T1Misc<{1,0,?,1,?,?,?}> {
- // A8.6.27
- bits<6> target;
- bits<3> Rn;
- let Inst{9} = target{5};
- let Inst{7-3} = target{4-0};
- let Inst{2-0} = Rn;
- }
-}
-
// Tail calls
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
// Darwin versions.
@@ -562,9 +536,10 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
// Non-Darwin versions (the difference is R9).
let Defs = [R0, R1, R2, R3, R12, QQQQ0, QQQQ2, QQQQ3, PC],
Uses = [SP] in {
- def tTAILJMPdND : tPseudoExpand<(outs), (ins t_brtarget:$dst, variable_ops),
+ def tTAILJMPdND : tPseudoExpand<(outs),
+ (ins t_brtarget:$dst, pred:$p, variable_ops),
4, IIC_Br, [],
- (tB t_brtarget:$dst)>,
+ (tB t_brtarget:$dst, pred:$p)>,
Requires<[IsThumb, IsNotDarwin]>;
def tTAILJMPrND : tPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops),
4, IIC_Br, [],
@@ -574,11 +549,11 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
}
-// A8.6.218 Supervisor Call (Software Interrupt) -- for disassembly only
+// A8.6.218 Supervisor Call (Software Interrupt)
// A8.6.16 B: Encoding T1
// If Inst{11-8} == 0b1111 then SEE SVC
let isCall = 1, Uses = [SP] in
-def tSVC : T1pI<(outs), (ins i32imm:$imm), IIC_Br,
+def tSVC : T1pI<(outs), (ins imm0_255:$imm), IIC_Br,
"svc", "\t$imm", []>, Encoding16 {
bits<8> imm;
let Inst{15-12} = 0b1101;
@@ -653,17 +628,17 @@ defm tLDRH : thumb_ld_rr_ri_enc<0b101, 0b1000, t_addrmode_rrs2,
let AddedComplexity = 10 in
def tLDRSB : // A8.6.80
- T1pILdStEncode<0b011, (outs tGPR:$dst), (ins t_addrmode_rr:$addr),
+ T1pILdStEncode<0b011, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr),
AddrModeT1_1, IIC_iLoad_bh_r,
- "ldrsb", "\t$dst, $addr",
- [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>;
+ "ldrsb", "\t$Rt, $addr",
+ [(set tGPR:$Rt, (sextloadi8 t_addrmode_rr:$addr))]>;
let AddedComplexity = 10 in
def tLDRSH : // A8.6.84
- T1pILdStEncode<0b111, (outs tGPR:$dst), (ins t_addrmode_rr:$addr),
+ T1pILdStEncode<0b111, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr),
AddrModeT1_2, IIC_iLoad_bh_r,
- "ldrsh", "\t$dst, $addr",
- [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>;
+ "ldrsh", "\t$Rt, $addr",
+ [(set tGPR:$Rt, (sextloadi16 t_addrmode_rr:$addr))]>;
let canFoldAsLoad = 1 in
def tLDRspi : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_sp:$addr), IIC_iLoad_i,
@@ -678,7 +653,7 @@ def tLDRspi : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_sp:$addr), IIC_iLoad_i,
// Load tconstpool
// FIXME: Use ldr.n to work around a Darwin assembler bug.
-let canFoldAsLoad = 1, isReMaterializable = 1 in
+let canFoldAsLoad = 1, isReMaterializable = 1, isCodeGenOnly = 1 in
def tLDRpci : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i,
"ldr", ".n\t$Rt, $addr",
[(set tGPR:$Rt, (load (ARMWrapper tconstpool:$addr)))]>,
@@ -736,42 +711,53 @@ def tSTRspi : T1pIs<(outs), (ins tGPR:$Rt, t_addrmode_sp:$addr), IIC_iStore_i,
// Load / store multiple Instructions.
//
-multiclass thumb_ldst_mult<string asm, InstrItinClass itin,
- InstrItinClass itin_upd, bits<6> T1Enc,
- bit L_bit> {
- def IA :
- T1I<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
- itin, !strconcat(asm, "ia${p}\t$Rn, $regs"), []>,
- T1Encoding<T1Enc> {
- bits<3> Rn;
- bits<8> regs;
- let Inst{10-8} = Rn;
- let Inst{7-0} = regs;
- }
- def IA_UPD :
- T1It<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
- itin_upd, !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []>,
- T1Encoding<T1Enc> {
- bits<3> Rn;
- bits<8> regs;
- let Inst{10-8} = Rn;
- let Inst{7-0} = regs;
- }
-}
-
// These require base address to be written back or one of the loaded regs.
let neverHasSideEffects = 1 in {
let mayLoad = 1, hasExtraDefRegAllocReq = 1 in
-defm tLDM : thumb_ldst_mult<"ldm", IIC_iLoad_m, IIC_iLoad_mu,
- {1,1,0,0,1,?}, 1>;
-
+def tLDMIA : T1I<(outs), (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ IIC_iLoad_m, "ldm${p}\t$Rn, $regs", []>, T1Encoding<{1,1,0,0,1,?}> {
+ bits<3> Rn;
+ bits<8> regs;
+ let Inst{10-8} = Rn;
+ let Inst{7-0} = regs;
+}
+
+// Writeback version is just a pseudo, as there's no encoding difference.
+// Writeback happens iff the base register is not in the destination register
+// list.
+def tLDMIA_UPD :
+ InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo, GenericDomain,
+ "$Rn = $wb", IIC_iLoad_mu>,
+ PseudoInstExpansion<(tLDMIA tGPR:$Rn, pred:$p, reglist:$regs)> {
+ let Size = 2;
+ let OutOperandList = (outs GPR:$wb);
+ let InOperandList = (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops);
+ let Pattern = [];
+ let isCodeGenOnly = 1;
+ let isPseudo = 1;
+ list<Predicate> Predicates = [IsThumb];
+}
+
+// There is no non-writeback version of STM for Thumb.
let mayStore = 1, hasExtraSrcRegAllocReq = 1 in
-defm tSTM : thumb_ldst_mult<"stm", IIC_iStore_m, IIC_iStore_mu,
- {1,1,0,0,0,?}, 0>;
+def tSTMIA_UPD : Thumb1I<(outs GPR:$wb),
+ (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ AddrModeNone, 2, IIC_iStore_mu,
+ "stm${p}\t$Rn!, $regs", "$Rn = $wb", []>,
+ T1Encoding<{1,1,0,0,0,?}> {
+ bits<3> Rn;
+ bits<8> regs;
+ let Inst{10-8} = Rn;
+ let Inst{7-0} = regs;
+}
} // neverHasSideEffects
+def : InstAlias<"ldm${p} $Rn!, $regs",
+ (tLDMIA tGPR:$Rn, pred:$p, reglist:$regs)>,
+ Requires<[IsThumb, IsThumb1Only]>;
+
let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in
def tPOP : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops),
IIC_iPop,
@@ -876,7 +862,7 @@ def tADC : // A8.6.2
// Add immediate
def tADDi3 : // A8.6.4 T1
- T1sIGenEncodeImm<0b01110, (outs tGPR:$Rd), (ins tGPR:$Rm, i32imm:$imm3),
+ T1sIGenEncodeImm<0b01110, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_7:$imm3),
IIC_iALUi,
"add", "\t$Rd, $Rm, $imm3",
[(set tGPR:$Rd, (add tGPR:$Rm, imm0_7:$imm3))]> {
@@ -885,8 +871,8 @@ def tADDi3 : // A8.6.4 T1
}
def tADDi8 : // A8.6.4 T2
- T1sItGenEncodeImm<{1,1,0,?,?}, (outs tGPR:$Rdn), (ins tGPR:$Rn, i32imm:$imm8),
- IIC_iALUi,
+ T1sItGenEncodeImm<{1,1,0,?,?}, (outs tGPR:$Rdn),
+ (ins tGPR:$Rn, imm0_255:$imm8), IIC_iALUi,
"add", "\t$Rdn, $imm8",
[(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255:$imm8))]>;
@@ -920,10 +906,10 @@ def tAND : // A8.6.12
// ASR immediate
def tASRri : // A8.6.14
- T1sIGenEncodeImm<{0,1,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, i32imm:$imm5),
+ T1sIGenEncodeImm<{0,1,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5),
IIC_iMOVsi,
"asr", "\t$Rd, $Rm, $imm5",
- [(set tGPR:$Rd, (sra tGPR:$Rm, (i32 imm:$imm5)))]> {
+ [(set tGPR:$Rd, (sra tGPR:$Rm, (i32 imm_sr:$imm5)))]> {
bits<5> imm5;
let Inst{10-6} = imm5;
}
@@ -962,7 +948,7 @@ def tCMNz : // A8.6.33
// CMP immediate
let isCompare = 1, Defs = [CPSR] in {
-def tCMPi8 : T1pI<(outs), (ins tGPR:$Rn, i32imm:$imm8), IIC_iCMPi,
+def tCMPi8 : T1pI<(outs), (ins tGPR:$Rn, imm0_255:$imm8), IIC_iCMPi,
"cmp", "\t$Rn, $imm8",
[(ARMcmp tGPR:$Rn, imm0_255:$imm8)]>,
T1General<{1,0,1,?,?}> {
@@ -1003,7 +989,7 @@ def tEOR : // A8.6.45
// LSL immediate
def tLSLri : // A8.6.88
- T1sIGenEncodeImm<{0,0,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, i32imm:$imm5),
+ T1sIGenEncodeImm<{0,0,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_31:$imm5),
IIC_iMOVsi,
"lsl", "\t$Rd, $Rm, $imm5",
[(set tGPR:$Rd, (shl tGPR:$Rm, (i32 imm:$imm5)))]> {
@@ -1020,10 +1006,10 @@ def tLSLrr : // A8.6.89
// LSR immediate
def tLSRri : // A8.6.90
- T1sIGenEncodeImm<{0,0,1,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, i32imm:$imm5),
+ T1sIGenEncodeImm<{0,0,1,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5),
IIC_iMOVsi,
"lsr", "\t$Rd, $Rm, $imm5",
- [(set tGPR:$Rd, (srl tGPR:$Rm, (i32 imm:$imm5)))]> {
+ [(set tGPR:$Rd, (srl tGPR:$Rm, (i32 imm_sr:$imm5)))]> {
bits<5> imm5;
let Inst{10-6} = imm5;
}
@@ -1047,6 +1033,10 @@ def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi,
let Inst{10-8} = Rd;
let Inst{7-0} = imm8;
}
+// Because we have an explicit tMOVSr below, we need an alias to handle
+// the immediate "movs" form here. Blech.
+def : tInstAlias <"movs $Rdn, $imm",
+ (tMOVi8 tGPR:$Rdn, CPSR, imm0_255:$imm, 14, 0)>;
// A7-73: MOV(2) - mov setting flag.
@@ -1077,10 +1067,19 @@ def tMOVSr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr,
// Multiply register
let isCommutable = 1 in
def tMUL : // A8.6.105 T1
- T1sItDPEncode<0b1101, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
- IIC_iMUL32,
- "mul", "\t$Rdn, $Rm, $Rdn",
- [(set tGPR:$Rdn, (mul tGPR:$Rn, tGPR:$Rm))]>;
+ Thumb1sI<(outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), AddrModeNone, 2,
+ IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm", "$Rm = $Rd",
+ [(set tGPR:$Rd, (mul tGPR:$Rn, tGPR:$Rm))]>,
+ T1DataProcessing<0b1101> {
+ bits<3> Rd;
+ bits<3> Rn;
+ let Inst{5-3} = Rn;
+ let Inst{2-0} = Rd;
+ let AsmMatchConverter = "cvtThumbMultiply";
+}
+
+def :tInstAlias<"mul${s}${p} $Rdm, $Rn", (tMUL tGPR:$Rdm, s_cc_out:$s, tGPR:$Rn,
+ pred:$p)>;
// Move inverse register
def tMVN : // A8.6.107
@@ -1132,6 +1131,9 @@ def tRSB : // A8.6.141
"rsb", "\t$Rd, $Rn, #0",
[(set tGPR:$Rd, (ineg tGPR:$Rn))]>;
+def : tInstAlias<"neg${s}${p} $Rd, $Rm",
+ (tRSB tGPR:$Rd, s_cc_out:$s, tGPR:$Rm, pred:$p)>;
+
// Subtract with carry register
let Uses = [CPSR] in
def tSBC : // A8.6.151
@@ -1142,7 +1144,7 @@ def tSBC : // A8.6.151
// Subtract immediate
def tSUBi3 : // A8.6.210 T1
- T1sIGenEncodeImm<0b01111, (outs tGPR:$Rd), (ins tGPR:$Rm, i32imm:$imm3),
+ T1sIGenEncodeImm<0b01111, (outs tGPR:$Rd), (ins tGPR:$Rm, imm0_7:$imm3),
IIC_iALUi,
"sub", "\t$Rd, $Rm, $imm3",
[(set tGPR:$Rd, (add tGPR:$Rm, imm0_7_neg:$imm3))]> {
@@ -1151,8 +1153,8 @@ def tSUBi3 : // A8.6.210 T1
}
def tSUBi8 : // A8.6.210 T2
- T1sItGenEncodeImm<{1,1,1,?,?}, (outs tGPR:$Rdn), (ins tGPR:$Rn, i32imm:$imm8),
- IIC_iALUi,
+ T1sItGenEncodeImm<{1,1,1,?,?}, (outs tGPR:$Rdn),
+ (ins tGPR:$Rn, imm0_255:$imm8), IIC_iALUi,
"sub", "\t$Rdn, $imm8",
[(set tGPR:$Rdn, (add tGPR:$Rn, imm8_255_neg:$imm8))]>;
@@ -1163,8 +1165,6 @@ def tSUBrr : // A8.6.212
"sub", "\t$Rd, $Rn, $Rm",
[(set tGPR:$Rd, (sub tGPR:$Rn, tGPR:$Rm))]>;
-// TODO: A7-96: STMIA - store multiple.
-
// Sign-extend byte
def tSXTB : // A8.6.222
T1pIMiscEncode<{0,0,1,0,0,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
@@ -1216,12 +1216,13 @@ let usesCustomInserter = 1 in // Expanded after instruction selection.
// assembler.
def tADR : T1I<(outs tGPR:$Rd), (ins t_adrlabel:$addr, pred:$p),
- IIC_iALUi, "adr{$p}\t$Rd, #$addr", []>,
+ IIC_iALUi, "adr{$p}\t$Rd, $addr", []>,
T1Encoding<{1,0,1,0,0,?}> {
bits<3> Rd;
bits<8> addr;
let Inst{10-8} = Rd;
let Inst{7-0} = addr;
+ let DecoderMethod = "DecodeThumbAddSpecialReg";
}
let neverHasSideEffects = 1, isReMaterializable = 1 in
@@ -1361,6 +1362,31 @@ def : T1Pat<(sextloadi16 t_addrmode_rrs2:$addr),
def : T1Pat<(sextloadi16 t_addrmode_is2:$addr),
(tASRri (tLSLri (tLDRHi t_addrmode_is2:$addr), 16), 16)>;
+def : T1Pat<(atomic_load_8 t_addrmode_is1:$src),
+ (tLDRBi t_addrmode_is1:$src)>;
+def : T1Pat<(atomic_load_8 t_addrmode_rrs1:$src),
+ (tLDRBr t_addrmode_rrs1:$src)>;
+def : T1Pat<(atomic_load_16 t_addrmode_is2:$src),
+ (tLDRHi t_addrmode_is2:$src)>;
+def : T1Pat<(atomic_load_16 t_addrmode_rrs2:$src),
+ (tLDRHr t_addrmode_rrs2:$src)>;
+def : T1Pat<(atomic_load_32 t_addrmode_is4:$src),
+ (tLDRi t_addrmode_is4:$src)>;
+def : T1Pat<(atomic_load_32 t_addrmode_rrs4:$src),
+ (tLDRr t_addrmode_rrs4:$src)>;
+def : T1Pat<(atomic_store_8 t_addrmode_is1:$ptr, tGPR:$val),
+ (tSTRBi tGPR:$val, t_addrmode_is1:$ptr)>;
+def : T1Pat<(atomic_store_8 t_addrmode_rrs1:$ptr, tGPR:$val),
+ (tSTRBr tGPR:$val, t_addrmode_rrs1:$ptr)>;
+def : T1Pat<(atomic_store_16 t_addrmode_is2:$ptr, tGPR:$val),
+ (tSTRHi tGPR:$val, t_addrmode_is2:$ptr)>;
+def : T1Pat<(atomic_store_16 t_addrmode_rrs2:$ptr, tGPR:$val),
+ (tSTRHr tGPR:$val, t_addrmode_rrs2:$ptr)>;
+def : T1Pat<(atomic_store_32 t_addrmode_is4:$ptr, tGPR:$val),
+ (tSTRi tGPR:$val, t_addrmode_is4:$ptr)>;
+def : T1Pat<(atomic_store_32 t_addrmode_rrs4:$ptr, tGPR:$val),
+ (tSTRr tGPR:$val, t_addrmode_rrs4:$ptr)>;
+
// Large immediate handling.
// Two piece imms.
@@ -1395,3 +1421,16 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
2, IIC_Br, [(brind GPR:$Rm)],
(tMOVr PC, GPR:$Rm, pred:$p)>;
}
+
+
+// In Thumb1, "nop" is encoded as a "mov r8, r8". Technically, the bf00
+// encoding is available on ARMv6K, but we don't differentiate that finely.
+def : InstAlias<"nop", (tMOVr R8, R8, 14, 0)>,Requires<[IsThumb, IsThumb1Only]>;
+
+
+// For round-trip assembly/disassembly, we have to handle a CPS instruction
+// without any iflags. That's not, strictly speaking, valid syntax, but it's
+// a useful extention and assembles to defined behaviour (the insn does
+// nothing).
+def : tInstAlias<"cps$imod", (tCPS imod_op:$imod, 0)>;
+def : tInstAlias<"cps$imod", (tCPS imod_op:$imod, 0)>;
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index c2c6cbc..471ec29 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -12,13 +12,32 @@
//===----------------------------------------------------------------------===//
// IT block predicate field
+def it_pred_asmoperand : AsmOperandClass {
+ let Name = "ITCondCode";
+ let ParserMethod = "parseITCondCode";
+}
def it_pred : Operand<i32> {
let PrintMethod = "printMandatoryPredicateOperand";
+ let ParserMatchClass = it_pred_asmoperand;
}
// IT block condition mask
+def it_mask_asmoperand : AsmOperandClass { let Name = "ITMask"; }
def it_mask : Operand<i32> {
let PrintMethod = "printThumbITMask";
+ let ParserMatchClass = it_mask_asmoperand;
+}
+
+// t2_shift_imm: An integer that encodes a shift amount and the type of shift
+// (asr or lsl). The 6-bit immediate encodes as:
+// {5} 0 ==> lsl
+// 1 asr
+// {4-0} imm5 shift amount.
+// asr #32 not allowed
+def t2_shift_imm : Operand<i32> {
+ let PrintMethod = "printShiftImmOperand";
+ let ParserMatchClass = ShifterImmAsmOperand;
+ let DecoderMethod = "DecodeT2ShifterImmOperand";
}
// Shifted operands. No register controlled shifts for Thumb2.
@@ -28,6 +47,8 @@ def t2_so_reg : Operand<i32>, // reg imm
[shl,srl,sra,rotr]> {
let EncoderMethod = "getT2SORegOpValue";
let PrintMethod = "printT2SOOperand";
+ let DecoderMethod = "DecodeSORegImmOperand";
+ let ParserMatchClass = ShiftedImmAsmOperand;
let MIOperandInfo = (ops rGPR, i32imm);
}
@@ -50,6 +71,7 @@ def t2_so_imm : Operand<i32>, ImmLeaf<i32, [{
}]> {
let ParserMatchClass = t2_so_imm_asmoperand;
let EncoderMethod = "getT2SOImmOpValue";
+ let DecoderMethod = "DecodeT2SOImm";
}
// t2_so_imm_not - Match an immediate that is a complement
@@ -65,11 +87,6 @@ def t2_so_imm_neg : Operand<i32>,
return ARM_AM::getT2SOImmVal(-((uint32_t)N->getZExtValue())) != -1;
}], t2_so_imm_neg_XFORM>;
-/// imm1_31 predicate - True if the 32-bit immediate is in the range [1,31].
-def imm1_31 : ImmLeaf<i32, [{
- return (int32_t)Imm >= 1 && (int32_t)Imm < 32;
-}]>;
-
/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
def imm0_4095 : Operand<i32>,
ImmLeaf<i32, [{
@@ -96,17 +113,20 @@ def lo5AllOne : PatLeaf<(i32 imm), [{
// Define Thumb2 specific addressing modes.
// t2addrmode_imm12 := reg + imm12
+def t2addrmode_imm12_asmoperand : AsmOperandClass {let Name="MemUImm12Offset";}
def t2addrmode_imm12 : Operand<i32>,
ComplexPattern<i32, 2, "SelectT2AddrModeImm12", []> {
let PrintMethod = "printAddrModeImm12Operand";
let EncoderMethod = "getAddrModeImm12OpValue";
+ let DecoderMethod = "DecodeT2AddrModeImm12";
+ let ParserMatchClass = t2addrmode_imm12_asmoperand;
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
- let ParserMatchClass = MemMode5AsmOperand;
}
// t2ldrlabel := imm12
def t2ldrlabel : Operand<i32> {
let EncoderMethod = "getAddrModeImm12OpValue";
+ let PrintMethod = "printT2LdrLabelOperand";
}
@@ -116,13 +136,36 @@ def t2adrlabel : Operand<i32> {
}
+// t2addrmode_posimm8 := reg + imm8
+def MemPosImm8OffsetAsmOperand : AsmOperandClass {let Name="MemPosImm8Offset";}
+def t2addrmode_posimm8 : Operand<i32> {
+ let PrintMethod = "printT2AddrModeImm8Operand";
+ let EncoderMethod = "getT2AddrModeImm8OpValue";
+ let DecoderMethod = "DecodeT2AddrModeImm8";
+ let ParserMatchClass = MemPosImm8OffsetAsmOperand;
+ let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
+}
+
+// t2addrmode_negimm8 := reg - imm8
+def MemNegImm8OffsetAsmOperand : AsmOperandClass {let Name="MemNegImm8Offset";}
+def t2addrmode_negimm8 : Operand<i32>,
+ ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
+ let PrintMethod = "printT2AddrModeImm8Operand";
+ let EncoderMethod = "getT2AddrModeImm8OpValue";
+ let DecoderMethod = "DecodeT2AddrModeImm8";
+ let ParserMatchClass = MemNegImm8OffsetAsmOperand;
+ let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
+}
+
// t2addrmode_imm8 := reg +/- imm8
+def MemImm8OffsetAsmOperand : AsmOperandClass { let Name = "MemImm8Offset"; }
def t2addrmode_imm8 : Operand<i32>,
ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
let PrintMethod = "printT2AddrModeImm8Operand";
let EncoderMethod = "getT2AddrModeImm8OpValue";
+ let DecoderMethod = "DecodeT2AddrModeImm8";
+ let ParserMatchClass = MemImm8OffsetAsmOperand;
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
- let ParserMatchClass = MemMode5AsmOperand;
}
def t2am_imm8_offset : Operand<i32>,
@@ -130,38 +173,61 @@ def t2am_imm8_offset : Operand<i32>,
[], [SDNPWantRoot]> {
let PrintMethod = "printT2AddrModeImm8OffsetOperand";
let EncoderMethod = "getT2AddrModeImm8OffsetOpValue";
- let ParserMatchClass = MemMode5AsmOperand;
+ let DecoderMethod = "DecodeT2Imm8";
}
// t2addrmode_imm8s4 := reg +/- (imm8 << 2)
+def MemImm8s4OffsetAsmOperand : AsmOperandClass {let Name = "MemImm8s4Offset";}
def t2addrmode_imm8s4 : Operand<i32> {
let PrintMethod = "printT2AddrModeImm8s4Operand";
let EncoderMethod = "getT2AddrModeImm8s4OpValue";
+ let DecoderMethod = "DecodeT2AddrModeImm8s4";
+ let ParserMatchClass = MemImm8s4OffsetAsmOperand;
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
- let ParserMatchClass = MemMode5AsmOperand;
}
+def t2am_imm8s4_offset_asmoperand : AsmOperandClass { let Name = "Imm8s4"; }
def t2am_imm8s4_offset : Operand<i32> {
let PrintMethod = "printT2AddrModeImm8s4OffsetOperand";
+ let EncoderMethod = "getT2Imm8s4OpValue";
+ let DecoderMethod = "DecodeT2Imm8S4";
+}
+
+// t2addrmode_imm0_1020s4 := reg + (imm8 << 2)
+def MemImm0_1020s4OffsetAsmOperand : AsmOperandClass {
+ let Name = "MemImm0_1020s4Offset";
+}
+def t2addrmode_imm0_1020s4 : Operand<i32> {
+ let PrintMethod = "printT2AddrModeImm0_1020s4Operand";
+ let EncoderMethod = "getT2AddrModeImm0_1020s4OpValue";
+ let DecoderMethod = "DecodeT2AddrModeImm0_1020s4";
+ let ParserMatchClass = MemImm0_1020s4OffsetAsmOperand;
+ let MIOperandInfo = (ops GPRnopc:$base, i32imm:$offsimm);
}
// t2addrmode_so_reg := reg + (reg << imm2)
+def t2addrmode_so_reg_asmoperand : AsmOperandClass {let Name="T2MemRegOffset";}
def t2addrmode_so_reg : Operand<i32>,
ComplexPattern<i32, 3, "SelectT2AddrModeSoReg", []> {
let PrintMethod = "printT2AddrModeSoRegOperand";
let EncoderMethod = "getT2AddrModeSORegOpValue";
+ let DecoderMethod = "DecodeT2AddrModeSOReg";
+ let ParserMatchClass = t2addrmode_so_reg_asmoperand;
let MIOperandInfo = (ops GPR:$base, rGPR:$offsreg, i32imm:$offsimm);
- let ParserMatchClass = MemMode5AsmOperand;
}
-// t2addrmode_reg := reg
-// Used by load/store exclusive instructions. Useful to enable right assembly
-// parsing and printing. Not used for any codegen matching.
-//
-def t2addrmode_reg : Operand<i32> {
- let PrintMethod = "printAddrMode7Operand";
- let MIOperandInfo = (ops GPR);
- let ParserMatchClass = MemMode7AsmOperand;
+// Addresses for the TBB/TBH instructions.
+def addrmode_tbb_asmoperand : AsmOperandClass { let Name = "MemTBB"; }
+def addrmode_tbb : Operand<i32> {
+ let PrintMethod = "printAddrModeTBB";
+ let ParserMatchClass = addrmode_tbb_asmoperand;
+ let MIOperandInfo = (ops GPR:$Rn, rGPR:$Rm);
+}
+def addrmode_tbh_asmoperand : AsmOperandClass { let Name = "MemTBH"; }
+def addrmode_tbh : Operand<i32> {
+ let PrintMethod = "printAddrModeTBH";
+ let ParserMatchClass = addrmode_tbh_asmoperand;
+ let MIOperandInfo = (ops GPR:$Rn, rGPR:$Rm);
}
//===----------------------------------------------------------------------===//
@@ -419,47 +485,6 @@ class T2MulLong<bits<3> opc22_20, bits<4> opc7_4,
}
-/// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
-/// unary operation that produces a value. These are predicable and can be
-/// changed to modify CPSR.
-multiclass T2I_un_irs<bits<4> opcod, string opc,
- InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
- PatFrag opnode, bit Cheap = 0, bit ReMat = 0> {
- // shifted imm
- def i : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), iii,
- opc, "\t$Rd, $imm",
- [(set rGPR:$Rd, (opnode t2_so_imm:$imm))]> {
- let isAsCheapAsAMove = Cheap;
- let isReMaterializable = ReMat;
- let Inst{31-27} = 0b11110;
- let Inst{25} = 0;
- let Inst{24-21} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15} = 0;
- }
- // register
- def r : T2sTwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), iir,
- opc, ".w\t$Rd, $Rm",
- [(set rGPR:$Rd, (opnode rGPR:$Rm))]> {
- let Inst{31-27} = 0b11101;
- let Inst{26-25} = 0b01;
- let Inst{24-21} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{14-12} = 0b000; // imm3
- let Inst{7-6} = 0b00; // imm2
- let Inst{5-4} = 0b00; // type
- }
- // shifted register
- def s : T2sOneRegShiftedReg<(outs rGPR:$Rd), (ins t2_so_reg:$ShiftedRm), iis,
- opc, ".w\t$Rd, $ShiftedRm",
- [(set rGPR:$Rd, (opnode t2_so_reg:$ShiftedRm))]> {
- let Inst{31-27} = 0b11101;
- let Inst{26-25} = 0b01;
- let Inst{24-21} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- }
-}
-
/// T2I_bin_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
/// binary operation that produces a value. These are predicable and can be
/// changed to modify CPSR.
@@ -500,21 +525,18 @@ multiclass T2I_bin_irs<bits<4> opcod, string opc,
}
// Assembly aliases for optional destination operand when it's the same
// as the source operand.
- def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $imm"),
+ def : t2InstAlias<!strconcat(opc, "${s}${p} $Rdn, $imm"),
(!cast<Instruction>(!strconcat(baseOpc, "ri")) rGPR:$Rdn, rGPR:$Rdn,
t2_so_imm:$imm, pred:$p,
- cc_out:$s)>,
- Requires<[IsThumb2]>;
- def : InstAlias<!strconcat(opc, "${s}${p}", wide, " $Rdn, $Rm"),
+ cc_out:$s)>;
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", wide, " $Rdn, $Rm"),
(!cast<Instruction>(!strconcat(baseOpc, "rr")) rGPR:$Rdn, rGPR:$Rdn,
rGPR:$Rm, pred:$p,
- cc_out:$s)>,
- Requires<[IsThumb2]>;
- def : InstAlias<!strconcat(opc, "${s}${p}", wide, " $Rdn, $shift"),
+ cc_out:$s)>;
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", wide, " $Rdn, $shift"),
(!cast<Instruction>(!strconcat(baseOpc, "rs")) rGPR:$Rdn, rGPR:$Rdn,
t2_so_reg:$shift, pred:$p,
- cc_out:$s)>,
- Requires<[IsThumb2]>;
+ cc_out:$s)>;
}
/// T2I_bin_w_irs - Same as T2I_bin_irs except these operations need
@@ -522,7 +544,27 @@ multiclass T2I_bin_irs<bits<4> opcod, string opc,
multiclass T2I_bin_w_irs<bits<4> opcod, string opc,
InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
PatFrag opnode, string baseOpc, bit Commutable = 0> :
- T2I_bin_irs<opcod, opc, iii, iir, iis, opnode, baseOpc, Commutable, ".w">;
+ T2I_bin_irs<opcod, opc, iii, iir, iis, opnode, baseOpc, Commutable, ".w"> {
+ // Assembler aliases w/o the ".w" suffix.
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rd, $Rn, $Rm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rr")) rGPR:$Rd, rGPR:$Rn,
+ rGPR:$Rm, pred:$p,
+ cc_out:$s)>;
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rd, $Rn, $shift"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rs")) rGPR:$Rd, rGPR:$Rn,
+ t2_so_reg:$shift, pred:$p,
+ cc_out:$s)>;
+
+ // and with the optional destination operand, too.
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rdn, $Rm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rr")) rGPR:$Rdn, rGPR:$Rdn,
+ rGPR:$Rm, pred:$p,
+ cc_out:$s)>;
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rdn, $shift"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rs")) rGPR:$Rdn, rGPR:$Rdn,
+ t2_so_reg:$shift, pred:$p,
+ cc_out:$s)>;
+}
/// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are
/// reversed. The 'rr' form is only defined for the disassembler; for codegen
@@ -563,45 +605,28 @@ multiclass T2I_rbin_irs<bits<4> opcod, string opc, PatFrag opnode> {
/// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the
/// instruction modifies the CPSR register.
-let isCodeGenOnly = 1, Defs = [CPSR] in {
+///
+/// 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 T2I_bin_s_irs<bits<4> opcod, string opc,
InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
PatFrag opnode, bit Commutable = 0> {
// shifted imm
- def ri : T2TwoRegImm<
+ def ri : T2sTwoRegImm<
(outs rGPR:$Rd), (ins GPR:$Rn, t2_so_imm:$imm), iii,
- !strconcat(opc, "s"), ".w\t$Rd, $Rn, $imm",
- [(set rGPR:$Rd, (opnode GPR:$Rn, t2_so_imm:$imm))]> {
- let Inst{31-27} = 0b11110;
- let Inst{25} = 0;
- let Inst{24-21} = opcod;
- let Inst{20} = 1; // The S bit.
- let Inst{15} = 0;
- }
+ opc, ".w\t$Rd, $Rn, $imm",
+ [(set rGPR:$Rd, CPSR, (opnode GPR:$Rn, t2_so_imm:$imm))]>;
// register
- def rr : T2ThreeReg<
+ def rr : T2sThreeReg<
(outs rGPR:$Rd), (ins GPR:$Rn, rGPR:$Rm), iir,
- !strconcat(opc, "s"), ".w\t$Rd, $Rn, $Rm",
- [(set rGPR:$Rd, (opnode GPR:$Rn, rGPR:$Rm))]> {
- let isCommutable = Commutable;
- let Inst{31-27} = 0b11101;
- let Inst{26-25} = 0b01;
- let Inst{24-21} = opcod;
- let Inst{20} = 1; // The S bit.
- let Inst{14-12} = 0b000; // imm3
- let Inst{7-6} = 0b00; // imm2
- let Inst{5-4} = 0b00; // type
- }
+ opc, ".w\t$Rd, $Rn, $Rm",
+ [(set rGPR:$Rd, CPSR, (opnode GPR:$Rn, rGPR:$Rm))]>;
// shifted register
- def rs : T2TwoRegShiftedReg<
+ def rs : T2sTwoRegShiftedReg<
(outs rGPR:$Rd), (ins GPR:$Rn, t2_so_reg:$ShiftedRm), iis,
- !strconcat(opc, "s"), ".w\t$Rd, $Rn, $ShiftedRm",
- [(set rGPR:$Rd, (opnode GPR:$Rn, t2_so_reg:$ShiftedRm))]> {
- let Inst{31-27} = 0b11101;
- let Inst{26-25} = 0b01;
- let Inst{24-21} = opcod;
- let Inst{20} = 1; // The S bit.
- }
+ opc, ".w\t$Rd, $Rn, $ShiftedRm",
+ [(set rGPR:$Rd, CPSR, (opnode GPR:$Rn, t2_so_reg:$ShiftedRm))]>;
}
}
@@ -614,9 +639,9 @@ multiclass T2I_bin_ii12rs<bits<3> op23_21, string opc, PatFrag opnode,
// in particular for taking the address of a local.
let isReMaterializable = 1 in {
def ri : T2sTwoRegImm<
- (outs rGPR:$Rd), (ins GPR:$Rn, t2_so_imm:$imm), IIC_iALUi,
- opc, ".w\t$Rd, $Rn, $imm",
- [(set rGPR:$Rd, (opnode GPR:$Rn, t2_so_imm:$imm))]> {
+ (outs GPRnopc:$Rd), (ins GPRnopc:$Rn, t2_so_imm:$imm), IIC_iALUi,
+ opc, ".w\t$Rd, $Rn, $imm",
+ [(set GPRnopc:$Rd, (opnode GPRnopc:$Rn, t2_so_imm:$imm))]> {
let Inst{31-27} = 0b11110;
let Inst{25} = 0;
let Inst{24} = 1;
@@ -626,9 +651,9 @@ multiclass T2I_bin_ii12rs<bits<3> op23_21, string opc, PatFrag opnode,
}
// 12-bit imm
def ri12 : T2I<
- (outs rGPR:$Rd), (ins GPR:$Rn, imm0_4095:$imm), IIC_iALUi,
+ (outs GPRnopc:$Rd), (ins GPR:$Rn, imm0_4095:$imm), IIC_iALUi,
!strconcat(opc, "w"), "\t$Rd, $Rn, $imm",
- [(set rGPR:$Rd, (opnode GPR:$Rn, imm0_4095:$imm))]> {
+ [(set GPRnopc:$Rd, (opnode GPR:$Rn, imm0_4095:$imm))]> {
bits<4> Rd;
bits<4> Rn;
bits<12> imm;
@@ -644,9 +669,9 @@ multiclass T2I_bin_ii12rs<bits<3> op23_21, string opc, PatFrag opnode,
let Inst{7-0} = imm{7-0};
}
// register
- def rr : T2sThreeReg<(outs rGPR:$Rd), (ins GPR:$Rn, rGPR:$Rm), IIC_iALUr,
- opc, ".w\t$Rd, $Rn, $Rm",
- [(set rGPR:$Rd, (opnode GPR:$Rn, rGPR:$Rm))]> {
+ def rr : T2sThreeReg<(outs GPRnopc:$Rd), (ins GPRnopc:$Rn, rGPR:$Rm),
+ IIC_iALUr, opc, ".w\t$Rd, $Rn, $Rm",
+ [(set GPRnopc:$Rd, (opnode GPRnopc:$Rn, rGPR:$Rm))]> {
let isCommutable = Commutable;
let Inst{31-27} = 0b11101;
let Inst{26-25} = 0b01;
@@ -658,9 +683,9 @@ multiclass T2I_bin_ii12rs<bits<3> op23_21, string opc, PatFrag opnode,
}
// shifted register
def rs : T2sTwoRegShiftedReg<
- (outs rGPR:$Rd), (ins GPR:$Rn, t2_so_reg:$ShiftedRm),
+ (outs GPRnopc:$Rd), (ins GPRnopc:$Rn, t2_so_reg:$ShiftedRm),
IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm",
- [(set rGPR:$Rd, (opnode GPR:$Rn, t2_so_reg:$ShiftedRm))]> {
+ [(set GPRnopc:$Rd, (opnode GPRnopc:$Rn, t2_so_reg:$ShiftedRm))]> {
let Inst{31-27} = 0b11101;
let Inst{26-25} = 0b01;
let Inst{24} = 1;
@@ -671,13 +696,13 @@ multiclass T2I_bin_ii12rs<bits<3> op23_21, string opc, PatFrag opnode,
/// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns
/// for a binary operation that produces a value and use the carry
/// bit. It's not predicable.
-let Uses = [CPSR] in {
+let Defs = [CPSR], Uses = [CPSR] in {
multiclass T2I_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
bit Commutable = 0> {
// shifted imm
def ri : T2sTwoRegImm<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm),
IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
- [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>,
+ [(set rGPR:$Rd, CPSR, (opnode rGPR:$Rn, t2_so_imm:$imm, CPSR))]>,
Requires<[IsThumb2]> {
let Inst{31-27} = 0b11110;
let Inst{25} = 0;
@@ -687,7 +712,7 @@ multiclass T2I_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
// register
def rr : T2sThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr,
opc, ".w\t$Rd, $Rn, $Rm",
- [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>,
+ [(set rGPR:$Rd, CPSR, (opnode rGPR:$Rn, rGPR:$Rm, CPSR))]>,
Requires<[IsThumb2]> {
let isCommutable = Commutable;
let Inst{31-27} = 0b11101;
@@ -701,7 +726,7 @@ multiclass T2I_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
def rs : T2sTwoRegShiftedReg<
(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm",
- [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>,
+ [(set rGPR:$Rd, CPSR, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm, CPSR))]>,
Requires<[IsThumb2]> {
let Inst{31-27} = 0b11101;
let Inst{26-25} = 0b01;
@@ -710,64 +735,35 @@ multiclass T2I_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
}
}
-// Carry setting variants
-// NOTE: CPSR def omitted because it will be handled by the custom inserter.
-let usesCustomInserter = 1 in {
-multiclass T2I_adde_sube_s_irs<PatFrag opnode, bit Commutable = 0> {
- // shifted imm
- def ri : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm),
- 4, IIC_iALUi,
- [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>;
- // register
- def rr : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm),
- 4, IIC_iALUr,
- [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]> {
- let isCommutable = Commutable;
- }
- // shifted register
- def rs : t2PseudoInst<
- (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
- 4, IIC_iALUsi,
- [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>;
-}
-}
-
/// T2I_rbin_s_is - Same as T2I_rbin_irs except sets 's' bit and the register
/// version is not needed since this is only for codegen.
-let isCodeGenOnly = 1, Defs = [CPSR] in {
+///
+/// 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 T2I_rbin_s_is<bits<4> opcod, string opc, PatFrag opnode> {
// shifted imm
- def ri : T2TwoRegImm<
+ def ri : T2sTwoRegImm<
(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), IIC_iALUi,
- !strconcat(opc, "s"), ".w\t$Rd, $Rn, $imm",
- [(set rGPR:$Rd, (opnode t2_so_imm:$imm, rGPR:$Rn))]> {
- let Inst{31-27} = 0b11110;
- let Inst{25} = 0;
- let Inst{24-21} = opcod;
- let Inst{20} = 1; // The S bit.
- let Inst{15} = 0;
- }
+ opc, ".w\t$Rd, $Rn, $imm",
+ [(set rGPR:$Rd, CPSR, (opnode t2_so_imm:$imm, rGPR:$Rn))]>;
// shifted register
- def rs : T2TwoRegShiftedReg<
+ def rs : T2sTwoRegShiftedReg<
(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
- IIC_iALUsi, !strconcat(opc, "s"), "\t$Rd, $Rn, $ShiftedRm",
- [(set rGPR:$Rd, (opnode t2_so_reg:$ShiftedRm, rGPR:$Rn))]> {
- let Inst{31-27} = 0b11101;
- let Inst{26-25} = 0b01;
- let Inst{24-21} = opcod;
- let Inst{20} = 1; // The S bit.
- }
+ IIC_iALUsi, opc, "\t$Rd, $Rn, $ShiftedRm",
+ [(set rGPR:$Rd, CPSR, (opnode t2_so_reg:$ShiftedRm, rGPR:$Rn))]>;
}
}
/// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift /
// rotate operation that produces a value.
-multiclass T2I_sh_ir<bits<2> opcod, string opc, PatFrag opnode> {
+multiclass T2I_sh_ir<bits<2> opcod, string opc, Operand ty, PatFrag opnode,
+ string baseOpc> {
// 5-bit imm
def ri : T2sTwoRegShiftImm<
- (outs rGPR:$Rd), (ins rGPR:$Rm, i32imm:$imm), IIC_iMOVsi,
+ (outs rGPR:$Rd), (ins rGPR:$Rm, ty:$imm), IIC_iMOVsi,
opc, ".w\t$Rd, $Rm, $imm",
- [(set rGPR:$Rd, (opnode rGPR:$Rm, imm1_31:$imm))]> {
+ [(set rGPR:$Rd, (opnode rGPR:$Rm, (i32 ty:$imm)))]> {
let Inst{31-27} = 0b11101;
let Inst{26-21} = 0b010010;
let Inst{19-16} = 0b1111; // Rn
@@ -784,20 +780,50 @@ multiclass T2I_sh_ir<bits<2> opcod, string opc, PatFrag opnode> {
let Inst{15-12} = 0b1111;
let Inst{7-4} = 0b0000;
}
+
+ // Optional destination register
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", ".w $Rdn, $imm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "ri")) rGPR:$Rdn, rGPR:$Rdn,
+ ty:$imm, pred:$p,
+ cc_out:$s)>;
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", ".w $Rdn, $Rm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rr")) rGPR:$Rdn, rGPR:$Rdn,
+ rGPR:$Rm, pred:$p,
+ cc_out:$s)>;
+
+ // Assembler aliases w/o the ".w" suffix.
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rd, $Rn, $imm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "ri")) rGPR:$Rd, rGPR:$Rn,
+ ty:$imm, pred:$p,
+ cc_out:$s)>;
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rd, $Rn, $Rm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rr")) rGPR:$Rd, rGPR:$Rn,
+ rGPR:$Rm, pred:$p,
+ cc_out:$s)>;
+
+ // and with the optional destination operand, too.
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rdn, $imm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "ri")) rGPR:$Rdn, rGPR:$Rdn,
+ ty:$imm, pred:$p,
+ cc_out:$s)>;
+ def : t2InstAlias<!strconcat(opc, "${s}${p}", " $Rdn, $Rm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rr")) rGPR:$Rdn, rGPR:$Rdn,
+ rGPR:$Rm, pred:$p,
+ cc_out:$s)>;
}
/// T2I_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test
/// patterns. Similar to T2I_bin_irs except the instruction does not produce
/// a explicit result, only implicitly set CPSR.
-let isCompare = 1, Defs = [CPSR] in {
multiclass T2I_cmp_irs<bits<4> opcod, string opc,
InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
- PatFrag opnode> {
+ PatFrag opnode, string baseOpc> {
+let isCompare = 1, Defs = [CPSR] in {
// shifted imm
def ri : T2OneRegCmpImm<
- (outs), (ins GPR:$Rn, t2_so_imm:$imm), iii,
+ (outs), (ins GPRnopc:$Rn, t2_so_imm:$imm), iii,
opc, ".w\t$Rn, $imm",
- [(opnode GPR:$Rn, t2_so_imm:$imm)]> {
+ [(opnode GPRnopc:$Rn, t2_so_imm:$imm)]> {
let Inst{31-27} = 0b11110;
let Inst{25} = 0;
let Inst{24-21} = opcod;
@@ -807,9 +833,9 @@ multiclass T2I_cmp_irs<bits<4> opcod, string opc,
}
// register
def rr : T2TwoRegCmp<
- (outs), (ins GPR:$lhs, rGPR:$rhs), iir,
- opc, ".w\t$lhs, $rhs",
- [(opnode GPR:$lhs, rGPR:$rhs)]> {
+ (outs), (ins GPRnopc:$Rn, rGPR:$Rm), iir,
+ opc, ".w\t$Rn, $Rm",
+ [(opnode GPRnopc:$Rn, rGPR:$Rm)]> {
let Inst{31-27} = 0b11101;
let Inst{26-25} = 0b01;
let Inst{24-21} = opcod;
@@ -821,9 +847,9 @@ multiclass T2I_cmp_irs<bits<4> opcod, string opc,
}
// shifted register
def rs : T2OneRegCmpShiftedReg<
- (outs), (ins GPR:$Rn, t2_so_reg:$ShiftedRm), iis,
+ (outs), (ins GPRnopc:$Rn, t2_so_reg:$ShiftedRm), iis,
opc, ".w\t$Rn, $ShiftedRm",
- [(opnode GPR:$Rn, t2_so_reg:$ShiftedRm)]> {
+ [(opnode GPRnopc:$Rn, t2_so_reg:$ShiftedRm)]> {
let Inst{31-27} = 0b11101;
let Inst{26-25} = 0b01;
let Inst{24-21} = opcod;
@@ -831,55 +857,60 @@ multiclass T2I_cmp_irs<bits<4> opcod, string opc,
let Inst{11-8} = 0b1111; // Rd
}
}
+
+ // Assembler aliases w/o the ".w" suffix.
+ // No alias here for 'rr' version as not all instantiations of this
+ // multiclass want one (CMP in particular, does not).
+ def : t2InstAlias<!strconcat(opc, "${p}", " $Rn, $imm"),
+ (!cast<Instruction>(!strconcat(baseOpc, "ri")) GPRnopc:$Rn,
+ t2_so_imm:$imm, pred:$p)>;
+ def : t2InstAlias<!strconcat(opc, "${p}", " $Rn, $shift"),
+ (!cast<Instruction>(!strconcat(baseOpc, "rs")) GPRnopc:$Rn,
+ t2_so_reg:$shift,
+ pred:$p)>;
}
/// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns.
multiclass T2I_ld<bit signed, bits<2> opcod, string opc,
- InstrItinClass iii, InstrItinClass iis, PatFrag opnode> {
- def i12 : T2Ii12<(outs GPR:$Rt), (ins t2addrmode_imm12:$addr), iii,
+ InstrItinClass iii, InstrItinClass iis, RegisterClass target,
+ PatFrag opnode> {
+ def i12 : T2Ii12<(outs target:$Rt), (ins t2addrmode_imm12:$addr), iii,
opc, ".w\t$Rt, $addr",
- [(set GPR:$Rt, (opnode t2addrmode_imm12:$addr))]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-25} = 0b00;
+ [(set target:$Rt, (opnode t2addrmode_imm12:$addr))]> {
+ bits<4> Rt;
+ bits<17> addr;
+ let Inst{31-25} = 0b1111100;
let Inst{24} = signed;
let Inst{23} = 1;
let Inst{22-21} = opcod;
let Inst{20} = 1; // load
-
- bits<4> Rt;
- let Inst{15-12} = Rt;
-
- bits<17> addr;
- let addr{12} = 1; // add = TRUE
let Inst{19-16} = addr{16-13}; // Rn
- let Inst{23} = addr{12}; // U
+ let Inst{15-12} = Rt;
let Inst{11-0} = addr{11-0}; // imm
}
- def i8 : T2Ii8 <(outs GPR:$Rt), (ins t2addrmode_imm8:$addr), iii,
+ def i8 : T2Ii8 <(outs target:$Rt), (ins t2addrmode_negimm8:$addr), iii,
opc, "\t$Rt, $addr",
- [(set GPR:$Rt, (opnode t2addrmode_imm8:$addr))]> {
+ [(set target:$Rt, (opnode t2addrmode_negimm8:$addr))]> {
+ 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} = 1; // load
+ let Inst{19-16} = addr{12-9}; // Rn
+ let Inst{15-12} = Rt;
let Inst{11} = 1;
// Offset: index==TRUE, wback==FALSE
let Inst{10} = 1; // The P bit.
- let Inst{8} = 0; // The W bit.
-
- bits<4> Rt;
- let Inst{15-12} = Rt;
-
- bits<13> addr;
- let Inst{19-16} = addr{12-9}; // Rn
let Inst{9} = addr{8}; // U
+ let Inst{8} = 0; // The W bit.
let Inst{7-0} = addr{7-0}; // imm
}
- def s : T2Iso <(outs GPR:$Rt), (ins t2addrmode_so_reg:$addr), iis,
+ def s : T2Iso <(outs target:$Rt), (ins t2addrmode_so_reg:$addr), iis,
opc, ".w\t$Rt, $addr",
- [(set GPR:$Rt, (opnode t2addrmode_so_reg:$addr))]> {
+ [(set target:$Rt, (opnode t2addrmode_so_reg:$addr))]> {
let Inst{31-27} = 0b11111;
let Inst{26-25} = 0b00;
let Inst{24} = signed;
@@ -895,12 +926,14 @@ multiclass T2I_ld<bit signed, bits<2> opcod, string opc,
let Inst{19-16} = addr{9-6}; // Rn
let Inst{3-0} = addr{5-2}; // Rm
let Inst{5-4} = addr{1-0}; // imm
+
+ let DecoderMethod = "DecodeT2LoadShift";
}
// FIXME: Is the pci variant actually needed?
- def pci : T2Ipc <(outs GPR:$Rt), (ins t2ldrlabel:$addr), iii,
+ def pci : T2Ipc <(outs target:$Rt), (ins t2ldrlabel:$addr), iii,
opc, ".w\t$Rt, $addr",
- [(set GPR:$Rt, (opnode (ARMWrapper tconstpool:$addr)))]> {
+ [(set target:$Rt, (opnode (ARMWrapper tconstpool:$addr)))]> {
let isReMaterializable = 1;
let Inst{31-27} = 0b11111;
let Inst{26-25} = 0b00;
@@ -918,10 +951,11 @@ multiclass T2I_ld<bit signed, bits<2> opcod, string opc,
/// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns.
multiclass T2I_st<bits<2> opcod, string opc,
- InstrItinClass iii, InstrItinClass iis, PatFrag opnode> {
- def i12 : T2Ii12<(outs), (ins GPR:$Rt, t2addrmode_imm12:$addr), iii,
+ InstrItinClass iii, InstrItinClass iis, RegisterClass target,
+ PatFrag opnode> {
+ def i12 : T2Ii12<(outs), (ins target:$Rt, t2addrmode_imm12:$addr), iii,
opc, ".w\t$Rt, $addr",
- [(opnode GPR:$Rt, t2addrmode_imm12:$addr)]> {
+ [(opnode target:$Rt, t2addrmode_imm12:$addr)]> {
let Inst{31-27} = 0b11111;
let Inst{26-23} = 0b0001;
let Inst{22-21} = opcod;
@@ -936,9 +970,9 @@ multiclass T2I_st<bits<2> opcod, string opc,
let Inst{23} = addr{12}; // U
let Inst{11-0} = addr{11-0}; // imm
}
- def i8 : T2Ii8 <(outs), (ins GPR:$Rt, t2addrmode_imm8:$addr), iii,
+ def i8 : T2Ii8 <(outs), (ins target:$Rt, t2addrmode_negimm8:$addr), iii,
opc, "\t$Rt, $addr",
- [(opnode GPR:$Rt, t2addrmode_imm8:$addr)]> {
+ [(opnode target:$Rt, t2addrmode_negimm8:$addr)]> {
let Inst{31-27} = 0b11111;
let Inst{26-23} = 0b0000;
let Inst{22-21} = opcod;
@@ -956,9 +990,9 @@ multiclass T2I_st<bits<2> opcod, string opc,
let Inst{9} = addr{8}; // U
let Inst{7-0} = addr{7-0}; // imm
}
- def s : T2Iso <(outs), (ins GPR:$Rt, t2addrmode_so_reg:$addr), iis,
+ def s : T2Iso <(outs), (ins target:$Rt, t2addrmode_so_reg:$addr), iis,
opc, ".w\t$Rt, $addr",
- [(opnode GPR:$Rt, t2addrmode_so_reg:$addr)]> {
+ [(opnode target:$Rt, t2addrmode_so_reg:$addr)]> {
let Inst{31-27} = 0b11111;
let Inst{26-23} = 0b0000;
let Inst{22-21} = opcod;
@@ -977,146 +1011,81 @@ multiclass T2I_st<bits<2> opcod, string opc,
/// T2I_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.
-multiclass T2I_ext_rrot<bits<3> opcod, string opc, PatFrag opnode> {
- def r : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iEXTr,
- opc, ".w\t$Rd, $Rm",
- [(set rGPR:$Rd, (opnode rGPR:$Rm))]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
- let Inst{5-4} = 0b00; // rotate
- }
- def r_rot : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr,
- opc, ".w\t$Rd, $Rm, ror $rot",
- [(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
-
- bits<2> rot;
- let Inst{5-4} = rot{1-0}; // rotate
- }
+class T2I_ext_rrot<bits<3> opcod, string opc, PatFrag opnode>
+ : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr,
+ opc, ".w\t$Rd, $Rm$rot",
+ [(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]>,
+ Requires<[IsThumb2]> {
+ let Inst{31-27} = 0b11111;
+ let Inst{26-23} = 0b0100;
+ let Inst{22-20} = opcod;
+ let Inst{19-16} = 0b1111; // Rn
+ let Inst{15-12} = 0b1111;
+ let Inst{7} = 1;
+
+ bits<2> rot;
+ let Inst{5-4} = rot{1-0}; // rotate
}
// UXTB16 - Requres T2ExtractPack, does not need the .w qualifier.
-multiclass T2I_ext_rrot_uxtb16<bits<3> opcod, string opc, PatFrag opnode> {
- def r : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iEXTr,
- opc, "\t$Rd, $Rm",
- [(set rGPR:$Rd, (opnode rGPR:$Rm))]>,
- Requires<[HasT2ExtractPack, IsThumb2]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
- let Inst{5-4} = 0b00; // rotate
- }
- def r_rot : T2TwoReg<(outs rGPR:$dst), (ins rGPR:$Rm, rot_imm:$rot),
- IIC_iEXTr, opc, "\t$dst, $Rm, ror $rot",
- [(set rGPR:$dst, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]>,
- Requires<[HasT2ExtractPack, IsThumb2]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
-
- bits<2> rot;
- let Inst{5-4} = rot{1-0}; // rotate
- }
+class T2I_ext_rrot_uxtb16<bits<3> opcod, string opc, PatFrag opnode>
+ : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot),
+ IIC_iEXTr, opc, "\t$Rd, $Rm$rot",
+ [(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]>,
+ Requires<[HasT2ExtractPack, IsThumb2]> {
+ bits<2> rot;
+ let Inst{31-27} = 0b11111;
+ let Inst{26-23} = 0b0100;
+ let Inst{22-20} = opcod;
+ let Inst{19-16} = 0b1111; // Rn
+ let Inst{15-12} = 0b1111;
+ let Inst{7} = 1;
+ let Inst{5-4} = rot;
}
// SXTB16 - Requres T2ExtractPack, does not need the .w qualifier, no pattern
// supported yet.
-multiclass T2I_ext_rrot_sxtb16<bits<3> opcod, string opc> {
- def r : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iEXTr,
- opc, "\t$Rd, $Rm", []>,
+class T2I_ext_rrot_sxtb16<bits<3> opcod, string opc>
+ : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr,
+ opc, "\t$Rd, $Rm$rot", []>,
Requires<[IsThumb2, HasT2ExtractPack]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
- let Inst{5-4} = 0b00; // rotate
- }
- def r_rot : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, i32imm:$rot), IIC_iEXTr,
- opc, "\t$Rd, $Rm, ror $rot", []>,
- Requires<[IsThumb2, HasT2ExtractPack]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{19-16} = 0b1111; // Rn
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
-
- bits<2> rot;
- let Inst{5-4} = rot{1-0}; // rotate
- }
+ bits<2> rot;
+ let Inst{31-27} = 0b11111;
+ let Inst{26-23} = 0b0100;
+ let Inst{22-20} = opcod;
+ let Inst{19-16} = 0b1111; // Rn
+ let Inst{15-12} = 0b1111;
+ let Inst{7} = 1;
+ let Inst{5-4} = rot;
}
/// T2I_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 T2I_exta_rrot<bits<3> opcod, string opc, PatFrag opnode> {
- def rr : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iEXTAr,
- opc, "\t$Rd, $Rn, $Rm",
- [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>,
- Requires<[HasT2ExtractPack, IsThumb2]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
- let Inst{5-4} = 0b00; // rotate
- }
- def rr_rot : T2ThreeReg<(outs rGPR:$Rd),
- (ins rGPR:$Rn, rGPR:$Rm, rot_imm:$rot),
- IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm, ror $rot",
- [(set rGPR:$Rd, (opnode rGPR:$Rn,
- (rotr rGPR:$Rm, rot_imm:$rot)))]>,
- Requires<[HasT2ExtractPack, IsThumb2]> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
-
- bits<2> rot;
- let Inst{5-4} = rot{1-0}; // rotate
- }
+class T2I_exta_rrot<bits<3> opcod, string opc, PatFrag opnode>
+ : T2ThreeReg<(outs rGPR:$Rd),
+ (ins rGPR:$Rn, rGPR:$Rm, rot_imm:$rot),
+ IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm$rot",
+ [(set rGPR:$Rd, (opnode rGPR:$Rn, (rotr rGPR:$Rm,rot_imm:$rot)))]>,
+ Requires<[HasT2ExtractPack, IsThumb2]> {
+ bits<2> rot;
+ let Inst{31-27} = 0b11111;
+ let Inst{26-23} = 0b0100;
+ let Inst{22-20} = opcod;
+ let Inst{15-12} = 0b1111;
+ let Inst{7} = 1;
+ let Inst{5-4} = rot;
}
-// DO variant - disassembly only, no pattern
-
-multiclass T2I_exta_rrot_DO<bits<3> opcod, string opc> {
- def rr : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iEXTAr,
- opc, "\t$Rd, $Rn, $Rm", []> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
- let Inst{5-4} = 0b00; // rotate
- }
- def rr_rot :T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, i32imm:$rot),
- IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm, ror $rot", []> {
- let Inst{31-27} = 0b11111;
- let Inst{26-23} = 0b0100;
- let Inst{22-20} = opcod;
- let Inst{15-12} = 0b1111;
- let Inst{7} = 1;
-
- bits<2> rot;
- let Inst{5-4} = rot{1-0}; // rotate
- }
+class T2I_exta_rrot_np<bits<3> opcod, string opc>
+ : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm,rot_imm:$rot),
+ IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm$rot", []> {
+ bits<2> rot;
+ let Inst{31-27} = 0b11111;
+ let Inst{26-23} = 0b0100;
+ let Inst{22-20} = opcod;
+ let Inst{15-12} = 0b1111;
+ let Inst{7} = 1;
+ let Inst{5-4} = rot;
}
//===----------------------------------------------------------------------===//
@@ -1143,7 +1112,7 @@ class T2PCOneRegImm<dag oops, dag iops, InstrItinClass itin,
// assembler.
def t2ADR : T2PCOneRegImm<(outs rGPR:$Rd),
(ins t2adrlabel:$addr, pred:$p),
- IIC_iALUi, "adr{$p}.w\t$Rd, #$addr", []> {
+ IIC_iALUi, "adr{$p}.w\t$Rd, $addr", []> {
let Inst{31-27} = 0b11110;
let Inst{25-24} = 0b10;
// Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE)
@@ -1160,6 +1129,8 @@ def t2ADR : T2PCOneRegImm<(outs rGPR:$Rd),
let Inst{26} = addr{11};
let Inst{14-12} = addr{10-8};
let Inst{7-0} = addr{7-0};
+
+ let DecoderMethod = "DecodeT2Adr";
}
let neverHasSideEffects = 1, isReMaterializable = 1 in
@@ -1177,33 +1148,33 @@ def t2LEApcrelJT : t2PseudoInst<(outs rGPR:$Rd),
// Load
let canFoldAsLoad = 1, isReMaterializable = 1 in
-defm t2LDR : T2I_ld<0, 0b10, "ldr", IIC_iLoad_i, IIC_iLoad_si,
+defm t2LDR : T2I_ld<0, 0b10, "ldr", IIC_iLoad_i, IIC_iLoad_si, GPR,
UnOpFrag<(load node:$Src)>>;
// Loads with zero extension
defm t2LDRH : T2I_ld<0, 0b01, "ldrh", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
- UnOpFrag<(zextloadi16 node:$Src)>>;
+ rGPR, UnOpFrag<(zextloadi16 node:$Src)>>;
defm t2LDRB : T2I_ld<0, 0b00, "ldrb", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
- UnOpFrag<(zextloadi8 node:$Src)>>;
+ rGPR, UnOpFrag<(zextloadi8 node:$Src)>>;
// Loads with sign extension
defm t2LDRSH : T2I_ld<1, 0b01, "ldrsh", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
- UnOpFrag<(sextloadi16 node:$Src)>>;
+ rGPR, UnOpFrag<(sextloadi16 node:$Src)>>;
defm t2LDRSB : T2I_ld<1, 0b00, "ldrsb", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
- UnOpFrag<(sextloadi8 node:$Src)>>;
+ rGPR, UnOpFrag<(sextloadi8 node:$Src)>>;
let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in {
// Load doubleword
def t2LDRDi8 : T2Ii8s4<1, 0, 1, (outs rGPR:$Rt, rGPR:$Rt2),
(ins t2addrmode_imm8s4:$addr),
- IIC_iLoad_d_i, "ldrd", "\t$Rt, $Rt2, $addr", []>;
+ IIC_iLoad_d_i, "ldrd", "\t$Rt, $Rt2, $addr", "", []>;
} // mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1
// zextload i1 -> zextload i8
def : T2Pat<(zextloadi1 t2addrmode_imm12:$addr),
(t2LDRBi12 t2addrmode_imm12:$addr)>;
-def : T2Pat<(zextloadi1 t2addrmode_imm8:$addr),
- (t2LDRBi8 t2addrmode_imm8:$addr)>;
+def : T2Pat<(zextloadi1 t2addrmode_negimm8:$addr),
+ (t2LDRBi8 t2addrmode_negimm8:$addr)>;
def : T2Pat<(zextloadi1 t2addrmode_so_reg:$addr),
(t2LDRBs t2addrmode_so_reg:$addr)>;
def : T2Pat<(zextloadi1 (ARMWrapper tconstpool:$addr)),
@@ -1214,8 +1185,8 @@ def : T2Pat<(zextloadi1 (ARMWrapper tconstpool:$addr)),
// earlier?
def : T2Pat<(extloadi1 t2addrmode_imm12:$addr),
(t2LDRBi12 t2addrmode_imm12:$addr)>;
-def : T2Pat<(extloadi1 t2addrmode_imm8:$addr),
- (t2LDRBi8 t2addrmode_imm8:$addr)>;
+def : T2Pat<(extloadi1 t2addrmode_negimm8:$addr),
+ (t2LDRBi8 t2addrmode_negimm8:$addr)>;
def : T2Pat<(extloadi1 t2addrmode_so_reg:$addr),
(t2LDRBs t2addrmode_so_reg:$addr)>;
def : T2Pat<(extloadi1 (ARMWrapper tconstpool:$addr)),
@@ -1223,8 +1194,8 @@ def : T2Pat<(extloadi1 (ARMWrapper tconstpool:$addr)),
def : T2Pat<(extloadi8 t2addrmode_imm12:$addr),
(t2LDRBi12 t2addrmode_imm12:$addr)>;
-def : T2Pat<(extloadi8 t2addrmode_imm8:$addr),
- (t2LDRBi8 t2addrmode_imm8:$addr)>;
+def : T2Pat<(extloadi8 t2addrmode_negimm8:$addr),
+ (t2LDRBi8 t2addrmode_negimm8:$addr)>;
def : T2Pat<(extloadi8 t2addrmode_so_reg:$addr),
(t2LDRBs t2addrmode_so_reg:$addr)>;
def : T2Pat<(extloadi8 (ARMWrapper tconstpool:$addr)),
@@ -1232,8 +1203,8 @@ def : T2Pat<(extloadi8 (ARMWrapper tconstpool:$addr)),
def : T2Pat<(extloadi16 t2addrmode_imm12:$addr),
(t2LDRHi12 t2addrmode_imm12:$addr)>;
-def : T2Pat<(extloadi16 t2addrmode_imm8:$addr),
- (t2LDRHi8 t2addrmode_imm8:$addr)>;
+def : T2Pat<(extloadi16 t2addrmode_negimm8:$addr),
+ (t2LDRHi8 t2addrmode_negimm8:$addr)>;
def : T2Pat<(extloadi16 t2addrmode_so_reg:$addr),
(t2LDRHs t2addrmode_so_reg:$addr)>;
def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)),
@@ -1247,83 +1218,86 @@ def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)),
// Indexed loads
let mayLoad = 1, neverHasSideEffects = 1 in {
-def t2LDR_PRE : T2Iidxldst<0, 0b10, 1, 1, (outs GPR:$Rt, GPR:$Rn),
+def t2LDR_PRE : T2Ipreldst<0, 0b10, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iLoad_iu,
- "ldr", "\t$Rt, $addr!", "$addr.base = $Rn",
- []>;
+ "ldr", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
+ []> {
+ let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
+}
-def t2LDR_POST : T2Iidxldst<0, 0b10, 1, 0, (outs GPR:$Rt, GPR:$Rn),
- (ins GPR:$base, t2am_imm8_offset:$addr),
- AddrModeT2_i8, IndexModePost, IIC_iLoad_iu,
- "ldr", "\t$Rt, [$Rn], $addr", "$base = $Rn",
- []>;
+def t2LDR_POST : T2Ipostldst<0, 0b10, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
+ (ins addr_offset_none:$Rn, t2am_imm8_offset:$offset),
+ AddrModeT2_i8, IndexModePost, IIC_iLoad_iu,
+ "ldr", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>;
-def t2LDRB_PRE : T2Iidxldst<0, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn),
+def t2LDRB_PRE : T2Ipreldst<0, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
- "ldrb", "\t$Rt, $addr!", "$addr.base = $Rn",
- []>;
-def t2LDRB_POST : T2Iidxldst<0, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn),
- (ins GPR:$base, t2am_imm8_offset:$addr),
- AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
- "ldrb", "\t$Rt, [$Rn], $addr", "$base = $Rn",
- []>;
-
-def t2LDRH_PRE : T2Iidxldst<0, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn),
+ "ldrb", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
+ []> {
+ let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
+}
+def t2LDRB_POST : T2Ipostldst<0, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
+ (ins addr_offset_none:$Rn, t2am_imm8_offset:$offset),
+ AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
+ "ldrb", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>;
+
+def t2LDRH_PRE : T2Ipreldst<0, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
- "ldrh", "\t$Rt, $addr!", "$addr.base = $Rn",
- []>;
-def t2LDRH_POST : T2Iidxldst<0, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn),
- (ins GPR:$base, t2am_imm8_offset:$addr),
- AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
- "ldrh", "\t$Rt, [$Rn], $addr", "$base = $Rn",
- []>;
-
-def t2LDRSB_PRE : T2Iidxldst<1, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn),
+ "ldrh", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
+ []> {
+ let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
+}
+def t2LDRH_POST : T2Ipostldst<0, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
+ (ins addr_offset_none:$Rn, t2am_imm8_offset:$offset),
+ AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
+ "ldrh", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>;
+
+def t2LDRSB_PRE : T2Ipreldst<1, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
- "ldrsb", "\t$Rt, $addr!", "$addr.base = $Rn",
- []>;
-def t2LDRSB_POST : T2Iidxldst<1, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn),
- (ins GPR:$base, t2am_imm8_offset:$addr),
- AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
- "ldrsb", "\t$Rt, [$Rn], $addr", "$base = $Rn",
- []>;
-
-def t2LDRSH_PRE : T2Iidxldst<1, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn),
+ "ldrsb", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
+ []> {
+ let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
+}
+def t2LDRSB_POST : T2Ipostldst<1, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
+ (ins addr_offset_none:$Rn, t2am_imm8_offset:$offset),
+ AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
+ "ldrsb", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>;
+
+def t2LDRSH_PRE : T2Ipreldst<1, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
- "ldrsh", "\t$Rt, $addr!", "$addr.base = $Rn",
- []>;
-def t2LDRSH_POST : T2Iidxldst<1, 0b01, 1, 0, (outs GPR:$dst, GPR:$Rn),
- (ins GPR:$base, t2am_imm8_offset:$addr),
- AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
- "ldrsh", "\t$dst, [$Rn], $addr", "$base = $Rn",
- []>;
+ "ldrsh", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
+ []> {
+ let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
+}
+def t2LDRSH_POST : T2Ipostldst<1, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
+ (ins addr_offset_none:$Rn, t2am_imm8_offset:$offset),
+ AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
+ "ldrsh", "\t$Rt, $Rn$offset", "$Rn = $Rn_wb", []>;
} // mayLoad = 1, neverHasSideEffects = 1
-// LDRT, LDRBT, LDRHT, LDRSBT, LDRSHT all have offset mode (PUW=0b110) and are
-// for disassembly only.
+// LDRT, LDRBT, LDRHT, LDRSBT, LDRSHT all have offset mode (PUW=0b110).
// Ref: A8.6.57 LDR (immediate, Thumb) Encoding T4
class T2IldT<bit signed, bits<2> type, string opc, InstrItinClass ii>
- : T2Ii8<(outs rGPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc,
+ : T2Ii8<(outs rGPR:$Rt), (ins t2addrmode_posimm8:$addr), ii, opc,
"\t$Rt, $addr", []> {
+ 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} = type;
let Inst{20} = 1; // load
+ let Inst{19-16} = addr{12-9};
+ let Inst{15-12} = Rt;
let Inst{11} = 1;
let Inst{10-8} = 0b110; // PUW.
-
- bits<4> Rt;
- bits<13> addr;
- let Inst{15-12} = Rt;
- let Inst{19-16} = addr{12-9};
- let Inst{7-0} = addr{7-0};
+ let Inst{7-0} = addr{7-0};
}
def t2LDRT : T2IldT<0, 0b10, "ldrt", IIC_iLoad_i>;
@@ -1333,67 +1307,97 @@ def t2LDRSBT : T2IldT<1, 0b00, "ldrsbt", IIC_iLoad_bh_i>;
def t2LDRSHT : T2IldT<1, 0b01, "ldrsht", IIC_iLoad_bh_i>;
// Store
-defm t2STR :T2I_st<0b10,"str", IIC_iStore_i, IIC_iStore_si,
+defm t2STR :T2I_st<0b10,"str", IIC_iStore_i, IIC_iStore_si, GPR,
BinOpFrag<(store node:$LHS, node:$RHS)>>;
defm t2STRB:T2I_st<0b00,"strb", IIC_iStore_bh_i, IIC_iStore_bh_si,
- BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>;
+ rGPR, BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>;
defm t2STRH:T2I_st<0b01,"strh", IIC_iStore_bh_i, IIC_iStore_bh_si,
- BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>;
+ rGPR, BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>;
// Store doubleword
let mayLoad = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in
def t2STRDi8 : T2Ii8s4<1, 0, 0, (outs),
(ins GPR:$Rt, GPR:$Rt2, t2addrmode_imm8s4:$addr),
- IIC_iStore_d_r, "strd", "\t$Rt, $Rt2, $addr", []>;
+ IIC_iStore_d_r, "strd", "\t$Rt, $Rt2, $addr", "", []>;
// Indexed stores
-def t2STR_PRE : T2Iidxldst<0, 0b10, 0, 1, (outs GPR:$base_wb),
- (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
+def t2STR_PRE : T2Ipreldst<0, 0b10, 0, 1, (outs GPRnopc:$Rn_wb),
+ (ins rGPR:$Rt, t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iStore_iu,
- "str", "\t$Rt, [$Rn, $addr]!",
- "$Rn = $base_wb,@earlyclobber $base_wb",
- [(set GPR:$base_wb,
- (pre_store GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
-
-def t2STR_POST : T2Iidxldst<0, 0b10, 0, 0, (outs GPR:$base_wb),
- (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
- AddrModeT2_i8, IndexModePost, IIC_iStore_iu,
- "str", "\t$Rt, [$Rn], $addr",
- "$Rn = $base_wb,@earlyclobber $base_wb",
- [(set GPR:$base_wb,
- (post_store GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
-
-def t2STRH_PRE : T2Iidxldst<0, 0b01, 0, 1, (outs GPR:$base_wb),
- (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
+ "str", "\t$Rt, $addr!",
+ "$addr.base = $Rn_wb,@earlyclobber $Rn_wb", []> {
+ let AsmMatchConverter = "cvtStWriteBackRegT2AddrModeImm8";
+}
+def t2STRH_PRE : T2Ipreldst<0, 0b01, 0, 1, (outs GPRnopc:$Rn_wb),
+ (ins rGPR:$Rt, t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iStore_iu,
- "strh", "\t$Rt, [$Rn, $addr]!",
- "$Rn = $base_wb,@earlyclobber $base_wb",
- [(set GPR:$base_wb,
- (pre_truncsti16 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
-
-def t2STRH_POST : T2Iidxldst<0, 0b01, 0, 0, (outs GPR:$base_wb),
- (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
- AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu,
- "strh", "\t$Rt, [$Rn], $addr",
- "$Rn = $base_wb,@earlyclobber $base_wb",
- [(set GPR:$base_wb,
- (post_truncsti16 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
+ "strh", "\t$Rt, $addr!",
+ "$addr.base = $Rn_wb,@earlyclobber $Rn_wb", []> {
+ let AsmMatchConverter = "cvtStWriteBackRegT2AddrModeImm8";
+}
-def t2STRB_PRE : T2Iidxldst<0, 0b00, 0, 1, (outs GPR:$base_wb),
- (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
+def t2STRB_PRE : T2Ipreldst<0, 0b00, 0, 1, (outs GPRnopc:$Rn_wb),
+ (ins rGPR:$Rt, t2addrmode_imm8:$addr),
AddrModeT2_i8, IndexModePre, IIC_iStore_bh_iu,
- "strb", "\t$Rt, [$Rn, $addr]!",
- "$Rn = $base_wb,@earlyclobber $base_wb",
- [(set GPR:$base_wb,
- (pre_truncsti8 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
+ "strb", "\t$Rt, $addr!",
+ "$addr.base = $Rn_wb,@earlyclobber $Rn_wb", []> {
+ let AsmMatchConverter = "cvtStWriteBackRegT2AddrModeImm8";
+}
-def t2STRB_POST : T2Iidxldst<0, 0b00, 0, 0, (outs GPR:$base_wb),
- (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
+def t2STR_POST : T2Ipostldst<0, 0b10, 0, 0, (outs GPRnopc:$Rn_wb),
+ (ins rGPR:$Rt, addr_offset_none:$Rn,
+ t2am_imm8_offset:$offset),
+ AddrModeT2_i8, IndexModePost, IIC_iStore_iu,
+ "str", "\t$Rt, $Rn$offset",
+ "$Rn = $Rn_wb,@earlyclobber $Rn_wb",
+ [(set GPRnopc:$Rn_wb,
+ (post_store rGPR:$Rt, addr_offset_none:$Rn,
+ t2am_imm8_offset:$offset))]>;
+
+def t2STRH_POST : T2Ipostldst<0, 0b01, 0, 0, (outs GPRnopc:$Rn_wb),
+ (ins rGPR:$Rt, addr_offset_none:$Rn,
+ t2am_imm8_offset:$offset),
AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu,
- "strb", "\t$Rt, [$Rn], $addr",
- "$Rn = $base_wb,@earlyclobber $base_wb",
- [(set GPR:$base_wb,
- (post_truncsti8 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
+ "strh", "\t$Rt, $Rn$offset",
+ "$Rn = $Rn_wb,@earlyclobber $Rn_wb",
+ [(set GPRnopc:$Rn_wb,
+ (post_truncsti16 rGPR:$Rt, addr_offset_none:$Rn,
+ t2am_imm8_offset:$offset))]>;
+
+def t2STRB_POST : T2Ipostldst<0, 0b00, 0, 0, (outs GPRnopc:$Rn_wb),
+ (ins rGPR:$Rt, addr_offset_none:$Rn,
+ t2am_imm8_offset:$offset),
+ AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu,
+ "strb", "\t$Rt, $Rn$offset",
+ "$Rn = $Rn_wb,@earlyclobber $Rn_wb",
+ [(set GPRnopc:$Rn_wb,
+ (post_truncsti8 rGPR:$Rt, addr_offset_none:$Rn,
+ t2am_imm8_offset:$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 t2STR_preidx: t2PseudoInst<(outs GPRnopc:$Rn_wb),
+ (ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset, pred:$p),
+ 4, IIC_iStore_ru,
+ [(set GPRnopc:$Rn_wb,
+ (pre_store rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset))]>;
+def t2STRB_preidx: t2PseudoInst<(outs GPRnopc:$Rn_wb),
+ (ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset, pred:$p),
+ 4, IIC_iStore_ru,
+ [(set GPRnopc:$Rn_wb,
+ (pre_truncsti8 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset))]>;
+def t2STRH_preidx: t2PseudoInst<(outs GPRnopc:$Rn_wb),
+ (ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset, pred:$p),
+ 4, IIC_iStore_ru,
+ [(set GPRnopc:$Rn_wb,
+ (pre_truncsti16 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$offset))]>;
+}
+
// STRT, STRBT, STRHT all have offset mode (PUW=0b110) and are for disassembly
// only.
@@ -1424,21 +1428,31 @@ def t2STRHT : T2IstT<0b01, "strht", IIC_iStore_bh_i>;
// ldrd / strd pre / post variants
// For disassembly only.
-def t2LDRD_PRE : T2Ii8s4<1, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2),
- (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru,
- "ldrd", "\t$Rt, $Rt2, [$base, $imm]!", []>;
+def t2LDRD_PRE : T2Ii8s4<1, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2, GPR:$wb),
+ (ins t2addrmode_imm8s4:$addr), IIC_iLoad_d_ru,
+ "ldrd", "\t$Rt, $Rt2, $addr!", "$addr.base = $wb", []> {
+ let AsmMatchConverter = "cvtT2LdrdPre";
+ let DecoderMethod = "DecodeT2LDRDPreInstruction";
+}
-def t2LDRD_POST : T2Ii8s4<0, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2),
- (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru,
- "ldrd", "\t$Rt, $Rt2, [$base], $imm", []>;
+def t2LDRD_POST : T2Ii8s4post<0, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2, GPR:$wb),
+ (ins addr_offset_none:$addr, t2am_imm8s4_offset:$imm),
+ IIC_iLoad_d_ru, "ldrd", "\t$Rt, $Rt2, $addr$imm",
+ "$addr.base = $wb", []>;
-def t2STRD_PRE : T2Ii8s4<1, 1, 0, (outs),
- (ins rGPR:$Rt, rGPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm),
- IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base, $imm]!", []>;
+def t2STRD_PRE : T2Ii8s4<1, 1, 0, (outs GPR:$wb),
+ (ins rGPR:$Rt, rGPR:$Rt2, t2addrmode_imm8s4:$addr),
+ IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, $addr!",
+ "$addr.base = $wb", []> {
+ let AsmMatchConverter = "cvtT2StrdPre";
+ let DecoderMethod = "DecodeT2STRDPreInstruction";
+}
-def t2STRD_POST : T2Ii8s4<0, 1, 0, (outs),
- (ins rGPR:$Rt, rGPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm),
- IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base], $imm", []>;
+def t2STRD_POST : T2Ii8s4post<0, 1, 0, (outs GPR:$wb),
+ (ins rGPR:$Rt, rGPR:$Rt2, addr_offset_none:$addr,
+ t2am_imm8s4_offset:$imm),
+ IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, $addr$imm",
+ "$addr.base = $wb", []>;
// T2Ipl (Preload Data/Instruction) signals the memory system of possible future
// data/instruction access. These are for disassembly only.
@@ -1463,9 +1477,9 @@ multiclass T2Ipl<bits<1> write, bits<1> instr, string opc> {
let Inst{11-0} = addr{11-0}; // imm12
}
- def i8 : T2Ii8<(outs), (ins t2addrmode_imm8:$addr), IIC_Preload, opc,
+ def i8 : T2Ii8<(outs), (ins t2addrmode_negimm8:$addr), IIC_Preload, opc,
"\t$addr",
- [(ARMPreload t2addrmode_imm8:$addr, (i32 write), (i32 instr))]> {
+ [(ARMPreload t2addrmode_negimm8:$addr, (i32 write), (i32 instr))]> {
let Inst{31-25} = 0b1111100;
let Inst{24} = instr;
let Inst{23} = 0; // U = 0
@@ -1496,6 +1510,8 @@ multiclass T2Ipl<bits<1> write, bits<1> instr, string opc> {
let Inst{19-16} = addr{9-6}; // Rn
let Inst{3-0} = addr{5-2}; // Rm
let Inst{5-4} = addr{1-0}; // imm2
+
+ let DecoderMethod = "DecodeT2LoadShift";
}
}
@@ -1507,11 +1523,11 @@ defm t2PLI : T2Ipl<0, 1, "pli">, Requires<[IsThumb2,HasV7]>;
// Load / store multiple Instructions.
//
-multiclass thumb2_ldst_mult<string asm, InstrItinClass itin,
+multiclass thumb2_ld_mult<string asm, InstrItinClass itin,
InstrItinClass itin_upd, bit L_bit> {
def IA :
T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
- itin, !strconcat(asm, "ia${p}.w\t$Rn, $regs"), []> {
+ itin, !strconcat(asm, "${p}.w\t$Rn, $regs"), []> {
bits<4> Rn;
bits<16> regs;
@@ -1522,11 +1538,12 @@ multiclass thumb2_ldst_mult<string asm, InstrItinClass itin,
let Inst{21} = 0; // No writeback
let Inst{20} = L_bit;
let Inst{19-16} = Rn;
- let Inst{15-0} = regs;
+ let Inst{15} = 0;
+ let Inst{14-0} = regs{14-0};
}
def IA_UPD :
T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
- itin_upd, !strconcat(asm, "ia${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> {
+ itin_upd, !strconcat(asm, "${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> {
bits<4> Rn;
bits<16> regs;
@@ -1537,11 +1554,12 @@ multiclass thumb2_ldst_mult<string asm, InstrItinClass itin,
let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
let Inst{19-16} = Rn;
- let Inst{15-0} = regs;
+ let Inst{15} = 0;
+ let Inst{14-0} = regs{14-0};
}
def DB :
T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
- itin, !strconcat(asm, "db${p}.w\t$Rn, $regs"), []> {
+ itin, !strconcat(asm, "db${p}\t$Rn, $regs"), []> {
bits<4> Rn;
bits<16> regs;
@@ -1552,11 +1570,12 @@ multiclass thumb2_ldst_mult<string asm, InstrItinClass itin,
let Inst{21} = 0; // No writeback
let Inst{20} = L_bit;
let Inst{19-16} = Rn;
- let Inst{15-0} = regs;
+ let Inst{15} = 0;
+ let Inst{14-0} = regs{14-0};
}
def DB_UPD :
T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
- itin_upd, !strconcat(asm, "db${p}.w\t$Rn, $regs"), "$Rn = $wb", []> {
+ itin_upd, !strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
bits<4> Rn;
bits<16> regs;
@@ -1567,17 +1586,95 @@ multiclass thumb2_ldst_mult<string asm, InstrItinClass itin,
let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
let Inst{19-16} = Rn;
- let Inst{15-0} = regs;
+ let Inst{15} = 0;
+ let Inst{14-0} = regs{14-0};
}
}
let neverHasSideEffects = 1 in {
let mayLoad = 1, hasExtraDefRegAllocReq = 1 in
-defm t2LDM : thumb2_ldst_mult<"ldm", IIC_iLoad_m, IIC_iLoad_mu, 1>;
+defm t2LDM : thumb2_ld_mult<"ldm", IIC_iLoad_m, IIC_iLoad_mu, 1>;
+
+multiclass thumb2_st_mult<string asm, InstrItinClass itin,
+ InstrItinClass itin_upd, bit L_bit> {
+ def IA :
+ T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ itin, !strconcat(asm, "${p}.w\t$Rn, $regs"), []> {
+ bits<4> Rn;
+ bits<16> regs;
+
+ let Inst{31-27} = 0b11101;
+ let Inst{26-25} = 0b00;
+ let Inst{24-23} = 0b01; // Increment After
+ let Inst{22} = 0;
+ let Inst{21} = 0; // No writeback
+ let Inst{20} = L_bit;
+ let Inst{19-16} = Rn;
+ let Inst{15} = 0;
+ let Inst{14} = regs{14};
+ let Inst{13} = 0;
+ let Inst{12-0} = regs{12-0};
+ }
+ def IA_UPD :
+ T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ itin_upd, !strconcat(asm, "${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> {
+ bits<4> Rn;
+ bits<16> regs;
+
+ let Inst{31-27} = 0b11101;
+ let Inst{26-25} = 0b00;
+ let Inst{24-23} = 0b01; // Increment After
+ let Inst{22} = 0;
+ let Inst{21} = 1; // Writeback
+ let Inst{20} = L_bit;
+ let Inst{19-16} = Rn;
+ let Inst{15} = 0;
+ let Inst{14} = regs{14};
+ let Inst{13} = 0;
+ let Inst{12-0} = regs{12-0};
+ }
+ def DB :
+ T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ itin, !strconcat(asm, "db${p}\t$Rn, $regs"), []> {
+ bits<4> Rn;
+ bits<16> regs;
+
+ let Inst{31-27} = 0b11101;
+ let Inst{26-25} = 0b00;
+ let Inst{24-23} = 0b10; // Decrement Before
+ let Inst{22} = 0;
+ let Inst{21} = 0; // No writeback
+ let Inst{20} = L_bit;
+ let Inst{19-16} = Rn;
+ let Inst{15} = 0;
+ let Inst{14} = regs{14};
+ let Inst{13} = 0;
+ let Inst{12-0} = regs{12-0};
+ }
+ def DB_UPD :
+ T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ itin_upd, !strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
+ bits<4> Rn;
+ bits<16> regs;
+
+ let Inst{31-27} = 0b11101;
+ let Inst{26-25} = 0b00;
+ let Inst{24-23} = 0b10; // Decrement Before
+ let Inst{22} = 0;
+ let Inst{21} = 1; // Writeback
+ let Inst{20} = L_bit;
+ let Inst{19-16} = Rn;
+ let Inst{15} = 0;
+ let Inst{14} = regs{14};
+ let Inst{13} = 0;
+ let Inst{12-0} = regs{12-0};
+ }
+}
+
let mayStore = 1, hasExtraSrcRegAllocReq = 1 in
-defm t2STM : thumb2_ldst_mult<"stm", IIC_iStore_m, IIC_iStore_mu, 0>;
+defm t2STM : thumb2_st_mult<"stm", IIC_iStore_m, IIC_iStore_mu, 0>;
} // neverHasSideEffects
@@ -1587,7 +1684,7 @@ defm t2STM : thumb2_ldst_mult<"stm", IIC_iStore_m, IIC_iStore_mu, 0>;
//
let neverHasSideEffects = 1 in
-def t2MOVr : T2sTwoReg<(outs GPR:$Rd), (ins GPR:$Rm), IIC_iMOVr,
+def t2MOVr : T2sTwoReg<(outs GPRnopc:$Rd), (ins GPR:$Rm), IIC_iMOVr,
"mov", ".w\t$Rd, $Rm", []> {
let Inst{31-27} = 0b11101;
let Inst{26-25} = 0b01;
@@ -1596,6 +1693,10 @@ def t2MOVr : T2sTwoReg<(outs GPR:$Rd), (ins GPR:$Rm), IIC_iMOVr,
let Inst{14-12} = 0b000;
let Inst{7-4} = 0b0000;
}
+def : t2InstAlias<"movs${p}.w $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPR:$Rm,
+ pred:$p, CPSR)>;
+def : t2InstAlias<"movs${p} $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPR:$Rm,
+ pred:$p, CPSR)>;
// AddedComplexity to ensure isel tries t2MOVi before t2MOVi16.
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1,
@@ -1610,12 +1711,20 @@ def t2MOVi : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), IIC_iMOVi,
let Inst{15} = 0;
}
-def : InstAlias<"mov${s}${p} $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm,
- pred:$p, cc_out:$s)>,
- Requires<[IsThumb2]>;
+// cc_out is handled as part of the explicit mnemonic in the parser for 'mov'.
+// Use aliases to get that to play nice here.
+def : t2InstAlias<"movs${p}.w $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm,
+ pred:$p, CPSR)>;
+def : t2InstAlias<"movs${p} $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm,
+ pred:$p, CPSR)>;
+
+def : t2InstAlias<"mov${p}.w $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm,
+ pred:$p, zero_reg)>;
+def : t2InstAlias<"mov${p} $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm,
+ pred:$p, zero_reg)>;
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
-def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm_hilo16:$imm), IIC_iMOVi,
+def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins imm0_65535_expr:$imm), IIC_iMOVi,
"movw", "\t$Rd, $imm",
[(set rGPR:$Rd, imm0_65535:$imm)]> {
let Inst{31-27} = 0b11110;
@@ -1632,6 +1741,7 @@ def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm_hilo16:$imm), IIC_iMOVi,
let Inst{26} = imm{11};
let Inst{14-12} = imm{10-8};
let Inst{7-0} = imm{7-0};
+ let DecoderMethod = "DecodeT2MOVTWInstruction";
}
def t2MOVi16_ga_pcrel : PseudoInst<(outs rGPR:$Rd),
@@ -1639,7 +1749,7 @@ def t2MOVi16_ga_pcrel : PseudoInst<(outs rGPR:$Rd),
let Constraints = "$src = $Rd" in {
def t2MOVTi16 : T2I<(outs rGPR:$Rd),
- (ins rGPR:$src, i32imm_hilo16:$imm), IIC_iMOVi,
+ (ins rGPR:$src, imm0_65535_expr:$imm), IIC_iMOVi,
"movt", "\t$Rd, $imm",
[(set rGPR:$Rd,
(or (and rGPR:$src, 0xffff), lo16AllZero:$imm))]> {
@@ -1657,6 +1767,7 @@ def t2MOVTi16 : T2I<(outs rGPR:$Rd),
let Inst{26} = imm{11};
let Inst{14-12} = imm{10-8};
let Inst{7-0} = imm{7-0};
+ let DecoderMethod = "DecodeT2MOVTWInstruction";
}
def t2MOVTi16_ga_pcrel : PseudoInst<(outs rGPR:$Rd),
@@ -1671,28 +1782,26 @@ def : T2Pat<(or rGPR:$src, 0xffff0000), (t2MOVTi16 rGPR:$src, 0xffff)>;
// Sign extenders
-defm t2SXTB : T2I_ext_rrot<0b100, "sxtb",
+def t2SXTB : T2I_ext_rrot<0b100, "sxtb",
UnOpFrag<(sext_inreg node:$Src, i8)>>;
-defm t2SXTH : T2I_ext_rrot<0b000, "sxth",
+def t2SXTH : T2I_ext_rrot<0b000, "sxth",
UnOpFrag<(sext_inreg node:$Src, i16)>>;
-defm t2SXTB16 : T2I_ext_rrot_sxtb16<0b010, "sxtb16">;
+def t2SXTB16 : T2I_ext_rrot_sxtb16<0b010, "sxtb16">;
-defm t2SXTAB : T2I_exta_rrot<0b100, "sxtab",
+def t2SXTAB : T2I_exta_rrot<0b100, "sxtab",
BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>;
-defm t2SXTAH : T2I_exta_rrot<0b000, "sxtah",
+def t2SXTAH : T2I_exta_rrot<0b000, "sxtah",
BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>;
-defm t2SXTAB16 : T2I_exta_rrot_DO<0b010, "sxtab16">;
-
-// TODO: SXT(A){B|H}16 - done for disassembly only
+def t2SXTAB16 : T2I_exta_rrot_np<0b010, "sxtab16">;
// Zero extenders
let AddedComplexity = 16 in {
-defm t2UXTB : T2I_ext_rrot<0b101, "uxtb",
+def t2UXTB : T2I_ext_rrot<0b101, "uxtb",
UnOpFrag<(and node:$Src, 0x000000FF)>>;
-defm t2UXTH : T2I_ext_rrot<0b001, "uxth",
+def t2UXTH : T2I_ext_rrot<0b001, "uxth",
UnOpFrag<(and node:$Src, 0x0000FFFF)>>;
-defm t2UXTB16 : T2I_ext_rrot_uxtb16<0b011, "uxtb16",
+def t2UXTB16 : T2I_ext_rrot_uxtb16<0b011, "uxtb16",
UnOpFrag<(and node:$Src, 0x00FF00FF)>>;
// FIXME: This pattern incorrectly assumes the shl operator is a rotate.
@@ -1700,17 +1809,17 @@ defm t2UXTB16 : T2I_ext_rrot_uxtb16<0b011, "uxtb16",
// 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 : T2Pat<(and (shl rGPR:$Src, (i32 8)), 0xFF00FF),
-// (t2UXTB16r_rot rGPR:$Src, 24)>,
+// (t2UXTB16 rGPR:$Src, 3)>,
// Requires<[HasT2ExtractPack, IsThumb2]>;
def : T2Pat<(and (srl rGPR:$Src, (i32 8)), 0xFF00FF),
- (t2UXTB16r_rot rGPR:$Src, 8)>,
+ (t2UXTB16 rGPR:$Src, 1)>,
Requires<[HasT2ExtractPack, IsThumb2]>;
-defm t2UXTAB : T2I_exta_rrot<0b101, "uxtab",
+def t2UXTAB : T2I_exta_rrot<0b101, "uxtab",
BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>;
-defm t2UXTAH : T2I_exta_rrot<0b001, "uxtah",
+def t2UXTAH : T2I_exta_rrot<0b001, "uxtah",
BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>;
-defm t2UXTAB16 : T2I_exta_rrot_DO<0b011, "uxtab16">;
+def t2UXTAB16 : T2I_exta_rrot_np<0b011, "uxtab16">;
}
//===----------------------------------------------------------------------===//
@@ -1723,27 +1832,37 @@ defm t2SUB : T2I_bin_ii12rs<0b101, "sub",
BinOpFrag<(sub node:$LHS, node:$RHS)>>;
// ADD and SUB with 's' bit set. No 12-bit immediate (T4) variants.
+//
+// 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 t2ADDS : T2I_bin_s_irs <0b1000, "add",
IIC_iALUi, IIC_iALUr, IIC_iALUsi,
- BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>;
+ BinOpFrag<(ARMaddc node:$LHS, node:$RHS)>, 1>;
defm t2SUBS : T2I_bin_s_irs <0b1101, "sub",
IIC_iALUi, IIC_iALUr, IIC_iALUsi,
- BinOpFrag<(subc node:$LHS, node:$RHS)>>;
+ BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
+let hasPostISelHook = 1 in {
defm t2ADC : T2I_adde_sube_irs<0b1010, "adc",
- BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, 1>;
+ BinOpWithFlagFrag<(ARMadde node:$LHS, node:$RHS, node:$FLAG)>, 1>;
defm t2SBC : T2I_adde_sube_irs<0b1011, "sbc",
- BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>;
-defm t2ADCS : T2I_adde_sube_s_irs<BinOpFrag<(adde_live_carry node:$LHS,
- node:$RHS)>, 1>;
-defm t2SBCS : T2I_adde_sube_s_irs<BinOpFrag<(sube_live_carry node:$LHS,
- node:$RHS)>>;
+ BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>>;
+}
// RSB
defm t2RSB : T2I_rbin_irs <0b1110, "rsb",
BinOpFrag<(sub node:$LHS, node:$RHS)>>;
+
+// FIXME: Eliminate them if we can write def : Pat patterns which defines
+// CPSR and the implicit def of CPSR is not needed.
defm t2RSBS : T2I_rbin_s_is <0b1110, "rsb",
- BinOpFrag<(subc node:$LHS, node:$RHS)>>;
+ BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
// (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
@@ -1760,23 +1879,18 @@ def : T2Pat<(add GPR:$src, t2_so_imm_neg:$imm),
def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm),
(t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>;
let AddedComplexity = 1 in
-def : T2Pat<(addc rGPR:$src, imm0_255_neg:$imm),
+def : T2Pat<(ARMaddc rGPR:$src, imm0_255_neg:$imm),
(t2SUBSri rGPR:$src, imm0_255_neg:$imm)>;
-def : T2Pat<(addc rGPR:$src, t2_so_imm_neg:$imm),
+def : T2Pat<(ARMaddc rGPR:$src, t2_so_imm_neg:$imm),
(t2SUBSri rGPR:$src, t2_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.
let AddedComplexity = 1 in
-def : T2Pat<(adde_dead_carry rGPR:$src, imm0_255_not:$imm),
+def : T2Pat<(ARMadde rGPR:$src, imm0_255_not:$imm, CPSR),
(t2SBCri rGPR:$src, imm0_255_not:$imm)>;
-def : T2Pat<(adde_dead_carry rGPR:$src, t2_so_imm_not:$imm),
+def : T2Pat<(ARMadde rGPR:$src, t2_so_imm_not:$imm, CPSR),
(t2SBCri rGPR:$src, t2_so_imm_not:$imm)>;
-let AddedComplexity = 1 in
-def : T2Pat<(adde_live_carry rGPR:$src, imm0_255_not:$imm),
- (t2SBCSri rGPR:$src, imm0_255_not:$imm)>;
-def : T2Pat<(adde_live_carry rGPR:$src, t2_so_imm_not:$imm),
- (t2SBCSri rGPR:$src, t2_so_imm_not:$imm)>;
// Select Bytes -- for disassembly only
@@ -1893,8 +2007,7 @@ class T2FourReg_mac<bit long, bits<3> op22_20, bits<4> op7_4, dag oops,
let Inst{7-4} = op7_4;
}
-// Unsigned Sum of Absolute Differences [and Accumulate] -- for disassembly only
-
+// Unsigned Sum of Absolute Differences [and Accumulate].
def t2USAD8 : T2ThreeReg_mac<0, 0b111, 0b0000, (outs rGPR:$Rd),
(ins rGPR:$Rn, rGPR:$Rm),
NoItinerary, "usad8", "\t$Rd, $Rn, $Rm", []>,
@@ -1906,8 +2019,7 @@ def t2USADA8 : T2FourReg_mac<0, 0b111, 0b0000, (outs rGPR:$Rd),
"usada8", "\t$Rd, $Rn, $Rm, $Ra", []>,
Requires<[IsThumb2, HasThumb2DSP]>;
-// Signed/Unsigned saturate -- for disassembly only
-
+// Signed/Unsigned saturate.
class T2SatI<dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
: T2I<oops, iops, itin, opc, asm, pattern> {
@@ -1918,26 +2030,26 @@ class T2SatI<dag oops, dag iops, InstrItinClass itin,
let Inst{11-8} = Rd;
let Inst{19-16} = Rn;
- let Inst{4-0} = sat_imm{4-0};
- let Inst{21} = sh{6};
+ let Inst{4-0} = sat_imm;
+ let Inst{21} = sh{5};
let Inst{14-12} = sh{4-2};
let Inst{7-6} = sh{1-0};
}
def t2SSAT: T2SatI<
- (outs rGPR:$Rd), (ins ssat_imm:$sat_imm, rGPR:$Rn, shift_imm:$sh),
- NoItinerary, "ssat", "\t$Rd, $sat_imm, $Rn$sh",
- [/* For disassembly only; pattern left blank */]> {
+ (outs rGPR:$Rd),
+ (ins imm1_32:$sat_imm, rGPR:$Rn, t2_shift_imm:$sh),
+ NoItinerary, "ssat", "\t$Rd, $sat_imm, $Rn$sh", []> {
let Inst{31-27} = 0b11110;
let Inst{25-22} = 0b1100;
let Inst{20} = 0;
let Inst{15} = 0;
+ let Inst{5} = 0;
}
def t2SSAT16: T2SatI<
- (outs rGPR:$Rd), (ins ssat_imm:$sat_imm, rGPR:$Rn), NoItinerary,
- "ssat16", "\t$Rd, $sat_imm, $Rn",
- [/* For disassembly only; pattern left blank */]>,
+ (outs rGPR:$Rd), (ins imm1_16:$sat_imm, rGPR:$Rn), NoItinerary,
+ "ssat16", "\t$Rd, $sat_imm, $Rn", []>,
Requires<[IsThumb2, HasThumb2DSP]> {
let Inst{31-27} = 0b11110;
let Inst{25-22} = 0b1100;
@@ -1946,30 +2058,30 @@ def t2SSAT16: T2SatI<
let Inst{21} = 1; // sh = '1'
let Inst{14-12} = 0b000; // imm3 = '000'
let Inst{7-6} = 0b00; // imm2 = '00'
+ let Inst{5-4} = 0b00;
}
def t2USAT: T2SatI<
- (outs rGPR:$Rd), (ins i32imm:$sat_imm, rGPR:$Rn, shift_imm:$sh),
- NoItinerary, "usat", "\t$Rd, $sat_imm, $Rn$sh",
- [/* For disassembly only; pattern left blank */]> {
+ (outs rGPR:$Rd),
+ (ins imm0_31:$sat_imm, rGPR:$Rn, t2_shift_imm:$sh),
+ NoItinerary, "usat", "\t$Rd, $sat_imm, $Rn$sh", []> {
let Inst{31-27} = 0b11110;
let Inst{25-22} = 0b1110;
let Inst{20} = 0;
let Inst{15} = 0;
}
-def t2USAT16: T2SatI<(outs rGPR:$dst), (ins i32imm:$sat_imm, rGPR:$Rn),
+def t2USAT16: T2SatI<(outs rGPR:$Rd), (ins imm0_15:$sat_imm, rGPR:$Rn),
NoItinerary,
- "usat16", "\t$dst, $sat_imm, $Rn",
- [/* For disassembly only; pattern left blank */]>,
+ "usat16", "\t$Rd, $sat_imm, $Rn", []>,
Requires<[IsThumb2, HasThumb2DSP]> {
- let Inst{31-27} = 0b11110;
- let Inst{25-22} = 0b1110;
+ let Inst{31-22} = 0b1111001110;
let Inst{20} = 0;
let Inst{15} = 0;
let Inst{21} = 1; // sh = '1'
let Inst{14-12} = 0b000; // imm3 = '000'
let Inst{7-6} = 0b00; // imm2 = '00'
+ let Inst{5-4} = 0b00;
}
def : T2Pat<(int_arm_ssat GPR:$a, imm:$pos), (t2SSAT imm:$pos, GPR:$a, 0)>;
@@ -1979,10 +2091,14 @@ def : T2Pat<(int_arm_usat GPR:$a, imm:$pos), (t2USAT imm:$pos, GPR:$a, 0)>;
// Shift and rotate Instructions.
//
-defm t2LSL : T2I_sh_ir<0b00, "lsl", BinOpFrag<(shl node:$LHS, node:$RHS)>>;
-defm t2LSR : T2I_sh_ir<0b01, "lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>;
-defm t2ASR : T2I_sh_ir<0b10, "asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>;
-defm t2ROR : T2I_sh_ir<0b11, "ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>;
+defm t2LSL : T2I_sh_ir<0b00, "lsl", imm0_31,
+ BinOpFrag<(shl node:$LHS, node:$RHS)>, "t2LSL">;
+defm t2LSR : T2I_sh_ir<0b01, "lsr", imm_sr,
+ BinOpFrag<(srl node:$LHS, node:$RHS)>, "t2LSR">;
+defm t2ASR : T2I_sh_ir<0b10, "asr", imm_sr,
+ BinOpFrag<(sra node:$LHS, node:$RHS)>, "t2ASR">;
+defm t2ROR : T2I_sh_ir<0b11, "ror", imm0_31,
+ BinOpFrag<(rotr node:$LHS, node:$RHS)>, "t2ROR">;
// (rotr x, (and y, 0x...1f)) ==> (ROR x, y)
def : Pat<(rotr rGPR:$lhs, (and rGPR:$rhs, lo5AllOne)),
@@ -2090,7 +2206,7 @@ def t2BFC : T2BitFI<(outs rGPR:$Rd), (ins rGPR:$src, bf_inv_mask_imm:$imm),
}
def t2SBFX: T2TwoRegBitFI<
- (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm0_31_m1:$msb),
+ (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm1_32:$msb),
IIC_iUNAsi, "sbfx", "\t$Rd, $Rn, $lsb, $msb", []> {
let Inst{31-27} = 0b11110;
let Inst{25} = 1;
@@ -2099,7 +2215,7 @@ def t2SBFX: T2TwoRegBitFI<
}
def t2UBFX: T2TwoRegBitFI<
- (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm0_31_m1:$msb),
+ (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm1_32:$msb),
IIC_iUNAsi, "ubfx", "\t$Rd, $Rn, $lsb, $msb", []> {
let Inst{31-27} = 0b11110;
let Inst{25} = 1;
@@ -2125,26 +2241,6 @@ let Constraints = "$src = $Rd" in {
let msb{4-0} = imm{9-5};
let lsb{4-0} = imm{4-0};
}
-
- // GNU as only supports this form of bfi (w/ 4 arguments)
- let isAsmParserOnly = 1 in
- def t2BFI4p : T2TwoRegBitFI<(outs rGPR:$Rd),
- (ins rGPR:$src, rGPR:$Rn, lsb_pos_imm:$lsbit,
- width_imm:$width),
- IIC_iBITi, "bfi", "\t$Rd, $Rn, $lsbit, $width",
- []> {
- let Inst{31-27} = 0b11110;
- let Inst{26} = 0; // should be 0.
- let Inst{25} = 1;
- let Inst{24-20} = 0b10110;
- let Inst{15} = 0;
- let Inst{5} = 0; // should be 0.
-
- bits<5> lsbit;
- bits<5> width;
- let msb{4-0} = width; // Custom encoder => lsb+width-1
- let lsb{4-0} = lsbit;
- }
}
defm t2ORN : T2I_bin_irs<0b0011, "orn",
@@ -2152,13 +2248,53 @@ defm t2ORN : T2I_bin_irs<0b0011, "orn",
BinOpFrag<(or node:$LHS, (not node:$RHS))>,
"t2ORN", 0, "">;
+/// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
+/// unary operation that produces a value. These are predicable and can be
+/// changed to modify CPSR.
+multiclass T2I_un_irs<bits<4> opcod, string opc,
+ InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
+ PatFrag opnode, bit Cheap = 0, bit ReMat = 0> {
+ // shifted imm
+ def i : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), iii,
+ opc, "\t$Rd, $imm",
+ [(set rGPR:$Rd, (opnode t2_so_imm:$imm))]> {
+ let isAsCheapAsAMove = Cheap;
+ let isReMaterializable = ReMat;
+ let Inst{31-27} = 0b11110;
+ let Inst{25} = 0;
+ let Inst{24-21} = opcod;
+ let Inst{19-16} = 0b1111; // Rn
+ let Inst{15} = 0;
+ }
+ // register
+ def r : T2sTwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm), iir,
+ opc, ".w\t$Rd, $Rm",
+ [(set rGPR:$Rd, (opnode rGPR:$Rm))]> {
+ let Inst{31-27} = 0b11101;
+ let Inst{26-25} = 0b01;
+ let Inst{24-21} = opcod;
+ let Inst{19-16} = 0b1111; // Rn
+ let Inst{14-12} = 0b000; // imm3
+ let Inst{7-6} = 0b00; // imm2
+ let Inst{5-4} = 0b00; // type
+ }
+ // shifted register
+ def s : T2sOneRegShiftedReg<(outs rGPR:$Rd), (ins t2_so_reg:$ShiftedRm), iis,
+ opc, ".w\t$Rd, $ShiftedRm",
+ [(set rGPR:$Rd, (opnode t2_so_reg:$ShiftedRm))]> {
+ let Inst{31-27} = 0b11101;
+ let Inst{26-25} = 0b01;
+ let Inst{24-21} = opcod;
+ let Inst{19-16} = 0b1111; // Rn
+ }
+}
+
// Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version
let AddedComplexity = 1 in
defm t2MVN : T2I_un_irs <0b0011, "mvn",
IIC_iMVNi, IIC_iMVNr, IIC_iMVNsi,
UnOpFrag<(not node:$Src)>, 1, 1>;
-
let AddedComplexity = 1 in
def : T2Pat<(and rGPR:$src, t2_so_imm_not:$imm),
(t2BICri rGPR:$src, t2_so_imm_not:$imm)>;
@@ -2209,9 +2345,9 @@ def t2MLS: T2FourReg<
let neverHasSideEffects = 1 in {
let isCommutable = 1 in {
def t2SMULL : T2MulLong<0b000, 0b0000,
- (outs rGPR:$Rd, rGPR:$Ra),
+ (outs rGPR:$RdLo, rGPR:$RdHi),
(ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL64,
- "smull", "\t$Rd, $Ra, $Rn, $Rm", []>;
+ "smull", "\t$RdLo, $RdHi, $Rn, $Rm", []>;
def t2UMULL : T2MulLong<0b010, 0b0000,
(outs rGPR:$RdLo, rGPR:$RdHi),
@@ -2468,7 +2604,7 @@ multiclass T2I_smla<string opc, PatFrag opnode> {
defm t2SMUL : T2I_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
defm t2SMLA : T2I_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
-// Halfword multiple accumulate long: SMLAL<x><y> -- for disassembly only
+// Halfword multiple accumulate long: SMLAL<x><y>
def t2SMLALBB : T2FourReg_mac<1, 0b100, 0b1000, (outs rGPR:$Ra,rGPR:$Rd),
(ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlalbb", "\t$Ra, $Rd, $Rn, $Rm",
[/* For disassembly only; pattern left blank */]>,
@@ -2487,8 +2623,6 @@ def t2SMLALTT : T2FourReg_mac<1, 0b100, 0b1011, (outs rGPR:$Ra,rGPR:$Rd),
Requires<[IsThumb2, HasThumb2DSP]>;
// Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD
-// These are for disassembly only.
-
def t2SMUAD: T2ThreeReg_mac<
0, 0b010, 0b0000, (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm),
IIC_iMAC32, "smuad", "\t$Rd, $Rn, $Rm", []>,
@@ -2513,7 +2647,7 @@ def t2SMUSDX:T2ThreeReg_mac<
Requires<[IsThumb2, HasThumb2DSP]> {
let Inst{15-12} = 0b1111;
}
-def t2SMLAD : T2ThreeReg_mac<
+def t2SMLAD : T2FourReg_mac<
0, 0b010, 0b0000, (outs rGPR:$Rd),
(ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smlad",
"\t$Rd, $Rn, $Rm, $Ra", []>,
@@ -2532,20 +2666,20 @@ def t2SMLSDX : T2FourReg_mac<0, 0b100, 0b0001, (outs rGPR:$Rd),
"\t$Rd, $Rn, $Rm, $Ra", []>,
Requires<[IsThumb2, HasThumb2DSP]>;
def t2SMLALD : T2FourReg_mac<1, 0b100, 0b1100, (outs rGPR:$Ra,rGPR:$Rd),
- (ins rGPR:$Rm, rGPR:$Rn), IIC_iMAC64, "smlald",
- "\t$Ra, $Rd, $Rm, $Rn", []>,
+ (ins rGPR:$Rn, rGPR:$Rm), IIC_iMAC64, "smlald",
+ "\t$Ra, $Rd, $Rn, $Rm", []>,
Requires<[IsThumb2, HasThumb2DSP]>;
def t2SMLALDX : T2FourReg_mac<1, 0b100, 0b1101, (outs rGPR:$Ra,rGPR:$Rd),
- (ins rGPR:$Rm,rGPR:$Rn), IIC_iMAC64, "smlaldx",
- "\t$Ra, $Rd, $Rm, $Rn", []>,
+ (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlaldx",
+ "\t$Ra, $Rd, $Rn, $Rm", []>,
Requires<[IsThumb2, HasThumb2DSP]>;
def t2SMLSLD : T2FourReg_mac<1, 0b101, 0b1100, (outs rGPR:$Ra,rGPR:$Rd),
- (ins rGPR:$Rm,rGPR:$Rn), IIC_iMAC64, "smlsld",
- "\t$Ra, $Rd, $Rm, $Rn", []>,
+ (ins rGPR:$Rn,rGPR:$Rm), IIC_iMAC64, "smlsld",
+ "\t$Ra, $Rd, $Rn, $Rm", []>,
Requires<[IsThumb2, HasThumb2DSP]>;
def t2SMLSLDX : T2FourReg_mac<1, 0b101, 0b1101, (outs rGPR:$Ra,rGPR:$Rd),
(ins rGPR:$Rm,rGPR:$Rn), IIC_iMAC64, "smlsldx",
- "\t$Ra, $Rd, $Rm, $Rn", []>,
+ "\t$Ra, $Rd, $Rn, $Rm", []>,
Requires<[IsThumb2, HasThumb2DSP]>;
//===----------------------------------------------------------------------===//
@@ -2613,10 +2747,10 @@ def : T2Pat<(or (sra (shl rGPR:$Rm, (i32 24)), (i32 16)),
(t2REVSH rGPR:$Rm)>;
def t2PKHBT : T2ThreeReg<
- (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, shift_imm:$sh),
+ (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, pkh_lsl_amt:$sh),
IIC_iBITsi, "pkhbt", "\t$Rd, $Rn, $Rm$sh",
[(set rGPR:$Rd, (or (and rGPR:$Rn, 0xFFFF),
- (and (shl rGPR:$Rm, lsl_amt:$sh),
+ (and (shl rGPR:$Rm, pkh_lsl_amt:$sh),
0xFFFF0000)))]>,
Requires<[HasT2ExtractPack, IsThumb2]> {
let Inst{31-27} = 0b11101;
@@ -2625,9 +2759,9 @@ def t2PKHBT : T2ThreeReg<
let Inst{5} = 0; // BT form
let Inst{4} = 0;
- bits<8> sh;
- let Inst{14-12} = sh{7-5};
- let Inst{7-6} = sh{4-3};
+ bits<5> sh;
+ let Inst{14-12} = sh{4-2};
+ let Inst{7-6} = sh{1-0};
}
// Alternate cases for PKHBT where identities eliminate some nodes.
@@ -2635,16 +2769,16 @@ def : T2Pat<(or (and rGPR:$src1, 0xFFFF), (and rGPR:$src2, 0xFFFF0000)),
(t2PKHBT rGPR:$src1, rGPR:$src2, 0)>,
Requires<[HasT2ExtractPack, IsThumb2]>;
def : T2Pat<(or (and rGPR:$src1, 0xFFFF), (shl rGPR:$src2, imm16_31:$sh)),
- (t2PKHBT rGPR:$src1, rGPR:$src2, (lsl_shift_imm imm16_31:$sh))>,
+ (t2PKHBT rGPR:$src1, rGPR:$src2, imm16_31:$sh)>,
Requires<[HasT2ExtractPack, IsThumb2]>;
// Note: Shifts of 1-15 bits will be transformed to srl instead of sra and
// will match the pattern below.
def t2PKHTB : T2ThreeReg<
- (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, shift_imm:$sh),
+ (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, pkh_asr_amt:$sh),
IIC_iBITsi, "pkhtb", "\t$Rd, $Rn, $Rm$sh",
[(set rGPR:$Rd, (or (and rGPR:$Rn, 0xFFFF0000),
- (and (sra rGPR:$Rm, asr_amt:$sh),
+ (and (sra rGPR:$Rm, pkh_asr_amt:$sh),
0xFFFF)))]>,
Requires<[HasT2ExtractPack, IsThumb2]> {
let Inst{31-27} = 0b11101;
@@ -2653,19 +2787,19 @@ def t2PKHTB : T2ThreeReg<
let Inst{5} = 1; // TB form
let Inst{4} = 0;
- bits<8> sh;
- let Inst{14-12} = sh{7-5};
- let Inst{7-6} = sh{4-3};
+ bits<5> sh;
+ let Inst{14-12} = sh{4-2};
+ let Inst{7-6} = sh{1-0};
}
// 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 : T2Pat<(or (and rGPR:$src1, 0xFFFF0000), (srl rGPR:$src2, imm16_31:$sh)),
- (t2PKHTB rGPR:$src1, rGPR:$src2, (asr_shift_imm imm16_31:$sh))>,
+ (t2PKHTB rGPR:$src1, rGPR:$src2, imm16_31:$sh)>,
Requires<[HasT2ExtractPack, IsThumb2]>;
def : T2Pat<(or (and rGPR:$src1, 0xFFFF0000),
(and (srl rGPR:$src2, imm1_15:$sh), 0xFFFF)),
- (t2PKHTB rGPR:$src1, rGPR:$src2, (asr_shift_imm imm1_15:$sh))>,
+ (t2PKHTB rGPR:$src1, rGPR:$src2, imm1_15:$sh)>,
Requires<[HasT2ExtractPack, IsThumb2]>;
//===----------------------------------------------------------------------===//
@@ -2673,14 +2807,14 @@ def : T2Pat<(or (and rGPR:$src1, 0xFFFF0000),
//
defm t2CMP : T2I_cmp_irs<0b1101, "cmp",
IIC_iCMPi, IIC_iCMPr, IIC_iCMPsi,
- BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
+ BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>, "t2CMP">;
-def : T2Pat<(ARMcmpZ GPR:$lhs, t2_so_imm:$imm),
- (t2CMPri GPR:$lhs, t2_so_imm:$imm)>;
-def : T2Pat<(ARMcmpZ GPR:$lhs, rGPR:$rhs),
- (t2CMPrr GPR:$lhs, rGPR:$rhs)>;
-def : T2Pat<(ARMcmpZ GPR:$lhs, t2_so_reg:$rhs),
- (t2CMPrs GPR:$lhs, t2_so_reg:$rhs)>;
+def : T2Pat<(ARMcmpZ GPRnopc:$lhs, t2_so_imm:$imm),
+ (t2CMPri GPRnopc:$lhs, t2_so_imm:$imm)>;
+def : T2Pat<(ARMcmpZ GPRnopc:$lhs, rGPR:$rhs),
+ (t2CMPrr GPRnopc:$lhs, rGPR:$rhs)>;
+def : T2Pat<(ARMcmpZ GPRnopc:$lhs, t2_so_reg:$rhs),
+ (t2CMPrs GPRnopc:$lhs, t2_so_reg:$rhs)>;
//FIXME: Disable CMN, as CCodes are backwards from compare expectations
// Compare-to-zero still works out, just not the relationals
@@ -2688,20 +2822,23 @@ def : T2Pat<(ARMcmpZ GPR:$lhs, t2_so_reg:$rhs),
// BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;
defm t2CMNz : T2I_cmp_irs<0b1000, "cmn",
IIC_iCMPi, IIC_iCMPr, IIC_iCMPsi,
- BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>;
+ BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>,
+ "t2CMNz">;
//def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm),
// (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>;
-def : T2Pat<(ARMcmpZ GPR:$src, t2_so_imm_neg:$imm),
- (t2CMNzri GPR:$src, t2_so_imm_neg:$imm)>;
+def : T2Pat<(ARMcmpZ GPRnopc:$src, t2_so_imm_neg:$imm),
+ (t2CMNzri GPRnopc:$src, t2_so_imm_neg:$imm)>;
defm t2TST : T2I_cmp_irs<0b0000, "tst",
IIC_iTSTi, IIC_iTSTr, IIC_iTSTsi,
- BinOpFrag<(ARMcmpZ (and_su node:$LHS, node:$RHS), 0)>>;
+ BinOpFrag<(ARMcmpZ (and_su node:$LHS, node:$RHS), 0)>,
+ "t2TST">;
defm t2TEQ : T2I_cmp_irs<0b0100, "teq",
IIC_iTSTi, IIC_iTSTr, IIC_iTSTsi,
- BinOpFrag<(ARMcmpZ (xor_su node:$LHS, node:$RHS), 0)>>;
+ BinOpFrag<(ARMcmpZ (xor_su node:$LHS, node:$RHS), 0)>,
+ "t2TEQ">;
// Conditional moves
// FIXME: should be able to write a pattern for ARMcmov, but can't use
@@ -2723,7 +2860,7 @@ def t2MOVCCi : t2PseudoInst<(outs rGPR:$Rd),
// FIXME: Pseudo-ize these. For now, just mark codegen only.
let isCodeGenOnly = 1 in {
let isMoveImm = 1 in
-def t2MOVCCi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$false, i32imm_hilo16:$imm),
+def t2MOVCCi16 : T2I<(outs rGPR:$Rd), (ins rGPR:$false, imm0_65535_expr:$imm),
IIC_iCMOVi,
"movw", "\t$Rd, $imm", []>,
RegConstraint<"$false = $Rd"> {
@@ -2807,20 +2944,19 @@ def t2DMB : AInoP<(outs), (ins memb_opt:$opt), ThumbFrm, NoItinerary,
}
def t2DSB : AInoP<(outs), (ins memb_opt:$opt), ThumbFrm, NoItinerary,
- "dsb", "\t$opt",
- [/* For disassembly only; pattern left blank */]>,
+ "dsb", "\t$opt", []>,
Requires<[IsThumb, HasDB]> {
bits<4> opt;
let Inst{31-4} = 0xf3bf8f4;
let Inst{3-0} = opt;
}
-// ISB has only full system option -- for disassembly only
-def t2ISB : AInoP<(outs), (ins), ThumbFrm, NoItinerary, "isb", "",
- [/* For disassembly only; pattern left blank */]>,
- Requires<[IsThumb2, HasV7]> {
+def t2ISB : AInoP<(outs), (ins memb_opt:$opt), ThumbFrm, NoItinerary,
+ "isb", "\t$opt",
+ []>, Requires<[IsThumb2, HasDB]> {
+ bits<4> opt;
let Inst{31-4} = 0xf3bf8f6;
- let Inst{3-0} = 0b1111;
+ let Inst{3-0} = opt;
}
class T2I_ldrex<bits<2> opcod, dag oops, dag iops, AddrMode am, int sz,
@@ -2858,28 +2994,27 @@ class T2I_strex<bits<2> opcod, dag oops, dag iops, AddrMode am, int sz,
}
let mayLoad = 1 in {
-def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr),
+def t2LDREXB : T2I_ldrex<0b00, (outs rGPR:$Rt), (ins addr_offset_none:$addr),
AddrModeNone, 4, NoItinerary,
"ldrexb", "\t$Rt, $addr", "", []>;
-def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins t2addrmode_reg:$addr),
+def t2LDREXH : T2I_ldrex<0b01, (outs rGPR:$Rt), (ins addr_offset_none:$addr),
AddrModeNone, 4, NoItinerary,
"ldrexh", "\t$Rt, $addr", "", []>;
-def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_reg:$addr),
+def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_imm0_1020s4:$addr),
AddrModeNone, 4, NoItinerary,
"ldrex", "\t$Rt, $addr", "", []> {
+ bits<4> Rt;
+ bits<12> addr;
let Inst{31-27} = 0b11101;
let Inst{26-20} = 0b0000101;
- let Inst{11-8} = 0b1111;
- let Inst{7-0} = 0b00000000; // imm8 = 0
-
- bits<4> Rt;
- bits<4> addr;
- let Inst{19-16} = addr;
+ let Inst{19-16} = addr{11-8};
let Inst{15-12} = Rt;
+ let Inst{11-8} = 0b1111;
+ let Inst{7-0} = addr{7-0};
}
let hasExtraDefRegAllocReq = 1 in
def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2),
- (ins t2addrmode_reg:$addr),
+ (ins addr_offset_none:$addr),
AddrModeNone, 4, NoItinerary,
"ldrexd", "\t$Rt, $Rt2, $addr", "",
[], {?, ?, ?, ?}> {
@@ -2890,33 +3025,33 @@ def t2LDREXD : T2I_ldrex<0b11, (outs rGPR:$Rt, rGPR:$Rt2),
let mayStore = 1, Constraints = "@earlyclobber $Rd" in {
def t2STREXB : T2I_strex<0b00, (outs rGPR:$Rd),
- (ins rGPR:$Rt, t2addrmode_reg:$addr),
+ (ins rGPR:$Rt, addr_offset_none:$addr),
AddrModeNone, 4, NoItinerary,
"strexb", "\t$Rd, $Rt, $addr", "", []>;
def t2STREXH : T2I_strex<0b01, (outs rGPR:$Rd),
- (ins rGPR:$Rt, t2addrmode_reg:$addr),
+ (ins rGPR:$Rt, addr_offset_none:$addr),
AddrModeNone, 4, NoItinerary,
"strexh", "\t$Rd, $Rt, $addr", "", []>;
-def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt, t2addrmode_reg:$addr),
+def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt,
+ t2addrmode_imm0_1020s4:$addr),
AddrModeNone, 4, NoItinerary,
"strex", "\t$Rd, $Rt, $addr", "",
[]> {
- let Inst{31-27} = 0b11101;
- let Inst{26-20} = 0b0000100;
- let Inst{7-0} = 0b00000000; // imm8 = 0
-
bits<4> Rd;
- bits<4> addr;
bits<4> Rt;
- let Inst{11-8} = Rd;
- let Inst{19-16} = addr;
+ bits<12> addr;
+ let Inst{31-27} = 0b11101;
+ let Inst{26-20} = 0b0000100;
+ let Inst{19-16} = addr{11-8};
let Inst{15-12} = Rt;
+ let Inst{11-8} = Rd;
+ let Inst{7-0} = addr{7-0};
}
}
let hasExtraSrcRegAllocReq = 1, Constraints = "@earlyclobber $Rd" in
def t2STREXD : T2I_strex<0b11, (outs rGPR:$Rd),
- (ins rGPR:$Rt, rGPR:$Rt2, t2addrmode_reg:$addr),
+ (ins rGPR:$Rt, rGPR:$Rt2, addr_offset_none:$addr),
AddrModeNone, 4, NoItinerary,
"strexd", "\t$Rd, $Rt, $Rt2, $addr", "", [],
{?, ?, ?, ?}> {
@@ -2924,9 +3059,7 @@ def t2STREXD : T2I_strex<0b11, (outs rGPR:$Rd),
let Inst{11-8} = Rt2;
}
-// Clear-Exclusive is for disassembly only.
-def t2CLREX : T2XI<(outs), (ins), NoItinerary, "clrex",
- [/* For disassembly only; pattern left blank */]>,
+def t2CLREX : T2I<(outs), (ins), NoItinerary, "clrex", "", []>,
Requires<[IsThumb2, HasV7]> {
let Inst{31-16} = 0xf3bf;
let Inst{15-14} = 0b10;
@@ -2986,8 +3119,8 @@ def t2LDMIA_RET: t2PseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
let isPredicable = 1 in
-def t2B : T2XI<(outs), (ins uncondbrtarget:$target), IIC_Br,
- "b.w\t$target",
+def t2B : T2I<(outs), (ins uncondbrtarget:$target), IIC_Br,
+ "b", ".w\t$target",
[(br bb:$target)]> {
let Inst{31-27} = 0b11110;
let Inst{15-14} = 0b10;
@@ -3009,15 +3142,13 @@ def t2BR_JT : t2PseudoInst<(outs),
// FIXME: Add a non-pc based case that can be predicated.
def t2TBB_JT : t2PseudoInst<(outs),
- (ins GPR:$index, i32imm:$jt, i32imm:$id),
- 0, IIC_Br, []>;
+ (ins GPR:$index, i32imm:$jt, i32imm:$id), 0, IIC_Br, []>;
def t2TBH_JT : t2PseudoInst<(outs),
- (ins GPR:$index, i32imm:$jt, i32imm:$id),
- 0, IIC_Br, []>;
+ (ins GPR:$index, i32imm:$jt, i32imm:$id), 0, IIC_Br, []>;
-def t2TBB : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
- "tbb", "\t[$Rn, $Rm]", []> {
+def t2TBB : T2I<(outs), (ins addrmode_tbb:$addr), IIC_Br,
+ "tbb", "\t$addr", []> {
bits<4> Rn;
bits<4> Rm;
let Inst{31-20} = 0b111010001101;
@@ -3025,10 +3156,12 @@ def t2TBB : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
let Inst{15-5} = 0b11110000000;
let Inst{4} = 0; // B form
let Inst{3-0} = Rm;
+
+ let DecoderMethod = "DecodeThumbTableBranch";
}
-def t2TBH : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
- "tbh", "\t[$Rn, $Rm, lsl #1]", []> {
+def t2TBH : T2I<(outs), (ins addrmode_tbh:$addr), IIC_Br,
+ "tbh", "\t$addr", []> {
bits<4> Rn;
bits<4> Rm;
let Inst{31-20} = 0b111010001101;
@@ -3036,13 +3169,15 @@ def t2TBH : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
let Inst{15-5} = 0b11110000000;
let Inst{4} = 1; // H form
let Inst{3-0} = Rm;
+
+ let DecoderMethod = "DecodeThumbTableBranch";
}
} // isNotDuplicable, isIndirectBranch
} // isBranch, isTerminator, isBarrier
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
-// a two-value operand where a dag node expects two operands. :(
+// a two-value operand where a dag node expects ", "two operands. :(
let isBranch = 1, isTerminator = 1 in
def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
"b", ".w\t$target",
@@ -3060,6 +3195,8 @@ def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
let Inst{13} = target{18};
let Inst{21-16} = target{17-12};
let Inst{10-0} = target{11-1};
+
+ let DecoderMethod = "DecodeThumb2BCCInstruction";
}
// Tail calls. The Darwin version of thumb tail calls uses a t2 branch, so
@@ -3068,9 +3205,10 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
// Darwin version.
let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC],
Uses = [SP] in
- def tTAILJMPd: tPseudoExpand<(outs), (ins uncondbrtarget:$dst, variable_ops),
+ def tTAILJMPd: tPseudoExpand<(outs),
+ (ins uncondbrtarget:$dst, pred:$p, variable_ops),
4, IIC_Br, [],
- (t2B uncondbrtarget:$dst)>,
+ (t2B uncondbrtarget:$dst, pred:$p)>,
Requires<[IsThumb2, IsDarwin]>;
}
@@ -3087,30 +3225,55 @@ def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask),
bits<4> mask;
let Inst{7-4} = cc;
let Inst{3-0} = mask;
+
+ let DecoderMethod = "DecodeIT";
}
// Branch and Exchange Jazelle -- for disassembly only
// Rm = Inst{19-16}
-def t2BXJ : T2I<(outs), (ins rGPR:$func), NoItinerary, "bxj", "\t$func",
- [/* For disassembly only; pattern left blank */]> {
+def t2BXJ : T2I<(outs), (ins rGPR:$func), NoItinerary, "bxj", "\t$func", []> {
+ bits<4> func;
let Inst{31-27} = 0b11110;
let Inst{26} = 0;
let Inst{25-20} = 0b111100;
- let Inst{15-14} = 0b10;
- let Inst{12} = 0;
-
- bits<4> func;
let Inst{19-16} = func;
+ let Inst{15-0} = 0b1000111100000000;
+}
+
+// Compare and branch on zero / non-zero
+let isBranch = 1, isTerminator = 1 in {
+ def tCBZ : T1I<(outs), (ins tGPR:$Rn, t_cbtarget:$target), IIC_Br,
+ "cbz\t$Rn, $target", []>,
+ T1Misc<{0,0,?,1,?,?,?}>,
+ Requires<[IsThumb2]> {
+ // A8.6.27
+ bits<6> target;
+ bits<3> Rn;
+ let Inst{9} = target{5};
+ let Inst{7-3} = target{4-0};
+ let Inst{2-0} = Rn;
+ }
+
+ def tCBNZ : T1I<(outs), (ins tGPR:$Rn, t_cbtarget:$target), IIC_Br,
+ "cbnz\t$Rn, $target", []>,
+ T1Misc<{1,0,?,1,?,?,?}>,
+ Requires<[IsThumb2]> {
+ // A8.6.27
+ bits<6> target;
+ bits<3> Rn;
+ let Inst{9} = target{5};
+ let Inst{7-3} = target{4-0};
+ let Inst{2-0} = Rn;
+ }
}
-// Change Processor State is a system instruction -- for disassembly and
-// parsing only.
+
+// Change Processor State is a system instruction.
// 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.
class t2CPS<dag iops, string asm_op> : T2XI<(outs), iops, NoItinerary,
- !strconcat("cps", asm_op),
- [/* For disassembly only; pattern left blank */]> {
+ !strconcat("cps", asm_op), []> {
bits<2> imod;
bits<3> iflags;
bits<5> mode;
@@ -3126,6 +3289,7 @@ class t2CPS<dag iops, string asm_op> : T2XI<(outs), iops, NoItinerary,
let Inst{8} = M;
let Inst{7-5} = iflags;
let Inst{4-0} = mode;
+ let DecoderMethod = "DecodeT2CPSInstruction";
}
let M = 1 in
@@ -3135,14 +3299,12 @@ let mode = 0, M = 0 in
def t2CPS2p : t2CPS<(ins imod_op:$imod, iflags_op:$iflags),
"$imod.w\t$iflags">;
let imod = 0, iflags = 0, M = 1 in
- def t2CPS1p : t2CPS<(ins i32imm:$mode), "\t$mode">;
+ def t2CPS1p : t2CPS<(ins imm0_31:$mode), "\t$mode">;
// A6.3.4 Branches and miscellaneous control
// Table A6-14 Change Processor State, and hint instructions
-// Helper class for disassembly only.
class T2I_hint<bits<8> op7_0, string opc, string asm>
- : T2I<(outs), (ins), NoItinerary, opc, asm,
- [/* For disassembly only; pattern left blank */]> {
+ : T2I<(outs), (ins), NoItinerary, opc, asm, []> {
let Inst{31-20} = 0xf3a;
let Inst{19-16} = 0b1111;
let Inst{15-14} = 0b10;
@@ -3158,20 +3320,17 @@ def t2WFI : T2I_hint<0b00000011, "wfi", ".w">;
def t2SEV : T2I_hint<0b00000100, "sev", ".w">;
def t2DBG : T2I<(outs), (ins imm0_15:$opt), NoItinerary, "dbg", "\t$opt", []> {
- let Inst{31-20} = 0xf3a;
- let Inst{15-14} = 0b10;
- let Inst{12} = 0;
- let Inst{10-8} = 0b000;
- let Inst{7-4} = 0b1111;
-
bits<4> opt;
+ let Inst{31-20} = 0b111100111010;
+ let Inst{19-16} = 0b1111;
+ let Inst{15-8} = 0b10000000;
+ let Inst{7-4} = 0b1111;
let Inst{3-0} = opt;
}
-// Secure Monitor Call is a system instruction -- for disassembly only
+// Secure Monitor Call is a system instruction.
// Option = Inst{19-16}
-def t2SMC : T2I<(outs), (ins i32imm:$opt), NoItinerary, "smc", "\t$opt",
- [/* For disassembly only; pattern left blank */]> {
+def t2SMC : T2I<(outs), (ins imm0_15:$opt), NoItinerary, "smc", "\t$opt", []> {
let Inst{31-27} = 0b11110;
let Inst{26-20} = 0b1111111;
let Inst{15-12} = 0b1000;
@@ -3180,32 +3339,30 @@ def t2SMC : T2I<(outs), (ins i32imm:$opt), NoItinerary, "smc", "\t$opt",
let Inst{19-16} = opt;
}
-class T2SRS<bits<12> op31_20,
- dag oops, dag iops, InstrItinClass itin,
- string opc, string asm, list<dag> pattern>
+class T2SRS<bits<2> Op, bit W, dag oops, dag iops, InstrItinClass itin,
+ string opc, string asm, list<dag> pattern>
: T2I<oops, iops, itin, opc, asm, pattern> {
- let Inst{31-20} = op31_20{11-0};
-
bits<5> mode;
+ let Inst{31-25} = 0b1110100;
+ let Inst{24-23} = Op;
+ let Inst{22} = 0;
+ let Inst{21} = W;
+ let Inst{20-16} = 0b01101;
+ let Inst{15-5} = 0b11000000000;
let Inst{4-0} = mode{4-0};
}
-// Store Return State is a system instruction -- for disassembly only
-def t2SRSDBW : T2SRS<0b111010000010,
- (outs),(ins i32imm:$mode),NoItinerary,"srsdb","\tsp!, $mode",
- [/* For disassembly only; pattern left blank */]>;
-def t2SRSDB : T2SRS<0b111010000000,
- (outs),(ins i32imm:$mode),NoItinerary,"srsdb","\tsp, $mode",
- [/* For disassembly only; pattern left blank */]>;
-def t2SRSIAW : T2SRS<0b111010011010,
- (outs),(ins i32imm:$mode),NoItinerary,"srsia","\tsp!, $mode",
- [/* For disassembly only; pattern left blank */]>;
-def t2SRSIA : T2SRS<0b111010011000,
- (outs), (ins i32imm:$mode),NoItinerary,"srsia","\tsp, $mode",
- [/* For disassembly only; pattern left blank */]>;
-
-// Return From Exception is a system instruction -- for disassembly only
+// Store Return State is a system instruction.
+def t2SRSDB_UPD : T2SRS<0b00, 1, (outs), (ins imm0_31:$mode), NoItinerary,
+ "srsdb", "\tsp!, $mode", []>;
+def t2SRSDB : T2SRS<0b00, 0, (outs), (ins imm0_31:$mode), NoItinerary,
+ "srsdb","\tsp, $mode", []>;
+def t2SRSIA_UPD : T2SRS<0b11, 1, (outs), (ins imm0_31:$mode), NoItinerary,
+ "srsia","\tsp!, $mode", []>;
+def t2SRSIA : T2SRS<0b11, 0, (outs), (ins imm0_31:$mode), NoItinerary,
+ "srsia","\tsp, $mode", []>;
+// Return From Exception is a system instruction.
class T2RFE<bits<12> op31_20, dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
: T2I<oops, iops, itin, opc, asm, pattern> {
@@ -3277,53 +3434,186 @@ def t2LDRpci_pic : PseudoInst<(outs rGPR:$dst), (ins i32imm:$addr, pclabel:$cp),
imm:$cp))]>,
Requires<[IsThumb2]>;
+// Pseudo isntruction that combines movs + predicated rsbmi
+// to implement integer ABS
+let usesCustomInserter = 1, Defs = [CPSR] in {
+def t2ABS : PseudoInst<(outs rGPR:$dst), (ins rGPR:$src),
+ NoItinerary, []>, Requires<[IsThumb2]>;
+}
+
+//===----------------------------------------------------------------------===//
+// Coprocessor load/store -- for disassembly only
+//
+class T2CI<bits<4> op31_28, dag oops, dag iops, string opc, string asm>
+ : T2I<oops, iops, NoItinerary, opc, asm, []> {
+ let Inst{31-28} = op31_28;
+ let Inst{27-25} = 0b110;
+}
+
+multiclass t2LdStCop<bits<4> op31_28, bit load, bit Dbit, string asm> {
+ def _OFFSET : T2CI<op31_28,
+ (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{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 : T2CI<op31_28,
+ (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} = 1; // W = 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 _POST: T2CI<op31_28,
+ (outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
+ postidx_imm8s4:$offset),
+ asm, "\t$cop, $CRd, $addr, $offset"> {
+ 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{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 : T2CI<op31_28, (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{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 t2LDC : t2LdStCop<0b1110, 1, 0, "ldc">;
+defm t2LDCL : t2LdStCop<0b1110, 1, 1, "ldcl">;
+defm t2STC : t2LdStCop<0b1110, 0, 0, "stc">;
+defm t2STCL : t2LdStCop<0b1110, 0, 1, "stcl">;
+defm t2LDC2 : t2LdStCop<0b1111, 1, 0, "ldc2">;
+defm t2LDC2L : t2LdStCop<0b1111, 1, 1, "ldc2l">;
+defm t2STC2 : t2LdStCop<0b1111, 0, 0, "stc2">;
+defm t2STC2L : t2LdStCop<0b1111, 0, 1, "stc2l">;
+
+
//===----------------------------------------------------------------------===//
// Move between special register and ARM core register -- for disassembly only
//
+// Move to ARM core register from Special Register
-class T2SpecialReg<bits<12> op31_20, bits<2> op15_14, bits<1> op12,
- dag oops, dag iops, InstrItinClass itin,
- string opc, string asm, list<dag> pattern>
- : T2I<oops, iops, itin, opc, asm, pattern> {
- let Inst{31-20} = op31_20{11-0};
- let Inst{15-14} = op15_14{1-0};
- let Inst{12} = op12{0};
+// A/R class MRS.
+//
+// A/R class can only move from CPSR or SPSR.
+def t2MRS_AR : T2I<(outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, apsr", []>,
+ Requires<[IsThumb2,IsARClass]> {
+ bits<4> Rd;
+ let Inst{31-12} = 0b11110011111011111000;
+ let Inst{11-8} = Rd;
+ let Inst{7-0} = 0b0000;
}
-class T2MRS<bits<12> op31_20, bits<2> op15_14, bits<1> op12,
- dag oops, dag iops, InstrItinClass itin,
- string opc, string asm, list<dag> pattern>
- : T2SpecialReg<op31_20, op15_14, op12, oops, iops, itin, opc, asm, pattern> {
+def : t2InstAlias<"mrs${p} $Rd, cpsr", (t2MRS_AR GPR:$Rd, pred:$p)>;
+
+def t2MRSsys_AR: T2I<(outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, spsr", []>,
+ Requires<[IsThumb2,IsARClass]> {
bits<4> Rd;
+ let Inst{31-12} = 0b11110011111111111000;
+ let Inst{11-8} = Rd;
+ let Inst{7-0} = 0b0000;
+}
+
+// M class MRS.
+//
+// This MRS has a mask field in bits 7-0 and can take more values than
+// the A/R class (a full msr_mask).
+def t2MRS_M : T2I<(outs rGPR:$Rd), (ins msr_mask:$mask), NoItinerary,
+ "mrs", "\t$Rd, $mask", []>,
+ Requires<[IsThumb2,IsMClass]> {
+ bits<4> Rd;
+ bits<8> mask;
+ let Inst{31-12} = 0b11110011111011111000;
let Inst{11-8} = Rd;
let Inst{19-16} = 0b1111;
+ let Inst{7-0} = mask;
}
-def t2MRS : T2MRS<0b111100111110, 0b10, 0,
- (outs rGPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, cpsr",
- [/* For disassembly only; pattern left blank */]>;
-def t2MRSsys : T2MRS<0b111100111111, 0b10, 0,
- (outs rGPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, spsr",
- [/* For disassembly only; pattern left blank */]>;
// Move from ARM core register to Special Register
//
+// A/R class MSR.
+//
// No need to have both system and application versions, the encodings are the
// same and the assembly parser has no way to distinguish between them. The mask
// 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 t2MSR : T2SpecialReg<0b111100111000 /* op31-20 */, 0b10 /* op15-14 */,
- 0 /* op12 */, (outs), (ins msr_mask:$mask, rGPR:$Rn),
- NoItinerary, "msr", "\t$mask, $Rn",
- [/* For disassembly only; pattern left blank */]> {
+def t2MSR_AR : T2I<(outs), (ins msr_mask:$mask, rGPR:$Rn),
+ NoItinerary, "msr", "\t$mask, $Rn", []>,
+ Requires<[IsThumb2,IsARClass]> {
bits<5> mask;
bits<4> Rn;
- let Inst{19-16} = Rn;
+ let Inst{31-21} = 0b11110011100;
let Inst{20} = mask{4}; // R Bit
- let Inst{13} = 0b0;
+ let Inst{19-16} = Rn;
+ let Inst{15-12} = 0b1000;
let Inst{11-8} = mask{3-0};
+ let Inst{7-0} = 0;
}
+// M class MSR.
+//
+// Move from ARM core register to Special Register
+def t2MSR_M : T2I<(outs), (ins msr_mask:$SYSm, rGPR:$Rn),
+ NoItinerary, "msr", "\t$SYSm, $Rn", []>,
+ Requires<[IsThumb2,IsMClass]> {
+ bits<8> SYSm;
+ bits<4> Rn;
+ let Inst{31-21} = 0b11110011100;
+ let Inst{20} = 0b0;
+ let Inst{19-16} = Rn;
+ let Inst{15-12} = 0b1000;
+ let Inst{7-0} = SYSm;
+}
+
+
//===----------------------------------------------------------------------===//
// Move between coprocessor and ARM core register
//
@@ -3389,13 +3679,12 @@ def t2MCR2 : t2MovRCopro<0b1111, "mcr2", 0,
/* from coprocessor to ARM core register */
def t2MRC : t2MovRCopro<0b1110, "mrc", 1,
- (outs GPR:$Rt),
- (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2),
- []>;
+ (outs GPR:$Rt), (ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn,
+ c_imm:$CRm, imm0_7:$opc2), []>;
def t2MRC2 : t2MovRCopro<0b1111, "mrc2", 1,
- (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn,
- c_imm:$CRm, i32imm:$opc2), []>;
+ (outs GPR:$Rt), (ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn,
+ c_imm:$CRm, imm0_7:$opc2), []>;
def : T2v6Pat<(int_arm_mrc imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2),
(t2MRC imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>;
@@ -3465,3 +3754,269 @@ def t2CDP2 : T2Cop<0b1111, (outs), (ins p_imm:$cop, imm0_15:$opc1,
let Inst{19-16} = CRn;
let Inst{23-20} = opc1;
}
+
+
+
+//===----------------------------------------------------------------------===//
+// Non-Instruction Patterns
+//
+
+// SXT/UXT with no rotate
+let AddedComplexity = 16 in {
+def : T2Pat<(and rGPR:$Rm, 0x000000FF), (t2UXTB rGPR:$Rm, 0)>,
+ Requires<[IsThumb2]>;
+def : T2Pat<(and rGPR:$Rm, 0x0000FFFF), (t2UXTH rGPR:$Rm, 0)>,
+ Requires<[IsThumb2]>;
+def : T2Pat<(and rGPR:$Rm, 0x00FF00FF), (t2UXTB16 rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+def : T2Pat<(add rGPR:$Rn, (and rGPR:$Rm, 0x00FF)),
+ (t2UXTAB rGPR:$Rn, rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+def : T2Pat<(add rGPR:$Rn, (and rGPR:$Rm, 0xFFFF)),
+ (t2UXTAH rGPR:$Rn, rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+}
+
+def : T2Pat<(sext_inreg rGPR:$Src, i8), (t2SXTB rGPR:$Src, 0)>,
+ Requires<[IsThumb2]>;
+def : T2Pat<(sext_inreg rGPR:$Src, i16), (t2SXTH rGPR:$Src, 0)>,
+ Requires<[IsThumb2]>;
+def : T2Pat<(add rGPR:$Rn, (sext_inreg rGPR:$Rm, i8)),
+ (t2SXTAB rGPR:$Rn, rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+def : T2Pat<(add rGPR:$Rn, (sext_inreg rGPR:$Rm, i16)),
+ (t2SXTAH rGPR:$Rn, rGPR:$Rm, 0)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+
+// Atomic load/store patterns
+def : T2Pat<(atomic_load_8 t2addrmode_imm12:$addr),
+ (t2LDRBi12 t2addrmode_imm12:$addr)>;
+def : T2Pat<(atomic_load_8 t2addrmode_negimm8:$addr),
+ (t2LDRBi8 t2addrmode_negimm8:$addr)>;
+def : T2Pat<(atomic_load_8 t2addrmode_so_reg:$addr),
+ (t2LDRBs t2addrmode_so_reg:$addr)>;
+def : T2Pat<(atomic_load_16 t2addrmode_imm12:$addr),
+ (t2LDRHi12 t2addrmode_imm12:$addr)>;
+def : T2Pat<(atomic_load_16 t2addrmode_negimm8:$addr),
+ (t2LDRHi8 t2addrmode_negimm8:$addr)>;
+def : T2Pat<(atomic_load_16 t2addrmode_so_reg:$addr),
+ (t2LDRHs t2addrmode_so_reg:$addr)>;
+def : T2Pat<(atomic_load_32 t2addrmode_imm12:$addr),
+ (t2LDRi12 t2addrmode_imm12:$addr)>;
+def : T2Pat<(atomic_load_32 t2addrmode_negimm8:$addr),
+ (t2LDRi8 t2addrmode_negimm8:$addr)>;
+def : T2Pat<(atomic_load_32 t2addrmode_so_reg:$addr),
+ (t2LDRs t2addrmode_so_reg:$addr)>;
+def : T2Pat<(atomic_store_8 t2addrmode_imm12:$addr, GPR:$val),
+ (t2STRBi12 GPR:$val, t2addrmode_imm12:$addr)>;
+def : T2Pat<(atomic_store_8 t2addrmode_negimm8:$addr, GPR:$val),
+ (t2STRBi8 GPR:$val, t2addrmode_negimm8:$addr)>;
+def : T2Pat<(atomic_store_8 t2addrmode_so_reg:$addr, GPR:$val),
+ (t2STRBs GPR:$val, t2addrmode_so_reg:$addr)>;
+def : T2Pat<(atomic_store_16 t2addrmode_imm12:$addr, GPR:$val),
+ (t2STRHi12 GPR:$val, t2addrmode_imm12:$addr)>;
+def : T2Pat<(atomic_store_16 t2addrmode_negimm8:$addr, GPR:$val),
+ (t2STRHi8 GPR:$val, t2addrmode_negimm8:$addr)>;
+def : T2Pat<(atomic_store_16 t2addrmode_so_reg:$addr, GPR:$val),
+ (t2STRHs GPR:$val, t2addrmode_so_reg:$addr)>;
+def : T2Pat<(atomic_store_32 t2addrmode_imm12:$addr, GPR:$val),
+ (t2STRi12 GPR:$val, t2addrmode_imm12:$addr)>;
+def : T2Pat<(atomic_store_32 t2addrmode_negimm8:$addr, GPR:$val),
+ (t2STRi8 GPR:$val, t2addrmode_negimm8:$addr)>;
+def : T2Pat<(atomic_store_32 t2addrmode_so_reg:$addr, GPR:$val),
+ (t2STRs GPR:$val, t2addrmode_so_reg:$addr)>;
+
+
+//===----------------------------------------------------------------------===//
+// Assembler aliases
+//
+
+// Aliases for ADC without the ".w" optional width specifier.
+def : t2InstAlias<"adc${s}${p} $Rd, $Rn, $Rm",
+ (t2ADCrr rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>;
+def : t2InstAlias<"adc${s}${p} $Rd, $Rn, $ShiftedRm",
+ (t2ADCrs rGPR:$Rd, rGPR:$Rn, t2_so_reg:$ShiftedRm,
+ pred:$p, cc_out:$s)>;
+
+// Aliases for SBC without the ".w" optional width specifier.
+def : t2InstAlias<"sbc${s}${p} $Rd, $Rn, $Rm",
+ (t2SBCrr rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>;
+def : t2InstAlias<"sbc${s}${p} $Rd, $Rn, $ShiftedRm",
+ (t2SBCrs rGPR:$Rd, rGPR:$Rn, t2_so_reg:$ShiftedRm,
+ pred:$p, cc_out:$s)>;
+
+// Aliases for ADD without the ".w" optional width specifier.
+def : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm",
+ (t2ADDri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
+def : t2InstAlias<"add${p} $Rd, $Rn, $imm",
+ (t2ADDri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095:$imm, pred:$p)>;
+def : t2InstAlias<"add${s}${p} $Rd, $Rn, $Rm",
+ (t2ADDrr GPRnopc:$Rd, GPRnopc:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>;
+def : t2InstAlias<"add${s}${p} $Rd, $Rn, $ShiftedRm",
+ (t2ADDrs GPRnopc:$Rd, GPRnopc:$Rn, t2_so_reg:$ShiftedRm,
+ pred:$p, cc_out:$s)>;
+
+// Aliases for SUB without the ".w" optional width specifier.
+def : t2InstAlias<"sub${s}${p} $Rd, $Rn, $imm",
+ (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
+def : t2InstAlias<"sub${p} $Rd, $Rn, $imm",
+ (t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095:$imm, pred:$p)>;
+def : t2InstAlias<"sub${s}${p} $Rd, $Rn, $Rm",
+ (t2SUBrr GPRnopc:$Rd, GPRnopc:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>;
+def : t2InstAlias<"sub${s}${p} $Rd, $Rn, $ShiftedRm",
+ (t2SUBrs GPRnopc:$Rd, GPRnopc:$Rn, t2_so_reg:$ShiftedRm,
+ pred:$p, cc_out:$s)>;
+
+// Alias for compares without the ".w" optional width specifier.
+def : t2InstAlias<"cmn${p} $Rn, $Rm",
+ (t2CMNzrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>;
+def : t2InstAlias<"teq${p} $Rn, $Rm",
+ (t2TEQrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>;
+def : t2InstAlias<"tst${p} $Rn, $Rm",
+ (t2TSTrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>;
+
+// Memory barriers
+def : InstAlias<"dmb", (t2DMB 0xf)>, Requires<[IsThumb2, HasDB]>;
+def : InstAlias<"dsb", (t2DSB 0xf)>, Requires<[IsThumb2, HasDB]>;
+def : InstAlias<"isb", (t2ISB 0xf)>, Requires<[IsThumb2, HasDB]>;
+
+// Alias for LDR, LDRB, LDRH, LDRSB, and LDRSH without the ".w" optional
+// width specifier.
+def : t2InstAlias<"ldr${p} $Rt, $addr",
+ (t2LDRi12 GPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
+def : t2InstAlias<"ldrb${p} $Rt, $addr",
+ (t2LDRBi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
+def : t2InstAlias<"ldrh${p} $Rt, $addr",
+ (t2LDRHi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
+def : t2InstAlias<"ldrsb${p} $Rt, $addr",
+ (t2LDRSBi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
+def : t2InstAlias<"ldrsh${p} $Rt, $addr",
+ (t2LDRSHi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
+
+def : t2InstAlias<"ldr${p} $Rt, $addr",
+ (t2LDRs GPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
+def : t2InstAlias<"ldrb${p} $Rt, $addr",
+ (t2LDRBs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
+def : t2InstAlias<"ldrh${p} $Rt, $addr",
+ (t2LDRHs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
+def : t2InstAlias<"ldrsb${p} $Rt, $addr",
+ (t2LDRSBs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
+def : t2InstAlias<"ldrsh${p} $Rt, $addr",
+ (t2LDRSHs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
+
+// Alias for MVN without the ".w" optional width specifier.
+def : t2InstAlias<"mvn${s}${p} $Rd, $Rm",
+ (t2MVNr rGPR:$Rd, rGPR:$Rm, pred:$p, cc_out:$s)>;
+def : t2InstAlias<"mvn${s}${p} $Rd, $ShiftedRm",
+ (t2MVNs rGPR:$Rd, t2_so_reg:$ShiftedRm, pred:$p, cc_out:$s)>;
+
+// 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",
+ (t2PKHBT rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+def : InstAlias<"pkhtb${p} $Rd, $Rn, $Rm",
+ (t2PKHBT rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>,
+ Requires<[HasT2ExtractPack, IsThumb2]>;
+
+// PUSH/POP aliases for STM/LDM
+def : t2InstAlias<"push${p}.w $regs", (t2STMDB_UPD SP, pred:$p, reglist:$regs)>;
+def : t2InstAlias<"push${p} $regs", (t2STMDB_UPD SP, pred:$p, reglist:$regs)>;
+def : t2InstAlias<"pop${p}.w $regs", (t2LDMIA_UPD SP, pred:$p, reglist:$regs)>;
+def : t2InstAlias<"pop${p} $regs", (t2LDMIA_UPD SP, pred:$p, reglist:$regs)>;
+
+// Alias for REV/REV16/REVSH without the ".w" optional width specifier.
+def : t2InstAlias<"rev${p} $Rd, $Rm", (t2REV rGPR:$Rd, rGPR:$Rm, pred:$p)>;
+def : t2InstAlias<"rev16${p} $Rd, $Rm", (t2REV16 rGPR:$Rd, rGPR:$Rm, pred:$p)>;
+def : t2InstAlias<"revsh${p} $Rd, $Rm", (t2REVSH rGPR:$Rd, rGPR:$Rm, pred:$p)>;
+
+
+// Alias for RSB without the ".w" optional width specifier, and with optional
+// implied destination register.
+def : t2InstAlias<"rsb${s}${p} $Rd, $Rn, $imm",
+ (t2RSBri rGPR:$Rd, rGPR:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
+def : t2InstAlias<"rsb${s}${p} $Rdn, $imm",
+ (t2RSBri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
+def : t2InstAlias<"rsb${s}${p} $Rdn, $Rm",
+ (t2RSBrr rGPR:$Rdn, rGPR:$Rdn, rGPR:$Rm, pred:$p, cc_out:$s)>;
+def : t2InstAlias<"rsb${s}${p} $Rdn, $ShiftedRm",
+ (t2RSBrs rGPR:$Rdn, rGPR:$Rdn, t2_so_reg:$ShiftedRm, pred:$p,
+ cc_out:$s)>;
+
+// SSAT/USAT optional shift operand.
+def : t2InstAlias<"ssat${p} $Rd, $sat_imm, $Rn",
+ (t2SSAT rGPR:$Rd, imm1_32:$sat_imm, rGPR:$Rn, 0, pred:$p)>;
+def : t2InstAlias<"usat${p} $Rd, $sat_imm, $Rn",
+ (t2USAT rGPR:$Rd, imm0_31:$sat_imm, rGPR:$Rn, 0, pred:$p)>;
+
+// STM w/o the .w suffix.
+def : t2InstAlias<"stm${p} $Rn, $regs",
+ (t2STMIA GPR:$Rn, pred:$p, reglist:$regs)>;
+
+// Alias for STR, STRB, and STRH without the ".w" optional
+// width specifier.
+def : t2InstAlias<"str${p} $Rt, $addr",
+ (t2STRi12 GPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
+def : t2InstAlias<"strb${p} $Rt, $addr",
+ (t2STRBi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
+def : t2InstAlias<"strh${p} $Rt, $addr",
+ (t2STRHi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>;
+
+def : t2InstAlias<"str${p} $Rt, $addr",
+ (t2STRs GPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
+def : t2InstAlias<"strb${p} $Rt, $addr",
+ (t2STRBs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
+def : t2InstAlias<"strh${p} $Rt, $addr",
+ (t2STRHs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>;
+
+// Extend instruction optional rotate operand.
+def : t2InstAlias<"sxtab${p} $Rd, $Rn, $Rm",
+ (t2SXTAB rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"sxtah${p} $Rd, $Rn, $Rm",
+ (t2SXTAH rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"sxtab16${p} $Rd, $Rn, $Rm",
+ (t2SXTAB16 rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
+
+def : t2InstAlias<"sxtb${p} $Rd, $Rm",
+ (t2SXTB rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"sxtb16${p} $Rd, $Rm",
+ (t2SXTB16 rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"sxth${p} $Rd, $Rm",
+ (t2SXTH rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"sxtb${p}.w $Rd, $Rm",
+ (t2SXTB rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"sxth${p}.w $Rd, $Rm",
+ (t2SXTH rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
+
+def : t2InstAlias<"uxtab${p} $Rd, $Rn, $Rm",
+ (t2UXTAB rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"uxtah${p} $Rd, $Rn, $Rm",
+ (t2UXTAH rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"uxtab16${p} $Rd, $Rn, $Rm",
+ (t2UXTAB16 rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"uxtb${p} $Rd, $Rm",
+ (t2UXTB rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"uxtb16${p} $Rd, $Rm",
+ (t2UXTB16 rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"uxth${p} $Rd, $Rm",
+ (t2UXTH rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
+
+def : t2InstAlias<"uxtb${p}.w $Rd, $Rm",
+ (t2UXTB rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
+def : t2InstAlias<"uxth${p}.w $Rd, $Rm",
+ (t2UXTH rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
+
+// Extend instruction w/o the ".w" optional width specifier.
+def : t2InstAlias<"uxtb${p} $Rd, $Rm$rot",
+ (t2UXTB rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
+def : t2InstAlias<"uxtb16${p} $Rd, $Rm$rot",
+ (t2UXTB16 rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
+def : t2InstAlias<"uxth${p} $Rd, $Rm$rot",
+ (t2UXTH rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
+
+def : t2InstAlias<"sxtb${p} $Rd, $Rm$rot",
+ (t2SXTB rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
+def : t2InstAlias<"sxtb16${p} $Rd, $Rm$rot",
+ (t2SXTB16 rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
+def : t2InstAlias<"sxth${p} $Rd, $Rm$rot",
+ (t2SXTH rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td
index f1f3cb9..e746cf2 100644
--- a/lib/Target/ARM/ARMInstrVFP.td
+++ b/lib/Target/ARM/ARMInstrVFP.td
@@ -31,18 +31,34 @@ def arm_fmdrr : SDNode<"ARMISD::VMOVDRR", SDT_VMOVDRR>;
// Operand Definitions.
//
+// 8-bit floating-point immediate encodings.
+def FPImmOperand : AsmOperandClass {
+ let Name = "FPImm";
+ let ParserMethod = "parseFPImm";
+}
+
def vfp_f32imm : Operand<f32>,
PatLeaf<(f32 fpimm), [{
- return ARM::getVFPf32Imm(N->getValueAPF()) != -1;
- }]> {
- let PrintMethod = "printVFPf32ImmOperand";
+ return ARM_AM::getFP32Imm(N->getValueAPF()) != -1;
+ }], SDNodeXForm<fpimm, [{
+ APFloat InVal = N->getValueAPF();
+ uint32_t enc = ARM_AM::getFP32Imm(InVal);
+ return CurDAG->getTargetConstant(enc, MVT::i32);
+ }]>> {
+ let PrintMethod = "printFPImmOperand";
+ let ParserMatchClass = FPImmOperand;
}
def vfp_f64imm : Operand<f64>,
PatLeaf<(f64 fpimm), [{
- return ARM::getVFPf64Imm(N->getValueAPF()) != -1;
- }]> {
- let PrintMethod = "printVFPf64ImmOperand";
+ return ARM_AM::getFP64Imm(N->getValueAPF()) != -1;
+ }], SDNodeXForm<fpimm, [{
+ APFloat InVal = N->getValueAPF();
+ uint32_t enc = ARM_AM::getFP64Imm(InVal);
+ return CurDAG->getTargetConstant(enc, MVT::i32);
+ }]>> {
+ let PrintMethod = "printFPImmOperand";
+ let ParserMatchClass = FPImmOperand;
}
@@ -385,26 +401,26 @@ def VCVTSD : VFPAI<(outs SPR:$Sd), (ins DPR:$Dm), VFPUnaryFrm,
// Between half-precision and single-precision. For disassembly only.
// FIXME: Verify encoding after integrated assembler is working.
-def VCVTBSH: ASuI<0b11101, 0b11, 0b0010, 0b01, 0, (outs SPR:$dst), (ins SPR:$a),
- /* FIXME */ IIC_fpCVTSH, "vcvtb", ".f32.f16\t$dst, $a",
+def VCVTBSH: ASuI<0b11101, 0b11, 0b0010, 0b01, 0, (outs SPR:$Sd), (ins SPR:$Sm),
+ /* FIXME */ IIC_fpCVTSH, "vcvtb", ".f32.f16\t$Sd, $Sm",
[/* For disassembly only; pattern left blank */]>;
def : ARMPat<(f32_to_f16 SPR:$a),
(i32 (COPY_TO_REGCLASS (VCVTBSH SPR:$a), GPR))>;
-def VCVTBHS: ASuI<0b11101, 0b11, 0b0011, 0b01, 0, (outs SPR:$dst), (ins SPR:$a),
- /* FIXME */ IIC_fpCVTHS, "vcvtb", ".f16.f32\t$dst, $a",
+def VCVTBHS: ASuI<0b11101, 0b11, 0b0011, 0b01, 0, (outs SPR:$Sd), (ins SPR:$Sm),
+ /* FIXME */ IIC_fpCVTHS, "vcvtb", ".f16.f32\t$Sd, $Sm",
[/* For disassembly only; pattern left blank */]>;
def : ARMPat<(f16_to_f32 GPR:$a),
(VCVTBHS (COPY_TO_REGCLASS GPR:$a, SPR))>;
-def VCVTTSH: ASuI<0b11101, 0b11, 0b0010, 0b11, 0, (outs SPR:$dst), (ins SPR:$a),
- /* FIXME */ IIC_fpCVTSH, "vcvtt", ".f32.f16\t$dst, $a",
+def VCVTTSH: ASuI<0b11101, 0b11, 0b0010, 0b11, 0, (outs SPR:$Sd), (ins SPR:$Sm),
+ /* FIXME */ IIC_fpCVTSH, "vcvtt", ".f32.f16\t$Sd, $Sm",
[/* For disassembly only; pattern left blank */]>;
-def VCVTTHS: ASuI<0b11101, 0b11, 0b0011, 0b11, 0, (outs SPR:$dst), (ins SPR:$a),
- /* FIXME */ IIC_fpCVTHS, "vcvtt", ".f16.f32\t$dst, $a",
+def VCVTTHS: ASuI<0b11101, 0b11, 0b0011, 0b11, 0, (outs SPR:$Sd), (ins SPR:$Sm),
+ /* FIXME */ IIC_fpCVTHS, "vcvtt", ".f16.f32\t$Sd, $Sm",
[/* For disassembly only; pattern left blank */]>;
def VNEGD : ADuI<0b11101, 0b11, 0b0001, 0b01, 0,
@@ -511,14 +527,25 @@ def VMOVRRD : AVConv3I<0b11000101, 0b1011,
}
def VMOVRRS : AVConv3I<0b11000101, 0b1010,
- (outs GPR:$wb, GPR:$dst2), (ins SPR:$src1, SPR:$src2),
- IIC_fpMOVDI, "vmov", "\t$wb, $dst2, $src1, $src2",
+ (outs GPR:$Rt, GPR:$Rt2), (ins SPR:$src1, SPR:$src2),
+ IIC_fpMOVDI, "vmov", "\t$Rt, $Rt2, $src1, $src2",
[/* For disassembly only; pattern left blank */]> {
+ bits<5> src1;
+ bits<4> Rt;
+ bits<4> Rt2;
+
+ // Encode instruction operands.
+ let Inst{3-0} = src1{3-0};
+ let Inst{5} = src1{4};
+ let Inst{15-12} = Rt;
+ let Inst{19-16} = Rt2;
+
let Inst{7-6} = 0b00;
// Some single precision VFP instructions may be executed on both NEON and VFP
// pipelines.
let D = VFPNeonDomain;
+ let DecoderMethod = "DecodeVMOVRRS";
}
} // neverHasSideEffects
@@ -552,11 +579,24 @@ def VMOVSRR : AVConv5I<0b11000100, 0b1010,
(outs SPR:$dst1, SPR:$dst2), (ins GPR:$src1, GPR:$src2),
IIC_fpMOVID, "vmov", "\t$dst1, $dst2, $src1, $src2",
[/* For disassembly only; pattern left blank */]> {
+ // Instruction operands.
+ bits<5> dst1;
+ bits<4> src1;
+ bits<4> src2;
+
+ // Encode instruction operands.
+ let Inst{3-0} = dst1{3-0};
+ let Inst{5} = dst1{4};
+ let Inst{15-12} = src1;
+ let Inst{19-16} = src2;
+
let Inst{7-6} = 0b00;
// Some single precision VFP instructions may be executed on both NEON and VFP
// pipelines.
let D = VFPNeonDomain;
+
+ let DecoderMethod = "DecodeVMOVSRR";
}
// FMRDH: SPR -> GPR
@@ -1084,45 +1124,42 @@ def FCONSTD : VFPAI<(outs DPR:$Dd), (ins vfp_f64imm:$imm),
VFPMiscFrm, IIC_fpUNA64,
"vmov", ".f64\t$Dd, $imm",
[(set DPR:$Dd, vfp_f64imm:$imm)]>, Requires<[HasVFP3]> {
- // Instruction operands.
- bits<5> Dd;
- bits<32> imm;
-
- // Encode instruction operands.
- let Inst{15-12} = Dd{3-0};
- let Inst{22} = Dd{4};
- let Inst{19} = imm{31};
- let Inst{18-16} = imm{22-20};
- let Inst{3-0} = imm{19-16};
+ bits<5> Dd;
+ bits<8> imm;
- // Encode remaining instruction bits.
let Inst{27-23} = 0b11101;
+ let Inst{22} = Dd{4};
let Inst{21-20} = 0b11;
+ let Inst{19-16} = imm{7-4};
+ let Inst{15-12} = Dd{3-0};
let Inst{11-9} = 0b101;
let Inst{8} = 1; // Double precision.
let Inst{7-4} = 0b0000;
+ let Inst{3-0} = imm{3-0};
}
def FCONSTS : VFPAI<(outs SPR:$Sd), (ins vfp_f32imm:$imm),
VFPMiscFrm, IIC_fpUNA32,
"vmov", ".f32\t$Sd, $imm",
[(set SPR:$Sd, vfp_f32imm:$imm)]>, Requires<[HasVFP3]> {
- // Instruction operands.
- bits<5> Sd;
- bits<32> imm;
-
- // Encode instruction operands.
- let Inst{15-12} = Sd{4-1};
- let Inst{22} = Sd{0};
- let Inst{19} = imm{31}; // The immediate is handled as a double.
- let Inst{18-16} = imm{22-20};
- let Inst{3-0} = imm{19-16};
+ bits<5> Sd;
+ bits<8> imm;
- // Encode remaining instruction bits.
let Inst{27-23} = 0b11101;
+ let Inst{22} = Sd{0};
let Inst{21-20} = 0b11;
+ let Inst{19-16} = imm{7-4};
+ let Inst{15-12} = Sd{4-1};
let Inst{11-9} = 0b101;
let Inst{8} = 0; // Single precision.
let Inst{7-4} = 0b0000;
+ let Inst{3-0} = imm{3-0};
}
}
+
+//===----------------------------------------------------------------------===//
+// Assembler aliases.
+//
+
+def : VFP2InstAlias<"fmstat${p}", (FMSTAT pred:$p)>;
+
diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
index c6efea1..faa8ba7 100644
--- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
+++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
@@ -14,10 +14,10 @@
#define DEBUG_TYPE "arm-ldst-opt"
#include "ARM.h"
-#include "ARMAddressingModes.h"
#include "ARMBaseInstrInfo.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMRegisterInfo.h"
+#include "MCTargetDesc/ARMAddressingModes.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
@@ -26,6 +26,7 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
@@ -763,9 +764,9 @@ static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc,
ARM_AM::AddrOpc Mode) {
switch (Opc) {
case ARM::LDRi12:
- return ARM::LDR_PRE;
+ return ARM::LDR_PRE_IMM;
case ARM::STRi12:
- return ARM::STR_PRE;
+ return ARM::STR_PRE_IMM;
case ARM::VLDRS:
return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
case ARM::VLDRD:
@@ -789,9 +790,9 @@ static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc,
ARM_AM::AddrOpc Mode) {
switch (Opc) {
case ARM::LDRi12:
- return ARM::LDR_POST;
+ return ARM::LDR_POST_IMM;
case ARM::STRi12:
- return ARM::STR_POST;
+ return ARM::STR_POST_IMM;
case ARM::VLDRS:
return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;
case ARM::VLDRD:
@@ -892,12 +893,6 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
if (!DoMerge)
return false;
- unsigned Offset = 0;
- if (isAM2)
- Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift);
- else if (!isAM5)
- Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes;
-
if (isAM5) {
// VLDM[SD}_UPD, VSTM[SD]_UPD
// (There are no base-updating versions of VLDR/VSTR instructions, but the
@@ -911,28 +906,44 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
.addReg(MO.getReg(), (isLd ? getDefRegState(true) :
getKillRegState(MO.isKill())));
} else if (isLd) {
- if (isAM2)
- // LDR_PRE, LDR_POST,
- BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg())
- .addReg(Base, RegState::Define)
- .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
- else
+ if (isAM2) {
+ // LDR_PRE, LDR_POST
+ if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) {
+ int Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes;
+ BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg())
+ .addReg(Base, RegState::Define)
+ .addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg);
+ } else {
+ int Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift);
+ BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg())
+ .addReg(Base, RegState::Define)
+ .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
+ }
+ } else {
+ int Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes;
// t2LDR_PRE, t2LDR_POST
BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg())
.addReg(Base, RegState::Define)
.addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg);
+ }
} else {
MachineOperand &MO = MI->getOperand(0);
- if (isAM2)
+ // FIXME: post-indexed stores use am2offset_imm, which still encodes
+ // the vestigal zero-reg offset register. When that's fixed, this clause
+ // can be removed entirely.
+ if (isAM2 && NewOpc == ARM::STR_POST_IMM) {
+ int Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift);
// STR_PRE, STR_POST
BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base)
.addReg(MO.getReg(), getKillRegState(MO.isKill()))
.addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
- else
+ } else {
+ int Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes;
// t2STR_PRE, t2STR_POST
BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base)
.addReg(MO.getReg(), getKillRegState(MO.isKill()))
.addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg);
+ }
}
MBB.erase(MBBI);
diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp
deleted file mode 100644
index 39be3f0..0000000
--- a/lib/Target/ARM/ARMMCCodeEmitter.cpp
+++ /dev/null
@@ -1,1314 +0,0 @@
-//===-- ARM/ARMMCCodeEmitter.cpp - Convert ARM code to machine code -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the ARMMCCodeEmitter class.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "mccodeemitter"
-#include "ARM.h"
-#include "ARMAddressingModes.h"
-#include "ARMFixupKinds.h"
-#include "ARMInstrInfo.h"
-#include "ARMMCExpr.h"
-#include "ARMSubtarget.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
-STATISTIC(MCNumCPRelocations, "Number of constant pool relocations created.");
-
-namespace {
-class ARMMCCodeEmitter : public MCCodeEmitter {
- ARMMCCodeEmitter(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
- void operator=(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
- const MCInstrInfo &MCII;
- const MCSubtargetInfo &STI;
-
-public:
- ARMMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
- MCContext &ctx)
- : MCII(mcii), STI(sti) {
- }
-
- ~ARMMCCodeEmitter() {}
-
- bool isThumb() const {
- // FIXME: Can tablegen auto-generate this?
- return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
- }
- bool isThumb2() const {
- return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) != 0;
- }
- bool isTargetDarwin() const {
- Triple TT(STI.getTargetTriple());
- Triple::OSType OS = TT.getOS();
- return OS == Triple::Darwin || OS == Triple::MacOSX || OS == Triple::IOS;
- }
-
- unsigned getMachineSoImmOpValue(unsigned SoImm) const;
-
- // getBinaryCodeForInstr - TableGen'erated function for getting the
- // binary encoding for an instruction.
- unsigned getBinaryCodeForInstr(const MCInst &MI,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getMachineOpValue - Return binary encoding of operand. If the machine
- /// operand requires relocation, record the relocation and return zero.
- unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getHiLo16ImmOpValue - Return the encoding for the hi / low 16-bit of
- /// the specified operand. This is used for operands with :lower16: and
- /// :upper16: prefixes.
- uint32_t getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx,
- unsigned &Reg, unsigned &Imm,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getThumbBLTargetOpValue - Return encoding info for Thumb immediate
- /// BL branch target.
- uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
- /// BLX branch target.
- uint32_t getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
- uint32_t getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target.
- uint32_t getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getThumbCBTargetOpValue - Return encoding info for Thumb branch target.
- uint32_t getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getBranchTargetOpValue - Return encoding info for 24-bit immediate
- /// branch target.
- uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
- /// immediate Thumb2 direct branch target.
- uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getARMBranchTargetOpValue - Return encoding info for 24-bit immediate
- /// branch target.
- uint32_t getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getAdrLabelOpValue - Return encoding info for 12-bit immediate
- /// ADR label target.
- uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
- uint32_t getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
- uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
-
- /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
- /// operand.
- uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getThumbAddrModeRegRegOpValue - Return encoding for 'reg + reg' operand.
- uint32_t getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups)const;
-
- /// getT2AddrModeImm8s4OpValue - Return encoding info for 'reg +/- imm8<<2'
- /// operand.
- uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
-
- /// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm'
- /// operand as needed by load/store instructions.
- uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getLdStmModeOpValue - Return encoding for load/store multiple mode.
- uint32_t getLdStmModeOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- ARM_AM::AMSubMode Mode = (ARM_AM::AMSubMode)MI.getOperand(OpIdx).getImm();
- switch (Mode) {
- default: assert(0 && "Unknown addressing sub-mode!");
- case ARM_AM::da: return 0;
- case ARM_AM::ia: return 1;
- case ARM_AM::db: return 2;
- case ARM_AM::ib: return 3;
- }
- }
- /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value.
- ///
- unsigned getShiftOp(ARM_AM::ShiftOpc ShOpc) const {
- switch (ShOpc) {
- default: llvm_unreachable("Unknown shift opc!");
- case ARM_AM::no_shift:
- case ARM_AM::lsl: return 0;
- case ARM_AM::lsr: return 1;
- case ARM_AM::asr: return 2;
- case ARM_AM::ror:
- case ARM_AM::rrx: return 3;
- }
- return 0;
- }
-
- /// getAddrMode2OpValue - Return encoding for addrmode2 operands.
- uint32_t getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getAddrMode2OffsetOpValue - Return encoding for am2offset operands.
- uint32_t getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getAddrMode3OffsetOpValue - Return encoding for am3offset operands.
- uint32_t getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getAddrMode3OpValue - Return encoding for addrmode3 operands.
- uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getAddrModeThumbSPOpValue - Return encoding info for 'reg +/- imm12'
- /// operand.
- uint32_t getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getAddrModeISOpValue - Encode the t_addrmode_is# operands.
- uint32_t getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands.
- uint32_t getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand.
- uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getCCOutOpValue - Return encoding of the 's' bit.
- unsigned getCCOutOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // The operand is either reg0 or CPSR. The 's' bit is encoded as '0' or
- // '1' respectively.
- return MI.getOperand(Op).getReg() == ARM::CPSR;
- }
-
- /// getSOImmOpValue - Return an encoded 12-bit shifted-immediate value.
- unsigned getSOImmOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- unsigned SoImm = MI.getOperand(Op).getImm();
- int SoImmVal = ARM_AM::getSOImmVal(SoImm);
- assert(SoImmVal != -1 && "Not a valid so_imm value!");
-
- // Encode rotate_imm.
- unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1)
- << ARMII::SoRotImmShift;
-
- // Encode immed_8.
- Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
- return Binary;
- }
-
- /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value.
- unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- unsigned SoImm = MI.getOperand(Op).getImm();
- unsigned Encoded = ARM_AM::getT2SOImmVal(SoImm);
- assert(Encoded != ~0U && "Not a Thumb2 so_imm value?");
- return Encoded;
- }
-
- unsigned getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getSORegOpValue - Return an encoded so_reg shifted register value.
- unsigned getSORegOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- unsigned getRotImmOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- switch (MI.getOperand(Op).getImm()) {
- default: assert (0 && "Not a valid rot_imm value!");
- case 0: return 0;
- case 8: return 1;
- case 16: return 2;
- case 24: return 3;
- }
- }
-
- unsigned getImmMinusOneOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return MI.getOperand(Op).getImm() - 1;
- }
-
- unsigned getNEONVcvtImm32OpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return 64 - MI.getOperand(Op).getImm();
- }
-
- unsigned getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- unsigned getMsbOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- unsigned getSsatBitPosValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- unsigned getRegisterListOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- unsigned getShiftRight8Imm(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getShiftRight16Imm(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getShiftRight32Imm(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getShiftRight64Imm(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- unsigned NEONThumb2DataIPostEncoder(const MCInst &MI,
- unsigned EncodedValue) const;
- unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI,
- unsigned EncodedValue) const;
- unsigned NEONThumb2DupPostEncoder(const MCInst &MI,
- unsigned EncodedValue) const;
-
- unsigned VFPThumb2PostEncoder(const MCInst &MI,
- unsigned EncodedValue) const;
-
- void EmitByte(unsigned char C, raw_ostream &OS) const {
- OS << (char)C;
- }
-
- void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const {
- // Output the constant in little endian byte order.
- for (unsigned i = 0; i != Size; ++i) {
- EmitByte(Val & 255, OS);
- Val >>= 8;
- }
- }
-
- void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const;
-};
-
-} // end anonymous namespace
-
-MCCodeEmitter *llvm::createARMMCCodeEmitter(const MCInstrInfo &MCII,
- const MCSubtargetInfo &STI,
- MCContext &Ctx) {
- return new ARMMCCodeEmitter(MCII, STI, Ctx);
-}
-
-/// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing
-/// instructions, and rewrite them to their Thumb2 form if we are currently in
-/// Thumb2 mode.
-unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
- unsigned EncodedValue) const {
- if (isThumb2()) {
- // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved
- // to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are
- // set to 1111.
- unsigned Bit24 = EncodedValue & 0x01000000;
- unsigned Bit28 = Bit24 << 4;
- EncodedValue &= 0xEFFFFFFF;
- EncodedValue |= Bit28;
- EncodedValue |= 0x0F000000;
- }
-
- return EncodedValue;
-}
-
-/// NEONThumb2LoadStorePostEncoder - Post-process encoded NEON load/store
-/// instructions, and rewrite them to their Thumb2 form if we are currently in
-/// Thumb2 mode.
-unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
- unsigned EncodedValue) const {
- if (isThumb2()) {
- EncodedValue &= 0xF0FFFFFF;
- EncodedValue |= 0x09000000;
- }
-
- return EncodedValue;
-}
-
-/// NEONThumb2DupPostEncoder - Post-process encoded NEON vdup
-/// instructions, and rewrite them to their Thumb2 form if we are currently in
-/// Thumb2 mode.
-unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
- unsigned EncodedValue) const {
- if (isThumb2()) {
- EncodedValue &= 0x00FFFFFF;
- EncodedValue |= 0xEE000000;
- }
-
- return EncodedValue;
-}
-
-/// VFPThumb2PostEncoder - Post-process encoded VFP instructions and rewrite
-/// them to their Thumb2 form if we are currently in Thumb2 mode.
-unsigned ARMMCCodeEmitter::
-VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const {
- if (isThumb2()) {
- EncodedValue &= 0x0FFFFFFF;
- EncodedValue |= 0xE0000000;
- }
- return EncodedValue;
-}
-
-/// getMachineOpValue - Return binary encoding of operand. If the machine
-/// operand requires relocation, record the relocation and return zero.
-unsigned ARMMCCodeEmitter::
-getMachineOpValue(const MCInst &MI, const MCOperand &MO,
- SmallVectorImpl<MCFixup> &Fixups) const {
- if (MO.isReg()) {
- unsigned Reg = MO.getReg();
- unsigned RegNo = getARMRegisterNumbering(Reg);
-
- // Q registers are encoded as 2x their register number.
- switch (Reg) {
- default:
- return RegNo;
- case ARM::Q0: case ARM::Q1: case ARM::Q2: case ARM::Q3:
- case ARM::Q4: case ARM::Q5: case ARM::Q6: case ARM::Q7:
- case ARM::Q8: case ARM::Q9: case ARM::Q10: case ARM::Q11:
- case ARM::Q12: case ARM::Q13: case ARM::Q14: case ARM::Q15:
- return 2 * RegNo;
- }
- } else if (MO.isImm()) {
- return static_cast<unsigned>(MO.getImm());
- } else if (MO.isFPImm()) {
- return static_cast<unsigned>(APFloat(MO.getFPImm())
- .bitcastToAPInt().getHiBits(32).getLimitedValue());
- }
-
- llvm_unreachable("Unable to encode MCOperand!");
- return 0;
-}
-
-/// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand.
-bool ARMMCCodeEmitter::
-EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg,
- unsigned &Imm, SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO = MI.getOperand(OpIdx);
- const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
-
- Reg = getARMRegisterNumbering(MO.getReg());
-
- int32_t SImm = MO1.getImm();
- bool isAdd = true;
-
- // Special value for #-0
- if (SImm == INT32_MIN)
- SImm = 0;
-
- // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
- if (SImm < 0) {
- SImm = -SImm;
- isAdd = false;
- }
-
- Imm = SImm;
- return isAdd;
-}
-
-/// getBranchTargetOpValue - Helper function to get the branch target operand,
-/// which is either an immediate or requires a fixup.
-static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
- unsigned FixupKind,
- SmallVectorImpl<MCFixup> &Fixups) {
- const MCOperand &MO = MI.getOperand(OpIdx);
-
- // If the destination is an immediate, we have nothing to do.
- if (MO.isImm()) return MO.getImm();
- assert(MO.isExpr() && "Unexpected branch target type!");
- const MCExpr *Expr = MO.getExpr();
- MCFixupKind Kind = MCFixupKind(FixupKind);
- Fixups.push_back(MCFixup::Create(0, Expr, Kind));
-
- // All of the information is in the fixup.
- return 0;
-}
-
-/// getThumbBLTargetOpValue - Return encoding info for immediate branch target.
-uint32_t ARMMCCodeEmitter::
-getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bl, Fixups);
-}
-
-/// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
-/// BLX branch target.
-uint32_t ARMMCCodeEmitter::
-getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx, Fixups);
-}
-
-/// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
-uint32_t ARMMCCodeEmitter::
-getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_br, Fixups);
-}
-
-/// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target.
-uint32_t ARMMCCodeEmitter::
-getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bcc, Fixups);
-}
-
-/// getThumbCBTargetOpValue - Return encoding info for Thumb branch target.
-uint32_t ARMMCCodeEmitter::
-getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cb, Fixups);
-}
-
-/// Return true if this branch has a non-always predication
-static bool HasConditionalBranch(const MCInst &MI) {
- int NumOp = MI.getNumOperands();
- if (NumOp >= 2) {
- for (int i = 0; i < NumOp-1; ++i) {
- const MCOperand &MCOp1 = MI.getOperand(i);
- const MCOperand &MCOp2 = MI.getOperand(i + 1);
- if (MCOp1.isImm() && MCOp2.isReg() &&
- (MCOp2.getReg() == 0 || MCOp2.getReg() == ARM::CPSR)) {
- if (ARMCC::CondCodes(MCOp1.getImm()) != ARMCC::AL)
- return true;
- }
- }
- }
- return false;
-}
-
-/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch
-/// target.
-uint32_t ARMMCCodeEmitter::
-getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // FIXME: This really, really shouldn't use TargetMachine. We don't want
- // coupling between MC and TM anywhere we can help it.
- if (isThumb2())
- return
- ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups);
- return getARMBranchTargetOpValue(MI, OpIdx, Fixups);
-}
-
-/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch
-/// target.
-uint32_t ARMMCCodeEmitter::
-getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- if (HasConditionalBranch(MI))
- return ::getBranchTargetOpValue(MI, OpIdx,
- ARM::fixup_arm_condbranch, Fixups);
- return ::getBranchTargetOpValue(MI, OpIdx,
- ARM::fixup_arm_uncondbranch, Fixups);
-}
-
-
-
-
-/// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
-/// immediate branch target.
-uint32_t ARMMCCodeEmitter::
-getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- unsigned Val =
- ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups);
- bool I = (Val & 0x800000);
- bool J1 = (Val & 0x400000);
- bool J2 = (Val & 0x200000);
- if (I ^ J1)
- Val &= ~0x400000;
- else
- Val |= 0x400000;
-
- if (I ^ J2)
- Val &= ~0x200000;
- else
- Val |= 0x200000;
-
- return Val;
-}
-
-/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
-/// target.
-uint32_t ARMMCCodeEmitter::
-getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- assert(MI.getOperand(OpIdx).isExpr() && "Unexpected adr target type!");
- return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_adr_pcrel_12,
- Fixups);
-}
-
-/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
-/// target.
-uint32_t ARMMCCodeEmitter::
-getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- assert(MI.getOperand(OpIdx).isExpr() && "Unexpected adr target type!");
- return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_adr_pcrel_12,
- Fixups);
-}
-
-/// getAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label
-/// target.
-uint32_t ARMMCCodeEmitter::
-getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- assert(MI.getOperand(OpIdx).isExpr() && "Unexpected adr target type!");
- return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_thumb_adr_pcrel_10,
- Fixups);
-}
-
-/// getThumbAddrModeRegRegOpValue - Return encoding info for 'reg + reg'
-/// operand.
-uint32_t ARMMCCodeEmitter::
-getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &) const {
- // [Rn, Rm]
- // {5-3} = Rm
- // {2-0} = Rn
- const MCOperand &MO1 = MI.getOperand(OpIdx);
- const MCOperand &MO2 = MI.getOperand(OpIdx + 1);
- unsigned Rn = getARMRegisterNumbering(MO1.getReg());
- unsigned Rm = getARMRegisterNumbering(MO2.getReg());
- return (Rm << 3) | Rn;
-}
-
-/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand.
-uint32_t ARMMCCodeEmitter::
-getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // {17-13} = reg
- // {12} = (U)nsigned (add == '1', sub == '0')
- // {11-0} = imm12
- unsigned Reg, Imm12;
- bool isAdd = true;
- // If The first operand isn't a register, we have a label reference.
- const MCOperand &MO = MI.getOperand(OpIdx);
- if (!MO.isReg()) {
- Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
- Imm12 = 0;
- isAdd = false ; // 'U' bit is set as part of the fixup.
-
- assert(MO.isExpr() && "Unexpected machine operand type!");
- const MCExpr *Expr = MO.getExpr();
-
- MCFixupKind Kind;
- if (isThumb2())
- Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12);
- else
- Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12);
- Fixups.push_back(MCFixup::Create(0, Expr, Kind));
-
- ++MCNumCPRelocations;
- } else
- isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm12, Fixups);
-
- uint32_t Binary = Imm12 & 0xfff;
- // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
- if (isAdd)
- Binary |= (1 << 12);
- Binary |= (Reg << 13);
- return Binary;
-}
-
-/// getT2AddrModeImm8s4OpValue - Return encoding info for
-/// 'reg +/- imm8<<2' operand.
-uint32_t ARMMCCodeEmitter::
-getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // {12-9} = reg
- // {8} = (U)nsigned (add == '1', sub == '0')
- // {7-0} = imm8
- unsigned Reg, Imm8;
- bool isAdd = true;
- // If The first operand isn't a register, we have a label reference.
- const MCOperand &MO = MI.getOperand(OpIdx);
- if (!MO.isReg()) {
- Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
- Imm8 = 0;
- isAdd = false ; // 'U' bit is set as part of the fixup.
-
- assert(MO.isExpr() && "Unexpected machine operand type!");
- const MCExpr *Expr = MO.getExpr();
- MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
- Fixups.push_back(MCFixup::Create(0, Expr, Kind));
-
- ++MCNumCPRelocations;
- } else
- isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups);
-
- uint32_t Binary = (Imm8 >> 2) & 0xff;
- // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
- if (isAdd)
- Binary |= (1 << 8);
- Binary |= (Reg << 9);
- return Binary;
-}
-
-// FIXME: This routine assumes that a binary
-// expression will always result in a PCRel expression
-// In reality, its only true if one or more subexpressions
-// is itself a PCRel (i.e. "." in asm or some other pcrel construct)
-// but this is good enough for now.
-static bool EvaluateAsPCRel(const MCExpr *Expr) {
- switch (Expr->getKind()) {
- default: assert(0 && "Unexpected expression type");
- case MCExpr::SymbolRef: return false;
- case MCExpr::Binary: return true;
- }
-}
-
-uint32_t
-ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // {20-16} = imm{15-12}
- // {11-0} = imm{11-0}
- const MCOperand &MO = MI.getOperand(OpIdx);
- if (MO.isImm())
- // Hi / lo 16 bits already extracted during earlier passes.
- return static_cast<unsigned>(MO.getImm());
-
- // Handle :upper16: and :lower16: assembly prefixes.
- const MCExpr *E = MO.getExpr();
- if (E->getKind() == MCExpr::Target) {
- const ARMMCExpr *ARM16Expr = cast<ARMMCExpr>(E);
- E = ARM16Expr->getSubExpr();
-
- MCFixupKind Kind;
- switch (ARM16Expr->getKind()) {
- default: assert(0 && "Unsupported ARMFixup");
- case ARMMCExpr::VK_ARM_HI16:
- if (!isTargetDarwin() && EvaluateAsPCRel(E))
- Kind = MCFixupKind(isThumb2()
- ? ARM::fixup_t2_movt_hi16_pcrel
- : ARM::fixup_arm_movt_hi16_pcrel);
- else
- Kind = MCFixupKind(isThumb2()
- ? ARM::fixup_t2_movt_hi16
- : ARM::fixup_arm_movt_hi16);
- break;
- case ARMMCExpr::VK_ARM_LO16:
- if (!isTargetDarwin() && EvaluateAsPCRel(E))
- Kind = MCFixupKind(isThumb2()
- ? ARM::fixup_t2_movw_lo16_pcrel
- : ARM::fixup_arm_movw_lo16_pcrel);
- else
- Kind = MCFixupKind(isThumb2()
- ? ARM::fixup_t2_movw_lo16
- : ARM::fixup_arm_movw_lo16);
- break;
- }
- Fixups.push_back(MCFixup::Create(0, E, Kind));
- return 0;
- };
-
- llvm_unreachable("Unsupported MCExpr type in MCOperand!");
- return 0;
-}
-
-uint32_t ARMMCCodeEmitter::
-getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO = MI.getOperand(OpIdx);
- const MCOperand &MO1 = MI.getOperand(OpIdx+1);
- const MCOperand &MO2 = MI.getOperand(OpIdx+2);
- unsigned Rn = getARMRegisterNumbering(MO.getReg());
- unsigned Rm = getARMRegisterNumbering(MO1.getReg());
- unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm());
- bool isAdd = ARM_AM::getAM2Op(MO2.getImm()) == ARM_AM::add;
- ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm());
- unsigned SBits = getShiftOp(ShOp);
-
- // {16-13} = Rn
- // {12} = isAdd
- // {11-0} = shifter
- // {3-0} = Rm
- // {4} = 0
- // {6-5} = type
- // {11-7} = imm
- uint32_t Binary = Rm;
- Binary |= Rn << 13;
- Binary |= SBits << 5;
- Binary |= ShImm << 7;
- if (isAdd)
- Binary |= 1 << 12;
- return Binary;
-}
-
-uint32_t ARMMCCodeEmitter::
-getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // {17-14} Rn
- // {13} 1 == imm12, 0 == Rm
- // {12} isAdd
- // {11-0} imm12/Rm
- const MCOperand &MO = MI.getOperand(OpIdx);
- unsigned Rn = getARMRegisterNumbering(MO.getReg());
- uint32_t Binary = getAddrMode2OffsetOpValue(MI, OpIdx + 1, Fixups);
- Binary |= Rn << 14;
- return Binary;
-}
-
-uint32_t ARMMCCodeEmitter::
-getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // {13} 1 == imm12, 0 == Rm
- // {12} isAdd
- // {11-0} imm12/Rm
- const MCOperand &MO = MI.getOperand(OpIdx);
- const MCOperand &MO1 = MI.getOperand(OpIdx+1);
- unsigned Imm = MO1.getImm();
- bool isAdd = ARM_AM::getAM2Op(Imm) == ARM_AM::add;
- bool isReg = MO.getReg() != 0;
- uint32_t Binary = ARM_AM::getAM2Offset(Imm);
- // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm12
- if (isReg) {
- ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(Imm);
- Binary <<= 7; // Shift amount is bits [11:7]
- Binary |= getShiftOp(ShOp) << 5; // Shift type is bits [6:5]
- Binary |= getARMRegisterNumbering(MO.getReg()); // Rm is bits [3:0]
- }
- return Binary | (isAdd << 12) | (isReg << 13);
-}
-
-uint32_t ARMMCCodeEmitter::
-getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // {9} 1 == imm8, 0 == Rm
- // {8} isAdd
- // {7-4} imm7_4/zero
- // {3-0} imm3_0/Rm
- const MCOperand &MO = MI.getOperand(OpIdx);
- const MCOperand &MO1 = MI.getOperand(OpIdx+1);
- unsigned Imm = MO1.getImm();
- bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
- bool isImm = MO.getReg() == 0;
- uint32_t Imm8 = ARM_AM::getAM3Offset(Imm);
- // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8
- if (!isImm)
- Imm8 = getARMRegisterNumbering(MO.getReg());
- return Imm8 | (isAdd << 8) | (isImm << 9);
-}
-
-uint32_t ARMMCCodeEmitter::
-getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // {13} 1 == imm8, 0 == Rm
- // {12-9} Rn
- // {8} isAdd
- // {7-4} imm7_4/zero
- // {3-0} imm3_0/Rm
- const MCOperand &MO = MI.getOperand(OpIdx);
- const MCOperand &MO1 = MI.getOperand(OpIdx+1);
- const MCOperand &MO2 = MI.getOperand(OpIdx+2);
- unsigned Rn = getARMRegisterNumbering(MO.getReg());
- unsigned Imm = MO2.getImm();
- bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
- bool isImm = MO1.getReg() == 0;
- uint32_t Imm8 = ARM_AM::getAM3Offset(Imm);
- // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8
- if (!isImm)
- Imm8 = getARMRegisterNumbering(MO1.getReg());
- return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13);
-}
-
-/// getAddrModeThumbSPOpValue - Encode the t_addrmode_sp operands.
-uint32_t ARMMCCodeEmitter::
-getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // [SP, #imm]
- // {7-0} = imm8
- const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
- assert(MI.getOperand(OpIdx).getReg() == ARM::SP &&
- "Unexpected base register!");
-
- // The immediate is already shifted for the implicit zeroes, so no change
- // here.
- return MO1.getImm() & 0xff;
-}
-
-/// getAddrModeISOpValue - Encode the t_addrmode_is# operands.
-uint32_t ARMMCCodeEmitter::
-getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // [Rn, #imm]
- // {7-3} = imm5
- // {2-0} = Rn
- const MCOperand &MO = MI.getOperand(OpIdx);
- const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
- unsigned Rn = getARMRegisterNumbering(MO.getReg());
- unsigned Imm5 = MO1.getImm();
- return ((Imm5 & 0x1f) << 3) | Rn;
-}
-
-/// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands.
-uint32_t ARMMCCodeEmitter::
-getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cp, Fixups);
-}
-
-/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm10' operand.
-uint32_t ARMMCCodeEmitter::
-getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // {12-9} = reg
- // {8} = (U)nsigned (add == '1', sub == '0')
- // {7-0} = imm8
- unsigned Reg, Imm8;
- bool isAdd;
- // If The first operand isn't a register, we have a label reference.
- const MCOperand &MO = MI.getOperand(OpIdx);
- if (!MO.isReg()) {
- Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
- Imm8 = 0;
- isAdd = false; // 'U' bit is handled as part of the fixup.
-
- assert(MO.isExpr() && "Unexpected machine operand type!");
- const MCExpr *Expr = MO.getExpr();
- MCFixupKind Kind;
- if (isThumb2())
- Kind = MCFixupKind(ARM::fixup_t2_pcrel_10);
- else
- Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
- Fixups.push_back(MCFixup::Create(0, Expr, Kind));
-
- ++MCNumCPRelocations;
- } else {
- EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups);
- isAdd = ARM_AM::getAM5Op(Imm8) == ARM_AM::add;
- }
-
- uint32_t Binary = ARM_AM::getAM5Offset(Imm8);
- // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
- if (isAdd)
- Binary |= (1 << 8);
- Binary |= (Reg << 9);
- return Binary;
-}
-
-unsigned ARMMCCodeEmitter::
-getSORegOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg to be
- // shifted. The second is either Rs, the amount to shift by, or reg0 in which
- // case the imm contains the amount to shift by.
- //
- // {3-0} = Rm.
- // {4} = 1 if reg shift, 0 if imm shift
- // {6-5} = type
- // If reg shift:
- // {11-8} = Rs
- // {7} = 0
- // else (imm shift)
- // {11-7} = imm
-
- const MCOperand &MO = MI.getOperand(OpIdx);
- const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
- const MCOperand &MO2 = MI.getOperand(OpIdx + 2);
- ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm());
-
- // Encode Rm.
- unsigned Binary = getARMRegisterNumbering(MO.getReg());
-
- // Encode the shift opcode.
- unsigned SBits = 0;
- unsigned Rs = MO1.getReg();
- if (Rs) {
- // Set shift operand (bit[7:4]).
- // LSL - 0001
- // LSR - 0011
- // ASR - 0101
- // ROR - 0111
- // RRX - 0110 and bit[11:8] clear.
- switch (SOpc) {
- default: llvm_unreachable("Unknown shift opc!");
- case ARM_AM::lsl: SBits = 0x1; break;
- case ARM_AM::lsr: SBits = 0x3; break;
- case ARM_AM::asr: SBits = 0x5; break;
- case ARM_AM::ror: SBits = 0x7; break;
- case ARM_AM::rrx: SBits = 0x6; break;
- }
- } else {
- // Set shift operand (bit[6:4]).
- // LSL - 000
- // LSR - 010
- // ASR - 100
- // ROR - 110
- switch (SOpc) {
- default: llvm_unreachable("Unknown shift opc!");
- case ARM_AM::lsl: SBits = 0x0; break;
- case ARM_AM::lsr: SBits = 0x2; break;
- case ARM_AM::asr: SBits = 0x4; break;
- case ARM_AM::ror: SBits = 0x6; break;
- }
- }
-
- Binary |= SBits << 4;
- if (SOpc == ARM_AM::rrx)
- return Binary;
-
- // Encode the shift operation Rs or shift_imm (except rrx).
- if (Rs) {
- // Encode Rs bit[11:8].
- assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0);
- return Binary | (getARMRegisterNumbering(Rs) << ARMII::RegRsShift);
- }
-
- // Encode shift_imm bit[11:7].
- return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7;
-}
-
-unsigned ARMMCCodeEmitter::
-getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO1 = MI.getOperand(OpNum);
- const MCOperand &MO2 = MI.getOperand(OpNum+1);
- const MCOperand &MO3 = MI.getOperand(OpNum+2);
-
- // Encoded as [Rn, Rm, imm].
- // FIXME: Needs fixup support.
- unsigned Value = getARMRegisterNumbering(MO1.getReg());
- Value <<= 4;
- Value |= getARMRegisterNumbering(MO2.getReg());
- Value <<= 2;
- Value |= MO3.getImm();
-
- return Value;
-}
-
-unsigned ARMMCCodeEmitter::
-getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO1 = MI.getOperand(OpNum);
- const MCOperand &MO2 = MI.getOperand(OpNum+1);
-
- // FIXME: Needs fixup support.
- unsigned Value = getARMRegisterNumbering(MO1.getReg());
-
- // Even though the immediate is 8 bits long, we need 9 bits in order
- // to represent the (inverse of the) sign bit.
- Value <<= 9;
- int32_t tmp = (int32_t)MO2.getImm();
- if (tmp < 0)
- tmp = abs(tmp);
- else
- Value |= 256; // Set the ADD bit
- Value |= tmp & 255;
- return Value;
-}
-
-unsigned ARMMCCodeEmitter::
-getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO1 = MI.getOperand(OpNum);
-
- // FIXME: Needs fixup support.
- unsigned Value = 0;
- int32_t tmp = (int32_t)MO1.getImm();
- if (tmp < 0)
- tmp = abs(tmp);
- else
- Value |= 256; // Set the ADD bit
- Value |= tmp & 255;
- return Value;
-}
-
-unsigned ARMMCCodeEmitter::
-getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO1 = MI.getOperand(OpNum);
-
- // FIXME: Needs fixup support.
- unsigned Value = 0;
- int32_t tmp = (int32_t)MO1.getImm();
- if (tmp < 0)
- tmp = abs(tmp);
- else
- Value |= 4096; // Set the ADD bit
- Value |= tmp & 4095;
- return Value;
-}
-
-unsigned ARMMCCodeEmitter::
-getT2SORegOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // Sub-operands are [reg, imm]. The first register is Rm, the reg to be
- // shifted. The second is the amount to shift by.
- //
- // {3-0} = Rm.
- // {4} = 0
- // {6-5} = type
- // {11-7} = imm
-
- const MCOperand &MO = MI.getOperand(OpIdx);
- const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
- ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm());
-
- // Encode Rm.
- unsigned Binary = getARMRegisterNumbering(MO.getReg());
-
- // Encode the shift opcode.
- unsigned SBits = 0;
- // Set shift operand (bit[6:4]).
- // LSL - 000
- // LSR - 010
- // ASR - 100
- // ROR - 110
- switch (SOpc) {
- default: llvm_unreachable("Unknown shift opc!");
- case ARM_AM::lsl: SBits = 0x0; break;
- case ARM_AM::lsr: SBits = 0x2; break;
- case ARM_AM::asr: SBits = 0x4; break;
- case ARM_AM::ror: SBits = 0x6; break;
- }
-
- Binary |= SBits << 4;
- if (SOpc == ARM_AM::rrx)
- return Binary;
-
- // Encode shift_imm bit[11:7].
- return Binary | ARM_AM::getSORegOffset(MO1.getImm()) << 7;
-}
-
-unsigned ARMMCCodeEmitter::
-getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // 10 bits. lower 5 bits are are the lsb of the mask, high five bits are the
- // msb of the mask.
- const MCOperand &MO = MI.getOperand(Op);
- uint32_t v = ~MO.getImm();
- uint32_t lsb = CountTrailingZeros_32(v);
- uint32_t msb = (32 - CountLeadingZeros_32 (v)) - 1;
- assert (v != 0 && lsb < 32 && msb < 32 && "Illegal bitfield mask!");
- return lsb | (msb << 5);
-}
-
-unsigned ARMMCCodeEmitter::
-getMsbOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // MSB - 5 bits.
- uint32_t lsb = MI.getOperand(Op-1).getImm();
- uint32_t width = MI.getOperand(Op).getImm();
- uint32_t msb = lsb+width-1;
- assert (width != 0 && msb < 32 && "Illegal bit width!");
- return msb;
-}
-
-unsigned ARMMCCodeEmitter::
-getSsatBitPosValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // For ssat instructions, the bit position should be encoded decremented by 1
- return MI.getOperand(Op).getImm()-1;
-}
-
-unsigned ARMMCCodeEmitter::
-getRegisterListOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // VLDM/VSTM:
- // {12-8} = Vd
- // {7-0} = Number of registers
- //
- // LDM/STM:
- // {15-0} = Bitfield of GPRs.
- unsigned Reg = MI.getOperand(Op).getReg();
- bool SPRRegs = ARM::SPRRegClass.contains(Reg);
- bool DPRRegs = ARM::DPRRegClass.contains(Reg);
-
- unsigned Binary = 0;
-
- if (SPRRegs || DPRRegs) {
- // VLDM/VSTM
- unsigned RegNo = getARMRegisterNumbering(Reg);
- unsigned NumRegs = (MI.getNumOperands() - Op) & 0xff;
- Binary |= (RegNo & 0x1f) << 8;
- if (SPRRegs)
- Binary |= NumRegs;
- else
- Binary |= NumRegs * 2;
- } else {
- for (unsigned I = Op, E = MI.getNumOperands(); I < E; ++I) {
- unsigned RegNo = getARMRegisterNumbering(MI.getOperand(I).getReg());
- Binary |= 1 << RegNo;
- }
- }
-
- return Binary;
-}
-
-/// getAddrMode6AddressOpValue - Encode an addrmode6 register number along
-/// with the alignment operand.
-unsigned ARMMCCodeEmitter::
-getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &Reg = MI.getOperand(Op);
- const MCOperand &Imm = MI.getOperand(Op + 1);
-
- unsigned RegNo = getARMRegisterNumbering(Reg.getReg());
- unsigned Align = 0;
-
- switch (Imm.getImm()) {
- default: break;
- case 2:
- case 4:
- case 8: Align = 0x01; break;
- case 16: Align = 0x02; break;
- case 32: Align = 0x03; break;
- }
-
- return RegNo | (Align << 4);
-}
-
-/// getAddrMode6OneLane32AddressOpValue - Encode an addrmode6 register number
-/// along with the alignment operand for use in VST1 and VLD1 with size 32.
-unsigned ARMMCCodeEmitter::
-getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &Reg = MI.getOperand(Op);
- const MCOperand &Imm = MI.getOperand(Op + 1);
-
- unsigned RegNo = getARMRegisterNumbering(Reg.getReg());
- unsigned Align = 0;
-
- switch (Imm.getImm()) {
- default: break;
- case 2:
- case 4:
- case 8:
- case 16: Align = 0x00; break;
- case 32: Align = 0x03; break;
- }
-
- return RegNo | (Align << 4);
-}
-
-
-/// getAddrMode6DupAddressOpValue - Encode an addrmode6 register number and
-/// alignment operand for use in VLD-dup instructions. This is the same as
-/// getAddrMode6AddressOpValue except for the alignment encoding, which is
-/// different for VLD4-dup.
-unsigned ARMMCCodeEmitter::
-getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &Reg = MI.getOperand(Op);
- const MCOperand &Imm = MI.getOperand(Op + 1);
-
- unsigned RegNo = getARMRegisterNumbering(Reg.getReg());
- unsigned Align = 0;
-
- switch (Imm.getImm()) {
- default: break;
- case 2:
- case 4:
- case 8: Align = 0x01; break;
- case 16: Align = 0x03; break;
- }
-
- return RegNo | (Align << 4);
-}
-
-unsigned ARMMCCodeEmitter::
-getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO = MI.getOperand(Op);
- if (MO.getReg() == 0) return 0x0D;
- return MO.getReg();
-}
-
-unsigned ARMMCCodeEmitter::
-getShiftRight8Imm(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return 8 - MI.getOperand(Op).getImm();
-}
-
-unsigned ARMMCCodeEmitter::
-getShiftRight16Imm(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return 16 - MI.getOperand(Op).getImm();
-}
-
-unsigned ARMMCCodeEmitter::
-getShiftRight32Imm(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return 32 - MI.getOperand(Op).getImm();
-}
-
-unsigned ARMMCCodeEmitter::
-getShiftRight64Imm(const MCInst &MI, unsigned Op,
- SmallVectorImpl<MCFixup> &Fixups) const {
- return 64 - MI.getOperand(Op).getImm();
-}
-
-void ARMMCCodeEmitter::
-EncodeInstruction(const MCInst &MI, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // Pseudo instructions don't get encoded.
- const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
- uint64_t TSFlags = Desc.TSFlags;
- if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo)
- return;
-
- int Size;
- if (Desc.getSize() == 2 || Desc.getSize() == 4)
- Size = Desc.getSize();
- else
- llvm_unreachable("Unexpected instruction size!");
-
- uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
- // Thumb 32-bit wide instructions need to emit the high order halfword
- // first.
- if (isThumb() && Size == 4) {
- EmitConstant(Binary >> 16, 2, OS);
- EmitConstant(Binary & 0xffff, 2, OS);
- } else
- EmitConstant(Binary, Size, OS);
- ++MCNumEmitted; // Keep track of the # of mi's emitted.
-}
-
-#include "ARMGenMCCodeEmitter.inc"
diff --git a/lib/Target/ARM/ARMMCInstLower.cpp b/lib/Target/ARM/ARMMCInstLower.cpp
index 7411b59..daa126d 100644
--- a/lib/Target/ARM/ARMMCInstLower.cpp
+++ b/lib/Target/ARM/ARMMCInstLower.cpp
@@ -14,7 +14,7 @@
#include "ARM.h"
#include "ARMAsmPrinter.h"
-#include "ARMMCExpr.h"
+#include "MCTargetDesc/ARMMCExpr.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/MC/MCExpr.h"
diff --git a/lib/Target/ARM/ARMMachObjectWriter.cpp b/lib/Target/ARM/ARMMachObjectWriter.cpp
deleted file mode 100644
index a36e47d..0000000
--- a/lib/Target/ARM/ARMMachObjectWriter.cpp
+++ /dev/null
@@ -1,389 +0,0 @@
-//===-- ARMMachObjectWriter.cpp - ARM Mach Object Writer ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ARM.h"
-#include "ARMFixupKinds.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCMachObjectWriter.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixup.h"
-#include "llvm/MC/MCFixupKindInfo.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Object/MachOFormat.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Target/TargetAsmBackend.h"
-using namespace llvm;
-using namespace llvm::object;
-
-namespace {
-class ARMMachObjectWriter : public MCMachObjectTargetWriter {
- void RecordARMScatteredRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- unsigned Log2Size,
- uint64_t &FixedValue);
- void RecordARMMovwMovtRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup, MCValue Target,
- uint64_t &FixedValue);
-
-public:
- ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType,
- uint32_t CPUSubtype)
- : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
- /*UseAggressiveSymbolFolding=*/true) {}
-
- void RecordRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCFragment *Fragment, const MCFixup &Fixup,
- MCValue Target, uint64_t &FixedValue);
-};
-}
-
-static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
- unsigned &Log2Size) {
- RelocType = unsigned(macho::RIT_Vanilla);
- Log2Size = ~0U;
-
- switch (Kind) {
- default:
- return false;
-
- case FK_Data_1:
- Log2Size = llvm::Log2_32(1);
- return true;
- case FK_Data_2:
- Log2Size = llvm::Log2_32(2);
- return true;
- case FK_Data_4:
- Log2Size = llvm::Log2_32(4);
- return true;
- case FK_Data_8:
- Log2Size = llvm::Log2_32(8);
- return true;
-
- // Handle 24-bit branch kinds.
- case ARM::fixup_arm_ldst_pcrel_12:
- case ARM::fixup_arm_pcrel_10:
- case ARM::fixup_arm_adr_pcrel_12:
- case ARM::fixup_arm_condbranch:
- case ARM::fixup_arm_uncondbranch:
- RelocType = unsigned(macho::RIT_ARM_Branch24Bit);
- // Report as 'long', even though that is not quite accurate.
- Log2Size = llvm::Log2_32(4);
- return true;
-
- // Handle Thumb branches.
- case ARM::fixup_arm_thumb_br:
- RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit);
- Log2Size = llvm::Log2_32(2);
- return true;
-
- case ARM::fixup_t2_uncondbranch:
- case ARM::fixup_arm_thumb_bl:
- case ARM::fixup_arm_thumb_blx:
- RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit);
- Log2Size = llvm::Log2_32(4);
- return true;
-
- case ARM::fixup_arm_movt_hi16:
- case ARM::fixup_arm_movt_hi16_pcrel:
- case ARM::fixup_t2_movt_hi16:
- case ARM::fixup_t2_movt_hi16_pcrel:
- RelocType = unsigned(macho::RIT_ARM_HalfDifference);
- // Report as 'long', even though that is not quite accurate.
- Log2Size = llvm::Log2_32(4);
- return true;
-
- case ARM::fixup_arm_movw_lo16:
- case ARM::fixup_arm_movw_lo16_pcrel:
- case ARM::fixup_t2_movw_lo16:
- case ARM::fixup_t2_movw_lo16_pcrel:
- RelocType = unsigned(macho::RIT_ARM_Half);
- // Report as 'long', even though that is not quite accurate.
- Log2Size = llvm::Log2_32(4);
- return true;
- }
-}
-
-void ARMMachObjectWriter::
-RecordARMMovwMovtRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- uint64_t &FixedValue) {
- uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
- unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
- unsigned Type = macho::RIT_ARM_Half;
-
- // See <reloc.h>.
- const MCSymbol *A = &Target.getSymA()->getSymbol();
- MCSymbolData *A_SD = &Asm.getSymbolData(*A);
-
- if (!A_SD->getFragment())
- report_fatal_error("symbol '" + A->getName() +
- "' can not be undefined in a subtraction expression");
-
- uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
- uint32_t Value2 = 0;
- uint64_t SecAddr =
- Writer->getSectionAddress(A_SD->getFragment()->getParent());
- FixedValue += SecAddr;
-
- if (const MCSymbolRefExpr *B = Target.getSymB()) {
- MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
-
- if (!B_SD->getFragment())
- report_fatal_error("symbol '" + B->getSymbol().getName() +
- "' can not be undefined in a subtraction expression");
-
- // Select the appropriate difference relocation type.
- Type = macho::RIT_ARM_HalfDifference;
- Value2 = Writer->getSymbolAddress(B_SD, Layout);
- FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
- }
-
- // Relocations are written out in reverse order, so the PAIR comes first.
- // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
- //
- // For these two r_type relocations they always have a pair following them and
- // the r_length bits are used differently. The encoding of the r_length is as
- // follows:
- // low bit of r_length:
- // 0 - :lower16: for movw instructions
- // 1 - :upper16: for movt instructions
- // high bit of r_length:
- // 0 - arm instructions
- // 1 - thumb instructions
- // the other half of the relocated expression is in the following pair
- // relocation entry in the the low 16 bits of r_address field.
- unsigned ThumbBit = 0;
- unsigned MovtBit = 0;
- switch ((unsigned)Fixup.getKind()) {
- default: break;
- case ARM::fixup_arm_movt_hi16:
- case ARM::fixup_arm_movt_hi16_pcrel:
- MovtBit = 1;
- break;
- case ARM::fixup_t2_movt_hi16:
- case ARM::fixup_t2_movt_hi16_pcrel:
- MovtBit = 1;
- // Fallthrough
- case ARM::fixup_t2_movw_lo16:
- case ARM::fixup_t2_movw_lo16_pcrel:
- ThumbBit = 1;
- break;
- }
-
-
- if (Type == macho::RIT_ARM_HalfDifference) {
- uint32_t OtherHalf = MovtBit
- ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16);
-
- macho::RelocationEntry MRE;
- MRE.Word0 = ((OtherHalf << 0) |
- (macho::RIT_Pair << 24) |
- (MovtBit << 28) |
- (ThumbBit << 29) |
- (IsPCRel << 30) |
- macho::RF_Scattered);
- MRE.Word1 = Value2;
- Writer->addRelocation(Fragment->getParent(), MRE);
- }
-
- macho::RelocationEntry MRE;
- MRE.Word0 = ((FixupOffset << 0) |
- (Type << 24) |
- (MovtBit << 28) |
- (ThumbBit << 29) |
- (IsPCRel << 30) |
- macho::RF_Scattered);
- MRE.Word1 = Value;
- Writer->addRelocation(Fragment->getParent(), MRE);
-}
-
-void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- unsigned Log2Size,
- uint64_t &FixedValue) {
- uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
- unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
- unsigned Type = macho::RIT_Vanilla;
-
- // See <reloc.h>.
- const MCSymbol *A = &Target.getSymA()->getSymbol();
- MCSymbolData *A_SD = &Asm.getSymbolData(*A);
-
- if (!A_SD->getFragment())
- report_fatal_error("symbol '" + A->getName() +
- "' can not be undefined in a subtraction expression");
-
- uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
- uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
- FixedValue += SecAddr;
- uint32_t Value2 = 0;
-
- if (const MCSymbolRefExpr *B = Target.getSymB()) {
- MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
-
- if (!B_SD->getFragment())
- report_fatal_error("symbol '" + B->getSymbol().getName() +
- "' can not be undefined in a subtraction expression");
-
- // Select the appropriate difference relocation type.
- Type = macho::RIT_Difference;
- Value2 = Writer->getSymbolAddress(B_SD, Layout);
- FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
- }
-
- // Relocations are written out in reverse order, so the PAIR comes first.
- if (Type == macho::RIT_Difference ||
- Type == macho::RIT_Generic_LocalDifference) {
- macho::RelocationEntry MRE;
- MRE.Word0 = ((0 << 0) |
- (macho::RIT_Pair << 24) |
- (Log2Size << 28) |
- (IsPCRel << 30) |
- macho::RF_Scattered);
- MRE.Word1 = Value2;
- Writer->addRelocation(Fragment->getParent(), MRE);
- }
-
- macho::RelocationEntry MRE;
- MRE.Word0 = ((FixupOffset << 0) |
- (Type << 24) |
- (Log2Size << 28) |
- (IsPCRel << 30) |
- macho::RF_Scattered);
- MRE.Word1 = Value;
- Writer->addRelocation(Fragment->getParent(), MRE);
-}
-
-void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- uint64_t &FixedValue) {
- unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
- unsigned Log2Size;
- unsigned RelocType = macho::RIT_Vanilla;
- if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) {
- report_fatal_error("unknown ARM fixup kind!");
- return;
- }
-
- // If this is a difference or a defined symbol plus an offset, then we need a
- // scattered relocation entry. Differences always require scattered
- // relocations.
- if (Target.getSymB()) {
- if (RelocType == macho::RIT_ARM_Half ||
- RelocType == macho::RIT_ARM_HalfDifference)
- return RecordARMMovwMovtRelocation(Writer, Asm, Layout, Fragment, Fixup,
- Target, FixedValue);
- return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
- Target, Log2Size, FixedValue);
- }
-
- // Get the symbol data, if any.
- MCSymbolData *SD = 0;
- if (Target.getSymA())
- SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
-
- // FIXME: For other platforms, we need to use scattered relocations for
- // internal relocations with offsets. If this is an internal relocation with
- // an offset, it also needs a scattered relocation entry.
- //
- // Is this right for ARM?
- uint32_t Offset = Target.getConstant();
- if (IsPCRel && RelocType == macho::RIT_Vanilla)
- Offset += 1 << Log2Size;
- if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD))
- return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
- Target, Log2Size, FixedValue);
-
- // See <reloc.h>.
- uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
- unsigned Index = 0;
- unsigned IsExtern = 0;
- unsigned Type = 0;
-
- if (Target.isAbsolute()) { // constant
- // FIXME!
- report_fatal_error("FIXME: relocations to absolute targets "
- "not yet implemented");
- } else {
- // Resolve constant variables.
- if (SD->getSymbol().isVariable()) {
- int64_t Res;
- if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
- Res, Layout, Writer->getSectionAddressMap())) {
- FixedValue = Res;
- return;
- }
- }
-
- // Check whether we need an external or internal relocation.
- if (Writer->doesSymbolRequireExternRelocation(SD)) {
- IsExtern = 1;
- Index = SD->getIndex();
-
- // For external relocations, make sure to offset the fixup value to
- // compensate for the addend of the symbol address, if it was
- // undefined. This occurs with weak definitions, for example.
- if (!SD->Symbol->isUndefined())
- FixedValue -= Layout.getSymbolOffset(SD);
- } else {
- // The index is the section ordinal (1-based).
- const MCSectionData &SymSD = Asm.getSectionData(
- SD->getSymbol().getSection());
- Index = SymSD.getOrdinal() + 1;
- FixedValue += Writer->getSectionAddress(&SymSD);
- }
- if (IsPCRel)
- FixedValue -= Writer->getSectionAddress(Fragment->getParent());
-
- // The type is determined by the fixup kind.
- Type = RelocType;
- }
-
- // struct relocation_info (8 bytes)
- macho::RelocationEntry MRE;
- MRE.Word0 = FixupOffset;
- MRE.Word1 = ((Index << 0) |
- (IsPCRel << 24) |
- (Log2Size << 25) |
- (IsExtern << 27) |
- (Type << 28));
- Writer->addRelocation(Fragment->getParent(), MRE);
-}
-
-MCObjectWriter *llvm::createARMMachObjectWriter(raw_ostream &OS,
- bool Is64Bit,
- uint32_t CPUType,
- uint32_t CPUSubtype) {
- return createMachObjectWriter(new ARMMachObjectWriter(Is64Bit,
- CPUType,
- CPUSubtype),
- OS, /*IsLittleEndian=*/true);
-}
diff --git a/lib/Target/ARM/ARMRegisterInfo.td b/lib/Target/ARM/ARMRegisterInfo.td
index 76eb496..036822d 100644
--- a/lib/Target/ARM/ARMRegisterInfo.td
+++ b/lib/Target/ARM/ARMRegisterInfo.td
@@ -182,8 +182,10 @@ def QQQQ3 : ARMReg<3, "qqqq3", [QQ6, QQ7]>;
// Current Program Status Register.
def CPSR : ARMReg<0, "cpsr">;
-def FPSCR : ARMReg<1, "fpscr">;
-def ITSTATE : ARMReg<2, "itstate">;
+def APSR : ARMReg<1, "apsr">;
+def SPSR : ARMReg<2, "spsr">;
+def FPSCR : ARMReg<3, "fpscr">;
+def ITSTATE : ARMReg<4, "itstate">;
// Special Registers - only available in privileged mode.
def FPSID : ARMReg<0, "fpsid">;
@@ -213,6 +215,23 @@ def GPR : RegisterClass<"ARM", [i32], 32, (add (sequence "R%u", 0, 12),
}];
}
+// GPRs without the PC. Some ARM instructions do not allow the PC in
+// certain operand slots, particularly as the destination. Primarily
+// useful for disassembly.
+def GPRnopc : RegisterClass<"ARM", [i32], 32, (sub GPR, PC)> {
+ let AltOrders = [(add LR, GPRnopc), (trunc GPRnopc, 8)];
+ let AltOrderSelect = [{
+ return 1 + MF.getTarget().getSubtarget<ARMSubtarget>().isThumb1Only();
+ }];
+}
+
+// GPRsp - Only the SP is legal. Used by Thumb1 instructions that want the
+// implied SP argument list.
+// FIXME: It would be better to not use this at all and refactor the
+// instructions to not have SP an an explicit argument. That makes
+// frame index resolution a bit trickier, though.
+def GPRsp : RegisterClass<"ARM", [i32], 32, (add SP)>;
+
// restricted GPR register class. Many Thumb2 instructions allow the full
// register range for operands, but have undefined behaviours when PC
// or SP (R13 or R15) are used. The ARM ISA refers to these operands
@@ -328,5 +347,6 @@ def QQQQPR : RegisterClass<"ARM", [v8i64], 256, (sequence "QQQQ%u", 0, 3)> {
// Condition code registers.
def CCR : RegisterClass<"ARM", [i32], 32, (add CPSR)> {
+ let CopyCost = -1; // Don't allow copying of status registers.
let isAllocatable = 0;
}
diff --git a/lib/Target/ARM/ARMSelectionDAGInfo.cpp b/lib/Target/ARM/ARMSelectionDAGInfo.cpp
index ef0aaf2..a3a3d58 100644
--- a/lib/Target/ARM/ARMSelectionDAGInfo.cpp
+++ b/lib/Target/ARM/ARMSelectionDAGInfo.cpp
@@ -138,13 +138,12 @@ ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
// Adjust parameters for memset, EABI uses format (ptr, size, value),
// GNU library uses (ptr, value, size)
// See RTABI section 4.3.4
-SDValue
-ARMSelectionDAGInfo::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl,
- SDValue Chain, SDValue Dst,
- SDValue Src, SDValue Size,
- unsigned Align, bool isVolatile,
- MachinePointerInfo DstPtrInfo) const
-{
+SDValue ARMSelectionDAGInfo::
+EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl,
+ SDValue Chain, SDValue Dst,
+ SDValue Src, SDValue Size,
+ unsigned Align, bool isVolatile,
+ MachinePointerInfo DstPtrInfo) const {
// Use default for non AAPCS subtargets
if (!Subtarget->isAAPCS_ABI())
return SDValue();
@@ -155,7 +154,7 @@ ARMSelectionDAGInfo::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl,
TargetLowering::ArgListEntry Entry;
// First argument: data pointer
- const Type *IntPtrTy = TLI.getTargetData()->getIntPtrType(*DAG.getContext());
+ Type *IntPtrTy = TLI.getTargetData()->getIntPtrType(*DAG.getContext());
Entry.Node = Dst;
Entry.Ty = IntPtrTy;
Args.push_back(Entry);
diff --git a/lib/Target/ARM/ARMSelectionDAGInfo.h b/lib/Target/ARM/ARMSelectionDAGInfo.h
index ec1bf5c..6419a73 100644
--- a/lib/Target/ARM/ARMSelectionDAGInfo.h
+++ b/lib/Target/ARM/ARMSelectionDAGInfo.h
@@ -14,10 +14,27 @@
#ifndef ARMSELECTIONDAGINFO_H
#define ARMSELECTIONDAGINFO_H
+#include "MCTargetDesc/ARMAddressingModes.h"
#include "llvm/Target/TargetSelectionDAGInfo.h"
namespace llvm {
+namespace ARM_AM {
+ static inline ShiftOpc getShiftOpcForNode(unsigned Opcode) {
+ switch (Opcode) {
+ default: return ARM_AM::no_shift;
+ case ISD::SHL: return ARM_AM::lsl;
+ case ISD::SRL: return ARM_AM::lsr;
+ case ISD::SRA: return ARM_AM::asr;
+ case ISD::ROTR: return ARM_AM::ror;
+ //case ISD::ROTL: // Only if imm -> turn into ROTR.
+ // Can't handle RRX here, because it would require folding a flag into
+ // the addressing mode. :( This causes us to miss certain things.
+ //case ARMISD::RRX: return ARM_AM::rrx;
+ }
+ }
+} // end namespace ARM_AM
+
class ARMSelectionDAGInfo : public TargetSelectionDAGInfo {
/// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
/// make the right decision when generating code for different targets.
diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp
index 1cab9e4..247d6be 100644
--- a/lib/Target/ARM/ARMSubtarget.cpp
+++ b/lib/Target/ARM/ARMSubtarget.cpp
@@ -53,11 +53,14 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
, HasVMLxForwarding(false)
, SlowFPBrcc(false)
, InThumbMode(false)
+ , InNaClMode(false)
, HasThumb2(false)
+ , IsMClass(false)
, NoARM(false)
, PostRAScheduler(false)
, IsR9Reserved(ReserveR9)
, UseMovt(false)
+ , SupportsTailCall(false)
, HasFP16(false)
, HasD16(false)
, HasHardwareDivide(false)
@@ -111,6 +114,8 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
else {
IsR9Reserved = ReserveR9 | !HasV6Ops;
UseMovt = DarwinUseMOVT && hasV6T2Ops();
+ const Triple &T = getTargetTriple();
+ SupportsTailCall = T.getOS() == Triple::IOS && !T.isOSVersionLT(5, 0);
}
if (!isThumb() || hasThumb2())
diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h
index c650872..b63e108 100644
--- a/lib/Target/ARM/ARMSubtarget.h
+++ b/lib/Target/ARM/ARMSubtarget.h
@@ -70,9 +70,16 @@ protected:
/// InThumbMode - True if compiling for Thumb, false for ARM.
bool InThumbMode;
+ /// InNaClMode - True if targeting Native Client
+ bool InNaClMode;
+
/// HasThumb2 - True if Thumb2 instructions are supported.
bool HasThumb2;
+ /// IsMClass - True if the subtarget belongs to the 'M' profile of CPUs -
+ /// v6m, v7m for example.
+ bool IsMClass;
+
/// NoARM - True if subtarget does not support ARM mode execution.
bool NoARM;
@@ -86,6 +93,11 @@ protected:
/// imms (including global addresses).
bool UseMovt;
+ /// SupportsTailCall - True if the OS supports tail call. The dynamic linker
+ /// must be able to synthesize call stubs for interworking between ARM and
+ /// Thumb.
+ bool SupportsTailCall;
+
/// HasFP16 - True if subtarget supports half-precision FP (We support VFP+HF
/// only so far)
bool HasFP16;
@@ -209,6 +221,9 @@ protected:
const Triple &getTargetTriple() const { return TargetTriple; }
bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
+ bool isTargetNaCl() const {
+ return TargetTriple.getOS() == Triple::NativeClient;
+ }
bool isTargetELF() const { return !isTargetDarwin(); }
bool isAPCS_ABI() const { return TargetABI == ARM_ABI_APCS; }
@@ -218,10 +233,13 @@ protected:
bool isThumb1Only() const { return InThumbMode && !HasThumb2; }
bool isThumb2() const { return InThumbMode && HasThumb2; }
bool hasThumb2() const { return HasThumb2; }
+ bool isMClass() const { return IsMClass; }
+ bool isARClass() const { return !IsMClass; }
bool isR9Reserved() const { return IsR9Reserved; }
bool useMovt() const { return UseMovt && hasV6T2Ops(); }
+ bool supportsTailCall() const { return SupportsTailCall; }
bool allowsUnalignedMem() const { return AllowsUnalignedMem; }
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
index f0b176a..96b1e89 100644
--- a/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -15,77 +15,50 @@
#include "ARM.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetRegistry.h"
using namespace llvm;
-// This is duplicated code. Refactor this.
-static MCStreamer *createMCStreamer(const Target &T, const std::string &TT,
- MCContext &Ctx, TargetAsmBackend &TAB,
- raw_ostream &OS,
- MCCodeEmitter *Emitter,
- bool RelaxAll,
- bool NoExecStack) {
- Triple TheTriple(TT);
-
- if (TheTriple.isOSDarwin())
- return createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll);
-
- if (TheTriple.isOSWindows()) {
- llvm_unreachable("ARM does not support Windows COFF format");
- return NULL;
- }
-
- return createELFStreamer(Ctx, TAB, OS, Emitter, RelaxAll, NoExecStack);
-}
+static cl::opt<bool>
+EnableGlobalMerge("global-merge", cl::Hidden,
+ cl::desc("Enable global merge pass"),
+ cl::init(true));
extern "C" void LLVMInitializeARMTarget() {
// Register the target.
RegisterTargetMachine<ARMTargetMachine> X(TheARMTarget);
RegisterTargetMachine<ThumbTargetMachine> Y(TheThumbTarget);
-
- // Register the MC Code Emitter
- TargetRegistry::RegisterCodeEmitter(TheARMTarget, createARMMCCodeEmitter);
- TargetRegistry::RegisterCodeEmitter(TheThumbTarget, createARMMCCodeEmitter);
-
- // Register the asm backend.
- TargetRegistry::RegisterAsmBackend(TheARMTarget, createARMAsmBackend);
- TargetRegistry::RegisterAsmBackend(TheThumbTarget, createARMAsmBackend);
-
- // Register the object streamer.
- TargetRegistry::RegisterObjectStreamer(TheARMTarget, createMCStreamer);
- TargetRegistry::RegisterObjectStreamer(TheThumbTarget, createMCStreamer);
-
}
/// TargetMachine ctor - Create an ARM architecture model.
///
-ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T,
- const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : LLVMTargetMachine(T, TT, CPU, FS),
+ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
Subtarget(TT, CPU, FS),
JITInfo(),
InstrItins(Subtarget.getInstrItineraryData()) {
- DefRelocModel = getRelocationModel();
-
// Default to soft float ABI
if (FloatABIType == FloatABI::Default)
FloatABIType = FloatABI::Soft;
}
-ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : ARMBaseTargetMachine(T, TT, CPU, FS), InstrInfo(Subtarget),
+ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : ARMBaseTargetMachine(T, TT, CPU, FS, RM, CM), InstrInfo(Subtarget),
DataLayout(Subtarget.isAPCS_ABI() ?
std::string("e-p:32:32-f64:32:64-i64:32:64-"
- "v128:32:128-v64:32:64-n32") :
+ "v128:32:128-v64:32:64-n32-S32") :
+ Subtarget.isAAPCS_ABI() ?
+ std::string("e-p:32:32-f64:64:64-i64:64:64-"
+ "v128:64:128-v64:64:64-n32-S64") :
std::string("e-p:32:32-f64:64:64-i64:64:64-"
- "v128:64:128-v64:64:64-n32")),
+ "v128:64:128-v64:64:64-n32-S32")),
ELFWriterInfo(*this),
TLInfo(*this),
TSInfo(*this),
@@ -95,20 +68,24 @@ ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT,
"support ARM mode execution!");
}
-ThumbTargetMachine::ThumbTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : ARMBaseTargetMachine(T, TT, CPU, FS),
+ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : ARMBaseTargetMachine(T, TT, CPU, FS, RM, CM),
InstrInfo(Subtarget.hasThumb2()
? ((ARMBaseInstrInfo*)new Thumb2InstrInfo(Subtarget))
: ((ARMBaseInstrInfo*)new Thumb1InstrInfo(Subtarget))),
DataLayout(Subtarget.isAPCS_ABI() ?
std::string("e-p:32:32-f64:32:64-i64:32:64-"
"i16:16:32-i8:8:32-i1:8:32-"
- "v128:32:128-v64:32:64-a:0:32-n32") :
+ "v128:32:128-v64:32:64-a:0:32-n32-S32") :
+ Subtarget.isAAPCS_ABI() ?
+ std::string("e-p:32:32-f64:64:64-i64:64:64-"
+ "i16:16:32-i8:8:32-i1:8:32-"
+ "v128:64:128-v64:64:64-a:0:32-n32-S64") :
std::string("e-p:32:32-f64:64:64-i64:64:64-"
"i16:16:32-i8:8:32-i1:8:32-"
- "v128:64:128-v64:64:64-a:0:32-n32")),
+ "v128:64:128-v64:64:64-a:0:32-n32-S32")),
ELFWriterInfo(*this),
TLInfo(*this),
TSInfo(*this),
@@ -117,10 +94,9 @@ ThumbTargetMachine::ThumbTargetMachine(const Target &T, const std::string &TT,
: (ARMFrameLowering*)new Thumb1FrameLowering(Subtarget)) {
}
-// Pass Pipeline Configuration
bool ARMBaseTargetMachine::addPreISel(PassManagerBase &PM,
CodeGenOpt::Level OptLevel) {
- if (OptLevel != CodeGenOpt::None)
+ if (OptLevel != CodeGenOpt::None && EnableGlobalMerge)
PM.add(createARMGlobalMergePass(getTargetLowering()));
return false;
@@ -139,7 +115,6 @@ bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM,
PM.add(createARMLoadStoreOptimizationPass(true));
if (OptLevel != CodeGenOpt::None && Subtarget.isCortexA9())
PM.add(createMLxExpansionPass());
-
return true;
}
@@ -150,7 +125,7 @@ bool ARMBaseTargetMachine::addPreSched2(PassManagerBase &PM,
if (!Subtarget.isThumb1Only())
PM.add(createARMLoadStoreOptimizationPass());
if (Subtarget.hasNEON())
- PM.add(createNEONMoveFixPass());
+ PM.add(createExecutionDependencyFixPass(&ARM::DPRRegClass));
}
// Expand some pseudo instructions into multiple instructions to allow
@@ -179,10 +154,6 @@ bool ARMBaseTargetMachine::addPreEmitPass(PassManagerBase &PM,
bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
JITCodeEmitter &JCE) {
- // FIXME: Move this to TargetJITInfo!
- if (DefRelocModel == Reloc::Default)
- setRelocationModel(Reloc::Static);
-
// Machine code emitter pass for ARM.
PM.add(createARMJITCodeEmitterPass(*this, JCE));
return false;
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
index bc3d46a..c8c601c 100644
--- a/lib/Target/ARM/ARMTargetMachine.h
+++ b/lib/Target/ARM/ARMTargetMachine.h
@@ -37,11 +37,11 @@ protected:
private:
ARMJITInfo JITInfo;
InstrItineraryData InstrItins;
- Reloc::Model DefRelocModel; // Reloc model before it's overridden.
public:
- ARMBaseTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ ARMBaseTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
virtual ARMJITInfo *getJITInfo() { return &JITInfo; }
virtual const ARMSubtarget *getSubtargetImpl() const { return &Subtarget; }
@@ -69,8 +69,9 @@ class ARMTargetMachine : public ARMBaseTargetMachine {
ARMSelectionDAGInfo TSInfo;
ARMFrameLowering FrameLowering;
public:
- ARMTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ ARMTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
virtual const ARMRegisterInfo *getRegisterInfo() const {
return &InstrInfo.getRegisterInfo();
@@ -108,8 +109,9 @@ class ThumbTargetMachine : public ARMBaseTargetMachine {
// Either Thumb1FrameLowering or ARMFrameLowering.
OwningPtr<ARMFrameLowering> FrameLowering;
public:
- ThumbTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ ThumbTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
/// returns either Thumb1RegisterInfo or Thumb2RegisterInfo
virtual const ARMBaseRegisterInfo *getRegisterInfo() const {
diff --git a/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp b/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp
index d9a5fa2..14d35ba 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp
@@ -7,16 +7,15 @@
//
//===----------------------------------------------------------------------===//
-#include "ARM.h"
-#include "ARMTargetMachine.h"
+#include "MCTargetDesc/ARMBaseInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCTargetAsmLexer.h"
-#include "llvm/Target/TargetAsmLexer.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
@@ -30,7 +29,7 @@ using namespace llvm;
namespace {
-class ARMBaseAsmLexer : public TargetAsmLexer {
+class ARMBaseAsmLexer : public MCTargetAsmLexer {
const MCAsmInfo &AsmInfo;
const AsmToken &lexDefinite() {
@@ -43,7 +42,7 @@ protected:
rmap_ty RegisterMap;
- void InitRegisterMap(const TargetRegisterInfo *info) {
+ void InitRegisterMap(const MCRegisterInfo *info) {
unsigned numRegs = info->getNumRegs();
for (unsigned i = 0; i < numRegs; ++i) {
@@ -77,33 +76,23 @@ protected:
}
public:
ARMBaseAsmLexer(const Target &T, const MCAsmInfo &MAI)
- : TargetAsmLexer(T), AsmInfo(MAI) {
+ : MCTargetAsmLexer(T), AsmInfo(MAI) {
}
};
class ARMAsmLexer : public ARMBaseAsmLexer {
public:
- ARMAsmLexer(const Target &T, const MCAsmInfo &MAI)
+ ARMAsmLexer(const Target &T, const MCRegisterInfo &MRI, const MCAsmInfo &MAI)
: ARMBaseAsmLexer(T, MAI) {
- std::string tripleString("arm-unknown-unknown");
- std::string featureString;
- std::string CPU;
- OwningPtr<const TargetMachine>
- targetMachine(T.createTargetMachine(tripleString, CPU, featureString));
- InitRegisterMap(targetMachine->getRegisterInfo());
+ InitRegisterMap(&MRI);
}
};
class ThumbAsmLexer : public ARMBaseAsmLexer {
public:
- ThumbAsmLexer(const Target &T, const MCAsmInfo &MAI)
+ ThumbAsmLexer(const Target &T, const MCRegisterInfo &MRI,const MCAsmInfo &MAI)
: ARMBaseAsmLexer(T, MAI) {
- std::string tripleString("thumb-unknown-unknown");
- std::string featureString;
- std::string CPU;
- OwningPtr<const TargetMachine>
- targetMachine(T.createTargetMachine(tripleString, CPU, featureString));
- InitRegisterMap(targetMachine->getRegisterInfo());
+ InitRegisterMap(&MRI);
}
};
@@ -149,6 +138,6 @@ AsmToken ARMBaseAsmLexer::LexTokenUAL() {
}
extern "C" void LLVMInitializeARMAsmLexer() {
- RegisterAsmLexer<ARMAsmLexer> X(TheARMTarget);
- RegisterAsmLexer<ThumbAsmLexer> Y(TheThumbTarget);
+ RegisterMCAsmLexer<ARMAsmLexer> X(TheARMTarget);
+ RegisterMCAsmLexer<ThumbAsmLexer> Y(TheThumbTarget);
}
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index a474127..24f15b4 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -7,11 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "ARM.h"
-#include "ARMAddressingModes.h"
-#include "ARMMCExpr.h"
-#include "ARMBaseRegisterInfo.h"
-#include "ARMSubtarget.h"
+#include "MCTargetDesc/ARMBaseInfo.h"
+#include "MCTargetDesc/ARMAddressingModes.h"
+#include "MCTargetDesc/ARMMCExpr.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
@@ -20,12 +18,17 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetAsmParser.h"
+#include "llvm/MC/MCTargetAsmParser.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
@@ -37,49 +40,65 @@ namespace {
class ARMOperand;
-class ARMAsmParser : public TargetAsmParser {
+class ARMAsmParser : public MCTargetAsmParser {
MCSubtargetInfo &STI;
MCAsmParser &Parser;
+ struct {
+ ARMCC::CondCodes Cond; // Condition for IT block.
+ unsigned Mask:4; // Condition mask for instructions.
+ // Starting at first 1 (from lsb).
+ // '1' condition as indicated in IT.
+ // '0' inverse of condition (else).
+ // Count of instructions in IT block is
+ // 4 - trailingzeroes(mask)
+
+ bool FirstCond; // Explicit flag for when we're parsing the
+ // First instruction in the IT block. It's
+ // implied in the mask, so needs special
+ // handling.
+
+ unsigned CurPosition; // Current position in parsing of IT
+ // block. In range [0,3]. Initialized
+ // according to count of instructions in block.
+ // ~0U if no active IT block.
+ } ITState;
+ bool inITBlock() { return ITState.CurPosition != ~0U;}
+ void forwardITPosition() {
+ if (!inITBlock()) return;
+ // Move to the next instruction in the IT block, if there is one. If not,
+ // mark the block as done.
+ unsigned TZ = CountTrailingZeros_32(ITState.Mask);
+ if (++ITState.CurPosition == 5 - TZ)
+ ITState.CurPosition = ~0U; // Done with the IT block after this.
+ }
+
+
MCAsmParser &getParser() const { return Parser; }
MCAsmLexer &getLexer() const { return Parser.getLexer(); }
void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
- int TryParseRegister();
- virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
- bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
- int TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
- bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
- bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &,
- ARMII::AddrMode AddrMode);
- bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
- bool ParsePrefix(ARMMCExpr::VariantKind &RefKind);
- const MCExpr *ApplyPrefixToExpr(const MCExpr *E,
- MCSymbolRefExpr::VariantKind Variant);
-
-
- bool ParseMemoryOffsetReg(bool &Negative,
- bool &OffsetRegShifted,
- enum ARM_AM::ShiftOpc &ShiftType,
- const MCExpr *&ShiftAmount,
- const MCExpr *&Offset,
- bool &OffsetIsReg,
- int &OffsetRegNum,
- SMLoc &E);
- bool ParseShift(enum ARM_AM::ShiftOpc &St,
- const MCExpr *&ShiftAmount, SMLoc &E);
- bool ParseDirectiveWord(unsigned Size, SMLoc L);
- bool ParseDirectiveThumb(SMLoc L);
- bool ParseDirectiveThumbFunc(SMLoc L);
- bool ParseDirectiveCode(SMLoc L);
- bool ParseDirectiveSyntax(SMLoc L);
-
- bool MatchAndEmitInstruction(SMLoc IDLoc,
- SmallVectorImpl<MCParsedAsmOperand*> &Operands,
- MCStreamer &Out);
- void GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
+ int tryParseRegister();
+ bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
+ int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
+ bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
+ bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
+ unsigned &ShiftAmount);
+ bool parseDirectiveWord(unsigned Size, SMLoc L);
+ bool parseDirectiveThumb(SMLoc L);
+ bool parseDirectiveThumbFunc(SMLoc L);
+ bool parseDirectiveCode(SMLoc L);
+ bool parseDirectiveSyntax(SMLoc L);
+
+ StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
+ bool &CarrySetting, unsigned &ProcessorIMod,
+ StringRef &ITMask);
+ void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
bool &CanAcceptPredicationCode);
bool isThumb() const {
@@ -89,10 +108,22 @@ class ARMAsmParser : public TargetAsmParser {
bool isThumbOne() const {
return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
}
+ bool isThumbTwo() const {
+ return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
+ }
+ bool hasV6Ops() const {
+ return STI.getFeatureBits() & ARM::HasV6Ops;
+ }
+ bool hasV7Ops() const {
+ return STI.getFeatureBits() & ARM::HasV7Ops;
+ }
void SwitchMode() {
unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
setAvailableFeatures(FB);
}
+ bool isMClass() const {
+ return STI.getFeatureBits() & ARM::FeatureMClass;
+ }
/// @name Auto-generated Match Functions
/// {
@@ -102,43 +133,108 @@ class ARMAsmParser : public TargetAsmParser {
/// }
- OperandMatchResultTy tryParseCoprocNumOperand(
- SmallVectorImpl<MCParsedAsmOperand*>&);
- OperandMatchResultTy tryParseCoprocRegOperand(
+ OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
+ OperandMatchResultTy parseCoprocNumOperand(
SmallVectorImpl<MCParsedAsmOperand*>&);
- OperandMatchResultTy tryParseMemBarrierOptOperand(
+ OperandMatchResultTy parseCoprocRegOperand(
SmallVectorImpl<MCParsedAsmOperand*>&);
- OperandMatchResultTy tryParseProcIFlagsOperand(
+ OperandMatchResultTy parseCoprocOptionOperand(
SmallVectorImpl<MCParsedAsmOperand*>&);
- OperandMatchResultTy tryParseMSRMaskOperand(
+ OperandMatchResultTy parseMemBarrierOptOperand(
SmallVectorImpl<MCParsedAsmOperand*>&);
- OperandMatchResultTy tryParseMemMode2Operand(
+ OperandMatchResultTy parseProcIFlagsOperand(
SmallVectorImpl<MCParsedAsmOperand*>&);
- OperandMatchResultTy tryParseMemMode3Operand(
+ OperandMatchResultTy parseMSRMaskOperand(
SmallVectorImpl<MCParsedAsmOperand*>&);
+ OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
+ StringRef Op, int Low, int High);
+ OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
+ return parsePKHImm(O, "lsl", 0, 31);
+ }
+ OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
+ return parsePKHImm(O, "asr", 1, 32);
+ }
+ OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
+ OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
+ OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
+ OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
+ OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
+ OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
+ OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
// Asm Match Converter Methods
- bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
+ bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
- bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
+ bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
- bool CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+ bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
- bool CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+ bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+ bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &);
+
+ bool validateInstruction(MCInst &Inst,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
+ void processInstruction(MCInst &Inst,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
+ bool shouldOmitCCOutOperand(StringRef Mnemonic,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands);
public:
+ enum ARMMatchResultTy {
+ Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
+ Match_RequiresNotITBlock,
+ Match_RequiresV6,
+ Match_RequiresThumb2
+ };
+
ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
- : TargetAsmParser(), STI(_STI), Parser(_Parser) {
+ : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
MCAsmParserExtension::Initialize(_Parser);
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+
+ // Not in an ITBlock to start with.
+ ITState.CurPosition = ~0U;
}
- virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
- SmallVectorImpl<MCParsedAsmOperand*> &Operands);
- virtual bool ParseDirective(AsmToken DirectiveID);
+ // Implementation of the MCTargetAsmParser interface:
+ bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
+ bool ParseInstruction(StringRef Name, SMLoc NameLoc,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands);
+ bool ParseDirective(AsmToken DirectiveID);
+
+ unsigned checkTargetMatchPredicate(MCInst &Inst);
+
+ bool MatchAndEmitInstruction(SMLoc IDLoc,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+ MCStreamer &Out);
};
} // end anonymous namespace
@@ -148,22 +244,30 @@ namespace {
/// instruction.
class ARMOperand : public MCParsedAsmOperand {
enum KindTy {
- CondCode,
- CCOut,
- CoprocNum,
- CoprocReg,
- Immediate,
- MemBarrierOpt,
- Memory,
- MSRMask,
- ProcIFlags,
- Register,
- RegisterList,
- DPRRegisterList,
- SPRRegisterList,
- ShiftedRegister,
- Shifter,
- Token
+ k_CondCode,
+ k_CCOut,
+ k_ITCondMask,
+ k_CoprocNum,
+ k_CoprocReg,
+ k_CoprocOption,
+ k_Immediate,
+ k_FPImmediate,
+ k_MemBarrierOpt,
+ k_Memory,
+ k_PostIndexRegister,
+ k_MSRMask,
+ k_ProcIFlags,
+ k_VectorIndex,
+ k_Register,
+ k_RegisterList,
+ k_DPRRegisterList,
+ k_SPRRegisterList,
+ k_ShiftedRegister,
+ k_ShiftedImmediate,
+ k_ShifterImmediate,
+ k_RotateImmediate,
+ k_BitfieldDescriptor,
+ k_Token
} Kind;
SMLoc StartLoc, EndLoc;
@@ -175,12 +279,20 @@ class ARMOperand : public MCParsedAsmOperand {
} CC;
struct {
- ARM_MB::MemBOpt Val;
- } MBOpt;
+ unsigned Val;
+ } Cop;
struct {
unsigned Val;
- } Cop;
+ } CoprocOption;
+
+ struct {
+ unsigned Mask:4;
+ } ITMask;
+
+ struct {
+ ARM_MB::MemBOpt Val;
+ } MBOpt;
struct {
ARM_PROC::IFlags Val;
@@ -200,37 +312,60 @@ class ARMOperand : public MCParsedAsmOperand {
} Reg;
struct {
+ unsigned Val;
+ } VectorIndex;
+
+ struct {
const MCExpr *Val;
} Imm;
+ struct {
+ unsigned Val; // encoded 8-bit representation
+ } FPImm;
+
/// Combined record for all forms of ARM address expressions.
struct {
- ARMII::AddrMode AddrMode;
unsigned BaseRegNum;
- union {
- unsigned RegNum; ///< Offset register num, when OffsetIsReg.
- const MCExpr *Value; ///< Offset value, when !OffsetIsReg.
- } Offset;
- const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
- enum ARM_AM::ShiftOpc ShiftType; // used when OffsetRegShifted is true
- unsigned OffsetRegShifted : 1; // only used when OffsetIsReg is true
- unsigned Preindexed : 1;
- unsigned Postindexed : 1;
- unsigned OffsetIsReg : 1;
- unsigned Negative : 1; // only used when OffsetIsReg is true
- unsigned Writeback : 1;
- } Mem;
+ // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
+ // was specified.
+ const MCConstantExpr *OffsetImm; // Offset immediate value
+ unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
+ ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
+ unsigned ShiftImm; // shift for OffsetReg.
+ unsigned Alignment; // 0 = no alignment specified
+ // n = alignment in bytes (8, 16, or 32)
+ unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
+ } Memory;
struct {
+ unsigned RegNum;
+ bool isAdd;
ARM_AM::ShiftOpc ShiftTy;
+ unsigned ShiftImm;
+ } PostIdxReg;
+
+ struct {
+ bool isASR;
unsigned Imm;
- } Shift;
+ } ShifterImm;
struct {
ARM_AM::ShiftOpc ShiftTy;
unsigned SrcReg;
unsigned ShiftReg;
unsigned ShiftImm;
- } ShiftedReg;
+ } RegShiftedReg;
+ struct {
+ ARM_AM::ShiftOpc ShiftTy;
+ unsigned SrcReg;
+ unsigned ShiftImm;
+ } RegShiftedImm;
+ struct {
+ unsigned Imm;
+ } RotImm;
+ struct {
+ unsigned LSB;
+ unsigned Width;
+ } Bitfield;
};
ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
@@ -240,45 +375,69 @@ public:
StartLoc = o.StartLoc;
EndLoc = o.EndLoc;
switch (Kind) {
- case CondCode:
+ case k_CondCode:
CC = o.CC;
break;
- case Token:
+ case k_ITCondMask:
+ ITMask = o.ITMask;
+ break;
+ case k_Token:
Tok = o.Tok;
break;
- case CCOut:
- case Register:
+ case k_CCOut:
+ case k_Register:
Reg = o.Reg;
break;
- case RegisterList:
- case DPRRegisterList:
- case SPRRegisterList:
+ case k_RegisterList:
+ case k_DPRRegisterList:
+ case k_SPRRegisterList:
Registers = o.Registers;
break;
- case CoprocNum:
- case CoprocReg:
+ case k_CoprocNum:
+ case k_CoprocReg:
Cop = o.Cop;
break;
- case Immediate:
+ case k_CoprocOption:
+ CoprocOption = o.CoprocOption;
+ break;
+ case k_Immediate:
Imm = o.Imm;
break;
- case MemBarrierOpt:
+ case k_FPImmediate:
+ FPImm = o.FPImm;
+ break;
+ case k_MemBarrierOpt:
MBOpt = o.MBOpt;
break;
- case Memory:
- Mem = o.Mem;
+ case k_Memory:
+ Memory = o.Memory;
+ break;
+ case k_PostIndexRegister:
+ PostIdxReg = o.PostIdxReg;
break;
- case MSRMask:
+ case k_MSRMask:
MMask = o.MMask;
break;
- case ProcIFlags:
+ case k_ProcIFlags:
IFlags = o.IFlags;
break;
- case Shifter:
- Shift = o.Shift;
+ case k_ShifterImmediate:
+ ShifterImm = o.ShifterImm;
+ break;
+ case k_ShiftedRegister:
+ RegShiftedReg = o.RegShiftedReg;
+ break;
+ case k_ShiftedImmediate:
+ RegShiftedImm = o.RegShiftedImm;
break;
- case ShiftedRegister:
- ShiftedReg = o.ShiftedReg;
+ case k_RotateImmediate:
+ RotImm = o.RotImm;
+ break;
+ case k_BitfieldDescriptor:
+ Bitfield = o.Bitfield;
+ break;
+ case k_VectorIndex:
+ VectorIndex = o.VectorIndex;
break;
}
}
@@ -289,94 +448,96 @@ public:
SMLoc getEndLoc() const { return EndLoc; }
ARMCC::CondCodes getCondCode() const {
- assert(Kind == CondCode && "Invalid access!");
+ assert(Kind == k_CondCode && "Invalid access!");
return CC.Val;
}
unsigned getCoproc() const {
- assert((Kind == CoprocNum || Kind == CoprocReg) && "Invalid access!");
+ assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
return Cop.Val;
}
StringRef getToken() const {
- assert(Kind == Token && "Invalid access!");
+ assert(Kind == k_Token && "Invalid access!");
return StringRef(Tok.Data, Tok.Length);
}
unsigned getReg() const {
- assert((Kind == Register || Kind == CCOut) && "Invalid access!");
+ assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
return Reg.RegNum;
}
const SmallVectorImpl<unsigned> &getRegList() const {
- assert((Kind == RegisterList || Kind == DPRRegisterList ||
- Kind == SPRRegisterList) && "Invalid access!");
+ assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
+ Kind == k_SPRRegisterList) && "Invalid access!");
return Registers;
}
const MCExpr *getImm() const {
- assert(Kind == Immediate && "Invalid access!");
+ assert(Kind == k_Immediate && "Invalid access!");
return Imm.Val;
}
+ unsigned getFPImm() const {
+ assert(Kind == k_FPImmediate && "Invalid access!");
+ return FPImm.Val;
+ }
+
+ unsigned getVectorIndex() const {
+ assert(Kind == k_VectorIndex && "Invalid access!");
+ return VectorIndex.Val;
+ }
+
ARM_MB::MemBOpt getMemBarrierOpt() const {
- assert(Kind == MemBarrierOpt && "Invalid access!");
+ assert(Kind == k_MemBarrierOpt && "Invalid access!");
return MBOpt.Val;
}
ARM_PROC::IFlags getProcIFlags() const {
- assert(Kind == ProcIFlags && "Invalid access!");
+ assert(Kind == k_ProcIFlags && "Invalid access!");
return IFlags.Val;
}
unsigned getMSRMask() const {
- assert(Kind == MSRMask && "Invalid access!");
+ assert(Kind == k_MSRMask && "Invalid access!");
return MMask.Val;
}
- /// @name Memory Operand Accessors
- /// @{
- ARMII::AddrMode getMemAddrMode() const {
- return Mem.AddrMode;
- }
- unsigned getMemBaseRegNum() const {
- return Mem.BaseRegNum;
- }
- unsigned getMemOffsetRegNum() const {
- assert(Mem.OffsetIsReg && "Invalid access!");
- return Mem.Offset.RegNum;
- }
- const MCExpr *getMemOffset() const {
- assert(!Mem.OffsetIsReg && "Invalid access!");
- return Mem.Offset.Value;
- }
- unsigned getMemOffsetRegShifted() const {
- assert(Mem.OffsetIsReg && "Invalid access!");
- return Mem.OffsetRegShifted;
+ bool isCoprocNum() const { return Kind == k_CoprocNum; }
+ bool isCoprocReg() const { return Kind == k_CoprocReg; }
+ bool isCoprocOption() const { return Kind == k_CoprocOption; }
+ bool isCondCode() const { return Kind == k_CondCode; }
+ bool isCCOut() const { return Kind == k_CCOut; }
+ bool isITMask() const { return Kind == k_ITCondMask; }
+ bool isITCondCode() const { return Kind == k_CondCode; }
+ bool isImm() const { return Kind == k_Immediate; }
+ bool isFPImm() const { return Kind == k_FPImmediate; }
+ bool isImm8s4() const {
+ if (Kind != k_Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
}
- const MCExpr *getMemShiftAmount() const {
- assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!");
- return Mem.ShiftAmount;
+ bool isImm0_1020s4() const {
+ if (Kind != k_Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
}
- enum ARM_AM::ShiftOpc getMemShiftType() const {
- assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!");
- return Mem.ShiftType;
+ bool isImm0_508s4() const {
+ if (Kind != k_Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
}
- bool getMemPreindexed() const { return Mem.Preindexed; }
- bool getMemPostindexed() const { return Mem.Postindexed; }
- bool getMemOffsetIsReg() const { return Mem.OffsetIsReg; }
- bool getMemNegative() const { return Mem.Negative; }
- bool getMemWriteback() const { return Mem.Writeback; }
-
- /// @}
-
- bool isCoprocNum() const { return Kind == CoprocNum; }
- bool isCoprocReg() const { return Kind == CoprocReg; }
- bool isCondCode() const { return Kind == CondCode; }
- bool isCCOut() const { return Kind == CCOut; }
- bool isImm() const { return Kind == Immediate; }
bool isImm0_255() const {
- if (Kind != Immediate)
+ if (Kind != k_Immediate)
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
@@ -384,7 +545,7 @@ public:
return Value >= 0 && Value < 256;
}
bool isImm0_7() const {
- if (Kind != Immediate)
+ if (Kind != k_Immediate)
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
@@ -392,130 +553,365 @@ public:
return Value >= 0 && Value < 8;
}
bool isImm0_15() const {
- if (Kind != Immediate)
+ if (Kind != k_Immediate)
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
return Value >= 0 && Value < 16;
}
+ bool isImm0_31() const {
+ if (Kind != k_Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value >= 0 && Value < 32;
+ }
+ bool isImm1_16() const {
+ if (Kind != k_Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value > 0 && Value < 17;
+ }
+ bool isImm1_32() const {
+ if (Kind != k_Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value > 0 && Value < 33;
+ }
bool isImm0_65535() const {
- if (Kind != Immediate)
+ if (Kind != k_Immediate)
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
return Value >= 0 && Value < 65536;
}
- bool isT2SOImm() const {
- if (Kind != Immediate)
+ bool isImm0_65535Expr() const {
+ if (Kind != k_Immediate)
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
- if (!CE) return false;
+ // If it's not a constant expression, it'll generate a fixup and be
+ // handled later.
+ if (!CE) return true;
int64_t Value = CE->getValue();
- return ARM_AM::getT2SOImmVal(Value) != -1;
+ return Value >= 0 && Value < 65536;
}
- bool isReg() const { return Kind == Register; }
- bool isRegList() const { return Kind == RegisterList; }
- bool isDPRRegList() const { return Kind == DPRRegisterList; }
- bool isSPRRegList() const { return Kind == SPRRegisterList; }
- bool isToken() const { return Kind == Token; }
- bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }
- bool isMemory() const { return Kind == Memory; }
- bool isShifter() const { return Kind == Shifter; }
- bool isShiftedReg() const { return Kind == ShiftedRegister; }
- bool isMemMode2() const {
- if (getMemAddrMode() != ARMII::AddrMode2)
+ bool isImm24bit() const {
+ if (Kind != k_Immediate)
return false;
-
- if (getMemOffsetIsReg())
- return true;
-
- if (getMemNegative() &&
- !(getMemPostindexed() || getMemPreindexed()))
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value >= 0 && Value <= 0xffffff;
+ }
+ bool isImmThumbSR() const {
+ if (Kind != k_Immediate)
return false;
-
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
-
- // The offset must be in the range 0-4095 (imm12).
- if (Value > 4095 || Value < -4095)
+ return Value > 0 && Value < 33;
+ }
+ bool isPKHLSLImm() const {
+ if (Kind != k_Immediate)
return false;
-
- return true;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value >= 0 && Value < 32;
}
- bool isMemMode3() const {
- if (getMemAddrMode() != ARMII::AddrMode3)
+ bool isPKHASRImm() const {
+ if (Kind != k_Immediate)
return false;
-
- if (getMemOffsetIsReg()) {
- if (getMemOffsetRegShifted())
- return false; // No shift with offset reg allowed
- return true;
- }
-
- if (getMemNegative() &&
- !(getMemPostindexed() || getMemPreindexed()))
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value > 0 && Value <= 32;
+ }
+ bool isARMSOImm() const {
+ if (Kind != k_Immediate)
return false;
-
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
-
- // The offset must be in the range 0-255 (imm8).
- if (Value > 255 || Value < -255)
+ return ARM_AM::getSOImmVal(Value) != -1;
+ }
+ bool isT2SOImm() const {
+ if (Kind != k_Immediate)
return false;
-
- return true;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return ARM_AM::getT2SOImmVal(Value) != -1;
}
- bool isMemMode5() const {
- if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||
- getMemNegative())
+ bool isSetEndImm() const {
+ if (Kind != k_Immediate)
return false;
-
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
-
- // The offset must be a multiple of 4 in the range 0-1020.
int64_t Value = CE->getValue();
- return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
- }
- bool isMemMode7() const {
- if (!isMemory() ||
- getMemPreindexed() ||
- getMemPostindexed() ||
- getMemOffsetIsReg() ||
- getMemNegative() ||
- getMemWriteback())
+ return Value == 1 || Value == 0;
+ }
+ bool isReg() const { return Kind == k_Register; }
+ bool isRegList() const { return Kind == k_RegisterList; }
+ bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
+ bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
+ bool isToken() const { return Kind == k_Token; }
+ bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
+ bool isMemory() const { return Kind == k_Memory; }
+ bool isShifterImm() const { return Kind == k_ShifterImmediate; }
+ bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
+ bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
+ bool isRotImm() const { return Kind == k_RotateImmediate; }
+ bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
+ bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
+ bool isPostIdxReg() const {
+ return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
+ }
+ bool isMemNoOffset(bool alignOK = false) const {
+ if (!isMemory())
return false;
-
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
+ // No offset of any kind.
+ return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
+ (alignOK || Memory.Alignment == 0);
+ }
+ bool isAlignedMemory() const {
+ return isMemNoOffset(true);
+ }
+ bool isAddrMode2() const {
+ if (!isMemory() || Memory.Alignment != 0) return false;
+ // Check for register offset.
+ if (Memory.OffsetRegNum) return true;
+ // Immediate offset in range [-4095, 4095].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return Val > -4096 && Val < 4096;
+ }
+ bool isAM2OffsetImm() const {
+ if (Kind != k_Immediate)
+ return false;
+ // Immediate offset in range [-4095, 4095].
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
-
- if (CE->getValue())
+ int64_t Val = CE->getValue();
+ return Val > -4096 && Val < 4096;
+ }
+ bool isAddrMode3() const {
+ if (!isMemory() || Memory.Alignment != 0) return false;
+ // No shifts are legal for AM3.
+ if (Memory.ShiftType != ARM_AM::no_shift) return false;
+ // Check for register offset.
+ if (Memory.OffsetRegNum) return true;
+ // Immediate offset in range [-255, 255].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return Val > -256 && Val < 256;
+ }
+ bool isAM3Offset() const {
+ if (Kind != k_Immediate && Kind != k_PostIndexRegister)
+ return false;
+ if (Kind == k_PostIndexRegister)
+ return PostIdxReg.ShiftTy == ARM_AM::no_shift;
+ // Immediate offset in range [-255, 255].
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Val = CE->getValue();
+ // Special case, #-0 is INT32_MIN.
+ return (Val > -256 && Val < 256) || Val == INT32_MIN;
+ }
+ bool isAddrMode5() const {
+ if (!isMemory() || Memory.Alignment != 0) return false;
+ // Check for register offset.
+ if (Memory.OffsetRegNum) return false;
+ // Immediate offset in range [-1020, 1020] and a multiple of 4.
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
+ Val == INT32_MIN;
+ }
+ bool isMemTBB() const {
+ if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
+ Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
+ return false;
+ return true;
+ }
+ bool isMemTBH() const {
+ if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
+ Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
+ Memory.Alignment != 0 )
+ return false;
+ return true;
+ }
+ bool isMemRegOffset() const {
+ if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
return false;
-
return true;
}
- bool isMemModeRegThumb() const {
- if (!isMemory() || !getMemOffsetIsReg() || getMemWriteback())
+ bool isT2MemRegOffset() const {
+ if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
+ Memory.Alignment != 0)
+ return false;
+ // Only lsl #{0, 1, 2, 3} allowed.
+ if (Memory.ShiftType == ARM_AM::no_shift)
+ return true;
+ if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
return false;
return true;
}
- bool isMemModeImmThumb() const {
- if (!isMemory() || getMemOffsetIsReg() || getMemWriteback())
+ bool isMemThumbRR() const {
+ // Thumb reg+reg addressing is simple. Just two registers, a base and
+ // an offset. No shifts, negations or any other complicating factors.
+ if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
+ Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
+ return false;
+ return isARMLowRegister(Memory.BaseRegNum) &&
+ (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
+ }
+ bool isMemThumbRIs4() const {
+ if (!isMemory() || Memory.OffsetRegNum != 0 ||
+ !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
+ return false;
+ // Immediate offset, multiple of 4 in range [0, 124].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return Val >= 0 && Val <= 124 && (Val % 4) == 0;
+ }
+ bool isMemThumbRIs2() const {
+ if (!isMemory() || Memory.OffsetRegNum != 0 ||
+ !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
+ return false;
+ // Immediate offset, multiple of 4 in range [0, 62].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return Val >= 0 && Val <= 62 && (Val % 2) == 0;
+ }
+ bool isMemThumbRIs1() const {
+ if (!isMemory() || Memory.OffsetRegNum != 0 ||
+ !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
+ return false;
+ // Immediate offset in range [0, 31].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return Val >= 0 && Val <= 31;
+ }
+ bool isMemThumbSPI() const {
+ if (!isMemory() || Memory.OffsetRegNum != 0 ||
+ Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
+ return false;
+ // Immediate offset, multiple of 4 in range [0, 1020].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
+ }
+ bool isMemImm8s4Offset() const {
+ if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
+ return false;
+ // Immediate offset a multiple of 4 in range [-1020, 1020].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
+ }
+ bool isMemImm0_1020s4Offset() const {
+ if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
+ return false;
+ // Immediate offset a multiple of 4 in range [0, 1020].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
+ }
+ bool isMemImm8Offset() const {
+ if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
+ return false;
+ // Immediate offset in range [-255, 255].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return (Val == INT32_MIN) || (Val > -256 && Val < 256);
+ }
+ bool isMemPosImm8Offset() const {
+ if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
+ return false;
+ // Immediate offset in range [0, 255].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return Val >= 0 && Val < 256;
+ }
+ bool isMemNegImm8Offset() const {
+ if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
+ return false;
+ // Immediate offset in range [-255, -1].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return Val > -256 && Val < 0;
+ }
+ bool isMemUImm12Offset() const {
+ // If we have an immediate that's not a constant, treat it as a label
+ // reference needing a fixup. If it is a constant, it's something else
+ // and we reject it.
+ if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
+ return true;
+
+ if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
return false;
+ // Immediate offset in range [0, 4095].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return (Val >= 0 && Val < 4096);
+ }
+ bool isMemImm12Offset() const {
+ // If we have an immediate that's not a constant, treat it as a label
+ // reference needing a fixup. If it is a constant, it's something else
+ // and we reject it.
+ if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
+ return true;
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
+ if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
+ return false;
+ // Immediate offset in range [-4095, 4095].
+ if (!Memory.OffsetImm) return true;
+ int64_t Val = Memory.OffsetImm->getValue();
+ return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
+ }
+ bool isPostIdxImm8() const {
+ if (Kind != k_Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Val = CE->getValue();
+ return (Val > -256 && Val < 256) || (Val == INT32_MIN);
+ }
+ bool isPostIdxImm8s4() const {
+ if (Kind != k_Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
+ int64_t Val = CE->getValue();
+ return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
+ (Val == INT32_MIN);
+ }
- // The offset must be a multiple of 4 in the range 0-124.
- uint64_t Value = CE->getValue();
- return ((Value & 0x3) == 0 && Value <= 124);
+ bool isMSRMask() const { return Kind == k_MSRMask; }
+ bool isProcIFlags() const { return Kind == k_ProcIFlags; }
+
+ bool isVectorIndex8() const {
+ if (Kind != k_VectorIndex) return false;
+ return VectorIndex.Val < 8;
+ }
+ bool isVectorIndex16() const {
+ if (Kind != k_VectorIndex) return false;
+ return VectorIndex.Val < 4;
}
- bool isMSRMask() const { return Kind == MSRMask; }
- bool isProcIFlags() const { return Kind == ProcIFlags; }
+ bool isVectorIndex32() const {
+ if (Kind != k_VectorIndex) return false;
+ return VectorIndex.Val < 2;
+ }
+
+
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
// Add as immediates when possible. Null MCExpr = 0.
@@ -544,6 +940,21 @@ public:
Inst.addOperand(MCOperand::CreateImm(getCoproc()));
}
+ void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
+ }
+
+ void addITMaskOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
+ }
+
+ void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
+ }
+
void addCCOutOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateReg(getReg()));
@@ -554,22 +965,27 @@ public:
Inst.addOperand(MCOperand::CreateReg(getReg()));
}
- void addShiftedRegOperands(MCInst &Inst, unsigned N) const {
+ void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
assert(N == 3 && "Invalid number of operands!");
- assert(isShiftedReg() && "addShiftedRegOperands() on non ShiftedReg!");
- assert((ShiftedReg.ShiftReg == 0 ||
- ARM_AM::getSORegOffset(ShiftedReg.ShiftImm) == 0) &&
- "Invalid shifted register operand!");
- Inst.addOperand(MCOperand::CreateReg(ShiftedReg.SrcReg));
- Inst.addOperand(MCOperand::CreateReg(ShiftedReg.ShiftReg));
+ assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
+ Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
+ Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Inst.addOperand(MCOperand::CreateImm(
- ARM_AM::getSORegOpc(ShiftedReg.ShiftTy, ShiftedReg.ShiftImm)));
+ ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
}
- void addShifterOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
+ void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
+ Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Inst.addOperand(MCOperand::CreateImm(
- ARM_AM::getSORegOpc(Shift.ShiftTy, 0)));
+ ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
+ }
+
+ void addShifterImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
+ ShifterImm.Imm));
}
void addRegListOperands(MCInst &Inst, unsigned N) const {
@@ -588,11 +1004,57 @@ public:
addRegListOperands(Inst, N);
}
+ void addRotImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // Encoded as val>>3. The printer handles display as 8, 16, 24.
+ Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
+ }
+
+ void addBitfieldOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // Munge the lsb/width into a bitfield mask.
+ unsigned lsb = Bitfield.LSB;
+ unsigned width = Bitfield.Width;
+ // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
+ uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
+ (32 - (lsb + width)));
+ Inst.addOperand(MCOperand::CreateImm(Mask));
+ }
+
void addImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
}
+ void addFPImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm(getFPImm()));
+ }
+
+ void addImm8s4Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // FIXME: We really want to scale the value here, but the LDRD/STRD
+ // instruction don't encode operands that way yet.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
+ }
+
+ void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // The immediate is scaled by four in the encoding and is stored
+ // in the MCInst as such. Lop off the low two bits here.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
+ }
+
+ void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // The immediate is scaled by four in the encoding and is stored
+ // in the MCInst as such. Lop off the low two bits here.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
+ }
+
void addImm0_255Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
@@ -608,137 +1070,344 @@ public:
addExpr(Inst, getImm());
}
+ void addImm0_31Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
+ void addImm1_16Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // The constant encodes as the immediate-1, and we store in the instruction
+ // the bits as encoded, so subtract off one here.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
+ }
+
+ void addImm1_32Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // The constant encodes as the immediate-1, and we store in the instruction
+ // the bits as encoded, so subtract off one here.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
+ }
+
void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
}
+ void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
+ void addImm24bitOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
+ void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // The constant encodes as the immediate, except for 32, which encodes as
+ // zero.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ unsigned Imm = CE->getValue();
+ Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
+ }
+
+ void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
+ void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // An ASR value of 32 encodes as 0, so that's how we want to add it to
+ // the instruction as well.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ int Val = CE->getValue();
+ Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
+ }
+
+ void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
}
+ void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
}
- void addMemMode7Operands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && isMemMode7() && "Invalid number of operands!");
- Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
-
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
- (void)CE;
- assert((CE || CE->getValue() == 0) &&
- "No offset operand support in mode 7");
+ void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
}
- void addMemMode2Operands(MCInst &Inst, unsigned N) const {
- assert(isMemMode2() && "Invalid mode or number of operands!");
- Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
- unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1);
+ void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
+ }
- if (getMemOffsetIsReg()) {
- Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));
+ void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 3 && "Invalid number of operands!");
+ int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
+ if (!Memory.OffsetRegNum) {
+ ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
+ // Special case for #-0
+ if (Val == INT32_MIN) Val = 0;
+ if (Val < 0) Val = -Val;
+ Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
+ } else {
+ // For register offset, we encode the shift type and negation flag
+ // here.
+ Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
+ Memory.ShiftImm, Memory.ShiftType);
+ }
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
- ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add;
- ARM_AM::ShiftOpc ShOpc = ARM_AM::no_shift;
- int64_t ShiftAmount = 0;
+ void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ assert(CE && "non-constant AM2OffsetImm operand!");
+ int32_t Val = CE->getValue();
+ ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
+ // Special case for #-0
+ if (Val == INT32_MIN) Val = 0;
+ if (Val < 0) Val = -Val;
+ Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
+ Inst.addOperand(MCOperand::CreateReg(0));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
- if (getMemOffsetRegShifted()) {
- ShOpc = getMemShiftType();
- const MCConstantExpr *CE =
- dyn_cast<MCConstantExpr>(getMemShiftAmount());
- ShiftAmount = CE->getValue();
- }
+ void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 3 && "Invalid number of operands!");
+ int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
+ if (!Memory.OffsetRegNum) {
+ ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
+ // Special case for #-0
+ if (Val == INT32_MIN) Val = 0;
+ if (Val < 0) Val = -Val;
+ Val = ARM_AM::getAM3Opc(AddSub, Val);
+ } else {
+ // For register offset, we encode the shift type and negation flag
+ // here.
+ Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
+ }
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
- Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(AMOpc, ShiftAmount,
- ShOpc, IdxMode)));
+ void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ if (Kind == k_PostIndexRegister) {
+ int32_t Val =
+ ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
+ Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
return;
}
- // Create a operand placeholder to always yield the same number of operands.
+ // Constant offset.
+ const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
+ int32_t Val = CE->getValue();
+ ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
+ // Special case for #-0
+ if (Val == INT32_MIN) Val = 0;
+ if (Val < 0) Val = -Val;
+ Val = ARM_AM::getAM3Opc(AddSub, Val);
Inst.addOperand(MCOperand::CreateReg(0));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
- // FIXME: #-0 is encoded differently than #0. Does the parser preserve
- // the difference?
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
- assert(CE && "Non-constant mode 2 offset operand!");
- int64_t Offset = CE->getValue();
+ void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ // The lower two bits are always zero and as such are not encoded.
+ int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
+ ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
+ // Special case for #-0
+ if (Val == INT32_MIN) Val = 0;
+ if (Val < 0) Val = -Val;
+ Val = ARM_AM::getAM5Opc(AddSub, Val);
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
- if (Offset >= 0)
- Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::add,
- Offset, ARM_AM::no_shift, IdxMode)));
- else
- Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::sub,
- -Offset, ARM_AM::no_shift, IdxMode)));
+ void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
+
+ void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ // The lower two bits are always zero and as such are not encoded.
+ int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
+
+ void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
+
+ void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
+ addMemImm8OffsetOperands(Inst, N);
+ }
+
+ void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
+ addMemImm8OffsetOperands(Inst, N);
}
- void addMemMode3Operands(MCInst &Inst, unsigned N) const {
- assert(isMemMode3() && "Invalid mode or number of operands!");
- Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
- unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1);
+ void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ // If this is an immediate, it's a label reference.
+ if (Kind == k_Immediate) {
+ addExpr(Inst, getImm());
+ Inst.addOperand(MCOperand::CreateImm(0));
+ return;
+ }
- if (getMemOffsetIsReg()) {
- Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));
+ // Otherwise, it's a normal memory reg+offset.
+ int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
- ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add;
- Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(AMOpc, 0,
- IdxMode)));
+ void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ // If this is an immediate, it's a label reference.
+ if (Kind == k_Immediate) {
+ addExpr(Inst, getImm());
+ Inst.addOperand(MCOperand::CreateImm(0));
return;
}
- // Create a operand placeholder to always yield the same number of operands.
- Inst.addOperand(MCOperand::CreateReg(0));
+ // Otherwise, it's a normal memory reg+offset.
+ int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
- // FIXME: #-0 is encoded differently than #0. Does the parser preserve
- // the difference?
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
- assert(CE && "Non-constant mode 3 offset operand!");
- int64_t Offset = CE->getValue();
+ void addMemTBBOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
+ }
- if (Offset >= 0)
- Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::add,
- Offset, IdxMode)));
- else
- Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::sub,
- -Offset, IdxMode)));
+ void addMemTBHOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
}
- void addMemMode5Operands(MCInst &Inst, unsigned N) const {
- assert(N == 2 && isMemMode5() && "Invalid number of operands!");
+ void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 3 && "Invalid number of operands!");
+ unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
+ Memory.ShiftImm, Memory.ShiftType);
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
- Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
- assert(!getMemOffsetIsReg() && "Invalid mode 5 operand");
+ void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 3 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
+ }
- // FIXME: #-0 is encoded differently than #0. Does the parser preserve
- // the difference?
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
- assert(CE && "Non-constant mode 5 offset operand!");
+ void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
+ }
- // The MCInst offset operand doesn't include the low two bits (like
- // the instruction encoding).
- int64_t Offset = CE->getValue() / 4;
- if (Offset >= 0)
- Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add,
- Offset)));
- else
- Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub,
- -Offset)));
+ void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
}
- void addMemModeRegThumbOperands(MCInst &Inst, unsigned N) const {
- assert(N == 2 && isMemModeRegThumb() && "Invalid number of operands!");
- Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
- Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));
+ void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
}
- void addMemModeImmThumbOperands(MCInst &Inst, unsigned N) const {
- assert(N == 2 && isMemModeImmThumb() && "Invalid number of operands!");
- Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
- assert(CE && "Non-constant mode offset operand!");
- Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
+ void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
+
+ void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
+ Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ }
+
+ void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ assert(CE && "non-constant post-idx-imm8 operand!");
+ int Imm = CE->getValue();
+ bool isAdd = Imm >= 0;
+ if (Imm == INT32_MIN) Imm = 0;
+ Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
+ Inst.addOperand(MCOperand::CreateImm(Imm));
+ }
+
+ void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ assert(CE && "non-constant post-idx-imm8s4 operand!");
+ int Imm = CE->getValue();
+ bool isAdd = Imm >= 0;
+ if (Imm == INT32_MIN) Imm = 0;
+ // Immediate is scaled by 4.
+ Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
+ Inst.addOperand(MCOperand::CreateImm(Imm));
+ }
+
+ void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
+ Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
+ }
+
+ void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
+ // The sign, shift type, and shift amount are encoded in a single operand
+ // using the AM2 encoding helpers.
+ ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
+ unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
+ PostIdxReg.ShiftTy);
+ Inst.addOperand(MCOperand::CreateImm(Imm));
}
void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
@@ -751,10 +1420,33 @@ public:
Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
}
+ void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
+ }
+
+ void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
+ }
+
+ void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
+ }
+
virtual void print(raw_ostream &OS) const;
+ static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
+ ARMOperand *Op = new ARMOperand(k_ITCondMask);
+ Op->ITMask.Mask = Mask;
+ Op->StartLoc = S;
+ Op->EndLoc = S;
+ return Op;
+ }
+
static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
- ARMOperand *Op = new ARMOperand(CondCode);
+ ARMOperand *Op = new ARMOperand(k_CondCode);
Op->CC.Val = CC;
Op->StartLoc = S;
Op->EndLoc = S;
@@ -762,7 +1454,7 @@ public:
}
static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
- ARMOperand *Op = new ARMOperand(CoprocNum);
+ ARMOperand *Op = new ARMOperand(k_CoprocNum);
Op->Cop.Val = CopVal;
Op->StartLoc = S;
Op->EndLoc = S;
@@ -770,15 +1462,23 @@ public:
}
static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
- ARMOperand *Op = new ARMOperand(CoprocReg);
+ ARMOperand *Op = new ARMOperand(k_CoprocReg);
Op->Cop.Val = CopVal;
Op->StartLoc = S;
Op->EndLoc = S;
return Op;
}
+ static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
+ ARMOperand *Op = new ARMOperand(k_CoprocOption);
+ Op->Cop.Val = Val;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
- ARMOperand *Op = new ARMOperand(CCOut);
+ ARMOperand *Op = new ARMOperand(k_CCOut);
Op->Reg.RegNum = RegNum;
Op->StartLoc = S;
Op->EndLoc = S;
@@ -786,7 +1486,7 @@ public:
}
static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
- ARMOperand *Op = new ARMOperand(Token);
+ ARMOperand *Op = new ARMOperand(k_Token);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
Op->StartLoc = S;
@@ -795,7 +1495,7 @@ public:
}
static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
- ARMOperand *Op = new ARMOperand(Register);
+ ARMOperand *Op = new ARMOperand(k_Register);
Op->Reg.RegNum = RegNum;
Op->StartLoc = S;
Op->EndLoc = E;
@@ -807,20 +1507,52 @@ public:
unsigned ShiftReg,
unsigned ShiftImm,
SMLoc S, SMLoc E) {
- ARMOperand *Op = new ARMOperand(ShiftedRegister);
- Op->ShiftedReg.ShiftTy = ShTy;
- Op->ShiftedReg.SrcReg = SrcReg;
- Op->ShiftedReg.ShiftReg = ShiftReg;
- Op->ShiftedReg.ShiftImm = ShiftImm;
+ ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
+ Op->RegShiftedReg.ShiftTy = ShTy;
+ Op->RegShiftedReg.SrcReg = SrcReg;
+ Op->RegShiftedReg.ShiftReg = ShiftReg;
+ Op->RegShiftedReg.ShiftImm = ShiftImm;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
+ unsigned SrcReg,
+ unsigned ShiftImm,
+ SMLoc S, SMLoc E) {
+ ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
+ Op->RegShiftedImm.ShiftTy = ShTy;
+ Op->RegShiftedImm.SrcReg = SrcReg;
+ Op->RegShiftedImm.ShiftImm = ShiftImm;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
- static ARMOperand *CreateShifter(ARM_AM::ShiftOpc ShTy,
+ static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
SMLoc S, SMLoc E) {
- ARMOperand *Op = new ARMOperand(Shifter);
- Op->Shift.ShiftTy = ShTy;
+ ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
+ Op->ShifterImm.isASR = isASR;
+ Op->ShifterImm.Imm = Imm;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
+ ARMOperand *Op = new ARMOperand(k_RotateImmediate);
+ Op->RotImm.Imm = Imm;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
+ SMLoc S, SMLoc E) {
+ ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
+ Op->Bitfield.LSB = LSB;
+ Op->Bitfield.Width = Width;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
@@ -829,12 +1561,13 @@ public:
static ARMOperand *
CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
SMLoc StartLoc, SMLoc EndLoc) {
- KindTy Kind = RegisterList;
+ KindTy Kind = k_RegisterList;
- if (ARM::DPRRegClass.contains(Regs.front().first))
- Kind = DPRRegisterList;
- else if (ARM::SPRRegClass.contains(Regs.front().first))
- Kind = SPRRegisterList;
+ if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
+ Kind = k_DPRRegisterList;
+ else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
+ contains(Regs.front().first))
+ Kind = k_SPRRegisterList;
ARMOperand *Op = new ARMOperand(Kind);
for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
@@ -846,55 +1579,68 @@ public:
return Op;
}
+ static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
+ MCContext &Ctx) {
+ ARMOperand *Op = new ARMOperand(k_VectorIndex);
+ Op->VectorIndex.Val = Idx;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
- ARMOperand *Op = new ARMOperand(Immediate);
+ ARMOperand *Op = new ARMOperand(k_Immediate);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
- static ARMOperand *CreateMem(ARMII::AddrMode AddrMode, unsigned BaseRegNum,
- bool OffsetIsReg, const MCExpr *Offset,
- int OffsetRegNum, bool OffsetRegShifted,
- enum ARM_AM::ShiftOpc ShiftType,
- const MCExpr *ShiftAmount, bool Preindexed,
- bool Postindexed, bool Negative, bool Writeback,
+ static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
+ ARMOperand *Op = new ARMOperand(k_FPImmediate);
+ Op->FPImm.Val = Val;
+ Op->StartLoc = S;
+ Op->EndLoc = S;
+ return Op;
+ }
+
+ static ARMOperand *CreateMem(unsigned BaseRegNum,
+ const MCConstantExpr *OffsetImm,
+ unsigned OffsetRegNum,
+ ARM_AM::ShiftOpc ShiftType,
+ unsigned ShiftImm,
+ unsigned Alignment,
+ bool isNegative,
SMLoc S, SMLoc E) {
- assert((OffsetRegNum == -1 || OffsetIsReg) &&
- "OffsetRegNum must imply OffsetIsReg!");
- assert((!OffsetRegShifted || OffsetIsReg) &&
- "OffsetRegShifted must imply OffsetIsReg!");
- assert((Offset || OffsetIsReg) &&
- "Offset must exists unless register offset is used!");
- assert((!ShiftAmount || (OffsetIsReg && OffsetRegShifted)) &&
- "Cannot have shift amount without shifted register offset!");
- assert((!Offset || !OffsetIsReg) &&
- "Cannot have expression offset and register offset!");
-
- ARMOperand *Op = new ARMOperand(Memory);
- Op->Mem.AddrMode = AddrMode;
- Op->Mem.BaseRegNum = BaseRegNum;
- Op->Mem.OffsetIsReg = OffsetIsReg;
- if (OffsetIsReg)
- Op->Mem.Offset.RegNum = OffsetRegNum;
- else
- Op->Mem.Offset.Value = Offset;
- Op->Mem.OffsetRegShifted = OffsetRegShifted;
- Op->Mem.ShiftType = ShiftType;
- Op->Mem.ShiftAmount = ShiftAmount;
- Op->Mem.Preindexed = Preindexed;
- Op->Mem.Postindexed = Postindexed;
- Op->Mem.Negative = Negative;
- Op->Mem.Writeback = Writeback;
+ ARMOperand *Op = new ARMOperand(k_Memory);
+ Op->Memory.BaseRegNum = BaseRegNum;
+ Op->Memory.OffsetImm = OffsetImm;
+ Op->Memory.OffsetRegNum = OffsetRegNum;
+ Op->Memory.ShiftType = ShiftType;
+ Op->Memory.ShiftImm = ShiftImm;
+ Op->Memory.Alignment = Alignment;
+ Op->Memory.isNegative = isNegative;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+ static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
+ ARM_AM::ShiftOpc ShiftTy,
+ unsigned ShiftImm,
+ SMLoc S, SMLoc E) {
+ ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
+ Op->PostIdxReg.RegNum = RegNum;
+ Op->PostIdxReg.isAdd = isAdd;
+ Op->PostIdxReg.ShiftTy = ShiftTy;
+ Op->PostIdxReg.ShiftImm = ShiftImm;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
- ARMOperand *Op = new ARMOperand(MemBarrierOpt);
+ ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Op->MBOpt.Val = Opt;
Op->StartLoc = S;
Op->EndLoc = S;
@@ -902,7 +1648,7 @@ public:
}
static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
- ARMOperand *Op = new ARMOperand(ProcIFlags);
+ ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Op->IFlags.Val = IFlags;
Op->StartLoc = S;
Op->EndLoc = S;
@@ -910,7 +1656,7 @@ public:
}
static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
- ARMOperand *Op = new ARMOperand(MSRMask);
+ ARMOperand *Op = new ARMOperand(k_MSRMask);
Op->MMask.Val = MMask;
Op->StartLoc = S;
Op->EndLoc = S;
@@ -922,53 +1668,56 @@ public:
void ARMOperand::print(raw_ostream &OS) const {
switch (Kind) {
- case CondCode:
+ case k_FPImmediate:
+ OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
+ << ") >";
+ break;
+ case k_CondCode:
OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
break;
- case CCOut:
+ case k_CCOut:
OS << "<ccout " << getReg() << ">";
break;
- case CoprocNum:
+ case k_ITCondMask: {
+ static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
+ "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
+ "(tee)", "(eee)" };
+ assert((ITMask.Mask & 0xf) == ITMask.Mask);
+ OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
+ break;
+ }
+ case k_CoprocNum:
OS << "<coprocessor number: " << getCoproc() << ">";
break;
- case CoprocReg:
+ case k_CoprocReg:
OS << "<coprocessor register: " << getCoproc() << ">";
break;
- case MSRMask:
+ case k_CoprocOption:
+ OS << "<coprocessor option: " << CoprocOption.Val << ">";
+ break;
+ case k_MSRMask:
OS << "<mask: " << getMSRMask() << ">";
break;
- case Immediate:
+ case k_Immediate:
getImm()->print(OS);
break;
- case MemBarrierOpt:
+ case k_MemBarrierOpt:
OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
break;
- case Memory:
+ case k_Memory:
OS << "<memory "
- << "am:" << ARMII::AddrModeToString(getMemAddrMode())
- << " base:" << getMemBaseRegNum();
- if (getMemOffsetIsReg()) {
- OS << " offset:<register " << getMemOffsetRegNum();
- if (getMemOffsetRegShifted()) {
- OS << " offset-shift-type:" << getMemShiftType();
- OS << " offset-shift-amount:" << *getMemShiftAmount();
- }
- } else {
- OS << " offset:" << *getMemOffset();
- }
- if (getMemOffsetIsReg())
- OS << " (offset-is-reg)";
- if (getMemPreindexed())
- OS << " (pre-indexed)";
- if (getMemPostindexed())
- OS << " (post-indexed)";
- if (getMemNegative())
- OS << " (negative)";
- if (getMemWriteback())
- OS << " (writeback)";
+ << " base:" << Memory.BaseRegNum;
+ OS << ">";
+ break;
+ case k_PostIndexRegister:
+ OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
+ << PostIdxReg.RegNum;
+ if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
+ OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
+ << PostIdxReg.ShiftImm;
OS << ">";
break;
- case ProcIFlags: {
+ case k_ProcIFlags: {
OS << "<ARM_PROC::";
unsigned IFlags = getProcIFlags();
for (int i=2; i >= 0; --i)
@@ -977,23 +1726,38 @@ void ARMOperand::print(raw_ostream &OS) const {
OS << ">";
break;
}
- case Register:
+ case k_Register:
OS << "<register " << getReg() << ">";
break;
- case Shifter:
- OS << "<shifter " << ARM_AM::getShiftOpcStr(Shift.ShiftTy) << ">";
+ case k_ShifterImmediate:
+ OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
+ << " #" << ShifterImm.Imm << ">";
+ break;
+ case k_ShiftedRegister:
+ OS << "<so_reg_reg "
+ << RegShiftedReg.SrcReg
+ << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
+ << ", " << RegShiftedReg.ShiftReg << ", "
+ << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
+ << ">";
break;
- case ShiftedRegister:
- OS << "<so_reg"
- << ShiftedReg.SrcReg
- << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(ShiftedReg.ShiftImm))
- << ", " << ShiftedReg.ShiftReg << ", "
- << ARM_AM::getSORegOffset(ShiftedReg.ShiftImm)
+ case k_ShiftedImmediate:
+ OS << "<so_reg_imm "
+ << RegShiftedImm.SrcReg
+ << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
+ << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
<< ">";
break;
- case RegisterList:
- case DPRRegisterList:
- case SPRRegisterList: {
+ case k_RotateImmediate:
+ OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
+ break;
+ case k_BitfieldDescriptor:
+ OS << "<bitfield " << "lsb: " << Bitfield.LSB
+ << ", width: " << Bitfield.Width << ">";
+ break;
+ case k_RegisterList:
+ case k_DPRRegisterList:
+ case k_SPRRegisterList: {
OS << "<register_list ";
const SmallVectorImpl<unsigned> &RegList = getRegList();
@@ -1006,9 +1770,12 @@ void ARMOperand::print(raw_ostream &OS) const {
OS << ">";
break;
}
- case Token:
+ case k_Token:
OS << "'" << getToken() << "'";
break;
+ case k_VectorIndex:
+ OS << "<vectorindex " << getVectorIndex() << ">";
+ break;
}
}
@@ -1021,7 +1788,7 @@ static unsigned MatchRegisterName(StringRef Name);
bool ARMAsmParser::ParseRegister(unsigned &RegNo,
SMLoc &StartLoc, SMLoc &EndLoc) {
- RegNo = TryParseRegister();
+ RegNo = tryParseRegister();
return (RegNo == (unsigned)-1);
}
@@ -1030,9 +1797,9 @@ bool ARMAsmParser::ParseRegister(unsigned &RegNo,
/// and if it is a register name the token is eaten and the register number is
/// returned. Otherwise return -1.
///
-int ARMAsmParser::TryParseRegister() {
+int ARMAsmParser::tryParseRegister() {
const AsmToken &Tok = Parser.getTok();
- assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
+ if (Tok.isNot(AsmToken::Identifier)) return -1;
// FIXME: Validate register for the current architecture; we have to do
// validation later, so maybe there is no need for this here.
@@ -1050,6 +1817,39 @@ int ARMAsmParser::TryParseRegister() {
if (!RegNum) return -1;
Parser.Lex(); // Eat identifier token.
+
+#if 0
+ // Also check for an index operand. This is only legal for vector registers,
+ // but that'll get caught OK in operand matching, so we don't need to
+ // explicitly filter everything else out here.
+ if (Parser.getTok().is(AsmToken::LBrac)) {
+ SMLoc SIdx = Parser.getTok().getLoc();
+ Parser.Lex(); // Eat left bracket token.
+
+ const MCExpr *ImmVal;
+ SMLoc ExprLoc = Parser.getTok().getLoc();
+ if (getParser().ParseExpression(ImmVal))
+ return MatchOperand_ParseFail;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
+ if (!MCE) {
+ TokError("immediate value expected for vector index");
+ return MatchOperand_ParseFail;
+ }
+
+ SMLoc E = Parser.getTok().getLoc();
+ if (Parser.getTok().isNot(AsmToken::RBrac)) {
+ Error(E, "']' expected");
+ return MatchOperand_ParseFail;
+ }
+
+ Parser.Lex(); // Eat right bracket token.
+
+ Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
+ SIdx, E,
+ getContext()));
+ }
+#endif
+
return RegNum;
}
@@ -1058,7 +1858,7 @@ int ARMAsmParser::TryParseRegister() {
// occurs, return -1. An irrecoverable error is one where tokens have been
// consumed in the process of trying to parse the shifter (i.e., when it is
// indeed a shifter operand, but malformed).
-int ARMAsmParser::TryParseShiftRegister(
+int ARMAsmParser::tryParseShiftRegister(
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
@@ -1120,7 +1920,7 @@ int ARMAsmParser::TryParseShiftRegister(
return -1;
}
} else if (Parser.getTok().is(AsmToken::Identifier)) {
- ShiftReg = TryParseRegister();
+ ShiftReg = tryParseRegister();
SMLoc L = Parser.getTok().getLoc();
if (ShiftReg == -1) {
Error (L, "expected immediate or register in shift operand");
@@ -1133,8 +1933,12 @@ int ARMAsmParser::TryParseShiftRegister(
}
}
- Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
- ShiftReg, Imm,
+ if (ShiftReg && ShiftTy != ARM_AM::rrx)
+ Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
+ ShiftReg, Imm,
+ S, Parser.getTok().getLoc()));
+ else
+ Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
S, Parser.getTok().getLoc()));
return 0;
@@ -1148,9 +1952,9 @@ int ARMAsmParser::TryParseShiftRegister(
/// TODO this is likely to change to allow different register types and or to
/// parse for a specific register type.
bool ARMAsmParser::
-TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
- int RegNo = TryParseRegister();
+ int RegNo = tryParseRegister();
if (RegNo == -1)
return true;
@@ -1161,6 +1965,37 @@ TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
ExclaimTok.getLoc()));
Parser.Lex(); // Eat exclaim token
+ return false;
+ }
+
+ // Also check for an index operand. This is only legal for vector registers,
+ // but that'll get caught OK in operand matching, so we don't need to
+ // explicitly filter everything else out here.
+ if (Parser.getTok().is(AsmToken::LBrac)) {
+ SMLoc SIdx = Parser.getTok().getLoc();
+ Parser.Lex(); // Eat left bracket token.
+
+ const MCExpr *ImmVal;
+ SMLoc ExprLoc = Parser.getTok().getLoc();
+ if (getParser().ParseExpression(ImmVal))
+ return MatchOperand_ParseFail;
+ const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
+ if (!MCE) {
+ TokError("immediate value expected for vector index");
+ return MatchOperand_ParseFail;
+ }
+
+ SMLoc E = Parser.getTok().getLoc();
+ if (Parser.getTok().isNot(AsmToken::RBrac)) {
+ Error(E, "']' expected");
+ return MatchOperand_ParseFail;
+ }
+
+ Parser.Lex(); // Eat right bracket token.
+
+ Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
+ SIdx, E,
+ getContext()));
}
return false;
@@ -1209,14 +2044,50 @@ static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
return -1;
}
-/// tryParseCoprocNumOperand - Try to parse an coprocessor number operand. The
+/// parseITCondCode - Try to parse a condition code for an IT instruction.
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ SMLoc S = Parser.getTok().getLoc();
+ const AsmToken &Tok = Parser.getTok();
+ if (!Tok.is(AsmToken::Identifier))
+ return MatchOperand_NoMatch;
+ unsigned CC = StringSwitch<unsigned>(Tok.getString())
+ .Case("eq", ARMCC::EQ)
+ .Case("ne", ARMCC::NE)
+ .Case("hs", ARMCC::HS)
+ .Case("cs", ARMCC::HS)
+ .Case("lo", ARMCC::LO)
+ .Case("cc", ARMCC::LO)
+ .Case("mi", ARMCC::MI)
+ .Case("pl", ARMCC::PL)
+ .Case("vs", ARMCC::VS)
+ .Case("vc", ARMCC::VC)
+ .Case("hi", ARMCC::HI)
+ .Case("ls", ARMCC::LS)
+ .Case("ge", ARMCC::GE)
+ .Case("lt", ARMCC::LT)
+ .Case("gt", ARMCC::GT)
+ .Case("le", ARMCC::LE)
+ .Case("al", ARMCC::AL)
+ .Default(~0U);
+ if (CC == ~0U)
+ return MatchOperand_NoMatch;
+ Parser.Lex(); // Eat the token.
+
+ Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
+
+ return MatchOperand_Success;
+}
+
+/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
/// token must be an Identifier when called, and if it is a coprocessor
/// number, the token is eaten and the operand is added to the operand list.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
-tryParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
- assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
+ if (Tok.isNot(AsmToken::Identifier))
+ return MatchOperand_NoMatch;
int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
if (Num == -1)
@@ -1227,14 +2098,15 @@ tryParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
-/// tryParseCoprocRegOperand - Try to parse an coprocessor register operand. The
+/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
/// token must be an Identifier when called, and if it is a coprocessor
/// number, the token is eaten and the operand is added to the operand list.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
-tryParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
- assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
+ if (Tok.isNot(AsmToken::Identifier))
+ return MatchOperand_NoMatch;
int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
if (Reg == -1)
@@ -1245,93 +2117,155 @@ tryParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
-/// Parse a register list, return it if successful else return null. The first
-/// token must be a '{' when called.
-bool ARMAsmParser::
-ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
- assert(Parser.getTok().is(AsmToken::LCurly) &&
- "Token is not a Left Curly Brace");
+/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
+/// coproc_option : '{' imm0_255 '}'
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
- // Read the rest of the registers in the list.
- unsigned PrevRegNum = 0;
- SmallVector<std::pair<unsigned, SMLoc>, 32> Registers;
-
- do {
- bool IsRange = Parser.getTok().is(AsmToken::Minus);
- Parser.Lex(); // Eat non-identifier token.
-
- const AsmToken &RegTok = Parser.getTok();
- SMLoc RegLoc = RegTok.getLoc();
- if (RegTok.isNot(AsmToken::Identifier)) {
- Error(RegLoc, "register expected");
- return true;
- }
-
- int RegNum = TryParseRegister();
- if (RegNum == -1) {
- Error(RegLoc, "register expected");
- return true;
- }
-
- if (IsRange) {
- int Reg = PrevRegNum;
- do {
- ++Reg;
- Registers.push_back(std::make_pair(Reg, RegLoc));
- } while (Reg != RegNum);
- } else {
- Registers.push_back(std::make_pair(RegNum, RegLoc));
- }
-
- PrevRegNum = RegNum;
- } while (Parser.getTok().is(AsmToken::Comma) ||
- Parser.getTok().is(AsmToken::Minus));
+ // If this isn't a '{', this isn't a coprocessor immediate operand.
+ if (Parser.getTok().isNot(AsmToken::LCurly))
+ return MatchOperand_NoMatch;
+ Parser.Lex(); // Eat the '{'
- // Process the right curly brace of the list.
- const AsmToken &RCurlyTok = Parser.getTok();
- if (RCurlyTok.isNot(AsmToken::RCurly)) {
- Error(RCurlyTok.getLoc(), "'}' expected");
- return true;
+ const MCExpr *Expr;
+ SMLoc Loc = Parser.getTok().getLoc();
+ if (getParser().ParseExpression(Expr)) {
+ Error(Loc, "illegal expression");
+ return MatchOperand_ParseFail;
}
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
+ if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
+ Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
+ return MatchOperand_ParseFail;
+ }
+ int Val = CE->getValue();
- SMLoc E = RCurlyTok.getLoc();
- Parser.Lex(); // Eat right curly brace token.
-
- // Verify the register list.
- SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
- RI = Registers.begin(), RE = Registers.end();
+ // Check for and consume the closing '}'
+ if (Parser.getTok().isNot(AsmToken::RCurly))
+ return MatchOperand_ParseFail;
+ SMLoc E = Parser.getTok().getLoc();
+ Parser.Lex(); // Eat the '}'
- unsigned HighRegNum = getARMRegisterNumbering(RI->first);
- bool EmittedWarning = false;
+ Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
+ return MatchOperand_Success;
+}
- DenseMap<unsigned, bool> RegMap;
- RegMap[HighRegNum] = true;
+// For register list parsing, we need to map from raw GPR register numbering
+// to the enumeration values. The enumeration values aren't sorted by
+// register number due to our using "sp", "lr" and "pc" as canonical names.
+static unsigned getNextRegister(unsigned Reg) {
+ // If this is a GPR, we need to do it manually, otherwise we can rely
+ // on the sort ordering of the enumeration since the other reg-classes
+ // are sane.
+ if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
+ return Reg + 1;
+ switch(Reg) {
+ default: assert(0 && "Invalid GPR number!");
+ case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
+ case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
+ case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
+ case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
+ case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
+ case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
+ case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
+ case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
+ }
+}
- for (++RI; RI != RE; ++RI) {
- const std::pair<unsigned, SMLoc> &RegInfo = *RI;
- unsigned Reg = getARMRegisterNumbering(RegInfo.first);
+/// Parse a register list.
+bool ARMAsmParser::
+parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ assert(Parser.getTok().is(AsmToken::LCurly) &&
+ "Token is not a Left Curly Brace");
+ SMLoc S = Parser.getTok().getLoc();
+ Parser.Lex(); // Eat '{' token.
+ SMLoc RegLoc = Parser.getTok().getLoc();
- if (RegMap[Reg]) {
- Error(RegInfo.second, "register duplicated in register list");
- return true;
+ // Check the first register in the list to see what register class
+ // this is a list of.
+ int Reg = tryParseRegister();
+ if (Reg == -1)
+ return Error(RegLoc, "register expected");
+
+ MCRegisterClass *RC;
+ if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
+ RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
+ else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
+ RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
+ else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
+ RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
+ else
+ return Error(RegLoc, "invalid register in register list");
+
+ // The reglist instructions have at most 16 registers, so reserve
+ // space for that many.
+ SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
+ // Store the first register.
+ Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
+
+ // This starts immediately after the first register token in the list,
+ // so we can see either a comma or a minus (range separator) as a legal
+ // next token.
+ while (Parser.getTok().is(AsmToken::Comma) ||
+ Parser.getTok().is(AsmToken::Minus)) {
+ if (Parser.getTok().is(AsmToken::Minus)) {
+ Parser.Lex(); // Eat the comma.
+ SMLoc EndLoc = Parser.getTok().getLoc();
+ int EndReg = tryParseRegister();
+ if (EndReg == -1)
+ return Error(EndLoc, "register expected");
+ // If the register is the same as the start reg, there's nothing
+ // more to do.
+ if (Reg == EndReg)
+ continue;
+ // The register must be in the same register class as the first.
+ if (!RC->contains(EndReg))
+ return Error(EndLoc, "invalid register in register list");
+ // Ranges must go from low to high.
+ if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
+ return Error(EndLoc, "bad range in register list");
+
+ // Add all the registers in the range to the register list.
+ while (Reg != EndReg) {
+ Reg = getNextRegister(Reg);
+ Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
+ }
+ continue;
}
-
- if (!EmittedWarning && Reg < HighRegNum)
- Warning(RegInfo.second,
- "register not in ascending order in register list");
-
- RegMap[Reg] = true;
- HighRegNum = std::max(Reg, HighRegNum);
+ Parser.Lex(); // Eat the comma.
+ RegLoc = Parser.getTok().getLoc();
+ int OldReg = Reg;
+ Reg = tryParseRegister();
+ if (Reg == -1)
+ return Error(RegLoc, "register expected");
+ // The register must be in the same register class as the first.
+ if (!RC->contains(Reg))
+ return Error(RegLoc, "invalid register in register list");
+ // List must be monotonically increasing.
+ if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
+ return Error(RegLoc, "register list not in ascending order");
+ // VFP register lists must also be contiguous.
+ // It's OK to use the enumeration values directly here rather, as the
+ // VFP register classes have the enum sorted properly.
+ if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
+ Reg != OldReg + 1)
+ return Error(RegLoc, "non-contiguous register range");
+ Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
}
+ SMLoc E = Parser.getTok().getLoc();
+ if (Parser.getTok().isNot(AsmToken::RCurly))
+ return Error(E, "'}' expected");
+ Parser.Lex(); // Eat '}' token.
+
Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
return false;
}
-/// tryParseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
+/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
-tryParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
@@ -1360,28 +2294,32 @@ tryParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
-/// tryParseProcIFlagsOperand - Try to parse iflags from CPS instruction.
+/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
-tryParseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
StringRef IFlagsStr = Tok.getString();
+ // An iflags string of "none" is interpreted to mean that none of the AIF
+ // bits are set. Not a terribly useful instruction, but a valid encoding.
unsigned IFlags = 0;
- for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
- unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
- .Case("a", ARM_PROC::A)
- .Case("i", ARM_PROC::I)
- .Case("f", ARM_PROC::F)
- .Default(~0U);
-
- // If some specific iflag is already set, it means that some letter is
- // present more than once, this is not acceptable.
- if (Flag == ~0U || (IFlags & Flag))
- return MatchOperand_NoMatch;
+ if (IFlagsStr != "none") {
+ for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
+ unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
+ .Case("a", ARM_PROC::A)
+ .Case("i", ARM_PROC::I)
+ .Case("f", ARM_PROC::F)
+ .Default(~0U);
+
+ // If some specific iflag is already set, it means that some letter is
+ // present more than once, this is not acceptable.
+ if (Flag == ~0U || (IFlags & Flag))
+ return MatchOperand_NoMatch;
- IFlags |= Flag;
+ IFlags |= Flag;
+ }
}
Parser.Lex(); // Eat identifier token.
@@ -1389,18 +2327,49 @@ tryParseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
-/// tryParseMSRMaskOperand - Try to parse mask flags from MSR instruction.
+/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
-tryParseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
StringRef Mask = Tok.getString();
+ if (isMClass()) {
+ // See ARMv6-M 10.1.1
+ unsigned FlagsVal = StringSwitch<unsigned>(Mask)
+ .Case("apsr", 0)
+ .Case("iapsr", 1)
+ .Case("eapsr", 2)
+ .Case("xpsr", 3)
+ .Case("ipsr", 5)
+ .Case("epsr", 6)
+ .Case("iepsr", 7)
+ .Case("msp", 8)
+ .Case("psp", 9)
+ .Case("primask", 16)
+ .Case("basepri", 17)
+ .Case("basepri_max", 18)
+ .Case("faultmask", 19)
+ .Case("control", 20)
+ .Default(~0U);
+
+ if (FlagsVal == ~0U)
+ return MatchOperand_NoMatch;
+
+ if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
+ // basepri, basepri_max and faultmask only valid for V7m.
+ return MatchOperand_NoMatch;
+
+ Parser.Lex(); // Eat identifier token.
+ Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
+ return MatchOperand_Success;
+ }
+
// Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
size_t Start = 0, Next = Mask.find('_');
StringRef Flags = "";
- StringRef SpecReg = Mask.slice(Start, Next);
+ std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
if (Next != StringRef::npos)
Flags = Mask.slice(Next+1, Mask.size());
@@ -1411,7 +2380,7 @@ tryParseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
if (SpecReg == "apsr") {
FlagsVal = StringSwitch<unsigned>(Flags)
- .Case("nzcvq", 0x8) // same as CPSR_c
+ .Case("nzcvq", 0x8) // same as CPSR_f
.Case("g", 0x4) // same as CPSR_s
.Case("nzcvqg", 0xc) // same as CPSR_fs
.Default(~0U);
@@ -1420,7 +2389,7 @@ tryParseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
if (!Flags.empty())
return MatchOperand_NoMatch;
else
- FlagsVal = 0; // No flag
+ FlagsVal = 8; // No flag
}
} else if (SpecReg == "cpsr" || SpecReg == "spsr") {
if (Flags == "all") // cpsr_all is an alias for cpsr_fc
@@ -1455,96 +2424,680 @@ tryParseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
-/// tryParseMemMode2Operand - Try to parse memory addressing mode 2 operand.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
-tryParseMemMode2Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
- assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\"");
+parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
+ int Low, int High) {
+ const AsmToken &Tok = Parser.getTok();
+ if (Tok.isNot(AsmToken::Identifier)) {
+ Error(Parser.getTok().getLoc(), Op + " operand expected.");
+ return MatchOperand_ParseFail;
+ }
+ StringRef ShiftName = Tok.getString();
+ std::string LowerOp = LowercaseString(Op);
+ std::string UpperOp = UppercaseString(Op);
+ if (ShiftName != LowerOp && ShiftName != UpperOp) {
+ Error(Parser.getTok().getLoc(), Op + " operand expected.");
+ return MatchOperand_ParseFail;
+ }
+ Parser.Lex(); // Eat shift type token.
- if (ParseMemory(Operands, ARMII::AddrMode2))
- return MatchOperand_NoMatch;
+ // There must be a '#' and a shift amount.
+ if (Parser.getTok().isNot(AsmToken::Hash)) {
+ Error(Parser.getTok().getLoc(), "'#' expected");
+ return MatchOperand_ParseFail;
+ }
+ Parser.Lex(); // Eat hash token.
+
+ const MCExpr *ShiftAmount;
+ SMLoc Loc = Parser.getTok().getLoc();
+ if (getParser().ParseExpression(ShiftAmount)) {
+ Error(Loc, "illegal expression");
+ return MatchOperand_ParseFail;
+ }
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
+ if (!CE) {
+ Error(Loc, "constant expression expected");
+ return MatchOperand_ParseFail;
+ }
+ int Val = CE->getValue();
+ if (Val < Low || Val > High) {
+ Error(Loc, "immediate value out of range");
+ return MatchOperand_ParseFail;
+ }
+
+ Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
return MatchOperand_Success;
}
-/// tryParseMemMode3Operand - Try to parse memory addressing mode 3 operand.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
-tryParseMemMode3Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
- assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\"");
+parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ const AsmToken &Tok = Parser.getTok();
+ SMLoc S = Tok.getLoc();
+ if (Tok.isNot(AsmToken::Identifier)) {
+ Error(Tok.getLoc(), "'be' or 'le' operand expected");
+ return MatchOperand_ParseFail;
+ }
+ int Val = StringSwitch<int>(Tok.getString())
+ .Case("be", 1)
+ .Case("le", 0)
+ .Default(-1);
+ Parser.Lex(); // Eat the token.
+
+ if (Val == -1) {
+ Error(Tok.getLoc(), "'be' or 'le' operand expected");
+ return MatchOperand_ParseFail;
+ }
+ Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
+ getContext()),
+ S, Parser.getTok().getLoc()));
+ return MatchOperand_Success;
+}
+
+/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
+/// instructions. Legal values are:
+/// lsl #n 'n' in [0,31]
+/// asr #n 'n' in [1,32]
+/// n == 32 encoded as n == 0.
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ const AsmToken &Tok = Parser.getTok();
+ SMLoc S = Tok.getLoc();
+ if (Tok.isNot(AsmToken::Identifier)) {
+ Error(S, "shift operator 'asr' or 'lsl' expected");
+ return MatchOperand_ParseFail;
+ }
+ StringRef ShiftName = Tok.getString();
+ bool isASR;
+ if (ShiftName == "lsl" || ShiftName == "LSL")
+ isASR = false;
+ else if (ShiftName == "asr" || ShiftName == "ASR")
+ isASR = true;
+ else {
+ Error(S, "shift operator 'asr' or 'lsl' expected");
+ return MatchOperand_ParseFail;
+ }
+ Parser.Lex(); // Eat the operator.
+
+ // A '#' and a shift amount.
+ if (Parser.getTok().isNot(AsmToken::Hash)) {
+ Error(Parser.getTok().getLoc(), "'#' expected");
+ return MatchOperand_ParseFail;
+ }
+ Parser.Lex(); // Eat hash token.
+
+ const MCExpr *ShiftAmount;
+ SMLoc E = Parser.getTok().getLoc();
+ if (getParser().ParseExpression(ShiftAmount)) {
+ Error(E, "malformed shift expression");
+ return MatchOperand_ParseFail;
+ }
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
+ if (!CE) {
+ Error(E, "shift amount must be an immediate");
+ return MatchOperand_ParseFail;
+ }
- if (ParseMemory(Operands, ARMII::AddrMode3))
+ int64_t Val = CE->getValue();
+ if (isASR) {
+ // Shift amount must be in [1,32]
+ if (Val < 1 || Val > 32) {
+ Error(E, "'asr' shift amount must be in range [1,32]");
+ return MatchOperand_ParseFail;
+ }
+ // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
+ if (isThumb() && Val == 32) {
+ Error(E, "'asr #32' shift amount not allowed in Thumb mode");
+ return MatchOperand_ParseFail;
+ }
+ if (Val == 32) Val = 0;
+ } else {
+ // Shift amount must be in [1,32]
+ if (Val < 0 || Val > 31) {
+ Error(E, "'lsr' shift amount must be in range [0,31]");
+ return MatchOperand_ParseFail;
+ }
+ }
+
+ E = Parser.getTok().getLoc();
+ Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
+
+ return MatchOperand_Success;
+}
+
+/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
+/// of instructions. Legal values are:
+/// ror #n 'n' in {0, 8, 16, 24}
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ const AsmToken &Tok = Parser.getTok();
+ SMLoc S = Tok.getLoc();
+ if (Tok.isNot(AsmToken::Identifier))
+ return MatchOperand_NoMatch;
+ StringRef ShiftName = Tok.getString();
+ if (ShiftName != "ror" && ShiftName != "ROR")
return MatchOperand_NoMatch;
+ Parser.Lex(); // Eat the operator.
+
+ // A '#' and a rotate amount.
+ if (Parser.getTok().isNot(AsmToken::Hash)) {
+ Error(Parser.getTok().getLoc(), "'#' expected");
+ return MatchOperand_ParseFail;
+ }
+ Parser.Lex(); // Eat hash token.
+
+ const MCExpr *ShiftAmount;
+ SMLoc E = Parser.getTok().getLoc();
+ if (getParser().ParseExpression(ShiftAmount)) {
+ Error(E, "malformed rotate expression");
+ return MatchOperand_ParseFail;
+ }
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
+ if (!CE) {
+ Error(E, "rotate amount must be an immediate");
+ return MatchOperand_ParseFail;
+ }
+
+ int64_t Val = CE->getValue();
+ // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
+ // normally, zero is represented in asm by omitting the rotate operand
+ // entirely.
+ if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
+ Error(E, "'ror' rotate amount must be 8, 16, or 24");
+ return MatchOperand_ParseFail;
+ }
+
+ E = Parser.getTok().getLoc();
+ Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
+
+ return MatchOperand_Success;
+}
+
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ SMLoc S = Parser.getTok().getLoc();
+ // The bitfield descriptor is really two operands, the LSB and the width.
+ if (Parser.getTok().isNot(AsmToken::Hash)) {
+ Error(Parser.getTok().getLoc(), "'#' expected");
+ return MatchOperand_ParseFail;
+ }
+ Parser.Lex(); // Eat hash token.
+
+ const MCExpr *LSBExpr;
+ SMLoc E = Parser.getTok().getLoc();
+ if (getParser().ParseExpression(LSBExpr)) {
+ Error(E, "malformed immediate expression");
+ return MatchOperand_ParseFail;
+ }
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
+ if (!CE) {
+ Error(E, "'lsb' operand must be an immediate");
+ return MatchOperand_ParseFail;
+ }
+
+ int64_t LSB = CE->getValue();
+ // The LSB must be in the range [0,31]
+ if (LSB < 0 || LSB > 31) {
+ Error(E, "'lsb' operand must be in the range [0,31]");
+ return MatchOperand_ParseFail;
+ }
+ E = Parser.getTok().getLoc();
+
+ // Expect another immediate operand.
+ if (Parser.getTok().isNot(AsmToken::Comma)) {
+ Error(Parser.getTok().getLoc(), "too few operands");
+ return MatchOperand_ParseFail;
+ }
+ Parser.Lex(); // Eat hash token.
+ if (Parser.getTok().isNot(AsmToken::Hash)) {
+ Error(Parser.getTok().getLoc(), "'#' expected");
+ return MatchOperand_ParseFail;
+ }
+ Parser.Lex(); // Eat hash token.
+
+ const MCExpr *WidthExpr;
+ if (getParser().ParseExpression(WidthExpr)) {
+ Error(E, "malformed immediate expression");
+ return MatchOperand_ParseFail;
+ }
+ CE = dyn_cast<MCConstantExpr>(WidthExpr);
+ if (!CE) {
+ Error(E, "'width' operand must be an immediate");
+ return MatchOperand_ParseFail;
+ }
+
+ int64_t Width = CE->getValue();
+ // The LSB must be in the range [1,32-lsb]
+ if (Width < 1 || Width > 32 - LSB) {
+ Error(E, "'width' operand must be in the range [1,32-lsb]");
+ return MatchOperand_ParseFail;
+ }
+ E = Parser.getTok().getLoc();
+
+ Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
return MatchOperand_Success;
}
-/// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Check for a post-index addressing register operand. Specifically:
+ // postidx_reg := '+' register {, shift}
+ // | '-' register {, shift}
+ // | register {, shift}
+
+ // This method must return MatchOperand_NoMatch without consuming any tokens
+ // in the case where there is no match, as other alternatives take other
+ // parse methods.
+ AsmToken Tok = Parser.getTok();
+ SMLoc S = Tok.getLoc();
+ bool haveEaten = false;
+ bool isAdd = true;
+ int Reg = -1;
+ if (Tok.is(AsmToken::Plus)) {
+ Parser.Lex(); // Eat the '+' token.
+ haveEaten = true;
+ } else if (Tok.is(AsmToken::Minus)) {
+ Parser.Lex(); // Eat the '-' token.
+ isAdd = false;
+ haveEaten = true;
+ }
+ if (Parser.getTok().is(AsmToken::Identifier))
+ Reg = tryParseRegister();
+ if (Reg == -1) {
+ if (!haveEaten)
+ return MatchOperand_NoMatch;
+ Error(Parser.getTok().getLoc(), "register expected");
+ return MatchOperand_ParseFail;
+ }
+ SMLoc E = Parser.getTok().getLoc();
+
+ ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
+ unsigned ShiftImm = 0;
+ if (Parser.getTok().is(AsmToken::Comma)) {
+ Parser.Lex(); // Eat the ','.
+ if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
+ return MatchOperand_ParseFail;
+ }
+
+ Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
+ ShiftImm, S, E));
+
+ return MatchOperand_Success;
+}
+
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Check for a post-index addressing register operand. Specifically:
+ // am3offset := '+' register
+ // | '-' register
+ // | register
+ // | # imm
+ // | # + imm
+ // | # - imm
+
+ // This method must return MatchOperand_NoMatch without consuming any tokens
+ // in the case where there is no match, as other alternatives take other
+ // parse methods.
+ AsmToken Tok = Parser.getTok();
+ SMLoc S = Tok.getLoc();
+
+ // Do immediates first, as we always parse those if we have a '#'.
+ if (Parser.getTok().is(AsmToken::Hash)) {
+ Parser.Lex(); // Eat the '#'.
+ // Explicitly look for a '-', as we need to encode negative zero
+ // differently.
+ bool isNegative = Parser.getTok().is(AsmToken::Minus);
+ const MCExpr *Offset;
+ if (getParser().ParseExpression(Offset))
+ return MatchOperand_ParseFail;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
+ if (!CE) {
+ Error(S, "constant expression expected");
+ return MatchOperand_ParseFail;
+ }
+ SMLoc E = Tok.getLoc();
+ // Negative zero is encoded as the flag value INT32_MIN.
+ int32_t Val = CE->getValue();
+ if (isNegative && Val == 0)
+ Val = INT32_MIN;
+
+ Operands.push_back(
+ ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
+
+ return MatchOperand_Success;
+ }
+
+
+ bool haveEaten = false;
+ bool isAdd = true;
+ int Reg = -1;
+ if (Tok.is(AsmToken::Plus)) {
+ Parser.Lex(); // Eat the '+' token.
+ haveEaten = true;
+ } else if (Tok.is(AsmToken::Minus)) {
+ Parser.Lex(); // Eat the '-' token.
+ isAdd = false;
+ haveEaten = true;
+ }
+ if (Parser.getTok().is(AsmToken::Identifier))
+ Reg = tryParseRegister();
+ if (Reg == -1) {
+ if (!haveEaten)
+ return MatchOperand_NoMatch;
+ Error(Parser.getTok().getLoc(), "register expected");
+ return MatchOperand_ParseFail;
+ }
+ SMLoc E = Parser.getTok().getLoc();
+
+ Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
+ 0, S, E));
+
+ return MatchOperand_Success;
+}
+
+/// cvtT2LdrdPre - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Rt, Rt2
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateReg(0));
+ // addr
+ ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
+ // pred
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// cvtT2StrdPre - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateReg(0));
+ // Rt, Rt2
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
+ // addr
+ ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
+ // pred
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.
bool ARMAsmParser::
-CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
+cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
// Create a writeback register dummy placeholder.
Inst.addOperand(MCOperand::CreateImm(0));
- ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);
+ ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
return true;
}
-/// CvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
+/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.
bool ARMAsmParser::
-CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
+cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// Create a writeback register dummy placeholder.
Inst.addOperand(MCOperand::CreateImm(0));
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
- ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);
+ ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
return true;
}
-/// CvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
+/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.
bool ARMAsmParser::
-CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
// Create a writeback register dummy placeholder.
Inst.addOperand(MCOperand::CreateImm(0));
- ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3);
+ ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+
+ ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+
+/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
return true;
}
-/// CvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
+/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.
bool ARMAsmParser::
-CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// Create a writeback register dummy placeholder.
Inst.addOperand(MCOperand::CreateImm(0));
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
- ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3);
+ ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Rt
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+ // addr
+ ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
+ // offset
+ ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
+ // pred
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Rt
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+ // addr
+ ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
+ // offset
+ ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
+ // pred
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+ // Rt
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ // addr
+ ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
+ // offset
+ ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
+ // pred
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+ // Rt
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ // addr
+ ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
+ // offset
+ ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
+ // pred
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// cvtLdrdPre - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtLdrdPre(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Rt, Rt2
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+ // addr
+ ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
+ // pred
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// cvtStrdPre - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtStrdPre(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+ // Rt, Rt2
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
+ // addr
+ ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
+ // pred
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
return true;
}
+/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+ // Create a writeback register dummy placeholder.
+ Inst.addOperand(MCOperand::CreateImm(0));
+ ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
+ ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+ return true;
+}
+
+/// cvtThumbMultiple- Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // The second source operand must be the same register as the destination
+ // operand.
+ if (Operands.size() == 6 &&
+ (((ARMOperand*)Operands[3])->getReg() !=
+ ((ARMOperand*)Operands[5])->getReg()) &&
+ (((ARMOperand*)Operands[3])->getReg() !=
+ ((ARMOperand*)Operands[4])->getReg())) {
+ Error(Operands[3]->getStartLoc(),
+ "destination register must match source register");
+ return false;
+ }
+ ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
+ ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
+ ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
+ // If we have a three-operand form, use that, else the second source operand
+ // is just the destination operand again.
+ if (Operands.size() == 6)
+ ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
+ else
+ Inst.addOperand(Inst.getOperand(0));
+ ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
+
+ return true;
+}
+
/// Parse an ARM memory expression, return false if successful else return true
/// or an error. The first token must be a '[' when called.
-///
-/// TODO Only preindexing and postindexing addressing are started, unindexed
-/// with option, etc are still to do.
bool ARMAsmParser::
-ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
- ARMII::AddrMode AddrMode = ARMII::AddrModeNone) {
+parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S, E;
assert(Parser.getTok().is(AsmToken::LBrac) &&
"Token is not a Left Bracket");
@@ -1552,185 +3105,178 @@ ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Parser.Lex(); // Eat left bracket token.
const AsmToken &BaseRegTok = Parser.getTok();
- if (BaseRegTok.isNot(AsmToken::Identifier)) {
- Error(BaseRegTok.getLoc(), "register expected");
- return true;
- }
- int BaseRegNum = TryParseRegister();
- if (BaseRegNum == -1) {
- Error(BaseRegTok.getLoc(), "register expected");
- return true;
- }
+ int BaseRegNum = tryParseRegister();
+ if (BaseRegNum == -1)
+ return Error(BaseRegTok.getLoc(), "register expected");
// The next token must either be a comma or a closing bracket.
const AsmToken &Tok = Parser.getTok();
if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
- return true;
+ return Error(Tok.getLoc(), "malformed memory operand");
- bool Preindexed = false;
- bool Postindexed = false;
- bool OffsetIsReg = false;
- bool Negative = false;
- bool Writeback = false;
- ARMOperand *WBOp = 0;
- int OffsetRegNum = -1;
- bool OffsetRegShifted = false;
- enum ARM_AM::ShiftOpc ShiftType = ARM_AM::lsl;
- const MCExpr *ShiftAmount = 0;
- const MCExpr *Offset = 0;
-
- // First look for preindexed address forms, that is after the "[Rn" we now
- // have to see if the next token is a comma.
- if (Tok.is(AsmToken::Comma)) {
- Preindexed = true;
- Parser.Lex(); // Eat comma token.
-
- if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
- Offset, OffsetIsReg, OffsetRegNum, E))
- return true;
- const AsmToken &RBracTok = Parser.getTok();
- if (RBracTok.isNot(AsmToken::RBrac)) {
- Error(RBracTok.getLoc(), "']' expected");
- return true;
- }
- E = RBracTok.getLoc();
+ if (Tok.is(AsmToken::RBrac)) {
+ E = Tok.getLoc();
Parser.Lex(); // Eat right bracket token.
- const AsmToken &ExclaimTok = Parser.getTok();
- if (ExclaimTok.is(AsmToken::Exclaim)) {
- // None of addrmode3 instruction uses "!"
- if (AddrMode == ARMII::AddrMode3)
- return true;
+ Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
+ 0, 0, false, S, E));
- WBOp = ARMOperand::CreateToken(ExclaimTok.getString(),
- ExclaimTok.getLoc());
- Writeback = true;
- Parser.Lex(); // Eat exclaim token
- } else { // In addressing mode 2, pre-indexed mode always end with "!"
- if (AddrMode == ARMII::AddrMode2)
- Preindexed = false;
+ // If there's a pre-indexing writeback marker, '!', just add it as a token
+ // operand. It's rather odd, but syntactically valid.
+ if (Parser.getTok().is(AsmToken::Exclaim)) {
+ Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
+ Parser.Lex(); // Eat the '!'.
}
- } else {
- // The "[Rn" we have so far was not followed by a comma.
- // If there's anything other than the right brace, this is a post indexing
- // addressing form.
- E = Tok.getLoc();
- Parser.Lex(); // Eat right bracket token.
+ return false;
+ }
- const AsmToken &NextTok = Parser.getTok();
+ assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
+ Parser.Lex(); // Eat the comma.
- if (NextTok.isNot(AsmToken::EndOfStatement)) {
- Postindexed = true;
- Writeback = true;
+ // If we have a ':', it's an alignment specifier.
+ if (Parser.getTok().is(AsmToken::Colon)) {
+ Parser.Lex(); // Eat the ':'.
+ E = Parser.getTok().getLoc();
- if (NextTok.isNot(AsmToken::Comma)) {
- Error(NextTok.getLoc(), "',' expected");
- return true;
- }
-
- Parser.Lex(); // Eat comma token.
+ const MCExpr *Expr;
+ if (getParser().ParseExpression(Expr))
+ return true;
- if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
- ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
- E))
- return true;
+ // The expression has to be a constant. Memory references with relocations
+ // don't come through here, as they use the <label> forms of the relevant
+ // instructions.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
+ if (!CE)
+ return Error (E, "constant expression expected");
+
+ unsigned Align = 0;
+ switch (CE->getValue()) {
+ default:
+ return Error(E, "alignment specifier must be 64, 128, or 256 bits");
+ case 64: Align = 8; break;
+ case 128: Align = 16; break;
+ case 256: Align = 32; break;
}
- }
- // Force Offset to exist if used.
- if (!OffsetIsReg) {
- if (!Offset)
- Offset = MCConstantExpr::Create(0, getContext());
- } else {
- if (AddrMode == ARMII::AddrMode3 && OffsetRegShifted) {
- Error(E, "shift amount not supported");
- return true;
+ // Now we should have the closing ']'
+ E = Parser.getTok().getLoc();
+ if (Parser.getTok().isNot(AsmToken::RBrac))
+ return Error(E, "']' expected");
+ Parser.Lex(); // Eat right bracket token.
+
+ // Don't worry about range checking the value here. That's handled by
+ // the is*() predicates.
+ Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
+ ARM_AM::no_shift, 0, Align,
+ false, S, E));
+
+ // If there's a pre-indexing writeback marker, '!', just add it as a token
+ // operand.
+ if (Parser.getTok().is(AsmToken::Exclaim)) {
+ Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
+ Parser.Lex(); // Eat the '!'.
}
+
+ return false;
}
- Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg,
- Offset, OffsetRegNum, OffsetRegShifted,
- ShiftType, ShiftAmount, Preindexed,
- Postindexed, Negative, Writeback, S, E));
- if (WBOp)
- Operands.push_back(WBOp);
+ // If we have a '#', it's an immediate offset, else assume it's a register
+ // offset.
+ if (Parser.getTok().is(AsmToken::Hash)) {
+ Parser.Lex(); // Eat the '#'.
+ E = Parser.getTok().getLoc();
- return false;
-}
+ bool isNegative = getParser().getTok().is(AsmToken::Minus);
+ const MCExpr *Offset;
+ if (getParser().ParseExpression(Offset))
+ return true;
+
+ // The expression has to be a constant. Memory references with relocations
+ // don't come through here, as they use the <label> forms of the relevant
+ // instructions.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
+ if (!CE)
+ return Error (E, "constant expression expected");
+
+ // If the constant was #-0, represent it as INT32_MIN.
+ int32_t Val = CE->getValue();
+ if (isNegative && Val == 0)
+ CE = MCConstantExpr::Create(INT32_MIN, getContext());
+
+ // Now we should have the closing ']'
+ E = Parser.getTok().getLoc();
+ if (Parser.getTok().isNot(AsmToken::RBrac))
+ return Error(E, "']' expected");
+ Parser.Lex(); // Eat right bracket token.
-/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
-/// we will parse the following (were +/- means that a plus or minus is
-/// optional):
-/// +/-Rm
-/// +/-Rm, shift
-/// #offset
-/// we return false on success or an error otherwise.
-bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
- bool &OffsetRegShifted,
- enum ARM_AM::ShiftOpc &ShiftType,
- const MCExpr *&ShiftAmount,
- const MCExpr *&Offset,
- bool &OffsetIsReg,
- int &OffsetRegNum,
- SMLoc &E) {
- Negative = false;
- OffsetRegShifted = false;
- OffsetIsReg = false;
- OffsetRegNum = -1;
- const AsmToken &NextTok = Parser.getTok();
- E = NextTok.getLoc();
- if (NextTok.is(AsmToken::Plus))
- Parser.Lex(); // Eat plus token.
- else if (NextTok.is(AsmToken::Minus)) {
- Negative = true;
- Parser.Lex(); // Eat minus token
- }
- // See if there is a register following the "[Rn," or "[Rn]," we have so far.
- const AsmToken &OffsetRegTok = Parser.getTok();
- if (OffsetRegTok.is(AsmToken::Identifier)) {
- SMLoc CurLoc = OffsetRegTok.getLoc();
- OffsetRegNum = TryParseRegister();
- if (OffsetRegNum != -1) {
- OffsetIsReg = true;
- E = CurLoc;
+ // Don't worry about range checking the value here. That's handled by
+ // the is*() predicates.
+ Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
+ ARM_AM::no_shift, 0, 0,
+ false, S, E));
+
+ // If there's a pre-indexing writeback marker, '!', just add it as a token
+ // operand.
+ if (Parser.getTok().is(AsmToken::Exclaim)) {
+ Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
+ Parser.Lex(); // Eat the '!'.
}
- }
- // If we parsed a register as the offset then there can be a shift after that.
- if (OffsetRegNum != -1) {
- // Look for a comma then a shift
- const AsmToken &Tok = Parser.getTok();
- if (Tok.is(AsmToken::Comma)) {
- Parser.Lex(); // Eat comma token.
+ return false;
+ }
- const AsmToken &Tok = Parser.getTok();
- if (ParseShift(ShiftType, ShiftAmount, E))
- return Error(Tok.getLoc(), "shift expected");
- OffsetRegShifted = true;
- }
+ // The register offset is optionally preceded by a '+' or '-'
+ bool isNegative = false;
+ if (Parser.getTok().is(AsmToken::Minus)) {
+ isNegative = true;
+ Parser.Lex(); // Eat the '-'.
+ } else if (Parser.getTok().is(AsmToken::Plus)) {
+ // Nothing to do.
+ Parser.Lex(); // Eat the '+'.
}
- else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
- // Look for #offset following the "[Rn," or "[Rn],"
- const AsmToken &HashTok = Parser.getTok();
- if (HashTok.isNot(AsmToken::Hash))
- return Error(HashTok.getLoc(), "'#' expected");
- Parser.Lex(); // Eat hash token.
+ E = Parser.getTok().getLoc();
+ int OffsetRegNum = tryParseRegister();
+ if (OffsetRegNum == -1)
+ return Error(E, "register expected");
+
+ // If there's a shift operator, handle it.
+ ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
+ unsigned ShiftImm = 0;
+ if (Parser.getTok().is(AsmToken::Comma)) {
+ Parser.Lex(); // Eat the ','.
+ if (parseMemRegOffsetShift(ShiftType, ShiftImm))
+ return true;
+ }
- if (getParser().ParseExpression(Offset))
- return true;
- E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ // Now we should have the closing ']'
+ E = Parser.getTok().getLoc();
+ if (Parser.getTok().isNot(AsmToken::RBrac))
+ return Error(E, "']' expected");
+ Parser.Lex(); // Eat right bracket token.
+
+ Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
+ ShiftType, ShiftImm, 0, isNegative,
+ S, E));
+
+ // If there's a pre-indexing writeback marker, '!', just add it as a token
+ // operand.
+ if (Parser.getTok().is(AsmToken::Exclaim)) {
+ Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
+ Parser.Lex(); // Eat the '!'.
}
+
return false;
}
-/// ParseShift as one of these two:
+/// parseMemRegOffsetShift - one of these two:
/// ( lsl | lsr | asr | ror ) , # shift_amount
/// rrx
-/// and returns true if it parses a shift otherwise it returns false.
-bool ARMAsmParser::ParseShift(ARM_AM::ShiftOpc &St,
- const MCExpr *&ShiftAmount, SMLoc &E) {
+/// return true if it parses a shift otherwise it returns false.
+bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
+ unsigned &Amount) {
+ SMLoc Loc = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Identifier))
return true;
@@ -1746,28 +3292,86 @@ bool ARMAsmParser::ParseShift(ARM_AM::ShiftOpc &St,
else if (ShiftName == "rrx" || ShiftName == "RRX")
St = ARM_AM::rrx;
else
- return true;
+ return Error(Loc, "illegal shift operator");
Parser.Lex(); // Eat shift type token.
- // Rrx stands alone.
- if (St == ARM_AM::rrx)
- return false;
-
- // Otherwise, there must be a '#' and a shift amount.
- const AsmToken &HashTok = Parser.getTok();
- if (HashTok.isNot(AsmToken::Hash))
- return Error(HashTok.getLoc(), "'#' expected");
- Parser.Lex(); // Eat hash token.
+ // rrx stands alone.
+ Amount = 0;
+ if (St != ARM_AM::rrx) {
+ Loc = Parser.getTok().getLoc();
+ // A '#' and a shift amount.
+ const AsmToken &HashTok = Parser.getTok();
+ if (HashTok.isNot(AsmToken::Hash))
+ return Error(HashTok.getLoc(), "'#' expected");
+ Parser.Lex(); // Eat hash token.
- if (getParser().ParseExpression(ShiftAmount))
- return true;
+ const MCExpr *Expr;
+ if (getParser().ParseExpression(Expr))
+ return true;
+ // Range check the immediate.
+ // lsl, ror: 0 <= imm <= 31
+ // lsr, asr: 0 <= imm <= 32
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
+ if (!CE)
+ return Error(Loc, "shift amount must be an immediate");
+ int64_t Imm = CE->getValue();
+ if (Imm < 0 ||
+ ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
+ ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
+ return Error(Loc, "immediate shift value out of range");
+ Amount = Imm;
+ }
return false;
}
+/// parseFPImm - A floating point immediate expression operand.
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ SMLoc S = Parser.getTok().getLoc();
+
+ if (Parser.getTok().isNot(AsmToken::Hash))
+ return MatchOperand_NoMatch;
+ Parser.Lex(); // Eat the '#'.
+
+ // Handle negation, as that still comes through as a separate token.
+ bool isNegative = false;
+ if (Parser.getTok().is(AsmToken::Minus)) {
+ isNegative = true;
+ Parser.Lex();
+ }
+ const AsmToken &Tok = Parser.getTok();
+ if (Tok.is(AsmToken::Real)) {
+ APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
+ uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
+ // If we had a '-' in front, toggle the sign bit.
+ IntVal ^= (uint64_t)isNegative << 63;
+ int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
+ Parser.Lex(); // Eat the token.
+ if (Val == -1) {
+ TokError("floating point value out of range");
+ return MatchOperand_ParseFail;
+ }
+ Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
+ return MatchOperand_Success;
+ }
+ if (Tok.is(AsmToken::Integer)) {
+ int64_t Val = Tok.getIntVal();
+ Parser.Lex(); // Eat the token.
+ if (Val > 255 || Val < 0) {
+ TokError("encoded floating point value out of range");
+ return MatchOperand_ParseFail;
+ }
+ Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
+ return MatchOperand_Success;
+ }
+
+ TokError("invalid floating point immediate");
+ return MatchOperand_ParseFail;
+}
/// Parse a arm instruction operand. For now this parses the operand regardless
/// of the mnemonic.
-bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
StringRef Mnemonic) {
SMLoc S, E;
@@ -1787,13 +3391,20 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Error(Parser.getTok().getLoc(), "unexpected token in operand");
return true;
case AsmToken::Identifier: {
- if (!TryParseRegisterWithWriteBack(Operands))
+ // If this is VMRS, check for the apsr_nzcv operand.
+ if (!tryParseRegisterWithWriteBack(Operands))
return false;
- int Res = TryParseShiftRegister(Operands);
+ int Res = tryParseShiftRegister(Operands);
if (Res == 0) // success
return false;
else if (Res == -1) // irrecoverable error
return true;
+ if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
+ S = Parser.getTok().getLoc();
+ Parser.Lex();
+ Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
+ return false;
+ }
// Fall though for the Identifier case that is not a register or a
// special name.
@@ -1811,26 +3422,36 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
return false;
}
case AsmToken::LBrac:
- return ParseMemory(Operands);
+ return parseMemory(Operands);
case AsmToken::LCurly:
- return ParseRegisterList(Operands);
- case AsmToken::Hash:
+ return parseRegisterList(Operands);
+ case AsmToken::Hash: {
// #42 -> immediate.
// TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
S = Parser.getTok().getLoc();
Parser.Lex();
+ bool isNegative = Parser.getTok().is(AsmToken::Minus);
const MCExpr *ImmVal;
if (getParser().ParseExpression(ImmVal))
return true;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
+ if (!CE) {
+ Error(S, "constant expression expected");
+ return MatchOperand_ParseFail;
+ }
+ int32_t Val = CE->getValue();
+ if (isNegative && Val == 0)
+ ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
return false;
+ }
case AsmToken::Colon: {
// ":lower16:" and ":upper16:" expression prefixes
// FIXME: Check it's an expression prefix,
// e.g. (FOO - :lower16:BAR) isn't legal.
ARMMCExpr::VariantKind RefKind;
- if (ParsePrefix(RefKind))
+ if (parsePrefix(RefKind))
return true;
const MCExpr *SubExprVal;
@@ -1846,9 +3467,9 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
}
}
-// ParsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
+// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
// :lower16: and :upper16:.
-bool ARMAsmParser::ParsePrefix(ARMMCExpr::VariantKind &RefKind) {
+bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
RefKind = ARMMCExpr::VK_ARM_None;
// :lower16: and :upper16: modifiers
@@ -1879,55 +3500,16 @@ bool ARMAsmParser::ParsePrefix(ARMMCExpr::VariantKind &RefKind) {
return false;
}
-const MCExpr *
-ARMAsmParser::ApplyPrefixToExpr(const MCExpr *E,
- MCSymbolRefExpr::VariantKind Variant) {
- // Recurse over the given expression, rebuilding it to apply the given variant
- // to the leftmost symbol.
- if (Variant == MCSymbolRefExpr::VK_None)
- return E;
-
- switch (E->getKind()) {
- case MCExpr::Target:
- llvm_unreachable("Can't handle target expr yet");
- case MCExpr::Constant:
- llvm_unreachable("Can't handle lower16/upper16 of constant yet");
-
- case MCExpr::SymbolRef: {
- const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
-
- if (SRE->getKind() != MCSymbolRefExpr::VK_None)
- return 0;
-
- return MCSymbolRefExpr::Create(&SRE->getSymbol(), Variant, getContext());
- }
-
- case MCExpr::Unary:
- llvm_unreachable("Can't handle unary expressions yet");
-
- case MCExpr::Binary: {
- const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
- const MCExpr *LHS = ApplyPrefixToExpr(BE->getLHS(), Variant);
- const MCExpr *RHS = BE->getRHS();
- if (!LHS)
- return 0;
-
- return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext());
- }
- }
-
- assert(0 && "Invalid expression kind!");
- return 0;
-}
-
/// \brief Given a mnemonic, split out possible predication code and carry
/// setting letters to form a canonical mnemonic and flags.
//
// FIXME: Would be nice to autogen this.
-static StringRef SplitMnemonic(StringRef Mnemonic,
- unsigned &PredicationCode,
- bool &CarrySetting,
- unsigned &ProcessorIMod) {
+// FIXME: This is a bit of a maze of special cases.
+StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
+ unsigned &PredicationCode,
+ bool &CarrySetting,
+ unsigned &ProcessorIMod,
+ StringRef &ITMask) {
PredicationCode = ARMCC::AL;
CarrySetting = false;
ProcessorIMod = 0;
@@ -1935,23 +3517,22 @@ static StringRef SplitMnemonic(StringRef Mnemonic,
// Ignore some mnemonics we know aren't predicated forms.
//
// FIXME: Would be nice to autogen this.
- if (Mnemonic == "teq" || Mnemonic == "vceq" ||
- Mnemonic == "movs" ||
- Mnemonic == "svc" ||
- (Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
- Mnemonic == "vmls" || Mnemonic == "vnmls") ||
- Mnemonic == "vacge" || Mnemonic == "vcge" ||
- Mnemonic == "vclt" ||
- Mnemonic == "vacgt" || Mnemonic == "vcgt" ||
- Mnemonic == "vcle" ||
- (Mnemonic == "smlal" || Mnemonic == "umaal" || Mnemonic == "umlal" ||
- Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" ||
- Mnemonic == "vqdmlal" || Mnemonic == "bics"))
+ if ((Mnemonic == "movs" && isThumb()) ||
+ Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
+ Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
+ Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
+ Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
+ Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
+ Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
+ Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
return Mnemonic;
// First, split out any predication code. Ignore mnemonics we know aren't
// predicated but do have a carry-set and so weren't caught above.
- if (Mnemonic != "adcs") {
+ if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
+ Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
+ Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
+ Mnemonic != "sbcs" && Mnemonic != "rscs") {
unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
.Case("eq", ARMCC::EQ)
.Case("ne", ARMCC::NE)
@@ -1980,11 +3561,12 @@ static StringRef SplitMnemonic(StringRef Mnemonic,
// Next, determine if we have a carry setting bit. We explicitly ignore all
// the instructions we know end in 's'.
if (Mnemonic.endswith("s") &&
- !(Mnemonic == "asrs" || Mnemonic == "cps" || Mnemonic == "mls" ||
- Mnemonic == "movs" || Mnemonic == "mrs" || Mnemonic == "smmls" ||
- Mnemonic == "vabs" || Mnemonic == "vcls" || Mnemonic == "vmls" ||
- Mnemonic == "vmrs" || Mnemonic == "vnmls" || Mnemonic == "vqabs" ||
- Mnemonic == "vrecps" || Mnemonic == "vrsqrts")) {
+ !(Mnemonic == "cps" || Mnemonic == "mls" ||
+ Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
+ Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
+ Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
+ Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
+ (Mnemonic == "movs" && isThumb()))) {
Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
CarrySetting = true;
}
@@ -2004,6 +3586,12 @@ static StringRef SplitMnemonic(StringRef Mnemonic,
}
}
+ // The "it" instruction has the condition mask on the end of the mnemonic.
+ if (Mnemonic.startswith("it")) {
+ ITMask = Mnemonic.slice(2, Mnemonic.size());
+ Mnemonic = Mnemonic.slice(0, 2);
+ }
+
return Mnemonic;
}
@@ -2012,37 +3600,154 @@ static StringRef SplitMnemonic(StringRef Mnemonic,
//
// FIXME: It would be nice to autogen this.
void ARMAsmParser::
-GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
+getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
bool &CanAcceptPredicationCode) {
if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
- Mnemonic == "smull" || Mnemonic == "add" || Mnemonic == "adc" ||
+ Mnemonic == "add" || Mnemonic == "adc" ||
Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
- Mnemonic == "umlal" || Mnemonic == "orr" || Mnemonic == "mvn" ||
+ Mnemonic == "orr" || Mnemonic == "mvn" ||
Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
- Mnemonic == "sbc" || Mnemonic == "mla" || Mnemonic == "umull" ||
- Mnemonic == "eor" || Mnemonic == "smlal" ||
- (Mnemonic == "mov" && !isThumbOne())) {
+ Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
+ (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
+ Mnemonic == "mla" || Mnemonic == "smlal" ||
+ Mnemonic == "umlal" || Mnemonic == "umull"))) {
CanAcceptCarrySet = true;
- } else {
+ } else
CanAcceptCarrySet = false;
- }
if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
- Mnemonic == "dsb" || Mnemonic == "movs" || Mnemonic == "isb" ||
- Mnemonic == "clrex" || Mnemonic.startswith("cps")) {
+ Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
+ (Mnemonic == "clrex" && !isThumb()) ||
+ (Mnemonic == "nop" && isThumbOne()) ||
+ ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
+ Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
+ Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
+ ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
+ !isThumb()) ||
+ Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
CanAcceptPredicationCode = false;
- } else {
+ } else
CanAcceptPredicationCode = true;
- }
- if (isThumb())
+ if (isThumb()) {
if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
CanAcceptPredicationCode = false;
+ }
+}
+
+bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ // FIXME: This is all horribly hacky. We really need a better way to deal
+ // with optional operands like this in the matcher table.
+
+ // The 'mov' mnemonic is special. One variant has a cc_out operand, while
+ // another does not. Specifically, the MOVW instruction does not. So we
+ // special case it here and remove the defaulted (non-setting) cc_out
+ // operand if that's the instruction we're trying to match.
+ //
+ // We do this as post-processing of the explicit operands rather than just
+ // conditionally adding the cc_out in the first place because we need
+ // to check the type of the parsed immediate operand.
+ if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
+ !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
+ static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
+ static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
+ return true;
+
+ // Register-register 'add' for thumb does not have a cc_out operand
+ // when there are only two register operands.
+ if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
+ static_cast<ARMOperand*>(Operands[3])->isReg() &&
+ static_cast<ARMOperand*>(Operands[4])->isReg() &&
+ static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
+ return true;
+ // Register-register 'add' for thumb does not have a cc_out operand
+ // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
+ // have to check the immediate range here since Thumb2 has a variant
+ // that can handle a different range and has a cc_out operand.
+ if (((isThumb() && Mnemonic == "add") ||
+ (isThumbTwo() && Mnemonic == "sub")) &&
+ Operands.size() == 6 &&
+ static_cast<ARMOperand*>(Operands[3])->isReg() &&
+ static_cast<ARMOperand*>(Operands[4])->isReg() &&
+ static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
+ static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
+ (static_cast<ARMOperand*>(Operands[5])->isReg() ||
+ static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
+ return true;
+ // For Thumb2, add/sub immediate does not have a cc_out operand for the
+ // imm0_4095 variant. That's the least-preferred variant when
+ // selecting via the generic "add" mnemonic, so to know that we
+ // should remove the cc_out operand, we have to explicitly check that
+ // it's not one of the other variants. Ugh.
+ if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
+ Operands.size() == 6 &&
+ static_cast<ARMOperand*>(Operands[3])->isReg() &&
+ static_cast<ARMOperand*>(Operands[4])->isReg() &&
+ static_cast<ARMOperand*>(Operands[5])->isImm()) {
+ // Nest conditions rather than one big 'if' statement for readability.
+ //
+ // If either register is a high reg, it's either one of the SP
+ // variants (handled above) or a 32-bit encoding, so we just
+ // check against T3.
+ if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
+ !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
+ static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
+ return false;
+ // If both registers are low, we're in an IT block, and the immediate is
+ // in range, we should use encoding T1 instead, which has a cc_out.
+ if (inITBlock() &&
+ isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
+ isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
+ static_cast<ARMOperand*>(Operands[5])->isImm0_7())
+ return false;
+
+ // Otherwise, we use encoding T4, which does not have a cc_out
+ // operand.
+ return true;
+ }
+
+ // The thumb2 multiply instruction doesn't have a CCOut register, so
+ // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
+ // use the 16-bit encoding or not.
+ if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
+ static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
+ static_cast<ARMOperand*>(Operands[3])->isReg() &&
+ static_cast<ARMOperand*>(Operands[4])->isReg() &&
+ static_cast<ARMOperand*>(Operands[5])->isReg() &&
+ // If the registers aren't low regs, the destination reg isn't the
+ // same as one of the source regs, or the cc_out operand is zero
+ // outside of an IT block, we have to use the 32-bit encoding, so
+ // remove the cc_out operand.
+ (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
+ !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
+ !inITBlock() ||
+ (static_cast<ARMOperand*>(Operands[3])->getReg() !=
+ static_cast<ARMOperand*>(Operands[5])->getReg() &&
+ static_cast<ARMOperand*>(Operands[3])->getReg() !=
+ static_cast<ARMOperand*>(Operands[4])->getReg())))
+ return true;
+
+
+
+ // Register-register 'add/sub' for thumb does not have a cc_out operand
+ // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
+ // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
+ // right, this will result in better diagnostics (which operand is off)
+ // anyway.
+ if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
+ (Operands.size() == 5 || Operands.size() == 6) &&
+ static_cast<ARMOperand*>(Operands[3])->isReg() &&
+ static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
+ static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
+ return true;
+
+ return false;
}
/// Parse an arm instruction mnemonic followed by its operands.
@@ -2050,16 +3755,51 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// Create the leading tokens for the mnemonic, split by '.' characters.
size_t Start = 0, Next = Name.find('.');
- StringRef Head = Name.slice(Start, Next);
+ StringRef Mnemonic = Name.slice(Start, Next);
// Split out the predication code and carry setting flag from the mnemonic.
unsigned PredicationCode;
unsigned ProcessorIMod;
bool CarrySetting;
- Head = SplitMnemonic(Head, PredicationCode, CarrySetting,
- ProcessorIMod);
+ StringRef ITMask;
+ Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
+ ProcessorIMod, ITMask);
+
+ // In Thumb1, only the branch (B) instruction can be predicated.
+ if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
+ Parser.EatToEndOfStatement();
+ return Error(NameLoc, "conditional execution not supported in Thumb1");
+ }
+
+ Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
- Operands.push_back(ARMOperand::CreateToken(Head, NameLoc));
+ // Handle the IT instruction ITMask. Convert it to a bitmask. This
+ // is the mask as it will be for the IT encoding if the conditional
+ // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
+ // where the conditional bit0 is zero, the instruction post-processing
+ // will adjust the mask accordingly.
+ if (Mnemonic == "it") {
+ SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
+ if (ITMask.size() > 3) {
+ Parser.EatToEndOfStatement();
+ return Error(Loc, "too many conditions on IT instruction");
+ }
+ unsigned Mask = 8;
+ for (unsigned i = ITMask.size(); i != 0; --i) {
+ char pos = ITMask[i - 1];
+ if (pos != 't' && pos != 'e') {
+ Parser.EatToEndOfStatement();
+ return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
+ }
+ Mask >>= 1;
+ if (ITMask[i - 1] == 't')
+ Mask |= 8;
+ }
+ Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
+ }
+
+ // FIXME: This is all a pretty gross hack. We should automatically handle
+ // optional operands like this via tblgen.
// Next, add the CCOut and ConditionCode operands, if needed.
//
@@ -2069,34 +3809,36 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
// the matcher deal with finding the right instruction or generating an
// appropriate error.
bool CanAcceptCarrySet, CanAcceptPredicationCode;
- GetMnemonicAcceptInfo(Head, CanAcceptCarrySet, CanAcceptPredicationCode);
+ getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
// If we had a carry-set on an instruction that can't do that, issue an
// error.
if (!CanAcceptCarrySet && CarrySetting) {
Parser.EatToEndOfStatement();
- return Error(NameLoc, "instruction '" + Head +
+ return Error(NameLoc, "instruction '" + Mnemonic +
"' can not set flags, but 's' suffix specified");
}
+ // If we had a predication code on an instruction that can't do that, issue an
+ // error.
+ if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
+ Parser.EatToEndOfStatement();
+ return Error(NameLoc, "instruction '" + Mnemonic +
+ "' is not predicable, but condition code specified");
+ }
// Add the carry setting operand, if necessary.
- //
- // FIXME: It would be awesome if we could somehow invent a location such that
- // match errors on this operand would print a nice diagnostic about how the
- // 's' character in the mnemonic resulted in a CCOut operand.
- if (CanAcceptCarrySet)
+ if (CanAcceptCarrySet) {
+ SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
- NameLoc));
+ Loc));
+ }
// Add the predication code operand, if necessary.
if (CanAcceptPredicationCode) {
+ SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
+ CarrySetting);
Operands.push_back(ARMOperand::CreateCondCode(
- ARMCC::CondCodes(PredicationCode), NameLoc));
- } else {
- // This mnemonic can't ever accept a predication code, but the user wrote
- // one (or misspelled another mnemonic).
-
- // FIXME: Issue a nice error.
+ ARMCC::CondCodes(PredicationCode), Loc));
}
// Add the processor imod operand, if necessary.
@@ -2104,11 +3846,6 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
Operands.push_back(ARMOperand::CreateImm(
MCConstantExpr::Create(ProcessorIMod, getContext()),
NameLoc, NameLoc));
- } else {
- // This mnemonic can't ever accept a imod, but the user wrote
- // one (or misspelled another mnemonic).
-
- // FIXME: Issue a nice error.
}
// Add the remaining tokens in the mnemonic.
@@ -2117,13 +3854,19 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
Next = Name.find('.', Start + 1);
StringRef ExtraToken = Name.slice(Start, Next);
- Operands.push_back(ARMOperand::CreateToken(ExtraToken, NameLoc));
+ // For now, we're only parsing Thumb1 (for the most part), so
+ // just ignore ".n" qualifiers. We'll use them to restrict
+ // matching when we do Thumb2.
+ if (ExtraToken != ".n") {
+ SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
+ Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
+ }
}
// Read the remaining operands.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
// Read the first operand.
- if (ParseOperand(Operands, Head)) {
+ if (parseOperand(Operands, Mnemonic)) {
Parser.EatToEndOfStatement();
return true;
}
@@ -2132,7 +3875,7 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
Parser.Lex(); // Eat the comma.
// Parse and remember the operand.
- if (ParseOperand(Operands, Head)) {
+ if (parseOperand(Operands, Mnemonic)) {
Parser.EatToEndOfStatement();
return true;
}
@@ -2140,75 +3883,548 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
}
if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ SMLoc Loc = getLexer().getLoc();
Parser.EatToEndOfStatement();
- return TokError("unexpected token in argument list");
+ return Error(Loc, "unexpected token in argument list");
}
Parser.Lex(); // Consume the EndOfStatement
+
+ // Some instructions, mostly Thumb, have forms for the same mnemonic that
+ // do and don't have a cc_out optional-def operand. With some spot-checks
+ // of the operand list, we can figure out which variant we're trying to
+ // parse and adjust accordingly before actually matching. We shouldn't ever
+ // try to remove a cc_out operand that was explicitly set on the the
+ // mnemonic, of course (CarrySetting == true). Reason number #317 the
+ // table driven matcher doesn't fit well with the ARM instruction set.
+ if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
+ ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
+ Operands.erase(Operands.begin() + 1);
+ delete Op;
+ }
+
+ // ARM mode 'blx' need special handling, as the register operand version
+ // is predicable, but the label operand version is not. So, we can't rely
+ // on the Mnemonic based checking to correctly figure out when to put
+ // a k_CondCode operand in the list. If we're trying to match the label
+ // version, remove the k_CondCode operand here.
+ if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
+ static_cast<ARMOperand*>(Operands[2])->isImm()) {
+ ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
+ Operands.erase(Operands.begin() + 1);
+ delete Op;
+ }
+
+ // The vector-compare-to-zero instructions have a literal token "#0" at
+ // the end that comes to here as an immediate operand. Convert it to a
+ // token to play nicely with the matcher.
+ if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
+ Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
+ static_cast<ARMOperand*>(Operands[5])->isImm()) {
+ ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
+ if (CE && CE->getValue() == 0) {
+ Operands.erase(Operands.begin() + 5);
+ Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
+ delete Op;
+ }
+ }
+ // VCMP{E} does the same thing, but with a different operand count.
+ if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
+ static_cast<ARMOperand*>(Operands[4])->isImm()) {
+ ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
+ if (CE && CE->getValue() == 0) {
+ Operands.erase(Operands.begin() + 4);
+ Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
+ delete Op;
+ }
+ }
+ // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
+ // end. Convert it to a token here.
+ if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
+ static_cast<ARMOperand*>(Operands[5])->isImm()) {
+ ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
+ if (CE && CE->getValue() == 0) {
+ Operands.erase(Operands.begin() + 5);
+ Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
+ delete Op;
+ }
+ }
+
+ return false;
+}
+
+// Validate context-sensitive operand constraints.
+
+// return 'true' if register list contains non-low GPR registers,
+// 'false' otherwise. If Reg is in the register list or is HiReg, set
+// 'containsReg' to true.
+static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
+ unsigned HiReg, bool &containsReg) {
+ containsReg = false;
+ for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
+ unsigned OpReg = Inst.getOperand(i).getReg();
+ if (OpReg == Reg)
+ containsReg = true;
+ // Anything other than a low register isn't legal here.
+ if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
+ return true;
+ }
+ return false;
+}
+
+// Check if the specified regisgter is in the register list of the inst,
+// starting at the indicated operand number.
+static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
+ for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
+ unsigned OpReg = Inst.getOperand(i).getReg();
+ if (OpReg == Reg)
+ return true;
+ }
+ return false;
+}
+
+// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
+// the ARMInsts array) instead. Getting that here requires awkward
+// API changes, though. Better way?
+namespace llvm {
+extern MCInstrDesc ARMInsts[];
+}
+static MCInstrDesc &getInstDesc(unsigned Opcode) {
+ return ARMInsts[Opcode];
+}
+
+// FIXME: We would really like to be able to tablegen'erate this.
+bool ARMAsmParser::
+validateInstruction(MCInst &Inst,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
+ SMLoc Loc = Operands[0]->getStartLoc();
+ // Check the IT block state first.
+ // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
+ // being allowed in IT blocks, but not being predicable. It just always
+ // executes.
+ if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
+ unsigned bit = 1;
+ if (ITState.FirstCond)
+ ITState.FirstCond = false;
+ else
+ bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
+ // The instruction must be predicable.
+ if (!MCID.isPredicable())
+ return Error(Loc, "instructions in IT block must be predicable");
+ unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
+ unsigned ITCond = bit ? ITState.Cond :
+ ARMCC::getOppositeCondition(ITState.Cond);
+ if (Cond != ITCond) {
+ // Find the condition code Operand to get its SMLoc information.
+ SMLoc CondLoc;
+ for (unsigned i = 1; i < Operands.size(); ++i)
+ if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
+ CondLoc = Operands[i]->getStartLoc();
+ return Error(CondLoc, "incorrect condition in IT block; got '" +
+ StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
+ "', but expected '" +
+ ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
+ }
+ // Check for non-'al' condition codes outside of the IT block.
+ } else if (isThumbTwo() && MCID.isPredicable() &&
+ Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
+ ARMCC::AL && Inst.getOpcode() != ARM::tB &&
+ Inst.getOpcode() != ARM::t2B)
+ return Error(Loc, "predicated instructions must be in IT block");
+
+ switch (Inst.getOpcode()) {
+ case ARM::LDRD:
+ case ARM::LDRD_PRE:
+ case ARM::LDRD_POST:
+ case ARM::LDREXD: {
+ // Rt2 must be Rt + 1.
+ unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
+ unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
+ if (Rt2 != Rt + 1)
+ return Error(Operands[3]->getStartLoc(),
+ "destination operands must be sequential");
+ return false;
+ }
+ case ARM::STRD: {
+ // Rt2 must be Rt + 1.
+ unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
+ unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
+ if (Rt2 != Rt + 1)
+ return Error(Operands[3]->getStartLoc(),
+ "source operands must be sequential");
+ return false;
+ }
+ case ARM::STRD_PRE:
+ case ARM::STRD_POST:
+ case ARM::STREXD: {
+ // Rt2 must be Rt + 1.
+ unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
+ unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
+ if (Rt2 != Rt + 1)
+ return Error(Operands[3]->getStartLoc(),
+ "source operands must be sequential");
+ return false;
+ }
+ case ARM::SBFX:
+ case ARM::UBFX: {
+ // width must be in range [1, 32-lsb]
+ unsigned lsb = Inst.getOperand(2).getImm();
+ unsigned widthm1 = Inst.getOperand(3).getImm();
+ if (widthm1 >= 32 - lsb)
+ return Error(Operands[5]->getStartLoc(),
+ "bitfield width must be in range [1,32-lsb]");
+ return false;
+ }
+ case ARM::tLDMIA: {
+ // If we're parsing Thumb2, the .w variant is available and handles
+ // most cases that are normally illegal for a Thumb1 LDM
+ // instruction. We'll make the transformation in processInstruction()
+ // if necessary.
+ //
+ // Thumb LDM instructions are writeback iff the base register is not
+ // in the register list.
+ unsigned Rn = Inst.getOperand(0).getReg();
+ bool hasWritebackToken =
+ (static_cast<ARMOperand*>(Operands[3])->isToken() &&
+ static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
+ bool listContainsBase;
+ if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
+ return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
+ "registers must be in range r0-r7");
+ // If we should have writeback, then there should be a '!' token.
+ if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
+ return Error(Operands[2]->getStartLoc(),
+ "writeback operator '!' expected");
+ // If we should not have writeback, there must not be a '!'. This is
+ // true even for the 32-bit wide encodings.
+ if (listContainsBase && hasWritebackToken)
+ return Error(Operands[3]->getStartLoc(),
+ "writeback operator '!' not allowed when base register "
+ "in register list");
+
+ break;
+ }
+ case ARM::t2LDMIA_UPD: {
+ if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
+ return Error(Operands[4]->getStartLoc(),
+ "writeback operator '!' not allowed when base register "
+ "in register list");
+ break;
+ }
+ case ARM::tPOP: {
+ bool listContainsBase;
+ if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
+ return Error(Operands[2]->getStartLoc(),
+ "registers must be in range r0-r7 or pc");
+ break;
+ }
+ case ARM::tPUSH: {
+ bool listContainsBase;
+ if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
+ return Error(Operands[2]->getStartLoc(),
+ "registers must be in range r0-r7 or lr");
+ break;
+ }
+ case ARM::tSTMIA_UPD: {
+ bool listContainsBase;
+ if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
+ return Error(Operands[4]->getStartLoc(),
+ "registers must be in range r0-r7");
+ break;
+ }
+ }
+
return false;
}
+void ARMAsmParser::
+processInstruction(MCInst &Inst,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ switch (Inst.getOpcode()) {
+ case ARM::LDMIA_UPD:
+ // If this is a load of a single register via a 'pop', then we should use
+ // a post-indexed LDR instruction instead, per the ARM ARM.
+ if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
+ Inst.getNumOperands() == 5) {
+ MCInst TmpInst;
+ TmpInst.setOpcode(ARM::LDR_POST_IMM);
+ TmpInst.addOperand(Inst.getOperand(4)); // Rt
+ TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
+ TmpInst.addOperand(Inst.getOperand(1)); // Rn
+ TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
+ TmpInst.addOperand(MCOperand::CreateImm(4));
+ TmpInst.addOperand(Inst.getOperand(2)); // CondCode
+ TmpInst.addOperand(Inst.getOperand(3));
+ Inst = TmpInst;
+ }
+ break;
+ case ARM::STMDB_UPD:
+ // If this is a store of a single register via a 'push', then we should use
+ // a pre-indexed STR instruction instead, per the ARM ARM.
+ if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
+ Inst.getNumOperands() == 5) {
+ MCInst TmpInst;
+ TmpInst.setOpcode(ARM::STR_PRE_IMM);
+ TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
+ TmpInst.addOperand(Inst.getOperand(4)); // Rt
+ TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
+ TmpInst.addOperand(MCOperand::CreateImm(-4));
+ TmpInst.addOperand(Inst.getOperand(2)); // CondCode
+ TmpInst.addOperand(Inst.getOperand(3));
+ Inst = TmpInst;
+ }
+ break;
+ case ARM::tADDi8:
+ // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
+ // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
+ // to encoding T2 if <Rd> is specified and encoding T2 is preferred
+ // to encoding T1 if <Rd> is omitted."
+ if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
+ Inst.setOpcode(ARM::tADDi3);
+ break;
+ case ARM::tSUBi8:
+ // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
+ // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
+ // to encoding T2 if <Rd> is specified and encoding T2 is preferred
+ // to encoding T1 if <Rd> is omitted."
+ if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
+ Inst.setOpcode(ARM::tSUBi3);
+ break;
+ case ARM::tB:
+ // A Thumb conditional branch outside of an IT block is a tBcc.
+ if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
+ Inst.setOpcode(ARM::tBcc);
+ break;
+ case ARM::t2B:
+ // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
+ if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
+ Inst.setOpcode(ARM::t2Bcc);
+ break;
+ case ARM::t2Bcc:
+ // If the conditional is AL or we're in an IT block, we really want t2B.
+ if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
+ Inst.setOpcode(ARM::t2B);
+ break;
+ case ARM::tBcc:
+ // If the conditional is AL, we really want tB.
+ if (Inst.getOperand(1).getImm() == ARMCC::AL)
+ Inst.setOpcode(ARM::tB);
+ break;
+ case ARM::tLDMIA: {
+ // If the register list contains any high registers, or if the writeback
+ // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
+ // instead if we're in Thumb2. Otherwise, this should have generated
+ // an error in validateInstruction().
+ unsigned Rn = Inst.getOperand(0).getReg();
+ bool hasWritebackToken =
+ (static_cast<ARMOperand*>(Operands[3])->isToken() &&
+ static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
+ bool listContainsBase;
+ if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
+ (!listContainsBase && !hasWritebackToken) ||
+ (listContainsBase && hasWritebackToken)) {
+ // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
+ assert (isThumbTwo());
+ Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
+ // If we're switching to the updating version, we need to insert
+ // the writeback tied operand.
+ if (hasWritebackToken)
+ Inst.insert(Inst.begin(),
+ MCOperand::CreateReg(Inst.getOperand(0).getReg()));
+ }
+ break;
+ }
+ case ARM::tSTMIA_UPD: {
+ // If the register list contains any high registers, we need to use
+ // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
+ // should have generated an error in validateInstruction().
+ unsigned Rn = Inst.getOperand(0).getReg();
+ bool listContainsBase;
+ if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
+ // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
+ assert (isThumbTwo());
+ Inst.setOpcode(ARM::t2STMIA_UPD);
+ }
+ break;
+ }
+ case ARM::t2MOVi: {
+ // If we can use the 16-bit encoding and the user didn't explicitly
+ // request the 32-bit variant, transform it here.
+ if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
+ Inst.getOperand(1).getImm() <= 255 &&
+ ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
+ Inst.getOperand(4).getReg() == ARM::CPSR) ||
+ (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
+ (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
+ static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
+ // The operands aren't in the same order for tMOVi8...
+ MCInst TmpInst;
+ TmpInst.setOpcode(ARM::tMOVi8);
+ TmpInst.addOperand(Inst.getOperand(0));
+ TmpInst.addOperand(Inst.getOperand(4));
+ TmpInst.addOperand(Inst.getOperand(1));
+ TmpInst.addOperand(Inst.getOperand(2));
+ TmpInst.addOperand(Inst.getOperand(3));
+ Inst = TmpInst;
+ }
+ break;
+ }
+ case ARM::t2MOVr: {
+ // If we can use the 16-bit encoding and the user didn't explicitly
+ // request the 32-bit variant, transform it here.
+ if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
+ isARMLowRegister(Inst.getOperand(1).getReg()) &&
+ Inst.getOperand(2).getImm() == ARMCC::AL &&
+ Inst.getOperand(4).getReg() == ARM::CPSR &&
+ (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
+ static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
+ // The operands aren't the same for tMOV[S]r... (no cc_out)
+ MCInst TmpInst;
+ TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
+ TmpInst.addOperand(Inst.getOperand(0));
+ TmpInst.addOperand(Inst.getOperand(1));
+ TmpInst.addOperand(Inst.getOperand(2));
+ TmpInst.addOperand(Inst.getOperand(3));
+ Inst = TmpInst;
+ }
+ break;
+ }
+ case ARM::t2SXTH:
+ case ARM::t2SXTB:
+ case ARM::t2UXTH:
+ case ARM::t2UXTB: {
+ // If we can use the 16-bit encoding and the user didn't explicitly
+ // request the 32-bit variant, transform it here.
+ if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
+ isARMLowRegister(Inst.getOperand(1).getReg()) &&
+ Inst.getOperand(2).getImm() == 0 &&
+ (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
+ static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
+ unsigned NewOpc;
+ switch (Inst.getOpcode()) {
+ default: llvm_unreachable("Illegal opcode!");
+ case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
+ case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
+ case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
+ case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
+ }
+ // The operands aren't the same for thumb1 (no rotate operand).
+ MCInst TmpInst;
+ TmpInst.setOpcode(NewOpc);
+ TmpInst.addOperand(Inst.getOperand(0));
+ TmpInst.addOperand(Inst.getOperand(1));
+ TmpInst.addOperand(Inst.getOperand(3));
+ TmpInst.addOperand(Inst.getOperand(4));
+ Inst = TmpInst;
+ }
+ break;
+ }
+ case ARM::t2IT: {
+ // The mask bits for all but the first condition are represented as
+ // the low bit of the condition code value implies 't'. We currently
+ // always have 1 implies 't', so XOR toggle the bits if the low bit
+ // of the condition code is zero. The encoding also expects the low
+ // bit of the condition to be encoded as bit 4 of the mask operand,
+ // so mask that in if needed
+ MCOperand &MO = Inst.getOperand(1);
+ unsigned Mask = MO.getImm();
+ unsigned OrigMask = Mask;
+ unsigned TZ = CountTrailingZeros_32(Mask);
+ if ((Inst.getOperand(0).getImm() & 1) == 0) {
+ assert(Mask && TZ <= 3 && "illegal IT mask value!");
+ for (unsigned i = 3; i != TZ; --i)
+ Mask ^= 1 << i;
+ } else
+ Mask |= 0x10;
+ MO.setImm(Mask);
+
+ // Set up the IT block state according to the IT instruction we just
+ // matched.
+ assert(!inITBlock() && "nested IT blocks?!");
+ ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
+ ITState.Mask = OrigMask; // Use the original mask, not the updated one.
+ ITState.CurPosition = 0;
+ ITState.FirstCond = true;
+ break;
+ }
+ }
+}
+
+unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
+ // 16-bit thumb arithmetic instructions either require or preclude the 'S'
+ // suffix depending on whether they're in an IT block or not.
+ unsigned Opc = Inst.getOpcode();
+ MCInstrDesc &MCID = getInstDesc(Opc);
+ if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
+ assert(MCID.hasOptionalDef() &&
+ "optionally flag setting instruction missing optional def operand");
+ assert(MCID.NumOperands == Inst.getNumOperands() &&
+ "operand count mismatch!");
+ // Find the optional-def operand (cc_out).
+ unsigned OpNo;
+ for (OpNo = 0;
+ !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
+ ++OpNo)
+ ;
+ // If we're parsing Thumb1, reject it completely.
+ if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
+ return Match_MnemonicFail;
+ // If we're parsing Thumb2, which form is legal depends on whether we're
+ // in an IT block.
+ if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
+ !inITBlock())
+ return Match_RequiresITBlock;
+ if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
+ inITBlock())
+ return Match_RequiresNotITBlock;
+ }
+ // Some high-register supporting Thumb1 encodings only allow both registers
+ // to be from r0-r7 when in Thumb2.
+ else if (Opc == ARM::tADDhirr && isThumbOne() &&
+ isARMLowRegister(Inst.getOperand(1).getReg()) &&
+ isARMLowRegister(Inst.getOperand(2).getReg()))
+ return Match_RequiresThumb2;
+ // Others only require ARMv6 or later.
+ else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
+ isARMLowRegister(Inst.getOperand(0).getReg()) &&
+ isARMLowRegister(Inst.getOperand(1).getReg()))
+ return Match_RequiresV6;
+ return Match_Success;
+}
+
bool ARMAsmParser::
MatchAndEmitInstruction(SMLoc IDLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out) {
MCInst Inst;
unsigned ErrorInfo;
- MatchResultTy MatchResult, MatchResult2;
+ unsigned MatchResult;
MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
- if (MatchResult != Match_Success) {
- // If we get a Match_InvalidOperand it might be some arithmetic instruction
- // that does not update the condition codes. So try adding a CCOut operand
- // with a value of reg0.
- if (MatchResult == Match_InvalidOperand) {
- Operands.insert(Operands.begin() + 1,
- ARMOperand::CreateCCOut(0,
- ((ARMOperand*)Operands[0])->getStartLoc()));
- MatchResult2 = MatchInstructionImpl(Operands, Inst, ErrorInfo);
- if (MatchResult2 == Match_Success)
- MatchResult = Match_Success;
- else {
- ARMOperand *CCOut = ((ARMOperand*)Operands[1]);
- Operands.erase(Operands.begin() + 1);
- delete CCOut;
- }
- }
- // If we get a Match_MnemonicFail it might be some arithmetic instruction
- // that updates the condition codes if it ends in 's'. So see if the
- // mnemonic ends in 's' and if so try removing the 's' and adding a CCOut
- // operand with a value of CPSR.
- else if (MatchResult == Match_MnemonicFail) {
- // Get the instruction mnemonic, which is the first token.
- StringRef Mnemonic = ((ARMOperand*)Operands[0])->getToken();
- if (Mnemonic.substr(Mnemonic.size()-1) == "s") {
- // removed the 's' from the mnemonic for matching.
- StringRef MnemonicNoS = Mnemonic.slice(0, Mnemonic.size() - 1);
- SMLoc NameLoc = ((ARMOperand*)Operands[0])->getStartLoc();
- ARMOperand *OldMnemonic = ((ARMOperand*)Operands[0]);
- Operands.erase(Operands.begin());
- delete OldMnemonic;
- Operands.insert(Operands.begin(),
- ARMOperand::CreateToken(MnemonicNoS, NameLoc));
- Operands.insert(Operands.begin() + 1,
- ARMOperand::CreateCCOut(ARM::CPSR, NameLoc));
- MatchResult2 = MatchInstructionImpl(Operands, Inst, ErrorInfo);
- if (MatchResult2 == Match_Success)
- MatchResult = Match_Success;
- else {
- ARMOperand *OldMnemonic = ((ARMOperand*)Operands[0]);
- Operands.erase(Operands.begin());
- delete OldMnemonic;
- Operands.insert(Operands.begin(),
- ARMOperand::CreateToken(Mnemonic, NameLoc));
- ARMOperand *CCOut = ((ARMOperand*)Operands[1]);
- Operands.erase(Operands.begin() + 1);
- delete CCOut;
- }
- }
- }
- }
switch (MatchResult) {
+ default: break;
case Match_Success:
+ // Context sensitive operand constraints aren't handled by the matcher,
+ // so check them here.
+ if (validateInstruction(Inst, Operands)) {
+ // Still progress the IT block, otherwise one wrong condition causes
+ // nasty cascading errors.
+ forwardITPosition();
+ return true;
+ }
+
+ // Some instructions need post-processing to, for example, tweak which
+ // encoding is selected.
+ processInstruction(Inst, Operands);
+
+ // Only move forward at the very end so that everything in validate
+ // and process gets a consistent answer about whether we're in an IT
+ // block.
+ forwardITPosition();
+
Out.EmitInstruction(Inst);
return false;
case Match_MissingFeature:
@@ -2227,34 +4443,43 @@ MatchAndEmitInstruction(SMLoc IDLoc,
return Error(ErrorLoc, "invalid operand for instruction");
}
case Match_MnemonicFail:
- return Error(IDLoc, "unrecognized instruction mnemonic");
+ return Error(IDLoc, "invalid instruction");
case Match_ConversionFail:
- return Error(IDLoc, "unable to convert operands to instruction");
+ // The converter function will have already emited a diagnostic.
+ return true;
+ case Match_RequiresNotITBlock:
+ return Error(IDLoc, "flag setting instruction only valid outside IT block");
+ case Match_RequiresITBlock:
+ return Error(IDLoc, "instruction only valid inside IT block");
+ case Match_RequiresV6:
+ return Error(IDLoc, "instruction variant requires ARMv6 or later");
+ case Match_RequiresThumb2:
+ return Error(IDLoc, "instruction variant requires Thumb2");
}
llvm_unreachable("Implement any new match types added!");
return true;
}
-/// ParseDirective parses the arm specific directives
+/// parseDirective parses the arm specific directives
bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getIdentifier();
if (IDVal == ".word")
- return ParseDirectiveWord(4, DirectiveID.getLoc());
+ return parseDirectiveWord(4, DirectiveID.getLoc());
else if (IDVal == ".thumb")
- return ParseDirectiveThumb(DirectiveID.getLoc());
+ return parseDirectiveThumb(DirectiveID.getLoc());
else if (IDVal == ".thumb_func")
- return ParseDirectiveThumbFunc(DirectiveID.getLoc());
+ return parseDirectiveThumbFunc(DirectiveID.getLoc());
else if (IDVal == ".code")
- return ParseDirectiveCode(DirectiveID.getLoc());
+ return parseDirectiveCode(DirectiveID.getLoc());
else if (IDVal == ".syntax")
- return ParseDirectiveSyntax(DirectiveID.getLoc());
+ return parseDirectiveSyntax(DirectiveID.getLoc());
return true;
}
-/// ParseDirectiveWord
+/// parseDirectiveWord
/// ::= .word [ expression (, expression)* ]
-bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
+bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
if (getLexer().isNot(AsmToken::EndOfStatement)) {
for (;;) {
const MCExpr *Value;
@@ -2277,9 +4502,9 @@ bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
return false;
}
-/// ParseDirectiveThumb
+/// parseDirectiveThumb
/// ::= .thumb
-bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
+bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(L, "unexpected token in directive");
Parser.Lex();
@@ -2290,9 +4515,9 @@ bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
return false;
}
-/// ParseDirectiveThumbFunc
+/// parseDirectiveThumbFunc
/// ::= .thumbfunc symbol_name
-bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
+bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
bool isMachO = MAI.hasSubsectionsViaSymbols();
StringRef Name;
@@ -2322,9 +4547,9 @@ bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
return false;
}
-/// ParseDirectiveSyntax
+/// parseDirectiveSyntax
/// ::= .syntax unified | divided
-bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
+bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Identifier))
return Error(L, "unexpected token in .syntax directive");
@@ -2345,9 +4570,9 @@ bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
return false;
}
-/// ParseDirectiveCode
+/// parseDirectiveCode
/// ::= .code 16 | 32
-bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
+bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Integer))
return Error(L, "unexpected token in .code directive");
@@ -2380,8 +4605,8 @@ extern "C" void LLVMInitializeARMAsmLexer();
/// Force static initialization.
extern "C" void LLVMInitializeARMAsmParser() {
- RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
- RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
+ RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
+ RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
LLVMInitializeARMAsmLexer();
}
diff --git a/lib/Target/ARM/AsmParser/CMakeLists.txt b/lib/Target/ARM/AsmParser/CMakeLists.txt
index 9ba7c01..3f5ad39 100644
--- a/lib/Target/ARM/AsmParser/CMakeLists.txt
+++ b/lib/Target/ARM/AsmParser/CMakeLists.txt
@@ -5,3 +5,12 @@ add_llvm_library(LLVMARMAsmParser
ARMAsmParser.cpp
)
+add_dependencies(LLVMARMAsmParser ARMCommonTableGen)
+
+add_llvm_library_dependencies(LLVMARMAsmParser
+ LLVMARMDesc
+ LLVMARMInfo
+ LLVMMC
+ LLVMMCParser
+ LLVMSupport
+ )
diff --git a/lib/Target/ARM/CMakeLists.txt b/lib/Target/ARM/CMakeLists.txt
index 21608d0..f045e83 100644
--- a/lib/Target/ARM/CMakeLists.txt
+++ b/lib/Target/ARM/CMakeLists.txt
@@ -1,21 +1,21 @@
set(LLVM_TARGET_DEFINITIONS ARM.td)
-tablegen(ARMGenRegisterInfo.inc -gen-register-info)
-tablegen(ARMGenInstrInfo.inc -gen-instr-info)
-tablegen(ARMGenCodeEmitter.inc -gen-emitter)
-tablegen(ARMGenMCCodeEmitter.inc -gen-emitter -mc-emitter)
-tablegen(ARMGenMCPseudoLowering.inc -gen-pseudo-lowering)
-tablegen(ARMGenAsmWriter.inc -gen-asm-writer)
-tablegen(ARMGenAsmMatcher.inc -gen-asm-matcher)
-tablegen(ARMGenDAGISel.inc -gen-dag-isel)
-tablegen(ARMGenFastISel.inc -gen-fast-isel)
-tablegen(ARMGenCallingConv.inc -gen-callingconv)
-tablegen(ARMGenSubtargetInfo.inc -gen-subtarget)
-tablegen(ARMGenEDInfo.inc -gen-enhanced-disassembly-info)
-tablegen(ARMGenDecoderTables.inc -gen-arm-decoder)
+llvm_tablegen(ARMGenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(ARMGenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(ARMGenCodeEmitter.inc -gen-emitter)
+llvm_tablegen(ARMGenMCCodeEmitter.inc -gen-emitter -mc-emitter)
+llvm_tablegen(ARMGenMCPseudoLowering.inc -gen-pseudo-lowering)
+llvm_tablegen(ARMGenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(ARMGenAsmMatcher.inc -gen-asm-matcher)
+llvm_tablegen(ARMGenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(ARMGenFastISel.inc -gen-fast-isel)
+llvm_tablegen(ARMGenCallingConv.inc -gen-callingconv)
+llvm_tablegen(ARMGenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(ARMGenEDInfo.inc -gen-enhanced-disassembly-info)
+llvm_tablegen(ARMGenDisassemblerTables.inc -gen-disassembler)
+add_public_tablegen_target(ARMCommonTableGen)
add_llvm_target(ARMCodeGen
- ARMAsmBackend.cpp
ARMAsmPrinter.cpp
ARMBaseInstrInfo.cpp
ARMBaseRegisterInfo.cpp
@@ -32,9 +32,6 @@ add_llvm_target(ARMCodeGen
ARMISelLowering.cpp
ARMInstrInfo.cpp
ARMJITInfo.cpp
- ARMMachObjectWriter.cpp
- ARMMCCodeEmitter.cpp
- ARMMCExpr.cpp
ARMLoadStoreOptimizer.cpp
ARMMCInstLower.cpp
ARMRegisterInfo.cpp
@@ -43,9 +40,8 @@ add_llvm_target(ARMCodeGen
ARMTargetMachine.cpp
ARMTargetObjectFile.cpp
MLxExpansionPass.cpp
- NEONMoveFix.cpp
- Thumb1InstrInfo.cpp
Thumb1FrameLowering.cpp
+ Thumb1InstrInfo.cpp
Thumb1RegisterInfo.cpp
Thumb2ITBlockPass.cpp
Thumb2InstrInfo.cpp
@@ -53,6 +49,20 @@ add_llvm_target(ARMCodeGen
Thumb2SizeReduction.cpp
)
+add_llvm_library_dependencies(LLVMARMCodeGen
+ LLVMARMAsmPrinter
+ LLVMARMDesc
+ LLVMARMInfo
+ LLVMAnalysis
+ LLVMAsmPrinter
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMTarget
+ )
+
# workaround for hanging compilation on MSVC10
if( MSVC_VERSION EQUAL 1600 )
set_property(
diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index bdce2c4..8f2f813 100644
--- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -6,584 +6,4077 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file is part of the ARM Disassembler.
-// It contains code to implement the public interfaces of ARMDisassembler and
-// ThumbDisassembler, both of which are instances of MCDisassembler.
-//
-//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "arm-disassembler"
-#include "ARMDisassembler.h"
-#include "ARMDisassemblerCore.h"
-
-#include "llvm/ADT/OwningPtr.h"
+#include "ARM.h"
+#include "ARMRegisterInfo.h"
+#include "ARMSubtarget.h"
+#include "MCTargetDesc/ARMAddressingModes.h"
+#include "MCTargetDesc/ARMMCExpr.h"
+#include "MCTargetDesc/ARMBaseInfo.h"
#include "llvm/MC/EDInstInfo.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
-//#define DEBUG(X) do { X; } while (0)
-
-/// ARMGenDecoderTables.inc - ARMDecoderTables.inc is tblgen'ed from
-/// ARMDecoderEmitter.cpp TableGen backend. It contains:
-///
-/// o Mappings from opcode to ARM/Thumb instruction format
-///
-/// o static uint16_t decodeInstruction(uint32_t insn) - the decoding function
-/// for an ARM instruction.
-///
-/// o static uint16_t decodeThumbInstruction(field_t insn) - the decoding
-/// function for a Thumb instruction.
-///
-#include "ARMGenDecoderTables.inc"
+using namespace llvm;
+
+typedef MCDisassembler::DecodeStatus DecodeStatus;
+namespace {
+/// ARMDisassembler - ARM disassembler for all ARM platforms.
+class ARMDisassembler : public MCDisassembler {
+public:
+ /// Constructor - Initializes the disassembler.
+ ///
+ ARMDisassembler(const MCSubtargetInfo &STI) :
+ MCDisassembler(STI) {
+ }
+
+ ~ARMDisassembler() {
+ }
+
+ /// getInstruction - See MCDisassembler.
+ DecodeStatus getInstruction(MCInst &instr,
+ uint64_t &size,
+ const MemoryObject &region,
+ uint64_t address,
+ raw_ostream &vStream,
+ raw_ostream &cStream) const;
+
+ /// getEDInfo - See MCDisassembler.
+ EDInstInfo *getEDInfo() const;
+private:
+};
+
+/// ThumbDisassembler - Thumb disassembler for all Thumb platforms.
+class ThumbDisassembler : public MCDisassembler {
+public:
+ /// Constructor - Initializes the disassembler.
+ ///
+ ThumbDisassembler(const MCSubtargetInfo &STI) :
+ MCDisassembler(STI) {
+ }
+
+ ~ThumbDisassembler() {
+ }
+
+ /// getInstruction - See MCDisassembler.
+ DecodeStatus getInstruction(MCInst &instr,
+ uint64_t &size,
+ const MemoryObject &region,
+ uint64_t address,
+ raw_ostream &vStream,
+ raw_ostream &cStream) const;
+
+ /// getEDInfo - See MCDisassembler.
+ EDInstInfo *getEDInfo() const;
+private:
+ mutable std::vector<unsigned> ITBlock;
+ DecodeStatus AddThumbPredicate(MCInst&) const;
+ void UpdateThumbVFPPredicate(MCInst&) const;
+};
+}
+
+static bool Check(DecodeStatus &Out, DecodeStatus In) {
+ switch (In) {
+ case MCDisassembler::Success:
+ // Out stays the same.
+ return true;
+ case MCDisassembler::SoftFail:
+ Out = In;
+ return true;
+ case MCDisassembler::Fail:
+ Out = In;
+ return false;
+ }
+ return false;
+}
+
+
+// Forward declare these because the autogenerated code will reference them.
+// Definitions are further down.
+static DecodeStatus DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeGPRnopcRegisterClass(llvm::MCInst &Inst,
+ unsigned RegNo, uint64_t Address,
+ const void *Decoder);
+static DecodeStatus DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodetcGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecoderGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeSPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeDPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeDPR_8RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeDPR_VFP2RegisterClass(llvm::MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder);
+static DecodeStatus DecodeQPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus DecodePredicateOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeCCOutOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeSOImmOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeSPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeDPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus DecodeBitfieldMaskOperand(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeCopMemInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
+static DecodeStatus DecodeSORegMemOperand(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeAddrMode3Instruction(llvm::MCInst &Inst,unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeSORegImmOperand(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeSORegRegOperand(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus DecodeMemMultipleWritebackInstruction(llvm::MCInst & Inst,
+ unsigned Insn,
+ uint64_t Adddress,
+ const void *Decoder);
+static DecodeStatus DecodeT2MOVTWInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeArmMOVTWInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeCPSInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2CPSInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeAddrMode7Operand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeBranchImmInstruction(llvm::MCInst &Inst,unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVCVTImmOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeAddrMode6Operand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVLD1DupInstruction(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVLD2DupInstruction(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVLD3DupInstruction(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVLD4DupInstruction(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeNEONModImmInstruction(llvm::MCInst &Inst,unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVSHLMaxInstruction(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeShiftRight8Imm(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeShiftRight16Imm(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeShiftRight32Imm(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeCoprocessor(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeMemBarrierOption(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeMSRMask(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeDoubleRegLoad(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeDoubleRegStore(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeLDRPreImm(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeLDRPreReg(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeSTRPreImm(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeSTRPreReg(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVLD1LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVLD2LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVLD3LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVLD4LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVST1LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVST2LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVST3LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVST4LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVMOVSRR(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeVMOVRRS(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbBROperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2BROperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbCmpBROperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbAddrModeRR(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbAddrModeIS(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbAddrModePC(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbAddrModeSP(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2AddrModeSOReg(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2LoadShift(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2Imm8S4(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2AddrModeImm0_1020s4(llvm::MCInst &Inst,unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbAddSPImm(llvm::MCInst &Inst, uint16_t Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbCPS(llvm::MCInst &Inst, uint16_t Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbTableBranch(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2SOImm(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbBCCTargetOperand(llvm::MCInst &Inst,unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeIT(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2LDRDPreInstruction(llvm::MCInst &Inst,unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2STRDPreInstruction(llvm::MCInst &Inst,unsigned Insn,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2Adr(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2LdStPre(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeT2ShifterImmOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder);
+
+
+
+#include "ARMGenDisassemblerTables.inc"
+#include "ARMGenInstrInfo.inc"
#include "ARMGenEDInfo.inc"
-using namespace llvm;
+static MCDisassembler *createARMDisassembler(const Target &T, const MCSubtargetInfo &STI) {
+ return new ARMDisassembler(STI);
+}
+
+static MCDisassembler *createThumbDisassembler(const Target &T, const MCSubtargetInfo &STI) {
+ return new ThumbDisassembler(STI);
+}
-/// showBitVector - Use the raw_ostream to log a diagnostic message describing
-/// the inidividual bits of the instruction.
-///
-static inline void showBitVector(raw_ostream &os, const uint32_t &insn) {
- // Split the bit position markers into more than one lines to fit 80 columns.
- os << " 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11"
- << " 10 9 8 7 6 5 4 3 2 1 0 \n";
- os << "---------------------------------------------------------------"
- << "----------------------------------\n";
- os << '|';
- for (unsigned i = 32; i != 0; --i) {
- if (insn >> (i - 1) & 0x01)
- os << " 1";
+EDInstInfo *ARMDisassembler::getEDInfo() const {
+ return instInfoARM;
+}
+
+EDInstInfo *ThumbDisassembler::getEDInfo() const {
+ return instInfoARM;
+}
+
+DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
+ const MemoryObject &Region,
+ uint64_t Address,
+ raw_ostream &os,
+ raw_ostream &cs) const {
+ CommentStream = &cs;
+
+ uint8_t bytes[4];
+
+ assert(!(STI.getFeatureBits() & ARM::ModeThumb) &&
+ "Asked to disassemble an ARM instruction but Subtarget is in Thumb mode!");
+
+ // We want to read exactly 4 bytes of data.
+ if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1) {
+ Size = 0;
+ return MCDisassembler::Fail;
+ }
+
+ // Encoded as a small-endian 32-bit word in the stream.
+ uint32_t insn = (bytes[3] << 24) |
+ (bytes[2] << 16) |
+ (bytes[1] << 8) |
+ (bytes[0] << 0);
+
+ // Calling the auto-generated decoder function.
+ DecodeStatus result = decodeARMInstruction32(MI, insn, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 4;
+ return result;
+ }
+
+ // VFP and NEON instructions, similarly, are shared between ARM
+ // and Thumb modes.
+ MI.clear();
+ result = decodeVFPInstruction32(MI, insn, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 4;
+ return result;
+ }
+
+ MI.clear();
+ result = decodeNEONDataInstruction32(MI, insn, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 4;
+ // Add a fake predicate operand, because we share these instruction
+ // definitions with Thumb2 where these instructions are predicable.
+ if (!DecodePredicateOperand(MI, 0xE, Address, this))
+ return MCDisassembler::Fail;
+ return result;
+ }
+
+ MI.clear();
+ result = decodeNEONLoadStoreInstruction32(MI, insn, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 4;
+ // Add a fake predicate operand, because we share these instruction
+ // definitions with Thumb2 where these instructions are predicable.
+ if (!DecodePredicateOperand(MI, 0xE, Address, this))
+ return MCDisassembler::Fail;
+ return result;
+ }
+
+ MI.clear();
+ result = decodeNEONDupInstruction32(MI, insn, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 4;
+ // Add a fake predicate operand, because we share these instruction
+ // definitions with Thumb2 where these instructions are predicable.
+ if (!DecodePredicateOperand(MI, 0xE, Address, this))
+ return MCDisassembler::Fail;
+ return result;
+ }
+
+ MI.clear();
+
+ Size = 0;
+ return MCDisassembler::Fail;
+}
+
+namespace llvm {
+extern MCInstrDesc ARMInsts[];
+}
+
+/// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the
+/// immediate Value in the MCInst. The immediate Value has had any PC
+/// adjustment made by the caller. If the instruction is a branch instruction
+/// then isBranch is true, else false. If the getOpInfo() function was set as
+/// part of the setupForSymbolicDisassembly() call then that function is called
+/// to get any symbolic information at the Address for this instruction. If
+/// that returns non-zero then the symbolic information it returns is used to
+/// create an MCExpr and that is added as an operand to the MCInst. If
+/// getOpInfo() returns zero and isBranch is true then a symbol look up for
+/// Value is done and if a symbol is found an MCExpr is created with that, else
+/// an MCExpr with Value is created. This function returns true if it adds an
+/// operand to the MCInst and false otherwise.
+static bool tryAddingSymbolicOperand(uint64_t Address, int32_t Value,
+ bool isBranch, uint64_t InstSize,
+ MCInst &MI, const void *Decoder) {
+ const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
+ LLVMOpInfoCallback getOpInfo = Dis->getLLVMOpInfoCallback();
+ if (!getOpInfo)
+ return false;
+
+ struct LLVMOpInfo1 SymbolicOp;
+ SymbolicOp.Value = Value;
+ void *DisInfo = Dis->getDisInfoBlock();
+ if (!getOpInfo(DisInfo, Address, 0 /* Offset */, InstSize, 1, &SymbolicOp)) {
+ if (isBranch) {
+ LLVMSymbolLookupCallback SymbolLookUp =
+ Dis->getLLVMSymbolLookupCallback();
+ if (SymbolLookUp) {
+ uint64_t ReferenceType;
+ ReferenceType = LLVMDisassembler_ReferenceType_In_Branch;
+ const char *ReferenceName;
+ const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address,
+ &ReferenceName);
+ if (Name) {
+ SymbolicOp.AddSymbol.Name = Name;
+ SymbolicOp.AddSymbol.Present = true;
+ SymbolicOp.Value = 0;
+ }
+ else {
+ SymbolicOp.Value = Value;
+ }
+ if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub)
+ (*Dis->CommentStream) << "symbol stub for: " << ReferenceName;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ return false;
+ }
+ }
+
+ MCContext *Ctx = Dis->getMCContext();
+ const MCExpr *Add = NULL;
+ if (SymbolicOp.AddSymbol.Present) {
+ if (SymbolicOp.AddSymbol.Name) {
+ StringRef Name(SymbolicOp.AddSymbol.Name);
+ MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name);
+ Add = MCSymbolRefExpr::Create(Sym, *Ctx);
+ } else {
+ Add = MCConstantExpr::Create(SymbolicOp.AddSymbol.Value, *Ctx);
+ }
+ }
+
+ const MCExpr *Sub = NULL;
+ if (SymbolicOp.SubtractSymbol.Present) {
+ if (SymbolicOp.SubtractSymbol.Name) {
+ StringRef Name(SymbolicOp.SubtractSymbol.Name);
+ MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name);
+ Sub = MCSymbolRefExpr::Create(Sym, *Ctx);
+ } else {
+ Sub = MCConstantExpr::Create(SymbolicOp.SubtractSymbol.Value, *Ctx);
+ }
+ }
+
+ const MCExpr *Off = NULL;
+ if (SymbolicOp.Value != 0)
+ Off = MCConstantExpr::Create(SymbolicOp.Value, *Ctx);
+
+ const MCExpr *Expr;
+ if (Sub) {
+ const MCExpr *LHS;
+ if (Add)
+ LHS = MCBinaryExpr::CreateSub(Add, Sub, *Ctx);
else
- os << " 0";
- os << (i%4 == 1 ? '|' : ':');
- }
- os << '\n';
- // Split the bit position markers into more than one lines to fit 80 columns.
- os << "---------------------------------------------------------------"
- << "----------------------------------\n";
- os << '\n';
-}
-
-/// decodeARMInstruction is a decorator function which tries special cases of
-/// instruction matching before calling the auto-generated decoder function.
-static unsigned decodeARMInstruction(uint32_t &insn) {
- if (slice(insn, 31, 28) == 15)
- goto AutoGenedDecoder;
-
- // Special case processing, if any, goes here....
-
- // LLVM combines the offset mode of A8.6.197 & A8.6.198 into STRB.
- // The insufficient encoding information of the combined instruction confuses
- // the decoder wrt BFC/BFI. Therefore, we try to recover here.
- // For BFC, Inst{27-21} = 0b0111110 & Inst{6-0} = 0b0011111.
- // For BFI, Inst{27-21} = 0b0111110 & Inst{6-4} = 0b001 & Inst{3-0} =! 0b1111.
- if (slice(insn, 27, 21) == 0x3e && slice(insn, 6, 4) == 1) {
- if (slice(insn, 3, 0) == 15)
- return ARM::BFC;
+ LHS = MCUnaryExpr::CreateMinus(Sub, *Ctx);
+ if (Off != 0)
+ Expr = MCBinaryExpr::CreateAdd(LHS, Off, *Ctx);
else
- return ARM::BFI;
- }
-
- // Ditto for STRBT, which is a super-instruction for A8.6.199 Encodings
- // A1 & A2.
- // As a result, the decoder fails to deocode USAT properly.
- if (slice(insn, 27, 21) == 0x37 && slice(insn, 5, 4) == 1)
- return ARM::USAT;
- // As a result, the decoder fails to deocode UQADD16 properly.
- if (slice(insn, 27, 20) == 0x66 && slice(insn, 7, 4) == 1)
- return ARM::UQADD16;
-
- // Ditto for ADDSrs, which is a super-instruction for A8.6.7 & A8.6.8.
- // As a result, the decoder fails to decode UMULL properly.
- if (slice(insn, 27, 21) == 0x04 && slice(insn, 7, 4) == 9) {
- return ARM::UMULL;
- }
-
- // Ditto for STR_PRE, which is a super-instruction for A8.6.194 & A8.6.195.
- // As a result, the decoder fails to decode SBFX properly.
- if (slice(insn, 27, 21) == 0x3d && slice(insn, 6, 4) == 5)
- return ARM::SBFX;
-
- // And STRB_PRE, which is a super-instruction for A8.6.197 & A8.6.198.
- // As a result, the decoder fails to decode UBFX properly.
- if (slice(insn, 27, 21) == 0x3f && slice(insn, 6, 4) == 5)
- return ARM::UBFX;
-
- // Ditto for STRT, which is a super-instruction for A8.6.210 Encoding A1 & A2.
- // As a result, the decoder fails to deocode SSAT properly.
- if (slice(insn, 27, 21) == 0x35 && slice(insn, 5, 4) == 1)
- return ARM::SSAT;
-
- // Ditto for RSCrs, which is a super-instruction for A8.6.146 & A8.6.147.
- // As a result, the decoder fails to decode STRHT/LDRHT/LDRSHT/LDRSBT.
- if (slice(insn, 27, 24) == 0) {
- switch (slice(insn, 21, 20)) {
- case 2:
- switch (slice(insn, 7, 4)) {
- case 11:
- return ARM::STRHT;
- default:
- break; // fallthrough
+ Expr = LHS;
+ } else if (Add) {
+ if (Off != 0)
+ Expr = MCBinaryExpr::CreateAdd(Add, Off, *Ctx);
+ else
+ Expr = Add;
+ } else {
+ if (Off != 0)
+ Expr = Off;
+ else
+ Expr = MCConstantExpr::Create(0, *Ctx);
+ }
+
+ if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_HI16)
+ MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateUpper16(Expr, *Ctx)));
+ else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_LO16)
+ MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateLower16(Expr, *Ctx)));
+ else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_None)
+ MI.addOperand(MCOperand::CreateExpr(Expr));
+ else
+ assert(0 && "bad SymbolicOp.VariantKind");
+
+ return true;
+}
+
+/// tryAddingPcLoadReferenceComment - trys to add a comment as to what is being
+/// referenced by a load instruction with the base register that is the Pc.
+/// These can often be values in a literal pool near the Address of the
+/// instruction. The Address of the instruction and its immediate Value are
+/// used as a possible literal pool entry. The SymbolLookUp call back will
+/// return the name of a symbol referenced by the the literal pool's entry if
+/// the referenced address is that of a symbol. Or it will return a pointer to
+/// a literal 'C' string if the referenced address of the literal pool's entry
+/// is an address into a section with 'C' string literals.
+static void tryAddingPcLoadReferenceComment(uint64_t Address, int Value,
+ const void *Decoder) {
+ const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
+ LLVMSymbolLookupCallback SymbolLookUp = Dis->getLLVMSymbolLookupCallback();
+ if (SymbolLookUp) {
+ void *DisInfo = Dis->getDisInfoBlock();
+ uint64_t ReferenceType;
+ ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load;
+ const char *ReferenceName;
+ (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName);
+ if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr ||
+ ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr)
+ (*Dis->CommentStream) << "literal pool for: " << ReferenceName;
+ }
+}
+
+// Thumb1 instructions don't have explicit S bits. Rather, they
+// implicitly set CPSR. Since it's not represented in the encoding, the
+// auto-generated decoder won't inject the CPSR operand. We need to fix
+// that as a post-pass.
+static void AddThumb1SBit(MCInst &MI, bool InITBlock) {
+ const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
+ unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
+ MCInst::iterator I = MI.begin();
+ for (unsigned i = 0; i < NumOps; ++i, ++I) {
+ if (I == MI.end()) break;
+ if (OpInfo[i].isOptionalDef() && OpInfo[i].RegClass == ARM::CCRRegClassID) {
+ if (i > 0 && OpInfo[i-1].isPredicate()) continue;
+ MI.insert(I, MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR));
+ return;
+ }
+ }
+
+ MI.insert(I, MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR));
+}
+
+// Most Thumb instructions don't have explicit predicates in the
+// encoding, but rather get their predicates from IT context. We need
+// to fix up the predicate operands using this context information as a
+// post-pass.
+MCDisassembler::DecodeStatus
+ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
+ MCDisassembler::DecodeStatus S = Success;
+
+ // A few instructions actually have predicates encoded in them. Don't
+ // try to overwrite it if we're seeing one of those.
+ switch (MI.getOpcode()) {
+ case ARM::tBcc:
+ case ARM::t2Bcc:
+ case ARM::tCBZ:
+ case ARM::tCBNZ:
+ case ARM::tCPS:
+ case ARM::t2CPS3p:
+ case ARM::t2CPS2p:
+ case ARM::t2CPS1p:
+ case ARM::tMOVSr:
+ case ARM::tSETEND:
+ // Some instructions (mostly conditional branches) are not
+ // allowed in IT blocks.
+ if (!ITBlock.empty())
+ S = SoftFail;
+ else
+ return Success;
+ break;
+ case ARM::tB:
+ case ARM::t2B:
+ case ARM::t2TBB:
+ case ARM::t2TBH:
+ // Some instructions (mostly unconditional branches) can
+ // only appears at the end of, or outside of, an IT.
+ if (ITBlock.size() > 1)
+ S = SoftFail;
+ break;
+ default:
+ break;
+ }
+
+ // If we're in an IT block, base the predicate on that. Otherwise,
+ // assume a predicate of AL.
+ unsigned CC;
+ if (!ITBlock.empty()) {
+ CC = ITBlock.back();
+ if (CC == 0xF)
+ CC = ARMCC::AL;
+ ITBlock.pop_back();
+ } else
+ CC = ARMCC::AL;
+
+ const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
+ unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
+ MCInst::iterator I = MI.begin();
+ for (unsigned i = 0; i < NumOps; ++i, ++I) {
+ if (I == MI.end()) break;
+ if (OpInfo[i].isPredicate()) {
+ I = MI.insert(I, MCOperand::CreateImm(CC));
+ ++I;
+ if (CC == ARMCC::AL)
+ MI.insert(I, MCOperand::CreateReg(0));
+ else
+ MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
+ return S;
+ }
+ }
+
+ I = MI.insert(I, MCOperand::CreateImm(CC));
+ ++I;
+ if (CC == ARMCC::AL)
+ MI.insert(I, MCOperand::CreateReg(0));
+ else
+ MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
+
+ return S;
+}
+
+// Thumb VFP instructions are a special case. Because we share their
+// encodings between ARM and Thumb modes, and they are predicable in ARM
+// mode, the auto-generated decoder will give them an (incorrect)
+// predicate operand. We need to rewrite these operands based on the IT
+// context as a post-pass.
+void ThumbDisassembler::UpdateThumbVFPPredicate(MCInst &MI) const {
+ unsigned CC;
+ if (!ITBlock.empty()) {
+ CC = ITBlock.back();
+ ITBlock.pop_back();
+ } else
+ CC = ARMCC::AL;
+
+ const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
+ MCInst::iterator I = MI.begin();
+ unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
+ for (unsigned i = 0; i < NumOps; ++i, ++I) {
+ if (OpInfo[i].isPredicate() ) {
+ I->setImm(CC);
+ ++I;
+ if (CC == ARMCC::AL)
+ I->setReg(0);
+ else
+ I->setReg(ARM::CPSR);
+ return;
+ }
+ }
+}
+
+DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
+ const MemoryObject &Region,
+ uint64_t Address,
+ raw_ostream &os,
+ raw_ostream &cs) const {
+ CommentStream = &cs;
+
+ uint8_t bytes[4];
+
+ assert((STI.getFeatureBits() & ARM::ModeThumb) &&
+ "Asked to disassemble in Thumb mode but Subtarget is in ARM mode!");
+
+ // We want to read exactly 2 bytes of data.
+ if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1) {
+ Size = 0;
+ return MCDisassembler::Fail;
+ }
+
+ uint16_t insn16 = (bytes[1] << 8) | bytes[0];
+ DecodeStatus result = decodeThumbInstruction16(MI, insn16, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 2;
+ Check(result, AddThumbPredicate(MI));
+ return result;
+ }
+
+ MI.clear();
+ result = decodeThumbSBitInstruction16(MI, insn16, Address, this, STI);
+ if (result) {
+ Size = 2;
+ bool InITBlock = !ITBlock.empty();
+ Check(result, AddThumbPredicate(MI));
+ AddThumb1SBit(MI, InITBlock);
+ return result;
+ }
+
+ MI.clear();
+ result = decodeThumb2Instruction16(MI, insn16, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 2;
+
+ // Nested IT blocks are UNPREDICTABLE. Must be checked before we add
+ // the Thumb predicate.
+ if (MI.getOpcode() == ARM::t2IT && !ITBlock.empty())
+ result = MCDisassembler::SoftFail;
+
+ Check(result, AddThumbPredicate(MI));
+
+ // If we find an IT instruction, we need to parse its condition
+ // code and mask operands so that we can apply them correctly
+ // to the subsequent instructions.
+ if (MI.getOpcode() == ARM::t2IT) {
+
+ // (3 - the number of trailing zeros) is the number of then / else.
+ unsigned firstcond = MI.getOperand(0).getImm();
+ unsigned Mask = MI.getOperand(1).getImm();
+ unsigned CondBit0 = Mask >> 4 & 1;
+ unsigned NumTZ = CountTrailingZeros_32(Mask);
+ assert(NumTZ <= 3 && "Invalid IT mask!");
+ for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
+ bool T = ((Mask >> Pos) & 1) == CondBit0;
+ if (T)
+ ITBlock.insert(ITBlock.begin(), firstcond);
+ else
+ ITBlock.insert(ITBlock.begin(), firstcond ^ 1);
}
+
+ ITBlock.push_back(firstcond);
+ }
+
+ return result;
+ }
+
+ // We want to read exactly 4 bytes of data.
+ if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1) {
+ Size = 0;
+ return MCDisassembler::Fail;
+ }
+
+ uint32_t insn32 = (bytes[3] << 8) |
+ (bytes[2] << 0) |
+ (bytes[1] << 24) |
+ (bytes[0] << 16);
+ MI.clear();
+ result = decodeThumbInstruction32(MI, insn32, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 4;
+ bool InITBlock = ITBlock.size();
+ Check(result, AddThumbPredicate(MI));
+ AddThumb1SBit(MI, InITBlock);
+ return result;
+ }
+
+ MI.clear();
+ result = decodeThumb2Instruction32(MI, insn32, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 4;
+ Check(result, AddThumbPredicate(MI));
+ return result;
+ }
+
+ MI.clear();
+ result = decodeVFPInstruction32(MI, insn32, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 4;
+ UpdateThumbVFPPredicate(MI);
+ return result;
+ }
+
+ MI.clear();
+ result = decodeNEONDupInstruction32(MI, insn32, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 4;
+ Check(result, AddThumbPredicate(MI));
+ return result;
+ }
+
+ if (fieldFromInstruction32(insn32, 24, 8) == 0xF9) {
+ MI.clear();
+ uint32_t NEONLdStInsn = insn32;
+ NEONLdStInsn &= 0xF0FFFFFF;
+ NEONLdStInsn |= 0x04000000;
+ result = decodeNEONLoadStoreInstruction32(MI, NEONLdStInsn, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 4;
+ Check(result, AddThumbPredicate(MI));
+ return result;
+ }
+ }
+
+ if (fieldFromInstruction32(insn32, 24, 4) == 0xF) {
+ MI.clear();
+ uint32_t NEONDataInsn = insn32;
+ NEONDataInsn &= 0xF0FFFFFF; // Clear bits 27-24
+ NEONDataInsn |= (NEONDataInsn & 0x10000000) >> 4; // Move bit 28 to bit 24
+ NEONDataInsn |= 0x12000000; // Set bits 28 and 25
+ result = decodeNEONDataInstruction32(MI, NEONDataInsn, Address, this, STI);
+ if (result != MCDisassembler::Fail) {
+ Size = 4;
+ Check(result, AddThumbPredicate(MI));
+ return result;
+ }
+ }
+
+ Size = 0;
+ return MCDisassembler::Fail;
+}
+
+
+extern "C" void LLVMInitializeARMDisassembler() {
+ TargetRegistry::RegisterMCDisassembler(TheARMTarget,
+ createARMDisassembler);
+ TargetRegistry::RegisterMCDisassembler(TheThumbTarget,
+ createThumbDisassembler);
+}
+
+static const unsigned GPRDecoderTable[] = {
+ ARM::R0, ARM::R1, ARM::R2, ARM::R3,
+ ARM::R4, ARM::R5, ARM::R6, ARM::R7,
+ ARM::R8, ARM::R9, ARM::R10, ARM::R11,
+ ARM::R12, ARM::SP, ARM::LR, ARM::PC
+};
+
+static DecodeStatus DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if (RegNo > 15)
+ return MCDisassembler::Fail;
+
+ unsigned Register = GPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::CreateReg(Register));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus
+DecodeGPRnopcRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if (RegNo == 15) return MCDisassembler::Fail;
+ return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
+}
+
+static DecodeStatus DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if (RegNo > 7)
+ return MCDisassembler::Fail;
+ return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
+}
+
+static DecodeStatus DecodetcGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ unsigned Register = 0;
+ switch (RegNo) {
+ case 0:
+ Register = ARM::R0;
+ break;
+ case 1:
+ Register = ARM::R1;
+ break;
+ case 2:
+ Register = ARM::R2;
break;
case 3:
- switch (slice(insn, 7, 4)) {
- case 11:
- return ARM::LDRHT;
- case 13:
- return ARM::LDRSBT;
- case 15:
- return ARM::LDRSHT;
- default:
- break; // fallthrough
- }
+ Register = ARM::R3;
+ break;
+ case 9:
+ Register = ARM::R9;
+ break;
+ case 12:
+ Register = ARM::R12;
break;
default:
- break; // fallthrough
+ return MCDisassembler::Fail;
}
+
+ Inst.addOperand(MCOperand::CreateReg(Register));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecoderGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if (RegNo == 13 || RegNo == 15) return MCDisassembler::Fail;
+ return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
+}
+
+static const unsigned SPRDecoderTable[] = {
+ ARM::S0, ARM::S1, ARM::S2, ARM::S3,
+ ARM::S4, ARM::S5, ARM::S6, ARM::S7,
+ ARM::S8, ARM::S9, ARM::S10, ARM::S11,
+ ARM::S12, ARM::S13, ARM::S14, ARM::S15,
+ ARM::S16, ARM::S17, ARM::S18, ARM::S19,
+ ARM::S20, ARM::S21, ARM::S22, ARM::S23,
+ ARM::S24, ARM::S25, ARM::S26, ARM::S27,
+ ARM::S28, ARM::S29, ARM::S30, ARM::S31
+};
+
+static DecodeStatus DecodeSPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+
+ unsigned Register = SPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::CreateReg(Register));
+ return MCDisassembler::Success;
+}
+
+static const unsigned DPRDecoderTable[] = {
+ ARM::D0, ARM::D1, ARM::D2, ARM::D3,
+ ARM::D4, ARM::D5, ARM::D6, ARM::D7,
+ ARM::D8, ARM::D9, ARM::D10, ARM::D11,
+ ARM::D12, ARM::D13, ARM::D14, ARM::D15,
+ ARM::D16, ARM::D17, ARM::D18, ARM::D19,
+ ARM::D20, ARM::D21, ARM::D22, ARM::D23,
+ ARM::D24, ARM::D25, ARM::D26, ARM::D27,
+ ARM::D28, ARM::D29, ARM::D30, ARM::D31
+};
+
+static DecodeStatus DecodeDPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+
+ unsigned Register = DPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::CreateReg(Register));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeDPR_8RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if (RegNo > 7)
+ return MCDisassembler::Fail;
+ return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
+}
+
+static DecodeStatus
+DecodeDPR_VFP2RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if (RegNo > 15)
+ return MCDisassembler::Fail;
+ return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
+}
+
+static const unsigned QPRDecoderTable[] = {
+ ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3,
+ ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7,
+ ARM::Q8, ARM::Q9, ARM::Q10, ARM::Q11,
+ ARM::Q12, ARM::Q13, ARM::Q14, ARM::Q15
+};
+
+
+static DecodeStatus DecodeQPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+ RegNo >>= 1;
+
+ unsigned Register = QPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::CreateReg(Register));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodePredicateOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ if (Val == 0xF) return MCDisassembler::Fail;
+ // AL predicate is not allowed on Thumb1 branches.
+ if (Inst.getOpcode() == ARM::tBcc && Val == 0xE)
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ if (Val == ARMCC::AL) {
+ Inst.addOperand(MCOperand::CreateReg(0));
+ } else
+ Inst.addOperand(MCOperand::CreateReg(ARM::CPSR));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeCCOutOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ if (Val)
+ Inst.addOperand(MCOperand::CreateReg(ARM::CPSR));
+ else
+ Inst.addOperand(MCOperand::CreateReg(0));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeSOImmOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ uint32_t imm = Val & 0xFF;
+ uint32_t rot = (Val & 0xF00) >> 7;
+ uint32_t rot_imm = (imm >> rot) | (imm << ((32-rot) & 0x1F));
+ Inst.addOperand(MCOperand::CreateImm(rot_imm));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeSORegImmOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rm = fieldFromInstruction32(Val, 0, 4);
+ unsigned type = fieldFromInstruction32(Val, 5, 2);
+ unsigned imm = fieldFromInstruction32(Val, 7, 5);
+
+ // Register-immediate
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
+ switch (type) {
+ case 0:
+ Shift = ARM_AM::lsl;
+ break;
+ case 1:
+ Shift = ARM_AM::lsr;
+ break;
+ case 2:
+ Shift = ARM_AM::asr;
+ break;
+ case 3:
+ Shift = ARM_AM::ror;
+ break;
}
- // Ditto for SBCrs, which is a super-instruction for A8.6.152 & A8.6.153.
- // As a result, the decoder fails to decode STRH_Post/LDRD_POST/STRD_POST
- // properly.
- if (slice(insn, 27, 25) == 0 && slice(insn, 20, 20) == 0) {
- unsigned PW = slice(insn, 24, 24) << 1 | slice(insn, 21, 21);
- switch (slice(insn, 7, 4)) {
- case 11:
- switch (PW) {
- case 2: // Offset
- return ARM::STRH;
- case 3: // Pre-indexed
- return ARM::STRH_PRE;
- case 0: // Post-indexed
- return ARM::STRH_POST;
- default:
- break; // fallthrough
- }
+ if (Shift == ARM_AM::ror && imm == 0)
+ Shift = ARM_AM::rrx;
+
+ unsigned Op = Shift | (imm << 3);
+ Inst.addOperand(MCOperand::CreateImm(Op));
+
+ return S;
+}
+
+static DecodeStatus DecodeSORegRegOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rm = fieldFromInstruction32(Val, 0, 4);
+ unsigned type = fieldFromInstruction32(Val, 5, 2);
+ unsigned Rs = fieldFromInstruction32(Val, 8, 4);
+
+ // Register-register
+ if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rs, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
+ switch (type) {
+ case 0:
+ Shift = ARM_AM::lsl;
break;
- case 13:
- switch (PW) {
- case 2: // Offset
- return ARM::LDRD;
- case 3: // Pre-indexed
- return ARM::LDRD_PRE;
- case 0: // Post-indexed
- return ARM::LDRD_POST;
- default:
- break; // fallthrough
- }
+ case 1:
+ Shift = ARM_AM::lsr;
break;
- case 15:
- switch (PW) {
- case 2: // Offset
- return ARM::STRD;
- case 3: // Pre-indexed
- return ARM::STRD_PRE;
- case 0: // Post-indexed
- return ARM::STRD_POST;
- default:
- break; // fallthrough
- }
+ case 2:
+ Shift = ARM_AM::asr;
break;
+ case 3:
+ Shift = ARM_AM::ror;
+ break;
+ }
+
+ Inst.addOperand(MCOperand::CreateImm(Shift));
+
+ return S;
+}
+
+static DecodeStatus DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ bool writebackLoad = false;
+ unsigned writebackReg = 0;
+ switch (Inst.getOpcode()) {
default:
- break; // fallthrough
+ break;
+ case ARM::LDMIA_UPD:
+ case ARM::LDMDB_UPD:
+ case ARM::LDMIB_UPD:
+ case ARM::LDMDA_UPD:
+ case ARM::t2LDMIA_UPD:
+ case ARM::t2LDMDB_UPD:
+ writebackLoad = true;
+ writebackReg = Inst.getOperand(0).getReg();
+ break;
+ }
+
+ // Empty register lists are not allowed.
+ if (CountPopulation_32(Val) == 0) return MCDisassembler::Fail;
+ for (unsigned i = 0; i < 16; ++i) {
+ if (Val & (1 << i)) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, i, Address, Decoder)))
+ return MCDisassembler::Fail;
+ // Writeback not allowed if Rn is in the target list.
+ if (writebackLoad && writebackReg == Inst.end()[-1].getReg())
+ Check(S, MCDisassembler::SoftFail);
}
}
- // Ditto for SBCSSrs, which is a super-instruction for A8.6.152 & A8.6.153.
- // As a result, the decoder fails to decode LDRH_POST/LDRSB_POST/LDRSH_POST
- // properly.
- if (slice(insn, 27, 25) == 0 && slice(insn, 20, 20) == 1) {
- unsigned PW = slice(insn, 24, 24) << 1 | slice(insn, 21, 21);
- switch (slice(insn, 7, 4)) {
- case 11:
- switch (PW) {
- case 2: // Offset
- return ARM::LDRH;
- case 3: // Pre-indexed
- return ARM::LDRH_PRE;
- case 0: // Post-indexed
- return ARM::LDRH_POST;
- default:
- break; // fallthrough
- }
+ return S;
+}
+
+static DecodeStatus DecodeSPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Vd = fieldFromInstruction32(Val, 8, 4);
+ unsigned regs = Val & 0xFF;
+
+ if (!Check(S, DecodeSPRRegisterClass(Inst, Vd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ for (unsigned i = 0; i < (regs - 1); ++i) {
+ if (!Check(S, DecodeSPRRegisterClass(Inst, ++Vd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ return S;
+}
+
+static DecodeStatus DecodeDPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Vd = fieldFromInstruction32(Val, 8, 4);
+ unsigned regs = (Val & 0xFF) / 2;
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Vd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ for (unsigned i = 0; i < (regs - 1); ++i) {
+ if (!Check(S, DecodeDPRRegisterClass(Inst, ++Vd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ return S;
+}
+
+static DecodeStatus DecodeBitfieldMaskOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ // This operand encodes a mask of contiguous zeros between a specified MSB
+ // and LSB. To decode it, we create the mask of all bits MSB-and-lower,
+ // the mask of all bits LSB-and-lower, and then xor them to create
+ // the mask of that's all ones on [msb, lsb]. Finally we not it to
+ // create the final mask.
+ unsigned msb = fieldFromInstruction32(Val, 5, 5);
+ unsigned lsb = fieldFromInstruction32(Val, 0, 5);
+
+ DecodeStatus S = MCDisassembler::Success;
+ if (lsb > msb) Check(S, MCDisassembler::SoftFail);
+
+ uint32_t msb_mask = 0xFFFFFFFF;
+ if (msb != 31) msb_mask = (1U << (msb+1)) - 1;
+ uint32_t lsb_mask = (1U << lsb) - 1;
+
+ Inst.addOperand(MCOperand::CreateImm(~(msb_mask ^ lsb_mask)));
+ return S;
+}
+
+static DecodeStatus DecodeCopMemInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+ unsigned CRd = fieldFromInstruction32(Insn, 12, 4);
+ unsigned coproc = fieldFromInstruction32(Insn, 8, 4);
+ unsigned imm = fieldFromInstruction32(Insn, 0, 8);
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned U = fieldFromInstruction32(Insn, 23, 1);
+
+ switch (Inst.getOpcode()) {
+ case ARM::LDC_OFFSET:
+ case ARM::LDC_PRE:
+ case ARM::LDC_POST:
+ case ARM::LDC_OPTION:
+ case ARM::LDCL_OFFSET:
+ case ARM::LDCL_PRE:
+ case ARM::LDCL_POST:
+ case ARM::LDCL_OPTION:
+ case ARM::STC_OFFSET:
+ case ARM::STC_PRE:
+ case ARM::STC_POST:
+ case ARM::STC_OPTION:
+ case ARM::STCL_OFFSET:
+ case ARM::STCL_PRE:
+ case ARM::STCL_POST:
+ case ARM::STCL_OPTION:
+ case ARM::t2LDC_OFFSET:
+ case ARM::t2LDC_PRE:
+ case ARM::t2LDC_POST:
+ case ARM::t2LDC_OPTION:
+ case ARM::t2LDCL_OFFSET:
+ case ARM::t2LDCL_PRE:
+ case ARM::t2LDCL_POST:
+ case ARM::t2LDCL_OPTION:
+ case ARM::t2STC_OFFSET:
+ case ARM::t2STC_PRE:
+ case ARM::t2STC_POST:
+ case ARM::t2STC_OPTION:
+ case ARM::t2STCL_OFFSET:
+ case ARM::t2STCL_PRE:
+ case ARM::t2STCL_POST:
+ case ARM::t2STCL_OPTION:
+ if (coproc == 0xA || coproc == 0xB)
+ return MCDisassembler::Fail;
+ break;
+ default:
break;
- case 13:
- switch (PW) {
- case 2: // Offset
- return ARM::LDRSB;
- case 3: // Pre-indexed
- return ARM::LDRSB_PRE;
- case 0: // Post-indexed
- return ARM::LDRSB_POST;
+ }
+
+ Inst.addOperand(MCOperand::CreateImm(coproc));
+ Inst.addOperand(MCOperand::CreateImm(CRd));
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ unsigned P = fieldFromInstruction32(Insn, 24, 1);
+ unsigned W = fieldFromInstruction32(Insn, 21, 1);
+
+ bool writeback = (P == 0) || (W == 1);
+ unsigned idx_mode = 0;
+ if (P && writeback)
+ idx_mode = ARMII::IndexModePre;
+ else if (!P && writeback)
+ idx_mode = ARMII::IndexModePost;
+
+ switch (Inst.getOpcode()) {
+ case ARM::t2LDC2_OFFSET:
+ case ARM::t2LDC2L_OFFSET:
+ case ARM::t2LDC2_PRE:
+ case ARM::t2LDC2L_PRE:
+ case ARM::t2STC2_OFFSET:
+ case ARM::t2STC2L_OFFSET:
+ case ARM::t2STC2_PRE:
+ case ARM::t2STC2L_PRE:
+ case ARM::LDC2_OFFSET:
+ case ARM::LDC2L_OFFSET:
+ case ARM::LDC2_PRE:
+ case ARM::LDC2L_PRE:
+ case ARM::STC2_OFFSET:
+ case ARM::STC2L_OFFSET:
+ case ARM::STC2_PRE:
+ case ARM::STC2L_PRE:
+ case ARM::t2LDC_OFFSET:
+ case ARM::t2LDCL_OFFSET:
+ case ARM::t2LDC_PRE:
+ case ARM::t2LDCL_PRE:
+ case ARM::t2STC_OFFSET:
+ case ARM::t2STCL_OFFSET:
+ case ARM::t2STC_PRE:
+ case ARM::t2STCL_PRE:
+ case ARM::LDC_OFFSET:
+ case ARM::LDCL_OFFSET:
+ case ARM::LDC_PRE:
+ case ARM::LDCL_PRE:
+ case ARM::STC_OFFSET:
+ case ARM::STCL_OFFSET:
+ case ARM::STC_PRE:
+ case ARM::STCL_PRE:
+ imm = ARM_AM::getAM5Opc(U ? ARM_AM::add : ARM_AM::sub, imm);
+ Inst.addOperand(MCOperand::CreateImm(imm));
+ break;
+ case ARM::t2LDC2_POST:
+ case ARM::t2LDC2L_POST:
+ case ARM::t2STC2_POST:
+ case ARM::t2STC2L_POST:
+ case ARM::LDC2_POST:
+ case ARM::LDC2L_POST:
+ case ARM::STC2_POST:
+ case ARM::STC2L_POST:
+ case ARM::t2LDC_POST:
+ case ARM::t2LDCL_POST:
+ case ARM::t2STC_POST:
+ case ARM::t2STCL_POST:
+ case ARM::LDC_POST:
+ case ARM::LDCL_POST:
+ case ARM::STC_POST:
+ case ARM::STCL_POST:
+ imm |= U << 8;
+ // fall through.
+ default:
+ // The 'option' variant doesn't encode 'U' in the immediate since
+ // the immediate is unsigned [0,255].
+ Inst.addOperand(MCOperand::CreateImm(imm));
+ break;
+ }
+
+ switch (Inst.getOpcode()) {
+ case ARM::LDC_OFFSET:
+ case ARM::LDC_PRE:
+ case ARM::LDC_POST:
+ case ARM::LDC_OPTION:
+ case ARM::LDCL_OFFSET:
+ case ARM::LDCL_PRE:
+ case ARM::LDCL_POST:
+ case ARM::LDCL_OPTION:
+ case ARM::STC_OFFSET:
+ case ARM::STC_PRE:
+ case ARM::STC_POST:
+ case ARM::STC_OPTION:
+ case ARM::STCL_OFFSET:
+ case ARM::STCL_PRE:
+ case ARM::STCL_POST:
+ case ARM::STCL_OPTION:
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ return S;
+}
+
+static DecodeStatus
+DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned imm = fieldFromInstruction32(Insn, 0, 12);
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+ unsigned reg = fieldFromInstruction32(Insn, 25, 1);
+ unsigned P = fieldFromInstruction32(Insn, 24, 1);
+ unsigned W = fieldFromInstruction32(Insn, 21, 1);
+
+ // On stores, the writeback operand precedes Rt.
+ switch (Inst.getOpcode()) {
+ case ARM::STR_POST_IMM:
+ case ARM::STR_POST_REG:
+ case ARM::STRB_POST_IMM:
+ case ARM::STRB_POST_REG:
+ case ARM::STRT_POST_REG:
+ case ARM::STRT_POST_IMM:
+ case ARM::STRBT_POST_REG:
+ case ARM::STRBT_POST_IMM:
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ // On loads, the writeback operand comes after Rt.
+ switch (Inst.getOpcode()) {
+ case ARM::LDR_POST_IMM:
+ case ARM::LDR_POST_REG:
+ case ARM::LDRB_POST_IMM:
+ case ARM::LDRB_POST_REG:
+ case ARM::LDRBT_POST_REG:
+ case ARM::LDRBT_POST_IMM:
+ case ARM::LDRT_POST_REG:
+ case ARM::LDRT_POST_IMM:
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ ARM_AM::AddrOpc Op = ARM_AM::add;
+ if (!fieldFromInstruction32(Insn, 23, 1))
+ Op = ARM_AM::sub;
+
+ bool writeback = (P == 0) || (W == 1);
+ unsigned idx_mode = 0;
+ if (P && writeback)
+ idx_mode = ARMII::IndexModePre;
+ else if (!P && writeback)
+ idx_mode = ARMII::IndexModePost;
+
+ if (writeback && (Rn == 15 || Rn == Rt))
+ S = MCDisassembler::SoftFail; // UNPREDICTABLE
+
+ if (reg) {
+ if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ ARM_AM::ShiftOpc Opc = ARM_AM::lsl;
+ switch( fieldFromInstruction32(Insn, 5, 2)) {
+ case 0:
+ Opc = ARM_AM::lsl;
+ break;
+ case 1:
+ Opc = ARM_AM::lsr;
+ break;
+ case 2:
+ Opc = ARM_AM::asr;
+ break;
+ case 3:
+ Opc = ARM_AM::ror;
+ break;
default:
- break; // fallthrough
- }
+ return MCDisassembler::Fail;
+ }
+ unsigned amt = fieldFromInstruction32(Insn, 7, 5);
+ unsigned imm = ARM_AM::getAM2Opc(Op, amt, Opc, idx_mode);
+
+ Inst.addOperand(MCOperand::CreateImm(imm));
+ } else {
+ Inst.addOperand(MCOperand::CreateReg(0));
+ unsigned tmp = ARM_AM::getAM2Opc(Op, imm, ARM_AM::lsl, idx_mode);
+ Inst.addOperand(MCOperand::CreateImm(tmp));
+ }
+
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeSORegMemOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Val, 13, 4);
+ unsigned Rm = fieldFromInstruction32(Val, 0, 4);
+ unsigned type = fieldFromInstruction32(Val, 5, 2);
+ unsigned imm = fieldFromInstruction32(Val, 7, 5);
+ unsigned U = fieldFromInstruction32(Val, 12, 1);
+
+ ARM_AM::ShiftOpc ShOp = ARM_AM::lsl;
+ switch (type) {
+ case 0:
+ ShOp = ARM_AM::lsl;
+ break;
+ case 1:
+ ShOp = ARM_AM::lsr;
+ break;
+ case 2:
+ ShOp = ARM_AM::asr;
+ break;
+ case 3:
+ ShOp = ARM_AM::ror;
+ break;
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ unsigned shift;
+ if (U)
+ shift = ARM_AM::getAM2Opc(ARM_AM::add, imm, ShOp);
+ else
+ shift = ARM_AM::getAM2Opc(ARM_AM::sub, imm, ShOp);
+ Inst.addOperand(MCOperand::CreateImm(shift));
+
+ return S;
+}
+
+static DecodeStatus
+DecodeAddrMode3Instruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned type = fieldFromInstruction32(Insn, 22, 1);
+ unsigned imm = fieldFromInstruction32(Insn, 8, 4);
+ unsigned U = ((~fieldFromInstruction32(Insn, 23, 1)) & 1) << 8;
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+ unsigned W = fieldFromInstruction32(Insn, 21, 1);
+ unsigned P = fieldFromInstruction32(Insn, 24, 1);
+
+ bool writeback = (W == 1) | (P == 0);
+
+ // For {LD,ST}RD, Rt must be even, else undefined.
+ switch (Inst.getOpcode()) {
+ case ARM::STRD:
+ case ARM::STRD_PRE:
+ case ARM::STRD_POST:
+ case ARM::LDRD:
+ case ARM::LDRD_PRE:
+ case ARM::LDRD_POST:
+ if (Rt & 0x1) return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ if (writeback) { // Writeback
+ if (P)
+ U |= ARMII::IndexModePre << 9;
+ else
+ U |= ARMII::IndexModePost << 9;
+
+ // On stores, the writeback operand precedes Rt.
+ switch (Inst.getOpcode()) {
+ case ARM::STRD:
+ case ARM::STRD_PRE:
+ case ARM::STRD_POST:
+ case ARM::STRH:
+ case ARM::STRH_PRE:
+ case ARM::STRH_POST:
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
+ switch (Inst.getOpcode()) {
+ case ARM::STRD:
+ case ARM::STRD_PRE:
+ case ARM::STRD_POST:
+ case ARM::LDRD:
+ case ARM::LDRD_PRE:
+ case ARM::LDRD_POST:
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder)))
+ return MCDisassembler::Fail;
break;
- case 15:
- switch (PW) {
- case 2: // Offset
- return ARM::LDRSH;
- case 3: // Pre-indexed
- return ARM::LDRSH_PRE;
- case 0: // Post-indexed
- return ARM::LDRSH_POST;
+ default:
+ break;
+ }
+
+ if (writeback) {
+ // On loads, the writeback operand comes after Rt.
+ switch (Inst.getOpcode()) {
+ case ARM::LDRD:
+ case ARM::LDRD_PRE:
+ case ARM::LDRD_POST:
+ case ARM::LDRH:
+ case ARM::LDRH_PRE:
+ case ARM::LDRH_POST:
+ case ARM::LDRSH:
+ case ARM::LDRSH_PRE:
+ case ARM::LDRSH_POST:
+ case ARM::LDRSB:
+ case ARM::LDRSB_PRE:
+ case ARM::LDRSB_POST:
+ case ARM::LDRHTr:
+ case ARM::LDRSBTr:
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ if (type) {
+ Inst.addOperand(MCOperand::CreateReg(0));
+ Inst.addOperand(MCOperand::CreateImm(U | (imm << 4) | Rm));
+ } else {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(U));
+ }
+
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeRFEInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned mode = fieldFromInstruction32(Insn, 23, 2);
+
+ switch (mode) {
+ case 0:
+ mode = ARM_AM::da;
+ break;
+ case 1:
+ mode = ARM_AM::ia;
+ break;
+ case 2:
+ mode = ARM_AM::db;
+ break;
+ case 3:
+ mode = ARM_AM::ib;
+ break;
+ }
+
+ Inst.addOperand(MCOperand::CreateImm(mode));
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeMemMultipleWritebackInstruction(llvm::MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+ unsigned reglist = fieldFromInstruction32(Insn, 0, 16);
+
+ if (pred == 0xF) {
+ switch (Inst.getOpcode()) {
+ case ARM::LDMDA:
+ Inst.setOpcode(ARM::RFEDA);
+ break;
+ case ARM::LDMDA_UPD:
+ Inst.setOpcode(ARM::RFEDA_UPD);
+ break;
+ case ARM::LDMDB:
+ Inst.setOpcode(ARM::RFEDB);
+ break;
+ case ARM::LDMDB_UPD:
+ Inst.setOpcode(ARM::RFEDB_UPD);
+ break;
+ case ARM::LDMIA:
+ Inst.setOpcode(ARM::RFEIA);
+ break;
+ case ARM::LDMIA_UPD:
+ Inst.setOpcode(ARM::RFEIA_UPD);
+ break;
+ case ARM::LDMIB:
+ Inst.setOpcode(ARM::RFEIB);
+ break;
+ case ARM::LDMIB_UPD:
+ Inst.setOpcode(ARM::RFEIB_UPD);
+ break;
+ case ARM::STMDA:
+ Inst.setOpcode(ARM::SRSDA);
+ break;
+ case ARM::STMDA_UPD:
+ Inst.setOpcode(ARM::SRSDA_UPD);
+ break;
+ case ARM::STMDB:
+ Inst.setOpcode(ARM::SRSDB);
+ break;
+ case ARM::STMDB_UPD:
+ Inst.setOpcode(ARM::SRSDB_UPD);
+ break;
+ case ARM::STMIA:
+ Inst.setOpcode(ARM::SRSIA);
+ break;
+ case ARM::STMIA_UPD:
+ Inst.setOpcode(ARM::SRSIA_UPD);
+ break;
+ case ARM::STMIB:
+ Inst.setOpcode(ARM::SRSIB);
+ break;
+ case ARM::STMIB_UPD:
+ Inst.setOpcode(ARM::SRSIB_UPD);
+ break;
default:
- break; // fallthrough
- }
+ if (!Check(S, MCDisassembler::Fail)) return MCDisassembler::Fail;
+ }
+
+ // For stores (which become SRS's, the only operand is the mode.
+ if (fieldFromInstruction32(Insn, 20, 1) == 0) {
+ Inst.addOperand(
+ MCOperand::CreateImm(fieldFromInstruction32(Insn, 0, 4)));
+ return S;
+ }
+
+ return DecodeRFEInstruction(Inst, Insn, Address, Decoder);
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail; // Tied
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeRegListOperand(Inst, reglist, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeCPSInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned imod = fieldFromInstruction32(Insn, 18, 2);
+ unsigned M = fieldFromInstruction32(Insn, 17, 1);
+ unsigned iflags = fieldFromInstruction32(Insn, 6, 3);
+ unsigned mode = fieldFromInstruction32(Insn, 0, 5);
+
+ DecodeStatus S = MCDisassembler::Success;
+
+ // imod == '01' --> UNPREDICTABLE
+ // NOTE: Even though this is technically UNPREDICTABLE, we choose to
+ // return failure here. The '01' imod value is unprintable, so there's
+ // nothing useful we could do even if we returned UNPREDICTABLE.
+
+ if (imod == 1) return MCDisassembler::Fail;
+
+ if (imod && M) {
+ Inst.setOpcode(ARM::CPS3p);
+ Inst.addOperand(MCOperand::CreateImm(imod));
+ Inst.addOperand(MCOperand::CreateImm(iflags));
+ Inst.addOperand(MCOperand::CreateImm(mode));
+ } else if (imod && !M) {
+ Inst.setOpcode(ARM::CPS2p);
+ Inst.addOperand(MCOperand::CreateImm(imod));
+ Inst.addOperand(MCOperand::CreateImm(iflags));
+ if (mode) S = MCDisassembler::SoftFail;
+ } else if (!imod && M) {
+ Inst.setOpcode(ARM::CPS1p);
+ Inst.addOperand(MCOperand::CreateImm(mode));
+ if (iflags) S = MCDisassembler::SoftFail;
+ } else {
+ // imod == '00' && M == '0' --> UNPREDICTABLE
+ Inst.setOpcode(ARM::CPS1p);
+ Inst.addOperand(MCOperand::CreateImm(mode));
+ S = MCDisassembler::SoftFail;
+ }
+
+ return S;
+}
+
+static DecodeStatus DecodeT2CPSInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned imod = fieldFromInstruction32(Insn, 9, 2);
+ unsigned M = fieldFromInstruction32(Insn, 8, 1);
+ unsigned iflags = fieldFromInstruction32(Insn, 5, 3);
+ unsigned mode = fieldFromInstruction32(Insn, 0, 5);
+
+ DecodeStatus S = MCDisassembler::Success;
+
+ // imod == '01' --> UNPREDICTABLE
+ // NOTE: Even though this is technically UNPREDICTABLE, we choose to
+ // return failure here. The '01' imod value is unprintable, so there's
+ // nothing useful we could do even if we returned UNPREDICTABLE.
+
+ if (imod == 1) return MCDisassembler::Fail;
+
+ if (imod && M) {
+ Inst.setOpcode(ARM::t2CPS3p);
+ Inst.addOperand(MCOperand::CreateImm(imod));
+ Inst.addOperand(MCOperand::CreateImm(iflags));
+ Inst.addOperand(MCOperand::CreateImm(mode));
+ } else if (imod && !M) {
+ Inst.setOpcode(ARM::t2CPS2p);
+ Inst.addOperand(MCOperand::CreateImm(imod));
+ Inst.addOperand(MCOperand::CreateImm(iflags));
+ if (mode) S = MCDisassembler::SoftFail;
+ } else if (!imod && M) {
+ Inst.setOpcode(ARM::t2CPS1p);
+ Inst.addOperand(MCOperand::CreateImm(mode));
+ if (iflags) S = MCDisassembler::SoftFail;
+ } else {
+ // imod == '00' && M == '0' --> UNPREDICTABLE
+ Inst.setOpcode(ARM::t2CPS1p);
+ Inst.addOperand(MCOperand::CreateImm(mode));
+ S = MCDisassembler::SoftFail;
+ }
+
+ return S;
+}
+
+static DecodeStatus DecodeT2MOVTWInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 8, 4);
+ unsigned imm = 0;
+
+ imm |= (fieldFromInstruction32(Insn, 0, 8) << 0);
+ imm |= (fieldFromInstruction32(Insn, 12, 3) << 8);
+ imm |= (fieldFromInstruction32(Insn, 16, 4) << 12);
+ imm |= (fieldFromInstruction32(Insn, 26, 1) << 11);
+
+ if (Inst.getOpcode() == ARM::t2MOVTi16)
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ if (!tryAddingSymbolicOperand(Address, imm, false, 4, Inst, Decoder))
+ Inst.addOperand(MCOperand::CreateImm(imm));
+
+ return S;
+}
+
+static DecodeStatus DecodeArmMOVTWInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+ unsigned imm = 0;
+
+ imm |= (fieldFromInstruction32(Insn, 0, 12) << 0);
+ imm |= (fieldFromInstruction32(Insn, 16, 4) << 12);
+
+ if (Inst.getOpcode() == ARM::MOVTi16)
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ if (!tryAddingSymbolicOperand(Address, imm, false, 4, Inst, Decoder))
+ Inst.addOperand(MCOperand::CreateImm(imm));
+
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rn = fieldFromInstruction32(Insn, 0, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 8, 4);
+ unsigned Ra = fieldFromInstruction32(Insn, 12, 4);
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+
+ if (pred == 0xF)
+ return DecodeCPSInstruction(Inst, Insn, Address, Decoder);
+
+ if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Ra, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned add = fieldFromInstruction32(Val, 12, 1);
+ unsigned imm = fieldFromInstruction32(Val, 0, 12);
+ unsigned Rn = fieldFromInstruction32(Val, 13, 4);
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ if (!add) imm *= -1;
+ if (imm == 0 && !add) imm = INT32_MIN;
+ Inst.addOperand(MCOperand::CreateImm(imm));
+ if (Rn == 15)
+ tryAddingPcLoadReferenceComment(Address, Address + imm + 8, Decoder);
+
+ return S;
+}
+
+static DecodeStatus DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Val, 9, 4);
+ unsigned U = fieldFromInstruction32(Val, 8, 1);
+ unsigned imm = fieldFromInstruction32(Val, 0, 8);
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ if (U)
+ Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add, imm)));
+ else
+ Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub, imm)));
+
+ return S;
+}
+
+static DecodeStatus DecodeAddrMode7Operand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ return DecodeGPRRegisterClass(Inst, Val, Address, Decoder);
+}
+
+static DecodeStatus
+DecodeBranchImmInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+ unsigned imm = fieldFromInstruction32(Insn, 0, 24) << 2;
+
+ if (pred == 0xF) {
+ Inst.setOpcode(ARM::BLXi);
+ imm |= fieldFromInstruction32(Insn, 24, 1) << 1;
+ Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(imm)));
+ return S;
+ }
+
+ if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<26>(imm) + 8, true,
+ 4, Inst, Decoder))
+ Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(imm)));
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+
+static DecodeStatus DecodeVCVTImmOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(64 - Val));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeAddrMode6Operand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rm = fieldFromInstruction32(Val, 0, 4);
+ unsigned align = fieldFromInstruction32(Val, 4, 2);
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!align)
+ Inst.addOperand(MCOperand::CreateImm(0));
+ else
+ Inst.addOperand(MCOperand::CreateImm(4 << align));
+
+ return S;
+}
+
+static DecodeStatus DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned wb = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ Rn |= fieldFromInstruction32(Insn, 4, 2) << 4;
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+
+ // First output register
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ // Second output register
+ switch (Inst.getOpcode()) {
+ case ARM::VLD1q8:
+ case ARM::VLD1q16:
+ case ARM::VLD1q32:
+ case ARM::VLD1q64:
+ case ARM::VLD1q8_UPD:
+ case ARM::VLD1q16_UPD:
+ case ARM::VLD1q32_UPD:
+ case ARM::VLD1q64_UPD:
+ case ARM::VLD1d8T:
+ case ARM::VLD1d16T:
+ case ARM::VLD1d32T:
+ case ARM::VLD1d64T:
+ case ARM::VLD1d8T_UPD:
+ case ARM::VLD1d16T_UPD:
+ case ARM::VLD1d32T_UPD:
+ case ARM::VLD1d64T_UPD:
+ case ARM::VLD1d8Q:
+ case ARM::VLD1d16Q:
+ case ARM::VLD1d32Q:
+ case ARM::VLD1d64Q:
+ case ARM::VLD1d8Q_UPD:
+ case ARM::VLD1d16Q_UPD:
+ case ARM::VLD1d32Q_UPD:
+ case ARM::VLD1d64Q_UPD:
+ case ARM::VLD2d8:
+ case ARM::VLD2d16:
+ case ARM::VLD2d32:
+ case ARM::VLD2d8_UPD:
+ case ARM::VLD2d16_UPD:
+ case ARM::VLD2d32_UPD:
+ case ARM::VLD2q8:
+ case ARM::VLD2q16:
+ case ARM::VLD2q32:
+ case ARM::VLD2q8_UPD:
+ case ARM::VLD2q16_UPD:
+ case ARM::VLD2q32_UPD:
+ case ARM::VLD3d8:
+ case ARM::VLD3d16:
+ case ARM::VLD3d32:
+ case ARM::VLD3d8_UPD:
+ case ARM::VLD3d16_UPD:
+ case ARM::VLD3d32_UPD:
+ case ARM::VLD4d8:
+ case ARM::VLD4d16:
+ case ARM::VLD4d32:
+ case ARM::VLD4d8_UPD:
+ case ARM::VLD4d16_UPD:
+ case ARM::VLD4d32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
break;
+ case ARM::VLD2b8:
+ case ARM::VLD2b16:
+ case ARM::VLD2b32:
+ case ARM::VLD2b8_UPD:
+ case ARM::VLD2b16_UPD:
+ case ARM::VLD2b32_UPD:
+ case ARM::VLD3q8:
+ case ARM::VLD3q16:
+ case ARM::VLD3q32:
+ case ARM::VLD3q8_UPD:
+ case ARM::VLD3q16_UPD:
+ case ARM::VLD3q32_UPD:
+ case ARM::VLD4q8:
+ case ARM::VLD4q16:
+ case ARM::VLD4q32:
+ case ARM::VLD4q8_UPD:
+ case ARM::VLD4q16_UPD:
+ case ARM::VLD4q32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
default:
- break; // fallthrough
+ break;
+ }
+
+ // Third output register
+ switch(Inst.getOpcode()) {
+ case ARM::VLD1d8T:
+ case ARM::VLD1d16T:
+ case ARM::VLD1d32T:
+ case ARM::VLD1d64T:
+ case ARM::VLD1d8T_UPD:
+ case ARM::VLD1d16T_UPD:
+ case ARM::VLD1d32T_UPD:
+ case ARM::VLD1d64T_UPD:
+ case ARM::VLD1d8Q:
+ case ARM::VLD1d16Q:
+ case ARM::VLD1d32Q:
+ case ARM::VLD1d64Q:
+ case ARM::VLD1d8Q_UPD:
+ case ARM::VLD1d16Q_UPD:
+ case ARM::VLD1d32Q_UPD:
+ case ARM::VLD1d64Q_UPD:
+ case ARM::VLD2q8:
+ case ARM::VLD2q16:
+ case ARM::VLD2q32:
+ case ARM::VLD2q8_UPD:
+ case ARM::VLD2q16_UPD:
+ case ARM::VLD2q32_UPD:
+ case ARM::VLD3d8:
+ case ARM::VLD3d16:
+ case ARM::VLD3d32:
+ case ARM::VLD3d8_UPD:
+ case ARM::VLD3d16_UPD:
+ case ARM::VLD3d32_UPD:
+ case ARM::VLD4d8:
+ case ARM::VLD4d16:
+ case ARM::VLD4d32:
+ case ARM::VLD4d8_UPD:
+ case ARM::VLD4d16_UPD:
+ case ARM::VLD4d32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ case ARM::VLD3q8:
+ case ARM::VLD3q16:
+ case ARM::VLD3q32:
+ case ARM::VLD3q8_UPD:
+ case ARM::VLD3q16_UPD:
+ case ARM::VLD3q32_UPD:
+ case ARM::VLD4q8:
+ case ARM::VLD4q16:
+ case ARM::VLD4q32:
+ case ARM::VLD4q8_UPD:
+ case ARM::VLD4q16_UPD:
+ case ARM::VLD4q32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ // Fourth output register
+ switch (Inst.getOpcode()) {
+ case ARM::VLD1d8Q:
+ case ARM::VLD1d16Q:
+ case ARM::VLD1d32Q:
+ case ARM::VLD1d64Q:
+ case ARM::VLD1d8Q_UPD:
+ case ARM::VLD1d16Q_UPD:
+ case ARM::VLD1d32Q_UPD:
+ case ARM::VLD1d64Q_UPD:
+ case ARM::VLD2q8:
+ case ARM::VLD2q16:
+ case ARM::VLD2q32:
+ case ARM::VLD2q8_UPD:
+ case ARM::VLD2q16_UPD:
+ case ARM::VLD2q32_UPD:
+ case ARM::VLD4d8:
+ case ARM::VLD4d16:
+ case ARM::VLD4d32:
+ case ARM::VLD4d8_UPD:
+ case ARM::VLD4d16_UPD:
+ case ARM::VLD4d32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ case ARM::VLD4q8:
+ case ARM::VLD4q16:
+ case ARM::VLD4q32:
+ case ARM::VLD4q8_UPD:
+ case ARM::VLD4q16_UPD:
+ case ARM::VLD4q32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ // Writeback operand
+ switch (Inst.getOpcode()) {
+ case ARM::VLD1d8_UPD:
+ case ARM::VLD1d16_UPD:
+ case ARM::VLD1d32_UPD:
+ case ARM::VLD1d64_UPD:
+ case ARM::VLD1q8_UPD:
+ case ARM::VLD1q16_UPD:
+ case ARM::VLD1q32_UPD:
+ case ARM::VLD1q64_UPD:
+ case ARM::VLD1d8T_UPD:
+ case ARM::VLD1d16T_UPD:
+ case ARM::VLD1d32T_UPD:
+ case ARM::VLD1d64T_UPD:
+ case ARM::VLD1d8Q_UPD:
+ case ARM::VLD1d16Q_UPD:
+ case ARM::VLD1d32Q_UPD:
+ case ARM::VLD1d64Q_UPD:
+ case ARM::VLD2d8_UPD:
+ case ARM::VLD2d16_UPD:
+ case ARM::VLD2d32_UPD:
+ case ARM::VLD2q8_UPD:
+ case ARM::VLD2q16_UPD:
+ case ARM::VLD2q32_UPD:
+ case ARM::VLD2b8_UPD:
+ case ARM::VLD2b16_UPD:
+ case ARM::VLD2b32_UPD:
+ case ARM::VLD3d8_UPD:
+ case ARM::VLD3d16_UPD:
+ case ARM::VLD3d32_UPD:
+ case ARM::VLD3q8_UPD:
+ case ARM::VLD3q16_UPD:
+ case ARM::VLD3q32_UPD:
+ case ARM::VLD4d8_UPD:
+ case ARM::VLD4d16_UPD:
+ case ARM::VLD4d32_UPD:
+ case ARM::VLD4q8_UPD:
+ case ARM::VLD4q16_UPD:
+ case ARM::VLD4q32_UPD:
+ if (!Check(S, DecodeGPRRegisterClass(Inst, wb, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ // AddrMode6 Base (register+alignment)
+ if (!Check(S, DecodeAddrMode6Operand(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ // AddrMode6 Offset (register)
+ if (Rm == 0xD)
+ Inst.addOperand(MCOperand::CreateReg(0));
+ else if (Rm != 0xF) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ return S;
+}
+
+static DecodeStatus DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned wb = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ Rn |= fieldFromInstruction32(Insn, 4, 2) << 4;
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+
+ // Writeback Operand
+ switch (Inst.getOpcode()) {
+ case ARM::VST1d8_UPD:
+ case ARM::VST1d16_UPD:
+ case ARM::VST1d32_UPD:
+ case ARM::VST1d64_UPD:
+ case ARM::VST1q8_UPD:
+ case ARM::VST1q16_UPD:
+ case ARM::VST1q32_UPD:
+ case ARM::VST1q64_UPD:
+ case ARM::VST1d8T_UPD:
+ case ARM::VST1d16T_UPD:
+ case ARM::VST1d32T_UPD:
+ case ARM::VST1d64T_UPD:
+ case ARM::VST1d8Q_UPD:
+ case ARM::VST1d16Q_UPD:
+ case ARM::VST1d32Q_UPD:
+ case ARM::VST1d64Q_UPD:
+ case ARM::VST2d8_UPD:
+ case ARM::VST2d16_UPD:
+ case ARM::VST2d32_UPD:
+ case ARM::VST2q8_UPD:
+ case ARM::VST2q16_UPD:
+ case ARM::VST2q32_UPD:
+ case ARM::VST2b8_UPD:
+ case ARM::VST2b16_UPD:
+ case ARM::VST2b32_UPD:
+ case ARM::VST3d8_UPD:
+ case ARM::VST3d16_UPD:
+ case ARM::VST3d32_UPD:
+ case ARM::VST3q8_UPD:
+ case ARM::VST3q16_UPD:
+ case ARM::VST3q32_UPD:
+ case ARM::VST4d8_UPD:
+ case ARM::VST4d16_UPD:
+ case ARM::VST4d32_UPD:
+ case ARM::VST4q8_UPD:
+ case ARM::VST4q16_UPD:
+ case ARM::VST4q32_UPD:
+ if (!Check(S, DecodeGPRRegisterClass(Inst, wb, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ // AddrMode6 Base (register+alignment)
+ if (!Check(S, DecodeAddrMode6Operand(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ // AddrMode6 Offset (register)
+ if (Rm == 0xD)
+ Inst.addOperand(MCOperand::CreateReg(0));
+ else if (Rm != 0xF) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ // First input register
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ // Second input register
+ switch (Inst.getOpcode()) {
+ case ARM::VST1q8:
+ case ARM::VST1q16:
+ case ARM::VST1q32:
+ case ARM::VST1q64:
+ case ARM::VST1q8_UPD:
+ case ARM::VST1q16_UPD:
+ case ARM::VST1q32_UPD:
+ case ARM::VST1q64_UPD:
+ case ARM::VST1d8T:
+ case ARM::VST1d16T:
+ case ARM::VST1d32T:
+ case ARM::VST1d64T:
+ case ARM::VST1d8T_UPD:
+ case ARM::VST1d16T_UPD:
+ case ARM::VST1d32T_UPD:
+ case ARM::VST1d64T_UPD:
+ case ARM::VST1d8Q:
+ case ARM::VST1d16Q:
+ case ARM::VST1d32Q:
+ case ARM::VST1d64Q:
+ case ARM::VST1d8Q_UPD:
+ case ARM::VST1d16Q_UPD:
+ case ARM::VST1d32Q_UPD:
+ case ARM::VST1d64Q_UPD:
+ case ARM::VST2d8:
+ case ARM::VST2d16:
+ case ARM::VST2d32:
+ case ARM::VST2d8_UPD:
+ case ARM::VST2d16_UPD:
+ case ARM::VST2d32_UPD:
+ case ARM::VST2q8:
+ case ARM::VST2q16:
+ case ARM::VST2q32:
+ case ARM::VST2q8_UPD:
+ case ARM::VST2q16_UPD:
+ case ARM::VST2q32_UPD:
+ case ARM::VST3d8:
+ case ARM::VST3d16:
+ case ARM::VST3d32:
+ case ARM::VST3d8_UPD:
+ case ARM::VST3d16_UPD:
+ case ARM::VST3d32_UPD:
+ case ARM::VST4d8:
+ case ARM::VST4d16:
+ case ARM::VST4d32:
+ case ARM::VST4d8_UPD:
+ case ARM::VST4d16_UPD:
+ case ARM::VST4d32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ case ARM::VST2b8:
+ case ARM::VST2b16:
+ case ARM::VST2b32:
+ case ARM::VST2b8_UPD:
+ case ARM::VST2b16_UPD:
+ case ARM::VST2b32_UPD:
+ case ARM::VST3q8:
+ case ARM::VST3q16:
+ case ARM::VST3q32:
+ case ARM::VST3q8_UPD:
+ case ARM::VST3q16_UPD:
+ case ARM::VST3q32_UPD:
+ case ARM::VST4q8:
+ case ARM::VST4q16:
+ case ARM::VST4q32:
+ case ARM::VST4q8_UPD:
+ case ARM::VST4q16_UPD:
+ case ARM::VST4q32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ // Third input register
+ switch (Inst.getOpcode()) {
+ case ARM::VST1d8T:
+ case ARM::VST1d16T:
+ case ARM::VST1d32T:
+ case ARM::VST1d64T:
+ case ARM::VST1d8T_UPD:
+ case ARM::VST1d16T_UPD:
+ case ARM::VST1d32T_UPD:
+ case ARM::VST1d64T_UPD:
+ case ARM::VST1d8Q:
+ case ARM::VST1d16Q:
+ case ARM::VST1d32Q:
+ case ARM::VST1d64Q:
+ case ARM::VST1d8Q_UPD:
+ case ARM::VST1d16Q_UPD:
+ case ARM::VST1d32Q_UPD:
+ case ARM::VST1d64Q_UPD:
+ case ARM::VST2q8:
+ case ARM::VST2q16:
+ case ARM::VST2q32:
+ case ARM::VST2q8_UPD:
+ case ARM::VST2q16_UPD:
+ case ARM::VST2q32_UPD:
+ case ARM::VST3d8:
+ case ARM::VST3d16:
+ case ARM::VST3d32:
+ case ARM::VST3d8_UPD:
+ case ARM::VST3d16_UPD:
+ case ARM::VST3d32_UPD:
+ case ARM::VST4d8:
+ case ARM::VST4d16:
+ case ARM::VST4d32:
+ case ARM::VST4d8_UPD:
+ case ARM::VST4d16_UPD:
+ case ARM::VST4d32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ case ARM::VST3q8:
+ case ARM::VST3q16:
+ case ARM::VST3q32:
+ case ARM::VST3q8_UPD:
+ case ARM::VST3q16_UPD:
+ case ARM::VST3q32_UPD:
+ case ARM::VST4q8:
+ case ARM::VST4q16:
+ case ARM::VST4q32:
+ case ARM::VST4q8_UPD:
+ case ARM::VST4q16_UPD:
+ case ARM::VST4q32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ // Fourth input register
+ switch (Inst.getOpcode()) {
+ case ARM::VST1d8Q:
+ case ARM::VST1d16Q:
+ case ARM::VST1d32Q:
+ case ARM::VST1d64Q:
+ case ARM::VST1d8Q_UPD:
+ case ARM::VST1d16Q_UPD:
+ case ARM::VST1d32Q_UPD:
+ case ARM::VST1d64Q_UPD:
+ case ARM::VST2q8:
+ case ARM::VST2q16:
+ case ARM::VST2q32:
+ case ARM::VST2q8_UPD:
+ case ARM::VST2q16_UPD:
+ case ARM::VST2q32_UPD:
+ case ARM::VST4d8:
+ case ARM::VST4d16:
+ case ARM::VST4d32:
+ case ARM::VST4d8_UPD:
+ case ARM::VST4d16_UPD:
+ case ARM::VST4d32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ case ARM::VST4q8:
+ case ARM::VST4q16:
+ case ARM::VST4q32:
+ case ARM::VST4q8_UPD:
+ case ARM::VST4q16_UPD:
+ case ARM::VST4q32_UPD:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ return S;
+}
+
+static DecodeStatus DecodeVLD1DupInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned align = fieldFromInstruction32(Insn, 4, 1);
+ unsigned size = fieldFromInstruction32(Insn, 6, 2);
+ unsigned regs = fieldFromInstruction32(Insn, 5, 1) + 1;
+
+ align *= (1 << size);
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (regs == 2) {
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+ if (Rm != 0xF) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(align));
+
+ if (Rm == 0xD)
+ Inst.addOperand(MCOperand::CreateReg(0));
+ else if (Rm != 0xF) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ return S;
+}
+
+static DecodeStatus DecodeVLD2DupInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned align = fieldFromInstruction32(Insn, 4, 1);
+ unsigned size = 1 << fieldFromInstruction32(Insn, 6, 2);
+ unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
+ align *= 2*size;
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (Rm != 0xF) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(align));
+
+ if (Rm == 0xD)
+ Inst.addOperand(MCOperand::CreateReg(0));
+ else if (Rm != 0xF) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ return S;
+}
+
+static DecodeStatus DecodeVLD3DupInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (Rm != 0xF) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(0));
+
+ if (Rm == 0xD)
+ Inst.addOperand(MCOperand::CreateReg(0));
+ else if (Rm != 0xF) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ return S;
+}
+
+static DecodeStatus DecodeVLD4DupInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned size = fieldFromInstruction32(Insn, 6, 2);
+ unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
+ unsigned align = fieldFromInstruction32(Insn, 4, 1);
+
+ if (size == 0x3) {
+ size = 4;
+ align = 16;
+ } else {
+ if (size == 2) {
+ size = 1 << size;
+ align *= 8;
+ } else {
+ size = 1 << size;
+ align *= 4*size;
}
}
-AutoGenedDecoder:
- // Calling the auto-generated decoder function.
- return decodeInstruction(insn);
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rd+3*inc)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (Rm != 0xF) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(align));
+
+ if (Rm == 0xD)
+ Inst.addOperand(MCOperand::CreateReg(0));
+ else if (Rm != 0xF) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ return S;
}
-// Helper function for special case handling of LDR (literal) and friends.
-// See, for example, A6.3.7 Load word: Table A6-18 Load word.
-// See A8.6.57 T3, T4 & A8.6.60 T2 and friends for why we morphed the opcode
-// before returning it.
-static unsigned T2Morph2LoadLiteral(unsigned Opcode) {
- switch (Opcode) {
- default:
- return Opcode; // Return unmorphed opcode.
+static DecodeStatus
+DecodeNEONModImmInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned imm = fieldFromInstruction32(Insn, 0, 4);
+ imm |= fieldFromInstruction32(Insn, 16, 3) << 4;
+ imm |= fieldFromInstruction32(Insn, 24, 1) << 7;
+ imm |= fieldFromInstruction32(Insn, 8, 4) << 8;
+ imm |= fieldFromInstruction32(Insn, 5, 1) << 12;
+ unsigned Q = fieldFromInstruction32(Insn, 6, 1);
+
+ if (Q) {
+ if (!Check(S, DecodeQPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ } else {
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ Inst.addOperand(MCOperand::CreateImm(imm));
+
+ switch (Inst.getOpcode()) {
+ case ARM::VORRiv4i16:
+ case ARM::VORRiv2i32:
+ case ARM::VBICiv4i16:
+ case ARM::VBICiv2i32:
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ case ARM::VORRiv8i16:
+ case ARM::VORRiv4i32:
+ case ARM::VBICiv8i16:
+ case ARM::VBICiv4i32:
+ if (!Check(S, DecodeQPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ return S;
+}
+
+static DecodeStatus DecodeVSHLMaxInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ Rm |= fieldFromInstruction32(Insn, 5, 1) << 4;
+ unsigned size = fieldFromInstruction32(Insn, 18, 2);
+
+ if (!Check(S, DecodeQPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(8 << size));
+
+ return S;
+}
+
+static DecodeStatus DecodeShiftRight8Imm(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(8 - Val));
+ return MCDisassembler::Success;
+}
- case ARM::t2LDR_POST: case ARM::t2LDR_PRE:
- case ARM::t2LDRi12: case ARM::t2LDRi8:
- case ARM::t2LDRs: case ARM::t2LDRT:
- return ARM::t2LDRpci;
+static DecodeStatus DecodeShiftRight16Imm(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(16 - Val));
+ return MCDisassembler::Success;
+}
- case ARM::t2LDRB_POST: case ARM::t2LDRB_PRE:
- case ARM::t2LDRBi12: case ARM::t2LDRBi8:
- case ARM::t2LDRBs: case ARM::t2LDRBT:
- return ARM::t2LDRBpci;
+static DecodeStatus DecodeShiftRight32Imm(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(32 - Val));
+ return MCDisassembler::Success;
+}
- case ARM::t2LDRH_POST: case ARM::t2LDRH_PRE:
- case ARM::t2LDRHi12: case ARM::t2LDRHi8:
- case ARM::t2LDRHs: case ARM::t2LDRHT:
- return ARM::t2LDRHpci;
+static DecodeStatus DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(64 - Val));
+ return MCDisassembler::Success;
+}
- case ARM::t2LDRSB_POST: case ARM::t2LDRSB_PRE:
- case ARM::t2LDRSBi12: case ARM::t2LDRSBi8:
- case ARM::t2LDRSBs: case ARM::t2LDRSBT:
- return ARM::t2LDRSBpci;
+static DecodeStatus DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ Rn |= fieldFromInstruction32(Insn, 7, 1) << 4;
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ Rm |= fieldFromInstruction32(Insn, 5, 1) << 4;
+ unsigned op = fieldFromInstruction32(Insn, 6, 1);
+ unsigned length = fieldFromInstruction32(Insn, 8, 2) + 1;
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (op) {
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail; // Writeback
+ }
- case ARM::t2LDRSH_POST: case ARM::t2LDRSH_PRE:
- case ARM::t2LDRSHi12: case ARM::t2LDRSHi8:
- case ARM::t2LDRSHs: case ARM::t2LDRSHT:
- return ARM::t2LDRSHpci;
+ for (unsigned i = 0; i < length; ++i) {
+ if (!Check(S, DecodeDPRRegisterClass(Inst, (Rn+i)%32, Address, Decoder)))
+ return MCDisassembler::Fail;
}
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
}
-// Helper function for special case handling of PLD (literal) and friends.
-// See A8.6.117 T1 & T2 and friends for why we morphed the opcode
-// before returning it.
-static unsigned T2Morph2PLDLiteral(unsigned Opcode) {
- switch (Opcode) {
- default:
- return Opcode; // Return unmorphed opcode.
-
- case ARM::t2PLDi8: case ARM::t2PLDs:
- case ARM::t2PLDWi12: case ARM::t2PLDWi8:
- case ARM::t2PLDWs:
- return ARM::t2PLDi12;
-
- case ARM::t2PLIi8: case ARM::t2PLIs:
- return ARM::t2PLIi12;
- }
-}
-
-/// decodeThumbSideEffect is a decorator function which can potentially twiddle
-/// the instruction or morph the returned opcode under Thumb2.
-///
-/// First it checks whether the insn is a NEON or VFP instr; if true, bit
-/// twiddling could be performed on insn to turn it into an ARM NEON/VFP
-/// equivalent instruction and decodeInstruction is called with the transformed
-/// insn.
-///
-/// Next, there is special handling for Load byte/halfword/word instruction by
-/// checking whether Rn=0b1111 and call T2Morph2LoadLiteral() on the decoded
-/// Thumb2 instruction. See comments below for further details.
-///
-/// Finally, one last check is made to see whether the insn is a NEON/VFP and
-/// decodeInstruction(insn) is invoked on the original insn.
-///
-/// Otherwise, decodeThumbInstruction is called with the original insn.
-static unsigned decodeThumbSideEffect(bool IsThumb2, unsigned &insn) {
- if (IsThumb2) {
- uint16_t op1 = slice(insn, 28, 27);
- uint16_t op2 = slice(insn, 26, 20);
-
- // A6.3 32-bit Thumb instruction encoding
- // Table A6-9 32-bit Thumb instruction encoding
-
- // The coprocessor instructions of interest are transformed to their ARM
- // equivalents.
-
- // --------- Transform Begin Marker ---------
- if ((op1 == 1 || op1 == 3) && slice(op2, 6, 4) == 7) {
- // A7.4 Advanced SIMD data-processing instructions
- // U bit of Thumb corresponds to Inst{24} of ARM.
- uint16_t U = slice(op1, 1, 1);
-
- // Inst{28-24} of ARM = {1,0,0,1,U};
- uint16_t bits28_24 = 9 << 1 | U;
- DEBUG(showBitVector(errs(), insn));
- setSlice(insn, 28, 24, bits28_24);
- return decodeInstruction(insn);
+static DecodeStatus DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned dst = fieldFromInstruction16(Insn, 8, 3);
+ unsigned imm = fieldFromInstruction16(Insn, 0, 8);
+
+ if (!Check(S, DecodetGPRRegisterClass(Inst, dst, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ switch(Inst.getOpcode()) {
+ default:
+ return MCDisassembler::Fail;
+ case ARM::tADR:
+ break; // tADR does not explicitly represent the PC as an operand.
+ case ARM::tADDrSPi:
+ Inst.addOperand(MCOperand::CreateReg(ARM::SP));
+ break;
+ }
+
+ Inst.addOperand(MCOperand::CreateImm(imm));
+ return S;
+}
+
+static DecodeStatus DecodeThumbBROperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(SignExtend32<12>(Val << 1)));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeT2BROperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(SignExtend32<21>(Val)));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeThumbCmpBROperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(SignExtend32<7>(Val << 1)));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeThumbAddrModeRR(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Val, 0, 3);
+ unsigned Rm = fieldFromInstruction32(Val, 3, 3);
+
+ if (!Check(S, DecodetGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodetGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeThumbAddrModeIS(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Val, 0, 3);
+ unsigned imm = fieldFromInstruction32(Val, 3, 5);
+
+ if (!Check(S, DecodetGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(imm));
+
+ return S;
+}
+
+static DecodeStatus DecodeThumbAddrModePC(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ unsigned imm = Val << 2;
+
+ Inst.addOperand(MCOperand::CreateImm(imm));
+ tryAddingPcLoadReferenceComment(Address, (Address & ~2u) + imm + 4, Decoder);
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeThumbAddrModeSP(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateReg(ARM::SP));
+ Inst.addOperand(MCOperand::CreateImm(Val));
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeT2AddrModeSOReg(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Val, 6, 4);
+ unsigned Rm = fieldFromInstruction32(Val, 2, 4);
+ unsigned imm = fieldFromInstruction32(Val, 0, 2);
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(imm));
+
+ return S;
+}
+
+static DecodeStatus DecodeT2LoadShift(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ switch (Inst.getOpcode()) {
+ case ARM::t2PLDs:
+ case ARM::t2PLDWs:
+ case ARM::t2PLIs:
+ break;
+ default: {
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
}
+ }
- if (op1 == 3 && slice(op2, 6, 4) == 1 && slice(op2, 0, 0) == 0) {
- // A7.7 Advanced SIMD element or structure load/store instructions
- // Inst{27-24} of Thumb = 0b1001
- // Inst{27-24} of ARM = 0b0100
- DEBUG(showBitVector(errs(), insn));
- setSlice(insn, 27, 24, 4);
- return decodeInstruction(insn);
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ if (Rn == 0xF) {
+ switch (Inst.getOpcode()) {
+ case ARM::t2LDRBs:
+ Inst.setOpcode(ARM::t2LDRBpci);
+ break;
+ case ARM::t2LDRHs:
+ Inst.setOpcode(ARM::t2LDRHpci);
+ break;
+ case ARM::t2LDRSHs:
+ Inst.setOpcode(ARM::t2LDRSHpci);
+ break;
+ case ARM::t2LDRSBs:
+ Inst.setOpcode(ARM::t2LDRSBpci);
+ break;
+ case ARM::t2PLDs:
+ Inst.setOpcode(ARM::t2PLDi12);
+ Inst.addOperand(MCOperand::CreateReg(ARM::PC));
+ break;
+ default:
+ return MCDisassembler::Fail;
}
- // --------- Transform End Marker ---------
-
- unsigned unmorphed = decodeThumbInstruction(insn);
-
- // See, for example, A6.3.7 Load word: Table A6-18 Load word.
- // See A8.6.57 T3, T4 & A8.6.60 T2 and friends for why we morphed the opcode
- // before returning it to our caller.
- if (op1 == 3 && slice(op2, 6, 5) == 0 && slice(op2, 0, 0) == 1
- && slice(insn, 19, 16) == 15) {
- unsigned morphed = T2Morph2LoadLiteral(unmorphed);
- if (morphed != unmorphed)
- return morphed;
+
+ int imm = fieldFromInstruction32(Insn, 0, 12);
+ if (!fieldFromInstruction32(Insn, 23, 1)) imm *= -1;
+ Inst.addOperand(MCOperand::CreateImm(imm));
+
+ return S;
+ }
+
+ unsigned addrmode = fieldFromInstruction32(Insn, 4, 2);
+ addrmode |= fieldFromInstruction32(Insn, 0, 4) << 2;
+ addrmode |= fieldFromInstruction32(Insn, 16, 4) << 6;
+ if (!Check(S, DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeT2Imm8S4(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ int imm = Val & 0xFF;
+ if (!(Val & 0x100)) imm *= -1;
+ Inst.addOperand(MCOperand::CreateImm(imm << 2));
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Val, 9, 4);
+ unsigned imm = fieldFromInstruction32(Val, 0, 9);
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeT2Imm8S4(Inst, imm, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeT2AddrModeImm0_1020s4(llvm::MCInst &Inst,unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Val, 8, 4);
+ unsigned imm = fieldFromInstruction32(Val, 0, 8);
+
+ if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ Inst.addOperand(MCOperand::CreateImm(imm));
+
+ return S;
+}
+
+static DecodeStatus DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ int imm = Val & 0xFF;
+ if (Val == 0)
+ imm = INT32_MIN;
+ else if (!(Val & 0x100))
+ imm *= -1;
+ Inst.addOperand(MCOperand::CreateImm(imm));
+
+ return MCDisassembler::Success;
+}
+
+
+static DecodeStatus DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Val, 9, 4);
+ unsigned imm = fieldFromInstruction32(Val, 0, 9);
+
+ // Some instructions always use an additive offset.
+ switch (Inst.getOpcode()) {
+ case ARM::t2LDRT:
+ case ARM::t2LDRBT:
+ case ARM::t2LDRHT:
+ case ARM::t2LDRSBT:
+ case ARM::t2LDRSHT:
+ case ARM::t2STRT:
+ case ARM::t2STRBT:
+ case ARM::t2STRHT:
+ imm |= 0x100;
+ break;
+ default:
+ break;
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeT2Imm8(Inst, imm, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeT2LdStPre(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned addr = fieldFromInstruction32(Insn, 0, 8);
+ addr |= fieldFromInstruction32(Insn, 9, 1) << 8;
+ addr |= Rn << 9;
+ unsigned load = fieldFromInstruction32(Insn, 20, 1);
+
+ if (!load) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ if (load) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ if (!Check(S, DecodeT2AddrModeImm8(Inst, addr, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Val, 13, 4);
+ unsigned imm = fieldFromInstruction32(Val, 0, 12);
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(imm));
+
+ return S;
+}
+
+
+static DecodeStatus DecodeThumbAddSPImm(llvm::MCInst &Inst, uint16_t Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned imm = fieldFromInstruction16(Insn, 0, 7);
+
+ Inst.addOperand(MCOperand::CreateReg(ARM::SP));
+ Inst.addOperand(MCOperand::CreateReg(ARM::SP));
+ Inst.addOperand(MCOperand::CreateImm(imm));
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ if (Inst.getOpcode() == ARM::tADDrSP) {
+ unsigned Rdm = fieldFromInstruction16(Insn, 0, 3);
+ Rdm |= fieldFromInstruction16(Insn, 7, 1) << 3;
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateReg(ARM::SP));
+ } else if (Inst.getOpcode() == ARM::tADDspr) {
+ unsigned Rm = fieldFromInstruction16(Insn, 3, 4);
+
+ Inst.addOperand(MCOperand::CreateReg(ARM::SP));
+ Inst.addOperand(MCOperand::CreateReg(ARM::SP));
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+
+ return S;
+}
+
+static DecodeStatus DecodeThumbCPS(llvm::MCInst &Inst, uint16_t Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned imod = fieldFromInstruction16(Insn, 4, 1) | 0x2;
+ unsigned flags = fieldFromInstruction16(Insn, 0, 3);
+
+ Inst.addOperand(MCOperand::CreateImm(imod));
+ Inst.addOperand(MCOperand::CreateImm(flags));
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned add = fieldFromInstruction32(Insn, 4, 1);
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(add));
+
+ return S;
+}
+
+static DecodeStatus DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ if (!tryAddingSymbolicOperand(Address,
+ (Address & ~2u) + SignExtend32<22>(Val << 1) + 4,
+ true, 4, Inst, Decoder))
+ Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeCoprocessor(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ if (Val == 0xA || Val == 0xB)
+ return MCDisassembler::Fail;
+
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus
+DecodeThumbTableBranch(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+
+ if (Rn == ARM::SP) S = MCDisassembler::SoftFail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ return S;
+}
+
+static DecodeStatus
+DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned pred = fieldFromInstruction32(Insn, 22, 4);
+ if (pred == 0xE || pred == 0xF) {
+ unsigned opc = fieldFromInstruction32(Insn, 4, 28);
+ switch (opc) {
+ default:
+ return MCDisassembler::Fail;
+ case 0xf3bf8f4:
+ Inst.setOpcode(ARM::t2DSB);
+ break;
+ case 0xf3bf8f5:
+ Inst.setOpcode(ARM::t2DMB);
+ break;
+ case 0xf3bf8f6:
+ Inst.setOpcode(ARM::t2ISB);
+ break;
}
- // See, for example, A8.6.117 PLD,PLDW (immediate) T1 & T2, and friends for
- // why we morphed the opcode before returning it to our caller.
- if (slice(insn, 31, 25) == 0x7C && slice(insn, 15, 12) == 0xF
- && slice(insn, 22, 22) == 0 && slice(insn, 20, 20) == 1
- && slice(insn, 19, 16) == 15) {
- unsigned morphed = T2Morph2PLDLiteral(unmorphed);
- if (morphed != unmorphed)
- return morphed;
+ unsigned imm = fieldFromInstruction32(Insn, 0, 4);
+ return DecodeMemBarrierOption(Inst, imm, Address, Decoder);
+ }
+
+ unsigned brtarget = fieldFromInstruction32(Insn, 0, 11) << 1;
+ brtarget |= fieldFromInstruction32(Insn, 11, 1) << 19;
+ brtarget |= fieldFromInstruction32(Insn, 13, 1) << 18;
+ brtarget |= fieldFromInstruction32(Insn, 16, 6) << 12;
+ brtarget |= fieldFromInstruction32(Insn, 26, 1) << 20;
+
+ if (!Check(S, DecodeT2BROperand(Inst, brtarget, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+// Decode a shifted immediate operand. These basically consist
+// of an 8-bit value, and a 4-bit directive that specifies either
+// a splat operation or a rotation.
+static DecodeStatus DecodeT2SOImm(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ unsigned ctrl = fieldFromInstruction32(Val, 10, 2);
+ if (ctrl == 0) {
+ unsigned byte = fieldFromInstruction32(Val, 8, 2);
+ unsigned imm = fieldFromInstruction32(Val, 0, 8);
+ switch (byte) {
+ case 0:
+ Inst.addOperand(MCOperand::CreateImm(imm));
+ break;
+ case 1:
+ Inst.addOperand(MCOperand::CreateImm((imm << 16) | imm));
+ break;
+ case 2:
+ Inst.addOperand(MCOperand::CreateImm((imm << 24) | (imm << 8)));
+ break;
+ case 3:
+ Inst.addOperand(MCOperand::CreateImm((imm << 24) | (imm << 16) |
+ (imm << 8) | imm));
+ break;
}
+ } else {
+ unsigned unrot = fieldFromInstruction32(Val, 0, 7) | 0x80;
+ unsigned rot = fieldFromInstruction32(Val, 7, 5);
+ unsigned imm = (unrot >> rot) | (unrot << ((32-rot)&31));
+ Inst.addOperand(MCOperand::CreateImm(imm));
+ }
- // One last check for NEON/VFP instructions.
- if ((op1 == 1 || op1 == 3) && slice(op2, 6, 6) == 1)
- return decodeInstruction(insn);
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus
+DecodeThumbBCCTargetOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder){
+ Inst.addOperand(MCOperand::CreateImm(Val << 1));
+ return MCDisassembler::Success;
+}
- // Fall through.
+static DecodeStatus DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder){
+ Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeMemBarrierOption(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ switch (Val) {
+ default:
+ return MCDisassembler::Fail;
+ case 0xF: // SY
+ case 0xE: // ST
+ case 0xB: // ISH
+ case 0xA: // ISHST
+ case 0x7: // NSH
+ case 0x6: // NSHST
+ case 0x3: // OSH
+ case 0x2: // OSHST
+ break;
}
- return decodeThumbInstruction(insn);
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ return MCDisassembler::Success;
}
-//
-// Public interface for the disassembler
-//
+static DecodeStatus DecodeMSRMask(llvm::MCInst &Inst, unsigned Val,
+ uint64_t Address, const void *Decoder) {
+ if (!Val) return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ return MCDisassembler::Success;
+}
-bool ARMDisassembler::getInstruction(MCInst &MI,
- uint64_t &Size,
- const MemoryObject &Region,
- uint64_t Address,
- raw_ostream &os) const {
- // The machine instruction.
- uint32_t insn;
- uint8_t bytes[4];
+static DecodeStatus DecodeDoubleRegLoad(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
- // We want to read exactly 4 bytes of data.
- if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1)
- return false;
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
- // Encoded as a small-endian 32-bit word in the stream.
- insn = (bytes[3] << 24) |
- (bytes[2] << 16) |
- (bytes[1] << 8) |
- (bytes[0] << 0);
-
- unsigned Opcode = decodeARMInstruction(insn);
- ARMFormat Format = ARMFormats[Opcode];
- Size = 4;
-
- DEBUG({
- errs() << "\nOpcode=" << Opcode << " Name=" <<ARMUtils::OpcodeName(Opcode)
- << " Format=" << stringForARMFormat(Format) << '(' << (int)Format
- << ")\n";
- showBitVector(errs(), insn);
- });
-
- OwningPtr<ARMBasicMCBuilder> Builder(CreateMCBuilder(Opcode, Format));
- if (!Builder)
- return false;
+ if ((Rt & 1) || Rt == 0xE || Rn == 0xF) return MCDisassembler::Fail;
- Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(),
- getDisInfoBlock(), getMCContext(),
- Address);
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
- if (!Builder->Build(MI, insn))
- return false;
+ return S;
+}
- return true;
+
+static DecodeStatus DecodeDoubleRegStore(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder){
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ unsigned Rt = fieldFromInstruction32(Insn, 0, 4);
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ if ((Rt & 1) || Rt == 0xE || Rn == 0xF) return MCDisassembler::Fail;
+ if (Rd == Rn || Rd == Rt || Rd == Rt+1) return MCDisassembler::Fail;
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
}
-bool ThumbDisassembler::getInstruction(MCInst &MI,
- uint64_t &Size,
- const MemoryObject &Region,
- uint64_t Address,
- raw_ostream &os) const {
- // The Thumb instruction stream is a sequence of halfwords.
-
- // This represents the first halfword as well as the machine instruction
- // passed to decodeThumbInstruction(). For 16-bit Thumb instruction, the top
- // halfword of insn is 0x00 0x00; otherwise, the first halfword is moved to
- // the top half followed by the second halfword.
- unsigned insn = 0;
- // Possible second halfword.
- uint16_t insn1 = 0;
-
- // A6.1 Thumb instruction set encoding
- //
- // If bits [15:11] of the halfword being decoded take any of the following
- // values, the halfword is the first halfword of a 32-bit instruction:
- // o 0b11101
- // o 0b11110
- // o 0b11111.
- //
- // Otherwise, the halfword is a 16-bit instruction.
-
- // Read 2 bytes of data first.
- uint8_t bytes[2];
- if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1)
- return false;
+static DecodeStatus DecodeLDRPreImm(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned imm = fieldFromInstruction32(Insn, 0, 12);
+ imm |= fieldFromInstruction32(Insn, 16, 4) << 13;
+ imm |= fieldFromInstruction32(Insn, 23, 1) << 12;
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+
+ if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail;
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeAddrModeImm12Operand(Inst, imm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
- // Encoded as a small-endian 16-bit halfword in the stream.
- insn = (bytes[1] << 8) | bytes[0];
- unsigned bits15_11 = slice(insn, 15, 11);
- bool IsThumb2 = false;
+static DecodeStatus DecodeLDRPreReg(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned imm = fieldFromInstruction32(Insn, 0, 12);
+ imm |= fieldFromInstruction32(Insn, 16, 4) << 13;
+ imm |= fieldFromInstruction32(Insn, 23, 1) << 12;
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+
+ if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail;
+ if (Rm == 0xF) S = MCDisassembler::SoftFail;
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeSORegMemOperand(Inst, imm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
- // 32-bit instructions if the bits [15:11] of the halfword matches
- // { 0b11101 /* 0x1D */, 0b11110 /* 0x1E */, ob11111 /* 0x1F */ }.
- if (bits15_11 == 0x1D || bits15_11 == 0x1E || bits15_11 == 0x1F) {
- IsThumb2 = true;
- if (Region.readBytes(Address + 2, 2, (uint8_t*)bytes, NULL) == -1)
- return false;
- // Encoded as a small-endian 16-bit halfword in the stream.
- insn1 = (bytes[1] << 8) | bytes[0];
- insn = (insn << 16 | insn1);
- }
-
- // The insn could potentially be bit-twiddled in order to be decoded as an ARM
- // NEON/VFP opcode. In such case, the modified insn is later disassembled as
- // an ARM NEON/VFP instruction.
- //
- // This is a short term solution for lack of encoding bits specified for the
- // Thumb2 NEON/VFP instructions. The long term solution could be adding some
- // infrastructure to have each instruction support more than one encodings.
- // Which encoding is used would be based on which subtarget the compiler/
- // disassembler is working with at the time. This would allow the sharing of
- // the NEON patterns between ARM and Thumb2, as well as potential greater
- // sharing between the regular ARM instructions and the 32-bit wide Thumb2
- // instructions as well.
- unsigned Opcode = decodeThumbSideEffect(IsThumb2, insn);
-
- ARMFormat Format = ARMFormats[Opcode];
- Size = IsThumb2 ? 4 : 2;
-
- DEBUG({
- errs() << "Opcode=" << Opcode << " Name=" << ARMUtils::OpcodeName(Opcode)
- << " Format=" << stringForARMFormat(Format) << '(' << (int)Format
- << ")\n";
- showBitVector(errs(), insn);
- });
-
- OwningPtr<ARMBasicMCBuilder> Builder(CreateMCBuilder(Opcode, Format));
- if (!Builder)
- return false;
- Builder->SetSession(const_cast<Session *>(&SO));
+static DecodeStatus DecodeSTRPreImm(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
- Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(),
- getDisInfoBlock(), getMCContext(),
- Address);
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned imm = fieldFromInstruction32(Insn, 0, 12);
+ imm |= fieldFromInstruction32(Insn, 16, 4) << 13;
+ imm |= fieldFromInstruction32(Insn, 23, 1) << 12;
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
- if (!Builder->Build(MI, insn))
- return false;
+ if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail;
- return true;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeAddrModeImm12Operand(Inst, imm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
}
-// A8.6.50
-// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
-static unsigned short CountITSize(unsigned ITMask) {
- // First count the trailing zeros of the IT mask.
- unsigned TZ = CountTrailingZeros_32(ITMask);
- if (TZ > 3) {
- DEBUG(errs() << "Encoding error: IT Mask '0000'");
- return 0;
+static DecodeStatus DecodeSTRPreReg(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned imm = fieldFromInstruction32(Insn, 0, 12);
+ imm |= fieldFromInstruction32(Insn, 16, 4) << 13;
+ imm |= fieldFromInstruction32(Insn, 23, 1) << 12;
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+
+ if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail;
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeSORegMemOperand(Inst, imm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeVLD1LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned size = fieldFromInstruction32(Insn, 10, 2);
+
+ unsigned align = 0;
+ unsigned index = 0;
+ switch (size) {
+ default:
+ return MCDisassembler::Fail;
+ case 0:
+ if (fieldFromInstruction32(Insn, 4, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 5, 3);
+ break;
+ case 1:
+ if (fieldFromInstruction32(Insn, 5, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 6, 2);
+ if (fieldFromInstruction32(Insn, 4, 1))
+ align = 2;
+ break;
+ case 2:
+ if (fieldFromInstruction32(Insn, 6, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 7, 1);
+ if (fieldFromInstruction32(Insn, 4, 2) != 0)
+ align = 4;
+ }
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (Rm != 0xF) { // Writeback
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(align));
+ if (Rm != 0xF) {
+ if (Rm != 0xD) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ } else
+ Inst.addOperand(MCOperand::CreateReg(0));
}
- return (4 - TZ);
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(index));
+
+ return S;
}
-/// Init ITState. Note that at least one bit is always 1 in mask.
-bool Session::InitIT(unsigned short bits7_0) {
- ITCounter = CountITSize(slice(bits7_0, 3, 0));
- if (ITCounter == 0)
- return false;
+static DecodeStatus DecodeVST1LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
- // A8.6.50 IT
- unsigned short FirstCond = slice(bits7_0, 7, 4);
- if (FirstCond == 0xF) {
- DEBUG(errs() << "Encoding error: IT FirstCond '1111'");
- return false;
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned size = fieldFromInstruction32(Insn, 10, 2);
+
+ unsigned align = 0;
+ unsigned index = 0;
+ switch (size) {
+ default:
+ return MCDisassembler::Fail;
+ case 0:
+ if (fieldFromInstruction32(Insn, 4, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 5, 3);
+ break;
+ case 1:
+ if (fieldFromInstruction32(Insn, 5, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 6, 2);
+ if (fieldFromInstruction32(Insn, 4, 1))
+ align = 2;
+ break;
+ case 2:
+ if (fieldFromInstruction32(Insn, 6, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 7, 1);
+ if (fieldFromInstruction32(Insn, 4, 2) != 0)
+ align = 4;
}
- if (FirstCond == 0xE && ITCounter != 1) {
- DEBUG(errs() << "Encoding error: IT FirstCond '1110' && Mask != '1000'");
- return false;
+
+ if (Rm != 0xF) { // Writeback
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(align));
+ if (Rm != 0xF) {
+ if (Rm != 0xD) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ } else
+ Inst.addOperand(MCOperand::CreateReg(0));
}
- ITState = bits7_0;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(index));
- return true;
+ return S;
}
-/// Update ITState if necessary.
-void Session::UpdateIT() {
- assert(ITCounter);
- --ITCounter;
- if (ITCounter == 0)
- ITState = 0;
- else {
- unsigned short NewITState4_0 = slice(ITState, 4, 0) << 1;
- setSlice(ITState, 4, 0, NewITState4_0);
+
+static DecodeStatus DecodeVLD2LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned size = fieldFromInstruction32(Insn, 10, 2);
+
+ unsigned align = 0;
+ unsigned index = 0;
+ unsigned inc = 1;
+ switch (size) {
+ default:
+ return MCDisassembler::Fail;
+ case 0:
+ index = fieldFromInstruction32(Insn, 5, 3);
+ if (fieldFromInstruction32(Insn, 4, 1))
+ align = 2;
+ break;
+ case 1:
+ index = fieldFromInstruction32(Insn, 6, 2);
+ if (fieldFromInstruction32(Insn, 4, 1))
+ align = 4;
+ if (fieldFromInstruction32(Insn, 5, 1))
+ inc = 2;
+ break;
+ case 2:
+ if (fieldFromInstruction32(Insn, 5, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 7, 1);
+ if (fieldFromInstruction32(Insn, 4, 1) != 0)
+ align = 8;
+ if (fieldFromInstruction32(Insn, 6, 1))
+ inc = 2;
+ break;
+ }
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (Rm != 0xF) { // Writeback
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(align));
+ if (Rm != 0xF) {
+ if (Rm != 0xD) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ } else
+ Inst.addOperand(MCOperand::CreateReg(0));
}
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(index));
+
+ return S;
}
-static MCDisassembler *createARMDisassembler(const Target &T) {
- return new ARMDisassembler;
+static DecodeStatus DecodeVST2LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned size = fieldFromInstruction32(Insn, 10, 2);
+
+ unsigned align = 0;
+ unsigned index = 0;
+ unsigned inc = 1;
+ switch (size) {
+ default:
+ return MCDisassembler::Fail;
+ case 0:
+ index = fieldFromInstruction32(Insn, 5, 3);
+ if (fieldFromInstruction32(Insn, 4, 1))
+ align = 2;
+ break;
+ case 1:
+ index = fieldFromInstruction32(Insn, 6, 2);
+ if (fieldFromInstruction32(Insn, 4, 1))
+ align = 4;
+ if (fieldFromInstruction32(Insn, 5, 1))
+ inc = 2;
+ break;
+ case 2:
+ if (fieldFromInstruction32(Insn, 5, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 7, 1);
+ if (fieldFromInstruction32(Insn, 4, 1) != 0)
+ align = 8;
+ if (fieldFromInstruction32(Insn, 6, 1))
+ inc = 2;
+ break;
+ }
+
+ if (Rm != 0xF) { // Writeback
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(align));
+ if (Rm != 0xF) {
+ if (Rm != 0xD) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ } else
+ Inst.addOperand(MCOperand::CreateReg(0));
+ }
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(index));
+
+ return S;
}
-static MCDisassembler *createThumbDisassembler(const Target &T) {
- return new ThumbDisassembler;
+
+static DecodeStatus DecodeVLD3LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned size = fieldFromInstruction32(Insn, 10, 2);
+
+ unsigned align = 0;
+ unsigned index = 0;
+ unsigned inc = 1;
+ switch (size) {
+ default:
+ return MCDisassembler::Fail;
+ case 0:
+ if (fieldFromInstruction32(Insn, 4, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 5, 3);
+ break;
+ case 1:
+ if (fieldFromInstruction32(Insn, 4, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 6, 2);
+ if (fieldFromInstruction32(Insn, 5, 1))
+ inc = 2;
+ break;
+ case 2:
+ if (fieldFromInstruction32(Insn, 4, 2))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 7, 1);
+ if (fieldFromInstruction32(Insn, 6, 1))
+ inc = 2;
+ break;
+ }
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ if (Rm != 0xF) { // Writeback
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(align));
+ if (Rm != 0xF) {
+ if (Rm != 0xD) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ } else
+ Inst.addOperand(MCOperand::CreateReg(0));
+ }
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(index));
+
+ return S;
}
-extern "C" void LLVMInitializeARMDisassembler() {
- // Register the disassembler.
- TargetRegistry::RegisterMCDisassembler(TheARMTarget,
- createARMDisassembler);
- TargetRegistry::RegisterMCDisassembler(TheThumbTarget,
- createThumbDisassembler);
+static DecodeStatus DecodeVST3LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned size = fieldFromInstruction32(Insn, 10, 2);
+
+ unsigned align = 0;
+ unsigned index = 0;
+ unsigned inc = 1;
+ switch (size) {
+ default:
+ return MCDisassembler::Fail;
+ case 0:
+ if (fieldFromInstruction32(Insn, 4, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 5, 3);
+ break;
+ case 1:
+ if (fieldFromInstruction32(Insn, 4, 1))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 6, 2);
+ if (fieldFromInstruction32(Insn, 5, 1))
+ inc = 2;
+ break;
+ case 2:
+ if (fieldFromInstruction32(Insn, 4, 2))
+ return MCDisassembler::Fail; // UNDEFINED
+ index = fieldFromInstruction32(Insn, 7, 1);
+ if (fieldFromInstruction32(Insn, 6, 1))
+ inc = 2;
+ break;
+ }
+
+ if (Rm != 0xF) { // Writeback
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(align));
+ if (Rm != 0xF) {
+ if (Rm != 0xD) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ } else
+ Inst.addOperand(MCOperand::CreateReg(0));
+ }
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(index));
+
+ return S;
}
-EDInstInfo *ARMDisassembler::getEDInfo() const {
- return instInfoARM;
+
+static DecodeStatus DecodeVLD4LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned size = fieldFromInstruction32(Insn, 10, 2);
+
+ unsigned align = 0;
+ unsigned index = 0;
+ unsigned inc = 1;
+ switch (size) {
+ default:
+ return MCDisassembler::Fail;
+ case 0:
+ if (fieldFromInstruction32(Insn, 4, 1))
+ align = 4;
+ index = fieldFromInstruction32(Insn, 5, 3);
+ break;
+ case 1:
+ if (fieldFromInstruction32(Insn, 4, 1))
+ align = 8;
+ index = fieldFromInstruction32(Insn, 6, 2);
+ if (fieldFromInstruction32(Insn, 5, 1))
+ inc = 2;
+ break;
+ case 2:
+ if (fieldFromInstruction32(Insn, 4, 2))
+ align = 4 << fieldFromInstruction32(Insn, 4, 2);
+ index = fieldFromInstruction32(Insn, 7, 1);
+ if (fieldFromInstruction32(Insn, 6, 1))
+ inc = 2;
+ break;
+ }
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+3*inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ if (Rm != 0xF) { // Writeback
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(align));
+ if (Rm != 0xF) {
+ if (Rm != 0xD) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ } else
+ Inst.addOperand(MCOperand::CreateReg(0));
+ }
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+3*inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(index));
+
+ return S;
}
-EDInstInfo *ThumbDisassembler::getEDInfo() const {
- return instInfoARM;
+static DecodeStatus DecodeVST4LN(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+ Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
+ unsigned size = fieldFromInstruction32(Insn, 10, 2);
+
+ unsigned align = 0;
+ unsigned index = 0;
+ unsigned inc = 1;
+ switch (size) {
+ default:
+ return MCDisassembler::Fail;
+ case 0:
+ if (fieldFromInstruction32(Insn, 4, 1))
+ align = 4;
+ index = fieldFromInstruction32(Insn, 5, 3);
+ break;
+ case 1:
+ if (fieldFromInstruction32(Insn, 4, 1))
+ align = 8;
+ index = fieldFromInstruction32(Insn, 6, 2);
+ if (fieldFromInstruction32(Insn, 5, 1))
+ inc = 2;
+ break;
+ case 2:
+ if (fieldFromInstruction32(Insn, 4, 2))
+ align = 4 << fieldFromInstruction32(Insn, 4, 2);
+ index = fieldFromInstruction32(Insn, 7, 1);
+ if (fieldFromInstruction32(Insn, 6, 1))
+ inc = 2;
+ break;
+ }
+
+ if (Rm != 0xF) { // Writeback
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ }
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(align));
+ if (Rm != 0xF) {
+ if (Rm != 0xD) {
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ } else
+ Inst.addOperand(MCOperand::CreateReg(0));
+ }
+
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Rd+3*inc, Address, Decoder)))
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateImm(index));
+
+ return S;
+}
+
+static DecodeStatus DecodeVMOVSRR(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned Rt2 = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+ Rm |= fieldFromInstruction32(Insn, 5, 1) << 4;
+
+ if (Rt == 0xF || Rt2 == 0xF || Rm == 0x1F)
+ S = MCDisassembler::SoftFail;
+
+ if (!Check(S, DecodeSPRRegisterClass(Inst, Rm , Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeSPRRegisterClass(Inst, Rm+1, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt , Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt2 , Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeVMOVRRS(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned Rt2 = fieldFromInstruction32(Insn, 16, 4);
+ unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
+ unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+ Rm |= fieldFromInstruction32(Insn, 5, 1) << 4;
+
+ if (Rt == 0xF || Rt2 == 0xF || Rm == 0x1F)
+ S = MCDisassembler::SoftFail;
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt , Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rt2 , Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeSPRRegisterClass(Inst, Rm , Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeSPRRegisterClass(Inst, Rm+1, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeIT(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+ unsigned pred = fieldFromInstruction16(Insn, 4, 4);
+ // The InstPrinter needs to have the low bit of the predicate in
+ // the mask operand to be able to print it properly.
+ unsigned mask = fieldFromInstruction16(Insn, 0, 5);
+
+ if (pred == 0xF) {
+ pred = 0xE;
+ S = MCDisassembler::SoftFail;
+ }
+
+ if ((mask & 0xF) == 0) {
+ // Preserve the high bit of the mask, which is the low bit of
+ // the predicate.
+ mask &= 0x10;
+ mask |= 0x8;
+ S = MCDisassembler::SoftFail;
+ }
+
+ Inst.addOperand(MCOperand::CreateImm(pred));
+ Inst.addOperand(MCOperand::CreateImm(mask));
+ return S;
}
+
+static DecodeStatus
+DecodeT2LDRDPreInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned Rt2 = fieldFromInstruction32(Insn, 8, 4);
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned addr = fieldFromInstruction32(Insn, 0, 8);
+ unsigned W = fieldFromInstruction32(Insn, 21, 1);
+ unsigned U = fieldFromInstruction32(Insn, 23, 1);
+ unsigned P = fieldFromInstruction32(Insn, 24, 1);
+ bool writeback = (W == 1) | (P == 0);
+
+ addr |= (U << 8) | (Rn << 9);
+
+ if (writeback && (Rn == Rt || Rn == Rt2))
+ Check(S, MCDisassembler::SoftFail);
+ if (Rt == Rt2)
+ Check(S, MCDisassembler::SoftFail);
+
+ // Rt
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
+ // Rt2
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rt2, Address, Decoder)))
+ return MCDisassembler::Fail;
+ // Writeback operand
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ // addr
+ if (!Check(S, DecodeT2AddrModeImm8s4(Inst, addr, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus
+DecodeT2STRDPreInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+ unsigned Rt2 = fieldFromInstruction32(Insn, 8, 4);
+ unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+ unsigned addr = fieldFromInstruction32(Insn, 0, 8);
+ unsigned W = fieldFromInstruction32(Insn, 21, 1);
+ unsigned U = fieldFromInstruction32(Insn, 23, 1);
+ unsigned P = fieldFromInstruction32(Insn, 24, 1);
+ bool writeback = (W == 1) | (P == 0);
+
+ addr |= (U << 8) | (Rn << 9);
+
+ if (writeback && (Rn == Rt || Rn == Rt2))
+ Check(S, MCDisassembler::SoftFail);
+
+ // Writeback operand
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ // Rt
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder)))
+ return MCDisassembler::Fail;
+ // Rt2
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rt2, Address, Decoder)))
+ return MCDisassembler::Fail;
+ // addr
+ if (!Check(S, DecodeT2AddrModeImm8s4(Inst, addr, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
+static DecodeStatus DecodeT2Adr(llvm::MCInst &Inst, uint32_t Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned sign1 = fieldFromInstruction32(Insn, 21, 1);
+ unsigned sign2 = fieldFromInstruction32(Insn, 23, 1);
+ if (sign1 != sign2) return MCDisassembler::Fail;
+
+ unsigned Val = fieldFromInstruction32(Insn, 0, 8);
+ Val |= fieldFromInstruction32(Insn, 12, 3) << 8;
+ Val |= fieldFromInstruction32(Insn, 26, 1) << 11;
+ Val |= sign1 << 12;
+ Inst.addOperand(MCOperand::CreateImm(SignExtend32<13>(Val)));
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeT2ShifterImmOperand(llvm::MCInst &Inst, uint32_t Val,
+ uint64_t Address,
+ const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ // Shift of "asr #32" is not allowed in Thumb2 mode.
+ if (Val == 0x20) S = MCDisassembler::SoftFail;
+ Inst.addOperand(MCOperand::CreateImm(Val));
+ return S;
+}
+
diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.h b/lib/Target/ARM/Disassembler/ARMDisassembler.h
deleted file mode 100644
index 0a74a38..0000000
--- a/lib/Target/ARM/Disassembler/ARMDisassembler.h
+++ /dev/null
@@ -1,99 +0,0 @@
-//===- ARMDisassembler.h - Disassembler for ARM/Thumb ISA -------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is part of the ARM Disassembler.
-// It contains the header for ARMDisassembler and ThumbDisassembler, both are
-// subclasses of MCDisassembler.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ARMDISASSEMBLER_H
-#define ARMDISASSEMBLER_H
-
-#include "llvm/MC/MCDisassembler.h"
-
-namespace llvm {
-
-class MCInst;
-class MemoryObject;
-class raw_ostream;
-
-struct EDInstInfo;
-
-/// ARMDisassembler - ARM disassembler for all ARM platforms.
-class ARMDisassembler : public MCDisassembler {
-public:
- /// Constructor - Initializes the disassembler.
- ///
- ARMDisassembler() :
- MCDisassembler() {
- }
-
- ~ARMDisassembler() {
- }
-
- /// getInstruction - See MCDisassembler.
- bool getInstruction(MCInst &instr,
- uint64_t &size,
- const MemoryObject &region,
- uint64_t address,
- raw_ostream &vStream) const;
-
- /// getEDInfo - See MCDisassembler.
- EDInstInfo *getEDInfo() const;
-private:
-};
-
-// Forward declaration.
-class ARMBasicMCBuilder;
-
-/// Session - Keep track of the IT Block progression.
-class Session {
- friend class ARMBasicMCBuilder;
-public:
- Session() : ITCounter(0), ITState(0) {}
- ~Session() {}
- /// InitIT - Initializes ITCounter/ITState.
- bool InitIT(unsigned short bits7_0);
- /// UpdateIT - Updates ITCounter/ITState as IT Block progresses.
- void UpdateIT();
-
-private:
- unsigned ITCounter; // Possible values: 0, 1, 2, 3, 4.
- unsigned ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
-};
-
-/// ThumbDisassembler - Thumb disassembler for all ARM platforms.
-class ThumbDisassembler : public MCDisassembler {
-public:
- /// Constructor - Initializes the disassembler.
- ///
- ThumbDisassembler() :
- MCDisassembler(), SO() {
- }
-
- ~ThumbDisassembler() {
- }
-
- /// getInstruction - See MCDisassembler.
- bool getInstruction(MCInst &instr,
- uint64_t &size,
- const MemoryObject &region,
- uint64_t address,
- raw_ostream &vStream) const;
-
- /// getEDInfo - See MCDisassembler.
- EDInstInfo *getEDInfo() const;
-private:
- Session SO;
-};
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
deleted file mode 100644
index d89c80a..0000000
--- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
+++ /dev/null
@@ -1,3818 +0,0 @@
-//===- ARMDisassemblerCore.cpp - ARM disassembler helpers -------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is part of the ARM Disassembler.
-// It contains code to represent the core concepts of Builder and DisassembleFP
-// to solve the problem of disassembling an ARM instr.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "arm-disassembler"
-
-#include "ARMDisassemblerCore.h"
-#include "ARMAddressingModes.h"
-#include "ARMMCExpr.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-//#define DEBUG(X) do { X; } while (0)
-
-/// ARMGenInstrInfo.inc - ARMGenInstrInfo.inc contains the static const
-/// MCInstrDesc ARMInsts[] definition and the MCOperandInfo[]'s describing the
-/// operand info for each ARMInsts[i].
-///
-/// Together with an instruction's encoding format, we can take advantage of the
-/// NumOperands and the OpInfo fields of the target instruction description in
-/// the quest to build out the MCOperand list for an MCInst.
-///
-/// The general guideline is that with a known format, the number of dst and src
-/// operands are well-known. The dst is built first, followed by the src
-/// operand(s). The operands not yet used at this point are for the Implicit
-/// Uses and Defs by this instr. For the Uses part, the pred:$p operand is
-/// defined with two components:
-///
-/// def pred { // Operand PredicateOperand
-/// ValueType Type = OtherVT;
-/// string PrintMethod = "printPredicateOperand";
-/// string AsmOperandLowerMethod = ?;
-/// dag MIOperandInfo = (ops i32imm, CCR);
-/// AsmOperandClass ParserMatchClass = ImmAsmOperand;
-/// dag DefaultOps = (ops (i32 14), (i32 zero_reg));
-/// }
-///
-/// which is manifested by the MCOperandInfo[] of:
-///
-/// { 0, 0|(1<<MCOI::Predicate), 0 },
-/// { ARM::CCRRegClassID, 0|(1<<MCOI::Predicate), 0 }
-///
-/// So the first predicate MCOperand corresponds to the immediate part of the
-/// ARM condition field (Inst{31-28}), and the second predicate MCOperand
-/// corresponds to a register kind of ARM::CPSR.
-///
-/// For the Defs part, in the simple case of only cc_out:$s, we have:
-///
-/// def cc_out { // Operand OptionalDefOperand
-/// ValueType Type = OtherVT;
-/// string PrintMethod = "printSBitModifierOperand";
-/// string AsmOperandLowerMethod = ?;
-/// dag MIOperandInfo = (ops CCR);
-/// AsmOperandClass ParserMatchClass = ImmAsmOperand;
-/// dag DefaultOps = (ops (i32 zero_reg));
-/// }
-///
-/// which is manifested by the one MCOperandInfo of:
-///
-/// { ARM::CCRRegClassID, 0|(1<<MCOI::OptionalDef), 0 }
-///
-
-namespace llvm {
-extern MCInstrDesc ARMInsts[];
-}
-
-using namespace llvm;
-
-const char *ARMUtils::OpcodeName(unsigned Opcode) {
- return ARMInsts[Opcode].Name;
-}
-
-// Return the register enum Based on RegClass and the raw register number.
-// FIXME: Auto-gened?
-static unsigned
-getRegisterEnum(BO B, unsigned RegClassID, unsigned RawRegister) {
- if (RegClassID == ARM::rGPRRegClassID) {
- // Check for The register numbers 13 and 15 that are not permitted for many
- // Thumb register specifiers.
- if (RawRegister == 13 || RawRegister == 15) {
- B->SetErr(-1);
- return 0;
- }
- // For this purpose, we can treat rGPR as if it were GPR.
- RegClassID = ARM::GPRRegClassID;
- }
-
- // See also decodeNEONRd(), decodeNEONRn(), decodeNEONRm().
- // A7.3 register encoding
- // Qd -> bit[12] == 0
- // Qn -> bit[16] == 0
- // Qm -> bit[0] == 0
- //
- // If one of these bits is 1, the instruction is UNDEFINED.
- if (RegClassID == ARM::QPRRegClassID && slice(RawRegister, 0, 0) == 1) {
- B->SetErr(-1);
- return 0;
- }
- unsigned RegNum =
- RegClassID == ARM::QPRRegClassID ? RawRegister >> 1 : RawRegister;
-
- switch (RegNum) {
- default:
- break;
- case 0:
- switch (RegClassID) {
- case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R0;
- case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
- case ARM::DPR_VFP2RegClassID:
- return ARM::D0;
- case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
- case ARM::QPR_VFP2RegClassID:
- return ARM::Q0;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S0;
- }
- break;
- case 1:
- switch (RegClassID) {
- case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R1;
- case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
- case ARM::DPR_VFP2RegClassID:
- return ARM::D1;
- case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
- case ARM::QPR_VFP2RegClassID:
- return ARM::Q1;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S1;
- }
- break;
- case 2:
- switch (RegClassID) {
- case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R2;
- case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
- case ARM::DPR_VFP2RegClassID:
- return ARM::D2;
- case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
- case ARM::QPR_VFP2RegClassID:
- return ARM::Q2;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S2;
- }
- break;
- case 3:
- switch (RegClassID) {
- case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R3;
- case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
- case ARM::DPR_VFP2RegClassID:
- return ARM::D3;
- case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
- case ARM::QPR_VFP2RegClassID:
- return ARM::Q3;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S3;
- }
- break;
- case 4:
- switch (RegClassID) {
- case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R4;
- case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
- case ARM::DPR_VFP2RegClassID:
- return ARM::D4;
- case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q4;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S4;
- }
- break;
- case 5:
- switch (RegClassID) {
- case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R5;
- case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
- case ARM::DPR_VFP2RegClassID:
- return ARM::D5;
- case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q5;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S5;
- }
- break;
- case 6:
- switch (RegClassID) {
- case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R6;
- case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
- case ARM::DPR_VFP2RegClassID:
- return ARM::D6;
- case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q6;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S6;
- }
- break;
- case 7:
- switch (RegClassID) {
- case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R7;
- case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
- case ARM::DPR_VFP2RegClassID:
- return ARM::D7;
- case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q7;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S7;
- }
- break;
- case 8:
- switch (RegClassID) {
- case ARM::GPRRegClassID: return ARM::R8;
- case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D8;
- case ARM::QPRRegClassID: return ARM::Q8;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S8;
- }
- break;
- case 9:
- switch (RegClassID) {
- case ARM::GPRRegClassID: return ARM::R9;
- case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D9;
- case ARM::QPRRegClassID: return ARM::Q9;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S9;
- }
- break;
- case 10:
- switch (RegClassID) {
- case ARM::GPRRegClassID: return ARM::R10;
- case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D10;
- case ARM::QPRRegClassID: return ARM::Q10;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S10;
- }
- break;
- case 11:
- switch (RegClassID) {
- case ARM::GPRRegClassID: return ARM::R11;
- case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D11;
- case ARM::QPRRegClassID: return ARM::Q11;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S11;
- }
- break;
- case 12:
- switch (RegClassID) {
- case ARM::GPRRegClassID: return ARM::R12;
- case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D12;
- case ARM::QPRRegClassID: return ARM::Q12;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S12;
- }
- break;
- case 13:
- switch (RegClassID) {
- case ARM::GPRRegClassID: return ARM::SP;
- case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D13;
- case ARM::QPRRegClassID: return ARM::Q13;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S13;
- }
- break;
- case 14:
- switch (RegClassID) {
- case ARM::GPRRegClassID: return ARM::LR;
- case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D14;
- case ARM::QPRRegClassID: return ARM::Q14;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S14;
- }
- break;
- case 15:
- switch (RegClassID) {
- case ARM::GPRRegClassID: return ARM::PC;
- case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D15;
- case ARM::QPRRegClassID: return ARM::Q15;
- case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S15;
- }
- break;
- case 16:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D16;
- case ARM::SPRRegClassID: return ARM::S16;
- }
- break;
- case 17:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D17;
- case ARM::SPRRegClassID: return ARM::S17;
- }
- break;
- case 18:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D18;
- case ARM::SPRRegClassID: return ARM::S18;
- }
- break;
- case 19:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D19;
- case ARM::SPRRegClassID: return ARM::S19;
- }
- break;
- case 20:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D20;
- case ARM::SPRRegClassID: return ARM::S20;
- }
- break;
- case 21:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D21;
- case ARM::SPRRegClassID: return ARM::S21;
- }
- break;
- case 22:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D22;
- case ARM::SPRRegClassID: return ARM::S22;
- }
- break;
- case 23:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D23;
- case ARM::SPRRegClassID: return ARM::S23;
- }
- break;
- case 24:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D24;
- case ARM::SPRRegClassID: return ARM::S24;
- }
- break;
- case 25:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D25;
- case ARM::SPRRegClassID: return ARM::S25;
- }
- break;
- case 26:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D26;
- case ARM::SPRRegClassID: return ARM::S26;
- }
- break;
- case 27:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D27;
- case ARM::SPRRegClassID: return ARM::S27;
- }
- break;
- case 28:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D28;
- case ARM::SPRRegClassID: return ARM::S28;
- }
- break;
- case 29:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D29;
- case ARM::SPRRegClassID: return ARM::S29;
- }
- break;
- case 30:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D30;
- case ARM::SPRRegClassID: return ARM::S30;
- }
- break;
- case 31:
- switch (RegClassID) {
- case ARM::DPRRegClassID: return ARM::D31;
- case ARM::SPRRegClassID: return ARM::S31;
- }
- break;
- }
- DEBUG(errs() << "Invalid (RegClassID, RawRegister) combination\n");
- // Encoding error. Mark the builder with error code != 0.
- B->SetErr(-1);
- return 0;
-}
-
-///////////////////////////////
-// //
-// Utility Functions //
-// //
-///////////////////////////////
-
-// Extract/Decode Rd: Inst{15-12}.
-static inline unsigned decodeRd(uint32_t insn) {
- return (insn >> ARMII::RegRdShift) & ARMII::GPRRegMask;
-}
-
-// Extract/Decode Rn: Inst{19-16}.
-static inline unsigned decodeRn(uint32_t insn) {
- return (insn >> ARMII::RegRnShift) & ARMII::GPRRegMask;
-}
-
-// Extract/Decode Rm: Inst{3-0}.
-static inline unsigned decodeRm(uint32_t insn) {
- return (insn & ARMII::GPRRegMask);
-}
-
-// Extract/Decode Rs: Inst{11-8}.
-static inline unsigned decodeRs(uint32_t insn) {
- return (insn >> ARMII::RegRsShift) & ARMII::GPRRegMask;
-}
-
-static inline unsigned getCondField(uint32_t insn) {
- return (insn >> ARMII::CondShift);
-}
-
-static inline unsigned getIBit(uint32_t insn) {
- return (insn >> ARMII::I_BitShift) & 1;
-}
-
-static inline unsigned getAM3IBit(uint32_t insn) {
- return (insn >> ARMII::AM3_I_BitShift) & 1;
-}
-
-static inline unsigned getPBit(uint32_t insn) {
- return (insn >> ARMII::P_BitShift) & 1;
-}
-
-static inline unsigned getUBit(uint32_t insn) {
- return (insn >> ARMII::U_BitShift) & 1;
-}
-
-static inline unsigned getPUBits(uint32_t insn) {
- return (insn >> ARMII::U_BitShift) & 3;
-}
-
-static inline unsigned getSBit(uint32_t insn) {
- return (insn >> ARMII::S_BitShift) & 1;
-}
-
-static inline unsigned getWBit(uint32_t insn) {
- return (insn >> ARMII::W_BitShift) & 1;
-}
-
-static inline unsigned getDBit(uint32_t insn) {
- return (insn >> ARMII::D_BitShift) & 1;
-}
-
-static inline unsigned getNBit(uint32_t insn) {
- return (insn >> ARMII::N_BitShift) & 1;
-}
-
-static inline unsigned getMBit(uint32_t insn) {
- return (insn >> ARMII::M_BitShift) & 1;
-}
-
-// See A8.4 Shifts applied to a register.
-// A8.4.2 Register controlled shifts.
-//
-// getShiftOpcForBits - getShiftOpcForBits translates from the ARM encoding bits
-// into llvm enums for shift opcode. The API clients should pass in the value
-// encoded with two bits, so the assert stays to signal a wrong API usage.
-//
-// A8-12: DecodeRegShift()
-static inline ARM_AM::ShiftOpc getShiftOpcForBits(unsigned bits) {
- switch (bits) {
- default: assert(0 && "No such value"); return ARM_AM::no_shift;
- case 0: return ARM_AM::lsl;
- case 1: return ARM_AM::lsr;
- case 2: return ARM_AM::asr;
- case 3: return ARM_AM::ror;
- }
-}
-
-// See A8.4 Shifts applied to a register.
-// A8.4.1 Constant shifts.
-//
-// getImmShiftSE - getImmShiftSE translates from the raw ShiftOpc and raw Imm5
-// encodings into the intended ShiftOpc and shift amount.
-//
-// A8-11: DecodeImmShift()
-static inline void getImmShiftSE(ARM_AM::ShiftOpc &ShOp, unsigned &ShImm) {
- if (ShImm != 0)
- return;
- switch (ShOp) {
- case ARM_AM::no_shift:
- case ARM_AM::rrx:
- break;
- case ARM_AM::lsl:
- ShOp = ARM_AM::no_shift;
- break;
- case ARM_AM::lsr:
- case ARM_AM::asr:
- ShImm = 32;
- break;
- case ARM_AM::ror:
- ShOp = ARM_AM::rrx;
- break;
- }
-}
-
-// getAMSubModeForBits - getAMSubModeForBits translates from the ARM encoding
-// bits Inst{24-23} (P(24) and U(23)) into llvm enums for AMSubMode. The API
-// clients should pass in the value encoded with two bits, so the assert stays
-// to signal a wrong API usage.
-static inline ARM_AM::AMSubMode getAMSubModeForBits(unsigned bits) {
- switch (bits) {
- default: assert(0 && "No such value"); return ARM_AM::bad_am_submode;
- case 1: return ARM_AM::ia; // P=0 U=1
- case 3: return ARM_AM::ib; // P=1 U=1
- case 0: return ARM_AM::da; // P=0 U=0
- case 2: return ARM_AM::db; // P=1 U=0
- }
-}
-
-////////////////////////////////////////////
-// //
-// Disassemble function definitions //
-// //
-////////////////////////////////////////////
-
-/// There is a separate Disassemble*Frm function entry for disassembly of an ARM
-/// instr into a list of MCOperands in the appropriate order, with possible dst,
-/// followed by possible src(s).
-///
-/// The processing of the predicate, and the 'S' modifier bit, if MI modifies
-/// the CPSR, is factored into ARMBasicMCBuilder's method named
-/// TryPredicateAndSBitModifier.
-
-static bool DisassemblePseudo(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
-
- assert(0 && "Unexpected pseudo instruction!");
- return false;
-}
-
-// A8.6.94 MLA
-// if d == 15 || n == 15 || m == 15 || a == 15 then UNPREDICTABLE;
-//
-// A8.6.105 MUL
-// if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
-//
-// A8.6.246 UMULL
-// if dLo == 15 || dHi == 15 || n == 15 || m == 15 then UNPREDICTABLE;
-// if dHi == dLo then UNPREDICTABLE;
-static bool BadRegsMulFrm(unsigned Opcode, uint32_t insn) {
- unsigned R19_16 = slice(insn, 19, 16);
- unsigned R15_12 = slice(insn, 15, 12);
- unsigned R11_8 = slice(insn, 11, 8);
- unsigned R3_0 = slice(insn, 3, 0);
- switch (Opcode) {
- default:
- // Did we miss an opcode?
- DEBUG(errs() << "BadRegsMulFrm: unexpected opcode!");
- return false;
- case ARM::MLA: case ARM::MLS: case ARM::SMLABB: case ARM::SMLABT:
- case ARM::SMLATB: case ARM::SMLATT: case ARM::SMLAWB: case ARM::SMLAWT:
- case ARM::SMMLA: case ARM::SMMLAR: case ARM::SMMLS: case ARM::SMMLSR:
- case ARM::USADA8:
- if (R19_16 == 15 || R15_12 == 15 || R11_8 == 15 || R3_0 == 15)
- return true;
- return false;
- case ARM::MUL: case ARM::SMMUL: case ARM::SMMULR:
- case ARM::SMULBB: case ARM::SMULBT: case ARM::SMULTB: case ARM::SMULTT:
- case ARM::SMULWB: case ARM::SMULWT: case ARM::SMUAD: case ARM::SMUADX:
- // A8.6.167 SMLAD & A8.6.172 SMLSD
- case ARM::SMLAD: case ARM::SMLADX: case ARM::SMLSD: case ARM::SMLSDX:
- case ARM::USAD8:
- if (R19_16 == 15 || R11_8 == 15 || R3_0 == 15)
- return true;
- return false;
- case ARM::SMLAL: case ARM::SMULL: case ARM::UMAAL: case ARM::UMLAL:
- case ARM::UMULL:
- case ARM::SMLALBB: case ARM::SMLALBT: case ARM::SMLALTB: case ARM::SMLALTT:
- case ARM::SMLALD: case ARM::SMLALDX: case ARM::SMLSLD: case ARM::SMLSLDX:
- if (R19_16 == 15 || R15_12 == 15 || R11_8 == 15 || R3_0 == 15)
- return true;
- if (R19_16 == R15_12)
- return true;
- return false;;
- }
-}
-
-// Multiply Instructions.
-// MLA, MLS, SMLABB, SMLABT, SMLATB, SMLATT, SMLAWB, SMLAWT, SMMLA, SMMLAR,
-// SMMLS, SMMLAR, SMLAD, SMLADX, SMLSD, SMLSDX, and USADA8 (for convenience):
-// Rd{19-16} Rn{3-0} Rm{11-8} Ra{15-12}
-// But note that register checking for {SMLAD, SMLADX, SMLSD, SMLSDX} is
-// only for {d, n, m}.
-//
-// MUL, SMMUL, SMMULR, SMULBB, SMULBT, SMULTB, SMULTT, SMULWB, SMULWT, SMUAD,
-// SMUADX, and USAD8 (for convenience):
-// Rd{19-16} Rn{3-0} Rm{11-8}
-//
-// SMLAL, SMULL, UMAAL, UMLAL, UMULL, SMLALBB, SMLALBT, SMLALTB, SMLALTT,
-// SMLALD, SMLADLX, SMLSLD, SMLSLDX:
-// RdLo{15-12} RdHi{19-16} Rn{3-0} Rm{11-8}
-//
-// The mapping of the multiply registers to the "regular" ARM registers, where
-// there are convenience decoder functions, is:
-//
-// Inst{15-12} => Rd
-// Inst{19-16} => Rn
-// Inst{3-0} => Rm
-// Inst{11-8} => Rs
-static bool DisassembleMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- unsigned short NumDefs = MCID.getNumDefs();
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(NumDefs > 0 && "NumDefs should be greater than 0 for MulFrm");
- assert(NumOps >= 3
- && OpInfo[0].RegClass == ARM::GPRRegClassID
- && OpInfo[1].RegClass == ARM::GPRRegClassID
- && OpInfo[2].RegClass == ARM::GPRRegClassID
- && "Expect three register operands");
-
- // Sanity check for the register encodings.
- if (BadRegsMulFrm(Opcode, insn))
- return false;
-
- // Instructions with two destination registers have RdLo{15-12} first.
- if (NumDefs == 2) {
- assert(NumOps >= 4 && OpInfo[3].RegClass == ARM::GPRRegClassID &&
- "Expect 4th register operand");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- ++OpIdx;
- }
-
- // The destination register: RdHi{19-16} or Rd{19-16}.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
-
- // The two src regsiters: Rn{3-0}, then Rm{11-8}.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRs(insn))));
- OpIdx += 3;
-
- // Many multiply instructions (e.g., MLA) have three src registers.
- // The third register operand is Ra{15-12}.
- if (OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- ++OpIdx;
- }
-
- return true;
-}
-
-// Helper routines for disassembly of coprocessor instructions.
-
-static bool LdStCopOpcode(unsigned Opcode) {
- if ((Opcode >= ARM::LDC2L_OFFSET && Opcode <= ARM::LDC_PRE) ||
- (Opcode >= ARM::STC2L_OFFSET && Opcode <= ARM::STC_PRE))
- return true;
- return false;
-}
-static bool CoprocessorOpcode(unsigned Opcode) {
- if (LdStCopOpcode(Opcode))
- return true;
-
- switch (Opcode) {
- default:
- return false;
- case ARM::CDP: case ARM::CDP2:
- case ARM::MCR: case ARM::MCR2: case ARM::MRC: case ARM::MRC2:
- case ARM::MCRR: case ARM::MCRR2: case ARM::MRRC: case ARM::MRRC2:
- return true;
- }
-}
-static inline unsigned GetCoprocessor(uint32_t insn) {
- return slice(insn, 11, 8);
-}
-static inline unsigned GetCopOpc1(uint32_t insn, bool CDP) {
- return CDP ? slice(insn, 23, 20) : slice(insn, 23, 21);
-}
-static inline unsigned GetCopOpc2(uint32_t insn) {
- return slice(insn, 7, 5);
-}
-static inline unsigned GetCopOpc(uint32_t insn) {
- return slice(insn, 7, 4);
-}
-// Most of the operands are in immediate forms, except Rd and Rn, which are ARM
-// core registers.
-//
-// CDP, CDP2: cop opc1 CRd CRn CRm opc2
-//
-// MCR, MCR2, MRC, MRC2: cop opc1 Rd CRn CRm opc2
-//
-// MCRR, MCRR2, MRRC, MRRc2: cop opc Rd Rn CRm
-//
-// LDC_OFFSET, LDC_PRE, LDC_POST: cop CRd Rn R0 [+/-]imm8:00
-// and friends
-// STC_OFFSET, STC_PRE, STC_POST: cop CRd Rn R0 [+/-]imm8:00
-// and friends
-// <-- addrmode2 -->
-//
-// LDC_OPTION: cop CRd Rn imm8
-// and friends
-// STC_OPTION: cop CRd Rn imm8
-// and friends
-//
-static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 4 && "Num of operands >= 4 for coprocessor instr");
-
- unsigned &OpIdx = NumOpsAdded;
- // A8.6.92
- // if coproc == '101x' then SEE "Advanced SIMD and VFP"
- // But since the special instructions have more explicit encoding bits
- // specified, if coproc == 10 or 11, we should reject it as invalid.
- unsigned coproc = GetCoprocessor(insn);
- if ((Opcode == ARM::MCR || Opcode == ARM::MCRR ||
- Opcode == ARM::MRC || Opcode == ARM::MRRC) &&
- (coproc == 10 || coproc == 11)) {
- DEBUG(errs() << "Encoding error: coproc == 10 or 11 for MCR[R]/MR[R]C\n");
- return false;
- }
-
- bool OneCopOpc = (Opcode == ARM::MCRR || Opcode == ARM::MCRR2 ||
- Opcode == ARM::MRRC || Opcode == ARM::MRRC2);
-
- // CDP/CDP2 has no GPR operand; the opc1 operand is also wider (Inst{23-20}).
- bool NoGPR = (Opcode == ARM::CDP || Opcode == ARM::CDP2);
- bool LdStCop = LdStCopOpcode(Opcode);
- bool RtOut = (Opcode == ARM::MRC || Opcode == ARM::MRC2);
-
- OpIdx = 0;
-
- if (RtOut) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- ++OpIdx;
- }
- MI.addOperand(MCOperand::CreateImm(coproc));
- ++OpIdx;
-
- if (LdStCop) {
- // Unindex if P:W = 0b00 --> _OPTION variant
- unsigned PW = getPBit(insn) << 1 | getWBit(insn);
-
- MI.addOperand(MCOperand::CreateImm(decodeRd(insn)));
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- OpIdx += 2;
-
- if (PW) {
- MI.addOperand(MCOperand::CreateReg(0));
- ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- unsigned IndexMode =
- (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
- unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, slice(insn, 7, 0) << 2,
- ARM_AM::no_shift, IndexMode);
- MI.addOperand(MCOperand::CreateImm(Offset));
- OpIdx += 2;
- } else {
- MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 0)));
- ++OpIdx;
- }
- } else {
- MI.addOperand(MCOperand::CreateImm(OneCopOpc ? GetCopOpc(insn)
- : GetCopOpc1(insn, NoGPR)));
- ++OpIdx;
-
- if (!RtOut) {
- MI.addOperand(NoGPR ? MCOperand::CreateImm(decodeRd(insn))
- : MCOperand::CreateReg(
- getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- ++OpIdx;
- }
-
- MI.addOperand(OneCopOpc ? MCOperand::CreateReg(
- getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn)))
- : MCOperand::CreateImm(decodeRn(insn)));
-
- MI.addOperand(MCOperand::CreateImm(decodeRm(insn)));
-
- OpIdx += 2;
-
- if (!OneCopOpc) {
- MI.addOperand(MCOperand::CreateImm(GetCopOpc2(insn)));
- ++OpIdx;
- }
- }
-
- return true;
-}
-
-// Branch Instructions.
-// BL: SignExtend(Imm24:'00', 32)
-// Bcc, BL_pred: SignExtend(Imm24:'00', 32) Pred0 Pred1
-// SMC: ZeroExtend(imm4, 32)
-// SVC: ZeroExtend(Imm24, 32)
-//
-// Various coprocessor instructions are assigned BrFrm arbitrarily.
-// Delegates to DisassembleCoprocessor() helper function.
-//
-// MRS/MRSsys: Rd
-// MSR/MSRsys: Rm mask=Inst{19-16}
-// BXJ: Rm
-// MSRi/MSRsysi: so_imm
-// SRSW/SRS: ldstm_mode:$amode mode_imm
-// RFEW/RFE: ldstm_mode:$amode Rn
-static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- if (CoprocessorOpcode(Opcode))
- return DisassembleCoprocessor(MI, Opcode, insn, NumOps, NumOpsAdded, B);
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- // MRS and MRSsys take one GPR reg Rd.
- if (Opcode == ARM::MRS || Opcode == ARM::MRSsys) {
- assert(NumOps >= 1 && OpInfo[0].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- NumOpsAdded = 1;
- return true;
- }
- // BXJ takes one GPR reg Rm.
- if (Opcode == ARM::BXJ) {
- assert(NumOps >= 1 && OpInfo[0].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- NumOpsAdded = 1;
- return true;
- }
- // MSR take a mask, followed by one GPR reg Rm. The mask contains the R Bit in
- // bit 4, and the special register fields in bits 3-0.
- if (Opcode == ARM::MSR) {
- assert(NumOps >= 1 && OpInfo[1].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateImm(slice(insn, 22, 22) << 4 /* R Bit */ |
- slice(insn, 19, 16) /* Special Reg */ ));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- NumOpsAdded = 2;
- return true;
- }
- // MSRi take a mask, followed by one so_imm operand. The mask contains the
- // R Bit in bit 4, and the special register fields in bits 3-0.
- if (Opcode == ARM::MSRi) {
- // A5.2.11 MSR (immediate), and hints & B6.1.6 MSR (immediate)
- // The hints instructions have more specific encodings, so if mask == 0,
- // we should reject this as an invalid instruction.
- if (slice(insn, 19, 16) == 0)
- return false;
- MI.addOperand(MCOperand::CreateImm(slice(insn, 22, 22) << 4 /* R Bit */ |
- slice(insn, 19, 16) /* Special Reg */ ));
- // SOImm is 4-bit rotate amount in bits 11-8 with 8-bit imm in bits 7-0.
- // A5.2.4 Rotate amount is twice the numeric value of Inst{11-8}.
- // See also ARMAddressingModes.h: getSOImmValImm() and getSOImmValRot().
- unsigned Rot = (insn >> ARMII::SoRotImmShift) & 0xF;
- unsigned Imm = insn & 0xFF;
- MI.addOperand(MCOperand::CreateImm(ARM_AM::rotr32(Imm, 2*Rot)));
- NumOpsAdded = 2;
- return true;
- }
- if (Opcode == ARM::SRSW || Opcode == ARM::SRS ||
- Opcode == ARM::RFEW || Opcode == ARM::RFE) {
- ARM_AM::AMSubMode SubMode = getAMSubModeForBits(getPUBits(insn));
- MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM4ModeImm(SubMode)));
-
- if (Opcode == ARM::SRSW || Opcode == ARM::SRS)
- MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));
- else
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- NumOpsAdded = 3;
- return true;
- }
-
- assert((Opcode == ARM::Bcc || Opcode == ARM::BL || Opcode == ARM::BL_pred
- || Opcode == ARM::SMC || Opcode == ARM::SVC) &&
- "Unexpected Opcode");
-
- assert(NumOps >= 1 && OpInfo[0].RegClass < 0 && "Imm operand expected");
-
- int Imm32 = 0;
- if (Opcode == ARM::SMC) {
- // ZeroExtend(imm4, 32) where imm24 = Inst{3-0}.
- Imm32 = slice(insn, 3, 0);
- } else if (Opcode == ARM::SVC) {
- // ZeroExtend(imm24, 32) where imm24 = Inst{23-0}.
- Imm32 = slice(insn, 23, 0);
- } else {
- // SignExtend(imm24:'00', 32) where imm24 = Inst{23-0}.
- unsigned Imm26 = slice(insn, 23, 0) << 2;
- //Imm32 = signextend<signed int, 26>(Imm26);
- Imm32 = SignExtend32<26>(Imm26);
- }
-
- MI.addOperand(MCOperand::CreateImm(Imm32));
- NumOpsAdded = 1;
-
- return true;
-}
-
-// Misc. Branch Instructions.
-// BX_RET, MOVPCLR
-// BLX, BLX_pred, BX, BX_pred
-// BLXi
-static bool DisassembleBrMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- // BX_RET and MOVPCLR have only two predicate operands; do an early return.
- if (Opcode == ARM::BX_RET || Opcode == ARM::MOVPCLR)
- return true;
-
- // BLX and BX take one GPR reg.
- if (Opcode == ARM::BLX || Opcode == ARM::BLX_pred ||
- Opcode == ARM::BX || Opcode == ARM::BX_pred) {
- assert(NumOps >= 1 && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- OpIdx = 1;
- return true;
- }
-
- // BLXi takes imm32 (the PC offset).
- if (Opcode == ARM::BLXi) {
- assert(NumOps >= 1 && OpInfo[0].RegClass < 0 && "Imm operand expected");
- // SignExtend(imm24:H:'0', 32) where imm24 = Inst{23-0} and H = Inst{24}.
- unsigned Imm26 = slice(insn, 23, 0) << 2 | slice(insn, 24, 24) << 1;
- int Imm32 = SignExtend32<26>(Imm26);
- MI.addOperand(MCOperand::CreateImm(Imm32));
- OpIdx = 1;
- return true;
- }
-
- return false;
-}
-
-static inline bool getBFCInvMask(uint32_t insn, uint32_t &mask) {
- uint32_t lsb = slice(insn, 11, 7);
- uint32_t msb = slice(insn, 20, 16);
- uint32_t Val = 0;
- if (msb < lsb) {
- DEBUG(errs() << "Encoding error: msb < lsb\n");
- return false;
- }
-
- for (uint32_t i = lsb; i <= msb; ++i)
- Val |= (1 << i);
- mask = ~Val;
- return true;
-}
-
-// Standard data-processing instructions allow PC as a register specifier,
-// but we should reject other DPFrm instructions with PC as registers.
-static bool BadRegsDPFrm(unsigned Opcode, uint32_t insn) {
- switch (Opcode) {
- default:
- // Did we miss an opcode?
- if (decodeRd(insn) == 15 || decodeRn(insn) == 15 || decodeRm(insn) == 15) {
- DEBUG(errs() << "DPFrm with bad reg specifier(s)\n");
- return true;
- }
- case ARM::ADCrr: case ARM::ADDSrr: case ARM::ADDrr: case ARM::ANDrr:
- case ARM::BICrr: case ARM::CMNzrr: case ARM::CMPrr: case ARM::EORrr:
- case ARM::ORRrr: case ARM::RSBrr: case ARM::RSCrr: case ARM::SBCrr:
- case ARM::SUBSrr: case ARM::SUBrr: case ARM::TEQrr: case ARM::TSTrr:
- return false;
- }
-}
-
-// A major complication is the fact that some of the saturating add/subtract
-// operations have Rd Rm Rn, instead of the "normal" Rd Rn Rm.
-// They are QADD, QDADD, QDSUB, and QSUB.
-static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- unsigned short NumDefs = MCID.getNumDefs();
- bool isUnary = isUnaryDP(MCID.TSFlags);
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- // Disassemble register def if there is one.
- if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- ++OpIdx;
- }
-
- // Now disassemble the src operands.
- if (OpIdx >= NumOps)
- return false;
-
- // Special-case handling of BFC/BFI/SBFX/UBFX.
- if (Opcode == ARM::BFC || Opcode == ARM::BFI) {
- // A8.6.17 BFC & A8.6.18 BFI
- // Sanity check Rd.
- if (decodeRd(insn) == 15)
- return false;
- MI.addOperand(MCOperand::CreateReg(0));
- if (Opcode == ARM::BFI) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- ++OpIdx;
- }
- uint32_t mask = 0;
- if (!getBFCInvMask(insn, mask))
- return false;
-
- MI.addOperand(MCOperand::CreateImm(mask));
- OpIdx += 2;
- return true;
- }
- if (Opcode == ARM::SBFX || Opcode == ARM::UBFX) {
- // Sanity check Rd and Rm.
- if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
- return false;
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- MI.addOperand(MCOperand::CreateImm(slice(insn, 11, 7)));
- MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 16) + 1));
- OpIdx += 3;
- return true;
- }
-
- bool RmRn = (Opcode == ARM::QADD || Opcode == ARM::QDADD ||
- Opcode == ARM::QDSUB || Opcode == ARM::QSUB);
-
- // BinaryDP has an Rn operand.
- if (!isUnary) {
- assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, ARM::GPRRegClassID,
- RmRn ? decodeRm(insn) : decodeRn(insn))));
- ++OpIdx;
- }
-
- // If this is a two-address operand, skip it, e.g., MOVCCr operand 1.
- if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) {
- MI.addOperand(MCOperand::CreateReg(0));
- ++OpIdx;
- }
-
- // Now disassemble operand 2.
- if (OpIdx >= NumOps)
- return false;
-
- if (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) {
- // We have a reg/reg form.
- // Assert disabled because saturating operations, e.g., A8.6.127 QASX, are
- // routed here as well.
- // assert(getIBit(insn) == 0 && "I_Bit != '0' reg/reg form");
- if (BadRegsDPFrm(Opcode, insn))
- return false;
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, ARM::GPRRegClassID,
- RmRn? decodeRn(insn) : decodeRm(insn))));
- ++OpIdx;
- } else if (Opcode == ARM::MOVi16 || Opcode == ARM::MOVTi16) {
- // These two instructions don't allow d as 15.
- if (decodeRd(insn) == 15)
- return false;
- // We have an imm16 = imm4:imm12 (imm4=Inst{19:16}, imm12 = Inst{11:0}).
- assert(getIBit(insn) == 1 && "I_Bit != '1' reg/imm form");
- unsigned Imm16 = slice(insn, 19, 16) << 12 | slice(insn, 11, 0);
- if (!B->tryAddingSymbolicOperand(Imm16, 4, MI))
- MI.addOperand(MCOperand::CreateImm(Imm16));
- ++OpIdx;
- } else {
- // We have a reg/imm form.
- // SOImm is 4-bit rotate amount in bits 11-8 with 8-bit imm in bits 7-0.
- // A5.2.4 Rotate amount is twice the numeric value of Inst{11-8}.
- // See also ARMAddressingModes.h: getSOImmValImm() and getSOImmValRot().
- assert(getIBit(insn) == 1 && "I_Bit != '1' reg/imm form");
- unsigned Rot = (insn >> ARMII::SoRotImmShift) & 0xF;
- unsigned Imm = insn & 0xFF;
- MI.addOperand(MCOperand::CreateImm(ARM_AM::rotr32(Imm, 2*Rot)));
- ++OpIdx;
- }
-
- return true;
-}
-
-static bool DisassembleDPSoRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- unsigned short NumDefs = MCID.getNumDefs();
- bool isUnary = isUnaryDP(MCID.TSFlags);
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- // Disassemble register def if there is one.
- if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- ++OpIdx;
- }
-
- // Disassemble the src operands.
- if (OpIdx >= NumOps)
- return false;
-
- // BinaryDP has an Rn operand.
- if (!isUnary) {
- assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- ++OpIdx;
- }
-
- // If this is a two-address operand, skip it, e.g., MOVCCs operand 1.
- if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) {
- MI.addOperand(MCOperand::CreateReg(0));
- ++OpIdx;
- }
-
- // Disassemble operand 2, which consists of three components.
- if (OpIdx + 2 >= NumOps)
- return false;
-
- assert((OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) &&
- (OpInfo[OpIdx+1].RegClass == ARM::GPRRegClassID) &&
- (OpInfo[OpIdx+2].RegClass < 0) &&
- "Expect 3 reg operands");
-
- // Register-controlled shifts have Inst{7} = 0 and Inst{4} = 1.
- unsigned Rs = slice(insn, 4, 4);
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- if (Rs) {
- // If Inst{7} != 0, we should reject this insn as an invalid encoding.
- if (slice(insn, 7, 7))
- return false;
-
- // A8.6.3 ADC (register-shifted register)
- // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
- //
- // This also accounts for shift instructions (register) where, fortunately,
- // Inst{19-16} = 0b0000.
- // A8.6.89 LSL (register)
- // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
- if (decodeRd(insn) == 15 || decodeRn(insn) == 15 ||
- decodeRm(insn) == 15 || decodeRs(insn) == 15)
- return false;
-
- // Register-controlled shifts: [Rm, Rs, shift].
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRs(insn))));
- // Inst{6-5} encodes the shift opcode.
- ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
- MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, 0)));
- } else {
- // Constant shifts: [Rm, reg0, shift_imm].
- MI.addOperand(MCOperand::CreateReg(0)); // NoRegister
- // Inst{6-5} encodes the shift opcode.
- ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
- // Inst{11-7} encodes the imm5 shift amount.
- unsigned ShImm = slice(insn, 11, 7);
-
- // A8.4.1. Possible rrx or shift amount of 32...
- getImmShiftSE(ShOp, ShImm);
- MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShImm)));
- }
- OpIdx += 3;
-
- return true;
-}
-
-static bool BadRegsLdStFrm(unsigned Opcode, uint32_t insn, bool Store, bool WBack,
- bool Imm) {
- const StringRef Name = ARMInsts[Opcode].Name;
- unsigned Rt = decodeRd(insn);
- unsigned Rn = decodeRn(insn);
- unsigned Rm = decodeRm(insn);
- unsigned P = getPBit(insn);
- unsigned W = getWBit(insn);
-
- if (Store) {
- // Only STR (immediate, register) allows PC as the source.
- if (Name.startswith("STRB") && Rt == 15) {
- DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n");
- return true;
- }
- if (WBack && (Rn == 15 || Rn == Rt)) {
- DEBUG(errs() << "if wback && (n == 15 || n == t) then UNPREDICTABLE\n");
- return true;
- }
- if (!Imm && Rm == 15) {
- DEBUG(errs() << "if m == 15 then UNPREDICTABLE\n");
- return true;
- }
- } else {
- // Only LDR (immediate, register) allows PC as the destination.
- if (Name.startswith("LDRB") && Rt == 15) {
- DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n");
- return true;
- }
- if (Imm) {
- // Immediate
- if (Rn == 15) {
- // The literal form must be in offset mode; it's an encoding error
- // otherwise.
- if (!(P == 1 && W == 0)) {
- DEBUG(errs() << "Ld literal form with !(P == 1 && W == 0)\n");
- return true;
- }
- // LDRB (literal) does not allow PC as the destination.
- if (Opcode != ARM::LDRi12 && Rt == 15) {
- DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n");
- return true;
- }
- } else {
- // Write back while Rn == Rt does not make sense.
- if (WBack && (Rn == Rt)) {
- DEBUG(errs() << "if wback && n == t then UNPREDICTABLE\n");
- return true;
- }
- }
- } else {
- // Register
- if (Rm == 15) {
- DEBUG(errs() << "if m == 15 then UNPREDICTABLE\n");
- return true;
- }
- if (WBack && (Rn == 15 || Rn == Rt)) {
- DEBUG(errs() << "if wback && (n == 15 || n == t) then UNPREDICTABLE\n");
- return true;
- }
- }
- }
- return false;
-}
-
-static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- bool isPrePost = isPrePostLdSt(MCID.TSFlags);
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- if (!OpInfo) return false;
-
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(((!isStore && MCID.getNumDefs() > 0) ||
- (isStore && (MCID.getNumDefs() == 0 || isPrePost)))
- && "Invalid arguments");
-
- // Operand 0 of a pre- and post-indexed store is the address base writeback.
- if (isPrePost && isStore) {
- assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- ++OpIdx;
- }
-
- // Disassemble the dst/src operand.
- if (OpIdx >= NumOps)
- return false;
-
- assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- ++OpIdx;
-
- // After dst of a pre- and post-indexed load is the address base writeback.
- if (isPrePost && !isStore) {
- assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- ++OpIdx;
- }
-
- // Disassemble the base operand.
- if (OpIdx >= NumOps)
- return false;
-
- assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1))
- && "Index mode or tied_to operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- ++OpIdx;
-
- // For reg/reg form, base reg is followed by +/- reg shop imm.
- // For immediate form, it is followed by +/- imm12.
- // See also ARMAddressingModes.h (Addressing Mode #2).
- if (OpIdx + 1 >= NumOps)
- return false;
-
- if (BadRegsLdStFrm(Opcode, insn, isStore, isPrePost, getIBit(insn)==0))
- return false;
-
- ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
- unsigned IndexMode =
- (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
- if (getIBit(insn) == 0) {
- // For pre- and post-indexed case, add a reg0 operand (Addressing Mode #2).
- // Otherwise, skip the reg operand since for addrmode_imm12, Rn has already
- // been populated.
- if (isPrePost) {
- MI.addOperand(MCOperand::CreateReg(0));
- OpIdx += 1;
- }
-
- unsigned Imm12 = slice(insn, 11, 0);
- if (Opcode == ARM::LDRBi12 || Opcode == ARM::LDRi12 ||
- Opcode == ARM::STRBi12 || Opcode == ARM::STRi12) {
- // Disassemble the 12-bit immediate offset, which is the second operand in
- // $addrmode_imm12 => (ops GPR:$base, i32imm:$offsimm).
- int Offset = AddrOpcode == ARM_AM::add ? 1 * Imm12 : -1 * Imm12;
- MI.addOperand(MCOperand::CreateImm(Offset));
- } else {
- // Disassemble the 12-bit immediate offset, which is the second operand in
- // $am2offset => (ops GPR, i32imm).
- unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift,
- IndexMode);
- MI.addOperand(MCOperand::CreateImm(Offset));
- }
- OpIdx += 1;
- } else {
- // If Inst{25} = 1 and Inst{4} != 0, we should reject this as invalid.
- if (slice(insn,4,4) == 1)
- return false;
-
- // Disassemble the offset reg (Rm), shift type, and immediate shift length.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- // Inst{6-5} encodes the shift opcode.
- ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
- // Inst{11-7} encodes the imm5 shift amount.
- unsigned ShImm = slice(insn, 11, 7);
-
- // A8.4.1. Possible rrx or shift amount of 32...
- getImmShiftSE(ShOp, ShImm);
- MI.addOperand(MCOperand::CreateImm(
- ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp, IndexMode)));
- OpIdx += 2;
- }
-
- return true;
-}
-
-static bool DisassembleLdFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- return DisassembleLdStFrm(MI, Opcode, insn, NumOps, NumOpsAdded, false, B);
-}
-
-static bool DisassembleStFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- return DisassembleLdStFrm(MI, Opcode, insn, NumOps, NumOpsAdded, true, B);
-}
-
-static bool HasDualReg(unsigned Opcode) {
- switch (Opcode) {
- default:
- return false;
- case ARM::LDRD: case ARM::LDRD_PRE: case ARM::LDRD_POST:
- case ARM::STRD: case ARM::STRD_PRE: case ARM::STRD_POST:
- return true;
- }
-}
-
-static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- bool isPrePost = isPrePostLdSt(MCID.TSFlags);
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- if (!OpInfo) return false;
-
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(((!isStore && MCID.getNumDefs() > 0) ||
- (isStore && (MCID.getNumDefs() == 0 || isPrePost)))
- && "Invalid arguments");
-
- // Operand 0 of a pre- and post-indexed store is the address base writeback.
- if (isPrePost && isStore) {
- assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- ++OpIdx;
- }
-
- // Disassemble the dst/src operand.
- if (OpIdx >= NumOps)
- return false;
-
- assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- ++OpIdx;
-
- // Fill in LDRD and STRD's second operand Rt operand.
- if (HasDualReg(Opcode)) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn) + 1)));
- ++OpIdx;
- }
-
- // After dst of a pre- and post-indexed load is the address base writeback.
- if (isPrePost && !isStore) {
- assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- ++OpIdx;
- }
-
- // Disassemble the base operand.
- if (OpIdx >= NumOps)
- return false;
-
- assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
- assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1))
- && "Offset mode or tied_to operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- ++OpIdx;
-
- // For reg/reg form, base reg is followed by +/- reg.
- // For immediate form, it is followed by +/- imm8.
- // See also ARMAddressingModes.h (Addressing Mode #3).
- if (OpIdx + 1 >= NumOps)
- return false;
-
- assert((OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) &&
- (OpInfo[OpIdx+1].RegClass < 0) &&
- "Expect 1 reg operand followed by 1 imm operand");
-
- ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
- unsigned IndexMode =
- (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
- if (getAM3IBit(insn) == 1) {
- MI.addOperand(MCOperand::CreateReg(0));
-
- // Disassemble the 8-bit immediate offset.
- unsigned Imm4H = (insn >> ARMII::ImmHiShift) & 0xF;
- unsigned Imm4L = insn & 0xF;
- unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L,
- IndexMode);
- MI.addOperand(MCOperand::CreateImm(Offset));
- } else {
- // Disassemble the offset reg (Rm).
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0, IndexMode);
- MI.addOperand(MCOperand::CreateImm(Offset));
- }
- OpIdx += 2;
-
- return true;
-}
-
-static bool DisassembleLdMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- return DisassembleLdStMiscFrm(MI, Opcode, insn, NumOps, NumOpsAdded, false,
- B);
-}
-
-static bool DisassembleStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- return DisassembleLdStMiscFrm(MI, Opcode, insn, NumOps, NumOpsAdded, true, B);
-}
-
-// The algorithm for disassembly of LdStMulFrm is different from others because
-// it explicitly populates the two predicate operands after the base register.
-// After that, we need to populate the reglist with each affected register
-// encoded as an MCOperand.
-static bool DisassembleLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 4 && "LdStMulFrm expects NumOps >= 4");
- NumOpsAdded = 0;
-
- unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
-
- // Writeback to base, if necessary.
- if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::STMIA_UPD ||
- Opcode == ARM::LDMDA_UPD || Opcode == ARM::STMDA_UPD ||
- Opcode == ARM::LDMDB_UPD || Opcode == ARM::STMDB_UPD ||
- Opcode == ARM::LDMIB_UPD || Opcode == ARM::STMIB_UPD) {
- MI.addOperand(MCOperand::CreateReg(Base));
- ++NumOpsAdded;
- }
-
- // Add the base register operand.
- MI.addOperand(MCOperand::CreateReg(Base));
-
- // Handling the two predicate operands before the reglist.
- int64_t CondVal = getCondField(insn);
- if (CondVal == 0xF)
- return false;
- MI.addOperand(MCOperand::CreateImm(CondVal));
- MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
-
- NumOpsAdded += 3;
-
- // Fill the variadic part of reglist.
- unsigned RegListBits = insn & ((1 << 16) - 1);
- for (unsigned i = 0; i < 16; ++i) {
- if ((RegListBits >> i) & 1) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- i)));
- ++NumOpsAdded;
- }
- }
-
- return true;
-}
-
-// LDREX, LDREXB, LDREXH: Rd Rn
-// LDREXD: Rd Rd+1 Rn
-// STREX, STREXB, STREXH: Rd Rm Rn
-// STREXD: Rd Rm Rm+1 Rn
-//
-// SWP, SWPB: Rd Rm Rn
-static bool DisassembleLdStExFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(NumOps >= 2
- && OpInfo[0].RegClass == ARM::GPRRegClassID
- && OpInfo[1].RegClass == ARM::GPRRegClassID
- && "Expect 2 reg operands");
-
- bool isStore = slice(insn, 20, 20) == 0;
- bool isDW = (Opcode == ARM::LDREXD || Opcode == ARM::STREXD);
-
- // Add the destination operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- ++OpIdx;
-
- // Store register Exclusive needs a source operand.
- if (isStore) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- ++OpIdx;
-
- if (isDW) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn)+1)));
- ++OpIdx;
- }
- } else if (isDW) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn)+1)));
- ++OpIdx;
- }
-
- // Finally add the pointer operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- ++OpIdx;
-
- return true;
-}
-
-// Misc. Arithmetic Instructions.
-// CLZ: Rd Rm
-// PKHBT, PKHTB: Rd Rn Rm , LSL/ASR #imm5
-// RBIT, REV, REV16, REVSH: Rd Rm
-static bool DisassembleArithMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(NumOps >= 2
- && OpInfo[0].RegClass == ARM::GPRRegClassID
- && OpInfo[1].RegClass == ARM::GPRRegClassID
- && "Expect 2 reg operands");
-
- bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::GPRRegClassID;
-
- // Sanity check the registers, which should not be 15.
- if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
- return false;
- if (ThreeReg && decodeRn(insn) == 15)
- return false;
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- ++OpIdx;
-
- if (ThreeReg) {
- assert(NumOps >= 4 && "Expect >= 4 operands");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- ++OpIdx;
- }
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- ++OpIdx;
-
- // If there is still an operand info left which is an immediate operand, add
- // an additional imm5 LSL/ASR operand.
- if (ThreeReg && OpInfo[OpIdx].RegClass < 0
- && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
- // Extract the 5-bit immediate field Inst{11-7}.
- unsigned ShiftAmt = (insn >> ARMII::ShiftShift) & 0x1F;
- ARM_AM::ShiftOpc Opc = ARM_AM::no_shift;
- if (Opcode == ARM::PKHBT)
- Opc = ARM_AM::lsl;
- else if (Opcode == ARM::PKHTB)
- Opc = ARM_AM::asr;
- getImmShiftSE(Opc, ShiftAmt);
- MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(Opc, ShiftAmt)));
- ++OpIdx;
- }
-
- return true;
-}
-
-/// DisassembleSatFrm - Disassemble saturate instructions:
-/// SSAT, SSAT16, USAT, and USAT16.
-static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- // A8.6.183 SSAT
- // if d == 15 || n == 15 then UNPREDICTABLE;
- if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
- return false;
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands
-
- // Disassemble register def.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
-
- unsigned Pos = slice(insn, 20, 16);
- if (Opcode == ARM::SSAT || Opcode == ARM::SSAT16)
- Pos += 1;
- MI.addOperand(MCOperand::CreateImm(Pos));
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
-
- if (NumOpsAdded == 4) {
- ARM_AM::ShiftOpc Opc = (slice(insn, 6, 6) != 0 ? ARM_AM::asr : ARM_AM::lsl);
- // Inst{11-7} encodes the imm5 shift amount.
- unsigned ShAmt = slice(insn, 11, 7);
- if (ShAmt == 0) {
- // A8.6.183. Possible ASR shift amount of 32...
- if (Opc == ARM_AM::asr)
- ShAmt = 32;
- else
- Opc = ARM_AM::no_shift;
- }
- MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(Opc, ShAmt)));
- }
- return true;
-}
-
-// Extend instructions.
-// SXT* and UXT*: Rd [Rn] Rm [rot_imm].
-// The 2nd operand register is Rn and the 3rd operand regsiter is Rm for the
-// three register operand form. Otherwise, Rn=0b1111 and only Rm is used.
-static bool DisassembleExtFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- // A8.6.220 SXTAB
- // if d == 15 || m == 15 then UNPREDICTABLE;
- if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
- return false;
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(NumOps >= 2
- && OpInfo[0].RegClass == ARM::GPRRegClassID
- && OpInfo[1].RegClass == ARM::GPRRegClassID
- && "Expect 2 reg operands");
-
- bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::GPRRegClassID;
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- ++OpIdx;
-
- if (ThreeReg) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- ++OpIdx;
- }
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- ++OpIdx;
-
- // If there is still an operand info left which is an immediate operand, add
- // an additional rotate immediate operand.
- if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
- && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
- // Extract the 2-bit rotate field Inst{11-10}.
- unsigned rot = (insn >> ARMII::ExtRotImmShift) & 3;
- // Rotation by 8, 16, or 24 bits.
- MI.addOperand(MCOperand::CreateImm(rot << 3));
- ++OpIdx;
- }
-
- return true;
-}
-
-/////////////////////////////////////
-// //
-// Utility Functions For VFP //
-// //
-/////////////////////////////////////
-
-// Extract/Decode Dd/Sd:
-//
-// SP => d = UInt(Vd:D)
-// DP => d = UInt(D:Vd)
-static unsigned decodeVFPRd(uint32_t insn, bool isSPVFP) {
- return isSPVFP ? (decodeRd(insn) << 1 | getDBit(insn))
- : (decodeRd(insn) | getDBit(insn) << 4);
-}
-
-// Extract/Decode Dn/Sn:
-//
-// SP => n = UInt(Vn:N)
-// DP => n = UInt(N:Vn)
-static unsigned decodeVFPRn(uint32_t insn, bool isSPVFP) {
- return isSPVFP ? (decodeRn(insn) << 1 | getNBit(insn))
- : (decodeRn(insn) | getNBit(insn) << 4);
-}
-
-// Extract/Decode Dm/Sm:
-//
-// SP => m = UInt(Vm:M)
-// DP => m = UInt(M:Vm)
-static unsigned decodeVFPRm(uint32_t insn, bool isSPVFP) {
- return isSPVFP ? (decodeRm(insn) << 1 | getMBit(insn))
- : (decodeRm(insn) | getMBit(insn) << 4);
-}
-
-// A7.5.1
-static APInt VFPExpandImm(unsigned char byte, unsigned N) {
- assert(N == 32 || N == 64);
-
- uint64_t Result;
- unsigned bit6 = slice(byte, 6, 6);
- if (N == 32) {
- Result = slice(byte, 7, 7) << 31 | slice(byte, 5, 0) << 19;
- if (bit6)
- Result |= 0x1f << 25;
- else
- Result |= 0x1 << 30;
- } else {
- Result = (uint64_t)slice(byte, 7, 7) << 63 |
- (uint64_t)slice(byte, 5, 0) << 48;
- if (bit6)
- Result |= 0xffULL << 54;
- else
- Result |= 0x1ULL << 62;
- }
- return APInt(N, Result);
-}
-
-// VFP Unary Format Instructions:
-//
-// VCMP[E]ZD, VCMP[E]ZS: compares one floating-point register with zero
-// VCVTDS, VCVTSD: converts between double-precision and single-precision
-// The rest of the instructions have homogeneous [VFP]Rd and [VFP]Rm registers.
-static bool DisassembleVFPUnaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 1 && "VFPUnaryFrm expects NumOps >= 1");
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- unsigned RegClass = OpInfo[OpIdx].RegClass;
- assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) &&
- "Reg operand expected");
- bool isSP = (RegClass == ARM::SPRRegClassID);
-
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, RegClass, decodeVFPRd(insn, isSP))));
- ++OpIdx;
-
- // Early return for compare with zero instructions.
- if (Opcode == ARM::VCMPEZD || Opcode == ARM::VCMPEZS
- || Opcode == ARM::VCMPZD || Opcode == ARM::VCMPZS)
- return true;
-
- RegClass = OpInfo[OpIdx].RegClass;
- assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) &&
- "Reg operand expected");
- isSP = (RegClass == ARM::SPRRegClassID);
-
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, RegClass, decodeVFPRm(insn, isSP))));
- ++OpIdx;
-
- return true;
-}
-
-// All the instructions have homogeneous [VFP]Rd, [VFP]Rn, and [VFP]Rm regs.
-// Some of them have operand constraints which tie the first operand in the
-// InOperandList to that of the dst. As far as asm printing is concerned, this
-// tied_to operand is simply skipped.
-static bool DisassembleVFPBinaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 3 && "VFPBinaryFrm expects NumOps >= 3");
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- unsigned RegClass = OpInfo[OpIdx].RegClass;
- assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) &&
- "Reg operand expected");
- bool isSP = (RegClass == ARM::SPRRegClassID);
-
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, RegClass, decodeVFPRd(insn, isSP))));
- ++OpIdx;
-
- // Skip tied_to operand constraint.
- if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
- assert(NumOps >= 4 && "Expect >=4 operands");
- MI.addOperand(MCOperand::CreateReg(0));
- ++OpIdx;
- }
-
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, RegClass, decodeVFPRn(insn, isSP))));
- ++OpIdx;
-
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, RegClass, decodeVFPRm(insn, isSP))));
- ++OpIdx;
-
- return true;
-}
-
-// A8.6.295 vcvt (floating-point <-> integer)
-// Int to FP: VSITOD, VSITOS, VUITOD, VUITOS
-// FP to Int: VTOSI[Z|R]D, VTOSI[Z|R]S, VTOUI[Z|R]D, VTOUI[Z|R]S
-//
-// A8.6.297 vcvt (floating-point and fixed-point)
-// Dd|Sd Dd|Sd(TIED_TO) #fbits(= 16|32 - UInt(imm4:i))
-static bool DisassembleVFPConv1Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 2 && "VFPConv1Frm expects NumOps >= 2");
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- if (!OpInfo) return false;
-
- bool SP = slice(insn, 8, 8) == 0; // A8.6.295 & A8.6.297
- bool fixed_point = slice(insn, 17, 17) == 1; // A8.6.297
- unsigned RegClassID = SP ? ARM::SPRRegClassID : ARM::DPRRegClassID;
-
- if (fixed_point) {
- // A8.6.297
- assert(NumOps >= 3 && "Expect >= 3 operands");
- int size = slice(insn, 7, 7) == 0 ? 16 : 32;
- int fbits = size - (slice(insn,3,0) << 1 | slice(insn,5,5));
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, RegClassID,
- decodeVFPRd(insn, SP))));
-
- assert(MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 &&
- "Tied to operand expected");
- MI.addOperand(MI.getOperand(0));
-
- assert(OpInfo[2].RegClass < 0 && !OpInfo[2].isPredicate() &&
- !OpInfo[2].isOptionalDef() && "Imm operand expected");
- MI.addOperand(MCOperand::CreateImm(fbits));
-
- NumOpsAdded = 3;
- } else {
- // A8.6.295
- // The Rd (destination) and Rm (source) bits have different interpretations
- // depending on their single-precisonness.
- unsigned d, m;
- if (slice(insn, 18, 18) == 1) { // to_integer operation
- d = decodeVFPRd(insn, true /* Is Single Precision */);
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, ARM::SPRRegClassID, d)));
- m = decodeVFPRm(insn, SP);
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, m)));
- } else {
- d = decodeVFPRd(insn, SP);
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, d)));
- m = decodeVFPRm(insn, true /* Is Single Precision */);
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, ARM::SPRRegClassID, m)));
- }
- NumOpsAdded = 2;
- }
-
- return true;
-}
-
-// VMOVRS - A8.6.330
-// Rt => Rd; Sn => UInt(Vn:N)
-static bool DisassembleVFPConv2Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 2 && "VFPConv2Frm expects NumOps >= 2");
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
- decodeVFPRn(insn, true))));
- NumOpsAdded = 2;
- return true;
-}
-
-// VMOVRRD - A8.6.332
-// Rt => Rd; Rt2 => Rn; Dm => UInt(M:Vm)
-//
-// VMOVRRS - A8.6.331
-// Rt => Rd; Rt2 => Rn; Sm => UInt(Vm:M); Sm1 = Sm+1
-static bool DisassembleVFPConv3Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 3 && "VFPConv3Frm expects NumOps >= 3");
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- OpIdx = 2;
-
- if (OpInfo[OpIdx].RegClass == ARM::SPRRegClassID) {
- unsigned Sm = decodeVFPRm(insn, true);
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
- Sm)));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
- Sm+1)));
- OpIdx += 2;
- } else {
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, ARM::DPRRegClassID,
- decodeVFPRm(insn, false))));
- ++OpIdx;
- }
- return true;
-}
-
-// VMOVSR - A8.6.330
-// Rt => Rd; Sn => UInt(Vn:N)
-static bool DisassembleVFPConv4Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 2 && "VFPConv4Frm expects NumOps >= 2");
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
- decodeVFPRn(insn, true))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- NumOpsAdded = 2;
- return true;
-}
-
-// VMOVDRR - A8.6.332
-// Rt => Rd; Rt2 => Rn; Dm => UInt(M:Vm)
-//
-// VMOVRRS - A8.6.331
-// Rt => Rd; Rt2 => Rn; Sm => UInt(Vm:M); Sm1 = Sm+1
-static bool DisassembleVFPConv5Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 3 && "VFPConv5Frm expects NumOps >= 3");
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- if (OpInfo[OpIdx].RegClass == ARM::SPRRegClassID) {
- unsigned Sm = decodeVFPRm(insn, true);
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
- Sm)));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
- Sm+1)));
- OpIdx += 2;
- } else {
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, ARM::DPRRegClassID,
- decodeVFPRm(insn, false))));
- ++OpIdx;
- }
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- OpIdx += 2;
- return true;
-}
-
-// VFP Load/Store Instructions.
-// VLDRD, VLDRS, VSTRD, VSTRS
-static bool DisassembleVFPLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 3 && "VFPLdStFrm expects NumOps >= 3");
-
- bool isSPVFP = (Opcode == ARM::VLDRS || Opcode == ARM::VSTRS);
- unsigned RegClassID = isSPVFP ? ARM::SPRRegClassID : ARM::DPRRegClassID;
-
- // Extract Dd/Sd for operand 0.
- unsigned RegD = decodeVFPRd(insn, isSPVFP);
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, RegD)));
-
- unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
- MI.addOperand(MCOperand::CreateReg(Base));
-
- // Next comes the AM5 Opcode.
- ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
- unsigned char Imm8 = insn & 0xFF;
- MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(AddrOpcode, Imm8)));
-
- NumOpsAdded = 3;
-
- return true;
-}
-
-// VFP Load/Store Multiple Instructions.
-// We have an optional write back reg, the base, and two predicate operands.
-// It is then followed by a reglist of either DPR(s) or SPR(s).
-//
-// VLDMD[_UPD], VLDMS[_UPD], VSTMD[_UPD], VSTMS[_UPD]
-static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 4 && "VFPLdStMulFrm expects NumOps >= 4");
-
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
-
- // Writeback to base, if necessary.
- if (Opcode == ARM::VLDMDIA_UPD || Opcode == ARM::VLDMSIA_UPD ||
- Opcode == ARM::VLDMDDB_UPD || Opcode == ARM::VLDMSDB_UPD ||
- Opcode == ARM::VSTMDIA_UPD || Opcode == ARM::VSTMSIA_UPD ||
- Opcode == ARM::VSTMDDB_UPD || Opcode == ARM::VSTMSDB_UPD) {
- MI.addOperand(MCOperand::CreateReg(Base));
- ++OpIdx;
- }
-
- MI.addOperand(MCOperand::CreateReg(Base));
-
- // Handling the two predicate operands before the reglist.
- int64_t CondVal = getCondField(insn);
- if (CondVal == 0xF)
- return false;
- MI.addOperand(MCOperand::CreateImm(CondVal));
- MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
-
- OpIdx += 3;
-
- bool isSPVFP = (Opcode == ARM::VLDMSIA ||
- Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMSDB_UPD ||
- Opcode == ARM::VSTMSIA ||
- Opcode == ARM::VSTMSIA_UPD || Opcode == ARM::VSTMSDB_UPD);
- unsigned RegClassID = isSPVFP ? ARM::SPRRegClassID : ARM::DPRRegClassID;
-
- // Extract Dd/Sd.
- unsigned RegD = decodeVFPRd(insn, isSPVFP);
-
- // Fill the variadic part of reglist.
- unsigned char Imm8 = insn & 0xFF;
- unsigned Regs = isSPVFP ? Imm8 : Imm8/2;
-
- // Apply some sanity checks before proceeding.
- if (Regs == 0 || (RegD + Regs) > 32 || (!isSPVFP && Regs > 16))
- return false;
-
- for (unsigned i = 0; i < Regs; ++i) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID,
- RegD + i)));
- ++OpIdx;
- }
-
- return true;
-}
-
-// Misc. VFP Instructions.
-// FMSTAT (vmrs with Rt=0b1111, i.e., to apsr_nzcv and no register operand)
-// FCONSTD (DPR and a VFPf64Imm operand)
-// FCONSTS (SPR and a VFPf32Imm operand)
-// VMRS/VMSR (GPR operand)
-static bool DisassembleVFPMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- if (Opcode == ARM::FMSTAT)
- return true;
-
- assert(NumOps >= 2 && "VFPMiscFrm expects >=2 operands");
-
- unsigned RegEnum = 0;
- switch (OpInfo[0].RegClass) {
- case ARM::DPRRegClassID:
- RegEnum = getRegisterEnum(B, ARM::DPRRegClassID, decodeVFPRd(insn, false));
- break;
- case ARM::SPRRegClassID:
- RegEnum = getRegisterEnum(B, ARM::SPRRegClassID, decodeVFPRd(insn, true));
- break;
- case ARM::GPRRegClassID:
- RegEnum = getRegisterEnum(B, ARM::GPRRegClassID, decodeRd(insn));
- break;
- default:
- assert(0 && "Invalid reg class id");
- return false;
- }
-
- MI.addOperand(MCOperand::CreateReg(RegEnum));
- ++OpIdx;
-
- // Extract/decode the f64/f32 immediate.
- if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
- && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
- // The asm syntax specifies the floating point value, not the 8-bit literal.
- APInt immRaw = VFPExpandImm(slice(insn,19,16) << 4 | slice(insn, 3, 0),
- Opcode == ARM::FCONSTD ? 64 : 32);
- APFloat immFP = APFloat(immRaw, true);
- double imm = Opcode == ARM::FCONSTD ? immFP.convertToDouble() :
- immFP.convertToFloat();
- MI.addOperand(MCOperand::CreateFPImm(imm));
-
- ++OpIdx;
- }
-
- return true;
-}
-
-// DisassembleThumbFrm() is defined in ThumbDisassemblerCore.h file.
-#include "ThumbDisassemblerCore.h"
-
-/////////////////////////////////////////////////////
-// //
-// Utility Functions For ARM Advanced SIMD //
-// //
-/////////////////////////////////////////////////////
-
-// The following NEON namings are based on A8.6.266 VABA, VABAL. Notice that
-// A8.6.303 VDUP (ARM core register)'s D/Vd pair is the N/Vn pair of VABA/VABAL.
-
-// A7.3 Register encoding
-
-// Extract/Decode NEON D/Vd:
-//
-// Note that for quadword, Qd = UInt(D:Vd<3:1>) = Inst{22:15-13}, whereas for
-// doubleword, Dd = UInt(D:Vd). We compensate for this difference by
-// handling it in the getRegisterEnum() utility function.
-// D = Inst{22}, Vd = Inst{15-12}
-static unsigned decodeNEONRd(uint32_t insn) {
- return ((insn >> ARMII::NEON_D_BitShift) & 1) << 4
- | ((insn >> ARMII::NEON_RegRdShift) & ARMII::NEONRegMask);
-}
-
-// Extract/Decode NEON N/Vn:
-//
-// Note that for quadword, Qn = UInt(N:Vn<3:1>) = Inst{7:19-17}, whereas for
-// doubleword, Dn = UInt(N:Vn). We compensate for this difference by
-// handling it in the getRegisterEnum() utility function.
-// N = Inst{7}, Vn = Inst{19-16}
-static unsigned decodeNEONRn(uint32_t insn) {
- return ((insn >> ARMII::NEON_N_BitShift) & 1) << 4
- | ((insn >> ARMII::NEON_RegRnShift) & ARMII::NEONRegMask);
-}
-
-// Extract/Decode NEON M/Vm:
-//
-// Note that for quadword, Qm = UInt(M:Vm<3:1>) = Inst{5:3-1}, whereas for
-// doubleword, Dm = UInt(M:Vm). We compensate for this difference by
-// handling it in the getRegisterEnum() utility function.
-// M = Inst{5}, Vm = Inst{3-0}
-static unsigned decodeNEONRm(uint32_t insn) {
- return ((insn >> ARMII::NEON_M_BitShift) & 1) << 4
- | ((insn >> ARMII::NEON_RegRmShift) & ARMII::NEONRegMask);
-}
-
-namespace {
-enum ElemSize {
- ESizeNA = 0,
- ESize8 = 8,
- ESize16 = 16,
- ESize32 = 32,
- ESize64 = 64
-};
-} // End of unnamed namespace
-
-// size field -> Inst{11-10}
-// index_align field -> Inst{7-4}
-//
-// The Lane Index interpretation depends on the Data Size:
-// 8 (encoded as size = 0b00) -> Index = index_align[3:1]
-// 16 (encoded as size = 0b01) -> Index = index_align[3:2]
-// 32 (encoded as size = 0b10) -> Index = index_align[3]
-//
-// Ref: A8.6.317 VLD4 (single 4-element structure to one lane).
-static unsigned decodeLaneIndex(uint32_t insn) {
- unsigned size = insn >> 10 & 3;
- assert((size == 0 || size == 1 || size == 2) &&
- "Encoding error: size should be either 0, 1, or 2");
-
- unsigned index_align = insn >> 4 & 0xF;
- return (index_align >> 1) >> size;
-}
-
-// imm64 = AdvSIMDExpandImm(op, cmode, i:imm3:imm4)
-// op = Inst{5}, cmode = Inst{11-8}
-// i = Inst{24} (ARM architecture)
-// imm3 = Inst{18-16}, imm4 = Inst{3-0}
-// Ref: Table A7-15 Modified immediate values for Advanced SIMD instructions.
-static uint64_t decodeN1VImm(uint32_t insn, ElemSize esize) {
- unsigned char op = (insn >> 5) & 1;
- unsigned char cmode = (insn >> 8) & 0xF;
- unsigned char Imm8 = ((insn >> 24) & 1) << 7 |
- ((insn >> 16) & 7) << 4 |
- (insn & 0xF);
- return (op << 12) | (cmode << 8) | Imm8;
-}
-
-// A8.6.339 VMUL, VMULL (by scalar)
-// ESize16 => m = Inst{2-0} (Vm<2:0>) D0-D7
-// ESize32 => m = Inst{3-0} (Vm<3:0>) D0-D15
-static unsigned decodeRestrictedDm(uint32_t insn, ElemSize esize) {
- switch (esize) {
- case ESize16:
- return insn & 7;
- case ESize32:
- return insn & 0xF;
- default:
- assert(0 && "Unreachable code!");
- return 0;
- }
-}
-
-// A8.6.339 VMUL, VMULL (by scalar)
-// ESize16 => index = Inst{5:3} (M:Vm<3>) D0-D7
-// ESize32 => index = Inst{5} (M) D0-D15
-static unsigned decodeRestrictedDmIndex(uint32_t insn, ElemSize esize) {
- switch (esize) {
- case ESize16:
- return (((insn >> 5) & 1) << 1) | ((insn >> 3) & 1);
- case ESize32:
- return (insn >> 5) & 1;
- default:
- assert(0 && "Unreachable code!");
- return 0;
- }
-}
-
-// A8.6.296 VCVT (between floating-point and fixed-point, Advanced SIMD)
-// (64 - <fbits>) is encoded as imm6, i.e., Inst{21-16}.
-static unsigned decodeVCVTFractionBits(uint32_t insn) {
- return 64 - ((insn >> 16) & 0x3F);
-}
-
-// A8.6.302 VDUP (scalar)
-// ESize8 => index = Inst{19-17}
-// ESize16 => index = Inst{19-18}
-// ESize32 => index = Inst{19}
-static unsigned decodeNVLaneDupIndex(uint32_t insn, ElemSize esize) {
- switch (esize) {
- case ESize8:
- return (insn >> 17) & 7;
- case ESize16:
- return (insn >> 18) & 3;
- case ESize32:
- return (insn >> 19) & 1;
- default:
- assert(0 && "Unspecified element size!");
- return 0;
- }
-}
-
-// A8.6.328 VMOV (ARM core register to scalar)
-// A8.6.329 VMOV (scalar to ARM core register)
-// ESize8 => index = Inst{21:6-5}
-// ESize16 => index = Inst{21:6}
-// ESize32 => index = Inst{21}
-static unsigned decodeNVLaneOpIndex(uint32_t insn, ElemSize esize) {
- switch (esize) {
- case ESize8:
- return ((insn >> 21) & 1) << 2 | ((insn >> 5) & 3);
- case ESize16:
- return ((insn >> 21) & 1) << 1 | ((insn >> 6) & 1);
- case ESize32:
- return ((insn >> 21) & 1);
- default:
- assert(0 && "Unspecified element size!");
- return 0;
- }
-}
-
-// Imm6 = Inst{21-16}, L = Inst{7}
-//
-// LeftShift == true (A8.6.367 VQSHL, A8.6.387 VSLI):
-// case L:imm6 of
-// '0001xxx' => esize = 8; shift_amount = imm6 - 8
-// '001xxxx' => esize = 16; shift_amount = imm6 - 16
-// '01xxxxx' => esize = 32; shift_amount = imm6 - 32
-// '1xxxxxx' => esize = 64; shift_amount = imm6
-//
-// LeftShift == false (A8.6.376 VRSHR, A8.6.368 VQSHRN):
-// case L:imm6 of
-// '0001xxx' => esize = 8; shift_amount = 16 - imm6
-// '001xxxx' => esize = 16; shift_amount = 32 - imm6
-// '01xxxxx' => esize = 32; shift_amount = 64 - imm6
-// '1xxxxxx' => esize = 64; shift_amount = 64 - imm6
-//
-static unsigned decodeNVSAmt(uint32_t insn, bool LeftShift) {
- ElemSize esize = ESizeNA;
- unsigned L = (insn >> 7) & 1;
- unsigned imm6 = (insn >> 16) & 0x3F;
- if (L == 0) {
- if (imm6 >> 3 == 1)
- esize = ESize8;
- else if (imm6 >> 4 == 1)
- esize = ESize16;
- else if (imm6 >> 5 == 1)
- esize = ESize32;
- else
- assert(0 && "Wrong encoding of Inst{7:21-16}!");
- } else
- esize = ESize64;
-
- if (LeftShift)
- return esize == ESize64 ? imm6 : (imm6 - esize);
- else
- return esize == ESize64 ? (esize - imm6) : (2*esize - imm6);
-}
-
-// A8.6.305 VEXT
-// Imm4 = Inst{11-8}
-static unsigned decodeN3VImm(uint32_t insn) {
- return (insn >> 8) & 0xF;
-}
-
-// VLD*
-// D[d] D[d2] ... Rn [TIED_TO Rn] align [Rm]
-// VLD*LN*
-// D[d] D[d2] ... Rn [TIED_TO Rn] align [Rm] TIED_TO ... imm(idx)
-// VST*
-// Rn [TIED_TO Rn] align [Rm] D[d] D[d2] ...
-// VST*LN*
-// Rn [TIED_TO Rn] align [Rm] D[d] D[d2] ... [imm(idx)]
-//
-// Correctly set VLD*/VST*'s TIED_TO GPR, as the asm printer needs it.
-static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, bool Store, bool DblSpaced,
- unsigned alignment, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
-
- // At least one DPR register plus addressing mode #6.
- assert(NumOps >= 3 && "Expect >= 3 operands");
-
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- // We have homogeneous NEON registers for Load/Store.
- unsigned RegClass = 0;
-
- // Double-spaced registers have increments of 2.
- unsigned Inc = DblSpaced ? 2 : 1;
-
- unsigned Rn = decodeRn(insn);
- unsigned Rm = decodeRm(insn);
- unsigned Rd = decodeNEONRd(insn);
-
- // A7.7.1 Advanced SIMD addressing mode.
- bool WB = Rm != 15;
-
- // LLVM Addressing Mode #6.
- unsigned RmEnum = 0;
- if (WB && Rm != 13)
- RmEnum = getRegisterEnum(B, ARM::GPRRegClassID, Rm);
-
- if (Store) {
- // Consume possible WB, AddrMode6, possible increment reg, the DPR/QPR's,
- // then possible lane index.
- assert(OpIdx < NumOps && OpInfo[0].RegClass == ARM::GPRRegClassID &&
- "Reg operand expected");
-
- if (WB) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- Rn)));
- ++OpIdx;
- }
-
- assert((OpIdx+1) < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- OpInfo[OpIdx + 1].RegClass < 0 && "Addrmode #6 Operands expected");
- // addrmode6 := (ops GPR:$addr, i32imm)
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- Rn)));
- MI.addOperand(MCOperand::CreateImm(alignment)); // Alignment
- OpIdx += 2;
-
- if (WB) {
- MI.addOperand(MCOperand::CreateReg(RmEnum));
- ++OpIdx;
- }
-
- assert(OpIdx < NumOps &&
- (OpInfo[OpIdx].RegClass == ARM::DPRRegClassID ||
- OpInfo[OpIdx].RegClass == ARM::QPRRegClassID) &&
- "Reg operand expected");
-
- RegClass = OpInfo[OpIdx].RegClass;
- while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) {
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, RegClass, Rd)));
- Rd += Inc;
- ++OpIdx;
- }
-
- // Handle possible lane index.
- if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
- && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
- MI.addOperand(MCOperand::CreateImm(decodeLaneIndex(insn)));
- ++OpIdx;
- }
-
- } else {
- // Consume the DPR/QPR's, possible WB, AddrMode6, possible incrment reg,
- // possible TIED_TO DPR/QPR's (ignored), then possible lane index.
- RegClass = OpInfo[0].RegClass;
-
- while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) {
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, RegClass, Rd)));
- Rd += Inc;
- ++OpIdx;
- }
-
- if (WB) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- Rn)));
- ++OpIdx;
- }
-
- assert((OpIdx+1) < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
- OpInfo[OpIdx + 1].RegClass < 0 && "Addrmode #6 Operands expected");
- // addrmode6 := (ops GPR:$addr, i32imm)
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- Rn)));
- MI.addOperand(MCOperand::CreateImm(alignment)); // Alignment
- OpIdx += 2;
-
- if (WB) {
- MI.addOperand(MCOperand::CreateReg(RmEnum));
- ++OpIdx;
- }
-
- while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) {
- assert(MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1 &&
- "Tied to operand expected");
- MI.addOperand(MCOperand::CreateReg(0));
- ++OpIdx;
- }
-
- // Handle possible lane index.
- if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
- && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
- MI.addOperand(MCOperand::CreateImm(decodeLaneIndex(insn)));
- ++OpIdx;
- }
- }
-
- // Accessing registers past the end of the NEON register file is not
- // defined.
- if (Rd > 32)
- return false;
-
- return true;
-}
-
-// A8.6.308, A8.6.311, A8.6.314, A8.6.317.
-static bool Align4OneLaneInst(unsigned elem, unsigned size,
- unsigned index_align, unsigned & alignment) {
- unsigned bits = 0;
- switch (elem) {
- default:
- return false;
- case 1:
- // A8.6.308
- if (size == 0)
- return slice(index_align, 0, 0) == 0;
- else if (size == 1) {
- bits = slice(index_align, 1, 0);
- if (bits != 0 && bits != 1)
- return false;
- if (bits == 1)
- alignment = 16;
- return true;
- } else if (size == 2) {
- bits = slice(index_align, 2, 0);
- if (bits != 0 && bits != 3)
- return false;
- if (bits == 3)
- alignment = 32;
- return true;;
- }
- return true;
- case 2:
- // A8.6.311
- if (size == 0) {
- if (slice(index_align, 0, 0) == 1)
- alignment = 16;
- return true;
- } if (size == 1) {
- if (slice(index_align, 0, 0) == 1)
- alignment = 32;
- return true;
- } else if (size == 2) {
- if (slice(index_align, 1, 1) != 0)
- return false;
- if (slice(index_align, 0, 0) == 1)
- alignment = 64;
- return true;;
- }
- return true;
- case 3:
- // A8.6.314
- if (size == 0) {
- if (slice(index_align, 0, 0) != 0)
- return false;
- return true;
- } if (size == 1) {
- if (slice(index_align, 0, 0) != 0)
- return false;
- return true;
- return true;
- } else if (size == 2) {
- if (slice(index_align, 1, 0) != 0)
- return false;
- return true;;
- }
- return true;
- case 4:
- // A8.6.317
- if (size == 0) {
- if (slice(index_align, 0, 0) == 1)
- alignment = 32;
- return true;
- } if (size == 1) {
- if (slice(index_align, 0, 0) == 1)
- alignment = 64;
- return true;
- } else if (size == 2) {
- bits = slice(index_align, 1, 0);
- if (bits == 3)
- return false;
- if (bits == 1)
- alignment = 64;
- else if (bits == 2)
- alignment = 128;
- return true;;
- }
- return true;
- }
-}
-
-// A7.7
-// If L (Inst{21}) == 0, store instructions.
-// Find out about double-spaced-ness of the Opcode and pass it on to
-// DisassembleNLdSt0().
-static bool DisassembleNLdSt(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const StringRef Name = ARMInsts[Opcode].Name;
- bool DblSpaced = false;
- // 0 represents standard alignment, i.e., unaligned data access.
- unsigned alignment = 0;
-
- unsigned elem = 0; // legal values: {1, 2, 3, 4}
- if (Name.startswith("VST1") || Name.startswith("VLD1"))
- elem = 1;
-
- if (Name.startswith("VST2") || Name.startswith("VLD2"))
- elem = 2;
-
- if (Name.startswith("VST3") || Name.startswith("VLD3"))
- elem = 3;
-
- if (Name.startswith("VST4") || Name.startswith("VLD4"))
- elem = 4;
-
- if (Name.find("LN") != std::string::npos) {
- // To one lane instructions.
- // See, for example, 8.6.317 VLD4 (single 4-element structure to one lane).
-
- // Utility function takes number of elements, size, and index_align.
- if (!Align4OneLaneInst(elem,
- slice(insn, 11, 10),
- slice(insn, 7, 4),
- alignment))
- return false;
-
- // <size> == 16 && Inst{5} == 1 --> DblSpaced = true
- if (Name.endswith("16") || Name.endswith("16_UPD"))
- DblSpaced = slice(insn, 5, 5) == 1;
-
- // <size> == 32 && Inst{6} == 1 --> DblSpaced = true
- if (Name.endswith("32") || Name.endswith("32_UPD"))
- DblSpaced = slice(insn, 6, 6) == 1;
- } else if (Name.find("DUP") != std::string::npos) {
- // Single element (or structure) to all lanes.
- // Inst{9-8} encodes the number of element(s) in the structure, with:
- // 0b00 (VLD1DUP) (for this, a bit makes sense only for data size 16 and 32.
- // 0b01 (VLD2DUP)
- // 0b10 (VLD3DUP) (for this, a bit must be encoded as 0)
- // 0b11 (VLD4DUP)
- //
- // Inst{7-6} encodes the data size, with:
- // 0b00 => 8, 0b01 => 16, 0b10 => 32
- //
- // Inst{4} (the a bit) encodes the align action (0: standard alignment)
- unsigned elem = slice(insn, 9, 8) + 1;
- unsigned a = slice(insn, 4, 4);
- if (elem != 3) {
- // 0b11 is not a valid encoding for Inst{7-6}.
- if (slice(insn, 7, 6) == 3)
- return false;
- unsigned data_size = 8 << slice(insn, 7, 6);
- // For VLD1DUP, a bit makes sense only for data size of 16 and 32.
- if (a && data_size == 8)
- return false;
-
- // Now we can calculate the alignment!
- if (a)
- alignment = elem * data_size;
- } else {
- if (a) {
- // A8.6.315 VLD3 (single 3-element structure to all lanes)
- // The a bit must be encoded as 0.
- return false;
- }
- }
- } else {
- // Multiple n-element structures with type encoded as Inst{11-8}.
- // See, for example, A8.6.316 VLD4 (multiple 4-element structures).
-
- // Inst{5-4} encodes alignment.
- unsigned align = slice(insn, 5, 4);
- switch (align) {
- default:
- break;
- case 1:
- alignment = 64; break;
- case 2:
- alignment = 128; break;
- case 3:
- alignment = 256; break;
- }
-
- unsigned type = slice(insn, 11, 8);
- // Reject UNDEFINED instructions based on type and align.
- // Plus set DblSpaced flag where appropriate.
- switch (elem) {
- default:
- break;
- case 1:
- // n == 1
- // A8.6.307 & A8.6.391
- if ((type == 7 && slice(align, 1, 1) == 1) ||
- (type == 10 && align == 3) ||
- (type == 6 && slice(align, 1, 1) == 1))
- return false;
- break;
- case 2:
- // n == 2 && type == 0b1001 -> DblSpaced = true
- // A8.6.310 & A8.6.393
- if ((type == 8 || type == 9) && align == 3)
- return false;
- DblSpaced = (type == 9);
- break;
- case 3:
- // n == 3 && type == 0b0101 -> DblSpaced = true
- // A8.6.313 & A8.6.395
- if (slice(insn, 7, 6) == 3 || slice(align, 1, 1) == 1)
- return false;
- DblSpaced = (type == 5);
- break;
- case 4:
- // n == 4 && type == 0b0001 -> DblSpaced = true
- // A8.6.316 & A8.6.397
- if (slice(insn, 7, 6) == 3)
- return false;
- DblSpaced = (type == 1);
- break;
- }
- }
- return DisassembleNLdSt0(MI, Opcode, insn, NumOps, NumOpsAdded,
- slice(insn, 21, 21) == 0, DblSpaced, alignment/8, B);
-}
-
-// VMOV (immediate)
-// Qd/Dd imm
-// VBIC (immediate)
-// VORR (immediate)
-// Qd/Dd imm src(=Qd/Dd)
-static bool DisassembleN1RegModImmFrm(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
-
- assert(NumOps >= 2 &&
- (OpInfo[0].RegClass == ARM::DPRRegClassID ||
- OpInfo[0].RegClass == ARM::QPRRegClassID) &&
- (OpInfo[1].RegClass < 0) &&
- "Expect 1 reg operand followed by 1 imm operand");
-
- // Qd/Dd = Inst{22:15-12} => NEON Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[0].RegClass,
- decodeNEONRd(insn))));
-
- ElemSize esize = ESizeNA;
- switch (Opcode) {
- case ARM::VMOVv8i8:
- case ARM::VMOVv16i8:
- esize = ESize8;
- break;
- case ARM::VMOVv4i16:
- case ARM::VMOVv8i16:
- case ARM::VMVNv4i16:
- case ARM::VMVNv8i16:
- case ARM::VBICiv4i16:
- case ARM::VBICiv8i16:
- case ARM::VORRiv4i16:
- case ARM::VORRiv8i16:
- esize = ESize16;
- break;
- case ARM::VMOVv2i32:
- case ARM::VMOVv4i32:
- case ARM::VMVNv2i32:
- case ARM::VMVNv4i32:
- case ARM::VBICiv2i32:
- case ARM::VBICiv4i32:
- case ARM::VORRiv2i32:
- case ARM::VORRiv4i32:
- esize = ESize32;
- break;
- case ARM::VMOVv1i64:
- case ARM::VMOVv2i64:
- esize = ESize64;
- break;
- default:
- assert(0 && "Unexpected opcode!");
- return false;
- }
-
- // One register and a modified immediate value.
- // Add the imm operand.
- MI.addOperand(MCOperand::CreateImm(decodeN1VImm(insn, esize)));
-
- NumOpsAdded = 2;
-
- // VBIC/VORRiv*i* variants have an extra $src = $Vd to be filled in.
- if (NumOps >= 3 &&
- (OpInfo[2].RegClass == ARM::DPRRegClassID ||
- OpInfo[2].RegClass == ARM::QPRRegClassID)) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[0].RegClass,
- decodeNEONRd(insn))));
- NumOpsAdded += 1;
- }
-
- return true;
-}
-
-namespace {
-enum N2VFlag {
- N2V_None,
- N2V_VectorDupLane,
- N2V_VectorConvert_Between_Float_Fixed
-};
-} // End of unnamed namespace
-
-// Vector Convert [between floating-point and fixed-point]
-// Qd/Dd Qm/Dm [fbits]
-//
-// Vector Duplicate Lane (from scalar to all elements) Instructions.
-// VDUPLN16d, VDUPLN16q, VDUPLN32d, VDUPLN32q, VDUPLN8d, VDUPLN8q:
-// Qd/Dd Dm index
-//
-// Vector Move Long:
-// Qd Dm
-//
-// Vector Move Narrow:
-// Dd Qm
-//
-// Others
-static bool DisassembleNVdVmOptImm(MCInst &MI, unsigned Opc, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, N2VFlag Flag, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opc];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
-
- assert(NumOps >= 2 &&
- (OpInfo[0].RegClass == ARM::DPRRegClassID ||
- OpInfo[0].RegClass == ARM::QPRRegClassID) &&
- (OpInfo[1].RegClass == ARM::DPRRegClassID ||
- OpInfo[1].RegClass == ARM::QPRRegClassID) &&
- "Expect >= 2 operands and first 2 as reg operands");
-
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- ElemSize esize = ESizeNA;
- if (Flag == N2V_VectorDupLane) {
- // VDUPLN has its index embedded. Its size can be inferred from the Opcode.
- assert(Opc >= ARM::VDUPLN16d && Opc <= ARM::VDUPLN8q &&
- "Unexpected Opcode");
- esize = (Opc == ARM::VDUPLN8d || Opc == ARM::VDUPLN8q) ? ESize8
- : ((Opc == ARM::VDUPLN16d || Opc == ARM::VDUPLN16q) ? ESize16
- : ESize32);
- }
-
- // Qd/Dd = Inst{22:15-12} => NEON Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- decodeNEONRd(insn))));
- ++OpIdx;
-
- // VPADAL...
- if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
- // TIED_TO operand.
- MI.addOperand(MCOperand::CreateReg(0));
- ++OpIdx;
- }
-
- // Dm = Inst{5:3-0} => NEON Rm
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- decodeNEONRm(insn))));
- ++OpIdx;
-
- // VZIP and others have two TIED_TO reg operands.
- int Idx;
- while (OpIdx < NumOps &&
- (Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
- // Add TIED_TO operand.
- MI.addOperand(MI.getOperand(Idx));
- ++OpIdx;
- }
-
- // Add the imm operand, if required.
- if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
- && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
-
- unsigned imm = 0xFFFFFFFF;
-
- if (Flag == N2V_VectorDupLane)
- imm = decodeNVLaneDupIndex(insn, esize);
- if (Flag == N2V_VectorConvert_Between_Float_Fixed)
- imm = decodeVCVTFractionBits(insn);
-
- assert(imm != 0xFFFFFFFF && "Internal error");
- MI.addOperand(MCOperand::CreateImm(imm));
- ++OpIdx;
- }
-
- return true;
-}
-
-static bool DisassembleN2RegFrm(MCInst &MI, unsigned Opc, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded,
- N2V_None, B);
-}
-static bool DisassembleNVCVTFrm(MCInst &MI, unsigned Opc, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded,
- N2V_VectorConvert_Between_Float_Fixed, B);
-}
-static bool DisassembleNVecDupLnFrm(MCInst &MI, unsigned Opc, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded,
- N2V_VectorDupLane, B);
-}
-
-// Vector Shift [Accumulate] Instructions.
-// Qd/Dd [Qd/Dd (TIED_TO)] Qm/Dm ShiftAmt
-//
-// Vector Shift Left Long (with maximum shift count) Instructions.
-// VSHLLi16, VSHLLi32, VSHLLi8: Qd Dm imm (== size)
-//
-static bool DisassembleNVectorShift(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, bool LeftShift, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
-
- assert(NumOps >= 3 &&
- (OpInfo[0].RegClass == ARM::DPRRegClassID ||
- OpInfo[0].RegClass == ARM::QPRRegClassID) &&
- (OpInfo[1].RegClass == ARM::DPRRegClassID ||
- OpInfo[1].RegClass == ARM::QPRRegClassID) &&
- "Expect >= 3 operands and first 2 as reg operands");
-
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- // Qd/Dd = Inst{22:15-12} => NEON Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- decodeNEONRd(insn))));
- ++OpIdx;
-
- if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
- // TIED_TO operand.
- MI.addOperand(MCOperand::CreateReg(0));
- ++OpIdx;
- }
-
- assert((OpInfo[OpIdx].RegClass == ARM::DPRRegClassID ||
- OpInfo[OpIdx].RegClass == ARM::QPRRegClassID) &&
- "Reg operand expected");
-
- // Qm/Dm = Inst{5:3-0} => NEON Rm
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- decodeNEONRm(insn))));
- ++OpIdx;
-
- assert(OpInfo[OpIdx].RegClass < 0 && "Imm operand expected");
-
- // Add the imm operand.
-
- // VSHLL has maximum shift count as the imm, inferred from its size.
- unsigned Imm;
- switch (Opcode) {
- default:
- Imm = decodeNVSAmt(insn, LeftShift);
- break;
- case ARM::VSHLLi8:
- Imm = 8;
- break;
- case ARM::VSHLLi16:
- Imm = 16;
- break;
- case ARM::VSHLLi32:
- Imm = 32;
- break;
- }
- MI.addOperand(MCOperand::CreateImm(Imm));
- ++OpIdx;
-
- return true;
-}
-
-// Left shift instructions.
-static bool DisassembleN2RegVecShLFrm(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- return DisassembleNVectorShift(MI, Opcode, insn, NumOps, NumOpsAdded, true,
- B);
-}
-// Right shift instructions have different shift amount interpretation.
-static bool DisassembleN2RegVecShRFrm(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- return DisassembleNVectorShift(MI, Opcode, insn, NumOps, NumOpsAdded, false,
- B);
-}
-
-namespace {
-enum N3VFlag {
- N3V_None,
- N3V_VectorExtract,
- N3V_VectorShift,
- N3V_Multiply_By_Scalar
-};
-} // End of unnamed namespace
-
-// NEON Three Register Instructions with Optional Immediate Operand
-//
-// Vector Extract Instructions.
-// Qd/Dd Qn/Dn Qm/Dm imm4
-//
-// Vector Shift (Register) Instructions.
-// Qd/Dd Qm/Dm Qn/Dn (notice the order of m, n)
-//
-// Vector Multiply [Accumulate/Subtract] [Long] By Scalar Instructions.
-// Qd/Dd Qn/Dn RestrictedDm index
-//
-// Others
-static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, N3VFlag Flag, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
-
- // No checking for OpInfo[2] because of MOVDneon/MOVQ with only two regs.
- assert(NumOps >= 3 &&
- (OpInfo[0].RegClass == ARM::DPRRegClassID ||
- OpInfo[0].RegClass == ARM::QPRRegClassID) &&
- (OpInfo[1].RegClass == ARM::DPRRegClassID ||
- OpInfo[1].RegClass == ARM::QPRRegClassID) &&
- "Expect >= 3 operands and first 2 as reg operands");
-
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- bool VdVnVm = Flag == N3V_VectorShift ? false : true;
- bool IsImm4 = Flag == N3V_VectorExtract ? true : false;
- bool IsDmRestricted = Flag == N3V_Multiply_By_Scalar ? true : false;
- ElemSize esize = ESizeNA;
- if (Flag == N3V_Multiply_By_Scalar) {
- unsigned size = (insn >> 20) & 3;
- if (size == 1) esize = ESize16;
- if (size == 2) esize = ESize32;
- assert (esize == ESize16 || esize == ESize32);
- }
-
- // Qd/Dd = Inst{22:15-12} => NEON Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- decodeNEONRd(insn))));
- ++OpIdx;
-
- // VABA, VABAL, VBSLd, VBSLq, ...
- if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
- // TIED_TO operand.
- MI.addOperand(MCOperand::CreateReg(0));
- ++OpIdx;
- }
-
- // Dn = Inst{7:19-16} => NEON Rn
- // or
- // Dm = Inst{5:3-0} => NEON Rm
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- VdVnVm ? decodeNEONRn(insn)
- : decodeNEONRm(insn))));
- ++OpIdx;
-
- // Dm = Inst{5:3-0} => NEON Rm
- // or
- // Dm is restricted to D0-D7 if size is 16, D0-D15 otherwise
- // or
- // Dn = Inst{7:19-16} => NEON Rn
- unsigned m = VdVnVm ? (IsDmRestricted ? decodeRestrictedDm(insn, esize)
- : decodeNEONRm(insn))
- : decodeNEONRn(insn);
-
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, OpInfo[OpIdx].RegClass, m)));
- ++OpIdx;
-
- if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
- && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
- // Add the imm operand.
- unsigned Imm = 0;
- if (IsImm4)
- Imm = decodeN3VImm(insn);
- else if (IsDmRestricted)
- Imm = decodeRestrictedDmIndex(insn, esize);
- else {
- assert(0 && "Internal error: unreachable code!");
- return false;
- }
-
- MI.addOperand(MCOperand::CreateImm(Imm));
- ++OpIdx;
- }
-
- return true;
-}
-
-static bool DisassembleN3RegFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
- N3V_None, B);
-}
-static bool DisassembleN3RegVecShFrm(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
- N3V_VectorShift, B);
-}
-static bool DisassembleNVecExtractFrm(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
- N3V_VectorExtract, B);
-}
-static bool DisassembleNVecMulScalarFrm(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
- N3V_Multiply_By_Scalar, B);
-}
-
-// Vector Table Lookup
-//
-// VTBL1, VTBX1: Dd [Dd(TIED_TO)] Dn Dm
-// VTBL2, VTBX2: Dd [Dd(TIED_TO)] Dn Dn+1 Dm
-// VTBL3, VTBX3: Dd [Dd(TIED_TO)] Dn Dn+1 Dn+2 Dm
-// VTBL4, VTBX4: Dd [Dd(TIED_TO)] Dn Dn+1 Dn+2 Dn+3 Dm
-static bool DisassembleNVTBLFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- if (!OpInfo) return false;
-
- assert(NumOps >= 3 &&
- OpInfo[0].RegClass == ARM::DPRRegClassID &&
- OpInfo[1].RegClass == ARM::DPRRegClassID &&
- OpInfo[2].RegClass == ARM::DPRRegClassID &&
- "Expect >= 3 operands and first 3 as reg operands");
-
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- unsigned Rn = decodeNEONRn(insn);
-
- // {Dn} encoded as len = 0b00
- // {Dn Dn+1} encoded as len = 0b01
- // {Dn Dn+1 Dn+2 } encoded as len = 0b10
- // {Dn Dn+1 Dn+2 Dn+3} encoded as len = 0b11
- unsigned Len = slice(insn, 9, 8) + 1;
-
- // Dd (the destination vector)
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
- decodeNEONRd(insn))));
- ++OpIdx;
-
- // Process tied_to operand constraint.
- int Idx;
- if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
- MI.addOperand(MI.getOperand(Idx));
- ++OpIdx;
- }
-
- // Do the <list> now.
- for (unsigned i = 0; i < Len; ++i) {
- assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::DPRRegClassID &&
- "Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
- Rn + i)));
- ++OpIdx;
- }
-
- // Dm (the index vector)
- assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::DPRRegClassID &&
- "Reg operand (index vector) expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
- decodeNEONRm(insn))));
- ++OpIdx;
-
- return true;
-}
-
-// Vector Get Lane (move scalar to ARM core register) Instructions.
-// VGETLNi32, VGETLNs16, VGETLNs8, VGETLNu16, VGETLNu8: Rt Dn index
-static bool DisassembleNGetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- if (!OpInfo) return false;
-
- assert(MCID.getNumDefs() == 1 && NumOps >= 3 &&
- OpInfo[0].RegClass == ARM::GPRRegClassID &&
- OpInfo[1].RegClass == ARM::DPRRegClassID &&
- OpInfo[2].RegClass < 0 &&
- "Expect >= 3 operands with one dst operand");
-
- ElemSize esize =
- Opcode == ARM::VGETLNi32 ? ESize32
- : ((Opcode == ARM::VGETLNs16 || Opcode == ARM::VGETLNu16) ? ESize16
- : ESize8);
-
- // Rt = Inst{15-12} => ARM Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
-
- // Dn = Inst{7:19-16} => NEON Rn
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
- decodeNEONRn(insn))));
-
- MI.addOperand(MCOperand::CreateImm(decodeNVLaneOpIndex(insn, esize)));
-
- NumOpsAdded = 3;
- return true;
-}
-
-// Vector Set Lane (move ARM core register to scalar) Instructions.
-// VSETLNi16, VSETLNi32, VSETLNi8: Dd Dd (TIED_TO) Rt index
-static bool DisassembleNSetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- if (!OpInfo) return false;
-
- assert(MCID.getNumDefs() == 1 && NumOps >= 3 &&
- OpInfo[0].RegClass == ARM::DPRRegClassID &&
- OpInfo[1].RegClass == ARM::DPRRegClassID &&
- MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 &&
- OpInfo[2].RegClass == ARM::GPRRegClassID &&
- OpInfo[3].RegClass < 0 &&
- "Expect >= 3 operands with one dst operand");
-
- ElemSize esize =
- Opcode == ARM::VSETLNi8 ? ESize8
- : (Opcode == ARM::VSETLNi16 ? ESize16
- : ESize32);
-
- // Dd = Inst{7:19-16} => NEON Rn
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
- decodeNEONRn(insn))));
-
- // TIED_TO operand.
- MI.addOperand(MCOperand::CreateReg(0));
-
- // Rt = Inst{15-12} => ARM Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
-
- MI.addOperand(MCOperand::CreateImm(decodeNVLaneOpIndex(insn, esize)));
-
- NumOpsAdded = 4;
- return true;
-}
-
-// Vector Duplicate Instructions (from ARM core register to all elements).
-// VDUP8d, VDUP16d, VDUP32d, VDUP8q, VDUP16q, VDUP32q: Qd/Dd Rt
-static bool DisassembleNDupFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
-
- assert(NumOps >= 2 &&
- (OpInfo[0].RegClass == ARM::DPRRegClassID ||
- OpInfo[0].RegClass == ARM::QPRRegClassID) &&
- OpInfo[1].RegClass == ARM::GPRRegClassID &&
- "Expect >= 2 operands and first 2 as reg operand");
-
- unsigned RegClass = OpInfo[0].RegClass;
-
- // Qd/Dd = Inst{7:19-16} => NEON Rn
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClass,
- decodeNEONRn(insn))));
-
- // Rt = Inst{15-12} => ARM Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
-
- NumOpsAdded = 2;
- return true;
-}
-
-static inline bool PreLoadOpcode(unsigned Opcode) {
- switch(Opcode) {
- case ARM::PLDi12: case ARM::PLDrs:
- case ARM::PLDWi12: case ARM::PLDWrs:
- case ARM::PLIi12: case ARM::PLIrs:
- return true;
- default:
- return false;
- }
-}
-
-static bool DisassemblePreLoadFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- // Preload Data/Instruction requires either 2 or 3 operands.
- // PLDi12, PLDWi12, PLIi12: addrmode_imm12
- // PLDrs, PLDWrs, PLIrs: ldst_so_reg
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
-
- if (Opcode == ARM::PLDi12 || Opcode == ARM::PLDWi12
- || Opcode == ARM::PLIi12) {
- unsigned Imm12 = slice(insn, 11, 0);
- bool Negative = getUBit(insn) == 0;
-
- // A8.6.118 PLD (literal) PLDWi12 with Rn=PC is transformed to PLDi12.
- if (Opcode == ARM::PLDWi12 && slice(insn, 19, 16) == 0xF) {
- DEBUG(errs() << "Rn == '1111': PLDWi12 morphed to PLDi12\n");
- MI.setOpcode(ARM::PLDi12);
- }
-
- // -0 is represented specially. All other values are as normal.
- int Offset = Negative ? -1 * Imm12 : Imm12;
- if (Imm12 == 0 && Negative)
- Offset = INT32_MIN;
-
- MI.addOperand(MCOperand::CreateImm(Offset));
- NumOpsAdded = 2;
- } else {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
-
- ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
-
- // Inst{6-5} encodes the shift opcode.
- ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
- // Inst{11-7} encodes the imm5 shift amount.
- unsigned ShImm = slice(insn, 11, 7);
-
- // A8.4.1. Possible rrx or shift amount of 32...
- getImmShiftSE(ShOp, ShImm);
- MI.addOperand(MCOperand::CreateImm(
- ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp)));
- NumOpsAdded = 3;
- }
-
- return true;
-}
-
-static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- if (Opcode == ARM::DMB || Opcode == ARM::DSB || Opcode == ARM::ISB) {
- // Inst{3-0} encodes the memory barrier option for the variants.
- unsigned opt = slice(insn, 3, 0);
- switch (opt) {
- case ARM_MB::SY: case ARM_MB::ST:
- case ARM_MB::ISH: case ARM_MB::ISHST:
- case ARM_MB::NSH: case ARM_MB::NSHST:
- case ARM_MB::OSH: case ARM_MB::OSHST:
- MI.addOperand(MCOperand::CreateImm(opt));
- NumOpsAdded = 1;
- return true;
- default:
- return false;
- }
- }
-
- switch (Opcode) {
- case ARM::CLREX:
- case ARM::NOP:
- case ARM::TRAP:
- case ARM::YIELD:
- case ARM::WFE:
- case ARM::WFI:
- case ARM::SEV:
- return true;
- case ARM::SWP:
- case ARM::SWPB:
- // SWP, SWPB: Rd Rm Rn
- // Delegate to DisassembleLdStExFrm()....
- return DisassembleLdStExFrm(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- default:
- break;
- }
-
- if (Opcode == ARM::SETEND) {
- NumOpsAdded = 1;
- MI.addOperand(MCOperand::CreateImm(slice(insn, 9, 9)));
- return true;
- }
-
- // FIXME: To enable correct asm parsing and disasm of CPS we need 3 different
- // opcodes which match the same real instruction. This is needed since there's
- // no current handling of optional arguments. Fix here when a better handling
- // of optional arguments is implemented.
- if (Opcode == ARM::CPS3p) { // M = 1
- // Let's reject these impossible imod values by returning false:
- // 1. (imod=0b01)
- //
- // AsmPrinter cannot handle imod=0b00, plus (imod=0b00,M=1,iflags!=0) is an
- // invalid combination, so we just check for imod=0b00 here.
- if (slice(insn, 19, 18) == 0 || slice(insn, 19, 18) == 1)
- return false;
- MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod
- MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6))); // iflags
- MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode
- NumOpsAdded = 3;
- return true;
- }
- if (Opcode == ARM::CPS2p) { // mode = 0, M = 0
- // Let's reject these impossible imod values by returning false:
- // 1. (imod=0b00,M=0)
- // 2. (imod=0b01)
- if (slice(insn, 19, 18) == 0 || slice(insn, 19, 18) == 1)
- return false;
- MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod
- MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6))); // iflags
- NumOpsAdded = 2;
- return true;
- }
- if (Opcode == ARM::CPS1p) { // imod = 0, iflags = 0, M = 1
- MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode
- NumOpsAdded = 1;
- return true;
- }
-
- // DBG has its option specified in Inst{3-0}.
- if (Opcode == ARM::DBG) {
- MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 0)));
- NumOpsAdded = 1;
- return true;
- }
-
- // BKPT takes an imm32 val equal to ZeroExtend(Inst{19-8:3-0}).
- if (Opcode == ARM::BKPT) {
- MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 8) << 4 |
- slice(insn, 3, 0)));
- NumOpsAdded = 1;
- return true;
- }
-
- if (PreLoadOpcode(Opcode))
- return DisassemblePreLoadFrm(MI, Opcode, insn, NumOps, NumOpsAdded, B);
-
- assert(0 && "Unexpected misc instruction!");
- return false;
-}
-
-/// FuncPtrs - FuncPtrs maps ARMFormat to its corresponding DisassembleFP.
-/// We divide the disassembly task into different categories, with each one
-/// corresponding to a specific instruction encoding format. There could be
-/// exceptions when handling a specific format, and that is why the Opcode is
-/// also present in the function prototype.
-static const DisassembleFP FuncPtrs[] = {
- &DisassemblePseudo,
- &DisassembleMulFrm,
- &DisassembleBrFrm,
- &DisassembleBrMiscFrm,
- &DisassembleDPFrm,
- &DisassembleDPSoRegFrm,
- &DisassembleLdFrm,
- &DisassembleStFrm,
- &DisassembleLdMiscFrm,
- &DisassembleStMiscFrm,
- &DisassembleLdStMulFrm,
- &DisassembleLdStExFrm,
- &DisassembleArithMiscFrm,
- &DisassembleSatFrm,
- &DisassembleExtFrm,
- &DisassembleVFPUnaryFrm,
- &DisassembleVFPBinaryFrm,
- &DisassembleVFPConv1Frm,
- &DisassembleVFPConv2Frm,
- &DisassembleVFPConv3Frm,
- &DisassembleVFPConv4Frm,
- &DisassembleVFPConv5Frm,
- &DisassembleVFPLdStFrm,
- &DisassembleVFPLdStMulFrm,
- &DisassembleVFPMiscFrm,
- &DisassembleThumbFrm,
- &DisassembleMiscFrm,
- &DisassembleNGetLnFrm,
- &DisassembleNSetLnFrm,
- &DisassembleNDupFrm,
-
- // VLD and VST (including one lane) Instructions.
- &DisassembleNLdSt,
-
- // A7.4.6 One register and a modified immediate value
- // 1-Register Instructions with imm.
- // LLVM only defines VMOVv instructions.
- &DisassembleN1RegModImmFrm,
-
- // 2-Register Instructions with no imm.
- &DisassembleN2RegFrm,
-
- // 2-Register Instructions with imm (vector convert float/fixed point).
- &DisassembleNVCVTFrm,
-
- // 2-Register Instructions with imm (vector dup lane).
- &DisassembleNVecDupLnFrm,
-
- // Vector Shift Left Instructions.
- &DisassembleN2RegVecShLFrm,
-
- // Vector Shift Righ Instructions, which has different interpretation of the
- // shift amount from the imm6 field.
- &DisassembleN2RegVecShRFrm,
-
- // 3-Register Data-Processing Instructions.
- &DisassembleN3RegFrm,
-
- // Vector Shift (Register) Instructions.
- // D:Vd M:Vm N:Vn (notice that M:Vm is the first operand)
- &DisassembleN3RegVecShFrm,
-
- // Vector Extract Instructions.
- &DisassembleNVecExtractFrm,
-
- // Vector [Saturating Rounding Doubling] Multiply [Accumulate/Subtract] [Long]
- // By Scalar Instructions.
- &DisassembleNVecMulScalarFrm,
-
- // Vector Table Lookup uses byte indexes in a control vector to look up byte
- // values in a table and generate a new vector.
- &DisassembleNVTBLFrm,
-
- NULL
-};
-
-/// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder.
-/// The general idea is to set the Opcode for the MCInst, followed by adding
-/// the appropriate MCOperands to the MCInst. ARM Basic MC Builder delegates
-/// to the Format-specific disassemble function for disassembly, followed by
-/// TryPredicateAndSBitModifier() to do PredicateOperand and OptionalDefOperand
-/// which follow the Dst/Src Operands.
-bool ARMBasicMCBuilder::BuildIt(MCInst &MI, uint32_t insn) {
- // Stage 1 sets the Opcode.
- MI.setOpcode(Opcode);
- // If the number of operands is zero, we're done!
- if (NumOps == 0)
- return true;
-
- // Stage 2 calls the format-specific disassemble function to build the operand
- // list.
- if (Disasm == NULL)
- return false;
- unsigned NumOpsAdded = 0;
- bool OK = (*Disasm)(MI, Opcode, insn, NumOps, NumOpsAdded, this);
-
- if (!OK || this->Err != 0) return false;
- if (NumOpsAdded >= NumOps)
- return true;
-
- // Stage 3 deals with operands unaccounted for after stage 2 is finished.
- // FIXME: Should this be done selectively?
- return TryPredicateAndSBitModifier(MI, Opcode, insn, NumOps - NumOpsAdded);
-}
-
-// A8.3 Conditional execution
-// A8.3.1 Pseudocode details of conditional execution
-// Condition bits '111x' indicate the instruction is always executed.
-static uint32_t CondCode(uint32_t CondField) {
- if (CondField == 0xF)
- return ARMCC::AL;
- return CondField;
-}
-
-/// DoPredicateOperands - DoPredicateOperands process the predicate operands
-/// of some Thumb instructions which come before the reglist operands. It
-/// returns true if the two predicate operands have been processed.
-bool ARMBasicMCBuilder::DoPredicateOperands(MCInst& MI, unsigned Opcode,
- uint32_t /* insn */, unsigned short NumOpsRemaining) {
-
- assert(NumOpsRemaining > 0 && "Invalid argument");
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- unsigned Idx = MI.getNumOperands();
-
- // First, we check whether this instr specifies the PredicateOperand through
- // a pair of MCOperandInfos with isPredicate() property.
- if (NumOpsRemaining >= 2 &&
- OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() &&
- OpInfo[Idx].RegClass < 0 &&
- OpInfo[Idx+1].RegClass == ARM::CCRRegClassID)
- {
- // If we are inside an IT block, get the IT condition bits maintained via
- // ARMBasicMCBuilder::ITState[7:0], through ARMBasicMCBuilder::GetITCond().
- // See also A2.5.2.
- if (InITBlock())
- MI.addOperand(MCOperand::CreateImm(GetITCond()));
- else
- MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
- MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
- return true;
- }
-
- return false;
-}
-
-/// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
-/// the possible Predicate and SBitModifier, to build the remaining MCOperand
-/// constituents.
-bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOpsRemaining) {
-
- assert(NumOpsRemaining > 0 && "Invalid argument");
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- const std::string &Name = ARMInsts[Opcode].Name;
- unsigned Idx = MI.getNumOperands();
- uint64_t TSFlags = ARMInsts[Opcode].TSFlags;
-
- // First, we check whether this instr specifies the PredicateOperand through
- // a pair of MCOperandInfos with isPredicate() property.
- if (NumOpsRemaining >= 2 &&
- OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() &&
- OpInfo[Idx].RegClass < 0 &&
- OpInfo[Idx+1].RegClass == ARM::CCRRegClassID)
- {
- // If we are inside an IT block, get the IT condition bits maintained via
- // ARMBasicMCBuilder::ITState[7:0], through ARMBasicMCBuilder::GetITCond().
- // See also A2.5.2.
- if (InITBlock())
- MI.addOperand(MCOperand::CreateImm(GetITCond()));
- else {
- if (Name.length() > 1 && Name[0] == 't') {
- // Thumb conditional branch instructions have their cond field embedded,
- // like ARM.
- //
- // A8.6.16 B
- // Check for undefined encodings.
- unsigned cond;
- if (Name == "t2Bcc") {
- if ((cond = slice(insn, 25, 22)) >= 14)
- return false;
- MI.addOperand(MCOperand::CreateImm(CondCode(cond)));
- } else if (Name == "tBcc") {
- if ((cond = slice(insn, 11, 8)) == 14)
- return false;
- MI.addOperand(MCOperand::CreateImm(CondCode(cond)));
- } else
- MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
- } else {
- // ARM instructions get their condition field from Inst{31-28}.
- // We should reject Inst{31-28} = 0b1111 as invalid encoding.
- if (!isNEONDomain(TSFlags) && getCondField(insn) == 0xF)
- return false;
- MI.addOperand(MCOperand::CreateImm(CondCode(getCondField(insn))));
- }
- }
- MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
- Idx += 2;
- NumOpsRemaining -= 2;
- }
-
- if (NumOpsRemaining == 0)
- return true;
-
- // Next, if OptionalDefOperand exists, we check whether the 'S' bit is set.
- if (OpInfo[Idx].isOptionalDef() && OpInfo[Idx].RegClass==ARM::CCRRegClassID) {
- MI.addOperand(MCOperand::CreateReg(getSBit(insn) == 1 ? ARM::CPSR : 0));
- --NumOpsRemaining;
- }
-
- if (NumOpsRemaining == 0)
- return true;
- else
- return false;
-}
-
-/// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary
-/// after BuildIt is finished.
-bool ARMBasicMCBuilder::RunBuildAfterHook(bool Status, MCInst &MI,
- uint32_t insn) {
-
- if (!SP) return Status;
-
- if (Opcode == ARM::t2IT)
- Status = SP->InitIT(slice(insn, 7, 0)) ? Status : false;
- else if (InITBlock())
- SP->UpdateIT();
-
- return Status;
-}
-
-/// Opcode, Format, and NumOperands make up an ARM Basic MCBuilder.
-ARMBasicMCBuilder::ARMBasicMCBuilder(unsigned opc, ARMFormat format,
- unsigned short num)
- : Opcode(opc), Format(format), NumOps(num), SP(0), Err(0) {
- unsigned Idx = (unsigned)format;
- assert(Idx < (array_lengthof(FuncPtrs) - 1) && "Unknown format");
- Disasm = FuncPtrs[Idx];
-}
-
-/// CreateMCBuilder - Return an ARMBasicMCBuilder that can build up the MC
-/// infrastructure of an MCInst given the Opcode and Format of the instr.
-/// Return NULL if it fails to create/return a proper builder. API clients
-/// are responsible for freeing up of the allocated memory. Cacheing can be
-/// performed by the API clients to improve performance.
-ARMBasicMCBuilder *llvm::CreateMCBuilder(unsigned Opcode, ARMFormat Format) {
- // For "Unknown format", fail by returning a NULL pointer.
- if ((unsigned)Format >= (array_lengthof(FuncPtrs) - 1)) {
- DEBUG(errs() << "Unknown format\n");
- return 0;
- }
-
- return new ARMBasicMCBuilder(Opcode, Format,
- ARMInsts[Opcode].getNumOperands());
-}
-
-/// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic
-/// operand in place of the immediate Value in the MCInst. The immediate
-/// Value has had any PC adjustment made by the caller. If the getOpInfo()
-/// function was set as part of the setupBuilderForSymbolicDisassembly() call
-/// then that function is called to get any symbolic information at the
-/// builder's Address for this instrution. If that returns non-zero then the
-/// symbolic information it returns is used to create an MCExpr and that is
-/// added as an operand to the MCInst. This function returns true if it adds
-/// an operand to the MCInst and false otherwise.
-bool ARMBasicMCBuilder::tryAddingSymbolicOperand(uint64_t Value,
- uint64_t InstSize,
- MCInst &MI) {
- if (!GetOpInfo)
- return false;
-
- struct LLVMOpInfo1 SymbolicOp;
- SymbolicOp.Value = Value;
- if (!GetOpInfo(DisInfo, Address, 0 /* Offset */, InstSize, 1, &SymbolicOp))
- return false;
-
- const MCExpr *Add = NULL;
- if (SymbolicOp.AddSymbol.Present) {
- if (SymbolicOp.AddSymbol.Name) {
- StringRef Name(SymbolicOp.AddSymbol.Name);
- MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name);
- Add = MCSymbolRefExpr::Create(Sym, *Ctx);
- } else {
- Add = MCConstantExpr::Create(SymbolicOp.AddSymbol.Value, *Ctx);
- }
- }
-
- const MCExpr *Sub = NULL;
- if (SymbolicOp.SubtractSymbol.Present) {
- if (SymbolicOp.SubtractSymbol.Name) {
- StringRef Name(SymbolicOp.SubtractSymbol.Name);
- MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name);
- Sub = MCSymbolRefExpr::Create(Sym, *Ctx);
- } else {
- Sub = MCConstantExpr::Create(SymbolicOp.SubtractSymbol.Value, *Ctx);
- }
- }
-
- const MCExpr *Off = NULL;
- if (SymbolicOp.Value != 0)
- Off = MCConstantExpr::Create(SymbolicOp.Value, *Ctx);
-
- const MCExpr *Expr;
- if (Sub) {
- const MCExpr *LHS;
- if (Add)
- LHS = MCBinaryExpr::CreateSub(Add, Sub, *Ctx);
- else
- LHS = MCUnaryExpr::CreateMinus(Sub, *Ctx);
- if (Off != 0)
- Expr = MCBinaryExpr::CreateAdd(LHS, Off, *Ctx);
- else
- Expr = LHS;
- } else if (Add) {
- if (Off != 0)
- Expr = MCBinaryExpr::CreateAdd(Add, Off, *Ctx);
- else
- Expr = Add;
- } else {
- if (Off != 0)
- Expr = Off;
- else
- Expr = MCConstantExpr::Create(0, *Ctx);
- }
-
- if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_HI16)
- MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateUpper16(Expr, *Ctx)));
- else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_LO16)
- MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateLower16(Expr, *Ctx)));
- else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_None)
- MI.addOperand(MCOperand::CreateExpr(Expr));
- else
- assert("bad SymbolicOp.VariantKind");
-
- return true;
-}
diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h
deleted file mode 100644
index a7ba141..0000000
--- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h
+++ /dev/null
@@ -1,336 +0,0 @@
-//===- ARMDisassemblerCore.h - ARM disassembler helpers ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is part of the ARM Disassembler.
-//
-// The first part defines the enumeration type of ARM instruction format, which
-// specifies the encoding used by the instruction, as well as a helper function
-// to convert the enums to printable char strings.
-//
-// It also contains code to represent the concepts of Builder and DisassembleFP
-// to solve the problem of disassembling an ARM instr.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ARMDISASSEMBLERCORE_H
-#define ARMDISASSEMBLERCORE_H
-
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm-c/Disassembler.h"
-#include "ARMBaseInstrInfo.h"
-#include "ARMRegisterInfo.h"
-#include "ARMDisassembler.h"
-
-namespace llvm {
-class MCContext;
-
-class ARMUtils {
-public:
- static const char *OpcodeName(unsigned Opcode);
-};
-
-/////////////////////////////////////////////////////
-// //
-// Enums and Utilities for ARM Instruction Format //
-// //
-/////////////////////////////////////////////////////
-
-#define ARM_FORMATS \
- ENTRY(ARM_FORMAT_PSEUDO, 0) \
- ENTRY(ARM_FORMAT_MULFRM, 1) \
- ENTRY(ARM_FORMAT_BRFRM, 2) \
- ENTRY(ARM_FORMAT_BRMISCFRM, 3) \
- ENTRY(ARM_FORMAT_DPFRM, 4) \
- ENTRY(ARM_FORMAT_DPSOREGFRM, 5) \
- ENTRY(ARM_FORMAT_LDFRM, 6) \
- ENTRY(ARM_FORMAT_STFRM, 7) \
- ENTRY(ARM_FORMAT_LDMISCFRM, 8) \
- ENTRY(ARM_FORMAT_STMISCFRM, 9) \
- ENTRY(ARM_FORMAT_LDSTMULFRM, 10) \
- ENTRY(ARM_FORMAT_LDSTEXFRM, 11) \
- ENTRY(ARM_FORMAT_ARITHMISCFRM, 12) \
- ENTRY(ARM_FORMAT_SATFRM, 13) \
- ENTRY(ARM_FORMAT_EXTFRM, 14) \
- ENTRY(ARM_FORMAT_VFPUNARYFRM, 15) \
- ENTRY(ARM_FORMAT_VFPBINARYFRM, 16) \
- ENTRY(ARM_FORMAT_VFPCONV1FRM, 17) \
- ENTRY(ARM_FORMAT_VFPCONV2FRM, 18) \
- ENTRY(ARM_FORMAT_VFPCONV3FRM, 19) \
- ENTRY(ARM_FORMAT_VFPCONV4FRM, 20) \
- ENTRY(ARM_FORMAT_VFPCONV5FRM, 21) \
- ENTRY(ARM_FORMAT_VFPLDSTFRM, 22) \
- ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 23) \
- ENTRY(ARM_FORMAT_VFPMISCFRM, 24) \
- ENTRY(ARM_FORMAT_THUMBFRM, 25) \
- ENTRY(ARM_FORMAT_MISCFRM, 26) \
- ENTRY(ARM_FORMAT_NEONGETLNFRM, 27) \
- ENTRY(ARM_FORMAT_NEONSETLNFRM, 28) \
- ENTRY(ARM_FORMAT_NEONDUPFRM, 29) \
- ENTRY(ARM_FORMAT_NLdSt, 30) \
- ENTRY(ARM_FORMAT_N1RegModImm, 31) \
- ENTRY(ARM_FORMAT_N2Reg, 32) \
- ENTRY(ARM_FORMAT_NVCVT, 33) \
- ENTRY(ARM_FORMAT_NVecDupLn, 34) \
- ENTRY(ARM_FORMAT_N2RegVecShL, 35) \
- ENTRY(ARM_FORMAT_N2RegVecShR, 36) \
- ENTRY(ARM_FORMAT_N3Reg, 37) \
- ENTRY(ARM_FORMAT_N3RegVecSh, 38) \
- ENTRY(ARM_FORMAT_NVecExtract, 39) \
- ENTRY(ARM_FORMAT_NVecMulScalar, 40) \
- ENTRY(ARM_FORMAT_NVTBL, 41)
-
-// ARM instruction format specifies the encoding used by the instruction.
-#define ENTRY(n, v) n = v,
-typedef enum {
- ARM_FORMATS
- ARM_FORMAT_NA
-} ARMFormat;
-#undef ENTRY
-
-// Converts enum to const char*.
-static const inline char *stringForARMFormat(ARMFormat form) {
-#define ENTRY(n, v) case n: return #n;
- switch(form) {
- ARM_FORMATS
- case ARM_FORMAT_NA:
- default:
- return "";
- }
-#undef ENTRY
-}
-
-/// Expands on the enum definitions from ARMBaseInstrInfo.h.
-/// They are being used by the disassembler implementation.
-namespace ARMII {
- enum {
- NEONRegMask = 15,
- GPRRegMask = 15,
- NEON_RegRdShift = 12,
- NEON_D_BitShift = 22,
- NEON_RegRnShift = 16,
- NEON_N_BitShift = 7,
- NEON_RegRmShift = 0,
- NEON_M_BitShift = 5
- };
-}
-
-/// Utility function for extracting [From, To] bits from a uint32_t.
-static inline unsigned slice(uint32_t Bits, unsigned From, unsigned To) {
- assert(From < 32 && To < 32 && From >= To);
- return (Bits >> To) & ((1 << (From - To + 1)) - 1);
-}
-
-/// Utility function for setting [From, To] bits to Val for a uint32_t.
-static inline void setSlice(unsigned &Bits, unsigned From, unsigned To,
- unsigned Val) {
- assert(From < 32 && To < 32 && From >= To);
- uint32_t Mask = ((1 << (From - To + 1)) - 1);
- Bits &= ~(Mask << To);
- Bits |= (Val & Mask) << To;
-}
-
-// Return an integer result equal to the number of bits of x that are ones.
-static inline uint32_t
-BitCount (uint64_t x)
-{
- // c accumulates the total bits set in x
- uint32_t c;
- for (c = 0; x; ++c)
- {
- x &= x - 1; // clear the least significant bit set
- }
- return c;
-}
-
-static inline bool
-BitIsSet (const uint64_t value, const uint64_t bit)
-{
- return (value & (1ull << bit)) != 0;
-}
-
-static inline bool
-BitIsClear (const uint64_t value, const uint64_t bit)
-{
- return (value & (1ull << bit)) == 0;
-}
-
-/// Various utilities for checking the target specific flags.
-
-/// A unary data processing instruction doesn't have an Rn operand.
-static inline bool isUnaryDP(uint64_t TSFlags) {
- return (TSFlags & ARMII::UnaryDP);
-}
-
-/// A NEON Domain instruction has cond field (Inst{31-28}) as 0b1111.
-static inline bool isNEONDomain(uint64_t TSFlags) {
- return (TSFlags & ARMII::DomainNEON) ||
- (TSFlags & ARMII::DomainNEONA8);
-}
-
-/// This four-bit field describes the addressing mode used.
-/// See also ARMBaseInstrInfo.h.
-static inline unsigned getAddrMode(uint64_t TSFlags) {
- return (TSFlags & ARMII::AddrModeMask);
-}
-
-/// {IndexModePre, IndexModePost}
-/// Only valid for load and store ops.
-/// See also ARMBaseInstrInfo.h.
-static inline unsigned getIndexMode(uint64_t TSFlags) {
- return (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
-}
-
-/// Pre-/post-indexed operations define an extra $base_wb in the OutOperandList.
-static inline bool isPrePostLdSt(uint64_t TSFlags) {
- return (TSFlags & ARMII::IndexModeMask) != 0;
-}
-
-// Forward declaration.
-class ARMBasicMCBuilder;
-
-// Builder Object is mostly ignored except in some Thumb disassemble functions.
-typedef ARMBasicMCBuilder *BO;
-
-/// DisassembleFP - DisassembleFP points to a function that disassembles an insn
-/// and builds the MCOperand list upon disassembly. It returns false on failure
-/// or true on success. The number of operands added is updated upon success.
-typedef bool (*DisassembleFP)(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO Builder);
-
-/// CreateMCBuilder - Return an ARMBasicMCBuilder that can build up the MC
-/// infrastructure of an MCInst given the Opcode and Format of the instr.
-/// Return NULL if it fails to create/return a proper builder. API clients
-/// are responsible for freeing up of the allocated memory. Cacheing can be
-/// performed by the API clients to improve performance.
-extern ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format);
-
-/// ARMBasicMCBuilder - ARMBasicMCBuilder represents an ARM MCInst builder that
-/// knows how to build up the MCOperand list.
-class ARMBasicMCBuilder {
- friend ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format);
- unsigned Opcode;
- ARMFormat Format;
- unsigned short NumOps;
- DisassembleFP Disasm;
- Session *SP;
- int Err; // !=0 if the builder encounters some error condition during build.
-
-private:
- /// Opcode, Format, and NumOperands make up an ARM Basic MCBuilder.
- ARMBasicMCBuilder(unsigned opc, ARMFormat format, unsigned short num);
-
-public:
- ARMBasicMCBuilder(ARMBasicMCBuilder &B)
- : Opcode(B.Opcode), Format(B.Format), NumOps(B.NumOps), Disasm(B.Disasm),
- SP(B.SP), GetOpInfo(0), DisInfo(0), Ctx(0) {
- Err = 0;
- }
-
- virtual ~ARMBasicMCBuilder() {}
-
- void SetSession(Session *sp) {
- SP = sp;
- }
-
- void SetErr(int ErrCode) {
- Err = ErrCode;
- }
-
- /// DoPredicateOperands - DoPredicateOperands process the predicate operands
- /// of some Thumb instructions which come before the reglist operands. It
- /// returns true if the two predicate operands have been processed.
- bool DoPredicateOperands(MCInst& MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOpsRemaning);
-
- /// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
- /// the possible Predicate and SBitModifier, to build the remaining MCOperand
- /// constituents.
- bool TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOpsRemaning);
-
- /// InITBlock - InITBlock returns true if we are inside an IT block.
- bool InITBlock() {
- if (SP)
- return SP->ITCounter > 0;
-
- return false;
- }
-
- /// Build - Build delegates to BuildIt to perform the heavy liftling. After
- /// that, it invokes RunBuildAfterHook where some housekeepings can be done.
- virtual bool Build(MCInst &MI, uint32_t insn) {
- bool Status = BuildIt(MI, insn);
- return RunBuildAfterHook(Status, MI, insn);
- }
-
- /// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder.
- /// The general idea is to set the Opcode for the MCInst, followed by adding
- /// the appropriate MCOperands to the MCInst. ARM Basic MC Builder delegates
- /// to the Format-specific disassemble function for disassembly, followed by
- /// TryPredicateAndSBitModifier() for PredicateOperand and OptionalDefOperand
- /// which follow the Dst/Src Operands.
- virtual bool BuildIt(MCInst &MI, uint32_t insn);
-
- /// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary
- /// after BuildIt is finished.
- virtual bool RunBuildAfterHook(bool Status, MCInst &MI, uint32_t insn);
-
-private:
- /// Get condition of the current IT instruction.
- unsigned GetITCond() {
- assert(SP);
- return slice(SP->ITState, 7, 4);
- }
-
-private:
- //
- // Hooks for symbolic disassembly via the public 'C' interface.
- //
- // The function to get the symbolic information for operands.
- LLVMOpInfoCallback GetOpInfo;
- // 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;
- // The address of the instruction being disassembled.
- uint64_t Address;
-
-public:
- void setupBuilderForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo,
- void *disInfo, MCContext *ctx,
- uint64_t address) {
- GetOpInfo = getOpInfo;
- DisInfo = disInfo;
- Ctx = ctx;
- Address = address;
- }
-
- uint64_t getBuilderAddress() const { return Address; }
-
- /// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic
- /// operand in place of the immediate Value in the MCInst. The immediate
- /// Value has had any PC adjustment made by the caller. If the getOpInfo()
- /// function was set as part of the setupBuilderForSymbolicDisassembly() call
- /// then that function is called to get any symbolic information at the
- /// builder's Address for this instrution. If that returns non-zero then the
- /// symbolic information it returns is used to create an MCExpr and that is
- /// added as an operand to the MCInst. This function returns true if it adds
- /// an operand to the MCInst and false otherwise.
- bool tryAddingSymbolicOperand(uint64_t Value, uint64_t InstSize, MCInst &MI);
-
-};
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Target/ARM/Disassembler/CMakeLists.txt b/lib/Target/ARM/Disassembler/CMakeLists.txt
index b23dd6b..da87751 100644
--- a/lib/Target/ARM/Disassembler/CMakeLists.txt
+++ b/lib/Target/ARM/Disassembler/CMakeLists.txt
@@ -2,7 +2,6 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/
add_llvm_library(LLVMARMDisassembler
ARMDisassembler.cpp
- ARMDisassemblerCore.cpp
)
# workaround for hanging compilation on MSVC8, 9 and 10
if( MSVC_VERSION EQUAL 1400 OR MSVC_VERSION EQUAL 1500 OR MSVC_VERSION EQUAL 1600 )
@@ -11,4 +10,12 @@ set_property(
PROPERTY COMPILE_FLAGS "/Od"
)
endif()
-add_dependencies(LLVMARMDisassembler ARMCodeGenTable_gen)
+add_dependencies(LLVMARMDisassembler ARMCommonTableGen)
+
+add_llvm_library_dependencies(LLVMARMDisassembler
+ LLVMARMCodeGen
+ LLVMARMDesc
+ LLVMARMInfo
+ LLVMMC
+ LLVMSupport
+ )
diff --git a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h
deleted file mode 100644
index 834c6f6..0000000
--- a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h
+++ /dev/null
@@ -1,2459 +0,0 @@
-//===- ThumbDisassemblerCore.h - Thumb disassembler helpers -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is part of the ARM Disassembler.
-// It contains code for disassembling a Thumb instr. It is to be included by
-// ARMDisassemblerCore.cpp because it contains the static DisassembleThumbFrm()
-// function which acts as the dispatcher to disassemble a Thumb instruction.
-//
-//===----------------------------------------------------------------------===//
-
-///////////////////////////////
-// //
-// Utility Functions //
-// //
-///////////////////////////////
-
-// Utilities for 16-bit Thumb instructions.
-/*
-15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- [ tRt ]
- [ tRm ] [ tRn ] [ tRd ]
- D [ Rm ] [ Rd ]
-
- [ imm3]
- [ imm5 ]
- i [ imm5 ]
- [ imm7 ]
- [ imm8 ]
- [ imm11 ]
-
- [ cond ]
-*/
-
-// Extract tRt: Inst{10-8}.
-static inline unsigned getT1tRt(uint32_t insn) {
- return slice(insn, 10, 8);
-}
-
-// Extract tRm: Inst{8-6}.
-static inline unsigned getT1tRm(uint32_t insn) {
- return slice(insn, 8, 6);
-}
-
-// Extract tRn: Inst{5-3}.
-static inline unsigned getT1tRn(uint32_t insn) {
- return slice(insn, 5, 3);
-}
-
-// Extract tRd: Inst{2-0}.
-static inline unsigned getT1tRd(uint32_t insn) {
- return slice(insn, 2, 0);
-}
-
-// Extract [D:Rd]: Inst{7:2-0}.
-static inline unsigned getT1Rd(uint32_t insn) {
- return slice(insn, 7, 7) << 3 | slice(insn, 2, 0);
-}
-
-// Extract Rm: Inst{6-3}.
-static inline unsigned getT1Rm(uint32_t insn) {
- return slice(insn, 6, 3);
-}
-
-// Extract imm3: Inst{8-6}.
-static inline unsigned getT1Imm3(uint32_t insn) {
- return slice(insn, 8, 6);
-}
-
-// Extract imm5: Inst{10-6}.
-static inline unsigned getT1Imm5(uint32_t insn) {
- return slice(insn, 10, 6);
-}
-
-// Extract i:imm5: Inst{9:7-3}.
-static inline unsigned getT1Imm6(uint32_t insn) {
- return slice(insn, 9, 9) << 5 | slice(insn, 7, 3);
-}
-
-// Extract imm7: Inst{6-0}.
-static inline unsigned getT1Imm7(uint32_t insn) {
- return slice(insn, 6, 0);
-}
-
-// Extract imm8: Inst{7-0}.
-static inline unsigned getT1Imm8(uint32_t insn) {
- return slice(insn, 7, 0);
-}
-
-// Extract imm11: Inst{10-0}.
-static inline unsigned getT1Imm11(uint32_t insn) {
- return slice(insn, 10, 0);
-}
-
-// Extract cond: Inst{11-8}.
-static inline unsigned getT1Cond(uint32_t insn) {
- return slice(insn, 11, 8);
-}
-
-static inline bool IsGPR(unsigned RegClass) {
- return RegClass == ARM::GPRRegClassID || RegClass == ARM::rGPRRegClassID;
-}
-
-// Utilities for 32-bit Thumb instructions.
-
-static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; }
-
-// Extract imm4: Inst{19-16}.
-static inline unsigned getImm4(uint32_t insn) {
- return slice(insn, 19, 16);
-}
-
-// Extract imm3: Inst{14-12}.
-static inline unsigned getImm3(uint32_t insn) {
- return slice(insn, 14, 12);
-}
-
-// Extract imm8: Inst{7-0}.
-static inline unsigned getImm8(uint32_t insn) {
- return slice(insn, 7, 0);
-}
-
-// A8.6.61 LDRB (immediate, Thumb) and friends
-// +/-: Inst{9}
-// imm8: Inst{7-0}
-static inline int decodeImm8(uint32_t insn) {
- int Offset = getImm8(insn);
- return slice(insn, 9, 9) ? Offset : -Offset;
-}
-
-// Extract imm12: Inst{11-0}.
-static inline unsigned getImm12(uint32_t insn) {
- return slice(insn, 11, 0);
-}
-
-// A8.6.63 LDRB (literal) and friends
-// +/-: Inst{23}
-// imm12: Inst{11-0}
-static inline int decodeImm12(uint32_t insn) {
- int Offset = getImm12(insn);
- return slice(insn, 23, 23) ? Offset : -Offset;
-}
-
-// Extract imm2: Inst{7-6}.
-static inline unsigned getImm2(uint32_t insn) {
- return slice(insn, 7, 6);
-}
-
-// For BFI, BFC, t2SBFX, and t2UBFX.
-// Extract lsb: Inst{14-12:7-6}.
-static inline unsigned getLsb(uint32_t insn) {
- return getImm3(insn) << 2 | getImm2(insn);
-}
-
-// For BFI and BFC.
-// Extract msb: Inst{4-0}.
-static inline unsigned getMsb(uint32_t insn) {
- return slice(insn, 4, 0);
-}
-
-// For t2SBFX and t2UBFX.
-// Extract widthminus1: Inst{4-0}.
-static inline unsigned getWidthMinus1(uint32_t insn) {
- return slice(insn, 4, 0);
-}
-
-// For t2ADDri12 and t2SUBri12.
-// imm12 = i:imm3:imm8;
-static inline unsigned getIImm3Imm8(uint32_t insn) {
- return slice(insn, 26, 26) << 11 | getImm3(insn) << 8 | getImm8(insn);
-}
-
-// For t2MOVi16 and t2MOVTi16.
-// imm16 = imm4:i:imm3:imm8;
-static inline unsigned getImm16(uint32_t insn) {
- return getImm4(insn) << 12 | slice(insn, 26, 26) << 11 |
- getImm3(insn) << 8 | getImm8(insn);
-}
-
-// Inst{5-4} encodes the shift type.
-static inline unsigned getShiftTypeBits(uint32_t insn) {
- return slice(insn, 5, 4);
-}
-
-// Inst{14-12}:Inst{7-6} encodes the imm5 shift amount.
-static inline unsigned getShiftAmtBits(uint32_t insn) {
- return getImm3(insn) << 2 | getImm2(insn);
-}
-
-// A8.6.17 BFC
-// Encoding T1 ARMv6T2, ARMv7
-// LLVM-specific encoding for #<lsb> and #<width>
-static inline bool getBitfieldInvMask(uint32_t insn, uint32_t &mask) {
- uint32_t lsb = getImm3(insn) << 2 | getImm2(insn);
- uint32_t msb = getMsb(insn);
- uint32_t Val = 0;
- if (msb < lsb) {
- DEBUG(errs() << "Encoding error: msb < lsb\n");
- return false;
- }
- for (uint32_t i = lsb; i <= msb; ++i)
- Val |= (1 << i);
- mask = ~Val;
- return true;
-}
-
-// A8.4 Shifts applied to a register
-// A8.4.1 Constant shifts
-// A8.4.3 Pseudocode details of instruction-specified shifts and rotates
-//
-// decodeImmShift() returns the shift amount and the the shift opcode.
-// Note that, as of Jan-06-2010, LLVM does not support rrx shifted operands yet.
-static inline unsigned decodeImmShift(unsigned bits2, unsigned imm5,
- ARM_AM::ShiftOpc &ShOp) {
-
- assert(imm5 < 32 && "Invalid imm5 argument");
- switch (bits2) {
- default: assert(0 && "No such value");
- case 0:
- ShOp = (imm5 == 0 ? ARM_AM::no_shift : ARM_AM::lsl);
- return imm5;
- case 1:
- ShOp = ARM_AM::lsr;
- return (imm5 == 0 ? 32 : imm5);
- case 2:
- ShOp = ARM_AM::asr;
- return (imm5 == 0 ? 32 : imm5);
- case 3:
- ShOp = (imm5 == 0 ? ARM_AM::rrx : ARM_AM::ror);
- return (imm5 == 0 ? 1 : imm5);
- }
-}
-
-// A6.3.2 Modified immediate constants in Thumb instructions
-//
-// ThumbExpandImm() returns the modified immediate constant given an imm12 for
-// Thumb data-processing instructions with modified immediate.
-// See also A6.3.1 Data-processing (modified immediate).
-static inline unsigned ThumbExpandImm(unsigned imm12) {
- assert(imm12 <= 0xFFF && "Invalid imm12 argument");
-
- // If the leading two bits is 0b00, the modified immediate constant is
- // obtained by splatting the low 8 bits into the first byte, every other byte,
- // or every byte of a 32-bit value.
- //
- // Otherwise, a rotate right of '1':imm12<6:0> by the amount imm12<11:7> is
- // performed.
-
- if (slice(imm12, 11, 10) == 0) {
- unsigned short control = slice(imm12, 9, 8);
- unsigned imm8 = slice(imm12, 7, 0);
- switch (control) {
- default:
- assert(0 && "No such value");
- return 0;
- case 0:
- return imm8;
- case 1:
- return imm8 << 16 | imm8;
- case 2:
- return imm8 << 24 | imm8 << 8;
- case 3:
- return imm8 << 24 | imm8 << 16 | imm8 << 8 | imm8;
- }
- } else {
- // A rotate is required.
- unsigned Val = 1 << 7 | slice(imm12, 6, 0);
- unsigned Amt = slice(imm12, 11, 7);
- return ARM_AM::rotr32(Val, Amt);
- }
-}
-
-static inline int decodeImm32_B_EncodingT3(uint32_t insn) {
- bool S = slice(insn, 26, 26);
- bool J1 = slice(insn, 13, 13);
- bool J2 = slice(insn, 11, 11);
- unsigned Imm21 = slice(insn, 21, 16) << 12 | slice(insn, 10, 0) << 1;
- if (S) Imm21 |= 1 << 20;
- if (J2) Imm21 |= 1 << 19;
- if (J1) Imm21 |= 1 << 18;
-
- return SignExtend32<21>(Imm21);
-}
-
-static inline int decodeImm32_B_EncodingT4(uint32_t insn) {
- unsigned S = slice(insn, 26, 26);
- bool I1 = slice(insn, 13, 13) == S;
- bool I2 = slice(insn, 11, 11) == S;
- unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 0) << 1;
- if (S) Imm25 |= 1 << 24;
- if (I1) Imm25 |= 1 << 23;
- if (I2) Imm25 |= 1 << 22;
-
- return SignExtend32<25>(Imm25);
-}
-
-static inline int decodeImm32_BL(uint32_t insn) {
- unsigned S = slice(insn, 26, 26);
- bool I1 = slice(insn, 13, 13) == S;
- bool I2 = slice(insn, 11, 11) == S;
- unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 0) << 1;
- if (S) Imm25 |= 1 << 24;
- if (I1) Imm25 |= 1 << 23;
- if (I2) Imm25 |= 1 << 22;
-
- return SignExtend32<25>(Imm25);
-}
-
-static inline int decodeImm32_BLX(uint32_t insn) {
- unsigned S = slice(insn, 26, 26);
- bool I1 = slice(insn, 13, 13) == S;
- bool I2 = slice(insn, 11, 11) == S;
- unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 1) << 2;
- if (S) Imm25 |= 1 << 24;
- if (I1) Imm25 |= 1 << 23;
- if (I2) Imm25 |= 1 << 22;
-
- return SignExtend32<25>(Imm25);
-}
-
-// See, for example, A8.6.221 SXTAB16.
-static inline unsigned decodeRotate(uint32_t insn) {
- unsigned rotate = slice(insn, 5, 4);
- return rotate << 3;
-}
-
-///////////////////////////////////////////////
-// //
-// Thumb1 instruction disassembly functions. //
-// //
-///////////////////////////////////////////////
-
-// See "Utilities for 16-bit Thumb instructions" for register naming convention.
-
-// A6.2.1 Shift (immediate), add, subtract, move, and compare
-//
-// shift immediate: tRd CPSR tRn imm5
-// add/sub register: tRd CPSR tRn tRm
-// add/sub 3-bit immediate: tRd CPSR tRn imm3
-// add/sub 8-bit immediate: tRt CPSR tRt(TIED_TO) imm8
-// mov/cmp immediate: tRt [CPSR] imm8 (CPSR present for mov)
-//
-// Special case:
-// tMOVSr: tRd tRn
-static bool DisassembleThumb1General(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID
- && "Invalid arguments");
-
- bool Imm3 = (Opcode == ARM::tADDi3 || Opcode == ARM::tSUBi3);
-
- // Use Rt implies use imm8.
- bool UseRt = (Opcode == ARM::tADDi8 || Opcode == ARM::tSUBi8 ||
- Opcode == ARM::tMOVi8 || Opcode == ARM::tCMPi8);
-
- // Add the destination operand.
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, ARM::tGPRRegClassID,
- UseRt ? getT1tRt(insn) : getT1tRd(insn))));
- ++OpIdx;
-
- // Check whether the next operand to be added is a CCR Register.
- if (OpInfo[OpIdx].RegClass == ARM::CCRRegClassID) {
- assert(OpInfo[OpIdx].isOptionalDef() && "Optional def operand expected");
- MI.addOperand(MCOperand::CreateReg(B->InITBlock() ? 0 : ARM::CPSR));
- ++OpIdx;
- }
-
- // Check whether the next operand to be added is a Thumb1 Register.
- assert(OpIdx < NumOps && "More operands expected");
- if (OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) {
- // For UseRt, the reg operand is tied to the first reg operand.
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, ARM::tGPRRegClassID,
- UseRt ? getT1tRt(insn) : getT1tRn(insn))));
- ++OpIdx;
- }
-
- // Special case for tMOVSr.
- if (OpIdx == NumOps)
- return true;
-
- // The next available operand is either a reg operand or an imm operand.
- if (OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) {
- // Three register operand instructions.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRm(insn))));
- } else {
- assert(OpInfo[OpIdx].RegClass < 0 &&
- !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()
- && "Pure imm operand expected");
- unsigned Imm = 0;
- if (UseRt)
- Imm = getT1Imm8(insn);
- else if (Imm3)
- Imm = getT1Imm3(insn);
- else {
- Imm = getT1Imm5(insn);
- ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 12, 11));
- getImmShiftSE(ShOp, Imm);
- }
- MI.addOperand(MCOperand::CreateImm(Imm));
- }
- ++OpIdx;
-
- return true;
-}
-
-// A6.2.2 Data-processing
-//
-// tCMPr, tTST, tCMN: tRd tRn
-// tMVN, tRSB: tRd CPSR tRn
-// Others: tRd CPSR tRd(TIED_TO) tRn
-static bool DisassembleThumb1DP(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
- (OpInfo[1].RegClass == ARM::CCRRegClassID
- || OpInfo[1].RegClass == ARM::tGPRRegClassID)
- && "Invalid arguments");
-
- // Add the destination operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRd(insn))));
- ++OpIdx;
-
- // Check whether the next operand to be added is a CCR Register.
- if (OpInfo[OpIdx].RegClass == ARM::CCRRegClassID) {
- assert(OpInfo[OpIdx].isOptionalDef() && "Optional def operand expected");
- MI.addOperand(MCOperand::CreateReg(B->InITBlock() ? 0 : ARM::CPSR));
- ++OpIdx;
- }
-
- // We have either { tRd(TIED_TO), tRn } or { tRn } remaining.
- // Process the TIED_TO operand first.
-
- assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID
- && "Thumb reg operand expected");
- int Idx;
- if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
- // The reg operand is tied to the first reg operand.
- MI.addOperand(MI.getOperand(Idx));
- ++OpIdx;
- }
-
- // Process possible next reg operand.
- if (OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) {
- // Add tRn operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRn(insn))));
- ++OpIdx;
- }
-
- return true;
-}
-
-// A6.2.3 Special data instructions and branch and exchange
-//
-// tADDhirr: Rd Rd(TIED_TO) Rm
-// tCMPhir: Rd Rm
-// tMOVr, tMOVgpr2gpr, tMOVgpr2tgpr, tMOVtgpr2gpr: Rd|tRd Rm|tRn
-// tBX: Rm
-// tBX_RET: 0 operand
-// tBX_RET_vararg: Rm
-// tBLXr_r9: Rm
-// tBRIND: Rm
-static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- // tBX_RET has 0 operand.
- if (NumOps == 0)
- return true;
-
- // BX/BLX/tBRIND (indirect branch, i.e, mov pc, Rm) has 1 reg operand: Rm.
- if (Opcode==ARM::tBLXr_r9 || Opcode==ARM::tBX || Opcode==ARM::tBRIND) {
- if (Opcode == ARM::tBLXr_r9) {
- // Handling the two predicate operands before the reg operand.
- if (!B->DoPredicateOperands(MI, Opcode, insn, NumOps))
- return false;
- NumOpsAdded += 2;
- }
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- getT1Rm(insn))));
- NumOpsAdded += 1;
-
- if (Opcode == ARM::tBX) {
- // Handling the two predicate operands after the reg operand.
- if (!B->DoPredicateOperands(MI, Opcode, insn, NumOps))
- return false;
- NumOpsAdded += 2;
- }
-
- return true;
- }
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- // Add the destination operand.
- unsigned RegClass = OpInfo[OpIdx].RegClass;
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, RegClass,
- IsGPR(RegClass) ? getT1Rd(insn)
- : getT1tRd(insn))));
- ++OpIdx;
-
- // We have either { Rd(TIED_TO), Rm } or { Rm|tRn } remaining.
- // Process the TIED_TO operand first.
-
- assert(OpIdx < NumOps && "More operands expected");
- int Idx;
- if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
- // The reg operand is tied to the first reg operand.
- MI.addOperand(MI.getOperand(Idx));
- ++OpIdx;
- }
-
- // The next reg operand is either Rm or tRn.
- assert(OpIdx < NumOps && "More operands expected");
- RegClass = OpInfo[OpIdx].RegClass;
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, RegClass,
- IsGPR(RegClass) ? getT1Rm(insn)
- : getT1tRn(insn))));
- ++OpIdx;
-
- return true;
-}
-
-// A8.6.59 LDR (literal)
-//
-// tLDRpci: tRt imm8*4
-static bool DisassembleThumb1LdPC(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
- (OpInfo[1].RegClass < 0 &&
- !OpInfo[1].isPredicate() &&
- !OpInfo[1].isOptionalDef())
- && "Invalid arguments");
-
- // Add the destination operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRt(insn))));
-
- // And the (imm8 << 2) operand.
- MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn) << 2));
-
- NumOpsAdded = 2;
-
- return true;
-}
-
-// Thumb specific addressing modes (see ARMInstrThumb.td):
-//
-// t_addrmode_rr := reg + reg
-//
-// t_addrmode_s4 := reg + reg
-// reg + imm5 * 4
-//
-// t_addrmode_s2 := reg + reg
-// reg + imm5 * 2
-//
-// t_addrmode_s1 := reg + reg
-// reg + imm5
-//
-// t_addrmode_sp := sp + imm8 * 4
-//
-
-// A8.6.63 LDRB (literal)
-// A8.6.79 LDRSB (literal)
-// A8.6.75 LDRH (literal)
-// A8.6.83 LDRSH (literal)
-// A8.6.59 LDR (literal)
-//
-// These instrs calculate an address from the PC value and an immediate offset.
-// Rd Rn=PC (+/-)imm12 (+ if Inst{23} == 0b1)
-static bool DisassembleThumb2Ldpci(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- assert(NumOps >= 2 &&
- OpInfo[0].RegClass == ARM::GPRRegClassID &&
- OpInfo[1].RegClass < 0 &&
- "Expect >= 2 operands, first as reg, and second as imm operand");
-
- // Build the register operand, followed by the (+/-)imm12 immediate.
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRd(insn))));
-
- MI.addOperand(MCOperand::CreateImm(decodeImm12(insn)));
-
- NumOpsAdded = 2;
-
- return true;
-}
-
-
-// A6.2.4 Load/store single data item
-//
-// Load/Store Register (reg|imm): tRd tRn imm5|tRm
-// Load Register Signed Byte|Halfword: tRd tRn tRm
-static bool DisassembleThumb1LdSt(unsigned opA, MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- assert(NumOps >= 2
- && OpInfo[0].RegClass == ARM::tGPRRegClassID
- && OpInfo[1].RegClass == ARM::tGPRRegClassID
- && "Expect >= 2 operands and first two as thumb reg operands");
-
- // Add the destination reg and the base reg.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRd(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRn(insn))));
- OpIdx = 2;
-
- // We have either { imm5 } or { tRm } remaining.
- // Note that STR/LDR (register) should skip the imm5 offset operand for
- // t_addrmode_s[1|2|4].
-
- assert(OpIdx < NumOps && "More operands expected");
-
- if (OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() &&
- !OpInfo[OpIdx].isOptionalDef()) {
- // Table A6-5 16-bit Thumb Load/store instructions
- // opA = 0b0101 for STR/LDR (register) and friends.
- // Otherwise, we have STR/LDR (immediate) and friends.
- assert(opA != 5 && "Immediate operand expected for this opcode");
- MI.addOperand(MCOperand::CreateImm(getT1Imm5(insn)));
- ++OpIdx;
- } else {
- // The next reg operand is tRm, the offset.
- assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID
- && "Thumb reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRm(insn))));
- ++OpIdx;
- }
- return true;
-}
-
-// A6.2.4 Load/store single data item
-//
-// Load/Store Register SP relative: tRt ARM::SP imm8
-static bool DisassembleThumb1LdStSP(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert((Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi)
- && "Unexpected opcode");
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- assert(NumOps >= 3 &&
- OpInfo[0].RegClass == ARM::tGPRRegClassID &&
- OpInfo[1].RegClass == ARM::GPRRegClassID &&
- (OpInfo[2].RegClass < 0 &&
- !OpInfo[2].isPredicate() &&
- !OpInfo[2].isOptionalDef())
- && "Invalid arguments");
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRt(insn))));
- MI.addOperand(MCOperand::CreateReg(ARM::SP));
- MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn)));
- NumOpsAdded = 3;
- return true;
-}
-
-// Table A6-1 16-bit Thumb instruction encoding
-// A8.6.10 ADR
-//
-// tADDrPCi: tRt imm8
-static bool DisassembleThumb1AddPCi(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(Opcode == ARM::tADDrPCi && "Unexpected opcode");
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
- (OpInfo[1].RegClass < 0 &&
- !OpInfo[1].isPredicate() &&
- !OpInfo[1].isOptionalDef())
- && "Invalid arguments");
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRt(insn))));
- MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn)));
- NumOpsAdded = 2;
- return true;
-}
-
-// Table A6-1 16-bit Thumb instruction encoding
-// A8.6.8 ADD (SP plus immediate)
-//
-// tADDrSPi: tRt ARM::SP imm8
-static bool DisassembleThumb1AddSPi(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(Opcode == ARM::tADDrSPi && "Unexpected opcode");
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- assert(NumOps >= 3 &&
- OpInfo[0].RegClass == ARM::tGPRRegClassID &&
- OpInfo[1].RegClass == ARM::GPRRegClassID &&
- (OpInfo[2].RegClass < 0 &&
- !OpInfo[2].isPredicate() &&
- !OpInfo[2].isOptionalDef())
- && "Invalid arguments");
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRt(insn))));
- MI.addOperand(MCOperand::CreateReg(ARM::SP));
- MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn)));
- NumOpsAdded = 3;
- return true;
-}
-
-// tPUSH, tPOP: Pred-Imm Pred-CCR register_list
-//
-// where register_list = low registers + [lr] for PUSH or
-// low registers + [pc] for POP
-//
-// "low registers" is specified by Inst{7-0}
-// lr|pc is specified by Inst{8}
-static bool DisassembleThumb1PushPop(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert((Opcode == ARM::tPUSH || Opcode == ARM::tPOP) && "Unexpected opcode");
-
- unsigned &OpIdx = NumOpsAdded;
-
- // Handling the two predicate operands before the reglist.
- if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
- OpIdx += 2;
- else {
- DEBUG(errs() << "Expected predicate operands not found.\n");
- return false;
- }
-
- unsigned RegListBits = slice(insn, 8, 8) << (Opcode == ARM::tPUSH ? 14 : 15)
- | slice(insn, 7, 0);
-
- // Fill the variadic part of reglist.
- for (unsigned i = 0; i < 16; ++i) {
- if ((RegListBits >> i) & 1) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- i)));
- ++OpIdx;
- }
- }
-
- return true;
-}
-
-// A6.2.5 Miscellaneous 16-bit instructions
-// Delegate to DisassembleThumb1PushPop() for tPUSH & tPOP.
-//
-// tADDspi, tSUBspi: ARM::SP ARM::SP(TIED_TO) imm7
-// t2IT: firstcond=Inst{7-4} mask=Inst{3-0}
-// tCBNZ, tCBZ: tRd imm6*2
-// tBKPT: imm8
-// tNOP, tSEV, tYIELD, tWFE, tWFI:
-// no operand (except predicate pair)
-// tSETENDBE, tSETENDLE, :
-// no operand
-// Others: tRd tRn
-static bool DisassembleThumb1Misc(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- if (NumOps == 0)
- return true;
-
- if (Opcode == ARM::tPUSH || Opcode == ARM::tPOP)
- return DisassembleThumb1PushPop(MI, Opcode, insn, NumOps, NumOpsAdded, B);
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
-
- // Predicate operands are handled elsewhere.
- if (NumOps == 2 &&
- OpInfo[0].isPredicate() && OpInfo[1].isPredicate() &&
- OpInfo[0].RegClass < 0 && OpInfo[1].RegClass == ARM::CCRRegClassID) {
- return true;
- }
-
- if (Opcode == ARM::tADDspi || Opcode == ARM::tSUBspi) {
- // Special case handling for tADDspi and tSUBspi.
- // A8.6.8 ADD (SP plus immediate) & A8.6.215 SUB (SP minus immediate)
- MI.addOperand(MCOperand::CreateReg(ARM::SP));
- MI.addOperand(MCOperand::CreateReg(ARM::SP));
- MI.addOperand(MCOperand::CreateImm(getT1Imm7(insn)));
- NumOpsAdded = 3;
- return true;
- }
-
- if (Opcode == ARM::t2IT) {
- // Special case handling for If-Then.
- // A8.6.50 IT
- // Tag the (firstcond[0] bit << 4) along with mask.
-
- // firstcond
- MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 4)));
-
- // firstcond[0] and mask
- MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));
- NumOpsAdded = 2;
- return true;
- }
-
- if (Opcode == ARM::tBKPT) {
- MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn))); // breakpoint value
- NumOpsAdded = 1;
- return true;
- }
-
- // CPS has a singleton $opt operand that contains the following information:
- // The first op would be 0b10 as enable and 0b11 as disable in regular ARM,
- // but in Thumb it's is 0 as enable and 1 as disable. So map it to ARM's
- // default one. The second get the AIF flags from Inst{2-0}.
- if (Opcode == ARM::tCPS) {
- MI.addOperand(MCOperand::CreateImm(2 + slice(insn, 4, 4)));
- MI.addOperand(MCOperand::CreateImm(slice(insn, 2, 0)));
- NumOpsAdded = 2;
- return true;
- }
-
- assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
- (OpInfo[1].RegClass < 0 || OpInfo[1].RegClass==ARM::tGPRRegClassID)
- && "Expect >=2 operands");
-
- // Add the destination operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRd(insn))));
-
- if (OpInfo[1].RegClass == ARM::tGPRRegClassID) {
- // Two register instructions.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- getT1tRn(insn))));
- } else {
- // CBNZ, CBZ
- assert((Opcode == ARM::tCBNZ || Opcode == ARM::tCBZ) &&"Unexpected opcode");
- MI.addOperand(MCOperand::CreateImm(getT1Imm6(insn) * 2));
- }
-
- NumOpsAdded = 2;
-
- return true;
-}
-
-// A8.6.53 LDM / LDMIA
-// A8.6.189 STM / STMIA
-//
-// tLDMIA_UPD/tSTMIA_UPD: tRt tRt AM4ModeImm Pred-Imm Pred-CCR register_list
-// tLDMIA: tRt AM4ModeImm Pred-Imm Pred-CCR register_list
-static bool DisassembleThumb1LdStMul(bool Ld, MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps,
- unsigned &NumOpsAdded, BO B) {
- assert((Opcode == ARM::tLDMIA || Opcode == ARM::tLDMIA_UPD ||
- Opcode == ARM::tSTMIA_UPD) && "Unexpected opcode");
-
- unsigned tRt = getT1tRt(insn);
- NumOpsAdded = 0;
-
- // WB register, if necessary.
- if (Opcode == ARM::tLDMIA_UPD || Opcode == ARM::tSTMIA_UPD) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- tRt)));
- ++NumOpsAdded;
- }
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- tRt)));
- ++NumOpsAdded;
-
- // Handling the two predicate operands before the reglist.
- if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) {
- NumOpsAdded += 2;
- } else {
- DEBUG(errs() << "Expected predicate operands not found.\n");
- return false;
- }
-
- unsigned RegListBits = slice(insn, 7, 0);
- if (BitCount(RegListBits) < 1) {
- DEBUG(errs() << "if BitCount(registers) < 1 then UNPREDICTABLE\n");
- return false;
- }
-
- // Fill the variadic part of reglist.
- for (unsigned i = 0; i < 8; ++i)
- if ((RegListBits >> i) & 1) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
- i)));
- ++NumOpsAdded;
- }
-
- return true;
-}
-
-static bool DisassembleThumb1LdMul(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- return DisassembleThumb1LdStMul(true, MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
-}
-
-static bool DisassembleThumb1StMul(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- return DisassembleThumb1LdStMul(false, MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
-}
-
-// A8.6.16 B Encoding T1
-// cond = Inst{11-8} & imm8 = Inst{7-0}
-// imm32 = SignExtend(imm8:'0', 32)
-//
-// tBcc: offset Pred-Imm Pred-CCR
-// tSVC: imm8 Pred-Imm Pred-CCR
-// tTRAP: 0 operand (early return)
-static bool DisassembleThumb1CondBr(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
-
- if (Opcode == ARM::tTRAP)
- return true;
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- assert(NumOps == 3 && OpInfo[0].RegClass < 0 &&
- OpInfo[1].isPredicate() && OpInfo[2].RegClass == ARM::CCRRegClassID
- && "Exactly 3 operands expected");
-
- unsigned Imm8 = getT1Imm8(insn);
- MI.addOperand(MCOperand::CreateImm(
- Opcode == ARM::tBcc ? SignExtend32<9>(Imm8 << 1)
- : (int)Imm8));
-
- // Predicate operands by ARMBasicMCBuilder::TryPredicateAndSBitModifier().
- // But note that for tBcc, if cond = '1110' then UNDEFINED.
- if (Opcode == ARM::tBcc && slice(insn, 11, 8) == 14) {
- DEBUG(errs() << "if cond = '1110' then UNDEFINED\n");
- return false;
- }
- NumOpsAdded = 1;
-
- return true;
-}
-
-// A8.6.16 B Encoding T2
-// imm11 = Inst{10-0}
-// imm32 = SignExtend(imm11:'0', 32)
-//
-// tB: offset
-static bool DisassembleThumb1Br(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- assert(NumOps == 1 && OpInfo[0].RegClass < 0 && "1 imm operand expected");
-
- unsigned Imm11 = getT1Imm11(insn);
-
- MI.addOperand(MCOperand::CreateImm(SignExtend32<12>(Imm11 << 1)));
-
- NumOpsAdded = 1;
-
- return true;
-
-}
-
-// See A6.2 16-bit Thumb instruction encoding for instruction classes
-// corresponding to op.
-//
-// Table A6-1 16-bit Thumb instruction encoding (abridged)
-// op Instruction or instruction class
-// ------ --------------------------------------------------------------------
-// 00xxxx Shift (immediate), add, subtract, move, and compare on page A6-7
-// 010000 Data-processing on page A6-8
-// 010001 Special data instructions and branch and exchange on page A6-9
-// 01001x Load from Literal Pool, see LDR (literal) on page A8-122
-// 0101xx Load/store single data item on page A6-10
-// 011xxx
-// 100xxx
-// 10100x Generate PC-relative address, see ADR on page A8-32
-// 10101x Generate SP-relative address, see ADD (SP plus immediate) on
-// page A8-28
-// 1011xx Miscellaneous 16-bit instructions on page A6-11
-// 11000x Store multiple registers, see STM / STMIA / STMEA on page A8-374
-// 11001x Load multiple registers, see LDM / LDMIA / LDMFD on page A8-110 a
-// 1101xx Conditional branch, and Supervisor Call on page A6-13
-// 11100x Unconditional Branch, see B on page A8-44
-//
-static bool DisassembleThumb1(uint16_t op, MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- unsigned op1 = slice(op, 5, 4);
- unsigned op2 = slice(op, 3, 2);
- unsigned op3 = slice(op, 1, 0);
- unsigned opA = slice(op, 5, 2);
- switch (op1) {
- case 0:
- // A6.2.1 Shift (immediate), add, subtract, move, and compare
- return DisassembleThumb1General(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- case 1:
- switch (op2) {
- case 0:
- switch (op3) {
- case 0:
- // A6.2.2 Data-processing
- return DisassembleThumb1DP(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- case 1:
- // A6.2.3 Special data instructions and branch and exchange
- return DisassembleThumb1Special(MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- default:
- // A8.6.59 LDR (literal)
- return DisassembleThumb1LdPC(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- }
- break;
- default:
- // A6.2.4 Load/store single data item
- return DisassembleThumb1LdSt(opA, MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- break;
- }
- break;
- case 2:
- switch (op2) {
- case 0:
- // A6.2.4 Load/store single data item
- return DisassembleThumb1LdSt(opA, MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- case 1:
- // A6.2.4 Load/store single data item
- return DisassembleThumb1LdStSP(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- case 2:
- if (op3 <= 1) {
- // A8.6.10 ADR
- return DisassembleThumb1AddPCi(MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- } else {
- // A8.6.8 ADD (SP plus immediate)
- return DisassembleThumb1AddSPi(MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- }
- default:
- // A6.2.5 Miscellaneous 16-bit instructions
- return DisassembleThumb1Misc(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- }
- break;
- case 3:
- switch (op2) {
- case 0:
- if (op3 <= 1) {
- // A8.6.189 STM / STMIA / STMEA
- return DisassembleThumb1StMul(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- } else {
- // A8.6.53 LDM / LDMIA / LDMFD
- return DisassembleThumb1LdMul(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- }
- case 1:
- // A6.2.6 Conditional branch, and Supervisor Call
- return DisassembleThumb1CondBr(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- case 2:
- // Unconditional Branch, see B on page A8-44
- return DisassembleThumb1Br(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- default:
- assert(0 && "Unreachable code");
- break;
- }
- break;
- default:
- assert(0 && "Unreachable code");
- break;
- }
-
- return false;
-}
-
-///////////////////////////////////////////////
-// //
-// Thumb2 instruction disassembly functions. //
-// //
-///////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////
-// //
-// Note: the register naming follows the ARM convention! //
-// //
-///////////////////////////////////////////////////////////
-
-static inline bool Thumb2SRSOpcode(unsigned Opcode) {
- switch (Opcode) {
- default:
- return false;
- case ARM::t2SRSDBW: case ARM::t2SRSDB:
- case ARM::t2SRSIAW: case ARM::t2SRSIA:
- return true;
- }
-}
-
-static inline bool Thumb2RFEOpcode(unsigned Opcode) {
- switch (Opcode) {
- default:
- return false;
- case ARM::t2RFEDBW: case ARM::t2RFEDB:
- case ARM::t2RFEIAW: case ARM::t2RFEIA:
- return true;
- }
-}
-
-// t2SRS[IA|DB]W/t2SRS[IA|DB]: mode_imm = Inst{4-0}
-static bool DisassembleThumb2SRS(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded) {
- MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));
- NumOpsAdded = 1;
- return true;
-}
-
-// t2RFE[IA|DB]W/t2RFE[IA|DB]: Rn
-static bool DisassembleThumb2RFE(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- unsigned Rn = decodeRn(insn);
- if (Rn == 15) {
- DEBUG(errs() << "if n == 15 then UNPREDICTABLE\n");
- return false;
- }
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,ARM::GPRRegClassID,Rn)));
- NumOpsAdded = 1;
- return true;
-}
-
-static bool DisassembleThumb2LdStMul(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- if (Thumb2SRSOpcode(Opcode))
- return DisassembleThumb2SRS(MI, Opcode, insn, NumOps, NumOpsAdded);
-
- if (Thumb2RFEOpcode(Opcode))
- return DisassembleThumb2RFE(MI, Opcode, insn, NumOps, NumOpsAdded, B);
-
- assert((Opcode == ARM::t2LDMIA || Opcode == ARM::t2LDMIA_UPD ||
- Opcode == ARM::t2LDMDB || Opcode == ARM::t2LDMDB_UPD ||
- Opcode == ARM::t2STMIA || Opcode == ARM::t2STMIA_UPD ||
- Opcode == ARM::t2STMDB || Opcode == ARM::t2STMDB_UPD)
- && "Unexpected opcode");
- assert(NumOps >= 4 && "Thumb2 LdStMul expects NumOps >= 4");
-
- NumOpsAdded = 0;
-
- unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
-
- // Writeback to base.
- if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD ||
- Opcode == ARM::t2STMIA_UPD || Opcode == ARM::t2STMDB_UPD) {
- MI.addOperand(MCOperand::CreateReg(Base));
- ++NumOpsAdded;
- }
-
- MI.addOperand(MCOperand::CreateReg(Base));
- ++NumOpsAdded;
-
- // Handling the two predicate operands before the reglist.
- if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) {
- NumOpsAdded += 2;
- } else {
- DEBUG(errs() << "Expected predicate operands not found.\n");
- return false;
- }
-
- unsigned RegListBits = insn & ((1 << 16) - 1);
-
- // Fill the variadic part of reglist.
- for (unsigned i = 0; i < 16; ++i)
- if ((RegListBits >> i) & 1) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- i)));
- ++NumOpsAdded;
- }
-
- return true;
-}
-
-// t2LDREX: Rd Rn
-// t2LDREXD: Rd Rs Rn
-// t2LDREXB, t2LDREXH: Rd Rn
-// t2STREX: Rs Rd Rn
-// t2STREXD: Rm Rd Rs Rn
-// t2STREXB, t2STREXH: Rm Rd Rn
-static bool DisassembleThumb2LdStEx(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(NumOps >= 2
- && OpInfo[0].RegClass > 0
- && OpInfo[1].RegClass > 0
- && "Expect >=2 operands and first two as reg operands");
-
- bool isStore = (ARM::t2STREX <= Opcode && Opcode <= ARM::t2STREXH);
- bool isSW = (Opcode == ARM::t2LDREX || Opcode == ARM::t2STREX);
- bool isDW = (Opcode == ARM::t2LDREXD || Opcode == ARM::t2STREXD);
-
- unsigned Rt = decodeRd(insn);
- unsigned Rt2 = decodeRs(insn); // But note that this is Rd for t2STREX.
- unsigned Rd = decodeRm(insn);
- unsigned Rn = decodeRn(insn);
-
- // Some sanity checking first.
- if (isStore) {
- // if d == n || d == t then UNPREDICTABLE
- // if d == n || d == t || d == t2 then UNPREDICTABLE
- if (isDW) {
- if (Rd == Rn || Rd == Rt || Rd == Rt2) {
- DEBUG(errs() << "if d == n || d == t || d == t2 then UNPREDICTABLE\n");
- return false;
- }
- } else {
- if (isSW) {
- if (Rt2 == Rn || Rt2 == Rt) {
- DEBUG(errs() << "if d == n || d == t then UNPREDICTABLE\n");
- return false;
- }
- } else {
- if (Rd == Rn || Rd == Rt) {
- DEBUG(errs() << "if d == n || d == t then UNPREDICTABLE\n");
- return false;
- }
- }
- }
- } else {
- // Load
- // A8.6.71 LDREXD
- // if t == t2 then UNPREDICTABLE
- if (isDW && Rt == Rt2) {
- DEBUG(errs() << "if t == t2 then UNPREDICTABLE\n");
- return false;
- }
- }
-
- // Add the destination operand for store.
- if (isStore) {
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- isSW ? Rt2 : Rd)));
- ++OpIdx;
- }
-
- // Source operand for store and destination operand for load.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- Rt)));
- ++OpIdx;
-
- // Thumb2 doubleword complication: with an extra source/destination operand.
- if (isDW) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass,
- Rt2)));
- ++OpIdx;
- }
-
- // Finally add the pointer operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- Rn)));
- ++OpIdx;
-
- return true;
-}
-
-// t2LDRDi8: Rd Rs Rn imm8s4 (offset mode)
-// t2LDRDpci: Rd Rs imm8s4 (Not decoded, prefer the generic t2LDRDi8 version)
-// t2STRDi8: Rd Rs Rn imm8s4 (offset mode)
-//
-// Ditto for t2LDRD_PRE, t2LDRD_POST, t2STRD_PRE, t2STRD_POST, which are for
-// disassembly only and do not have a tied_to writeback base register operand.
-static bool DisassembleThumb2LdStDual(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- if (!OpInfo) return false;
-
- assert(NumOps >= 4
- && OpInfo[0].RegClass > 0
- && OpInfo[0].RegClass == OpInfo[1].RegClass
- && OpInfo[2].RegClass > 0
- && OpInfo[3].RegClass < 0
- && "Expect >= 4 operands and first 3 as reg operands");
-
- // Thumnb allows for specifying Rt and Rt2, unlike ARM (which has Rt2==Rt+1).
- unsigned Rt = decodeRd(insn);
- unsigned Rt2 = decodeRs(insn);
- unsigned Rn = decodeRn(insn);
-
- // Some sanity checking first.
-
- // A8.6.67 LDRD (literal) has its W bit as (0).
- if (Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2LDRD_PRE || Opcode == ARM::t2LDRD_POST) {
- if (Rn == 15 && slice(insn, 21, 21) != 0)
- return false;
- } else {
- // For Dual Store, PC cannot be used as the base register.
- if (Rn == 15) {
- DEBUG(errs() << "if n == 15 then UNPREDICTABLE\n");
- return false;
- }
- }
- if (Rt == Rt2) {
- DEBUG(errs() << "if t == t2 then UNPREDICTABLE\n");
- return false;
- }
- if (Opcode != ARM::t2LDRDi8 && Opcode != ARM::t2STRDi8) {
- if (Rn == Rt || Rn == Rt2) {
- DEBUG(errs() << "if wback && (n == t || n == t2) then UNPREDICTABLE\n");
- return false;
- }
- }
-
- // Add the <Rt> <Rt2> operands.
- unsigned RegClassPair = OpInfo[0].RegClass;
- unsigned RegClassBase = OpInfo[2].RegClass;
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassPair,
- decodeRd(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassPair,
- decodeRs(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassBase,
- decodeRn(insn))));
-
- // Finally add (+/-)imm8*4, depending on the U bit.
- int Offset = getImm8(insn) * 4;
- if (getUBit(insn) == 0)
- Offset = -Offset;
- MI.addOperand(MCOperand::CreateImm(Offset));
- NumOpsAdded = 4;
-
- return true;
-}
-
-// t2TBB, t2TBH: Rn Rm Pred-Imm Pred-CCR
-static bool DisassembleThumb2TB(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- assert(NumOps >= 2 && "Expect >= 2 operands");
-
- // The generic version of TBB/TBH needs a base register.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- // Add the index register.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- NumOpsAdded = 2;
-
- return true;
-}
-
-static inline bool Thumb2ShiftOpcode(unsigned Opcode) {
- switch (Opcode) {
- default:
- return false;
- case ARM::t2MOVCClsl: case ARM::t2MOVCClsr:
- case ARM::t2MOVCCasr: case ARM::t2MOVCCror:
- case ARM::t2LSLri: case ARM::t2LSRri:
- case ARM::t2ASRri: case ARM::t2RORri:
- return true;
- }
-}
-
-// A6.3.11 Data-processing (shifted register)
-//
-// Two register operands (Rn=0b1111 no 1st operand reg): Rs Rm
-// Two register operands (Rs=0b1111 no dst operand reg): Rn Rm
-// Three register operands: Rs Rn Rm
-// Three register operands: (Rn=0b1111 Conditional Move) Rs Ro(TIED_TO) Rm
-//
-// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
-// register with shift forms: (Rm, ConstantShiftSpecifier).
-// Constant shift specifier: Imm = (ShOp | ShAmt<<3).
-//
-// There are special instructions, like t2MOVsra_flag and t2MOVsrl_flag, which
-// only require two register operands: Rd, Rm in ARM Reference Manual terms, and
-// nothing else, because the shift amount is already specified.
-// Similar case holds for t2MOVrx, t2ADDrr, ..., etc.
-static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- // Special case handling.
- if (Opcode == ARM::t2BR_JT) {
- assert(NumOps == 4
- && OpInfo[0].RegClass == ARM::GPRRegClassID
- && OpInfo[1].RegClass == ARM::GPRRegClassID
- && OpInfo[2].RegClass < 0
- && OpInfo[3].RegClass < 0
- && "Exactly 4 operands expect and first two as reg operands");
- // Only need to populate the src reg operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- MI.addOperand(MCOperand::CreateReg(0));
- MI.addOperand(MCOperand::CreateImm(0));
- MI.addOperand(MCOperand::CreateImm(0));
- NumOpsAdded = 4;
- return true;
- }
-
- OpIdx = 0;
-
- assert(NumOps >= 2
- && (OpInfo[0].RegClass == ARM::GPRRegClassID ||
- OpInfo[0].RegClass == ARM::rGPRRegClassID)
- && (OpInfo[1].RegClass == ARM::GPRRegClassID ||
- OpInfo[1].RegClass == ARM::rGPRRegClassID)
- && "Expect >= 2 operands and first two as reg operands");
-
- bool ThreeReg = (NumOps > 2 && (OpInfo[2].RegClass == ARM::GPRRegClassID ||
- OpInfo[2].RegClass == ARM::rGPRRegClassID));
- bool NoDstReg = (decodeRs(insn) == 0xF);
-
- // Build the register operands, followed by the constant shift specifier.
-
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, OpInfo[0].RegClass,
- NoDstReg ? decodeRn(insn) : decodeRs(insn))));
- ++OpIdx;
-
- if (ThreeReg) {
- int Idx;
- if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
- // Process tied_to operand constraint.
- MI.addOperand(MI.getOperand(Idx));
- ++OpIdx;
- } else if (!NoDstReg) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[1].RegClass,
- decodeRn(insn))));
- ++OpIdx;
- } else {
- DEBUG(errs() << "Thumb2 encoding error: d==15 for three-reg operands.\n");
- return false;
- }
- }
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- decodeRm(insn))));
- ++OpIdx;
-
- if (NumOps == OpIdx)
- return true;
-
- if (OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
- && !OpInfo[OpIdx].isOptionalDef()) {
-
- if (Thumb2ShiftOpcode(Opcode)) {
- unsigned Imm = getShiftAmtBits(insn);
- ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 5, 4));
- getImmShiftSE(ShOp, Imm);
- MI.addOperand(MCOperand::CreateImm(Imm));
- } else {
- // Build the constant shift specifier operand.
- unsigned bits2 = getShiftTypeBits(insn);
- unsigned imm5 = getShiftAmtBits(insn);
- ARM_AM::ShiftOpc ShOp = ARM_AM::no_shift;
- unsigned ShAmt = decodeImmShift(bits2, imm5, ShOp);
- MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShAmt)));
- }
- ++OpIdx;
- }
-
- return true;
-}
-
-// A6.3.1 Data-processing (modified immediate)
-//
-// Two register operands: Rs Rn ModImm
-// One register operands (Rs=0b1111 no explicit dest reg): Rn ModImm
-// One register operands (Rn=0b1111 no explicit src reg): Rs ModImm -
-// {t2MOVi, t2MVNi}
-//
-// ModImm = ThumbExpandImm(i:imm3:imm8)
-static bool DisassembleThumb2DPModImm(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- unsigned RdRegClassID = OpInfo[0].RegClass;
- assert(NumOps >= 2 && (RdRegClassID == ARM::GPRRegClassID ||
- RdRegClassID == ARM::rGPRRegClassID)
- && "Expect >= 2 operands and first one as reg operand");
-
- unsigned RnRegClassID = OpInfo[1].RegClass;
- bool TwoReg = (RnRegClassID == ARM::GPRRegClassID
- || RnRegClassID == ARM::rGPRRegClassID);
- bool NoDstReg = (decodeRs(insn) == 0xF);
-
- // Build the register operands, followed by the modified immediate.
-
- MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(B, RdRegClassID,
- NoDstReg ? decodeRn(insn) : decodeRs(insn))));
- ++OpIdx;
-
- if (TwoReg) {
- if (NoDstReg) {
- DEBUG(errs()<<"Thumb2 encoding error: d==15 for DPModImm 2-reg instr.\n");
- return false;
- }
- int Idx;
- if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
- // The reg operand is tied to the first reg operand.
- MI.addOperand(MI.getOperand(Idx));
- } else {
- // Add second reg operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID,
- decodeRn(insn))));
- }
- ++OpIdx;
- }
-
- // The modified immediate operand should come next.
- assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 &&
- !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()
- && "Pure imm operand expected");
-
- // i:imm3:imm8
- // A6.3.2 Modified immediate constants in Thumb instructions
- unsigned imm12 = getIImm3Imm8(insn);
- MI.addOperand(MCOperand::CreateImm(ThumbExpandImm(imm12)));
- ++OpIdx;
-
- return true;
-}
-
-static inline bool Thumb2SaturateOpcode(unsigned Opcode) {
- switch (Opcode) {
- case ARM::t2SSAT: case ARM::t2SSAT16:
- case ARM::t2USAT: case ARM::t2USAT16:
- return true;
- default:
- return false;
- }
-}
-
-/// DisassembleThumb2Sat - Disassemble Thumb2 saturate instructions:
-/// o t2SSAT, t2USAT: Rs sat_pos Rn shamt
-/// o t2SSAT16, t2USAT16: Rs sat_pos Rn
-static bool DisassembleThumb2Sat(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned &NumOpsAdded, BO B) {
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands
-
- // Disassemble the register def.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
- decodeRs(insn))));
-
- unsigned Pos = slice(insn, 4, 0);
- if (Opcode == ARM::t2SSAT || Opcode == ARM::t2SSAT16)
- Pos += 1;
- MI.addOperand(MCOperand::CreateImm(Pos));
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
- decodeRn(insn))));
-
- if (NumOpsAdded == 4) {
- ARM_AM::ShiftOpc Opc = (slice(insn, 21, 21) != 0 ?
- ARM_AM::asr : ARM_AM::lsl);
- // Inst{14-12:7-6} encodes the imm5 shift amount.
- unsigned ShAmt = slice(insn, 14, 12) << 2 | slice(insn, 7, 6);
- if (ShAmt == 0) {
- if (Opc == ARM_AM::asr)
- ShAmt = 32;
- else
- Opc = ARM_AM::no_shift;
- }
- MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(Opc, ShAmt)));
- }
- return true;
-}
-
-// A6.3.3 Data-processing (plain binary immediate)
-//
-// o t2ADDri12, t2SUBri12: Rs Rn imm12
-// o t2LEApcrel (ADR): Rs imm12
-// o t2BFC (BFC): Rs Ro(TIED_TO) bf_inv_mask_imm
-// o t2BFI (BFI): Rs Ro(TIED_TO) Rn bf_inv_mask_imm
-// o t2MOVi16: Rs imm16
-// o t2MOVTi16: Rs imm16
-// o t2SBFX (SBFX): Rs Rn lsb width
-// o t2UBFX (UBFX): Rs Rn lsb width
-// o t2BFI (BFI): Rs Rn lsb width
-static bool DisassembleThumb2DPBinImm(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- unsigned RdRegClassID = OpInfo[0].RegClass;
- assert(NumOps >= 2 && (RdRegClassID == ARM::GPRRegClassID ||
- RdRegClassID == ARM::rGPRRegClassID)
- && "Expect >= 2 operands and first one as reg operand");
-
- unsigned RnRegClassID = OpInfo[1].RegClass;
- bool TwoReg = (RnRegClassID == ARM::GPRRegClassID
- || RnRegClassID == ARM::rGPRRegClassID);
-
- // Build the register operand(s), followed by the immediate(s).
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RdRegClassID,
- decodeRs(insn))));
- ++OpIdx;
-
- if (TwoReg) {
- assert(NumOps >= 3 && "Expect >= 3 operands");
- int Idx;
- if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
- // Process tied_to operand constraint.
- MI.addOperand(MI.getOperand(Idx));
- } else {
- // Add src reg operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID,
- decodeRn(insn))));
- }
- ++OpIdx;
- }
-
- if (Opcode == ARM::t2BFI) {
- // Add val reg operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID,
- decodeRn(insn))));
- ++OpIdx;
- }
-
- assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
- && !OpInfo[OpIdx].isOptionalDef()
- && "Pure imm operand expected");
-
- // Pre-increment OpIdx.
- ++OpIdx;
-
- if (Opcode == ARM::t2ADDri12 || Opcode == ARM::t2SUBri12
- || Opcode == ARM::t2LEApcrel)
- MI.addOperand(MCOperand::CreateImm(getIImm3Imm8(insn)));
- else if (Opcode == ARM::t2MOVi16 || Opcode == ARM::t2MOVTi16) {
- if (!B->tryAddingSymbolicOperand(getImm16(insn), 4, MI))
- MI.addOperand(MCOperand::CreateImm(getImm16(insn)));
- } else if (Opcode == ARM::t2BFC || Opcode == ARM::t2BFI) {
- uint32_t mask = 0;
- if (getBitfieldInvMask(insn, mask))
- MI.addOperand(MCOperand::CreateImm(mask));
- else
- return false;
- } else {
- // Handle the case of: lsb width
- assert((Opcode == ARM::t2SBFX || Opcode == ARM::t2UBFX)
- && "Unexpected opcode");
- MI.addOperand(MCOperand::CreateImm(getLsb(insn)));
- MI.addOperand(MCOperand::CreateImm(getWidthMinus1(insn) + 1));
-
- ++OpIdx;
- }
-
- return true;
-}
-
-// A6.3.4 Table A6-15 Miscellaneous control instructions
-// A8.6.41 DMB
-// A8.6.42 DSB
-// A8.6.49 ISB
-static inline bool t2MiscCtrlInstr(uint32_t insn) {
- if (slice(insn, 31, 20) == 0xf3b && slice(insn, 15, 14) == 2 &&
- slice(insn, 12, 12) == 0)
- return true;
-
- return false;
-}
-
-// A6.3.4 Branches and miscellaneous control
-//
-// A8.6.16 B
-// Branches: t2B, t2Bcc -> imm operand
-//
-// Branches: t2TPsoft -> no operand
-//
-// A8.6.23 BL, BLX (immediate)
-// Branches (defined in ARMInstrThumb.td): tBLr9, tBLXi_r9 -> imm operand
-//
-// A8.6.26
-// t2BXJ -> Rn
-//
-// Miscellaneous control:
-// -> no operand (except pred-imm pred-ccr for CLREX, memory barrier variants)
-//
-// Hint: t2NOP, t2YIELD, t2WFE, t2WFI, t2SEV
-// -> no operand (except pred-imm pred-ccr)
-//
-// t2DBG -> imm4 = Inst{3-0}
-//
-// t2MRS/t2MRSsys -> Rs
-// t2MSR/t2MSRsys -> Rn mask=Inst{11-8}
-// t2SMC -> imm4 = Inst{19-16}
-static bool DisassembleThumb2BrMiscCtrl(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- if (NumOps == 0)
- return true;
-
- if (Opcode == ARM::t2DMB || Opcode == ARM::t2DSB) {
- // Inst{3-0} encodes the memory barrier option for the variants.
- unsigned opt = slice(insn, 3, 0);
- switch (opt) {
- case ARM_MB::SY: case ARM_MB::ST:
- case ARM_MB::ISH: case ARM_MB::ISHST:
- case ARM_MB::NSH: case ARM_MB::NSHST:
- case ARM_MB::OSH: case ARM_MB::OSHST:
- MI.addOperand(MCOperand::CreateImm(opt));
- NumOpsAdded = 1;
- return true;
- default:
- return false;
- }
- }
-
- if (t2MiscCtrlInstr(insn))
- return true;
-
- switch (Opcode) {
- case ARM::t2CLREX:
- case ARM::t2NOP:
- case ARM::t2YIELD:
- case ARM::t2WFE:
- case ARM::t2WFI:
- case ARM::t2SEV:
- return true;
- default:
- break;
- }
-
- // FIXME: To enable correct asm parsing and disasm of CPS we need 3 different
- // opcodes which match the same real instruction. This is needed since there's
- // no current handling of optional arguments. Fix here when a better handling
- // of optional arguments is implemented.
- if (Opcode == ARM::t2CPS3p) {
- MI.addOperand(MCOperand::CreateImm(slice(insn, 10, 9))); // imod
- MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 5))); // iflags
- MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode
- NumOpsAdded = 3;
- return true;
- }
- if (Opcode == ARM::t2CPS2p) {
- MI.addOperand(MCOperand::CreateImm(slice(insn, 10, 9))); // imod
- MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 5))); // iflags
- NumOpsAdded = 2;
- return true;
- }
- if (Opcode == ARM::t2CPS1p) {
- MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode
- NumOpsAdded = 1;
- return true;
- }
-
- // DBG has its option specified in Inst{3-0}.
- if (Opcode == ARM::t2DBG) {
- MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 0)));
- NumOpsAdded = 1;
- return true;
- }
-
- // MRS and MRSsys take one GPR reg Rs.
- if (Opcode == ARM::t2MRS || Opcode == ARM::t2MRSsys) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRs(insn))));
- NumOpsAdded = 1;
- return true;
- }
- // BXJ takes one GPR reg Rn.
- if (Opcode == ARM::t2BXJ) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- NumOpsAdded = 1;
- return true;
- }
- // MSR take a mask, followed by one GPR reg Rn. The mask contains the R Bit in
- // bit 4, and the special register fields in bits 3-0.
- if (Opcode == ARM::t2MSR) {
- MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 20) << 4 /* R Bit */ |
- slice(insn, 11, 8) /* Special Reg */));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- NumOpsAdded = 2;
- return true;
- }
- // SMC take imm4.
- if (Opcode == ARM::t2SMC) {
- MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 16)));
- NumOpsAdded = 1;
- return true;
- }
-
- // Some instructions have predicate operands first before the immediate.
- if (Opcode == ARM::tBLXi_r9 || Opcode == ARM::tBLr9) {
- // Handling the two predicate operands before the imm operand.
- if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
- NumOpsAdded += 2;
- else {
- DEBUG(errs() << "Expected predicate operands not found.\n");
- return false;
- }
- }
-
- // Add the imm operand.
- int Offset = 0;
-
- switch (Opcode) {
- default:
- assert(0 && "Unexpected opcode");
- return false;
- case ARM::t2B:
- Offset = decodeImm32_B_EncodingT4(insn);
- break;
- case ARM::t2Bcc:
- Offset = decodeImm32_B_EncodingT3(insn);
- break;
- case ARM::tBLr9:
- Offset = decodeImm32_BL(insn);
- break;
- case ARM::tBLXi_r9:
- Offset = decodeImm32_BLX(insn);
- break;
- }
-
- if (!B->tryAddingSymbolicOperand(Offset + B->getBuilderAddress() + 4, 4, MI))
- MI.addOperand(MCOperand::CreateImm(Offset));
-
- // This is an increment as some predicate operands may have been added first.
- NumOpsAdded += 1;
-
- return true;
-}
-
-static inline bool Thumb2PreloadOpcode(unsigned Opcode) {
- switch (Opcode) {
- default:
- return false;
- case ARM::t2PLDi12: case ARM::t2PLDi8:
- case ARM::t2PLDs:
- case ARM::t2PLDWi12: case ARM::t2PLDWi8:
- case ARM::t2PLDWs:
- case ARM::t2PLIi12: case ARM::t2PLIi8:
- case ARM::t2PLIs:
- return true;
- }
-}
-
-static bool DisassembleThumb2PreLoad(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- // Preload Data/Instruction requires either 2 or 3 operands.
- // t2PLDi12, t2PLDi8, t2PLDpci: Rn [+/-]imm12/imm8
- // t2PLDr: Rn Rm
- // t2PLDs: Rn Rm imm2=Inst{5-4}
- // Same pattern applies for t2PLDW* and t2PLI*.
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(NumOps >= 2 &&
- OpInfo[0].RegClass == ARM::GPRRegClassID &&
- "Expect >= 2 operands and first one as reg operand");
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRn(insn))));
- ++OpIdx;
-
- if (OpInfo[OpIdx].RegClass == ARM::rGPRRegClassID) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
- decodeRm(insn))));
- } else {
- assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
- && !OpInfo[OpIdx].isOptionalDef()
- && "Pure imm operand expected");
- int Offset = 0;
- if (Opcode == ARM::t2PLDi8 || Opcode == ARM::t2PLDWi8 ||
- Opcode == ARM::t2PLIi8) {
- // A8.6.117 Encoding T2: add = FALSE
- unsigned Imm8 = getImm8(insn);
- Offset = -1 * Imm8;
- } else {
- // The i12 forms. See, for example, A8.6.117 Encoding T1.
- // Note that currently t2PLDi12 also handles the previously named t2PLDpci
- // opcode, that's why we use decodeImm12(insn) which returns +/- imm12.
- Offset = decodeImm12(insn);
- }
- MI.addOperand(MCOperand::CreateImm(Offset));
- }
- ++OpIdx;
-
- if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 &&
- !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
- // Fills in the shift amount for t2PLDs, t2PLDWs, t2PLIs.
- MI.addOperand(MCOperand::CreateImm(slice(insn, 5, 4)));
- ++OpIdx;
- }
-
- return true;
-}
-
-static bool BadRegsThumb2LdSt(unsigned Opcode, uint32_t insn, bool Load,
- unsigned R0, unsigned R1, unsigned R2, bool UseRm, bool WB) {
-
- // Inst{22-21} encodes the data item transferred for load/store.
- // For single word, it is encoded as ob10.
- bool Word = (slice(insn, 22, 21) == 2);
- bool Half = (slice(insn, 22, 21) == 1);
- bool Byte = (slice(insn, 22, 21) == 0);
-
- if (UseRm && BadReg(R2)) {
- DEBUG(errs() << "if BadReg(m) then UNPREDICTABLE\n");
- return true;
- }
-
- if (Load) {
- if (!Word && R0 == 13) {
- DEBUG(errs() << "if t == 13 then UNPREDICTABLE\n");
- return true;
- }
- if (Byte) {
- if (WB && R0 == 15 && slice(insn, 10, 8) == 3) {
- // A8.6.78 LDRSB (immediate) Encoding T2 (errata markup 8.0)
- DEBUG(errs() << "if t == 15 && PUW == '011' then UNPREDICTABLE\n");
- return true;
- }
- }
- // A6.3.8 Load halfword, memory hints
- if (Half) {
- if (WB) {
- if (R0 == R1) {
- // A8.6.82 LDRSH (immediate) Encoding T2
- DEBUG(errs() << "if WB && n == t then UNPREDICTABLE\n");
- return true;
- }
- if (R0 == 15 && slice(insn, 10, 8) == 3) {
- // A8.6.82 LDRSH (immediate) Encoding T2 (errata markup 8.0)
- DEBUG(errs() << "if t == 15 && PUW == '011' then UNPREDICTABLE\n");
- return true;
- }
- } else {
- if (Opcode == ARM::t2LDRHi8 || Opcode == ARM::t2LDRSHi8) {
- if (R0 == 15 && slice(insn, 10, 8) == 4) {
- // A8.6.82 LDRSH (immediate) Encoding T2
- DEBUG(errs() << "if Rt == '1111' and PUW == '100' then SEE"
- << " \"Unallocated memory hints\"\n");
- return true;
- }
- } else {
- if (R0 == 15) {
- // A8.6.82 LDRSH (immediate) Encoding T1
- DEBUG(errs() << "if Rt == '1111' then SEE"
- << " \"Unallocated memory hints\"\n");
- return true;
- }
- }
- }
- }
- } else {
- if (WB && R0 == R1) {
- DEBUG(errs() << "if wback && n == t then UNPREDICTABLE\n");
- return true;
- }
- if ((WB && R0 == 15) || (!WB && R1 == 15)) {
- DEBUG(errs() << "if Rn == '1111' then UNDEFINED\n");
- return true;
- }
- if (Word) {
- if ((WB && R1 == 15) || (!WB && R0 == 15)) {
- DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n");
- return true;
- }
- } else {
- if ((WB && BadReg(R1)) || (!WB && BadReg(R0))) {
- DEBUG(errs() << "if BadReg(t) then UNPREDICTABLE\n");
- return true;
- }
- }
- }
- return false;
-}
-
-// A6.3.10 Store single data item
-// A6.3.9 Load byte, memory hints
-// A6.3.8 Load halfword, memory hints
-// A6.3.7 Load word
-//
-// For example,
-//
-// t2LDRi12: Rd Rn (+)imm12
-// t2LDRi8: Rd Rn (+/-)imm8 (+ if Inst{9} == 0b1)
-// t2LDRs: Rd Rn Rm ConstantShiftSpecifier (see also
-// DisassembleThumb2DPSoReg)
-// t2LDR_POST: Rd Rn Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
-// t2LDR_PRE: Rd Rn Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
-//
-// t2STRi12: Rd Rn (+)imm12
-// t2STRi8: Rd Rn (+/-)imm8 (+ if Inst{9} == 0b1)
-// t2STRs: Rd Rn Rm ConstantShiftSpecifier (see also
-// DisassembleThumb2DPSoReg)
-// t2STR_POST: Rn Rd Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
-// t2STR_PRE: Rn Rd Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
-//
-// Note that for indexed modes, the Rn(TIED_TO) operand needs to be populated
-// correctly, as LLVM AsmPrinter depends on it. For indexed stores, the first
-// operand is Rn; for all the other instructions, Rd is the first operand.
-//
-// Delegates to DisassembleThumb2PreLoad() for preload data/instruction.
-// Delegates to DisassembleThumb2Ldpci() for load * literal operations.
-static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- unsigned Rn = decodeRn(insn);
-
- if (Thumb2PreloadOpcode(Opcode))
- return DisassembleThumb2PreLoad(MI, Opcode, insn, NumOps, NumOpsAdded, B);
-
- // See, for example, A6.3.7 Load word: Table A6-18 Load word.
- if (Load && Rn == 15)
- return DisassembleThumb2Ldpci(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(NumOps >= 3 &&
- OpInfo[0].RegClass > 0 &&
- OpInfo[1].RegClass > 0 &&
- "Expect >= 3 operands and first two as reg operands");
-
- bool ThreeReg = (OpInfo[2].RegClass > 0);
- bool TIED_TO = ThreeReg && MCID.getOperandConstraint(2, MCOI::TIED_TO) != -1;
- bool Imm12 = !ThreeReg && slice(insn, 23, 23) == 1; // ARMInstrThumb2.td
-
- // Build the register operands, followed by the immediate.
- unsigned R0 = 0, R1 = 0, R2 = 0;
- unsigned Rd = decodeRd(insn);
- int Imm = 0;
-
- if (!Load && TIED_TO) {
- R0 = Rn;
- R1 = Rd;
- } else {
- R0 = Rd;
- R1 = Rn;
- }
- if (ThreeReg) {
- if (TIED_TO) {
- R2 = Rn;
- Imm = decodeImm8(insn);
- } else {
- R2 = decodeRm(insn);
- // See, for example, A8.6.64 LDRB (register).
- // And ARMAsmPrinter::printT2AddrModeSoRegOperand().
- // LSL is the default shift opc, and LLVM does not expect it to be encoded
- // as part of the immediate operand.
- // Imm = ARM_AM::getSORegOpc(ARM_AM::lsl, slice(insn, 5, 4));
- Imm = slice(insn, 5, 4);
- }
- } else {
- if (Imm12)
- Imm = getImm12(insn);
- else
- Imm = decodeImm8(insn);
- }
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- R0)));
- ++OpIdx;
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- R1)));
- ++OpIdx;
-
- if (ThreeReg) {
- // This could be an offset register or a TIED_TO register.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass,
- R2)));
- ++OpIdx;
- }
-
- if (BadRegsThumb2LdSt(Opcode, insn, Load, R0, R1, R2, ThreeReg & !TIED_TO,
- TIED_TO))
- return false;
-
- assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
- && !OpInfo[OpIdx].isOptionalDef()
- && "Pure imm operand expected");
-
- MI.addOperand(MCOperand::CreateImm(Imm));
- ++OpIdx;
-
- return true;
-}
-
-// A6.3.12 Data-processing (register)
-//
-// Two register operands [rotate]: Rs Rm [rotation(= (rotate:'000'))]
-// Three register operands only: Rs Rn Rm
-// Three register operands [rotate]: Rs Rn Rm [rotation(= (rotate:'000'))]
-//
-// Parallel addition and subtraction 32-bit Thumb instructions: Rs Rn Rm
-//
-// Miscellaneous operations: Rs [Rn] Rm
-static bool DisassembleThumb2DPReg(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCInstrDesc &MCID = ARMInsts[Opcode];
- const MCOperandInfo *OpInfo = MCID.OpInfo;
- unsigned &OpIdx = NumOpsAdded;
-
- OpIdx = 0;
-
- assert(NumOps >= 2 &&
- OpInfo[0].RegClass > 0 &&
- OpInfo[1].RegClass > 0 &&
- "Expect >= 2 operands and first two as reg operands");
-
- // Build the register operands, followed by the optional rotation amount.
-
- bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass > 0;
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- decodeRs(insn))));
- ++OpIdx;
-
- if (ThreeReg) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass,
- decodeRn(insn))));
- ++OpIdx;
- }
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
- decodeRm(insn))));
- ++OpIdx;
-
- if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
- && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
- // Add the rotation amount immediate.
- MI.addOperand(MCOperand::CreateImm(decodeRotate(insn)));
- ++OpIdx;
- }
-
- return true;
-}
-
-// A6.3.16 Multiply, multiply accumulate, and absolute difference
-//
-// t2MLA, t2MLS, t2SMMLA, t2SMMLS: Rs Rn Rm Ra=Inst{15-12}
-// t2MUL, t2SMMUL: Rs Rn Rm
-// t2SMLA[BB|BT|TB|TT|WB|WT]: Rs Rn Rm Ra=Inst{15-12}
-// t2SMUL[BB|BT|TB|TT|WB|WT]: Rs Rn Rm
-//
-// Dual halfword multiply: t2SMUAD[X], t2SMUSD[X], t2SMLAD[X], t2SMLSD[X]:
-// Rs Rn Rm Ra=Inst{15-12}
-//
-// Unsigned Sum of Absolute Differences [and Accumulate]
-// Rs Rn Rm [Ra=Inst{15-12}]
-static bool DisassembleThumb2Mul(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
-
- assert(NumOps >= 3 &&
- OpInfo[0].RegClass == ARM::rGPRRegClassID &&
- OpInfo[1].RegClass == ARM::rGPRRegClassID &&
- OpInfo[2].RegClass == ARM::rGPRRegClassID &&
- "Expect >= 3 operands and first three as reg operands");
-
- // Build the register operands.
-
- bool FourReg = NumOps > 3 && OpInfo[3].RegClass == ARM::rGPRRegClassID;
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
- decodeRs(insn))));
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
- decodeRn(insn))));
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
- decodeRm(insn))));
-
- if (FourReg)
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
- decodeRd(insn))));
-
- NumOpsAdded = FourReg ? 4 : 3;
-
- return true;
-}
-
-// A6.3.17 Long multiply, long multiply accumulate, and divide
-//
-// t2SMULL, t2UMULL, t2SMLAL, t2UMLAL, t2UMAAL: RdLo RdHi Rn Rm
-// where RdLo = Inst{15-12} and RdHi = Inst{11-8}
-//
-// Halfword multiple accumulate long: t2SMLAL<x><y>: RdLo RdHi Rn Rm
-// where RdLo = Inst{15-12} and RdHi = Inst{11-8}
-//
-// Dual halfword multiple: t2SMLALD[X], t2SMLSLD[X]: RdLo RdHi Rn Rm
-// where RdLo = Inst{15-12} and RdHi = Inst{11-8}
-//
-// Signed/Unsigned divide: t2SDIV, t2UDIV: Rs Rn Rm
-static bool DisassembleThumb2LongMul(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
-
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
-
- assert(NumOps >= 3 &&
- OpInfo[0].RegClass == ARM::rGPRRegClassID &&
- OpInfo[1].RegClass == ARM::rGPRRegClassID &&
- OpInfo[2].RegClass == ARM::rGPRRegClassID &&
- "Expect >= 3 operands and first three as reg operands");
-
- bool FourReg = NumOps > 3 && OpInfo[3].RegClass == ARM::rGPRRegClassID;
-
- // Build the register operands.
-
- if (FourReg)
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
- decodeRd(insn))));
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
- decodeRs(insn))));
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
- decodeRn(insn))));
-
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
- decodeRm(insn))));
-
- if (FourReg)
- NumOpsAdded = 4;
- else
- NumOpsAdded = 3;
-
- return true;
-}
-
-// See A6.3 32-bit Thumb instruction encoding for instruction classes
-// corresponding to (op1, op2, op).
-//
-// Table A6-9 32-bit Thumb instruction encoding
-// op1 op2 op Instruction class, see
-// --- ------- -- -----------------------------------------------------------
-// 01 00xx0xx - Load/store multiple on page A6-23
-// 00xx1xx - Load/store dual, load/store exclusive, table branch on
-// page A6-24
-// 01xxxxx - Data-processing (shifted register) on page A6-31
-// 1xxxxxx - Coprocessor instructions on page A6-40
-// 10 x0xxxxx 0 Data-processing (modified immediate) on page A6-15
-// x1xxxxx 0 Data-processing (plain binary immediate) on page A6-19
-// - 1 Branches and miscellaneous control on page A6-20
-// 11 000xxx0 - Store single data item on page A6-30
-// 001xxx0 - Advanced SIMD element or structure load/store instructions
-// on page A7-27
-// 00xx001 - Load byte, memory hints on page A6-28
-// 00xx011 - Load halfword, memory hints on page A6-26
-// 00xx101 - Load word on page A6-25
-// 00xx111 - UNDEFINED
-// 010xxxx - Data-processing (register) on page A6-33
-// 0110xxx - Multiply, multiply accumulate, and absolute difference on
-// page A6-38
-// 0111xxx - Long multiply, long multiply accumulate, and divide on
-// page A6-39
-// 1xxxxxx - Coprocessor instructions on page A6-40
-//
-static bool DisassembleThumb2(uint16_t op1, uint16_t op2, uint16_t op,
- MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps,
- unsigned &NumOpsAdded, BO B) {
-
- switch (op1) {
- case 1:
- if (slice(op2, 6, 5) == 0) {
- if (slice(op2, 2, 2) == 0) {
- // Load/store multiple.
- return DisassembleThumb2LdStMul(MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- }
-
- // Load/store dual, load/store exclusive, table branch, otherwise.
- assert(slice(op2, 2, 2) == 1 && "Thumb2 encoding error!");
- if ((ARM::t2LDREX <= Opcode && Opcode <= ARM::t2LDREXH) ||
- (ARM::t2STREX <= Opcode && Opcode <= ARM::t2STREXH)) {
- // Load/store exclusive.
- return DisassembleThumb2LdStEx(MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- }
- if (Opcode == ARM::t2LDRDi8 ||
- Opcode == ARM::t2LDRD_PRE || Opcode == ARM::t2LDRD_POST ||
- Opcode == ARM::t2STRDi8 ||
- Opcode == ARM::t2STRD_PRE || Opcode == ARM::t2STRD_POST) {
- // Load/store dual.
- return DisassembleThumb2LdStDual(MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- }
- if (Opcode == ARM::t2TBB || Opcode == ARM::t2TBH) {
- // Table branch.
- return DisassembleThumb2TB(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- }
- } else if (slice(op2, 6, 5) == 1) {
- // Data-processing (shifted register).
- return DisassembleThumb2DPSoReg(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- }
-
- // FIXME: A6.3.18 Coprocessor instructions
- // But see ThumbDisassembler::getInstruction().
-
- break;
- case 2:
- if (op == 0) {
- if (slice(op2, 5, 5) == 0)
- // Data-processing (modified immediate)
- return DisassembleThumb2DPModImm(MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- if (Thumb2SaturateOpcode(Opcode))
- return DisassembleThumb2Sat(MI, Opcode, insn, NumOpsAdded, B);
-
- // Data-processing (plain binary immediate)
- return DisassembleThumb2DPBinImm(MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- }
- // Branches and miscellaneous control on page A6-20.
- return DisassembleThumb2BrMiscCtrl(MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- case 3:
- switch (slice(op2, 6, 5)) {
- case 0:
- // Load/store instructions...
- if (slice(op2, 0, 0) == 0) {
- if (slice(op2, 4, 4) == 0) {
- // Store single data item on page A6-30
- return DisassembleThumb2LdSt(false, MI,Opcode,insn,NumOps,NumOpsAdded,
- B);
- } else {
- // FIXME: Advanced SIMD element or structure load/store instructions.
- // But see ThumbDisassembler::getInstruction().
- ;
- }
- } else {
- // Table A6-9 32-bit Thumb instruction encoding: Load byte|halfword|word
- return DisassembleThumb2LdSt(true, MI, Opcode, insn, NumOps,
- NumOpsAdded, B);
- }
- break;
- case 1:
- if (slice(op2, 4, 4) == 0) {
- // A6.3.12 Data-processing (register)
- return DisassembleThumb2DPReg(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- } else if (slice(op2, 3, 3) == 0) {
- // A6.3.16 Multiply, multiply accumulate, and absolute difference
- return DisassembleThumb2Mul(MI, Opcode, insn, NumOps, NumOpsAdded, B);
- } else {
- // A6.3.17 Long multiply, long multiply accumulate, and divide
- return DisassembleThumb2LongMul(MI, Opcode, insn, NumOps, NumOpsAdded,
- B);
- }
- break;
- default:
- // FIXME: A6.3.18 Coprocessor instructions
- // But see ThumbDisassembler::getInstruction().
- ;
- break;
- }
-
- break;
- default:
- assert(0 && "Thumb2 encoding error!");
- break;
- }
-
- return false;
-}
-
-static bool DisassembleThumbFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO Builder) {
-
- uint16_t HalfWord = slice(insn, 31, 16);
-
- if (HalfWord == 0) {
- // A6.2 16-bit Thumb instruction encoding
- // op = bits[15:10]
- uint16_t op = slice(insn, 15, 10);
- return DisassembleThumb1(op, MI, Opcode, insn, NumOps, NumOpsAdded,
- Builder);
- }
-
- unsigned bits15_11 = slice(HalfWord, 15, 11);
-
- // A6.1 Thumb instruction set encoding
- if (!(bits15_11 == 0x1D || bits15_11 == 0x1E || bits15_11 == 0x1F)) {
- assert("Bits[15:11] first halfword of Thumb2 instruction is out of range");
- return false;
- }
-
- // A6.3 32-bit Thumb instruction encoding
-
- uint16_t op1 = slice(HalfWord, 12, 11);
- uint16_t op2 = slice(HalfWord, 10, 4);
- uint16_t op = slice(insn, 15, 15);
-
- return DisassembleThumb2(op1, op2, op, MI, Opcode, insn, NumOps, NumOpsAdded,
- Builder);
-}
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
index 78d3e47..ccdac3e 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
@@ -12,9 +12,9 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
-#include "ARMBaseInfo.h"
#include "ARMInstPrinter.h"
-#include "ARMAddressingModes.h"
+#include "MCTargetDesc/ARMBaseInfo.h"
+#include "MCTargetDesc/ARMAddressingModes.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
@@ -25,6 +25,23 @@ using namespace llvm;
#define GET_INSTRUCTION_NAME
#include "ARMGenAsmWriter.inc"
+/// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
+///
+/// getSORegOffset returns an integer from 0-31, representing '32' as 0.
+static unsigned translateShiftImm(unsigned imm) {
+ if (imm == 0)
+ return 32;
+ return imm;
+}
+
+
+ARMInstPrinter::ARMInstPrinter(const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI) :
+ MCInstPrinter(MAI) {
+ // Initialize the set of available features.
+ setAvailableFeatures(STI.getFeatureBits());
+}
+
StringRef ARMInstPrinter::getOpcodeName(unsigned Opcode) const {
return getInstructionName(Opcode);
}
@@ -33,11 +50,12 @@ void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
OS << getRegisterName(RegNo);
}
-void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
+void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
+ StringRef Annot) {
unsigned Opcode = MI->getOpcode();
// Check for MOVs and print canonical forms, instead.
- if (Opcode == ARM::MOVs) {
+ if (Opcode == ARM::MOVsr) {
// FIXME: Thumb variants?
const MCOperand &Dst = MI->getOperand(0);
const MCOperand &MO1 = MI->getOperand(1);
@@ -51,20 +69,36 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
O << '\t' << getRegisterName(Dst.getReg())
<< ", " << getRegisterName(MO1.getReg());
- if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
- return;
+ O << ", " << getRegisterName(MO2.getReg());
+ assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
+ printAnnotation(O, Annot);
+ return;
+ }
- O << ", ";
+ if (Opcode == ARM::MOVsi) {
+ // FIXME: Thumb variants?
+ const MCOperand &Dst = MI->getOperand(0);
+ const MCOperand &MO1 = MI->getOperand(1);
+ const MCOperand &MO2 = MI->getOperand(2);
+
+ O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()));
+ printSBitModifierOperand(MI, 5, O);
+ printPredicateOperand(MI, 3, O);
- if (MO2.getReg()) {
- O << getRegisterName(MO2.getReg());
- assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
- } else {
- O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
+ O << '\t' << getRegisterName(Dst.getReg())
+ << ", " << getRegisterName(MO1.getReg());
+
+ if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx) {
+ printAnnotation(O, Annot);
+ return;
}
+
+ O << ", #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));
+ printAnnotation(O, Annot);
return;
}
+
// A8.6.123 PUSH
if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) &&
MI->getOperand(0).getReg() == ARM::SP) {
@@ -74,6 +108,15 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
O << ".w";
O << '\t';
printRegisterList(MI, 4, O);
+ printAnnotation(O, Annot);
+ return;
+ }
+ if (Opcode == ARM::STR_PRE_IMM && MI->getOperand(2).getReg() == ARM::SP &&
+ MI->getOperand(3).getImm() == -4) {
+ O << '\t' << "push";
+ printPredicateOperand(MI, 4, O);
+ O << "\t{" << getRegisterName(MI->getOperand(1).getReg()) << "}";
+ printAnnotation(O, Annot);
return;
}
@@ -86,8 +129,18 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
O << ".w";
O << '\t';
printRegisterList(MI, 4, O);
+ printAnnotation(O, Annot);
return;
}
+ if (Opcode == ARM::LDR_POST_IMM && MI->getOperand(2).getReg() == ARM::SP &&
+ MI->getOperand(4).getImm() == 4) {
+ O << '\t' << "pop";
+ printPredicateOperand(MI, 5, O);
+ O << "\t{" << getRegisterName(MI->getOperand(0).getReg()) << "}";
+ printAnnotation(O, Annot);
+ return;
+ }
+
// A8.6.355 VPUSH
if ((Opcode == ARM::VSTMSDB_UPD || Opcode == ARM::VSTMDDB_UPD) &&
@@ -96,6 +149,7 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
printPredicateOperand(MI, 2, O);
O << '\t';
printRegisterList(MI, 4, O);
+ printAnnotation(O, Annot);
return;
}
@@ -106,10 +160,40 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
printPredicateOperand(MI, 2, O);
O << '\t';
printRegisterList(MI, 4, O);
+ printAnnotation(O, Annot);
+ return;
+ }
+
+ if (Opcode == ARM::tLDMIA) {
+ bool Writeback = true;
+ unsigned BaseReg = MI->getOperand(0).getReg();
+ for (unsigned i = 3; i < MI->getNumOperands(); ++i) {
+ if (MI->getOperand(i).getReg() == BaseReg)
+ Writeback = false;
+ }
+
+ O << "\tldm";
+
+ printPredicateOperand(MI, 1, O);
+ O << '\t' << getRegisterName(BaseReg);
+ if (Writeback) O << "!";
+ O << ", ";
+ printRegisterList(MI, 3, O);
+ printAnnotation(O, Annot);
+ return;
+ }
+
+ // Thumb1 NOP
+ if (Opcode == ARM::tMOVr && MI->getOperand(0).getReg() == ARM::R8 &&
+ MI->getOperand(1).getReg() == ARM::R8) {
+ O << "\tnop";
+ printPredicateOperand(MI, 2, O);
+ printAnnotation(O, Annot);
return;
}
printInstruction(MI, O);
+ printAnnotation(O, Annot);
}
void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
@@ -122,16 +206,38 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
O << '#' << Op.getImm();
} else {
assert(Op.isExpr() && "unknown operand kind in printOperand");
- O << *Op.getExpr();
+ // If a symbolic branch target was added as a constant expression then print
+ // that address in hex.
+ const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr());
+ int64_t Address;
+ if (BranchTarget && BranchTarget->EvaluateAsAbsolute(Address)) {
+ O << "0x";
+ O.write_hex(Address);
+ }
+ else {
+ // Otherwise, just print the expression.
+ O << *Op.getExpr();
+ }
}
}
+void ARMInstPrinter::printT2LdrLabelOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ const MCOperand &MO1 = MI->getOperand(OpNum);
+ if (MO1.isExpr())
+ O << *MO1.getExpr();
+ else if (MO1.isImm())
+ O << "[pc, #" << MO1.getImm() << "]";
+ else
+ llvm_unreachable("Unknown LDR label operand?");
+}
+
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
// "Addressing Mode 1 - Data-processing operands" forms. This includes:
// REG 0 0 - e.g. R5
// REG REG 0,SH_OPC - e.g. R5, ROR R3
// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
-void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
+void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
const MCOperand &MO1 = MI->getOperand(OpNum);
const MCOperand &MO2 = MI->getOperand(OpNum+1);
@@ -144,14 +250,27 @@ void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
if (ShOpc == ARM_AM::rrx)
return;
- if (MO2.getReg()) {
- O << ' ' << getRegisterName(MO2.getReg());
- assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
- } else if (ShOpc != ARM_AM::rrx) {
- O << " #" << ARM_AM::getSORegOffset(MO3.getImm());
- }
+
+ O << ' ' << getRegisterName(MO2.getReg());
+ assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
+}
+
+void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ const MCOperand &MO1 = MI->getOperand(OpNum);
+ const MCOperand &MO2 = MI->getOperand(OpNum+1);
+
+ O << getRegisterName(MO1.getReg());
+
+ // Print the shift opc.
+ ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
+ O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
+ if (ShOpc == ARM_AM::rrx)
+ return;
+ O << " #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));
}
+
//===--------------------------------------------------------------------===//
// Addressing Mode #2
//===--------------------------------------------------------------------===//
@@ -209,6 +328,22 @@ void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,
<< " #" << ShImm;
}
+void ARMInstPrinter::printAddrModeTBB(const MCInst *MI, unsigned Op,
+ raw_ostream &O) {
+ const MCOperand &MO1 = MI->getOperand(Op);
+ const MCOperand &MO2 = MI->getOperand(Op+1);
+ O << "[" << getRegisterName(MO1.getReg()) << ", "
+ << getRegisterName(MO2.getReg()) << "]";
+}
+
+void ARMInstPrinter::printAddrModeTBH(const MCInst *MI, unsigned Op,
+ raw_ostream &O) {
+ const MCOperand &MO1 = MI->getOperand(Op);
+ const MCOperand &MO2 = MI->getOperand(Op+1);
+ O << "[" << getRegisterName(MO1.getReg()) << ", "
+ << getRegisterName(MO2.getReg()) << ", lsl #1]";
+}
+
void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
raw_ostream &O) {
const MCOperand &MO1 = MI->getOperand(Op);
@@ -284,7 +419,7 @@ void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
O << '[' << getRegisterName(MO1.getReg());
if (MO2.getReg()) {
- O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
+ O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
<< getRegisterName(MO2.getReg()) << ']';
return;
}
@@ -315,8 +450,8 @@ void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
const MCOperand &MO2 = MI->getOperand(OpNum+1);
if (MO1.getReg()) {
- O << (char)ARM_AM::getAM3Op(MO2.getImm())
- << getRegisterName(MO1.getReg());
+ O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
+ << getRegisterName(MO1.getReg());
return;
}
@@ -326,6 +461,31 @@ void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
<< ImmOffs;
}
+void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI,
+ unsigned OpNum,
+ raw_ostream &O) {
+ const MCOperand &MO = MI->getOperand(OpNum);
+ unsigned Imm = MO.getImm();
+ O << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff);
+}
+
+void ARMInstPrinter::printPostIdxRegOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ const MCOperand &MO1 = MI->getOperand(OpNum);
+ const MCOperand &MO2 = MI->getOperand(OpNum+1);
+
+ O << (MO2.getImm() ? "" : "-") << getRegisterName(MO1.getReg());
+}
+
+void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst *MI,
+ unsigned OpNum,
+ raw_ostream &O) {
+ const MCOperand &MO = MI->getOperand(OpNum);
+ unsigned Imm = MO.getImm();
+ O << '#' << ((Imm & 256) ? "" : "-") << ((Imm & 0xff) << 2);
+}
+
+
void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum)
@@ -345,7 +505,9 @@ void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
O << "[" << getRegisterName(MO1.getReg());
- if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
+ unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());
+ unsigned Op = ARM_AM::getAM5Op(MO2.getImm());
+ if (ImmOffs || Op == ARM_AM::sub) {
O << ", #"
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
<< ImmOffs * 4;
@@ -402,20 +564,31 @@ void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
unsigned ShiftOp = MI->getOperand(OpNum).getImm();
- ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
- switch (Opc) {
- case ARM_AM::no_shift:
+ bool isASR = (ShiftOp & (1 << 5)) != 0;
+ unsigned Amt = ShiftOp & 0x1f;
+ if (isASR)
+ O << ", asr #" << (Amt == 0 ? 32 : Amt);
+ else if (Amt)
+ O << ", lsl #" << Amt;
+}
+
+void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ unsigned Imm = MI->getOperand(OpNum).getImm();
+ if (Imm == 0)
return;
- case ARM_AM::lsl:
- O << ", lsl #";
- break;
- case ARM_AM::asr:
- O << ", asr #";
- break;
- default:
- assert(0 && "unexpected shift opcode for shift immediate operand");
- }
- O << ARM_AM::getSORegOffset(ShiftOp);
+ assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
+ O << ", lsl #" << Imm;
+}
+
+void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ unsigned Imm = MI->getOperand(OpNum).getImm();
+ // A shift amount of 32 is encoded as 0.
+ if (Imm == 0)
+ Imm = 32;
+ assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
+ O << ", asr #" << Imm;
}
void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
@@ -450,6 +623,9 @@ void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
for (int i=2; i >= 0; --i)
if (IFlags & (1 << i))
O << ARM_PROC::IFlagsToString(1 << i);
+
+ if (IFlags == 0)
+ O << "none";
}
void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
@@ -458,10 +634,43 @@ void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
unsigned SpecRegRBit = Op.getImm() >> 4;
unsigned Mask = Op.getImm() & 0xf;
+ if (getAvailableFeatures() & ARM::FeatureMClass) {
+ switch (Op.getImm()) {
+ default: assert(0 && "Unexpected mask value!");
+ case 0: O << "apsr"; return;
+ case 1: O << "iapsr"; return;
+ case 2: O << "eapsr"; return;
+ case 3: O << "xpsr"; return;
+ case 5: O << "ipsr"; return;
+ case 6: O << "epsr"; return;
+ case 7: O << "iepsr"; return;
+ case 8: O << "msp"; return;
+ case 9: O << "psp"; return;
+ case 16: O << "primask"; return;
+ case 17: O << "basepri"; return;
+ case 18: O << "basepri_max"; return;
+ case 19: O << "faultmask"; return;
+ case 20: O << "control"; return;
+ }
+ }
+
+ // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
+ // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
+ if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
+ O << "APSR_";
+ switch (Mask) {
+ default: assert(0);
+ case 4: O << "g"; return;
+ case 8: O << "nzcvq"; return;
+ case 12: O << "nzcvqg"; return;
+ }
+ llvm_unreachable("Unexpected mask value!");
+ }
+
if (SpecRegRBit)
- O << "spsr";
+ O << "SPSR";
else
- O << "cpsr";
+ O << "CPSR";
if (Mask) {
O << '_';
@@ -501,15 +710,20 @@ void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
}
void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
- raw_ostream &O) {
+ raw_ostream &O) {
O << "p" << MI->getOperand(OpNum).getImm();
}
void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
- raw_ostream &O) {
+ raw_ostream &O) {
O << "c" << MI->getOperand(OpNum).getImm();
}
+void ARMInstPrinter::printCoprocOptionImm(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ O << "{" << MI->getOperand(OpNum).getImm() << "}";
+}
+
void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
@@ -517,7 +731,13 @@ void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
- O << "#" << MI->getOperand(OpNum).getImm() * 4;
+ O << "#" << MI->getOperand(OpNum).getImm() * 4;
+}
+
+void ARMInstPrinter::printThumbSRImm(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ unsigned Imm = MI->getOperand(OpNum).getImm();
+ O << "#" << (Imm == 0 ? 32 : Imm);
}
void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
@@ -610,7 +830,7 @@ void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
if (ShOpc != ARM_AM::rrx)
- O << " #" << ARM_AM::getSORegOffset(MO2.getImm());
+ O << " #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));
}
void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
@@ -647,7 +867,9 @@ void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
int32_t OffImm = (int32_t)MO2.getImm();
// Don't print +0.
- if (OffImm < 0)
+ if (OffImm == INT32_MIN)
+ O << ", #-0";
+ else if (OffImm < 0)
O << ", #-" << -OffImm;
else if (OffImm > 0)
O << ", #" << OffImm;
@@ -671,6 +893,18 @@ void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
O << "]";
}
+void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(const MCInst *MI,
+ unsigned OpNum,
+ raw_ostream &O) {
+ const MCOperand &MO1 = MI->getOperand(OpNum);
+ const MCOperand &MO2 = MI->getOperand(OpNum+1);
+
+ O << "[" << getRegisterName(MO1.getReg());
+ if (MO2.getImm())
+ O << ", #" << MO2.getImm() * 4;
+ O << "]";
+}
+
void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
unsigned OpNum,
raw_ostream &O) {
@@ -678,9 +912,9 @@ void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
int32_t OffImm = (int32_t)MO1.getImm();
// Don't print +0.
if (OffImm < 0)
- O << "#-" << -OffImm;
- else if (OffImm > 0)
- O << "#" << OffImm;
+ O << ", #-" << -OffImm;
+ else
+ O << ", #" << OffImm;
}
void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
@@ -689,10 +923,13 @@ void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
const MCOperand &MO1 = MI->getOperand(OpNum);
int32_t OffImm = (int32_t)MO1.getImm() / 4;
// Don't print +0.
- if (OffImm < 0)
- O << "#-" << -OffImm * 4;
- else if (OffImm > 0)
- O << "#" << OffImm * 4;
+ if (OffImm != 0) {
+ O << ", ";
+ if (OffImm < 0)
+ O << "#-" << -OffImm * 4;
+ else if (OffImm > 0)
+ O << "#" << OffImm * 4;
+ }
}
void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
@@ -715,39 +952,10 @@ void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
O << "]";
}
-void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
- raw_ostream &O) {
- const MCOperand &MO = MI->getOperand(OpNum);
- O << '#';
- if (MO.isFPImm()) {
- O << (float)MO.getFPImm();
- } else {
- union {
- uint32_t I;
- float F;
- } FPUnion;
-
- FPUnion.I = MO.getImm();
- O << FPUnion.F;
- }
-}
-
-void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
- raw_ostream &O) {
+void ARMInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
const MCOperand &MO = MI->getOperand(OpNum);
- O << '#';
- if (MO.isFPImm()) {
- O << MO.getFPImm();
- } else {
- // We expect the binary encoding of a floating point number here.
- union {
- uint64_t I;
- double D;
- } FPUnion;
-
- FPUnion.I = MO.getImm();
- O << FPUnion.D;
- }
+ O << '#' << ARM_AM::getFPImmFloat(MO.getImm());
}
void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
@@ -757,3 +965,28 @@ void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
O << "#0x" << utohexstr(Val);
}
+
+void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ unsigned Imm = MI->getOperand(OpNum).getImm();
+ O << "#" << Imm + 1;
+}
+
+void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ unsigned Imm = MI->getOperand(OpNum).getImm();
+ if (Imm == 0)
+ return;
+ O << ", ror #";
+ switch (Imm) {
+ default: assert (0 && "illegal ror immediate!");
+ case 1: O << "8"; break;
+ case 2: O << "16"; break;
+ case 3: O << "24"; break;
+ }
+}
+
+void ARMInstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ O << "[" << MI->getOperand(OpNum).getImm() << "]";
+}
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
index d5f238b..5c2173f 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
@@ -15,6 +15,7 @@
#define ARMINSTPRINTER_H
#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
namespace llvm {
@@ -22,10 +23,9 @@ class MCOperand;
class ARMInstPrinter : public MCInstPrinter {
public:
- ARMInstPrinter(const MCAsmInfo &MAI)
- : MCInstPrinter(MAI) {}
+ ARMInstPrinter(const MCAsmInfo &MAI, const MCSubtargetInfo &STI);
- virtual void printInst(const MCInst *MI, raw_ostream &O);
+ virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
virtual StringRef getOpcodeName(unsigned Opcode) const;
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
@@ -38,8 +38,11 @@ public:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
- void printSORegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printSORegRegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printSORegImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printAddrModeTBB(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printAddrModeTBH(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAddrMode2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAM2PostIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum,
@@ -48,11 +51,15 @@ public:
raw_ostream &O);
void printAddrMode3Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
- void printAM3PostIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O);
- void printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum,
- raw_ostream &O);
void printAddrMode3OffsetOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O);
+ void printAM3PostIndexOp(const MCInst *MI, unsigned Op, raw_ostream &O);
+ void printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,raw_ostream &O);
+ void printPostIdxImm8Operand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O);
+ void printPostIdxRegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printPostIdxImm8s4Operand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O);
void printLdStmModeOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAddrMode5Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
@@ -65,8 +72,11 @@ public:
raw_ostream &O);
void printMemBOption(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printShiftImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printThumbSRImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printThumbITMask(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O);
@@ -88,6 +98,8 @@ public:
raw_ostream &O);
void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum,
raw_ostream &O);
+ void printT2AddrModeImm0_1020s4Operand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O);
void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O);
void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum,
@@ -108,11 +120,15 @@ public:
void printNoHashImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printPImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printCImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
- void printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
- void printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printCoprocOptionImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printFPImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printNEONModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printImmPlusOneOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printRotImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printPCLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printT2LdrLabelOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printVectorIndex(const MCInst *MI, unsigned OpNum, raw_ostream &O);
};
} // end namespace llvm
diff --git a/lib/Target/ARM/InstPrinter/CMakeLists.txt b/lib/Target/ARM/InstPrinter/CMakeLists.txt
index 18645c0..fa0b495 100644
--- a/lib/Target/ARM/InstPrinter/CMakeLists.txt
+++ b/lib/Target/ARM/InstPrinter/CMakeLists.txt
@@ -3,4 +3,10 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/
add_llvm_library(LLVMARMAsmPrinter
ARMInstPrinter.cpp
)
-add_dependencies(LLVMARMAsmPrinter ARMCodeGenTable_gen)
+
+add_dependencies(LLVMARMAsmPrinter ARMCommonTableGen)
+
+add_llvm_library_dependencies(LLVMARMAsmPrinter
+ LLVMMC
+ LLVMSupport
+ )
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h b/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h
new file mode 100644
index 0000000..9982fa6
--- /dev/null
+++ b/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h
@@ -0,0 +1,667 @@
+//===- ARMAddressingModes.h - ARM Addressing Modes --------------*- 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 ARM addressing mode implementation stuff.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_ARM_ARMADDRESSINGMODES_H
+#define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+
+namespace llvm {
+
+/// ARM_AM - ARM Addressing Mode Stuff
+namespace ARM_AM {
+ enum ShiftOpc {
+ no_shift = 0,
+ asr,
+ lsl,
+ lsr,
+ ror,
+ rrx
+ };
+
+ enum AddrOpc {
+ sub = 0,
+ add
+ };
+
+ static inline const char *getAddrOpcStr(AddrOpc Op) {
+ return Op == sub ? "-" : "";
+ }
+
+ static inline const char *getShiftOpcStr(ShiftOpc Op) {
+ switch (Op) {
+ default: assert(0 && "Unknown shift opc!");
+ case ARM_AM::asr: return "asr";
+ case ARM_AM::lsl: return "lsl";
+ case ARM_AM::lsr: return "lsr";
+ case ARM_AM::ror: return "ror";
+ case ARM_AM::rrx: return "rrx";
+ }
+ }
+
+ static inline unsigned getShiftOpcEncoding(ShiftOpc Op) {
+ switch (Op) {
+ default: assert(0 && "Unknown shift opc!");
+ case ARM_AM::asr: return 2;
+ case ARM_AM::lsl: return 0;
+ case ARM_AM::lsr: return 1;
+ case ARM_AM::ror: return 3;
+ }
+ }
+
+ enum AMSubMode {
+ bad_am_submode = 0,
+ ia,
+ ib,
+ da,
+ db
+ };
+
+ static inline const char *getAMSubModeStr(AMSubMode Mode) {
+ switch (Mode) {
+ default: assert(0 && "Unknown addressing sub-mode!");
+ case ARM_AM::ia: return "ia";
+ case ARM_AM::ib: return "ib";
+ case ARM_AM::da: return "da";
+ case ARM_AM::db: return "db";
+ }
+ }
+
+ /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits.
+ ///
+ static inline unsigned rotr32(unsigned Val, unsigned Amt) {
+ assert(Amt < 32 && "Invalid rotate amount");
+ return (Val >> Amt) | (Val << ((32-Amt)&31));
+ }
+
+ /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits.
+ ///
+ static inline unsigned rotl32(unsigned Val, unsigned Amt) {
+ assert(Amt < 32 && "Invalid rotate amount");
+ return (Val << Amt) | (Val >> ((32-Amt)&31));
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Addressing Mode #1: shift_operand with registers
+ //===--------------------------------------------------------------------===//
+ //
+ // This 'addressing mode' is used for arithmetic instructions. It can
+ // represent things like:
+ // reg
+ // reg [asr|lsl|lsr|ror|rrx] reg
+ // reg [asr|lsl|lsr|ror|rrx] imm
+ //
+ // This is stored three operands [rega, regb, opc]. The first is the base
+ // reg, the second is the shift amount (or reg0 if not present or imm). The
+ // third operand encodes the shift opcode and the imm if a reg isn't present.
+ //
+ static inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) {
+ return ShOp | (Imm << 3);
+ }
+ static inline unsigned getSORegOffset(unsigned Op) {
+ return Op >> 3;
+ }
+ static inline ShiftOpc getSORegShOp(unsigned Op) {
+ return (ShiftOpc)(Op & 7);
+ }
+
+ /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return
+ /// the 8-bit imm value.
+ static inline unsigned getSOImmValImm(unsigned Imm) {
+ return Imm & 0xFF;
+ }
+ /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return
+ /// the rotate amount.
+ static inline unsigned getSOImmValRot(unsigned Imm) {
+ return (Imm >> 8) * 2;
+ }
+
+ /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand,
+ /// computing the rotate amount to use. If this immediate value cannot be
+ /// handled with a single shifter-op, determine a good rotate amount that will
+ /// take a maximal chunk of bits out of the immediate.
+ static inline unsigned getSOImmValRotate(unsigned Imm) {
+ // 8-bit (or less) immediates are trivially shifter_operands with a rotate
+ // of zero.
+ if ((Imm & ~255U) == 0) return 0;
+
+ // Use CTZ to compute the rotate amount.
+ unsigned TZ = CountTrailingZeros_32(Imm);
+
+ // Rotate amount must be even. Something like 0x200 must be rotated 8 bits,
+ // not 9.
+ unsigned RotAmt = TZ & ~1;
+
+ // If we can handle this spread, return it.
+ if ((rotr32(Imm, RotAmt) & ~255U) == 0)
+ return (32-RotAmt)&31; // HW rotates right, not left.
+
+ // For values like 0xF000000F, we should ignore the low 6 bits, then
+ // retry the hunt.
+ if (Imm & 63U) {
+ unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U);
+ unsigned RotAmt2 = TZ2 & ~1;
+ if ((rotr32(Imm, RotAmt2) & ~255U) == 0)
+ return (32-RotAmt2)&31; // HW rotates right, not left.
+ }
+
+ // Otherwise, we have no way to cover this span of bits with a single
+ // shifter_op immediate. Return a chunk of bits that will be useful to
+ // handle.
+ return (32-RotAmt)&31; // HW rotates right, not left.
+ }
+
+ /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit
+ /// into an shifter_operand immediate operand, return the 12-bit encoding for
+ /// it. If not, return -1.
+ static inline int getSOImmVal(unsigned Arg) {
+ // 8-bit (or less) immediates are trivially shifter_operands with a rotate
+ // of zero.
+ if ((Arg & ~255U) == 0) return Arg;
+
+ unsigned RotAmt = getSOImmValRotate(Arg);
+
+ // If this cannot be handled with a single shifter_op, bail out.
+ if (rotr32(~255U, RotAmt) & Arg)
+ return -1;
+
+ // Encode this correctly.
+ return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8);
+ }
+
+ /// isSOImmTwoPartVal - Return true if the specified value can be obtained by
+ /// or'ing together two SOImmVal's.
+ static inline bool isSOImmTwoPartVal(unsigned V) {
+ // If this can be handled with a single shifter_op, bail out.
+ V = rotr32(~255U, getSOImmValRotate(V)) & V;
+ if (V == 0)
+ return false;
+
+ // If this can be handled with two shifter_op's, accept.
+ V = rotr32(~255U, getSOImmValRotate(V)) & V;
+ return V == 0;
+ }
+
+ /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal,
+ /// return the first chunk of it.
+ static inline unsigned getSOImmTwoPartFirst(unsigned V) {
+ return rotr32(255U, getSOImmValRotate(V)) & V;
+ }
+
+ /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal,
+ /// return the second chunk of it.
+ static inline unsigned getSOImmTwoPartSecond(unsigned V) {
+ // Mask out the first hunk.
+ V = rotr32(~255U, getSOImmValRotate(V)) & V;
+
+ // Take what's left.
+ assert(V == (rotr32(255U, getSOImmValRotate(V)) & V));
+ return V;
+ }
+
+ /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed
+ /// by a left shift. Returns the shift amount to use.
+ static inline unsigned getThumbImmValShift(unsigned Imm) {
+ // 8-bit (or less) immediates are trivially immediate operand with a shift
+ // of zero.
+ if ((Imm & ~255U) == 0) return 0;
+
+ // Use CTZ to compute the shift amount.
+ return CountTrailingZeros_32(Imm);
+ }
+
+ /// isThumbImmShiftedVal - Return true if the specified value can be obtained
+ /// by left shifting a 8-bit immediate.
+ static inline bool isThumbImmShiftedVal(unsigned V) {
+ // If this can be handled with
+ V = (~255U << getThumbImmValShift(V)) & V;
+ return V == 0;
+ }
+
+ /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed
+ /// by a left shift. Returns the shift amount to use.
+ static inline unsigned getThumbImm16ValShift(unsigned Imm) {
+ // 16-bit (or less) immediates are trivially immediate operand with a shift
+ // of zero.
+ if ((Imm & ~65535U) == 0) return 0;
+
+ // Use CTZ to compute the shift amount.
+ return CountTrailingZeros_32(Imm);
+ }
+
+ /// isThumbImm16ShiftedVal - Return true if the specified value can be
+ /// obtained by left shifting a 16-bit immediate.
+ static inline bool isThumbImm16ShiftedVal(unsigned V) {
+ // If this can be handled with
+ V = (~65535U << getThumbImm16ValShift(V)) & V;
+ return V == 0;
+ }
+
+ /// getThumbImmNonShiftedVal - If V is a value that satisfies
+ /// isThumbImmShiftedVal, return the non-shiftd value.
+ static inline unsigned getThumbImmNonShiftedVal(unsigned V) {
+ return V >> getThumbImmValShift(V);
+ }
+
+
+ /// getT2SOImmValSplat - Return the 12-bit encoded representation
+ /// if the specified value can be obtained by splatting the low 8 bits
+ /// into every other byte or every byte of a 32-bit value. i.e.,
+ /// 00000000 00000000 00000000 abcdefgh control = 0
+ /// 00000000 abcdefgh 00000000 abcdefgh control = 1
+ /// abcdefgh 00000000 abcdefgh 00000000 control = 2
+ /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3
+ /// Return -1 if none of the above apply.
+ /// See ARM Reference Manual A6.3.2.
+ static inline int getT2SOImmValSplatVal(unsigned V) {
+ unsigned u, Vs, Imm;
+ // control = 0
+ if ((V & 0xffffff00) == 0)
+ return V;
+
+ // If the value is zeroes in the first byte, just shift those off
+ Vs = ((V & 0xff) == 0) ? V >> 8 : V;
+ // Any passing value only has 8 bits of payload, splatted across the word
+ Imm = Vs & 0xff;
+ // Likewise, any passing values have the payload splatted into the 3rd byte
+ u = Imm | (Imm << 16);
+
+ // control = 1 or 2
+ if (Vs == u)
+ return (((Vs == V) ? 1 : 2) << 8) | Imm;
+
+ // control = 3
+ if (Vs == (u | (u << 8)))
+ return (3 << 8) | Imm;
+
+ return -1;
+ }
+
+ /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the
+ /// specified value is a rotated 8-bit value. Return -1 if no rotation
+ /// encoding is possible.
+ /// See ARM Reference Manual A6.3.2.
+ static inline int getT2SOImmValRotateVal(unsigned V) {
+ unsigned RotAmt = CountLeadingZeros_32(V);
+ if (RotAmt >= 24)
+ return -1;
+
+ // If 'Arg' can be handled with a single shifter_op return the value.
+ if ((rotr32(0xff000000U, RotAmt) & V) == V)
+ return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7);
+
+ return -1;
+ }
+
+ /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit
+ /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit
+ /// encoding for it. If not, return -1.
+ /// See ARM Reference Manual A6.3.2.
+ static inline int getT2SOImmVal(unsigned Arg) {
+ // If 'Arg' is an 8-bit splat, then get the encoded value.
+ int Splat = getT2SOImmValSplatVal(Arg);
+ if (Splat != -1)
+ return Splat;
+
+ // If 'Arg' can be handled with a single shifter_op return the value.
+ int Rot = getT2SOImmValRotateVal(Arg);
+ if (Rot != -1)
+ return Rot;
+
+ return -1;
+ }
+
+ static inline unsigned getT2SOImmValRotate(unsigned V) {
+ if ((V & ~255U) == 0) return 0;
+ // Use CTZ to compute the rotate amount.
+ unsigned RotAmt = CountTrailingZeros_32(V);
+ return (32 - RotAmt) & 31;
+ }
+
+ static inline bool isT2SOImmTwoPartVal (unsigned Imm) {
+ unsigned V = Imm;
+ // Passing values can be any combination of splat values and shifter
+ // values. If this can be handled with a single shifter or splat, bail
+ // out. Those should be handled directly, not with a two-part val.
+ if (getT2SOImmValSplatVal(V) != -1)
+ return false;
+ V = rotr32 (~255U, getT2SOImmValRotate(V)) & V;
+ if (V == 0)
+ return false;
+
+ // If this can be handled as an immediate, accept.
+ if (getT2SOImmVal(V) != -1) return true;
+
+ // Likewise, try masking out a splat value first.
+ V = Imm;
+ if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1)
+ V &= ~0xff00ff00U;
+ else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1)
+ V &= ~0x00ff00ffU;
+ // If what's left can be handled as an immediate, accept.
+ if (getT2SOImmVal(V) != -1) return true;
+
+ // Otherwise, do not accept.
+ return false;
+ }
+
+ static inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) {
+ assert (isT2SOImmTwoPartVal(Imm) &&
+ "Immedate cannot be encoded as two part immediate!");
+ // Try a shifter operand as one part
+ unsigned V = rotr32 (~255, getT2SOImmValRotate(Imm)) & Imm;
+ // If the rest is encodable as an immediate, then return it.
+ if (getT2SOImmVal(V) != -1) return V;
+
+ // Try masking out a splat value first.
+ if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1)
+ return Imm & 0xff00ff00U;
+
+ // The other splat is all that's left as an option.
+ assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1);
+ return Imm & 0x00ff00ffU;
+ }
+
+ static inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) {
+ // Mask out the first hunk
+ Imm ^= getT2SOImmTwoPartFirst(Imm);
+ // Return what's left
+ assert (getT2SOImmVal(Imm) != -1 &&
+ "Unable to encode second part of T2 two part SO immediate");
+ return Imm;
+ }
+
+
+ //===--------------------------------------------------------------------===//
+ // Addressing Mode #2
+ //===--------------------------------------------------------------------===//
+ //
+ // This is used for most simple load/store instructions.
+ //
+ // addrmode2 := reg +/- reg shop imm
+ // addrmode2 := reg +/- imm12
+ //
+ // The first operand is always a Reg. The second operand is a reg if in
+ // reg/reg form, otherwise it's reg#0. The third field encodes the operation
+ // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The
+ // fourth operand 16-17 encodes the index mode.
+ //
+ // If this addressing mode is a frame index (before prolog/epilog insertion
+ // and code rewriting), this operand will have the form: FI#, reg0, <offs>
+ // with no shift amount for the frame offset.
+ //
+ static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO,
+ unsigned IdxMode = 0) {
+ assert(Imm12 < (1 << 12) && "Imm too large!");
+ bool isSub = Opc == sub;
+ return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ;
+ }
+ static inline unsigned getAM2Offset(unsigned AM2Opc) {
+ return AM2Opc & ((1 << 12)-1);
+ }
+ static inline AddrOpc getAM2Op(unsigned AM2Opc) {
+ return ((AM2Opc >> 12) & 1) ? sub : add;
+ }
+ static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) {
+ return (ShiftOpc)((AM2Opc >> 13) & 7);
+ }
+ static inline unsigned getAM2IdxMode(unsigned AM2Opc) {
+ return (AM2Opc >> 16);
+ }
+
+
+ //===--------------------------------------------------------------------===//
+ // Addressing Mode #3
+ //===--------------------------------------------------------------------===//
+ //
+ // This is used for sign-extending loads, and load/store-pair instructions.
+ //
+ // addrmode3 := reg +/- reg
+ // addrmode3 := reg +/- imm8
+ //
+ // The first operand is always a Reg. The second operand is a reg if in
+ // reg/reg form, otherwise it's reg#0. The third field encodes the operation
+ // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the
+ // index mode.
+
+ /// getAM3Opc - This function encodes the addrmode3 opc field.
+ static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset,
+ unsigned IdxMode = 0) {
+ bool isSub = Opc == sub;
+ return ((int)isSub << 8) | Offset | (IdxMode << 9);
+ }
+ static inline unsigned char getAM3Offset(unsigned AM3Opc) {
+ return AM3Opc & 0xFF;
+ }
+ static inline AddrOpc getAM3Op(unsigned AM3Opc) {
+ return ((AM3Opc >> 8) & 1) ? sub : add;
+ }
+ static inline unsigned getAM3IdxMode(unsigned AM3Opc) {
+ return (AM3Opc >> 9);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Addressing Mode #4
+ //===--------------------------------------------------------------------===//
+ //
+ // This is used for load / store multiple instructions.
+ //
+ // addrmode4 := reg, <mode>
+ //
+ // The four modes are:
+ // IA - Increment after
+ // IB - Increment before
+ // DA - Decrement after
+ // DB - Decrement before
+ // For VFP instructions, only the IA and DB modes are valid.
+
+ static inline AMSubMode getAM4SubMode(unsigned Mode) {
+ return (AMSubMode)(Mode & 0x7);
+ }
+
+ static inline unsigned getAM4ModeImm(AMSubMode SubMode) {
+ return (int)SubMode;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Addressing Mode #5
+ //===--------------------------------------------------------------------===//
+ //
+ // This is used for coprocessor instructions, such as FP load/stores.
+ //
+ // addrmode5 := reg +/- imm8*4
+ //
+ // The first operand is always a Reg. The second operand encodes the
+ // operation in bit 8 and the immediate in bits 0-7.
+
+ /// getAM5Opc - This function encodes the addrmode5 opc field.
+ static inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) {
+ bool isSub = Opc == sub;
+ return ((int)isSub << 8) | Offset;
+ }
+ static inline unsigned char getAM5Offset(unsigned AM5Opc) {
+ return AM5Opc & 0xFF;
+ }
+ static inline AddrOpc getAM5Op(unsigned AM5Opc) {
+ return ((AM5Opc >> 8) & 1) ? sub : add;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Addressing Mode #6
+ //===--------------------------------------------------------------------===//
+ //
+ // This is used for NEON load / store instructions.
+ //
+ // addrmode6 := reg with optional alignment
+ //
+ // This is stored in two operands [regaddr, align]. The first is the
+ // address register. The second operand is the value of the alignment
+ // specifier in bytes or zero if no explicit alignment.
+ // Valid alignments depend on the specific instruction.
+
+ //===--------------------------------------------------------------------===//
+ // NEON Modified Immediates
+ //===--------------------------------------------------------------------===//
+ //
+ // Several NEON instructions (e.g., VMOV) take a "modified immediate"
+ // vector operand, where a small immediate encoded in the instruction
+ // specifies a full NEON vector value. These modified immediates are
+ // represented here as encoded integers. The low 8 bits hold the immediate
+ // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold
+ // the "Cmode" field of the instruction. The interfaces below treat the
+ // Op and Cmode values as a single 5-bit value.
+
+ static inline unsigned createNEONModImm(unsigned OpCmode, unsigned Val) {
+ return (OpCmode << 8) | Val;
+ }
+ static inline unsigned getNEONModImmOpCmode(unsigned ModImm) {
+ return (ModImm >> 8) & 0x1f;
+ }
+ static inline unsigned getNEONModImmVal(unsigned ModImm) {
+ return ModImm & 0xff;
+ }
+
+ /// decodeNEONModImm - Decode a NEON modified immediate value into the
+ /// element value and the element size in bits. (If the element size is
+ /// smaller than the vector, it is splatted into all the elements.)
+ static inline uint64_t decodeNEONModImm(unsigned ModImm, unsigned &EltBits) {
+ unsigned OpCmode = getNEONModImmOpCmode(ModImm);
+ unsigned Imm8 = getNEONModImmVal(ModImm);
+ uint64_t Val = 0;
+
+ if (OpCmode == 0xe) {
+ // 8-bit vector elements
+ Val = Imm8;
+ EltBits = 8;
+ } else if ((OpCmode & 0xc) == 0x8) {
+ // 16-bit vector elements
+ unsigned ByteNum = (OpCmode & 0x6) >> 1;
+ Val = Imm8 << (8 * ByteNum);
+ EltBits = 16;
+ } else if ((OpCmode & 0x8) == 0) {
+ // 32-bit vector elements, zero with one byte set
+ unsigned ByteNum = (OpCmode & 0x6) >> 1;
+ Val = Imm8 << (8 * ByteNum);
+ EltBits = 32;
+ } else if ((OpCmode & 0xe) == 0xc) {
+ // 32-bit vector elements, one byte with low bits set
+ unsigned ByteNum = 1 + (OpCmode & 0x1);
+ Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum)));
+ EltBits = 32;
+ } else if (OpCmode == 0x1e) {
+ // 64-bit vector elements
+ for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) {
+ if ((ModImm >> ByteNum) & 1)
+ Val |= (uint64_t)0xff << (8 * ByteNum);
+ }
+ EltBits = 64;
+ } else {
+ assert(false && "Unsupported NEON immediate");
+ }
+ return Val;
+ }
+
+ AMSubMode getLoadStoreMultipleSubMode(int Opcode);
+
+ //===--------------------------------------------------------------------===//
+ // Floating-point Immediates
+ //
+ static inline float getFPImmFloat(unsigned Imm) {
+ // We expect an 8-bit binary encoding of a floating-point number here.
+ union {
+ uint32_t I;
+ float F;
+ } FPUnion;
+
+ uint8_t Sign = (Imm >> 7) & 0x1;
+ uint8_t Exp = (Imm >> 4) & 0x7;
+ uint8_t Mantissa = Imm & 0xf;
+
+ // 8-bit FP iEEEE Float Encoding
+ // abcd efgh aBbbbbbc defgh000 00000000 00000000
+ //
+ // where B = NOT(b);
+
+ FPUnion.I = 0;
+ FPUnion.I |= Sign << 31;
+ FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
+ FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
+ FPUnion.I |= (Exp & 0x3) << 23;
+ FPUnion.I |= Mantissa << 19;
+ return FPUnion.F;
+ }
+
+ /// getFP32Imm - Return an 8-bit floating-point version of the 32-bit
+ /// floating-point value. If the value cannot be represented as an 8-bit
+ /// floating-point value, then return -1.
+ static inline int getFP32Imm(const APInt &Imm) {
+ 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;
+ }
+
+ static inline int getFP32Imm(const APFloat &FPImm) {
+ return getFP32Imm(FPImm.bitcastToAPInt());
+ }
+
+ /// getFP64Imm - Return an 8-bit floating-point version of the 64-bit
+ /// floating-point value. If the value cannot be represented as an 8-bit
+ /// floating-point value, then return -1.
+ static inline int getFP64Imm(const APInt &Imm) {
+ 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() & 0xfffffffffffffULL;
+
+ // We can handle 4 bits of mantissa.
+ // mantissa = (16+UInt(e:f:g:h))/16.
+ if (Mantissa & 0xffffffffffffULL)
+ 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;
+ }
+
+ static inline int getFP64Imm(const APFloat &FPImm) {
+ return getFP64Imm(FPImm.bitcastToAPInt());
+ }
+
+} // end namespace ARM_AM
+} // end namespace llvm
+
+#endif
+
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
new file mode 100644
index 0000000..c31c5e6
--- /dev/null
+++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -0,0 +1,531 @@
+//===-- ARMAsmBackend.cpp - ARM Assembler Backend -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/ARMMCTargetDesc.h"
+#include "MCTargetDesc/ARMBaseInfo.h"
+#include "MCTargetDesc/ARMFixupKinds.h"
+#include "MCTargetDesc/ARMAddressingModes.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCMachObjectWriter.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Object/MachOFormat.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+namespace {
+class ARMELFObjectWriter : public MCELFObjectTargetWriter {
+public:
+ ARMELFObjectWriter(Triple::OSType OSType)
+ : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSType, ELF::EM_ARM,
+ /*HasRelocationAddend*/ false) {}
+};
+
+class ARMAsmBackend : public MCAsmBackend {
+ const MCSubtargetInfo* STI;
+ bool isThumbMode; // Currently emitting Thumb code.
+public:
+ ARMAsmBackend(const Target &T, const StringRef TT)
+ : MCAsmBackend(), STI(ARM_MC::createARMMCSubtargetInfo(TT, "", "")),
+ isThumbMode(TT.startswith("thumb")) {}
+
+ ~ARMAsmBackend() {
+ delete STI;
+ }
+
+ unsigned getNumFixupKinds() const { return ARM::NumTargetFixupKinds; }
+
+ bool hasNOP() const {
+ return (STI->getFeatureBits() & ARM::HasV6T2Ops) != 0;
+ }
+
+ const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
+ const static MCFixupKindInfo Infos[ARM::NumTargetFixupKinds] = {
+// This table *must* be in the order that the fixup_* kinds are defined in
+// ARMFixupKinds.h.
+//
+// Name Offset (bits) Size (bits) Flags
+{ "fixup_arm_ldst_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
+ MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
+{ "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
+ MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
+{ "fixup_thumb_adr_pcrel_10",0, 8, MCFixupKindInfo::FKF_IsPCRel |
+ MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
+{ "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
+ MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
+{ "fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_thumb_cp", 0, 8, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_thumb_bcc", 0, 8, MCFixupKindInfo::FKF_IsPCRel },
+// movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 - 19.
+{ "fixup_arm_movt_hi16", 0, 20, 0 },
+{ "fixup_arm_movw_lo16", 0, 20, 0 },
+{ "fixup_t2_movt_hi16", 0, 20, 0 },
+{ "fixup_t2_movw_lo16", 0, 20, 0 },
+{ "fixup_arm_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_t2_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_t2_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel },
+ };
+
+ if (Kind < FirstTargetFixupKind)
+ return MCAsmBackend::getFixupKindInfo(Kind);
+
+ assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
+ "Invalid kind!");
+ return Infos[Kind - FirstTargetFixupKind];
+ }
+
+ bool MayNeedRelaxation(const MCInst &Inst) const;
+
+ void RelaxInstruction(const MCInst &Inst, MCInst &Res) const;
+
+ bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const;
+
+ void HandleAssemblerFlag(MCAssemblerFlag Flag) {
+ switch (Flag) {
+ default: break;
+ case MCAF_Code16:
+ setIsThumb(true);
+ break;
+ case MCAF_Code32:
+ setIsThumb(false);
+ break;
+ }
+ }
+
+ unsigned getPointerSize() const { return 4; }
+ bool isThumb() const { return isThumbMode; }
+ void setIsThumb(bool it) { isThumbMode = it; }
+};
+} // end anonymous namespace
+
+bool ARMAsmBackend::MayNeedRelaxation(const MCInst &Inst) const {
+ // FIXME: Thumb targets, different move constant targets..
+ return false;
+}
+
+void ARMAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
+ assert(0 && "ARMAsmBackend::RelaxInstruction() unimplemented");
+ return;
+}
+
+bool ARMAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
+ const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8
+ const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP
+ const uint32_t ARMv4_NopEncoding = 0xe1a0000; // using MOV r0,r0
+ const uint32_t ARMv6T2_NopEncoding = 0xe3207800; // NOP
+ if (isThumb()) {
+ const uint16_t nopEncoding = hasNOP() ? Thumb2_16bitNopEncoding
+ : Thumb1_16bitNopEncoding;
+ uint64_t NumNops = Count / 2;
+ for (uint64_t i = 0; i != NumNops; ++i)
+ OW->Write16(nopEncoding);
+ if (Count & 1)
+ OW->Write8(0);
+ return true;
+ }
+ // ARM mode
+ const uint32_t nopEncoding = hasNOP() ? ARMv6T2_NopEncoding
+ : ARMv4_NopEncoding;
+ uint64_t NumNops = Count / 4;
+ for (uint64_t i = 0; i != NumNops; ++i)
+ OW->Write32(nopEncoding);
+ // FIXME: should this function return false when unable to write exactly
+ // 'Count' bytes with NOP encodings?
+ switch (Count % 4) {
+ default: break; // No leftover bytes to write
+ case 1: OW->Write8(0); break;
+ case 2: OW->Write16(0); break;
+ case 3: OW->Write16(0); OW->Write8(0xa0); break;
+ }
+
+ return true;
+}
+
+static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("Unknown fixup kind!");
+ case FK_Data_1:
+ case FK_Data_2:
+ case FK_Data_4:
+ return Value;
+ case ARM::fixup_arm_movt_hi16:
+ Value >>= 16;
+ // Fallthrough
+ case ARM::fixup_arm_movw_lo16:
+ case ARM::fixup_arm_movt_hi16_pcrel:
+ case ARM::fixup_arm_movw_lo16_pcrel: {
+ unsigned Hi4 = (Value & 0xF000) >> 12;
+ unsigned Lo12 = Value & 0x0FFF;
+ // inst{19-16} = Hi4;
+ // inst{11-0} = Lo12;
+ Value = (Hi4 << 16) | (Lo12);
+ return Value;
+ }
+ case ARM::fixup_t2_movt_hi16:
+ Value >>= 16;
+ // Fallthrough
+ case ARM::fixup_t2_movw_lo16:
+ case ARM::fixup_t2_movt_hi16_pcrel: //FIXME: Shouldn't this be shifted like
+ // the other hi16 fixup?
+ case ARM::fixup_t2_movw_lo16_pcrel: {
+ unsigned Hi4 = (Value & 0xF000) >> 12;
+ unsigned i = (Value & 0x800) >> 11;
+ unsigned Mid3 = (Value & 0x700) >> 8;
+ unsigned Lo8 = Value & 0x0FF;
+ // inst{19-16} = Hi4;
+ // inst{26} = i;
+ // inst{14-12} = Mid3;
+ // inst{7-0} = Lo8;
+ Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8);
+ uint64_t swapped = (Value & 0xFFFF0000) >> 16;
+ swapped |= (Value & 0x0000FFFF) << 16;
+ return swapped;
+ }
+ case ARM::fixup_arm_ldst_pcrel_12:
+ // ARM PC-relative values are offset by 8.
+ Value -= 4;
+ // FALLTHROUGH
+ case ARM::fixup_t2_ldst_pcrel_12: {
+ // Offset by 4, adjusted by two due to the half-word ordering of thumb.
+ Value -= 4;
+ bool isAdd = true;
+ if ((int64_t)Value < 0) {
+ Value = -Value;
+ isAdd = false;
+ }
+ assert ((Value < 4096) && "Out of range pc-relative fixup value!");
+ Value |= isAdd << 23;
+
+ // Same addressing mode as fixup_arm_pcrel_10,
+ // but with 16-bit halfwords swapped.
+ if (Kind == ARM::fixup_t2_ldst_pcrel_12) {
+ uint64_t swapped = (Value & 0xFFFF0000) >> 16;
+ swapped |= (Value & 0x0000FFFF) << 16;
+ return swapped;
+ }
+
+ return Value;
+ }
+ case ARM::fixup_thumb_adr_pcrel_10:
+ return ((Value - 4) >> 2) & 0xff;
+ case ARM::fixup_arm_adr_pcrel_12: {
+ // ARM PC-relative values are offset by 8.
+ Value -= 8;
+ unsigned opc = 4; // bits {24-21}. Default to add: 0b0100
+ if ((int64_t)Value < 0) {
+ Value = -Value;
+ opc = 2; // 0b0010
+ }
+ assert(ARM_AM::getSOImmVal(Value) != -1 &&
+ "Out of range pc-relative fixup value!");
+ // Encode the immediate and shift the opcode into place.
+ return ARM_AM::getSOImmVal(Value) | (opc << 21);
+ }
+
+ case ARM::fixup_t2_adr_pcrel_12: {
+ Value -= 4;
+ unsigned opc = 0;
+ if ((int64_t)Value < 0) {
+ Value = -Value;
+ opc = 5;
+ }
+
+ uint32_t out = (opc << 21);
+ out |= (Value & 0x800) << 15;
+ out |= (Value & 0x700) << 4;
+ out |= (Value & 0x0FF);
+
+ uint64_t swapped = (out & 0xFFFF0000) >> 16;
+ swapped |= (out & 0x0000FFFF) << 16;
+ return swapped;
+ }
+
+ case ARM::fixup_arm_condbranch:
+ case ARM::fixup_arm_uncondbranch:
+ // These values don't encode the low two bits since they're always zero.
+ // Offset by 8 just as above.
+ return 0xffffff & ((Value - 8) >> 2);
+ case ARM::fixup_t2_uncondbranch: {
+ Value = Value - 4;
+ Value >>= 1; // Low bit is not encoded.
+
+ uint32_t out = 0;
+ bool I = Value & 0x800000;
+ bool J1 = Value & 0x400000;
+ bool J2 = Value & 0x200000;
+ J1 ^= I;
+ J2 ^= I;
+
+ out |= I << 26; // S bit
+ out |= !J1 << 13; // J1 bit
+ out |= !J2 << 11; // J2 bit
+ out |= (Value & 0x1FF800) << 5; // imm6 field
+ out |= (Value & 0x0007FF); // imm11 field
+
+ uint64_t swapped = (out & 0xFFFF0000) >> 16;
+ swapped |= (out & 0x0000FFFF) << 16;
+ return swapped;
+ }
+ case ARM::fixup_t2_condbranch: {
+ Value = Value - 4;
+ Value >>= 1; // Low bit is not encoded.
+
+ uint64_t out = 0;
+ out |= (Value & 0x80000) << 7; // S bit
+ out |= (Value & 0x40000) >> 7; // J2 bit
+ out |= (Value & 0x20000) >> 4; // J1 bit
+ out |= (Value & 0x1F800) << 5; // imm6 field
+ out |= (Value & 0x007FF); // imm11 field
+
+ uint32_t swapped = (out & 0xFFFF0000) >> 16;
+ swapped |= (out & 0x0000FFFF) << 16;
+ return swapped;
+ }
+ case ARM::fixup_arm_thumb_bl: {
+ // The value doesn't encode the low bit (always zero) and is offset by
+ // four. The value is encoded into disjoint bit positions in the destination
+ // opcode. x = unchanged, I = immediate value bit, S = sign extension bit
+ //
+ // BL: xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII
+ //
+ // Note that the halfwords are stored high first, low second; so we need
+ // to transpose the fixup value here to map properly.
+ unsigned isNeg = (int64_t(Value - 4) < 0) ? 1 : 0;
+ uint32_t Binary = 0;
+ Value = 0x3fffff & ((Value - 4) >> 1);
+ Binary = (Value & 0x7ff) << 16; // Low imm11 value.
+ Binary |= (Value & 0x1ffc00) >> 11; // High imm10 value.
+ Binary |= isNeg << 10; // Sign bit.
+ return Binary;
+ }
+ case ARM::fixup_arm_thumb_blx: {
+ // The value doesn't encode the low two bits (always zero) and is offset by
+ // four (see fixup_arm_thumb_cp). The value is encoded into disjoint bit
+ // positions in the destination opcode. x = unchanged, I = immediate value
+ // bit, S = sign extension bit, 0 = zero.
+ //
+ // BLX: xxxxxSIIIIIIIIII xxxxxIIIIIIIIII0
+ //
+ // Note that the halfwords are stored high first, low second; so we need
+ // to transpose the fixup value here to map properly.
+ unsigned isNeg = (int64_t(Value-4) < 0) ? 1 : 0;
+ uint32_t Binary = 0;
+ Value = 0xfffff & ((Value - 2) >> 2);
+ Binary = (Value & 0x3ff) << 17; // Low imm10L value.
+ Binary |= (Value & 0xffc00) >> 10; // High imm10H value.
+ Binary |= isNeg << 10; // Sign bit.
+ return Binary;
+ }
+ case ARM::fixup_arm_thumb_cp:
+ // Offset by 4, and don't encode the low two bits. Two bytes of that
+ // 'off by 4' is implicitly handled by the half-word ordering of the
+ // Thumb encoding, so we only need to adjust by 2 here.
+ return ((Value - 2) >> 2) & 0xff;
+ case ARM::fixup_arm_thumb_cb: {
+ // Offset by 4 and don't encode the lower bit, which is always 0.
+ uint32_t Binary = (Value - 4) >> 1;
+ return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3);
+ }
+ case ARM::fixup_arm_thumb_br:
+ // Offset by 4 and don't encode the lower bit, which is always 0.
+ return ((Value - 4) >> 1) & 0x7ff;
+ case ARM::fixup_arm_thumb_bcc:
+ // Offset by 4 and don't encode the lower bit, which is always 0.
+ return ((Value - 4) >> 1) & 0xff;
+ case ARM::fixup_arm_pcrel_10:
+ Value = Value - 4; // ARM fixups offset by an additional word and don't
+ // need to adjust for the half-word ordering.
+ // Fall through.
+ case ARM::fixup_t2_pcrel_10: {
+ // Offset by 4, adjusted by two due to the half-word ordering of thumb.
+ Value = Value - 4;
+ bool isAdd = true;
+ if ((int64_t)Value < 0) {
+ Value = -Value;
+ isAdd = false;
+ }
+ // These values don't encode the low two bits since they're always zero.
+ Value >>= 2;
+ assert ((Value < 256) && "Out of range pc-relative fixup value!");
+ Value |= isAdd << 23;
+
+ // Same addressing mode as fixup_arm_pcrel_10,
+ // but with 16-bit halfwords swapped.
+ if (Kind == ARM::fixup_t2_pcrel_10) {
+ uint32_t swapped = (Value & 0xFFFF0000) >> 16;
+ swapped |= (Value & 0x0000FFFF) << 16;
+ return swapped;
+ }
+
+ return Value;
+ }
+ }
+}
+
+namespace {
+
+// FIXME: This should be in a separate file.
+// ELF is an ELF of course...
+class ELFARMAsmBackend : public ARMAsmBackend {
+public:
+ Triple::OSType OSType;
+ ELFARMAsmBackend(const Target &T, const StringRef TT,
+ Triple::OSType _OSType)
+ : ARMAsmBackend(T, TT), OSType(_OSType) { }
+
+ void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
+ uint64_t Value) const;
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ return createELFObjectWriter(new ARMELFObjectWriter(OSType), OS,
+ /*IsLittleEndian*/ true);
+ }
+};
+
+// FIXME: Raise this to share code between Darwin and ELF.
+void ELFARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data,
+ unsigned DataSize, uint64_t Value) const {
+ unsigned NumBytes = 4; // FIXME: 2 for Thumb
+ Value = adjustFixupValue(Fixup.getKind(), Value);
+ if (!Value) return; // Doesn't change encoding.
+
+ unsigned Offset = Fixup.getOffset();
+
+ // For each byte of the fragment that the fixup touches, mask in the bits from
+ // the fixup value. The Value has been "split up" into the appropriate
+ // bitfields above.
+ for (unsigned i = 0; i != NumBytes; ++i)
+ Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
+}
+
+// FIXME: This should be in a separate file.
+class DarwinARMAsmBackend : public ARMAsmBackend {
+public:
+ const object::mach::CPUSubtypeARM Subtype;
+ DarwinARMAsmBackend(const Target &T, const StringRef TT,
+ object::mach::CPUSubtypeARM st)
+ : ARMAsmBackend(T, TT), Subtype(st) { }
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ return createARMMachObjectWriter(OS, /*Is64Bit=*/false,
+ object::mach::CTM_ARM,
+ Subtype);
+ }
+
+ void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
+ uint64_t Value) const;
+
+ virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
+ return false;
+ }
+};
+
+/// getFixupKindNumBytes - The number of bytes the fixup may change.
+static unsigned getFixupKindNumBytes(unsigned Kind) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("Unknown fixup kind!");
+
+ case FK_Data_1:
+ case ARM::fixup_arm_thumb_bcc:
+ case ARM::fixup_arm_thumb_cp:
+ case ARM::fixup_thumb_adr_pcrel_10:
+ return 1;
+
+ case FK_Data_2:
+ case ARM::fixup_arm_thumb_br:
+ case ARM::fixup_arm_thumb_cb:
+ return 2;
+
+ case ARM::fixup_arm_ldst_pcrel_12:
+ case ARM::fixup_arm_pcrel_10:
+ case ARM::fixup_arm_adr_pcrel_12:
+ case ARM::fixup_arm_condbranch:
+ case ARM::fixup_arm_uncondbranch:
+ return 3;
+
+ case FK_Data_4:
+ case ARM::fixup_t2_ldst_pcrel_12:
+ case ARM::fixup_t2_condbranch:
+ case ARM::fixup_t2_uncondbranch:
+ case ARM::fixup_t2_pcrel_10:
+ case ARM::fixup_t2_adr_pcrel_12:
+ case ARM::fixup_arm_thumb_bl:
+ case ARM::fixup_arm_thumb_blx:
+ case ARM::fixup_arm_movt_hi16:
+ case ARM::fixup_arm_movw_lo16:
+ case ARM::fixup_arm_movt_hi16_pcrel:
+ case ARM::fixup_arm_movw_lo16_pcrel:
+ case ARM::fixup_t2_movt_hi16:
+ case ARM::fixup_t2_movw_lo16:
+ case ARM::fixup_t2_movt_hi16_pcrel:
+ case ARM::fixup_t2_movw_lo16_pcrel:
+ return 4;
+ }
+}
+
+void DarwinARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data,
+ unsigned DataSize, uint64_t Value) const {
+ unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
+ Value = adjustFixupValue(Fixup.getKind(), Value);
+ if (!Value) return; // Doesn't change encoding.
+
+ unsigned Offset = Fixup.getOffset();
+ assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!");
+
+ // For each byte of the fragment that the fixup touches, mask in the
+ // bits from the fixup value.
+ for (unsigned i = 0; i != NumBytes; ++i)
+ Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
+}
+
+} // end anonymous namespace
+
+MCAsmBackend *llvm::createARMAsmBackend(const Target &T, StringRef TT) {
+ Triple TheTriple(TT);
+
+ if (TheTriple.isOSDarwin()) {
+ if (TheTriple.getArchName() == "armv4t" ||
+ TheTriple.getArchName() == "thumbv4t")
+ return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V4T);
+ else if (TheTriple.getArchName() == "armv5e" ||
+ TheTriple.getArchName() == "thumbv5e")
+ return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V5TEJ);
+ else if (TheTriple.getArchName() == "armv6" ||
+ TheTriple.getArchName() == "thumbv6")
+ return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6);
+ return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7);
+ }
+
+ if (TheTriple.isOSWindows())
+ assert(0 && "Windows not supported on ARM");
+
+ return new ELFARMAsmBackend(T, TT, Triple(TT).getOS());
+}
diff --git a/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h b/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h
new file mode 100644
index 0000000..ec4b6ff
--- /dev/null
+++ b/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h
@@ -0,0 +1,449 @@
+//===-- ARMBaseInfo.h - Top level definitions for ARM -------- --*- 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 small standalone helper functions and enum definitions for
+// the ARM target useful for the compiler back-end and the MC libraries.
+// As such, it deliberately does not include references to LLVM core
+// code gen types, passes, etc..
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ARMBASEINFO_H
+#define ARMBASEINFO_H
+
+#include "ARMMCTargetDesc.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace llvm {
+
+// Enums corresponding to ARM condition codes
+namespace ARMCC {
+ // The CondCodes constants map directly to the 4-bit encoding of the
+ // condition field for predicated instructions.
+ enum CondCodes { // Meaning (integer) Meaning (floating-point)
+ EQ, // Equal Equal
+ NE, // Not equal Not equal, or unordered
+ HS, // Carry set >, ==, or unordered
+ LO, // Carry clear Less than
+ MI, // Minus, negative Less than
+ PL, // Plus, positive or zero >, ==, or unordered
+ VS, // Overflow Unordered
+ VC, // No overflow Not unordered
+ HI, // Unsigned higher Greater than, or unordered
+ LS, // Unsigned lower or same Less than or equal
+ GE, // Greater than or equal Greater than or equal
+ LT, // Less than Less than, or unordered
+ GT, // Greater than Greater than
+ LE, // Less than or equal <, ==, or unordered
+ AL // Always (unconditional) Always (unconditional)
+ };
+
+ inline static CondCodes getOppositeCondition(CondCodes CC) {
+ switch (CC) {
+ default: llvm_unreachable("Unknown condition code");
+ case EQ: return NE;
+ case NE: return EQ;
+ case HS: return LO;
+ case LO: return HS;
+ case MI: return PL;
+ case PL: return MI;
+ case VS: return VC;
+ case VC: return VS;
+ case HI: return LS;
+ case LS: return HI;
+ case GE: return LT;
+ case LT: return GE;
+ case GT: return LE;
+ case LE: return GT;
+ }
+ }
+} // namespace ARMCC
+
+inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) {
+ switch (CC) {
+ default: llvm_unreachable("Unknown condition code");
+ case ARMCC::EQ: return "eq";
+ case ARMCC::NE: return "ne";
+ case ARMCC::HS: return "hs";
+ case ARMCC::LO: return "lo";
+ case ARMCC::MI: return "mi";
+ case ARMCC::PL: return "pl";
+ case ARMCC::VS: return "vs";
+ case ARMCC::VC: return "vc";
+ case ARMCC::HI: return "hi";
+ case ARMCC::LS: return "ls";
+ case ARMCC::GE: return "ge";
+ case ARMCC::LT: return "lt";
+ case ARMCC::GT: return "gt";
+ case ARMCC::LE: return "le";
+ case ARMCC::AL: return "al";
+ }
+}
+
+namespace ARM_PROC {
+ enum IMod {
+ IE = 2,
+ ID = 3
+ };
+
+ enum IFlags {
+ F = 1,
+ I = 2,
+ A = 4
+ };
+
+ inline static const char *IFlagsToString(unsigned val) {
+ switch (val) {
+ default: llvm_unreachable("Unknown iflags operand");
+ case F: return "f";
+ case I: return "i";
+ case A: return "a";
+ }
+ }
+
+ inline static const char *IModToString(unsigned val) {
+ switch (val) {
+ default: llvm_unreachable("Unknown imod operand");
+ case IE: return "ie";
+ case ID: return "id";
+ }
+ }
+}
+
+namespace ARM_MB {
+ // The Memory Barrier Option constants map directly to the 4-bit encoding of
+ // the option field for memory barrier operations.
+ enum MemBOpt {
+ SY = 15,
+ ST = 14,
+ ISH = 11,
+ ISHST = 10,
+ NSH = 7,
+ NSHST = 6,
+ OSH = 3,
+ OSHST = 2
+ };
+
+ inline static const char *MemBOptToString(unsigned val) {
+ switch (val) {
+ default: llvm_unreachable("Unknown memory operation");
+ case SY: return "sy";
+ case ST: return "st";
+ case ISH: return "ish";
+ case ISHST: return "ishst";
+ case NSH: return "nsh";
+ case NSHST: return "nshst";
+ case OSH: return "osh";
+ case OSHST: return "oshst";
+ }
+ }
+} // namespace ARM_MB
+
+/// getARMRegisterNumbering - Given the enum value for some register, e.g.
+/// ARM::LR, return the number that it corresponds to (e.g. 14).
+inline static unsigned getARMRegisterNumbering(unsigned Reg) {
+ using namespace ARM;
+ switch (Reg) {
+ default:
+ llvm_unreachable("Unknown ARM register!");
+ case R0: case S0: case D0: case Q0: return 0;
+ case R1: case S1: case D1: case Q1: return 1;
+ case R2: case S2: case D2: case Q2: return 2;
+ case R3: case S3: case D3: case Q3: return 3;
+ case R4: case S4: case D4: case Q4: return 4;
+ case R5: case S5: case D5: case Q5: return 5;
+ case R6: case S6: case D6: case Q6: return 6;
+ case R7: case S7: case D7: case Q7: return 7;
+ case R8: case S8: case D8: case Q8: return 8;
+ case R9: case S9: case D9: case Q9: return 9;
+ case R10: case S10: case D10: case Q10: return 10;
+ case R11: case S11: case D11: case Q11: return 11;
+ case R12: case S12: case D12: case Q12: return 12;
+ case SP: case S13: case D13: case Q13: return 13;
+ case LR: case S14: case D14: case Q14: return 14;
+ case PC: case S15: case D15: case Q15: return 15;
+
+ case S16: case D16: return 16;
+ case S17: case D17: return 17;
+ case S18: case D18: return 18;
+ case S19: case D19: return 19;
+ case S20: case D20: return 20;
+ case S21: case D21: return 21;
+ case S22: case D22: return 22;
+ case S23: case D23: return 23;
+ case S24: case D24: return 24;
+ case S25: case D25: return 25;
+ case S26: case D26: return 26;
+ case S27: case D27: return 27;
+ case S28: case D28: return 28;
+ case S29: case D29: return 29;
+ case S30: case D30: return 30;
+ case S31: case D31: return 31;
+ }
+}
+
+/// isARMLowRegister - Returns true if the register is a 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;
+ }
+}
+
+/// ARMII - This namespace holds all of the target specific flags that
+/// instruction info tracks.
+///
+namespace ARMII {
+
+ /// ARM Index Modes
+ enum IndexMode {
+ IndexModeNone = 0,
+ IndexModePre = 1,
+ IndexModePost = 2,
+ IndexModeUpd = 3
+ };
+
+ /// ARM Addressing Modes
+ enum AddrMode {
+ AddrModeNone = 0,
+ AddrMode1 = 1,
+ AddrMode2 = 2,
+ AddrMode3 = 3,
+ AddrMode4 = 4,
+ AddrMode5 = 5,
+ AddrMode6 = 6,
+ AddrModeT1_1 = 7,
+ AddrModeT1_2 = 8,
+ AddrModeT1_4 = 9,
+ AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data
+ AddrModeT2_i12 = 11,
+ AddrModeT2_i8 = 12,
+ AddrModeT2_so = 13,
+ AddrModeT2_pc = 14, // +/- i12 for pc relative data
+ AddrModeT2_i8s4 = 15, // i8 * 4
+ AddrMode_i12 = 16
+ };
+
+ inline static const char *AddrModeToString(AddrMode addrmode) {
+ switch (addrmode) {
+ default: llvm_unreachable("Unknown memory operation");
+ case AddrModeNone: return "AddrModeNone";
+ case AddrMode1: return "AddrMode1";
+ case AddrMode2: return "AddrMode2";
+ case AddrMode3: return "AddrMode3";
+ case AddrMode4: return "AddrMode4";
+ case AddrMode5: return "AddrMode5";
+ case AddrMode6: return "AddrMode6";
+ case AddrModeT1_1: return "AddrModeT1_1";
+ case AddrModeT1_2: return "AddrModeT1_2";
+ case AddrModeT1_4: return "AddrModeT1_4";
+ case AddrModeT1_s: return "AddrModeT1_s";
+ case AddrModeT2_i12: return "AddrModeT2_i12";
+ case AddrModeT2_i8: return "AddrModeT2_i8";
+ case AddrModeT2_so: return "AddrModeT2_so";
+ case AddrModeT2_pc: return "AddrModeT2_pc";
+ case AddrModeT2_i8s4: return "AddrModeT2_i8s4";
+ case AddrMode_i12: return "AddrMode_i12";
+ }
+ }
+
+ /// Target Operand Flag enum.
+ enum TOF {
+ //===------------------------------------------------------------------===//
+ // ARM Specific MachineOperand flags.
+
+ MO_NO_FLAG,
+
+ /// MO_LO16 - On a symbol operand, this represents a relocation containing
+ /// lower 16 bit of the address. Used only via movw instruction.
+ MO_LO16,
+
+ /// MO_HI16 - On a symbol operand, this represents a relocation containing
+ /// higher 16 bit of the address. Used only via movt instruction.
+ MO_HI16,
+
+ /// MO_LO16_NONLAZY - On a symbol operand "FOO", this represents a
+ /// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol,
+ /// i.e. "FOO$non_lazy_ptr".
+ /// Used only via movw instruction.
+ MO_LO16_NONLAZY,
+
+ /// MO_HI16_NONLAZY - On a symbol operand "FOO", this represents a
+ /// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol,
+ /// i.e. "FOO$non_lazy_ptr". Used only via movt instruction.
+ MO_HI16_NONLAZY,
+
+ /// MO_LO16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
+ /// relocation containing lower 16 bit of the PC relative address of the
+ /// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
+ /// Used only via movw instruction.
+ MO_LO16_NONLAZY_PIC,
+
+ /// MO_HI16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
+ /// relocation containing lower 16 bit of the PC relative address of the
+ /// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
+ /// Used only via movt instruction.
+ MO_HI16_NONLAZY_PIC,
+
+ /// MO_PLT - On a symbol operand, this represents an ELF PLT reference on a
+ /// call operand.
+ MO_PLT
+ };
+
+ 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,
+
+ // ThumbArithFlagSetting - The instruction is a 16-bit flag setting Thumb
+ // instruction. Used by the parser to determine whether to require the 'S'
+ // suffix on the mnemonic (when not in an IT block) or preclude it (when
+ // in an IT block).
+ ThumbArithFlagSetting = 1 << 18,
+
+ //===------------------------------------------------------------------===//
+ // 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
+ };
+
+} // end namespace ARMII
+
+} // end namespace llvm;
+
+#endif
diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h
index 350c92d..350c92d 100644
--- a/lib/Target/ARM/ARMFixupKinds.h
+++ b/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
index 53b4c95..1c109e0 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
@@ -52,6 +52,9 @@ ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() {
AsmTransCBE = arm_asm_table;
Data64bitsDirective = 0;
CommentString = "@";
+ Code16Directive = ".code\t16";
+ Code32Directive = ".code\t32";
+
SupportsDebugInformation = true;
// Exceptions handling
@@ -64,12 +67,14 @@ ARMELFMCAsmInfo::ARMELFMCAsmInfo() {
Data64bitsDirective = 0;
CommentString = "@";
-
- HasLEB128 = true;
PrivateGlobalPrefix = ".L";
+ Code16Directive = ".code\t16";
+ Code32Directive = ".code\t32";
+
WeakRefDirective = "\t.weak\t";
- HasLCOMMDirective = true;
+ LCOMMDirectiveType = LCOMM::NoAlignment;
+ HasLEB128 = true;
SupportsDebugInformation = true;
// Exceptions handling
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
new file mode 100644
index 0000000..865c3e2
--- /dev/null
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
@@ -0,0 +1,1468 @@
+//===-- ARM/ARMMCCodeEmitter.cpp - Convert ARM code to machine code -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the ARMMCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mccodeemitter"
+#include "MCTargetDesc/ARMAddressingModes.h"
+#include "MCTargetDesc/ARMBaseInfo.h"
+#include "MCTargetDesc/ARMFixupKinds.h"
+#include "MCTargetDesc/ARMMCExpr.h"
+#include "MCTargetDesc/ARMMCTargetDesc.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
+STATISTIC(MCNumCPRelocations, "Number of constant pool relocations created.");
+
+namespace {
+class ARMMCCodeEmitter : public MCCodeEmitter {
+ ARMMCCodeEmitter(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
+ void operator=(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
+ const MCInstrInfo &MCII;
+ const MCSubtargetInfo &STI;
+
+public:
+ ARMMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
+ MCContext &ctx)
+ : MCII(mcii), STI(sti) {
+ }
+
+ ~ARMMCCodeEmitter() {}
+
+ bool isThumb() const {
+ // FIXME: Can tablegen auto-generate this?
+ return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
+ }
+ bool isThumb2() const {
+ return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) != 0;
+ }
+ bool isTargetDarwin() const {
+ Triple TT(STI.getTargetTriple());
+ Triple::OSType OS = TT.getOS();
+ return OS == Triple::Darwin || OS == Triple::MacOSX || OS == Triple::IOS;
+ }
+
+ unsigned getMachineSoImmOpValue(unsigned SoImm) const;
+
+ // getBinaryCodeForInstr - TableGen'erated function for getting the
+ // binary encoding for an instruction.
+ unsigned getBinaryCodeForInstr(const MCInst &MI,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getMachineOpValue - Return binary encoding of operand. If the machine
+ /// operand requires relocation, record the relocation and return zero.
+ unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getHiLo16ImmOpValue - Return the encoding for the hi / low 16-bit of
+ /// the specified operand. This is used for operands with :lower16: and
+ /// :upper16: prefixes.
+ uint32_t getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx,
+ unsigned &Reg, unsigned &Imm,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getThumbBLTargetOpValue - Return encoding info for Thumb immediate
+ /// BL branch target.
+ uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
+ /// BLX branch target.
+ uint32_t getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
+ uint32_t getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target.
+ uint32_t getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getThumbCBTargetOpValue - Return encoding info for Thumb branch target.
+ uint32_t getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getBranchTargetOpValue - Return encoding info for 24-bit immediate
+ /// branch target.
+ uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
+ /// immediate Thumb2 direct branch target.
+ uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getARMBranchTargetOpValue - Return encoding info for 24-bit immediate
+ /// branch target.
+ uint32_t getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ uint32_t getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getAdrLabelOpValue - Return encoding info for 12-bit immediate
+ /// ADR label target.
+ uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ uint32_t getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+
+ /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
+ /// operand.
+ uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getThumbAddrModeRegRegOpValue - Return encoding for 'reg + reg' operand.
+ uint32_t getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups)const;
+
+ /// getT2AddrModeImm8s4OpValue - Return encoding info for 'reg +/- imm8<<2'
+ /// operand.
+ uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getT2AddrModeImm0_1020s4OpValue - Return encoding info for 'reg + imm8<<2'
+ /// operand.
+ uint32_t getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getT2Imm8s4OpValue - Return encoding info for '+/- imm8<<2'
+ /// operand.
+ uint32_t getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+
+ /// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm'
+ /// operand as needed by load/store instructions.
+ uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getLdStmModeOpValue - Return encoding for load/store multiple mode.
+ uint32_t getLdStmModeOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ ARM_AM::AMSubMode Mode = (ARM_AM::AMSubMode)MI.getOperand(OpIdx).getImm();
+ switch (Mode) {
+ default: assert(0 && "Unknown addressing sub-mode!");
+ case ARM_AM::da: return 0;
+ case ARM_AM::ia: return 1;
+ case ARM_AM::db: return 2;
+ case ARM_AM::ib: return 3;
+ }
+ }
+ /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value.
+ ///
+ unsigned getShiftOp(ARM_AM::ShiftOpc ShOpc) const {
+ switch (ShOpc) {
+ default: llvm_unreachable("Unknown shift opc!");
+ case ARM_AM::no_shift:
+ case ARM_AM::lsl: return 0;
+ case ARM_AM::lsr: return 1;
+ case ARM_AM::asr: return 2;
+ case ARM_AM::ror:
+ case ARM_AM::rrx: return 3;
+ }
+ return 0;
+ }
+
+ /// getAddrMode2OpValue - Return encoding for addrmode2 operands.
+ uint32_t getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getAddrMode2OffsetOpValue - Return encoding for am2offset operands.
+ uint32_t getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getPostIdxRegOpValue - Return encoding for postidx_reg operands.
+ uint32_t getPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getAddrMode3OffsetOpValue - Return encoding for am3offset operands.
+ uint32_t getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getAddrMode3OpValue - Return encoding for addrmode3 operands.
+ uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getAddrModeThumbSPOpValue - Return encoding info for 'reg +/- imm12'
+ /// operand.
+ uint32_t getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getAddrModeISOpValue - Encode the t_addrmode_is# operands.
+ uint32_t getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands.
+ uint32_t getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand.
+ uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getCCOutOpValue - Return encoding of the 's' bit.
+ unsigned getCCOutOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // The operand is either reg0 or CPSR. The 's' bit is encoded as '0' or
+ // '1' respectively.
+ return MI.getOperand(Op).getReg() == ARM::CPSR;
+ }
+
+ /// getSOImmOpValue - Return an encoded 12-bit shifted-immediate value.
+ unsigned getSOImmOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ unsigned SoImm = MI.getOperand(Op).getImm();
+ int SoImmVal = ARM_AM::getSOImmVal(SoImm);
+ assert(SoImmVal != -1 && "Not a valid so_imm value!");
+
+ // Encode rotate_imm.
+ unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1)
+ << ARMII::SoRotImmShift;
+
+ // Encode immed_8.
+ Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
+ return Binary;
+ }
+
+ /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value.
+ unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ unsigned SoImm = MI.getOperand(Op).getImm();
+ unsigned Encoded = ARM_AM::getT2SOImmVal(SoImm);
+ assert(Encoded != ~0U && "Not a Thumb2 so_imm value?");
+ return Encoded;
+ }
+
+ unsigned getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getSORegOpValue - Return an encoded so_reg shifted register value.
+ unsigned getSORegRegOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getSORegImmOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ unsigned getNEONVcvtImm32OpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ return 64 - MI.getOperand(Op).getImm();
+ }
+
+ unsigned getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ unsigned getRegisterListOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ unsigned getShiftRight8Imm(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getShiftRight16Imm(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getShiftRight32Imm(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getShiftRight64Imm(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ unsigned getThumbSRImmOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ unsigned NEONThumb2DataIPostEncoder(const MCInst &MI,
+ unsigned EncodedValue) const;
+ unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI,
+ unsigned EncodedValue) const;
+ unsigned NEONThumb2DupPostEncoder(const MCInst &MI,
+ unsigned EncodedValue) const;
+
+ unsigned VFPThumb2PostEncoder(const MCInst &MI,
+ unsigned EncodedValue) const;
+
+ void EmitByte(unsigned char C, raw_ostream &OS) const {
+ OS << (char)C;
+ }
+
+ void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const {
+ // Output the constant in little endian byte order.
+ for (unsigned i = 0; i != Size; ++i) {
+ EmitByte(Val & 255, OS);
+ Val >>= 8;
+ }
+ }
+
+ void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+};
+
+} // end anonymous namespace
+
+MCCodeEmitter *llvm::createARMMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new ARMMCCodeEmitter(MCII, STI, Ctx);
+}
+
+/// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing
+/// instructions, and rewrite them to their Thumb2 form if we are currently in
+/// Thumb2 mode.
+unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
+ unsigned EncodedValue) const {
+ if (isThumb2()) {
+ // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved
+ // to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are
+ // set to 1111.
+ unsigned Bit24 = EncodedValue & 0x01000000;
+ unsigned Bit28 = Bit24 << 4;
+ EncodedValue &= 0xEFFFFFFF;
+ EncodedValue |= Bit28;
+ EncodedValue |= 0x0F000000;
+ }
+
+ return EncodedValue;
+}
+
+/// NEONThumb2LoadStorePostEncoder - Post-process encoded NEON load/store
+/// instructions, and rewrite them to their Thumb2 form if we are currently in
+/// Thumb2 mode.
+unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
+ unsigned EncodedValue) const {
+ if (isThumb2()) {
+ EncodedValue &= 0xF0FFFFFF;
+ EncodedValue |= 0x09000000;
+ }
+
+ return EncodedValue;
+}
+
+/// NEONThumb2DupPostEncoder - Post-process encoded NEON vdup
+/// instructions, and rewrite them to their Thumb2 form if we are currently in
+/// Thumb2 mode.
+unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
+ unsigned EncodedValue) const {
+ if (isThumb2()) {
+ EncodedValue &= 0x00FFFFFF;
+ EncodedValue |= 0xEE000000;
+ }
+
+ return EncodedValue;
+}
+
+/// VFPThumb2PostEncoder - Post-process encoded VFP instructions and rewrite
+/// them to their Thumb2 form if we are currently in Thumb2 mode.
+unsigned ARMMCCodeEmitter::
+VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const {
+ if (isThumb2()) {
+ EncodedValue &= 0x0FFFFFFF;
+ EncodedValue |= 0xE0000000;
+ }
+ return EncodedValue;
+}
+
+/// getMachineOpValue - Return binary encoding of operand. If the machine
+/// operand requires relocation, record the relocation and return zero.
+unsigned ARMMCCodeEmitter::
+getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ if (MO.isReg()) {
+ unsigned Reg = MO.getReg();
+ unsigned RegNo = getARMRegisterNumbering(Reg);
+
+ // Q registers are encoded as 2x their register number.
+ switch (Reg) {
+ default:
+ return RegNo;
+ case ARM::Q0: case ARM::Q1: case ARM::Q2: case ARM::Q3:
+ case ARM::Q4: case ARM::Q5: case ARM::Q6: case ARM::Q7:
+ case ARM::Q8: case ARM::Q9: case ARM::Q10: case ARM::Q11:
+ case ARM::Q12: case ARM::Q13: case ARM::Q14: case ARM::Q15:
+ return 2 * RegNo;
+ }
+ } else if (MO.isImm()) {
+ return static_cast<unsigned>(MO.getImm());
+ } else if (MO.isFPImm()) {
+ return static_cast<unsigned>(APFloat(MO.getFPImm())
+ .bitcastToAPInt().getHiBits(32).getLimitedValue());
+ }
+
+ llvm_unreachable("Unable to encode MCOperand!");
+ return 0;
+}
+
+/// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand.
+bool ARMMCCodeEmitter::
+EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg,
+ unsigned &Imm, SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
+
+ Reg = getARMRegisterNumbering(MO.getReg());
+
+ int32_t SImm = MO1.getImm();
+ bool isAdd = true;
+
+ // Special value for #-0
+ if (SImm == INT32_MIN) {
+ SImm = 0;
+ isAdd = false;
+ }
+
+ // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
+ if (SImm < 0) {
+ SImm = -SImm;
+ isAdd = false;
+ }
+
+ Imm = SImm;
+ return isAdd;
+}
+
+/// getBranchTargetOpValue - Helper function to get the branch target operand,
+/// which is either an immediate or requires a fixup.
+static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ unsigned FixupKind,
+ SmallVectorImpl<MCFixup> &Fixups) {
+ const MCOperand &MO = MI.getOperand(OpIdx);
+
+ // If the destination is an immediate, we have nothing to do.
+ if (MO.isImm()) return MO.getImm();
+ assert(MO.isExpr() && "Unexpected branch target type!");
+ const MCExpr *Expr = MO.getExpr();
+ MCFixupKind Kind = MCFixupKind(FixupKind);
+ Fixups.push_back(MCFixup::Create(0, Expr, Kind));
+
+ // All of the information is in the fixup.
+ return 0;
+}
+
+// Thumb BL and BLX use a strange offset encoding where bits 22 and 21 are
+// determined by negating them and XOR'ing them with bit 23.
+static int32_t encodeThumbBLOffset(int32_t offset) {
+ offset >>= 1;
+ uint32_t S = (offset & 0x800000) >> 23;
+ uint32_t J1 = (offset & 0x400000) >> 22;
+ uint32_t J2 = (offset & 0x200000) >> 21;
+ J1 = (~J1 & 0x1);
+ J2 = (~J2 & 0x1);
+ J1 ^= S;
+ J2 ^= S;
+
+ offset &= ~0x600000;
+ offset |= J1 << 22;
+ offset |= J2 << 21;
+
+ return offset;
+}
+
+/// getThumbBLTargetOpValue - Return encoding info for immediate branch target.
+uint32_t ARMMCCodeEmitter::
+getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bl,
+ Fixups);
+ return encodeThumbBLOffset(MO.getImm());
+}
+
+/// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
+/// BLX branch target.
+uint32_t ARMMCCodeEmitter::
+getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx,
+ Fixups);
+ return encodeThumbBLOffset(MO.getImm());
+}
+
+/// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
+uint32_t ARMMCCodeEmitter::
+getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_br,
+ Fixups);
+ return (MO.getImm() >> 1);
+}
+
+/// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target.
+uint32_t ARMMCCodeEmitter::
+getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bcc,
+ Fixups);
+ return (MO.getImm() >> 1);
+}
+
+/// getThumbCBTargetOpValue - Return encoding info for Thumb branch target.
+uint32_t ARMMCCodeEmitter::
+getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cb, Fixups);
+ return (MO.getImm() >> 1);
+}
+
+/// Return true if this branch has a non-always predication
+static bool HasConditionalBranch(const MCInst &MI) {
+ int NumOp = MI.getNumOperands();
+ if (NumOp >= 2) {
+ for (int i = 0; i < NumOp-1; ++i) {
+ const MCOperand &MCOp1 = MI.getOperand(i);
+ const MCOperand &MCOp2 = MI.getOperand(i + 1);
+ if (MCOp1.isImm() && MCOp2.isReg() &&
+ (MCOp2.getReg() == 0 || MCOp2.getReg() == ARM::CPSR)) {
+ if (ARMCC::CondCodes(MCOp1.getImm()) != ARMCC::AL)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch
+/// target.
+uint32_t ARMMCCodeEmitter::
+getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // FIXME: This really, really shouldn't use TargetMachine. We don't want
+ // coupling between MC and TM anywhere we can help it.
+ if (isThumb2())
+ return
+ ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups);
+ return getARMBranchTargetOpValue(MI, OpIdx, Fixups);
+}
+
+/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch
+/// target.
+uint32_t ARMMCCodeEmitter::
+getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr()) {
+ if (HasConditionalBranch(MI))
+ return ::getBranchTargetOpValue(MI, OpIdx,
+ ARM::fixup_arm_condbranch, Fixups);
+ return ::getBranchTargetOpValue(MI, OpIdx,
+ ARM::fixup_arm_uncondbranch, Fixups);
+ }
+
+ return MO.getImm() >> 2;
+}
+
+uint32_t ARMMCCodeEmitter::
+getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr()) {
+ if (HasConditionalBranch(MI))
+ return ::getBranchTargetOpValue(MI, OpIdx,
+ ARM::fixup_arm_condbranch, Fixups);
+ return ::getBranchTargetOpValue(MI, OpIdx,
+ ARM::fixup_arm_uncondbranch, Fixups);
+ }
+
+ return MO.getImm() >> 1;
+}
+
+/// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
+/// immediate branch target.
+uint32_t ARMMCCodeEmitter::
+getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ unsigned Val =
+ ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups);
+ bool I = (Val & 0x800000);
+ bool J1 = (Val & 0x400000);
+ bool J2 = (Val & 0x200000);
+ if (I ^ J1)
+ Val &= ~0x400000;
+ else
+ Val |= 0x400000;
+
+ if (I ^ J2)
+ Val &= ~0x200000;
+ else
+ Val |= 0x200000;
+
+ return Val;
+}
+
+/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
+/// target.
+uint32_t ARMMCCodeEmitter::
+getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_adr_pcrel_12,
+ Fixups);
+ int32_t offset = MO.getImm();
+ uint32_t Val = 0x2000;
+ if (offset < 0) {
+ Val = 0x1000;
+ offset *= -1;
+ }
+ Val |= offset;
+ return Val;
+}
+
+/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
+/// target.
+uint32_t ARMMCCodeEmitter::
+getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_adr_pcrel_12,
+ Fixups);
+ int32_t Val = MO.getImm();
+ if (Val < 0) {
+ Val *= -1;
+ Val |= 0x1000;
+ }
+ return Val;
+}
+
+/// getAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label
+/// target.
+uint32_t ARMMCCodeEmitter::
+getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_thumb_adr_pcrel_10,
+ Fixups);
+ return MO.getImm();
+}
+
+/// getThumbAddrModeRegRegOpValue - Return encoding info for 'reg + reg'
+/// operand.
+uint32_t ARMMCCodeEmitter::
+getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &) const {
+ // [Rn, Rm]
+ // {5-3} = Rm
+ // {2-0} = Rn
+ const MCOperand &MO1 = MI.getOperand(OpIdx);
+ const MCOperand &MO2 = MI.getOperand(OpIdx + 1);
+ unsigned Rn = getARMRegisterNumbering(MO1.getReg());
+ unsigned Rm = getARMRegisterNumbering(MO2.getReg());
+ return (Rm << 3) | Rn;
+}
+
+/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand.
+uint32_t ARMMCCodeEmitter::
+getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // {17-13} = reg
+ // {12} = (U)nsigned (add == '1', sub == '0')
+ // {11-0} = imm12
+ unsigned Reg, Imm12;
+ bool isAdd = true;
+ // If The first operand isn't a register, we have a label reference.
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ if (!MO.isReg()) {
+ Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
+ Imm12 = 0;
+ isAdd = false ; // 'U' bit is set as part of the fixup.
+
+ if (MO.isExpr()) {
+ const MCExpr *Expr = MO.getExpr();
+
+ MCFixupKind Kind;
+ if (isThumb2())
+ Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12);
+ else
+ Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12);
+ Fixups.push_back(MCFixup::Create(0, Expr, Kind));
+
+ ++MCNumCPRelocations;
+ } else {
+ Reg = ARM::PC;
+ int32_t Offset = MO.getImm();
+ if (Offset < 0) {
+ Offset *= -1;
+ isAdd = false;
+ }
+ Imm12 = Offset;
+ }
+ } else
+ isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm12, Fixups);
+
+ uint32_t Binary = Imm12 & 0xfff;
+ // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
+ if (isAdd)
+ Binary |= (1 << 12);
+ Binary |= (Reg << 13);
+ return Binary;
+}
+
+/// getT2Imm8s4OpValue - Return encoding info for
+/// '+/- imm8<<2' operand.
+uint32_t ARMMCCodeEmitter::
+getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // FIXME: The immediate operand should have already been encoded like this
+ // before ever getting here. The encoder method should just need to combine
+ // the MI operands for the register and the offset into a single
+ // representation for the complex operand in the .td file. This isn't just
+ // style, unfortunately. As-is, we can't represent the distinct encoding
+ // for #-0.
+
+ // {8} = (U)nsigned (add == '1', sub == '0')
+ // {7-0} = imm8
+ int32_t Imm8 = MI.getOperand(OpIdx).getImm();
+ bool isAdd = Imm8 >= 0;
+
+ // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
+ if (Imm8 < 0)
+ Imm8 = -Imm8;
+
+ // Scaled by 4.
+ Imm8 /= 4;
+
+ uint32_t Binary = Imm8 & 0xff;
+ // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
+ if (isAdd)
+ Binary |= (1 << 8);
+ return Binary;
+}
+
+/// getT2AddrModeImm8s4OpValue - Return encoding info for
+/// 'reg +/- imm8<<2' operand.
+uint32_t ARMMCCodeEmitter::
+getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // {12-9} = reg
+ // {8} = (U)nsigned (add == '1', sub == '0')
+ // {7-0} = imm8
+ unsigned Reg, Imm8;
+ bool isAdd = true;
+ // If The first operand isn't a register, we have a label reference.
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ if (!MO.isReg()) {
+ Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
+ Imm8 = 0;
+ isAdd = false ; // 'U' bit is set as part of the fixup.
+
+ assert(MO.isExpr() && "Unexpected machine operand type!");
+ const MCExpr *Expr = MO.getExpr();
+ MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
+ Fixups.push_back(MCFixup::Create(0, Expr, Kind));
+
+ ++MCNumCPRelocations;
+ } else
+ isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups);
+
+ // FIXME: The immediate operand should have already been encoded like this
+ // before ever getting here. The encoder method should just need to combine
+ // the MI operands for the register and the offset into a single
+ // representation for the complex operand in the .td file. This isn't just
+ // style, unfortunately. As-is, we can't represent the distinct encoding
+ // for #-0.
+ uint32_t Binary = (Imm8 >> 2) & 0xff;
+ // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
+ if (isAdd)
+ Binary |= (1 << 8);
+ Binary |= (Reg << 9);
+ return Binary;
+}
+
+/// getT2AddrModeImm0_1020s4OpValue - Return encoding info for
+/// 'reg + imm8<<2' operand.
+uint32_t ARMMCCodeEmitter::
+getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // {11-8} = reg
+ // {7-0} = imm8
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
+ unsigned Reg = getARMRegisterNumbering(MO.getReg());
+ unsigned Imm8 = MO1.getImm();
+ return (Reg << 8) | Imm8;
+}
+
+// FIXME: This routine assumes that a binary
+// expression will always result in a PCRel expression
+// In reality, its only true if one or more subexpressions
+// is itself a PCRel (i.e. "." in asm or some other pcrel construct)
+// but this is good enough for now.
+static bool EvaluateAsPCRel(const MCExpr *Expr) {
+ switch (Expr->getKind()) {
+ default: assert(0 && "Unexpected expression type");
+ case MCExpr::SymbolRef: return false;
+ case MCExpr::Binary: return true;
+ }
+}
+
+uint32_t
+ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // {20-16} = imm{15-12}
+ // {11-0} = imm{11-0}
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ if (MO.isImm())
+ // Hi / lo 16 bits already extracted during earlier passes.
+ return static_cast<unsigned>(MO.getImm());
+
+ // Handle :upper16: and :lower16: assembly prefixes.
+ const MCExpr *E = MO.getExpr();
+ if (E->getKind() == MCExpr::Target) {
+ const ARMMCExpr *ARM16Expr = cast<ARMMCExpr>(E);
+ E = ARM16Expr->getSubExpr();
+
+ MCFixupKind Kind;
+ switch (ARM16Expr->getKind()) {
+ default: assert(0 && "Unsupported ARMFixup");
+ case ARMMCExpr::VK_ARM_HI16:
+ if (!isTargetDarwin() && EvaluateAsPCRel(E))
+ Kind = MCFixupKind(isThumb2()
+ ? ARM::fixup_t2_movt_hi16_pcrel
+ : ARM::fixup_arm_movt_hi16_pcrel);
+ else
+ Kind = MCFixupKind(isThumb2()
+ ? ARM::fixup_t2_movt_hi16
+ : ARM::fixup_arm_movt_hi16);
+ break;
+ case ARMMCExpr::VK_ARM_LO16:
+ if (!isTargetDarwin() && EvaluateAsPCRel(E))
+ Kind = MCFixupKind(isThumb2()
+ ? ARM::fixup_t2_movw_lo16_pcrel
+ : ARM::fixup_arm_movw_lo16_pcrel);
+ else
+ Kind = MCFixupKind(isThumb2()
+ ? ARM::fixup_t2_movw_lo16
+ : ARM::fixup_arm_movw_lo16);
+ break;
+ }
+ Fixups.push_back(MCFixup::Create(0, E, Kind));
+ return 0;
+ };
+
+ llvm_unreachable("Unsupported MCExpr type in MCOperand!");
+ return 0;
+}
+
+uint32_t ARMMCCodeEmitter::
+getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ const MCOperand &MO1 = MI.getOperand(OpIdx+1);
+ const MCOperand &MO2 = MI.getOperand(OpIdx+2);
+ unsigned Rn = getARMRegisterNumbering(MO.getReg());
+ unsigned Rm = getARMRegisterNumbering(MO1.getReg());
+ unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm());
+ bool isAdd = ARM_AM::getAM2Op(MO2.getImm()) == ARM_AM::add;
+ ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm());
+ unsigned SBits = getShiftOp(ShOp);
+
+ // {16-13} = Rn
+ // {12} = isAdd
+ // {11-0} = shifter
+ // {3-0} = Rm
+ // {4} = 0
+ // {6-5} = type
+ // {11-7} = imm
+ uint32_t Binary = Rm;
+ Binary |= Rn << 13;
+ Binary |= SBits << 5;
+ Binary |= ShImm << 7;
+ if (isAdd)
+ Binary |= 1 << 12;
+ return Binary;
+}
+
+uint32_t ARMMCCodeEmitter::
+getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // {17-14} Rn
+ // {13} 1 == imm12, 0 == Rm
+ // {12} isAdd
+ // {11-0} imm12/Rm
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ unsigned Rn = getARMRegisterNumbering(MO.getReg());
+ uint32_t Binary = getAddrMode2OffsetOpValue(MI, OpIdx + 1, Fixups);
+ Binary |= Rn << 14;
+ return Binary;
+}
+
+uint32_t ARMMCCodeEmitter::
+getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // {13} 1 == imm12, 0 == Rm
+ // {12} isAdd
+ // {11-0} imm12/Rm
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ const MCOperand &MO1 = MI.getOperand(OpIdx+1);
+ unsigned Imm = MO1.getImm();
+ bool isAdd = ARM_AM::getAM2Op(Imm) == ARM_AM::add;
+ bool isReg = MO.getReg() != 0;
+ uint32_t Binary = ARM_AM::getAM2Offset(Imm);
+ // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm12
+ if (isReg) {
+ ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(Imm);
+ Binary <<= 7; // Shift amount is bits [11:7]
+ Binary |= getShiftOp(ShOp) << 5; // Shift type is bits [6:5]
+ Binary |= getARMRegisterNumbering(MO.getReg()); // Rm is bits [3:0]
+ }
+ return Binary | (isAdd << 12) | (isReg << 13);
+}
+
+uint32_t ARMMCCodeEmitter::
+getPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // {4} isAdd
+ // {3-0} Rm
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ const MCOperand &MO1 = MI.getOperand(OpIdx+1);
+ bool isAdd = MO1.getImm() != 0;
+ return getARMRegisterNumbering(MO.getReg()) | (isAdd << 4);
+}
+
+uint32_t ARMMCCodeEmitter::
+getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // {9} 1 == imm8, 0 == Rm
+ // {8} isAdd
+ // {7-4} imm7_4/zero
+ // {3-0} imm3_0/Rm
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ const MCOperand &MO1 = MI.getOperand(OpIdx+1);
+ unsigned Imm = MO1.getImm();
+ bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
+ bool isImm = MO.getReg() == 0;
+ uint32_t Imm8 = ARM_AM::getAM3Offset(Imm);
+ // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8
+ if (!isImm)
+ Imm8 = getARMRegisterNumbering(MO.getReg());
+ return Imm8 | (isAdd << 8) | (isImm << 9);
+}
+
+uint32_t ARMMCCodeEmitter::
+getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // {13} 1 == imm8, 0 == Rm
+ // {12-9} Rn
+ // {8} isAdd
+ // {7-4} imm7_4/zero
+ // {3-0} imm3_0/Rm
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ const MCOperand &MO1 = MI.getOperand(OpIdx+1);
+ const MCOperand &MO2 = MI.getOperand(OpIdx+2);
+ unsigned Rn = getARMRegisterNumbering(MO.getReg());
+ unsigned Imm = MO2.getImm();
+ bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
+ bool isImm = MO1.getReg() == 0;
+ uint32_t Imm8 = ARM_AM::getAM3Offset(Imm);
+ // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8
+ if (!isImm)
+ Imm8 = getARMRegisterNumbering(MO1.getReg());
+ return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13);
+}
+
+/// getAddrModeThumbSPOpValue - Encode the t_addrmode_sp operands.
+uint32_t ARMMCCodeEmitter::
+getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // [SP, #imm]
+ // {7-0} = imm8
+ const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
+ assert(MI.getOperand(OpIdx).getReg() == ARM::SP &&
+ "Unexpected base register!");
+
+ // The immediate is already shifted for the implicit zeroes, so no change
+ // here.
+ return MO1.getImm() & 0xff;
+}
+
+/// getAddrModeISOpValue - Encode the t_addrmode_is# operands.
+uint32_t ARMMCCodeEmitter::
+getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // [Rn, #imm]
+ // {7-3} = imm5
+ // {2-0} = Rn
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
+ unsigned Rn = getARMRegisterNumbering(MO.getReg());
+ unsigned Imm5 = MO1.getImm();
+ return ((Imm5 & 0x1f) << 3) | Rn;
+}
+
+/// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands.
+uint32_t ARMMCCodeEmitter::
+getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cp, Fixups);
+ return (MO.getImm() >> 2);
+}
+
+/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm10' operand.
+uint32_t ARMMCCodeEmitter::
+getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // {12-9} = reg
+ // {8} = (U)nsigned (add == '1', sub == '0')
+ // {7-0} = imm8
+ unsigned Reg, Imm8;
+ bool isAdd;
+ // If The first operand isn't a register, we have a label reference.
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ if (!MO.isReg()) {
+ Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
+ Imm8 = 0;
+ isAdd = false; // 'U' bit is handled as part of the fixup.
+
+ assert(MO.isExpr() && "Unexpected machine operand type!");
+ const MCExpr *Expr = MO.getExpr();
+ MCFixupKind Kind;
+ if (isThumb2())
+ Kind = MCFixupKind(ARM::fixup_t2_pcrel_10);
+ else
+ Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
+ Fixups.push_back(MCFixup::Create(0, Expr, Kind));
+
+ ++MCNumCPRelocations;
+ } else {
+ EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups);
+ isAdd = ARM_AM::getAM5Op(Imm8) == ARM_AM::add;
+ }
+
+ uint32_t Binary = ARM_AM::getAM5Offset(Imm8);
+ // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
+ if (isAdd)
+ Binary |= (1 << 8);
+ Binary |= (Reg << 9);
+ return Binary;
+}
+
+unsigned ARMMCCodeEmitter::
+getSORegRegOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg to be
+ // shifted. The second is Rs, the amount to shift by, and the third specifies
+ // the type of the shift.
+ //
+ // {3-0} = Rm.
+ // {4} = 1
+ // {6-5} = type
+ // {11-8} = Rs
+ // {7} = 0
+
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
+ const MCOperand &MO2 = MI.getOperand(OpIdx + 2);
+ ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm());
+
+ // Encode Rm.
+ unsigned Binary = getARMRegisterNumbering(MO.getReg());
+
+ // Encode the shift opcode.
+ unsigned SBits = 0;
+ unsigned Rs = MO1.getReg();
+ if (Rs) {
+ // Set shift operand (bit[7:4]).
+ // LSL - 0001
+ // LSR - 0011
+ // ASR - 0101
+ // ROR - 0111
+ switch (SOpc) {
+ default: llvm_unreachable("Unknown shift opc!");
+ case ARM_AM::lsl: SBits = 0x1; break;
+ case ARM_AM::lsr: SBits = 0x3; break;
+ case ARM_AM::asr: SBits = 0x5; break;
+ case ARM_AM::ror: SBits = 0x7; break;
+ }
+ }
+
+ Binary |= SBits << 4;
+
+ // Encode the shift operation Rs.
+ // Encode Rs bit[11:8].
+ assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0);
+ return Binary | (getARMRegisterNumbering(Rs) << ARMII::RegRsShift);
+}
+
+unsigned ARMMCCodeEmitter::
+getSORegImmOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // Sub-operands are [reg, imm]. The first register is Rm, the reg to be
+ // shifted. The second is the amount to shift by.
+ //
+ // {3-0} = Rm.
+ // {4} = 0
+ // {6-5} = type
+ // {11-7} = imm
+
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
+ ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm());
+
+ // Encode Rm.
+ unsigned Binary = getARMRegisterNumbering(MO.getReg());
+
+ // Encode the shift opcode.
+ unsigned SBits = 0;
+
+ // Set shift operand (bit[6:4]).
+ // LSL - 000
+ // LSR - 010
+ // ASR - 100
+ // ROR - 110
+ // RRX - 110 and bit[11:8] clear.
+ switch (SOpc) {
+ default: llvm_unreachable("Unknown shift opc!");
+ case ARM_AM::lsl: SBits = 0x0; break;
+ case ARM_AM::lsr: SBits = 0x2; break;
+ case ARM_AM::asr: SBits = 0x4; break;
+ case ARM_AM::ror: SBits = 0x6; break;
+ case ARM_AM::rrx:
+ Binary |= 0x60;
+ return Binary;
+ }
+
+ // Encode shift_imm bit[11:7].
+ Binary |= SBits << 4;
+ unsigned Offset = ARM_AM::getSORegOffset(MO1.getImm());
+ assert(Offset && "Offset must be in range 1-32!");
+ if (Offset == 32) Offset = 0;
+ return Binary | (Offset << 7);
+}
+
+
+unsigned ARMMCCodeEmitter::
+getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO1 = MI.getOperand(OpNum);
+ const MCOperand &MO2 = MI.getOperand(OpNum+1);
+ const MCOperand &MO3 = MI.getOperand(OpNum+2);
+
+ // Encoded as [Rn, Rm, imm].
+ // FIXME: Needs fixup support.
+ unsigned Value = getARMRegisterNumbering(MO1.getReg());
+ Value <<= 4;
+ Value |= getARMRegisterNumbering(MO2.getReg());
+ Value <<= 2;
+ Value |= MO3.getImm();
+
+ return Value;
+}
+
+unsigned ARMMCCodeEmitter::
+getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO1 = MI.getOperand(OpNum);
+ const MCOperand &MO2 = MI.getOperand(OpNum+1);
+
+ // FIXME: Needs fixup support.
+ unsigned Value = getARMRegisterNumbering(MO1.getReg());
+
+ // Even though the immediate is 8 bits long, we need 9 bits in order
+ // to represent the (inverse of the) sign bit.
+ Value <<= 9;
+ int32_t tmp = (int32_t)MO2.getImm();
+ if (tmp < 0)
+ tmp = abs(tmp);
+ else
+ Value |= 256; // Set the ADD bit
+ Value |= tmp & 255;
+ return Value;
+}
+
+unsigned ARMMCCodeEmitter::
+getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO1 = MI.getOperand(OpNum);
+
+ // FIXME: Needs fixup support.
+ unsigned Value = 0;
+ int32_t tmp = (int32_t)MO1.getImm();
+ if (tmp < 0)
+ tmp = abs(tmp);
+ else
+ Value |= 256; // Set the ADD bit
+ Value |= tmp & 255;
+ return Value;
+}
+
+unsigned ARMMCCodeEmitter::
+getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO1 = MI.getOperand(OpNum);
+
+ // FIXME: Needs fixup support.
+ unsigned Value = 0;
+ int32_t tmp = (int32_t)MO1.getImm();
+ if (tmp < 0)
+ tmp = abs(tmp);
+ else
+ Value |= 4096; // Set the ADD bit
+ Value |= tmp & 4095;
+ return Value;
+}
+
+unsigned ARMMCCodeEmitter::
+getT2SORegOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // Sub-operands are [reg, imm]. The first register is Rm, the reg to be
+ // shifted. The second is the amount to shift by.
+ //
+ // {3-0} = Rm.
+ // {4} = 0
+ // {6-5} = type
+ // {11-7} = imm
+
+ const MCOperand &MO = MI.getOperand(OpIdx);
+ const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
+ ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm());
+
+ // Encode Rm.
+ unsigned Binary = getARMRegisterNumbering(MO.getReg());
+
+ // Encode the shift opcode.
+ unsigned SBits = 0;
+ // Set shift operand (bit[6:4]).
+ // LSL - 000
+ // LSR - 010
+ // ASR - 100
+ // ROR - 110
+ switch (SOpc) {
+ default: llvm_unreachable("Unknown shift opc!");
+ case ARM_AM::lsl: SBits = 0x0; break;
+ case ARM_AM::lsr: SBits = 0x2; break;
+ case ARM_AM::asr: SBits = 0x4; break;
+ case ARM_AM::rrx: // FALLTHROUGH
+ case ARM_AM::ror: SBits = 0x6; break;
+ }
+
+ Binary |= SBits << 4;
+ if (SOpc == ARM_AM::rrx)
+ return Binary;
+
+ // Encode shift_imm bit[11:7].
+ return Binary | ARM_AM::getSORegOffset(MO1.getImm()) << 7;
+}
+
+unsigned ARMMCCodeEmitter::
+getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // 10 bits. lower 5 bits are are the lsb of the mask, high five bits are the
+ // msb of the mask.
+ const MCOperand &MO = MI.getOperand(Op);
+ uint32_t v = ~MO.getImm();
+ uint32_t lsb = CountTrailingZeros_32(v);
+ uint32_t msb = (32 - CountLeadingZeros_32 (v)) - 1;
+ assert (v != 0 && lsb < 32 && msb < 32 && "Illegal bitfield mask!");
+ return lsb | (msb << 5);
+}
+
+unsigned ARMMCCodeEmitter::
+getRegisterListOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // VLDM/VSTM:
+ // {12-8} = Vd
+ // {7-0} = Number of registers
+ //
+ // LDM/STM:
+ // {15-0} = Bitfield of GPRs.
+ unsigned Reg = MI.getOperand(Op).getReg();
+ bool SPRRegs = llvm::ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg);
+ bool DPRRegs = llvm::ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg);
+
+ unsigned Binary = 0;
+
+ if (SPRRegs || DPRRegs) {
+ // VLDM/VSTM
+ unsigned RegNo = getARMRegisterNumbering(Reg);
+ unsigned NumRegs = (MI.getNumOperands() - Op) & 0xff;
+ Binary |= (RegNo & 0x1f) << 8;
+ if (SPRRegs)
+ Binary |= NumRegs;
+ else
+ Binary |= NumRegs * 2;
+ } else {
+ for (unsigned I = Op, E = MI.getNumOperands(); I < E; ++I) {
+ unsigned RegNo = getARMRegisterNumbering(MI.getOperand(I).getReg());
+ Binary |= 1 << RegNo;
+ }
+ }
+
+ return Binary;
+}
+
+/// getAddrMode6AddressOpValue - Encode an addrmode6 register number along
+/// with the alignment operand.
+unsigned ARMMCCodeEmitter::
+getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &Reg = MI.getOperand(Op);
+ const MCOperand &Imm = MI.getOperand(Op + 1);
+
+ unsigned RegNo = getARMRegisterNumbering(Reg.getReg());
+ unsigned Align = 0;
+
+ switch (Imm.getImm()) {
+ default: break;
+ case 2:
+ case 4:
+ case 8: Align = 0x01; break;
+ case 16: Align = 0x02; break;
+ case 32: Align = 0x03; break;
+ }
+
+ return RegNo | (Align << 4);
+}
+
+/// getAddrMode6OneLane32AddressOpValue - Encode an addrmode6 register number
+/// along with the alignment operand for use in VST1 and VLD1 with size 32.
+unsigned ARMMCCodeEmitter::
+getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &Reg = MI.getOperand(Op);
+ const MCOperand &Imm = MI.getOperand(Op + 1);
+
+ unsigned RegNo = getARMRegisterNumbering(Reg.getReg());
+ unsigned Align = 0;
+
+ switch (Imm.getImm()) {
+ default: break;
+ case 2:
+ case 4:
+ case 8:
+ case 16: Align = 0x00; break;
+ case 32: Align = 0x03; break;
+ }
+
+ return RegNo | (Align << 4);
+}
+
+
+/// getAddrMode6DupAddressOpValue - Encode an addrmode6 register number and
+/// alignment operand for use in VLD-dup instructions. This is the same as
+/// getAddrMode6AddressOpValue except for the alignment encoding, which is
+/// different for VLD4-dup.
+unsigned ARMMCCodeEmitter::
+getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &Reg = MI.getOperand(Op);
+ const MCOperand &Imm = MI.getOperand(Op + 1);
+
+ unsigned RegNo = getARMRegisterNumbering(Reg.getReg());
+ unsigned Align = 0;
+
+ switch (Imm.getImm()) {
+ default: break;
+ case 2:
+ case 4:
+ case 8: Align = 0x01; break;
+ case 16: Align = 0x03; break;
+ }
+
+ return RegNo | (Align << 4);
+}
+
+unsigned ARMMCCodeEmitter::
+getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO = MI.getOperand(Op);
+ if (MO.getReg() == 0) return 0x0D;
+ return MO.getReg();
+}
+
+unsigned ARMMCCodeEmitter::
+getShiftRight8Imm(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ return 8 - MI.getOperand(Op).getImm();
+}
+
+unsigned ARMMCCodeEmitter::
+getShiftRight16Imm(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ return 16 - MI.getOperand(Op).getImm();
+}
+
+unsigned ARMMCCodeEmitter::
+getShiftRight32Imm(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ return 32 - MI.getOperand(Op).getImm();
+}
+
+unsigned ARMMCCodeEmitter::
+getShiftRight64Imm(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ return 64 - MI.getOperand(Op).getImm();
+}
+
+void ARMMCCodeEmitter::
+EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // Pseudo instructions don't get encoded.
+ const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
+ uint64_t TSFlags = Desc.TSFlags;
+ if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo)
+ return;
+
+ int Size;
+ if (Desc.getSize() == 2 || Desc.getSize() == 4)
+ Size = Desc.getSize();
+ else
+ llvm_unreachable("Unexpected instruction size!");
+
+ uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
+ // Thumb 32-bit wide instructions need to emit the high order halfword
+ // first.
+ if (isThumb() && Size == 4) {
+ EmitConstant(Binary >> 16, 2, OS);
+ EmitConstant(Binary & 0xffff, 2, OS);
+ } else
+ EmitConstant(Binary, Size, OS);
+ ++MCNumEmitted; // Keep track of the # of mi's emitted.
+}
+
+#include "ARMGenMCCodeEmitter.inc"
diff --git a/lib/Target/ARM/ARMMCExpr.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp
index 2727ba8..2727ba8 100644
--- a/lib/Target/ARM/ARMMCExpr.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp
diff --git a/lib/Target/ARM/ARMMCExpr.h b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h
index 0a2e883..0a2e883 100644
--- a/lib/Target/ARM/ARMMCExpr.h
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCExpr.h
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
index f8fcf2b..a55c410 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
@@ -13,10 +13,16 @@
#include "ARMMCTargetDesc.h"
#include "ARMMCAsmInfo.h"
+#include "ARMBaseInfo.h"
+#include "InstPrinter/ARMInstPrinter.h"
+#include "llvm/MC/MCCodeGenInfo.h"
+#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_REGINFO_MC_DESC
#include "ARMGenRegisterInfo.inc"
@@ -35,7 +41,7 @@ std::string ARM_MC::ParseARMTriple(StringRef TT) {
unsigned Len = TT.size();
unsigned Idx = 0;
- // FIXME: Enahnce Triple helper class to extract ARM version.
+ // FIXME: Enhance Triple helper class to extract ARM version.
bool isThumb = false;
if (Len >= 5 && TT.substr(0, 4) == "armv")
Idx = 4;
@@ -50,18 +56,21 @@ std::string ARM_MC::ParseARMTriple(StringRef TT) {
unsigned SubVer = TT[Idx];
if (SubVer >= '7' && SubVer <= '9') {
if (Len >= Idx+2 && TT[Idx+1] == 'm') {
- // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv
- ARMArchFeature = "+v7,+noarm,+db,+hwdiv";
+ // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureMClass
+ ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+mclass";
} else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') {
// v7em: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2,
- // FeatureT2XtPk
- ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk";
+ // FeatureT2XtPk, FeatureMClass
+ ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk,+mclass";
} else
- // v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2
- ARMArchFeature = "+v7,+neon,+db,+t2dsp";
+ // v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk
+ ARMArchFeature = "+v7,+neon,+db,+t2dsp,+t2xtpk";
} else if (SubVer == '6') {
if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
ARMArchFeature = "+v6t2";
+ else if (Len >= Idx+2 && TT[Idx+1] == 'm')
+ // v6m: FeatureNoARM, FeatureMClass
+ ARMArchFeature = "+v6t2,+noarm,+mclass";
else
ARMArchFeature = "+v6";
} else if (SubVer == '5') {
@@ -80,6 +89,14 @@ std::string ARM_MC::ParseARMTriple(StringRef TT) {
ARMArchFeature += ",+thumb-mode";
}
+ Triple TheTriple(TT);
+ if (TheTriple.getOS() == Triple::NativeClient) {
+ if (ARMArchFeature.empty())
+ ARMArchFeature = "+nacl-mode";
+ else
+ ARMArchFeature += ",+nacl-mode";
+ }
+
return ARMArchFeature;
}
@@ -98,36 +115,18 @@ MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-// Force static initialization.
-extern "C" void LLVMInitializeARMMCSubtargetInfo() {
- TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget,
- ARM_MC::createARMMCSubtargetInfo);
- TargetRegistry::RegisterMCSubtargetInfo(TheThumbTarget,
- ARM_MC::createARMMCSubtargetInfo);
-}
-
static MCInstrInfo *createARMMCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
InitARMMCInstrInfo(X);
return X;
}
-extern "C" void LLVMInitializeARMMCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(TheARMTarget, createARMMCInstrInfo);
- TargetRegistry::RegisterMCInstrInfo(TheThumbTarget, createARMMCInstrInfo);
-}
-
-static MCRegisterInfo *createARMMCRegisterInfo() {
+static MCRegisterInfo *createARMMCRegisterInfo(StringRef Triple) {
MCRegisterInfo *X = new MCRegisterInfo();
- InitARMMCRegisterInfo(X);
+ InitARMMCRegisterInfo(X, ARM::LR);
return X;
}
-extern "C" void LLVMInitializeARMMCRegInfo() {
- TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo);
- TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo);
-}
-
static MCAsmInfo *createARMMCAsmInfo(const Target &T, StringRef TT) {
Triple TheTriple(TT);
@@ -137,8 +136,128 @@ static MCAsmInfo *createARMMCAsmInfo(const Target &T, StringRef TT) {
return new ARMELFMCAsmInfo();
}
-extern "C" void LLVMInitializeARMMCAsmInfo() {
- // Register the target asm info.
+static MCCodeGenInfo *createARMMCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+ if (RM == Reloc::Default) {
+ Triple TheTriple(TT);
+ // Default relocation model on Darwin is PIC, not DynamicNoPIC.
+ RM = TheTriple.isOSDarwin() ? Reloc::PIC_ : Reloc::DynamicNoPIC;
+ }
+ X->InitMCCodeGenInfo(RM, CM);
+ return X;
+}
+
+// This is duplicated code. Refactor this.
+static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
+ MCContext &Ctx, MCAsmBackend &MAB,
+ raw_ostream &OS,
+ MCCodeEmitter *Emitter,
+ bool RelaxAll,
+ bool NoExecStack) {
+ Triple TheTriple(TT);
+
+ if (TheTriple.isOSDarwin())
+ return createMachOStreamer(Ctx, MAB, OS, Emitter, RelaxAll);
+
+ if (TheTriple.isOSWindows()) {
+ llvm_unreachable("ARM does not support Windows COFF format");
+ return NULL;
+ }
+
+ return createELFStreamer(Ctx, MAB, OS, Emitter, RelaxAll, NoExecStack);
+}
+
+static MCInstPrinter *createARMMCInstPrinter(const Target &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI) {
+ if (SyntaxVariant == 0)
+ return new ARMInstPrinter(MAI, STI);
+ return 0;
+}
+
+namespace {
+
+class ARMMCInstrAnalysis : public MCInstrAnalysis {
+public:
+ ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
+
+ virtual bool isUnconditionalBranch(const MCInst &Inst) const {
+ // BCCs with the "always" predicate are unconditional branches.
+ if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
+ return true;
+ return MCInstrAnalysis::isUnconditionalBranch(Inst);
+ }
+
+ virtual bool isConditionalBranch(const MCInst &Inst) const {
+ // BCCs with the "always" predicate are unconditional branches.
+ if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
+ return false;
+ return MCInstrAnalysis::isConditionalBranch(Inst);
+ }
+
+ uint64_t evaluateBranch(const MCInst &Inst, uint64_t Addr,
+ uint64_t Size) const {
+ // We only handle PCRel branches for now.
+ if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)
+ return -1ULL;
+
+ int64_t Imm = Inst.getOperand(0).getImm();
+ // FIXME: This is not right for thumb.
+ return Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
+ }
+};
+
+}
+
+static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
+ return new ARMMCInstrAnalysis(Info);
+}
+
+// Force static initialization.
+extern "C" void LLVMInitializeARMTargetMC() {
+ // Register the MC asm info.
RegisterMCAsmInfoFn A(TheARMTarget, createARMMCAsmInfo);
RegisterMCAsmInfoFn B(TheThumbTarget, createARMMCAsmInfo);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(TheARMTarget, createARMMCCodeGenInfo);
+ TargetRegistry::RegisterMCCodeGenInfo(TheThumbTarget, createARMMCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheARMTarget, createARMMCInstrInfo);
+ TargetRegistry::RegisterMCInstrInfo(TheThumbTarget, createARMMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo);
+ TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget,
+ ARM_MC::createARMMCSubtargetInfo);
+ TargetRegistry::RegisterMCSubtargetInfo(TheThumbTarget,
+ ARM_MC::createARMMCSubtargetInfo);
+
+ // Register the MC instruction analyzer.
+ TargetRegistry::RegisterMCInstrAnalysis(TheARMTarget,
+ createARMMCInstrAnalysis);
+ TargetRegistry::RegisterMCInstrAnalysis(TheThumbTarget,
+ createARMMCInstrAnalysis);
+
+ // Register the MC Code Emitter
+ TargetRegistry::RegisterMCCodeEmitter(TheARMTarget, createARMMCCodeEmitter);
+ TargetRegistry::RegisterMCCodeEmitter(TheThumbTarget, createARMMCCodeEmitter);
+
+ // Register the asm backend.
+ TargetRegistry::RegisterMCAsmBackend(TheARMTarget, createARMAsmBackend);
+ TargetRegistry::RegisterMCAsmBackend(TheThumbTarget, createARMAsmBackend);
+
+ // Register the object streamer.
+ TargetRegistry::RegisterMCObjectStreamer(TheARMTarget, createMCStreamer);
+ TargetRegistry::RegisterMCObjectStreamer(TheThumbTarget, createMCStreamer);
+
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter);
+ TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter);
}
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h
index 74701e3..9b3d3bd 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h
@@ -14,12 +14,19 @@
#ifndef ARMMCTARGETDESC_H
#define ARMMCTARGETDESC_H
+#include "llvm/Support/DataTypes.h"
#include <string>
namespace llvm {
+class MCAsmBackend;
+class MCCodeEmitter;
+class MCContext;
+class MCInstrInfo;
+class MCObjectWriter;
class MCSubtargetInfo;
-class Target;
class StringRef;
+class Target;
+class raw_ostream;
extern Target TheARMTarget, TheThumbTarget;
@@ -33,6 +40,18 @@ namespace ARM_MC {
StringRef FS);
}
+MCCodeEmitter *createARMMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx);
+
+MCAsmBackend *createARMAsmBackend(const Target &T, StringRef TT);
+
+/// createARMMachObjectWriter - Construct an ARM Mach-O object writer.
+MCObjectWriter *createARMMachObjectWriter(raw_ostream &OS,
+ bool Is64Bit,
+ uint32_t CPUType,
+ uint32_t CPUSubtype);
+
} // End llvm namespace
// Defines symbolic names for ARM registers. This defines a mapping from
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp
new file mode 100644
index 0000000..352c73e
--- /dev/null
+++ b/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp
@@ -0,0 +1,388 @@
+//===-- ARMMachObjectWriter.cpp - ARM Mach Object Writer ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/ARMBaseInfo.h"
+#include "MCTargetDesc/ARMFixupKinds.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCAsmLayout.h"
+#include "llvm/MC/MCMachObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Object/MachOFormat.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace llvm;
+using namespace llvm::object;
+
+namespace {
+class ARMMachObjectWriter : public MCMachObjectTargetWriter {
+ void RecordARMScatteredRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ unsigned Log2Size,
+ uint64_t &FixedValue);
+ void RecordARMMovwMovtRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup, MCValue Target,
+ uint64_t &FixedValue);
+
+public:
+ ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType,
+ uint32_t CPUSubtype)
+ : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
+ /*UseAggressiveSymbolFolding=*/true) {}
+
+ void RecordRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm, const MCAsmLayout &Layout,
+ const MCFragment *Fragment, const MCFixup &Fixup,
+ MCValue Target, uint64_t &FixedValue);
+};
+}
+
+static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
+ unsigned &Log2Size) {
+ RelocType = unsigned(macho::RIT_Vanilla);
+ Log2Size = ~0U;
+
+ switch (Kind) {
+ default:
+ return false;
+
+ case FK_Data_1:
+ Log2Size = llvm::Log2_32(1);
+ return true;
+ case FK_Data_2:
+ Log2Size = llvm::Log2_32(2);
+ return true;
+ case FK_Data_4:
+ Log2Size = llvm::Log2_32(4);
+ return true;
+ case FK_Data_8:
+ Log2Size = llvm::Log2_32(8);
+ return true;
+
+ // Handle 24-bit branch kinds.
+ case ARM::fixup_arm_ldst_pcrel_12:
+ case ARM::fixup_arm_pcrel_10:
+ case ARM::fixup_arm_adr_pcrel_12:
+ case ARM::fixup_arm_condbranch:
+ case ARM::fixup_arm_uncondbranch:
+ RelocType = unsigned(macho::RIT_ARM_Branch24Bit);
+ // Report as 'long', even though that is not quite accurate.
+ Log2Size = llvm::Log2_32(4);
+ return true;
+
+ // Handle Thumb branches.
+ case ARM::fixup_arm_thumb_br:
+ RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit);
+ Log2Size = llvm::Log2_32(2);
+ return true;
+
+ case ARM::fixup_t2_uncondbranch:
+ case ARM::fixup_arm_thumb_bl:
+ case ARM::fixup_arm_thumb_blx:
+ RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit);
+ Log2Size = llvm::Log2_32(4);
+ return true;
+
+ case ARM::fixup_arm_movt_hi16:
+ case ARM::fixup_arm_movt_hi16_pcrel:
+ case ARM::fixup_t2_movt_hi16:
+ case ARM::fixup_t2_movt_hi16_pcrel:
+ RelocType = unsigned(macho::RIT_ARM_HalfDifference);
+ // Report as 'long', even though that is not quite accurate.
+ Log2Size = llvm::Log2_32(4);
+ return true;
+
+ case ARM::fixup_arm_movw_lo16:
+ case ARM::fixup_arm_movw_lo16_pcrel:
+ case ARM::fixup_t2_movw_lo16:
+ case ARM::fixup_t2_movw_lo16_pcrel:
+ RelocType = unsigned(macho::RIT_ARM_Half);
+ // Report as 'long', even though that is not quite accurate.
+ Log2Size = llvm::Log2_32(4);
+ return true;
+ }
+}
+
+void ARMMachObjectWriter::
+RecordARMMovwMovtRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ uint64_t &FixedValue) {
+ uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
+ unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
+ unsigned Type = macho::RIT_ARM_Half;
+
+ // See <reloc.h>.
+ const MCSymbol *A = &Target.getSymA()->getSymbol();
+ MCSymbolData *A_SD = &Asm.getSymbolData(*A);
+
+ if (!A_SD->getFragment())
+ report_fatal_error("symbol '" + A->getName() +
+ "' can not be undefined in a subtraction expression");
+
+ uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
+ uint32_t Value2 = 0;
+ uint64_t SecAddr =
+ Writer->getSectionAddress(A_SD->getFragment()->getParent());
+ FixedValue += SecAddr;
+
+ if (const MCSymbolRefExpr *B = Target.getSymB()) {
+ MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
+
+ if (!B_SD->getFragment())
+ report_fatal_error("symbol '" + B->getSymbol().getName() +
+ "' can not be undefined in a subtraction expression");
+
+ // Select the appropriate difference relocation type.
+ Type = macho::RIT_ARM_HalfDifference;
+ Value2 = Writer->getSymbolAddress(B_SD, Layout);
+ FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
+ }
+
+ // Relocations are written out in reverse order, so the PAIR comes first.
+ // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
+ //
+ // For these two r_type relocations they always have a pair following them and
+ // the r_length bits are used differently. The encoding of the r_length is as
+ // follows:
+ // low bit of r_length:
+ // 0 - :lower16: for movw instructions
+ // 1 - :upper16: for movt instructions
+ // high bit of r_length:
+ // 0 - arm instructions
+ // 1 - thumb instructions
+ // the other half of the relocated expression is in the following pair
+ // relocation entry in the the low 16 bits of r_address field.
+ unsigned ThumbBit = 0;
+ unsigned MovtBit = 0;
+ switch ((unsigned)Fixup.getKind()) {
+ default: break;
+ case ARM::fixup_arm_movt_hi16:
+ case ARM::fixup_arm_movt_hi16_pcrel:
+ MovtBit = 1;
+ break;
+ case ARM::fixup_t2_movt_hi16:
+ case ARM::fixup_t2_movt_hi16_pcrel:
+ MovtBit = 1;
+ // Fallthrough
+ case ARM::fixup_t2_movw_lo16:
+ case ARM::fixup_t2_movw_lo16_pcrel:
+ ThumbBit = 1;
+ break;
+ }
+
+
+ if (Type == macho::RIT_ARM_HalfDifference) {
+ uint32_t OtherHalf = MovtBit
+ ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16);
+
+ macho::RelocationEntry MRE;
+ MRE.Word0 = ((OtherHalf << 0) |
+ (macho::RIT_Pair << 24) |
+ (MovtBit << 28) |
+ (ThumbBit << 29) |
+ (IsPCRel << 30) |
+ macho::RF_Scattered);
+ MRE.Word1 = Value2;
+ Writer->addRelocation(Fragment->getParent(), MRE);
+ }
+
+ macho::RelocationEntry MRE;
+ MRE.Word0 = ((FixupOffset << 0) |
+ (Type << 24) |
+ (MovtBit << 28) |
+ (ThumbBit << 29) |
+ (IsPCRel << 30) |
+ macho::RF_Scattered);
+ MRE.Word1 = Value;
+ Writer->addRelocation(Fragment->getParent(), MRE);
+}
+
+void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ unsigned Log2Size,
+ uint64_t &FixedValue) {
+ uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
+ unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
+ unsigned Type = macho::RIT_Vanilla;
+
+ // See <reloc.h>.
+ const MCSymbol *A = &Target.getSymA()->getSymbol();
+ MCSymbolData *A_SD = &Asm.getSymbolData(*A);
+
+ if (!A_SD->getFragment())
+ report_fatal_error("symbol '" + A->getName() +
+ "' can not be undefined in a subtraction expression");
+
+ uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
+ uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
+ FixedValue += SecAddr;
+ uint32_t Value2 = 0;
+
+ if (const MCSymbolRefExpr *B = Target.getSymB()) {
+ MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
+
+ if (!B_SD->getFragment())
+ report_fatal_error("symbol '" + B->getSymbol().getName() +
+ "' can not be undefined in a subtraction expression");
+
+ // Select the appropriate difference relocation type.
+ Type = macho::RIT_Difference;
+ Value2 = Writer->getSymbolAddress(B_SD, Layout);
+ FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
+ }
+
+ // Relocations are written out in reverse order, so the PAIR comes first.
+ if (Type == macho::RIT_Difference ||
+ Type == macho::RIT_Generic_LocalDifference) {
+ macho::RelocationEntry MRE;
+ MRE.Word0 = ((0 << 0) |
+ (macho::RIT_Pair << 24) |
+ (Log2Size << 28) |
+ (IsPCRel << 30) |
+ macho::RF_Scattered);
+ MRE.Word1 = Value2;
+ Writer->addRelocation(Fragment->getParent(), MRE);
+ }
+
+ macho::RelocationEntry MRE;
+ MRE.Word0 = ((FixupOffset << 0) |
+ (Type << 24) |
+ (Log2Size << 28) |
+ (IsPCRel << 30) |
+ macho::RF_Scattered);
+ MRE.Word1 = Value;
+ Writer->addRelocation(Fragment->getParent(), MRE);
+}
+
+void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ uint64_t &FixedValue) {
+ unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
+ unsigned Log2Size;
+ unsigned RelocType = macho::RIT_Vanilla;
+ if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) {
+ report_fatal_error("unknown ARM fixup kind!");
+ return;
+ }
+
+ // If this is a difference or a defined symbol plus an offset, then we need a
+ // scattered relocation entry. Differences always require scattered
+ // relocations.
+ if (Target.getSymB()) {
+ if (RelocType == macho::RIT_ARM_Half ||
+ RelocType == macho::RIT_ARM_HalfDifference)
+ return RecordARMMovwMovtRelocation(Writer, Asm, Layout, Fragment, Fixup,
+ Target, FixedValue);
+ return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
+ Target, Log2Size, FixedValue);
+ }
+
+ // Get the symbol data, if any.
+ MCSymbolData *SD = 0;
+ if (Target.getSymA())
+ SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
+
+ // FIXME: For other platforms, we need to use scattered relocations for
+ // internal relocations with offsets. If this is an internal relocation with
+ // an offset, it also needs a scattered relocation entry.
+ //
+ // Is this right for ARM?
+ uint32_t Offset = Target.getConstant();
+ if (IsPCRel && RelocType == macho::RIT_Vanilla)
+ Offset += 1 << Log2Size;
+ if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD))
+ return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
+ Target, Log2Size, FixedValue);
+
+ // See <reloc.h>.
+ uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
+ unsigned Index = 0;
+ unsigned IsExtern = 0;
+ unsigned Type = 0;
+
+ if (Target.isAbsolute()) { // constant
+ // FIXME!
+ report_fatal_error("FIXME: relocations to absolute targets "
+ "not yet implemented");
+ } else {
+ // Resolve constant variables.
+ if (SD->getSymbol().isVariable()) {
+ int64_t Res;
+ if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
+ Res, Layout, Writer->getSectionAddressMap())) {
+ FixedValue = Res;
+ return;
+ }
+ }
+
+ // Check whether we need an external or internal relocation.
+ if (Writer->doesSymbolRequireExternRelocation(SD)) {
+ IsExtern = 1;
+ Index = SD->getIndex();
+
+ // For external relocations, make sure to offset the fixup value to
+ // compensate for the addend of the symbol address, if it was
+ // undefined. This occurs with weak definitions, for example.
+ if (!SD->Symbol->isUndefined())
+ FixedValue -= Layout.getSymbolOffset(SD);
+ } else {
+ // The index is the section ordinal (1-based).
+ const MCSectionData &SymSD = Asm.getSectionData(
+ SD->getSymbol().getSection());
+ Index = SymSD.getOrdinal() + 1;
+ FixedValue += Writer->getSectionAddress(&SymSD);
+ }
+ if (IsPCRel)
+ FixedValue -= Writer->getSectionAddress(Fragment->getParent());
+
+ // The type is determined by the fixup kind.
+ Type = RelocType;
+ }
+
+ // struct relocation_info (8 bytes)
+ macho::RelocationEntry MRE;
+ MRE.Word0 = FixupOffset;
+ MRE.Word1 = ((Index << 0) |
+ (IsPCRel << 24) |
+ (Log2Size << 25) |
+ (IsExtern << 27) |
+ (Type << 28));
+ Writer->addRelocation(Fragment->getParent(), MRE);
+}
+
+MCObjectWriter *llvm::createARMMachObjectWriter(raw_ostream &OS,
+ bool Is64Bit,
+ uint32_t CPUType,
+ uint32_t CPUSubtype) {
+ return createMachObjectWriter(new ARMMachObjectWriter(Is64Bit,
+ CPUType,
+ CPUSubtype),
+ OS, /*IsLittleEndian=*/true);
+}
diff --git a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
index 68daf42..adc37cb 100644
--- a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
@@ -1,7 +1,19 @@
add_llvm_library(LLVMARMDesc
- ARMMCTargetDesc.cpp
+ ARMAsmBackend.cpp
ARMMCAsmInfo.cpp
+ ARMMCCodeEmitter.cpp
+ ARMMCExpr.cpp
+ ARMMCTargetDesc.cpp
+ ARMMachObjectWriter.cpp
)
+add_dependencies(LLVMARMDesc ARMCommonTableGen)
# Hack: we need to include 'main' target directory to grab private headers
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..)
+
+add_llvm_library_dependencies(LLVMARMDesc
+ LLVMARMInfo
+ LLVMARMAsmPrinter
+ LLVMMC
+ LLVMSupport
+ )
diff --git a/lib/Target/ARM/Makefile b/lib/Target/ARM/Makefile
index eb8c603..3e48ed1 100644
--- a/lib/Target/ARM/Makefile
+++ b/lib/Target/ARM/Makefile
@@ -16,9 +16,8 @@ BUILT_SOURCES = ARMGenRegisterInfo.inc ARMGenInstrInfo.inc \
ARMGenAsmWriter.inc ARMGenAsmMatcher.inc \
ARMGenDAGISel.inc ARMGenSubtargetInfo.inc \
ARMGenCodeEmitter.inc ARMGenCallingConv.inc \
- ARMGenDecoderTables.inc ARMGenEDInfo.inc \
- ARMGenFastISel.inc ARMGenMCCodeEmitter.inc \
- ARMGenMCPseudoLowering.inc
+ ARMGenEDInfo.inc ARMGenFastISel.inc ARMGenMCCodeEmitter.inc \
+ ARMGenMCPseudoLowering.inc ARMGenDisassemblerTables.inc
DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc
diff --git a/lib/Target/ARM/NEONMoveFix.cpp b/lib/Target/ARM/NEONMoveFix.cpp
deleted file mode 100644
index c85d1e9..0000000
--- a/lib/Target/ARM/NEONMoveFix.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-//===-- NEONMoveFix.cpp - Convert vfp reg-reg moves into neon ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "neon-mov-fix"
-#include "ARM.h"
-#include "ARMMachineFunctionInfo.h"
-#include "ARMInstrInfo.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-STATISTIC(NumVMovs, "Number of reg-reg moves converted");
-
-namespace {
- struct NEONMoveFixPass : public MachineFunctionPass {
- static char ID;
- NEONMoveFixPass() : MachineFunctionPass(ID) {}
-
- virtual bool runOnMachineFunction(MachineFunction &Fn);
-
- virtual const char *getPassName() const {
- return "NEON reg-reg move conversion";
- }
-
- private:
- const TargetRegisterInfo *TRI;
- const ARMBaseInstrInfo *TII;
- bool isA8;
-
- typedef DenseMap<unsigned, const MachineInstr*> RegMap;
-
- bool InsertMoves(MachineBasicBlock &MBB);
- };
- char NEONMoveFixPass::ID = 0;
-}
-
-static bool inNEONDomain(unsigned Domain, bool isA8) {
- return (Domain & ARMII::DomainNEON) ||
- (isA8 && (Domain & ARMII::DomainNEONA8));
-}
-
-bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) {
- RegMap Defs;
- bool Modified = false;
-
- // Walk over MBB tracking the def points of the registers.
- MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end();
- MachineBasicBlock::iterator NextMII;
- for (; MII != E; MII = NextMII) {
- NextMII = llvm::next(MII);
- MachineInstr *MI = &*MII;
-
- if (MI->getOpcode() == ARM::VMOVD &&
- !TII->isPredicated(MI)) {
- unsigned SrcReg = MI->getOperand(1).getReg();
- // If we do not find an instruction defining the reg, this means the
- // register should be live-in for this BB. It's always to better to use
- // NEON reg-reg moves.
- unsigned Domain = ARMII::DomainNEON;
- RegMap::iterator DefMI = Defs.find(SrcReg);
- if (DefMI != Defs.end()) {
- Domain = DefMI->second->getDesc().TSFlags & ARMII::DomainMask;
- // Instructions in general domain are subreg accesses.
- // Map them to NEON reg-reg moves.
- if (Domain == ARMII::DomainGeneral)
- Domain = ARMII::DomainNEON;
- }
-
- if (inNEONDomain(Domain, isA8)) {
- // Convert VMOVD to VORRd
- unsigned DestReg = MI->getOperand(0).getReg();
-
- DEBUG({errs() << "vmov convert: "; MI->dump();});
-
- // It's safe to ignore imp-defs / imp-uses here, since:
- // - We're running late, no intelligent condegen passes should be run
- // afterwards
- // - The imp-defs / imp-uses are superregs only, we don't care about
- // them.
- AddDefaultPred(BuildMI(MBB, *MI, MI->getDebugLoc(),
- TII->get(ARM::VORRd), DestReg)
- .addReg(SrcReg).addReg(SrcReg));
- MBB.erase(MI);
- MachineBasicBlock::iterator I = prior(NextMII);
- MI = &*I;
-
- DEBUG({errs() << " into: "; MI->dump();});
-
- Modified = true;
- ++NumVMovs;
- } else {
- assert((Domain & ARMII::DomainVFP) && "Invalid domain!");
- // Do nothing.
- }
- }
-
- // Update def information.
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- const MachineOperand& MO = MI->getOperand(i);
- if (!MO.isReg() || !MO.isDef())
- continue;
- unsigned MOReg = MO.getReg();
-
- Defs[MOReg] = MI;
- // Catch aliases as well.
- for (const unsigned *R = TRI->getAliasSet(MOReg); *R; ++R)
- Defs[*R] = MI;
- }
- }
-
- return Modified;
-}
-
-bool NEONMoveFixPass::runOnMachineFunction(MachineFunction &Fn) {
- ARMFunctionInfo *AFI = Fn.getInfo<ARMFunctionInfo>();
- const TargetMachine &TM = Fn.getTarget();
-
- if (AFI->isThumb1OnlyFunction())
- return false;
-
- TRI = TM.getRegisterInfo();
- TII = static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
- isA8 = TM.getSubtarget<ARMSubtarget>().isCortexA8();
-
- bool Modified = false;
- for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
- ++MFI) {
- MachineBasicBlock &MBB = *MFI;
- Modified |= InsertMoves(MBB);
- }
-
- return Modified;
-}
-
-/// createNEONMoveFixPass - Returns an instance of the NEON reg-reg moves fix
-/// pass.
-FunctionPass *llvm::createNEONMoveFixPass() {
- return new NEONMoveFixPass();
-}
diff --git a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
index 163a0a9..500e3de 100644
--- a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
+++ b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "ARM.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::TheARMTarget, llvm::TheThumbTarget;
diff --git a/lib/Target/ARM/TargetInfo/CMakeLists.txt b/lib/Target/ARM/TargetInfo/CMakeLists.txt
index 3910bb0..8b38b13 100644
--- a/lib/Target/ARM/TargetInfo/CMakeLists.txt
+++ b/lib/Target/ARM/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMARMInfo
ARMTargetInfo.cpp
)
-add_dependencies(LLVMARMInfo ARMCodeGenTable_gen)
+add_dependencies(LLVMARMInfo ARMCommonTableGen)
+
+add_llvm_library_dependencies(LLVMARMInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
diff --git a/lib/Target/ARM/Thumb1FrameLowering.cpp b/lib/Target/ARM/Thumb1FrameLowering.cpp
index c258870..d848177 100644
--- a/lib/Target/ARM/Thumb1FrameLowering.cpp
+++ b/lib/Target/ARM/Thumb1FrameLowering.cpp
@@ -21,7 +21,7 @@
using namespace llvm;
-bool Thumb1FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
+bool Thumb1FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const{
const MachineFrameInfo *FFI = MF.getFrameInfo();
unsigned CFSize = FFI->getMaxCallFrameSize();
// It's not always a good idea to include the call frame as part of the
@@ -133,9 +133,9 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const {
// Adjust FP so it point to the stack slot that contains the previous FP.
if (hasFP(MF)) {
- BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr)
+ AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr)
.addFrameIndex(FramePtrSpillFI).addImm(0)
- .setMIFlags(MachineInstr::FrameSetup);
+ .setMIFlags(MachineInstr::FrameSetup));
if (NumBytes > 508)
// If offset is > 508 then sp cannot be adjusted in a single instruction,
// try restoring from fp instead.
@@ -155,6 +155,11 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const {
AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
AFI->setDPRCalleeSavedAreaSize(DPRCSSize);
+ // Thumb1 does not currently support dynamic stack realignment. Report a
+ // fatal error rather then silently generate bad code.
+ if (RegInfo->needsStackRealignment(MF))
+ report_fatal_error("Dynamic stack realignment not supported for thumb1.");
+
// If we need a base pointer, set it up here. It's whatever the value
// of the stack pointer is at this point. Any variable size objects
// will be allocated after this, so we can still use the base pointer
diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp
index 4eb0b6c..e8ed482 100644
--- a/lib/Target/ARM/Thumb1RegisterInfo.cpp
+++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp
@@ -13,12 +13,12 @@
//===----------------------------------------------------------------------===//
#include "ARM.h"
-#include "ARMAddressingModes.h"
#include "ARMBaseInstrInfo.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMSubtarget.h"
#include "Thumb1InstrInfo.h"
#include "Thumb1RegisterInfo.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/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetMachine.h"
@@ -182,7 +181,6 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
int Opc = 0;
int ExtraOpc = 0;
bool NeedCC = false;
- bool NeedPred = false;
if (DestReg == BaseReg && BaseReg == ARM::SP) {
assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
@@ -217,7 +215,7 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
} else {
Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
NumBits = 8;
- NeedPred = NeedCC = true;
+ NeedCC = true;
}
isTwoAddr = true;
}
@@ -241,7 +239,8 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
Bytes -= ThisVal;
const MCInstrDesc &MCID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3);
const MachineInstrBuilder MIB =
- AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg).setMIFlags(MIFlags));
+ AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)
+ .setMIFlags(MIFlags));
AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal));
} else {
AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
@@ -262,18 +261,15 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
if (NeedCC)
MIB = AddDefaultT1CC(MIB);
MIB.addReg(DestReg).addImm(ThisVal);
- if (NeedPred)
- MIB = AddDefaultPred(MIB);
+ MIB = AddDefaultPred(MIB);
MIB.setMIFlags(MIFlags);
- }
- else {
+ } else {
bool isKill = BaseReg != ARM::SP;
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
if (NeedCC)
MIB = AddDefaultT1CC(MIB);
MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal);
- if (NeedPred)
- MIB = AddDefaultPred(MIB);
+ MIB = AddDefaultPred(MIB);
MIB.setMIFlags(MIFlags);
BaseReg = DestReg;
@@ -285,7 +281,7 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
Scale = 1;
Chunk = ((1 << NumBits) - 1) * Scale;
Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
- NeedPred = NeedCC = isTwoAddr = true;
+ NeedCC = isTwoAddr = true;
}
}
}
@@ -405,7 +401,6 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
unsigned Scale = 1;
if (FrameReg != ARM::SP) {
Opcode = ARM::tADDi3;
- MI.setDesc(TII.get(Opcode));
NumBits = 3;
} else {
NumBits = 8;
@@ -419,10 +414,9 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
// Turn it into a move.
MI.setDesc(TII.get(ARM::tMOVr));
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
- // Remove offset and add predicate operands.
+ // Remove offset
MI.RemoveOperand(FrameRegIdx+1);
MachineInstrBuilder MIB(&MI);
- AddDefaultPred(MIB);
return true;
}
@@ -431,6 +425,7 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
if (((Offset / Scale) & ~Mask) == 0) {
// Replace the FrameIndex with sp / fp
if (Opcode == ARM::tADDi3) {
+ MI.setDesc(TII.get(Opcode));
removeOperands(MI, FrameRegIdx);
MachineInstrBuilder MIB(&MI);
AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg)
@@ -459,6 +454,7 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
// r0 = add sp, 255*4
// r0 = add r0, (imm - 255*4)
if (Opcode == ARM::tADDi3) {
+ MI.setDesc(TII.get(Opcode));
removeOperands(MI, FrameRegIdx);
MachineInstrBuilder MIB(&MI);
AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask));
@@ -479,10 +475,6 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
MI.setDesc(TII.get(ARM::tADDhirr));
MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false, false, true);
MI.getOperand(FrameRegIdx+1).ChangeToRegister(FrameReg, false);
- if (Opcode == ARM::tADDi3) {
- MachineInstrBuilder MIB(&MI);
- AddDefaultPred(MIB);
- }
}
return true;
} else {
@@ -545,9 +537,9 @@ Thumb1RegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I,
++i;
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
}
- bool Done = false;
- Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII);
+ bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII);
assert (Done && "Unable to resolve frame index!");
+ (void)Done;
}
/// saveScavengerRegister - Spill the register so it can be used by the
diff --git a/lib/Target/ARM/Thumb2ITBlockPass.cpp b/lib/Target/ARM/Thumb2ITBlockPass.cpp
index 360ec00..b627400 100644
--- a/lib/Target/ARM/Thumb2ITBlockPass.cpp
+++ b/lib/Target/ARM/Thumb2ITBlockPass.cpp
@@ -124,6 +124,27 @@ Thumb2ITBlockPass::MoveCopyOutOfITBlock(MachineInstr *MI,
if (Uses.count(DstReg) || Defs.count(SrcReg))
return false;
+ // If the CPSR is defined by this copy, then we don't want to move it. E.g.,
+ // if we have:
+ //
+ // movs r1, r1
+ // rsb r1, 0
+ // movs r2, r2
+ // rsb r2, 0
+ //
+ // we don't want this to be converted to:
+ //
+ // movs r1, r1
+ // movs r2, r2
+ // itt mi
+ // rsb r1, 0
+ // rsb r2, 0
+ //
+ const MCInstrDesc &MCID = MI->getDesc();
+ if (MCID.hasOptionalDef() &&
+ MI->getOperand(MCID.getNumOperands() - 1).getReg() == ARM::CPSR)
+ return false;
+
// Then peek at the next instruction to see if it's predicated on CC or OCC.
// If not, then there is nothing to be gained by moving the copy.
MachineBasicBlock::iterator I = MI; ++I;
diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp
index 51b56aa..cf040c82 100644
--- a/lib/Target/ARM/Thumb2InstrInfo.cpp
+++ b/lib/Target/ARM/Thumb2InstrInfo.cpp
@@ -14,9 +14,9 @@
#include "Thumb2InstrInfo.h"
#include "ARM.h"
#include "ARMConstantPoolValue.h"
-#include "ARMAddressingModes.h"
#include "ARMMachineFunctionInfo.h"
#include "Thumb2InstrInfo.h"
+#include "MCTargetDesc/ARMAddressingModes.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
@@ -122,7 +122,8 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
if (RC == ARM::GPRRegisterClass || RC == ARM::tGPRRegisterClass ||
- RC == ARM::tcGPRRegisterClass || RC == ARM::rGPRRegisterClass) {
+ RC == ARM::tcGPRRegisterClass || RC == ARM::rGPRRegisterClass ||
+ RC == ARM::GPRnopcRegisterClass) {
DebugLoc DL;
if (I != MBB.end()) DL = I->getDebugLoc();
@@ -149,7 +150,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
if (RC == ARM::GPRRegisterClass || RC == ARM::tGPRRegisterClass ||
- RC == ARM::tcGPRRegisterClass || RC == ARM::rGPRRegisterClass) {
+ RC == ARM::tcGPRRegisterClass || RC == ARM::rGPRRegisterClass ||
+ RC == ARM::GPRnopcRegisterClass) {
DebugLoc DL;
if (I != MBB.end()) DL = I->getDebugLoc();
@@ -233,9 +235,8 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
if (DestReg == ARM::SP && (ThisVal < ((1 << 7)-1) * 4)) {
assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?");
Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
- // FIXME: Fix Thumb1 immediate encoding.
- BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
- .addReg(BaseReg).addImm(ThisVal/4).setMIFlags(MIFlags);
+ AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
+ .addReg(BaseReg).addImm(ThisVal/4).setMIFlags(MIFlags));
NumBytes = 0;
continue;
}
diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp
index c741a6e..89a155c 100644
--- a/lib/Target/ARM/Thumb2SizeReduction.cpp
+++ b/lib/Target/ARM/Thumb2SizeReduction.cpp
@@ -9,11 +9,11 @@
#define DEBUG_TYPE "t2-reduce-size"
#include "ARM.h"
-#include "ARMAddressingModes.h"
#include "ARMBaseRegisterInfo.h"
#include "ARMBaseInstrInfo.h"
#include "ARMSubtarget.h"
#include "Thumb2InstrInfo.h"
+#include "MCTargetDesc/ARMAddressingModes.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -97,11 +97,11 @@ namespace {
{ ARM::t2SUBrr, ARM::tSUBrr, 0, 0, 0, 1, 0, 0,0, 0,0 },
{ ARM::t2SUBSri,ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 2,2, 0,0 },
{ ARM::t2SUBSrr,ARM::tSUBrr, 0, 0, 0, 1, 0, 2,0, 0,0 },
- { ARM::t2SXTBr, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0,0 },
- { ARM::t2SXTHr, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0,0 },
+ { ARM::t2SXTB, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0,1 },
+ { ARM::t2SXTH, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0,1 },
{ ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 2,0, 0,0 },
- { ARM::t2UXTBr, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0,0 },
- { ARM::t2UXTHr, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0,0 },
+ { ARM::t2UXTB, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0,1 },
+ { ARM::t2UXTH, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0,1 },
// FIXME: Clean this up after splitting each Thumb load / store opcode
// into multiple ones.
@@ -507,6 +507,7 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI,
.addOperand(MI->getOperand(0))
.addOperand(MI->getOperand(1))
.addImm(Imm / 4); // The tADDrSPi has an implied scale by four.
+ AddDefaultPred(MIB);
// Transfer MI flags.
MIB.setMIFlags(MI->getFlags());
@@ -546,6 +547,10 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI,
}
case ARM::t2RSBri:
case ARM::t2RSBSri:
+ case ARM::t2SXTB:
+ case ARM::t2SXTH:
+ case ARM::t2UXTB:
+ case ARM::t2UXTH:
if (MI->getOperand(2).getImm() == 0)
return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, CPSRDef);
break;
@@ -742,7 +747,11 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI,
if (i < NumOps && MCID.OpInfo[i].isOptionalDef())
continue;
if ((MCID.getOpcode() == ARM::t2RSBSri ||
- MCID.getOpcode() == ARM::t2RSBri) && i == 2)
+ MCID.getOpcode() == ARM::t2RSBri ||
+ MCID.getOpcode() == ARM::t2SXTB ||
+ MCID.getOpcode() == ARM::t2SXTH ||
+ MCID.getOpcode() == ARM::t2UXTB ||
+ MCID.getOpcode() == ARM::t2UXTH) && i == 2)
// Skip the zero immediate operand, it's now implicit.
continue;
bool isPred = (i < NumOps && MCID.OpInfo[i].isPredicate());
diff --git a/lib/Target/Alpha/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AlphaAsmPrinter.cpp
index 46ae286..5dce06a 100644
--- a/lib/Target/Alpha/AlphaAsmPrinter.cpp
+++ b/lib/Target/Alpha/AlphaAsmPrinter.cpp
@@ -26,8 +26,8 @@
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
diff --git a/lib/Target/Alpha/AlphaISelDAGToDAG.cpp b/lib/Target/Alpha/AlphaISelDAGToDAG.cpp
index 7b91fea..f877c65 100644
--- a/lib/Target/Alpha/AlphaISelDAGToDAG.cpp
+++ b/lib/Target/Alpha/AlphaISelDAGToDAG.cpp
@@ -80,7 +80,7 @@ namespace {
// Otherwise we don't know that the it's okay to zapnot this entire
// byte. Only do this iff we can prove that the missing bits are
// already null, so the bytezap doesn't need to really null them.
- BitsToCheck |= ~Constant & (0xFF << 8*i);
+ BitsToCheck |= ~Constant & (0xFFULL << 8*i);
}
}
}
@@ -114,9 +114,8 @@ namespace {
if (!x) return 0;
unsigned at = CountLeadingZeros_64(x);
uint64_t complow = 1ULL << (63 - at);
- uint64_t comphigh = 1ULL << (64 - at);
- //cerr << x << ":" << complow << ":" << comphigh << "\n";
- if (abs64(complow - x) <= abs64(comphigh - x))
+ uint64_t comphigh = complow << 1;
+ if (x - complow <= comphigh - x)
return complow;
else
return comphigh;
diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp
index de003fb..3057eb8 100644
--- a/lib/Target/Alpha/AlphaISelLowering.cpp
+++ b/lib/Target/Alpha/AlphaISelLowering.cpp
@@ -49,6 +49,7 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM)
// Set up the TargetLowering object.
//I am having problems with shr n i8 1
setBooleanContents(ZeroOrOneBooleanContent);
+ setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
addRegisterClass(MVT::f64, Alpha::F8RCRegisterClass);
@@ -153,6 +154,9 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM)
setOperationAction(ISD::JumpTable, MVT::i64, Custom);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
+ setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Expand);
+ setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Expand);
+
setStackPointerRegisterToSaveRestore(Alpha::R30);
setJumpBufSize(272);
@@ -160,10 +164,12 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM)
setMinFunctionAlignment(4);
+ setInsertFencesForAtomic(true);
+
computeRegisterProperties();
}
-MVT::SimpleValueType AlphaTargetLowering::getSetCCResultType(EVT VT) const {
+EVT AlphaTargetLowering::getSetCCResultType(EVT VT) const {
return MVT::i64;
}
diff --git a/lib/Target/Alpha/AlphaISelLowering.h b/lib/Target/Alpha/AlphaISelLowering.h
index 13383f4..80f8efa 100644
--- a/lib/Target/Alpha/AlphaISelLowering.h
+++ b/lib/Target/Alpha/AlphaISelLowering.h
@@ -66,7 +66,7 @@ namespace llvm {
virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i64; }
/// getSetCCResultType - Get the SETCC result ValueType
- virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
+ virtual EVT getSetCCResultType(EVT VT) const;
/// LowerOperation - Provide custom lowering hooks for some operations.
///
diff --git a/lib/Target/Alpha/AlphaInstrInfo.cpp b/lib/Target/Alpha/AlphaInstrInfo.cpp
index 4dcec8f..8df2ed7 100644
--- a/lib/Target/Alpha/AlphaInstrInfo.cpp
+++ b/lib/Target/Alpha/AlphaInstrInfo.cpp
@@ -16,7 +16,6 @@
#include "AlphaMachineFunctionInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/lib/Target/Alpha/AlphaInstrInfo.td b/lib/Target/Alpha/AlphaInstrInfo.td
index b201712..c8c9377 100644
--- a/lib/Target/Alpha/AlphaInstrInfo.td
+++ b/lib/Target/Alpha/AlphaInstrInfo.td
@@ -607,6 +607,8 @@ def : Pat<(membarrier (i64 imm), (i64 imm), (i64 imm), (i64 1), (i64 imm)),
def : Pat<(membarrier (i64 imm), (i64 imm), (i64 imm), (i64 imm), (i64 imm)),
(MB)>;
+def : Pat<(atomic_fence (imm), (imm)), (MB)>;
+
//Basic Floating point ops
//Floats
diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp
index df8f157..8b6230f 100644
--- a/lib/Target/Alpha/AlphaRegisterInfo.cpp
+++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp
@@ -21,7 +21,6 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
@@ -40,8 +39,7 @@
using namespace llvm;
AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii)
- : AlphaGenRegisterInfo(),
- TII(tii) {
+ : AlphaGenRegisterInfo(Alpha::R26), TII(tii) {
}
static long getUpper16(long l) {
@@ -178,10 +176,6 @@ AlphaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
}
}
-unsigned AlphaRegisterInfo::getRARegister() const {
- return Alpha::R26;
-}
-
unsigned AlphaRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
@@ -198,16 +192,6 @@ unsigned AlphaRegisterInfo::getEHHandlerRegister() const {
return 0;
}
-int AlphaRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
- llvm_unreachable("What is the dwarf register number");
- return -1;
-}
-
-int AlphaRegisterInfo::getLLVMRegNum(unsigned DwarfRegNum, bool isEH) const {
- llvm_unreachable("What is the dwarf register number");
- return -1;
-}
-
std::string AlphaRegisterInfo::getPrettyName(unsigned reg)
{
std::string s(AlphaRegDesc[reg].Name);
diff --git a/lib/Target/Alpha/AlphaRegisterInfo.h b/lib/Target/Alpha/AlphaRegisterInfo.h
index 1072bf7..e35be27 100644
--- a/lib/Target/Alpha/AlphaRegisterInfo.h
+++ b/lib/Target/Alpha/AlphaRegisterInfo.h
@@ -42,16 +42,12 @@ struct AlphaRegisterInfo : public AlphaGenRegisterInfo {
int SPAdj, RegScavenger *RS = NULL) const;
// Debug information queries.
- unsigned getRARegister() const;
unsigned getFrameRegister(const MachineFunction &MF) const;
// Exception handling queries.
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- int getLLVMRegNum(unsigned RegNum, bool isEH) const;
-
static std::string getPrettyName(unsigned reg);
};
diff --git a/lib/Target/Alpha/AlphaSubtarget.cpp b/lib/Target/Alpha/AlphaSubtarget.cpp
index 624a5e2..bd55ce9 100644
--- a/lib/Target/Alpha/AlphaSubtarget.cpp
+++ b/lib/Target/Alpha/AlphaSubtarget.cpp
@@ -13,7 +13,6 @@
#include "AlphaSubtarget.h"
#include "Alpha.h"
-#include "llvm/Target/TargetRegistry.h"
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
diff --git a/lib/Target/Alpha/AlphaTargetMachine.cpp b/lib/Target/Alpha/AlphaTargetMachine.cpp
index 3b65d41..fc9a677 100644
--- a/lib/Target/Alpha/AlphaTargetMachine.cpp
+++ b/lib/Target/Alpha/AlphaTargetMachine.cpp
@@ -14,7 +14,7 @@
#include "AlphaTargetMachine.h"
#include "llvm/PassManager.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
extern "C" void LLVMInitializeAlphaTarget() {
@@ -22,19 +22,17 @@ extern "C" void LLVMInitializeAlphaTarget() {
RegisterTargetMachine<AlphaTargetMachine> X(TheAlphaTarget);
}
-AlphaTargetMachine::AlphaTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : LLVMTargetMachine(T, TT, CPU, FS),
+AlphaTargetMachine::AlphaTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
DataLayout("e-f128:128:128-n64"),
FrameLowering(Subtarget),
Subtarget(TT, CPU, FS),
TLInfo(*this),
TSInfo(*this) {
- setRelocationModel(Reloc::PIC_);
}
-
//===----------------------------------------------------------------------===//
// Pass Pipeline Configuration
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/Alpha/AlphaTargetMachine.h b/lib/Target/Alpha/AlphaTargetMachine.h
index cf00e58..48bb948 100644
--- a/lib/Target/Alpha/AlphaTargetMachine.h
+++ b/lib/Target/Alpha/AlphaTargetMachine.h
@@ -36,8 +36,9 @@ class AlphaTargetMachine : public LLVMTargetMachine {
AlphaSelectionDAGInfo TSInfo;
public:
- AlphaTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ AlphaTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
virtual const AlphaInstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const TargetFrameLowering *getFrameLowering() const {
diff --git a/lib/Target/Alpha/CMakeLists.txt b/lib/Target/Alpha/CMakeLists.txt
index a6027bb..a6d5516 100644
--- a/lib/Target/Alpha/CMakeLists.txt
+++ b/lib/Target/Alpha/CMakeLists.txt
@@ -1,11 +1,12 @@
set(LLVM_TARGET_DEFINITIONS Alpha.td)
-tablegen(AlphaGenRegisterInfo.inc -gen-register-info)
-tablegen(AlphaGenInstrInfo.inc -gen-instr-info)
-tablegen(AlphaGenAsmWriter.inc -gen-asm-writer)
-tablegen(AlphaGenDAGISel.inc -gen-dag-isel)
-tablegen(AlphaGenCallingConv.inc -gen-callingconv)
-tablegen(AlphaGenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(AlphaGenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(AlphaGenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(AlphaGenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(AlphaGenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(AlphaGenCallingConv.inc -gen-callingconv)
+llvm_tablegen(AlphaGenSubtargetInfo.inc -gen-subtarget)
+add_public_tablegen_target(AlphaCommonTableGen)
add_llvm_target(AlphaCodeGen
AlphaAsmPrinter.cpp
@@ -21,5 +22,17 @@ add_llvm_target(AlphaCodeGen
AlphaSelectionDAGInfo.cpp
)
+add_llvm_library_dependencies(LLVMAlphaCodeGen
+ LLVMAlphaDesc
+ LLVMAlphaInfo
+ LLVMAsmPrinter
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMTarget
+ )
+
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
diff --git a/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp b/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp
index 562052b..4ad021c 100644
--- a/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp
+++ b/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp
@@ -13,10 +13,11 @@
#include "AlphaMCTargetDesc.h"
#include "AlphaMCAsmInfo.h"
+#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_MC_DESC
#include "AlphaGenInstrInfo.inc"
@@ -36,8 +37,10 @@ static MCInstrInfo *createAlphaMCInstrInfo() {
return X;
}
-extern "C" void LLVMInitializeAlphaMCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(TheAlphaTarget, createAlphaMCInstrInfo);
+static MCRegisterInfo *createAlphaMCRegisterInfo(StringRef TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitAlphaMCRegisterInfo(X, Alpha::R26);
+ return X;
}
static MCSubtargetInfo *createAlphaMCSubtargetInfo(StringRef TT, StringRef CPU,
@@ -47,11 +50,29 @@ static MCSubtargetInfo *createAlphaMCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-extern "C" void LLVMInitializeAlphaMCSubtargetInfo() {
- TargetRegistry::RegisterMCSubtargetInfo(TheAlphaTarget,
- createAlphaMCSubtargetInfo);
+static MCCodeGenInfo *createAlphaMCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+ X->InitMCCodeGenInfo(Reloc::PIC_, CM);
+ return X;
}
-extern "C" void LLVMInitializeAlphaMCAsmInfo() {
+// Force static initialization.
+extern "C" void LLVMInitializeAlphaTargetMC() {
+ // Register the MC asm info.
RegisterMCAsmInfo<AlphaMCAsmInfo> X(TheAlphaTarget);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(TheAlphaTarget,
+ createAlphaMCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheAlphaTarget, createAlphaMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheAlphaTarget, createAlphaMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(TheAlphaTarget,
+ createAlphaMCSubtargetInfo);
}
diff --git a/lib/Target/Alpha/MCTargetDesc/CMakeLists.txt b/lib/Target/Alpha/MCTargetDesc/CMakeLists.txt
index ad0dd26..f745ecb 100644
--- a/lib/Target/Alpha/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/Alpha/MCTargetDesc/CMakeLists.txt
@@ -2,3 +2,10 @@ add_llvm_library(LLVMAlphaDesc
AlphaMCTargetDesc.cpp
AlphaMCAsmInfo.cpp
)
+
+add_llvm_library_dependencies(LLVMAlphaDesc
+ LLVMAlphaInfo
+ LLVMMC
+ )
+
+add_dependencies(LLVMAlphaDesc AlphaCommonTableGen)
diff --git a/lib/Target/Alpha/TargetInfo/AlphaTargetInfo.cpp b/lib/Target/Alpha/TargetInfo/AlphaTargetInfo.cpp
index f7099b9..bdc69e7 100644
--- a/lib/Target/Alpha/TargetInfo/AlphaTargetInfo.cpp
+++ b/lib/Target/Alpha/TargetInfo/AlphaTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "Alpha.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
llvm::Target llvm::TheAlphaTarget;
diff --git a/lib/Target/Alpha/TargetInfo/CMakeLists.txt b/lib/Target/Alpha/TargetInfo/CMakeLists.txt
index 2a7291b..cac3178 100644
--- a/lib/Target/Alpha/TargetInfo/CMakeLists.txt
+++ b/lib/Target/Alpha/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMAlphaInfo
AlphaTargetInfo.cpp
)
-add_dependencies(LLVMAlphaInfo AlphaCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMAlphaInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMAlphaInfo AlphaCommonTableGen)
diff --git a/lib/Target/Blackfin/BlackfinAsmPrinter.cpp b/lib/Target/Blackfin/BlackfinAsmPrinter.cpp
index 6ba258b..ed9844e 100644
--- a/lib/Target/Blackfin/BlackfinAsmPrinter.cpp
+++ b/lib/Target/Blackfin/BlackfinAsmPrinter.cpp
@@ -29,9 +29,9 @@
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
diff --git a/lib/Target/Blackfin/BlackfinFrameLowering.h b/lib/Target/Blackfin/BlackfinFrameLowering.h
index 726fa2c..169aa8e 100644
--- a/lib/Target/Blackfin/BlackfinFrameLowering.h
+++ b/lib/Target/Blackfin/BlackfinFrameLowering.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef ALPHA_FRAMEINFO_H
-#define ALPHA_FRAMEINFO_H
+#ifndef BLACKFIN_FRAMEINFO_H
+#define BLACKFIN_FRAMEINFO_H
#include "Blackfin.h"
#include "BlackfinSubtarget.h"
diff --git a/lib/Target/Blackfin/BlackfinISelLowering.cpp b/lib/Target/Blackfin/BlackfinISelLowering.cpp
index d572832..7d4c45f 100644
--- a/lib/Target/Blackfin/BlackfinISelLowering.cpp
+++ b/lib/Target/Blackfin/BlackfinISelLowering.cpp
@@ -42,6 +42,7 @@ using namespace llvm;
BlackfinTargetLowering::BlackfinTargetLowering(TargetMachine &TM)
: TargetLowering(TM, new TargetLoweringObjectFileELF()) {
setBooleanContents(ZeroOrOneBooleanContent);
+ setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
setStackPointerRegisterToSaveRestore(BF::SP);
setIntDivIsCheap(false);
@@ -99,6 +100,7 @@ BlackfinTargetLowering::BlackfinTargetLowering(TargetMachine &TM)
// Blackfin has no intrinsics for these particular operations.
setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
+ setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
@@ -134,7 +136,7 @@ const char *BlackfinTargetLowering::getTargetNodeName(unsigned Opcode) const {
}
}
-MVT::SimpleValueType BlackfinTargetLowering::getSetCCResultType(EVT VT) const {
+EVT BlackfinTargetLowering::getSetCCResultType(EVT VT) const {
// SETCC always sets the CC register. Technically that is an i1 register, but
// that type is not legal, so we treat it as an i32 register.
return MVT::i32;
diff --git a/lib/Target/Blackfin/BlackfinISelLowering.h b/lib/Target/Blackfin/BlackfinISelLowering.h
index b65775b..90908ba 100644
--- a/lib/Target/Blackfin/BlackfinISelLowering.h
+++ b/lib/Target/Blackfin/BlackfinISelLowering.h
@@ -33,7 +33,7 @@ namespace llvm {
public:
BlackfinTargetLowering(TargetMachine &TM);
virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i16; }
- virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
+ virtual EVT getSetCCResultType(EVT VT) const;
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
virtual void ReplaceNodeResults(SDNode *N,
SmallVectorImpl<SDValue> &Results,
diff --git a/lib/Target/Blackfin/BlackfinInstrInfo.cpp b/lib/Target/Blackfin/BlackfinInstrInfo.cpp
index d190ae7..c06a919 100644
--- a/lib/Target/Blackfin/BlackfinInstrInfo.cpp
+++ b/lib/Target/Blackfin/BlackfinInstrInfo.cpp
@@ -16,10 +16,10 @@
#include "Blackfin.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_CTOR
#include "BlackfinGenInstrInfo.inc"
diff --git a/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp b/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp
index ae8ee9e..7135676 100644
--- a/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp
+++ b/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp
@@ -34,7 +34,7 @@ namespace bfinIntrinsic {
}
-std::string BlackfinIntrinsicInfo::getName(unsigned IntrID, const Type **Tys,
+std::string BlackfinIntrinsicInfo::getName(unsigned IntrID, Type **Tys,
unsigned numTys) const {
static const char *const names[] = {
#define GET_INTRINSIC_NAME_TABLE
@@ -81,8 +81,8 @@ bool BlackfinIntrinsicInfo::isOverloaded(unsigned IntrID) const {
#include "BlackfinGenIntrinsics.inc"
#undef GET_INTRINSIC_ATTRIBUTES
-static const FunctionType *getType(LLVMContext &Context, unsigned id) {
- const Type *ResultTy = NULL;
+static FunctionType *getType(LLVMContext &Context, unsigned id) {
+ Type *ResultTy = NULL;
std::vector<Type*> ArgTys;
bool IsVarArg = false;
@@ -94,7 +94,7 @@ static const FunctionType *getType(LLVMContext &Context, unsigned id) {
}
Function *BlackfinIntrinsicInfo::getDeclaration(Module *M, unsigned IntrID,
- const Type **Tys,
+ Type **Tys,
unsigned numTy) const {
assert(!isOverloaded(IntrID) && "Blackfin intrinsics are not overloaded");
AttrListPtr AList = getAttributes((bfinIntrinsic::ID) IntrID);
diff --git a/lib/Target/Blackfin/BlackfinIntrinsicInfo.h b/lib/Target/Blackfin/BlackfinIntrinsicInfo.h
index 7c4b5a9..f05db5a 100644
--- a/lib/Target/Blackfin/BlackfinIntrinsicInfo.h
+++ b/lib/Target/Blackfin/BlackfinIntrinsicInfo.h
@@ -19,11 +19,11 @@ namespace llvm {
class BlackfinIntrinsicInfo : public TargetIntrinsicInfo {
public:
- std::string getName(unsigned IntrID, const Type **Tys = 0,
+ std::string getName(unsigned IntrID, Type **Tys = 0,
unsigned numTys = 0) const;
unsigned lookupName(const char *Name, unsigned Len) const;
bool isOverloaded(unsigned IID) const;
- Function *getDeclaration(Module *M, unsigned ID, const Type **Tys = 0,
+ Function *getDeclaration(Module *M, unsigned ID, Type **Tys = 0,
unsigned numTys = 0) const;
};
diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp
index 3a7c104..0d415c5 100644
--- a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp
+++ b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp
@@ -20,7 +20,6 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetMachine.h"
@@ -37,7 +36,7 @@ using namespace llvm;
BlackfinRegisterInfo::BlackfinRegisterInfo(BlackfinSubtarget &st,
const TargetInstrInfo &tii)
- : BlackfinGenRegisterInfo(), Subtarget(st), TII(tii) {}
+ : BlackfinGenRegisterInfo(BF::RETS), Subtarget(st), TII(tii) {}
const unsigned*
BlackfinRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
@@ -327,10 +326,6 @@ BlackfinRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
}
}
-unsigned BlackfinRegisterInfo::getRARegister() const {
- return BF::RETS;
-}
-
unsigned
BlackfinRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
@@ -347,14 +342,3 @@ unsigned BlackfinRegisterInfo::getEHHandlerRegister() const {
llvm_unreachable("What is the exception handler register");
return 0;
}
-
-int BlackfinRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
- llvm_unreachable("What is the dwarf register number");
- return -1;
-}
-
-int BlackfinRegisterInfo::getLLVMRegNum(unsigned DwarfRegNum,
- bool isEH) const {
- llvm_unreachable("What is the dwarf register number");
- return -1;
-}
diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.h b/lib/Target/Blackfin/BlackfinRegisterInfo.h
index 86f45c1..6ac22af 100644
--- a/lib/Target/Blackfin/BlackfinRegisterInfo.h
+++ b/lib/Target/Blackfin/BlackfinRegisterInfo.h
@@ -53,15 +53,11 @@ namespace llvm {
int SPAdj, RegScavenger *RS = NULL) const;
unsigned getFrameRegister(const MachineFunction &MF) const;
- unsigned getRARegister() const;
// Exception handling queries.
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- int getLLVMRegNum(unsigned RegNum, bool isEH) const;
-
// Utility functions
void adjustRegister(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
diff --git a/lib/Target/Blackfin/BlackfinSubtarget.cpp b/lib/Target/Blackfin/BlackfinSubtarget.cpp
index ec919cd..0bdce09 100644
--- a/lib/Target/Blackfin/BlackfinSubtarget.cpp
+++ b/lib/Target/Blackfin/BlackfinSubtarget.cpp
@@ -13,7 +13,7 @@
#include "BlackfinSubtarget.h"
#include "Blackfin.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
diff --git a/lib/Target/Blackfin/BlackfinTargetMachine.cpp b/lib/Target/Blackfin/BlackfinTargetMachine.cpp
index a1c9f1c..a4ae46b 100644
--- a/lib/Target/Blackfin/BlackfinTargetMachine.cpp
+++ b/lib/Target/Blackfin/BlackfinTargetMachine.cpp
@@ -13,7 +13,7 @@
#include "BlackfinTargetMachine.h"
#include "Blackfin.h"
#include "llvm/PassManager.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
@@ -22,10 +22,12 @@ extern "C" void LLVMInitializeBlackfinTarget() {
}
BlackfinTargetMachine::BlackfinTargetMachine(const Target &T,
- const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : LLVMTargetMachine(T, TT, CPU, FS),
+ StringRef TT,
+ StringRef CPU,
+ StringRef FS,
+ Reloc::Model RM,
+ CodeModel::Model CM)
+ : LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
DataLayout("e-p:32:32-i64:32-f64:32-n32"),
Subtarget(TT, CPU, FS),
TLInfo(*this),
diff --git a/lib/Target/Blackfin/BlackfinTargetMachine.h b/lib/Target/Blackfin/BlackfinTargetMachine.h
index bd7dc84..c85337fe2 100644
--- a/lib/Target/Blackfin/BlackfinTargetMachine.h
+++ b/lib/Target/Blackfin/BlackfinTargetMachine.h
@@ -35,8 +35,9 @@ namespace llvm {
BlackfinFrameLowering FrameLowering;
BlackfinIntrinsicInfo IntrinsicInfo;
public:
- BlackfinTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ BlackfinTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
virtual const BlackfinInstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const TargetFrameLowering *getFrameLowering() const {
diff --git a/lib/Target/Blackfin/CMakeLists.txt b/lib/Target/Blackfin/CMakeLists.txt
index d3f33a9..94d05fb 100644
--- a/lib/Target/Blackfin/CMakeLists.txt
+++ b/lib/Target/Blackfin/CMakeLists.txt
@@ -1,12 +1,13 @@
set(LLVM_TARGET_DEFINITIONS Blackfin.td)
-tablegen(BlackfinGenRegisterInfo.inc -gen-register-info)
-tablegen(BlackfinGenInstrInfo.inc -gen-instr-info)
-tablegen(BlackfinGenAsmWriter.inc -gen-asm-writer)
-tablegen(BlackfinGenDAGISel.inc -gen-dag-isel)
-tablegen(BlackfinGenSubtargetInfo.inc -gen-subtarget)
-tablegen(BlackfinGenCallingConv.inc -gen-callingconv)
-tablegen(BlackfinGenIntrinsics.inc -gen-tgt-intrinsic)
+llvm_tablegen(BlackfinGenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(BlackfinGenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(BlackfinGenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(BlackfinGenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(BlackfinGenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(BlackfinGenCallingConv.inc -gen-callingconv)
+llvm_tablegen(BlackfinGenIntrinsics.inc -gen-tgt-intrinsic)
+add_public_tablegen_target(BlackfinCommonTableGen)
add_llvm_target(BlackfinCodeGen
BlackfinAsmPrinter.cpp
@@ -21,5 +22,17 @@ add_llvm_target(BlackfinCodeGen
BlackfinSelectionDAGInfo.cpp
)
+add_llvm_library_dependencies(LLVMBlackfinCodeGen
+ LLVMAsmPrinter
+ LLVMBlackfinDesc
+ LLVMBlackfinInfo
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMTarget
+ )
+
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
diff --git a/lib/Target/Blackfin/MCTargetDesc/BlackfinMCTargetDesc.cpp b/lib/Target/Blackfin/MCTargetDesc/BlackfinMCTargetDesc.cpp
index 0fa1471..272e3c2 100644
--- a/lib/Target/Blackfin/MCTargetDesc/BlackfinMCTargetDesc.cpp
+++ b/lib/Target/Blackfin/MCTargetDesc/BlackfinMCTargetDesc.cpp
@@ -13,10 +13,11 @@
#include "BlackfinMCTargetDesc.h"
#include "BlackfinMCAsmInfo.h"
+#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_MC_DESC
#include "BlackfinGenInstrInfo.inc"
@@ -36,12 +37,12 @@ static MCInstrInfo *createBlackfinMCInstrInfo() {
return X;
}
-extern "C" void LLVMInitializeBlackfinMCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(TheBlackfinTarget,
- createBlackfinMCInstrInfo);
+static MCRegisterInfo *createBlackfinMCRegisterInfo(StringRef TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitBlackfinMCRegisterInfo(X, BF::RETS);
+ return X;
}
-
static MCSubtargetInfo *createBlackfinMCSubtargetInfo(StringRef TT,
StringRef CPU,
StringRef FS) {
@@ -50,11 +51,31 @@ static MCSubtargetInfo *createBlackfinMCSubtargetInfo(StringRef TT,
return X;
}
-extern "C" void LLVMInitializeBlackfinMCSubtargetInfo() {
- TargetRegistry::RegisterMCSubtargetInfo(TheBlackfinTarget,
- createBlackfinMCSubtargetInfo);
+static MCCodeGenInfo *createBlackfinMCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+ X->InitMCCodeGenInfo(RM, CM);
+ return X;
}
-extern "C" void LLVMInitializeBlackfinMCAsmInfo() {
+// Force static initialization.
+extern "C" void LLVMInitializeBlackfinTargetMC() {
+ // Register the MC asm info.
RegisterMCAsmInfo<BlackfinMCAsmInfo> X(TheBlackfinTarget);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(TheBlackfinTarget,
+ createBlackfinMCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheBlackfinTarget,
+ createBlackfinMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheBlackfinTarget,
+ createBlackfinMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(TheBlackfinTarget,
+ createBlackfinMCSubtargetInfo);
}
diff --git a/lib/Target/Blackfin/MCTargetDesc/CMakeLists.txt b/lib/Target/Blackfin/MCTargetDesc/CMakeLists.txt
index 8cd924f..73315d8 100644
--- a/lib/Target/Blackfin/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/Blackfin/MCTargetDesc/CMakeLists.txt
@@ -2,3 +2,10 @@ add_llvm_library(LLVMBlackfinDesc
BlackfinMCTargetDesc.cpp
BlackfinMCAsmInfo.cpp
)
+
+add_llvm_library_dependencies(LLVMBlackfinDesc
+ LLVMBlackfinInfo
+ LLVMMC
+ )
+
+add_dependencies(LLVMBlackfinDesc BlackfinCommonTableGen)
diff --git a/lib/Target/Blackfin/TargetInfo/BlackfinTargetInfo.cpp b/lib/Target/Blackfin/TargetInfo/BlackfinTargetInfo.cpp
index 402e0af..57f1d3e 100644
--- a/lib/Target/Blackfin/TargetInfo/BlackfinTargetInfo.cpp
+++ b/lib/Target/Blackfin/TargetInfo/BlackfinTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "Blackfin.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
diff --git a/lib/Target/Blackfin/TargetInfo/CMakeLists.txt b/lib/Target/Blackfin/TargetInfo/CMakeLists.txt
index 5ca8060..771f092 100644
--- a/lib/Target/Blackfin/TargetInfo/CMakeLists.txt
+++ b/lib/Target/Blackfin/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMBlackfinInfo
BlackfinTargetInfo.cpp
)
-add_dependencies(LLVMBlackfinInfo BlackfinCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMBlackfinInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMBlackfinInfo BlackfinCommonTableGen)
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index 415beb1..69d8c46 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -37,10 +37,11 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/ErrorHandling.h"
@@ -48,6 +49,7 @@
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/Host.h"
#include "llvm/Config/config.h"
#include <algorithm>
@@ -62,12 +64,6 @@ extern "C" void LLVMInitializeCBackendTarget() {
RegisterTargetMachine<CTargetMachine> X(TheCBackendTarget);
}
-extern "C" void LLVMInitializeCBackendMCAsmInfo() {}
-
-extern "C" void LLVMInitializeCBackendMCInstrInfo() {}
-
-extern "C" void LLVMInitializeCBackendMCSubtargetInfo() {}
-
namespace {
class CBEMCAsmInfo : public MCAsmInfo {
public:
@@ -86,6 +82,8 @@ namespace {
LoopInfo *LI;
const Module *TheModule;
const MCAsmInfo* TAsm;
+ const MCRegisterInfo *MRI;
+ const MCObjectFileInfo *MOFI;
MCContext *TCtx;
const TargetData* TD;
@@ -99,14 +97,14 @@ namespace {
/// UnnamedStructIDs - This contains a unique ID for each struct that is
/// either anonymous or has no name.
- DenseMap<const StructType*, unsigned> UnnamedStructIDs;
+ DenseMap<StructType*, unsigned> UnnamedStructIDs;
public:
static char ID;
explicit CWriter(formatted_raw_ostream &o)
: FunctionPass(ID), Out(o), IL(0), Mang(0), LI(0),
- TheModule(0), TAsm(0), TCtx(0), TD(0), OpaqueCounter(0),
- NextAnonValueNumber(0) {
+ TheModule(0), TAsm(0), MRI(0), MOFI(0), TCtx(0), TD(0),
+ OpaqueCounter(0), NextAnonValueNumber(0) {
initializeLoopInfoPass(*PassRegistry::getPassRegistry());
FPCounter = 0;
}
@@ -145,6 +143,8 @@ namespace {
delete Mang;
delete TCtx;
delete TAsm;
+ delete MRI;
+ delete MOFI;
FPConstantMap.clear();
ByValParams.clear();
intrinsicPrototypesAlreadyGenerated.clear();
@@ -152,20 +152,20 @@ namespace {
return false;
}
- raw_ostream &printType(raw_ostream &Out, const Type *Ty,
+ raw_ostream &printType(raw_ostream &Out, Type *Ty,
bool isSigned = false,
const std::string &VariableName = "",
bool IgnoreName = false,
const AttrListPtr &PAL = AttrListPtr());
- raw_ostream &printSimpleType(raw_ostream &Out, const Type *Ty,
+ raw_ostream &printSimpleType(raw_ostream &Out, Type *Ty,
bool isSigned,
const std::string &NameSoFar = "");
void printStructReturnPointerFunctionType(raw_ostream &Out,
const AttrListPtr &PAL,
- const PointerType *Ty);
+ PointerType *Ty);
- std::string getStructName(const StructType *ST);
+ std::string getStructName(StructType *ST);
/// writeOperandDeref - Print the result of dereferencing the specified
/// operand with '*'. This is equivalent to printing '*' then using
@@ -188,7 +188,7 @@ namespace {
void writeOperandWithCast(Value* Operand, const ICmpInst &I);
bool writeInstructionCast(const Instruction &I);
- void writeMemoryAccess(Value *Operand, const Type *OperandType,
+ void writeMemoryAccess(Value *Operand, Type *OperandType,
bool IsVolatile, unsigned Alignment);
private :
@@ -200,7 +200,7 @@ namespace {
void printIntrinsicDefinition(const Function &F, raw_ostream &Out);
void printModuleTypes();
- void printContainedStructs(const Type *Ty, SmallPtrSet<const Type *, 16> &);
+ void printContainedStructs(Type *Ty, SmallPtrSet<Type *, 16> &);
void printFloatingPointConstants(Function &F);
void printFloatingPointConstants(const Constant *C);
void printFunctionSignature(const Function *F, bool Prototype);
@@ -209,7 +209,7 @@ namespace {
void printBasicBlock(BasicBlock *BB);
void printLoop(Loop *L);
- void printCast(unsigned opcode, const Type *SrcTy, const Type *DstTy);
+ void printCast(unsigned opcode, Type *SrcTy, Type *DstTy);
void printConstant(Constant *CPV, bool Static);
void printConstantWithCast(Constant *CPV, unsigned Opcode);
bool printConstExprCast(const ConstantExpr *CE, bool Static);
@@ -288,10 +288,12 @@ namespace {
void visitInvokeInst(InvokeInst &I) {
llvm_unreachable("Lowerinvoke pass didn't work!");
}
-
void visitUnwindInst(UnwindInst &I) {
llvm_unreachable("Lowerinvoke pass didn't work!");
}
+ void visitResumeInst(ResumeInst &I) {
+ llvm_unreachable("DwarfEHPrepare pass didn't work!");
+ }
void visitUnreachableInst(UnreachableInst &I);
void visitPHINode(PHINode &I);
@@ -360,8 +362,8 @@ static std::string CBEMangle(const std::string &S) {
return Result;
}
-std::string CWriter::getStructName(const StructType *ST) {
- if (!ST->isAnonymous() && !ST->getName().empty())
+std::string CWriter::getStructName(StructType *ST) {
+ if (!ST->isLiteral() && !ST->getName().empty())
return CBEMangle("l_"+ST->getName().str());
return "l_unnamed_" + utostr(UnnamedStructIDs[ST]);
@@ -373,20 +375,20 @@ std::string CWriter::getStructName(const StructType *ST) {
/// print it as "Struct (*)(...)", for struct return functions.
void CWriter::printStructReturnPointerFunctionType(raw_ostream &Out,
const AttrListPtr &PAL,
- const PointerType *TheTy) {
- const FunctionType *FTy = cast<FunctionType>(TheTy->getElementType());
+ PointerType *TheTy) {
+ FunctionType *FTy = cast<FunctionType>(TheTy->getElementType());
std::string tstr;
raw_string_ostream FunctionInnards(tstr);
FunctionInnards << " (*) (";
bool PrintedType = false;
FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end();
- const Type *RetTy = cast<PointerType>(*I)->getElementType();
+ Type *RetTy = cast<PointerType>(*I)->getElementType();
unsigned Idx = 1;
for (++I, ++Idx; I != E; ++I, ++Idx) {
if (PrintedType)
FunctionInnards << ", ";
- const Type *ArgTy = *I;
+ Type *ArgTy = *I;
if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
assert(ArgTy->isPointerTy());
ArgTy = cast<PointerType>(ArgTy)->getElementType();
@@ -408,7 +410,7 @@ void CWriter::printStructReturnPointerFunctionType(raw_ostream &Out,
}
raw_ostream &
-CWriter::printSimpleType(raw_ostream &Out, const Type *Ty, bool isSigned,
+CWriter::printSimpleType(raw_ostream &Out, Type *Ty, bool isSigned,
const std::string &NameSoFar) {
assert((Ty->isPrimitiveType() || Ty->isIntegerTy() || Ty->isVectorTy()) &&
"Invalid type for printSimpleType");
@@ -444,7 +446,7 @@ CWriter::printSimpleType(raw_ostream &Out, const Type *Ty, bool isSigned,
" __attribute__((vector_size(64))) " + NameSoFar);
case Type::VectorTyID: {
- const VectorType *VTy = cast<VectorType>(Ty);
+ VectorType *VTy = cast<VectorType>(Ty);
return printSimpleType(Out, VTy->getElementType(), isSigned,
" __attribute__((vector_size(" +
utostr(TD->getTypeAllocSize(VTy)) + " ))) " + NameSoFar);
@@ -461,7 +463,7 @@ CWriter::printSimpleType(raw_ostream &Out, const Type *Ty, bool isSigned,
// Pass the Type* and the variable name and this prints out the variable
// declaration.
//
-raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
+raw_ostream &CWriter::printType(raw_ostream &Out, Type *Ty,
bool isSigned, const std::string &NameSoFar,
bool IgnoreName, const AttrListPtr &PAL) {
if (Ty->isPrimitiveType() || Ty->isIntegerTy() || Ty->isVectorTy()) {
@@ -471,14 +473,14 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
switch (Ty->getTypeID()) {
case Type::FunctionTyID: {
- const FunctionType *FTy = cast<FunctionType>(Ty);
+ FunctionType *FTy = cast<FunctionType>(Ty);
std::string tstr;
raw_string_ostream FunctionInnards(tstr);
FunctionInnards << " (" << NameSoFar << ") (";
unsigned Idx = 1;
for (FunctionType::param_iterator I = FTy->param_begin(),
E = FTy->param_end(); I != E; ++I) {
- const Type *ArgTy = *I;
+ Type *ArgTy = *I;
if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
assert(ArgTy->isPointerTy());
ArgTy = cast<PointerType>(ArgTy)->getElementType();
@@ -502,7 +504,7 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
return Out;
}
case Type::StructTyID: {
- const StructType *STy = cast<StructType>(Ty);
+ StructType *STy = cast<StructType>(Ty);
// Check to see if the type is named.
if (!IgnoreName)
@@ -523,7 +525,7 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
}
case Type::PointerTyID: {
- const PointerType *PTy = cast<PointerType>(Ty);
+ PointerType *PTy = cast<PointerType>(Ty);
std::string ptrName = "*" + NameSoFar;
if (PTy->getElementType()->isArrayTy() ||
@@ -537,7 +539,7 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
}
case Type::ArrayTyID: {
- const ArrayType *ATy = cast<ArrayType>(Ty);
+ ArrayType *ATy = cast<ArrayType>(Ty);
unsigned NumElements = ATy->getNumElements();
if (NumElements == 0) NumElements = 1;
// Arrays are wrapped in structs to allow them to have normal
@@ -560,7 +562,7 @@ void CWriter::printConstantArray(ConstantArray *CPA, bool Static) {
// As a special case, print the array as a string if it is an array of
// ubytes or an array of sbytes with positive values.
//
- const Type *ETy = CPA->getType()->getElementType();
+ Type *ETy = CPA->getType()->getElementType();
bool isString = (ETy == Type::getInt8Ty(CPA->getContext()) ||
ETy == Type::getInt8Ty(CPA->getContext()));
@@ -682,7 +684,7 @@ static bool isFPCSafeToPrint(const ConstantFP *CFP) {
/// Print out the casting for a cast operation. This does the double casting
/// necessary for conversion to the destination type, if necessary.
/// @brief Print a cast
-void CWriter::printCast(unsigned opc, const Type *SrcTy, const Type *DstTy) {
+void CWriter::printCast(unsigned opc, Type *SrcTy, Type *DstTy) {
// Print the destination type cast
switch (opc) {
case Instruction::UIToFP:
@@ -917,7 +919,7 @@ void CWriter::printConstant(Constant *CPV, bool Static) {
}
if (ConstantInt *CI = dyn_cast<ConstantInt>(CPV)) {
- const Type* Ty = CI->getType();
+ Type* Ty = CI->getType();
if (Ty == Type::getInt1Ty(CPV->getContext()))
Out << (CI->getZExtValue() ? '1' : '0');
else if (Ty == Type::getInt32Ty(CPV->getContext()))
@@ -1027,7 +1029,7 @@ void CWriter::printConstant(Constant *CPV, bool Static) {
printConstantArray(CA, Static);
} else {
assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
- const ArrayType *AT = cast<ArrayType>(CPV->getType());
+ ArrayType *AT = cast<ArrayType>(CPV->getType());
Out << '{';
if (AT->getNumElements()) {
Out << ' ';
@@ -1054,7 +1056,7 @@ void CWriter::printConstant(Constant *CPV, bool Static) {
printConstantVector(CV, Static);
} else {
assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
- const VectorType *VT = cast<VectorType>(CPV->getType());
+ VectorType *VT = cast<VectorType>(CPV->getType());
Out << "{ ";
Constant *CZ = Constant::getNullValue(VT->getElementType());
printConstant(CZ, Static);
@@ -1074,7 +1076,7 @@ void CWriter::printConstant(Constant *CPV, bool Static) {
Out << ")";
}
if (isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV)) {
- const StructType *ST = cast<StructType>(CPV->getType());
+ StructType *ST = cast<StructType>(CPV->getType());
Out << '{';
if (ST->getNumElements()) {
Out << ' ';
@@ -1123,7 +1125,7 @@ void CWriter::printConstant(Constant *CPV, bool Static) {
// care of detecting that case and printing the cast for the ConstantExpr.
bool CWriter::printConstExprCast(const ConstantExpr* CE, bool Static) {
bool NeedsExplicitCast = false;
- const Type *Ty = CE->getOperand(0)->getType();
+ Type *Ty = CE->getOperand(0)->getType();
bool TypeIsSigned = false;
switch (CE->getOpcode()) {
case Instruction::Add:
@@ -1175,7 +1177,7 @@ bool CWriter::printConstExprCast(const ConstantExpr* CE, bool Static) {
void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
// Extract the operand's type, we'll need it.
- const Type* OpTy = CPV->getType();
+ Type* OpTy = CPV->getType();
// Indicate whether to do the cast or not.
bool shouldCast = false;
@@ -1267,7 +1269,7 @@ std::string CWriter::GetValueName(const Value *Operand) {
void CWriter::writeInstComputationInline(Instruction &I) {
// We can't currently support integer types other than 1, 8, 16, 32, 64.
// Validate this.
- const Type *Ty = I.getType();
+ Type *Ty = I.getType();
if (Ty->isIntegerTy() && (Ty!=Type::getInt1Ty(I.getContext()) &&
Ty!=Type::getInt8Ty(I.getContext()) &&
Ty!=Type::getInt16Ty(I.getContext()) &&
@@ -1330,7 +1332,7 @@ void CWriter::writeOperand(Value *Operand, bool Static) {
// This function takes care of detecting that case and printing the cast
// for the Instruction.
bool CWriter::writeInstructionCast(const Instruction &I) {
- const Type *Ty = I.getOperand(0)->getType();
+ Type *Ty = I.getOperand(0)->getType();
switch (I.getOpcode()) {
case Instruction::Add:
case Instruction::Sub:
@@ -1362,7 +1364,7 @@ bool CWriter::writeInstructionCast(const Instruction &I) {
void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
// Extract the operand's type, we'll need it.
- const Type* OpTy = Operand->getType();
+ Type* OpTy = Operand->getType();
// Indicate whether to do the cast or not.
bool shouldCast = false;
@@ -1430,7 +1432,7 @@ void CWriter::writeOperandWithCast(Value* Operand, const ICmpInst &Cmp) {
bool castIsSigned = Cmp.isSigned();
// If the operand was a pointer, convert to a large integer type.
- const Type* OpTy = Operand->getType();
+ Type* OpTy = Operand->getType();
if (OpTy->isPointerTy())
OpTy = TD->getIntPtrType(Operand->getContext());
@@ -1665,7 +1667,8 @@ bool CWriter::doInitialization(Module &M) {
TAsm = Match->createMCAsmInfo(Triple);
#endif
TAsm = new CBEMCAsmInfo();
- TCtx = new MCContext(*TAsm, NULL);
+ MRI = new MCRegisterInfo();
+ TCtx = new MCContext(*TAsm, *MRI, NULL);
Mang = new Mangler(*TCtx, *TD);
// Keep track of which functions are static ctors/dtors so they can have
@@ -2049,7 +2052,7 @@ void CWriter::printModuleTypes() {
for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) {
StructType *ST = StructTypes[i];
- if (ST->isAnonymous() || ST->getName().empty())
+ if (ST->isLiteral() || ST->getName().empty())
UnnamedStructIDs[ST] = NextTypeID++;
std::string Name = getStructName(ST);
@@ -2060,7 +2063,7 @@ void CWriter::printModuleTypes() {
Out << '\n';
// Keep track of which structures have been printed so far.
- SmallPtrSet<const Type *, 16> StructPrinted;
+ SmallPtrSet<Type *, 16> StructPrinted;
// Loop over all structures then push them into the stack so they are
// printed in the correct order.
@@ -2077,8 +2080,8 @@ void CWriter::printModuleTypes() {
//
// TODO: Make this work properly with vector types
//
-void CWriter::printContainedStructs(const Type *Ty,
- SmallPtrSet<const Type *, 16> &StructPrinted) {
+void CWriter::printContainedStructs(Type *Ty,
+ SmallPtrSet<Type *, 16> &StructPrinted) {
// Don't walk through pointers.
if (Ty->isPointerTy() || Ty->isPrimitiveType() || Ty->isIntegerTy())
return;
@@ -2088,7 +2091,7 @@ void CWriter::printContainedStructs(const Type *Ty,
E = Ty->subtype_end(); I != E; ++I)
printContainedStructs(*I, StructPrinted);
- if (const StructType *ST = dyn_cast<StructType>(Ty)) {
+ if (StructType *ST = dyn_cast<StructType>(Ty)) {
// Check to see if we have already printed this struct.
if (!StructPrinted.insert(Ty)) return;
@@ -2120,7 +2123,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
}
// Loop over the arguments, printing them...
- const FunctionType *FT = cast<FunctionType>(F->getFunctionType());
+ FunctionType *FT = cast<FunctionType>(F->getFunctionType());
const AttrListPtr &PAL = F->getAttributes();
std::string tstr;
@@ -2150,7 +2153,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
ArgName = GetValueName(I);
else
ArgName = "";
- const Type *ArgTy = I->getType();
+ Type *ArgTy = I->getType();
if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
ArgTy = cast<PointerType>(ArgTy)->getElementType();
ByValParams.insert(I);
@@ -2177,7 +2180,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
for (; I != E; ++I) {
if (PrintedArg) FunctionInnards << ", ";
- const Type *ArgTy = *I;
+ Type *ArgTy = *I;
if (PAL.paramHasAttr(Idx, Attribute::ByVal)) {
assert(ArgTy->isPointerTy());
ArgTy = cast<PointerType>(ArgTy)->getElementType();
@@ -2205,7 +2208,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
FunctionInnards << ')';
// Get the return tpe for the function.
- const Type *RetTy;
+ Type *RetTy;
if (!isStructReturn)
RetTy = F->getReturnType();
else {
@@ -2222,8 +2225,8 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
static inline bool isFPIntBitCast(const Instruction &I) {
if (!isa<BitCastInst>(I))
return false;
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DstTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DstTy = I.getType();
return (SrcTy->isFloatingPointTy() && DstTy->isIntegerTy()) ||
(DstTy->isFloatingPointTy() && SrcTy->isIntegerTy());
}
@@ -2237,7 +2240,7 @@ void CWriter::printFunction(Function &F) {
// If this is a struct return function, handle the result with magic.
if (isStructReturn) {
- const Type *StructTy =
+ Type *StructTy =
cast<PointerType>(F.arg_begin()->getType())->getElementType();
Out << " ";
printType(Out, StructTy, false, "StructReturn");
@@ -2380,22 +2383,29 @@ void CWriter::visitReturnInst(ReturnInst &I) {
void CWriter::visitSwitchInst(SwitchInst &SI) {
+ Value* Cond = SI.getCondition();
+
Out << " switch (";
- writeOperand(SI.getOperand(0));
+ writeOperand(Cond);
Out << ") {\n default:\n";
printPHICopiesForSuccessor (SI.getParent(), SI.getDefaultDest(), 2);
printBranchToBlock(SI.getParent(), SI.getDefaultDest(), 2);
Out << ";\n";
- for (unsigned i = 2, e = SI.getNumOperands(); i != e; i += 2) {
+
+ unsigned NumCases = SI.getNumCases();
+ // Skip the first item since that's the default case.
+ for (unsigned i = 1; i < NumCases; ++i) {
+ ConstantInt* CaseVal = SI.getCaseValue(i);
+ BasicBlock* Succ = SI.getSuccessor(i);
Out << " case ";
- writeOperand(SI.getOperand(i));
+ writeOperand(CaseVal);
Out << ":\n";
- BasicBlock *Succ = cast<BasicBlock>(SI.getOperand(i+1));
printPHICopiesForSuccessor (SI.getParent(), Succ, 2);
printBranchToBlock(SI.getParent(), Succ, 2);
if (Function::iterator(Succ) == llvm::next(Function::iterator(SI.getParent())))
Out << " break;\n";
}
+
Out << " }\n";
}
@@ -2656,7 +2666,7 @@ void CWriter::visitFCmpInst(FCmpInst &I) {
Out << ")";
}
-static const char * getFloatBitCastField(const Type *Ty) {
+static const char * getFloatBitCastField(Type *Ty) {
switch (Ty->getTypeID()) {
default: llvm_unreachable("Invalid Type");
case Type::FloatTyID: return "Float";
@@ -2672,8 +2682,8 @@ static const char * getFloatBitCastField(const Type *Ty) {
}
void CWriter::visitCastInst(CastInst &I) {
- const Type *DstTy = I.getType();
- const Type *SrcTy = I.getOperand(0)->getType();
+ Type *DstTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
if (isFPIntBitCast(I)) {
Out << '(';
// These int<->float and long<->double casts need to be handled specially
@@ -2719,7 +2729,7 @@ void CWriter::visitSelectInst(SelectInst &I) {
// Returns the macro name or value of the max or min of an integer type
// (as defined in limits.h).
-static void printLimitValue(const IntegerType &Ty, bool isSigned, bool isMax,
+static void printLimitValue(IntegerType &Ty, bool isSigned, bool isMax,
raw_ostream &Out) {
const char* type;
const char* sprefix = "";
@@ -2745,16 +2755,16 @@ static void printLimitValue(const IntegerType &Ty, bool isSigned, bool isMax,
}
#ifndef NDEBUG
-static bool isSupportedIntegerSize(const IntegerType &T) {
+static bool isSupportedIntegerSize(IntegerType &T) {
return T.getBitWidth() == 8 || T.getBitWidth() == 16 ||
T.getBitWidth() == 32 || T.getBitWidth() == 64;
}
#endif
void CWriter::printIntrinsicDefinition(const Function &F, raw_ostream &Out) {
- const FunctionType *funT = F.getFunctionType();
- const Type *retT = F.getReturnType();
- const IntegerType *elemT = cast<IntegerType>(funT->getParamType(1));
+ FunctionType *funT = F.getFunctionType();
+ Type *retT = F.getReturnType();
+ IntegerType *elemT = cast<IntegerType>(funT->getParamType(1));
assert(isSupportedIntegerSize(*elemT) &&
"CBackend does not support arbitrary size integers.");
@@ -2829,7 +2839,6 @@ void CWriter::lowerIntrinsics(Function &F) {
if (Function *F = CI->getCalledFunction())
switch (F->getIntrinsicID()) {
case Intrinsic::not_intrinsic:
- case Intrinsic::memory_barrier:
case Intrinsic::vastart:
case Intrinsic::vacopy:
case Intrinsic::vaend:
@@ -2908,8 +2917,8 @@ void CWriter::visitCallInst(CallInst &I) {
Value *Callee = I.getCalledValue();
- const PointerType *PTy = cast<PointerType>(Callee->getType());
- const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+ PointerType *PTy = cast<PointerType>(Callee->getType());
+ FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
// If this is a call to a struct-return function, assign to the first
// parameter instead of passing it to the call.
@@ -3020,9 +3029,6 @@ bool CWriter::visitBuiltinCall(CallInst &I, Intrinsic::ID ID,
WroteCallee = true;
return false;
}
- case Intrinsic::memory_barrier:
- Out << "__sync_synchronize()";
- return true;
case Intrinsic::vastart:
Out << "0; ";
@@ -3217,7 +3223,7 @@ void CWriter::visitInlineAsm(CallInst &CI) {
std::vector<std::pair<Value*, int> > ResultVals;
if (CI.getType() == Type::getVoidTy(CI.getContext()))
;
- else if (const StructType *ST = dyn_cast<StructType>(CI.getType())) {
+ else if (StructType *ST = dyn_cast<StructType>(CI.getType())) {
for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i)
ResultVals.push_back(std::make_pair(&CI, (int)i));
} else {
@@ -3348,7 +3354,7 @@ void CWriter::printGEPExpression(Value *Ptr, gep_type_iterator I,
// Find out if the last index is into a vector. If so, we have to print this
// specially. Since vectors can't have elements of indexable type, only the
// last index could possibly be of a vector element.
- const VectorType *LastIndexIsVector = 0;
+ VectorType *LastIndexIsVector = 0;
{
for (gep_type_iterator TmpI = I; TmpI != E; ++TmpI)
LastIndexIsVector = dyn_cast<VectorType>(*TmpI);
@@ -3421,7 +3427,7 @@ void CWriter::printGEPExpression(Value *Ptr, gep_type_iterator I,
Out << ")";
}
-void CWriter::writeMemoryAccess(Value *Operand, const Type *OperandType,
+void CWriter::writeMemoryAccess(Value *Operand, Type *OperandType,
bool IsVolatile, unsigned Alignment) {
bool IsUnaligned = Alignment &&
@@ -3463,7 +3469,7 @@ void CWriter::visitStoreInst(StoreInst &I) {
Out << " = ";
Value *Operand = I.getOperand(0);
Constant *BitMask = 0;
- if (const IntegerType* ITy = dyn_cast<IntegerType>(Operand->getType()))
+ if (IntegerType* ITy = dyn_cast<IntegerType>(Operand->getType()))
if (!ITy->isPowerOf2ByteWidth())
// We have a bit width that doesn't match an even power-of-2 byte
// size. Consequently we must & the value with the type's bit mask
@@ -3492,7 +3498,7 @@ void CWriter::visitVAArgInst(VAArgInst &I) {
}
void CWriter::visitInsertElementInst(InsertElementInst &I) {
- const Type *EltTy = I.getType()->getElementType();
+ Type *EltTy = I.getType()->getElementType();
writeOperand(I.getOperand(0));
Out << ";\n ";
Out << "((";
@@ -3507,7 +3513,7 @@ void CWriter::visitInsertElementInst(InsertElementInst &I) {
void CWriter::visitExtractElementInst(ExtractElementInst &I) {
// We know that our operand is not inlined.
Out << "((";
- const Type *EltTy =
+ Type *EltTy =
cast<VectorType>(I.getOperand(0)->getType())->getElementType();
printType(Out, PointerType::getUnqual(EltTy));
Out << ")(&" << GetValueName(I.getOperand(0)) << "))[";
@@ -3519,9 +3525,9 @@ void CWriter::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
Out << "(";
printType(Out, SVI.getType());
Out << "){ ";
- const VectorType *VT = SVI.getType();
+ VectorType *VT = SVI.getType();
unsigned NumElts = VT->getNumElements();
- const Type *EltTy = VT->getElementType();
+ Type *EltTy = VT->getElementType();
for (unsigned i = 0; i != NumElts; ++i) {
if (i) Out << ", ";
@@ -3557,9 +3563,9 @@ void CWriter::visitInsertValueInst(InsertValueInst &IVI) {
Out << GetValueName(&IVI);
for (const unsigned *b = IVI.idx_begin(), *i = b, *e = IVI.idx_end();
i != e; ++i) {
- const Type *IndexedTy =
+ Type *IndexedTy =
ExtractValueInst::getIndexedType(IVI.getOperand(0)->getType(),
- ArrayRef<unsigned>(b, i+1));
+ makeArrayRef(b, i+1));
if (IndexedTy->isArrayTy())
Out << ".array[" << *i << "]";
else
@@ -3579,9 +3585,9 @@ void CWriter::visitExtractValueInst(ExtractValueInst &EVI) {
Out << GetValueName(EVI.getOperand(0));
for (const unsigned *b = EVI.idx_begin(), *i = b, *e = EVI.idx_end();
i != e; ++i) {
- const Type *IndexedTy =
+ Type *IndexedTy =
ExtractValueInst::getIndexedType(EVI.getOperand(0)->getType(),
- ArrayRef<unsigned>(b, i+1));
+ makeArrayRef(b, i+1));
if (IndexedTy->isArrayTy())
Out << ".array[" << *i << "]";
else
diff --git a/lib/Target/CBackend/CMakeLists.txt b/lib/Target/CBackend/CMakeLists.txt
index a23ff85..96ae49f 100644
--- a/lib/Target/CBackend/CMakeLists.txt
+++ b/lib/Target/CBackend/CMakeLists.txt
@@ -2,4 +2,16 @@ add_llvm_target(CBackend
CBackend.cpp
)
+add_llvm_library_dependencies(LLVMCBackend
+ LLVMAnalysis
+ LLVMCBackendInfo
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMScalarOpts
+ LLVMSupport
+ LLVMTarget
+ LLVMTransformUtils
+ )
+
add_subdirectory(TargetInfo)
diff --git a/lib/Target/CBackend/CTargetMachine.h b/lib/Target/CBackend/CTargetMachine.h
index e64216b..4f1ca97 100644
--- a/lib/Target/CBackend/CTargetMachine.h
+++ b/lib/Target/CBackend/CTargetMachine.h
@@ -20,8 +20,9 @@
namespace llvm {
struct CTargetMachine : public TargetMachine {
- CTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS)
+ CTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
: TargetMachine(T, TT, CPU, FS) {}
virtual bool addPassesToEmitFile(PassManagerBase &PM,
diff --git a/lib/Target/CBackend/TargetInfo/CBackendTargetInfo.cpp b/lib/Target/CBackend/TargetInfo/CBackendTargetInfo.cpp
index f7e8ff2..e8274ff 100644
--- a/lib/Target/CBackend/TargetInfo/CBackendTargetInfo.cpp
+++ b/lib/Target/CBackend/TargetInfo/CBackendTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "CTargetMachine.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::TheCBackendTarget;
@@ -17,3 +17,5 @@ Target llvm::TheCBackendTarget;
extern "C" void LLVMInitializeCBackendTargetInfo() {
RegisterTarget<> X(TheCBackendTarget, "c", "C backend");
}
+
+extern "C" void LLVMInitializeCBackendTargetMC() {}
diff --git a/lib/Target/CBackend/TargetInfo/CMakeLists.txt b/lib/Target/CBackend/TargetInfo/CMakeLists.txt
index 5b35fa7..8e616be 100644
--- a/lib/Target/CBackend/TargetInfo/CMakeLists.txt
+++ b/lib/Target/CBackend/TargetInfo/CMakeLists.txt
@@ -4,3 +4,8 @@ add_llvm_library(LLVMCBackendInfo
CBackendTargetInfo.cpp
)
+add_llvm_library_dependencies(LLVMCBackendInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
diff --git a/lib/Target/CMakeLists.txt b/lib/Target/CMakeLists.txt
index f982316..030f808 100644
--- a/lib/Target/CMakeLists.txt
+++ b/lib/Target/CMakeLists.txt
@@ -1,8 +1,6 @@
add_llvm_library(LLVMTarget
Mangler.cpp
Target.cpp
- TargetAsmInfo.cpp
- TargetAsmLexer.cpp
TargetData.cpp
TargetELFWriterInfo.cpp
TargetFrameLowering.cpp
@@ -15,6 +13,12 @@ add_llvm_library(LLVMTarget
TargetSubtargetInfo.cpp
)
+add_llvm_library_dependencies(LLVMTarget
+ LLVMCore
+ LLVMMC
+ LLVMSupport
+ )
+
set(LLVM_ENUM_ASM_PRINTERS "")
set(LLVM_ENUM_ASM_PARSERS "")
set(LLVM_ENUM_DISASSEMBLERS "")
diff --git a/lib/Target/CellSPU/CMakeLists.txt b/lib/Target/CellSPU/CMakeLists.txt
index 0b94e0c..158fb3e 100644
--- a/lib/Target/CellSPU/CMakeLists.txt
+++ b/lib/Target/CellSPU/CMakeLists.txt
@@ -1,12 +1,13 @@
set(LLVM_TARGET_DEFINITIONS SPU.td)
-tablegen(SPUGenAsmWriter.inc -gen-asm-writer)
-tablegen(SPUGenCodeEmitter.inc -gen-emitter)
-tablegen(SPUGenRegisterInfo.inc -gen-register-info)
-tablegen(SPUGenInstrInfo.inc -gen-instr-info)
-tablegen(SPUGenDAGISel.inc -gen-dag-isel)
-tablegen(SPUGenSubtargetInfo.inc -gen-subtarget)
-tablegen(SPUGenCallingConv.inc -gen-callingconv)
+llvm_tablegen(SPUGenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(SPUGenCodeEmitter.inc -gen-emitter)
+llvm_tablegen(SPUGenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(SPUGenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(SPUGenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(SPUGenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(SPUGenCallingConv.inc -gen-callingconv)
+add_public_tablegen_target(CellSPUCommonTableGen)
add_llvm_target(CellSPUCodeGen
SPUAsmPrinter.cpp
@@ -22,5 +23,17 @@ add_llvm_target(CellSPUCodeGen
SPUNopFiller.cpp
)
+add_llvm_library_dependencies(LLVMCellSPUCodeGen
+ LLVMAsmPrinter
+ LLVMCellSPUDesc
+ LLVMCellSPUInfo
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMTarget
+ )
+
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
diff --git a/lib/Target/CellSPU/MCTargetDesc/CMakeLists.txt b/lib/Target/CellSPU/MCTargetDesc/CMakeLists.txt
index 85fb258..d41fe93 100644
--- a/lib/Target/CellSPU/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/CellSPU/MCTargetDesc/CMakeLists.txt
@@ -2,3 +2,10 @@ add_llvm_library(LLVMCellSPUDesc
SPUMCTargetDesc.cpp
SPUMCAsmInfo.cpp
)
+
+add_llvm_library_dependencies(LLVMCellSPUDesc
+ LLVMCellSPUInfo
+ LLVMMC
+ )
+
+add_dependencies(LLVMCellSPUDesc CellSPUCommonTableGen)
diff --git a/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.cpp b/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.cpp
index 26c5a4b..d5af2a8 100644
--- a/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.cpp
+++ b/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.cpp
@@ -13,10 +13,12 @@
#include "SPUMCTargetDesc.h"
#include "SPUMCAsmInfo.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_MC_DESC
#include "SPUGenInstrInfo.inc"
@@ -35,8 +37,10 @@ static MCInstrInfo *createSPUMCInstrInfo() {
return X;
}
-extern "C" void LLVMInitializeCellSPUMCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(TheCellSPUTarget, createSPUMCInstrInfo);
+static MCRegisterInfo *createCellSPUMCRegisterInfo(StringRef TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitSPUMCRegisterInfo(X, SPU::R0);
+ return X;
}
static MCSubtargetInfo *createSPUMCSubtargetInfo(StringRef TT, StringRef CPU,
@@ -46,11 +50,43 @@ static MCSubtargetInfo *createSPUMCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-extern "C" void LLVMInitializeCellSPUMCSubtargetInfo() {
- TargetRegistry::RegisterMCSubtargetInfo(TheCellSPUTarget,
- createSPUMCSubtargetInfo);
+static MCAsmInfo *createSPUMCAsmInfo(const Target &T, StringRef TT) {
+ MCAsmInfo *MAI = new SPULinuxMCAsmInfo(T, TT);
+
+ // Initial state of the frame pointer is R1.
+ MachineLocation Dst(MachineLocation::VirtualFP);
+ MachineLocation Src(SPU::R1, 0);
+ MAI->addInitialFrameState(0, Dst, Src);
+
+ return MAI;
+}
+
+static MCCodeGenInfo *createSPUMCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+ // For the time being, use static relocations, since there's really no
+ // support for PIC yet.
+ X->InitMCCodeGenInfo(Reloc::Static, CM);
+ return X;
}
-extern "C" void LLVMInitializeCellSPUMCAsmInfo() {
- RegisterMCAsmInfo<SPULinuxMCAsmInfo> X(TheCellSPUTarget);
+// Force static initialization.
+extern "C" void LLVMInitializeCellSPUTargetMC() {
+ // Register the MC asm info.
+ RegisterMCAsmInfoFn X(TheCellSPUTarget, createSPUMCAsmInfo);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(TheCellSPUTarget,
+ createSPUMCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheCellSPUTarget, createSPUMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheCellSPUTarget,
+ createCellSPUMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(TheCellSPUTarget,
+ createSPUMCSubtargetInfo);
}
diff --git a/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.h b/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.h
index c5c037d..a3717b0 100644
--- a/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.h
+++ b/lib/Target/CellSPU/MCTargetDesc/SPUMCTargetDesc.h
@@ -1,4 +1,4 @@
-//===-- SPUMCTargetDesc.h - Alpha Target Descriptions ---------*- C++ -*-===//
+//===-- SPUMCTargetDesc.h - CellSPU Target Descriptions ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file provides Alpha specific target descriptions.
+// This file provides CellSPU specific target descriptions.
//
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/CellSPU/SPUAsmPrinter.cpp b/lib/Target/CellSPU/SPUAsmPrinter.cpp
index fd96694..90b5270 100644
--- a/lib/Target/CellSPU/SPUAsmPrinter.cpp
+++ b/lib/Target/CellSPU/SPUAsmPrinter.cpp
@@ -29,10 +29,10 @@
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
diff --git a/lib/Target/CellSPU/SPUFrameLowering.cpp b/lib/Target/CellSPU/SPUFrameLowering.cpp
index a3e7e73..093f99f 100644
--- a/lib/Target/CellSPU/SPUFrameLowering.cpp
+++ b/lib/Target/CellSPU/SPUFrameLowering.cpp
@@ -181,18 +181,6 @@ void SPUFrameLowering::emitPrologue(MachineFunction &MF) const {
MachineLocation FPSrc(MachineLocation::VirtualFP);
Moves.push_back(MachineMove(ReadyLabel, FPDst, FPSrc));
}
- } else {
- // This is a leaf function -- insert a branch hint iff there are
- // sufficient number instructions in the basic block. Note that
- // this is just a best guess based on the basic block's size.
- if (MBB.size() >= (unsigned) SPUFrameLowering::branchHintPenalty()) {
- MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
- dl = MBBI->getDebugLoc();
-
- // Insert terminator label
- BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL))
- .addSym(MMI.getContext().CreateTempSymbol());
- }
}
}
@@ -249,14 +237,6 @@ void SPUFrameLowering::emitEpilogue(MachineFunction &MF,
}
}
-void SPUFrameLowering::getInitialFrameState(std::vector<MachineMove> &Moves)
- const {
- // Initial state of the frame pointer is R1.
- MachineLocation Dst(MachineLocation::VirtualFP);
- MachineLocation Src(SPU::R1, 0);
- Moves.push_back(MachineMove(0, Dst, Src));
-}
-
void SPUFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS) const{
// Mark LR and SP unused, since the prolog spills them to stack and
diff --git a/lib/Target/CellSPU/SPUFrameLowering.h b/lib/Target/CellSPU/SPUFrameLowering.h
index 4fee72d..b837f2c 100644
--- a/lib/Target/CellSPU/SPUFrameLowering.h
+++ b/lib/Target/CellSPU/SPUFrameLowering.h
@@ -43,9 +43,6 @@ namespace llvm {
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS = NULL) const;
- //! Perform target-specific stack frame setup.
- void getInitialFrameState(std::vector<MachineMove> &Moves) const;
-
//! Return a function's saved spill slots
/*!
For CellSPU, a function's saved spill slots is just the link register.
@@ -77,17 +74,6 @@ namespace llvm {
static int FItoStackOffset(int frame_index) {
return frame_index * stackSlotSize();
}
- //! Number of instructions required to overcome hint-for-branch latency
- /*!
- HBR (hint-for-branch) instructions can be inserted when, for example,
- we know that a given function is going to be called, such as printf(),
- in the control flow graph. HBRs are only inserted if a sufficient number
- of instructions occurs between the HBR and the target. Currently, HBRs
- take 6 cycles, ergo, the magic number 6.
- */
- static int branchHintPenalty() {
- return 6;
- }
};
}
diff --git a/lib/Target/CellSPU/SPUISelLowering.cpp b/lib/Target/CellSPU/SPUISelLowering.cpp
index f0ceee2..ac33111 100644
--- a/lib/Target/CellSPU/SPUISelLowering.cpp
+++ b/lib/Target/CellSPU/SPUISelLowering.cpp
@@ -69,7 +69,7 @@ namespace {
TargetLowering::ArgListEntry Entry;
for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
EVT ArgVT = Op.getOperand(i).getValueType();
- const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext());
+ Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext());
Entry.Node = Op.getOperand(i);
Entry.Ty = ArgTy;
Entry.isSExt = isSigned;
@@ -80,7 +80,7 @@ namespace {
TLI.getPointerTy());
// Splice the libcall in wherever FindInputOutputChains tells us to.
- const Type *RetTy =
+ Type *RetTy =
Op.getNode()->getValueType(0).getTypeForEVT(*DAG.getContext());
std::pair<SDValue, SDValue> CallInfo =
TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false,
@@ -174,6 +174,7 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
// SPU has no intrinsics for these particular operations:
setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
+ setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
// SPU has no division/remainder instructions
setOperationAction(ISD::SREM, MVT::i8, Expand);
@@ -401,6 +402,9 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
MVT::SimpleValueType VT = (MVT::SimpleValueType)i;
+ // Set operation actions to legal types only.
+ if (!isTypeLegal(VT)) continue;
+
// add/sub are legal for all supported vector VT's.
setOperationAction(ISD::ADD, VT, Legal);
setOperationAction(ISD::SUB, VT, Legal);
@@ -438,6 +442,7 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
setOperationAction(ISD::FDIV, MVT::v4f32, Legal);
setBooleanContents(ZeroOrNegativeOneBooleanContent);
+ setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); // FIXME: Is this correct?
setStackPointerRegisterToSaveRestore(SPU::R1);
@@ -497,7 +502,7 @@ SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
// Return the Cell SPU's SETCC result type
//===----------------------------------------------------------------------===//
-MVT::SimpleValueType SPUTargetLowering::getSetCCResultType(EVT VT) const {
+EVT SPUTargetLowering::getSetCCResultType(EVT VT) const {
// i8, i16 and i32 are valid SETCC result types
MVT::SimpleValueType retval;
@@ -2727,6 +2732,7 @@ static SDValue LowerSIGN_EXTEND(SDValue Op, SelectionDAG &DAG)
// the type to extend from needs to be i64 or i32.
assert((OpVT == MVT::i128 && (Op0VT == MVT::i64 || Op0VT == MVT::i32)) &&
"LowerSIGN_EXTEND: input and/or output operand have wrong size");
+ (void)OpVT;
// Create shuffle mask
unsigned mask1 = 0x10101010; // byte 0 - 3 and 4 - 7
@@ -3216,7 +3222,7 @@ SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
/// isLegalAddressImmediate - Return true if the integer value can be used
/// as the offset of the target addressing mode.
bool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
- const Type *Ty) const {
+ Type *Ty) const {
// SPU's addresses are 256K:
return (V > -(1 << 18) && V < (1 << 18) - 1);
}
@@ -3239,7 +3245,7 @@ bool SPUTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
bool
SPUTargetLowering::isLegalAddressingMode(const AddrMode &AM,
- const Type * ) const{
+ Type * ) const{
// A-form: 18bit absolute address.
if (AM.BaseGV && !AM.HasBaseReg && AM.Scale == 0 && AM.BaseOffs == 0)
diff --git a/lib/Target/CellSPU/SPUISelLowering.h b/lib/Target/CellSPU/SPUISelLowering.h
index d23f6cc..aa4a168 100644
--- a/lib/Target/CellSPU/SPUISelLowering.h
+++ b/lib/Target/CellSPU/SPUISelLowering.h
@@ -107,7 +107,7 @@ namespace llvm {
virtual const char *getTargetNodeName(unsigned Opcode) const;
/// getSetCCResultType - Return the ValueType for ISD::SETCC
- virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
+ virtual EVT getSetCCResultType(EVT VT) const;
virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; }
@@ -147,7 +147,7 @@ namespace llvm {
/// isLegalAddressImmediate - Return true if the integer value can be used
/// as the offset of the target addressing mode.
- virtual bool isLegalAddressImmediate(int64_t V, const Type *Ty) const;
+ virtual bool isLegalAddressImmediate(int64_t V, Type *Ty) const;
virtual bool isLegalAddressImmediate(GlobalValue *) const;
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
@@ -179,7 +179,7 @@ namespace llvm {
virtual bool isLegalICmpImmediate(int64_t Imm) const;
virtual bool isLegalAddressingMode(const AddrMode &AM,
- const Type *Ty) const;
+ Type *Ty) const;
};
}
diff --git a/lib/Target/CellSPU/SPUInstrInfo.cpp b/lib/Target/CellSPU/SPUInstrInfo.cpp
index e67b10c..007bc0e 100644
--- a/lib/Target/CellSPU/SPUInstrInfo.cpp
+++ b/lib/Target/CellSPU/SPUInstrInfo.cpp
@@ -17,9 +17,9 @@
#include "SPUHazardRecognizers.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/MC/MCContext.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#define GET_INSTRINFO_CTOR
@@ -290,6 +290,8 @@ static void removeHBR( MachineBasicBlock &MBB) {
if (I->getOpcode() == SPU::HBRA ||
I->getOpcode() == SPU::HBR_LABEL){
I=MBB.erase(I);
+ if (I == MBB.end())
+ break;
}
}
}
diff --git a/lib/Target/CellSPU/SPUInstrInfo.td b/lib/Target/CellSPU/SPUInstrInfo.td
index e103c9b..f76ebd7 100644
--- a/lib/Target/CellSPU/SPUInstrInfo.td
+++ b/lib/Target/CellSPU/SPUInstrInfo.td
@@ -1594,8 +1594,8 @@ multiclass BitwiseOrImm
{
def v4i32: ORIVecInst<v4i32, v4i32Uns10Imm>;
- def r32: ORIInst<(outs R32C:$rT), (ins R32C:$rA, u10imm_i32:$val),
- [(set R32C:$rT, (or R32C:$rA, i32ImmUns10:$val))]>;
+ def r32: ORIInst<(outs R32C:$rT), (ins R32C:$rA, s10imm_i32:$val),
+ [(set R32C:$rT, (or R32C:$rA, i32ImmSExt10:$val))]>;
// i16i32: hacked version of the ori instruction to extend 16-bit quantities
// to 32-bit quantities. used exclusively to match "anyext" conversions (vide
@@ -3467,8 +3467,10 @@ let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in {
[/* no pattern */]>;
// Indirect branch
- def BI:
- BIForm<0b00010101100, "bi\t$func", [(brind R32C:$func)]>;
+ let isIndirectBranch = 1 in {
+ def BI:
+ BIForm<0b00010101100, "bi\t$func", [(brind R32C:$func)]>;
+ }
}
// Conditional branches:
diff --git a/lib/Target/CellSPU/SPURegisterInfo.cpp b/lib/Target/CellSPU/SPURegisterInfo.cpp
index 19896c0..bbac6fd 100644
--- a/lib/Target/CellSPU/SPURegisterInfo.cpp
+++ b/lib/Target/CellSPU/SPURegisterInfo.cpp
@@ -25,7 +25,6 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/ValueTypes.h"
@@ -187,7 +186,7 @@ unsigned SPURegisterInfo::getRegisterNumbering(unsigned RegEnum) {
SPURegisterInfo::SPURegisterInfo(const SPUSubtarget &subtarget,
const TargetInstrInfo &tii) :
- SPUGenRegisterInfo(), Subtarget(subtarget), TII(tii)
+ SPUGenRegisterInfo(SPU::R0), Subtarget(subtarget), TII(tii)
{
}
@@ -311,28 +310,12 @@ SPURegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
}
unsigned
-SPURegisterInfo::getRARegister() const
-{
- return SPU::R0;
-}
-
-unsigned
SPURegisterInfo::getFrameRegister(const MachineFunction &MF) const
{
return SPU::R1;
}
int
-SPURegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
- // FIXME: Most probably dwarf numbers differs for Linux and Darwin
- return SPUGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
-}
-
-int SPURegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const {
- return SPUGenRegisterInfo::getLLVMRegNumFull(RegNum, 0);
-}
-
-int
SPURegisterInfo::convertDFormToXForm(int dFormOpcode) const
{
switch(dFormOpcode)
diff --git a/lib/Target/CellSPU/SPURegisterInfo.h b/lib/Target/CellSPU/SPURegisterInfo.h
index 5e014f8..b7818a4 100644
--- a/lib/Target/CellSPU/SPURegisterInfo.h
+++ b/lib/Target/CellSPU/SPURegisterInfo.h
@@ -74,8 +74,6 @@ namespace llvm {
void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
RegScavenger *RS = NULL) const;
- //! Get return address register (LR, aka R0)
- unsigned getRARegister() const;
//! Get the stack frame register (SP, aka R1)
unsigned getFrameRegister(const MachineFunction &MF) const;
@@ -83,10 +81,6 @@ namespace llvm {
// New methods added:
//------------------------------------------------------------------------
- //! Get DWARF debugging register number
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- int getLLVMRegNum(unsigned RegNum, bool isEH) const;
-
//! Convert D-form load/store to X-form load/store
/*!
Converts a regiser displacement load/store into a register-indexed
diff --git a/lib/Target/CellSPU/SPUSubtarget.cpp b/lib/Target/CellSPU/SPUSubtarget.cpp
index 856dc82..43335ab 100644
--- a/lib/Target/CellSPU/SPUSubtarget.cpp
+++ b/lib/Target/CellSPU/SPUSubtarget.cpp
@@ -14,7 +14,7 @@
#include "SPUSubtarget.h"
#include "SPU.h"
#include "SPURegisterInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/ADT/SmallVector.h"
#define GET_SUBTARGETINFO_TARGET_DESC
diff --git a/lib/Target/CellSPU/SPUTargetMachine.cpp b/lib/Target/CellSPU/SPUTargetMachine.cpp
index 3542a2b..93a7f6e 100644
--- a/lib/Target/CellSPU/SPUTargetMachine.cpp
+++ b/lib/Target/CellSPU/SPUTargetMachine.cpp
@@ -16,7 +16,8 @@
#include "llvm/PassManager.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
@@ -31,9 +32,10 @@ SPUFrameLowering::getCalleeSaveSpillSlots(unsigned &NumEntries) const {
return &LR[0];
}
-SPUTargetMachine::SPUTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,const std::string &FS)
- : LLVMTargetMachine(T, TT, CPU, FS),
+SPUTargetMachine::SPUTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
Subtarget(TT, CPU, FS),
DataLayout(Subtarget.getTargetDataString()),
InstrInfo(*this),
@@ -41,9 +43,6 @@ SPUTargetMachine::SPUTargetMachine(const Target &T, const std::string &TT,
TLInfo(*this),
TSInfo(*this),
InstrItins(Subtarget.getInstrItineraryData()) {
- // For the time being, use static relocations, since there's really no
- // support for PIC yet.
- setRelocationModel(Reloc::Static);
}
//===----------------------------------------------------------------------===//
@@ -59,8 +58,16 @@ bool SPUTargetMachine::addInstSelector(PassManagerBase &PM,
// passes to run just before printing the assembly
bool SPUTargetMachine::
-addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
-{
+addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel) {
+ // load the TCE instruction scheduler, if available via
+ // loaded plugins
+ typedef llvm::FunctionPass* (*BuilderFunc)(const char*);
+ BuilderFunc schedulerCreator =
+ (BuilderFunc)(intptr_t)sys::DynamicLibrary::SearchForAddressOfSymbol(
+ "createTCESchedulerPass");
+ if (schedulerCreator != NULL)
+ PM.add(schedulerCreator("cellspu"));
+
//align instructions with nops/lnops for dual issue
PM.add(createSPUNopFillerPass(*this));
return true;
diff --git a/lib/Target/CellSPU/SPUTargetMachine.h b/lib/Target/CellSPU/SPUTargetMachine.h
index d96f86d..fffe77c 100644
--- a/lib/Target/CellSPU/SPUTargetMachine.h
+++ b/lib/Target/CellSPU/SPUTargetMachine.h
@@ -38,8 +38,9 @@ class SPUTargetMachine : public LLVMTargetMachine {
SPUSelectionDAGInfo TSInfo;
InstrItineraryData InstrItins;
public:
- SPUTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ SPUTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
/// Return the subtarget implementation object
virtual const SPUSubtarget *getSubtargetImpl() const {
diff --git a/lib/Target/CellSPU/TargetInfo/CMakeLists.txt b/lib/Target/CellSPU/TargetInfo/CMakeLists.txt
index 928d0fe..3f2d6b0 100644
--- a/lib/Target/CellSPU/TargetInfo/CMakeLists.txt
+++ b/lib/Target/CellSPU/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMCellSPUInfo
CellSPUTargetInfo.cpp
)
-add_dependencies(LLVMCellSPUInfo CellSPUCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMCellSPUInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMCellSPUInfo CellSPUCommonTableGen)
diff --git a/lib/Target/CellSPU/TargetInfo/CellSPUTargetInfo.cpp b/lib/Target/CellSPU/TargetInfo/CellSPUTargetInfo.cpp
index 049ea23..84aadfa 100644
--- a/lib/Target/CellSPU/TargetInfo/CellSPUTargetInfo.cpp
+++ b/lib/Target/CellSPU/TargetInfo/CellSPUTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "SPU.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::TheCellSPUTarget;
diff --git a/lib/Target/CppBackend/CMakeLists.txt b/lib/Target/CppBackend/CMakeLists.txt
index e937559..95b6058 100644
--- a/lib/Target/CppBackend/CMakeLists.txt
+++ b/lib/Target/CppBackend/CMakeLists.txt
@@ -2,4 +2,11 @@ add_llvm_target(CppBackend
CPPBackend.cpp
)
+add_llvm_library_dependencies(LLVMCppBackend
+ LLVMCore
+ LLVMCppBackendInfo
+ LLVMSupport
+ LLVMTarget
+ )
+
add_subdirectory(TargetInfo)
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp
index 10d18f6..ae0e3c4 100644
--- a/lib/Target/CppBackend/CPPBackend.cpp
+++ b/lib/Target/CppBackend/CPPBackend.cpp
@@ -29,7 +29,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
#include <algorithm>
@@ -77,22 +77,12 @@ extern "C" void LLVMInitializeCppBackendTarget() {
RegisterTargetMachine<CPPTargetMachine> X(TheCppBackendTarget);
}
-extern "C" void LLVMInitializeCppBackendMCAsmInfo() {}
-
-extern "C" void LLVMInitializeCppBackendMCInstrInfo() {
- RegisterMCInstrInfo<MCInstrInfo> X(TheCppBackendTarget);
-}
-
-extern "C" void LLVMInitializeCppBackendMCSubtargetInfo() {
- RegisterMCSubtargetInfo<MCSubtargetInfo> X(TheCppBackendTarget);
-}
-
namespace {
- typedef std::vector<const Type*> TypeList;
- typedef std::map<const Type*,std::string> TypeMap;
+ typedef std::vector<Type*> TypeList;
+ typedef std::map<Type*,std::string> TypeMap;
typedef std::map<const Value*,std::string> ValueMap;
typedef std::set<std::string> NameSet;
- typedef std::set<const Type*> TypeSet;
+ typedef std::set<Type*> TypeSet;
typedef std::set<const Value*> ValueSet;
typedef std::map<const Value*,std::string> ForwardRefMap;
@@ -143,14 +133,14 @@ namespace {
void printEscapedString(const std::string& str);
void printCFP(const ConstantFP* CFP);
- std::string getCppName(const Type* val);
- inline void printCppName(const Type* val);
+ std::string getCppName(Type* val);
+ inline void printCppName(Type* val);
std::string getCppName(const Value* val);
inline void printCppName(const Value* val);
void printAttributes(const AttrListPtr &PAL, const std::string &name);
- void printType(const Type* Ty);
+ void printType(Type* Ty);
void printTypes(const Module* M);
void printConstant(const Constant *CPV);
@@ -164,7 +154,7 @@ namespace {
void printFunctionHead(const Function *F);
void printFunctionBody(const Function *F);
void printInstruction(const Instruction *I, const std::string& bbname);
- std::string getOpName(Value*);
+ std::string getOpName(const Value*);
void printModuleBody();
};
@@ -184,7 +174,7 @@ static inline void sanitize(std::string &str) {
str[i] = '_';
}
-static std::string getTypePrefix(const Type *Ty) {
+static std::string getTypePrefix(Type *Ty) {
switch (Ty->getTypeID()) {
case Type::VoidTyID: return "void_";
case Type::IntegerTyID:
@@ -339,7 +329,7 @@ void CppWriter::printEscapedString(const std::string &Str) {
}
}
-std::string CppWriter::getCppName(const Type* Ty) {
+std::string CppWriter::getCppName(Type* Ty) {
// First, handle the primitive types .. easy
if (Ty->isPrimitiveType() || Ty->isIntegerTy()) {
switch (Ty->getTypeID()) {
@@ -379,7 +369,7 @@ std::string CppWriter::getCppName(const Type* Ty) {
// See if the type has a name in the symboltable and build accordingly
std::string name;
- if (const StructType *STy = dyn_cast<StructType>(Ty))
+ if (StructType *STy = dyn_cast<StructType>(Ty))
if (STy->hasName())
name = STy->getName();
@@ -393,7 +383,7 @@ std::string CppWriter::getCppName(const Type* Ty) {
return TypeNames[Ty] = name;
}
-void CppWriter::printCppName(const Type* Ty) {
+void CppWriter::printCppName(Type* Ty) {
printEscapedString(getCppName(Ty));
}
@@ -480,6 +470,9 @@ void CppWriter::printAttributes(const AttrListPtr &PAL,
HANDLE_ATTR(NoImplicitFloat);
HANDLE_ATTR(Naked);
HANDLE_ATTR(InlineHint);
+ HANDLE_ATTR(ReturnsTwice);
+ HANDLE_ATTR(UWTable);
+ HANDLE_ATTR(NonLazyBind);
#undef HANDLE_ATTR
if (attrs & Attribute::StackAlignment)
Out << " | Attribute::constructStackAlignmentFromInt("
@@ -499,7 +492,7 @@ void CppWriter::printAttributes(const AttrListPtr &PAL,
}
}
-void CppWriter::printType(const Type* Ty) {
+void CppWriter::printType(Type* Ty) {
// We don't print definitions for primitive types
if (Ty->isPrimitiveType() || Ty->isIntegerTy())
return;
@@ -514,13 +507,13 @@ void CppWriter::printType(const Type* Ty) {
// Print the type definition
switch (Ty->getTypeID()) {
case Type::FunctionTyID: {
- const FunctionType* FT = cast<FunctionType>(Ty);
+ FunctionType* FT = cast<FunctionType>(Ty);
Out << "std::vector<Type*>" << typeName << "_args;";
nl(Out);
FunctionType::param_iterator PI = FT->param_begin();
FunctionType::param_iterator PE = FT->param_end();
for (; PI != PE; ++PI) {
- const Type* argTy = static_cast<const Type*>(*PI);
+ Type* argTy = static_cast<Type*>(*PI);
printType(argTy);
std::string argName(getCppName(argTy));
Out << typeName << "_args.push_back(" << argName;
@@ -539,13 +532,21 @@ void CppWriter::printType(const Type* Ty) {
break;
}
case Type::StructTyID: {
- const StructType* ST = cast<StructType>(Ty);
- if (!ST->isAnonymous()) {
- Out << "StructType *" << typeName << " = ";
- Out << "StructType::createNamed(mod->getContext(), \"";
+ StructType* ST = cast<StructType>(Ty);
+ if (!ST->isLiteral()) {
+ Out << "StructType *" << typeName << " = mod->getTypeByName(\"";
+ printEscapedString(ST->getName());
+ Out << "\");";
+ nl(Out);
+ Out << "if (!" << typeName << ") {";
+ nl(Out);
+ Out << typeName << " = ";
+ Out << "StructType::create(mod->getContext(), \"";
printEscapedString(ST->getName());
Out << "\");";
nl(Out);
+ Out << "}";
+ nl(Out);
// Indicate that this type is now defined.
DefinedTypes.insert(Ty);
}
@@ -555,7 +556,7 @@ void CppWriter::printType(const Type* Ty) {
StructType::element_iterator EI = ST->element_begin();
StructType::element_iterator EE = ST->element_end();
for (; EI != EE; ++EI) {
- const Type* fieldTy = static_cast<const Type*>(*EI);
+ Type* fieldTy = static_cast<Type*>(*EI);
printType(fieldTy);
std::string fieldName(getCppName(fieldTy));
Out << typeName << "_fields.push_back(" << fieldName;
@@ -563,21 +564,27 @@ void CppWriter::printType(const Type* Ty) {
nl(Out);
}
- if (ST->isAnonymous()) {
+ if (ST->isLiteral()) {
Out << "StructType *" << typeName << " = ";
Out << "StructType::get(" << "mod->getContext(), ";
} else {
+ Out << "if (" << typeName << "->isOpaque()) {";
+ nl(Out);
Out << typeName << "->setBody(";
}
Out << typeName << "_fields, /*isPacked=*/"
<< (ST->isPacked() ? "true" : "false") << ");";
nl(Out);
+ if (!ST->isLiteral()) {
+ Out << "}";
+ nl(Out);
+ }
break;
}
case Type::ArrayTyID: {
- const ArrayType* AT = cast<ArrayType>(Ty);
- const Type* ET = AT->getElementType();
+ ArrayType* AT = cast<ArrayType>(Ty);
+ Type* ET = AT->getElementType();
printType(ET);
if (DefinedTypes.find(Ty) == DefinedTypes.end()) {
std::string elemName(getCppName(ET));
@@ -589,8 +596,8 @@ void CppWriter::printType(const Type* Ty) {
break;
}
case Type::PointerTyID: {
- const PointerType* PT = cast<PointerType>(Ty);
- const Type* ET = PT->getElementType();
+ PointerType* PT = cast<PointerType>(Ty);
+ Type* ET = PT->getElementType();
printType(ET);
if (DefinedTypes.find(Ty) == DefinedTypes.end()) {
std::string elemName(getCppName(ET));
@@ -602,8 +609,8 @@ void CppWriter::printType(const Type* Ty) {
break;
}
case Type::VectorTyID: {
- const VectorType* PT = cast<VectorType>(Ty);
- const Type* ET = PT->getElementType();
+ VectorType* PT = cast<VectorType>(Ty);
+ Type* ET = PT->getElementType();
printType(ET);
if (DefinedTypes.find(Ty) == DefinedTypes.end()) {
std::string elemName(getCppName(ET));
@@ -766,9 +773,7 @@ void CppWriter::printConstant(const Constant *CV) {
Out << "Constant* " << constName
<< " = ConstantExpr::getGetElementPtr("
<< getCppName(CE->getOperand(0)) << ", "
- << "&" << constName << "_indices[0], "
- << constName << "_indices.size()"
- << ");";
+ << constName << "_indices);";
} else if (CE->isCast()) {
printConstant(CE->getOperand(0));
Out << "Constant* " << constName << " = ConstantExpr::getCast(";
@@ -988,7 +993,7 @@ void CppWriter::printVariableBody(const GlobalVariable *GV) {
}
}
-std::string CppWriter::getOpName(Value* V) {
+std::string CppWriter::getOpName(const Value* V) {
if (!isa<Instruction>(V) || DefinedValues.find(V) != DefinedValues.end())
return getCppName(V);
@@ -1053,14 +1058,17 @@ void CppWriter::printInstruction(const Instruction *I,
case Instruction::Switch: {
const SwitchInst *SI = cast<SwitchInst>(I);
Out << "SwitchInst* " << iName << " = SwitchInst::Create("
- << opNames[0] << ", "
- << opNames[1] << ", "
+ << getOpName(SI->getCondition()) << ", "
+ << getOpName(SI->getDefaultDest()) << ", "
<< SI->getNumCases() << ", " << bbname << ");";
nl(Out);
- for (unsigned i = 2; i != SI->getNumOperands(); i += 2) {
+ unsigned NumCases = SI->getNumCases();
+ for (unsigned i = 1; i < NumCases; ++i) {
+ const ConstantInt* CaseVal = SI->getCaseValue(i);
+ const BasicBlock* BB = SI->getSuccessor(i);
Out << iName << "->addCase("
- << opNames[i] << ", "
- << opNames[i+1] << ");";
+ << getOpName(CaseVal) << ", "
+ << getOpName(BB) << ");";
nl(Out);
}
break;
@@ -1076,6 +1084,11 @@ void CppWriter::printInstruction(const Instruction *I,
}
break;
}
+ case Instruction::Resume: {
+ Out << "ResumeInst::Create(mod->getContext(), " << opNames[0]
+ << ", " << bbname << ");";
+ break;
+ }
case Instruction::Invoke: {
const InvokeInst* inv = cast<InvokeInst>(I);
Out << "std::vector<Value*> " << iName << "_params;";
@@ -1090,8 +1103,7 @@ void CppWriter::printInstruction(const Instruction *I,
<< getOpName(inv->getCalledFunction()) << ", "
<< getOpName(inv->getNormalDest()) << ", "
<< getOpName(inv->getUnwindDest()) << ", "
- << iName << "_params.begin(), "
- << iName << "_params.end(), \"";
+ << iName << "_params, \"";
printEscapedString(inv->getName());
Out << "\", " << bbname << ");";
nl(Out) << iName << "->setCallingConv(";
@@ -1252,8 +1264,7 @@ void CppWriter::printInstruction(const Instruction *I,
nl(Out);
}
Out << "Instruction* " << iName << " = GetElementPtrInst::Create("
- << opNames[0] << ", " << iName << "_indices.begin(), "
- << iName << "_indices.end()";
+ << opNames[0] << ", " << iName << "_indices";
}
Out << ", \"";
printEscapedString(gep->getName());
@@ -1304,7 +1315,7 @@ void CppWriter::printInstruction(const Instruction *I,
case Instruction::PtrToInt: Out << "PtrToIntInst"; break;
case Instruction::IntToPtr: Out << "IntToPtrInst"; break;
case Instruction::BitCast: Out << "BitCastInst"; break;
- default: assert(!"Unreachable"); break;
+ default: assert(0 && "Unreachable"); break;
}
Out << "(" << opNames[0] << ", "
<< getCppName(cst->getType()) << ", \"";
@@ -1331,8 +1342,7 @@ void CppWriter::printInstruction(const Instruction *I,
}
Out << "CallInst* " << iName << " = CallInst::Create("
<< opNames[call->getNumArgOperands()] << ", "
- << iName << "_params.begin(), "
- << iName << "_params.end(), \"";
+ << iName << "_params, \"";
} else if (call->getNumArgOperands() == 1) {
Out << "CallInst* " << iName << " = CallInst::Create("
<< opNames[call->getNumArgOperands()] << ", " << opNames[0] << ", \"";
@@ -1415,7 +1425,7 @@ void CppWriter::printInstruction(const Instruction *I,
Out << "ExtractValueInst* " << getCppName(evi)
<< " = ExtractValueInst::Create(" << opNames[0]
<< ", "
- << iName << "_indices.begin(), " << iName << "_indices.end(), \"";
+ << iName << "_indices, \"";
printEscapedString(evi->getName());
Out << "\", " << bbname << ");";
break;
@@ -1432,7 +1442,7 @@ void CppWriter::printInstruction(const Instruction *I,
Out << "InsertValueInst* " << getCppName(ivi)
<< " = InsertValueInst::Create(" << opNames[0]
<< ", " << opNames[1] << ", "
- << iName << "_indices.begin(), " << iName << "_indices.end(), \"";
+ << iName << "_indices, \"";
printEscapedString(ivi->getName());
Out << "\", " << bbname << ");";
break;
@@ -1542,13 +1552,12 @@ void CppWriter::printFunctionUses(const Function* F) {
void CppWriter::printFunctionHead(const Function* F) {
nl(Out) << "Function* " << getCppName(F);
- if (is_inline) {
- Out << " = mod->getFunction(\"";
- printEscapedString(F->getName());
- Out << "\", " << getCppName(F->getFunctionType()) << ");";
- nl(Out) << "if (!" << getCppName(F) << ") {";
- nl(Out) << getCppName(F);
- }
+ Out << " = mod->getFunction(\"";
+ printEscapedString(F->getName());
+ Out << "\");";
+ nl(Out) << "if (!" << getCppName(F) << ") {";
+ nl(Out) << getCppName(F);
+
Out<< " = Function::Create(";
nl(Out,1) << "/*Type=*/" << getCppName(F->getFunctionType()) << ",";
nl(Out) << "/*Linkage=*/";
@@ -1585,10 +1594,8 @@ void CppWriter::printFunctionHead(const Function* F) {
Out << "->setGC(\"" << F->getGC() << "\");";
nl(Out);
}
- if (is_inline) {
- Out << "}";
- nl(Out);
- }
+ Out << "}";
+ nl(Out);
printAttributes(F->getAttributes(), getCppName(F));
printCppName(F);
Out << "->setAttributes(" << getCppName(F) << "_PAL);";
@@ -1873,7 +1880,7 @@ void CppWriter::printVariable(const std::string& fname,
void CppWriter::printType(const std::string &fname,
const std::string &typeName) {
- const Type* Ty = TheModule->getTypeByName(typeName);
+ Type* Ty = TheModule->getTypeByName(typeName);
if (!Ty) {
error(std::string("Type '") + typeName + "' not found in input module");
return;
diff --git a/lib/Target/CppBackend/CPPTargetMachine.h b/lib/Target/CppBackend/CPPTargetMachine.h
index 7322e3e..287e537 100644
--- a/lib/Target/CppBackend/CPPTargetMachine.h
+++ b/lib/Target/CppBackend/CPPTargetMachine.h
@@ -22,8 +22,9 @@ namespace llvm {
class formatted_raw_ostream;
struct CPPTargetMachine : public TargetMachine {
- CPPTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS)
+ CPPTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
: TargetMachine(T, TT, CPU, FS) {}
virtual bool addPassesToEmitFile(PassManagerBase &PM,
diff --git a/lib/Target/CppBackend/TargetInfo/CMakeLists.txt b/lib/Target/CppBackend/TargetInfo/CMakeLists.txt
index edaf5d3..7165d8f 100644
--- a/lib/Target/CppBackend/TargetInfo/CMakeLists.txt
+++ b/lib/Target/CppBackend/TargetInfo/CMakeLists.txt
@@ -4,3 +4,7 @@ add_llvm_library(LLVMCppBackendInfo
CppBackendTargetInfo.cpp
)
+add_llvm_library_dependencies(LLVMCppBackendInfo
+ LLVMMC
+ LLVMTarget
+ )
diff --git a/lib/Target/CppBackend/TargetInfo/CppBackendTargetInfo.cpp b/lib/Target/CppBackend/TargetInfo/CppBackendTargetInfo.cpp
index d0aeb12..a8ac0a2 100644
--- a/lib/Target/CppBackend/TargetInfo/CppBackendTargetInfo.cpp
+++ b/lib/Target/CppBackend/TargetInfo/CppBackendTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "CPPTargetMachine.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::TheCppBackendTarget;
@@ -24,3 +24,5 @@ extern "C" void LLVMInitializeCppBackendTargetInfo() {
"C++ backend",
&CppBackend_TripleMatchQuality);
}
+
+extern "C" void LLVMInitializeCppBackendTargetMC() {}
diff --git a/lib/Target/MBlaze/AsmParser/CMakeLists.txt b/lib/Target/MBlaze/AsmParser/CMakeLists.txt
index 87e7cb5..ec8f52a 100644
--- a/lib/Target/MBlaze/AsmParser/CMakeLists.txt
+++ b/lib/Target/MBlaze/AsmParser/CMakeLists.txt
@@ -6,3 +6,11 @@ add_llvm_library(LLVMMBlazeAsmParser
MBlazeAsmParser.cpp
)
+add_llvm_library_dependencies(LLVMMBlazeAsmParser
+ LLVMMBlazeInfo
+ LLVMMC
+ LLVMMCParser
+ LLVMSupport
+ )
+
+add_dependencies(LLVMMBlazeAsmParser MBlazeCommonTableGen)
diff --git a/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp b/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp
index 1596596..2d357bb 100644
--- a/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp
+++ b/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp
@@ -7,8 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "MBlaze.h"
-#include "MBlazeTargetMachine.h"
+#include "MCTargetDesc/MBlazeBaseInfo.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
@@ -17,10 +16,10 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCTargetAsmLexer.h"
-#include "llvm/Target/TargetAsmLexer.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#include <string>
#include <map>
@@ -29,7 +28,7 @@ using namespace llvm;
namespace {
- class MBlazeBaseAsmLexer : public TargetAsmLexer {
+ class MBlazeBaseAsmLexer : public MCTargetAsmLexer {
const MCAsmInfo &AsmInfo;
const AsmToken &lexDefinite() {
@@ -42,7 +41,7 @@ namespace {
rmap_ty RegisterMap;
- void InitRegisterMap(const TargetRegisterInfo *info) {
+ void InitRegisterMap(const MCRegisterInfo *info) {
unsigned numRegs = info->getNumRegs();
for (unsigned i = 0; i < numRegs; ++i) {
@@ -76,20 +75,16 @@ namespace {
}
public:
MBlazeBaseAsmLexer(const Target &T, const MCAsmInfo &MAI)
- : TargetAsmLexer(T), AsmInfo(MAI) {
+ : MCTargetAsmLexer(T), AsmInfo(MAI) {
}
};
class MBlazeAsmLexer : public MBlazeBaseAsmLexer {
public:
- MBlazeAsmLexer(const Target &T, const MCAsmInfo &MAI)
+ MBlazeAsmLexer(const Target &T, const MCRegisterInfo &MRI,
+ const MCAsmInfo &MAI)
: MBlazeBaseAsmLexer(T, MAI) {
- std::string tripleString("mblaze-unknown-unknown");
- std::string featureString;
- std::string CPU;
- OwningPtr<const TargetMachine>
- targetMachine(T.createTargetMachine(tripleString, CPU, featureString));
- InitRegisterMap(targetMachine->getRegisterInfo());
+ InitRegisterMap(&MRI);
}
};
}
@@ -123,6 +118,6 @@ AsmToken MBlazeBaseAsmLexer::LexTokenUAL() {
}
extern "C" void LLVMInitializeMBlazeAsmLexer() {
- RegisterAsmLexer<MBlazeAsmLexer> X(TheMBlazeTarget);
+ RegisterMCAsmLexer<MBlazeAsmLexer> X(TheMBlazeTarget);
}
diff --git a/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp b/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp
index eebd9d8..97d311c 100644
--- a/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp
+++ b/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp
@@ -7,19 +7,16 @@
//
//===----------------------------------------------------------------------===//
-#include "MBlaze.h"
-#include "MBlazeSubtarget.h"
-#include "MBlazeRegisterInfo.h"
-#include "MBlazeISelLowering.h"
+#include "MCTargetDesc/MBlazeBaseInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetAsmParser.h"
+#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
@@ -30,7 +27,7 @@ using namespace llvm;
namespace {
struct MBlazeOperand;
-class MBlazeAsmParser : public TargetAsmParser {
+class MBlazeAsmParser : public MCTargetAsmParser {
MCAsmParser &Parser;
MCAsmParser &getParser() const { return Parser; }
@@ -64,7 +61,7 @@ class MBlazeAsmParser : public TargetAsmParser {
public:
MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
- : TargetAsmParser(), Parser(_Parser) {}
+ : MCTargetAsmParser(), Parser(_Parser) {}
virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
@@ -286,19 +283,19 @@ void MBlazeOperand::print(raw_ostream &OS) const {
break;
case Register:
OS << "<register R";
- OS << MBlazeRegisterInfo::getRegisterNumbering(getReg()) << ">";
+ OS << getMBlazeRegisterNumbering(getReg()) << ">";
break;
case Token:
OS << "'" << getToken() << "'";
break;
case Memory: {
OS << "<memory R";
- OS << MBlazeRegisterInfo::getRegisterNumbering(getMemBase());
+ OS << getMBlazeRegisterNumbering(getMemBase());
OS << ", ";
unsigned RegOff = getMemOffReg();
if (RegOff)
- OS << "R" << MBlazeRegisterInfo::getRegisterNumbering(RegOff);
+ OS << "R" << getMBlazeRegisterNumbering(RegOff);
else
OS << getMemOff();
OS << ">";
@@ -326,6 +323,7 @@ MatchAndEmitInstruction(SMLoc IDLoc,
unsigned ErrorInfo;
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) {
+ default: break;
case Match_Success:
Out.EmitInstruction(Inst);
return false;
@@ -521,7 +519,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
return false;
}
-/// ParseDirective parses the arm specific directives
+/// ParseDirective parses the MBlaze specific directives
bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getIdentifier();
if (IDVal == ".word")
@@ -558,7 +556,7 @@ extern "C" void LLVMInitializeMBlazeAsmLexer();
/// Force static initialization.
extern "C" void LLVMInitializeMBlazeAsmParser() {
- RegisterAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
+ RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
LLVMInitializeMBlazeAsmLexer();
}
diff --git a/lib/Target/MBlaze/AsmParser/Makefile b/lib/Target/MBlaze/AsmParser/Makefile
index 611a0f4..1e68766 100644
--- a/lib/Target/MBlaze/AsmParser/Makefile
+++ b/lib/Target/MBlaze/AsmParser/Makefile
@@ -1,4 +1,4 @@
-##===- lib/Target/ARM/AsmParser/Makefile -------------------*- Makefile -*-===##
+##===- lib/Target/MBlaze/AsmParser/Makefile ----------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
diff --git a/lib/Target/MBlaze/CMakeLists.txt b/lib/Target/MBlaze/CMakeLists.txt
index 0bc5b78..47b0db2 100644
--- a/lib/Target/MBlaze/CMakeLists.txt
+++ b/lib/Target/MBlaze/CMakeLists.txt
@@ -1,15 +1,16 @@
set(LLVM_TARGET_DEFINITIONS MBlaze.td)
-tablegen(MBlazeGenRegisterInfo.inc -gen-register-info)
-tablegen(MBlazeGenInstrInfo.inc -gen-instr-info)
-tablegen(MBlazeGenCodeEmitter.inc -gen-emitter)
-tablegen(MBlazeGenAsmWriter.inc -gen-asm-writer)
-tablegen(MBlazeGenAsmMatcher.inc -gen-asm-matcher)
-tablegen(MBlazeGenDAGISel.inc -gen-dag-isel)
-tablegen(MBlazeGenCallingConv.inc -gen-callingconv)
-tablegen(MBlazeGenSubtargetInfo.inc -gen-subtarget)
-tablegen(MBlazeGenIntrinsics.inc -gen-tgt-intrinsic)
-tablegen(MBlazeGenEDInfo.inc -gen-enhanced-disassembly-info)
+llvm_tablegen(MBlazeGenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(MBlazeGenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(MBlazeGenCodeEmitter.inc -gen-emitter)
+llvm_tablegen(MBlazeGenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(MBlazeGenAsmMatcher.inc -gen-asm-matcher)
+llvm_tablegen(MBlazeGenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(MBlazeGenCallingConv.inc -gen-callingconv)
+llvm_tablegen(MBlazeGenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(MBlazeGenIntrinsics.inc -gen-tgt-intrinsic)
+llvm_tablegen(MBlazeGenEDInfo.inc -gen-enhanced-disassembly-info)
+add_public_tablegen_target(MBlazeCommonTableGen)
add_llvm_target(MBlazeCodeGen
MBlazeDelaySlotFiller.cpp
@@ -24,10 +25,21 @@ add_llvm_target(MBlazeCodeGen
MBlazeIntrinsicInfo.cpp
MBlazeSelectionDAGInfo.cpp
MBlazeAsmPrinter.cpp
- MBlazeAsmBackend.cpp
MBlazeMCInstLower.cpp
MBlazeELFWriterInfo.cpp
- MBlazeMCCodeEmitter.cpp
+ )
+
+add_llvm_library_dependencies(LLVMMBlazeCodeGen
+ LLVMAsmPrinter
+ LLVMCodeGen
+ LLVMCore
+ LLVMMBlazeAsmPrinter
+ LLVMMBlazeDesc
+ LLVMMBlazeInfo
+ LLVMMC
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMTarget
)
add_subdirectory(AsmParser)
diff --git a/lib/Target/MBlaze/Disassembler/CMakeLists.txt b/lib/Target/MBlaze/Disassembler/CMakeLists.txt
index 9376e68..112c64c 100644
--- a/lib/Target/MBlaze/Disassembler/CMakeLists.txt
+++ b/lib/Target/MBlaze/Disassembler/CMakeLists.txt
@@ -13,4 +13,12 @@ set_property(
)
endif()
-add_dependencies(LLVMMBlazeDisassembler MBlazeCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMMBlazeDisassembler
+ LLVMMBlazeCodeGen
+ LLVMMBlazeDesc
+ LLVMMBlazeInfo
+ LLVMMC
+ LLVMSupport
+ )
+
+add_dependencies(LLVMMBlazeDisassembler MBlazeCommonTableGen)
diff --git a/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp b/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp
index 88d80a1..fd761f1 100644
--- a/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp
+++ b/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp
@@ -20,9 +20,9 @@
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
// #include "MBlazeGenDecoderTables.inc"
@@ -60,27 +60,27 @@ static unsigned mblazeBinary2Opcode[] = {
};
static unsigned getRD(uint32_t insn) {
- if (!MBlazeRegisterInfo::isRegister((insn>>21)&0x1F))
+ if (!isMBlazeRegister((insn>>21)&0x1F))
return UNSUPPORTED;
- return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>21)&0x1F);
+ return getMBlazeRegisterFromNumbering((insn>>21)&0x1F);
}
static unsigned getRA(uint32_t insn) {
- if (!MBlazeRegisterInfo::getRegisterFromNumbering((insn>>16)&0x1F))
+ if (!getMBlazeRegisterFromNumbering((insn>>16)&0x1F))
return UNSUPPORTED;
- return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>16)&0x1F);
+ return getMBlazeRegisterFromNumbering((insn>>16)&0x1F);
}
static unsigned getRB(uint32_t insn) {
- if (!MBlazeRegisterInfo::getRegisterFromNumbering((insn>>11)&0x1F))
+ if (!getMBlazeRegisterFromNumbering((insn>>11)&0x1F))
return UNSUPPORTED;
- return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>11)&0x1F);
+ return getMBlazeRegisterFromNumbering((insn>>11)&0x1F);
}
static int64_t getRS(uint32_t insn) {
- if (!MBlazeRegisterInfo::isSpecialRegister(insn&0x3FFF))
+ if (!isSpecialMBlazeRegister(insn&0x3FFF))
return UNSUPPORTED;
- return MBlazeRegisterInfo::getSpecialRegisterFromNumbering(insn&0x3FFF);
+ return getSpecialMBlazeRegisterFromNumbering(insn&0x3FFF);
}
static int64_t getIMM(uint32_t insn) {
@@ -493,11 +493,12 @@ EDInstInfo *MBlazeDisassembler::getEDInfo() const {
// Public interface for the disassembler
//
-bool MBlazeDisassembler::getInstruction(MCInst &instr,
+MCDisassembler::DecodeStatus MBlazeDisassembler::getInstruction(MCInst &instr,
uint64_t &size,
const MemoryObject &region,
uint64_t address,
- raw_ostream &vStream) const {
+ raw_ostream &vStream,
+ raw_ostream &cStream) const {
// The machine instruction.
uint32_t insn;
uint64_t read;
@@ -508,7 +509,7 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
// We want to read exactly 4 bytes of data.
if (region.readBytes(address, 4, (uint8_t*)bytes, &read) == -1 || read < 4)
- return false;
+ return Fail;
// Encoded as a big-endian 32-bit word in the stream.
insn = (bytes[0]<<24) | (bytes[1]<<16) | (bytes[2]<< 8) | (bytes[3]<<0);
@@ -517,7 +518,7 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
// that it is a valid instruction.
unsigned opcode = getOPCODE(insn);
if (opcode == UNSUPPORTED)
- return false;
+ return Fail;
instr.setOpcode(opcode);
@@ -529,11 +530,11 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
uint64_t tsFlags = MBlazeInsts[opcode].TSFlags;
switch ((tsFlags & MBlazeII::FormMask)) {
default:
- return false;
+ return Fail;
case MBlazeII::FRRRR:
if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateReg(RB));
instr.addOperand(MCOperand::CreateReg(RA));
@@ -541,7 +542,7 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
case MBlazeII::FRRR:
if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateReg(RA));
instr.addOperand(MCOperand::CreateReg(RB));
@@ -550,23 +551,23 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
case MBlazeII::FRI:
switch (opcode) {
default:
- return false;
+ return Fail;
case MBlaze::MFS:
if (RD == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateImm(insn&0x3FFF));
break;
case MBlaze::MTS:
if (RA == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateImm(insn&0x3FFF));
instr.addOperand(MCOperand::CreateReg(RA));
break;
case MBlaze::MSRSET:
case MBlaze::MSRCLR:
if (RD == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateImm(insn&0x7FFF));
break;
@@ -575,7 +576,7 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
case MBlazeII::FRRI:
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateReg(RA));
switch (opcode) {
@@ -592,35 +593,35 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
case MBlazeII::FCRR:
if (RA == UNSUPPORTED || RB == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RA));
instr.addOperand(MCOperand::CreateReg(RB));
break;
case MBlazeII::FCRI:
if (RA == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RA));
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
break;
case MBlazeII::FRCR:
if (RD == UNSUPPORTED || RB == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateReg(RB));
break;
case MBlazeII::FRCI:
if (RD == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
break;
case MBlazeII::FCCR:
if (RB == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RB));
break;
@@ -630,7 +631,7 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
case MBlazeII::FRRCI:
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateReg(RA));
instr.addOperand(MCOperand::CreateImm(getSHT(insn)));
@@ -638,35 +639,35 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
case MBlazeII::FRRC:
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateReg(RA));
break;
case MBlazeII::FRCX:
if (RD == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
break;
case MBlazeII::FRCS:
if (RD == UNSUPPORTED || RS == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateReg(RS));
break;
case MBlazeII::FCRCS:
if (RS == UNSUPPORTED || RA == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RS));
instr.addOperand(MCOperand::CreateReg(RA));
break;
case MBlazeII::FCRCX:
if (RA == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RA));
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
break;
@@ -677,13 +678,13 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
case MBlazeII::FCR:
if (RB == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RB));
break;
case MBlazeII::FRIR:
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
- return false;
+ return Fail;
instr.addOperand(MCOperand::CreateReg(RD));
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
instr.addOperand(MCOperand::CreateReg(RA));
@@ -693,11 +694,12 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr,
// We always consume 4 bytes of data on success
size = 4;
- return true;
+ return Success;
}
-static MCDisassembler *createMBlazeDisassembler(const Target &T) {
- return new MBlazeDisassembler;
+static MCDisassembler *createMBlazeDisassembler(const Target &T,
+ const MCSubtargetInfo &STI) {
+ return new MBlazeDisassembler(STI);
}
extern "C" void LLVMInitializeMBlazeDisassembler() {
diff --git a/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.h b/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.h
index d05eced..0ac0d89 100644
--- a/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.h
+++ b/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.h
@@ -32,19 +32,20 @@ class MBlazeDisassembler : public MCDisassembler {
public:
/// Constructor - Initializes the disassembler.
///
- MBlazeDisassembler() :
- MCDisassembler() {
+ MBlazeDisassembler(const MCSubtargetInfo &STI) :
+ MCDisassembler(STI) {
}
~MBlazeDisassembler() {
}
/// getInstruction - See MCDisassembler.
- bool getInstruction(MCInst &instr,
+ MCDisassembler::DecodeStatus getInstruction(MCInst &instr,
uint64_t &size,
const MemoryObject &region,
uint64_t address,
- raw_ostream &vStream) const;
+ raw_ostream &vStream,
+ raw_ostream &cStream) const;
/// getEDInfo - See MCDisassembler.
EDInstInfo *getEDInfo() const;
diff --git a/lib/Target/MBlaze/InstPrinter/CMakeLists.txt b/lib/Target/MBlaze/InstPrinter/CMakeLists.txt
index 242a573..aff0b3d 100644
--- a/lib/Target/MBlaze/InstPrinter/CMakeLists.txt
+++ b/lib/Target/MBlaze/InstPrinter/CMakeLists.txt
@@ -2,7 +2,12 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/..
${CMAKE_CURRENT_SOURCE_DIR}/.. )
add_llvm_library(LLVMMBlazeAsmPrinter
- MBlazeInstPrinter.cpp
+ MBlazeInstPrinter.cpp
)
-add_dependencies(LLVMMBlazeAsmPrinter MBlazeCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMMBlazeAsmPrinter
+ LLVMMC
+ LLVMSupport
+ )
+
+add_dependencies(LLVMMBlazeAsmPrinter MBlazeCommonTableGen)
diff --git a/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp
index a7fd287..a1f1dbc 100644
--- a/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp
+++ b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp
@@ -25,8 +25,10 @@ using namespace llvm;
// Include the auto-generated portion of the assembly writer.
#include "MBlazeGenAsmWriter.inc"
-void MBlazeInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
+void MBlazeInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
+ StringRef Annot) {
printInstruction(MI, O);
+ printAnnotation(O, Annot);
}
void MBlazeInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
diff --git a/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h
index eacca41..570ab08 100644
--- a/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h
+++ b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h
@@ -24,7 +24,7 @@ namespace llvm {
MBlazeInstPrinter(const MCAsmInfo &MAI)
: MCInstPrinter(MAI) {}
- virtual void printInst(const MCInst *MI, raw_ostream &O);
+ virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, raw_ostream &O);
diff --git a/lib/Target/MBlaze/MBlaze.h b/lib/Target/MBlaze/MBlaze.h
index 3390794..1399b85 100644
--- a/lib/Target/MBlaze/MBlaze.h
+++ b/lib/Target/MBlaze/MBlaze.h
@@ -15,6 +15,7 @@
#ifndef TARGET_MBLAZE_H
#define TARGET_MBLAZE_H
+#include "MCTargetDesc/MBlazeBaseInfo.h"
#include "MCTargetDesc/MBlazeMCTargetDesc.h"
#include "llvm/Target/TargetMachine.h"
@@ -22,17 +23,6 @@ namespace llvm {
class MBlazeTargetMachine;
class FunctionPass;
class MachineCodeEmitter;
- class MCCodeEmitter;
- class MCInstrInfo;
- class MCSubtargetInfo;
- class TargetAsmBackend;
- class formatted_raw_ostream;
-
- MCCodeEmitter *createMBlazeMCCodeEmitter(const MCInstrInfo &MCII,
- const MCSubtargetInfo &STI,
- MCContext &Ctx);
-
- TargetAsmBackend *createMBlazeAsmBackend(const Target &, const std::string &);
FunctionPass *createMBlazeISelDag(MBlazeTargetMachine &TM);
FunctionPass *createMBlazeDelaySlotFillerPass(MBlazeTargetMachine &TM);
diff --git a/lib/Target/MBlaze/MBlazeAsmBackend.cpp b/lib/Target/MBlaze/MBlazeAsmBackend.cpp
deleted file mode 100644
index 08f14c3..0000000
--- a/lib/Target/MBlaze/MBlazeAsmBackend.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-//===-- MBlazeAsmBackend.cpp - MBlaze Assembler Backend -------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Target/TargetAsmBackend.h"
-#include "MBlaze.h"
-#include "MBlazeELFWriterInfo.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCELFObjectWriter.h"
-#include "llvm/MC/MCELFSymbolFlags.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetAsmBackend.h"
-using namespace llvm;
-
-static unsigned getFixupKindSize(unsigned Kind) {
- switch (Kind) {
- default: assert(0 && "invalid fixup kind!");
- case FK_Data_1: return 1;
- case FK_PCRel_2:
- case FK_Data_2: return 2;
- case FK_PCRel_4:
- case FK_Data_4: return 4;
- case FK_Data_8: return 8;
- }
-}
-
-
-namespace {
-class MBlazeELFObjectWriter : public MCELFObjectTargetWriter {
-public:
- MBlazeELFObjectWriter(Triple::OSType OSType)
- : MCELFObjectTargetWriter(/*is64Bit*/ false, OSType, ELF::EM_MBLAZE,
- /*HasRelocationAddend*/ true) {}
-};
-
-class MBlazeAsmBackend : public TargetAsmBackend {
-public:
- MBlazeAsmBackend(const Target &T)
- : TargetAsmBackend() {
- }
-
- unsigned getNumFixupKinds() const {
- return 2;
- }
-
- bool MayNeedRelaxation(const MCInst &Inst) const;
-
- void RelaxInstruction(const MCInst &Inst, MCInst &Res) const;
-
- bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const;
-
- unsigned getPointerSize() const {
- return 4;
- }
-};
-
-static unsigned getRelaxedOpcode(unsigned Op) {
- switch (Op) {
- default: return Op;
- case MBlaze::ADDIK: return MBlaze::ADDIK32;
- case MBlaze::ORI: return MBlaze::ORI32;
- case MBlaze::BRLID: return MBlaze::BRLID32;
- }
-}
-
-bool MBlazeAsmBackend::MayNeedRelaxation(const MCInst &Inst) const {
- if (getRelaxedOpcode(Inst.getOpcode()) == Inst.getOpcode())
- return false;
-
- bool hasExprOrImm = false;
- for (unsigned i = 0; i < Inst.getNumOperands(); ++i)
- hasExprOrImm |= Inst.getOperand(i).isExpr();
-
- return hasExprOrImm;
-}
-
-void MBlazeAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
- Res = Inst;
- Res.setOpcode(getRelaxedOpcode(Inst.getOpcode()));
-}
-
-bool MBlazeAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
- if ((Count % 4) != 0)
- return false;
-
- for (uint64_t i = 0; i < Count; i += 4)
- OW->Write32(0x00000000);
-
- return true;
-}
-} // end anonymous namespace
-
-namespace {
-class ELFMBlazeAsmBackend : public MBlazeAsmBackend {
-public:
- Triple::OSType OSType;
- ELFMBlazeAsmBackend(const Target &T, Triple::OSType _OSType)
- : MBlazeAsmBackend(T), OSType(_OSType) { }
-
- void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
- uint64_t Value) const;
-
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- return createELFObjectWriter(new MBlazeELFObjectWriter(OSType), OS,
- /*IsLittleEndian*/ false);
- }
-};
-
-void ELFMBlazeAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data,
- unsigned DataSize, uint64_t Value) const {
- unsigned Size = getFixupKindSize(Fixup.getKind());
-
- assert(Fixup.getOffset() + Size <= DataSize &&
- "Invalid fixup offset!");
-
- char *data = Data + Fixup.getOffset();
- switch (Size) {
- default: llvm_unreachable("Cannot fixup unknown value.");
- case 1: llvm_unreachable("Cannot fixup 1 byte value.");
- case 8: llvm_unreachable("Cannot fixup 8 byte value.");
-
- case 4:
- *(data+7) = uint8_t(Value);
- *(data+6) = uint8_t(Value >> 8);
- *(data+3) = uint8_t(Value >> 16);
- *(data+2) = uint8_t(Value >> 24);
- break;
-
- case 2:
- *(data+3) = uint8_t(Value >> 0);
- *(data+2) = uint8_t(Value >> 8);
- }
-}
-} // end anonymous namespace
-
-TargetAsmBackend *llvm::createMBlazeAsmBackend(const Target &T,
- const std::string &TT) {
- Triple TheTriple(TT);
-
- if (TheTriple.isOSDarwin())
- assert(0 && "Mac not supported on MBlaze");
-
- if (TheTriple.isOSWindows())
- assert(0 && "Windows not supported on MBlaze");
-
- return new ELFMBlazeAsmBackend(T, TheTriple.getOS());
-}
diff --git a/lib/Target/MBlaze/MBlazeAsmPrinter.cpp b/lib/Target/MBlaze/MBlazeAsmPrinter.cpp
index 0016df5..97bd083 100644
--- a/lib/Target/MBlaze/MBlazeAsmPrinter.cpp
+++ b/lib/Target/MBlaze/MBlazeAsmPrinter.cpp
@@ -38,10 +38,10 @@
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <cctype>
@@ -136,19 +136,17 @@ void MBlazeAsmPrinter::printSavedRegsBitmask() {
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg();
- unsigned RegNum = MBlazeRegisterInfo::getRegisterNumbering(Reg);
+ unsigned RegNum = getMBlazeRegisterNumbering(Reg);
if (MBlaze::GPRRegisterClass->contains(Reg))
CPUBitmask |= (1 << RegNum);
}
// Return Address and Frame registers must also be set in CPUBitmask.
if (TFI->hasFP(*MF))
- CPUBitmask |= (1 << MBlazeRegisterInfo::
- getRegisterNumbering(RI.getFrameRegister(*MF)));
+ CPUBitmask |= (1 << getMBlazeRegisterNumbering(RI.getFrameRegister(*MF)));
if (MFI->adjustsStack())
- CPUBitmask |= (1 << MBlazeRegisterInfo::
- getRegisterNumbering(RI.getRARegister()));
+ CPUBitmask |= (1 << getMBlazeRegisterNumbering(RI.getRARegister()));
// Print CPUBitmask
OutStreamer.EmitRawText("\t.mask\t0x" + Twine::utohexstr(CPUBitmask));
@@ -318,18 +316,7 @@ isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
return I == Pred->end() || !I->getDesc().isBarrier();
}
-static MCInstPrinter *createMBlazeMCInstPrinter(const Target &T,
- unsigned SyntaxVariant,
- const MCAsmInfo &MAI) {
- if (SyntaxVariant == 0)
- return new MBlazeInstPrinter(MAI);
- return 0;
-}
-
// Force static initialization.
extern "C" void LLVMInitializeMBlazeAsmPrinter() {
RegisterAsmPrinter<MBlazeAsmPrinter> X(TheMBlazeTarget);
- TargetRegistry::RegisterMCInstPrinter(TheMBlazeTarget,
- createMBlazeMCInstPrinter);
-
}
diff --git a/lib/Target/MBlaze/MBlazeFrameLowering.cpp b/lib/Target/MBlaze/MBlazeFrameLowering.cpp
index e763902..f28d5a7 100644
--- a/lib/Target/MBlaze/MBlazeFrameLowering.cpp
+++ b/lib/Target/MBlaze/MBlazeFrameLowering.cpp
@@ -1,4 +1,4 @@
-//=======- MBlazeFrameLowering.cpp - MBlaze Frame Information ------*- C++ -*-====//
+//===- MBlazeFrameLowering.cpp - MBlaze Frame Information ------*- C++ -*-====//
//
// The LLVM Compiler Infrastructure
//
diff --git a/lib/Target/MBlaze/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp
index 62dfdcc..8ec548f 100644
--- a/lib/Target/MBlaze/MBlazeISelLowering.cpp
+++ b/lib/Target/MBlaze/MBlazeISelLowering.cpp
@@ -59,6 +59,7 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM)
// MBlaze does not have i1 type, so use i32 for
// setcc operations results (slt, sgt, ...).
setBooleanContents(ZeroOrOneBooleanContent);
+ setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
// Set up the register classes
addRegisterClass(MVT::i32, MBlaze::GPRRegisterClass);
@@ -187,7 +188,7 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM)
computeRegisterProperties();
}
-MVT::SimpleValueType MBlazeTargetLowering::getSetCCResultType(EVT VT) const {
+EVT MBlazeTargetLowering::getSetCCResultType(EVT VT) const {
return MVT::i32;
}
@@ -964,13 +965,13 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
// The last register argument that must be saved is MBlaze::R10
TargetRegisterClass *RC = MBlaze::GPRRegisterClass;
- unsigned Begin = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R5);
- unsigned Start = MBlazeRegisterInfo::getRegisterNumbering(ArgRegEnd+1);
- unsigned End = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R10);
+ unsigned Begin = getMBlazeRegisterNumbering(MBlaze::R5);
+ unsigned Start = getMBlazeRegisterNumbering(ArgRegEnd+1);
+ unsigned End = getMBlazeRegisterNumbering(MBlaze::R10);
unsigned StackLoc = Start - Begin + 1;
for (; Start <= End; ++Start, ++StackLoc) {
- unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start);
+ unsigned Reg = getMBlazeRegisterFromNumbering(Start);
unsigned LiveReg = MF.addLiveIn(Reg, RC);
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32);
@@ -1096,7 +1097,7 @@ MBlazeTargetLowering::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:
diff --git a/lib/Target/MBlaze/MBlazeISelLowering.h b/lib/Target/MBlaze/MBlazeISelLowering.h
index bb128da..8b49bc3 100644
--- a/lib/Target/MBlaze/MBlazeISelLowering.h
+++ b/lib/Target/MBlaze/MBlazeISelLowering.h
@@ -102,7 +102,7 @@ namespace llvm {
virtual const char *getTargetNodeName(unsigned Opcode) const;
/// getSetCCResultType - get the ISD::SETCC result ValueType
- MVT::SimpleValueType getSetCCResultType(EVT VT) const;
+ EVT getSetCCResultType(EVT VT) const;
private:
// Subtarget Info
diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.cpp b/lib/Target/MBlaze/MBlazeInstrInfo.cpp
index 188f10a..7ae05b3 100644
--- a/lib/Target/MBlaze/MBlazeInstrInfo.cpp
+++ b/lib/Target/MBlaze/MBlazeInstrInfo.cpp
@@ -17,9 +17,9 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/ADT/STLExtras.h"
#define GET_INSTRINFO_CTOR
@@ -239,7 +239,8 @@ unsigned MBlazeInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
return 2;
}
-bool MBlazeInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
+bool MBlazeInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand>
+ &Cond) const {
assert(Cond.size() == 2 && "Invalid MBlaze branch opcode!");
switch (Cond[0].getImm()) {
default: return true;
diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.h b/lib/Target/MBlaze/MBlazeInstrInfo.h
index 79f962b..7174405 100644
--- a/lib/Target/MBlaze/MBlazeInstrInfo.h
+++ b/lib/Target/MBlaze/MBlazeInstrInfo.h
@@ -166,62 +166,6 @@ namespace MBlaze {
}
}
-/// MBlazeII - This namespace holds all of the target specific flags that
-/// instruction info tracks.
-///
-namespace MBlazeII {
- enum {
- // PseudoFrm - This represents an instruction that is a pseudo instruction
- // or one that has not been implemented yet. It is illegal to code generate
- // it, but tolerated for intermediate implementation stages.
- FPseudo = 0,
- FRRR,
- FRRI,
- FCRR,
- FCRI,
- FRCR,
- FRCI,
- FCCR,
- FCCI,
- FRRCI,
- FRRC,
- FRCX,
- FRCS,
- FCRCS,
- FCRCX,
- FCX,
- FCR,
- FRIR,
- FRRRR,
- FRI,
- FC,
- FormMask = 63
-
- //===------------------------------------------------------------------===//
- // MBlaze Specific MachineOperand flags.
- // MO_NO_FLAG,
-
- /// MO_GOT - Represents the offset into the global offset table at which
- /// the address the relocation entry symbol resides during execution.
- // MO_GOT,
-
- /// MO_GOT_CALL - Represents the offset into the global offset table at
- /// which the address of a call site relocation entry symbol resides
- /// during execution. This is different from the above since this flag
- /// can only be present in call instructions.
- // MO_GOT_CALL,
-
- /// MO_GPREL - Represents the offset from the current gp value to be used
- /// for the relocatable object file being produced.
- // MO_GPREL,
-
- /// MO_ABS_HILO - Represents the hi or low part of an absolute symbol
- /// address.
- // MO_ABS_HILO
-
- };
-}
-
class MBlazeInstrInfo : public MBlazeGenInstrInfo {
MBlazeTargetMachine &TM;
const MBlazeRegisterInfo RI;
diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.td b/lib/Target/MBlaze/MBlazeInstrInfo.td
index 950f2d7..1d8c987 100644
--- a/lib/Target/MBlaze/MBlazeInstrInfo.td
+++ b/lib/Target/MBlaze/MBlazeInstrInfo.td
@@ -442,17 +442,19 @@ let Predicates=[HasMul] in {
//===----------------------------------------------------------------------===//
let canFoldAsLoad = 1, isReMaterializable = 1 in {
- def LBU : LoadM<0x30, 0x000, "lbu ">;
- def LBUR : LoadM<0x30, 0x200, "lbur ">;
+ let neverHasSideEffects = 1 in {
+ def LBU : LoadM<0x30, 0x000, "lbu ">;
+ def LBUR : LoadM<0x30, 0x200, "lbur ">;
- def LHU : LoadM<0x31, 0x000, "lhu ">;
- def LHUR : LoadM<0x31, 0x200, "lhur ">;
+ def LHU : LoadM<0x31, 0x000, "lhu ">;
+ def LHUR : LoadM<0x31, 0x200, "lhur ">;
- def LW : LoadM<0x32, 0x000, "lw ">;
- def LWR : LoadM<0x32, 0x200, "lwr ">;
+ def LW : LoadM<0x32, 0x000, "lw ">;
+ def LWR : LoadM<0x32, 0x200, "lwr ">;
- let Defs = [CARRY] in {
- def LWX : LoadM<0x32, 0x400, "lwx ">;
+ let Defs = [CARRY] in {
+ def LWX : LoadM<0x32, 0x400, "lwx ">;
+ }
}
def LBUI : LoadMI<0x38, "lbui ", zextloadi8>;
@@ -877,6 +879,9 @@ def : Pat<(zextloadi8 xaddr:$addr), (i32 (LBU xaddr:$addr))>;
// Peepholes
def : Pat<(store (i32 0), iaddr:$dst), (SWI (i32 R0), iaddr:$dst)>;
+// Atomic fence
+def : Pat<(atomic_fence (imm), (imm)), (MEMBARRIER)>;
+
//===----------------------------------------------------------------------===//
// Floating Point Support
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp b/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp
index 32d67b2..ea81dd6 100644
--- a/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp
+++ b/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp
@@ -37,7 +37,7 @@ namespace mblazeIntrinsic {
#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
}
-std::string MBlazeIntrinsicInfo::getName(unsigned IntrID, const Type **Tys,
+std::string MBlazeIntrinsicInfo::getName(unsigned IntrID, Type **Tys,
unsigned numTys) const {
static const char *const names[] = {
#define GET_INTRINSIC_NAME_TABLE
@@ -90,8 +90,8 @@ bool MBlazeIntrinsicInfo::isOverloaded(unsigned IntrID) const {
#include "MBlazeGenIntrinsics.inc"
#undef GET_INTRINSIC_ATTRIBUTES
-static const FunctionType *getType(LLVMContext &Context, unsigned id) {
- const Type *ResultTy = NULL;
+static FunctionType *getType(LLVMContext &Context, unsigned id) {
+ Type *ResultTy = NULL;
std::vector<Type*> ArgTys;
bool IsVarArg = false;
@@ -103,7 +103,7 @@ static const FunctionType *getType(LLVMContext &Context, unsigned id) {
}
Function *MBlazeIntrinsicInfo::getDeclaration(Module *M, unsigned IntrID,
- const Type **Tys,
+ Type **Tys,
unsigned numTy) const {
assert(!isOverloaded(IntrID) && "MBlaze intrinsics are not overloaded");
AttrListPtr AList = getAttributes((mblazeIntrinsic::ID) IntrID);
diff --git a/lib/Target/MBlaze/MBlazeIntrinsicInfo.h b/lib/Target/MBlaze/MBlazeIntrinsicInfo.h
index 9804c77..80760d8 100644
--- a/lib/Target/MBlaze/MBlazeIntrinsicInfo.h
+++ b/lib/Target/MBlaze/MBlazeIntrinsicInfo.h
@@ -19,12 +19,12 @@ namespace llvm {
class MBlazeIntrinsicInfo : public TargetIntrinsicInfo {
public:
- std::string getName(unsigned IntrID, const Type **Tys = 0,
+ std::string getName(unsigned IntrID, Type **Tys = 0,
unsigned numTys = 0) const;
unsigned lookupName(const char *Name, unsigned Len) const;
unsigned lookupGCCName(const char *Name) const;
bool isOverloaded(unsigned IID) const;
- Function *getDeclaration(Module *M, unsigned ID, const Type **Tys = 0,
+ Function *getDeclaration(Module *M, unsigned ID, Type **Tys = 0,
unsigned numTys = 0) const;
};
diff --git a/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp b/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp
deleted file mode 100644
index ddc636d..0000000
--- a/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-//===-- MBlazeMCCodeEmitter.cpp - Convert MBlaze code to machine code -----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the MBlazeMCCodeEmitter class.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "mccodeemitter"
-#include "MBlaze.h"
-#include "MBlazeInstrInfo.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCFixup.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
-
-namespace {
-class MBlazeMCCodeEmitter : public MCCodeEmitter {
- MBlazeMCCodeEmitter(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT
- void operator=(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT
- const MCInstrInfo &MCII;
-
-public:
- MBlazeMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
- MCContext &ctx)
- : MCII(mcii) {
- }
-
- ~MBlazeMCCodeEmitter() {}
-
- // getBinaryCodeForInstr - TableGen'erated function for getting the
- // binary encoding for an instruction.
- unsigned getBinaryCodeForInstr(const MCInst &MI) const;
-
- /// getMachineOpValue - Return binary encoding of operand. If the machine
- /// operand requires relocation, record the relocation and return zero.
- unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO) const;
- unsigned getMachineOpValue(const MCInst &MI, unsigned OpIdx) const {
- return getMachineOpValue(MI, MI.getOperand(OpIdx));
- }
-
- static unsigned GetMBlazeRegNum(const MCOperand &MO) {
- // FIXME: getMBlazeRegisterNumbering() is sufficient?
- assert(0 && "MBlazeMCCodeEmitter::GetMBlazeRegNum() not yet implemented.");
- return 0;
- }
-
- void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
- // The MicroBlaze uses a bit reversed format so we need to reverse the
- // order of the bits. Taken from:
- // http://graphics.stanford.edu/~seander/bithacks.html
- C = ((C * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
-
- OS << (char)C;
- ++CurByte;
- }
-
- void EmitRawByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
- OS << (char)C;
- ++CurByte;
- }
-
- void EmitConstant(uint64_t Val, unsigned Size, unsigned &CurByte,
- raw_ostream &OS) const {
- assert(Size <= 8 && "size too big in emit constant");
-
- for (unsigned i = 0; i != Size; ++i) {
- EmitByte(Val & 255, CurByte, OS);
- Val >>= 8;
- }
- }
-
- void EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const;
- void EmitIMM(const MCInst &MI, unsigned &CurByte, raw_ostream &OS) const;
-
- void EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel,
- unsigned &CurByte, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const;
-};
-
-} // end anonymous namespace
-
-
-MCCodeEmitter *llvm::createMBlazeMCCodeEmitter(const MCInstrInfo &MCII,
- const MCSubtargetInfo &STI,
- MCContext &Ctx) {
- return new MBlazeMCCodeEmitter(MCII, STI, Ctx);
-}
-
-/// getMachineOpValue - Return binary encoding of operand. If the machine
-/// operand requires relocation, record the relocation and return zero.
-unsigned MBlazeMCCodeEmitter::getMachineOpValue(const MCInst &MI,
- const MCOperand &MO) const {
- if (MO.isReg())
- return MBlazeRegisterInfo::getRegisterNumbering(MO.getReg());
- else if (MO.isImm())
- return static_cast<unsigned>(MO.getImm());
- else if (MO.isExpr())
- return 0; // The relocation has already been recorded at this point.
- else {
-#ifndef NDEBUG
- errs() << MO;
-#endif
- llvm_unreachable(0);
- }
- return 0;
-}
-
-void MBlazeMCCodeEmitter::
-EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const {
- int32_t val = (int32_t)imm.getImm();
- if (val > 32767 || val < -32768) {
- EmitByte(0x0D, CurByte, OS);
- EmitByte(0x00, CurByte, OS);
- EmitRawByte((val >> 24) & 0xFF, CurByte, OS);
- EmitRawByte((val >> 16) & 0xFF, CurByte, OS);
- }
-}
-
-void MBlazeMCCodeEmitter::
-EmitIMM(const MCInst &MI, unsigned &CurByte,raw_ostream &OS) const {
- switch (MI.getOpcode()) {
- default: break;
-
- case MBlaze::ADDIK32:
- case MBlaze::ORI32:
- case MBlaze::BRLID32:
- EmitByte(0x0D, CurByte, OS);
- EmitByte(0x00, CurByte, OS);
- EmitRawByte(0, CurByte, OS);
- EmitRawByte(0, CurByte, OS);
- }
-}
-
-void MBlazeMCCodeEmitter::
-EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel, unsigned &CurByte,
- raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const {
- assert(MI.getNumOperands()>opNo && "Not enought operands for instruction");
-
- MCOperand oper = MI.getOperand(opNo);
-
- if (oper.isImm()) {
- EmitIMM(oper, CurByte, OS);
- } else if (oper.isExpr()) {
- MCFixupKind FixupKind;
- switch (MI.getOpcode()) {
- default:
- FixupKind = pcrel ? FK_PCRel_2 : FK_Data_2;
- Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind));
- break;
- case MBlaze::ORI32:
- case MBlaze::ADDIK32:
- case MBlaze::BRLID32:
- FixupKind = pcrel ? FK_PCRel_4 : FK_Data_4;
- Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind));
- break;
- }
- }
-}
-
-
-
-void MBlazeMCCodeEmitter::
-EncodeInstruction(const MCInst &MI, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const {
- unsigned Opcode = MI.getOpcode();
- const MCInstrDesc &Desc = MCII.get(Opcode);
- uint64_t TSFlags = Desc.TSFlags;
- // Keep track of the current byte being emitted.
- unsigned CurByte = 0;
-
- // Emit an IMM instruction if the instruction we are encoding requires it
- EmitIMM(MI,CurByte,OS);
-
- switch ((TSFlags & MBlazeII::FormMask)) {
- default: break;
- case MBlazeII::FPseudo:
- // Pseudo instructions don't get encoded.
- return;
- case MBlazeII::FRRI:
- EmitImmediate(MI, 2, false, CurByte, OS, Fixups);
- break;
- case MBlazeII::FRIR:
- EmitImmediate(MI, 1, false, CurByte, OS, Fixups);
- break;
- case MBlazeII::FCRI:
- EmitImmediate(MI, 1, true, CurByte, OS, Fixups);
- break;
- case MBlazeII::FRCI:
- EmitImmediate(MI, 1, true, CurByte, OS, Fixups);
- case MBlazeII::FCCI:
- EmitImmediate(MI, 0, true, CurByte, OS, Fixups);
- break;
- }
-
- ++MCNumEmitted; // Keep track of the # of mi's emitted
- unsigned Value = getBinaryCodeForInstr(MI);
- EmitConstant(Value, 4, CurByte, OS);
-}
-
-// FIXME: These #defines shouldn't be necessary. Instead, tblgen should
-// be able to generate code emitter helpers for either variant, like it
-// does for the AsmWriter.
-#define MBlazeCodeEmitter MBlazeMCCodeEmitter
-#define MachineInstr MCInst
-#include "MBlazeGenCodeEmitter.inc"
-#undef MBlazeCodeEmitter
-#undef MachineInstr
diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp
index f0b201a..9788ba9 100644
--- a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp
+++ b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp
@@ -25,7 +25,6 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
@@ -44,164 +43,7 @@ using namespace llvm;
MBlazeRegisterInfo::
MBlazeRegisterInfo(const MBlazeSubtarget &ST, const TargetInstrInfo &tii)
- : MBlazeGenRegisterInfo(), Subtarget(ST), TII(tii) {}
-
-/// getRegisterNumbering - Given the enum value for some register, e.g.
-/// MBlaze::R0, return the number that it corresponds to (e.g. 0).
-unsigned MBlazeRegisterInfo::getRegisterNumbering(unsigned RegEnum) {
- switch (RegEnum) {
- case MBlaze::R0 : return 0;
- case MBlaze::R1 : return 1;
- case MBlaze::R2 : return 2;
- case MBlaze::R3 : return 3;
- case MBlaze::R4 : return 4;
- case MBlaze::R5 : return 5;
- case MBlaze::R6 : return 6;
- case MBlaze::R7 : return 7;
- case MBlaze::R8 : return 8;
- case MBlaze::R9 : return 9;
- case MBlaze::R10 : return 10;
- case MBlaze::R11 : return 11;
- case MBlaze::R12 : return 12;
- case MBlaze::R13 : return 13;
- case MBlaze::R14 : return 14;
- case MBlaze::R15 : return 15;
- case MBlaze::R16 : return 16;
- case MBlaze::R17 : return 17;
- case MBlaze::R18 : return 18;
- case MBlaze::R19 : return 19;
- case MBlaze::R20 : return 20;
- case MBlaze::R21 : return 21;
- case MBlaze::R22 : return 22;
- case MBlaze::R23 : return 23;
- case MBlaze::R24 : return 24;
- case MBlaze::R25 : return 25;
- case MBlaze::R26 : return 26;
- case MBlaze::R27 : return 27;
- case MBlaze::R28 : return 28;
- case MBlaze::R29 : return 29;
- case MBlaze::R30 : return 30;
- case MBlaze::R31 : return 31;
- case MBlaze::RPC : return 0x0000;
- case MBlaze::RMSR : return 0x0001;
- case MBlaze::REAR : return 0x0003;
- case MBlaze::RESR : return 0x0005;
- case MBlaze::RFSR : return 0x0007;
- case MBlaze::RBTR : return 0x000B;
- case MBlaze::REDR : return 0x000D;
- case MBlaze::RPID : return 0x1000;
- case MBlaze::RZPR : return 0x1001;
- case MBlaze::RTLBX : return 0x1002;
- case MBlaze::RTLBLO : return 0x1003;
- case MBlaze::RTLBHI : return 0x1004;
- case MBlaze::RPVR0 : return 0x2000;
- case MBlaze::RPVR1 : return 0x2001;
- case MBlaze::RPVR2 : return 0x2002;
- case MBlaze::RPVR3 : return 0x2003;
- case MBlaze::RPVR4 : return 0x2004;
- case MBlaze::RPVR5 : return 0x2005;
- case MBlaze::RPVR6 : return 0x2006;
- case MBlaze::RPVR7 : return 0x2007;
- case MBlaze::RPVR8 : return 0x2008;
- case MBlaze::RPVR9 : return 0x2009;
- case MBlaze::RPVR10 : return 0x200A;
- case MBlaze::RPVR11 : return 0x200B;
- default: llvm_unreachable("Unknown register number!");
- }
- return 0; // Not reached
-}
-
-/// getRegisterFromNumbering - Given the enum value for some register, e.g.
-/// MBlaze::R0, return the number that it corresponds to (e.g. 0).
-unsigned MBlazeRegisterInfo::getRegisterFromNumbering(unsigned Reg) {
- switch (Reg) {
- case 0 : return MBlaze::R0;
- case 1 : return MBlaze::R1;
- case 2 : return MBlaze::R2;
- case 3 : return MBlaze::R3;
- case 4 : return MBlaze::R4;
- case 5 : return MBlaze::R5;
- case 6 : return MBlaze::R6;
- case 7 : return MBlaze::R7;
- case 8 : return MBlaze::R8;
- case 9 : return MBlaze::R9;
- case 10 : return MBlaze::R10;
- case 11 : return MBlaze::R11;
- case 12 : return MBlaze::R12;
- case 13 : return MBlaze::R13;
- case 14 : return MBlaze::R14;
- case 15 : return MBlaze::R15;
- case 16 : return MBlaze::R16;
- case 17 : return MBlaze::R17;
- case 18 : return MBlaze::R18;
- case 19 : return MBlaze::R19;
- case 20 : return MBlaze::R20;
- case 21 : return MBlaze::R21;
- case 22 : return MBlaze::R22;
- case 23 : return MBlaze::R23;
- case 24 : return MBlaze::R24;
- case 25 : return MBlaze::R25;
- case 26 : return MBlaze::R26;
- case 27 : return MBlaze::R27;
- case 28 : return MBlaze::R28;
- case 29 : return MBlaze::R29;
- case 30 : return MBlaze::R30;
- case 31 : return MBlaze::R31;
- default: llvm_unreachable("Unknown register number!");
- }
- return 0; // Not reached
-}
-
-unsigned MBlazeRegisterInfo::getSpecialRegisterFromNumbering(unsigned Reg) {
- switch (Reg) {
- case 0x0000 : return MBlaze::RPC;
- case 0x0001 : return MBlaze::RMSR;
- case 0x0003 : return MBlaze::REAR;
- case 0x0005 : return MBlaze::RESR;
- case 0x0007 : return MBlaze::RFSR;
- case 0x000B : return MBlaze::RBTR;
- case 0x000D : return MBlaze::REDR;
- case 0x1000 : return MBlaze::RPID;
- case 0x1001 : return MBlaze::RZPR;
- case 0x1002 : return MBlaze::RTLBX;
- case 0x1003 : return MBlaze::RTLBLO;
- case 0x1004 : return MBlaze::RTLBHI;
- case 0x2000 : return MBlaze::RPVR0;
- case 0x2001 : return MBlaze::RPVR1;
- case 0x2002 : return MBlaze::RPVR2;
- case 0x2003 : return MBlaze::RPVR3;
- case 0x2004 : return MBlaze::RPVR4;
- case 0x2005 : return MBlaze::RPVR5;
- case 0x2006 : return MBlaze::RPVR6;
- case 0x2007 : return MBlaze::RPVR7;
- case 0x2008 : return MBlaze::RPVR8;
- case 0x2009 : return MBlaze::RPVR9;
- case 0x200A : return MBlaze::RPVR10;
- case 0x200B : return MBlaze::RPVR11;
- default: llvm_unreachable("Unknown register number!");
- }
- return 0; // Not reached
-}
-
-bool MBlazeRegisterInfo::isRegister(unsigned Reg) {
- return Reg <= 31;
-}
-
-bool MBlazeRegisterInfo::isSpecialRegister(unsigned Reg) {
- switch (Reg) {
- case 0x0000 : case 0x0001 : case 0x0003 : case 0x0005 :
- case 0x0007 : case 0x000B : case 0x000D : case 0x1000 :
- case 0x1001 : case 0x1002 : case 0x1003 : case 0x1004 :
- case 0x2000 : case 0x2001 : case 0x2002 : case 0x2003 :
- case 0x2004 : case 0x2005 : case 0x2006 : case 0x2007 :
- case 0x2008 : case 0x2009 : case 0x200A : case 0x200B :
- return true;
-
- default:
- return false;
- }
- return false; // Not reached
-}
+ : MBlazeGenRegisterInfo(MBlaze::R15), Subtarget(ST), TII(tii) {}
unsigned MBlazeRegisterInfo::getPICCallReg() {
return MBlaze::R20;
@@ -334,10 +176,6 @@ processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
MFI->setObjectOffset(MBlazeFI->getGPFI(), MBlazeFI->getGPStackOffset());
}
-unsigned MBlazeRegisterInfo::getRARegister() const {
- return MBlaze::R15;
-}
-
unsigned MBlazeRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
@@ -353,11 +191,3 @@ unsigned MBlazeRegisterInfo::getEHHandlerRegister() const {
llvm_unreachable("What is the exception handler register");
return 0;
}
-
-int MBlazeRegisterInfo::getDwarfRegNum(unsigned RegNo, bool isEH) const {
- return MBlazeGenRegisterInfo::getDwarfRegNumFull(RegNo,0);
-}
-
-int MBlazeRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const {
- return MBlazeGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0);
-}
diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.h b/lib/Target/MBlaze/MBlazeRegisterInfo.h
index 7ebce21..7e4b269 100644
--- a/lib/Target/MBlaze/MBlazeRegisterInfo.h
+++ b/lib/Target/MBlaze/MBlazeRegisterInfo.h
@@ -42,14 +42,6 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo {
MBlazeRegisterInfo(const MBlazeSubtarget &Subtarget,
const TargetInstrInfo &tii);
- /// getRegisterNumbering - Given the enum value for some register, e.g.
- /// MBlaze::RA, return the number that it corresponds to (e.g. 31).
- static unsigned getRegisterNumbering(unsigned RegEnum);
- static unsigned getRegisterFromNumbering(unsigned RegEnum);
- static unsigned getSpecialRegisterFromNumbering(unsigned RegEnum);
- static bool isRegister(unsigned RegEnum);
- static bool isSpecialRegister(unsigned RegEnum);
-
/// Get PIC indirect call register
static unsigned getPICCallReg();
@@ -69,15 +61,11 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo {
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
/// Debug information queries.
- unsigned getRARegister() const;
unsigned getFrameRegister(const MachineFunction &MF) const;
/// Exception handling queries.
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
-
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- int getLLVMRegNum(unsigned RegNum, bool isEH) const;
};
} // end namespace llvm
diff --git a/lib/Target/MBlaze/MBlazeSubtarget.cpp b/lib/Target/MBlaze/MBlazeSubtarget.cpp
index eda141d..7e5667f 100644
--- a/lib/Target/MBlaze/MBlazeSubtarget.cpp
+++ b/lib/Target/MBlaze/MBlazeSubtarget.cpp
@@ -15,7 +15,7 @@
#include "MBlaze.h"
#include "MBlazeRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.cpp b/lib/Target/MBlaze/MBlazeTargetMachine.cpp
index 7208874..7bff53e 100644
--- a/lib/Target/MBlaze/MBlazeTargetMachine.cpp
+++ b/lib/Target/MBlaze/MBlazeTargetMachine.cpp
@@ -16,48 +16,13 @@
#include "llvm/PassManager.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetRegistry.h"
using namespace llvm;
-static MCStreamer *createMCStreamer(const Target &T, const std::string &TT,
- MCContext &Ctx, TargetAsmBackend &TAB,
- raw_ostream &_OS,
- MCCodeEmitter *_Emitter,
- bool RelaxAll,
- bool NoExecStack) {
- Triple TheTriple(TT);
-
- if (TheTriple.isOSDarwin()) {
- llvm_unreachable("MBlaze does not support Darwin MACH-O format");
- return NULL;
- }
-
- if (TheTriple.isOSWindows()) {
- llvm_unreachable("MBlaze does not support Windows COFF format");
- return NULL;
- }
-
- return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll, NoExecStack);
-}
-
-
extern "C" void LLVMInitializeMBlazeTarget() {
// Register the target.
RegisterTargetMachine<MBlazeTargetMachine> X(TheMBlazeTarget);
-
- // Register the MC code emitter
- TargetRegistry::RegisterCodeEmitter(TheMBlazeTarget,
- llvm::createMBlazeMCCodeEmitter);
-
- // Register the asm backend
- TargetRegistry::RegisterAsmBackend(TheMBlazeTarget,
- createMBlazeAsmBackend);
-
- // Register the object streamer
- TargetRegistry::RegisterObjectStreamer(TheMBlazeTarget,
- createMCStreamer);
-
}
// DataLayout --> Big-endian, 32-bit pointer/ABI/alignment
@@ -67,21 +32,16 @@ extern "C" void LLVMInitializeMBlazeTarget() {
// offset from the stack/frame pointer, using StackGrowsUp enables
// an easier handling.
MBlazeTargetMachine::
-MBlazeTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS):
- LLVMTargetMachine(T, TT, CPU, FS),
+MBlazeTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM):
+ LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
Subtarget(TT, CPU, FS),
DataLayout("E-p:32:32:32-i8:8:8-i16:16:16"),
InstrInfo(*this),
FrameLowering(Subtarget),
TLInfo(*this), TSInfo(*this), ELFWriterInfo(*this),
InstrItins(Subtarget.getInstrItineraryData()) {
- if (getRelocationModel() == Reloc::Default) {
- setRelocationModel(Reloc::Static);
- }
-
- if (getCodeModel() == CodeModel::Default)
- setCodeModel(CodeModel::Small);
}
// Install an instruction selector pass using
diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.h b/lib/Target/MBlaze/MBlazeTargetMachine.h
index cd6caaf..c1bc08a 100644
--- a/lib/Target/MBlaze/MBlazeTargetMachine.h
+++ b/lib/Target/MBlaze/MBlazeTargetMachine.h
@@ -41,8 +41,9 @@ namespace llvm {
InstrItineraryData InstrItins;
public:
- MBlazeTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ MBlazeTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
virtual const MBlazeInstrInfo *getInstrInfo() const
{ return &InstrInfo; }
diff --git a/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp b/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp
index abd1b0b..f66ea30 100644
--- a/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp
+++ b/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp
@@ -69,7 +69,7 @@ IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM,
if (Kind.isMergeable1ByteCString())
return false;
- const Type *Ty = GV->getType()->getElementType();
+ Type *Ty = GV->getType()->getElementType();
return IsInSmallSection(TM.getTargetData()->getTypeAllocSize(Ty));
}
diff --git a/lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt b/lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt
index 3d15708..37871b6 100644
--- a/lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt
@@ -1,4 +1,15 @@
add_llvm_library(LLVMMBlazeDesc
- MBlazeMCTargetDesc.cpp
+ MBlazeAsmBackend.cpp
MBlazeMCAsmInfo.cpp
+ MBlazeMCCodeEmitter.cpp
+ MBlazeMCTargetDesc.cpp
+ )
+
+add_llvm_library_dependencies(LLVMMBlazeDesc
+ LLVMMBlazeAsmPrinter
+ LLVMMBlazeInfo
+ LLVMMC
+ LLVMSupport
)
+
+add_dependencies(LLVMMBlazeDesc MBlazeCommonTableGen)
diff --git a/lib/Target/MBlaze/MCTargetDesc/MBlazeAsmBackend.cpp b/lib/Target/MBlaze/MCTargetDesc/MBlazeAsmBackend.cpp
new file mode 100644
index 0000000..08f7d46a
--- /dev/null
+++ b/lib/Target/MBlaze/MCTargetDesc/MBlazeAsmBackend.cpp
@@ -0,0 +1,159 @@
+//===-- MBlazeAsmBackend.cpp - MBlaze Assembler Backend -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/MBlazeMCTargetDesc.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCAsmLayout.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCELFSymbolFlags.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+static unsigned getFixupKindSize(unsigned Kind) {
+ switch (Kind) {
+ default: assert(0 && "invalid fixup kind!");
+ case FK_Data_1: return 1;
+ case FK_PCRel_2:
+ case FK_Data_2: return 2;
+ case FK_PCRel_4:
+ case FK_Data_4: return 4;
+ case FK_Data_8: return 8;
+ }
+}
+
+
+namespace {
+class MBlazeELFObjectWriter : public MCELFObjectTargetWriter {
+public:
+ MBlazeELFObjectWriter(Triple::OSType OSType)
+ : MCELFObjectTargetWriter(/*is64Bit*/ false, OSType, ELF::EM_MBLAZE,
+ /*HasRelocationAddend*/ true) {}
+};
+
+class MBlazeAsmBackend : public MCAsmBackend {
+public:
+ MBlazeAsmBackend(const Target &T)
+ : MCAsmBackend() {
+ }
+
+ unsigned getNumFixupKinds() const {
+ return 2;
+ }
+
+ bool MayNeedRelaxation(const MCInst &Inst) const;
+
+ void RelaxInstruction(const MCInst &Inst, MCInst &Res) const;
+
+ bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const;
+
+ unsigned getPointerSize() const {
+ return 4;
+ }
+};
+
+static unsigned getRelaxedOpcode(unsigned Op) {
+ switch (Op) {
+ default: return Op;
+ case MBlaze::ADDIK: return MBlaze::ADDIK32;
+ case MBlaze::ORI: return MBlaze::ORI32;
+ case MBlaze::BRLID: return MBlaze::BRLID32;
+ }
+}
+
+bool MBlazeAsmBackend::MayNeedRelaxation(const MCInst &Inst) const {
+ if (getRelaxedOpcode(Inst.getOpcode()) == Inst.getOpcode())
+ return false;
+
+ bool hasExprOrImm = false;
+ for (unsigned i = 0; i < Inst.getNumOperands(); ++i)
+ hasExprOrImm |= Inst.getOperand(i).isExpr();
+
+ return hasExprOrImm;
+}
+
+void MBlazeAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
+ Res = Inst;
+ Res.setOpcode(getRelaxedOpcode(Inst.getOpcode()));
+}
+
+bool MBlazeAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
+ if ((Count % 4) != 0)
+ return false;
+
+ for (uint64_t i = 0; i < Count; i += 4)
+ OW->Write32(0x00000000);
+
+ return true;
+}
+} // end anonymous namespace
+
+namespace {
+class ELFMBlazeAsmBackend : public MBlazeAsmBackend {
+public:
+ Triple::OSType OSType;
+ ELFMBlazeAsmBackend(const Target &T, Triple::OSType _OSType)
+ : MBlazeAsmBackend(T), OSType(_OSType) { }
+
+ void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
+ uint64_t Value) const;
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ return createELFObjectWriter(new MBlazeELFObjectWriter(OSType), OS,
+ /*IsLittleEndian*/ false);
+ }
+};
+
+void ELFMBlazeAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data,
+ unsigned DataSize, uint64_t Value) const {
+ unsigned Size = getFixupKindSize(Fixup.getKind());
+
+ assert(Fixup.getOffset() + Size <= DataSize &&
+ "Invalid fixup offset!");
+
+ char *data = Data + Fixup.getOffset();
+ switch (Size) {
+ default: llvm_unreachable("Cannot fixup unknown value.");
+ case 1: llvm_unreachable("Cannot fixup 1 byte value.");
+ case 8: llvm_unreachable("Cannot fixup 8 byte value.");
+
+ case 4:
+ *(data+7) = uint8_t(Value);
+ *(data+6) = uint8_t(Value >> 8);
+ *(data+3) = uint8_t(Value >> 16);
+ *(data+2) = uint8_t(Value >> 24);
+ break;
+
+ case 2:
+ *(data+3) = uint8_t(Value >> 0);
+ *(data+2) = uint8_t(Value >> 8);
+ }
+}
+} // end anonymous namespace
+
+MCAsmBackend *llvm::createMBlazeAsmBackend(const Target &T, StringRef TT) {
+ Triple TheTriple(TT);
+
+ if (TheTriple.isOSDarwin())
+ assert(0 && "Mac not supported on MBlaze");
+
+ if (TheTriple.isOSWindows())
+ assert(0 && "Windows not supported on MBlaze");
+
+ return new ELFMBlazeAsmBackend(T, TheTriple.getOS());
+}
diff --git a/lib/Target/MBlaze/MCTargetDesc/MBlazeBaseInfo.h b/lib/Target/MBlaze/MCTargetDesc/MBlazeBaseInfo.h
new file mode 100644
index 0000000..776dbc4
--- /dev/null
+++ b/lib/Target/MBlaze/MCTargetDesc/MBlazeBaseInfo.h
@@ -0,0 +1,240 @@
+//===-- MBlazeBaseInfo.h - Top level definitions for MBlaze -- --*- 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 small standalone helper functions and enum definitions for
+// the MBlaze target useful for the compiler back-end and the MC libraries.
+// As such, it deliberately does not include references to LLVM core
+// code gen types, passes, etc..
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MBlazeBASEINFO_H
+#define MBlazeBASEINFO_H
+
+#include "MBlazeMCTargetDesc.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace llvm {
+
+/// MBlazeII - This namespace holds all of the target specific flags that
+/// instruction info tracks.
+///
+namespace MBlazeII {
+ enum {
+ // PseudoFrm - This represents an instruction that is a pseudo instruction
+ // or one that has not been implemented yet. It is illegal to code generate
+ // it, but tolerated for intermediate implementation stages.
+ FPseudo = 0,
+ FRRR,
+ FRRI,
+ FCRR,
+ FCRI,
+ FRCR,
+ FRCI,
+ FCCR,
+ FCCI,
+ FRRCI,
+ FRRC,
+ FRCX,
+ FRCS,
+ FCRCS,
+ FCRCX,
+ FCX,
+ FCR,
+ FRIR,
+ FRRRR,
+ FRI,
+ FC,
+ FormMask = 63
+
+ //===------------------------------------------------------------------===//
+ // MBlaze Specific MachineOperand flags.
+ // MO_NO_FLAG,
+
+ /// MO_GOT - Represents the offset into the global offset table at which
+ /// the address the relocation entry symbol resides during execution.
+ // MO_GOT,
+
+ /// MO_GOT_CALL - Represents the offset into the global offset table at
+ /// which the address of a call site relocation entry symbol resides
+ /// during execution. This is different from the above since this flag
+ /// can only be present in call instructions.
+ // MO_GOT_CALL,
+
+ /// MO_GPREL - Represents the offset from the current gp value to be used
+ /// for the relocatable object file being produced.
+ // MO_GPREL,
+
+ /// MO_ABS_HILO - Represents the hi or low part of an absolute symbol
+ /// address.
+ // MO_ABS_HILO
+
+ };
+}
+
+static inline bool isMBlazeRegister(unsigned Reg) {
+ return Reg <= 31;
+}
+
+static inline bool isSpecialMBlazeRegister(unsigned Reg) {
+ switch (Reg) {
+ case 0x0000 : case 0x0001 : case 0x0003 : case 0x0005 :
+ case 0x0007 : case 0x000B : case 0x000D : case 0x1000 :
+ case 0x1001 : case 0x1002 : case 0x1003 : case 0x1004 :
+ case 0x2000 : case 0x2001 : case 0x2002 : case 0x2003 :
+ case 0x2004 : case 0x2005 : case 0x2006 : case 0x2007 :
+ case 0x2008 : case 0x2009 : case 0x200A : case 0x200B :
+ return true;
+
+ default:
+ return false;
+ }
+ return false; // Not reached
+}
+
+/// getMBlazeRegisterNumbering - Given the enum value for some register, e.g.
+/// MBlaze::R0, return the number that it corresponds to (e.g. 0).
+static inline unsigned getMBlazeRegisterNumbering(unsigned RegEnum) {
+ switch (RegEnum) {
+ case MBlaze::R0 : return 0;
+ case MBlaze::R1 : return 1;
+ case MBlaze::R2 : return 2;
+ case MBlaze::R3 : return 3;
+ case MBlaze::R4 : return 4;
+ case MBlaze::R5 : return 5;
+ case MBlaze::R6 : return 6;
+ case MBlaze::R7 : return 7;
+ case MBlaze::R8 : return 8;
+ case MBlaze::R9 : return 9;
+ case MBlaze::R10 : return 10;
+ case MBlaze::R11 : return 11;
+ case MBlaze::R12 : return 12;
+ case MBlaze::R13 : return 13;
+ case MBlaze::R14 : return 14;
+ case MBlaze::R15 : return 15;
+ case MBlaze::R16 : return 16;
+ case MBlaze::R17 : return 17;
+ case MBlaze::R18 : return 18;
+ case MBlaze::R19 : return 19;
+ case MBlaze::R20 : return 20;
+ case MBlaze::R21 : return 21;
+ case MBlaze::R22 : return 22;
+ case MBlaze::R23 : return 23;
+ case MBlaze::R24 : return 24;
+ case MBlaze::R25 : return 25;
+ case MBlaze::R26 : return 26;
+ case MBlaze::R27 : return 27;
+ case MBlaze::R28 : return 28;
+ case MBlaze::R29 : return 29;
+ case MBlaze::R30 : return 30;
+ case MBlaze::R31 : return 31;
+ case MBlaze::RPC : return 0x0000;
+ case MBlaze::RMSR : return 0x0001;
+ case MBlaze::REAR : return 0x0003;
+ case MBlaze::RESR : return 0x0005;
+ case MBlaze::RFSR : return 0x0007;
+ case MBlaze::RBTR : return 0x000B;
+ case MBlaze::REDR : return 0x000D;
+ case MBlaze::RPID : return 0x1000;
+ case MBlaze::RZPR : return 0x1001;
+ case MBlaze::RTLBX : return 0x1002;
+ case MBlaze::RTLBLO : return 0x1003;
+ case MBlaze::RTLBHI : return 0x1004;
+ case MBlaze::RPVR0 : return 0x2000;
+ case MBlaze::RPVR1 : return 0x2001;
+ case MBlaze::RPVR2 : return 0x2002;
+ case MBlaze::RPVR3 : return 0x2003;
+ case MBlaze::RPVR4 : return 0x2004;
+ case MBlaze::RPVR5 : return 0x2005;
+ case MBlaze::RPVR6 : return 0x2006;
+ case MBlaze::RPVR7 : return 0x2007;
+ case MBlaze::RPVR8 : return 0x2008;
+ case MBlaze::RPVR9 : return 0x2009;
+ case MBlaze::RPVR10 : return 0x200A;
+ case MBlaze::RPVR11 : return 0x200B;
+ default: llvm_unreachable("Unknown register number!");
+ }
+ return 0; // Not reached
+}
+
+/// getRegisterFromNumbering - Given the enum value for some register, e.g.
+/// MBlaze::R0, return the number that it corresponds to (e.g. 0).
+static inline unsigned getMBlazeRegisterFromNumbering(unsigned Reg) {
+ switch (Reg) {
+ case 0 : return MBlaze::R0;
+ case 1 : return MBlaze::R1;
+ case 2 : return MBlaze::R2;
+ case 3 : return MBlaze::R3;
+ case 4 : return MBlaze::R4;
+ case 5 : return MBlaze::R5;
+ case 6 : return MBlaze::R6;
+ case 7 : return MBlaze::R7;
+ case 8 : return MBlaze::R8;
+ case 9 : return MBlaze::R9;
+ case 10 : return MBlaze::R10;
+ case 11 : return MBlaze::R11;
+ case 12 : return MBlaze::R12;
+ case 13 : return MBlaze::R13;
+ case 14 : return MBlaze::R14;
+ case 15 : return MBlaze::R15;
+ case 16 : return MBlaze::R16;
+ case 17 : return MBlaze::R17;
+ case 18 : return MBlaze::R18;
+ case 19 : return MBlaze::R19;
+ case 20 : return MBlaze::R20;
+ case 21 : return MBlaze::R21;
+ case 22 : return MBlaze::R22;
+ case 23 : return MBlaze::R23;
+ case 24 : return MBlaze::R24;
+ case 25 : return MBlaze::R25;
+ case 26 : return MBlaze::R26;
+ case 27 : return MBlaze::R27;
+ case 28 : return MBlaze::R28;
+ case 29 : return MBlaze::R29;
+ case 30 : return MBlaze::R30;
+ case 31 : return MBlaze::R31;
+ default: llvm_unreachable("Unknown register number!");
+ }
+ return 0; // Not reached
+}
+
+static inline unsigned getSpecialMBlazeRegisterFromNumbering(unsigned Reg) {
+ switch (Reg) {
+ case 0x0000 : return MBlaze::RPC;
+ case 0x0001 : return MBlaze::RMSR;
+ case 0x0003 : return MBlaze::REAR;
+ case 0x0005 : return MBlaze::RESR;
+ case 0x0007 : return MBlaze::RFSR;
+ case 0x000B : return MBlaze::RBTR;
+ case 0x000D : return MBlaze::REDR;
+ case 0x1000 : return MBlaze::RPID;
+ case 0x1001 : return MBlaze::RZPR;
+ case 0x1002 : return MBlaze::RTLBX;
+ case 0x1003 : return MBlaze::RTLBLO;
+ case 0x1004 : return MBlaze::RTLBHI;
+ case 0x2000 : return MBlaze::RPVR0;
+ case 0x2001 : return MBlaze::RPVR1;
+ case 0x2002 : return MBlaze::RPVR2;
+ case 0x2003 : return MBlaze::RPVR3;
+ case 0x2004 : return MBlaze::RPVR4;
+ case 0x2005 : return MBlaze::RPVR5;
+ case 0x2006 : return MBlaze::RPVR6;
+ case 0x2007 : return MBlaze::RPVR7;
+ case 0x2008 : return MBlaze::RPVR8;
+ case 0x2009 : return MBlaze::RPVR9;
+ case 0x200A : return MBlaze::RPVR10;
+ case 0x200B : return MBlaze::RPVR11;
+ default: llvm_unreachable("Unknown register number!");
+ }
+ return 0; // Not reached
+}
+
+} // end namespace llvm;
+
+#endif
diff --git a/lib/Target/MBlaze/MCTargetDesc/MBlazeMCCodeEmitter.cpp b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCCodeEmitter.cpp
new file mode 100644
index 0000000..1514557
--- /dev/null
+++ b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCCodeEmitter.cpp
@@ -0,0 +1,224 @@
+//===-- MBlazeMCCodeEmitter.cpp - Convert MBlaze code to machine code -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the MBlazeMCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mccodeemitter"
+#include "MCTargetDesc/MBlazeBaseInfo.h"
+#include "MCTargetDesc/MBlazeMCTargetDesc.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
+
+namespace {
+class MBlazeMCCodeEmitter : public MCCodeEmitter {
+ MBlazeMCCodeEmitter(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT
+ void operator=(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT
+ const MCInstrInfo &MCII;
+
+public:
+ MBlazeMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
+ MCContext &ctx)
+ : MCII(mcii) {
+ }
+
+ ~MBlazeMCCodeEmitter() {}
+
+ // getBinaryCodeForInstr - TableGen'erated function for getting the
+ // binary encoding for an instruction.
+ unsigned getBinaryCodeForInstr(const MCInst &MI) const;
+
+ /// getMachineOpValue - Return binary encoding of operand. If the machine
+ /// operand requires relocation, record the relocation and return zero.
+ unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO) const;
+ unsigned getMachineOpValue(const MCInst &MI, unsigned OpIdx) const {
+ return getMachineOpValue(MI, MI.getOperand(OpIdx));
+ }
+
+ static unsigned GetMBlazeRegNum(const MCOperand &MO) {
+ // FIXME: getMBlazeRegisterNumbering() is sufficient?
+ assert(0 && "MBlazeMCCodeEmitter::GetMBlazeRegNum() not yet implemented.");
+ return 0;
+ }
+
+ void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
+ // The MicroBlaze uses a bit reversed format so we need to reverse the
+ // order of the bits. Taken from:
+ // http://graphics.stanford.edu/~seander/bithacks.html
+ C = ((C * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
+
+ OS << (char)C;
+ ++CurByte;
+ }
+
+ void EmitRawByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
+ OS << (char)C;
+ ++CurByte;
+ }
+
+ void EmitConstant(uint64_t Val, unsigned Size, unsigned &CurByte,
+ raw_ostream &OS) const {
+ assert(Size <= 8 && "size too big in emit constant");
+
+ for (unsigned i = 0; i != Size; ++i) {
+ EmitByte(Val & 255, CurByte, OS);
+ Val >>= 8;
+ }
+ }
+
+ void EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const;
+ void EmitIMM(const MCInst &MI, unsigned &CurByte, raw_ostream &OS) const;
+
+ void EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel,
+ unsigned &CurByte, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+};
+
+} // end anonymous namespace
+
+
+MCCodeEmitter *llvm::createMBlazeMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new MBlazeMCCodeEmitter(MCII, STI, Ctx);
+}
+
+/// getMachineOpValue - Return binary encoding of operand. If the machine
+/// operand requires relocation, record the relocation and return zero.
+unsigned MBlazeMCCodeEmitter::getMachineOpValue(const MCInst &MI,
+ const MCOperand &MO) const {
+ if (MO.isReg())
+ return getMBlazeRegisterNumbering(MO.getReg());
+ else if (MO.isImm())
+ return static_cast<unsigned>(MO.getImm());
+ else if (MO.isExpr())
+ return 0; // The relocation has already been recorded at this point.
+ else {
+#ifndef NDEBUG
+ errs() << MO;
+#endif
+ llvm_unreachable(0);
+ }
+ return 0;
+}
+
+void MBlazeMCCodeEmitter::
+EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const {
+ int32_t val = (int32_t)imm.getImm();
+ if (val > 32767 || val < -32768) {
+ EmitByte(0x0D, CurByte, OS);
+ EmitByte(0x00, CurByte, OS);
+ EmitRawByte((val >> 24) & 0xFF, CurByte, OS);
+ EmitRawByte((val >> 16) & 0xFF, CurByte, OS);
+ }
+}
+
+void MBlazeMCCodeEmitter::
+EmitIMM(const MCInst &MI, unsigned &CurByte,raw_ostream &OS) const {
+ switch (MI.getOpcode()) {
+ default: break;
+
+ case MBlaze::ADDIK32:
+ case MBlaze::ORI32:
+ case MBlaze::BRLID32:
+ EmitByte(0x0D, CurByte, OS);
+ EmitByte(0x00, CurByte, OS);
+ EmitRawByte(0, CurByte, OS);
+ EmitRawByte(0, CurByte, OS);
+ }
+}
+
+void MBlazeMCCodeEmitter::
+EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel, unsigned &CurByte,
+ raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const {
+ assert(MI.getNumOperands()>opNo && "Not enought operands for instruction");
+
+ MCOperand oper = MI.getOperand(opNo);
+
+ if (oper.isImm()) {
+ EmitIMM(oper, CurByte, OS);
+ } else if (oper.isExpr()) {
+ MCFixupKind FixupKind;
+ switch (MI.getOpcode()) {
+ default:
+ FixupKind = pcrel ? FK_PCRel_2 : FK_Data_2;
+ Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind));
+ break;
+ case MBlaze::ORI32:
+ case MBlaze::ADDIK32:
+ case MBlaze::BRLID32:
+ FixupKind = pcrel ? FK_PCRel_4 : FK_Data_4;
+ Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind));
+ break;
+ }
+ }
+}
+
+
+
+void MBlazeMCCodeEmitter::
+EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ unsigned Opcode = MI.getOpcode();
+ const MCInstrDesc &Desc = MCII.get(Opcode);
+ uint64_t TSFlags = Desc.TSFlags;
+ // Keep track of the current byte being emitted.
+ unsigned CurByte = 0;
+
+ // Emit an IMM instruction if the instruction we are encoding requires it
+ EmitIMM(MI,CurByte,OS);
+
+ switch ((TSFlags & MBlazeII::FormMask)) {
+ default: break;
+ case MBlazeII::FPseudo:
+ // Pseudo instructions don't get encoded.
+ return;
+ case MBlazeII::FRRI:
+ EmitImmediate(MI, 2, false, CurByte, OS, Fixups);
+ break;
+ case MBlazeII::FRIR:
+ EmitImmediate(MI, 1, false, CurByte, OS, Fixups);
+ break;
+ case MBlazeII::FCRI:
+ EmitImmediate(MI, 1, true, CurByte, OS, Fixups);
+ break;
+ case MBlazeII::FRCI:
+ EmitImmediate(MI, 1, true, CurByte, OS, Fixups);
+ case MBlazeII::FCCI:
+ EmitImmediate(MI, 0, true, CurByte, OS, Fixups);
+ break;
+ }
+
+ ++MCNumEmitted; // Keep track of the # of mi's emitted
+ unsigned Value = getBinaryCodeForInstr(MI);
+ EmitConstant(Value, 4, CurByte, OS);
+}
+
+// FIXME: These #defines shouldn't be necessary. Instead, tblgen should
+// be able to generate code emitter helpers for either variant, like it
+// does for the AsmWriter.
+#define MBlazeCodeEmitter MBlazeMCCodeEmitter
+#define MachineInstr MCInst
+#include "MBlazeGenCodeEmitter.inc"
+#undef MBlazeCodeEmitter
+#undef MachineInstr
diff --git a/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp
index 20d6c0b..43ae281 100644
--- a/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp
+++ b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp
@@ -13,10 +13,14 @@
#include "MBlazeMCTargetDesc.h"
#include "MBlazeMCAsmInfo.h"
+#include "InstPrinter/MBlazeInstPrinter.h"
+#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_MC_DESC
#include "MBlazeGenInstrInfo.inc"
@@ -36,8 +40,10 @@ static MCInstrInfo *createMBlazeMCInstrInfo() {
return X;
}
-extern "C" void LLVMInitializeMBlazeMCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(TheMBlazeTarget, createMBlazeMCInstrInfo);
+static MCRegisterInfo *createMBlazeMCRegisterInfo(StringRef TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitMBlazeMCRegisterInfo(X, MBlaze::R15);
+ return X;
}
static MCSubtargetInfo *createMBlazeMCSubtargetInfo(StringRef TT, StringRef CPU,
@@ -47,11 +53,6 @@ static MCSubtargetInfo *createMBlazeMCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-extern "C" void LLVMInitializeMBlazeMCSubtargetInfo() {
- TargetRegistry::RegisterMCSubtargetInfo(TheMBlazeTarget,
- createMBlazeMCSubtargetInfo);
-}
-
static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) {
Triple TheTriple(TT);
switch (TheTriple.getOS()) {
@@ -60,6 +61,80 @@ static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) {
}
}
-extern "C" void LLVMInitializeMBlazeMCAsmInfo() {
+static MCCodeGenInfo *createMBlazeMCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+ if (RM == Reloc::Default)
+ RM = Reloc::Static;
+ if (CM == CodeModel::Default)
+ CM = CodeModel::Small;
+ X->InitMCCodeGenInfo(RM, CM);
+ return X;
+}
+
+static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
+ MCContext &Ctx, MCAsmBackend &MAB,
+ raw_ostream &_OS,
+ MCCodeEmitter *_Emitter,
+ bool RelaxAll,
+ bool NoExecStack) {
+ Triple TheTriple(TT);
+
+ if (TheTriple.isOSDarwin()) {
+ llvm_unreachable("MBlaze does not support Darwin MACH-O format");
+ return NULL;
+ }
+
+ if (TheTriple.isOSWindows()) {
+ llvm_unreachable("MBlaze does not support Windows COFF format");
+ return NULL;
+ }
+
+ return createELFStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll, NoExecStack);
+}
+
+static MCInstPrinter *createMBlazeMCInstPrinter(const Target &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI) {
+ if (SyntaxVariant == 0)
+ return new MBlazeInstPrinter(MAI);
+ return 0;
+}
+
+// Force static initialization.
+extern "C" void LLVMInitializeMBlazeTargetMC() {
+ // Register the MC asm info.
RegisterMCAsmInfoFn X(TheMBlazeTarget, createMCAsmInfo);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(TheMBlazeTarget,
+ createMBlazeMCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheMBlazeTarget, createMBlazeMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheMBlazeTarget,
+ createMBlazeMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(TheMBlazeTarget,
+ createMBlazeMCSubtargetInfo);
+
+ // Register the MC code emitter
+ TargetRegistry::RegisterMCCodeEmitter(TheMBlazeTarget,
+ llvm::createMBlazeMCCodeEmitter);
+
+ // Register the asm backend
+ TargetRegistry::RegisterMCAsmBackend(TheMBlazeTarget,
+ createMBlazeAsmBackend);
+
+ // Register the object streamer
+ TargetRegistry::RegisterMCObjectStreamer(TheMBlazeTarget,
+ createMCStreamer);
+
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(TheMBlazeTarget,
+ createMBlazeMCInstPrinter);
}
diff --git a/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h
index b14772e..deff5cb 100644
--- a/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h
+++ b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h
@@ -15,12 +15,23 @@
#define MBLAZEMCTARGETDESC_H
namespace llvm {
+class MCAsmBackend;
+class MCContext;
+class MCCodeEmitter;
+class MCInstrInfo;
class MCSubtargetInfo;
class Target;
class StringRef;
+class formatted_raw_ostream;
extern Target TheMBlazeTarget;
+MCCodeEmitter *createMBlazeMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx);
+
+MCAsmBackend *createMBlazeAsmBackend(const Target &T, StringRef TT);
+
} // End llvm namespace
// Defines symbolic names for MBlaze registers. This defines a mapping from
diff --git a/lib/Target/MBlaze/TargetInfo/CMakeLists.txt b/lib/Target/MBlaze/TargetInfo/CMakeLists.txt
index 40696f6..93fce58 100644
--- a/lib/Target/MBlaze/TargetInfo/CMakeLists.txt
+++ b/lib/Target/MBlaze/TargetInfo/CMakeLists.txt
@@ -5,4 +5,10 @@ add_llvm_library(LLVMMBlazeInfo
MBlazeTargetInfo.cpp
)
-add_dependencies(LLVMMBlazeInfo MBlazeCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMMBlazeInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMMBlazeInfo MBlazeCommonTableGen)
diff --git a/lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp b/lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp
index 16e01db..71210d8 100644
--- a/lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp
+++ b/lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "MBlaze.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::TheMBlazeTarget;
diff --git a/lib/Target/MSP430/CMakeLists.txt b/lib/Target/MSP430/CMakeLists.txt
index 33f3d44..0952b76 100644
--- a/lib/Target/MSP430/CMakeLists.txt
+++ b/lib/Target/MSP430/CMakeLists.txt
@@ -1,11 +1,12 @@
set(LLVM_TARGET_DEFINITIONS MSP430.td)
-tablegen(MSP430GenRegisterInfo.inc -gen-register-info)
-tablegen(MSP430GenInstrInfo.inc -gen-instr-info)
-tablegen(MSP430GenAsmWriter.inc -gen-asm-writer)
-tablegen(MSP430GenDAGISel.inc -gen-dag-isel)
-tablegen(MSP430GenCallingConv.inc -gen-callingconv)
-tablegen(MSP430GenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(MSP430GenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(MSP430GenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(MSP430GenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(MSP430GenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(MSP430GenCallingConv.inc -gen-callingconv)
+llvm_tablegen(MSP430GenSubtargetInfo.inc -gen-subtarget)
+add_public_tablegen_target(MSP430CommonTableGen)
add_llvm_target(MSP430CodeGen
MSP430BranchSelector.cpp
@@ -21,6 +22,19 @@ add_llvm_target(MSP430CodeGen
MSP430MCInstLower.cpp
)
+add_llvm_library_dependencies(LLVMMSP430CodeGen
+ LLVMAsmPrinter
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMMSP430AsmPrinter
+ LLVMMSP430Desc
+ LLVMMSP430Info
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMTarget
+ )
+
add_subdirectory(InstPrinter)
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
diff --git a/lib/Target/MSP430/InstPrinter/CMakeLists.txt b/lib/Target/MSP430/InstPrinter/CMakeLists.txt
index f5458d5..ce39d95 100644
--- a/lib/Target/MSP430/InstPrinter/CMakeLists.txt
+++ b/lib/Target/MSP430/InstPrinter/CMakeLists.txt
@@ -3,4 +3,10 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/
add_llvm_library(LLVMMSP430AsmPrinter
MSP430InstPrinter.cpp
)
-add_dependencies(LLVMMSP430AsmPrinter MSP430CodeGenTable_gen)
+
+add_llvm_library_dependencies(LLVMMSP430AsmPrinter
+ LLVMMC
+ LLVMSupport
+ )
+
+add_dependencies(LLVMMSP430AsmPrinter MSP430CommonTableGen)
diff --git a/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp b/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp
index e10d4fe..5d6c6ad 100644
--- a/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp
+++ b/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp
@@ -25,8 +25,10 @@ using namespace llvm;
// Include the auto-generated portion of the assembly writer.
#include "MSP430GenAsmWriter.inc"
-void MSP430InstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
+void MSP430InstPrinter::printInst(const MCInst *MI, raw_ostream &O,
+ StringRef Annot) {
printInstruction(MI, O);
+ printAnnotation(O, Annot);
}
void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo,
diff --git a/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h b/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h
index 50d98b7..a1984a8 100644
--- a/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h
+++ b/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h
@@ -22,9 +22,9 @@ namespace llvm {
class MSP430InstPrinter : public MCInstPrinter {
public:
MSP430InstPrinter(const MCAsmInfo &MAI)
- : MCInstPrinter(MAI) {}
+ : MCInstPrinter(MAI) {}
- virtual void printInst(const MCInst *MI, raw_ostream &O);
+ virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, raw_ostream &O);
diff --git a/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt b/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt
index 0f3ebd3..04bd03e 100644
--- a/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt
@@ -2,3 +2,11 @@ add_llvm_library(LLVMMSP430Desc
MSP430MCTargetDesc.cpp
MSP430MCAsmInfo.cpp
)
+
+add_llvm_library_dependencies(LLVMMSP430Desc
+ LLVMMC
+ LLVMMSP430AsmPrinter
+ LLVMMSP430Info
+ )
+
+add_dependencies(LLVMMSP430Desc MSP430CommonTableGen)
diff --git a/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp
index 43a704d..fda70b8 100644
--- a/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp
+++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp
@@ -13,10 +13,12 @@
#include "MSP430MCTargetDesc.h"
#include "MSP430MCAsmInfo.h"
+#include "InstPrinter/MSP430InstPrinter.h"
+#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_MC_DESC
#include "MSP430GenInstrInfo.inc"
@@ -29,18 +31,18 @@
using namespace llvm;
-
static MCInstrInfo *createMSP430MCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
InitMSP430MCInstrInfo(X);
return X;
}
-extern "C" void LLVMInitializeMSP430MCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(TheMSP430Target, createMSP430MCInstrInfo);
+static MCRegisterInfo *createMSP430MCRegisterInfo(StringRef TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitMSP430MCRegisterInfo(X, MSP430::PCW);
+ return X;
}
-
static MCSubtargetInfo *createMSP430MCSubtargetInfo(StringRef TT, StringRef CPU,
StringRef FS) {
MCSubtargetInfo *X = new MCSubtargetInfo();
@@ -48,11 +50,42 @@ static MCSubtargetInfo *createMSP430MCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-extern "C" void LLVMInitializeMSP430MCSubtargetInfo() {
- TargetRegistry::RegisterMCSubtargetInfo(TheMSP430Target,
- createMSP430MCSubtargetInfo);
+static MCCodeGenInfo *createMSP430MCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+ X->InitMCCodeGenInfo(RM, CM);
+ return X;
+}
+
+static MCInstPrinter *createMSP430MCInstPrinter(const Target &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI) {
+ if (SyntaxVariant == 0)
+ return new MSP430InstPrinter(MAI);
+ return 0;
}
-extern "C" void LLVMInitializeMSP430MCAsmInfo() {
+extern "C" void LLVMInitializeMSP430TargetMC() {
+ // Register the MC asm info.
RegisterMCAsmInfo<MSP430MCAsmInfo> X(TheMSP430Target);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(TheMSP430Target,
+ createMSP430MCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheMSP430Target, createMSP430MCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheMSP430Target,
+ createMSP430MCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(TheMSP430Target,
+ createMSP430MCSubtargetInfo);
+
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(TheMSP430Target,
+ createMSP430MCInstPrinter);
}
diff --git a/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h
index 0d8a6bd..35f2590 100644
--- a/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h
+++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef ALPHAMCTARGETDESC_H
-#define ALPHAMCTARGETDESC_H
+#ifndef MSP430MCTARGETDESC_H
+#define MSP430MCTARGETDESC_H
namespace llvm {
class MCSubtargetInfo;
diff --git a/lib/Target/MSP430/MSP430AsmPrinter.cpp b/lib/Target/MSP430/MSP430AsmPrinter.cpp
index 2042056..8836549 100644
--- a/lib/Target/MSP430/MSP430AsmPrinter.cpp
+++ b/lib/Target/MSP430/MSP430AsmPrinter.cpp
@@ -32,9 +32,7 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetLoweringObjectFile.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -163,17 +161,7 @@ void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) {
OutStreamer.EmitInstruction(TmpInst);
}
-static MCInstPrinter *createMSP430MCInstPrinter(const Target &T,
- unsigned SyntaxVariant,
- const MCAsmInfo &MAI) {
- if (SyntaxVariant == 0)
- return new MSP430InstPrinter(MAI);
- return 0;
-}
-
// Force static initialization.
extern "C" void LLVMInitializeMSP430AsmPrinter() {
RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
- TargetRegistry::RegisterMCInstPrinter(TheMSP430Target,
- createMSP430MCInstPrinter);
}
diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp
index 0a3eab1..dc37431 100644
--- a/lib/Target/MSP430/MSP430ISelLowering.cpp
+++ b/lib/Target/MSP430/MSP430ISelLowering.cpp
@@ -79,6 +79,7 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
setStackPointerRegisterToSaveRestore(MSP430::SPW);
setBooleanContents(ZeroOrOneBooleanContent);
+ setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
setSchedulingPreference(Sched::Latency);
// We have post-incremented loads / stores.
@@ -987,8 +988,8 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
}
}
-bool MSP430TargetLowering::isTruncateFree(const Type *Ty1,
- const Type *Ty2) const {
+bool MSP430TargetLowering::isTruncateFree(Type *Ty1,
+ Type *Ty2) const {
if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
return false;
@@ -1002,7 +1003,7 @@ bool MSP430TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {
return (VT1.getSizeInBits() > VT2.getSizeInBits());
}
-bool MSP430TargetLowering::isZExtFree(const Type *Ty1, const Type *Ty2) const {
+bool MSP430TargetLowering::isZExtFree(Type *Ty1, Type *Ty2) const {
// MSP430 implicitly zero-extends 8-bit results in 16-bit registers.
return 0 && Ty1->isIntegerTy(8) && Ty2->isIntegerTy(16);
}
diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h
index bd660a0..237f604 100644
--- a/lib/Target/MSP430/MSP430ISelLowering.h
+++ b/lib/Target/MSP430/MSP430ISelLowering.h
@@ -102,7 +102,7 @@ namespace llvm {
/// isTruncateFree - Return true if it's free to truncate a value of type
/// Ty1 to type Ty2. e.g. On msp430 it's free to truncate a i16 value in
/// register R15W to i8 by referencing its sub-register R15B.
- virtual bool isTruncateFree(const Type *Ty1, const Type *Ty2) const;
+ virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const;
virtual bool isTruncateFree(EVT VT1, EVT VT2) const;
/// isZExtFree - Return true if any actual instruction that defines a value
@@ -113,7 +113,7 @@ namespace llvm {
/// necessarily apply to truncate instructions. e.g. on msp430, all
/// instructions that define 8-bit values implicit zero-extend the result
/// out to 16 bits.
- virtual bool isZExtFree(const Type *Ty1, const Type *Ty2) const;
+ virtual bool isZExtFree(Type *Ty1, Type *Ty2) const;
virtual bool isZExtFree(EVT VT1, EVT VT2) const;
MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI,
diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp
index 846d093..ffd4318 100644
--- a/lib/Target/MSP430/MSP430InstrInfo.cpp
+++ b/lib/Target/MSP430/MSP430InstrInfo.cpp
@@ -20,8 +20,8 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_CTOR
#include "MSP430GenInstrInfo.inc"
diff --git a/lib/Target/MSP430/MSP430RegisterInfo.cpp b/lib/Target/MSP430/MSP430RegisterInfo.cpp
index 1cc60bb..9049c4b 100644
--- a/lib/Target/MSP430/MSP430RegisterInfo.cpp
+++ b/lib/Target/MSP430/MSP430RegisterInfo.cpp
@@ -34,7 +34,7 @@ using namespace llvm;
// FIXME: Provide proper call frame setup / destroy opcodes.
MSP430RegisterInfo::MSP430RegisterInfo(MSP430TargetMachine &tm,
const TargetInstrInfo &tii)
- : MSP430GenRegisterInfo(), TM(tm), TII(tii) {
+ : MSP430GenRegisterInfo(MSP430::PCW), TM(tm), TII(tii) {
StackAlign = TM.getFrameLowering()->getStackAlignment();
}
@@ -233,22 +233,8 @@ MSP430RegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF)
}
}
-unsigned MSP430RegisterInfo::getRARegister() const {
- return MSP430::PCW;
-}
-
unsigned MSP430RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
return TFI->hasFP(MF) ? MSP430::FPW : MSP430::SPW;
}
-
-int MSP430RegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
- llvm_unreachable("Not implemented yet!");
- return 0;
-}
-
-int MSP430RegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const {
- llvm_unreachable("Not implemented yet!");
- return 0;
-}
diff --git a/lib/Target/MSP430/MSP430RegisterInfo.h b/lib/Target/MSP430/MSP430RegisterInfo.h
index fb70594..10a3d53 100644
--- a/lib/Target/MSP430/MSP430RegisterInfo.h
+++ b/lib/Target/MSP430/MSP430RegisterInfo.h
@@ -58,12 +58,7 @@ public:
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
// Debug information queries.
- unsigned getRARegister() const;
unsigned getFrameRegister(const MachineFunction &MF) const;
-
- //! Get DWARF debugging register number
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- int getLLVMRegNum(unsigned RegNum, bool isEH) const;
};
} // end namespace llvm
diff --git a/lib/Target/MSP430/MSP430Subtarget.cpp b/lib/Target/MSP430/MSP430Subtarget.cpp
index b58c50a..3ee14d9 100644
--- a/lib/Target/MSP430/MSP430Subtarget.cpp
+++ b/lib/Target/MSP430/MSP430Subtarget.cpp
@@ -13,7 +13,7 @@
#include "MSP430Subtarget.h"
#include "MSP430.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
diff --git a/lib/Target/MSP430/MSP430TargetMachine.cpp b/lib/Target/MSP430/MSP430TargetMachine.cpp
index 971f512..4dd8933 100644
--- a/lib/Target/MSP430/MSP430TargetMachine.cpp
+++ b/lib/Target/MSP430/MSP430TargetMachine.cpp
@@ -16,7 +16,7 @@
#include "llvm/PassManager.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
extern "C" void LLVMInitializeMSP430Target() {
@@ -25,10 +25,11 @@ extern "C" void LLVMInitializeMSP430Target() {
}
MSP430TargetMachine::MSP430TargetMachine(const Target &T,
- const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : LLVMTargetMachine(T, TT, CPU, FS),
+ StringRef TT,
+ StringRef CPU,
+ StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
Subtarget(TT, CPU, FS),
// FIXME: Check TargetData string.
DataLayout("e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"),
diff --git a/lib/Target/MSP430/MSP430TargetMachine.h b/lib/Target/MSP430/MSP430TargetMachine.h
index 2a9eea0..eb483dc 100644
--- a/lib/Target/MSP430/MSP430TargetMachine.h
+++ b/lib/Target/MSP430/MSP430TargetMachine.h
@@ -38,8 +38,9 @@ class MSP430TargetMachine : public LLVMTargetMachine {
MSP430FrameLowering FrameLowering;
public:
- MSP430TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ MSP430TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
virtual const TargetFrameLowering *getFrameLowering() const {
return &FrameLowering;
diff --git a/lib/Target/MSP430/TargetInfo/CMakeLists.txt b/lib/Target/MSP430/TargetInfo/CMakeLists.txt
index 2d1aa9d..1526946 100644
--- a/lib/Target/MSP430/TargetInfo/CMakeLists.txt
+++ b/lib/Target/MSP430/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMMSP430Info
MSP430TargetInfo.cpp
)
-add_dependencies(LLVMMSP430Info MSP430CodeGenTable_gen)
+add_llvm_library_dependencies(LLVMMSP430Info
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMMSP430Info MSP430CommonTableGen)
diff --git a/lib/Target/MSP430/TargetInfo/MSP430TargetInfo.cpp b/lib/Target/MSP430/TargetInfo/MSP430TargetInfo.cpp
index f9ca5c4..8b3e01e 100644
--- a/lib/Target/MSP430/TargetInfo/MSP430TargetInfo.cpp
+++ b/lib/Target/MSP430/TargetInfo/MSP430TargetInfo.cpp
@@ -9,7 +9,7 @@
#include "MSP430.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::TheMSP430Target;
diff --git a/lib/Target/Mangler.cpp b/lib/Target/Mangler.cpp
index 46c687b..53ad155f 100644
--- a/lib/Target/Mangler.cpp
+++ b/lib/Target/Mangler.cpp
@@ -159,7 +159,7 @@ static void AddFastCallStdCallSuffix(SmallVectorImpl<char> &OutName,
unsigned ArgWords = 0;
for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
AI != AE; ++AI) {
- const Type *Ty = AI->getType();
+ Type *Ty = AI->getType();
// 'Dereference' type in case of byval parameter attribute
if (AI->hasByValAttr())
Ty = cast<PointerType>(Ty)->getElementType();
@@ -214,7 +214,7 @@ void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
// fastcall and stdcall functions usually need @42 at the end to specify
// the argument info.
- const FunctionType *FT = F->getFunctionType();
+ FunctionType *FT = F->getFunctionType();
if ((CC == CallingConv::X86_FastCall || CC == CallingConv::X86_StdCall) &&
// "Pure" variadic functions do not receive @0 suffix.
(!FT->isVarArg() || FT->getNumParams() == 0 ||
diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt
index 36ab1a9..1b4329b 100644
--- a/lib/Target/Mips/CMakeLists.txt
+++ b/lib/Target/Mips/CMakeLists.txt
@@ -1,17 +1,20 @@
set(LLVM_TARGET_DEFINITIONS Mips.td)
-tablegen(MipsGenRegisterInfo.inc -gen-register-info)
-tablegen(MipsGenInstrInfo.inc -gen-instr-info)
-tablegen(MipsGenAsmWriter.inc -gen-asm-writer)
-tablegen(MipsGenDAGISel.inc -gen-dag-isel)
-tablegen(MipsGenCallingConv.inc -gen-callingconv)
-tablegen(MipsGenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(MipsGenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(MipsGenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(MipsGenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(MipsGenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(MipsGenCallingConv.inc -gen-callingconv)
+llvm_tablegen(MipsGenSubtargetInfo.inc -gen-subtarget)
+add_public_tablegen_target(MipsCommonTableGen)
add_llvm_target(MipsCodeGen
MipsAsmPrinter.cpp
+ MipsCodeEmitter.cpp
MipsDelaySlotFiller.cpp
MipsEmitGPRestore.cpp
MipsExpandPseudo.cpp
+ MipsJITInfo.cpp
MipsInstrInfo.cpp
MipsISelDAGToDAG.cpp
MipsISelLowering.cpp
@@ -25,6 +28,19 @@ add_llvm_target(MipsCodeGen
MipsSelectionDAGInfo.cpp
)
+add_llvm_library_dependencies(LLVMMipsCodeGen
+ LLVMAsmPrinter
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMMipsAsmPrinter
+ LLVMMipsDesc
+ LLVMMipsInfo
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMTarget
+ )
+
add_subdirectory(InstPrinter)
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
diff --git a/lib/Target/Mips/InstPrinter/CMakeLists.txt b/lib/Target/Mips/InstPrinter/CMakeLists.txt
index 8852fd4..c45b35d 100644
--- a/lib/Target/Mips/InstPrinter/CMakeLists.txt
+++ b/lib/Target/Mips/InstPrinter/CMakeLists.txt
@@ -3,4 +3,10 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/
add_llvm_library(LLVMMipsAsmPrinter
MipsInstPrinter.cpp
)
-add_dependencies(LLVMMipsAsmPrinter MipsCodeGenTable_gen)
+
+add_llvm_library_dependencies(LLVMMipsAsmPrinter
+ LLVMMC
+ LLVMSupport
+ )
+
+add_dependencies(LLVMMipsAsmPrinter MipsCommonTableGen)
diff --git a/lib/Target/Mips/InstPrinter/Makefile b/lib/Target/Mips/InstPrinter/Makefile
index 63e38ef..74872a4 100644
--- a/lib/Target/Mips/InstPrinter/Makefile
+++ b/lib/Target/Mips/InstPrinter/Makefile
@@ -10,7 +10,7 @@
LEVEL = ../../../..
LIBRARYNAME = LLVMMipsAsmPrinter
-# Hack: we need to include 'main' arm target directory to grab private headers
+# Hack: we need to include 'main' mips target directory to grab private headers
CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
include $(LEVEL)/Makefile.common
diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
index 41c1dd3..3dafc61 100644
--- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
+++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
@@ -1,4 +1,4 @@
-//===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax --------===//
+//===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax ------===//
//
// The LLVM Compiler Infrastructure
//
@@ -69,8 +69,10 @@ void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
OS << '$' << LowercaseString(getRegisterName(RegNo));
}
-void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
+void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
+ StringRef Annot) {
printInstruction(MI, O);
+ printAnnotation(O, Annot);
}
void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h
index 680208e..5c11165 100644
--- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h
+++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h
@@ -1,4 +1,4 @@
-//===-- MipsInstPrinter.h - Convert Mips MCInst to assembly syntax ----------===//
+//===-- MipsInstPrinter.h - Convert Mips MCInst to assembly syntax --------===//
//
// The LLVM Compiler Infrastructure
//
@@ -86,7 +86,7 @@ public:
virtual StringRef getOpcodeName(unsigned Opcode) const;
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
- virtual void printInst(const MCInst *MI, raw_ostream &O);
+ virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
private:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
diff --git a/lib/Target/Mips/MCTargetDesc/CMakeLists.txt b/lib/Target/Mips/MCTargetDesc/CMakeLists.txt
index 97de75d..2ceb5c9 100644
--- a/lib/Target/Mips/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/Mips/MCTargetDesc/CMakeLists.txt
@@ -1,4 +1,15 @@
add_llvm_library(LLVMMipsDesc
- MipsMCTargetDesc.cpp
+ MipsAsmBackend.cpp
MipsMCAsmInfo.cpp
+ MipsMCCodeEmitter.cpp
+ MipsMCTargetDesc.cpp
+ )
+
+add_llvm_library_dependencies(LLVMMipsDesc
+ LLVMMC
+ LLVMMipsAsmPrinter
+ LLVMMipsInfo
+ LLVMSupport
)
+
+add_dependencies(LLVMMipsDesc MipsCommonTableGen)
diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
new file mode 100644
index 0000000..f190ec4
--- /dev/null
+++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -0,0 +1,117 @@
+#include "MCTargetDesc/MipsMCTargetDesc.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCMachObjectWriter.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Object/MachOFormat.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+namespace {
+class MipsELFObjectWriter : public MCELFObjectTargetWriter {
+public:
+ MipsELFObjectWriter(bool is64Bit, Triple::OSType OSType, uint16_t EMachine,
+ bool HasRelocationAddend)
+ : MCELFObjectTargetWriter(is64Bit, OSType, EMachine,
+ HasRelocationAddend) {}
+};
+
+class MipsAsmBackend : public MCAsmBackend {
+public:
+ MipsAsmBackend(const Target &T)
+ : MCAsmBackend() {}
+
+ unsigned getNumFixupKinds() const {
+ return 1; //tbd
+ }
+
+ /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided
+ /// data fragment, at the offset specified by the fixup and following the
+ /// fixup kind as appropriate.
+ void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
+ uint64_t Value) const {
+ }
+
+ /// @name Target Relaxation Interfaces
+ /// @{
+
+ /// MayNeedRelaxation - Check whether the given instruction may need
+ /// relaxation.
+ ///
+ /// \param Inst - The instruction to test.
+ bool MayNeedRelaxation(const MCInst &Inst) const {
+ return false;
+ }
+
+ /// RelaxInstruction - Relax the instruction in the given fragment to the next
+ /// wider instruction.
+ ///
+ /// \param Inst - The instruction to relax, which may be the same as the
+ /// output.
+ /// \parm Res [output] - On return, the relaxed instruction.
+ void RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
+ }
+
+ /// @}
+
+ /// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given
+ /// output. If the target cannot generate such a sequence, it should return an
+ /// error.
+ ///
+ /// \return - True on success.
+ bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
+ return false;
+ }
+};
+
+class MipsEB_AsmBackend : public MipsAsmBackend {
+public:
+ Triple::OSType OSType;
+
+ MipsEB_AsmBackend(const Target &T, Triple::OSType _OSType)
+ : MipsAsmBackend(T), OSType(_OSType) {}
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ return createELFObjectWriter(createELFObjectTargetWriter(),
+ OS, /*IsLittleEndian*/ false);
+ }
+
+ MCELFObjectTargetWriter *createELFObjectTargetWriter() const {
+ return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false);
+ }
+};
+
+class MipsEL_AsmBackend : public MipsAsmBackend {
+public:
+ Triple::OSType OSType;
+
+ MipsEL_AsmBackend(const Target &T, Triple::OSType _OSType)
+ : MipsAsmBackend(T), OSType(_OSType) {}
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ return createELFObjectWriter(createELFObjectTargetWriter(),
+ OS, /*IsLittleEndian*/ true);
+ }
+
+ MCELFObjectTargetWriter *createELFObjectTargetWriter() const {
+ return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false);
+ }
+};
+}
+
+MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, StringRef TT) {
+ Triple TheTriple(TT);
+
+ // just return little endian for now
+ //
+ return new MipsEL_AsmBackend(T, Triple(TT).getOS());
+}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
new file mode 100644
index 0000000..f7a6fa9
--- /dev/null
+++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
@@ -0,0 +1,113 @@
+//===-- MipsBaseInfo.h - Top level definitions for ARM ------- --*- 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 small standalone helper functions and enum definitions for
+// the Mips target useful for the compiler back-end and the MC libraries.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MIPSBASEINFO_H
+#define MIPSBASEINFO_H
+
+#include "MipsMCTargetDesc.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace llvm {
+/// getMipsRegisterNumbering - Given the enum value for some register,
+/// return the number that it corresponds to.
+inline static unsigned getMipsRegisterNumbering(unsigned RegEnum)
+{
+ switch (RegEnum) {
+ case Mips::ZERO: case Mips::ZERO_64: case Mips::F0: case Mips::D0_64:
+ case Mips::D0:
+ return 0;
+ case Mips::AT: case Mips::AT_64: case Mips::F1: case Mips::D1_64:
+ return 1;
+ case Mips::V0: case Mips::V0_64: case Mips::F2: case Mips::D2_64:
+ case Mips::D1:
+ return 2;
+ case Mips::V1: case Mips::V1_64: case Mips::F3: case Mips::D3_64:
+ return 3;
+ case Mips::A0: case Mips::A0_64: case Mips::F4: case Mips::D4_64:
+ case Mips::D2:
+ return 4;
+ case Mips::A1: case Mips::A1_64: case Mips::F5: case Mips::D5_64:
+ return 5;
+ case Mips::A2: case Mips::A2_64: case Mips::F6: case Mips::D6_64:
+ case Mips::D3:
+ return 6;
+ case Mips::A3: case Mips::A3_64: case Mips::F7: case Mips::D7_64:
+ return 7;
+ case Mips::T0: case Mips::T0_64: case Mips::F8: case Mips::D8_64:
+ case Mips::D4:
+ return 8;
+ case Mips::T1: case Mips::T1_64: case Mips::F9: case Mips::D9_64:
+ return 9;
+ case Mips::T2: case Mips::T2_64: case Mips::F10: case Mips::D10_64:
+ case Mips::D5:
+ return 10;
+ case Mips::T3: case Mips::T3_64: case Mips::F11: case Mips::D11_64:
+ return 11;
+ case Mips::T4: case Mips::T4_64: case Mips::F12: case Mips::D12_64:
+ case Mips::D6:
+ return 12;
+ case Mips::T5: case Mips::T5_64: case Mips::F13: case Mips::D13_64:
+ return 13;
+ case Mips::T6: case Mips::T6_64: case Mips::F14: case Mips::D14_64:
+ case Mips::D7:
+ return 14;
+ case Mips::T7: case Mips::T7_64: case Mips::F15: case Mips::D15_64:
+ return 15;
+ case Mips::S0: case Mips::S0_64: case Mips::F16: case Mips::D16_64:
+ case Mips::D8:
+ return 16;
+ case Mips::S1: case Mips::S1_64: case Mips::F17: case Mips::D17_64:
+ return 17;
+ case Mips::S2: case Mips::S2_64: case Mips::F18: case Mips::D18_64:
+ case Mips::D9:
+ return 18;
+ case Mips::S3: case Mips::S3_64: case Mips::F19: case Mips::D19_64:
+ return 19;
+ case Mips::S4: case Mips::S4_64: case Mips::F20: case Mips::D20_64:
+ case Mips::D10:
+ return 20;
+ case Mips::S5: case Mips::S5_64: case Mips::F21: case Mips::D21_64:
+ return 21;
+ case Mips::S6: case Mips::S6_64: case Mips::F22: case Mips::D22_64:
+ case Mips::D11:
+ return 22;
+ case Mips::S7: case Mips::S7_64: case Mips::F23: case Mips::D23_64:
+ return 23;
+ case Mips::T8: case Mips::T8_64: case Mips::F24: case Mips::D24_64:
+ case Mips::D12:
+ return 24;
+ case Mips::T9: case Mips::T9_64: case Mips::F25: case Mips::D25_64:
+ return 25;
+ case Mips::K0: case Mips::K0_64: case Mips::F26: case Mips::D26_64:
+ case Mips::D13:
+ return 26;
+ case Mips::K1: case Mips::K1_64: case Mips::F27: case Mips::D27_64:
+ return 27;
+ case Mips::GP: case Mips::GP_64: case Mips::F28: case Mips::D28_64:
+ case Mips::D14:
+ return 28;
+ case Mips::SP: case Mips::SP_64: case Mips::F29: case Mips::D29_64:
+ return 29;
+ case Mips::FP: case Mips::FP_64: case Mips::F30: case Mips::D30_64:
+ case Mips::D15:
+ return 30;
+ case Mips::RA: case Mips::RA_64: case Mips::F31: case Mips::D31_64:
+ return 31;
+ default: llvm_unreachable("Unknown register number!");
+ }
+ return 0; // Not reached
+}
+}
+
+#endif
diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
new file mode 100644
index 0000000..8b099ea
--- /dev/null
+++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
@@ -0,0 +1,90 @@
+#ifndef LLVM_Mips_MipsFIXUPKINDS_H
+#define LLVM_Mips_MipsFIXUPKINDS_H
+
+//===-- Mips/MipsFixupKinds.h - Mips Specific Fixup Entries --------*- 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/MCFixup.h"
+
+namespace llvm {
+namespace Mips {
+ enum Fixups {
+ // fixup_Mips_xxx - R_MIPS_NONE
+ fixup_Mips_NONE = FirstTargetFixupKind,
+
+ // fixup_Mips_xxx - R_MIPS_16.
+ fixup_Mips_16,
+
+ // fixup_Mips_xxx - R_MIPS_32.
+ fixup_Mips_32,
+
+ // fixup_Mips_xxx - R_MIPS_REL32.
+ fixup_Mips_REL32,
+
+ // fixup_Mips_xxx - R_MIPS_26.
+ fixup_Mips_26,
+
+ // fixup_Mips_xxx - R_MIPS_HI16.
+ fixup_Mips_HI16,
+
+ // fixup_Mips_xxx - R_MIPS_LO16.
+ fixup_Mips_LO16,
+
+ // fixup_Mips_xxx - R_MIPS_GPREL16.
+ fixup_Mips_GPREL16,
+
+ // fixup_Mips_xxx - R_MIPS_LITERAL.
+ fixup_Mips_LITERAL,
+
+ // fixup_Mips_xxx - R_MIPS_GOT16.
+ fixup_Mips_GOT16,
+
+ // fixup_Mips_xxx - R_MIPS_PC16.
+ fixup_Mips_PC16,
+
+ // fixup_Mips_xxx - R_MIPS_CALL16.
+ fixup_Mips_CALL16,
+
+ // fixup_Mips_xxx - R_MIPS_GPREL32.
+ fixup_Mips_GPREL32,
+
+ // fixup_Mips_xxx - R_MIPS_SHIFT5.
+ fixup_Mips_SHIFT5,
+
+ // fixup_Mips_xxx - R_MIPS_SHIFT6.
+ fixup_Mips_SHIFT6,
+
+ // fixup_Mips_xxx - R_MIPS_64.
+ fixup_Mips_64,
+
+ // fixup_Mips_xxx - R_MIPS_TLS_GD.
+ fixup_Mips_TLSGD,
+
+ // fixup_Mips_xxx - R_MIPS_TLS_GOTTPREL.
+ fixup_Mips_GOTTPREL,
+
+ // fixup_Mips_xxx - R_MIPS_TLS_TPREL_HI16.
+ fixup_Mips_TPREL_HI,
+
+ // fixup_Mips_xxx - R_MIPS_TLS_TPREL_LO16.
+ fixup_Mips_TPREL_LO,
+
+ // fixup_Mips_xxx - yyy. // This should become R_MIPS_PC16
+ fixup_Mips_Branch_PCRel,
+
+ // Marker
+ LastTargetFixupKind,
+ NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
+ };
+} // namespace llvm
+} // namespace Mips
+
+
+#endif /* LLVM_Mips_MipsFIXUPKINDS_H */
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
index 5d92425..71ae804 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
@@ -18,7 +18,8 @@ using namespace llvm;
MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, StringRef TT) {
Triple TheTriple(TT);
- if (TheTriple.getArch() == Triple::mips)
+ if ((TheTriple.getArch() == Triple::mips) ||
+ (TheTriple.getArch() == Triple::mips64))
IsLittleEndian = false;
AlignmentIsInBytes = false;
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
new file mode 100644
index 0000000..d66de23
--- /dev/null
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
@@ -0,0 +1,52 @@
+//===-- MipsMCCodeEmitter.cpp - Convert Mips code to machine code ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the MipsMCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+//
+#define DEBUG_TYPE "mccodeemitter"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "MCTargetDesc/MipsMCTargetDesc.h"
+
+using namespace llvm;
+
+namespace {
+class MipsMCCodeEmitter : public MCCodeEmitter {
+ MipsMCCodeEmitter(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT
+ void operator=(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT
+ const MCInstrInfo &MCII;
+ const MCSubtargetInfo &STI;
+
+public:
+ MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
+ MCContext &ctx)
+ : MCII(mcii), STI(sti) {}
+
+ ~MipsMCCodeEmitter() {}
+
+ void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ }
+}; // class MipsMCCodeEmitter
+} // namespace
+
+MCCodeEmitter *llvm::createMipsMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new MipsMCCodeEmitter(MCII, STI, Ctx);
+}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
index 06f0d0b..1f9e3dd 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
@@ -13,10 +13,14 @@
#include "MipsMCTargetDesc.h"
#include "MipsMCAsmInfo.h"
+#include "InstPrinter/MipsInstPrinter.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_MC_DESC
#include "MipsGenInstrInfo.inc"
@@ -35,11 +39,12 @@ static MCInstrInfo *createMipsMCInstrInfo() {
return X;
}
-extern "C" void LLVMInitializeMipsMCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(TheMipsTarget, createMipsMCInstrInfo);
+static MCRegisterInfo *createMipsMCRegisterInfo(StringRef TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitMipsMCRegisterInfo(X, Mips::RA);
+ return X;
}
-
static MCSubtargetInfo *createMipsMCSubtargetInfo(StringRef TT, StringRef CPU,
StringRef FS) {
MCSubtargetInfo *X = new MCSubtargetInfo();
@@ -47,12 +52,111 @@ static MCSubtargetInfo *createMipsMCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-extern "C" void LLVMInitializeMipsMCSubtargetInfo() {
+static MCAsmInfo *createMipsMCAsmInfo(const Target &T, StringRef TT) {
+ MCAsmInfo *MAI = new MipsMCAsmInfo(T, TT);
+
+ MachineLocation Dst(MachineLocation::VirtualFP);
+ MachineLocation Src(Mips::SP, 0);
+ MAI->addInitialFrameState(0, Dst, Src);
+
+ return MAI;
+}
+
+static MCCodeGenInfo *createMipsMCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+ if (RM == Reloc::Default)
+ RM = Reloc::PIC_;
+ X->InitMCCodeGenInfo(RM, CM);
+ return X;
+}
+
+static MCInstPrinter *createMipsMCInstPrinter(const Target &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI) {
+ return new MipsInstPrinter(MAI);
+}
+
+static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
+ MCContext &Ctx, MCAsmBackend &MAB,
+ raw_ostream &_OS,
+ MCCodeEmitter *_Emitter,
+ bool RelaxAll,
+ bool NoExecStack) {
+ Triple TheTriple(TT);
+
+ return createELFStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll, NoExecStack);
+}
+
+extern "C" void LLVMInitializeMipsTargetMC() {
+ // Register the MC asm info.
+ RegisterMCAsmInfoFn X(TheMipsTarget, createMipsMCAsmInfo);
+ RegisterMCAsmInfoFn Y(TheMipselTarget, createMipsMCAsmInfo);
+ RegisterMCAsmInfoFn A(TheMips64Target, createMipsMCAsmInfo);
+ RegisterMCAsmInfoFn B(TheMips64elTarget, createMipsMCAsmInfo);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(TheMipsTarget,
+ createMipsMCCodeGenInfo);
+ TargetRegistry::RegisterMCCodeGenInfo(TheMipselTarget,
+ createMipsMCCodeGenInfo);
+ TargetRegistry::RegisterMCCodeGenInfo(TheMips64Target,
+ createMipsMCCodeGenInfo);
+ TargetRegistry::RegisterMCCodeGenInfo(TheMips64elTarget,
+ createMipsMCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheMipsTarget, createMipsMCInstrInfo);
+ TargetRegistry::RegisterMCInstrInfo(TheMipselTarget, createMipsMCInstrInfo);
+ TargetRegistry::RegisterMCInstrInfo(TheMips64Target, createMipsMCInstrInfo);
+ TargetRegistry::RegisterMCInstrInfo(TheMips64elTarget, createMipsMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheMipsTarget, createMipsMCRegisterInfo);
+ TargetRegistry::RegisterMCRegInfo(TheMipselTarget, createMipsMCRegisterInfo);
+ TargetRegistry::RegisterMCRegInfo(TheMips64Target, createMipsMCRegisterInfo);
+ TargetRegistry::RegisterMCRegInfo(TheMips64elTarget,
+ createMipsMCRegisterInfo);
+
+ // Register the MC Code Emitter
+ TargetRegistry::RegisterMCCodeEmitter(TheMipsTarget, createMipsMCCodeEmitter);
+ TargetRegistry::RegisterMCCodeEmitter(TheMipselTarget,
+ createMipsMCCodeEmitter);
+ TargetRegistry::RegisterMCCodeEmitter(TheMips64Target,
+ createMipsMCCodeEmitter);
+ TargetRegistry::RegisterMCCodeEmitter(TheMips64elTarget,
+ createMipsMCCodeEmitter);
+
+ // Register the object streamer.
+ TargetRegistry::RegisterMCObjectStreamer(TheMipsTarget, createMCStreamer);
+ TargetRegistry::RegisterMCObjectStreamer(TheMipselTarget, createMCStreamer);
+ TargetRegistry::RegisterMCObjectStreamer(TheMips64Target, createMCStreamer);
+ TargetRegistry::RegisterMCObjectStreamer(TheMips64elTarget, createMCStreamer);
+
+ // Register the asm backend.
+ TargetRegistry::RegisterMCAsmBackend(TheMipsTarget, createMipsAsmBackend);
+ TargetRegistry::RegisterMCAsmBackend(TheMipselTarget, createMipsAsmBackend);
+ TargetRegistry::RegisterMCAsmBackend(TheMips64Target, createMipsAsmBackend);
+ TargetRegistry::RegisterMCAsmBackend(TheMips64elTarget, createMipsAsmBackend);
+
+ // Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(TheMipsTarget,
createMipsMCSubtargetInfo);
-}
+ TargetRegistry::RegisterMCSubtargetInfo(TheMipselTarget,
+ createMipsMCSubtargetInfo);
+ TargetRegistry::RegisterMCSubtargetInfo(TheMips64Target,
+ createMipsMCSubtargetInfo);
+ TargetRegistry::RegisterMCSubtargetInfo(TheMips64elTarget,
+ createMipsMCSubtargetInfo);
-extern "C" void LLVMInitializeMipsMCAsmInfo() {
- RegisterMCAsmInfo<MipsMCAsmInfo> X(TheMipsTarget);
- RegisterMCAsmInfo<MipsMCAsmInfo> Y(TheMipselTarget);
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(TheMipsTarget,
+ createMipsMCInstPrinter);
+ TargetRegistry::RegisterMCInstPrinter(TheMipselTarget,
+ createMipsMCInstPrinter);
+ TargetRegistry::RegisterMCInstPrinter(TheMips64Target,
+ createMipsMCInstPrinter);
+ TargetRegistry::RegisterMCInstPrinter(TheMips64elTarget,
+ createMipsMCInstPrinter);
}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
index 3d18f11..7a0042a 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
@@ -1,4 +1,4 @@
-//===-- AlphaMCTargetDesc.h - Alpha Target Descriptions ---------*- C++ -*-===//
+//===-- MipsMCTargetDesc.h - Mips Target Descriptions -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,21 +7,32 @@
//
//===----------------------------------------------------------------------===//
//
-// This file provides Alpha specific target descriptions.
+// This file provides Mips specific target descriptions.
//
//===----------------------------------------------------------------------===//
-#ifndef ALPHAMCTARGETDESC_H
-#define ALPHAMCTARGETDESC_H
+#ifndef MIPSMCTARGETDESC_H
+#define MIPSMCTARGETDESC_H
namespace llvm {
+class MCAsmBackend;
+class MCInstrInfo;
+class MCCodeEmitter;
+class MCContext;
class MCSubtargetInfo;
-class Target;
class StringRef;
+class Target;
extern Target TheMipsTarget;
extern Target TheMipselTarget;
+extern Target TheMips64Target;
+extern Target TheMips64elTarget;
+
+MCCodeEmitter *createMipsMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx);
+MCAsmBackend *createMipsAsmBackend(const Target &T, StringRef TT);
} // End llvm namespace
// Defines symbolic names for Mips registers. This defines a mapping from
diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h
index 984b5ad..bacecf2 100644
--- a/lib/Target/Mips/Mips.h
+++ b/lib/Target/Mips/Mips.h
@@ -29,6 +29,9 @@ namespace llvm {
FunctionPass *createMipsExpandPseudoPass(MipsTargetMachine &TM);
FunctionPass *createMipsEmitGPRestorePass(MipsTargetMachine &TM);
+ FunctionPass *createMipsJITCodeEmitterPass(MipsTargetMachine &TM,
+ JITCodeEmitter &JCE);
+
} // end namespace llvm;
#endif
diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td
index 433cd57..39c2c16 100644
--- a/lib/Target/Mips/Mips.td
+++ b/lib/Target/Mips/Mips.td
@@ -38,6 +38,10 @@ def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat",
"true", "Only supports single precision float">;
def FeatureO32 : SubtargetFeature<"o32", "MipsABI", "O32",
"Enable o32 ABI">;
+def FeatureN32 : SubtargetFeature<"n32", "MipsABI", "N32",
+ "Enable n32 ABI">;
+def FeatureN64 : SubtargetFeature<"n64", "MipsABI", "N64",
+ "Enable n64 ABI">;
def FeatureEABI : SubtargetFeature<"eabi", "MipsABI", "EABI",
"Enable eabi ABI">;
def FeatureVFPU : SubtargetFeature<"vfpu", "HasVFPU",
@@ -54,16 +58,19 @@ def FeatureSwap : SubtargetFeature<"swap", "HasSwap", "true",
"Enable 'byte/half swap' instructions.">;
def FeatureBitCount : SubtargetFeature<"bitcount", "HasBitCount", "true",
"Enable 'count leading bits' instructions.">;
-def FeatureMips1 : SubtargetFeature<"mips1", "MipsArchVersion", "Mips1",
- "Mips1 ISA Support">;
-def FeatureMips2 : SubtargetFeature<"mips2", "MipsArchVersion", "Mips2",
- "Mips2 ISA Support">;
def FeatureMips32 : SubtargetFeature<"mips32", "MipsArchVersion", "Mips32",
"Mips32 ISA Support",
[FeatureCondMov, FeatureBitCount]>;
def FeatureMips32r2 : SubtargetFeature<"mips32r2", "MipsArchVersion",
"Mips32r2", "Mips32r2 ISA Support",
[FeatureMips32, FeatureSEInReg]>;
+def FeatureMips64 : SubtargetFeature<"mips64", "MipsArchVersion",
+ "Mips64", "Mips64 ISA Support",
+ [FeatureGP64Bit, FeatureFP64Bit,
+ FeatureMips32]>;
+def FeatureMips64r2 : SubtargetFeature<"mips64r2", "MipsArchVersion",
+ "Mips64r2", "Mips64r2 ISA Support",
+ [FeatureMips64, FeatureMips32r2]>;
//===----------------------------------------------------------------------===//
// Mips processors supported.
@@ -72,21 +79,10 @@ def FeatureMips32r2 : SubtargetFeature<"mips32r2", "MipsArchVersion",
class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, MipsGenericItineraries, Features>;
-def : Proc<"mips1", [FeatureMips1]>;
-def : Proc<"r2000", [FeatureMips1]>;
-def : Proc<"r3000", [FeatureMips1]>;
-
-def : Proc<"mips2", [FeatureMips2]>;
-def : Proc<"r6000", [FeatureMips2]>;
-
+def : Proc<"mips32r1", [FeatureMips32]>;
def : Proc<"4ke", [FeatureMips32r2]>;
-
-// Allegrex is a 32bit subset of r4000, both for integer and fp registers,
-// but much more similar to Mips2 than Mips3. It also contains some of
-// Mips32/Mips32r2 instructions and a custom vector fpu processor.
-def : Proc<"allegrex", [FeatureMips2, FeatureSingleFloat, FeatureEABI,
- FeatureVFPU, FeatureSEInReg, FeatureCondMov, FeatureMulDivAdd,
- FeatureMinMax, FeatureSwap, FeatureBitCount]>;
+def : Proc<"mips64r1", [FeatureMips64]>;
+def : Proc<"mips64r2", [FeatureMips64r2]>;
def MipsAsmWriter : AsmWriter {
string AsmWriterClassName = "InstPrinter";
diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td
new file mode 100644
index 0000000..49b0223
--- /dev/null
+++ b/lib/Target/Mips/Mips64InstrInfo.td
@@ -0,0 +1,214 @@
+//===- Mips64InstrInfo.td - Mips64 Instruction Information -*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes Mips64 instructions.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Mips Operand, Complex Patterns and Transformations Definitions.
+//===----------------------------------------------------------------------===//
+
+// Instruction operand types
+def shamt_64 : Operand<i64>;
+
+// Unsigned Operand
+def uimm16_64 : Operand<i64> {
+ let PrintMethod = "printUnsignedImm";
+}
+
+// Transformation Function - get Imm - 32.
+def Subtract32 : SDNodeXForm<imm, [{
+ return getI32Imm((unsigned)N->getZExtValue() - 32);
+}]>;
+
+// imm32_63 predicate - True if imm is in range [32, 63].
+def imm32_63 : ImmLeaf<i64,
+ [{return (int32_t)Imm >= 32 && (int32_t)Imm < 64;}],
+ Subtract32>;
+
+//===----------------------------------------------------------------------===//
+// Instructions specific format
+//===----------------------------------------------------------------------===//
+// Shifts
+class LogicR_shift_rotate_imm64<bits<6> func, bits<5> _rs, string instr_asm,
+ SDNode OpNode, PatFrag PF>:
+ FR<0x00, func, (outs CPU64Regs:$dst), (ins CPU64Regs:$b, shamt_64:$c),
+ !strconcat(instr_asm, "\t$dst, $b, $c"),
+ [(set CPU64Regs:$dst, (OpNode CPU64Regs:$b, (i64 PF:$c)))],
+ IIAlu> {
+ let rs = _rs;
+}
+
+class LogicR_shift_rotate_reg64<bits<6> func, bits<5> _shamt, string instr_asm,
+ SDNode OpNode>:
+ FR<0x00, func, (outs CPU64Regs:$dst), (ins CPU64Regs:$c, CPU64Regs:$b),
+ !strconcat(instr_asm, "\t$dst, $b, $c"),
+ [(set CPU64Regs:$dst, (OpNode CPU64Regs:$b, CPU64Regs:$c))], IIAlu> {
+ let shamt = _shamt;
+}
+
+// Mul, Div
+let Defs = [HI64, LO64] in {
+ let isCommutable = 1 in
+ class Mul64<bits<6> func, string instr_asm, InstrItinClass itin>:
+ FR<0x00, func, (outs), (ins CPU64Regs:$a, CPU64Regs:$b),
+ !strconcat(instr_asm, "\t$a, $b"), [], itin>;
+
+ class Div64<SDNode op, bits<6> func, string instr_asm, InstrItinClass itin>:
+ FR<0x00, func, (outs), (ins CPU64Regs:$a, CPU64Regs:$b),
+ !strconcat(instr_asm, "\t$$zero, $a, $b"),
+ [(op CPU64Regs:$a, CPU64Regs:$b)], itin>;
+}
+
+// Move from Hi/Lo
+let shamt = 0 in {
+let rs = 0, rt = 0 in
+class MoveFromLOHI64<bits<6> func, string instr_asm>:
+ FR<0x00, func, (outs CPU64Regs:$dst), (ins),
+ !strconcat(instr_asm, "\t$dst"), [], IIHiLo>;
+
+let rt = 0, rd = 0 in
+class MoveToLOHI64<bits<6> func, string instr_asm>:
+ FR<0x00, func, (outs), (ins CPU64Regs:$src),
+ !strconcat(instr_asm, "\t$src"), [], IIHiLo>;
+}
+
+// Count Leading Ones/Zeros in Word
+class CountLeading64<bits<6> func, string instr_asm, list<dag> pattern>:
+ FR<0x1c, func, (outs CPU64Regs:$dst), (ins CPU64Regs:$src),
+ !strconcat(instr_asm, "\t$dst, $src"), pattern, IIAlu>,
+ Requires<[HasBitCount]> {
+ let shamt = 0;
+ let rt = rd;
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction definition
+//===----------------------------------------------------------------------===//
+
+/// Arithmetic Instructions (ALU Immediate)
+def DADDiu : ArithLogicI<0x19, "daddiu", add, simm16_64, immSExt16,
+ CPU64Regs>;
+def DANDi : ArithLogicI<0x0c, "andi", and, uimm16_64, immZExt16, CPU64Regs>;
+def SLTi64 : SetCC_I<0x0a, "slti", setlt, simm16_64, immSExt16, CPU64Regs>;
+def SLTiu64 : SetCC_I<0x0b, "sltiu", setult, simm16_64, immSExt16, CPU64Regs>;
+def ORi64 : ArithLogicI<0x0d, "ori", or, uimm16_64, immZExt16, CPU64Regs>;
+def XORi64 : ArithLogicI<0x0e, "xori", xor, uimm16_64, immZExt16, CPU64Regs>;
+
+/// Arithmetic Instructions (3-Operand, R-Type)
+def DADDu : ArithLogicR<0x00, 0x2d, "daddu", add, IIAlu, CPU64Regs, 1>;
+def DSUBu : ArithLogicR<0x00, 0x2f, "dsubu", sub, IIAlu, CPU64Regs>;
+def SLT64 : SetCC_R<0x00, 0x2a, "slt", setlt, CPU64Regs>;
+def SLTu64 : SetCC_R<0x00, 0x2b, "sltu", setult, CPU64Regs>;
+def AND64 : ArithLogicR<0x00, 0x24, "and", and, IIAlu, CPU64Regs, 1>;
+def OR64 : ArithLogicR<0x00, 0x25, "or", or, IIAlu, CPU64Regs, 1>;
+def XOR64 : ArithLogicR<0x00, 0x26, "xor", xor, IIAlu, CPU64Regs, 1>;
+def NOR64 : LogicNOR<0x00, 0x27, "nor", CPU64Regs>;
+
+/// Shift Instructions
+def DSLL : LogicR_shift_rotate_imm64<0x38, 0x00, "dsll", shl, immZExt5>;
+def DSRL : LogicR_shift_rotate_imm64<0x3a, 0x00, "dsrl", srl, immZExt5>;
+def DSRA : LogicR_shift_rotate_imm64<0x3b, 0x00, "dsra", sra, immZExt5>;
+def DSLL32 : LogicR_shift_rotate_imm64<0x3c, 0x00, "dsll32", shl, imm32_63>;
+def DSRL32 : LogicR_shift_rotate_imm64<0x3e, 0x00, "dsrl32", srl, imm32_63>;
+def DSRA32 : LogicR_shift_rotate_imm64<0x3f, 0x00, "dsra32", sra, imm32_63>;
+def DSLLV : LogicR_shift_rotate_reg64<0x24, 0x00, "dsllv", shl>;
+def DSRLV : LogicR_shift_rotate_reg64<0x26, 0x00, "dsrlv", srl>;
+def DSRAV : LogicR_shift_rotate_reg64<0x27, 0x00, "dsrav", sra>;
+
+// Rotate Instructions
+let Predicates = [HasMips64r2] in {
+ def DROTR : LogicR_shift_rotate_imm64<0x3a, 0x01, "drotr", rotr, immZExt5>;
+ def DROTR32 : LogicR_shift_rotate_imm64<0x3e, 0x01, "drotr32", rotr,
+ imm32_63>;
+ def DROTRV : LogicR_shift_rotate_reg64<0x16, 0x01, "drotrv", rotr>;
+}
+
+/// Load and Store Instructions
+/// aligned
+defm LB64 : LoadM64<0x20, "lb", sextloadi8>;
+defm LBu64 : LoadM64<0x24, "lbu", zextloadi8>;
+defm LH64 : LoadM64<0x21, "lh", sextloadi16_a>;
+defm LHu64 : LoadM64<0x25, "lhu", zextloadi16_a>;
+defm LW64 : LoadM64<0x23, "lw", sextloadi32_a>;
+defm LWu64 : LoadM64<0x27, "lwu", zextloadi32_a>;
+defm SB64 : StoreM64<0x28, "sb", truncstorei8>;
+defm SH64 : StoreM64<0x29, "sh", truncstorei16_a>;
+defm SW64 : StoreM64<0x2b, "sw", truncstorei32_a>;
+defm LD : LoadM64<0x37, "ld", load_a>;
+defm SD : StoreM64<0x3f, "sd", store_a>;
+
+/// unaligned
+defm ULH64 : LoadM64<0x21, "ulh", sextloadi16_u, 1>;
+defm ULHu64 : LoadM64<0x25, "ulhu", zextloadi16_u, 1>;
+defm ULW64 : LoadM64<0x23, "ulw", sextloadi32_u, 1>;
+defm USH64 : StoreM64<0x29, "ush", truncstorei16_u, 1>;
+defm USW64 : StoreM64<0x2b, "usw", truncstorei32_u, 1>;
+defm ULD : LoadM64<0x37, "uld", load_u, 1>;
+defm USD : StoreM64<0x3f, "usd", store_u, 1>;
+
+/// Jump and Branch Instructions
+def BEQ64 : CBranch<0x04, "beq", seteq, CPU64Regs>;
+def BNE64 : CBranch<0x05, "bne", setne, CPU64Regs>;
+def BGEZ64 : CBranchZero<0x01, 1, "bgez", setge, CPU64Regs>;
+def BGTZ64 : CBranchZero<0x07, 0, "bgtz", setgt, CPU64Regs>;
+def BLEZ64 : CBranchZero<0x07, 0, "blez", setle, CPU64Regs>;
+def BLTZ64 : CBranchZero<0x01, 0, "bltz", setlt, CPU64Regs>;
+
+/// Multiply and Divide Instructions.
+def DMULT : Mul64<0x1c, "dmult", IIImul>;
+def DMULTu : Mul64<0x1d, "dmultu", IIImul>;
+def DSDIV : Div64<MipsDivRem, 0x1e, "ddiv", IIIdiv>;
+def DUDIV : Div64<MipsDivRemU, 0x1f, "ddivu", IIIdiv>;
+
+let Defs = [HI64] in
+ def MTHI64 : MoveToLOHI64<0x11, "mthi">;
+let Defs = [LO64] in
+ def MTLO64 : MoveToLOHI64<0x13, "mtlo">;
+
+let Uses = [HI64] in
+ def MFHI64 : MoveFromLOHI64<0x10, "mfhi">;
+let Uses = [LO64] in
+ def MFLO64 : MoveFromLOHI64<0x12, "mflo">;
+
+/// Count Leading
+def DCLZ : CountLeading64<0x24, "dclz",
+ [(set CPU64Regs:$dst, (ctlz CPU64Regs:$src))]>;
+def DCLO : CountLeading64<0x25, "dclo",
+ [(set CPU64Regs:$dst, (ctlz (not CPU64Regs:$src)))]>;
+
+//===----------------------------------------------------------------------===//
+// Arbitrary patterns that map to one or more instructions
+//===----------------------------------------------------------------------===//
+
+// Small immediates
+def : Pat<(i64 immSExt16:$in),
+ (DADDiu ZERO_64, imm:$in)>;
+def : Pat<(i64 immZExt16:$in),
+ (ORi64 ZERO_64, imm:$in)>;
+
+// zextloadi32_u
+def : Pat<(zextloadi32_u addr:$a), (DSRL (DSLL (ULW64_P8 addr:$a), 32), 32)>,
+ Requires<[IsN64]>;
+def : Pat<(zextloadi32_u addr:$a), (DSRL (DSLL (ULW64 addr:$a), 32), 32)>,
+ Requires<[NotN64]>;
+
+// hi/lo relocs
+def : Pat<(i64 (MipsLo tglobaladdr:$in)), (DADDiu ZERO_64, tglobaladdr:$in)>;
+
+defm : BrcondPats<CPU64Regs, BEQ64, BNE64, SLT64, SLTu64, SLTi64, SLTiu64,
+ ZERO_64>;
+
+// setcc patterns
+defm : SeteqPats<CPU64Regs, SLTiu64, XOR64, SLTu64, ZERO_64>;
+defm : SetlePats<CPU64Regs, SLT64, SLTu64>;
+defm : SetgtPats<CPU64Regs, SLT64, SLTu64>;
+defm : SetgePats<CPU64Regs, SLT64, SLTu64>;
+defm : SetgeImmPats<CPU64Regs, SLTi64, SLTiu64>;
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
index 69e03bd..0e82681 100644
--- a/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -18,6 +18,7 @@
#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
#include "MipsMCInstLower.h"
+#include "MipsMCSymbolRefExpr.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "llvm/BasicBlock.h"
#include "llvm/Instructions.h"
@@ -25,6 +26,7 @@
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInst.h"
@@ -33,15 +35,22 @@
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/DebugInfo.h"
using namespace llvm;
+static bool isUnalignedLoadStore(unsigned Opc) {
+ return Opc == Mips::ULW || Opc == Mips::ULH || Opc == Mips::ULHu ||
+ Opc == Mips::USW || Opc == Mips::USH ||
+ Opc == Mips::ULW_P8 || Opc == Mips::ULH_P8 || Opc == Mips::ULHu_P8 ||
+ Opc == Mips::USW_P8 || Opc == Mips::USH_P8;
+}
+
void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
SmallString<128> Str;
raw_svector_ostream OS(Str);
@@ -52,8 +61,21 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
MipsMCInstLower MCInstLowering(Mang, *MF, *this);
+ unsigned Opc = MI->getOpcode();
MCInst TmpInst0;
MCInstLowering.Lower(MI, TmpInst0);
+
+ // Enclose unaligned load or store with .macro & .nomacro directives.
+ if (isUnalignedLoadStore(Opc)) {
+ MCInst Directive;
+ Directive.setOpcode(Mips::MACRO);
+ OutStreamer.EmitInstruction(Directive);
+ OutStreamer.EmitInstruction(TmpInst0);
+ Directive.setOpcode(Mips::NOMACRO);
+ OutStreamer.EmitInstruction(Directive);
+ return;
+ }
+
OutStreamer.EmitInstruction(TmpInst0);
}
@@ -180,7 +202,6 @@ void MipsAsmPrinter::emitFrameDirective() {
const char *MipsAsmPrinter::getCurrentABIString() const {
switch (Subtarget->getTargetABI()) {
case MipsSubtarget::O32: return "abi32";
- case MipsSubtarget::O64: return "abiO64";
case MipsSubtarget::N32: return "abiN32";
case MipsSubtarget::N64: return "abi64";
case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64
@@ -304,6 +325,11 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
case MipsII::MO_GOTTPREL: O << "%gottprel("; break;
case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break;
case MipsII::MO_TPREL_LO: O << "%tprel_lo("; break;
+ case MipsII::MO_GPOFF_HI: O << "%hi(%neg(%gp_rel("; break;
+ case MipsII::MO_GPOFF_LO: O << "%lo(%neg(%gp_rel("; break;
+ case MipsII::MO_GOT_DISP: O << "%got_disp("; break;
+ case MipsII::MO_GOT_PAGE: O << "%got_page("; break;
+ case MipsII::MO_GOT_OFST: O << "%got_ofst("; break;
}
switch (MO.getType()) {
@@ -424,17 +450,9 @@ void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
}
// Force static initialization.
-static MCInstPrinter *createMipsMCInstPrinter(const Target &T,
- unsigned SyntaxVariant,
- const MCAsmInfo &MAI) {
- return new MipsInstPrinter(MAI);
-}
-
extern "C" void LLVMInitializeMipsAsmPrinter() {
RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget);
RegisterAsmPrinter<MipsAsmPrinter> Y(TheMipselTarget);
-
- TargetRegistry::RegisterMCInstPrinter(TheMipsTarget, createMipsMCInstPrinter);
- TargetRegistry::RegisterMCInstPrinter(TheMipselTarget,
- createMipsMCInstPrinter);
+ RegisterAsmPrinter<MipsAsmPrinter> A(TheMips64Target);
+ RegisterAsmPrinter<MipsAsmPrinter> B(TheMips64elTarget);
}
diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td
index 876f0fc..0ae4ef6 100644
--- a/lib/Target/Mips/MipsCallingConv.td
+++ b/lib/Target/Mips/MipsCallingConv.td
@@ -31,6 +31,55 @@ def RetCC_MipsO32 : CallingConv<[
]>;
//===----------------------------------------------------------------------===//
+// Mips N32/64 Calling Convention
+//===----------------------------------------------------------------------===//
+
+def CC_MipsN : CallingConv<[
+ // FIXME: Handle byval, complex and float double parameters.
+
+ // Promote i8/i16/i32 arguments to i64.
+ CCIfType<[i8, i16, i32], CCPromoteToType<i64>>,
+
+ // Integer arguments are passed in integer registers.
+ CCIfType<[i64], CCAssignToRegWithShadow<[A0_64, A1_64, A2_64, A3_64,
+ T0_64, T1_64, T2_64, T3_64],
+ [D12_64, D13_64, D14_64, D15_64,
+ D16_64, D17_64, D18_64, D19_64]>>,
+
+ // f32 arguments are passed in single precision FP registers.
+ CCIfType<[f32], CCAssignToRegWithShadow<[F12, F13, F14, F15,
+ F16, F17, F18, F19],
+ [A0_64, A1_64, A2_64, A3_64,
+ T0_64, T1_64, T2_64, T3_64]>>,
+
+ // f64 arguments are passed in double precision FP registers.
+ CCIfType<[f64], CCAssignToRegWithShadow<[D12_64, D13_64, D14_64, D15_64,
+ D16_64, D17_64, D18_64, D19_64],
+ [A0_64, A1_64, A2_64, A3_64,
+ T0_64, T1_64, T2_64, T3_64]>>,
+
+ // All stack parameter slots become 64-bit doublewords and are 8-byte aligned.
+ CCIfType<[i64, f64], CCAssignToStack<8, 8>>,
+ CCIfType<[f32], CCAssignToStack<4, 8>>
+]>;
+
+def RetCC_MipsN : CallingConv<[
+ // FIXME: Handle complex and float double return values.
+
+ // i32 are returned in registers V0, V1
+ CCIfType<[i32], CCAssignToReg<[V0, V1]>>,
+
+ // i64 are returned in registers V0_64, V1_64
+ CCIfType<[i64], CCAssignToReg<[V0_64, V1_64]>>,
+
+ // f32 are returned in registers F0, F2
+ CCIfType<[f32], CCAssignToReg<[F0, F2]>>,
+
+ // f64 are returned in registers D0, D2
+ CCIfType<[f64], CCAssignToReg<[D0_64, D2_64]>>
+]>;
+
+//===----------------------------------------------------------------------===//
// Mips EABI Calling Convention
//===----------------------------------------------------------------------===//
@@ -77,10 +126,14 @@ def RetCC_MipsEABI : CallingConv<[
//===----------------------------------------------------------------------===//
def CC_Mips : CallingConv<[
- CCIfSubtarget<"isABI_EABI()", CCDelegateTo<CC_MipsEABI>>
+ CCIfSubtarget<"isABI_EABI()", CCDelegateTo<CC_MipsEABI>>,
+ CCIfSubtarget<"isABI_N32()", CCDelegateTo<CC_MipsN>>,
+ CCIfSubtarget<"isABI_N64()", CCDelegateTo<CC_MipsN>>
]>;
def RetCC_Mips : CallingConv<[
CCIfSubtarget<"isABI_EABI()", CCDelegateTo<RetCC_MipsEABI>>,
+ CCIfSubtarget<"isABI_N32()", CCDelegateTo<RetCC_MipsN>>,
+ CCIfSubtarget<"isABI_N64()", CCDelegateTo<RetCC_MipsN>>,
CCDelegateTo<RetCC_MipsO32>
]>;
diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp
new file mode 100644
index 0000000..9220d9c
--- /dev/null
+++ b/lib/Target/Mips/MipsCodeEmitter.cpp
@@ -0,0 +1,245 @@
+//===-- Mips/MipsCodeEmitter.cpp - Convert Mips code to machine code -----===//
+//
+// 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 pass that transforms the Mips machine instructions
+// into relocatable machine code.
+//
+//===---------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "jit"
+#include "Mips.h"
+#include "MipsInstrInfo.h"
+#include "MipsRelocations.h"
+#include "MipsSubtarget.h"
+#include "MipsTargetMachine.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+#include "llvm/PassManager.h"
+#include "llvm/CodeGen/JITCodeEmitter.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#ifndef NDEBUG
+#include <iomanip>
+#endif
+
+#include "llvm/CodeGen/MachineOperand.h"
+
+using namespace llvm;
+
+STATISTIC(NumEmitted, "Number of machine instructions emitted");
+
+namespace {
+
+class MipsCodeEmitter : public MachineFunctionPass {
+ MipsJITInfo *JTI;
+ const MipsInstrInfo *II;
+ const TargetData *TD;
+ const MipsSubtarget *Subtarget;
+ TargetMachine &TM;
+ JITCodeEmitter &MCE;
+ const std::vector<MachineConstantPoolEntry> *MCPEs;
+ const std::vector<MachineJumpTableEntry> *MJTEs;
+ bool IsPIC;
+
+ void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<MachineModuleInfo> ();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ static char ID;
+
+ public:
+ MipsCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) :
+ MachineFunctionPass(ID), JTI(0),
+ II((const MipsInstrInfo *) tm.getInstrInfo()),
+ TD(tm.getTargetData()), TM(tm), MCE(mce), MCPEs(0), MJTEs(0),
+ IsPIC(TM.getRelocationModel() == Reloc::PIC_) {
+ }
+
+ bool runOnMachineFunction(MachineFunction &MF);
+
+ virtual const char *getPassName() const {
+ return "Mips Machine Code Emitter";
+ }
+
+ /// getBinaryCodeForInstr - This function, generated by the
+ /// CodeEmitterGenerator using TableGen, produces the binary encoding for
+ /// machine instructions.
+ unsigned getBinaryCodeForInstr(const MachineInstr &MI) const;
+
+ void emitInstruction(const MachineInstr &MI);
+
+ private:
+
+ void emitWordLE(unsigned Word);
+
+ /// Routines that handle operands which add machine relocations which are
+ /// fixed up by the relocation stage.
+ void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc,
+ bool MayNeedFarStub) const;
+ void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const;
+ void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const;
+ void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const;
+ void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc) const;
+
+ /// getMachineOpValue - Return binary encoding of operand. If the machine
+ /// operand requires relocation, record the relocation and return zero.
+ unsigned getMachineOpValue(const MachineInstr &MI,
+ const MachineOperand &MO) const;
+
+ unsigned getRelocation(const MachineInstr &MI,
+ const MachineOperand &MO) const;
+
+ };
+}
+
+char MipsCodeEmitter::ID = 0;
+
+bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
+ JTI = ((MipsTargetMachine&) MF.getTarget()).getJITInfo();
+ II = ((const MipsTargetMachine&) MF.getTarget()).getInstrInfo();
+ TD = ((const MipsTargetMachine&) MF.getTarget()).getTargetData();
+ Subtarget = &TM.getSubtarget<MipsSubtarget> ();
+ MCPEs = &MF.getConstantPool()->getConstants();
+ MJTEs = 0;
+ if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables();
+ JTI->Initialize(MF, IsPIC);
+ MCE.setModuleInfo(&getAnalysis<MachineModuleInfo> ());
+
+ do {
+ DEBUG(errs() << "JITTing function '"
+ << MF.getFunction()->getName() << "'\n");
+ MCE.startFunction(MF);
+
+ for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
+ MBB != E; ++MBB){
+ MCE.StartMachineBasicBlock(MBB);
+ for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end();
+ I != E; ++I)
+ emitInstruction(*I);
+ }
+ } while (MCE.finishFunction(MF));
+
+ return false;
+}
+
+unsigned MipsCodeEmitter::getRelocation(const MachineInstr &MI,
+ const MachineOperand &MO) const {
+ // NOTE: This relocations are for static.
+ uint64_t TSFlags = MI.getDesc().TSFlags;
+ uint64_t Form = TSFlags & MipsII::FormMask;
+ if (Form == MipsII::FrmJ)
+ return Mips::reloc_mips_26;
+ if ((Form == MipsII::FrmI || Form == MipsII::FrmFI)
+ && MI.getDesc().isBranch())
+ return Mips::reloc_mips_branch;
+ if (Form == MipsII::FrmI && MI.getOpcode() == Mips::LUi)
+ return Mips::reloc_mips_hi;
+ return Mips::reloc_mips_lo;
+}
+
+/// getMachineOpValue - Return binary encoding of operand. If the machine
+/// operand requires relocation, record the relocation and return zero.
+unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI,
+ const MachineOperand &MO) const {
+ if (MO.isReg())
+ return MipsRegisterInfo::getRegisterNumbering(MO.getReg());
+ else if (MO.isImm())
+ return static_cast<unsigned>(MO.getImm());
+ else if (MO.isGlobal())
+ emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true);
+ else if (MO.isSymbol())
+ emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO));
+ else if (MO.isCPI())
+ emitConstPoolAddress(MO.getIndex(), getRelocation(MI, MO));
+ else if (MO.isJTI())
+ emitJumpTableAddress(MO.getIndex(), getRelocation(MI, MO));
+ else if (MO.isMBB())
+ emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO));
+ else
+ llvm_unreachable("Unable to encode MachineOperand!");
+ return 0;
+}
+
+void MipsCodeEmitter::emitGlobalAddress(const GlobalValue *GV, unsigned Reloc,
+ bool MayNeedFarStub) const {
+ MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
+ const_cast<GlobalValue *>(GV), 0, MayNeedFarStub));
+}
+
+void MipsCodeEmitter::
+emitExternalSymbolAddress(const char *ES, unsigned Reloc) const {
+ MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
+ Reloc, ES, 0, 0, false));
+}
+
+void MipsCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc) const {
+ MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
+ Reloc, CPI, 0, false));
+}
+
+void MipsCodeEmitter::
+emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const {
+ MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
+ Reloc, JTIndex, 0, false));
+}
+
+void MipsCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB,
+ unsigned Reloc) const {
+ MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
+ Reloc, BB));
+}
+
+void MipsCodeEmitter::emitInstruction(const MachineInstr &MI) {
+ DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI);
+
+ MCE.processDebugLoc(MI.getDebugLoc(), true);
+
+ // Skip pseudo instructions.
+ if ((MI.getDesc().TSFlags & MipsII::FormMask) == MipsII::Pseudo)
+ return;
+
+ ++NumEmitted; // Keep track of the # of mi's emitted
+
+ switch (MI.getOpcode()) {
+ default:
+ emitWordLE(getBinaryCodeForInstr(MI));
+ break;
+ }
+
+ MCE.processDebugLoc(MI.getDebugLoc(), false);
+}
+
+void MipsCodeEmitter::emitWordLE(unsigned Word) {
+ DEBUG(errs() << " 0x";
+ errs().write_hex(Word) << "\n");
+ MCE.emitWordLE(Word);
+}
+
+/// createMipsJITCodeEmitterPass - Return a pass that emits the collected Mips
+/// code to the specified MCE object.
+FunctionPass *llvm::createMipsJITCodeEmitterPass(MipsTargetMachine &TM,
+ JITCodeEmitter &JCE) {
+ return new MipsCodeEmitter(TM, JCE);
+}
+
+unsigned MipsCodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {
+ // this function will be automatically generated by the CodeEmitterGenerator
+ // using TableGen
+ return 0;
+}
diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp
index c3a6211..be3b7a0 100644
--- a/lib/Target/Mips/MipsDelaySlotFiller.cpp
+++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// Simple pass to fills delay slots with NOPs.
+// Simple pass to fills delay slots with useful instructions.
//
//===----------------------------------------------------------------------===//
@@ -17,18 +17,31 @@
#include "MipsTargetMachine.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;
STATISTIC(FilledSlots, "Number of delay slots filled");
+STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that"
+ " are not NOP.");
+
+static cl::opt<bool> EnableDelaySlotFiller(
+ "enable-mips-delay-filler",
+ cl::init(false),
+ cl::desc("Fill the Mips delay slots useful instructions."),
+ cl::Hidden);
namespace {
struct Filler : public MachineFunctionPass {
TargetMachine &TM;
const TargetInstrInfo *TII;
+ MachineBasicBlock::iterator LastFiller;
static char ID;
Filler(TargetMachine &tm)
@@ -47,31 +60,61 @@ namespace {
return Changed;
}
+ bool isDelayFiller(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator candidate);
+
+ void insertCallUses(MachineBasicBlock::iterator MI,
+ SmallSet<unsigned, 32>& RegDefs,
+ SmallSet<unsigned, 32>& RegUses);
+
+ void insertDefsUses(MachineBasicBlock::iterator MI,
+ SmallSet<unsigned, 32>& RegDefs,
+ SmallSet<unsigned, 32>& RegUses);
+
+ bool IsRegInSet(SmallSet<unsigned, 32>& RegSet,
+ unsigned Reg);
+
+ bool delayHasHazard(MachineBasicBlock::iterator candidate,
+ bool &sawLoad, bool &sawStore,
+ SmallSet<unsigned, 32> &RegDefs,
+ SmallSet<unsigned, 32> &RegUses);
+
+ bool
+ findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot,
+ MachineBasicBlock::iterator &Filler);
+
+
};
char Filler::ID = 0;
} // end of anonymous namespace
/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
-/// Currently, we fill delay slots with NOPs. We assume there is only one
-/// delay slot per delayed instruction.
+/// We assume there is only one delay slot per delayed instruction.
bool Filler::
-runOnMachineBasicBlock(MachineBasicBlock &MBB)
-{
+runOnMachineBasicBlock(MachineBasicBlock &MBB) {
bool Changed = false;
- for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
- const MCInstrDesc& MCid = I->getDesc();
- if (MCid.hasDelaySlot() &&
- (TM.getSubtarget<MipsSubtarget>().isMips1() ||
- MCid.isCall() || MCid.isBranch() || MCid.isReturn())) {
- MachineBasicBlock::iterator J = I;
- ++J;
- BuildMI(MBB, J, I->getDebugLoc(), TII->get(Mips::NOP));
+ LastFiller = MBB.end();
+
+ for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I)
+ if (I->getDesc().hasDelaySlot()) {
++FilledSlots;
Changed = true;
- }
- }
+ MachineBasicBlock::iterator D;
+
+ if (EnableDelaySlotFiller && findDelayInstr(MBB, I, D)) {
+ MBB.splice(llvm::next(I), &MBB, D);
+ ++UsefulSlots;
+ }
+ else
+ BuildMI(MBB, llvm::next(I), I->getDebugLoc(), TII->get(Mips::NOP));
+
+ // Record the filler instruction that filled the delay slot.
+ // The instruction after it will be visited in the next iteration.
+ LastFiller = ++I;
+ }
return Changed;
+
}
/// createMipsDelaySlotFillerPass - Returns a pass that fills in delay
@@ -80,3 +123,134 @@ FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) {
return new Filler(tm);
}
+bool Filler::findDelayInstr(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator slot,
+ MachineBasicBlock::iterator &Filler) {
+ SmallSet<unsigned, 32> RegDefs;
+ SmallSet<unsigned, 32> RegUses;
+
+ insertDefsUses(slot, RegDefs, RegUses);
+
+ bool sawLoad = false;
+ bool sawStore = false;
+
+ for (MachineBasicBlock::reverse_iterator I(slot); I != MBB.rend(); ++I) {
+ // skip debug value
+ if (I->isDebugValue())
+ continue;
+
+ // Convert to forward iterator.
+ MachineBasicBlock::iterator FI(llvm::next(I).base());
+
+ if (I->hasUnmodeledSideEffects()
+ || I->isInlineAsm()
+ || I->isLabel()
+ || FI == LastFiller
+ || I->getDesc().isPseudo()
+ //
+ // Should not allow:
+ // ERET, DERET or WAIT, PAUSE. Need to add these to instruction
+ // list. TBD.
+ )
+ break;
+
+ if (delayHasHazard(FI, sawLoad, sawStore, RegDefs, RegUses)) {
+ insertDefsUses(FI, RegDefs, RegUses);
+ continue;
+ }
+
+ Filler = FI;
+ return true;
+ }
+
+ return false;
+}
+
+bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate,
+ bool &sawLoad,
+ bool &sawStore,
+ SmallSet<unsigned, 32> &RegDefs,
+ SmallSet<unsigned, 32> &RegUses) {
+ if (candidate->isImplicitDef() || candidate->isKill())
+ return true;
+
+ MCInstrDesc MCID = candidate->getDesc();
+ // Loads or stores cannot be moved past a store to the delay slot
+ // and stores cannot be moved past a load.
+ if (MCID.mayLoad()) {
+ if (sawStore)
+ return true;
+ sawLoad = true;
+ }
+
+ if (MCID.mayStore()) {
+ if (sawStore)
+ return true;
+ sawStore = true;
+ if (sawLoad)
+ return true;
+ }
+
+ assert((!MCID.isCall() && !MCID.isReturn()) &&
+ "Cannot put calls or returns in delay slot.");
+
+ for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) {
+ const MachineOperand &MO = candidate->getOperand(i);
+ unsigned Reg;
+
+ if (!MO.isReg() || !(Reg = MO.getReg()))
+ continue; // skip
+
+ if (MO.isDef()) {
+ // check whether Reg is defined or used before delay slot.
+ if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg))
+ return true;
+ }
+ if (MO.isUse()) {
+ // check whether Reg is defined before delay slot.
+ if (IsRegInSet(RegDefs, Reg))
+ return true;
+ }
+ }
+ return false;
+}
+
+// Insert Defs and Uses of MI into the sets RegDefs and RegUses.
+void Filler::insertDefsUses(MachineBasicBlock::iterator MI,
+ SmallSet<unsigned, 32>& RegDefs,
+ SmallSet<unsigned, 32>& RegUses) {
+ // If MI is a call or return, just examine the explicit non-variadic operands.
+ MCInstrDesc MCID = MI->getDesc();
+ unsigned e = MCID.isCall() || MCID.isReturn() ? MCID.getNumOperands() :
+ MI->getNumOperands();
+
+ // Add RA to RegDefs to prevent users of RA from going into delay slot.
+ if (MCID.isCall())
+ RegDefs.insert(Mips::RA);
+
+ for (unsigned i = 0; i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+ unsigned Reg;
+
+ if (!MO.isReg() || !(Reg = MO.getReg()))
+ continue;
+
+ if (MO.isDef())
+ RegDefs.insert(Reg);
+ else if (MO.isUse())
+ RegUses.insert(Reg);
+ }
+}
+
+//returns true if the Reg or its alias is in the RegSet.
+bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet, unsigned Reg) {
+ if (RegSet.count(Reg))
+ return true;
+ // check Aliased Registers
+ for (const unsigned *Alias = TM.getRegisterInfo()->getAliasSet(Reg);
+ *Alias; ++Alias)
+ if (RegSet.count(*Alias))
+ return true;
+
+ return false;
+}
diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp
index a0f90a0..22d1e47 100644
--- a/lib/Target/Mips/MipsFrameLowering.cpp
+++ b/lib/Target/Mips/MipsFrameLowering.cpp
@@ -254,9 +254,15 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
}
// Restore GP from the saved stack location
- if (MipsFI->needGPSaveRestore())
- BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE))
- .addImm(MFI->getObjectOffset(MipsFI->getGPFI()));
+ if (MipsFI->needGPSaveRestore()) {
+ unsigned Offset = MFI->getObjectOffset(MipsFI->getGPFI());
+ BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)).addImm(Offset);
+
+ if (Offset >= 0x8000) {
+ BuildMI(MBB, llvm::prior(MBBI), dl, TII.get(Mips::MACRO));
+ BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO));
+ }
+ }
}
void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
@@ -300,13 +306,6 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
}
}
-void
-MipsFrameLowering::getInitialFrameState(std::vector<MachineMove> &Moves) const {
- MachineLocation Dst(MachineLocation::VirtualFP);
- MachineLocation Src(Mips::SP, 0);
- Moves.push_back(MachineMove(0, Dst, Src));
-}
-
void MipsFrameLowering::
processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS) const {
diff --git a/lib/Target/Mips/MipsFrameLowering.h b/lib/Target/Mips/MipsFrameLowering.h
index 78c78ee..c249756 100644
--- a/lib/Target/Mips/MipsFrameLowering.h
+++ b/lib/Target/Mips/MipsFrameLowering.h
@@ -27,7 +27,8 @@ protected:
public:
explicit MipsFrameLowering(const MipsSubtarget &sti)
- : TargetFrameLowering(StackGrowsDown, 8, 0), STI(sti) {
+ : TargetFrameLowering(StackGrowsDown, sti.hasMips64() ? 16 : 8, 0),
+ STI(sti) {
}
bool targetHandlesStackFrameRounding() const;
@@ -39,8 +40,6 @@ public:
bool hasFP(const MachineFunction &MF) const;
- void getInitialFrameState(std::vector<MachineMove> &Moves) const;
-
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS) const;
};
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 90aaeb6..9c831ed 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -86,9 +86,6 @@ private:
// Complex Pattern.
bool SelectAddr(SDValue N, SDValue &Base, SDValue &Offset);
- SDNode *SelectLoadFp64(SDNode *N);
- SDNode *SelectStoreFp64(SDNode *N);
-
// getI32Imm - Return a target constant with the specified
// value, of type i32.
inline SDValue getI32Imm(unsigned Imm) {
@@ -114,17 +111,20 @@ SDNode *MipsDAGToDAGISel::getGlobalBaseReg() {
/// Used on Mips Load/Store instructions
bool MipsDAGToDAGISel::
SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
+ EVT ValTy = Addr.getValueType();
+ unsigned GPReg = ValTy == MVT::i32 ? Mips::GP : Mips::GP_64;
+
// if Address is FI, get the TargetFrameIndex.
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
- Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
- Offset = CurDAG->getTargetConstant(0, MVT::i32);
+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
+ Offset = CurDAG->getTargetConstant(0, ValTy);
return true;
}
// on PIC code Load GA
if (TM.getRelocationModel() == Reloc::PIC_) {
if (Addr.getOpcode() == MipsISD::WrapperPIC) {
- Base = CurDAG->getRegister(Mips::GP, MVT::i32);
+ Base = CurDAG->getRegister(GPReg, ValTy);
Offset = Addr.getOperand(0);
return true;
}
@@ -133,7 +133,7 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
Addr.getOpcode() == ISD::TargetGlobalAddress))
return false;
else if (Addr.getOpcode() == ISD::TargetGlobalTLSAddress) {
- Base = CurDAG->getRegister(Mips::GP, MVT::i32);
+ Base = CurDAG->getRegister(GPReg, ValTy);
Offset = Addr;
return true;
}
@@ -147,11 +147,11 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
// If the first operand is a FI, get the TargetFI Node
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
(Addr.getOperand(0)))
- Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
else
Base = Addr.getOperand(0);
- Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
+ Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy);
return true;
}
}
@@ -180,134 +180,10 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
}
Base = Addr;
- Offset = CurDAG->getTargetConstant(0, MVT::i32);
+ Offset = CurDAG->getTargetConstant(0, ValTy);
return true;
}
-SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) {
- MVT::SimpleValueType NVT =
- N->getValueType(0).getSimpleVT().SimpleTy;
-
- if (!Subtarget.isMips1() || NVT != MVT::f64)
- return NULL;
-
- LoadSDNode *LN = cast<LoadSDNode>(N);
- if (LN->getExtensionType() != ISD::NON_EXTLOAD ||
- LN->getAddressingMode() != ISD::UNINDEXED)
- return NULL;
-
- SDValue Chain = N->getOperand(0);
- SDValue N1 = N->getOperand(1);
- SDValue Offset0, Offset1, Base;
-
- if (!SelectAddr(N1, Base, Offset0) ||
- N1.getValueType() != MVT::i32)
- return NULL;
-
- MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
- MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
- DebugLoc dl = N->getDebugLoc();
-
- // The second load should start after for 4 bytes.
- if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Offset0))
- Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32);
- else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Offset0))
- Offset1 = CurDAG->getTargetConstantPool(CP->getConstVal(),
- MVT::i32,
- CP->getAlignment(),
- CP->getOffset()+4,
- CP->getTargetFlags());
- else
- return NULL;
-
- // Choose the offsets depending on the endianess
- if (TM.getTargetData()->isBigEndian())
- std::swap(Offset0, Offset1);
-
- // Instead of:
- // ldc $f0, X($3)
- // Generate:
- // lwc $f0, X($3)
- // lwc $f1, X+4($3)
- SDNode *LD0 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32,
- MVT::Other, Base, Offset0, Chain);
- SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
- dl, NVT), 0);
- SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl,
- MVT::f64, Undef, SDValue(LD0, 0));
-
- SDNode *LD1 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32,
- MVT::Other, Base, Offset1, SDValue(LD0, 1));
- SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl,
- MVT::f64, I0, SDValue(LD1, 0));
-
- ReplaceUses(SDValue(N, 0), I1);
- ReplaceUses(SDValue(N, 1), Chain);
- cast<MachineSDNode>(LD0)->setMemRefs(MemRefs0, MemRefs0 + 1);
- cast<MachineSDNode>(LD1)->setMemRefs(MemRefs0, MemRefs0 + 1);
- return I1.getNode();
-}
-
-SDNode *MipsDAGToDAGISel::SelectStoreFp64(SDNode *N) {
-
- if (!Subtarget.isMips1() ||
- N->getOperand(1).getValueType() != MVT::f64)
- return NULL;
-
- SDValue Chain = N->getOperand(0);
-
- StoreSDNode *SN = cast<StoreSDNode>(N);
- if (SN->isTruncatingStore() || SN->getAddressingMode() != ISD::UNINDEXED)
- return NULL;
-
- SDValue N1 = N->getOperand(1);
- SDValue N2 = N->getOperand(2);
- SDValue Offset0, Offset1, Base;
-
- if (!SelectAddr(N2, Base, Offset0) ||
- N1.getValueType() != MVT::f64 ||
- N2.getValueType() != MVT::i32)
- return NULL;
-
- MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
- MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
- DebugLoc dl = N->getDebugLoc();
-
- // Get the even and odd part from the f64 register
- SDValue FPOdd = CurDAG->getTargetExtractSubreg(Mips::sub_fpodd,
- dl, MVT::f32, N1);
- SDValue FPEven = CurDAG->getTargetExtractSubreg(Mips::sub_fpeven,
- dl, MVT::f32, N1);
-
- // The second store should start after for 4 bytes.
- if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Offset0))
- Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32);
- else
- return NULL;
-
- // Choose the offsets depending on the endianess
- if (TM.getTargetData()->isBigEndian())
- std::swap(Offset0, Offset1);
-
- // Instead of:
- // sdc $f0, X($3)
- // Generate:
- // swc $f0, X($3)
- // swc $f1, X+4($3)
- SDValue Ops0[] = { FPEven, Base, Offset0, Chain };
- Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl,
- MVT::Other, Ops0, 4), 0);
- cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1);
-
- SDValue Ops1[] = { FPOdd, Base, Offset1, Chain };
- Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl,
- MVT::Other, Ops1, 4), 0);
- cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1);
-
- ReplaceUses(SDValue(N, 0), Chain);
- return Chain.getNode();
-}
-
/// Select instructions not customized! Used for
/// expanded, promoted and normal instructions
SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
@@ -364,6 +240,8 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
/// Mul with two results
case ISD::SMUL_LOHI:
case ISD::UMUL_LOHI: {
+ assert(Node->getValueType(0) != MVT::i64 &&
+ "64-bit multiplication with two results not handled.");
SDValue Op1 = Node->getOperand(0);
SDValue Op2 = Node->getOperand(1);
@@ -389,21 +267,29 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
/// Special Muls
case ISD::MUL:
- if (Subtarget.isMips32())
+ // Mips32 has a 32-bit three operand mul instruction.
+ if (Subtarget.hasMips32() && Node->getValueType(0) == MVT::i32)
break;
case ISD::MULHS:
case ISD::MULHU: {
+ assert((Opcode == ISD::MUL || Node->getValueType(0) != MVT::i64) &&
+ "64-bit MULH* not handled.");
+ EVT Ty = Node->getValueType(0);
SDValue MulOp1 = Node->getOperand(0);
SDValue MulOp2 = Node->getOperand(1);
- unsigned MulOp = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT);
+ unsigned MulOp = (Opcode == ISD::MULHU ?
+ Mips::MULTu :
+ (Ty == MVT::i32 ? Mips::MULT : Mips::DMULT));
SDNode *MulNode = CurDAG->getMachineNode(MulOp, dl,
MVT::Glue, MulOp1, MulOp2);
SDValue InFlag = SDValue(MulNode, 0);
- if (Opcode == ISD::MUL)
- return CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, InFlag);
+ if (Opcode == ISD::MUL) {
+ unsigned Opc = (Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64);
+ return CurDAG->getMachineNode(Opc, dl, Ty, InFlag);
+ }
else
return CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag);
}
@@ -417,31 +303,12 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) {
SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
Mips::ZERO, MVT::i32);
- SDValue Undef = SDValue(
- CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::f64), 0);
- SDNode *MTC = CurDAG->getMachineNode(Mips::MTC1, dl, MVT::f32, Zero);
- SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl,
- MVT::f64, Undef, SDValue(MTC, 0));
- SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl,
- MVT::f64, I0, SDValue(MTC, 0));
- ReplaceUses(SDValue(Node, 0), I1);
- return I1.getNode();
+ return CurDAG->getMachineNode(Mips::BuildPairF64, dl, MVT::f64, Zero,
+ Zero);
}
break;
}
- case ISD::LOAD:
- if (SDNode *ResNode = SelectLoadFp64(Node))
- return ResNode;
- // Other cases are autogenerated.
- break;
-
- case ISD::STORE:
- if (SDNode *ResNode = SelectStoreFp64(Node))
- return ResNode;
- // Other cases are autogenerated.
- break;
-
case MipsISD::ThreadPointer: {
unsigned SrcReg = Mips::HWR29;
unsigned DestReg = Mips::V1;
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index b4f4b1b..1932e74 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -35,6 +35,18 @@
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
+// If I is a shifted mask, set the size (Size) and the first bit of the
+// mask (Pos), and return true.
+// For example, if I is 0x003ff800, (Pos, Size) = (11, 11).
+static bool IsShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) {
+ if (!isUInt<32>(I) || !isShiftedMask_32(I))
+ return false;
+
+ Size = CountPopulation_32(I);
+ Pos = CountTrailingZeros_32(I);
+ return true;
+}
+
const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
case MipsISD::JmpLink: return "MipsISD::JmpLink";
@@ -61,27 +73,38 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64";
case MipsISD::WrapperPIC: return "MipsISD::WrapperPIC";
case MipsISD::DynAlloc: return "MipsISD::DynAlloc";
+ case MipsISD::Sync: return "MipsISD::Sync";
+ case MipsISD::Ext: return "MipsISD::Ext";
+ case MipsISD::Ins: return "MipsISD::Ins";
default: return NULL;
}
}
MipsTargetLowering::
MipsTargetLowering(MipsTargetMachine &TM)
- : TargetLowering(TM, new MipsTargetObjectFile()) {
- Subtarget = &TM.getSubtarget<MipsSubtarget>();
+ : TargetLowering(TM, new MipsTargetObjectFile()),
+ Subtarget(&TM.getSubtarget<MipsSubtarget>()),
+ HasMips64(Subtarget->hasMips64()), IsN64(Subtarget->isABI_N64()) {
// Mips does not have i1 type, so use i32 for
// setcc operations results (slt, sgt, ...).
setBooleanContents(ZeroOrOneBooleanContent);
+ setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
// Set up the register classes
addRegisterClass(MVT::i32, Mips::CPURegsRegisterClass);
addRegisterClass(MVT::f32, Mips::FGR32RegisterClass);
+ if (HasMips64)
+ addRegisterClass(MVT::i64, Mips::CPU64RegsRegisterClass);
+
// When dealing with single precision only, use libcalls
- if (!Subtarget->isSingleFloat())
- if (!Subtarget->isFP64bit())
+ if (!Subtarget->isSingleFloat()) {
+ if (HasMips64)
+ addRegisterClass(MVT::f64, Mips::FGR64RegisterClass);
+ else
addRegisterClass(MVT::f64, Mips::AFGR64RegisterClass);
+ }
// Load extented operations for i1 types must be promoted
setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
@@ -100,6 +123,7 @@ MipsTargetLowering(MipsTargetMachine &TM)
// Mips Custom Operations
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
+ setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
@@ -115,6 +139,10 @@ MipsTargetLowering(MipsTargetMachine &TM)
setOperationAction(ISD::SREM, MVT::i32, Expand);
setOperationAction(ISD::UDIV, MVT::i32, Expand);
setOperationAction(ISD::UREM, MVT::i32, Expand);
+ setOperationAction(ISD::SDIV, MVT::i64, Expand);
+ setOperationAction(ISD::SREM, MVT::i64, Expand);
+ setOperationAction(ISD::UDIV, MVT::i64, Expand);
+ setOperationAction(ISD::UREM, MVT::i64, Expand);
// Operations not directly supported by Mips.
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
@@ -126,10 +154,14 @@ MipsTargetLowering(MipsTargetMachine &TM)
setOperationAction(ISD::CTPOP, MVT::i32, Expand);
setOperationAction(ISD::CTTZ, MVT::i32, Expand);
setOperationAction(ISD::ROTL, MVT::i32, Expand);
+ setOperationAction(ISD::ROTL, MVT::i64, Expand);
- if (!Subtarget->isMips32r2())
+ if (!Subtarget->hasMips32r2())
setOperationAction(ISD::ROTR, MVT::i32, Expand);
+ if (!Subtarget->hasMips64r2())
+ setOperationAction(ISD::ROTR, MVT::i64, Expand);
+
setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
@@ -159,7 +191,14 @@ MipsTargetLowering(MipsTargetMachine &TM)
// Use the default for now
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
- setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
+
+ setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom);
+ setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
+
+ setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Expand);
+ setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Expand);
+
+ setInsertFencesForAtomic(true);
if (Subtarget->isSingleFloat())
setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
@@ -180,6 +219,8 @@ MipsTargetLowering(MipsTargetMachine &TM)
setTargetDAGCombine(ISD::SDIVREM);
setTargetDAGCombine(ISD::UDIVREM);
setTargetDAGCombine(ISD::SETCC);
+ setTargetDAGCombine(ISD::AND);
+ setTargetDAGCombine(ISD::OR);
setMinFunctionAlignment(2);
@@ -190,7 +231,12 @@ MipsTargetLowering(MipsTargetMachine &TM)
setExceptionSelectorRegister(Mips::A1);
}
-MVT::SimpleValueType MipsTargetLowering::getSetCCResultType(EVT VT) const {
+bool MipsTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const {
+ MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy;
+ return SVT == MVT::i64 || SVT == MVT::i32 || SVT == MVT::i16;
+}
+
+EVT MipsTargetLowering::getSetCCResultType(EVT VT) const {
return MVT::i32;
}
@@ -348,7 +394,7 @@ static SDValue PerformADDECombine(SDNode *N, SelectionDAG& DAG,
if (DCI.isBeforeLegalize())
return SDValue();
- if (Subtarget->isMips32() && SelectMadd(N, &DAG))
+ if (Subtarget->hasMips32() && SelectMadd(N, &DAG))
return SDValue(N, 0);
return SDValue();
@@ -360,7 +406,7 @@ static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG,
if (DCI.isBeforeLegalize())
return SDValue();
- if (Subtarget->isMips32() && SelectMsub(N, &DAG))
+ if (Subtarget->hasMips32() && SelectMsub(N, &DAG))
return SDValue(N, 0);
return SDValue();
@@ -372,6 +418,9 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG,
if (DCI.isBeforeLegalizeOps())
return SDValue();
+ EVT Ty = N->getValueType(0);
+ unsigned LO = (Ty == MVT::i32) ? Mips::LO : Mips::LO64;
+ unsigned HI = (Ty == MVT::i32) ? Mips::HI : Mips::HI64;
unsigned opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem :
MipsISD::DivRemU;
DebugLoc dl = N->getDebugLoc();
@@ -383,7 +432,7 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG,
// insert MFLO
if (N->hasAnyUseOfValue(0)) {
- SDValue CopyFromLo = DAG.getCopyFromReg(InChain, dl, Mips::LO, MVT::i32,
+ SDValue CopyFromLo = DAG.getCopyFromReg(InChain, dl, LO, Ty,
InGlue);
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyFromLo);
InChain = CopyFromLo.getValue(1);
@@ -393,7 +442,7 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG,
// insert MFHI
if (N->hasAnyUseOfValue(1)) {
SDValue CopyFromHi = DAG.getCopyFromReg(InChain, dl,
- Mips::HI, MVT::i32, InGlue);
+ HI, Ty, InGlue);
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi);
}
@@ -490,6 +539,101 @@ static SDValue PerformSETCCCombine(SDNode *N, SelectionDAG& DAG,
return CreateCMovFP(DAG, Cond, True, False, N->getDebugLoc());
}
+static SDValue PerformANDCombine(SDNode *N, SelectionDAG& DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget* Subtarget) {
+ // Pattern match EXT.
+ // $dst = and ((sra or srl) $src , pos), (2**size - 1)
+ // => ext $dst, $src, size, pos
+ if (DCI.isBeforeLegalizeOps() || !Subtarget->hasMips32r2())
+ return SDValue();
+
+ SDValue ShiftRight = N->getOperand(0), Mask = N->getOperand(1);
+
+ // Op's first operand must be a shift right.
+ if (ShiftRight.getOpcode() != ISD::SRA && ShiftRight.getOpcode() != ISD::SRL)
+ return SDValue();
+
+ // The second operand of the shift must be an immediate.
+ uint64_t Pos;
+ ConstantSDNode *CN;
+ if (!(CN = dyn_cast<ConstantSDNode>(ShiftRight.getOperand(1))))
+ return SDValue();
+
+ Pos = CN->getZExtValue();
+
+ uint64_t SMPos, SMSize;
+ // Op's second operand must be a shifted mask.
+ if (!(CN = dyn_cast<ConstantSDNode>(Mask)) ||
+ !IsShiftedMask(CN->getZExtValue(), SMPos, SMSize))
+ return SDValue();
+
+ // Return if the shifted mask does not start at bit 0 or the sum of its size
+ // and Pos exceeds the word's size.
+ if (SMPos != 0 || Pos + SMSize > 32)
+ return SDValue();
+
+ return DAG.getNode(MipsISD::Ext, N->getDebugLoc(), MVT::i32,
+ ShiftRight.getOperand(0),
+ DAG.getConstant(Pos, MVT::i32),
+ DAG.getConstant(SMSize, MVT::i32));
+}
+
+static SDValue PerformORCombine(SDNode *N, SelectionDAG& DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget* Subtarget) {
+ // Pattern match INS.
+ // $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1),
+ // where mask1 = (2**size - 1) << pos, mask0 = ~mask1
+ // => ins $dst, $src, size, pos, $src1
+ if (DCI.isBeforeLegalizeOps() || !Subtarget->hasMips32r2())
+ return SDValue();
+
+ SDValue And0 = N->getOperand(0), And1 = N->getOperand(1);
+ uint64_t SMPos0, SMSize0, SMPos1, SMSize1;
+ ConstantSDNode *CN;
+
+ // See if Op's first operand matches (and $src1 , mask0).
+ if (And0.getOpcode() != ISD::AND)
+ return SDValue();
+
+ if (!(CN = dyn_cast<ConstantSDNode>(And0.getOperand(1))) ||
+ !IsShiftedMask(~CN->getSExtValue(), SMPos0, SMSize0))
+ return SDValue();
+
+ // See if Op's second operand matches (and (shl $src, pos), mask1).
+ if (And1.getOpcode() != ISD::AND)
+ return SDValue();
+
+ if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) ||
+ !IsShiftedMask(CN->getZExtValue(), SMPos1, SMSize1))
+ return SDValue();
+
+ // The shift masks must have the same position and size.
+ if (SMPos0 != SMPos1 || SMSize0 != SMSize1)
+ return SDValue();
+
+ SDValue Shl = And1.getOperand(0);
+ if (Shl.getOpcode() != ISD::SHL)
+ return SDValue();
+
+ if (!(CN = dyn_cast<ConstantSDNode>(Shl.getOperand(1))))
+ return SDValue();
+
+ unsigned Shamt = CN->getZExtValue();
+
+ // Return if the shift amount and the first bit position of mask are not the
+ // same.
+ if (Shamt != SMPos0)
+ return SDValue();
+
+ return DAG.getNode(MipsISD::Ins, N->getDebugLoc(), MVT::i32,
+ Shl.getOperand(0),
+ DAG.getConstant(SMPos0, MVT::i32),
+ DAG.getConstant(SMSize0, MVT::i32),
+ And0.getOperand(0));
+}
+
SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
const {
SelectionDAG &DAG = DCI.DAG;
@@ -506,6 +650,10 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
return PerformDivRemCombine(N, DAG, DCI, Subtarget);
case ISD::SETCC:
return PerformSETCCCombine(N, DAG, DCI, Subtarget);
+ case ISD::AND:
+ return PerformANDCombine(N, DAG, DCI, Subtarget);
+ case ISD::OR:
+ return PerformORCombine(N, DAG, DCI, Subtarget);
}
return SDValue();
@@ -527,6 +675,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
case ISD::VASTART: return LowerVASTART(Op, DAG);
case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
+ case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG);
+ case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG);
}
return SDValue();
}
@@ -733,13 +883,13 @@ MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
DebugLoc dl = MI->getDebugLoc();
- unsigned Dest = MI->getOperand(0).getReg();
+ unsigned OldVal = MI->getOperand(0).getReg();
unsigned Ptr = MI->getOperand(1).getReg();
unsigned Incr = MI->getOperand(2).getReg();
- unsigned Oldval = RegInfo.createVirtualRegister(RC);
- unsigned Tmp1 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp2 = RegInfo.createVirtualRegister(RC);
+ unsigned StoreVal = RegInfo.createVirtualRegister(RC);
+ unsigned AndRes = RegInfo.createVirtualRegister(RC);
+ unsigned Success = RegInfo.createVirtualRegister(RC);
// insert new blocks after the current block
const BasicBlock *LLVM_BB = BB->getBasicBlock();
@@ -758,61 +908,38 @@ MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
// thisMBB:
// ...
- // sw incr, fi(sp) // store incr to stack (when BinOpcode == 0)
// fallthrough --> loopMBB
-
- // Note: for atomic.swap (when BinOpcode == 0), storing incr to stack before
- // the loop and then loading it from stack in block loopMBB is necessary to
- // prevent MachineLICM pass to hoist "or" instruction out of the block
- // loopMBB.
-
- int fi = 0;
- if (BinOpcode == 0 && !Nand) {
- // Get or create a temporary stack location.
- MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>();
- fi = MipsFI->getAtomicFrameIndex();
- if (fi == -1) {
- fi = MF->getFrameInfo()->CreateStackObject(Size, Size, false);
- MipsFI->setAtomicFrameIndex(fi);
- }
-
- BuildMI(BB, dl, TII->get(Mips::SW))
- .addReg(Incr).addFrameIndex(fi).addImm(0);
- }
BB->addSuccessor(loopMBB);
+ loopMBB->addSuccessor(loopMBB);
+ loopMBB->addSuccessor(exitMBB);
// loopMBB:
// ll oldval, 0(ptr)
- // or dest, $0, oldval
- // <binop> tmp1, oldval, incr
- // sc tmp1, 0(ptr)
- // beq tmp1, $0, loopMBB
+ // <binop> storeval, oldval, incr
+ // sc success, storeval, 0(ptr)
+ // beq success, $0, loopMBB
BB = loopMBB;
- BuildMI(BB, dl, TII->get(Mips::LL), Oldval).addReg(Ptr).addImm(0);
- BuildMI(BB, dl, TII->get(Mips::OR), Dest).addReg(Mips::ZERO).addReg(Oldval);
+ BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(Ptr).addImm(0);
if (Nand) {
- // and tmp2, oldval, incr
- // nor tmp1, $0, tmp2
- BuildMI(BB, dl, TII->get(Mips::AND), Tmp2).addReg(Oldval).addReg(Incr);
- BuildMI(BB, dl, TII->get(Mips::NOR), Tmp1).addReg(Mips::ZERO).addReg(Tmp2);
+ // and andres, oldval, incr
+ // nor storeval, $0, andres
+ BuildMI(BB, dl, TII->get(Mips::AND), AndRes).addReg(OldVal).addReg(Incr);
+ BuildMI(BB, dl, TII->get(Mips::NOR), StoreVal)
+ .addReg(Mips::ZERO).addReg(AndRes);
} else if (BinOpcode) {
- // <binop> tmp1, oldval, incr
- BuildMI(BB, dl, TII->get(BinOpcode), Tmp1).addReg(Oldval).addReg(Incr);
+ // <binop> storeval, oldval, incr
+ BuildMI(BB, dl, TII->get(BinOpcode), StoreVal).addReg(OldVal).addReg(Incr);
} else {
- // lw tmp2, fi(sp) // load incr from stack
- // or tmp1, $zero, tmp2
- BuildMI(BB, dl, TII->get(Mips::LW), Tmp2).addFrameIndex(fi).addImm(0);
- BuildMI(BB, dl, TII->get(Mips::OR), Tmp1).addReg(Mips::ZERO).addReg(Tmp2);
+ StoreVal = Incr;
}
- BuildMI(BB, dl, TII->get(Mips::SC), Tmp1).addReg(Tmp1).addReg(Ptr).addImm(0);
+ BuildMI(BB, dl, TII->get(Mips::SC), Success)
+ .addReg(StoreVal).addReg(Ptr).addImm(0);
BuildMI(BB, dl, TII->get(Mips::BEQ))
- .addReg(Tmp1).addReg(Mips::ZERO).addMBB(loopMBB);
- BB->addSuccessor(loopMBB);
- BB->addSuccessor(exitMBB);
+ .addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB);
MI->eraseFromParent(); // The instruction is gone now.
- return BB;
+ return exitMBB;
}
MachineBasicBlock *
@@ -833,33 +960,34 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI,
unsigned Ptr = MI->getOperand(1).getReg();
unsigned Incr = MI->getOperand(2).getReg();
- unsigned Addr = RegInfo.createVirtualRegister(RC);
- unsigned Shift = RegInfo.createVirtualRegister(RC);
+ unsigned AlignedAddr = RegInfo.createVirtualRegister(RC);
+ unsigned ShiftAmt = RegInfo.createVirtualRegister(RC);
unsigned Mask = RegInfo.createVirtualRegister(RC);
unsigned Mask2 = RegInfo.createVirtualRegister(RC);
- unsigned Newval = RegInfo.createVirtualRegister(RC);
- unsigned Oldval = RegInfo.createVirtualRegister(RC);
+ unsigned NewVal = RegInfo.createVirtualRegister(RC);
+ unsigned OldVal = RegInfo.createVirtualRegister(RC);
unsigned Incr2 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp1 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp2 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp3 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp4 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp5 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp6 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp7 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp8 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp9 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp10 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp11 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp12 = RegInfo.createVirtualRegister(RC);
+ unsigned MaskLSB2 = RegInfo.createVirtualRegister(RC);
+ unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC);
+ unsigned MaskUpper = RegInfo.createVirtualRegister(RC);
+ unsigned AndRes = RegInfo.createVirtualRegister(RC);
+ unsigned BinOpRes = RegInfo.createVirtualRegister(RC);
+ unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC);
+ unsigned StoreVal = RegInfo.createVirtualRegister(RC);
+ unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC);
+ unsigned SrlRes = RegInfo.createVirtualRegister(RC);
+ unsigned SllRes = RegInfo.createVirtualRegister(RC);
+ unsigned Success = RegInfo.createVirtualRegister(RC);
// insert new blocks after the current block
const BasicBlock *LLVM_BB = BB->getBasicBlock();
MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
MachineFunction::iterator It = BB;
++It;
MF->insert(It, loopMBB);
+ MF->insert(It, sinkMBB);
MF->insert(It, exitMBB);
// Transfer the remainder of BB and its successor edges to exitMBB.
@@ -868,111 +996,104 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI,
BB->end());
exitMBB->transferSuccessorsAndUpdatePHIs(BB);
+ BB->addSuccessor(loopMBB);
+ loopMBB->addSuccessor(loopMBB);
+ loopMBB->addSuccessor(sinkMBB);
+ sinkMBB->addSuccessor(exitMBB);
+
// thisMBB:
- // addiu tmp1,$0,-4 # 0xfffffffc
- // and addr,ptr,tmp1
- // andi tmp2,ptr,3
- // sll shift,tmp2,3
- // ori tmp3,$0,255 # 0xff
- // sll mask,tmp3,shift
+ // addiu masklsb2,$0,-4 # 0xfffffffc
+ // and alignedaddr,ptr,masklsb2
+ // andi ptrlsb2,ptr,3
+ // sll shiftamt,ptrlsb2,3
+ // ori maskupper,$0,255 # 0xff
+ // sll mask,maskupper,shiftamt
// nor mask2,$0,mask
- // andi tmp4,incr,255
- // sll incr2,tmp4,shift
- // sw incr2, fi(sp) // store incr2 to stack (when BinOpcode == 0)
-
- // Note: for atomic.swap (when BinOpcode == 0), storing incr2 to stack before
- // the loop and then loading it from stack in block loopMBB is necessary to
- // prevent MachineLICM pass to hoist "or" instruction out of the block
- // loopMBB.
+ // sll incr2,incr,shiftamt
int64_t MaskImm = (Size == 1) ? 255 : 65535;
- BuildMI(BB, dl, TII->get(Mips::ADDiu), Tmp1).addReg(Mips::ZERO).addImm(-4);
- BuildMI(BB, dl, TII->get(Mips::AND), Addr).addReg(Ptr).addReg(Tmp1);
- BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp2).addReg(Ptr).addImm(3);
- BuildMI(BB, dl, TII->get(Mips::SLL), Shift).addReg(Tmp2).addImm(3);
- BuildMI(BB, dl, TII->get(Mips::ORi), Tmp3).addReg(Mips::ZERO).addImm(MaskImm);
- BuildMI(BB, dl, TII->get(Mips::SLL), Mask).addReg(Tmp3).addReg(Shift);
+ BuildMI(BB, dl, TII->get(Mips::ADDiu), MaskLSB2)
+ .addReg(Mips::ZERO).addImm(-4);
+ BuildMI(BB, dl, TII->get(Mips::AND), AlignedAddr)
+ .addReg(Ptr).addReg(MaskLSB2);
+ BuildMI(BB, dl, TII->get(Mips::ANDi), PtrLSB2).addReg(Ptr).addImm(3);
+ BuildMI(BB, dl, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3);
+ BuildMI(BB, dl, TII->get(Mips::ORi), MaskUpper)
+ .addReg(Mips::ZERO).addImm(MaskImm);
+ BuildMI(BB, dl, TII->get(Mips::SLLV), Mask)
+ .addReg(ShiftAmt).addReg(MaskUpper);
BuildMI(BB, dl, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask);
- if (BinOpcode != Mips::SUBu) {
- BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp4).addReg(Incr).addImm(MaskImm);
- BuildMI(BB, dl, TII->get(Mips::SLL), Incr2).addReg(Tmp4).addReg(Shift);
- } else {
- BuildMI(BB, dl, TII->get(Mips::SUBu), Tmp4).addReg(Mips::ZERO).addReg(Incr);
- BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp5).addReg(Tmp4).addImm(MaskImm);
- BuildMI(BB, dl, TII->get(Mips::SLL), Incr2).addReg(Tmp5).addReg(Shift);
- }
+ BuildMI(BB, dl, TII->get(Mips::SLLV), Incr2).addReg(ShiftAmt).addReg(Incr);
- int fi = 0;
- if (BinOpcode == 0 && !Nand) {
- // Get or create a temporary stack location.
- MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>();
- fi = MipsFI->getAtomicFrameIndex();
- if (fi == -1) {
- fi = MF->getFrameInfo()->CreateStackObject(Size, Size, false);
- MipsFI->setAtomicFrameIndex(fi);
- }
-
- BuildMI(BB, dl, TII->get(Mips::SW))
- .addReg(Incr2).addFrameIndex(fi).addImm(0);
- }
- BB->addSuccessor(loopMBB);
+ // atomic.load.binop
+ // loopMBB:
+ // ll oldval,0(alignedaddr)
+ // binop binopres,oldval,incr2
+ // and newval,binopres,mask
+ // and maskedoldval0,oldval,mask2
+ // or storeval,maskedoldval0,newval
+ // sc success,storeval,0(alignedaddr)
+ // beq success,$0,loopMBB
+
+ // atomic.swap
// loopMBB:
- // ll oldval,0(addr)
- // binop tmp7,oldval,incr2
- // and newval,tmp7,mask
- // and tmp8,oldval,mask2
- // or tmp9,tmp8,newval
- // sc tmp9,0(addr)
- // beq tmp9,$0,loopMBB
+ // ll oldval,0(alignedaddr)
+ // and newval,incr2,mask
+ // and maskedoldval0,oldval,mask2
+ // or storeval,maskedoldval0,newval
+ // sc success,storeval,0(alignedaddr)
+ // beq success,$0,loopMBB
+
BB = loopMBB;
- BuildMI(BB, dl, TII->get(Mips::LL), Oldval).addReg(Addr).addImm(0);
+ BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0);
if (Nand) {
- // and tmp6, oldval, incr2
- // nor tmp7, $0, tmp6
- BuildMI(BB, dl, TII->get(Mips::AND), Tmp6).addReg(Oldval).addReg(Incr2);
- BuildMI(BB, dl, TII->get(Mips::NOR), Tmp7).addReg(Mips::ZERO).addReg(Tmp6);
- } else if (BinOpcode == Mips::SUBu) {
- // addu tmp7, oldval, incr2
- BuildMI(BB, dl, TII->get(Mips::ADDu), Tmp7).addReg(Oldval).addReg(Incr2);
+ // and andres, oldval, incr2
+ // nor binopres, $0, andres
+ // and newval, binopres, mask
+ BuildMI(BB, dl, TII->get(Mips::AND), AndRes).addReg(OldVal).addReg(Incr2);
+ BuildMI(BB, dl, TII->get(Mips::NOR), BinOpRes)
+ .addReg(Mips::ZERO).addReg(AndRes);
+ BuildMI(BB, dl, TII->get(Mips::AND), NewVal).addReg(BinOpRes).addReg(Mask);
} else if (BinOpcode) {
- // <binop> tmp7, oldval, incr2
- BuildMI(BB, dl, TII->get(BinOpcode), Tmp7).addReg(Oldval).addReg(Incr2);
- } else {
- // lw tmp6, fi(sp) // load incr2 from stack
- // or tmp7, $zero, tmp6
- BuildMI(BB, dl, TII->get(Mips::LW), Tmp6).addFrameIndex(fi).addImm(0);
- BuildMI(BB, dl, TII->get(Mips::OR), Tmp7).addReg(Mips::ZERO).addReg(Tmp6);
+ // <binop> binopres, oldval, incr2
+ // and newval, binopres, mask
+ BuildMI(BB, dl, TII->get(BinOpcode), BinOpRes).addReg(OldVal).addReg(Incr2);
+ BuildMI(BB, dl, TII->get(Mips::AND), NewVal).addReg(BinOpRes).addReg(Mask);
+ } else {// atomic.swap
+ // and newval, incr2, mask
+ BuildMI(BB, dl, TII->get(Mips::AND), NewVal).addReg(Incr2).addReg(Mask);
}
- BuildMI(BB, dl, TII->get(Mips::AND), Newval).addReg(Tmp7).addReg(Mask);
- BuildMI(BB, dl, TII->get(Mips::AND), Tmp8).addReg(Oldval).addReg(Mask2);
- BuildMI(BB, dl, TII->get(Mips::OR), Tmp9).addReg(Tmp8).addReg(Newval);
- BuildMI(BB, dl, TII->get(Mips::SC), Tmp9).addReg(Tmp9).addReg(Addr).addImm(0);
+
+ BuildMI(BB, dl, TII->get(Mips::AND), MaskedOldVal0)
+ .addReg(OldVal).addReg(Mask2);
+ BuildMI(BB, dl, TII->get(Mips::OR), StoreVal)
+ .addReg(MaskedOldVal0).addReg(NewVal);
+ BuildMI(BB, dl, TII->get(Mips::SC), Success)
+ .addReg(StoreVal).addReg(AlignedAddr).addImm(0);
BuildMI(BB, dl, TII->get(Mips::BEQ))
- .addReg(Tmp9).addReg(Mips::ZERO).addMBB(loopMBB);
- BB->addSuccessor(loopMBB);
- BB->addSuccessor(exitMBB);
-
- // exitMBB:
- // and tmp10,oldval,mask
- // srl tmp11,tmp10,shift
- // sll tmp12,tmp11,24
- // sra dest,tmp12,24
- BB = exitMBB;
+ .addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB);
+
+ // sinkMBB:
+ // and maskedoldval1,oldval,mask
+ // srl srlres,maskedoldval1,shiftamt
+ // sll sllres,srlres,24
+ // sra dest,sllres,24
+ BB = sinkMBB;
int64_t ShiftImm = (Size == 1) ? 24 : 16;
- // reverse order
- BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SRA), Dest)
- .addReg(Tmp12).addImm(ShiftImm);
- BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SLL), Tmp12)
- .addReg(Tmp11).addImm(ShiftImm);
- BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SRL), Tmp11)
- .addReg(Tmp10).addReg(Shift);
- BuildMI(*BB, BB->begin(), dl, TII->get(Mips::AND), Tmp10)
- .addReg(Oldval).addReg(Mask);
+
+ BuildMI(BB, dl, TII->get(Mips::AND), MaskedOldVal1)
+ .addReg(OldVal).addReg(Mask);
+ BuildMI(BB, dl, TII->get(Mips::SRLV), SrlRes)
+ .addReg(ShiftAmt).addReg(MaskedOldVal1);
+ BuildMI(BB, dl, TII->get(Mips::SLL), SllRes)
+ .addReg(SrlRes).addImm(ShiftImm);
+ BuildMI(BB, dl, TII->get(Mips::SRA), Dest)
+ .addReg(SllRes).addImm(ShiftImm);
MI->eraseFromParent(); // The instruction is gone now.
- return BB;
+ return exitMBB;
}
MachineBasicBlock *
@@ -989,11 +1110,10 @@ MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI,
unsigned Dest = MI->getOperand(0).getReg();
unsigned Ptr = MI->getOperand(1).getReg();
- unsigned Oldval = MI->getOperand(2).getReg();
- unsigned Newval = MI->getOperand(3).getReg();
+ unsigned OldVal = MI->getOperand(2).getReg();
+ unsigned NewVal = MI->getOperand(3).getReg();
- unsigned Tmp1 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp2 = RegInfo.createVirtualRegister(RC);
+ unsigned Success = RegInfo.createVirtualRegister(RC);
// insert new blocks after the current block
const BasicBlock *LLVM_BB = BB->getBasicBlock();
@@ -1012,26 +1132,14 @@ MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI,
BB->end());
exitMBB->transferSuccessorsAndUpdatePHIs(BB);
- // Get or create a temporary stack location.
- MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>();
- int fi = MipsFI->getAtomicFrameIndex();
- if (fi == -1) {
- fi = MF->getFrameInfo()->CreateStackObject(Size, Size, false);
- MipsFI->setAtomicFrameIndex(fi);
- }
-
// thisMBB:
// ...
- // sw newval, fi(sp) // store newval to stack
// fallthrough --> loop1MBB
-
- // Note: storing newval to stack before the loop and then loading it from
- // stack in block loop2MBB is necessary to prevent MachineLICM pass to
- // hoist "or" instruction out of the block loop2MBB.
-
- BuildMI(BB, dl, TII->get(Mips::SW))
- .addReg(Newval).addFrameIndex(fi).addImm(0);
BB->addSuccessor(loop1MBB);
+ loop1MBB->addSuccessor(exitMBB);
+ loop1MBB->addSuccessor(loop2MBB);
+ loop2MBB->addSuccessor(loop1MBB);
+ loop2MBB->addSuccessor(exitMBB);
// loop1MBB:
// ll dest, 0(ptr)
@@ -1039,27 +1147,20 @@ MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI,
BB = loop1MBB;
BuildMI(BB, dl, TII->get(Mips::LL), Dest).addReg(Ptr).addImm(0);
BuildMI(BB, dl, TII->get(Mips::BNE))
- .addReg(Dest).addReg(Oldval).addMBB(exitMBB);
- BB->addSuccessor(exitMBB);
- BB->addSuccessor(loop2MBB);
+ .addReg(Dest).addReg(OldVal).addMBB(exitMBB);
// loop2MBB:
- // lw tmp2, fi(sp) // load newval from stack
- // or tmp1, $0, tmp2
- // sc tmp1, 0(ptr)
- // beq tmp1, $0, loop1MBB
+ // sc success, newval, 0(ptr)
+ // beq success, $0, loop1MBB
BB = loop2MBB;
- BuildMI(BB, dl, TII->get(Mips::LW), Tmp2).addFrameIndex(fi).addImm(0);
- BuildMI(BB, dl, TII->get(Mips::OR), Tmp1).addReg(Mips::ZERO).addReg(Tmp2);
- BuildMI(BB, dl, TII->get(Mips::SC), Tmp1).addReg(Tmp1).addReg(Ptr).addImm(0);
+ BuildMI(BB, dl, TII->get(Mips::SC), Success)
+ .addReg(NewVal).addReg(Ptr).addImm(0);
BuildMI(BB, dl, TII->get(Mips::BEQ))
- .addReg(Tmp1).addReg(Mips::ZERO).addMBB(loop1MBB);
- BB->addSuccessor(loop1MBB);
- BB->addSuccessor(exitMBB);
+ .addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB);
MI->eraseFromParent(); // The instruction is gone now.
- return BB;
+ return exitMBB;
}
MachineBasicBlock *
@@ -1077,36 +1178,39 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI,
unsigned Dest = MI->getOperand(0).getReg();
unsigned Ptr = MI->getOperand(1).getReg();
- unsigned Oldval = MI->getOperand(2).getReg();
- unsigned Newval = MI->getOperand(3).getReg();
+ unsigned CmpVal = MI->getOperand(2).getReg();
+ unsigned NewVal = MI->getOperand(3).getReg();
- unsigned Addr = RegInfo.createVirtualRegister(RC);
- unsigned Shift = RegInfo.createVirtualRegister(RC);
+ unsigned AlignedAddr = RegInfo.createVirtualRegister(RC);
+ unsigned ShiftAmt = RegInfo.createVirtualRegister(RC);
unsigned Mask = RegInfo.createVirtualRegister(RC);
unsigned Mask2 = RegInfo.createVirtualRegister(RC);
- unsigned Oldval2 = RegInfo.createVirtualRegister(RC);
- unsigned Oldval3 = RegInfo.createVirtualRegister(RC);
- unsigned Oldval4 = RegInfo.createVirtualRegister(RC);
- unsigned Newval2 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp1 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp2 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp3 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp4 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp5 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp6 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp7 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp8 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp9 = RegInfo.createVirtualRegister(RC);
+ unsigned ShiftedCmpVal = RegInfo.createVirtualRegister(RC);
+ unsigned OldVal = RegInfo.createVirtualRegister(RC);
+ unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC);
+ unsigned ShiftedNewVal = RegInfo.createVirtualRegister(RC);
+ unsigned MaskLSB2 = RegInfo.createVirtualRegister(RC);
+ unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC);
+ unsigned MaskUpper = RegInfo.createVirtualRegister(RC);
+ unsigned MaskedCmpVal = RegInfo.createVirtualRegister(RC);
+ unsigned MaskedNewVal = RegInfo.createVirtualRegister(RC);
+ unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC);
+ unsigned StoreVal = RegInfo.createVirtualRegister(RC);
+ unsigned SrlRes = RegInfo.createVirtualRegister(RC);
+ unsigned SllRes = RegInfo.createVirtualRegister(RC);
+ unsigned Success = RegInfo.createVirtualRegister(RC);
// insert new blocks after the current block
const BasicBlock *LLVM_BB = BB->getBasicBlock();
MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
MachineFunction::iterator It = BB;
++It;
MF->insert(It, loop1MBB);
MF->insert(It, loop2MBB);
+ MF->insert(It, sinkMBB);
MF->insert(It, exitMBB);
// Transfer the remainder of BB and its successor edges to exitMBB.
@@ -1115,76 +1219,90 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI,
BB->end());
exitMBB->transferSuccessorsAndUpdatePHIs(BB);
+ BB->addSuccessor(loop1MBB);
+ loop1MBB->addSuccessor(sinkMBB);
+ loop1MBB->addSuccessor(loop2MBB);
+ loop2MBB->addSuccessor(loop1MBB);
+ loop2MBB->addSuccessor(sinkMBB);
+ sinkMBB->addSuccessor(exitMBB);
+
+ // FIXME: computation of newval2 can be moved to loop2MBB.
// thisMBB:
- // addiu tmp1,$0,-4 # 0xfffffffc
- // and addr,ptr,tmp1
- // andi tmp2,ptr,3
- // sll shift,tmp2,3
- // ori tmp3,$0,255 # 0xff
- // sll mask,tmp3,shift
+ // addiu masklsb2,$0,-4 # 0xfffffffc
+ // and alignedaddr,ptr,masklsb2
+ // andi ptrlsb2,ptr,3
+ // sll shiftamt,ptrlsb2,3
+ // ori maskupper,$0,255 # 0xff
+ // sll mask,maskupper,shiftamt
// nor mask2,$0,mask
- // andi tmp4,oldval,255
- // sll oldval2,tmp4,shift
- // andi tmp5,newval,255
- // sll newval2,tmp5,shift
+ // andi maskedcmpval,cmpval,255
+ // sll shiftedcmpval,maskedcmpval,shiftamt
+ // andi maskednewval,newval,255
+ // sll shiftednewval,maskednewval,shiftamt
int64_t MaskImm = (Size == 1) ? 255 : 65535;
- BuildMI(BB, dl, TII->get(Mips::ADDiu), Tmp1).addReg(Mips::ZERO).addImm(-4);
- BuildMI(BB, dl, TII->get(Mips::AND), Addr).addReg(Ptr).addReg(Tmp1);
- BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp2).addReg(Ptr).addImm(3);
- BuildMI(BB, dl, TII->get(Mips::SLL), Shift).addReg(Tmp2).addImm(3);
- BuildMI(BB, dl, TII->get(Mips::ORi), Tmp3).addReg(Mips::ZERO).addImm(MaskImm);
- BuildMI(BB, dl, TII->get(Mips::SLL), Mask).addReg(Tmp3).addReg(Shift);
+ BuildMI(BB, dl, TII->get(Mips::ADDiu), MaskLSB2)
+ .addReg(Mips::ZERO).addImm(-4);
+ BuildMI(BB, dl, TII->get(Mips::AND), AlignedAddr)
+ .addReg(Ptr).addReg(MaskLSB2);
+ BuildMI(BB, dl, TII->get(Mips::ANDi), PtrLSB2).addReg(Ptr).addImm(3);
+ BuildMI(BB, dl, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3);
+ BuildMI(BB, dl, TII->get(Mips::ORi), MaskUpper)
+ .addReg(Mips::ZERO).addImm(MaskImm);
+ BuildMI(BB, dl, TII->get(Mips::SLLV), Mask)
+ .addReg(ShiftAmt).addReg(MaskUpper);
BuildMI(BB, dl, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask);
- BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp4).addReg(Oldval).addImm(MaskImm);
- BuildMI(BB, dl, TII->get(Mips::SLL), Oldval2).addReg(Tmp4).addReg(Shift);
- BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp5).addReg(Newval).addImm(MaskImm);
- BuildMI(BB, dl, TII->get(Mips::SLL), Newval2).addReg(Tmp5).addReg(Shift);
- BB->addSuccessor(loop1MBB);
+ BuildMI(BB, dl, TII->get(Mips::ANDi), MaskedCmpVal)
+ .addReg(CmpVal).addImm(MaskImm);
+ BuildMI(BB, dl, TII->get(Mips::SLLV), ShiftedCmpVal)
+ .addReg(ShiftAmt).addReg(MaskedCmpVal);
+ BuildMI(BB, dl, TII->get(Mips::ANDi), MaskedNewVal)
+ .addReg(NewVal).addImm(MaskImm);
+ BuildMI(BB, dl, TII->get(Mips::SLLV), ShiftedNewVal)
+ .addReg(ShiftAmt).addReg(MaskedNewVal);
// loop1MBB:
- // ll oldval3,0(addr)
- // and oldval4,oldval3,mask
- // bne oldval4,oldval2,exitMBB
+ // ll oldval,0(alginedaddr)
+ // and maskedoldval0,oldval,mask
+ // bne maskedoldval0,shiftedcmpval,sinkMBB
BB = loop1MBB;
- BuildMI(BB, dl, TII->get(Mips::LL), Oldval3).addReg(Addr).addImm(0);
- BuildMI(BB, dl, TII->get(Mips::AND), Oldval4).addReg(Oldval3).addReg(Mask);
+ BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0);
+ BuildMI(BB, dl, TII->get(Mips::AND), MaskedOldVal0)
+ .addReg(OldVal).addReg(Mask);
BuildMI(BB, dl, TII->get(Mips::BNE))
- .addReg(Oldval4).addReg(Oldval2).addMBB(exitMBB);
- BB->addSuccessor(exitMBB);
- BB->addSuccessor(loop2MBB);
+ .addReg(MaskedOldVal0).addReg(ShiftedCmpVal).addMBB(sinkMBB);
// loop2MBB:
- // and tmp6,oldval3,mask2
- // or tmp7,tmp6,newval2
- // sc tmp7,0(addr)
- // beq tmp7,$0,loop1MBB
+ // and maskedoldval1,oldval,mask2
+ // or storeval,maskedoldval1,shiftednewval
+ // sc success,storeval,0(alignedaddr)
+ // beq success,$0,loop1MBB
BB = loop2MBB;
- BuildMI(BB, dl, TII->get(Mips::AND), Tmp6).addReg(Oldval3).addReg(Mask2);
- BuildMI(BB, dl, TII->get(Mips::OR), Tmp7).addReg(Tmp6).addReg(Newval2);
- BuildMI(BB, dl, TII->get(Mips::SC), Tmp7)
- .addReg(Tmp7).addReg(Addr).addImm(0);
+ BuildMI(BB, dl, TII->get(Mips::AND), MaskedOldVal1)
+ .addReg(OldVal).addReg(Mask2);
+ BuildMI(BB, dl, TII->get(Mips::OR), StoreVal)
+ .addReg(MaskedOldVal1).addReg(ShiftedNewVal);
+ BuildMI(BB, dl, TII->get(Mips::SC), Success)
+ .addReg(StoreVal).addReg(AlignedAddr).addImm(0);
BuildMI(BB, dl, TII->get(Mips::BEQ))
- .addReg(Tmp7).addReg(Mips::ZERO).addMBB(loop1MBB);
- BB->addSuccessor(loop1MBB);
- BB->addSuccessor(exitMBB);
+ .addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB);
- // exitMBB:
- // srl tmp8,oldval4,shift
- // sll tmp9,tmp8,24
- // sra dest,tmp9,24
- BB = exitMBB;
+ // sinkMBB:
+ // srl srlres,maskedoldval0,shiftamt
+ // sll sllres,srlres,24
+ // sra dest,sllres,24
+ BB = sinkMBB;
int64_t ShiftImm = (Size == 1) ? 24 : 16;
- // reverse order
- BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SRA), Dest)
- .addReg(Tmp9).addImm(ShiftImm);
- BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SLL), Tmp9)
- .addReg(Tmp8).addImm(ShiftImm);
- BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SRL), Tmp8)
- .addReg(Oldval4).addReg(Shift);
+
+ BuildMI(BB, dl, TII->get(Mips::SRLV), SrlRes)
+ .addReg(ShiftAmt).addReg(MaskedOldVal0);
+ BuildMI(BB, dl, TII->get(Mips::SLL), SllRes)
+ .addReg(SrlRes).addImm(ShiftImm);
+ BuildMI(BB, dl, TII->get(Mips::SRA), Dest)
+ .addReg(SllRes).addImm(ShiftImm);
MI->eraseFromParent(); // The instruction is gone now.
- return BB;
+ return exitMBB;
}
//===----------------------------------------------------------------------===//
@@ -1267,9 +1385,9 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op,
SelectionDAG &DAG) const {
// FIXME there isn't actually debug info here
DebugLoc dl = Op.getDebugLoc();
- const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
+ const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
- if (getTargetMachine().getRelocationModel() != Reloc::PIC_) {
+ if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) {
SDVTList VTs = DAG.getVTList(MVT::i32);
MipsTargetObjectFile &TLOF = (MipsTargetObjectFile&)getObjFileLowering();
@@ -1292,21 +1410,26 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op,
return DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo);
}
- SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0,
- MipsII::MO_GOT);
- GA = DAG.getNode(MipsISD::WrapperPIC, dl, MVT::i32, GA);
- SDValue ResNode = DAG.getLoad(MVT::i32, dl,
+ EVT ValTy = Op.getValueType();
+ bool HasGotOfst = (GV->hasInternalLinkage() ||
+ (GV->hasLocalLinkage() && !isa<Function>(GV)));
+ unsigned GotFlag = IsN64 ?
+ (HasGotOfst ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT_DISP) :
+ MipsII::MO_GOT;
+ SDValue GA = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0, GotFlag);
+ GA = DAG.getNode(MipsISD::WrapperPIC, dl, ValTy, GA);
+ SDValue ResNode = DAG.getLoad(ValTy, dl,
DAG.getEntryNode(), GA, MachinePointerInfo(),
false, false, 0);
// On functions and global targets not internal linked only
// a load from got/GP is necessary for PIC to work.
- if (!GV->hasInternalLinkage() &&
- (!GV->hasLocalLinkage() || isa<Function>(GV)))
+ if (!HasGotOfst)
return ResNode;
- SDValue GALo = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0,
- MipsII::MO_ABS_LO);
- SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, GALo);
- return DAG.getNode(ISD::ADD, dl, MVT::i32, ResNode, Lo);
+ SDValue GALo = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0,
+ IsN64 ? MipsII::MO_GOT_OFST :
+ MipsII::MO_ABS_LO);
+ SDValue Lo = DAG.getNode(MipsISD::Lo, dl, ValTy, GALo);
+ return DAG.getNode(ISD::ADD, dl, ValTy, ResNode, Lo);
}
SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op,
@@ -1361,11 +1484,11 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
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);
std::pair<SDValue, SDValue> CallResult =
LowerCallTo(DAG.getEntryNode(),
- (const Type *) Type::getInt32Ty(*DAG.getContext()),
+ (Type *) Type::getInt32Ty(*DAG.getContext()),
false, false, false, false, 0, CallingConv::C, false, true,
DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG,
dl);
@@ -1557,6 +1680,25 @@ LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
return FrameAddr;
}
+// TODO: set SType according to the desired memory barrier behavior.
+SDValue MipsTargetLowering::LowerMEMBARRIER(SDValue Op,
+ SelectionDAG& DAG) const {
+ unsigned SType = 0;
+ DebugLoc dl = Op.getDebugLoc();
+ return DAG.getNode(MipsISD::Sync, dl, MVT::Other, Op.getOperand(0),
+ DAG.getConstant(SType, MVT::i32));
+}
+
+SDValue MipsTargetLowering::LowerATOMIC_FENCE(SDValue Op,
+ SelectionDAG& DAG) const {
+ // FIXME: Need pseudo-fence for 'singlethread' fences
+ // FIXME: Set SType for weaker fences where supported/appropriate.
+ unsigned SType = 0;
+ DebugLoc dl = Op.getDebugLoc();
+ return DAG.getNode(MipsISD::Sync, dl, MVT::Other, Op.getOperand(0),
+ DAG.getConstant(SType, MVT::i32));
+}
+
//===----------------------------------------------------------------------===//
// Calling Convention Implementation
//===----------------------------------------------------------------------===//
@@ -1679,55 +1821,109 @@ static const unsigned O32IntRegs[] = {
Mips::A0, Mips::A1, Mips::A2, Mips::A3
};
+// Return next O32 integer argument register.
+static unsigned getNextIntArgReg(unsigned Reg) {
+ assert((Reg == Mips::A0) || (Reg == Mips::A2));
+ return (Reg == Mips::A0) ? Mips::A1 : Mips::A3;
+}
+
// Write ByVal Arg to arg registers and stack.
static void
-WriteByValArg(SDValue& Chain, DebugLoc dl,
+WriteByValArg(SDValue& ByValChain, SDValue Chain, DebugLoc dl,
SmallVector<std::pair<unsigned, SDValue>, 16>& RegsToPass,
SmallVector<SDValue, 8>& MemOpChains, int& LastFI,
MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg,
const CCValAssign &VA, const ISD::ArgFlagsTy& Flags,
- MVT PtrType) {
- unsigned FirstWord = VA.getLocMemOffset() / 4;
- unsigned NumWords = (Flags.getByValSize() + 3) / 4;
- unsigned LastWord = FirstWord + NumWords;
- unsigned CurWord;
-
- // copy the first 4 words of byval arg to registers A0 - A3
- for (CurWord = FirstWord; CurWord < std::min(LastWord, O32IntRegsSize);
- ++CurWord) {
+ MVT PtrType, bool isLittle) {
+ unsigned LocMemOffset = VA.getLocMemOffset();
+ unsigned Offset = 0;
+ uint32_t RemainingSize = Flags.getByValSize();
+ unsigned ByValAlign = Flags.getByValAlign();
+
+ // Copy the first 4 words of byval arg to registers A0 - A3.
+ // FIXME: Use a stricter alignment if it enables better optimization in passes
+ // run later.
+ for (; RemainingSize >= 4 && LocMemOffset < 4 * 4;
+ Offset += 4, RemainingSize -= 4, LocMemOffset += 4) {
SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg,
- DAG.getConstant((CurWord - FirstWord) * 4,
- MVT::i32));
+ DAG.getConstant(Offset, MVT::i32));
SDValue LoadVal = DAG.getLoad(MVT::i32, dl, Chain, LoadPtr,
MachinePointerInfo(),
- false, false, 0);
+ false, false, std::min(ByValAlign,
+ (unsigned )4));
MemOpChains.push_back(LoadVal.getValue(1));
- unsigned DstReg = O32IntRegs[CurWord];
+ unsigned DstReg = O32IntRegs[LocMemOffset / 4];
RegsToPass.push_back(std::make_pair(DstReg, LoadVal));
}
- // copy remaining part of byval arg to stack.
- if (CurWord < LastWord) {
- unsigned SizeInBytes = (LastWord - CurWord) * 4;
- SDValue Src = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg,
- DAG.getConstant((CurWord - FirstWord) * 4,
- MVT::i32));
- LastFI = MFI->CreateFixedObject(SizeInBytes, CurWord * 4, true);
- SDValue Dst = DAG.getFrameIndex(LastFI, PtrType);
- Chain = DAG.getMemcpy(Chain, dl, Dst, Src,
- DAG.getConstant(SizeInBytes, MVT::i32),
- /*Align*/4,
- /*isVolatile=*/false, /*AlwaysInline=*/false,
- MachinePointerInfo(0), MachinePointerInfo(0));
- MemOpChains.push_back(Chain);
+ if (RemainingSize == 0)
+ return;
+
+ // If there still is a register available for argument passing, write the
+ // remaining part of the structure to it using subword loads and shifts.
+ if (LocMemOffset < 4 * 4) {
+ assert(RemainingSize <= 3 && RemainingSize >= 1 &&
+ "There must be one to three bytes remaining.");
+ unsigned LoadSize = (RemainingSize == 3 ? 2 : RemainingSize);
+ SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg,
+ DAG.getConstant(Offset, MVT::i32));
+ unsigned Alignment = std::min(ByValAlign, (unsigned )4);
+ SDValue LoadVal = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, Chain,
+ LoadPtr, MachinePointerInfo(),
+ MVT::getIntegerVT(LoadSize * 8), false,
+ false, Alignment);
+ MemOpChains.push_back(LoadVal.getValue(1));
+
+ // If target is big endian, shift it to the most significant half-word or
+ // byte.
+ if (!isLittle)
+ LoadVal = DAG.getNode(ISD::SHL, dl, MVT::i32, LoadVal,
+ DAG.getConstant(32 - LoadSize * 8, MVT::i32));
+
+ Offset += LoadSize;
+ RemainingSize -= LoadSize;
+
+ // Read second subword if necessary.
+ if (RemainingSize != 0) {
+ assert(RemainingSize == 1 && "There must be one byte remaining.");
+ LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg,
+ DAG.getConstant(Offset, MVT::i32));
+ unsigned Alignment = std::min(ByValAlign, (unsigned )2);
+ SDValue Subword = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, Chain,
+ LoadPtr, MachinePointerInfo(),
+ MVT::i8, false, false, Alignment);
+ MemOpChains.push_back(Subword.getValue(1));
+ // Insert the loaded byte to LoadVal.
+ // FIXME: Use INS if supported by target.
+ unsigned ShiftAmt = isLittle ? 16 : 8;
+ SDValue Shift = DAG.getNode(ISD::SHL, dl, MVT::i32, Subword,
+ DAG.getConstant(ShiftAmt, MVT::i32));
+ LoadVal = DAG.getNode(ISD::OR, dl, MVT::i32, LoadVal, Shift);
+ }
+
+ unsigned DstReg = O32IntRegs[LocMemOffset / 4];
+ RegsToPass.push_back(std::make_pair(DstReg, LoadVal));
+ return;
}
+
+ // Create a fixed object on stack at offset LocMemOffset and copy
+ // remaining part of byval arg to it using memcpy.
+ SDValue Src = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg,
+ DAG.getConstant(Offset, MVT::i32));
+ LastFI = MFI->CreateFixedObject(RemainingSize, LocMemOffset, true);
+ SDValue Dst = DAG.getFrameIndex(LastFI, PtrType);
+ ByValChain = DAG.getMemcpy(ByValChain, dl, Dst, Src,
+ DAG.getConstant(RemainingSize, MVT::i32),
+ std::min(ByValAlign, (unsigned)4),
+ /*isVolatile=*/false, /*AlwaysInline=*/false,
+ MachinePointerInfo(0), MachinePointerInfo(0));
}
/// LowerCall - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
/// TODO: isTailCall.
SDValue
-MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
+MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee,
CallingConv::ID CallConv, bool isVarArg,
bool &isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs,
@@ -1757,8 +1953,13 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
// Get a count of how many bytes are to be pushed on the stack.
unsigned NextStackOffset = CCInfo.getNextStackOffset();
- Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NextStackOffset,
- true));
+ // Chain is the output chain of the last Load/Store or CopyToReg node.
+ // ByValChain is the output chain of the last Memcpy node created for copying
+ // byval arguments to the stack.
+ SDValue Chain, CallSeqStart, ByValChain;
+ SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, true);
+ Chain = CallSeqStart = DAG.getCALLSEQ_START(InChain, NextStackOffsetVal);
+ ByValChain = InChain;
// If this is the first call, create a stack frame object that points to
// a location to which .cprestore saves $gp.
@@ -1818,8 +2019,10 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
Arg, DAG.getConstant(1, MVT::i32));
if (!Subtarget->isLittle())
std::swap(Lo, Hi);
- RegsToPass.push_back(std::make_pair(VA.getLocReg(), Lo));
- RegsToPass.push_back(std::make_pair(VA.getLocReg()+1, Hi));
+ unsigned LocRegLo = VA.getLocReg();
+ unsigned LocRegHigh = getNextIntArgReg(LocRegLo);
+ RegsToPass.push_back(std::make_pair(LocRegLo, Lo));
+ RegsToPass.push_back(std::make_pair(LocRegHigh, Hi));
continue;
}
}
@@ -1852,8 +2055,8 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
"No support for ByVal args by ABIs other than O32 yet.");
assert(Flags.getByValSize() &&
"ByVal args of size 0 should have been ignored by front-end.");
- WriteByValArg(Chain, dl, RegsToPass, MemOpChains, LastFI, MFI, DAG, Arg,
- VA, Flags, getPointerTy());
+ WriteByValArg(ByValChain, Chain, dl, RegsToPass, MemOpChains, LastFI, MFI,
+ DAG, Arg, VA, Flags, getPointerTy(), Subtarget->isLittle());
continue;
}
@@ -1875,6 +2078,12 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
if (LastFI)
MipsFI->extendOutArgFIRange(FirstFI, LastFI);
+ // If a memcpy has been created to copy a byval arg to a stack, replace the
+ // chain input of CallSeqStart with ByValChain.
+ if (InChain != ByValChain)
+ DAG.UpdateNodeOperands(CallSeqStart.getNode(), ByValChain,
+ NextStackOffsetVal);
+
// Transform all store nodes into one single node because all store
// nodes are independent of each other.
if (!MemOpChains.empty())
@@ -2071,12 +2280,13 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
if (RegVT == MVT::i32)
RC = Mips::CPURegsRegisterClass;
+ else if (RegVT == MVT::i64)
+ RC = Mips::CPU64RegsRegisterClass;
else if (RegVT == MVT::f32)
RC = Mips::FGR32RegisterClass;
- else if (RegVT == MVT::f64) {
- if (!Subtarget->isSingleFloat())
- RC = Mips::AFGR64RegisterClass;
- } else
+ else if (RegVT == MVT::f64)
+ RC = HasMips64 ? Mips::FGR64RegisterClass : Mips::AFGR64RegisterClass;
+ else
llvm_unreachable("RegVT not supported by FormalArguments Lowering");
// Transform the arguments stored on
@@ -2105,7 +2315,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
ArgValue = DAG.getNode(ISD::BITCAST, dl, MVT::f32, ArgValue);
if (RegVT == MVT::i32 && VA.getValVT() == MVT::f64) {
unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(),
- VA.getLocReg()+1, RC);
+ getNextIntArgReg(ArgReg), RC);
SDValue ArgValue2 = DAG.getCopyFromReg(Chain, dl, Reg2, RegVT);
if (!Subtarget->isLittle())
std::swap(ArgValue, ArgValue2);
@@ -2313,7 +2523,7 @@ MipsTargetLowering::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:
diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h
index bda26a2..4be3fed5 100644
--- a/lib/Target/Mips/MipsISelLowering.h
+++ b/lib/Target/Mips/MipsISelLowering.h
@@ -81,7 +81,12 @@ namespace llvm {
WrapperPIC,
- DynAlloc
+ DynAlloc,
+
+ Sync,
+
+ Ext,
+ Ins
};
}
@@ -93,6 +98,8 @@ namespace llvm {
public:
explicit MipsTargetLowering(MipsTargetMachine &TM);
+ virtual bool allowsUnalignedMemoryAccesses (EVT VT) const;
+
/// LowerOperation - Provide custom lowering hooks for some operations.
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
@@ -101,13 +108,14 @@ namespace llvm {
virtual const char *getTargetNodeName(unsigned Opcode) const;
/// getSetCCResultType - get the ISD::SETCC result ValueType
- MVT::SimpleValueType getSetCCResultType(EVT VT) const;
+ EVT getSetCCResultType(EVT VT) const;
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
private:
// Subtarget Info
const MipsSubtarget *Subtarget;
-
+
+ bool HasMips64, IsN64;
// Lower Operand helpers
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
@@ -128,6 +136,8 @@ namespace llvm {
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const;
+ SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const;
virtual SDValue
LowerFormalArguments(SDValue Chain,
diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td
index 021c167..2fb9d18 100644
--- a/lib/Target/Mips/MipsInstrFPU.td
+++ b/lib/Target/Mips/MipsInstrFPU.td
@@ -27,7 +27,7 @@
def SDT_MipsFPBrcond : SDTypeProfile<0, 2, [SDTCisInt<0>,
SDTCisVT<1, OtherVT>]>;
def SDT_MipsFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<1>,
- SDTCisInt<2>]>;
+ SDTCisVT<2, i32>]>;
def SDT_MipsCMovFP : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
SDTCisSameAs<1, 2>]>;
def SDT_MipsBuildPairF64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>,
@@ -35,12 +35,11 @@ def SDT_MipsBuildPairF64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>,
SDTCisSameAs<1, 2>]>;
def SDT_MipsExtractElementF64 : SDTypeProfile<1, 2, [SDTCisVT<0, i32>,
SDTCisVT<1, f64>,
- SDTCisVT<0, i32>]>;
+ SDTCisVT<2, i32>]>;
def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp, [SDNPOutGlue]>;
def MipsCMovFP_T : SDNode<"MipsISD::CMovFP_T", SDT_MipsCMovFP, [SDNPInGlue]>;
def MipsCMovFP_F : SDNode<"MipsISD::CMovFP_F", SDT_MipsCMovFP, [SDNPInGlue]>;
-def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInGlue]>;
def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond,
[SDNPHasChain, SDNPOptInGlue]>;
def MipsBuildPairF64 : SDNode<"MipsISD::BuildPairF64", SDT_MipsBuildPairF64>;
@@ -55,10 +54,10 @@ let PrintMethod = "printFCCOperand" in
// Feature predicates.
//===----------------------------------------------------------------------===//
-def In32BitMode : Predicate<"!Subtarget.isFP64bit()">;
+def IsFP64bit : Predicate<"Subtarget.isFP64bit()">;
+def NotFP64bit : Predicate<"!Subtarget.isFP64bit()">;
def IsSingleFloat : Predicate<"Subtarget.isSingleFloat()">;
def IsNotSingleFloat : Predicate<"!Subtarget.isSingleFloat()">;
-def IsNotMipsI : Predicate<"!Subtarget.isMips1()">;
//===----------------------------------------------------------------------===//
// Instruction Class Templates
@@ -74,97 +73,87 @@ def IsNotMipsI : Predicate<"!Subtarget.isMips1()">;
// Only S32 and D32 are supported right now.
//===----------------------------------------------------------------------===//
-multiclass FFR1_1<bits<6> funct, string asmstr>
-{
- def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), (ins FGR32:$fs),
- !strconcat(asmstr, ".s\t$fd, $fs"), []>;
-
- def _D32 : FFR<0x11, funct, 0x1, (outs FGR32:$fd), (ins AFGR64:$fs),
- !strconcat(asmstr, ".d\t$fd, $fs"), []>, Requires<[In32BitMode]>;
+// FP load.
+class FPLoad<bits<6> op, string opstr, PatFrag FOp, RegisterClass RC,
+ Operand MemOpnd>:
+ FFI<op, (outs RC:$ft), (ins MemOpnd:$base),
+ !strconcat(opstr, "\t$ft, $base"), [(set RC:$ft, (FOp addr:$base))]>;
+
+// FP store.
+class FPStore<bits<6> op, string opstr, PatFrag FOp, RegisterClass RC,
+ Operand MemOpnd>:
+ FFI<op, (outs), (ins RC:$ft, MemOpnd:$base),
+ !strconcat(opstr, "\t$ft, $base"), [(store RC:$ft, addr:$base)]>;
+
+// Instructions that convert an FP value to 32-bit fixed point.
+multiclass FFR1_W_M<bits<6> funct, string opstr> {
+ def _S : FFR1<funct, 16, opstr, "w.s", FGR32, FGR32>;
+ def _D32 : FFR1<funct, 17, opstr, "w.d", FGR32, AFGR64>,
+ Requires<[NotFP64bit]>;
+ def _D64 : FFR1<funct, 17, opstr, "w.d", FGR32, FGR64>,
+ Requires<[IsFP64bit]>;
}
-multiclass FFR1_2<bits<6> funct, string asmstr, SDNode FOp>
-{
- def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), (ins FGR32:$fs),
- !strconcat(asmstr, ".s\t$fd, $fs"),
- [(set FGR32:$fd, (FOp FGR32:$fs))]>;
-
- def _D32 : FFR<0x11, funct, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs),
- !strconcat(asmstr, ".d\t$fd, $fs"),
- [(set AFGR64:$fd, (FOp AFGR64:$fs))]>, Requires<[In32BitMode]>;
+// Instructions that convert an FP value to 64-bit fixed point.
+let Predicates = [IsFP64bit] in
+multiclass FFR1_L_M<bits<6> funct, string opstr> {
+ def _S : FFR1<funct, 16, opstr, "l.s", FGR64, FGR32>;
+ def _D64 : FFR1<funct, 17, opstr, "l.d", FGR64, FGR64>;
}
-class FFR1_3<bits<6> funct, bits<5> fmt, RegisterClass RcSrc,
- RegisterClass RcDst, string asmstr>:
- FFR<0x11, funct, fmt, (outs RcSrc:$fd), (ins RcDst:$fs),
- !strconcat(asmstr, "\t$fd, $fs"), []>;
-
+// FP-to-FP conversion instructions.
+multiclass FFR1P_M<bits<6> funct, string opstr, SDNode OpNode> {
+ def _S : FFR1P<funct, 16, opstr, "s", FGR32, FGR32, OpNode>;
+ def _D32 : FFR1P<funct, 17, opstr, "d", AFGR64, AFGR64, OpNode>,
+ Requires<[NotFP64bit]>;
+ def _D64 : FFR1P<funct, 17, opstr, "d", FGR64, FGR64, OpNode>,
+ Requires<[IsFP64bit]>;
+}
-multiclass FFR1_4<bits<6> funct, string asmstr, SDNode FOp, bit isComm = 0> {
+multiclass FFR2P_M<bits<6> funct, string opstr, SDNode OpNode, bit isComm = 0> {
let isCommutable = isComm in {
- def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd),
- (ins FGR32:$fs, FGR32:$ft),
- !strconcat(asmstr, ".s\t$fd, $fs, $ft"),
- [(set FGR32:$fd, (FOp FGR32:$fs, FGR32:$ft))]>;
-
- def _D32 : FFR<0x11, funct, 0x1, (outs AFGR64:$fd),
- (ins AFGR64:$fs, AFGR64:$ft),
- !strconcat(asmstr, ".d\t$fd, $fs, $ft"),
- [(set AFGR64:$fd, (FOp AFGR64:$fs, AFGR64:$ft))]>,
- Requires<[In32BitMode]>;
+ def _S : FFR2P<funct, 16, opstr, "s", FGR32, OpNode>;
+ def _D32 : FFR2P<funct, 17, opstr, "d", AFGR64, OpNode>,
+ Requires<[NotFP64bit]>;
+ def _D64 : FFR2P<funct, 17, opstr, "d", FGR64, OpNode>,
+ Requires<[IsFP64bit]>;
}
}
//===----------------------------------------------------------------------===//
// Floating Point Instructions
//===----------------------------------------------------------------------===//
+defm ROUND_W : FFR1_W_M<0xc, "round">;
+defm ROUND_L : FFR1_L_M<0x8, "round">;
+defm TRUNC_W : FFR1_W_M<0xd, "trunc">;
+defm TRUNC_L : FFR1_L_M<0x9, "trunc">;
+defm CEIL_W : FFR1_W_M<0xe, "ceil">;
+defm CEIL_L : FFR1_L_M<0xa, "ceil">;
+defm FLOOR_W : FFR1_W_M<0xf, "floor">;
+defm FLOOR_L : FFR1_L_M<0xb, "floor">;
+defm CVT_W : FFR1_W_M<0x24, "cvt">;
+defm CVT_L : FFR1_L_M<0x25, "cvt">;
+
+def CVT_S_W : FFR1<0x20, 20, "cvt", "s.w", FGR32, FGR32>;
+
+let Predicates = [NotFP64bit] in {
+ def CVT_S_D32 : FFR1<0x20, 17, "cvt", "s.d", FGR32, AFGR64>;
+ def CVT_D32_W : FFR1<0x21, 20, "cvt", "d.w", AFGR64, FGR32>;
+ def CVT_D32_S : FFR1<0x21, 16, "cvt", "d.s", AFGR64, FGR32>;
+}
-let ft = 0 in {
- defm FLOOR_W : FFR1_1<0b001111, "floor.w">;
- defm CEIL_W : FFR1_1<0b001110, "ceil.w">;
- defm ROUND_W : FFR1_1<0b001100, "round.w">;
- defm TRUNC_W : FFR1_1<0b001101, "trunc.w">;
- defm CVTW : FFR1_1<0b100100, "cvt.w">;
-
- defm FABS : FFR1_2<0b000101, "abs", fabs>;
- defm FNEG : FFR1_2<0b000111, "neg", fneg>;
- defm FSQRT : FFR1_2<0b000100, "sqrt", fsqrt>;
-
- /// Convert to Single Precison
- def CVTS_W32 : FFR1_3<0b100000, 0x2, FGR32, FGR32, "cvt.s.w">;
-
- let Predicates = [IsNotSingleFloat] in {
- /// Ceil to long signed integer
- def CEIL_LS : FFR1_3<0b001010, 0x0, FGR32, FGR32, "ceil.l">;
- def CEIL_LD : FFR1_3<0b001010, 0x1, AFGR64, AFGR64, "ceil.l">;
-
- /// Round to long signed integer
- def ROUND_LS : FFR1_3<0b001000, 0x0, FGR32, FGR32, "round.l">;
- def ROUND_LD : FFR1_3<0b001000, 0x1, AFGR64, AFGR64, "round.l">;
-
- /// Floor to long signed integer
- def FLOOR_LS : FFR1_3<0b001011, 0x0, FGR32, FGR32, "floor.l">;
- def FLOOR_LD : FFR1_3<0b001011, 0x1, AFGR64, AFGR64, "floor.l">;
-
- /// Trunc to long signed integer
- def TRUNC_LS : FFR1_3<0b001001, 0x0, FGR32, FGR32, "trunc.l">;
- def TRUNC_LD : FFR1_3<0b001001, 0x1, AFGR64, AFGR64, "trunc.l">;
-
- /// Convert to long signed integer
- def CVTL_S : FFR1_3<0b100101, 0x0, FGR32, FGR32, "cvt.l">;
- def CVTL_D : FFR1_3<0b100101, 0x1, AFGR64, AFGR64, "cvt.l">;
-
- /// Convert to Double Precison
- def CVTD_S32 : FFR1_3<0b100001, 0x0, AFGR64, FGR32, "cvt.d.s">;
- def CVTD_W32 : FFR1_3<0b100001, 0x2, AFGR64, FGR32, "cvt.d.w">;
- def CVTD_L32 : FFR1_3<0b100001, 0x3, AFGR64, AFGR64, "cvt.d.l">;
-
- /// Convert to Single Precison
- def CVTS_D32 : FFR1_3<0b100000, 0x1, FGR32, AFGR64, "cvt.s.d">;
- def CVTS_L32 : FFR1_3<0b100000, 0x3, FGR32, AFGR64, "cvt.s.l">;
- }
+let Predicates = [IsFP64bit] in {
+ def CVT_S_D64 : FFR1<0x20, 17, "cvt", "s.d", FGR32, FGR64>;
+ def CVT_S_L : FFR1<0x20, 21, "cvt", "s.l", FGR32, FGR64>;
+ def CVT_D64_W : FFR1<0x21, 20, "cvt", "d.w", FGR64, FGR32>;
+ def CVT_D64_S : FFR1<0x21, 16, "cvt", "d.s", FGR64, FGR32>;
+ def CVT_D64_L : FFR1<0x21, 21, "cvt", "d.l", FGR64, FGR64>;
}
+defm FABS : FFR1P_M<0x5, "abs", fabs>;
+defm FNEG : FFR1P_M<0x7, "neg", fneg>;
+defm FSQRT : FFR1P_M<0x4, "sqrt", fsqrt>;
+
// The odd-numbered registers are only referenced when doing loads,
// stores, and moves between floating-point and integer registers.
// When defining instructions, we reference all 32-bit registers,
@@ -178,37 +167,46 @@ let fd = 0 in {
"ctc1\t$fs, $rt", []>;
def MFC1 : FFR<0x11, 0x00, 0x00, (outs CPURegs:$rt), (ins FGR32:$fs),
- "mfc1\t$rt, $fs", []>;
+ "mfc1\t$rt, $fs",
+ [(set CPURegs:$rt, (bitconvert FGR32:$fs))]>;
def MTC1 : FFR<0x11, 0x00, 0x04, (outs FGR32:$fs), (ins CPURegs:$rt),
- "mtc1\t$rt, $fs", []>;
+ "mtc1\t$rt, $fs",
+ [(set FGR32:$fs, (bitconvert CPURegs:$rt))]>;
}
-def FMOV_S32 : FFR<0x11, 0b000110, 0x0, (outs FGR32:$fd), (ins FGR32:$fs),
- "mov.s\t$fd, $fs", []>;
-def FMOV_D32 : FFR<0x11, 0b000110, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs),
- "mov.d\t$fd, $fs", []>;
+def FMOV_S : FFR1<0x6, 16, "mov", "s", FGR32, FGR32>;
+def FMOV_D32 : FFR1<0x6, 17, "mov", "d", AFGR64, AFGR64>,
+ Requires<[NotFP64bit]>;
+def FMOV_D64 : FFR1<0x6, 17, "mov", "d", FGR64, FGR64>,
+ Requires<[IsFP64bit]>;
/// Floating Point Memory Instructions
-let Predicates = [IsNotSingleFloat, IsNotMipsI] in {
- def LDC1 : FFI<0b110101, (outs AFGR64:$ft), (ins mem:$addr),
- "ldc1\t$ft, $addr", [(set AFGR64:$ft, (load addr:$addr))]>;
-
- def SDC1 : FFI<0b111101, (outs), (ins AFGR64:$ft, mem:$addr),
- "sdc1\t$ft, $addr", [(store AFGR64:$ft, addr:$addr)]>;
+let Predicates = [IsN64] in {
+ def LWC1_P8 : FPLoad<0x31, "lwc1", load, FGR32, mem64>;
+ def SWC1_P8 : FPStore<0x39, "swc1", store, FGR32, mem64>;
+ def LDC164_P8 : FPLoad<0x35, "ldc1", load, FGR64, mem64>;
+ def SDC164_P8 : FPStore<0x3d, "sdc1", store, FGR64, mem64>;
}
-// LWC1 and SWC1 can always be emitted with odd registers.
-def LWC1 : FFI<0b110001, (outs FGR32:$ft), (ins mem:$addr), "lwc1\t$ft, $addr",
- [(set FGR32:$ft, (load addr:$addr))]>;
-def SWC1 : FFI<0b111001, (outs), (ins FGR32:$ft, mem:$addr),
- "swc1\t$ft, $addr", [(store FGR32:$ft, addr:$addr)]>;
+let Predicates = [NotN64] in {
+ def LWC1 : FPLoad<0x31, "lwc1", load, FGR32, mem>;
+ def SWC1 : FPStore<0x39, "swc1", store, FGR32, mem>;
+ let Predicates = [HasMips64] in {
+ def LDC164 : FPLoad<0x35, "ldc1", load, FGR64, mem>;
+ def SDC164 : FPStore<0x3d, "sdc1", store, FGR64, mem>;
+ }
+ let Predicates = [NotMips64] in {
+ def LDC1 : FPLoad<0x35, "ldc1", load, AFGR64, mem>;
+ def SDC1 : FPStore<0x3d, "sdc1", store, AFGR64, mem>;
+ }
+}
/// Floating-point Aritmetic
-defm FADD : FFR1_4<0x10, "add", fadd, 1>;
-defm FDIV : FFR1_4<0x03, "div", fdiv>;
-defm FMUL : FFR1_4<0x02, "mul", fmul, 1>;
-defm FSUB : FFR1_4<0x01, "sub", fsub>;
+defm FADD : FFR2P_M<0x10, "add", fadd, 1>;
+defm FDIV : FFR2P_M<0x03, "div", fdiv>;
+defm FMUL : FFR2P_M<0x02, "mul", fmul, 1>;
+defm FSUB : FFR2P_M<0x01, "sub", fsub>;
//===----------------------------------------------------------------------===//
// Floating Point Branch Codes
@@ -217,8 +215,6 @@ defm FSUB : FFR1_4<0x01, "sub", fsub>;
// They must be kept in synch.
def MIPS_BRANCH_F : PatLeaf<(i32 0)>;
def MIPS_BRANCH_T : PatLeaf<(i32 1)>;
-def MIPS_BRANCH_FL : PatLeaf<(i32 2)>;
-def MIPS_BRANCH_TL : PatLeaf<(i32 3)>;
/// Floating Point Branch of False/True (Likely)
let isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in
@@ -228,8 +224,6 @@ let isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in
def BC1F : FBRANCH<MIPS_BRANCH_F, "bc1f">;
def BC1T : FBRANCH<MIPS_BRANCH_T, "bc1t">;
-def BC1FL : FBRANCH<MIPS_BRANCH_FL, "bc1fl">;
-def BC1TL : FBRANCH<MIPS_BRANCH_TL, "bc1tl">;
//===----------------------------------------------------------------------===//
// Floating Point Flag Conditions
@@ -254,7 +248,7 @@ def MIPS_FCOND_LE : PatLeaf<(i32 14)>;
def MIPS_FCOND_NGT : PatLeaf<(i32 15)>;
/// Floating Point Compare
-let hasDelaySlot = 1, Defs=[FCR31] in {
+let Defs=[FCR31] in {
def FCMP_S32 : FCC<0x0, (outs), (ins FGR32:$fs, FGR32:$ft, condcode:$cc),
"c.$cc.s\t$fs, $ft",
[(MipsFPCmp FGR32:$fs, FGR32:$ft, imm:$cc)]>;
@@ -262,7 +256,7 @@ let hasDelaySlot = 1, Defs=[FCR31] in {
def FCMP_D32 : FCC<0x1, (outs), (ins AFGR64:$fs, AFGR64:$ft, condcode:$cc),
"c.$cc.d\t$fs, $ft",
[(MipsFPCmp AFGR64:$fs, AFGR64:$ft, imm:$cc)]>,
- Requires<[In32BitMode]>;
+ Requires<[NotFP64bit]>;
}
@@ -280,7 +274,7 @@ class CondMovIntFP<RegisterClass RC, bits<5> fmt, bits<6> func,
def MOVZ_S : CondMovIntFP<FGR32, 16, 18, "movz.s">;
def MOVN_S : CondMovIntFP<FGR32, 16, 19, "movn.s">;
-let Predicates = [In32BitMode] in {
+let Predicates = [NotFP64bit] in {
def MOVZ_D : CondMovIntFP<AFGR64, 17, 18, "movz.d">;
def MOVN_D : CondMovIntFP<AFGR64, 17, 19, "movn.d">;
}
@@ -288,7 +282,7 @@ let Predicates = [In32BitMode] in {
defm : MovzPats<FGR32, MOVZ_S>;
defm : MovnPats<FGR32, MOVN_S>;
-let Predicates = [In32BitMode] in {
+let Predicates = [NotFP64bit] in {
defm : MovzPats<AFGR64, MOVZ_D>;
defm : MovnPats<AFGR64, MOVN_D>;
}
@@ -313,7 +307,7 @@ def MOVF : CondMovFPInt<MipsCMovFP_F, 0, "movf">;
def MOVT_S : CondMovFPFP<FGR32, MipsCMovFP_T, 16, 1, "movt.s">;
def MOVF_S : CondMovFPFP<FGR32, MipsCMovFP_F, 16, 0, "movf.s">;
-let Predicates = [In32BitMode] in {
+let Predicates = [NotFP64bit] in {
def MOVT_D : CondMovFPFP<AFGR64, MipsCMovFP_T, 17, 1, "movt.d">;
def MOVF_D : CondMovFPFP<AFGR64, MipsCMovFP_F, 17, 0, "movf.d">;
}
@@ -353,22 +347,16 @@ def fpimm0neg : PatLeaf<(fpimm), [{
}]>;
def : Pat<(f32 fpimm0), (MTC1 ZERO)>;
-def : Pat<(f32 fpimm0neg), (FNEG_S32 (MTC1 ZERO))>;
+def : Pat<(f32 fpimm0neg), (FNEG_S (MTC1 ZERO))>;
-def : Pat<(f32 (sint_to_fp CPURegs:$src)), (CVTS_W32 (MTC1 CPURegs:$src))>;
-def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVTD_W32 (MTC1 CPURegs:$src))>;
+def : Pat<(f32 (sint_to_fp CPURegs:$src)), (CVT_S_W (MTC1 CPURegs:$src))>;
+def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVT_D32_W (MTC1 CPURegs:$src))>;
-def : Pat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S32 FGR32:$src))>;
+def : Pat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S FGR32:$src))>;
def : Pat<(i32 (fp_to_sint AFGR64:$src)), (MFC1 (TRUNC_W_D32 AFGR64:$src))>;
-def : Pat<(i32 (bitconvert FGR32:$src)), (MFC1 FGR32:$src)>;
-def : Pat<(f32 (bitconvert CPURegs:$src)), (MTC1 CPURegs:$src)>;
-
-let Predicates = [In32BitMode] in {
- def : Pat<(f32 (fround AFGR64:$src)), (CVTS_D32 AFGR64:$src)>;
- def : Pat<(f64 (fextend FGR32:$src)), (CVTD_S32 FGR32:$src)>;
+let Predicates = [NotFP64bit] in {
+ def : Pat<(f32 (fround AFGR64:$src)), (CVT_S_D32 AFGR64:$src)>;
+ def : Pat<(f64 (fextend FGR32:$src)), (CVT_D32_S FGR32:$src)>;
}
-// MipsFPRound is only emitted for MipsI targets.
-def : Pat<(f32 (MipsFPRound AFGR64:$src)), (CVTW_D32 AFGR64:$src)>;
-
diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td
index 9f55fb3..d246a26 100644
--- a/lib/Target/Mips/MipsInstrFormats.td
+++ b/lib/Target/Mips/MipsInstrFormats.td
@@ -44,7 +44,9 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern,
// Mips Pseudo Instructions Format
class MipsPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>:
- MipsInst<outs, ins, asmstr, pattern, IIPseudo>;
+ MipsInst<outs, ins, asmstr, pattern, IIPseudo> {
+ let isPseudo = 1;
+}
//===----------------------------------------------------------------------===//
// Format R instruction class in Mips : <|opcode|rs|rt|rd|shamt|funct|>
@@ -88,6 +90,21 @@ class FI<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern,
let Inst{15-0} = imm16;
}
+class CBranchBase<bits<6> op, dag outs, dag ins, string asmstr,
+ list<dag> pattern, InstrItinClass itin>:
+ MipsInst<outs, ins, asmstr, pattern, itin>
+{
+ bits<5> rs;
+ bits<5> rt;
+ bits<16> imm16;
+
+ let opcode = op;
+
+ let Inst{25-21} = rs;
+ let Inst{20-16} = rt;
+ let Inst{15-0} = imm16;
+}
+
//===----------------------------------------------------------------------===//
// Format J instruction class in Mips : <|opcode|address|>
//===----------------------------------------------------------------------===//
@@ -224,4 +241,27 @@ class FFCMOV<bits<5> _fmt, bits<1> _tf, dag outs, dag ins, string asmstr,
let Inst{15-11} = fs;
let Inst{10-6} = fd;
let Inst{5-0} = 17;
-} \ No newline at end of file
+}
+
+// FP unary instructions without patterns.
+class FFR1<bits<6> funct, bits<5> fmt, string opstr, string fmtstr,
+ RegisterClass DstRC, RegisterClass SrcRC> :
+ FFR<0x11, funct, fmt, (outs DstRC:$fd), (ins SrcRC:$fs),
+ !strconcat(opstr, ".", fmtstr, "\t$fd, $fs"), []> {
+ let ft = 0;
+}
+
+// FP unary instructions with patterns.
+class FFR1P<bits<6> funct, bits<5> fmt, string opstr, string fmtstr,
+ RegisterClass DstRC, RegisterClass SrcRC, SDNode OpNode> :
+ FFR<0x11, funct, fmt, (outs DstRC:$fd), (ins SrcRC:$fs),
+ !strconcat(opstr, ".", fmtstr, "\t$fd, $fs"),
+ [(set DstRC:$fd, (OpNode SrcRC:$fs))]> {
+ let ft = 0;
+}
+
+class FFR2P<bits<6> funct, bits<5> fmt, string opstr,
+ string fmtstr, RegisterClass RC, SDNode OpNode> :
+ FFR<0x11, funct, fmt, (outs RC:$fd), (ins RC:$fs, RC:$ft),
+ !strconcat(opstr, ".", fmtstr, "\t$fd, $fs, $ft"),
+ [(set RC:$fd, (OpNode RC:$fs, RC:$ft))]>;
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
index 0a7a7f2..559943a 100644
--- a/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -17,8 +17,8 @@
#include "InstPrinter/MipsInstPrinter.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/ADT/STLExtras.h"
#define GET_INSTRINFO_CTOR
@@ -28,7 +28,8 @@ using namespace llvm;
MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm)
: MipsGenInstrInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP),
- TM(tm), RI(*TM.getSubtargetImpl(), *this) {}
+ TM(tm), IsN64(TM.getSubtarget<MipsSubtarget>().isABI_N64()),
+ RI(*TM.getSubtargetImpl(), *this) {}
const MipsRegisterInfo &MipsInstrInfo::getRegisterInfo() const {
@@ -47,8 +48,12 @@ static bool isZeroImm(const MachineOperand &op) {
unsigned MipsInstrInfo::
isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const
{
- if ((MI->getOpcode() == Mips::LW) || (MI->getOpcode() == Mips::LWC1) ||
- (MI->getOpcode() == Mips::LDC1)) {
+ unsigned Opc = MI->getOpcode();
+
+ if ((Opc == Mips::LW) || (Opc == Mips::LW_P8) || (Opc == Mips::LD) ||
+ (Opc == Mips::LD_P8) || (Opc == Mips::LWC1) || (Opc == Mips::LWC1_P8) ||
+ (Opc == Mips::LDC1) || (Opc == Mips::LDC164) ||
+ (Opc == Mips::LDC164_P8)) {
if ((MI->getOperand(1).isFI()) && // is a stack slot
(MI->getOperand(2).isImm()) && // the imm is zero
(isZeroImm(MI->getOperand(2)))) {
@@ -68,8 +73,12 @@ isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const
unsigned MipsInstrInfo::
isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const
{
- if ((MI->getOpcode() == Mips::SW) || (MI->getOpcode() == Mips::SWC1) ||
- (MI->getOpcode() == Mips::SDC1)) {
+ unsigned Opc = MI->getOpcode();
+
+ if ((Opc == Mips::SW) || (Opc == Mips::SW_P8) || (Opc == Mips::SD) ||
+ (Opc == Mips::SD_P8) || (Opc == Mips::SWC1) || (Opc == Mips::SWC1_P8) ||
+ (Opc == Mips::SDC1) || (Opc == Mips::SDC164) ||
+ (Opc == Mips::SDC164_P8)) {
if ((MI->getOperand(1).isFI()) && // is a stack slot
(MI->getOperand(2).isImm()) && // the imm is zero
(isZeroImm(MI->getOperand(2)))) {
@@ -94,70 +103,63 @@ copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I, DebugLoc DL,
unsigned DestReg, unsigned SrcReg,
bool KillSrc) const {
- bool DestCPU = Mips::CPURegsRegClass.contains(DestReg);
- bool SrcCPU = Mips::CPURegsRegClass.contains(SrcReg);
-
- // CPU-CPU is the most common.
- if (DestCPU && SrcCPU) {
- BuildMI(MBB, I, DL, get(Mips::ADDu), DestReg).addReg(Mips::ZERO)
- .addReg(SrcReg, getKillRegState(KillSrc));
- return;
- }
+ unsigned Opc = 0, ZeroReg = 0;
- // Copy to CPU from other registers.
- if (DestCPU) {
- if (Mips::CCRRegClass.contains(SrcReg))
- BuildMI(MBB, I, DL, get(Mips::CFC1), DestReg)
- .addReg(SrcReg, getKillRegState(KillSrc));
+ if (Mips::CPURegsRegClass.contains(DestReg)) { // Copy to CPU Reg.
+ if (Mips::CPURegsRegClass.contains(SrcReg))
+ Opc = Mips::ADDu, ZeroReg = Mips::ZERO;
+ else if (Mips::CCRRegClass.contains(SrcReg))
+ Opc = Mips::CFC1;
else if (Mips::FGR32RegClass.contains(SrcReg))
- BuildMI(MBB, I, DL, get(Mips::MFC1), DestReg)
- .addReg(SrcReg, getKillRegState(KillSrc));
+ Opc = Mips::MFC1;
else if (SrcReg == Mips::HI)
- BuildMI(MBB, I, DL, get(Mips::MFHI), DestReg);
+ Opc = Mips::MFHI, SrcReg = 0;
else if (SrcReg == Mips::LO)
- BuildMI(MBB, I, DL, get(Mips::MFLO), DestReg);
- else
- llvm_unreachable("Copy to CPU from invalid register");
- return;
+ Opc = Mips::MFLO, SrcReg = 0;
}
-
- // Copy to other registers from CPU.
- if (SrcCPU) {
+ else if (Mips::CPURegsRegClass.contains(SrcReg)) { // Copy from CPU Reg.
if (Mips::CCRRegClass.contains(DestReg))
- BuildMI(MBB, I, DL, get(Mips::CTC1), DestReg)
- .addReg(SrcReg, getKillRegState(KillSrc));
+ Opc = Mips::CTC1;
else if (Mips::FGR32RegClass.contains(DestReg))
- BuildMI(MBB, I, DL, get(Mips::MTC1), DestReg)
- .addReg(SrcReg, getKillRegState(KillSrc));
+ Opc = Mips::MTC1;
else if (DestReg == Mips::HI)
- BuildMI(MBB, I, DL, get(Mips::MTHI))
- .addReg(SrcReg, getKillRegState(KillSrc));
+ Opc = Mips::MTHI, DestReg = 0;
else if (DestReg == Mips::LO)
- BuildMI(MBB, I, DL, get(Mips::MTLO))
- .addReg(SrcReg, getKillRegState(KillSrc));
- else
- llvm_unreachable("Copy from CPU to invalid register");
- return;
+ Opc = Mips::MTLO, DestReg = 0;
}
-
- if (Mips::FGR32RegClass.contains(DestReg, SrcReg)) {
- BuildMI(MBB, I, DL, get(Mips::FMOV_S32), DestReg)
- .addReg(SrcReg, getKillRegState(KillSrc));
- return;
+ else if (Mips::FGR32RegClass.contains(DestReg, SrcReg))
+ Opc = Mips::FMOV_S;
+ else if (Mips::AFGR64RegClass.contains(DestReg, SrcReg))
+ Opc = Mips::FMOV_D32;
+ else if (Mips::CCRRegClass.contains(DestReg, SrcReg))
+ Opc = Mips::MOVCCRToCCR;
+ else if (Mips::CPU64RegsRegClass.contains(DestReg)) { // Copy to CPU64 Reg.
+ if (Mips::CPU64RegsRegClass.contains(SrcReg))
+ Opc = Mips::DADDu, ZeroReg = Mips::ZERO_64;
+ else if (SrcReg == Mips::HI64)
+ Opc = Mips::MFHI64, SrcReg = 0;
+ else if (SrcReg == Mips::LO64)
+ Opc = Mips::MFLO64, SrcReg = 0;
}
-
- if (Mips::AFGR64RegClass.contains(DestReg, SrcReg)) {
- BuildMI(MBB, I, DL, get(Mips::FMOV_D32), DestReg)
- .addReg(SrcReg, getKillRegState(KillSrc));
- return;
+ else if (Mips::CPU64RegsRegClass.contains(SrcReg)) { // Copy from CPU64 Reg.
+ if (DestReg == Mips::HI64)
+ Opc = Mips::MTHI64, DestReg = 0;
+ else if (DestReg == Mips::LO64)
+ Opc = Mips::MTLO64, DestReg = 0;
}
- if (Mips::CCRRegClass.contains(DestReg, SrcReg)) {
- BuildMI(MBB, I, DL, get(Mips::MOVCCRToCCR), DestReg)
- .addReg(SrcReg, getKillRegState(KillSrc));
- return;
- }
- llvm_unreachable("Cannot copy registers");
+ assert(Opc && "Cannot copy registers");
+
+ MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc));
+
+ if (DestReg)
+ MIB.addReg(DestReg, RegState::Define);
+
+ if (ZeroReg)
+ MIB.addReg(ZeroReg);
+
+ if (SrcReg)
+ MIB.addReg(SrcReg, getKillRegState(KillSrc));
}
void MipsInstrInfo::
@@ -167,31 +169,22 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
const TargetRegisterInfo *TRI) const {
DebugLoc DL;
if (I != MBB.end()) DL = I->getDebugLoc();
+ unsigned Opc = 0;
if (RC == Mips::CPURegsRegisterClass)
- BuildMI(MBB, I, DL, get(Mips::SW)).addReg(SrcReg, getKillRegState(isKill))
- .addFrameIndex(FI).addImm(0);
+ Opc = IsN64 ? Mips::SW_P8 : Mips::SW;
+ else if (RC == Mips::CPU64RegsRegisterClass)
+ Opc = IsN64 ? Mips::SD_P8 : Mips::SD;
else if (RC == Mips::FGR32RegisterClass)
- BuildMI(MBB, I, DL, get(Mips::SWC1)).addReg(SrcReg, getKillRegState(isKill))
- .addFrameIndex(FI).addImm(0);
- else if (RC == Mips::AFGR64RegisterClass) {
- if (!TM.getSubtarget<MipsSubtarget>().isMips1()) {
- BuildMI(MBB, I, DL, get(Mips::SDC1))
- .addReg(SrcReg, getKillRegState(isKill))
- .addFrameIndex(FI).addImm(0);
- } else {
- const TargetRegisterInfo *TRI =
- MBB.getParent()->getTarget().getRegisterInfo();
- const unsigned *SubSet = TRI->getSubRegisters(SrcReg);
- BuildMI(MBB, I, DL, get(Mips::SWC1))
- .addReg(SubSet[0], getKillRegState(isKill))
- .addFrameIndex(FI).addImm(0);
- BuildMI(MBB, I, DL, get(Mips::SWC1))
- .addReg(SubSet[1], getKillRegState(isKill))
- .addFrameIndex(FI).addImm(4);
- }
- } else
- llvm_unreachable("Register class not handled!");
+ Opc = IsN64 ? Mips::SWC1_P8 : Mips::SWC1;
+ else if (RC == Mips::AFGR64RegisterClass)
+ Opc = Mips::SDC1;
+ else if (RC == Mips::FGR64RegisterClass)
+ Opc = IsN64 ? Mips::SDC164_P8 : Mips::SDC164;
+
+ assert(Opc && "Register class not handled!");
+ BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill))
+ .addFrameIndex(FI).addImm(0);
}
void MipsInstrInfo::
@@ -202,25 +195,21 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
{
DebugLoc DL;
if (I != MBB.end()) DL = I->getDebugLoc();
+ unsigned Opc = 0;
if (RC == Mips::CPURegsRegisterClass)
- BuildMI(MBB, I, DL, get(Mips::LW), DestReg).addFrameIndex(FI).addImm(0);
+ Opc = IsN64 ? Mips::LW_P8 : Mips::LW;
+ else if (RC == Mips::CPU64RegsRegisterClass)
+ Opc = IsN64 ? Mips::LD_P8 : Mips::LD;
else if (RC == Mips::FGR32RegisterClass)
- BuildMI(MBB, I, DL, get(Mips::LWC1), DestReg).addFrameIndex(FI).addImm(0);
- else if (RC == Mips::AFGR64RegisterClass) {
- if (!TM.getSubtarget<MipsSubtarget>().isMips1()) {
- BuildMI(MBB, I, DL, get(Mips::LDC1), DestReg).addFrameIndex(FI).addImm(0);
- } else {
- const TargetRegisterInfo *TRI =
- MBB.getParent()->getTarget().getRegisterInfo();
- const unsigned *SubSet = TRI->getSubRegisters(DestReg);
- BuildMI(MBB, I, DL, get(Mips::LWC1), SubSet[0])
- .addFrameIndex(FI).addImm(0);
- BuildMI(MBB, I, DL, get(Mips::LWC1), SubSet[1])
- .addFrameIndex(FI).addImm(4);
- }
- } else
- llvm_unreachable("Register class not handled!");
+ Opc = IsN64 ? Mips::LWC1_P8 : Mips::LWC1;
+ else if (RC == Mips::AFGR64RegisterClass)
+ Opc = Mips::LDC1;
+ else if (RC == Mips::FGR64RegisterClass)
+ Opc = IsN64 ? Mips::LDC164_P8 : Mips::LDC164;
+
+ assert(Opc && "Register class not handled!");
+ BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(0);
}
MachineInstr*
@@ -237,9 +226,12 @@ MipsInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx,
//===----------------------------------------------------------------------===//
static unsigned GetAnalyzableBrOpc(unsigned Opc) {
- return (Opc == Mips::BEQ || Opc == Mips::BNE || Opc == Mips::BGTZ ||
- Opc == Mips::BGEZ || Opc == Mips::BLTZ || Opc == Mips::BLEZ ||
- Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::J) ? Opc : 0;
+ return (Opc == Mips::BEQ || Opc == Mips::BNE || Opc == Mips::BGTZ ||
+ Opc == Mips::BGEZ || Opc == Mips::BLTZ || Opc == Mips::BLEZ ||
+ Opc == Mips::BEQ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 ||
+ Opc == Mips::BGEZ64 || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 ||
+ Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::J) ?
+ Opc : 0;
}
/// GetOppositeBranchOpc - Return the inverse of the specified
@@ -248,14 +240,20 @@ unsigned Mips::GetOppositeBranchOpc(unsigned Opc)
{
switch (Opc) {
default: llvm_unreachable("Illegal opcode!");
- case Mips::BEQ : return Mips::BNE;
- case Mips::BNE : return Mips::BEQ;
- case Mips::BGTZ : return Mips::BLEZ;
- case Mips::BGEZ : return Mips::BLTZ;
- case Mips::BLTZ : return Mips::BGEZ;
- case Mips::BLEZ : return Mips::BGTZ;
- case Mips::BC1T : return Mips::BC1F;
- case Mips::BC1F : return Mips::BC1T;
+ case Mips::BEQ : return Mips::BNE;
+ case Mips::BNE : return Mips::BEQ;
+ case Mips::BGTZ : return Mips::BLEZ;
+ case Mips::BGEZ : return Mips::BLTZ;
+ case Mips::BLTZ : return Mips::BGEZ;
+ case Mips::BLEZ : return Mips::BGTZ;
+ case Mips::BEQ64 : return Mips::BNE64;
+ case Mips::BNE64 : return Mips::BEQ64;
+ case Mips::BGTZ64 : return Mips::BLEZ64;
+ case Mips::BGEZ64 : return Mips::BLTZ64;
+ case Mips::BLTZ64 : return Mips::BGEZ64;
+ case Mips::BLEZ64 : return Mips::BGTZ64;
+ case Mips::BC1T : return Mips::BC1F;
+ case Mips::BC1F : return Mips::BC1T;
}
}
diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h
index 4421c48..271d248 100644
--- a/lib/Target/Mips/MipsInstrInfo.h
+++ b/lib/Target/Mips/MipsInstrInfo.h
@@ -72,12 +72,47 @@ namespace MipsII {
/// MO_TPREL_HI/LO - Represents the hi and low part of the offset from
// the thread pointer (Local Exec TLS).
MO_TPREL_HI,
- MO_TPREL_LO
+ MO_TPREL_LO,
+
+ // N32/64 Flags.
+ MO_GPOFF_HI,
+ MO_GPOFF_LO,
+ MO_GOT_DISP,
+ MO_GOT_PAGE,
+ MO_GOT_OFST
+ };
+
+ enum {
+ //===------------------------------------------------------------------===//
+ // Instruction encodings. These are the standard/most common forms for
+ // Mips instructions.
+ //
+
+ // Pseudo - This represents an instruction that is a pseudo instruction
+ // or one that has not been implemented yet. It is illegal to code generate
+ // it, but tolerated for intermediate implementation stages.
+ Pseudo = 0,
+
+ /// FrmR - This form is for instructions of the format R.
+ FrmR = 1,
+ /// FrmI - This form is for instructions of the format I.
+ FrmI = 2,
+ /// FrmJ - This form is for instructions of the format J.
+ FrmJ = 3,
+ /// FrmFR - This form is for instructions of the format FR.
+ FrmFR = 4,
+ /// FrmFI - This form is for instructions of the format FI.
+ FrmFI = 5,
+ /// FrmOther - This form is for instructions that have no specific format.
+ FrmOther = 6,
+
+ FormMask = 15
};
}
class MipsInstrInfo : public MipsGenInstrInfo {
MipsTargetMachine &TM;
+ bool IsN64;
const MipsRegisterInfo RI;
public:
explicit MipsInstrInfo(MipsTargetMachine &TM);
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index d1a0587..06b7de7 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -34,13 +34,20 @@ def SDT_MipsMAddMSub : SDTypeProfile<0, 4,
SDTCisSameAs<1, 2>,
SDTCisSameAs<2, 3>]>;
def SDT_MipsDivRem : SDTypeProfile<0, 2,
- [SDTCisVT<0, i32>,
+ [SDTCisInt<0>,
SDTCisSameAs<0, 1>]>;
def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;
def SDT_MipsDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i32>,
SDTCisVT<1, iPTR>]>;
+def SDT_Sync : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
+
+def SDT_Ext : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>,
+ SDTCisVT<2, i32>, SDTCisSameAs<2, 3>]>;
+def SDT_Ins : SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisSameAs<0, 1>,
+ SDTCisVT<2, i32>, SDTCisSameAs<2, 3>,
+ SDTCisSameAs<0, 4>]>;
// Call
def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink,
@@ -106,6 +113,11 @@ def MipsWrapperPIC : SDNode<"MipsISD::WrapperPIC", SDTIntUnaryOp>;
def MipsDynAlloc : SDNode<"MipsISD::DynAlloc", SDT_MipsDynAlloc,
[SDNPHasChain, SDNPInGlue]>;
+def MipsSync : SDNode<"MipsISD::Sync", SDT_Sync, [SDNPHasChain]>;
+
+def MipsExt : SDNode<"MipsISD::Ext", SDT_Ext>;
+def MipsIns : SDNode<"MipsISD::Ins", SDT_Ins>;
+
//===----------------------------------------------------------------------===//
// Mips Instruction Predicate Definitions.
//===----------------------------------------------------------------------===//
@@ -113,8 +125,13 @@ def HasSEInReg : Predicate<"Subtarget.hasSEInReg()">;
def HasBitCount : Predicate<"Subtarget.hasBitCount()">;
def HasSwap : Predicate<"Subtarget.hasSwap()">;
def HasCondMov : Predicate<"Subtarget.hasCondMov()">;
-def IsMips32 : Predicate<"Subtarget.isMips32()">;
-def IsMips32r2 : Predicate<"Subtarget.isMips32r2()">;
+def HasMips32 : Predicate<"Subtarget.hasMips32()">;
+def HasMips32r2 : Predicate<"Subtarget.hasMips32r2()">;
+def HasMips64 : Predicate<"Subtarget.hasMips64()">;
+def NotMips64 : Predicate<"!Subtarget.hasMips64()">;
+def HasMips64r2 : Predicate<"Subtarget.hasMips64r2()">;
+def IsN64 : Predicate<"Subtarget.isABI_N64()">;
+def NotN64 : Predicate<"!Subtarget.isABI_N64()">;
//===----------------------------------------------------------------------===//
// Mips Operand, Complex Patterns and Transformations Definitions.
@@ -124,6 +141,7 @@ def IsMips32r2 : Predicate<"Subtarget.isMips32r2()">;
def brtarget : Operand<OtherVT>;
def calltarget : Operand<i32>;
def simm16 : Operand<i32>;
+def simm16_64 : Operand<i64>;
def shamt : Operand<i32>;
// Unsigned Operand
@@ -137,6 +155,11 @@ def mem : Operand<i32> {
let MIOperandInfo = (ops CPURegs, simm16);
}
+def mem64 : Operand<i64> {
+ let PrintMethod = "printMemOperand";
+ let MIOperandInfo = (ops CPU64Regs, simm16_64);
+}
+
def mem_ea : Operand<i32> {
let PrintMethod = "printMemOperandEA";
let MIOperandInfo = (ops CPURegs, simm16);
@@ -177,36 +200,85 @@ def immZExt5 : PatLeaf<(imm), [{
def addr : ComplexPattern<iPTR, 2, "SelectAddr", [frameindex], []>;
//===----------------------------------------------------------------------===//
+// Pattern fragment for load/store
+//===----------------------------------------------------------------------===//
+class UnalignedLoad<PatFrag Node> : PatFrag<(ops node:$ptr), (Node node:$ptr), [{
+ LoadSDNode *LD = cast<LoadSDNode>(N);
+ return LD->getMemoryVT().getSizeInBits()/8 > LD->getAlignment();
+}]>;
+
+class AlignedLoad<PatFrag Node> : PatFrag<(ops node:$ptr), (Node node:$ptr), [{
+ LoadSDNode *LD = cast<LoadSDNode>(N);
+ return LD->getMemoryVT().getSizeInBits()/8 <= LD->getAlignment();
+}]>;
+
+class UnalignedStore<PatFrag Node> : PatFrag<(ops node:$val, node:$ptr),
+ (Node node:$val, node:$ptr), [{
+ StoreSDNode *SD = cast<StoreSDNode>(N);
+ return SD->getMemoryVT().getSizeInBits()/8 > SD->getAlignment();
+}]>;
+
+class AlignedStore<PatFrag Node> : PatFrag<(ops node:$val, node:$ptr),
+ (Node node:$val, node:$ptr), [{
+ StoreSDNode *SD = cast<StoreSDNode>(N);
+ return SD->getMemoryVT().getSizeInBits()/8 <= SD->getAlignment();
+}]>;
+
+// Load/Store PatFrags.
+def sextloadi16_a : AlignedLoad<sextloadi16>;
+def zextloadi16_a : AlignedLoad<zextloadi16>;
+def extloadi16_a : AlignedLoad<extloadi16>;
+def load_a : AlignedLoad<load>;
+def sextloadi32_a : AlignedLoad<sextloadi32>;
+def zextloadi32_a : AlignedLoad<zextloadi32>;
+def extloadi32_a : AlignedLoad<extloadi32>;
+def truncstorei16_a : AlignedStore<truncstorei16>;
+def store_a : AlignedStore<store>;
+def truncstorei32_a : AlignedStore<truncstorei32>;
+def sextloadi16_u : UnalignedLoad<sextloadi16>;
+def zextloadi16_u : UnalignedLoad<zextloadi16>;
+def extloadi16_u : UnalignedLoad<extloadi16>;
+def load_u : UnalignedLoad<load>;
+def sextloadi32_u : UnalignedLoad<sextloadi32>;
+def zextloadi32_u : UnalignedLoad<zextloadi32>;
+def extloadi32_u : UnalignedLoad<extloadi32>;
+def truncstorei16_u : UnalignedStore<truncstorei16>;
+def store_u : UnalignedStore<store>;
+def truncstorei32_u : UnalignedStore<truncstorei32>;
+
+//===----------------------------------------------------------------------===//
// Instructions specific format
//===----------------------------------------------------------------------===//
-// Arithmetic 3 register operands
-class ArithR<bits<6> op, bits<6> func, string instr_asm, SDNode OpNode,
- InstrItinClass itin, bit isComm = 0>:
- FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c),
- !strconcat(instr_asm, "\t$dst, $b, $c"),
- [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin> {
+// Arithmetic and logical instructions with 3 register operands.
+class ArithLogicR<bits<6> op, bits<6> func, string instr_asm, SDNode OpNode,
+ InstrItinClass itin, RegisterClass RC, bit isComm = 0>:
+ FR<op, func, (outs RC:$rd), (ins RC:$rs, RC:$rt),
+ !strconcat(instr_asm, "\t$rd, $rs, $rt"),
+ [(set RC:$rd, (OpNode RC:$rs, RC:$rt))], itin> {
+ let shamt = 0;
let isCommutable = isComm;
}
class ArithOverflowR<bits<6> op, bits<6> func, string instr_asm,
- bit isComm = 0>:
- FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c),
- !strconcat(instr_asm, "\t$dst, $b, $c"), [], IIAlu> {
+ InstrItinClass itin, RegisterClass RC, bit isComm = 0>:
+ FR<op, func, (outs RC:$rd), (ins RC:$rs, RC:$rt),
+ !strconcat(instr_asm, "\t$rd, $rs, $rt"), [], itin> {
+ let shamt = 0;
let isCommutable = isComm;
}
-// Arithmetic 2 register operands
-class ArithI<bits<6> op, string instr_asm, SDNode OpNode,
- Operand Od, PatLeaf imm_type> :
- FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c),
- !strconcat(instr_asm, "\t$dst, $b, $c"),
- [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>;
+// Arithmetic and logical instructions with 2 register operands.
+class ArithLogicI<bits<6> op, string instr_asm, SDNode OpNode,
+ Operand Od, PatLeaf imm_type, RegisterClass RC> :
+ FI<op, (outs RC:$rt), (ins RC:$rs, Od:$i),
+ !strconcat(instr_asm, "\t$rt, $rs, $i"),
+ [(set RC:$rt, (OpNode RC:$rs, imm_type:$i))], IIAlu>;
class ArithOverflowI<bits<6> op, string instr_asm, SDNode OpNode,
- Operand Od, PatLeaf imm_type> :
- FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c),
- !strconcat(instr_asm, "\t$dst, $b, $c"), [], IIAlu>;
+ Operand Od, PatLeaf imm_type, RegisterClass RC> :
+ FI<op, (outs RC:$rt), (ins RC:$rs, Od:$i),
+ !strconcat(instr_asm, "\t$rt, $rs, $i"), [], IIAlu>;
// Arithmetic Multiply ADD/SUB
let rd = 0, shamt = 0, Defs = [HI, LO], Uses = [HI, LO] in
@@ -214,92 +286,134 @@ class MArithR<bits<6> func, string instr_asm, SDNode op, bit isComm = 0> :
FR<0x1c, func, (outs), (ins CPURegs:$rs, CPURegs:$rt),
!strconcat(instr_asm, "\t$rs, $rt"),
[(op CPURegs:$rs, CPURegs:$rt, LO, HI)], IIImul> {
+ let rd = 0;
+ let shamt = 0;
let isCommutable = isComm;
}
// Logical
-let isCommutable = 1 in
-class LogicR<bits<6> func, string instr_asm, SDNode OpNode>:
- FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c),
- !strconcat(instr_asm, "\t$dst, $b, $c"),
- [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>;
-
-class LogicI<bits<6> op, string instr_asm, SDNode OpNode>:
- FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, uimm16:$c),
- !strconcat(instr_asm, "\t$dst, $b, $c"),
- [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>;
-
-let isCommutable = 1 in
-class LogicNOR<bits<6> op, bits<6> func, string instr_asm>:
- FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c),
- !strconcat(instr_asm, "\t$dst, $b, $c"),
- [(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))], IIAlu>;
+class LogicNOR<bits<6> op, bits<6> func, string instr_asm, RegisterClass RC>:
+ FR<op, func, (outs RC:$rd), (ins RC:$rs, RC:$rt),
+ !strconcat(instr_asm, "\t$rd, $rs, $rt"),
+ [(set RC:$rd, (not (or RC:$rs, RC:$rt)))], IIAlu> {
+ let shamt = 0;
+ let isCommutable = 1;
+}
// Shifts
class LogicR_shift_rotate_imm<bits<6> func, bits<5> _rs, string instr_asm,
SDNode OpNode>:
- FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$b, shamt:$c),
- !strconcat(instr_asm, "\t$dst, $b, $c"),
- [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))], IIAlu> {
+ FR<0x00, func, (outs CPURegs:$rd), (ins CPURegs:$rt, shamt:$shamt),
+ !strconcat(instr_asm, "\t$rd, $rt, $shamt"),
+ [(set CPURegs:$rd, (OpNode CPURegs:$rt, (i32 immZExt5:$shamt)))], IIAlu> {
let rs = _rs;
}
-class LogicR_shift_rotate_reg<bits<6> func, bits<5> _shamt, string instr_asm,
+class LogicR_shift_rotate_reg<bits<6> func, bits<5> isRotate, string instr_asm,
SDNode OpNode>:
- FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$c, CPURegs:$b),
- !strconcat(instr_asm, "\t$dst, $b, $c"),
- [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu> {
- let shamt = _shamt;
+ FR<0x00, func, (outs CPURegs:$rd), (ins CPURegs:$rs, CPURegs:$rt),
+ !strconcat(instr_asm, "\t$rd, $rt, $rs"),
+ [(set CPURegs:$rd, (OpNode CPURegs:$rt, CPURegs:$rs))], IIAlu> {
+ let shamt = isRotate;
}
// Load Upper Imediate
class LoadUpper<bits<6> op, string instr_asm>:
- FI< op,
- (outs CPURegs:$dst),
- (ins uimm16:$imm),
- !strconcat(instr_asm, "\t$dst, $imm"),
- [], IIAlu>;
+ FI<op, (outs CPURegs:$rt), (ins uimm16:$imm),
+ !strconcat(instr_asm, "\t$rt, $imm"), [], IIAlu> {
+ let rs = 0;
+}
// Memory Load/Store
-let canFoldAsLoad = 1, hasDelaySlot = 1 in
-class LoadM<bits<6> op, string instr_asm, PatFrag OpNode>:
- FI<op, (outs CPURegs:$dst), (ins mem:$addr),
- !strconcat(instr_asm, "\t$dst, $addr"),
- [(set CPURegs:$dst, (OpNode addr:$addr))], IILoad>;
+let canFoldAsLoad = 1 in
+class LoadM<bits<6> op, string instr_asm, PatFrag OpNode, RegisterClass RC,
+ Operand MemOpnd, bit Pseudo>:
+ FI<op, (outs RC:$rt), (ins MemOpnd:$addr),
+ !strconcat(instr_asm, "\t$rt, $addr"),
+ [(set RC:$rt, (OpNode addr:$addr))], IILoad> {
+ let isPseudo = Pseudo;
+}
-class StoreM<bits<6> op, string instr_asm, PatFrag OpNode>:
- FI<op, (outs), (ins CPURegs:$dst, mem:$addr),
- !strconcat(instr_asm, "\t$dst, $addr"),
- [(OpNode CPURegs:$dst, addr:$addr)], IIStore>;
+class StoreM<bits<6> op, string instr_asm, PatFrag OpNode, RegisterClass RC,
+ Operand MemOpnd, bit Pseudo>:
+ FI<op, (outs), (ins RC:$rt, MemOpnd:$addr),
+ !strconcat(instr_asm, "\t$rt, $addr"),
+ [(OpNode RC:$rt, addr:$addr)], IIStore> {
+ let isPseudo = Pseudo;
+}
+
+// 32-bit load.
+multiclass LoadM32<bits<6> op, string instr_asm, PatFrag OpNode,
+ bit Pseudo = 0> {
+ def #NAME# : LoadM<op, instr_asm, OpNode, CPURegs, mem, Pseudo>,
+ Requires<[NotN64]>;
+ def _P8 : LoadM<op, instr_asm, OpNode, CPURegs, mem64, Pseudo>,
+ Requires<[IsN64]>;
+}
+
+// 64-bit load.
+multiclass LoadM64<bits<6> op, string instr_asm, PatFrag OpNode,
+ bit Pseudo = 0> {
+ def #NAME# : LoadM<op, instr_asm, OpNode, CPU64Regs, mem, Pseudo>,
+ Requires<[NotN64]>;
+ def _P8 : LoadM<op, instr_asm, OpNode, CPU64Regs, mem64, Pseudo>,
+ Requires<[IsN64]>;
+}
+
+// 32-bit store.
+multiclass StoreM32<bits<6> op, string instr_asm, PatFrag OpNode,
+ bit Pseudo = 0> {
+ def #NAME# : StoreM<op, instr_asm, OpNode, CPURegs, mem, Pseudo>,
+ Requires<[NotN64]>;
+ def _P8 : StoreM<op, instr_asm, OpNode, CPURegs, mem64, Pseudo>,
+ Requires<[IsN64]>;
+}
+
+// 64-bit store.
+multiclass StoreM64<bits<6> op, string instr_asm, PatFrag OpNode,
+ bit Pseudo = 0> {
+ def #NAME# : StoreM<op, instr_asm, OpNode, CPU64Regs, mem, Pseudo>,
+ Requires<[NotN64]>;
+ def _P8 : StoreM<op, instr_asm, OpNode, CPU64Regs, mem64, Pseudo>,
+ Requires<[IsN64]>;
+}
// Conditional Branch
-let isBranch = 1, isTerminator=1, hasDelaySlot = 1 in {
-class CBranch<bits<6> op, string instr_asm, PatFrag cond_op>:
- FI<op, (outs), (ins CPURegs:$a, CPURegs:$b, brtarget:$offset),
- !strconcat(instr_asm, "\t$a, $b, $offset"),
- [(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)],
- IIBranch>;
+class CBranch<bits<6> op, string instr_asm, PatFrag cond_op, RegisterClass RC>:
+ CBranchBase<op, (outs), (ins RC:$rs, RC:$rt, brtarget:$offset),
+ !strconcat(instr_asm, "\t$rs, $rt, $offset"),
+ [(brcond (i32 (cond_op RC:$rs, RC:$rt)), bb:$offset)], IIBranch> {
+ let isBranch = 1;
+ let isTerminator = 1;
+ let hasDelaySlot = 1;
+}
-class CBranchZero<bits<6> op, string instr_asm, PatFrag cond_op>:
- FI<op, (outs), (ins CPURegs:$src, brtarget:$offset),
- !strconcat(instr_asm, "\t$src, $offset"),
- [(brcond (cond_op CPURegs:$src, 0), bb:$offset)],
- IIBranch>;
+class CBranchZero<bits<6> op, bits<5> _rt, string instr_asm, PatFrag cond_op,
+ RegisterClass RC>:
+ CBranchBase<op, (outs), (ins RC:$rs, brtarget:$offset),
+ !strconcat(instr_asm, "\t$rs, $offset"),
+ [(brcond (i32 (cond_op RC:$rs, 0)), bb:$offset)], IIBranch> {
+ let rt = _rt;
+ let isBranch = 1;
+ let isTerminator = 1;
+ let hasDelaySlot = 1;
}
// SetCC
-class SetCC_R<bits<6> op, bits<6> func, string instr_asm,
- PatFrag cond_op>:
- FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c),
- !strconcat(instr_asm, "\t$dst, $b, $c"),
- [(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))],
- IIAlu>;
+class SetCC_R<bits<6> op, bits<6> func, string instr_asm, PatFrag cond_op,
+ RegisterClass RC>:
+ FR<op, func, (outs CPURegs:$rd), (ins RC:$rs, RC:$rt),
+ !strconcat(instr_asm, "\t$rd, $rs, $rt"),
+ [(set CPURegs:$rd, (cond_op RC:$rs, RC:$rt))],
+ IIAlu> {
+ let shamt = 0;
+}
-class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op,
- Operand Od, PatLeaf imm_type>:
- FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c),
- !strconcat(instr_asm, "\t$dst, $b, $c"),
- [(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))],
+class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op, Operand Od,
+ PatLeaf imm_type, RegisterClass RC>:
+ FI<op, (outs CPURegs:$rd), (ins RC:$rs, Od:$i),
+ !strconcat(instr_asm, "\t$rd, $rs, $i"),
+ [(set CPURegs:$rd, (cond_op RC:$rs, imm_type:$i))],
IIAlu>;
// Unconditional branch
@@ -310,8 +424,12 @@ class JumpFJ<bits<6> op, string instr_asm>:
let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1 in
class JumpFR<bits<6> op, bits<6> func, string instr_asm>:
- FR<op, func, (outs), (ins CPURegs:$target),
- !strconcat(instr_asm, "\t$target"), [(brind CPURegs:$target)], IIBranch>;
+ FR<op, func, (outs), (ins CPURegs:$rs),
+ !strconcat(instr_asm, "\t$rs"), [(brind CPURegs:$rs)], IIBranch> {
+ let rt = 0;
+ let rd = 0;
+ let shamt = 0;
+}
// Jump and Link (Call)
let isCall=1, hasDelaySlot=1,
@@ -323,76 +441,124 @@ let isCall=1, hasDelaySlot=1,
!strconcat(instr_asm, "\t$target"), [(MipsJmpLink imm:$target)],
IIBranch>;
- let rd=31 in
class JumpLinkReg<bits<6> op, bits<6> func, string instr_asm>:
FR<op, func, (outs), (ins CPURegs:$rs, variable_ops),
- !strconcat(instr_asm, "\t$rs"), [(MipsJmpLink CPURegs:$rs)], IIBranch>;
+ !strconcat(instr_asm, "\t$rs"), [(MipsJmpLink CPURegs:$rs)], IIBranch> {
+ let rt = 0;
+ let rd = 31;
+ let shamt = 0;
+ }
class BranchLink<string instr_asm>:
FI<0x1, (outs), (ins CPURegs:$rs, brtarget:$target, variable_ops),
- !strconcat(instr_asm, "\t$rs, $target"), [], IIBranch>;
+ !strconcat(instr_asm, "\t$rs, $target"), [], IIBranch> {
+ let rt = 0;
+ }
}
// Mul, Div
-let Defs = [HI, LO] in {
- let isCommutable = 1 in
- class Mul<bits<6> func, string instr_asm, InstrItinClass itin>:
- FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b),
- !strconcat(instr_asm, "\t$a, $b"), [], itin>;
+class Mul<bits<6> func, string instr_asm, InstrItinClass itin>:
+ FR<0x00, func, (outs), (ins CPURegs:$rs, CPURegs:$rt),
+ !strconcat(instr_asm, "\t$rs, $rt"), [], itin> {
+ let rd = 0;
+ let shamt = 0;
+ let isCommutable = 1;
+ let Defs = [HI, LO];
+}
- class Div<SDNode op, bits<6> func, string instr_asm, InstrItinClass itin>:
- FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b),
- !strconcat(instr_asm, "\t$$zero, $a, $b"),
- [(op CPURegs:$a, CPURegs:$b)], itin>;
+class Div<SDNode op, bits<6> func, string instr_asm, InstrItinClass itin>:
+ FR<0x00, func, (outs), (ins CPURegs:$rs, CPURegs:$rt),
+ !strconcat(instr_asm, "\t$$zero, $rs, $rt"),
+ [(op CPURegs:$rs, CPURegs:$rt)], itin> {
+ let rd = 0;
+ let shamt = 0;
+ let Defs = [HI, LO];
}
// Move from Hi/Lo
class MoveFromLOHI<bits<6> func, string instr_asm>:
- FR<0x00, func, (outs CPURegs:$dst), (ins),
- !strconcat(instr_asm, "\t$dst"), [], IIHiLo>;
+ FR<0x00, func, (outs CPURegs:$rd), (ins),
+ !strconcat(instr_asm, "\t$rd"), [], IIHiLo> {
+ let rs = 0;
+ let rt = 0;
+ let shamt = 0;
+}
class MoveToLOHI<bits<6> func, string instr_asm>:
- FR<0x00, func, (outs), (ins CPURegs:$src),
- !strconcat(instr_asm, "\t$src"), [], IIHiLo>;
+ FR<0x00, func, (outs), (ins CPURegs:$rs),
+ !strconcat(instr_asm, "\t$rs"), [], IIHiLo> {
+ let rt = 0;
+ let rd = 0;
+ let shamt = 0;
+}
class EffectiveAddress<string instr_asm> :
- FI<0x09, (outs CPURegs:$dst), (ins mem_ea:$addr),
- instr_asm, [(set CPURegs:$dst, addr:$addr)], IIAlu>;
+ FI<0x09, (outs CPURegs:$rt), (ins mem_ea:$addr),
+ instr_asm, [(set CPURegs:$rt, addr:$addr)], IIAlu>;
// Count Leading Ones/Zeros in Word
class CountLeading<bits<6> func, string instr_asm, list<dag> pattern>:
- FR<0x1c, func, (outs CPURegs:$dst), (ins CPURegs:$src),
- !strconcat(instr_asm, "\t$dst, $src"), pattern, IIAlu>,
+ FR<0x1c, func, (outs CPURegs:$rd), (ins CPURegs:$rs),
+ !strconcat(instr_asm, "\t$rd, $rs"), pattern, IIAlu>,
Requires<[HasBitCount]> {
let shamt = 0;
let rt = rd;
}
// Sign Extend in Register.
-class SignExtInReg<bits<6> func, string instr_asm, ValueType vt>:
- FR<0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src),
- !strconcat(instr_asm, "\t$dst, $src"),
- [(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>;
+class SignExtInReg<bits<5> sa, string instr_asm, ValueType vt>:
+ FR<0x3f, 0x20, (outs CPURegs:$rd), (ins CPURegs:$rt),
+ !strconcat(instr_asm, "\t$rd, $rt"),
+ [(set CPURegs:$rd, (sext_inreg CPURegs:$rt, vt))], NoItinerary> {
+ let rs = 0;
+ let shamt = sa;
+ let Predicates = [HasSEInReg];
+}
// Byte Swap
-class ByteSwap<bits<6> func, string instr_asm>:
- FR<0x1f, func, (outs CPURegs:$dst), (ins CPURegs:$src),
- !strconcat(instr_asm, "\t$dst, $src"),
- [(set CPURegs:$dst, (bswap CPURegs:$src))], NoItinerary>;
-
-// Conditional Move
-class CondMov<bits<6> func, string instr_asm, PatLeaf MovCode>:
- FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$F, CPURegs:$T,
- CPURegs:$cond), !strconcat(instr_asm, "\t$dst, $T, $cond"),
- [], NoItinerary>;
+class ByteSwap<bits<6> func, bits<5> sa, string instr_asm>:
+ FR<0x1f, func, (outs CPURegs:$rd), (ins CPURegs:$rt),
+ !strconcat(instr_asm, "\t$rd, $rt"),
+ [(set CPURegs:$rd, (bswap CPURegs:$rt))], NoItinerary> {
+ let rs = 0;
+ let shamt = sa;
+ let Predicates = [HasSwap];
+}
// Read Hardware
-class ReadHardware: FR<0x1f, 0x3b, (outs CPURegs:$dst), (ins HWRegs:$src),
- "rdhwr\t$dst, $src", [], IIAlu> {
+class ReadHardware: FR<0x1f, 0x3b, (outs CPURegs:$rt), (ins HWRegs:$rd),
+ "rdhwr\t$rt, $rd", [], IIAlu> {
let rs = 0;
let shamt = 0;
}
+// Ext and Ins
+class ExtIns<bits<6> _funct, string instr_asm, dag outs, dag ins,
+ list<dag> pattern, InstrItinClass itin>:
+ FR<0x1f, _funct, outs, ins, !strconcat(instr_asm, " $rt, $rs, $pos, $sz"),
+ pattern, itin>, Requires<[HasMips32r2]> {
+ bits<5> pos;
+ bits<5> sz;
+ let rd = sz;
+ let shamt = pos;
+}
+
+// Atomic instructions with 2 source operands (ATOMIC_SWAP & ATOMIC_LOAD_*).
+class Atomic2Ops<PatFrag Op, string Opstr> :
+ MipsPseudo<(outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
+ !strconcat("atomic_", Opstr, "\t$dst, $ptr, $incr"),
+ [(set CPURegs:$dst,
+ (Op CPURegs:$ptr, CPURegs:$incr))]>;
+
+// Atomic Compare & Swap.
+class AtomicCmpSwap<PatFrag Op, string Width> :
+ MipsPseudo<(outs CPURegs:$dst),
+ (ins CPURegs:$ptr, CPURegs:$cmp, CPURegs:$swap),
+ !strconcat("atomic_cmp_swap_", Width,
+ "\t$dst, $ptr, $cmp, $swap"),
+ [(set CPURegs:$dst,
+ (Op CPURegs:$ptr, CPURegs:$cmp, CPURegs:$swap))]>;
+
//===----------------------------------------------------------------------===//
// Pseudo instructions
//===----------------------------------------------------------------------===//
@@ -427,112 +593,32 @@ def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>;
def CPRESTORE : MipsPseudo<(outs), (ins i32imm:$loc), ".cprestore\t$loc", []>;
let usesCustomInserter = 1 in {
- def ATOMIC_LOAD_ADD_I8 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_add_8\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_add_8 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_ADD_I16 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_add_16\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_add_16 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_ADD_I32 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_add_32\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_add_32 CPURegs:$ptr, CPURegs:$incr))]>;
-
- def ATOMIC_LOAD_SUB_I8 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_sub_8\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_sub_8 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_SUB_I16 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_sub_16\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_sub_16 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_SUB_I32 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_sub_32\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_sub_32 CPURegs:$ptr, CPURegs:$incr))]>;
-
- def ATOMIC_LOAD_AND_I8 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_and_8\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_and_8 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_AND_I16 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_and_16\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_and_16 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_AND_I32 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_and_32\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_and_32 CPURegs:$ptr, CPURegs:$incr))]>;
-
- def ATOMIC_LOAD_OR_I8 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_or_8\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_or_8 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_OR_I16 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_or_16\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_or_16 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_OR_I32 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_or_32\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_or_32 CPURegs:$ptr, CPURegs:$incr))]>;
-
- def ATOMIC_LOAD_XOR_I8 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_xor_8\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_xor_8 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_XOR_I16 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_xor_16\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_xor_16 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_XOR_I32 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_xor_32\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_xor_32 CPURegs:$ptr, CPURegs:$incr))]>;
-
- def ATOMIC_LOAD_NAND_I8 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_nand_8\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_nand_8 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_NAND_I16 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_nand_16\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_nand_16 CPURegs:$ptr, CPURegs:$incr))]>;
- def ATOMIC_LOAD_NAND_I32 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
- "atomic_load_nand_32\t$dst, $ptr, $incr",
- [(set CPURegs:$dst, (atomic_load_nand_32 CPURegs:$ptr, CPURegs:$incr))]>;
-
- def ATOMIC_SWAP_I8 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val),
- "atomic_swap_8\t$dst, $ptr, $val",
- [(set CPURegs:$dst, (atomic_swap_8 CPURegs:$ptr, CPURegs:$val))]>;
- def ATOMIC_SWAP_I16 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val),
- "atomic_swap_16\t$dst, $ptr, $val",
- [(set CPURegs:$dst, (atomic_swap_16 CPURegs:$ptr, CPURegs:$val))]>;
- def ATOMIC_SWAP_I32 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val),
- "atomic_swap_32\t$dst, $ptr, $val",
- [(set CPURegs:$dst, (atomic_swap_32 CPURegs:$ptr, CPURegs:$val))]>;
-
- def ATOMIC_CMP_SWAP_I8 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval),
- "atomic_cmp_swap_8\t$dst, $ptr, $oldval, $newval",
- [(set CPURegs:$dst,
- (atomic_cmp_swap_8 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>;
- def ATOMIC_CMP_SWAP_I16 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval),
- "atomic_cmp_swap_16\t$dst, $ptr, $oldval, $newval",
- [(set CPURegs:$dst,
- (atomic_cmp_swap_16 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>;
- def ATOMIC_CMP_SWAP_I32 : MipsPseudo<
- (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval),
- "atomic_cmp_swap_32\t$dst, $ptr, $oldval, $newval",
- [(set CPURegs:$dst,
- (atomic_cmp_swap_32 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>;
+ def ATOMIC_LOAD_ADD_I8 : Atomic2Ops<atomic_load_add_8, "load_add_8">;
+ def ATOMIC_LOAD_ADD_I16 : Atomic2Ops<atomic_load_add_16, "load_add_16">;
+ def ATOMIC_LOAD_ADD_I32 : Atomic2Ops<atomic_load_add_32, "load_add_32">;
+ def ATOMIC_LOAD_SUB_I8 : Atomic2Ops<atomic_load_sub_8, "load_sub_8">;
+ def ATOMIC_LOAD_SUB_I16 : Atomic2Ops<atomic_load_sub_16, "load_sub_16">;
+ def ATOMIC_LOAD_SUB_I32 : Atomic2Ops<atomic_load_sub_32, "load_sub_32">;
+ def ATOMIC_LOAD_AND_I8 : Atomic2Ops<atomic_load_and_8, "load_and_8">;
+ def ATOMIC_LOAD_AND_I16 : Atomic2Ops<atomic_load_and_16, "load_and_16">;
+ def ATOMIC_LOAD_AND_I32 : Atomic2Ops<atomic_load_and_32, "load_and_32">;
+ def ATOMIC_LOAD_OR_I8 : Atomic2Ops<atomic_load_or_8, "load_or_8">;
+ def ATOMIC_LOAD_OR_I16 : Atomic2Ops<atomic_load_or_16, "load_or_16">;
+ def ATOMIC_LOAD_OR_I32 : Atomic2Ops<atomic_load_or_32, "load_or_32">;
+ def ATOMIC_LOAD_XOR_I8 : Atomic2Ops<atomic_load_xor_8, "load_xor_8">;
+ def ATOMIC_LOAD_XOR_I16 : Atomic2Ops<atomic_load_xor_16, "load_xor_16">;
+ def ATOMIC_LOAD_XOR_I32 : Atomic2Ops<atomic_load_xor_32, "load_xor_32">;
+ def ATOMIC_LOAD_NAND_I8 : Atomic2Ops<atomic_load_nand_8, "load_nand_8">;
+ def ATOMIC_LOAD_NAND_I16 : Atomic2Ops<atomic_load_nand_16, "load_nand_16">;
+ def ATOMIC_LOAD_NAND_I32 : Atomic2Ops<atomic_load_nand_32, "load_nand_32">;
+
+ def ATOMIC_SWAP_I8 : Atomic2Ops<atomic_swap_8, "swap_8">;
+ def ATOMIC_SWAP_I16 : Atomic2Ops<atomic_swap_16, "swap_16">;
+ def ATOMIC_SWAP_I32 : Atomic2Ops<atomic_swap_32, "swap_32">;
+
+ def ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap<atomic_cmp_swap_8, "8">;
+ def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap<atomic_cmp_swap_16, "16">;
+ def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap<atomic_cmp_swap_32, "32">;
}
//===----------------------------------------------------------------------===//
@@ -544,26 +630,26 @@ let usesCustomInserter = 1 in {
//===----------------------------------------------------------------------===//
/// Arithmetic Instructions (ALU Immediate)
-def ADDiu : ArithI<0x09, "addiu", add, simm16, immSExt16>;
-def ADDi : ArithOverflowI<0x08, "addi", add, simm16, immSExt16>;
-def SLTi : SetCC_I<0x0a, "slti", setlt, simm16, immSExt16>;
-def SLTiu : SetCC_I<0x0b, "sltiu", setult, simm16, immSExt16>;
-def ANDi : LogicI<0x0c, "andi", and>;
-def ORi : LogicI<0x0d, "ori", or>;
-def XORi : LogicI<0x0e, "xori", xor>;
+def ADDiu : ArithLogicI<0x09, "addiu", add, simm16, immSExt16, CPURegs>;
+def ADDi : ArithOverflowI<0x08, "addi", add, simm16, immSExt16, CPURegs>;
+def SLTi : SetCC_I<0x0a, "slti", setlt, simm16, immSExt16, CPURegs>;
+def SLTiu : SetCC_I<0x0b, "sltiu", setult, simm16, immSExt16, CPURegs>;
+def ANDi : ArithLogicI<0x0c, "andi", and, uimm16, immZExt16, CPURegs>;
+def ORi : ArithLogicI<0x0d, "ori", or, uimm16, immZExt16, CPURegs>;
+def XORi : ArithLogicI<0x0e, "xori", xor, uimm16, immZExt16, CPURegs>;
def LUi : LoadUpper<0x0f, "lui">;
/// Arithmetic Instructions (3-Operand, R-Type)
-def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu, 1>;
-def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>;
-def ADD : ArithOverflowR<0x00, 0x20, "add", 1>;
-def SUB : ArithOverflowR<0x00, 0x22, "sub">;
-def SLT : SetCC_R<0x00, 0x2a, "slt", setlt>;
-def SLTu : SetCC_R<0x00, 0x2b, "sltu", setult>;
-def AND : LogicR<0x24, "and", and>;
-def OR : LogicR<0x25, "or", or>;
-def XOR : LogicR<0x26, "xor", xor>;
-def NOR : LogicNOR<0x00, 0x27, "nor">;
+def ADDu : ArithLogicR<0x00, 0x21, "addu", add, IIAlu, CPURegs, 1>;
+def SUBu : ArithLogicR<0x00, 0x23, "subu", sub, IIAlu, CPURegs>;
+def ADD : ArithOverflowR<0x00, 0x20, "add", IIAlu, CPURegs, 1>;
+def SUB : ArithOverflowR<0x00, 0x22, "sub", IIAlu, CPURegs>;
+def SLT : SetCC_R<0x00, 0x2a, "slt", setlt, CPURegs>;
+def SLTu : SetCC_R<0x00, 0x2b, "sltu", setult, CPURegs>;
+def AND : ArithLogicR<0x00, 0x24, "and", and, IIAlu, CPURegs, 1>;
+def OR : ArithLogicR<0x00, 0x25, "or", or, IIAlu, CPURegs, 1>;
+def XOR : ArithLogicR<0x00, 0x26, "xor", xor, IIAlu, CPURegs, 1>;
+def NOR : LogicNOR<0x00, 0x27, "nor", CPURegs>;
/// Shift Instructions
def SLL : LogicR_shift_rotate_imm<0x00, 0x00, "sll", shl>;
@@ -574,45 +660,58 @@ def SRLV : LogicR_shift_rotate_reg<0x06, 0x00, "srlv", srl>;
def SRAV : LogicR_shift_rotate_reg<0x07, 0x00, "srav", sra>;
// Rotate Instructions
-let Predicates = [IsMips32r2] in {
+let Predicates = [HasMips32r2] in {
def ROTR : LogicR_shift_rotate_imm<0x02, 0x01, "rotr", rotr>;
def ROTRV : LogicR_shift_rotate_reg<0x06, 0x01, "rotrv", rotr>;
}
/// Load and Store Instructions
-def LB : LoadM<0x20, "lb", sextloadi8>;
-def LBu : LoadM<0x24, "lbu", zextloadi8>;
-def LH : LoadM<0x21, "lh", sextloadi16>;
-def LHu : LoadM<0x25, "lhu", zextloadi16>;
-def LW : LoadM<0x23, "lw", load>;
-def SB : StoreM<0x28, "sb", truncstorei8>;
-def SH : StoreM<0x29, "sh", truncstorei16>;
-def SW : StoreM<0x2b, "sw", store>;
+/// aligned
+defm LB : LoadM32<0x20, "lb", sextloadi8>;
+defm LBu : LoadM32<0x24, "lbu", zextloadi8>;
+defm LH : LoadM32<0x21, "lh", sextloadi16_a>;
+defm LHu : LoadM32<0x25, "lhu", zextloadi16_a>;
+defm LW : LoadM32<0x23, "lw", load_a>;
+defm SB : StoreM32<0x28, "sb", truncstorei8>;
+defm SH : StoreM32<0x29, "sh", truncstorei16_a>;
+defm SW : StoreM32<0x2b, "sw", store_a>;
+
+/// unaligned
+defm ULH : LoadM32<0x21, "ulh", sextloadi16_u, 1>;
+defm ULHu : LoadM32<0x25, "ulhu", zextloadi16_u, 1>;
+defm ULW : LoadM32<0x23, "ulw", load_u, 1>;
+defm USH : StoreM32<0x29, "ush", truncstorei16_u, 1>;
+defm USW : StoreM32<0x2b, "usw", store_u, 1>;
+
+let hasSideEffects = 1 in
+def SYNC : MipsInst<(outs), (ins i32imm:$stype), "sync $stype",
+ [(MipsSync imm:$stype)], NoItinerary>
+{
+ let opcode = 0;
+ let Inst{25-11} = 0;
+ let Inst{5-0} = 15;
+}
/// Load-linked, Store-conditional
-let hasDelaySlot = 1 in
+let mayLoad = 1 in
def LL : FI<0x30, (outs CPURegs:$dst), (ins mem:$addr),
"ll\t$dst, $addr", [], IILoad>;
-let Constraints = "$src = $dst" in
+let mayStore = 1, Constraints = "$src = $dst" in
def SC : FI<0x38, (outs CPURegs:$dst), (ins CPURegs:$src, mem:$addr),
"sc\t$src, $addr", [], IIStore>;
/// Jump and Branch Instructions
def J : JumpFJ<0x02, "j">;
-def JR : JumpFR<0x00, 0x08, "jr">;
+let isIndirectBranch = 1 in
+ def JR : JumpFR<0x00, 0x08, "jr">;
def JAL : JumpLink<0x03, "jal">;
def JALR : JumpLinkReg<0x00, 0x09, "jalr">;
-def BEQ : CBranch<0x04, "beq", seteq>;
-def BNE : CBranch<0x05, "bne", setne>;
-
-let rt=1 in
- def BGEZ : CBranchZero<0x01, "bgez", setge>;
-
-let rt=0 in {
- def BGTZ : CBranchZero<0x07, "bgtz", setgt>;
- def BLEZ : CBranchZero<0x07, "blez", setle>;
- def BLTZ : CBranchZero<0x01, "bltz", setlt>;
-}
+def BEQ : CBranch<0x04, "beq", seteq, CPURegs>;
+def BNE : CBranch<0x05, "bne", setne, CPURegs>;
+def BGEZ : CBranchZero<0x01, 1, "bgez", setge, CPURegs>;
+def BGTZ : CBranchZero<0x07, 0, "bgtz", setgt, CPURegs>;
+def BLEZ : CBranchZero<0x07, 0, "blez", setle, CPURegs>;
+def BLTZ : CBranchZero<0x01, 0, "bltz", setlt, CPURegs>;
def BGEZAL : BranchLink<"bgezal">;
def BLTZAL : BranchLink<"bltzal">;
@@ -639,40 +738,31 @@ let Uses = [LO] in
def MFLO : MoveFromLOHI<0x12, "mflo">;
/// Sign Ext In Register Instructions.
-let Predicates = [HasSEInReg] in {
- let shamt = 0x10, rs = 0 in
- def SEB : SignExtInReg<0x21, "seb", i8>;
-
- let shamt = 0x18, rs = 0 in
- def SEH : SignExtInReg<0x20, "seh", i16>;
-}
+def SEB : SignExtInReg<0x10, "seb", i8>;
+def SEH : SignExtInReg<0x18, "seh", i16>;
/// Count Leading
-def CLZ : CountLeading<0b100000, "clz",
- [(set CPURegs:$dst, (ctlz CPURegs:$src))]>;
-def CLO : CountLeading<0b100001, "clo",
- [(set CPURegs:$dst, (ctlz (not CPURegs:$src)))]>;
+def CLZ : CountLeading<0x20, "clz",
+ [(set CPURegs:$rd, (ctlz CPURegs:$rs))]>;
+def CLO : CountLeading<0x21, "clo",
+ [(set CPURegs:$rd, (ctlz (not CPURegs:$rs)))]>;
/// Byte Swap
-let Predicates = [HasSwap] in {
- let shamt = 0x3, rs = 0 in
- def WSBW : ByteSwap<0x20, "wsbw">;
-}
-
-/// Conditional Move
-def MIPS_CMOV_ZERO : PatLeaf<(i32 0)>;
-def MIPS_CMOV_NZERO : PatLeaf<(i32 1)>;
+def WSBW : ByteSwap<0x20, 0x2, "wsbw">;
// Conditional moves:
// These instructions are expanded in
// MipsISelLowering::EmitInstrWithCustomInserter if target does not have
// conditional move instructions.
// flag:int, data:int
-let usesCustomInserter = 1, shamt = 0, Constraints = "$F = $dst" in
- class CondMovIntInt<bits<6> funct, string instr_asm> :
- FR<0, funct, (outs CPURegs:$dst),
- (ins CPURegs:$T, CPURegs:$cond, CPURegs:$F),
- !strconcat(instr_asm, "\t$dst, $T, $cond"), [], NoItinerary>;
+class CondMovIntInt<bits<6> funct, string instr_asm> :
+ FR<0, funct, (outs CPURegs:$rd),
+ (ins CPURegs:$rs, CPURegs:$rt, CPURegs:$F),
+ !strconcat(instr_asm, "\t$rd, $rs, $rt"), [], NoItinerary> {
+ let shamt = 0;
+ let usesCustomInserter = 1;
+ let Constraints = "$F = $rd";
+}
def MOVZ_I : CondMovIntInt<0x0a, "movz">;
def MOVN_I : CondMovIntInt<0x0b, "movn">;
@@ -685,13 +775,13 @@ let addr=0 in
// instructions. The same not happens for stack address copies, so an
// add op with mem ComplexPattern is used and the stack address copy
// can be matched. It's similar to Sparc LEA_ADDRi
-def LEA_ADDiu : EffectiveAddress<"addiu\t$dst, $addr">;
+def LEA_ADDiu : EffectiveAddress<"addiu\t$rt, $addr">;
// DynAlloc node points to dynamically allocated stack space.
// $sp is added to the list of implicitly used registers to prevent dead code
// elimination from removing instructions that modify $sp.
let Uses = [SP] in
-def DynAlloc : EffectiveAddress<"addiu\t$dst, $addr">;
+def DynAlloc : EffectiveAddress<"addiu\t$rt, $addr">;
// MADD*/MSUB*
def MADD : MArithR<0, "madd", MipsMAdd, 1>;
@@ -701,10 +791,25 @@ def MSUBU : MArithR<5, "msubu", MipsMSubu>;
// MUL is a assembly macro in the current used ISAs. In recent ISA's
// it is a real instruction.
-def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul, 1>, Requires<[IsMips32]>;
+def MUL : ArithLogicR<0x1c, 0x02, "mul", mul, IIImul, CPURegs, 1>,
+ Requires<[HasMips32]>;
def RDHWR : ReadHardware;
+def EXT : ExtIns<0, "ext", (outs CPURegs:$rt),
+ (ins CPURegs:$rs, uimm16:$pos, uimm16:$sz),
+ [(set CPURegs:$rt,
+ (MipsExt CPURegs:$rs, immZExt5:$pos, immZExt5:$sz))],
+ NoItinerary>;
+
+let Constraints = "$src = $rt" in
+def INS : ExtIns<4, "ins", (outs CPURegs:$rt),
+ (ins CPURegs:$rs, uimm16:$pos, uimm16:$sz, CPURegs:$src),
+ [(set CPURegs:$rt,
+ (MipsIns CPURegs:$rs, immZExt5:$pos, immZExt5:$sz,
+ CPURegs:$src))],
+ NoItinerary>;
+
//===----------------------------------------------------------------------===//
// Arbitrary patterns that map to one or more instructions
//===----------------------------------------------------------------------===//
@@ -738,16 +843,20 @@ def : Pat<(MipsJmpLink (i32 texternalsym:$dst)),
// hi/lo relocs
def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
def : Pat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>;
+def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
+def : Pat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$in)>;
def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)),
(ADDiu CPURegs:$hi, tglobaladdr:$lo)>;
def : Pat<(add CPURegs:$hi, (MipsLo tblockaddress:$lo)),
(ADDiu CPURegs:$hi, tblockaddress:$lo)>;
def : Pat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>;
+def : Pat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>;
def : Pat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)),
(ADDiu CPURegs:$hi, tjumptable:$lo)>;
def : Pat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>;
+def : Pat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>;
def : Pat<(add CPURegs:$hi, (MipsLo tconstpool:$lo)),
(ADDiu CPURegs:$hi, tconstpool:$lo)>;
@@ -763,6 +872,7 @@ def : Pat<(add CPURegs:$gp, (MipsTlsGd tglobaltlsaddr:$in)),
// tprel hi/lo
def : Pat<(MipsTprelHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>;
+def : Pat<(MipsTprelLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>;
def : Pat<(add CPURegs:$hi, (MipsTprelLo tglobaltlsaddr:$lo)),
(ADDiu CPURegs:$hi, tglobaltlsaddr:$lo)>;
@@ -784,60 +894,67 @@ def : Pat<(not CPURegs:$in),
// extended load and stores
def : Pat<(extloadi1 addr:$src), (LBu addr:$src)>;
def : Pat<(extloadi8 addr:$src), (LBu addr:$src)>;
-def : Pat<(extloadi16 addr:$src), (LHu addr:$src)>;
+def : Pat<(extloadi16_a addr:$src), (LHu addr:$src)>;
+def : Pat<(extloadi16_u addr:$src), (ULHu addr:$src)>;
// peepholes
def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
// brcond patterns
-def : Pat<(brcond (setne CPURegs:$lhs, 0), bb:$dst),
- (BNE CPURegs:$lhs, ZERO, bb:$dst)>;
-def : Pat<(brcond (seteq CPURegs:$lhs, 0), bb:$dst),
- (BEQ CPURegs:$lhs, ZERO, bb:$dst)>;
-
-def : Pat<(brcond (setge CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BEQ (SLT CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>;
-def : Pat<(brcond (setuge CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BEQ (SLTu CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>;
-def : Pat<(brcond (setge CPURegs:$lhs, immSExt16:$rhs), bb:$dst),
- (BEQ (SLTi CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
-def : Pat<(brcond (setuge CPURegs:$lhs, immSExt16:$rhs), bb:$dst),
- (BEQ (SLTiu CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
-
-def : Pat<(brcond (setle CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BEQ (SLT CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>;
-def : Pat<(brcond (setule CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BEQ (SLTu CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>;
-
-def : Pat<(brcond CPURegs:$cond, bb:$dst),
- (BNE CPURegs:$cond, ZERO, bb:$dst)>;
+multiclass BrcondPats<RegisterClass RC, Instruction BEQOp, Instruction BNEOp,
+ Instruction SLTOp, Instruction SLTuOp, Instruction SLTiOp,
+ Instruction SLTiuOp, Register ZEROReg> {
+def : Pat<(brcond (i32 (setne RC:$lhs, 0)), bb:$dst),
+ (BNEOp RC:$lhs, ZEROReg, bb:$dst)>;
+def : Pat<(brcond (i32 (seteq RC:$lhs, 0)), bb:$dst),
+ (BEQOp RC:$lhs, ZEROReg, bb:$dst)>;
+
+def : Pat<(brcond (i32 (setge RC:$lhs, RC:$rhs)), bb:$dst),
+ (BEQ (SLTOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (i32 (setuge RC:$lhs, RC:$rhs)), bb:$dst),
+ (BEQ (SLTuOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (i32 (setge RC:$lhs, immSExt16:$rhs)), bb:$dst),
+ (BEQ (SLTiOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (i32 (setuge RC:$lhs, immSExt16:$rhs)), bb:$dst),
+ (BEQ (SLTiuOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
+
+def : Pat<(brcond (i32 (setle RC:$lhs, RC:$rhs)), bb:$dst),
+ (BEQ (SLTOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (i32 (setule RC:$lhs, RC:$rhs)), bb:$dst),
+ (BEQ (SLTuOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>;
+
+def : Pat<(brcond RC:$cond, bb:$dst),
+ (BNEOp RC:$cond, ZEROReg, bb:$dst)>;
+}
+
+defm : BrcondPats<CPURegs, BEQ, BNE, SLT, SLTu, SLTi, SLTiu, ZERO>;
// select patterns
multiclass MovzPats<RegisterClass RC, Instruction MOVZInst> {
- def : Pat<(select (setge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
+ def : Pat<(select (i32 (setge CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F),
(MOVZInst RC:$T, (SLT CPURegs:$lhs, CPURegs:$rhs), RC:$F)>;
- def : Pat<(select (setuge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
+ def : Pat<(select (i32 (setuge CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F),
(MOVZInst RC:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs), RC:$F)>;
- def : Pat<(select (setge CPURegs:$lhs, immSExt16:$rhs), RC:$T, RC:$F),
+ def : Pat<(select (i32 (setge CPURegs:$lhs, immSExt16:$rhs)), RC:$T, RC:$F),
(MOVZInst RC:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs), RC:$F)>;
- def : Pat<(select (setuge CPURegs:$lh, immSExt16:$rh), RC:$T, RC:$F),
+ def : Pat<(select (i32 (setuge CPURegs:$lh, immSExt16:$rh)), RC:$T, RC:$F),
(MOVZInst RC:$T, (SLTiu CPURegs:$lh, immSExt16:$rh), RC:$F)>;
- def : Pat<(select (setle CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
+ def : Pat<(select (i32 (setle CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F),
(MOVZInst RC:$T, (SLT CPURegs:$rhs, CPURegs:$lhs), RC:$F)>;
- def : Pat<(select (setule CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
+ def : Pat<(select (i32 (setule CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F),
(MOVZInst RC:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs), RC:$F)>;
- def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
+ def : Pat<(select (i32 (seteq CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F),
(MOVZInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>;
- def : Pat<(select (seteq CPURegs:$lhs, 0), RC:$T, RC:$F),
+ def : Pat<(select (i32 (seteq CPURegs:$lhs, 0)), RC:$T, RC:$F),
(MOVZInst RC:$T, CPURegs:$lhs, RC:$F)>;
}
multiclass MovnPats<RegisterClass RC, Instruction MOVNInst> {
- def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
+ def : Pat<(select (i32 (setne CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F),
(MOVNInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>;
def : Pat<(select CPURegs:$cond, RC:$T, RC:$F),
(MOVNInst RC:$T, CPURegs:$cond, RC:$F)>;
- def : Pat<(select (setne CPURegs:$lhs, 0), RC:$T, RC:$F),
+ def : Pat<(select (i32 (setne CPURegs:$lhs, 0)), RC:$T, RC:$F),
(MOVNInst RC:$T, CPURegs:$lhs, RC:$F)>;
}
@@ -845,30 +962,48 @@ defm : MovzPats<CPURegs, MOVZ_I>;
defm : MovnPats<CPURegs, MOVN_I>;
// setcc patterns
-def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs),
- (SLTu (XOR CPURegs:$lhs, CPURegs:$rhs), 1)>;
-def : Pat<(setne CPURegs:$lhs, CPURegs:$rhs),
- (SLTu ZERO, (XOR CPURegs:$lhs, CPURegs:$rhs))>;
-
-def : Pat<(setle CPURegs:$lhs, CPURegs:$rhs),
- (XORi (SLT CPURegs:$rhs, CPURegs:$lhs), 1)>;
-def : Pat<(setule CPURegs:$lhs, CPURegs:$rhs),
- (XORi (SLTu CPURegs:$rhs, CPURegs:$lhs), 1)>;
-
-def : Pat<(setgt CPURegs:$lhs, CPURegs:$rhs),
- (SLT CPURegs:$rhs, CPURegs:$lhs)>;
-def : Pat<(setugt CPURegs:$lhs, CPURegs:$rhs),
- (SLTu CPURegs:$rhs, CPURegs:$lhs)>;
-
-def : Pat<(setge CPURegs:$lhs, CPURegs:$rhs),
- (XORi (SLT CPURegs:$lhs, CPURegs:$rhs), 1)>;
-def : Pat<(setuge CPURegs:$lhs, CPURegs:$rhs),
- (XORi (SLTu CPURegs:$lhs, CPURegs:$rhs), 1)>;
-
-def : Pat<(setge CPURegs:$lhs, immSExt16:$rhs),
- (XORi (SLTi CPURegs:$lhs, immSExt16:$rhs), 1)>;
-def : Pat<(setuge CPURegs:$lhs, immSExt16:$rhs),
- (XORi (SLTiu CPURegs:$lhs, immSExt16:$rhs), 1)>;
+multiclass SeteqPats<RegisterClass RC, Instruction SLTiuOp, Instruction XOROp,
+ Instruction SLTuOp, Register ZEROReg> {
+ def : Pat<(seteq RC:$lhs, RC:$rhs),
+ (SLTiuOp (XOROp RC:$lhs, RC:$rhs), 1)>;
+ def : Pat<(setne RC:$lhs, RC:$rhs),
+ (SLTuOp ZEROReg, (XOROp RC:$lhs, RC:$rhs))>;
+}
+
+multiclass SetlePats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> {
+ def : Pat<(setle RC:$lhs, RC:$rhs),
+ (XORi (SLTOp RC:$rhs, RC:$lhs), 1)>;
+ def : Pat<(setule RC:$lhs, RC:$rhs),
+ (XORi (SLTuOp RC:$rhs, RC:$lhs), 1)>;
+}
+
+multiclass SetgtPats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> {
+ def : Pat<(setgt RC:$lhs, RC:$rhs),
+ (SLTOp RC:$rhs, RC:$lhs)>;
+ def : Pat<(setugt RC:$lhs, RC:$rhs),
+ (SLTuOp RC:$rhs, RC:$lhs)>;
+}
+
+multiclass SetgePats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> {
+ def : Pat<(setge RC:$lhs, RC:$rhs),
+ (XORi (SLTOp RC:$lhs, RC:$rhs), 1)>;
+ def : Pat<(setuge RC:$lhs, RC:$rhs),
+ (XORi (SLTuOp RC:$lhs, RC:$rhs), 1)>;
+}
+
+multiclass SetgeImmPats<RegisterClass RC, Instruction SLTiOp,
+ Instruction SLTiuOp> {
+ def : Pat<(setge RC:$lhs, immSExt16:$rhs),
+ (XORi (SLTiOp RC:$lhs, immSExt16:$rhs), 1)>;
+ def : Pat<(setuge RC:$lhs, immSExt16:$rhs),
+ (XORi (SLTiuOp RC:$lhs, immSExt16:$rhs), 1)>;
+}
+
+defm : SeteqPats<CPURegs, SLTiu, XOR, SLTu, ZERO>;
+defm : SetlePats<CPURegs, SLT, SLTu>;
+defm : SetgtPats<CPURegs, SLT, SLTu>;
+defm : SetgePats<CPURegs, SLT, SLTu>;
+defm : SetgeImmPats<CPURegs, SLTi, SLTiu>;
// select MipsDynAlloc
def : Pat<(MipsDynAlloc addr:$f), (DynAlloc addr:$f)>;
@@ -878,4 +1013,5 @@ def : Pat<(MipsDynAlloc addr:$f), (DynAlloc addr:$f)>;
//===----------------------------------------------------------------------===//
include "MipsInstrFPU.td"
+include "Mips64InstrInfo.td"
diff --git a/lib/Target/Mips/MipsJITInfo.cpp b/lib/Target/Mips/MipsJITInfo.cpp
new file mode 100644
index 0000000..28c2b48
--- /dev/null
+++ b/lib/Target/Mips/MipsJITInfo.cpp
@@ -0,0 +1,230 @@
+//===- MipsJITInfo.cpp - Implement the JIT interfaces for the Mips target -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the JIT interfaces for the Mips target.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "jit"
+#include "MipsJITInfo.h"
+#include "MipsInstrInfo.h"
+#include "MipsRelocations.h"
+#include "MipsSubtarget.h"
+#include "llvm/Function.h"
+#include "llvm/CodeGen/JITCodeEmitter.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Memory.h"
+#include <cstdlib>
+using namespace llvm;
+
+
+void MipsJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
+ report_fatal_error("MipsJITInfo::replaceMachineCodeForFunction");
+}
+
+/// JITCompilerFunction - This contains the address of the JIT function used to
+/// compile a function lazily.
+static TargetJITInfo::JITCompilerFn JITCompilerFunction;
+
+// Get the ASMPREFIX for the current host. This is often '_'.
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__
+#endif
+#define GETASMPREFIX2(X) #X
+#define GETASMPREFIX(X) GETASMPREFIX2(X)
+#define ASMPREFIX GETASMPREFIX(__USER_LABEL_PREFIX__)
+
+// CompilationCallback stub - We can't use a C function with inline assembly in
+// it, because the prolog/epilog inserted by GCC won't work for us. Instead,
+// write our own wrapper, which does things our way, so we have complete control
+// over register saving and restoring. This code saves registers, calls
+// MipsCompilationCallbackC and restores registers.
+extern "C" {
+#if defined (__mips__)
+void MipsCompilationCallback();
+
+ asm(
+ ".text\n"
+ ".align 2\n"
+ ".globl " ASMPREFIX "MipsCompilationCallback\n"
+ ASMPREFIX "MipsCompilationCallback:\n"
+ ".ent " ASMPREFIX "MipsCompilationCallback\n"
+ ".frame $29, 32, $31\n"
+ ".set noreorder\n"
+ ".cpload $t9\n"
+
+ "addiu $sp, $sp, -60\n"
+ ".cprestore 16\n"
+
+ // Save argument registers a0, a1, a2, a3, f12, f14 since they may contain
+ // stuff for the real target function right now. We have to act as if this
+ // whole compilation callback doesn't exist as far as the caller is
+ // concerned. We also need to save the ra register since it contains the
+ // original return address, and t8 register since it contains the address
+ // of the end of function stub.
+ "sw $a0, 20($sp)\n"
+ "sw $a1, 24($sp)\n"
+ "sw $a2, 28($sp)\n"
+ "sw $a3, 32($sp)\n"
+ "sw $ra, 36($sp)\n"
+ "sw $t8, 40($sp)\n"
+ "sdc1 $f12, 44($sp)\n"
+ "sdc1 $f14, 52($sp)\n"
+
+ // t8 points at the end of function stub. Pass the beginning of the stub
+ // to the MipsCompilationCallbackC.
+ "addiu $a0, $t8, -16\n"
+ "jal " ASMPREFIX "MipsCompilationCallbackC\n"
+ "nop\n"
+
+ // Restore registers.
+ "lw $a0, 20($sp)\n"
+ "lw $a1, 24($sp)\n"
+ "lw $a2, 28($sp)\n"
+ "lw $a3, 32($sp)\n"
+ "lw $ra, 36($sp)\n"
+ "lw $t8, 40($sp)\n"
+ "ldc1 $f12, 44($sp)\n"
+ "ldc1 $f14, 52($sp)\n"
+ "addiu $sp, $sp, 60\n"
+
+ // Jump to the (newly modified) stub to invoke the real function.
+ "addiu $t8, $t8, -16\n"
+ "jr $t8\n"
+ "nop\n"
+
+ ".set reorder\n"
+ ".end " ASMPREFIX "MipsCompilationCallback\n"
+ );
+#else // host != Mips
+ void MipsCompilationCallback() {
+ llvm_unreachable(
+ "Cannot call MipsCompilationCallback() on a non-Mips arch!");
+ }
+#endif
+}
+
+/// MipsCompilationCallbackC - This is the target-specific function invoked
+/// by the function stub when we did not know the real target of a call.
+/// This function must locate the start of the stub or call site and pass
+/// it into the JIT compiler function.
+extern "C" void MipsCompilationCallbackC(intptr_t StubAddr) {
+ // Get the address of the compiled code for this function.
+ intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr);
+
+ // Rewrite the function stub so that we don't end up here every time we
+ // execute the call. We're replacing the first four instructions of the
+ // stub with code that jumps to the compiled function:
+ // lui $t9, %hi(NewVal)
+ // addiu $t9, $t9, %lo(NewVal)
+ // jr $t9
+ // nop
+
+ int Hi = ((unsigned)NewVal & 0xffff0000) >> 16;
+ if ((NewVal & 0x8000) != 0)
+ Hi++;
+ int Lo = (int)(NewVal & 0xffff);
+
+ *(intptr_t *)(StubAddr) = 0xf << 26 | 25 << 16 | Hi;
+ *(intptr_t *)(StubAddr + 4) = 9 << 26 | 25 << 21 | 25 << 16 | Lo;
+ *(intptr_t *)(StubAddr + 8) = 25 << 21 | 8;
+ *(intptr_t *)(StubAddr + 12) = 0;
+
+ sys::Memory::InvalidateInstructionCache((void*) StubAddr, 16);
+}
+
+TargetJITInfo::LazyResolverFn MipsJITInfo::getLazyResolverFunction(
+ JITCompilerFn F) {
+ JITCompilerFunction = F;
+ return MipsCompilationCallback;
+}
+
+TargetJITInfo::StubLayout MipsJITInfo::getStubLayout() {
+ // The stub contains 4 4-byte instructions, aligned at 4 bytes. See
+ // emitFunctionStub for details.
+ StubLayout Result = { 4*4, 4 };
+ return Result;
+}
+
+void *MipsJITInfo::emitFunctionStub(const Function* F, void *Fn,
+ JITCodeEmitter &JCE) {
+ JCE.emitAlignment(4);
+ void *Addr = (void*) (JCE.getCurrentPCValue());
+ if (!sys::Memory::setRangeWritable(Addr, 16))
+ llvm_unreachable("ERROR: Unable to mark stub writable.");
+
+ intptr_t EmittedAddr;
+ if (Fn != (void*)(intptr_t)MipsCompilationCallback)
+ EmittedAddr = (intptr_t)Fn;
+ else
+ EmittedAddr = (intptr_t)MipsCompilationCallback;
+
+
+ int Hi = ((unsigned)EmittedAddr & 0xffff0000) >> 16;
+ if ((EmittedAddr & 0x8000) != 0)
+ Hi++;
+ int Lo = (int)(EmittedAddr & 0xffff);
+
+ // lui t9, %hi(EmittedAddr)
+ // addiu t9, t9, %lo(EmittedAddr)
+ // jalr t8, t9
+ // nop
+ JCE.emitWordLE(0xf << 26 | 25 << 16 | Hi);
+ JCE.emitWordLE(9 << 26 | 25 << 21 | 25 << 16 | Lo);
+ JCE.emitWordLE(25 << 21 | 24 << 11 | 9);
+ JCE.emitWordLE(0);
+
+ sys::Memory::InvalidateInstructionCache(Addr, 16);
+ if (!sys::Memory::setRangeExecutable(Addr, 16))
+ llvm_unreachable("ERROR: Unable to mark stub executable.");
+
+ return Addr;
+}
+
+/// relocate - Before the JIT can run a block of code that has been emitted,
+/// it must rewrite the code to contain the actual addresses of any
+/// referenced global symbols.
+void MipsJITInfo::relocate(void *Function, MachineRelocation *MR,
+ unsigned NumRelocs, unsigned char* GOTBase) {
+ for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
+
+ void *RelocPos = (char*) Function + MR->getMachineCodeOffset();
+ intptr_t ResultPtr = (intptr_t) MR->getResultPointer();
+
+ switch ((Mips::RelocationType) MR->getRelocationType()) {
+ case Mips::reloc_mips_branch:
+ ResultPtr = (((ResultPtr - (intptr_t) RelocPos) - 4) >> 2) & 0xffff;
+ *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
+ break;
+
+ case Mips::reloc_mips_26:
+ ResultPtr = (ResultPtr & 0x0fffffff) >> 2;
+ *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
+ break;
+
+ case Mips::reloc_mips_hi:
+ ResultPtr = ResultPtr >> 16;
+ if ((((intptr_t) (MR->getResultPointer()) & 0xffff) >> 15) == 1) {
+ ResultPtr += 1;
+ }
+ *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
+ break;
+
+ case Mips::reloc_mips_lo:
+ ResultPtr = ResultPtr & 0xffff;
+ *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
+ break;
+
+ default:
+ llvm_unreachable("ERROR: Unknown Mips relocation.");
+ }
+ }
+}
diff --git a/lib/Target/Mips/MipsJITInfo.h b/lib/Target/Mips/MipsJITInfo.h
new file mode 100644
index 0000000..41f32a3
--- /dev/null
+++ b/lib/Target/Mips/MipsJITInfo.h
@@ -0,0 +1,70 @@
+//===- MipsJITInfo.h - Mips implementation of the JIT interface -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the MipsJITInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MIPSJITINFO_H
+#define MIPSJITINFO_H
+
+#include "MipsMachineFunction.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/Target/TargetJITInfo.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+class MipsTargetMachine;
+
+class MipsJITInfo : public TargetJITInfo {
+
+ bool IsPIC;
+
+ public:
+ explicit MipsJITInfo() :
+ IsPIC(false) {}
+
+ /// replaceMachineCodeForFunction - Make it so that calling the function
+ /// whose machine code is at OLD turns into a call to NEW, perhaps by
+ /// overwriting OLD with a branch to NEW. This is used for self-modifying
+ /// code.
+ ///
+ virtual void replaceMachineCodeForFunction(void *Old, void *New);
+
+ // getStubLayout - Returns the size and alignment of the largest call stub
+ // on Mips.
+ virtual StubLayout getStubLayout();
+
+ /// emitFunctionStub - Use the specified JITCodeEmitter object to emit a
+ /// small native function that simply calls the function at the specified
+ /// address.
+ virtual void *emitFunctionStub(const Function* F, void *Fn,
+ JITCodeEmitter &JCE);
+
+ /// getLazyResolverFunction - Expose the lazy resolver to the JIT.
+ virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn);
+
+ /// relocate - Before the JIT can run a block of code that has been emitted,
+ /// it must rewrite the code to contain the actual addresses of any
+ /// referenced global symbols.
+ virtual void relocate(void *Function, MachineRelocation *MR,
+ unsigned NumRelocs, unsigned char* GOTBase);
+
+ /// Initialize - Initialize internal stage for the function being JITted.
+ void Initialize(const MachineFunction &MF, bool isPIC) {
+ IsPIC = isPIC;
+ }
+
+};
+}
+
+#endif
diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp
index f5cc3aa..608a7d2 100644
--- a/lib/Target/Mips/MipsMCInstLower.cpp
+++ b/lib/Target/Mips/MipsMCInstLower.cpp
@@ -29,10 +29,10 @@ MipsMCInstLower::MipsMCInstLower(Mangler *mang, const MachineFunction &mf,
: Ctx(mf.getContext()), Mang(mang), AsmPrinter(asmprinter) {}
MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
- MachineOperandType MOTy) const {
+ MachineOperandType MOTy,
+ unsigned Offset) const {
MipsMCSymbolRefExpr::VariantKind Kind;
const MCSymbol *Symbol;
- int Offset = 0;
switch(MO.getTargetFlags()) {
default: assert(0 && "Invalid target flag!");
@@ -46,6 +46,11 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
case MipsII::MO_GOTTPREL: Kind = MipsMCSymbolRefExpr::VK_Mips_GOTTPREL; break;
case MipsII::MO_TPREL_HI: Kind = MipsMCSymbolRefExpr::VK_Mips_TPREL_HI; break;
case MipsII::MO_TPREL_LO: Kind = MipsMCSymbolRefExpr::VK_Mips_TPREL_LO; break;
+ case MipsII::MO_GPOFF_HI: Kind = MipsMCSymbolRefExpr::VK_Mips_GPOFF_HI; break;
+ case MipsII::MO_GPOFF_LO: Kind = MipsMCSymbolRefExpr::VK_Mips_GPOFF_LO; break;
+ case MipsII::MO_GOT_DISP: Kind = MipsMCSymbolRefExpr::VK_Mips_GOT_DISP; break;
+ case MipsII::MO_GOT_PAGE: Kind = MipsMCSymbolRefExpr::VK_Mips_GOT_PAGE; break;
+ case MipsII::MO_GOT_OFST: Kind = MipsMCSymbolRefExpr::VK_Mips_GOT_OFST; break;
}
switch (MOTy) {
@@ -72,7 +77,7 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
case MachineOperand::MO_ConstantPoolIndex:
Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
if (MO.getOffset())
- Offset = MO.getOffset();
+ Offset += MO.getOffset();
break;
default:
@@ -83,36 +88,39 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
Ctx));
}
+MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO) const {
+ MachineOperandType MOTy = MO.getType();
+
+ switch (MOTy) {
+ default:
+ assert(0 && "unknown operand type");
+ break;
+ case MachineOperand::MO_Register:
+ // Ignore all implicit register operands.
+ if (MO.isImplicit()) break;
+ return MCOperand::CreateReg(MO.getReg());
+ case MachineOperand::MO_Immediate:
+ return MCOperand::CreateImm(MO.getImm());
+ case MachineOperand::MO_MachineBasicBlock:
+ case MachineOperand::MO_GlobalAddress:
+ case MachineOperand::MO_ExternalSymbol:
+ case MachineOperand::MO_JumpTableIndex:
+ case MachineOperand::MO_ConstantPoolIndex:
+ case MachineOperand::MO_BlockAddress:
+ return LowerSymbolOperand(MO, MOTy, 0);
+ }
+
+ return MCOperand();
+}
+
void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
OutMI.setOpcode(MI->getOpcode());
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
- MCOperand MCOp;
- MachineOperandType MOTy = MO.getType();
+ MCOperand MCOp = LowerOperand(MO);
- switch (MOTy) {
- default:
- MI->dump();
- llvm_unreachable("unknown operand type");
- case MachineOperand::MO_Register:
- // Ignore all implicit register operands.
- if (MO.isImplicit()) continue;
- MCOp = MCOperand::CreateReg(MO.getReg());
- break;
- case MachineOperand::MO_Immediate:
- MCOp = MCOperand::CreateImm(MO.getImm());
- break;
- case MachineOperand::MO_MachineBasicBlock:
- case MachineOperand::MO_GlobalAddress:
- case MachineOperand::MO_ExternalSymbol:
- case MachineOperand::MO_JumpTableIndex:
- case MachineOperand::MO_ConstantPoolIndex:
- case MachineOperand::MO_BlockAddress:
- MCOp = LowerSymbolOperand(MO, MOTy);
- break;
- }
-
- OutMI.addOperand(MCOp);
+ if (MCOp.isValid())
+ OutMI.addOperand(MCOp);
}
}
diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h
index ec5201b..223f23a 100644
--- a/lib/Target/Mips/MipsMCInstLower.h
+++ b/lib/Target/Mips/MipsMCInstLower.h
@@ -1,4 +1,4 @@
-//===-- MipsMCInstLower.h - Lower MachineInstr to MCInst -------------------===//
+//===-- MipsMCInstLower.h - Lower MachineInstr to MCInst -------------------==//
//
// The LLVM Compiler Infrastructure
//
@@ -36,7 +36,8 @@ public:
void Lower(const MachineInstr *MI, MCInst &OutMI) const;
private:
MCOperand LowerSymbolOperand(const MachineOperand &MO,
- MachineOperandType MOTy) const;
+ MachineOperandType MOTy, unsigned Offset) const;
+ MCOperand LowerOperand(const MachineOperand& MO) const;
};
}
diff --git a/lib/Target/Mips/MipsMCSymbolRefExpr.cpp b/lib/Target/Mips/MipsMCSymbolRefExpr.cpp
index 9a2bdae..a0a242c 100644
--- a/lib/Target/Mips/MipsMCSymbolRefExpr.cpp
+++ b/lib/Target/Mips/MipsMCSymbolRefExpr.cpp
@@ -33,6 +33,11 @@ void MipsMCSymbolRefExpr::PrintImpl(raw_ostream &OS) const {
case VK_Mips_GOTTPREL: OS << "%gottprel("; break;
case VK_Mips_TPREL_HI: OS << "%tprel_hi("; break;
case VK_Mips_TPREL_LO: OS << "%tprel_lo("; break;
+ case VK_Mips_GPOFF_HI: OS << "%hi(%neg(%gp_rel("; break;
+ case VK_Mips_GPOFF_LO: OS << "%lo(%neg(%gp_rel("; break;
+ case VK_Mips_GOT_DISP: OS << "%got_disp("; break;
+ case VK_Mips_GOT_PAGE: OS << "%got_page("; break;
+ case VK_Mips_GOT_OFST: OS << "%got_ofst("; break;
}
OS << *Symbol;
@@ -43,7 +48,9 @@ void MipsMCSymbolRefExpr::PrintImpl(raw_ostream &OS) const {
OS << Offset;
}
- if (Kind != VK_Mips_None)
+ if (Kind == VK_Mips_GPOFF_HI || Kind == VK_Mips_GPOFF_LO)
+ OS << ")))";
+ else if (Kind != VK_Mips_None)
OS << ')';
}
diff --git a/lib/Target/Mips/MipsMCSymbolRefExpr.h b/lib/Target/Mips/MipsMCSymbolRefExpr.h
index 3e69596..55e85a7 100644
--- a/lib/Target/Mips/MipsMCSymbolRefExpr.h
+++ b/lib/Target/Mips/MipsMCSymbolRefExpr.h
@@ -25,7 +25,12 @@ public:
VK_Mips_TLSGD,
VK_Mips_GOTTPREL,
VK_Mips_TPREL_HI,
- VK_Mips_TPREL_LO
+ VK_Mips_TPREL_LO,
+ VK_Mips_GPOFF_HI,
+ VK_Mips_GPOFF_LO,
+ VK_Mips_GOT_DISP,
+ VK_Mips_GOT_PAGE,
+ VK_Mips_GOT_OFST
};
private:
diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h
index dbb7a67..bc30b6b 100644
--- a/lib/Target/Mips/MipsMachineFunction.h
+++ b/lib/Target/Mips/MipsMachineFunction.h
@@ -51,16 +51,12 @@ private:
mutable int DynAllocFI; // Frame index of dynamically allocated stack area.
unsigned MaxCallFrameSize;
- /// AtomicFrameIndex - To implement atomic.swap and atomic.cmp.swap
- /// intrinsics, it is necessary to use a temporary stack location.
- /// This field holds the frame index of this location.
- int AtomicFrameIndex;
public:
MipsFunctionInfo(MachineFunction& MF)
: MF(MF), SRetReturnReg(0), GlobalBaseReg(0),
VarArgsFrameIndex(0), InArgFIRange(std::make_pair(-1, 0)),
OutArgFIRange(std::make_pair(-1, 0)), GPFI(0), DynAllocFI(0),
- MaxCallFrameSize(0), AtomicFrameIndex(-1)
+ MaxCallFrameSize(0)
{}
bool isInArgFI(int FI) const {
@@ -104,9 +100,6 @@ public:
unsigned getMaxCallFrameSize() const { return MaxCallFrameSize; }
void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; }
-
- int getAtomicFrameIndex() const { return AtomicFrameIndex; }
- void setAtomicFrameIndex(int Index) { AtomicFrameIndex = Index; }
};
} // end of namespace llvm
diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp
index 24390da..f8c0fda 100644
--- a/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -24,7 +24,6 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
@@ -44,7 +43,7 @@ using namespace llvm;
MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST,
const TargetInstrInfo &tii)
- : MipsGenRegisterInfo(), Subtarget(ST), TII(tii) {}
+ : MipsGenRegisterInfo(Mips::RA), Subtarget(ST), TII(tii) {}
/// getRegisterNumbering - Given the enum value for some register, e.g.
/// Mips::RA, return the number that it corresponds to (e.g. 31).
@@ -52,39 +51,87 @@ unsigned MipsRegisterInfo::
getRegisterNumbering(unsigned RegEnum)
{
switch (RegEnum) {
- case Mips::ZERO : case Mips::F0 : case Mips::D0 : return 0;
- case Mips::AT : case Mips::F1 : return 1;
- case Mips::V0 : case Mips::F2 : case Mips::D1 : return 2;
- case Mips::V1 : case Mips::F3 : return 3;
- case Mips::A0 : case Mips::F4 : case Mips::D2 : return 4;
- case Mips::A1 : case Mips::F5 : return 5;
- case Mips::A2 : case Mips::F6 : case Mips::D3 : return 6;
- case Mips::A3 : case Mips::F7 : return 7;
- case Mips::T0 : case Mips::F8 : case Mips::D4 : return 8;
- case Mips::T1 : case Mips::F9 : return 9;
- case Mips::T2 : case Mips::F10: case Mips::D5: return 10;
- case Mips::T3 : case Mips::F11: return 11;
- case Mips::T4 : case Mips::F12: case Mips::D6: return 12;
- case Mips::T5 : case Mips::F13: return 13;
- case Mips::T6 : case Mips::F14: case Mips::D7: return 14;
- case Mips::T7 : case Mips::F15: return 15;
- case Mips::S0 : case Mips::F16: case Mips::D8: return 16;
- case Mips::S1 : case Mips::F17: return 17;
- case Mips::S2 : case Mips::F18: case Mips::D9: return 18;
- case Mips::S3 : case Mips::F19: return 19;
- case Mips::S4 : case Mips::F20: case Mips::D10: return 20;
- case Mips::S5 : case Mips::F21: return 21;
- case Mips::S6 : case Mips::F22: case Mips::D11: return 22;
- case Mips::S7 : case Mips::F23: return 23;
- case Mips::T8 : case Mips::F24: case Mips::D12: return 24;
- case Mips::T9 : case Mips::F25: return 25;
- case Mips::K0 : case Mips::F26: case Mips::D13: return 26;
- case Mips::K1 : case Mips::F27: return 27;
- case Mips::GP : case Mips::F28: case Mips::D14: return 28;
- case Mips::SP : case Mips::F29: return 29;
- case Mips::FP : case Mips::F30: case Mips::D15: return 30;
- case Mips::RA : case Mips::F31: return 31;
- default: llvm_unreachable("Unknown register number!");
+ case Mips::ZERO: case Mips::ZERO_64: case Mips::F0: case Mips::D0_64:
+ case Mips::D0:
+ return 0;
+ case Mips::AT: case Mips::AT_64: case Mips::F1: case Mips::D1_64:
+ return 1;
+ case Mips::V0: case Mips::V0_64: case Mips::F2: case Mips::D2_64:
+ case Mips::D1:
+ return 2;
+ case Mips::V1: case Mips::V1_64: case Mips::F3: case Mips::D3_64:
+ return 3;
+ case Mips::A0: case Mips::A0_64: case Mips::F4: case Mips::D4_64:
+ case Mips::D2:
+ return 4;
+ case Mips::A1: case Mips::A1_64: case Mips::F5: case Mips::D5_64:
+ return 5;
+ case Mips::A2: case Mips::A2_64: case Mips::F6: case Mips::D6_64:
+ case Mips::D3:
+ return 6;
+ case Mips::A3: case Mips::A3_64: case Mips::F7: case Mips::D7_64:
+ return 7;
+ case Mips::T0: case Mips::T0_64: case Mips::F8: case Mips::D8_64:
+ case Mips::D4:
+ return 8;
+ case Mips::T1: case Mips::T1_64: case Mips::F9: case Mips::D9_64:
+ return 9;
+ case Mips::T2: case Mips::T2_64: case Mips::F10: case Mips::D10_64:
+ case Mips::D5:
+ return 10;
+ case Mips::T3: case Mips::T3_64: case Mips::F11: case Mips::D11_64:
+ return 11;
+ case Mips::T4: case Mips::T4_64: case Mips::F12: case Mips::D12_64:
+ case Mips::D6:
+ return 12;
+ case Mips::T5: case Mips::T5_64: case Mips::F13: case Mips::D13_64:
+ return 13;
+ case Mips::T6: case Mips::T6_64: case Mips::F14: case Mips::D14_64:
+ case Mips::D7:
+ return 14;
+ case Mips::T7: case Mips::T7_64: case Mips::F15: case Mips::D15_64:
+ return 15;
+ case Mips::S0: case Mips::S0_64: case Mips::F16: case Mips::D16_64:
+ case Mips::D8:
+ return 16;
+ case Mips::S1: case Mips::S1_64: case Mips::F17: case Mips::D17_64:
+ return 17;
+ case Mips::S2: case Mips::S2_64: case Mips::F18: case Mips::D18_64:
+ case Mips::D9:
+ return 18;
+ case Mips::S3: case Mips::S3_64: case Mips::F19: case Mips::D19_64:
+ return 19;
+ case Mips::S4: case Mips::S4_64: case Mips::F20: case Mips::D20_64:
+ case Mips::D10:
+ return 20;
+ case Mips::S5: case Mips::S5_64: case Mips::F21: case Mips::D21_64:
+ return 21;
+ case Mips::S6: case Mips::S6_64: case Mips::F22: case Mips::D22_64:
+ case Mips::D11:
+ return 22;
+ case Mips::S7: case Mips::S7_64: case Mips::F23: case Mips::D23_64:
+ return 23;
+ case Mips::T8: case Mips::T8_64: case Mips::F24: case Mips::D24_64:
+ case Mips::D12:
+ return 24;
+ case Mips::T9: case Mips::T9_64: case Mips::F25: case Mips::D25_64:
+ return 25;
+ case Mips::K0: case Mips::K0_64: case Mips::F26: case Mips::D26_64:
+ case Mips::D13:
+ return 26;
+ case Mips::K1: case Mips::K1_64: case Mips::F27: case Mips::D27_64:
+ return 27;
+ case Mips::GP: case Mips::GP_64: case Mips::F28: case Mips::D28_64:
+ case Mips::D14:
+ return 28;
+ case Mips::SP: case Mips::SP_64: case Mips::F29: case Mips::D29_64:
+ return 29;
+ case Mips::FP: case Mips::FP_64: case Mips::F30: case Mips::D30_64:
+ case Mips::D15:
+ return 30;
+ case Mips::RA: case Mips::RA_64: case Mips::F31: case Mips::D31_64:
+ return 31;
+ default: llvm_unreachable("Unknown register number!");
}
return 0; // Not reached
}
@@ -101,7 +148,7 @@ getCalleeSavedRegs(const MachineFunction *MF) const
{
// Mips callee-save register range is $16-$23, $f20-$f30
static const unsigned SingleFloatOnlyCalleeSavedRegs[] = {
- Mips::F30, Mips::F29, Mips::F28, Mips::F27, Mips::F26,
+ Mips::F31, Mips::F30, Mips::F29, Mips::F28, Mips::F27, Mips::F26,
Mips::F25, Mips::F24, Mips::F23, Mips::F22, Mips::F21, Mips::F20,
Mips::RA, Mips::FP, Mips::S7, Mips::S6, Mips::S5, Mips::S4,
Mips::S3, Mips::S2, Mips::S1, Mips::S0, 0
@@ -113,31 +160,71 @@ getCalleeSavedRegs(const MachineFunction *MF) const
Mips::S3, Mips::S2, Mips::S1, Mips::S0, 0
};
+ static const unsigned N32CalleeSavedRegs[] = {
+ Mips::D31_64, Mips::D29_64, Mips::D27_64, Mips::D25_64, Mips::D23_64,
+ Mips::D21_64,
+ Mips::RA_64, Mips::FP_64, Mips::GP_64, Mips::S7_64, Mips::S6_64,
+ Mips::S5_64, Mips::S4_64, Mips::S3_64, Mips::S2_64, Mips::S1_64,
+ Mips::S0_64, 0
+ };
+
+ static const unsigned N64CalleeSavedRegs[] = {
+ Mips::D31_64, Mips::D30_64, Mips::D29_64, Mips::D28_64, Mips::D27_64,
+ Mips::D26_64, Mips::D25_64, Mips::D24_64,
+ Mips::RA_64, Mips::FP_64, Mips::GP_64, Mips::S7_64, Mips::S6_64,
+ Mips::S5_64, Mips::S4_64, Mips::S3_64, Mips::S2_64, Mips::S1_64,
+ Mips::S0_64, 0
+ };
+
if (Subtarget.isSingleFloat())
return SingleFloatOnlyCalleeSavedRegs;
- else
+ else if (!Subtarget.hasMips64())
return Mips32CalleeSavedRegs;
+ else if (Subtarget.isABI_N32())
+ return N32CalleeSavedRegs;
+
+ assert(Subtarget.isABI_N64());
+ return N64CalleeSavedRegs;
}
BitVector MipsRegisterInfo::
getReservedRegs(const MachineFunction &MF) const {
+ static const unsigned ReservedCPURegs[] = {
+ Mips::ZERO, Mips::AT, Mips::K0, Mips::K1,
+ Mips::GP, Mips::SP, Mips::FP, Mips::RA, 0
+ };
+
+ static const unsigned ReservedCPU64Regs[] = {
+ Mips::ZERO_64, Mips::AT_64, Mips::K0_64, Mips::K1_64,
+ Mips::GP_64, Mips::SP_64, Mips::FP_64, Mips::RA_64, 0
+ };
+
BitVector Reserved(getNumRegs());
- Reserved.set(Mips::ZERO);
- Reserved.set(Mips::AT);
- Reserved.set(Mips::K0);
- Reserved.set(Mips::K1);
- Reserved.set(Mips::GP);
- Reserved.set(Mips::SP);
- Reserved.set(Mips::FP);
- Reserved.set(Mips::RA);
- Reserved.set(Mips::F31);
- Reserved.set(Mips::D15);
-
- // SRV4 requires that odd register can't be used.
- if (!Subtarget.isSingleFloat() && !Subtarget.isMips32())
- for (unsigned FReg=(Mips::F0)+1; FReg < Mips::F30; FReg+=2)
- Reserved.set(FReg);
+ typedef TargetRegisterClass::iterator RegIter;
+
+ for (const unsigned *Reg = ReservedCPURegs; *Reg; ++Reg)
+ Reserved.set(*Reg);
+ if (Subtarget.hasMips64()) {
+ for (const unsigned *Reg = ReservedCPU64Regs; *Reg; ++Reg)
+ Reserved.set(*Reg);
+
+ // Reserve all registers in AFGR64.
+ for (RegIter Reg = Mips::AFGR64RegisterClass->begin();
+ Reg != Mips::AFGR64RegisterClass->end(); ++Reg)
+ Reserved.set(*Reg);
+ }
+ else {
+ // Reserve all registers in CPU64Regs & FGR64.
+ for (RegIter Reg = Mips::CPU64RegsRegisterClass->begin();
+ Reg != Mips::CPU64RegsRegisterClass->end(); ++Reg)
+ Reserved.set(*Reg);
+
+ for (RegIter Reg = Mips::FGR64RegisterClass->begin();
+ Reg != Mips::FGR64RegisterClass->end(); ++Reg)
+ Reserved.set(*Reg);
+ }
+
return Reserved;
}
@@ -245,11 +332,6 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
}
unsigned MipsRegisterInfo::
-getRARegister() const {
- return Mips::RA;
-}
-
-unsigned MipsRegisterInfo::
getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
@@ -267,12 +349,3 @@ getEHHandlerRegister() const {
llvm_unreachable("What is the exception handler register");
return 0;
}
-
-int MipsRegisterInfo::
-getDwarfRegNum(unsigned RegNum, bool isEH) const {
- return MipsGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
-}
-
-int MipsRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const {
- return MipsGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0);
-}
diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h
index 646369b..67e57dd 100644
--- a/lib/Target/Mips/MipsRegisterInfo.h
+++ b/lib/Target/Mips/MipsRegisterInfo.h
@@ -57,15 +57,11 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo {
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
/// Debug information queries.
- unsigned getRARegister() const;
unsigned getFrameRegister(const MachineFunction &MF) const;
/// Exception handling queries.
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
-
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- int getLLVMRegNum(unsigned RegNum, bool isEH) const;
};
} // end namespace llvm
diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td
index f0db518..925ad9e 100644
--- a/lib/Target/Mips/MipsRegisterInfo.td
+++ b/lib/Target/Mips/MipsRegisterInfo.td
@@ -10,6 +10,11 @@
//===----------------------------------------------------------------------===//
// Declarations that describe the MIPS register file
//===----------------------------------------------------------------------===//
+let Namespace = "Mips" in {
+def sub_fpeven : SubRegIndex;
+def sub_fpodd : SubRegIndex;
+def sub_32 : SubRegIndex;
+}
// We have banks of 32 registers each.
class MipsReg<string n> : Register<n> {
@@ -28,22 +33,31 @@ class MipsGPRReg<bits<5> num, string n> : MipsReg<n> {
let Num = num;
}
+// Mips 64-bit CPU Registers
+class Mips64GPRReg<bits<5> num, string n, list<Register> subregs>
+ : MipsRegWithSubRegs<n, subregs> {
+ let Num = num;
+ let SubRegIndices = [sub_32];
+}
+
// Mips 32-bit FPU Registers
class FPR<bits<5> num, string n> : MipsReg<n> {
let Num = num;
}
// Mips 64-bit (aliased) FPU Registers
-let Namespace = "Mips" in {
-def sub_fpeven : SubRegIndex;
-def sub_fpodd : SubRegIndex;
-}
class AFPR<bits<5> num, string n, list<Register> subregs>
: MipsRegWithSubRegs<n, subregs> {
let Num = num;
let SubRegIndices = [sub_fpeven, sub_fpodd];
}
+class AFPR64<bits<5> num, string n, list<Register> subregs>
+ : MipsRegWithSubRegs<n, subregs> {
+ let Num = num;
+ let SubRegIndices = [sub_32];
+}
+
// Mips Hardware Registers
class HWR<bits<5> num, string n> : MipsReg<n> {
let Num = num;
@@ -54,6 +68,7 @@ class HWR<bits<5> num, string n> : MipsReg<n> {
//===----------------------------------------------------------------------===//
let Namespace = "Mips" in {
+ // FIXME: Fix DwarfRegNum.
// General Purpose Registers
def ZERO : MipsGPRReg< 0, "ZERO">, DwarfRegNum<[0]>;
@@ -89,6 +104,40 @@ let Namespace = "Mips" in {
def FP : MipsGPRReg< 30, "FP">, DwarfRegNum<[30]>;
def RA : MipsGPRReg< 31, "RA">, DwarfRegNum<[31]>;
+ // General Purpose 64-bit Registers
+ def ZERO_64 : Mips64GPRReg< 0, "ZERO", [ZERO]>;
+ def AT_64 : Mips64GPRReg< 1, "AT", [AT]>;
+ def V0_64 : Mips64GPRReg< 2, "2", [V0]>;
+ def V1_64 : Mips64GPRReg< 3, "3", [V1]>;
+ def A0_64 : Mips64GPRReg< 4, "4", [A0]>;
+ def A1_64 : Mips64GPRReg< 5, "5", [A1]>;
+ def A2_64 : Mips64GPRReg< 6, "6", [A2]>;
+ def A3_64 : Mips64GPRReg< 7, "7", [A3]>;
+ def T0_64 : Mips64GPRReg< 8, "8", [T0]>;
+ def T1_64 : Mips64GPRReg< 9, "9", [T1]>;
+ def T2_64 : Mips64GPRReg< 10, "10", [T2]>;
+ def T3_64 : Mips64GPRReg< 11, "11", [T3]>;
+ def T4_64 : Mips64GPRReg< 12, "12", [T4]>;
+ def T5_64 : Mips64GPRReg< 13, "13", [T5]>;
+ def T6_64 : Mips64GPRReg< 14, "14", [T6]>;
+ def T7_64 : Mips64GPRReg< 15, "15", [T7]>;
+ def S0_64 : Mips64GPRReg< 16, "16", [S0]>;
+ def S1_64 : Mips64GPRReg< 17, "17", [S1]>;
+ def S2_64 : Mips64GPRReg< 18, "18", [S2]>;
+ def S3_64 : Mips64GPRReg< 19, "19", [S3]>;
+ def S4_64 : Mips64GPRReg< 20, "20", [S4]>;
+ def S5_64 : Mips64GPRReg< 21, "21", [S5]>;
+ def S6_64 : Mips64GPRReg< 22, "22", [S6]>;
+ def S7_64 : Mips64GPRReg< 23, "23", [S7]>;
+ def T8_64 : Mips64GPRReg< 24, "24", [T8]>;
+ def T9_64 : Mips64GPRReg< 25, "25", [T9]>;
+ def K0_64 : Mips64GPRReg< 26, "26", [K0]>;
+ def K1_64 : Mips64GPRReg< 27, "27", [K1]>;
+ def GP_64 : Mips64GPRReg< 28, "GP", [GP]>;
+ def SP_64 : Mips64GPRReg< 29, "SP", [SP]>;
+ def FP_64 : Mips64GPRReg< 30, "FP", [FP]>;
+ def RA_64 : Mips64GPRReg< 31, "RA", [RA]>;
+
/// Mips Single point precision FPU Registers
def F0 : FPR< 0, "F0">, DwarfRegNum<[32]>;
def F1 : FPR< 1, "F1">, DwarfRegNum<[33]>;
@@ -142,10 +191,49 @@ let Namespace = "Mips" in {
def D14 : AFPR<28, "F28", [F28, F29]>;
def D15 : AFPR<30, "F30", [F30, F31]>;
+ /// Mips Double point precision FPU Registers in MFP64 mode.
+ def D0_64 : AFPR64<0, "F0", [F0]>;
+ def D1_64 : AFPR64<1, "F1", [F1]>;
+ def D2_64 : AFPR64<2, "F2", [F2]>;
+ def D3_64 : AFPR64<3, "F3", [F3]>;
+ def D4_64 : AFPR64<4, "F4", [F4]>;
+ def D5_64 : AFPR64<5, "F5", [F5]>;
+ def D6_64 : AFPR64<6, "F6", [F6]>;
+ def D7_64 : AFPR64<7, "F7", [F7]>;
+ def D8_64 : AFPR64<8, "F8", [F8]>;
+ def D9_64 : AFPR64<9, "F9", [F9]>;
+ def D10_64 : AFPR64<10, "F10", [F10]>;
+ def D11_64 : AFPR64<11, "F11", [F11]>;
+ def D12_64 : AFPR64<12, "F12", [F12]>;
+ def D13_64 : AFPR64<13, "F13", [F13]>;
+ def D14_64 : AFPR64<14, "F14", [F14]>;
+ def D15_64 : AFPR64<15, "F15", [F15]>;
+ def D16_64 : AFPR64<16, "F16", [F16]>;
+ def D17_64 : AFPR64<17, "F17", [F17]>;
+ def D18_64 : AFPR64<18, "F18", [F18]>;
+ def D19_64 : AFPR64<19, "F19", [F19]>;
+ def D20_64 : AFPR64<20, "F20", [F20]>;
+ def D21_64 : AFPR64<21, "F21", [F21]>;
+ def D22_64 : AFPR64<22, "F22", [F22]>;
+ def D23_64 : AFPR64<23, "F23", [F23]>;
+ def D24_64 : AFPR64<24, "F24", [F24]>;
+ def D25_64 : AFPR64<25, "F25", [F25]>;
+ def D26_64 : AFPR64<26, "F26", [F26]>;
+ def D27_64 : AFPR64<27, "F27", [F27]>;
+ def D28_64 : AFPR64<28, "F28", [F28]>;
+ def D29_64 : AFPR64<29, "F29", [F29]>;
+ def D30_64 : AFPR64<30, "F30", [F30]>;
+ def D31_64 : AFPR64<31, "F31", [F31]>;
+
// Hi/Lo registers
def HI : Register<"hi">, DwarfRegNum<[64]>;
def LO : Register<"lo">, DwarfRegNum<[65]>;
+ let SubRegIndices = [sub_32] in {
+ def HI64 : RegisterWithSubRegs<"hi", [HI]>;
+ def LO64 : RegisterWithSubRegs<"lo", [LO]>;
+ }
+
// Status flags register
def FCR31 : Register<"31">;
@@ -167,6 +255,18 @@ def CPURegs : RegisterClass<"Mips", [i32], 32, (add
// Reserved
ZERO, AT, K0, K1, GP, SP, FP, RA)>;
+def CPU64Regs : RegisterClass<"Mips", [i64], 64, (add
+ // Return Values and Arguments
+ V0_64, V1_64, A0_64, A1_64, A2_64, A3_64,
+ // Not preserved across procedure calls
+ T0_64, T1_64, T2_64, T3_64, T4_64, T5_64, T6_64, T7_64, T8_64, T9_64,
+ // Callee save
+ S0_64, S1_64, S2_64, S3_64, S4_64, S5_64, S6_64, S7_64,
+ // Reserved
+ ZERO_64, AT_64, K0_64, K1_64, GP_64, SP_64, FP_64, RA_64)> {
+ let SubRegClasses = [(CPURegs sub_32)];
+}
+
// 64bit fp:
// * FGR64 - 32 64-bit registers
// * AFGR64 - 16 32-bit even registers (32-bit FP Mode)
@@ -182,17 +282,22 @@ def AFGR64 : RegisterClass<"Mips", [f64], 64, (add
// Not preserved across procedure calls
D2, D3, D4, D5, D8, D9,
// Callee save
- D10, D11, D12, D13, D14,
- // Reserved
- D15)> {
+ D10, D11, D12, D13, D14, D15)> {
let SubRegClasses = [(FGR32 sub_fpeven, sub_fpodd)];
}
+def FGR64 : RegisterClass<"Mips", [f64], 64, (sequence "D%u_64", 0, 31)> {
+ let SubRegClasses = [(FGR32 sub_32)];
+}
+
// Condition Register for floating point operations
def CCR : RegisterClass<"Mips", [i32], 32, (add FCR31)>;
// Hi/Lo Registers
def HILO : RegisterClass<"Mips", [i32], 32, (add HI, LO)>;
+def HILO64 : RegisterClass<"Mips", [i64], 64, (add HI64, LO64)> {
+ let SubRegClasses = [(HILO sub_32)];
+}
// Hardware registers
def HWRegs : RegisterClass<"Mips", [i32], 32, (add HWR29)>;
diff --git a/lib/Target/Mips/MipsRelocations.h b/lib/Target/Mips/MipsRelocations.h
new file mode 100644
index 0000000..66d1bfd
--- /dev/null
+++ b/lib/Target/Mips/MipsRelocations.h
@@ -0,0 +1,41 @@
+//===- MipsRelocations.h - Mips Code Relocations ---------------*- 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 Mips target-specific relocation types
+// (for relocation-model=static).
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef MIPSRELOCATIONS_H_
+#define MIPSRELOCATIONS_H_
+
+#include "llvm/CodeGen/MachineRelocation.h"
+
+namespace llvm {
+ namespace Mips{
+ enum RelocationType {
+ // reloc_mips_branch - pc relative relocation for branches. The lower 18
+ // bits of the difference between the branch target and the branch
+ // instruction, shifted right by 2.
+ reloc_mips_branch = 1,
+
+ // reloc_mips_hi - upper 16 bits of the address (modified by +1 if the
+ // lower 16 bits of the address is negative).
+ reloc_mips_hi = 2,
+
+ // reloc_mips_lo - lower 16 bits of the address.
+ reloc_mips_lo = 3,
+
+ // reloc_mips_26 - lower 28 bits of the address, shifted right by 2.
+ reloc_mips_26 = 4
+ };
+ }
+}
+
+#endif /* MIPSRELOCATIONS_H_ */
diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp
index 6eee333..016d449 100644
--- a/lib/Target/Mips/MipsSubtarget.cpp
+++ b/lib/Target/Mips/MipsSubtarget.cpp
@@ -13,7 +13,7 @@
#include "MipsSubtarget.h"
#include "Mips.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
@@ -24,15 +24,14 @@ using namespace llvm;
MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU,
const std::string &FS, bool little) :
MipsGenSubtargetInfo(TT, CPU, FS),
- MipsArchVersion(Mips1), MipsABI(O32), IsLittle(little), IsSingleFloat(false),
- IsFP64bit(false), IsGP64bit(false), HasVFPU(false), IsLinux(true),
- HasSEInReg(false), HasCondMov(false), HasMulDivAdd(false), HasMinMax(false),
- HasSwap(false), HasBitCount(false)
+ MipsArchVersion(Mips32), MipsABI(UnknownABI), IsLittle(little),
+ IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false),
+ IsLinux(true), HasSEInReg(false), HasCondMov(false), HasMulDivAdd(false),
+ HasMinMax(false), HasSwap(false), HasBitCount(false)
{
std::string CPUName = CPU;
if (CPUName.empty())
- CPUName = "mips1";
- MipsArchVersion = Mips1;
+ CPUName = "mips32r1";
// Parse features string.
ParseSubtargetFeatures(CPUName, FS);
@@ -40,23 +39,16 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU,
// Initialize scheduling itinerary for the specified CPU.
InstrItins = getInstrItineraryForCPU(CPUName);
+ // Set MipsABI if it hasn't been set yet.
+ if (MipsABI == UnknownABI)
+ MipsABI = hasMips64() ? N64 : O32;
+
+ // Check if Architecture and ABI are compatible.
+ assert(((!hasMips64() && (isABI_O32() || isABI_EABI())) ||
+ (hasMips64() && (isABI_N32() || isABI_N64()))) &&
+ "Invalid Arch & ABI pair.");
+
// Is the target system Linux ?
if (TT.find("linux") == std::string::npos)
IsLinux = false;
-
- // When only the target triple is specified and is
- // a allegrex target, set the features. We also match
- // big and little endian allegrex cores (dont really
- // know if a big one exists)
- if (TT.find("mipsallegrex") != std::string::npos ||
- TT.find("psp") != std::string::npos) {
- MipsABI = EABI;
- IsSingleFloat = true;
- MipsArchVersion = Mips2;
- HasVFPU = true; // Enables Allegrex Vector FPU (not supported yet)
- HasSEInReg = true;
- HasBitCount = true;
- HasSwap = true;
- HasCondMov = true;
- }
}
diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h
index 533d4af..d9dddad 100644
--- a/lib/Target/Mips/MipsSubtarget.h
+++ b/lib/Target/Mips/MipsSubtarget.h
@@ -27,14 +27,15 @@ class StringRef;
class MipsSubtarget : public MipsGenSubtargetInfo {
public:
+ // NOTE: O64 will not be supported.
enum MipsABIEnum {
- O32, O64, N32, N64, EABI
+ UnknownABI, O32, N32, N64, EABI
};
protected:
enum MipsArchEnum {
- Mips1, Mips2, Mips3, Mips4, Mips32, Mips32r2
+ Mips32, Mips32r2, Mips64, Mips64r2
};
// Mips architecture version
@@ -90,6 +91,8 @@ public:
/// Only O32 and EABI supported right now.
bool isABI_EABI() const { return MipsABI == EABI; }
+ bool isABI_N64() const { return MipsABI == N64; }
+ bool isABI_N32() const { return MipsABI == N32; }
bool isABI_O32() const { return MipsABI == O32; }
unsigned getTargetABI() const { return MipsABI; }
@@ -102,9 +105,11 @@ public:
/// subtarget options. Definition of function is auto generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
- bool isMips1() const { return MipsArchVersion == Mips1; }
- bool isMips32() const { return MipsArchVersion >= Mips32; }
- bool isMips32r2() const { return MipsArchVersion == Mips32r2; }
+ bool hasMips32() const { return MipsArchVersion >= Mips32; }
+ bool hasMips32r2() const { return MipsArchVersion == Mips32r2 ||
+ MipsArchVersion == Mips64r2; }
+ bool hasMips64() const { return MipsArchVersion >= Mips64; }
+ bool hasMips64r2() const { return MipsArchVersion == Mips64r2; }
bool isLittle() const { return IsLittle; }
bool isFP64bit() const { return IsFP64bit; }
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index 20b9f4e..6480da3 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -14,13 +14,15 @@
#include "Mips.h"
#include "MipsTargetMachine.h"
#include "llvm/PassManager.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
extern "C" void LLVMInitializeMipsTarget() {
// Register the target.
- RegisterTargetMachine<MipsTargetMachine> X(TheMipsTarget);
+ RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget);
RegisterTargetMachine<MipselTargetMachine> Y(TheMipselTarget);
+ RegisterTargetMachine<Mips64ebTargetMachine> A(TheMips64Target);
+ RegisterTargetMachine<Mips64elTargetMachine> B(TheMips64elTarget);
}
// DataLayout --> Big-endian, 32-bit pointer/ABI/alignment
@@ -31,30 +33,47 @@ extern "C" void LLVMInitializeMipsTarget() {
// an easier handling.
// Using CodeModel::Large enables different CALL behavior.
MipsTargetMachine::
-MipsTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS,
- bool isLittle=false):
- LLVMTargetMachine(T, TT, CPU, FS),
+MipsTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM,
+ bool isLittle):
+ LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
Subtarget(TT, CPU, FS, isLittle),
- DataLayout(isLittle ?
- std::string("e-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32") :
- std::string("E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32")),
+ DataLayout(isLittle ?
+ (Subtarget.isABI_N64() ?
+ "e-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-n32" :
+ "e-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32") :
+ (Subtarget.isABI_N64() ?
+ "E-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-n32" :
+ "E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32")),
InstrInfo(*this),
FrameLowering(Subtarget),
- TLInfo(*this), TSInfo(*this) {
- // Abicall enables PIC by default
- if (getRelocationModel() == Reloc::Default) {
- if (Subtarget.isABI_O32())
- setRelocationModel(Reloc::PIC_);
- else
- setRelocationModel(Reloc::Static);
- }
+ TLInfo(*this), TSInfo(*this), JITInfo() {
}
+MipsebTargetMachine::
+MipsebTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM) :
+ MipsTargetMachine(T, TT, CPU, FS, RM, CM, false) {}
+
MipselTargetMachine::
-MipselTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS) :
- MipsTargetMachine(T, TT, CPU, FS, true) {}
+MipselTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM) :
+ MipsTargetMachine(T, TT, CPU, FS, RM, CM, true) {}
+
+Mips64ebTargetMachine::
+Mips64ebTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM) :
+ MipsTargetMachine(T, TT, CPU, FS, RM, CM, false) {}
+
+Mips64elTargetMachine::
+Mips64elTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM) :
+ MipsTargetMachine(T, TT, CPU, FS, RM, CM, true) {}
// Install an instruction selector pass using
// the ISelDag to gen Mips code.
@@ -77,7 +96,10 @@ addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
bool MipsTargetMachine::
addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) {
- PM.add(createMipsEmitGPRestorePass(*this));
+ // Do not restore $gp if target is Mips64.
+ // In N32/64, $gp is a callee-saved register.
+ if (!Subtarget.hasMips64())
+ PM.add(createMipsEmitGPRestorePass(*this));
return true;
}
@@ -86,3 +108,12 @@ addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) {
PM.add(createMipsExpandPseudoPass(*this));
return true;
}
+
+bool MipsTargetMachine::addCodeEmitter(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel,
+ JITCodeEmitter &JCE) {
+ // Machine code emitter pass for Mips.
+ PM.add(createMipsJITCodeEmitterPass(*this, JCE));
+ return false;
+}
+
diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h
index a021af2..118ed10 100644
--- a/lib/Target/Mips/MipsTargetMachine.h
+++ b/lib/Target/Mips/MipsTargetMachine.h
@@ -22,6 +22,7 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameLowering.h"
+#include "MipsJITInfo.h"
namespace llvm {
class formatted_raw_ostream;
@@ -33,9 +34,12 @@ namespace llvm {
MipsFrameLowering FrameLowering;
MipsTargetLowering TLInfo;
MipsSelectionDAGInfo TSInfo;
+ MipsJITInfo JITInfo;
+
public:
- MipsTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS,
+ MipsTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM,
bool isLittle);
virtual const MipsInstrInfo *getInstrInfo() const
@@ -46,6 +50,9 @@ namespace llvm {
{ return &Subtarget; }
virtual const TargetData *getTargetData() const
{ return &DataLayout;}
+ virtual MipsJITInfo *getJITInfo()
+ { return &JITInfo; }
+
virtual const MipsRegisterInfo *getRegisterInfo() const {
return &InstrInfo.getRegisterInfo();
@@ -67,16 +74,47 @@ namespace llvm {
virtual bool addPreRegAlloc(PassManagerBase &PM,
CodeGenOpt::Level OptLevel);
virtual bool addPostRegAlloc(PassManagerBase &, CodeGenOpt::Level);
+ virtual bool addCodeEmitter(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel,
+ JITCodeEmitter &JCE);
+
};
-/// MipselTargetMachine - Mipsel target machine.
+/// MipsebTargetMachine - Mips32 big endian target machine.
+///
+class MipsebTargetMachine : public MipsTargetMachine {
+public:
+ MipsebTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
+};
+
+/// MipselTargetMachine - Mips32 little endian target machine.
///
class MipselTargetMachine : public MipsTargetMachine {
public:
- MipselTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ MipselTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
};
+/// Mips64ebTargetMachine - Mips64 big endian target machine.
+///
+class Mips64ebTargetMachine : public MipsTargetMachine {
+public:
+ Mips64ebTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
+};
+
+/// Mips64elTargetMachine - Mips64 little endian target machine.
+///
+class Mips64elTargetMachine : public MipsTargetMachine {
+public:
+ Mips64elTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
+};
} // End llvm namespace
#endif
diff --git a/lib/Target/Mips/MipsTargetObjectFile.cpp b/lib/Target/Mips/MipsTargetObjectFile.cpp
index cf5d1b5..05c46f5 100644
--- a/lib/Target/Mips/MipsTargetObjectFile.cpp
+++ b/lib/Target/Mips/MipsTargetObjectFile.cpp
@@ -79,7 +79,7 @@ IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM,
if (Kind.isMergeable1ByteCString())
return false;
- const Type *Ty = GV->getType()->getElementType();
+ Type *Ty = GV->getType()->getElementType();
return IsInSmallSection(TM.getTargetData()->getTypeAllocSize(Ty));
}
diff --git a/lib/Target/Mips/TargetInfo/CMakeLists.txt b/lib/Target/Mips/TargetInfo/CMakeLists.txt
index 6e5d56b..5692604 100644
--- a/lib/Target/Mips/TargetInfo/CMakeLists.txt
+++ b/lib/Target/Mips/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMMipsInfo
MipsTargetInfo.cpp
)
-add_dependencies(LLVMMipsInfo MipsCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMMipsInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMMipsInfo MipsCommonTableGen)
diff --git a/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
index a8d6fe9..243632b 100644
--- a/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
+++ b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
@@ -9,13 +9,23 @@
#include "Mips.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::TheMipsTarget, llvm::TheMipselTarget;
+Target llvm::TheMips64Target, llvm::TheMips64elTarget;
extern "C" void LLVMInitializeMipsTargetInfo() {
- RegisterTarget<Triple::mips> X(TheMipsTarget, "mips", "Mips");
+ RegisterTarget<Triple::mips,
+ /*HasJIT=*/true> X(TheMipsTarget, "mips", "Mips");
- RegisterTarget<Triple::mipsel> Y(TheMipselTarget, "mipsel", "Mipsel");
+ RegisterTarget<Triple::mipsel,
+ /*HasJIT=*/true> Y(TheMipselTarget, "mipsel", "Mipsel");
+
+ RegisterTarget<Triple::mips64,
+ /*HasJIT=*/false> A(TheMips64Target, "mips64", "Mips64 [experimental]");
+
+ RegisterTarget<Triple::mips64el,
+ /*HasJIT=*/false> B(TheMips64elTarget,
+ "mips64el", "Mips64el [experimental]");
}
diff --git a/lib/Target/PTX/CMakeLists.txt b/lib/Target/PTX/CMakeLists.txt
index ce08916..6e87b17 100644
--- a/lib/Target/PTX/CMakeLists.txt
+++ b/lib/Target/PTX/CMakeLists.txt
@@ -1,24 +1,44 @@
set(LLVM_TARGET_DEFINITIONS PTX.td)
-tablegen(PTXGenAsmWriter.inc -gen-asm-writer)
-tablegen(PTXGenCallingConv.inc -gen-callingconv)
-tablegen(PTXGenDAGISel.inc -gen-dag-isel)
-tablegen(PTXGenInstrInfo.inc -gen-instr-info)
-tablegen(PTXGenRegisterInfo.inc -gen-register-info)
-tablegen(PTXGenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(PTXGenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(PTXGenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(PTXGenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(PTXGenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(PTXGenSubtargetInfo.inc -gen-subtarget)
+add_public_tablegen_target(PTXCommonTableGen)
add_llvm_target(PTXCodeGen
PTXAsmPrinter.cpp
PTXISelDAGToDAG.cpp
PTXISelLowering.cpp
PTXInstrInfo.cpp
+ PTXFPRoundingModePass.cpp
PTXFrameLowering.cpp
PTXMCAsmStreamer.cpp
+ PTXMCInstLower.cpp
PTXMFInfoExtract.cpp
+ PTXParamManager.cpp
+ PTXRegAlloc.cpp
PTXRegisterInfo.cpp
+ PTXSelectionDAGInfo.cpp
PTXSubtarget.cpp
PTXTargetMachine.cpp
)
+add_llvm_library_dependencies(LLVMPTXCodeGen
+ LLVMAnalysis
+ LLVMAsmPrinter
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMPTXDesc
+ LLVMPTXInfo
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMTarget
+ )
+
add_subdirectory(TargetInfo)
+add_subdirectory(InstPrinter)
add_subdirectory(MCTargetDesc)
+
diff --git a/lib/Target/PTX/InstPrinter/CMakeLists.txt b/lib/Target/PTX/InstPrinter/CMakeLists.txt
new file mode 100644
index 0000000..029d060
--- /dev/null
+++ b/lib/Target/PTX/InstPrinter/CMakeLists.txt
@@ -0,0 +1,13 @@
+include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )
+
+add_llvm_library(LLVMPTXAsmPrinter
+ PTXInstPrinter.cpp
+ )
+
+add_dependencies(LLVMPTXAsmPrinter PTXCommonTableGen)
+
+add_llvm_library_dependencies(LLVMPTXAsmPrinter
+ LLVMMC
+ LLVMSupport
+ )
+
diff --git a/lib/Target/PTX/InstPrinter/Makefile b/lib/Target/PTX/InstPrinter/Makefile
new file mode 100644
index 0000000..0ccfe44
--- /dev/null
+++ b/lib/Target/PTX/InstPrinter/Makefile
@@ -0,0 +1,16 @@
+##===- lib/Target/PTX/AsmPrinter/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 = LLVMPTXAsmPrinter
+
+# Hack: we need to include 'main' ptx target directory to grab private headers
+CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
+
+include $(LEVEL)/Makefile.common
+
diff --git a/lib/Target/PTX/InstPrinter/PTXInstPrinter.cpp b/lib/Target/PTX/InstPrinter/PTXInstPrinter.cpp
new file mode 100644
index 0000000..aabb404
--- /dev/null
+++ b/lib/Target/PTX/InstPrinter/PTXInstPrinter.cpp
@@ -0,0 +1,192 @@
+//===-- PTXInstPrinter.cpp - Convert PTX MCInst to assembly syntax --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class prints a PTX MCInst to a .ptx file.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "asm-printer"
+#include "PTXInstPrinter.h"
+#include "MCTargetDesc/PTXBaseInfo.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+#define GET_INSTRUCTION_NAME
+#include "PTXGenAsmWriter.inc"
+
+PTXInstPrinter::PTXInstPrinter(const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI) :
+ MCInstPrinter(MAI) {
+ // Initialize the set of available features.
+ setAvailableFeatures(STI.getFeatureBits());
+}
+
+StringRef PTXInstPrinter::getOpcodeName(unsigned Opcode) const {
+ return getInstructionName(Opcode);
+}
+
+void PTXInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
+ OS << getRegisterName(RegNo);
+}
+
+void PTXInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
+ StringRef Annot) {
+ printPredicate(MI, O);
+ switch (MI->getOpcode()) {
+ default:
+ printInstruction(MI, O);
+ break;
+ case PTX::CALL:
+ printCall(MI, O);
+ }
+ O << ";";
+ printAnnotation(O, Annot);
+}
+
+void PTXInstPrinter::printPredicate(const MCInst *MI, raw_ostream &O) {
+ // The last two operands are the predicate operands
+ int RegIndex;
+ int OpIndex;
+
+ if (MI->getOpcode() == PTX::CALL) {
+ RegIndex = 0;
+ OpIndex = 1;
+ } else {
+ RegIndex = MI->getNumOperands()-2;
+ OpIndex = MI->getNumOperands()-1;
+ }
+
+ int PredOp = MI->getOperand(OpIndex).getImm();
+ if (PredOp == PTXPredicate::None)
+ return;
+
+ if (PredOp == PTXPredicate::Negate)
+ O << '!';
+ else
+ O << '@';
+
+ printOperand(MI, RegIndex, O);
+}
+
+void PTXInstPrinter::printCall(const MCInst *MI, raw_ostream &O) {
+ O << "\tcall.uni\t";
+ // The first two operands are the predicate slot
+ unsigned Index = 2;
+ unsigned NumRets = MI->getOperand(Index++).getImm();
+
+ if (NumRets > 0) {
+ O << "(";
+ printOperand(MI, Index++, O);
+ for (unsigned i = 1; i < NumRets; ++i) {
+ O << ", ";
+ printOperand(MI, Index++, O);
+ }
+ O << "), ";
+ }
+
+ O << *(MI->getOperand(Index++).getExpr()) << ", (";
+
+ unsigned NumArgs = MI->getOperand(Index++).getImm();
+ if (NumArgs > 0) {
+ printOperand(MI, Index++, O);
+ for (unsigned i = 1; i < NumArgs; ++i) {
+ O << ", ";
+ printOperand(MI, Index++, O);
+ }
+ }
+ O << ")";
+}
+
+void PTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ if (Op.isImm()) {
+ O << Op.getImm();
+ } else if (Op.isFPImm()) {
+ double Imm = Op.getFPImm();
+ APFloat FPImm(Imm);
+ APInt FPIntImm = FPImm.bitcastToAPInt();
+ O << "0D";
+ // PTX requires us to output the full 64 bits, even if the number is zero
+ if (FPIntImm.getZExtValue() > 0) {
+ O << FPIntImm.toString(16, false);
+ } else {
+ O << "0000000000000000";
+ }
+ } else {
+ assert(Op.isExpr() && "unknown operand kind in printOperand");
+ const MCExpr *Expr = Op.getExpr();
+ if (const MCSymbolRefExpr *SymRefExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
+ const MCSymbol &Sym = SymRefExpr->getSymbol();
+ O << Sym.getName();
+ } else {
+ O << *Op.getExpr();
+ }
+ }
+}
+
+void PTXInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ // By definition, operand OpNo+1 is an i32imm
+ const MCOperand &Op2 = MI->getOperand(OpNo+1);
+ printOperand(MI, OpNo, O);
+ if (Op2.getImm() == 0)
+ return; // don't print "+0"
+ O << "+" << Op2.getImm();
+}
+
+void PTXInstPrinter::printRoundingMode(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ assert (Op.isImm() && "Rounding modes must be immediate values");
+ switch (Op.getImm()) {
+ default:
+ llvm_unreachable("Unknown rounding mode!");
+ case PTXRoundingMode::RndDefault:
+ llvm_unreachable("FP rounding-mode pass did not handle instruction!");
+ break;
+ case PTXRoundingMode::RndNone:
+ // Do not print anything.
+ break;
+ case PTXRoundingMode::RndNearestEven:
+ O << ".rn";
+ break;
+ case PTXRoundingMode::RndTowardsZero:
+ O << ".rz";
+ break;
+ case PTXRoundingMode::RndNegInf:
+ O << ".rm";
+ break;
+ case PTXRoundingMode::RndPosInf:
+ O << ".rp";
+ break;
+ case PTXRoundingMode::RndApprox:
+ O << ".approx";
+ break;
+ case PTXRoundingMode::RndNearestEvenInt:
+ O << ".rni";
+ break;
+ case PTXRoundingMode::RndTowardsZeroInt:
+ O << ".rzi";
+ break;
+ case PTXRoundingMode::RndNegInfInt:
+ O << ".rmi";
+ break;
+ case PTXRoundingMode::RndPosInfInt:
+ O << ".rpi";
+ break;
+ }
+}
+
diff --git a/lib/Target/PTX/InstPrinter/PTXInstPrinter.h b/lib/Target/PTX/InstPrinter/PTXInstPrinter.h
new file mode 100644
index 0000000..86dfd48
--- /dev/null
+++ b/lib/Target/PTX/InstPrinter/PTXInstPrinter.h
@@ -0,0 +1,47 @@
+//===-- PTXInstPrinter.h - Convert PTX MCInst to assembly syntax ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class prints n PTX MCInst to a .ptx file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PTXINSTPRINTER_H
+#define PTXINSTPRINTER_H
+
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+
+namespace llvm {
+
+class MCOperand;
+
+class PTXInstPrinter : public MCInstPrinter {
+public:
+ PTXInstPrinter(const MCAsmInfo &MAI, const MCSubtargetInfo &STI);
+
+ virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
+ virtual StringRef getOpcodeName(unsigned Opcode) const;
+ virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
+
+ static const char *getInstructionName(unsigned Opcode);
+
+ // Autogenerated by tblgen.
+ void printInstruction(const MCInst *MI, raw_ostream &O);
+ static const char *getRegisterName(unsigned RegNo);
+
+ void printPredicate(const MCInst *MI, raw_ostream &O);
+ void printCall(const MCInst *MI, raw_ostream &O);
+ void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printMemOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printRoundingMode(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+};
+}
+
+#endif
+
diff --git a/lib/Target/PTX/MCTargetDesc/CMakeLists.txt b/lib/Target/PTX/MCTargetDesc/CMakeLists.txt
index df0f63f..811ef4b 100644
--- a/lib/Target/PTX/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/PTX/MCTargetDesc/CMakeLists.txt
@@ -2,3 +2,12 @@ add_llvm_library(LLVMPTXDesc
PTXMCTargetDesc.cpp
PTXMCAsmInfo.cpp
)
+
+add_llvm_library_dependencies(LLVMPTXDesc
+ LLVMMC
+ LLVMPTXInfo
+ LLVMPTXAsmPrinter
+ LLVMSupport
+ )
+
+add_dependencies(LLVMPTXDesc PTXCommonTableGen)
diff --git a/lib/Target/PTX/MCTargetDesc/PTXBaseInfo.h b/lib/Target/PTX/MCTargetDesc/PTXBaseInfo.h
new file mode 100644
index 0000000..c6094be
--- /dev/null
+++ b/lib/Target/PTX/MCTargetDesc/PTXBaseInfo.h
@@ -0,0 +1,63 @@
+//===-- PTXBaseInfo.h - Top level definitions for PTX -------- --*- 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 small standalone helper functions and enum definitions for
+// the PTX target useful for the compiler back-end and the MC libraries.
+// As such, it deliberately does not include references to LLVM core
+// code gen types, passes, etc..
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PTXBASEINFO_H
+#define PTXBASEINFO_H
+
+#include "PTXMCTargetDesc.h"
+
+namespace llvm {
+ namespace PTXStateSpace {
+ enum {
+ Global = 0, // default to global state space
+ Constant = 1,
+ Local = 2,
+ Parameter = 3,
+ Shared = 4
+ };
+ } // namespace PTXStateSpace
+
+ namespace PTXPredicate {
+ enum {
+ Normal = 0,
+ Negate = 1,
+ None = 2
+ };
+ } // namespace PTXPredicate
+
+ /// Namespace to hold all target-specific flags.
+ namespace PTXRoundingMode {
+ // Instruction Flags
+ enum {
+ // Rounding Mode Flags
+ RndMask = 15,
+ RndDefault = 0, // ---
+ RndNone = 1, // <NONE>
+ RndNearestEven = 2, // .rn
+ RndTowardsZero = 3, // .rz
+ RndNegInf = 4, // .rm
+ RndPosInf = 5, // .rp
+ RndApprox = 6, // .approx
+ RndNearestEvenInt = 7, // .rni
+ RndTowardsZeroInt = 8, // .rzi
+ RndNegInfInt = 9, // .rmi
+ RndPosInfInt = 10 // .rpi
+ };
+ } // namespace PTXII
+} // namespace llvm
+
+#endif
+
diff --git a/lib/Target/PTX/MCTargetDesc/PTXMCTargetDesc.cpp b/lib/Target/PTX/MCTargetDesc/PTXMCTargetDesc.cpp
index 23f70bd..a5af3b8 100644
--- a/lib/Target/PTX/MCTargetDesc/PTXMCTargetDesc.cpp
+++ b/lib/Target/PTX/MCTargetDesc/PTXMCTargetDesc.cpp
@@ -13,10 +13,12 @@
#include "PTXMCTargetDesc.h"
#include "PTXMCAsmInfo.h"
+#include "InstPrinter/PTXInstPrinter.h"
+#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_MC_DESC
#include "PTXGenInstrInfo.inc"
@@ -35,9 +37,11 @@ static MCInstrInfo *createPTXMCInstrInfo() {
return X;
}
-extern "C" void LLVMInitializePTXMCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(ThePTX32Target, createPTXMCInstrInfo);
- TargetRegistry::RegisterMCInstrInfo(ThePTX64Target, createPTXMCInstrInfo);
+static MCRegisterInfo *createPTXMCRegisterInfo(StringRef TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ // PTX does not have a return address register.
+ InitPTXMCRegisterInfo(X, 0);
+ return X;
}
static MCSubtargetInfo *createPTXMCSubtargetInfo(StringRef TT, StringRef CPU,
@@ -47,14 +51,45 @@ static MCSubtargetInfo *createPTXMCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-extern "C" void LLVMInitializePTXMCSubtargetInfo() {
+static MCCodeGenInfo *createPTXMCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+ X->InitMCCodeGenInfo(RM, CM);
+ return X;
+}
+
+static MCInstPrinter *createPTXMCInstPrinter(const Target &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI) {
+ assert(SyntaxVariant == 0 && "We only have one syntax variant");
+ return new PTXInstPrinter(MAI, STI);
+}
+
+extern "C" void LLVMInitializePTXTargetMC() {
+ // Register the MC asm info.
+ RegisterMCAsmInfo<PTXMCAsmInfo> X(ThePTX32Target);
+ RegisterMCAsmInfo<PTXMCAsmInfo> Y(ThePTX64Target);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(ThePTX32Target, createPTXMCCodeGenInfo);
+ TargetRegistry::RegisterMCCodeGenInfo(ThePTX64Target, createPTXMCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(ThePTX32Target, createPTXMCInstrInfo);
+ TargetRegistry::RegisterMCInstrInfo(ThePTX64Target, createPTXMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(ThePTX32Target, createPTXMCRegisterInfo);
+ TargetRegistry::RegisterMCRegInfo(ThePTX64Target, createPTXMCRegisterInfo);
+
+ // Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(ThePTX32Target,
createPTXMCSubtargetInfo);
TargetRegistry::RegisterMCSubtargetInfo(ThePTX64Target,
createPTXMCSubtargetInfo);
-}
-extern "C" void LLVMInitializePTXMCAsmInfo() {
- RegisterMCAsmInfo<PTXMCAsmInfo> X(ThePTX32Target);
- RegisterMCAsmInfo<PTXMCAsmInfo> Y(ThePTX64Target);
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(ThePTX32Target, createPTXMCInstPrinter);
+ TargetRegistry::RegisterMCInstPrinter(ThePTX64Target, createPTXMCInstPrinter);
}
diff --git a/lib/Target/PTX/Makefile b/lib/Target/PTX/Makefile
index 93dd38a..fa09634 100644
--- a/lib/Target/PTX/Makefile
+++ b/lib/Target/PTX/Makefile
@@ -13,12 +13,11 @@ TARGET = PTX
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = PTXGenAsmWriter.inc \
- PTXGenCallingConv.inc \
PTXGenDAGISel.inc \
PTXGenInstrInfo.inc \
PTXGenRegisterInfo.inc \
PTXGenSubtargetInfo.inc
-DIRS = TargetInfo MCTargetDesc
+DIRS = InstPrinter TargetInfo MCTargetDesc
include $(LEVEL)/Makefile.common
diff --git a/lib/Target/PTX/PTX.h b/lib/Target/PTX/PTX.h
index 28cab24..7d46cce 100644
--- a/lib/Target/PTX/PTX.h
+++ b/lib/Target/PTX/PTX.h
@@ -15,34 +15,30 @@
#ifndef PTX_H
#define PTX_H
-#include "MCTargetDesc/PTXMCTargetDesc.h"
+#include "MCTargetDesc/PTXBaseInfo.h"
#include "llvm/Target/TargetMachine.h"
namespace llvm {
+ class MachineInstr;
+ class MCInst;
+ class PTXAsmPrinter;
class PTXTargetMachine;
class FunctionPass;
- namespace PTX {
- enum StateSpace {
- GLOBAL = 0, // default to global state space
- CONSTANT = 1,
- LOCAL = 2,
- PARAMETER = 3,
- SHARED = 4
- };
-
- enum Predicate {
- PRED_NORMAL = 0,
- PRED_NEGATE = 1
- };
- } // namespace PTX
-
FunctionPass *createPTXISelDag(PTXTargetMachine &TM,
CodeGenOpt::Level OptLevel);
FunctionPass *createPTXMFInfoExtract(PTXTargetMachine &TM,
CodeGenOpt::Level OptLevel);
+ FunctionPass *createPTXFPRoundingModePass(PTXTargetMachine &TM,
+ CodeGenOpt::Level OptLevel);
+
+ FunctionPass *createPTXRegisterAllocator();
+
+ void LowerPTXMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
+ PTXAsmPrinter &AP);
+
} // namespace llvm;
#endif // PTX_H
diff --git a/lib/Target/PTX/PTX.td b/lib/Target/PTX/PTX.td
index f6fbe9f..693bb9c 100644
--- a/lib/Target/PTX/PTX.td
+++ b/lib/Target/PTX/PTX.td
@@ -52,13 +52,13 @@ def FeatureSM12 : SubtargetFeature<"sm12", "PTXTarget", "PTX_SM_1_2",
def FeatureSM13 : SubtargetFeature<"sm13", "PTXTarget", "PTX_SM_1_3",
"Use Shader Model 1.3">;
def FeatureSM20 : SubtargetFeature<"sm20", "PTXTarget", "PTX_SM_2_0",
- "Use Shader Model 2.0">;
+ "Use Shader Model 2.0", [FeatureDouble]>;
def FeatureSM21 : SubtargetFeature<"sm21", "PTXTarget", "PTX_SM_2_1",
- "Use Shader Model 2.1">;
+ "Use Shader Model 2.1", [FeatureDouble]>;
def FeatureSM22 : SubtargetFeature<"sm22", "PTXTarget", "PTX_SM_2_2",
- "Use Shader Model 2.2">;
+ "Use Shader Model 2.2", [FeatureDouble]>;
def FeatureSM23 : SubtargetFeature<"sm23", "PTXTarget", "PTX_SM_2_3",
- "Use Shader Model 2.3">;
+ "Use Shader Model 2.3", [FeatureDouble]>;
def FeatureCOMPUTE10 : SubtargetFeature<"compute10", "PTXTarget",
"PTX_COMPUTE_1_0",
@@ -74,7 +74,8 @@ def FeatureCOMPUTE13 : SubtargetFeature<"compute13", "PTXTarget",
"Use Compute Compatibility 1.3">;
def FeatureCOMPUTE20 : SubtargetFeature<"compute20", "PTXTarget",
"PTX_COMPUTE_2_0",
- "Use Compute Compatibility 2.0">;
+ "Use Compute Compatibility 2.0",
+ [FeatureDouble]>;
//===----------------------------------------------------------------------===//
// PTX supported processors
@@ -113,12 +114,6 @@ def : Proc<"fermi", [FeatureSM20, FeatureDouble]>;
include "PTXRegisterInfo.td"
//===----------------------------------------------------------------------===//
-// Calling Conventions
-//===----------------------------------------------------------------------===//
-
-include "PTXCallingConv.td"
-
-//===----------------------------------------------------------------------===//
// Instruction Descriptions
//===----------------------------------------------------------------------===//
@@ -127,9 +122,20 @@ include "PTXInstrInfo.td"
def PTXInstrInfo : InstrInfo;
//===----------------------------------------------------------------------===//
+// Assembly printer
+//===----------------------------------------------------------------------===//
+// PTX uses the MC printer for asm output, so make sure the TableGen
+// AsmWriter bits get associated with the correct class.
+def PTXAsmWriter : AsmWriter {
+ string AsmWriterClassName = "InstPrinter";
+ bit isMCAsmWriter = 1;
+}
+
+//===----------------------------------------------------------------------===//
// Target Declaration
//===----------------------------------------------------------------------===//
def PTX : Target {
let InstructionSet = PTXInstrInfo;
+ let AssemblyWriters = [PTXAsmWriter];
}
diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp
index 2848d54..733744b 100644
--- a/lib/Target/PTX/PTXAsmPrinter.cpp
+++ b/lib/Target/PTX/PTXAsmPrinter.cpp
@@ -15,9 +15,14 @@
#define DEBUG_TYPE "ptx-asm-printer"
#include "PTX.h"
+#include "PTXAsmPrinter.h"
#include "PTXMachineFunctionInfo.h"
+#include "PTXParamManager.h"
+#include "PTXRegisterInfo.h"
#include "PTXTargetMachine.h"
+#include "llvm/Argument.h"
#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
@@ -28,69 +33,32 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-namespace {
-class PTXAsmPrinter : public AsmPrinter {
-public:
- explicit PTXAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
- : AsmPrinter(TM, Streamer) {}
-
- const char *getPassName() const { return "PTX Assembly Printer"; }
-
- bool doFinalization(Module &M);
-
- virtual void EmitStartOfAsmFile(Module &M);
-
- virtual bool runOnMachineFunction(MachineFunction &MF);
-
- virtual void EmitFunctionBodyStart();
- virtual void EmitFunctionBodyEnd() { OutStreamer.EmitRawText(Twine("}")); }
-
- virtual void EmitInstruction(const MachineInstr *MI);
-
- void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
- void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS,
- const char *Modifier = 0);
- void printParamOperand(const MachineInstr *MI, int opNum, raw_ostream &OS,
- const char *Modifier = 0);
- void printReturnOperand(const MachineInstr *MI, int opNum, raw_ostream &OS,
- const char *Modifier = 0);
- void printPredicateOperand(const MachineInstr *MI, raw_ostream &O);
-
- unsigned GetOrCreateSourceID(StringRef FileName,
- StringRef DirName);
-
- // autogen'd.
- void printInstruction(const MachineInstr *MI, raw_ostream &OS);
- static const char *getRegisterName(unsigned RegNo);
-
-private:
- void EmitVariableDeclaration(const GlobalVariable *gv);
- void EmitFunctionDeclaration();
-
- StringMap<unsigned> SourceIdMap;
-}; // class PTXAsmPrinter
-} // namespace
-
static const char PARAM_PREFIX[] = "__param_";
static const char RETURN_PREFIX[] = "__ret_";
-static const char *getRegisterTypeName(unsigned RegNo) {
-#define TEST_REGCLS(cls, clsstr) \
- if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr;
+static const char *getRegisterTypeName(unsigned RegNo,
+ const MachineRegisterInfo& MRI) {
+ const TargetRegisterClass *TRC = MRI.getRegClass(RegNo);
+
+#define TEST_REGCLS(cls, clsstr) \
+ if (PTX::cls ## RegisterClass == TRC) return # clsstr;
+
TEST_REGCLS(RegPred, pred);
TEST_REGCLS(RegI16, b16);
TEST_REGCLS(RegI32, b32);
@@ -106,16 +74,16 @@ static const char *getRegisterTypeName(unsigned RegNo) {
static const char *getStateSpaceName(unsigned addressSpace) {
switch (addressSpace) {
default: llvm_unreachable("Unknown state space");
- case PTX::GLOBAL: return "global";
- case PTX::CONSTANT: return "const";
- case PTX::LOCAL: return "local";
- case PTX::PARAMETER: return "param";
- case PTX::SHARED: return "shared";
+ case PTXStateSpace::Global: return "global";
+ case PTXStateSpace::Constant: return "const";
+ case PTXStateSpace::Local: return "local";
+ case PTXStateSpace::Parameter: return "param";
+ case PTXStateSpace::Shared: return "shared";
}
return NULL;
}
-static const char *getTypeName(const Type* type) {
+static const char *getTypeName(Type* type) {
while (true) {
switch (type->getTypeID()) {
default: llvm_unreachable("Unknown type");
@@ -130,7 +98,7 @@ static const char *getTypeName(const Type* type) {
}
case Type::ArrayTyID:
case Type::PointerTyID:
- type = dyn_cast<const SequentialType>(type)->getElementType();
+ type = dyn_cast<SequentialType>(type)->getElementType();
break;
}
}
@@ -170,6 +138,7 @@ void PTXAsmPrinter::EmitStartOfAsmFile(Module &M)
{
const PTXSubtarget& ST = TM.getSubtarget<PTXSubtarget>();
+ // Emit the PTX .version and .target attributes
OutStreamer.EmitRawText(Twine("\t.version " + ST.getPTXVersionString()));
OutStreamer.EmitRawText(Twine("\t.target " + ST.getTargetString() +
(ST.supportsDouble() ? ""
@@ -203,177 +172,118 @@ void PTXAsmPrinter::EmitStartOfAsmFile(Module &M)
EmitVariableDeclaration(i);
}
-bool PTXAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- SetupMachineFunction(MF);
- EmitFunctionDeclaration();
- EmitFunctionBody();
- return false;
-}
-
void PTXAsmPrinter::EmitFunctionBodyStart() {
OutStreamer.EmitRawText(Twine("{"));
const PTXMachineFunctionInfo *MFI = MF->getInfo<PTXMachineFunctionInfo>();
+ const PTXParamManager &PM = MFI->getParamManager();
+
+ // Print register definitions
+ std::string regDefs;
+ unsigned numRegs;
+
+ // pred
+ numRegs = MFI->getNumRegistersForClass(PTX::RegPredRegisterClass);
+ if(numRegs > 0) {
+ regDefs += "\t.reg .pred %p<";
+ regDefs += utostr(numRegs);
+ regDefs += ">;\n";
+ }
+
+ // i16
+ numRegs = MFI->getNumRegistersForClass(PTX::RegI16RegisterClass);
+ if(numRegs > 0) {
+ regDefs += "\t.reg .b16 %rh<";
+ regDefs += utostr(numRegs);
+ regDefs += ">;\n";
+ }
+
+ // i32
+ numRegs = MFI->getNumRegistersForClass(PTX::RegI32RegisterClass);
+ if(numRegs > 0) {
+ regDefs += "\t.reg .b32 %r<";
+ regDefs += utostr(numRegs);
+ regDefs += ">;\n";
+ }
+
+ // i64
+ numRegs = MFI->getNumRegistersForClass(PTX::RegI64RegisterClass);
+ if(numRegs > 0) {
+ regDefs += "\t.reg .b64 %rd<";
+ regDefs += utostr(numRegs);
+ regDefs += ">;\n";
+ }
+
+ // f32
+ numRegs = MFI->getNumRegistersForClass(PTX::RegF32RegisterClass);
+ if(numRegs > 0) {
+ regDefs += "\t.reg .f32 %f<";
+ regDefs += utostr(numRegs);
+ regDefs += ">;\n";
+ }
+
+ // f64
+ numRegs = MFI->getNumRegistersForClass(PTX::RegF64RegisterClass);
+ if(numRegs > 0) {
+ regDefs += "\t.reg .f64 %fd<";
+ regDefs += utostr(numRegs);
+ regDefs += ">;\n";
+ }
- // Print local variable definition
- for (PTXMachineFunctionInfo::reg_iterator
- i = MFI->localVarRegBegin(), e = MFI->localVarRegEnd(); i != e; ++ i) {
- unsigned reg = *i;
-
- std::string def = "\t.reg .";
- def += getRegisterTypeName(reg);
- def += ' ';
- def += getRegisterName(reg);
- def += ';';
- OutStreamer.EmitRawText(Twine(def));
+ // Local params
+ for (PTXParamManager::param_iterator i = PM.local_begin(), e = PM.local_end();
+ i != e; ++i) {
+ regDefs += "\t.param .b";
+ regDefs += utostr(PM.getParamSize(*i));
+ regDefs += " ";
+ regDefs += PM.getParamName(*i);
+ regDefs += ";\n";
}
+ OutStreamer.EmitRawText(Twine(regDefs));
+
+
const MachineFrameInfo* FrameInfo = MF->getFrameInfo();
DEBUG(dbgs() << "Have " << FrameInfo->getNumObjects()
<< " frame object(s)\n");
for (unsigned i = 0, e = FrameInfo->getNumObjects(); i != e; ++i) {
DEBUG(dbgs() << "Size of object: " << FrameInfo->getObjectSize(i) << "\n");
if (FrameInfo->getObjectSize(i) > 0) {
- std::string def = "\t.reg .b";
- def += utostr(FrameInfo->getObjectSize(i)*8); // Convert to bits
- def += " s";
+ std::string def = "\t.local .align ";
+ def += utostr(FrameInfo->getObjectAlignment(i));
+ def += " .b8";
+ def += " __local";
def += utostr(i);
+ def += "[";
+ def += utostr(FrameInfo->getObjectSize(i)); // Convert to bits
+ def += "]";
def += ";";
OutStreamer.EmitRawText(Twine(def));
}
}
-}
-
-void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) {
- std::string str;
- str.reserve(64);
-
- raw_string_ostream OS(str);
-
- DebugLoc DL = MI->getDebugLoc();
- if (!DL.isUnknown()) {
-
- const MDNode *S = DL.getScope(MF->getFunction()->getContext());
-
- // This is taken from DwarfDebug.cpp, which is conveniently not a public
- // LLVM class.
- StringRef Fn;
- StringRef Dir;
- unsigned Src = 1;
- if (S) {
- DIDescriptor Scope(S);
- if (Scope.isCompileUnit()) {
- DICompileUnit CU(S);
- Fn = CU.getFilename();
- Dir = CU.getDirectory();
- } else if (Scope.isFile()) {
- DIFile F(S);
- Fn = F.getFilename();
- Dir = F.getDirectory();
- } else if (Scope.isSubprogram()) {
- DISubprogram SP(S);
- Fn = SP.getFilename();
- Dir = SP.getDirectory();
- } else if (Scope.isLexicalBlock()) {
- DILexicalBlock DB(S);
- Fn = DB.getFilename();
- Dir = DB.getDirectory();
- } else
- assert(0 && "Unexpected scope info");
-
- Src = GetOrCreateSourceID(Fn, Dir);
- }
- OutStreamer.EmitDwarfLocDirective(Src, DL.getLine(), DL.getCol(),
- 0, 0, 0, Fn);
-
- const MCDwarfLoc& MDL = OutContext.getCurrentDwarfLoc();
-
- OS << "\t.loc ";
- OS << utostr(MDL.getFileNum());
- OS << " ";
- OS << utostr(MDL.getLine());
- OS << " ";
- OS << utostr(MDL.getColumn());
- OS << "\n";
- }
-
-
- // Emit predicate
- printPredicateOperand(MI, OS);
-
- // Write instruction to str
- printInstruction(MI, OS);
- OS << ';';
- OS.flush();
-
- StringRef strref = StringRef(str);
- OutStreamer.EmitRawText(strref);
-}
-
-void PTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
- raw_ostream &OS) {
- const MachineOperand &MO = MI->getOperand(opNum);
-
- switch (MO.getType()) {
- default:
- llvm_unreachable("<unknown operand type>");
- break;
- case MachineOperand::MO_GlobalAddress:
- OS << *Mang->getSymbol(MO.getGlobal());
- break;
- case MachineOperand::MO_Immediate:
- OS << (long) MO.getImm();
- break;
- case MachineOperand::MO_MachineBasicBlock:
- OS << *MO.getMBB()->getSymbol();
- break;
- case MachineOperand::MO_Register:
- OS << getRegisterName(MO.getReg());
- break;
- case MachineOperand::MO_FPImmediate:
- APInt constFP = MO.getFPImm()->getValueAPF().bitcastToAPInt();
- bool isFloat = MO.getFPImm()->getType()->getTypeID() == Type::FloatTyID;
- // Emit 0F for 32-bit floats and 0D for 64-bit doubles.
- if (isFloat) {
- OS << "0F";
- }
- else {
- OS << "0D";
- }
- // Emit the encoded floating-point value.
- if (constFP.getZExtValue() > 0) {
- OS << constFP.toString(16, false);
- }
- else {
- OS << "00000000";
- // If We have a double-precision zero, pad to 8-bytes.
- if (!isFloat) {
- OS << "00000000";
- }
- }
- break;
- }
-}
-
-void PTXAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
- raw_ostream &OS, const char *Modifier) {
- printOperand(MI, opNum, OS);
- if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0)
- return; // don't print "+0"
-
- OS << "+";
- printOperand(MI, opNum+1, OS);
+ //unsigned Index = 1;
+ // Print parameter passing params
+ //for (PTXMachineFunctionInfo::param_iterator
+ // i = MFI->paramBegin(), e = MFI->paramEnd(); i != e; ++i) {
+ // std::string def = "\t.param .b";
+ // def += utostr(*i);
+ // def += " __ret_";
+ // def += utostr(Index);
+ // Index++;
+ // def += ";";
+ // OutStreamer.EmitRawText(Twine(def));
+ //}
}
-void PTXAsmPrinter::printParamOperand(const MachineInstr *MI, int opNum,
- raw_ostream &OS, const char *Modifier) {
- OS << PARAM_PREFIX << (int) MI->getOperand(opNum).getImm() + 1;
+void PTXAsmPrinter::EmitFunctionBodyEnd() {
+ OutStreamer.EmitRawText(Twine("}"));
}
-void PTXAsmPrinter::printReturnOperand(const MachineInstr *MI, int opNum,
- raw_ostream &OS, const char *Modifier) {
- OS << RETURN_PREFIX << (int) MI->getOperand(opNum).getImm() + 1;
+void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) {
+ MCInst TmpInst;
+ LowerPTXMachineInstrToMCInst(MI, TmpInst, *this);
+ OutStreamer.EmitInstruction(TmpInst);
}
void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) {
@@ -400,14 +310,14 @@ void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) {
unsigned alignment = gv->getAlignment();
if (alignment != 0) {
decl += ".align ";
- decl += utostr(Log2_32(gv->getAlignment()));
+ decl += utostr(gv->getAlignment());
decl += " ";
}
if (PointerType::classof(gv->getType())) {
- const PointerType* pointerTy = dyn_cast<const PointerType>(gv->getType());
- const Type* elementTy = pointerTy->getElementType();
+ PointerType* pointerTy = dyn_cast<PointerType>(gv->getType());
+ Type* elementTy = pointerTy->getElementType();
decl += ".b8 ";
decl += gvsym->getName();
@@ -417,14 +327,14 @@ void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) {
{
assert(elementTy->isArrayTy() && "Only pointers to arrays are supported");
- const ArrayType* arrayTy = dyn_cast<const ArrayType>(elementTy);
+ ArrayType* arrayTy = dyn_cast<ArrayType>(elementTy);
elementTy = arrayTy->getElementType();
unsigned numElements = arrayTy->getNumElements();
while (elementTy->isArrayTy()) {
- arrayTy = dyn_cast<const ArrayType>(elementTy);
+ arrayTy = dyn_cast<ArrayType>(elementTy);
elementTy = arrayTy->getElementType();
numElements *= arrayTy->getNumElements();
@@ -447,7 +357,7 @@ void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) {
if (gv->hasInitializer())
{
- const Constant *C = gv->getInitializer();
+ const Constant *C = gv->getInitializer();
if (const ConstantArray *CA = dyn_cast<ConstantArray>(C))
{
decl += " = {";
@@ -484,7 +394,7 @@ void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) {
OutStreamer.AddBlankLine();
}
-void PTXAsmPrinter::EmitFunctionDeclaration() {
+void PTXAsmPrinter::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()) {
@@ -494,25 +404,39 @@ void PTXAsmPrinter::EmitFunctionDeclaration() {
}
const PTXMachineFunctionInfo *MFI = MF->getInfo<PTXMachineFunctionInfo>();
+ const PTXParamManager &PM = MFI->getParamManager();
const bool isKernel = MFI->isKernel();
const PTXSubtarget& ST = TM.getSubtarget<PTXSubtarget>();
+ const MachineRegisterInfo& MRI = MF->getRegInfo();
std::string decl = isKernel ? ".entry" : ".func";
- unsigned cnt = 0;
-
if (!isKernel) {
decl += " (";
- for (PTXMachineFunctionInfo::ret_iterator
- i = MFI->retRegBegin(), e = MFI->retRegEnd(), b = i;
- i != e; ++i) {
- if (i != b) {
- decl += ", ";
+ if (ST.useParamSpaceForDeviceArgs()) {
+ for (PTXParamManager::param_iterator i = PM.ret_begin(), e = PM.ret_end(),
+ b = i; i != e; ++i) {
+ if (i != b) {
+ decl += ", ";
+ }
+
+ decl += ".param .b";
+ decl += utostr(PM.getParamSize(*i));
+ decl += " ";
+ decl += PM.getParamName(*i);
+ }
+ } else {
+ for (PTXMachineFunctionInfo::reg_iterator
+ i = MFI->retreg_begin(), e = MFI->retreg_end(), b = i;
+ i != e; ++i) {
+ if (i != b) {
+ decl += ", ";
+ }
+ decl += ".reg .";
+ decl += getRegisterTypeName(*i, MRI);
+ decl += " ";
+ decl += MFI->getRegisterName(*i);
}
- decl += ".reg .";
- decl += getRegisterTypeName(*i);
- decl += " ";
- decl += getRegisterName(*i);
}
decl += ")";
}
@@ -523,26 +447,65 @@ void PTXAsmPrinter::EmitFunctionDeclaration() {
decl += " (";
- cnt = 0;
+ const Function *F = MF->getFunction();
// Print parameters
- for (PTXMachineFunctionInfo::reg_iterator
- i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i;
- i != e; ++i) {
- if (i != b) {
- decl += ", ";
- }
- if (isKernel || ST.useParamSpaceForDeviceArgs()) {
+ if (isKernel || ST.useParamSpaceForDeviceArgs()) {
+ /*for (PTXParamManager::param_iterator i = PM.arg_begin(), e = PM.arg_end(),
+ b = i; i != e; ++i) {
+ if (i != b) {
+ decl += ", ";
+ }
+
decl += ".param .b";
- decl += utostr(*i);
+ decl += utostr(PM.getParamSize(*i));
decl += " ";
- decl += PARAM_PREFIX;
- decl += utostr(++cnt);
- } else {
+ decl += PM.getParamName(*i);
+ }*/
+ int Counter = 1;
+ for (Function::const_arg_iterator i = F->arg_begin(), e = F->arg_end(),
+ b = i; i != e; ++i) {
+ if (i != b)
+ decl += ", ";
+ const Type *ArgType = (*i).getType();
+ decl += ".param .b";
+ if (ArgType->isPointerTy()) {
+ if (ST.is64Bit())
+ decl += "64";
+ else
+ decl += "32";
+ } else {
+ decl += utostr(ArgType->getPrimitiveSizeInBits());
+ }
+ if (ArgType->isPointerTy() && ST.emitPtrAttribute()) {
+ const PointerType *PtrType = dyn_cast<const PointerType>(ArgType);
+ decl += " .ptr";
+ switch (PtrType->getAddressSpace()) {
+ default:
+ llvm_unreachable("Unknown address space in argument");
+ case PTXStateSpace::Global:
+ decl += " .global";
+ break;
+ case PTXStateSpace::Shared:
+ decl += " .shared";
+ break;
+ }
+ }
+ decl += " __param_";
+ decl += utostr(Counter++);
+ }
+ } else {
+ for (PTXMachineFunctionInfo::reg_iterator
+ i = MFI->argreg_begin(), e = MFI->argreg_end(), b = i;
+ i != e; ++i) {
+ if (i != b) {
+ decl += ", ";
+ }
+
decl += ".reg .";
- decl += getRegisterTypeName(*i);
+ decl += getRegisterTypeName(*i, MRI);
decl += " ";
- decl += getRegisterName(*i);
+ decl += MFI->getRegisterName(*i);
}
}
decl += ")";
@@ -550,25 +513,6 @@ void PTXAsmPrinter::EmitFunctionDeclaration() {
OutStreamer.EmitRawText(Twine(decl));
}
-void PTXAsmPrinter::
-printPredicateOperand(const MachineInstr *MI, raw_ostream &O) {
- int i = MI->findFirstPredOperandIdx();
- if (i == -1)
- llvm_unreachable("missing predicate operand");
-
- unsigned reg = MI->getOperand(i).getReg();
- int predOp = MI->getOperand(i+1).getImm();
-
- DEBUG(dbgs() << "predicate: (" << reg << ", " << predOp << ")\n");
-
- if (reg != PTX::NoRegister) {
- O << '@';
- if (predOp == PTX::PRED_NEGATE)
- O << '!';
- O << getRegisterName(reg);
- }
-}
-
unsigned PTXAsmPrinter::GetOrCreateSourceID(StringRef FileName,
StringRef DirName) {
// If FE did not provide a file name, then assume stdin.
@@ -596,10 +540,58 @@ unsigned PTXAsmPrinter::GetOrCreateSourceID(StringRef FileName,
return SrcId;
}
-#include "PTXGenAsmWriter.inc"
+MCOperand PTXAsmPrinter::GetSymbolRef(const MachineOperand &MO,
+ const MCSymbol *Symbol) {
+ const MCExpr *Expr;
+ Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, OutContext);
+ return MCOperand::CreateExpr(Expr);
+}
+
+MCOperand PTXAsmPrinter::lowerOperand(const MachineOperand &MO) {
+ MCOperand MCOp;
+ const PTXMachineFunctionInfo *MFI = MF->getInfo<PTXMachineFunctionInfo>();
+ const MCExpr *Expr;
+ const char *RegSymbolName;
+ switch (MO.getType()) {
+ default:
+ llvm_unreachable("Unknown operand type");
+ case MachineOperand::MO_Register:
+ // We create register operands as symbols, since the PTXInstPrinter class
+ // has no way to map virtual registers back to a name without some ugly
+ // hacks.
+ // FIXME: Figure out a better way to handle virtual register naming.
+ RegSymbolName = MFI->getRegisterName(MO.getReg());
+ Expr = MCSymbolRefExpr::Create(RegSymbolName, MCSymbolRefExpr::VK_None,
+ OutContext);
+ MCOp = MCOperand::CreateExpr(Expr);
+ break;
+ case MachineOperand::MO_Immediate:
+ MCOp = MCOperand::CreateImm(MO.getImm());
+ break;
+ case MachineOperand::MO_MachineBasicBlock:
+ MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
+ MO.getMBB()->getSymbol(), OutContext));
+ break;
+ case MachineOperand::MO_GlobalAddress:
+ MCOp = GetSymbolRef(MO, Mang->getSymbol(MO.getGlobal()));
+ break;
+ case MachineOperand::MO_ExternalSymbol:
+ MCOp = GetSymbolRef(MO, GetExternalSymbolSymbol(MO.getSymbolName()));
+ break;
+ case MachineOperand::MO_FPImmediate:
+ APFloat Val = MO.getFPImm()->getValueAPF();
+ bool ignored;
+ Val.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &ignored);
+ MCOp = MCOperand::CreateFPImm(Val.convertToDouble());
+ break;
+ }
+
+ return MCOp;
+}
// Force static initialization.
extern "C" void LLVMInitializePTXAsmPrinter() {
RegisterAsmPrinter<PTXAsmPrinter> X(ThePTX32Target);
RegisterAsmPrinter<PTXAsmPrinter> Y(ThePTX64Target);
}
+
diff --git a/lib/Target/PTX/PTXAsmPrinter.h b/lib/Target/PTX/PTXAsmPrinter.h
new file mode 100644
index 0000000..538c080
--- /dev/null
+++ b/lib/Target/PTX/PTXAsmPrinter.h
@@ -0,0 +1,57 @@
+//===-- PTXAsmPrinter.h - Print machine code to a PTX file ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// PTX Assembly printer class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PTXASMPRINTER_H
+#define PTXASMPRINTER_H
+
+#include "PTX.h"
+#include "PTXTargetMachine.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+class MCOperand;
+
+class LLVM_LIBRARY_VISIBILITY PTXAsmPrinter : public AsmPrinter {
+public:
+ explicit PTXAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
+ : AsmPrinter(TM, Streamer) {}
+
+ const char *getPassName() const { return "PTX Assembly Printer"; }
+
+ bool doFinalization(Module &M);
+
+ virtual void EmitStartOfAsmFile(Module &M);
+ virtual void EmitFunctionBodyStart();
+ virtual void EmitFunctionBodyEnd();
+ virtual void EmitFunctionEntryLabel();
+ virtual void EmitInstruction(const MachineInstr *MI);
+
+ unsigned GetOrCreateSourceID(StringRef FileName,
+ StringRef DirName);
+
+ MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol);
+ MCOperand lowerOperand(const MachineOperand &MO);
+
+private:
+ void EmitVariableDeclaration(const GlobalVariable *gv);
+ void EmitFunctionDeclaration();
+
+ StringMap<unsigned> SourceIdMap;
+}; // class PTXAsmPrinter
+} // namespace llvm
+
+#endif
+
diff --git a/lib/Target/PTX/PTXCallingConv.td b/lib/Target/PTX/PTXCallingConv.td
deleted file mode 100644
index 3e3ff48..0000000
--- a/lib/Target/PTX/PTXCallingConv.td
+++ /dev/null
@@ -1,29 +0,0 @@
-
-//===--- PTXCallingConv.td - Calling Conventions -----------*- tablegen -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This describes the calling conventions for the PTX architecture.
-//
-//===----------------------------------------------------------------------===//
-
-// PTX Formal Parameter Calling Convention
-def CC_PTX : CallingConv<[
- CCIfType<[i1], CCAssignToReg<[P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124, P125, P126, P127]>>,
- CCIfType<[i16], CCAssignToReg<[RH12, RH13, RH14, RH15, RH16, RH17, RH18, RH19, RH20, RH21, RH22, RH23, RH24, RH25, RH26, RH27, RH28, RH29, RH30, RH31, RH32, RH33, RH34, RH35, RH36, RH37, RH38, RH39, RH40, RH41, RH42, RH43, RH44, RH45, RH46, RH47, RH48, RH49, RH50, RH51, RH52, RH53, RH54, RH55, RH56, RH57, RH58, RH59, RH60, RH61, RH62, RH63, RH64, RH65, RH66, RH67, RH68, RH69, RH70, RH71, RH72, RH73, RH74, RH75, RH76, RH77, RH78, RH79, RH80, RH81, RH82, RH83, RH84, RH85, RH86, RH87, RH88, RH89, RH90, RH91, RH92, RH93, RH94, RH95, RH96, RH97, RH98, RH99, RH100, RH101, RH102, RH103, RH104, RH105, RH106, RH107, RH108, RH109, RH110, RH111, RH112, RH113, RH114, RH115, RH116, RH117, RH118, RH119, RH120, RH121, RH122, RH123, RH124, RH125, RH126, RH127]>>,
- CCIfType<[i32,f32], CCAssignToReg<[R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, R77, R78, R79, R80, R81, R82, R83, R84, R85, R86, R87, R88, R89, R90, R91, R92, R93, R94, R95, R96, R97, R98, R99, R100, R101, R102, R103, R104, R105, R106, R107, R108, R109, R110, R111, R112, R113, R114, R115, R116, R117, R118, R119, R120, R121, R122, R123, R124, R125, R126, R127]>>,
- CCIfType<[i64,f64], CCAssignToReg<[RD12, RD13, RD14, RD15, RD16, RD17, RD18, RD19, RD20, RD21, RD22, RD23, RD24, RD25, RD26, RD27, RD28, RD29, RD30, RD31, RD32, RD33, RD34, RD35, RD36, RD37, RD38, RD39, RD40, RD41, RD42, RD43, RD44, RD45, RD46, RD47, RD48, RD49, RD50, RD51, RD52, RD53, RD54, RD55, RD56, RD57, RD58, RD59, RD60, RD61, RD62, RD63, RD64, RD65, RD66, RD67, RD68, RD69, RD70, RD71, RD72, RD73, RD74, RD75, RD76, RD77, RD78, RD79, RD80, RD81, RD82, RD83, RD84, RD85, RD86, RD87, RD88, RD89, RD90, RD91, RD92, RD93, RD94, RD95, RD96, RD97, RD98, RD99, RD100, RD101, RD102, RD103, RD104, RD105, RD106, RD107, RD108, RD109, RD110, RD111, RD112, RD113, RD114, RD115, RD116, RD117, RD118, RD119, RD120, RD121, RD122, RD123, RD124, RD125, RD126, RD127]>>
-]>;
-
-// PTX Return Value Calling Convention
-def RetCC_PTX : CallingConv<[
- CCIfType<[i1], CCAssignToReg<[P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11]>>,
- CCIfType<[i16], CCAssignToReg<[RH0, RH1, RH2, RH3, RH4, RH5, RH6, RH7, RH8, RH9, RH10, RH11]>>,
- CCIfType<[i32,f32], CCAssignToReg<[R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11]>>,
- CCIfType<[i64,f64], CCAssignToReg<[RD0, RD1, RD2, RD3, RD4, RD5, RD6, RD7, RD8, RD9, RD10, RD11]>>
-]>;
diff --git a/lib/Target/PTX/PTXFPRoundingModePass.cpp b/lib/Target/PTX/PTXFPRoundingModePass.cpp
new file mode 100644
index 0000000..0b653e0
--- /dev/null
+++ b/lib/Target/PTX/PTXFPRoundingModePass.cpp
@@ -0,0 +1,179 @@
+//===-- PTXFPRoundingModePass.cpp - Assign rounding modes pass ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a machine function pass that sets appropriate FP rounding
+// modes for all relevant instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "ptx-fp-rounding-mode"
+
+#include "PTX.h"
+#include "PTXTargetMachine.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+
+// NOTE: PTXFPRoundingModePass should be executed just before emission.
+
+namespace llvm {
+ /// PTXFPRoundingModePass - Pass to assign appropriate FP rounding modes to
+ /// all FP instructions. Essentially, this pass just looks for all FP
+ /// instructions that have a rounding mode set to RndDefault, and sets an
+ /// appropriate rounding mode based on the target device.
+ ///
+ class PTXFPRoundingModePass : public MachineFunctionPass {
+ private:
+ static char ID;
+
+ typedef std::pair<unsigned, unsigned> RndModeDesc;
+
+ PTXTargetMachine& TargetMachine;
+ DenseMap<unsigned, RndModeDesc> Instrs;
+
+ public:
+ PTXFPRoundingModePass(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel)
+ : MachineFunctionPass(ID),
+ TargetMachine(TM) {
+ initializeMap();
+ }
+
+ virtual bool runOnMachineFunction(MachineFunction &MF);
+
+ virtual const char *getPassName() const {
+ return "PTX FP Rounding Mode Pass";
+ }
+
+ private:
+
+ void initializeMap();
+ void processInstruction(MachineInstr &MI);
+ }; // class PTXFPRoundingModePass
+} // namespace llvm
+
+using namespace llvm;
+
+char PTXFPRoundingModePass::ID = 0;
+
+bool PTXFPRoundingModePass::runOnMachineFunction(MachineFunction &MF) {
+ // Look at each basic block
+ for (MachineFunction::iterator bbi = MF.begin(), bbe = MF.end(); bbi != bbe;
+ ++bbi) {
+ MachineBasicBlock &MBB = *bbi;
+ // Look at each instruction
+ for (MachineBasicBlock::iterator ii = MBB.begin(), ie = MBB.end();
+ ii != ie; ++ii) {
+ MachineInstr &MI = *ii;
+ processInstruction(MI);
+ }
+ }
+ return false;
+}
+
+void PTXFPRoundingModePass::initializeMap() {
+ using namespace PTXRoundingMode;
+ const PTXSubtarget& ST = TargetMachine.getSubtarget<PTXSubtarget>();
+
+ // Build a map of default rounding mode for all instructions that need a
+ // rounding mode.
+ Instrs[PTX::FADDrr32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FADDri32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FADDrr64] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FADDri64] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FSUBrr32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FSUBri32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FSUBrr64] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FSUBri64] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FMULrr32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FMULri32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FMULrr64] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FMULri64] = std::make_pair(1U, (unsigned)RndNearestEven);
+
+ Instrs[PTX::FNEGrr32] = std::make_pair(1U, (unsigned)RndNone);
+ Instrs[PTX::FNEGri32] = std::make_pair(1U, (unsigned)RndNone);
+ Instrs[PTX::FNEGrr64] = std::make_pair(1U, (unsigned)RndNone);
+ Instrs[PTX::FNEGri64] = std::make_pair(1U, (unsigned)RndNone);
+
+ unsigned FDivRndMode = ST.fdivNeedsRoundingMode() ? RndNearestEven : RndNone;
+ Instrs[PTX::FDIVrr32] = std::make_pair(1U, FDivRndMode);
+ Instrs[PTX::FDIVri32] = std::make_pair(1U, FDivRndMode);
+ Instrs[PTX::FDIVrr64] = std::make_pair(1U, FDivRndMode);
+ Instrs[PTX::FDIVri64] = std::make_pair(1U, FDivRndMode);
+
+ unsigned FMADRndMode = ST.fmadNeedsRoundingMode() ? RndNearestEven : RndNone;
+ Instrs[PTX::FMADrrr32] = std::make_pair(1U, FMADRndMode);
+ Instrs[PTX::FMADrri32] = std::make_pair(1U, FMADRndMode);
+ Instrs[PTX::FMADrii32] = std::make_pair(1U, FMADRndMode);
+ Instrs[PTX::FMADrrr64] = std::make_pair(1U, FMADRndMode);
+ Instrs[PTX::FMADrri64] = std::make_pair(1U, FMADRndMode);
+ Instrs[PTX::FMADrii64] = std::make_pair(1U, FMADRndMode);
+
+ Instrs[PTX::FSQRTrr32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FSQRTri32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FSQRTrr64] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::FSQRTri64] = std::make_pair(1U, (unsigned)RndNearestEven);
+
+ Instrs[PTX::FSINrr32] = std::make_pair(1U, (unsigned)RndApprox);
+ Instrs[PTX::FSINri32] = std::make_pair(1U, (unsigned)RndApprox);
+ Instrs[PTX::FSINrr64] = std::make_pair(1U, (unsigned)RndApprox);
+ Instrs[PTX::FSINri64] = std::make_pair(1U, (unsigned)RndApprox);
+ Instrs[PTX::FCOSrr32] = std::make_pair(1U, (unsigned)RndApprox);
+ Instrs[PTX::FCOSri32] = std::make_pair(1U, (unsigned)RndApprox);
+ Instrs[PTX::FCOSrr64] = std::make_pair(1U, (unsigned)RndApprox);
+ Instrs[PTX::FCOSri64] = std::make_pair(1U, (unsigned)RndApprox);
+
+ Instrs[PTX::CVTu16f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+ Instrs[PTX::CVTs16f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+ Instrs[PTX::CVTu16f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+ Instrs[PTX::CVTs16f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+ Instrs[PTX::CVTu32f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+ Instrs[PTX::CVTs32f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+ Instrs[PTX::CVTu32f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+ Instrs[PTX::CVTs32f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+ Instrs[PTX::CVTu64f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+ Instrs[PTX::CVTs64f32] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+ Instrs[PTX::CVTu64f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+ Instrs[PTX::CVTs64f64] = std::make_pair(1U, (unsigned)RndTowardsZeroInt);
+
+ Instrs[PTX::CVTf32u16] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf32s16] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf32u32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf32s32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf32u64] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf32s64] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf32f64] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf64u16] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf64s16] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf64u32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf64s32] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf64u64] = std::make_pair(1U, (unsigned)RndNearestEven);
+ Instrs[PTX::CVTf64s64] = std::make_pair(1U, (unsigned)RndNearestEven);
+}
+
+void PTXFPRoundingModePass::processInstruction(MachineInstr &MI) {
+ // Is this an instruction that needs a rounding mode?
+ if (Instrs.count(MI.getOpcode())) {
+ const RndModeDesc &Desc = Instrs[MI.getOpcode()];
+ // Get the rounding mode operand
+ MachineOperand &Op = MI.getOperand(Desc.first);
+ // Update the rounding mode if needed
+ if (Op.getImm() == PTXRoundingMode::RndDefault) {
+ Op.setImm(Desc.second);
+ }
+ }
+}
+
+FunctionPass *llvm::createPTXFPRoundingModePass(PTXTargetMachine &TM,
+ CodeGenOpt::Level OptLevel) {
+ return new PTXFPRoundingModePass(TM, OptLevel);
+}
+
diff --git a/lib/Target/PTX/PTXISelDAGToDAG.cpp b/lib/Target/PTX/PTXISelDAGToDAG.cpp
index 9adfa62..5c7ee29 100644
--- a/lib/Target/PTX/PTXISelDAGToDAG.cpp
+++ b/lib/Target/PTX/PTXISelDAGToDAG.cpp
@@ -12,7 +12,9 @@
//===----------------------------------------------------------------------===//
#include "PTX.h"
+#include "PTXMachineFunctionInfo.h"
#include "PTXTargetMachine.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Support/Debug.h"
@@ -37,6 +39,7 @@ class PTXDAGToDAGISel : public SelectionDAGISel {
bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
+ bool SelectADDRlocal(SDValue &Addr, SDValue &Base, SDValue &Offset);
// Include the pieces auto'gened from the target description
#include "PTXGenDAGISel.inc"
@@ -46,6 +49,10 @@ class PTXDAGToDAGISel : public SelectionDAGISel {
// pattern (PTXbrcond bb:$d, ...) in PTXInstrInfo.td
SDNode *SelectBRCOND(SDNode *Node);
+ SDNode *SelectREADPARAM(SDNode *Node);
+ SDNode *SelectWRITEPARAM(SDNode *Node);
+ SDNode *SelectFrameIndex(SDNode *Node);
+
bool isImm(const SDValue &operand);
bool SelectImm(const SDValue &operand, SDValue &imm);
@@ -68,6 +75,12 @@ SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
switch (Node->getOpcode()) {
case ISD::BRCOND:
return SelectBRCOND(Node);
+ case PTXISD::READ_PARAM:
+ return SelectREADPARAM(Node);
+ case PTXISD::WRITE_PARAM:
+ return SelectWRITEPARAM(Node);
+ case ISD::FrameIndex:
+ return SelectFrameIndex(Node);
default:
return SelectCode(Node);
}
@@ -79,7 +92,7 @@ SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) {
SDValue Chain = Node->getOperand(0);
SDValue Pred = Node->getOperand(1);
SDValue Target = Node->getOperand(2); // branch target
- SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
+ SDValue PredOp = CurDAG->getTargetConstant(PTXPredicate::Normal, MVT::i32);
DebugLoc dl = Node->getDebugLoc();
assert(Target.getOpcode() == ISD::BasicBlock);
@@ -90,6 +103,97 @@ SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) {
return CurDAG->getMachineNode(PTX::BRAdp, dl, MVT::Other, Ops, 4);
}
+SDNode *PTXDAGToDAGISel::SelectREADPARAM(SDNode *Node) {
+ SDValue Chain = Node->getOperand(0);
+ SDValue Index = Node->getOperand(1);
+
+ int OpCode;
+
+ // Get the type of parameter we are reading
+ EVT VT = Node->getValueType(0);
+ assert(VT.isSimple() && "READ_PARAM only implemented for MVT types");
+
+ MVT Type = VT.getSimpleVT();
+
+ if (Type == MVT::i1)
+ OpCode = PTX::READPARAMPRED;
+ else if (Type == MVT::i16)
+ OpCode = PTX::READPARAMI16;
+ else if (Type == MVT::i32)
+ OpCode = PTX::READPARAMI32;
+ else if (Type == MVT::i64)
+ OpCode = PTX::READPARAMI64;
+ else if (Type == MVT::f32)
+ OpCode = PTX::READPARAMF32;
+ else {
+ assert(Type == MVT::f64 && "Unexpected type!");
+ OpCode = PTX::READPARAMF64;
+ }
+
+ SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
+ SDValue PredOp = CurDAG->getTargetConstant(PTXPredicate::None, MVT::i32);
+ DebugLoc dl = Node->getDebugLoc();
+
+ SDValue Ops[] = { Index, Pred, PredOp, Chain };
+ return CurDAG->getMachineNode(OpCode, dl, VT, Ops, 4);
+}
+
+SDNode *PTXDAGToDAGISel::SelectWRITEPARAM(SDNode *Node) {
+
+ SDValue Chain = Node->getOperand(0);
+ SDValue Value = Node->getOperand(1);
+
+ int OpCode;
+
+ //Node->dumpr(CurDAG);
+
+ // Get the type of parameter we are writing
+ EVT VT = Value->getValueType(0);
+ assert(VT.isSimple() && "WRITE_PARAM only implemented for MVT types");
+
+ MVT Type = VT.getSimpleVT();
+
+ if (Type == MVT::i1)
+ OpCode = PTX::WRITEPARAMPRED;
+ else if (Type == MVT::i16)
+ OpCode = PTX::WRITEPARAMI16;
+ else if (Type == MVT::i32)
+ OpCode = PTX::WRITEPARAMI32;
+ else if (Type == MVT::i64)
+ OpCode = PTX::WRITEPARAMI64;
+ else if (Type == MVT::f32)
+ OpCode = PTX::WRITEPARAMF32;
+ else if (Type == MVT::f64)
+ OpCode = PTX::WRITEPARAMF64;
+ else
+ llvm_unreachable("Invalid type in SelectWRITEPARAM");
+
+ SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
+ SDValue PredOp = CurDAG->getTargetConstant(PTXPredicate::None, MVT::i32);
+ DebugLoc dl = Node->getDebugLoc();
+
+ SDValue Ops[] = { Value, Pred, PredOp, Chain };
+ SDNode* Ret = CurDAG->getMachineNode(OpCode, dl, MVT::Other, Ops, 4);
+
+ //dbgs() << "SelectWRITEPARAM produced:\n\t";
+ //Ret->dumpr(CurDAG);
+
+ return Ret;
+}
+
+SDNode *PTXDAGToDAGISel::SelectFrameIndex(SDNode *Node) {
+ int FI = cast<FrameIndexSDNode>(Node)->getIndex();
+ //dbgs() << "Selecting FrameIndex at index " << FI << "\n";
+ //SDValue TFI = CurDAG->getTargetFrameIndex(FI, Node->getValueType(0));
+
+ PTXMachineFunctionInfo *MFI = MF->getInfo<PTXMachineFunctionInfo>();
+
+ SDValue FrameSymbol = CurDAG->getTargetExternalSymbol(MFI->getFrameSymbol(FI),
+ Node->getValueType(0));
+
+ return FrameSymbol.getNode();
+}
+
// Match memory operand of the form [reg+reg]
bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
@@ -107,14 +211,54 @@ bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
SDValue &Offset) {
- if (Addr.getOpcode() != ISD::ADD) {
+ // FrameIndex addresses are handled separately
+ //errs() << "SelectADDRri: ";
+ //Addr.getNode()->dumpr();
+ if (isa<FrameIndexSDNode>(Addr)) {
+ //errs() << "Failure\n";
+ return false;
+ }
+
+ if (CurDAG->isBaseWithConstantOffset(Addr)) {
+ Base = Addr.getOperand(0);
+ if (isa<FrameIndexSDNode>(Base)) {
+ //errs() << "Failure\n";
+ return false;
+ }
+ ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
+ Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
+ //errs() << "Success\n";
+ return true;
+ }
+
+ /*if (Addr.getNumOperands() == 1) {
+ Base = Addr;
+ Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
+ errs() << "Success\n";
+ return true;
+ }*/
+
+ //errs() << "SelectADDRri fails on: ";
+ //Addr.getNode()->dumpr();
+
+ if (isImm(Addr)) {
+ //errs() << "Failure\n";
+ return false;
+ }
+
+ Base = Addr;
+ Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
+
+ //errs() << "Success\n";
+ return true;
+
+ /*if (Addr.getOpcode() != ISD::ADD) {
// let SelectADDRii handle the [imm] case
if (isImm(Addr))
return false;
// it is [reg]
assert(Addr.getValueType().isSimple() && "Type must be simple");
-
Base = Addr;
Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
@@ -136,7 +280,7 @@ bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
}
// neither [reg+imm] nor [imm+reg]
- return false;
+ return false;*/
}
// Match memory operand of the form [imm+imm] and [imm]
@@ -160,6 +304,36 @@ bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
return false;
}
+// Match memory operand of the form [reg], [imm+reg], and [reg+imm]
+bool PTXDAGToDAGISel::SelectADDRlocal(SDValue &Addr, SDValue &Base,
+ SDValue &Offset) {
+ //errs() << "SelectADDRlocal: ";
+ //Addr.getNode()->dumpr();
+ if (isa<FrameIndexSDNode>(Addr)) {
+ Base = Addr;
+ Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
+ //errs() << "Success\n";
+ return true;
+ }
+
+ if (CurDAG->isBaseWithConstantOffset(Addr)) {
+ Base = Addr.getOperand(0);
+ if (!isa<FrameIndexSDNode>(Base)) {
+ //errs() << "Failure\n";
+ return false;
+ }
+ ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
+ Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
+ //errs() << "Offset: ";
+ //Offset.getNode()->dumpr();
+ //errs() << "Success\n";
+ return true;
+ }
+
+ //errs() << "Failure\n";
+ return false;
+}
+
bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
return ConstantSDNode::classof(operand.getNode());
}
diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp
index 6fcf710..3307d91 100644
--- a/lib/Target/PTX/PTXISelLowering.cpp
+++ b/lib/Target/PTX/PTXISelLowering.cpp
@@ -16,23 +16,19 @@
#include "PTXMachineFunctionInfo.h"
#include "PTXRegisterInfo.h"
#include "PTXSubtarget.h"
+#include "llvm/Function.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
-// Calling Convention Implementation
-//===----------------------------------------------------------------------===//
-
-#include "PTXGenCallingConv.inc"
-
-//===----------------------------------------------------------------------===//
// TargetLowering Implementation
//===----------------------------------------------------------------------===//
@@ -47,57 +43,58 @@ PTXTargetLowering::PTXTargetLowering(TargetMachine &TM)
addRegisterClass(MVT::f64, PTX::RegF64RegisterClass);
setBooleanContents(ZeroOrOneBooleanContent);
+ setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
setMinFunctionAlignment(2);
-
+
////////////////////////////////////
/////////// Expansion //////////////
////////////////////////////////////
-
+
// (any/zero/sign) extload => load + (any/zero/sign) extend
-
+
setLoadExtAction(ISD::EXTLOAD, MVT::i16, Expand);
setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand);
setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand);
-
+
// f32 extload => load + fextend
-
- setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
-
+
+ setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
+
// f64 truncstore => trunc + store
-
- setTruncStoreAction(MVT::f64, MVT::f32, Expand);
-
+
+ setTruncStoreAction(MVT::f64, MVT::f32, Expand);
+
// sign_extend_inreg => sign_extend
-
+
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
-
+
// br_cc => brcond
-
+
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
// select_cc => setcc
-
+
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
-
+
////////////////////////////////////
//////////// Legal /////////////////
////////////////////////////////////
-
+
setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
setOperationAction(ISD::ConstantFP, MVT::f64, Legal);
-
+
////////////////////////////////////
//////////// Custom ////////////////
////////////////////////////////////
-
+
// customise setcc to use bitwise logic if possible
-
+
setOperationAction(ISD::SETCC, MVT::i1, Custom);
// customize translation of memory addresses
-
+
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
@@ -105,7 +102,7 @@ PTXTargetLowering::PTXTargetLowering(TargetMachine &TM)
computeRegisterProperties();
}
-MVT::SimpleValueType PTXTargetLowering::getSetCCResultType(EVT VT) const {
+EVT PTXTargetLowering::getSetCCResultType(EVT VT) const {
return MVT::i1;
}
@@ -130,10 +127,16 @@ const char *PTXTargetLowering::getTargetNodeName(unsigned Opcode) const {
return "PTXISD::LOAD_PARAM";
case PTXISD::STORE_PARAM:
return "PTXISD::STORE_PARAM";
+ case PTXISD::READ_PARAM:
+ return "PTXISD::READ_PARAM";
+ case PTXISD::WRITE_PARAM:
+ return "PTXISD::WRITE_PARAM";
case PTXISD::EXIT:
return "PTXISD::EXIT";
case PTXISD::RET:
return "PTXISD::RET";
+ case PTXISD::CALL:
+ return "PTXISD::CALL";
}
}
@@ -149,7 +152,7 @@ SDValue PTXTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
DebugLoc dl = Op.getDebugLoc();
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
- // Look for X == 0, X == 1, X != 0, or X != 1
+ // Look for X == 0, X == 1, X != 0, or X != 1
// We can simplify these to bitwise logic
if (Op1.getOpcode() == ISD::Constant &&
@@ -197,6 +200,7 @@ SDValue PTXTargetLowering::
MachineFunction &MF = DAG.getMachineFunction();
const PTXSubtarget& ST = getTargetMachine().getSubtarget<PTXSubtarget>();
PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
+ PTXParamManager &PM = MFI->getParamManager();
switch (CallConv) {
default:
@@ -216,68 +220,34 @@ SDValue PTXTargetLowering::
if (MFI->isKernel() || ST.useParamSpaceForDeviceArgs()) {
// We just need to emit the proper LOAD_PARAM ISDs
for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
-
assert((!MFI->isKernel() || Ins[i].VT != MVT::i1) &&
"Kernels cannot take pred operands");
+ unsigned ParamSize = Ins[i].VT.getStoreSizeInBits();
+ unsigned Param = PM.addArgumentParam(ParamSize);
+ const std::string &ParamName = PM.getParamName(Param);
+ SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(),
+ MVT::Other);
SDValue ArgValue = DAG.getNode(PTXISD::LOAD_PARAM, dl, Ins[i].VT, Chain,
- DAG.getTargetConstant(i, MVT::i32));
+ ParamValue);
InVals.push_back(ArgValue);
-
- // Instead of storing a physical register in our argument list, we just
- // store the total size of the parameter, in bits. The ASM printer
- // knows how to process this.
- MFI->addArgReg(Ins[i].VT.getStoreSizeInBits());
}
}
else {
- // For device functions, we use the PTX calling convention to do register
- // assignments then create CopyFromReg ISDs for the allocated registers
-
- SmallVector<CCValAssign, 16> ArgLocs;
- CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), ArgLocs,
- *DAG.getContext());
-
- CCInfo.AnalyzeFormalArguments(Ins, CC_PTX);
-
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
-
- CCValAssign& VA = ArgLocs[i];
- EVT RegVT = VA.getLocVT();
- TargetRegisterClass* TRC = 0;
-
- assert(VA.isRegLoc() && "CCValAssign must be RegLoc");
-
- // Determine which register class we need
- if (RegVT == MVT::i1) {
- TRC = PTX::RegPredRegisterClass;
- }
- else if (RegVT == MVT::i16) {
- TRC = PTX::RegI16RegisterClass;
- }
- else if (RegVT == MVT::i32) {
- TRC = PTX::RegI32RegisterClass;
- }
- else if (RegVT == MVT::i64) {
- TRC = PTX::RegI64RegisterClass;
- }
- else if (RegVT == MVT::f32) {
- TRC = PTX::RegF32RegisterClass;
- }
- else if (RegVT == MVT::f64) {
- TRC = PTX::RegF64RegisterClass;
- }
- else {
- llvm_unreachable("Unknown parameter type");
- }
+ for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
+ EVT RegVT = Ins[i].VT;
+ TargetRegisterClass* TRC = getRegClassFor(RegVT);
+ // Use a unique index in the instruction to prevent instruction folding.
+ // Yes, this is a hack.
+ SDValue Index = DAG.getTargetConstant(i, MVT::i32);
unsigned Reg = MF.getRegInfo().createVirtualRegister(TRC);
- MF.getRegInfo().addLiveIn(VA.getLocReg(), Reg);
+ SDValue ArgValue = DAG.getNode(PTXISD::READ_PARAM, dl, RegVT, Chain,
+ Index);
- SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
InVals.push_back(ArgValue);
- MFI->addArgReg(VA.getLocReg());
+ MFI->addArgReg(Reg);
}
}
@@ -301,41 +271,66 @@ SDValue PTXTargetLowering::
assert(Outs.size() == 0 && "Kernel must return void.");
return DAG.getNode(PTXISD::EXIT, dl, MVT::Other, Chain);
case CallingConv::PTX_Device:
- //assert(Outs.size() <= 1 && "Can at most return one value.");
+ assert(Outs.size() <= 1 && "Can at most return one value.");
break;
}
MachineFunction& MF = DAG.getMachineFunction();
PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
+ PTXParamManager &PM = MFI->getParamManager();
SDValue Flag;
+ const PTXSubtarget& ST = getTargetMachine().getSubtarget<PTXSubtarget>();
- // Even though we could use the .param space for return arguments for
- // device functions if SM >= 2.0 and the number of return arguments is
- // only 1, we just always use registers since this makes the codegen
- // easier.
- SmallVector<CCValAssign, 16> RVLocs;
- CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
- getTargetMachine(), RVLocs, *DAG.getContext());
-
- CCInfo.AnalyzeReturn(Outs, RetCC_PTX);
-
- for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
- CCValAssign& VA = RVLocs[i];
-
- assert(VA.isRegLoc() && "CCValAssign must be RegLoc");
+ if (ST.useParamSpaceForDeviceArgs()) {
+ assert(Outs.size() < 2 && "Device functions can return at most one value");
+
+ if (Outs.size() == 1) {
+ unsigned ParamSize = OutVals[0].getValueType().getSizeInBits();
+ unsigned Param = PM.addReturnParam(ParamSize);
+ const std::string &ParamName = PM.getParamName(Param);
+ SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(),
+ MVT::Other);
+ Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, MVT::Other, Chain,
+ ParamValue, OutVals[0]);
+ }
+ } else {
+ for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
+ EVT RegVT = Outs[i].VT;
+ TargetRegisterClass* TRC = 0;
- unsigned Reg = VA.getLocReg();
+ // Determine which register class we need
+ if (RegVT == MVT::i1) {
+ TRC = PTX::RegPredRegisterClass;
+ }
+ else if (RegVT == MVT::i16) {
+ TRC = PTX::RegI16RegisterClass;
+ }
+ else if (RegVT == MVT::i32) {
+ TRC = PTX::RegI32RegisterClass;
+ }
+ else if (RegVT == MVT::i64) {
+ TRC = PTX::RegI64RegisterClass;
+ }
+ else if (RegVT == MVT::f32) {
+ TRC = PTX::RegF32RegisterClass;
+ }
+ else if (RegVT == MVT::f64) {
+ TRC = PTX::RegF64RegisterClass;
+ }
+ else {
+ llvm_unreachable("Unknown parameter type");
+ }
- DAG.getMachineFunction().getRegInfo().addLiveOut(Reg);
+ unsigned Reg = MF.getRegInfo().createVirtualRegister(TRC);
- Chain = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i], Flag);
+ SDValue Copy = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i]/*, Flag*/);
+ SDValue OutReg = DAG.getRegister(Reg, RegVT);
- // Guarantee that all emitted copies are stuck together,
- // avoiding something bad
- Flag = Chain.getValue(1);
+ Chain = DAG.getNode(PTXISD::WRITE_PARAM, dl, MVT::Other, Copy, OutReg);
- MFI->addRetReg(Reg);
+ MFI->addRetReg(Reg);
+ }
}
if (Flag.getNode() == 0) {
@@ -345,3 +340,83 @@ SDValue PTXTargetLowering::
return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag);
}
}
+
+SDValue
+PTXTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
+ CallingConv::ID CallConv, bool isVarArg,
+ bool &isTailCall,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<SDValue> &OutVals,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const {
+
+ MachineFunction& MF = DAG.getMachineFunction();
+ PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
+ PTXParamManager &PM = MFI->getParamManager();
+
+ assert(getTargetMachine().getSubtarget<PTXSubtarget>().callsAreHandled() &&
+ "Calls are not handled for the target device");
+
+ std::vector<SDValue> Ops;
+ // The layout of the ops will be [Chain, #Ins, Ins, Callee, #Outs, Outs]
+ Ops.resize(Outs.size() + Ins.size() + 4);
+
+ Ops[0] = Chain;
+
+ // Identify the callee function
+ const GlobalValue *GV = cast<GlobalAddressSDNode>(Callee)->getGlobal();
+ assert(cast<Function>(GV)->getCallingConv() == CallingConv::PTX_Device &&
+ "PTX function calls must be to PTX device functions");
+ Callee = DAG.getTargetGlobalAddress(GV, dl, getPointerTy());
+ Ops[Ins.size()+2] = Callee;
+
+ // Generate STORE_PARAM nodes for each function argument. In PTX, function
+ // arguments are explicitly stored into .param variables and passed as
+ // arguments. There is no register/stack-based calling convention in PTX.
+ Ops[Ins.size()+3] = DAG.getTargetConstant(OutVals.size(), MVT::i32);
+ for (unsigned i = 0; i != OutVals.size(); ++i) {
+ unsigned Size = OutVals[i].getValueType().getSizeInBits();
+ unsigned Param = PM.addLocalParam(Size);
+ const std::string &ParamName = PM.getParamName(Param);
+ SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(),
+ MVT::Other);
+ Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, MVT::Other, Chain,
+ ParamValue, OutVals[i]);
+ Ops[i+Ins.size()+4] = ParamValue;
+ }
+
+ std::vector<SDValue> InParams;
+
+ // Generate list of .param variables to hold the return value(s).
+ Ops[1] = DAG.getTargetConstant(Ins.size(), MVT::i32);
+ for (unsigned i = 0; i < Ins.size(); ++i) {
+ unsigned Size = Ins[i].VT.getStoreSizeInBits();
+ unsigned Param = PM.addLocalParam(Size);
+ const std::string &ParamName = PM.getParamName(Param);
+ SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(),
+ MVT::Other);
+ Ops[i+2] = ParamValue;
+ InParams.push_back(ParamValue);
+ }
+
+ Ops[0] = Chain;
+
+ // Create the CALL node.
+ Chain = DAG.getNode(PTXISD::CALL, dl, MVT::Other, &Ops[0], Ops.size());
+
+ // Create the LOAD_PARAM nodes that retrieve the function return value(s).
+ for (unsigned i = 0; i < Ins.size(); ++i) {
+ SDValue Load = DAG.getNode(PTXISD::LOAD_PARAM, dl, Ins[i].VT, Chain,
+ InParams[i]);
+ InVals.push_back(Load);
+ }
+
+ return Chain;
+}
+
+unsigned PTXTargetLowering::getNumRegisters(LLVMContext &Context, EVT VT) {
+ // All arguments consist of one "register," regardless of the type.
+ return 1;
+}
+
diff --git a/lib/Target/PTX/PTXISelLowering.h b/lib/Target/PTX/PTXISelLowering.h
index 4318541..4d25665 100644
--- a/lib/Target/PTX/PTXISelLowering.h
+++ b/lib/Target/PTX/PTXISelLowering.h
@@ -26,9 +26,12 @@ namespace PTXISD {
FIRST_NUMBER = ISD::BUILTIN_OP_END,
LOAD_PARAM,
STORE_PARAM,
+ READ_PARAM,
+ WRITE_PARAM,
EXIT,
RET,
- COPY_ADDRESS
+ COPY_ADDRESS,
+ CALL
};
} // namespace PTXISD
@@ -60,7 +63,19 @@ class PTXTargetLowering : public TargetLowering {
DebugLoc dl,
SelectionDAG &DAG) const;
- virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
+ virtual SDValue
+ LowerCall(SDValue Chain, SDValue Callee,
+ CallingConv::ID CallConv, bool isVarArg,
+ bool &isTailCall,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<SDValue> &OutVals,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const;
+
+ virtual EVT getSetCCResultType(EVT VT) const;
+
+ virtual unsigned getNumRegisters(LLVMContext &Context, EVT VT);
private:
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
diff --git a/lib/Target/PTX/PTXInstrFormats.td b/lib/Target/PTX/PTXInstrFormats.td
index 8cee351..397fdc3 100644
--- a/lib/Target/PTX/PTXInstrFormats.td
+++ b/lib/Target/PTX/PTXInstrFormats.td
@@ -7,12 +7,39 @@
//
//===----------------------------------------------------------------------===//
-// PTX Predicate operand, default to (0, 0) = (zero-reg, always).
+
+// Rounding Mode Specifier
+/*class RoundingMode<bits<3> val> {
+ bits<3> Value = val;
+}
+
+def RndDefault : RoundingMode<0>;
+def RndNearestEven : RoundingMode<1>;
+def RndNearestZero : RoundingMode<2>;
+def RndNegInf : RoundingMode<3>;
+def RndPosInf : RoundingMode<4>;
+def RndApprox : RoundingMode<5>;*/
+
+
+// Rounding Mode Operand
+def RndMode : Operand<i32> {
+ let PrintMethod = "printRoundingMode";
+}
+
+def RndDefault : PatLeaf<(i32 0)>;
+
+// PTX Predicate operand, default to (0, 0) = (zero-reg, none).
// Leave PrintMethod empty; predicate printing is defined elsewhere.
def pred : PredicateOperand<OtherVT, (ops RegPred, i32imm),
- (ops (i1 zero_reg), (i32 0))>;
+ (ops (i1 zero_reg), (i32 2))>;
+def RndModeOperand : Operand<OtherVT> {
+ let MIOperandInfo = (ops i32imm);
+}
+
+// Instruction Types
let Namespace = "PTX" in {
+
class InstPTX<dag oops, dag iops, string asmstr, list<dag> pattern>
: Instruction {
dag OutOperandList = oops;
diff --git a/lib/Target/PTX/PTXInstrInfo.cpp b/lib/Target/PTX/PTXInstrInfo.cpp
index 425265a..1b947a5 100644
--- a/lib/Target/PTX/PTXInstrInfo.cpp
+++ b/lib/Target/PTX/PTXInstrInfo.cpp
@@ -16,10 +16,11 @@
#include "PTX.h"
#include "PTXInstrInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#define GET_INSTRINFO_CTOR
@@ -47,8 +48,13 @@ void PTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I, DebugLoc DL,
unsigned DstReg, unsigned SrcReg,
bool KillSrc) const {
- for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) {
- if (map[i].cls->contains(DstReg, SrcReg)) {
+
+ const MachineRegisterInfo& MRI = MBB.getParent()->getRegInfo();
+ //assert(MRI.getRegClass(SrcReg) == MRI.getRegClass(DstReg) &&
+ // "Invalid register copy between two register classes");
+
+ for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++i) {
+ if (map[i].cls == MRI.getRegClass(DstReg)) {
const MCInstrDesc &MCID = get(map[i].opcode);
MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).
addReg(SrcReg, getKillRegState(KillSrc));
@@ -161,7 +167,7 @@ DefinesPredicate(MachineInstr *MI,
return false;
Pred.push_back(MO);
- Pred.push_back(MachineOperand::CreateImm(PTX::PRED_NORMAL));
+ Pred.push_back(MachineOperand::CreateImm(PTXPredicate::None));
return true;
}
@@ -277,7 +283,7 @@ InsertBranch(MachineBasicBlock &MBB,
BuildMI(&MBB, DL, get(PTX::BRAdp))
.addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
BuildMI(&MBB, DL, get(PTX::BRAd))
- .addMBB(FBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
+ .addMBB(FBB).addReg(PTX::NoRegister).addImm(PTXPredicate::None);
return 2;
} else if (Cond.size()) {
BuildMI(&MBB, DL, get(PTX::BRAdp))
@@ -285,7 +291,7 @@ InsertBranch(MachineBasicBlock &MBB,
return 1;
} else {
BuildMI(&MBB, DL, get(PTX::BRAd))
- .addMBB(TBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
+ .addMBB(TBB).addReg(PTX::NoRegister).addImm(PTXPredicate::None);
return 1;
}
}
@@ -296,34 +302,7 @@ void PTXInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
unsigned SrcReg, bool isKill, int FrameIdx,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
- MachineInstr& MI = *MII;
- DebugLoc DL = MI.getDebugLoc();
-
- DEBUG(dbgs() << "storeRegToStackSlot: " << MI);
-
- int OpCode;
-
- // Select the appropriate opcode based on the register class
- if (RC == PTX::RegI16RegisterClass) {
- OpCode = PTX::STACKSTOREI16;
- } else if (RC == PTX::RegI32RegisterClass) {
- OpCode = PTX::STACKSTOREI32;
- } else if (RC == PTX::RegI64RegisterClass) {
- OpCode = PTX::STACKSTOREI32;
- } else if (RC == PTX::RegF32RegisterClass) {
- OpCode = PTX::STACKSTOREF32;
- } else if (RC == PTX::RegF64RegisterClass) {
- OpCode = PTX::STACKSTOREF64;
- } else {
- llvm_unreachable("Unknown PTX register class!");
- }
-
- // Build the store instruction (really a mov)
- MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
- MIB.addFrameIndex(FrameIdx);
- MIB.addReg(SrcReg);
-
- AddDefaultPredicate(MIB);
+ assert(false && "storeRegToStackSlot should not be called for PTX");
}
void PTXInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
@@ -331,34 +310,7 @@ void PTXInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
unsigned DestReg, int FrameIdx,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
- MachineInstr& MI = *MII;
- DebugLoc DL = MI.getDebugLoc();
-
- DEBUG(dbgs() << "loadRegToStackSlot: " << MI);
-
- int OpCode;
-
- // Select the appropriate opcode based on the register class
- if (RC == PTX::RegI16RegisterClass) {
- OpCode = PTX::STACKLOADI16;
- } else if (RC == PTX::RegI32RegisterClass) {
- OpCode = PTX::STACKLOADI32;
- } else if (RC == PTX::RegI64RegisterClass) {
- OpCode = PTX::STACKLOADI32;
- } else if (RC == PTX::RegF32RegisterClass) {
- OpCode = PTX::STACKLOADF32;
- } else if (RC == PTX::RegF64RegisterClass) {
- OpCode = PTX::STACKLOADF64;
- } else {
- llvm_unreachable("Unknown PTX register class!");
- }
-
- // Build the load instruction (really a mov)
- MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
- MIB.addReg(DestReg);
- MIB.addFrameIndex(FrameIdx);
-
- AddDefaultPredicate(MIB);
+ assert(false && "loadRegFromStackSlot should not be called for PTX");
}
// static helper routines
@@ -367,7 +319,7 @@ MachineSDNode *PTXInstrInfo::
GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
DebugLoc dl, EVT VT, SDValue Op1) {
SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
- SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
+ SDValue predOp = DAG->getTargetConstant(PTXPredicate::None, MVT::i32);
SDValue ops[] = { Op1, predReg, predOp };
return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
}
@@ -376,7 +328,7 @@ MachineSDNode *PTXInstrInfo::
GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2) {
SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
- SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
+ SDValue predOp = DAG->getTargetConstant(PTXPredicate::None, MVT::i32);
SDValue ops[] = { Op1, Op2, predReg, predOp };
return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
}
@@ -384,7 +336,7 @@ GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
if (MI->findFirstPredOperandIdx() == -1) {
MI->addOperand(MachineOperand::CreateReg(PTX::NoRegister, /*IsDef=*/false));
- MI->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL));
+ MI->addOperand(MachineOperand::CreateImm(PTXPredicate::None));
}
}
diff --git a/lib/Target/PTX/PTXInstrInfo.td b/lib/Target/PTX/PTXInstrInfo.td
index 6bfe906..a3fcea9 100644
--- a/lib/Target/PTX/PTXInstrInfo.td
+++ b/lib/Target/PTX/PTXInstrInfo.td
@@ -21,10 +21,6 @@ include "PTXInstrFormats.td"
// Code Generation Predicates
//===----------------------------------------------------------------------===//
-// Addressing
-def Use32BitAddresses : Predicate<"!getSubtarget().is64Bit()">;
-def Use64BitAddresses : Predicate<"getSubtarget().is64Bit()">;
-
// Shader Model Support
def FDivNeedsRoundingMode : Predicate<"getSubtarget().fdivNeedsRoundingMode()">;
def FDivNoRoundingMode : Predicate<"!getSubtarget().fdivNeedsRoundingMode()">;
@@ -43,130 +39,19 @@ def DoesNotSupportPTX23 : Predicate<"!getSubtarget().supportsPTX23()">;
def SupportsFMA : Predicate<"getSubtarget().supportsFMA()">;
def DoesNotSupportFMA : Predicate<"!getSubtarget().supportsFMA()">;
-//===----------------------------------------------------------------------===//
-// Instruction Pattern Stuff
-//===----------------------------------------------------------------------===//
-def load_global : PatFrag<(ops node:$ptr), (load node:$ptr), [{
- const Value *Src;
- const PointerType *PT;
- if ((Src = cast<LoadSDNode>(N)->getSrcValue()) &&
- (PT = dyn_cast<PointerType>(Src->getType())))
- return PT->getAddressSpace() == PTX::GLOBAL;
- return false;
-}]>;
-
-def load_constant : PatFrag<(ops node:$ptr), (load node:$ptr), [{
- const Value *Src;
- const PointerType *PT;
- if ((Src = cast<LoadSDNode>(N)->getSrcValue()) &&
- (PT = dyn_cast<PointerType>(Src->getType())))
- return PT->getAddressSpace() == PTX::CONSTANT;
- return false;
-}]>;
-
-def load_local : PatFrag<(ops node:$ptr), (load node:$ptr), [{
- const Value *Src;
- const PointerType *PT;
- if ((Src = cast<LoadSDNode>(N)->getSrcValue()) &&
- (PT = dyn_cast<PointerType>(Src->getType())))
- return PT->getAddressSpace() == PTX::LOCAL;
- return false;
-}]>;
-
-def load_parameter : PatFrag<(ops node:$ptr), (load node:$ptr), [{
- const Value *Src;
- const PointerType *PT;
- if ((Src = cast<LoadSDNode>(N)->getSrcValue()) &&
- (PT = dyn_cast<PointerType>(Src->getType())))
- return PT->getAddressSpace() == PTX::PARAMETER;
- return false;
-}]>;
-
-def load_shared : PatFrag<(ops node:$ptr), (load node:$ptr), [{
- const Value *Src;
- const PointerType *PT;
- if ((Src = cast<LoadSDNode>(N)->getSrcValue()) &&
- (PT = dyn_cast<PointerType>(Src->getType())))
- return PT->getAddressSpace() == PTX::SHARED;
- return false;
-}]>;
-
-def store_global
- : PatFrag<(ops node:$d, node:$ptr), (store node:$d, node:$ptr), [{
- const Value *Src;
- const PointerType *PT;
- if ((Src = cast<StoreSDNode>(N)->getSrcValue()) &&
- (PT = dyn_cast<PointerType>(Src->getType())))
- return PT->getAddressSpace() == PTX::GLOBAL;
- return false;
-}]>;
-
-def store_local
- : PatFrag<(ops node:$d, node:$ptr), (store node:$d, node:$ptr), [{
- const Value *Src;
- const PointerType *PT;
- if ((Src = cast<StoreSDNode>(N)->getSrcValue()) &&
- (PT = dyn_cast<PointerType>(Src->getType())))
- return PT->getAddressSpace() == PTX::LOCAL;
- return false;
-}]>;
-
-def store_parameter
- : PatFrag<(ops node:$d, node:$ptr), (store node:$d, node:$ptr), [{
- const Value *Src;
- const PointerType *PT;
- if ((Src = cast<StoreSDNode>(N)->getSrcValue()) &&
- (PT = dyn_cast<PointerType>(Src->getType())))
- return PT->getAddressSpace() == PTX::PARAMETER;
- return false;
-}]>;
-
-def store_shared
- : PatFrag<(ops node:$d, node:$ptr), (store node:$d, node:$ptr), [{
- const Value *Src;
- const PointerType *PT;
- if ((Src = cast<StoreSDNode>(N)->getSrcValue()) &&
- (PT = dyn_cast<PointerType>(Src->getType())))
- return PT->getAddressSpace() == PTX::SHARED;
- return false;
-}]>;
-
-// Addressing modes.
-def ADDRrr32 : ComplexPattern<i32, 2, "SelectADDRrr", [], []>;
-def ADDRrr64 : ComplexPattern<i64, 2, "SelectADDRrr", [], []>;
-def ADDRri32 : ComplexPattern<i32, 2, "SelectADDRri", [], []>;
-def ADDRri64 : ComplexPattern<i64, 2, "SelectADDRri", [], []>;
-def ADDRii32 : ComplexPattern<i32, 2, "SelectADDRii", [], []>;
-def ADDRii64 : ComplexPattern<i64, 2, "SelectADDRii", [], []>;
-
-// Address operands
-def MEMri32 : Operand<i32> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops RegI32, i32imm);
-}
-def MEMri64 : Operand<i64> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops RegI64, i64imm);
-}
-def MEMii32 : Operand<i32> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops i32imm, i32imm);
-}
-def MEMii64 : Operand<i64> {
- let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops i64imm, i64imm);
-}
-// The operand here does not correspond to an actual address, so we
-// can use i32 in 64-bit address modes.
-def MEMpi : Operand<i32> {
- let PrintMethod = "printParamOperand";
- let MIOperandInfo = (ops i32imm);
-}
-def MEMret : Operand<i32> {
- let PrintMethod = "printReturnOperand";
- let MIOperandInfo = (ops i32imm);
-}
+
+// def SDT_PTXCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
+// def SDT_PTXCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+
+// def PTXcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PTXCallSeqStart,
+// [SDNPHasChain, SDNPOutGlue]>;
+// def PTXcallseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PTXCallSeqEnd,
+// [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
+
+def PTXcall : SDNode<"PTXISD::CALL", SDTNone,
+ [SDNPHasChain, SDNPVariadic, SDNPOptInGlue, SDNPOutGlue]>;
+
// Branch & call targets have OtherVT type.
def brtarget : Operand<OtherVT>;
@@ -189,87 +74,73 @@ def PTXret
def PTXcopyaddress
: SDNode<"PTXISD::COPY_ADDRESS", SDTypeProfile<1, 1, []>, []>;
-// Load/store .param space
-def PTXloadparam
- : SDNode<"PTXISD::LOAD_PARAM", SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>,
- [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue]>;
-def PTXstoreparam
- : SDNode<"PTXISD::STORE_PARAM", SDTypeProfile<0, 2, [SDTCisVT<0, i32>]>,
- [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue]>;
+
//===----------------------------------------------------------------------===//
// Instruction Class Templates
//===----------------------------------------------------------------------===//
+// For floating-point instructions, we cannot just embed the pattern into the
+// instruction definition since we need to muck around with the rounding mode,
+// and I do not know how to insert constants into instructions directly from
+// pattern matches.
+
//===- Floating-Point Instructions - 2 Operand Form -----------------------===//
-multiclass PTX_FLOAT_2OP<string opcstr, SDNode opnode> {
+multiclass PTX_FLOAT_2OP<string opcstr> {
def rr32 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a),
- !strconcat(opcstr, ".f32\t$d, $a"),
- [(set RegF32:$d, (opnode RegF32:$a))]>;
+ (ins RndMode:$r, RegF32:$a),
+ !strconcat(opcstr, "$r.f32\t$d, $a"), []>;
def ri32 : InstPTX<(outs RegF32:$d),
- (ins f32imm:$a),
- !strconcat(opcstr, ".f32\t$d, $a"),
- [(set RegF32:$d, (opnode fpimm:$a))]>;
+ (ins RndMode:$r, f32imm:$a),
+ !strconcat(opcstr, "$r.f32\t$d, $a"), []>;
def rr64 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a),
- !strconcat(opcstr, ".f64\t$d, $a"),
- [(set RegF64:$d, (opnode RegF64:$a))]>;
+ (ins RndMode:$r, RegF64:$a),
+ !strconcat(opcstr, "$r.f64\t$d, $a"), []>;
def ri64 : InstPTX<(outs RegF64:$d),
- (ins f64imm:$a),
- !strconcat(opcstr, ".f64\t$d, $a"),
- [(set RegF64:$d, (opnode fpimm:$a))]>;
+ (ins RndMode:$r, f64imm:$a),
+ !strconcat(opcstr, "$r.f64\t$d, $a"), []>;
}
//===- Floating-Point Instructions - 3 Operand Form -----------------------===//
-multiclass PTX_FLOAT_3OP<string opcstr, SDNode opnode> {
+multiclass PTX_FLOAT_3OP<string opcstr> {
def rr32 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a, RegF32:$b),
- !strconcat(opcstr, ".f32\t$d, $a, $b"),
- [(set RegF32:$d, (opnode RegF32:$a, RegF32:$b))]>;
+ (ins RndMode:$r, RegF32:$a, RegF32:$b),
+ !strconcat(opcstr, "$r.f32\t$d, $a, $b"), []>;
def ri32 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a, f32imm:$b),
- !strconcat(opcstr, ".f32\t$d, $a, $b"),
- [(set RegF32:$d, (opnode RegF32:$a, fpimm:$b))]>;
+ (ins RndMode:$r, RegF32:$a, f32imm:$b),
+ !strconcat(opcstr, "$r.f32\t$d, $a, $b"), []>;
def rr64 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a, RegF64:$b),
- !strconcat(opcstr, ".f64\t$d, $a, $b"),
- [(set RegF64:$d, (opnode RegF64:$a, RegF64:$b))]>;
+ (ins RndMode:$r, RegF64:$a, RegF64:$b),
+ !strconcat(opcstr, "$r.f64\t$d, $a, $b"), []>;
def ri64 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a, f64imm:$b),
- !strconcat(opcstr, ".f64\t$d, $a, $b"),
- [(set RegF64:$d, (opnode RegF64:$a, fpimm:$b))]>;
+ (ins RndMode:$r, RegF64:$a, f64imm:$b),
+ !strconcat(opcstr, "$r.f64\t$d, $a, $b"), []>;
}
//===- Floating-Point Instructions - 4 Operand Form -----------------------===//
-multiclass PTX_FLOAT_4OP<string opcstr, SDNode opnode1, SDNode opnode2> {
+multiclass PTX_FLOAT_4OP<string opcstr> {
def rrr32 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a, RegF32:$b, RegF32:$c),
- !strconcat(opcstr, ".f32\t$d, $a, $b, $c"),
- [(set RegF32:$d, (opnode2 (opnode1 RegF32:$a,
- RegF32:$b),
- RegF32:$c))]>;
+ (ins RndMode:$r, RegF32:$a, RegF32:$b, RegF32:$c),
+ !strconcat(opcstr, "$r.f32\t$d, $a, $b, $c"), []>;
def rri32 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a, RegF32:$b, f32imm:$c),
- !strconcat(opcstr, ".f32\t$d, $a, $b, $c"),
- [(set RegF32:$d, (opnode2 (opnode1 RegF32:$a,
- RegF32:$b),
- fpimm:$c))]>;
+ (ins RndMode:$r, RegF32:$a, RegF32:$b, f32imm:$c),
+ !strconcat(opcstr, "$r.f32\t$d, $a, $b, $c"), []>;
+ def rii32 : InstPTX<(outs RegF32:$d),
+ (ins RndMode:$r, RegF32:$a, f32imm:$b, f32imm:$c),
+ !strconcat(opcstr, "$r.f32\t$d, $a, $b, $c"), []>;
def rrr64 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a, RegF64:$b, RegF64:$c),
- !strconcat(opcstr, ".f64\t$d, $a, $b, $c"),
- [(set RegF64:$d, (opnode2 (opnode1 RegF64:$a,
- RegF64:$b),
- RegF64:$c))]>;
+ (ins RndMode:$r, RegF64:$a, RegF64:$b, RegF64:$c),
+ !strconcat(opcstr, "$r.f64\t$d, $a, $b, $c"), []>;
def rri64 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a, RegF64:$b, f64imm:$c),
- !strconcat(opcstr, ".f64\t$d, $a, $b, $c"),
- [(set RegF64:$d, (opnode2 (opnode1 RegF64:$a,
- RegF64:$b),
- fpimm:$c))]>;
+ (ins RndMode:$r, RegF64:$a, RegF64:$b, f64imm:$c),
+ !strconcat(opcstr, "$r.f64\t$d, $a, $b, $c"), []>;
+ def rii64 : InstPTX<(outs RegF64:$d),
+ (ins RndMode:$r, RegF64:$a, f64imm:$b, f64imm:$c),
+ !strconcat(opcstr, "$r.f64\t$d, $a, $b, $c"), []>;
}
-multiclass INT3<string opcstr, SDNode opnode> {
+//===- Integer Instructions - 3 Operand Form ------------------------------===//
+multiclass PTX_INT3<string opcstr, SDNode opnode> {
def rr16 : InstPTX<(outs RegI16:$d),
(ins RegI16:$a, RegI16:$b),
!strconcat(opcstr, ".u16\t$d, $a, $b"),
@@ -296,6 +167,35 @@ multiclass INT3<string opcstr, SDNode opnode> {
[(set RegI64:$d, (opnode RegI64:$a, imm:$b))]>;
}
+//===- Integer Instructions - 3 Operand Form (Signed) ---------------------===//
+multiclass PTX_INT3_SIGNED<string opcstr, SDNode opnode> {
+ def rr16 : InstPTX<(outs RegI16:$d),
+ (ins RegI16:$a, RegI16:$b),
+ !strconcat(opcstr, ".s16\t$d, $a, $b"),
+ [(set RegI16:$d, (opnode RegI16:$a, RegI16:$b))]>;
+ def ri16 : InstPTX<(outs RegI16:$d),
+ (ins RegI16:$a, i16imm:$b),
+ !strconcat(opcstr, ".s16\t$d, $a, $b"),
+ [(set RegI16:$d, (opnode RegI16:$a, imm:$b))]>;
+ def rr32 : InstPTX<(outs RegI32:$d),
+ (ins RegI32:$a, RegI32:$b),
+ !strconcat(opcstr, ".s32\t$d, $a, $b"),
+ [(set RegI32:$d, (opnode RegI32:$a, RegI32:$b))]>;
+ def ri32 : InstPTX<(outs RegI32:$d),
+ (ins RegI32:$a, i32imm:$b),
+ !strconcat(opcstr, ".s32\t$d, $a, $b"),
+ [(set RegI32:$d, (opnode RegI32:$a, imm:$b))]>;
+ def rr64 : InstPTX<(outs RegI64:$d),
+ (ins RegI64:$a, RegI64:$b),
+ !strconcat(opcstr, ".s64\t$d, $a, $b"),
+ [(set RegI64:$d, (opnode RegI64:$a, RegI64:$b))]>;
+ def ri64 : InstPTX<(outs RegI64:$d),
+ (ins RegI64:$a, i64imm:$b),
+ !strconcat(opcstr, ".s64\t$d, $a, $b"),
+ [(set RegI64:$d, (opnode RegI64:$a, imm:$b))]>;
+}
+
+//===- Bitwise Logic Instructions - 3 Operand Form ------------------------===//
multiclass PTX_LOGIC<string opcstr, SDNode opnode> {
def ripreds : InstPTX<(outs RegPred:$d),
(ins RegPred:$a, i1imm:$b),
@@ -331,7 +231,8 @@ multiclass PTX_LOGIC<string opcstr, SDNode opnode> {
[(set RegI64:$d, (opnode RegI64:$a, imm:$b))]>;
}
-multiclass INT3ntnc<string opcstr, SDNode opnode> {
+//===- Integer Shift Instructions - 3 Operand Form ------------------------===//
+multiclass PTX_INT3ntnc<string opcstr, SDNode opnode> {
def rr16 : InstPTX<(outs RegI16:$d),
(ins RegI16:$a, RegI16:$b),
!strconcat(opcstr, "16\t$d, $a, $b"),
@@ -370,6 +271,7 @@ multiclass INT3ntnc<string opcstr, SDNode opnode> {
[(set RegI64:$d, (opnode imm:$a, RegI64:$b))]>;
}
+//===- Set Predicate Instructions (Int) - 3/4 Operand Forms ---------------===//
multiclass PTX_SETP_I<RegisterClass RC, string regclsname, Operand immcls,
CondCode cmp, string cmpstr> {
// TODO support 5-operand format: p|q, a, b, c
@@ -385,56 +287,77 @@ multiclass PTX_SETP_I<RegisterClass RC, string regclsname, Operand immcls,
def rr_and_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, $c"),
+ !strconcat("setp.", cmpstr, ".and.", regclsname,
+ "\t$p, $a, $b, $c"),
[(set RegPred:$p, (and (setcc RC:$a, RC:$b, cmp), RegPred:$c))]>;
def ri_and_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, $c"),
- [(set RegPred:$p, (and (setcc RC:$a, imm:$b, cmp), RegPred:$c))]>;
+ !strconcat("setp.", cmpstr, ".and.", regclsname,
+ "\t$p, $a, $b, $c"),
+ [(set RegPred:$p, (and (setcc RC:$a, imm:$b, cmp),
+ RegPred:$c))]>;
def rr_or_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, $c"),
+ !strconcat("setp.", cmpstr, ".or.", regclsname,
+ "\t$p, $a, $b, $c"),
[(set RegPred:$p, (or (setcc RC:$a, RC:$b, cmp), RegPred:$c))]>;
def ri_or_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, $c"),
+ !strconcat("setp.", cmpstr, ".or.", regclsname,
+ "\t$p, $a, $b, $c"),
[(set RegPred:$p, (or (setcc RC:$a, imm:$b, cmp), RegPred:$c))]>;
def rr_xor_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, $c"),
+ !strconcat("setp.", cmpstr, ".xor.", regclsname,
+ "\t$p, $a, $b, $c"),
[(set RegPred:$p, (xor (setcc RC:$a, RC:$b, cmp), RegPred:$c))]>;
def ri_xor_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, $c"),
- [(set RegPred:$p, (xor (setcc RC:$a, imm:$b, cmp), RegPred:$c))]>;
+ !strconcat("setp.", cmpstr, ".xor.", regclsname,
+ "\t$p, $a, $b, $c"),
+ [(set RegPred:$p, (xor (setcc RC:$a, imm:$b, cmp),
+ RegPred:$c))]>;
def rr_and_not_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (and (setcc RC:$a, RC:$b, cmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, ".and.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (and (setcc RC:$a, RC:$b, cmp),
+ (not RegPred:$c)))]>;
def ri_and_not_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (and (setcc RC:$a, imm:$b, cmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, ".and.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (and (setcc RC:$a, imm:$b, cmp),
+ (not RegPred:$c)))]>;
def rr_or_not_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (or (setcc RC:$a, RC:$b, cmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, ".or.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (or (setcc RC:$a, RC:$b, cmp),
+ (not RegPred:$c)))]>;
def ri_or_not_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (or (setcc RC:$a, imm:$b, cmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, ".or.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (or (setcc RC:$a, imm:$b, cmp),
+ (not RegPred:$c)))]>;
def rr_xor_not_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, cmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, ".xor.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, cmp),
+ (not RegPred:$c)))]>;
def ri_xor_not_r
: InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (xor (setcc RC:$a, imm:$b, cmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, ".xor.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (xor (setcc RC:$a, imm:$b, cmp),
+ (not RegPred:$c)))]>;
}
-multiclass PTX_SETP_FP<RegisterClass RC, string regclsname,
+//===- Set Predicate Instructions (FP) - 3/4 Operand Form -----------------===//
+multiclass PTX_SETP_FP<RegisterClass RC, string regclsname, Operand immcls,
CondCode ucmp, CondCode ocmp, string cmpstr> {
// TODO support 5-operand format: p|q, a, b, c
@@ -447,137 +370,110 @@ multiclass PTX_SETP_FP<RegisterClass RC, string regclsname,
!strconcat("setp.", cmpstr, ".", regclsname, "\t$p, $a, $b"),
[(set RegPred:$p, (setcc RC:$a, RC:$b, ocmp))]>;
+ def ri_u
+ : InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b),
+ !strconcat("setp.", cmpstr, "u.", regclsname, "\t$p, $a, $b"),
+ [(set RegPred:$p, (setcc RC:$a, fpimm:$b, ucmp))]>;
+ def ri_o
+ : InstPTX<(outs RegPred:$p), (ins RC:$a, immcls:$b),
+ !strconcat("setp.", cmpstr, ".", regclsname, "\t$p, $a, $b"),
+ [(set RegPred:$p, (setcc RC:$a, fpimm:$b, ocmp))]>;
+
def rr_and_r_u
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, "u.and.", regclsname, "\t$p, $a, $b, $c"),
- [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ucmp), RegPred:$c))]>;
+ !strconcat("setp.", cmpstr, "u.and.", regclsname,
+ "\t$p, $a, $b, $c"),
+ [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ucmp),
+ RegPred:$c))]>;
def rr_and_r_o
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, $c"),
- [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ocmp), RegPred:$c))]>;
+ !strconcat("setp.", cmpstr, ".and.", regclsname,
+ "\t$p, $a, $b, $c"),
+ [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ocmp),
+ RegPred:$c))]>;
def rr_or_r_u
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, "u.or.", regclsname, "\t$p, $a, $b, $c"),
+ !strconcat("setp.", cmpstr, "u.or.", regclsname,
+ "\t$p, $a, $b, $c"),
[(set RegPred:$p, (or (setcc RC:$a, RC:$b, ucmp), RegPred:$c))]>;
def rr_or_r_o
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, $c"),
+ !strconcat("setp.", cmpstr, ".or.", regclsname,
+ "\t$p, $a, $b, $c"),
[(set RegPred:$p, (or (setcc RC:$a, RC:$b, ocmp), RegPred:$c))]>;
def rr_xor_r_u
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, "u.xor.", regclsname, "\t$p, $a, $b, $c"),
- [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ucmp), RegPred:$c))]>;
+ !strconcat("setp.", cmpstr, "u.xor.", regclsname,
+ "\t$p, $a, $b, $c"),
+ [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ucmp),
+ RegPred:$c))]>;
def rr_xor_r_o
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, $c"),
- [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ocmp), RegPred:$c))]>;
+ !strconcat("setp.", cmpstr, ".xor.", regclsname,
+ "\t$p, $a, $b, $c"),
+ [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ocmp),
+ RegPred:$c))]>;
def rr_and_not_r_u
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, "u.and.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ucmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, "u.and.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ucmp),
+ (not RegPred:$c)))]>;
def rr_and_not_r_o
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".and.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ocmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, ".and.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (and (setcc RC:$a, RC:$b, ocmp),
+ (not RegPred:$c)))]>;
def rr_or_not_r_u
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, "u.or.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (or (setcc RC:$a, RC:$b, ucmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, "u.or.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (or (setcc RC:$a, RC:$b, ucmp),
+ (not RegPred:$c)))]>;
def rr_or_not_r_o
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".or.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (or (setcc RC:$a, RC:$b, ocmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, ".or.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (or (setcc RC:$a, RC:$b, ocmp),
+ (not RegPred:$c)))]>;
def rr_xor_not_r_u
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, "u.xor.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ucmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, "u.xor.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ucmp),
+ (not RegPred:$c)))]>;
def rr_xor_not_r_o
: InstPTX<(outs RegPred:$p), (ins RC:$a, RC:$b, RegPred:$c),
- !strconcat("setp.", cmpstr, ".xor.", regclsname, "\t$p, $a, $b, !$c"),
- [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ocmp), (not RegPred:$c)))]>;
+ !strconcat("setp.", cmpstr, ".xor.", regclsname,
+ "\t$p, $a, $b, !$c"),
+ [(set RegPred:$p, (xor (setcc RC:$a, RC:$b, ocmp),
+ (not RegPred:$c)))]>;
}
-multiclass PTX_SELP<RegisterClass RC, string regclsname> {
+//===- Select Predicate Instructions - 4 Operand Form ---------------------===//
+multiclass PTX_SELP<RegisterClass RC, string regclsname, Operand immcls,
+ SDNode immnode> {
def rr
: InstPTX<(outs RC:$r), (ins RegPred:$a, RC:$b, RC:$c),
!strconcat("selp.", regclsname, "\t$r, $b, $c, $a"),
[(set RC:$r, (select RegPred:$a, RC:$b, RC:$c))]>;
+ def ri
+ : InstPTX<(outs RC:$r), (ins RegPred:$a, RC:$b, immcls:$c),
+ !strconcat("selp.", regclsname, "\t$r, $b, $c, $a"),
+ [(set RC:$r, (select RegPred:$a, RC:$b, immnode:$c))]>;
+ def ii
+ : InstPTX<(outs RC:$r), (ins RegPred:$a, immcls:$b, immcls:$c),
+ !strconcat("selp.", regclsname, "\t$r, $b, $c, $a"),
+ [(set RC:$r, (select RegPred:$a, immnode:$b, immnode:$c))]>;
}
-multiclass PTX_LD<string opstr, string typestr, RegisterClass RC, PatFrag pat_load> {
- def rr32 : InstPTX<(outs RC:$d),
- (ins MEMri32:$a),
- !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
- [(set RC:$d, (pat_load ADDRrr32:$a))]>, Requires<[Use32BitAddresses]>;
- def rr64 : InstPTX<(outs RC:$d),
- (ins MEMri64:$a),
- !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
- [(set RC:$d, (pat_load ADDRrr64:$a))]>, Requires<[Use64BitAddresses]>;
- def ri32 : InstPTX<(outs RC:$d),
- (ins MEMri32:$a),
- !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
- [(set RC:$d, (pat_load ADDRri32:$a))]>, Requires<[Use32BitAddresses]>;
- def ri64 : InstPTX<(outs RC:$d),
- (ins MEMri64:$a),
- !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
- [(set RC:$d, (pat_load ADDRri64:$a))]>, Requires<[Use64BitAddresses]>;
- def ii32 : InstPTX<(outs RC:$d),
- (ins MEMii32:$a),
- !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
- [(set RC:$d, (pat_load ADDRii32:$a))]>, Requires<[Use32BitAddresses]>;
- def ii64 : InstPTX<(outs RC:$d),
- (ins MEMii64:$a),
- !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
- [(set RC:$d, (pat_load ADDRii64:$a))]>, Requires<[Use64BitAddresses]>;
-}
-
-multiclass PTX_LD_ALL<string opstr, PatFrag pat_load> {
- defm u16 : PTX_LD<opstr, ".u16", RegI16, pat_load>;
- defm u32 : PTX_LD<opstr, ".u32", RegI32, pat_load>;
- defm u64 : PTX_LD<opstr, ".u64", RegI64, pat_load>;
- defm f32 : PTX_LD<opstr, ".f32", RegF32, pat_load>;
- defm f64 : PTX_LD<opstr, ".f64", RegF64, pat_load>;
-}
-
-multiclass PTX_ST<string opstr, string typestr, RegisterClass RC, PatFrag pat_store> {
- def rr32 : InstPTX<(outs),
- (ins RC:$d, MEMri32:$a),
- !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
- [(pat_store RC:$d, ADDRrr32:$a)]>, Requires<[Use32BitAddresses]>;
- def rr64 : InstPTX<(outs),
- (ins RC:$d, MEMri64:$a),
- !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
- [(pat_store RC:$d, ADDRrr64:$a)]>, Requires<[Use64BitAddresses]>;
- def ri32 : InstPTX<(outs),
- (ins RC:$d, MEMri32:$a),
- !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
- [(pat_store RC:$d, ADDRri32:$a)]>, Requires<[Use32BitAddresses]>;
- def ri64 : InstPTX<(outs),
- (ins RC:$d, MEMri64:$a),
- !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
- [(pat_store RC:$d, ADDRri64:$a)]>, Requires<[Use64BitAddresses]>;
- def ii32 : InstPTX<(outs),
- (ins RC:$d, MEMii32:$a),
- !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
- [(pat_store RC:$d, ADDRii32:$a)]>, Requires<[Use32BitAddresses]>;
- def ii64 : InstPTX<(outs),
- (ins RC:$d, MEMii64:$a),
- !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
- [(pat_store RC:$d, ADDRii64:$a)]>, Requires<[Use64BitAddresses]>;
-}
-multiclass PTX_ST_ALL<string opstr, PatFrag pat_store> {
- defm u16 : PTX_ST<opstr, ".u16", RegI16, pat_store>;
- defm u32 : PTX_ST<opstr, ".u32", RegI32, pat_store>;
- defm u64 : PTX_ST<opstr, ".u64", RegI64, pat_store>;
- defm f32 : PTX_ST<opstr, ".f32", RegF32, pat_store>;
- defm f64 : PTX_ST<opstr, ".f64", RegF64, pat_store>;
-}
//===----------------------------------------------------------------------===//
// Instructions
@@ -585,118 +481,61 @@ multiclass PTX_ST_ALL<string opstr, PatFrag pat_store> {
///===- Integer Arithmetic Instructions -----------------------------------===//
-defm ADD : INT3<"add", add>;
-defm SUB : INT3<"sub", sub>;
-defm MUL : INT3<"mul.lo", mul>; // FIXME: Allow 32x32 -> 64 multiplies
-defm DIV : INT3<"div", udiv>;
-defm REM : INT3<"rem", urem>;
+defm ADD : PTX_INT3<"add", add>;
+defm SUB : PTX_INT3<"sub", sub>;
+defm MUL : PTX_INT3<"mul.lo", mul>; // FIXME: Allow 32x32 -> 64 multiplies
+defm DIV : PTX_INT3<"div", udiv>;
+defm SDIV : PTX_INT3_SIGNED<"div", sdiv>;
+defm REM : PTX_INT3<"rem", urem>;
///===- Floating-Point Arithmetic Instructions ----------------------------===//
-// Standard Unary Operations
-defm FNEG : PTX_FLOAT_2OP<"neg", fneg>;
+// FNEG
+defm FNEG : PTX_FLOAT_2OP<"neg">;
// Standard Binary Operations
-defm FADD : PTX_FLOAT_3OP<"add.rn", fadd>;
-defm FSUB : PTX_FLOAT_3OP<"sub.rn", fsub>;
-defm FMUL : PTX_FLOAT_3OP<"mul.rn", fmul>;
-
-// For floating-point division:
-// SM_13+ defaults to .rn for f32 and f64,
-// SM10 must *not* provide a rounding
-
-// TODO:
-// - Allow user selection of rounding modes for fdiv
-// - Add support for -prec-div=false (.approx)
-
-def FDIVrr32SM13 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a, RegF32:$b),
- "div.rn.f32\t$d, $a, $b",
- [(set RegF32:$d, (fdiv RegF32:$a, RegF32:$b))]>,
- Requires<[FDivNeedsRoundingMode]>;
-def FDIVri32SM13 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a, f32imm:$b),
- "div.rn.f32\t$d, $a, $b",
- [(set RegF32:$d, (fdiv RegF32:$a, fpimm:$b))]>,
- Requires<[FDivNeedsRoundingMode]>;
-def FDIVrr32SM10 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a, RegF32:$b),
- "div.f32\t$d, $a, $b",
- [(set RegF32:$d, (fdiv RegF32:$a, RegF32:$b))]>,
- Requires<[FDivNoRoundingMode]>;
-def FDIVri32SM10 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a, f32imm:$b),
- "div.f32\t$d, $a, $b",
- [(set RegF32:$d, (fdiv RegF32:$a, fpimm:$b))]>,
- Requires<[FDivNoRoundingMode]>;
-
-def FDIVrr64SM13 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a, RegF64:$b),
- "div.rn.f64\t$d, $a, $b",
- [(set RegF64:$d, (fdiv RegF64:$a, RegF64:$b))]>,
- Requires<[FDivNeedsRoundingMode]>;
-def FDIVri64SM13 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a, f64imm:$b),
- "div.rn.f64\t$d, $a, $b",
- [(set RegF64:$d, (fdiv RegF64:$a, fpimm:$b))]>,
- Requires<[FDivNeedsRoundingMode]>;
-def FDIVrr64SM10 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a, RegF64:$b),
- "div.f64\t$d, $a, $b",
- [(set RegF64:$d, (fdiv RegF64:$a, RegF64:$b))]>,
- Requires<[FDivNoRoundingMode]>;
-def FDIVri64SM10 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a, f64imm:$b),
- "div.f64\t$d, $a, $b",
- [(set RegF64:$d, (fdiv RegF64:$a, fpimm:$b))]>,
- Requires<[FDivNoRoundingMode]>;
-
-
+defm FADD : PTX_FLOAT_3OP<"add">;
+defm FSUB : PTX_FLOAT_3OP<"sub">;
+defm FMUL : PTX_FLOAT_3OP<"mul">;
+defm FDIV : PTX_FLOAT_3OP<"div">;
// Multi-operation hybrid instructions
+defm FMAD : PTX_FLOAT_4OP<"mad">, Requires<[SupportsFMA]>;
-// The selection of mad/fma is tricky. In some cases, they are the *same*
-// instruction, but in other cases we may prefer one or the other. Also,
-// different PTX versions differ on whether rounding mode flags are required.
-// In the short term, mad is supported on all PTX versions and we use a
-// default rounding mode no matter what shader model or PTX version.
-// TODO: Allow the rounding mode to be selectable through llc.
-defm FMADSM13 : PTX_FLOAT_4OP<"mad.rn", fmul, fadd>,
- Requires<[FMadNeedsRoundingMode, SupportsFMA]>;
-defm FMAD : PTX_FLOAT_4OP<"mad", fmul, fadd>,
- Requires<[FMadNoRoundingMode, SupportsFMA]>;
///===- Floating-Point Intrinsic Instructions -----------------------------===//
-def FSQRT32 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a),
- "sqrt.rn.f32\t$d, $a",
- [(set RegF32:$d, (fsqrt RegF32:$a))]>;
-
-def FSQRT64 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a),
- "sqrt.rn.f64\t$d, $a",
- [(set RegF64:$d, (fsqrt RegF64:$a))]>;
-
-def FSIN32 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a),
- "sin.approx.f32\t$d, $a",
- [(set RegF32:$d, (fsin RegF32:$a))]>;
+// SQRT
+def FSQRTrr32 : InstPTX<(outs RegF32:$d), (ins RndMode:$r, RegF32:$a),
+ "sqrt$r.f32\t$d, $a", []>;
+def FSQRTri32 : InstPTX<(outs RegF32:$d), (ins RndMode:$r, f32imm:$a),
+ "sqrt$r.f32\t$d, $a", []>;
+def FSQRTrr64 : InstPTX<(outs RegF64:$d), (ins RndMode:$r, RegF64:$a),
+ "sqrt$r.f64\t$d, $a", []>;
+def FSQRTri64 : InstPTX<(outs RegF64:$d), (ins RndMode:$r, f64imm:$a),
+ "sqrt$r.f64\t$d, $a", []>;
+
+// SIN
+def FSINrr32 : InstPTX<(outs RegF32:$d), (ins RndMode:$r, RegF32:$a),
+ "sin$r.f32\t$d, $a", []>;
+def FSINri32 : InstPTX<(outs RegF32:$d), (ins RndMode:$r, f32imm:$a),
+ "sin$r.f32\t$d, $a", []>;
+def FSINrr64 : InstPTX<(outs RegF64:$d), (ins RndMode:$r, RegF64:$a),
+ "sin$r.f64\t$d, $a", []>;
+def FSINri64 : InstPTX<(outs RegF64:$d), (ins RndMode:$r, f64imm:$a),
+ "sin$r.f64\t$d, $a", []>;
+
+// COS
+def FCOSrr32 : InstPTX<(outs RegF32:$d), (ins RndMode:$r, RegF32:$a),
+ "cos$r.f32\t$d, $a", []>;
+def FCOSri32 : InstPTX<(outs RegF32:$d), (ins RndMode:$r, f32imm:$a),
+ "cos$r.f32\t$d, $a", []>;
+def FCOSrr64 : InstPTX<(outs RegF64:$d), (ins RndMode:$r, RegF64:$a),
+ "cos$r.f64\t$d, $a", []>;
+def FCOSri64 : InstPTX<(outs RegF64:$d), (ins RndMode:$r, f64imm:$a),
+ "cos$r.f64\t$d, $a", []>;
-def FSIN64 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a),
- "sin.approx.f64\t$d, $a",
- [(set RegF64:$d, (fsin RegF64:$a))]>;
-def FCOS32 : InstPTX<(outs RegF32:$d),
- (ins RegF32:$a),
- "cos.approx.f32\t$d, $a",
- [(set RegF32:$d, (fcos RegF32:$a))]>;
-
-def FCOS64 : InstPTX<(outs RegF64:$d),
- (ins RegF64:$a),
- "cos.approx.f64\t$d, $a",
- [(set RegF64:$d, (fcos RegF64:$a))]>;
///===- Comparison and Selection Instructions -----------------------------===//
@@ -744,35 +583,35 @@ defm SETPGEs64 : PTX_SETP_I<RegI64, "s64", i64imm, SETGE, "ge">;
// Compare f32
-defm SETPEQf32 : PTX_SETP_FP<RegF32, "f32", SETUEQ, SETOEQ, "eq">;
-defm SETPNEf32 : PTX_SETP_FP<RegF32, "f32", SETUNE, SETONE, "ne">;
-defm SETPLTf32 : PTX_SETP_FP<RegF32, "f32", SETULT, SETOLT, "lt">;
-defm SETPLEf32 : PTX_SETP_FP<RegF32, "f32", SETULE, SETOLE, "le">;
-defm SETPGTf32 : PTX_SETP_FP<RegF32, "f32", SETUGT, SETOGT, "gt">;
-defm SETPGEf32 : PTX_SETP_FP<RegF32, "f32", SETUGE, SETOGE, "ge">;
+defm SETPEQf32 : PTX_SETP_FP<RegF32, "f32", f32imm, SETUEQ, SETOEQ, "eq">;
+defm SETPNEf32 : PTX_SETP_FP<RegF32, "f32", f32imm, SETUNE, SETONE, "ne">;
+defm SETPLTf32 : PTX_SETP_FP<RegF32, "f32", f32imm, SETULT, SETOLT, "lt">;
+defm SETPLEf32 : PTX_SETP_FP<RegF32, "f32", f32imm, SETULE, SETOLE, "le">;
+defm SETPGTf32 : PTX_SETP_FP<RegF32, "f32", f32imm, SETUGT, SETOGT, "gt">;
+defm SETPGEf32 : PTX_SETP_FP<RegF32, "f32", f32imm, SETUGE, SETOGE, "ge">;
// Compare f64
-defm SETPEQf64 : PTX_SETP_FP<RegF64, "f64", SETUEQ, SETOEQ, "eq">;
-defm SETPNEf64 : PTX_SETP_FP<RegF64, "f64", SETUNE, SETONE, "ne">;
-defm SETPLTf64 : PTX_SETP_FP<RegF64, "f64", SETULT, SETOLT, "lt">;
-defm SETPLEf64 : PTX_SETP_FP<RegF64, "f64", SETULE, SETOLE, "le">;
-defm SETPGTf64 : PTX_SETP_FP<RegF64, "f64", SETUGT, SETOGT, "gt">;
-defm SETPGEf64 : PTX_SETP_FP<RegF64, "f64", SETUGE, SETOGE, "ge">;
+defm SETPEQf64 : PTX_SETP_FP<RegF64, "f64", f64imm, SETUEQ, SETOEQ, "eq">;
+defm SETPNEf64 : PTX_SETP_FP<RegF64, "f64", f64imm, SETUNE, SETONE, "ne">;
+defm SETPLTf64 : PTX_SETP_FP<RegF64, "f64", f64imm, SETULT, SETOLT, "lt">;
+defm SETPLEf64 : PTX_SETP_FP<RegF64, "f64", f64imm, SETULE, SETOLE, "le">;
+defm SETPGTf64 : PTX_SETP_FP<RegF64, "f64", f64imm, SETUGT, SETOGT, "gt">;
+defm SETPGEf64 : PTX_SETP_FP<RegF64, "f64", f64imm, SETUGE, SETOGE, "ge">;
// .selp
-defm PTX_SELPu16 : PTX_SELP<RegI16, "u16">;
-defm PTX_SELPu32 : PTX_SELP<RegI32, "u32">;
-defm PTX_SELPu64 : PTX_SELP<RegI64, "u64">;
-defm PTX_SELPf32 : PTX_SELP<RegF32, "f32">;
-defm PTX_SELPf64 : PTX_SELP<RegF64, "f64">;
+defm SELPi16 : PTX_SELP<RegI16, "u16", i16imm, imm>;
+defm SELPi32 : PTX_SELP<RegI32, "u32", i32imm, imm>;
+defm SELPi64 : PTX_SELP<RegI64, "u64", i64imm, imm>;
+defm SELPf32 : PTX_SELP<RegF32, "f32", f32imm, fpimm>;
+defm SELPf64 : PTX_SELP<RegF64, "f64", f64imm, fpimm>;
///===- Logic and Shift Instructions --------------------------------------===//
-defm SHL : INT3ntnc<"shl.b", PTXshl>;
-defm SRL : INT3ntnc<"shr.u", PTXsrl>;
-defm SRA : INT3ntnc<"shr.s", PTXsra>;
+defm SHL : PTX_INT3ntnc<"shl.b", PTXshl>;
+defm SRL : PTX_INT3ntnc<"shr.u", PTXsrl>;
+defm SRA : PTX_INT3ntnc<"shr.s", PTXsra>;
defm AND : PTX_LOGIC<"and", and>;
defm OR : PTX_LOGIC<"or", or>;
@@ -780,6 +619,24 @@ defm XOR : PTX_LOGIC<"xor", xor>;
///===- Data Movement and Conversion Instructions -------------------------===//
+// any_extend
+// Implement the anyext instruction in terms of the PTX cvt instructions.
+//def : Pat<(i32 (anyext RegI16:$a)), (CVT_u32_u16 RegI16:$a)>;
+//def : Pat<(i64 (anyext RegI16:$a)), (CVT_u64_u16 RegI16:$a)>;
+//def : Pat<(i64 (anyext RegI32:$a)), (CVT_u64_u32 RegI32:$a)>;
+
+// bitconvert
+// These instructions implement the bit-wise conversion between integer and
+// floating-point types.
+def MOVi32f32
+ : InstPTX<(outs RegI32:$d), (ins RegF32:$a), "mov.b32\t$d, $a", []>;
+def MOVf32i32
+ : InstPTX<(outs RegF32:$d), (ins RegI32:$a), "mov.b32\t$d, $a", []>;
+def MOVi64f64
+ : InstPTX<(outs RegI64:$d), (ins RegF64:$a), "mov.b64\t$d, $a", []>;
+def MOVf64i64
+ : InstPTX<(outs RegF64:$d), (ins RegI64:$a), "mov.b64\t$d, $a", []>;
+
let neverHasSideEffects = 1 in {
def MOVPREDrr
: InstPTX<(outs RegPred:$d), (ins RegPred:$a), "mov.pred\t$d, $a", []>;
@@ -825,278 +682,332 @@ let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
[(set RegI64:$d, (PTXcopyaddress tglobaladdr:$a))]>;
}
-// Loads
-defm LDg : PTX_LD_ALL<"ld.global", load_global>;
-defm LDc : PTX_LD_ALL<"ld.const", load_constant>;
-defm LDl : PTX_LD_ALL<"ld.local", load_local>;
-defm LDs : PTX_LD_ALL<"ld.shared", load_shared>;
+// PTX cvt instructions
+// Note all of these may actually be used, we just define all possible patterns
+// here (that make sense).
+// FIXME: Can we collapse this somehow into a multiclass def?
+
+// To i16
+def CVTu16u32
+ : InstPTX<(outs RegI16:$d), (ins RegI32:$a), "cvt.u16.u32\t$d, $a", []>;
+def CVTu16u64
+ : InstPTX<(outs RegI16:$d), (ins RegI64:$a), "cvt.u16.u64\t$d, $a", []>;
+def CVTu16f32
+ : InstPTX<(outs RegI16:$d), (ins RndMode:$r, RegF32:$a),
+ "cvt$r.u16.f32\t$d, $a", []>;
+def CVTs16f32
+ : InstPTX<(outs RegI16:$d), (ins RndMode:$r, RegF32:$a),
+ "cvt$r.s16.f32\t$d, $a", []>;
+def CVTu16f64
+ : InstPTX<(outs RegI16:$d), (ins RndMode:$r, RegF64:$a),
+ "cvt$r.u16.f64\t$d, $a", []>;
+def CVTs16f64
+ : InstPTX<(outs RegI16:$d), (ins RndMode:$r, RegF64:$a),
+ "cvt$r.s16.f64\t$d, $a", []>;
+
+// To i32
+def CVTu32u16
+ : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.u16\t$d, $a", []>;
+def CVTs32s16
+ : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.s32.s16\t$d, $a", []>;
+def CVTu32u64
+ : InstPTX<(outs RegI32:$d), (ins RegI64:$a), "cvt.u32.u64\t$d, $a", []>;
+def CVTu32f32
+ : InstPTX<(outs RegI32:$d), (ins RndMode:$r, RegF32:$a),
+ "cvt$r.u32.f32\t$d, $a", []>;
+def CVTs32f32
+ : InstPTX<(outs RegI32:$d), (ins RndMode:$r, RegF32:$a),
+ "cvt$r.s32.f32\t$d, $a", []>;
+def CVTu32f64
+ : InstPTX<(outs RegI32:$d), (ins RndMode:$r, RegF64:$a),
+ "cvt$r.u32.f64\t$d, $a", []>;
+def CVTs32f64
+ : InstPTX<(outs RegI32:$d), (ins RndMode:$r, RegF64:$a),
+ "cvt$r.s32.f64\t$d, $a", []>;
+
+// To i64
+def CVTu64u16
+ : InstPTX<(outs RegI64:$d), (ins RegI16:$a), "cvt.u64.u16\t$d, $a", []>;
+def CVTs64s16
+ : InstPTX<(outs RegI64:$d), (ins RegI16:$a), "cvt.s64.s16\t$d, $a", []>;
+def CVTu64u32
+ : InstPTX<(outs RegI64:$d), (ins RegI32:$a), "cvt.u64.u32\t$d, $a", []>;
+def CVTs64s32
+ : InstPTX<(outs RegI64:$d), (ins RegI32:$a), "cvt.s64.s32\t$d, $a", []>;
+def CVTu64f32
+ : InstPTX<(outs RegI64:$d), (ins RndMode:$r, RegF32:$a),
+ "cvt$r.u64.f32\t$d, $a", []>;
+def CVTs64f32
+ : InstPTX<(outs RegI64:$d), (ins RndMode:$r, RegF32:$a),
+ "cvt$r.s64.f32\t$d, $a", []>;
+def CVTu64f64
+ : InstPTX<(outs RegI64:$d), (ins RndMode:$r, RegF64:$a),
+ "cvt$r.u64.f64\t$d, $a", []>;
+def CVTs64f64
+ : InstPTX<(outs RegI64:$d), (ins RndMode:$r, RegF64:$a),
+ "cvt$r.s64.f64\t$d, $a", []>;
+
+// To f32
+def CVTf32u16
+ : InstPTX<(outs RegF32:$d), (ins RndMode:$r, RegI16:$a),
+ "cvt$r.f32.u16\t$d, $a", []>;
+def CVTf32s16
+ : InstPTX<(outs RegF32:$d), (ins RndMode:$r, RegI16:$a),
+ "cvt$r.f32.s16\t$d, $a", []>;
+def CVTf32u32
+ : InstPTX<(outs RegF32:$d), (ins RndMode:$r, RegI32:$a),
+ "cvt$r.f32.u32\t$d, $a", []>;
+def CVTf32s32
+ : InstPTX<(outs RegF32:$d), (ins RndMode:$r, RegI32:$a),
+ "cvt$r.f32.s32\t$d, $a", []>;
+def CVTf32u64
+ : InstPTX<(outs RegF32:$d), (ins RndMode:$r, RegI64:$a),
+ "cvt$r.f32.u64\t$d, $a", []>;
+def CVTf32s64
+ : InstPTX<(outs RegF32:$d), (ins RndMode:$r, RegI64:$a),
+ "cvt$r.f32.s64\t$d, $a", []>;
+def CVTf32f64
+ : InstPTX<(outs RegF32:$d), (ins RndMode:$r, RegF64:$a),
+ "cvt$r.f32.f64\t$d, $a", []>;
+
+// To f64
+def CVTf64u16
+ : InstPTX<(outs RegF64:$d), (ins RndMode:$r, RegI16:$a),
+ "cvt$r.f64.u16\t$d, $a", []>;
+def CVTf64s16
+ : InstPTX<(outs RegF64:$d), (ins RndMode:$r, RegI16:$a),
+ "cvt$r.f64.s16\t$d, $a", []>;
+def CVTf64u32
+ : InstPTX<(outs RegF64:$d), (ins RndMode:$r, RegI32:$a),
+ "cvt$r.f64.u32\t$d, $a", []>;
+def CVTf64s32
+ : InstPTX<(outs RegF64:$d), (ins RndMode:$r, RegI32:$a),
+ "cvt$r.f64.s32\t$d, $a", []>;
+def CVTf64u64
+ : InstPTX<(outs RegF64:$d), (ins RndMode:$r, RegI64:$a),
+ "cvt$r.f64.u64\t$d, $a", []>;
+def CVTf64s64
+ : InstPTX<(outs RegF64:$d), (ins RndMode:$r, RegI64:$a),
+ "cvt$r.f64.s64\t$d, $a", []>;
+def CVTf64f32
+ : InstPTX<(outs RegF64:$d), (ins RegF32:$a), "cvt.f64.f32\t$d, $a", []>;
+
+ ///===- Control Flow Instructions -----------------------------------------===//
-// These instructions are used to load/store from the .param space for
-// device and kernel parameters
+let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
+ def BRAd
+ : InstPTX<(outs), (ins brtarget:$d), "bra\t$d", [(br bb:$d)]>;
+}
-let hasSideEffects = 1 in {
- def LDpiPred : InstPTX<(outs RegPred:$d), (ins MEMpi:$a),
- "ld.param.pred\t$d, [$a]",
- [(set RegPred:$d, (PTXloadparam timm:$a))]>;
- def LDpiU16 : InstPTX<(outs RegI16:$d), (ins MEMpi:$a),
- "ld.param.u16\t$d, [$a]",
- [(set RegI16:$d, (PTXloadparam timm:$a))]>;
- def LDpiU32 : InstPTX<(outs RegI32:$d), (ins MEMpi:$a),
- "ld.param.u32\t$d, [$a]",
- [(set RegI32:$d, (PTXloadparam timm:$a))]>;
- def LDpiU64 : InstPTX<(outs RegI64:$d), (ins MEMpi:$a),
- "ld.param.u64\t$d, [$a]",
- [(set RegI64:$d, (PTXloadparam timm:$a))]>;
- def LDpiF32 : InstPTX<(outs RegF32:$d), (ins MEMpi:$a),
- "ld.param.f32\t$d, [$a]",
- [(set RegF32:$d, (PTXloadparam timm:$a))]>;
- def LDpiF64 : InstPTX<(outs RegF64:$d), (ins MEMpi:$a),
- "ld.param.f64\t$d, [$a]",
- [(set RegF64:$d, (PTXloadparam timm:$a))]>;
-
- def STpiPred : InstPTX<(outs), (ins MEMret:$d, RegPred:$a),
- "st.param.pred\t[$d], $a",
- [(PTXstoreparam timm:$d, RegPred:$a)]>;
- def STpiU16 : InstPTX<(outs), (ins MEMret:$d, RegI16:$a),
- "st.param.u16\t[$d], $a",
- [(PTXstoreparam timm:$d, RegI16:$a)]>;
- def STpiU32 : InstPTX<(outs), (ins MEMret:$d, RegI32:$a),
- "st.param.u32\t[$d], $a",
- [(PTXstoreparam timm:$d, RegI32:$a)]>;
- def STpiU64 : InstPTX<(outs), (ins MEMret:$d, RegI64:$a),
- "st.param.u64\t[$d], $a",
- [(PTXstoreparam timm:$d, RegI64:$a)]>;
- def STpiF32 : InstPTX<(outs), (ins MEMret:$d, RegF32:$a),
- "st.param.f32\t[$d], $a",
- [(PTXstoreparam timm:$d, RegF32:$a)]>;
- def STpiF64 : InstPTX<(outs), (ins MEMret:$d, RegF64:$a),
- "st.param.f64\t[$d], $a",
- [(PTXstoreparam timm:$d, RegF64:$a)]>;
+let isBranch = 1, isTerminator = 1 in {
+ // FIXME: The pattern part is blank because I cannot (or do not yet know
+ // how to) use the first operand of PredicateOperand (a RegPred register) here
+ def BRAdp
+ : InstPTX<(outs), (ins brtarget:$d), "bra\t$d",
+ [/*(brcond pred:$_p, bb:$d)*/]>;
}
-// Stores
-defm STg : PTX_ST_ALL<"st.global", store_global>;
-defm STl : PTX_ST_ALL<"st.local", store_local>;
-defm STs : PTX_ST_ALL<"st.shared", store_shared>;
+let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
+ def EXIT : InstPTX<(outs), (ins), "exit", [(PTXexit)]>;
+ def RET : InstPTX<(outs), (ins), "ret", [(PTXret)]>;
+}
-// defm STp : PTX_ST_ALL<"st.param", store_parameter>;
-// defm LDp : PTX_LD_ALL<"ld.param", load_parameter>;
-// TODO: Do something with st.param if/when it is needed.
+let hasSideEffects = 1 in {
+ def CALL : InstPTX<(outs), (ins), "call", [(PTXcall)]>;
+}
-// Conversion to pred
-// PTX does not directly support converting to a predicate type, so we fake it
-// by performing a greater-than test between the value and zero. This follows
-// the C convention that any non-zero value is equivalent to 'true'.
-def CVT_pred_u16
- : InstPTX<(outs RegPred:$d), (ins RegI16:$a), "setp.gt.u16\t$d, $a, 0",
- [(set RegPred:$d, (trunc RegI16:$a))]>;
+///===- Parameter Passing Pseudo-Instructions -----------------------------===//
+
+def READPARAMPRED : InstPTX<(outs RegPred:$a), (ins i32imm:$b),
+ "mov.pred\t$a, %param$b", []>;
+def READPARAMI16 : InstPTX<(outs RegI16:$a), (ins i32imm:$b),
+ "mov.b16\t$a, %param$b", []>;
+def READPARAMI32 : InstPTX<(outs RegI32:$a), (ins i32imm:$b),
+ "mov.b32\t$a, %param$b", []>;
+def READPARAMI64 : InstPTX<(outs RegI64:$a), (ins i32imm:$b),
+ "mov.b64\t$a, %param$b", []>;
+def READPARAMF32 : InstPTX<(outs RegF32:$a), (ins i32imm:$b),
+ "mov.f32\t$a, %param$b", []>;
+def READPARAMF64 : InstPTX<(outs RegF64:$a), (ins i32imm:$b),
+ "mov.f64\t$a, %param$b", []>;
+
+def WRITEPARAMPRED : InstPTX<(outs), (ins RegPred:$a), "//w", []>;
+def WRITEPARAMI16 : InstPTX<(outs), (ins RegI16:$a), "//w", []>;
+def WRITEPARAMI32 : InstPTX<(outs), (ins RegI32:$a), "//w", []>;
+def WRITEPARAMI64 : InstPTX<(outs), (ins RegI64:$a), "//w", []>;
+def WRITEPARAMF32 : InstPTX<(outs), (ins RegF32:$a), "//w", []>;
+def WRITEPARAMF64 : InstPTX<(outs), (ins RegF64:$a), "//w", []>;
-def CVT_pred_u32
- : InstPTX<(outs RegPred:$d), (ins RegI32:$a), "setp.gt.u32\t$d, $a, 0",
- [(set RegPred:$d, (trunc RegI32:$a))]>;
-def CVT_pred_u64
- : InstPTX<(outs RegPred:$d), (ins RegI64:$a), "setp.gt.u64\t$d, $a, 0",
- [(set RegPred:$d, (trunc RegI64:$a))]>;
+//===----------------------------------------------------------------------===//
+// Instruction Selection Patterns
+//===----------------------------------------------------------------------===//
-def CVT_pred_f32
- : InstPTX<(outs RegPred:$d), (ins RegF32:$a), "setp.gt.f32\t$d, $a, 0",
- [(set RegPred:$d, (fp_to_uint RegF32:$a))]>;
+// FADD
+def : Pat<(f32 (fadd RegF32:$a, RegF32:$b)),
+ (FADDrr32 RndDefault, RegF32:$a, RegF32:$b)>;
+def : Pat<(f32 (fadd RegF32:$a, fpimm:$b)),
+ (FADDri32 RndDefault, RegF32:$a, fpimm:$b)>;
+def : Pat<(f64 (fadd RegF64:$a, RegF64:$b)),
+ (FADDrr64 RndDefault, RegF64:$a, RegF64:$b)>;
+def : Pat<(f64 (fadd RegF64:$a, fpimm:$b)),
+ (FADDri64 RndDefault, RegF64:$a, fpimm:$b)>;
+
+// FSUB
+def : Pat<(f32 (fsub RegF32:$a, RegF32:$b)),
+ (FSUBrr32 RndDefault, RegF32:$a, RegF32:$b)>;
+def : Pat<(f32 (fsub RegF32:$a, fpimm:$b)),
+ (FSUBri32 RndDefault, RegF32:$a, fpimm:$b)>;
+def : Pat<(f64 (fsub RegF64:$a, RegF64:$b)),
+ (FSUBrr64 RndDefault, RegF64:$a, RegF64:$b)>;
+def : Pat<(f64 (fsub RegF64:$a, fpimm:$b)),
+ (FSUBri64 RndDefault, RegF64:$a, fpimm:$b)>;
+
+// FMUL
+def : Pat<(f32 (fmul RegF32:$a, RegF32:$b)),
+ (FMULrr32 RndDefault, RegF32:$a, RegF32:$b)>;
+def : Pat<(f32 (fmul RegF32:$a, fpimm:$b)),
+ (FMULri32 RndDefault, RegF32:$a, fpimm:$b)>;
+def : Pat<(f64 (fmul RegF64:$a, RegF64:$b)),
+ (FMULrr64 RndDefault, RegF64:$a, RegF64:$b)>;
+def : Pat<(f64 (fmul RegF64:$a, fpimm:$b)),
+ (FMULri64 RndDefault, RegF64:$a, fpimm:$b)>;
+
+// FDIV
+def : Pat<(f32 (fdiv RegF32:$a, RegF32:$b)),
+ (FDIVrr32 RndDefault, RegF32:$a, RegF32:$b)>;
+def : Pat<(f32 (fdiv RegF32:$a, fpimm:$b)),
+ (FDIVri32 RndDefault, RegF32:$a, fpimm:$b)>;
+def : Pat<(f64 (fdiv RegF64:$a, RegF64:$b)),
+ (FDIVrr64 RndDefault, RegF64:$a, RegF64:$b)>;
+def : Pat<(f64 (fdiv RegF64:$a, fpimm:$b)),
+ (FDIVri64 RndDefault, RegF64:$a, fpimm:$b)>;
+
+// FMUL+FADD
+def : Pat<(f32 (fadd (fmul RegF32:$a, RegF32:$b), RegF32:$c)),
+ (FMADrrr32 RndDefault, RegF32:$a, RegF32:$b, RegF32:$c)>;
+def : Pat<(f32 (fadd (fmul RegF32:$a, RegF32:$b), fpimm:$c)),
+ (FMADrri32 RndDefault, RegF32:$a, RegF32:$b, fpimm:$c)>;
+def : Pat<(f32 (fadd (fmul RegF32:$a, fpimm:$b), fpimm:$c)),
+ (FMADrrr32 RndDefault, RegF32:$a, fpimm:$b, fpimm:$c)>;
+def : Pat<(f32 (fadd (fmul RegF32:$a, RegF32:$b), fpimm:$c)),
+ (FMADrri32 RndDefault, RegF32:$a, RegF32:$b, fpimm:$c)>;
+def : Pat<(f64 (fadd (fmul RegF64:$a, RegF64:$b), RegF64:$c)),
+ (FMADrrr64 RndDefault, RegF64:$a, RegF64:$b, RegF64:$c)>;
+def : Pat<(f64 (fadd (fmul RegF64:$a, RegF64:$b), fpimm:$c)),
+ (FMADrri64 RndDefault, RegF64:$a, RegF64:$b, fpimm:$c)>;
+def : Pat<(f64 (fadd (fmul RegF64:$a, fpimm:$b), fpimm:$c)),
+ (FMADrri64 RndDefault, RegF64:$a, fpimm:$b, fpimm:$c)>;
+
+// FNEG
+def : Pat<(f32 (fneg RegF32:$a)), (FNEGrr32 RndDefault, RegF32:$a)>;
+def : Pat<(f32 (fneg fpimm:$a)), (FNEGri32 RndDefault, fpimm:$a)>;
+def : Pat<(f64 (fneg RegF64:$a)), (FNEGrr64 RndDefault, RegF64:$a)>;
+def : Pat<(f64 (fneg fpimm:$a)), (FNEGri64 RndDefault, fpimm:$a)>;
+
+// FSQRT
+def : Pat<(f32 (fsqrt RegF32:$a)), (FSQRTrr32 RndDefault, RegF32:$a)>;
+def : Pat<(f32 (fsqrt fpimm:$a)), (FSQRTri32 RndDefault, fpimm:$a)>;
+def : Pat<(f64 (fsqrt RegF64:$a)), (FSQRTrr64 RndDefault, RegF64:$a)>;
+def : Pat<(f64 (fsqrt fpimm:$a)), (FSQRTri64 RndDefault, fpimm:$a)>;
+
+// FSIN
+def : Pat<(f32 (fsin RegF32:$a)), (FSINrr32 RndDefault, RegF32:$a)>;
+def : Pat<(f32 (fsin fpimm:$a)), (FSINri32 RndDefault, fpimm:$a)>;
+def : Pat<(f64 (fsin RegF64:$a)), (FSINrr64 RndDefault, RegF64:$a)>;
+def : Pat<(f64 (fsin fpimm:$a)), (FSINri64 RndDefault, fpimm:$a)>;
+
+// FCOS
+def : Pat<(f32 (fcos RegF32:$a)), (FCOSrr32 RndDefault, RegF32:$a)>;
+def : Pat<(f32 (fcos fpimm:$a)), (FCOSri32 RndDefault, fpimm:$a)>;
+def : Pat<(f64 (fcos RegF64:$a)), (FCOSrr64 RndDefault, RegF64:$a)>;
+def : Pat<(f64 (fcos fpimm:$a)), (FCOSri64 RndDefault, fpimm:$a)>;
+
+// Type conversion notes:
+// - PTX does not directly support converting a predicate to a value, so we
+// use a select instruction to select either 0 or 1 (integer or fp) based
+// on the truth value of the predicate.
+// - PTX does not directly support converting to a predicate type, so we fake it
+// by performing a greater-than test between the value and zero. This follows
+// the C convention that any non-zero value is equivalent to 'true'.
-def CVT_pred_f64
- : InstPTX<(outs RegPred:$d), (ins RegF64:$a), "setp.gt.f64\t$d, $a, 0",
- [(set RegPred:$d, (fp_to_uint RegF64:$a))]>;
+// Conversion to pred
+def : Pat<(i1 (trunc RegI16:$a)), (SETPGTu16ri RegI16:$a, 0)>;
+def : Pat<(i1 (trunc RegI32:$a)), (SETPGTu32ri RegI32:$a, 0)>;
+def : Pat<(i1 (trunc RegI64:$a)), (SETPGTu64ri RegI64:$a, 0)>;
+def : Pat<(i1 (fp_to_uint RegF32:$a)), (SETPGTu32ri (MOVi32f32 RegF32:$a), 0)>;
+def : Pat<(i1 (fp_to_uint RegF64:$a)), (SETPGTu64ri (MOVi64f64 RegF64:$a), 0)>;
// Conversion to u16
-// PTX does not directly support converting a predicate to a value, so we
-// use a select instruction to select either 0 or 1 (integer or fp) based
-// on the truth value of the predicate.
-def CVT_u16_preda
- : InstPTX<(outs RegI16:$d), (ins RegPred:$a), "selp.u16\t$d, 1, 0, $a",
- [(set RegI16:$d, (anyext RegPred:$a))]>;
-
-def CVT_u16_pred
- : InstPTX<(outs RegI16:$d), (ins RegPred:$a), "selp.u16\t$d, 1, 0, $a",
- [(set RegI16:$d, (zext RegPred:$a))]>;
-
-def CVT_u16_preds
- : InstPTX<(outs RegI16:$d), (ins RegPred:$a), "selp.u16\t$d, 1, 0, $a",
- [(set RegI16:$d, (sext RegPred:$a))]>;
-
-def CVT_u16_u32
- : InstPTX<(outs RegI16:$d), (ins RegI32:$a), "cvt.u16.u32\t$d, $a",
- [(set RegI16:$d, (trunc RegI32:$a))]>;
-
-def CVT_u16_u64
- : InstPTX<(outs RegI16:$d), (ins RegI64:$a), "cvt.u16.u64\t$d, $a",
- [(set RegI16:$d, (trunc RegI64:$a))]>;
-
-def CVT_u16_f32
- : InstPTX<(outs RegI16:$d), (ins RegF32:$a), "cvt.rzi.u16.f32\t$d, $a",
- [(set RegI16:$d, (fp_to_uint RegF32:$a))]>;
-
-def CVT_u16_f64
- : InstPTX<(outs RegI16:$d), (ins RegF64:$a), "cvt.rzi.u16.f64\t$d, $a",
- [(set RegI16:$d, (fp_to_uint RegF64:$a))]>;
+def : Pat<(i16 (anyext RegPred:$a)), (SELPi16ii RegPred:$a, 1, 0)>;
+def : Pat<(i16 (sext RegPred:$a)), (SELPi16ii RegPred:$a, 0xFFFF, 0)>;
+def : Pat<(i16 (zext RegPred:$a)), (SELPi16ii RegPred:$a, 1, 0)>;
+def : Pat<(i16 (trunc RegI32:$a)), (CVTu16u32 RegI32:$a)>;
+def : Pat<(i16 (trunc RegI64:$a)), (CVTu16u64 RegI64:$a)>;
+def : Pat<(i16 (fp_to_uint RegF32:$a)), (CVTu16f32 RndDefault, RegF32:$a)>;
+def : Pat<(i16 (fp_to_sint RegF32:$a)), (CVTs16f32 RndDefault, RegF32:$a)>;
+def : Pat<(i16 (fp_to_uint RegF64:$a)), (CVTu16f64 RndDefault, RegF64:$a)>;
+def : Pat<(i16 (fp_to_sint RegF64:$a)), (CVTs16f64 RndDefault, RegF64:$a)>;
// Conversion to u32
-
-def CVT_u32_pred
- : InstPTX<(outs RegI32:$d), (ins RegPred:$a), "selp.u32\t$d, 1, 0, $a",
- [(set RegI32:$d, (zext RegPred:$a))]>;
-
-def CVT_u32_b16
- : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.u16\t$d, $a",
- [(set RegI32:$d, (anyext RegI16:$a))]>;
-
-def CVT_u32_u16
- : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.u16\t$d, $a",
- [(set RegI32:$d, (zext RegI16:$a))]>;
-
-def CVT_u32_preds
- : InstPTX<(outs RegI32:$d), (ins RegPred:$a), "selp.u32\t$d, 1, 0, $a",
- [(set RegI32:$d, (sext RegPred:$a))]>;
-
-def CVT_u32_s16
- : InstPTX<(outs RegI32:$d), (ins RegI16:$a), "cvt.u32.s16\t$d, $a",
- [(set RegI32:$d, (sext RegI16:$a))]>;
-
-def CVT_u32_u64
- : InstPTX<(outs RegI32:$d), (ins RegI64:$a), "cvt.u32.u64\t$d, $a",
- [(set RegI32:$d, (trunc RegI64:$a))]>;
-
-def CVT_u32_f32
- : InstPTX<(outs RegI32:$d), (ins RegF32:$a), "cvt.rzi.u32.f32\t$d, $a",
- [(set RegI32:$d, (fp_to_uint RegF32:$a))]>;
-
-def CVT_u32_f64
- : InstPTX<(outs RegI32:$d), (ins RegF64:$a), "cvt.rzi.u32.f64\t$d, $a",
- [(set RegI32:$d, (fp_to_uint RegF64:$a))]>;
+def : Pat<(i32 (anyext RegPred:$a)), (SELPi32ii RegPred:$a, 1, 0)>;
+def : Pat<(i32 (sext RegPred:$a)), (SELPi32ii RegPred:$a, 0xFFFFFFFF, 0)>;
+def : Pat<(i32 (zext RegPred:$a)), (SELPi32ii RegPred:$a, 1, 0)>;
+def : Pat<(i32 (anyext RegI16:$a)), (CVTu32u16 RegI16:$a)>;
+def : Pat<(i32 (sext RegI16:$a)), (CVTs32s16 RegI16:$a)>;
+def : Pat<(i32 (zext RegI16:$a)), (CVTu32u16 RegI16:$a)>;
+def : Pat<(i32 (trunc RegI64:$a)), (CVTu32u64 RegI64:$a)>;
+def : Pat<(i32 (fp_to_uint RegF32:$a)), (CVTu32f32 RndDefault, RegF32:$a)>;
+def : Pat<(i32 (fp_to_sint RegF32:$a)), (CVTs32f32 RndDefault, RegF32:$a)>;
+def : Pat<(i32 (fp_to_uint RegF64:$a)), (CVTu32f64 RndDefault, RegF64:$a)>;
+def : Pat<(i32 (fp_to_sint RegF64:$a)), (CVTs32f64 RndDefault, RegF64:$a)>;
+def : Pat<(i32 (bitconvert RegF32:$a)), (MOVi32f32 RegF32:$a)>;
// Conversion to u64
-
-def CVT_u64_pred
- : InstPTX<(outs RegI64:$d), (ins RegPred:$a), "selp.u64\t$d, 1, 0, $a",
- [(set RegI64:$d, (zext RegPred:$a))]>;
-
-def CVT_u64_preds
- : InstPTX<(outs RegI64:$d), (ins RegPred:$a), "selp.u64\t$d, 1, 0, $a",
- [(set RegI64:$d, (sext RegPred:$a))]>;
-
-def CVT_u64_u16
- : InstPTX<(outs RegI64:$d), (ins RegI16:$a), "cvt.u64.u16\t$d, $a",
- [(set RegI64:$d, (zext RegI16:$a))]>;
-
-def CVT_u64_s16
- : InstPTX<(outs RegI64:$d), (ins RegI16:$a), "cvt.u64.s16\t$d, $a",
- [(set RegI64:$d, (sext RegI16:$a))]>;
-
-def CVT_u64_u32
- : InstPTX<(outs RegI64:$d), (ins RegI32:$a), "cvt.u64.u32\t$d, $a",
- [(set RegI64:$d, (zext RegI32:$a))]>;
-
-def CVT_u64_s32
- : InstPTX<(outs RegI64:$d), (ins RegI32:$a), "cvt.u64.s32\t$d, $a",
- [(set RegI64:$d, (sext RegI32:$a))]>;
-
-def CVT_u64_f32
- : InstPTX<(outs RegI64:$d), (ins RegF32:$a), "cvt.rzi.u64.f32\t$d, $a",
- [(set RegI64:$d, (fp_to_uint RegF32:$a))]>;
-
-def CVT_u64_f64
- : InstPTX<(outs RegI64:$d), (ins RegF64:$a), "cvt.rzi.u64.f64\t$d, $a",
- [(set RegI64:$d, (fp_to_uint RegF64:$a))]>;
+def : Pat<(i64 (anyext RegPred:$a)), (SELPi64ii RegPred:$a, 1, 0)>;
+def : Pat<(i64 (sext RegPred:$a)), (SELPi64ii RegPred:$a,
+ 0xFFFFFFFFFFFFFFFF, 0)>;
+def : Pat<(i64 (zext RegPred:$a)), (SELPi64ii RegPred:$a, 1, 0)>;
+def : Pat<(i64 (anyext RegI16:$a)), (CVTu64u16 RegI16:$a)>;
+def : Pat<(i64 (sext RegI16:$a)), (CVTs64s16 RegI16:$a)>;
+def : Pat<(i64 (zext RegI16:$a)), (CVTu64u16 RegI16:$a)>;
+def : Pat<(i64 (anyext RegI32:$a)), (CVTu64u32 RegI32:$a)>;
+def : Pat<(i64 (sext RegI32:$a)), (CVTs64s32 RegI32:$a)>;
+def : Pat<(i64 (zext RegI32:$a)), (CVTu64u32 RegI32:$a)>;
+def : Pat<(i64 (fp_to_uint RegF32:$a)), (CVTu64f32 RndDefault, RegF32:$a)>;
+def : Pat<(i64 (fp_to_sint RegF32:$a)), (CVTs64f32 RndDefault, RegF32:$a)>;
+def : Pat<(i64 (fp_to_uint RegF64:$a)), (CVTu64f64 RndDefault, RegF64:$a)>;
+def : Pat<(i64 (fp_to_sint RegF64:$a)), (CVTs64f64 RndDefault, RegF64:$a)>;
+def : Pat<(i64 (bitconvert RegF64:$a)), (MOVi64f64 RegF64:$a)>;
// Conversion to f32
-
-def CVT_f32_pred
- : InstPTX<(outs RegF32:$d), (ins RegPred:$a),
- "selp.f32\t$d, 0F3F800000, 0F00000000, $a", // 1.0
- [(set RegF32:$d, (uint_to_fp RegPred:$a))]>;
-
-def CVT_f32_u16
- : InstPTX<(outs RegF32:$d), (ins RegI16:$a), "cvt.rn.f32.u16\t$d, $a",
- [(set RegF32:$d, (uint_to_fp RegI16:$a))]>;
-
-def CVT_f32_u32
- : InstPTX<(outs RegF32:$d), (ins RegI32:$a), "cvt.rn.f32.u32\t$d, $a",
- [(set RegF32:$d, (uint_to_fp RegI32:$a))]>;
-
-def CVT_f32_u64
- : InstPTX<(outs RegF32:$d), (ins RegI64:$a), "cvt.rn.f32.u64\t$d, $a",
- [(set RegF32:$d, (uint_to_fp RegI64:$a))]>;
-
-def CVT_f32_f64
- : InstPTX<(outs RegF32:$d), (ins RegF64:$a), "cvt.rn.f32.f64\t$d, $a",
- [(set RegF32:$d, (fround RegF64:$a))]>;
+def : Pat<(f32 (uint_to_fp RegPred:$a)), (SELPf32rr RegPred:$a,
+ (MOVf32i32 0x3F800000), (MOVf32i32 0))>;
+def : Pat<(f32 (uint_to_fp RegI16:$a)), (CVTf32u16 RndDefault, RegI16:$a)>;
+def : Pat<(f32 (sint_to_fp RegI16:$a)), (CVTf32s16 RndDefault, RegI16:$a)>;
+def : Pat<(f32 (uint_to_fp RegI32:$a)), (CVTf32u32 RndDefault, RegI32:$a)>;
+def : Pat<(f32 (sint_to_fp RegI32:$a)), (CVTf32s32 RndDefault, RegI32:$a)>;
+def : Pat<(f32 (uint_to_fp RegI64:$a)), (CVTf32u64 RndDefault, RegI64:$a)>;
+def : Pat<(f32 (sint_to_fp RegI64:$a)), (CVTf32s64 RndDefault, RegI64:$a)>;
+def : Pat<(f32 (fround RegF64:$a)), (CVTf32f64 RndDefault, RegF64:$a)>;
+def : Pat<(f32 (bitconvert RegI32:$a)), (MOVf32i32 RegI32:$a)>;
// Conversion to f64
+def : Pat<(f64 (uint_to_fp RegPred:$a)), (SELPf64rr RegPred:$a,
+ (MOVf64i64 0x3F80000000000000), (MOVf64i64 0))>;
+def : Pat<(f64 (uint_to_fp RegI16:$a)), (CVTf64u16 RndDefault, RegI16:$a)>;
+def : Pat<(f64 (sint_to_fp RegI16:$a)), (CVTf64s16 RndDefault, RegI16:$a)>;
+def : Pat<(f64 (uint_to_fp RegI32:$a)), (CVTf64u32 RndDefault, RegI32:$a)>;
+def : Pat<(f64 (sint_to_fp RegI32:$a)), (CVTf64s32 RndDefault, RegI32:$a)>;
+def : Pat<(f64 (uint_to_fp RegI64:$a)), (CVTf64u64 RndDefault, RegI64:$a)>;
+def : Pat<(f64 (sint_to_fp RegI64:$a)), (CVTf64s64 RndDefault, RegI64:$a)>;
+def : Pat<(f64 (fextend RegF32:$a)), (CVTf64f32 RegF32:$a)>;
+def : Pat<(f64 (bitconvert RegI64:$a)), (MOVf64i64 RegI64:$a)>;
-def CVT_f64_pred
- : InstPTX<(outs RegF64:$d), (ins RegPred:$a),
- "selp.f64\t$d, 0D3F80000000000000, 0D0000000000000000, $a", // 1.0
- [(set RegF64:$d, (uint_to_fp RegPred:$a))]>;
-
-def CVT_f64_u16
- : InstPTX<(outs RegF64:$d), (ins RegI16:$a), "cvt.rn.f64.u16\t$d, $a",
- [(set RegF64:$d, (uint_to_fp RegI16:$a))]>;
-
-def CVT_f64_u32
- : InstPTX<(outs RegF64:$d), (ins RegI32:$a), "cvt.rn.f64.u32\t$d, $a",
- [(set RegF64:$d, (uint_to_fp RegI32:$a))]>;
-
-def CVT_f64_u64
- : InstPTX<(outs RegF64:$d), (ins RegI64:$a), "cvt.rn.f64.u64\t$d, $a",
- [(set RegF64:$d, (uint_to_fp RegI64:$a))]>;
-
-def CVT_f64_f32
- : InstPTX<(outs RegF64:$d), (ins RegF32:$a), "cvt.f64.f32\t$d, $a",
- [(set RegF64:$d, (fextend RegF32:$a))]>;
-
-///===- Control Flow Instructions -----------------------------------------===//
-
-let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
- def BRAd
- : InstPTX<(outs), (ins brtarget:$d), "bra\t$d", [(br bb:$d)]>;
-}
-
-let isBranch = 1, isTerminator = 1 in {
- // FIXME: The pattern part is blank because I cannot (or do not yet know
- // how to) use the first operand of PredicateOperand (a RegPred register) here
- def BRAdp
- : InstPTX<(outs), (ins brtarget:$d), "bra\t$d",
- [/*(brcond pred:$_p, bb:$d)*/]>;
-}
-
-let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
- def EXIT : InstPTX<(outs), (ins), "exit", [(PTXexit)]>;
- def RET : InstPTX<(outs), (ins), "ret", [(PTXret)]>;
-}
-
-///===- Spill Instructions ------------------------------------------------===//
-// Special instructions used for stack spilling
-def STACKSTOREI16 : InstPTX<(outs), (ins i32imm:$d, RegI16:$a),
- "mov.u16\ts$d, $a", []>;
-def STACKSTOREI32 : InstPTX<(outs), (ins i32imm:$d, RegI32:$a),
- "mov.u32\ts$d, $a", []>;
-def STACKSTOREI64 : InstPTX<(outs), (ins i32imm:$d, RegI64:$a),
- "mov.u64\ts$d, $a", []>;
-def STACKSTOREF32 : InstPTX<(outs), (ins i32imm:$d, RegF32:$a),
- "mov.f32\ts$d, $a", []>;
-def STACKSTOREF64 : InstPTX<(outs), (ins i32imm:$d, RegF64:$a),
- "mov.f64\ts$d, $a", []>;
-
-def STACKLOADI16 : InstPTX<(outs), (ins RegI16:$d, i32imm:$a),
- "mov.u16\t$d, s$a", []>;
-def STACKLOADI32 : InstPTX<(outs), (ins RegI32:$d, i32imm:$a),
- "mov.u32\t$d, s$a", []>;
-def STACKLOADI64 : InstPTX<(outs), (ins RegI64:$d, i32imm:$a),
- "mov.u64\t$d, s$a", []>;
-def STACKLOADF32 : InstPTX<(outs), (ins RegF32:$d, i32imm:$a),
- "mov.f32\t$d, s$a", []>;
-def STACKLOADF64 : InstPTX<(outs), (ins RegF64:$d, i32imm:$a),
- "mov.f64\t$d, s$a", []>;
///===- Intrinsic Instructions --------------------------------------------===//
-
include "PTXIntrinsicInstrInfo.td"
+
+///===- Load/Store Instructions -------------------------------------------===//
+include "PTXInstrLoadStore.td"
+
diff --git a/lib/Target/PTX/PTXInstrLoadStore.td b/lib/Target/PTX/PTXInstrLoadStore.td
new file mode 100644
index 0000000..9b4f56c
--- /dev/null
+++ b/lib/Target/PTX/PTXInstrLoadStore.td
@@ -0,0 +1,278 @@
+//===- PTXInstrLoadStore.td - PTX Load/Store Instruction Defs -*- tblgen-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the PTX load/store instructions in TableGen format.
+//
+//===----------------------------------------------------------------------===//
+
+
+// Addressing Predicates
+// We have to differentiate between 32- and 64-bit pointer types
+def Use32BitAddresses : Predicate<"!getSubtarget().is64Bit()">;
+def Use64BitAddresses : Predicate<"getSubtarget().is64Bit()">;
+
+//===----------------------------------------------------------------------===//
+// Pattern Fragments for Loads/Stores
+//===----------------------------------------------------------------------===//
+
+def load_global : PatFrag<(ops node:$ptr), (load node:$ptr), [{
+ const Value *Src;
+ const PointerType *PT;
+ if ((Src = cast<LoadSDNode>(N)->getSrcValue()) &&
+ (PT = dyn_cast<PointerType>(Src->getType())))
+ return PT->getAddressSpace() == PTXStateSpace::Global;
+ return false;
+}]>;
+
+def load_constant : PatFrag<(ops node:$ptr), (load node:$ptr), [{
+ const Value *Src;
+ const PointerType *PT;
+ if ((Src = cast<LoadSDNode>(N)->getSrcValue()) &&
+ (PT = dyn_cast<PointerType>(Src->getType())))
+ return PT->getAddressSpace() == PTXStateSpace::Constant;
+ return false;
+}]>;
+
+def load_shared : PatFrag<(ops node:$ptr), (load node:$ptr), [{
+ const Value *Src;
+ const PointerType *PT;
+ if ((Src = cast<LoadSDNode>(N)->getSrcValue()) &&
+ (PT = dyn_cast<PointerType>(Src->getType())))
+ return PT->getAddressSpace() == PTXStateSpace::Shared;
+ return false;
+}]>;
+
+def store_global
+ : PatFrag<(ops node:$d, node:$ptr), (store node:$d, node:$ptr), [{
+ const Value *Src;
+ const PointerType *PT;
+ if ((Src = cast<StoreSDNode>(N)->getSrcValue()) &&
+ (PT = dyn_cast<PointerType>(Src->getType())))
+ return PT->getAddressSpace() == PTXStateSpace::Global;
+ return false;
+}]>;
+
+def store_shared
+ : PatFrag<(ops node:$d, node:$ptr), (store node:$d, node:$ptr), [{
+ const Value *Src;
+ const PointerType *PT;
+ if ((Src = cast<StoreSDNode>(N)->getSrcValue()) &&
+ (PT = dyn_cast<PointerType>(Src->getType())))
+ return PT->getAddressSpace() == PTXStateSpace::Shared;
+ return false;
+}]>;
+
+// Addressing modes.
+def ADDRrr32 : ComplexPattern<i32, 2, "SelectADDRrr", [], []>;
+def ADDRrr64 : ComplexPattern<i64, 2, "SelectADDRrr", [], []>;
+def ADDRri32 : ComplexPattern<i32, 2, "SelectADDRri", [], []>;
+def ADDRri64 : ComplexPattern<i64, 2, "SelectADDRri", [], []>;
+def ADDRii32 : ComplexPattern<i32, 2, "SelectADDRii", [], []>;
+def ADDRii64 : ComplexPattern<i64, 2, "SelectADDRii", [], []>;
+def ADDRlocal32 : ComplexPattern<i32, 2, "SelectADDRlocal", [], []>;
+def ADDRlocal64 : ComplexPattern<i64, 2, "SelectADDRlocal", [], []>;
+
+// Address operands
+def MEMri32 : Operand<i32> {
+ let PrintMethod = "printMemOperand";
+ let MIOperandInfo = (ops RegI32, i32imm);
+}
+def MEMri64 : Operand<i64> {
+ let PrintMethod = "printMemOperand";
+ let MIOperandInfo = (ops RegI64, i64imm);
+}
+def LOCALri32 : Operand<i32> {
+ let PrintMethod = "printMemOperand";
+ let MIOperandInfo = (ops i32imm, i32imm);
+}
+def LOCALri64 : Operand<i64> {
+ let PrintMethod = "printMemOperand";
+ let MIOperandInfo = (ops i64imm, i64imm);
+}
+def MEMii32 : Operand<i32> {
+ let PrintMethod = "printMemOperand";
+ let MIOperandInfo = (ops i32imm, i32imm);
+}
+def MEMii64 : Operand<i64> {
+ let PrintMethod = "printMemOperand";
+ let MIOperandInfo = (ops i64imm, i64imm);
+}
+// The operand here does not correspond to an actual address, so we
+// can use i32 in 64-bit address modes.
+def MEMpi : Operand<i32> {
+ let PrintMethod = "printParamOperand";
+ let MIOperandInfo = (ops i32imm);
+}
+def MEMret : Operand<i32> {
+ let PrintMethod = "printReturnOperand";
+ let MIOperandInfo = (ops i32imm);
+}
+
+
+// Load/store .param space
+def PTXloadparam
+ : SDNode<"PTXISD::LOAD_PARAM", SDTypeProfile<1, 1, [SDTCisPtrTy<1>]>,
+ [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue]>;
+def PTXstoreparam
+ : SDNode<"PTXISD::STORE_PARAM", SDTypeProfile<0, 2, [SDTCisVT<0, i32>]>,
+ [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue]>;
+
+def PTXreadparam
+ : SDNode<"PTXISD::READ_PARAM", SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>,
+ [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue]>;
+def PTXwriteparam
+ : SDNode<"PTXISD::WRITE_PARAM", SDTypeProfile<0, 1, []>,
+ [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue]>;
+
+
+
+//===----------------------------------------------------------------------===//
+// Classes for loads/stores
+//===----------------------------------------------------------------------===//
+multiclass PTX_LD<string opstr, string typestr,
+ RegisterClass RC, PatFrag pat_load> {
+ def rr32 : InstPTX<(outs RC:$d),
+ (ins MEMri32:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
+ [(set RC:$d, (pat_load ADDRrr32:$a))]>,
+ Requires<[Use32BitAddresses]>;
+ def rr64 : InstPTX<(outs RC:$d),
+ (ins MEMri64:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
+ [(set RC:$d, (pat_load ADDRrr64:$a))]>,
+ Requires<[Use64BitAddresses]>;
+ def ri32 : InstPTX<(outs RC:$d),
+ (ins MEMri32:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
+ [(set RC:$d, (pat_load ADDRri32:$a))]>,
+ Requires<[Use32BitAddresses]>;
+ def ri64 : InstPTX<(outs RC:$d),
+ (ins MEMri64:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
+ [(set RC:$d, (pat_load ADDRri64:$a))]>,
+ Requires<[Use64BitAddresses]>;
+ def ii32 : InstPTX<(outs RC:$d),
+ (ins MEMii32:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
+ [(set RC:$d, (pat_load ADDRii32:$a))]>,
+ Requires<[Use32BitAddresses]>;
+ def ii64 : InstPTX<(outs RC:$d),
+ (ins MEMii64:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t$d, [$a]")),
+ [(set RC:$d, (pat_load ADDRii64:$a))]>,
+ Requires<[Use64BitAddresses]>;
+}
+
+multiclass PTX_ST<string opstr, string typestr, RegisterClass RC,
+ PatFrag pat_store> {
+ def rr32 : InstPTX<(outs),
+ (ins RC:$d, MEMri32:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
+ [(pat_store RC:$d, ADDRrr32:$a)]>,
+ Requires<[Use32BitAddresses]>;
+ def rr64 : InstPTX<(outs),
+ (ins RC:$d, MEMri64:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
+ [(pat_store RC:$d, ADDRrr64:$a)]>,
+ Requires<[Use64BitAddresses]>;
+ def ri32 : InstPTX<(outs),
+ (ins RC:$d, MEMri32:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
+ [(pat_store RC:$d, ADDRri32:$a)]>,
+ Requires<[Use32BitAddresses]>;
+ def ri64 : InstPTX<(outs),
+ (ins RC:$d, MEMri64:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
+ [(pat_store RC:$d, ADDRri64:$a)]>,
+ Requires<[Use64BitAddresses]>;
+ def ii32 : InstPTX<(outs),
+ (ins RC:$d, MEMii32:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
+ [(pat_store RC:$d, ADDRii32:$a)]>,
+ Requires<[Use32BitAddresses]>;
+ def ii64 : InstPTX<(outs),
+ (ins RC:$d, MEMii64:$a),
+ !strconcat(opstr, !strconcat(typestr, "\t[$a], $d")),
+ [(pat_store RC:$d, ADDRii64:$a)]>,
+ Requires<[Use64BitAddresses]>;
+}
+
+multiclass PTX_LOCAL_LD_ST<string typestr, RegisterClass RC> {
+ def LDri32 : InstPTX<(outs RC:$d), (ins LOCALri32:$a),
+ !strconcat("ld.local", !strconcat(typestr, "\t$d, [$a]")),
+ [(set RC:$d, (load_global ADDRlocal32:$a))]>;
+ def LDri64 : InstPTX<(outs RC:$d), (ins LOCALri64:$a),
+ !strconcat("ld.local", !strconcat(typestr, "\t$d, [$a]")),
+ [(set RC:$d, (load_global ADDRlocal64:$a))]>;
+ def STri32 : InstPTX<(outs), (ins RC:$d, LOCALri32:$a),
+ !strconcat("st.local", !strconcat(typestr, "\t[$a], $d")),
+ [(store_global RC:$d, ADDRlocal32:$a)]>;
+ def STri64 : InstPTX<(outs), (ins RC:$d, LOCALri64:$a),
+ !strconcat("st.local", !strconcat(typestr, "\t[$a], $d")),
+ [(store_global RC:$d, ADDRlocal64:$a)]>;
+}
+
+multiclass PTX_PARAM_LD_ST<string typestr, RegisterClass RC> {
+ let hasSideEffects = 1 in {
+ def LDpi : InstPTX<(outs RC:$d), (ins i32imm:$a),
+ !strconcat("ld.param", !strconcat(typestr, "\t$d, [$a]")),
+ [(set RC:$d, (PTXloadparam texternalsym:$a))]>;
+ def STpi : InstPTX<(outs), (ins i32imm:$d, RC:$a),
+ !strconcat("st.param", !strconcat(typestr, "\t[$d], $a")),
+ [(PTXstoreparam texternalsym:$d, RC:$a)]>;
+ }
+}
+
+multiclass PTX_LD_ALL<string opstr, PatFrag pat_load> {
+ defm u16 : PTX_LD<opstr, ".u16", RegI16, pat_load>;
+ defm u32 : PTX_LD<opstr, ".u32", RegI32, pat_load>;
+ defm u64 : PTX_LD<opstr, ".u64", RegI64, pat_load>;
+ defm f32 : PTX_LD<opstr, ".f32", RegF32, pat_load>;
+ defm f64 : PTX_LD<opstr, ".f64", RegF64, pat_load>;
+}
+
+multiclass PTX_ST_ALL<string opstr, PatFrag pat_store> {
+ defm u16 : PTX_ST<opstr, ".u16", RegI16, pat_store>;
+ defm u32 : PTX_ST<opstr, ".u32", RegI32, pat_store>;
+ defm u64 : PTX_ST<opstr, ".u64", RegI64, pat_store>;
+ defm f32 : PTX_ST<opstr, ".f32", RegF32, pat_store>;
+ defm f64 : PTX_ST<opstr, ".f64", RegF64, pat_store>;
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Instruction definitions for loads/stores
+//===----------------------------------------------------------------------===//
+
+// Global/shared stores
+defm STg : PTX_ST_ALL<"st.global", store_global>;
+defm STs : PTX_ST_ALL<"st.shared", store_shared>;
+
+// Global/shared/constant loads
+defm LDg : PTX_LD_ALL<"ld.global", load_global>;
+defm LDc : PTX_LD_ALL<"ld.const", load_constant>;
+defm LDs : PTX_LD_ALL<"ld.shared", load_shared>;
+
+// Param loads/stores
+defm PARAMPRED : PTX_PARAM_LD_ST<".pred", RegPred>;
+defm PARAMU16 : PTX_PARAM_LD_ST<".u16", RegI16>;
+defm PARAMU32 : PTX_PARAM_LD_ST<".u32", RegI32>;
+defm PARAMU64 : PTX_PARAM_LD_ST<".u64", RegI64>;
+defm PARAMF32 : PTX_PARAM_LD_ST<".f32", RegF32>;
+defm PARAMF64 : PTX_PARAM_LD_ST<".f64", RegF64>;
+
+// Local loads/stores
+defm LOCALPRED : PTX_LOCAL_LD_ST<".pred", RegPred>;
+defm LOCALU16 : PTX_LOCAL_LD_ST<".u16", RegI16>;
+defm LOCALU32 : PTX_LOCAL_LD_ST<".u32", RegI32>;
+defm LOCALU64 : PTX_LOCAL_LD_ST<".u64", RegI64>;
+defm LOCALF32 : PTX_LOCAL_LD_ST<".f32", RegF32>;
+defm LOCALF64 : PTX_LOCAL_LD_ST<".f64", RegF64>;
+
diff --git a/lib/Target/PTX/PTXIntrinsicInstrInfo.td b/lib/Target/PTX/PTXIntrinsicInstrInfo.td
index 8d97909..9de1cb6 100644
--- a/lib/Target/PTX/PTXIntrinsicInstrInfo.td
+++ b/lib/Target/PTX/PTXIntrinsicInstrInfo.td
@@ -25,37 +25,63 @@ class PTX_READ_SPECIAL_REGISTER_R32<string regname, Intrinsic intop>
// TODO Add read vector-version of special registers
-//def PTX_READ_TID_R64 : PTX_READ_SPECIAL_REGISTER_R64<"tid", int_ptx_read_tid_r64>;
-def PTX_READ_TID_X : PTX_READ_SPECIAL_REGISTER_R32<"tid.x", int_ptx_read_tid_x>;
-def PTX_READ_TID_Y : PTX_READ_SPECIAL_REGISTER_R32<"tid.y", int_ptx_read_tid_y>;
-def PTX_READ_TID_Z : PTX_READ_SPECIAL_REGISTER_R32<"tid.z", int_ptx_read_tid_z>;
-def PTX_READ_TID_W : PTX_READ_SPECIAL_REGISTER_R32<"tid.w", int_ptx_read_tid_w>;
+//def PTX_READ_TID_R64 : PTX_READ_SPECIAL_REGISTER_R64<"tid",
+// int_ptx_read_tid_r64>;
+def PTX_READ_TID_X : PTX_READ_SPECIAL_REGISTER_R32<"tid.x",
+ int_ptx_read_tid_x>;
+def PTX_READ_TID_Y : PTX_READ_SPECIAL_REGISTER_R32<"tid.y",
+ int_ptx_read_tid_y>;
+def PTX_READ_TID_Z : PTX_READ_SPECIAL_REGISTER_R32<"tid.z",
+ int_ptx_read_tid_z>;
+def PTX_READ_TID_W : PTX_READ_SPECIAL_REGISTER_R32<"tid.w",
+ int_ptx_read_tid_w>;
-//def PTX_READ_NTID_R64 : PTX_READ_SPECIAL_REGISTER_R64<"ntid", int_ptx_read_ntid_r64>;
-def PTX_READ_NTID_X : PTX_READ_SPECIAL_REGISTER_R32<"ntid.x", int_ptx_read_ntid_x>;
-def PTX_READ_NTID_Y : PTX_READ_SPECIAL_REGISTER_R32<"ntid.y", int_ptx_read_ntid_y>;
-def PTX_READ_NTID_Z : PTX_READ_SPECIAL_REGISTER_R32<"ntid.z", int_ptx_read_ntid_z>;
-def PTX_READ_NTID_W : PTX_READ_SPECIAL_REGISTER_R32<"ntid.w", int_ptx_read_ntid_w>;
+//def PTX_READ_NTID_R64 : PTX_READ_SPECIAL_REGISTER_R64<"ntid",
+// int_ptx_read_ntid_r64>;
+def PTX_READ_NTID_X : PTX_READ_SPECIAL_REGISTER_R32<"ntid.x",
+ int_ptx_read_ntid_x>;
+def PTX_READ_NTID_Y : PTX_READ_SPECIAL_REGISTER_R32<"ntid.y",
+ int_ptx_read_ntid_y>;
+def PTX_READ_NTID_Z : PTX_READ_SPECIAL_REGISTER_R32<"ntid.z",
+ int_ptx_read_ntid_z>;
+def PTX_READ_NTID_W : PTX_READ_SPECIAL_REGISTER_R32<"ntid.w",
+ int_ptx_read_ntid_w>;
-def PTX_READ_LANEID : PTX_READ_SPECIAL_REGISTER_R32<"laneid", int_ptx_read_laneid>;
-def PTX_READ_WARPID : PTX_READ_SPECIAL_REGISTER_R32<"warpid", int_ptx_read_warpid>;
-def PTX_READ_NWARPID : PTX_READ_SPECIAL_REGISTER_R32<"nwarpid", int_ptx_read_nwarpid>;
+def PTX_READ_LANEID : PTX_READ_SPECIAL_REGISTER_R32<"laneid",
+ int_ptx_read_laneid>;
+def PTX_READ_WARPID : PTX_READ_SPECIAL_REGISTER_R32<"warpid",
+ int_ptx_read_warpid>;
+def PTX_READ_NWARPID : PTX_READ_SPECIAL_REGISTER_R32<"nwarpid",
+ int_ptx_read_nwarpid>;
-//def PTX_READ_CTAID_R64 : PTX_READ_SPECIAL_REGISTER_R64<"ctaid", int_ptx_read_ctaid_r64>;
-def PTX_READ_CTAID_X : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.x", int_ptx_read_ctaid_x>;
-def PTX_READ_CTAID_Y : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.y", int_ptx_read_ctaid_y>;
-def PTX_READ_CTAID_Z : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.z", int_ptx_read_ctaid_z>;
-def PTX_READ_CTAID_W : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.w", int_ptx_read_ctaid_w>;
+//def PTX_READ_CTAID_R64 :
+//PTX_READ_SPECIAL_REGISTER_R64<"ctaid", int_ptx_read_ctaid_r64>;
+def PTX_READ_CTAID_X : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.x",
+ int_ptx_read_ctaid_x>;
+def PTX_READ_CTAID_Y : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.y",
+ int_ptx_read_ctaid_y>;
+def PTX_READ_CTAID_Z : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.z",
+ int_ptx_read_ctaid_z>;
+def PTX_READ_CTAID_W : PTX_READ_SPECIAL_REGISTER_R32<"ctaid.w",
+ int_ptx_read_ctaid_w>;
-//def PTX_READ_NCTAID_R64 : PTX_READ_SPECIAL_REGISTER_R64<"nctaid", int_ptx_read_nctaid_r64>;
-def PTX_READ_NCTAID_X : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.x", int_ptx_read_nctaid_x>;
-def PTX_READ_NCTAID_Y : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.y", int_ptx_read_nctaid_y>;
-def PTX_READ_NCTAID_Z : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.z", int_ptx_read_nctaid_z>;
-def PTX_READ_NCTAID_W : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.w", int_ptx_read_nctaid_w>;
+//def PTX_READ_NCTAID_R64 :
+//PTX_READ_SPECIAL_REGISTER_R64<"nctaid", int_ptx_read_nctaid_r64>;
+def PTX_READ_NCTAID_X : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.x",
+ int_ptx_read_nctaid_x>;
+def PTX_READ_NCTAID_Y : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.y",
+ int_ptx_read_nctaid_y>;
+def PTX_READ_NCTAID_Z : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.z",
+ int_ptx_read_nctaid_z>;
+def PTX_READ_NCTAID_W : PTX_READ_SPECIAL_REGISTER_R32<"nctaid.w",
+ int_ptx_read_nctaid_w>;
-def PTX_READ_SMID : PTX_READ_SPECIAL_REGISTER_R32<"smid", int_ptx_read_smid>;
-def PTX_READ_NSMID : PTX_READ_SPECIAL_REGISTER_R32<"nsmid", int_ptx_read_nsmid>;
-def PTX_READ_GRIDID : PTX_READ_SPECIAL_REGISTER_R32<"gridid", int_ptx_read_gridid>;
+def PTX_READ_SMID : PTX_READ_SPECIAL_REGISTER_R32<"smid",
+ int_ptx_read_smid>;
+def PTX_READ_NSMID : PTX_READ_SPECIAL_REGISTER_R32<"nsmid",
+ int_ptx_read_nsmid>;
+def PTX_READ_GRIDID : PTX_READ_SPECIAL_REGISTER_R32<"gridid",
+ int_ptx_read_gridid>;
def PTX_READ_LANEMASK_EQ
: PTX_READ_SPECIAL_REGISTER_R32<"lanemask_eq", int_ptx_read_lanemask_eq>;
diff --git a/lib/Target/PTX/PTXMCAsmStreamer.cpp b/lib/Target/PTX/PTXMCAsmStreamer.cpp
index b13a3da..468ce93 100644
--- a/lib/Target/PTX/PTXMCAsmStreamer.cpp
+++ b/lib/Target/PTX/PTXMCAsmStreamer.cpp
@@ -100,7 +100,7 @@ public:
/// @{
virtual void ChangeSection(const MCSection *Section);
- virtual void InitSections() {}
+ virtual void InitSections() { /* PTX does not use sections */ }
virtual void EmitLabel(MCSymbol *Symbol);
@@ -132,7 +132,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 ByteAlignment - 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);
@@ -233,7 +235,7 @@ void PTXMCAsmStreamer::ChangeSection(const MCSection *Section) {
void PTXMCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
- //assert(getCurrentSection() && "Cannot emit before setting section!");
+ assert(getCurrentSection() && "Cannot emit before setting section!");
OS << *Symbol << MAI.getLabelSuffix();
EmitEOL();
@@ -283,7 +285,8 @@ void PTXMCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
void PTXMCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {}
-void PTXMCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {}
+void PTXMCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {}
void PTXMCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
unsigned Size, unsigned ByteAlignment) {}
@@ -510,7 +513,7 @@ void PTXMCAsmStreamer::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();
@@ -533,7 +536,7 @@ namespace llvm {
formatted_raw_ostream &OS,
bool isVerboseAsm, bool useLoc, bool useCFI,
MCInstPrinter *IP,
- MCCodeEmitter *CE, TargetAsmBackend *TAB,
+ MCCodeEmitter *CE, MCAsmBackend *MAB,
bool ShowInst) {
return new PTXMCAsmStreamer(Context, OS, isVerboseAsm, useLoc,
IP, CE, ShowInst);
diff --git a/lib/Target/PTX/PTXMCInstLower.cpp b/lib/Target/PTX/PTXMCInstLower.cpp
new file mode 100644
index 0000000..142e639
--- /dev/null
+++ b/lib/Target/PTX/PTXMCInstLower.cpp
@@ -0,0 +1,32 @@
+//===-- PTXMCInstLower.cpp - Convert PTX MachineInstr to an MCInst --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to lower PTX MachineInstrs to their corresponding
+// MCInst records.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PTX.h"
+#include "PTXAsmPrinter.h"
+#include "llvm/Constants.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/Target/Mangler.h"
+
+void llvm::LowerPTXMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
+ PTXAsmPrinter &AP) {
+ OutMI.setOpcode(MI->getOpcode());
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+ MCOperand MCOp;
+ OutMI.addOperand(AP.lowerOperand(MO));
+ }
+}
+
diff --git a/lib/Target/PTX/PTXMFInfoExtract.cpp b/lib/Target/PTX/PTXMFInfoExtract.cpp
index 6fe9e6c..b33a273 100644
--- a/lib/Target/PTX/PTXMFInfoExtract.cpp
+++ b/lib/Target/PTX/PTXMFInfoExtract.cpp
@@ -52,36 +52,12 @@ bool PTXMFInfoExtract::runOnMachineFunction(MachineFunction &MF) {
PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
MachineRegisterInfo &MRI = MF.getRegInfo();
- DEBUG(dbgs() << "******** PTX FUNCTION LOCAL VAR REG DEF ********\n");
-
- DEBUG(dbgs()
- << "PTX::NoRegister == " << PTX::NoRegister << "\n"
- << "PTX::NUM_TARGET_REGS == " << PTX::NUM_TARGET_REGS << "\n");
-
- DEBUG(for (unsigned reg = PTX::NoRegister + 1;
- reg < PTX::NUM_TARGET_REGS; ++reg)
- if (MRI.isPhysRegUsed(reg))
- dbgs() << "Used Reg: " << reg << "\n";);
-
- // FIXME: This is a slow linear scanning
- for (unsigned reg = PTX::NoRegister + 1; reg < PTX::NUM_TARGET_REGS; ++reg)
- if (MRI.isPhysRegUsed(reg) &&
- !MFI->isRetReg(reg) &&
- (MFI->isKernel() || !MFI->isArgReg(reg)))
- MFI->addLocalVarReg(reg);
-
- // Notify MachineFunctionInfo that I've done adding local var reg
- MFI->doneAddLocalVar();
-
- DEBUG(for (PTXMachineFunctionInfo::reg_iterator
- i = MFI->argRegBegin(), e = MFI->argRegEnd();
- i != e; ++i)
- dbgs() << "Arg Reg: " << *i << "\n";);
-
- DEBUG(for (PTXMachineFunctionInfo::reg_iterator
- i = MFI->localVarRegBegin(), e = MFI->localVarRegEnd();
- i != e; ++i)
- dbgs() << "Local Var Reg: " << *i << "\n";);
+ // Generate list of all virtual registers used in this function
+ for (unsigned i = 0; i < MRI.getNumVirtRegs(); ++i) {
+ unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
+ const TargetRegisterClass *TRC = MRI.getRegClass(Reg);
+ MFI->addVirtualRegister(TRC, Reg);
+ }
return false;
}
diff --git a/lib/Target/PTX/PTXMachineFunctionInfo.h b/lib/Target/PTX/PTXMachineFunctionInfo.h
index 9d65f5b..3b985f7 100644
--- a/lib/Target/PTX/PTXMachineFunctionInfo.h
+++ b/lib/Target/PTX/PTXMachineFunctionInfo.h
@@ -15,75 +15,148 @@
#define PTX_MACHINE_FUNCTION_INFO_H
#include "PTX.h"
+#include "PTXParamManager.h"
+#include "PTXRegisterInfo.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
namespace llvm {
+
/// PTXMachineFunctionInfo - This class is derived from MachineFunction and
/// contains private PTX target-specific information for each MachineFunction.
///
class PTXMachineFunctionInfo : public MachineFunctionInfo {
private:
- bool is_kernel;
- std::vector<unsigned> reg_arg, reg_local_var;
- std::vector<unsigned> reg_ret;
- bool _isDoneAddArg;
+ bool IsKernel;
+ DenseSet<unsigned> RegArgs;
+ DenseSet<unsigned> RegRets;
+
+ typedef std::vector<unsigned> RegisterList;
+ typedef DenseMap<const TargetRegisterClass*, RegisterList> RegisterMap;
+ typedef DenseMap<unsigned, std::string> RegisterNameMap;
+ typedef DenseMap<int, std::string> FrameMap;
+
+ RegisterMap UsedRegs;
+ RegisterNameMap RegNames;
+ FrameMap FrameSymbols;
+
+ PTXParamManager ParamManager;
public:
+ typedef DenseSet<unsigned>::const_iterator reg_iterator;
+
PTXMachineFunctionInfo(MachineFunction &MF)
- : is_kernel(false), reg_ret(PTX::NoRegister), _isDoneAddArg(false) {
- reg_arg.reserve(8);
- reg_local_var.reserve(32);
+ : IsKernel(false) {
+ UsedRegs[PTX::RegPredRegisterClass] = RegisterList();
+ UsedRegs[PTX::RegI16RegisterClass] = RegisterList();
+ UsedRegs[PTX::RegI32RegisterClass] = RegisterList();
+ UsedRegs[PTX::RegI64RegisterClass] = RegisterList();
+ UsedRegs[PTX::RegF32RegisterClass] = RegisterList();
+ UsedRegs[PTX::RegF64RegisterClass] = RegisterList();
}
- void setKernel(bool _is_kernel=true) { is_kernel = _is_kernel; }
-
- void addArgReg(unsigned reg) { reg_arg.push_back(reg); }
- void addLocalVarReg(unsigned reg) { reg_local_var.push_back(reg); }
- void addRetReg(unsigned reg) {
- if (!isRetReg(reg)) {
- reg_ret.push_back(reg);
+ /// getParamManager - Returns the PTXParamManager instance for this function.
+ PTXParamManager& getParamManager() { return ParamManager; }
+ const PTXParamManager& getParamManager() const { return ParamManager; }
+
+ /// setKernel/isKernel - Gets/sets a flag that indicates if this function is
+ /// a PTX kernel function.
+ void setKernel(bool _IsKernel=true) { IsKernel = _IsKernel; }
+ bool isKernel() const { return IsKernel; }
+
+ /// argreg_begin/argreg_end - Returns iterators to the set of registers
+ /// containing function arguments.
+ reg_iterator argreg_begin() const { return RegArgs.begin(); }
+ reg_iterator argreg_end() const { return RegArgs.end(); }
+
+ /// retreg_begin/retreg_end - Returns iterators to the set of registers
+ /// containing the function return values.
+ reg_iterator retreg_begin() const { return RegRets.begin(); }
+ reg_iterator retreg_end() const { return RegRets.end(); }
+
+ /// addRetReg - Adds a register to the set of return-value registers.
+ void addRetReg(unsigned Reg) {
+ if (!RegRets.count(Reg)) {
+ RegRets.insert(Reg);
+ std::string name;
+ name = "%ret";
+ name += utostr(RegRets.size() - 1);
+ RegNames[Reg] = name;
}
}
- void doneAddArg(void) {
- _isDoneAddArg = true;
+ /// addArgReg - Adds a register to the set of function argument registers.
+ void addArgReg(unsigned Reg) {
+ RegArgs.insert(Reg);
+ std::string name;
+ name = "%param";
+ name += utostr(RegArgs.size() - 1);
+ RegNames[Reg] = name;
}
- void doneAddLocalVar(void) {}
-
- bool isKernel() const { return is_kernel; }
- typedef std::vector<unsigned>::const_iterator reg_iterator;
- typedef std::vector<unsigned>::const_reverse_iterator reg_reverse_iterator;
- typedef std::vector<unsigned>::const_iterator ret_iterator;
-
- bool argRegEmpty() const { return reg_arg.empty(); }
- int getNumArg() const { return reg_arg.size(); }
- reg_iterator argRegBegin() const { return reg_arg.begin(); }
- reg_iterator argRegEnd() const { return reg_arg.end(); }
- reg_reverse_iterator argRegReverseBegin() const { return reg_arg.rbegin(); }
- reg_reverse_iterator argRegReverseEnd() const { return reg_arg.rend(); }
-
- bool localVarRegEmpty() const { return reg_local_var.empty(); }
- reg_iterator localVarRegBegin() const { return reg_local_var.begin(); }
- reg_iterator localVarRegEnd() const { return reg_local_var.end(); }
-
- bool retRegEmpty() const { return reg_ret.empty(); }
- int getNumRet() const { return reg_ret.size(); }
- ret_iterator retRegBegin() const { return reg_ret.begin(); }
- ret_iterator retRegEnd() const { return reg_ret.end(); }
+ /// addVirtualRegister - Adds a virtual register to the set of all used
+ /// registers in the function.
+ void addVirtualRegister(const TargetRegisterClass *TRC, unsigned Reg) {
+ std::string name;
+
+ // Do not count registers that are argument/return registers.
+ if (!RegRets.count(Reg) && !RegArgs.count(Reg)) {
+ UsedRegs[TRC].push_back(Reg);
+ if (TRC == PTX::RegPredRegisterClass)
+ name = "%p";
+ else if (TRC == PTX::RegI16RegisterClass)
+ name = "%rh";
+ else if (TRC == PTX::RegI32RegisterClass)
+ name = "%r";
+ else if (TRC == PTX::RegI64RegisterClass)
+ name = "%rd";
+ else if (TRC == PTX::RegF32RegisterClass)
+ name = "%f";
+ else if (TRC == PTX::RegF64RegisterClass)
+ name = "%fd";
+ else
+ llvm_unreachable("Invalid register class");
+
+ name += utostr(UsedRegs[TRC].size() - 1);
+ RegNames[Reg] = name;
+ }
+ }
- bool isArgReg(unsigned reg) const {
- return std::find(reg_arg.begin(), reg_arg.end(), reg) != reg_arg.end();
+ /// getRegisterName - Returns the name of the specified virtual register. This
+ /// name is used during PTX emission.
+ const char *getRegisterName(unsigned Reg) const {
+ if (RegNames.count(Reg))
+ return RegNames.find(Reg)->second.c_str();
+ else if (Reg == PTX::NoRegister)
+ return "%noreg";
+ else
+ llvm_unreachable("Register not in register name map");
}
- bool isRetReg(unsigned reg) const {
- return std::find(reg_ret.begin(), reg_ret.end(), reg) != reg_ret.end();
+ /// getNumRegistersForClass - Returns the number of virtual registers that are
+ /// used for the specified register class.
+ unsigned getNumRegistersForClass(const TargetRegisterClass *TRC) const {
+ return UsedRegs.lookup(TRC).size();
}
- bool isLocalVarReg(unsigned reg) const {
- return std::find(reg_local_var.begin(), reg_local_var.end(), reg)
- != reg_local_var.end();
+ /// getFrameSymbol - Returns the symbol name for the given FrameIndex.
+ const char* getFrameSymbol(int FrameIndex) {
+ if (FrameSymbols.count(FrameIndex)) {
+ return FrameSymbols.lookup(FrameIndex).c_str();
+ } else {
+ std::string Name = "__local";
+ Name += utostr(FrameIndex);
+ // The whole point of caching this name is to ensure the pointer we pass
+ // to any getExternalSymbol() calls will remain valid for the lifetime of
+ // the back-end instance. This is to work around an issue in SelectionDAG
+ // where symbol names are expected to be life-long strings.
+ FrameSymbols[FrameIndex] = Name;
+ return FrameSymbols[FrameIndex].c_str();
+ }
}
}; // class PTXMachineFunctionInfo
} // namespace llvm
diff --git a/lib/Target/PTX/PTXParamManager.cpp b/lib/Target/PTX/PTXParamManager.cpp
new file mode 100644
index 0000000..7753787
--- /dev/null
+++ b/lib/Target/PTX/PTXParamManager.cpp
@@ -0,0 +1,73 @@
+//===- PTXParamManager.cpp - Manager for .param variables -------*- 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 the PTXParamManager class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PTX.h"
+#include "PTXParamManager.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace llvm;
+
+PTXParamManager::PTXParamManager() {
+}
+
+unsigned PTXParamManager::addArgumentParam(unsigned Size) {
+ PTXParam Param;
+ Param.Type = PTX_PARAM_TYPE_ARGUMENT;
+ Param.Size = Size;
+
+ std::string Name;
+ Name = "__param_";
+ Name += utostr(ArgumentParams.size()+1);
+ Param.Name = Name;
+
+ unsigned Index = AllParams.size();
+ AllParams[Index] = Param;
+ ArgumentParams.push_back(Index);
+
+ return Index;
+}
+
+unsigned PTXParamManager::addReturnParam(unsigned Size) {
+ PTXParam Param;
+ Param.Type = PTX_PARAM_TYPE_RETURN;
+ Param.Size = Size;
+
+ std::string Name;
+ Name = "__ret_";
+ Name += utostr(ReturnParams.size()+1);
+ Param.Name = Name;
+
+ unsigned Index = AllParams.size();
+ AllParams[Index] = Param;
+ ReturnParams.push_back(Index);
+
+ return Index;
+}
+
+unsigned PTXParamManager::addLocalParam(unsigned Size) {
+ PTXParam Param;
+ Param.Type = PTX_PARAM_TYPE_LOCAL;
+ Param.Size = Size;
+
+ std::string Name;
+ Name = "__localparam_";
+ Name += utostr(LocalParams.size()+1);
+ Param.Name = Name;
+
+ unsigned Index = AllParams.size();
+ AllParams[Index] = Param;
+ LocalParams.push_back(Index);
+
+ return Index;
+}
+
diff --git a/lib/Target/PTX/PTXParamManager.h b/lib/Target/PTX/PTXParamManager.h
new file mode 100644
index 0000000..9fd2de5
--- /dev/null
+++ b/lib/Target/PTX/PTXParamManager.h
@@ -0,0 +1,86 @@
+//===- PTXParamManager.h - Manager for .param variables ----------*- 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 PTXParamManager class, which manages all defined .param
+// variables for a particular function.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PTX_PARAM_MANAGER_H
+#define PTX_PARAM_MANAGER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+
+/// PTXParamManager - This class manages all .param variables defined for a
+/// particular function.
+class PTXParamManager {
+private:
+
+ /// PTXParamType - Type of a .param variable
+ enum PTXParamType {
+ PTX_PARAM_TYPE_ARGUMENT,
+ PTX_PARAM_TYPE_RETURN,
+ PTX_PARAM_TYPE_LOCAL
+ };
+
+ /// PTXParam - Definition of a PTX .param variable
+ struct PTXParam {
+ PTXParamType Type;
+ unsigned Size;
+ std::string Name;
+ };
+
+ DenseMap<unsigned, PTXParam> AllParams;
+ SmallVector<unsigned, 4> ArgumentParams;
+ SmallVector<unsigned, 4> ReturnParams;
+ SmallVector<unsigned, 4> LocalParams;
+
+public:
+
+ typedef SmallVector<unsigned, 4>::const_iterator param_iterator;
+
+ PTXParamManager();
+
+ param_iterator arg_begin() const { return ArgumentParams.begin(); }
+ param_iterator arg_end() const { return ArgumentParams.end(); }
+ param_iterator ret_begin() const { return ReturnParams.begin(); }
+ param_iterator ret_end() const { return ReturnParams.end(); }
+ param_iterator local_begin() const { return LocalParams.begin(); }
+ param_iterator local_end() const { return LocalParams.end(); }
+
+ /// addArgumentParam - Returns a new .param used as an argument.
+ unsigned addArgumentParam(unsigned Size);
+
+ /// addReturnParam - Returns a new .param used as a return argument.
+ unsigned addReturnParam(unsigned Size);
+
+ /// addLocalParam - Returns a new .param used as a local .param variable.
+ unsigned addLocalParam(unsigned Size);
+
+ /// getParamName - Returns the name of the parameter as a string.
+ const std::string &getParamName(unsigned Param) const {
+ assert(AllParams.count(Param) == 1 && "Param has not been defined!");
+ return AllParams.find(Param)->second.Name;
+ }
+
+ /// getParamSize - Returns the size of the parameter in bits.
+ unsigned getParamSize(unsigned Param) const {
+ assert(AllParams.count(Param) == 1 && "Param has not been defined!");
+ return AllParams.find(Param)->second.Size;
+ }
+
+};
+
+}
+
+#endif
+
diff --git a/lib/Target/PTX/PTXRegAlloc.cpp b/lib/Target/PTX/PTXRegAlloc.cpp
new file mode 100644
index 0000000..2d2d5c3
--- /dev/null
+++ b/lib/Target/PTX/PTXRegAlloc.cpp
@@ -0,0 +1,58 @@
+//===-- PTXRegAlloc.cpp - PTX Register Allocator --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a register allocator for PTX code.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "ptx-reg-alloc"
+
+#include "PTX.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/RegAllocRegistry.h"
+
+using namespace llvm;
+
+namespace {
+ // Special register allocator for PTX.
+ class PTXRegAlloc : public MachineFunctionPass {
+ public:
+ static char ID;
+ PTXRegAlloc() : MachineFunctionPass(ID) {
+ initializePHIEliminationPass(*PassRegistry::getPassRegistry());
+ initializeTwoAddressInstructionPassPass(*PassRegistry::getPassRegistry());
+ }
+
+ virtual const char* getPassName() const {
+ return "PTX Register Allocator";
+ }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesCFG();
+ AU.addRequiredID(PHIEliminationID);
+ AU.addRequiredID(TwoAddressInstructionPassID);
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ virtual bool runOnMachineFunction(MachineFunction &MF) {
+ // We do not actually do anything (at least not yet).
+ return false;
+ }
+ };
+
+ char PTXRegAlloc::ID = 0;
+
+ static RegisterRegAlloc
+ ptxRegAlloc("ptx", "PTX register allocator", createPTXRegisterAllocator);
+}
+
+FunctionPass *llvm::createPTXRegisterAllocator() {
+ return new PTXRegAlloc();
+}
+
diff --git a/lib/Target/PTX/PTXRegisterInfo.cpp b/lib/Target/PTX/PTXRegisterInfo.cpp
index cb56ea9..c806266 100644
--- a/lib/Target/PTX/PTXRegisterInfo.cpp
+++ b/lib/Target/PTX/PTXRegisterInfo.cpp
@@ -14,6 +14,9 @@
#include "PTX.h"
#include "PTXRegisterInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -23,15 +26,23 @@
using namespace llvm;
PTXRegisterInfo::PTXRegisterInfo(PTXTargetMachine &TM,
- const TargetInstrInfo &TII)
- : PTXGenRegisterInfo() {
+ const TargetInstrInfo &tii)
+ // PTX does not have a return address register.
+ : PTXGenRegisterInfo(0), TII(tii) {
}
void PTXRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj,
RegScavenger *RS) const {
unsigned Index;
- MachineInstr& MI = *II;
+ MachineInstr &MI = *II;
+ //MachineBasicBlock &MBB = *MI.getParent();
+ //DebugLoc dl = MI.getDebugLoc();
+ //MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
+
+ //unsigned Reg = MRI.createVirtualRegister(PTX::RegF32RegisterClass);
+
+ llvm_unreachable("FrameIndex should have been previously eliminated!");
Index = 0;
while (!MI.getOperand(Index).isFI()) {
@@ -46,6 +57,18 @@ void PTXRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
DEBUG(dbgs() << "- SPAdj: " << SPAdj << "\n");
DEBUG(dbgs() << "- FrameIndex: " << FrameIndex << "\n");
+ //MachineInstr* MI2 = BuildMI(MBB, II, dl, TII.get(PTX::LOAD_LOCAL_F32))
+ //.addReg(Reg, RegState::Define).addImm(FrameIndex);
+ //if (MI2->findFirstPredOperandIdx() == -1) {
+ // MI2->addOperand(MachineOperand::CreateReg(PTX::NoRegister, /*IsDef=*/false));
+ // MI2->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL));
+ //}
+ //MI2->dump();
+
+ //MachineOperand ESOp = MachineOperand::CreateES("__local__");
+
// This frame index is post stack slot re-use assignments
+ //MI.getOperand(Index).ChangeToRegister(Reg, false);
MI.getOperand(Index).ChangeToImmediate(FrameIndex);
+ //MI.getOperand(Index) = ESOp;
}
diff --git a/lib/Target/PTX/PTXRegisterInfo.h b/lib/Target/PTX/PTXRegisterInfo.h
index 0b63cb6..55fafe4 100644
--- a/lib/Target/PTX/PTXRegisterInfo.h
+++ b/lib/Target/PTX/PTXRegisterInfo.h
@@ -25,8 +25,12 @@ class PTXTargetMachine;
class MachineFunction;
struct PTXRegisterInfo : public PTXGenRegisterInfo {
+private:
+ const TargetInstrInfo &TII;
+
+public:
PTXRegisterInfo(PTXTargetMachine &TM,
- const TargetInstrInfo &TII);
+ const TargetInstrInfo &tii);
virtual const unsigned
*getCalleeSavedRegs(const MachineFunction *MF = 0) const {
@@ -47,18 +51,6 @@ struct PTXRegisterInfo : public PTXGenRegisterInfo {
llvm_unreachable("PTX does not have a frame register");
return 0;
}
-
- virtual unsigned getRARegister() const {
- llvm_unreachable("PTX does not have a return address register");
- return 0;
- }
-
- virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const {
- return PTXGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
- }
- virtual int getLLVMRegNum(unsigned RegNum, bool isEH) const {
- return PTXGenRegisterInfo::getLLVMRegNumFull(RegNum, 0);
- }
}; // struct PTXRegisterInfo
} // namespace llvm
diff --git a/lib/Target/PTX/PTXRegisterInfo.td b/lib/Target/PTX/PTXRegisterInfo.td
index 1313d24..6ed6d3f 100644
--- a/lib/Target/PTX/PTXRegisterInfo.td
+++ b/lib/Target/PTX/PTXRegisterInfo.td
@@ -20,536 +20,18 @@ class PTXReg<string n> : Register<n> {
// Registers
//===----------------------------------------------------------------------===//
-///===- Predicate Registers -----------------------------------------------===//
-
-def P0 : PTXReg<"p0">;
-def P1 : PTXReg<"p1">;
-def P2 : PTXReg<"p2">;
-def P3 : PTXReg<"p3">;
-def P4 : PTXReg<"p4">;
-def P5 : PTXReg<"p5">;
-def P6 : PTXReg<"p6">;
-def P7 : PTXReg<"p7">;
-def P8 : PTXReg<"p8">;
-def P9 : PTXReg<"p9">;
-def P10 : PTXReg<"p10">;
-def P11 : PTXReg<"p11">;
-def P12 : PTXReg<"p12">;
-def P13 : PTXReg<"p13">;
-def P14 : PTXReg<"p14">;
-def P15 : PTXReg<"p15">;
-def P16 : PTXReg<"p16">;
-def P17 : PTXReg<"p17">;
-def P18 : PTXReg<"p18">;
-def P19 : PTXReg<"p19">;
-def P20 : PTXReg<"p20">;
-def P21 : PTXReg<"p21">;
-def P22 : PTXReg<"p22">;
-def P23 : PTXReg<"p23">;
-def P24 : PTXReg<"p24">;
-def P25 : PTXReg<"p25">;
-def P26 : PTXReg<"p26">;
-def P27 : PTXReg<"p27">;
-def P28 : PTXReg<"p28">;
-def P29 : PTXReg<"p29">;
-def P30 : PTXReg<"p30">;
-def P31 : PTXReg<"p31">;
-def P32 : PTXReg<"p32">;
-def P33 : PTXReg<"p33">;
-def P34 : PTXReg<"p34">;
-def P35 : PTXReg<"p35">;
-def P36 : PTXReg<"p36">;
-def P37 : PTXReg<"p37">;
-def P38 : PTXReg<"p38">;
-def P39 : PTXReg<"p39">;
-def P40 : PTXReg<"p40">;
-def P41 : PTXReg<"p41">;
-def P42 : PTXReg<"p42">;
-def P43 : PTXReg<"p43">;
-def P44 : PTXReg<"p44">;
-def P45 : PTXReg<"p45">;
-def P46 : PTXReg<"p46">;
-def P47 : PTXReg<"p47">;
-def P48 : PTXReg<"p48">;
-def P49 : PTXReg<"p49">;
-def P50 : PTXReg<"p50">;
-def P51 : PTXReg<"p51">;
-def P52 : PTXReg<"p52">;
-def P53 : PTXReg<"p53">;
-def P54 : PTXReg<"p54">;
-def P55 : PTXReg<"p55">;
-def P56 : PTXReg<"p56">;
-def P57 : PTXReg<"p57">;
-def P58 : PTXReg<"p58">;
-def P59 : PTXReg<"p59">;
-def P60 : PTXReg<"p60">;
-def P61 : PTXReg<"p61">;
-def P62 : PTXReg<"p62">;
-def P63 : PTXReg<"p63">;
-def P64 : PTXReg<"p64">;
-def P65 : PTXReg<"p65">;
-def P66 : PTXReg<"p66">;
-def P67 : PTXReg<"p67">;
-def P68 : PTXReg<"p68">;
-def P69 : PTXReg<"p69">;
-def P70 : PTXReg<"p70">;
-def P71 : PTXReg<"p71">;
-def P72 : PTXReg<"p72">;
-def P73 : PTXReg<"p73">;
-def P74 : PTXReg<"p74">;
-def P75 : PTXReg<"p75">;
-def P76 : PTXReg<"p76">;
-def P77 : PTXReg<"p77">;
-def P78 : PTXReg<"p78">;
-def P79 : PTXReg<"p79">;
-def P80 : PTXReg<"p80">;
-def P81 : PTXReg<"p81">;
-def P82 : PTXReg<"p82">;
-def P83 : PTXReg<"p83">;
-def P84 : PTXReg<"p84">;
-def P85 : PTXReg<"p85">;
-def P86 : PTXReg<"p86">;
-def P87 : PTXReg<"p87">;
-def P88 : PTXReg<"p88">;
-def P89 : PTXReg<"p89">;
-def P90 : PTXReg<"p90">;
-def P91 : PTXReg<"p91">;
-def P92 : PTXReg<"p92">;
-def P93 : PTXReg<"p93">;
-def P94 : PTXReg<"p94">;
-def P95 : PTXReg<"p95">;
-def P96 : PTXReg<"p96">;
-def P97 : PTXReg<"p97">;
-def P98 : PTXReg<"p98">;
-def P99 : PTXReg<"p99">;
-def P100 : PTXReg<"p100">;
-def P101 : PTXReg<"p101">;
-def P102 : PTXReg<"p102">;
-def P103 : PTXReg<"p103">;
-def P104 : PTXReg<"p104">;
-def P105 : PTXReg<"p105">;
-def P106 : PTXReg<"p106">;
-def P107 : PTXReg<"p107">;
-def P108 : PTXReg<"p108">;
-def P109 : PTXReg<"p109">;
-def P110 : PTXReg<"p110">;
-def P111 : PTXReg<"p111">;
-def P112 : PTXReg<"p112">;
-def P113 : PTXReg<"p113">;
-def P114 : PTXReg<"p114">;
-def P115 : PTXReg<"p115">;
-def P116 : PTXReg<"p116">;
-def P117 : PTXReg<"p117">;
-def P118 : PTXReg<"p118">;
-def P119 : PTXReg<"p119">;
-def P120 : PTXReg<"p120">;
-def P121 : PTXReg<"p121">;
-def P122 : PTXReg<"p122">;
-def P123 : PTXReg<"p123">;
-def P124 : PTXReg<"p124">;
-def P125 : PTXReg<"p125">;
-def P126 : PTXReg<"p126">;
-def P127 : PTXReg<"p127">;
-
-///===- 16-Bit Registers --------------------------------------------------===//
-
-def RH0 : PTXReg<"rh0">;
-def RH1 : PTXReg<"rh1">;
-def RH2 : PTXReg<"rh2">;
-def RH3 : PTXReg<"rh3">;
-def RH4 : PTXReg<"rh4">;
-def RH5 : PTXReg<"rh5">;
-def RH6 : PTXReg<"rh6">;
-def RH7 : PTXReg<"rh7">;
-def RH8 : PTXReg<"rh8">;
-def RH9 : PTXReg<"rh9">;
-def RH10 : PTXReg<"rh10">;
-def RH11 : PTXReg<"rh11">;
-def RH12 : PTXReg<"rh12">;
-def RH13 : PTXReg<"rh13">;
-def RH14 : PTXReg<"rh14">;
-def RH15 : PTXReg<"rh15">;
-def RH16 : PTXReg<"rh16">;
-def RH17 : PTXReg<"rh17">;
-def RH18 : PTXReg<"rh18">;
-def RH19 : PTXReg<"rh19">;
-def RH20 : PTXReg<"rh20">;
-def RH21 : PTXReg<"rh21">;
-def RH22 : PTXReg<"rh22">;
-def RH23 : PTXReg<"rh23">;
-def RH24 : PTXReg<"rh24">;
-def RH25 : PTXReg<"rh25">;
-def RH26 : PTXReg<"rh26">;
-def RH27 : PTXReg<"rh27">;
-def RH28 : PTXReg<"rh28">;
-def RH29 : PTXReg<"rh29">;
-def RH30 : PTXReg<"rh30">;
-def RH31 : PTXReg<"rh31">;
-def RH32 : PTXReg<"rh32">;
-def RH33 : PTXReg<"rh33">;
-def RH34 : PTXReg<"rh34">;
-def RH35 : PTXReg<"rh35">;
-def RH36 : PTXReg<"rh36">;
-def RH37 : PTXReg<"rh37">;
-def RH38 : PTXReg<"rh38">;
-def RH39 : PTXReg<"rh39">;
-def RH40 : PTXReg<"rh40">;
-def RH41 : PTXReg<"rh41">;
-def RH42 : PTXReg<"rh42">;
-def RH43 : PTXReg<"rh43">;
-def RH44 : PTXReg<"rh44">;
-def RH45 : PTXReg<"rh45">;
-def RH46 : PTXReg<"rh46">;
-def RH47 : PTXReg<"rh47">;
-def RH48 : PTXReg<"rh48">;
-def RH49 : PTXReg<"rh49">;
-def RH50 : PTXReg<"rh50">;
-def RH51 : PTXReg<"rh51">;
-def RH52 : PTXReg<"rh52">;
-def RH53 : PTXReg<"rh53">;
-def RH54 : PTXReg<"rh54">;
-def RH55 : PTXReg<"rh55">;
-def RH56 : PTXReg<"rh56">;
-def RH57 : PTXReg<"rh57">;
-def RH58 : PTXReg<"rh58">;
-def RH59 : PTXReg<"rh59">;
-def RH60 : PTXReg<"rh60">;
-def RH61 : PTXReg<"rh61">;
-def RH62 : PTXReg<"rh62">;
-def RH63 : PTXReg<"rh63">;
-def RH64 : PTXReg<"rh64">;
-def RH65 : PTXReg<"rh65">;
-def RH66 : PTXReg<"rh66">;
-def RH67 : PTXReg<"rh67">;
-def RH68 : PTXReg<"rh68">;
-def RH69 : PTXReg<"rh69">;
-def RH70 : PTXReg<"rh70">;
-def RH71 : PTXReg<"rh71">;
-def RH72 : PTXReg<"rh72">;
-def RH73 : PTXReg<"rh73">;
-def RH74 : PTXReg<"rh74">;
-def RH75 : PTXReg<"rh75">;
-def RH76 : PTXReg<"rh76">;
-def RH77 : PTXReg<"rh77">;
-def RH78 : PTXReg<"rh78">;
-def RH79 : PTXReg<"rh79">;
-def RH80 : PTXReg<"rh80">;
-def RH81 : PTXReg<"rh81">;
-def RH82 : PTXReg<"rh82">;
-def RH83 : PTXReg<"rh83">;
-def RH84 : PTXReg<"rh84">;
-def RH85 : PTXReg<"rh85">;
-def RH86 : PTXReg<"rh86">;
-def RH87 : PTXReg<"rh87">;
-def RH88 : PTXReg<"rh88">;
-def RH89 : PTXReg<"rh89">;
-def RH90 : PTXReg<"rh90">;
-def RH91 : PTXReg<"rh91">;
-def RH92 : PTXReg<"rh92">;
-def RH93 : PTXReg<"rh93">;
-def RH94 : PTXReg<"rh94">;
-def RH95 : PTXReg<"rh95">;
-def RH96 : PTXReg<"rh96">;
-def RH97 : PTXReg<"rh97">;
-def RH98 : PTXReg<"rh98">;
-def RH99 : PTXReg<"rh99">;
-def RH100 : PTXReg<"rh100">;
-def RH101 : PTXReg<"rh101">;
-def RH102 : PTXReg<"rh102">;
-def RH103 : PTXReg<"rh103">;
-def RH104 : PTXReg<"rh104">;
-def RH105 : PTXReg<"rh105">;
-def RH106 : PTXReg<"rh106">;
-def RH107 : PTXReg<"rh107">;
-def RH108 : PTXReg<"rh108">;
-def RH109 : PTXReg<"rh109">;
-def RH110 : PTXReg<"rh110">;
-def RH111 : PTXReg<"rh111">;
-def RH112 : PTXReg<"rh112">;
-def RH113 : PTXReg<"rh113">;
-def RH114 : PTXReg<"rh114">;
-def RH115 : PTXReg<"rh115">;
-def RH116 : PTXReg<"rh116">;
-def RH117 : PTXReg<"rh117">;
-def RH118 : PTXReg<"rh118">;
-def RH119 : PTXReg<"rh119">;
-def RH120 : PTXReg<"rh120">;
-def RH121 : PTXReg<"rh121">;
-def RH122 : PTXReg<"rh122">;
-def RH123 : PTXReg<"rh123">;
-def RH124 : PTXReg<"rh124">;
-def RH125 : PTXReg<"rh125">;
-def RH126 : PTXReg<"rh126">;
-def RH127 : PTXReg<"rh127">;
-
-///===- 32-Bit Registers --------------------------------------------------===//
-
-def R0 : PTXReg<"r0">;
-def R1 : PTXReg<"r1">;
-def R2 : PTXReg<"r2">;
-def R3 : PTXReg<"r3">;
-def R4 : PTXReg<"r4">;
-def R5 : PTXReg<"r5">;
-def R6 : PTXReg<"r6">;
-def R7 : PTXReg<"r7">;
-def R8 : PTXReg<"r8">;
-def R9 : PTXReg<"r9">;
-def R10 : PTXReg<"r10">;
-def R11 : PTXReg<"r11">;
-def R12 : PTXReg<"r12">;
-def R13 : PTXReg<"r13">;
-def R14 : PTXReg<"r14">;
-def R15 : PTXReg<"r15">;
-def R16 : PTXReg<"r16">;
-def R17 : PTXReg<"r17">;
-def R18 : PTXReg<"r18">;
-def R19 : PTXReg<"r19">;
-def R20 : PTXReg<"r20">;
-def R21 : PTXReg<"r21">;
-def R22 : PTXReg<"r22">;
-def R23 : PTXReg<"r23">;
-def R24 : PTXReg<"r24">;
-def R25 : PTXReg<"r25">;
-def R26 : PTXReg<"r26">;
-def R27 : PTXReg<"r27">;
-def R28 : PTXReg<"r28">;
-def R29 : PTXReg<"r29">;
-def R30 : PTXReg<"r30">;
-def R31 : PTXReg<"r31">;
-def R32 : PTXReg<"r32">;
-def R33 : PTXReg<"r33">;
-def R34 : PTXReg<"r34">;
-def R35 : PTXReg<"r35">;
-def R36 : PTXReg<"r36">;
-def R37 : PTXReg<"r37">;
-def R38 : PTXReg<"r38">;
-def R39 : PTXReg<"r39">;
-def R40 : PTXReg<"r40">;
-def R41 : PTXReg<"r41">;
-def R42 : PTXReg<"r42">;
-def R43 : PTXReg<"r43">;
-def R44 : PTXReg<"r44">;
-def R45 : PTXReg<"r45">;
-def R46 : PTXReg<"r46">;
-def R47 : PTXReg<"r47">;
-def R48 : PTXReg<"r48">;
-def R49 : PTXReg<"r49">;
-def R50 : PTXReg<"r50">;
-def R51 : PTXReg<"r51">;
-def R52 : PTXReg<"r52">;
-def R53 : PTXReg<"r53">;
-def R54 : PTXReg<"r54">;
-def R55 : PTXReg<"r55">;
-def R56 : PTXReg<"r56">;
-def R57 : PTXReg<"r57">;
-def R58 : PTXReg<"r58">;
-def R59 : PTXReg<"r59">;
-def R60 : PTXReg<"r60">;
-def R61 : PTXReg<"r61">;
-def R62 : PTXReg<"r62">;
-def R63 : PTXReg<"r63">;
-def R64 : PTXReg<"r64">;
-def R65 : PTXReg<"r65">;
-def R66 : PTXReg<"r66">;
-def R67 : PTXReg<"r67">;
-def R68 : PTXReg<"r68">;
-def R69 : PTXReg<"r69">;
-def R70 : PTXReg<"r70">;
-def R71 : PTXReg<"r71">;
-def R72 : PTXReg<"r72">;
-def R73 : PTXReg<"r73">;
-def R74 : PTXReg<"r74">;
-def R75 : PTXReg<"r75">;
-def R76 : PTXReg<"r76">;
-def R77 : PTXReg<"r77">;
-def R78 : PTXReg<"r78">;
-def R79 : PTXReg<"r79">;
-def R80 : PTXReg<"r80">;
-def R81 : PTXReg<"r81">;
-def R82 : PTXReg<"r82">;
-def R83 : PTXReg<"r83">;
-def R84 : PTXReg<"r84">;
-def R85 : PTXReg<"r85">;
-def R86 : PTXReg<"r86">;
-def R87 : PTXReg<"r87">;
-def R88 : PTXReg<"r88">;
-def R89 : PTXReg<"r89">;
-def R90 : PTXReg<"r90">;
-def R91 : PTXReg<"r91">;
-def R92 : PTXReg<"r92">;
-def R93 : PTXReg<"r93">;
-def R94 : PTXReg<"r94">;
-def R95 : PTXReg<"r95">;
-def R96 : PTXReg<"r96">;
-def R97 : PTXReg<"r97">;
-def R98 : PTXReg<"r98">;
-def R99 : PTXReg<"r99">;
-def R100 : PTXReg<"r100">;
-def R101 : PTXReg<"r101">;
-def R102 : PTXReg<"r102">;
-def R103 : PTXReg<"r103">;
-def R104 : PTXReg<"r104">;
-def R105 : PTXReg<"r105">;
-def R106 : PTXReg<"r106">;
-def R107 : PTXReg<"r107">;
-def R108 : PTXReg<"r108">;
-def R109 : PTXReg<"r109">;
-def R110 : PTXReg<"r110">;
-def R111 : PTXReg<"r111">;
-def R112 : PTXReg<"r112">;
-def R113 : PTXReg<"r113">;
-def R114 : PTXReg<"r114">;
-def R115 : PTXReg<"r115">;
-def R116 : PTXReg<"r116">;
-def R117 : PTXReg<"r117">;
-def R118 : PTXReg<"r118">;
-def R119 : PTXReg<"r119">;
-def R120 : PTXReg<"r120">;
-def R121 : PTXReg<"r121">;
-def R122 : PTXReg<"r122">;
-def R123 : PTXReg<"r123">;
-def R124 : PTXReg<"r124">;
-def R125 : PTXReg<"r125">;
-def R126 : PTXReg<"r126">;
-def R127 : PTXReg<"r127">;
-
-///===- 64-Bit Registers --------------------------------------------------===//
-
-def RD0 : PTXReg<"rd0">;
-def RD1 : PTXReg<"rd1">;
-def RD2 : PTXReg<"rd2">;
-def RD3 : PTXReg<"rd3">;
-def RD4 : PTXReg<"rd4">;
-def RD5 : PTXReg<"rd5">;
-def RD6 : PTXReg<"rd6">;
-def RD7 : PTXReg<"rd7">;
-def RD8 : PTXReg<"rd8">;
-def RD9 : PTXReg<"rd9">;
-def RD10 : PTXReg<"rd10">;
-def RD11 : PTXReg<"rd11">;
-def RD12 : PTXReg<"rd12">;
-def RD13 : PTXReg<"rd13">;
-def RD14 : PTXReg<"rd14">;
-def RD15 : PTXReg<"rd15">;
-def RD16 : PTXReg<"rd16">;
-def RD17 : PTXReg<"rd17">;
-def RD18 : PTXReg<"rd18">;
-def RD19 : PTXReg<"rd19">;
-def RD20 : PTXReg<"rd20">;
-def RD21 : PTXReg<"rd21">;
-def RD22 : PTXReg<"rd22">;
-def RD23 : PTXReg<"rd23">;
-def RD24 : PTXReg<"rd24">;
-def RD25 : PTXReg<"rd25">;
-def RD26 : PTXReg<"rd26">;
-def RD27 : PTXReg<"rd27">;
-def RD28 : PTXReg<"rd28">;
-def RD29 : PTXReg<"rd29">;
-def RD30 : PTXReg<"rd30">;
-def RD31 : PTXReg<"rd31">;
-def RD32 : PTXReg<"rd32">;
-def RD33 : PTXReg<"rd33">;
-def RD34 : PTXReg<"rd34">;
-def RD35 : PTXReg<"rd35">;
-def RD36 : PTXReg<"rd36">;
-def RD37 : PTXReg<"rd37">;
-def RD38 : PTXReg<"rd38">;
-def RD39 : PTXReg<"rd39">;
-def RD40 : PTXReg<"rd40">;
-def RD41 : PTXReg<"rd41">;
-def RD42 : PTXReg<"rd42">;
-def RD43 : PTXReg<"rd43">;
-def RD44 : PTXReg<"rd44">;
-def RD45 : PTXReg<"rd45">;
-def RD46 : PTXReg<"rd46">;
-def RD47 : PTXReg<"rd47">;
-def RD48 : PTXReg<"rd48">;
-def RD49 : PTXReg<"rd49">;
-def RD50 : PTXReg<"rd50">;
-def RD51 : PTXReg<"rd51">;
-def RD52 : PTXReg<"rd52">;
-def RD53 : PTXReg<"rd53">;
-def RD54 : PTXReg<"rd54">;
-def RD55 : PTXReg<"rd55">;
-def RD56 : PTXReg<"rd56">;
-def RD57 : PTXReg<"rd57">;
-def RD58 : PTXReg<"rd58">;
-def RD59 : PTXReg<"rd59">;
-def RD60 : PTXReg<"rd60">;
-def RD61 : PTXReg<"rd61">;
-def RD62 : PTXReg<"rd62">;
-def RD63 : PTXReg<"rd63">;
-def RD64 : PTXReg<"rd64">;
-def RD65 : PTXReg<"rd65">;
-def RD66 : PTXReg<"rd66">;
-def RD67 : PTXReg<"rd67">;
-def RD68 : PTXReg<"rd68">;
-def RD69 : PTXReg<"rd69">;
-def RD70 : PTXReg<"rd70">;
-def RD71 : PTXReg<"rd71">;
-def RD72 : PTXReg<"rd72">;
-def RD73 : PTXReg<"rd73">;
-def RD74 : PTXReg<"rd74">;
-def RD75 : PTXReg<"rd75">;
-def RD76 : PTXReg<"rd76">;
-def RD77 : PTXReg<"rd77">;
-def RD78 : PTXReg<"rd78">;
-def RD79 : PTXReg<"rd79">;
-def RD80 : PTXReg<"rd80">;
-def RD81 : PTXReg<"rd81">;
-def RD82 : PTXReg<"rd82">;
-def RD83 : PTXReg<"rd83">;
-def RD84 : PTXReg<"rd84">;
-def RD85 : PTXReg<"rd85">;
-def RD86 : PTXReg<"rd86">;
-def RD87 : PTXReg<"rd87">;
-def RD88 : PTXReg<"rd88">;
-def RD89 : PTXReg<"rd89">;
-def RD90 : PTXReg<"rd90">;
-def RD91 : PTXReg<"rd91">;
-def RD92 : PTXReg<"rd92">;
-def RD93 : PTXReg<"rd93">;
-def RD94 : PTXReg<"rd94">;
-def RD95 : PTXReg<"rd95">;
-def RD96 : PTXReg<"rd96">;
-def RD97 : PTXReg<"rd97">;
-def RD98 : PTXReg<"rd98">;
-def RD99 : PTXReg<"rd99">;
-def RD100 : PTXReg<"rd100">;
-def RD101 : PTXReg<"rd101">;
-def RD102 : PTXReg<"rd102">;
-def RD103 : PTXReg<"rd103">;
-def RD104 : PTXReg<"rd104">;
-def RD105 : PTXReg<"rd105">;
-def RD106 : PTXReg<"rd106">;
-def RD107 : PTXReg<"rd107">;
-def RD108 : PTXReg<"rd108">;
-def RD109 : PTXReg<"rd109">;
-def RD110 : PTXReg<"rd110">;
-def RD111 : PTXReg<"rd111">;
-def RD112 : PTXReg<"rd112">;
-def RD113 : PTXReg<"rd113">;
-def RD114 : PTXReg<"rd114">;
-def RD115 : PTXReg<"rd115">;
-def RD116 : PTXReg<"rd116">;
-def RD117 : PTXReg<"rd117">;
-def RD118 : PTXReg<"rd118">;
-def RD119 : PTXReg<"rd119">;
-def RD120 : PTXReg<"rd120">;
-def RD121 : PTXReg<"rd121">;
-def RD122 : PTXReg<"rd122">;
-def RD123 : PTXReg<"rd123">;
-def RD124 : PTXReg<"rd124">;
-def RD125 : PTXReg<"rd125">;
-def RD126 : PTXReg<"rd126">;
-def RD127 : PTXReg<"rd127">;
+// The generated register info code throws warnings for empty register classes
+// (e.g. zero-length arrays), so we use a dummy register here just to prevent
+// these warnings.
+def DUMMY_REG : PTXReg<"R0">;
//===----------------------------------------------------------------------===//
// Register classes
//===----------------------------------------------------------------------===//
-def RegPred : RegisterClass<"PTX", [i1], 8, (sequence "P%u", 0, 127)>;
-def RegI16 : RegisterClass<"PTX", [i16], 16, (sequence "RH%u", 0, 127)>;
-def RegI32 : RegisterClass<"PTX", [i32], 32, (sequence "R%u", 0, 127)>;
-def RegI64 : RegisterClass<"PTX", [i64], 64, (sequence "RD%u", 0, 127)>;
-def RegF32 : RegisterClass<"PTX", [f32], 32, (sequence "R%u", 0, 127)>;
-def RegF64 : RegisterClass<"PTX", [f64], 64, (sequence "RD%u", 0, 127)>;
+def RegPred : RegisterClass<"PTX", [i1], 8, (add DUMMY_REG)>;
+def RegI16 : RegisterClass<"PTX", [i16], 16, (add DUMMY_REG)>;
+def RegI32 : RegisterClass<"PTX", [i32], 32, (add DUMMY_REG)>;
+def RegI64 : RegisterClass<"PTX", [i64], 64, (add DUMMY_REG)>;
+def RegF32 : RegisterClass<"PTX", [f32], 32, (add DUMMY_REG)>;
+def RegF64 : RegisterClass<"PTX", [f64], 64, (add DUMMY_REG)>;
+
diff --git a/lib/Target/PTX/PTXSelectionDAGInfo.cpp b/lib/Target/PTX/PTXSelectionDAGInfo.cpp
new file mode 100644
index 0000000..50ef14a
--- /dev/null
+++ b/lib/Target/PTX/PTXSelectionDAGInfo.cpp
@@ -0,0 +1,149 @@
+//===-- PTXSelectionDAGInfo.cpp - PTX SelectionDAG 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 the PTXSelectionDAGInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "ptx-selectiondag-info"
+#include "PTXTargetMachine.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+using namespace llvm;
+
+PTXSelectionDAGInfo::PTXSelectionDAGInfo(const TargetMachine &TM)
+ : TargetSelectionDAGInfo(TM),
+ Subtarget(&TM.getSubtarget<PTXSubtarget>()) {
+}
+
+PTXSelectionDAGInfo::~PTXSelectionDAGInfo() {
+}
+
+SDValue
+PTXSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
+ SDValue Chain,
+ SDValue Dst, SDValue Src,
+ SDValue Size, unsigned Align,
+ bool isVolatile, bool AlwaysInline,
+ MachinePointerInfo DstPtrInfo,
+ MachinePointerInfo SrcPtrInfo) const {
+ // Do repeated 4-byte loads and stores. To be improved.
+ // This requires 4-byte alignment.
+ if ((Align & 3) != 0)
+ return SDValue();
+ // This requires the copy size to be a constant, preferably
+ // within a subtarget-specific limit.
+ ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
+ if (!ConstantSize)
+ return SDValue();
+ uint64_t SizeVal = ConstantSize->getZExtValue();
+ // Always inline memcpys. In PTX, we do not have a C library that provides
+ // a memcpy function.
+ //if (!AlwaysInline)
+ // return SDValue();
+
+ unsigned BytesLeft = SizeVal & 3;
+ unsigned NumMemOps = SizeVal >> 2;
+ unsigned EmittedNumMemOps = 0;
+ EVT VT = MVT::i32;
+ unsigned VTSize = 4;
+ unsigned i = 0;
+ const unsigned MAX_LOADS_IN_LDM = 6;
+ SDValue TFOps[MAX_LOADS_IN_LDM];
+ SDValue Loads[MAX_LOADS_IN_LDM];
+ uint64_t SrcOff = 0, DstOff = 0;
+ EVT PointerType = Subtarget->is64Bit() ? MVT::i64 : MVT::i32;
+
+ // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the
+ // same number of stores. The loads and stores will get combined into
+ // ldm/stm later on.
+ while (EmittedNumMemOps < NumMemOps) {
+ for (i = 0;
+ i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
+ Loads[i] = DAG.getLoad(VT, dl, Chain,
+ DAG.getNode(ISD::ADD, dl, PointerType, Src,
+ DAG.getConstant(SrcOff, PointerType)),
+ SrcPtrInfo.getWithOffset(SrcOff), isVolatile,
+ false, 0);
+ TFOps[i] = Loads[i].getValue(1);
+ SrcOff += VTSize;
+ }
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
+
+ for (i = 0;
+ i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
+ TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
+ DAG.getNode(ISD::ADD, dl, PointerType, Dst,
+ DAG.getConstant(DstOff, PointerType)),
+ DstPtrInfo.getWithOffset(DstOff),
+ isVolatile, false, 0);
+ DstOff += VTSize;
+ }
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
+
+ EmittedNumMemOps += i;
+ }
+
+ if (BytesLeft == 0)
+ return Chain;
+
+ // Issue loads / stores for the trailing (1 - 3) bytes.
+ unsigned BytesLeftSave = BytesLeft;
+ i = 0;
+ while (BytesLeft) {
+ if (BytesLeft >= 2) {
+ VT = MVT::i16;
+ VTSize = 2;
+ } else {
+ VT = MVT::i8;
+ VTSize = 1;
+ }
+
+ Loads[i] = DAG.getLoad(VT, dl, Chain,
+ DAG.getNode(ISD::ADD, dl, PointerType, Src,
+ DAG.getConstant(SrcOff, PointerType)),
+ SrcPtrInfo.getWithOffset(SrcOff), false, false, 0);
+ TFOps[i] = Loads[i].getValue(1);
+ ++i;
+ SrcOff += VTSize;
+ BytesLeft -= VTSize;
+ }
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
+
+ i = 0;
+ BytesLeft = BytesLeftSave;
+ while (BytesLeft) {
+ if (BytesLeft >= 2) {
+ VT = MVT::i16;
+ VTSize = 2;
+ } else {
+ VT = MVT::i8;
+ VTSize = 1;
+ }
+
+ TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
+ DAG.getNode(ISD::ADD, dl, PointerType, Dst,
+ DAG.getConstant(DstOff, PointerType)),
+ DstPtrInfo.getWithOffset(DstOff), false, false, 0);
+ ++i;
+ DstOff += VTSize;
+ BytesLeft -= VTSize;
+ }
+ return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
+}
+
+SDValue PTXSelectionDAGInfo::
+EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl,
+ SDValue Chain, SDValue Dst,
+ SDValue Src, SDValue Size,
+ unsigned Align, bool isVolatile,
+ MachinePointerInfo DstPtrInfo) const {
+ llvm_unreachable("memset lowering not implemented for PTX yet");
+}
+
diff --git a/lib/Target/PTX/PTXSelectionDAGInfo.h b/lib/Target/PTX/PTXSelectionDAGInfo.h
new file mode 100644
index 0000000..e0c7167
--- /dev/null
+++ b/lib/Target/PTX/PTXSelectionDAGInfo.h
@@ -0,0 +1,53 @@
+//===-- PTXSelectionDAGInfo.h - PTX SelectionDAG 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 defines the PTX subclass for TargetSelectionDAGInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PTXSELECTIONDAGINFO_H
+#define PTXSELECTIONDAGINFO_H
+
+#include "llvm/Target/TargetSelectionDAGInfo.h"
+
+namespace llvm {
+
+/// PTXSelectionDAGInfo - TargetSelectionDAGInfo sub-class for the PTX target.
+/// At the moment, this is mostly just a copy of ARMSelectionDAGInfo.
+class PTXSelectionDAGInfo : public TargetSelectionDAGInfo {
+ /// Subtarget - Keep a pointer to the PTXSubtarget around so that we can
+ /// make the right decision when generating code for different targets.
+ const PTXSubtarget *Subtarget;
+
+public:
+ explicit PTXSelectionDAGInfo(const TargetMachine &TM);
+ ~PTXSelectionDAGInfo();
+
+ virtual
+ SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
+ SDValue Chain,
+ SDValue Dst, SDValue Src,
+ SDValue Size, unsigned Align,
+ bool isVolatile, bool AlwaysInline,
+ MachinePointerInfo DstPtrInfo,
+ MachinePointerInfo SrcPtrInfo) const;
+
+ virtual
+ SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl,
+ SDValue Chain,
+ SDValue Op1, SDValue Op2,
+ SDValue Op3, unsigned Align,
+ bool isVolatile,
+ MachinePointerInfo DstPtrInfo) const;
+};
+
+}
+
+#endif
+
diff --git a/lib/Target/PTX/PTXSubtarget.cpp b/lib/Target/PTX/PTXSubtarget.cpp
index 8ec646e..1eb57d2 100644
--- a/lib/Target/PTX/PTXSubtarget.cpp
+++ b/lib/Target/PTX/PTXSubtarget.cpp
@@ -14,7 +14,7 @@
#include "PTXSubtarget.h"
#include "PTX.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
diff --git a/lib/Target/PTX/PTXSubtarget.h b/lib/Target/PTX/PTXSubtarget.h
index 0921f1f..b946d7c 100644
--- a/lib/Target/PTX/PTXSubtarget.h
+++ b/lib/Target/PTX/PTXSubtarget.h
@@ -114,7 +114,16 @@ class StringRef;
(PTXTarget >= PTX_COMPUTE_2_0 && PTXTarget < PTX_LAST_COMPUTE);
}
- void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
+ bool callsAreHandled() const {
+ return (PTXTarget >= PTX_SM_2_0 && PTXTarget < PTX_LAST_SM) ||
+ (PTXTarget >= PTX_COMPUTE_2_0 && PTXTarget < PTX_LAST_COMPUTE);
+ }
+
+ bool emitPtrAttribute() const {
+ return PTXVersion >= PTX_VERSION_2_2;
+ }
+
+ void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
}; // class PTXSubtarget
} // namespace llvm
diff --git a/lib/Target/PTX/PTXTargetMachine.cpp b/lib/Target/PTX/PTXTargetMachine.cpp
index ab926e0..449a3d9 100644
--- a/lib/Target/PTX/PTXTargetMachine.cpp
+++ b/lib/Target/PTX/PTXTargetMachine.cpp
@@ -14,8 +14,32 @@
#include "PTX.h"
#include "PTXTargetMachine.h"
#include "llvm/PassManager.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFunctionAnalysis.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TargetRegistry.h"
+
using namespace llvm;
@@ -25,7 +49,7 @@ namespace llvm {
bool useCFI,
MCInstPrinter *InstPrint,
MCCodeEmitter *CE,
- TargetAsmBackend *TAB,
+ MCAsmBackend *MAB,
bool ShowInst);
}
@@ -43,34 +67,47 @@ namespace {
"e-p:32:32-i64:32:32-f64:32:32-v128:32:128-v64:32:64-n32:64";
const char* DataLayout64 =
"e-p:64:64-i64:32:32-f64:32:32-v128:32:128-v64:32:64-n32:64";
+
+ // Copied from LLVMTargetMachine.cpp
+ void printNoVerify(PassManagerBase &PM, const char *Banner) {
+ if (PrintMachineCode)
+ PM.add(createMachineFunctionPrinterPass(dbgs(), Banner));
+ }
+
+ void printAndVerify(PassManagerBase &PM,
+ const char *Banner) {
+ if (PrintMachineCode)
+ PM.add(createMachineFunctionPrinterPass(dbgs(), Banner));
+
+ //if (VerifyMachineCode)
+ // PM.add(createMachineVerifierPass(Banner));
+ }
}
// DataLayout and FrameLowering are filled with dummy data
PTXTargetMachine::PTXTargetMachine(const Target &T,
- const std::string &TT,
- const std::string &CPU,
- const std::string &FS,
+ StringRef TT, StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM,
bool is64Bit)
- : LLVMTargetMachine(T, TT, CPU, FS),
+ : LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
DataLayout(is64Bit ? DataLayout64 : DataLayout32),
Subtarget(TT, CPU, FS, is64Bit),
FrameLowering(Subtarget),
InstrInfo(*this),
+ TSInfo(*this),
TLInfo(*this) {
}
-PTX32TargetMachine::PTX32TargetMachine(const Target &T,
- const std::string& TT,
- const std::string& CPU,
- const std::string& FS)
- : PTXTargetMachine(T, TT, CPU, FS, false) {
+PTX32TargetMachine::PTX32TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : PTXTargetMachine(T, TT, CPU, FS, RM, CM, false) {
}
-PTX64TargetMachine::PTX64TargetMachine(const Target &T,
- const std::string& TT,
- const std::string& CPU,
- const std::string& FS)
- : PTXTargetMachine(T, TT, CPU, FS, true) {
+PTX64TargetMachine::PTX64TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : PTXTargetMachine(T, TT, CPU, FS, RM, CM, true) {
}
bool PTXTargetMachine::addInstSelector(PassManagerBase &PM,
@@ -82,6 +119,255 @@ bool PTXTargetMachine::addInstSelector(PassManagerBase &PM,
bool PTXTargetMachine::addPostRegAlloc(PassManagerBase &PM,
CodeGenOpt::Level OptLevel) {
// PTXMFInfoExtract must after register allocation!
+ //PM.add(createPTXMFInfoExtract(*this, OptLevel));
+ return false;
+}
+
+bool PTXTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
+ formatted_raw_ostream &Out,
+ CodeGenFileType FileType,
+ CodeGenOpt::Level OptLevel,
+ bool DisableVerify) {
+ // This is mostly based on LLVMTargetMachine::addPassesToEmitFile
+
+ // Add common CodeGen passes.
+ MCContext *Context = 0;
+ if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Context))
+ return true;
+ assert(Context != 0 && "Failed to get MCContext");
+
+ if (hasMCSaveTempLabels())
+ Context->setAllowTemporaryLabels(false);
+
+ const MCAsmInfo &MAI = *getMCAsmInfo();
+ const MCSubtargetInfo &STI = getSubtarget<MCSubtargetInfo>();
+ OwningPtr<MCStreamer> AsmStreamer;
+
+ switch (FileType) {
+ default: return true;
+ case CGFT_AssemblyFile: {
+ MCInstPrinter *InstPrinter =
+ getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI, STI);
+
+ // Create a code emitter if asked to show the encoding.
+ MCCodeEmitter *MCE = 0;
+ MCAsmBackend *MAB = 0;
+
+ MCStreamer *S = getTarget().createAsmStreamer(*Context, Out,
+ true, /* verbose asm */
+ hasMCUseLoc(),
+ hasMCUseCFI(),
+ InstPrinter,
+ MCE, MAB,
+ false /* show MC encoding */);
+ AsmStreamer.reset(S);
+ break;
+ }
+ case CGFT_ObjectFile: {
+ llvm_unreachable("Object file emission is not supported with PTX");
+ }
+ case CGFT_Null:
+ // The Null output is intended for use for performance analysis and testing,
+ // not real users.
+ AsmStreamer.reset(createNullStreamer(*Context));
+ break;
+ }
+
+ // MC Logging
+ //AsmStreamer.reset(createLoggingStreamer(AsmStreamer.take(), errs()));
+
+ // Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
+ FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer);
+ if (Printer == 0)
+ return true;
+
+ // If successful, createAsmPrinter took ownership of AsmStreamer.
+ AsmStreamer.take();
+
+ PM.add(Printer);
+
+ PM.add(createGCInfoDeleter());
+ return false;
+}
+
+bool PTXTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel,
+ bool DisableVerify,
+ MCContext *&OutContext) {
+ // Add standard LLVM codegen passes.
+ // This is derived from LLVMTargetMachine::addCommonCodeGenPasses, with some
+ // modifications for the PTX target.
+
+ // Standard LLVM-Level Passes.
+
+ // Basic AliasAnalysis support.
+ // 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());
+
+ // Before running any passes, run the verifier to determine if the input
+ // coming from the front-end and/or optimizer is valid.
+ if (!DisableVerify)
+ PM.add(createVerifierPass());
+
+ // Run loop strength reduction before anything else.
+ if (OptLevel != CodeGenOpt::None) {
+ PM.add(createLoopStrengthReducePass(getTargetLowering()));
+ //PM.add(createPrintFunctionPass("\n\n*** Code after LSR ***\n", &dbgs()));
+ }
+
+ PM.add(createGCLoweringPass());
+
+ // Make sure that no unreachable blocks are instruction selected.
+ PM.add(createUnreachableBlockEliminationPass());
+
+ PM.add(createLowerInvokePass(getTargetLowering()));
+ // The lower invoke pass may create unreachable code. Remove it.
+ PM.add(createUnreachableBlockEliminationPass());
+
+ if (OptLevel != CodeGenOpt::None)
+ PM.add(createCodeGenPreparePass(getTargetLowering()));
+
+ PM.add(createStackProtectorPass(getTargetLowering()));
+
+ addPreISel(PM, OptLevel);
+
+ //PM.add(createPrintFunctionPass("\n\n"
+ // "*** Final LLVM Code input to ISel ***\n",
+ // &dbgs()));
+
+ // All passes which modify the LLVM IR are now complete; run the verifier
+ // to ensure that the IR is valid.
+ if (!DisableVerify)
+ PM.add(createVerifierPass());
+
+ // Standard Lower-Level Passes.
+
+ // Install a MachineModuleInfo class, which is an immutable pass that holds
+ // all the per-module stuff we're generating, including MCContext.
+ MachineModuleInfo *MMI = new MachineModuleInfo(*getMCAsmInfo(),
+ *getRegisterInfo(),
+ &getTargetLowering()->getObjFileLowering());
+ PM.add(MMI);
+ OutContext = &MMI->getContext(); // Return the MCContext specifically by-ref.
+
+ // Set up a MachineFunction for the rest of CodeGen to work on.
+ PM.add(new MachineFunctionAnalysis(*this, OptLevel));
+
+ // Ask the target for an isel.
+ if (addInstSelector(PM, OptLevel))
+ return true;
+
+ // Print the instruction selected machine code...
+ printAndVerify(PM, "After Instruction Selection");
+
+ // Expand pseudo-instructions emitted by ISel.
+ PM.add(createExpandISelPseudosPass());
+
+ // Pre-ra tail duplication.
+ if (OptLevel != CodeGenOpt::None) {
+ PM.add(createTailDuplicatePass(true));
+ printAndVerify(PM, "After Pre-RegAlloc TailDuplicate");
+ }
+
+ // Optimize PHIs before DCE: removing dead PHI cycles may make more
+ // instructions dead.
+ if (OptLevel != CodeGenOpt::None)
+ PM.add(createOptimizePHIsPass());
+
+ // If the target requests it, assign local variables to stack slots relative
+ // to one another and simplify frame index references where possible.
+ PM.add(createLocalStackSlotAllocationPass());
+
+ if (OptLevel != CodeGenOpt::None) {
+ // With optimization, dead code should already be eliminated. However
+ // 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());
+ printAndVerify(PM, "After codegen DCE pass");
+
+ PM.add(createMachineLICMPass());
+ PM.add(createMachineCSEPass());
+ PM.add(createMachineSinkingPass());
+ printAndVerify(PM, "After Machine LICM, CSE and Sinking passes");
+
+ PM.add(createPeepholeOptimizerPass());
+ printAndVerify(PM, "After codegen peephole optimization pass");
+ }
+
+ // Run pre-ra passes.
+ if (addPreRegAlloc(PM, OptLevel))
+ printAndVerify(PM, "After PreRegAlloc passes");
+
+ // Perform register allocation.
+ PM.add(createPTXRegisterAllocator());
+ printAndVerify(PM, "After Register Allocation");
+
+ // Perform stack slot coloring and post-ra machine LICM.
+ if (OptLevel != CodeGenOpt::None) {
+ // FIXME: Re-enable coloring with register when it's capable of adding
+ // kill markers.
+ PM.add(createStackSlotColoringPass(false));
+
+ // FIXME: Post-RA LICM has asserts that fire on virtual registers.
+ // Run post-ra machine LICM to hoist reloads / remats.
+ //if (!DisablePostRAMachineLICM)
+ // PM.add(createMachineLICMPass(false));
+
+ printAndVerify(PM, "After StackSlotColoring and postra Machine LICM");
+ }
+
+ // Run post-ra passes.
+ if (addPostRegAlloc(PM, OptLevel))
+ printAndVerify(PM, "After PostRegAlloc passes");
+
+ PM.add(createExpandPostRAPseudosPass());
+ printAndVerify(PM, "After ExpandPostRAPseudos");
+
+ // Insert prolog/epilog code. Eliminate abstract frame index references...
+ PM.add(createPrologEpilogCodeInserter());
+ printAndVerify(PM, "After PrologEpilogCodeInserter");
+
+ // Run pre-sched2 passes.
+ if (addPreSched2(PM, OptLevel))
+ printAndVerify(PM, "After PreSched2 passes");
+
+ // Second pass scheduler.
+ if (OptLevel != CodeGenOpt::None) {
+ PM.add(createPostRAScheduler(OptLevel));
+ printAndVerify(PM, "After PostRAScheduler");
+ }
+
+ // Branch folding must be run after regalloc and prolog/epilog insertion.
+ if (OptLevel != CodeGenOpt::None) {
+ PM.add(createBranchFoldingPass(getEnableTailMergeDefault()));
+ printNoVerify(PM, "After BranchFolding");
+ }
+
+ // Tail duplication.
+ if (OptLevel != CodeGenOpt::None) {
+ PM.add(createTailDuplicatePass(false));
+ printNoVerify(PM, "After TailDuplicate");
+ }
+
+ PM.add(createGCMachineCodeAnalysisPass());
+
+ //if (PrintGCInfo)
+ // PM.add(createGCInfoPrinter(dbgs()));
+
+ if (OptLevel != CodeGenOpt::None) {
+ PM.add(createCodePlacementOptPass());
+ printNoVerify(PM, "After CodePlacementOpt");
+ }
+
+ if (addPreEmitPass(PM, OptLevel))
+ printNoVerify(PM, "After PreEmit passes");
+
PM.add(createPTXMFInfoExtract(*this, OptLevel));
+ PM.add(createPTXFPRoundingModePass(*this, OptLevel));
+
return false;
}
diff --git a/lib/Target/PTX/PTXTargetMachine.h b/lib/Target/PTX/PTXTargetMachine.h
index ae42153..5b7c82b 100644
--- a/lib/Target/PTX/PTXTargetMachine.h
+++ b/lib/Target/PTX/PTXTargetMachine.h
@@ -17,6 +17,7 @@
#include "PTXISelLowering.h"
#include "PTXInstrInfo.h"
#include "PTXFrameLowering.h"
+#include "PTXSelectionDAGInfo.h"
#include "PTXSubtarget.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameLowering.h"
@@ -25,15 +26,17 @@
namespace llvm {
class PTXTargetMachine : public LLVMTargetMachine {
private:
- const TargetData DataLayout;
- PTXSubtarget Subtarget; // has to be initialized before FrameLowering
- PTXFrameLowering FrameLowering;
- PTXInstrInfo InstrInfo;
- PTXTargetLowering TLInfo;
+ const TargetData DataLayout;
+ PTXSubtarget Subtarget; // has to be initialized before FrameLowering
+ PTXFrameLowering FrameLowering;
+ PTXInstrInfo InstrInfo;
+ PTXSelectionDAGInfo TSInfo;
+ PTXTargetLowering TLInfo;
public:
- PTXTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS,
+ PTXTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM,
bool is64Bit);
virtual const TargetData *getTargetData() const { return &DataLayout; }
@@ -49,27 +52,62 @@ class PTXTargetMachine : public LLVMTargetMachine {
virtual const PTXTargetLowering *getTargetLowering() const {
return &TLInfo; }
+ virtual const PTXSelectionDAGInfo* getSelectionDAGInfo() const {
+ return &TSInfo;
+ }
+
virtual const PTXSubtarget *getSubtargetImpl() const { return &Subtarget; }
virtual bool addInstSelector(PassManagerBase &PM,
CodeGenOpt::Level OptLevel);
virtual bool addPostRegAlloc(PassManagerBase &PM,
CodeGenOpt::Level OptLevel);
+
+ // We override this method to supply our own set of codegen passes.
+ virtual bool addPassesToEmitFile(PassManagerBase &,
+ formatted_raw_ostream &,
+ CodeGenFileType,
+ CodeGenOpt::Level,
+ bool = true);
+
+ // Emission of machine code through JITCodeEmitter is not supported.
+ virtual bool addPassesToEmitMachineCode(PassManagerBase &,
+ JITCodeEmitter &,
+ CodeGenOpt::Level,
+ bool = true) {
+ return true;
+ }
+
+ // Emission of machine code through MCJIT is not supported.
+ virtual bool addPassesToEmitMC(PassManagerBase &,
+ MCContext *&,
+ raw_ostream &,
+ CodeGenOpt::Level,
+ bool = true) {
+ return true;
+ }
+
+ private:
+
+ bool addCommonCodeGenPasses(PassManagerBase &, CodeGenOpt::Level,
+ bool DisableVerify, MCContext *&OutCtx);
}; // class PTXTargetMachine
class PTX32TargetMachine : public PTXTargetMachine {
public:
- PTX32TargetMachine(const Target &T, const std::string &TT,
- const std::string& CPU, const std::string& FS);
+ PTX32TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
}; // class PTX32TargetMachine
class PTX64TargetMachine : public PTXTargetMachine {
public:
- PTX64TargetMachine(const Target &T, const std::string &TT,
- const std::string& CPU, const std::string& FS);
+ PTX64TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
}; // class PTX32TargetMachine
} // namespace llvm
diff --git a/lib/Target/PTX/TargetInfo/CMakeLists.txt b/lib/Target/PTX/TargetInfo/CMakeLists.txt
index 4b09cf5..2366e45 100644
--- a/lib/Target/PTX/TargetInfo/CMakeLists.txt
+++ b/lib/Target/PTX/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMPTXInfo
PTXTargetInfo.cpp
)
-add_dependencies(LLVMPTXInfo PTXCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMPTXInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMPTXInfo PTXCommonTableGen)
diff --git a/lib/Target/PTX/TargetInfo/PTXTargetInfo.cpp b/lib/Target/PTX/TargetInfo/PTXTargetInfo.cpp
index 9df6c75..09a2735 100644
--- a/lib/Target/PTX/TargetInfo/PTXTargetInfo.cpp
+++ b/lib/Target/PTX/TargetInfo/PTXTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "PTX.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
diff --git a/lib/Target/PTX/generate-register-td.py b/lib/Target/PTX/generate-register-td.py
deleted file mode 100755
index 1528690..0000000
--- a/lib/Target/PTX/generate-register-td.py
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/usr/bin/env python
-##===- generate-register-td.py --------------------------------*-python-*--===##
-##
-## The LLVM Compiler Infrastructure
-##
-## This file is distributed under the University of Illinois Open Source
-## License. See LICENSE.TXT for details.
-##
-##===----------------------------------------------------------------------===##
-##
-## This file describes the PTX register file generator.
-##
-##===----------------------------------------------------------------------===##
-
-from sys import argv, exit, stdout
-
-
-if len(argv) != 5:
- print('Usage: generate-register-td.py <num_preds> <num_16> <num_32> <num_64>')
- exit(1)
-
-try:
- num_pred = int(argv[1])
- num_16bit = int(argv[2])
- num_32bit = int(argv[3])
- num_64bit = int(argv[4])
-except:
- print('ERROR: Invalid integer parameter')
- exit(1)
-
-## Print the register definition file
-td_file = open('PTXRegisterInfo.td', 'w')
-
-td_file.write('''
-//===- PTXRegisterInfo.td - PTX Register defs ----------------*- tblgen -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// Declarations that describe the PTX register file
-//===----------------------------------------------------------------------===//
-
-class PTXReg<string n> : Register<n> {
- let Namespace = "PTX";
-}
-
-//===----------------------------------------------------------------------===//
-// Registers
-//===----------------------------------------------------------------------===//
-''')
-
-
-# Print predicate registers
-td_file.write('\n///===- Predicate Registers -----------------------------------------------===//\n\n')
-for r in range(0, num_pred):
- td_file.write('def P%d : PTXReg<"p%d">;\n' % (r, r))
-
-# Print 16-bit registers
-td_file.write('\n///===- 16-Bit Registers --------------------------------------------------===//\n\n')
-for r in range(0, num_16bit):
- td_file.write('def RH%d : PTXReg<"rh%d">;\n' % (r, r))
-
-# Print 32-bit registers
-td_file.write('\n///===- 32-Bit Registers --------------------------------------------------===//\n\n')
-for r in range(0, num_32bit):
- td_file.write('def R%d : PTXReg<"r%d">;\n' % (r, r))
-
-# Print 64-bit registers
-td_file.write('\n///===- 64-Bit Registers --------------------------------------------------===//\n\n')
-for r in range(0, num_64bit):
- td_file.write('def RD%d : PTXReg<"rd%d">;\n' % (r, r))
-
-
-td_file.write('''
-//===----------------------------------------------------------------------===//
-// Register classes
-//===----------------------------------------------------------------------===//
-''')
-
-
-# Print register classes
-
-td_file.write('def RegPred : RegisterClass<"PTX", [i1], 8, (sequence "P%%u", 0, %d)>;\n' % (num_pred-1))
-td_file.write('def RegI16 : RegisterClass<"PTX", [i16], 16, (sequence "RH%%u", 0, %d)>;\n' % (num_16bit-1))
-td_file.write('def RegI32 : RegisterClass<"PTX", [i32], 32, (sequence "R%%u", 0, %d)>;\n' % (num_32bit-1))
-td_file.write('def RegI64 : RegisterClass<"PTX", [i64], 64, (sequence "RD%%u", 0, %d)>;\n' % (num_64bit-1))
-td_file.write('def RegF32 : RegisterClass<"PTX", [f32], 32, (sequence "R%%u", 0, %d)>;\n' % (num_32bit-1))
-td_file.write('def RegF64 : RegisterClass<"PTX", [f64], 64, (sequence "RD%%u", 0, %d)>;\n' % (num_64bit-1))
-
-
-td_file.close()
-
-## Now write the PTXCallingConv.td file
-td_file = open('PTXCallingConv.td', 'w')
-
-# Reserve 10% of the available registers for return values, and the other 90%
-# for parameters
-num_ret_pred = int(0.1 * num_pred)
-num_ret_16bit = int(0.1 * num_16bit)
-num_ret_32bit = int(0.1 * num_32bit)
-num_ret_64bit = int(0.1 * num_64bit)
-num_param_pred = num_pred - num_ret_pred
-num_param_16bit = num_16bit - num_ret_16bit
-num_param_32bit = num_32bit - num_ret_32bit
-num_param_64bit = num_64bit - num_ret_64bit
-
-param_regs_pred = [('P%d' % (i+num_ret_pred)) for i in range(0, num_param_pred)]
-ret_regs_pred = ['P%d' % i for i in range(0, num_ret_pred)]
-param_regs_16bit = [('RH%d' % (i+num_ret_16bit)) for i in range(0, num_param_16bit)]
-ret_regs_16bit = ['RH%d' % i for i in range(0, num_ret_16bit)]
-param_regs_32bit = [('R%d' % (i+num_ret_32bit)) for i in range(0, num_param_32bit)]
-ret_regs_32bit = ['R%d' % i for i in range(0, num_ret_32bit)]
-param_regs_64bit = [('RD%d' % (i+num_ret_64bit)) for i in range(0, num_param_64bit)]
-ret_regs_64bit = ['RD%d' % i for i in range(0, num_ret_64bit)]
-
-param_list_pred = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_pred)
-ret_list_pred = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_pred)
-param_list_16bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_16bit)
-ret_list_16bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_16bit)
-param_list_32bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_32bit)
-ret_list_32bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_32bit)
-param_list_64bit = reduce(lambda x, y: '%s, %s' % (x, y), param_regs_64bit)
-ret_list_64bit = reduce(lambda x, y: '%s, %s' % (x, y), ret_regs_64bit)
-
-td_file.write('''
-//===--- PTXCallingConv.td - Calling Conventions -----------*- tablegen -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This describes the calling conventions for the PTX architecture.
-//
-//===----------------------------------------------------------------------===//
-
-// PTX Formal Parameter Calling Convention
-def CC_PTX : CallingConv<[
- CCIfType<[i1], CCAssignToReg<[%s]>>,
- CCIfType<[i16], CCAssignToReg<[%s]>>,
- CCIfType<[i32,f32], CCAssignToReg<[%s]>>,
- CCIfType<[i64,f64], CCAssignToReg<[%s]>>
-]>;
-
-// PTX Return Value Calling Convention
-def RetCC_PTX : CallingConv<[
- CCIfType<[i1], CCAssignToReg<[%s]>>,
- CCIfType<[i16], CCAssignToReg<[%s]>>,
- CCIfType<[i32,f32], CCAssignToReg<[%s]>>,
- CCIfType<[i64,f64], CCAssignToReg<[%s]>>
-]>;
-''' % (param_list_pred, param_list_16bit, param_list_32bit, param_list_64bit,
- ret_list_pred, ret_list_16bit, ret_list_32bit, ret_list_64bit))
-
-
-td_file.close()
diff --git a/lib/Target/PowerPC/CMakeLists.txt b/lib/Target/PowerPC/CMakeLists.txt
index d1dda37..73b4aba 100644
--- a/lib/Target/PowerPC/CMakeLists.txt
+++ b/lib/Target/PowerPC/CMakeLists.txt
@@ -1,16 +1,16 @@
set(LLVM_TARGET_DEFINITIONS PPC.td)
-tablegen(PPCGenAsmWriter.inc -gen-asm-writer)
-tablegen(PPCGenCodeEmitter.inc -gen-emitter)
-tablegen(PPCGenMCCodeEmitter.inc -gen-emitter -mc-emitter)
-tablegen(PPCGenRegisterInfo.inc -gen-register-info)
-tablegen(PPCGenInstrInfo.inc -gen-instr-info)
-tablegen(PPCGenDAGISel.inc -gen-dag-isel)
-tablegen(PPCGenCallingConv.inc -gen-callingconv)
-tablegen(PPCGenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(PPCGenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(PPCGenCodeEmitter.inc -gen-emitter)
+llvm_tablegen(PPCGenMCCodeEmitter.inc -gen-emitter -mc-emitter)
+llvm_tablegen(PPCGenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(PPCGenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(PPCGenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(PPCGenCallingConv.inc -gen-callingconv)
+llvm_tablegen(PPCGenSubtargetInfo.inc -gen-subtarget)
+add_public_tablegen_target(PowerPCCommonTableGen)
add_llvm_target(PowerPCCodeGen
- PPCAsmBackend.cpp
PPCAsmPrinter.cpp
PPCBranchSelector.cpp
PPCCodeEmitter.cpp
@@ -20,15 +20,27 @@ add_llvm_target(PowerPCCodeGen
PPCISelLowering.cpp
PPCFrameLowering.cpp
PPCJITInfo.cpp
- PPCMCCodeEmitter.cpp
PPCMCInstLower.cpp
- PPCPredicates.cpp
PPCRegisterInfo.cpp
PPCSubtarget.cpp
PPCTargetMachine.cpp
PPCSelectionDAGInfo.cpp
)
+add_llvm_library_dependencies(LLVMPowerPCCodeGen
+ LLVMAnalysis
+ LLVMAsmPrinter
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMPowerPCAsmPrinter
+ LLVMPowerPCDesc
+ LLVMPowerPCInfo
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMTarget
+ )
+
add_subdirectory(InstPrinter)
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
diff --git a/lib/Target/PowerPC/InstPrinter/CMakeLists.txt b/lib/Target/PowerPC/InstPrinter/CMakeLists.txt
index 389ea77..1d857e2 100644
--- a/lib/Target/PowerPC/InstPrinter/CMakeLists.txt
+++ b/lib/Target/PowerPC/InstPrinter/CMakeLists.txt
@@ -3,4 +3,10 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/
add_llvm_library(LLVMPowerPCAsmPrinter
PPCInstPrinter.cpp
)
-add_dependencies(LLVMPowerPCAsmPrinter PowerPCCodeGenTable_gen)
+
+add_llvm_library_dependencies(LLVMPowerPCAsmPrinter
+ LLVMMC
+ LLVMSupport
+ )
+
+add_dependencies(LLVMPowerPCAsmPrinter PowerPCCommonTableGen)
diff --git a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
index 1a9bd76..b6a0835 100644
--- a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
+++ b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
@@ -13,7 +13,8 @@
#define DEBUG_TYPE "asm-printer"
#include "PPCInstPrinter.h"
-#include "PPCPredicates.h"
+#include "MCTargetDesc/PPCBaseInfo.h"
+#include "MCTargetDesc/PPCPredicates.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/raw_ostream.h"
@@ -30,7 +31,8 @@ void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
OS << getRegisterName(RegNo);
}
-void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
+void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
+ StringRef Annot) {
// Check for slwi/srwi mnemonics.
if (MI->getOpcode() == PPC::RLWINM) {
unsigned char SH = MI->getOperand(2).getImm();
@@ -49,6 +51,8 @@ void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
O << ", ";
printOperand(MI, 1, O);
O << ", " << (unsigned int)SH;
+
+ printAnnotation(O, Annot);
return;
}
}
@@ -59,6 +63,7 @@ void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
printOperand(MI, 0, O);
O << ", ";
printOperand(MI, 1, O);
+ printAnnotation(O, Annot);
return;
}
@@ -72,11 +77,13 @@ void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
O << ", ";
printOperand(MI, 1, O);
O << ", " << (unsigned int)SH;
+ printAnnotation(O, Annot);
return;
}
}
printInstruction(MI, O);
+ printAnnotation(O, Annot);
}
diff --git a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h
index d022a44..4ed4b76 100644
--- a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h
+++ b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h
@@ -32,7 +32,7 @@ public:
}
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
- virtual void printInst(const MCInst *MI, raw_ostream &O);
+ virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
virtual StringRef getOpcodeName(unsigned Opcode) const;
static const char *getInstructionName(unsigned Opcode);
diff --git a/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt b/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt
index a1b8166..c4041db 100644
--- a/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt
@@ -1,4 +1,16 @@
add_llvm_library(LLVMPowerPCDesc
+ PPCAsmBackend.cpp
PPCMCTargetDesc.cpp
PPCMCAsmInfo.cpp
+ PPCMCCodeEmitter.cpp
+ PPCPredicates.cpp
)
+
+add_llvm_library_dependencies(LLVMPowerPCDesc
+ LLVMMC
+ LLVMPowerPCAsmPrinter
+ LLVMPowerPCInfo
+ LLVMSupport
+ )
+
+add_dependencies(LLVMPowerPCDesc PowerPCCommonTableGen)
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
new file mode 100644
index 0000000..9f2fd6d
--- /dev/null
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
@@ -0,0 +1,191 @@
+//===-- PPCAsmBackend.cpp - PPC Assembler Backend -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmBackend.h"
+#include "MCTargetDesc/PPCMCTargetDesc.h"
+#include "MCTargetDesc/PPCFixupKinds.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCMachObjectWriter.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Object/MachOFormat.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
+using namespace llvm;
+
+static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("Unknown fixup kind!");
+ case FK_Data_1:
+ case FK_Data_2:
+ case FK_Data_4:
+ return Value;
+ case PPC::fixup_ppc_brcond14:
+ return Value & 0x3ffc;
+ case PPC::fixup_ppc_br24:
+ return Value & 0x3fffffc;
+#if 0
+ case PPC::fixup_ppc_hi16:
+ return (Value >> 16) & 0xffff;
+#endif
+ case PPC::fixup_ppc_ha16:
+ return ((Value >> 16) + ((Value & 0x8000) ? 1 : 0)) & 0xffff;
+ case PPC::fixup_ppc_lo16:
+ return Value & 0xffff;
+ }
+}
+
+namespace {
+class PPCMachObjectWriter : public MCMachObjectTargetWriter {
+public:
+ PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType,
+ uint32_t CPUSubtype)
+ : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {}
+
+ void RecordRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm, const MCAsmLayout &Layout,
+ const MCFragment *Fragment, const MCFixup &Fixup,
+ MCValue Target, uint64_t &FixedValue) {}
+};
+
+class PPCELFObjectWriter : public MCELFObjectTargetWriter {
+public:
+ PPCELFObjectWriter(bool Is64Bit, Triple::OSType OSType, uint16_t EMachine,
+ bool HasRelocationAddend, bool isLittleEndian)
+ : MCELFObjectTargetWriter(Is64Bit, OSType, EMachine, HasRelocationAddend) {}
+};
+
+class PPCAsmBackend : public MCAsmBackend {
+const Target &TheTarget;
+public:
+ PPCAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {}
+
+ unsigned getNumFixupKinds() const { return PPC::NumTargetFixupKinds; }
+
+ const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
+ const static MCFixupKindInfo Infos[PPC::NumTargetFixupKinds] = {
+ // name offset bits flags
+ { "fixup_ppc_br24", 6, 24, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_ppc_lo16", 16, 16, 0 },
+ { "fixup_ppc_ha16", 16, 16, 0 },
+ { "fixup_ppc_lo14", 16, 14, 0 }
+ };
+
+ if (Kind < FirstTargetFixupKind)
+ return MCAsmBackend::getFixupKindInfo(Kind);
+
+ assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
+ "Invalid kind!");
+ return Infos[Kind - FirstTargetFixupKind];
+ }
+
+ bool MayNeedRelaxation(const MCInst &Inst) const {
+ // FIXME.
+ return false;
+ }
+
+ void RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
+ // FIXME.
+ assert(0 && "RelaxInstruction() unimplemented");
+ }
+
+ bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
+ // FIXME: Zero fill for now. That's not right, but at least will get the
+ // section size right.
+ for (uint64_t i = 0; i != Count; ++i)
+ OW->Write8(0);
+ return true;
+ }
+
+ unsigned getPointerSize() const {
+ StringRef Name = TheTarget.getName();
+ if (Name == "ppc64") return 8;
+ assert(Name == "ppc32" && "Unknown target name!");
+ return 4;
+ }
+};
+} // end anonymous namespace
+
+
+// FIXME: This should be in a separate file.
+namespace {
+ class DarwinPPCAsmBackend : public PPCAsmBackend {
+ public:
+ DarwinPPCAsmBackend(const Target &T) : PPCAsmBackend(T) { }
+
+ void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
+ uint64_t Value) const {
+ assert(0 && "UNIMP");
+ }
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ bool is64 = getPointerSize() == 8;
+ return createMachObjectWriter(new PPCMachObjectWriter(
+ /*Is64Bit=*/is64,
+ (is64 ? object::mach::CTM_PowerPC64 :
+ object::mach::CTM_PowerPC),
+ object::mach::CSPPC_ALL),
+ OS, /*IsLittleEndian=*/false);
+ }
+
+ virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
+ return false;
+ }
+ };
+
+ class ELFPPCAsmBackend : public PPCAsmBackend {
+ Triple::OSType OSType;
+ public:
+ ELFPPCAsmBackend(const Target &T, Triple::OSType OSType) :
+ PPCAsmBackend(T), OSType(OSType) { }
+
+ void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
+ uint64_t Value) const {
+ Value = adjustFixupValue(Fixup.getKind(), Value);
+ if (!Value) return; // Doesn't change encoding.
+
+ unsigned Offset = Fixup.getOffset();
+
+ // For each byte of the fragment that the fixup touches, mask in the bits from
+ // the fixup value. The Value has been "split up" into the appropriate
+ // bitfields above.
+ for (unsigned i = 0; i != 4; ++i)
+ Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff);
+ }
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ bool is64 = getPointerSize() == 8;
+ return createELFObjectWriter(new PPCELFObjectWriter(
+ /*Is64Bit=*/is64,
+ OSType,
+ is64 ? ELF::EM_PPC64 : ELF::EM_PPC,
+ /*addend*/ true, /*isLittleEndian*/ false),
+ OS, /*IsLittleEndian=*/false);
+ }
+
+ virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
+ return false;
+ }
+ };
+
+} // end anonymous namespace
+
+
+
+
+MCAsmBackend *llvm::createPPCAsmBackend(const Target &T, StringRef TT) {
+ if (Triple(TT).isOSDarwin())
+ return new DarwinPPCAsmBackend(T);
+
+ return new ELFPPCAsmBackend(T, Triple(TT).getOS());
+}
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCBaseInfo.h b/lib/Target/PowerPC/MCTargetDesc/PPCBaseInfo.h
new file mode 100644
index 0000000..369bbdc
--- /dev/null
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCBaseInfo.h
@@ -0,0 +1,70 @@
+//===-- PPCBaseInfo.h - Top level definitions for PPC -------- --*- 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 small standalone helper functions and enum definitions for
+// the PPC target useful for the compiler back-end and the MC libraries.
+// As such, it deliberately does not include references to LLVM core
+// code gen types, passes, etc..
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PPCBASEINFO_H
+#define PPCBASEINFO_H
+
+#include "PPCMCTargetDesc.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace llvm {
+
+/// getPPCRegisterNumbering - Given the enum value for some register, e.g.
+/// PPC::F14, return the number that it corresponds to (e.g. 14).
+inline static unsigned getPPCRegisterNumbering(unsigned RegEnum) {
+ using namespace PPC;
+ switch (RegEnum) {
+ case 0: return 0;
+ case R0 : case X0 : case F0 : case V0 : case CR0: case CR0LT: return 0;
+ case R1 : case X1 : case F1 : case V1 : case CR1: case CR0GT: return 1;
+ case R2 : case X2 : case F2 : case V2 : case CR2: case CR0EQ: return 2;
+ case R3 : case X3 : case F3 : case V3 : case CR3: case CR0UN: return 3;
+ case R4 : case X4 : case F4 : case V4 : case CR4: case CR1LT: return 4;
+ case R5 : case X5 : case F5 : case V5 : case CR5: case CR1GT: return 5;
+ case R6 : case X6 : case F6 : case V6 : case CR6: case CR1EQ: return 6;
+ case R7 : case X7 : case F7 : case V7 : case CR7: case CR1UN: return 7;
+ case R8 : case X8 : case F8 : case V8 : case CR2LT: return 8;
+ case R9 : case X9 : case F9 : case V9 : case CR2GT: return 9;
+ case R10: case X10: case F10: case V10: case CR2EQ: return 10;
+ case R11: case X11: case F11: case V11: case CR2UN: return 11;
+ case R12: case X12: case F12: case V12: case CR3LT: return 12;
+ case R13: case X13: case F13: case V13: case CR3GT: return 13;
+ case R14: case X14: case F14: case V14: case CR3EQ: return 14;
+ case R15: case X15: case F15: case V15: case CR3UN: return 15;
+ case R16: case X16: case F16: case V16: case CR4LT: return 16;
+ case R17: case X17: case F17: case V17: case CR4GT: return 17;
+ case R18: case X18: case F18: case V18: case CR4EQ: return 18;
+ case R19: case X19: case F19: case V19: case CR4UN: return 19;
+ case R20: case X20: case F20: case V20: case CR5LT: return 20;
+ case R21: case X21: case F21: case V21: case CR5GT: return 21;
+ case R22: case X22: case F22: case V22: case CR5EQ: return 22;
+ case R23: case X23: case F23: case V23: case CR5UN: return 23;
+ case R24: case X24: case F24: case V24: case CR6LT: return 24;
+ case R25: case X25: case F25: case V25: case CR6GT: return 25;
+ case R26: case X26: case F26: case V26: case CR6EQ: return 26;
+ case R27: case X27: case F27: case V27: case CR6UN: return 27;
+ case R28: case X28: case F28: case V28: case CR7LT: return 28;
+ case R29: case X29: case F29: case V29: case CR7GT: return 29;
+ case R30: case X30: case F30: case V30: case CR7EQ: return 30;
+ case R31: case X31: case F31: case V31: case CR7UN: return 31;
+ default:
+ llvm_unreachable("Unhandled reg in PPCRegisterInfo::getRegisterNumbering!");
+ }
+}
+
+} // end namespace llvm;
+
+#endif
diff --git a/lib/Target/PowerPC/PPCFixupKinds.h b/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
index b3c889e..b3c889e 100644
--- a/lib/Target/PowerPC/PPCFixupKinds.h
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
index b6dca83..e9424d8 100644
--- a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
@@ -31,6 +31,10 @@ PPCMCAsmInfoDarwin::PPCMCAsmInfoDarwin(bool is64Bit) {
}
PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) {
+ if (is64Bit)
+ PointerSize = 8;
+ IsLittleEndian = false;
+
// ".comm align is in bytes but .align is pow-2."
AlignmentIsInBytes = false;
@@ -56,7 +60,7 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) {
ZeroDirective = "\t.space\t";
Data64bitsDirective = is64Bit ? "\t.quad\t" : 0;
- HasLCOMMDirective = true;
+ LCOMMDirectiveType = LCOMM::NoAlignment;
AssemblerDialect = 0; // Old-Style mnemonics.
}
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
new file mode 100644
index 0000000..262f97c3
--- /dev/null
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
@@ -0,0 +1,193 @@
+//===-- PPCMCCodeEmitter.cpp - Convert PPC code to machine code -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PPCMCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mccodeemitter"
+#include "MCTargetDesc/PPCBaseInfo.h"
+#include "MCTargetDesc/PPCFixupKinds.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace llvm;
+
+STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
+
+namespace {
+class PPCMCCodeEmitter : public MCCodeEmitter {
+ PPCMCCodeEmitter(const PPCMCCodeEmitter &); // DO NOT IMPLEMENT
+ void operator=(const PPCMCCodeEmitter &); // DO NOT IMPLEMENT
+
+public:
+ PPCMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
+ MCContext &ctx) {
+ }
+
+ ~PPCMCCodeEmitter() {}
+
+ unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getHA16Encoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getLO16Encoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getMachineOpValue - Return binary encoding of operand. If the machine
+ /// operand requires relocation, record the relocation and return zero.
+ unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ // getBinaryCodeForInstr - TableGen'erated function for getting the
+ // binary encoding for an instruction.
+ unsigned getBinaryCodeForInstr(const MCInst &MI,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+ void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ unsigned Bits = getBinaryCodeForInstr(MI, Fixups);
+
+ // Output the constant in big endian byte order.
+ for (unsigned i = 0; i != 4; ++i) {
+ OS << (char)(Bits >> 24);
+ Bits <<= 8;
+ }
+
+ ++MCNumEmitted; // Keep track of the # of mi's emitted.
+ }
+
+};
+
+} // end anonymous namespace
+
+MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new PPCMCCodeEmitter(MCII, STI, Ctx);
+}
+
+unsigned PPCMCCodeEmitter::
+getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
+
+ // Add a fixup for the branch target.
+ Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
+ (MCFixupKind)PPC::fixup_ppc_br24));
+ return 0;
+}
+
+unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
+
+ // Add a fixup for the branch target.
+ Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
+ (MCFixupKind)PPC::fixup_ppc_brcond14));
+ return 0;
+}
+
+unsigned PPCMCCodeEmitter::getHA16Encoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
+
+ // Add a fixup for the branch target.
+ Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
+ (MCFixupKind)PPC::fixup_ppc_ha16));
+ return 0;
+}
+
+unsigned PPCMCCodeEmitter::getLO16Encoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
+
+ // Add a fixup for the branch target.
+ Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
+ (MCFixupKind)PPC::fixup_ppc_lo16));
+ return 0;
+}
+
+unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // Encode (imm, reg) as a memri, which has the low 16-bits as the
+ // displacement and the next 5 bits as the register #.
+ assert(MI.getOperand(OpNo+1).isReg());
+ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 16;
+
+ const MCOperand &MO = MI.getOperand(OpNo);
+ if (MO.isImm())
+ return (getMachineOpValue(MI, MO, Fixups) & 0xFFFF) | RegBits;
+
+ // Add a fixup for the displacement field.
+ Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
+ (MCFixupKind)PPC::fixup_ppc_lo16));
+ return RegBits;
+}
+
+
+unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // Encode (imm, reg) as a memrix, which has the low 14-bits as the
+ // displacement and the next 5 bits as the register #.
+ assert(MI.getOperand(OpNo+1).isReg());
+ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 14;
+
+ const MCOperand &MO = MI.getOperand(OpNo);
+ if (MO.isImm())
+ return (getMachineOpValue(MI, MO, Fixups) & 0x3FFF) | RegBits;
+
+ // Add a fixup for the branch target.
+ Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
+ (MCFixupKind)PPC::fixup_ppc_lo14));
+ return RegBits;
+}
+
+
+unsigned PPCMCCodeEmitter::
+get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ assert((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MFOCRF) &&
+ (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
+ return 0x80 >> getPPCRegisterNumbering(MO.getReg());
+}
+
+
+unsigned PPCMCCodeEmitter::
+getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ if (MO.isReg()) {
+ // MTCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
+ // The GPR operand should come through here though.
+ assert((MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MFOCRF) ||
+ MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
+ return getPPCRegisterNumbering(MO.getReg());
+ }
+
+ assert(MO.isImm() &&
+ "Relocation required in an instruction that we cannot encode!");
+ return MO.getImm();
+}
+
+
+#include "PPCGenMCCodeEmitter.inc"
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index 02b887f..d5c8a9e 100644
--- a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -13,10 +13,14 @@
#include "PPCMCTargetDesc.h"
#include "PPCMCAsmInfo.h"
+#include "InstPrinter/PPCInstPrinter.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_MC_DESC
#include "PPCGenInstrInfo.inc"
@@ -35,11 +39,16 @@ static MCInstrInfo *createPPCMCInstrInfo() {
return X;
}
-extern "C" void LLVMInitializePowerPCMCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(ThePPC32Target, createPPCMCInstrInfo);
- TargetRegistry::RegisterMCInstrInfo(ThePPC64Target, createPPCMCInstrInfo);
-}
+static MCRegisterInfo *createPPCMCRegisterInfo(StringRef TT) {
+ Triple TheTriple(TT);
+ bool isPPC64 = (TheTriple.getArch() == Triple::ppc64);
+ unsigned Flavour = isPPC64 ? 0 : 1;
+ unsigned RA = isPPC64 ? PPC::LR8 : PPC::LR;
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitPPCMCRegisterInfo(X, RA, Flavour, Flavour);
+ return X;
+}
static MCSubtargetInfo *createPPCMCSubtargetInfo(StringRef TT, StringRef CPU,
StringRef FS) {
@@ -48,23 +57,95 @@ static MCSubtargetInfo *createPPCMCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-extern "C" void LLVMInitializePowerPCMCSubtargetInfo() {
+static MCAsmInfo *createPPCMCAsmInfo(const Target &T, StringRef TT) {
+ Triple TheTriple(TT);
+ bool isPPC64 = TheTriple.getArch() == Triple::ppc64;
+
+ MCAsmInfo *MAI;
+ if (TheTriple.isOSDarwin())
+ MAI = new PPCMCAsmInfoDarwin(isPPC64);
+ else
+ MAI = new PPCLinuxMCAsmInfo(isPPC64);
+
+ // Initial state of the frame pointer is R1.
+ MachineLocation Dst(MachineLocation::VirtualFP);
+ MachineLocation Src(PPC::R1, 0);
+ MAI->addInitialFrameState(0, Dst, Src);
+
+ return MAI;
+}
+
+static MCCodeGenInfo *createPPCMCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+
+ if (RM == Reloc::Default) {
+ Triple T(TT);
+ if (T.isOSDarwin())
+ RM = Reloc::DynamicNoPIC;
+ else
+ RM = Reloc::Static;
+ }
+ X->InitMCCodeGenInfo(RM, CM);
+ return X;
+}
+
+// This is duplicated code. Refactor this.
+static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
+ MCContext &Ctx, MCAsmBackend &MAB,
+ raw_ostream &OS,
+ MCCodeEmitter *Emitter,
+ bool RelaxAll,
+ bool NoExecStack) {
+ if (Triple(TT).isOSDarwin())
+ return createMachOStreamer(Ctx, MAB, OS, Emitter, RelaxAll);
+
+ return createELFStreamer(Ctx, MAB, OS, Emitter, RelaxAll, NoExecStack);
+}
+
+static MCInstPrinter *createPPCMCInstPrinter(const Target &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI) {
+ return new PPCInstPrinter(MAI, SyntaxVariant);
+}
+
+extern "C" void LLVMInitializePowerPCTargetMC() {
+ // Register the MC asm info.
+ RegisterMCAsmInfoFn C(ThePPC32Target, createPPCMCAsmInfo);
+ RegisterMCAsmInfoFn D(ThePPC64Target, createPPCMCAsmInfo);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(ThePPC32Target, createPPCMCCodeGenInfo);
+ TargetRegistry::RegisterMCCodeGenInfo(ThePPC64Target, createPPCMCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(ThePPC32Target, createPPCMCInstrInfo);
+ TargetRegistry::RegisterMCInstrInfo(ThePPC64Target, createPPCMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(ThePPC32Target, createPPCMCRegisterInfo);
+ TargetRegistry::RegisterMCRegInfo(ThePPC64Target, createPPCMCRegisterInfo);
+
+ // Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(ThePPC32Target,
createPPCMCSubtargetInfo);
TargetRegistry::RegisterMCSubtargetInfo(ThePPC64Target,
createPPCMCSubtargetInfo);
-}
-static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) {
- Triple TheTriple(TT);
- bool isPPC64 = TheTriple.getArch() == Triple::ppc64;
- if (TheTriple.isOSDarwin())
- return new PPCMCAsmInfoDarwin(isPPC64);
- return new PPCLinuxMCAsmInfo(isPPC64);
+ // Register the MC Code Emitter
+ TargetRegistry::RegisterMCCodeEmitter(ThePPC32Target, createPPCMCCodeEmitter);
+ TargetRegistry::RegisterMCCodeEmitter(ThePPC64Target, createPPCMCCodeEmitter);
-}
+ // Register the asm backend.
+ TargetRegistry::RegisterMCAsmBackend(ThePPC32Target, createPPCAsmBackend);
+ TargetRegistry::RegisterMCAsmBackend(ThePPC64Target, createPPCAsmBackend);
+
+ // Register the object streamer.
+ TargetRegistry::RegisterMCObjectStreamer(ThePPC32Target, createMCStreamer);
+ TargetRegistry::RegisterMCObjectStreamer(ThePPC64Target, createMCStreamer);
-extern "C" void LLVMInitializePowerPCMCAsmInfo() {
- RegisterMCAsmInfoFn C(ThePPC32Target, createMCAsmInfo);
- RegisterMCAsmInfoFn D(ThePPC64Target, createMCAsmInfo);
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(ThePPC32Target, createPPCMCInstPrinter);
+ TargetRegistry::RegisterMCInstPrinter(ThePPC64Target, createPPCMCInstPrinter);
}
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
index cee2350..e5bf2a9 100644
--- a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
@@ -15,6 +15,10 @@
#define PPCMCTARGETDESC_H
namespace llvm {
+class MCAsmBackend;
+class MCCodeEmitter;
+class MCContext;
+class MCInstrInfo;
class MCSubtargetInfo;
class Target;
class StringRef;
@@ -22,6 +26,12 @@ class StringRef;
extern Target ThePPC32Target;
extern Target ThePPC64Target;
+MCCodeEmitter *createPPCMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx);
+
+MCAsmBackend *createPPCAsmBackend(const Target &T, StringRef TT);
+
} // End llvm namespace
// Defines symbolic names for PowerPC registers. This defines a mapping from
diff --git a/lib/Target/PowerPC/PPCPredicates.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp
index 12bb0a1..12bb0a1 100644
--- a/lib/Target/PowerPC/PPCPredicates.cpp
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h b/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h
new file mode 100644
index 0000000..f872e86
--- /dev/null
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h
@@ -0,0 +1,37 @@
+//===-- PPCPredicates.h - PPC Branch Predicate Information ------*- 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 the PowerPC branch predicates.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_POWERPC_PPCPREDICATES_H
+#define LLVM_TARGET_POWERPC_PPCPREDICATES_H
+
+namespace llvm {
+namespace PPC {
+ /// Predicate - These are "(BI << 5) | BO" for various predicates.
+ enum Predicate {
+ PRED_ALWAYS = (0 << 5) | 20,
+ PRED_LT = (0 << 5) | 12,
+ PRED_LE = (1 << 5) | 4,
+ PRED_EQ = (2 << 5) | 12,
+ PRED_GE = (0 << 5) | 4,
+ PRED_GT = (1 << 5) | 12,
+ PRED_NE = (2 << 5) | 4,
+ PRED_UN = (3 << 5) | 12,
+ PRED_NU = (3 << 5) | 4
+ };
+
+ /// Invert the specified predicate. != -> ==, < -> >=.
+ Predicate InvertPredicate(Predicate Opcode);
+}
+}
+
+#endif
diff --git a/lib/Target/PowerPC/PPC.h b/lib/Target/PowerPC/PPC.h
index 7191dd1..5dc1863 100644
--- a/lib/Target/PowerPC/PPC.h
+++ b/lib/Target/PowerPC/PPC.h
@@ -15,6 +15,7 @@
#ifndef LLVM_TARGET_POWERPC_H
#define LLVM_TARGET_POWERPC_H
+#include "MCTargetDesc/PPCBaseInfo.h"
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include <string>
@@ -30,22 +31,12 @@ namespace llvm {
class MachineInstr;
class AsmPrinter;
class MCInst;
- class MCCodeEmitter;
- class MCContext;
- class MCInstrInfo;
- class MCSubtargetInfo;
class TargetMachine;
- class TargetAsmBackend;
FunctionPass *createPPCBranchSelectionPass();
FunctionPass *createPPCISelDag(PPCTargetMachine &TM);
FunctionPass *createPPCJITCodeEmitterPass(PPCTargetMachine &TM,
JITCodeEmitter &MCE);
- MCCodeEmitter *createPPCMCCodeEmitter(const MCInstrInfo &MCII,
- const MCSubtargetInfo &STI,
- MCContext &Ctx);
- TargetAsmBackend *createPPCAsmBackend(const Target &, const std::string &);
-
void LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
AsmPrinter &AP, bool isDarwin);
diff --git a/lib/Target/PowerPC/PPC.td b/lib/Target/PowerPC/PPC.td
index aabf494..2d5d302 100644
--- a/lib/Target/PowerPC/PPC.td
+++ b/lib/Target/PowerPC/PPC.td
@@ -43,9 +43,9 @@ def FeatureAltivec : SubtargetFeature<"altivec","HasAltivec", "true",
def FeatureGPUL : SubtargetFeature<"gpul","IsGigaProcessor", "true",
"Enable GPUL instructions">;
def FeatureFSqrt : SubtargetFeature<"fsqrt","HasFSQRT", "true",
- "Enable the fsqrt instruction">;
+ "Enable the fsqrt instruction">;
def FeatureSTFIWX : SubtargetFeature<"stfiwx","HasSTFIWX", "true",
- "Enable the stfiwx instruction">;
+ "Enable the stfiwx instruction">;
//===----------------------------------------------------------------------===//
// Register File Description
diff --git a/lib/Target/PowerPC/PPCAsmBackend.cpp b/lib/Target/PowerPC/PPCAsmBackend.cpp
deleted file mode 100644
index 4b8cbb7..0000000
--- a/lib/Target/PowerPC/PPCAsmBackend.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-//===-- PPCAsmBackend.cpp - PPC Assembler Backend -------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Target/TargetAsmBackend.h"
-#include "PPC.h"
-#include "PPCFixupKinds.h"
-#include "llvm/MC/MCMachObjectWriter.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Object/MachOFormat.h"
-#include "llvm/Target/TargetRegistry.h"
-using namespace llvm;
-
-namespace {
-class PPCMachObjectWriter : public MCMachObjectTargetWriter {
-public:
- PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType,
- uint32_t CPUSubtype)
- : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {}
-
- void RecordRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCFragment *Fragment, const MCFixup &Fixup,
- MCValue Target, uint64_t &FixedValue) {}
-};
-
-class PPCAsmBackend : public TargetAsmBackend {
-const Target &TheTarget;
-public:
- PPCAsmBackend(const Target &T) : TargetAsmBackend(), TheTarget(T) {}
-
- unsigned getNumFixupKinds() const { return PPC::NumTargetFixupKinds; }
-
- const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
- const static MCFixupKindInfo Infos[PPC::NumTargetFixupKinds] = {
- // name offset bits flags
- { "fixup_ppc_br24", 6, 24, MCFixupKindInfo::FKF_IsPCRel },
- { "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel },
- { "fixup_ppc_lo16", 16, 16, 0 },
- { "fixup_ppc_ha16", 16, 16, 0 },
- { "fixup_ppc_lo14", 16, 14, 0 }
- };
-
- if (Kind < FirstTargetFixupKind)
- return TargetAsmBackend::getFixupKindInfo(Kind);
-
- assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
- "Invalid kind!");
- return Infos[Kind - FirstTargetFixupKind];
- }
-
- bool MayNeedRelaxation(const MCInst &Inst) const {
- // FIXME.
- return false;
- }
-
- void RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
- // FIXME.
- assert(0 && "RelaxInstruction() unimplemented");
- }
-
- bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
- // FIXME: Zero fill for now. That's not right, but at least will get the
- // section size right.
- for (uint64_t i = 0; i != Count; ++i)
- OW->Write8(0);
- return true;
- }
-
- unsigned getPointerSize() const {
- StringRef Name = TheTarget.getName();
- if (Name == "ppc64") return 8;
- assert(Name == "ppc32" && "Unknown target name!");
- return 4;
- }
-};
-} // end anonymous namespace
-
-
-// FIXME: This should be in a separate file.
-namespace {
- class DarwinPPCAsmBackend : public PPCAsmBackend {
- public:
- DarwinPPCAsmBackend(const Target &T) : PPCAsmBackend(T) { }
-
- void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
- uint64_t Value) const {
- assert(0 && "UNIMP");
- }
-
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- bool is64 = getPointerSize() == 8;
- return createMachObjectWriter(new PPCMachObjectWriter(
- /*Is64Bit=*/is64,
- (is64 ? object::mach::CTM_PowerPC64 :
- object::mach::CTM_PowerPC),
- object::mach::CSPPC_ALL),
- OS, /*IsLittleEndian=*/false);
- }
-
- virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
- return false;
- }
- };
-} // end anonymous namespace
-
-
-
-
-TargetAsmBackend *llvm::createPPCAsmBackend(const Target &T,
- const std::string &TT) {
- if (Triple(TT).isOSDarwin())
- return new DarwinPPCAsmBackend(T);
-
- return 0;
-}
diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 9de2200..9528459 100644
--- a/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -18,9 +18,9 @@
#define DEBUG_TYPE "asmprinter"
#include "PPC.h"
-#include "PPCPredicates.h"
#include "PPCTargetMachine.h"
#include "PPCSubtarget.h"
+#include "MCTargetDesc/PPCPredicates.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
@@ -43,11 +43,11 @@
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
@@ -679,18 +679,8 @@ static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm,
return new PPCLinuxAsmPrinter(tm, Streamer);
}
-static MCInstPrinter *createPPCMCInstPrinter(const Target &T,
- unsigned SyntaxVariant,
- const MCAsmInfo &MAI) {
- return new PPCInstPrinter(MAI, SyntaxVariant);
-}
-
-
// Force static initialization.
extern "C" void LLVMInitializePowerPCAsmPrinter() {
TargetRegistry::RegisterAsmPrinter(ThePPC32Target, createPPCAsmPrinterPass);
TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass);
-
- TargetRegistry::RegisterMCInstPrinter(ThePPC32Target, createPPCMCInstPrinter);
- TargetRegistry::RegisterMCInstPrinter(ThePPC64Target, createPPCMCInstPrinter);
}
diff --git a/lib/Target/PowerPC/PPCBranchSelector.cpp b/lib/Target/PowerPC/PPCBranchSelector.cpp
index e161d23..475edf3 100644
--- a/lib/Target/PowerPC/PPCBranchSelector.cpp
+++ b/lib/Target/PowerPC/PPCBranchSelector.cpp
@@ -19,7 +19,7 @@
#include "PPC.h"
#include "PPCInstrBuilder.h"
#include "PPCInstrInfo.h"
-#include "PPCPredicates.h"
+#include "MCTargetDesc/PPCPredicates.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/Statistic.h"
diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp
index 42232a0..4a1f182 100644
--- a/lib/Target/PowerPC/PPCCodeEmitter.cpp
+++ b/lib/Target/PowerPC/PPCCodeEmitter.cpp
@@ -140,7 +140,7 @@ unsigned PPCCodeEmitter::get_crbitm_encoding(const MachineInstr &MI,
const MachineOperand &MO = MI.getOperand(OpNo);
assert((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MFOCRF) &&
(MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
- return 0x80 >> PPCRegisterInfo::getRegisterNumbering(MO.getReg());
+ return 0x80 >> getPPCRegisterNumbering(MO.getReg());
}
MachineRelocation PPCCodeEmitter::GetRelocation(const MachineOperand &MO,
@@ -250,7 +250,7 @@ unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI,
// The GPR operand should come through here though.
assert((MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MFOCRF) ||
MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
- return PPCRegisterInfo::getRegisterNumbering(MO.getReg());
+ return getPPCRegisterNumbering(MO.getReg());
}
assert(MO.isImm() &&
diff --git a/lib/Target/PowerPC/PPCFrameLowering.cpp b/lib/Target/PowerPC/PPCFrameLowering.cpp
index 375e000..7dead10 100644
--- a/lib/Target/PowerPC/PPCFrameLowering.cpp
+++ b/lib/Target/PowerPC/PPCFrameLowering.cpp
@@ -109,14 +109,14 @@ static void HandleVRSaveUpdate(MachineInstr *MI, const TargetInstrInfo &TII) {
for (MachineRegisterInfo::livein_iterator
I = MF->getRegInfo().livein_begin(),
E = MF->getRegInfo().livein_end(); I != E; ++I) {
- unsigned RegNo = PPCRegisterInfo::getRegisterNumbering(I->first);
+ unsigned RegNo = getPPCRegisterNumbering(I->first);
if (VRRegNo[RegNo] == I->first) // If this really is a vector reg.
UsedRegMask &= ~(1 << (31-RegNo)); // Doesn't need to be marked.
}
for (MachineRegisterInfo::liveout_iterator
I = MF->getRegInfo().liveout_begin(),
E = MF->getRegInfo().liveout_end(); I != E; ++I) {
- unsigned RegNo = PPCRegisterInfo::getRegisterNumbering(*I);
+ unsigned RegNo = getPPCRegisterNumbering(*I);
if (VRRegNo[RegNo] == *I) // If this really is a vector reg.
UsedRegMask &= ~(1 << (31-RegNo)); // Doesn't need to be marked.
}
@@ -712,13 +712,6 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
}
}
-void PPCFrameLowering::getInitialFrameState(std::vector<MachineMove> &Moves) const {
- // Initial state of the frame pointer is R1.
- MachineLocation Dst(MachineLocation::VirtualFP);
- MachineLocation Src(PPC::R1, 0);
- Moves.push_back(MachineMove(0, Dst, Src));
-}
-
static bool spillsCR(const MachineFunction &MF) {
const PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
return FuncInfo->isCRSpilled();
@@ -885,7 +878,7 @@ void PPCFrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF)
FFI->setObjectOffset(FI, LowerBound + FFI->getObjectOffset(FI));
}
- LowerBound -= (31 - PPCRegisterInfo::getRegisterNumbering(MinFPR) + 1) * 8;
+ LowerBound -= (31 - getPPCRegisterNumbering(MinFPR) + 1) * 8;
}
// Check whether the frame pointer register is allocated. If so, make sure it
@@ -919,8 +912,8 @@ void PPCFrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF)
}
unsigned MinReg =
- std::min<unsigned>(PPCRegisterInfo::getRegisterNumbering(MinGPR),
- PPCRegisterInfo::getRegisterNumbering(MinG8R));
+ std::min<unsigned>(getPPCRegisterNumbering(MinGPR),
+ getPPCRegisterNumbering(MinG8R));
if (Subtarget.isPPC64()) {
LowerBound -= (31 - MinReg + 1) * 8;
diff --git a/lib/Target/PowerPC/PPCFrameLowering.h b/lib/Target/PowerPC/PPCFrameLowering.h
index 0c18de1..20faa71 100644
--- a/lib/Target/PowerPC/PPCFrameLowering.h
+++ b/lib/Target/PowerPC/PPCFrameLowering.h
@@ -40,7 +40,6 @@ public:
bool hasFP(const MachineFunction &MF) const;
bool needsFP(const MachineFunction &MF) const;
- void getInitialFrameState(std::vector<MachineMove> &Moves) const;
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS = NULL) const;
diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 2176c02..6f204cc 100644
--- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -14,8 +14,8 @@
#define DEBUG_TYPE "ppc-codegen"
#include "PPC.h"
-#include "PPCPredicates.h"
#include "PPCTargetMachine.h"
+#include "MCTargetDesc/PPCPredicates.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index 9741a39..d6b8a9e 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -14,8 +14,8 @@
#include "PPCISelLowering.h"
#include "PPCMachineFunctionInfo.h"
#include "PPCPerfectShuffle.h"
-#include "PPCPredicates.h"
#include "PPCTargetMachine.h"
+#include "MCTargetDesc/PPCPredicates.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/VectorExtras.h"
#include "llvm/CodeGen/CallingConvLower.h"
@@ -211,7 +211,8 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
setOperationAction(ISD::TRAP, MVT::Other, Legal);
// TRAMPOLINE is custom lowered.
- setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom);
+ setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom);
+ setOperationAction(ISD::ADJUST_TRAMPOLINE, MVT::Other, Custom);
// VASTART needs to be custom lowered to use the VarArgsFrameIndex
setOperationAction(ISD::VASTART , MVT::Other, Custom);
@@ -365,7 +366,11 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
setOperationAction(ISD::BUILD_VECTOR, MVT::v4f32, Custom);
}
+ setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Expand);
+ setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Expand);
+
setBooleanContents(ZeroOrOneBooleanContent);
+ setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
if (TM.getSubtarget<PPCSubtarget>().isPPC64()) {
setStackPointerRegisterToSaveRestore(PPC::X1);
@@ -401,12 +406,14 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
if (PPCSubTarget.isDarwin())
setPrefFunctionAlignment(4);
+ setInsertFencesForAtomic(true);
+
computeRegisterProperties();
}
/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate
/// function arguments in the caller parameter area.
-unsigned PPCTargetLowering::getByValTypeAlignment(const Type *Ty) const {
+unsigned PPCTargetLowering::getByValTypeAlignment(Type *Ty) const {
const TargetMachine &TM = getTargetMachine();
// Darwin passes everything on 4 byte boundary.
if (TM.getSubtarget<PPCSubtarget>().isDarwin())
@@ -463,7 +470,7 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
}
}
-MVT::SimpleValueType PPCTargetLowering::getSetCCResultType(EVT VT) const {
+EVT PPCTargetLowering::getSetCCResultType(EVT VT) const {
return MVT::i32;
}
@@ -1368,8 +1375,13 @@ SDValue PPCTargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG,
return DAG.getLoad(VT, dl, InChain, Result, MachinePointerInfo(), false, false, 0);
}
-SDValue PPCTargetLowering::LowerTRAMPOLINE(SDValue Op,
- SelectionDAG &DAG) const {
+SDValue PPCTargetLowering::LowerADJUST_TRAMPOLINE(SDValue Op,
+ SelectionDAG &DAG) const {
+ return Op.getOperand(0);
+}
+
+SDValue PPCTargetLowering::LowerINIT_TRAMPOLINE(SDValue Op,
+ SelectionDAG &DAG) const {
SDValue Chain = Op.getOperand(0);
SDValue Trmp = Op.getOperand(1); // trampoline
SDValue FPtr = Op.getOperand(2); // nested function
@@ -1378,7 +1390,7 @@ SDValue PPCTargetLowering::LowerTRAMPOLINE(SDValue Op,
EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
bool isPPC64 = (PtrVT == MVT::i64);
- const Type *IntPtrTy =
+ Type *IntPtrTy =
DAG.getTargetLoweringInfo().getTargetData()->getIntPtrType(
*DAG.getContext());
@@ -1398,16 +1410,13 @@ SDValue PPCTargetLowering::LowerTRAMPOLINE(SDValue Op,
// Lower to a call to __trampoline_setup(Trmp, TrampSize, FPtr, ctx_reg)
std::pair<SDValue, SDValue> CallResult =
- LowerCallTo(Chain, Op.getValueType().getTypeForEVT(*DAG.getContext()),
+ LowerCallTo(Chain, Type::getVoidTy(*DAG.getContext()),
false, false, false, false, 0, CallingConv::C, false,
/*isReturnValueUsed=*/true,
DAG.getExternalSymbol("__trampoline_setup", PtrVT),
Args, DAG, dl);
- SDValue Ops[] =
- { CallResult.first, CallResult.second };
-
- return DAG.getMergeValues(Ops, 2, dl);
+ return CallResult.second;
}
SDValue PPCTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG,
@@ -2550,7 +2559,7 @@ unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag,
if (!DAG.getTarget().getSubtarget<PPCSubtarget>().isJITCodeModel()) {
unsigned OpFlags = 0;
if (DAG.getTarget().getRelocationModel() != Reloc::Static &&
- (!PPCSubTarget.getTargetTriple().isMacOSX() ||
+ (PPCSubTarget.getTargetTriple().isMacOSX() &&
PPCSubTarget.getTargetTriple().isMacOSXVersionLT(10, 5)) &&
(G->getGlobal()->isDeclaration() ||
G->getGlobal()->isWeakForLinker())) {
@@ -2574,7 +2583,7 @@ unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag,
unsigned char OpFlags = 0;
if (DAG.getTarget().getRelocationModel() != Reloc::Static &&
- (!PPCSubTarget.getTargetTriple().isMacOSX() ||
+ (PPCSubTarget.getTargetTriple().isMacOSX() &&
PPCSubTarget.getTargetTriple().isMacOSXVersionLT(10, 5))) {
// PC-relative references to external symbols should go through $stub,
// unless we're building with the leopard linker or later, which
@@ -2941,6 +2950,7 @@ PPCTargetLowering::LowerCall_SVR4(SDValue Chain, SDValue Callee,
SmallVector<TailCallArgumentInfo, 8> TailCallArguments;
SmallVector<SDValue, 8> MemOpChains;
+ bool seenFloatArg = false;
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, j = 0, e = ArgLocs.size();
i != e;
@@ -2985,6 +2995,7 @@ PPCTargetLowering::LowerCall_SVR4(SDValue Chain, SDValue Callee,
}
if (VA.isRegLoc()) {
+ seenFloatArg |= VA.getLocVT().isFloatingPoint();
// Put argument in a physical register.
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
} else {
@@ -3011,9 +3022,11 @@ PPCTargetLowering::LowerCall_SVR4(SDValue Chain, SDValue Callee,
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&MemOpChains[0], MemOpChains.size());
- // Set CR6 to true if this is a vararg call.
+ // Set CR6 to true if this is a vararg call with floating args passed in
+ // registers.
if (isVarArg) {
- SDValue SetCR(DAG.getMachineNode(PPC::CRSET, dl, MVT::i32), 0);
+ SDValue SetCR(DAG.getMachineNode(seenFloatArg ? PPC::CRSET : PPC::CRUNSET,
+ dl, MVT::i32), 0);
RegsToPass.push_back(std::make_pair(unsigned(PPC::CR1EQ), SetCR));
}
@@ -3403,6 +3416,17 @@ PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee,
Ins, InVals);
}
+bool
+PPCTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+ MachineFunction &MF, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ LLVMContext &Context) const {
+ SmallVector<CCValAssign, 16> RVLocs;
+ CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(),
+ RVLocs, Context);
+ return CCInfo.CheckReturn(Outs, RetCC_PPC);
+}
+
SDValue
PPCTargetLowering::LowerReturn(SDValue Chain,
CallingConv::ID CallConv, bool isVarArg,
@@ -4490,7 +4514,8 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::GlobalTLSAddress: llvm_unreachable("TLS not implemented for PPC");
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
case ISD::SETCC: return LowerSETCC(Op, DAG);
- case ISD::TRAMPOLINE: return LowerTRAMPOLINE(Op, DAG);
+ case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG);
+ case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG);
case ISD::VASTART:
return LowerVASTART(Op, DAG, PPCSubTarget);
@@ -5504,7 +5529,7 @@ PPCTargetLowering::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:
@@ -5634,7 +5659,7 @@ void PPCTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
// isLegalAddressingMode - Return true if the addressing mode represented
// by AM is legal for this target, for a load/store of the specified type.
bool PPCTargetLowering::isLegalAddressingMode(const AddrMode &AM,
- const Type *Ty) const {
+ Type *Ty) const {
// FIXME: PPC does not allow r+i addressing modes for vectors!
// PPC allows a sign-extended 16-bit immediate field.
@@ -5670,7 +5695,7 @@ bool PPCTargetLowering::isLegalAddressingMode(const AddrMode &AM,
/// isLegalAddressImmediate - Return true if the integer value can be used
/// as the offset of the target addressing mode for load / store of the
/// given type.
-bool PPCTargetLowering::isLegalAddressImmediate(int64_t V,const Type *Ty) const{
+bool PPCTargetLowering::isLegalAddressImmediate(int64_t V,Type *Ty) const{
// PPC allows a sign-extended 16-bit immediate field.
return (V > -(1 << 16) && V < (1 << 16)-1);
}
diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h
index 986b4e7..430e45e 100644
--- a/lib/Target/PowerPC/PPCISelLowering.h
+++ b/lib/Target/PowerPC/PPCISelLowering.h
@@ -246,7 +246,7 @@ namespace llvm {
virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; }
/// getSetCCResultType - Return the ISD::SETCC ValueType
- virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
+ virtual EVT getSetCCResultType(EVT VT) const;
/// getPreIndexedAddressParts - returns true by value, base pointer and
/// offset pointer and addressing mode by reference if the node's address
@@ -323,7 +323,7 @@ namespace llvm {
/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate
/// function arguments in the caller parameter area. This is the actual
/// alignment, not its logarithm.
- unsigned getByValTypeAlignment(const Type *Ty) const;
+ unsigned getByValTypeAlignment(Type *Ty) const;
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
/// vector. If it is invalid, don't add anything to Ops.
@@ -334,12 +334,12 @@ 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;
/// isLegalAddressImmediate - Return true if the integer value can be used
/// as the offset of the target addressing mode for load / store of the
/// given type.
- virtual bool isLegalAddressImmediate(int64_t V, const Type *Ty) const;
+ virtual bool isLegalAddressImmediate(int64_t V, Type *Ty) const;
/// isLegalAddressImmediate - Return true if the GlobalValue can be used as
/// the offset of the target addressing mode.
@@ -390,7 +390,8 @@ namespace llvm {
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
- SDValue LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG,
const PPCSubtarget &Subtarget) const;
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG,
@@ -444,6 +445,12 @@ namespace llvm {
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const;
+ virtual bool
+ CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ LLVMContext &Context) const;
+
virtual SDValue
LowerReturn(SDValue Chain,
CallingConv::ID CallConv, bool isVarArg,
diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp
index 143444f..2bc109c 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -15,18 +15,18 @@
#include "PPC.h"
#include "PPCInstrBuilder.h"
#include "PPCMachineFunctionInfo.h"
-#include "PPCPredicates.h"
#include "PPCTargetMachine.h"
#include "PPCHazardRecognizers.h"
+#include "MCTargetDesc/PPCPredicates.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/STLExtras.h"
@@ -334,7 +334,7 @@ PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF,
const TargetRegisterClass *RC,
SmallVectorImpl<MachineInstr*> &NewMIs) const{
DebugLoc DL;
- if (RC == PPC::GPRCRegisterClass) {
+ if (PPC::GPRCRegisterClass->hasSubClassEq(RC)) {
if (SrcReg != PPC::LR) {
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STW))
.addReg(SrcReg,
@@ -350,7 +350,7 @@ PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF,
getKillRegState(isKill)),
FrameIdx));
}
- } else if (RC == PPC::G8RCRegisterClass) {
+ } else if (PPC::G8RCRegisterClass->hasSubClassEq(RC)) {
if (SrcReg != PPC::LR8) {
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STD))
.addReg(SrcReg,
@@ -366,17 +366,17 @@ PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF,
getKillRegState(isKill)),
FrameIdx));
}
- } else if (RC == PPC::F8RCRegisterClass) {
+ } else if (PPC::F8RCRegisterClass->hasSubClassEq(RC)) {
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFD))
.addReg(SrcReg,
getKillRegState(isKill)),
FrameIdx));
- } else if (RC == PPC::F4RCRegisterClass) {
+ } else if (PPC::F4RCRegisterClass->hasSubClassEq(RC)) {
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFS))
.addReg(SrcReg,
getKillRegState(isKill)),
FrameIdx));
- } else if (RC == PPC::CRRCRegisterClass) {
+ } else if (PPC::CRRCRegisterClass->hasSubClassEq(RC)) {
if ((EnablePPC32RS && !TM.getSubtargetImpl()->isPPC64()) ||
(EnablePPC64RS && TM.getSubtargetImpl()->isPPC64())) {
// FIXME (64-bit): Enable
@@ -402,7 +402,7 @@ PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF,
// If the saved register wasn't CR0, shift the bits left so that they are
// in CR0's slot.
if (SrcReg != PPC::CR0) {
- unsigned ShiftBits = PPCRegisterInfo::getRegisterNumbering(SrcReg)*4;
+ unsigned ShiftBits = getPPCRegisterNumbering(SrcReg)*4;
// rlwinm scratch, scratch, ShiftBits, 0, 31.
NewMIs.push_back(BuildMI(MF, DL, get(PPC::RLWINM), ScratchReg)
.addReg(ScratchReg).addImm(ShiftBits)
@@ -414,7 +414,7 @@ PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF,
getKillRegState(isKill)),
FrameIdx));
}
- } else if (RC == PPC::CRBITRCRegisterClass) {
+ } else if (PPC::CRBITRCRegisterClass->hasSubClassEq(RC)) {
// FIXME: We use CRi here because there is no mtcrf on a bit. Since the
// backend currently only uses CR1EQ as an individual bit, this should
// not cause any bug. If we need other uses of CR bits, the following
@@ -448,7 +448,7 @@ PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF,
return StoreRegToStackSlot(MF, Reg, isKill, FrameIdx,
PPC::CRRCRegisterClass, NewMIs);
- } else if (RC == PPC::VRRCRegisterClass) {
+ } else if (PPC::VRRCRegisterClass->hasSubClassEq(RC)) {
// We don't have indexed addressing for vector loads. Emit:
// R0 = ADDI FI#
// STVX VAL, 0, R0
@@ -499,7 +499,7 @@ PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL,
unsigned DestReg, int FrameIdx,
const TargetRegisterClass *RC,
SmallVectorImpl<MachineInstr*> &NewMIs)const{
- if (RC == PPC::GPRCRegisterClass) {
+ if (PPC::GPRCRegisterClass->hasSubClassEq(RC)) {
if (DestReg != PPC::LR) {
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LWZ),
DestReg), FrameIdx));
@@ -508,7 +508,7 @@ PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL,
PPC::R11), FrameIdx));
NewMIs.push_back(BuildMI(MF, DL, get(PPC::MTLR)).addReg(PPC::R11));
}
- } else if (RC == PPC::G8RCRegisterClass) {
+ } else if (PPC::G8RCRegisterClass->hasSubClassEq(RC)) {
if (DestReg != PPC::LR8) {
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LD), DestReg),
FrameIdx));
@@ -517,13 +517,13 @@ PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL,
PPC::R11), FrameIdx));
NewMIs.push_back(BuildMI(MF, DL, get(PPC::MTLR8)).addReg(PPC::R11));
}
- } else if (RC == PPC::F8RCRegisterClass) {
+ } else if (PPC::F8RCRegisterClass->hasSubClassEq(RC)) {
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LFD), DestReg),
FrameIdx));
- } else if (RC == PPC::F4RCRegisterClass) {
+ } else if (PPC::F4RCRegisterClass->hasSubClassEq(RC)) {
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LFS), DestReg),
FrameIdx));
- } else if (RC == PPC::CRRCRegisterClass) {
+ } else if (PPC::CRRCRegisterClass->hasSubClassEq(RC)) {
// FIXME: We need a scatch reg here. The trouble with using R0 is that
// it's possible for the stack frame to be so big the save location is
// out of range of immediate offsets, necessitating another register.
@@ -537,7 +537,7 @@ PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL,
// If the reloaded register isn't CR0, shift the bits right so that they are
// in the right CR's slot.
if (DestReg != PPC::CR0) {
- unsigned ShiftBits = PPCRegisterInfo::getRegisterNumbering(DestReg)*4;
+ unsigned ShiftBits = getPPCRegisterNumbering(DestReg)*4;
// rlwinm r11, r11, 32-ShiftBits, 0, 31.
NewMIs.push_back(BuildMI(MF, DL, get(PPC::RLWINM), ScratchReg)
.addReg(ScratchReg).addImm(32-ShiftBits).addImm(0)
@@ -546,7 +546,7 @@ PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL,
NewMIs.push_back(BuildMI(MF, DL, get(PPC::MTCRF), DestReg)
.addReg(ScratchReg));
- } else if (RC == PPC::CRBITRCRegisterClass) {
+ } else if (PPC::CRBITRCRegisterClass->hasSubClassEq(RC)) {
unsigned Reg = 0;
if (DestReg == PPC::CR0LT || DestReg == PPC::CR0GT ||
@@ -577,7 +577,7 @@ PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL,
return LoadRegFromStackSlot(MF, DL, Reg, FrameIdx,
PPC::CRRCRegisterClass, NewMIs);
- } else if (RC == PPC::VRRCRegisterClass) {
+ } else if (PPC::VRRCRegisterClass->hasSubClassEq(RC)) {
// We don't have indexed addressing for vector loads. Emit:
// R0 = ADDI FI#
// Dest = LVX 0, R0
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index 773578c..f248b5b 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/lib/Target/PowerPC/PPCInstrInfo.td
@@ -1053,6 +1053,10 @@ def CRSET : XLForm_1_ext<19, 289, (outs CRBITRC:$dst), (ins),
"creqv $dst, $dst, $dst", BrCR,
[]>;
+def CRUNSET: XLForm_1_ext<19, 193, (outs CRBITRC:$dst), (ins),
+ "crxor $dst, $dst, $dst", BrCR,
+ []>;
+
// XFX-Form instructions. Instructions that deal with SPRs.
//
let Uses = [CTR] in {
@@ -1472,5 +1476,7 @@ def : Pat<(membarrier (i32 imm /*ll*/),
(i32 imm /*device*/)),
(SYNC)>;
+def : Pat<(atomic_fence (imm), (imm)), (SYNC)>;
+
include "PPCInstrAltivec.td"
include "PPCInstr64Bit.td"
diff --git a/lib/Target/PowerPC/PPCMCCodeEmitter.cpp b/lib/Target/PowerPC/PPCMCCodeEmitter.cpp
deleted file mode 100644
index cf73d86..0000000
--- a/lib/Target/PowerPC/PPCMCCodeEmitter.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-//===-- PPCMCCodeEmitter.cpp - Convert PPC code to machine code -----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the PPCMCCodeEmitter class.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "mccodeemitter"
-#include "PPC.h"
-#include "PPCRegisterInfo.h"
-#include "PPCFixupKinds.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/ErrorHandling.h"
-using namespace llvm;
-
-STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
-
-namespace {
-class PPCMCCodeEmitter : public MCCodeEmitter {
- PPCMCCodeEmitter(const PPCMCCodeEmitter &); // DO NOT IMPLEMENT
- void operator=(const PPCMCCodeEmitter &); // DO NOT IMPLEMENT
-
-public:
- PPCMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
- MCContext &ctx) {
- }
-
- ~PPCMCCodeEmitter() {}
-
- unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getHA16Encoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getLO16Encoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const;
- unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- /// getMachineOpValue - Return binary encoding of operand. If the machine
- /// operand requires relocation, record the relocation and return zero.
- unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- // getBinaryCodeForInstr - TableGen'erated function for getting the
- // binary encoding for an instruction.
- unsigned getBinaryCodeForInstr(const MCInst &MI,
- SmallVectorImpl<MCFixup> &Fixups) const;
- void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const {
- unsigned Bits = getBinaryCodeForInstr(MI, Fixups);
-
- // Output the constant in big endian byte order.
- for (unsigned i = 0; i != 4; ++i) {
- OS << (char)(Bits >> 24);
- Bits <<= 8;
- }
-
- ++MCNumEmitted; // Keep track of the # of mi's emitted.
- }
-
-};
-
-} // end anonymous namespace
-
-MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
- const MCSubtargetInfo &STI,
- MCContext &Ctx) {
- return new PPCMCCodeEmitter(MCII, STI, Ctx);
-}
-
-unsigned PPCMCCodeEmitter::
-getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO = MI.getOperand(OpNo);
- if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
-
- // Add a fixup for the branch target.
- Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
- (MCFixupKind)PPC::fixup_ppc_br24));
- return 0;
-}
-
-unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO = MI.getOperand(OpNo);
- if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
-
- // Add a fixup for the branch target.
- Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
- (MCFixupKind)PPC::fixup_ppc_brcond14));
- return 0;
-}
-
-unsigned PPCMCCodeEmitter::getHA16Encoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO = MI.getOperand(OpNo);
- if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
-
- // Add a fixup for the branch target.
- Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
- (MCFixupKind)PPC::fixup_ppc_ha16));
- return 0;
-}
-
-unsigned PPCMCCodeEmitter::getLO16Encoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO = MI.getOperand(OpNo);
- if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
-
- // Add a fixup for the branch target.
- Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
- (MCFixupKind)PPC::fixup_ppc_lo16));
- return 0;
-}
-
-unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // Encode (imm, reg) as a memri, which has the low 16-bits as the
- // displacement and the next 5 bits as the register #.
- assert(MI.getOperand(OpNo+1).isReg());
- unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 16;
-
- const MCOperand &MO = MI.getOperand(OpNo);
- if (MO.isImm())
- return (getMachineOpValue(MI, MO, Fixups) & 0xFFFF) | RegBits;
-
- // Add a fixup for the displacement field.
- Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
- (MCFixupKind)PPC::fixup_ppc_lo16));
- return RegBits;
-}
-
-
-unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const {
- // Encode (imm, reg) as a memrix, which has the low 14-bits as the
- // displacement and the next 5 bits as the register #.
- assert(MI.getOperand(OpNo+1).isReg());
- unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 14;
-
- const MCOperand &MO = MI.getOperand(OpNo);
- if (MO.isImm())
- return (getMachineOpValue(MI, MO, Fixups) & 0x3FFF) | RegBits;
-
- // Add a fixup for the branch target.
- Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
- (MCFixupKind)PPC::fixup_ppc_lo14));
- return RegBits;
-}
-
-
-unsigned PPCMCCodeEmitter::
-get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO = MI.getOperand(OpNo);
- assert((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MFOCRF) &&
- (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
- return 0x80 >> PPCRegisterInfo::getRegisterNumbering(MO.getReg());
-}
-
-
-unsigned PPCMCCodeEmitter::
-getMachineOpValue(const MCInst &MI, const MCOperand &MO,
- SmallVectorImpl<MCFixup> &Fixups) const {
- if (MO.isReg()) {
- // MTCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
- // The GPR operand should come through here though.
- assert((MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MFOCRF) ||
- MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
- return PPCRegisterInfo::getRegisterNumbering(MO.getReg());
- }
-
- assert(MO.isImm() &&
- "Relocation required in an instruction that we cannot encode!");
- return MO.getImm();
-}
-
-
-#include "PPCGenMCCodeEmitter.inc"
diff --git a/lib/Target/PowerPC/PPCPredicates.h b/lib/Target/PowerPC/PPCPredicates.h
deleted file mode 100644
index b2c8315..0000000
--- a/lib/Target/PowerPC/PPCPredicates.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===-- PPCPredicates.h - PPC Branch Predicate Information ------*- 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 the PowerPC branch predicates.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TARGET_POWERPC_PPCPREDICATES_H
-#define LLVM_TARGET_POWERPC_PPCPREDICATES_H
-
-#include "PPC.h"
-
-namespace llvm {
-namespace PPC {
- /// Predicate - These are "(BI << 5) | BO" for various predicates.
- enum Predicate {
- PRED_ALWAYS = (0 << 5) | 20,
- PRED_LT = (0 << 5) | 12,
- PRED_LE = (1 << 5) | 4,
- PRED_EQ = (2 << 5) | 12,
- PRED_GE = (0 << 5) | 4,
- PRED_GT = (1 << 5) | 12,
- PRED_NE = (2 << 5) | 4,
- PRED_UN = (3 << 5) | 12,
- PRED_NU = (3 << 5) | 4
- };
-
- /// Invert the specified predicate. != -> ==, < -> >=.
- Predicate InvertPredicate(Predicate Opcode);
-}
-}
-
-#endif
diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp
index 9c2428b..2e90b7a 100644
--- a/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -28,7 +28,6 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Target/TargetFrameLowering.h"
@@ -68,52 +67,12 @@ PPCRegisterInfo::requiresRegisterScavenging(const MachineFunction &) const {
(EnablePPC64RS && Subtarget.isPPC64()));
}
-/// getRegisterNumbering - Given the enum value for some register, e.g.
-/// PPC::F14, return the number that it corresponds to (e.g. 14).
-unsigned PPCRegisterInfo::getRegisterNumbering(unsigned RegEnum) {
- using namespace PPC;
- switch (RegEnum) {
- case 0: return 0;
- case R0 : case X0 : case F0 : case V0 : case CR0: case CR0LT: return 0;
- case R1 : case X1 : case F1 : case V1 : case CR1: case CR0GT: return 1;
- case R2 : case X2 : case F2 : case V2 : case CR2: case CR0EQ: return 2;
- case R3 : case X3 : case F3 : case V3 : case CR3: case CR0UN: return 3;
- case R4 : case X4 : case F4 : case V4 : case CR4: case CR1LT: return 4;
- case R5 : case X5 : case F5 : case V5 : case CR5: case CR1GT: return 5;
- case R6 : case X6 : case F6 : case V6 : case CR6: case CR1EQ: return 6;
- case R7 : case X7 : case F7 : case V7 : case CR7: case CR1UN: return 7;
- case R8 : case X8 : case F8 : case V8 : case CR2LT: return 8;
- case R9 : case X9 : case F9 : case V9 : case CR2GT: return 9;
- case R10: case X10: case F10: case V10: case CR2EQ: return 10;
- case R11: case X11: case F11: case V11: case CR2UN: return 11;
- case R12: case X12: case F12: case V12: case CR3LT: return 12;
- case R13: case X13: case F13: case V13: case CR3GT: return 13;
- case R14: case X14: case F14: case V14: case CR3EQ: return 14;
- case R15: case X15: case F15: case V15: case CR3UN: return 15;
- case R16: case X16: case F16: case V16: case CR4LT: return 16;
- case R17: case X17: case F17: case V17: case CR4GT: return 17;
- case R18: case X18: case F18: case V18: case CR4EQ: return 18;
- case R19: case X19: case F19: case V19: case CR4UN: return 19;
- case R20: case X20: case F20: case V20: case CR5LT: return 20;
- case R21: case X21: case F21: case V21: case CR5GT: return 21;
- case R22: case X22: case F22: case V22: case CR5EQ: return 22;
- case R23: case X23: case F23: case V23: case CR5UN: return 23;
- case R24: case X24: case F24: case V24: case CR6LT: return 24;
- case R25: case X25: case F25: case V25: case CR6GT: return 25;
- case R26: case X26: case F26: case V26: case CR6EQ: return 26;
- case R27: case X27: case F27: case V27: case CR6UN: return 27;
- case R28: case X28: case F28: case V28: case CR7LT: return 28;
- case R29: case X29: case F29: case V29: case CR7GT: return 29;
- case R30: case X30: case F30: case V30: case CR7EQ: return 30;
- case R31: case X31: case F31: case V31: case CR7UN: return 31;
- default:
- llvm_unreachable("Unhandled reg in PPCRegisterInfo::getRegisterNumbering!");
- }
-}
-
PPCRegisterInfo::PPCRegisterInfo(const PPCSubtarget &ST,
const TargetInstrInfo &tii)
- : PPCGenRegisterInfo(), Subtarget(ST), TII(tii) {
+ : PPCGenRegisterInfo(ST.isPPC64() ? PPC::LR8 : PPC::LR,
+ ST.isPPC64() ? 0 : 1,
+ ST.isPPC64() ? 0 : 1),
+ Subtarget(ST), TII(tii) {
ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX;
ImmToIdxMap[PPC::LBZ] = PPC::LBZX; ImmToIdxMap[PPC::STB] = PPC::STBX;
ImmToIdxMap[PPC::LHZ] = PPC::LHZX; ImmToIdxMap[PPC::LHA] = PPC::LHAX;
@@ -519,7 +478,7 @@ void PPCRegisterInfo::lowerCRSpilling(MachineBasicBlock::iterator II,
// rlwinm rA, rA, ShiftBits, 0, 31.
BuildMI(MBB, II, dl, TII.get(PPC::RLWINM), Reg)
.addReg(Reg, RegState::Kill)
- .addImm(PPCRegisterInfo::getRegisterNumbering(SrcReg) * 4)
+ .addImm(getPPCRegisterNumbering(SrcReg) * 4)
.addImm(0)
.addImm(31);
@@ -668,10 +627,6 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
MI.getOperand(OperandBase + 1).ChangeToRegister(SReg, false);
}
-unsigned PPCRegisterInfo::getRARegister() const {
- return !Subtarget.isPPC64() ? PPC::LR : PPC::LR8;
-}
-
unsigned PPCRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
@@ -688,27 +643,3 @@ unsigned PPCRegisterInfo::getEHExceptionRegister() const {
unsigned PPCRegisterInfo::getEHHandlerRegister() const {
return !Subtarget.isPPC64() ? PPC::R4 : PPC::X4;
}
-
-/// DWARFFlavour - Flavour of dwarf regnumbers
-///
-namespace DWARFFlavour {
- enum {
- PPC64 = 0, PPC32 = 1
- };
-}
-
-int PPCRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
- // FIXME: Most probably dwarf numbers differs for Linux and Darwin
- unsigned Flavour = Subtarget.isPPC64() ?
- DWARFFlavour::PPC64 : DWARFFlavour::PPC32;
-
- return PPCGenRegisterInfo::getDwarfRegNumFull(RegNum, Flavour);
-}
-
-int PPCRegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const {
- // FIXME: Most probably dwarf numbers differs for Linux and Darwin
- unsigned Flavour = Subtarget.isPPC64() ?
- DWARFFlavour::PPC64 : DWARFFlavour::PPC32;
-
- return PPCGenRegisterInfo::getLLVMRegNumFull(RegNum, Flavour);
-}
diff --git a/lib/Target/PowerPC/PPCRegisterInfo.h b/lib/Target/PowerPC/PPCRegisterInfo.h
index 33fe5eb..1cc7213 100644
--- a/lib/Target/PowerPC/PPCRegisterInfo.h
+++ b/lib/Target/PowerPC/PPCRegisterInfo.h
@@ -33,10 +33,6 @@ class PPCRegisterInfo : public PPCGenRegisterInfo {
public:
PPCRegisterInfo(const PPCSubtarget &SubTarget, const TargetInstrInfo &tii);
- /// getRegisterNumbering - Given the enum value for some register, e.g.
- /// PPC::F14, return the number that it corresponds to (e.g. 14).
- static unsigned getRegisterNumbering(unsigned RegEnum);
-
/// getPointerRegClass - Return the register class to use to hold pointers.
/// This is used for addressing modes.
virtual const TargetRegisterClass *getPointerRegClass(unsigned Kind=0) const;
@@ -62,15 +58,11 @@ public:
int SPAdj, RegScavenger *RS = NULL) const;
// Debug information queries.
- unsigned getRARegister() const;
unsigned getFrameRegister(const MachineFunction &MF) const;
// Exception handling queries.
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
-
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- int getLLVMRegNum(unsigned RegNum, bool isEH) const;
};
} // end namespace llvm
diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp
index 5ea9b0f..cf194de 100644
--- a/lib/Target/PowerPC/PPCSubtarget.cpp
+++ b/lib/Target/PowerPC/PPCSubtarget.cpp
@@ -15,7 +15,7 @@
#include "PPC.h"
#include "llvm/GlobalValue.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#include <cstdlib>
#define GET_SUBTARGETINFO_TARGET_DESC
diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp
index e0ea5ad..f5744b8 100644
--- a/lib/Target/PowerPC/PPCTargetMachine.cpp
+++ b/lib/Target/PowerPC/PPCTargetMachine.cpp
@@ -16,76 +16,43 @@
#include "llvm/PassManager.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
-// This is duplicated code. Refactor this.
-static MCStreamer *createMCStreamer(const Target &T, const std::string &TT,
- MCContext &Ctx, TargetAsmBackend &TAB,
- raw_ostream &OS,
- MCCodeEmitter *Emitter,
- bool RelaxAll,
- bool NoExecStack) {
- if (Triple(TT).isOSDarwin())
- return createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll);
-
- return NULL;
-}
-
extern "C" void LLVMInitializePowerPCTarget() {
// Register the targets
RegisterTargetMachine<PPC32TargetMachine> A(ThePPC32Target);
RegisterTargetMachine<PPC64TargetMachine> B(ThePPC64Target);
-
- // Register the MC Code Emitter
- TargetRegistry::RegisterCodeEmitter(ThePPC32Target, createPPCMCCodeEmitter);
- TargetRegistry::RegisterCodeEmitter(ThePPC64Target, createPPCMCCodeEmitter);
-
-
- // Register the asm backend.
- TargetRegistry::RegisterAsmBackend(ThePPC32Target, createPPCAsmBackend);
- TargetRegistry::RegisterAsmBackend(ThePPC64Target, createPPCAsmBackend);
-
- // Register the object streamer.
- TargetRegistry::RegisterObjectStreamer(ThePPC32Target, createMCStreamer);
- TargetRegistry::RegisterObjectStreamer(ThePPC64Target, createMCStreamer);
}
-
-PPCTargetMachine::PPCTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS, bool is64Bit)
- : LLVMTargetMachine(T, TT, CPU, FS),
+PPCTargetMachine::PPCTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM,
+ bool is64Bit)
+ : LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
Subtarget(TT, CPU, FS, is64Bit),
DataLayout(Subtarget.getTargetDataString()), InstrInfo(*this),
FrameLowering(Subtarget), JITInfo(*this, is64Bit),
TLInfo(*this), TSInfo(*this),
InstrItins(Subtarget.getInstrItineraryData()) {
-
- if (getRelocationModel() == Reloc::Default) {
- if (Subtarget.isDarwin())
- setRelocationModel(Reloc::DynamicNoPIC);
- else
- setRelocationModel(Reloc::Static);
- }
}
/// Override this for PowerPC. Tail merging happily breaks up instruction issue
/// groups, which typically degrades performance.
bool PPCTargetMachine::getEnableTailMergeDefault() const { return false; }
-PPC32TargetMachine::PPC32TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : PPCTargetMachine(T, TT, CPU, FS, false) {
+PPC32TargetMachine::PPC32TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : PPCTargetMachine(T, TT, CPU, FS, RM, CM, false) {
}
-PPC64TargetMachine::PPC64TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : PPCTargetMachine(T, TT, CPU, FS, true) {
+PPC64TargetMachine::PPC64TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : PPCTargetMachine(T, TT, CPU, FS, RM, CM, true) {
}
@@ -110,19 +77,11 @@ bool PPCTargetMachine::addPreEmitPass(PassManagerBase &PM,
bool PPCTargetMachine::addCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
JITCodeEmitter &JCE) {
- // The JIT should use the static relocation model in ppc32 mode, PIC in ppc64.
// FIXME: This should be moved to TargetJITInfo!!
- if (Subtarget.isPPC64()) {
- // We use PIC codegen in ppc64 mode, because otherwise we'd have to use many
- // instructions to materialize arbitrary global variable + function +
- // constant pool addresses.
- setRelocationModel(Reloc::PIC_);
+ if (Subtarget.isPPC64())
// Temporary workaround for the inability of PPC64 JIT to handle jump
// tables.
DisableJumpTables = true;
- } else {
- setRelocationModel(Reloc::Static);
- }
// Inform the subtarget that we are in JIT mode. FIXME: does this break macho
// writing?
diff --git a/lib/Target/PowerPC/PPCTargetMachine.h b/lib/Target/PowerPC/PPCTargetMachine.h
index baf07e3..d06f084 100644
--- a/lib/Target/PowerPC/PPCTargetMachine.h
+++ b/lib/Target/PowerPC/PPCTargetMachine.h
@@ -40,9 +40,9 @@ class PPCTargetMachine : public LLVMTargetMachine {
InstrItineraryData InstrItins;
public:
- PPCTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS,
- bool is64Bit);
+ PPCTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM, bool is64Bit);
virtual const PPCInstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const PPCFrameLowering *getFrameLowering() const {
@@ -77,16 +77,18 @@ public:
///
class PPC32TargetMachine : public PPCTargetMachine {
public:
- PPC32TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ PPC32TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
};
/// PPC64TargetMachine - PowerPC 64-bit target machine.
///
class PPC64TargetMachine : public PPCTargetMachine {
public:
- PPC64TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ PPC64TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
};
} // end namespace llvm
diff --git a/lib/Target/PowerPC/TargetInfo/CMakeLists.txt b/lib/Target/PowerPC/TargetInfo/CMakeLists.txt
index 058d599..f63111f 100644
--- a/lib/Target/PowerPC/TargetInfo/CMakeLists.txt
+++ b/lib/Target/PowerPC/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMPowerPCInfo
PowerPCTargetInfo.cpp
)
-add_dependencies(LLVMPowerPCInfo PowerPCCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMPowerPCInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMPowerPCInfo PowerPCCommonTableGen)
diff --git a/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp b/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp
index ad607d0..5dc8568 100644
--- a/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp
+++ b/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "PPC.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::ThePPC32Target, llvm::ThePPC64Target;
diff --git a/lib/Target/README.txt b/lib/Target/README.txt
index 4cc9534..1f69ffb 100644
--- a/lib/Target/README.txt
+++ b/lib/Target/README.txt
@@ -2348,3 +2348,13 @@ which can do this in a single operation (instruction or libcall). It is
probably best to do this in the code generator.
//===---------------------------------------------------------------------===//
+
+unsigned foo(unsigned x, unsigned y) { return (x & y) == 0 || x == 0; }
+should fold to (x & y) == 0.
+
+//===---------------------------------------------------------------------===//
+
+unsigned foo(unsigned x, unsigned y) { return x > y && x != 0; }
+should fold to x > y.
+
+//===---------------------------------------------------------------------===//
diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt
index c77ded4..5b87849 100644
--- a/lib/Target/Sparc/CMakeLists.txt
+++ b/lib/Target/Sparc/CMakeLists.txt
@@ -1,11 +1,12 @@
set(LLVM_TARGET_DEFINITIONS Sparc.td)
-tablegen(SparcGenRegisterInfo.inc -gen-register-info)
-tablegen(SparcGenInstrInfo.inc -gen-instr-info)
-tablegen(SparcGenAsmWriter.inc -gen-asm-writer)
-tablegen(SparcGenDAGISel.inc -gen-dag-isel)
-tablegen(SparcGenSubtargetInfo.inc -gen-subtarget)
-tablegen(SparcGenCallingConv.inc -gen-callingconv)
+llvm_tablegen(SparcGenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(SparcGenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(SparcGenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(SparcGenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(SparcGenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(SparcGenCallingConv.inc -gen-callingconv)
+add_public_tablegen_target(SparcCommonTableGen)
add_llvm_target(SparcCodeGen
DelaySlotFiller.cpp
@@ -21,5 +22,17 @@ add_llvm_target(SparcCodeGen
SparcSelectionDAGInfo.cpp
)
+add_llvm_library_dependencies(LLVMSparcCodeGen
+ LLVMAsmPrinter
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMSelectionDAG
+ LLVMSparcDesc
+ LLVMSparcInfo
+ LLVMSupport
+ LLVMTarget
+ )
+
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
diff --git a/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt b/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
index 1e8c029..d3bdf0b 100644
--- a/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
@@ -2,3 +2,11 @@ add_llvm_library(LLVMSparcDesc
SparcMCTargetDesc.cpp
SparcMCAsmInfo.cpp
)
+
+add_llvm_library_dependencies(LLVMSparcDesc
+ LLVMMC
+ LLVMSparcInfo
+ LLVMSupport
+ )
+
+add_dependencies(LLVMSparcDesc SparcCommonTableGen)
diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
index cb92a2b..cb2a7df 100644
--- a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
+++ b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
@@ -13,10 +13,11 @@
#include "SparcMCTargetDesc.h"
#include "SparcMCAsmInfo.h"
+#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_MC_DESC
#include "SparcGenInstrInfo.inc"
@@ -35,8 +36,10 @@ static MCInstrInfo *createSparcMCInstrInfo() {
return X;
}
-extern "C" void LLVMInitializeSparcMCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(TheSparcTarget, createSparcMCInstrInfo);
+static MCRegisterInfo *createSparcMCRegisterInfo(StringRef TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitSparcMCRegisterInfo(X, SP::I7);
+ return X;
}
static MCSubtargetInfo *createSparcMCSubtargetInfo(StringRef TT, StringRef CPU,
@@ -46,12 +49,31 @@ static MCSubtargetInfo *createSparcMCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-extern "C" void LLVMInitializeSparcMCSubtargetInfo() {
- TargetRegistry::RegisterMCSubtargetInfo(TheSparcTarget,
- createSparcMCSubtargetInfo);
+static MCCodeGenInfo *createSparcMCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+ X->InitMCCodeGenInfo(RM, CM);
+ return X;
}
-extern "C" void LLVMInitializeSparcMCAsmInfo() {
+extern "C" void LLVMInitializeSparcTargetMC() {
+ // Register the MC asm info.
RegisterMCAsmInfo<SparcELFMCAsmInfo> X(TheSparcTarget);
RegisterMCAsmInfo<SparcELFMCAsmInfo> Y(TheSparcV9Target);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(TheSparcTarget,
+ createSparcMCCodeGenInfo);
+ TargetRegistry::RegisterMCCodeGenInfo(TheSparcV9Target,
+ createSparcMCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheSparcTarget, createSparcMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheSparcTarget, createSparcMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(TheSparcTarget,
+ createSparcMCSubtargetInfo);
}
diff --git a/lib/Target/Sparc/SparcAsmPrinter.cpp b/lib/Target/Sparc/SparcAsmPrinter.cpp
index edde842..345e1bc 100644
--- a/lib/Target/Sparc/SparcAsmPrinter.cpp
+++ b/lib/Target/Sparc/SparcAsmPrinter.cpp
@@ -22,9 +22,9 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp
index 6f30d3f..d70b163 100644
--- a/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/lib/Target/Sparc/SparcISelLowering.cpp
@@ -631,8 +631,8 @@ SparcTargetLowering::getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const
assert(CalleeFn->hasStructRetAttr() &&
"Callee does not have the StructRet attribute.");
- const PointerType *Ty = cast<PointerType>(CalleeFn->arg_begin()->getType());
- const Type *ElementTy = Ty->getElementType();
+ PointerType *Ty = cast<PointerType>(CalleeFn->arg_begin()->getType());
+ Type *ElementTy = Ty->getElementType();
return getTargetData()->getTypeAllocSize(ElementTy);
}
@@ -748,8 +748,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
- // SPARC has no intrinsics for these particular operations.
+ // FIXME: There are instructions available for ATOMIC_FENCE
+ // on SparcV8 and later.
setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
+ setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
setOperationAction(ISD::FSIN , MVT::f64, Expand);
setOperationAction(ISD::FCOS , MVT::f64, Expand);
diff --git a/lib/Target/Sparc/SparcInstrInfo.cpp b/lib/Target/Sparc/SparcInstrInfo.cpp
index 4e3ddf8..7a6bf50 100644
--- a/lib/Target/Sparc/SparcInstrInfo.cpp
+++ b/lib/Target/Sparc/SparcInstrInfo.cpp
@@ -17,8 +17,8 @@
#include "SparcSubtarget.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp
index 0acdd2c..8c16251 100644
--- a/lib/Target/Sparc/SparcRegisterInfo.cpp
+++ b/lib/Target/Sparc/SparcRegisterInfo.cpp
@@ -17,7 +17,6 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Type.h"
@@ -31,7 +30,7 @@ using namespace llvm;
SparcRegisterInfo::SparcRegisterInfo(SparcSubtarget &st,
const TargetInstrInfo &tii)
- : SparcGenRegisterInfo(), Subtarget(st), TII(tii) {
+ : SparcGenRegisterInfo(SP::I7), Subtarget(st), TII(tii) {
}
const unsigned* SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
@@ -113,10 +112,6 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
void SparcRegisterInfo::
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {}
-unsigned SparcRegisterInfo::getRARegister() const {
- return SP::I7;
-}
-
unsigned SparcRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
return SP::I6;
}
@@ -130,11 +125,3 @@ unsigned SparcRegisterInfo::getEHHandlerRegister() const {
llvm_unreachable("What is the exception handler register");
return 0;
}
-
-int SparcRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
- return SparcGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
-}
-
-int SparcRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const {
- return SparcGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0);
-}
diff --git a/lib/Target/Sparc/SparcRegisterInfo.h b/lib/Target/Sparc/SparcRegisterInfo.h
index ec9e63a..f845667 100644
--- a/lib/Target/Sparc/SparcRegisterInfo.h
+++ b/lib/Target/Sparc/SparcRegisterInfo.h
@@ -46,15 +46,11 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo {
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
// Debug information queries.
- unsigned getRARegister() const;
unsigned getFrameRegister(const MachineFunction &MF) const;
// Exception handling queries.
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
-
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- int getLLVMRegNum(unsigned RegNum, bool isEH) const;
};
} // end namespace llvm
diff --git a/lib/Target/Sparc/SparcSubtarget.cpp b/lib/Target/Sparc/SparcSubtarget.cpp
index de647e8..6c501cf 100644
--- a/lib/Target/Sparc/SparcSubtarget.cpp
+++ b/lib/Target/Sparc/SparcSubtarget.cpp
@@ -13,7 +13,7 @@
#include "SparcSubtarget.h"
#include "Sparc.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
diff --git a/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp
index cbe6d87..3d7b4a4 100644
--- a/lib/Target/Sparc/SparcTargetMachine.cpp
+++ b/lib/Target/Sparc/SparcTargetMachine.cpp
@@ -13,7 +13,7 @@
#include "Sparc.h"
#include "SparcTargetMachine.h"
#include "llvm/PassManager.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
extern "C" void LLVMInitializeSparcTarget() {
@@ -24,10 +24,11 @@ extern "C" void LLVMInitializeSparcTarget() {
/// SparcTargetMachine ctor - Create an ILP32 architecture model
///
-SparcTargetMachine::SparcTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS, bool is64bit)
- : LLVMTargetMachine(T, TT, CPU, FS),
+SparcTargetMachine::SparcTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM,
+ bool is64bit)
+ : LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
Subtarget(TT, CPU, FS, is64bit),
DataLayout(Subtarget.getDataLayout()),
TLInfo(*this), TSInfo(*this), InstrInfo(Subtarget),
@@ -51,15 +52,15 @@ bool SparcTargetMachine::addPreEmitPass(PassManagerBase &PM,
}
SparcV8TargetMachine::SparcV8TargetMachine(const Target &T,
- const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : SparcTargetMachine(T, TT, CPU, FS, false) {
+ StringRef TT, StringRef CPU,
+ StringRef FS, Reloc::Model RM,
+ CodeModel::Model CM)
+ : SparcTargetMachine(T, TT, CPU, FS, RM, CM, false) {
}
SparcV9TargetMachine::SparcV9TargetMachine(const Target &T,
- const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : SparcTargetMachine(T, TT, CPU, FS, true) {
+ StringRef TT, StringRef CPU,
+ StringRef FS, Reloc::Model RM,
+ CodeModel::Model CM)
+ : SparcTargetMachine(T, TT, CPU, FS, RM, CM, true) {
}
diff --git a/lib/Target/Sparc/SparcTargetMachine.h b/lib/Target/Sparc/SparcTargetMachine.h
index 799fc49..3c907dd 100644
--- a/lib/Target/Sparc/SparcTargetMachine.h
+++ b/lib/Target/Sparc/SparcTargetMachine.h
@@ -33,9 +33,9 @@ class SparcTargetMachine : public LLVMTargetMachine {
SparcInstrInfo InstrInfo;
SparcFrameLowering FrameLowering;
public:
- SparcTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS,
- bool is64bit);
+ SparcTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM, bool is64bit);
virtual const SparcInstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const TargetFrameLowering *getFrameLowering() const {
@@ -62,16 +62,18 @@ public:
///
class SparcV8TargetMachine : public SparcTargetMachine {
public:
- SparcV8TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ SparcV8TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
};
/// SparcV9TargetMachine - Sparc 64-bit target machine
///
class SparcV9TargetMachine : public SparcTargetMachine {
public:
- SparcV9TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ SparcV9TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
};
} // end namespace llvm
diff --git a/lib/Target/Sparc/TargetInfo/CMakeLists.txt b/lib/Target/Sparc/TargetInfo/CMakeLists.txt
index 870b56a..a076023 100644
--- a/lib/Target/Sparc/TargetInfo/CMakeLists.txt
+++ b/lib/Target/Sparc/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMSparcInfo
SparcTargetInfo.cpp
)
-add_dependencies(LLVMSparcInfo SparcCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMSparcInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMSparcInfo SparcCommonTableGen)
diff --git a/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp b/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp
index 5c06f07..c9d5b7b 100644
--- a/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp
+++ b/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "Sparc.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::TheSparcTarget;
diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt
index f4bdbd8..7c09c0e 100644
--- a/lib/Target/SystemZ/CMakeLists.txt
+++ b/lib/Target/SystemZ/CMakeLists.txt
@@ -1,11 +1,12 @@
set(LLVM_TARGET_DEFINITIONS SystemZ.td)
-tablegen(SystemZGenRegisterInfo.inc -gen-register-info)
-tablegen(SystemZGenInstrInfo.inc -gen-instr-info)
-tablegen(SystemZGenAsmWriter.inc -gen-asm-writer)
-tablegen(SystemZGenDAGISel.inc -gen-dag-isel)
-tablegen(SystemZGenCallingConv.inc -gen-callingconv)
-tablegen(SystemZGenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(SystemZGenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(SystemZGenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(SystemZGenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(SystemZGenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(SystemZGenCallingConv.inc -gen-callingconv)
+llvm_tablegen(SystemZGenSubtargetInfo.inc -gen-subtarget)
+add_public_tablegen_target(SystemZCommonTableGen)
add_llvm_target(SystemZCodeGen
SystemZAsmPrinter.cpp
@@ -19,5 +20,17 @@ add_llvm_target(SystemZCodeGen
SystemZSelectionDAGInfo.cpp
)
+add_llvm_library_dependencies(LLVMSystemZCodeGen
+ LLVMAsmPrinter
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMSystemZDesc
+ LLVMSystemZInfo
+ LLVMTarget
+ )
+
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
diff --git a/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt b/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt
index 2ac9016..822df09 100644
--- a/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt
@@ -3,5 +3,12 @@ add_llvm_library(LLVMSystemZDesc
SystemZMCAsmInfo.cpp
)
+add_llvm_library_dependencies(LLVMSystemZDesc
+ LLVMMC
+ LLVMSystemZInfo
+ )
+
+add_dependencies(LLVMSystemZDesc SystemZCommonTableGen)
+
# Hack: we need to include 'main' target directory to grab private headers
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..)
diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp
index 5a826a6..23fb1e0 100644
--- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp
+++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp
@@ -13,10 +13,11 @@
#include "SystemZMCTargetDesc.h"
#include "SystemZMCAsmInfo.h"
+#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_MC_DESC
#include "SystemZGenInstrInfo.inc"
@@ -35,9 +36,10 @@ static MCInstrInfo *createSystemZMCInstrInfo() {
return X;
}
-extern "C" void LLVMInitializeSystemZMCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(TheSystemZTarget,
- createSystemZMCInstrInfo);
+static MCRegisterInfo *createSystemZMCRegisterInfo(StringRef TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitSystemZMCRegisterInfo(X, 0);
+ return X;
}
static MCSubtargetInfo *createSystemZMCSubtargetInfo(StringRef TT,
@@ -48,11 +50,32 @@ static MCSubtargetInfo *createSystemZMCSubtargetInfo(StringRef TT,
return X;
}
-extern "C" void LLVMInitializeSystemZMCSubtargetInfo() {
- TargetRegistry::RegisterMCSubtargetInfo(TheSystemZTarget,
- createSystemZMCSubtargetInfo);
+static MCCodeGenInfo *createSystemZMCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+ if (RM == Reloc::Default)
+ RM = Reloc::Static;
+ X->InitMCCodeGenInfo(RM, CM);
+ return X;
}
-extern "C" void LLVMInitializeSystemZMCAsmInfo() {
+extern "C" void LLVMInitializeSystemZTargetMC() {
+ // Register the MC asm info.
RegisterMCAsmInfo<SystemZMCAsmInfo> X(TheSystemZTarget);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(TheSystemZTarget,
+ createSystemZMCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheSystemZTarget,
+ createSystemZMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheSystemZTarget,
+ createSystemZMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(TheSystemZTarget,
+ createSystemZMCSubtargetInfo);
}
diff --git a/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index fd4d8b7..43dcdfc 100644
--- a/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -28,10 +28,8 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetLoweringObjectFile.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp
index 871c297..48ca99f 100644
--- a/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -81,6 +81,7 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :
setSchedulingPreference(Sched::RegPressure);
setBooleanContents(ZeroOrOneBooleanContent);
+ setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp
index 99e2730..5f3dd80 100644
--- a/lib/Target/SystemZ/SystemZInstrInfo.cpp
+++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp
@@ -21,8 +21,8 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_CTOR
#include "SystemZGenInstrInfo.inc"
diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td
index 11a39fc..580d65b 100644
--- a/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -478,7 +478,7 @@ def MOV64rmm : RSYI<0x04EB,
"lmg\t{$from, $to, $dst}",
[]>;
-let isReMaterializable = 1, isAsCheapAsAMove = 1,
+let isReMaterializable = 1, neverHasSideEffects = 1, isAsCheapAsAMove = 1,
Constraints = "$src = $dst" in {
def MOV64Pr0_even : Pseudo<(outs GR64P:$dst), (ins GR64P:$src),
"lhi\t${dst:subreg_even}, 0",
diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp
index 59692e8..b1050d4 100644
--- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp
+++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp
@@ -33,7 +33,7 @@ using namespace llvm;
SystemZRegisterInfo::SystemZRegisterInfo(SystemZTargetMachine &tm,
const SystemZInstrInfo &tii)
- : SystemZGenRegisterInfo(), TM(tm), TII(tii) {
+ : SystemZGenRegisterInfo(0), TM(tm), TII(tii) {
}
const unsigned*
@@ -126,11 +126,6 @@ SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
MI.getOperand(i+1).ChangeToImmediate(Offset);
}
-unsigned SystemZRegisterInfo::getRARegister() const {
- assert(0 && "What is the return address register");
- return 0;
-}
-
unsigned
SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
assert(0 && "What is the frame register");
@@ -146,13 +141,3 @@ unsigned SystemZRegisterInfo::getEHHandlerRegister() const {
assert(0 && "What is the exception handler register");
return 0;
}
-
-int SystemZRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
- assert(0 && "What is the dwarf register number");
- return -1;
-}
-
-int SystemZRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const {
- assert(0 && "What is the dwarf register number");
- return -1;
-}
diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.h b/lib/Target/SystemZ/SystemZRegisterInfo.h
index 2e262e1..03935b2 100644
--- a/lib/Target/SystemZ/SystemZRegisterInfo.h
+++ b/lib/Target/SystemZ/SystemZRegisterInfo.h
@@ -48,15 +48,11 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
int SPAdj, RegScavenger *RS = NULL) const;
// Debug information queries.
- unsigned getRARegister() const;
unsigned getFrameRegister(const MachineFunction &MF) const;
// Exception handling queries.
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
-
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- int getLLVMRegNum(unsigned RegNum, bool isEH) const;
};
} // end namespace llvm
diff --git a/lib/Target/SystemZ/SystemZSubtarget.cpp b/lib/Target/SystemZ/SystemZSubtarget.cpp
index b3ed066..0845510 100644
--- a/lib/Target/SystemZ/SystemZSubtarget.cpp
+++ b/lib/Target/SystemZ/SystemZSubtarget.cpp
@@ -15,7 +15,7 @@
#include "SystemZ.h"
#include "llvm/GlobalValue.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
diff --git a/lib/Target/SystemZ/SystemZTargetMachine.cpp b/lib/Target/SystemZ/SystemZTargetMachine.cpp
index 48298cc..e390f06 100644
--- a/lib/Target/SystemZ/SystemZTargetMachine.cpp
+++ b/lib/Target/SystemZ/SystemZTargetMachine.cpp
@@ -10,7 +10,7 @@
#include "SystemZTargetMachine.h"
#include "SystemZ.h"
#include "llvm/PassManager.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
extern "C" void LLVMInitializeSystemZTarget() {
@@ -21,18 +21,15 @@ extern "C" void LLVMInitializeSystemZTarget() {
/// SystemZTargetMachine ctor - Create an ILP64 architecture model
///
SystemZTargetMachine::SystemZTargetMachine(const Target &T,
- const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : LLVMTargetMachine(T, TT, CPU, FS),
+ StringRef TT, StringRef CPU,
+ StringRef FS, Reloc::Model RM,
+ CodeModel::Model CM)
+ : LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
Subtarget(TT, CPU, FS),
DataLayout("E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32"
"-f64:64:64-f128:128:128-a0:16:16-n32:64"),
InstrInfo(*this), TLInfo(*this), TSInfo(*this),
FrameLowering(Subtarget) {
-
- if (getRelocationModel() == Reloc::Default)
- setRelocationModel(Reloc::Static);
}
bool SystemZTargetMachine::addInstSelector(PassManagerBase &PM,
diff --git a/lib/Target/SystemZ/SystemZTargetMachine.h b/lib/Target/SystemZ/SystemZTargetMachine.h
index e40b556..43dce4b 100644
--- a/lib/Target/SystemZ/SystemZTargetMachine.h
+++ b/lib/Target/SystemZ/SystemZTargetMachine.h
@@ -37,8 +37,9 @@ class SystemZTargetMachine : public LLVMTargetMachine {
SystemZSelectionDAGInfo TSInfo;
SystemZFrameLowering FrameLowering;
public:
- SystemZTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ SystemZTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
virtual const TargetFrameLowering *getFrameLowering() const {
return &FrameLowering;
diff --git a/lib/Target/SystemZ/TargetInfo/CMakeLists.txt b/lib/Target/SystemZ/TargetInfo/CMakeLists.txt
index 743d8d3..3180708 100644
--- a/lib/Target/SystemZ/TargetInfo/CMakeLists.txt
+++ b/lib/Target/SystemZ/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMSystemZInfo
SystemZTargetInfo.cpp
)
-add_dependencies(LLVMSystemZInfo SystemZCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMSystemZInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMSystemZInfo SystemZCommonTableGen)
diff --git a/lib/Target/SystemZ/TargetInfo/SystemZTargetInfo.cpp b/lib/Target/SystemZ/TargetInfo/SystemZTargetInfo.cpp
index 8272b11..da99282 100644
--- a/lib/Target/SystemZ/TargetInfo/SystemZTargetInfo.cpp
+++ b/lib/Target/SystemZ/TargetInfo/SystemZTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "SystemZ.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::TheSystemZTarget;
diff --git a/lib/Target/Target.cpp b/lib/Target/Target.cpp
index a42ce54..a2b83bc 100644
--- a/lib/Target/Target.cpp
+++ b/lib/Target/Target.cpp
@@ -17,6 +17,7 @@
#include "llvm/InitializePasses.h"
#include "llvm/PassManager.h"
#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/LLVMContext.h"
#include <cstring>
@@ -39,6 +40,11 @@ void LLVMAddTargetData(LLVMTargetDataRef TD, LLVMPassManagerRef PM) {
unwrap(PM)->add(new TargetData(*unwrap(TD)));
}
+void LLVMAddTargetLibraryInfo(LLVMTargetLibraryInfoRef TLI,
+ LLVMPassManagerRef PM) {
+ unwrap(PM)->add(new TargetLibraryInfo(*unwrap(TLI)));
+}
+
char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef TD) {
std::string StringRep = unwrap(TD)->getStringRepresentation();
return strdup(StringRep.c_str());
@@ -87,13 +93,13 @@ unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef TD,
unsigned LLVMElementAtOffset(LLVMTargetDataRef TD, LLVMTypeRef StructTy,
unsigned long long Offset) {
- const StructType *STy = unwrap<StructType>(StructTy);
+ StructType *STy = unwrap<StructType>(StructTy);
return unwrap(TD)->getStructLayout(STy)->getElementContainingOffset(Offset);
}
unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef TD, LLVMTypeRef StructTy,
unsigned Element) {
- const StructType *STy = unwrap<StructType>(StructTy);
+ StructType *STy = unwrap<StructType>(StructTy);
return unwrap(TD)->getStructLayout(STy)->getElementOffset(Element);
}
diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp
deleted file mode 100644
index a97b0e8..0000000
--- a/lib/Target/TargetAsmInfo.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//===-- llvm/Target/TargetAsmInfo.cpp - Target Assembly Info --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetLowering.h"
-#include "llvm/Target/TargetLoweringObjectFile.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegisterInfo.h"
-using namespace llvm;
-
-TargetAsmInfo::TargetAsmInfo(const TargetMachine &TM) {
- TLOF = &TM.getTargetLowering()->getObjFileLowering();
- TFI = TM.getFrameLowering();
- TRI = TM.getRegisterInfo();
- TFI->getInitialFrameState(InitialFrameState);
-}
diff --git a/lib/Target/TargetAsmLexer.cpp b/lib/Target/TargetAsmLexer.cpp
deleted file mode 100644
index d4893ff..0000000
--- a/lib/Target/TargetAsmLexer.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-//===-- llvm/Target/TargetAsmLexer.cpp - Target Assembly Lexer ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Target/TargetAsmLexer.h"
-using namespace llvm;
-
-TargetAsmLexer::TargetAsmLexer(const Target &T) : TheTarget(T), Lexer(NULL) {}
-TargetAsmLexer::~TargetAsmLexer() {}
diff --git a/lib/Target/TargetData.cpp b/lib/Target/TargetData.cpp
index 17d022a..bd6a6b6 100644
--- a/lib/Target/TargetData.cpp
+++ b/lib/Target/TargetData.cpp
@@ -41,7 +41,7 @@ char TargetData::ID = 0;
// Support for StructLayout
//===----------------------------------------------------------------------===//
-StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
+StructLayout::StructLayout(StructType *ST, const TargetData &TD) {
assert(!ST->isOpaque() && "Cannot get layout of opaque structs");
StructAlignment = 0;
StructSize = 0;
@@ -49,7 +49,7 @@ StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
// Loop over each of the elements, placing them in memory.
for (unsigned i = 0, e = NumElements; i != e; ++i) {
- const Type *Ty = ST->getElementType(i);
+ Type *Ty = ST->getElementType(i);
unsigned TyAlign = ST->isPacked() ? 1 : TD.getABITypeAlignment(Ty);
// Add padding if necessary to align the data element properly.
@@ -139,6 +139,7 @@ void TargetData::init(StringRef Desc) {
PointerMemSize = 8;
PointerABIAlign = 8;
PointerPrefAlign = PointerABIAlign;
+ StackNaturalAlign = 0;
// Default alignments
setAlignment(INTEGER_ALIGN, 1, 1, 1); // i1
@@ -218,7 +219,12 @@ void TargetData::init(StringRef Desc) {
Token = Split.second;
} while (!Specifier.empty() || !Token.empty());
break;
-
+ case 'S': // Stack natural alignment.
+ StackNaturalAlign = getInt(Specifier.substr(1));
+ StackNaturalAlign /= 8;
+ // FIXME: Should we really be truncating these alingments and
+ // sizes silently?
+ break;
default:
break;
}
@@ -261,7 +267,7 @@ TargetData::setAlignment(AlignTypeEnum align_type, unsigned abi_align,
/// preferred if ABIInfo = false) the target wants for the specified datatype.
unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType,
uint32_t BitWidth, bool ABIInfo,
- const Type *Ty) const {
+ Type *Ty) const {
// Check to see if we have an exact match and remember the best match we see.
int BestMatchIdx = -1;
int LargestInt = -1;
@@ -315,7 +321,7 @@ unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType,
namespace {
class StructLayoutMap {
- typedef DenseMap<const StructType*, StructLayout*> LayoutInfoTy;
+ typedef DenseMap<StructType*, StructLayout*> LayoutInfoTy;
LayoutInfoTy LayoutInfo;
public:
@@ -329,7 +335,7 @@ public:
}
}
- StructLayout *&operator[](const StructType *STy) {
+ StructLayout *&operator[](StructType *STy) {
return LayoutInfo[STy];
}
@@ -343,7 +349,7 @@ TargetData::~TargetData() {
delete static_cast<StructLayoutMap*>(LayoutMap);
}
-const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
+const StructLayout *TargetData::getStructLayout(StructType *Ty) const {
if (!LayoutMap)
LayoutMap = new StructLayoutMap();
@@ -372,7 +378,9 @@ std::string TargetData::getStringRepresentation() const {
OS << (LittleEndian ? "e" : "E")
<< "-p:" << PointerMemSize*8 << ':' << PointerABIAlign*8
- << ':' << PointerPrefAlign*8;
+ << ':' << PointerPrefAlign*8
+ << "-S" << StackNaturalAlign*8;
+
for (unsigned i = 0, e = Alignments.size(); i != e; ++i) {
const TargetAlignElem &AI = Alignments[i];
OS << '-' << (char)AI.AlignType << AI.TypeBitWidth << ':'
@@ -389,14 +397,14 @@ std::string TargetData::getStringRepresentation() const {
}
-uint64_t TargetData::getTypeSizeInBits(const Type *Ty) const {
+uint64_t TargetData::getTypeSizeInBits(Type *Ty) const {
assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
switch (Ty->getTypeID()) {
case Type::LabelTyID:
case Type::PointerTyID:
return getPointerSizeInBits();
case Type::ArrayTyID: {
- const ArrayType *ATy = cast<ArrayType>(Ty);
+ ArrayType *ATy = cast<ArrayType>(Ty);
return getTypeAllocSizeInBits(ATy->getElementType())*ATy->getNumElements();
}
case Type::StructTyID:
@@ -435,7 +443,7 @@ uint64_t TargetData::getTypeSizeInBits(const Type *Ty) const {
Get the ABI (\a abi_or_pref == true) or preferred alignment (\a abi_or_pref
== false) for the requested type \a Ty.
*/
-unsigned TargetData::getAlignment(const Type *Ty, bool abi_or_pref) const {
+unsigned TargetData::getAlignment(Type *Ty, bool abi_or_pref) const {
int AlignType = -1;
assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
@@ -485,7 +493,7 @@ unsigned TargetData::getAlignment(const Type *Ty, bool abi_or_pref) const {
abi_or_pref, Ty);
}
-unsigned TargetData::getABITypeAlignment(const Type *Ty) const {
+unsigned TargetData::getABITypeAlignment(Type *Ty) const {
return getAlignment(Ty, true);
}
@@ -496,7 +504,7 @@ unsigned TargetData::getABIIntegerTypeAlignment(unsigned BitWidth) const {
}
-unsigned TargetData::getCallFrameTypeAlignment(const Type *Ty) const {
+unsigned TargetData::getCallFrameTypeAlignment(Type *Ty) const {
for (unsigned i = 0, e = Alignments.size(); i != e; ++i)
if (Alignments[i].AlignType == STACK_ALIGN)
return Alignments[i].ABIAlign;
@@ -504,11 +512,11 @@ unsigned TargetData::getCallFrameTypeAlignment(const Type *Ty) const {
return getABITypeAlignment(Ty);
}
-unsigned TargetData::getPrefTypeAlignment(const Type *Ty) const {
+unsigned TargetData::getPrefTypeAlignment(Type *Ty) const {
return getAlignment(Ty, false);
}
-unsigned TargetData::getPreferredTypeAlignmentShift(const Type *Ty) const {
+unsigned TargetData::getPreferredTypeAlignmentShift(Type *Ty) const {
unsigned Align = getPrefTypeAlignment(Ty);
assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
return Log2_32(Align);
@@ -521,16 +529,17 @@ IntegerType *TargetData::getIntPtrType(LLVMContext &C) const {
}
-uint64_t TargetData::getIndexedOffset(const Type *ptrTy, Value* const* Indices,
- unsigned NumIndices) const {
- const Type *Ty = ptrTy;
+uint64_t TargetData::getIndexedOffset(Type *ptrTy,
+ ArrayRef<Value *> Indices) const {
+ Type *Ty = ptrTy;
assert(Ty->isPointerTy() && "Illegal argument for getIndexedOffset()");
uint64_t Result = 0;
generic_gep_type_iterator<Value* const*>
- TI = gep_type_begin(ptrTy, Indices, Indices+NumIndices);
- for (unsigned CurIDX = 0; CurIDX != NumIndices; ++CurIDX, ++TI) {
- if (const StructType *STy = dyn_cast<StructType>(*TI)) {
+ TI = gep_type_begin(ptrTy, Indices);
+ for (unsigned CurIDX = 0, EndIDX = Indices.size(); CurIDX != EndIDX;
+ ++CurIDX, ++TI) {
+ if (StructType *STy = dyn_cast<StructType>(*TI)) {
assert(Indices[CurIDX]->getType() ==
Type::getInt32Ty(ptrTy->getContext()) &&
"Illegal struct idx");
@@ -561,7 +570,7 @@ uint64_t TargetData::getIndexedOffset(const Type *ptrTy, Value* const* Indices,
/// global. This includes an explicitly requested alignment (if the global
/// has one).
unsigned TargetData::getPreferredAlignment(const GlobalVariable *GV) const {
- const Type *ElemType = GV->getType()->getElementType();
+ Type *ElemType = GV->getType()->getElementType();
unsigned Alignment = getPrefTypeAlignment(ElemType);
unsigned GVAlignment = GV->getAlignment();
if (GVAlignment >= Alignment) {
diff --git a/lib/Target/TargetFrameLowering.cpp b/lib/Target/TargetFrameLowering.cpp
index 19fd581..122f869 100644
--- a/lib/Target/TargetFrameLowering.cpp
+++ b/lib/Target/TargetFrameLowering.cpp
@@ -23,14 +23,6 @@ using namespace llvm;
TargetFrameLowering::~TargetFrameLowering() {
}
-/// getInitialFrameState - Returns a list of machine moves that are assumed
-/// on entry to a function.
-void
-TargetFrameLowering::getInitialFrameState(std::vector<MachineMove> &Moves)
- const {
- // Default is to do nothing.
-}
-
/// getFrameIndexOffset - Returns the displacement from the frame register to
/// the stack frame of the specified index. This is the default implementation
/// which is overridden for some targets.
diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp
index 703431b..56b7b69 100644
--- a/lib/Target/TargetLoweringObjectFile.cpp
+++ b/lib/Target/TargetLoweringObjectFile.cpp
@@ -35,34 +35,16 @@ using namespace llvm;
// Generic Code
//===----------------------------------------------------------------------===//
-TargetLoweringObjectFile::TargetLoweringObjectFile() :
- Ctx(0),
- TextSection(0),
- DataSection(0),
- BSSSection(0),
- ReadOnlySection(0),
- StaticCtorSection(0),
- StaticDtorSection(0),
- LSDASection(0),
- CompactUnwindSection(0),
- DwarfAbbrevSection(0),
- DwarfInfoSection(0),
- DwarfLineSection(0),
- DwarfFrameSection(0),
- DwarfPubNamesSection(0),
- DwarfPubTypesSection(0),
- DwarfDebugInlineSection(0),
- DwarfStrSection(0),
- DwarfLocSection(0),
- DwarfARangesSection(0),
- DwarfRangesSection(0),
- DwarfMacroInfoSection(0),
- TLSExtraDataSection(0),
- CommDirectiveSupportsAlignment(true),
- SupportsWeakOmittedEHFrame(true),
- IsFunctionEHFrameSymbolPrivate(true) {
+/// 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.
+void TargetLoweringObjectFile::Initialize(MCContext &ctx,
+ const TargetMachine &TM) {
+ Ctx = &ctx;
+ InitMCObjectFileInfo(TM.getTargetTriple(),
+ TM.getRelocationModel(), TM.getCodeModel(), *Ctx);
}
-
+
TargetLoweringObjectFile::~TargetLoweringObjectFile() {
}
@@ -93,7 +75,7 @@ static bool isSuitableForBSS(const GlobalVariable *GV) {
/// known to have a type that is an array of 1/2/4 byte elements) ends with a
/// nul value and contains no other nuls in it.
static bool IsNullTerminatedString(const Constant *C) {
- const ArrayType *ATy = cast<ArrayType>(C->getType());
+ ArrayType *ATy = cast<ArrayType>(C->getType());
// First check: is we have constant array of i8 terminated with zero
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(C)) {
@@ -188,8 +170,8 @@ SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV,
// If initializer is a null-terminated string, put it in a "cstring"
// section of the right width.
- if (const ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {
- if (const IntegerType *ITy =
+ if (ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {
+ if (IntegerType *ITy =
dyn_cast<IntegerType>(ATy->getElementType())) {
if ((ITy->getBitWidth() == 8 || ITy->getBitWidth() == 16 ||
ITy->getBitWidth() == 32) &&
@@ -341,20 +323,3 @@ getExprForDwarfReference(const MCSymbol *Sym, unsigned Encoding,
}
}
}
-
-unsigned TargetLoweringObjectFile::getPersonalityEncoding() const {
- return dwarf::DW_EH_PE_absptr;
-}
-
-unsigned TargetLoweringObjectFile::getLSDAEncoding() const {
- return dwarf::DW_EH_PE_absptr;
-}
-
-unsigned TargetLoweringObjectFile::getFDEEncoding(bool CFI) const {
- return dwarf::DW_EH_PE_absptr;
-}
-
-unsigned TargetLoweringObjectFile::getTTypeEncoding() const {
- return dwarf::DW_EH_PE_absptr;
-}
-
diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp
index 74a1f4e..fe8a7ce 100644
--- a/lib/Target/TargetMachine.cpp
+++ b/lib/Target/TargetMachine.cpp
@@ -40,8 +40,6 @@ namespace llvm {
bool JITExceptionHandling;
bool JITEmitDebugInfo;
bool JITEmitDebugInfoToDisk;
- Reloc::Model RelocationModel;
- CodeModel::Model CMModel;
bool GuaranteedTailCallOpt;
unsigned StackAlignmentOverride;
bool RealignStack;
@@ -49,6 +47,7 @@ namespace llvm {
bool StrongPHIElim;
bool HasDivModLibcall;
bool AsmVerbosityDefault(false);
+ bool EnableSegmentedStacks;
}
static cl::opt<bool, true>
@@ -143,38 +142,6 @@ EmitJitDebugInfoToDisk("jit-emit-debug-to-disk",
cl::location(JITEmitDebugInfoToDisk),
cl::init(false));
-static cl::opt<llvm::Reloc::Model, true>
-DefRelocationModel("relocation-model",
- cl::desc("Choose relocation model"),
- cl::location(RelocationModel),
- cl::init(Reloc::Default),
- cl::values(
- clEnumValN(Reloc::Default, "default",
- "Target default relocation model"),
- clEnumValN(Reloc::Static, "static",
- "Non-relocatable code"),
- clEnumValN(Reloc::PIC_, "pic",
- "Fully relocatable, position independent code"),
- clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
- "Relocatable external references, non-relocatable code"),
- clEnumValEnd));
-static cl::opt<llvm::CodeModel::Model, true>
-DefCodeModel("code-model",
- cl::desc("Choose code model"),
- cl::location(CMModel),
- cl::init(CodeModel::Default),
- cl::values(
- clEnumValN(CodeModel::Default, "default",
- "Target default code model"),
- clEnumValN(CodeModel::Small, "small",
- "Small code model"),
- clEnumValN(CodeModel::Kernel, "kernel",
- "Kernel code model"),
- clEnumValN(CodeModel::Medium, "medium",
- "Medium code model"),
- clEnumValN(CodeModel::Large, "large",
- "Large code model"),
- clEnumValEnd));
static cl::opt<bool, true>
EnableGuaranteedTailCallOpt("tailcallopt",
cl::desc("Turn fastcc calls into tail calls by (potentially) changing ABI."),
@@ -212,13 +179,20 @@ static cl::opt<bool>
FunctionSections("ffunction-sections",
cl::desc("Emit functions into separate sections"),
cl::init(false));
+static cl::opt<bool, true>
+SegmentedStacks("segmented-stacks",
+ cl::desc("Use segmented stacks if possible."),
+ cl::location(EnableSegmentedStacks),
+ cl::init(false));
+
//---------------------------------------------------------------------------
// TargetMachine Class
//
TargetMachine::TargetMachine(const Target &T,
StringRef TT, StringRef CPU, StringRef FS)
- : TheTarget(T), TargetTriple(TT), TargetCPU(CPU), TargetFS(FS), AsmInfo(0),
+ : TheTarget(T), TargetTriple(TT), TargetCPU(CPU), TargetFS(FS),
+ CodeGenInfo(0), AsmInfo(0),
MCRelaxAll(false),
MCNoExecStack(false),
MCSaveTempLabels(false),
@@ -231,29 +205,24 @@ TargetMachine::TargetMachine(const Target &T,
}
TargetMachine::~TargetMachine() {
+ delete CodeGenInfo;
delete AsmInfo;
}
/// getRelocationModel - Returns the code generation relocation model. The
/// choices are static, PIC, and dynamic-no-pic, and target default.
-Reloc::Model TargetMachine::getRelocationModel() {
- return RelocationModel;
-}
-
-/// setRelocationModel - Sets the code generation relocation model.
-void TargetMachine::setRelocationModel(Reloc::Model Model) {
- RelocationModel = Model;
+Reloc::Model TargetMachine::getRelocationModel() const {
+ if (!CodeGenInfo)
+ return Reloc::Default;
+ return CodeGenInfo->getRelocationModel();
}
/// getCodeModel - Returns the code model. The choices are small, kernel,
/// medium, large, and target default.
-CodeModel::Model TargetMachine::getCodeModel() {
- return CMModel;
-}
-
-/// setCodeModel - Sets the code model.
-void TargetMachine::setCodeModel(CodeModel::Model Model) {
- CMModel = Model;
+CodeModel::Model TargetMachine::getCodeModel() const {
+ if (!CodeGenInfo)
+ return CodeModel::Default;
+ return CodeGenInfo->getCodeModel();
}
bool TargetMachine::getAsmVerbosityDefault() {
diff --git a/lib/Target/TargetRegisterInfo.cpp b/lib/Target/TargetRegisterInfo.cpp
index 90a8f8d..67239b8 100644
--- a/lib/Target/TargetRegisterInfo.cpp
+++ b/lib/Target/TargetRegisterInfo.cpp
@@ -98,44 +98,25 @@ BitVector TargetRegisterInfo::getAllocatableSet(const MachineFunction &MF,
}
const TargetRegisterClass *
-llvm::getCommonSubClass(const TargetRegisterClass *A,
- const TargetRegisterClass *B) {
- // First take care of the trivial cases
+TargetRegisterInfo::getCommonSubClass(const TargetRegisterClass *A,
+ const TargetRegisterClass *B) const {
+ // First take care of the trivial cases.
if (A == B)
return A;
if (!A || !B)
return 0;
- // If B is a subclass of A, it will be handled in the loop below
- if (B->hasSubClass(A))
- return A;
+ // Register classes are ordered topologically, so the largest common
+ // sub-class it the common sub-class with the smallest ID.
+ const unsigned *SubA = A->getSubClassMask();
+ const unsigned *SubB = B->getSubClassMask();
- const TargetRegisterClass *Best = 0;
- for (TargetRegisterClass::sc_iterator I = A->subclasses_begin();
- const TargetRegisterClass *X = *I; ++I) {
- if (X == B)
- return B; // B is a subclass of A
-
- // X must be a common subclass of A and B
- if (!B->hasSubClass(X))
- continue;
-
- // A superclass is definitely better.
- if (!Best || Best->hasSuperClass(X)) {
- Best = X;
- continue;
- }
-
- // A subclass is definitely worse
- if (Best->hasSubClass(X))
- continue;
-
- // Best and *I have no super/sub class relation - pick the larger class, or
- // the smaller spill size.
- int nb = std::distance(Best->begin(), Best->end());
- int ni = std::distance(X->begin(), X->end());
- if (ni>nb || (ni==nb && X->getSize() < Best->getSize()))
- Best = X;
- }
- return Best;
+ // We could start the search from max(A.ID, B.ID), but we are only going to
+ // execute 2-3 iterations anyway.
+ for (unsigned Base = 0, BaseE = getNumRegClasses(); Base < BaseE; Base += 32)
+ if (unsigned Common = *SubA++ & *SubB++)
+ return getRegClass(Base + CountTrailingZeros_32(Common));
+
+ // No common sub-class exists.
+ return NULL;
}
diff --git a/lib/Target/X86/AsmParser/CMakeLists.txt b/lib/Target/X86/AsmParser/CMakeLists.txt
index 40dbdd7..94aca7a 100644
--- a/lib/Target/X86/AsmParser/CMakeLists.txt
+++ b/lib/Target/X86/AsmParser/CMakeLists.txt
@@ -4,4 +4,13 @@ add_llvm_library(LLVMX86AsmParser
X86AsmLexer.cpp
X86AsmParser.cpp
)
-add_dependencies(LLVMX86AsmParser X86CodeGenTable_gen)
+
+add_llvm_library_dependencies(LLVMX86AsmParser
+ LLVMMC
+ LLVMMCParser
+ LLVMSupport
+ LLVMX86Desc
+ LLVMX86Info
+ )
+
+add_dependencies(LLVMX86AsmParser X86CommonTableGen)
diff --git a/lib/Target/X86/AsmParser/X86AsmLexer.cpp b/lib/Target/X86/AsmParser/X86AsmLexer.cpp
index ec73087..1eaccff 100644
--- a/lib/Target/X86/AsmParser/X86AsmLexer.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmLexer.cpp
@@ -7,20 +7,20 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Target/TargetAsmLexer.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "MCTargetDesc/X86BaseInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
-#include "X86.h"
+#include "llvm/MC/MCTargetAsmLexer.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
using namespace llvm;
namespace {
-class X86AsmLexer : public TargetAsmLexer {
+class X86AsmLexer : public MCTargetAsmLexer {
const MCAsmInfo &AsmInfo;
bool tentativeIsValid;
@@ -60,8 +60,8 @@ protected:
}
}
public:
- X86AsmLexer(const Target &T, const MCAsmInfo &MAI)
- : TargetAsmLexer(T), AsmInfo(MAI), tentativeIsValid(false) {
+ X86AsmLexer(const Target &T, const MCRegisterInfo &MRI, const MCAsmInfo &MAI)
+ : MCTargetAsmLexer(T), AsmInfo(MAI), tentativeIsValid(false) {
}
};
@@ -160,6 +160,6 @@ AsmToken X86AsmLexer::LexTokenIntel() {
}
extern "C" void LLVMInitializeX86AsmLexer() {
- RegisterAsmLexer<X86AsmLexer> X(TheX86_32Target);
- RegisterAsmLexer<X86AsmLexer> Y(TheX86_64Target);
+ RegisterMCAsmLexer<X86AsmLexer> X(TheX86_32Target);
+ RegisterMCAsmLexer<X86AsmLexer> Y(TheX86_64Target);
}
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index d45dd35..cb4f15f 100644
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -7,14 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Target/TargetAsmParser.h"
-#include "X86.h"
-#include "X86Subtarget.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetAsmParser.h"
+#include "MCTargetDesc/X86BaseInfo.h"
+#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
@@ -26,6 +24,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -33,7 +32,7 @@ using namespace llvm;
namespace {
struct X86Operand;
-class X86ATTAsmParser : public TargetAsmParser {
+class X86ATTAsmParser : public MCTargetAsmParser {
MCSubtargetInfo &STI;
MCAsmParser &Parser;
@@ -48,6 +47,7 @@ private:
X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
bool ParseDirectiveWord(unsigned Size, SMLoc L);
+ bool ParseDirectiveCode(StringRef IDVal, SMLoc L);
bool MatchAndEmitInstruction(SMLoc IDLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
@@ -65,6 +65,10 @@ private:
// FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
}
+ void SwitchMode() {
+ unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(X86::Mode64Bit));
+ setAvailableFeatures(FB);
+ }
/// @name Auto-generated Matcher Functions
/// {
@@ -76,7 +80,7 @@ private:
public:
X86ATTAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
- : TargetAsmParser(), STI(sti), Parser(parser) {
+ : MCTargetAsmParser(), STI(sti), Parser(parser) {
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
@@ -223,6 +227,21 @@ struct X86Operand : public MCParsedAsmOperand {
(0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
(0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
}
+ bool isImmZExtu32u8() const {
+ if (!isImm())
+ return false;
+
+ // If this isn't a constant expr, just assume it fits and let relaxation
+ // handle it.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE)
+ return true;
+
+ // Otherwise, check the value is in a range that makes sense for this
+ // extension.
+ uint64_t Value = CE->getValue();
+ return (Value <= 0x00000000000000FFULL);
+ }
bool isImmSExti64i8() const {
if (!isImm())
return false;
@@ -382,19 +401,25 @@ bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
if (Tok.isNot(AsmToken::Identifier))
return Error(Tok.getLoc(), "invalid register name");
- // FIXME: Validate register for the current architecture; we have to do
- // validation later, so maybe there is no need for this here.
RegNo = MatchRegisterName(Tok.getString());
// If the match failed, try the register name as lowercase.
if (RegNo == 0)
RegNo = MatchRegisterName(LowercaseString(Tok.getString()));
- // FIXME: This should be done using Requires<In32BitMode> and
- // Requires<In64BitMode> so "eiz" usage in 64-bit instructions
- // can be also checked.
- if (RegNo == X86::RIZ && !is64BitMode())
- return Error(Tok.getLoc(), "riz register in 64-bit mode only");
+ if (!is64BitMode()) {
+ // FIXME: This should be done using Requires<In32BitMode> and
+ // Requires<In64BitMode> so "eiz" usage in 64-bit instructions can be also
+ // checked.
+ // FIXME: Check AH, CH, DH, BH cannot be used in an instruction requiring a
+ // REX prefix.
+ if (RegNo == X86::RIZ ||
+ X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo) ||
+ X86II::isX86_64NonExtLowByteReg(RegNo) ||
+ X86II::isX86_64ExtendedReg(RegNo))
+ return Error(Tok.getLoc(), "register %"
+ + Tok.getString() + " is only available in 64-bit mode");
+ }
// Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens.
if (RegNo == 0 && (Tok.getString() == "st" || Tok.getString() == "ST")) {
@@ -472,7 +497,7 @@ X86Operand *X86ATTAsmParser::ParseOperand() {
SMLoc Start, End;
if (ParseRegister(RegNo, Start, End)) return 0;
if (RegNo == X86::EIZ || RegNo == X86::RIZ) {
- Error(Start, "eiz and riz can only be used as index registers");
+ Error(Start, "%eiz and %riz can only be used as index registers");
return 0;
}
@@ -956,6 +981,7 @@ MatchAndEmitInstruction(SMLoc IDLoc,
// First, try a direct match.
switch (MatchInstructionImpl(Operands, Inst, OrigErrorInfo)) {
+ default: break;
case Match_Success:
Out.EmitInstruction(Inst);
return false;
@@ -994,7 +1020,7 @@ MatchAndEmitInstruction(SMLoc IDLoc,
// Check for the various suffix matches.
Tmp[Base.size()] = Suffixes[0];
unsigned ErrorInfoIgnore;
- MatchResultTy Match1, Match2, Match3, Match4;
+ unsigned Match1, Match2, Match3, Match4;
Match1 = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore);
Tmp[Base.size()] = Suffixes[1];
@@ -1096,6 +1122,8 @@ bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getIdentifier();
if (IDVal == ".word")
return ParseDirectiveWord(2, DirectiveID.getLoc());
+ else if (IDVal.startswith(".code"))
+ return ParseDirectiveCode(IDVal, DirectiveID.getLoc());
return true;
}
@@ -1124,15 +1152,35 @@ bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
return false;
}
+/// ParseDirectiveCode
+/// ::= .code32 | .code64
+bool X86ATTAsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {
+ if (IDVal == ".code32") {
+ Parser.Lex();
+ if (is64BitMode()) {
+ SwitchMode();
+ getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
+ }
+ } else if (IDVal == ".code64") {
+ Parser.Lex();
+ if (!is64BitMode()) {
+ SwitchMode();
+ getParser().getStreamer().EmitAssemblerFlag(MCAF_Code64);
+ }
+ } else {
+ return Error(L, "unexpected directive " + IDVal);
+ }
+ return false;
+}
extern "C" void LLVMInitializeX86AsmLexer();
// Force static initialization.
extern "C" void LLVMInitializeX86AsmParser() {
- RegisterAsmParser<X86ATTAsmParser> X(TheX86_32Target);
- RegisterAsmParser<X86ATTAsmParser> Y(TheX86_64Target);
+ RegisterMCAsmParser<X86ATTAsmParser> X(TheX86_32Target);
+ RegisterMCAsmParser<X86ATTAsmParser> Y(TheX86_64Target);
LLVMInitializeX86AsmLexer();
}
diff --git a/lib/Target/X86/CMakeLists.txt b/lib/Target/X86/CMakeLists.txt
index b112f9f..351e767 100644
--- a/lib/Target/X86/CMakeLists.txt
+++ b/lib/Target/X86/CMakeLists.txt
@@ -1,20 +1,19 @@
set(LLVM_TARGET_DEFINITIONS X86.td)
-tablegen(X86GenRegisterInfo.inc -gen-register-info)
-tablegen(X86GenDisassemblerTables.inc -gen-disassembler)
-tablegen(X86GenInstrInfo.inc -gen-instr-info)
-tablegen(X86GenAsmWriter.inc -gen-asm-writer)
-tablegen(X86GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1)
-tablegen(X86GenAsmMatcher.inc -gen-asm-matcher)
-tablegen(X86GenDAGISel.inc -gen-dag-isel)
-tablegen(X86GenFastISel.inc -gen-fast-isel)
-tablegen(X86GenCallingConv.inc -gen-callingconv)
-tablegen(X86GenSubtargetInfo.inc -gen-subtarget)
-tablegen(X86GenEDInfo.inc -gen-enhanced-disassembly-info)
+llvm_tablegen(X86GenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(X86GenDisassemblerTables.inc -gen-disassembler)
+llvm_tablegen(X86GenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(X86GenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(X86GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1)
+llvm_tablegen(X86GenAsmMatcher.inc -gen-asm-matcher)
+llvm_tablegen(X86GenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(X86GenFastISel.inc -gen-fast-isel)
+llvm_tablegen(X86GenCallingConv.inc -gen-callingconv)
+llvm_tablegen(X86GenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(X86GenEDInfo.inc -gen-enhanced-disassembly-info)
+add_public_tablegen_target(X86CommonTableGen)
set(sources
- SSEDomainFix.cpp
- X86AsmBackend.cpp
X86AsmPrinter.cpp
X86COFFMachineModuleInfo.cpp
X86CodeEmitter.cpp
@@ -26,14 +25,13 @@ set(sources
X86ISelLowering.cpp
X86InstrInfo.cpp
X86JITInfo.cpp
- X86MachObjectWriter.cpp
- X86MCCodeEmitter.cpp
X86MCInstLower.cpp
X86RegisterInfo.cpp
X86SelectionDAGInfo.cpp
X86Subtarget.cpp
X86TargetMachine.cpp
X86TargetObjectFile.cpp
+ X86VZeroUpper.cpp
)
if( CMAKE_CL_64 )
@@ -53,6 +51,19 @@ endif()
add_llvm_target(X86CodeGen ${sources})
+add_llvm_library_dependencies(LLVMX86CodeGen
+ LLVMAnalysis
+ LLVMAsmPrinter
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMTarget
+ LLVMX86AsmPrinter
+ LLVMX86Desc
+ )
+
add_subdirectory(AsmParser)
add_subdirectory(Disassembler)
add_subdirectory(InstPrinter)
diff --git a/lib/Target/X86/Disassembler/CMakeLists.txt b/lib/Target/X86/Disassembler/CMakeLists.txt
index 972a0d9..4f570d5 100644
--- a/lib/Target/X86/Disassembler/CMakeLists.txt
+++ b/lib/Target/X86/Disassembler/CMakeLists.txt
@@ -4,6 +4,13 @@ add_llvm_library(LLVMX86Disassembler
X86Disassembler.cpp
X86DisassemblerDecoder.c
)
+
+add_llvm_library_dependencies(LLVMX86Disassembler
+ LLVMMC
+ LLVMSupport
+ LLVMX86Info
+ )
+
# workaround for hanging compilation on MSVC9 and 10
if( MSVC_VERSION EQUAL 1400 OR MSVC_VERSION EQUAL 1500 OR MSVC_VERSION EQUAL 1600 )
set_property(
@@ -11,4 +18,5 @@ set_property(
PROPERTY COMPILE_FLAGS "/Od"
)
endif()
-add_dependencies(LLVMX86Disassembler X86CodeGenTable_gen)
+
+add_dependencies(LLVMX86Disassembler X86CommonTableGen)
diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp
index 4a0d2ec..3aacb20 100644
--- a/lib/Target/X86/Disassembler/X86Disassembler.cpp
+++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp
@@ -21,13 +21,16 @@
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#define GET_REGINFO_ENUM
#include "X86GenRegisterInfo.inc"
+#define GET_INSTRINFO_ENUM
+#include "X86GenInstrInfo.inc"
#include "X86GenEDInfo.inc"
using namespace llvm;
@@ -64,8 +67,8 @@ extern Target TheX86_32Target, TheX86_64Target;
static bool translateInstruction(MCInst &target,
InternalInstruction &source);
-X86GenericDisassembler::X86GenericDisassembler(DisassemblerMode mode) :
- MCDisassembler(),
+X86GenericDisassembler::X86GenericDisassembler(const MCSubtargetInfo &STI, DisassemblerMode mode) :
+ MCDisassembler(STI),
fMode(mode) {
}
@@ -106,28 +109,34 @@ static void logger(void* arg, const char* log) {
// Public interface for the disassembler
//
-bool X86GenericDisassembler::getInstruction(MCInst &instr,
- uint64_t &size,
- const MemoryObject &region,
- uint64_t address,
- raw_ostream &vStream) const {
+MCDisassembler::DecodeStatus
+X86GenericDisassembler::getInstruction(MCInst &instr,
+ uint64_t &size,
+ const MemoryObject &region,
+ uint64_t address,
+ raw_ostream &vStream,
+ raw_ostream &cStream) const {
InternalInstruction internalInstr;
+
+ dlog_t loggerFn = logger;
+ if (&vStream == &nulls())
+ loggerFn = 0; // Disable logging completely if it's going to nulls().
int ret = decodeInstruction(&internalInstr,
regionReader,
(void*)&region,
- logger,
+ loggerFn,
(void*)&vStream,
address,
fMode);
if (ret) {
size = internalInstr.readerCursor - address;
- return false;
+ return Fail;
}
else {
size = internalInstr.length;
- return !translateInstruction(instr, internalInstr);
+ return (!translateInstruction(instr, internalInstr)) ? Success : Fail;
}
}
@@ -183,8 +192,46 @@ static void translateImmediate(MCInst &mcInst, uint64_t immediate,
break;
}
}
+ // By default sign-extend all X86 immediates based on their encoding.
+ else if (type == TYPE_IMM8 || type == TYPE_IMM16 || type == TYPE_IMM32 ||
+ type == TYPE_IMM64) {
+ uint32_t Opcode = mcInst.getOpcode();
+ switch (operand.encoding) {
+ default:
+ break;
+ case ENCODING_IB:
+ // Special case those X86 instructions that use the imm8 as a set of
+ // bits, bit count, etc. and are not sign-extend.
+ if (Opcode != X86::BLENDPSrri && Opcode != X86::BLENDPDrri &&
+ Opcode != X86::PBLENDWrri && Opcode != X86::MPSADBWrri &&
+ Opcode != X86::DPPSrri && Opcode != X86::DPPDrri &&
+ Opcode != X86::INSERTPSrr && Opcode != X86::VBLENDPSYrri &&
+ Opcode != X86::VBLENDPSYrmi && Opcode != X86::VBLENDPDYrri &&
+ Opcode != X86::VBLENDPDYrmi && Opcode != X86::VPBLENDWrri &&
+ Opcode != X86::VMPSADBWrri && Opcode != X86::VDPPSYrri &&
+ Opcode != X86::VDPPSYrmi && Opcode != X86::VDPPDrri &&
+ Opcode != X86::VINSERTPSrr)
+ type = TYPE_MOFFS8;
+ break;
+ case ENCODING_IW:
+ type = TYPE_MOFFS16;
+ break;
+ case ENCODING_ID:
+ type = TYPE_MOFFS32;
+ break;
+ case ENCODING_IO:
+ type = TYPE_MOFFS64;
+ break;
+ }
+ }
switch (type) {
+ case TYPE_XMM128:
+ mcInst.addOperand(MCOperand::CreateReg(X86::XMM0 + (immediate >> 4)));
+ return;
+ case TYPE_XMM256:
+ mcInst.addOperand(MCOperand::CreateReg(X86::YMM0 + (immediate >> 4)));
+ return;
case TYPE_MOFFS8:
case TYPE_REL8:
if(immediate & 0x80)
@@ -543,12 +590,12 @@ static bool translateInstruction(MCInst &mcInst,
return false;
}
-static MCDisassembler *createX86_32Disassembler(const Target &T) {
- return new X86Disassembler::X86_32Disassembler;
+static MCDisassembler *createX86_32Disassembler(const Target &T, const MCSubtargetInfo &STI) {
+ return new X86Disassembler::X86_32Disassembler(STI);
}
-static MCDisassembler *createX86_64Disassembler(const Target &T) {
- return new X86Disassembler::X86_64Disassembler;
+static MCDisassembler *createX86_64Disassembler(const Target &T, const MCSubtargetInfo &STI) {
+ return new X86Disassembler::X86_64Disassembler(STI);
}
extern "C" void LLVMInitializeX86Disassembler() {
diff --git a/lib/Target/X86/Disassembler/X86Disassembler.h b/lib/Target/X86/Disassembler/X86Disassembler.h
index 550cf9d..6ac9a0f 100644
--- a/lib/Target/X86/Disassembler/X86Disassembler.h
+++ b/lib/Target/X86/Disassembler/X86Disassembler.h
@@ -92,6 +92,7 @@ struct InternalInstruction;
namespace llvm {
class MCInst;
+class MCSubtargetInfo;
class MemoryObject;
class raw_ostream;
@@ -107,16 +108,17 @@ protected:
/// Constructor - Initializes the disassembler.
///
/// @param mode - The X86 architecture mode to decode for.
- X86GenericDisassembler(DisassemblerMode mode);
+ X86GenericDisassembler(const MCSubtargetInfo &STI, DisassemblerMode mode);
public:
~X86GenericDisassembler();
/// getInstruction - See MCDisassembler.
- bool getInstruction(MCInst &instr,
- uint64_t &size,
- const MemoryObject &region,
- uint64_t address,
- raw_ostream &vStream) const;
+ DecodeStatus getInstruction(MCInst &instr,
+ uint64_t &size,
+ const MemoryObject &region,
+ uint64_t address,
+ raw_ostream &vStream,
+ raw_ostream &cStream) const;
/// getEDInfo - See MCDisassembler.
EDInstInfo *getEDInfo() const;
@@ -127,24 +129,24 @@ private:
/// X86_16Disassembler - 16-bit X86 disassembler.
class X86_16Disassembler : public X86GenericDisassembler {
public:
- X86_16Disassembler() :
- X86GenericDisassembler(MODE_16BIT) {
+ X86_16Disassembler(const MCSubtargetInfo &STI) :
+ X86GenericDisassembler(STI, MODE_16BIT) {
}
};
/// X86_16Disassembler - 32-bit X86 disassembler.
class X86_32Disassembler : public X86GenericDisassembler {
public:
- X86_32Disassembler() :
- X86GenericDisassembler(MODE_32BIT) {
+ X86_32Disassembler(const MCSubtargetInfo &STI) :
+ X86GenericDisassembler(STI, MODE_32BIT) {
}
};
/// X86_16Disassembler - 64-bit X86 disassembler.
class X86_64Disassembler : public X86GenericDisassembler {
public:
- X86_64Disassembler() :
- X86GenericDisassembler(MODE_64BIT) {
+ X86_64Disassembler(const MCSubtargetInfo &STI) :
+ X86GenericDisassembler(STI, MODE_64BIT) {
}
};
diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c
index de1610b..f9b0fe5 100644
--- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c
+++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c
@@ -58,8 +58,8 @@ static InstructionContext contextForAttrs(uint8_t attrMask) {
* @return - TRUE if the ModR/M byte is required, FALSE otherwise.
*/
static int modRMRequired(OpcodeType type,
- InstructionContext insnContext,
- uint8_t opcode) {
+ InstructionContext insnContext,
+ uint8_t opcode) {
const struct ContextDecision* decision = 0;
switch (type) {
@@ -391,7 +391,7 @@ static int readPrefixes(struct InternalInstruction* insn) {
return -1;
}
- if (insn->mode == MODE_64BIT || byte1 & 0x8) {
+ if (insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0) {
insn->vexSize = 3;
insn->necessaryPrefixLocation = insn->readerCursor - 1;
}
@@ -406,12 +406,14 @@ static int readPrefixes(struct InternalInstruction* insn) {
consumeByte(insn, &insn->vexPrefix[2]);
/* We simulate the REX prefix for simplicity's sake */
-
- insn->rexPrefix = 0x40
- | (wFromVEX3of3(insn->vexPrefix[2]) << 3)
- | (rFromVEX2of3(insn->vexPrefix[1]) << 2)
- | (xFromVEX2of3(insn->vexPrefix[1]) << 1)
- | (bFromVEX2of3(insn->vexPrefix[1]) << 0);
+
+ if (insn->mode == MODE_64BIT) {
+ insn->rexPrefix = 0x40
+ | (wFromVEX3of3(insn->vexPrefix[2]) << 3)
+ | (rFromVEX2of3(insn->vexPrefix[1]) << 2)
+ | (xFromVEX2of3(insn->vexPrefix[1]) << 1)
+ | (bFromVEX2of3(insn->vexPrefix[1]) << 0);
+ }
switch (ppFromVEX3of3(insn->vexPrefix[2]))
{
@@ -433,7 +435,7 @@ static int readPrefixes(struct InternalInstruction* insn) {
return -1;
}
- if (insn->mode == MODE_64BIT || byte1 & 0x8) {
+ if (insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0) {
insn->vexSize = 2;
}
else {
@@ -444,8 +446,10 @@ static int readPrefixes(struct InternalInstruction* insn) {
insn->vexPrefix[0] = byte;
consumeByte(insn, &insn->vexPrefix[1]);
- insn->rexPrefix = 0x40
- | (rFromVEX2of2(insn->vexPrefix[1]) << 2);
+ if (insn->mode == MODE_64BIT) {
+ insn->rexPrefix = 0x40
+ | (rFromVEX2of2(insn->vexPrefix[1]) << 2);
+ }
switch (ppFromVEX2of2(insn->vexPrefix[1]))
{
@@ -700,34 +704,6 @@ static BOOL is16BitEquvalent(const char* orig, const char* equiv) {
}
/*
- * is64BitEquivalent - Determines whether two instruction names refer to
- * equivalent instructions but one is 64-bit whereas the other is not.
- *
- * @param orig - The instruction that is not 64-bit
- * @param equiv - The instruction that is 64-bit
- */
-static BOOL is64BitEquivalent(const char* orig, const char* equiv) {
- off_t i;
-
- for (i = 0;; i++) {
- if (orig[i] == '\0' && equiv[i] == '\0')
- return TRUE;
- if (orig[i] == '\0' || equiv[i] == '\0')
- return FALSE;
- if (orig[i] != equiv[i]) {
- if ((orig[i] == 'W' || orig[i] == 'L') && equiv[i] == 'Q')
- continue;
- if ((orig[i] == '1' || orig[i] == '3') && equiv[i] == '6')
- continue;
- if ((orig[i] == '6' || orig[i] == '2') && equiv[i] == '4')
- continue;
- return FALSE;
- }
- }
-}
-
-
-/*
* getID - Determines the ID of an instruction, consuming the ModR/M byte as
* appropriate for extended and escape opcodes. Determines the attributes and
* context for the instruction before doing so.
@@ -763,8 +739,6 @@ static int getID(struct InternalInstruction* insn) {
break;
}
- if (wFromVEX3of3(insn->vexPrefix[2]))
- attrMask |= ATTR_REXW;
if (lFromVEX3of3(insn->vexPrefix[2]))
attrMask |= ATTR_VEXL;
}
@@ -789,63 +763,55 @@ static int getID(struct InternalInstruction* insn) {
}
}
else {
- if (insn->rexPrefix & 0x08)
- attrMask |= ATTR_REXW;
-
if (isPrefixAtLocation(insn, 0x66, insn->necessaryPrefixLocation))
attrMask |= ATTR_OPSIZE;
else if (isPrefixAtLocation(insn, 0xf3, insn->necessaryPrefixLocation))
attrMask |= ATTR_XS;
else if (isPrefixAtLocation(insn, 0xf2, insn->necessaryPrefixLocation))
attrMask |= ATTR_XD;
-
}
+ if (insn->rexPrefix & 0x08)
+ attrMask |= ATTR_REXW;
+
if (getIDWithAttrMask(&instructionID, insn, attrMask))
return -1;
/* The following clauses compensate for limitations of the tables. */
- if ((attrMask & ATTR_XD) && (attrMask & ATTR_REXW)) {
+ if ((attrMask & ATTR_VEXL) && (attrMask & ATTR_REXW)) {
/*
- * Although for SSE instructions it is usually necessary to treat REX.W+F2
- * as F2 for decode (in the absence of a 64BIT_REXW_XD category) there is
- * an occasional instruction where F2 is incidental and REX.W is the more
- * significant. If the decoded instruction is 32-bit and adding REX.W
- * instead of F2 changes a 32 to a 64, we adopt the new encoding.
+ * Some VEX instructions ignore the L-bit, but use the W-bit. Normally L-bit
+ * has precedence since there are no L-bit with W-bit entries in the tables.
+ * So if the L-bit isn't significant we should use the W-bit instead.
*/
-
+
const struct InstructionSpecifier *spec;
- uint16_t instructionIDWithREXw;
- const struct InstructionSpecifier *specWithREXw;
-
+ uint16_t instructionIDWithWBit;
+ const struct InstructionSpecifier *specWithWBit;
+
spec = specifierForUID(instructionID);
-
- if (getIDWithAttrMask(&instructionIDWithREXw,
+
+ if (getIDWithAttrMask(&instructionIDWithWBit,
insn,
- attrMask & (~ATTR_XD))) {
- /*
- * Decoding with REX.w would yield nothing; give up and return original
- * decode.
- */
-
+ (attrMask & (~ATTR_VEXL)) | ATTR_REXW)) {
insn->instructionID = instructionID;
insn->spec = spec;
return 0;
}
-
- specWithREXw = specifierForUID(instructionIDWithREXw);
-
- if (is64BitEquivalent(spec->name, specWithREXw->name)) {
- insn->instructionID = instructionIDWithREXw;
- insn->spec = specWithREXw;
+
+ specWithWBit = specifierForUID(instructionIDWithWBit);
+
+ if (instructionID != instructionIDWithWBit) {
+ insn->instructionID = instructionIDWithWBit;
+ insn->spec = specWithWBit;
} else {
insn->instructionID = instructionID;
insn->spec = spec;
}
return 0;
}
-
+
if (insn->prefixPresent[0x66] && !(attrMask & ATTR_OPSIZE)) {
/*
* The instruction tables make no distinction between instructions that
@@ -885,6 +851,43 @@ static int getID(struct InternalInstruction* insn) {
}
return 0;
}
+
+ if (insn->opcodeType == ONEBYTE && insn->opcode == 0x90 &&
+ insn->rexPrefix & 0x01) {
+ /*
+ * NOOP shouldn't decode as NOOP if REX.b is set. Instead
+ * it should decode as XCHG %r8, %eax.
+ */
+
+ const struct InstructionSpecifier *spec;
+ uint16_t instructionIDWithNewOpcode;
+ const struct InstructionSpecifier *specWithNewOpcode;
+
+ spec = specifierForUID(instructionID);
+
+ /* Borrow opcode from one of the other XCHGar opcodes */
+ insn->opcode = 0x91;
+
+ if (getIDWithAttrMask(&instructionIDWithNewOpcode,
+ insn,
+ attrMask)) {
+ insn->opcode = 0x90;
+
+ insn->instructionID = instructionID;
+ insn->spec = spec;
+ return 0;
+ }
+
+ specWithNewOpcode = specifierForUID(instructionIDWithNewOpcode);
+
+ /* Change back */
+ insn->opcode = 0x90;
+
+ insn->instructionID = instructionIDWithNewOpcode;
+ insn->spec = specWithNewOpcode;
+
+ return 0;
+ }
insn->instructionID = instructionID;
insn->spec = specifierForUID(insn->instructionID);
@@ -1434,11 +1437,10 @@ static int readImmediate(struct InternalInstruction* insn, uint8_t size) {
}
/*
- * readVVVV - Consumes an immediate operand from an instruction, given the
- * desired operand size.
+ * readVVVV - Consumes vvvv from an instruction if it has a VEX prefix.
*
* @param insn - The instruction whose operand is to be read.
- * @return - 0 if the immediate was successfully consumed; nonzero
+ * @return - 0 if the vvvv was successfully consumed; nonzero
* otherwise.
*/
static int readVVVV(struct InternalInstruction* insn) {
@@ -1451,6 +1453,9 @@ static int readVVVV(struct InternalInstruction* insn) {
else
return -1;
+ if (insn->mode != MODE_64BIT)
+ insn->vvvv &= 0x7;
+
return 0;
}
@@ -1463,8 +1468,14 @@ static int readVVVV(struct InternalInstruction* insn) {
*/
static int readOperands(struct InternalInstruction* insn) {
int index;
+ int hasVVVV, needVVVV;
dbgprintf(insn, "readOperands()");
+
+ /* If non-zero vvvv specified, need to make sure one of the operands
+ uses it. */
+ hasVVVV = !readVVVV(insn);
+ needVVVV = hasVVVV && (insn->vvvv != 0);
for (index = 0; index < X86_MAX_OPERANDS; ++index) {
switch (insn->spec->operands[index].encoding) {
@@ -1537,7 +1548,8 @@ static int readOperands(struct InternalInstruction* insn) {
return -1;
break;
case ENCODING_VVVV:
- if (readVVVV(insn))
+ needVVVV = 0; /* Mark that we have found a VVVV operand. */
+ if (!hasVVVV)
return -1;
if (fixupReg(insn, &insn->spec->operands[index]))
return -1;
@@ -1549,6 +1561,9 @@ static int readOperands(struct InternalInstruction* insn) {
return -1;
}
}
+
+ /* If we didn't find ENCODING_VVVV operand, but non-zero vvvv present, fail */
+ if (needVVVV) return -1;
return 0;
}
diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h
index 70315ed..8b79335 100644
--- a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h
+++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h
@@ -81,12 +81,18 @@ enum attributeBits {
"but not the operands") \
ENUM_ENTRY(IC_XS, 2, "may say something about the opcode " \
"but not the operands") \
+ ENUM_ENTRY(IC_XD_OPSIZE, 3, "requires an OPSIZE prefix, so " \
+ "operands change width") \
+ ENUM_ENTRY(IC_XS_OPSIZE, 3, "requires an OPSIZE prefix, so " \
+ "operands change width") \
ENUM_ENTRY(IC_64BIT_REXW, 4, "requires a REX.W prefix, so operands "\
"change width; overrides IC_OPSIZE") \
ENUM_ENTRY(IC_64BIT_OPSIZE, 3, "Just as meaningful as IC_OPSIZE") \
ENUM_ENTRY(IC_64BIT_XD, 5, "XD instructions are SSE; REX.W is " \
"secondary") \
ENUM_ENTRY(IC_64BIT_XS, 5, "Just as meaningful as IC_64BIT_XD") \
+ ENUM_ENTRY(IC_64BIT_XD_OPSIZE, 3, "Just as meaningful as IC_XD_OPSIZE") \
+ ENUM_ENTRY(IC_64BIT_XS_OPSIZE, 3, "Just as meaningful as IC_XS_OPSIZE") \
ENUM_ENTRY(IC_64BIT_REXW_XS, 6, "OPSIZE could mean a different " \
"opcode") \
ENUM_ENTRY(IC_64BIT_REXW_XD, 6, "Just as meaningful as " \
@@ -104,7 +110,7 @@ enum attributeBits {
ENUM_ENTRY(IC_VEX_W_OPSIZE, 4, "requires VEX, W, and OpSize") \
ENUM_ENTRY(IC_VEX_L, 3, "requires VEX and the L prefix") \
ENUM_ENTRY(IC_VEX_L_XS, 4, "requires VEX and the L and XS prefix")\
- ENUM_ENTRY(IC_VEX_L_XD, 4, "requires VEX and the L and XS prefix")\
+ ENUM_ENTRY(IC_VEX_L_XD, 4, "requires VEX and the L and XD prefix")\
ENUM_ENTRY(IC_VEX_L_OPSIZE, 4, "requires VEX, L, and OpSize")
diff --git a/lib/Target/X86/InstPrinter/CMakeLists.txt b/lib/Target/X86/InstPrinter/CMakeLists.txt
index 033973e..2a2b5db 100644
--- a/lib/Target/X86/InstPrinter/CMakeLists.txt
+++ b/lib/Target/X86/InstPrinter/CMakeLists.txt
@@ -5,4 +5,11 @@ add_llvm_library(LLVMX86AsmPrinter
X86IntelInstPrinter.cpp
X86InstComments.cpp
)
-add_dependencies(LLVMX86AsmPrinter X86CodeGenTable_gen)
+
+add_llvm_library_dependencies(LLVMX86AsmPrinter
+ LLVMMC
+ LLVMSupport
+ LLVMX86Utils
+ )
+
+add_dependencies(LLVMX86AsmPrinter X86CommonTableGen)
diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp
index c37d879..029d491 100644
--- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp
+++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp
@@ -39,14 +39,17 @@ void X86ATTInstPrinter::printRegName(raw_ostream &OS,
OS << '%' << getRegisterName(RegNo);
}
-void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) {
+void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
+ StringRef Annot) {
// Try to print any aliases first.
if (!printAliasInstr(MI, OS))
printInstruction(MI, OS);
// If verbose assembly is enabled, we can print some informative comments.
- if (CommentStream)
+ if (CommentStream) {
+ printAnnotation(OS, Annot);
EmitAnyX86InstComments(MI, *CommentStream, getRegisterName);
+ }
}
StringRef X86ATTInstPrinter::getOpcodeName(unsigned Opcode) const {
@@ -90,7 +93,8 @@ void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
if (Op.isReg()) {
O << '%' << getRegisterName(Op.getReg());
} else if (Op.isImm()) {
- O << '$' << Op.getImm();
+ // Print X86 immediates as signed values.
+ O << '$' << (int64_t)Op.getImm();
if (CommentStream && (Op.getImm() > 255 || Op.getImm() < -256))
*CommentStream << format("imm = 0x%llX\n", (long long)Op.getImm());
diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h
index 5426e5c..0293869 100644
--- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h
+++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h
@@ -25,7 +25,7 @@ public:
X86ATTInstPrinter(const MCAsmInfo &MAI);
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
- virtual void printInst(const MCInst *MI, raw_ostream &OS);
+ virtual void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot);
virtual StringRef getOpcodeName(unsigned Opcode) const;
// Autogenerated by tblgen, returns true if we successfully printed an
diff --git a/lib/Target/X86/InstPrinter/X86InstComments.cpp b/lib/Target/X86/InstPrinter/X86InstComments.cpp
index 4e28dfe..8d85b95 100644
--- a/lib/Target/X86/InstPrinter/X86InstComments.cpp
+++ b/lib/Target/X86/InstPrinter/X86InstComments.cpp
@@ -14,9 +14,9 @@
#include "X86InstComments.h"
#include "MCTargetDesc/X86MCTargetDesc.h"
+#include "Utils/X86ShuffleDecode.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/raw_ostream.h"
-#include "../Utils/X86ShuffleDecode.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
@@ -136,9 +136,11 @@ void llvm::EmitAnyX86InstComments(const MCInst *MI, raw_ostream &OS,
break;
case X86::SHUFPDrri:
+ Src2Name = getRegName(MI->getOperand(2).getReg());
+ // FALL THROUGH.
+ case X86::SHUFPDrmi:
DecodeSHUFPSMask(2, MI->getOperand(3).getImm(), ShuffleMask);
Src1Name = getRegName(MI->getOperand(0).getReg());
- Src2Name = getRegName(MI->getOperand(2).getReg());
break;
case X86::SHUFPSrri:
@@ -205,6 +207,31 @@ void llvm::EmitAnyX86InstComments(const MCInst *MI, raw_ostream &OS,
DecodeUNPCKHPMask(4, ShuffleMask);
Src1Name = getRegName(MI->getOperand(0).getReg());
break;
+ case X86::VPERMILPSri:
+ DecodeVPERMILPSMask(4, MI->getOperand(2).getImm(),
+ ShuffleMask);
+ Src1Name = getRegName(MI->getOperand(0).getReg());
+ break;
+ case X86::VPERMILPSYri:
+ DecodeVPERMILPSMask(8, MI->getOperand(2).getImm(),
+ ShuffleMask);
+ Src1Name = getRegName(MI->getOperand(0).getReg());
+ break;
+ case X86::VPERMILPDri:
+ DecodeVPERMILPDMask(2, MI->getOperand(2).getImm(),
+ ShuffleMask);
+ Src1Name = getRegName(MI->getOperand(0).getReg());
+ break;
+ case X86::VPERMILPDYri:
+ DecodeVPERMILPDMask(4, MI->getOperand(2).getImm(),
+ ShuffleMask);
+ Src1Name = getRegName(MI->getOperand(0).getReg());
+ break;
+ case X86::VPERM2F128rr:
+ DecodeVPERM2F128Mask(MI->getOperand(3).getImm(), ShuffleMask);
+ Src1Name = getRegName(MI->getOperand(1).getReg());
+ Src2Name = getRegName(MI->getOperand(2).getReg());
+ break;
}
diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp
index 506e26c..f9ab5ae 100644
--- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp
+++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp
@@ -32,12 +32,15 @@ void X86IntelInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
OS << getRegisterName(RegNo);
}
-void X86IntelInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) {
+void X86IntelInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
+ StringRef Annot) {
printInstruction(MI, OS);
// If verbose assembly is enabled, we can print some informative comments.
- if (CommentStream)
+ if (CommentStream) {
+ printAnnotation(OS, Annot);
EmitAnyX86InstComments(MI, *CommentStream, getRegisterName);
+ }
}
StringRef X86IntelInstPrinter::getOpcodeName(unsigned Opcode) const {
return getInstructionName(Opcode);
diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h
index e84a194..6d5ec62 100644
--- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h
+++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h
@@ -27,7 +27,7 @@ public:
: MCInstPrinter(MAI) {}
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
- virtual void printInst(const MCInst *MI, raw_ostream &OS);
+ virtual void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot);
virtual StringRef getOpcodeName(unsigned Opcode) const;
// Autogenerated by tblgen.
diff --git a/lib/Target/X86/MCTargetDesc/CMakeLists.txt b/lib/Target/X86/MCTargetDesc/CMakeLists.txt
index ca88f8f..8721912 100644
--- a/lib/Target/X86/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/X86/MCTargetDesc/CMakeLists.txt
@@ -1,7 +1,20 @@
add_llvm_library(LLVMX86Desc
+ X86AsmBackend.cpp
X86MCTargetDesc.cpp
X86MCAsmInfo.cpp
+ X86MCCodeEmitter.cpp
+ X86MachObjectWriter.cpp
)
+add_llvm_library_dependencies(LLVMX86Desc
+ LLVMMC
+ LLVMSupport
+ LLVMX86AsmPrinter
+ LLVMX86AsmPrinter
+ LLVMX86Info
+ )
+
+add_dependencies(LLVMX86Desc X86CommonTableGen)
+
# Hack: we need to include 'main' target directory to grab private headers
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..)
diff --git a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
new file mode 100644
index 0000000..69ad7d7
--- /dev/null
+++ b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
@@ -0,0 +1,458 @@
+//===-- X86AsmBackend.cpp - X86 Assembler Backend -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmBackend.h"
+#include "MCTargetDesc/X86BaseInfo.h"
+#include "MCTargetDesc/X86FixupKinds.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCMachObjectWriter.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSectionCOFF.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/Object/MachOFormat.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+// Option to allow disabling arithmetic relaxation to workaround PR9807, which
+// is useful when running bitwise comparison experiments on Darwin. We should be
+// able to remove this once PR9807 is resolved.
+static cl::opt<bool>
+MCDisableArithRelaxation("mc-x86-disable-arith-relaxation",
+ cl::desc("Disable relaxation of arithmetic instruction for X86"));
+
+static unsigned getFixupKindLog2Size(unsigned Kind) {
+ switch (Kind) {
+ default: assert(0 && "invalid fixup kind!");
+ case FK_PCRel_1:
+ case FK_Data_1: return 0;
+ case FK_PCRel_2:
+ case FK_Data_2: return 1;
+ case FK_PCRel_4:
+ case X86::reloc_riprel_4byte:
+ case X86::reloc_riprel_4byte_movq_load:
+ case X86::reloc_signed_4byte:
+ case X86::reloc_global_offset_table:
+ case FK_Data_4: return 2;
+ case FK_PCRel_8:
+ case FK_Data_8: return 3;
+ }
+}
+
+namespace {
+
+class X86ELFObjectWriter : public MCELFObjectTargetWriter {
+public:
+ X86ELFObjectWriter(bool is64Bit, Triple::OSType OSType, uint16_t EMachine,
+ bool HasRelocationAddend)
+ : MCELFObjectTargetWriter(is64Bit, OSType, EMachine, HasRelocationAddend) {}
+};
+
+class X86AsmBackend : public MCAsmBackend {
+public:
+ X86AsmBackend(const Target &T)
+ : MCAsmBackend() {}
+
+ unsigned getNumFixupKinds() const {
+ return X86::NumTargetFixupKinds;
+ }
+
+ const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
+ const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = {
+ { "reloc_riprel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel },
+ { "reloc_riprel_4byte_movq_load", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel},
+ { "reloc_signed_4byte", 0, 4 * 8, 0},
+ { "reloc_global_offset_table", 0, 4 * 8, 0}
+ };
+
+ if (Kind < FirstTargetFixupKind)
+ return MCAsmBackend::getFixupKindInfo(Kind);
+
+ assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
+ "Invalid kind!");
+ return Infos[Kind - FirstTargetFixupKind];
+ }
+
+ void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
+ uint64_t Value) const {
+ unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind());
+
+ assert(Fixup.getOffset() + Size <= DataSize &&
+ "Invalid fixup offset!");
+
+ // Check that uppper bits are either all zeros or all ones.
+ // Specifically ignore overflow/underflow as long as the leakage is
+ // limited to the lower bits. This is to remain compatible with
+ // other assemblers.
+ assert(isIntN(Size * 8 + 1, Value) &&
+ "Value does not fit in the Fixup field");
+
+ for (unsigned i = 0; i != Size; ++i)
+ Data[Fixup.getOffset() + i] = uint8_t(Value >> (i * 8));
+ }
+
+ bool MayNeedRelaxation(const MCInst &Inst) const;
+
+ void RelaxInstruction(const MCInst &Inst, MCInst &Res) const;
+
+ bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const;
+};
+} // end anonymous namespace
+
+static unsigned getRelaxedOpcodeBranch(unsigned Op) {
+ switch (Op) {
+ default:
+ return Op;
+
+ case X86::JAE_1: return X86::JAE_4;
+ case X86::JA_1: return X86::JA_4;
+ case X86::JBE_1: return X86::JBE_4;
+ case X86::JB_1: return X86::JB_4;
+ case X86::JE_1: return X86::JE_4;
+ case X86::JGE_1: return X86::JGE_4;
+ case X86::JG_1: return X86::JG_4;
+ case X86::JLE_1: return X86::JLE_4;
+ case X86::JL_1: return X86::JL_4;
+ case X86::JMP_1: return X86::JMP_4;
+ case X86::JNE_1: return X86::JNE_4;
+ case X86::JNO_1: return X86::JNO_4;
+ case X86::JNP_1: return X86::JNP_4;
+ case X86::JNS_1: return X86::JNS_4;
+ case X86::JO_1: return X86::JO_4;
+ case X86::JP_1: return X86::JP_4;
+ case X86::JS_1: return X86::JS_4;
+ }
+}
+
+static unsigned getRelaxedOpcodeArith(unsigned Op) {
+ switch (Op) {
+ default:
+ return Op;
+
+ // IMUL
+ case X86::IMUL16rri8: return X86::IMUL16rri;
+ case X86::IMUL16rmi8: return X86::IMUL16rmi;
+ case X86::IMUL32rri8: return X86::IMUL32rri;
+ case X86::IMUL32rmi8: return X86::IMUL32rmi;
+ case X86::IMUL64rri8: return X86::IMUL64rri32;
+ case X86::IMUL64rmi8: return X86::IMUL64rmi32;
+
+ // AND
+ case X86::AND16ri8: return X86::AND16ri;
+ case X86::AND16mi8: return X86::AND16mi;
+ case X86::AND32ri8: return X86::AND32ri;
+ case X86::AND32mi8: return X86::AND32mi;
+ case X86::AND64ri8: return X86::AND64ri32;
+ case X86::AND64mi8: return X86::AND64mi32;
+
+ // OR
+ case X86::OR16ri8: return X86::OR16ri;
+ case X86::OR16mi8: return X86::OR16mi;
+ case X86::OR32ri8: return X86::OR32ri;
+ case X86::OR32mi8: return X86::OR32mi;
+ case X86::OR64ri8: return X86::OR64ri32;
+ case X86::OR64mi8: return X86::OR64mi32;
+
+ // XOR
+ case X86::XOR16ri8: return X86::XOR16ri;
+ case X86::XOR16mi8: return X86::XOR16mi;
+ case X86::XOR32ri8: return X86::XOR32ri;
+ case X86::XOR32mi8: return X86::XOR32mi;
+ case X86::XOR64ri8: return X86::XOR64ri32;
+ case X86::XOR64mi8: return X86::XOR64mi32;
+
+ // ADD
+ case X86::ADD16ri8: return X86::ADD16ri;
+ case X86::ADD16mi8: return X86::ADD16mi;
+ case X86::ADD32ri8: return X86::ADD32ri;
+ case X86::ADD32mi8: return X86::ADD32mi;
+ case X86::ADD64ri8: return X86::ADD64ri32;
+ case X86::ADD64mi8: return X86::ADD64mi32;
+
+ // SUB
+ case X86::SUB16ri8: return X86::SUB16ri;
+ case X86::SUB16mi8: return X86::SUB16mi;
+ case X86::SUB32ri8: return X86::SUB32ri;
+ case X86::SUB32mi8: return X86::SUB32mi;
+ case X86::SUB64ri8: return X86::SUB64ri32;
+ case X86::SUB64mi8: return X86::SUB64mi32;
+
+ // CMP
+ case X86::CMP16ri8: return X86::CMP16ri;
+ case X86::CMP16mi8: return X86::CMP16mi;
+ case X86::CMP32ri8: return X86::CMP32ri;
+ case X86::CMP32mi8: return X86::CMP32mi;
+ case X86::CMP64ri8: return X86::CMP64ri32;
+ case X86::CMP64mi8: return X86::CMP64mi32;
+
+ // PUSH
+ case X86::PUSHi8: return X86::PUSHi32;
+ case X86::PUSHi16: return X86::PUSHi32;
+ case X86::PUSH64i8: return X86::PUSH64i32;
+ case X86::PUSH64i16: return X86::PUSH64i32;
+ }
+}
+
+static unsigned getRelaxedOpcode(unsigned Op) {
+ unsigned R = getRelaxedOpcodeArith(Op);
+ if (R != Op)
+ return R;
+ return getRelaxedOpcodeBranch(Op);
+}
+
+bool X86AsmBackend::MayNeedRelaxation(const MCInst &Inst) const {
+ // Branches can always be relaxed.
+ if (getRelaxedOpcodeBranch(Inst.getOpcode()) != Inst.getOpcode())
+ return true;
+
+ if (MCDisableArithRelaxation)
+ return false;
+
+ // Check if this instruction is ever relaxable.
+ if (getRelaxedOpcodeArith(Inst.getOpcode()) == Inst.getOpcode())
+ return false;
+
+
+ // Check if it has an expression and is not RIP relative.
+ bool hasExp = false;
+ bool hasRIP = false;
+ for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
+ const MCOperand &Op = Inst.getOperand(i);
+ if (Op.isExpr())
+ hasExp = true;
+
+ if (Op.isReg() && Op.getReg() == X86::RIP)
+ hasRIP = true;
+ }
+
+ // FIXME: Why exactly do we need the !hasRIP? Is it just a limitation on
+ // how we do relaxations?
+ return hasExp && !hasRIP;
+}
+
+// FIXME: Can tblgen help at all here to verify there aren't other instructions
+// we can relax?
+void X86AsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
+ // The only relaxations X86 does is from a 1byte pcrel to a 4byte pcrel.
+ unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode());
+
+ if (RelaxedOp == Inst.getOpcode()) {
+ SmallString<256> Tmp;
+ raw_svector_ostream OS(Tmp);
+ Inst.dump_pretty(OS);
+ OS << "\n";
+ report_fatal_error("unexpected instruction to relax: " + OS.str());
+ }
+
+ Res = Inst;
+ Res.setOpcode(RelaxedOp);
+}
+
+/// WriteNopData - Write optimal nops to the output file for the \arg Count
+/// bytes. This returns the number of bytes written. It may return 0 if
+/// the \arg Count is more than the maximum optimal nops.
+bool X86AsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
+ static const uint8_t Nops[10][10] = {
+ // nop
+ {0x90},
+ // xchg %ax,%ax
+ {0x66, 0x90},
+ // nopl (%[re]ax)
+ {0x0f, 0x1f, 0x00},
+ // nopl 0(%[re]ax)
+ {0x0f, 0x1f, 0x40, 0x00},
+ // nopl 0(%[re]ax,%[re]ax,1)
+ {0x0f, 0x1f, 0x44, 0x00, 0x00},
+ // nopw 0(%[re]ax,%[re]ax,1)
+ {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
+ // nopl 0L(%[re]ax)
+ {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
+ // nopl 0L(%[re]ax,%[re]ax,1)
+ {0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+ // nopw 0L(%[re]ax,%[re]ax,1)
+ {0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+ // nopw %cs:0L(%[re]ax,%[re]ax,1)
+ {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+ };
+
+ // Write an optimal sequence for the first 15 bytes.
+ const uint64_t OptimalCount = (Count < 16) ? Count : 15;
+ const uint64_t Prefixes = OptimalCount <= 10 ? 0 : OptimalCount - 10;
+ for (uint64_t i = 0, e = Prefixes; i != e; i++)
+ OW->Write8(0x66);
+ const uint64_t Rest = OptimalCount - Prefixes;
+ for (uint64_t i = 0, e = Rest; i != e; i++)
+ OW->Write8(Nops[Rest - 1][i]);
+
+ // Finish with single byte nops.
+ for (uint64_t i = OptimalCount, e = Count; i != e; ++i)
+ OW->Write8(0x90);
+
+ return true;
+}
+
+/* *** */
+
+namespace {
+class ELFX86AsmBackend : public X86AsmBackend {
+public:
+ Triple::OSType OSType;
+ ELFX86AsmBackend(const Target &T, Triple::OSType _OSType)
+ : X86AsmBackend(T), OSType(_OSType) {
+ HasReliableSymbolDifference = true;
+ }
+
+ virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
+ const MCSectionELF &ES = static_cast<const MCSectionELF&>(Section);
+ return ES.getFlags() & ELF::SHF_MERGE;
+ }
+};
+
+class ELFX86_32AsmBackend : public ELFX86AsmBackend {
+public:
+ ELFX86_32AsmBackend(const Target &T, Triple::OSType OSType)
+ : ELFX86AsmBackend(T, OSType) {}
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ return createELFObjectWriter(createELFObjectTargetWriter(),
+ OS, /*IsLittleEndian*/ true);
+ }
+
+ MCELFObjectTargetWriter *createELFObjectTargetWriter() const {
+ return new X86ELFObjectWriter(false, OSType, ELF::EM_386, false);
+ }
+};
+
+class ELFX86_64AsmBackend : public ELFX86AsmBackend {
+public:
+ ELFX86_64AsmBackend(const Target &T, Triple::OSType OSType)
+ : ELFX86AsmBackend(T, OSType) {}
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ return createELFObjectWriter(createELFObjectTargetWriter(),
+ OS, /*IsLittleEndian*/ true);
+ }
+
+ MCELFObjectTargetWriter *createELFObjectTargetWriter() const {
+ return new X86ELFObjectWriter(true, OSType, ELF::EM_X86_64, true);
+ }
+};
+
+class WindowsX86AsmBackend : public X86AsmBackend {
+ bool Is64Bit;
+
+public:
+ WindowsX86AsmBackend(const Target &T, bool is64Bit)
+ : X86AsmBackend(T)
+ , Is64Bit(is64Bit) {
+ }
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ return createWinCOFFObjectWriter(OS, Is64Bit);
+ }
+};
+
+class DarwinX86AsmBackend : public X86AsmBackend {
+public:
+ DarwinX86AsmBackend(const Target &T)
+ : X86AsmBackend(T) { }
+};
+
+class DarwinX86_32AsmBackend : public DarwinX86AsmBackend {
+public:
+ DarwinX86_32AsmBackend(const Target &T)
+ : DarwinX86AsmBackend(T) {}
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ return createX86MachObjectWriter(OS, /*Is64Bit=*/false,
+ object::mach::CTM_i386,
+ object::mach::CSX86_ALL);
+ }
+};
+
+class DarwinX86_64AsmBackend : public DarwinX86AsmBackend {
+public:
+ DarwinX86_64AsmBackend(const Target &T)
+ : DarwinX86AsmBackend(T) {
+ HasReliableSymbolDifference = true;
+ }
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ return createX86MachObjectWriter(OS, /*Is64Bit=*/true,
+ object::mach::CTM_x86_64,
+ object::mach::CSX86_ALL);
+ }
+
+ virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
+ // Temporary labels in the string literals sections require symbols. The
+ // issue is that the x86_64 relocation format does not allow symbol +
+ // offset, and so the linker does not have enough information to resolve the
+ // access to the appropriate atom unless an external relocation is used. For
+ // non-cstring sections, we expect the compiler to use a non-temporary label
+ // for anything that could have an addend pointing outside the symbol.
+ //
+ // See <rdar://problem/4765733>.
+ const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
+ return SMO.getType() == MCSectionMachO::S_CSTRING_LITERALS;
+ }
+
+ virtual bool isSectionAtomizable(const MCSection &Section) const {
+ const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
+ // Fixed sized data sections are uniqued, they cannot be diced into atoms.
+ switch (SMO.getType()) {
+ default:
+ return true;
+
+ case MCSectionMachO::S_4BYTE_LITERALS:
+ case MCSectionMachO::S_8BYTE_LITERALS:
+ case MCSectionMachO::S_16BYTE_LITERALS:
+ case MCSectionMachO::S_LITERAL_POINTERS:
+ case MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS:
+ case MCSectionMachO::S_LAZY_SYMBOL_POINTERS:
+ case MCSectionMachO::S_MOD_INIT_FUNC_POINTERS:
+ case MCSectionMachO::S_MOD_TERM_FUNC_POINTERS:
+ case MCSectionMachO::S_INTERPOSING:
+ return false;
+ }
+ }
+};
+
+} // end anonymous namespace
+
+MCAsmBackend *llvm::createX86_32AsmBackend(const Target &T, StringRef TT) {
+ Triple TheTriple(TT);
+
+ if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO)
+ return new DarwinX86_32AsmBackend(T);
+
+ if (TheTriple.isOSWindows())
+ return new WindowsX86AsmBackend(T, false);
+
+ return new ELFX86_32AsmBackend(T, TheTriple.getOS());
+}
+
+MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T, StringRef TT) {
+ Triple TheTriple(TT);
+
+ if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO)
+ return new DarwinX86_64AsmBackend(T);
+
+ if (TheTriple.isOSWindows())
+ return new WindowsX86AsmBackend(T, true);
+
+ return new ELFX86_64AsmBackend(T, TheTriple.getOS());
+}
diff --git a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
new file mode 100644
index 0000000..e6ba705
--- /dev/null
+++ b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -0,0 +1,548 @@
+//===-- X86BaseInfo.h - Top level definitions for X86 -------- --*- 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 small standalone helper functions and enum definitions for
+// the X86 target useful for the compiler back-end and the MC libraries.
+// As such, it deliberately does not include references to LLVM core
+// code gen types, passes, etc..
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef X86BASEINFO_H
+#define X86BASEINFO_H
+
+#include "X86MCTargetDesc.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+
+namespace llvm {
+
+namespace X86 {
+ // Enums for memory operand decoding. Each memory operand is represented with
+ // a 5 operand sequence in the form:
+ // [BaseReg, ScaleAmt, IndexReg, Disp, Segment]
+ // These enums help decode this.
+ enum {
+ AddrBaseReg = 0,
+ AddrScaleAmt = 1,
+ AddrIndexReg = 2,
+ AddrDisp = 3,
+
+ /// AddrSegmentReg - The operand # of the segment in the memory operand.
+ AddrSegmentReg = 4,
+
+ /// AddrNumOperands - Total number of operands in a memory reference.
+ AddrNumOperands = 5
+ };
+} // end namespace X86;
+
+
+/// X86II - This namespace holds all of the target specific flags that
+/// instruction info tracks.
+///
+namespace X86II {
+ /// Target Operand Flag enum.
+ enum TOF {
+ //===------------------------------------------------------------------===//
+ // X86 Specific MachineOperand flags.
+
+ MO_NO_FLAG,
+
+ /// MO_GOT_ABSOLUTE_ADDRESS - On a symbol operand, this represents a
+ /// relocation of:
+ /// SYMBOL_LABEL + [. - PICBASELABEL]
+ MO_GOT_ABSOLUTE_ADDRESS,
+
+ /// MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the
+ /// immediate should get the value of the symbol minus the PIC base label:
+ /// SYMBOL_LABEL - PICBASELABEL
+ MO_PIC_BASE_OFFSET,
+
+ /// MO_GOT - On a symbol operand this indicates that the immediate is the
+ /// offset to the GOT entry for the symbol name from the base of the GOT.
+ ///
+ /// See the X86-64 ELF ABI supplement for more details.
+ /// SYMBOL_LABEL @GOT
+ MO_GOT,
+
+ /// MO_GOTOFF - On a symbol operand this indicates that the immediate is
+ /// the offset to the location of the symbol name from the base of the GOT.
+ ///
+ /// See the X86-64 ELF ABI supplement for more details.
+ /// SYMBOL_LABEL @GOTOFF
+ MO_GOTOFF,
+
+ /// MO_GOTPCREL - On a symbol operand this indicates that the immediate is
+ /// offset to the GOT entry for the symbol name from the current code
+ /// location.
+ ///
+ /// See the X86-64 ELF ABI supplement for more details.
+ /// SYMBOL_LABEL @GOTPCREL
+ MO_GOTPCREL,
+
+ /// MO_PLT - On a symbol operand this indicates that the immediate is
+ /// offset to the PLT entry of symbol name from the current code location.
+ ///
+ /// See the X86-64 ELF ABI supplement for more details.
+ /// SYMBOL_LABEL @PLT
+ MO_PLT,
+
+ /// MO_TLSGD - On a symbol operand this indicates that the immediate is
+ /// some TLS offset.
+ ///
+ /// See 'ELF Handling for Thread-Local Storage' for more details.
+ /// SYMBOL_LABEL @TLSGD
+ MO_TLSGD,
+
+ /// MO_GOTTPOFF - On a symbol operand this indicates that the immediate is
+ /// some TLS offset.
+ ///
+ /// See 'ELF Handling for Thread-Local Storage' for more details.
+ /// SYMBOL_LABEL @GOTTPOFF
+ MO_GOTTPOFF,
+
+ /// MO_INDNTPOFF - On a symbol operand this indicates that the immediate is
+ /// some TLS offset.
+ ///
+ /// See 'ELF Handling for Thread-Local Storage' for more details.
+ /// SYMBOL_LABEL @INDNTPOFF
+ MO_INDNTPOFF,
+
+ /// MO_TPOFF - On a symbol operand this indicates that the immediate is
+ /// some TLS offset.
+ ///
+ /// See 'ELF Handling for Thread-Local Storage' for more details.
+ /// SYMBOL_LABEL @TPOFF
+ MO_TPOFF,
+
+ /// MO_NTPOFF - On a symbol operand this indicates that the immediate is
+ /// some TLS offset.
+ ///
+ /// See 'ELF Handling for Thread-Local Storage' for more details.
+ /// SYMBOL_LABEL @NTPOFF
+ MO_NTPOFF,
+
+ /// MO_DLLIMPORT - On a symbol operand "FOO", this indicates that the
+ /// reference is actually to the "__imp_FOO" symbol. This is used for
+ /// dllimport linkage on windows.
+ MO_DLLIMPORT,
+
+ /// MO_DARWIN_STUB - On a symbol operand "FOO", this indicates that the
+ /// reference is actually to the "FOO$stub" symbol. This is used for calls
+ /// and jumps to external functions on Tiger and earlier.
+ MO_DARWIN_STUB,
+
+ /// MO_DARWIN_NONLAZY - On a symbol operand "FOO", this indicates that the
+ /// reference is actually to the "FOO$non_lazy_ptr" symbol, which is a
+ /// non-PIC-base-relative reference to a non-hidden dyld lazy pointer stub.
+ MO_DARWIN_NONLAZY,
+
+ /// MO_DARWIN_NONLAZY_PIC_BASE - On a symbol operand "FOO", this indicates
+ /// that the reference is actually to "FOO$non_lazy_ptr - PICBASE", which is
+ /// a PIC-base-relative reference to a non-hidden dyld lazy pointer stub.
+ MO_DARWIN_NONLAZY_PIC_BASE,
+
+ /// MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE - On a symbol operand "FOO", this
+ /// indicates that the reference is actually to "FOO$non_lazy_ptr -PICBASE",
+ /// which is a PIC-base-relative reference to a hidden dyld lazy pointer
+ /// stub.
+ MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE,
+
+ /// MO_TLVP - On a symbol operand this indicates that the immediate is
+ /// some TLS offset.
+ ///
+ /// This is the TLS offset for the Darwin TLS mechanism.
+ MO_TLVP,
+
+ /// MO_TLVP_PIC_BASE - On a symbol operand this indicates that the immediate
+ /// is some TLS offset from the picbase.
+ ///
+ /// This is the 32-bit TLS offset for Darwin TLS in PIC mode.
+ MO_TLVP_PIC_BASE
+ };
+
+ enum {
+ //===------------------------------------------------------------------===//
+ // Instruction encodings. These are the standard/most common forms for X86
+ // instructions.
+ //
+
+ // PseudoFrm - This represents an instruction that is a pseudo instruction
+ // or one that has not been implemented yet. It is illegal to code generate
+ // it, but tolerated for intermediate implementation stages.
+ Pseudo = 0,
+
+ /// Raw - This form is for instructions that don't have any operands, so
+ /// they are just a fixed opcode value, like 'leave'.
+ RawFrm = 1,
+
+ /// AddRegFrm - This form is used for instructions like 'push r32' that have
+ /// their one register operand added to their opcode.
+ AddRegFrm = 2,
+
+ /// MRMDestReg - This form is used for instructions that use the Mod/RM byte
+ /// to specify a destination, which in this case is a register.
+ ///
+ MRMDestReg = 3,
+
+ /// MRMDestMem - This form is used for instructions that use the Mod/RM byte
+ /// to specify a destination, which in this case is memory.
+ ///
+ MRMDestMem = 4,
+
+ /// MRMSrcReg - This form is used for instructions that use the Mod/RM byte
+ /// to specify a source, which in this case is a register.
+ ///
+ MRMSrcReg = 5,
+
+ /// MRMSrcMem - This form is used for instructions that use the Mod/RM byte
+ /// to specify a source, which in this case is memory.
+ ///
+ MRMSrcMem = 6,
+
+ /// MRM[0-7][rm] - These forms are used to represent instructions that use
+ /// a Mod/RM byte, and use the middle field to hold extended opcode
+ /// information. In the intel manual these are represented as /0, /1, ...
+ ///
+
+ // First, instructions that operate on a register r/m operand...
+ MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19, // Format /0 /1 /2 /3
+ MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23, // Format /4 /5 /6 /7
+
+ // Next, instructions that operate on a memory r/m operand...
+ MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27, // Format /0 /1 /2 /3
+ MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31, // Format /4 /5 /6 /7
+
+ // MRMInitReg - This form is used for instructions whose source and
+ // destinations are the same register.
+ MRMInitReg = 32,
+
+ //// MRM_C1 - A mod/rm byte of exactly 0xC1.
+ MRM_C1 = 33,
+ MRM_C2 = 34,
+ MRM_C3 = 35,
+ MRM_C4 = 36,
+ MRM_C8 = 37,
+ MRM_C9 = 38,
+ MRM_E8 = 39,
+ MRM_F0 = 40,
+ MRM_F8 = 41,
+ MRM_F9 = 42,
+ MRM_D0 = 45,
+ MRM_D1 = 46,
+
+ /// RawFrmImm8 - This is used for the ENTER instruction, which has two
+ /// immediates, the first of which is a 16-bit immediate (specified by
+ /// the imm encoding) and the second is a 8-bit fixed value.
+ RawFrmImm8 = 43,
+
+ /// RawFrmImm16 - This is used for CALL FAR instructions, which have two
+ /// immediates, the first of which is a 16 or 32-bit immediate (specified by
+ /// the imm encoding) and the second is a 16-bit fixed value. In the AMD
+ /// manual, this operand is described as pntr16:32 and pntr16:16
+ RawFrmImm16 = 44,
+
+ FormMask = 63,
+
+ //===------------------------------------------------------------------===//
+ // Actual flags...
+
+ // OpSize - Set if this instruction requires an operand size prefix (0x66),
+ // which most often indicates that the instruction operates on 16 bit data
+ // instead of 32 bit data.
+ OpSize = 1 << 6,
+
+ // AsSize - Set if this instruction requires an operand size prefix (0x67),
+ // which most often indicates that the instruction address 16 bit address
+ // instead of 32 bit address (or 32 bit address in 64 bit mode).
+ AdSize = 1 << 7,
+
+ //===------------------------------------------------------------------===//
+ // Op0Mask - There are several prefix bytes that are used to form two byte
+ // opcodes. These are currently 0x0F, 0xF3, and 0xD8-0xDF. This mask is
+ // used to obtain the setting of this field. If no bits in this field is
+ // set, there is no prefix byte for obtaining a multibyte opcode.
+ //
+ Op0Shift = 8,
+ Op0Mask = 0x1F << Op0Shift,
+
+ // TB - TwoByte - Set if this instruction has a two byte opcode, which
+ // starts with a 0x0F byte before the real opcode.
+ TB = 1 << Op0Shift,
+
+ // REP - The 0xF3 prefix byte indicating repetition of the following
+ // instruction.
+ REP = 2 << Op0Shift,
+
+ // D8-DF - These escape opcodes are used by the floating point unit. These
+ // values must remain sequential.
+ D8 = 3 << Op0Shift, D9 = 4 << Op0Shift,
+ DA = 5 << Op0Shift, DB = 6 << Op0Shift,
+ DC = 7 << Op0Shift, DD = 8 << Op0Shift,
+ DE = 9 << Op0Shift, DF = 10 << Op0Shift,
+
+ // XS, XD - These prefix codes are for single and double precision scalar
+ // floating point operations performed in the SSE registers.
+ XD = 11 << Op0Shift, XS = 12 << Op0Shift,
+
+ // T8, TA, A6, A7 - Prefix after the 0x0F prefix.
+ T8 = 13 << Op0Shift, TA = 14 << Op0Shift,
+ A6 = 15 << Op0Shift, A7 = 16 << Op0Shift,
+
+ // TF - Prefix before and after 0x0F
+ TF = 17 << Op0Shift,
+
+ //===------------------------------------------------------------------===//
+ // REX_W - REX prefixes are instruction prefixes used in 64-bit mode.
+ // They are used to specify GPRs and SSE registers, 64-bit operand size,
+ // etc. We only cares about REX.W and REX.R bits and only the former is
+ // statically determined.
+ //
+ REXShift = Op0Shift + 5,
+ REX_W = 1 << REXShift,
+
+ //===------------------------------------------------------------------===//
+ // This three-bit field describes the size of an immediate operand. Zero is
+ // unused so that we can tell if we forgot to set a value.
+ ImmShift = REXShift + 1,
+ ImmMask = 7 << ImmShift,
+ Imm8 = 1 << ImmShift,
+ Imm8PCRel = 2 << ImmShift,
+ Imm16 = 3 << ImmShift,
+ Imm16PCRel = 4 << ImmShift,
+ Imm32 = 5 << ImmShift,
+ Imm32PCRel = 6 << ImmShift,
+ Imm64 = 7 << ImmShift,
+
+ //===------------------------------------------------------------------===//
+ // FP Instruction Classification... Zero is non-fp instruction.
+
+ // FPTypeMask - Mask for all of the FP types...
+ FPTypeShift = ImmShift + 3,
+ FPTypeMask = 7 << FPTypeShift,
+
+ // NotFP - The default, set for instructions that do not use FP registers.
+ NotFP = 0 << FPTypeShift,
+
+ // ZeroArgFP - 0 arg FP instruction which implicitly pushes ST(0), f.e. fld0
+ ZeroArgFP = 1 << FPTypeShift,
+
+ // OneArgFP - 1 arg FP instructions which implicitly read ST(0), such as fst
+ OneArgFP = 2 << FPTypeShift,
+
+ // OneArgFPRW - 1 arg FP instruction which implicitly read ST(0) and write a
+ // result back to ST(0). For example, fcos, fsqrt, etc.
+ //
+ OneArgFPRW = 3 << FPTypeShift,
+
+ // TwoArgFP - 2 arg FP instructions which implicitly read ST(0), and an
+ // explicit argument, storing the result to either ST(0) or the implicit
+ // argument. For example: fadd, fsub, fmul, etc...
+ TwoArgFP = 4 << FPTypeShift,
+
+ // CompareFP - 2 arg FP instructions which implicitly read ST(0) and an
+ // explicit argument, but have no destination. Example: fucom, fucomi, ...
+ CompareFP = 5 << FPTypeShift,
+
+ // CondMovFP - "2 operand" floating point conditional move instructions.
+ CondMovFP = 6 << FPTypeShift,
+
+ // SpecialFP - Special instruction forms. Dispatch by opcode explicitly.
+ SpecialFP = 7 << FPTypeShift,
+
+ // Lock prefix
+ LOCKShift = FPTypeShift + 3,
+ LOCK = 1 << LOCKShift,
+
+ // Segment override prefixes. Currently we just need ability to address
+ // stuff in gs and fs segments.
+ SegOvrShift = LOCKShift + 1,
+ SegOvrMask = 3 << SegOvrShift,
+ FS = 1 << SegOvrShift,
+ GS = 2 << SegOvrShift,
+
+ // Execution domain for SSE instructions in bits 23, 24.
+ // 0 in bits 23-24 means normal, non-SSE instruction.
+ SSEDomainShift = SegOvrShift + 2,
+
+ OpcodeShift = SSEDomainShift + 2,
+
+ //===------------------------------------------------------------------===//
+ /// VEX - The opcode prefix used by AVX instructions
+ VEXShift = OpcodeShift + 8,
+ VEX = 1U << 0,
+
+ /// VEX_W - Has a opcode specific functionality, but is used in the same
+ /// way as REX_W is for regular SSE instructions.
+ VEX_W = 1U << 1,
+
+ /// VEX_4V - Used to specify an additional AVX/SSE register. Several 2
+ /// address instructions in SSE are represented as 3 address ones in AVX
+ /// and the additional register is encoded in VEX_VVVV prefix.
+ VEX_4V = 1U << 2,
+
+ /// VEX_I8IMM - Specifies that the last register used in a AVX instruction,
+ /// must be encoded in the i8 immediate field. This usually happens in
+ /// instructions with 4 operands.
+ VEX_I8IMM = 1U << 3,
+
+ /// VEX_L - Stands for a bit in the VEX opcode prefix meaning the current
+ /// instruction uses 256-bit wide registers. This is usually auto detected
+ /// if a VR256 register is used, but some AVX instructions also have this
+ /// field marked when using a f256 memory references.
+ VEX_L = 1U << 4,
+
+ // VEX_LIG - Specifies that this instruction ignores the L-bit in the VEX
+ // prefix. Usually used for scalar instructions. Needed by disassembler.
+ VEX_LIG = 1U << 5,
+
+ /// Has3DNow0F0FOpcode - This flag indicates that the instruction uses the
+ /// wacky 0x0F 0x0F prefix for 3DNow! instructions. The manual documents
+ /// this as having a 0x0F prefix with a 0x0F opcode, and each instruction
+ /// storing a classifier in the imm8 field. To simplify our implementation,
+ /// we handle this by storeing the classifier in the opcode field and using
+ /// this flag to indicate that the encoder should do the wacky 3DNow! thing.
+ Has3DNow0F0FOpcode = 1U << 6
+ };
+
+ // getBaseOpcodeFor - This function returns the "base" X86 opcode for the
+ // specified machine instruction.
+ //
+ static inline unsigned char getBaseOpcodeFor(uint64_t TSFlags) {
+ return TSFlags >> X86II::OpcodeShift;
+ }
+
+ static inline bool hasImm(uint64_t TSFlags) {
+ return (TSFlags & X86II::ImmMask) != 0;
+ }
+
+ /// getSizeOfImm - Decode the "size of immediate" field from the TSFlags field
+ /// of the specified instruction.
+ static inline unsigned getSizeOfImm(uint64_t TSFlags) {
+ switch (TSFlags & X86II::ImmMask) {
+ default: assert(0 && "Unknown immediate size");
+ case X86II::Imm8:
+ case X86II::Imm8PCRel: return 1;
+ case X86II::Imm16:
+ case X86II::Imm16PCRel: return 2;
+ case X86II::Imm32:
+ case X86II::Imm32PCRel: return 4;
+ case X86II::Imm64: return 8;
+ }
+ }
+
+ /// isImmPCRel - Return true if the immediate of the specified instruction's
+ /// TSFlags indicates that it is pc relative.
+ static inline unsigned isImmPCRel(uint64_t TSFlags) {
+ switch (TSFlags & X86II::ImmMask) {
+ default: assert(0 && "Unknown immediate size");
+ case X86II::Imm8PCRel:
+ case X86II::Imm16PCRel:
+ case X86II::Imm32PCRel:
+ return true;
+ case X86II::Imm8:
+ case X86II::Imm16:
+ case X86II::Imm32:
+ case X86II::Imm64:
+ return false;
+ }
+ }
+
+ /// getMemoryOperandNo - The function returns the MCInst operand # for the
+ /// first field of the memory operand. If the instruction doesn't have a
+ /// memory operand, this returns -1.
+ ///
+ /// Note that this ignores tied operands. If there is a tied register which
+ /// is duplicated in the MCInst (e.g. "EAX = addl EAX, [mem]") it is only
+ /// counted as one operand.
+ ///
+ static inline int getMemoryOperandNo(uint64_t TSFlags) {
+ switch (TSFlags & X86II::FormMask) {
+ case X86II::MRMInitReg: assert(0 && "FIXME: Remove this form");
+ default: assert(0 && "Unknown FormMask value in getMemoryOperandNo!");
+ case X86II::Pseudo:
+ case X86II::RawFrm:
+ case X86II::AddRegFrm:
+ case X86II::MRMDestReg:
+ case X86II::MRMSrcReg:
+ case X86II::RawFrmImm8:
+ case X86II::RawFrmImm16:
+ return -1;
+ case X86II::MRMDestMem:
+ return 0;
+ case X86II::MRMSrcMem: {
+ bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V;
+ unsigned FirstMemOp = 1;
+ if (HasVEX_4V)
+ ++FirstMemOp;// Skip the register source (which is encoded in VEX_VVVV).
+
+ // FIXME: Maybe lea should have its own form? This is a horrible hack.
+ //if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r ||
+ // Opcode == X86::LEA16r || Opcode == X86::LEA32r)
+ return FirstMemOp;
+ }
+ case X86II::MRM0r: case X86II::MRM1r:
+ case X86II::MRM2r: case X86II::MRM3r:
+ case X86II::MRM4r: case X86II::MRM5r:
+ case X86II::MRM6r: case X86II::MRM7r:
+ return -1;
+ case X86II::MRM0m: case X86II::MRM1m:
+ case X86II::MRM2m: case X86II::MRM3m:
+ case X86II::MRM4m: case X86II::MRM5m:
+ case X86II::MRM6m: case X86II::MRM7m:
+ return 0;
+ case X86II::MRM_C1:
+ case X86II::MRM_C2:
+ case X86II::MRM_C3:
+ case X86II::MRM_C4:
+ case X86II::MRM_C8:
+ case X86II::MRM_C9:
+ case X86II::MRM_E8:
+ case X86II::MRM_F0:
+ case X86II::MRM_F8:
+ case X86II::MRM_F9:
+ case X86II::MRM_D0:
+ case X86II::MRM_D1:
+ return -1;
+ }
+ }
+
+ /// isX86_64ExtendedReg - Is the MachineOperand a x86-64 extended (r8 or
+ /// higher) register? e.g. r8, xmm8, xmm13, etc.
+ static inline bool isX86_64ExtendedReg(unsigned RegNo) {
+ switch (RegNo) {
+ default: break;
+ case X86::R8: case X86::R9: case X86::R10: case X86::R11:
+ case X86::R12: case X86::R13: case X86::R14: case X86::R15:
+ case X86::R8D: case X86::R9D: case X86::R10D: case X86::R11D:
+ case X86::R12D: case X86::R13D: case X86::R14D: case X86::R15D:
+ case X86::R8W: case X86::R9W: case X86::R10W: case X86::R11W:
+ case X86::R12W: case X86::R13W: case X86::R14W: case X86::R15W:
+ case X86::R8B: case X86::R9B: case X86::R10B: case X86::R11B:
+ case X86::R12B: case X86::R13B: case X86::R14B: case X86::R15B:
+ case X86::XMM8: case X86::XMM9: case X86::XMM10: case X86::XMM11:
+ case X86::XMM12: case X86::XMM13: case X86::XMM14: case X86::XMM15:
+ case X86::YMM8: case X86::YMM9: case X86::YMM10: case X86::YMM11:
+ case X86::YMM12: case X86::YMM13: case X86::YMM14: case X86::YMM15:
+ case X86::CR8: case X86::CR9: case X86::CR10: case X86::CR11:
+ case X86::CR12: case X86::CR13: case X86::CR14: case X86::CR15:
+ return true;
+ }
+ return false;
+ }
+
+ static inline bool isX86_64NonExtLowByteReg(unsigned reg) {
+ return (reg == X86::SPL || reg == X86::BPL ||
+ reg == X86::SIL || reg == X86::DIL);
+ }
+}
+
+} // end namespace llvm;
+
+#endif
diff --git a/lib/Target/X86/X86FixupKinds.h b/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
index 17d242a..17d242a 100644
--- a/lib/Target/X86/X86FixupKinds.h
+++ b/lib/Target/X86/MCTargetDesc/X86FixupKinds.h
diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
new file mode 100644
index 0000000..2eee112
--- /dev/null
+++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -0,0 +1,1074 @@
+//===-- X86/X86MCCodeEmitter.cpp - Convert X86 code to machine code -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the X86MCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mccodeemitter"
+#include "MCTargetDesc/X86MCTargetDesc.h"
+#include "MCTargetDesc/X86BaseInfo.h"
+#include "MCTargetDesc/X86FixupKinds.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+class X86MCCodeEmitter : public MCCodeEmitter {
+ X86MCCodeEmitter(const X86MCCodeEmitter &); // DO NOT IMPLEMENT
+ void operator=(const X86MCCodeEmitter &); // DO NOT IMPLEMENT
+ const MCInstrInfo &MCII;
+ const MCSubtargetInfo &STI;
+ MCContext &Ctx;
+public:
+ X86MCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
+ MCContext &ctx)
+ : MCII(mcii), STI(sti), Ctx(ctx) {
+ }
+
+ ~X86MCCodeEmitter() {}
+
+ bool is64BitMode() const {
+ // FIXME: Can tablegen auto-generate this?
+ return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
+ }
+
+ static unsigned GetX86RegNum(const MCOperand &MO) {
+ return X86_MC::getX86RegNum(MO.getReg());
+ }
+
+ // On regular x86, both XMM0-XMM7 and XMM8-XMM15 are encoded in the range
+ // 0-7 and the difference between the 2 groups is given by the REX prefix.
+ // In the VEX prefix, registers are seen sequencially from 0-15 and encoded
+ // in 1's complement form, example:
+ //
+ // ModRM field => XMM9 => 1
+ // VEX.VVVV => XMM9 => ~9
+ //
+ // See table 4-35 of Intel AVX Programming Reference for details.
+ static unsigned char getVEXRegisterEncoding(const MCInst &MI,
+ unsigned OpNum) {
+ unsigned SrcReg = MI.getOperand(OpNum).getReg();
+ unsigned SrcRegNum = GetX86RegNum(MI.getOperand(OpNum));
+ if ((SrcReg >= X86::XMM8 && SrcReg <= X86::XMM15) ||
+ (SrcReg >= X86::YMM8 && SrcReg <= X86::YMM15))
+ SrcRegNum += 8;
+
+ // The registers represented through VEX_VVVV should
+ // be encoded in 1's complement form.
+ return (~SrcRegNum) & 0xf;
+ }
+
+ void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
+ OS << (char)C;
+ ++CurByte;
+ }
+
+ void EmitConstant(uint64_t Val, unsigned Size, unsigned &CurByte,
+ raw_ostream &OS) const {
+ // Output the constant in little endian byte order.
+ for (unsigned i = 0; i != Size; ++i) {
+ EmitByte(Val & 255, CurByte, OS);
+ Val >>= 8;
+ }
+ }
+
+ void EmitImmediate(const MCOperand &Disp,
+ unsigned ImmSize, MCFixupKind FixupKind,
+ unsigned &CurByte, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups,
+ int ImmOffset = 0) const;
+
+ inline static unsigned char ModRMByte(unsigned Mod, unsigned RegOpcode,
+ unsigned RM) {
+ assert(Mod < 4 && RegOpcode < 8 && RM < 8 && "ModRM Fields out of range!");
+ return RM | (RegOpcode << 3) | (Mod << 6);
+ }
+
+ void EmitRegModRMByte(const MCOperand &ModRMReg, unsigned RegOpcodeFld,
+ unsigned &CurByte, raw_ostream &OS) const {
+ EmitByte(ModRMByte(3, RegOpcodeFld, GetX86RegNum(ModRMReg)), CurByte, OS);
+ }
+
+ void EmitSIBByte(unsigned SS, unsigned Index, unsigned Base,
+ unsigned &CurByte, raw_ostream &OS) const {
+ // SIB byte is in the same format as the ModRMByte.
+ EmitByte(ModRMByte(SS, Index, Base), CurByte, OS);
+ }
+
+
+ void EmitMemModRMByte(const MCInst &MI, unsigned Op,
+ unsigned RegOpcodeField,
+ uint64_t TSFlags, unsigned &CurByte, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ void EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand,
+ const MCInst &MI, const MCInstrDesc &Desc,
+ raw_ostream &OS) const;
+
+ void EmitSegmentOverridePrefix(uint64_t TSFlags, unsigned &CurByte,
+ int MemOperand, const MCInst &MI,
+ raw_ostream &OS) const;
+
+ void EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand,
+ const MCInst &MI, const MCInstrDesc &Desc,
+ raw_ostream &OS) const;
+};
+
+} // end anonymous namespace
+
+
+MCCodeEmitter *llvm::createX86MCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new X86MCCodeEmitter(MCII, STI, Ctx);
+}
+
+/// isDisp8 - Return true if this signed displacement fits in a 8-bit
+/// sign-extended field.
+static bool isDisp8(int Value) {
+ return Value == (signed char)Value;
+}
+
+/// getImmFixupKind - Return the appropriate fixup kind to use for an immediate
+/// in an instruction with the specified TSFlags.
+static MCFixupKind getImmFixupKind(uint64_t TSFlags) {
+ unsigned Size = X86II::getSizeOfImm(TSFlags);
+ bool isPCRel = X86II::isImmPCRel(TSFlags);
+
+ return MCFixup::getKindForSize(Size, isPCRel);
+}
+
+/// Is32BitMemOperand - Return true if the specified instruction with a memory
+/// operand should emit the 0x67 prefix byte in 64-bit mode due to a 32-bit
+/// memory operand. Op specifies the operand # of the memoperand.
+static bool Is32BitMemOperand(const MCInst &MI, unsigned Op) {
+ const MCOperand &BaseReg = MI.getOperand(Op+X86::AddrBaseReg);
+ const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg);
+
+ if ((BaseReg.getReg() != 0 &&
+ X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg.getReg())) ||
+ (IndexReg.getReg() != 0 &&
+ X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg.getReg())))
+ return true;
+ return false;
+}
+
+/// StartsWithGlobalOffsetTable - Return true for the simple cases where this
+/// expression starts with _GLOBAL_OFFSET_TABLE_. This is a needed to support
+/// PIC on ELF i386 as that symbol is magic. We check only simple case that
+/// are know to be used: _GLOBAL_OFFSET_TABLE_ by itself or at the start
+/// of a binary expression.
+static bool StartsWithGlobalOffsetTable(const MCExpr *Expr) {
+ if (Expr->getKind() == MCExpr::Binary) {
+ const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Expr);
+ Expr = BE->getLHS();
+ }
+
+ if (Expr->getKind() != MCExpr::SymbolRef)
+ return false;
+
+ const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
+ const MCSymbol &S = Ref->getSymbol();
+ return S.getName() == "_GLOBAL_OFFSET_TABLE_";
+}
+
+void X86MCCodeEmitter::
+EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
+ unsigned &CurByte, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups, int ImmOffset) const {
+ const MCExpr *Expr = NULL;
+ if (DispOp.isImm()) {
+ // If this is a simple integer displacement that doesn't require a
+ // relocation, emit it now.
+ if (FixupKind != FK_PCRel_1 &&
+ FixupKind != FK_PCRel_2 &&
+ FixupKind != FK_PCRel_4) {
+ EmitConstant(DispOp.getImm()+ImmOffset, Size, CurByte, OS);
+ return;
+ }
+ Expr = MCConstantExpr::Create(DispOp.getImm(), Ctx);
+ } else {
+ Expr = DispOp.getExpr();
+ }
+
+ // If we have an immoffset, add it to the expression.
+ if ((FixupKind == FK_Data_4 ||
+ FixupKind == MCFixupKind(X86::reloc_signed_4byte)) &&
+ StartsWithGlobalOffsetTable(Expr)) {
+ assert(ImmOffset == 0);
+
+ FixupKind = MCFixupKind(X86::reloc_global_offset_table);
+ ImmOffset = CurByte;
+ }
+
+ // If the fixup is pc-relative, we need to bias the value to be relative to
+ // the start of the field, not the end of the field.
+ if (FixupKind == FK_PCRel_4 ||
+ FixupKind == MCFixupKind(X86::reloc_riprel_4byte) ||
+ FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load))
+ ImmOffset -= 4;
+ if (FixupKind == FK_PCRel_2)
+ ImmOffset -= 2;
+ if (FixupKind == FK_PCRel_1)
+ ImmOffset -= 1;
+
+ if (ImmOffset)
+ Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(ImmOffset, Ctx),
+ Ctx);
+
+ // Emit a symbolic constant as a fixup and 4 zeros.
+ Fixups.push_back(MCFixup::Create(CurByte, Expr, FixupKind));
+ EmitConstant(0, Size, CurByte, OS);
+}
+
+void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op,
+ unsigned RegOpcodeField,
+ uint64_t TSFlags, unsigned &CurByte,
+ raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const{
+ const MCOperand &Disp = MI.getOperand(Op+X86::AddrDisp);
+ const MCOperand &Base = MI.getOperand(Op+X86::AddrBaseReg);
+ const MCOperand &Scale = MI.getOperand(Op+X86::AddrScaleAmt);
+ const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg);
+ unsigned BaseReg = Base.getReg();
+
+ // Handle %rip relative addressing.
+ if (BaseReg == X86::RIP) { // [disp32+RIP] in X86-64 mode
+ assert(is64BitMode() && "Rip-relative addressing requires 64-bit mode");
+ assert(IndexReg.getReg() == 0 && "Invalid rip-relative address");
+ EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS);
+
+ unsigned FixupKind = X86::reloc_riprel_4byte;
+
+ // movq loads are handled with a special relocation form which allows the
+ // linker to eliminate some loads for GOT references which end up in the
+ // same linkage unit.
+ if (MI.getOpcode() == X86::MOV64rm)
+ FixupKind = X86::reloc_riprel_4byte_movq_load;
+
+ // rip-relative addressing is actually relative to the *next* instruction.
+ // Since an immediate can follow the mod/rm byte for an instruction, this
+ // means that we need to bias the immediate field of the instruction with
+ // the size of the immediate field. If we have this case, add it into the
+ // expression to emit.
+ int ImmSize = X86II::hasImm(TSFlags) ? X86II::getSizeOfImm(TSFlags) : 0;
+
+ EmitImmediate(Disp, 4, MCFixupKind(FixupKind),
+ CurByte, OS, Fixups, -ImmSize);
+ return;
+ }
+
+ unsigned BaseRegNo = BaseReg ? GetX86RegNum(Base) : -1U;
+
+ // Determine whether a SIB byte is needed.
+ // If no BaseReg, issue a RIP relative instruction only if the MCE can
+ // resolve addresses on-the-fly, otherwise use SIB (Intel Manual 2A, table
+ // 2-7) and absolute references.
+
+ if (// The SIB byte must be used if there is an index register.
+ IndexReg.getReg() == 0 &&
+ // The SIB byte must be used if the base is ESP/RSP/R12, all of which
+ // encode to an R/M value of 4, which indicates that a SIB byte is
+ // present.
+ BaseRegNo != N86::ESP &&
+ // If there is no base register and we're in 64-bit mode, we need a SIB
+ // byte to emit an addr that is just 'disp32' (the non-RIP relative form).
+ (!is64BitMode() || BaseReg != 0)) {
+
+ if (BaseReg == 0) { // [disp32] in X86-32 mode
+ EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS);
+ EmitImmediate(Disp, 4, FK_Data_4, CurByte, OS, Fixups);
+ return;
+ }
+
+ // If the base is not EBP/ESP and there is no displacement, use simple
+ // indirect register encoding, this handles addresses like [EAX]. The
+ // encoding for [EBP] with no displacement means [disp32] so we handle it
+ // by emitting a displacement of 0 below.
+ if (Disp.isImm() && Disp.getImm() == 0 && BaseRegNo != N86::EBP) {
+ EmitByte(ModRMByte(0, RegOpcodeField, BaseRegNo), CurByte, OS);
+ return;
+ }
+
+ // Otherwise, if the displacement fits in a byte, encode as [REG+disp8].
+ if (Disp.isImm() && isDisp8(Disp.getImm())) {
+ EmitByte(ModRMByte(1, RegOpcodeField, BaseRegNo), CurByte, OS);
+ EmitImmediate(Disp, 1, FK_Data_1, CurByte, OS, Fixups);
+ return;
+ }
+
+ // Otherwise, emit the most general non-SIB encoding: [REG+disp32]
+ EmitByte(ModRMByte(2, RegOpcodeField, BaseRegNo), CurByte, OS);
+ EmitImmediate(Disp, 4, MCFixupKind(X86::reloc_signed_4byte), CurByte, OS,
+ Fixups);
+ return;
+ }
+
+ // We need a SIB byte, so start by outputting the ModR/M byte first
+ assert(IndexReg.getReg() != X86::ESP &&
+ IndexReg.getReg() != X86::RSP && "Cannot use ESP as index reg!");
+
+ bool ForceDisp32 = false;
+ bool ForceDisp8 = false;
+ if (BaseReg == 0) {
+ // If there is no base register, we emit the special case SIB byte with
+ // MOD=0, BASE=5, to JUST get the index, scale, and displacement.
+ EmitByte(ModRMByte(0, RegOpcodeField, 4), CurByte, OS);
+ ForceDisp32 = true;
+ } else if (!Disp.isImm()) {
+ // Emit the normal disp32 encoding.
+ EmitByte(ModRMByte(2, RegOpcodeField, 4), CurByte, OS);
+ ForceDisp32 = true;
+ } else if (Disp.getImm() == 0 &&
+ // Base reg can't be anything that ends up with '5' as the base
+ // reg, it is the magic [*] nomenclature that indicates no base.
+ BaseRegNo != N86::EBP) {
+ // Emit no displacement ModR/M byte
+ EmitByte(ModRMByte(0, RegOpcodeField, 4), CurByte, OS);
+ } else if (isDisp8(Disp.getImm())) {
+ // Emit the disp8 encoding.
+ EmitByte(ModRMByte(1, RegOpcodeField, 4), CurByte, OS);
+ ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP
+ } else {
+ // Emit the normal disp32 encoding.
+ EmitByte(ModRMByte(2, RegOpcodeField, 4), CurByte, OS);
+ }
+
+ // Calculate what the SS field value should be...
+ static const unsigned SSTable[] = { ~0U, 0, 1, ~0U, 2, ~0U, ~0U, ~0U, 3 };
+ unsigned SS = SSTable[Scale.getImm()];
+
+ if (BaseReg == 0) {
+ // Handle the SIB byte for the case where there is no base, see Intel
+ // Manual 2A, table 2-7. The displacement has already been output.
+ unsigned IndexRegNo;
+ if (IndexReg.getReg())
+ IndexRegNo = GetX86RegNum(IndexReg);
+ else // Examples: [ESP+1*<noreg>+4] or [scaled idx]+disp32 (MOD=0,BASE=5)
+ IndexRegNo = 4;
+ EmitSIBByte(SS, IndexRegNo, 5, CurByte, OS);
+ } else {
+ unsigned IndexRegNo;
+ if (IndexReg.getReg())
+ IndexRegNo = GetX86RegNum(IndexReg);
+ else
+ IndexRegNo = 4; // For example [ESP+1*<noreg>+4]
+ EmitSIBByte(SS, IndexRegNo, GetX86RegNum(Base), CurByte, OS);
+ }
+
+ // Do we need to output a displacement?
+ if (ForceDisp8)
+ EmitImmediate(Disp, 1, FK_Data_1, CurByte, OS, Fixups);
+ else if (ForceDisp32 || Disp.getImm() != 0)
+ EmitImmediate(Disp, 4, MCFixupKind(X86::reloc_signed_4byte), CurByte, OS,
+ Fixups);
+}
+
+/// EmitVEXOpcodePrefix - AVX instructions are encoded using a opcode prefix
+/// called VEX.
+void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
+ int MemOperand, const MCInst &MI,
+ const MCInstrDesc &Desc,
+ raw_ostream &OS) const {
+ bool HasVEX_4V = false;
+ if ((TSFlags >> X86II::VEXShift) & X86II::VEX_4V)
+ HasVEX_4V = true;
+
+ // VEX_R: opcode externsion equivalent to REX.R in
+ // 1's complement (inverted) form
+ //
+ // 1: Same as REX_R=0 (must be 1 in 32-bit mode)
+ // 0: Same as REX_R=1 (64 bit mode only)
+ //
+ unsigned char VEX_R = 0x1;
+
+ // VEX_X: equivalent to REX.X, only used when a
+ // register is used for index in SIB Byte.
+ //
+ // 1: Same as REX.X=0 (must be 1 in 32-bit mode)
+ // 0: Same as REX.X=1 (64-bit mode only)
+ unsigned char VEX_X = 0x1;
+
+ // VEX_B:
+ //
+ // 1: Same as REX_B=0 (ignored in 32-bit mode)
+ // 0: Same as REX_B=1 (64 bit mode only)
+ //
+ unsigned char VEX_B = 0x1;
+
+ // VEX_W: opcode specific (use like REX.W, or used for
+ // opcode extension, or ignored, depending on the opcode byte)
+ unsigned char VEX_W = 0;
+
+ // VEX_5M (VEX m-mmmmm field):
+ //
+ // 0b00000: Reserved for future use
+ // 0b00001: implied 0F leading opcode
+ // 0b00010: implied 0F 38 leading opcode bytes
+ // 0b00011: implied 0F 3A leading opcode bytes
+ // 0b00100-0b11111: Reserved for future use
+ //
+ unsigned char VEX_5M = 0x1;
+
+ // VEX_4V (VEX vvvv field): a register specifier
+ // (in 1's complement form) or 1111 if unused.
+ unsigned char VEX_4V = 0xf;
+
+ // VEX_L (Vector Length):
+ //
+ // 0: scalar or 128-bit vector
+ // 1: 256-bit vector
+ //
+ unsigned char VEX_L = 0;
+
+ // VEX_PP: opcode extension providing equivalent
+ // functionality of a SIMD prefix
+ //
+ // 0b00: None
+ // 0b01: 66
+ // 0b10: F3
+ // 0b11: F2
+ //
+ unsigned char VEX_PP = 0;
+
+ // Encode the operand size opcode prefix as needed.
+ if (TSFlags & X86II::OpSize)
+ VEX_PP = 0x01;
+
+ if ((TSFlags >> X86II::VEXShift) & X86II::VEX_W)
+ VEX_W = 1;
+
+ if ((TSFlags >> X86II::VEXShift) & X86II::VEX_L)
+ VEX_L = 1;
+
+ switch (TSFlags & X86II::Op0Mask) {
+ default: assert(0 && "Invalid prefix!");
+ case X86II::T8: // 0F 38
+ VEX_5M = 0x2;
+ break;
+ case X86II::TA: // 0F 3A
+ VEX_5M = 0x3;
+ break;
+ case X86II::TF: // F2 0F 38
+ VEX_PP = 0x3;
+ VEX_5M = 0x2;
+ break;
+ case X86II::XS: // F3 0F
+ VEX_PP = 0x2;
+ break;
+ case X86II::XD: // F2 0F
+ VEX_PP = 0x3;
+ break;
+ case X86II::A6: // Bypass: Not used by VEX
+ case X86II::A7: // Bypass: Not used by VEX
+ case X86II::TB: // Bypass: Not used by VEX
+ case 0:
+ break; // No prefix!
+ }
+
+ // Set the vector length to 256-bit if YMM0-YMM15 is used
+ for (unsigned i = 0; i != MI.getNumOperands(); ++i) {
+ if (!MI.getOperand(i).isReg())
+ continue;
+ unsigned SrcReg = MI.getOperand(i).getReg();
+ if (SrcReg >= X86::YMM0 && SrcReg <= X86::YMM15)
+ VEX_L = 1;
+ }
+
+ // Classify VEX_B, VEX_4V, VEX_R, VEX_X
+ unsigned CurOp = 0;
+ switch (TSFlags & X86II::FormMask) {
+ case X86II::MRMInitReg: assert(0 && "FIXME: Remove this!");
+ case X86II::MRMDestMem: {
+ // MRMDestMem instructions forms:
+ // MemAddr, src1(ModR/M)
+ // MemAddr, src1(VEX_4V), src2(ModR/M)
+ // MemAddr, src1(ModR/M), imm8
+ //
+ if (X86II::isX86_64ExtendedReg(MI.getOperand(X86::AddrBaseReg).getReg()))
+ VEX_B = 0x0;
+ if (X86II::isX86_64ExtendedReg(MI.getOperand(X86::AddrIndexReg).getReg()))
+ VEX_X = 0x0;
+
+ CurOp = X86::AddrNumOperands;
+ if (HasVEX_4V)
+ VEX_4V = getVEXRegisterEncoding(MI, CurOp++);
+
+ const MCOperand &MO = MI.getOperand(CurOp);
+ if (MO.isReg() && X86II::isX86_64ExtendedReg(MO.getReg()))
+ VEX_R = 0x0;
+ break;
+ }
+ case X86II::MRMSrcMem: {
+ // MRMSrcMem instructions forms:
+ // src1(ModR/M), MemAddr
+ // src1(ModR/M), src2(VEX_4V), MemAddr
+ // src1(ModR/M), MemAddr, imm8
+ // src1(ModR/M), MemAddr, src2(VEX_I8IMM)
+ //
+ if (X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
+ VEX_R = 0x0;
+
+ unsigned MemAddrOffset = 1;
+ if (HasVEX_4V) {
+ VEX_4V = getVEXRegisterEncoding(MI, 1);
+ MemAddrOffset++;
+ }
+
+ if (X86II::isX86_64ExtendedReg(
+ MI.getOperand(MemAddrOffset+X86::AddrBaseReg).getReg()))
+ VEX_B = 0x0;
+ if (X86II::isX86_64ExtendedReg(
+ MI.getOperand(MemAddrOffset+X86::AddrIndexReg).getReg()))
+ VEX_X = 0x0;
+ break;
+ }
+ case X86II::MRM0m: case X86II::MRM1m:
+ case X86II::MRM2m: case X86II::MRM3m:
+ case X86II::MRM4m: case X86II::MRM5m:
+ case X86II::MRM6m: case X86II::MRM7m:
+ // MRM[0-9]m instructions forms:
+ // MemAddr
+ if (X86II::isX86_64ExtendedReg(MI.getOperand(X86::AddrBaseReg).getReg()))
+ VEX_B = 0x0;
+ if (X86II::isX86_64ExtendedReg(MI.getOperand(X86::AddrIndexReg).getReg()))
+ VEX_X = 0x0;
+ break;
+ case X86II::MRMSrcReg:
+ // MRMSrcReg instructions forms:
+ // dst(ModR/M), src1(VEX_4V), src2(ModR/M), src3(VEX_I8IMM)
+ // dst(ModR/M), src1(ModR/M)
+ // dst(ModR/M), src1(ModR/M), imm8
+ //
+ if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg()))
+ VEX_R = 0x0;
+ CurOp++;
+
+ if (HasVEX_4V)
+ VEX_4V = getVEXRegisterEncoding(MI, CurOp++);
+ if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg()))
+ VEX_B = 0x0;
+ break;
+ case X86II::MRMDestReg:
+ // MRMDestReg instructions forms:
+ // dst(ModR/M), src(ModR/M)
+ // dst(ModR/M), src(ModR/M), imm8
+ if (X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
+ VEX_B = 0x0;
+ if (X86II::isX86_64ExtendedReg(MI.getOperand(1).getReg()))
+ VEX_R = 0x0;
+ break;
+ case X86II::MRM0r: case X86II::MRM1r:
+ case X86II::MRM2r: case X86II::MRM3r:
+ case X86II::MRM4r: case X86II::MRM5r:
+ case X86II::MRM6r: case X86II::MRM7r:
+ // MRM0r-MRM7r instructions forms:
+ // dst(VEX_4V), src(ModR/M), imm8
+ VEX_4V = getVEXRegisterEncoding(MI, 0);
+ if (X86II::isX86_64ExtendedReg(MI.getOperand(1).getReg()))
+ VEX_B = 0x0;
+ break;
+ default: // RawFrm
+ break;
+ }
+
+ // Emit segment override opcode prefix as needed.
+ EmitSegmentOverridePrefix(TSFlags, CurByte, MemOperand, MI, OS);
+
+ // VEX opcode prefix can have 2 or 3 bytes
+ //
+ // 3 bytes:
+ // +-----+ +--------------+ +-------------------+
+ // | C4h | | RXB | m-mmmm | | W | vvvv | L | pp |
+ // +-----+ +--------------+ +-------------------+
+ // 2 bytes:
+ // +-----+ +-------------------+
+ // | C5h | | R | vvvv | L | pp |
+ // +-----+ +-------------------+
+ //
+ unsigned char LastByte = VEX_PP | (VEX_L << 2) | (VEX_4V << 3);
+
+ if (VEX_B && VEX_X && !VEX_W && (VEX_5M == 1)) { // 2 byte VEX prefix
+ EmitByte(0xC5, CurByte, OS);
+ EmitByte(LastByte | (VEX_R << 7), CurByte, OS);
+ return;
+ }
+
+ // 3 byte VEX prefix
+ EmitByte(0xC4, CurByte, OS);
+ EmitByte(VEX_R << 7 | VEX_X << 6 | VEX_B << 5 | VEX_5M, CurByte, OS);
+ EmitByte(LastByte | (VEX_W << 7), CurByte, OS);
+}
+
+/// DetermineREXPrefix - Determine if the MCInst has to be encoded with a X86-64
+/// REX prefix which specifies 1) 64-bit instructions, 2) non-default operand
+/// size, and 3) use of X86-64 extended registers.
+static unsigned DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags,
+ const MCInstrDesc &Desc) {
+ unsigned REX = 0;
+ if (TSFlags & X86II::REX_W)
+ REX |= 1 << 3; // set REX.W
+
+ if (MI.getNumOperands() == 0) return REX;
+
+ unsigned NumOps = MI.getNumOperands();
+ // FIXME: MCInst should explicitize the two-addrness.
+ bool isTwoAddr = NumOps > 1 &&
+ Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1;
+
+ // If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix.
+ unsigned i = isTwoAddr ? 1 : 0;
+ for (; i != NumOps; ++i) {
+ const MCOperand &MO = MI.getOperand(i);
+ if (!MO.isReg()) continue;
+ unsigned Reg = MO.getReg();
+ if (!X86II::isX86_64NonExtLowByteReg(Reg)) continue;
+ // FIXME: The caller of DetermineREXPrefix slaps this prefix onto anything
+ // that returns non-zero.
+ REX |= 0x40; // REX fixed encoding prefix
+ break;
+ }
+
+ switch (TSFlags & X86II::FormMask) {
+ case X86II::MRMInitReg: assert(0 && "FIXME: Remove this!");
+ case X86II::MRMSrcReg:
+ if (MI.getOperand(0).isReg() &&
+ X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
+ REX |= 1 << 2; // set REX.R
+ i = isTwoAddr ? 2 : 1;
+ for (; i != NumOps; ++i) {
+ const MCOperand &MO = MI.getOperand(i);
+ if (MO.isReg() && X86II::isX86_64ExtendedReg(MO.getReg()))
+ REX |= 1 << 0; // set REX.B
+ }
+ break;
+ case X86II::MRMSrcMem: {
+ if (MI.getOperand(0).isReg() &&
+ X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
+ REX |= 1 << 2; // set REX.R
+ unsigned Bit = 0;
+ i = isTwoAddr ? 2 : 1;
+ for (; i != NumOps; ++i) {
+ const MCOperand &MO = MI.getOperand(i);
+ if (MO.isReg()) {
+ if (X86II::isX86_64ExtendedReg(MO.getReg()))
+ REX |= 1 << Bit; // set REX.B (Bit=0) and REX.X (Bit=1)
+ Bit++;
+ }
+ }
+ break;
+ }
+ case X86II::MRM0m: case X86II::MRM1m:
+ case X86II::MRM2m: case X86II::MRM3m:
+ case X86II::MRM4m: case X86II::MRM5m:
+ case X86II::MRM6m: case X86II::MRM7m:
+ case X86II::MRMDestMem: {
+ unsigned e = (isTwoAddr ? X86::AddrNumOperands+1 : X86::AddrNumOperands);
+ i = isTwoAddr ? 1 : 0;
+ if (NumOps > e && MI.getOperand(e).isReg() &&
+ X86II::isX86_64ExtendedReg(MI.getOperand(e).getReg()))
+ REX |= 1 << 2; // set REX.R
+ unsigned Bit = 0;
+ for (; i != e; ++i) {
+ const MCOperand &MO = MI.getOperand(i);
+ if (MO.isReg()) {
+ if (X86II::isX86_64ExtendedReg(MO.getReg()))
+ REX |= 1 << Bit; // REX.B (Bit=0) and REX.X (Bit=1)
+ Bit++;
+ }
+ }
+ break;
+ }
+ default:
+ if (MI.getOperand(0).isReg() &&
+ X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
+ REX |= 1 << 0; // set REX.B
+ i = isTwoAddr ? 2 : 1;
+ for (unsigned e = NumOps; i != e; ++i) {
+ const MCOperand &MO = MI.getOperand(i);
+ if (MO.isReg() && X86II::isX86_64ExtendedReg(MO.getReg()))
+ REX |= 1 << 2; // set REX.R
+ }
+ break;
+ }
+ return REX;
+}
+
+/// EmitSegmentOverridePrefix - Emit segment override opcode prefix as needed
+void X86MCCodeEmitter::EmitSegmentOverridePrefix(uint64_t TSFlags,
+ unsigned &CurByte, int MemOperand,
+ const MCInst &MI,
+ raw_ostream &OS) const {
+ switch (TSFlags & X86II::SegOvrMask) {
+ default: assert(0 && "Invalid segment!");
+ case 0:
+ // No segment override, check for explicit one on memory operand.
+ if (MemOperand != -1) { // If the instruction has a memory operand.
+ switch (MI.getOperand(MemOperand+X86::AddrSegmentReg).getReg()) {
+ default: assert(0 && "Unknown segment register!");
+ case 0: break;
+ case X86::CS: EmitByte(0x2E, CurByte, OS); break;
+ case X86::SS: EmitByte(0x36, CurByte, OS); break;
+ case X86::DS: EmitByte(0x3E, CurByte, OS); break;
+ case X86::ES: EmitByte(0x26, CurByte, OS); break;
+ case X86::FS: EmitByte(0x64, CurByte, OS); break;
+ case X86::GS: EmitByte(0x65, CurByte, OS); break;
+ }
+ }
+ break;
+ case X86II::FS:
+ EmitByte(0x64, CurByte, OS);
+ break;
+ case X86II::GS:
+ EmitByte(0x65, CurByte, OS);
+ break;
+ }
+}
+
+/// EmitOpcodePrefix - Emit all instruction prefixes prior to the opcode.
+///
+/// MemOperand is the operand # of the start of a memory operand if present. If
+/// Not present, it is -1.
+void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
+ int MemOperand, const MCInst &MI,
+ const MCInstrDesc &Desc,
+ raw_ostream &OS) const {
+
+ // Emit the lock opcode prefix as needed.
+ if (TSFlags & X86II::LOCK)
+ EmitByte(0xF0, CurByte, OS);
+
+ // Emit segment override opcode prefix as needed.
+ EmitSegmentOverridePrefix(TSFlags, CurByte, MemOperand, MI, OS);
+
+ // Emit the repeat opcode prefix as needed.
+ if ((TSFlags & X86II::Op0Mask) == X86II::REP)
+ EmitByte(0xF3, CurByte, OS);
+
+ // Emit the address size opcode prefix as needed.
+ if ((TSFlags & X86II::AdSize) ||
+ (MemOperand != -1 && is64BitMode() && Is32BitMemOperand(MI, MemOperand)))
+ EmitByte(0x67, CurByte, OS);
+
+ // Emit the operand size opcode prefix as needed.
+ if (TSFlags & X86II::OpSize)
+ EmitByte(0x66, CurByte, OS);
+
+ bool Need0FPrefix = false;
+ switch (TSFlags & X86II::Op0Mask) {
+ default: assert(0 && "Invalid prefix!");
+ case 0: break; // No prefix!
+ case X86II::REP: break; // already handled.
+ case X86II::TB: // Two-byte opcode prefix
+ case X86II::T8: // 0F 38
+ case X86II::TA: // 0F 3A
+ case X86II::A6: // 0F A6
+ case X86II::A7: // 0F A7
+ Need0FPrefix = true;
+ break;
+ case X86II::TF: // F2 0F 38
+ EmitByte(0xF2, CurByte, OS);
+ Need0FPrefix = true;
+ break;
+ case X86II::XS: // F3 0F
+ EmitByte(0xF3, CurByte, OS);
+ Need0FPrefix = true;
+ break;
+ case X86II::XD: // F2 0F
+ EmitByte(0xF2, CurByte, OS);
+ Need0FPrefix = true;
+ break;
+ case X86II::D8: EmitByte(0xD8, CurByte, OS); break;
+ case X86II::D9: EmitByte(0xD9, CurByte, OS); break;
+ case X86II::DA: EmitByte(0xDA, CurByte, OS); break;
+ case X86II::DB: EmitByte(0xDB, CurByte, OS); break;
+ case X86II::DC: EmitByte(0xDC, CurByte, OS); break;
+ case X86II::DD: EmitByte(0xDD, CurByte, OS); break;
+ case X86II::DE: EmitByte(0xDE, CurByte, OS); break;
+ case X86II::DF: EmitByte(0xDF, CurByte, OS); break;
+ }
+
+ // Handle REX prefix.
+ // FIXME: Can this come before F2 etc to simplify emission?
+ if (is64BitMode()) {
+ if (unsigned REX = DetermineREXPrefix(MI, TSFlags, Desc))
+ EmitByte(0x40 | REX, CurByte, OS);
+ }
+
+ // 0x0F escape code must be emitted just before the opcode.
+ if (Need0FPrefix)
+ EmitByte(0x0F, CurByte, OS);
+
+ // FIXME: Pull this up into previous switch if REX can be moved earlier.
+ switch (TSFlags & X86II::Op0Mask) {
+ case X86II::TF: // F2 0F 38
+ case X86II::T8: // 0F 38
+ EmitByte(0x38, CurByte, OS);
+ break;
+ case X86II::TA: // 0F 3A
+ EmitByte(0x3A, CurByte, OS);
+ break;
+ case X86II::A6: // 0F A6
+ EmitByte(0xA6, CurByte, OS);
+ break;
+ case X86II::A7: // 0F A7
+ EmitByte(0xA7, CurByte, OS);
+ break;
+ }
+}
+
+void X86MCCodeEmitter::
+EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ unsigned Opcode = MI.getOpcode();
+ const MCInstrDesc &Desc = MCII.get(Opcode);
+ uint64_t TSFlags = Desc.TSFlags;
+
+ // Pseudo instructions don't get encoded.
+ if ((TSFlags & X86II::FormMask) == X86II::Pseudo)
+ return;
+
+ // If this is a two-address instruction, skip one of the register operands.
+ // FIXME: This should be handled during MCInst lowering.
+ unsigned NumOps = Desc.getNumOperands();
+ unsigned CurOp = 0;
+ if (NumOps > 1 && Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1)
+ ++CurOp;
+ else if (NumOps > 2 && Desc.getOperandConstraint(NumOps-1, MCOI::TIED_TO)== 0)
+ // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32
+ --NumOps;
+
+ // Keep track of the current byte being emitted.
+ unsigned CurByte = 0;
+
+ // Is this instruction encoded using the AVX VEX prefix?
+ bool HasVEXPrefix = false;
+
+ // It uses the VEX.VVVV field?
+ bool HasVEX_4V = false;
+
+ if ((TSFlags >> X86II::VEXShift) & X86II::VEX)
+ HasVEXPrefix = true;
+ if ((TSFlags >> X86II::VEXShift) & X86II::VEX_4V)
+ HasVEX_4V = true;
+
+ // Determine where the memory operand starts, if present.
+ int MemoryOperand = X86II::getMemoryOperandNo(TSFlags);
+ if (MemoryOperand != -1) MemoryOperand += CurOp;
+
+ if (!HasVEXPrefix)
+ EmitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS);
+ else
+ EmitVEXOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS);
+
+ unsigned char BaseOpcode = X86II::getBaseOpcodeFor(TSFlags);
+
+ if ((TSFlags >> X86II::VEXShift) & X86II::Has3DNow0F0FOpcode)
+ BaseOpcode = 0x0F; // Weird 3DNow! encoding.
+
+ unsigned SrcRegNum = 0;
+ switch (TSFlags & X86II::FormMask) {
+ case X86II::MRMInitReg:
+ assert(0 && "FIXME: Remove this form when the JIT moves to MCCodeEmitter!");
+ default: errs() << "FORM: " << (TSFlags & X86II::FormMask) << "\n";
+ assert(0 && "Unknown FormMask value in X86MCCodeEmitter!");
+ case X86II::Pseudo:
+ assert(0 && "Pseudo instruction shouldn't be emitted");
+ case X86II::RawFrm:
+ EmitByte(BaseOpcode, CurByte, OS);
+ break;
+ case X86II::RawFrmImm8:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitImmediate(MI.getOperand(CurOp++),
+ X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags),
+ CurByte, OS, Fixups);
+ EmitImmediate(MI.getOperand(CurOp++), 1, FK_Data_1, CurByte, OS, Fixups);
+ break;
+ case X86II::RawFrmImm16:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitImmediate(MI.getOperand(CurOp++),
+ X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags),
+ CurByte, OS, Fixups);
+ EmitImmediate(MI.getOperand(CurOp++), 2, FK_Data_2, CurByte, OS, Fixups);
+ break;
+
+ case X86II::AddRegFrm:
+ EmitByte(BaseOpcode + GetX86RegNum(MI.getOperand(CurOp++)), CurByte, OS);
+ break;
+
+ case X86II::MRMDestReg:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitRegModRMByte(MI.getOperand(CurOp),
+ GetX86RegNum(MI.getOperand(CurOp+1)), CurByte, OS);
+ CurOp += 2;
+ break;
+
+ case X86II::MRMDestMem:
+ EmitByte(BaseOpcode, CurByte, OS);
+ SrcRegNum = CurOp + X86::AddrNumOperands;
+
+ if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV)
+ SrcRegNum++;
+
+ EmitMemModRMByte(MI, CurOp,
+ GetX86RegNum(MI.getOperand(SrcRegNum)),
+ TSFlags, CurByte, OS, Fixups);
+ CurOp = SrcRegNum + 1;
+ break;
+
+ case X86II::MRMSrcReg:
+ EmitByte(BaseOpcode, CurByte, OS);
+ SrcRegNum = CurOp + 1;
+
+ if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV)
+ SrcRegNum++;
+
+ EmitRegModRMByte(MI.getOperand(SrcRegNum),
+ GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS);
+ CurOp = SrcRegNum + 1;
+ break;
+
+ case X86II::MRMSrcMem: {
+ int AddrOperands = X86::AddrNumOperands;
+ unsigned FirstMemOp = CurOp+1;
+ if (HasVEX_4V) {
+ ++AddrOperands;
+ ++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV).
+ }
+
+ EmitByte(BaseOpcode, CurByte, OS);
+
+ EmitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)),
+ TSFlags, CurByte, OS, Fixups);
+ CurOp += AddrOperands + 1;
+ break;
+ }
+
+ case X86II::MRM0r: case X86II::MRM1r:
+ case X86II::MRM2r: case X86II::MRM3r:
+ case X86II::MRM4r: case X86II::MRM5r:
+ case X86II::MRM6r: case X86II::MRM7r:
+ if (HasVEX_4V) // Skip the register dst (which is encoded in VEX_VVVV).
+ CurOp++;
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitRegModRMByte(MI.getOperand(CurOp++),
+ (TSFlags & X86II::FormMask)-X86II::MRM0r,
+ CurByte, OS);
+ break;
+ case X86II::MRM0m: case X86II::MRM1m:
+ case X86II::MRM2m: case X86II::MRM3m:
+ case X86II::MRM4m: case X86II::MRM5m:
+ case X86II::MRM6m: case X86II::MRM7m:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitMemModRMByte(MI, CurOp, (TSFlags & X86II::FormMask)-X86II::MRM0m,
+ TSFlags, CurByte, OS, Fixups);
+ CurOp += X86::AddrNumOperands;
+ break;
+ case X86II::MRM_C1:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xC1, CurByte, OS);
+ break;
+ case X86II::MRM_C2:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xC2, CurByte, OS);
+ break;
+ case X86II::MRM_C3:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xC3, CurByte, OS);
+ break;
+ case X86II::MRM_C4:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xC4, CurByte, OS);
+ break;
+ case X86II::MRM_C8:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xC8, CurByte, OS);
+ break;
+ case X86II::MRM_C9:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xC9, CurByte, OS);
+ break;
+ case X86II::MRM_E8:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xE8, CurByte, OS);
+ break;
+ case X86II::MRM_F0:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xF0, CurByte, OS);
+ break;
+ case X86II::MRM_F8:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xF8, CurByte, OS);
+ break;
+ case X86II::MRM_F9:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xF9, CurByte, OS);
+ break;
+ case X86II::MRM_D0:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xD0, CurByte, OS);
+ break;
+ case X86II::MRM_D1:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xD1, CurByte, OS);
+ break;
+ }
+
+ // If there is a remaining operand, it must be a trailing immediate. Emit it
+ // according to the right size for the instruction.
+ if (CurOp != NumOps) {
+ // The last source register of a 4 operand instruction in AVX is encoded
+ // in bits[7:4] of a immediate byte, and bits[3:0] are ignored.
+ if ((TSFlags >> X86II::VEXShift) & X86II::VEX_I8IMM) {
+ const MCOperand &MO = MI.getOperand(CurOp++);
+ bool IsExtReg = X86II::isX86_64ExtendedReg(MO.getReg());
+ unsigned RegNum = (IsExtReg ? (1 << 7) : 0);
+ RegNum |= GetX86RegNum(MO) << 4;
+ EmitImmediate(MCOperand::CreateImm(RegNum), 1, FK_Data_1, CurByte, OS,
+ Fixups);
+ } else {
+ unsigned FixupKind;
+ // FIXME: Is there a better way to know that we need a signed relocation?
+ if (MI.getOpcode() == X86::ADD64ri32 ||
+ MI.getOpcode() == X86::MOV64ri32 ||
+ MI.getOpcode() == X86::MOV64mi32 ||
+ MI.getOpcode() == X86::PUSH64i32)
+ FixupKind = X86::reloc_signed_4byte;
+ else
+ FixupKind = getImmFixupKind(TSFlags);
+ EmitImmediate(MI.getOperand(CurOp++),
+ X86II::getSizeOfImm(TSFlags), MCFixupKind(FixupKind),
+ CurByte, OS, Fixups);
+ }
+ }
+
+ if ((TSFlags >> X86II::VEXShift) & X86II::Has3DNow0F0FOpcode)
+ EmitByte(X86II::getBaseOpcodeFor(TSFlags), CurByte, OS);
+
+#ifndef NDEBUG
+ // FIXME: Verify.
+ if (/*!Desc.isVariadic() &&*/ CurOp != NumOps) {
+ errs() << "Cannot encode all operands of: ";
+ MI.dump();
+ errs() << '\n';
+ abort();
+ }
+#endif
+}
diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
index b77f37b..f98d5e3 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
@@ -13,12 +13,18 @@
#include "X86MCTargetDesc.h"
#include "X86MCAsmInfo.h"
+#include "InstPrinter/X86ATTInstPrinter.h"
+#include "InstPrinter/X86IntelInstPrinter.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/MC/MCCodeGenInfo.h"
+#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_REGINFO_MC_DESC
#include "X86GenRegisterInfo.inc"
@@ -34,9 +40,16 @@ using namespace llvm;
std::string X86_MC::ParseX86Triple(StringRef TT) {
Triple TheTriple(TT);
+ std::string FS;
if (TheTriple.getArch() == Triple::x86_64)
- return "+64bit-mode";
- return "-64bit-mode";
+ FS = "+64bit-mode";
+ else
+ FS = "-64bit-mode";
+ if (TheTriple.getOS() == Triple::NativeClient)
+ FS += ",+nacl-mode";
+ else
+ FS += ",-nacl-mode";
+ return FS;
}
/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
@@ -107,6 +120,135 @@ void X86_MC::DetectFamilyModel(unsigned EAX, unsigned &Family,
}
}
+unsigned X86_MC::getDwarfRegFlavour(StringRef TT, bool isEH) {
+ Triple TheTriple(TT);
+ if (TheTriple.getArch() == Triple::x86_64)
+ return DWARFFlavour::X86_64;
+
+ if (TheTriple.isOSDarwin())
+ return isEH ? DWARFFlavour::X86_32_DarwinEH : DWARFFlavour::X86_32_Generic;
+ if (TheTriple.getOS() == Triple::MinGW32 ||
+ TheTriple.getOS() == Triple::Cygwin)
+ // Unsupported by now, just quick fallback
+ return DWARFFlavour::X86_32_Generic;
+ return DWARFFlavour::X86_32_Generic;
+}
+
+/// getX86RegNum - This function maps LLVM register identifiers to their X86
+/// specific numbering, which is used in various places encoding instructions.
+unsigned X86_MC::getX86RegNum(unsigned RegNo) {
+ switch(RegNo) {
+ case X86::RAX: case X86::EAX: case X86::AX: case X86::AL: return N86::EAX;
+ case X86::RCX: case X86::ECX: case X86::CX: case X86::CL: return N86::ECX;
+ case X86::RDX: case X86::EDX: case X86::DX: case X86::DL: return N86::EDX;
+ case X86::RBX: case X86::EBX: case X86::BX: case X86::BL: return N86::EBX;
+ case X86::RSP: case X86::ESP: case X86::SP: case X86::SPL: case X86::AH:
+ return N86::ESP;
+ case X86::RBP: case X86::EBP: case X86::BP: case X86::BPL: case X86::CH:
+ return N86::EBP;
+ case X86::RSI: case X86::ESI: case X86::SI: case X86::SIL: case X86::DH:
+ return N86::ESI;
+ case X86::RDI: case X86::EDI: case X86::DI: case X86::DIL: case X86::BH:
+ return N86::EDI;
+
+ case X86::R8: case X86::R8D: case X86::R8W: case X86::R8B:
+ return N86::EAX;
+ case X86::R9: case X86::R9D: case X86::R9W: case X86::R9B:
+ return N86::ECX;
+ case X86::R10: case X86::R10D: case X86::R10W: case X86::R10B:
+ return N86::EDX;
+ case X86::R11: case X86::R11D: case X86::R11W: case X86::R11B:
+ return N86::EBX;
+ case X86::R12: case X86::R12D: case X86::R12W: case X86::R12B:
+ return N86::ESP;
+ case X86::R13: case X86::R13D: case X86::R13W: case X86::R13B:
+ return N86::EBP;
+ case X86::R14: case X86::R14D: case X86::R14W: case X86::R14B:
+ return N86::ESI;
+ case X86::R15: case X86::R15D: case X86::R15W: case X86::R15B:
+ return N86::EDI;
+
+ case X86::ST0: case X86::ST1: case X86::ST2: case X86::ST3:
+ case X86::ST4: case X86::ST5: case X86::ST6: case X86::ST7:
+ return RegNo-X86::ST0;
+
+ case X86::XMM0: case X86::XMM8:
+ case X86::YMM0: case X86::YMM8: case X86::MM0:
+ return 0;
+ case X86::XMM1: case X86::XMM9:
+ case X86::YMM1: case X86::YMM9: case X86::MM1:
+ return 1;
+ case X86::XMM2: case X86::XMM10:
+ case X86::YMM2: case X86::YMM10: case X86::MM2:
+ return 2;
+ case X86::XMM3: case X86::XMM11:
+ case X86::YMM3: case X86::YMM11: case X86::MM3:
+ return 3;
+ case X86::XMM4: case X86::XMM12:
+ case X86::YMM4: case X86::YMM12: case X86::MM4:
+ return 4;
+ case X86::XMM5: case X86::XMM13:
+ case X86::YMM5: case X86::YMM13: case X86::MM5:
+ return 5;
+ case X86::XMM6: case X86::XMM14:
+ case X86::YMM6: case X86::YMM14: case X86::MM6:
+ return 6;
+ case X86::XMM7: case X86::XMM15:
+ case X86::YMM7: case X86::YMM15: case X86::MM7:
+ return 7;
+
+ case X86::ES: return 0;
+ case X86::CS: return 1;
+ case X86::SS: return 2;
+ case X86::DS: return 3;
+ case X86::FS: return 4;
+ case X86::GS: return 5;
+
+ case X86::CR0: case X86::CR8 : case X86::DR0: return 0;
+ case X86::CR1: case X86::CR9 : case X86::DR1: return 1;
+ case X86::CR2: case X86::CR10: case X86::DR2: return 2;
+ case X86::CR3: case X86::CR11: case X86::DR3: return 3;
+ case X86::CR4: case X86::CR12: case X86::DR4: return 4;
+ case X86::CR5: case X86::CR13: case X86::DR5: return 5;
+ case X86::CR6: case X86::CR14: case X86::DR6: return 6;
+ case X86::CR7: case X86::CR15: case X86::DR7: return 7;
+
+ // Pseudo index registers are equivalent to a "none"
+ // scaled index (See Intel Manual 2A, table 2-3)
+ case X86::EIZ:
+ case X86::RIZ:
+ return 4;
+
+ default:
+ assert((int(RegNo) > 0) && "Unknown physical register!");
+ return 0;
+ }
+}
+
+void X86_MC::InitLLVM2SEHRegisterMapping(MCRegisterInfo *MRI) {
+ // FIXME: TableGen these.
+ for (unsigned Reg = X86::NoRegister+1; Reg < X86::NUM_TARGET_REGS; ++Reg) {
+ int SEH = X86_MC::getX86RegNum(Reg);
+ switch (Reg) {
+ case X86::R8: case X86::R8D: case X86::R8W: case X86::R8B:
+ case X86::R9: case X86::R9D: case X86::R9W: case X86::R9B:
+ case X86::R10: case X86::R10D: case X86::R10W: case X86::R10B:
+ case X86::R11: case X86::R11D: case X86::R11W: case X86::R11B:
+ case X86::R12: case X86::R12D: case X86::R12W: case X86::R12B:
+ case X86::R13: case X86::R13D: case X86::R13W: case X86::R13B:
+ case X86::R14: case X86::R14D: case X86::R14W: case X86::R14B:
+ case X86::R15: case X86::R15D: case X86::R15W: case X86::R15B:
+ case X86::XMM8: case X86::XMM9: case X86::XMM10: case X86::XMM11:
+ case X86::XMM12: case X86::XMM13: case X86::XMM14: case X86::XMM15:
+ case X86::YMM8: case X86::YMM9: case X86::YMM10: case X86::YMM11:
+ case X86::YMM12: case X86::YMM13: case X86::YMM14: case X86::YMM15:
+ SEH += 8;
+ break;
+ }
+ MRI->mapLLVMRegToSEHReg(Reg, SEH);
+ }
+}
+
MCSubtargetInfo *X86_MC::createX86MCSubtargetInfo(StringRef TT, StringRef CPU,
StringRef FS) {
std::string ArchFS = X86_MC::ParseX86Triple(TT);
@@ -131,55 +273,191 @@ MCSubtargetInfo *X86_MC::createX86MCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-// Force static initialization.
-extern "C" void LLVMInitializeX86MCSubtargetInfo() {
- TargetRegistry::RegisterMCSubtargetInfo(TheX86_32Target,
- X86_MC::createX86MCSubtargetInfo);
- TargetRegistry::RegisterMCSubtargetInfo(TheX86_64Target,
- X86_MC::createX86MCSubtargetInfo);
-}
-
static MCInstrInfo *createX86MCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
InitX86MCInstrInfo(X);
return X;
}
-extern "C" void LLVMInitializeX86MCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(TheX86_32Target, createX86MCInstrInfo);
- TargetRegistry::RegisterMCInstrInfo(TheX86_64Target, createX86MCInstrInfo);
-}
+static MCRegisterInfo *createX86MCRegisterInfo(StringRef TT) {
+ Triple TheTriple(TT);
+ unsigned RA = (TheTriple.getArch() == Triple::x86_64)
+ ? X86::RIP // Should have dwarf #16.
+ : X86::EIP; // Should have dwarf #8.
-static MCRegisterInfo *createX86MCRegisterInfo() {
MCRegisterInfo *X = new MCRegisterInfo();
- InitX86MCRegisterInfo(X);
+ InitX86MCRegisterInfo(X, RA,
+ X86_MC::getDwarfRegFlavour(TT, false),
+ X86_MC::getDwarfRegFlavour(TT, true));
+ X86_MC::InitLLVM2SEHRegisterMapping(X);
return X;
}
-extern "C" void LLVMInitializeX86MCRegInfo() {
- TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo);
- TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo);
-}
-
-
static MCAsmInfo *createX86MCAsmInfo(const Target &T, StringRef TT) {
Triple TheTriple(TT);
+ bool is64Bit = TheTriple.getArch() == Triple::x86_64;
+ MCAsmInfo *MAI;
if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) {
- if (TheTriple.getArch() == Triple::x86_64)
- return new X86_64MCAsmInfoDarwin(TheTriple);
+ if (is64Bit)
+ MAI = new X86_64MCAsmInfoDarwin(TheTriple);
else
- return new X86MCAsmInfoDarwin(TheTriple);
+ MAI = new X86MCAsmInfoDarwin(TheTriple);
+ } else if (TheTriple.isOSWindows()) {
+ MAI = new X86MCAsmInfoCOFF(TheTriple);
+ } else {
+ MAI = new X86ELFMCAsmInfo(TheTriple);
}
+ // Initialize initial frame state.
+ // Calculate amount of bytes used for return address storing
+ int stackGrowth = is64Bit ? -8 : -4;
+
+ // Initial state of the frame pointer is esp+stackGrowth.
+ MachineLocation Dst(MachineLocation::VirtualFP);
+ MachineLocation Src(is64Bit ? X86::RSP : X86::ESP, stackGrowth);
+ MAI->addInitialFrameState(0, Dst, Src);
+
+ // Add return address to move list
+ MachineLocation CSDst(is64Bit ? X86::RSP : X86::ESP, stackGrowth);
+ MachineLocation CSSrc(is64Bit ? X86::RIP : X86::EIP);
+ MAI->addInitialFrameState(0, CSDst, CSSrc);
+
+ return MAI;
+}
+
+static MCCodeGenInfo *createX86MCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+
+ Triple T(TT);
+ bool is64Bit = T.getArch() == Triple::x86_64;
+
+ if (RM == Reloc::Default) {
+ // Darwin defaults to PIC in 64 bit mode and dynamic-no-pic in 32 bit mode.
+ // Win64 requires rip-rel addressing, thus we force it to PIC. Otherwise we
+ // use static relocation model by default.
+ if (T.isOSDarwin()) {
+ if (is64Bit)
+ RM = Reloc::PIC_;
+ else
+ RM = Reloc::DynamicNoPIC;
+ } else if (T.isOSWindows() && is64Bit)
+ RM = Reloc::PIC_;
+ else
+ RM = Reloc::Static;
+ }
+
+ // ELF and X86-64 don't have a distinct DynamicNoPIC model. DynamicNoPIC
+ // is defined as a model for code which may be used in static or dynamic
+ // executables but not necessarily a shared library. On X86-32 we just
+ // compile in -static mode, in x86-64 we use PIC.
+ if (RM == Reloc::DynamicNoPIC) {
+ if (is64Bit)
+ RM = Reloc::PIC_;
+ else if (!T.isOSDarwin())
+ RM = Reloc::Static;
+ }
+
+ // If we are on Darwin, disallow static relocation model in X86-64 mode, since
+ // the Mach-O file format doesn't support it.
+ if (RM == Reloc::Static && T.isOSDarwin() && is64Bit)
+ RM = Reloc::PIC_;
+
+ // For static codegen, if we're not already set, use Small codegen.
+ if (CM == CodeModel::Default)
+ CM = CodeModel::Small;
+ else if (CM == CodeModel::JITDefault)
+ // 64-bit JIT places everything in the same buffer except external funcs.
+ CM = is64Bit ? CodeModel::Large : CodeModel::Small;
+
+ X->InitMCCodeGenInfo(RM, CM);
+ return X;
+}
+
+static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
+ MCContext &Ctx, MCAsmBackend &MAB,
+ raw_ostream &_OS,
+ MCCodeEmitter *_Emitter,
+ bool RelaxAll,
+ bool NoExecStack) {
+ Triple TheTriple(TT);
+
+ if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO)
+ return createMachOStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll);
+
if (TheTriple.isOSWindows())
- return new X86MCAsmInfoCOFF(TheTriple);
+ return createWinCOFFStreamer(Ctx, MAB, *_Emitter, _OS, RelaxAll);
+
+ return createELFStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll, NoExecStack);
+}
+
+static MCInstPrinter *createX86MCInstPrinter(const Target &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCSubtargetInfo &STI) {
+ if (SyntaxVariant == 0)
+ return new X86ATTInstPrinter(MAI);
+ if (SyntaxVariant == 1)
+ return new X86IntelInstPrinter(MAI);
+ return 0;
+}
- return new X86ELFMCAsmInfo(TheTriple);
+static MCInstrAnalysis *createX86MCInstrAnalysis(const MCInstrInfo *Info) {
+ return new MCInstrAnalysis(Info);
}
-extern "C" void LLVMInitializeX86MCAsmInfo() {
- // Register the target asm info.
+// Force static initialization.
+extern "C" void LLVMInitializeX86TargetMC() {
+ // Register the MC asm info.
RegisterMCAsmInfoFn A(TheX86_32Target, createX86MCAsmInfo);
RegisterMCAsmInfoFn B(TheX86_64Target, createX86MCAsmInfo);
+
+ // Register the MC codegen info.
+ RegisterMCCodeGenInfoFn C(TheX86_32Target, createX86MCCodeGenInfo);
+ RegisterMCCodeGenInfoFn D(TheX86_64Target, createX86MCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheX86_32Target, createX86MCInstrInfo);
+ TargetRegistry::RegisterMCInstrInfo(TheX86_64Target, createX86MCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo);
+ TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(TheX86_32Target,
+ X86_MC::createX86MCSubtargetInfo);
+ TargetRegistry::RegisterMCSubtargetInfo(TheX86_64Target,
+ X86_MC::createX86MCSubtargetInfo);
+
+ // Register the MC instruction analyzer.
+ TargetRegistry::RegisterMCInstrAnalysis(TheX86_32Target,
+ createX86MCInstrAnalysis);
+ TargetRegistry::RegisterMCInstrAnalysis(TheX86_64Target,
+ createX86MCInstrAnalysis);
+
+ // Register the code emitter.
+ TargetRegistry::RegisterMCCodeEmitter(TheX86_32Target,
+ createX86MCCodeEmitter);
+ TargetRegistry::RegisterMCCodeEmitter(TheX86_64Target,
+ createX86MCCodeEmitter);
+
+ // Register the asm backend.
+ TargetRegistry::RegisterMCAsmBackend(TheX86_32Target,
+ createX86_32AsmBackend);
+ TargetRegistry::RegisterMCAsmBackend(TheX86_64Target,
+ createX86_64AsmBackend);
+
+ // Register the object streamer.
+ TargetRegistry::RegisterMCObjectStreamer(TheX86_32Target,
+ createMCStreamer);
+ TargetRegistry::RegisterMCObjectStreamer(TheX86_64Target,
+ createMCStreamer);
+
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(TheX86_32Target,
+ createX86MCInstPrinter);
+ TargetRegistry::RegisterMCInstPrinter(TheX86_64Target,
+ createX86MCInstPrinter);
}
diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
index 89ea22b..c144c51 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
+++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
@@ -14,15 +14,39 @@
#ifndef X86MCTARGETDESC_H
#define X86MCTARGETDESC_H
+#include "llvm/Support/DataTypes.h"
#include <string>
namespace llvm {
+class MCAsmBackend;
+class MCCodeEmitter;
+class MCContext;
+class MCInstrInfo;
+class MCObjectWriter;
+class MCRegisterInfo;
class MCSubtargetInfo;
class Target;
class StringRef;
+class raw_ostream;
extern Target TheX86_32Target, TheX86_64Target;
+/// DWARFFlavour - Flavour of dwarf regnumbers
+///
+namespace DWARFFlavour {
+ enum {
+ X86_64 = 0, X86_32_DarwinEH = 1, X86_32_Generic = 2
+ };
+}
+
+/// N86 namespace - Native X86 register numbers
+///
+namespace N86 {
+ enum {
+ EAX = 0, ECX = 1, EDX = 2, EBX = 3, ESP = 4, EBP = 5, ESI = 6, EDI = 7
+ };
+}
+
namespace X86_MC {
std::string ParseX86Triple(StringRef TT);
@@ -33,13 +57,32 @@ namespace X86_MC {
void DetectFamilyModel(unsigned EAX, unsigned &Family, unsigned &Model);
- /// createARMMCSubtargetInfo - Create a X86 MCSubtargetInfo instance.
+ unsigned getDwarfRegFlavour(StringRef TT, bool isEH);
+
+ unsigned getX86RegNum(unsigned RegNo);
+
+ void InitLLVM2SEHRegisterMapping(MCRegisterInfo *MRI);
+
+ /// createX86MCSubtargetInfo - Create a X86 MCSubtargetInfo instance.
/// This is exposed so Asm parser, etc. do not need to go through
/// TargetRegistry.
MCSubtargetInfo *createX86MCSubtargetInfo(StringRef TT, StringRef CPU,
StringRef FS);
}
+MCCodeEmitter *createX86MCCodeEmitter(const MCInstrInfo &MCII,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx);
+
+MCAsmBackend *createX86_32AsmBackend(const Target &T, StringRef TT);
+MCAsmBackend *createX86_64AsmBackend(const Target &T, StringRef TT);
+
+/// createX86MachObjectWriter - Construct an X86 Mach-O object writer.
+MCObjectWriter *createX86MachObjectWriter(raw_ostream &OS,
+ bool Is64Bit,
+ uint32_t CPUType,
+ uint32_t CPUSubtype);
+
} // End llvm namespace
diff --git a/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
new file mode 100644
index 0000000..f0f1982
--- /dev/null
+++ b/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
@@ -0,0 +1,554 @@
+//===-- X86MachObjectWriter.cpp - X86 Mach-O Writer -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/X86FixupKinds.h"
+#include "MCTargetDesc/X86MCTargetDesc.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCAsmLayout.h"
+#include "llvm/MC/MCMachObjectWriter.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Object/MachOFormat.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+namespace {
+class X86MachObjectWriter : public MCMachObjectTargetWriter {
+ void RecordScatteredRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ unsigned Log2Size,
+ uint64_t &FixedValue);
+ void RecordTLVPRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ uint64_t &FixedValue);
+
+ void RecordX86Relocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ uint64_t &FixedValue);
+ void RecordX86_64Relocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ uint64_t &FixedValue);
+public:
+ X86MachObjectWriter(bool Is64Bit, uint32_t CPUType,
+ uint32_t CPUSubtype)
+ : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
+ /*UseAggressiveSymbolFolding=*/Is64Bit) {}
+
+ void RecordRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm, const MCAsmLayout &Layout,
+ const MCFragment *Fragment, const MCFixup &Fixup,
+ MCValue Target, uint64_t &FixedValue) {
+ if (Writer->is64Bit())
+ RecordX86_64Relocation(Writer, Asm, Layout, Fragment, Fixup, Target,
+ FixedValue);
+ else
+ RecordX86Relocation(Writer, Asm, Layout, Fragment, Fixup, Target,
+ FixedValue);
+ }
+};
+}
+
+static bool isFixupKindRIPRel(unsigned Kind) {
+ return Kind == X86::reloc_riprel_4byte ||
+ Kind == X86::reloc_riprel_4byte_movq_load;
+}
+
+static unsigned getFixupKindLog2Size(unsigned Kind) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("invalid fixup kind!");
+ case FK_PCRel_1:
+ case FK_Data_1: return 0;
+ case FK_PCRel_2:
+ case FK_Data_2: return 1;
+ case FK_PCRel_4:
+ // FIXME: Remove these!!!
+ case X86::reloc_riprel_4byte:
+ case X86::reloc_riprel_4byte_movq_load:
+ case X86::reloc_signed_4byte:
+ case FK_Data_4: return 2;
+ case FK_Data_8: return 3;
+ }
+}
+
+void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ uint64_t &FixedValue) {
+ unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
+ unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind());
+ unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
+
+ // See <reloc.h>.
+ uint32_t FixupOffset =
+ Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
+ uint32_t FixupAddress =
+ Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
+ int64_t Value = 0;
+ unsigned Index = 0;
+ unsigned IsExtern = 0;
+ unsigned Type = 0;
+
+ Value = Target.getConstant();
+
+ if (IsPCRel) {
+ // Compensate for the relocation offset, Darwin x86_64 relocations only have
+ // the addend and appear to have attempted to define it to be the actual
+ // expression addend without the PCrel bias. However, instructions with data
+ // following the relocation are not accommodated for (see comment below
+ // regarding SIGNED{1,2,4}), so it isn't exactly that either.
+ Value += 1LL << Log2Size;
+ }
+
+ if (Target.isAbsolute()) { // constant
+ // SymbolNum of 0 indicates the absolute section.
+ Type = macho::RIT_X86_64_Unsigned;
+ Index = 0;
+
+ // FIXME: I believe this is broken, I don't think the linker can understand
+ // it. I think it would require a local relocation, but I'm not sure if that
+ // would work either. The official way to get an absolute PCrel relocation
+ // is to use an absolute symbol (which we don't support yet).
+ if (IsPCRel) {
+ IsExtern = 1;
+ Type = macho::RIT_X86_64_Branch;
+ }
+ } else if (Target.getSymB()) { // A - B + constant
+ const MCSymbol *A = &Target.getSymA()->getSymbol();
+ MCSymbolData &A_SD = Asm.getSymbolData(*A);
+ const MCSymbolData *A_Base = Asm.getAtom(&A_SD);
+
+ const MCSymbol *B = &Target.getSymB()->getSymbol();
+ MCSymbolData &B_SD = Asm.getSymbolData(*B);
+ const MCSymbolData *B_Base = Asm.getAtom(&B_SD);
+
+ // Neither symbol can be modified.
+ if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
+ Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
+ report_fatal_error("unsupported relocation of modified symbol");
+
+ // We don't support PCrel relocations of differences. Darwin 'as' doesn't
+ // implement most of these correctly.
+ if (IsPCRel)
+ report_fatal_error("unsupported pc-relative relocation of difference");
+
+ // The support for the situation where one or both of the symbols would
+ // require a local relocation is handled just like if the symbols were
+ // external. This is certainly used in the case of debug sections where the
+ // section has only temporary symbols and thus the symbols don't have base
+ // symbols. This is encoded using the section ordinal and non-extern
+ // relocation entries.
+
+ // Darwin 'as' doesn't emit correct relocations for this (it ends up with a
+ // single SIGNED relocation); reject it for now. Except the case where both
+ // symbols don't have a base, equal but both NULL.
+ if (A_Base == B_Base && A_Base)
+ report_fatal_error("unsupported relocation with identical base");
+
+ Value += Writer->getSymbolAddress(&A_SD, Layout) -
+ (A_Base == NULL ? 0 : Writer->getSymbolAddress(A_Base, Layout));
+ Value -= Writer->getSymbolAddress(&B_SD, Layout) -
+ (B_Base == NULL ? 0 : Writer->getSymbolAddress(B_Base, Layout));
+
+ if (A_Base) {
+ Index = A_Base->getIndex();
+ IsExtern = 1;
+ }
+ else {
+ Index = A_SD.getFragment()->getParent()->getOrdinal() + 1;
+ IsExtern = 0;
+ }
+ Type = macho::RIT_X86_64_Unsigned;
+
+ macho::RelocationEntry MRE;
+ MRE.Word0 = FixupOffset;
+ MRE.Word1 = ((Index << 0) |
+ (IsPCRel << 24) |
+ (Log2Size << 25) |
+ (IsExtern << 27) |
+ (Type << 28));
+ Writer->addRelocation(Fragment->getParent(), MRE);
+
+ if (B_Base) {
+ Index = B_Base->getIndex();
+ IsExtern = 1;
+ }
+ else {
+ Index = B_SD.getFragment()->getParent()->getOrdinal() + 1;
+ IsExtern = 0;
+ }
+ Type = macho::RIT_X86_64_Subtractor;
+ } else {
+ const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
+ MCSymbolData &SD = Asm.getSymbolData(*Symbol);
+ const MCSymbolData *Base = Asm.getAtom(&SD);
+
+ // Relocations inside debug sections always use local relocations when
+ // possible. This seems to be done because the debugger doesn't fully
+ // understand x86_64 relocation entries, and expects to find values that
+ // have already been fixed up.
+ if (Symbol->isInSection()) {
+ const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(
+ Fragment->getParent()->getSection());
+ if (Section.hasAttribute(MCSectionMachO::S_ATTR_DEBUG))
+ Base = 0;
+ }
+
+ // x86_64 almost always uses external relocations, except when there is no
+ // symbol to use as a base address (a local symbol with no preceding
+ // non-local symbol).
+ if (Base) {
+ Index = Base->getIndex();
+ IsExtern = 1;
+
+ // Add the local offset, if needed.
+ if (Base != &SD)
+ Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base);
+ } else if (Symbol->isInSection() && !Symbol->isVariable()) {
+ // The index is the section ordinal (1-based).
+ Index = SD.getFragment()->getParent()->getOrdinal() + 1;
+ IsExtern = 0;
+ Value += Writer->getSymbolAddress(&SD, Layout);
+
+ if (IsPCRel)
+ Value -= FixupAddress + (1 << Log2Size);
+ } else if (Symbol->isVariable()) {
+ const MCExpr *Value = Symbol->getVariableValue();
+ int64_t Res;
+ bool isAbs = Value->EvaluateAsAbsolute(Res, Layout,
+ Writer->getSectionAddressMap());
+ if (isAbs) {
+ FixedValue = Res;
+ return;
+ } else {
+ report_fatal_error("unsupported relocation of variable '" +
+ Symbol->getName() + "'");
+ }
+ } else {
+ report_fatal_error("unsupported relocation of undefined symbol '" +
+ Symbol->getName() + "'");
+ }
+
+ MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
+ if (IsPCRel) {
+ if (IsRIPRel) {
+ if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
+ // x86_64 distinguishes movq foo@GOTPCREL so that the linker can
+ // rewrite the movq to an leaq at link time if the symbol ends up in
+ // the same linkage unit.
+ if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load)
+ Type = macho::RIT_X86_64_GOTLoad;
+ else
+ Type = macho::RIT_X86_64_GOT;
+ } else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
+ Type = macho::RIT_X86_64_TLV;
+ } else if (Modifier != MCSymbolRefExpr::VK_None) {
+ report_fatal_error("unsupported symbol modifier in relocation");
+ } else {
+ Type = macho::RIT_X86_64_Signed;
+
+ // The Darwin x86_64 relocation format has a problem where it cannot
+ // encode an address (L<foo> + <constant>) which is outside the atom
+ // containing L<foo>. Generally, this shouldn't occur but it does
+ // happen when we have a RIPrel instruction with data following the
+ // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel
+ // adjustment Darwin x86_64 uses, the offset is still negative and the
+ // linker has no way to recognize this.
+ //
+ // To work around this, Darwin uses several special relocation types
+ // to indicate the offsets. However, the specification or
+ // implementation of these seems to also be incomplete; they should
+ // adjust the addend as well based on the actual encoded instruction
+ // (the additional bias), but instead appear to just look at the final
+ // offset.
+ switch (-(Target.getConstant() + (1LL << Log2Size))) {
+ case 1: Type = macho::RIT_X86_64_Signed1; break;
+ case 2: Type = macho::RIT_X86_64_Signed2; break;
+ case 4: Type = macho::RIT_X86_64_Signed4; break;
+ }
+ }
+ } else {
+ if (Modifier != MCSymbolRefExpr::VK_None)
+ report_fatal_error("unsupported symbol modifier in branch "
+ "relocation");
+
+ Type = macho::RIT_X86_64_Branch;
+ }
+ } else {
+ if (Modifier == MCSymbolRefExpr::VK_GOT) {
+ Type = macho::RIT_X86_64_GOT;
+ } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
+ // GOTPCREL is allowed as a modifier on non-PCrel instructions, in which
+ // case all we do is set the PCrel bit in the relocation entry; this is
+ // used with exception handling, for example. The source is required to
+ // include any necessary offset directly.
+ Type = macho::RIT_X86_64_GOT;
+ IsPCRel = 1;
+ } else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
+ report_fatal_error("TLVP symbol modifier should have been rip-rel");
+ } else if (Modifier != MCSymbolRefExpr::VK_None)
+ report_fatal_error("unsupported symbol modifier in relocation");
+ else
+ Type = macho::RIT_X86_64_Unsigned;
+ }
+ }
+
+ // x86_64 always writes custom values into the fixups.
+ FixedValue = Value;
+
+ // struct relocation_info (8 bytes)
+ macho::RelocationEntry MRE;
+ MRE.Word0 = FixupOffset;
+ MRE.Word1 = ((Index << 0) |
+ (IsPCRel << 24) |
+ (Log2Size << 25) |
+ (IsExtern << 27) |
+ (Type << 28));
+ Writer->addRelocation(Fragment->getParent(), MRE);
+}
+
+void X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ unsigned Log2Size,
+ uint64_t &FixedValue) {
+ uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
+ unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
+ unsigned Type = macho::RIT_Vanilla;
+
+ // See <reloc.h>.
+ const MCSymbol *A = &Target.getSymA()->getSymbol();
+ MCSymbolData *A_SD = &Asm.getSymbolData(*A);
+
+ if (!A_SD->getFragment())
+ report_fatal_error("symbol '" + A->getName() +
+ "' can not be undefined in a subtraction expression");
+
+ uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
+ uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
+ FixedValue += SecAddr;
+ uint32_t Value2 = 0;
+
+ if (const MCSymbolRefExpr *B = Target.getSymB()) {
+ MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
+
+ if (!B_SD->getFragment())
+ report_fatal_error("symbol '" + B->getSymbol().getName() +
+ "' can not be undefined in a subtraction expression");
+
+ // Select the appropriate difference relocation type.
+ //
+ // Note that there is no longer any semantic difference between these two
+ // relocation types from the linkers point of view, this is done solely for
+ // pedantic compatibility with 'as'.
+ Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference :
+ (unsigned)macho::RIT_Generic_LocalDifference;
+ Value2 = Writer->getSymbolAddress(B_SD, Layout);
+ FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
+ }
+
+ // Relocations are written out in reverse order, so the PAIR comes first.
+ if (Type == macho::RIT_Difference ||
+ Type == macho::RIT_Generic_LocalDifference) {
+ macho::RelocationEntry MRE;
+ MRE.Word0 = ((0 << 0) |
+ (macho::RIT_Pair << 24) |
+ (Log2Size << 28) |
+ (IsPCRel << 30) |
+ macho::RF_Scattered);
+ MRE.Word1 = Value2;
+ Writer->addRelocation(Fragment->getParent(), MRE);
+ }
+
+ macho::RelocationEntry MRE;
+ MRE.Word0 = ((FixupOffset << 0) |
+ (Type << 24) |
+ (Log2Size << 28) |
+ (IsPCRel << 30) |
+ macho::RF_Scattered);
+ MRE.Word1 = Value;
+ Writer->addRelocation(Fragment->getParent(), MRE);
+}
+
+void X86MachObjectWriter::RecordTLVPRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ uint64_t &FixedValue) {
+ assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP &&
+ !is64Bit() &&
+ "Should only be called with a 32-bit TLVP relocation!");
+
+ unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
+ uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
+ unsigned IsPCRel = 0;
+
+ // Get the symbol data.
+ MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol());
+ unsigned Index = SD_A->getIndex();
+
+ // We're only going to have a second symbol in pic mode and it'll be a
+ // subtraction from the picbase. For 32-bit pic the addend is the difference
+ // between the picbase and the next address. For 32-bit static the addend is
+ // zero.
+ if (Target.getSymB()) {
+ // If this is a subtraction then we're pcrel.
+ uint32_t FixupAddress =
+ Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
+ MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol());
+ IsPCRel = 1;
+ FixedValue = (FixupAddress - Writer->getSymbolAddress(SD_B, Layout) +
+ Target.getConstant());
+ FixedValue += 1ULL << Log2Size;
+ } else {
+ FixedValue = 0;
+ }
+
+ // struct relocation_info (8 bytes)
+ macho::RelocationEntry MRE;
+ MRE.Word0 = Value;
+ MRE.Word1 = ((Index << 0) |
+ (IsPCRel << 24) |
+ (Log2Size << 25) |
+ (1 << 27) | // Extern
+ (macho::RIT_Generic_TLV << 28)); // Type
+ Writer->addRelocation(Fragment->getParent(), MRE);
+}
+
+void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ uint64_t &FixedValue) {
+ unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
+ unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
+
+ // If this is a 32-bit TLVP reloc it's handled a bit differently.
+ if (Target.getSymA() &&
+ Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
+ RecordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
+ FixedValue);
+ return;
+ }
+
+ // If this is a difference or a defined symbol plus an offset, then we need a
+ // scattered relocation entry. Differences always require scattered
+ // relocations.
+ if (Target.getSymB())
+ return RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
+ Target, Log2Size, FixedValue);
+
+ // Get the symbol data, if any.
+ MCSymbolData *SD = 0;
+ if (Target.getSymA())
+ SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
+
+ // If this is an internal relocation with an offset, it also needs a scattered
+ // relocation entry.
+ uint32_t Offset = Target.getConstant();
+ if (IsPCRel)
+ Offset += 1 << Log2Size;
+ if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD))
+ return RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
+ Target, Log2Size, FixedValue);
+
+ // See <reloc.h>.
+ uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
+ unsigned Index = 0;
+ unsigned IsExtern = 0;
+ unsigned Type = 0;
+
+ if (Target.isAbsolute()) { // constant
+ // SymbolNum of 0 indicates the absolute section.
+ //
+ // FIXME: Currently, these are never generated (see code below). I cannot
+ // find a case where they are actually emitted.
+ Type = macho::RIT_Vanilla;
+ } else {
+ // Resolve constant variables.
+ if (SD->getSymbol().isVariable()) {
+ int64_t Res;
+ if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
+ Res, Layout, Writer->getSectionAddressMap())) {
+ FixedValue = Res;
+ return;
+ }
+ }
+
+ // Check whether we need an external or internal relocation.
+ if (Writer->doesSymbolRequireExternRelocation(SD)) {
+ IsExtern = 1;
+ Index = SD->getIndex();
+ // For external relocations, make sure to offset the fixup value to
+ // compensate for the addend of the symbol address, if it was
+ // undefined. This occurs with weak definitions, for example.
+ if (!SD->Symbol->isUndefined())
+ FixedValue -= Layout.getSymbolOffset(SD);
+ } else {
+ // The index is the section ordinal (1-based).
+ const MCSectionData &SymSD = Asm.getSectionData(
+ SD->getSymbol().getSection());
+ Index = SymSD.getOrdinal() + 1;
+ FixedValue += Writer->getSectionAddress(&SymSD);
+ }
+ if (IsPCRel)
+ FixedValue -= Writer->getSectionAddress(Fragment->getParent());
+
+ Type = macho::RIT_Vanilla;
+ }
+
+ // struct relocation_info (8 bytes)
+ macho::RelocationEntry MRE;
+ MRE.Word0 = FixupOffset;
+ MRE.Word1 = ((Index << 0) |
+ (IsPCRel << 24) |
+ (Log2Size << 25) |
+ (IsExtern << 27) |
+ (Type << 28));
+ Writer->addRelocation(Fragment->getParent(), MRE);
+}
+
+MCObjectWriter *llvm::createX86MachObjectWriter(raw_ostream &OS,
+ bool Is64Bit,
+ uint32_t CPUType,
+ uint32_t CPUSubtype) {
+ return createMachObjectWriter(new X86MachObjectWriter(Is64Bit,
+ CPUType,
+ CPUSubtype),
+ OS, /*IsLittleEndian=*/true);
+}
diff --git a/lib/Target/X86/README-SSE.txt b/lib/Target/X86/README-SSE.txt
index f16ec02..7d901af 100644
--- a/lib/Target/X86/README-SSE.txt
+++ b/lib/Target/X86/README-SSE.txt
@@ -862,7 +862,7 @@ define float @bar(float %x) nounwind {
This IR (from PR6194):
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin10.0.0"
%0 = type { double, double }
diff --git a/lib/Target/X86/README.txt b/lib/Target/X86/README.txt
index 560947a..b407955 100644
--- a/lib/Target/X86/README.txt
+++ b/lib/Target/X86/README.txt
@@ -2,11 +2,6 @@
// Random ideas for the X86 backend.
//===---------------------------------------------------------------------===//
-We should add support for the "movbe" instruction, which does a byte-swapping
-copy (3-addr bswap + memory support?) This is available on Atom processors.
-
-//===---------------------------------------------------------------------===//
-
This should be one DIV/IDIV instruction, not a libcall:
unsigned test(unsigned long long X, unsigned Y) {
@@ -1222,7 +1217,7 @@ Also check why xmm7 is not used at all in the function.
Take the following:
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-S128"
target triple = "i386-apple-darwin8"
@in_exit.4870.b = internal global i1 false ; <i1*> [#uses=2]
define fastcc void @abort_gzip() noreturn nounwind {
@@ -2066,3 +2061,34 @@ The trick is to match "fetch_and_add(X, -C) == C".
//===---------------------------------------------------------------------===//
+unsigned log2(unsigned x) {
+ return x > 1 ? 32-__builtin_clz(x-1) : 0;
+}
+
+generates (x86_64):
+ xorl %eax, %eax
+ cmpl $2, %edi
+ jb LBB0_2
+## BB#1:
+ decl %edi
+ movl $63, %ecx
+ bsrl %edi, %eax
+ cmovel %ecx, %eax
+ xorl $-32, %eax
+ addl $33, %eax
+LBB0_2:
+ ret
+
+The cmov and the early test are redundant:
+ xorl %eax, %eax
+ cmpl $2, %edi
+ jb LBB0_2
+## BB#1:
+ decl %edi
+ bsrl %edi, %eax
+ xorl $-32, %eax
+ addl $33, %eax
+LBB0_2:
+ ret
+
+//===---------------------------------------------------------------------===//
diff --git a/lib/Target/X86/SSEDomainFix.cpp b/lib/Target/X86/SSEDomainFix.cpp
deleted file mode 100644
index 13680c5..0000000
--- a/lib/Target/X86/SSEDomainFix.cpp
+++ /dev/null
@@ -1,506 +0,0 @@
-//===- SSEDomainFix.cpp - Use proper int/float domain for SSE ---*- 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 SSEDomainFix pass.
-//
-// Some 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.
-//
-// This pass changes the variant instructions to minimize domain crossings.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "sse-domain-fix"
-#include "X86InstrInfo.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/ADT/DepthFirstIterator.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-/// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track
-/// of execution domains.
-///
-/// An open DomainValue represents a set of instructions that can still switch
-/// execution domain. Multiple registers may refer to the same open
-/// DomainValue - they will eventually be collapsed to the same execution
-/// domain.
-///
-/// A collapsed DomainValue represents a single register that has been forced
-/// into one of more execution domains. There is a separate collapsed
-/// DomainValue for each register, but it may contain multiple execution
-/// domains. A register value is initially created in a single execution
-/// domain, but if we were forced to pay the penalty of a domain crossing, we
-/// keep track of the fact the the register is now available in multiple
-/// domains.
-namespace {
-struct DomainValue {
- // Basic reference counting.
- unsigned Refs;
-
- // Bitmask of available domains. For an open DomainValue, it is the still
- // possible domains for collapsing. For a collapsed DomainValue it is the
- // domains where the register is available for free.
- unsigned AvailableDomains;
-
- // Position of the last defining instruction.
- unsigned Dist;
-
- // Twiddleable instructions using or defining these registers.
- SmallVector<MachineInstr*, 8> Instrs;
-
- // A collapsed DomainValue has no instructions to twiddle - it simply keeps
- // track of the domains where the registers are already available.
- bool isCollapsed() const { return Instrs.empty(); }
-
- // Is domain available?
- bool hasDomain(unsigned domain) const {
- return AvailableDomains & (1u << domain);
- }
-
- // Mark domain as available.
- void addDomain(unsigned domain) {
- AvailableDomains |= 1u << domain;
- }
-
- // Restrict to a single domain available.
- void setSingleDomain(unsigned domain) {
- AvailableDomains = 1u << domain;
- }
-
- // Return bitmask of domains that are available and in mask.
- unsigned getCommonDomains(unsigned mask) const {
- return AvailableDomains & mask;
- }
-
- // First domain available.
- unsigned getFirstDomain() const {
- return CountTrailingZeros_32(AvailableDomains);
- }
-
- DomainValue() { clear(); }
-
- void clear() {
- Refs = AvailableDomains = Dist = 0;
- Instrs.clear();
- }
-};
-}
-
-static const unsigned NumRegs = 16;
-
-namespace {
-class SSEDomainFixPass : public MachineFunctionPass {
- static char ID;
- SpecificBumpPtrAllocator<DomainValue> Allocator;
- SmallVector<DomainValue*,16> Avail;
-
- MachineFunction *MF;
- const X86InstrInfo *TII;
- const TargetRegisterInfo *TRI;
- MachineBasicBlock *MBB;
- DomainValue **LiveRegs;
- typedef DenseMap<MachineBasicBlock*,DomainValue**> LiveOutMap;
- LiveOutMap LiveOuts;
- unsigned Distance;
-
-public:
- SSEDomainFixPass() : MachineFunctionPass(ID) {}
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- MachineFunctionPass::getAnalysisUsage(AU);
- }
-
- virtual bool runOnMachineFunction(MachineFunction &MF);
-
- virtual const char *getPassName() const {
- return "SSE execution domain fixup";
- }
-
-private:
- // Register mapping.
- int RegIndex(unsigned Reg);
-
- // DomainValue allocation.
- DomainValue *Alloc(int domain = -1);
- void Recycle(DomainValue*);
-
- // LiveRegs manipulations.
- void SetLiveReg(int rx, DomainValue *DV);
- void Kill(int rx);
- void Force(int rx, unsigned domain);
- void Collapse(DomainValue *dv, unsigned domain);
- bool Merge(DomainValue *A, DomainValue *B);
-
- void enterBasicBlock();
- void visitGenericInstr(MachineInstr*);
- void visitSoftInstr(MachineInstr*, unsigned mask);
- void visitHardInstr(MachineInstr*, unsigned domain);
-};
-}
-
-char SSEDomainFixPass::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;
-}
-
-DomainValue *SSEDomainFixPass::Alloc(int domain) {
- DomainValue *dv = Avail.empty() ?
- new(Allocator.Allocate()) DomainValue :
- Avail.pop_back_val();
- dv->Dist = Distance;
- if (domain >= 0)
- dv->addDomain(domain);
- return dv;
-}
-
-void SSEDomainFixPass::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) {
- assert(unsigned(rx) < NumRegs && "Invalid index");
- if (!LiveRegs) {
- LiveRegs = new DomainValue*[NumRegs];
- std::fill(LiveRegs, LiveRegs+NumRegs, (DomainValue*)0);
- }
-
- if (LiveRegs[rx] == dv)
- return;
- if (LiveRegs[rx]) {
- assert(LiveRegs[rx]->Refs && "Bad refcount");
- if (--LiveRegs[rx]->Refs == 0) Recycle(LiveRegs[rx]);
- }
- LiveRegs[rx] = dv;
- if (dv) ++dv->Refs;
-}
-
-// Kill register rx, recycle or collapse any DomainValue.
-void SSEDomainFixPass::Kill(int rx) {
- assert(unsigned(rx) < NumRegs && "Invalid index");
- if (!LiveRegs || !LiveRegs[rx]) return;
-
- // Before killing the last reference to an open DomainValue, collapse it to
- // the first available domain.
- if (LiveRegs[rx]->Refs == 1 && !LiveRegs[rx]->isCollapsed())
- Collapse(LiveRegs[rx], LiveRegs[rx]->getFirstDomain());
- else
- SetLiveReg(rx, 0);
-}
-
-/// Force register rx into domain.
-void SSEDomainFixPass::Force(int rx, unsigned domain) {
- assert(unsigned(rx) < NumRegs && "Invalid index");
- DomainValue *dv;
- if (LiveRegs && (dv = LiveRegs[rx])) {
- if (dv->isCollapsed())
- dv->addDomain(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.
- Collapse(dv, dv->getFirstDomain());
- assert(LiveRegs[rx] && "Not live after collapse?");
- LiveRegs[rx]->addDomain(domain);
- }
- } else {
- // Set up basic collapsed DomainValue.
- SetLiveReg(rx, Alloc(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) {
- assert(dv->hasDomain(domain) && "Cannot collapse");
-
- // Collapse all the instructions.
- while (!dv->Instrs.empty())
- TII->SetSSEDomain(dv->Instrs.pop_back_val(), domain);
- dv->setSingleDomain(domain);
-
- // If there are multiple users, give them new, unique DomainValues.
- if (LiveRegs && dv->Refs > 1)
- for (unsigned rx = 0; rx != NumRegs; ++rx)
- if (LiveRegs[rx] == dv)
- SetLiveReg(rx, Alloc(domain));
-}
-
-/// Merge - All instructions and registers in B are moved to A, and B is
-/// released.
-bool SSEDomainFixPass::Merge(DomainValue *A, DomainValue *B) {
- assert(!A->isCollapsed() && "Cannot merge into collapsed");
- assert(!B->isCollapsed() && "Cannot merge from collapsed");
- if (A == B)
- return true;
- // Restrict to the domains that A and B have in common.
- unsigned common = A->getCommonDomains(B->AvailableDomains);
- if (!common)
- return false;
- A->AvailableDomains = common;
- A->Dist = std::max(A->Dist, B->Dist);
- A->Instrs.append(B->Instrs.begin(), B->Instrs.end());
- for (unsigned rx = 0; rx != NumRegs; ++rx)
- if (LiveRegs[rx] == B)
- SetLiveReg(rx, A);
- return true;
-}
-
-void SSEDomainFixPass::enterBasicBlock() {
- // Try to coalesce live-out registers from predecessors.
- for (MachineBasicBlock::livein_iterator i = MBB->livein_begin(),
- e = MBB->livein_end(); i != e; ++i) {
- int rx = RegIndex(*i);
- if (rx < 0) continue;
- for (MachineBasicBlock::const_pred_iterator pi = MBB->pred_begin(),
- pe = MBB->pred_end(); pi != pe; ++pi) {
- LiveOutMap::const_iterator fi = LiveOuts.find(*pi);
- if (fi == LiveOuts.end()) continue;
- DomainValue *pdv = fi->second[rx];
- if (!pdv) continue;
- if (!LiveRegs || !LiveRegs[rx]) {
- SetLiveReg(rx, pdv);
- continue;
- }
-
- // We have a live DomainValue from more than one predecessor.
- if (LiveRegs[rx]->isCollapsed()) {
- // We are already collapsed, but predecessor is not. Force him.
- unsigned domain = LiveRegs[rx]->getFirstDomain();
- if (!pdv->isCollapsed() && pdv->hasDomain(domain))
- Collapse(pdv, domain);
- continue;
- }
-
- // Currently open, merge in predecessor.
- if (!pdv->isCollapsed())
- Merge(LiveRegs[rx], pdv);
- else
- Force(rx, pdv->getFirstDomain());
- }
- }
-}
-
-// A hard instruction only works in one domain. All input registers will be
-// forced into that domain.
-void SSEDomainFixPass::visitHardInstr(MachineInstr *mi, unsigned domain) {
- // Collapse all uses.
- for (unsigned i = mi->getDesc().getNumDefs(),
- e = mi->getDesc().getNumOperands(); i != e; ++i) {
- MachineOperand &mo = mi->getOperand(i);
- if (!mo.isReg()) continue;
- int rx = RegIndex(mo.getReg());
- if (rx < 0) continue;
- Force(rx, domain);
- }
-
- // Kill all defs and force them.
- for (unsigned i = 0, e = mi->getDesc().getNumDefs(); i != e; ++i) {
- MachineOperand &mo = mi->getOperand(i);
- if (!mo.isReg()) continue;
- int rx = RegIndex(mo.getReg());
- if (rx < 0) continue;
- Kill(rx);
- Force(rx, domain);
- }
-}
-
-// A soft instruction can be changed to work in other domains given by mask.
-void SSEDomainFixPass::visitSoftInstr(MachineInstr *mi, unsigned mask) {
- // Bitmask of available domains for this instruction after taking collapsed
- // operands into account.
- unsigned available = mask;
-
- // Scan the explicit use operands for incoming domains.
- SmallVector<int, 4> used;
- if (LiveRegs)
- for (unsigned i = mi->getDesc().getNumDefs(),
- e = mi->getDesc().getNumOperands(); i != e; ++i) {
- MachineOperand &mo = mi->getOperand(i);
- if (!mo.isReg()) continue;
- int rx = RegIndex(mo.getReg());
- if (rx < 0) continue;
- if (DomainValue *dv = LiveRegs[rx]) {
- // Bitmask of domains that dv and available have in common.
- unsigned common = dv->getCommonDomains(available);
- // Is it possible to use this collapsed register for free?
- if (dv->isCollapsed()) {
- // Restrict available domains to the ones in common with the operand.
- // If there are no common domains, we must pay the cross-domain
- // penalty for this operand.
- if (common) available = common;
- } else if (common)
- // Open DomainValue is compatible, save it for merging.
- used.push_back(rx);
- else
- // Open DomainValue is not compatible with instruction. It is useless
- // now.
- Kill(rx);
- }
- }
-
- // If the collapsed operands force a single domain, propagate the collapse.
- if (isPowerOf2_32(available)) {
- unsigned domain = CountTrailingZeros_32(available);
- TII->SetSSEDomain(mi, domain);
- visitHardInstr(mi, domain);
- return;
- }
-
- // Kill off any remaining uses that don't match available, and build a list of
- // incoming DomainValues that we want to merge.
- SmallVector<DomainValue*,4> doms;
- for (SmallVector<int, 4>::iterator i=used.begin(), e=used.end(); i!=e; ++i) {
- int rx = *i;
- DomainValue *dv = LiveRegs[rx];
- // This useless DomainValue could have been missed above.
- if (!dv->getCommonDomains(available)) {
- Kill(*i);
- continue;
- }
- // sorted, uniqued insert.
- bool inserted = false;
- for (SmallVector<DomainValue*,4>::iterator i = doms.begin(), e = doms.end();
- i != e && !inserted; ++i) {
- if (dv == *i)
- inserted = true;
- else if (dv->Dist < (*i)->Dist) {
- inserted = true;
- doms.insert(i, dv);
- }
- }
- if (!inserted)
- doms.push_back(dv);
- }
-
- // doms are now sorted in order of appearance. Try to merge them all, giving
- // priority to the latest ones.
- DomainValue *dv = 0;
- while (!doms.empty()) {
- if (!dv) {
- dv = doms.pop_back_val();
- continue;
- }
-
- DomainValue *latest = doms.pop_back_val();
- if (Merge(dv, latest)) continue;
-
- // If latest didn't merge, it is useless now. Kill all registers using it.
- for (SmallVector<int,4>::iterator i=used.begin(), e=used.end(); i != e; ++i)
- if (LiveRegs[*i] == latest)
- Kill(*i);
- }
-
- // dv is the DomainValue we are going to use for this instruction.
- if (!dv)
- dv = Alloc();
- dv->Dist = Distance;
- dv->AvailableDomains = available;
- dv->Instrs.push_back(mi);
-
- // Finally set all defs and non-collapsed uses to dv.
- for (unsigned i = 0, e = mi->getDesc().getNumOperands(); i != e; ++i) {
- MachineOperand &mo = mi->getOperand(i);
- if (!mo.isReg()) continue;
- int rx = RegIndex(mo.getReg());
- if (rx < 0) continue;
- if (!LiveRegs || !LiveRegs[rx] || (mo.isDef() && LiveRegs[rx]!=dv)) {
- Kill(rx);
- SetLiveReg(rx, dv);
- }
- }
-}
-
-void SSEDomainFixPass::visitGenericInstr(MachineInstr *mi) {
- // Process explicit defs, kill any XMM registers redefined.
- for (unsigned i = 0, e = mi->getDesc().getNumDefs(); i != e; ++i) {
- MachineOperand &mo = mi->getOperand(i);
- if (!mo.isReg()) continue;
- int rx = RegIndex(mo.getReg());
- if (rx < 0) continue;
- Kill(rx);
- }
-}
-
-bool SSEDomainFixPass::runOnMachineFunction(MachineFunction &mf) {
- MF = &mf;
- TII = static_cast<const X86InstrInfo*>(MF->getTarget().getInstrInfo());
- TRI = MF->getTarget().getRegisterInfo();
- MBB = 0;
- LiveRegs = 0;
- Distance = 0;
- assert(NumRegs == X86::VR128RegClass.getNumRegs() && "Bad regclass");
-
- // If no XMM 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)
- if (MF->getRegInfo().isPhysRegUsed(*I)) {
- anyregs = true;
- break;
- }
- if (!anyregs) return false;
-
- MachineBasicBlock *Entry = MF->begin();
- SmallPtrSet<MachineBasicBlock*, 16> Visited;
- for (df_ext_iterator<MachineBasicBlock*, SmallPtrSet<MachineBasicBlock*, 16> >
- DFI = df_ext_begin(Entry, Visited), DFE = df_ext_end(Entry, Visited);
- DFI != DFE; ++DFI) {
- MBB = *DFI;
- enterBasicBlock();
- for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
- ++I) {
- MachineInstr *mi = I;
- if (mi->isDebugValue()) continue;
- ++Distance;
- std::pair<uint16_t, uint16_t> domp = TII->GetSSEDomain(mi);
- if (domp.first)
- if (domp.second)
- visitSoftInstr(mi, domp.second);
- else
- visitHardInstr(mi, domp.first);
- else if (LiveRegs)
- visitGenericInstr(mi);
- }
-
- // Save live registers at end of MBB - used by enterBasicBlock().
- if (LiveRegs)
- LiveOuts.insert(std::make_pair(MBB, LiveRegs));
- LiveRegs = 0;
- }
-
- // Clear the LiveOuts vectors. Should we also collapse any remaining
- // DomainValues?
- for (LiveOutMap::const_iterator i = LiveOuts.begin(), e = LiveOuts.end();
- i != e; ++i)
- delete[] i->second;
- LiveOuts.clear();
- Avail.clear();
- Allocator.DestroyAll();
-
- return false;
-}
-
-FunctionPass *llvm::createSSEDomainFixPass() {
- return new SSEDomainFixPass();
-}
diff --git a/lib/Target/X86/TargetInfo/CMakeLists.txt b/lib/Target/X86/TargetInfo/CMakeLists.txt
index 90be9f5..4da00fa 100644
--- a/lib/Target/X86/TargetInfo/CMakeLists.txt
+++ b/lib/Target/X86/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMX86Info
X86TargetInfo.cpp
)
-add_dependencies(LLVMX86Info X86CodeGenTable_gen)
+add_llvm_library_dependencies(LLVMX86Info
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMX86Info X86CommonTableGen)
diff --git a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
index 08d4d84..52a67f7 100644
--- a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
+++ b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
@@ -9,7 +9,7 @@
#include "X86.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::TheX86_32Target, llvm::TheX86_64Target;
diff --git a/lib/Target/X86/Utils/CMakeLists.txt b/lib/Target/X86/Utils/CMakeLists.txt
index 3ad5f99..caffd8b 100644
--- a/lib/Target/X86/Utils/CMakeLists.txt
+++ b/lib/Target/X86/Utils/CMakeLists.txt
@@ -3,4 +3,10 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/
add_llvm_library(LLVMX86Utils
X86ShuffleDecode.cpp
)
-add_dependencies(LLVMX86Utils X86CodeGenTable_gen)
+
+add_llvm_library_dependencies(LLVMX86Utils
+ LLVMCore
+ LLVMSupport
+ )
+
+add_dependencies(LLVMX86Utils X86CommonTableGen)
diff --git a/lib/Target/X86/Utils/X86ShuffleDecode.cpp b/lib/Target/X86/Utils/X86ShuffleDecode.cpp
index cd06060..aeb3309 100644
--- a/lib/Target/X86/Utils/X86ShuffleDecode.cpp
+++ b/lib/Target/X86/Utils/X86ShuffleDecode.cpp
@@ -167,24 +167,77 @@ void DecodeUNPCKLPMask(EVT VT,
SmallVectorImpl<unsigned> &ShuffleMask) {
unsigned NumElts = VT.getVectorNumElements();
- // Handle vector lengths > 128 bits. Define a "section" as a set of
- // 128 bits. AVX defines UNPCK* to operate independently on 128-bit
- // sections.
- unsigned NumSections = VT.getSizeInBits() / 128;
- if (NumSections == 0 ) NumSections = 1; // Handle MMX
- unsigned NumSectionElts = NumElts / NumSections;
+ // Handle 128 and 256-bit vector lengths. AVX defines UNPCK* to operate
+ // independently on 128-bit lanes.
+ unsigned NumLanes = VT.getSizeInBits() / 128;
+ if (NumLanes == 0 ) NumLanes = 1; // Handle MMX
+ unsigned NumLaneElts = NumElts / NumLanes;
unsigned Start = 0;
- unsigned End = NumSectionElts / 2;
- for (unsigned s = 0; s < NumSections; ++s) {
+ unsigned End = NumLaneElts / 2;
+ for (unsigned s = 0; s < NumLanes; ++s) {
for (unsigned i = Start; i != End; ++i) {
ShuffleMask.push_back(i); // Reads from dest/src1
- ShuffleMask.push_back(i+NumSectionElts); // Reads from src/src2
+ ShuffleMask.push_back(i+NumLaneElts); // Reads from src/src2
}
// Process the next 128 bits.
- Start += NumSectionElts;
- End += NumSectionElts;
+ Start += NumLaneElts;
+ End += NumLaneElts;
}
}
+// DecodeVPERMILPSMask - Decodes VPERMILPS permutes for any 128-bit 32-bit
+// elements. For 256-bit vectors, it's considered as two 128 lanes, the
+// referenced elements can't cross lanes and the mask of the first lane must
+// be the same of the second.
+void DecodeVPERMILPSMask(unsigned NumElts, unsigned Imm,
+ SmallVectorImpl<unsigned> &ShuffleMask) {
+ unsigned NumLanes = (NumElts*32)/128;
+ unsigned LaneSize = NumElts/NumLanes;
+
+ for (unsigned l = 0; l != NumLanes; ++l) {
+ for (unsigned i = 0; i != LaneSize; ++i) {
+ unsigned Idx = (Imm >> (i*2)) & 0x3 ;
+ ShuffleMask.push_back(Idx+(l*LaneSize));
+ }
+ }
+}
+
+// DecodeVPERMILPDMask - Decodes VPERMILPD permutes for any 128-bit 64-bit
+// elements. For 256-bit vectors, it's considered as two 128 lanes, the
+// referenced elements can't cross lanes but the mask of the first lane can
+// be the different of the second (not like VPERMILPS).
+void DecodeVPERMILPDMask(unsigned NumElts, unsigned Imm,
+ SmallVectorImpl<unsigned> &ShuffleMask) {
+ unsigned NumLanes = (NumElts*64)/128;
+ unsigned LaneSize = NumElts/NumLanes;
+
+ for (unsigned l = 0; l < NumLanes; ++l) {
+ for (unsigned i = l*LaneSize; i < LaneSize*(l+1); ++i) {
+ unsigned Idx = (Imm >> i) & 0x1;
+ ShuffleMask.push_back(Idx+(l*LaneSize));
+ }
+ }
+}
+
+void DecodeVPERM2F128Mask(EVT VT, unsigned Imm,
+ SmallVectorImpl<unsigned> &ShuffleMask) {
+ unsigned HalfSize = VT.getVectorNumElements()/2;
+ unsigned FstHalfBegin = (Imm & 0x3) * HalfSize;
+ unsigned SndHalfBegin = ((Imm >> 4) & 0x3) * HalfSize;
+
+ for (int i = FstHalfBegin, e = FstHalfBegin+HalfSize; i != e; ++i)
+ ShuffleMask.push_back(i);
+ for (int i = SndHalfBegin, e = SndHalfBegin+HalfSize; i != e; ++i)
+ ShuffleMask.push_back(i);
+}
+
+void DecodeVPERM2F128Mask(unsigned Imm,
+ SmallVectorImpl<unsigned> &ShuffleMask) {
+ // VPERM2F128 is used by any 256-bit EVT, but X86InstComments only
+ // has information about the instruction and not the types. So for
+ // instruction comments purpose, assume the 256-bit vector is v4i64.
+ return DecodeVPERM2F128Mask(MVT::v4i64, Imm, ShuffleMask);
+}
+
} // llvm namespace
diff --git a/lib/Target/X86/Utils/X86ShuffleDecode.h b/lib/Target/X86/Utils/X86ShuffleDecode.h
index b18f670..58193e6 100644
--- a/lib/Target/X86/Utils/X86ShuffleDecode.h
+++ b/lib/Target/X86/Utils/X86ShuffleDecode.h
@@ -82,6 +82,26 @@ void DecodeUNPCKLPDMask(unsigned NElts,
void DecodeUNPCKLPMask(EVT VT,
SmallVectorImpl<unsigned> &ShuffleMask);
+
+// DecodeVPERMILPSMask - Decodes VPERMILPS permutes for any 128-bit 32-bit
+// elements. For 256-bit vectors, it's considered as two 128 lanes, the
+// referenced elements can't cross lanes and the mask of the first lane must
+// be the same of the second.
+void DecodeVPERMILPSMask(unsigned NElts, unsigned Imm,
+ SmallVectorImpl<unsigned> &ShuffleMask);
+
+// DecodeVPERMILPDMask - Decodes VPERMILPD permutes for any 128-bit 64-bit
+// elements. For 256-bit vectors, it's considered as two 128 lanes, the
+// referenced elements can't cross lanes but the mask of the first lane can
+// be the different of the second (not like VPERMILPS).
+void DecodeVPERMILPDMask(unsigned NElts, unsigned Imm,
+ SmallVectorImpl<unsigned> &ShuffleMask);
+
+void DecodeVPERM2F128Mask(unsigned Imm,
+ SmallVectorImpl<unsigned> &ShuffleMask);
+void DecodeVPERM2F128Mask(EVT VT, unsigned Imm,
+ SmallVectorImpl<unsigned> &ShuffleMask);
+
} // llvm namespace
#endif
diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h
index ec52dfb..81e9422 100644
--- a/lib/Target/X86/X86.h
+++ b/lib/Target/X86/X86.h
@@ -15,6 +15,7 @@
#ifndef TARGET_X86_H
#define TARGET_X86_H
+#include "MCTargetDesc/X86BaseInfo.h"
#include "MCTargetDesc/X86MCTargetDesc.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Target/TargetMachine.h"
@@ -24,16 +25,8 @@ namespace llvm {
class FunctionPass;
class JITCodeEmitter;
class MachineCodeEmitter;
-class MCCodeEmitter;
-class MCContext;
-class MCInstrInfo;
-class MCObjectWriter;
-class MCSubtargetInfo;
class Target;
-class TargetAsmBackend;
class X86TargetMachine;
-class formatted_raw_ostream;
-class raw_ostream;
/// createX86ISelDag - This pass converts a legalized DAG into a
/// X86-specific DAG, ready for instruction scheduling.
@@ -51,22 +44,16 @@ FunctionPass* createGlobalBaseRegPass();
///
FunctionPass *createX86FloatingPointStackifierPass();
-/// createSSEDomainFixPass - This pass twiddles SSE opcodes to prevent domain
-/// crossings.
-FunctionPass *createSSEDomainFixPass();
+/// createX86IssueVZeroUpperPass - This pass inserts AVX vzeroupper instructions
+/// before each call to avoid transition penalty between functions encoded with
+/// AVX and SSE.
+FunctionPass *createX86IssueVZeroUpperPass();
/// createX86CodeEmitterPass - Return a pass that emits the collected X86 code
/// to the specified MCE object.
FunctionPass *createX86JITCodeEmitterPass(X86TargetMachine &TM,
JITCodeEmitter &JCE);
-MCCodeEmitter *createX86MCCodeEmitter(const MCInstrInfo &MCII,
- const MCSubtargetInfo &STI,
- MCContext &Ctx);
-
-TargetAsmBackend *createX86_32AsmBackend(const Target &, const std::string &);
-TargetAsmBackend *createX86_64AsmBackend(const Target &, const std::string &);
-
/// createX86EmitCodeToMemory - Returns a pass that converts a register
/// allocated function into raw machine code in a dynamically
/// allocated chunk of memory.
@@ -79,13 +66,6 @@ FunctionPass *createEmitX86CodeToMemory();
///
FunctionPass *createX86MaxStackAlignmentHeuristicPass();
-
-/// createX86MachObjectWriter - Construct an X86 Mach-O object writer.
-MCObjectWriter *createX86MachObjectWriter(raw_ostream &OS,
- bool Is64Bit,
- uint32_t CPUType,
- uint32_t CPUSubtype);
-
} // End llvm namespace
#endif
diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td
index 4ccb43f..104b91f 100644
--- a/lib/Target/X86/X86.td
+++ b/lib/Target/X86/X86.td
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
//
-// This is a target description file for the Intel i386 architecture, referred to
-// here as the "X86" architecture.
+// This is a target description file for the Intel i386 architecture, referred
+// to here as the "X86" architecture.
//
//===----------------------------------------------------------------------===//
@@ -23,6 +23,9 @@ include "llvm/Target/Target.td"
def Mode64Bit : SubtargetFeature<"64bit-mode", "In64BitMode", "true",
"64-bit mode (x86_64)">;
+def ModeNaCl : SubtargetFeature<"nacl-mode", "InNaClMode", "true",
+ "Native Client mode">;
+
//===----------------------------------------------------------------------===//
// X86 Subtarget features.
//===----------------------------------------------------------------------===//
@@ -68,6 +71,9 @@ def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA",
def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true",
"Support 64-bit instructions",
[FeatureCMOV]>;
+def FeatureCMPXCHG16B : SubtargetFeature<"cmpxchg16b", "HasCmpxchg16b", "true",
+ "64-bit with cmpxchg16b",
+ [Feature64Bit]>;
def FeatureSlowBTMem : SubtargetFeature<"slow-bt-mem", "IsBTMemSlow", "true",
"Bit testing of memory is slow">;
def FeatureFastUAMem : SubtargetFeature<"fast-unaligned-mem",
@@ -90,6 +96,16 @@ def FeatureVectorUAMem : SubtargetFeature<"vector-unaligned-mem",
"Allow unaligned memory operands on vector/SIMD instructions">;
def FeatureAES : SubtargetFeature<"aes", "HasAES", "true",
"Enable AES instructions">;
+def FeatureMOVBE : SubtargetFeature<"movbe", "HasMOVBE", "true",
+ "Support MOVBE instruction">;
+def FeatureRDRAND : SubtargetFeature<"rdrand", "HasRDRAND", "true",
+ "Support RDRAND instruction">;
+def FeatureF16C : SubtargetFeature<"f16c", "HasF16C", "true",
+ "Support 16-bit floating point conversion instructions">;
+def FeatureLZCNT : SubtargetFeature<"lzcnt", "HasLZCNT", "true",
+ "Support LZCNT instruction">;
+def FeatureBMI : SubtargetFeature<"bmi", "HasBMI", "true",
+ "Support BMI instructions">;
//===----------------------------------------------------------------------===//
// X86 processors supported.
@@ -112,27 +128,43 @@ def : Proc<"pentium3m", [FeatureSSE1, FeatureSlowBTMem]>;
def : Proc<"pentium-m", [FeatureSSE2, FeatureSlowBTMem]>;
def : Proc<"pentium4", [FeatureSSE2]>;
def : Proc<"pentium4m", [FeatureSSE2, FeatureSlowBTMem]>;
-def : Proc<"x86-64", [FeatureSSE2, Feature64Bit, FeatureSlowBTMem]>;
+def : Proc<"x86-64", [FeatureSSE2, Feature64Bit, FeatureSlowBTMem]>;
def : Proc<"yonah", [FeatureSSE3, FeatureSlowBTMem]>;
def : Proc<"prescott", [FeatureSSE3, FeatureSlowBTMem]>;
-def : Proc<"nocona", [FeatureSSE3, Feature64Bit, FeatureSlowBTMem]>;
-def : Proc<"core2", [FeatureSSSE3, Feature64Bit, FeatureSlowBTMem]>;
-def : Proc<"penryn", [FeatureSSE41, Feature64Bit, FeatureSlowBTMem]>;
-def : Proc<"atom", [FeatureSSE3, Feature64Bit, FeatureSlowBTMem]>;
+def : Proc<"nocona", [FeatureSSE3, FeatureCMPXCHG16B,
+ FeatureSlowBTMem]>;
+def : Proc<"core2", [FeatureSSSE3, FeatureCMPXCHG16B,
+ FeatureSlowBTMem]>;
+def : Proc<"penryn", [FeatureSSE41, FeatureCMPXCHG16B,
+ FeatureSlowBTMem]>;
+def : Proc<"atom", [FeatureSSE3, FeatureCMPXCHG16B, FeatureMOVBE,
+ FeatureSlowBTMem]>;
// "Arrandale" along with corei3 and corei5
-def : Proc<"corei7", [FeatureSSE42, Feature64Bit, FeatureSlowBTMem,
- FeatureFastUAMem, FeatureAES]>;
-def : Proc<"nehalem", [FeatureSSE42, Feature64Bit, FeatureSlowBTMem,
- FeatureFastUAMem]>;
+def : Proc<"corei7", [FeatureSSE42, FeatureCMPXCHG16B,
+ FeatureSlowBTMem, FeatureFastUAMem, FeatureAES]>;
+def : Proc<"nehalem", [FeatureSSE42, FeatureCMPXCHG16B,
+ FeatureSlowBTMem, FeatureFastUAMem]>;
// Westmere is a similar machine to nehalem with some additional features.
// Westmere is the corei3/i5/i7 path from nehalem to sandybridge
-def : Proc<"westmere", [FeatureSSE42, Feature64Bit, FeatureSlowBTMem,
- FeatureFastUAMem, FeatureAES, FeatureCLMUL]>;
+def : Proc<"westmere", [FeatureSSE42, FeatureCMPXCHG16B,
+ FeatureSlowBTMem, FeatureFastUAMem, FeatureAES,
+ FeatureCLMUL]>;
+// Sandy Bridge
// SSE is not listed here since llvm treats AVX as a reimplementation of SSE,
// rather than a superset.
// FIXME: Disabling AVX for now since it's not ready.
-def : Proc<"corei7-avx", [FeatureSSE42, Feature64Bit,
+def : Proc<"corei7-avx", [FeatureSSE42, FeatureCMPXCHG16B,
FeatureAES, FeatureCLMUL]>;
+// Ivy Bridge
+def : Proc<"core-avx-i", [FeatureSSE42, FeatureCMPXCHG16B,
+ FeatureAES, FeatureCLMUL,
+ FeatureRDRAND, FeatureF16C]>;
+
+// Haswell
+def : Proc<"core-avx2", [FeatureSSE42, FeatureCMPXCHG16B, FeatureAES,
+ FeatureCLMUL, FeatureRDRAND, FeatureF16C,
+ FeatureFMA3, FeatureMOVBE, FeatureLZCNT,
+ FeatureBMI]>;
def : Proc<"k6", [FeatureMMX]>;
def : Proc<"k6-2", [Feature3DNow]>;
@@ -150,19 +182,21 @@ def : Proc<"athlon64", [FeatureSSE2, Feature3DNowA, Feature64Bit,
FeatureSlowBTMem]>;
def : Proc<"athlon-fx", [FeatureSSE2, Feature3DNowA, Feature64Bit,
FeatureSlowBTMem]>;
-def : Proc<"k8-sse3", [FeatureSSE3, Feature3DNowA, Feature64Bit,
+def : Proc<"k8-sse3", [FeatureSSE3, Feature3DNowA, FeatureCMPXCHG16B,
FeatureSlowBTMem]>;
-def : Proc<"opteron-sse3", [FeatureSSE3, Feature3DNowA, Feature64Bit,
+def : Proc<"opteron-sse3", [FeatureSSE3, Feature3DNowA, FeatureCMPXCHG16B,
FeatureSlowBTMem]>;
-def : Proc<"athlon64-sse3", [FeatureSSE3, Feature3DNowA, Feature64Bit,
+def : Proc<"athlon64-sse3", [FeatureSSE3, Feature3DNowA, FeatureCMPXCHG16B,
FeatureSlowBTMem]>;
def : Proc<"amdfam10", [FeatureSSE3, FeatureSSE4A,
- Feature3DNowA, Feature64Bit, FeatureSlowBTMem]>;
+ Feature3DNowA, FeatureCMPXCHG16B,
+ FeatureSlowBTMem]>;
def : Proc<"barcelona", [FeatureSSE3, FeatureSSE4A,
- Feature3DNowA, Feature64Bit, FeatureSlowBTMem]>;
-def : Proc<"istanbul", [Feature3DNowA, Feature64Bit, FeatureSSE4A,
- Feature3DNowA]>;
-def : Proc<"shanghai", [Feature3DNowA, Feature64Bit, FeatureSSE4A,
+ Feature3DNowA, FeatureCMPXCHG16B,
+ FeatureSlowBTMem]>;
+def : Proc<"istanbul", [Feature3DNowA, FeatureCMPXCHG16B,
+ FeatureSSE4A, Feature3DNowA]>;
+def : Proc<"shanghai", [Feature3DNowA, FeatureCMPXCHG16B, FeatureSSE4A,
Feature3DNowA]>;
def : Proc<"winchip-c6", [FeatureMMX]>;
diff --git a/lib/Target/X86/X86AsmBackend.cpp b/lib/Target/X86/X86AsmBackend.cpp
deleted file mode 100644
index 9b556a5..0000000
--- a/lib/Target/X86/X86AsmBackend.cpp
+++ /dev/null
@@ -1,453 +0,0 @@
-//===-- X86AsmBackend.cpp - X86 Assembler Backend -------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Target/TargetAsmBackend.h"
-#include "X86.h"
-#include "X86FixupKinds.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCELFObjectWriter.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixupKindInfo.h"
-#include "llvm/MC/MCMachObjectWriter.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/Object/MachOFormat.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetAsmBackend.h"
-using namespace llvm;
-
-// Option to allow disabling arithmetic relaxation to workaround PR9807, which
-// is useful when running bitwise comparison experiments on Darwin. We should be
-// able to remove this once PR9807 is resolved.
-static cl::opt<bool>
-MCDisableArithRelaxation("mc-x86-disable-arith-relaxation",
- cl::desc("Disable relaxation of arithmetic instruction for X86"));
-
-static unsigned getFixupKindLog2Size(unsigned Kind) {
- switch (Kind) {
- default: assert(0 && "invalid fixup kind!");
- case FK_PCRel_1:
- case FK_Data_1: return 0;
- case FK_PCRel_2:
- case FK_Data_2: return 1;
- case FK_PCRel_4:
- case X86::reloc_riprel_4byte:
- case X86::reloc_riprel_4byte_movq_load:
- case X86::reloc_signed_4byte:
- case X86::reloc_global_offset_table:
- case FK_Data_4: return 2;
- case FK_PCRel_8:
- case FK_Data_8: return 3;
- }
-}
-
-namespace {
-
-class X86ELFObjectWriter : public MCELFObjectTargetWriter {
-public:
- X86ELFObjectWriter(bool is64Bit, Triple::OSType OSType, uint16_t EMachine,
- bool HasRelocationAddend)
- : MCELFObjectTargetWriter(is64Bit, OSType, EMachine, HasRelocationAddend) {}
-};
-
-class X86AsmBackend : public TargetAsmBackend {
-public:
- X86AsmBackend(const Target &T)
- : TargetAsmBackend() {}
-
- unsigned getNumFixupKinds() const {
- return X86::NumTargetFixupKinds;
- }
-
- const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
- const static MCFixupKindInfo Infos[X86::NumTargetFixupKinds] = {
- { "reloc_riprel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel },
- { "reloc_riprel_4byte_movq_load", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel},
- { "reloc_signed_4byte", 0, 4 * 8, 0},
- { "reloc_global_offset_table", 0, 4 * 8, 0}
- };
-
- if (Kind < FirstTargetFixupKind)
- return TargetAsmBackend::getFixupKindInfo(Kind);
-
- assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
- "Invalid kind!");
- return Infos[Kind - FirstTargetFixupKind];
- }
-
- void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
- uint64_t Value) const {
- unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind());
-
- assert(Fixup.getOffset() + Size <= DataSize &&
- "Invalid fixup offset!");
- for (unsigned i = 0; i != Size; ++i)
- Data[Fixup.getOffset() + i] = uint8_t(Value >> (i * 8));
- }
-
- bool MayNeedRelaxation(const MCInst &Inst) const;
-
- void RelaxInstruction(const MCInst &Inst, MCInst &Res) const;
-
- bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const;
-};
-} // end anonymous namespace
-
-static unsigned getRelaxedOpcodeBranch(unsigned Op) {
- switch (Op) {
- default:
- return Op;
-
- case X86::JAE_1: return X86::JAE_4;
- case X86::JA_1: return X86::JA_4;
- case X86::JBE_1: return X86::JBE_4;
- case X86::JB_1: return X86::JB_4;
- case X86::JE_1: return X86::JE_4;
- case X86::JGE_1: return X86::JGE_4;
- case X86::JG_1: return X86::JG_4;
- case X86::JLE_1: return X86::JLE_4;
- case X86::JL_1: return X86::JL_4;
- case X86::JMP_1: return X86::JMP_4;
- case X86::JNE_1: return X86::JNE_4;
- case X86::JNO_1: return X86::JNO_4;
- case X86::JNP_1: return X86::JNP_4;
- case X86::JNS_1: return X86::JNS_4;
- case X86::JO_1: return X86::JO_4;
- case X86::JP_1: return X86::JP_4;
- case X86::JS_1: return X86::JS_4;
- }
-}
-
-static unsigned getRelaxedOpcodeArith(unsigned Op) {
- switch (Op) {
- default:
- return Op;
-
- // IMUL
- case X86::IMUL16rri8: return X86::IMUL16rri;
- case X86::IMUL16rmi8: return X86::IMUL16rmi;
- case X86::IMUL32rri8: return X86::IMUL32rri;
- case X86::IMUL32rmi8: return X86::IMUL32rmi;
- case X86::IMUL64rri8: return X86::IMUL64rri32;
- case X86::IMUL64rmi8: return X86::IMUL64rmi32;
-
- // AND
- case X86::AND16ri8: return X86::AND16ri;
- case X86::AND16mi8: return X86::AND16mi;
- case X86::AND32ri8: return X86::AND32ri;
- case X86::AND32mi8: return X86::AND32mi;
- case X86::AND64ri8: return X86::AND64ri32;
- case X86::AND64mi8: return X86::AND64mi32;
-
- // OR
- case X86::OR16ri8: return X86::OR16ri;
- case X86::OR16mi8: return X86::OR16mi;
- case X86::OR32ri8: return X86::OR32ri;
- case X86::OR32mi8: return X86::OR32mi;
- case X86::OR64ri8: return X86::OR64ri32;
- case X86::OR64mi8: return X86::OR64mi32;
-
- // XOR
- case X86::XOR16ri8: return X86::XOR16ri;
- case X86::XOR16mi8: return X86::XOR16mi;
- case X86::XOR32ri8: return X86::XOR32ri;
- case X86::XOR32mi8: return X86::XOR32mi;
- case X86::XOR64ri8: return X86::XOR64ri32;
- case X86::XOR64mi8: return X86::XOR64mi32;
-
- // ADD
- case X86::ADD16ri8: return X86::ADD16ri;
- case X86::ADD16mi8: return X86::ADD16mi;
- case X86::ADD32ri8: return X86::ADD32ri;
- case X86::ADD32mi8: return X86::ADD32mi;
- case X86::ADD64ri8: return X86::ADD64ri32;
- case X86::ADD64mi8: return X86::ADD64mi32;
-
- // SUB
- case X86::SUB16ri8: return X86::SUB16ri;
- case X86::SUB16mi8: return X86::SUB16mi;
- case X86::SUB32ri8: return X86::SUB32ri;
- case X86::SUB32mi8: return X86::SUB32mi;
- case X86::SUB64ri8: return X86::SUB64ri32;
- case X86::SUB64mi8: return X86::SUB64mi32;
-
- // CMP
- case X86::CMP16ri8: return X86::CMP16ri;
- case X86::CMP16mi8: return X86::CMP16mi;
- case X86::CMP32ri8: return X86::CMP32ri;
- case X86::CMP32mi8: return X86::CMP32mi;
- case X86::CMP64ri8: return X86::CMP64ri32;
- case X86::CMP64mi8: return X86::CMP64mi32;
-
- // PUSH
- case X86::PUSHi8: return X86::PUSHi32;
- case X86::PUSHi16: return X86::PUSHi32;
- case X86::PUSH64i8: return X86::PUSH64i32;
- case X86::PUSH64i16: return X86::PUSH64i32;
- }
-}
-
-static unsigned getRelaxedOpcode(unsigned Op) {
- unsigned R = getRelaxedOpcodeArith(Op);
- if (R != Op)
- return R;
- return getRelaxedOpcodeBranch(Op);
-}
-
-bool X86AsmBackend::MayNeedRelaxation(const MCInst &Inst) const {
- // Branches can always be relaxed.
- if (getRelaxedOpcodeBranch(Inst.getOpcode()) != Inst.getOpcode())
- return true;
-
- if (MCDisableArithRelaxation)
- return false;
-
- // Check if this instruction is ever relaxable.
- if (getRelaxedOpcodeArith(Inst.getOpcode()) == Inst.getOpcode())
- return false;
-
-
- // Check if it has an expression and is not RIP relative.
- bool hasExp = false;
- bool hasRIP = false;
- for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
- const MCOperand &Op = Inst.getOperand(i);
- if (Op.isExpr())
- hasExp = true;
-
- if (Op.isReg() && Op.getReg() == X86::RIP)
- hasRIP = true;
- }
-
- // FIXME: Why exactly do we need the !hasRIP? Is it just a limitation on
- // how we do relaxations?
- return hasExp && !hasRIP;
-}
-
-// FIXME: Can tblgen help at all here to verify there aren't other instructions
-// we can relax?
-void X86AsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
- // The only relaxations X86 does is from a 1byte pcrel to a 4byte pcrel.
- unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode());
-
- if (RelaxedOp == Inst.getOpcode()) {
- SmallString<256> Tmp;
- raw_svector_ostream OS(Tmp);
- Inst.dump_pretty(OS);
- OS << "\n";
- report_fatal_error("unexpected instruction to relax: " + OS.str());
- }
-
- Res = Inst;
- Res.setOpcode(RelaxedOp);
-}
-
-/// WriteNopData - Write optimal nops to the output file for the \arg Count
-/// bytes. This returns the number of bytes written. It may return 0 if
-/// the \arg Count is more than the maximum optimal nops.
-bool X86AsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
- static const uint8_t Nops[10][10] = {
- // nop
- {0x90},
- // xchg %ax,%ax
- {0x66, 0x90},
- // nopl (%[re]ax)
- {0x0f, 0x1f, 0x00},
- // nopl 0(%[re]ax)
- {0x0f, 0x1f, 0x40, 0x00},
- // nopl 0(%[re]ax,%[re]ax,1)
- {0x0f, 0x1f, 0x44, 0x00, 0x00},
- // nopw 0(%[re]ax,%[re]ax,1)
- {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
- // nopl 0L(%[re]ax)
- {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
- // nopl 0L(%[re]ax,%[re]ax,1)
- {0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
- // nopw 0L(%[re]ax,%[re]ax,1)
- {0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
- // nopw %cs:0L(%[re]ax,%[re]ax,1)
- {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
- };
-
- // Write an optimal sequence for the first 15 bytes.
- const uint64_t OptimalCount = (Count < 16) ? Count : 15;
- const uint64_t Prefixes = OptimalCount <= 10 ? 0 : OptimalCount - 10;
- for (uint64_t i = 0, e = Prefixes; i != e; i++)
- OW->Write8(0x66);
- const uint64_t Rest = OptimalCount - Prefixes;
- for (uint64_t i = 0, e = Rest; i != e; i++)
- OW->Write8(Nops[Rest - 1][i]);
-
- // Finish with single byte nops.
- for (uint64_t i = OptimalCount, e = Count; i != e; ++i)
- OW->Write8(0x90);
-
- return true;
-}
-
-/* *** */
-
-namespace {
-class ELFX86AsmBackend : public X86AsmBackend {
-public:
- Triple::OSType OSType;
- ELFX86AsmBackend(const Target &T, Triple::OSType _OSType)
- : X86AsmBackend(T), OSType(_OSType) {
- HasReliableSymbolDifference = true;
- }
-
- virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
- const MCSectionELF &ES = static_cast<const MCSectionELF&>(Section);
- return ES.getFlags() & ELF::SHF_MERGE;
- }
-};
-
-class ELFX86_32AsmBackend : public ELFX86AsmBackend {
-public:
- ELFX86_32AsmBackend(const Target &T, Triple::OSType OSType)
- : ELFX86AsmBackend(T, OSType) {}
-
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- return createELFObjectWriter(createELFObjectTargetWriter(),
- OS, /*IsLittleEndian*/ true);
- }
-
- MCELFObjectTargetWriter *createELFObjectTargetWriter() const {
- return new X86ELFObjectWriter(false, OSType, ELF::EM_386, false);
- }
-};
-
-class ELFX86_64AsmBackend : public ELFX86AsmBackend {
-public:
- ELFX86_64AsmBackend(const Target &T, Triple::OSType OSType)
- : ELFX86AsmBackend(T, OSType) {}
-
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- return createELFObjectWriter(createELFObjectTargetWriter(),
- OS, /*IsLittleEndian*/ true);
- }
-
- MCELFObjectTargetWriter *createELFObjectTargetWriter() const {
- return new X86ELFObjectWriter(true, OSType, ELF::EM_X86_64, true);
- }
-};
-
-class WindowsX86AsmBackend : public X86AsmBackend {
- bool Is64Bit;
-
-public:
- WindowsX86AsmBackend(const Target &T, bool is64Bit)
- : X86AsmBackend(T)
- , Is64Bit(is64Bit) {
- }
-
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- return createWinCOFFObjectWriter(OS, Is64Bit);
- }
-};
-
-class DarwinX86AsmBackend : public X86AsmBackend {
-public:
- DarwinX86AsmBackend(const Target &T)
- : X86AsmBackend(T) { }
-};
-
-class DarwinX86_32AsmBackend : public DarwinX86AsmBackend {
-public:
- DarwinX86_32AsmBackend(const Target &T)
- : DarwinX86AsmBackend(T) {}
-
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- return createX86MachObjectWriter(OS, /*Is64Bit=*/false,
- object::mach::CTM_i386,
- object::mach::CSX86_ALL);
- }
-};
-
-class DarwinX86_64AsmBackend : public DarwinX86AsmBackend {
-public:
- DarwinX86_64AsmBackend(const Target &T)
- : DarwinX86AsmBackend(T) {
- HasReliableSymbolDifference = true;
- }
-
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- return createX86MachObjectWriter(OS, /*Is64Bit=*/true,
- object::mach::CTM_x86_64,
- object::mach::CSX86_ALL);
- }
-
- virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
- // Temporary labels in the string literals sections require symbols. The
- // issue is that the x86_64 relocation format does not allow symbol +
- // offset, and so the linker does not have enough information to resolve the
- // access to the appropriate atom unless an external relocation is used. For
- // non-cstring sections, we expect the compiler to use a non-temporary label
- // for anything that could have an addend pointing outside the symbol.
- //
- // See <rdar://problem/4765733>.
- const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
- return SMO.getType() == MCSectionMachO::S_CSTRING_LITERALS;
- }
-
- virtual bool isSectionAtomizable(const MCSection &Section) const {
- const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
- // Fixed sized data sections are uniqued, they cannot be diced into atoms.
- switch (SMO.getType()) {
- default:
- return true;
-
- case MCSectionMachO::S_4BYTE_LITERALS:
- case MCSectionMachO::S_8BYTE_LITERALS:
- case MCSectionMachO::S_16BYTE_LITERALS:
- case MCSectionMachO::S_LITERAL_POINTERS:
- case MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS:
- case MCSectionMachO::S_LAZY_SYMBOL_POINTERS:
- case MCSectionMachO::S_MOD_INIT_FUNC_POINTERS:
- case MCSectionMachO::S_MOD_TERM_FUNC_POINTERS:
- case MCSectionMachO::S_INTERPOSING:
- return false;
- }
- }
-};
-
-} // end anonymous namespace
-
-TargetAsmBackend *llvm::createX86_32AsmBackend(const Target &T,
- const std::string &TT) {
- Triple TheTriple(TT);
-
- if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO)
- return new DarwinX86_32AsmBackend(T);
-
- if (TheTriple.isOSWindows())
- return new WindowsX86AsmBackend(T, false);
-
- return new ELFX86_32AsmBackend(T, TheTriple.getOS());
-}
-
-TargetAsmBackend *llvm::createX86_64AsmBackend(const Target &T,
- const std::string &TT) {
- Triple TheTriple(TT);
-
- if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO)
- return new DarwinX86_64AsmBackend(T);
-
- if (TheTriple.isOSWindows())
- return new WindowsX86AsmBackend(T, true);
-
- return new ELFX86_64AsmBackend(T, TheTriple.getOS());
-}
diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp
index 99b4479..4c3ff02 100644
--- a/lib/Target/X86/X86AsmPrinter.cpp
+++ b/lib/Target/X86/X86AsmPrinter.cpp
@@ -35,12 +35,12 @@
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
+#include "llvm/Target/Mangler.h"
+#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Target/Mangler.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;
@@ -504,8 +504,8 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
// .indirect_symbol _foo
OutStreamer.EmitSymbolAttribute(Stubs[i].second.getPointer(),
MCSA_IndirectSymbol);
- // hlt; hlt; hlt; hlt; hlt hlt = 0xf4 = -12.
- const char HltInsts[] = { -12, -12, -12, -12, -12 };
+ // hlt; hlt; hlt; hlt; hlt hlt = 0xf4.
+ const char HltInsts[] = "\xf4\xf4\xf4\xf4\xf4";
OutStreamer.EmitBytes(StringRef(HltInsts, 5), 0/*addrspace*/);
}
@@ -708,21 +708,8 @@ void X86AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
// Target Registry Stuff
//===----------------------------------------------------------------------===//
-static MCInstPrinter *createX86MCInstPrinter(const Target &T,
- unsigned SyntaxVariant,
- const MCAsmInfo &MAI) {
- if (SyntaxVariant == 0)
- return new X86ATTInstPrinter(MAI);
- if (SyntaxVariant == 1)
- return new X86IntelInstPrinter(MAI);
- return 0;
-}
-
// Force static initialization.
extern "C" void LLVMInitializeX86AsmPrinter() {
RegisterAsmPrinter<X86AsmPrinter> X(TheX86_32Target);
RegisterAsmPrinter<X86AsmPrinter> Y(TheX86_64Target);
-
- TargetRegistry::RegisterMCInstPrinter(TheX86_32Target,createX86MCInstPrinter);
- TargetRegistry::RegisterMCInstPrinter(TheX86_64Target,createX86MCInstPrinter);
}
diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp
index 4b11db7..aeff03a 100644
--- a/lib/Target/X86/X86CodeEmitter.cpp
+++ b/lib/Target/X86/X86CodeEmitter.cpp
@@ -98,8 +98,6 @@ namespace {
void emitMemModRMByte(const MachineInstr &MI,
unsigned Op, unsigned RegOpcodeField,
intptr_t PCAdj = 0);
-
- unsigned getX86RegNum(unsigned RegNo) const;
};
template<class CodeEmitter>
@@ -169,7 +167,7 @@ static unsigned determineREX(const MachineInstr &MI) {
const MachineOperand& MO = MI.getOperand(i);
if (MO.isReg()) {
unsigned Reg = MO.getReg();
- if (X86InstrInfo::isX86_64NonExtLowByteReg(Reg))
+ if (X86II::isX86_64NonExtLowByteReg(Reg))
REX |= 0x40;
}
}
@@ -346,11 +344,6 @@ void Emitter<CodeEmitter>::emitJumpTableAddress(unsigned JTI, unsigned Reloc,
MCE.emitWordLE(0);
}
-template<class CodeEmitter>
-unsigned Emitter<CodeEmitter>::getX86RegNum(unsigned RegNo) const {
- return X86RegisterInfo::getX86RegNum(RegNo);
-}
-
inline static unsigned char ModRMByte(unsigned Mod, unsigned RegOpcode,
unsigned RM) {
assert(Mod < 4 && RegOpcode < 8 && RM < 8 && "ModRM Fields out of range!");
@@ -360,7 +353,7 @@ inline static unsigned char ModRMByte(unsigned Mod, unsigned RegOpcode,
template<class CodeEmitter>
void Emitter<CodeEmitter>::emitRegModRMByte(unsigned ModRMReg,
unsigned RegOpcodeFld){
- MCE.emitByte(ModRMByte(3, RegOpcodeFld, getX86RegNum(ModRMReg)));
+ MCE.emitByte(ModRMByte(3, RegOpcodeFld, X86_MC::getX86RegNum(ModRMReg)));
}
template<class CodeEmitter>
@@ -498,7 +491,7 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
// 2-7) and absolute references.
unsigned BaseRegNo = -1U;
if (BaseReg != 0 && BaseReg != X86::RIP)
- BaseRegNo = getX86RegNum(BaseReg);
+ BaseRegNo = X86_MC::getX86RegNum(BaseReg);
if (// The SIB byte must be used if there is an index register.
IndexReg.getReg() == 0 &&
@@ -566,7 +559,7 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
}
// Calculate what the SS field value should be...
- static const unsigned SSTable[] = { ~0, 0, 1, ~0, 2, ~0, ~0, ~0, 3 };
+ static const unsigned SSTable[] = { ~0U, 0, 1, ~0U, 2, ~0U, ~0U, ~0U, 3 };
unsigned SS = SSTable[Scale.getImm()];
if (BaseReg == 0) {
@@ -574,15 +567,15 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
// Manual 2A, table 2-7. The displacement has already been output.
unsigned IndexRegNo;
if (IndexReg.getReg())
- IndexRegNo = getX86RegNum(IndexReg.getReg());
+ IndexRegNo = X86_MC::getX86RegNum(IndexReg.getReg());
else // Examples: [ESP+1*<noreg>+4] or [scaled idx]+disp32 (MOD=0,BASE=5)
IndexRegNo = 4;
emitSIBByte(SS, IndexRegNo, 5);
} else {
- unsigned BaseRegNo = getX86RegNum(BaseReg);
+ unsigned BaseRegNo = X86_MC::getX86RegNum(BaseReg);
unsigned IndexRegNo;
if (IndexReg.getReg())
- IndexRegNo = getX86RegNum(IndexReg.getReg());
+ IndexRegNo = X86_MC::getX86RegNum(IndexReg.getReg());
else
IndexRegNo = 4; // For example [ESP+1*<noreg>+4]
emitSIBByte(SS, IndexRegNo, BaseRegNo);
@@ -809,7 +802,8 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
}
case X86II::AddRegFrm: {
- MCE.emitByte(BaseOpcode + getX86RegNum(MI.getOperand(CurOp++).getReg()));
+ MCE.emitByte(BaseOpcode +
+ X86_MC::getX86RegNum(MI.getOperand(CurOp++).getReg()));
if (CurOp == NumOps)
break;
@@ -844,7 +838,7 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
case X86II::MRMDestReg: {
MCE.emitByte(BaseOpcode);
emitRegModRMByte(MI.getOperand(CurOp).getReg(),
- getX86RegNum(MI.getOperand(CurOp+1).getReg()));
+ X86_MC::getX86RegNum(MI.getOperand(CurOp+1).getReg()));
CurOp += 2;
if (CurOp != NumOps)
emitConstant(MI.getOperand(CurOp++).getImm(),
@@ -854,7 +848,7 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
case X86II::MRMDestMem: {
MCE.emitByte(BaseOpcode);
emitMemModRMByte(MI, CurOp,
- getX86RegNum(MI.getOperand(CurOp + X86::AddrNumOperands)
+ X86_MC::getX86RegNum(MI.getOperand(CurOp + X86::AddrNumOperands)
.getReg()));
CurOp += X86::AddrNumOperands + 1;
if (CurOp != NumOps)
@@ -866,7 +860,7 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
case X86II::MRMSrcReg:
MCE.emitByte(BaseOpcode);
emitRegModRMByte(MI.getOperand(CurOp+1).getReg(),
- getX86RegNum(MI.getOperand(CurOp).getReg()));
+ X86_MC::getX86RegNum(MI.getOperand(CurOp).getReg()));
CurOp += 2;
if (CurOp != NumOps)
emitConstant(MI.getOperand(CurOp++).getImm(),
@@ -880,8 +874,8 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
X86II::getSizeOfImm(Desc->TSFlags) : 0;
MCE.emitByte(BaseOpcode);
- emitMemModRMByte(MI, CurOp+1, getX86RegNum(MI.getOperand(CurOp).getReg()),
- PCAdj);
+ emitMemModRMByte(MI, CurOp+1,
+ X86_MC::getX86RegNum(MI.getOperand(CurOp).getReg()),PCAdj);
CurOp += AddrOperands + 1;
if (CurOp != NumOps)
emitConstant(MI.getOperand(CurOp++).getImm(),
@@ -968,7 +962,7 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
MCE.emitByte(BaseOpcode);
// Duplicate register, used by things like MOV8r0 (aka xor reg,reg).
emitRegModRMByte(MI.getOperand(CurOp).getReg(),
- getX86RegNum(MI.getOperand(CurOp).getReg()));
+ X86_MC::getX86RegNum(MI.getOperand(CurOp).getReg()));
++CurOp;
break;
diff --git a/lib/Target/X86/X86ELFWriterInfo.cpp b/lib/Target/X86/X86ELFWriterInfo.cpp
index f1d7ede..4a72d15 100644
--- a/lib/Target/X86/X86ELFWriterInfo.cpp
+++ b/lib/Target/X86/X86ELFWriterInfo.cpp
@@ -147,7 +147,7 @@ long int X86ELFWriterInfo::computeRelocation(unsigned SymOffset,
if (RelTy == ELF::R_X86_64_PC32 || RelTy == ELF::R_386_PC32)
return SymOffset - (RelOffset + 4);
else
- assert("computeRelocation unknown for this relocation type");
+ assert(0 && "computeRelocation unknown for this relocation type");
return 0;
}
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp
index 21e163a..f912b28 100644
--- a/lib/Target/X86/X86FastISel.cpp
+++ b/lib/Target/X86/X86FastISel.cpp
@@ -22,6 +22,7 @@
#include "llvm/CallingConv.h"
#include "llvm/DerivedTypes.h"
#include "llvm/GlobalVariable.h"
+#include "llvm/GlobalAlias.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Operator.h"
@@ -59,8 +60,8 @@ public:
explicit X86FastISel(FunctionLoweringInfo &funcInfo) : FastISel(funcInfo) {
Subtarget = &TM.getSubtarget<X86Subtarget>();
StackPtr = Subtarget->is64Bit() ? X86::RSP : X86::ESP;
- X86ScalarSSEf64 = Subtarget->hasSSE2();
- X86ScalarSSEf32 = Subtarget->hasSSE1();
+ X86ScalarSSEf64 = Subtarget->hasSSE2() || Subtarget->hasAVX();
+ X86ScalarSSEf32 = Subtarget->hasSSE1() || Subtarget->hasAVX();
}
virtual bool TargetSelectInstruction(const Instruction *I);
@@ -134,7 +135,7 @@ private:
(VT == MVT::f32 && X86ScalarSSEf32); // f32 is when SSE1
}
- bool isTypeLegal(const Type *Ty, MVT &VT, bool AllowI1 = false);
+ bool isTypeLegal(Type *Ty, MVT &VT, bool AllowI1 = false);
bool IsMemcpySmall(uint64_t Len);
@@ -144,7 +145,7 @@ private:
} // end anonymous namespace.
-bool X86FastISel::isTypeLegal(const Type *Ty, MVT &VT, bool AllowI1) {
+bool X86FastISel::isTypeLegal(Type *Ty, MVT &VT, bool AllowI1) {
EVT evt = TLI.getValueType(Ty, /*HandleUnknown=*/true);
if (evt == MVT::Other || !evt.isSimple())
// Unhandled type. Halt "fast" selection and bail.
@@ -198,8 +199,8 @@ bool X86FastISel::X86FastEmitLoad(EVT VT, const X86AddressMode &AM,
RC = X86::GR64RegisterClass;
break;
case MVT::f32:
- if (Subtarget->hasSSE1()) {
- Opc = X86::MOVSSrm;
+ if (X86ScalarSSEf32) {
+ Opc = Subtarget->hasAVX() ? X86::VMOVSSrm : X86::MOVSSrm;
RC = X86::FR32RegisterClass;
} else {
Opc = X86::LD_Fp32m;
@@ -207,8 +208,8 @@ bool X86FastISel::X86FastEmitLoad(EVT VT, const X86AddressMode &AM,
}
break;
case MVT::f64:
- if (Subtarget->hasSSE2()) {
- Opc = X86::MOVSDrm;
+ if (X86ScalarSSEf64) {
+ Opc = Subtarget->hasAVX() ? X86::VMOVSDrm : X86::MOVSDrm;
RC = X86::FR64RegisterClass;
} else {
Opc = X86::LD_Fp64m;
@@ -250,10 +251,12 @@ X86FastISel::X86FastEmitStore(EVT VT, unsigned Val, const X86AddressMode &AM) {
case MVT::i32: Opc = X86::MOV32mr; break;
case MVT::i64: Opc = X86::MOV64mr; break; // Must be in x86-64 mode.
case MVT::f32:
- Opc = Subtarget->hasSSE1() ? X86::MOVSSmr : X86::ST_Fp32m;
+ Opc = X86ScalarSSEf32 ?
+ (Subtarget->hasAVX() ? X86::VMOVSSmr : X86::MOVSSmr) : X86::ST_Fp32m;
break;
case MVT::f64:
- Opc = Subtarget->hasSSE2() ? X86::MOVSDmr : X86::ST_Fp64m;
+ Opc = X86ScalarSSEf64 ?
+ (Subtarget->hasAVX() ? X86::VMOVSDmr : X86::MOVSDmr) : X86::ST_Fp64m;
break;
}
@@ -336,7 +339,7 @@ bool X86FastISel::X86SelectAddress(const Value *V, X86AddressMode &AM) {
U = C;
}
- if (const PointerType *Ty = dyn_cast<PointerType>(V->getType()))
+ if (PointerType *Ty = dyn_cast<PointerType>(V->getType()))
if (Ty->getAddressSpace() > 255)
// Fast instruction selection doesn't support the special
// address spaces.
@@ -399,7 +402,7 @@ bool X86FastISel::X86SelectAddress(const Value *V, X86AddressMode &AM) {
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<StructType>(*GTI)) {
+ if (StructType *STy = dyn_cast<StructType>(*GTI)) {
const StructLayout *SL = TD.getStructLayout(STy);
Disp += SL->getElementOffset(cast<ConstantInt>(Op)->getZExtValue());
continue;
@@ -465,14 +468,23 @@ bool X86FastISel::X86SelectAddress(const Value *V, X86AddressMode &AM) {
// Handle constant address.
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
- // Can't handle alternate code models or TLS yet.
+ // Can't handle alternate code models yet.
if (TM.getCodeModel() != CodeModel::Small)
return false;
+ // Can't handle TLS yet.
if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
if (GVar->isThreadLocal())
return false;
+ // Can't handle TLS yet, part 2 (this is slightly crazy, but this is how
+ // it works...).
+ if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
+ if (const GlobalVariable *GVar =
+ dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false)))
+ if (GVar->isThreadLocal())
+ return false;
+
// RIP-relative addresses can't have additional register operands, so if
// we've already folded stuff into the addressing mode, just force the
// global value into its own register, which we can use as the basereg.
@@ -658,6 +670,10 @@ bool X86FastISel::X86SelectCallAddress(const Value *V, X86AddressMode &AM) {
/// X86SelectStore - Select and emit code to implement store instructions.
bool X86FastISel::X86SelectStore(const Instruction *I) {
+ // Atomic stores need special handling.
+ if (cast<StoreInst>(I)->isAtomic())
+ return false;
+
MVT VT;
if (!isTypeLegal(I->getOperand(0)->getType(), VT, /*AllowI1=*/true))
return false;
@@ -780,6 +796,10 @@ bool X86FastISel::X86SelectRet(const Instruction *I) {
/// X86SelectLoad - Select and emit code to implement load instructions.
///
bool X86FastISel::X86SelectLoad(const Instruction *I) {
+ // Atomic loads need special handling.
+ if (cast<LoadInst>(I)->isAtomic())
+ return false;
+
MVT VT;
if (!isTypeLegal(I->getType(), VT, /*AllowI1=*/true))
return false;
@@ -797,14 +817,20 @@ bool X86FastISel::X86SelectLoad(const Instruction *I) {
}
static unsigned X86ChooseCmpOpcode(EVT VT, const X86Subtarget *Subtarget) {
+ bool HasAVX = Subtarget->hasAVX();
+ bool X86ScalarSSEf32 = HasAVX || Subtarget->hasSSE1();
+ bool X86ScalarSSEf64 = HasAVX || Subtarget->hasSSE2();
+
switch (VT.getSimpleVT().SimpleTy) {
default: return 0;
case MVT::i8: return X86::CMP8rr;
case MVT::i16: return X86::CMP16rr;
case MVT::i32: return X86::CMP32rr;
case MVT::i64: return X86::CMP64rr;
- case MVT::f32: return Subtarget->hasSSE1() ? X86::UCOMISSrr : 0;
- case MVT::f64: return Subtarget->hasSSE2() ? X86::UCOMISDrr : 0;
+ case MVT::f32:
+ return X86ScalarSSEf32 ? (HasAVX ? X86::VUCOMISSrr : X86::UCOMISSrr) : 0;
+ case MVT::f64:
+ return X86ScalarSSEf64 ? (HasAVX ? X86::VUCOMISDrr : X86::UCOMISDrr) : 0;
}
}
@@ -1207,7 +1233,7 @@ bool X86FastISel::X86SelectSelect(const Instruction *I) {
bool X86FastISel::X86SelectFPExt(const Instruction *I) {
// fpext from float to double.
- if (Subtarget->hasSSE2() &&
+ if (X86ScalarSSEf64 &&
I->getType()->isDoubleTy()) {
const Value *V = I->getOperand(0);
if (V->getType()->isFloatTy()) {
@@ -1226,7 +1252,7 @@ bool X86FastISel::X86SelectFPExt(const Instruction *I) {
}
bool X86FastISel::X86SelectFPTrunc(const Instruction *I) {
- if (Subtarget->hasSSE2()) {
+ if (X86ScalarSSEf64) {
if (I->getType()->isFloatTy()) {
const Value *V = I->getOperand(0);
if (V->getType()->isDoubleTy()) {
@@ -1365,6 +1391,9 @@ bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) {
case Intrinsic::memset: {
const MemSetInst &MSI = cast<MemSetInst>(I);
+ if (MSI.isVolatile())
+ return false;
+
unsigned SizeWidth = Subtarget->is64Bit() ? 64 : 32;
if (!MSI.getLength()->getType()->isIntegerTy(SizeWidth))
return false;
@@ -1411,7 +1440,7 @@ bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) {
// Replace "add with overflow" intrinsics with an "add" instruction followed
// by a seto/setc instruction.
const Function *Callee = I.getCalledFunction();
- const Type *RetTy =
+ Type *RetTy =
cast<StructType>(Callee->getReturnType())->getTypeAtIndex(unsigned(0));
MVT VT;
@@ -1484,8 +1513,8 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) {
if (CC == CallingConv::Fast && GuaranteedTailCallOpt)
return false;
- const PointerType *PT = cast<PointerType>(CS.getCalledValue()->getType());
- const FunctionType *FTy = cast<FunctionType>(PT->getElementType());
+ PointerType *PT = cast<PointerType>(CS.getCalledValue()->getType());
+ FunctionType *FTy = cast<FunctionType>(PT->getElementType());
bool isVarArg = FTy->isVarArg();
// Don't know how to handle Win64 varargs yet. Nothing special needed for
@@ -1547,8 +1576,8 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) {
Flags.setZExt();
if (CS.paramHasAttr(AttrInd, Attribute::ByVal)) {
- const PointerType *Ty = cast<PointerType>(ArgVal->getType());
- const Type *ElementTy = Ty->getElementType();
+ PointerType *Ty = cast<PointerType>(ArgVal->getType());
+ Type *ElementTy = Ty->getElementType();
unsigned FrameSize = TD.getTypeAllocSize(ElementTy);
unsigned FrameAlign = CS.getParamAlignment(AttrInd);
if (!FrameAlign)
@@ -1600,7 +1629,7 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) {
if (ArgReg == 0) return false;
- const Type *ArgTy = ArgVal->getType();
+ Type *ArgTy = ArgVal->getType();
MVT ArgVT;
if (!isTypeLegal(ArgTy, ArgVT))
return false;
@@ -1709,7 +1738,7 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) {
assert(Res && "memcpy length already checked!"); (void)Res;
} else if (isa<ConstantInt>(ArgVal) || isa<ConstantPointerNull>(ArgVal)) {
// If this is a really simple value, emit this with the Value* version
- //of X86FastEmitStore. If it isn't simple, we don't want to do this,
+ // of X86FastEmitStore. If it isn't simple, we don't want to do this,
// as it can cause us to reevaluate the argument.
X86FastEmitStore(ArgVT, ArgVal, AM);
} else {
@@ -1965,8 +1994,8 @@ unsigned X86FastISel::TargetMaterializeConstant(const Constant *C) {
RC = X86::GR64RegisterClass;
break;
case MVT::f32:
- if (Subtarget->hasSSE1()) {
- Opc = X86::MOVSSrm;
+ if (X86ScalarSSEf32) {
+ Opc = Subtarget->hasAVX() ? X86::VMOVSSrm : X86::MOVSSrm;
RC = X86::FR32RegisterClass;
} else {
Opc = X86::LD_Fp32m;
@@ -1974,8 +2003,8 @@ unsigned X86FastISel::TargetMaterializeConstant(const Constant *C) {
}
break;
case MVT::f64:
- if (Subtarget->hasSSE2()) {
- Opc = X86::MOVSDrm;
+ if (X86ScalarSSEf64) {
+ Opc = Subtarget->hasAVX() ? X86::VMOVSDrm : X86::MOVSDrm;
RC = X86::FR64RegisterClass;
} else {
Opc = X86::LD_Fp64m;
@@ -2070,8 +2099,8 @@ unsigned X86FastISel::TargetMaterializeFloatZero(const ConstantFP *CF) {
switch (VT.SimpleTy) {
default: return false;
case MVT::f32:
- if (Subtarget->hasSSE1()) {
- Opc = X86::FsFLD0SS;
+ if (X86ScalarSSEf32) {
+ Opc = Subtarget->hasAVX() ? X86::VFsFLD0SS : X86::FsFLD0SS;
RC = X86::FR32RegisterClass;
} else {
Opc = X86::LD_Fp032;
@@ -2079,8 +2108,8 @@ unsigned X86FastISel::TargetMaterializeFloatZero(const ConstantFP *CF) {
}
break;
case MVT::f64:
- if (Subtarget->hasSSE2()) {
- Opc = X86::FsFLD0SD;
+ if (X86ScalarSSEf64) {
+ Opc = Subtarget->hasAVX() ? X86::VFsFLD0SD : X86::FsFLD0SD;
RC = X86::FR64RegisterClass;
} else {
Opc = X86::LD_Fp064;
diff --git a/lib/Target/X86/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp
index 6eed6abd..e3461c8 100644
--- a/lib/Target/X86/X86FloatingPoint.cpp
+++ b/lib/Target/X86/X86FloatingPoint.cpp
@@ -260,6 +260,21 @@ namespace {
BuildMI(*MBB, I, dl, TII->get(X86::LD_Frr)).addReg(STReg);
}
+ /// duplicatePendingSTBeforeKill - The instruction at I is about to kill
+ /// RegNo. If any PendingST registers still need the RegNo value, duplicate
+ /// them to new scratch registers.
+ void duplicatePendingSTBeforeKill(unsigned RegNo, MachineInstr *I) {
+ for (unsigned i = 0; i != NumPendingSTs; ++i) {
+ if (PendingST[i] != RegNo)
+ continue;
+ unsigned SR = getScratchReg();
+ DEBUG(dbgs() << "Duplicating pending ST" << i
+ << " in FP" << RegNo << " to FP" << SR << '\n');
+ duplicateToTop(RegNo, SR, I);
+ PendingST[i] = SR;
+ }
+ }
+
/// popStackAfter - Pop the current value off of the top of the FP stack
/// after the specified instruction.
void popStackAfter(MachineBasicBlock::iterator &I);
@@ -406,6 +421,10 @@ bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) {
if (MI->isCopy() && isFPCopy(MI))
FPInstClass = X86II::SpecialFP;
+ if (MI->isImplicitDef() &&
+ X86::RFP80RegClass.contains(MI->getOperand(0).getReg()))
+ FPInstClass = X86II::SpecialFP;
+
if (FPInstClass == X86II::NotFP)
continue; // Efficiently ignore non-fp insts!
@@ -461,6 +480,7 @@ bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) {
}
dumpStack();
);
+ (void)PrevMI;
Changed = true;
}
@@ -969,6 +989,9 @@ void FPS::handleOneArgFP(MachineBasicBlock::iterator &I) {
unsigned Reg = getFPReg(MI->getOperand(NumOps-1));
bool KillsSrc = MI->killsRegister(X86::FP0+Reg);
+ if (KillsSrc)
+ duplicatePendingSTBeforeKill(Reg, I);
+
// FISTP64m is strange because there isn't a non-popping versions.
// If we have one _and_ we don't want to pop the operand, duplicate the value
// on the stack instead of moving it. This ensure that popping the value is
@@ -1032,6 +1055,7 @@ void FPS::handleOneArgFPRW(MachineBasicBlock::iterator &I) {
bool KillsSrc = MI->killsRegister(X86::FP0+Reg);
if (KillsSrc) {
+ duplicatePendingSTBeforeKill(Reg, I);
// If this is the last use of the source register, just make sure it's on
// the top of the stack.
moveToTop(Reg, I);
@@ -1318,6 +1342,7 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
// When the source is killed, allocate a scratch FP register.
if (KillsSrc) {
+ duplicatePendingSTBeforeKill(SrcFP, I);
unsigned Slot = getSlot(SrcFP);
unsigned SR = getScratchReg();
PendingST[DstST] = SR;
@@ -1369,6 +1394,15 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
break;
}
+ case TargetOpcode::IMPLICIT_DEF: {
+ // All FP registers must be explicitly defined, so load a 0 instead.
+ unsigned Reg = MI->getOperand(0).getReg() - X86::FP0;
+ DEBUG(dbgs() << "Emitting LD_F0 for implicit FP" << Reg << '\n');
+ BuildMI(*MBB, I, MI->getDebugLoc(), TII->get(X86::LD_F0));
+ pushReg(Reg);
+ break;
+ }
+
case X86::FpPOP_RETVAL: {
// The FpPOP_RETVAL instruction is used after calls that return a value on
// the floating point stack. We cannot model this with ST defs since CALL
diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp
index ed45a9a..d54f4ae 100644
--- a/lib/Target/X86/X86FrameLowering.cpp
+++ b/lib/Target/X86/X86FrameLowering.cpp
@@ -15,6 +15,7 @@
#include "X86InstrBuilder.h"
#include "X86InstrInfo.h"
#include "X86MachineFunctionInfo.h"
+#include "X86Subtarget.h"
#include "X86TargetMachine.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
@@ -91,12 +92,12 @@ static unsigned findDeadCallerSavedReg(MachineBasicBlock &MBB,
return 0;
static const unsigned CallerSavedRegs32Bit[] = {
- X86::EAX, X86::EDX, X86::ECX
+ X86::EAX, X86::EDX, X86::ECX, 0
};
static const unsigned CallerSavedRegs64Bit[] = {
X86::RAX, X86::RDX, X86::RCX, X86::RSI, X86::RDI,
- X86::R8, X86::R9, X86::R10, X86::R11
+ X86::R8, X86::R9, X86::R10, X86::R11, 0
};
unsigned Opc = MBBI->getOpcode();
@@ -283,8 +284,8 @@ static bool isEAXLiveIn(MachineFunction &MF) {
}
void X86FrameLowering::emitCalleeSavedFrameMoves(MachineFunction &MF,
- MCSymbol *Label,
- unsigned FramePtr) const {
+ MCSymbol *Label,
+ unsigned FramePtr) const {
MachineFrameInfo *MFI = MF.getFrameInfo();
MachineModuleInfo &MMI = MF.getMMI();
@@ -346,6 +347,247 @@ void X86FrameLowering::emitCalleeSavedFrameMoves(MachineFunction &MF,
}
}
+/// getCompactUnwindRegNum - Get the compact unwind number for a given
+/// register. The number corresponds to the enum lists in
+/// compact_unwind_encoding.h.
+static int getCompactUnwindRegNum(const unsigned *CURegs, unsigned Reg) {
+ int Idx = 1;
+ for (; *CURegs; ++CURegs, ++Idx)
+ if (*CURegs == Reg)
+ return Idx;
+
+ return -1;
+}
+
+/// encodeCompactUnwindRegistersWithoutFrame - Create the permutation encoding
+/// used with frameless stacks. It is passed the number of registers to be saved
+/// and an array of the registers saved.
+static uint32_t encodeCompactUnwindRegistersWithoutFrame(unsigned SavedRegs[6],
+ unsigned RegCount,
+ bool Is64Bit) {
+ // The saved registers are numbered from 1 to 6. In order to encode the order
+ // in which they were saved, we re-number them according to their place in the
+ // register order. The re-numbering is relative to the last re-numbered
+ // register. E.g., if we have registers {6, 2, 4, 5} saved in that order:
+ //
+ // Orig Re-Num
+ // ---- ------
+ // 6 6
+ // 2 2
+ // 4 3
+ // 5 3
+ //
+ static const unsigned CU32BitRegs[] = {
+ X86::EBX, X86::ECX, X86::EDX, X86::EDI, X86::ESI, X86::EBP, 0
+ };
+ static const unsigned CU64BitRegs[] = {
+ X86::RBX, X86::R12, X86::R13, X86::R14, X86::R15, X86::RBP, 0
+ };
+ const unsigned *CURegs = (Is64Bit ? CU64BitRegs : CU32BitRegs);
+
+ uint32_t RenumRegs[6];
+ for (unsigned i = 6 - RegCount; i < 6; ++i) {
+ int CUReg = getCompactUnwindRegNum(CURegs, SavedRegs[i]);
+ if (CUReg == -1) return ~0U;
+ SavedRegs[i] = CUReg;
+
+ unsigned Countless = 0;
+ for (unsigned j = 6 - RegCount; j < i; ++j)
+ if (SavedRegs[j] < SavedRegs[i])
+ ++Countless;
+
+ RenumRegs[i] = SavedRegs[i] - Countless - 1;
+ }
+
+ // Take the renumbered values and encode them into a 10-bit number.
+ uint32_t permutationEncoding = 0;
+ switch (RegCount) {
+ case 6:
+ permutationEncoding |= 120 * RenumRegs[0] + 24 * RenumRegs[1]
+ + 6 * RenumRegs[2] + 2 * RenumRegs[3]
+ + RenumRegs[4];
+ break;
+ case 5:
+ permutationEncoding |= 120 * RenumRegs[1] + 24 * RenumRegs[2]
+ + 6 * RenumRegs[3] + 2 * RenumRegs[4]
+ + RenumRegs[5];
+ break;
+ case 4:
+ permutationEncoding |= 60 * RenumRegs[2] + 12 * RenumRegs[3]
+ + 3 * RenumRegs[4] + RenumRegs[5];
+ break;
+ case 3:
+ permutationEncoding |= 20 * RenumRegs[3] + 4 * RenumRegs[4]
+ + RenumRegs[5];
+ break;
+ case 2:
+ permutationEncoding |= 5 * RenumRegs[4] + RenumRegs[5];
+ break;
+ case 1:
+ permutationEncoding |= RenumRegs[5];
+ break;
+ }
+
+ assert((permutationEncoding & 0x3FF) == permutationEncoding &&
+ "Invalid compact register encoding!");
+ return permutationEncoding;
+}
+
+/// encodeCompactUnwindRegistersWithFrame - Return the registers encoded for a
+/// compact encoding with a frame pointer.
+static uint32_t encodeCompactUnwindRegistersWithFrame(unsigned SavedRegs[6],
+ bool Is64Bit) {
+ static const unsigned CU32BitRegs[] = {
+ X86::EBX, X86::ECX, X86::EDX, X86::EDI, X86::ESI, X86::EBP, 0
+ };
+ static const unsigned CU64BitRegs[] = {
+ X86::RBX, X86::R12, X86::R13, X86::R14, X86::R15, X86::RBP, 0
+ };
+ const unsigned *CURegs = (Is64Bit ? CU64BitRegs : CU32BitRegs);
+
+ // Encode the registers in the order they were saved, 3-bits per register. The
+ // registers are numbered from 1 to 6.
+ uint32_t RegEnc = 0;
+ for (int I = 5; I >= 0; --I) {
+ unsigned Reg = SavedRegs[I];
+ if (Reg == 0) break;
+ int CURegNum = getCompactUnwindRegNum(CURegs, Reg);
+ if (CURegNum == -1)
+ return ~0U;
+ RegEnc |= (CURegNum & 0x7) << (5 - I);
+ }
+
+ assert((RegEnc & 0x7FFF) == RegEnc && "Invalid compact register encoding!");
+ return RegEnc;
+}
+
+uint32_t X86FrameLowering::getCompactUnwindEncoding(MachineFunction &MF) const {
+ const X86RegisterInfo *RegInfo = TM.getRegisterInfo();
+ unsigned FramePtr = RegInfo->getFrameRegister(MF);
+ unsigned StackPtr = RegInfo->getStackRegister();
+
+ X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
+ int TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta();
+
+ bool Is64Bit = STI.is64Bit();
+ bool HasFP = hasFP(MF);
+
+ unsigned SavedRegs[6] = { 0, 0, 0, 0, 0, 0 };
+ int SavedRegIdx = 6;
+
+ unsigned OffsetSize = (Is64Bit ? 8 : 4);
+
+ unsigned PushInstr = (Is64Bit ? X86::PUSH64r : X86::PUSH32r);
+ unsigned PushInstrSize = 1;
+ unsigned MoveInstr = (Is64Bit ? X86::MOV64rr : X86::MOV32rr);
+ unsigned MoveInstrSize = (Is64Bit ? 3 : 2);
+ unsigned SubtractInstr = getSUBriOpcode(Is64Bit, -TailCallReturnAddrDelta);
+ unsigned SubtractInstrIdx = (Is64Bit ? 3 : 2);
+
+ unsigned StackDivide = (Is64Bit ? 8 : 4);
+
+ unsigned InstrOffset = 0;
+ unsigned CFAOffset = 0;
+ unsigned StackAdjust = 0;
+
+ MachineBasicBlock &MBB = MF.front(); // Prologue is in entry BB.
+ bool ExpectEnd = false;
+ for (MachineBasicBlock::iterator
+ MBBI = MBB.begin(), MBBE = MBB.end(); MBBI != MBBE; ++MBBI) {
+ MachineInstr &MI = *MBBI;
+ unsigned Opc = MI.getOpcode();
+ if (Opc == X86::PROLOG_LABEL) continue;
+ if (!MI.getFlag(MachineInstr::FrameSetup)) break;
+
+ // We don't exect any more prolog instructions.
+ if (ExpectEnd) return 0;
+
+ if (Opc == PushInstr) {
+ // If there are too many saved registers, we cannot use compact encoding.
+ if (--SavedRegIdx < 0) return 0;
+
+ SavedRegs[SavedRegIdx] = MI.getOperand(0).getReg();
+ CFAOffset += OffsetSize;
+ InstrOffset += PushInstrSize;
+ } else if (Opc == MoveInstr) {
+ unsigned SrcReg = MI.getOperand(1).getReg();
+ unsigned DstReg = MI.getOperand(0).getReg();
+
+ if (DstReg != FramePtr || SrcReg != StackPtr)
+ return 0;
+
+ CFAOffset = 0;
+ memset(SavedRegs, 0, sizeof(SavedRegs));
+ InstrOffset += MoveInstrSize;
+ } else if (Opc == SubtractInstr) {
+ if (StackAdjust)
+ // We all ready have a stack pointer adjustment.
+ return 0;
+
+ if (!MI.getOperand(0).isReg() ||
+ MI.getOperand(0).getReg() != MI.getOperand(1).getReg() ||
+ MI.getOperand(0).getReg() != StackPtr || !MI.getOperand(2).isImm())
+ // We need this to be a stack adjustment pointer. Something like:
+ //
+ // %RSP<def> = SUB64ri8 %RSP, 48
+ return 0;
+
+ StackAdjust = MI.getOperand(2).getImm() / StackDivide;
+ SubtractInstrIdx += InstrOffset;
+ ExpectEnd = true;
+ }
+ }
+
+ // Encode that we are using EBP/RBP as the frame pointer.
+ uint32_t CompactUnwindEncoding = 0;
+ CFAOffset /= StackDivide;
+ if (HasFP) {
+ if ((CFAOffset & 0xFF) != CFAOffset)
+ // Offset was too big for compact encoding.
+ return 0;
+
+ // Get the encoding of the saved registers when we have a frame pointer.
+ uint32_t RegEnc = encodeCompactUnwindRegistersWithFrame(SavedRegs, Is64Bit);
+ if (RegEnc == ~0U)
+ return 0;
+
+ CompactUnwindEncoding |= 0x01000000;
+ CompactUnwindEncoding |= (CFAOffset & 0xFF) << 16;
+ CompactUnwindEncoding |= RegEnc & 0x7FFF;
+ } else {
+ unsigned FullOffset = CFAOffset + StackAdjust;
+ if ((FullOffset & 0xFF) == FullOffset) {
+ // Frameless stack.
+ CompactUnwindEncoding |= 0x02000000;
+ CompactUnwindEncoding |= (FullOffset & 0xFF) << 16;
+ } else {
+ if ((CFAOffset & 0x7) != CFAOffset)
+ // The extra stack adjustments are too big for us to handle.
+ return 0;
+
+ // Frameless stack with an offset too large for us to encode compactly.
+ CompactUnwindEncoding |= 0x03000000;
+
+ // Encode the offset to the nnnnnn value in the 'subl $nnnnnn, ESP'
+ // instruction.
+ CompactUnwindEncoding |= (SubtractInstrIdx & 0xFF) << 16;
+
+ // Encode any extra stack stack changes (done via push instructions).
+ CompactUnwindEncoding |= (CFAOffset & 0x7) << 13;
+ }
+
+ // Get the encoding of the saved registers when we don't have a frame
+ // pointer.
+ uint32_t RegEnc = encodeCompactUnwindRegistersWithoutFrame(SavedRegs,
+ 6 - SavedRegIdx,
+ Is64Bit);
+ if (RegEnc == ~0U) return 0;
+ CompactUnwindEncoding |= RegEnc & 0x3FF;
+ }
+
+ return CompactUnwindEncoding;
+}
+
/// emitPrologue - Push callee-saved registers onto the stack, which
/// automatically adjust the stack pointer. Adjust the stack pointer to allocate
/// space for local variables. Also emit labels used by the exception handler to
@@ -370,7 +612,6 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
unsigned SlotSize = RegInfo->getSlotSize();
unsigned FramePtr = RegInfo->getFrameRegister(MF);
unsigned StackPtr = RegInfo->getStackRegister();
-
DebugLoc DL;
// If we're forcing a stack realignment we can't rely on just the frame
@@ -398,7 +639,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
!RegInfo->needsStackRealignment(MF) &&
!MFI->hasVarSizedObjects() && // No dynamic alloca.
!MFI->adjustsStack() && // No calls.
- !IsWin64) { // Win64 has no Red Zone
+ !IsWin64 && // Win64 has no Red Zone
+ !EnableSegmentedStacks) { // Regular stack
uint64_t MinSize = X86FI->getCalleeSavedFrameSize();
if (HasFP) MinSize += SlotSize;
StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
@@ -459,7 +701,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
if (needsFrameMoves) {
// Mark the place where EBP/RBP was saved.
MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol();
- BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(FrameLabel);
+ BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL))
+ .addSym(FrameLabel);
// Define the current CFA rule to use the provided offset.
if (StackSize) {
@@ -478,7 +721,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
Moves.push_back(MachineMove(FrameLabel, FPDst, FPSrc));
}
- // Update EBP with the new base value...
+ // Update EBP with the new base value.
BuildMI(MBB, MBBI, DL,
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), FramePtr)
.addReg(StackPtr)
@@ -487,7 +730,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
if (needsFrameMoves) {
// Mark effective beginning of when frame pointer becomes valid.
MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol();
- BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(FrameLabel);
+ BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL))
+ .addSym(FrameLabel);
// Define the current CFA to use the EBP/RBP register.
MachineLocation FPDst(FramePtr);
@@ -504,8 +748,10 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
if (RegInfo->needsStackRealignment(MF)) {
MachineInstr *MI =
BuildMI(MBB, MBBI, DL,
- TII.get(Is64Bit ? X86::AND64ri32 : X86::AND32ri),
- StackPtr).addReg(StackPtr).addImm(-MaxAlign);
+ TII.get(Is64Bit ? X86::AND64ri32 : X86::AND32ri), StackPtr)
+ .addReg(StackPtr)
+ .addImm(-MaxAlign)
+ .setMIFlag(MachineInstr::FrameSetup);
// The EFLAGS implicit def is dead.
MI->getOperand(3).setIsDead();
@@ -522,6 +768,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
(MBBI->getOpcode() == X86::PUSH32r ||
MBBI->getOpcode() == X86::PUSH64r)) {
PushedRegs = true;
+ MBBI->setFlag(MachineInstr::FrameSetup);
++MBBI;
if (!HasFP && needsFrameMoves) {
@@ -530,8 +777,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(Label);
// Define the current CFA rule to use the provided offset.
- unsigned Ptr = StackSize ?
- MachineLocation::VirtualFP : StackPtr;
+ unsigned Ptr = StackSize ? MachineLocation::VirtualFP : StackPtr;
MachineLocation SPDst(Ptr);
MachineLocation SPSrc(Ptr, StackOffset);
Moves.push_back(MachineMove(Label, SPDst, SPSrc));
@@ -586,26 +832,30 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
// Save EAX
BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH32r))
- .addReg(X86::EAX, RegState::Kill);
+ .addReg(X86::EAX, RegState::Kill)
+ .setMIFlag(MachineInstr::FrameSetup);
}
if (Is64Bit) {
// Handle the 64-bit Windows ABI case where we need to call __chkstk.
// Function prologue is responsible for adjusting the stack pointer.
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64ri), X86::RAX)
- .addImm(NumBytes);
+ .addImm(NumBytes)
+ .setMIFlag(MachineInstr::FrameSetup);
} else {
// Allocate NumBytes-4 bytes on stack in case of isEAXAlive.
// We'll also use 4 already allocated bytes for EAX.
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
- .addImm(isEAXAlive ? NumBytes - 4 : NumBytes);
+ .addImm(isEAXAlive ? NumBytes - 4 : NumBytes)
+ .setMIFlag(MachineInstr::FrameSetup);
}
BuildMI(MBB, MBBI, DL,
TII.get(Is64Bit ? X86::W64ALLOCA : X86::CALLpcrel32))
.addExternalSymbol(StackProbeSymbol)
.addReg(StackPtr, RegState::Define | RegState::Implicit)
- .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit);
+ .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit)
+ .setMIFlag(MachineInstr::FrameSetup);
// MSVC x64's __chkstk needs to adjust %rsp.
// FIXME: %rax preserves the offset and should be available.
@@ -618,6 +868,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
MachineInstr *MI = addRegOffset(BuildMI(MF, DL, TII.get(X86::MOV32rm),
X86::EAX),
StackPtr, false, NumBytes - 4);
+ MI->setFlag(MachineInstr::FrameSetup);
MBB.insert(MBBI, MI);
}
} else if (NumBytes)
@@ -627,7 +878,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
if (( (!HasFP && NumBytes) || PushedRegs) && needsFrameMoves) {
// Mark end of stack pointer adjustment.
MCSymbol *Label = MMI.getContext().CreateTempSymbol();
- BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(Label);
+ BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL))
+ .addSym(Label);
if (!HasFP && NumBytes) {
// Define the current CFA rule to use the provided offset.
@@ -647,6 +899,11 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const {
if (PushedRegs)
emitCalleeSavedFrameMoves(MF, Label, HasFP ? FramePtr : StackPtr);
}
+
+ // Darwin 10.7 and greater has support for compact unwind encoding.
+ if (STI.getTargetTriple().isMacOSX() &&
+ !STI.getTargetTriple().isMacOSXVersionLT(10, 7))
+ MMI.setCompactUnwindEncoding(getCompactUnwindEncoding(MF));
}
void X86FrameLowering::emitEpilogue(MachineFunction &MF,
@@ -844,23 +1101,6 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
}
}
-void
-X86FrameLowering::getInitialFrameState(std::vector<MachineMove> &Moves) const {
- // Calculate amount of bytes used for return address storing
- int stackGrowth = (STI.is64Bit() ? -8 : -4);
- const X86RegisterInfo *RI = TM.getRegisterInfo();
-
- // Initial state of the frame pointer is esp+stackGrowth.
- MachineLocation Dst(MachineLocation::VirtualFP);
- MachineLocation Src(RI->getStackRegister(), stackGrowth);
- Moves.push_back(MachineMove(0, Dst, Src));
-
- // Add return address to move list
- MachineLocation CSDst(RI->getStackRegister(), stackGrowth);
- MachineLocation CSSrc(RI->getRARegister());
- Moves.push_back(MachineMove(0, CSDst, CSSrc));
-}
-
int X86FrameLowering::getFrameIndexOffset(const MachineFunction &MF, int FI) const {
const X86RegisterInfo *RI =
static_cast<const X86RegisterInfo*>(MF.getTarget().getRegisterInfo());
@@ -873,9 +1113,7 @@ int X86FrameLowering::getFrameIndexOffset(const MachineFunction &MF, int FI) con
// Skip the saved EBP.
Offset += RI->getSlotSize();
} else {
- unsigned Align = MFI->getObjectAlignment(FI);
- assert((-(Offset + StackSize)) % Align == 0);
- Align = 0;
+ assert((-(Offset + StackSize)) % MFI->getObjectAlignment(FI) == 0);
return Offset + StackSize;
}
// FIXME: Support tail calls
@@ -1027,184 +1265,183 @@ X86FrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
true);
assert(FrameIdx == MFI->getObjectIndexBegin() &&
"Slot for EBP register must be last in order to be found!");
- FrameIdx = 0;
+ (void)FrameIdx;
}
}
-/// permuteEncode - Create the permutation encoding used with frameless
-/// stacks. It is passed the number of registers to be saved and an array of the
-/// registers saved.
-static uint32_t permuteEncode(unsigned SavedCount, unsigned Registers[6]) {
- // The saved registers are numbered from 1 to 6. In order to encode the order
- // in which they were saved, we re-number them according to their place in the
- // register order. The re-numbering is relative to the last re-numbered
- // register. E.g., if we have registers {6, 2, 4, 5} saved in that order:
- //
- // Orig Re-Num
- // ---- ------
- // 6 6
- // 2 2
- // 4 3
- // 5 3
- //
- bool Used[7] = { false, false, false, false, false, false, false };
- uint32_t RenumRegs[6];
- for (unsigned I = 0; I < SavedCount; ++I) {
- uint32_t Renum = 0;
- for (unsigned U = 1; U < 7; ++U) {
- if (U == Registers[I])
- break;
- if (!Used[U])
- ++Renum;
- }
-
- Used[Registers[I]] = true;
- RenumRegs[I] = Renum;
+static bool
+HasNestArgument(const MachineFunction *MF) {
+ const Function *F = MF->getFunction();
+ for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
+ I != E; I++) {
+ if (I->hasNestAttr())
+ return true;
}
+ return false;
+}
- // Take the renumbered values and encode them into a 10-bit number.
- uint32_t permutationEncoding = 0;
- switch (SavedCount) {
- case 6:
- permutationEncoding |= 120 * RenumRegs[0] + 24 * RenumRegs[1]
- + 6 * RenumRegs[2] + 2 * RenumRegs[3]
- + RenumRegs[4];
- break;
- case 5:
- permutationEncoding |= 120 * RenumRegs[0] + 24 * RenumRegs[1]
- + 6 * RenumRegs[2] + 2 * RenumRegs[3]
- + RenumRegs[4];
- break;
- case 4:
- permutationEncoding |= 60 * RenumRegs[0] + 12 * RenumRegs[1]
- + 3 * RenumRegs[2] + RenumRegs[3];
- break;
- case 3:
- permutationEncoding |= 20 * RenumRegs[0] + 4 * RenumRegs[1]
- + RenumRegs[2];
- break;
- case 2:
- permutationEncoding |= 5 * RenumRegs[0] + RenumRegs[1];
- break;
- case 1:
- permutationEncoding |= RenumRegs[0];
- break;
+static unsigned
+GetScratchRegister(bool Is64Bit, const MachineFunction &MF) {
+ if (Is64Bit) {
+ return X86::R11;
+ } else {
+ CallingConv::ID CallingConvention = MF.getFunction()->getCallingConv();
+ bool IsNested = HasNestArgument(&MF);
+
+ if (CallingConvention == CallingConv::X86_FastCall) {
+ if (IsNested) {
+ report_fatal_error("Segmented stacks does not support fastcall with "
+ "nested function.");
+ return -1;
+ } else {
+ return X86::EAX;
+ }
+ } else {
+ if (IsNested)
+ return X86::EDX;
+ else
+ return X86::ECX;
+ }
}
-
- return permutationEncoding;
}
-uint32_t X86FrameLowering::
-getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs,
- int DataAlignmentFactor, bool IsEH) const {
- uint32_t Encoding = 0;
- int CFAOffset = 0;
- const TargetRegisterInfo *TRI = TM.getRegisterInfo();
- unsigned SavedRegs[6] = { 0, 0, 0, 0, 0, 0 };
- unsigned SavedRegIdx = 0;
- int FramePointerReg = -1;
+void
+X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
+ MachineBasicBlock &prologueMBB = MF.front();
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ const X86InstrInfo &TII = *TM.getInstrInfo();
+ uint64_t StackSize;
+ bool Is64Bit = STI.is64Bit();
+ unsigned TlsReg, TlsOffset;
+ DebugLoc DL;
+ const X86Subtarget *ST = &MF.getTarget().getSubtarget<X86Subtarget>();
- for (ArrayRef<MCCFIInstruction>::const_iterator
- I = Instrs.begin(), E = Instrs.end(); I != E; ++I) {
- const MCCFIInstruction &Inst = *I;
- MCSymbol *Label = Inst.getLabel();
+ unsigned ScratchReg = GetScratchRegister(Is64Bit, MF);
+ assert(!MF.getRegInfo().isLiveIn(ScratchReg) &&
+ "Scratch register is live-in");
- // Ignore invalid labels.
- if (Label && !Label->isDefined()) continue;
+ if (MF.getFunction()->isVarArg())
+ report_fatal_error("Segmented stacks do not support vararg functions.");
+ if (!ST->isTargetLinux())
+ report_fatal_error("Segmented stacks supported only on linux.");
- unsigned Operation = Inst.getOperation();
- if (Operation != MCCFIInstruction::Move &&
- Operation != MCCFIInstruction::RelMove)
- // FIXME: We can't handle this frame just yet.
- return 0;
-
- const MachineLocation &Dst = Inst.getDestination();
- const MachineLocation &Src = Inst.getSource();
- const bool IsRelative = (Operation == MCCFIInstruction::RelMove);
-
- if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
- if (Src.getReg() != MachineLocation::VirtualFP) {
- // DW_CFA_def_cfa
- assert(FramePointerReg == -1 &&"Defining more than one frame pointer?");
- if (TRI->getLLVMRegNum(Src.getReg(), IsEH) != X86::EBP &&
- TRI->getLLVMRegNum(Src.getReg(), IsEH) != X86::RBP)
- // The frame pointer isn't EBP/RBP. Cannot make unwind information
- // compact.
- return 0;
- FramePointerReg = TRI->getCompactUnwindRegNum(Src.getReg(), IsEH);
- } // else DW_CFA_def_cfa_offset
-
- if (IsRelative)
- CFAOffset += Src.getOffset();
- else
- CFAOffset -= Src.getOffset();
+ MachineBasicBlock *allocMBB = MF.CreateMachineBasicBlock();
+ MachineBasicBlock *checkMBB = MF.CreateMachineBasicBlock();
+ X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
+ bool IsNested = false;
- continue;
- }
+ // We need to know if the function has a nest argument only in 64 bit mode.
+ if (Is64Bit)
+ IsNested = HasNestArgument(&MF);
- if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) {
- // DW_CFA_def_cfa_register
- assert(FramePointerReg == -1 && "Defining more than one frame pointer?");
+ // The MOV R10, RAX needs to be in a different block, since the RET we emit in
+ // allocMBB needs to be last (terminating) instruction.
+ MachineBasicBlock *restoreR10MBB = NULL;
+ if (IsNested)
+ restoreR10MBB = MF.CreateMachineBasicBlock();
- if (TRI->getLLVMRegNum(Dst.getReg(), IsEH) != X86::EBP &&
- TRI->getLLVMRegNum(Dst.getReg(), IsEH) != X86::RBP)
- // The frame pointer isn't EBP/RBP. Cannot make unwind information
- // compact.
- return 0;
+ for (MachineBasicBlock::livein_iterator i = prologueMBB.livein_begin(),
+ e = prologueMBB.livein_end(); i != e; i++) {
+ allocMBB->addLiveIn(*i);
+ checkMBB->addLiveIn(*i);
- FramePointerReg = TRI->getCompactUnwindRegNum(Dst.getReg(), IsEH);
- if (SavedRegIdx != 1 || SavedRegs[0] != unsigned(FramePointerReg))
- return 0;
+ if (IsNested)
+ restoreR10MBB->addLiveIn(*i);
+ }
- SavedRegs[0] = 0;
- SavedRegIdx = 0;
- continue;
- }
+ if (IsNested) {
+ allocMBB->addLiveIn(X86::R10);
+ restoreR10MBB->addLiveIn(X86::RAX);
+ }
- unsigned Reg = Src.getReg();
- int Offset = Dst.getOffset();
- if (IsRelative)
- Offset -= CFAOffset;
- Offset /= DataAlignmentFactor;
+ if (IsNested)
+ MF.push_front(restoreR10MBB);
+ MF.push_front(allocMBB);
+ MF.push_front(checkMBB);
+
+ // Eventually StackSize will be calculated by a link-time pass; which will
+ // also decide whether checking code needs to be injected into this particular
+ // prologue.
+ StackSize = MFI->getStackSize();
+
+ // Read the limit off the current stacklet off the stack_guard location.
+ if (Is64Bit) {
+ TlsReg = X86::FS;
+ TlsOffset = 0x70;
+
+ BuildMI(checkMBB, DL, TII.get(X86::LEA64r), ScratchReg).addReg(X86::RSP)
+ .addImm(0).addReg(0).addImm(-StackSize).addReg(0);
+ BuildMI(checkMBB, DL, TII.get(X86::CMP64rm)).addReg(ScratchReg)
+ .addReg(0).addImm(0).addReg(0).addImm(TlsOffset).addReg(TlsReg);
+ } else {
+ TlsReg = X86::GS;
+ TlsOffset = 0x30;
- if (Offset < 0) {
- // FIXME: Handle?
- // DW_CFA_offset_extended_sf
- return 0;
- } else if (Reg < 64) {
- // DW_CFA_offset + Reg
- if (SavedRegIdx >= 6) return 0;
- int CURegNum = TRI->getCompactUnwindRegNum(Reg, IsEH);
- if (CURegNum == -1) return 0;
- SavedRegs[SavedRegIdx++] = CURegNum;
- } else {
- // FIXME: Handle?
- // DW_CFA_offset_extended
- return 0;
- }
+ BuildMI(checkMBB, DL, TII.get(X86::LEA32r), ScratchReg).addReg(X86::ESP)
+ .addImm(0).addReg(0).addImm(-StackSize).addReg(0);
+ BuildMI(checkMBB, DL, TII.get(X86::CMP32rm)).addReg(ScratchReg)
+ .addReg(0).addImm(0).addReg(0).addImm(TlsOffset).addReg(TlsReg);
}
- // Bail if there are too many registers to encode.
- if (SavedRegIdx > 6) return 0;
+ // This jump is taken if SP >= (Stacklet Limit + Stack Space required).
+ // It jumps to normal execution of the function body.
+ BuildMI(checkMBB, DL, TII.get(X86::JG_4)).addMBB(&prologueMBB);
+
+ // On 32 bit we first push the arguments size and then the frame size. On 64
+ // bit, we pass the stack frame size in r10 and the argument size in r11.
+ if (Is64Bit) {
+ // Functions with nested arguments use R10, so it needs to be saved across
+ // the call to _morestack
+
+ if (IsNested)
+ BuildMI(allocMBB, DL, TII.get(X86::MOV64rr), X86::RAX).addReg(X86::R10);
+
+ BuildMI(allocMBB, DL, TII.get(X86::MOV64ri), X86::R10)
+ .addImm(StackSize);
+ BuildMI(allocMBB, DL, TII.get(X86::MOV64ri), X86::R11)
+ .addImm(X86FI->getArgumentStackSize());
+ MF.getRegInfo().setPhysRegUsed(X86::R10);
+ MF.getRegInfo().setPhysRegUsed(X86::R11);
+ } else {
+ // Since we'll call __morestack, stack alignment needs to be preserved.
+ BuildMI(allocMBB, DL, TII.get(X86::SUB32ri), X86::ESP).addReg(X86::ESP)
+ .addImm(8);
+ BuildMI(allocMBB, DL, TII.get(X86::PUSHi32))
+ .addImm(X86FI->getArgumentStackSize());
+ BuildMI(allocMBB, DL, TII.get(X86::PUSHi32))
+ .addImm(StackSize);
+ }
- // Check if the offset is too big.
- CFAOffset /= 4;
- if ((CFAOffset & 0xFF) != CFAOffset)
- return 0;
- Encoding |= (CFAOffset & 0xFF) << 16; // Size encoding.
-
- if (FramePointerReg != -1) {
- Encoding |= 0x01000000; // EBP/RBP Unwind Frame
- for (unsigned I = 0; I != SavedRegIdx; ++I) {
- unsigned Reg = SavedRegs[I];
- if (Reg == unsigned(FramePointerReg)) continue;
- Encoding |= (Reg & 0x7) << (I * 3); // Register encoding
- }
+ // __morestack is in libgcc
+ if (Is64Bit)
+ BuildMI(allocMBB, DL, TII.get(X86::CALL64pcrel32))
+ .addExternalSymbol("__morestack");
+ else
+ BuildMI(allocMBB, DL, TII.get(X86::CALLpcrel32))
+ .addExternalSymbol("__morestack");
+
+ // __morestack only seems to remove 8 bytes off the stack. Add back the
+ // additional 8 bytes we added before pushing the arguments.
+ if (!Is64Bit)
+ BuildMI(allocMBB, DL, TII.get(X86::ADD32ri), X86::ESP).addReg(X86::ESP)
+ .addImm(8);
+ BuildMI(allocMBB, DL, TII.get(X86::RET));
+
+ if (IsNested)
+ BuildMI(restoreR10MBB, DL, TII.get(X86::MOV64rr), X86::R10)
+ .addReg(X86::RAX);
+
+ if (IsNested) {
+ allocMBB->addSuccessor(restoreR10MBB);
+ restoreR10MBB->addSuccessor(&prologueMBB);
} else {
- Encoding |= 0x02000000; // Frameless unwind with small stack
- Encoding |= (SavedRegIdx & 0x7) << 10;
- Encoding |= permuteEncode(SavedRegIdx, SavedRegs);
+ allocMBB->addSuccessor(&prologueMBB);
}
- return Encoding;
+ checkMBB->addSuccessor(allocMBB);
+ checkMBB->addSuccessor(&prologueMBB);
+
+#ifdef XDEBUG
+ MF.verify();
+#endif
}
diff --git a/lib/Target/X86/X86FrameLowering.h b/lib/Target/X86/X86FrameLowering.h
index 14c31ed..6f49064 100644
--- a/lib/Target/X86/X86FrameLowering.h
+++ b/lib/Target/X86/X86FrameLowering.h
@@ -41,6 +41,8 @@ public:
void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
+ void adjustForSegmentedStacks(MachineFunction &MF) const;
+
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS = NULL) const;
@@ -57,11 +59,8 @@ public:
bool hasFP(const MachineFunction &MF) const;
bool hasReservedCallFrame(const MachineFunction &MF) const;
- void getInitialFrameState(std::vector<MachineMove> &Moves) const;
int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
-
- uint32_t getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs,
- int DataAlignmentFactor, bool IsEH) const;
+ uint32_t getCompactUnwindEncoding(MachineFunction &MF) const;
};
} // End llvm namespace
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index 2b0f283..02b0ff2 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -474,10 +474,15 @@ void X86DAGToDAGISel::PreprocessISelDAG() {
if (N->getOpcode() != ISD::FP_ROUND && N->getOpcode() != ISD::FP_EXTEND)
continue;
- // If the source and destination are SSE registers, then this is a legal
- // conversion that should not be lowered.
EVT SrcVT = N->getOperand(0).getValueType();
EVT DstVT = N->getValueType(0);
+
+ // If any of the sources are vectors, no fp stack involved.
+ if (SrcVT.isVector() || DstVT.isVector())
+ continue;
+
+ // If the source and destination are SSE registers, then this is a legal
+ // conversion that should not be lowered.
bool SrcIsSSE = X86Lowering.isScalarFPTypeInSSEReg(SrcVT);
bool DstIsSSE = X86Lowering.isScalarFPTypeInSSEReg(DstVT);
if (SrcIsSSE && DstIsSSE)
@@ -2168,9 +2173,10 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) {
SDValue Subreg = CurDAG->getTargetExtractSubreg(X86::sub_8bit_hi, dl,
MVT::i8, Reg);
- // Emit a testb. No special NOREX tricks are needed since there's
- // only one GPR operand!
- return CurDAG->getMachineNode(X86::TEST8ri, dl, MVT::i32,
+ // Emit a testb. The EXTRACT_SUBREG becomes a COPY that can only
+ // target GR8_NOREX registers, so make sure the register class is
+ // forced.
+ return CurDAG->getMachineNode(X86::TEST8ri_NOREX, dl, MVT::i32,
Subreg, ShiftedImm);
}
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 5096d9a..7c8ce17 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -51,6 +51,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetOptions.h"
using namespace llvm;
using namespace dwarf;
@@ -71,9 +72,6 @@ static SDValue Extract128BitVector(SDValue Vec,
SelectionDAG &DAG,
DebugLoc dl);
-static SDValue ConcatVectors(SDValue Lower, SDValue Upper, SelectionDAG &DAG);
-
-
/// Generate a DAG to grab 128-bits from a vector > 128 bits. This
/// sets things up to match to an AVX VEXTRACTF128 instruction or a
/// simple subregister reference. Idx is an index in the 128 bits we
@@ -85,14 +83,10 @@ static SDValue Extract128BitVector(SDValue Vec,
DebugLoc dl) {
EVT VT = Vec.getValueType();
assert(VT.getSizeInBits() == 256 && "Unexpected vector size!");
-
EVT ElVT = VT.getVectorElementType();
-
- int Factor = VT.getSizeInBits() / 128;
-
- EVT ResultVT = EVT::getVectorVT(*DAG.getContext(),
- ElVT,
- VT.getVectorNumElements() / Factor);
+ int Factor = VT.getSizeInBits()/128;
+ EVT ResultVT = EVT::getVectorVT(*DAG.getContext(), ElVT,
+ VT.getVectorNumElements()/Factor);
// Extract from UNDEF is UNDEF.
if (Vec.getOpcode() == ISD::UNDEF)
@@ -111,7 +105,6 @@ static SDValue Extract128BitVector(SDValue Vec,
* ElemsPerChunk);
SDValue VecIdx = DAG.getConstant(NormalizedIdxVal, MVT::i32);
-
SDValue Result = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, ResultVT, Vec,
VecIdx);
@@ -136,21 +129,18 @@ static SDValue Insert128BitVector(SDValue Result,
assert(VT.getSizeInBits() == 128 && "Unexpected vector size!");
EVT ElVT = VT.getVectorElementType();
-
unsigned IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
-
EVT ResultVT = Result.getValueType();
// Insert the relevant 128 bits.
- unsigned ElemsPerChunk = 128 / ElVT.getSizeInBits();
+ unsigned ElemsPerChunk = 128/ElVT.getSizeInBits();
// This is the index of the first element of the 128-bit chunk
// we want.
- unsigned NormalizedIdxVal = (((IdxVal * ElVT.getSizeInBits()) / 128)
+ unsigned NormalizedIdxVal = (((IdxVal * ElVT.getSizeInBits())/128)
* ElemsPerChunk);
SDValue VecIdx = DAG.getConstant(NormalizedIdxVal, MVT::i32);
-
Result = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResultVT, Result, Vec,
VecIdx);
return Result;
@@ -159,34 +149,6 @@ static SDValue Insert128BitVector(SDValue Result,
return SDValue();
}
-/// Given two vectors, concat them.
-static SDValue ConcatVectors(SDValue Lower, SDValue Upper, SelectionDAG &DAG) {
- DebugLoc dl = Lower.getDebugLoc();
-
- assert(Lower.getValueType() == Upper.getValueType() && "Mismatched vectors!");
-
- EVT VT = EVT::getVectorVT(*DAG.getContext(),
- Lower.getValueType().getVectorElementType(),
- Lower.getValueType().getVectorNumElements() * 2);
-
- // TODO: Generalize to arbitrary vector length (this assumes 256-bit vectors).
- assert(VT.getSizeInBits() == 256 && "Unsupported vector concat!");
-
- // Insert the upper subvector.
- SDValue Vec = Insert128BitVector(DAG.getNode(ISD::UNDEF, dl, VT), Upper,
- DAG.getConstant(
- // This is half the length of the result
- // vector. Start inserting the upper 128
- // bits here.
- Lower.getValueType().getVectorNumElements(),
- MVT::i32),
- DAG, dl);
-
- // Insert the lower subvector.
- Vec = Insert128BitVector(Vec, Lower, DAG.getConstant(0, MVT::i32), DAG, dl);
- return Vec;
-}
-
static TargetLoweringObjectFile *createTLOF(X86TargetMachine &TM) {
const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
bool is64Bit = Subtarget->is64Bit();
@@ -197,11 +159,8 @@ static TargetLoweringObjectFile *createTLOF(X86TargetMachine &TM) {
return new TargetLoweringObjectFileMachO();
}
- if (Subtarget->isTargetELF()) {
- if (is64Bit)
- return new X8664_ELFTargetObjectFile(TM);
- return new X8632_ELFTargetObjectFile(TM);
- }
+ if (Subtarget->isTargetELF())
+ return new TargetLoweringObjectFileELF();
if (Subtarget->isTargetCOFF() && !Subtarget->isTargetEnvMacho())
return new TargetLoweringObjectFileCOFF();
llvm_unreachable("unknown subtarget type");
@@ -222,6 +181,8 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
// X86 is weird, it always uses i8 for shift amounts and setcc results.
setBooleanContents(ZeroOrOneBooleanContent);
+ // X86-SSE is even stranger. It uses -1 or 0 for vector masks.
+ setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
// For 64-bit since we have so many registers use the ILP scheduler, for
// 32-bit code use the register pressure specific scheduling.
@@ -354,7 +315,8 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::FP_TO_UINT , MVT::i64 , Expand);
setOperationAction(ISD::FP_TO_UINT , MVT::i32 , Promote);
} else if (!UseSoftFloat) {
- if (X86ScalarSSEf32 && !Subtarget->hasSSE3())
+ // Since AVX is a superset of SSE3, only check for SSE here.
+ if (Subtarget->hasSSE1() && !Subtarget->hasSSE3())
// Expand FP_TO_UINT into a select.
// FIXME: We would like to use a Custom expander here eventually to do
// the optimal thing for SSE vs. the default expansion in the legalizer.
@@ -417,15 +379,24 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::FREM , MVT::f80 , Expand);
setOperationAction(ISD::FLT_ROUNDS_ , MVT::i32 , Custom);
- setOperationAction(ISD::CTTZ , MVT::i8 , Custom);
- setOperationAction(ISD::CTLZ , MVT::i8 , Custom);
- setOperationAction(ISD::CTTZ , MVT::i16 , Custom);
- setOperationAction(ISD::CTLZ , MVT::i16 , Custom);
- setOperationAction(ISD::CTTZ , MVT::i32 , Custom);
- setOperationAction(ISD::CTLZ , MVT::i32 , Custom);
- if (Subtarget->is64Bit()) {
- setOperationAction(ISD::CTTZ , MVT::i64 , Custom);
- setOperationAction(ISD::CTLZ , MVT::i64 , Custom);
+ if (Subtarget->hasBMI()) {
+ setOperationAction(ISD::CTTZ , MVT::i8 , Promote);
+ } else {
+ setOperationAction(ISD::CTTZ , MVT::i8 , Custom);
+ setOperationAction(ISD::CTTZ , MVT::i16 , Custom);
+ setOperationAction(ISD::CTTZ , MVT::i32 , Custom);
+ if (Subtarget->is64Bit())
+ setOperationAction(ISD::CTTZ , MVT::i64 , Custom);
+ }
+
+ if (Subtarget->hasLZCNT()) {
+ setOperationAction(ISD::CTLZ , MVT::i8 , Promote);
+ } else {
+ setOperationAction(ISD::CTLZ , MVT::i8 , Custom);
+ setOperationAction(ISD::CTLZ , MVT::i16 , Custom);
+ setOperationAction(ISD::CTLZ , MVT::i32 , Custom);
+ if (Subtarget->is64Bit())
+ setOperationAction(ISD::CTLZ , MVT::i64 , Custom);
}
if (Subtarget->hasPOPCNT()) {
@@ -491,8 +462,8 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
if (Subtarget->hasXMM())
setOperationAction(ISD::PREFETCH , MVT::Other, Legal);
- // We may not have a libcall for MEMBARRIER so we should lower this.
setOperationAction(ISD::MEMBARRIER , MVT::Other, Custom);
+ setOperationAction(ISD::ATOMIC_FENCE , MVT::Other, Custom);
// On X86 and X86-64, atomic operations are lowered to locked instructions.
// Locked instructions, in turn, have implicit fence semantics (all memory
@@ -506,9 +477,11 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
MVT VT = IntVTs[i];
setOperationAction(ISD::ATOMIC_CMP_SWAP, VT, Custom);
setOperationAction(ISD::ATOMIC_LOAD_SUB, VT, Custom);
+ setOperationAction(ISD::ATOMIC_STORE, VT, Custom);
}
if (!Subtarget->is64Bit()) {
+ setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom);
setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i64, Custom);
setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i64, Custom);
setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i64, Custom);
@@ -518,6 +491,10 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Custom);
}
+ if (Subtarget->hasCmpxchg16b()) {
+ setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i128, Custom);
+ }
+
// FIXME - use subtarget debug flags
if (!Subtarget->isTargetDarwin() &&
!Subtarget->isTargetELF() &&
@@ -539,7 +516,8 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);
setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i64, Custom);
- setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom);
+ setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom);
+ setOperationAction(ISD::ADJUST_TRAMPOLINE, MVT::Other, Custom);
setOperationAction(ISD::TRAP, MVT::Other, Legal);
@@ -556,11 +534,16 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
- setOperationAction(ISD::DYNAMIC_STACKALLOC,
- (Subtarget->is64Bit() ? MVT::i64 : MVT::i32),
- (Subtarget->isTargetCOFF()
- && !Subtarget->isTargetEnvMacho()
- ? Custom : Expand));
+
+ if (Subtarget->isTargetCOFF() && !Subtarget->isTargetEnvMacho())
+ setOperationAction(ISD::DYNAMIC_STACKALLOC, Subtarget->is64Bit() ?
+ MVT::i64 : MVT::i32, Custom);
+ else if (EnableSegmentedStacks)
+ setOperationAction(ISD::DYNAMIC_STACKALLOC, Subtarget->is64Bit() ?
+ MVT::i64 : MVT::i32, Custom);
+ else
+ setOperationAction(ISD::DYNAMIC_STACKALLOC, Subtarget->is64Bit() ?
+ MVT::i64 : MVT::i32, Expand);
if (!UseSoftFloat && X86ScalarSSEf64) {
// f32 and f64 use SSE.
@@ -739,7 +722,7 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::ROTL, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::ROTR, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::BSWAP, (MVT::SimpleValueType)VT, Expand);
- setOperationAction(ISD::VSETCC, (MVT::SimpleValueType)VT, Expand);
+ setOperationAction(ISD::SETCC, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::FLOG, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::FLOG2, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::FLOG10, (MVT::SimpleValueType)VT, Expand);
@@ -754,6 +737,7 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::SIGN_EXTEND, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::ZERO_EXTEND, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::ANY_EXTEND, (MVT::SimpleValueType)VT, Expand);
+ setOperationAction(ISD::VSELECT, (MVT::SimpleValueType)VT, Expand);
for (unsigned InnerVT = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
InnerVT <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++InnerVT)
setTruncStoreAction((MVT::SimpleValueType)VT,
@@ -816,7 +800,7 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v4f32, Custom);
setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v4f32, Custom);
setOperationAction(ISD::SELECT, MVT::v4f32, Custom);
- setOperationAction(ISD::VSETCC, MVT::v4f32, Custom);
+ setOperationAction(ISD::SETCC, MVT::v4f32, Custom);
}
if (!UseSoftFloat && Subtarget->hasXMMInt()) {
@@ -846,10 +830,10 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::FSQRT, MVT::v2f64, Legal);
setOperationAction(ISD::FNEG, MVT::v2f64, Custom);
- setOperationAction(ISD::VSETCC, MVT::v2f64, Custom);
- setOperationAction(ISD::VSETCC, MVT::v16i8, Custom);
- setOperationAction(ISD::VSETCC, MVT::v8i16, Custom);
- setOperationAction(ISD::VSETCC, MVT::v4i32, Custom);
+ setOperationAction(ISD::SETCC, MVT::v2i64, Custom);
+ setOperationAction(ISD::SETCC, MVT::v16i8, Custom);
+ setOperationAction(ISD::SETCC, MVT::v8i16, Custom);
+ setOperationAction(ISD::SETCC, MVT::v4i32, Custom);
setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v16i8, Custom);
setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v8i16, Custom);
@@ -925,7 +909,7 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::SINT_TO_FP, MVT::v4i32, Legal);
}
- if (Subtarget->hasSSE41()) {
+ if (Subtarget->hasSSE41() || Subtarget->hasAVX()) {
setOperationAction(ISD::FFLOOR, MVT::f32, Legal);
setOperationAction(ISD::FCEIL, MVT::f32, Legal);
setOperationAction(ISD::FTRUNC, MVT::f32, Legal);
@@ -944,6 +928,12 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::SHL, MVT::v4i32, Custom);
setOperationAction(ISD::SHL, MVT::v16i8, Custom);
+ setOperationAction(ISD::VSELECT, MVT::v2f64, Legal);
+ setOperationAction(ISD::VSELECT, MVT::v2i64, Legal);
+ setOperationAction(ISD::VSELECT, MVT::v16i8, Legal);
+ setOperationAction(ISD::VSELECT, MVT::v4i32, Legal);
+ setOperationAction(ISD::VSELECT, MVT::v4f32, Legal);
+
// i8 and i16 vectors are custom , because the source register and source
// source memory operand types are not the same width. f32 vectors are
// custom since the immediate controlling the insert encodes additional
@@ -964,10 +954,11 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
}
}
- if (Subtarget->hasSSE2()) {
+ if (Subtarget->hasXMMInt()) {
setOperationAction(ISD::SRL, MVT::v2i64, Custom);
setOperationAction(ISD::SRL, MVT::v4i32, Custom);
setOperationAction(ISD::SRL, MVT::v16i8, Custom);
+ setOperationAction(ISD::SRL, MVT::v8i16, Custom);
setOperationAction(ISD::SHL, MVT::v2i64, Custom);
setOperationAction(ISD::SHL, MVT::v4i32, Custom);
@@ -977,15 +968,16 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::SRA, MVT::v8i16, Custom);
}
- if (Subtarget->hasSSE42())
- setOperationAction(ISD::VSETCC, MVT::v2i64, Custom);
+ if (Subtarget->hasSSE42() || Subtarget->hasAVX())
+ setOperationAction(ISD::SETCC, MVT::v2i64, Custom);
if (!UseSoftFloat && Subtarget->hasAVX()) {
- addRegisterClass(MVT::v8f32, X86::VR256RegisterClass);
- addRegisterClass(MVT::v4f64, X86::VR256RegisterClass);
- addRegisterClass(MVT::v8i32, X86::VR256RegisterClass);
- addRegisterClass(MVT::v4i64, X86::VR256RegisterClass);
- addRegisterClass(MVT::v32i8, X86::VR256RegisterClass);
+ addRegisterClass(MVT::v32i8, X86::VR256RegisterClass);
+ addRegisterClass(MVT::v16i16, X86::VR256RegisterClass);
+ addRegisterClass(MVT::v8i32, X86::VR256RegisterClass);
+ addRegisterClass(MVT::v8f32, X86::VR256RegisterClass);
+ addRegisterClass(MVT::v4i64, X86::VR256RegisterClass);
+ addRegisterClass(MVT::v4f64, X86::VR256RegisterClass);
setOperationAction(ISD::LOAD, MVT::v8f32, Legal);
setOperationAction(ISD::LOAD, MVT::v4f64, Legal);
@@ -1005,6 +997,59 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::FSQRT, MVT::v4f64, Legal);
setOperationAction(ISD::FNEG, MVT::v4f64, Custom);
+ setOperationAction(ISD::FP_TO_SINT, MVT::v8i32, Legal);
+ setOperationAction(ISD::SINT_TO_FP, MVT::v8i32, Legal);
+ setOperationAction(ISD::FP_ROUND, MVT::v4f32, Legal);
+
+ setOperationAction(ISD::CONCAT_VECTORS, MVT::v4f64, Custom);
+ setOperationAction(ISD::CONCAT_VECTORS, MVT::v4i64, Custom);
+ setOperationAction(ISD::CONCAT_VECTORS, MVT::v8f32, Custom);
+ setOperationAction(ISD::CONCAT_VECTORS, MVT::v8i32, Custom);
+ setOperationAction(ISD::CONCAT_VECTORS, MVT::v32i8, Custom);
+ setOperationAction(ISD::CONCAT_VECTORS, MVT::v16i16, Custom);
+
+ setOperationAction(ISD::SRL, MVT::v4i64, Custom);
+ setOperationAction(ISD::SRL, MVT::v8i32, Custom);
+ setOperationAction(ISD::SRL, MVT::v16i16, Custom);
+ setOperationAction(ISD::SRL, MVT::v32i8, Custom);
+
+ setOperationAction(ISD::SHL, MVT::v4i64, Custom);
+ setOperationAction(ISD::SHL, MVT::v8i32, Custom);
+ setOperationAction(ISD::SHL, MVT::v16i16, Custom);
+ setOperationAction(ISD::SHL, MVT::v32i8, Custom);
+
+ setOperationAction(ISD::SRA, MVT::v8i32, Custom);
+ setOperationAction(ISD::SRA, MVT::v16i16, Custom);
+
+ setOperationAction(ISD::SETCC, MVT::v32i8, Custom);
+ setOperationAction(ISD::SETCC, MVT::v16i16, Custom);
+ setOperationAction(ISD::SETCC, MVT::v8i32, Custom);
+ setOperationAction(ISD::SETCC, MVT::v4i64, Custom);
+
+ setOperationAction(ISD::SELECT, MVT::v4f64, Custom);
+ setOperationAction(ISD::SELECT, MVT::v4i64, Custom);
+ setOperationAction(ISD::SELECT, MVT::v8f32, Custom);
+
+ setOperationAction(ISD::VSELECT, MVT::v4f64, Legal);
+ setOperationAction(ISD::VSELECT, MVT::v4i64, Legal);
+ setOperationAction(ISD::VSELECT, MVT::v8i32, Legal);
+ setOperationAction(ISD::VSELECT, MVT::v8f32, Legal);
+
+ setOperationAction(ISD::ADD, MVT::v4i64, Custom);
+ setOperationAction(ISD::ADD, MVT::v8i32, Custom);
+ setOperationAction(ISD::ADD, MVT::v16i16, Custom);
+ setOperationAction(ISD::ADD, MVT::v32i8, Custom);
+
+ setOperationAction(ISD::SUB, MVT::v4i64, Custom);
+ setOperationAction(ISD::SUB, MVT::v8i32, Custom);
+ setOperationAction(ISD::SUB, MVT::v16i16, Custom);
+ setOperationAction(ISD::SUB, MVT::v32i8, Custom);
+
+ setOperationAction(ISD::MUL, MVT::v4i64, Custom);
+ setOperationAction(ISD::MUL, MVT::v8i32, Custom);
+ setOperationAction(ISD::MUL, MVT::v16i16, Custom);
+ // Don't lower v32i8 because there is no 128-bit byte mul
+
// Custom lower several nodes for 256-bit types.
for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
@@ -1093,6 +1138,7 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setTargetDAGCombine(ISD::VECTOR_SHUFFLE);
setTargetDAGCombine(ISD::EXTRACT_VECTOR_ELT);
setTargetDAGCombine(ISD::BUILD_VECTOR);
+ setTargetDAGCombine(ISD::VSELECT);
setTargetDAGCombine(ISD::SELECT);
setTargetDAGCombine(ISD::SHL);
setTargetDAGCombine(ISD::SRA);
@@ -1100,7 +1146,10 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setTargetDAGCombine(ISD::OR);
setTargetDAGCombine(ISD::AND);
setTargetDAGCombine(ISD::ADD);
+ setTargetDAGCombine(ISD::FADD);
+ setTargetDAGCombine(ISD::FSUB);
setTargetDAGCombine(ISD::SUB);
+ setTargetDAGCombine(ISD::LOAD);
setTargetDAGCombine(ISD::STORE);
setTargetDAGCombine(ISD::ZERO_EXTEND);
setTargetDAGCombine(ISD::SINT_TO_FP);
@@ -1124,25 +1173,26 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
}
-MVT::SimpleValueType X86TargetLowering::getSetCCResultType(EVT VT) const {
- return MVT::i8;
+EVT X86TargetLowering::getSetCCResultType(EVT VT) const {
+ if (!VT.isVector()) return MVT::i8;
+ return VT.changeVectorElementTypeToInteger();
}
/// getMaxByValAlign - Helper for getByValTypeAlignment to determine
/// the desired ByVal argument alignment.
-static void getMaxByValAlign(const Type *Ty, unsigned &MaxAlign) {
+static void getMaxByValAlign(Type *Ty, unsigned &MaxAlign) {
if (MaxAlign == 16)
return;
- if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) {
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty)) {
if (VTy->getBitWidth() == 128)
MaxAlign = 16;
- } else if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
+ } else if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
unsigned EltAlign = 0;
getMaxByValAlign(ATy->getElementType(), EltAlign);
if (EltAlign > MaxAlign)
MaxAlign = EltAlign;
- } else if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+ } else if (StructType *STy = dyn_cast<StructType>(Ty)) {
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
unsigned EltAlign = 0;
getMaxByValAlign(STy->getElementType(i), EltAlign);
@@ -1159,7 +1209,7 @@ static void getMaxByValAlign(const Type *Ty, unsigned &MaxAlign) {
/// function arguments in the caller parameter area. For X86, aggregates
/// that contain SSE vectors are placed at 16-byte boundaries while the rest
/// are at 4-byte boundaries.
-unsigned X86TargetLowering::getByValTypeAlignment(const Type *Ty) const {
+unsigned X86TargetLowering::getByValTypeAlignment(Type *Ty) const {
if (Subtarget->is64Bit()) {
// Max of 8 and alignment of type.
unsigned TyAlign = TD->getABITypeAlignment(Ty);
@@ -1203,9 +1253,12 @@ X86TargetLowering::getOptimalMemOpType(uint64_t Size,
((DstAlign == 0 || DstAlign >= 16) &&
(SrcAlign == 0 || SrcAlign >= 16))) &&
Subtarget->getStackAlignment() >= 16) {
- if (Subtarget->hasSSE2())
+ if (Subtarget->hasAVX() &&
+ Subtarget->getStackAlignment() >= 32)
+ return MVT::v8f32;
+ if (Subtarget->hasXMMInt())
return MVT::v4i32;
- if (Subtarget->hasSSE1())
+ if (Subtarget->hasXMM())
return MVT::v4f32;
} else if (!MemcpyStrSrc && Size >= 8 &&
!Subtarget->is64Bit() &&
@@ -1408,7 +1461,7 @@ X86TargetLowering::LowerReturn(SDValue Chain,
ValToCopy);
// If we don't have SSE2 available, convert to v4f32 so the generated
// register is legal.
- if (!Subtarget->hasSSE2())
+ if (!Subtarget->hasXMMInt())
ValToCopy = DAG.getNode(ISD::BITCAST, dl, MVT::v4f32,ValToCopy);
}
}
@@ -1700,6 +1753,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
// places.
assert(VA.getValNo() != LastVal &&
"Don't support value assigned to multiple locs yet");
+ (void)LastVal;
LastVal = VA.getValNo();
if (VA.isRegLoc()) {
@@ -1917,6 +1971,8 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
FuncInfo->setVarArgsFrameIndex(0xAAAAAAA);
}
+ FuncInfo->setArgumentStackSize(StackSize);
+
return Chain;
}
@@ -2744,8 +2800,6 @@ static bool isTargetShuffle(unsigned Opcode) {
case X86ISD::MOVSD:
case X86ISD::UNPCKLPS:
case X86ISD::UNPCKLPD:
- case X86ISD::VUNPCKLPS:
- case X86ISD::VUNPCKLPD:
case X86ISD::VUNPCKLPSY:
case X86ISD::VUNPCKLPDY:
case X86ISD::PUNPCKLWD:
@@ -2754,10 +2808,17 @@ static bool isTargetShuffle(unsigned Opcode) {
case X86ISD::PUNPCKLQDQ:
case X86ISD::UNPCKHPS:
case X86ISD::UNPCKHPD:
+ case X86ISD::VUNPCKHPSY:
+ case X86ISD::VUNPCKHPDY:
case X86ISD::PUNPCKHWD:
case X86ISD::PUNPCKHBW:
case X86ISD::PUNPCKHDQ:
case X86ISD::PUNPCKHQDQ:
+ case X86ISD::VPERMILPS:
+ case X86ISD::VPERMILPSY:
+ case X86ISD::VPERMILPD:
+ case X86ISD::VPERMILPDY:
+ case X86ISD::VPERM2F128:
return true;
}
return false;
@@ -2783,6 +2844,10 @@ static SDValue getTargetShuffleNode(unsigned Opc, DebugLoc dl, EVT VT,
case X86ISD::PSHUFD:
case X86ISD::PSHUFHW:
case X86ISD::PSHUFLW:
+ case X86ISD::VPERMILPS:
+ case X86ISD::VPERMILPSY:
+ case X86ISD::VPERMILPD:
+ case X86ISD::VPERMILPDY:
return DAG.getNode(Opc, dl, VT, V1, DAG.getConstant(TargetMask, MVT::i8));
}
@@ -2796,6 +2861,7 @@ static SDValue getTargetShuffleNode(unsigned Opc, DebugLoc dl, EVT VT,
case X86ISD::PALIGN:
case X86ISD::SHUFPD:
case X86ISD::SHUFPS:
+ case X86ISD::VPERM2F128:
return DAG.getNode(Opc, dl, VT, V1, V2,
DAG.getConstant(TargetMask, MVT::i8));
}
@@ -2815,8 +2881,6 @@ static SDValue getTargetShuffleNode(unsigned Opc, DebugLoc dl, EVT VT,
case X86ISD::MOVSD:
case X86ISD::UNPCKLPS:
case X86ISD::UNPCKLPD:
- case X86ISD::VUNPCKLPS:
- case X86ISD::VUNPCKLPD:
case X86ISD::VUNPCKLPSY:
case X86ISD::VUNPCKLPDY:
case X86ISD::PUNPCKLWD:
@@ -2825,6 +2889,8 @@ static SDValue getTargetShuffleNode(unsigned Opc, DebugLoc dl, EVT VT,
case X86ISD::PUNPCKLQDQ:
case X86ISD::UNPCKHPS:
case X86ISD::UNPCKHPD:
+ case X86ISD::VUNPCKHPSY:
+ case X86ISD::VUNPCKHPDY:
case X86ISD::PUNPCKHWD:
case X86ISD::PUNPCKHBW:
case X86ISD::PUNPCKHDQ:
@@ -3026,6 +3092,17 @@ static bool isUndefOrInRange(int Val, int Low, int Hi) {
return (Val < 0) || (Val >= Low && Val < Hi);
}
+/// isUndefOrInRange - Return true if every element in Mask, begining
+/// from position Pos and ending in Pos+Size, falls within the specified
+/// range (L, L+Pos]. or is undef.
+static bool isUndefOrInRange(const SmallVectorImpl<int> &Mask,
+ int Pos, int Size, int Low, int Hi) {
+ for (int i = Pos, e = Pos+Size; i != e; ++i)
+ if (!isUndefOrInRange(Mask[i], Low, Hi))
+ return false;
+ return true;
+}
+
/// isUndefOrEqual - Val is either less than zero (undef) or equal to the
/// specified value.
static bool isUndefOrEqual(int Val, int CmpVal) {
@@ -3034,6 +3111,17 @@ static bool isUndefOrEqual(int Val, int CmpVal) {
return false;
}
+/// isSequentialOrUndefInRange - Return true if every element in Mask, begining
+/// from position Pos and ending in Pos+Size, falls within the specified
+/// sequential range (L, L+Pos]. or is undef.
+static bool isSequentialOrUndefInRange(const SmallVectorImpl<int> &Mask,
+ int Pos, int Size, int Low) {
+ for (int i = Pos, e = Pos+Size; i != e; ++i, ++Low)
+ if (!isUndefOrEqual(Mask[i], Low))
+ return false;
+ return true;
+}
+
/// isPSHUFDMask - Return true if the node specifies a shuffle of elements that
/// is suitable for input to PSHUFD or PSHUFW. That is, it doesn't reference
/// the second operand.
@@ -3104,11 +3192,13 @@ bool X86::isPSHUFLWMask(ShuffleVectorSDNode *N) {
/// isPALIGNRMask - Return true if the node specifies a shuffle of elements that
/// is suitable for input to PALIGNR.
static bool isPALIGNRMask(const SmallVectorImpl<int> &Mask, EVT VT,
- bool hasSSSE3) {
+ bool hasSSSE3OrAVX) {
int i, e = VT.getVectorNumElements();
+ if (VT.getSizeInBits() != 128 && VT.getSizeInBits() != 64)
+ return false;
// Do not handle v2i64 / v2f64 shuffles with palignr.
- if (e < 4 || !hasSSSE3)
+ if (e < 4 || !hasSSSE3OrAVX)
return false;
for (i = 0; i != e; ++i)
@@ -3119,42 +3209,176 @@ static bool isPALIGNRMask(const SmallVectorImpl<int> &Mask, EVT VT,
if (i == e)
return false;
- // Determine if it's ok to perform a palignr with only the LHS, since we
- // don't have access to the actual shuffle elements to see if RHS is undef.
- bool Unary = Mask[i] < (int)e;
- bool NeedsUnary = false;
+ // Make sure we're shifting in the right direction.
+ if (Mask[i] <= i)
+ return false;
int s = Mask[i] - i;
// Check the rest of the elements to see if they are consecutive.
for (++i; i != e; ++i) {
int m = Mask[i];
- if (m < 0)
- continue;
+ if (m >= 0 && m != s+i)
+ return false;
+ }
+ return true;
+}
+
+/// isVSHUFPSYMask - Return true if the specified VECTOR_SHUFFLE operand
+/// specifies a shuffle of elements that is suitable for input to 256-bit
+/// VSHUFPSY.
+static bool isVSHUFPSYMask(const SmallVectorImpl<int> &Mask, EVT VT,
+ const X86Subtarget *Subtarget) {
+ int NumElems = VT.getVectorNumElements();
+
+ if (!Subtarget->hasAVX() || VT.getSizeInBits() != 256)
+ return false;
+
+ if (NumElems != 8)
+ return false;
- Unary = Unary && (m < (int)e);
- NeedsUnary = NeedsUnary || (m < s);
+ // VSHUFPSY divides the resulting vector into 4 chunks.
+ // The sources are also splitted into 4 chunks, and each destination
+ // chunk must come from a different source chunk.
+ //
+ // SRC1 => X7 X6 X5 X4 X3 X2 X1 X0
+ // SRC2 => Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y9
+ //
+ // DST => Y7..Y4, Y7..Y4, X7..X4, X7..X4,
+ // Y3..Y0, Y3..Y0, X3..X0, X3..X0
+ //
+ int QuarterSize = NumElems/4;
+ int HalfSize = QuarterSize*2;
+ for (int i = 0; i < QuarterSize; ++i)
+ if (!isUndefOrInRange(Mask[i], 0, HalfSize))
+ return false;
+ for (int i = QuarterSize; i < QuarterSize*2; ++i)
+ if (!isUndefOrInRange(Mask[i], NumElems, NumElems+HalfSize))
+ return false;
- if (NeedsUnary && !Unary)
+ // The mask of the second half must be the same as the first but with
+ // the appropriate offsets. This works in the same way as VPERMILPS
+ // works with masks.
+ for (int i = QuarterSize*2; i < QuarterSize*3; ++i) {
+ if (!isUndefOrInRange(Mask[i], HalfSize, NumElems))
+ return false;
+ int FstHalfIdx = i-HalfSize;
+ if (Mask[FstHalfIdx] < 0)
+ continue;
+ if (!isUndefOrEqual(Mask[i], Mask[FstHalfIdx]+HalfSize))
return false;
- if (Unary && m != ((s+i) & (e-1)))
+ }
+ for (int i = QuarterSize*3; i < NumElems; ++i) {
+ if (!isUndefOrInRange(Mask[i], NumElems+HalfSize, NumElems*2))
return false;
- if (!Unary && m != (s+i))
+ int FstHalfIdx = i-HalfSize;
+ if (Mask[FstHalfIdx] < 0)
+ continue;
+ if (!isUndefOrEqual(Mask[i], Mask[FstHalfIdx]+HalfSize))
return false;
+
}
+
return true;
}
-bool X86::isPALIGNRMask(ShuffleVectorSDNode *N) {
- SmallVector<int, 8> M;
- N->getMask(M);
- return ::isPALIGNRMask(M, N->getValueType(0), true);
+/// getShuffleVSHUFPSYImmediate - Return the appropriate immediate to shuffle
+/// the specified VECTOR_MASK mask with VSHUFPSY instruction.
+static unsigned getShuffleVSHUFPSYImmediate(SDNode *N) {
+ ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
+ EVT VT = SVOp->getValueType(0);
+ int NumElems = VT.getVectorNumElements();
+
+ assert(NumElems == 8 && VT.getSizeInBits() == 256 &&
+ "Only supports v8i32 and v8f32 types");
+
+ int HalfSize = NumElems/2;
+ unsigned Mask = 0;
+ for (int i = 0; i != NumElems ; ++i) {
+ if (SVOp->getMaskElt(i) < 0)
+ continue;
+ // The mask of the first half must be equal to the second one.
+ unsigned Shamt = (i%HalfSize)*2;
+ unsigned Elt = SVOp->getMaskElt(i) % HalfSize;
+ Mask |= Elt << Shamt;
+ }
+
+ return Mask;
+}
+
+/// isVSHUFPDYMask - Return true if the specified VECTOR_SHUFFLE operand
+/// specifies a shuffle of elements that is suitable for input to 256-bit
+/// VSHUFPDY. This shuffle doesn't have the same restriction as the PS
+/// version and the mask of the second half isn't binded with the first
+/// one.
+static bool isVSHUFPDYMask(const SmallVectorImpl<int> &Mask, EVT VT,
+ const X86Subtarget *Subtarget) {
+ int NumElems = VT.getVectorNumElements();
+
+ if (!Subtarget->hasAVX() || VT.getSizeInBits() != 256)
+ return false;
+
+ if (NumElems != 4)
+ return false;
+
+ // VSHUFPSY divides the resulting vector into 4 chunks.
+ // The sources are also splitted into 4 chunks, and each destination
+ // chunk must come from a different source chunk.
+ //
+ // SRC1 => X3 X2 X1 X0
+ // SRC2 => Y3 Y2 Y1 Y0
+ //
+ // DST => Y2..Y3, X2..X3, Y1..Y0, X1..X0
+ //
+ int QuarterSize = NumElems/4;
+ int HalfSize = QuarterSize*2;
+ for (int i = 0; i < QuarterSize; ++i)
+ if (!isUndefOrInRange(Mask[i], 0, HalfSize))
+ return false;
+ for (int i = QuarterSize; i < QuarterSize*2; ++i)
+ if (!isUndefOrInRange(Mask[i], NumElems, NumElems+HalfSize))
+ return false;
+ for (int i = QuarterSize*2; i < QuarterSize*3; ++i)
+ if (!isUndefOrInRange(Mask[i], HalfSize, NumElems))
+ return false;
+ for (int i = QuarterSize*3; i < NumElems; ++i)
+ if (!isUndefOrInRange(Mask[i], NumElems+HalfSize, NumElems*2))
+ return false;
+
+ return true;
+}
+
+/// getShuffleVSHUFPDYImmediate - Return the appropriate immediate to shuffle
+/// the specified VECTOR_MASK mask with VSHUFPDY instruction.
+static unsigned getShuffleVSHUFPDYImmediate(SDNode *N) {
+ ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
+ EVT VT = SVOp->getValueType(0);
+ int NumElems = VT.getVectorNumElements();
+
+ assert(NumElems == 4 && VT.getSizeInBits() == 256 &&
+ "Only supports v4i64 and v4f64 types");
+
+ int HalfSize = NumElems/2;
+ unsigned Mask = 0;
+ for (int i = 0; i != NumElems ; ++i) {
+ if (SVOp->getMaskElt(i) < 0)
+ continue;
+ int Elt = SVOp->getMaskElt(i) % HalfSize;
+ Mask |= Elt << i;
+ }
+
+ return Mask;
}
/// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand
-/// specifies a shuffle of elements that is suitable for input to SHUFP*.
+/// specifies a shuffle of elements that is suitable for input to 128-bit
+/// SHUFPS and SHUFPD.
static bool isSHUFPMask(const SmallVectorImpl<int> &Mask, EVT VT) {
int NumElems = VT.getVectorNumElements();
+
+ if (VT.getSizeInBits() != 128)
+ return false;
+
if (NumElems != 2 && NumElems != 4)
return false;
@@ -3204,7 +3428,13 @@ static bool isCommutedSHUFP(ShuffleVectorSDNode *N) {
/// isMOVHLPSMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVHLPS.
bool X86::isMOVHLPSMask(ShuffleVectorSDNode *N) {
- if (N->getValueType(0).getVectorNumElements() != 4)
+ EVT VT = N->getValueType(0);
+ unsigned NumElems = VT.getVectorNumElements();
+
+ if (VT.getSizeInBits() != 128)
+ return false;
+
+ if (NumElems != 4)
return false;
// Expect bit0 == 6, bit1 == 7, bit2 == 2, bit3 == 3
@@ -3218,15 +3448,19 @@ bool X86::isMOVHLPSMask(ShuffleVectorSDNode *N) {
/// of vector_shuffle v, v, <2, 3, 2, 3>, i.e. vector_shuffle v, undef,
/// <2, 3, 2, 3>
bool X86::isMOVHLPS_v_undef_Mask(ShuffleVectorSDNode *N) {
- unsigned NumElems = N->getValueType(0).getVectorNumElements();
+ EVT VT = N->getValueType(0);
+ unsigned NumElems = VT.getVectorNumElements();
+
+ if (VT.getSizeInBits() != 128)
+ return false;
if (NumElems != 4)
return false;
return isUndefOrEqual(N->getMaskElt(0), 2) &&
- isUndefOrEqual(N->getMaskElt(1), 3) &&
- isUndefOrEqual(N->getMaskElt(2), 2) &&
- isUndefOrEqual(N->getMaskElt(3), 3);
+ isUndefOrEqual(N->getMaskElt(1), 3) &&
+ isUndefOrEqual(N->getMaskElt(2), 2) &&
+ isUndefOrEqual(N->getMaskElt(3), 3);
}
/// isMOVLPMask - Return true if the specified VECTOR_SHUFFLE operand
@@ -3273,20 +3507,22 @@ bool X86::isMOVLHPSMask(ShuffleVectorSDNode *N) {
static bool isUNPCKLMask(const SmallVectorImpl<int> &Mask, EVT VT,
bool V2IsSplat = false) {
int NumElts = VT.getVectorNumElements();
- if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
+
+ assert((VT.is128BitVector() || VT.is256BitVector()) &&
+ "Unsupported vector type for unpckh");
+
+ if (VT.getSizeInBits() == 256 && NumElts != 4 && NumElts != 8)
return false;
- // Handle vector lengths > 128 bits. Define a "section" as a set of
- // 128 bits. AVX defines UNPCK* to operate independently on 128-bit
- // sections.
- unsigned NumSections = VT.getSizeInBits() / 128;
- if (NumSections == 0 ) NumSections = 1; // Handle MMX
- unsigned NumSectionElts = NumElts / NumSections;
+ // Handle 128 and 256-bit vector lengths. AVX defines UNPCK* to operate
+ // independently on 128-bit lanes.
+ unsigned NumLanes = VT.getSizeInBits()/128;
+ unsigned NumLaneElts = NumElts/NumLanes;
unsigned Start = 0;
- unsigned End = NumSectionElts;
- for (unsigned s = 0; s < NumSections; ++s) {
- for (unsigned i = Start, j = s * NumSectionElts;
+ unsigned End = NumLaneElts;
+ for (unsigned s = 0; s < NumLanes; ++s) {
+ for (unsigned i = Start, j = s * NumLaneElts;
i != End;
i += 2, ++j) {
int BitI = Mask[i];
@@ -3302,8 +3538,8 @@ static bool isUNPCKLMask(const SmallVectorImpl<int> &Mask, EVT VT,
}
}
// Process the next 128 bits.
- Start += NumSectionElts;
- End += NumSectionElts;
+ Start += NumLaneElts;
+ End += NumLaneElts;
}
return true;
@@ -3320,21 +3556,38 @@ bool X86::isUNPCKLMask(ShuffleVectorSDNode *N, bool V2IsSplat) {
static bool isUNPCKHMask(const SmallVectorImpl<int> &Mask, EVT VT,
bool V2IsSplat = false) {
int NumElts = VT.getVectorNumElements();
- if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
+
+ assert((VT.is128BitVector() || VT.is256BitVector()) &&
+ "Unsupported vector type for unpckh");
+
+ if (VT.getSizeInBits() == 256 && NumElts != 4 && NumElts != 8)
return false;
- for (int i = 0, j = 0; i != NumElts; i += 2, ++j) {
- int BitI = Mask[i];
- int BitI1 = Mask[i+1];
- if (!isUndefOrEqual(BitI, j + NumElts/2))
- return false;
- if (V2IsSplat) {
- if (isUndefOrEqual(BitI1, NumElts))
- return false;
- } else {
- if (!isUndefOrEqual(BitI1, j + NumElts/2 + NumElts))
+ // Handle 128 and 256-bit vector lengths. AVX defines UNPCK* to operate
+ // independently on 128-bit lanes.
+ unsigned NumLanes = VT.getSizeInBits()/128;
+ unsigned NumLaneElts = NumElts/NumLanes;
+
+ unsigned Start = 0;
+ unsigned End = NumLaneElts;
+ for (unsigned l = 0; l != NumLanes; ++l) {
+ for (unsigned i = Start, j = (l*NumLaneElts)+NumLaneElts/2;
+ i != End; i += 2, ++j) {
+ int BitI = Mask[i];
+ int BitI1 = Mask[i+1];
+ if (!isUndefOrEqual(BitI, j))
return false;
+ if (V2IsSplat) {
+ if (isUndefOrEqual(BitI1, NumElts))
+ return false;
+ } else {
+ if (!isUndefOrEqual(BitI1, j+NumElts))
+ return false;
+ }
}
+ // Process the next 128 bits.
+ Start += NumLaneElts;
+ End += NumLaneElts;
}
return true;
}
@@ -3353,16 +3606,21 @@ static bool isUNPCKL_v_undef_Mask(const SmallVectorImpl<int> &Mask, EVT VT) {
if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16)
return false;
- // Handle vector lengths > 128 bits. Define a "section" as a set of
- // 128 bits. AVX defines UNPCK* to operate independently on 128-bit
- // sections.
- unsigned NumSections = VT.getSizeInBits() / 128;
- if (NumSections == 0 ) NumSections = 1; // Handle MMX
- unsigned NumSectionElts = NumElems / NumSections;
+ // For 256-bit i64/f64, use MOVDDUPY instead, so reject the matching pattern
+ // FIXME: Need a better way to get rid of this, there's no latency difference
+ // between UNPCKLPD and MOVDDUP, the later should always be checked first and
+ // the former later. We should also remove the "_undef" special mask.
+ if (NumElems == 4 && VT.getSizeInBits() == 256)
+ return false;
+
+ // Handle 128 and 256-bit vector lengths. AVX defines UNPCK* to operate
+ // independently on 128-bit lanes.
+ unsigned NumLanes = VT.getSizeInBits() / 128;
+ unsigned NumLaneElts = NumElems / NumLanes;
- for (unsigned s = 0; s < NumSections; ++s) {
- for (unsigned i = s * NumSectionElts, j = s * NumSectionElts;
- i != NumSectionElts * (s + 1);
+ for (unsigned s = 0; s < NumLanes; ++s) {
+ for (unsigned i = s * NumLaneElts, j = s * NumLaneElts;
+ i != NumLaneElts * (s + 1);
i += 2, ++j) {
int BitI = Mask[i];
int BitI1 = Mask[i+1];
@@ -3433,6 +3691,189 @@ bool X86::isMOVLMask(ShuffleVectorSDNode *N) {
return ::isMOVLMask(M, N->getValueType(0));
}
+/// isVPERM2F128Mask - Match 256-bit shuffles where the elements are considered
+/// as permutations between 128-bit chunks or halves. As an example: this
+/// shuffle bellow:
+/// vector_shuffle <4, 5, 6, 7, 12, 13, 14, 15>
+/// The first half comes from the second half of V1 and the second half from the
+/// the second half of V2.
+static bool isVPERM2F128Mask(const SmallVectorImpl<int> &Mask, EVT VT,
+ const X86Subtarget *Subtarget) {
+ if (!Subtarget->hasAVX() || VT.getSizeInBits() != 256)
+ return false;
+
+ // The shuffle result is divided into half A and half B. In total the two
+ // sources have 4 halves, namely: C, D, E, F. The final values of A and
+ // B must come from C, D, E or F.
+ int HalfSize = VT.getVectorNumElements()/2;
+ bool MatchA = false, MatchB = false;
+
+ // Check if A comes from one of C, D, E, F.
+ for (int Half = 0; Half < 4; ++Half) {
+ if (isSequentialOrUndefInRange(Mask, 0, HalfSize, Half*HalfSize)) {
+ MatchA = true;
+ break;
+ }
+ }
+
+ // Check if B comes from one of C, D, E, F.
+ for (int Half = 0; Half < 4; ++Half) {
+ if (isSequentialOrUndefInRange(Mask, HalfSize, HalfSize, Half*HalfSize)) {
+ MatchB = true;
+ break;
+ }
+ }
+
+ return MatchA && MatchB;
+}
+
+/// getShuffleVPERM2F128Immediate - Return the appropriate immediate to shuffle
+/// the specified VECTOR_MASK mask with VPERM2F128 instructions.
+static unsigned getShuffleVPERM2F128Immediate(SDNode *N) {
+ ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
+ EVT VT = SVOp->getValueType(0);
+
+ int HalfSize = VT.getVectorNumElements()/2;
+
+ int FstHalf = 0, SndHalf = 0;
+ for (int i = 0; i < HalfSize; ++i) {
+ if (SVOp->getMaskElt(i) > 0) {
+ FstHalf = SVOp->getMaskElt(i)/HalfSize;
+ break;
+ }
+ }
+ for (int i = HalfSize; i < HalfSize*2; ++i) {
+ if (SVOp->getMaskElt(i) > 0) {
+ SndHalf = SVOp->getMaskElt(i)/HalfSize;
+ break;
+ }
+ }
+
+ return (FstHalf | (SndHalf << 4));
+}
+
+/// isVPERMILPDMask - Return true if the specified VECTOR_SHUFFLE operand
+/// specifies a shuffle of elements that is suitable for input to VPERMILPD*.
+/// Note that VPERMIL mask matching is different depending whether theunderlying
+/// type is 32 or 64. In the VPERMILPS the high half of the mask should point
+/// to the same elements of the low, but to the higher half of the source.
+/// In VPERMILPD the two lanes could be shuffled independently of each other
+/// with the same restriction that lanes can't be crossed.
+static bool isVPERMILPDMask(const SmallVectorImpl<int> &Mask, EVT VT,
+ const X86Subtarget *Subtarget) {
+ int NumElts = VT.getVectorNumElements();
+ int NumLanes = VT.getSizeInBits()/128;
+
+ if (!Subtarget->hasAVX())
+ return false;
+
+ // Only match 256-bit with 64-bit types
+ if (VT.getSizeInBits() != 256 || NumElts != 4)
+ return false;
+
+ // The mask on the high lane is independent of the low. Both can match
+ // any element in inside its own lane, but can't cross.
+ int LaneSize = NumElts/NumLanes;
+ for (int l = 0; l < NumLanes; ++l)
+ for (int i = l*LaneSize; i < LaneSize*(l+1); ++i) {
+ int LaneStart = l*LaneSize;
+ if (!isUndefOrInRange(Mask[i], LaneStart, LaneStart+LaneSize))
+ return false;
+ }
+
+ return true;
+}
+
+/// isVPERMILPSMask - Return true if the specified VECTOR_SHUFFLE operand
+/// specifies a shuffle of elements that is suitable for input to VPERMILPS*.
+/// Note that VPERMIL mask matching is different depending whether theunderlying
+/// type is 32 or 64. In the VPERMILPS the high half of the mask should point
+/// to the same elements of the low, but to the higher half of the source.
+/// In VPERMILPD the two lanes could be shuffled independently of each other
+/// with the same restriction that lanes can't be crossed.
+static bool isVPERMILPSMask(const SmallVectorImpl<int> &Mask, EVT VT,
+ const X86Subtarget *Subtarget) {
+ unsigned NumElts = VT.getVectorNumElements();
+ unsigned NumLanes = VT.getSizeInBits()/128;
+
+ if (!Subtarget->hasAVX())
+ return false;
+
+ // Only match 256-bit with 32-bit types
+ if (VT.getSizeInBits() != 256 || NumElts != 8)
+ return false;
+
+ // The mask on the high lane should be the same as the low. Actually,
+ // they can differ if any of the corresponding index in a lane is undef
+ // and the other stays in range.
+ int LaneSize = NumElts/NumLanes;
+ for (int i = 0; i < LaneSize; ++i) {
+ int HighElt = i+LaneSize;
+ bool HighValid = isUndefOrInRange(Mask[HighElt], LaneSize, NumElts);
+ bool LowValid = isUndefOrInRange(Mask[i], 0, LaneSize);
+
+ if (!HighValid || !LowValid)
+ return false;
+ if (Mask[i] < 0 || Mask[HighElt] < 0)
+ continue;
+ if (Mask[HighElt]-Mask[i] != LaneSize)
+ return false;
+ }
+
+ return true;
+}
+
+/// getShuffleVPERMILPSImmediate - Return the appropriate immediate to shuffle
+/// the specified VECTOR_MASK mask with VPERMILPS* instructions.
+static unsigned getShuffleVPERMILPSImmediate(SDNode *N) {
+ ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
+ EVT VT = SVOp->getValueType(0);
+
+ int NumElts = VT.getVectorNumElements();
+ int NumLanes = VT.getSizeInBits()/128;
+ int LaneSize = NumElts/NumLanes;
+
+ // Although the mask is equal for both lanes do it twice to get the cases
+ // where a mask will match because the same mask element is undef on the
+ // first half but valid on the second. This would get pathological cases
+ // such as: shuffle <u, 0, 1, 2, 4, 4, 5, 6>, which is completely valid.
+ unsigned Mask = 0;
+ for (int l = 0; l < NumLanes; ++l) {
+ for (int i = 0; i < LaneSize; ++i) {
+ int MaskElt = SVOp->getMaskElt(i+(l*LaneSize));
+ if (MaskElt < 0)
+ continue;
+ if (MaskElt >= LaneSize)
+ MaskElt -= LaneSize;
+ Mask |= MaskElt << (i*2);
+ }
+ }
+
+ return Mask;
+}
+
+/// getShuffleVPERMILPDImmediate - Return the appropriate immediate to shuffle
+/// the specified VECTOR_MASK mask with VPERMILPD* instructions.
+static unsigned getShuffleVPERMILPDImmediate(SDNode *N) {
+ ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
+ EVT VT = SVOp->getValueType(0);
+
+ int NumElts = VT.getVectorNumElements();
+ int NumLanes = VT.getSizeInBits()/128;
+
+ unsigned Mask = 0;
+ int LaneSize = NumElts/NumLanes;
+ for (int l = 0; l < NumLanes; ++l)
+ for (int i = l*LaneSize; i < LaneSize*(l+1); ++i) {
+ int MaskElt = SVOp->getMaskElt(i);
+ if (MaskElt < 0)
+ continue;
+ Mask |= (MaskElt-l*LaneSize) << i;
+ }
+
+ return Mask;
+}
+
/// isCommutedMOVL - Returns true if the shuffle mask is except the reverse
/// of what x86 movss want. X86 movs requires the lowest element to be lowest
/// element of vector 2 and the other elements to come from vector 1 in order.
@@ -3463,58 +3904,92 @@ static bool isCommutedMOVL(ShuffleVectorSDNode *N, bool V2IsSplat = false,
/// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVSHDUP.
-bool X86::isMOVSHDUPMask(ShuffleVectorSDNode *N) {
- if (N->getValueType(0).getVectorNumElements() != 4)
+/// Masks to match: <1, 1, 3, 3> or <1, 1, 3, 3, 5, 5, 7, 7>
+bool X86::isMOVSHDUPMask(ShuffleVectorSDNode *N,
+ const X86Subtarget *Subtarget) {
+ if (!Subtarget->hasSSE3() && !Subtarget->hasAVX())
return false;
- // Expect 1, 1, 3, 3
- for (unsigned i = 0; i < 2; ++i) {
- int Elt = N->getMaskElt(i);
- if (Elt >= 0 && Elt != 1)
- return false;
- }
+ // The second vector must be undef
+ if (N->getOperand(1).getOpcode() != ISD::UNDEF)
+ return false;
- bool HasHi = false;
- for (unsigned i = 2; i < 4; ++i) {
- int Elt = N->getMaskElt(i);
- if (Elt >= 0 && Elt != 3)
+ EVT VT = N->getValueType(0);
+ unsigned NumElems = VT.getVectorNumElements();
+
+ if ((VT.getSizeInBits() == 128 && NumElems != 4) ||
+ (VT.getSizeInBits() == 256 && NumElems != 8))
+ return false;
+
+ // "i+1" is the value the indexed mask element must have
+ for (unsigned i = 0; i < NumElems; i += 2)
+ if (!isUndefOrEqual(N->getMaskElt(i), i+1) ||
+ !isUndefOrEqual(N->getMaskElt(i+1), i+1))
return false;
- if (Elt == 3)
- HasHi = true;
- }
- // Don't use movshdup if it can be done with a shufps.
- // FIXME: verify that matching u, u, 3, 3 is what we want.
- return HasHi;
+
+ return true;
}
/// isMOVSLDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVSLDUP.
-bool X86::isMOVSLDUPMask(ShuffleVectorSDNode *N) {
- if (N->getValueType(0).getVectorNumElements() != 4)
+/// Masks to match: <0, 0, 2, 2> or <0, 0, 2, 2, 4, 4, 6, 6>
+bool X86::isMOVSLDUPMask(ShuffleVectorSDNode *N,
+ const X86Subtarget *Subtarget) {
+ if (!Subtarget->hasSSE3() && !Subtarget->hasAVX())
+ return false;
+
+ // The second vector must be undef
+ if (N->getOperand(1).getOpcode() != ISD::UNDEF)
+ return false;
+
+ EVT VT = N->getValueType(0);
+ unsigned NumElems = VT.getVectorNumElements();
+
+ if ((VT.getSizeInBits() == 128 && NumElems != 4) ||
+ (VT.getSizeInBits() == 256 && NumElems != 8))
return false;
- // Expect 0, 0, 2, 2
- for (unsigned i = 0; i < 2; ++i)
- if (N->getMaskElt(i) > 0)
+ // "i" is the value the indexed mask element must have
+ for (unsigned i = 0; i < NumElems; i += 2)
+ if (!isUndefOrEqual(N->getMaskElt(i), i) ||
+ !isUndefOrEqual(N->getMaskElt(i+1), i))
return false;
- bool HasHi = false;
- for (unsigned i = 2; i < 4; ++i) {
- int Elt = N->getMaskElt(i);
- if (Elt >= 0 && Elt != 2)
+ return true;
+}
+
+/// isMOVDDUPYMask - Return true if the specified VECTOR_SHUFFLE operand
+/// specifies a shuffle of elements that is suitable for input to 256-bit
+/// version of MOVDDUP.
+static bool isMOVDDUPYMask(ShuffleVectorSDNode *N,
+ const X86Subtarget *Subtarget) {
+ EVT VT = N->getValueType(0);
+ int NumElts = VT.getVectorNumElements();
+ bool V2IsUndef = N->getOperand(1).getOpcode() == ISD::UNDEF;
+
+ if (!Subtarget->hasAVX() || VT.getSizeInBits() != 256 ||
+ !V2IsUndef || NumElts != 4)
+ return false;
+
+ for (int i = 0; i != NumElts/2; ++i)
+ if (!isUndefOrEqual(N->getMaskElt(i), 0))
return false;
- if (Elt == 2)
- HasHi = true;
- }
- // Don't use movsldup if it can be done with a shufps.
- return HasHi;
+ for (int i = NumElts/2; i != NumElts; ++i)
+ if (!isUndefOrEqual(N->getMaskElt(i), NumElts/2))
+ return false;
+ return true;
}
/// isMOVDDUPMask - Return true if the specified VECTOR_SHUFFLE operand
-/// specifies a shuffle of elements that is suitable for input to MOVDDUP.
+/// specifies a shuffle of elements that is suitable for input to 128-bit
+/// version of MOVDDUP.
bool X86::isMOVDDUPMask(ShuffleVectorSDNode *N) {
- int e = N->getValueType(0).getVectorNumElements() / 2;
+ EVT VT = N->getValueType(0);
+
+ if (VT.getSizeInBits() != 128)
+ return false;
+ int e = VT.getVectorNumElements() / 2;
for (int i = 0; i < e; ++i)
if (!isUndefOrEqual(N->getMaskElt(i), i))
return false;
@@ -3627,6 +4102,7 @@ unsigned X86::getShufflePALIGNRImmediate(SDNode *N) {
if (Val >= 0)
break;
}
+ assert(Val - i > 0 && "PALIGNR imm should be positive");
return (Val - i) * EltSize;
}
@@ -3644,7 +4120,6 @@ unsigned X86::getExtractVEXTRACTF128Immediate(SDNode *N) {
EVT ElVT = VecVT.getVectorElementType();
unsigned NumElemsPerChunk = 128 / ElVT.getSizeInBits();
-
return Index / NumElemsPerChunk;
}
@@ -3662,7 +4137,6 @@ unsigned X86::getInsertVINSERTF128Immediate(SDNode *N) {
EVT ElVT = VecVT.getVectorElementType();
unsigned NumElemsPerChunk = 128 / ElVT.getSizeInBits();
-
return Index / NumElemsPerChunk;
}
@@ -3716,7 +4190,10 @@ static void CommuteVectorShuffleMask(SmallVectorImpl<int> &Mask, EVT VT) {
/// V1 (and in order), and the upper half elements should come from the upper
/// half of V2 (and in order).
static bool ShouldXformToMOVHLPS(ShuffleVectorSDNode *Op) {
- if (Op->getValueType(0).getVectorNumElements() != 4)
+ EVT VT = Op->getValueType(0);
+ if (VT.getSizeInBits() != 128)
+ return false;
+ if (VT.getVectorNumElements() != 4)
return false;
for (unsigned i = 0, e = 2; i != e; ++i)
if (!isUndefOrEqual(Op->getMaskElt(i), i+2))
@@ -3748,6 +4225,10 @@ static bool isScalarLoadToVector(SDNode *N, LoadSDNode **LD = NULL) {
/// MOVLP, it must be either a vector load or a scalar load to vector.
static bool ShouldXformToMOVLP(SDNode *V1, SDNode *V2,
ShuffleVectorSDNode *Op) {
+ EVT VT = Op->getValueType(0);
+ if (VT.getSizeInBits() != 128)
+ return false;
+
if (!ISD::isNON_EXTLoad(V1) && !isScalarLoadToVector(V1))
return false;
// Is V2 is a vector load, don't do this transformation. We will try to use
@@ -3755,7 +4236,7 @@ static bool ShouldXformToMOVLP(SDNode *V1, SDNode *V2,
if (ISD::isNON_EXTLoad(V2))
return false;
- unsigned NumElems = Op->getValueType(0).getVectorNumElements();
+ unsigned NumElems = VT.getVectorNumElements();
if (NumElems != 2 && NumElems != 4)
return false;
@@ -3811,7 +4292,7 @@ static bool isZeroShuffle(ShuffleVectorSDNode *N) {
/// getZeroVector - Returns a vector of specified type with all zero elements.
///
-static SDValue getZeroVector(EVT VT, bool HasSSE2, SelectionDAG &DAG,
+static SDValue getZeroVector(EVT VT, bool HasXMMInt, SelectionDAG &DAG,
DebugLoc dl) {
assert(VT.isVector() && "Expected a vector type");
@@ -3819,7 +4300,7 @@ static SDValue getZeroVector(EVT VT, bool HasSSE2, SelectionDAG &DAG,
// to their dest type. This ensures they get CSE'd.
SDValue Vec;
if (VT.getSizeInBits() == 128) { // SSE
- if (HasSSE2) { // SSE2
+ if (HasXMMInt) { // SSE2
SDValue Cst = DAG.getTargetConstant(0, MVT::i32);
Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Cst, Cst, Cst, Cst);
} else { // SSE1
@@ -3838,21 +4319,25 @@ static SDValue getZeroVector(EVT VT, bool HasSSE2, SelectionDAG &DAG,
}
/// getOnesVector - Returns a vector of specified type with all bits set.
-/// Always build ones vectors as <4 x i32> or <8 x i32> bitcasted to
-/// their original type, ensuring they get CSE'd.
+/// Always build ones vectors as <4 x i32>. For 256-bit types, use two
+/// <4 x i32> inserted in a <8 x i32> appropriately. Then bitcast to their
+/// original type, ensuring they get CSE'd.
static SDValue getOnesVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) {
assert(VT.isVector() && "Expected a vector type");
assert((VT.is128BitVector() || VT.is256BitVector())
&& "Expected a 128-bit or 256-bit vector type");
SDValue Cst = DAG.getTargetConstant(~0U, MVT::i32);
+ SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
+ Cst, Cst, Cst, Cst);
- SDValue Vec;
if (VT.is256BitVector()) {
- SDValue Ops[] = { Cst, Cst, Cst, Cst, Cst, Cst, Cst, Cst };
- Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v8i32, Ops, 8);
- } else
- Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Cst, Cst, Cst, Cst);
+ SDValue InsV = Insert128BitVector(DAG.getNode(ISD::UNDEF, dl, MVT::v8i32),
+ Vec, DAG.getConstant(0, MVT::i32), DAG, dl);
+ Vec = Insert128BitVector(InsV, Vec,
+ DAG.getConstant(4 /* NumElems/2 */, MVT::i32), DAG, dl);
+ }
+
return DAG.getNode(ISD::BITCAST, dl, VT, Vec);
}
@@ -3902,7 +4387,7 @@ static SDValue getUnpackl(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1,
return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]);
}
-/// getUnpackhMask - Returns a vector_shuffle node for an unpackh operation.
+/// getUnpackh - Returns a vector_shuffle node for an unpackh operation.
static SDValue getUnpackh(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1,
SDValue V2) {
unsigned NumElems = VT.getVectorNumElements();
@@ -3915,31 +4400,95 @@ static SDValue getUnpackh(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1,
return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]);
}
-/// PromoteSplat - Promote a splat of v4i32, v8i16 or v16i8 to v4f32.
-static SDValue PromoteSplat(ShuffleVectorSDNode *SV, SelectionDAG &DAG) {
- EVT PVT = MVT::v4f32;
- EVT VT = SV->getValueType(0);
- DebugLoc dl = SV->getDebugLoc();
- SDValue V1 = SV->getOperand(0);
+// PromoteSplati8i16 - All i16 and i8 vector types can't be used directly by
+// a generic shuffle instruction because the target has no such instructions.
+// Generate shuffles which repeat i16 and i8 several times until they can be
+// represented by v4f32 and then be manipulated by target suported shuffles.
+static SDValue PromoteSplati8i16(SDValue V, SelectionDAG &DAG, int &EltNo) {
+ EVT VT = V.getValueType();
int NumElems = VT.getVectorNumElements();
- int EltNo = SV->getSplatIndex();
+ DebugLoc dl = V.getDebugLoc();
- // unpack elements to the correct location
while (NumElems > 4) {
if (EltNo < NumElems/2) {
- V1 = getUnpackl(DAG, dl, VT, V1, V1);
+ V = getUnpackl(DAG, dl, VT, V, V);
} else {
- V1 = getUnpackh(DAG, dl, VT, V1, V1);
+ V = getUnpackh(DAG, dl, VT, V, V);
EltNo -= NumElems/2;
}
NumElems >>= 1;
}
+ return V;
+}
+
+/// getLegalSplat - Generate a legal splat with supported x86 shuffles
+static SDValue getLegalSplat(SelectionDAG &DAG, SDValue V, int EltNo) {
+ EVT VT = V.getValueType();
+ DebugLoc dl = V.getDebugLoc();
+ assert((VT.getSizeInBits() == 128 || VT.getSizeInBits() == 256)
+ && "Vector size not supported");
+
+ if (VT.getSizeInBits() == 128) {
+ V = DAG.getNode(ISD::BITCAST, dl, MVT::v4f32, V);
+ int SplatMask[4] = { EltNo, EltNo, EltNo, EltNo };
+ V = DAG.getVectorShuffle(MVT::v4f32, dl, V, DAG.getUNDEF(MVT::v4f32),
+ &SplatMask[0]);
+ } else {
+ // To use VPERMILPS to splat scalars, the second half of indicies must
+ // refer to the higher part, which is a duplication of the lower one,
+ // because VPERMILPS can only handle in-lane permutations.
+ int SplatMask[8] = { EltNo, EltNo, EltNo, EltNo,
+ EltNo+4, EltNo+4, EltNo+4, EltNo+4 };
+
+ V = DAG.getNode(ISD::BITCAST, dl, MVT::v8f32, V);
+ V = DAG.getVectorShuffle(MVT::v8f32, dl, V, DAG.getUNDEF(MVT::v8f32),
+ &SplatMask[0]);
+ }
+
+ return DAG.getNode(ISD::BITCAST, dl, VT, V);
+}
+
+/// PromoteSplat - Splat is promoted to target supported vector shuffles.
+static SDValue PromoteSplat(ShuffleVectorSDNode *SV, SelectionDAG &DAG) {
+ EVT SrcVT = SV->getValueType(0);
+ SDValue V1 = SV->getOperand(0);
+ DebugLoc dl = SV->getDebugLoc();
+
+ int EltNo = SV->getSplatIndex();
+ int NumElems = SrcVT.getVectorNumElements();
+ unsigned Size = SrcVT.getSizeInBits();
+
+ assert(((Size == 128 && NumElems > 4) || Size == 256) &&
+ "Unknown how to promote splat for type");
+
+ // Extract the 128-bit part containing the splat element and update
+ // the splat element index when it refers to the higher register.
+ if (Size == 256) {
+ unsigned Idx = (EltNo > NumElems/2) ? NumElems/2 : 0;
+ V1 = Extract128BitVector(V1, DAG.getConstant(Idx, MVT::i32), DAG, dl);
+ if (Idx > 0)
+ EltNo -= NumElems/2;
+ }
+
+ // All i16 and i8 vector types can't be used directly by a generic shuffle
+ // instruction because the target has no such instruction. Generate shuffles
+ // which repeat i16 and i8 several times until they fit in i32, and then can
+ // be manipulated by target suported shuffles.
+ EVT EltVT = SrcVT.getVectorElementType();
+ if (EltVT == MVT::i8 || EltVT == MVT::i16)
+ V1 = PromoteSplati8i16(V1, DAG, EltNo);
+
+ // Recreate the 256-bit vector and place the same 128-bit vector
+ // into the low and high part. This is necessary because we want
+ // to use VPERM* to shuffle the vectors
+ if (Size == 256) {
+ SDValue InsV = Insert128BitVector(DAG.getUNDEF(SrcVT), V1,
+ DAG.getConstant(0, MVT::i32), DAG, dl);
+ V1 = Insert128BitVector(InsV, V1,
+ DAG.getConstant(NumElems/2, MVT::i32), DAG, dl);
+ }
- // Perform the splat.
- int SplatMask[4] = { EltNo, EltNo, EltNo, EltNo };
- V1 = DAG.getNode(ISD::BITCAST, dl, PVT, V1);
- V1 = DAG.getVectorShuffle(PVT, dl, V1, DAG.getUNDEF(PVT), &SplatMask[0]);
- return DAG.getNode(ISD::BITCAST, dl, VT, V1);
+ return getLegalSplat(DAG, V1, EltNo);
}
/// getShuffleVectorZeroOrUndef - Return a vector_shuffle of the specified
@@ -3947,11 +4496,11 @@ static SDValue PromoteSplat(ShuffleVectorSDNode *SV, SelectionDAG &DAG) {
/// element of V2 is swizzled into the zero/undef vector, landing at element
/// Idx. This produces a shuffle mask like 4,1,2,3 (idx=0) or 0,1,2,4 (idx=3).
static SDValue getShuffleVectorZeroOrUndef(SDValue V2, unsigned Idx,
- bool isZero, bool HasSSE2,
- SelectionDAG &DAG) {
+ bool isZero, bool HasXMMInt,
+ SelectionDAG &DAG) {
EVT VT = V2.getValueType();
SDValue V1 = isZero
- ? getZeroVector(VT, HasSSE2, DAG, V2.getDebugLoc()) : DAG.getUNDEF(VT);
+ ? getZeroVector(VT, HasXMMInt, DAG, V2.getDebugLoc()) : DAG.getUNDEF(VT);
unsigned NumElems = VT.getVectorNumElements();
SmallVector<int, 16> MaskVec;
for (unsigned i = 0; i != NumElems; ++i)
@@ -4005,6 +4554,8 @@ static SDValue getShuffleScalarElt(SDNode *N, int Index, SelectionDAG &DAG,
break;
case X86ISD::UNPCKHPS:
case X86ISD::UNPCKHPD:
+ case X86ISD::VUNPCKHPSY:
+ case X86ISD::VUNPCKHPDY:
DecodeUNPCKHPMask(NumElems, ShuffleMask);
break;
case X86ISD::PUNPCKLBW:
@@ -4015,8 +4566,6 @@ static SDValue getShuffleScalarElt(SDNode *N, int Index, SelectionDAG &DAG,
break;
case X86ISD::UNPCKLPS:
case X86ISD::UNPCKLPD:
- case X86ISD::VUNPCKLPS:
- case X86ISD::VUNPCKLPD:
case X86ISD::VUNPCKLPSY:
case X86ISD::VUNPCKLPDY:
DecodeUNPCKLPMask(VT, ShuffleMask);
@@ -4052,8 +4601,41 @@ static SDValue getShuffleScalarElt(SDNode *N, int Index, SelectionDAG &DAG,
return getShuffleScalarElt(V.getOperand(OpNum).getNode(), Index, DAG,
Depth+1);
}
+ case X86ISD::VPERMILPS:
+ ImmN = N->getOperand(N->getNumOperands()-1);
+ DecodeVPERMILPSMask(4, cast<ConstantSDNode>(ImmN)->getZExtValue(),
+ ShuffleMask);
+ break;
+ case X86ISD::VPERMILPSY:
+ ImmN = N->getOperand(N->getNumOperands()-1);
+ DecodeVPERMILPSMask(8, cast<ConstantSDNode>(ImmN)->getZExtValue(),
+ ShuffleMask);
+ break;
+ case X86ISD::VPERMILPD:
+ ImmN = N->getOperand(N->getNumOperands()-1);
+ DecodeVPERMILPDMask(2, cast<ConstantSDNode>(ImmN)->getZExtValue(),
+ ShuffleMask);
+ break;
+ case X86ISD::VPERMILPDY:
+ ImmN = N->getOperand(N->getNumOperands()-1);
+ DecodeVPERMILPDMask(4, cast<ConstantSDNode>(ImmN)->getZExtValue(),
+ ShuffleMask);
+ break;
+ case X86ISD::VPERM2F128:
+ ImmN = N->getOperand(N->getNumOperands()-1);
+ DecodeVPERM2F128Mask(VT, cast<ConstantSDNode>(ImmN)->getZExtValue(),
+ ShuffleMask);
+ break;
+ case X86ISD::MOVDDUP:
+ case X86ISD::MOVLHPD:
+ case X86ISD::MOVLPD:
+ case X86ISD::MOVLPS:
+ case X86ISD::MOVSHDUP:
+ case X86ISD::MOVSLDUP:
+ case X86ISD::PALIGN:
+ return SDValue(); // Not yet implemented.
default:
- assert("not implemented for target shuffle node");
+ assert(0 && "unknown target shuffle node");
return SDValue();
}
@@ -4205,6 +4787,11 @@ static bool isVectorShiftLeft(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG,
/// logical left or right shift of a vector.
static bool isVectorShift(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG,
bool &isLeft, SDValue &ShVal, unsigned &ShAmt) {
+ // Although the logic below support any bitwidth size, there are no
+ // shift instructions which handle more than 128-bit vectors.
+ if (SVOp->getValueType(0).getSizeInBits() > 128)
+ return false;
+
if (isVectorShiftLeft(SVOp, DAG, isLeft, ShVal, ShAmt) ||
isVectorShiftRight(SVOp, DAG, isLeft, ShVal, ShAmt))
return true;
@@ -4295,6 +4882,7 @@ static SDValue LowerBuildVectorv8i16(SDValue Op, unsigned NonZeros,
static SDValue getVShift(bool isLeft, EVT VT, SDValue SrcOp,
unsigned NumBits, SelectionDAG &DAG,
const TargetLowering &TLI, DebugLoc dl) {
+ assert(VT.getSizeInBits() == 128 && "Unknown type for VShift");
EVT ShVT = MVT::v2i64;
unsigned Opc = isLeft ? X86ISD::VSHL : X86ISD::VSRL;
SrcOp = DAG.getNode(ISD::BITCAST, dl, ShVT, SrcOp);
@@ -4333,42 +4921,52 @@ X86TargetLowering::LowerAsSplatVectorLoad(SDValue SrcOp, EVT VT, DebugLoc dl,
return SDValue();
}
+ // FIXME: 256-bit vector instructions don't require a strict alignment,
+ // improve this code to support it better.
+ unsigned RequiredAlign = VT.getSizeInBits()/8;
SDValue Chain = LD->getChain();
- // Make sure the stack object alignment is at least 16.
+ // Make sure the stack object alignment is at least 16 or 32.
MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
- if (DAG.InferPtrAlignment(Ptr) < 16) {
+ if (DAG.InferPtrAlignment(Ptr) < RequiredAlign) {
if (MFI->isFixedObjectIndex(FI)) {
// Can't change the alignment. FIXME: It's possible to compute
// the exact stack offset and reference FI + adjust offset instead.
// If someone *really* cares about this. That's the way to implement it.
return SDValue();
} else {
- MFI->setObjectAlignment(FI, 16);
+ MFI->setObjectAlignment(FI, RequiredAlign);
}
}
- // (Offset % 16) must be multiple of 4. Then address is then
+ // (Offset % 16 or 32) must be multiple of 4. Then address is then
// Ptr + (Offset & ~15).
if (Offset < 0)
return SDValue();
- if ((Offset % 16) & 3)
+ if ((Offset % RequiredAlign) & 3)
return SDValue();
- int64_t StartOffset = Offset & ~15;
+ int64_t StartOffset = Offset & ~(RequiredAlign-1);
if (StartOffset)
Ptr = DAG.getNode(ISD::ADD, Ptr.getDebugLoc(), Ptr.getValueType(),
Ptr,DAG.getConstant(StartOffset, Ptr.getValueType()));
int EltNo = (Offset - StartOffset) >> 2;
- int Mask[4] = { EltNo, EltNo, EltNo, EltNo };
- EVT VT = (PVT == MVT::i32) ? MVT::v4i32 : MVT::v4f32;
- SDValue V1 = DAG.getLoad(VT, dl, Chain, Ptr,
+ int NumElems = VT.getVectorNumElements();
+
+ EVT CanonVT = VT.getSizeInBits() == 128 ? MVT::v4i32 : MVT::v8i32;
+ EVT NVT = EVT::getVectorVT(*DAG.getContext(), PVT, NumElems);
+ SDValue V1 = DAG.getLoad(NVT, dl, Chain, Ptr,
LD->getPointerInfo().getWithOffset(StartOffset),
false, false, 0);
- // Canonicalize it to a v4i32 shuffle.
- V1 = DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, V1);
- return DAG.getNode(ISD::BITCAST, dl, VT,
- DAG.getVectorShuffle(MVT::v4i32, dl, V1,
- DAG.getUNDEF(MVT::v4i32),&Mask[0]));
+
+ // Canonicalize it to a v4i32 or v8i32 shuffle.
+ SmallVector<int, 8> Mask;
+ for (int i = 0; i < NumElems; ++i)
+ Mask.push_back(EltNo);
+
+ V1 = DAG.getNode(ISD::BITCAST, dl, CanonVT, V1);
+ return DAG.getNode(ISD::BITCAST, dl, NVT,
+ DAG.getVectorShuffle(CanonVT, dl, V1,
+ DAG.getUNDEF(CanonVT),&Mask[0]));
}
return SDValue();
@@ -4428,12 +5026,16 @@ static SDValue EltsFromConsecutiveLoads(EVT VT, SmallVectorImpl<SDValue> &Elts,
LDBase->getPointerInfo(),
LDBase->isVolatile(), LDBase->isNonTemporal(),
LDBase->getAlignment());
- } else if (NumElems == 4 && LastLoadedElt == 1) {
+ } else if (NumElems == 4 && LastLoadedElt == 1 &&
+ DAG.getTargetLoweringInfo().isTypeLegal(MVT::v2i64)) {
SDVTList Tys = DAG.getVTList(MVT::v2i64, MVT::Other);
SDValue Ops[] = { LDBase->getChain(), LDBase->getBasePtr() };
- SDValue ResNode = DAG.getMemIntrinsicNode(X86ISD::VZEXT_LOAD, DL, Tys,
- Ops, 2, MVT::i32,
- LDBase->getMemOperand());
+ SDValue ResNode =
+ DAG.getMemIntrinsicNode(X86ISD::VZEXT_LOAD, DL, Tys, Ops, 2, MVT::i64,
+ LDBase->getPointerInfo(),
+ LDBase->getAlignment(),
+ false/*isVolatile*/, true/*ReadMem*/,
+ false/*WriteMem*/);
return DAG.getNode(ISD::BITCAST, DL, VT, ResNode);
}
return SDValue();
@@ -4445,47 +5047,26 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
EVT VT = Op.getValueType();
EVT ExtVT = VT.getVectorElementType();
-
unsigned NumElems = Op.getNumOperands();
- // For AVX-length vectors, build the individual 128-bit pieces and
- // use shuffles to put them in place.
- if (VT.getSizeInBits() > 256 &&
- Subtarget->hasAVX() &&
- !ISD::isBuildVectorAllZeros(Op.getNode())) {
- SmallVector<SDValue, 8> V;
- V.resize(NumElems);
- for (unsigned i = 0; i < NumElems; ++i) {
- V[i] = Op.getOperand(i);
- }
-
- EVT HVT = EVT::getVectorVT(*DAG.getContext(), ExtVT, NumElems/2);
-
- // Build the lower subvector.
- SDValue Lower = DAG.getNode(ISD::BUILD_VECTOR, dl, HVT, &V[0], NumElems/2);
- // Build the upper subvector.
- SDValue Upper = DAG.getNode(ISD::BUILD_VECTOR, dl, HVT, &V[NumElems / 2],
- NumElems/2);
+ // Vectors containing all zeros can be matched by pxor and xorps later
+ if (ISD::isBuildVectorAllZeros(Op.getNode())) {
+ // Canonicalize this to <4 x i32> to 1) ensure the zero vectors are CSE'd
+ // and 2) ensure that i64 scalars are eliminated on x86-32 hosts.
+ if (Op.getValueType() == MVT::v4i32 ||
+ Op.getValueType() == MVT::v8i32)
+ return Op;
- return ConcatVectors(Lower, Upper, DAG);
+ return getZeroVector(Op.getValueType(), Subtarget->hasXMMInt(), DAG, dl);
}
- // All zero's:
- // - pxor (SSE2), xorps (SSE1), vpxor (128 AVX), xorp[s|d] (256 AVX)
- // All one's:
- // - pcmpeqd (SSE2 and 128 AVX), fallback to constant pools (256 AVX)
- if (ISD::isBuildVectorAllZeros(Op.getNode()) ||
- ISD::isBuildVectorAllOnes(Op.getNode())) {
- // Canonicalize this to <4 x i32> or <8 x 32> (SSE) to
- // 1) ensure the zero vectors are CSE'd, and 2) ensure that i64 scalars are
- // eliminated on x86-32 hosts.
- if (Op.getValueType() == MVT::v4i32 ||
- Op.getValueType() == MVT::v8i32)
+ // Vectors containing all ones can be matched by pcmpeqd on 128-bit width
+ // vectors or broken into v4i32 operations on 256-bit vectors.
+ if (ISD::isBuildVectorAllOnes(Op.getNode())) {
+ if (Op.getValueType() == MVT::v4i32)
return Op;
- if (ISD::isBuildVectorAllOnes(Op.getNode()))
- return getOnesVector(Op.getValueType(), DAG, dl);
- return getZeroVector(Op.getValueType(), Subtarget->hasSSE2(), DAG, dl);
+ return getOnesVector(Op.getValueType(), DAG, dl);
}
unsigned EVTBits = ExtVT.getSizeInBits();
@@ -4538,7 +5119,7 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
Item = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Item);
Item = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VecVT, Item);
Item = getShuffleVectorZeroOrUndef(Item, 0, true,
- Subtarget->hasSSE2(), DAG);
+ Subtarget->hasXMMInt(), DAG);
// Now we have our 32-bit value zero extended in the low element of
// a vector. If Idx != 0, swizzle it into place.
@@ -4566,7 +5147,7 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
(ExtVT == MVT::i64 && Subtarget->is64Bit())) {
Item = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Item);
// Turn it into a MOVL (i.e. movss, movsd, or movd) to a zero vector.
- return getShuffleVectorZeroOrUndef(Item, 0, true, Subtarget->hasSSE2(),
+ return getShuffleVectorZeroOrUndef(Item, 0, true,Subtarget->hasXMMInt(),
DAG);
} else if (ExtVT == MVT::i16 || ExtVT == MVT::i8) {
Item = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Item);
@@ -4574,7 +5155,7 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
EVT MiddleVT = MVT::v4i32;
Item = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MiddleVT, Item);
Item = getShuffleVectorZeroOrUndef(Item, 0, true,
- Subtarget->hasSSE2(), DAG);
+ Subtarget->hasXMMInt(), DAG);
return DAG.getNode(ISD::BITCAST, dl, VT, Item);
}
}
@@ -4603,7 +5184,7 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
// Turn it into a shuffle of zero and zero-extended scalar to vector.
Item = getShuffleVectorZeroOrUndef(Item, 0, NumZero > 0,
- Subtarget->hasSSE2(), DAG);
+ Subtarget->hasXMMInt(), DAG);
SmallVector<int, 8> MaskVec;
for (unsigned i = 0; i < NumElems; i++)
MaskVec.push_back(i == Idx ? 0 : 1);
@@ -4631,6 +5212,27 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
if (IsAllConstants)
return SDValue();
+ // For AVX-length vectors, build the individual 128-bit pieces and use
+ // shuffles to put them in place.
+ if (VT.getSizeInBits() == 256 && !ISD::isBuildVectorAllZeros(Op.getNode())) {
+ SmallVector<SDValue, 32> V;
+ for (unsigned i = 0; i < NumElems; ++i)
+ V.push_back(Op.getOperand(i));
+
+ EVT HVT = EVT::getVectorVT(*DAG.getContext(), ExtVT, NumElems/2);
+
+ // Build both the lower and upper subvector.
+ SDValue Lower = DAG.getNode(ISD::BUILD_VECTOR, dl, HVT, &V[0], NumElems/2);
+ SDValue Upper = DAG.getNode(ISD::BUILD_VECTOR, dl, HVT, &V[NumElems / 2],
+ NumElems/2);
+
+ // Recreate the wider vector with the lower and upper part.
+ SDValue Vec = Insert128BitVector(DAG.getNode(ISD::UNDEF, dl, VT), Lower,
+ DAG.getConstant(0, MVT::i32), DAG, dl);
+ return Insert128BitVector(Vec, Upper, DAG.getConstant(NumElems/2, MVT::i32),
+ DAG, dl);
+ }
+
// Let legalizer expand 2-wide build_vectors.
if (EVTBits == 64) {
if (NumNonZero == 1) {
@@ -4639,7 +5241,7 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
SDValue V2 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT,
Op.getOperand(Idx));
return getShuffleVectorZeroOrUndef(V2, Idx, true,
- Subtarget->hasSSE2(), DAG);
+ Subtarget->hasXMMInt(), DAG);
}
return SDValue();
}
@@ -4664,7 +5266,7 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
for (unsigned i = 0; i < 4; ++i) {
bool isZero = !(NonZeros & (1 << i));
if (isZero)
- V[i] = getZeroVector(VT, Subtarget->hasSSE2(), DAG, dl);
+ V[i] = getZeroVector(VT, Subtarget->hasXMMInt(), DAG, dl);
else
V[i] = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Op.getOperand(i));
}
@@ -4708,7 +5310,7 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
return LD;
// For SSE 4.1, use insertps to put the high elements into the low element.
- if (getSubtarget()->hasSSE41()) {
+ if (getSubtarget()->hasSSE41() || getSubtarget()->hasAVX()) {
SDValue Result;
if (Op.getOperand(0).getOpcode() != ISD::UNDEF)
Result = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Op.getOperand(0));
@@ -4758,13 +5360,12 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
return SDValue();
}
-SDValue
-X86TargetLowering::LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const {
- // We support concatenate two MMX registers and place them in a MMX
- // register. This is better than doing a stack convert.
+// LowerMMXCONCAT_VECTORS - We support concatenate two MMX registers and place
+// them in a MMX register. This is better than doing a stack convert.
+static SDValue LowerMMXCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) {
DebugLoc dl = Op.getDebugLoc();
EVT ResVT = Op.getValueType();
- assert(Op.getNumOperands() == 2);
+
assert(ResVT == MVT::v2i64 || ResVT == MVT::v4i32 ||
ResVT == MVT::v8i16 || ResVT == MVT::v16i8);
int Mask[2];
@@ -4785,6 +5386,42 @@ X86TargetLowering::LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const {
return DAG.getNode(ISD::BITCAST, dl, ResVT, VecOp);
}
+// LowerAVXCONCAT_VECTORS - 256-bit AVX can use the vinsertf128 instruction
+// to create 256-bit vectors from two other 128-bit ones.
+static SDValue LowerAVXCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) {
+ DebugLoc dl = Op.getDebugLoc();
+ EVT ResVT = Op.getValueType();
+
+ assert(ResVT.getSizeInBits() == 256 && "Value type must be 256-bit wide");
+
+ SDValue V1 = Op.getOperand(0);
+ SDValue V2 = Op.getOperand(1);
+ unsigned NumElems = ResVT.getVectorNumElements();
+
+ SDValue V = Insert128BitVector(DAG.getNode(ISD::UNDEF, dl, ResVT), V1,
+ DAG.getConstant(0, MVT::i32), DAG, dl);
+ return Insert128BitVector(V, V2, DAG.getConstant(NumElems/2, MVT::i32),
+ DAG, dl);
+}
+
+SDValue
+X86TargetLowering::LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const {
+ EVT ResVT = Op.getValueType();
+
+ assert(Op.getNumOperands() == 2);
+ assert((ResVT.getSizeInBits() == 128 || ResVT.getSizeInBits() == 256) &&
+ "Unsupported CONCAT_VECTORS for value type");
+
+ // We support concatenate two MMX registers and place them in a MMX register.
+ // This is better than doing a stack convert.
+ if (ResVT.is128BitVector())
+ return LowerMMXCONCAT_VECTORS(Op, DAG);
+
+ // 256-bit AVX can use the vinsertf128 instruction to create 256-bit vectors
+ // from two other 128-bit ones.
+ return LowerAVXCONCAT_VECTORS(Op, DAG);
+}
+
// v8i16 shuffles - Prefer shuffles in the following order:
// 1. [all] pshuflw, pshufhw, optional move
// 2. [ssse3] 1 x pshufb
@@ -4844,7 +5481,7 @@ X86TargetLowering::LowerVECTOR_SHUFFLEv8i16(SDValue Op,
// quads, disable the next transformation since it does not help SSSE3.
bool V1Used = InputQuads[0] || InputQuads[1];
bool V2Used = InputQuads[2] || InputQuads[3];
- if (Subtarget->hasSSSE3()) {
+ if (Subtarget->hasSSSE3() || Subtarget->hasAVX()) {
if (InputQuads.count() == 2 && V1Used && V2Used) {
BestLoQuad = InputQuads.find_first();
BestHiQuad = InputQuads.find_next(BestLoQuad);
@@ -4917,7 +5554,7 @@ X86TargetLowering::LowerVECTOR_SHUFFLEv8i16(SDValue Op,
// If we have SSSE3, and all words of the result are from 1 input vector,
// case 2 is generated, otherwise case 3 is generated. If no SSSE3
// is present, fall back to case 4.
- if (Subtarget->hasSSSE3()) {
+ if (Subtarget->hasSSSE3() || Subtarget->hasAVX()) {
SmallVector<SDValue,16> pshufbMask;
// If we have elements from both input vectors, set the high bit of the
@@ -4985,7 +5622,8 @@ X86TargetLowering::LowerVECTOR_SHUFFLEv8i16(SDValue Op,
NewV = DAG.getVectorShuffle(MVT::v8i16, dl, NewV, DAG.getUNDEF(MVT::v8i16),
&MaskV[0]);
- if (NewV.getOpcode() == ISD::VECTOR_SHUFFLE && Subtarget->hasSSSE3())
+ if (NewV.getOpcode() == ISD::VECTOR_SHUFFLE &&
+ (Subtarget->hasSSSE3() || Subtarget->hasAVX()))
NewV = getTargetShuffleNode(X86ISD::PSHUFLW, dl, MVT::v8i16,
NewV.getOperand(0),
X86::getShufflePSHUFLWImmediate(NewV.getNode()),
@@ -5013,7 +5651,8 @@ X86TargetLowering::LowerVECTOR_SHUFFLEv8i16(SDValue Op,
NewV = DAG.getVectorShuffle(MVT::v8i16, dl, NewV, DAG.getUNDEF(MVT::v8i16),
&MaskV[0]);
- if (NewV.getOpcode() == ISD::VECTOR_SHUFFLE && Subtarget->hasSSSE3())
+ if (NewV.getOpcode() == ISD::VECTOR_SHUFFLE &&
+ (Subtarget->hasSSSE3() || Subtarget->hasAVX()))
NewV = getTargetShuffleNode(X86ISD::PSHUFHW, dl, MVT::v8i16,
NewV.getOperand(0),
X86::getShufflePSHUFHWImmediate(NewV.getNode()),
@@ -5079,7 +5718,7 @@ SDValue LowerVECTOR_SHUFFLEv16i8(ShuffleVectorSDNode *SVOp,
}
// If SSSE3, use 1 pshufb instruction per vector with elements in the result.
- if (TLI.getSubtarget()->hasSSSE3()) {
+ if (TLI.getSubtarget()->hasSSSE3() || TLI.getSubtarget()->hasAVX()) {
SmallVector<SDValue,16> pshufbMask;
// If all result elements are from one input vector, then only translate
@@ -5276,15 +5915,109 @@ static SDValue getVZextMovL(EVT VT, EVT OpVT,
OpVT, SrcOp)));
}
-/// LowerVECTOR_SHUFFLE_4wide - Handle all 4 wide cases with a number of
-/// shuffles.
+/// areShuffleHalvesWithinDisjointLanes - Check whether each half of a vector
+/// shuffle node referes to only one lane in the sources.
+static bool areShuffleHalvesWithinDisjointLanes(ShuffleVectorSDNode *SVOp) {
+ EVT VT = SVOp->getValueType(0);
+ int NumElems = VT.getVectorNumElements();
+ int HalfSize = NumElems/2;
+ SmallVector<int, 16> M;
+ SVOp->getMask(M);
+ bool MatchA = false, MatchB = false;
+
+ for (int l = 0; l < NumElems*2; l += HalfSize) {
+ if (isUndefOrInRange(M, 0, HalfSize, l, l+HalfSize)) {
+ MatchA = true;
+ break;
+ }
+ }
+
+ for (int l = 0; l < NumElems*2; l += HalfSize) {
+ if (isUndefOrInRange(M, HalfSize, HalfSize, l, l+HalfSize)) {
+ MatchB = true;
+ break;
+ }
+ }
+
+ return MatchA && MatchB;
+}
+
+/// LowerVECTOR_SHUFFLE_256 - Handle all 256-bit wide vectors shuffles
+/// which could not be matched by any known target speficic shuffle
+static SDValue
+LowerVECTOR_SHUFFLE_256(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) {
+ if (areShuffleHalvesWithinDisjointLanes(SVOp)) {
+ // If each half of a vector shuffle node referes to only one lane in the
+ // source vectors, extract each used 128-bit lane and shuffle them using
+ // 128-bit shuffles. Then, concatenate the results. Otherwise leave
+ // the work to the legalizer.
+ DebugLoc dl = SVOp->getDebugLoc();
+ EVT VT = SVOp->getValueType(0);
+ int NumElems = VT.getVectorNumElements();
+ int HalfSize = NumElems/2;
+
+ // Extract the reference for each half
+ int FstVecExtractIdx = 0, SndVecExtractIdx = 0;
+ int FstVecOpNum = 0, SndVecOpNum = 0;
+ for (int i = 0; i < HalfSize; ++i) {
+ int Elt = SVOp->getMaskElt(i);
+ if (SVOp->getMaskElt(i) < 0)
+ continue;
+ FstVecOpNum = Elt/NumElems;
+ FstVecExtractIdx = Elt % NumElems < HalfSize ? 0 : HalfSize;
+ break;
+ }
+ for (int i = HalfSize; i < NumElems; ++i) {
+ int Elt = SVOp->getMaskElt(i);
+ if (SVOp->getMaskElt(i) < 0)
+ continue;
+ SndVecOpNum = Elt/NumElems;
+ SndVecExtractIdx = Elt % NumElems < HalfSize ? 0 : HalfSize;
+ break;
+ }
+
+ // Extract the subvectors
+ SDValue V1 = Extract128BitVector(SVOp->getOperand(FstVecOpNum),
+ DAG.getConstant(FstVecExtractIdx, MVT::i32), DAG, dl);
+ SDValue V2 = Extract128BitVector(SVOp->getOperand(SndVecOpNum),
+ DAG.getConstant(SndVecExtractIdx, MVT::i32), DAG, dl);
+
+ // Generate 128-bit shuffles
+ SmallVector<int, 16> MaskV1, MaskV2;
+ for (int i = 0; i < HalfSize; ++i) {
+ int Elt = SVOp->getMaskElt(i);
+ MaskV1.push_back(Elt < 0 ? Elt : Elt % HalfSize);
+ }
+ for (int i = HalfSize; i < NumElems; ++i) {
+ int Elt = SVOp->getMaskElt(i);
+ MaskV2.push_back(Elt < 0 ? Elt : Elt % HalfSize);
+ }
+
+ EVT NVT = V1.getValueType();
+ V1 = DAG.getVectorShuffle(NVT, dl, V1, DAG.getUNDEF(NVT), &MaskV1[0]);
+ V2 = DAG.getVectorShuffle(NVT, dl, V2, DAG.getUNDEF(NVT), &MaskV2[0]);
+
+ // Concatenate the result back
+ SDValue V = Insert128BitVector(DAG.getNode(ISD::UNDEF, dl, VT), V1,
+ DAG.getConstant(0, MVT::i32), DAG, dl);
+ return Insert128BitVector(V, V2, DAG.getConstant(NumElems/2, MVT::i32),
+ DAG, dl);
+ }
+
+ return SDValue();
+}
+
+/// LowerVECTOR_SHUFFLE_128v4 - Handle all 128-bit wide vectors with
+/// 4 elements, and match them with several different shuffle types.
static SDValue
-LowerVECTOR_SHUFFLE_4wide(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) {
+LowerVECTOR_SHUFFLE_128v4(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) {
SDValue V1 = SVOp->getOperand(0);
SDValue V2 = SVOp->getOperand(1);
DebugLoc dl = SVOp->getDebugLoc();
EVT VT = SVOp->getValueType(0);
+ assert(VT.getSizeInBits() == 128 && "Unsupported vector size");
+
SmallVector<std::pair<int, int>, 8> Locs;
Locs.resize(4);
SmallVector<int, 8> Mask1(4U, -1);
@@ -5542,18 +6275,21 @@ SDValue getMOVDDup(SDValue &Op, DebugLoc &dl, SDValue V1, SelectionDAG &DAG) {
static
SDValue getMOVLowToHigh(SDValue &Op, DebugLoc &dl, SelectionDAG &DAG,
- bool HasSSE2) {
+ bool HasXMMInt) {
SDValue V1 = Op.getOperand(0);
SDValue V2 = Op.getOperand(1);
EVT VT = Op.getValueType();
assert(VT != MVT::v2i64 && "unsupported shuffle type");
- if (HasSSE2 && VT == MVT::v2f64)
+ if (HasXMMInt && VT == MVT::v2f64)
return getTargetShuffleNode(X86ISD::MOVLHPD, dl, VT, V1, V2, DAG);
- // v4f32 or v4i32
- return getTargetShuffleNode(X86ISD::MOVLHPS, dl, VT, V1, V2, DAG);
+ // v4f32 or v4i32: canonizalized to v4f32 (which is legal for SSE1)
+ return DAG.getNode(ISD::BITCAST, dl, VT,
+ getTargetShuffleNode(X86ISD::MOVLHPS, dl, MVT::v4f32,
+ DAG.getNode(ISD::BITCAST, dl, MVT::v4f32, V1),
+ DAG.getNode(ISD::BITCAST, dl, MVT::v4f32, V2), DAG));
}
static
@@ -5572,8 +6308,24 @@ SDValue getMOVHighToLow(SDValue &Op, DebugLoc &dl, SelectionDAG &DAG) {
return getTargetShuffleNode(X86ISD::MOVHLPS, dl, VT, V1, V2, DAG);
}
+static inline unsigned getSHUFPOpcode(EVT VT) {
+ switch(VT.getSimpleVT().SimpleTy) {
+ case MVT::v8i32: // Use fp unit for int unpack.
+ case MVT::v8f32:
+ case MVT::v4i32: // Use fp unit for int unpack.
+ case MVT::v4f32: return X86ISD::SHUFPS;
+ case MVT::v4i64: // Use fp unit for int unpack.
+ case MVT::v4f64:
+ case MVT::v2i64: // Use fp unit for int unpack.
+ case MVT::v2f64: return X86ISD::SHUFPD;
+ default:
+ llvm_unreachable("Unknown type for shufp*");
+ }
+ return 0;
+}
+
static
-SDValue getMOVLP(SDValue &Op, DebugLoc &dl, SelectionDAG &DAG, bool HasSSE2) {
+SDValue getMOVLP(SDValue &Op, DebugLoc &dl, SelectionDAG &DAG, bool HasXMMInt) {
SDValue V1 = Op.getOperand(0);
SDValue V2 = Op.getOperand(1);
EVT VT = Op.getValueType();
@@ -5602,7 +6354,7 @@ SDValue getMOVLP(SDValue &Op, DebugLoc &dl, SelectionDAG &DAG, bool HasSSE2) {
CanFoldLoad = false;
if (CanFoldLoad) {
- if (HasSSE2 && NumElems == 2)
+ if (HasXMMInt && NumElems == 2)
return getTargetShuffleNode(X86ISD::MOVLPD, dl, VT, V1, V2, DAG);
if (NumElems == 4)
@@ -5616,28 +6368,30 @@ SDValue getMOVLP(SDValue &Op, DebugLoc &dl, SelectionDAG &DAG, bool HasSSE2) {
// this is horrible, but will stay like this until we move all shuffle
// matching to x86 specific nodes. Note that for the 1st condition all
// types are matched with movsd.
- if ((HasSSE2 && NumElems == 2) || !X86::isMOVLMask(SVOp))
- return getTargetShuffleNode(X86ISD::MOVSD, dl, VT, V1, V2, DAG);
- else if (HasSSE2)
+ if (HasXMMInt) {
+ // FIXME: isMOVLMask should be checked and matched before getMOVLP,
+ // as to remove this logic from here, as much as possible
+ if (NumElems == 2 || !X86::isMOVLMask(SVOp))
+ return getTargetShuffleNode(X86ISD::MOVSD, dl, VT, V1, V2, DAG);
return getTargetShuffleNode(X86ISD::MOVSS, dl, VT, V1, V2, DAG);
-
+ }
assert(VT != MVT::v4i32 && "unsupported shuffle type");
// Invert the operand order and use SHUFPS to match it.
- return getTargetShuffleNode(X86ISD::SHUFPS, dl, VT, V2, V1,
+ return getTargetShuffleNode(getSHUFPOpcode(VT), dl, VT, V2, V1,
X86::getShuffleSHUFImmediate(SVOp), DAG);
}
-static inline unsigned getUNPCKLOpcode(EVT VT, const X86Subtarget *Subtarget) {
+static inline unsigned getUNPCKLOpcode(EVT VT) {
switch(VT.getSimpleVT().SimpleTy) {
case MVT::v4i32: return X86ISD::PUNPCKLDQ;
case MVT::v2i64: return X86ISD::PUNPCKLQDQ;
- case MVT::v4f32:
- return Subtarget->hasAVX() ? X86ISD::VUNPCKLPS : X86ISD::UNPCKLPS;
- case MVT::v2f64:
- return Subtarget->hasAVX() ? X86ISD::VUNPCKLPD : X86ISD::UNPCKLPD;
+ case MVT::v4f32: return X86ISD::UNPCKLPS;
+ case MVT::v2f64: return X86ISD::UNPCKLPD;
+ case MVT::v8i32: // Use fp unit for int unpack.
case MVT::v8f32: return X86ISD::VUNPCKLPSY;
+ case MVT::v4i64: // Use fp unit for int unpack.
case MVT::v4f64: return X86ISD::VUNPCKLPDY;
case MVT::v16i8: return X86ISD::PUNPCKLBW;
case MVT::v8i16: return X86ISD::PUNPCKLWD;
@@ -5653,6 +6407,10 @@ static inline unsigned getUNPCKHOpcode(EVT VT) {
case MVT::v2i64: return X86ISD::PUNPCKHQDQ;
case MVT::v4f32: return X86ISD::UNPCKHPS;
case MVT::v2f64: return X86ISD::UNPCKHPD;
+ case MVT::v8i32: // Use fp unit for int unpack.
+ case MVT::v8f32: return X86ISD::VUNPCKHPSY;
+ case MVT::v4i64: // Use fp unit for int unpack.
+ case MVT::v4f64: return X86ISD::VUNPCKHPDY;
case MVT::v16i8: return X86ISD::PUNPCKHBW;
case MVT::v8i16: return X86ISD::PUNPCKHWD;
default:
@@ -5661,6 +6419,68 @@ static inline unsigned getUNPCKHOpcode(EVT VT) {
return 0;
}
+static inline unsigned getVPERMILOpcode(EVT VT) {
+ switch(VT.getSimpleVT().SimpleTy) {
+ case MVT::v4i32:
+ case MVT::v4f32: return X86ISD::VPERMILPS;
+ case MVT::v2i64:
+ case MVT::v2f64: return X86ISD::VPERMILPD;
+ case MVT::v8i32:
+ case MVT::v8f32: return X86ISD::VPERMILPSY;
+ case MVT::v4i64:
+ case MVT::v4f64: return X86ISD::VPERMILPDY;
+ default:
+ llvm_unreachable("Unknown type for vpermil");
+ }
+ return 0;
+}
+
+/// isVectorBroadcast - Check if the node chain is suitable to be xformed to
+/// a vbroadcast node. The nodes are suitable whenever we can fold a load coming
+/// from a 32 or 64 bit scalar. Update Op to the desired load to be folded.
+static bool isVectorBroadcast(SDValue &Op) {
+ EVT VT = Op.getValueType();
+ bool Is256 = VT.getSizeInBits() == 256;
+
+ assert((VT.getSizeInBits() == 128 || Is256) &&
+ "Unsupported type for vbroadcast node");
+
+ SDValue V = Op;
+ if (V.hasOneUse() && V.getOpcode() == ISD::BITCAST)
+ V = V.getOperand(0);
+
+ if (Is256 && !(V.hasOneUse() &&
+ V.getOpcode() == ISD::INSERT_SUBVECTOR &&
+ V.getOperand(0).getOpcode() == ISD::UNDEF))
+ return false;
+
+ if (Is256)
+ V = V.getOperand(1);
+
+ if (!V.hasOneUse())
+ return false;
+
+ // Check the source scalar_to_vector type. 256-bit broadcasts are
+ // supported for 32/64-bit sizes, while 128-bit ones are only supported
+ // for 32-bit scalars.
+ if (V.getOpcode() != ISD::SCALAR_TO_VECTOR)
+ return false;
+
+ unsigned ScalarSize = V.getOperand(0).getValueType().getSizeInBits();
+ if (ScalarSize != 32 && ScalarSize != 64)
+ return false;
+ if (!Is256 && ScalarSize == 64)
+ return false;
+
+ V = V.getOperand(0);
+ if (!MayFoldLoad(V))
+ return false;
+
+ // Return the load node
+ Op = V;
+ return true;
+}
+
static
SDValue NormalizeVectorShuffle(SDValue Op, SelectionDAG &DAG,
const TargetLowering &TLI,
@@ -5672,23 +6492,29 @@ SDValue NormalizeVectorShuffle(SDValue Op, SelectionDAG &DAG,
SDValue V2 = Op.getOperand(1);
if (isZeroShuffle(SVOp))
- return getZeroVector(VT, Subtarget->hasSSE2(), DAG, dl);
+ return getZeroVector(VT, Subtarget->hasXMMInt(), DAG, dl);
// Handle splat operations
if (SVOp->isSplat()) {
- // Special case, this is the only place now where it's
- // allowed to return a vector_shuffle operation without
- // using a target specific node, because *hopefully* it
- // will be optimized away by the dag combiner.
- if (VT.getVectorNumElements() <= 4 &&
- CanXFormVExtractWithShuffleIntoLoad(Op, DAG, TLI))
+ unsigned NumElem = VT.getVectorNumElements();
+ int Size = VT.getSizeInBits();
+ // Special case, this is the only place now where it's allowed to return
+ // a vector_shuffle operation without using a target specific node, because
+ // *hopefully* it will be optimized away by the dag combiner. FIXME: should
+ // this be moved to DAGCombine instead?
+ if (NumElem <= 4 && CanXFormVExtractWithShuffleIntoLoad(Op, DAG, TLI))
return Op;
- // Handle splats by matching through known masks
- if (VT.getVectorNumElements() <= 4)
+ // Use vbroadcast whenever the splat comes from a foldable load
+ if (Subtarget->hasAVX() && isVectorBroadcast(V1))
+ return DAG.getNode(X86ISD::VBROADCAST, dl, VT, V1);
+
+ // Handle splats by matching through known shuffle masks
+ if ((Size == 128 && NumElem <= 4) ||
+ (Size == 256 && NumElem < 8))
return SDValue();
- // Canonicalize all of the remaining to v4f32.
+ // All remaning splats are promoted to target supported vector shuffles.
return PromoteSplat(SVOp, DAG);
}
@@ -5698,7 +6524,8 @@ SDValue NormalizeVectorShuffle(SDValue Op, SelectionDAG &DAG,
SDValue NewOp = RewriteAsNarrowerShuffle(SVOp, DAG, dl);
if (NewOp.getNode())
return DAG.getNode(ISD::BITCAST, dl, VT, NewOp);
- } else if ((VT == MVT::v4i32 || (VT == MVT::v4f32 && Subtarget->hasSSE2()))) {
+ } else if ((VT == MVT::v4i32 ||
+ (VT == MVT::v4f32 && Subtarget->hasXMMInt()))) {
// FIXME: Figure out a cleaner way to do this.
// Try to make use of movq to zero out the top part.
if (ISD::isBuildVectorAllZeros(V2.getNode())) {
@@ -5731,9 +6558,7 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const {
bool V2IsUndef = V2.getOpcode() == ISD::UNDEF;
bool V1IsSplat = false;
bool V2IsSplat = false;
- bool HasSSE2 = Subtarget->hasSSE2() || Subtarget->hasAVX();
- bool HasSSE3 = Subtarget->hasSSE3() || Subtarget->hasAVX();
- bool HasSSSE3 = Subtarget->hasSSSE3() || Subtarget->hasAVX();
+ bool HasXMMInt = Subtarget->hasXMMInt();
MachineFunction &MF = DAG.getMachineFunction();
bool OptForSize = MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize);
@@ -5765,21 +6590,20 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const {
// NOTE: isPSHUFDMask can also match both masks below (unpckl_undef and
// unpckh_undef). Only use pshufd if speed is more important than size.
if (OptForSize && X86::isUNPCKL_v_undef_Mask(SVOp))
- if (VT != MVT::v2i64 && VT != MVT::v2f64)
- return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()), dl, VT, V1, V1, DAG);
+ return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V1, V1, DAG);
if (OptForSize && X86::isUNPCKH_v_undef_Mask(SVOp))
- if (VT != MVT::v2i64 && VT != MVT::v2f64)
- return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V1, DAG);
+ return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V1, DAG);
- if (X86::isMOVDDUPMask(SVOp) && HasSSE3 && V2IsUndef &&
- RelaxedMayFoldVectorLoad(V1))
+ if (X86::isMOVDDUPMask(SVOp) &&
+ (Subtarget->hasSSE3() || Subtarget->hasAVX()) &&
+ V2IsUndef && RelaxedMayFoldVectorLoad(V1))
return getMOVDDup(Op, dl, V1, DAG);
if (X86::isMOVHLPS_v_undef_Mask(SVOp))
return getMOVHighToLow(Op, dl, DAG);
// Use to match splats
- if (HasSSE2 && X86::isUNPCKHMask(SVOp) && V2IsUndef &&
+ if (HasXMMInt && X86::isUNPCKHMask(SVOp) && V2IsUndef &&
(VT == MVT::v2f64 || VT == MVT::v2i64))
return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V1, DAG);
@@ -5792,24 +6616,19 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const {
unsigned TargetMask = X86::getShuffleSHUFImmediate(SVOp);
- if (HasSSE2 && (VT == MVT::v4f32 || VT == MVT::v4i32))
+ if (HasXMMInt && (VT == MVT::v4f32 || VT == MVT::v4i32))
return getTargetShuffleNode(X86ISD::PSHUFD, dl, VT, V1, TargetMask, DAG);
- if (HasSSE2 && (VT == MVT::v2i64 || VT == MVT::v2f64))
- return getTargetShuffleNode(X86ISD::SHUFPD, dl, VT, V1, V1,
- TargetMask, DAG);
-
- if (VT == MVT::v4f32)
- return getTargetShuffleNode(X86ISD::SHUFPS, dl, VT, V1, V1,
- TargetMask, DAG);
+ return getTargetShuffleNode(getSHUFPOpcode(VT), dl, VT, V1, V1,
+ TargetMask, DAG);
}
// Check if this can be converted into a logical shift.
bool isLeft = false;
unsigned ShAmt = 0;
SDValue ShVal;
- bool isShift = getSubtarget()->hasSSE2() &&
- isVectorShift(SVOp, DAG, isLeft, ShVal, ShAmt);
+ bool isShift = getSubtarget()->hasXMMInt() &&
+ isVectorShift(SVOp, DAG, isLeft, ShVal, ShAmt);
if (isShift && ShVal.hasOneUse()) {
// If the shifted value has multiple uses, it may be cheaper to use
// v_set0 + movlhps or movhlps, etc.
@@ -5824,7 +6643,7 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const {
if (ISD::isBuildVectorAllZeros(V1.getNode()))
return getVZextMovL(VT, VT, V2, DAG, Subtarget, dl);
if (!X86::isMOVLPMask(SVOp)) {
- if (HasSSE2 && (VT == MVT::v2i64 || VT == MVT::v2f64))
+ if (HasXMMInt && (VT == MVT::v2i64 || VT == MVT::v2f64))
return getTargetShuffleNode(X86ISD::MOVSD, dl, VT, V1, V2, DAG);
if (VT == MVT::v4i32 || VT == MVT::v4f32)
@@ -5834,19 +6653,19 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const {
// FIXME: fold these into legal mask.
if (X86::isMOVLHPSMask(SVOp) && !X86::isUNPCKLMask(SVOp))
- return getMOVLowToHigh(Op, dl, DAG, HasSSE2);
+ return getMOVLowToHigh(Op, dl, DAG, HasXMMInt);
if (X86::isMOVHLPSMask(SVOp))
return getMOVHighToLow(Op, dl, DAG);
- if (X86::isMOVSHDUPMask(SVOp) && HasSSE3 && V2IsUndef && NumElems == 4)
+ if (X86::isMOVSHDUPMask(SVOp, Subtarget))
return getTargetShuffleNode(X86ISD::MOVSHDUP, dl, VT, V1, DAG);
- if (X86::isMOVSLDUPMask(SVOp) && HasSSE3 && V2IsUndef && NumElems == 4)
+ if (X86::isMOVSLDUPMask(SVOp, Subtarget))
return getTargetShuffleNode(X86ISD::MOVSLDUP, dl, VT, V1, DAG);
if (X86::isMOVLPMask(SVOp))
- return getMOVLP(Op, dl, DAG, HasSSE2);
+ return getMOVLP(Op, dl, DAG, HasXMMInt);
if (ShouldXformToMOVHLPS(SVOp) ||
ShouldXformToMOVLP(V1.getNode(), V2.getNode(), SVOp))
@@ -5887,8 +6706,7 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const {
}
if (X86::isUNPCKLMask(SVOp))
- return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()),
- dl, VT, V1, V2, DAG);
+ return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V1, V2, DAG);
if (X86::isUNPCKHMask(SVOp))
return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V2, DAG);
@@ -5915,8 +6733,7 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const {
ShuffleVectorSDNode *NewSVOp = cast<ShuffleVectorSDNode>(NewOp);
if (X86::isUNPCKLMask(NewSVOp))
- return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()),
- dl, VT, V2, V1, DAG);
+ return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V2, V1, DAG);
if (X86::isUNPCKHMask(NewSVOp))
return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V2, V1, DAG);
@@ -5932,18 +6749,15 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const {
SmallVector<int, 16> M;
SVOp->getMask(M);
- if (isPALIGNRMask(M, VT, HasSSSE3))
+ if (isPALIGNRMask(M, VT, Subtarget->hasSSSE3() || Subtarget->hasAVX()))
return getTargetShuffleNode(X86ISD::PALIGN, dl, VT, V1, V2,
X86::getShufflePALIGNRImmediate(SVOp),
DAG);
if (ShuffleVectorSDNode::isSplatMask(&M[0], VT) &&
SVOp->getSplatIndex() == 0 && V2IsUndef) {
- if (VT == MVT::v2f64) {
- X86ISD::NodeType Opcode =
- getSubtarget()->hasAVX() ? X86ISD::VUNPCKLPD : X86ISD::UNPCKLPD;
- return getTargetShuffleNode(Opcode, dl, VT, V1, V1, DAG);
- }
+ if (VT == MVT::v2f64)
+ return getTargetShuffleNode(X86ISD::UNPCKLPD, dl, VT, V1, V1, DAG);
if (VT == MVT::v2i64)
return getTargetShuffleNode(X86ISD::PUNPCKLQDQ, dl, VT, V1, V1, DAG);
}
@@ -5958,23 +6772,54 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const {
X86::getShufflePSHUFLWImmediate(SVOp),
DAG);
- if (isSHUFPMask(M, VT)) {
- unsigned TargetMask = X86::getShuffleSHUFImmediate(SVOp);
- if (VT == MVT::v4f32 || VT == MVT::v4i32)
- return getTargetShuffleNode(X86ISD::SHUFPS, dl, VT, V1, V2,
- TargetMask, DAG);
- if (VT == MVT::v2f64 || VT == MVT::v2i64)
- return getTargetShuffleNode(X86ISD::SHUFPD, dl, VT, V1, V2,
- TargetMask, DAG);
- }
+ if (isSHUFPMask(M, VT))
+ return getTargetShuffleNode(getSHUFPOpcode(VT), dl, VT, V1, V2,
+ X86::getShuffleSHUFImmediate(SVOp), DAG);
if (X86::isUNPCKL_v_undef_Mask(SVOp))
- if (VT != MVT::v2i64 && VT != MVT::v2f64)
- return getTargetShuffleNode(getUNPCKLOpcode(VT, getSubtarget()),
- dl, VT, V1, V1, DAG);
+ return getTargetShuffleNode(getUNPCKLOpcode(VT), dl, VT, V1, V1, DAG);
if (X86::isUNPCKH_v_undef_Mask(SVOp))
- if (VT != MVT::v2i64 && VT != MVT::v2f64)
- return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V1, DAG);
+ return getTargetShuffleNode(getUNPCKHOpcode(VT), dl, VT, V1, V1, DAG);
+
+ //===--------------------------------------------------------------------===//
+ // Generate target specific nodes for 128 or 256-bit shuffles only
+ // supported in the AVX instruction set.
+ //
+
+ // Handle VMOVDDUPY permutations
+ if (isMOVDDUPYMask(SVOp, Subtarget))
+ return getTargetShuffleNode(X86ISD::MOVDDUP, dl, VT, V1, DAG);
+
+ // Handle VPERMILPS* permutations
+ if (isVPERMILPSMask(M, VT, Subtarget))
+ return getTargetShuffleNode(getVPERMILOpcode(VT), dl, VT, V1,
+ getShuffleVPERMILPSImmediate(SVOp), DAG);
+
+ // Handle VPERMILPD* permutations
+ if (isVPERMILPDMask(M, VT, Subtarget))
+ return getTargetShuffleNode(getVPERMILOpcode(VT), dl, VT, V1,
+ getShuffleVPERMILPDImmediate(SVOp), DAG);
+
+ // Handle VPERM2F128 permutations
+ if (isVPERM2F128Mask(M, VT, Subtarget))
+ return getTargetShuffleNode(X86ISD::VPERM2F128, dl, VT, V1, V2,
+ getShuffleVPERM2F128Immediate(SVOp), DAG);
+
+ // Handle VSHUFPSY permutations
+ if (isVSHUFPSYMask(M, VT, Subtarget))
+ return getTargetShuffleNode(getSHUFPOpcode(VT), dl, VT, V1, V2,
+ getShuffleVSHUFPSYImmediate(SVOp), DAG);
+
+ // Handle VSHUFPDY permutations
+ if (isVSHUFPDYMask(M, VT, Subtarget))
+ return getTargetShuffleNode(getSHUFPOpcode(VT), dl, VT, V1, V2,
+ getShuffleVSHUFPDYImmediate(SVOp), DAG);
+
+ //===--------------------------------------------------------------------===//
+ // Since no target specific shuffle was selected for this generic one,
+ // lower it into other known shuffles. FIXME: this isn't true yet, but
+ // this is the plan.
+ //
// Handle v8i16 specifically since SSE can do byte extraction and insertion.
if (VT == MVT::v8i16) {
@@ -5989,9 +6834,14 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const {
return NewOp;
}
- // Handle all 4 wide cases with a number of shuffles.
- if (NumElems == 4)
- return LowerVECTOR_SHUFFLE_4wide(SVOp, DAG);
+ // Handle all 128-bit wide vectors with 4 elements, and match them with
+ // several different shuffle types.
+ if (NumElems == 4 && VT.getSizeInBits() == 128)
+ return LowerVECTOR_SHUFFLE_128v4(SVOp, DAG);
+
+ // Handle general 256-bit shuffles
+ if (VT.is256BitVector())
+ return LowerVECTOR_SHUFFLE_256(SVOp, DAG);
return SDValue();
}
@@ -6001,6 +6851,10 @@ X86TargetLowering::LowerEXTRACT_VECTOR_ELT_SSE4(SDValue Op,
SelectionDAG &DAG) const {
EVT VT = Op.getValueType();
DebugLoc dl = Op.getDebugLoc();
+
+ if (Op.getOperand(0).getValueType().getSizeInBits() != 128)
+ return SDValue();
+
if (VT.getSizeInBits() == 8) {
SDValue Extract = DAG.getNode(X86ISD::PEXTRB, dl, MVT::i32,
Op.getOperand(0), Op.getOperand(1));
@@ -6060,36 +6914,26 @@ X86TargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op,
SDValue Vec = Op.getOperand(0);
EVT VecVT = Vec.getValueType();
- // If this is a 256-bit vector result, first extract the 128-bit
- // vector and then extract from the 128-bit vector.
- if (VecVT.getSizeInBits() > 128) {
+ // If this is a 256-bit vector result, first extract the 128-bit vector and
+ // then extract the element from the 128-bit vector.
+ if (VecVT.getSizeInBits() == 256) {
DebugLoc dl = Op.getNode()->getDebugLoc();
unsigned NumElems = VecVT.getVectorNumElements();
SDValue Idx = Op.getOperand(1);
-
- if (!isa<ConstantSDNode>(Idx))
- return SDValue();
-
- unsigned ExtractNumElems = NumElems / (VecVT.getSizeInBits() / 128);
unsigned IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
// Get the 128-bit vector.
- bool Upper = IdxVal >= ExtractNumElems;
- Vec = Extract128BitVector(Vec, Idx, DAG, dl);
-
- // Extract from it.
- SDValue ScaledIdx = Idx;
- if (Upper)
- ScaledIdx = DAG.getNode(ISD::SUB, dl, Idx.getValueType(), Idx,
- DAG.getConstant(ExtractNumElems,
- Idx.getValueType()));
+ bool Upper = IdxVal >= NumElems/2;
+ Vec = Extract128BitVector(Vec,
+ DAG.getConstant(Upper ? NumElems/2 : 0, MVT::i32), DAG, dl);
+
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, Op.getValueType(), Vec,
- ScaledIdx);
+ Upper ? DAG.getConstant(IdxVal-NumElems/2, MVT::i32) : Idx);
}
assert(Vec.getValueSizeInBits() <= 128 && "Unexpected vector length");
- if (Subtarget->hasSSE41()) {
+ if (Subtarget->hasSSE41() || Subtarget->hasAVX()) {
SDValue Res = LowerEXTRACT_VECTOR_ELT_SSE4(Op, DAG);
if (Res.getNode())
return Res;
@@ -6120,7 +6964,7 @@ X86TargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op,
return Op;
// SHUFPS the element to the lowest double word, then movss.
- int Mask[4] = { Idx, -1, -1, -1 };
+ int Mask[4] = { static_cast<int>(Idx), -1, -1, -1 };
EVT VVT = Op.getOperand(0).getValueType();
SDValue Vec = DAG.getVectorShuffle(VVT, dl, Op.getOperand(0),
DAG.getUNDEF(VVT), Mask);
@@ -6159,6 +7003,9 @@ X86TargetLowering::LowerINSERT_VECTOR_ELT_SSE4(SDValue Op,
SDValue N1 = Op.getOperand(1);
SDValue N2 = Op.getOperand(2);
+ if (VT.getSizeInBits() == 256)
+ return SDValue();
+
if ((EltVT.getSizeInBits() == 8 || EltVT.getSizeInBits() == 16) &&
isa<ConstantSDNode>(N2)) {
unsigned Opc;
@@ -6206,35 +7053,28 @@ X86TargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const {
SDValue N1 = Op.getOperand(1);
SDValue N2 = Op.getOperand(2);
- // If this is a 256-bit vector result, first insert into a 128-bit
- // vector and then insert into the 256-bit vector.
- if (VT.getSizeInBits() > 128) {
+ // If this is a 256-bit vector result, first extract the 128-bit vector,
+ // insert the element into the extracted half and then place it back.
+ if (VT.getSizeInBits() == 256) {
if (!isa<ConstantSDNode>(N2))
return SDValue();
- // Get the 128-bit vector.
+ // Get the desired 128-bit vector half.
unsigned NumElems = VT.getVectorNumElements();
unsigned IdxVal = cast<ConstantSDNode>(N2)->getZExtValue();
- bool Upper = IdxVal >= NumElems / 2;
-
- SDValue SubN0 = Extract128BitVector(N0, N2, DAG, dl);
+ bool Upper = IdxVal >= NumElems/2;
+ SDValue Ins128Idx = DAG.getConstant(Upper ? NumElems/2 : 0, MVT::i32);
+ SDValue V = Extract128BitVector(N0, Ins128Idx, DAG, dl);
- // Insert into it.
- SDValue ScaledN2 = N2;
- if (Upper)
- ScaledN2 = DAG.getNode(ISD::SUB, dl, N2.getValueType(), N2,
- DAG.getConstant(NumElems /
- (VT.getSizeInBits() / 128),
- N2.getValueType()));
- Op = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, SubN0.getValueType(), SubN0,
- N1, ScaledN2);
+ // Insert the element into the desired half.
+ V = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, V.getValueType(), V,
+ N1, Upper ? DAG.getConstant(IdxVal-NumElems/2, MVT::i32) : N2);
- // Insert the 128-bit vector
- // FIXME: Why UNDEF?
- return Insert128BitVector(N0, Op, N2, DAG, dl);
+ // Insert the changed part back to the 256-bit vector
+ return Insert128BitVector(N0, V, Ins128Idx, DAG, dl);
}
- if (Subtarget->hasSSE41())
+ if (Subtarget->hasSSE41() || Subtarget->hasAVX())
return LowerINSERT_VECTOR_ELT_SSE4(Op, DAG);
if (EltVT == MVT::i8)
@@ -6405,12 +7245,17 @@ X86TargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const {
CodeModel::Model M = getTargetMachine().getCodeModel();
if (Subtarget->isPICStyleRIPRel() &&
- (M == CodeModel::Small || M == CodeModel::Kernel))
+ (M == CodeModel::Small || M == CodeModel::Kernel)) {
+ if (Subtarget->isTargetDarwin() || Subtarget->isTargetELF())
+ OpFlag = X86II::MO_GOTPCREL;
WrapperKind = X86ISD::WrapperRIP;
- else if (Subtarget->isPICStyleGOT())
- OpFlag = X86II::MO_GOTOFF;
- else if (Subtarget->isPICStyleStubPIC())
- OpFlag = X86II::MO_PIC_BASE_OFFSET;
+ } else if (Subtarget->isPICStyleGOT()) {
+ OpFlag = X86II::MO_GOT;
+ } else if (Subtarget->isPICStyleStubPIC()) {
+ OpFlag = X86II::MO_DARWIN_NONLAZY_PIC_BASE;
+ } else if (Subtarget->isPICStyleStubNoDynamic()) {
+ OpFlag = X86II::MO_DARWIN_NONLAZY;
+ }
SDValue Result = DAG.getTargetExternalSymbol(Sym, getPointerTy(), OpFlag);
@@ -6427,6 +7272,12 @@ X86TargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const {
Result);
}
+ // For symbols that require a load from a stub to get the address, emit the
+ // load.
+ if (isGlobalStubReference(OpFlag))
+ Result = DAG.getLoad(getPointerTy(), DL, DAG.getEntryNode(), Result,
+ MachinePointerInfo::getGOT(), false, false, 0);
+
return Result;
}
@@ -6676,7 +7527,8 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
// And our return value (tls address) is in the standard call return value
// location.
unsigned Reg = Subtarget->is64Bit() ? X86::RAX : X86::EAX;
- return DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy());
+ return DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(),
+ Chain.getValue(1));
}
assert(false &&
@@ -6922,9 +7774,11 @@ SDValue X86TargetLowering::LowerUINT_TO_FP_i32(SDValue Op,
// Load the 32-bit value into an XMM register.
SDValue Load = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v4i32,
- DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
- Op.getOperand(0),
- DAG.getIntPtrConstant(0)));
+ Op.getOperand(0));
+
+ // Zero out the upper parts of the register.
+ Load = getShuffleVectorZeroOrUndef(Load, 0, true, Subtarget->hasXMMInt(),
+ DAG);
Load = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64,
DAG.getNode(ISD::BITCAST, dl, MVT::v2f64, Load),
@@ -7513,6 +8367,9 @@ SDValue X86TargetLowering::LowerToBT(SDValue And, ISD::CondCode CC,
}
SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
+
+ if (Op.getValueType().isVector()) return LowerVSETCC(Op, DAG);
+
assert(Op.getValueType() == MVT::i8 && "SetCC type must be 8-bit integer");
SDValue Op0 = Op.getOperand(0);
SDValue Op1 = Op.getOperand(1);
@@ -7563,6 +8420,39 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
DAG.getConstant(X86CC, MVT::i8), EFLAGS);
}
+// Lower256IntVSETCC - Break a VSETCC 256-bit integer VSETCC into two new 128
+// ones, and then concatenate the result back.
+static SDValue Lower256IntVSETCC(SDValue Op, SelectionDAG &DAG) {
+ EVT VT = Op.getValueType();
+
+ assert(VT.getSizeInBits() == 256 && Op.getOpcode() == ISD::SETCC &&
+ "Unsupported value type for operation");
+
+ int NumElems = VT.getVectorNumElements();
+ DebugLoc dl = Op.getDebugLoc();
+ SDValue CC = Op.getOperand(2);
+ SDValue Idx0 = DAG.getConstant(0, MVT::i32);
+ SDValue Idx1 = DAG.getConstant(NumElems/2, MVT::i32);
+
+ // Extract the LHS vectors
+ SDValue LHS = Op.getOperand(0);
+ SDValue LHS1 = Extract128BitVector(LHS, Idx0, DAG, dl);
+ SDValue LHS2 = Extract128BitVector(LHS, Idx1, DAG, dl);
+
+ // Extract the RHS vectors
+ SDValue RHS = Op.getOperand(1);
+ SDValue RHS1 = Extract128BitVector(RHS, Idx0, DAG, dl);
+ SDValue RHS2 = Extract128BitVector(RHS, Idx1, DAG, dl);
+
+ // Issue the operation on the smaller types and concatenate the result back
+ MVT EltVT = VT.getVectorElementType().getSimpleVT();
+ EVT NewVT = MVT::getVectorVT(EltVT, NumElems/2);
+ return DAG.getNode(ISD::CONCAT_VECTORS, dl, VT,
+ DAG.getNode(Op.getOpcode(), dl, NewVT, LHS1, RHS1, CC),
+ DAG.getNode(Op.getOpcode(), dl, NewVT, LHS2, RHS2, CC));
+}
+
+
SDValue X86TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) const {
SDValue Cond;
SDValue Op0 = Op.getOperand(0);
@@ -7575,11 +8465,21 @@ SDValue X86TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) const {
if (isFP) {
unsigned SSECC = 8;
- EVT VT0 = Op0.getValueType();
- assert(VT0 == MVT::v4f32 || VT0 == MVT::v2f64);
- unsigned Opc = VT0 == MVT::v4f32 ? X86ISD::CMPPS : X86ISD::CMPPD;
+ EVT EltVT = Op0.getValueType().getVectorElementType();
+ assert(EltVT == MVT::f32 || EltVT == MVT::f64);
+
+ unsigned Opc = EltVT == MVT::f32 ? X86ISD::CMPPS : X86ISD::CMPPD;
bool Swap = false;
+ // SSE Condition code mapping:
+ // 0 - EQ
+ // 1 - LT
+ // 2 - LE
+ // 3 - UNORD
+ // 4 - NEQ
+ // 5 - NLT
+ // 6 - NLE
+ // 7 - ORD
switch (SetCCOpcode) {
default: break;
case ISD::SETOEQ:
@@ -7624,6 +8524,10 @@ SDValue X86TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) const {
return DAG.getNode(Opc, dl, VT, Op0, Op1, DAG.getConstant(SSECC, MVT::i8));
}
+ // Break 256-bit integer vector compare into smaller ones.
+ if (!isFP && VT.getSizeInBits() == 256)
+ return Lower256IntVSETCC(Op, DAG);
+
// We are handling one of the integer comparisons here. Since SSE only has
// GT and EQ comparisons for integer, swapping operands and multiple
// operations may be required for some comparisons.
@@ -7654,6 +8558,13 @@ SDValue X86TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) const {
if (Swap)
std::swap(Op0, Op1);
+ // Check that the operation in question is available (most are plain SSE2,
+ // but PCMPGTQ and PCMPEQQ have different requirements).
+ if (Opc == X86ISD::PCMPGTQ && !Subtarget->hasSSE42() && !Subtarget->hasAVX())
+ return SDValue();
+ if (Opc == X86ISD::PCMPEQQ && !Subtarget->hasSSE41() && !Subtarget->hasAVX())
+ return SDValue();
+
// Since SSE has no unsigned integer comparisons, we need to flip the sign
// bits of the inputs before performing those operations.
if (FlipSigns) {
@@ -8014,9 +8925,11 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
SDValue
X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
SelectionDAG &DAG) const {
- assert((Subtarget->isTargetCygMing() || Subtarget->isTargetWindows()) &&
- "This should be used only on Windows targets");
- assert(!Subtarget->isTargetEnvMacho());
+ assert((Subtarget->isTargetCygMing() || Subtarget->isTargetWindows() ||
+ EnableSegmentedStacks) &&
+ "This should be used only on Windows targets or when segmented stacks "
+ "are being used");
+ assert(!Subtarget->isTargetEnvMacho() && "Not implemented");
DebugLoc dl = Op.getDebugLoc();
// Get the inputs.
@@ -8024,23 +8937,49 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
SDValue Size = Op.getOperand(1);
// FIXME: Ensure alignment here
- SDValue Flag;
+ bool Is64Bit = Subtarget->is64Bit();
+ EVT SPTy = Is64Bit ? MVT::i64 : MVT::i32;
- EVT SPTy = Subtarget->is64Bit() ? MVT::i64 : MVT::i32;
- unsigned Reg = (Subtarget->is64Bit() ? X86::RAX : X86::EAX);
+ if (EnableSegmentedStacks) {
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
- Chain = DAG.getCopyToReg(Chain, dl, Reg, Size, Flag);
- Flag = Chain.getValue(1);
+ if (Is64Bit) {
+ // The 64 bit implementation of segmented stacks needs to clobber both r10
+ // r11. This makes it impossible to use it along with nested parameters.
+ const Function *F = MF.getFunction();
+
+ for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
+ I != E; I++)
+ if (I->hasNestAttr())
+ report_fatal_error("Cannot use segmented stacks with functions that "
+ "have nested arguments.");
+ }
+
+ const TargetRegisterClass *AddrRegClass =
+ getRegClassFor(Subtarget->is64Bit() ? MVT::i64:MVT::i32);
+ unsigned Vreg = MRI.createVirtualRegister(AddrRegClass);
+ Chain = DAG.getCopyToReg(Chain, dl, Vreg, Size);
+ SDValue Value = DAG.getNode(X86ISD::SEG_ALLOCA, dl, SPTy, Chain,
+ DAG.getRegister(Vreg, SPTy));
+ SDValue Ops1[2] = { Value, Chain };
+ return DAG.getMergeValues(Ops1, 2, dl);
+ } else {
+ SDValue Flag;
+ unsigned Reg = (Subtarget->is64Bit() ? X86::RAX : X86::EAX);
- SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
+ Chain = DAG.getCopyToReg(Chain, dl, Reg, Size, Flag);
+ Flag = Chain.getValue(1);
+ SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
- Chain = DAG.getNode(X86ISD::WIN_ALLOCA, dl, NodeTys, Chain, Flag);
- Flag = Chain.getValue(1);
+ Chain = DAG.getNode(X86ISD::WIN_ALLOCA, dl, NodeTys, Chain, Flag);
+ Flag = Chain.getValue(1);
- Chain = DAG.getCopyFromReg(Chain, dl, X86StackPtr, SPTy).getValue(1);
+ Chain = DAG.getCopyFromReg(Chain, dl, X86StackPtr, SPTy).getValue(1);
- SDValue Ops1[2] = { Chain.getValue(0), Chain };
- return DAG.getMergeValues(Ops1, 2, dl);
+ SDValue Ops1[2] = { Chain.getValue(0), Chain };
+ return DAG.getMergeValues(Ops1, 2, dl);
+ }
}
SDValue X86TargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
@@ -8118,7 +9057,7 @@ SDValue X86TargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG) const {
DebugLoc dl = Op.getDebugLoc();
EVT ArgVT = Op.getNode()->getValueType(0);
- const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext());
+ Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext());
uint32_t ArgSize = getTargetData()->getTypeAllocSize(ArgTy);
uint8_t ArgMode;
@@ -8292,6 +9231,19 @@ X86TargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const
DAG.getConstant(X86CC, MVT::i8), Cond);
return DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, SetCC);
}
+ // Arithmetic intrinsics.
+ case Intrinsic::x86_sse3_hadd_ps:
+ case Intrinsic::x86_sse3_hadd_pd:
+ case Intrinsic::x86_avx_hadd_ps_256:
+ case Intrinsic::x86_avx_hadd_pd_256:
+ return DAG.getNode(X86ISD::FHADD, dl, Op.getValueType(),
+ Op.getOperand(1), Op.getOperand(2));
+ case Intrinsic::x86_sse3_hsub_ps:
+ case Intrinsic::x86_sse3_hsub_pd:
+ case Intrinsic::x86_avx_hsub_ps_256:
+ case Intrinsic::x86_avx_hsub_pd_256:
+ return DAG.getNode(X86ISD::FHSUB, dl, Op.getValueType(),
+ Op.getOperand(1), Op.getOperand(2));
// ptest and testp intrinsics. The intrinsic these come from are designed to
// return an integer value, not just an instruction so lower it to the ptest
// or testp pattern and a setcc for the result.
@@ -8535,8 +9487,13 @@ SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
Chain, DAG.getRegister(StoreAddrReg, getPointerTy()));
}
-SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op,
- SelectionDAG &DAG) const {
+SDValue X86TargetLowering::LowerADJUST_TRAMPOLINE(SDValue Op,
+ SelectionDAG &DAG) const {
+ return Op.getOperand(0);
+}
+
+SDValue X86TargetLowering::LowerINIT_TRAMPOLINE(SDValue Op,
+ SelectionDAG &DAG) const {
SDValue Root = Op.getOperand(0);
SDValue Trmp = Op.getOperand(1); // trampoline
SDValue FPtr = Op.getOperand(2); // nested function
@@ -8552,8 +9509,8 @@ SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op,
const unsigned char JMP64r = 0xFF; // 64-bit jmp through register opcode.
const unsigned char MOV64ri = 0xB8; // X86::MOV64ri opcode.
- const unsigned char N86R10 = RegInfo->getX86RegNum(X86::R10);
- const unsigned char N86R11 = RegInfo->getX86RegNum(X86::R11);
+ const unsigned char N86R10 = X86_MC::getX86RegNum(X86::R10);
+ const unsigned char N86R11 = X86_MC::getX86RegNum(X86::R11);
const unsigned char REX_WB = 0x40 | 0x08 | 0x01; // REX prefix
@@ -8600,9 +9557,7 @@ SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op,
MachinePointerInfo(TrmpAddr, 22),
false, false, 0);
- SDValue Ops[] =
- { Trmp, DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 6) };
- return DAG.getMergeValues(Ops, 2, dl);
+ return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 6);
} else {
const Function *Func =
cast<Function>(cast<SrcValueSDNode>(Op.getOperand(5))->getValue());
@@ -8619,7 +9574,7 @@ SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op,
NestReg = X86::ECX;
// Check that ECX wasn't needed by an 'inreg' parameter.
- const FunctionType *FTy = Func->getFunctionType();
+ FunctionType *FTy = Func->getFunctionType();
const AttrListPtr &Attrs = Func->getAttributes();
if (!Attrs.isEmpty() && !Func->isVarArg()) {
@@ -8657,7 +9612,7 @@ SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op,
// This is storing the opcode for MOV32ri.
const unsigned char MOV32ri = 0xB8; // X86::MOV32ri's opcode byte.
- const unsigned char N86Reg = RegInfo->getX86RegNum(NestReg);
+ const unsigned char N86Reg = X86_MC::getX86RegNum(NestReg);
OutChains[0] = DAG.getStore(Root, dl,
DAG.getConstant(MOV32ri|N86Reg, MVT::i8),
Trmp, MachinePointerInfo(TrmpAddr),
@@ -8682,9 +9637,7 @@ SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op,
MachinePointerInfo(TrmpAddr, 6),
false, false, 1);
- SDValue Ops[] =
- { Trmp, DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 4) };
- return DAG.getMergeValues(Ops, 2, dl);
+ return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 4);
}
}
@@ -8822,8 +9775,58 @@ SDValue X86TargetLowering::LowerCTTZ(SDValue Op, SelectionDAG &DAG) const {
return Op;
}
-SDValue X86TargetLowering::LowerMUL_V2I64(SDValue Op, SelectionDAG &DAG) const {
+// Lower256IntArith - Break a 256-bit integer operation into two new 128-bit
+// ones, and then concatenate the result back.
+static SDValue Lower256IntArith(SDValue Op, SelectionDAG &DAG) {
+ EVT VT = Op.getValueType();
+
+ assert(VT.getSizeInBits() == 256 && VT.isInteger() &&
+ "Unsupported value type for operation");
+
+ int NumElems = VT.getVectorNumElements();
+ DebugLoc dl = Op.getDebugLoc();
+ SDValue Idx0 = DAG.getConstant(0, MVT::i32);
+ SDValue Idx1 = DAG.getConstant(NumElems/2, MVT::i32);
+
+ // Extract the LHS vectors
+ SDValue LHS = Op.getOperand(0);
+ SDValue LHS1 = Extract128BitVector(LHS, Idx0, DAG, dl);
+ SDValue LHS2 = Extract128BitVector(LHS, Idx1, DAG, dl);
+
+ // Extract the RHS vectors
+ SDValue RHS = Op.getOperand(1);
+ SDValue RHS1 = Extract128BitVector(RHS, Idx0, DAG, dl);
+ SDValue RHS2 = Extract128BitVector(RHS, Idx1, DAG, dl);
+
+ MVT EltVT = VT.getVectorElementType().getSimpleVT();
+ EVT NewVT = MVT::getVectorVT(EltVT, NumElems/2);
+
+ return DAG.getNode(ISD::CONCAT_VECTORS, dl, VT,
+ DAG.getNode(Op.getOpcode(), dl, NewVT, LHS1, RHS1),
+ DAG.getNode(Op.getOpcode(), dl, NewVT, LHS2, RHS2));
+}
+
+SDValue X86TargetLowering::LowerADD(SDValue Op, SelectionDAG &DAG) const {
+ assert(Op.getValueType().getSizeInBits() == 256 &&
+ Op.getValueType().isInteger() &&
+ "Only handle AVX 256-bit vector integer operation");
+ return Lower256IntArith(Op, DAG);
+}
+
+SDValue X86TargetLowering::LowerSUB(SDValue Op, SelectionDAG &DAG) const {
+ assert(Op.getValueType().getSizeInBits() == 256 &&
+ Op.getValueType().isInteger() &&
+ "Only handle AVX 256-bit vector integer operation");
+ return Lower256IntArith(Op, DAG);
+}
+
+SDValue X86TargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
EVT VT = Op.getValueType();
+
+ // Decompose 256-bit ops into smaller 128-bit ops.
+ if (VT.getSizeInBits() == 256)
+ return Lower256IntArith(Op, DAG);
+
assert(VT == MVT::v2i64 && "Only know how to lower V2I64 multiply");
DebugLoc dl = Op.getDebugLoc();
@@ -8872,11 +9875,51 @@ SDValue X86TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) const {
DebugLoc dl = Op.getDebugLoc();
SDValue R = Op.getOperand(0);
SDValue Amt = Op.getOperand(1);
-
LLVMContext *Context = DAG.getContext();
- // Must have SSE2.
- if (!Subtarget->hasSSE2()) return SDValue();
+ if (!Subtarget->hasXMMInt())
+ return SDValue();
+
+ // Decompose 256-bit shifts into smaller 128-bit shifts.
+ if (VT.getSizeInBits() == 256) {
+ int NumElems = VT.getVectorNumElements();
+ MVT EltVT = VT.getVectorElementType().getSimpleVT();
+ EVT NewVT = MVT::getVectorVT(EltVT, NumElems/2);
+
+ // Extract the two vectors
+ SDValue V1 = Extract128BitVector(R, DAG.getConstant(0, MVT::i32), DAG, dl);
+ SDValue V2 = Extract128BitVector(R, DAG.getConstant(NumElems/2, MVT::i32),
+ DAG, dl);
+
+ // Recreate the shift amount vectors
+ SDValue Amt1, Amt2;
+ if (Amt.getOpcode() == ISD::BUILD_VECTOR) {
+ // Constant shift amount
+ SmallVector<SDValue, 4> Amt1Csts;
+ SmallVector<SDValue, 4> Amt2Csts;
+ for (int i = 0; i < NumElems/2; ++i)
+ Amt1Csts.push_back(Amt->getOperand(i));
+ for (int i = NumElems/2; i < NumElems; ++i)
+ Amt2Csts.push_back(Amt->getOperand(i));
+
+ Amt1 = DAG.getNode(ISD::BUILD_VECTOR, dl, NewVT,
+ &Amt1Csts[0], NumElems/2);
+ Amt2 = DAG.getNode(ISD::BUILD_VECTOR, dl, NewVT,
+ &Amt2Csts[0], NumElems/2);
+ } else {
+ // Variable shift amount
+ Amt1 = Extract128BitVector(Amt, DAG.getConstant(0, MVT::i32), DAG, dl);
+ Amt2 = Extract128BitVector(Amt, DAG.getConstant(NumElems/2, MVT::i32),
+ DAG, dl);
+ }
+
+ // Issue new vector shifts for the smaller types
+ V1 = DAG.getNode(Op.getOpcode(), dl, NewVT, V1, Amt1);
+ V2 = DAG.getNode(Op.getOpcode(), dl, NewVT, V2, Amt2);
+
+ // Concatenate the result back
+ return DAG.getNode(ISD::CONCAT_VECTORS, dl, VT, V1, V2);
+ }
// Optimize shl/srl/sra with constant shift amount.
if (isSplatVector(Amt.getNode())) {
@@ -8927,9 +9970,6 @@ SDValue X86TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) const {
}
// Lower SHL with variable shift amount.
- // Cannot lower SHL without SSE2 or later.
- if (!Subtarget->hasSSE2()) return SDValue();
-
if (VT == MVT::v4i32 && Op->getOpcode() == ISD::SHL) {
Op = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT,
DAG.getConstant(Intrinsic::x86_sse2_pslli_d, MVT::i32),
@@ -8971,7 +10011,7 @@ SDValue X86TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) const {
M = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT,
DAG.getConstant(Intrinsic::x86_sse2_pslli_w, MVT::i32), M,
DAG.getConstant(4, MVT::i32));
- R = DAG.getNode(X86ISD::PBLENDVB, dl, VT, R, M, Op);
+ R = DAG.getNode(ISD::VSELECT, dl, VT, Op, R, M);
// a += a
Op = DAG.getNode(ISD::ADD, dl, VT, Op, Op);
@@ -8986,13 +10026,13 @@ SDValue X86TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) const {
M = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT,
DAG.getConstant(Intrinsic::x86_sse2_pslli_w, MVT::i32), M,
DAG.getConstant(2, MVT::i32));
- R = DAG.getNode(X86ISD::PBLENDVB, dl, VT, R, M, Op);
+ R = DAG.getNode(ISD::VSELECT, dl, VT, Op, R, M);
// a += a
Op = DAG.getNode(ISD::ADD, dl, VT, Op, Op);
// return pblendv(r, r+r, a);
- R = DAG.getNode(X86ISD::PBLENDVB, dl, VT,
- R, DAG.getNode(ISD::ADD, dl, VT, R, R), Op);
+ R = DAG.getNode(ISD::VSELECT, dl, VT, Op,
+ R, DAG.getNode(ISD::ADD, dl, VT, R, R));
return R;
}
return SDValue();
@@ -9057,8 +10097,7 @@ SDValue X86TargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const {
DAG.getConstant(X86::COND_O, MVT::i32),
SDValue(Sum.getNode(), 2));
- DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), SetCC);
- return Sum;
+ return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Sum, SetCC);
}
}
@@ -9071,8 +10110,7 @@ SDValue X86TargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const {
DAG.getConstant(Cond, MVT::i32),
SDValue(Sum.getNode(), 1));
- DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), SetCC);
- return Sum;
+ return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Sum, SetCC);
}
SDValue X86TargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const{
@@ -9080,8 +10118,7 @@ SDValue X86TargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG)
SDNode* Node = Op.getNode();
EVT ExtraVT = cast<VTSDNode>(Node->getOperand(1))->getVT();
EVT VT = Node->getValueType(0);
-
- if (Subtarget->hasSSE2() && VT.isVector()) {
+ if (Subtarget->hasXMMInt() && VT.isVector()) {
unsigned BitsDiff = VT.getScalarType().getSizeInBits() -
ExtraVT.getScalarType().getSizeInBits();
SDValue ShAmt = DAG.getConstant(BitsDiff, MVT::i32);
@@ -9091,11 +10128,6 @@ SDValue X86TargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG)
switch (VT.getSimpleVT().SimpleTy) {
default:
return SDValue();
- case MVT::v2i64: {
- SHLIntrinsicsID = Intrinsic::x86_sse2_pslli_q;
- SRAIntrinsicsID = 0;
- break;
- }
case MVT::v4i32: {
SHLIntrinsicsID = Intrinsic::x86_sse2_pslli_d;
SRAIntrinsicsID = Intrinsic::x86_sse2_psrai_d;
@@ -9115,12 +10147,9 @@ SDValue X86TargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG)
// In case of 1 bit sext, no need to shr
if (ExtraVT.getScalarType().getSizeInBits() == 1) return Tmp1;
- if (SRAIntrinsicsID) {
- Tmp1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT,
- DAG.getConstant(SRAIntrinsicsID, MVT::i32),
- Tmp1, ShAmt);
- }
- return Tmp1;
+ return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT,
+ DAG.getConstant(SRAIntrinsicsID, MVT::i32),
+ Tmp1, ShAmt);
}
return SDValue();
@@ -9132,7 +10161,7 @@ SDValue X86TargetLowering::LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) const{
// Go ahead and emit the fence on x86-64 even if we asked for no-sse2.
// There isn't any reason to disable it if the target processor supports it.
- if (!Subtarget->hasSSE2() && !Subtarget->is64Bit()) {
+ if (!Subtarget->hasXMMInt() && !Subtarget->is64Bit()) {
SDValue Chain = Op.getOperand(0);
SDValue Zero = DAG.getConstant(0, MVT::i32);
SDValue Ops[] = {
@@ -9172,6 +10201,45 @@ SDValue X86TargetLowering::LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) const{
return DAG.getNode(X86ISD::MFENCE, dl, MVT::Other, Op.getOperand(0));
}
+SDValue X86TargetLowering::LowerATOMIC_FENCE(SDValue Op,
+ SelectionDAG &DAG) const {
+ DebugLoc dl = Op.getDebugLoc();
+ AtomicOrdering FenceOrdering = static_cast<AtomicOrdering>(
+ cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue());
+ SynchronizationScope FenceScope = static_cast<SynchronizationScope>(
+ cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue());
+
+ // The only fence that needs an instruction is a sequentially-consistent
+ // cross-thread fence.
+ if (FenceOrdering == SequentiallyConsistent && FenceScope == CrossThread) {
+ // Use mfence if we have SSE2 or we're on x86-64 (even if we asked for
+ // no-sse2). There isn't any reason to disable it if the target processor
+ // supports it.
+ if (Subtarget->hasXMMInt() || Subtarget->is64Bit())
+ return DAG.getNode(X86ISD::MFENCE, dl, MVT::Other, Op.getOperand(0));
+
+ SDValue Chain = Op.getOperand(0);
+ SDValue Zero = DAG.getConstant(0, MVT::i32);
+ SDValue Ops[] = {
+ DAG.getRegister(X86::ESP, MVT::i32), // Base
+ DAG.getTargetConstant(1, MVT::i8), // Scale
+ DAG.getRegister(0, MVT::i32), // Index
+ DAG.getTargetConstant(0, MVT::i32), // Disp
+ DAG.getRegister(0, MVT::i32), // Segment.
+ Zero,
+ Chain
+ };
+ SDNode *Res =
+ DAG.getMachineNode(X86::OR32mrLocked, dl, MVT::Other, Ops,
+ array_lengthof(Ops));
+ return SDValue(Res, 0);
+ }
+
+ // MEMBARRIER is a compiler barrier; it codegens to a no-op.
+ return DAG.getNode(X86ISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0));
+}
+
+
SDValue X86TargetLowering::LowerCMP_SWAP(SDValue Op, SelectionDAG &DAG) const {
EVT T = Op.getValueType();
DebugLoc DL = Op.getDebugLoc();
@@ -9227,7 +10295,7 @@ SDValue X86TargetLowering::LowerBITCAST(SDValue Op,
SelectionDAG &DAG) const {
EVT SrcVT = Op.getOperand(0).getValueType();
EVT DstVT = Op.getValueType();
- assert(Subtarget->is64Bit() && !Subtarget->hasSSE2() &&
+ assert(Subtarget->is64Bit() && !Subtarget->hasXMMInt() &&
Subtarget->hasMMX() && "Unexpected custom BITCAST");
assert((DstVT == MVT::i64 ||
(DstVT.isVector() && DstVT.getSizeInBits()==64)) &&
@@ -9255,7 +10323,34 @@ SDValue X86TargetLowering::LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG) const {
Node->getOperand(0),
Node->getOperand(1), negOp,
cast<AtomicSDNode>(Node)->getSrcValue(),
- cast<AtomicSDNode>(Node)->getAlignment());
+ cast<AtomicSDNode>(Node)->getAlignment(),
+ cast<AtomicSDNode>(Node)->getOrdering(),
+ cast<AtomicSDNode>(Node)->getSynchScope());
+}
+
+static SDValue LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) {
+ SDNode *Node = Op.getNode();
+ DebugLoc dl = Node->getDebugLoc();
+ EVT VT = cast<AtomicSDNode>(Node)->getMemoryVT();
+
+ // Convert seq_cst store -> xchg
+ // Convert wide store -> swap (-> cmpxchg8b/cmpxchg16b)
+ // FIXME: On 32-bit, store -> fist or movq would be more efficient
+ // (The only way to get a 16-byte store is cmpxchg16b)
+ // FIXME: 16-byte ATOMIC_SWAP isn't actually hooked up at the moment.
+ if (cast<AtomicSDNode>(Node)->getOrdering() == SequentiallyConsistent ||
+ !DAG.getTargetLoweringInfo().isTypeLegal(VT)) {
+ SDValue Swap = DAG.getAtomic(ISD::ATOMIC_SWAP, dl,
+ cast<AtomicSDNode>(Node)->getMemoryVT(),
+ Node->getOperand(0),
+ Node->getOperand(1), Node->getOperand(2),
+ cast<AtomicSDNode>(Node)->getMemOperand(),
+ cast<AtomicSDNode>(Node)->getOrdering(),
+ cast<AtomicSDNode>(Node)->getSynchScope());
+ return Swap.getValue(1);
+ }
+ // Other atomic stores have a simple pattern.
+ return Op;
}
static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) {
@@ -9291,8 +10386,10 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
default: llvm_unreachable("Should not custom lower this!");
case ISD::SIGN_EXTEND_INREG: return LowerSIGN_EXTEND_INREG(Op,DAG);
case ISD::MEMBARRIER: return LowerMEMBARRIER(Op,DAG);
+ case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op,DAG);
case ISD::ATOMIC_CMP_SWAP: return LowerCMP_SWAP(Op,DAG);
case ISD::ATOMIC_LOAD_SUB: return LowerLOAD_SUB(Op,DAG);
+ case ISD::ATOMIC_STORE: return LowerATOMIC_STORE(Op,DAG);
case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG);
case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
@@ -9318,7 +10415,6 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
case ISD::FGETSIGN: return LowerFGETSIGN(Op, DAG);
case ISD::SETCC: return LowerSETCC(Op, DAG);
- case ISD::VSETCC: return LowerVSETCC(Op, DAG);
case ISD::SELECT: return LowerSELECT(Op, DAG);
case ISD::BRCOND: return LowerBRCOND(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
@@ -9332,11 +10428,12 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
- case ISD::TRAMPOLINE: return LowerTRAMPOLINE(Op, DAG);
+ case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG);
+ case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG);
case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG);
case ISD::CTLZ: return LowerCTLZ(Op, DAG);
case ISD::CTTZ: return LowerCTTZ(Op, DAG);
- case ISD::MUL: return LowerMUL_V2I64(Op, DAG);
+ case ISD::MUL: return LowerMUL(Op, DAG);
case ISD::SRA:
case ISD::SRL:
case ISD::SHL: return LowerShift(Op, DAG);
@@ -9352,15 +10449,38 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::ADDE:
case ISD::SUBC:
case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
+ case ISD::ADD: return LowerADD(Op, DAG);
+ case ISD::SUB: return LowerSUB(Op, DAG);
}
}
+static void ReplaceATOMIC_LOAD(SDNode *Node,
+ SmallVectorImpl<SDValue> &Results,
+ SelectionDAG &DAG) {
+ DebugLoc dl = Node->getDebugLoc();
+ EVT VT = cast<AtomicSDNode>(Node)->getMemoryVT();
+
+ // Convert wide load -> cmpxchg8b/cmpxchg16b
+ // FIXME: On 32-bit, load -> fild or movq would be more efficient
+ // (The only way to get a 16-byte load is cmpxchg16b)
+ // FIXME: 16-byte ATOMIC_CMP_SWAP isn't actually hooked up at the moment.
+ SDValue Zero = DAG.getConstant(0, VT);
+ SDValue Swap = DAG.getAtomic(ISD::ATOMIC_CMP_SWAP, dl, VT,
+ Node->getOperand(0),
+ Node->getOperand(1), Zero, Zero,
+ cast<AtomicSDNode>(Node)->getMemOperand(),
+ cast<AtomicSDNode>(Node)->getOrdering(),
+ cast<AtomicSDNode>(Node)->getSynchScope());
+ Results.push_back(Swap.getValue(0));
+ Results.push_back(Swap.getValue(1));
+}
+
void X86TargetLowering::
ReplaceATOMIC_BINARY_64(SDNode *Node, SmallVectorImpl<SDValue>&Results,
SelectionDAG &DAG, unsigned NewOp) const {
- EVT T = Node->getValueType(0);
DebugLoc dl = Node->getDebugLoc();
- assert (T == MVT::i64 && "Only know how to expand i64 atomics");
+ assert (Node->getValueType(0) == MVT::i64 &&
+ "Only know how to expand i64 atomics");
SDValue Chain = Node->getOperand(0);
SDValue In1 = Node->getOperand(1);
@@ -9423,37 +10543,48 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N,
}
case ISD::ATOMIC_CMP_SWAP: {
EVT T = N->getValueType(0);
- assert (T == MVT::i64 && "Only know how to expand i64 Cmp and Swap");
+ assert((T == MVT::i64 || T == MVT::i128) && "can only expand cmpxchg pair");
+ bool Regs64bit = T == MVT::i128;
+ EVT HalfT = Regs64bit ? MVT::i64 : MVT::i32;
SDValue cpInL, cpInH;
- cpInL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(2),
- DAG.getConstant(0, MVT::i32));
- cpInH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(2),
- DAG.getConstant(1, MVT::i32));
- cpInL = DAG.getCopyToReg(N->getOperand(0), dl, X86::EAX, cpInL, SDValue());
- cpInH = DAG.getCopyToReg(cpInL.getValue(0), dl, X86::EDX, cpInH,
- cpInL.getValue(1));
+ cpInL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, HalfT, N->getOperand(2),
+ DAG.getConstant(0, HalfT));
+ cpInH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, HalfT, N->getOperand(2),
+ DAG.getConstant(1, HalfT));
+ cpInL = DAG.getCopyToReg(N->getOperand(0), dl,
+ Regs64bit ? X86::RAX : X86::EAX,
+ cpInL, SDValue());
+ cpInH = DAG.getCopyToReg(cpInL.getValue(0), dl,
+ Regs64bit ? X86::RDX : X86::EDX,
+ cpInH, cpInL.getValue(1));
SDValue swapInL, swapInH;
- swapInL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(3),
- DAG.getConstant(0, MVT::i32));
- swapInH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(3),
- DAG.getConstant(1, MVT::i32));
- swapInL = DAG.getCopyToReg(cpInH.getValue(0), dl, X86::EBX, swapInL,
- cpInH.getValue(1));
- swapInH = DAG.getCopyToReg(swapInL.getValue(0), dl, X86::ECX, swapInH,
- swapInL.getValue(1));
+ swapInL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, HalfT, N->getOperand(3),
+ DAG.getConstant(0, HalfT));
+ swapInH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, HalfT, N->getOperand(3),
+ DAG.getConstant(1, HalfT));
+ swapInL = DAG.getCopyToReg(cpInH.getValue(0), dl,
+ Regs64bit ? X86::RBX : X86::EBX,
+ swapInL, cpInH.getValue(1));
+ swapInH = DAG.getCopyToReg(swapInL.getValue(0), dl,
+ Regs64bit ? X86::RCX : X86::ECX,
+ swapInH, swapInL.getValue(1));
SDValue Ops[] = { swapInH.getValue(0),
N->getOperand(1),
swapInH.getValue(1) };
SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue);
MachineMemOperand *MMO = cast<AtomicSDNode>(N)->getMemOperand();
- SDValue Result = DAG.getMemIntrinsicNode(X86ISD::LCMPXCHG8_DAG, dl, Tys,
+ unsigned Opcode = Regs64bit ? X86ISD::LCMPXCHG16_DAG :
+ X86ISD::LCMPXCHG8_DAG;
+ SDValue Result = DAG.getMemIntrinsicNode(Opcode, dl, Tys,
Ops, 3, T, MMO);
- SDValue cpOutL = DAG.getCopyFromReg(Result.getValue(0), dl, X86::EAX,
- MVT::i32, Result.getValue(1));
- SDValue cpOutH = DAG.getCopyFromReg(cpOutL.getValue(1), dl, X86::EDX,
- MVT::i32, cpOutL.getValue(2));
+ SDValue cpOutL = DAG.getCopyFromReg(Result.getValue(0), dl,
+ Regs64bit ? X86::RAX : X86::EAX,
+ HalfT, Result.getValue(1));
+ SDValue cpOutH = DAG.getCopyFromReg(cpOutL.getValue(1), dl,
+ Regs64bit ? X86::RDX : X86::EDX,
+ HalfT, cpOutL.getValue(2));
SDValue OpsF[] = { cpOutL.getValue(0), cpOutH.getValue(0)};
- Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, OpsF, 2));
+ Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, T, OpsF, 2));
Results.push_back(cpOutH.getValue(1));
return;
}
@@ -9478,6 +10609,8 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N,
case ISD::ATOMIC_SWAP:
ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMSWAP64_DAG);
return;
+ case ISD::ATOMIC_LOAD:
+ ReplaceATOMIC_LOAD(N, Results, DAG);
}
}
@@ -9527,11 +10660,12 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::PSIGNB: return "X86ISD::PSIGNB";
case X86ISD::PSIGNW: return "X86ISD::PSIGNW";
case X86ISD::PSIGND: return "X86ISD::PSIGND";
- case X86ISD::PBLENDVB: return "X86ISD::PBLENDVB";
case X86ISD::FMAX: return "X86ISD::FMAX";
case X86ISD::FMIN: return "X86ISD::FMIN";
case X86ISD::FRSQRT: return "X86ISD::FRSQRT";
case X86ISD::FRCP: return "X86ISD::FRCP";
+ case X86ISD::FHADD: return "X86ISD::FHADD";
+ case X86ISD::FHSUB: return "X86ISD::FHSUB";
case X86ISD::TLSADDR: return "X86ISD::TLSADDR";
case X86ISD::TLSCALL: return "X86ISD::TLSCALL";
case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN";
@@ -9570,6 +10704,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::OR: return "X86ISD::OR";
case X86ISD::XOR: return "X86ISD::XOR";
case X86ISD::AND: return "X86ISD::AND";
+ case X86ISD::ANDN: return "X86ISD::ANDN";
case X86ISD::MUL_IMM: return "X86ISD::MUL_IMM";
case X86ISD::PTEST: return "X86ISD::PTEST";
case X86ISD::TESTP: return "X86ISD::TESTP";
@@ -9596,9 +10731,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::MOVSS: return "X86ISD::MOVSS";
case X86ISD::UNPCKLPS: return "X86ISD::UNPCKLPS";
case X86ISD::UNPCKLPD: return "X86ISD::UNPCKLPD";
- case X86ISD::VUNPCKLPS: return "X86ISD::VUNPCKLPS";
- case X86ISD::VUNPCKLPD: return "X86ISD::VUNPCKLPD";
- case X86ISD::VUNPCKLPSY: return "X86ISD::VUNPCKLPSY";
case X86ISD::VUNPCKLPDY: return "X86ISD::VUNPCKLPDY";
case X86ISD::UNPCKHPS: return "X86ISD::UNPCKHPS";
case X86ISD::UNPCKHPD: return "X86ISD::UNPCKHPD";
@@ -9610,16 +10742,24 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::PUNPCKHWD: return "X86ISD::PUNPCKHWD";
case X86ISD::PUNPCKHDQ: return "X86ISD::PUNPCKHDQ";
case X86ISD::PUNPCKHQDQ: return "X86ISD::PUNPCKHQDQ";
+ case X86ISD::VBROADCAST: return "X86ISD::VBROADCAST";
+ case X86ISD::VPERMILPS: return "X86ISD::VPERMILPS";
+ case X86ISD::VPERMILPSY: return "X86ISD::VPERMILPSY";
+ case X86ISD::VPERMILPD: return "X86ISD::VPERMILPD";
+ case X86ISD::VPERMILPDY: return "X86ISD::VPERMILPDY";
+ case X86ISD::VPERM2F128: return "X86ISD::VPERM2F128";
case X86ISD::VASTART_SAVE_XMM_REGS: return "X86ISD::VASTART_SAVE_XMM_REGS";
case X86ISD::VAARG_64: return "X86ISD::VAARG_64";
case X86ISD::WIN_ALLOCA: return "X86ISD::WIN_ALLOCA";
+ case X86ISD::MEMBARRIER: return "X86ISD::MEMBARRIER";
+ case X86ISD::SEG_ALLOCA: return "X86ISD::SEG_ALLOCA";
}
}
// isLegalAddressingMode - Return true if the addressing mode represented
// by AM is legal for this target, for a load/store of the specified type.
bool X86TargetLowering::isLegalAddressingMode(const AddrMode &AM,
- const Type *Ty) const {
+ Type *Ty) const {
// X86 supports extremely general addressing modes.
CodeModel::Model M = getTargetMachine().getCodeModel();
Reloc::Model R = getTargetMachine().getRelocationModel();
@@ -9671,7 +10811,7 @@ bool X86TargetLowering::isLegalAddressingMode(const AddrMode &AM,
}
-bool X86TargetLowering::isTruncateFree(const Type *Ty1, const Type *Ty2) const {
+bool X86TargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const {
if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
return false;
unsigned NumBits1 = Ty1->getPrimitiveSizeInBits();
@@ -9691,7 +10831,7 @@ bool X86TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {
return true;
}
-bool X86TargetLowering::isZExtFree(const Type *Ty1, const Type *Ty2) const {
+bool X86TargetLowering::isZExtFree(Type *Ty1, Type *Ty2) const {
// x86-64 implicitly zero-extends 32-bit results in 64-bit registers.
return Ty1->isIntegerTy(32) && Ty2->isIntegerTy(64) && Subtarget->is64Bit();
}
@@ -9715,7 +10855,7 @@ X86TargetLowering::isShuffleMaskLegal(const SmallVectorImpl<int> &M,
EVT VT) const {
// Very little shuffling can be done for 64-bit vectors right now.
if (VT.getSizeInBits() == 64)
- return isPALIGNRMask(M, VT, Subtarget->hasSSSE3());
+ return isPALIGNRMask(M, VT, Subtarget->hasSSSE3() || Subtarget->hasAVX());
// FIXME: pshufb, blends, shifts.
return (VT.getVectorNumElements() == 2 ||
@@ -9725,7 +10865,7 @@ X86TargetLowering::isShuffleMaskLegal(const SmallVectorImpl<int> &M,
isPSHUFDMask(M, VT) ||
isPSHUFHWMask(M, VT) ||
isPSHUFLWMask(M, VT) ||
- isPALIGNRMask(M, VT, Subtarget->hasSSSE3()) ||
+ isPALIGNRMask(M, VT, Subtarget->hasSSSE3() || Subtarget->hasAVX()) ||
isUNPCKLMask(M, VT) ||
isUNPCKHMask(M, VT) ||
isUNPCKL_v_undef_Mask(M, VT) ||
@@ -10158,7 +11298,9 @@ X86TargetLowering::EmitPCMP(MachineInstr *MI, MachineBasicBlock *BB,
if (!(Op.isReg() && Op.isImplicit()))
MIB.addOperand(Op);
}
- BuildMI(*BB, MI, dl, TII->get(X86::MOVAPSrr), MI->getOperand(0).getReg())
+ BuildMI(*BB, MI, dl,
+ TII->get(Subtarget->hasAVX() ? X86::VMOVAPSrr : X86::MOVAPSrr),
+ MI->getOperand(0).getReg())
.addReg(X86::XMM0);
MI->eraseFromParent();
@@ -10513,6 +11655,7 @@ X86TargetLowering::EmitVAStartSaveXMMRegsWithCustomInserter(
MBB->addSuccessor(EndMBB);
}
+ unsigned MOVOpc = Subtarget->hasAVX() ? X86::VMOVAPSmr : X86::MOVAPSmr;
// In the XMM save block, save all the XMM argument registers.
for (int i = 3, e = MI->getNumOperands(); i != e; ++i) {
int64_t Offset = (i - 3) * 16 + VarArgsFPOffset;
@@ -10521,7 +11664,7 @@ X86TargetLowering::EmitVAStartSaveXMMRegsWithCustomInserter(
MachinePointerInfo::getFixedStack(RegSaveFrameIndex, Offset),
MachineMemOperand::MOStore,
/*Size=*/16, /*Align=*/16);
- BuildMI(XMMSaveMBB, DL, TII->get(X86::MOVAPSmr))
+ BuildMI(XMMSaveMBB, DL, TII->get(MOVOpc))
.addFrameIndex(RegSaveFrameIndex)
.addImm(/*Scale=*/1)
.addReg(/*IndexReg=*/0)
@@ -10565,17 +11708,9 @@ X86TargetLowering::EmitLoweredSelect(MachineInstr *MI,
// If the EFLAGS register isn't dead in the terminator, then claim that it's
// live into the sink and copy blocks.
- const MachineFunction *MF = BB->getParent();
- const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo();
- BitVector ReservedRegs = TRI->getReservedRegs(*MF);
-
- for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
- const MachineOperand &MO = MI->getOperand(I);
- if (!MO.isReg() || !MO.isUse() || MO.isKill()) continue;
- unsigned Reg = MO.getReg();
- if (Reg != X86::EFLAGS) continue;
- copy0MBB->addLiveIn(Reg);
- sinkMBB->addLiveIn(Reg);
+ if (!MI->killsRegister(X86::EFLAGS)) {
+ copy0MBB->addLiveIn(X86::EFLAGS);
+ sinkMBB->addLiveIn(X86::EFLAGS);
}
// Transfer the remainder of BB and its successor edges to sinkMBB.
@@ -10611,6 +11746,119 @@ X86TargetLowering::EmitLoweredSelect(MachineInstr *MI,
}
MachineBasicBlock *
+X86TargetLowering::EmitLoweredSegAlloca(MachineInstr *MI, MachineBasicBlock *BB,
+ bool Is64Bit) const {
+ const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
+ DebugLoc DL = MI->getDebugLoc();
+ MachineFunction *MF = BB->getParent();
+ const BasicBlock *LLVM_BB = BB->getBasicBlock();
+
+ assert(EnableSegmentedStacks);
+
+ unsigned TlsReg = Is64Bit ? X86::FS : X86::GS;
+ unsigned TlsOffset = Is64Bit ? 0x70 : 0x30;
+
+ // BB:
+ // ... [Till the alloca]
+ // If stacklet is not large enough, jump to mallocMBB
+ //
+ // bumpMBB:
+ // Allocate by subtracting from RSP
+ // Jump to continueMBB
+ //
+ // mallocMBB:
+ // Allocate by call to runtime
+ //
+ // continueMBB:
+ // ...
+ // [rest of original BB]
+ //
+
+ MachineBasicBlock *mallocMBB = MF->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *bumpMBB = MF->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *continueMBB = MF->CreateMachineBasicBlock(LLVM_BB);
+
+ MachineRegisterInfo &MRI = MF->getRegInfo();
+ const TargetRegisterClass *AddrRegClass =
+ getRegClassFor(Is64Bit ? MVT::i64:MVT::i32);
+
+ unsigned mallocPtrVReg = MRI.createVirtualRegister(AddrRegClass),
+ bumpSPPtrVReg = MRI.createVirtualRegister(AddrRegClass),
+ tmpSPVReg = MRI.createVirtualRegister(AddrRegClass),
+ sizeVReg = MI->getOperand(1).getReg(),
+ physSPReg = Is64Bit ? X86::RSP : X86::ESP;
+
+ MachineFunction::iterator MBBIter = BB;
+ ++MBBIter;
+
+ MF->insert(MBBIter, bumpMBB);
+ MF->insert(MBBIter, mallocMBB);
+ MF->insert(MBBIter, continueMBB);
+
+ continueMBB->splice(continueMBB->begin(), BB, llvm::next
+ (MachineBasicBlock::iterator(MI)), BB->end());
+ continueMBB->transferSuccessorsAndUpdatePHIs(BB);
+
+ // Add code to the main basic block to check if the stack limit has been hit,
+ // and if so, jump to mallocMBB otherwise to bumpMBB.
+ BuildMI(BB, DL, TII->get(TargetOpcode::COPY), tmpSPVReg).addReg(physSPReg);
+ BuildMI(BB, DL, TII->get(Is64Bit ? X86::SUB64rr:X86::SUB32rr), tmpSPVReg)
+ .addReg(tmpSPVReg).addReg(sizeVReg);
+ BuildMI(BB, DL, TII->get(Is64Bit ? X86::CMP64mr:X86::CMP32mr))
+ .addReg(0).addImm(0).addReg(0).addImm(TlsOffset).addReg(TlsReg)
+ .addReg(tmpSPVReg);
+ BuildMI(BB, DL, TII->get(X86::JG_4)).addMBB(mallocMBB);
+
+ // bumpMBB simply decreases the stack pointer, since we know the current
+ // stacklet has enough space.
+ BuildMI(bumpMBB, DL, TII->get(TargetOpcode::COPY), physSPReg)
+ .addReg(tmpSPVReg);
+ BuildMI(bumpMBB, DL, TII->get(TargetOpcode::COPY), bumpSPPtrVReg)
+ .addReg(tmpSPVReg);
+ BuildMI(bumpMBB, DL, TII->get(X86::JMP_4)).addMBB(continueMBB);
+
+ // Calls into a routine in libgcc to allocate more space from the heap.
+ if (Is64Bit) {
+ BuildMI(mallocMBB, DL, TII->get(X86::MOV64rr), X86::RDI)
+ .addReg(sizeVReg);
+ BuildMI(mallocMBB, DL, TII->get(X86::CALL64pcrel32))
+ .addExternalSymbol("__morestack_allocate_stack_space").addReg(X86::RDI);
+ } else {
+ BuildMI(mallocMBB, DL, TII->get(X86::SUB32ri), physSPReg).addReg(physSPReg)
+ .addImm(12);
+ BuildMI(mallocMBB, DL, TII->get(X86::PUSH32r)).addReg(sizeVReg);
+ BuildMI(mallocMBB, DL, TII->get(X86::CALLpcrel32))
+ .addExternalSymbol("__morestack_allocate_stack_space");
+ }
+
+ if (!Is64Bit)
+ BuildMI(mallocMBB, DL, TII->get(X86::ADD32ri), physSPReg).addReg(physSPReg)
+ .addImm(16);
+
+ BuildMI(mallocMBB, DL, TII->get(TargetOpcode::COPY), mallocPtrVReg)
+ .addReg(Is64Bit ? X86::RAX : X86::EAX);
+ BuildMI(mallocMBB, DL, TII->get(X86::JMP_4)).addMBB(continueMBB);
+
+ // Set up the CFG correctly.
+ BB->addSuccessor(bumpMBB);
+ BB->addSuccessor(mallocMBB);
+ mallocMBB->addSuccessor(continueMBB);
+ bumpMBB->addSuccessor(continueMBB);
+
+ // Take care of the PHI nodes.
+ BuildMI(*continueMBB, continueMBB->begin(), DL, TII->get(X86::PHI),
+ MI->getOperand(0).getReg())
+ .addReg(mallocPtrVReg).addMBB(mallocMBB)
+ .addReg(bumpSPPtrVReg).addMBB(bumpMBB);
+
+ // Delete the original pseudo instruction.
+ MI->eraseFromParent();
+
+ // And we're done.
+ return continueMBB;
+}
+
+MachineBasicBlock *
X86TargetLowering::EmitLoweredWinAlloca(MachineInstr *MI,
MachineBasicBlock *BB) const {
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
@@ -10718,11 +11966,11 @@ MachineBasicBlock *
X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const {
switch (MI->getOpcode()) {
- default: assert(false && "Unexpected instr type to insert");
+ default: assert(0 && "Unexpected instr type to insert");
case X86::TAILJMPd64:
case X86::TAILJMPr64:
case X86::TAILJMPm64:
- assert(!"TAILJMP64 would not be touched here.");
+ assert(0 && "TAILJMP64 would not be touched here.");
case X86::TCRETURNdi64:
case X86::TCRETURNri64:
case X86::TCRETURNmi64:
@@ -10745,6 +11993,10 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
return BB;
case X86::WIN_ALLOCA:
return EmitLoweredWinAlloca(MI, BB);
+ case X86::SEG_ALLOCA_32:
+ return EmitLoweredSegAlloca(MI, BB, false);
+ case X86::SEG_ALLOCA_64:
+ return EmitLoweredSegAlloca(MI, BB, true);
case X86::TLSCall_32:
case X86::TLSCall_64:
return EmitLoweredTLSCall(MI, BB);
@@ -10754,6 +12006,9 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
case X86::CMOV_V4F32:
case X86::CMOV_V2F64:
case X86::CMOV_V2I64:
+ case X86::CMOV_V8F32:
+ case X86::CMOV_V4F64:
+ case X86::CMOV_V4I64:
case X86::CMOV_GR16:
case X86::CMOV_GR32:
case X86::CMOV_RFP32:
@@ -11074,6 +12329,33 @@ void X86TargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
KnownZero |= APInt::getHighBitsSet(Mask.getBitWidth(),
Mask.getBitWidth() - 1);
break;
+ case ISD::INTRINSIC_WO_CHAIN: {
+ unsigned IntId = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
+ unsigned NumLoBits = 0;
+ switch (IntId) {
+ default: break;
+ case Intrinsic::x86_sse_movmsk_ps:
+ case Intrinsic::x86_avx_movmsk_ps_256:
+ case Intrinsic::x86_sse2_movmsk_pd:
+ case Intrinsic::x86_avx_movmsk_pd_256:
+ case Intrinsic::x86_mmx_pmovmskb:
+ case Intrinsic::x86_sse2_pmovmskb_128: {
+ // High bits of movmskp{s|d}, pmovmskb are known zero.
+ switch (IntId) {
+ case Intrinsic::x86_sse_movmsk_ps: NumLoBits = 4; break;
+ case Intrinsic::x86_avx_movmsk_ps_256: NumLoBits = 8; break;
+ case Intrinsic::x86_sse2_movmsk_pd: NumLoBits = 2; break;
+ case Intrinsic::x86_avx_movmsk_pd_256: NumLoBits = 4; break;
+ case Intrinsic::x86_mmx_pmovmskb: NumLoBits = 8; break;
+ case Intrinsic::x86_sse2_pmovmskb_128: NumLoBits = 16; break;
+ }
+ KnownZero = APInt::getHighBitsSet(Mask.getBitWidth(),
+ Mask.getBitWidth() - NumLoBits);
+ break;
+ }
+ }
+ break;
+ }
}
}
@@ -11102,23 +12384,132 @@ bool X86TargetLowering::isGAPlusOffset(SDNode *N,
return TargetLowering::isGAPlusOffset(N, GA, Offset);
}
-/// PerformShuffleCombine - Combine a vector_shuffle that is equal to
-/// build_vector load1, load2, load3, load4, <0, 1, 2, 3> into a 128-bit load
-/// if the load addresses are consecutive, non-overlapping, and in the right
-/// order.
+/// isShuffleHigh128VectorInsertLow - Checks whether the shuffle node is the
+/// same as extracting the high 128-bit part of 256-bit vector and then
+/// inserting the result into the low part of a new 256-bit vector
+static bool isShuffleHigh128VectorInsertLow(ShuffleVectorSDNode *SVOp) {
+ EVT VT = SVOp->getValueType(0);
+ int NumElems = VT.getVectorNumElements();
+
+ // vector_shuffle <4, 5, 6, 7, u, u, u, u> or <2, 3, u, u>
+ for (int i = 0, j = NumElems/2; i < NumElems/2; ++i, ++j)
+ if (!isUndefOrEqual(SVOp->getMaskElt(i), j) ||
+ SVOp->getMaskElt(j) >= 0)
+ return false;
+
+ return true;
+}
+
+/// isShuffleLow128VectorInsertHigh - Checks whether the shuffle node is the
+/// same as extracting the low 128-bit part of 256-bit vector and then
+/// inserting the result into the high part of a new 256-bit vector
+static bool isShuffleLow128VectorInsertHigh(ShuffleVectorSDNode *SVOp) {
+ EVT VT = SVOp->getValueType(0);
+ int NumElems = VT.getVectorNumElements();
+
+ // vector_shuffle <u, u, u, u, 0, 1, 2, 3> or <u, u, 0, 1>
+ for (int i = NumElems/2, j = 0; i < NumElems; ++i, ++j)
+ if (!isUndefOrEqual(SVOp->getMaskElt(i), j) ||
+ SVOp->getMaskElt(j) >= 0)
+ return false;
+
+ return true;
+}
+
+/// PerformShuffleCombine256 - Performs shuffle combines for 256-bit vectors.
+static SDValue PerformShuffleCombine256(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI) {
+ DebugLoc dl = N->getDebugLoc();
+ ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
+ SDValue V1 = SVOp->getOperand(0);
+ SDValue V2 = SVOp->getOperand(1);
+ EVT VT = SVOp->getValueType(0);
+ int NumElems = VT.getVectorNumElements();
+
+ if (V1.getOpcode() == ISD::CONCAT_VECTORS &&
+ V2.getOpcode() == ISD::CONCAT_VECTORS) {
+ //
+ // 0,0,0,...
+ // |
+ // V UNDEF BUILD_VECTOR UNDEF
+ // \ / \ /
+ // CONCAT_VECTOR CONCAT_VECTOR
+ // \ /
+ // \ /
+ // RESULT: V + zero extended
+ //
+ if (V2.getOperand(0).getOpcode() != ISD::BUILD_VECTOR ||
+ V2.getOperand(1).getOpcode() != ISD::UNDEF ||
+ V1.getOperand(1).getOpcode() != ISD::UNDEF)
+ return SDValue();
+
+ if (!ISD::isBuildVectorAllZeros(V2.getOperand(0).getNode()))
+ return SDValue();
+
+ // To match the shuffle mask, the first half of the mask should
+ // be exactly the first vector, and all the rest a splat with the
+ // first element of the second one.
+ for (int i = 0; i < NumElems/2; ++i)
+ if (!isUndefOrEqual(SVOp->getMaskElt(i), i) ||
+ !isUndefOrEqual(SVOp->getMaskElt(i+NumElems/2), NumElems))
+ return SDValue();
+
+ // Emit a zeroed vector and insert the desired subvector on its
+ // first half.
+ SDValue Zeros = getZeroVector(VT, true /* HasXMMInt */, DAG, dl);
+ SDValue InsV = Insert128BitVector(Zeros, V1.getOperand(0),
+ DAG.getConstant(0, MVT::i32), DAG, dl);
+ return DCI.CombineTo(N, InsV);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Combine some shuffles into subvector extracts and inserts:
+ //
+
+ // vector_shuffle <4, 5, 6, 7, u, u, u, u> or <2, 3, u, u>
+ if (isShuffleHigh128VectorInsertLow(SVOp)) {
+ SDValue V = Extract128BitVector(V1, DAG.getConstant(NumElems/2, MVT::i32),
+ DAG, dl);
+ SDValue InsV = Insert128BitVector(DAG.getNode(ISD::UNDEF, dl, VT),
+ V, DAG.getConstant(0, MVT::i32), DAG, dl);
+ return DCI.CombineTo(N, InsV);
+ }
+
+ // vector_shuffle <u, u, u, u, 0, 1, 2, 3> or <u, u, 0, 1>
+ if (isShuffleLow128VectorInsertHigh(SVOp)) {
+ SDValue V = Extract128BitVector(V1, DAG.getConstant(0, MVT::i32), DAG, dl);
+ SDValue InsV = Insert128BitVector(DAG.getNode(ISD::UNDEF, dl, VT),
+ V, DAG.getConstant(NumElems/2, MVT::i32), DAG, dl);
+ return DCI.CombineTo(N, InsV);
+ }
+
+ return SDValue();
+}
+
+/// PerformShuffleCombine - Performs several different shuffle combines.
static SDValue PerformShuffleCombine(SDNode *N, SelectionDAG &DAG,
- TargetLowering::DAGCombinerInfo &DCI) {
+ TargetLowering::DAGCombinerInfo &DCI,
+ const X86Subtarget *Subtarget) {
DebugLoc dl = N->getDebugLoc();
EVT VT = N->getValueType(0);
- if (VT.getSizeInBits() != 128)
- return SDValue();
-
// Don't create instructions with illegal types after legalize types has run.
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
if (!DCI.isBeforeLegalize() && !TLI.isTypeLegal(VT.getVectorElementType()))
return SDValue();
+ // Combine 256-bit vector shuffles. This is only profitable when in AVX mode
+ if (Subtarget->hasAVX() && VT.getSizeInBits() == 256 &&
+ N->getOpcode() == ISD::VECTOR_SHUFFLE)
+ return PerformShuffleCombine256(N, DAG, DCI);
+
+ // Only handle 128 wide vector from here on.
+ if (VT.getSizeInBits() != 128)
+ return SDValue();
+
+ // Combine a vector_shuffle that is equal to build_vector load1, load2, load3,
+ // load4, <0, 1, 2, 3> into a 128-bit load if the load addresses are
+ // consecutive, non-overlapping, and in the right order.
SmallVector<SDValue, 16> Elts;
for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i)
Elts.push_back(getShuffleScalarElt(N, i, DAG, 0));
@@ -11209,7 +12600,8 @@ static SDValue PerformEXTRACT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
-/// PerformSELECTCombine - Do target-specific dag combines on SELECT nodes.
+/// PerformSELECTCombine - Do target-specific dag combines on SELECT and VSELECT
+/// nodes.
static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
const X86Subtarget *Subtarget) {
DebugLoc DL = N->getDebugLoc();
@@ -11217,14 +12609,16 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
// Get the LHS/RHS of the select.
SDValue LHS = N->getOperand(1);
SDValue RHS = N->getOperand(2);
+ EVT VT = LHS.getValueType();
// If we have SSE[12] support, try to form min/max nodes. SSE min/max
// instructions match the semantics of the common C idiom x<y?x:y but not
// x<=y?x:y, because of how they handle negative zero (which can be
// ignored in unsafe-math mode).
- if (Subtarget->hasSSE2() &&
- (LHS.getValueType() == MVT::f32 || LHS.getValueType() == MVT::f64) &&
- Cond.getOpcode() == ISD::SETCC) {
+ if (Cond.getOpcode() == ISD::SETCC && VT.isFloatingPoint() &&
+ VT != MVT::f80 && DAG.getTargetLoweringInfo().isTypeLegal(VT) &&
+ (Subtarget->hasXMMInt() ||
+ (Subtarget->hasSSE1() && VT.getScalarType() == MVT::f32))) {
ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
unsigned Opcode = 0;
@@ -11267,7 +12661,7 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
// Converting this to a max would handle comparisons between positive
// and negative zero incorrectly.
if (!UnsafeFPMath &&
- !DAG.isKnownNeverZero(LHS) && !DAG.isKnownNeverZero(LHS))
+ !DAG.isKnownNeverZero(LHS) && !DAG.isKnownNeverZero(RHS))
break;
Opcode = X86ISD::FMAX;
break;
@@ -11680,7 +13074,7 @@ static SDValue PerformShiftCombine(SDNode* N, SelectionDAG &DAG,
// all elements are shifted by the same amount. We can't do this in legalize
// because the a constant vector is typically transformed to a constant pool
// so we have no knowledge of the shift amount.
- if (!Subtarget->hasSSE2())
+ if (!Subtarget->hasXMMInt())
return SDValue();
if (VT != MVT::v2i64 && VT != MVT::v4i32 && VT != MVT::v8i16)
@@ -11796,7 +13190,7 @@ static SDValue CMPEQCombine(SDNode *N, SelectionDAG &DAG,
// SSE1 supports CMP{eq|ne}SS, and SSE2 added CMP{eq|ne}SD, but
// we're requiring SSE2 for both.
- if (Subtarget->hasSSE2() && isAndOrOfSetCCs(SDValue(N, 0U), opcode)) {
+ if (Subtarget->hasXMMInt() && isAndOrOfSetCCs(SDValue(N, 0U), opcode)) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
SDValue CMP0 = N0->getOperand(1);
@@ -11864,6 +13258,36 @@ static SDValue CMPEQCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+/// CanFoldXORWithAllOnes - Test whether the XOR operand is a AllOnes vector
+/// so it can be folded inside ANDNP.
+static bool CanFoldXORWithAllOnes(const SDNode *N) {
+ EVT VT = N->getValueType(0);
+
+ // Match direct AllOnes for 128 and 256-bit vectors
+ if (ISD::isBuildVectorAllOnes(N))
+ return true;
+
+ // Look through a bit convert.
+ if (N->getOpcode() == ISD::BITCAST)
+ N = N->getOperand(0).getNode();
+
+ // Sometimes the operand may come from a insert_subvector building a 256-bit
+ // allones vector
+ if (VT.getSizeInBits() == 256 &&
+ N->getOpcode() == ISD::INSERT_SUBVECTOR) {
+ SDValue V1 = N->getOperand(0);
+ SDValue V2 = N->getOperand(1);
+
+ if (V1.getOpcode() == ISD::INSERT_SUBVECTOR &&
+ V1.getOperand(0).getOpcode() == ISD::UNDEF &&
+ ISD::isBuildVectorAllOnes(V1.getOperand(1).getNode()) &&
+ ISD::isBuildVectorAllOnes(V2.getNode()))
+ return true;
+ }
+
+ return false;
+}
+
static SDValue PerformAndCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const X86Subtarget *Subtarget) {
@@ -11874,11 +13298,28 @@ static SDValue PerformAndCombine(SDNode *N, SelectionDAG &DAG,
if (R.getNode())
return R;
+ EVT VT = N->getValueType(0);
+
+ // Create ANDN instructions
+ if (Subtarget->hasBMI() && (VT == MVT::i32 || VT == MVT::i64)) {
+ SDValue N0 = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+ DebugLoc DL = N->getDebugLoc();
+
+ // Check LHS for not
+ if (N0.getOpcode() == ISD::XOR && isAllOnes(N0.getOperand(1)))
+ return DAG.getNode(X86ISD::ANDN, DL, VT, N0.getOperand(0), N1);
+ // Check RHS for not
+ if (N1.getOpcode() == ISD::XOR && isAllOnes(N1.getOperand(1)))
+ return DAG.getNode(X86ISD::ANDN, DL, VT, N1.getOperand(0), N0);
+
+ return SDValue();
+ }
+
// Want to form ANDNP nodes:
// 1) In the hopes of then easily combining them with OR and AND nodes
// to form PBLEND/PSIGN.
// 2) To match ANDN packed intrinsics
- EVT VT = N->getValueType(0);
if (VT != MVT::v2i64 && VT != MVT::v4i64)
return SDValue();
@@ -11888,12 +13329,14 @@ static SDValue PerformAndCombine(SDNode *N, SelectionDAG &DAG,
// Check LHS for vnot
if (N0.getOpcode() == ISD::XOR &&
- ISD::isBuildVectorAllOnes(N0.getOperand(1).getNode()))
+ //ISD::isBuildVectorAllOnes(N0.getOperand(1).getNode()))
+ CanFoldXORWithAllOnes(N0.getOperand(1).getNode()))
return DAG.getNode(X86ISD::ANDNP, DL, VT, N0.getOperand(0), N1);
// Check RHS for vnot
if (N1.getOpcode() == ISD::XOR &&
- ISD::isBuildVectorAllOnes(N1.getOperand(1).getNode()))
+ //ISD::isBuildVectorAllOnes(N1.getOperand(1).getNode()))
+ CanFoldXORWithAllOnes(N1.getOperand(1).getNode()))
return DAG.getNode(X86ISD::ANDNP, DL, VT, N1.getOperand(0), N0);
return SDValue();
@@ -11917,7 +13360,7 @@ static SDValue PerformOrCombine(SDNode *N, SelectionDAG &DAG,
SDValue N1 = N->getOperand(1);
// look for psign/blend
- if (Subtarget->hasSSSE3()) {
+ if (Subtarget->hasSSSE3() || Subtarget->hasAVX()) {
if (VT == MVT::v2i64) {
// Canonicalize pandn to RHS
if (N0.getOpcode() == X86ISD::ANDNP)
@@ -11990,13 +13433,13 @@ static SDValue PerformOrCombine(SDNode *N, SelectionDAG &DAG,
}
}
// PBLENDVB only available on SSE 4.1
- if (!Subtarget->hasSSE41())
+ if (!(Subtarget->hasSSE41() || Subtarget->hasAVX()))
return SDValue();
X = DAG.getNode(ISD::BITCAST, DL, MVT::v16i8, X);
Y = DAG.getNode(ISD::BITCAST, DL, MVT::v16i8, Y);
Mask = DAG.getNode(ISD::BITCAST, DL, MVT::v16i8, Mask);
- Mask = DAG.getNode(X86ISD::PBLENDVB, DL, MVT::v16i8, X, Y, Mask);
+ Mask = DAG.getNode(ISD::VSELECT, DL, MVT::v16i8, Mask, X, Y);
return DAG.getNode(ISD::BITCAST, DL, MVT::v2i64, Mask);
}
}
@@ -12057,24 +13500,211 @@ static SDValue PerformOrCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+/// PerformLOADCombine - Do target-specific dag combines on LOAD nodes.
+static SDValue PerformLOADCombine(SDNode *N, SelectionDAG &DAG,
+ const X86Subtarget *Subtarget) {
+ LoadSDNode *Ld = cast<LoadSDNode>(N);
+ EVT RegVT = Ld->getValueType(0);
+ EVT MemVT = Ld->getMemoryVT();
+ DebugLoc dl = Ld->getDebugLoc();
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+
+ ISD::LoadExtType Ext = Ld->getExtensionType();
+
+ // If this is a vector EXT Load then attempt to optimize it using a
+ // shuffle. We need SSE4 for the shuffles.
+ // TODO: It is possible to support ZExt by zeroing the undef values
+ // during the shuffle phase or after the shuffle.
+ if (RegVT.isVector() && Ext == ISD::EXTLOAD && Subtarget->hasSSE41()) {
+ assert(MemVT != RegVT && "Cannot extend to the same type");
+ assert(MemVT.isVector() && "Must load a vector from memory");
+
+ unsigned NumElems = RegVT.getVectorNumElements();
+ unsigned RegSz = RegVT.getSizeInBits();
+ unsigned MemSz = MemVT.getSizeInBits();
+ assert(RegSz > MemSz && "Register size must be greater than the mem size");
+ // All sizes must be a power of two
+ if (!isPowerOf2_32(RegSz * MemSz * NumElems)) return SDValue();
+
+ // Attempt to load the original value using a single load op.
+ // Find a scalar type which is equal to the loaded word size.
+ MVT SclrLoadTy = MVT::i8;
+ for (unsigned tp = MVT::FIRST_INTEGER_VALUETYPE;
+ tp < MVT::LAST_INTEGER_VALUETYPE; ++tp) {
+ MVT Tp = (MVT::SimpleValueType)tp;
+ if (TLI.isTypeLegal(Tp) && Tp.getSizeInBits() == MemSz) {
+ SclrLoadTy = Tp;
+ break;
+ }
+ }
+
+ // Proceed if a load word is found.
+ if (SclrLoadTy.getSizeInBits() != MemSz) return SDValue();
+
+ EVT LoadUnitVecVT = EVT::getVectorVT(*DAG.getContext(), SclrLoadTy,
+ RegSz/SclrLoadTy.getSizeInBits());
+
+ EVT WideVecVT = EVT::getVectorVT(*DAG.getContext(), MemVT.getScalarType(),
+ RegSz/MemVT.getScalarType().getSizeInBits());
+ // Can't shuffle using an illegal type.
+ if (!TLI.isTypeLegal(WideVecVT)) return SDValue();
+
+ // Perform a single load.
+ SDValue ScalarLoad = DAG.getLoad(SclrLoadTy, dl, Ld->getChain(),
+ Ld->getBasePtr(),
+ Ld->getPointerInfo(), Ld->isVolatile(),
+ Ld->isNonTemporal(), Ld->getAlignment());
+
+ // Insert the word loaded into a vector.
+ SDValue ScalarInVector = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl,
+ LoadUnitVecVT, ScalarLoad);
+
+ // Bitcast the loaded value to a vector of the original element type, in
+ // the size of the target vector type.
+ SDValue SlicedVec = DAG.getNode(ISD::BITCAST, dl, WideVecVT, ScalarInVector);
+ unsigned SizeRatio = RegSz/MemSz;
+
+ // Redistribute the loaded elements into the different locations.
+ SmallVector<int, 8> ShuffleVec(NumElems * SizeRatio, -1);
+ for (unsigned i = 0; i < NumElems; i++) ShuffleVec[i*SizeRatio] = i;
+
+ SDValue Shuff = DAG.getVectorShuffle(WideVecVT, dl, SlicedVec,
+ DAG.getUNDEF(SlicedVec.getValueType()),
+ ShuffleVec.data());
+
+ // Bitcast to the requested type.
+ Shuff = DAG.getNode(ISD::BITCAST, dl, RegVT, Shuff);
+ // Replace the original load with the new sequence
+ // and return the new chain.
+ DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Shuff);
+ return SDValue(ScalarLoad.getNode(), 1);
+ }
+
+ return SDValue();
+}
+
/// PerformSTORECombine - Do target-specific dag combines on STORE nodes.
static SDValue PerformSTORECombine(SDNode *N, SelectionDAG &DAG,
const X86Subtarget *Subtarget) {
+ StoreSDNode *St = cast<StoreSDNode>(N);
+ EVT VT = St->getValue().getValueType();
+ EVT StVT = St->getMemoryVT();
+ DebugLoc dl = St->getDebugLoc();
+ SDValue StoredVal = St->getOperand(1);
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+
+ // If we are saving a concatination of two XMM registers, perform two stores.
+ // This is better in Sandy Bridge cause one 256-bit mem op is done via two
+ // 128-bit ones. If in the future the cost becomes only one memory access the
+ // first version would be better.
+ if (VT.getSizeInBits() == 256 &&
+ StoredVal.getNode()->getOpcode() == ISD::CONCAT_VECTORS &&
+ StoredVal.getNumOperands() == 2) {
+
+ SDValue Value0 = StoredVal.getOperand(0);
+ SDValue Value1 = StoredVal.getOperand(1);
+
+ SDValue Stride = DAG.getConstant(16, TLI.getPointerTy());
+ SDValue Ptr0 = St->getBasePtr();
+ SDValue Ptr1 = DAG.getNode(ISD::ADD, dl, Ptr0.getValueType(), Ptr0, Stride);
+
+ SDValue Ch0 = DAG.getStore(St->getChain(), dl, Value0, Ptr0,
+ St->getPointerInfo(), St->isVolatile(),
+ St->isNonTemporal(), St->getAlignment());
+ SDValue Ch1 = DAG.getStore(St->getChain(), dl, Value1, Ptr1,
+ St->getPointerInfo(), St->isVolatile(),
+ St->isNonTemporal(), St->getAlignment());
+ return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Ch0, Ch1);
+ }
+
+ // Optimize trunc store (of multiple scalars) to shuffle and store.
+ // First, pack all of the elements in one place. Next, store to memory
+ // in fewer chunks.
+ if (St->isTruncatingStore() && VT.isVector()) {
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ unsigned NumElems = VT.getVectorNumElements();
+ assert(StVT != VT && "Cannot truncate to the same type");
+ unsigned FromSz = VT.getVectorElementType().getSizeInBits();
+ unsigned ToSz = StVT.getVectorElementType().getSizeInBits();
+
+ // From, To sizes and ElemCount must be pow of two
+ if (!isPowerOf2_32(NumElems * FromSz * ToSz)) return SDValue();
+ // We are going to use the original vector elt for storing.
+ // Accumulated smaller vector elements must be a multiple of the store size.
+ if (0 != (NumElems * FromSz) % ToSz) return SDValue();
+
+ unsigned SizeRatio = FromSz / ToSz;
+
+ assert(SizeRatio * NumElems * ToSz == VT.getSizeInBits());
+
+ // Create a type on which we perform the shuffle
+ EVT WideVecVT = EVT::getVectorVT(*DAG.getContext(),
+ StVT.getScalarType(), NumElems*SizeRatio);
+
+ assert(WideVecVT.getSizeInBits() == VT.getSizeInBits());
+
+ SDValue WideVec = DAG.getNode(ISD::BITCAST, dl, WideVecVT, St->getValue());
+ SmallVector<int, 8> ShuffleVec(NumElems * SizeRatio, -1);
+ for (unsigned i = 0; i < NumElems; i++ ) ShuffleVec[i] = i * SizeRatio;
+
+ // Can't shuffle using an illegal type
+ if (!TLI.isTypeLegal(WideVecVT)) return SDValue();
+
+ SDValue Shuff = DAG.getVectorShuffle(WideVecVT, dl, WideVec,
+ DAG.getUNDEF(WideVec.getValueType()),
+ ShuffleVec.data());
+ // At this point all of the data is stored at the bottom of the
+ // register. We now need to save it to mem.
+
+ // Find the largest store unit
+ MVT StoreType = MVT::i8;
+ for (unsigned tp = MVT::FIRST_INTEGER_VALUETYPE;
+ tp < MVT::LAST_INTEGER_VALUETYPE; ++tp) {
+ MVT Tp = (MVT::SimpleValueType)tp;
+ if (TLI.isTypeLegal(Tp) && StoreType.getSizeInBits() < NumElems * ToSz)
+ StoreType = Tp;
+ }
+
+ // Bitcast the original vector into a vector of store-size units
+ EVT StoreVecVT = EVT::getVectorVT(*DAG.getContext(),
+ StoreType, VT.getSizeInBits()/EVT(StoreType).getSizeInBits());
+ assert(StoreVecVT.getSizeInBits() == VT.getSizeInBits());
+ SDValue ShuffWide = DAG.getNode(ISD::BITCAST, dl, StoreVecVT, Shuff);
+ SmallVector<SDValue, 8> Chains;
+ SDValue Increment = DAG.getConstant(StoreType.getSizeInBits()/8,
+ TLI.getPointerTy());
+ SDValue Ptr = St->getBasePtr();
+
+ // Perform one or more big stores into memory.
+ for (unsigned i = 0; i < (ToSz*NumElems)/StoreType.getSizeInBits() ; i++) {
+ SDValue SubVec = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
+ StoreType, ShuffWide,
+ DAG.getIntPtrConstant(i));
+ SDValue Ch = DAG.getStore(St->getChain(), dl, SubVec, Ptr,
+ St->getPointerInfo(), St->isVolatile(),
+ St->isNonTemporal(), St->getAlignment());
+ Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, Increment);
+ Chains.push_back(Ch);
+ }
+
+ return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Chains[0],
+ Chains.size());
+ }
+
+
// Turn load->store of MMX types into GPR load/stores. This avoids clobbering
// the FP state in cases where an emms may be missing.
// A preferable solution to the general problem is to figure out the right
// places to insert EMMS. This qualifies as a quick hack.
// Similarly, turn load->store of i64 into double load/stores in 32-bit mode.
- StoreSDNode *St = cast<StoreSDNode>(N);
- EVT VT = St->getValue().getValueType();
if (VT.getSizeInBits() != 64)
return SDValue();
const Function *F = DAG.getMachineFunction().getFunction();
bool NoImplicitFloatOps = F->hasFnAttr(Attribute::NoImplicitFloat);
bool F64IsLegal = !UseSoftFloat && !NoImplicitFloatOps
- && Subtarget->hasSSE2();
+ && Subtarget->hasXMMInt();
if ((VT.isVector() ||
(VT == MVT::i64 && F64IsLegal && !Subtarget->is64Bit())) &&
isa<LoadSDNode>(St->getValue()) &&
@@ -12172,6 +13802,150 @@ static SDValue PerformSTORECombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+/// isHorizontalBinOp - Return 'true' if this vector operation is "horizontal"
+/// and return the operands for the horizontal operation in LHS and RHS. A
+/// horizontal operation performs the binary operation on successive elements
+/// of its first operand, then on successive elements of its second operand,
+/// returning the resulting values in a vector. For example, if
+/// A = < float a0, float a1, float a2, float a3 >
+/// and
+/// B = < float b0, float b1, float b2, float b3 >
+/// then the result of doing a horizontal operation on A and B is
+/// A horizontal-op B = < a0 op a1, a2 op a3, b0 op b1, b2 op b3 >.
+/// In short, LHS and RHS are inspected to see if LHS op RHS is of the form
+/// A horizontal-op B, for some already available A and B, and if so then LHS is
+/// set to A, RHS to B, and the routine returns 'true'.
+/// Note that the binary operation should have the property that if one of the
+/// operands is UNDEF then the result is UNDEF.
+static bool isHorizontalBinOp(SDValue &LHS, SDValue &RHS, bool isCommutative) {
+ // Look for the following pattern: if
+ // A = < float a0, float a1, float a2, float a3 >
+ // B = < float b0, float b1, float b2, float b3 >
+ // and
+ // LHS = VECTOR_SHUFFLE A, B, <0, 2, 4, 6>
+ // RHS = VECTOR_SHUFFLE A, B, <1, 3, 5, 7>
+ // then LHS op RHS = < a0 op a1, a2 op a3, b0 op b1, b2 op b3 >
+ // which is A horizontal-op B.
+
+ // At least one of the operands should be a vector shuffle.
+ if (LHS.getOpcode() != ISD::VECTOR_SHUFFLE &&
+ RHS.getOpcode() != ISD::VECTOR_SHUFFLE)
+ return false;
+
+ EVT VT = LHS.getValueType();
+ unsigned N = VT.getVectorNumElements();
+
+ // View LHS in the form
+ // LHS = VECTOR_SHUFFLE A, B, LMask
+ // If LHS is not a shuffle then pretend it is the shuffle
+ // LHS = VECTOR_SHUFFLE LHS, undef, <0, 1, ..., N-1>
+ // NOTE: in what follows a default initialized SDValue represents an UNDEF of
+ // type VT.
+ SDValue A, B;
+ SmallVector<int, 8> LMask(N);
+ if (LHS.getOpcode() == ISD::VECTOR_SHUFFLE) {
+ if (LHS.getOperand(0).getOpcode() != ISD::UNDEF)
+ A = LHS.getOperand(0);
+ if (LHS.getOperand(1).getOpcode() != ISD::UNDEF)
+ B = LHS.getOperand(1);
+ cast<ShuffleVectorSDNode>(LHS.getNode())->getMask(LMask);
+ } else {
+ if (LHS.getOpcode() != ISD::UNDEF)
+ A = LHS;
+ for (unsigned i = 0; i != N; ++i)
+ LMask[i] = i;
+ }
+
+ // Likewise, view RHS in the form
+ // RHS = VECTOR_SHUFFLE C, D, RMask
+ SDValue C, D;
+ SmallVector<int, 8> RMask(N);
+ if (RHS.getOpcode() == ISD::VECTOR_SHUFFLE) {
+ if (RHS.getOperand(0).getOpcode() != ISD::UNDEF)
+ C = RHS.getOperand(0);
+ if (RHS.getOperand(1).getOpcode() != ISD::UNDEF)
+ D = RHS.getOperand(1);
+ cast<ShuffleVectorSDNode>(RHS.getNode())->getMask(RMask);
+ } else {
+ if (RHS.getOpcode() != ISD::UNDEF)
+ C = RHS;
+ for (unsigned i = 0; i != N; ++i)
+ RMask[i] = i;
+ }
+
+ // Check that the shuffles are both shuffling the same vectors.
+ if (!(A == C && B == D) && !(A == D && B == C))
+ return false;
+
+ // If everything is UNDEF then bail out: it would be better to fold to UNDEF.
+ if (!A.getNode() && !B.getNode())
+ return false;
+
+ // If A and B occur in reverse order in RHS, then "swap" them (which means
+ // rewriting the mask).
+ if (A != C)
+ for (unsigned i = 0; i != N; ++i) {
+ unsigned Idx = RMask[i];
+ if (Idx < N)
+ RMask[i] += N;
+ else if (Idx < 2*N)
+ RMask[i] -= N;
+ }
+
+ // At this point LHS and RHS are equivalent to
+ // LHS = VECTOR_SHUFFLE A, B, LMask
+ // RHS = VECTOR_SHUFFLE A, B, RMask
+ // Check that the masks correspond to performing a horizontal operation.
+ for (unsigned i = 0; i != N; ++i) {
+ unsigned LIdx = LMask[i], RIdx = RMask[i];
+
+ // Ignore any UNDEF components.
+ if (LIdx >= 2*N || RIdx >= 2*N || (!A.getNode() && (LIdx < N || RIdx < N))
+ || (!B.getNode() && (LIdx >= N || RIdx >= N)))
+ continue;
+
+ // Check that successive elements are being operated on. If not, this is
+ // not a horizontal operation.
+ if (!(LIdx == 2*i && RIdx == 2*i + 1) &&
+ !(isCommutative && LIdx == 2*i + 1 && RIdx == 2*i))
+ return false;
+ }
+
+ LHS = A.getNode() ? A : B; // If A is 'UNDEF', use B for it.
+ RHS = B.getNode() ? B : A; // If B is 'UNDEF', use A for it.
+ return true;
+}
+
+/// PerformFADDCombine - Do target-specific dag combines on floating point adds.
+static SDValue PerformFADDCombine(SDNode *N, SelectionDAG &DAG,
+ const X86Subtarget *Subtarget) {
+ EVT VT = N->getValueType(0);
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
+
+ // Try to synthesize horizontal adds from adds of shuffles.
+ if ((Subtarget->hasSSE3() || Subtarget->hasAVX()) &&
+ (VT == MVT::v4f32 || VT == MVT::v2f64) &&
+ isHorizontalBinOp(LHS, RHS, true))
+ return DAG.getNode(X86ISD::FHADD, N->getDebugLoc(), VT, LHS, RHS);
+ return SDValue();
+}
+
+/// PerformFSUBCombine - Do target-specific dag combines on floating point subs.
+static SDValue PerformFSUBCombine(SDNode *N, SelectionDAG &DAG,
+ const X86Subtarget *Subtarget) {
+ EVT VT = N->getValueType(0);
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
+
+ // Try to synthesize horizontal subs from subs of shuffles.
+ if ((Subtarget->hasSSE3() || Subtarget->hasAVX()) &&
+ (VT == MVT::v4f32 || VT == MVT::v2f64) &&
+ isHorizontalBinOp(LHS, RHS, false))
+ return DAG.getNode(X86ISD::FHSUB, N->getDebugLoc(), VT, LHS, RHS);
+ return SDValue();
+}
+
/// PerformFORCombine - Do target-specific dag combines on X86ISD::FOR and
/// X86ISD::FXOR nodes.
static SDValue PerformFORCombine(SDNode *N, SelectionDAG &DAG) {
@@ -12326,7 +14100,7 @@ static SDValue PerformADCCombine(SDNode *N, SelectionDAG &DAG,
// (add Y, (setne X, 0)) -> sbb -1, Y
// (sub (sete X, 0), Y) -> sbb 0, Y
// (sub (setne X, 0), Y) -> adc -1, Y
-static SDValue OptimizeConditonalInDecrement(SDNode *N, SelectionDAG &DAG) {
+static SDValue OptimizeConditionalInDecrement(SDNode *N, SelectionDAG &DAG) {
DebugLoc DL = N->getDebugLoc();
// Look through ZExts.
@@ -12362,6 +14136,31 @@ static SDValue OptimizeConditonalInDecrement(SDNode *N, SelectionDAG &DAG) {
DAG.getConstant(0, OtherVal.getValueType()), NewCmp);
}
+static SDValue PerformSubCombine(SDNode *N, SelectionDAG &DAG) {
+ SDValue Op0 = N->getOperand(0);
+ SDValue Op1 = N->getOperand(1);
+
+ // X86 can't encode an immediate LHS of a sub. See if we can push the
+ // negation into a preceding instruction.
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op0)) {
+ // If the RHS of the sub is a XOR with one use and a constant, invert the
+ // immediate. Then add one to the LHS of the sub so we can turn
+ // X-Y -> X+~Y+1, saving one register.
+ if (Op1->hasOneUse() && Op1.getOpcode() == ISD::XOR &&
+ isa<ConstantSDNode>(Op1.getOperand(1))) {
+ APInt XorC = cast<ConstantSDNode>(Op1.getOperand(1))->getAPIntValue();
+ EVT VT = Op0.getValueType();
+ SDValue NewXor = DAG.getNode(ISD::XOR, Op1.getDebugLoc(), VT,
+ Op1.getOperand(0),
+ DAG.getConstant(~XorC, VT));
+ return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, NewXor,
+ DAG.getConstant(C->getAPIntValue()+1, VT));
+ }
+ }
+
+ return OptimizeConditionalInDecrement(N, DAG);
+}
+
SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
DAGCombinerInfo &DCI) const {
SelectionDAG &DAG = DCI.DAG;
@@ -12369,10 +14168,11 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
default: break;
case ISD::EXTRACT_VECTOR_ELT:
return PerformEXTRACT_VECTOR_ELTCombine(N, DAG, *this);
+ case ISD::VSELECT:
case ISD::SELECT: return PerformSELECTCombine(N, DAG, Subtarget);
case X86ISD::CMOV: return PerformCMOVCombine(N, DAG, DCI);
- case ISD::ADD:
- case ISD::SUB: return OptimizeConditonalInDecrement(N, DAG);
+ case ISD::ADD: return OptimizeConditionalInDecrement(N, DAG);
+ case ISD::SUB: return PerformSubCombine(N, DAG);
case X86ISD::ADC: return PerformADCCombine(N, DAG, DCI);
case ISD::MUL: return PerformMulCombine(N, DAG, DCI);
case ISD::SHL:
@@ -12380,8 +14180,11 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
case ISD::SRL: return PerformShiftCombine(N, DAG, Subtarget);
case ISD::AND: return PerformAndCombine(N, DAG, DCI, Subtarget);
case ISD::OR: return PerformOrCombine(N, DAG, DCI, Subtarget);
+ case ISD::LOAD: return PerformLOADCombine(N, DAG, Subtarget);
case ISD::STORE: return PerformSTORECombine(N, DAG, Subtarget);
case ISD::SINT_TO_FP: return PerformSINT_TO_FPCombine(N, DAG, this);
+ case ISD::FADD: return PerformFADDCombine(N, DAG, Subtarget);
+ case ISD::FSUB: return PerformFSUBCombine(N, DAG, Subtarget);
case X86ISD::FXOR:
case X86ISD::FOR: return PerformFORCombine(N, DAG);
case X86ISD::FAND: return PerformFANDCombine(N, DAG);
@@ -12398,14 +14201,14 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
case X86ISD::PUNPCKHQDQ:
case X86ISD::UNPCKHPS:
case X86ISD::UNPCKHPD:
+ case X86ISD::VUNPCKHPSY:
+ case X86ISD::VUNPCKHPDY:
case X86ISD::PUNPCKLBW:
case X86ISD::PUNPCKLWD:
case X86ISD::PUNPCKLDQ:
case X86ISD::PUNPCKLQDQ:
case X86ISD::UNPCKLPS:
case X86ISD::UNPCKLPD:
- case X86ISD::VUNPCKLPS:
- case X86ISD::VUNPCKLPD:
case X86ISD::VUNPCKLPSY:
case X86ISD::VUNPCKLPDY:
case X86ISD::MOVHLPS:
@@ -12415,7 +14218,12 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
case X86ISD::PSHUFLW:
case X86ISD::MOVSS:
case X86ISD::MOVSD:
- case ISD::VECTOR_SHUFFLE: return PerformShuffleCombine(N, DAG, DCI);
+ case X86ISD::VPERMILPS:
+ case X86ISD::VPERMILPSY:
+ case X86ISD::VPERMILPD:
+ case X86ISD::VPERMILPDY:
+ case X86ISD::VPERM2F128:
+ case ISD::VECTOR_SHUFFLE: return PerformShuffleCombine(N, DAG, DCI,Subtarget);
}
return SDValue();
@@ -12551,7 +14359,7 @@ bool X86TargetLowering::ExpandInlineAsm(CallInst *CI) const {
AsmPieces[1] == "${0:q}")) {
// No need to check constraints, nothing other than the equivalent of
// "=r,0" would be valid here.
- const IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
+ IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
if (!Ty || Ty->getBitWidth() % 16 != 0)
return false;
return IntrinsicLowering::LowerToByteSwap(CI);
@@ -12572,7 +14380,7 @@ bool X86TargetLowering::ExpandInlineAsm(CallInst *CI) const {
AsmPieces[1] == "~{dirflag}" &&
AsmPieces[2] == "~{flags}" &&
AsmPieces[3] == "~{fpsr}") {
- const IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
+ IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
if (!Ty || Ty->getBitWidth() % 16 != 0)
return false;
return IntrinsicLowering::LowerToByteSwap(CI);
@@ -12603,7 +14411,7 @@ bool X86TargetLowering::ExpandInlineAsm(CallInst *CI) const {
AsmPieces[1] == "~{dirflag}" &&
AsmPieces[2] == "~{flags}" &&
AsmPieces[3] == "~{fpsr}") {
- const IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
+ IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
if (!Ty || Ty->getBitWidth() % 16 != 0)
return false;
return IntrinsicLowering::LowerToByteSwap(CI);
@@ -12629,7 +14437,7 @@ bool X86TargetLowering::ExpandInlineAsm(CallInst *CI) const {
SplitString(AsmPieces[2], Words, " \t,");
if (Words.size() == 3 && Words[0] == "xchgl" && Words[1] == "%eax" &&
Words[2] == "%edx") {
- const IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
+ IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
if (!Ty || Ty->getBitWidth() % 16 != 0)
return false;
return IntrinsicLowering::LowerToByteSwap(CI);
@@ -12700,7 +14508,7 @@ TargetLowering::ConstraintWeight
// 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:
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index b603678..342a5e6 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -175,8 +175,14 @@ namespace llvm {
/// PSIGNB/W/D - Copy integer sign.
PSIGNB, PSIGNW, PSIGND,
- /// PBLENDVB - Variable blend
- PBLENDVB,
+ /// BLEND family of opcodes
+ BLENDV,
+
+ /// FHADD - Floating point horizontal add.
+ FHADD,
+
+ /// FHSUB - Floating point horizontal sub.
+ FHSUB,
/// FMAX, FMIN - Floating point max and min.
///
@@ -222,6 +228,8 @@ namespace llvm {
ADD, SUB, ADC, SBB, SMUL,
INC, DEC, OR, XOR, AND,
+ ANDN, // ANDN - Bitwise AND NOT with FLAGS results.
+
UMUL, // LOW, HI, FLAGS = umul LHS, RHS
// MUL_IMM - X86 specific multiply by immediate.
@@ -257,12 +265,12 @@ namespace llvm {
MOVSS,
UNPCKLPS,
UNPCKLPD,
- VUNPCKLPS,
- VUNPCKLPD,
VUNPCKLPSY,
VUNPCKLPDY,
UNPCKHPS,
UNPCKHPD,
+ VUNPCKHPSY,
+ VUNPCKHPDY,
PUNPCKLBW,
PUNPCKLWD,
PUNPCKLDQ,
@@ -271,6 +279,12 @@ namespace llvm {
PUNPCKHWD,
PUNPCKHDQ,
PUNPCKHQDQ,
+ VPERMILPS,
+ VPERMILPSY,
+ VPERMILPD,
+ VPERMILPDY,
+ VPERM2F128,
+ VBROADCAST,
// VASTART_SAVE_XMM_REGS - Save xmm argument registers to the stack,
// according to %al. An operator is needed so that this can be expanded
@@ -280,6 +294,11 @@ namespace llvm {
// WIN_ALLOCA - Windows's _chkstk call to do stack probing.
WIN_ALLOCA,
+ // SEG_ALLOCA - For allocating variable amounts of stack space when using
+ // segmented stacks. Check if the current stacklet has enough space, and
+ // falls back to heap allocation if not.
+ SEG_ALLOCA,
+
// Memory barrier
MEMBARRIER,
MFENCE,
@@ -297,9 +316,10 @@ namespace llvm {
ATOMNAND64_DAG,
ATOMSWAP64_DAG,
- // LCMPXCHG_DAG, LCMPXCHG8_DAG - Compare and swap.
+ // LCMPXCHG_DAG, LCMPXCHG8_DAG, LCMPXCHG16_DAG - Compare and swap.
LCMPXCHG_DAG,
LCMPXCHG8_DAG,
+ LCMPXCHG16_DAG,
// VZEXT_LOAD - Load, scalar_to_vector, and zero extend.
VZEXT_LOAD,
@@ -407,20 +427,16 @@ namespace llvm {
/// isMOVSHDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVSHDUP.
- bool isMOVSHDUPMask(ShuffleVectorSDNode *N);
+ bool isMOVSHDUPMask(ShuffleVectorSDNode *N, const X86Subtarget *Subtarget);
/// isMOVSLDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVSLDUP.
- bool isMOVSLDUPMask(ShuffleVectorSDNode *N);
+ bool isMOVSLDUPMask(ShuffleVectorSDNode *N, const X86Subtarget *Subtarget);
/// isMOVDDUPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVDDUP.
bool isMOVDDUPMask(ShuffleVectorSDNode *N);
- /// isPALIGNRMask - Return true if the specified VECTOR_SHUFFLE operand
- /// specifies a shuffle of elements that is suitable for input to PALIGNR.
- bool isPALIGNRMask(ShuffleVectorSDNode *N);
-
/// isVEXTRACTF128Index - Return true if the specified
/// EXTRACT_SUBVECTOR operand specifies a vector extract that is
/// suitable for input to VEXTRACTF128.
@@ -505,7 +521,7 @@ namespace llvm {
/// function arguments in the caller parameter area. For X86, aggregates
/// that contains are placed at 16-byte boundaries while the rest are at
/// 4-byte boundaries.
- virtual unsigned getByValTypeAlignment(const Type *Ty) const;
+ virtual unsigned getByValTypeAlignment(Type *Ty) const;
/// getOptimalMemOpType - Returns the target specific optimal type for load
/// and store operations as a result of memset, memcpy, and memmove
@@ -564,8 +580,8 @@ namespace llvm {
/// DAG node.
virtual const char *getTargetNodeName(unsigned Opcode) const;
- /// getSetCCResultType - Return the ISD::SETCC ValueType
- virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
+ /// getSetCCResultType - Return the value type to use for ISD::SETCC.
+ virtual EVT getSetCCResultType(EVT VT) const;
/// computeMaskedBitsForTargetNode - Determine which of the bits specified
/// in Mask are known to be either zero or one and return them in the
@@ -617,12 +633,12 @@ 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;
/// 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;
virtual bool isTruncateFree(EVT VT1, EVT VT2) const;
/// isZExtFree - Return true if any actual instruction that defines a
@@ -633,7 +649,7 @@ namespace llvm {
/// 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;
virtual bool isZExtFree(EVT VT1, EVT VT2) const;
/// isNarrowingProfitable - Return true if it's profitable to narrow
@@ -813,11 +829,14 @@ namespace llvm {
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
- SDValue LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerCTLZ(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerCTTZ(SDValue Op, SelectionDAG &DAG) const;
- SDValue LowerMUL_V2I64(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerADD(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerSUB(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerShift(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerXALUO(SDValue Op, SelectionDAG &DAG) const;
@@ -825,6 +844,7 @@ namespace llvm {
SDValue LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const;
// Utility functions to help LowerVECTOR_SHUFFLE
@@ -931,6 +951,10 @@ namespace llvm {
MachineBasicBlock *EmitLoweredWinAlloca(MachineInstr *MI,
MachineBasicBlock *BB) const;
+ MachineBasicBlock *EmitLoweredSegAlloca(MachineInstr *MI,
+ MachineBasicBlock *BB,
+ bool Is64Bit) const;
+
MachineBasicBlock *EmitLoweredTLSCall(MachineInstr *MI,
MachineBasicBlock *BB) const;
diff --git a/lib/Target/X86/X86InstrArithmetic.td b/lib/Target/X86/X86InstrArithmetic.td
index 9f7a4b0..74b647a 100644
--- a/lib/Target/X86/X86InstrArithmetic.td
+++ b/lib/Target/X86/X86InstrArithmetic.td
@@ -650,6 +650,15 @@ class BinOpRR_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo>
let isCodeGenOnly = 1;
}
+// BinOpRR_F_Rev - Instructions like "cmp reg, reg" (reversed encoding).
+class BinOpRR_F_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo>
+ : ITy<opcode, MRMSrcReg, typeinfo, (outs),
+ (ins typeinfo.RegClass:$src1, typeinfo.RegClass:$src2),
+ mnemonic, "{$src2, $src1|$src1, $src2}", []> {
+ // The disassembler should know about this, but not the asmparser.
+ let isCodeGenOnly = 1;
+}
+
// BinOpRM - Instructions like "add reg, reg, [mem]".
class BinOpRM<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
dag outlist, list<dag> pattern>
@@ -857,11 +866,10 @@ class BinOpMI8_F<string mnemonic, X86TypeInfo typeinfo,
// BinOpAI - Instructions like "add %eax, %eax, imm".
class BinOpAI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
- Register areg>
+ Register areg, string operands>
: ITy<opcode, RawFrm, typeinfo,
(outs), (ins typeinfo.ImmOperand:$src),
- mnemonic, !strconcat("{$src, %", areg.AsmName, "|%",
- areg.AsmName, ", $src}"), []> {
+ mnemonic, operands, []> {
let ImmT = typeinfo.ImmEncoding;
let Uses = [areg];
let Defs = [areg];
@@ -926,10 +934,14 @@ multiclass ArithBinOp_RF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
def #NAME#32mi : BinOpMI_RMW<mnemonic, Xi32, opnode, MemMRM>;
def #NAME#64mi32 : BinOpMI_RMW<mnemonic, Xi64, opnode, MemMRM>;
- def #NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL>;
- def #NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX>;
- def #NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX>;
- def #NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX>;
+ def #NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
+ "{$src, %al|AL, $src}">;
+ def #NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
+ "{$src, %ax|AX, $src}">;
+ def #NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
+ "{$src, %eax|EAX, $src}">;
+ def #NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
+ "{$src, %rax|RAX, $src}">;
}
}
@@ -993,10 +1005,14 @@ multiclass ArithBinOp_RFF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
def #NAME#32mi : BinOpMI_RMW_FF<mnemonic, Xi32, opnode, MemMRM>;
def #NAME#64mi32 : BinOpMI_RMW_FF<mnemonic, Xi64, opnode, MemMRM>;
- def #NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL>;
- def #NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX>;
- def #NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX>;
- def #NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX>;
+ def #NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
+ "{$src, %al|AL, $src}">;
+ def #NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
+ "{$src, %ax|AX, $src}">;
+ def #NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
+ "{$src, %eax|EAX, $src}">;
+ def #NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
+ "{$src, %rax|RAX, $src}">;
}
}
@@ -1017,10 +1033,10 @@ multiclass ArithBinOp_F<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
def #NAME#64rr : BinOpRR_F<BaseOpc, mnemonic, Xi64, opnode>;
} // isCommutable
- def #NAME#8rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi8>;
- def #NAME#16rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi16>;
- def #NAME#32rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi32>;
- def #NAME#64rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi64>;
+ def #NAME#8rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi8>;
+ def #NAME#16rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi16>;
+ def #NAME#32rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi32>;
+ def #NAME#64rr_REV : BinOpRR_F_Rev<BaseOpc2, mnemonic, Xi64>;
def #NAME#8rm : BinOpRM_F<BaseOpc2, mnemonic, Xi8 , opnode>;
def #NAME#16rm : BinOpRM_F<BaseOpc2, mnemonic, Xi16, opnode>;
@@ -1056,10 +1072,14 @@ multiclass ArithBinOp_F<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
def #NAME#32mi : BinOpMI_F<mnemonic, Xi32, opnode, MemMRM>;
def #NAME#64mi32 : BinOpMI_F<mnemonic, Xi64, opnode, MemMRM>;
- def #NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL>;
- def #NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX>;
- def #NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX>;
- def #NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX>;
+ def #NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
+ "{$src, %al|AL, $src}">;
+ def #NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
+ "{$src, %ax|AX, $src}">;
+ def #NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
+ "{$src, %eax|EAX, $src}">;
+ def #NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
+ "{$src, %rax|RAX, $src}">;
}
}
@@ -1117,9 +1137,37 @@ let Defs = [EFLAGS] in {
def TEST32mi : BinOpMI_F<"test", Xi32, X86testpat, MRM0m, 0xF6>;
def TEST64mi32 : BinOpMI_F<"test", Xi64, X86testpat, MRM0m, 0xF6>;
- def TEST8i8 : BinOpAI<0xA8, "test", Xi8 , AL>;
- def TEST16i16 : BinOpAI<0xA8, "test", Xi16, AX>;
- def TEST32i32 : BinOpAI<0xA8, "test", Xi32, EAX>;
- def TEST64i32 : BinOpAI<0xA8, "test", Xi64, RAX>;
-}
+ def TEST8i8 : BinOpAI<0xA8, "test", Xi8 , AL,
+ "{$src, %al|AL, $src}">;
+ def TEST16i16 : BinOpAI<0xA8, "test", Xi16, AX,
+ "{$src, %ax|AX, $src}">;
+ def TEST32i32 : BinOpAI<0xA8, "test", Xi32, EAX,
+ "{$src, %eax|EAX, $src}">;
+ def TEST64i32 : BinOpAI<0xA8, "test", Xi64, RAX,
+ "{$src, %rax|RAX, $src}">;
+
+ // When testing the result of EXTRACT_SUBREG sub_8bit_hi, make sure the
+ // register class is constrained to GR8_NOREX.
+ let isPseudo = 1 in
+ def TEST8ri_NOREX : I<0, Pseudo, (outs), (ins GR8_NOREX:$src, i8imm:$mask),
+ "", []>;
+}
+//===----------------------------------------------------------------------===//
+// ANDN Instruction
+//
+multiclass bmi_andn<string mnemonic, RegisterClass RC, X86MemOperand x86memop,
+ PatFrag ld_frag> {
+ def rr : I<0xF2, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2),
+ !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
+ [(set RC:$dst, EFLAGS, (X86andn_flag RC:$src1, RC:$src2))]>;
+ def rm : I<0xF2, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2),
+ !strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
+ [(set RC:$dst, EFLAGS,
+ (X86andn_flag RC:$src1, (ld_frag addr:$src2)))]>;
+}
+
+let Predicates = [HasBMI], Defs = [EFLAGS] in {
+ defm ANDN32 : bmi_andn<"andn{l}", GR32, i32mem, loadi32>, T8, VEX_4V;
+ defm ANDN64 : bmi_andn<"andn{q}", GR64, i64mem, loadi64>, T8, VEX_4V, VEX_W;
+}
diff --git a/lib/Target/X86/X86InstrCompiler.td b/lib/Target/X86/X86InstrCompiler.td
index adcc747..da28690 100644
--- a/lib/Target/X86/X86InstrCompiler.td
+++ b/lib/Target/X86/X86InstrCompiler.td
@@ -106,6 +106,26 @@ let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in
def WIN_ALLOCA : I<0, Pseudo, (outs), (ins),
"# dynamic stack allocation",
[(X86WinAlloca)]>;
+
+// When using segmented stacks these are lowered into instructions which first
+// check if the current stacklet has enough free memory. If it does, memory is
+// allocated by bumping the stack pointer. Otherwise memory is allocated from
+// the heap.
+
+let Defs = [EAX, ESP, EFLAGS], Uses = [ESP, EAX] in
+def SEG_ALLOCA_32 : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$size),
+ "# variable sized alloca for segmented stacks",
+ [(set GR32:$dst,
+ (X86SegAlloca GR32:$size))]>,
+ Requires<[In32BitMode]>;
+
+let Defs = [RAX, RSP, EFLAGS], Uses = [RSP, RAX] in
+def SEG_ALLOCA_64 : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$size),
+ "# variable sized alloca for segmented stacks",
+ [(set GR64:$dst,
+ (X86SegAlloca GR64:$size))]>,
+ Requires<[In64BitMode]>;
+
}
@@ -329,18 +349,11 @@ def TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
//===----------------------------------------------------------------------===//
// Conditional Move Pseudo Instructions
-let Constraints = "$src1 = $dst" in {
-
-// Conditional moves
-let Uses = [EFLAGS] in {
-
// X86 doesn't have 8-bit conditional moves. Use a customInserter to
// emit control flow. An alternative to this is to mark i8 SELECT as Promote,
// however that requires promoting the operands, and can induce additional
-// i8 register pressure. Note that CMOV_GR8 is conservatively considered to
-// clobber EFLAGS, because if one of the operands is zero, the expansion
-// could involve an xor.
-let usesCustomInserter = 1, Constraints = "", Defs = [EFLAGS] in {
+// i8 register pressure.
+let usesCustomInserter = 1, Uses = [EFLAGS] in {
def CMOV_GR8 : I<0, Pseudo,
(outs GR8:$dst), (ins GR8:$src1, GR8:$src2, i8imm:$cond),
"#CMOV_GR8 PSEUDO!",
@@ -380,10 +393,7 @@ def CMOV_RFP80 : I<0, Pseudo,
(X86cmov RFP80:$src1, RFP80:$src2, imm:$cond,
EFLAGS))]>;
} // Predicates = [NoCMov]
-} // UsesCustomInserter = 1, Constraints = "", Defs = [EFLAGS]
-} // Uses = [EFLAGS]
-
-} // Constraints = "$src1 = $dst" in
+} // UsesCustomInserter = 1, Uses = [EFLAGS]
//===----------------------------------------------------------------------===//
@@ -532,7 +542,7 @@ def OR32mrLocked : I<0x09, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$zero),
let hasSideEffects = 1 in
def Int_MemBarrier : I<0, Pseudo, (outs), (ins),
"#MEMBARRIER",
- [(X86MemBarrier)]>, Requires<[HasSSE2]>;
+ [(X86MemBarrier)]>;
// TODO: Get this to fold the constant into the instruction.
let hasSideEffects = 1, Defs = [ESP], isCodeGenOnly = 1 in
@@ -630,8 +640,8 @@ def #NAME#64mi8 : RIi8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4},
defm LOCK_ADD : LOCK_ArithBinOp<0x00, 0x80, 0x83, MRM0m, "add">;
defm LOCK_SUB : LOCK_ArithBinOp<0x28, 0x80, 0x83, MRM5m, "sub">;
defm LOCK_OR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM1m, "or">;
-defm LOCK_AND : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM4m, "and">;
-defm LOCK_XOR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM6m, "xor">;
+defm LOCK_AND : LOCK_ArithBinOp<0x20, 0x80, 0x83, MRM4m, "and">;
+defm LOCK_XOR : LOCK_ArithBinOp<0x30, 0x80, 0x83, MRM6m, "xor">;
// Optimized codegen when the non-memory output is not used.
let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1 in {
@@ -665,12 +675,20 @@ def LOCK_DEC64m : RI<0xFF, MRM1m, (outs), (ins i64mem:$dst),
// Atomic compare and swap.
let Defs = [EAX, EDX, EFLAGS], Uses = [EAX, EBX, ECX, EDX],
- isCodeGenOnly = 1 in {
+ isCodeGenOnly = 1 in
def LCMPXCHG8B : I<0xC7, MRM1m, (outs), (ins i64mem:$ptr),
"lock\n\t"
"cmpxchg8b\t$ptr",
[(X86cas8 addr:$ptr)]>, TB, LOCK;
-}
+
+let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RBX, RCX, RDX],
+ isCodeGenOnly = 1 in
+def LCMPXCHG16B : RI<0xC7, MRM1m, (outs), (ins i128mem:$ptr),
+ "lock\n\t"
+ "cmpxchg16b\t$ptr",
+ [(X86cas16 addr:$ptr)]>, TB, LOCK,
+ Requires<[HasCmpxchg16b]>;
+
let Defs = [AL, EFLAGS], Uses = [AL], isCodeGenOnly = 1 in {
def LCMPXCHG8 : I<0xB0, MRMDestMem, (outs), (ins i8mem:$ptr, GR8:$swap),
"lock\n\t"
@@ -695,7 +713,7 @@ def LCMPXCHG32 : I<0xB1, MRMDestMem, (outs), (ins i32mem:$ptr, GR32:$swap),
let Defs = [RAX, EFLAGS], Uses = [RAX], isCodeGenOnly = 1 in {
def LCMPXCHG64 : RI<0xB1, MRMDestMem, (outs), (ins i64mem:$ptr, GR64:$swap),
"lock\n\t"
- "cmpxchgq\t$swap,$ptr",
+ "cmpxchg{q}\t{$swap, $ptr|$ptr, $swap}",
[(X86cas addr:$ptr, GR64:$swap, 8)]>, TB, LOCK;
}
@@ -718,11 +736,37 @@ def LXADD32 : I<0xC1, MRMSrcMem, (outs GR32:$dst), (ins GR32:$val, i32mem:$ptr),
TB, LOCK;
def LXADD64 : RI<0xC1, MRMSrcMem, (outs GR64:$dst), (ins GR64:$val,i64mem:$ptr),
"lock\n\t"
- "xadd\t$val, $ptr",
+ "xadd{q}\t{$val, $ptr|$ptr, $val}",
[(set GR64:$dst, (atomic_load_add_64 addr:$ptr, GR64:$val))]>,
TB, LOCK;
}
+def ACQUIRE_MOV8rm : I<0, Pseudo, (outs GR8 :$dst), (ins i8mem :$src),
+ "#ACQUIRE_MOV PSEUDO!",
+ [(set GR8:$dst, (atomic_load_8 addr:$src))]>;
+def ACQUIRE_MOV16rm : I<0, Pseudo, (outs GR16:$dst), (ins i16mem:$src),
+ "#ACQUIRE_MOV PSEUDO!",
+ [(set GR16:$dst, (atomic_load_16 addr:$src))]>;
+def ACQUIRE_MOV32rm : I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$src),
+ "#ACQUIRE_MOV PSEUDO!",
+ [(set GR32:$dst, (atomic_load_32 addr:$src))]>;
+def ACQUIRE_MOV64rm : I<0, Pseudo, (outs GR64:$dst), (ins i64mem:$src),
+ "#ACQUIRE_MOV PSEUDO!",
+ [(set GR64:$dst, (atomic_load_64 addr:$src))]>;
+
+def RELEASE_MOV8mr : I<0, Pseudo, (outs), (ins i8mem :$dst, GR8 :$src),
+ "#RELEASE_MOV PSEUDO!",
+ [(atomic_store_8 addr:$dst, GR8 :$src)]>;
+def RELEASE_MOV16mr : I<0, Pseudo, (outs), (ins i16mem:$dst, GR16:$src),
+ "#RELEASE_MOV PSEUDO!",
+ [(atomic_store_16 addr:$dst, GR16:$src)]>;
+def RELEASE_MOV32mr : I<0, Pseudo, (outs), (ins i32mem:$dst, GR32:$src),
+ "#RELEASE_MOV PSEUDO!",
+ [(atomic_store_32 addr:$dst, GR32:$src)]>;
+def RELEASE_MOV64mr : I<0, Pseudo, (outs), (ins i64mem:$dst, GR64:$src),
+ "#RELEASE_MOV PSEUDO!",
+ [(atomic_store_64 addr:$dst, GR64:$src)]>;
+
//===----------------------------------------------------------------------===//
// Conditional Move Pseudo Instructions.
//===----------------------------------------------------------------------===//
@@ -759,6 +803,24 @@ let Uses = [EFLAGS], usesCustomInserter = 1 in {
[(set VR128:$dst,
(v2i64 (X86cmov VR128:$t, VR128:$f, imm:$cond,
EFLAGS)))]>;
+ def CMOV_V8F32 : I<0, Pseudo,
+ (outs VR256:$dst), (ins VR256:$t, VR256:$f, i8imm:$cond),
+ "#CMOV_V8F32 PSEUDO!",
+ [(set VR256:$dst,
+ (v8f32 (X86cmov VR256:$t, VR256:$f, imm:$cond,
+ EFLAGS)))]>;
+ def CMOV_V4F64 : I<0, Pseudo,
+ (outs VR256:$dst), (ins VR256:$t, VR256:$f, i8imm:$cond),
+ "#CMOV_V4F64 PSEUDO!",
+ [(set VR256:$dst,
+ (v4f64 (X86cmov VR256:$t, VR256:$f, imm:$cond,
+ EFLAGS)))]>;
+ def CMOV_V4I64 : I<0, Pseudo,
+ (outs VR256:$dst), (ins VR256:$t, VR256:$f, i8imm:$cond),
+ "#CMOV_V4I64 PSEUDO!",
+ [(set VR256:$dst,
+ (v4i64 (X86cmov VR256:$t, VR256:$f, imm:$cond,
+ EFLAGS)))]>;
}
diff --git a/lib/Target/X86/X86InstrExtension.td b/lib/Target/X86/X86InstrExtension.td
index 2e1d523..e62e6b7 100644
--- a/lib/Target/X86/X86InstrExtension.td
+++ b/lib/Target/X86/X86InstrExtension.td
@@ -76,12 +76,12 @@ def MOVZX32rm16: I<0xB7, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src),
// except that they use GR32_NOREX for the output operand register class
// instead of GR32. This allows them to operate on h registers on x86-64.
def MOVZX32_NOREXrr8 : I<0xB6, MRMSrcReg,
- (outs GR32_NOREX:$dst), (ins GR8:$src),
+ (outs GR32_NOREX:$dst), (ins GR8_NOREX:$src),
"movz{bl|x}\t{$src, $dst|$dst, $src}",
[]>, TB;
let mayLoad = 1 in
def MOVZX32_NOREXrm8 : I<0xB6, MRMSrcMem,
- (outs GR32_NOREX:$dst), (ins i8mem:$src),
+ (outs GR32_NOREX:$dst), (ins i8mem_NOREX:$src),
"movz{bl|x}\t{$src, $dst|$dst, $src}",
[]>, TB;
diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td
index 6d89bcc..0a1590b 100644
--- a/lib/Target/X86/X86InstrFormats.td
+++ b/lib/Target/X86/X86InstrFormats.td
@@ -113,6 +113,7 @@ class VEX_W { bit hasVEX_WPrefix = 1; }
class VEX_4V : VEX { bit hasVEX_4VPrefix = 1; }
class VEX_I8IMM { bit hasVEX_i8ImmReg = 1; }
class VEX_L { bit hasVEX_L = 1; }
+class VEX_LIG { bit ignoresVEX_L = 1; }
class Has3DNow0F0FOpcode { bit has3DNow0F0FOpcode = 1; }
class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
@@ -150,6 +151,7 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
bit hasVEX_i8ImmReg = 0; // Does this inst require the last source register
// to be encoded in a immediate field?
bit hasVEX_L = 0; // Does this inst use large (256-bit) registers?
+ bit ignoresVEX_L = 0; // Does this instruction ignore the L-bit
bit has3DNow0F0FOpcode =0;// Wacky 3dNow! encoding?
// TSFlags layout should be kept in sync with X86InstrInfo.h.
@@ -169,7 +171,8 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
let TSFlags{35} = hasVEX_4VPrefix;
let TSFlags{36} = hasVEX_i8ImmReg;
let TSFlags{37} = hasVEX_L;
- let TSFlags{38} = has3DNow0F0FOpcode;
+ let TSFlags{38} = ignoresVEX_L;
+ let TSFlags{39} = has3DNow0F0FOpcode;
}
class PseudoI<dag oops, dag iops, list<dag> pattern>
@@ -501,6 +504,9 @@ class RSDI<bits<8> o, Format F, dag outs, dag ins, string asm,
class RPDI<bits<8> o, Format F, dag outs, dag ins, string asm,
list<dag> pattern>
: PDI<o, F, outs, ins, asm, pattern>, REX_W;
+class VRPDI<bits<8> o, Format F, dag outs, dag ins, string asm,
+ list<dag> pattern>
+ : VPDI<o, F, outs, ins, asm, pattern>, VEX_W;
// MMX Instruction templates
//
diff --git a/lib/Target/X86/X86InstrFragmentsSIMD.td b/lib/Target/X86/X86InstrFragmentsSIMD.td
index b00109c..af919fb 100644
--- a/lib/Target/X86/X86InstrFragmentsSIMD.td
+++ b/lib/Target/X86/X86InstrFragmentsSIMD.td
@@ -39,6 +39,8 @@ def X86frsqrt : SDNode<"X86ISD::FRSQRT", SDTFPUnaryOp>;
def X86frcp : SDNode<"X86ISD::FRCP", SDTFPUnaryOp>;
def X86fsrl : SDNode<"X86ISD::FSRL", SDTX86FPShiftOp>;
def X86fgetsign: SDNode<"X86ISD::FGETSIGNx86",SDTFPToIntOp>;
+def X86fhadd : SDNode<"X86ISD::FHADD", SDTFPBinOp>;
+def X86fhsub : SDNode<"X86ISD::FHSUB", SDTFPBinOp>;
def X86comi : SDNode<"X86ISD::COMI", SDTX86CmpTest>;
def X86ucomi : SDNode<"X86ISD::UCOMI", SDTX86CmpTest>;
def X86cmpss : SDNode<"X86ISD::FSETCCss", SDTX86Cmpss>;
@@ -49,18 +51,15 @@ def X86pshufb : SDNode<"X86ISD::PSHUFB",
def X86andnp : SDNode<"X86ISD::ANDNP",
SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>]>>;
-def X86psignb : SDNode<"X86ISD::PSIGNB",
+def X86psignb : SDNode<"X86ISD::PSIGNB",
SDTypeProfile<1, 2, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>]>>;
-def X86psignw : SDNode<"X86ISD::PSIGNW",
+def X86psignw : SDNode<"X86ISD::PSIGNW",
SDTypeProfile<1, 2, [SDTCisVT<0, v8i16>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>]>>;
-def X86psignd : SDNode<"X86ISD::PSIGND",
+def X86psignd : SDNode<"X86ISD::PSIGND",
SDTypeProfile<1, 2, [SDTCisVT<0, v4i32>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>]>>;
-def X86pblendv : SDNode<"X86ISD::PBLENDVB",
- SDTypeProfile<1, 3, [SDTCisVT<0, v16i8>, SDTCisSameAs<0,1>,
- SDTCisSameAs<0,2>, SDTCisSameAs<0,3>]>>;
def X86pextrb : SDNode<"X86ISD::PEXTRB",
SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisPtrTy<2>]>>;
def X86pextrw : SDNode<"X86ISD::PEXTRW",
@@ -109,6 +108,8 @@ def SDTShuff2OpI : SDTypeProfile<1, 2, [SDTCisVec<0>,
def SDTShuff3OpI : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>, SDTCisInt<3>]>;
+def SDTVBroadcast : SDTypeProfile<1, 1, [SDTCisVec<0>]>;
+
def X86PAlign : SDNode<"X86ISD::PALIGN", SDTShuff3OpI>;
def X86PShufd : SDNode<"X86ISD::PSHUFD", SDTShuff2OpI>;
@@ -133,12 +134,15 @@ def X86Movhlpd : SDNode<"X86ISD::MOVHLPD", SDTShuff2Op>;
def X86Movlps : SDNode<"X86ISD::MOVLPS", SDTShuff2Op>;
def X86Movlpd : SDNode<"X86ISD::MOVLPD", SDTShuff2Op>;
-def X86Unpcklps : SDNode<"X86ISD::UNPCKLPS", SDTShuff2Op>;
-def X86Unpcklpd : SDNode<"X86ISD::UNPCKLPD", SDTShuff2Op>;
+def X86Unpcklps : SDNode<"X86ISD::UNPCKLPS", SDTShuff2Op>;
+def X86Unpcklpd : SDNode<"X86ISD::UNPCKLPD", SDTShuff2Op>;
def X86Unpcklpsy : SDNode<"X86ISD::VUNPCKLPSY", SDTShuff2Op>;
def X86Unpcklpdy : SDNode<"X86ISD::VUNPCKLPDY", SDTShuff2Op>;
-def X86Unpckhps : SDNode<"X86ISD::UNPCKHPS", SDTShuff2Op>;
-def X86Unpckhpd : SDNode<"X86ISD::UNPCKHPD", SDTShuff2Op>;
+
+def X86Unpckhps : SDNode<"X86ISD::UNPCKHPS", SDTShuff2Op>;
+def X86Unpckhpd : SDNode<"X86ISD::UNPCKHPD", SDTShuff2Op>;
+def X86Unpckhpsy : SDNode<"X86ISD::VUNPCKHPSY", SDTShuff2Op>;
+def X86Unpckhpdy : SDNode<"X86ISD::VUNPCKHPDY", SDTShuff2Op>;
def X86Punpcklbw : SDNode<"X86ISD::PUNPCKLBW", SDTShuff2Op>;
def X86Punpcklwd : SDNode<"X86ISD::PUNPCKLWD", SDTShuff2Op>;
@@ -150,6 +154,15 @@ def X86Punpckhwd : SDNode<"X86ISD::PUNPCKHWD", SDTShuff2Op>;
def X86Punpckhdq : SDNode<"X86ISD::PUNPCKHDQ", SDTShuff2Op>;
def X86Punpckhqdq : SDNode<"X86ISD::PUNPCKHQDQ", SDTShuff2Op>;
+def X86VPermilps : SDNode<"X86ISD::VPERMILPS", SDTShuff2OpI>;
+def X86VPermilpsy : SDNode<"X86ISD::VPERMILPSY", SDTShuff2OpI>;
+def X86VPermilpd : SDNode<"X86ISD::VPERMILPD", SDTShuff2OpI>;
+def X86VPermilpdy : SDNode<"X86ISD::VPERMILPDY", SDTShuff2OpI>;
+
+def X86VPerm2f128 : SDNode<"X86ISD::VPERM2F128", SDTShuff3OpI>;
+
+def X86VBroadcast : SDNode<"X86ISD::VBROADCAST", SDTVBroadcast>;
+
//===----------------------------------------------------------------------===//
// SSE Complex Patterns
//===----------------------------------------------------------------------===//
@@ -193,17 +206,28 @@ def loadv4f64 : PatFrag<(ops node:$ptr), (v4f64 (load node:$ptr))>;
def loadv8i32 : PatFrag<(ops node:$ptr), (v8i32 (load node:$ptr))>;
def loadv4i64 : PatFrag<(ops node:$ptr), (v4i64 (load node:$ptr))>;
-// Like 'store', but always requires vector alignment.
+// Like 'store', but always requires 128-bit vector alignment.
def alignedstore : PatFrag<(ops node:$val, node:$ptr),
(store node:$val, node:$ptr), [{
return cast<StoreSDNode>(N)->getAlignment() >= 16;
}]>;
-// Like 'load', but always requires vector alignment.
+// Like 'store', but always requires 256-bit vector alignment.
+def alignedstore256 : PatFrag<(ops node:$val, node:$ptr),
+ (store node:$val, node:$ptr), [{
+ return cast<StoreSDNode>(N)->getAlignment() >= 32;
+}]>;
+
+// Like 'load', but always requires 128-bit vector alignment.
def alignedload : PatFrag<(ops node:$ptr), (load node:$ptr), [{
return cast<LoadSDNode>(N)->getAlignment() >= 16;
}]>;
+// Like 'load', but always requires 256-bit vector alignment.
+def alignedload256 : PatFrag<(ops node:$ptr), (load node:$ptr), [{
+ return cast<LoadSDNode>(N)->getAlignment() >= 32;
+}]>;
+
def alignedloadfsf32 : PatFrag<(ops node:$ptr),
(f32 (alignedload node:$ptr))>;
def alignedloadfsf64 : PatFrag<(ops node:$ptr),
@@ -221,13 +245,13 @@ def alignedloadv2i64 : PatFrag<(ops node:$ptr),
// 256-bit aligned load pattern fragments
def alignedloadv8f32 : PatFrag<(ops node:$ptr),
- (v8f32 (alignedload node:$ptr))>;
+ (v8f32 (alignedload256 node:$ptr))>;
def alignedloadv4f64 : PatFrag<(ops node:$ptr),
- (v4f64 (alignedload node:$ptr))>;
+ (v4f64 (alignedload256 node:$ptr))>;
def alignedloadv8i32 : PatFrag<(ops node:$ptr),
- (v8i32 (alignedload node:$ptr))>;
+ (v8i32 (alignedload256 node:$ptr))>;
def alignedloadv4i64 : PatFrag<(ops node:$ptr),
- (v4i64 (alignedload node:$ptr))>;
+ (v4i64 (alignedload256 node:$ptr))>;
// Like 'load', but uses special alignment checks suitable for use in
// memory operands in most SSE instructions, which are required to
@@ -356,7 +380,7 @@ def EXTRACT_get_vextractf128_imm : SDNodeXForm<extract_subvector, [{
return getI8Imm(X86::getExtractVEXTRACTF128Immediate(N));
}]>;
-// INSERT_get_vinsertf128_imm xform function: convert insert_subvector index to
+// INSERT_get_vinsertf128_imm xform function: convert insert_subvector index to
// VINSERTF128 imm.
def INSERT_get_vinsertf128_imm : SDNodeXForm<insert_subvector, [{
return getI8Imm(X86::getInsertVINSERTF128Immediate(N));
@@ -398,16 +422,6 @@ def movl : PatFrag<(ops node:$lhs, node:$rhs),
return X86::isMOVLMask(cast<ShuffleVectorSDNode>(N));
}]>;
-def movshdup : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
- return X86::isMOVSHDUPMask(cast<ShuffleVectorSDNode>(N));
-}]>;
-
-def movsldup : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
- return X86::isMOVSLDUPMask(cast<ShuffleVectorSDNode>(N));
-}]>;
-
def unpckl : PatFrag<(ops node:$lhs, node:$rhs),
(vector_shuffle node:$lhs, node:$rhs), [{
return X86::isUNPCKLMask(cast<ShuffleVectorSDNode>(N));
@@ -418,16 +432,6 @@ def unpckh : PatFrag<(ops node:$lhs, node:$rhs),
return X86::isUNPCKHMask(cast<ShuffleVectorSDNode>(N));
}]>;
-def unpckl_undef : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
- return X86::isUNPCKL_v_undef_Mask(cast<ShuffleVectorSDNode>(N));
-}]>;
-
-def unpckh_undef : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
- return X86::isUNPCKH_v_undef_Mask(cast<ShuffleVectorSDNode>(N));
-}]>;
-
def pshufd : PatFrag<(ops node:$lhs, node:$rhs),
(vector_shuffle node:$lhs, node:$rhs), [{
return X86::isPSHUFDMask(cast<ShuffleVectorSDNode>(N));
@@ -448,11 +452,6 @@ def pshuflw : PatFrag<(ops node:$lhs, node:$rhs),
return X86::isPSHUFLWMask(cast<ShuffleVectorSDNode>(N));
}], SHUFFLE_get_pshuflw_imm>;
-def palign : PatFrag<(ops node:$lhs, node:$rhs),
- (vector_shuffle node:$lhs, node:$rhs), [{
- return X86::isPALIGNRMask(cast<ShuffleVectorSDNode>(N));
-}], SHUFFLE_get_palign_imm>;
-
def vextractf128_extract : PatFrag<(ops node:$bigvec, node:$index),
(extract_subvector node:$bigvec,
node:$index), [{
@@ -465,3 +464,4 @@ def vinsertf128_insert : PatFrag<(ops node:$bigvec, node:$smallvec,
node:$index), [{
return X86::isVINSERTF128Index(N);
}], INSERT_get_vinsertf128_imm>;
+
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 55b5835..3a02de0 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -53,6 +53,36 @@ ReMatPICStubLoad("remat-pic-stub-load",
cl::desc("Re-materialize load from stub in PIC mode"),
cl::init(false), cl::Hidden);
+enum {
+ // Select which memory operand is being unfolded.
+ // (stored in bits 0 - 7)
+ TB_INDEX_0 = 0,
+ TB_INDEX_1 = 1,
+ TB_INDEX_2 = 2,
+ TB_INDEX_MASK = 0xff,
+
+ // Minimum alignment required for load/store.
+ // Used for RegOp->MemOp conversion.
+ // (stored in bits 8 - 15)
+ TB_ALIGN_SHIFT = 8,
+ TB_ALIGN_NONE = 0 << TB_ALIGN_SHIFT,
+ TB_ALIGN_16 = 16 << TB_ALIGN_SHIFT,
+ TB_ALIGN_32 = 32 << TB_ALIGN_SHIFT,
+ TB_ALIGN_MASK = 0xff << TB_ALIGN_SHIFT,
+
+ // Do not insert the reverse map (MemOp -> RegOp) into the table.
+ // This may be needed because there is a many -> one mapping.
+ TB_NO_REVERSE = 1 << 16,
+
+ // Do not insert the forward map (RegOp -> MemOp) into the table.
+ // This is needed for Native Client, which prohibits branch
+ // instructions from using a memory operand.
+ TB_NO_FORWARD = 1 << 17,
+
+ TB_FOLDED_LOAD = 1 << 18,
+ TB_FOLDED_STORE = 1 << 19
+};
+
X86InstrInfo::X86InstrInfo(X86TargetMachine &tm)
: X86GenInstrInfo((tm.getSubtarget<X86Subtarget>().is64Bit()
? X86::ADJCALLSTACKDOWN64
@@ -61,655 +91,829 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm)
? X86::ADJCALLSTACKUP64
: X86::ADJCALLSTACKUP32)),
TM(tm), RI(tm, *this) {
- enum {
- TB_NOT_REVERSABLE = 1U << 31,
- TB_FLAGS = TB_NOT_REVERSABLE
- };
- static const unsigned OpTbl2Addr[][2] = {
- { X86::ADC32ri, X86::ADC32mi },
- { X86::ADC32ri8, X86::ADC32mi8 },
- { X86::ADC32rr, X86::ADC32mr },
- { X86::ADC64ri32, X86::ADC64mi32 },
- { X86::ADC64ri8, X86::ADC64mi8 },
- { X86::ADC64rr, X86::ADC64mr },
- { X86::ADD16ri, X86::ADD16mi },
- { X86::ADD16ri8, X86::ADD16mi8 },
- { X86::ADD16ri_DB, X86::ADD16mi | TB_NOT_REVERSABLE },
- { X86::ADD16ri8_DB, X86::ADD16mi8 | TB_NOT_REVERSABLE },
- { X86::ADD16rr, X86::ADD16mr },
- { X86::ADD16rr_DB, X86::ADD16mr | TB_NOT_REVERSABLE },
- { X86::ADD32ri, X86::ADD32mi },
- { X86::ADD32ri8, X86::ADD32mi8 },
- { X86::ADD32ri_DB, X86::ADD32mi | TB_NOT_REVERSABLE },
- { X86::ADD32ri8_DB, X86::ADD32mi8 | TB_NOT_REVERSABLE },
- { X86::ADD32rr, X86::ADD32mr },
- { X86::ADD32rr_DB, X86::ADD32mr | TB_NOT_REVERSABLE },
- { X86::ADD64ri32, X86::ADD64mi32 },
- { X86::ADD64ri8, X86::ADD64mi8 },
- { X86::ADD64ri32_DB,X86::ADD64mi32 | TB_NOT_REVERSABLE },
- { X86::ADD64ri8_DB, X86::ADD64mi8 | TB_NOT_REVERSABLE },
- { X86::ADD64rr, X86::ADD64mr },
- { X86::ADD64rr_DB, X86::ADD64mr | TB_NOT_REVERSABLE },
- { X86::ADD8ri, X86::ADD8mi },
- { X86::ADD8rr, X86::ADD8mr },
- { X86::AND16ri, X86::AND16mi },
- { X86::AND16ri8, X86::AND16mi8 },
- { X86::AND16rr, X86::AND16mr },
- { X86::AND32ri, X86::AND32mi },
- { X86::AND32ri8, X86::AND32mi8 },
- { X86::AND32rr, X86::AND32mr },
- { X86::AND64ri32, X86::AND64mi32 },
- { X86::AND64ri8, X86::AND64mi8 },
- { X86::AND64rr, X86::AND64mr },
- { X86::AND8ri, X86::AND8mi },
- { X86::AND8rr, X86::AND8mr },
- { X86::DEC16r, X86::DEC16m },
- { X86::DEC32r, X86::DEC32m },
- { X86::DEC64_16r, X86::DEC64_16m },
- { X86::DEC64_32r, X86::DEC64_32m },
- { X86::DEC64r, X86::DEC64m },
- { X86::DEC8r, X86::DEC8m },
- { X86::INC16r, X86::INC16m },
- { X86::INC32r, X86::INC32m },
- { X86::INC64_16r, X86::INC64_16m },
- { X86::INC64_32r, X86::INC64_32m },
- { X86::INC64r, X86::INC64m },
- { X86::INC8r, X86::INC8m },
- { X86::NEG16r, X86::NEG16m },
- { X86::NEG32r, X86::NEG32m },
- { X86::NEG64r, X86::NEG64m },
- { X86::NEG8r, X86::NEG8m },
- { X86::NOT16r, X86::NOT16m },
- { X86::NOT32r, X86::NOT32m },
- { X86::NOT64r, X86::NOT64m },
- { X86::NOT8r, X86::NOT8m },
- { X86::OR16ri, X86::OR16mi },
- { X86::OR16ri8, X86::OR16mi8 },
- { X86::OR16rr, X86::OR16mr },
- { X86::OR32ri, X86::OR32mi },
- { X86::OR32ri8, X86::OR32mi8 },
- { X86::OR32rr, X86::OR32mr },
- { X86::OR64ri32, X86::OR64mi32 },
- { X86::OR64ri8, X86::OR64mi8 },
- { X86::OR64rr, X86::OR64mr },
- { X86::OR8ri, X86::OR8mi },
- { X86::OR8rr, X86::OR8mr },
- { X86::ROL16r1, X86::ROL16m1 },
- { X86::ROL16rCL, X86::ROL16mCL },
- { X86::ROL16ri, X86::ROL16mi },
- { X86::ROL32r1, X86::ROL32m1 },
- { X86::ROL32rCL, X86::ROL32mCL },
- { X86::ROL32ri, X86::ROL32mi },
- { X86::ROL64r1, X86::ROL64m1 },
- { X86::ROL64rCL, X86::ROL64mCL },
- { X86::ROL64ri, X86::ROL64mi },
- { X86::ROL8r1, X86::ROL8m1 },
- { X86::ROL8rCL, X86::ROL8mCL },
- { X86::ROL8ri, X86::ROL8mi },
- { X86::ROR16r1, X86::ROR16m1 },
- { X86::ROR16rCL, X86::ROR16mCL },
- { X86::ROR16ri, X86::ROR16mi },
- { X86::ROR32r1, X86::ROR32m1 },
- { X86::ROR32rCL, X86::ROR32mCL },
- { X86::ROR32ri, X86::ROR32mi },
- { X86::ROR64r1, X86::ROR64m1 },
- { X86::ROR64rCL, X86::ROR64mCL },
- { X86::ROR64ri, X86::ROR64mi },
- { X86::ROR8r1, X86::ROR8m1 },
- { X86::ROR8rCL, X86::ROR8mCL },
- { X86::ROR8ri, X86::ROR8mi },
- { X86::SAR16r1, X86::SAR16m1 },
- { X86::SAR16rCL, X86::SAR16mCL },
- { X86::SAR16ri, X86::SAR16mi },
- { X86::SAR32r1, X86::SAR32m1 },
- { X86::SAR32rCL, X86::SAR32mCL },
- { X86::SAR32ri, X86::SAR32mi },
- { X86::SAR64r1, X86::SAR64m1 },
- { X86::SAR64rCL, X86::SAR64mCL },
- { X86::SAR64ri, X86::SAR64mi },
- { X86::SAR8r1, X86::SAR8m1 },
- { X86::SAR8rCL, X86::SAR8mCL },
- { X86::SAR8ri, X86::SAR8mi },
- { X86::SBB32ri, X86::SBB32mi },
- { X86::SBB32ri8, X86::SBB32mi8 },
- { X86::SBB32rr, X86::SBB32mr },
- { X86::SBB64ri32, X86::SBB64mi32 },
- { X86::SBB64ri8, X86::SBB64mi8 },
- { X86::SBB64rr, X86::SBB64mr },
- { X86::SHL16rCL, X86::SHL16mCL },
- { X86::SHL16ri, X86::SHL16mi },
- { X86::SHL32rCL, X86::SHL32mCL },
- { X86::SHL32ri, X86::SHL32mi },
- { X86::SHL64rCL, X86::SHL64mCL },
- { X86::SHL64ri, X86::SHL64mi },
- { X86::SHL8rCL, X86::SHL8mCL },
- { X86::SHL8ri, X86::SHL8mi },
- { X86::SHLD16rrCL, X86::SHLD16mrCL },
- { X86::SHLD16rri8, X86::SHLD16mri8 },
- { X86::SHLD32rrCL, X86::SHLD32mrCL },
- { X86::SHLD32rri8, X86::SHLD32mri8 },
- { X86::SHLD64rrCL, X86::SHLD64mrCL },
- { X86::SHLD64rri8, X86::SHLD64mri8 },
- { X86::SHR16r1, X86::SHR16m1 },
- { X86::SHR16rCL, X86::SHR16mCL },
- { X86::SHR16ri, X86::SHR16mi },
- { X86::SHR32r1, X86::SHR32m1 },
- { X86::SHR32rCL, X86::SHR32mCL },
- { X86::SHR32ri, X86::SHR32mi },
- { X86::SHR64r1, X86::SHR64m1 },
- { X86::SHR64rCL, X86::SHR64mCL },
- { X86::SHR64ri, X86::SHR64mi },
- { X86::SHR8r1, X86::SHR8m1 },
- { X86::SHR8rCL, X86::SHR8mCL },
- { X86::SHR8ri, X86::SHR8mi },
- { X86::SHRD16rrCL, X86::SHRD16mrCL },
- { X86::SHRD16rri8, X86::SHRD16mri8 },
- { X86::SHRD32rrCL, X86::SHRD32mrCL },
- { X86::SHRD32rri8, X86::SHRD32mri8 },
- { X86::SHRD64rrCL, X86::SHRD64mrCL },
- { X86::SHRD64rri8, X86::SHRD64mri8 },
- { X86::SUB16ri, X86::SUB16mi },
- { X86::SUB16ri8, X86::SUB16mi8 },
- { X86::SUB16rr, X86::SUB16mr },
- { X86::SUB32ri, X86::SUB32mi },
- { X86::SUB32ri8, X86::SUB32mi8 },
- { X86::SUB32rr, X86::SUB32mr },
- { X86::SUB64ri32, X86::SUB64mi32 },
- { X86::SUB64ri8, X86::SUB64mi8 },
- { X86::SUB64rr, X86::SUB64mr },
- { X86::SUB8ri, X86::SUB8mi },
- { X86::SUB8rr, X86::SUB8mr },
- { X86::XOR16ri, X86::XOR16mi },
- { X86::XOR16ri8, X86::XOR16mi8 },
- { X86::XOR16rr, X86::XOR16mr },
- { X86::XOR32ri, X86::XOR32mi },
- { X86::XOR32ri8, X86::XOR32mi8 },
- { X86::XOR32rr, X86::XOR32mr },
- { X86::XOR64ri32, X86::XOR64mi32 },
- { X86::XOR64ri8, X86::XOR64mi8 },
- { X86::XOR64rr, X86::XOR64mr },
- { X86::XOR8ri, X86::XOR8mi },
- { X86::XOR8rr, X86::XOR8mr }
+ static const unsigned OpTbl2Addr[][3] = {
+ { X86::ADC32ri, X86::ADC32mi, 0 },
+ { X86::ADC32ri8, X86::ADC32mi8, 0 },
+ { X86::ADC32rr, X86::ADC32mr, 0 },
+ { X86::ADC64ri32, X86::ADC64mi32, 0 },
+ { X86::ADC64ri8, X86::ADC64mi8, 0 },
+ { X86::ADC64rr, X86::ADC64mr, 0 },
+ { X86::ADD16ri, X86::ADD16mi, 0 },
+ { X86::ADD16ri8, X86::ADD16mi8, 0 },
+ { X86::ADD16ri_DB, X86::ADD16mi, TB_NO_REVERSE },
+ { X86::ADD16ri8_DB, X86::ADD16mi8, TB_NO_REVERSE },
+ { X86::ADD16rr, X86::ADD16mr, 0 },
+ { X86::ADD16rr_DB, X86::ADD16mr, TB_NO_REVERSE },
+ { X86::ADD32ri, X86::ADD32mi, 0 },
+ { X86::ADD32ri8, X86::ADD32mi8, 0 },
+ { X86::ADD32ri_DB, X86::ADD32mi, TB_NO_REVERSE },
+ { X86::ADD32ri8_DB, X86::ADD32mi8, TB_NO_REVERSE },
+ { X86::ADD32rr, X86::ADD32mr, 0 },
+ { X86::ADD32rr_DB, X86::ADD32mr, TB_NO_REVERSE },
+ { X86::ADD64ri32, X86::ADD64mi32, 0 },
+ { X86::ADD64ri8, X86::ADD64mi8, 0 },
+ { X86::ADD64ri32_DB,X86::ADD64mi32, TB_NO_REVERSE },
+ { X86::ADD64ri8_DB, X86::ADD64mi8, TB_NO_REVERSE },
+ { X86::ADD64rr, X86::ADD64mr, 0 },
+ { X86::ADD64rr_DB, X86::ADD64mr, TB_NO_REVERSE },
+ { X86::ADD8ri, X86::ADD8mi, 0 },
+ { X86::ADD8rr, X86::ADD8mr, 0 },
+ { X86::AND16ri, X86::AND16mi, 0 },
+ { X86::AND16ri8, X86::AND16mi8, 0 },
+ { X86::AND16rr, X86::AND16mr, 0 },
+ { X86::AND32ri, X86::AND32mi, 0 },
+ { X86::AND32ri8, X86::AND32mi8, 0 },
+ { X86::AND32rr, X86::AND32mr, 0 },
+ { X86::AND64ri32, X86::AND64mi32, 0 },
+ { X86::AND64ri8, X86::AND64mi8, 0 },
+ { X86::AND64rr, X86::AND64mr, 0 },
+ { X86::AND8ri, X86::AND8mi, 0 },
+ { X86::AND8rr, X86::AND8mr, 0 },
+ { X86::DEC16r, X86::DEC16m, 0 },
+ { X86::DEC32r, X86::DEC32m, 0 },
+ { X86::DEC64_16r, X86::DEC64_16m, 0 },
+ { X86::DEC64_32r, X86::DEC64_32m, 0 },
+ { X86::DEC64r, X86::DEC64m, 0 },
+ { X86::DEC8r, X86::DEC8m, 0 },
+ { X86::INC16r, X86::INC16m, 0 },
+ { X86::INC32r, X86::INC32m, 0 },
+ { X86::INC64_16r, X86::INC64_16m, 0 },
+ { X86::INC64_32r, X86::INC64_32m, 0 },
+ { X86::INC64r, X86::INC64m, 0 },
+ { X86::INC8r, X86::INC8m, 0 },
+ { X86::NEG16r, X86::NEG16m, 0 },
+ { X86::NEG32r, X86::NEG32m, 0 },
+ { X86::NEG64r, X86::NEG64m, 0 },
+ { X86::NEG8r, X86::NEG8m, 0 },
+ { X86::NOT16r, X86::NOT16m, 0 },
+ { X86::NOT32r, X86::NOT32m, 0 },
+ { X86::NOT64r, X86::NOT64m, 0 },
+ { X86::NOT8r, X86::NOT8m, 0 },
+ { X86::OR16ri, X86::OR16mi, 0 },
+ { X86::OR16ri8, X86::OR16mi8, 0 },
+ { X86::OR16rr, X86::OR16mr, 0 },
+ { X86::OR32ri, X86::OR32mi, 0 },
+ { X86::OR32ri8, X86::OR32mi8, 0 },
+ { X86::OR32rr, X86::OR32mr, 0 },
+ { X86::OR64ri32, X86::OR64mi32, 0 },
+ { X86::OR64ri8, X86::OR64mi8, 0 },
+ { X86::OR64rr, X86::OR64mr, 0 },
+ { X86::OR8ri, X86::OR8mi, 0 },
+ { X86::OR8rr, X86::OR8mr, 0 },
+ { X86::ROL16r1, X86::ROL16m1, 0 },
+ { X86::ROL16rCL, X86::ROL16mCL, 0 },
+ { X86::ROL16ri, X86::ROL16mi, 0 },
+ { X86::ROL32r1, X86::ROL32m1, 0 },
+ { X86::ROL32rCL, X86::ROL32mCL, 0 },
+ { X86::ROL32ri, X86::ROL32mi, 0 },
+ { X86::ROL64r1, X86::ROL64m1, 0 },
+ { X86::ROL64rCL, X86::ROL64mCL, 0 },
+ { X86::ROL64ri, X86::ROL64mi, 0 },
+ { X86::ROL8r1, X86::ROL8m1, 0 },
+ { X86::ROL8rCL, X86::ROL8mCL, 0 },
+ { X86::ROL8ri, X86::ROL8mi, 0 },
+ { X86::ROR16r1, X86::ROR16m1, 0 },
+ { X86::ROR16rCL, X86::ROR16mCL, 0 },
+ { X86::ROR16ri, X86::ROR16mi, 0 },
+ { X86::ROR32r1, X86::ROR32m1, 0 },
+ { X86::ROR32rCL, X86::ROR32mCL, 0 },
+ { X86::ROR32ri, X86::ROR32mi, 0 },
+ { X86::ROR64r1, X86::ROR64m1, 0 },
+ { X86::ROR64rCL, X86::ROR64mCL, 0 },
+ { X86::ROR64ri, X86::ROR64mi, 0 },
+ { X86::ROR8r1, X86::ROR8m1, 0 },
+ { X86::ROR8rCL, X86::ROR8mCL, 0 },
+ { X86::ROR8ri, X86::ROR8mi, 0 },
+ { X86::SAR16r1, X86::SAR16m1, 0 },
+ { X86::SAR16rCL, X86::SAR16mCL, 0 },
+ { X86::SAR16ri, X86::SAR16mi, 0 },
+ { X86::SAR32r1, X86::SAR32m1, 0 },
+ { X86::SAR32rCL, X86::SAR32mCL, 0 },
+ { X86::SAR32ri, X86::SAR32mi, 0 },
+ { X86::SAR64r1, X86::SAR64m1, 0 },
+ { X86::SAR64rCL, X86::SAR64mCL, 0 },
+ { X86::SAR64ri, X86::SAR64mi, 0 },
+ { X86::SAR8r1, X86::SAR8m1, 0 },
+ { X86::SAR8rCL, X86::SAR8mCL, 0 },
+ { X86::SAR8ri, X86::SAR8mi, 0 },
+ { X86::SBB32ri, X86::SBB32mi, 0 },
+ { X86::SBB32ri8, X86::SBB32mi8, 0 },
+ { X86::SBB32rr, X86::SBB32mr, 0 },
+ { X86::SBB64ri32, X86::SBB64mi32, 0 },
+ { X86::SBB64ri8, X86::SBB64mi8, 0 },
+ { X86::SBB64rr, X86::SBB64mr, 0 },
+ { X86::SHL16rCL, X86::SHL16mCL, 0 },
+ { X86::SHL16ri, X86::SHL16mi, 0 },
+ { X86::SHL32rCL, X86::SHL32mCL, 0 },
+ { X86::SHL32ri, X86::SHL32mi, 0 },
+ { X86::SHL64rCL, X86::SHL64mCL, 0 },
+ { X86::SHL64ri, X86::SHL64mi, 0 },
+ { X86::SHL8rCL, X86::SHL8mCL, 0 },
+ { X86::SHL8ri, X86::SHL8mi, 0 },
+ { X86::SHLD16rrCL, X86::SHLD16mrCL, 0 },
+ { X86::SHLD16rri8, X86::SHLD16mri8, 0 },
+ { X86::SHLD32rrCL, X86::SHLD32mrCL, 0 },
+ { X86::SHLD32rri8, X86::SHLD32mri8, 0 },
+ { X86::SHLD64rrCL, X86::SHLD64mrCL, 0 },
+ { X86::SHLD64rri8, X86::SHLD64mri8, 0 },
+ { X86::SHR16r1, X86::SHR16m1, 0 },
+ { X86::SHR16rCL, X86::SHR16mCL, 0 },
+ { X86::SHR16ri, X86::SHR16mi, 0 },
+ { X86::SHR32r1, X86::SHR32m1, 0 },
+ { X86::SHR32rCL, X86::SHR32mCL, 0 },
+ { X86::SHR32ri, X86::SHR32mi, 0 },
+ { X86::SHR64r1, X86::SHR64m1, 0 },
+ { X86::SHR64rCL, X86::SHR64mCL, 0 },
+ { X86::SHR64ri, X86::SHR64mi, 0 },
+ { X86::SHR8r1, X86::SHR8m1, 0 },
+ { X86::SHR8rCL, X86::SHR8mCL, 0 },
+ { X86::SHR8ri, X86::SHR8mi, 0 },
+ { X86::SHRD16rrCL, X86::SHRD16mrCL, 0 },
+ { X86::SHRD16rri8, X86::SHRD16mri8, 0 },
+ { X86::SHRD32rrCL, X86::SHRD32mrCL, 0 },
+ { X86::SHRD32rri8, X86::SHRD32mri8, 0 },
+ { X86::SHRD64rrCL, X86::SHRD64mrCL, 0 },
+ { X86::SHRD64rri8, X86::SHRD64mri8, 0 },
+ { X86::SUB16ri, X86::SUB16mi, 0 },
+ { X86::SUB16ri8, X86::SUB16mi8, 0 },
+ { X86::SUB16rr, X86::SUB16mr, 0 },
+ { X86::SUB32ri, X86::SUB32mi, 0 },
+ { X86::SUB32ri8, X86::SUB32mi8, 0 },
+ { X86::SUB32rr, X86::SUB32mr, 0 },
+ { X86::SUB64ri32, X86::SUB64mi32, 0 },
+ { X86::SUB64ri8, X86::SUB64mi8, 0 },
+ { X86::SUB64rr, X86::SUB64mr, 0 },
+ { X86::SUB8ri, X86::SUB8mi, 0 },
+ { X86::SUB8rr, X86::SUB8mr, 0 },
+ { X86::XOR16ri, X86::XOR16mi, 0 },
+ { X86::XOR16ri8, X86::XOR16mi8, 0 },
+ { X86::XOR16rr, X86::XOR16mr, 0 },
+ { X86::XOR32ri, X86::XOR32mi, 0 },
+ { X86::XOR32ri8, X86::XOR32mi8, 0 },
+ { X86::XOR32rr, X86::XOR32mr, 0 },
+ { X86::XOR64ri32, X86::XOR64mi32, 0 },
+ { X86::XOR64ri8, X86::XOR64mi8, 0 },
+ { X86::XOR64rr, X86::XOR64mr, 0 },
+ { X86::XOR8ri, X86::XOR8mi, 0 },
+ { X86::XOR8rr, X86::XOR8mr, 0 }
};
for (unsigned i = 0, e = array_lengthof(OpTbl2Addr); i != e; ++i) {
unsigned RegOp = OpTbl2Addr[i][0];
- unsigned MemOp = OpTbl2Addr[i][1] & ~TB_FLAGS;
- assert(!RegOp2MemOpTable2Addr.count(RegOp) && "Duplicated entries?");
- RegOp2MemOpTable2Addr[RegOp] = std::make_pair(MemOp, 0U);
-
- // If this is not a reversible operation (because there is a many->one)
- // mapping, don't insert the reverse of the operation into MemOp2RegOpTable.
- if (OpTbl2Addr[i][1] & TB_NOT_REVERSABLE)
- continue;
-
- // Index 0, folded load and store, no alignment requirement.
- unsigned AuxInfo = 0 | (1 << 4) | (1 << 5);
-
- assert(!MemOp2RegOpTable.count(MemOp) &&
- "Duplicated entries in unfolding maps?");
- MemOp2RegOpTable[MemOp] = std::make_pair(RegOp, AuxInfo);
- }
-
- // If the third value is 1, then it's folding either a load or a store.
- static const unsigned OpTbl0[][4] = {
- { X86::BT16ri8, X86::BT16mi8, 1, 0 },
- { X86::BT32ri8, X86::BT32mi8, 1, 0 },
- { X86::BT64ri8, X86::BT64mi8, 1, 0 },
- { X86::CALL32r, X86::CALL32m, 1, 0 },
- { X86::CALL64r, X86::CALL64m, 1, 0 },
- { X86::WINCALL64r, X86::WINCALL64m, 1, 0 },
- { X86::CMP16ri, X86::CMP16mi, 1, 0 },
- { X86::CMP16ri8, X86::CMP16mi8, 1, 0 },
- { X86::CMP16rr, X86::CMP16mr, 1, 0 },
- { X86::CMP32ri, X86::CMP32mi, 1, 0 },
- { X86::CMP32ri8, X86::CMP32mi8, 1, 0 },
- { X86::CMP32rr, X86::CMP32mr, 1, 0 },
- { X86::CMP64ri32, X86::CMP64mi32, 1, 0 },
- { X86::CMP64ri8, X86::CMP64mi8, 1, 0 },
- { X86::CMP64rr, X86::CMP64mr, 1, 0 },
- { X86::CMP8ri, X86::CMP8mi, 1, 0 },
- { X86::CMP8rr, X86::CMP8mr, 1, 0 },
- { X86::DIV16r, X86::DIV16m, 1, 0 },
- { X86::DIV32r, X86::DIV32m, 1, 0 },
- { X86::DIV64r, X86::DIV64m, 1, 0 },
- { X86::DIV8r, X86::DIV8m, 1, 0 },
- { X86::EXTRACTPSrr, X86::EXTRACTPSmr, 0, 16 },
- { X86::FsMOVAPDrr, X86::MOVSDmr | TB_NOT_REVERSABLE , 0, 0 },
- { X86::FsMOVAPSrr, X86::MOVSSmr | TB_NOT_REVERSABLE , 0, 0 },
- { X86::IDIV16r, X86::IDIV16m, 1, 0 },
- { X86::IDIV32r, X86::IDIV32m, 1, 0 },
- { X86::IDIV64r, X86::IDIV64m, 1, 0 },
- { X86::IDIV8r, X86::IDIV8m, 1, 0 },
- { X86::IMUL16r, X86::IMUL16m, 1, 0 },
- { X86::IMUL32r, X86::IMUL32m, 1, 0 },
- { X86::IMUL64r, X86::IMUL64m, 1, 0 },
- { X86::IMUL8r, X86::IMUL8m, 1, 0 },
- { X86::JMP32r, X86::JMP32m, 1, 0 },
- { X86::JMP64r, X86::JMP64m, 1, 0 },
- { X86::MOV16ri, X86::MOV16mi, 0, 0 },
- { X86::MOV16rr, X86::MOV16mr, 0, 0 },
- { X86::MOV32ri, X86::MOV32mi, 0, 0 },
- { X86::MOV32rr, X86::MOV32mr, 0, 0 },
- { X86::MOV64ri32, X86::MOV64mi32, 0, 0 },
- { X86::MOV64rr, X86::MOV64mr, 0, 0 },
- { X86::MOV8ri, X86::MOV8mi, 0, 0 },
- { X86::MOV8rr, X86::MOV8mr, 0, 0 },
- { X86::MOV8rr_NOREX, X86::MOV8mr_NOREX, 0, 0 },
- { X86::MOVAPDrr, X86::MOVAPDmr, 0, 16 },
- { X86::MOVAPSrr, X86::MOVAPSmr, 0, 16 },
- { X86::MOVDQArr, X86::MOVDQAmr, 0, 16 },
- { X86::VMOVAPDYrr, X86::VMOVAPDYmr, 0, 32 },
- { X86::VMOVAPSYrr, X86::VMOVAPSYmr, 0, 32 },
- { X86::VMOVDQAYrr, X86::VMOVDQAYmr, 0, 32 },
- { X86::MOVPDI2DIrr, X86::MOVPDI2DImr, 0, 0 },
- { X86::MOVPQIto64rr,X86::MOVPQI2QImr, 0, 0 },
- { X86::MOVSDto64rr, X86::MOVSDto64mr, 0, 0 },
- { X86::MOVSS2DIrr, X86::MOVSS2DImr, 0, 0 },
- { X86::MOVUPDrr, X86::MOVUPDmr, 0, 0 },
- { X86::MOVUPSrr, X86::MOVUPSmr, 0, 0 },
- { X86::VMOVUPDYrr, X86::VMOVUPDYmr, 0, 0 },
- { X86::VMOVUPSYrr, X86::VMOVUPSYmr, 0, 0 },
- { X86::MUL16r, X86::MUL16m, 1, 0 },
- { X86::MUL32r, X86::MUL32m, 1, 0 },
- { X86::MUL64r, X86::MUL64m, 1, 0 },
- { X86::MUL8r, X86::MUL8m, 1, 0 },
- { X86::SETAEr, X86::SETAEm, 0, 0 },
- { X86::SETAr, X86::SETAm, 0, 0 },
- { X86::SETBEr, X86::SETBEm, 0, 0 },
- { X86::SETBr, X86::SETBm, 0, 0 },
- { X86::SETEr, X86::SETEm, 0, 0 },
- { X86::SETGEr, X86::SETGEm, 0, 0 },
- { X86::SETGr, X86::SETGm, 0, 0 },
- { X86::SETLEr, X86::SETLEm, 0, 0 },
- { X86::SETLr, X86::SETLm, 0, 0 },
- { X86::SETNEr, X86::SETNEm, 0, 0 },
- { X86::SETNOr, X86::SETNOm, 0, 0 },
- { X86::SETNPr, X86::SETNPm, 0, 0 },
- { X86::SETNSr, X86::SETNSm, 0, 0 },
- { X86::SETOr, X86::SETOm, 0, 0 },
- { X86::SETPr, X86::SETPm, 0, 0 },
- { X86::SETSr, X86::SETSm, 0, 0 },
- { X86::TAILJMPr, X86::TAILJMPm, 1, 0 },
- { X86::TAILJMPr64, X86::TAILJMPm64, 1, 0 },
- { X86::TEST16ri, X86::TEST16mi, 1, 0 },
- { X86::TEST32ri, X86::TEST32mi, 1, 0 },
- { X86::TEST64ri32, X86::TEST64mi32, 1, 0 },
- { X86::TEST8ri, X86::TEST8mi, 1, 0 }
+ unsigned MemOp = OpTbl2Addr[i][1];
+ unsigned Flags = OpTbl2Addr[i][2];
+ AddTableEntry(RegOp2MemOpTable2Addr, MemOp2RegOpTable,
+ RegOp, MemOp,
+ // Index 0, folded load and store, no alignment requirement.
+ Flags | TB_INDEX_0 | TB_FOLDED_LOAD | TB_FOLDED_STORE);
+ }
+
+ static const unsigned OpTbl0[][3] = {
+ { X86::BT16ri8, X86::BT16mi8, TB_FOLDED_LOAD },
+ { X86::BT32ri8, X86::BT32mi8, TB_FOLDED_LOAD },
+ { X86::BT64ri8, X86::BT64mi8, TB_FOLDED_LOAD },
+ { X86::CALL32r, X86::CALL32m, TB_FOLDED_LOAD },
+ { X86::CALL64r, X86::CALL64m, TB_FOLDED_LOAD },
+ { X86::WINCALL64r, X86::WINCALL64m, TB_FOLDED_LOAD },
+ { X86::CMP16ri, X86::CMP16mi, TB_FOLDED_LOAD },
+ { X86::CMP16ri8, X86::CMP16mi8, TB_FOLDED_LOAD },
+ { X86::CMP16rr, X86::CMP16mr, TB_FOLDED_LOAD },
+ { X86::CMP32ri, X86::CMP32mi, TB_FOLDED_LOAD },
+ { X86::CMP32ri8, X86::CMP32mi8, TB_FOLDED_LOAD },
+ { X86::CMP32rr, X86::CMP32mr, TB_FOLDED_LOAD },
+ { X86::CMP64ri32, X86::CMP64mi32, TB_FOLDED_LOAD },
+ { X86::CMP64ri8, X86::CMP64mi8, TB_FOLDED_LOAD },
+ { X86::CMP64rr, X86::CMP64mr, TB_FOLDED_LOAD },
+ { X86::CMP8ri, X86::CMP8mi, TB_FOLDED_LOAD },
+ { X86::CMP8rr, X86::CMP8mr, TB_FOLDED_LOAD },
+ { X86::DIV16r, X86::DIV16m, TB_FOLDED_LOAD },
+ { X86::DIV32r, X86::DIV32m, TB_FOLDED_LOAD },
+ { X86::DIV64r, X86::DIV64m, TB_FOLDED_LOAD },
+ { X86::DIV8r, X86::DIV8m, TB_FOLDED_LOAD },
+ { X86::EXTRACTPSrr, X86::EXTRACTPSmr, TB_FOLDED_STORE | TB_ALIGN_16 },
+ { X86::FsMOVAPDrr, X86::MOVSDmr, TB_FOLDED_STORE | TB_NO_REVERSE },
+ { X86::FsMOVAPSrr, X86::MOVSSmr, TB_FOLDED_STORE | TB_NO_REVERSE },
+ { X86::IDIV16r, X86::IDIV16m, TB_FOLDED_LOAD },
+ { X86::IDIV32r, X86::IDIV32m, TB_FOLDED_LOAD },
+ { X86::IDIV64r, X86::IDIV64m, TB_FOLDED_LOAD },
+ { X86::IDIV8r, X86::IDIV8m, TB_FOLDED_LOAD },
+ { X86::IMUL16r, X86::IMUL16m, TB_FOLDED_LOAD },
+ { X86::IMUL32r, X86::IMUL32m, TB_FOLDED_LOAD },
+ { X86::IMUL64r, X86::IMUL64m, TB_FOLDED_LOAD },
+ { X86::IMUL8r, X86::IMUL8m, TB_FOLDED_LOAD },
+ { X86::JMP32r, X86::JMP32m, TB_FOLDED_LOAD },
+ { X86::JMP64r, X86::JMP64m, TB_FOLDED_LOAD },
+ { X86::MOV16ri, X86::MOV16mi, TB_FOLDED_STORE },
+ { X86::MOV16rr, X86::MOV16mr, TB_FOLDED_STORE },
+ { X86::MOV32ri, X86::MOV32mi, TB_FOLDED_STORE },
+ { X86::MOV32rr, X86::MOV32mr, TB_FOLDED_STORE },
+ { X86::MOV64ri32, X86::MOV64mi32, TB_FOLDED_STORE },
+ { X86::MOV64rr, X86::MOV64mr, TB_FOLDED_STORE },
+ { X86::MOV8ri, X86::MOV8mi, TB_FOLDED_STORE },
+ { X86::MOV8rr, X86::MOV8mr, TB_FOLDED_STORE },
+ { X86::MOV8rr_NOREX, X86::MOV8mr_NOREX, TB_FOLDED_STORE },
+ { X86::MOVAPDrr, X86::MOVAPDmr, TB_FOLDED_STORE | TB_ALIGN_16 },
+ { X86::MOVAPSrr, X86::MOVAPSmr, TB_FOLDED_STORE | TB_ALIGN_16 },
+ { X86::MOVDQArr, X86::MOVDQAmr, TB_FOLDED_STORE | TB_ALIGN_16 },
+ { X86::MOVPDI2DIrr, X86::MOVPDI2DImr, TB_FOLDED_STORE },
+ { X86::MOVPQIto64rr,X86::MOVPQI2QImr, TB_FOLDED_STORE },
+ { X86::MOVSDto64rr, X86::MOVSDto64mr, TB_FOLDED_STORE },
+ { X86::MOVSS2DIrr, X86::MOVSS2DImr, TB_FOLDED_STORE },
+ { X86::MOVUPDrr, X86::MOVUPDmr, TB_FOLDED_STORE },
+ { X86::MOVUPSrr, X86::MOVUPSmr, TB_FOLDED_STORE },
+ { X86::MUL16r, X86::MUL16m, TB_FOLDED_LOAD },
+ { X86::MUL32r, X86::MUL32m, TB_FOLDED_LOAD },
+ { X86::MUL64r, X86::MUL64m, TB_FOLDED_LOAD },
+ { X86::MUL8r, X86::MUL8m, TB_FOLDED_LOAD },
+ { X86::SETAEr, X86::SETAEm, TB_FOLDED_STORE },
+ { X86::SETAr, X86::SETAm, TB_FOLDED_STORE },
+ { X86::SETBEr, X86::SETBEm, TB_FOLDED_STORE },
+ { X86::SETBr, X86::SETBm, TB_FOLDED_STORE },
+ { X86::SETEr, X86::SETEm, TB_FOLDED_STORE },
+ { X86::SETGEr, X86::SETGEm, TB_FOLDED_STORE },
+ { X86::SETGr, X86::SETGm, TB_FOLDED_STORE },
+ { X86::SETLEr, X86::SETLEm, TB_FOLDED_STORE },
+ { X86::SETLr, X86::SETLm, TB_FOLDED_STORE },
+ { X86::SETNEr, X86::SETNEm, TB_FOLDED_STORE },
+ { X86::SETNOr, X86::SETNOm, TB_FOLDED_STORE },
+ { X86::SETNPr, X86::SETNPm, TB_FOLDED_STORE },
+ { X86::SETNSr, X86::SETNSm, TB_FOLDED_STORE },
+ { X86::SETOr, X86::SETOm, TB_FOLDED_STORE },
+ { X86::SETPr, X86::SETPm, TB_FOLDED_STORE },
+ { X86::SETSr, X86::SETSm, TB_FOLDED_STORE },
+ { X86::TAILJMPr, X86::TAILJMPm, TB_FOLDED_LOAD },
+ { X86::TAILJMPr64, X86::TAILJMPm64, TB_FOLDED_LOAD },
+ { X86::TEST16ri, X86::TEST16mi, TB_FOLDED_LOAD },
+ { X86::TEST32ri, X86::TEST32mi, TB_FOLDED_LOAD },
+ { X86::TEST64ri32, X86::TEST64mi32, TB_FOLDED_LOAD },
+ { X86::TEST8ri, X86::TEST8mi, TB_FOLDED_LOAD },
+ // AVX 128-bit versions of foldable instructions
+ { X86::VEXTRACTPSrr,X86::VEXTRACTPSmr, TB_FOLDED_STORE | TB_ALIGN_16 },
+ { X86::FsVMOVAPDrr, X86::VMOVSDmr, TB_FOLDED_STORE | TB_NO_REVERSE },
+ { X86::FsVMOVAPSrr, X86::VMOVSSmr, TB_FOLDED_STORE | TB_NO_REVERSE },
+ { X86::VMOVAPDrr, X86::VMOVAPDmr, TB_FOLDED_STORE | TB_ALIGN_16 },
+ { X86::VMOVAPSrr, X86::VMOVAPSmr, TB_FOLDED_STORE | TB_ALIGN_16 },
+ { X86::VMOVDQArr, X86::VMOVDQAmr, TB_FOLDED_STORE | TB_ALIGN_16 },
+ { X86::VMOVPDI2DIrr,X86::VMOVPDI2DImr, TB_FOLDED_STORE },
+ { X86::VMOVPQIto64rr, X86::VMOVPQI2QImr,TB_FOLDED_STORE },
+ { X86::VMOVSDto64rr,X86::VMOVSDto64mr, TB_FOLDED_STORE },
+ { X86::VMOVSS2DIrr, X86::VMOVSS2DImr, TB_FOLDED_STORE },
+ { X86::VMOVUPDrr, X86::VMOVUPDmr, TB_FOLDED_STORE },
+ { X86::VMOVUPSrr, X86::VMOVUPSmr, TB_FOLDED_STORE },
+ // AVX 256-bit foldable instructions
+ { X86::VMOVAPDYrr, X86::VMOVAPDYmr, TB_FOLDED_STORE | TB_ALIGN_32 },
+ { X86::VMOVAPSYrr, X86::VMOVAPSYmr, TB_FOLDED_STORE | TB_ALIGN_32 },
+ { X86::VMOVDQAYrr, X86::VMOVDQAYmr, TB_FOLDED_STORE | TB_ALIGN_32 },
+ { X86::VMOVUPDYrr, X86::VMOVUPDYmr, TB_FOLDED_STORE },
+ { X86::VMOVUPSYrr, X86::VMOVUPSYmr, TB_FOLDED_STORE }
};
for (unsigned i = 0, e = array_lengthof(OpTbl0); i != e; ++i) {
unsigned RegOp = OpTbl0[i][0];
- unsigned MemOp = OpTbl0[i][1] & ~TB_FLAGS;
- unsigned FoldedLoad = OpTbl0[i][2];
- unsigned Align = OpTbl0[i][3];
- assert(!RegOp2MemOpTable0.count(RegOp) && "Duplicated entries?");
- RegOp2MemOpTable0[RegOp] = std::make_pair(MemOp, Align);
-
- // If this is not a reversible operation (because there is a many->one)
- // mapping, don't insert the reverse of the operation into MemOp2RegOpTable.
- if (OpTbl0[i][1] & TB_NOT_REVERSABLE)
- continue;
-
- // Index 0, folded load or store.
- unsigned AuxInfo = 0 | (FoldedLoad << 4) | ((FoldedLoad^1) << 5);
- assert(!MemOp2RegOpTable.count(MemOp) && "Duplicated entries?");
- MemOp2RegOpTable[MemOp] = std::make_pair(RegOp, AuxInfo);
+ unsigned MemOp = OpTbl0[i][1];
+ unsigned Flags = OpTbl0[i][2];
+ AddTableEntry(RegOp2MemOpTable0, MemOp2RegOpTable,
+ RegOp, MemOp, TB_INDEX_0 | Flags);
}
static const unsigned OpTbl1[][3] = {
- { X86::CMP16rr, X86::CMP16rm, 0 },
- { X86::CMP32rr, X86::CMP32rm, 0 },
- { X86::CMP64rr, X86::CMP64rm, 0 },
- { X86::CMP8rr, X86::CMP8rm, 0 },
- { X86::CVTSD2SSrr, X86::CVTSD2SSrm, 0 },
- { X86::CVTSI2SD64rr, X86::CVTSI2SD64rm, 0 },
- { X86::CVTSI2SDrr, X86::CVTSI2SDrm, 0 },
- { X86::CVTSI2SS64rr, X86::CVTSI2SS64rm, 0 },
- { X86::CVTSI2SSrr, X86::CVTSI2SSrm, 0 },
- { X86::CVTSS2SDrr, X86::CVTSS2SDrm, 0 },
- { X86::CVTTSD2SI64rr, X86::CVTTSD2SI64rm, 0 },
- { X86::CVTTSD2SIrr, X86::CVTTSD2SIrm, 0 },
- { X86::CVTTSS2SI64rr, X86::CVTTSS2SI64rm, 0 },
- { X86::CVTTSS2SIrr, X86::CVTTSS2SIrm, 0 },
- { X86::FsMOVAPDrr, X86::MOVSDrm | TB_NOT_REVERSABLE , 0 },
- { X86::FsMOVAPSrr, X86::MOVSSrm | TB_NOT_REVERSABLE , 0 },
- { X86::IMUL16rri, X86::IMUL16rmi, 0 },
- { X86::IMUL16rri8, X86::IMUL16rmi8, 0 },
- { X86::IMUL32rri, X86::IMUL32rmi, 0 },
- { X86::IMUL32rri8, X86::IMUL32rmi8, 0 },
- { X86::IMUL64rri32, X86::IMUL64rmi32, 0 },
- { X86::IMUL64rri8, X86::IMUL64rmi8, 0 },
- { X86::Int_COMISDrr, X86::Int_COMISDrm, 0 },
- { X86::Int_COMISSrr, X86::Int_COMISSrm, 0 },
- { X86::Int_CVTDQ2PDrr, X86::Int_CVTDQ2PDrm, 16 },
- { X86::Int_CVTDQ2PSrr, X86::Int_CVTDQ2PSrm, 16 },
- { X86::Int_CVTPD2DQrr, X86::Int_CVTPD2DQrm, 16 },
- { X86::Int_CVTPD2PSrr, X86::Int_CVTPD2PSrm, 16 },
- { X86::Int_CVTPS2DQrr, X86::Int_CVTPS2DQrm, 16 },
- { X86::Int_CVTPS2PDrr, X86::Int_CVTPS2PDrm, 0 },
- { X86::CVTSD2SI64rr, X86::CVTSD2SI64rm, 0 },
- { X86::CVTSD2SIrr, X86::CVTSD2SIrm, 0 },
- { X86::Int_CVTSD2SSrr, X86::Int_CVTSD2SSrm, 0 },
- { X86::Int_CVTSI2SD64rr,X86::Int_CVTSI2SD64rm, 0 },
- { X86::Int_CVTSI2SDrr, X86::Int_CVTSI2SDrm, 0 },
- { X86::Int_CVTSI2SS64rr,X86::Int_CVTSI2SS64rm, 0 },
- { X86::Int_CVTSI2SSrr, X86::Int_CVTSI2SSrm, 0 },
- { X86::Int_CVTSS2SDrr, X86::Int_CVTSS2SDrm, 0 },
- { X86::Int_CVTSS2SI64rr,X86::Int_CVTSS2SI64rm, 0 },
- { X86::Int_CVTSS2SIrr, X86::Int_CVTSS2SIrm, 0 },
- { X86::CVTTPD2DQrr, X86::CVTTPD2DQrm, 16 },
- { X86::CVTTPS2DQrr, X86::CVTTPS2DQrm, 16 },
- { X86::Int_CVTTSD2SI64rr,X86::Int_CVTTSD2SI64rm, 0 },
- { X86::Int_CVTTSD2SIrr, X86::Int_CVTTSD2SIrm, 0 },
- { X86::Int_CVTTSS2SI64rr,X86::Int_CVTTSS2SI64rm, 0 },
- { X86::Int_CVTTSS2SIrr, X86::Int_CVTTSS2SIrm, 0 },
- { X86::Int_UCOMISDrr, X86::Int_UCOMISDrm, 0 },
- { X86::Int_UCOMISSrr, X86::Int_UCOMISSrm, 0 },
- { X86::MOV16rr, X86::MOV16rm, 0 },
- { X86::MOV32rr, X86::MOV32rm, 0 },
- { X86::MOV64rr, X86::MOV64rm, 0 },
- { X86::MOV64toPQIrr, X86::MOVQI2PQIrm, 0 },
- { X86::MOV64toSDrr, X86::MOV64toSDrm, 0 },
- { X86::MOV8rr, X86::MOV8rm, 0 },
- { X86::MOVAPDrr, X86::MOVAPDrm, 16 },
- { X86::MOVAPSrr, X86::MOVAPSrm, 16 },
- { X86::VMOVAPDYrr, X86::VMOVAPDYrm, 32 },
- { X86::VMOVAPSYrr, X86::VMOVAPSYrm, 32 },
- { X86::MOVDDUPrr, X86::MOVDDUPrm, 0 },
- { X86::MOVDI2PDIrr, X86::MOVDI2PDIrm, 0 },
- { X86::MOVDI2SSrr, X86::MOVDI2SSrm, 0 },
- { X86::MOVDQArr, X86::MOVDQArm, 16 },
- { X86::VMOVDQAYrr, X86::VMOVDQAYrm, 16 },
- { X86::MOVSHDUPrr, X86::MOVSHDUPrm, 16 },
- { X86::MOVSLDUPrr, X86::MOVSLDUPrm, 16 },
- { X86::MOVSX16rr8, X86::MOVSX16rm8, 0 },
- { X86::MOVSX32rr16, X86::MOVSX32rm16, 0 },
- { X86::MOVSX32rr8, X86::MOVSX32rm8, 0 },
- { X86::MOVSX64rr16, X86::MOVSX64rm16, 0 },
- { X86::MOVSX64rr32, X86::MOVSX64rm32, 0 },
- { X86::MOVSX64rr8, X86::MOVSX64rm8, 0 },
- { X86::MOVUPDrr, X86::MOVUPDrm, 16 },
- { X86::MOVUPSrr, X86::MOVUPSrm, 0 },
- { X86::VMOVUPDYrr, X86::VMOVUPDYrm, 0 },
- { X86::VMOVUPSYrr, X86::VMOVUPSYrm, 0 },
- { X86::MOVZDI2PDIrr, X86::MOVZDI2PDIrm, 0 },
- { X86::MOVZQI2PQIrr, X86::MOVZQI2PQIrm, 0 },
- { X86::MOVZPQILo2PQIrr, X86::MOVZPQILo2PQIrm, 16 },
- { X86::MOVZX16rr8, X86::MOVZX16rm8, 0 },
- { X86::MOVZX32rr16, X86::MOVZX32rm16, 0 },
- { X86::MOVZX32_NOREXrr8, X86::MOVZX32_NOREXrm8, 0 },
- { X86::MOVZX32rr8, X86::MOVZX32rm8, 0 },
- { X86::MOVZX64rr16, X86::MOVZX64rm16, 0 },
- { X86::MOVZX64rr32, X86::MOVZX64rm32, 0 },
- { X86::MOVZX64rr8, X86::MOVZX64rm8, 0 },
- { X86::PSHUFDri, X86::PSHUFDmi, 16 },
- { X86::PSHUFHWri, X86::PSHUFHWmi, 16 },
- { X86::PSHUFLWri, X86::PSHUFLWmi, 16 },
- { X86::RCPPSr, X86::RCPPSm, 16 },
- { X86::RCPPSr_Int, X86::RCPPSm_Int, 16 },
- { X86::RSQRTPSr, X86::RSQRTPSm, 16 },
- { X86::RSQRTPSr_Int, X86::RSQRTPSm_Int, 16 },
- { X86::RSQRTSSr, X86::RSQRTSSm, 0 },
- { X86::RSQRTSSr_Int, X86::RSQRTSSm_Int, 0 },
- { X86::SQRTPDr, X86::SQRTPDm, 16 },
- { X86::SQRTPDr_Int, X86::SQRTPDm_Int, 16 },
- { X86::SQRTPSr, X86::SQRTPSm, 16 },
- { X86::SQRTPSr_Int, X86::SQRTPSm_Int, 16 },
- { X86::SQRTSDr, X86::SQRTSDm, 0 },
- { X86::SQRTSDr_Int, X86::SQRTSDm_Int, 0 },
- { X86::SQRTSSr, X86::SQRTSSm, 0 },
- { X86::SQRTSSr_Int, X86::SQRTSSm_Int, 0 },
- { X86::TEST16rr, X86::TEST16rm, 0 },
- { X86::TEST32rr, X86::TEST32rm, 0 },
- { X86::TEST64rr, X86::TEST64rm, 0 },
- { X86::TEST8rr, X86::TEST8rm, 0 },
+ { X86::CMP16rr, X86::CMP16rm, 0 },
+ { X86::CMP32rr, X86::CMP32rm, 0 },
+ { X86::CMP64rr, X86::CMP64rm, 0 },
+ { X86::CMP8rr, X86::CMP8rm, 0 },
+ { X86::CVTSD2SSrr, X86::CVTSD2SSrm, 0 },
+ { X86::CVTSI2SD64rr, X86::CVTSI2SD64rm, 0 },
+ { X86::CVTSI2SDrr, X86::CVTSI2SDrm, 0 },
+ { X86::CVTSI2SS64rr, X86::CVTSI2SS64rm, 0 },
+ { X86::CVTSI2SSrr, X86::CVTSI2SSrm, 0 },
+ { X86::CVTSS2SDrr, X86::CVTSS2SDrm, 0 },
+ { X86::CVTTSD2SI64rr, X86::CVTTSD2SI64rm, 0 },
+ { X86::CVTTSD2SIrr, X86::CVTTSD2SIrm, 0 },
+ { X86::CVTTSS2SI64rr, X86::CVTTSS2SI64rm, 0 },
+ { X86::CVTTSS2SIrr, X86::CVTTSS2SIrm, 0 },
+ { X86::FsMOVAPDrr, X86::MOVSDrm, TB_NO_REVERSE },
+ { X86::FsMOVAPSrr, X86::MOVSSrm, TB_NO_REVERSE },
+ { X86::IMUL16rri, X86::IMUL16rmi, 0 },
+ { X86::IMUL16rri8, X86::IMUL16rmi8, 0 },
+ { X86::IMUL32rri, X86::IMUL32rmi, 0 },
+ { X86::IMUL32rri8, X86::IMUL32rmi8, 0 },
+ { X86::IMUL64rri32, X86::IMUL64rmi32, 0 },
+ { X86::IMUL64rri8, X86::IMUL64rmi8, 0 },
+ { X86::Int_COMISDrr, X86::Int_COMISDrm, 0 },
+ { X86::Int_COMISSrr, X86::Int_COMISSrm, 0 },
+ { X86::Int_CVTDQ2PDrr, X86::Int_CVTDQ2PDrm, TB_ALIGN_16 },
+ { X86::Int_CVTDQ2PSrr, X86::Int_CVTDQ2PSrm, TB_ALIGN_16 },
+ { X86::Int_CVTPD2DQrr, X86::Int_CVTPD2DQrm, TB_ALIGN_16 },
+ { X86::Int_CVTPD2PSrr, X86::Int_CVTPD2PSrm, TB_ALIGN_16 },
+ { X86::Int_CVTPS2DQrr, X86::Int_CVTPS2DQrm, TB_ALIGN_16 },
+ { X86::Int_CVTPS2PDrr, X86::Int_CVTPS2PDrm, 0 },
+ { X86::CVTSD2SI64rr, X86::CVTSD2SI64rm, 0 },
+ { X86::CVTSD2SIrr, X86::CVTSD2SIrm, 0 },
+ { X86::Int_CVTSD2SSrr, X86::Int_CVTSD2SSrm, 0 },
+ { X86::Int_CVTSI2SD64rr,X86::Int_CVTSI2SD64rm, 0 },
+ { X86::Int_CVTSI2SDrr, X86::Int_CVTSI2SDrm, 0 },
+ { X86::Int_CVTSI2SS64rr,X86::Int_CVTSI2SS64rm, 0 },
+ { X86::Int_CVTSI2SSrr, X86::Int_CVTSI2SSrm, 0 },
+ { X86::Int_CVTSS2SDrr, X86::Int_CVTSS2SDrm, 0 },
+ { X86::CVTTPD2DQrr, X86::CVTTPD2DQrm, TB_ALIGN_16 },
+ { X86::CVTTPS2DQrr, X86::CVTTPS2DQrm, TB_ALIGN_16 },
+ { X86::Int_CVTTSD2SI64rr,X86::Int_CVTTSD2SI64rm, 0 },
+ { X86::Int_CVTTSD2SIrr, X86::Int_CVTTSD2SIrm, 0 },
+ { X86::Int_CVTTSS2SI64rr,X86::Int_CVTTSS2SI64rm, 0 },
+ { X86::Int_CVTTSS2SIrr, X86::Int_CVTTSS2SIrm, 0 },
+ { X86::Int_UCOMISDrr, X86::Int_UCOMISDrm, 0 },
+ { X86::Int_UCOMISSrr, X86::Int_UCOMISSrm, 0 },
+ { X86::MOV16rr, X86::MOV16rm, 0 },
+ { X86::MOV32rr, X86::MOV32rm, 0 },
+ { X86::MOV64rr, X86::MOV64rm, 0 },
+ { X86::MOV64toPQIrr, X86::MOVQI2PQIrm, 0 },
+ { X86::MOV64toSDrr, X86::MOV64toSDrm, 0 },
+ { X86::MOV8rr, X86::MOV8rm, 0 },
+ { X86::MOVAPDrr, X86::MOVAPDrm, TB_ALIGN_16 },
+ { X86::MOVAPSrr, X86::MOVAPSrm, TB_ALIGN_16 },
+ { X86::MOVDDUPrr, X86::MOVDDUPrm, 0 },
+ { X86::MOVDI2PDIrr, X86::MOVDI2PDIrm, 0 },
+ { X86::MOVDI2SSrr, X86::MOVDI2SSrm, 0 },
+ { X86::MOVDQArr, X86::MOVDQArm, TB_ALIGN_16 },
+ { X86::MOVSHDUPrr, X86::MOVSHDUPrm, TB_ALIGN_16 },
+ { X86::MOVSLDUPrr, X86::MOVSLDUPrm, TB_ALIGN_16 },
+ { X86::MOVSX16rr8, X86::MOVSX16rm8, 0 },
+ { X86::MOVSX32rr16, X86::MOVSX32rm16, 0 },
+ { X86::MOVSX32rr8, X86::MOVSX32rm8, 0 },
+ { X86::MOVSX64rr16, X86::MOVSX64rm16, 0 },
+ { X86::MOVSX64rr32, X86::MOVSX64rm32, 0 },
+ { X86::MOVSX64rr8, X86::MOVSX64rm8, 0 },
+ { X86::MOVUPDrr, X86::MOVUPDrm, TB_ALIGN_16 },
+ { X86::MOVUPSrr, X86::MOVUPSrm, 0 },
+ { X86::MOVZDI2PDIrr, X86::MOVZDI2PDIrm, 0 },
+ { X86::MOVZQI2PQIrr, X86::MOVZQI2PQIrm, 0 },
+ { X86::MOVZPQILo2PQIrr, X86::MOVZPQILo2PQIrm, TB_ALIGN_16 },
+ { X86::MOVZX16rr8, X86::MOVZX16rm8, 0 },
+ { X86::MOVZX32rr16, X86::MOVZX32rm16, 0 },
+ { X86::MOVZX32_NOREXrr8, X86::MOVZX32_NOREXrm8, 0 },
+ { X86::MOVZX32rr8, X86::MOVZX32rm8, 0 },
+ { X86::MOVZX64rr16, X86::MOVZX64rm16, 0 },
+ { X86::MOVZX64rr32, X86::MOVZX64rm32, 0 },
+ { X86::MOVZX64rr8, X86::MOVZX64rm8, 0 },
+ { X86::PSHUFDri, X86::PSHUFDmi, TB_ALIGN_16 },
+ { X86::PSHUFHWri, X86::PSHUFHWmi, TB_ALIGN_16 },
+ { X86::PSHUFLWri, X86::PSHUFLWmi, TB_ALIGN_16 },
+ { X86::RCPPSr, X86::RCPPSm, TB_ALIGN_16 },
+ { X86::RCPPSr_Int, X86::RCPPSm_Int, TB_ALIGN_16 },
+ { X86::RSQRTPSr, X86::RSQRTPSm, TB_ALIGN_16 },
+ { X86::RSQRTPSr_Int, X86::RSQRTPSm_Int, TB_ALIGN_16 },
+ { X86::RSQRTSSr, X86::RSQRTSSm, 0 },
+ { X86::RSQRTSSr_Int, X86::RSQRTSSm_Int, 0 },
+ { X86::SQRTPDr, X86::SQRTPDm, TB_ALIGN_16 },
+ { X86::SQRTPDr_Int, X86::SQRTPDm_Int, TB_ALIGN_16 },
+ { X86::SQRTPSr, X86::SQRTPSm, TB_ALIGN_16 },
+ { X86::SQRTPSr_Int, X86::SQRTPSm_Int, TB_ALIGN_16 },
+ { X86::SQRTSDr, X86::SQRTSDm, 0 },
+ { X86::SQRTSDr_Int, X86::SQRTSDm_Int, 0 },
+ { X86::SQRTSSr, X86::SQRTSSm, 0 },
+ { X86::SQRTSSr_Int, X86::SQRTSSm_Int, 0 },
+ { X86::TEST16rr, X86::TEST16rm, 0 },
+ { X86::TEST32rr, X86::TEST32rm, 0 },
+ { X86::TEST64rr, X86::TEST64rm, 0 },
+ { X86::TEST8rr, X86::TEST8rm, 0 },
// FIXME: TEST*rr EAX,EAX ---> CMP [mem], 0
- { X86::UCOMISDrr, X86::UCOMISDrm, 0 },
- { X86::UCOMISSrr, X86::UCOMISSrm, 0 }
+ { X86::UCOMISDrr, X86::UCOMISDrm, 0 },
+ { X86::UCOMISSrr, X86::UCOMISSrm, 0 },
+ // AVX 128-bit versions of foldable instructions
+ { X86::Int_VCOMISDrr, X86::Int_VCOMISDrm, 0 },
+ { X86::Int_VCOMISSrr, X86::Int_VCOMISSrm, 0 },
+ { X86::Int_VCVTDQ2PDrr, X86::Int_VCVTDQ2PDrm, TB_ALIGN_16 },
+ { X86::Int_VCVTDQ2PSrr, X86::Int_VCVTDQ2PSrm, TB_ALIGN_16 },
+ { X86::Int_VCVTPD2DQrr, X86::Int_VCVTPD2DQrm, TB_ALIGN_16 },
+ { X86::Int_VCVTPD2PSrr, X86::Int_VCVTPD2PSrm, TB_ALIGN_16 },
+ { X86::Int_VCVTPS2DQrr, X86::Int_VCVTPS2DQrm, TB_ALIGN_16 },
+ { X86::Int_VCVTPS2PDrr, X86::Int_VCVTPS2PDrm, 0 },
+ { X86::Int_VUCOMISDrr, X86::Int_VUCOMISDrm, 0 },
+ { X86::Int_VUCOMISSrr, X86::Int_VUCOMISSrm, 0 },
+ { X86::FsVMOVAPDrr, X86::VMOVSDrm, TB_NO_REVERSE },
+ { X86::FsVMOVAPSrr, X86::VMOVSSrm, TB_NO_REVERSE },
+ { X86::VMOV64toPQIrr, X86::VMOVQI2PQIrm, 0 },
+ { X86::VMOV64toSDrr, X86::VMOV64toSDrm, 0 },
+ { X86::VMOVAPDrr, X86::VMOVAPDrm, TB_ALIGN_16 },
+ { X86::VMOVAPSrr, X86::VMOVAPSrm, TB_ALIGN_16 },
+ { X86::VMOVDDUPrr, X86::VMOVDDUPrm, 0 },
+ { X86::VMOVDI2PDIrr, X86::VMOVDI2PDIrm, 0 },
+ { X86::VMOVDI2SSrr, X86::VMOVDI2SSrm, 0 },
+ { X86::VMOVDQArr, X86::VMOVDQArm, TB_ALIGN_16 },
+ { X86::VMOVSLDUPrr, X86::VMOVSLDUPrm, TB_ALIGN_16 },
+ { X86::VMOVSHDUPrr, X86::VMOVSHDUPrm, TB_ALIGN_16 },
+ { X86::VMOVUPDrr, X86::VMOVUPDrm, TB_ALIGN_16 },
+ { X86::VMOVUPSrr, X86::VMOVUPSrm, 0 },
+ { X86::VMOVZDI2PDIrr, X86::VMOVZDI2PDIrm, 0 },
+ { X86::VMOVZQI2PQIrr, X86::VMOVZQI2PQIrm, 0 },
+ { X86::VMOVZPQILo2PQIrr,X86::VMOVZPQILo2PQIrm, TB_ALIGN_16 },
+ { X86::VPSHUFDri, X86::VPSHUFDmi, TB_ALIGN_16 },
+ { X86::VPSHUFHWri, X86::VPSHUFHWmi, TB_ALIGN_16 },
+ { X86::VPSHUFLWri, X86::VPSHUFLWmi, TB_ALIGN_16 },
+ { X86::VRCPPSr, X86::VRCPPSm, TB_ALIGN_16 },
+ { X86::VRCPPSr_Int, X86::VRCPPSm_Int, TB_ALIGN_16 },
+ { X86::VRSQRTPSr, X86::VRSQRTPSm, TB_ALIGN_16 },
+ { X86::VRSQRTPSr_Int, X86::VRSQRTPSm_Int, TB_ALIGN_16 },
+ { X86::VSQRTPDr, X86::VSQRTPDm, TB_ALIGN_16 },
+ { X86::VSQRTPDr_Int, X86::VSQRTPDm_Int, TB_ALIGN_16 },
+ { X86::VSQRTPSr, X86::VSQRTPSm, TB_ALIGN_16 },
+ { X86::VSQRTPSr_Int, X86::VSQRTPSm_Int, TB_ALIGN_16 },
+ { X86::VUCOMISDrr, X86::VUCOMISDrm, 0 },
+ { X86::VUCOMISSrr, X86::VUCOMISSrm, 0 },
+ // AVX 256-bit foldable instructions
+ { X86::VMOVAPDYrr, X86::VMOVAPDYrm, TB_ALIGN_32 },
+ { X86::VMOVAPSYrr, X86::VMOVAPSYrm, TB_ALIGN_32 },
+ { X86::VMOVDQAYrr, X86::VMOVDQAYrm, TB_ALIGN_16 },
+ { X86::VMOVUPDYrr, X86::VMOVUPDYrm, 0 },
+ { X86::VMOVUPSYrr, X86::VMOVUPSYrm, 0 }
};
for (unsigned i = 0, e = array_lengthof(OpTbl1); i != e; ++i) {
unsigned RegOp = OpTbl1[i][0];
- unsigned MemOp = OpTbl1[i][1] & ~TB_FLAGS;
- unsigned Align = OpTbl1[i][2];
- assert(!RegOp2MemOpTable1.count(RegOp) && "Duplicate entries");
- RegOp2MemOpTable1[RegOp] = std::make_pair(MemOp, Align);
-
- // If this is not a reversible operation (because there is a many->one)
- // mapping, don't insert the reverse of the operation into MemOp2RegOpTable.
- if (OpTbl1[i][1] & TB_NOT_REVERSABLE)
- continue;
-
- // Index 1, folded load
- unsigned AuxInfo = 1 | (1 << 4);
- assert(!MemOp2RegOpTable.count(MemOp) && "Duplicate entries");
- MemOp2RegOpTable[MemOp] = std::make_pair(RegOp, AuxInfo);
+ unsigned MemOp = OpTbl1[i][1];
+ unsigned Flags = OpTbl1[i][2];
+ AddTableEntry(RegOp2MemOpTable1, MemOp2RegOpTable,
+ RegOp, MemOp,
+ // Index 1, folded load
+ Flags | TB_INDEX_1 | TB_FOLDED_LOAD);
}
static const unsigned OpTbl2[][3] = {
- { X86::ADC32rr, X86::ADC32rm, 0 },
- { X86::ADC64rr, X86::ADC64rm, 0 },
- { X86::ADD16rr, X86::ADD16rm, 0 },
- { X86::ADD16rr_DB, X86::ADD16rm | TB_NOT_REVERSABLE, 0 },
- { X86::ADD32rr, X86::ADD32rm, 0 },
- { X86::ADD32rr_DB, X86::ADD32rm | TB_NOT_REVERSABLE, 0 },
- { X86::ADD64rr, X86::ADD64rm, 0 },
- { X86::ADD64rr_DB, X86::ADD64rm | TB_NOT_REVERSABLE, 0 },
- { X86::ADD8rr, X86::ADD8rm, 0 },
- { X86::ADDPDrr, X86::ADDPDrm, 16 },
- { X86::ADDPSrr, X86::ADDPSrm, 16 },
- { X86::ADDSDrr, X86::ADDSDrm, 0 },
- { X86::ADDSSrr, X86::ADDSSrm, 0 },
- { X86::ADDSUBPDrr, X86::ADDSUBPDrm, 16 },
- { X86::ADDSUBPSrr, X86::ADDSUBPSrm, 16 },
- { X86::AND16rr, X86::AND16rm, 0 },
- { X86::AND32rr, X86::AND32rm, 0 },
- { X86::AND64rr, X86::AND64rm, 0 },
- { X86::AND8rr, X86::AND8rm, 0 },
- { X86::ANDNPDrr, X86::ANDNPDrm, 16 },
- { X86::ANDNPSrr, X86::ANDNPSrm, 16 },
- { X86::ANDPDrr, X86::ANDPDrm, 16 },
- { X86::ANDPSrr, X86::ANDPSrm, 16 },
- { X86::CMOVA16rr, X86::CMOVA16rm, 0 },
- { X86::CMOVA32rr, X86::CMOVA32rm, 0 },
- { X86::CMOVA64rr, X86::CMOVA64rm, 0 },
- { X86::CMOVAE16rr, X86::CMOVAE16rm, 0 },
- { X86::CMOVAE32rr, X86::CMOVAE32rm, 0 },
- { X86::CMOVAE64rr, X86::CMOVAE64rm, 0 },
- { X86::CMOVB16rr, X86::CMOVB16rm, 0 },
- { X86::CMOVB32rr, X86::CMOVB32rm, 0 },
- { X86::CMOVB64rr, X86::CMOVB64rm, 0 },
- { X86::CMOVBE16rr, X86::CMOVBE16rm, 0 },
- { X86::CMOVBE32rr, X86::CMOVBE32rm, 0 },
- { X86::CMOVBE64rr, X86::CMOVBE64rm, 0 },
- { X86::CMOVE16rr, X86::CMOVE16rm, 0 },
- { X86::CMOVE32rr, X86::CMOVE32rm, 0 },
- { X86::CMOVE64rr, X86::CMOVE64rm, 0 },
- { X86::CMOVG16rr, X86::CMOVG16rm, 0 },
- { X86::CMOVG32rr, X86::CMOVG32rm, 0 },
- { X86::CMOVG64rr, X86::CMOVG64rm, 0 },
- { X86::CMOVGE16rr, X86::CMOVGE16rm, 0 },
- { X86::CMOVGE32rr, X86::CMOVGE32rm, 0 },
- { X86::CMOVGE64rr, X86::CMOVGE64rm, 0 },
- { X86::CMOVL16rr, X86::CMOVL16rm, 0 },
- { X86::CMOVL32rr, X86::CMOVL32rm, 0 },
- { X86::CMOVL64rr, X86::CMOVL64rm, 0 },
- { X86::CMOVLE16rr, X86::CMOVLE16rm, 0 },
- { X86::CMOVLE32rr, X86::CMOVLE32rm, 0 },
- { X86::CMOVLE64rr, X86::CMOVLE64rm, 0 },
- { X86::CMOVNE16rr, X86::CMOVNE16rm, 0 },
- { X86::CMOVNE32rr, X86::CMOVNE32rm, 0 },
- { X86::CMOVNE64rr, X86::CMOVNE64rm, 0 },
- { X86::CMOVNO16rr, X86::CMOVNO16rm, 0 },
- { X86::CMOVNO32rr, X86::CMOVNO32rm, 0 },
- { X86::CMOVNO64rr, X86::CMOVNO64rm, 0 },
- { X86::CMOVNP16rr, X86::CMOVNP16rm, 0 },
- { X86::CMOVNP32rr, X86::CMOVNP32rm, 0 },
- { X86::CMOVNP64rr, X86::CMOVNP64rm, 0 },
- { X86::CMOVNS16rr, X86::CMOVNS16rm, 0 },
- { X86::CMOVNS32rr, X86::CMOVNS32rm, 0 },
- { X86::CMOVNS64rr, X86::CMOVNS64rm, 0 },
- { X86::CMOVO16rr, X86::CMOVO16rm, 0 },
- { X86::CMOVO32rr, X86::CMOVO32rm, 0 },
- { X86::CMOVO64rr, X86::CMOVO64rm, 0 },
- { X86::CMOVP16rr, X86::CMOVP16rm, 0 },
- { X86::CMOVP32rr, X86::CMOVP32rm, 0 },
- { X86::CMOVP64rr, X86::CMOVP64rm, 0 },
- { X86::CMOVS16rr, X86::CMOVS16rm, 0 },
- { X86::CMOVS32rr, X86::CMOVS32rm, 0 },
- { X86::CMOVS64rr, X86::CMOVS64rm, 0 },
- { X86::CMPPDrri, X86::CMPPDrmi, 16 },
- { X86::CMPPSrri, X86::CMPPSrmi, 16 },
- { X86::CMPSDrr, X86::CMPSDrm, 0 },
- { X86::CMPSSrr, X86::CMPSSrm, 0 },
- { X86::DIVPDrr, X86::DIVPDrm, 16 },
- { X86::DIVPSrr, X86::DIVPSrm, 16 },
- { X86::DIVSDrr, X86::DIVSDrm, 0 },
- { X86::DIVSSrr, X86::DIVSSrm, 0 },
- { X86::FsANDNPDrr, X86::FsANDNPDrm, 16 },
- { X86::FsANDNPSrr, X86::FsANDNPSrm, 16 },
- { X86::FsANDPDrr, X86::FsANDPDrm, 16 },
- { X86::FsANDPSrr, X86::FsANDPSrm, 16 },
- { X86::FsORPDrr, X86::FsORPDrm, 16 },
- { X86::FsORPSrr, X86::FsORPSrm, 16 },
- { X86::FsXORPDrr, X86::FsXORPDrm, 16 },
- { X86::FsXORPSrr, X86::FsXORPSrm, 16 },
- { X86::HADDPDrr, X86::HADDPDrm, 16 },
- { X86::HADDPSrr, X86::HADDPSrm, 16 },
- { X86::HSUBPDrr, X86::HSUBPDrm, 16 },
- { X86::HSUBPSrr, X86::HSUBPSrm, 16 },
- { X86::IMUL16rr, X86::IMUL16rm, 0 },
- { X86::IMUL32rr, X86::IMUL32rm, 0 },
- { X86::IMUL64rr, X86::IMUL64rm, 0 },
- { X86::Int_CMPSDrr, X86::Int_CMPSDrm, 0 },
- { X86::Int_CMPSSrr, X86::Int_CMPSSrm, 0 },
- { X86::MAXPDrr, X86::MAXPDrm, 16 },
- { X86::MAXPDrr_Int, X86::MAXPDrm_Int, 16 },
- { X86::MAXPSrr, X86::MAXPSrm, 16 },
- { X86::MAXPSrr_Int, X86::MAXPSrm_Int, 16 },
- { X86::MAXSDrr, X86::MAXSDrm, 0 },
- { X86::MAXSDrr_Int, X86::MAXSDrm_Int, 0 },
- { X86::MAXSSrr, X86::MAXSSrm, 0 },
- { X86::MAXSSrr_Int, X86::MAXSSrm_Int, 0 },
- { X86::MINPDrr, X86::MINPDrm, 16 },
- { X86::MINPDrr_Int, X86::MINPDrm_Int, 16 },
- { X86::MINPSrr, X86::MINPSrm, 16 },
- { X86::MINPSrr_Int, X86::MINPSrm_Int, 16 },
- { X86::MINSDrr, X86::MINSDrm, 0 },
- { X86::MINSDrr_Int, X86::MINSDrm_Int, 0 },
- { X86::MINSSrr, X86::MINSSrm, 0 },
- { X86::MINSSrr_Int, X86::MINSSrm_Int, 0 },
- { X86::MULPDrr, X86::MULPDrm, 16 },
- { X86::MULPSrr, X86::MULPSrm, 16 },
- { X86::MULSDrr, X86::MULSDrm, 0 },
- { X86::MULSSrr, X86::MULSSrm, 0 },
- { X86::OR16rr, X86::OR16rm, 0 },
- { X86::OR32rr, X86::OR32rm, 0 },
- { X86::OR64rr, X86::OR64rm, 0 },
- { X86::OR8rr, X86::OR8rm, 0 },
- { X86::ORPDrr, X86::ORPDrm, 16 },
- { X86::ORPSrr, X86::ORPSrm, 16 },
- { X86::PACKSSDWrr, X86::PACKSSDWrm, 16 },
- { X86::PACKSSWBrr, X86::PACKSSWBrm, 16 },
- { X86::PACKUSWBrr, X86::PACKUSWBrm, 16 },
- { X86::PADDBrr, X86::PADDBrm, 16 },
- { X86::PADDDrr, X86::PADDDrm, 16 },
- { X86::PADDQrr, X86::PADDQrm, 16 },
- { X86::PADDSBrr, X86::PADDSBrm, 16 },
- { X86::PADDSWrr, X86::PADDSWrm, 16 },
- { X86::PADDWrr, X86::PADDWrm, 16 },
- { X86::PANDNrr, X86::PANDNrm, 16 },
- { X86::PANDrr, X86::PANDrm, 16 },
- { X86::PAVGBrr, X86::PAVGBrm, 16 },
- { X86::PAVGWrr, X86::PAVGWrm, 16 },
- { X86::PCMPEQBrr, X86::PCMPEQBrm, 16 },
- { X86::PCMPEQDrr, X86::PCMPEQDrm, 16 },
- { X86::PCMPEQWrr, X86::PCMPEQWrm, 16 },
- { X86::PCMPGTBrr, X86::PCMPGTBrm, 16 },
- { X86::PCMPGTDrr, X86::PCMPGTDrm, 16 },
- { X86::PCMPGTWrr, X86::PCMPGTWrm, 16 },
- { X86::PINSRWrri, X86::PINSRWrmi, 16 },
- { X86::PMADDWDrr, X86::PMADDWDrm, 16 },
- { X86::PMAXSWrr, X86::PMAXSWrm, 16 },
- { X86::PMAXUBrr, X86::PMAXUBrm, 16 },
- { X86::PMINSWrr, X86::PMINSWrm, 16 },
- { X86::PMINUBrr, X86::PMINUBrm, 16 },
- { X86::PMULDQrr, X86::PMULDQrm, 16 },
- { X86::PMULHUWrr, X86::PMULHUWrm, 16 },
- { X86::PMULHWrr, X86::PMULHWrm, 16 },
- { X86::PMULLDrr, X86::PMULLDrm, 16 },
- { X86::PMULLWrr, X86::PMULLWrm, 16 },
- { X86::PMULUDQrr, X86::PMULUDQrm, 16 },
- { X86::PORrr, X86::PORrm, 16 },
- { X86::PSADBWrr, X86::PSADBWrm, 16 },
- { X86::PSLLDrr, X86::PSLLDrm, 16 },
- { X86::PSLLQrr, X86::PSLLQrm, 16 },
- { X86::PSLLWrr, X86::PSLLWrm, 16 },
- { X86::PSRADrr, X86::PSRADrm, 16 },
- { X86::PSRAWrr, X86::PSRAWrm, 16 },
- { X86::PSRLDrr, X86::PSRLDrm, 16 },
- { X86::PSRLQrr, X86::PSRLQrm, 16 },
- { X86::PSRLWrr, X86::PSRLWrm, 16 },
- { X86::PSUBBrr, X86::PSUBBrm, 16 },
- { X86::PSUBDrr, X86::PSUBDrm, 16 },
- { X86::PSUBSBrr, X86::PSUBSBrm, 16 },
- { X86::PSUBSWrr, X86::PSUBSWrm, 16 },
- { X86::PSUBWrr, X86::PSUBWrm, 16 },
- { X86::PUNPCKHBWrr, X86::PUNPCKHBWrm, 16 },
- { X86::PUNPCKHDQrr, X86::PUNPCKHDQrm, 16 },
- { X86::PUNPCKHQDQrr, X86::PUNPCKHQDQrm, 16 },
- { X86::PUNPCKHWDrr, X86::PUNPCKHWDrm, 16 },
- { X86::PUNPCKLBWrr, X86::PUNPCKLBWrm, 16 },
- { X86::PUNPCKLDQrr, X86::PUNPCKLDQrm, 16 },
- { X86::PUNPCKLQDQrr, X86::PUNPCKLQDQrm, 16 },
- { X86::PUNPCKLWDrr, X86::PUNPCKLWDrm, 16 },
- { X86::PXORrr, X86::PXORrm, 16 },
- { X86::SBB32rr, X86::SBB32rm, 0 },
- { X86::SBB64rr, X86::SBB64rm, 0 },
- { X86::SHUFPDrri, X86::SHUFPDrmi, 16 },
- { X86::SHUFPSrri, X86::SHUFPSrmi, 16 },
- { X86::SUB16rr, X86::SUB16rm, 0 },
- { X86::SUB32rr, X86::SUB32rm, 0 },
- { X86::SUB64rr, X86::SUB64rm, 0 },
- { X86::SUB8rr, X86::SUB8rm, 0 },
- { X86::SUBPDrr, X86::SUBPDrm, 16 },
- { X86::SUBPSrr, X86::SUBPSrm, 16 },
- { X86::SUBSDrr, X86::SUBSDrm, 0 },
- { X86::SUBSSrr, X86::SUBSSrm, 0 },
+ { X86::ADC32rr, X86::ADC32rm, 0 },
+ { X86::ADC64rr, X86::ADC64rm, 0 },
+ { X86::ADD16rr, X86::ADD16rm, 0 },
+ { X86::ADD16rr_DB, X86::ADD16rm, TB_NO_REVERSE },
+ { X86::ADD32rr, X86::ADD32rm, 0 },
+ { X86::ADD32rr_DB, X86::ADD32rm, TB_NO_REVERSE },
+ { X86::ADD64rr, X86::ADD64rm, 0 },
+ { X86::ADD64rr_DB, X86::ADD64rm, TB_NO_REVERSE },
+ { X86::ADD8rr, X86::ADD8rm, 0 },
+ { X86::ADDPDrr, X86::ADDPDrm, TB_ALIGN_16 },
+ { X86::ADDPSrr, X86::ADDPSrm, TB_ALIGN_16 },
+ { X86::ADDSDrr, X86::ADDSDrm, 0 },
+ { X86::ADDSSrr, X86::ADDSSrm, 0 },
+ { X86::ADDSUBPDrr, X86::ADDSUBPDrm, TB_ALIGN_16 },
+ { X86::ADDSUBPSrr, X86::ADDSUBPSrm, TB_ALIGN_16 },
+ { X86::AND16rr, X86::AND16rm, 0 },
+ { X86::AND32rr, X86::AND32rm, 0 },
+ { X86::AND64rr, X86::AND64rm, 0 },
+ { X86::AND8rr, X86::AND8rm, 0 },
+ { X86::ANDNPDrr, X86::ANDNPDrm, TB_ALIGN_16 },
+ { X86::ANDNPSrr, X86::ANDNPSrm, TB_ALIGN_16 },
+ { X86::ANDPDrr, X86::ANDPDrm, TB_ALIGN_16 },
+ { X86::ANDPSrr, X86::ANDPSrm, TB_ALIGN_16 },
+ { X86::CMOVA16rr, X86::CMOVA16rm, 0 },
+ { X86::CMOVA32rr, X86::CMOVA32rm, 0 },
+ { X86::CMOVA64rr, X86::CMOVA64rm, 0 },
+ { X86::CMOVAE16rr, X86::CMOVAE16rm, 0 },
+ { X86::CMOVAE32rr, X86::CMOVAE32rm, 0 },
+ { X86::CMOVAE64rr, X86::CMOVAE64rm, 0 },
+ { X86::CMOVB16rr, X86::CMOVB16rm, 0 },
+ { X86::CMOVB32rr, X86::CMOVB32rm, 0 },
+ { X86::CMOVB64rr, X86::CMOVB64rm, 0 },
+ { X86::CMOVBE16rr, X86::CMOVBE16rm, 0 },
+ { X86::CMOVBE32rr, X86::CMOVBE32rm, 0 },
+ { X86::CMOVBE64rr, X86::CMOVBE64rm, 0 },
+ { X86::CMOVE16rr, X86::CMOVE16rm, 0 },
+ { X86::CMOVE32rr, X86::CMOVE32rm, 0 },
+ { X86::CMOVE64rr, X86::CMOVE64rm, 0 },
+ { X86::CMOVG16rr, X86::CMOVG16rm, 0 },
+ { X86::CMOVG32rr, X86::CMOVG32rm, 0 },
+ { X86::CMOVG64rr, X86::CMOVG64rm, 0 },
+ { X86::CMOVGE16rr, X86::CMOVGE16rm, 0 },
+ { X86::CMOVGE32rr, X86::CMOVGE32rm, 0 },
+ { X86::CMOVGE64rr, X86::CMOVGE64rm, 0 },
+ { X86::CMOVL16rr, X86::CMOVL16rm, 0 },
+ { X86::CMOVL32rr, X86::CMOVL32rm, 0 },
+ { X86::CMOVL64rr, X86::CMOVL64rm, 0 },
+ { X86::CMOVLE16rr, X86::CMOVLE16rm, 0 },
+ { X86::CMOVLE32rr, X86::CMOVLE32rm, 0 },
+ { X86::CMOVLE64rr, X86::CMOVLE64rm, 0 },
+ { X86::CMOVNE16rr, X86::CMOVNE16rm, 0 },
+ { X86::CMOVNE32rr, X86::CMOVNE32rm, 0 },
+ { X86::CMOVNE64rr, X86::CMOVNE64rm, 0 },
+ { X86::CMOVNO16rr, X86::CMOVNO16rm, 0 },
+ { X86::CMOVNO32rr, X86::CMOVNO32rm, 0 },
+ { X86::CMOVNO64rr, X86::CMOVNO64rm, 0 },
+ { X86::CMOVNP16rr, X86::CMOVNP16rm, 0 },
+ { X86::CMOVNP32rr, X86::CMOVNP32rm, 0 },
+ { X86::CMOVNP64rr, X86::CMOVNP64rm, 0 },
+ { X86::CMOVNS16rr, X86::CMOVNS16rm, 0 },
+ { X86::CMOVNS32rr, X86::CMOVNS32rm, 0 },
+ { X86::CMOVNS64rr, X86::CMOVNS64rm, 0 },
+ { X86::CMOVO16rr, X86::CMOVO16rm, 0 },
+ { X86::CMOVO32rr, X86::CMOVO32rm, 0 },
+ { X86::CMOVO64rr, X86::CMOVO64rm, 0 },
+ { X86::CMOVP16rr, X86::CMOVP16rm, 0 },
+ { X86::CMOVP32rr, X86::CMOVP32rm, 0 },
+ { X86::CMOVP64rr, X86::CMOVP64rm, 0 },
+ { X86::CMOVS16rr, X86::CMOVS16rm, 0 },
+ { X86::CMOVS32rr, X86::CMOVS32rm, 0 },
+ { X86::CMOVS64rr, X86::CMOVS64rm, 0 },
+ { X86::CMPPDrri, X86::CMPPDrmi, TB_ALIGN_16 },
+ { X86::CMPPSrri, X86::CMPPSrmi, TB_ALIGN_16 },
+ { X86::CMPSDrr, X86::CMPSDrm, 0 },
+ { X86::CMPSSrr, X86::CMPSSrm, 0 },
+ { X86::DIVPDrr, X86::DIVPDrm, TB_ALIGN_16 },
+ { X86::DIVPSrr, X86::DIVPSrm, TB_ALIGN_16 },
+ { X86::DIVSDrr, X86::DIVSDrm, 0 },
+ { X86::DIVSSrr, X86::DIVSSrm, 0 },
+ { X86::FsANDNPDrr, X86::FsANDNPDrm, TB_ALIGN_16 },
+ { X86::FsANDNPSrr, X86::FsANDNPSrm, TB_ALIGN_16 },
+ { X86::FsANDPDrr, X86::FsANDPDrm, TB_ALIGN_16 },
+ { X86::FsANDPSrr, X86::FsANDPSrm, TB_ALIGN_16 },
+ { X86::FsORPDrr, X86::FsORPDrm, TB_ALIGN_16 },
+ { X86::FsORPSrr, X86::FsORPSrm, TB_ALIGN_16 },
+ { X86::FsXORPDrr, X86::FsXORPDrm, TB_ALIGN_16 },
+ { X86::FsXORPSrr, X86::FsXORPSrm, TB_ALIGN_16 },
+ { X86::HADDPDrr, X86::HADDPDrm, TB_ALIGN_16 },
+ { X86::HADDPSrr, X86::HADDPSrm, TB_ALIGN_16 },
+ { X86::HSUBPDrr, X86::HSUBPDrm, TB_ALIGN_16 },
+ { X86::HSUBPSrr, X86::HSUBPSrm, TB_ALIGN_16 },
+ { X86::IMUL16rr, X86::IMUL16rm, 0 },
+ { X86::IMUL32rr, X86::IMUL32rm, 0 },
+ { X86::IMUL64rr, X86::IMUL64rm, 0 },
+ { X86::Int_CMPSDrr, X86::Int_CMPSDrm, 0 },
+ { X86::Int_CMPSSrr, X86::Int_CMPSSrm, 0 },
+ { X86::MAXPDrr, X86::MAXPDrm, TB_ALIGN_16 },
+ { X86::MAXPDrr_Int, X86::MAXPDrm_Int, TB_ALIGN_16 },
+ { X86::MAXPSrr, X86::MAXPSrm, TB_ALIGN_16 },
+ { X86::MAXPSrr_Int, X86::MAXPSrm_Int, TB_ALIGN_16 },
+ { X86::MAXSDrr, X86::MAXSDrm, 0 },
+ { X86::MAXSDrr_Int, X86::MAXSDrm_Int, 0 },
+ { X86::MAXSSrr, X86::MAXSSrm, 0 },
+ { X86::MAXSSrr_Int, X86::MAXSSrm_Int, 0 },
+ { X86::MINPDrr, X86::MINPDrm, TB_ALIGN_16 },
+ { X86::MINPDrr_Int, X86::MINPDrm_Int, TB_ALIGN_16 },
+ { X86::MINPSrr, X86::MINPSrm, TB_ALIGN_16 },
+ { X86::MINPSrr_Int, X86::MINPSrm_Int, TB_ALIGN_16 },
+ { X86::MINSDrr, X86::MINSDrm, 0 },
+ { X86::MINSDrr_Int, X86::MINSDrm_Int, 0 },
+ { X86::MINSSrr, X86::MINSSrm, 0 },
+ { X86::MINSSrr_Int, X86::MINSSrm_Int, 0 },
+ { X86::MULPDrr, X86::MULPDrm, TB_ALIGN_16 },
+ { X86::MULPSrr, X86::MULPSrm, TB_ALIGN_16 },
+ { X86::MULSDrr, X86::MULSDrm, 0 },
+ { X86::MULSSrr, X86::MULSSrm, 0 },
+ { X86::OR16rr, X86::OR16rm, 0 },
+ { X86::OR32rr, X86::OR32rm, 0 },
+ { X86::OR64rr, X86::OR64rm, 0 },
+ { X86::OR8rr, X86::OR8rm, 0 },
+ { X86::ORPDrr, X86::ORPDrm, TB_ALIGN_16 },
+ { X86::ORPSrr, X86::ORPSrm, TB_ALIGN_16 },
+ { X86::PACKSSDWrr, X86::PACKSSDWrm, TB_ALIGN_16 },
+ { X86::PACKSSWBrr, X86::PACKSSWBrm, TB_ALIGN_16 },
+ { X86::PACKUSWBrr, X86::PACKUSWBrm, TB_ALIGN_16 },
+ { X86::PADDBrr, X86::PADDBrm, TB_ALIGN_16 },
+ { X86::PADDDrr, X86::PADDDrm, TB_ALIGN_16 },
+ { X86::PADDQrr, X86::PADDQrm, TB_ALIGN_16 },
+ { X86::PADDSBrr, X86::PADDSBrm, TB_ALIGN_16 },
+ { X86::PADDSWrr, X86::PADDSWrm, TB_ALIGN_16 },
+ { X86::PADDWrr, X86::PADDWrm, TB_ALIGN_16 },
+ { X86::PANDNrr, X86::PANDNrm, TB_ALIGN_16 },
+ { X86::PANDrr, X86::PANDrm, TB_ALIGN_16 },
+ { X86::PAVGBrr, X86::PAVGBrm, TB_ALIGN_16 },
+ { X86::PAVGWrr, X86::PAVGWrm, TB_ALIGN_16 },
+ { X86::PCMPEQBrr, X86::PCMPEQBrm, TB_ALIGN_16 },
+ { X86::PCMPEQDrr, X86::PCMPEQDrm, TB_ALIGN_16 },
+ { X86::PCMPEQWrr, X86::PCMPEQWrm, TB_ALIGN_16 },
+ { X86::PCMPGTBrr, X86::PCMPGTBrm, TB_ALIGN_16 },
+ { X86::PCMPGTDrr, X86::PCMPGTDrm, TB_ALIGN_16 },
+ { X86::PCMPGTWrr, X86::PCMPGTWrm, TB_ALIGN_16 },
+ { X86::PINSRWrri, X86::PINSRWrmi, TB_ALIGN_16 },
+ { X86::PMADDWDrr, X86::PMADDWDrm, TB_ALIGN_16 },
+ { X86::PMAXSWrr, X86::PMAXSWrm, TB_ALIGN_16 },
+ { X86::PMAXUBrr, X86::PMAXUBrm, TB_ALIGN_16 },
+ { X86::PMINSWrr, X86::PMINSWrm, TB_ALIGN_16 },
+ { X86::PMINUBrr, X86::PMINUBrm, TB_ALIGN_16 },
+ { X86::PMULDQrr, X86::PMULDQrm, TB_ALIGN_16 },
+ { X86::PMULHUWrr, X86::PMULHUWrm, TB_ALIGN_16 },
+ { X86::PMULHWrr, X86::PMULHWrm, TB_ALIGN_16 },
+ { X86::PMULLDrr, X86::PMULLDrm, TB_ALIGN_16 },
+ { X86::PMULLWrr, X86::PMULLWrm, TB_ALIGN_16 },
+ { X86::PMULUDQrr, X86::PMULUDQrm, TB_ALIGN_16 },
+ { X86::PORrr, X86::PORrm, TB_ALIGN_16 },
+ { X86::PSADBWrr, X86::PSADBWrm, TB_ALIGN_16 },
+ { X86::PSLLDrr, X86::PSLLDrm, TB_ALIGN_16 },
+ { X86::PSLLQrr, X86::PSLLQrm, TB_ALIGN_16 },
+ { X86::PSLLWrr, X86::PSLLWrm, TB_ALIGN_16 },
+ { X86::PSRADrr, X86::PSRADrm, TB_ALIGN_16 },
+ { X86::PSRAWrr, X86::PSRAWrm, TB_ALIGN_16 },
+ { X86::PSRLDrr, X86::PSRLDrm, TB_ALIGN_16 },
+ { X86::PSRLQrr, X86::PSRLQrm, TB_ALIGN_16 },
+ { X86::PSRLWrr, X86::PSRLWrm, TB_ALIGN_16 },
+ { X86::PSUBBrr, X86::PSUBBrm, TB_ALIGN_16 },
+ { X86::PSUBDrr, X86::PSUBDrm, TB_ALIGN_16 },
+ { X86::PSUBSBrr, X86::PSUBSBrm, TB_ALIGN_16 },
+ { X86::PSUBSWrr, X86::PSUBSWrm, TB_ALIGN_16 },
+ { X86::PSUBWrr, X86::PSUBWrm, TB_ALIGN_16 },
+ { X86::PUNPCKHBWrr, X86::PUNPCKHBWrm, TB_ALIGN_16 },
+ { X86::PUNPCKHDQrr, X86::PUNPCKHDQrm, TB_ALIGN_16 },
+ { X86::PUNPCKHQDQrr, X86::PUNPCKHQDQrm, TB_ALIGN_16 },
+ { X86::PUNPCKHWDrr, X86::PUNPCKHWDrm, TB_ALIGN_16 },
+ { X86::PUNPCKLBWrr, X86::PUNPCKLBWrm, TB_ALIGN_16 },
+ { X86::PUNPCKLDQrr, X86::PUNPCKLDQrm, TB_ALIGN_16 },
+ { X86::PUNPCKLQDQrr, X86::PUNPCKLQDQrm, TB_ALIGN_16 },
+ { X86::PUNPCKLWDrr, X86::PUNPCKLWDrm, TB_ALIGN_16 },
+ { X86::PXORrr, X86::PXORrm, TB_ALIGN_16 },
+ { X86::SBB32rr, X86::SBB32rm, 0 },
+ { X86::SBB64rr, X86::SBB64rm, 0 },
+ { X86::SHUFPDrri, X86::SHUFPDrmi, TB_ALIGN_16 },
+ { X86::SHUFPSrri, X86::SHUFPSrmi, TB_ALIGN_16 },
+ { X86::SUB16rr, X86::SUB16rm, 0 },
+ { X86::SUB32rr, X86::SUB32rm, 0 },
+ { X86::SUB64rr, X86::SUB64rm, 0 },
+ { X86::SUB8rr, X86::SUB8rm, 0 },
+ { X86::SUBPDrr, X86::SUBPDrm, TB_ALIGN_16 },
+ { X86::SUBPSrr, X86::SUBPSrm, TB_ALIGN_16 },
+ { X86::SUBSDrr, X86::SUBSDrm, 0 },
+ { X86::SUBSSrr, X86::SUBSSrm, 0 },
// FIXME: TEST*rr -> swapped operand of TEST*mr.
- { X86::UNPCKHPDrr, X86::UNPCKHPDrm, 16 },
- { X86::UNPCKHPSrr, X86::UNPCKHPSrm, 16 },
- { X86::UNPCKLPDrr, X86::UNPCKLPDrm, 16 },
- { X86::UNPCKLPSrr, X86::UNPCKLPSrm, 16 },
- { X86::XOR16rr, X86::XOR16rm, 0 },
- { X86::XOR32rr, X86::XOR32rm, 0 },
- { X86::XOR64rr, X86::XOR64rm, 0 },
- { X86::XOR8rr, X86::XOR8rm, 0 },
- { X86::XORPDrr, X86::XORPDrm, 16 },
- { X86::XORPSrr, X86::XORPSrm, 16 }
+ { X86::UNPCKHPDrr, X86::UNPCKHPDrm, TB_ALIGN_16 },
+ { X86::UNPCKHPSrr, X86::UNPCKHPSrm, TB_ALIGN_16 },
+ { X86::UNPCKLPDrr, X86::UNPCKLPDrm, TB_ALIGN_16 },
+ { X86::UNPCKLPSrr, X86::UNPCKLPSrm, TB_ALIGN_16 },
+ { X86::XOR16rr, X86::XOR16rm, 0 },
+ { X86::XOR32rr, X86::XOR32rm, 0 },
+ { X86::XOR64rr, X86::XOR64rm, 0 },
+ { X86::XOR8rr, X86::XOR8rm, 0 },
+ { X86::XORPDrr, X86::XORPDrm, TB_ALIGN_16 },
+ { X86::XORPSrr, X86::XORPSrm, TB_ALIGN_16 },
+ // AVX 128-bit versions of foldable instructions
+ { X86::VCVTSD2SSrr, X86::VCVTSD2SSrm, 0 },
+ { X86::Int_VCVTSD2SSrr, X86::Int_VCVTSD2SSrm, 0 },
+ { X86::VCVTSI2SD64rr, X86::VCVTSI2SD64rm, 0 },
+ { X86::Int_VCVTSI2SD64rr, X86::Int_VCVTSI2SD64rm, 0 },
+ { X86::VCVTSI2SDrr, X86::VCVTSI2SDrm, 0 },
+ { X86::Int_VCVTSI2SDrr, X86::Int_VCVTSI2SDrm, 0 },
+ { X86::VCVTSI2SS64rr, X86::VCVTSI2SS64rm, 0 },
+ { X86::Int_VCVTSI2SS64rr, X86::Int_VCVTSI2SS64rm, 0 },
+ { X86::VCVTSI2SSrr, X86::VCVTSI2SSrm, 0 },
+ { X86::Int_VCVTSI2SSrr, X86::Int_VCVTSI2SSrm, 0 },
+ { X86::VCVTSS2SDrr, X86::VCVTSS2SDrm, 0 },
+ { X86::Int_VCVTSS2SDrr, X86::Int_VCVTSS2SDrm, 0 },
+ { X86::VCVTTSD2SI64rr, X86::VCVTTSD2SI64rm, 0 },
+ { X86::Int_VCVTTSD2SI64rr,X86::Int_VCVTTSD2SI64rm, 0 },
+ { X86::VCVTTSD2SIrr, X86::VCVTTSD2SIrm, 0 },
+ { X86::Int_VCVTTSD2SIrr, X86::Int_VCVTTSD2SIrm, 0 },
+ { X86::VCVTTSS2SI64rr, X86::VCVTTSS2SI64rm, 0 },
+ { X86::Int_VCVTTSS2SI64rr,X86::Int_VCVTTSS2SI64rm, 0 },
+ { X86::VCVTTSS2SIrr, X86::VCVTTSS2SIrm, 0 },
+ { X86::Int_VCVTTSS2SIrr, X86::Int_VCVTTSS2SIrm, 0 },
+ { X86::VCVTSD2SI64rr, X86::VCVTSD2SI64rm, 0 },
+ { X86::VCVTSD2SIrr, X86::VCVTSD2SIrm, 0 },
+ { X86::VCVTTPD2DQrr, X86::VCVTTPD2DQrm, TB_ALIGN_16 },
+ { X86::VCVTTPS2DQrr, X86::VCVTTPS2DQrm, TB_ALIGN_16 },
+ { X86::VRSQRTSSr, X86::VRSQRTSSm, 0 },
+ { X86::VSQRTSDr, X86::VSQRTSDm, 0 },
+ { X86::VSQRTSSr, X86::VSQRTSSm, 0 },
+ { X86::VADDPDrr, X86::VADDPDrm, TB_ALIGN_16 },
+ { X86::VADDPSrr, X86::VADDPSrm, TB_ALIGN_16 },
+ { X86::VADDSDrr, X86::VADDSDrm, 0 },
+ { X86::VADDSSrr, X86::VADDSSrm, 0 },
+ { X86::VADDSUBPDrr, X86::VADDSUBPDrm, TB_ALIGN_16 },
+ { X86::VADDSUBPSrr, X86::VADDSUBPSrm, TB_ALIGN_16 },
+ { X86::VANDNPDrr, X86::VANDNPDrm, TB_ALIGN_16 },
+ { X86::VANDNPSrr, X86::VANDNPSrm, TB_ALIGN_16 },
+ { X86::VANDPDrr, X86::VANDPDrm, TB_ALIGN_16 },
+ { X86::VANDPSrr, X86::VANDPSrm, TB_ALIGN_16 },
+ { X86::VCMPPDrri, X86::VCMPPDrmi, TB_ALIGN_16 },
+ { X86::VCMPPSrri, X86::VCMPPSrmi, TB_ALIGN_16 },
+ { X86::VCMPSDrr, X86::VCMPSDrm, 0 },
+ { X86::VCMPSSrr, X86::VCMPSSrm, 0 },
+ { X86::VDIVPDrr, X86::VDIVPDrm, TB_ALIGN_16 },
+ { X86::VDIVPSrr, X86::VDIVPSrm, TB_ALIGN_16 },
+ { X86::VDIVSDrr, X86::VDIVSDrm, 0 },
+ { X86::VDIVSSrr, X86::VDIVSSrm, 0 },
+ { X86::VFsANDNPDrr, X86::VFsANDNPDrm, TB_ALIGN_16 },
+ { X86::VFsANDNPSrr, X86::VFsANDNPSrm, TB_ALIGN_16 },
+ { X86::VFsANDPDrr, X86::VFsANDPDrm, TB_ALIGN_16 },
+ { X86::VFsANDPSrr, X86::VFsANDPSrm, TB_ALIGN_16 },
+ { X86::VFsORPDrr, X86::VFsORPDrm, TB_ALIGN_16 },
+ { X86::VFsORPSrr, X86::VFsORPSrm, TB_ALIGN_16 },
+ { X86::VFsXORPDrr, X86::VFsXORPDrm, TB_ALIGN_16 },
+ { X86::VFsXORPSrr, X86::VFsXORPSrm, TB_ALIGN_16 },
+ { X86::VHADDPDrr, X86::VHADDPDrm, TB_ALIGN_16 },
+ { X86::VHADDPSrr, X86::VHADDPSrm, TB_ALIGN_16 },
+ { X86::VHSUBPDrr, X86::VHSUBPDrm, TB_ALIGN_16 },
+ { X86::VHSUBPSrr, X86::VHSUBPSrm, TB_ALIGN_16 },
+ { X86::Int_VCMPSDrr, X86::Int_VCMPSDrm, 0 },
+ { X86::Int_VCMPSSrr, X86::Int_VCMPSSrm, 0 },
+ { X86::VMAXPDrr, X86::VMAXPDrm, TB_ALIGN_16 },
+ { X86::VMAXPDrr_Int, X86::VMAXPDrm_Int, TB_ALIGN_16 },
+ { X86::VMAXPSrr, X86::VMAXPSrm, TB_ALIGN_16 },
+ { X86::VMAXPSrr_Int, X86::VMAXPSrm_Int, TB_ALIGN_16 },
+ { X86::VMAXSDrr, X86::VMAXSDrm, 0 },
+ { X86::VMAXSDrr_Int, X86::VMAXSDrm_Int, 0 },
+ { X86::VMAXSSrr, X86::VMAXSSrm, 0 },
+ { X86::VMAXSSrr_Int, X86::VMAXSSrm_Int, 0 },
+ { X86::VMINPDrr, X86::VMINPDrm, TB_ALIGN_16 },
+ { X86::VMINPDrr_Int, X86::VMINPDrm_Int, TB_ALIGN_16 },
+ { X86::VMINPSrr, X86::VMINPSrm, TB_ALIGN_16 },
+ { X86::VMINPSrr_Int, X86::VMINPSrm_Int, TB_ALIGN_16 },
+ { X86::VMINSDrr, X86::VMINSDrm, 0 },
+ { X86::VMINSDrr_Int, X86::VMINSDrm_Int, 0 },
+ { X86::VMINSSrr, X86::VMINSSrm, 0 },
+ { X86::VMINSSrr_Int, X86::VMINSSrm_Int, 0 },
+ { X86::VMULPDrr, X86::VMULPDrm, TB_ALIGN_16 },
+ { X86::VMULPSrr, X86::VMULPSrm, TB_ALIGN_16 },
+ { X86::VMULSDrr, X86::VMULSDrm, 0 },
+ { X86::VMULSSrr, X86::VMULSSrm, 0 },
+ { X86::VORPDrr, X86::VORPDrm, TB_ALIGN_16 },
+ { X86::VORPSrr, X86::VORPSrm, TB_ALIGN_16 },
+ { X86::VPACKSSDWrr, X86::VPACKSSDWrm, TB_ALIGN_16 },
+ { X86::VPACKSSWBrr, X86::VPACKSSWBrm, TB_ALIGN_16 },
+ { X86::VPACKUSWBrr, X86::VPACKUSWBrm, TB_ALIGN_16 },
+ { X86::VPADDBrr, X86::VPADDBrm, TB_ALIGN_16 },
+ { X86::VPADDDrr, X86::VPADDDrm, TB_ALIGN_16 },
+ { X86::VPADDQrr, X86::VPADDQrm, TB_ALIGN_16 },
+ { X86::VPADDSBrr, X86::VPADDSBrm, TB_ALIGN_16 },
+ { X86::VPADDSWrr, X86::VPADDSWrm, TB_ALIGN_16 },
+ { X86::VPADDWrr, X86::VPADDWrm, TB_ALIGN_16 },
+ { X86::VPANDNrr, X86::VPANDNrm, TB_ALIGN_16 },
+ { X86::VPANDrr, X86::VPANDrm, TB_ALIGN_16 },
+ { X86::VPCMPEQBrr, X86::VPCMPEQBrm, TB_ALIGN_16 },
+ { X86::VPCMPEQDrr, X86::VPCMPEQDrm, TB_ALIGN_16 },
+ { X86::VPCMPEQWrr, X86::VPCMPEQWrm, TB_ALIGN_16 },
+ { X86::VPCMPGTBrr, X86::VPCMPGTBrm, TB_ALIGN_16 },
+ { X86::VPCMPGTDrr, X86::VPCMPGTDrm, TB_ALIGN_16 },
+ { X86::VPCMPGTWrr, X86::VPCMPGTWrm, TB_ALIGN_16 },
+ { X86::VPINSRWrri, X86::VPINSRWrmi, TB_ALIGN_16 },
+ { X86::VPMADDWDrr, X86::VPMADDWDrm, TB_ALIGN_16 },
+ { X86::VPMAXSWrr, X86::VPMAXSWrm, TB_ALIGN_16 },
+ { X86::VPMAXUBrr, X86::VPMAXUBrm, TB_ALIGN_16 },
+ { X86::VPMINSWrr, X86::VPMINSWrm, TB_ALIGN_16 },
+ { X86::VPMINUBrr, X86::VPMINUBrm, TB_ALIGN_16 },
+ { X86::VPMULDQrr, X86::VPMULDQrm, TB_ALIGN_16 },
+ { X86::VPMULHUWrr, X86::VPMULHUWrm, TB_ALIGN_16 },
+ { X86::VPMULHWrr, X86::VPMULHWrm, TB_ALIGN_16 },
+ { X86::VPMULLDrr, X86::VPMULLDrm, TB_ALIGN_16 },
+ { X86::VPMULLWrr, X86::VPMULLWrm, TB_ALIGN_16 },
+ { X86::VPMULUDQrr, X86::VPMULUDQrm, TB_ALIGN_16 },
+ { X86::VPORrr, X86::VPORrm, TB_ALIGN_16 },
+ { X86::VPSADBWrr, X86::VPSADBWrm, TB_ALIGN_16 },
+ { X86::VPSLLDrr, X86::VPSLLDrm, TB_ALIGN_16 },
+ { X86::VPSLLQrr, X86::VPSLLQrm, TB_ALIGN_16 },
+ { X86::VPSLLWrr, X86::VPSLLWrm, TB_ALIGN_16 },
+ { X86::VPSRADrr, X86::VPSRADrm, TB_ALIGN_16 },
+ { X86::VPSRAWrr, X86::VPSRAWrm, TB_ALIGN_16 },
+ { X86::VPSRLDrr, X86::VPSRLDrm, TB_ALIGN_16 },
+ { X86::VPSRLQrr, X86::VPSRLQrm, TB_ALIGN_16 },
+ { X86::VPSRLWrr, X86::VPSRLWrm, TB_ALIGN_16 },
+ { X86::VPSUBBrr, X86::VPSUBBrm, TB_ALIGN_16 },
+ { X86::VPSUBDrr, X86::VPSUBDrm, TB_ALIGN_16 },
+ { X86::VPSUBSBrr, X86::VPSUBSBrm, TB_ALIGN_16 },
+ { X86::VPSUBSWrr, X86::VPSUBSWrm, TB_ALIGN_16 },
+ { X86::VPSUBWrr, X86::VPSUBWrm, TB_ALIGN_16 },
+ { X86::VPUNPCKHBWrr, X86::VPUNPCKHBWrm, TB_ALIGN_16 },
+ { X86::VPUNPCKHDQrr, X86::VPUNPCKHDQrm, TB_ALIGN_16 },
+ { X86::VPUNPCKHQDQrr, X86::VPUNPCKHQDQrm, TB_ALIGN_16 },
+ { X86::VPUNPCKHWDrr, X86::VPUNPCKHWDrm, TB_ALIGN_16 },
+ { X86::VPUNPCKLBWrr, X86::VPUNPCKLBWrm, TB_ALIGN_16 },
+ { X86::VPUNPCKLDQrr, X86::VPUNPCKLDQrm, TB_ALIGN_16 },
+ { X86::VPUNPCKLQDQrr, X86::VPUNPCKLQDQrm, TB_ALIGN_16 },
+ { X86::VPUNPCKLWDrr, X86::VPUNPCKLWDrm, TB_ALIGN_16 },
+ { X86::VPXORrr, X86::VPXORrm, TB_ALIGN_16 },
+ { X86::VSHUFPDrri, X86::VSHUFPDrmi, TB_ALIGN_16 },
+ { X86::VSHUFPSrri, X86::VSHUFPSrmi, TB_ALIGN_16 },
+ { X86::VSUBPDrr, X86::VSUBPDrm, TB_ALIGN_16 },
+ { X86::VSUBPSrr, X86::VSUBPSrm, TB_ALIGN_16 },
+ { X86::VSUBSDrr, X86::VSUBSDrm, 0 },
+ { X86::VSUBSSrr, X86::VSUBSSrm, 0 },
+ { X86::VUNPCKHPDrr, X86::VUNPCKHPDrm, TB_ALIGN_16 },
+ { X86::VUNPCKHPSrr, X86::VUNPCKHPSrm, TB_ALIGN_16 },
+ { X86::VUNPCKLPDrr, X86::VUNPCKLPDrm, TB_ALIGN_16 },
+ { X86::VUNPCKLPSrr, X86::VUNPCKLPSrm, TB_ALIGN_16 },
+ { X86::VXORPDrr, X86::VXORPDrm, TB_ALIGN_16 },
+ { X86::VXORPSrr, X86::VXORPSrm, TB_ALIGN_16 }
+ // FIXME: add AVX 256-bit foldable instructions
};
for (unsigned i = 0, e = array_lengthof(OpTbl2); i != e; ++i) {
unsigned RegOp = OpTbl2[i][0];
- unsigned MemOp = OpTbl2[i][1] & ~TB_FLAGS;
- unsigned Align = OpTbl2[i][2];
-
- assert(!RegOp2MemOpTable2.count(RegOp) && "Duplicate entry!");
- RegOp2MemOpTable2[RegOp] = std::make_pair(MemOp, Align);
-
- // If this is not a reversible operation (because there is a many->one)
- // mapping, don't insert the reverse of the operation into MemOp2RegOpTable.
- if (OpTbl2[i][1] & TB_NOT_REVERSABLE)
- continue;
+ unsigned MemOp = OpTbl2[i][1];
+ unsigned Flags = OpTbl2[i][2];
+ AddTableEntry(RegOp2MemOpTable2, MemOp2RegOpTable,
+ RegOp, MemOp,
+ // Index 2, folded load
+ Flags | TB_INDEX_2 | TB_FOLDED_LOAD);
+ }
+}
- // Index 2, folded load
- unsigned AuxInfo = 2 | (1 << 4);
- assert(!MemOp2RegOpTable.count(MemOp) &&
+void
+X86InstrInfo::AddTableEntry(RegOp2MemOpTableType &R2MTable,
+ MemOp2RegOpTableType &M2RTable,
+ unsigned RegOp, unsigned MemOp, unsigned Flags) {
+ if ((Flags & TB_NO_FORWARD) == 0) {
+ assert(!R2MTable.count(RegOp) && "Duplicate entry!");
+ R2MTable[RegOp] = std::make_pair(MemOp, Flags);
+ }
+ if ((Flags & TB_NO_REVERSE) == 0) {
+ assert(!M2RTable.count(MemOp) &&
"Duplicated entries in unfolding maps?");
- MemOp2RegOpTable[MemOp] = std::make_pair(RegOp, AuxInfo);
- }
+ M2RTable[MemOp] = std::make_pair(RegOp, Flags);
+ }
}
bool
@@ -796,6 +1000,11 @@ static bool isFrameLoadOpcode(int Opcode) {
case X86::MOVAPSrm:
case X86::MOVAPDrm:
case X86::MOVDQArm:
+ case X86::VMOVSSrm:
+ case X86::VMOVSDrm:
+ case X86::VMOVAPSrm:
+ case X86::VMOVAPDrm:
+ case X86::VMOVDQArm:
case X86::VMOVAPSYrm:
case X86::VMOVAPDYrm:
case X86::VMOVDQAYrm:
@@ -820,6 +1029,11 @@ static bool isFrameStoreOpcode(int Opcode) {
case X86::MOVAPSmr:
case X86::MOVAPDmr:
case X86::MOVDQAmr:
+ case X86::VMOVSSmr:
+ case X86::VMOVSDmr:
+ case X86::VMOVAPSmr:
+ case X86::VMOVAPDmr:
+ case X86::VMOVDQAmr:
case X86::VMOVAPSYmr:
case X86::VMOVAPDYmr:
case X86::VMOVDQAYmr:
@@ -852,24 +1066,6 @@ unsigned X86InstrInfo::isLoadFromStackSlotPostFE(const MachineInstr *MI,
return 0;
}
-bool X86InstrInfo::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<const FixedStackPseudoSourceValue>((*o)->getValue())) {
- FrameIndex = Value->getFrameIndex();
- MMO = *o;
- return true;
- }
- }
- return false;
-}
-
unsigned X86InstrInfo::isStoreToStackSlot(const MachineInstr *MI,
int &FrameIndex) const {
if (isFrameStoreOpcode(MI->getOpcode()))
@@ -892,24 +1088,6 @@ unsigned X86InstrInfo::isStoreToStackSlotPostFE(const MachineInstr *MI,
return 0;
}
-bool X86InstrInfo::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<const FixedStackPseudoSourceValue>((*o)->getValue())) {
- FrameIndex = Value->getFrameIndex();
- MMO = *o;
- return true;
- }
- }
- return false;
-}
-
/// regIsPICBase - Return true if register is PIC base (i.e.g defined by
/// X86::MOVPC32r.
static bool regIsPICBase(unsigned BaseReg, const MachineRegisterInfo &MRI) {
@@ -941,12 +1119,20 @@ X86InstrInfo::isReallyTriviallyReMaterializable(const MachineInstr *MI,
case X86::MOVUPSrm:
case X86::MOVAPDrm:
case X86::MOVDQArm:
+ case X86::VMOVSSrm:
+ case X86::VMOVSDrm:
+ case X86::VMOVAPSrm:
+ case X86::VMOVUPSrm:
+ case X86::VMOVAPDrm:
+ case X86::VMOVDQArm:
case X86::VMOVAPSYrm:
case X86::VMOVUPSYrm:
case X86::VMOVAPDYrm:
case X86::VMOVDQAYrm:
case X86::MMX_MOVD64rm:
case X86::MMX_MOVQ64rm:
+ case X86::FsVMOVAPSrm:
+ case X86::FsVMOVAPDrm:
case X86::FsMOVAPSrm:
case X86::FsMOVAPDrm: {
// Loads from constant pools are trivially rematerializable.
@@ -1009,15 +1195,11 @@ static bool isSafeToClobberEFLAGS(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) {
MachineBasicBlock::iterator E = MBB.end();
- // It's always safe to clobber EFLAGS at the end of a block.
- if (I == E)
- return true;
-
// For compile time consideration, if we are not able to determine the
// safety after visiting 4 instructions in each direction, we will assume
// it's not safe.
MachineBasicBlock::iterator Iter = I;
- for (unsigned i = 0; i < 4; ++i) {
+ for (unsigned i = 0; Iter != E && i < 4; ++i) {
bool SeenDef = false;
for (unsigned j = 0, e = Iter->getNumOperands(); j != e; ++j) {
MachineOperand &MO = Iter->getOperand(j);
@@ -1037,10 +1219,16 @@ static bool isSafeToClobberEFLAGS(MachineBasicBlock &MBB,
// Skip over DBG_VALUE.
while (Iter != E && Iter->isDebugValue())
++Iter;
+ }
- // If we make it to the end of the block, it's safe to clobber EFLAGS.
- if (Iter == E)
- return true;
+ // It is safe to clobber EFLAGS at the end of a block of no successor has it
+ // live in.
+ if (Iter == E) {
+ for (MachineBasicBlock::succ_iterator SI = MBB.succ_begin(),
+ SE = MBB.succ_end(); SI != SE; ++SI)
+ if ((*SI)->isLiveIn(X86::EFLAGS))
+ return false;
+ return true;
}
MachineBasicBlock::iterator B = MBB.begin();
@@ -1946,7 +2134,8 @@ static bool isHReg(unsigned Reg) {
}
// Try and copy between VR128/VR64 and GR64 registers.
-static unsigned CopyToFromAsymmetricReg(unsigned DestReg, unsigned SrcReg) {
+static unsigned CopyToFromAsymmetricReg(unsigned DestReg, unsigned SrcReg,
+ bool HasAVX) {
// SrcReg(VR128) -> DestReg(GR64)
// SrcReg(VR64) -> DestReg(GR64)
// SrcReg(GR64) -> DestReg(VR128)
@@ -1955,7 +2144,7 @@ static unsigned CopyToFromAsymmetricReg(unsigned DestReg, unsigned SrcReg) {
if (X86::GR64RegClass.contains(DestReg)) {
if (X86::VR128RegClass.contains(SrcReg)) {
// Copy from a VR128 register to a GR64 register.
- return X86::MOVPQIto64rr;
+ return HasAVX ? X86::VMOVPQIto64rr : X86::MOVPQIto64rr;
} else if (X86::VR64RegClass.contains(SrcReg)) {
// Copy from a VR64 register to a GR64 register.
return X86::MOVSDto64rr;
@@ -1963,12 +2152,23 @@ static unsigned CopyToFromAsymmetricReg(unsigned DestReg, unsigned SrcReg) {
} else if (X86::GR64RegClass.contains(SrcReg)) {
// Copy from a GR64 register to a VR128 register.
if (X86::VR128RegClass.contains(DestReg))
- return X86::MOV64toPQIrr;
+ return HasAVX ? X86::VMOV64toPQIrr : X86::MOV64toPQIrr;
// Copy from a GR64 register to a VR64 register.
else if (X86::VR64RegClass.contains(DestReg))
return X86::MOV64toSDrr;
}
+ // SrcReg(FR32) -> DestReg(GR32)
+ // SrcReg(GR32) -> DestReg(FR32)
+
+ if (X86::GR32RegClass.contains(DestReg) && X86::FR32RegClass.contains(SrcReg))
+ // Copy from a FR32 register to a GR32 register.
+ return HasAVX ? X86::VMOVSS2DIrr : X86::MOVSS2DIrr;
+
+ if (X86::FR32RegClass.contains(DestReg) && X86::GR32RegClass.contains(SrcReg))
+ // Copy from a GR32 register to a FR32 register.
+ return HasAVX ? X86::VMOVDI2SSrr : X86::MOVDI2SSrr;
+
return 0;
}
@@ -1977,6 +2177,7 @@ void X86InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
unsigned DestReg, unsigned SrcReg,
bool KillSrc) const {
// First deal with the normal symmetric copies.
+ bool HasAVX = TM.getSubtarget<X86Subtarget>().hasAVX();
unsigned Opc = 0;
if (X86::GR64RegClass.contains(DestReg, SrcReg))
Opc = X86::MOV64rr;
@@ -1988,18 +2189,21 @@ void X86InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
// Copying to or from a physical H register on x86-64 requires a NOREX
// move. Otherwise use a normal move.
if ((isHReg(DestReg) || isHReg(SrcReg)) &&
- TM.getSubtarget<X86Subtarget>().is64Bit())
+ TM.getSubtarget<X86Subtarget>().is64Bit()) {
Opc = X86::MOV8rr_NOREX;
- else
+ // Both operands must be encodable without an REX prefix.
+ assert(X86::GR8_NOREXRegClass.contains(SrcReg, DestReg) &&
+ "8-bit H register can not be copied outside GR8_NOREX");
+ } else
Opc = X86::MOV8rr;
} else if (X86::VR128RegClass.contains(DestReg, SrcReg))
- Opc = X86::MOVAPSrr;
+ Opc = HasAVX ? X86::VMOVAPSrr : X86::MOVAPSrr;
else if (X86::VR256RegClass.contains(DestReg, SrcReg))
Opc = X86::VMOVAPSYrr;
else if (X86::VR64RegClass.contains(DestReg, SrcReg))
Opc = X86::MMX_MOVQ64rr;
else
- Opc = CopyToFromAsymmetricReg(DestReg, SrcReg);
+ Opc = CopyToFromAsymmetricReg(DestReg, SrcReg, HasAVX);
if (Opc) {
BuildMI(MBB, MI, DL, get(Opc), DestReg)
@@ -2043,6 +2247,7 @@ static unsigned getLoadStoreRegOpcode(unsigned Reg,
bool isStackAligned,
const TargetMachine &TM,
bool load) {
+ bool HasAVX = TM.getSubtarget<X86Subtarget>().hasAVX();
switch (RC->getSize()) {
default:
llvm_unreachable("Unknown spill size");
@@ -2061,7 +2266,9 @@ static unsigned getLoadStoreRegOpcode(unsigned Reg,
if (X86::GR32RegClass.hasSubClassEq(RC))
return load ? X86::MOV32rm : X86::MOV32mr;
if (X86::FR32RegClass.hasSubClassEq(RC))
- return load ? X86::MOVSSrm : X86::MOVSSmr;
+ return load ?
+ (HasAVX ? X86::VMOVSSrm : X86::MOVSSrm) :
+ (HasAVX ? X86::VMOVSSmr : X86::MOVSSmr);
if (X86::RFP32RegClass.hasSubClassEq(RC))
return load ? X86::LD_Fp32m : X86::ST_Fp32m;
llvm_unreachable("Unknown 4-byte regclass");
@@ -2069,7 +2276,9 @@ static unsigned getLoadStoreRegOpcode(unsigned Reg,
if (X86::GR64RegClass.hasSubClassEq(RC))
return load ? X86::MOV64rm : X86::MOV64mr;
if (X86::FR64RegClass.hasSubClassEq(RC))
- return load ? X86::MOVSDrm : X86::MOVSDmr;
+ return load ?
+ (HasAVX ? X86::VMOVSDrm : X86::MOVSDrm) :
+ (HasAVX ? X86::VMOVSDmr : X86::MOVSDmr);
if (X86::VR64RegClass.hasSubClassEq(RC))
return load ? X86::MMX_MOVQ64rm : X86::MMX_MOVQ64mr;
if (X86::RFP64RegClass.hasSubClassEq(RC))
@@ -2078,13 +2287,18 @@ static unsigned getLoadStoreRegOpcode(unsigned Reg,
case 10:
assert(X86::RFP80RegClass.hasSubClassEq(RC) && "Unknown 10-byte regclass");
return load ? X86::LD_Fp80m : X86::ST_FpP80m;
- case 16:
+ case 16: {
assert(X86::VR128RegClass.hasSubClassEq(RC) && "Unknown 16-byte regclass");
// If stack is realigned we can use aligned stores.
if (isStackAligned)
- return load ? X86::MOVAPSrm : X86::MOVAPSmr;
+ return load ?
+ (HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm) :
+ (HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
else
- return load ? X86::MOVUPSrm : X86::MOVUPSmr;
+ return load ?
+ (HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm) :
+ (HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
+ }
case 32:
assert(X86::VR256RegClass.hasSubClassEq(RC) && "Unknown 32-byte regclass");
// If stack is realigned we can use aligned stores.
@@ -2118,7 +2332,8 @@ void X86InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
const MachineFunction &MF = *MBB.getParent();
assert(MF.getFrameInfo()->getObjectSize(FrameIdx) >= RC->getSize() &&
"Stack slot too small for store");
- bool isAligned = (TM.getFrameLowering()->getStackAlignment() >= 16) ||
+ unsigned Alignment = RC->getSize() == 32 ? 32 : 16;
+ bool isAligned = (TM.getFrameLowering()->getStackAlignment() >= Alignment) ||
RI.canRealignStack(MF);
unsigned Opc = getStoreRegOpcode(SrcReg, RC, isAligned, TM);
DebugLoc DL = MBB.findDebugLoc(MI);
@@ -2133,7 +2348,9 @@ void X86InstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
MachineInstr::mmo_iterator MMOBegin,
MachineInstr::mmo_iterator MMOEnd,
SmallVectorImpl<MachineInstr*> &NewMIs) const {
- bool isAligned = MMOBegin != MMOEnd && (*MMOBegin)->getAlignment() >= 16;
+ unsigned Alignment = RC->getSize() == 32 ? 32 : 16;
+ bool isAligned = MMOBegin != MMOEnd &&
+ (*MMOBegin)->getAlignment() >= Alignment;
unsigned Opc = getStoreRegOpcode(SrcReg, RC, isAligned, TM);
DebugLoc DL;
MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc));
@@ -2151,7 +2368,8 @@ void X86InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
const MachineFunction &MF = *MBB.getParent();
- bool isAligned = (TM.getFrameLowering()->getStackAlignment() >= 16) ||
+ unsigned Alignment = RC->getSize() == 32 ? 32 : 16;
+ bool isAligned = (TM.getFrameLowering()->getStackAlignment() >= Alignment) ||
RI.canRealignStack(MF);
unsigned Opc = getLoadRegOpcode(DestReg, RC, isAligned, TM);
DebugLoc DL = MBB.findDebugLoc(MI);
@@ -2164,7 +2382,9 @@ void X86InstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
MachineInstr::mmo_iterator MMOBegin,
MachineInstr::mmo_iterator MMOEnd,
SmallVectorImpl<MachineInstr*> &NewMIs) const {
- bool isAligned = MMOBegin != MMOEnd && (*MMOBegin)->getAlignment() >= 16;
+ unsigned Alignment = RC->getSize() == 32 ? 32 : 16;
+ bool isAligned = MMOBegin != MMOEnd &&
+ (*MMOBegin)->getAlignment() >= Alignment;
unsigned Opc = getLoadRegOpcode(DestReg, RC, isAligned, TM);
DebugLoc DL;
MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
@@ -2174,6 +2394,40 @@ void X86InstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
NewMIs.push_back(MIB);
}
+/// Expand2AddrUndef - Expand a single-def pseudo instruction to a two-addr
+/// instruction with two undef reads of the register being defined. This is
+/// used for mapping:
+/// %xmm4 = V_SET0
+/// to:
+/// %xmm4 = PXORrr %xmm4<undef>, %xmm4<undef>
+///
+static bool Expand2AddrUndef(MachineInstr *MI, const MCInstrDesc &Desc) {
+ assert(Desc.getNumOperands() == 3 && "Expected two-addr instruction.");
+ unsigned Reg = MI->getOperand(0).getReg();
+ MI->setDesc(Desc);
+
+ // MachineInstr::addOperand() will insert explicit operands before any
+ // implicit operands.
+ MachineInstrBuilder(MI).addReg(Reg, RegState::Undef)
+ .addReg(Reg, RegState::Undef);
+ // But we don't trust that.
+ assert(MI->getOperand(1).getReg() == Reg &&
+ MI->getOperand(2).getReg() == Reg && "Misplaced operand");
+ return true;
+}
+
+bool X86InstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
+ bool HasAVX = TM.getSubtarget<X86Subtarget>().hasAVX();
+ switch (MI->getOpcode()) {
+ case X86::V_SET0:
+ return Expand2AddrUndef(MI, get(HasAVX ? X86::VPXORrr : X86::PXORrr));
+ case X86::TEST8ri_NOREX:
+ MI->setDesc(get(X86::TEST8ri));
+ return true;
+ }
+ return false;
+}
+
MachineInstr*
X86InstrInfo::emitFrameIndexDebugValue(MachineFunction &MF,
int FrameIx, uint64_t Offset,
@@ -2305,7 +2559,7 @@ X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
OpcodeTablePtr->find(MI->getOpcode());
if (I != OpcodeTablePtr->end()) {
unsigned Opcode = I->second.first;
- unsigned MinAlign = I->second.second;
+ unsigned MinAlign = (I->second.second & TB_ALIGN_MASK) >> TB_ALIGN_SHIFT;
if (Align < MinAlign)
return NULL;
bool NarrowToMOV32rm = false;
@@ -2352,6 +2606,51 @@ X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
return NULL;
}
+/// hasPartialRegUpdate - Return true for all instructions that only update
+/// the first 32 or 64-bits of the destination register and leave the rest
+/// unmodified. This can be used to avoid folding loads if the instructions
+/// only update part of the destination register, and the non-updated part is
+/// not needed. e.g. cvtss2sd, sqrtss. Unfolding the load from these
+/// instructions breaks the partial register dependency and it can improve
+/// performance. e.g.:
+///
+/// movss (%rdi), %xmm0
+/// cvtss2sd %xmm0, %xmm0
+///
+/// Instead of
+/// cvtss2sd (%rdi), %xmm0
+///
+/// FIXME: This should be turned into a TSFlags.
+///
+static bool hasPartialRegUpdate(unsigned Opcode) {
+ switch (Opcode) {
+ case X86::CVTSD2SSrr:
+ case X86::Int_CVTSD2SSrr:
+ case X86::CVTSS2SDrr:
+ case X86::Int_CVTSS2SDrr:
+ case X86::RCPSSr:
+ case X86::RCPSSr_Int:
+ case X86::ROUNDSDr:
+ case X86::ROUNDSSr:
+ case X86::RSQRTSSr:
+ case X86::RSQRTSSr_Int:
+ case X86::SQRTSSr:
+ case X86::SQRTSSr_Int:
+ // AVX encoded versions
+ case X86::VCVTSD2SSrr:
+ case X86::Int_VCVTSD2SSrr:
+ case X86::VCVTSS2SDrr:
+ case X86::Int_VCVTSS2SDrr:
+ case X86::VRCPSSr:
+ case X86::VROUNDSDr:
+ case X86::VROUNDSSr:
+ case X86::VRSQRTSSr:
+ case X86::VSQRTSSr:
+ return true;
+ }
+
+ return false;
+}
MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
MachineInstr *MI,
@@ -2360,22 +2659,11 @@ MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
// Check switch flag
if (NoFusing) return NULL;
- if (!MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize))
- switch (MI->getOpcode()) {
- case X86::CVTSD2SSrr:
- case X86::Int_CVTSD2SSrr:
- case X86::CVTSS2SDrr:
- case X86::Int_CVTSS2SDrr:
- case X86::RCPSSr:
- case X86::RCPSSr_Int:
- case X86::ROUNDSDr:
- case X86::ROUNDSSr:
- case X86::RSQRTSSr:
- case X86::RSQRTSSr_Int:
- case X86::SQRTSSr:
- case X86::SQRTSSr_Int:
- return 0;
- }
+ // Unless optimizing for size, don't fold to avoid partial
+ // register update stalls
+ if (!MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize) &&
+ hasPartialRegUpdate(MI->getOpcode()))
+ return 0;
const MachineFrameInfo *MFI = MF.getFrameInfo();
unsigned Size = MFI->getObjectSize(FrameIndex);
@@ -2412,22 +2700,11 @@ MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
// Check switch flag
if (NoFusing) return NULL;
- if (!MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize))
- switch (MI->getOpcode()) {
- case X86::CVTSD2SSrr:
- case X86::Int_CVTSD2SSrr:
- case X86::CVTSS2SDrr:
- case X86::Int_CVTSS2SDrr:
- case X86::RCPSSr:
- case X86::RCPSSr_Int:
- case X86::ROUNDSDr:
- case X86::ROUNDSSr:
- case X86::RSQRTSSr:
- case X86::RSQRTSSr_Int:
- case X86::SQRTSSr:
- case X86::SQRTSSr_Int:
- return 0;
- }
+ // Unless optimizing for size, don't fold to avoid partial
+ // register update stalls
+ if (!MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize) &&
+ hasPartialRegUpdate(MI->getOpcode()))
+ return 0;
// Determine the alignment of the load.
unsigned Alignment = 0;
@@ -2439,13 +2716,9 @@ MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
case X86::AVX_SET0PDY:
Alignment = 32;
break;
- case X86::V_SET0PS:
- case X86::V_SET0PD:
- case X86::V_SET0PI:
+ case X86::V_SET0:
case X86::V_SETALLONES:
- case X86::AVX_SET0PS:
- case X86::AVX_SET0PD:
- case X86::AVX_SET0PI:
+ case X86::AVX_SETALLONES:
Alignment = 16;
break;
case X86::FsFLD0SD:
@@ -2481,18 +2754,16 @@ MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
SmallVector<MachineOperand,X86::AddrNumOperands> MOs;
switch (LoadMI->getOpcode()) {
- case X86::V_SET0PS:
- case X86::V_SET0PD:
- case X86::V_SET0PI:
+ case X86::V_SET0:
case X86::V_SETALLONES:
- case X86::AVX_SET0PS:
- case X86::AVX_SET0PD:
- case X86::AVX_SET0PI:
case X86::AVX_SET0PSY:
case X86::AVX_SET0PDY:
+ case X86::AVX_SETALLONES:
case X86::FsFLD0SD:
- case X86::FsFLD0SS: {
- // Folding a V_SET0P? or V_SETALLONES as a load, to ease register pressure.
+ case X86::FsFLD0SS:
+ case X86::VFsFLD0SD:
+ case X86::VFsFLD0SS: {
+ // Folding a V_SET0 or V_SETALLONES as a load, to ease register pressure.
// Create a constant-pool entry and operands to load from it.
// Medium and large mode can't fold loads this way.
@@ -2515,7 +2786,7 @@ MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
// Create a constant-pool entry.
MachineConstantPool &MCP = *MF.getConstantPool();
- const Type *Ty;
+ Type *Ty;
unsigned Opc = LoadMI->getOpcode();
if (Opc == X86::FsFLD0SS || Opc == X86::VFsFLD0SS)
Ty = Type::getFloatTy(MF.getFunction()->getContext());
@@ -2525,9 +2796,10 @@ MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
Ty = VectorType::get(Type::getFloatTy(MF.getFunction()->getContext()), 8);
else
Ty = VectorType::get(Type::getInt32Ty(MF.getFunction()->getContext()), 4);
- const Constant *C = LoadMI->getOpcode() == X86::V_SETALLONES ?
- Constant::getAllOnesValue(Ty) :
- Constant::getNullValue(Ty);
+
+ bool IsAllOnes = (Opc == X86::V_SETALLONES || Opc == X86::AVX_SETALLONES);
+ const Constant *C = IsAllOnes ? Constant::getAllOnesValue(Ty) :
+ Constant::getNullValue(Ty);
unsigned CPI = MCP.getConstantPoolIndex(C, Alignment);
// Create operands to load from the constant pool entry.
@@ -2615,9 +2887,9 @@ bool X86InstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI,
if (I == MemOp2RegOpTable.end())
return false;
unsigned Opc = I->second.first;
- unsigned Index = I->second.second & 0xf;
- bool FoldedLoad = I->second.second & (1 << 4);
- bool FoldedStore = I->second.second & (1 << 5);
+ unsigned Index = I->second.second & TB_INDEX_MASK;
+ bool FoldedLoad = I->second.second & TB_FOLDED_LOAD;
+ bool FoldedStore = I->second.second & TB_FOLDED_STORE;
if (UnfoldLoad && !FoldedLoad)
return false;
UnfoldLoad &= FoldedLoad;
@@ -2743,9 +3015,9 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
if (I == MemOp2RegOpTable.end())
return false;
unsigned Opc = I->second.first;
- unsigned Index = I->second.second & 0xf;
- bool FoldedLoad = I->second.second & (1 << 4);
- bool FoldedStore = I->second.second & (1 << 5);
+ unsigned Index = I->second.second & TB_INDEX_MASK;
+ bool FoldedLoad = I->second.second & TB_FOLDED_LOAD;
+ bool FoldedStore = I->second.second & TB_FOLDED_STORE;
const MCInstrDesc &MCID = get(Opc);
const TargetRegisterClass *RC = getRegClass(MCID, Index, &RI);
unsigned NumDefs = MCID.NumDefs;
@@ -2780,7 +3052,9 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
!TM.getSubtarget<X86Subtarget>().isUnalignedMemAccessFast())
// Do not introduce a slow unaligned load.
return false;
- bool isAligned = (*MMOs.first) && (*MMOs.first)->getAlignment() >= 16;
+ unsigned Alignment = RC->getSize() == 32 ? 32 : 16;
+ bool isAligned = (*MMOs.first) &&
+ (*MMOs.first)->getAlignment() >= Alignment;
Load = DAG.getMachineNode(getLoadRegOpcode(0, RC, isAligned, TM), dl,
VT, MVT::Other, &AddrOps[0], AddrOps.size());
NewNodes.push_back(Load);
@@ -2822,7 +3096,9 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
!TM.getSubtarget<X86Subtarget>().isUnalignedMemAccessFast())
// Do not introduce a slow unaligned store.
return false;
- bool isAligned = (*MMOs.first) && (*MMOs.first)->getAlignment() >= 16;
+ unsigned Alignment = RC->getSize() == 32 ? 32 : 16;
+ bool isAligned = (*MMOs.first) &&
+ (*MMOs.first)->getAlignment() >= Alignment;
SDNode *Store = DAG.getMachineNode(getStoreRegOpcode(0, DstRC,
isAligned, TM),
dl, MVT::Other,
@@ -2843,14 +3119,14 @@ unsigned X86InstrInfo::getOpcodeAfterMemoryUnfold(unsigned Opc,
MemOp2RegOpTable.find(Opc);
if (I == MemOp2RegOpTable.end())
return 0;
- bool FoldedLoad = I->second.second & (1 << 4);
- bool FoldedStore = I->second.second & (1 << 5);
+ bool FoldedLoad = I->second.second & TB_FOLDED_LOAD;
+ bool FoldedStore = I->second.second & TB_FOLDED_STORE;
if (UnfoldLoad && !FoldedLoad)
return 0;
if (UnfoldStore && !FoldedStore)
return 0;
if (LoadRegIndex)
- *LoadRegIndex = I->second.second & 0xf;
+ *LoadRegIndex = I->second.second & TB_INDEX_MASK;
return I->second.first;
}
@@ -2881,6 +3157,16 @@ X86InstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
case X86::MOVAPDrm:
case X86::MOVDQArm:
case X86::MOVDQUrm:
+ // AVX load instructions
+ case X86::VMOVSSrm:
+ case X86::VMOVSDrm:
+ case X86::FsVMOVAPSrm:
+ case X86::FsVMOVAPDrm:
+ case X86::VMOVAPSrm:
+ case X86::VMOVUPSrm:
+ case X86::VMOVAPDrm:
+ case X86::VMOVDQArm:
+ case X86::VMOVDQUrm:
case X86::VMOVAPSYrm:
case X86::VMOVUPSYrm:
case X86::VMOVAPDYrm:
@@ -2908,6 +3194,16 @@ X86InstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
case X86::MOVAPDrm:
case X86::MOVDQArm:
case X86::MOVDQUrm:
+ // AVX load instructions
+ case X86::VMOVSSrm:
+ case X86::VMOVSDrm:
+ case X86::FsVMOVAPSrm:
+ case X86::FsVMOVAPDrm:
+ case X86::VMOVAPSrm:
+ case X86::VMOVUPSrm:
+ case X86::VMOVAPDrm:
+ case X86::VMOVDQArm:
+ case X86::VMOVDQUrm:
case X86::VMOVAPSYrm:
case X86::VMOVUPSYrm:
case X86::VMOVAPDYrm:
@@ -3007,31 +3303,6 @@ isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const {
RC == &X86::RFP64RegClass || RC == &X86::RFP80RegClass);
}
-
-/// isX86_64ExtendedReg - Is the MachineOperand a x86-64 extended (r8 or higher)
-/// register? e.g. r8, xmm8, xmm13, etc.
-bool X86InstrInfo::isX86_64ExtendedReg(unsigned RegNo) {
- switch (RegNo) {
- default: break;
- case X86::R8: case X86::R9: case X86::R10: case X86::R11:
- case X86::R12: case X86::R13: case X86::R14: case X86::R15:
- case X86::R8D: case X86::R9D: case X86::R10D: case X86::R11D:
- case X86::R12D: case X86::R13D: case X86::R14D: case X86::R15D:
- case X86::R8W: case X86::R9W: case X86::R10W: case X86::R11W:
- case X86::R12W: case X86::R13W: case X86::R14W: case X86::R15W:
- case X86::R8B: case X86::R9B: case X86::R10B: case X86::R11B:
- case X86::R12B: case X86::R13B: case X86::R14B: case X86::R15B:
- case X86::XMM8: case X86::XMM9: case X86::XMM10: case X86::XMM11:
- case X86::XMM12: case X86::XMM13: case X86::XMM14: case X86::XMM15:
- case X86::YMM8: case X86::YMM9: case X86::YMM10: case X86::YMM11:
- case X86::YMM12: case X86::YMM13: case X86::YMM14: case X86::YMM15:
- case X86::CR8: case X86::CR9: case X86::CR10: case X86::CR11:
- case X86::CR12: case X86::CR13: case X86::CR14: case X86::CR15:
- return true;
- }
- return false;
-}
-
/// getGlobalBaseReg - Return a virtual register initialized with the
/// the global base register value. Output instructions required to
/// initialize the register in the function entry block, if necessary.
@@ -3072,7 +3343,6 @@ static const unsigned ReplaceableInstrs[][3] = {
{ X86::ANDPSrr, X86::ANDPDrr, X86::PANDrr },
{ X86::ORPSrm, X86::ORPDrm, X86::PORrm },
{ X86::ORPSrr, X86::ORPDrr, X86::PORrr },
- { X86::V_SET0PS, X86::V_SET0PD, X86::V_SET0PI },
{ X86::XORPSrm, X86::XORPDrm, X86::PXORrm },
{ X86::XORPSrr, X86::XORPDrr, X86::PXORrr },
// AVX 128-bit support
@@ -3088,7 +3358,6 @@ static const unsigned ReplaceableInstrs[][3] = {
{ X86::VANDPSrr, X86::VANDPDrr, X86::VPANDrr },
{ X86::VORPSrm, X86::VORPDrm, X86::VPORrm },
{ X86::VORPSrr, X86::VORPDrr, X86::VPORrr },
- { X86::AVX_SET0PS, X86::AVX_SET0PD, X86::AVX_SET0PI },
{ X86::VXORPSrm, X86::VXORPDrm, X86::VPXORrm },
{ X86::VXORPSrr, X86::VXORPDrr, X86::VPXORrr },
// AVX 256-bit support
@@ -3111,13 +3380,13 @@ static const unsigned *lookup(unsigned opcode, unsigned domain) {
}
std::pair<uint16_t, uint16_t>
-X86InstrInfo::GetSSEDomain(const MachineInstr *MI) const {
+X86InstrInfo::getExecutionDomain(const MachineInstr *MI) const {
uint16_t domain = (MI->getDesc().TSFlags >> X86II::SSEDomainShift) & 3;
return std::make_pair(domain,
domain && lookup(MI->getOpcode(), domain) ? 0xe : 0);
}
-void X86InstrInfo::SetSSEDomain(MachineInstr *MI, unsigned Domain) const {
+void X86InstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
assert(Domain>0 && Domain<4 && "Invalid execution domain");
uint16_t dom = (MI->getDesc().TSFlags >> X86II::SSEDomainShift) & 3;
assert(dom && "Not an SSE instruction");
@@ -3158,6 +3427,29 @@ bool X86InstrInfo::isHighLatencyDef(int opc) const {
case X86::SQRTSSm_Int:
case X86::SQRTSSr:
case X86::SQRTSSr_Int:
+ // AVX instructions with high latency
+ case X86::VDIVSDrm:
+ case X86::VDIVSDrm_Int:
+ case X86::VDIVSDrr:
+ case X86::VDIVSDrr_Int:
+ case X86::VDIVSSrm:
+ case X86::VDIVSSrm_Int:
+ case X86::VDIVSSrr:
+ case X86::VDIVSSrr_Int:
+ case X86::VSQRTPDm:
+ case X86::VSQRTPDm_Int:
+ case X86::VSQRTPDr:
+ case X86::VSQRTPDr_Int:
+ case X86::VSQRTPSm:
+ case X86::VSQRTPSm_Int:
+ case X86::VSQRTPSr:
+ case X86::VSQRTPSr_Int:
+ case X86::VSQRTSDm:
+ case X86::VSQRTSDm_Int:
+ case X86::VSQRTSDr:
+ case X86::VSQRTSSm:
+ case X86::VSQRTSSm_Int:
+ case X86::VSQRTSSr:
return true;
}
}
diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h
index 5f2eba3..97009db 100644
--- a/lib/Target/X86/X86InstrInfo.h
+++ b/lib/Target/X86/X86InstrInfo.h
@@ -27,24 +27,6 @@ namespace llvm {
class X86TargetMachine;
namespace X86 {
- // Enums for memory operand decoding. Each memory operand is represented with
- // a 5 operand sequence in the form:
- // [BaseReg, ScaleAmt, IndexReg, Disp, Segment]
- // These enums help decode this.
- enum {
- AddrBaseReg = 0,
- AddrScaleAmt = 1,
- AddrIndexReg = 2,
- AddrDisp = 3,
-
- /// AddrSegmentReg - The operand # of the segment in the memory operand.
- AddrSegmentReg = 4,
-
- /// AddrNumOperands - Total number of operands in a memory reference.
- AddrNumOperands = 5
- };
-
-
// X86 specific condition code. These correspond to X86_*_COND in
// X86InstrInfo.td. They must be kept in synch.
enum CondCode {
@@ -82,133 +64,8 @@ namespace X86 {
/// GetOppositeBranchCondition - Return the inverse of the specified cond,
/// e.g. turning COND_E to COND_NE.
CondCode GetOppositeBranchCondition(X86::CondCode CC);
+} // end namespace X86;
-}
-
-/// X86II - This namespace holds all of the target specific flags that
-/// instruction info tracks.
-///
-namespace X86II {
- /// Target Operand Flag enum.
- enum TOF {
- //===------------------------------------------------------------------===//
- // X86 Specific MachineOperand flags.
-
- MO_NO_FLAG,
-
- /// MO_GOT_ABSOLUTE_ADDRESS - On a symbol operand, this represents a
- /// relocation of:
- /// SYMBOL_LABEL + [. - PICBASELABEL]
- MO_GOT_ABSOLUTE_ADDRESS,
-
- /// MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the
- /// immediate should get the value of the symbol minus the PIC base label:
- /// SYMBOL_LABEL - PICBASELABEL
- MO_PIC_BASE_OFFSET,
-
- /// MO_GOT - On a symbol operand this indicates that the immediate is the
- /// offset to the GOT entry for the symbol name from the base of the GOT.
- ///
- /// See the X86-64 ELF ABI supplement for more details.
- /// SYMBOL_LABEL @GOT
- MO_GOT,
-
- /// MO_GOTOFF - On a symbol operand this indicates that the immediate is
- /// the offset to the location of the symbol name from the base of the GOT.
- ///
- /// See the X86-64 ELF ABI supplement for more details.
- /// SYMBOL_LABEL @GOTOFF
- MO_GOTOFF,
-
- /// MO_GOTPCREL - On a symbol operand this indicates that the immediate is
- /// offset to the GOT entry for the symbol name from the current code
- /// location.
- ///
- /// See the X86-64 ELF ABI supplement for more details.
- /// SYMBOL_LABEL @GOTPCREL
- MO_GOTPCREL,
-
- /// MO_PLT - On a symbol operand this indicates that the immediate is
- /// offset to the PLT entry of symbol name from the current code location.
- ///
- /// See the X86-64 ELF ABI supplement for more details.
- /// SYMBOL_LABEL @PLT
- MO_PLT,
-
- /// MO_TLSGD - On a symbol operand this indicates that the immediate is
- /// some TLS offset.
- ///
- /// See 'ELF Handling for Thread-Local Storage' for more details.
- /// SYMBOL_LABEL @TLSGD
- MO_TLSGD,
-
- /// MO_GOTTPOFF - On a symbol operand this indicates that the immediate is
- /// some TLS offset.
- ///
- /// See 'ELF Handling for Thread-Local Storage' for more details.
- /// SYMBOL_LABEL @GOTTPOFF
- MO_GOTTPOFF,
-
- /// MO_INDNTPOFF - On a symbol operand this indicates that the immediate is
- /// some TLS offset.
- ///
- /// See 'ELF Handling for Thread-Local Storage' for more details.
- /// SYMBOL_LABEL @INDNTPOFF
- MO_INDNTPOFF,
-
- /// MO_TPOFF - On a symbol operand this indicates that the immediate is
- /// some TLS offset.
- ///
- /// See 'ELF Handling for Thread-Local Storage' for more details.
- /// SYMBOL_LABEL @TPOFF
- MO_TPOFF,
-
- /// MO_NTPOFF - On a symbol operand this indicates that the immediate is
- /// some TLS offset.
- ///
- /// See 'ELF Handling for Thread-Local Storage' for more details.
- /// SYMBOL_LABEL @NTPOFF
- MO_NTPOFF,
-
- /// MO_DLLIMPORT - On a symbol operand "FOO", this indicates that the
- /// reference is actually to the "__imp_FOO" symbol. This is used for
- /// dllimport linkage on windows.
- MO_DLLIMPORT,
-
- /// MO_DARWIN_STUB - On a symbol operand "FOO", this indicates that the
- /// reference is actually to the "FOO$stub" symbol. This is used for calls
- /// and jumps to external functions on Tiger and earlier.
- MO_DARWIN_STUB,
-
- /// MO_DARWIN_NONLAZY - On a symbol operand "FOO", this indicates that the
- /// reference is actually to the "FOO$non_lazy_ptr" symbol, which is a
- /// non-PIC-base-relative reference to a non-hidden dyld lazy pointer stub.
- MO_DARWIN_NONLAZY,
-
- /// MO_DARWIN_NONLAZY_PIC_BASE - On a symbol operand "FOO", this indicates
- /// that the reference is actually to "FOO$non_lazy_ptr - PICBASE", which is
- /// a PIC-base-relative reference to a non-hidden dyld lazy pointer stub.
- MO_DARWIN_NONLAZY_PIC_BASE,
-
- /// MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE - On a symbol operand "FOO", this
- /// indicates that the reference is actually to "FOO$non_lazy_ptr -PICBASE",
- /// which is a PIC-base-relative reference to a hidden dyld lazy pointer
- /// stub.
- MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE,
-
- /// MO_TLVP - On a symbol operand this indicates that the immediate is
- /// some TLS offset.
- ///
- /// This is the TLS offset for the Darwin TLS mechanism.
- MO_TLVP,
-
- /// MO_TLVP_PIC_BASE - On a symbol operand this indicates that the immediate
- /// is some TLS offset from the picbase.
- ///
- /// This is the 32-bit TLS offset for Darwin TLS in PIC mode.
- MO_TLVP_PIC_BASE
- };
-}
/// isGlobalStubReference - Return true if the specified TargetFlag operand is
/// a reference to a stub for a global, not the global itself.
@@ -243,353 +100,6 @@ inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) {
}
}
-/// X86II - This namespace holds all of the target specific flags that
-/// instruction info tracks.
-///
-namespace X86II {
- enum {
- //===------------------------------------------------------------------===//
- // Instruction encodings. These are the standard/most common forms for X86
- // instructions.
- //
-
- // PseudoFrm - This represents an instruction that is a pseudo instruction
- // or one that has not been implemented yet. It is illegal to code generate
- // it, but tolerated for intermediate implementation stages.
- Pseudo = 0,
-
- /// Raw - This form is for instructions that don't have any operands, so
- /// they are just a fixed opcode value, like 'leave'.
- RawFrm = 1,
-
- /// AddRegFrm - This form is used for instructions like 'push r32' that have
- /// their one register operand added to their opcode.
- AddRegFrm = 2,
-
- /// MRMDestReg - This form is used for instructions that use the Mod/RM byte
- /// to specify a destination, which in this case is a register.
- ///
- MRMDestReg = 3,
-
- /// MRMDestMem - This form is used for instructions that use the Mod/RM byte
- /// to specify a destination, which in this case is memory.
- ///
- MRMDestMem = 4,
-
- /// MRMSrcReg - This form is used for instructions that use the Mod/RM byte
- /// to specify a source, which in this case is a register.
- ///
- MRMSrcReg = 5,
-
- /// MRMSrcMem - This form is used for instructions that use the Mod/RM byte
- /// to specify a source, which in this case is memory.
- ///
- MRMSrcMem = 6,
-
- /// MRM[0-7][rm] - These forms are used to represent instructions that use
- /// a Mod/RM byte, and use the middle field to hold extended opcode
- /// information. In the intel manual these are represented as /0, /1, ...
- ///
-
- // First, instructions that operate on a register r/m operand...
- MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19, // Format /0 /1 /2 /3
- MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23, // Format /4 /5 /6 /7
-
- // Next, instructions that operate on a memory r/m operand...
- MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27, // Format /0 /1 /2 /3
- MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31, // Format /4 /5 /6 /7
-
- // MRMInitReg - This form is used for instructions whose source and
- // destinations are the same register.
- MRMInitReg = 32,
-
- //// MRM_C1 - A mod/rm byte of exactly 0xC1.
- MRM_C1 = 33,
- MRM_C2 = 34,
- MRM_C3 = 35,
- MRM_C4 = 36,
- MRM_C8 = 37,
- MRM_C9 = 38,
- MRM_E8 = 39,
- MRM_F0 = 40,
- MRM_F8 = 41,
- MRM_F9 = 42,
- MRM_D0 = 45,
- MRM_D1 = 46,
-
- /// RawFrmImm8 - This is used for the ENTER instruction, which has two
- /// immediates, the first of which is a 16-bit immediate (specified by
- /// the imm encoding) and the second is a 8-bit fixed value.
- RawFrmImm8 = 43,
-
- /// RawFrmImm16 - This is used for CALL FAR instructions, which have two
- /// immediates, the first of which is a 16 or 32-bit immediate (specified by
- /// the imm encoding) and the second is a 16-bit fixed value. In the AMD
- /// manual, this operand is described as pntr16:32 and pntr16:16
- RawFrmImm16 = 44,
-
- FormMask = 63,
-
- //===------------------------------------------------------------------===//
- // Actual flags...
-
- // OpSize - Set if this instruction requires an operand size prefix (0x66),
- // which most often indicates that the instruction operates on 16 bit data
- // instead of 32 bit data.
- OpSize = 1 << 6,
-
- // AsSize - Set if this instruction requires an operand size prefix (0x67),
- // which most often indicates that the instruction address 16 bit address
- // instead of 32 bit address (or 32 bit address in 64 bit mode).
- AdSize = 1 << 7,
-
- //===------------------------------------------------------------------===//
- // Op0Mask - There are several prefix bytes that are used to form two byte
- // opcodes. These are currently 0x0F, 0xF3, and 0xD8-0xDF. This mask is
- // used to obtain the setting of this field. If no bits in this field is
- // set, there is no prefix byte for obtaining a multibyte opcode.
- //
- Op0Shift = 8,
- Op0Mask = 0x1F << Op0Shift,
-
- // TB - TwoByte - Set if this instruction has a two byte opcode, which
- // starts with a 0x0F byte before the real opcode.
- TB = 1 << Op0Shift,
-
- // REP - The 0xF3 prefix byte indicating repetition of the following
- // instruction.
- REP = 2 << Op0Shift,
-
- // D8-DF - These escape opcodes are used by the floating point unit. These
- // values must remain sequential.
- D8 = 3 << Op0Shift, D9 = 4 << Op0Shift,
- DA = 5 << Op0Shift, DB = 6 << Op0Shift,
- DC = 7 << Op0Shift, DD = 8 << Op0Shift,
- DE = 9 << Op0Shift, DF = 10 << Op0Shift,
-
- // XS, XD - These prefix codes are for single and double precision scalar
- // floating point operations performed in the SSE registers.
- XD = 11 << Op0Shift, XS = 12 << Op0Shift,
-
- // T8, TA, A6, A7 - Prefix after the 0x0F prefix.
- T8 = 13 << Op0Shift, TA = 14 << Op0Shift,
- A6 = 15 << Op0Shift, A7 = 16 << Op0Shift,
-
- // TF - Prefix before and after 0x0F
- TF = 17 << Op0Shift,
-
- //===------------------------------------------------------------------===//
- // REX_W - REX prefixes are instruction prefixes used in 64-bit mode.
- // They are used to specify GPRs and SSE registers, 64-bit operand size,
- // etc. We only cares about REX.W and REX.R bits and only the former is
- // statically determined.
- //
- REXShift = Op0Shift + 5,
- REX_W = 1 << REXShift,
-
- //===------------------------------------------------------------------===//
- // This three-bit field describes the size of an immediate operand. Zero is
- // unused so that we can tell if we forgot to set a value.
- ImmShift = REXShift + 1,
- ImmMask = 7 << ImmShift,
- Imm8 = 1 << ImmShift,
- Imm8PCRel = 2 << ImmShift,
- Imm16 = 3 << ImmShift,
- Imm16PCRel = 4 << ImmShift,
- Imm32 = 5 << ImmShift,
- Imm32PCRel = 6 << ImmShift,
- Imm64 = 7 << ImmShift,
-
- //===------------------------------------------------------------------===//
- // FP Instruction Classification... Zero is non-fp instruction.
-
- // FPTypeMask - Mask for all of the FP types...
- FPTypeShift = ImmShift + 3,
- FPTypeMask = 7 << FPTypeShift,
-
- // NotFP - The default, set for instructions that do not use FP registers.
- NotFP = 0 << FPTypeShift,
-
- // ZeroArgFP - 0 arg FP instruction which implicitly pushes ST(0), f.e. fld0
- ZeroArgFP = 1 << FPTypeShift,
-
- // OneArgFP - 1 arg FP instructions which implicitly read ST(0), such as fst
- OneArgFP = 2 << FPTypeShift,
-
- // OneArgFPRW - 1 arg FP instruction which implicitly read ST(0) and write a
- // result back to ST(0). For example, fcos, fsqrt, etc.
- //
- OneArgFPRW = 3 << FPTypeShift,
-
- // TwoArgFP - 2 arg FP instructions which implicitly read ST(0), and an
- // explicit argument, storing the result to either ST(0) or the implicit
- // argument. For example: fadd, fsub, fmul, etc...
- TwoArgFP = 4 << FPTypeShift,
-
- // CompareFP - 2 arg FP instructions which implicitly read ST(0) and an
- // explicit argument, but have no destination. Example: fucom, fucomi, ...
- CompareFP = 5 << FPTypeShift,
-
- // CondMovFP - "2 operand" floating point conditional move instructions.
- CondMovFP = 6 << FPTypeShift,
-
- // SpecialFP - Special instruction forms. Dispatch by opcode explicitly.
- SpecialFP = 7 << FPTypeShift,
-
- // Lock prefix
- LOCKShift = FPTypeShift + 3,
- LOCK = 1 << LOCKShift,
-
- // Segment override prefixes. Currently we just need ability to address
- // stuff in gs and fs segments.
- SegOvrShift = LOCKShift + 1,
- SegOvrMask = 3 << SegOvrShift,
- FS = 1 << SegOvrShift,
- GS = 2 << SegOvrShift,
-
- // Execution domain for SSE instructions in bits 23, 24.
- // 0 in bits 23-24 means normal, non-SSE instruction.
- SSEDomainShift = SegOvrShift + 2,
-
- OpcodeShift = SSEDomainShift + 2,
-
- //===------------------------------------------------------------------===//
- /// VEX - The opcode prefix used by AVX instructions
- VEXShift = OpcodeShift + 8,
- VEX = 1U << 0,
-
- /// VEX_W - Has a opcode specific functionality, but is used in the same
- /// way as REX_W is for regular SSE instructions.
- VEX_W = 1U << 1,
-
- /// VEX_4V - Used to specify an additional AVX/SSE register. Several 2
- /// address instructions in SSE are represented as 3 address ones in AVX
- /// and the additional register is encoded in VEX_VVVV prefix.
- VEX_4V = 1U << 2,
-
- /// VEX_I8IMM - Specifies that the last register used in a AVX instruction,
- /// must be encoded in the i8 immediate field. This usually happens in
- /// instructions with 4 operands.
- VEX_I8IMM = 1U << 3,
-
- /// VEX_L - Stands for a bit in the VEX opcode prefix meaning the current
- /// instruction uses 256-bit wide registers. This is usually auto detected
- /// if a VR256 register is used, but some AVX instructions also have this
- /// field marked when using a f256 memory references.
- VEX_L = 1U << 4,
-
- /// Has3DNow0F0FOpcode - This flag indicates that the instruction uses the
- /// wacky 0x0F 0x0F prefix for 3DNow! instructions. The manual documents
- /// this as having a 0x0F prefix with a 0x0F opcode, and each instruction
- /// storing a classifier in the imm8 field. To simplify our implementation,
- /// we handle this by storeing the classifier in the opcode field and using
- /// this flag to indicate that the encoder should do the wacky 3DNow! thing.
- Has3DNow0F0FOpcode = 1U << 5
- };
-
- // getBaseOpcodeFor - This function returns the "base" X86 opcode for the
- // specified machine instruction.
- //
- static inline unsigned char getBaseOpcodeFor(uint64_t TSFlags) {
- return TSFlags >> X86II::OpcodeShift;
- }
-
- static inline bool hasImm(uint64_t TSFlags) {
- return (TSFlags & X86II::ImmMask) != 0;
- }
-
- /// getSizeOfImm - Decode the "size of immediate" field from the TSFlags field
- /// of the specified instruction.
- static inline unsigned getSizeOfImm(uint64_t TSFlags) {
- switch (TSFlags & X86II::ImmMask) {
- default: assert(0 && "Unknown immediate size");
- case X86II::Imm8:
- case X86II::Imm8PCRel: return 1;
- case X86II::Imm16:
- case X86II::Imm16PCRel: return 2;
- case X86II::Imm32:
- case X86II::Imm32PCRel: return 4;
- case X86II::Imm64: return 8;
- }
- }
-
- /// isImmPCRel - Return true if the immediate of the specified instruction's
- /// TSFlags indicates that it is pc relative.
- static inline unsigned isImmPCRel(uint64_t TSFlags) {
- switch (TSFlags & X86II::ImmMask) {
- default: assert(0 && "Unknown immediate size");
- case X86II::Imm8PCRel:
- case X86II::Imm16PCRel:
- case X86II::Imm32PCRel:
- return true;
- case X86II::Imm8:
- case X86II::Imm16:
- case X86II::Imm32:
- case X86II::Imm64:
- return false;
- }
- }
-
- /// getMemoryOperandNo - The function returns the MCInst operand # for the
- /// first field of the memory operand. If the instruction doesn't have a
- /// memory operand, this returns -1.
- ///
- /// Note that this ignores tied operands. If there is a tied register which
- /// is duplicated in the MCInst (e.g. "EAX = addl EAX, [mem]") it is only
- /// counted as one operand.
- ///
- static inline int getMemoryOperandNo(uint64_t TSFlags) {
- switch (TSFlags & X86II::FormMask) {
- case X86II::MRMInitReg: assert(0 && "FIXME: Remove this form");
- default: assert(0 && "Unknown FormMask value in getMemoryOperandNo!");
- case X86II::Pseudo:
- case X86II::RawFrm:
- case X86II::AddRegFrm:
- case X86II::MRMDestReg:
- case X86II::MRMSrcReg:
- case X86II::RawFrmImm8:
- case X86II::RawFrmImm16:
- return -1;
- case X86II::MRMDestMem:
- return 0;
- case X86II::MRMSrcMem: {
- bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V;
- unsigned FirstMemOp = 1;
- if (HasVEX_4V)
- ++FirstMemOp;// Skip the register source (which is encoded in VEX_VVVV).
-
- // FIXME: Maybe lea should have its own form? This is a horrible hack.
- //if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r ||
- // Opcode == X86::LEA16r || Opcode == X86::LEA32r)
- return FirstMemOp;
- }
- case X86II::MRM0r: case X86II::MRM1r:
- case X86II::MRM2r: case X86II::MRM3r:
- case X86II::MRM4r: case X86II::MRM5r:
- case X86II::MRM6r: case X86II::MRM7r:
- return -1;
- case X86II::MRM0m: case X86II::MRM1m:
- case X86II::MRM2m: case X86II::MRM3m:
- case X86II::MRM4m: case X86II::MRM5m:
- case X86II::MRM6m: case X86II::MRM7m:
- return 0;
- case X86II::MRM_C1:
- case X86II::MRM_C2:
- case X86II::MRM_C3:
- case X86II::MRM_C4:
- case X86II::MRM_C8:
- case X86II::MRM_C9:
- case X86II::MRM_E8:
- case X86II::MRM_F0:
- case X86II::MRM_F8:
- case X86II::MRM_F9:
- case X86II::MRM_D0:
- case X86II::MRM_D1:
- return -1;
- }
- }
-}
-
inline static bool isScale(const MachineOperand &MO) {
return MO.isImm() &&
(MO.getImm() == 1 || MO.getImm() == 2 ||
@@ -621,14 +131,22 @@ class X86InstrInfo : public X86GenInstrInfo {
/// RegOp2MemOpTable2Addr, RegOp2MemOpTable0, RegOp2MemOpTable1,
/// RegOp2MemOpTable2 - Load / store folding opcode maps.
///
- DenseMap<unsigned, std::pair<unsigned,unsigned> > RegOp2MemOpTable2Addr;
- DenseMap<unsigned, std::pair<unsigned,unsigned> > RegOp2MemOpTable0;
- DenseMap<unsigned, std::pair<unsigned,unsigned> > RegOp2MemOpTable1;
- DenseMap<unsigned, std::pair<unsigned,unsigned> > RegOp2MemOpTable2;
+ typedef DenseMap<unsigned,
+ std::pair<unsigned, unsigned> > RegOp2MemOpTableType;
+ RegOp2MemOpTableType RegOp2MemOpTable2Addr;
+ RegOp2MemOpTableType RegOp2MemOpTable0;
+ RegOp2MemOpTableType RegOp2MemOpTable1;
+ RegOp2MemOpTableType RegOp2MemOpTable2;
/// MemOp2RegOpTable - Load / store unfolding opcode map.
///
- DenseMap<unsigned, std::pair<unsigned, unsigned> > MemOp2RegOpTable;
+ typedef DenseMap<unsigned,
+ std::pair<unsigned, unsigned> > MemOp2RegOpTableType;
+ MemOp2RegOpTableType MemOp2RegOpTable;
+
+ void AddTableEntry(RegOp2MemOpTableType &R2MTable,
+ MemOp2RegOpTableType &M2RTable,
+ unsigned RegOp, unsigned MemOp, unsigned Flags);
public:
explicit X86InstrInfo(X86TargetMachine &tm);
@@ -656,17 +174,6 @@ public:
unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI,
int &FrameIndex) const;
- /// hasLoadFromStackSlot - If the specified machine instruction has
- /// a load from a stack slot, return true along with the FrameIndex
- /// of the loaded stack slot and the machine mem operand containing
- /// the reference. If not, return false. Unlike
- /// isLoadFromStackSlot, this returns true for any instructions that
- /// loads from the stack. This is a hint only and may not catch all
- /// cases.
- bool hasLoadFromStackSlot(const MachineInstr *MI,
- const MachineMemOperand *&MMO,
- int &FrameIndex) const;
-
unsigned isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const;
/// isStoreToStackSlotPostFE - Check for post-frame ptr elimination
/// stack locations as well. This uses a heuristic so it isn't
@@ -674,16 +181,6 @@ public:
unsigned isStoreToStackSlotPostFE(const MachineInstr *MI,
int &FrameIndex) const;
- /// hasStoreToStackSlot - If the specified machine instruction has a
- /// store to a stack slot, return true along with the FrameIndex of
- /// the loaded stack slot and the machine mem operand containing the
- /// reference. If not, return false. Unlike isStoreToStackSlot,
- /// this returns true for any instructions that loads from the
- /// stack. This is a hint only and may not catch all cases.
- bool hasStoreToStackSlot(const MachineInstr *MI,
- const MachineMemOperand *&MMO,
- int &FrameIndex) const;
-
bool isReallyTriviallyReMaterializable(const MachineInstr *MI,
AliasAnalysis *AA) const;
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
@@ -750,6 +247,9 @@ public:
MachineInstr::mmo_iterator MMOBegin,
MachineInstr::mmo_iterator MMOEnd,
SmallVectorImpl<MachineInstr*> &NewMIs) const;
+
+ virtual bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const;
+
virtual
MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF,
int FrameIx, uint64_t Offset,
@@ -829,32 +329,21 @@ public:
/// instruction that defines the specified register class.
bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const;
- static bool isX86_64NonExtLowByteReg(unsigned reg) {
- return (reg == X86::SPL || reg == X86::BPL ||
- reg == X86::SIL || reg == X86::DIL);
- }
-
static bool isX86_64ExtendedReg(const MachineOperand &MO) {
if (!MO.isReg()) return false;
- return isX86_64ExtendedReg(MO.getReg());
+ return X86II::isX86_64ExtendedReg(MO.getReg());
}
- /// isX86_64ExtendedReg - Is the MachineOperand a x86-64 extended (r8 or
- /// higher) register? e.g. r8, xmm8, xmm13, etc.
- static bool isX86_64ExtendedReg(unsigned RegNo);
-
/// getGlobalBaseReg - Return a virtual register initialized with the
/// the global base register value. Output instructions required to
/// initialize the register in the function entry block, if necessary.
///
unsigned getGlobalBaseReg(MachineFunction *MF) const;
- /// GetSSEDomain - Return the SSE execution domain of MI as the first element,
- /// and a bitmask of possible arguments to SetSSEDomain ase the second.
- std::pair<uint16_t, uint16_t> GetSSEDomain(const MachineInstr *MI) const;
+ std::pair<uint16_t, uint16_t>
+ getExecutionDomain(const MachineInstr *MI) const;
- /// SetSSEDomain - Set the SSEDomain of MI.
- void SetSSEDomain(MachineInstr *MI, unsigned Domain) const;
+ void setExecutionDomain(MachineInstr *MI, unsigned Domain) const;
MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
MachineInstr* MI,
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 7eb07b0..d54bf27 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -65,7 +65,7 @@ def SDTX86SetCC_C : SDTypeProfile<1, 2,
def SDTX86cas : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisInt<1>,
SDTCisVT<2, i8>]>;
-def SDTX86cas8 : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
+def SDTX86caspair : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
def SDTX86atomicBinary : SDTypeProfile<2, 3, [SDTCisInt<0>, SDTCisInt<1>,
SDTCisPtrTy<2>, SDTCisInt<3>,SDTCisInt<4>]>;
@@ -97,6 +97,8 @@ def SDT_X86TLSADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
def SDT_X86TLSCALL : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
+def SDT_X86SEG_ALLOCA : SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>;
+
def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
def SDT_X86TCRET : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>;
@@ -133,9 +135,13 @@ def X86setcc_c : SDNode<"X86ISD::SETCC_CARRY", SDTX86SetCC_C>;
def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas,
[SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore,
SDNPMayLoad, SDNPMemOperand]>;
-def X86cas8 : SDNode<"X86ISD::LCMPXCHG8_DAG", SDTX86cas8,
+def X86cas8 : SDNode<"X86ISD::LCMPXCHG8_DAG", SDTX86caspair,
+ [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore,
+ SDNPMayLoad, SDNPMemOperand]>;
+def X86cas16 : SDNode<"X86ISD::LCMPXCHG16_DAG", SDTX86caspair,
[SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore,
SDNPMayLoad, SDNPMemOperand]>;
+
def X86AtomAdd64 : SDNode<"X86ISD::ATOMADD64_DAG", SDTX86atomicBinary,
[SDNPHasChain, SDNPMayStore,
SDNPMayLoad, SDNPMemOperand]>;
@@ -218,12 +224,16 @@ def X86xor_flag : SDNode<"X86ISD::XOR", SDTBinaryArithWithFlags,
[SDNPCommutative]>;
def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags,
[SDNPCommutative]>;
+def X86andn_flag : SDNode<"X86ISD::ANDN", SDTBinaryArithWithFlags>;
def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>;
def X86WinAlloca : SDNode<"X86ISD::WIN_ALLOCA", SDTX86Void,
[SDNPHasChain, SDNPInGlue, SDNPOutGlue]>;
+def X86SegAlloca : SDNode<"X86ISD::SEG_ALLOCA", SDT_X86SEG_ALLOCA,
+ [SDNPHasChain]>;
+
def X86TLSCall : SDNode<"X86ISD::TLSCALL", SDT_X86TLSCALL,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
@@ -331,6 +341,11 @@ class ImmSExtAsmOperandClass : AsmOperandClass {
let RenderMethod = "addImmOperands";
}
+class ImmZExtAsmOperandClass : AsmOperandClass {
+ let SuperClasses = [ImmAsmOperand];
+ let RenderMethod = "addImmOperands";
+}
+
// Sign-extended immediate classes. We don't need to define the full lattice
// here because there is no instruction with an ambiguity between ImmSExti64i32
// and ImmSExti32i8.
@@ -358,6 +373,12 @@ def ImmSExti32i8AsmOperand : ImmSExtAsmOperandClass {
let Name = "ImmSExti32i8";
}
+// [0, 0x000000FF]
+def ImmZExtu32u8AsmOperand : ImmZExtAsmOperandClass {
+ let Name = "ImmZExtu32u8";
+}
+
+
// [0, 0x0000007F] |
// [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF]
def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass {
@@ -377,6 +398,11 @@ def i32i8imm : Operand<i32> {
let ParserMatchClass = ImmSExti32i8AsmOperand;
let OperandType = "OPERAND_IMMEDIATE";
}
+// 32-bits but only 8 bits are significant, and those 8 bits are unsigned.
+def u32u8imm : Operand<i32> {
+ let ParserMatchClass = ImmZExtu32u8AsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
+}
// 64-bits but only 32 bits are significant.
def i64i32imm : Operand<i64> {
@@ -389,11 +415,13 @@ def i64i32imm : Operand<i64> {
def i64i32imm_pcrel : Operand<i64> {
let PrintMethod = "print_pcrel_imm";
let ParserMatchClass = X86AbsMemAsmOperand;
+ let OperandType = "OPERAND_PCREL";
}
// 64-bits but only 8 bits are significant.
def i64i8imm : Operand<i64> {
let ParserMatchClass = ImmSExti64i8AsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def lea64_32mem : Operand<i32> {
@@ -442,18 +470,33 @@ def HasSSE4A : Predicate<"Subtarget->hasSSE4A()">;
def HasAVX : Predicate<"Subtarget->hasAVX()">;
def HasXMMInt : Predicate<"Subtarget->hasXMMInt()">;
+def HasPOPCNT : Predicate<"Subtarget->hasPOPCNT()">;
def HasAES : Predicate<"Subtarget->hasAES()">;
def HasCLMUL : Predicate<"Subtarget->hasCLMUL()">;
def HasFMA3 : Predicate<"Subtarget->hasFMA3()">;
def HasFMA4 : Predicate<"Subtarget->hasFMA4()">;
+def HasMOVBE : Predicate<"Subtarget->hasMOVBE()">;
+def HasRDRAND : Predicate<"Subtarget->hasRDRAND()">;
+def HasF16C : Predicate<"Subtarget->hasF16C()">;
+def HasLZCNT : Predicate<"Subtarget->hasLZCNT()">;
+def HasBMI : Predicate<"Subtarget->hasBMI()">;
def FPStackf32 : Predicate<"!Subtarget->hasXMM()">;
def FPStackf64 : Predicate<"!Subtarget->hasXMMInt()">;
+def HasCmpxchg16b: Predicate<"Subtarget->hasCmpxchg16b()">;
def In32BitMode : Predicate<"!Subtarget->is64Bit()">,
AssemblerPredicate<"!Mode64Bit">;
def In64BitMode : Predicate<"Subtarget->is64Bit()">,
AssemblerPredicate<"Mode64Bit">;
def IsWin64 : Predicate<"Subtarget->isTargetWin64()">;
def NotWin64 : Predicate<"!Subtarget->isTargetWin64()">;
+def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">,
+ AssemblerPredicate<"ModeNaCl">;
+def IsNaCl32 : Predicate<"Subtarget->isTargetNaCl32()">,
+ AssemblerPredicate<"ModeNaCl,!Mode64Bit">;
+def IsNaCl64 : Predicate<"Subtarget->isTargetNaCl64()">,
+ AssemblerPredicate<"ModeNaCl,Mode64Bit">;
+def NotNaCl : Predicate<"!Subtarget->isTargetNaCl()">,
+ AssemblerPredicate<"!ModeNaCl">;
def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">;
def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">;
def FarData : Predicate<"TM.getCodeModel() != CodeModel::Small &&"
@@ -766,30 +809,30 @@ def BSR64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
// These uses the DF flag in the EFLAGS register to inc or dec EDI and ESI
let Defs = [EDI,ESI], Uses = [EDI,ESI,EFLAGS] in {
-def MOVSB : I<0xA4, RawFrm, (outs), (ins), "{movsb}", []>;
-def MOVSW : I<0xA5, RawFrm, (outs), (ins), "{movsw}", []>, OpSize;
-def MOVSD : I<0xA5, RawFrm, (outs), (ins), "{movsl|movsd}", []>;
+def MOVSB : I<0xA4, RawFrm, (outs), (ins), "movsb", []>;
+def MOVSW : I<0xA5, RawFrm, (outs), (ins), "movsw", []>, OpSize;
+def MOVSD : I<0xA5, RawFrm, (outs), (ins), "movs{l|d}", []>;
def MOVSQ : RI<0xA5, RawFrm, (outs), (ins), "movsq", []>;
}
// These uses the DF flag in the EFLAGS register to inc or dec EDI and ESI
let Defs = [EDI], Uses = [AL,EDI,EFLAGS] in
-def STOSB : I<0xAA, RawFrm, (outs), (ins), "{stosb}", []>;
+def STOSB : I<0xAA, RawFrm, (outs), (ins), "stosb", []>;
let Defs = [EDI], Uses = [AX,EDI,EFLAGS] in
-def STOSW : I<0xAB, RawFrm, (outs), (ins), "{stosw}", []>, OpSize;
+def STOSW : I<0xAB, RawFrm, (outs), (ins), "stosw", []>, OpSize;
let Defs = [EDI], Uses = [EAX,EDI,EFLAGS] in
-def STOSD : I<0xAB, RawFrm, (outs), (ins), "{stosl|stosd}", []>;
+def STOSD : I<0xAB, RawFrm, (outs), (ins), "stos{l|d}", []>;
let Defs = [RCX,RDI], Uses = [RAX,RCX,RDI,EFLAGS] in
def STOSQ : RI<0xAB, RawFrm, (outs), (ins), "stosq", []>;
-def SCAS8 : I<0xAE, RawFrm, (outs), (ins), "scas{b}", []>;
-def SCAS16 : I<0xAF, RawFrm, (outs), (ins), "scas{w}", []>, OpSize;
-def SCAS32 : I<0xAF, RawFrm, (outs), (ins), "scas{l}", []>;
+def SCAS8 : I<0xAE, RawFrm, (outs), (ins), "scasb", []>;
+def SCAS16 : I<0xAF, RawFrm, (outs), (ins), "scasw", []>, OpSize;
+def SCAS32 : I<0xAF, RawFrm, (outs), (ins), "scas{l|d}", []>;
def SCAS64 : RI<0xAF, RawFrm, (outs), (ins), "scasq", []>;
-def CMPS8 : I<0xA6, RawFrm, (outs), (ins), "cmps{b}", []>;
-def CMPS16 : I<0xA7, RawFrm, (outs), (ins), "cmps{w}", []>, OpSize;
-def CMPS32 : I<0xA7, RawFrm, (outs), (ins), "cmps{l}", []>;
+def CMPS8 : I<0xA6, RawFrm, (outs), (ins), "cmpsb", []>;
+def CMPS16 : I<0xA7, RawFrm, (outs), (ins), "cmpsw", []>, OpSize;
+def CMPS32 : I<0xA7, RawFrm, (outs), (ins), "cmps{l|d}", []>;
def CMPS64 : RI<0xA7, RawFrm, (outs), (ins), "cmpsq", []>;
@@ -841,22 +884,22 @@ def MOV64mi32 : RIi32<0xC7, MRM0m, (outs), (ins i64mem:$dst, i64i32imm:$src),
/// moffs8, moffs16 and moffs32 versions of moves. The immediate is a
/// 32-bit offset from the PC. These are only valid in x86-32 mode.
def MOV8o8a : Ii32 <0xA0, RawFrm, (outs), (ins offset8:$src),
- "mov{b}\t{$src, %al|%al, $src}", []>,
+ "mov{b}\t{$src, %al|AL, $src}", []>,
Requires<[In32BitMode]>;
def MOV16o16a : Ii32 <0xA1, RawFrm, (outs), (ins offset16:$src),
- "mov{w}\t{$src, %ax|%ax, $src}", []>, OpSize,
+ "mov{w}\t{$src, %ax|AL, $src}", []>, OpSize,
Requires<[In32BitMode]>;
def MOV32o32a : Ii32 <0xA1, RawFrm, (outs), (ins offset32:$src),
- "mov{l}\t{$src, %eax|%eax, $src}", []>,
+ "mov{l}\t{$src, %eax|EAX, $src}", []>,
Requires<[In32BitMode]>;
def MOV8ao8 : Ii32 <0xA2, RawFrm, (outs offset8:$dst), (ins),
- "mov{b}\t{%al, $dst|$dst, %al}", []>,
+ "mov{b}\t{%al, $dst|$dst, AL}", []>,
Requires<[In32BitMode]>;
def MOV16ao16 : Ii32 <0xA3, RawFrm, (outs offset16:$dst), (ins),
- "mov{w}\t{%ax, $dst|$dst, %ax}", []>, OpSize,
+ "mov{w}\t{%ax, $dst|$dst, AL}", []>, OpSize,
Requires<[In32BitMode]>;
def MOV32ao32 : Ii32 <0xA3, RawFrm, (outs offset32:$dst), (ins),
- "mov{l}\t{%eax, $dst|$dst, %eax}", []>,
+ "mov{l}\t{%eax, $dst|$dst, EAX}", []>,
Requires<[In32BitMode]>;
// FIXME: These definitions are utterly broken
@@ -865,13 +908,13 @@ def MOV32ao32 : Ii32 <0xA3, RawFrm, (outs offset32:$dst), (ins),
// in question.
/*
def MOV64o8a : RIi8<0xA0, RawFrm, (outs), (ins offset8:$src),
- "mov{q}\t{$src, %rax|%rax, $src}", []>;
+ "mov{q}\t{$src, %rax|RAX, $src}", []>;
def MOV64o64a : RIi32<0xA1, RawFrm, (outs), (ins offset64:$src),
- "mov{q}\t{$src, %rax|%rax, $src}", []>;
+ "mov{q}\t{$src, %rax|RAX, $src}", []>;
def MOV64ao8 : RIi8<0xA2, RawFrm, (outs offset8:$dst), (ins),
- "mov{q}\t{%rax, $dst|$dst, %rax}", []>;
+ "mov{q}\t{%rax, $dst|$dst, RAX}", []>;
def MOV64ao64 : RIi32<0xA3, RawFrm, (outs offset64:$dst), (ins),
- "mov{q}\t{%rax, $dst|$dst, %rax}", []>;
+ "mov{q}\t{%rax, $dst|$dst, RAX}", []>;
*/
@@ -926,7 +969,7 @@ let mayStore = 1 in
def MOV8mr_NOREX : I<0x88, MRMDestMem,
(outs), (ins i8mem_NOREX:$dst, GR8_NOREX:$src),
"mov{b}\t{$src, $dst|$dst, $src} # NOREX", []>;
-let mayLoad = 1,
+let mayLoad = 1, neverHasSideEffects = 1,
canFoldAsLoad = 1, isReMaterializable = 1 in
def MOV8rm_NOREX : I<0x8A, MRMSrcMem,
(outs GR8_NOREX:$dst), (ins i8mem_NOREX:$src),
@@ -1117,11 +1160,15 @@ def XCHG64rr : RI<0x87, MRMSrcReg, (outs GR64:$dst), (ins GR64:$val,GR64:$src),
}
def XCHG16ar : I<0x90, AddRegFrm, (outs), (ins GR16:$src),
- "xchg{w}\t{$src, %ax|%ax, $src}", []>, OpSize;
+ "xchg{w}\t{$src, %ax|AX, $src}", []>, OpSize;
def XCHG32ar : I<0x90, AddRegFrm, (outs), (ins GR32:$src),
- "xchg{l}\t{$src, %eax|%eax, $src}", []>;
+ "xchg{l}\t{$src, %eax|EAX, $src}", []>, Requires<[In32BitMode]>;
+// Uses GR32_NOAX in 64-bit mode to prevent encoding using the 0x90 NOP encoding.
+// xchg %eax, %eax needs to clear upper 32-bits of RAX so is not a NOP.
+def XCHG32ar64 : I<0x90, AddRegFrm, (outs), (ins GR32_NOAX:$src),
+ "xchg{l}\t{$src, %eax|EAX, $src}", []>, Requires<[In64BitMode]>;
def XCHG64ar : RI<0x90, AddRegFrm, (outs), (ins GR64:$src),
- "xchg{q}\t{$src, %rax|%rax, $src}", []>;
+ "xchg{q}\t{$src, %rax|RAX, $src}", []>;
@@ -1172,7 +1219,7 @@ def CMPXCHG8B : I<0xC7, MRM1m, (outs), (ins i64mem:$dst),
let Defs = [RAX, RDX, EFLAGS], Uses = [RAX, RBX, RCX, RDX] in
def CMPXCHG16B : RI<0xC7, MRM1m, (outs), (ins i128mem:$dst),
- "cmpxchg16b\t$dst", []>, TB;
+ "cmpxchg16b\t$dst", []>, TB, Requires<[HasCmpxchg16b]>;
@@ -1261,6 +1308,104 @@ def ARPL16mr : I<0x63, MRMSrcMem, (outs GR16:$src), (ins i16mem:$dst),
"arpl\t{$src, $dst|$dst, $src}", []>, Requires<[In32BitMode]>;
//===----------------------------------------------------------------------===//
+// MOVBE Instructions
+//
+let Predicates = [HasMOVBE] in {
+ def MOVBE16rm : I<0xF0, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src),
+ "movbe{w}\t{$src, $dst|$dst, $src}",
+ [(set GR16:$dst, (bswap (loadi16 addr:$src)))]>, OpSize, T8;
+ def MOVBE32rm : I<0xF0, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
+ "movbe{l}\t{$src, $dst|$dst, $src}",
+ [(set GR32:$dst, (bswap (loadi32 addr:$src)))]>, T8;
+ def MOVBE64rm : RI<0xF0, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
+ "movbe{q}\t{$src, $dst|$dst, $src}",
+ [(set GR64:$dst, (bswap (loadi64 addr:$src)))]>, T8;
+ def MOVBE16mr : I<0xF1, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src),
+ "movbe{w}\t{$src, $dst|$dst, $src}",
+ [(store (bswap GR16:$src), addr:$dst)]>, OpSize, T8;
+ def MOVBE32mr : I<0xF1, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src),
+ "movbe{l}\t{$src, $dst|$dst, $src}",
+ [(store (bswap GR32:$src), addr:$dst)]>, T8;
+ def MOVBE64mr : RI<0xF1, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src),
+ "movbe{q}\t{$src, $dst|$dst, $src}",
+ [(store (bswap GR64:$src), addr:$dst)]>, T8;
+}
+
+//===----------------------------------------------------------------------===//
+// RDRAND Instruction
+//
+let Predicates = [HasRDRAND], Defs = [EFLAGS] in {
+ def RDRAND16r : I<0xC7, MRM6r, (outs GR16:$dst), (ins),
+ "rdrand{w}\t$dst", []>, OpSize, TB;
+ def RDRAND32r : I<0xC7, MRM6r, (outs GR32:$dst), (ins),
+ "rdrand{l}\t$dst", []>, TB;
+ def RDRAND64r : RI<0xC7, MRM6r, (outs GR64:$dst), (ins),
+ "rdrand{q}\t$dst", []>, TB;
+}
+
+//===----------------------------------------------------------------------===//
+// LZCNT Instruction
+//
+let Predicates = [HasLZCNT], Defs = [EFLAGS] in {
+ def LZCNT16rr : I<0xBD, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src),
+ "lzcnt{w}\t{$src, $dst|$dst, $src}",
+ [(set GR16:$dst, (ctlz GR16:$src)), (implicit EFLAGS)]>, XS,
+ OpSize;
+ def LZCNT16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src),
+ "lzcnt{w}\t{$src, $dst|$dst, $src}",
+ [(set GR16:$dst, (ctlz (loadi16 addr:$src))),
+ (implicit EFLAGS)]>, XS, OpSize;
+
+ def LZCNT32rr : I<0xBD, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src),
+ "lzcnt{l}\t{$src, $dst|$dst, $src}",
+ [(set GR32:$dst, (ctlz GR32:$src)), (implicit EFLAGS)]>, XS;
+ def LZCNT32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
+ "lzcnt{l}\t{$src, $dst|$dst, $src}",
+ [(set GR32:$dst, (ctlz (loadi32 addr:$src))),
+ (implicit EFLAGS)]>, XS;
+
+ def LZCNT64rr : RI<0xBD, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src),
+ "lzcnt{q}\t{$src, $dst|$dst, $src}",
+ [(set GR64:$dst, (ctlz GR64:$src)), (implicit EFLAGS)]>,
+ XS;
+ def LZCNT64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
+ "lzcnt{q}\t{$src, $dst|$dst, $src}",
+ [(set GR64:$dst, (ctlz (loadi64 addr:$src))),
+ (implicit EFLAGS)]>, XS;
+}
+
+//===----------------------------------------------------------------------===//
+// TZCNT Instruction
+//
+let Predicates = [HasBMI], Defs = [EFLAGS] in {
+ def TZCNT16rr : I<0xBC, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src),
+ "tzcnt{w}\t{$src, $dst|$dst, $src}",
+ [(set GR16:$dst, (cttz GR16:$src)), (implicit EFLAGS)]>, XS,
+ OpSize;
+ def TZCNT16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src),
+ "tzcnt{w}\t{$src, $dst|$dst, $src}",
+ [(set GR16:$dst, (cttz (loadi16 addr:$src))),
+ (implicit EFLAGS)]>, XS, OpSize;
+
+ def TZCNT32rr : I<0xBC, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src),
+ "tzcnt{l}\t{$src, $dst|$dst, $src}",
+ [(set GR32:$dst, (cttz GR32:$src)), (implicit EFLAGS)]>, XS;
+ def TZCNT32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
+ "tzcnt{l}\t{$src, $dst|$dst, $src}",
+ [(set GR32:$dst, (cttz (loadi32 addr:$src))),
+ (implicit EFLAGS)]>, XS;
+
+ def TZCNT64rr : RI<0xBC, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src),
+ "tzcnt{q}\t{$src, $dst|$dst, $src}",
+ [(set GR64:$dst, (cttz GR64:$src)), (implicit EFLAGS)]>,
+ XS;
+ def TZCNT64rm : RI<0xBC, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
+ "tzcnt{q}\t{$src, $dst|$dst, $src}",
+ [(set GR64:$dst, (cttz (loadi64 addr:$src))),
+ (implicit EFLAGS)]>, XS;
+}
+
+//===----------------------------------------------------------------------===//
// Subsystems.
//===----------------------------------------------------------------------===//
@@ -1646,3 +1791,9 @@ def : InstAlias<"xchgb $mem, $val", (XCHG8rm GR8 :$val, i8mem :$mem)>;
def : InstAlias<"xchgw $mem, $val", (XCHG16rm GR16:$val, i16mem:$mem)>;
def : InstAlias<"xchgl $mem, $val", (XCHG32rm GR32:$val, i32mem:$mem)>;
def : InstAlias<"xchgq $mem, $val", (XCHG64rm GR64:$val, i64mem:$mem)>;
+
+// xchg: We accept "xchgX <reg>, %eax" and "xchgX %eax, <reg>" as synonyms.
+def : InstAlias<"xchgw %ax, $src", (XCHG16ar GR16:$src)>;
+def : InstAlias<"xchgl %eax, $src", (XCHG32ar GR32:$src)>, Requires<[In32BitMode]>;
+def : InstAlias<"xchgl %eax, $src", (XCHG32ar64 GR32_NOAX:$src)>, Requires<[In64BitMode]>;
+def : InstAlias<"xchgq %rax, $src", (XCHG64ar GR64:$src)>;
diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td
index fe11d77..d3ced23 100644
--- a/lib/Target/X86/X86InstrSSE.td
+++ b/lib/Target/X86/X86InstrSSE.td
@@ -116,7 +116,217 @@ multiclass sse12_fp_packed_int<bits<8> opc, string OpcodeStr, RegisterClass RC,
}
//===----------------------------------------------------------------------===//
-// SSE 1 & 2 - Move Instructions
+// Non-instruction patterns
+//===----------------------------------------------------------------------===//
+
+// A vector extract of the first f32/f64 position is a subregister copy
+def : Pat<(f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))),
+ (f32 (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss))>;
+def : Pat<(f64 (vector_extract (v2f64 VR128:$src), (iPTR 0))),
+ (f64 (EXTRACT_SUBREG (v2f64 VR128:$src), sub_sd))>;
+
+// A 128-bit subvector extract from the first 256-bit vector position
+// is a subregister copy that needs no instruction.
+def : Pat<(v4i32 (extract_subvector (v8i32 VR256:$src), (i32 0))),
+ (v4i32 (EXTRACT_SUBREG (v8i32 VR256:$src), sub_xmm))>;
+def : Pat<(v4f32 (extract_subvector (v8f32 VR256:$src), (i32 0))),
+ (v4f32 (EXTRACT_SUBREG (v8f32 VR256:$src), sub_xmm))>;
+
+def : Pat<(v2i64 (extract_subvector (v4i64 VR256:$src), (i32 0))),
+ (v2i64 (EXTRACT_SUBREG (v4i64 VR256:$src), sub_xmm))>;
+def : Pat<(v2f64 (extract_subvector (v4f64 VR256:$src), (i32 0))),
+ (v2f64 (EXTRACT_SUBREG (v4f64 VR256:$src), sub_xmm))>;
+
+def : Pat<(v8i16 (extract_subvector (v16i16 VR256:$src), (i32 0))),
+ (v8i16 (EXTRACT_SUBREG (v16i16 VR256:$src), sub_xmm))>;
+def : Pat<(v16i8 (extract_subvector (v32i8 VR256:$src), (i32 0))),
+ (v16i8 (EXTRACT_SUBREG (v32i8 VR256:$src), sub_xmm))>;
+
+// A 128-bit subvector insert to the first 256-bit vector position
+// is a subregister copy that needs no instruction.
+def : Pat<(insert_subvector undef, (v2i64 VR128:$src), (i32 0)),
+ (INSERT_SUBREG (v4i64 (IMPLICIT_DEF)), VR128:$src, sub_xmm)>;
+def : Pat<(insert_subvector undef, (v2f64 VR128:$src), (i32 0)),
+ (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), VR128:$src, sub_xmm)>;
+def : Pat<(insert_subvector undef, (v4i32 VR128:$src), (i32 0)),
+ (INSERT_SUBREG (v8i32 (IMPLICIT_DEF)), VR128:$src, sub_xmm)>;
+def : Pat<(insert_subvector undef, (v4f32 VR128:$src), (i32 0)),
+ (INSERT_SUBREG (v8f32 (IMPLICIT_DEF)), VR128:$src, sub_xmm)>;
+def : Pat<(insert_subvector undef, (v8i16 VR128:$src), (i32 0)),
+ (INSERT_SUBREG (v16i16 (IMPLICIT_DEF)), VR128:$src, sub_xmm)>;
+def : Pat<(insert_subvector undef, (v16i8 VR128:$src), (i32 0)),
+ (INSERT_SUBREG (v32i8 (IMPLICIT_DEF)), VR128:$src, sub_xmm)>;
+
+// Implicitly promote a 32-bit scalar to a vector.
+def : Pat<(v4f32 (scalar_to_vector FR32:$src)),
+ (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FR32:$src, sub_ss)>;
+def : Pat<(v8f32 (scalar_to_vector FR32:$src)),
+ (INSERT_SUBREG (v8f32 (IMPLICIT_DEF)), FR32:$src, sub_ss)>;
+// Implicitly promote a 64-bit scalar to a vector.
+def : Pat<(v2f64 (scalar_to_vector FR64:$src)),
+ (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FR64:$src, sub_sd)>;
+def : Pat<(v4f64 (scalar_to_vector FR64:$src)),
+ (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), FR64:$src, sub_sd)>;
+
+// Bitcasts between 128-bit vector types. Return the original type since
+// no instruction is needed for the conversion
+let Predicates = [HasXMMInt] in {
+ def : Pat<(v2i64 (bitconvert (v4i32 VR128:$src))), (v2i64 VR128:$src)>;
+ def : Pat<(v2i64 (bitconvert (v8i16 VR128:$src))), (v2i64 VR128:$src)>;
+ def : Pat<(v2i64 (bitconvert (v16i8 VR128:$src))), (v2i64 VR128:$src)>;
+ def : Pat<(v2i64 (bitconvert (v2f64 VR128:$src))), (v2i64 VR128:$src)>;
+ def : Pat<(v2i64 (bitconvert (v4f32 VR128:$src))), (v2i64 VR128:$src)>;
+ def : Pat<(v4i32 (bitconvert (v2i64 VR128:$src))), (v4i32 VR128:$src)>;
+ def : Pat<(v4i32 (bitconvert (v8i16 VR128:$src))), (v4i32 VR128:$src)>;
+ def : Pat<(v4i32 (bitconvert (v16i8 VR128:$src))), (v4i32 VR128:$src)>;
+ def : Pat<(v4i32 (bitconvert (v2f64 VR128:$src))), (v4i32 VR128:$src)>;
+ def : Pat<(v4i32 (bitconvert (v4f32 VR128:$src))), (v4i32 VR128:$src)>;
+ def : Pat<(v8i16 (bitconvert (v2i64 VR128:$src))), (v8i16 VR128:$src)>;
+ def : Pat<(v8i16 (bitconvert (v4i32 VR128:$src))), (v8i16 VR128:$src)>;
+ def : Pat<(v8i16 (bitconvert (v16i8 VR128:$src))), (v8i16 VR128:$src)>;
+ def : Pat<(v8i16 (bitconvert (v2f64 VR128:$src))), (v8i16 VR128:$src)>;
+ def : Pat<(v8i16 (bitconvert (v4f32 VR128:$src))), (v8i16 VR128:$src)>;
+ def : Pat<(v16i8 (bitconvert (v2i64 VR128:$src))), (v16i8 VR128:$src)>;
+ def : Pat<(v16i8 (bitconvert (v4i32 VR128:$src))), (v16i8 VR128:$src)>;
+ def : Pat<(v16i8 (bitconvert (v8i16 VR128:$src))), (v16i8 VR128:$src)>;
+ def : Pat<(v16i8 (bitconvert (v2f64 VR128:$src))), (v16i8 VR128:$src)>;
+ def : Pat<(v16i8 (bitconvert (v4f32 VR128:$src))), (v16i8 VR128:$src)>;
+ def : Pat<(v4f32 (bitconvert (v2i64 VR128:$src))), (v4f32 VR128:$src)>;
+ def : Pat<(v4f32 (bitconvert (v4i32 VR128:$src))), (v4f32 VR128:$src)>;
+ def : Pat<(v4f32 (bitconvert (v8i16 VR128:$src))), (v4f32 VR128:$src)>;
+ def : Pat<(v4f32 (bitconvert (v16i8 VR128:$src))), (v4f32 VR128:$src)>;
+ def : Pat<(v4f32 (bitconvert (v2f64 VR128:$src))), (v4f32 VR128:$src)>;
+ def : Pat<(v2f64 (bitconvert (v2i64 VR128:$src))), (v2f64 VR128:$src)>;
+ def : Pat<(v2f64 (bitconvert (v4i32 VR128:$src))), (v2f64 VR128:$src)>;
+ def : Pat<(v2f64 (bitconvert (v8i16 VR128:$src))), (v2f64 VR128:$src)>;
+ def : Pat<(v2f64 (bitconvert (v16i8 VR128:$src))), (v2f64 VR128:$src)>;
+ def : Pat<(v2f64 (bitconvert (v4f32 VR128:$src))), (v2f64 VR128:$src)>;
+}
+
+// Bitcasts between 256-bit vector types. Return the original type since
+// no instruction is needed for the conversion
+let Predicates = [HasAVX] in {
+ def : Pat<(v4f64 (bitconvert (v8f32 VR256:$src))), (v4f64 VR256:$src)>;
+ def : Pat<(v4f64 (bitconvert (v8i32 VR256:$src))), (v4f64 VR256:$src)>;
+ def : Pat<(v4f64 (bitconvert (v4i64 VR256:$src))), (v4f64 VR256:$src)>;
+ def : Pat<(v4f64 (bitconvert (v16i16 VR256:$src))), (v4f64 VR256:$src)>;
+ def : Pat<(v4f64 (bitconvert (v32i8 VR256:$src))), (v4f64 VR256:$src)>;
+ def : Pat<(v8f32 (bitconvert (v8i32 VR256:$src))), (v8f32 VR256:$src)>;
+ def : Pat<(v8f32 (bitconvert (v4i64 VR256:$src))), (v8f32 VR256:$src)>;
+ def : Pat<(v8f32 (bitconvert (v4f64 VR256:$src))), (v8f32 VR256:$src)>;
+ def : Pat<(v8f32 (bitconvert (v32i8 VR256:$src))), (v8f32 VR256:$src)>;
+ def : Pat<(v8f32 (bitconvert (v16i16 VR256:$src))), (v8f32 VR256:$src)>;
+ def : Pat<(v4i64 (bitconvert (v8f32 VR256:$src))), (v4i64 VR256:$src)>;
+ def : Pat<(v4i64 (bitconvert (v8i32 VR256:$src))), (v4i64 VR256:$src)>;
+ def : Pat<(v4i64 (bitconvert (v4f64 VR256:$src))), (v4i64 VR256:$src)>;
+ def : Pat<(v4i64 (bitconvert (v32i8 VR256:$src))), (v4i64 VR256:$src)>;
+ def : Pat<(v4i64 (bitconvert (v16i16 VR256:$src))), (v4i64 VR256:$src)>;
+ def : Pat<(v32i8 (bitconvert (v4f64 VR256:$src))), (v32i8 VR256:$src)>;
+ def : Pat<(v32i8 (bitconvert (v4i64 VR256:$src))), (v32i8 VR256:$src)>;
+ def : Pat<(v32i8 (bitconvert (v8f32 VR256:$src))), (v32i8 VR256:$src)>;
+ def : Pat<(v32i8 (bitconvert (v8i32 VR256:$src))), (v32i8 VR256:$src)>;
+ def : Pat<(v32i8 (bitconvert (v16i16 VR256:$src))), (v32i8 VR256:$src)>;
+ def : Pat<(v8i32 (bitconvert (v32i8 VR256:$src))), (v8i32 VR256:$src)>;
+ def : Pat<(v8i32 (bitconvert (v16i16 VR256:$src))), (v8i32 VR256:$src)>;
+ def : Pat<(v8i32 (bitconvert (v8f32 VR256:$src))), (v8i32 VR256:$src)>;
+ def : Pat<(v8i32 (bitconvert (v4i64 VR256:$src))), (v8i32 VR256:$src)>;
+ def : Pat<(v8i32 (bitconvert (v4f64 VR256:$src))), (v8i32 VR256:$src)>;
+ def : Pat<(v16i16 (bitconvert (v8f32 VR256:$src))), (v16i16 VR256:$src)>;
+ def : Pat<(v16i16 (bitconvert (v8i32 VR256:$src))), (v16i16 VR256:$src)>;
+ def : Pat<(v16i16 (bitconvert (v4i64 VR256:$src))), (v16i16 VR256:$src)>;
+ def : Pat<(v16i16 (bitconvert (v4f64 VR256:$src))), (v16i16 VR256:$src)>;
+ def : Pat<(v16i16 (bitconvert (v32i8 VR256:$src))), (v16i16 VR256:$src)>;
+}
+
+// Alias instructions that map fld0 to pxor for sse.
+// FIXME: Set encoding to pseudo!
+let isReMaterializable = 1, isAsCheapAsAMove = 1, isCodeGenOnly = 1,
+ canFoldAsLoad = 1 in {
+ def FsFLD0SS : I<0xEF, MRMInitReg, (outs FR32:$dst), (ins), "",
+ [(set FR32:$dst, fp32imm0)]>,
+ Requires<[HasSSE1]>, TB, OpSize;
+ def FsFLD0SD : I<0xEF, MRMInitReg, (outs FR64:$dst), (ins), "",
+ [(set FR64:$dst, fpimm0)]>,
+ Requires<[HasSSE2]>, TB, OpSize;
+ def VFsFLD0SS : I<0xEF, MRMInitReg, (outs FR32:$dst), (ins), "",
+ [(set FR32:$dst, fp32imm0)]>,
+ Requires<[HasAVX]>, TB, OpSize, VEX_4V;
+ def VFsFLD0SD : I<0xEF, MRMInitReg, (outs FR64:$dst), (ins), "",
+ [(set FR64:$dst, fpimm0)]>,
+ Requires<[HasAVX]>, TB, OpSize, VEX_4V;
+}
+
+//===----------------------------------------------------------------------===//
+// AVX & SSE - Zero/One Vectors
+//===----------------------------------------------------------------------===//
+
+// Alias instruction that maps zero vector to pxor / xorp* for sse.
+// This is expanded by ExpandPostRAPseudos to an xorps / vxorps, and then
+// swizzled by ExecutionDepsFix to pxor.
+// We set canFoldAsLoad because this can be converted to a constant-pool
+// load of an all-zeros value if folding it would be beneficial.
+let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1,
+ isPseudo = 1, neverHasSideEffects = 1 in {
+def V_SET0 : I<0, Pseudo, (outs VR128:$dst), (ins), "", []>;
+}
+
+def : Pat<(v4f32 immAllZerosV), (V_SET0)>;
+def : Pat<(v2f64 immAllZerosV), (V_SET0)>;
+def : Pat<(v4i32 immAllZerosV), (V_SET0)>;
+def : Pat<(v2i64 immAllZerosV), (V_SET0)>;
+def : Pat<(v8i16 immAllZerosV), (V_SET0)>;
+def : Pat<(v16i8 immAllZerosV), (V_SET0)>;
+
+
+// The same as done above but for AVX. The 256-bit ISA does not support PI,
+// and doesn't need it because on sandy bridge the register is set to zero
+// at the rename stage without using any execution unit, so SET0PSY
+// and SET0PDY can be used for vector int instructions without penalty
+// FIXME: Change encoding to pseudo! This is blocked right now by the x86
+// JIT implementatioan, it does not expand the instructions below like
+// X86MCInstLower does.
+let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1,
+ isCodeGenOnly = 1, Predicates = [HasAVX] in {
+def AVX_SET0PSY : PSI<0x57, MRMInitReg, (outs VR256:$dst), (ins), "",
+ [(set VR256:$dst, (v8f32 immAllZerosV))]>, VEX_4V;
+def AVX_SET0PDY : PDI<0x57, MRMInitReg, (outs VR256:$dst), (ins), "",
+ [(set VR256:$dst, (v4f64 immAllZerosV))]>, VEX_4V;
+}
+
+
+// AVX has no support for 256-bit integer instructions, but since the 128-bit
+// VPXOR instruction writes zero to its upper part, it's safe build zeros.
+def : Pat<(v8i32 immAllZerosV), (SUBREG_TO_REG (i32 0), (V_SET0), sub_xmm)>;
+def : Pat<(bc_v8i32 (v8f32 immAllZerosV)),
+ (SUBREG_TO_REG (i32 0), (V_SET0), sub_xmm)>;
+
+def : Pat<(v4i64 immAllZerosV), (SUBREG_TO_REG (i64 0), (V_SET0), sub_xmm)>;
+def : Pat<(bc_v4i64 (v8f32 immAllZerosV)),
+ (SUBREG_TO_REG (i64 0), (V_SET0), sub_xmm)>;
+
+// We set canFoldAsLoad because this can be converted to a constant-pool
+// load of an all-ones value if folding it would be beneficial.
+// FIXME: Change encoding to pseudo! This is blocked right now by the x86
+// JIT implementation, it does not expand the instructions below like
+// X86MCInstLower does.
+let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1,
+ isCodeGenOnly = 1, ExeDomain = SSEPackedInt in
+ def V_SETALLONES : PDI<0x76, MRMInitReg, (outs VR128:$dst), (ins), "",
+ [(set VR128:$dst, (v4i32 immAllOnesV))]>;
+let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1,
+ isCodeGenOnly = 1, ExeDomain = SSEPackedInt, Predicates = [HasAVX] in
+ def AVX_SETALLONES : PDI<0x76, MRMInitReg, (outs VR128:$dst), (ins), "",
+ [(set VR128:$dst, (v4i32 immAllOnesV))]>, VEX_4V;
+
+
+//===----------------------------------------------------------------------===//
+// SSE 1 & 2 - Move FP Scalar Instructions
+//
+// Move Instructions. Register-to-register movss/movsd is not used for FR32/64
+// register copies because it's a partial register update; FsMOVAPSrr/FsMOVAPDrr
+// is used instead. Register-to-register movss/movsd is not modeled as an
+// INSERT_SUBREG because INSERT_SUBREG requires that the insert be implementable
+// in terms of a copy, and just mentioned, we don't use movss/movsd for copies.
//===----------------------------------------------------------------------===//
class sse12_move_rr<RegisterClass RC, ValueType vt, string asm> :
@@ -130,28 +340,57 @@ class sse12_move_rm<RegisterClass RC, X86MemOperand x86memop,
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
[(set RC:$dst, (mem_pat addr:$src))]>;
-// Move Instructions. Register-to-register movss/movsd is not used for FR32/64
-// register copies because it's a partial register update; FsMOVAPSrr/FsMOVAPDrr
-// is used instead. Register-to-register movss/movsd is not modeled as an
-// INSERT_SUBREG because INSERT_SUBREG requires that the insert be implementable
-// in terms of a copy, and just mentioned, we don't use movss/movsd for copies.
+// AVX
def VMOVSSrr : sse12_move_rr<FR32, v4f32,
- "movss\t{$src2, $src1, $dst|$dst, $src1, $src2}">, XS, VEX_4V;
+ "movss\t{$src2, $src1, $dst|$dst, $src1, $src2}">, XS, VEX_4V,
+ VEX_LIG;
def VMOVSDrr : sse12_move_rr<FR64, v2f64,
- "movsd\t{$src2, $src1, $dst|$dst, $src1, $src2}">, XD, VEX_4V;
+ "movsd\t{$src2, $src1, $dst|$dst, $src1, $src2}">, XD, VEX_4V,
+ VEX_LIG;
-let canFoldAsLoad = 1, isReMaterializable = 1 in {
- def VMOVSSrm : sse12_move_rm<FR32, f32mem, loadf32, "movss">, XS, VEX;
+// For the disassembler
+let isCodeGenOnly = 1 in {
+ def VMOVSSrr_REV : SI<0x11, MRMDestReg, (outs VR128:$dst),
+ (ins VR128:$src1, FR32:$src2),
+ "movss\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>,
+ XS, VEX_4V, VEX_LIG;
+ def VMOVSDrr_REV : SI<0x11, MRMDestReg, (outs VR128:$dst),
+ (ins VR128:$src1, FR64:$src2),
+ "movsd\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>,
+ XD, VEX_4V, VEX_LIG;
+}
+let canFoldAsLoad = 1, isReMaterializable = 1 in {
+ def VMOVSSrm : sse12_move_rm<FR32, f32mem, loadf32, "movss">, XS, VEX,
+ VEX_LIG;
let AddedComplexity = 20 in
- def VMOVSDrm : sse12_move_rm<FR64, f64mem, loadf64, "movsd">, XD, VEX;
+ def VMOVSDrm : sse12_move_rm<FR64, f64mem, loadf64, "movsd">, XD, VEX,
+ VEX_LIG;
}
+def VMOVSSmr : SI<0x11, MRMDestMem, (outs), (ins f32mem:$dst, FR32:$src),
+ "movss\t{$src, $dst|$dst, $src}",
+ [(store FR32:$src, addr:$dst)]>, XS, VEX, VEX_LIG;
+def VMOVSDmr : SI<0x11, MRMDestMem, (outs), (ins f64mem:$dst, FR64:$src),
+ "movsd\t{$src, $dst|$dst, $src}",
+ [(store FR64:$src, addr:$dst)]>, XD, VEX, VEX_LIG;
+
+// SSE1 & 2
let Constraints = "$src1 = $dst" in {
def MOVSSrr : sse12_move_rr<FR32, v4f32,
"movss\t{$src2, $dst|$dst, $src2}">, XS;
def MOVSDrr : sse12_move_rr<FR64, v2f64,
"movsd\t{$src2, $dst|$dst, $src2}">, XD;
+
+ // For the disassembler
+ let isCodeGenOnly = 1 in {
+ def MOVSSrr_REV : SI<0x11, MRMDestReg, (outs VR128:$dst),
+ (ins VR128:$src1, FR32:$src2),
+ "movss\t{$src2, $dst|$dst, $src2}", []>, XS;
+ def MOVSDrr_REV : SI<0x11, MRMDestReg, (outs VR128:$dst),
+ (ins VR128:$src1, FR64:$src2),
+ "movsd\t{$src2, $dst|$dst, $src2}", []>, XD;
+ }
}
let canFoldAsLoad = 1, isReMaterializable = 1 in {
@@ -161,54 +400,6 @@ let canFoldAsLoad = 1, isReMaterializable = 1 in {
def MOVSDrm : sse12_move_rm<FR64, f64mem, loadf64, "movsd">, XD;
}
-let AddedComplexity = 15 in {
-// Extract the low 32-bit value from one vector and insert it into another.
-def : Pat<(v4f32 (movl VR128:$src1, VR128:$src2)),
- (MOVSSrr (v4f32 VR128:$src1),
- (EXTRACT_SUBREG (v4f32 VR128:$src2), sub_ss))>;
-// Extract the low 64-bit value from one vector and insert it into another.
-def : Pat<(v2f64 (movl VR128:$src1, VR128:$src2)),
- (MOVSDrr (v2f64 VR128:$src1),
- (EXTRACT_SUBREG (v2f64 VR128:$src2), sub_sd))>;
-}
-
-// Implicitly promote a 32-bit scalar to a vector.
-def : Pat<(v4f32 (scalar_to_vector FR32:$src)),
- (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FR32:$src, sub_ss)>;
-// Implicitly promote a 64-bit scalar to a vector.
-def : Pat<(v2f64 (scalar_to_vector FR64:$src)),
- (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FR64:$src, sub_sd)>;
-// Implicitly promote a 32-bit scalar to a vector.
-def : Pat<(v8f32 (scalar_to_vector FR32:$src)),
- (INSERT_SUBREG (v8f32 (IMPLICIT_DEF)), FR32:$src, sub_ss)>;
-// Implicitly promote a 64-bit scalar to a vector.
-def : Pat<(v4f64 (scalar_to_vector FR64:$src)),
- (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), FR64:$src, sub_sd)>;
-
-let AddedComplexity = 20 in {
-// MOVSSrm zeros the high parts of the register; represent this
-// with SUBREG_TO_REG.
-def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))),
- (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>;
-def : Pat<(v4f32 (scalar_to_vector (loadf32 addr:$src))),
- (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>;
-def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))),
- (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>;
-// MOVSDrm zeros the high parts of the register; represent this
-// with SUBREG_TO_REG.
-def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))),
- (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>;
-def : Pat<(v2f64 (scalar_to_vector (loadf64 addr:$src))),
- (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>;
-def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))),
- (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>;
-def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))),
- (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>;
-def : Pat<(v2f64 (X86vzload addr:$src)),
- (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>;
-}
-
-// Store scalar value to memory.
def MOVSSmr : SSI<0x11, MRMDestMem, (outs), (ins f32mem:$dst, FR32:$src),
"movss\t{$src, $dst|$dst, $src}",
[(store FR32:$src, addr:$dst)]>;
@@ -216,24 +407,257 @@ def MOVSDmr : SDI<0x11, MRMDestMem, (outs), (ins f64mem:$dst, FR64:$src),
"movsd\t{$src, $dst|$dst, $src}",
[(store FR64:$src, addr:$dst)]>;
-def VMOVSSmr : SI<0x11, MRMDestMem, (outs), (ins f32mem:$dst, FR32:$src),
- "movss\t{$src, $dst|$dst, $src}",
- [(store FR32:$src, addr:$dst)]>, XS, VEX;
-def VMOVSDmr : SI<0x11, MRMDestMem, (outs), (ins f64mem:$dst, FR64:$src),
- "movsd\t{$src, $dst|$dst, $src}",
- [(store FR64:$src, addr:$dst)]>, XD, VEX;
+// Patterns
+let Predicates = [HasSSE1] in {
+ let AddedComplexity = 15 in {
+ // Extract the low 32-bit value from one vector and insert it into another.
+ def : Pat<(v4f32 (movl VR128:$src1, VR128:$src2)),
+ (MOVSSrr (v4f32 VR128:$src1),
+ (EXTRACT_SUBREG (v4f32 VR128:$src2), sub_ss))>;
+ def : Pat<(v4i32 (movl VR128:$src1, VR128:$src2)),
+ (MOVSSrr (v4i32 VR128:$src1),
+ (EXTRACT_SUBREG (v4i32 VR128:$src2), sub_ss))>;
+
+ // Move scalar to XMM zero-extended, zeroing a VR128 then do a
+ // MOVSS to the lower bits.
+ def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector FR32:$src)))),
+ (MOVSSrr (v4f32 (V_SET0)), FR32:$src)>;
+ def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))),
+ (MOVSSrr (v4f32 (V_SET0)),
+ (f32 (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss)))>;
+ def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))),
+ (MOVSSrr (v4i32 (V_SET0)),
+ (EXTRACT_SUBREG (v4i32 VR128:$src), sub_ss))>;
+ }
-// Extract and store.
-def : Pat<(store (f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))),
- addr:$dst),
- (MOVSSmr addr:$dst,
- (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss))>;
-def : Pat<(store (f64 (vector_extract (v2f64 VR128:$src), (iPTR 0))),
- addr:$dst),
- (MOVSDmr addr:$dst,
- (EXTRACT_SUBREG (v2f64 VR128:$src), sub_sd))>;
+ let AddedComplexity = 20 in {
+ // MOVSSrm zeros the high parts of the register; represent this
+ // with SUBREG_TO_REG.
+ def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))),
+ (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>;
+ def : Pat<(v4f32 (scalar_to_vector (loadf32 addr:$src))),
+ (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>;
+ def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))),
+ (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>;
+ }
+
+ // Extract and store.
+ def : Pat<(store (f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))),
+ addr:$dst),
+ (MOVSSmr addr:$dst,
+ (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss))>;
+
+ // Shuffle with MOVSS
+ def : Pat<(v4f32 (X86Movss VR128:$src1, (scalar_to_vector FR32:$src2))),
+ (MOVSSrr VR128:$src1, FR32:$src2)>;
+ def : Pat<(v4i32 (X86Movss VR128:$src1, VR128:$src2)),
+ (MOVSSrr (v4i32 VR128:$src1),
+ (EXTRACT_SUBREG (v4i32 VR128:$src2), sub_ss))>;
+ def : Pat<(v4f32 (X86Movss VR128:$src1, VR128:$src2)),
+ (MOVSSrr (v4f32 VR128:$src1),
+ (EXTRACT_SUBREG (v4f32 VR128:$src2), sub_ss))>;
+}
+
+let Predicates = [HasSSE2] in {
+ let AddedComplexity = 15 in {
+ // Extract the low 64-bit value from one vector and insert it into another.
+ def : Pat<(v2f64 (movl VR128:$src1, VR128:$src2)),
+ (MOVSDrr (v2f64 VR128:$src1),
+ (EXTRACT_SUBREG (v2f64 VR128:$src2), sub_sd))>;
+ def : Pat<(v2i64 (movl VR128:$src1, VR128:$src2)),
+ (MOVSDrr (v2i64 VR128:$src1),
+ (EXTRACT_SUBREG (v2i64 VR128:$src2), sub_sd))>;
+
+ // vector_shuffle v1, v2 <4, 5, 2, 3> using movsd
+ def : Pat<(v4f32 (movlp VR128:$src1, VR128:$src2)),
+ (MOVSDrr VR128:$src1, (EXTRACT_SUBREG VR128:$src2, sub_sd))>;
+ def : Pat<(v4i32 (movlp VR128:$src1, VR128:$src2)),
+ (MOVSDrr VR128:$src1, (EXTRACT_SUBREG VR128:$src2, sub_sd))>;
+
+ // Move scalar to XMM zero-extended, zeroing a VR128 then do a
+ // MOVSD to the lower bits.
+ def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector FR64:$src)))),
+ (MOVSDrr (v2f64 (V_SET0)), FR64:$src)>;
+ }
+
+ let AddedComplexity = 20 in {
+ // MOVSDrm zeros the high parts of the register; represent this
+ // with SUBREG_TO_REG.
+ def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))),
+ (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>;
+ def : Pat<(v2f64 (scalar_to_vector (loadf64 addr:$src))),
+ (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>;
+ def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))),
+ (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>;
+ def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))),
+ (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>;
+ def : Pat<(v2f64 (X86vzload addr:$src)),
+ (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>;
+ }
+
+ // Extract and store.
+ def : Pat<(store (f64 (vector_extract (v2f64 VR128:$src), (iPTR 0))),
+ addr:$dst),
+ (MOVSDmr addr:$dst,
+ (EXTRACT_SUBREG (v2f64 VR128:$src), sub_sd))>;
+
+ // Shuffle with MOVSD
+ def : Pat<(v2f64 (X86Movsd VR128:$src1, (scalar_to_vector FR64:$src2))),
+ (MOVSDrr VR128:$src1, FR64:$src2)>;
+ def : Pat<(v2i64 (X86Movsd VR128:$src1, VR128:$src2)),
+ (MOVSDrr (v2i64 VR128:$src1),
+ (EXTRACT_SUBREG (v2i64 VR128:$src2), sub_sd))>;
+ def : Pat<(v2f64 (X86Movsd VR128:$src1, VR128:$src2)),
+ (MOVSDrr (v2f64 VR128:$src1),
+ (EXTRACT_SUBREG (v2f64 VR128:$src2), sub_sd))>;
+ def : Pat<(v4f32 (X86Movsd VR128:$src1, VR128:$src2)),
+ (MOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4f32 VR128:$src2),sub_sd))>;
+ def : Pat<(v4i32 (X86Movsd VR128:$src1, VR128:$src2)),
+ (MOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4i32 VR128:$src2),sub_sd))>;
+
+ // FIXME: Instead of a X86Movlps there should be a X86Movsd here, the problem
+ // is during lowering, where it's not possible to recognize the fold cause
+ // it has two uses through a bitcast. One use disappears at isel time and the
+ // fold opportunity reappears.
+ def : Pat<(v4f32 (X86Movlps VR128:$src1, VR128:$src2)),
+ (MOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4f32 VR128:$src2),sub_sd))>;
+ def : Pat<(v4i32 (X86Movlps VR128:$src1, VR128:$src2)),
+ (MOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4i32 VR128:$src2),sub_sd))>;
+}
+
+let Predicates = [HasAVX] in {
+ let AddedComplexity = 15 in {
+ // Extract the low 32-bit value from one vector and insert it into another.
+ def : Pat<(v4f32 (movl VR128:$src1, VR128:$src2)),
+ (VMOVSSrr (v4f32 VR128:$src1),
+ (EXTRACT_SUBREG (v4f32 VR128:$src2), sub_ss))>;
+ def : Pat<(v4i32 (movl VR128:$src1, VR128:$src2)),
+ (VMOVSSrr (v4i32 VR128:$src1),
+ (EXTRACT_SUBREG (v4i32 VR128:$src2), sub_ss))>;
+
+ // Extract the low 64-bit value from one vector and insert it into another.
+ def : Pat<(v2f64 (movl VR128:$src1, VR128:$src2)),
+ (VMOVSDrr (v2f64 VR128:$src1),
+ (EXTRACT_SUBREG (v2f64 VR128:$src2), sub_sd))>;
+ def : Pat<(v2i64 (movl VR128:$src1, VR128:$src2)),
+ (VMOVSDrr (v2i64 VR128:$src1),
+ (EXTRACT_SUBREG (v2i64 VR128:$src2), sub_sd))>;
+
+ // vector_shuffle v1, v2 <4, 5, 2, 3> using movsd
+ def : Pat<(v4f32 (movlp VR128:$src1, VR128:$src2)),
+ (VMOVSDrr VR128:$src1, (EXTRACT_SUBREG VR128:$src2, sub_sd))>;
+ def : Pat<(v4i32 (movlp VR128:$src1, VR128:$src2)),
+ (VMOVSDrr VR128:$src1, (EXTRACT_SUBREG VR128:$src2, sub_sd))>;
+
+ // Move scalar to XMM zero-extended, zeroing a VR128 then do a
+ // MOVS{S,D} to the lower bits.
+ def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector FR32:$src)))),
+ (VMOVSSrr (v4f32 (V_SET0)), FR32:$src)>;
+ def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))),
+ (VMOVSSrr (v4f32 (V_SET0)),
+ (f32 (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss)))>;
+ def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))),
+ (VMOVSSrr (v4i32 (V_SET0)),
+ (EXTRACT_SUBREG (v4i32 VR128:$src), sub_ss))>;
+ def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector FR64:$src)))),
+ (VMOVSDrr (v2f64 (V_SET0)), FR64:$src)>;
+ }
+
+ let AddedComplexity = 20 in {
+ // MOVSSrm zeros the high parts of the register; represent this
+ // with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0
+ def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))),
+ (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_ss)>;
+ def : Pat<(v4f32 (scalar_to_vector (loadf32 addr:$src))),
+ (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_ss)>;
+ def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))),
+ (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_ss)>;
+
+ // MOVSDrm zeros the high parts of the register; represent this
+ // with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0
+ def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))),
+ (SUBREG_TO_REG (i64 0), (VMOVSDrm addr:$src), sub_sd)>;
+ def : Pat<(v2f64 (scalar_to_vector (loadf64 addr:$src))),
+ (SUBREG_TO_REG (i64 0), (VMOVSDrm addr:$src), sub_sd)>;
+ def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))),
+ (SUBREG_TO_REG (i64 0), (VMOVSDrm addr:$src), sub_sd)>;
+ def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))),
+ (SUBREG_TO_REG (i64 0), (VMOVSDrm addr:$src), sub_sd)>;
+ def : Pat<(v2f64 (X86vzload addr:$src)),
+ (SUBREG_TO_REG (i64 0), (VMOVSDrm addr:$src), sub_sd)>;
+
+ // Represent the same patterns above but in the form they appear for
+ // 256-bit types
+ def : Pat<(v8f32 (X86vzmovl (insert_subvector undef,
+ (v4f32 (scalar_to_vector (loadf32 addr:$src))), (i32 0)))),
+ (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_ss)>;
+ def : Pat<(v4f64 (X86vzmovl (insert_subvector undef,
+ (v2f64 (scalar_to_vector (loadf64 addr:$src))), (i32 0)))),
+ (SUBREG_TO_REG (i32 0), (VMOVSDrm addr:$src), sub_sd)>;
+ }
+ def : Pat<(v8f32 (X86vzmovl (insert_subvector undef,
+ (v4f32 (scalar_to_vector FR32:$src)), (i32 0)))),
+ (SUBREG_TO_REG (i32 0),
+ (v4f32 (VMOVSSrr (v4f32 (V_SET0)), FR32:$src)),
+ sub_xmm)>;
+ def : Pat<(v4f64 (X86vzmovl (insert_subvector undef,
+ (v2f64 (scalar_to_vector FR64:$src)), (i32 0)))),
+ (SUBREG_TO_REG (i64 0),
+ (v2f64 (VMOVSDrr (v2f64 (V_SET0)), FR64:$src)),
+ sub_xmm)>;
+
+ // Extract and store.
+ def : Pat<(store (f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))),
+ addr:$dst),
+ (VMOVSSmr addr:$dst,
+ (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss))>;
+ def : Pat<(store (f64 (vector_extract (v2f64 VR128:$src), (iPTR 0))),
+ addr:$dst),
+ (VMOVSDmr addr:$dst,
+ (EXTRACT_SUBREG (v2f64 VR128:$src), sub_sd))>;
+
+ // Shuffle with VMOVSS
+ def : Pat<(v4f32 (X86Movss VR128:$src1, (scalar_to_vector FR32:$src2))),
+ (VMOVSSrr VR128:$src1, FR32:$src2)>;
+ def : Pat<(v4i32 (X86Movss VR128:$src1, VR128:$src2)),
+ (VMOVSSrr (v4i32 VR128:$src1),
+ (EXTRACT_SUBREG (v4i32 VR128:$src2), sub_ss))>;
+ def : Pat<(v4f32 (X86Movss VR128:$src1, VR128:$src2)),
+ (VMOVSSrr (v4f32 VR128:$src1),
+ (EXTRACT_SUBREG (v4f32 VR128:$src2), sub_ss))>;
+
+ // Shuffle with VMOVSD
+ def : Pat<(v2f64 (X86Movsd VR128:$src1, (scalar_to_vector FR64:$src2))),
+ (VMOVSDrr VR128:$src1, FR64:$src2)>;
+ def : Pat<(v2i64 (X86Movsd VR128:$src1, VR128:$src2)),
+ (VMOVSDrr (v2i64 VR128:$src1),
+ (EXTRACT_SUBREG (v2i64 VR128:$src2), sub_sd))>;
+ def : Pat<(v2f64 (X86Movsd VR128:$src1, VR128:$src2)),
+ (VMOVSDrr (v2f64 VR128:$src1),
+ (EXTRACT_SUBREG (v2f64 VR128:$src2), sub_sd))>;
+ def : Pat<(v4f32 (X86Movsd VR128:$src1, VR128:$src2)),
+ (VMOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4f32 VR128:$src2),
+ sub_sd))>;
+ def : Pat<(v4i32 (X86Movsd VR128:$src1, VR128:$src2)),
+ (VMOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4i32 VR128:$src2),
+ sub_sd))>;
+
+ // FIXME: Instead of a X86Movlps there should be a X86Movsd here, the problem
+ // is during lowering, where it's not possible to recognize the fold cause
+ // it has two uses through a bitcast. One use disappears at isel time and the
+ // fold opportunity reappears.
+ def : Pat<(v4f32 (X86Movlps VR128:$src1, VR128:$src2)),
+ (VMOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4f32 VR128:$src2),
+ sub_sd))>;
+ def : Pat<(v4i32 (X86Movlps VR128:$src1, VR128:$src2)),
+ (VMOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4i32 VR128:$src2),
+ sub_sd))>;
+}
+
+//===----------------------------------------------------------------------===//
+// SSE 1 & 2 - Move Aligned/Unaligned FP Instructions
+//===----------------------------------------------------------------------===//
-// Move Aligned/Unaligned floating point values
multiclass sse12_mov_packed<bits<8> opc, RegisterClass RC,
X86MemOperand x86memop, PatFrag ld_frag,
string asm, Domain d,
@@ -248,22 +672,22 @@ let canFoldAsLoad = 1, isReMaterializable = IsReMaterializable in
}
defm VMOVAPS : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv4f32,
- "movaps", SSEPackedSingle>, VEX;
+ "movaps", SSEPackedSingle>, TB, VEX;
defm VMOVAPD : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv2f64,
- "movapd", SSEPackedDouble>, OpSize, VEX;
+ "movapd", SSEPackedDouble>, TB, OpSize, VEX;
defm VMOVUPS : sse12_mov_packed<0x10, VR128, f128mem, loadv4f32,
- "movups", SSEPackedSingle>, VEX;
+ "movups", SSEPackedSingle>, TB, VEX;
defm VMOVUPD : sse12_mov_packed<0x10, VR128, f128mem, loadv2f64,
- "movupd", SSEPackedDouble, 0>, OpSize, VEX;
+ "movupd", SSEPackedDouble, 0>, TB, OpSize, VEX;
defm VMOVAPSY : sse12_mov_packed<0x28, VR256, f256mem, alignedloadv8f32,
- "movaps", SSEPackedSingle>, VEX;
+ "movaps", SSEPackedSingle>, TB, VEX;
defm VMOVAPDY : sse12_mov_packed<0x28, VR256, f256mem, alignedloadv4f64,
- "movapd", SSEPackedDouble>, OpSize, VEX;
+ "movapd", SSEPackedDouble>, TB, OpSize, VEX;
defm VMOVUPSY : sse12_mov_packed<0x10, VR256, f256mem, loadv8f32,
- "movups", SSEPackedSingle>, VEX;
+ "movups", SSEPackedSingle>, TB, VEX;
defm VMOVUPDY : sse12_mov_packed<0x10, VR256, f256mem, loadv4f64,
- "movupd", SSEPackedDouble, 0>, OpSize, VEX;
+ "movupd", SSEPackedDouble, 0>, TB, OpSize, VEX;
defm MOVAPS : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv4f32,
"movaps", SSEPackedSingle>, TB;
defm MOVAPD : sse12_mov_packed<0x28, VR128, f128mem, alignedloadv2f64,
@@ -287,10 +711,10 @@ def VMOVUPDmr : VPDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src),
[(store (v2f64 VR128:$src), addr:$dst)]>, VEX;
def VMOVAPSYmr : VPSI<0x29, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src),
"movaps\t{$src, $dst|$dst, $src}",
- [(alignedstore (v8f32 VR256:$src), addr:$dst)]>, VEX;
+ [(alignedstore256 (v8f32 VR256:$src), addr:$dst)]>, VEX;
def VMOVAPDYmr : VPDI<0x29, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src),
"movapd\t{$src, $dst|$dst, $src}",
- [(alignedstore (v4f64 VR256:$src), addr:$dst)]>, VEX;
+ [(alignedstore256 (v4f64 VR256:$src), addr:$dst)]>, VEX;
def VMOVUPSYmr : VPSI<0x11, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src),
"movups\t{$src, $dst|$dst, $src}",
[(store (v8f32 VR256:$src), addr:$dst)]>, VEX;
@@ -298,6 +722,34 @@ def VMOVUPDYmr : VPDI<0x11, MRMDestMem, (outs), (ins f256mem:$dst, VR256:$src),
"movupd\t{$src, $dst|$dst, $src}",
[(store (v4f64 VR256:$src), addr:$dst)]>, VEX;
+// For disassembler
+let isCodeGenOnly = 1 in {
+ def VMOVAPSrr_REV : VPSI<0x29, MRMDestReg, (outs VR128:$dst),
+ (ins VR128:$src),
+ "movaps\t{$src, $dst|$dst, $src}", []>, VEX;
+ def VMOVAPDrr_REV : VPDI<0x29, MRMDestReg, (outs VR128:$dst),
+ (ins VR128:$src),
+ "movapd\t{$src, $dst|$dst, $src}", []>, VEX;
+ def VMOVUPSrr_REV : VPSI<0x11, MRMDestReg, (outs VR128:$dst),
+ (ins VR128:$src),
+ "movups\t{$src, $dst|$dst, $src}", []>, VEX;
+ def VMOVUPDrr_REV : VPDI<0x11, MRMDestReg, (outs VR128:$dst),
+ (ins VR128:$src),
+ "movupd\t{$src, $dst|$dst, $src}", []>, VEX;
+ def VMOVAPSYrr_REV : VPSI<0x29, MRMDestReg, (outs VR256:$dst),
+ (ins VR256:$src),
+ "movaps\t{$src, $dst|$dst, $src}", []>, VEX;
+ def VMOVAPDYrr_REV : VPDI<0x29, MRMDestReg, (outs VR256:$dst),
+ (ins VR256:$src),
+ "movapd\t{$src, $dst|$dst, $src}", []>, VEX;
+ def VMOVUPSYrr_REV : VPSI<0x11, MRMDestReg, (outs VR256:$dst),
+ (ins VR256:$src),
+ "movups\t{$src, $dst|$dst, $src}", []>, VEX;
+ def VMOVUPDYrr_REV : VPDI<0x11, MRMDestReg, (outs VR256:$dst),
+ (ins VR256:$src),
+ "movupd\t{$src, $dst|$dst, $src}", []>, VEX;
+}
+
def : Pat<(int_x86_avx_loadu_ps_256 addr:$src), (VMOVUPSYrm addr:$src)>;
def : Pat<(int_x86_avx_storeu_ps_256 addr:$dst, VR256:$src),
(VMOVUPSYmr addr:$dst, VR256:$src)>;
@@ -319,24 +771,155 @@ def MOVUPDmr : PDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src),
"movupd\t{$src, $dst|$dst, $src}",
[(store (v2f64 VR128:$src), addr:$dst)]>;
-// Intrinsic forms of MOVUPS/D load and store
-def VMOVUPSmr_Int : VPSI<0x11, MRMDestMem, (outs),
- (ins f128mem:$dst, VR128:$src),
- "movups\t{$src, $dst|$dst, $src}",
- [(int_x86_sse_storeu_ps addr:$dst, VR128:$src)]>, VEX;
-def VMOVUPDmr_Int : VPDI<0x11, MRMDestMem, (outs),
- (ins f128mem:$dst, VR128:$src),
- "movupd\t{$src, $dst|$dst, $src}",
- [(int_x86_sse2_storeu_pd addr:$dst, VR128:$src)]>, VEX;
-
-def MOVUPSmr_Int : PSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src),
- "movups\t{$src, $dst|$dst, $src}",
- [(int_x86_sse_storeu_ps addr:$dst, VR128:$src)]>;
-def MOVUPDmr_Int : PDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src),
- "movupd\t{$src, $dst|$dst, $src}",
- [(int_x86_sse2_storeu_pd addr:$dst, VR128:$src)]>;
-
-// Move Low/High packed floating point values
+// For disassembler
+let isCodeGenOnly = 1 in {
+ def MOVAPSrr_REV : PSI<0x29, MRMDestReg, (outs VR128:$dst), (ins VR128:$src),
+ "movaps\t{$src, $dst|$dst, $src}", []>;
+ def MOVAPDrr_REV : PDI<0x29, MRMDestReg, (outs VR128:$dst), (ins VR128:$src),
+ "movapd\t{$src, $dst|$dst, $src}", []>;
+ def MOVUPSrr_REV : PSI<0x11, MRMDestReg, (outs VR128:$dst), (ins VR128:$src),
+ "movups\t{$src, $dst|$dst, $src}", []>;
+ def MOVUPDrr_REV : PDI<0x11, MRMDestReg, (outs VR128:$dst), (ins VR128:$src),
+ "movupd\t{$src, $dst|$dst, $src}", []>;
+}
+
+let Predicates = [HasAVX] in {
+ def : Pat<(int_x86_sse_storeu_ps addr:$dst, VR128:$src),
+ (VMOVUPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(int_x86_sse2_storeu_pd addr:$dst, VR128:$src),
+ (VMOVUPDmr addr:$dst, VR128:$src)>;
+}
+
+let Predicates = [HasSSE1] in
+ def : Pat<(int_x86_sse_storeu_ps addr:$dst, VR128:$src),
+ (MOVUPSmr addr:$dst, VR128:$src)>;
+let Predicates = [HasSSE2] in
+ def : Pat<(int_x86_sse2_storeu_pd addr:$dst, VR128:$src),
+ (MOVUPDmr addr:$dst, VR128:$src)>;
+
+// Use movaps / movups for SSE integer load / store (one byte shorter).
+// The instructions selected below are then converted to MOVDQA/MOVDQU
+// during the SSE domain pass.
+let Predicates = [HasSSE1] in {
+ def : Pat<(alignedloadv4i32 addr:$src),
+ (MOVAPSrm addr:$src)>;
+ def : Pat<(loadv4i32 addr:$src),
+ (MOVUPSrm addr:$src)>;
+ def : Pat<(alignedloadv2i64 addr:$src),
+ (MOVAPSrm addr:$src)>;
+ def : Pat<(loadv2i64 addr:$src),
+ (MOVUPSrm addr:$src)>;
+
+ def : Pat<(alignedstore (v2i64 VR128:$src), addr:$dst),
+ (MOVAPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(alignedstore (v4i32 VR128:$src), addr:$dst),
+ (MOVAPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(alignedstore (v8i16 VR128:$src), addr:$dst),
+ (MOVAPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(alignedstore (v16i8 VR128:$src), addr:$dst),
+ (MOVAPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(store (v2i64 VR128:$src), addr:$dst),
+ (MOVUPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(store (v4i32 VR128:$src), addr:$dst),
+ (MOVUPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(store (v8i16 VR128:$src), addr:$dst),
+ (MOVUPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(store (v16i8 VR128:$src), addr:$dst),
+ (MOVUPSmr addr:$dst, VR128:$src)>;
+}
+
+// Use vmovaps/vmovups for AVX integer load/store.
+let Predicates = [HasAVX] in {
+ // 128-bit load/store
+ def : Pat<(alignedloadv4i32 addr:$src),
+ (VMOVAPSrm addr:$src)>;
+ def : Pat<(loadv4i32 addr:$src),
+ (VMOVUPSrm addr:$src)>;
+ def : Pat<(alignedloadv2i64 addr:$src),
+ (VMOVAPSrm addr:$src)>;
+ def : Pat<(loadv2i64 addr:$src),
+ (VMOVUPSrm addr:$src)>;
+
+ def : Pat<(alignedstore (v2i64 VR128:$src), addr:$dst),
+ (VMOVAPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(alignedstore (v4i32 VR128:$src), addr:$dst),
+ (VMOVAPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(alignedstore (v8i16 VR128:$src), addr:$dst),
+ (VMOVAPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(alignedstore (v16i8 VR128:$src), addr:$dst),
+ (VMOVAPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(store (v2i64 VR128:$src), addr:$dst),
+ (VMOVUPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(store (v4i32 VR128:$src), addr:$dst),
+ (VMOVUPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(store (v8i16 VR128:$src), addr:$dst),
+ (VMOVUPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(store (v16i8 VR128:$src), addr:$dst),
+ (VMOVUPSmr addr:$dst, VR128:$src)>;
+
+ // 256-bit load/store
+ def : Pat<(alignedloadv4i64 addr:$src),
+ (VMOVAPSYrm addr:$src)>;
+ def : Pat<(loadv4i64 addr:$src),
+ (VMOVUPSYrm addr:$src)>;
+ def : Pat<(alignedloadv8i32 addr:$src),
+ (VMOVAPSYrm addr:$src)>;
+ def : Pat<(loadv8i32 addr:$src),
+ (VMOVUPSYrm addr:$src)>;
+ def : Pat<(alignedstore256 (v4i64 VR256:$src), addr:$dst),
+ (VMOVAPSYmr addr:$dst, VR256:$src)>;
+ def : Pat<(alignedstore256 (v8i32 VR256:$src), addr:$dst),
+ (VMOVAPSYmr addr:$dst, VR256:$src)>;
+ def : Pat<(alignedstore256 (v16i16 VR256:$src), addr:$dst),
+ (VMOVAPSYmr addr:$dst, VR256:$src)>;
+ def : Pat<(alignedstore256 (v32i8 VR256:$src), addr:$dst),
+ (VMOVAPSYmr addr:$dst, VR256:$src)>;
+ def : Pat<(store (v4i64 VR256:$src), addr:$dst),
+ (VMOVUPSYmr addr:$dst, VR256:$src)>;
+ def : Pat<(store (v8i32 VR256:$src), addr:$dst),
+ (VMOVUPSYmr addr:$dst, VR256:$src)>;
+ def : Pat<(store (v16i16 VR256:$src), addr:$dst),
+ (VMOVUPSYmr addr:$dst, VR256:$src)>;
+ def : Pat<(store (v32i8 VR256:$src), addr:$dst),
+ (VMOVUPSYmr addr:$dst, VR256:$src)>;
+}
+
+// Alias instruction to do FR32 or FR64 reg-to-reg copy using movaps. Upper
+// bits are disregarded. FIXME: Set encoding to pseudo!
+let neverHasSideEffects = 1 in {
+def FsMOVAPSrr : PSI<0x28, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src),
+ "movaps\t{$src, $dst|$dst, $src}", []>;
+def FsMOVAPDrr : PDI<0x28, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src),
+ "movapd\t{$src, $dst|$dst, $src}", []>;
+def FsVMOVAPSrr : VPSI<0x28, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src),
+ "movaps\t{$src, $dst|$dst, $src}", []>, VEX;
+def FsVMOVAPDrr : VPDI<0x28, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src),
+ "movapd\t{$src, $dst|$dst, $src}", []>, VEX;
+}
+
+// Alias instruction to load FR32 or FR64 from f128mem using movaps. Upper
+// bits are disregarded. FIXME: Set encoding to pseudo!
+let canFoldAsLoad = 1, isReMaterializable = 1 in {
+def FsMOVAPSrm : PSI<0x28, MRMSrcMem, (outs FR32:$dst), (ins f128mem:$src),
+ "movaps\t{$src, $dst|$dst, $src}",
+ [(set FR32:$dst, (alignedloadfsf32 addr:$src))]>;
+def FsMOVAPDrm : PDI<0x28, MRMSrcMem, (outs FR64:$dst), (ins f128mem:$src),
+ "movapd\t{$src, $dst|$dst, $src}",
+ [(set FR64:$dst, (alignedloadfsf64 addr:$src))]>;
+let isCodeGenOnly = 1 in {
+ def FsVMOVAPSrm : VPSI<0x28, MRMSrcMem, (outs FR32:$dst), (ins f128mem:$src),
+ "movaps\t{$src, $dst|$dst, $src}",
+ [(set FR32:$dst, (alignedloadfsf32 addr:$src))]>, VEX;
+ def FsVMOVAPDrm : VPDI<0x28, MRMSrcMem, (outs FR64:$dst), (ins f128mem:$src),
+ "movapd\t{$src, $dst|$dst, $src}",
+ [(set FR64:$dst, (alignedloadfsf64 addr:$src))]>, VEX;
+}
+}
+
+//===----------------------------------------------------------------------===//
+// SSE 1 & 2 - Move Low packed FP Instructions
+//===----------------------------------------------------------------------===//
+
multiclass sse12_mov_hilo_packed<bits<8>opc, RegisterClass RC,
PatFrag mov_frag, string base_opc,
string asm_opr> {
@@ -359,14 +942,10 @@ multiclass sse12_mov_hilo_packed<bits<8>opc, RegisterClass RC,
let AddedComplexity = 20 in {
defm VMOVL : sse12_mov_hilo_packed<0x12, VR128, movlp, "movlp",
"\t{$src2, $src1, $dst|$dst, $src1, $src2}">, VEX_4V;
- defm VMOVH : sse12_mov_hilo_packed<0x16, VR128, movlhps, "movhp",
- "\t{$src2, $src1, $dst|$dst, $src1, $src2}">, VEX_4V;
}
let Constraints = "$src1 = $dst", AddedComplexity = 20 in {
defm MOVL : sse12_mov_hilo_packed<0x12, VR128, movlp, "movlp",
"\t{$src2, $dst|$dst, $src2}">;
- defm MOVH : sse12_mov_hilo_packed<0x16, VR128, movlhps, "movhp",
- "\t{$src2, $dst|$dst, $src2}">;
}
def VMOVLPSmr : VPSI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src),
@@ -386,6 +965,147 @@ def MOVLPDmr : PDI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src),
[(store (f64 (vector_extract (v2f64 VR128:$src),
(iPTR 0))), addr:$dst)]>;
+let Predicates = [HasAVX] in {
+ let AddedComplexity = 20 in {
+ // vector_shuffle v1, (load v2) <4, 5, 2, 3> using MOVLPS
+ def : Pat<(v4f32 (movlp VR128:$src1, (load addr:$src2))),
+ (VMOVLPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4i32 (movlp VR128:$src1, (load addr:$src2))),
+ (VMOVLPSrm VR128:$src1, addr:$src2)>;
+ // vector_shuffle v1, (load v2) <2, 1> using MOVLPS
+ def : Pat<(v2f64 (movlp VR128:$src1, (load addr:$src2))),
+ (VMOVLPDrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2i64 (movlp VR128:$src1, (load addr:$src2))),
+ (VMOVLPDrm VR128:$src1, addr:$src2)>;
+ }
+
+ // (store (vector_shuffle (load addr), v2, <4, 5, 2, 3>), addr) using MOVLPS
+ def : Pat<(store (v4f32 (movlp (load addr:$src1), VR128:$src2)), addr:$src1),
+ (VMOVLPSmr addr:$src1, VR128:$src2)>;
+ def : Pat<(store (v4i32 (movlp (bc_v4i32 (loadv2i64 addr:$src1)),
+ VR128:$src2)), addr:$src1),
+ (VMOVLPSmr addr:$src1, VR128:$src2)>;
+
+ // (store (vector_shuffle (load addr), v2, <2, 1>), addr) using MOVLPS
+ def : Pat<(store (v2f64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1),
+ (VMOVLPDmr addr:$src1, VR128:$src2)>;
+ def : Pat<(store (v2i64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1),
+ (VMOVLPDmr addr:$src1, VR128:$src2)>;
+
+ // Shuffle with VMOVLPS
+ def : Pat<(v4f32 (X86Movlps VR128:$src1, (load addr:$src2))),
+ (VMOVLPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4i32 (X86Movlps VR128:$src1, (load addr:$src2))),
+ (VMOVLPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(X86Movlps VR128:$src1,
+ (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))),
+ (VMOVLPSrm VR128:$src1, addr:$src2)>;
+
+ // Shuffle with VMOVLPD
+ def : Pat<(v2f64 (X86Movlpd VR128:$src1, (load addr:$src2))),
+ (VMOVLPDrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2i64 (X86Movlpd VR128:$src1, (load addr:$src2))),
+ (VMOVLPDrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2f64 (X86Movlpd VR128:$src1,
+ (scalar_to_vector (loadf64 addr:$src2)))),
+ (VMOVLPDrm VR128:$src1, addr:$src2)>;
+
+ // Store patterns
+ def : Pat<(store (v4f32 (X86Movlps (load addr:$src1), VR128:$src2)),
+ addr:$src1),
+ (VMOVLPSmr addr:$src1, VR128:$src2)>;
+ def : Pat<(store (v4i32 (X86Movlps
+ (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2)), addr:$src1),
+ (VMOVLPSmr addr:$src1, VR128:$src2)>;
+ def : Pat<(store (v2f64 (X86Movlpd (load addr:$src1), VR128:$src2)),
+ addr:$src1),
+ (VMOVLPDmr addr:$src1, VR128:$src2)>;
+ def : Pat<(store (v2i64 (X86Movlpd (load addr:$src1), VR128:$src2)),
+ addr:$src1),
+ (VMOVLPDmr addr:$src1, VR128:$src2)>;
+}
+
+let Predicates = [HasSSE1] in {
+ let AddedComplexity = 20 in {
+ // vector_shuffle v1, (load v2) <4, 5, 2, 3> using MOVLPS
+ def : Pat<(v4f32 (movlp VR128:$src1, (load addr:$src2))),
+ (MOVLPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4i32 (movlp VR128:$src1, (load addr:$src2))),
+ (MOVLPSrm VR128:$src1, addr:$src2)>;
+ }
+
+ // (store (vector_shuffle (load addr), v2, <4, 5, 2, 3>), addr) using MOVLPS
+ def : Pat<(store (v4f32 (movlp (load addr:$src1), VR128:$src2)), addr:$src1),
+ (MOVLPSmr addr:$src1, VR128:$src2)>;
+ def : Pat<(store (v4i32 (movlp (bc_v4i32 (loadv2i64 addr:$src1)),
+ VR128:$src2)), addr:$src1),
+ (MOVLPSmr addr:$src1, VR128:$src2)>;
+
+ // Shuffle with MOVLPS
+ def : Pat<(v4f32 (X86Movlps VR128:$src1, (load addr:$src2))),
+ (MOVLPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4i32 (X86Movlps VR128:$src1, (load addr:$src2))),
+ (MOVLPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(X86Movlps VR128:$src1,
+ (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))),
+ (MOVLPSrm VR128:$src1, addr:$src2)>;
+
+ // Store patterns
+ def : Pat<(store (v4f32 (X86Movlps (load addr:$src1), VR128:$src2)),
+ addr:$src1),
+ (MOVLPSmr addr:$src1, VR128:$src2)>;
+ def : Pat<(store (v4i32 (X86Movlps
+ (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2)),
+ addr:$src1),
+ (MOVLPSmr addr:$src1, VR128:$src2)>;
+}
+
+let Predicates = [HasSSE2] in {
+ let AddedComplexity = 20 in {
+ // vector_shuffle v1, (load v2) <2, 1> using MOVLPS
+ def : Pat<(v2f64 (movlp VR128:$src1, (load addr:$src2))),
+ (MOVLPDrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2i64 (movlp VR128:$src1, (load addr:$src2))),
+ (MOVLPDrm VR128:$src1, addr:$src2)>;
+ }
+
+ // (store (vector_shuffle (load addr), v2, <2, 1>), addr) using MOVLPS
+ def : Pat<(store (v2f64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1),
+ (MOVLPDmr addr:$src1, VR128:$src2)>;
+ def : Pat<(store (v2i64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1),
+ (MOVLPDmr addr:$src1, VR128:$src2)>;
+
+ // Shuffle with MOVLPD
+ def : Pat<(v2f64 (X86Movlpd VR128:$src1, (load addr:$src2))),
+ (MOVLPDrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2i64 (X86Movlpd VR128:$src1, (load addr:$src2))),
+ (MOVLPDrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2f64 (X86Movlpd VR128:$src1,
+ (scalar_to_vector (loadf64 addr:$src2)))),
+ (MOVLPDrm VR128:$src1, addr:$src2)>;
+
+ // Store patterns
+ def : Pat<(store (v2f64 (X86Movlpd (load addr:$src1), VR128:$src2)),
+ addr:$src1),
+ (MOVLPDmr addr:$src1, VR128:$src2)>;
+ def : Pat<(store (v2i64 (X86Movlpd (load addr:$src1), VR128:$src2)),
+ addr:$src1),
+ (MOVLPDmr addr:$src1, VR128:$src2)>;
+}
+
+//===----------------------------------------------------------------------===//
+// SSE 1 & 2 - Move Hi packed FP Instructions
+//===----------------------------------------------------------------------===//
+
+let AddedComplexity = 20 in {
+ defm VMOVH : sse12_mov_hilo_packed<0x16, VR128, movlhps, "movhp",
+ "\t{$src2, $src1, $dst|$dst, $src1, $src2}">, VEX_4V;
+}
+let Constraints = "$src1 = $dst", AddedComplexity = 20 in {
+ defm MOVH : sse12_mov_hilo_packed<0x16, VR128, movlhps, "movhp",
+ "\t{$src2, $dst|$dst, $src2}">;
+}
+
// v2f64 extract element 1 is always custom lowered to unpack high to low
// and extract element 0 so the non-store version isn't too horrible.
def VMOVHPSmr : VPSI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src),
@@ -411,6 +1131,80 @@ def MOVHPDmr : PDI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src),
(v2f64 (unpckh VR128:$src, (undef))),
(iPTR 0))), addr:$dst)]>;
+let Predicates = [HasAVX] in {
+ // VMOVHPS patterns
+ def : Pat<(movlhps VR128:$src1, (bc_v4i32 (v2i64 (X86vzload addr:$src2)))),
+ (VMOVHPSrm (v4i32 VR128:$src1), addr:$src2)>;
+ def : Pat<(X86Movlhps VR128:$src1,
+ (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))),
+ (VMOVHPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(X86Movlhps VR128:$src1,
+ (bc_v4i32 (v2i64 (X86vzload addr:$src2)))),
+ (VMOVHPSrm VR128:$src1, addr:$src2)>;
+
+ // FIXME: Instead of X86Unpcklpd, there should be a X86Movlhpd here, the problem
+ // is during lowering, where it's not possible to recognize the load fold cause
+ // it has two uses through a bitcast. One use disappears at isel time and the
+ // fold opportunity reappears.
+ def : Pat<(v2f64 (X86Unpcklpd VR128:$src1,
+ (scalar_to_vector (loadf64 addr:$src2)))),
+ (VMOVHPDrm VR128:$src1, addr:$src2)>;
+
+ // FIXME: This should be matched by a X86Movhpd instead. Same as above
+ def : Pat<(v2f64 (X86Movlhpd VR128:$src1,
+ (scalar_to_vector (loadf64 addr:$src2)))),
+ (VMOVHPDrm VR128:$src1, addr:$src2)>;
+
+ // Store patterns
+ def : Pat<(store (f64 (vector_extract
+ (v2f64 (X86Unpckhps VR128:$src, (undef))), (iPTR 0))), addr:$dst),
+ (VMOVHPSmr addr:$dst, VR128:$src)>;
+ def : Pat<(store (f64 (vector_extract
+ (v2f64 (X86Unpckhpd VR128:$src, (undef))), (iPTR 0))), addr:$dst),
+ (VMOVHPDmr addr:$dst, VR128:$src)>;
+}
+
+let Predicates = [HasSSE1] in {
+ // MOVHPS patterns
+ def : Pat<(movlhps VR128:$src1, (bc_v4i32 (v2i64 (X86vzload addr:$src2)))),
+ (MOVHPSrm (v4i32 VR128:$src1), addr:$src2)>;
+ def : Pat<(X86Movlhps VR128:$src1,
+ (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))),
+ (MOVHPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(X86Movlhps VR128:$src1,
+ (bc_v4f32 (v2i64 (X86vzload addr:$src2)))),
+ (MOVHPSrm VR128:$src1, addr:$src2)>;
+
+ // Store patterns
+ def : Pat<(store (f64 (vector_extract
+ (v2f64 (X86Unpckhps VR128:$src, (undef))), (iPTR 0))), addr:$dst),
+ (MOVHPSmr addr:$dst, VR128:$src)>;
+}
+
+let Predicates = [HasSSE2] in {
+ // FIXME: Instead of X86Unpcklpd, there should be a X86Movlhpd here, the problem
+ // is during lowering, where it's not possible to recognize the load fold cause
+ // it has two uses through a bitcast. One use disappears at isel time and the
+ // fold opportunity reappears.
+ def : Pat<(v2f64 (X86Unpcklpd VR128:$src1,
+ (scalar_to_vector (loadf64 addr:$src2)))),
+ (MOVHPDrm VR128:$src1, addr:$src2)>;
+
+ // FIXME: This should be matched by a X86Movhpd instead. Same as above
+ def : Pat<(v2f64 (X86Movlhpd VR128:$src1,
+ (scalar_to_vector (loadf64 addr:$src2)))),
+ (MOVHPDrm VR128:$src1, addr:$src2)>;
+
+ // Store patterns
+ def : Pat<(store (f64 (vector_extract
+ (v2f64 (X86Unpckhpd VR128:$src, (undef))), (iPTR 0))),addr:$dst),
+ (MOVHPDmr addr:$dst, VR128:$src)>;
+}
+
+//===----------------------------------------------------------------------===//
+// SSE 1 & 2 - Move Low to High and High to Low packed FP Instructions
+//===----------------------------------------------------------------------===//
+
let AddedComplexity = 20 in {
def VMOVLHPSrr : VPSI<0x16, MRMSrcReg, (outs VR128:$dst),
(ins VR128:$src1, VR128:$src2),
@@ -438,13 +1232,80 @@ let Constraints = "$src1 = $dst", AddedComplexity = 20 in {
(v4f32 (movhlps VR128:$src1, VR128:$src2)))]>;
}
-def : Pat<(movlhps VR128:$src1, (bc_v4i32 (v2i64 (X86vzload addr:$src2)))),
- (MOVHPSrm (v4i32 VR128:$src1), addr:$src2)>;
-let AddedComplexity = 20 in {
- def : Pat<(v4f32 (movddup VR128:$src, (undef))),
- (MOVLHPSrr (v4f32 VR128:$src), (v4f32 VR128:$src))>;
- def : Pat<(v2i64 (movddup VR128:$src, (undef))),
- (MOVLHPSrr (v2i64 VR128:$src), (v2i64 VR128:$src))>;
+let Predicates = [HasAVX] in {
+ // MOVLHPS patterns
+ let AddedComplexity = 20 in {
+ def : Pat<(v4f32 (movddup VR128:$src, (undef))),
+ (VMOVLHPSrr (v4f32 VR128:$src), (v4f32 VR128:$src))>;
+ def : Pat<(v2i64 (movddup VR128:$src, (undef))),
+ (VMOVLHPSrr (v2i64 VR128:$src), (v2i64 VR128:$src))>;
+
+ // vector_shuffle v1, v2 <0, 1, 4, 5> using MOVLHPS
+ def : Pat<(v4i32 (movlhps VR128:$src1, VR128:$src2)),
+ (VMOVLHPSrr VR128:$src1, VR128:$src2)>;
+ }
+ def : Pat<(v4f32 (X86Movlhps VR128:$src1, VR128:$src2)),
+ (VMOVLHPSrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v4i32 (X86Movlhps VR128:$src1, VR128:$src2)),
+ (VMOVLHPSrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (X86Movlhps VR128:$src1, VR128:$src2)),
+ (VMOVLHPSrr (v2i64 VR128:$src1), VR128:$src2)>;
+
+ // MOVHLPS patterns
+ let AddedComplexity = 20 in {
+ // vector_shuffle v1, v2 <6, 7, 2, 3> using MOVHLPS
+ def : Pat<(v4i32 (movhlps VR128:$src1, VR128:$src2)),
+ (VMOVHLPSrr VR128:$src1, VR128:$src2)>;
+
+ // vector_shuffle v1, undef <2, ?, ?, ?> using MOVHLPS
+ def : Pat<(v4f32 (movhlps_undef VR128:$src1, (undef))),
+ (VMOVHLPSrr VR128:$src1, VR128:$src1)>;
+ def : Pat<(v4i32 (movhlps_undef VR128:$src1, (undef))),
+ (VMOVHLPSrr VR128:$src1, VR128:$src1)>;
+ }
+
+ def : Pat<(v4f32 (X86Movhlps VR128:$src1, VR128:$src2)),
+ (VMOVHLPSrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v4i32 (X86Movhlps VR128:$src1, VR128:$src2)),
+ (VMOVHLPSrr VR128:$src1, VR128:$src2)>;
+}
+
+let Predicates = [HasSSE1] in {
+ // MOVLHPS patterns
+ let AddedComplexity = 20 in {
+ def : Pat<(v4f32 (movddup VR128:$src, (undef))),
+ (MOVLHPSrr (v4f32 VR128:$src), (v4f32 VR128:$src))>;
+ def : Pat<(v2i64 (movddup VR128:$src, (undef))),
+ (MOVLHPSrr (v2i64 VR128:$src), (v2i64 VR128:$src))>;
+
+ // vector_shuffle v1, v2 <0, 1, 4, 5> using MOVLHPS
+ def : Pat<(v4i32 (movlhps VR128:$src1, VR128:$src2)),
+ (MOVLHPSrr VR128:$src1, VR128:$src2)>;
+ }
+ def : Pat<(v4f32 (X86Movlhps VR128:$src1, VR128:$src2)),
+ (MOVLHPSrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v4i32 (X86Movlhps VR128:$src1, VR128:$src2)),
+ (MOVLHPSrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (X86Movlhps VR128:$src1, VR128:$src2)),
+ (MOVLHPSrr (v2i64 VR128:$src1), VR128:$src2)>;
+
+ // MOVHLPS patterns
+ let AddedComplexity = 20 in {
+ // vector_shuffle v1, v2 <6, 7, 2, 3> using MOVHLPS
+ def : Pat<(v4i32 (movhlps VR128:$src1, VR128:$src2)),
+ (MOVHLPSrr VR128:$src1, VR128:$src2)>;
+
+ // vector_shuffle v1, undef <2, ?, ?, ?> using MOVHLPS
+ def : Pat<(v4f32 (movhlps_undef VR128:$src1, (undef))),
+ (MOVHLPSrr VR128:$src1, VR128:$src1)>;
+ def : Pat<(v4i32 (movhlps_undef VR128:$src1, (undef))),
+ (MOVHLPSrr VR128:$src1, VR128:$src1)>;
+ }
+
+ def : Pat<(v4f32 (X86Movhlps VR128:$src1, VR128:$src2)),
+ (MOVHLPSrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v4i32 (X86Movhlps VR128:$src1, VR128:$src2)),
+ (MOVHLPSrr VR128:$src1, VR128:$src2)>;
}
//===----------------------------------------------------------------------===//
@@ -462,10 +1323,9 @@ multiclass sse12_cvt_s<bits<8> opc, RegisterClass SrcRC, RegisterClass DstRC,
multiclass sse12_cvt_s_np<bits<8> opc, RegisterClass SrcRC, RegisterClass DstRC,
X86MemOperand x86memop, string asm> {
- def rr : SI<opc, MRMSrcReg, (outs DstRC:$dst), (ins SrcRC:$src), asm,
- []>;
- def rm : SI<opc, MRMSrcMem, (outs DstRC:$dst), (ins x86memop:$src), asm,
- []>;
+ def rr : SI<opc, MRMSrcReg, (outs DstRC:$dst), (ins SrcRC:$src), asm, []>;
+ let mayLoad = 1 in
+ def rm : SI<opc, MRMSrcMem, (outs DstRC:$dst), (ins x86memop:$src), asm, []>;
}
multiclass sse12_cvt_p<bits<8> opc, RegisterClass SrcRC, RegisterClass DstRC,
@@ -481,36 +1341,39 @@ multiclass sse12_vcvt_avx<bits<8> opc, RegisterClass SrcRC, RegisterClass DstRC,
X86MemOperand x86memop, string asm> {
def rr : SI<opc, MRMSrcReg, (outs DstRC:$dst), (ins DstRC:$src1, SrcRC:$src),
!strconcat(asm,"\t{$src, $src1, $dst|$dst, $src1, $src}"), []>;
+ let mayLoad = 1 in
def rm : SI<opc, MRMSrcMem, (outs DstRC:$dst),
(ins DstRC:$src1, x86memop:$src),
!strconcat(asm,"\t{$src, $src1, $dst|$dst, $src1, $src}"), []>;
}
defm VCVTTSS2SI : sse12_cvt_s<0x2C, FR32, GR32, fp_to_sint, f32mem, loadf32,
- "cvttss2si\t{$src, $dst|$dst, $src}">, XS, VEX;
+ "cvttss2si\t{$src, $dst|$dst, $src}">, XS, VEX,
+ VEX_LIG;
defm VCVTTSS2SI64 : sse12_cvt_s<0x2C, FR32, GR64, fp_to_sint, f32mem, loadf32,
"cvttss2si\t{$src, $dst|$dst, $src}">, XS, VEX,
- VEX_W;
+ VEX_W, VEX_LIG;
defm VCVTTSD2SI : sse12_cvt_s<0x2C, FR64, GR32, fp_to_sint, f64mem, loadf64,
- "cvttsd2si\t{$src, $dst|$dst, $src}">, XD, VEX;
+ "cvttsd2si\t{$src, $dst|$dst, $src}">, XD, VEX,
+ VEX_LIG;
defm VCVTTSD2SI64 : sse12_cvt_s<0x2C, FR64, GR64, fp_to_sint, f64mem, loadf64,
"cvttsd2si\t{$src, $dst|$dst, $src}">, XD,
- VEX, VEX_W;
+ VEX, VEX_W, VEX_LIG;
// The assembler can recognize rr 64-bit instructions by seeing a rxx
// register, but the same isn't true when only using memory operands,
// provide other assembly "l" and "q" forms to address this explicitly
// where appropriate to do so.
defm VCVTSI2SS : sse12_vcvt_avx<0x2A, GR32, FR32, i32mem, "cvtsi2ss">, XS,
- VEX_4V;
+ VEX_4V, VEX_LIG;
defm VCVTSI2SS64 : sse12_vcvt_avx<0x2A, GR64, FR32, i64mem, "cvtsi2ss{q}">, XS,
- VEX_4V, VEX_W;
+ VEX_4V, VEX_W, VEX_LIG;
defm VCVTSI2SD : sse12_vcvt_avx<0x2A, GR32, FR64, i32mem, "cvtsi2sd">, XD,
- VEX_4V;
+ VEX_4V, VEX_LIG;
defm VCVTSI2SDL : sse12_vcvt_avx<0x2A, GR32, FR64, i32mem, "cvtsi2sd{l}">, XD,
- VEX_4V;
+ VEX_4V, VEX_LIG;
defm VCVTSI2SD64 : sse12_vcvt_avx<0x2A, GR64, FR64, i64mem, "cvtsi2sd{q}">, XD,
- VEX_4V, VEX_W;
+ VEX_4V, VEX_W, VEX_LIG;
let Predicates = [HasAVX] in {
def : Pat<(f32 (sint_to_fp (loadi32 addr:$src))),
@@ -579,11 +1442,6 @@ multiclass sse12_cvt_sint_3addr<bits<8> opc, RegisterClass SrcRC,
[(set DstRC:$dst, (Int DstRC:$src1, (ld_frag addr:$src2)))]>;
}
-defm Int_VCVTSS2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse_cvtss2si,
- f32mem, load, "cvtss2si">, XS, VEX;
-defm Int_VCVTSS2SI64 : sse12_cvt_sint<0x2D, VR128, GR64,
- int_x86_sse_cvtss2si64, f32mem, load, "cvtss2si">,
- XS, VEX, VEX_W;
defm Int_VCVTSD2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse2_cvtsd2si,
f128mem, load, "cvtsd2si">, XD, VEX;
defm Int_VCVTSD2SI64 : sse12_cvt_sint<0x2D, VR128, GR64,
@@ -594,14 +1452,12 @@ defm Int_VCVTSD2SI64 : sse12_cvt_sint<0x2D, VR128, GR64,
// Get rid of this hack or rename the intrinsics, there are several
// intructions that only match with the intrinsic form, why create duplicates
// to let them be recognized by the assembler?
-defm VCVTSD2SI_alt : sse12_cvt_s_np<0x2D, FR64, GR32, f64mem,
- "cvtsd2si\t{$src, $dst|$dst, $src}">, XD, VEX;
+defm VCVTSD2SI : sse12_cvt_s_np<0x2D, FR64, GR32, f64mem,
+ "cvtsd2si\t{$src, $dst|$dst, $src}">, XD, VEX, VEX_LIG;
defm VCVTSD2SI64 : sse12_cvt_s_np<0x2D, FR64, GR64, f64mem,
- "cvtsd2si\t{$src, $dst|$dst, $src}">, XD, VEX, VEX_W;
-defm Int_CVTSS2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse_cvtss2si,
- f32mem, load, "cvtss2si">, XS;
-defm Int_CVTSS2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, int_x86_sse_cvtss2si64,
- f32mem, load, "cvtss2si{q}">, XS, REX_W;
+ "cvtsd2si\t{$src, $dst|$dst, $src}">, XD, VEX, VEX_W,
+ VEX_LIG;
+
defm CVTSD2SI : sse12_cvt_sint<0x2D, VR128, GR32, int_x86_sse2_cvtsd2si,
f128mem, load, "cvtsd2si{l}">, XD;
defm CVTSD2SI64 : sse12_cvt_sint<0x2D, VR128, GR64, int_x86_sse2_cvtsd2si64,
@@ -660,10 +1516,11 @@ defm Int_CVTTSD2SI64 : sse12_cvt_sint<0x2C, VR128, GR64,
let Pattern = []<dag> in {
defm VCVTSS2SI : sse12_cvt_s<0x2D, FR32, GR32, undef, f32mem, load,
- "cvtss2si{l}\t{$src, $dst|$dst, $src}">, XS, VEX;
+ "cvtss2si{l}\t{$src, $dst|$dst, $src}">, XS,
+ VEX, VEX_LIG;
defm VCVTSS2SI64 : sse12_cvt_s<0x2D, FR32, GR64, undef, f32mem, load,
"cvtss2si\t{$src, $dst|$dst, $src}">, XS, VEX,
- VEX_W;
+ VEX_W, VEX_LIG;
defm VCVTDQ2PS : sse12_cvt_p<0x5B, VR128, VR128, undef, i128mem, load,
"cvtdq2ps\t{$src, $dst|$dst, $src}",
SSEPackedSingle>, TB, VEX;
@@ -671,6 +1528,7 @@ defm VCVTDQ2PSY : sse12_cvt_p<0x5B, VR256, VR256, undef, i256mem, load,
"cvtdq2ps\t{$src, $dst|$dst, $src}",
SSEPackedSingle>, TB, VEX;
}
+
let Pattern = []<dag> in {
defm CVTSS2SI : sse12_cvt_s<0x2D, FR32, GR32, undef, f32mem, load /*dummy*/,
"cvtss2si{l}\t{$src, $dst|$dst, $src}">, XS;
@@ -681,19 +1539,43 @@ defm CVTDQ2PS : sse12_cvt_p<0x5B, VR128, VR128, undef, i128mem, load /*dummy*/,
SSEPackedSingle>, TB; /* PD SSE3 form is avaiable */
}
+let Predicates = [HasSSE1] in {
+ def : Pat<(int_x86_sse_cvtss2si VR128:$src),
+ (CVTSS2SIrr (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss))>;
+ def : Pat<(int_x86_sse_cvtss2si (load addr:$src)),
+ (CVTSS2SIrm addr:$src)>;
+ def : Pat<(int_x86_sse_cvtss2si64 VR128:$src),
+ (CVTSS2SI64rr (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss))>;
+ def : Pat<(int_x86_sse_cvtss2si64 (load addr:$src)),
+ (CVTSS2SI64rm addr:$src)>;
+}
+
+let Predicates = [HasAVX] in {
+ def : Pat<(int_x86_sse_cvtss2si VR128:$src),
+ (VCVTSS2SIrr (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss))>;
+ def : Pat<(int_x86_sse_cvtss2si (load addr:$src)),
+ (VCVTSS2SIrm addr:$src)>;
+ def : Pat<(int_x86_sse_cvtss2si64 VR128:$src),
+ (VCVTSS2SI64rr (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss))>;
+ def : Pat<(int_x86_sse_cvtss2si64 (load addr:$src)),
+ (VCVTSS2SI64rm addr:$src)>;
+}
+
/// SSE 2 Only
// Convert scalar double to scalar single
def VCVTSD2SSrr : VSDI<0x5A, MRMSrcReg, (outs FR32:$dst),
(ins FR64:$src1, FR64:$src2),
"cvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>,
- VEX_4V;
+ VEX_4V, VEX_LIG;
+let mayLoad = 1 in
def VCVTSD2SSrm : I<0x5A, MRMSrcMem, (outs FR32:$dst),
(ins FR64:$src1, f64mem:$src2),
"vcvtsd2ss\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- []>, XD, Requires<[HasAVX, OptForSize]>, VEX_4V;
+ []>, XD, Requires<[HasAVX, OptForSize]>, VEX_4V, VEX_LIG;
+
def : Pat<(f32 (fround FR64:$src)), (VCVTSD2SSrr FR64:$src, FR64:$src)>,
- Requires<[HasAVX]>;
+ Requires<[HasAVX]>;
def CVTSD2SSrr : SDI<0x5A, MRMSrcReg, (outs FR32:$dst), (ins FR64:$src),
"cvtsd2ss\t{$src, $dst|$dst, $src}",
@@ -715,13 +1597,25 @@ defm Int_CVTSD2SS: sse12_cvt_sint_3addr<0x5A, VR128, VR128,
def VCVTSS2SDrr : I<0x5A, MRMSrcReg, (outs FR64:$dst),
(ins FR32:$src1, FR32:$src2),
"vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- []>, XS, Requires<[HasAVX]>, VEX_4V;
+ []>, XS, Requires<[HasAVX]>, VEX_4V, VEX_LIG;
+let mayLoad = 1 in
def VCVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst),
(ins FR32:$src1, f32mem:$src2),
"vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- []>, XS, VEX_4V, Requires<[HasAVX, OptForSize]>;
-def : Pat<(f64 (fextend FR32:$src)), (VCVTSS2SDrr FR32:$src, FR32:$src)>,
- Requires<[HasAVX]>;
+ []>, XS, VEX_4V, VEX_LIG, Requires<[HasAVX, OptForSize]>;
+
+let Predicates = [HasAVX] in {
+ def : Pat<(f64 (fextend FR32:$src)),
+ (VCVTSS2SDrr FR32:$src, FR32:$src)>;
+ def : Pat<(fextend (loadf32 addr:$src)),
+ (VCVTSS2SDrm (f32 (IMPLICIT_DEF)), addr:$src)>;
+ def : Pat<(extloadf32 addr:$src),
+ (VCVTSS2SDrm (f32 (IMPLICIT_DEF)), addr:$src)>;
+}
+
+def : Pat<(extloadf32 addr:$src),
+ (VCVTSS2SDrr (f32 (IMPLICIT_DEF)), (MOVSSrm addr:$src))>,
+ Requires<[HasAVX, OptForSpeed]>;
def CVTSS2SDrr : I<0x5A, MRMSrcReg, (outs FR64:$dst), (ins FR32:$src),
"cvtss2sd\t{$src, $dst|$dst, $src}",
@@ -732,6 +1626,16 @@ def CVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst), (ins f32mem:$src),
[(set FR64:$dst, (extloadf32 addr:$src))]>, XS,
Requires<[HasSSE2, OptForSize]>;
+// extload f32 -> f64. This matches load+fextend because we have a hack in
+// the isel (PreprocessForFPConvert) that can introduce loads after dag
+// combine.
+// Since these loads aren't folded into the fextend, we have to match it
+// explicitly here.
+def : Pat<(fextend (loadf32 addr:$src)),
+ (CVTSS2SDrm addr:$src)>, Requires<[HasSSE2]>;
+def : Pat<(extloadf32 addr:$src),
+ (CVTSS2SDrr (MOVSSrm addr:$src))>, Requires<[HasSSE2, OptForSpeed]>;
+
def Int_VCVTSS2SDrr: I<0x5A, MRMSrcReg,
(outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
"vcvtss2sd\t{$src2, $src1, $dst|$dst, $src1, $src2}",
@@ -759,10 +1663,6 @@ def Int_CVTSS2SDrm: I<0x5A, MRMSrcMem,
Requires<[HasSSE2]>;
}
-def : Pat<(extloadf32 addr:$src),
- (CVTSS2SDrr (MOVSSrm addr:$src))>,
- Requires<[HasSSE2, OptForSpeed]>;
-
// Convert doubleword to packed single/double fp
// SSE2 instructions without OpSize prefix
def Int_VCVTDQ2PSrr : I<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
@@ -862,10 +1762,12 @@ def Int_CVTPD2DQrm : I<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
// SSE2 packed instructions with XS prefix
def VCVTTPS2DQrr : VSSI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvttps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
+let mayLoad = 1 in
def VCVTTPS2DQrm : VSSI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
"cvttps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTTPS2DQYrr : VSSI<0x5B, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src),
"cvttps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
+let mayLoad = 1 in
def VCVTTPS2DQYrm : VSSI<0x5B, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src),
"cvttps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
def CVTTPS2DQrr : SSI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
@@ -877,7 +1779,6 @@ def CVTTPS2DQrm : SSI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
[(set VR128:$dst,
(int_x86_sse2_cvttps2dq (memop addr:$src)))]>;
-
def Int_VCVTTPS2DQrr : I<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"vcvttps2dq\t{$src, $dst|$dst, $src}",
[(set VR128:$dst,
@@ -889,16 +1790,33 @@ def Int_VCVTTPS2DQrm : I<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
(memop addr:$src)))]>,
XS, VEX, Requires<[HasAVX]>;
-def Int_VCVTTPD2DQrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst),
- (ins VR128:$src),
- "cvttpd2dq\t{$src, $dst|$dst, $src}",
- [(set VR128:$dst, (int_x86_sse2_cvttpd2dq VR128:$src))]>,
- VEX;
-def Int_VCVTTPD2DQrm : VPDI<0xE6, MRMSrcMem, (outs VR128:$dst),
- (ins f128mem:$src),
- "cvttpd2dq\t{$src, $dst|$dst, $src}",
- [(set VR128:$dst, (int_x86_sse2_cvttpd2dq
- (memop addr:$src)))]>, VEX;
+let Predicates = [HasSSE2] in {
+ def : Pat<(v4f32 (sint_to_fp (v4i32 VR128:$src))),
+ (Int_CVTDQ2PSrr VR128:$src)>;
+ def : Pat<(v4i32 (fp_to_sint (v4f32 VR128:$src))),
+ (CVTTPS2DQrr VR128:$src)>;
+}
+
+let Predicates = [HasAVX] in {
+ def : Pat<(v4f32 (sint_to_fp (v4i32 VR128:$src))),
+ (Int_VCVTDQ2PSrr VR128:$src)>;
+ def : Pat<(v4i32 (fp_to_sint (v4f32 VR128:$src))),
+ (VCVTTPS2DQrr VR128:$src)>;
+ def : Pat<(v8f32 (sint_to_fp (v8i32 VR256:$src))),
+ (VCVTDQ2PSYrr VR256:$src)>;
+ def : Pat<(v8i32 (fp_to_sint (v8f32 VR256:$src))),
+ (VCVTTPS2DQYrr VR256:$src)>;
+}
+
+def VCVTTPD2DQrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
+ "cvttpd2dq\t{$src, $dst|$dst, $src}",
+ [(set VR128:$dst,
+ (int_x86_sse2_cvttpd2dq VR128:$src))]>, VEX;
+let isCodeGenOnly = 1 in
+def VCVTTPD2DQrm : VPDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
+ "cvttpd2dq\t{$src, $dst|$dst, $src}",
+ [(set VR128:$dst, (int_x86_sse2_cvttpd2dq
+ (memop addr:$src)))]>, VEX;
def CVTTPD2DQrr : PDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvttpd2dq\t{$src, $dst|$dst, $src}",
[(set VR128:$dst, (int_x86_sse2_cvttpd2dq VR128:$src))]>;
@@ -910,8 +1828,6 @@ def CVTTPD2DQrm : PDI<0xE6, MRMSrcMem, (outs VR128:$dst),(ins f128mem:$src),
// The assembler can recognize rr 256-bit instructions by seeing a ymm
// register, but the same isn't true when using memory operands instead.
// Provide other assembly rr and rm forms to address this explicitly.
-def VCVTTPD2DQrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
- "cvttpd2dq\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTTPD2DQXrYr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src),
"cvttpd2dq\t{$src, $dst|$dst, $src}", []>, VEX;
@@ -931,13 +1847,13 @@ def VCVTTPD2DQYrm : VPDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src),
let Predicates = [HasAVX] in {
// SSE2 instructions without OpSize prefix
def VCVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
- "vcvtps2pd\t{$src, $dst|$dst, $src}", []>, VEX;
+ "vcvtps2pd\t{$src, $dst|$dst, $src}", []>, TB, VEX;
def VCVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src),
- "vcvtps2pd\t{$src, $dst|$dst, $src}", []>, VEX;
+ "vcvtps2pd\t{$src, $dst|$dst, $src}", []>, TB, VEX;
def VCVTPS2PDYrr : I<0x5A, MRMSrcReg, (outs VR256:$dst), (ins VR128:$src),
- "vcvtps2pd\t{$src, $dst|$dst, $src}", []>, VEX;
+ "vcvtps2pd\t{$src, $dst|$dst, $src}", []>, TB, VEX;
def VCVTPS2PDYrm : I<0x5A, MRMSrcMem, (outs VR256:$dst), (ins f128mem:$src),
- "vcvtps2pd\t{$src, $dst|$dst, $src}", []>, VEX;
+ "vcvtps2pd\t{$src, $dst|$dst, $src}", []>, TB, VEX;
}
def CVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvtps2pd\t{$src, $dst|$dst, $src}", []>, TB;
@@ -947,12 +1863,12 @@ def CVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src),
def Int_VCVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"vcvtps2pd\t{$src, $dst|$dst, $src}",
[(set VR128:$dst, (int_x86_sse2_cvtps2pd VR128:$src))]>,
- VEX, Requires<[HasAVX]>;
+ TB, VEX, Requires<[HasAVX]>;
def Int_VCVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src),
"vcvtps2pd\t{$src, $dst|$dst, $src}",
[(set VR128:$dst, (int_x86_sse2_cvtps2pd
(load addr:$src)))]>,
- VEX, Requires<[HasAVX]>;
+ TB, VEX, Requires<[HasAVX]>;
def Int_CVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvtps2pd\t{$src, $dst|$dst, $src}",
[(set VR128:$dst, (int_x86_sse2_cvtps2pd VR128:$src))]>,
@@ -1038,75 +1954,61 @@ def : Pat<(int_x86_avx_cvtt_ps2dq_256 VR256:$src),
def : Pat<(int_x86_avx_cvtt_ps2dq_256 (memopv8f32 addr:$src)),
(VCVTTPS2DQYrm addr:$src)>;
+// Match fround and fextend for 128/256-bit conversions
+def : Pat<(v4f32 (fround (v4f64 VR256:$src))),
+ (VCVTPD2PSYrr VR256:$src)>;
+def : Pat<(v4f32 (fround (loadv4f64 addr:$src))),
+ (VCVTPD2PSYrm addr:$src)>;
+
+def : Pat<(v4f64 (fextend (v4f32 VR128:$src))),
+ (VCVTPS2PDYrr VR128:$src)>;
+def : Pat<(v4f64 (fextend (loadv4f32 addr:$src))),
+ (VCVTPS2PDYrm addr:$src)>;
+
//===----------------------------------------------------------------------===//
// SSE 1 & 2 - Compare Instructions
//===----------------------------------------------------------------------===//
// sse12_cmp_scalar - sse 1 & 2 compare scalar instructions
multiclass sse12_cmp_scalar<RegisterClass RC, X86MemOperand x86memop,
+ SDNode OpNode, ValueType VT, PatFrag ld_frag,
string asm, string asm_alt> {
- let isAsmParserOnly = 1 in {
- def rr : SIi8<0xC2, MRMSrcReg,
- (outs RC:$dst), (ins RC:$src1, RC:$src, SSECC:$cc),
- asm, []>;
- let mayLoad = 1 in
- def rm : SIi8<0xC2, MRMSrcMem,
- (outs RC:$dst), (ins RC:$src1, x86memop:$src, SSECC:$cc),
- asm, []>;
- }
+ def rr : SIi8<0xC2, MRMSrcReg,
+ (outs RC:$dst), (ins RC:$src1, RC:$src2, SSECC:$cc), asm,
+ [(set RC:$dst, (OpNode (VT RC:$src1), RC:$src2, imm:$cc))]>;
+ def rm : SIi8<0xC2, MRMSrcMem,
+ (outs RC:$dst), (ins RC:$src1, x86memop:$src2, SSECC:$cc), asm,
+ [(set RC:$dst, (OpNode (VT RC:$src1),
+ (ld_frag addr:$src2), imm:$cc))]>;
// Accept explicit immediate argument form instead of comparison code.
- def rr_alt : SIi8<0xC2, MRMSrcReg,
- (outs RC:$dst), (ins RC:$src1, RC:$src, i8imm:$src2),
- asm_alt, []>;
- let mayLoad = 1 in
- def rm_alt : SIi8<0xC2, MRMSrcMem,
- (outs RC:$dst), (ins RC:$src1, x86memop:$src, i8imm:$src2),
- asm_alt, []>;
+ let neverHasSideEffects = 1 in {
+ def rr_alt : SIi8<0xC2, MRMSrcReg, (outs RC:$dst),
+ (ins RC:$src1, RC:$src2, i8imm:$cc), asm_alt, []>;
+ let mayLoad = 1 in
+ def rm_alt : SIi8<0xC2, MRMSrcMem, (outs RC:$dst),
+ (ins RC:$src1, x86memop:$src2, i8imm:$cc), asm_alt, []>;
+ }
}
-let neverHasSideEffects = 1 in {
- defm VCMPSS : sse12_cmp_scalar<FR32, f32mem,
- "cmp${cc}ss\t{$src, $src1, $dst|$dst, $src1, $src}",
- "cmpss\t{$src2, $src, $src1, $dst|$dst, $src1, $src, $src2}">,
- XS, VEX_4V;
- defm VCMPSD : sse12_cmp_scalar<FR64, f64mem,
- "cmp${cc}sd\t{$src, $src1, $dst|$dst, $src1, $src}",
- "cmpsd\t{$src2, $src, $src1, $dst|$dst, $src1, $src, $src2}">,
- XD, VEX_4V;
-}
+defm VCMPSS : sse12_cmp_scalar<FR32, f32mem, X86cmpss, f32, loadf32,
+ "cmp${cc}ss\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ "cmpss\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}">,
+ XS, VEX_4V, VEX_LIG;
+defm VCMPSD : sse12_cmp_scalar<FR64, f64mem, X86cmpsd, f64, loadf64,
+ "cmp${cc}sd\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ "cmpsd\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}">,
+ XD, VEX_4V, VEX_LIG;
let Constraints = "$src1 = $dst" in {
-def CMPSSrr : SIi8<0xC2, MRMSrcReg,
- (outs FR32:$dst), (ins FR32:$src1, FR32:$src2, SSECC:$cc),
+ defm CMPSS : sse12_cmp_scalar<FR32, f32mem, X86cmpss, f32, loadf32,
"cmp${cc}ss\t{$src2, $dst|$dst, $src2}",
- [(set FR32:$dst, (X86cmpss (f32 FR32:$src1), FR32:$src2, imm:$cc))]>, XS;
-def CMPSSrm : SIi8<0xC2, MRMSrcMem,
- (outs FR32:$dst), (ins FR32:$src1, f32mem:$src2, SSECC:$cc),
- "cmp${cc}ss\t{$src2, $dst|$dst, $src2}",
- [(set FR32:$dst, (X86cmpss (f32 FR32:$src1), (loadf32 addr:$src2), imm:$cc))]>, XS;
-def CMPSDrr : SIi8<0xC2, MRMSrcReg,
- (outs FR64:$dst), (ins FR64:$src1, FR64:$src2, SSECC:$cc),
- "cmp${cc}sd\t{$src2, $dst|$dst, $src2}",
- [(set FR64:$dst, (X86cmpsd (f64 FR64:$src1), FR64:$src2, imm:$cc))]>, XD;
-def CMPSDrm : SIi8<0xC2, MRMSrcMem,
- (outs FR64:$dst), (ins FR64:$src1, f64mem:$src2, SSECC:$cc),
+ "cmpss\t{$cc, $src2, $dst|$dst, $src2, $cc}">,
+ XS;
+ defm CMPSD : sse12_cmp_scalar<FR64, f64mem, X86cmpsd, f64, loadf64,
"cmp${cc}sd\t{$src2, $dst|$dst, $src2}",
- [(set FR64:$dst, (X86cmpsd (f64 FR64:$src1), (loadf64 addr:$src2), imm:$cc))]>, XD;
-}
-let Constraints = "$src1 = $dst", neverHasSideEffects = 1 in {
-def CMPSSrr_alt : SIi8<0xC2, MRMSrcReg,
- (outs FR32:$dst), (ins FR32:$src1, FR32:$src, i8imm:$src2),
- "cmpss\t{$src2, $src, $dst|$dst, $src, $src2}", []>, XS;
-def CMPSSrm_alt : SIi8<0xC2, MRMSrcMem,
- (outs FR32:$dst), (ins FR32:$src1, f32mem:$src, i8imm:$src2),
- "cmpss\t{$src2, $src, $dst|$dst, $src, $src2}", []>, XS;
-def CMPSDrr_alt : SIi8<0xC2, MRMSrcReg,
- (outs FR64:$dst), (ins FR64:$src1, FR64:$src, i8imm:$src2),
- "cmpsd\t{$src2, $src, $dst|$dst, $src, $src2}", []>, XD;
-def CMPSDrm_alt : SIi8<0xC2, MRMSrcMem,
- (outs FR64:$dst), (ins FR64:$src1, f64mem:$src, i8imm:$src2),
- "cmpsd\t{$src2, $src, $dst|$dst, $src, $src2}", []>, XD;
+ "cmpsd\t{$cc, $src2, $dst|$dst, $src2, $cc}">,
+ XD;
}
multiclass sse12_cmp_scalar_int<RegisterClass RC, X86MemOperand x86memop,
@@ -1151,25 +2053,28 @@ multiclass sse12_ord_cmp<bits<8> opc, RegisterClass RC, SDNode OpNode,
let Defs = [EFLAGS] in {
defm VUCOMISS : sse12_ord_cmp<0x2E, FR32, X86cmp, f32, f32mem, loadf32,
- "ucomiss", SSEPackedSingle>, VEX;
+ "ucomiss", SSEPackedSingle>, TB, VEX, VEX_LIG;
defm VUCOMISD : sse12_ord_cmp<0x2E, FR64, X86cmp, f64, f64mem, loadf64,
- "ucomisd", SSEPackedDouble>, OpSize, VEX;
+ "ucomisd", SSEPackedDouble>, TB, OpSize, VEX,
+ VEX_LIG;
let Pattern = []<dag> in {
defm VCOMISS : sse12_ord_cmp<0x2F, VR128, undef, v4f32, f128mem, load,
- "comiss", SSEPackedSingle>, VEX;
+ "comiss", SSEPackedSingle>, TB, VEX,
+ VEX_LIG;
defm VCOMISD : sse12_ord_cmp<0x2F, VR128, undef, v2f64, f128mem, load,
- "comisd", SSEPackedDouble>, OpSize, VEX;
+ "comisd", SSEPackedDouble>, TB, OpSize, VEX,
+ VEX_LIG;
}
defm Int_VUCOMISS : sse12_ord_cmp<0x2E, VR128, X86ucomi, v4f32, f128mem,
- load, "ucomiss", SSEPackedSingle>, VEX;
+ load, "ucomiss", SSEPackedSingle>, TB, VEX;
defm Int_VUCOMISD : sse12_ord_cmp<0x2E, VR128, X86ucomi, v2f64, f128mem,
- load, "ucomisd", SSEPackedDouble>, OpSize, VEX;
+ load, "ucomisd", SSEPackedDouble>, TB, OpSize, VEX;
defm Int_VCOMISS : sse12_ord_cmp<0x2F, VR128, X86comi, v4f32, f128mem,
- load, "comiss", SSEPackedSingle>, VEX;
+ load, "comiss", SSEPackedSingle>, TB, VEX;
defm Int_VCOMISD : sse12_ord_cmp<0x2F, VR128, X86comi, v2f64, f128mem,
- load, "comisd", SSEPackedDouble>, OpSize, VEX;
+ load, "comisd", SSEPackedDouble>, TB, OpSize, VEX;
defm UCOMISS : sse12_ord_cmp<0x2E, FR32, X86cmp, f32, f32mem, loadf32,
"ucomiss", SSEPackedSingle>, TB;
defm UCOMISD : sse12_ord_cmp<0x2E, FR64, X86cmp, f64, f64mem, loadf64,
@@ -1199,57 +2104,82 @@ multiclass sse12_cmp_packed<RegisterClass RC, X86MemOperand x86memop,
Domain d> {
let isAsmParserOnly = 1 in {
def rri : PIi8<0xC2, MRMSrcReg,
- (outs RC:$dst), (ins RC:$src1, RC:$src, SSECC:$cc), asm,
- [(set RC:$dst, (Int RC:$src1, RC:$src, imm:$cc))], d>;
+ (outs RC:$dst), (ins RC:$src1, RC:$src2, SSECC:$cc), asm,
+ [(set RC:$dst, (Int RC:$src1, RC:$src2, imm:$cc))], d>;
def rmi : PIi8<0xC2, MRMSrcMem,
- (outs RC:$dst), (ins RC:$src1, f128mem:$src, SSECC:$cc), asm,
- [(set RC:$dst, (Int RC:$src1, (memop addr:$src), imm:$cc))], d>;
+ (outs RC:$dst), (ins RC:$src1, f128mem:$src2, SSECC:$cc), asm,
+ [(set RC:$dst, (Int RC:$src1, (memop addr:$src2), imm:$cc))], d>;
}
// Accept explicit immediate argument form instead of comparison code.
def rri_alt : PIi8<0xC2, MRMSrcReg,
- (outs RC:$dst), (ins RC:$src1, RC:$src, i8imm:$src2),
+ (outs RC:$dst), (ins RC:$src1, RC:$src2, i8imm:$cc),
asm_alt, [], d>;
def rmi_alt : PIi8<0xC2, MRMSrcMem,
- (outs RC:$dst), (ins RC:$src1, f128mem:$src, i8imm:$src2),
+ (outs RC:$dst), (ins RC:$src1, f128mem:$src2, i8imm:$cc),
asm_alt, [], d>;
}
defm VCMPPS : sse12_cmp_packed<VR128, f128mem, int_x86_sse_cmp_ps,
- "cmp${cc}ps\t{$src, $src1, $dst|$dst, $src1, $src}",
- "cmpps\t{$src2, $src, $src1, $dst|$dst, $src1, $src, $src2}",
- SSEPackedSingle>, VEX_4V;
+ "cmp${cc}ps\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ "cmpps\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}",
+ SSEPackedSingle>, TB, VEX_4V;
defm VCMPPD : sse12_cmp_packed<VR128, f128mem, int_x86_sse2_cmp_pd,
- "cmp${cc}pd\t{$src, $src1, $dst|$dst, $src1, $src}",
- "cmppd\t{$src2, $src, $src1, $dst|$dst, $src1, $src, $src2}",
- SSEPackedDouble>, OpSize, VEX_4V;
+ "cmp${cc}pd\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ "cmppd\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}",
+ SSEPackedDouble>, TB, OpSize, VEX_4V;
defm VCMPPSY : sse12_cmp_packed<VR256, f256mem, int_x86_avx_cmp_ps_256,
- "cmp${cc}ps\t{$src, $src1, $dst|$dst, $src1, $src}",
- "cmpps\t{$src2, $src, $src1, $dst|$dst, $src1, $src, $src2}",
- SSEPackedSingle>, VEX_4V;
+ "cmp${cc}ps\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ "cmpps\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}",
+ SSEPackedSingle>, TB, VEX_4V;
defm VCMPPDY : sse12_cmp_packed<VR256, f256mem, int_x86_avx_cmp_pd_256,
- "cmp${cc}pd\t{$src, $src1, $dst|$dst, $src1, $src}",
- "cmppd\t{$src2, $src, $src1, $dst|$dst, $src1, $src, $src2}",
- SSEPackedDouble>, OpSize, VEX_4V;
+ "cmp${cc}pd\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ "cmppd\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}",
+ SSEPackedDouble>, TB, OpSize, VEX_4V;
let Constraints = "$src1 = $dst" in {
defm CMPPS : sse12_cmp_packed<VR128, f128mem, int_x86_sse_cmp_ps,
- "cmp${cc}ps\t{$src, $dst|$dst, $src}",
- "cmpps\t{$src2, $src, $dst|$dst, $src, $src2}",
+ "cmp${cc}ps\t{$src2, $dst|$dst, $src2}",
+ "cmpps\t{$cc, $src2, $dst|$dst, $src2, $cc}",
SSEPackedSingle>, TB;
defm CMPPD : sse12_cmp_packed<VR128, f128mem, int_x86_sse2_cmp_pd,
- "cmp${cc}pd\t{$src, $dst|$dst, $src}",
- "cmppd\t{$src2, $src, $dst|$dst, $src, $src2}",
+ "cmp${cc}pd\t{$src2, $dst|$dst, $src2}",
+ "cmppd\t{$cc, $src2, $dst|$dst, $src2, $cc}",
SSEPackedDouble>, TB, OpSize;
}
+let Predicates = [HasSSE1] in {
def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), VR128:$src2, imm:$cc)),
(CMPPSrri (v4f32 VR128:$src1), (v4f32 VR128:$src2), imm:$cc)>;
def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), (memop addr:$src2), imm:$cc)),
(CMPPSrmi (v4f32 VR128:$src1), addr:$src2, imm:$cc)>;
+}
+
+let Predicates = [HasSSE2] in {
def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), VR128:$src2, imm:$cc)),
(CMPPDrri VR128:$src1, VR128:$src2, imm:$cc)>;
def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), (memop addr:$src2), imm:$cc)),
(CMPPDrmi VR128:$src1, addr:$src2, imm:$cc)>;
+}
+
+let Predicates = [HasAVX] in {
+def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), VR128:$src2, imm:$cc)),
+ (VCMPPSrri (v4f32 VR128:$src1), (v4f32 VR128:$src2), imm:$cc)>;
+def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), (memop addr:$src2), imm:$cc)),
+ (VCMPPSrmi (v4f32 VR128:$src1), addr:$src2, imm:$cc)>;
+def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), VR128:$src2, imm:$cc)),
+ (VCMPPDrri VR128:$src1, VR128:$src2, imm:$cc)>;
+def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), (memop addr:$src2), imm:$cc)),
+ (VCMPPDrmi VR128:$src1, addr:$src2, imm:$cc)>;
+
+def : Pat<(v8i32 (X86cmpps (v8f32 VR256:$src1), VR256:$src2, imm:$cc)),
+ (VCMPPSYrri (v8f32 VR256:$src1), (v8f32 VR256:$src2), imm:$cc)>;
+def : Pat<(v8i32 (X86cmpps (v8f32 VR256:$src1), (memop addr:$src2), imm:$cc)),
+ (VCMPPSYrmi (v8f32 VR256:$src1), addr:$src2, imm:$cc)>;
+def : Pat<(v4i64 (X86cmppd (v4f64 VR256:$src1), VR256:$src2, imm:$cc)),
+ (VCMPPDYrri VR256:$src1, VR256:$src2, imm:$cc)>;
+def : Pat<(v4i64 (X86cmppd (v4f64 VR256:$src1), (memop addr:$src2), imm:$cc)),
+ (VCMPPDYrmi VR256:$src1, addr:$src2, imm:$cc)>;
+}
//===----------------------------------------------------------------------===//
// SSE 1 & 2 - Shuffle Instructions
@@ -1293,6 +2223,132 @@ let Constraints = "$src1 = $dst" in {
memopv2f64, SSEPackedDouble>, TB, OpSize;
}
+let Predicates = [HasSSE1] in {
+ def : Pat<(v4f32 (X86Shufps VR128:$src1,
+ (memopv4f32 addr:$src2), (i8 imm:$imm))),
+ (SHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>;
+ def : Pat<(v4f32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (SHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>;
+ def : Pat<(v4i32 (X86Shufps VR128:$src1,
+ (bc_v4i32 (memopv2i64 addr:$src2)), (i8 imm:$imm))),
+ (SHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>;
+ def : Pat<(v4i32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (SHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>;
+ // vector_shuffle v1, v2 <4, 5, 2, 3> using SHUFPSrri (we prefer movsd, but
+ // fall back to this for SSE1)
+ def : Pat<(v4f32 (movlp:$src3 VR128:$src1, (v4f32 VR128:$src2))),
+ (SHUFPSrri VR128:$src2, VR128:$src1,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ // Special unary SHUFPSrri case.
+ def : Pat<(v4f32 (pshufd:$src3 VR128:$src1, (undef))),
+ (SHUFPSrri VR128:$src1, VR128:$src1,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+}
+
+let Predicates = [HasSSE2] in {
+ // Special binary v4i32 shuffle cases with SHUFPS.
+ def : Pat<(v4i32 (shufp:$src3 VR128:$src1, (v4i32 VR128:$src2))),
+ (SHUFPSrri VR128:$src1, VR128:$src2,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ def : Pat<(v4i32 (shufp:$src3 VR128:$src1,
+ (bc_v4i32 (memopv2i64 addr:$src2)))),
+ (SHUFPSrmi VR128:$src1, addr:$src2,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ // Special unary SHUFPDrri cases.
+ def : Pat<(v2i64 (pshufd:$src3 VR128:$src1, (undef))),
+ (SHUFPDrri VR128:$src1, VR128:$src1,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ def : Pat<(v2f64 (pshufd:$src3 VR128:$src1, (undef))),
+ (SHUFPDrri VR128:$src1, VR128:$src1,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ // Special binary v2i64 shuffle cases using SHUFPDrri.
+ def : Pat<(v2i64 (shufp:$src3 VR128:$src1, VR128:$src2)),
+ (SHUFPDrri VR128:$src1, VR128:$src2,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ // Generic SHUFPD patterns
+ def : Pat<(v2f64 (X86Shufps VR128:$src1,
+ (memopv2f64 addr:$src2), (i8 imm:$imm))),
+ (SHUFPDrmi VR128:$src1, addr:$src2, imm:$imm)>;
+ def : Pat<(v2i64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (SHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>;
+ def : Pat<(v2f64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (SHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>;
+}
+
+let Predicates = [HasAVX] in {
+ def : Pat<(v4f32 (X86Shufps VR128:$src1,
+ (memopv4f32 addr:$src2), (i8 imm:$imm))),
+ (VSHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>;
+ def : Pat<(v4f32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (VSHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>;
+ def : Pat<(v4i32 (X86Shufps VR128:$src1,
+ (bc_v4i32 (memopv2i64 addr:$src2)), (i8 imm:$imm))),
+ (VSHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>;
+ def : Pat<(v4i32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (VSHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>;
+ // vector_shuffle v1, v2 <4, 5, 2, 3> using SHUFPSrri (we prefer movsd, but
+ // fall back to this for SSE1)
+ def : Pat<(v4f32 (movlp:$src3 VR128:$src1, (v4f32 VR128:$src2))),
+ (VSHUFPSrri VR128:$src2, VR128:$src1,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ // Special unary SHUFPSrri case.
+ def : Pat<(v4f32 (pshufd:$src3 VR128:$src1, (undef))),
+ (VSHUFPSrri VR128:$src1, VR128:$src1,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ // Special binary v4i32 shuffle cases with SHUFPS.
+ def : Pat<(v4i32 (shufp:$src3 VR128:$src1, (v4i32 VR128:$src2))),
+ (VSHUFPSrri VR128:$src1, VR128:$src2,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ def : Pat<(v4i32 (shufp:$src3 VR128:$src1,
+ (bc_v4i32 (memopv2i64 addr:$src2)))),
+ (VSHUFPSrmi VR128:$src1, addr:$src2,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ // Special unary SHUFPDrri cases.
+ def : Pat<(v2i64 (pshufd:$src3 VR128:$src1, (undef))),
+ (VSHUFPDrri VR128:$src1, VR128:$src1,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ def : Pat<(v2f64 (pshufd:$src3 VR128:$src1, (undef))),
+ (VSHUFPDrri VR128:$src1, VR128:$src1,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+ // Special binary v2i64 shuffle cases using SHUFPDrri.
+ def : Pat<(v2i64 (shufp:$src3 VR128:$src1, VR128:$src2)),
+ (VSHUFPDrri VR128:$src1, VR128:$src2,
+ (SHUFFLE_get_shuf_imm VR128:$src3))>;
+
+ def : Pat<(v2f64 (X86Shufps VR128:$src1,
+ (memopv2f64 addr:$src2), (i8 imm:$imm))),
+ (VSHUFPDrmi VR128:$src1, addr:$src2, imm:$imm)>;
+ def : Pat<(v2i64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (VSHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>;
+ def : Pat<(v2f64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (VSHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>;
+
+ // 256-bit patterns
+ def : Pat<(v8i32 (X86Shufps VR256:$src1, VR256:$src2, (i8 imm:$imm))),
+ (VSHUFPSYrri VR256:$src1, VR256:$src2, imm:$imm)>;
+ def : Pat<(v8i32 (X86Shufps VR256:$src1,
+ (bc_v8i32 (memopv4i64 addr:$src2)), (i8 imm:$imm))),
+ (VSHUFPSYrmi VR256:$src1, addr:$src2, imm:$imm)>;
+
+ def : Pat<(v8f32 (X86Shufps VR256:$src1, VR256:$src2, (i8 imm:$imm))),
+ (VSHUFPSYrri VR256:$src1, VR256:$src2, imm:$imm)>;
+ def : Pat<(v8f32 (X86Shufps VR256:$src1,
+ (memopv8f32 addr:$src2), (i8 imm:$imm))),
+ (VSHUFPSYrmi VR256:$src1, addr:$src2, imm:$imm)>;
+
+ def : Pat<(v4i64 (X86Shufpd VR256:$src1, VR256:$src2, (i8 imm:$imm))),
+ (VSHUFPDYrri VR256:$src1, VR256:$src2, imm:$imm)>;
+ def : Pat<(v4i64 (X86Shufpd VR256:$src1,
+ (memopv4i64 addr:$src2), (i8 imm:$imm))),
+ (VSHUFPDYrmi VR256:$src1, addr:$src2, imm:$imm)>;
+
+ def : Pat<(v4f64 (X86Shufpd VR256:$src1, VR256:$src2, (i8 imm:$imm))),
+ (VSHUFPDYrri VR256:$src1, VR256:$src2, imm:$imm)>;
+ def : Pat<(v4f64 (X86Shufpd VR256:$src1,
+ (memopv4f64 addr:$src2), (i8 imm:$imm))),
+ (VSHUFPDYrmi VR256:$src1, addr:$src2, imm:$imm)>;
+}
+
//===----------------------------------------------------------------------===//
// SSE 1 & 2 - Unpack Instructions
//===----------------------------------------------------------------------===//
@@ -1316,29 +2372,29 @@ multiclass sse12_unpack_interleave<bits<8> opc, PatFrag OpNode, ValueType vt,
let AddedComplexity = 10 in {
defm VUNPCKHPS: sse12_unpack_interleave<0x15, unpckh, v4f32, memopv4f32,
VR128, f128mem, "unpckhps\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- SSEPackedSingle>, VEX_4V;
+ SSEPackedSingle>, TB, VEX_4V;
defm VUNPCKHPD: sse12_unpack_interleave<0x15, unpckh, v2f64, memopv2f64,
VR128, f128mem, "unpckhpd\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- SSEPackedDouble>, OpSize, VEX_4V;
+ SSEPackedDouble>, TB, OpSize, VEX_4V;
defm VUNPCKLPS: sse12_unpack_interleave<0x14, unpckl, v4f32, memopv4f32,
VR128, f128mem, "unpcklps\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- SSEPackedSingle>, VEX_4V;
+ SSEPackedSingle>, TB, VEX_4V;
defm VUNPCKLPD: sse12_unpack_interleave<0x14, unpckl, v2f64, memopv2f64,
VR128, f128mem, "unpcklpd\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- SSEPackedDouble>, OpSize, VEX_4V;
+ SSEPackedDouble>, TB, OpSize, VEX_4V;
defm VUNPCKHPSY: sse12_unpack_interleave<0x15, unpckh, v8f32, memopv8f32,
VR256, f256mem, "unpckhps\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- SSEPackedSingle>, VEX_4V;
+ SSEPackedSingle>, TB, VEX_4V;
defm VUNPCKHPDY: sse12_unpack_interleave<0x15, unpckh, v4f64, memopv4f64,
VR256, f256mem, "unpckhpd\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- SSEPackedDouble>, OpSize, VEX_4V;
+ SSEPackedDouble>, TB, OpSize, VEX_4V;
defm VUNPCKLPSY: sse12_unpack_interleave<0x14, unpckl, v8f32, memopv8f32,
VR256, f256mem, "unpcklps\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- SSEPackedSingle>, VEX_4V;
+ SSEPackedSingle>, TB, VEX_4V;
defm VUNPCKLPDY: sse12_unpack_interleave<0x14, unpckl, v4f64, memopv4f64,
VR256, f256mem, "unpcklpd\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- SSEPackedDouble>, OpSize, VEX_4V;
+ SSEPackedDouble>, TB, OpSize, VEX_4V;
let Constraints = "$src1 = $dst" in {
defm UNPCKHPS: sse12_unpack_interleave<0x15, unpckh, v4f32, memopv4f32,
@@ -1356,6 +2412,103 @@ let AddedComplexity = 10 in {
} // Constraints = "$src1 = $dst"
} // AddedComplexity
+let Predicates = [HasSSE1] in {
+ def : Pat<(v4f32 (X86Unpcklps VR128:$src1, (memopv4f32 addr:$src2))),
+ (UNPCKLPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4f32 (X86Unpcklps VR128:$src1, VR128:$src2)),
+ (UNPCKLPSrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v4f32 (X86Unpckhps VR128:$src1, (memopv4f32 addr:$src2))),
+ (UNPCKHPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4f32 (X86Unpckhps VR128:$src1, VR128:$src2)),
+ (UNPCKHPSrr VR128:$src1, VR128:$src2)>;
+}
+
+let Predicates = [HasSSE2] in {
+ def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, (memopv2f64 addr:$src2))),
+ (UNPCKLPDrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, VR128:$src2)),
+ (UNPCKLPDrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, (memopv2f64 addr:$src2))),
+ (UNPCKHPDrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, VR128:$src2)),
+ (UNPCKHPDrr VR128:$src1, VR128:$src2)>;
+
+ // FIXME: Instead of X86Movddup, there should be a X86Unpcklpd here, the
+ // problem is during lowering, where it's not possible to recognize the load
+ // fold cause it has two uses through a bitcast. One use disappears at isel
+ // time and the fold opportunity reappears.
+ def : Pat<(v2f64 (X86Movddup VR128:$src)),
+ (UNPCKLPDrr VR128:$src, VR128:$src)>;
+
+ let AddedComplexity = 10 in
+ def : Pat<(splat_lo (v2f64 VR128:$src), (undef)),
+ (UNPCKLPDrr VR128:$src, VR128:$src)>;
+}
+
+let Predicates = [HasAVX] in {
+ def : Pat<(v4f32 (X86Unpcklps VR128:$src1, (memopv4f32 addr:$src2))),
+ (VUNPCKLPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4f32 (X86Unpcklps VR128:$src1, VR128:$src2)),
+ (VUNPCKLPSrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v4f32 (X86Unpckhps VR128:$src1, (memopv4f32 addr:$src2))),
+ (VUNPCKHPSrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4f32 (X86Unpckhps VR128:$src1, VR128:$src2)),
+ (VUNPCKHPSrr VR128:$src1, VR128:$src2)>;
+
+ def : Pat<(v8f32 (X86Unpcklpsy VR256:$src1, (memopv8f32 addr:$src2))),
+ (VUNPCKLPSYrm VR256:$src1, addr:$src2)>;
+ def : Pat<(v8f32 (X86Unpcklpsy VR256:$src1, VR256:$src2)),
+ (VUNPCKLPSYrr VR256:$src1, VR256:$src2)>;
+ def : Pat<(v8i32 (X86Unpcklpsy VR256:$src1, VR256:$src2)),
+ (VUNPCKLPSYrr VR256:$src1, VR256:$src2)>;
+ def : Pat<(v8i32 (X86Unpcklpsy VR256:$src1, (memopv8i32 addr:$src2))),
+ (VUNPCKLPSYrm VR256:$src1, addr:$src2)>;
+ def : Pat<(v8f32 (X86Unpckhpsy VR256:$src1, (memopv8f32 addr:$src2))),
+ (VUNPCKHPSYrm VR256:$src1, addr:$src2)>;
+ def : Pat<(v8f32 (X86Unpckhpsy VR256:$src1, VR256:$src2)),
+ (VUNPCKHPSYrr VR256:$src1, VR256:$src2)>;
+ def : Pat<(v8i32 (X86Unpckhpsy VR256:$src1, (memopv8i32 addr:$src2))),
+ (VUNPCKHPSYrm VR256:$src1, addr:$src2)>;
+ def : Pat<(v8i32 (X86Unpckhpsy VR256:$src1, VR256:$src2)),
+ (VUNPCKHPSYrr VR256:$src1, VR256:$src2)>;
+
+ def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, (memopv2f64 addr:$src2))),
+ (VUNPCKLPDrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, VR128:$src2)),
+ (VUNPCKLPDrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, (memopv2f64 addr:$src2))),
+ (VUNPCKHPDrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, VR128:$src2)),
+ (VUNPCKHPDrr VR128:$src1, VR128:$src2)>;
+
+ def : Pat<(v4f64 (X86Unpcklpdy VR256:$src1, (memopv4f64 addr:$src2))),
+ (VUNPCKLPDYrm VR256:$src1, addr:$src2)>;
+ def : Pat<(v4f64 (X86Unpcklpdy VR256:$src1, VR256:$src2)),
+ (VUNPCKLPDYrr VR256:$src1, VR256:$src2)>;
+ def : Pat<(v4i64 (X86Unpcklpdy VR256:$src1, (memopv4i64 addr:$src2))),
+ (VUNPCKLPDYrm VR256:$src1, addr:$src2)>;
+ def : Pat<(v4i64 (X86Unpcklpdy VR256:$src1, VR256:$src2)),
+ (VUNPCKLPDYrr VR256:$src1, VR256:$src2)>;
+ def : Pat<(v4f64 (X86Unpckhpdy VR256:$src1, (memopv4f64 addr:$src2))),
+ (VUNPCKHPDYrm VR256:$src1, addr:$src2)>;
+ def : Pat<(v4f64 (X86Unpckhpdy VR256:$src1, VR256:$src2)),
+ (VUNPCKHPDYrr VR256:$src1, VR256:$src2)>;
+ def : Pat<(v4i64 (X86Unpckhpdy VR256:$src1, (memopv4i64 addr:$src2))),
+ (VUNPCKHPDYrm VR256:$src1, addr:$src2)>;
+ def : Pat<(v4i64 (X86Unpckhpdy VR256:$src1, VR256:$src2)),
+ (VUNPCKHPDYrr VR256:$src1, VR256:$src2)>;
+
+ // FIXME: Instead of X86Movddup, there should be a X86Unpcklpd here, the
+ // problem is during lowering, where it's not possible to recognize the load
+ // fold cause it has two uses through a bitcast. One use disappears at isel
+ // time and the fold opportunity reappears.
+ def : Pat<(v2f64 (X86Movddup VR128:$src)),
+ (VUNPCKLPDrr VR128:$src, VR128:$src)>;
+ let AddedComplexity = 10 in
+ def : Pat<(splat_lo (v2f64 VR128:$src), (undef)),
+ (VUNPCKLPDrr VR128:$src, VR128:$src)>;
+}
+
//===----------------------------------------------------------------------===//
// SSE 1 & 2 - Extract Floating-Point Sign mask
//===----------------------------------------------------------------------===//
@@ -1370,91 +2523,60 @@ multiclass sse12_extr_sign_mask<RegisterClass RC, Intrinsic Int, string asm,
!strconcat(asm, "\t{$src, $dst|$dst, $src}"), [], d>, REX_W;
}
-// Mask creation
-defm VMOVMSKPS : sse12_extr_sign_mask<VR128, int_x86_sse_movmsk_ps,
- "movmskps", SSEPackedSingle>, VEX;
-defm VMOVMSKPD : sse12_extr_sign_mask<VR128, int_x86_sse2_movmsk_pd,
- "movmskpd", SSEPackedDouble>, OpSize,
- VEX;
-defm VMOVMSKPSY : sse12_extr_sign_mask<VR256, int_x86_avx_movmsk_ps_256,
- "movmskps", SSEPackedSingle>, VEX;
-defm VMOVMSKPDY : sse12_extr_sign_mask<VR256, int_x86_avx_movmsk_pd_256,
- "movmskpd", SSEPackedDouble>, OpSize,
- VEX;
defm MOVMSKPS : sse12_extr_sign_mask<VR128, int_x86_sse_movmsk_ps, "movmskps",
SSEPackedSingle>, TB;
defm MOVMSKPD : sse12_extr_sign_mask<VR128, int_x86_sse2_movmsk_pd, "movmskpd",
SSEPackedDouble>, TB, OpSize;
-// X86fgetsign
-def MOVMSKPDrr32_alt : PI<0x50, MRMSrcReg, (outs GR32:$dst), (ins FR64:$src),
- "movmskpd\t{$src, $dst|$dst, $src}",
- [(set GR32:$dst, (X86fgetsign FR64:$src))], SSEPackedDouble>, TB, OpSize;
-def MOVMSKPDrr64_alt : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins FR64:$src),
- "movmskpd\t{$src, $dst|$dst, $src}",
- [(set GR64:$dst, (X86fgetsign FR64:$src))], SSEPackedDouble>, TB, OpSize;
-def MOVMSKPSrr32_alt : PI<0x50, MRMSrcReg, (outs GR32:$dst), (ins FR32:$src),
- "movmskps\t{$src, $dst|$dst, $src}",
- [(set GR32:$dst, (X86fgetsign FR32:$src))], SSEPackedSingle>, TB;
-def MOVMSKPSrr64_alt : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins FR32:$src),
- "movmskps\t{$src, $dst|$dst, $src}",
- [(set GR64:$dst, (X86fgetsign FR32:$src))], SSEPackedSingle>, TB;
-
-// Assembler Only
-def VMOVMSKPSr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src),
- "movmskps\t{$src, $dst|$dst, $src}", [], SSEPackedSingle>, VEX;
-def VMOVMSKPDr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src),
- "movmskpd\t{$src, $dst|$dst, $src}", [], SSEPackedDouble>, OpSize,
- VEX;
-def VMOVMSKPSYr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR256:$src),
- "movmskps\t{$src, $dst|$dst, $src}", [], SSEPackedSingle>, VEX;
-def VMOVMSKPDYr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR256:$src),
- "movmskpd\t{$src, $dst|$dst, $src}", [], SSEPackedDouble>, OpSize,
- VEX;
-
-//===----------------------------------------------------------------------===//
-// SSE 1 & 2 - Misc aliasing of packed SSE 1 & 2 instructions
-//===----------------------------------------------------------------------===//
-
-// Aliases of packed SSE1 & SSE2 instructions for scalar use. These all have
-// names that start with 'Fs'.
-
-// Alias instructions that map fld0 to pxor for sse.
-let isReMaterializable = 1, isAsCheapAsAMove = 1, isCodeGenOnly = 1,
- canFoldAsLoad = 1 in {
- // FIXME: Set encoding to pseudo!
-def FsFLD0SS : I<0xEF, MRMInitReg, (outs FR32:$dst), (ins), "",
- [(set FR32:$dst, fp32imm0)]>,
- Requires<[HasSSE1]>, TB, OpSize;
-def FsFLD0SD : I<0xEF, MRMInitReg, (outs FR64:$dst), (ins), "",
- [(set FR64:$dst, fpimm0)]>,
- Requires<[HasSSE2]>, TB, OpSize;
-def VFsFLD0SS : I<0xEF, MRMInitReg, (outs FR32:$dst), (ins), "",
- [(set FR32:$dst, fp32imm0)]>,
- Requires<[HasAVX]>, TB, OpSize, VEX_4V;
-def VFsFLD0SD : I<0xEF, MRMInitReg, (outs FR64:$dst), (ins), "",
- [(set FR64:$dst, fpimm0)]>,
- Requires<[HasAVX]>, TB, OpSize, VEX_4V;
-}
-
-// Alias instruction to do FR32 or FR64 reg-to-reg copy using movaps. Upper
-// bits are disregarded.
-let neverHasSideEffects = 1 in {
-def FsMOVAPSrr : PSI<0x28, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src),
- "movaps\t{$src, $dst|$dst, $src}", []>;
-def FsMOVAPDrr : PDI<0x28, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src),
- "movapd\t{$src, $dst|$dst, $src}", []>;
-}
+def : Pat<(i32 (X86fgetsign FR32:$src)),
+ (MOVMSKPSrr32 (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FR32:$src,
+ sub_ss))>, Requires<[HasSSE1]>;
+def : Pat<(i64 (X86fgetsign FR32:$src)),
+ (MOVMSKPSrr64 (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FR32:$src,
+ sub_ss))>, Requires<[HasSSE1]>;
+def : Pat<(i32 (X86fgetsign FR64:$src)),
+ (MOVMSKPDrr32 (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FR64:$src,
+ sub_sd))>, Requires<[HasSSE2]>;
+def : Pat<(i64 (X86fgetsign FR64:$src)),
+ (MOVMSKPDrr64 (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FR64:$src,
+ sub_sd))>, Requires<[HasSSE2]>;
-// Alias instruction to load FR32 or FR64 from f128mem using movaps. Upper
-// bits are disregarded.
-let canFoldAsLoad = 1, isReMaterializable = 1 in {
-def FsMOVAPSrm : PSI<0x28, MRMSrcMem, (outs FR32:$dst), (ins f128mem:$src),
- "movaps\t{$src, $dst|$dst, $src}",
- [(set FR32:$dst, (alignedloadfsf32 addr:$src))]>;
-def FsMOVAPDrm : PDI<0x28, MRMSrcMem, (outs FR64:$dst), (ins f128mem:$src),
- "movapd\t{$src, $dst|$dst, $src}",
- [(set FR64:$dst, (alignedloadfsf64 addr:$src))]>;
+let Predicates = [HasAVX] in {
+ defm VMOVMSKPS : sse12_extr_sign_mask<VR128, int_x86_sse_movmsk_ps,
+ "movmskps", SSEPackedSingle>, TB, VEX;
+ defm VMOVMSKPD : sse12_extr_sign_mask<VR128, int_x86_sse2_movmsk_pd,
+ "movmskpd", SSEPackedDouble>, TB,
+ OpSize, VEX;
+ defm VMOVMSKPSY : sse12_extr_sign_mask<VR256, int_x86_avx_movmsk_ps_256,
+ "movmskps", SSEPackedSingle>, TB, VEX;
+ defm VMOVMSKPDY : sse12_extr_sign_mask<VR256, int_x86_avx_movmsk_pd_256,
+ "movmskpd", SSEPackedDouble>, TB,
+ OpSize, VEX;
+
+ def : Pat<(i32 (X86fgetsign FR32:$src)),
+ (VMOVMSKPSrr32 (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FR32:$src,
+ sub_ss))>;
+ def : Pat<(i64 (X86fgetsign FR32:$src)),
+ (VMOVMSKPSrr64 (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FR32:$src,
+ sub_ss))>;
+ def : Pat<(i32 (X86fgetsign FR64:$src)),
+ (VMOVMSKPDrr32 (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FR64:$src,
+ sub_sd))>;
+ def : Pat<(i64 (X86fgetsign FR64:$src)),
+ (VMOVMSKPDrr64 (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FR64:$src,
+ sub_sd))>;
+
+ // Assembler Only
+ def VMOVMSKPSr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src),
+ "movmskps\t{$src, $dst|$dst, $src}", [], SSEPackedSingle>, TB, VEX;
+ def VMOVMSKPDr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR128:$src),
+ "movmskpd\t{$src, $dst|$dst, $src}", [], SSEPackedDouble>, TB,
+ OpSize, VEX;
+ def VMOVMSKPSYr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR256:$src),
+ "movmskps\t{$src, $dst|$dst, $src}", [], SSEPackedSingle>, TB, VEX;
+ def VMOVMSKPDYr64r : PI<0x50, MRMSrcReg, (outs GR64:$dst), (ins VR256:$src),
+ "movmskpd\t{$src, $dst|$dst, $src}", [], SSEPackedDouble>, TB,
+ OpSize, VEX;
}
//===----------------------------------------------------------------------===//
@@ -1466,10 +2588,10 @@ def FsMOVAPDrm : PDI<0x28, MRMSrcMem, (outs FR64:$dst), (ins f128mem:$src),
multiclass sse12_fp_alias_pack_logical<bits<8> opc, string OpcodeStr,
SDNode OpNode> {
defm V#NAME#PS : sse12_fp_packed<opc, !strconcat(OpcodeStr, "ps"), OpNode,
- FR32, f32, f128mem, memopfsf32, SSEPackedSingle, 0>, VEX_4V;
+ FR32, f32, f128mem, memopfsf32, SSEPackedSingle, 0>, TB, VEX_4V;
defm V#NAME#PD : sse12_fp_packed<opc, !strconcat(OpcodeStr, "pd"), OpNode,
- FR64, f64, f128mem, memopfsf64, SSEPackedDouble, 0>, OpSize, VEX_4V;
+ FR64, f64, f128mem, memopfsf64, SSEPackedDouble, 0>, TB, OpSize, VEX_4V;
let Constraints = "$src1 = $dst" in {
defm PS : sse12_fp_packed<opc, !strconcat(OpcodeStr, "ps"), OpNode, FR32,
@@ -1494,21 +2616,22 @@ let neverHasSideEffects = 1, Pattern = []<dag>, isCommutable = 0 in
///
multiclass sse12_fp_packed_logical<bits<8> opc, string OpcodeStr,
SDNode OpNode> {
- let Pattern = []<dag> in {
- defm V#NAME#PS : sse12_fp_packed_logical_rm<opc, VR128, SSEPackedSingle,
- !strconcat(OpcodeStr, "ps"), f128mem,
- [(set VR128:$dst, (v2i64 (OpNode VR128:$src1, VR128:$src2)))],
- [(set VR128:$dst, (OpNode (bc_v2i64 (v4f32 VR128:$src1)),
- (memopv2i64 addr:$src2)))], 0>, VEX_4V;
-
- defm V#NAME#PD : sse12_fp_packed_logical_rm<opc, VR128, SSEPackedDouble,
- !strconcat(OpcodeStr, "pd"), f128mem,
- [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)),
- (bc_v2i64 (v2f64 VR128:$src2))))],
- [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)),
- (memopv2i64 addr:$src2)))], 0>,
- OpSize, VEX_4V;
- }
+ // In AVX no need to add a pattern for 128-bit logical rr ps, because they
+ // are all promoted to v2i64, and the patterns are covered by the int
+ // version. This is needed in SSE only, because v2i64 isn't supported on
+ // SSE1, but only on SSE2.
+ defm V#NAME#PS : sse12_fp_packed_logical_rm<opc, VR128, SSEPackedSingle,
+ !strconcat(OpcodeStr, "ps"), f128mem, [],
+ [(set VR128:$dst, (OpNode (bc_v2i64 (v4f32 VR128:$src1)),
+ (memopv2i64 addr:$src2)))], 0>, TB, VEX_4V;
+
+ defm V#NAME#PD : sse12_fp_packed_logical_rm<opc, VR128, SSEPackedDouble,
+ !strconcat(OpcodeStr, "pd"), f128mem,
+ [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)),
+ (bc_v2i64 (v2f64 VR128:$src2))))],
+ [(set VR128:$dst, (OpNode (bc_v2i64 (v2f64 VR128:$src1)),
+ (memopv2i64 addr:$src2)))], 0>,
+ TB, OpSize, VEX_4V;
let Constraints = "$src1 = $dst" in {
defm PS : sse12_fp_packed_logical_rm<opc, VR128, SSEPackedSingle,
!strconcat(OpcodeStr, "ps"), f128mem,
@@ -1533,7 +2656,7 @@ multiclass sse12_fp_packed_logical_y<bits<8> opc, string OpcodeStr,
!strconcat(OpcodeStr, "ps"), f256mem,
[(set VR256:$dst, (v4i64 (OpNode VR256:$src1, VR256:$src2)))],
[(set VR256:$dst, (OpNode (bc_v4i64 (v8f32 VR256:$src1)),
- (memopv4i64 addr:$src2)))], 0>, VEX_4V;
+ (memopv4i64 addr:$src2)))], 0>, TB, VEX_4V;
defm PDY : sse12_fp_packed_logical_rm<opc, VR256, SSEPackedDouble,
!strconcat(OpcodeStr, "pd"), f256mem,
@@ -1541,7 +2664,7 @@ multiclass sse12_fp_packed_logical_y<bits<8> opc, string OpcodeStr,
(bc_v4i64 (v4f64 VR256:$src2))))],
[(set VR256:$dst, (OpNode (bc_v4i64 (v4f64 VR256:$src1)),
(memopv4i64 addr:$src2)))], 0>,
- OpSize, VEX_4V;
+ TB, OpSize, VEX_4V;
}
// AVX 256-bit packed logical ops forms
@@ -1632,32 +2755,32 @@ multiclass basic_sse12_fp_binop_p_y_int<bits<8> opc, string OpcodeStr> {
// Binary Arithmetic instructions
defm VADD : basic_sse12_fp_binop_s<0x58, "add", fadd, 0>,
- basic_sse12_fp_binop_s_int<0x58, "add", 0>,
- basic_sse12_fp_binop_p<0x58, "add", fadd, 0>,
+ basic_sse12_fp_binop_s_int<0x58, "add", 0>, VEX_4V, VEX_LIG;
+defm VADD : basic_sse12_fp_binop_p<0x58, "add", fadd, 0>,
basic_sse12_fp_binop_p_y<0x58, "add", fadd>, VEX_4V;
defm VMUL : basic_sse12_fp_binop_s<0x59, "mul", fmul, 0>,
- basic_sse12_fp_binop_s_int<0x59, "mul", 0>,
- basic_sse12_fp_binop_p<0x59, "mul", fmul, 0>,
+ basic_sse12_fp_binop_s_int<0x59, "mul", 0>, VEX_4V, VEX_LIG;
+defm VMUL : basic_sse12_fp_binop_p<0x59, "mul", fmul, 0>,
basic_sse12_fp_binop_p_y<0x59, "mul", fmul>, VEX_4V;
let isCommutable = 0 in {
defm VSUB : basic_sse12_fp_binop_s<0x5C, "sub", fsub, 0>,
- basic_sse12_fp_binop_s_int<0x5C, "sub", 0>,
- basic_sse12_fp_binop_p<0x5C, "sub", fsub, 0>,
+ basic_sse12_fp_binop_s_int<0x5C, "sub", 0>, VEX_4V, VEX_LIG;
+ defm VSUB : basic_sse12_fp_binop_p<0x5C, "sub", fsub, 0>,
basic_sse12_fp_binop_p_y<0x5C, "sub", fsub>, VEX_4V;
defm VDIV : basic_sse12_fp_binop_s<0x5E, "div", fdiv, 0>,
- basic_sse12_fp_binop_s_int<0x5E, "div", 0>,
- basic_sse12_fp_binop_p<0x5E, "div", fdiv, 0>,
+ basic_sse12_fp_binop_s_int<0x5E, "div", 0>, VEX_4V, VEX_LIG;
+ defm VDIV : basic_sse12_fp_binop_p<0x5E, "div", fdiv, 0>,
basic_sse12_fp_binop_p_y<0x5E, "div", fdiv>, VEX_4V;
defm VMAX : basic_sse12_fp_binop_s<0x5F, "max", X86fmax, 0>,
- basic_sse12_fp_binop_s_int<0x5F, "max", 0>,
- basic_sse12_fp_binop_p<0x5F, "max", X86fmax, 0>,
+ basic_sse12_fp_binop_s_int<0x5F, "max", 0>, VEX_4V, VEX_LIG;
+ defm VMAX : basic_sse12_fp_binop_p<0x5F, "max", X86fmax, 0>,
basic_sse12_fp_binop_p_int<0x5F, "max", 0>,
basic_sse12_fp_binop_p_y<0x5F, "max", X86fmax>,
basic_sse12_fp_binop_p_y_int<0x5F, "max">, VEX_4V;
defm VMIN : basic_sse12_fp_binop_s<0x5D, "min", X86fmin, 0>,
- basic_sse12_fp_binop_s_int<0x5D, "min", 0>,
- basic_sse12_fp_binop_p<0x5D, "min", X86fmin, 0>,
+ basic_sse12_fp_binop_s_int<0x5D, "min", 0>, VEX_4V, VEX_LIG;
+ defm VMIN : basic_sse12_fp_binop_p<0x5D, "min", X86fmin, 0>,
basic_sse12_fp_binop_p_int<0x5D, "min", 0>,
basic_sse12_fp_binop_p_y_int<0x5D, "min">,
basic_sse12_fp_binop_p_y<0x5D, "min", X86fmin>, VEX_4V;
@@ -1720,23 +2843,18 @@ multiclass sse1_fp_unop_s<bits<8> opc, string OpcodeStr,
}
/// sse1_fp_unop_s_avx - AVX SSE1 unops in scalar form.
-multiclass sse1_fp_unop_s_avx<bits<8> opc, string OpcodeStr,
- SDNode OpNode, Intrinsic F32Int> {
+multiclass sse1_fp_unop_s_avx<bits<8> opc, string OpcodeStr> {
def SSr : SSI<opc, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src1, FR32:$src2),
!strconcat(OpcodeStr,
"ss\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>;
- def SSm : I<opc, MRMSrcMem, (outs FR32:$dst), (ins FR32:$src1, f32mem:$src2),
- !strconcat(OpcodeStr,
- "ss\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
- []>, XS, Requires<[HasAVX, OptForSize]>;
- def SSr_Int : SSI<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
+ let mayLoad = 1 in
+ def SSm : SSI<opc, MRMSrcMem, (outs FR32:$dst), (ins FR32:$src1,f32mem:$src2),
!strconcat(OpcodeStr,
- "ss\t{$src, $dst, $dst|$dst, $dst, $src}"),
- [(set VR128:$dst, (F32Int VR128:$src))]>;
- def SSm_Int : SSI<opc, MRMSrcMem, (outs VR128:$dst), (ins ssmem:$src),
+ "ss\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>;
+ def SSm_Int : SSI<opc, MRMSrcMem, (outs VR128:$dst),
+ (ins ssmem:$src1, VR128:$src2),
!strconcat(OpcodeStr,
- "ss\t{$src, $dst, $dst|$dst, $dst, $src}"),
- [(set VR128:$dst, (F32Int sse_load_f32:$src))]>;
+ "ss\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>;
}
/// sse1_fp_unop_p - SSE1 unops in packed form.
@@ -1801,21 +2919,17 @@ multiclass sse2_fp_unop_s<bits<8> opc, string OpcodeStr,
}
/// sse2_fp_unop_s_avx - AVX SSE2 unops in scalar form.
-multiclass sse2_fp_unop_s_avx<bits<8> opc, string OpcodeStr,
- SDNode OpNode, Intrinsic F64Int> {
+multiclass sse2_fp_unop_s_avx<bits<8> opc, string OpcodeStr> {
def SDr : SDI<opc, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src1, FR64:$src2),
!strconcat(OpcodeStr,
"sd\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>;
- def SDm : SDI<opc, MRMSrcMem, (outs FR64:$dst),
- (ins FR64:$src1, f64mem:$src2),
+ def SDm : SDI<opc, MRMSrcMem, (outs FR64:$dst), (ins FR64:$src1,f64mem:$src2),
+ !strconcat(OpcodeStr,
+ "sd\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>;
+ def SDm_Int : SDI<opc, MRMSrcMem, (outs VR128:$dst),
+ (ins VR128:$src1, sdmem:$src2),
!strconcat(OpcodeStr,
"sd\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>;
- def SDr_Int : SDI<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
- !strconcat(OpcodeStr, "sd\t{$src, $dst, $dst|$dst, $dst, $src}"),
- [(set VR128:$dst, (F64Int VR128:$src))]>;
- def SDm_Int : SDI<opc, MRMSrcMem, (outs VR128:$dst), (ins sdmem:$src),
- !strconcat(OpcodeStr, "sd\t{$src, $dst, $dst|$dst, $dst, $src}"),
- [(set VR128:$dst, (F64Int sse_load_f64:$src))]>;
}
/// sse2_fp_unop_p - SSE2 unops in vector forms.
@@ -1863,9 +2977,8 @@ multiclass sse2_fp_unop_p_y_int<bits<8> opc, string OpcodeStr,
let Predicates = [HasAVX] in {
// Square root.
- defm VSQRT : sse1_fp_unop_s_avx<0x51, "vsqrt", fsqrt, int_x86_sse_sqrt_ss>,
- sse2_fp_unop_s_avx<0x51, "vsqrt", fsqrt, int_x86_sse2_sqrt_sd>,
- VEX_4V;
+ defm VSQRT : sse1_fp_unop_s_avx<0x51, "vsqrt">,
+ sse2_fp_unop_s_avx<0x51, "vsqrt">, VEX_4V, VEX_LIG;
defm VSQRT : sse1_fp_unop_p<0x51, "vsqrt", fsqrt>,
sse2_fp_unop_p<0x51, "vsqrt", fsqrt>,
@@ -1879,21 +2992,76 @@ let Predicates = [HasAVX] in {
// Reciprocal approximations. Note that these typically require refinement
// in order to obtain suitable precision.
- defm VRSQRT : sse1_fp_unop_s_avx<0x52, "vrsqrt", X86frsqrt,
- int_x86_sse_rsqrt_ss>, VEX_4V;
+ defm VRSQRT : sse1_fp_unop_s_avx<0x52, "vrsqrt">, VEX_4V, VEX_LIG;
defm VRSQRT : sse1_fp_unop_p<0x52, "vrsqrt", X86frsqrt>,
sse1_fp_unop_p_y<0x52, "vrsqrt", X86frsqrt>,
sse1_fp_unop_p_y_int<0x52, "vrsqrt", int_x86_avx_rsqrt_ps_256>,
sse1_fp_unop_p_int<0x52, "vrsqrt", int_x86_sse_rsqrt_ps>, VEX;
- defm VRCP : sse1_fp_unop_s_avx<0x53, "vrcp", X86frcp, int_x86_sse_rcp_ss>,
- VEX_4V;
+ defm VRCP : sse1_fp_unop_s_avx<0x53, "vrcp">, VEX_4V, VEX_LIG;
defm VRCP : sse1_fp_unop_p<0x53, "vrcp", X86frcp>,
sse1_fp_unop_p_y<0x53, "vrcp", X86frcp>,
sse1_fp_unop_p_y_int<0x53, "vrcp", int_x86_avx_rcp_ps_256>,
sse1_fp_unop_p_int<0x53, "vrcp", int_x86_sse_rcp_ps>, VEX;
}
+def : Pat<(f32 (fsqrt FR32:$src)),
+ (VSQRTSSr (f32 (IMPLICIT_DEF)), FR32:$src)>, Requires<[HasAVX]>;
+def : Pat<(f32 (fsqrt (load addr:$src))),
+ (VSQRTSSm (f32 (IMPLICIT_DEF)), addr:$src)>,
+ Requires<[HasAVX, OptForSize]>;
+def : Pat<(f64 (fsqrt FR64:$src)),
+ (VSQRTSDr (f64 (IMPLICIT_DEF)), FR64:$src)>, Requires<[HasAVX]>;
+def : Pat<(f64 (fsqrt (load addr:$src))),
+ (VSQRTSDm (f64 (IMPLICIT_DEF)), addr:$src)>,
+ Requires<[HasAVX, OptForSize]>;
+
+def : Pat<(f32 (X86frsqrt FR32:$src)),
+ (VRSQRTSSr (f32 (IMPLICIT_DEF)), FR32:$src)>, Requires<[HasAVX]>;
+def : Pat<(f32 (X86frsqrt (load addr:$src))),
+ (VRSQRTSSm (f32 (IMPLICIT_DEF)), addr:$src)>,
+ Requires<[HasAVX, OptForSize]>;
+
+def : Pat<(f32 (X86frcp FR32:$src)),
+ (VRCPSSr (f32 (IMPLICIT_DEF)), FR32:$src)>, Requires<[HasAVX]>;
+def : Pat<(f32 (X86frcp (load addr:$src))),
+ (VRCPSSm (f32 (IMPLICIT_DEF)), addr:$src)>,
+ Requires<[HasAVX, OptForSize]>;
+
+let Predicates = [HasAVX] in {
+ def : Pat<(int_x86_sse_sqrt_ss VR128:$src),
+ (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)),
+ (VSQRTSSr (f32 (IMPLICIT_DEF)),
+ (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss)),
+ sub_ss)>;
+ def : Pat<(int_x86_sse_sqrt_ss sse_load_f32:$src),
+ (VSQRTSSm_Int (v4f32 (IMPLICIT_DEF)), sse_load_f32:$src)>;
+
+ def : Pat<(int_x86_sse2_sqrt_sd VR128:$src),
+ (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)),
+ (VSQRTSDr (f64 (IMPLICIT_DEF)),
+ (EXTRACT_SUBREG (v2f64 VR128:$src), sub_sd)),
+ sub_sd)>;
+ def : Pat<(int_x86_sse2_sqrt_sd sse_load_f64:$src),
+ (VSQRTSDm_Int (v2f64 (IMPLICIT_DEF)), sse_load_f64:$src)>;
+
+ def : Pat<(int_x86_sse_rsqrt_ss VR128:$src),
+ (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)),
+ (VRSQRTSSr (f32 (IMPLICIT_DEF)),
+ (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss)),
+ sub_ss)>;
+ def : Pat<(int_x86_sse_rsqrt_ss sse_load_f32:$src),
+ (VRSQRTSSm_Int (v4f32 (IMPLICIT_DEF)), sse_load_f32:$src)>;
+
+ def : Pat<(int_x86_sse_rcp_ss VR128:$src),
+ (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)),
+ (VRCPSSr (f32 (IMPLICIT_DEF)),
+ (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss)),
+ sub_ss)>;
+ def : Pat<(int_x86_sse_rcp_ss sse_load_f32:$src),
+ (VRCPSSm_Int (v4f32 (IMPLICIT_DEF)), sse_load_f32:$src)>;
+}
+
// Square root.
defm SQRT : sse1_fp_unop_s<0x51, "sqrt", fsqrt, int_x86_sse_sqrt_ss>,
sse1_fp_unop_p<0x51, "sqrt", fsqrt>,
@@ -1992,7 +3160,7 @@ def MOVNTDQmr : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src),
[(alignednontemporalstore (v4f32 VR128:$src), addr:$dst)]>;
def : Pat<(alignednontemporalstore (v2i64 VR128:$src), addr:$dst),
- (MOVNTDQmr addr:$dst, VR128:$src)>;
+ (MOVNTDQmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>;
// There is no AVX form for instructions below this point
def MOVNTImr : I<0xC3, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src),
@@ -2006,7 +3174,7 @@ def MOVNTI_64mr : RI<0xC3, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src),
}
//===----------------------------------------------------------------------===//
-// SSE 1 & 2 - Misc Instructions (No AVX form)
+// SSE 1 & 2 - Prefetch and memory fence
//===----------------------------------------------------------------------===//
// Prefetch intrinsic.
@@ -2019,66 +3187,26 @@ def PREFETCHT2 : PSI<0x18, MRM3m, (outs), (ins i8mem:$src),
def PREFETCHNTA : PSI<0x18, MRM0m, (outs), (ins i8mem:$src),
"prefetchnta\t$src", [(prefetch addr:$src, imm, (i32 0), (i32 1))]>;
-// Load, store, and memory fence
-def SFENCE : I<0xAE, MRM_F8, (outs), (ins), "sfence", [(int_x86_sse_sfence)]>,
- TB, Requires<[HasSSE1]>;
-def : Pat<(X86SFence), (SFENCE)>;
-
-// Alias instructions that map zero vector to pxor / xorp* for sse.
-// We set canFoldAsLoad because this can be converted to a constant-pool
-// load of an all-zeros value if folding it would be beneficial.
-// FIXME: Change encoding to pseudo! This is blocked right now by the x86
-// JIT implementation, it does not expand the instructions below like
-// X86MCInstLower does.
-let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1,
- isCodeGenOnly = 1 in {
-def V_SET0PS : PSI<0x57, MRMInitReg, (outs VR128:$dst), (ins), "",
- [(set VR128:$dst, (v4f32 immAllZerosV))]>;
-def V_SET0PD : PDI<0x57, MRMInitReg, (outs VR128:$dst), (ins), "",
- [(set VR128:$dst, (v2f64 immAllZerosV))]>;
-let ExeDomain = SSEPackedInt in
-def V_SET0PI : PDI<0xEF, MRMInitReg, (outs VR128:$dst), (ins), "",
- [(set VR128:$dst, (v4i32 immAllZerosV))]>;
-}
-
-// The same as done above but for AVX. The 128-bit versions are the
-// same, but re-encoded. The 256-bit does not support PI version, and
-// doesn't need it because on sandy bridge the register is set to zero
-// at the rename stage without using any execution unit, so SET0PSY
-// and SET0PDY can be used for vector int instructions without penalty
-// FIXME: Change encoding to pseudo! This is blocked right now by the x86
-// JIT implementatioan, it does not expand the instructions below like
-// X86MCInstLower does.
-let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1,
- isCodeGenOnly = 1, Predicates = [HasAVX] in {
-def AVX_SET0PS : PSI<0x57, MRMInitReg, (outs VR128:$dst), (ins), "",
- [(set VR128:$dst, (v4f32 immAllZerosV))]>, VEX_4V;
-def AVX_SET0PD : PDI<0x57, MRMInitReg, (outs VR128:$dst), (ins), "",
- [(set VR128:$dst, (v2f64 immAllZerosV))]>, VEX_4V;
-def AVX_SET0PSY : PSI<0x57, MRMInitReg, (outs VR256:$dst), (ins), "",
- [(set VR256:$dst, (v8f32 immAllZerosV))]>, VEX_4V;
-def AVX_SET0PDY : PDI<0x57, MRMInitReg, (outs VR256:$dst), (ins), "",
- [(set VR256:$dst, (v4f64 immAllZerosV))]>, VEX_4V;
-let ExeDomain = SSEPackedInt in
-def AVX_SET0PI : PDI<0xEF, MRMInitReg, (outs VR128:$dst), (ins), "",
- [(set VR128:$dst, (v4i32 immAllZerosV))]>;
-}
+// Flush cache
+def CLFLUSH : I<0xAE, MRM7m, (outs), (ins i8mem:$src),
+ "clflush\t$src", [(int_x86_sse2_clflush addr:$src)]>,
+ TB, Requires<[HasSSE2]>;
-def : Pat<(v2i64 immAllZerosV), (V_SET0PI)>;
-def : Pat<(v8i16 immAllZerosV), (V_SET0PI)>;
-def : Pat<(v16i8 immAllZerosV), (V_SET0PI)>;
+// Pause. This "instruction" is encoded as "rep; nop", so even though it
+// was introduced with SSE2, it's backward compatible.
+def PAUSE : I<0x90, RawFrm, (outs), (ins), "pause", []>, REP;
-def : Pat<(f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))),
- (f32 (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss))>;
+// Load, store, and memory fence
+def SFENCE : I<0xAE, MRM_F8, (outs), (ins),
+ "sfence", [(int_x86_sse_sfence)]>, TB, Requires<[HasSSE1]>;
+def LFENCE : I<0xAE, MRM_E8, (outs), (ins),
+ "lfence", [(int_x86_sse2_lfence)]>, TB, Requires<[HasSSE2]>;
+def MFENCE : I<0xAE, MRM_F0, (outs), (ins),
+ "mfence", [(int_x86_sse2_mfence)]>, TB, Requires<[HasSSE2]>;
-// FIXME: According to the intel manual, DEST[127:64] <- SRC1[127:64], while
-// in the non-AVX version bits 127:64 aren't touched. Find a better way to
-// represent this instead of always zeroing SRC1. One possible solution is
-// to represent the instruction w/ something similar as the "$src1 = $dst"
-// constraint but without the tied operands.
-def : Pat<(extloadf32 addr:$src),
- (VCVTSS2SDrm (f32 (EXTRACT_SUBREG (AVX_SET0PS), sub_ss)), addr:$src)>,
- Requires<[HasAVX, OptForSpeed]>;
+def : Pat<(X86SFence), (SFENCE)>;
+def : Pat<(X86LFence), (LFENCE)>;
+def : Pat<(X86MFence), (MFENCE)>;
//===----------------------------------------------------------------------===//
// SSE 1 & 2 - Load/Store XCSR register
@@ -2106,10 +3234,22 @@ def VMOVDQArr : VPDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
def VMOVDQAYrr : VPDI<0x6F, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src),
"movdqa\t{$src, $dst|$dst, $src}", []>, VEX;
}
-def VMOVDQUrr : VPDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
- "movdqu\t{$src, $dst|$dst, $src}", []>, XS, VEX;
-def VMOVDQUYrr : VPDI<0x6F, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src),
- "movdqu\t{$src, $dst|$dst, $src}", []>, XS, VEX;
+def VMOVDQUrr : VSSI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
+ "movdqu\t{$src, $dst|$dst, $src}", []>, VEX;
+def VMOVDQUYrr : VSSI<0x6F, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src),
+ "movdqu\t{$src, $dst|$dst, $src}", []>, VEX;
+
+// For Disassembler
+let isCodeGenOnly = 1 in {
+def VMOVDQArr_REV : VPDI<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src),
+ "movdqa\t{$src, $dst|$dst, $src}", []>, VEX;
+def VMOVDQAYrr_REV : VPDI<0x7F, MRMDestReg, (outs VR256:$dst), (ins VR256:$src),
+ "movdqa\t{$src, $dst|$dst, $src}", []>, VEX;
+def VMOVDQUrr_REV : VSSI<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src),
+ "movdqu\t{$src, $dst|$dst, $src}", []>, VEX;
+def VMOVDQUYrr_REV : VSSI<0x7F, MRMDestReg, (outs VR256:$dst), (ins VR256:$src),
+ "movdqu\t{$src, $dst|$dst, $src}", []>, VEX;
+}
let canFoldAsLoad = 1, mayLoad = 1 in {
def VMOVDQArm : VPDI<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src),
@@ -2147,6 +3287,16 @@ def MOVDQUrr : I<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"movdqu\t{$src, $dst|$dst, $src}",
[]>, XS, Requires<[HasSSE2]>;
+// For Disassembler
+let isCodeGenOnly = 1 in {
+def MOVDQArr_REV : PDI<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src),
+ "movdqa\t{$src, $dst|$dst, $src}", []>;
+
+def MOVDQUrr_REV : I<0x7F, MRMDestReg, (outs VR128:$dst), (ins VR128:$src),
+ "movdqu\t{$src, $dst|$dst, $src}",
+ []>, XS, Requires<[HasSSE2]>;
+}
+
let canFoldAsLoad = 1, mayLoad = 1 in {
def MOVDQArm : PDI<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src),
"movdqa\t{$src, $dst|$dst, $src}",
@@ -2180,9 +3330,11 @@ def MOVDQUmr_Int : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src),
} // ExeDomain = SSEPackedInt
-def : Pat<(int_x86_avx_loadu_dq_256 addr:$src), (VMOVDQUYrm addr:$src)>;
-def : Pat<(int_x86_avx_storeu_dq_256 addr:$dst, VR256:$src),
- (VMOVDQUYmr addr:$dst, VR256:$src)>;
+let Predicates = [HasAVX] in {
+ def : Pat<(int_x86_avx_loadu_dq_256 addr:$src), (VMOVDQUYrm addr:$src)>;
+ def : Pat<(int_x86_avx_storeu_dq_256 addr:$dst, VR256:$src),
+ (VMOVDQUYmr addr:$dst, VR256:$src)>;
+}
//===---------------------------------------------------------------------===//
// SSE2 - Packed Integer Arithmetic Instructions
@@ -2415,15 +3567,14 @@ let ExeDomain = SSEPackedInt in {
def VPANDNrr : PDI<0xDF, MRMSrcReg,
(outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
"vpandn\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set VR128:$dst, (v2i64 (and (vnot VR128:$src1),
- VR128:$src2)))]>, VEX_4V;
+ [(set VR128:$dst,
+ (v2i64 (X86andnp VR128:$src1, VR128:$src2)))]>,VEX_4V;
def VPANDNrm : PDI<0xDF, MRMSrcMem,
(outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
"vpandn\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set VR128:$dst, (v2i64 (and (vnot VR128:$src1),
- (memopv2i64 addr:$src2))))]>,
- VEX_4V;
+ [(set VR128:$dst, (X86andnp VR128:$src1,
+ (memopv2i64 addr:$src2)))]>, VEX_4V;
}
}
@@ -2527,6 +3678,32 @@ let Predicates = [HasAVX] in {
0>, VEX_4V;
defm VPCMPGTD : PDI_binop_rm_int<0x66, "vpcmpgtd", int_x86_sse2_pcmpgt_d, 0,
0>, VEX_4V;
+
+ def : Pat<(v16i8 (X86pcmpeqb VR128:$src1, VR128:$src2)),
+ (VPCMPEQBrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v16i8 (X86pcmpeqb VR128:$src1, (memop addr:$src2))),
+ (VPCMPEQBrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v8i16 (X86pcmpeqw VR128:$src1, VR128:$src2)),
+ (VPCMPEQWrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v8i16 (X86pcmpeqw VR128:$src1, (memop addr:$src2))),
+ (VPCMPEQWrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4i32 (X86pcmpeqd VR128:$src1, VR128:$src2)),
+ (VPCMPEQDrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v4i32 (X86pcmpeqd VR128:$src1, (memop addr:$src2))),
+ (VPCMPEQDrm VR128:$src1, addr:$src2)>;
+
+ def : Pat<(v16i8 (X86pcmpgtb VR128:$src1, VR128:$src2)),
+ (VPCMPGTBrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v16i8 (X86pcmpgtb VR128:$src1, (memop addr:$src2))),
+ (VPCMPGTBrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v8i16 (X86pcmpgtw VR128:$src1, VR128:$src2)),
+ (VPCMPGTWrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v8i16 (X86pcmpgtw VR128:$src1, (memop addr:$src2))),
+ (VPCMPGTWrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4i32 (X86pcmpgtd VR128:$src1, VR128:$src2)),
+ (VPCMPGTDrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v4i32 (X86pcmpgtd VR128:$src1, (memop addr:$src2))),
+ (VPCMPGTDrm VR128:$src1, addr:$src2)>;
}
let Constraints = "$src1 = $dst" in {
@@ -2538,31 +3715,33 @@ let Constraints = "$src1 = $dst" in {
defm PCMPGTD : PDI_binop_rm_int<0x66, "pcmpgtd", int_x86_sse2_pcmpgt_d>;
} // Constraints = "$src1 = $dst"
-def : Pat<(v16i8 (X86pcmpeqb VR128:$src1, VR128:$src2)),
- (PCMPEQBrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v16i8 (X86pcmpeqb VR128:$src1, (memop addr:$src2))),
- (PCMPEQBrm VR128:$src1, addr:$src2)>;
-def : Pat<(v8i16 (X86pcmpeqw VR128:$src1, VR128:$src2)),
- (PCMPEQWrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v8i16 (X86pcmpeqw VR128:$src1, (memop addr:$src2))),
- (PCMPEQWrm VR128:$src1, addr:$src2)>;
-def : Pat<(v4i32 (X86pcmpeqd VR128:$src1, VR128:$src2)),
- (PCMPEQDrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v4i32 (X86pcmpeqd VR128:$src1, (memop addr:$src2))),
- (PCMPEQDrm VR128:$src1, addr:$src2)>;
-
-def : Pat<(v16i8 (X86pcmpgtb VR128:$src1, VR128:$src2)),
- (PCMPGTBrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v16i8 (X86pcmpgtb VR128:$src1, (memop addr:$src2))),
- (PCMPGTBrm VR128:$src1, addr:$src2)>;
-def : Pat<(v8i16 (X86pcmpgtw VR128:$src1, VR128:$src2)),
- (PCMPGTWrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v8i16 (X86pcmpgtw VR128:$src1, (memop addr:$src2))),
- (PCMPGTWrm VR128:$src1, addr:$src2)>;
-def : Pat<(v4i32 (X86pcmpgtd VR128:$src1, VR128:$src2)),
- (PCMPGTDrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v4i32 (X86pcmpgtd VR128:$src1, (memop addr:$src2))),
- (PCMPGTDrm VR128:$src1, addr:$src2)>;
+let Predicates = [HasSSE2] in {
+ def : Pat<(v16i8 (X86pcmpeqb VR128:$src1, VR128:$src2)),
+ (PCMPEQBrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v16i8 (X86pcmpeqb VR128:$src1, (memop addr:$src2))),
+ (PCMPEQBrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v8i16 (X86pcmpeqw VR128:$src1, VR128:$src2)),
+ (PCMPEQWrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v8i16 (X86pcmpeqw VR128:$src1, (memop addr:$src2))),
+ (PCMPEQWrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4i32 (X86pcmpeqd VR128:$src1, VR128:$src2)),
+ (PCMPEQDrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v4i32 (X86pcmpeqd VR128:$src1, (memop addr:$src2))),
+ (PCMPEQDrm VR128:$src1, addr:$src2)>;
+
+ def : Pat<(v16i8 (X86pcmpgtb VR128:$src1, VR128:$src2)),
+ (PCMPGTBrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v16i8 (X86pcmpgtb VR128:$src1, (memop addr:$src2))),
+ (PCMPGTBrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v8i16 (X86pcmpgtw VR128:$src1, VR128:$src2)),
+ (PCMPGTWrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v8i16 (X86pcmpgtw VR128:$src1, (memop addr:$src2))),
+ (PCMPGTWrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v4i32 (X86pcmpgtd VR128:$src1, VR128:$src2)),
+ (PCMPGTDrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v4i32 (X86pcmpgtd VR128:$src1, (memop addr:$src2))),
+ (PCMPGTDrm VR128:$src1, addr:$src2)>;
+}
//===---------------------------------------------------------------------===//
// SSE2 - Packed Integer Pack Instructions
@@ -2608,7 +3787,7 @@ def mi : Ii8<0x70, MRMSrcMem,
let Predicates = [HasAVX] in {
let AddedComplexity = 5 in
- defm VPSHUFD : sse2_pshuffle<"vpshufd", v4i32, pshufd, bc_v4i32>, OpSize,
+ defm VPSHUFD : sse2_pshuffle<"vpshufd", v4i32, pshufd, bc_v4i32>, TB, OpSize,
VEX;
// SSE2 with ImmT == Imm8 and XS prefix.
@@ -2618,6 +3797,34 @@ let Predicates = [HasAVX] in {
// SSE2 with ImmT == Imm8 and XD prefix.
defm VPSHUFLW : sse2_pshuffle<"vpshuflw", v8i16, pshuflw, bc_v8i16>, XD,
VEX;
+
+ let AddedComplexity = 5 in
+ def : Pat<(v4f32 (pshufd:$src2 VR128:$src1, (undef))),
+ (VPSHUFDri VR128:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>;
+ // Unary v4f32 shuffle with VPSHUF* in order to fold a load.
+ def : Pat<(pshufd:$src2 (bc_v4i32 (memopv4f32 addr:$src1)), (undef)),
+ (VPSHUFDmi addr:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>;
+
+ def : Pat<(v4i32 (X86PShufd (bc_v4i32 (memopv2i64 addr:$src1)),
+ (i8 imm:$imm))),
+ (VPSHUFDmi addr:$src1, imm:$imm)>;
+ def : Pat<(v4i32 (X86PShufd (bc_v4i32 (memopv4f32 addr:$src1)),
+ (i8 imm:$imm))),
+ (VPSHUFDmi addr:$src1, imm:$imm)>;
+ def : Pat<(v4f32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
+ (VPSHUFDri VR128:$src1, imm:$imm)>;
+ def : Pat<(v4i32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
+ (VPSHUFDri VR128:$src1, imm:$imm)>;
+ def : Pat<(v8i16 (X86PShufhw VR128:$src, (i8 imm:$imm))),
+ (VPSHUFHWri VR128:$src, imm:$imm)>;
+ def : Pat<(v8i16 (X86PShufhw (bc_v8i16 (memopv2i64 addr:$src)),
+ (i8 imm:$imm))),
+ (VPSHUFHWmi addr:$src, imm:$imm)>;
+ def : Pat<(v8i16 (X86PShuflw VR128:$src, (i8 imm:$imm))),
+ (VPSHUFLWri VR128:$src, imm:$imm)>;
+ def : Pat<(v8i16 (X86PShuflw (bc_v8i16 (memopv2i64 addr:$src)),
+ (i8 imm:$imm))),
+ (VPSHUFLWmi addr:$src, imm:$imm)>;
}
let Predicates = [HasSSE2] in {
@@ -2629,6 +3836,34 @@ let Predicates = [HasSSE2] in {
// SSE2 with ImmT == Imm8 and XD prefix.
defm PSHUFLW : sse2_pshuffle<"pshuflw", v8i16, pshuflw, bc_v8i16>, XD;
+
+ let AddedComplexity = 5 in
+ def : Pat<(v4f32 (pshufd:$src2 VR128:$src1, (undef))),
+ (PSHUFDri VR128:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>;
+ // Unary v4f32 shuffle with PSHUF* in order to fold a load.
+ def : Pat<(pshufd:$src2 (bc_v4i32 (memopv4f32 addr:$src1)), (undef)),
+ (PSHUFDmi addr:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>;
+
+ def : Pat<(v4i32 (X86PShufd (bc_v4i32 (memopv2i64 addr:$src1)),
+ (i8 imm:$imm))),
+ (PSHUFDmi addr:$src1, imm:$imm)>;
+ def : Pat<(v4i32 (X86PShufd (bc_v4i32 (memopv4f32 addr:$src1)),
+ (i8 imm:$imm))),
+ (PSHUFDmi addr:$src1, imm:$imm)>;
+ def : Pat<(v4f32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
+ (PSHUFDri VR128:$src1, imm:$imm)>;
+ def : Pat<(v4i32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
+ (PSHUFDri VR128:$src1, imm:$imm)>;
+ def : Pat<(v8i16 (X86PShufhw VR128:$src, (i8 imm:$imm))),
+ (PSHUFHWri VR128:$src, imm:$imm)>;
+ def : Pat<(v8i16 (X86PShufhw (bc_v8i16 (memopv2i64 addr:$src)),
+ (i8 imm:$imm))),
+ (PSHUFHWmi addr:$src, imm:$imm)>;
+ def : Pat<(v8i16 (X86PShuflw VR128:$src, (i8 imm:$imm))),
+ (PSHUFLWri VR128:$src, imm:$imm)>;
+ def : Pat<(v8i16 (X86PShuflw (bc_v8i16 (memopv2i64 addr:$src)),
+ (i8 imm:$imm))),
+ (PSHUFLWmi addr:$src, imm:$imm)>;
}
//===---------------------------------------------------------------------===//
@@ -2637,71 +3872,69 @@ let Predicates = [HasSSE2] in {
let ExeDomain = SSEPackedInt in {
multiclass sse2_unpack<bits<8> opc, string OpcodeStr, ValueType vt,
- PatFrag unp_frag, PatFrag bc_frag, bit Is2Addr = 1> {
+ SDNode OpNode, PatFrag bc_frag, bit Is2Addr = 1> {
def rr : PDI<opc, MRMSrcReg,
(outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
!if(Is2Addr,
!strconcat(OpcodeStr,"\t{$src2, $dst|$dst, $src2}"),
!strconcat(OpcodeStr,"\t{$src2, $src1, $dst|$dst, $src1, $src2}")),
- [(set VR128:$dst, (vt (unp_frag VR128:$src1, VR128:$src2)))]>;
+ [(set VR128:$dst, (vt (OpNode VR128:$src1, VR128:$src2)))]>;
def rm : PDI<opc, MRMSrcMem,
(outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
!if(Is2Addr,
!strconcat(OpcodeStr,"\t{$src2, $dst|$dst, $src2}"),
!strconcat(OpcodeStr,"\t{$src2, $src1, $dst|$dst, $src1, $src2}")),
- [(set VR128:$dst, (unp_frag VR128:$src1,
+ [(set VR128:$dst, (OpNode VR128:$src1,
(bc_frag (memopv2i64
addr:$src2))))]>;
}
let Predicates = [HasAVX] in {
- defm VPUNPCKLBW : sse2_unpack<0x60, "vpunpcklbw", v16i8, unpckl, bc_v16i8,
- 0>, VEX_4V;
- defm VPUNPCKLWD : sse2_unpack<0x61, "vpunpcklwd", v8i16, unpckl, bc_v8i16,
- 0>, VEX_4V;
- defm VPUNPCKLDQ : sse2_unpack<0x62, "vpunpckldq", v4i32, unpckl, bc_v4i32,
- 0>, VEX_4V;
+ defm VPUNPCKLBW : sse2_unpack<0x60, "vpunpcklbw", v16i8, X86Punpcklbw,
+ bc_v16i8, 0>, VEX_4V;
+ defm VPUNPCKLWD : sse2_unpack<0x61, "vpunpcklwd", v8i16, X86Punpcklwd,
+ bc_v8i16, 0>, VEX_4V;
+ defm VPUNPCKLDQ : sse2_unpack<0x62, "vpunpckldq", v4i32, X86Punpckldq,
+ bc_v4i32, 0>, VEX_4V;
/// FIXME: we could eliminate this and use sse2_unpack instead if tblgen
/// knew to collapse (bitconvert VT to VT) into its operand.
def VPUNPCKLQDQrr : PDI<0x6C, MRMSrcReg,
- (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
- "vpunpcklqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set VR128:$dst,
- (v2i64 (unpckl VR128:$src1, VR128:$src2)))]>, VEX_4V;
+ (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
+ "vpunpcklqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set VR128:$dst, (v2i64 (X86Punpcklqdq VR128:$src1,
+ VR128:$src2)))]>, VEX_4V;
def VPUNPCKLQDQrm : PDI<0x6C, MRMSrcMem,
- (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
- "vpunpcklqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set VR128:$dst,
- (v2i64 (unpckl VR128:$src1,
- (memopv2i64 addr:$src2))))]>, VEX_4V;
-
- defm VPUNPCKHBW : sse2_unpack<0x68, "vpunpckhbw", v16i8, unpckh, bc_v16i8,
- 0>, VEX_4V;
- defm VPUNPCKHWD : sse2_unpack<0x69, "vpunpckhwd", v8i16, unpckh, bc_v8i16,
- 0>, VEX_4V;
- defm VPUNPCKHDQ : sse2_unpack<0x6A, "vpunpckhdq", v4i32, unpckh, bc_v4i32,
- 0>, VEX_4V;
+ (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
+ "vpunpcklqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set VR128:$dst, (v2i64 (X86Punpcklqdq VR128:$src1,
+ (memopv2i64 addr:$src2))))]>, VEX_4V;
+
+ defm VPUNPCKHBW : sse2_unpack<0x68, "vpunpckhbw", v16i8, X86Punpckhbw,
+ bc_v16i8, 0>, VEX_4V;
+ defm VPUNPCKHWD : sse2_unpack<0x69, "vpunpckhwd", v8i16, X86Punpckhwd,
+ bc_v8i16, 0>, VEX_4V;
+ defm VPUNPCKHDQ : sse2_unpack<0x6A, "vpunpckhdq", v4i32, X86Punpckhdq,
+ bc_v4i32, 0>, VEX_4V;
/// FIXME: we could eliminate this and use sse2_unpack instead if tblgen
/// knew to collapse (bitconvert VT to VT) into its operand.
def VPUNPCKHQDQrr : PDI<0x6D, MRMSrcReg,
- (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
- "vpunpckhqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set VR128:$dst,
- (v2i64 (unpckh VR128:$src1, VR128:$src2)))]>, VEX_4V;
+ (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
+ "vpunpckhqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set VR128:$dst, (v2i64 (X86Punpckhqdq VR128:$src1,
+ VR128:$src2)))]>, VEX_4V;
def VPUNPCKHQDQrm : PDI<0x6D, MRMSrcMem,
- (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
- "vpunpckhqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set VR128:$dst,
- (v2i64 (unpckh VR128:$src1,
- (memopv2i64 addr:$src2))))]>, VEX_4V;
+ (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
+ "vpunpckhqdq\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set VR128:$dst, (v2i64 (X86Punpckhqdq VR128:$src1,
+ (memopv2i64 addr:$src2))))]>, VEX_4V;
}
let Constraints = "$src1 = $dst" in {
- defm PUNPCKLBW : sse2_unpack<0x60, "punpcklbw", v16i8, unpckl, bc_v16i8>;
- defm PUNPCKLWD : sse2_unpack<0x61, "punpcklwd", v8i16, unpckl, bc_v8i16>;
- defm PUNPCKLDQ : sse2_unpack<0x62, "punpckldq", v4i32, unpckl, bc_v4i32>;
+ defm PUNPCKLBW : sse2_unpack<0x60, "punpcklbw", v16i8, X86Punpcklbw, bc_v16i8>;
+ defm PUNPCKLWD : sse2_unpack<0x61, "punpcklwd", v8i16, X86Punpcklwd, bc_v8i16>;
+ defm PUNPCKLDQ : sse2_unpack<0x62, "punpckldq", v4i32, X86Punpckldq, bc_v4i32>;
/// FIXME: we could eliminate this and use sse2_unpack instead if tblgen
/// knew to collapse (bitconvert VT to VT) into its operand.
@@ -2709,17 +3942,17 @@ let Constraints = "$src1 = $dst" in {
(outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
"punpcklqdq\t{$src2, $dst|$dst, $src2}",
[(set VR128:$dst,
- (v2i64 (unpckl VR128:$src1, VR128:$src2)))]>;
+ (v2i64 (X86Punpcklqdq VR128:$src1, VR128:$src2)))]>;
def PUNPCKLQDQrm : PDI<0x6C, MRMSrcMem,
(outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
"punpcklqdq\t{$src2, $dst|$dst, $src2}",
[(set VR128:$dst,
- (v2i64 (unpckl VR128:$src1,
+ (v2i64 (X86Punpcklqdq VR128:$src1,
(memopv2i64 addr:$src2))))]>;
- defm PUNPCKHBW : sse2_unpack<0x68, "punpckhbw", v16i8, unpckh, bc_v16i8>;
- defm PUNPCKHWD : sse2_unpack<0x69, "punpckhwd", v8i16, unpckh, bc_v8i16>;
- defm PUNPCKHDQ : sse2_unpack<0x6A, "punpckhdq", v4i32, unpckh, bc_v4i32>;
+ defm PUNPCKHBW : sse2_unpack<0x68, "punpckhbw", v16i8, X86Punpckhbw, bc_v16i8>;
+ defm PUNPCKHWD : sse2_unpack<0x69, "punpckhwd", v8i16, X86Punpckhwd, bc_v8i16>;
+ defm PUNPCKHDQ : sse2_unpack<0x6A, "punpckhdq", v4i32, X86Punpckhdq, bc_v4i32>;
/// FIXME: we could eliminate this and use sse2_unpack instead if tblgen
/// knew to collapse (bitconvert VT to VT) into its operand.
@@ -2727,17 +3960,24 @@ let Constraints = "$src1 = $dst" in {
(outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
"punpckhqdq\t{$src2, $dst|$dst, $src2}",
[(set VR128:$dst,
- (v2i64 (unpckh VR128:$src1, VR128:$src2)))]>;
+ (v2i64 (X86Punpckhqdq VR128:$src1, VR128:$src2)))]>;
def PUNPCKHQDQrm : PDI<0x6D, MRMSrcMem,
(outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
"punpckhqdq\t{$src2, $dst|$dst, $src2}",
[(set VR128:$dst,
- (v2i64 (unpckh VR128:$src1,
+ (v2i64 (X86Punpckhqdq VR128:$src1,
(memopv2i64 addr:$src2))))]>;
}
-
} // ExeDomain = SSEPackedInt
+// Splat v2f64 / v2i64
+let AddedComplexity = 10 in {
+ def : Pat<(splat_lo (v2i64 VR128:$src), (undef)),
+ (PUNPCKLQDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>;
+ def : Pat<(splat_lo (v2i64 VR128:$src), (undef)),
+ (VPUNPCKLQDQrr VR128:$src, VR128:$src)>, Requires<[HasAVX]>;
+}
+
//===---------------------------------------------------------------------===//
// SSE2 - Packed Integer Extract and Insert
//===---------------------------------------------------------------------===//
@@ -2769,7 +4009,7 @@ def VPEXTRWri : Ii8<0xC5, MRMSrcReg,
(outs GR32:$dst), (ins VR128:$src1, i32i8imm:$src2),
"vpextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}",
[(set GR32:$dst, (X86pextrw (v8i16 VR128:$src1),
- imm:$src2))]>, OpSize, VEX;
+ imm:$src2))]>, TB, OpSize, VEX;
def PEXTRWri : PDIi8<0xC5, MRMSrcReg,
(outs GR32:$dst), (ins VR128:$src1, i32i8imm:$src2),
"pextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}",
@@ -2778,11 +4018,11 @@ def PEXTRWri : PDIi8<0xC5, MRMSrcReg,
// Insert
let Predicates = [HasAVX] in {
- defm VPINSRW : sse2_pinsrw<0>, OpSize, VEX_4V;
+ defm VPINSRW : sse2_pinsrw<0>, TB, OpSize, VEX_4V;
def VPINSRWrr64i : Ii8<0xC4, MRMSrcReg, (outs VR128:$dst),
(ins VR128:$src1, GR64:$src2, i32i8imm:$src3),
"vpinsrw\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}",
- []>, OpSize, VEX_4V;
+ []>, TB, OpSize, VEX_4V;
}
let Constraints = "$src1 = $dst" in
@@ -2839,7 +4079,9 @@ def MASKMOVDQU64 : PDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask),
// SSE2 - Move Doubleword
//===---------------------------------------------------------------------===//
+//===---------------------------------------------------------------------===//
// Move Int Doubleword to Packed Double Int
+//
def VMOVDI2PDIrr : VPDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src),
"movd\t{$src, $dst|$dst, $src}",
[(set VR128:$dst,
@@ -2849,6 +4091,14 @@ def VMOVDI2PDIrm : VPDI<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i32mem:$src),
[(set VR128:$dst,
(v4i32 (scalar_to_vector (loadi32 addr:$src))))]>,
VEX;
+def VMOV64toPQIrr : VRPDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR64:$src),
+ "mov{d|q}\t{$src, $dst|$dst, $src}",
+ [(set VR128:$dst,
+ (v2i64 (scalar_to_vector GR64:$src)))]>, VEX;
+def VMOV64toSDrr : VRPDI<0x6E, MRMSrcReg, (outs FR64:$dst), (ins GR64:$src),
+ "mov{d|q}\t{$src, $dst|$dst, $src}",
+ [(set FR64:$dst, (bitconvert GR64:$src))]>, VEX;
+
def MOVDI2PDIrr : PDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src),
"movd\t{$src, $dst|$dst, $src}",
[(set VR128:$dst,
@@ -2865,8 +4115,9 @@ def MOV64toSDrr : RPDI<0x6E, MRMSrcReg, (outs FR64:$dst), (ins GR64:$src),
"mov{d|q}\t{$src, $dst|$dst, $src}",
[(set FR64:$dst, (bitconvert GR64:$src))]>;
-
+//===---------------------------------------------------------------------===//
// Move Int Doubleword to Single Scalar
+//
def VMOVDI2SSrr : VPDI<0x6E, MRMSrcReg, (outs FR32:$dst), (ins GR32:$src),
"movd\t{$src, $dst|$dst, $src}",
[(set FR32:$dst, (bitconvert GR32:$src))]>, VEX;
@@ -2883,7 +4134,9 @@ def MOVDI2SSrm : PDI<0x6E, MRMSrcMem, (outs FR32:$dst), (ins i32mem:$src),
"movd\t{$src, $dst|$dst, $src}",
[(set FR32:$dst, (bitconvert (loadi32 addr:$src)))]>;
+//===---------------------------------------------------------------------===//
// Move Packed Doubleword Int to Packed Double Int
+//
def VMOVPDI2DIrr : VPDI<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR128:$src),
"movd\t{$src, $dst|$dst, $src}",
[(set GR32:$dst, (vector_extract (v4i32 VR128:$src),
@@ -2902,22 +4155,48 @@ def MOVPDI2DImr : PDI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, VR128:$src),
[(store (i32 (vector_extract (v4i32 VR128:$src),
(iPTR 0))), addr:$dst)]>;
-def MOVPQIto64rr : RPDI<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128:$src),
+//===---------------------------------------------------------------------===//
+// Move Packed Doubleword Int first element to Doubleword Int
+//
+def VMOVPQIto64rr : I<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128:$src),
+ "mov{d|q}\t{$src, $dst|$dst, $src}",
+ [(set GR64:$dst, (vector_extract (v2i64 VR128:$src),
+ (iPTR 0)))]>,
+ TB, OpSize, VEX, VEX_W, Requires<[HasAVX, In64BitMode]>;
+
+def MOVPQIto64rr : RPDI<0x7E, MRMDestReg, (outs GR64:$dst), (ins VR128:$src),
+ "mov{d|q}\t{$src, $dst|$dst, $src}",
+ [(set GR64:$dst, (vector_extract (v2i64 VR128:$src),
+ (iPTR 0)))]>;
+
+//===---------------------------------------------------------------------===//
+// Bitcast FR64 <-> GR64
+//
+let Predicates = [HasAVX] in
+def VMOV64toSDrm : S3SI<0x7E, MRMSrcMem, (outs FR64:$dst), (ins i64mem:$src),
+ "vmovq\t{$src, $dst|$dst, $src}",
+ [(set FR64:$dst, (bitconvert (loadi64 addr:$src)))]>,
+ VEX;
+def VMOVSDto64rr : VRPDI<0x7E, MRMDestReg, (outs GR64:$dst), (ins FR64:$src),
"mov{d|q}\t{$src, $dst|$dst, $src}",
- [(set GR64:$dst, (vector_extract (v2i64 VR128:$src),
- (iPTR 0)))]>;
+ [(set GR64:$dst, (bitconvert FR64:$src))]>;
+def VMOVSDto64mr : VRPDI<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, FR64:$src),
+ "movq\t{$src, $dst|$dst, $src}",
+ [(store (i64 (bitconvert FR64:$src)), addr:$dst)]>;
+
def MOV64toSDrm : S3SI<0x7E, MRMSrcMem, (outs FR64:$dst), (ins i64mem:$src),
"movq\t{$src, $dst|$dst, $src}",
[(set FR64:$dst, (bitconvert (loadi64 addr:$src)))]>;
+def MOVSDto64rr : RPDI<0x7E, MRMDestReg, (outs GR64:$dst), (ins FR64:$src),
+ "mov{d|q}\t{$src, $dst|$dst, $src}",
+ [(set GR64:$dst, (bitconvert FR64:$src))]>;
+def MOVSDto64mr : RPDI<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, FR64:$src),
+ "movq\t{$src, $dst|$dst, $src}",
+ [(store (i64 (bitconvert FR64:$src)), addr:$dst)]>;
-def MOVSDto64rr : RPDI<0x7E, MRMDestReg, (outs GR64:$dst), (ins FR64:$src),
- "mov{d|q}\t{$src, $dst|$dst, $src}",
- [(set GR64:$dst, (bitconvert FR64:$src))]>;
-def MOVSDto64mr : RPDI<0x7E, MRMDestMem, (outs), (ins i64mem:$dst, FR64:$src),
- "movq\t{$src, $dst|$dst, $src}",
- [(store (i64 (bitconvert FR64:$src)), addr:$dst)]>;
-
+//===---------------------------------------------------------------------===//
// Move Scalar Single to Double Int
+//
def VMOVSS2DIrr : VPDI<0x7E, MRMDestReg, (outs GR32:$dst), (ins FR32:$src),
"movd\t{$src, $dst|$dst, $src}",
[(set GR32:$dst, (bitconvert FR32:$src))]>, VEX;
@@ -2931,7 +4210,9 @@ def MOVSS2DImr : PDI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, FR32:$src),
"movd\t{$src, $dst|$dst, $src}",
[(store (i32 (bitconvert FR32:$src)), addr:$dst)]>;
-// movd / movq to XMM register zero-extends
+//===---------------------------------------------------------------------===//
+// Patterns and instructions to describe movd/movq to XMM register zero-extends
+//
let AddedComplexity = 15 in {
def VMOVZDI2PDIrr : VPDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src),
"movd\t{$src, $dst|$dst, $src}",
@@ -2967,15 +4248,36 @@ def MOVZDI2PDIrm : PDI<0x6E, MRMSrcMem, (outs VR128:$dst), (ins i32mem:$src),
[(set VR128:$dst,
(v4i32 (X86vzmovl (v4i32 (scalar_to_vector
(loadi32 addr:$src))))))]>;
+}
-def : Pat<(v4i32 (X86vzmovl (loadv4i32 addr:$src))),
+let Predicates = [HasSSE2], AddedComplexity = 20 in {
+ def : Pat<(v4i32 (X86vzmovl (loadv4i32 addr:$src))),
(MOVZDI2PDIrm addr:$src)>;
-def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv4f32 addr:$src)))),
+ def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv4f32 addr:$src)))),
(MOVZDI2PDIrm addr:$src)>;
-def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))),
+ def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))),
(MOVZDI2PDIrm addr:$src)>;
}
+let Predicates = [HasAVX] in {
+ // AVX 128-bit movd/movq instruction write zeros in the high 128-bit part.
+ let AddedComplexity = 20 in {
+ def : Pat<(v4i32 (X86vzmovl (loadv4i32 addr:$src))),
+ (VMOVZDI2PDIrm addr:$src)>;
+ def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv4f32 addr:$src)))),
+ (VMOVZDI2PDIrm addr:$src)>;
+ def : Pat<(v4i32 (X86vzmovl (bc_v4i32 (loadv2i64 addr:$src)))),
+ (VMOVZDI2PDIrm addr:$src)>;
+ }
+ // Use regular 128-bit instructions to match 256-bit scalar_to_vec+zext.
+ def : Pat<(v8i32 (X86vzmovl (insert_subvector undef,
+ (v4i32 (scalar_to_vector GR32:$src)),(i32 0)))),
+ (SUBREG_TO_REG (i32 0), (VMOVZDI2PDIrr GR32:$src), sub_xmm)>;
+ def : Pat<(v4i64 (X86vzmovl (insert_subvector undef,
+ (v2i64 (scalar_to_vector GR64:$src)),(i32 0)))),
+ (SUBREG_TO_REG (i64 0), (VMOVZQI2PQIrr GR64:$src), sub_xmm)>;
+}
+
// These are the correct encodings of the instructions so that we know how to
// read correct assembly, even though we continue to emit the wrong ones for
// compatibility with Darwin's buggy assembler.
@@ -2996,7 +4298,9 @@ def : InstAlias<"movq\t{$src, $dst|$dst, $src}",
// SSE2 - Move Quadword
//===---------------------------------------------------------------------===//
+//===---------------------------------------------------------------------===//
// Move Quadword Int to Packed Quadword Int
+//
def VMOVQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src),
"vmovq\t{$src, $dst|$dst, $src}",
[(set VR128:$dst,
@@ -3008,7 +4312,9 @@ def MOVQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src),
(v2i64 (scalar_to_vector (loadi64 addr:$src))))]>, XS,
Requires<[HasSSE2]>; // SSE2 instruction with XS Prefix
+//===---------------------------------------------------------------------===//
// Move Packed Quadword Int to Quadword Int
+//
def VMOVPQI2QImr : VPDI<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src),
"movq\t{$src, $dst|$dst, $src}",
[(store (i64 (vector_extract (v2i64 VR128:$src),
@@ -3018,10 +4324,9 @@ def MOVPQI2QImr : PDI<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src),
[(store (i64 (vector_extract (v2i64 VR128:$src),
(iPTR 0))), addr:$dst)]>;
-def : Pat<(f64 (vector_extract (v2f64 VR128:$src), (iPTR 0))),
- (f64 (EXTRACT_SUBREG (v2f64 VR128:$src), sub_sd))>;
-
+//===---------------------------------------------------------------------===//
// Store / copy lower 64-bits of a XMM register.
+//
def VMOVLQ128mr : VPDI<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src),
"movq\t{$src, $dst|$dst, $src}",
[(int_x86_sse2_storel_dq addr:$dst, VR128:$src)]>, VEX;
@@ -3037,7 +4342,7 @@ def VMOVZQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src),
(loadi64 addr:$src))))))]>,
XS, VEX, Requires<[HasAVX]>;
-let AddedComplexity = 20 in {
+let AddedComplexity = 20 in
def MOVZQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src),
"movq\t{$src, $dst|$dst, $src}",
[(set VR128:$dst,
@@ -3045,15 +4350,27 @@ def MOVZQI2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src),
(loadi64 addr:$src))))))]>,
XS, Requires<[HasSSE2]>;
-def : Pat<(v2i64 (X86vzmovl (loadv2i64 addr:$src))),
+let Predicates = [HasSSE2], AddedComplexity = 20 in {
+ def : Pat<(v2i64 (X86vzmovl (loadv2i64 addr:$src))),
(MOVZQI2PQIrm addr:$src)>;
-def : Pat<(v2i64 (X86vzmovl (bc_v2i64 (loadv4f32 addr:$src)))),
+ def : Pat<(v2i64 (X86vzmovl (bc_v2i64 (loadv4f32 addr:$src)))),
(MOVZQI2PQIrm addr:$src)>;
-def : Pat<(v2i64 (X86vzload addr:$src)), (MOVZQI2PQIrm addr:$src)>;
+ def : Pat<(v2i64 (X86vzload addr:$src)), (MOVZQI2PQIrm addr:$src)>;
+}
+
+let Predicates = [HasAVX], AddedComplexity = 20 in {
+ def : Pat<(v2i64 (X86vzmovl (loadv2i64 addr:$src))),
+ (VMOVZQI2PQIrm addr:$src)>;
+ def : Pat<(v2i64 (X86vzmovl (bc_v2i64 (loadv4f32 addr:$src)))),
+ (VMOVZQI2PQIrm addr:$src)>;
+ def : Pat<(v2i64 (X86vzload addr:$src)),
+ (VMOVZQI2PQIrm addr:$src)>;
}
+//===---------------------------------------------------------------------===//
// Moving from XMM to XMM and clear upper 64 bits. Note, there is a bug in
// IA32 document. movq xmm1, xmm2 does clear the high bits.
+//
let AddedComplexity = 15 in
def VMOVZPQILo2PQIrr : I<0x7E, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"vmovq\t{$src, $dst|$dst, $src}",
@@ -3077,9 +4394,21 @@ def MOVZPQILo2PQIrm : I<0x7E, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src),
[(set VR128:$dst, (v2i64 (X86vzmovl
(loadv2i64 addr:$src))))]>,
XS, Requires<[HasSSE2]>;
+}
-def : Pat<(v2i64 (X86vzmovl (bc_v2i64 (loadv4i32 addr:$src)))),
- (MOVZPQILo2PQIrm addr:$src)>;
+let AddedComplexity = 20 in {
+ let Predicates = [HasSSE2] in {
+ def : Pat<(v2i64 (X86vzmovl (bc_v2i64 (loadv4i32 addr:$src)))),
+ (MOVZPQILo2PQIrm addr:$src)>;
+ def : Pat<(v2f64 (X86vzmovl (v2f64 VR128:$src))),
+ (MOVZPQILo2PQIrr VR128:$src)>;
+ }
+ let Predicates = [HasAVX] in {
+ def : Pat<(v2i64 (X86vzmovl (bc_v2i64 (loadv4i32 addr:$src)))),
+ (VMOVZPQILo2PQIrm addr:$src)>;
+ def : Pat<(v2f64 (X86vzmovl (v2f64 VR128:$src))),
+ (VMOVZPQILo2PQIrr VR128:$src)>;
+ }
}
// Instructions to match in the assembler
@@ -3102,37 +4431,6 @@ def MOVQxrxr : I<0x7E, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"movq\t{$src, $dst|$dst, $src}", []>, XS;
//===---------------------------------------------------------------------===//
-// SSE2 - Misc Instructions
-//===---------------------------------------------------------------------===//
-
-// Flush cache
-def CLFLUSH : I<0xAE, MRM7m, (outs), (ins i8mem:$src),
- "clflush\t$src", [(int_x86_sse2_clflush addr:$src)]>,
- TB, Requires<[HasSSE2]>;
-
-// Load, store, and memory fence
-def LFENCE : I<0xAE, MRM_E8, (outs), (ins),
- "lfence", [(int_x86_sse2_lfence)]>, TB, Requires<[HasSSE2]>;
-def MFENCE : I<0xAE, MRM_F0, (outs), (ins),
- "mfence", [(int_x86_sse2_mfence)]>, TB, Requires<[HasSSE2]>;
-def : Pat<(X86LFence), (LFENCE)>;
-def : Pat<(X86MFence), (MFENCE)>;
-
-
-// Pause. This "instruction" is encoded as "rep; nop", so even though it
-// was introduced with SSE2, it's backward compatible.
-def PAUSE : I<0x90, RawFrm, (outs), (ins), "pause", []>, REP;
-
-// Alias instructions that map zero vector to pxor / xorp* for sse.
-// We set canFoldAsLoad because this can be converted to a constant-pool
-// load of an all-ones value if folding it would be beneficial.
-let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1,
- isCodeGenOnly = 1, ExeDomain = SSEPackedInt in
- // FIXME: Change encoding to pseudo.
- def V_SETALLONES : PDI<0x76, MRMInitReg, (outs VR128:$dst), (ins), "",
- [(set VR128:$dst, (v4i32 immAllOnesV))]>;
-
-//===---------------------------------------------------------------------===//
// SSE3 - Conversion Instructions
//===---------------------------------------------------------------------===//
@@ -3164,6 +4462,11 @@ def CVTPD2DQrm : S3DI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
def CVTPD2DQrr : S3DI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvtpd2dq\t{$src, $dst|$dst, $src}", []>;
+def : Pat<(v4i32 (fp_to_sint (v4f64 VR256:$src))),
+ (VCVTPD2DQYrr VR256:$src)>;
+def : Pat<(v4i32 (fp_to_sint (memopv4f64 addr:$src))),
+ (VCVTPD2DQYrm addr:$src)>;
+
// Convert Packed DW Integers to Packed Double FP
let Predicates = [HasAVX] in {
def VCVTDQ2PDrm : S3SI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
@@ -3192,41 +4495,74 @@ def : Pat<(int_x86_avx_cvt_pd2dq_256 VR256:$src),
def : Pat<(int_x86_avx_cvt_pd2dq_256 (memopv4f64 addr:$src)),
(VCVTPD2DQYrm addr:$src)>;
+def : Pat<(v4f64 (sint_to_fp (v4i32 VR128:$src))),
+ (VCVTDQ2PDYrr VR128:$src)>;
+def : Pat<(v4f64 (sint_to_fp (memopv4i32 addr:$src))),
+ (VCVTDQ2PDYrm addr:$src)>;
+
//===---------------------------------------------------------------------===//
-// SSE3 - Move Instructions
+// SSE3 - Replicate Single FP - MOVSHDUP and MOVSLDUP
//===---------------------------------------------------------------------===//
-
-// Replicate Single FP
-multiclass sse3_replicate_sfp<bits<8> op, PatFrag rep_frag, string OpcodeStr> {
-def rr : S3SI<op, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
+multiclass sse3_replicate_sfp<bits<8> op, SDNode OpNode, string OpcodeStr,
+ ValueType vt, RegisterClass RC, PatFrag mem_frag,
+ X86MemOperand x86memop> {
+def rr : S3SI<op, MRMSrcReg, (outs RC:$dst), (ins RC:$src),
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
- [(set VR128:$dst, (v4f32 (rep_frag
- VR128:$src, (undef))))]>;
-def rm : S3SI<op, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
+ [(set RC:$dst, (vt (OpNode RC:$src)))]>;
+def rm : S3SI<op, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src),
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
- [(set VR128:$dst, (rep_frag
- (memopv4f32 addr:$src), (undef)))]>;
+ [(set RC:$dst, (OpNode (mem_frag addr:$src)))]>;
}
-multiclass sse3_replicate_sfp_y<bits<8> op, PatFrag rep_frag,
- string OpcodeStr> {
-def rr : S3SI<op, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src),
- !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), []>;
-def rm : S3SI<op, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src),
- !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"), []>;
+let Predicates = [HasAVX] in {
+ defm VMOVSHDUP : sse3_replicate_sfp<0x16, X86Movshdup, "vmovshdup",
+ v4f32, VR128, memopv4f32, f128mem>, VEX;
+ defm VMOVSLDUP : sse3_replicate_sfp<0x12, X86Movsldup, "vmovsldup",
+ v4f32, VR128, memopv4f32, f128mem>, VEX;
+ defm VMOVSHDUPY : sse3_replicate_sfp<0x16, X86Movshdup, "vmovshdup",
+ v8f32, VR256, memopv8f32, f256mem>, VEX;
+ defm VMOVSLDUPY : sse3_replicate_sfp<0x12, X86Movsldup, "vmovsldup",
+ v8f32, VR256, memopv8f32, f256mem>, VEX;
+}
+defm MOVSHDUP : sse3_replicate_sfp<0x16, X86Movshdup, "movshdup", v4f32, VR128,
+ memopv4f32, f128mem>;
+defm MOVSLDUP : sse3_replicate_sfp<0x12, X86Movsldup, "movsldup", v4f32, VR128,
+ memopv4f32, f128mem>;
+
+let Predicates = [HasSSE3] in {
+ def : Pat<(v4i32 (X86Movshdup VR128:$src)),
+ (MOVSHDUPrr VR128:$src)>;
+ def : Pat<(v4i32 (X86Movshdup (bc_v4i32 (memopv2i64 addr:$src)))),
+ (MOVSHDUPrm addr:$src)>;
+ def : Pat<(v4i32 (X86Movsldup VR128:$src)),
+ (MOVSLDUPrr VR128:$src)>;
+ def : Pat<(v4i32 (X86Movsldup (bc_v4i32 (memopv2i64 addr:$src)))),
+ (MOVSLDUPrm addr:$src)>;
}
let Predicates = [HasAVX] in {
- // FIXME: Merge above classes when we have patterns for the ymm version
- defm VMOVSHDUP : sse3_replicate_sfp<0x16, movshdup, "vmovshdup">, VEX;
- defm VMOVSLDUP : sse3_replicate_sfp<0x12, movsldup, "vmovsldup">, VEX;
- defm VMOVSHDUPY : sse3_replicate_sfp_y<0x16, movshdup, "vmovshdup">, VEX;
- defm VMOVSLDUPY : sse3_replicate_sfp_y<0x12, movsldup, "vmovsldup">, VEX;
+ def : Pat<(v4i32 (X86Movshdup VR128:$src)),
+ (VMOVSHDUPrr VR128:$src)>;
+ def : Pat<(v4i32 (X86Movshdup (bc_v4i32 (memopv2i64 addr:$src)))),
+ (VMOVSHDUPrm addr:$src)>;
+ def : Pat<(v4i32 (X86Movsldup VR128:$src)),
+ (VMOVSLDUPrr VR128:$src)>;
+ def : Pat<(v4i32 (X86Movsldup (bc_v4i32 (memopv2i64 addr:$src)))),
+ (VMOVSLDUPrm addr:$src)>;
+ def : Pat<(v8i32 (X86Movshdup VR256:$src)),
+ (VMOVSHDUPYrr VR256:$src)>;
+ def : Pat<(v8i32 (X86Movshdup (bc_v8i32 (memopv4i64 addr:$src)))),
+ (VMOVSHDUPYrm addr:$src)>;
+ def : Pat<(v8i32 (X86Movsldup VR256:$src)),
+ (VMOVSLDUPYrr VR256:$src)>;
+ def : Pat<(v8i32 (X86Movsldup (bc_v8i32 (memopv4i64 addr:$src)))),
+ (VMOVSLDUPYrm addr:$src)>;
}
-defm MOVSHDUP : sse3_replicate_sfp<0x16, movshdup, "movshdup">;
-defm MOVSLDUP : sse3_replicate_sfp<0x12, movsldup, "movsldup">;
-// Replicate Double FP
+//===---------------------------------------------------------------------===//
+// SSE3 - Replicate Double FP - MOVDDUP
+//===---------------------------------------------------------------------===//
+
multiclass sse3_replicate_dfp<string OpcodeStr> {
def rr : S3DI<0x12, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
@@ -3238,23 +4574,90 @@ def rm : S3DI<0x12, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src),
(undef))))]>;
}
+// FIXME: Merge with above classe when there're patterns for the ymm version
multiclass sse3_replicate_dfp_y<string OpcodeStr> {
-def rr : S3DI<0x12, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src),
- !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
- []>;
-def rm : S3DI<0x12, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src),
- !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
- []>;
+let Predicates = [HasAVX] in {
+ def rr : S3DI<0x12, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src),
+ !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
+ []>;
+ def rm : S3DI<0x12, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src),
+ !strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
+ []>;
+ }
+}
+
+defm MOVDDUP : sse3_replicate_dfp<"movddup">;
+defm VMOVDDUP : sse3_replicate_dfp<"vmovddup">, VEX;
+defm VMOVDDUPY : sse3_replicate_dfp_y<"vmovddup">, VEX;
+
+let Predicates = [HasSSE3] in {
+ def : Pat<(movddup (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src)))),
+ (undef)),
+ (MOVDDUPrm addr:$src)>;
+ let AddedComplexity = 5 in {
+ def : Pat<(movddup (memopv2f64 addr:$src), (undef)), (MOVDDUPrm addr:$src)>;
+ def : Pat<(movddup (bc_v4f32 (memopv2f64 addr:$src)), (undef)),
+ (MOVDDUPrm addr:$src)>;
+ def : Pat<(movddup (memopv2i64 addr:$src), (undef)), (MOVDDUPrm addr:$src)>;
+ def : Pat<(movddup (bc_v4i32 (memopv2i64 addr:$src)), (undef)),
+ (MOVDDUPrm addr:$src)>;
+ }
+ def : Pat<(X86Movddup (memopv2f64 addr:$src)),
+ (MOVDDUPrm addr:$src)>;
+ def : Pat<(X86Movddup (bc_v2f64 (memopv4f32 addr:$src))),
+ (MOVDDUPrm addr:$src)>;
+ def : Pat<(X86Movddup (bc_v2f64 (memopv2i64 addr:$src))),
+ (MOVDDUPrm addr:$src)>;
+ def : Pat<(X86Movddup (v2f64 (scalar_to_vector (loadf64 addr:$src)))),
+ (MOVDDUPrm addr:$src)>;
+ def : Pat<(X86Movddup (bc_v2f64
+ (v2i64 (scalar_to_vector (loadi64 addr:$src))))),
+ (MOVDDUPrm addr:$src)>;
}
let Predicates = [HasAVX] in {
- // FIXME: Merge above classes when we have patterns for the ymm version
- defm VMOVDDUP : sse3_replicate_dfp<"vmovddup">, VEX;
- defm VMOVDDUPY : sse3_replicate_dfp_y<"vmovddup">, VEX;
+ def : Pat<(movddup (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src)))),
+ (undef)),
+ (VMOVDDUPrm addr:$src)>;
+ let AddedComplexity = 5 in {
+ def : Pat<(movddup (memopv2f64 addr:$src), (undef)), (VMOVDDUPrm addr:$src)>;
+ def : Pat<(movddup (bc_v4f32 (memopv2f64 addr:$src)), (undef)),
+ (VMOVDDUPrm addr:$src)>;
+ def : Pat<(movddup (memopv2i64 addr:$src), (undef)), (VMOVDDUPrm addr:$src)>;
+ def : Pat<(movddup (bc_v4i32 (memopv2i64 addr:$src)), (undef)),
+ (VMOVDDUPrm addr:$src)>;
+ }
+ def : Pat<(X86Movddup (memopv2f64 addr:$src)),
+ (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
+ def : Pat<(X86Movddup (bc_v2f64 (memopv4f32 addr:$src))),
+ (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
+ def : Pat<(X86Movddup (bc_v2f64 (memopv2i64 addr:$src))),
+ (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
+ def : Pat<(X86Movddup (v2f64 (scalar_to_vector (loadf64 addr:$src)))),
+ (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
+ def : Pat<(X86Movddup (bc_v2f64
+ (v2i64 (scalar_to_vector (loadi64 addr:$src))))),
+ (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
+
+ // 256-bit version
+ def : Pat<(X86Movddup (memopv4f64 addr:$src)),
+ (VMOVDDUPYrm addr:$src)>;
+ def : Pat<(X86Movddup (memopv4i64 addr:$src)),
+ (VMOVDDUPYrm addr:$src)>;
+ def : Pat<(X86Movddup (v4f64 (scalar_to_vector (loadf64 addr:$src)))),
+ (VMOVDDUPYrm addr:$src)>;
+ def : Pat<(X86Movddup (v4i64 (scalar_to_vector (loadi64 addr:$src)))),
+ (VMOVDDUPYrm addr:$src)>;
+ def : Pat<(X86Movddup (v4f64 VR256:$src)),
+ (VMOVDDUPYrr VR256:$src)>;
+ def : Pat<(X86Movddup (v4i64 VR256:$src)),
+ (VMOVDDUPYrr VR256:$src)>;
}
-defm MOVDDUP : sse3_replicate_dfp<"movddup">;
-// Move Unaligned Integer
+//===---------------------------------------------------------------------===//
+// SSE3 - Move Unaligned Integer
+//===---------------------------------------------------------------------===//
+
let Predicates = [HasAVX] in {
def VLDDQUrm : S3DI<0xF0, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src),
"vlddqu\t{$src, $dst|$dst, $src}",
@@ -3267,38 +4670,6 @@ def LDDQUrm : S3DI<0xF0, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src),
"lddqu\t{$src, $dst|$dst, $src}",
[(set VR128:$dst, (int_x86_sse3_ldu_dq addr:$src))]>;
-def : Pat<(movddup (bc_v2f64 (v2i64 (scalar_to_vector (loadi64 addr:$src)))),
- (undef)),
- (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>;
-
-// Several Move patterns
-let AddedComplexity = 5 in {
-def : Pat<(movddup (memopv2f64 addr:$src), (undef)),
- (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>;
-def : Pat<(movddup (bc_v4f32 (memopv2f64 addr:$src)), (undef)),
- (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>;
-def : Pat<(movddup (memopv2i64 addr:$src), (undef)),
- (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>;
-def : Pat<(movddup (bc_v4i32 (memopv2i64 addr:$src)), (undef)),
- (MOVDDUPrm addr:$src)>, Requires<[HasSSE3]>;
-}
-
-// vector_shuffle v1, <undef> <1, 1, 3, 3>
-let AddedComplexity = 15 in
-def : Pat<(v4i32 (movshdup VR128:$src, (undef))),
- (MOVSHDUPrr VR128:$src)>, Requires<[HasSSE3]>;
-let AddedComplexity = 20 in
-def : Pat<(v4i32 (movshdup (bc_v4i32 (memopv2i64 addr:$src)), (undef))),
- (MOVSHDUPrm addr:$src)>, Requires<[HasSSE3]>;
-
-// vector_shuffle v1, <undef> <0, 0, 2, 2>
-let AddedComplexity = 15 in
- def : Pat<(v4i32 (movsldup VR128:$src, (undef))),
- (MOVSLDUPrr VR128:$src)>, Requires<[HasSSE3]>;
-let AddedComplexity = 20 in
- def : Pat<(v4i32 (movsldup (bc_v4i32 (memopv2i64 addr:$src)), (undef))),
- (MOVSLDUPrm addr:$src)>, Requires<[HasSSE3]>;
-
//===---------------------------------------------------------------------===//
// SSE3 - Arithmetic
//===---------------------------------------------------------------------===//
@@ -3344,62 +4715,58 @@ let Constraints = "$src1 = $dst", Predicates = [HasSSE3],
// Horizontal ops
multiclass S3D_Int<bits<8> o, string OpcodeStr, ValueType vt, RegisterClass RC,
- X86MemOperand x86memop, Intrinsic IntId, bit Is2Addr = 1> {
+ X86MemOperand x86memop, SDNode OpNode, bit Is2Addr = 1> {
def rr : S3DI<o, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2),
!if(Is2Addr,
!strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}")),
- [(set RC:$dst, (vt (IntId RC:$src1, RC:$src2)))]>;
+ [(set RC:$dst, (vt (OpNode RC:$src1, RC:$src2)))]>;
def rm : S3DI<o, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2),
!if(Is2Addr,
!strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}")),
- [(set RC:$dst, (vt (IntId RC:$src1, (memop addr:$src2))))]>;
+ [(set RC:$dst, (vt (OpNode RC:$src1, (memop addr:$src2))))]>;
}
multiclass S3_Int<bits<8> o, string OpcodeStr, ValueType vt, RegisterClass RC,
- X86MemOperand x86memop, Intrinsic IntId, bit Is2Addr = 1> {
+ X86MemOperand x86memop, SDNode OpNode, bit Is2Addr = 1> {
def rr : S3I<o, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2),
!if(Is2Addr,
!strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}")),
- [(set RC:$dst, (vt (IntId RC:$src1, RC:$src2)))]>;
+ [(set RC:$dst, (vt (OpNode RC:$src1, RC:$src2)))]>;
def rm : S3I<o, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2),
!if(Is2Addr,
!strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}")),
- [(set RC:$dst, (vt (IntId RC:$src1, (memop addr:$src2))))]>;
+ [(set RC:$dst, (vt (OpNode RC:$src1, (memop addr:$src2))))]>;
}
let Predicates = [HasAVX] in {
defm VHADDPS : S3D_Int<0x7C, "vhaddps", v4f32, VR128, f128mem,
- int_x86_sse3_hadd_ps, 0>, VEX_4V;
+ X86fhadd, 0>, VEX_4V;
defm VHADDPD : S3_Int <0x7C, "vhaddpd", v2f64, VR128, f128mem,
- int_x86_sse3_hadd_pd, 0>, VEX_4V;
+ X86fhadd, 0>, VEX_4V;
defm VHSUBPS : S3D_Int<0x7D, "vhsubps", v4f32, VR128, f128mem,
- int_x86_sse3_hsub_ps, 0>, VEX_4V;
+ X86fhsub, 0>, VEX_4V;
defm VHSUBPD : S3_Int <0x7D, "vhsubpd", v2f64, VR128, f128mem,
- int_x86_sse3_hsub_pd, 0>, VEX_4V;
+ X86fhsub, 0>, VEX_4V;
defm VHADDPSY : S3D_Int<0x7C, "vhaddps", v8f32, VR256, f256mem,
- int_x86_avx_hadd_ps_256, 0>, VEX_4V;
+ X86fhadd, 0>, VEX_4V;
defm VHADDPDY : S3_Int <0x7C, "vhaddpd", v4f64, VR256, f256mem,
- int_x86_avx_hadd_pd_256, 0>, VEX_4V;
+ X86fhadd, 0>, VEX_4V;
defm VHSUBPSY : S3D_Int<0x7D, "vhsubps", v8f32, VR256, f256mem,
- int_x86_avx_hsub_ps_256, 0>, VEX_4V;
+ X86fhsub, 0>, VEX_4V;
defm VHSUBPDY : S3_Int <0x7D, "vhsubpd", v4f64, VR256, f256mem,
- int_x86_avx_hsub_pd_256, 0>, VEX_4V;
+ X86fhsub, 0>, VEX_4V;
}
let Constraints = "$src1 = $dst" in {
- defm HADDPS : S3D_Int<0x7C, "haddps", v4f32, VR128, f128mem,
- int_x86_sse3_hadd_ps>;
- defm HADDPD : S3_Int<0x7C, "haddpd", v2f64, VR128, f128mem,
- int_x86_sse3_hadd_pd>;
- defm HSUBPS : S3D_Int<0x7D, "hsubps", v4f32, VR128, f128mem,
- int_x86_sse3_hsub_ps>;
- defm HSUBPD : S3_Int<0x7D, "hsubpd", v2f64, VR128, f128mem,
- int_x86_sse3_hsub_pd>;
+ defm HADDPS : S3D_Int<0x7C, "haddps", v4f32, VR128, f128mem, X86fhadd>;
+ defm HADDPD : S3_Int<0x7C, "haddpd", v2f64, VR128, f128mem, X86fhadd>;
+ defm HSUBPS : S3D_Int<0x7D, "hsubps", v4f32, VR128, f128mem, X86fhsub>;
+ defm HSUBPD : S3_Int<0x7D, "hsubpd", v2f64, VR128, f128mem, X86fhsub>;
}
//===---------------------------------------------------------------------===//
@@ -3466,7 +4833,7 @@ multiclass SS3I_binop_rm_int<bits<8> opc, string OpcodeStr,
(bitconvert (memopv16i8 addr:$src2))))]>, OpSize;
}
-let Predicates = [HasAVX] in {
+let ImmT = NoImm, Predicates = [HasAVX] in {
let isCommutable = 0 in {
defm VPHADDW : SS3I_binop_rm_int<0x01, "vphaddw", memopv8i16,
int_x86_ssse3_phadd_w_128, 0>, VEX_4V;
@@ -3525,17 +4892,33 @@ defm PMULHRSW : SS3I_binop_rm_int<0x0B, "pmulhrsw", memopv8i16,
int_x86_ssse3_pmul_hr_sw_128>;
}
-def : Pat<(X86pshufb VR128:$src, VR128:$mask),
- (PSHUFBrr128 VR128:$src, VR128:$mask)>, Requires<[HasSSSE3]>;
-def : Pat<(X86pshufb VR128:$src, (bc_v16i8 (memopv2i64 addr:$mask))),
- (PSHUFBrm128 VR128:$src, addr:$mask)>, Requires<[HasSSSE3]>;
+let Predicates = [HasSSSE3] in {
+ def : Pat<(X86pshufb VR128:$src, VR128:$mask),
+ (PSHUFBrr128 VR128:$src, VR128:$mask)>;
+ def : Pat<(X86pshufb VR128:$src, (bc_v16i8 (memopv2i64 addr:$mask))),
+ (PSHUFBrm128 VR128:$src, addr:$mask)>;
+
+ def : Pat<(X86psignb VR128:$src1, VR128:$src2),
+ (PSIGNBrr128 VR128:$src1, VR128:$src2)>;
+ def : Pat<(X86psignw VR128:$src1, VR128:$src2),
+ (PSIGNWrr128 VR128:$src1, VR128:$src2)>;
+ def : Pat<(X86psignd VR128:$src1, VR128:$src2),
+ (PSIGNDrr128 VR128:$src1, VR128:$src2)>;
+}
+
+let Predicates = [HasAVX] in {
+ def : Pat<(X86pshufb VR128:$src, VR128:$mask),
+ (VPSHUFBrr128 VR128:$src, VR128:$mask)>;
+ def : Pat<(X86pshufb VR128:$src, (bc_v16i8 (memopv2i64 addr:$mask))),
+ (VPSHUFBrm128 VR128:$src, addr:$mask)>;
-def : Pat<(X86psignb VR128:$src1, VR128:$src2),
- (PSIGNBrr128 VR128:$src1, VR128:$src2)>, Requires<[HasSSSE3]>;
-def : Pat<(X86psignw VR128:$src1, VR128:$src2),
- (PSIGNWrr128 VR128:$src1, VR128:$src2)>, Requires<[HasSSSE3]>;
-def : Pat<(X86psignd VR128:$src1, VR128:$src2),
- (PSIGNDrr128 VR128:$src1, VR128:$src2)>, Requires<[HasSSSE3]>;
+ def : Pat<(X86psignb VR128:$src1, VR128:$src2),
+ (VPSIGNBrr128 VR128:$src1, VR128:$src2)>;
+ def : Pat<(X86psignw VR128:$src1, VR128:$src2),
+ (VPSIGNWrr128 VR128:$src1, VR128:$src2)>;
+ def : Pat<(X86psignd VR128:$src1, VR128:$src2),
+ (VPSIGNDrr128 VR128:$src1, VR128:$src2)>;
+}
//===---------------------------------------------------------------------===//
// SSSE3 - Packed Align Instruction Patterns
@@ -3560,33 +4943,35 @@ multiclass ssse3_palign<string asm, bit Is2Addr = 1> {
let Predicates = [HasAVX] in
defm VPALIGN : ssse3_palign<"vpalignr", 0>, VEX_4V;
-let Constraints = "$src1 = $dst" in
+let Constraints = "$src1 = $dst", Predicates = [HasSSSE3] in
defm PALIGN : ssse3_palign<"palignr">;
-let AddedComplexity = 5 in {
-def : Pat<(v4i32 (palign:$src3 VR128:$src1, VR128:$src2)),
- (PALIGNR128rr VR128:$src2, VR128:$src1,
- (SHUFFLE_get_palign_imm VR128:$src3))>,
- Requires<[HasSSSE3]>;
-def : Pat<(v4f32 (palign:$src3 VR128:$src1, VR128:$src2)),
- (PALIGNR128rr VR128:$src2, VR128:$src1,
- (SHUFFLE_get_palign_imm VR128:$src3))>,
- Requires<[HasSSSE3]>;
-def : Pat<(v8i16 (palign:$src3 VR128:$src1, VR128:$src2)),
- (PALIGNR128rr VR128:$src2, VR128:$src1,
- (SHUFFLE_get_palign_imm VR128:$src3))>,
- Requires<[HasSSSE3]>;
-def : Pat<(v16i8 (palign:$src3 VR128:$src1, VR128:$src2)),
- (PALIGNR128rr VR128:$src2, VR128:$src1,
- (SHUFFLE_get_palign_imm VR128:$src3))>,
- Requires<[HasSSSE3]>;
+let Predicates = [HasSSSE3] in {
+def : Pat<(v4i32 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
+def : Pat<(v4f32 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
+def : Pat<(v8i16 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
+def : Pat<(v16i8 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
+}
+
+let Predicates = [HasAVX] in {
+def : Pat<(v4i32 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (VPALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
+def : Pat<(v4f32 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (VPALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
+def : Pat<(v8i16 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (VPALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
+def : Pat<(v16i8 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
+ (VPALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
}
//===---------------------------------------------------------------------===//
-// SSSE3 Misc Instructions
+// SSSE3 - Thread synchronization
//===---------------------------------------------------------------------===//
-// Thread synchronization
let usesCustomInserter = 1 in {
def MONITOR : PseudoI<(outs), (ins i32mem:$src1, GR32:$src2, GR32:$src3),
[(int_x86_sse3_monitor addr:$src1, GR32:$src2, GR32:$src3)]>;
@@ -3609,338 +4994,6 @@ def : InstAlias<"monitor %eax, %ecx, %edx", (MONITORrrr)>,
def : InstAlias<"monitor %rax, %rcx, %rdx", (MONITORrrr)>,
Requires<[In64BitMode]>;
-//===---------------------------------------------------------------------===//
-// Non-Instruction Patterns
-//===---------------------------------------------------------------------===//
-
-// extload f32 -> f64. This matches load+fextend because we have a hack in
-// the isel (PreprocessForFPConvert) that can introduce loads after dag
-// combine.
-// Since these loads aren't folded into the fextend, we have to match it
-// explicitly here.
-let Predicates = [HasSSE2] in
- def : Pat<(fextend (loadf32 addr:$src)),
- (CVTSS2SDrm addr:$src)>;
-
-// FIXME: According to the intel manual, DEST[127:64] <- SRC1[127:64], while
-// in the non-AVX version bits 127:64 aren't touched. Find a better way to
-// represent this instead of always zeroing SRC1. One possible solution is
-// to represent the instruction w/ something similar as the "$src1 = $dst"
-// constraint but without the tied operands.
-let Predicates = [HasAVX] in
- def : Pat<(fextend (loadf32 addr:$src)),
- (VCVTSS2SDrm (f32 (EXTRACT_SUBREG (AVX_SET0PS), sub_ss)),
- addr:$src)>;
-
-// bit_convert
-let Predicates = [HasXMMInt] in {
- def : Pat<(v2i64 (bitconvert (v4i32 VR128:$src))), (v2i64 VR128:$src)>;
- def : Pat<(v2i64 (bitconvert (v8i16 VR128:$src))), (v2i64 VR128:$src)>;
- def : Pat<(v2i64 (bitconvert (v16i8 VR128:$src))), (v2i64 VR128:$src)>;
- def : Pat<(v2i64 (bitconvert (v2f64 VR128:$src))), (v2i64 VR128:$src)>;
- def : Pat<(v2i64 (bitconvert (v4f32 VR128:$src))), (v2i64 VR128:$src)>;
- def : Pat<(v4i32 (bitconvert (v2i64 VR128:$src))), (v4i32 VR128:$src)>;
- def : Pat<(v4i32 (bitconvert (v8i16 VR128:$src))), (v4i32 VR128:$src)>;
- def : Pat<(v4i32 (bitconvert (v16i8 VR128:$src))), (v4i32 VR128:$src)>;
- def : Pat<(v4i32 (bitconvert (v2f64 VR128:$src))), (v4i32 VR128:$src)>;
- def : Pat<(v4i32 (bitconvert (v4f32 VR128:$src))), (v4i32 VR128:$src)>;
- def : Pat<(v8i16 (bitconvert (v2i64 VR128:$src))), (v8i16 VR128:$src)>;
- def : Pat<(v8i16 (bitconvert (v4i32 VR128:$src))), (v8i16 VR128:$src)>;
- def : Pat<(v8i16 (bitconvert (v16i8 VR128:$src))), (v8i16 VR128:$src)>;
- def : Pat<(v8i16 (bitconvert (v2f64 VR128:$src))), (v8i16 VR128:$src)>;
- def : Pat<(v8i16 (bitconvert (v4f32 VR128:$src))), (v8i16 VR128:$src)>;
- def : Pat<(v16i8 (bitconvert (v2i64 VR128:$src))), (v16i8 VR128:$src)>;
- def : Pat<(v16i8 (bitconvert (v4i32 VR128:$src))), (v16i8 VR128:$src)>;
- def : Pat<(v16i8 (bitconvert (v8i16 VR128:$src))), (v16i8 VR128:$src)>;
- def : Pat<(v16i8 (bitconvert (v2f64 VR128:$src))), (v16i8 VR128:$src)>;
- def : Pat<(v16i8 (bitconvert (v4f32 VR128:$src))), (v16i8 VR128:$src)>;
- def : Pat<(v4f32 (bitconvert (v2i64 VR128:$src))), (v4f32 VR128:$src)>;
- def : Pat<(v4f32 (bitconvert (v4i32 VR128:$src))), (v4f32 VR128:$src)>;
- def : Pat<(v4f32 (bitconvert (v8i16 VR128:$src))), (v4f32 VR128:$src)>;
- def : Pat<(v4f32 (bitconvert (v16i8 VR128:$src))), (v4f32 VR128:$src)>;
- def : Pat<(v4f32 (bitconvert (v2f64 VR128:$src))), (v4f32 VR128:$src)>;
- def : Pat<(v2f64 (bitconvert (v2i64 VR128:$src))), (v2f64 VR128:$src)>;
- def : Pat<(v2f64 (bitconvert (v4i32 VR128:$src))), (v2f64 VR128:$src)>;
- def : Pat<(v2f64 (bitconvert (v8i16 VR128:$src))), (v2f64 VR128:$src)>;
- def : Pat<(v2f64 (bitconvert (v16i8 VR128:$src))), (v2f64 VR128:$src)>;
- def : Pat<(v2f64 (bitconvert (v4f32 VR128:$src))), (v2f64 VR128:$src)>;
-}
-
-let Predicates = [HasAVX] in {
- def : Pat<(v4f64 (bitconvert (v8f32 VR256:$src))), (v4f64 VR256:$src)>;
- def : Pat<(v4f64 (bitconvert (v4i64 VR256:$src))), (v4f64 VR256:$src)>;
- def : Pat<(v4f64 (bitconvert (v32i8 VR256:$src))), (v4f64 VR256:$src)>;
- def : Pat<(v8f32 (bitconvert (v4i64 VR256:$src))), (v8f32 VR256:$src)>;
- def : Pat<(v8f32 (bitconvert (v4f64 VR256:$src))), (v8f32 VR256:$src)>;
- def : Pat<(v8f32 (bitconvert (v32i8 VR256:$src))), (v8f32 VR256:$src)>;
- def : Pat<(v4i64 (bitconvert (v8f32 VR256:$src))), (v4i64 VR256:$src)>;
- def : Pat<(v4i64 (bitconvert (v4f64 VR256:$src))), (v4i64 VR256:$src)>;
- def : Pat<(v4i64 (bitconvert (v32i8 VR256:$src))), (v4i64 VR256:$src)>;
- def : Pat<(v32i8 (bitconvert (v4f64 VR256:$src))), (v32i8 VR256:$src)>;
- def : Pat<(v32i8 (bitconvert (v4i64 VR256:$src))), (v32i8 VR256:$src)>;
- def : Pat<(v32i8 (bitconvert (v8f32 VR256:$src))), (v32i8 VR256:$src)>;
- def : Pat<(v32i8 (bitconvert (v8i32 VR256:$src))), (v32i8 VR256:$src)>;
- def : Pat<(v8i32 (bitconvert (v32i8 VR256:$src))), (v8i32 VR256:$src)>;
-}
-
-// Move scalar to XMM zero-extended
-// movd to XMM register zero-extends
-let AddedComplexity = 15 in {
-// Zeroing a VR128 then do a MOVS{S|D} to the lower bits.
-def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector FR64:$src)))),
- (MOVSDrr (v2f64 (V_SET0PS)), FR64:$src)>;
-def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector FR32:$src)))),
- (MOVSSrr (v4f32 (V_SET0PS)), FR32:$src)>;
-def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))),
- (MOVSSrr (v4f32 (V_SET0PS)),
- (f32 (EXTRACT_SUBREG (v4f32 VR128:$src), sub_ss)))>;
-def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))),
- (MOVSSrr (v4i32 (V_SET0PI)),
- (EXTRACT_SUBREG (v4i32 VR128:$src), sub_ss))>;
-}
-
-// Splat v2f64 / v2i64
-let AddedComplexity = 10 in {
-def : Pat<(splat_lo (v2f64 VR128:$src), (undef)),
- (UNPCKLPDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>;
-def : Pat<(unpckh (v2f64 VR128:$src), (undef)),
- (UNPCKHPDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>;
-def : Pat<(splat_lo (v2i64 VR128:$src), (undef)),
- (PUNPCKLQDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>;
-def : Pat<(unpckh (v2i64 VR128:$src), (undef)),
- (PUNPCKHQDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>;
-}
-
-// Special unary SHUFPSrri case.
-def : Pat<(v4f32 (pshufd:$src3 VR128:$src1, (undef))),
- (SHUFPSrri VR128:$src1, VR128:$src1,
- (SHUFFLE_get_shuf_imm VR128:$src3))>;
-let AddedComplexity = 5 in
-def : Pat<(v4f32 (pshufd:$src2 VR128:$src1, (undef))),
- (PSHUFDri VR128:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>,
- Requires<[HasSSE2]>;
-// Special unary SHUFPDrri case.
-def : Pat<(v2i64 (pshufd:$src3 VR128:$src1, (undef))),
- (SHUFPDrri VR128:$src1, VR128:$src1,
- (SHUFFLE_get_shuf_imm VR128:$src3))>,
- Requires<[HasSSE2]>;
-// Special unary SHUFPDrri case.
-def : Pat<(v2f64 (pshufd:$src3 VR128:$src1, (undef))),
- (SHUFPDrri VR128:$src1, VR128:$src1,
- (SHUFFLE_get_shuf_imm VR128:$src3))>,
- Requires<[HasSSE2]>;
-// Unary v4f32 shuffle with PSHUF* in order to fold a load.
-def : Pat<(pshufd:$src2 (bc_v4i32 (memopv4f32 addr:$src1)), (undef)),
- (PSHUFDmi addr:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>,
- Requires<[HasSSE2]>;
-
-// Special binary v4i32 shuffle cases with SHUFPS.
-def : Pat<(v4i32 (shufp:$src3 VR128:$src1, (v4i32 VR128:$src2))),
- (SHUFPSrri VR128:$src1, VR128:$src2,
- (SHUFFLE_get_shuf_imm VR128:$src3))>,
- Requires<[HasSSE2]>;
-def : Pat<(v4i32 (shufp:$src3 VR128:$src1, (bc_v4i32 (memopv2i64 addr:$src2)))),
- (SHUFPSrmi VR128:$src1, addr:$src2,
- (SHUFFLE_get_shuf_imm VR128:$src3))>,
- Requires<[HasSSE2]>;
-// Special binary v2i64 shuffle cases using SHUFPDrri.
-def : Pat<(v2i64 (shufp:$src3 VR128:$src1, VR128:$src2)),
- (SHUFPDrri VR128:$src1, VR128:$src2,
- (SHUFFLE_get_shuf_imm VR128:$src3))>,
- Requires<[HasSSE2]>;
-
-// vector_shuffle v1, <undef>, <0, 0, 1, 1, ...>
-let AddedComplexity = 15 in {
-def : Pat<(v4i32 (unpckl_undef:$src2 VR128:$src, (undef))),
- (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>,
- Requires<[OptForSpeed, HasSSE2]>;
-def : Pat<(v4f32 (unpckl_undef:$src2 VR128:$src, (undef))),
- (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>,
- Requires<[OptForSpeed, HasSSE2]>;
-}
-let AddedComplexity = 10 in {
-def : Pat<(v4f32 (unpckl_undef VR128:$src, (undef))),
- (UNPCKLPSrr VR128:$src, VR128:$src)>;
-def : Pat<(v16i8 (unpckl_undef VR128:$src, (undef))),
- (PUNPCKLBWrr VR128:$src, VR128:$src)>;
-def : Pat<(v8i16 (unpckl_undef VR128:$src, (undef))),
- (PUNPCKLWDrr VR128:$src, VR128:$src)>;
-def : Pat<(v4i32 (unpckl_undef VR128:$src, (undef))),
- (PUNPCKLDQrr VR128:$src, VR128:$src)>;
-}
-
-// vector_shuffle v1, <undef>, <2, 2, 3, 3, ...>
-let AddedComplexity = 15 in {
-def : Pat<(v4i32 (unpckh_undef:$src2 VR128:$src, (undef))),
- (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>,
- Requires<[OptForSpeed, HasSSE2]>;
-def : Pat<(v4f32 (unpckh_undef:$src2 VR128:$src, (undef))),
- (PSHUFDri VR128:$src, (SHUFFLE_get_shuf_imm VR128:$src2))>,
- Requires<[OptForSpeed, HasSSE2]>;
-}
-let AddedComplexity = 10 in {
-def : Pat<(v4f32 (unpckh_undef VR128:$src, (undef))),
- (UNPCKHPSrr VR128:$src, VR128:$src)>;
-def : Pat<(v16i8 (unpckh_undef VR128:$src, (undef))),
- (PUNPCKHBWrr VR128:$src, VR128:$src)>;
-def : Pat<(v8i16 (unpckh_undef VR128:$src, (undef))),
- (PUNPCKHWDrr VR128:$src, VR128:$src)>;
-def : Pat<(v4i32 (unpckh_undef VR128:$src, (undef))),
- (PUNPCKHDQrr VR128:$src, VR128:$src)>;
-}
-
-let AddedComplexity = 20 in {
-// vector_shuffle v1, v2 <0, 1, 4, 5> using MOVLHPS
-def : Pat<(v4i32 (movlhps VR128:$src1, VR128:$src2)),
- (MOVLHPSrr VR128:$src1, VR128:$src2)>;
-
-// vector_shuffle v1, v2 <6, 7, 2, 3> using MOVHLPS
-def : Pat<(v4i32 (movhlps VR128:$src1, VR128:$src2)),
- (MOVHLPSrr VR128:$src1, VR128:$src2)>;
-
-// vector_shuffle v1, undef <2, ?, ?, ?> using MOVHLPS
-def : Pat<(v4f32 (movhlps_undef VR128:$src1, (undef))),
- (MOVHLPSrr VR128:$src1, VR128:$src1)>;
-def : Pat<(v4i32 (movhlps_undef VR128:$src1, (undef))),
- (MOVHLPSrr VR128:$src1, VR128:$src1)>;
-}
-
-let AddedComplexity = 20 in {
-// vector_shuffle v1, (load v2) <4, 5, 2, 3> using MOVLPS
-def : Pat<(v4f32 (movlp VR128:$src1, (load addr:$src2))),
- (MOVLPSrm VR128:$src1, addr:$src2)>;
-def : Pat<(v2f64 (movlp VR128:$src1, (load addr:$src2))),
- (MOVLPDrm VR128:$src1, addr:$src2)>;
-def : Pat<(v4i32 (movlp VR128:$src1, (load addr:$src2))),
- (MOVLPSrm VR128:$src1, addr:$src2)>;
-def : Pat<(v2i64 (movlp VR128:$src1, (load addr:$src2))),
- (MOVLPDrm VR128:$src1, addr:$src2)>;
-}
-
-// (store (vector_shuffle (load addr), v2, <4, 5, 2, 3>), addr) using MOVLPS
-def : Pat<(store (v4f32 (movlp (load addr:$src1), VR128:$src2)), addr:$src1),
- (MOVLPSmr addr:$src1, VR128:$src2)>;
-def : Pat<(store (v2f64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1),
- (MOVLPDmr addr:$src1, VR128:$src2)>;
-def : Pat<(store (v4i32 (movlp (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2)),
- addr:$src1),
- (MOVLPSmr addr:$src1, VR128:$src2)>;
-def : Pat<(store (v2i64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1),
- (MOVLPDmr addr:$src1, VR128:$src2)>;
-
-let AddedComplexity = 15 in {
-// Setting the lowest element in the vector.
-def : Pat<(v4i32 (movl VR128:$src1, VR128:$src2)),
- (MOVSSrr (v4i32 VR128:$src1),
- (EXTRACT_SUBREG (v4i32 VR128:$src2), sub_ss))>;
-def : Pat<(v2i64 (movl VR128:$src1, VR128:$src2)),
- (MOVSDrr (v2i64 VR128:$src1),
- (EXTRACT_SUBREG (v2i64 VR128:$src2), sub_sd))>;
-
-// vector_shuffle v1, v2 <4, 5, 2, 3> using movsd
-def : Pat<(v4f32 (movlp VR128:$src1, VR128:$src2)),
- (MOVSDrr VR128:$src1, (EXTRACT_SUBREG VR128:$src2, sub_sd))>,
- Requires<[HasSSE2]>;
-def : Pat<(v4i32 (movlp VR128:$src1, VR128:$src2)),
- (MOVSDrr VR128:$src1, (EXTRACT_SUBREG VR128:$src2, sub_sd))>,
- Requires<[HasSSE2]>;
-}
-
-// vector_shuffle v1, v2 <4, 5, 2, 3> using SHUFPSrri (we prefer movsd, but
-// fall back to this for SSE1)
-def : Pat<(v4f32 (movlp:$src3 VR128:$src1, (v4f32 VR128:$src2))),
- (SHUFPSrri VR128:$src2, VR128:$src1,
- (SHUFFLE_get_shuf_imm VR128:$src3))>;
-
-// Set lowest element and zero upper elements.
-def : Pat<(v2f64 (X86vzmovl (v2f64 VR128:$src))),
- (MOVZPQILo2PQIrr VR128:$src)>, Requires<[HasSSE2]>;
-
-// vector -> vector casts
-def : Pat<(v4f32 (sint_to_fp (v4i32 VR128:$src))),
- (Int_CVTDQ2PSrr VR128:$src)>, Requires<[HasSSE2]>;
-def : Pat<(v4i32 (fp_to_sint (v4f32 VR128:$src))),
- (CVTTPS2DQrr VR128:$src)>, Requires<[HasSSE2]>;
-
-// Use movaps / movups for SSE integer load / store (one byte shorter).
-// The instructions selected below are then converted to MOVDQA/MOVDQU
-// during the SSE domain pass.
-let Predicates = [HasSSE1] in {
- def : Pat<(alignedloadv4i32 addr:$src),
- (MOVAPSrm addr:$src)>;
- def : Pat<(loadv4i32 addr:$src),
- (MOVUPSrm addr:$src)>;
- def : Pat<(alignedloadv2i64 addr:$src),
- (MOVAPSrm addr:$src)>;
- def : Pat<(loadv2i64 addr:$src),
- (MOVUPSrm addr:$src)>;
-
- def : Pat<(alignedstore (v2i64 VR128:$src), addr:$dst),
- (MOVAPSmr addr:$dst, VR128:$src)>;
- def : Pat<(alignedstore (v4i32 VR128:$src), addr:$dst),
- (MOVAPSmr addr:$dst, VR128:$src)>;
- def : Pat<(alignedstore (v8i16 VR128:$src), addr:$dst),
- (MOVAPSmr addr:$dst, VR128:$src)>;
- def : Pat<(alignedstore (v16i8 VR128:$src), addr:$dst),
- (MOVAPSmr addr:$dst, VR128:$src)>;
- def : Pat<(store (v2i64 VR128:$src), addr:$dst),
- (MOVUPSmr addr:$dst, VR128:$src)>;
- def : Pat<(store (v4i32 VR128:$src), addr:$dst),
- (MOVUPSmr addr:$dst, VR128:$src)>;
- def : Pat<(store (v8i16 VR128:$src), addr:$dst),
- (MOVUPSmr addr:$dst, VR128:$src)>;
- def : Pat<(store (v16i8 VR128:$src), addr:$dst),
- (MOVUPSmr addr:$dst, VR128:$src)>;
-}
-
-// Use vmovaps/vmovups for AVX integer load/store.
-let Predicates = [HasAVX] in {
- // 128-bit load/store
- def : Pat<(alignedloadv4i32 addr:$src),
- (VMOVAPSrm addr:$src)>;
- def : Pat<(loadv4i32 addr:$src),
- (VMOVUPSrm addr:$src)>;
- def : Pat<(alignedloadv2i64 addr:$src),
- (VMOVAPSrm addr:$src)>;
- def : Pat<(loadv2i64 addr:$src),
- (VMOVUPSrm addr:$src)>;
-
- def : Pat<(alignedstore (v2i64 VR128:$src), addr:$dst),
- (VMOVAPSmr addr:$dst, VR128:$src)>;
- def : Pat<(alignedstore (v4i32 VR128:$src), addr:$dst),
- (VMOVAPSmr addr:$dst, VR128:$src)>;
- def : Pat<(alignedstore (v8i16 VR128:$src), addr:$dst),
- (VMOVAPSmr addr:$dst, VR128:$src)>;
- def : Pat<(alignedstore (v16i8 VR128:$src), addr:$dst),
- (VMOVAPSmr addr:$dst, VR128:$src)>;
- def : Pat<(store (v2i64 VR128:$src), addr:$dst),
- (VMOVUPSmr addr:$dst, VR128:$src)>;
- def : Pat<(store (v4i32 VR128:$src), addr:$dst),
- (VMOVUPSmr addr:$dst, VR128:$src)>;
- def : Pat<(store (v8i16 VR128:$src), addr:$dst),
- (VMOVUPSmr addr:$dst, VR128:$src)>;
- def : Pat<(store (v16i8 VR128:$src), addr:$dst),
- (VMOVUPSmr addr:$dst, VR128:$src)>;
-
- // 256-bit load/store
- def : Pat<(alignedloadv4i64 addr:$src),
- (VMOVAPSYrm addr:$src)>;
- def : Pat<(loadv4i64 addr:$src),
- (VMOVUPSYrm addr:$src)>;
- def : Pat<(alignedloadv8i32 addr:$src),
- (VMOVAPSYrm addr:$src)>;
- def : Pat<(loadv8i32 addr:$src),
- (VMOVUPSYrm addr:$src)>;
- def : Pat<(alignedstore (v4i64 VR256:$src), addr:$dst),
- (VMOVAPSYmr addr:$dst, VR256:$src)>;
- def : Pat<(alignedstore (v8i32 VR256:$src), addr:$dst),
- (VMOVAPSYmr addr:$dst, VR256:$src)>;
- def : Pat<(store (v4i64 VR256:$src), addr:$dst),
- (VMOVUPSYmr addr:$dst, VR256:$src)>;
- def : Pat<(store (v8i32 VR256:$src), addr:$dst),
- (VMOVUPSYmr addr:$dst, VR256:$src)>;
-}
-
//===----------------------------------------------------------------------===//
// SSE4.1 - Packed Move with Sign/Zero Extend
//===----------------------------------------------------------------------===//
@@ -3979,36 +5032,71 @@ defm PMOVZXBW : SS41I_binop_rm_int8<0x30, "pmovzxbw", int_x86_sse41_pmovzxbw>;
defm PMOVZXWD : SS41I_binop_rm_int8<0x33, "pmovzxwd", int_x86_sse41_pmovzxwd>;
defm PMOVZXDQ : SS41I_binop_rm_int8<0x35, "pmovzxdq", int_x86_sse41_pmovzxdq>;
-// Common patterns involving scalar load.
-def : Pat<(int_x86_sse41_pmovsxbw (vzmovl_v2i64 addr:$src)),
- (PMOVSXBWrm addr:$src)>, Requires<[HasSSE41]>;
-def : Pat<(int_x86_sse41_pmovsxbw (vzload_v2i64 addr:$src)),
- (PMOVSXBWrm addr:$src)>, Requires<[HasSSE41]>;
+let Predicates = [HasSSE41] in {
+ // Common patterns involving scalar load.
+ def : Pat<(int_x86_sse41_pmovsxbw (vzmovl_v2i64 addr:$src)),
+ (PMOVSXBWrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovsxbw (vzload_v2i64 addr:$src)),
+ (PMOVSXBWrm addr:$src)>;
+
+ def : Pat<(int_x86_sse41_pmovsxwd (vzmovl_v2i64 addr:$src)),
+ (PMOVSXWDrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovsxwd (vzload_v2i64 addr:$src)),
+ (PMOVSXWDrm addr:$src)>;
+
+ def : Pat<(int_x86_sse41_pmovsxdq (vzmovl_v2i64 addr:$src)),
+ (PMOVSXDQrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovsxdq (vzload_v2i64 addr:$src)),
+ (PMOVSXDQrm addr:$src)>;
-def : Pat<(int_x86_sse41_pmovsxwd (vzmovl_v2i64 addr:$src)),
- (PMOVSXWDrm addr:$src)>, Requires<[HasSSE41]>;
-def : Pat<(int_x86_sse41_pmovsxwd (vzload_v2i64 addr:$src)),
- (PMOVSXWDrm addr:$src)>, Requires<[HasSSE41]>;
+ def : Pat<(int_x86_sse41_pmovzxbw (vzmovl_v2i64 addr:$src)),
+ (PMOVZXBWrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovzxbw (vzload_v2i64 addr:$src)),
+ (PMOVZXBWrm addr:$src)>;
-def : Pat<(int_x86_sse41_pmovsxdq (vzmovl_v2i64 addr:$src)),
- (PMOVSXDQrm addr:$src)>, Requires<[HasSSE41]>;
-def : Pat<(int_x86_sse41_pmovsxdq (vzload_v2i64 addr:$src)),
- (PMOVSXDQrm addr:$src)>, Requires<[HasSSE41]>;
+ def : Pat<(int_x86_sse41_pmovzxwd (vzmovl_v2i64 addr:$src)),
+ (PMOVZXWDrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovzxwd (vzload_v2i64 addr:$src)),
+ (PMOVZXWDrm addr:$src)>;
-def : Pat<(int_x86_sse41_pmovzxbw (vzmovl_v2i64 addr:$src)),
- (PMOVZXBWrm addr:$src)>, Requires<[HasSSE41]>;
-def : Pat<(int_x86_sse41_pmovzxbw (vzload_v2i64 addr:$src)),
- (PMOVZXBWrm addr:$src)>, Requires<[HasSSE41]>;
+ def : Pat<(int_x86_sse41_pmovzxdq (vzmovl_v2i64 addr:$src)),
+ (PMOVZXDQrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovzxdq (vzload_v2i64 addr:$src)),
+ (PMOVZXDQrm addr:$src)>;
+}
+
+let Predicates = [HasAVX] in {
+ // Common patterns involving scalar load.
+ def : Pat<(int_x86_sse41_pmovsxbw (vzmovl_v2i64 addr:$src)),
+ (VPMOVSXBWrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovsxbw (vzload_v2i64 addr:$src)),
+ (VPMOVSXBWrm addr:$src)>;
+
+ def : Pat<(int_x86_sse41_pmovsxwd (vzmovl_v2i64 addr:$src)),
+ (VPMOVSXWDrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovsxwd (vzload_v2i64 addr:$src)),
+ (VPMOVSXWDrm addr:$src)>;
-def : Pat<(int_x86_sse41_pmovzxwd (vzmovl_v2i64 addr:$src)),
- (PMOVZXWDrm addr:$src)>, Requires<[HasSSE41]>;
-def : Pat<(int_x86_sse41_pmovzxwd (vzload_v2i64 addr:$src)),
- (PMOVZXWDrm addr:$src)>, Requires<[HasSSE41]>;
+ def : Pat<(int_x86_sse41_pmovsxdq (vzmovl_v2i64 addr:$src)),
+ (VPMOVSXDQrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovsxdq (vzload_v2i64 addr:$src)),
+ (VPMOVSXDQrm addr:$src)>;
-def : Pat<(int_x86_sse41_pmovzxdq (vzmovl_v2i64 addr:$src)),
- (PMOVZXDQrm addr:$src)>, Requires<[HasSSE41]>;
-def : Pat<(int_x86_sse41_pmovzxdq (vzload_v2i64 addr:$src)),
- (PMOVZXDQrm addr:$src)>, Requires<[HasSSE41]>;
+ def : Pat<(int_x86_sse41_pmovzxbw (vzmovl_v2i64 addr:$src)),
+ (VPMOVZXBWrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovzxbw (vzload_v2i64 addr:$src)),
+ (VPMOVZXBWrm addr:$src)>;
+
+ def : Pat<(int_x86_sse41_pmovzxwd (vzmovl_v2i64 addr:$src)),
+ (VPMOVZXWDrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovzxwd (vzload_v2i64 addr:$src)),
+ (VPMOVZXWDrm addr:$src)>;
+
+ def : Pat<(int_x86_sse41_pmovzxdq (vzmovl_v2i64 addr:$src)),
+ (VPMOVZXDQrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovzxdq (vzload_v2i64 addr:$src)),
+ (VPMOVZXDQrm addr:$src)>;
+}
multiclass SS41I_binop_rm_int4<bits<8> opc, string OpcodeStr, Intrinsic IntId> {
@@ -4039,17 +5127,31 @@ defm PMOVSXWQ : SS41I_binop_rm_int4<0x24, "pmovsxwq", int_x86_sse41_pmovsxwq>;
defm PMOVZXBD : SS41I_binop_rm_int4<0x31, "pmovzxbd", int_x86_sse41_pmovzxbd>;
defm PMOVZXWQ : SS41I_binop_rm_int4<0x34, "pmovzxwq", int_x86_sse41_pmovzxwq>;
-// Common patterns involving scalar load
-def : Pat<(int_x86_sse41_pmovsxbd (vzmovl_v4i32 addr:$src)),
- (PMOVSXBDrm addr:$src)>, Requires<[HasSSE41]>;
-def : Pat<(int_x86_sse41_pmovsxwq (vzmovl_v4i32 addr:$src)),
- (PMOVSXWQrm addr:$src)>, Requires<[HasSSE41]>;
+let Predicates = [HasSSE41] in {
+ // Common patterns involving scalar load
+ def : Pat<(int_x86_sse41_pmovsxbd (vzmovl_v4i32 addr:$src)),
+ (PMOVSXBDrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovsxwq (vzmovl_v4i32 addr:$src)),
+ (PMOVSXWQrm addr:$src)>;
+
+ def : Pat<(int_x86_sse41_pmovzxbd (vzmovl_v4i32 addr:$src)),
+ (PMOVZXBDrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovzxwq (vzmovl_v4i32 addr:$src)),
+ (PMOVZXWQrm addr:$src)>;
+}
-def : Pat<(int_x86_sse41_pmovzxbd (vzmovl_v4i32 addr:$src)),
- (PMOVZXBDrm addr:$src)>, Requires<[HasSSE41]>;
-def : Pat<(int_x86_sse41_pmovzxwq (vzmovl_v4i32 addr:$src)),
- (PMOVZXWQrm addr:$src)>, Requires<[HasSSE41]>;
+let Predicates = [HasAVX] in {
+ // Common patterns involving scalar load
+ def : Pat<(int_x86_sse41_pmovsxbd (vzmovl_v4i32 addr:$src)),
+ (VPMOVSXBDrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovsxwq (vzmovl_v4i32 addr:$src)),
+ (VPMOVSXWQrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovzxbd (vzmovl_v4i32 addr:$src)),
+ (VPMOVZXBDrm addr:$src)>;
+ def : Pat<(int_x86_sse41_pmovzxwq (vzmovl_v4i32 addr:$src)),
+ (VPMOVZXWQrm addr:$src)>;
+}
multiclass SS41I_binop_rm_int2<bits<8> opc, string OpcodeStr, Intrinsic IntId> {
def rr : SS48I<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
@@ -4073,16 +5175,31 @@ defm VPMOVZXBQ : SS41I_binop_rm_int2<0x32, "vpmovzxbq", int_x86_sse41_pmovzxbq>,
defm PMOVSXBQ : SS41I_binop_rm_int2<0x22, "pmovsxbq", int_x86_sse41_pmovsxbq>;
defm PMOVZXBQ : SS41I_binop_rm_int2<0x32, "pmovzxbq", int_x86_sse41_pmovzxbq>;
-// Common patterns involving scalar load
-def : Pat<(int_x86_sse41_pmovsxbq
- (bitconvert (v4i32 (X86vzmovl
- (v4i32 (scalar_to_vector (loadi32 addr:$src))))))),
- (PMOVSXBQrm addr:$src)>, Requires<[HasSSE41]>;
+let Predicates = [HasSSE41] in {
+ // Common patterns involving scalar load
+ def : Pat<(int_x86_sse41_pmovsxbq
+ (bitconvert (v4i32 (X86vzmovl
+ (v4i32 (scalar_to_vector (loadi32 addr:$src))))))),
+ (PMOVSXBQrm addr:$src)>;
+
+ def : Pat<(int_x86_sse41_pmovzxbq
+ (bitconvert (v4i32 (X86vzmovl
+ (v4i32 (scalar_to_vector (loadi32 addr:$src))))))),
+ (PMOVZXBQrm addr:$src)>;
+}
+
+let Predicates = [HasAVX] in {
+ // Common patterns involving scalar load
+ def : Pat<(int_x86_sse41_pmovsxbq
+ (bitconvert (v4i32 (X86vzmovl
+ (v4i32 (scalar_to_vector (loadi32 addr:$src))))))),
+ (VPMOVSXBQrm addr:$src)>;
-def : Pat<(int_x86_sse41_pmovzxbq
- (bitconvert (v4i32 (X86vzmovl
- (v4i32 (scalar_to_vector (loadi32 addr:$src))))))),
- (PMOVZXBQrm addr:$src)>, Requires<[HasSSE41]>;
+ def : Pat<(int_x86_sse41_pmovzxbq
+ (bitconvert (v4i32 (X86vzmovl
+ (v4i32 (scalar_to_vector (loadi32 addr:$src))))))),
+ (VPMOVZXBQrm addr:$src)>;
+}
//===----------------------------------------------------------------------===//
// SSE4.1 - Extract Instructions
@@ -4208,7 +5325,12 @@ def : Pat<(store (f32 (bitconvert (extractelt (bc_v4i32 (v4f32 VR128:$src1)),
imm:$src2))),
addr:$dst),
(EXTRACTPSmr addr:$dst, VR128:$src1, imm:$src2)>,
- Requires<[HasSSE41]>;
+ Requires<[HasSSE41]>;
+def : Pat<(store (f32 (bitconvert (extractelt (bc_v4i32 (v4f32 VR128:$src1)),
+ imm:$src2))),
+ addr:$dst),
+ (VEXTRACTPSmr addr:$dst, VR128:$src1, imm:$src2)>,
+ Requires<[HasAVX]>;
//===----------------------------------------------------------------------===//
// SSE4.1 - Insert Instructions
@@ -4297,7 +5419,7 @@ let Constraints = "$src1 = $dst" in
// in the target vector.
multiclass SS41I_insertf32<bits<8> opc, string asm, bit Is2Addr = 1> {
def rr : SS4AIi8<opc, MRMSrcReg, (outs VR128:$dst),
- (ins VR128:$src1, VR128:$src2, i32i8imm:$src3),
+ (ins VR128:$src1, VR128:$src2, u32u8imm:$src3),
!if(Is2Addr,
!strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
!strconcat(asm,
@@ -4306,7 +5428,7 @@ multiclass SS41I_insertf32<bits<8> opc, string asm, bit Is2Addr = 1> {
(X86insrtps VR128:$src1, VR128:$src2, imm:$src3))]>,
OpSize;
def rm : SS4AIi8<opc, MRMSrcMem, (outs VR128:$dst),
- (ins VR128:$src1, f32mem:$src2, i32i8imm:$src3),
+ (ins VR128:$src1, f32mem:$src2, u32u8imm:$src3),
!if(Is2Addr,
!strconcat(asm, "\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
!strconcat(asm,
@@ -4348,7 +5470,7 @@ multiclass sse41_fp_unop_rm<bits<8> opcps, bits<8> opcpd, string OpcodeStr,
// Vector intrinsic operation, mem
def PSm : Ii8<opcps, MRMSrcMem,
- (outs RC:$dst), (ins f256mem:$src1, i32i8imm:$src2),
+ (outs RC:$dst), (ins x86memop:$src1, i32i8imm:$src2),
!strconcat(OpcodeStr,
"ps\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
[(set RC:$dst,
@@ -4366,7 +5488,7 @@ multiclass sse41_fp_unop_rm<bits<8> opcps, bits<8> opcpd, string OpcodeStr,
// Vector intrinsic operation, mem
def PDm : SS4AIi8<opcpd, MRMSrcMem,
- (outs RC:$dst), (ins f256mem:$src1, i32i8imm:$src2),
+ (outs RC:$dst), (ins x86memop:$src1, i32i8imm:$src2),
!strconcat(OpcodeStr,
"pd\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
[(set RC:$dst,
@@ -4501,14 +5623,14 @@ let Predicates = [HasAVX] in {
int_x86_avx_round_pd_256>, VEX;
defm VROUND : sse41_fp_binop_rm<0x0A, 0x0B, "vround",
int_x86_sse41_round_ss,
- int_x86_sse41_round_sd, 0>, VEX_4V;
+ int_x86_sse41_round_sd, 0>, VEX_4V, VEX_LIG;
// Instructions for the assembler
defm VROUND : sse41_fp_unop_rm_avx_p<0x08, 0x09, VR128, f128mem, "vround">,
VEX;
defm VROUNDY : sse41_fp_unop_rm_avx_p<0x08, 0x09, VR256, f256mem, "vround">,
VEX;
- defm VROUND : sse41_fp_binop_rm_avx_s<0x0A, 0x0B, "vround">, VEX_4V;
+ defm VROUND : sse41_fp_binop_rm_avx_s<0x0A, 0x0B, "vround">, VEX_4V, VEX_LIG;
}
defm ROUND : sse41_fp_unop_rm<0x08, 0x09, "round", f128mem, VR128,
@@ -4578,26 +5700,34 @@ defm VTESTPDY : avx_bittest<0x0F, "vtestpd", VR256, f256mem, memopv4f64, v4f64>;
// SSE4.1 - Misc Instructions
//===----------------------------------------------------------------------===//
-def POPCNT16rr : I<0xB8, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src),
- "popcnt{w}\t{$src, $dst|$dst, $src}",
- [(set GR16:$dst, (ctpop GR16:$src))]>, OpSize, XS;
-def POPCNT16rm : I<0xB8, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src),
- "popcnt{w}\t{$src, $dst|$dst, $src}",
- [(set GR16:$dst, (ctpop (loadi16 addr:$src)))]>, OpSize, XS;
-
-def POPCNT32rr : I<0xB8, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src),
- "popcnt{l}\t{$src, $dst|$dst, $src}",
- [(set GR32:$dst, (ctpop GR32:$src))]>, XS;
-def POPCNT32rm : I<0xB8, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
- "popcnt{l}\t{$src, $dst|$dst, $src}",
- [(set GR32:$dst, (ctpop (loadi32 addr:$src)))]>, XS;
-
-def POPCNT64rr : RI<0xB8, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src),
- "popcnt{q}\t{$src, $dst|$dst, $src}",
- [(set GR64:$dst, (ctpop GR64:$src))]>, XS;
-def POPCNT64rm : RI<0xB8, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
- "popcnt{q}\t{$src, $dst|$dst, $src}",
- [(set GR64:$dst, (ctpop (loadi64 addr:$src)))]>, XS;
+let Defs = [EFLAGS], Predicates = [HasPOPCNT] in {
+ def POPCNT16rr : I<0xB8, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src),
+ "popcnt{w}\t{$src, $dst|$dst, $src}",
+ [(set GR16:$dst, (ctpop GR16:$src)), (implicit EFLAGS)]>,
+ OpSize, XS;
+ def POPCNT16rm : I<0xB8, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src),
+ "popcnt{w}\t{$src, $dst|$dst, $src}",
+ [(set GR16:$dst, (ctpop (loadi16 addr:$src))),
+ (implicit EFLAGS)]>, OpSize, XS;
+
+ def POPCNT32rr : I<0xB8, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src),
+ "popcnt{l}\t{$src, $dst|$dst, $src}",
+ [(set GR32:$dst, (ctpop GR32:$src)), (implicit EFLAGS)]>,
+ XS;
+ def POPCNT32rm : I<0xB8, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
+ "popcnt{l}\t{$src, $dst|$dst, $src}",
+ [(set GR32:$dst, (ctpop (loadi32 addr:$src))),
+ (implicit EFLAGS)]>, XS;
+
+ def POPCNT64rr : RI<0xB8, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src),
+ "popcnt{q}\t{$src, $dst|$dst, $src}",
+ [(set GR64:$dst, (ctpop GR64:$src)), (implicit EFLAGS)]>,
+ XS;
+ def POPCNT64rm : RI<0xB8, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
+ "popcnt{q}\t{$src, $dst|$dst, $src}",
+ [(set GR64:$dst, (ctpop (loadi64 addr:$src))),
+ (implicit EFLAGS)]>, XS;
+}
@@ -4666,6 +5796,11 @@ let Predicates = [HasAVX] in {
0>, VEX_4V;
defm VPMULDQ : SS41I_binop_rm_int<0x28, "vpmuldq", int_x86_sse41_pmuldq,
0>, VEX_4V;
+
+ def : Pat<(v2i64 (X86pcmpeqq VR128:$src1, VR128:$src2)),
+ (VPCMPEQQrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (X86pcmpeqq VR128:$src1, (memop addr:$src2))),
+ (VPCMPEQQrm VR128:$src1, addr:$src2)>;
}
let Constraints = "$src1 = $dst" in {
@@ -4720,7 +5855,7 @@ multiclass SS41I_binop_rmi_int<bits<8> opc, string OpcodeStr,
X86MemOperand x86memop, bit Is2Addr = 1> {
let isCommutable = 1 in
def rri : SS4AIi8<opc, MRMSrcReg, (outs RC:$dst),
- (ins RC:$src1, RC:$src2, i32i8imm:$src3),
+ (ins RC:$src1, RC:$src2, u32u8imm:$src3),
!if(Is2Addr,
!strconcat(OpcodeStr,
"\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
@@ -4729,7 +5864,7 @@ multiclass SS41I_binop_rmi_int<bits<8> opc, string OpcodeStr,
[(set RC:$dst, (IntId RC:$src1, RC:$src2, imm:$src3))]>,
OpSize;
def rmi : SS4AIi8<opc, MRMSrcMem, (outs RC:$dst),
- (ins RC:$src1, x86memop:$src2, i32i8imm:$src3),
+ (ins RC:$src1, x86memop:$src2, u32u8imm:$src3),
!if(Is2Addr,
!strconcat(OpcodeStr,
"\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
@@ -4815,6 +5950,36 @@ defm VBLENDVPDY : SS41I_quaternary_int_avx<0x4B, "vblendvpd", VR256, i256mem,
defm VBLENDVPSY : SS41I_quaternary_int_avx<0x4A, "vblendvps", VR256, i256mem,
memopv32i8, int_x86_avx_blendv_ps_256>;
+let Predicates = [HasAVX] in {
+ def : Pat<(v16i8 (vselect (v16i8 VR128:$mask), (v16i8 VR128:$src1),
+ (v16i8 VR128:$src2))),
+ (VPBLENDVBrr VR128:$src2, VR128:$src1, VR128:$mask)>;
+ def : Pat<(v4i32 (vselect (v4i32 VR128:$mask), (v4i32 VR128:$src1),
+ (v4i32 VR128:$src2))),
+ (VBLENDVPSrr VR128:$src2, VR128:$src1, VR128:$mask)>;
+ def : Pat<(v4f32 (vselect (v4i32 VR128:$mask), (v4f32 VR128:$src1),
+ (v4f32 VR128:$src2))),
+ (VBLENDVPSrr VR128:$src2, VR128:$src1, VR128:$mask)>;
+ def : Pat<(v2i64 (vselect (v2i64 VR128:$mask), (v2i64 VR128:$src1),
+ (v2i64 VR128:$src2))),
+ (VBLENDVPDrr VR128:$src2, VR128:$src1, VR128:$mask)>;
+ def : Pat<(v2f64 (vselect (v2i64 VR128:$mask), (v2f64 VR128:$src1),
+ (v2f64 VR128:$src2))),
+ (VBLENDVPDrr VR128:$src2, VR128:$src1, VR128:$mask)>;
+ def : Pat<(v8i32 (vselect (v8i32 VR256:$mask), (v8i32 VR256:$src1),
+ (v8i32 VR256:$src2))),
+ (VBLENDVPSYrr VR256:$src2, VR256:$src1, VR256:$mask)>;
+ def : Pat<(v8f32 (vselect (v8i32 VR256:$mask), (v8f32 VR256:$src1),
+ (v8f32 VR256:$src2))),
+ (VBLENDVPSYrr VR256:$src2, VR256:$src1, VR256:$mask)>;
+ def : Pat<(v4i64 (vselect (v4i64 VR256:$mask), (v4i64 VR256:$src1),
+ (v4i64 VR256:$src2))),
+ (VBLENDVPDYrr VR256:$src2, VR256:$src1, VR256:$mask)>;
+ def : Pat<(v4f64 (vselect (v4i64 VR256:$mask), (v4f64 VR256:$src1),
+ (v4f64 VR256:$src2))),
+ (VBLENDVPDYrr VR256:$src2, VR256:$src1, VR256:$mask)>;
+}
+
/// SS41I_ternary_int - SSE 4.1 ternary operator
let Uses = [XMM0], Constraints = "$src1 = $dst" in {
multiclass SS41I_ternary_int<bits<8> opc, string OpcodeStr, Intrinsic IntId> {
@@ -4835,12 +6000,27 @@ let Uses = [XMM0], Constraints = "$src1 = $dst" in {
}
}
-defm BLENDVPD : SS41I_ternary_int<0x15, "blendvpd", int_x86_sse41_blendvpd>;
-defm BLENDVPS : SS41I_ternary_int<0x14, "blendvps", int_x86_sse41_blendvps>;
-defm PBLENDVB : SS41I_ternary_int<0x10, "pblendvb", int_x86_sse41_pblendvb>;
-
-def : Pat<(X86pblendv VR128:$src1, VR128:$src2, XMM0),
- (PBLENDVBrr0 VR128:$src1, VR128:$src2)>;
+defm BLENDVPD : SS41I_ternary_int<0x15, "blendvpd", int_x86_sse41_blendvpd>;
+defm BLENDVPS : SS41I_ternary_int<0x14, "blendvps", int_x86_sse41_blendvps>;
+defm PBLENDVB : SS41I_ternary_int<0x10, "pblendvb", int_x86_sse41_pblendvb>;
+
+let Predicates = [HasSSE41] in {
+ def : Pat<(v16i8 (vselect (v16i8 XMM0), (v16i8 VR128:$src1),
+ (v16i8 VR128:$src2))),
+ (PBLENDVBrr0 VR128:$src2, VR128:$src1)>;
+ def : Pat<(v4i32 (vselect (v4i32 XMM0), (v4i32 VR128:$src1),
+ (v4i32 VR128:$src2))),
+ (BLENDVPSrr0 VR128:$src2, VR128:$src1)>;
+ def : Pat<(v4f32 (vselect (v4i32 XMM0), (v4f32 VR128:$src1),
+ (v4f32 VR128:$src2))),
+ (BLENDVPSrr0 VR128:$src2, VR128:$src1)>;
+ def : Pat<(v2i64 (vselect (v2i64 XMM0), (v2i64 VR128:$src1),
+ (v2i64 VR128:$src2))),
+ (BLENDVPDrr0 VR128:$src2, VR128:$src1)>;
+ def : Pat<(v2f64 (vselect (v2i64 XMM0), (v2f64 VR128:$src1),
+ (v2f64 VR128:$src2))),
+ (BLENDVPDrr0 VR128:$src2, VR128:$src1)>;
+}
let Predicates = [HasAVX] in
def VMOVNTDQArm : SS48I<0x2A, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src),
@@ -4876,9 +6056,16 @@ multiclass SS42I_binop_rm_int<bits<8> opc, string OpcodeStr,
(bitconvert (memopv16i8 addr:$src2))))]>, OpSize;
}
-let Predicates = [HasAVX] in
+let Predicates = [HasAVX] in {
defm VPCMPGTQ : SS42I_binop_rm_int<0x37, "vpcmpgtq", int_x86_sse42_pcmpgtq,
0>, VEX_4V;
+
+ def : Pat<(v2i64 (X86pcmpgtq VR128:$src1, VR128:$src2)),
+ (VPCMPGTQrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (X86pcmpgtq VR128:$src1, (memop addr:$src2))),
+ (VPCMPGTQrm VR128:$src1, addr:$src2)>;
+}
+
let Constraints = "$src1 = $dst" in
defm PCMPGTQ : SS42I_binop_rm_int<0x37, "pcmpgtq", int_x86_sse42_pcmpgtq>;
@@ -5158,22 +6345,43 @@ let Constraints = "$src1 = $dst" in {
int_x86_aesni_aesdeclast>;
}
-def : Pat<(v2i64 (int_x86_aesni_aesenc VR128:$src1, VR128:$src2)),
- (AESENCrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v2i64 (int_x86_aesni_aesenc VR128:$src1, (memop addr:$src2))),
- (AESENCrm VR128:$src1, addr:$src2)>;
-def : Pat<(v2i64 (int_x86_aesni_aesenclast VR128:$src1, VR128:$src2)),
- (AESENCLASTrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v2i64 (int_x86_aesni_aesenclast VR128:$src1, (memop addr:$src2))),
- (AESENCLASTrm VR128:$src1, addr:$src2)>;
-def : Pat<(v2i64 (int_x86_aesni_aesdec VR128:$src1, VR128:$src2)),
- (AESDECrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v2i64 (int_x86_aesni_aesdec VR128:$src1, (memop addr:$src2))),
- (AESDECrm VR128:$src1, addr:$src2)>;
-def : Pat<(v2i64 (int_x86_aesni_aesdeclast VR128:$src1, VR128:$src2)),
- (AESDECLASTrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v2i64 (int_x86_aesni_aesdeclast VR128:$src1, (memop addr:$src2))),
- (AESDECLASTrm VR128:$src1, addr:$src2)>;
+let Predicates = [HasAES] in {
+ def : Pat<(v2i64 (int_x86_aesni_aesenc VR128:$src1, VR128:$src2)),
+ (AESENCrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesenc VR128:$src1, (memop addr:$src2))),
+ (AESENCrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesenclast VR128:$src1, VR128:$src2)),
+ (AESENCLASTrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesenclast VR128:$src1, (memop addr:$src2))),
+ (AESENCLASTrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesdec VR128:$src1, VR128:$src2)),
+ (AESDECrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesdec VR128:$src1, (memop addr:$src2))),
+ (AESDECrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesdeclast VR128:$src1, VR128:$src2)),
+ (AESDECLASTrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesdeclast VR128:$src1, (memop addr:$src2))),
+ (AESDECLASTrm VR128:$src1, addr:$src2)>;
+}
+
+let Predicates = [HasAVX, HasAES], AddedComplexity = 20 in {
+ def : Pat<(v2i64 (int_x86_aesni_aesenc VR128:$src1, VR128:$src2)),
+ (VAESENCrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesenc VR128:$src1, (memop addr:$src2))),
+ (VAESENCrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesenclast VR128:$src1, VR128:$src2)),
+ (VAESENCLASTrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesenclast VR128:$src1, (memop addr:$src2))),
+ (VAESENCLASTrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesdec VR128:$src1, VR128:$src2)),
+ (VAESDECrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesdec VR128:$src1, (memop addr:$src2))),
+ (VAESDECrm VR128:$src1, addr:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesdeclast VR128:$src1, VR128:$src2)),
+ (VAESDECLASTrr VR128:$src1, VR128:$src2)>;
+ def : Pat<(v2i64 (int_x86_aesni_aesdeclast VR128:$src1, (memop addr:$src2))),
+ (VAESDECLASTrm VR128:$src1, addr:$src2)>;
+}
// Perform the AES InvMixColumn Transformation
let Predicates = [HasAVX, HasAES] in {
@@ -5288,8 +6496,10 @@ defm : pclmul_alias<"lqlq", 0x00>;
// AVX Instructions
//===----------------------------------------------------------------------===//
-
-// Load from memory and broadcast to all elements of the destination operand
+//===----------------------------------------------------------------------===//
+// VBROADCAST - Load from memory and broadcast to all elements of the
+// destination operand
+//
class avx_broadcast<bits<8> opc, string OpcodeStr, RegisterClass RC,
X86MemOperand x86memop, Intrinsic Int> :
AVX8I<opc, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src),
@@ -5305,7 +6515,26 @@ def VBROADCASTSD : avx_broadcast<0x19, "vbroadcastsd", VR256, f64mem,
def VBROADCASTF128 : avx_broadcast<0x1A, "vbroadcastf128", VR256, f128mem,
int_x86_avx_vbroadcastf128_pd_256>;
-// Insert packed floating-point values
+def : Pat<(int_x86_avx_vbroadcastf128_ps_256 addr:$src),
+ (VBROADCASTF128 addr:$src)>;
+
+def : Pat<(v8i32 (X86VBroadcast (loadi32 addr:$src))),
+ (VBROADCASTSSY addr:$src)>;
+def : Pat<(v4i64 (X86VBroadcast (loadi64 addr:$src))),
+ (VBROADCASTSD addr:$src)>;
+def : Pat<(v8f32 (X86VBroadcast (loadf32 addr:$src))),
+ (VBROADCASTSSY addr:$src)>;
+def : Pat<(v4f64 (X86VBroadcast (loadf64 addr:$src))),
+ (VBROADCASTSD addr:$src)>;
+
+def : Pat<(v4f32 (X86VBroadcast (loadf32 addr:$src))),
+ (VBROADCASTSS addr:$src)>;
+def : Pat<(v4i32 (X86VBroadcast (loadi32 addr:$src))),
+ (VBROADCASTSS addr:$src)>;
+
+//===----------------------------------------------------------------------===//
+// VINSERTF128 - Insert packed floating-point values
+//
def VINSERTF128rr : AVXAIi8<0x18, MRMSrcReg, (outs VR256:$dst),
(ins VR256:$src1, VR128:$src2, i8imm:$src3),
"vinsertf128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}",
@@ -5315,7 +6544,41 @@ def VINSERTF128rm : AVXAIi8<0x18, MRMSrcMem, (outs VR256:$dst),
"vinsertf128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}",
[]>, VEX_4V;
-// Extract packed floating-point values
+def : Pat<(int_x86_avx_vinsertf128_pd_256 VR256:$src1, VR128:$src2, imm:$src3),
+ (VINSERTF128rr VR256:$src1, VR128:$src2, imm:$src3)>;
+def : Pat<(int_x86_avx_vinsertf128_ps_256 VR256:$src1, VR128:$src2, imm:$src3),
+ (VINSERTF128rr VR256:$src1, VR128:$src2, imm:$src3)>;
+def : Pat<(int_x86_avx_vinsertf128_si_256 VR256:$src1, VR128:$src2, imm:$src3),
+ (VINSERTF128rr VR256:$src1, VR128:$src2, imm:$src3)>;
+
+def : Pat<(vinsertf128_insert:$ins (v8f32 VR256:$src1), (v4f32 VR128:$src2),
+ (i32 imm)),
+ (VINSERTF128rr VR256:$src1, VR128:$src2,
+ (INSERT_get_vinsertf128_imm VR256:$ins))>;
+def : Pat<(vinsertf128_insert:$ins (v4f64 VR256:$src1), (v2f64 VR128:$src2),
+ (i32 imm)),
+ (VINSERTF128rr VR256:$src1, VR128:$src2,
+ (INSERT_get_vinsertf128_imm VR256:$ins))>;
+def : Pat<(vinsertf128_insert:$ins (v8i32 VR256:$src1), (v4i32 VR128:$src2),
+ (i32 imm)),
+ (VINSERTF128rr VR256:$src1, VR128:$src2,
+ (INSERT_get_vinsertf128_imm VR256:$ins))>;
+def : Pat<(vinsertf128_insert:$ins (v4i64 VR256:$src1), (v2i64 VR128:$src2),
+ (i32 imm)),
+ (VINSERTF128rr VR256:$src1, VR128:$src2,
+ (INSERT_get_vinsertf128_imm VR256:$ins))>;
+def : Pat<(vinsertf128_insert:$ins (v32i8 VR256:$src1), (v16i8 VR128:$src2),
+ (i32 imm)),
+ (VINSERTF128rr VR256:$src1, VR128:$src2,
+ (INSERT_get_vinsertf128_imm VR256:$ins))>;
+def : Pat<(vinsertf128_insert:$ins (v16i16 VR256:$src1), (v8i16 VR128:$src2),
+ (i32 imm)),
+ (VINSERTF128rr VR256:$src1, VR128:$src2,
+ (INSERT_get_vinsertf128_imm VR256:$ins))>;
+
+//===----------------------------------------------------------------------===//
+// VEXTRACTF128 - Extract packed floating-point values
+//
def VEXTRACTF128rr : AVXAIi8<0x19, MRMDestReg, (outs VR128:$dst),
(ins VR256:$src1, i8imm:$src2),
"vextractf128\t{$src2, $src1, $dst|$dst, $src1, $src2}",
@@ -5325,7 +6588,41 @@ def VEXTRACTF128mr : AVXAIi8<0x19, MRMDestMem, (outs),
"vextractf128\t{$src2, $src1, $dst|$dst, $src1, $src2}",
[]>, VEX;
-// Conditional SIMD Packed Loads and Stores
+def : Pat<(int_x86_avx_vextractf128_pd_256 VR256:$src1, imm:$src2),
+ (VEXTRACTF128rr VR256:$src1, imm:$src2)>;
+def : Pat<(int_x86_avx_vextractf128_ps_256 VR256:$src1, imm:$src2),
+ (VEXTRACTF128rr VR256:$src1, imm:$src2)>;
+def : Pat<(int_x86_avx_vextractf128_si_256 VR256:$src1, imm:$src2),
+ (VEXTRACTF128rr VR256:$src1, imm:$src2)>;
+
+def : Pat<(vextractf128_extract:$ext VR256:$src1, (i32 imm)),
+ (v4f32 (VEXTRACTF128rr
+ (v8f32 VR256:$src1),
+ (EXTRACT_get_vextractf128_imm VR128:$ext)))>;
+def : Pat<(vextractf128_extract:$ext VR256:$src1, (i32 imm)),
+ (v2f64 (VEXTRACTF128rr
+ (v4f64 VR256:$src1),
+ (EXTRACT_get_vextractf128_imm VR128:$ext)))>;
+def : Pat<(vextractf128_extract:$ext VR256:$src1, (i32 imm)),
+ (v4i32 (VEXTRACTF128rr
+ (v8i32 VR256:$src1),
+ (EXTRACT_get_vextractf128_imm VR128:$ext)))>;
+def : Pat<(vextractf128_extract:$ext VR256:$src1, (i32 imm)),
+ (v2i64 (VEXTRACTF128rr
+ (v4i64 VR256:$src1),
+ (EXTRACT_get_vextractf128_imm VR128:$ext)))>;
+def : Pat<(vextractf128_extract:$ext VR256:$src1, (i32 imm)),
+ (v8i16 (VEXTRACTF128rr
+ (v16i16 VR256:$src1),
+ (EXTRACT_get_vextractf128_imm VR128:$ext)))>;
+def : Pat<(vextractf128_extract:$ext VR256:$src1, (i32 imm)),
+ (v16i8 (VEXTRACTF128rr
+ (v32i8 VR256:$src1),
+ (EXTRACT_get_vextractf128_imm VR128:$ext)))>;
+
+//===----------------------------------------------------------------------===//
+// VMASKMOV - Conditional SIMD Packed Loads and Stores
+//
multiclass avx_movmask_rm<bits<8> opc_rm, bits<8> opc_mr, string OpcodeStr,
Intrinsic IntLd, Intrinsic IntLd256,
Intrinsic IntSt, Intrinsic IntSt256,
@@ -5363,7 +6660,9 @@ defm VMASKMOVPD : avx_movmask_rm<0x2D, 0x2F, "vmaskmovpd",
int_x86_avx_maskstore_pd_256,
memopv2f64, memopv4f64>;
-// Permute Floating-Point Values
+//===----------------------------------------------------------------------===//
+// VPERMIL - Permute Single and Double Floating-Point Values
+//
multiclass avx_permil<bits<8> opc_rm, bits<8> opc_rmi, string OpcodeStr,
RegisterClass RC, X86MemOperand x86memop_f,
X86MemOperand x86memop_i, PatFrag f_frag, PatFrag i_frag,
@@ -5404,6 +6703,18 @@ defm VPERMILPDY : avx_permil<0x0D, 0x05, "vpermilpd", VR256, f256mem, i256mem,
int_x86_avx_vpermilvar_pd_256,
int_x86_avx_vpermil_pd_256>;
+def : Pat<(v8f32 (X86VPermilpsy VR256:$src1, (i8 imm:$imm))),
+ (VPERMILPSYri VR256:$src1, imm:$imm)>;
+def : Pat<(v4f64 (X86VPermilpdy VR256:$src1, (i8 imm:$imm))),
+ (VPERMILPDYri VR256:$src1, imm:$imm)>;
+def : Pat<(v8i32 (X86VPermilpsy VR256:$src1, (i8 imm:$imm))),
+ (VPERMILPSYri VR256:$src1, imm:$imm)>;
+def : Pat<(v4i64 (X86VPermilpdy VR256:$src1, (i8 imm:$imm))),
+ (VPERMILPDYri VR256:$src1, imm:$imm)>;
+
+//===----------------------------------------------------------------------===//
+// VPERM2F128 - Permute Floating-Point Values in 128-bit chunks
+//
def VPERM2F128rr : AVXAIi8<0x06, MRMSrcReg, (outs VR256:$dst),
(ins VR256:$src1, VR256:$src2, i8imm:$src3),
"vperm2f128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}",
@@ -5413,65 +6724,6 @@ def VPERM2F128rm : AVXAIi8<0x06, MRMSrcMem, (outs VR256:$dst),
"vperm2f128\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}",
[]>, VEX_4V;
-// Zero All YMM registers
-def VZEROALL : I<0x77, RawFrm, (outs), (ins), "vzeroall",
- [(int_x86_avx_vzeroall)]>, VEX, VEX_L, Requires<[HasAVX]>;
-
-// Zero Upper bits of YMM registers
-def VZEROUPPER : I<0x77, RawFrm, (outs), (ins), "vzeroupper",
- [(int_x86_avx_vzeroupper)]>, VEX, Requires<[HasAVX]>;
-
-def : Pat<(int_x86_avx_vinsertf128_pd_256 VR256:$src1, VR128:$src2, imm:$src3),
- (VINSERTF128rr VR256:$src1, VR128:$src2, imm:$src3)>;
-def : Pat<(int_x86_avx_vinsertf128_ps_256 VR256:$src1, VR128:$src2, imm:$src3),
- (VINSERTF128rr VR256:$src1, VR128:$src2, imm:$src3)>;
-def : Pat<(int_x86_avx_vinsertf128_si_256 VR256:$src1, VR128:$src2, imm:$src3),
- (VINSERTF128rr VR256:$src1, VR128:$src2, imm:$src3)>;
-
-def : Pat<(vinsertf128_insert:$ins (v8f32 VR256:$src1), (v4f32 VR128:$src2),
- (i32 imm)),
- (VINSERTF128rr VR256:$src1, VR128:$src2,
- (INSERT_get_vinsertf128_imm VR256:$ins))>;
-def : Pat<(vinsertf128_insert:$ins (v4f64 VR256:$src1), (v2f64 VR128:$src2),
- (i32 imm)),
- (VINSERTF128rr VR256:$src1, VR128:$src2,
- (INSERT_get_vinsertf128_imm VR256:$ins))>;
-def : Pat<(vinsertf128_insert:$ins (v8i32 VR256:$src1), (v4i32 VR128:$src2),
- (i32 imm)),
- (VINSERTF128rr VR256:$src1, VR128:$src2,
- (INSERT_get_vinsertf128_imm VR256:$ins))>;
-def : Pat<(vinsertf128_insert:$ins (v4i64 VR256:$src1), (v2i64 VR128:$src2),
- (i32 imm)),
- (VINSERTF128rr VR256:$src1, VR128:$src2,
- (INSERT_get_vinsertf128_imm VR256:$ins))>;
-
-def : Pat<(int_x86_avx_vextractf128_pd_256 VR256:$src1, imm:$src2),
- (VEXTRACTF128rr VR256:$src1, imm:$src2)>;
-def : Pat<(int_x86_avx_vextractf128_ps_256 VR256:$src1, imm:$src2),
- (VEXTRACTF128rr VR256:$src1, imm:$src2)>;
-def : Pat<(int_x86_avx_vextractf128_si_256 VR256:$src1, imm:$src2),
- (VEXTRACTF128rr VR256:$src1, imm:$src2)>;
-
-def : Pat<(vextractf128_extract:$ext VR256:$src1, (i32 imm)),
- (v4f32 (VEXTRACTF128rr
- (v8f32 VR256:$src1),
- (EXTRACT_get_vextractf128_imm VR128:$ext)))>;
-def : Pat<(vextractf128_extract:$ext VR256:$src1, (i32 imm)),
- (v2f64 (VEXTRACTF128rr
- (v4f64 VR256:$src1),
- (EXTRACT_get_vextractf128_imm VR128:$ext)))>;
-def : Pat<(vextractf128_extract:$ext VR256:$src1, (i32 imm)),
- (v4i32 (VEXTRACTF128rr
- (v8i32 VR256:$src1),
- (EXTRACT_get_vextractf128_imm VR128:$ext)))>;
-def : Pat<(vextractf128_extract:$ext VR256:$src1, (i32 imm)),
- (v2i64 (VEXTRACTF128rr
- (v4i64 VR256:$src1),
- (EXTRACT_get_vextractf128_imm VR128:$ext)))>;
-
-def : Pat<(int_x86_avx_vbroadcastf128_ps_256 addr:$src),
- (VBROADCASTF128 addr:$src)>;
-
def : Pat<(int_x86_avx_vperm2f128_ps_256 VR256:$src1, VR256:$src2, imm:$src3),
(VPERM2F128rr VR256:$src1, VR256:$src2, imm:$src3)>;
def : Pat<(int_x86_avx_vperm2f128_pd_256 VR256:$src1, VR256:$src2, imm:$src3),
@@ -5489,377 +6741,59 @@ def : Pat<(int_x86_avx_vperm2f128_si_256
VR256:$src1, (memopv8i32 addr:$src2), imm:$src3),
(VPERM2F128rm VR256:$src1, addr:$src2, imm:$src3)>;
+def : Pat<(v8f32 (X86VPerm2f128 VR256:$src1, VR256:$src2, (i8 imm:$imm))),
+ (VPERM2F128rr VR256:$src1, VR256:$src2, imm:$imm)>;
+def : Pat<(v8i32 (X86VPerm2f128 VR256:$src1, VR256:$src2, (i8 imm:$imm))),
+ (VPERM2F128rr VR256:$src1, VR256:$src2, imm:$imm)>;
+def : Pat<(v4i64 (X86VPerm2f128 VR256:$src1, VR256:$src2, (i8 imm:$imm))),
+ (VPERM2F128rr VR256:$src1, VR256:$src2, imm:$imm)>;
+def : Pat<(v4f64 (X86VPerm2f128 VR256:$src1, VR256:$src2, (i8 imm:$imm))),
+ (VPERM2F128rr VR256:$src1, VR256:$src2, imm:$imm)>;
+def : Pat<(v32i8 (X86VPerm2f128 VR256:$src1, VR256:$src2, (i8 imm:$imm))),
+ (VPERM2F128rr VR256:$src1, VR256:$src2, imm:$imm)>;
+def : Pat<(v16i16 (X86VPerm2f128 VR256:$src1, VR256:$src2, (i8 imm:$imm))),
+ (VPERM2F128rr VR256:$src1, VR256:$src2, imm:$imm)>;
+
//===----------------------------------------------------------------------===//
-// SSE Shuffle pattern fragments
-//===----------------------------------------------------------------------===//
+// VZERO - Zero YMM registers
+//
+let Defs = [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7,
+ YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15] in {
+ // Zero All YMM registers
+ def VZEROALL : I<0x77, RawFrm, (outs), (ins), "vzeroall",
+ [(int_x86_avx_vzeroall)]>, TB, VEX, VEX_L, Requires<[HasAVX]>;
-// This is part of a "work in progress" refactoring. The idea is that all
-// vector shuffles are going to be translated into target specific nodes and
-// directly matched by the patterns below (which can be changed along the way)
-// The AVX version of some but not all of them are described here, and more
-// should come in a near future.
-
-// Shuffle with PSHUFD instruction folding loads. The first two patterns match
-// SSE2 loads, which are always promoted to v2i64. The last one should match
-// the SSE1 case, where the only legal load is v4f32, but there is no PSHUFD
-// in SSE2, how does it ever worked? Anyway, the pattern will remain here until
-// we investigate further.
-def : Pat<(v4i32 (X86PShufd (bc_v4i32 (memopv2i64 addr:$src1)),
- (i8 imm:$imm))),
- (VPSHUFDmi addr:$src1, imm:$imm)>, Requires<[HasAVX]>;
-def : Pat<(v4i32 (X86PShufd (bc_v4i32 (memopv2i64 addr:$src1)),
- (i8 imm:$imm))),
- (PSHUFDmi addr:$src1, imm:$imm)>;
-def : Pat<(v4i32 (X86PShufd (bc_v4i32 (memopv4f32 addr:$src1)),
- (i8 imm:$imm))),
- (PSHUFDmi addr:$src1, imm:$imm)>; // FIXME: has this ever worked?
-
-// Shuffle with PSHUFD instruction.
-def : Pat<(v4f32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
- (VPSHUFDri VR128:$src1, imm:$imm)>, Requires<[HasAVX]>;
-def : Pat<(v4f32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
- (PSHUFDri VR128:$src1, imm:$imm)>;
-
-def : Pat<(v4i32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
- (VPSHUFDri VR128:$src1, imm:$imm)>, Requires<[HasAVX]>;
-def : Pat<(v4i32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
- (PSHUFDri VR128:$src1, imm:$imm)>;
-
-// Shuffle with SHUFPD instruction.
-def : Pat<(v2f64 (X86Shufps VR128:$src1,
- (memopv2f64 addr:$src2), (i8 imm:$imm))),
- (VSHUFPDrmi VR128:$src1, addr:$src2, imm:$imm)>, Requires<[HasAVX]>;
-def : Pat<(v2f64 (X86Shufps VR128:$src1,
- (memopv2f64 addr:$src2), (i8 imm:$imm))),
- (SHUFPDrmi VR128:$src1, addr:$src2, imm:$imm)>;
-
-def : Pat<(v2i64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (VSHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>, Requires<[HasAVX]>;
-def : Pat<(v2i64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (SHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>;
-
-def : Pat<(v2f64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (VSHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>, Requires<[HasAVX]>;
-def : Pat<(v2f64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (SHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>;
-
-// Shuffle with SHUFPS instruction.
-def : Pat<(v4f32 (X86Shufps VR128:$src1,
- (memopv4f32 addr:$src2), (i8 imm:$imm))),
- (VSHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>, Requires<[HasAVX]>;
-def : Pat<(v4f32 (X86Shufps VR128:$src1,
- (memopv4f32 addr:$src2), (i8 imm:$imm))),
- (SHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>;
-
-def : Pat<(v4f32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (VSHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>, Requires<[HasAVX]>;
-def : Pat<(v4f32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (SHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>;
-
-def : Pat<(v4i32 (X86Shufps VR128:$src1,
- (bc_v4i32 (memopv2i64 addr:$src2)), (i8 imm:$imm))),
- (VSHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>, Requires<[HasAVX]>;
-def : Pat<(v4i32 (X86Shufps VR128:$src1,
- (bc_v4i32 (memopv2i64 addr:$src2)), (i8 imm:$imm))),
- (SHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>;
-
-def : Pat<(v4i32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (VSHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>, Requires<[HasAVX]>;
-def : Pat<(v4i32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (SHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>;
-
-// Shuffle with MOVHLPS instruction
-def : Pat<(v4f32 (X86Movhlps VR128:$src1, VR128:$src2)),
- (MOVHLPSrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v4i32 (X86Movhlps VR128:$src1, VR128:$src2)),
- (MOVHLPSrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with MOVDDUP instruction
-def : Pat<(X86Movddup (memopv2f64 addr:$src)),
- (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
-def : Pat<(X86Movddup (memopv2f64 addr:$src)),
- (MOVDDUPrm addr:$src)>;
-
-def : Pat<(X86Movddup (bc_v2f64 (memopv4f32 addr:$src))),
- (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
-def : Pat<(X86Movddup (bc_v2f64 (memopv4f32 addr:$src))),
- (MOVDDUPrm addr:$src)>;
-
-def : Pat<(X86Movddup (bc_v2f64 (memopv2i64 addr:$src))),
- (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
-def : Pat<(X86Movddup (bc_v2f64 (memopv2i64 addr:$src))),
- (MOVDDUPrm addr:$src)>;
-
-def : Pat<(X86Movddup (v2f64 (scalar_to_vector (loadf64 addr:$src)))),
- (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
-def : Pat<(X86Movddup (v2f64 (scalar_to_vector (loadf64 addr:$src)))),
- (MOVDDUPrm addr:$src)>;
-
-def : Pat<(X86Movddup (bc_v2f64
- (v2i64 (scalar_to_vector (loadi64 addr:$src))))),
- (VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
-def : Pat<(X86Movddup (bc_v2f64
- (v2i64 (scalar_to_vector (loadi64 addr:$src))))),
- (MOVDDUPrm addr:$src)>;
-
-
-// Shuffle with UNPCKLPS
-def : Pat<(v4f32 (X86Unpcklps VR128:$src1, (memopv4f32 addr:$src2))),
- (VUNPCKLPSrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v8f32 (X86Unpcklpsy VR256:$src1, (memopv8f32 addr:$src2))),
- (VUNPCKLPSYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v4f32 (X86Unpcklps VR128:$src1, (memopv4f32 addr:$src2))),
- (UNPCKLPSrm VR128:$src1, addr:$src2)>;
-
-def : Pat<(v4f32 (X86Unpcklps VR128:$src1, VR128:$src2)),
- (VUNPCKLPSrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v8f32 (X86Unpcklpsy VR256:$src1, VR256:$src2)),
- (VUNPCKLPSYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v4f32 (X86Unpcklps VR128:$src1, VR128:$src2)),
- (UNPCKLPSrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with UNPCKHPS
-def : Pat<(v4f32 (X86Unpckhps VR128:$src1, (memopv4f32 addr:$src2))),
- (VUNPCKHPSrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v4f32 (X86Unpckhps VR128:$src1, (memopv4f32 addr:$src2))),
- (UNPCKHPSrm VR128:$src1, addr:$src2)>;
-
-def : Pat<(v4f32 (X86Unpckhps VR128:$src1, VR128:$src2)),
- (VUNPCKHPSrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v4f32 (X86Unpckhps VR128:$src1, VR128:$src2)),
- (UNPCKHPSrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with UNPCKLPD
-def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, (memopv2f64 addr:$src2))),
- (VUNPCKLPDrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v4f64 (X86Unpcklpdy VR256:$src1, (memopv4f64 addr:$src2))),
- (VUNPCKLPDYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, (memopv2f64 addr:$src2))),
- (UNPCKLPDrm VR128:$src1, addr:$src2)>;
-
-def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, VR128:$src2)),
- (VUNPCKLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v4f64 (X86Unpcklpdy VR256:$src1, VR256:$src2)),
- (VUNPCKLPDYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, VR128:$src2)),
- (UNPCKLPDrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with UNPCKHPD
-def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, (memopv2f64 addr:$src2))),
- (VUNPCKHPDrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, (memopv2f64 addr:$src2))),
- (UNPCKHPDrm VR128:$src1, addr:$src2)>;
-
-def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, VR128:$src2)),
- (VUNPCKHPDrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>;
-def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, VR128:$src2)),
- (UNPCKHPDrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKLBW
-def : Pat<(v16i8 (X86Punpcklbw VR128:$src1,
- (bc_v16i8 (memopv2i64 addr:$src2)))),
- (PUNPCKLBWrm VR128:$src1, addr:$src2)>;
-def : Pat<(v16i8 (X86Punpcklbw VR128:$src1, VR128:$src2)),
- (PUNPCKLBWrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKLWD
-def : Pat<(v8i16 (X86Punpcklwd VR128:$src1,
- (bc_v8i16 (memopv2i64 addr:$src2)))),
- (PUNPCKLWDrm VR128:$src1, addr:$src2)>;
-def : Pat<(v8i16 (X86Punpcklwd VR128:$src1, VR128:$src2)),
- (PUNPCKLWDrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKLDQ
-def : Pat<(v4i32 (X86Punpckldq VR128:$src1,
- (bc_v4i32 (memopv2i64 addr:$src2)))),
- (PUNPCKLDQrm VR128:$src1, addr:$src2)>;
-def : Pat<(v4i32 (X86Punpckldq VR128:$src1, VR128:$src2)),
- (PUNPCKLDQrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKLQDQ
-def : Pat<(v2i64 (X86Punpcklqdq VR128:$src1, (memopv2i64 addr:$src2))),
- (PUNPCKLQDQrm VR128:$src1, addr:$src2)>;
-def : Pat<(v2i64 (X86Punpcklqdq VR128:$src1, VR128:$src2)),
- (PUNPCKLQDQrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKHBW
-def : Pat<(v16i8 (X86Punpckhbw VR128:$src1,
- (bc_v16i8 (memopv2i64 addr:$src2)))),
- (PUNPCKHBWrm VR128:$src1, addr:$src2)>;
-def : Pat<(v16i8 (X86Punpckhbw VR128:$src1, VR128:$src2)),
- (PUNPCKHBWrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKHWD
-def : Pat<(v8i16 (X86Punpckhwd VR128:$src1,
- (bc_v8i16 (memopv2i64 addr:$src2)))),
- (PUNPCKHWDrm VR128:$src1, addr:$src2)>;
-def : Pat<(v8i16 (X86Punpckhwd VR128:$src1, VR128:$src2)),
- (PUNPCKHWDrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKHDQ
-def : Pat<(v4i32 (X86Punpckhdq VR128:$src1,
- (bc_v4i32 (memopv2i64 addr:$src2)))),
- (PUNPCKHDQrm VR128:$src1, addr:$src2)>;
-def : Pat<(v4i32 (X86Punpckhdq VR128:$src1, VR128:$src2)),
- (PUNPCKHDQrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with PUNPCKHQDQ
-def : Pat<(v2i64 (X86Punpckhqdq VR128:$src1, (memopv2i64 addr:$src2))),
- (PUNPCKHQDQrm VR128:$src1, addr:$src2)>;
-def : Pat<(v2i64 (X86Punpckhqdq VR128:$src1, VR128:$src2)),
- (PUNPCKHQDQrr VR128:$src1, VR128:$src2)>;
-
-// Shuffle with MOVLHPS
-def : Pat<(X86Movlhps VR128:$src1,
- (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))),
- (MOVHPSrm VR128:$src1, addr:$src2)>;
-def : Pat<(X86Movlhps VR128:$src1,
- (bc_v4i32 (v2i64 (X86vzload addr:$src2)))),
- (MOVHPSrm VR128:$src1, addr:$src2)>;
-def : Pat<(v4f32 (X86Movlhps VR128:$src1, VR128:$src2)),
- (MOVLHPSrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v4i32 (X86Movlhps VR128:$src1, VR128:$src2)),
- (MOVLHPSrr VR128:$src1, VR128:$src2)>;
-def : Pat<(v2i64 (X86Movlhps VR128:$src1, VR128:$src2)),
- (MOVLHPSrr (v2i64 VR128:$src1), VR128:$src2)>;
-
-// FIXME: Instead of X86Movddup, there should be a X86Unpcklpd here, the problem
-// is during lowering, where it's not possible to recognize the load fold cause
-// it has two uses through a bitcast. One use disappears at isel time and the
-// fold opportunity reappears.
-def : Pat<(v2f64 (X86Movddup VR128:$src)),
- (UNPCKLPDrr VR128:$src, VR128:$src)>;
-
-// Shuffle with MOVLHPD
-def : Pat<(v2f64 (X86Movlhpd VR128:$src1,
- (scalar_to_vector (loadf64 addr:$src2)))),
- (MOVHPDrm VR128:$src1, addr:$src2)>;
-
-// FIXME: Instead of X86Unpcklpd, there should be a X86Movlhpd here, the problem
-// is during lowering, where it's not possible to recognize the load fold cause
-// it has two uses through a bitcast. One use disappears at isel time and the
-// fold opportunity reappears.
-def : Pat<(v2f64 (X86Unpcklpd VR128:$src1,
- (scalar_to_vector (loadf64 addr:$src2)))),
- (MOVHPDrm VR128:$src1, addr:$src2)>;
-
-// Shuffle with MOVSS
-def : Pat<(v4f32 (X86Movss VR128:$src1, (scalar_to_vector FR32:$src2))),
- (MOVSSrr VR128:$src1, FR32:$src2)>;
-def : Pat<(v4i32 (X86Movss VR128:$src1, VR128:$src2)),
- (MOVSSrr (v4i32 VR128:$src1),
- (EXTRACT_SUBREG (v4i32 VR128:$src2), sub_ss))>;
-def : Pat<(v4f32 (X86Movss VR128:$src1, VR128:$src2)),
- (MOVSSrr (v4f32 VR128:$src1),
- (EXTRACT_SUBREG (v4f32 VR128:$src2), sub_ss))>;
-// FIXME: Instead of a X86Movss there should be a X86Movlps here, the problem
-// is during lowering, where it's not possible to recognize the load fold cause
-// it has two uses through a bitcast. One use disappears at isel time and the
-// fold opportunity reappears.
-def : Pat<(X86Movss VR128:$src1,
- (bc_v4i32 (v2i64 (load addr:$src2)))),
- (MOVLPSrm VR128:$src1, addr:$src2)>;
-
-// Shuffle with MOVSD
-def : Pat<(v2f64 (X86Movsd VR128:$src1, (scalar_to_vector FR64:$src2))),
- (MOVSDrr VR128:$src1, FR64:$src2)>;
-def : Pat<(v2i64 (X86Movsd VR128:$src1, VR128:$src2)),
- (MOVSDrr (v2i64 VR128:$src1),
- (EXTRACT_SUBREG (v2i64 VR128:$src2), sub_sd))>;
-def : Pat<(v2f64 (X86Movsd VR128:$src1, VR128:$src2)),
- (MOVSDrr (v2f64 VR128:$src1),
- (EXTRACT_SUBREG (v2f64 VR128:$src2), sub_sd))>;
-def : Pat<(v4f32 (X86Movsd VR128:$src1, VR128:$src2)),
- (MOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4f32 VR128:$src2), sub_sd))>;
-def : Pat<(v4i32 (X86Movsd VR128:$src1, VR128:$src2)),
- (MOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4i32 VR128:$src2), sub_sd))>;
-
-// Shuffle with MOVSHDUP
-def : Pat<(v4i32 (X86Movshdup VR128:$src)),
- (MOVSHDUPrr VR128:$src)>;
-def : Pat<(X86Movshdup (bc_v4i32 (memopv2i64 addr:$src))),
- (MOVSHDUPrm addr:$src)>;
-
-def : Pat<(v4f32 (X86Movshdup VR128:$src)),
- (MOVSHDUPrr VR128:$src)>;
-def : Pat<(X86Movshdup (memopv4f32 addr:$src)),
- (MOVSHDUPrm addr:$src)>;
-
-// Shuffle with MOVSLDUP
-def : Pat<(v4i32 (X86Movsldup VR128:$src)),
- (MOVSLDUPrr VR128:$src)>;
-def : Pat<(X86Movsldup (bc_v4i32 (memopv2i64 addr:$src))),
- (MOVSLDUPrm addr:$src)>;
-
-def : Pat<(v4f32 (X86Movsldup VR128:$src)),
- (MOVSLDUPrr VR128:$src)>;
-def : Pat<(X86Movsldup (memopv4f32 addr:$src)),
- (MOVSLDUPrm addr:$src)>;
-
-// Shuffle with PSHUFHW
-def : Pat<(v8i16 (X86PShufhw VR128:$src, (i8 imm:$imm))),
- (PSHUFHWri VR128:$src, imm:$imm)>;
-def : Pat<(v8i16 (X86PShufhw (bc_v8i16 (memopv2i64 addr:$src)), (i8 imm:$imm))),
- (PSHUFHWmi addr:$src, imm:$imm)>;
-
-// Shuffle with PSHUFLW
-def : Pat<(v8i16 (X86PShuflw VR128:$src, (i8 imm:$imm))),
- (PSHUFLWri VR128:$src, imm:$imm)>;
-def : Pat<(v8i16 (X86PShuflw (bc_v8i16 (memopv2i64 addr:$src)), (i8 imm:$imm))),
- (PSHUFLWmi addr:$src, imm:$imm)>;
-
-// Shuffle with PALIGN
-def : Pat<(v4i32 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
-def : Pat<(v4f32 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
-def : Pat<(v8i16 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
-def : Pat<(v16i8 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
- (PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
+ // Zero Upper bits of YMM registers
+ def VZEROUPPER : I<0x77, RawFrm, (outs), (ins), "vzeroupper",
+ [(int_x86_avx_vzeroupper)]>, TB, VEX, Requires<[HasAVX]>;
+}
-// Shuffle with MOVLPS
-def : Pat<(v4f32 (X86Movlps VR128:$src1, (load addr:$src2))),
- (MOVLPSrm VR128:$src1, addr:$src2)>;
-def : Pat<(v4i32 (X86Movlps VR128:$src1, (load addr:$src2))),
- (MOVLPSrm VR128:$src1, addr:$src2)>;
-def : Pat<(X86Movlps VR128:$src1,
- (bc_v4f32 (v2f64 (scalar_to_vector (loadf64 addr:$src2))))),
- (MOVLPSrm VR128:$src1, addr:$src2)>;
-// FIXME: Instead of a X86Movlps there should be a X86Movsd here, the problem
-// is during lowering, where it's not possible to recognize the load fold cause
-// it has two uses through a bitcast. One use disappears at isel time and the
-// fold opportunity reappears.
-def : Pat<(v4f32 (X86Movlps VR128:$src1, VR128:$src2)),
- (MOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4f32 VR128:$src2), sub_sd))>;
-
-def : Pat<(v4i32 (X86Movlps VR128:$src1, VR128:$src2)),
- (MOVSDrr VR128:$src1, (EXTRACT_SUBREG (v4i32 VR128:$src2), sub_sd))>;
-
-// Shuffle with MOVLPD
-def : Pat<(v2f64 (X86Movlpd VR128:$src1, (load addr:$src2))),
- (MOVLPDrm VR128:$src1, addr:$src2)>;
-def : Pat<(v2i64 (X86Movlpd VR128:$src1, (load addr:$src2))),
- (MOVLPDrm VR128:$src1, addr:$src2)>;
-def : Pat<(v2f64 (X86Movlpd VR128:$src1,
- (scalar_to_vector (loadf64 addr:$src2)))),
- (MOVLPDrm VR128:$src1, addr:$src2)>;
-
-// Extra patterns to match stores with MOVHPS/PD and MOVLPS/PD
-def : Pat<(store (f64 (vector_extract
- (v2f64 (X86Unpckhps VR128:$src, (undef))), (iPTR 0))),addr:$dst),
- (MOVHPSmr addr:$dst, VR128:$src)>;
-def : Pat<(store (f64 (vector_extract
- (v2f64 (X86Unpckhpd VR128:$src, (undef))), (iPTR 0))),addr:$dst),
- (MOVHPDmr addr:$dst, VR128:$src)>;
-
-def : Pat<(store (v4f32 (X86Movlps (load addr:$src1), VR128:$src2)),addr:$src1),
- (MOVLPSmr addr:$src1, VR128:$src2)>;
-def : Pat<(store (v4i32 (X86Movlps
- (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2)), addr:$src1),
- (MOVLPSmr addr:$src1, VR128:$src2)>;
-
-def : Pat<(store (v2f64 (X86Movlpd (load addr:$src1), VR128:$src2)),addr:$src1),
- (MOVLPDmr addr:$src1, VR128:$src2)>;
-def : Pat<(store (v2i64 (X86Movlpd (load addr:$src1), VR128:$src2)),addr:$src1),
- (MOVLPDmr addr:$src1, VR128:$src2)>;
+//===----------------------------------------------------------------------===//
+// Half precision conversion instructions
+//
+let Predicates = [HasAVX, HasF16C] in {
+ def VCVTPH2PSrm : I<0x13, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src),
+ "vcvtph2ps\t{$src, $dst|$dst, $src}", []>, T8, OpSize, VEX;
+ def VCVTPH2PSrr : I<0x13, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
+ "vcvtph2ps\t{$src, $dst|$dst, $src}", []>, T8, OpSize, VEX;
+ def VCVTPH2PSYrm : I<0x13, MRMSrcMem, (outs VR256:$dst), (ins f128mem:$src),
+ "vcvtph2ps\t{$src, $dst|$dst, $src}", []>, T8, OpSize, VEX;
+ def VCVTPH2PSYrr : I<0x13, MRMSrcReg, (outs VR256:$dst), (ins VR128:$src),
+ "vcvtph2ps\t{$src, $dst|$dst, $src}", []>, T8, OpSize, VEX;
+ def VCVTPS2PHmr : Ii8<0x1D, MRMDestMem, (outs f64mem:$dst),
+ (ins VR128:$src1, i32i8imm:$src2),
+ "vcvtps2ph\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>,
+ TA, OpSize, VEX;
+ def VCVTPS2PHrr : Ii8<0x1D, MRMDestReg, (outs VR128:$dst),
+ (ins VR128:$src1, i32i8imm:$src2),
+ "vcvtps2ph\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>,
+ TA, OpSize, VEX;
+ def VCVTPS2PHYmr : Ii8<0x1D, MRMDestMem, (outs f128mem:$dst),
+ (ins VR256:$src1, i32i8imm:$src2),
+ "vcvtps2ph\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>,
+ TA, OpSize, VEX;
+ def VCVTPS2PHYrr : Ii8<0x1D, MRMDestReg, (outs VR128:$dst),
+ (ins VR256:$src1, i32i8imm:$src2),
+ "vcvtps2ph\t{$src2, $src1, $dst|$dst, $src1, $src2}", []>,
+ TA, OpSize, VEX;
+}
diff --git a/lib/Target/X86/X86InstrSystem.td b/lib/Target/X86/X86InstrSystem.td
index 31de878..05a5b36 100644
--- a/lib/Target/X86/X86InstrSystem.td
+++ b/lib/Target/X86/X86InstrSystem.td
@@ -67,43 +67,43 @@ def IRET64 : RI<0xcf, RawFrm, (outs), (ins), "iretq", []>,
//
let Defs = [AL], Uses = [DX] in
def IN8rr : I<0xEC, RawFrm, (outs), (ins),
- "in{b}\t{%dx, %al|%AL, %DX}", []>;
+ "in{b}\t{%dx, %al|AL, DX}", []>;
let Defs = [AX], Uses = [DX] in
def IN16rr : I<0xED, RawFrm, (outs), (ins),
- "in{w}\t{%dx, %ax|%AX, %DX}", []>, OpSize;
+ "in{w}\t{%dx, %ax|AX, DX}", []>, OpSize;
let Defs = [EAX], Uses = [DX] in
def IN32rr : I<0xED, RawFrm, (outs), (ins),
- "in{l}\t{%dx, %eax|%EAX, %DX}", []>;
+ "in{l}\t{%dx, %eax|EAX, DX}", []>;
let Defs = [AL] in
def IN8ri : Ii8<0xE4, RawFrm, (outs), (ins i8imm:$port),
- "in{b}\t{$port, %al|%AL, $port}", []>;
+ "in{b}\t{$port, %al|AL, $port}", []>;
let Defs = [AX] in
def IN16ri : Ii8<0xE5, RawFrm, (outs), (ins i8imm:$port),
- "in{w}\t{$port, %ax|%AX, $port}", []>, OpSize;
+ "in{w}\t{$port, %ax|AX, $port}", []>, OpSize;
let Defs = [EAX] in
def IN32ri : Ii8<0xE5, RawFrm, (outs), (ins i8imm:$port),
- "in{l}\t{$port, %eax|%EAX, $port}", []>;
+ "in{l}\t{$port, %eax|EAX, $port}", []>;
let Uses = [DX, AL] in
def OUT8rr : I<0xEE, RawFrm, (outs), (ins),
- "out{b}\t{%al, %dx|%DX, %AL}", []>;
+ "out{b}\t{%al, %dx|DX, AL}", []>;
let Uses = [DX, AX] in
def OUT16rr : I<0xEF, RawFrm, (outs), (ins),
- "out{w}\t{%ax, %dx|%DX, %AX}", []>, OpSize;
+ "out{w}\t{%ax, %dx|DX, AX}", []>, OpSize;
let Uses = [DX, EAX] in
def OUT32rr : I<0xEF, RawFrm, (outs), (ins),
- "out{l}\t{%eax, %dx|%DX, %EAX}", []>;
+ "out{l}\t{%eax, %dx|DX, EAX}", []>;
let Uses = [AL] in
def OUT8ir : Ii8<0xE6, RawFrm, (outs), (ins i8imm:$port),
- "out{b}\t{%al, $port|$port, %AL}", []>;
+ "out{b}\t{%al, $port|$port, AL}", []>;
let Uses = [AX] in
def OUT16ir : Ii8<0xE7, RawFrm, (outs), (ins i8imm:$port),
- "out{w}\t{%ax, $port|$port, %AX}", []>, OpSize;
+ "out{w}\t{%ax, $port|$port, AX}", []>, OpSize;
let Uses = [EAX] in
def OUT32ir : Ii8<0xE7, RawFrm, (outs), (ins i8imm:$port),
- "out{l}\t{%eax, $port|$port, %EAX}", []>;
+ "out{l}\t{%eax, $port|$port, EAX}", []>;
def IN8 : I<0x6C, RawFrm, (outs), (ins), "ins{b}", []>;
def IN16 : I<0x6D, RawFrm, (outs), (ins), "ins{w}", []>, OpSize;
@@ -229,65 +229,65 @@ def LTRm : I<0x00, MRM3m, (outs), (ins i16mem:$src),
"ltr{w}\t{$src}", []>, TB;
def PUSHCS16 : I<0x0E, RawFrm, (outs), (ins),
- "push{w}\t%cs", []>, Requires<[In32BitMode]>, OpSize;
+ "push{w}\t{%cs|CS}", []>, Requires<[In32BitMode]>, OpSize;
def PUSHCS32 : I<0x0E, RawFrm, (outs), (ins),
- "push{l}\t%cs", []>, Requires<[In32BitMode]>;
+ "push{l}\t{%cs|CS}", []>, Requires<[In32BitMode]>;
def PUSHSS16 : I<0x16, RawFrm, (outs), (ins),
- "push{w}\t%ss", []>, Requires<[In32BitMode]>, OpSize;
+ "push{w}\t{%ss|SS}", []>, Requires<[In32BitMode]>, OpSize;
def PUSHSS32 : I<0x16, RawFrm, (outs), (ins),
- "push{l}\t%ss", []>, Requires<[In32BitMode]>;
+ "push{l}\t{%ss|SS}", []>, Requires<[In32BitMode]>;
def PUSHDS16 : I<0x1E, RawFrm, (outs), (ins),
- "push{w}\t%ds", []>, Requires<[In32BitMode]>, OpSize;
+ "push{w}\t{%ds|DS}", []>, Requires<[In32BitMode]>, OpSize;
def PUSHDS32 : I<0x1E, RawFrm, (outs), (ins),
- "push{l}\t%ds", []>, Requires<[In32BitMode]>;
+ "push{l}\t{%ds|DS}", []>, Requires<[In32BitMode]>;
def PUSHES16 : I<0x06, RawFrm, (outs), (ins),
- "push{w}\t%es", []>, Requires<[In32BitMode]>, OpSize;
+ "push{w}\t{%es|ES}", []>, Requires<[In32BitMode]>, OpSize;
def PUSHES32 : I<0x06, RawFrm, (outs), (ins),
- "push{l}\t%es", []>, Requires<[In32BitMode]>;
+ "push{l}\t{%es|ES}", []>, Requires<[In32BitMode]>;
def PUSHFS16 : I<0xa0, RawFrm, (outs), (ins),
- "push{w}\t%fs", []>, OpSize, TB;
+ "push{w}\t{%fs|FS}", []>, OpSize, TB;
def PUSHFS32 : I<0xa0, RawFrm, (outs), (ins),
- "push{l}\t%fs", []>, TB, Requires<[In32BitMode]>;
+ "push{l}\t{%fs|FS}", []>, TB, Requires<[In32BitMode]>;
def PUSHGS16 : I<0xa8, RawFrm, (outs), (ins),
- "push{w}\t%gs", []>, OpSize, TB;
+ "push{w}\t{%gs|GS}", []>, OpSize, TB;
def PUSHGS32 : I<0xa8, RawFrm, (outs), (ins),
- "push{l}\t%gs", []>, TB, Requires<[In32BitMode]>;
+ "push{l}\t{%gs|GS}", []>, TB, Requires<[In32BitMode]>;
def PUSHFS64 : I<0xa0, RawFrm, (outs), (ins),
- "push{q}\t%fs", []>, TB;
+ "push{q}\t{%fs|FS}", []>, TB;
def PUSHGS64 : I<0xa8, RawFrm, (outs), (ins),
- "push{q}\t%gs", []>, TB;
+ "push{q}\t{%gs|GS}", []>, TB;
// No "pop cs" instruction.
def POPSS16 : I<0x17, RawFrm, (outs), (ins),
- "pop{w}\t%ss", []>, OpSize, Requires<[In32BitMode]>;
+ "pop{w}\t{%ss|SS}", []>, OpSize, Requires<[In32BitMode]>;
def POPSS32 : I<0x17, RawFrm, (outs), (ins),
- "pop{l}\t%ss", []> , Requires<[In32BitMode]>;
+ "pop{l}\t{%ss|SS}", []> , Requires<[In32BitMode]>;
def POPDS16 : I<0x1F, RawFrm, (outs), (ins),
- "pop{w}\t%ds", []>, OpSize, Requires<[In32BitMode]>;
+ "pop{w}\t{%ds|DS}", []>, OpSize, Requires<[In32BitMode]>;
def POPDS32 : I<0x1F, RawFrm, (outs), (ins),
- "pop{l}\t%ds", []> , Requires<[In32BitMode]>;
+ "pop{l}\t{%ds|DS}", []> , Requires<[In32BitMode]>;
def POPES16 : I<0x07, RawFrm, (outs), (ins),
- "pop{w}\t%es", []>, OpSize, Requires<[In32BitMode]>;
+ "pop{w}\t{%es|ES}", []>, OpSize, Requires<[In32BitMode]>;
def POPES32 : I<0x07, RawFrm, (outs), (ins),
- "pop{l}\t%es", []> , Requires<[In32BitMode]>;
+ "pop{l}\t{%es|ES}", []> , Requires<[In32BitMode]>;
def POPFS16 : I<0xa1, RawFrm, (outs), (ins),
- "pop{w}\t%fs", []>, OpSize, TB;
+ "pop{w}\t{%fs|FS}", []>, OpSize, TB;
def POPFS32 : I<0xa1, RawFrm, (outs), (ins),
- "pop{l}\t%fs", []>, TB , Requires<[In32BitMode]>;
+ "pop{l}\t{%fs|FS}", []>, TB , Requires<[In32BitMode]>;
def POPFS64 : I<0xa1, RawFrm, (outs), (ins),
- "pop{q}\t%fs", []>, TB;
+ "pop{q}\t{%fs|FS}", []>, TB;
def POPGS16 : I<0xa9, RawFrm, (outs), (ins),
- "pop{w}\t%gs", []>, OpSize, TB;
+ "pop{w}\t{%gs|GS}", []>, OpSize, TB;
def POPGS32 : I<0xa9, RawFrm, (outs), (ins),
- "pop{l}\t%gs", []>, TB , Requires<[In32BitMode]>;
+ "pop{l}\t{%gs|GS}", []>, TB , Requires<[In32BitMode]>;
def POPGS64 : I<0xa9, RawFrm, (outs), (ins),
- "pop{q}\t%gs", []>, TB;
+ "pop{q}\t{%gs|GS}", []>, TB;
def LDS16rm : I<0xc5, MRMSrcMem, (outs GR16:$dst), (ins opaque32mem:$src),
@@ -400,12 +400,29 @@ def CPUID : I<0xA2, RawFrm, (outs), (ins), "cpuid", []>, TB;
def INVD : I<0x08, RawFrm, (outs), (ins), "invd", []>, TB;
def WBINVD : I<0x09, RawFrm, (outs), (ins), "wbinvd", []>, TB;
+//===----------------------------------------------------------------------===//
+// XSAVE instructions
let Defs = [RDX, RAX], Uses = [RCX] in
def XGETBV : I<0x01, MRM_D0, (outs), (ins), "xgetbv", []>, TB;
let Uses = [RDX, RAX, RCX] in
def XSETBV : I<0x01, MRM_D1, (outs), (ins), "xsetbv", []>, TB;
+let Uses = [RDX, RAX] in {
+ def XSAVE : I<0xAE, MRM4m, (outs opaque512mem:$dst), (ins),
+ "xsave\t$dst", []>, TB;
+ def XSAVE64 : I<0xAE, MRM4m, (outs opaque512mem:$dst), (ins),
+ "xsaveq\t$dst", []>, TB, REX_W, Requires<[In64BitMode]>;
+ def XRSTOR : I<0xAE, MRM5m, (outs), (ins opaque512mem:$dst),
+ "xrstor\t$dst", []>, TB;
+ def XRSTOR64 : I<0xAE, MRM5m, (outs), (ins opaque512mem:$dst),
+ "xrstorq\t$dst", []>, TB, REX_W, Requires<[In64BitMode]>;
+ def XSAVEOPT : I<0xAE, MRM6m, (outs opaque512mem:$dst), (ins),
+ "xsaveopt\t$dst", []>, TB;
+ def XSAVEOPT64 : I<0xAE, MRM6m, (outs opaque512mem:$dst), (ins),
+ "xsaveoptq\t$dst", []>, TB, REX_W, Requires<[In64BitMode]>;
+}
+
//===----------------------------------------------------------------------===//
// VIA PadLock crypto instructions
let Defs = [RAX, RDI], Uses = [RDX, RDI] in
@@ -427,3 +444,24 @@ let Defs = [RAX, RSI, RDI], Uses = [RAX, RSI, RDI] in {
}
let Defs = [RAX, RDX, RSI], Uses = [RAX, RSI] in
def MONTMUL : I<0xc0, RawFrm, (outs), (ins), "montmul", []>, A6;
+
+//===----------------------------------------------------------------------===//
+// FS/GS Base Instructions
+let Predicates = [In64BitMode] in {
+ def RDFSBASE : I<0xAE, MRM0r, (outs GR32:$dst), (ins),
+ "rdfsbase{l}\t$dst", []>, TB, XS;
+ def RDFSBASE64 : RI<0xAE, MRM0r, (outs GR64:$dst), (ins),
+ "rdfsbase{q}\t$dst", []>, TB, XS;
+ def RDGSBASE : I<0xAE, MRM1r, (outs GR32:$dst), (ins),
+ "rdgsbase{l}\t$dst", []>, TB, XS;
+ def RDGSBASE64 : RI<0xAE, MRM1r, (outs GR64:$dst), (ins),
+ "rdgsbase{q}\t$dst", []>, TB, XS;
+ def WRFSBASE : I<0xAE, MRM2r, (outs), (ins GR32:$dst),
+ "wrfsbase{l}\t$dst", []>, TB, XS;
+ def WRFSBASE64 : RI<0xAE, MRM2r, (outs), (ins GR64:$dst),
+ "wrfsbase{q}\t$dst", []>, TB, XS;
+ def WRGSBASE : I<0xAE, MRM3r, (outs), (ins GR32:$dst),
+ "wrgsbase{l}\t$dst", []>, TB, XS;
+ def WRGSBASE64 : RI<0xAE, MRM3r, (outs), (ins GR64:$dst),
+ "wrgsbase{q}\t$dst", []>, TB, XS;
+}
diff --git a/lib/Target/X86/X86InstrVMX.td b/lib/Target/X86/X86InstrVMX.td
index daf61e4..09a7a7d0c 100644
--- a/lib/Target/X86/X86InstrVMX.td
+++ b/lib/Target/X86/X86InstrVMX.td
@@ -16,9 +16,15 @@
// VMX instructions
// 66 0F 38 80
-def INVEPT : I<0x80, RawFrm, (outs), (ins), "invept", []>, OpSize, T8;
+def INVEPT32 : I<0x80, MRMSrcMem, (outs), (ins GR32:$src1, i128mem:$src2),
+ "invept {$src2, $src1|$src1, $src2}", []>, OpSize, T8;
+def INVEPT64 : I<0x80, MRMSrcMem, (outs), (ins GR64:$src1, i128mem:$src2),
+ "invept {$src2, $src1|$src1, $src2}", []>, OpSize, T8;
// 66 0F 38 81
-def INVVPID : I<0x81, RawFrm, (outs), (ins), "invvpid", []>, OpSize, T8;
+def INVVPID32 : I<0x81, MRMSrcMem, (outs), (ins GR32:$src1, i128mem:$src2),
+ "invvpid {$src2, $src1|$src1, $src2}", []>, OpSize, T8;
+def INVVPID64 : I<0x81, MRMSrcMem, (outs), (ins GR64:$src1, i128mem:$src2),
+ "invvpid {$src2, $src1|$src1, $src2}", []>, OpSize, T8;
// 0F 01 C1
def VMCALL : I<0x01, MRM_C1, (outs), (ins), "vmcall", []>, TB;
def VMCLEARm : I<0xC7, MRM6m, (outs), (ins i64mem:$vmcs),
diff --git a/lib/Target/X86/X86MCCodeEmitter.cpp b/lib/Target/X86/X86MCCodeEmitter.cpp
deleted file mode 100644
index ce8ef49..0000000
--- a/lib/Target/X86/X86MCCodeEmitter.cpp
+++ /dev/null
@@ -1,1044 +0,0 @@
-//===-- X86/X86MCCodeEmitter.cpp - Convert X86 code to machine code -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the X86MCCodeEmitter class.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "mccodeemitter"
-#include "X86.h"
-#include "X86InstrInfo.h"
-#include "X86FixupKinds.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-namespace {
-class X86MCCodeEmitter : public MCCodeEmitter {
- X86MCCodeEmitter(const X86MCCodeEmitter &); // DO NOT IMPLEMENT
- void operator=(const X86MCCodeEmitter &); // DO NOT IMPLEMENT
- const MCInstrInfo &MCII;
- const MCSubtargetInfo &STI;
- MCContext &Ctx;
-public:
- X86MCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
- MCContext &ctx)
- : MCII(mcii), STI(sti), Ctx(ctx) {
- }
-
- ~X86MCCodeEmitter() {}
-
- bool is64BitMode() const {
- // FIXME: Can tablegen auto-generate this?
- return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
- }
-
- static unsigned GetX86RegNum(const MCOperand &MO) {
- return X86RegisterInfo::getX86RegNum(MO.getReg());
- }
-
- // On regular x86, both XMM0-XMM7 and XMM8-XMM15 are encoded in the range
- // 0-7 and the difference between the 2 groups is given by the REX prefix.
- // In the VEX prefix, registers are seen sequencially from 0-15 and encoded
- // in 1's complement form, example:
- //
- // ModRM field => XMM9 => 1
- // VEX.VVVV => XMM9 => ~9
- //
- // See table 4-35 of Intel AVX Programming Reference for details.
- static unsigned char getVEXRegisterEncoding(const MCInst &MI,
- unsigned OpNum) {
- unsigned SrcReg = MI.getOperand(OpNum).getReg();
- unsigned SrcRegNum = GetX86RegNum(MI.getOperand(OpNum));
- if ((SrcReg >= X86::XMM8 && SrcReg <= X86::XMM15) ||
- (SrcReg >= X86::YMM8 && SrcReg <= X86::YMM15))
- SrcRegNum += 8;
-
- // The registers represented through VEX_VVVV should
- // be encoded in 1's complement form.
- return (~SrcRegNum) & 0xf;
- }
-
- void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
- OS << (char)C;
- ++CurByte;
- }
-
- void EmitConstant(uint64_t Val, unsigned Size, unsigned &CurByte,
- raw_ostream &OS) const {
- // Output the constant in little endian byte order.
- for (unsigned i = 0; i != Size; ++i) {
- EmitByte(Val & 255, CurByte, OS);
- Val >>= 8;
- }
- }
-
- void EmitImmediate(const MCOperand &Disp,
- unsigned ImmSize, MCFixupKind FixupKind,
- unsigned &CurByte, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups,
- int ImmOffset = 0) const;
-
- inline static unsigned char ModRMByte(unsigned Mod, unsigned RegOpcode,
- unsigned RM) {
- assert(Mod < 4 && RegOpcode < 8 && RM < 8 && "ModRM Fields out of range!");
- return RM | (RegOpcode << 3) | (Mod << 6);
- }
-
- void EmitRegModRMByte(const MCOperand &ModRMReg, unsigned RegOpcodeFld,
- unsigned &CurByte, raw_ostream &OS) const {
- EmitByte(ModRMByte(3, RegOpcodeFld, GetX86RegNum(ModRMReg)), CurByte, OS);
- }
-
- void EmitSIBByte(unsigned SS, unsigned Index, unsigned Base,
- unsigned &CurByte, raw_ostream &OS) const {
- // SIB byte is in the same format as the ModRMByte.
- EmitByte(ModRMByte(SS, Index, Base), CurByte, OS);
- }
-
-
- void EmitMemModRMByte(const MCInst &MI, unsigned Op,
- unsigned RegOpcodeField,
- uint64_t TSFlags, unsigned &CurByte, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const;
-
- void EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand,
- const MCInst &MI, const MCInstrDesc &Desc,
- raw_ostream &OS) const;
-
- void EmitSegmentOverridePrefix(uint64_t TSFlags, unsigned &CurByte,
- int MemOperand, const MCInst &MI,
- raw_ostream &OS) const;
-
- void EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand,
- const MCInst &MI, const MCInstrDesc &Desc,
- raw_ostream &OS) const;
-};
-
-} // end anonymous namespace
-
-
-MCCodeEmitter *llvm::createX86MCCodeEmitter(const MCInstrInfo &MCII,
- const MCSubtargetInfo &STI,
- MCContext &Ctx) {
- return new X86MCCodeEmitter(MCII, STI, Ctx);
-}
-
-/// isDisp8 - Return true if this signed displacement fits in a 8-bit
-/// sign-extended field.
-static bool isDisp8(int Value) {
- return Value == (signed char)Value;
-}
-
-/// getImmFixupKind - Return the appropriate fixup kind to use for an immediate
-/// in an instruction with the specified TSFlags.
-static MCFixupKind getImmFixupKind(uint64_t TSFlags) {
- unsigned Size = X86II::getSizeOfImm(TSFlags);
- bool isPCRel = X86II::isImmPCRel(TSFlags);
-
- return MCFixup::getKindForSize(Size, isPCRel);
-}
-
-/// Is32BitMemOperand - Return true if the specified instruction with a memory
-/// operand should emit the 0x67 prefix byte in 64-bit mode due to a 32-bit
-/// memory operand. Op specifies the operand # of the memoperand.
-static bool Is32BitMemOperand(const MCInst &MI, unsigned Op) {
- const MCOperand &BaseReg = MI.getOperand(Op+X86::AddrBaseReg);
- const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg);
-
- if ((BaseReg.getReg() != 0 && X86::GR32RegClass.contains(BaseReg.getReg())) ||
- (IndexReg.getReg() != 0 && X86::GR32RegClass.contains(IndexReg.getReg())))
- return true;
- return false;
-}
-
-/// StartsWithGlobalOffsetTable - Return true for the simple cases where this
-/// expression starts with _GLOBAL_OFFSET_TABLE_. This is a needed to support
-/// PIC on ELF i386 as that symbol is magic. We check only simple case that
-/// are know to be used: _GLOBAL_OFFSET_TABLE_ by itself or at the start
-/// of a binary expression.
-static bool StartsWithGlobalOffsetTable(const MCExpr *Expr) {
- if (Expr->getKind() == MCExpr::Binary) {
- const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Expr);
- Expr = BE->getLHS();
- }
-
- if (Expr->getKind() != MCExpr::SymbolRef)
- return false;
-
- const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
- const MCSymbol &S = Ref->getSymbol();
- return S.getName() == "_GLOBAL_OFFSET_TABLE_";
-}
-
-void X86MCCodeEmitter::
-EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
- unsigned &CurByte, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups, int ImmOffset) const {
- const MCExpr *Expr = NULL;
- if (DispOp.isImm()) {
- // If this is a simple integer displacement that doesn't require a relocation,
- // emit it now.
- if (FixupKind != FK_PCRel_1 &&
- FixupKind != FK_PCRel_2 &&
- FixupKind != FK_PCRel_4) {
- EmitConstant(DispOp.getImm()+ImmOffset, Size, CurByte, OS);
- return;
- }
- Expr = MCConstantExpr::Create(DispOp.getImm(), Ctx);
- } else {
- Expr = DispOp.getExpr();
- }
-
- // If we have an immoffset, add it to the expression.
- if (FixupKind == FK_Data_4 && StartsWithGlobalOffsetTable(Expr)) {
- assert(ImmOffset == 0);
-
- FixupKind = MCFixupKind(X86::reloc_global_offset_table);
- ImmOffset = CurByte;
- }
-
- // If the fixup is pc-relative, we need to bias the value to be relative to
- // the start of the field, not the end of the field.
- if (FixupKind == FK_PCRel_4 ||
- FixupKind == MCFixupKind(X86::reloc_riprel_4byte) ||
- FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load))
- ImmOffset -= 4;
- if (FixupKind == FK_PCRel_2)
- ImmOffset -= 2;
- if (FixupKind == FK_PCRel_1)
- ImmOffset -= 1;
-
- if (ImmOffset)
- Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(ImmOffset, Ctx),
- Ctx);
-
- // Emit a symbolic constant as a fixup and 4 zeros.
- Fixups.push_back(MCFixup::Create(CurByte, Expr, FixupKind));
- EmitConstant(0, Size, CurByte, OS);
-}
-
-void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op,
- unsigned RegOpcodeField,
- uint64_t TSFlags, unsigned &CurByte,
- raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const{
- const MCOperand &Disp = MI.getOperand(Op+X86::AddrDisp);
- const MCOperand &Base = MI.getOperand(Op+X86::AddrBaseReg);
- const MCOperand &Scale = MI.getOperand(Op+X86::AddrScaleAmt);
- const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg);
- unsigned BaseReg = Base.getReg();
-
- // Handle %rip relative addressing.
- if (BaseReg == X86::RIP) { // [disp32+RIP] in X86-64 mode
- assert(is64BitMode() && "Rip-relative addressing requires 64-bit mode");
- assert(IndexReg.getReg() == 0 && "Invalid rip-relative address");
- EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS);
-
- unsigned FixupKind = X86::reloc_riprel_4byte;
-
- // movq loads are handled with a special relocation form which allows the
- // linker to eliminate some loads for GOT references which end up in the
- // same linkage unit.
- if (MI.getOpcode() == X86::MOV64rm)
- FixupKind = X86::reloc_riprel_4byte_movq_load;
-
- // rip-relative addressing is actually relative to the *next* instruction.
- // Since an immediate can follow the mod/rm byte for an instruction, this
- // means that we need to bias the immediate field of the instruction with
- // the size of the immediate field. If we have this case, add it into the
- // expression to emit.
- int ImmSize = X86II::hasImm(TSFlags) ? X86II::getSizeOfImm(TSFlags) : 0;
-
- EmitImmediate(Disp, 4, MCFixupKind(FixupKind),
- CurByte, OS, Fixups, -ImmSize);
- return;
- }
-
- unsigned BaseRegNo = BaseReg ? GetX86RegNum(Base) : -1U;
-
- // Determine whether a SIB byte is needed.
- // If no BaseReg, issue a RIP relative instruction only if the MCE can
- // resolve addresses on-the-fly, otherwise use SIB (Intel Manual 2A, table
- // 2-7) and absolute references.
-
- if (// The SIB byte must be used if there is an index register.
- IndexReg.getReg() == 0 &&
- // The SIB byte must be used if the base is ESP/RSP/R12, all of which
- // encode to an R/M value of 4, which indicates that a SIB byte is
- // present.
- BaseRegNo != N86::ESP &&
- // If there is no base register and we're in 64-bit mode, we need a SIB
- // byte to emit an addr that is just 'disp32' (the non-RIP relative form).
- (!is64BitMode() || BaseReg != 0)) {
-
- if (BaseReg == 0) { // [disp32] in X86-32 mode
- EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS);
- EmitImmediate(Disp, 4, FK_Data_4, CurByte, OS, Fixups);
- return;
- }
-
- // If the base is not EBP/ESP and there is no displacement, use simple
- // indirect register encoding, this handles addresses like [EAX]. The
- // encoding for [EBP] with no displacement means [disp32] so we handle it
- // by emitting a displacement of 0 below.
- if (Disp.isImm() && Disp.getImm() == 0 && BaseRegNo != N86::EBP) {
- EmitByte(ModRMByte(0, RegOpcodeField, BaseRegNo), CurByte, OS);
- return;
- }
-
- // Otherwise, if the displacement fits in a byte, encode as [REG+disp8].
- if (Disp.isImm() && isDisp8(Disp.getImm())) {
- EmitByte(ModRMByte(1, RegOpcodeField, BaseRegNo), CurByte, OS);
- EmitImmediate(Disp, 1, FK_Data_1, CurByte, OS, Fixups);
- return;
- }
-
- // Otherwise, emit the most general non-SIB encoding: [REG+disp32]
- EmitByte(ModRMByte(2, RegOpcodeField, BaseRegNo), CurByte, OS);
- EmitImmediate(Disp, 4, MCFixupKind(X86::reloc_signed_4byte), CurByte, OS,
- Fixups);
- return;
- }
-
- // We need a SIB byte, so start by outputting the ModR/M byte first
- assert(IndexReg.getReg() != X86::ESP &&
- IndexReg.getReg() != X86::RSP && "Cannot use ESP as index reg!");
-
- bool ForceDisp32 = false;
- bool ForceDisp8 = false;
- if (BaseReg == 0) {
- // If there is no base register, we emit the special case SIB byte with
- // MOD=0, BASE=5, to JUST get the index, scale, and displacement.
- EmitByte(ModRMByte(0, RegOpcodeField, 4), CurByte, OS);
- ForceDisp32 = true;
- } else if (!Disp.isImm()) {
- // Emit the normal disp32 encoding.
- EmitByte(ModRMByte(2, RegOpcodeField, 4), CurByte, OS);
- ForceDisp32 = true;
- } else if (Disp.getImm() == 0 &&
- // Base reg can't be anything that ends up with '5' as the base
- // reg, it is the magic [*] nomenclature that indicates no base.
- BaseRegNo != N86::EBP) {
- // Emit no displacement ModR/M byte
- EmitByte(ModRMByte(0, RegOpcodeField, 4), CurByte, OS);
- } else if (isDisp8(Disp.getImm())) {
- // Emit the disp8 encoding.
- EmitByte(ModRMByte(1, RegOpcodeField, 4), CurByte, OS);
- ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP
- } else {
- // Emit the normal disp32 encoding.
- EmitByte(ModRMByte(2, RegOpcodeField, 4), CurByte, OS);
- }
-
- // Calculate what the SS field value should be...
- static const unsigned SSTable[] = { ~0, 0, 1, ~0, 2, ~0, ~0, ~0, 3 };
- unsigned SS = SSTable[Scale.getImm()];
-
- if (BaseReg == 0) {
- // Handle the SIB byte for the case where there is no base, see Intel
- // Manual 2A, table 2-7. The displacement has already been output.
- unsigned IndexRegNo;
- if (IndexReg.getReg())
- IndexRegNo = GetX86RegNum(IndexReg);
- else // Examples: [ESP+1*<noreg>+4] or [scaled idx]+disp32 (MOD=0,BASE=5)
- IndexRegNo = 4;
- EmitSIBByte(SS, IndexRegNo, 5, CurByte, OS);
- } else {
- unsigned IndexRegNo;
- if (IndexReg.getReg())
- IndexRegNo = GetX86RegNum(IndexReg);
- else
- IndexRegNo = 4; // For example [ESP+1*<noreg>+4]
- EmitSIBByte(SS, IndexRegNo, GetX86RegNum(Base), CurByte, OS);
- }
-
- // Do we need to output a displacement?
- if (ForceDisp8)
- EmitImmediate(Disp, 1, FK_Data_1, CurByte, OS, Fixups);
- else if (ForceDisp32 || Disp.getImm() != 0)
- EmitImmediate(Disp, 4, MCFixupKind(X86::reloc_signed_4byte), CurByte, OS,
- Fixups);
-}
-
-/// EmitVEXOpcodePrefix - AVX instructions are encoded using a opcode prefix
-/// called VEX.
-void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
- int MemOperand, const MCInst &MI,
- const MCInstrDesc &Desc,
- raw_ostream &OS) const {
- bool HasVEX_4V = false;
- if ((TSFlags >> X86II::VEXShift) & X86II::VEX_4V)
- HasVEX_4V = true;
-
- // VEX_R: opcode externsion equivalent to REX.R in
- // 1's complement (inverted) form
- //
- // 1: Same as REX_R=0 (must be 1 in 32-bit mode)
- // 0: Same as REX_R=1 (64 bit mode only)
- //
- unsigned char VEX_R = 0x1;
-
- // VEX_X: equivalent to REX.X, only used when a
- // register is used for index in SIB Byte.
- //
- // 1: Same as REX.X=0 (must be 1 in 32-bit mode)
- // 0: Same as REX.X=1 (64-bit mode only)
- unsigned char VEX_X = 0x1;
-
- // VEX_B:
- //
- // 1: Same as REX_B=0 (ignored in 32-bit mode)
- // 0: Same as REX_B=1 (64 bit mode only)
- //
- unsigned char VEX_B = 0x1;
-
- // VEX_W: opcode specific (use like REX.W, or used for
- // opcode extension, or ignored, depending on the opcode byte)
- unsigned char VEX_W = 0;
-
- // VEX_5M (VEX m-mmmmm field):
- //
- // 0b00000: Reserved for future use
- // 0b00001: implied 0F leading opcode
- // 0b00010: implied 0F 38 leading opcode bytes
- // 0b00011: implied 0F 3A leading opcode bytes
- // 0b00100-0b11111: Reserved for future use
- //
- unsigned char VEX_5M = 0x1;
-
- // VEX_4V (VEX vvvv field): a register specifier
- // (in 1's complement form) or 1111 if unused.
- unsigned char VEX_4V = 0xf;
-
- // VEX_L (Vector Length):
- //
- // 0: scalar or 128-bit vector
- // 1: 256-bit vector
- //
- unsigned char VEX_L = 0;
-
- // VEX_PP: opcode extension providing equivalent
- // functionality of a SIMD prefix
- //
- // 0b00: None
- // 0b01: 66
- // 0b10: F3
- // 0b11: F2
- //
- unsigned char VEX_PP = 0;
-
- // Encode the operand size opcode prefix as needed.
- if (TSFlags & X86II::OpSize)
- VEX_PP = 0x01;
-
- if ((TSFlags >> X86II::VEXShift) & X86II::VEX_W)
- VEX_W = 1;
-
- if ((TSFlags >> X86II::VEXShift) & X86II::VEX_L)
- VEX_L = 1;
-
- switch (TSFlags & X86II::Op0Mask) {
- default: assert(0 && "Invalid prefix!");
- case X86II::T8: // 0F 38
- VEX_5M = 0x2;
- break;
- case X86II::TA: // 0F 3A
- VEX_5M = 0x3;
- break;
- case X86II::TF: // F2 0F 38
- VEX_PP = 0x3;
- VEX_5M = 0x2;
- break;
- case X86II::XS: // F3 0F
- VEX_PP = 0x2;
- break;
- case X86II::XD: // F2 0F
- VEX_PP = 0x3;
- break;
- case X86II::A6: // Bypass: Not used by VEX
- case X86II::A7: // Bypass: Not used by VEX
- case X86II::TB: // Bypass: Not used by VEX
- case 0:
- break; // No prefix!
- }
-
- // Set the vector length to 256-bit if YMM0-YMM15 is used
- for (unsigned i = 0; i != MI.getNumOperands(); ++i) {
- if (!MI.getOperand(i).isReg())
- continue;
- unsigned SrcReg = MI.getOperand(i).getReg();
- if (SrcReg >= X86::YMM0 && SrcReg <= X86::YMM15)
- VEX_L = 1;
- }
-
- unsigned NumOps = MI.getNumOperands();
- unsigned CurOp = 0;
- bool IsDestMem = false;
-
- switch (TSFlags & X86II::FormMask) {
- case X86II::MRMInitReg: assert(0 && "FIXME: Remove this!");
- case X86II::MRMDestMem:
- IsDestMem = true;
- // The important info for the VEX prefix is never beyond the address
- // registers. Don't check beyond that.
- NumOps = CurOp = X86::AddrNumOperands;
- case X86II::MRM0m: case X86II::MRM1m:
- case X86II::MRM2m: case X86II::MRM3m:
- case X86II::MRM4m: case X86II::MRM5m:
- case X86II::MRM6m: case X86II::MRM7m:
- case X86II::MRMSrcMem:
- case X86II::MRMSrcReg:
- if (MI.getNumOperands() > CurOp && MI.getOperand(CurOp).isReg() &&
- X86InstrInfo::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg()))
- VEX_R = 0x0;
- CurOp++;
-
- if (HasVEX_4V) {
- VEX_4V = getVEXRegisterEncoding(MI, IsDestMem ? CurOp-1 : CurOp);
- CurOp++;
- }
-
- // To only check operands before the memory address ones, start
- // the search from the beginning
- if (IsDestMem)
- CurOp = 0;
-
- // If the last register should be encoded in the immediate field
- // do not use any bit from VEX prefix to this register, ignore it
- if ((TSFlags >> X86II::VEXShift) & X86II::VEX_I8IMM)
- NumOps--;
-
- for (; CurOp != NumOps; ++CurOp) {
- const MCOperand &MO = MI.getOperand(CurOp);
- if (MO.isReg() && X86InstrInfo::isX86_64ExtendedReg(MO.getReg()))
- VEX_B = 0x0;
- if (!VEX_B && MO.isReg() &&
- ((TSFlags & X86II::FormMask) == X86II::MRMSrcMem) &&
- X86InstrInfo::isX86_64ExtendedReg(MO.getReg()))
- VEX_X = 0x0;
- }
- break;
- default: // MRMDestReg, MRM0r-MRM7r, RawFrm
- if (!MI.getNumOperands())
- break;
-
- if (MI.getOperand(CurOp).isReg() &&
- X86InstrInfo::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg()))
- VEX_B = 0;
-
- if (HasVEX_4V)
- VEX_4V = getVEXRegisterEncoding(MI, CurOp);
-
- CurOp++;
- for (; CurOp != NumOps; ++CurOp) {
- const MCOperand &MO = MI.getOperand(CurOp);
- if (MO.isReg() && !HasVEX_4V &&
- X86InstrInfo::isX86_64ExtendedReg(MO.getReg()))
- VEX_R = 0x0;
- }
- break;
- }
-
- // Emit segment override opcode prefix as needed.
- EmitSegmentOverridePrefix(TSFlags, CurByte, MemOperand, MI, OS);
-
- // VEX opcode prefix can have 2 or 3 bytes
- //
- // 3 bytes:
- // +-----+ +--------------+ +-------------------+
- // | C4h | | RXB | m-mmmm | | W | vvvv | L | pp |
- // +-----+ +--------------+ +-------------------+
- // 2 bytes:
- // +-----+ +-------------------+
- // | C5h | | R | vvvv | L | pp |
- // +-----+ +-------------------+
- //
- unsigned char LastByte = VEX_PP | (VEX_L << 2) | (VEX_4V << 3);
-
- if (VEX_B && VEX_X && !VEX_W && (VEX_5M == 1)) { // 2 byte VEX prefix
- EmitByte(0xC5, CurByte, OS);
- EmitByte(LastByte | (VEX_R << 7), CurByte, OS);
- return;
- }
-
- // 3 byte VEX prefix
- EmitByte(0xC4, CurByte, OS);
- EmitByte(VEX_R << 7 | VEX_X << 6 | VEX_B << 5 | VEX_5M, CurByte, OS);
- EmitByte(LastByte | (VEX_W << 7), CurByte, OS);
-}
-
-/// DetermineREXPrefix - Determine if the MCInst has to be encoded with a X86-64
-/// REX prefix which specifies 1) 64-bit instructions, 2) non-default operand
-/// size, and 3) use of X86-64 extended registers.
-static unsigned DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags,
- const MCInstrDesc &Desc) {
- unsigned REX = 0;
- if (TSFlags & X86II::REX_W)
- REX |= 1 << 3; // set REX.W
-
- if (MI.getNumOperands() == 0) return REX;
-
- unsigned NumOps = MI.getNumOperands();
- // FIXME: MCInst should explicitize the two-addrness.
- bool isTwoAddr = NumOps > 1 &&
- Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1;
-
- // If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix.
- unsigned i = isTwoAddr ? 1 : 0;
- for (; i != NumOps; ++i) {
- const MCOperand &MO = MI.getOperand(i);
- if (!MO.isReg()) continue;
- unsigned Reg = MO.getReg();
- if (!X86InstrInfo::isX86_64NonExtLowByteReg(Reg)) continue;
- // FIXME: The caller of DetermineREXPrefix slaps this prefix onto anything
- // that returns non-zero.
- REX |= 0x40; // REX fixed encoding prefix
- break;
- }
-
- switch (TSFlags & X86II::FormMask) {
- case X86II::MRMInitReg: assert(0 && "FIXME: Remove this!");
- case X86II::MRMSrcReg:
- if (MI.getOperand(0).isReg() &&
- X86InstrInfo::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
- REX |= 1 << 2; // set REX.R
- i = isTwoAddr ? 2 : 1;
- for (; i != NumOps; ++i) {
- const MCOperand &MO = MI.getOperand(i);
- if (MO.isReg() && X86InstrInfo::isX86_64ExtendedReg(MO.getReg()))
- REX |= 1 << 0; // set REX.B
- }
- break;
- case X86II::MRMSrcMem: {
- if (MI.getOperand(0).isReg() &&
- X86InstrInfo::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
- REX |= 1 << 2; // set REX.R
- unsigned Bit = 0;
- i = isTwoAddr ? 2 : 1;
- for (; i != NumOps; ++i) {
- const MCOperand &MO = MI.getOperand(i);
- if (MO.isReg()) {
- if (X86InstrInfo::isX86_64ExtendedReg(MO.getReg()))
- REX |= 1 << Bit; // set REX.B (Bit=0) and REX.X (Bit=1)
- Bit++;
- }
- }
- break;
- }
- case X86II::MRM0m: case X86II::MRM1m:
- case X86II::MRM2m: case X86II::MRM3m:
- case X86II::MRM4m: case X86II::MRM5m:
- case X86II::MRM6m: case X86II::MRM7m:
- case X86II::MRMDestMem: {
- unsigned e = (isTwoAddr ? X86::AddrNumOperands+1 : X86::AddrNumOperands);
- i = isTwoAddr ? 1 : 0;
- if (NumOps > e && MI.getOperand(e).isReg() &&
- X86InstrInfo::isX86_64ExtendedReg(MI.getOperand(e).getReg()))
- REX |= 1 << 2; // set REX.R
- unsigned Bit = 0;
- for (; i != e; ++i) {
- const MCOperand &MO = MI.getOperand(i);
- if (MO.isReg()) {
- if (X86InstrInfo::isX86_64ExtendedReg(MO.getReg()))
- REX |= 1 << Bit; // REX.B (Bit=0) and REX.X (Bit=1)
- Bit++;
- }
- }
- break;
- }
- default:
- if (MI.getOperand(0).isReg() &&
- X86InstrInfo::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
- REX |= 1 << 0; // set REX.B
- i = isTwoAddr ? 2 : 1;
- for (unsigned e = NumOps; i != e; ++i) {
- const MCOperand &MO = MI.getOperand(i);
- if (MO.isReg() && X86InstrInfo::isX86_64ExtendedReg(MO.getReg()))
- REX |= 1 << 2; // set REX.R
- }
- break;
- }
- return REX;
-}
-
-/// EmitSegmentOverridePrefix - Emit segment override opcode prefix as needed
-void X86MCCodeEmitter::EmitSegmentOverridePrefix(uint64_t TSFlags,
- unsigned &CurByte, int MemOperand,
- const MCInst &MI,
- raw_ostream &OS) const {
- switch (TSFlags & X86II::SegOvrMask) {
- default: assert(0 && "Invalid segment!");
- case 0:
- // No segment override, check for explicit one on memory operand.
- if (MemOperand != -1) { // If the instruction has a memory operand.
- switch (MI.getOperand(MemOperand+X86::AddrSegmentReg).getReg()) {
- default: assert(0 && "Unknown segment register!");
- case 0: break;
- case X86::CS: EmitByte(0x2E, CurByte, OS); break;
- case X86::SS: EmitByte(0x36, CurByte, OS); break;
- case X86::DS: EmitByte(0x3E, CurByte, OS); break;
- case X86::ES: EmitByte(0x26, CurByte, OS); break;
- case X86::FS: EmitByte(0x64, CurByte, OS); break;
- case X86::GS: EmitByte(0x65, CurByte, OS); break;
- }
- }
- break;
- case X86II::FS:
- EmitByte(0x64, CurByte, OS);
- break;
- case X86II::GS:
- EmitByte(0x65, CurByte, OS);
- break;
- }
-}
-
-/// EmitOpcodePrefix - Emit all instruction prefixes prior to the opcode.
-///
-/// MemOperand is the operand # of the start of a memory operand if present. If
-/// Not present, it is -1.
-void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
- int MemOperand, const MCInst &MI,
- const MCInstrDesc &Desc,
- raw_ostream &OS) const {
-
- // Emit the lock opcode prefix as needed.
- if (TSFlags & X86II::LOCK)
- EmitByte(0xF0, CurByte, OS);
-
- // Emit segment override opcode prefix as needed.
- EmitSegmentOverridePrefix(TSFlags, CurByte, MemOperand, MI, OS);
-
- // Emit the repeat opcode prefix as needed.
- if ((TSFlags & X86II::Op0Mask) == X86II::REP)
- EmitByte(0xF3, CurByte, OS);
-
- // Emit the address size opcode prefix as needed.
- if ((TSFlags & X86II::AdSize) ||
- (MemOperand != -1 && is64BitMode() && Is32BitMemOperand(MI, MemOperand)))
- EmitByte(0x67, CurByte, OS);
-
- // Emit the operand size opcode prefix as needed.
- if (TSFlags & X86II::OpSize)
- EmitByte(0x66, CurByte, OS);
-
- bool Need0FPrefix = false;
- switch (TSFlags & X86II::Op0Mask) {
- default: assert(0 && "Invalid prefix!");
- case 0: break; // No prefix!
- case X86II::REP: break; // already handled.
- case X86II::TB: // Two-byte opcode prefix
- case X86II::T8: // 0F 38
- case X86II::TA: // 0F 3A
- case X86II::A6: // 0F A6
- case X86II::A7: // 0F A7
- Need0FPrefix = true;
- break;
- case X86II::TF: // F2 0F 38
- EmitByte(0xF2, CurByte, OS);
- Need0FPrefix = true;
- break;
- case X86II::XS: // F3 0F
- EmitByte(0xF3, CurByte, OS);
- Need0FPrefix = true;
- break;
- case X86II::XD: // F2 0F
- EmitByte(0xF2, CurByte, OS);
- Need0FPrefix = true;
- break;
- case X86II::D8: EmitByte(0xD8, CurByte, OS); break;
- case X86II::D9: EmitByte(0xD9, CurByte, OS); break;
- case X86II::DA: EmitByte(0xDA, CurByte, OS); break;
- case X86II::DB: EmitByte(0xDB, CurByte, OS); break;
- case X86II::DC: EmitByte(0xDC, CurByte, OS); break;
- case X86II::DD: EmitByte(0xDD, CurByte, OS); break;
- case X86II::DE: EmitByte(0xDE, CurByte, OS); break;
- case X86II::DF: EmitByte(0xDF, CurByte, OS); break;
- }
-
- // Handle REX prefix.
- // FIXME: Can this come before F2 etc to simplify emission?
- if (is64BitMode()) {
- if (unsigned REX = DetermineREXPrefix(MI, TSFlags, Desc))
- EmitByte(0x40 | REX, CurByte, OS);
- }
-
- // 0x0F escape code must be emitted just before the opcode.
- if (Need0FPrefix)
- EmitByte(0x0F, CurByte, OS);
-
- // FIXME: Pull this up into previous switch if REX can be moved earlier.
- switch (TSFlags & X86II::Op0Mask) {
- case X86II::TF: // F2 0F 38
- case X86II::T8: // 0F 38
- EmitByte(0x38, CurByte, OS);
- break;
- case X86II::TA: // 0F 3A
- EmitByte(0x3A, CurByte, OS);
- break;
- case X86II::A6: // 0F A6
- EmitByte(0xA6, CurByte, OS);
- break;
- case X86II::A7: // 0F A7
- EmitByte(0xA7, CurByte, OS);
- break;
- }
-}
-
-void X86MCCodeEmitter::
-EncodeInstruction(const MCInst &MI, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const {
- unsigned Opcode = MI.getOpcode();
- const MCInstrDesc &Desc = MCII.get(Opcode);
- uint64_t TSFlags = Desc.TSFlags;
-
- // Pseudo instructions don't get encoded.
- if ((TSFlags & X86II::FormMask) == X86II::Pseudo)
- return;
-
- // If this is a two-address instruction, skip one of the register operands.
- // FIXME: This should be handled during MCInst lowering.
- unsigned NumOps = Desc.getNumOperands();
- unsigned CurOp = 0;
- if (NumOps > 1 && Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1)
- ++CurOp;
- else if (NumOps > 2 && Desc.getOperandConstraint(NumOps-1, MCOI::TIED_TO)== 0)
- // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32
- --NumOps;
-
- // Keep track of the current byte being emitted.
- unsigned CurByte = 0;
-
- // Is this instruction encoded using the AVX VEX prefix?
- bool HasVEXPrefix = false;
-
- // It uses the VEX.VVVV field?
- bool HasVEX_4V = false;
-
- if ((TSFlags >> X86II::VEXShift) & X86II::VEX)
- HasVEXPrefix = true;
- if ((TSFlags >> X86II::VEXShift) & X86II::VEX_4V)
- HasVEX_4V = true;
-
-
- // Determine where the memory operand starts, if present.
- int MemoryOperand = X86II::getMemoryOperandNo(TSFlags);
- if (MemoryOperand != -1) MemoryOperand += CurOp;
-
- if (!HasVEXPrefix)
- EmitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS);
- else
- EmitVEXOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS);
-
-
- unsigned char BaseOpcode = X86II::getBaseOpcodeFor(TSFlags);
-
- if ((TSFlags >> X86II::VEXShift) & X86II::Has3DNow0F0FOpcode)
- BaseOpcode = 0x0F; // Weird 3DNow! encoding.
-
- unsigned SrcRegNum = 0;
- switch (TSFlags & X86II::FormMask) {
- case X86II::MRMInitReg:
- assert(0 && "FIXME: Remove this form when the JIT moves to MCCodeEmitter!");
- default: errs() << "FORM: " << (TSFlags & X86II::FormMask) << "\n";
- assert(0 && "Unknown FormMask value in X86MCCodeEmitter!");
- case X86II::Pseudo:
- assert(0 && "Pseudo instruction shouldn't be emitted");
- case X86II::RawFrm:
- EmitByte(BaseOpcode, CurByte, OS);
- break;
-
- case X86II::RawFrmImm8:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitImmediate(MI.getOperand(CurOp++),
- X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags),
- CurByte, OS, Fixups);
- EmitImmediate(MI.getOperand(CurOp++), 1, FK_Data_1, CurByte, OS, Fixups);
- break;
- case X86II::RawFrmImm16:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitImmediate(MI.getOperand(CurOp++),
- X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags),
- CurByte, OS, Fixups);
- EmitImmediate(MI.getOperand(CurOp++), 2, FK_Data_2, CurByte, OS, Fixups);
- break;
-
- case X86II::AddRegFrm:
- EmitByte(BaseOpcode + GetX86RegNum(MI.getOperand(CurOp++)), CurByte, OS);
- break;
-
- case X86II::MRMDestReg:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitRegModRMByte(MI.getOperand(CurOp),
- GetX86RegNum(MI.getOperand(CurOp+1)), CurByte, OS);
- CurOp += 2;
- break;
-
- case X86II::MRMDestMem:
- EmitByte(BaseOpcode, CurByte, OS);
- SrcRegNum = CurOp + X86::AddrNumOperands;
-
- if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV)
- SrcRegNum++;
-
- EmitMemModRMByte(MI, CurOp,
- GetX86RegNum(MI.getOperand(SrcRegNum)),
- TSFlags, CurByte, OS, Fixups);
- CurOp = SrcRegNum + 1;
- break;
-
- case X86II::MRMSrcReg:
- EmitByte(BaseOpcode, CurByte, OS);
- SrcRegNum = CurOp + 1;
-
- if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV)
- SrcRegNum++;
-
- EmitRegModRMByte(MI.getOperand(SrcRegNum),
- GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS);
- CurOp = SrcRegNum + 1;
- break;
-
- case X86II::MRMSrcMem: {
- int AddrOperands = X86::AddrNumOperands;
- unsigned FirstMemOp = CurOp+1;
- if (HasVEX_4V) {
- ++AddrOperands;
- ++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV).
- }
-
- EmitByte(BaseOpcode, CurByte, OS);
-
- EmitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)),
- TSFlags, CurByte, OS, Fixups);
- CurOp += AddrOperands + 1;
- break;
- }
-
- case X86II::MRM0r: case X86II::MRM1r:
- case X86II::MRM2r: case X86II::MRM3r:
- case X86II::MRM4r: case X86II::MRM5r:
- case X86II::MRM6r: case X86II::MRM7r:
- if (HasVEX_4V) // Skip the register dst (which is encoded in VEX_VVVV).
- CurOp++;
- EmitByte(BaseOpcode, CurByte, OS);
- EmitRegModRMByte(MI.getOperand(CurOp++),
- (TSFlags & X86II::FormMask)-X86II::MRM0r,
- CurByte, OS);
- break;
- case X86II::MRM0m: case X86II::MRM1m:
- case X86II::MRM2m: case X86II::MRM3m:
- case X86II::MRM4m: case X86II::MRM5m:
- case X86II::MRM6m: case X86II::MRM7m:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitMemModRMByte(MI, CurOp, (TSFlags & X86II::FormMask)-X86II::MRM0m,
- TSFlags, CurByte, OS, Fixups);
- CurOp += X86::AddrNumOperands;
- break;
- case X86II::MRM_C1:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xC1, CurByte, OS);
- break;
- case X86II::MRM_C2:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xC2, CurByte, OS);
- break;
- case X86II::MRM_C3:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xC3, CurByte, OS);
- break;
- case X86II::MRM_C4:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xC4, CurByte, OS);
- break;
- case X86II::MRM_C8:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xC8, CurByte, OS);
- break;
- case X86II::MRM_C9:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xC9, CurByte, OS);
- break;
- case X86II::MRM_E8:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xE8, CurByte, OS);
- break;
- case X86II::MRM_F0:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xF0, CurByte, OS);
- break;
- case X86II::MRM_F8:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xF8, CurByte, OS);
- break;
- case X86II::MRM_F9:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xF9, CurByte, OS);
- break;
- case X86II::MRM_D0:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xD0, CurByte, OS);
- break;
- case X86II::MRM_D1:
- EmitByte(BaseOpcode, CurByte, OS);
- EmitByte(0xD1, CurByte, OS);
- break;
- }
-
- // If there is a remaining operand, it must be a trailing immediate. Emit it
- // according to the right size for the instruction.
- if (CurOp != NumOps) {
- // The last source register of a 4 operand instruction in AVX is encoded
- // in bits[7:4] of a immediate byte, and bits[3:0] are ignored.
- if ((TSFlags >> X86II::VEXShift) & X86II::VEX_I8IMM) {
- const MCOperand &MO = MI.getOperand(CurOp++);
- bool IsExtReg =
- X86InstrInfo::isX86_64ExtendedReg(MO.getReg());
- unsigned RegNum = (IsExtReg ? (1 << 7) : 0);
- RegNum |= GetX86RegNum(MO) << 4;
- EmitImmediate(MCOperand::CreateImm(RegNum), 1, FK_Data_1, CurByte, OS,
- Fixups);
- } else {
- unsigned FixupKind;
- // FIXME: Is there a better way to know that we need a signed relocation?
- if (MI.getOpcode() == X86::ADD64ri32 ||
- MI.getOpcode() == X86::MOV64ri32 ||
- MI.getOpcode() == X86::MOV64mi32 ||
- MI.getOpcode() == X86::PUSH64i32)
- FixupKind = X86::reloc_signed_4byte;
- else
- FixupKind = getImmFixupKind(TSFlags);
- EmitImmediate(MI.getOperand(CurOp++),
- X86II::getSizeOfImm(TSFlags), MCFixupKind(FixupKind),
- CurByte, OS, Fixups);
- }
- }
-
- if ((TSFlags >> X86II::VEXShift) & X86II::Has3DNow0F0FOpcode)
- EmitByte(X86II::getBaseOpcodeFor(TSFlags), CurByte, OS);
-
-
-#ifndef NDEBUG
- // FIXME: Verify.
- if (/*!Desc.isVariadic() &&*/ CurOp != NumOps) {
- errs() << "Cannot encode all operands of: ";
- MI.dump();
- errs() << '\n';
- abort();
- }
-#endif
-}
diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp
index e385335..50bc14d 100644
--- a/lib/Target/X86/X86MCInstLower.cpp
+++ b/lib/Target/X86/X86MCInstLower.cpp
@@ -372,15 +372,10 @@ ReSimplify:
case X86::FsFLD0SD: LowerUnaryToTwoAddr(OutMI, X86::PXORrr); break;
case X86::VFsFLD0SS: LowerUnaryToTwoAddr(OutMI, X86::VPXORrr); break;
case X86::VFsFLD0SD: LowerUnaryToTwoAddr(OutMI, X86::VPXORrr); break;
- case X86::V_SET0PS: LowerUnaryToTwoAddr(OutMI, X86::XORPSrr); break;
- case X86::V_SET0PD: LowerUnaryToTwoAddr(OutMI, X86::XORPDrr); break;
- case X86::V_SET0PI: LowerUnaryToTwoAddr(OutMI, X86::PXORrr); break;
case X86::V_SETALLONES: LowerUnaryToTwoAddr(OutMI, X86::PCMPEQDrr); break;
- case X86::AVX_SET0PS: LowerUnaryToTwoAddr(OutMI, X86::VXORPSrr); break;
case X86::AVX_SET0PSY: LowerUnaryToTwoAddr(OutMI, X86::VXORPSYrr); break;
- case X86::AVX_SET0PD: LowerUnaryToTwoAddr(OutMI, X86::VXORPDrr); break;
case X86::AVX_SET0PDY: LowerUnaryToTwoAddr(OutMI, X86::VXORPDYrr); break;
- case X86::AVX_SET0PI: LowerUnaryToTwoAddr(OutMI, X86::VPXORrr); break;
+ case X86::AVX_SETALLONES: LowerUnaryToTwoAddr(OutMI, X86::VPCMPEQDrr); break;
case X86::MOV16r0:
LowerSubReg32_Op0(OutMI, X86::MOV32r0); // MOV16r0 -> MOV32r0
@@ -468,6 +463,18 @@ ReSimplify:
case X86::JLE_4: OutMI.setOpcode(X86::JLE_1); break;
case X86::JG_4: OutMI.setOpcode(X86::JG_1); break;
+ // Atomic load and store require a separate pseudo-inst because Acquire
+ // implies mayStore and Release implies mayLoad; fix these to regular MOV
+ // instructions here
+ case X86::ACQUIRE_MOV8rm: OutMI.setOpcode(X86::MOV8rm); goto ReSimplify;
+ case X86::ACQUIRE_MOV16rm: OutMI.setOpcode(X86::MOV16rm); goto ReSimplify;
+ case X86::ACQUIRE_MOV32rm: OutMI.setOpcode(X86::MOV32rm); goto ReSimplify;
+ case X86::ACQUIRE_MOV64rm: OutMI.setOpcode(X86::MOV64rm); goto ReSimplify;
+ case X86::RELEASE_MOV8mr: OutMI.setOpcode(X86::MOV8mr); goto ReSimplify;
+ case X86::RELEASE_MOV16mr: OutMI.setOpcode(X86::MOV16mr); goto ReSimplify;
+ case X86::RELEASE_MOV32mr: OutMI.setOpcode(X86::MOV32mr); goto ReSimplify;
+ case X86::RELEASE_MOV64mr: OutMI.setOpcode(X86::MOV64mr); goto ReSimplify;
+
// We don't currently select the correct instruction form for instructions
// which have a short %eax, etc. form. Handle this by custom lowering, for
// now.
@@ -585,6 +592,8 @@ static void LowerTlsAddr(MCStreamer &OutStreamer,
}
void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
+ OutStreamer.EmitCodeRegion();
+
X86MCInstLower MCInstLowering(Mang, *MF, *this);
switch (MI->getOpcode()) {
case TargetOpcode::DBG_VALUE:
@@ -601,7 +610,7 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
if (OutStreamer.hasRawTextSupport())
OutStreamer.EmitRawText(StringRef("\t#MEMBARRIER"));
return;
-
+
case X86::EH_RETURN:
case X86::EH_RETURN64: {
diff --git a/lib/Target/X86/X86MachObjectWriter.cpp b/lib/Target/X86/X86MachObjectWriter.cpp
deleted file mode 100644
index 3711038..0000000
--- a/lib/Target/X86/X86MachObjectWriter.cpp
+++ /dev/null
@@ -1,554 +0,0 @@
-//===-- X86MachObjectWriter.cpp - X86 Mach-O Writer -----------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "X86.h"
-#include "X86FixupKinds.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCMachObjectWriter.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Object/MachOFormat.h"
-
-using namespace llvm;
-using namespace llvm::object;
-
-namespace {
-class X86MachObjectWriter : public MCMachObjectTargetWriter {
- void RecordScatteredRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- unsigned Log2Size,
- uint64_t &FixedValue);
- void RecordTLVPRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- uint64_t &FixedValue);
-
- void RecordX86Relocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- uint64_t &FixedValue);
- void RecordX86_64Relocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- uint64_t &FixedValue);
-public:
- X86MachObjectWriter(bool Is64Bit, uint32_t CPUType,
- uint32_t CPUSubtype)
- : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
- /*UseAggressiveSymbolFolding=*/Is64Bit) {}
-
- void RecordRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCFragment *Fragment, const MCFixup &Fixup,
- MCValue Target, uint64_t &FixedValue) {
- if (Writer->is64Bit())
- RecordX86_64Relocation(Writer, Asm, Layout, Fragment, Fixup, Target,
- FixedValue);
- else
- RecordX86Relocation(Writer, Asm, Layout, Fragment, Fixup, Target,
- FixedValue);
- }
-};
-}
-
-static bool isFixupKindRIPRel(unsigned Kind) {
- return Kind == X86::reloc_riprel_4byte ||
- Kind == X86::reloc_riprel_4byte_movq_load;
-}
-
-static unsigned getFixupKindLog2Size(unsigned Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("invalid fixup kind!");
- case FK_PCRel_1:
- case FK_Data_1: return 0;
- case FK_PCRel_2:
- case FK_Data_2: return 1;
- case FK_PCRel_4:
- // FIXME: Remove these!!!
- case X86::reloc_riprel_4byte:
- case X86::reloc_riprel_4byte_movq_load:
- case X86::reloc_signed_4byte:
- case FK_Data_4: return 2;
- case FK_Data_8: return 3;
- }
-}
-
-void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- uint64_t &FixedValue) {
- unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
- unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind());
- unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
-
- // See <reloc.h>.
- uint32_t FixupOffset =
- Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
- uint32_t FixupAddress =
- Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
- int64_t Value = 0;
- unsigned Index = 0;
- unsigned IsExtern = 0;
- unsigned Type = 0;
-
- Value = Target.getConstant();
-
- if (IsPCRel) {
- // Compensate for the relocation offset, Darwin x86_64 relocations only have
- // the addend and appear to have attempted to define it to be the actual
- // expression addend without the PCrel bias. However, instructions with data
- // following the relocation are not accommodated for (see comment below
- // regarding SIGNED{1,2,4}), so it isn't exactly that either.
- Value += 1LL << Log2Size;
- }
-
- if (Target.isAbsolute()) { // constant
- // SymbolNum of 0 indicates the absolute section.
- Type = macho::RIT_X86_64_Unsigned;
- Index = 0;
-
- // FIXME: I believe this is broken, I don't think the linker can understand
- // it. I think it would require a local relocation, but I'm not sure if that
- // would work either. The official way to get an absolute PCrel relocation
- // is to use an absolute symbol (which we don't support yet).
- if (IsPCRel) {
- IsExtern = 1;
- Type = macho::RIT_X86_64_Branch;
- }
- } else if (Target.getSymB()) { // A - B + constant
- const MCSymbol *A = &Target.getSymA()->getSymbol();
- MCSymbolData &A_SD = Asm.getSymbolData(*A);
- const MCSymbolData *A_Base = Asm.getAtom(&A_SD);
-
- const MCSymbol *B = &Target.getSymB()->getSymbol();
- MCSymbolData &B_SD = Asm.getSymbolData(*B);
- const MCSymbolData *B_Base = Asm.getAtom(&B_SD);
-
- // Neither symbol can be modified.
- if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
- Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
- report_fatal_error("unsupported relocation of modified symbol");
-
- // We don't support PCrel relocations of differences. Darwin 'as' doesn't
- // implement most of these correctly.
- if (IsPCRel)
- report_fatal_error("unsupported pc-relative relocation of difference");
-
- // The support for the situation where one or both of the symbols would
- // require a local relocation is handled just like if the symbols were
- // external. This is certainly used in the case of debug sections where the
- // section has only temporary symbols and thus the symbols don't have base
- // symbols. This is encoded using the section ordinal and non-extern
- // relocation entries.
-
- // Darwin 'as' doesn't emit correct relocations for this (it ends up with a
- // single SIGNED relocation); reject it for now. Except the case where both
- // symbols don't have a base, equal but both NULL.
- if (A_Base == B_Base && A_Base)
- report_fatal_error("unsupported relocation with identical base");
-
- Value += Writer->getSymbolAddress(&A_SD, Layout) -
- (A_Base == NULL ? 0 : Writer->getSymbolAddress(A_Base, Layout));
- Value -= Writer->getSymbolAddress(&B_SD, Layout) -
- (B_Base == NULL ? 0 : Writer->getSymbolAddress(B_Base, Layout));
-
- if (A_Base) {
- Index = A_Base->getIndex();
- IsExtern = 1;
- }
- else {
- Index = A_SD.getFragment()->getParent()->getOrdinal() + 1;
- IsExtern = 0;
- }
- Type = macho::RIT_X86_64_Unsigned;
-
- macho::RelocationEntry MRE;
- MRE.Word0 = FixupOffset;
- MRE.Word1 = ((Index << 0) |
- (IsPCRel << 24) |
- (Log2Size << 25) |
- (IsExtern << 27) |
- (Type << 28));
- Writer->addRelocation(Fragment->getParent(), MRE);
-
- if (B_Base) {
- Index = B_Base->getIndex();
- IsExtern = 1;
- }
- else {
- Index = B_SD.getFragment()->getParent()->getOrdinal() + 1;
- IsExtern = 0;
- }
- Type = macho::RIT_X86_64_Subtractor;
- } else {
- const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
- MCSymbolData &SD = Asm.getSymbolData(*Symbol);
- const MCSymbolData *Base = Asm.getAtom(&SD);
-
- // Relocations inside debug sections always use local relocations when
- // possible. This seems to be done because the debugger doesn't fully
- // understand x86_64 relocation entries, and expects to find values that
- // have already been fixed up.
- if (Symbol->isInSection()) {
- const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(
- Fragment->getParent()->getSection());
- if (Section.hasAttribute(MCSectionMachO::S_ATTR_DEBUG))
- Base = 0;
- }
-
- // x86_64 almost always uses external relocations, except when there is no
- // symbol to use as a base address (a local symbol with no preceding
- // non-local symbol).
- if (Base) {
- Index = Base->getIndex();
- IsExtern = 1;
-
- // Add the local offset, if needed.
- if (Base != &SD)
- Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base);
- } else if (Symbol->isInSection() && !Symbol->isVariable()) {
- // The index is the section ordinal (1-based).
- Index = SD.getFragment()->getParent()->getOrdinal() + 1;
- IsExtern = 0;
- Value += Writer->getSymbolAddress(&SD, Layout);
-
- if (IsPCRel)
- Value -= FixupAddress + (1 << Log2Size);
- } else if (Symbol->isVariable()) {
- const MCExpr *Value = Symbol->getVariableValue();
- int64_t Res;
- bool isAbs = Value->EvaluateAsAbsolute(Res, Layout,
- Writer->getSectionAddressMap());
- if (isAbs) {
- FixedValue = Res;
- return;
- } else {
- report_fatal_error("unsupported relocation of variable '" +
- Symbol->getName() + "'");
- }
- } else {
- report_fatal_error("unsupported relocation of undefined symbol '" +
- Symbol->getName() + "'");
- }
-
- MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
- if (IsPCRel) {
- if (IsRIPRel) {
- if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
- // x86_64 distinguishes movq foo@GOTPCREL so that the linker can
- // rewrite the movq to an leaq at link time if the symbol ends up in
- // the same linkage unit.
- if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load)
- Type = macho::RIT_X86_64_GOTLoad;
- else
- Type = macho::RIT_X86_64_GOT;
- } else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
- Type = macho::RIT_X86_64_TLV;
- } else if (Modifier != MCSymbolRefExpr::VK_None) {
- report_fatal_error("unsupported symbol modifier in relocation");
- } else {
- Type = macho::RIT_X86_64_Signed;
-
- // The Darwin x86_64 relocation format has a problem where it cannot
- // encode an address (L<foo> + <constant>) which is outside the atom
- // containing L<foo>. Generally, this shouldn't occur but it does
- // happen when we have a RIPrel instruction with data following the
- // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel
- // adjustment Darwin x86_64 uses, the offset is still negative and the
- // linker has no way to recognize this.
- //
- // To work around this, Darwin uses several special relocation types
- // to indicate the offsets. However, the specification or
- // implementation of these seems to also be incomplete; they should
- // adjust the addend as well based on the actual encoded instruction
- // (the additional bias), but instead appear to just look at the final
- // offset.
- switch (-(Target.getConstant() + (1LL << Log2Size))) {
- case 1: Type = macho::RIT_X86_64_Signed1; break;
- case 2: Type = macho::RIT_X86_64_Signed2; break;
- case 4: Type = macho::RIT_X86_64_Signed4; break;
- }
- }
- } else {
- if (Modifier != MCSymbolRefExpr::VK_None)
- report_fatal_error("unsupported symbol modifier in branch "
- "relocation");
-
- Type = macho::RIT_X86_64_Branch;
- }
- } else {
- if (Modifier == MCSymbolRefExpr::VK_GOT) {
- Type = macho::RIT_X86_64_GOT;
- } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
- // GOTPCREL is allowed as a modifier on non-PCrel instructions, in which
- // case all we do is set the PCrel bit in the relocation entry; this is
- // used with exception handling, for example. The source is required to
- // include any necessary offset directly.
- Type = macho::RIT_X86_64_GOT;
- IsPCRel = 1;
- } else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
- report_fatal_error("TLVP symbol modifier should have been rip-rel");
- } else if (Modifier != MCSymbolRefExpr::VK_None)
- report_fatal_error("unsupported symbol modifier in relocation");
- else
- Type = macho::RIT_X86_64_Unsigned;
- }
- }
-
- // x86_64 always writes custom values into the fixups.
- FixedValue = Value;
-
- // struct relocation_info (8 bytes)
- macho::RelocationEntry MRE;
- MRE.Word0 = FixupOffset;
- MRE.Word1 = ((Index << 0) |
- (IsPCRel << 24) |
- (Log2Size << 25) |
- (IsExtern << 27) |
- (Type << 28));
- Writer->addRelocation(Fragment->getParent(), MRE);
-}
-
-void X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- unsigned Log2Size,
- uint64_t &FixedValue) {
- uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
- unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
- unsigned Type = macho::RIT_Vanilla;
-
- // See <reloc.h>.
- const MCSymbol *A = &Target.getSymA()->getSymbol();
- MCSymbolData *A_SD = &Asm.getSymbolData(*A);
-
- if (!A_SD->getFragment())
- report_fatal_error("symbol '" + A->getName() +
- "' can not be undefined in a subtraction expression");
-
- uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
- uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
- FixedValue += SecAddr;
- uint32_t Value2 = 0;
-
- if (const MCSymbolRefExpr *B = Target.getSymB()) {
- MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
-
- if (!B_SD->getFragment())
- report_fatal_error("symbol '" + B->getSymbol().getName() +
- "' can not be undefined in a subtraction expression");
-
- // Select the appropriate difference relocation type.
- //
- // Note that there is no longer any semantic difference between these two
- // relocation types from the linkers point of view, this is done solely for
- // pedantic compatibility with 'as'.
- Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference :
- (unsigned)macho::RIT_Generic_LocalDifference;
- Value2 = Writer->getSymbolAddress(B_SD, Layout);
- FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
- }
-
- // Relocations are written out in reverse order, so the PAIR comes first.
- if (Type == macho::RIT_Difference ||
- Type == macho::RIT_Generic_LocalDifference) {
- macho::RelocationEntry MRE;
- MRE.Word0 = ((0 << 0) |
- (macho::RIT_Pair << 24) |
- (Log2Size << 28) |
- (IsPCRel << 30) |
- macho::RF_Scattered);
- MRE.Word1 = Value2;
- Writer->addRelocation(Fragment->getParent(), MRE);
- }
-
- macho::RelocationEntry MRE;
- MRE.Word0 = ((FixupOffset << 0) |
- (Type << 24) |
- (Log2Size << 28) |
- (IsPCRel << 30) |
- macho::RF_Scattered);
- MRE.Word1 = Value;
- Writer->addRelocation(Fragment->getParent(), MRE);
-}
-
-void X86MachObjectWriter::RecordTLVPRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- uint64_t &FixedValue) {
- assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP &&
- !is64Bit() &&
- "Should only be called with a 32-bit TLVP relocation!");
-
- unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
- uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
- unsigned IsPCRel = 0;
-
- // Get the symbol data.
- MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol());
- unsigned Index = SD_A->getIndex();
-
- // We're only going to have a second symbol in pic mode and it'll be a
- // subtraction from the picbase. For 32-bit pic the addend is the difference
- // between the picbase and the next address. For 32-bit static the addend is
- // zero.
- if (Target.getSymB()) {
- // If this is a subtraction then we're pcrel.
- uint32_t FixupAddress =
- Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
- MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol());
- IsPCRel = 1;
- FixedValue = (FixupAddress - Writer->getSymbolAddress(SD_B, Layout) +
- Target.getConstant());
- FixedValue += 1ULL << Log2Size;
- } else {
- FixedValue = 0;
- }
-
- // struct relocation_info (8 bytes)
- macho::RelocationEntry MRE;
- MRE.Word0 = Value;
- MRE.Word1 = ((Index << 0) |
- (IsPCRel << 24) |
- (Log2Size << 25) |
- (1 << 27) | // Extern
- (macho::RIT_Generic_TLV << 28)); // Type
- Writer->addRelocation(Fragment->getParent(), MRE);
-}
-
-void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- uint64_t &FixedValue) {
- unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
- unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
-
- // If this is a 32-bit TLVP reloc it's handled a bit differently.
- if (Target.getSymA() &&
- Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
- RecordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
- FixedValue);
- return;
- }
-
- // If this is a difference or a defined symbol plus an offset, then we need a
- // scattered relocation entry. Differences always require scattered
- // relocations.
- if (Target.getSymB())
- return RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
- Target, Log2Size, FixedValue);
-
- // Get the symbol data, if any.
- MCSymbolData *SD = 0;
- if (Target.getSymA())
- SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
-
- // If this is an internal relocation with an offset, it also needs a scattered
- // relocation entry.
- uint32_t Offset = Target.getConstant();
- if (IsPCRel)
- Offset += 1 << Log2Size;
- if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD))
- return RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
- Target, Log2Size, FixedValue);
-
- // See <reloc.h>.
- uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
- unsigned Index = 0;
- unsigned IsExtern = 0;
- unsigned Type = 0;
-
- if (Target.isAbsolute()) { // constant
- // SymbolNum of 0 indicates the absolute section.
- //
- // FIXME: Currently, these are never generated (see code below). I cannot
- // find a case where they are actually emitted.
- Type = macho::RIT_Vanilla;
- } else {
- // Resolve constant variables.
- if (SD->getSymbol().isVariable()) {
- int64_t Res;
- if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
- Res, Layout, Writer->getSectionAddressMap())) {
- FixedValue = Res;
- return;
- }
- }
-
- // Check whether we need an external or internal relocation.
- if (Writer->doesSymbolRequireExternRelocation(SD)) {
- IsExtern = 1;
- Index = SD->getIndex();
- // For external relocations, make sure to offset the fixup value to
- // compensate for the addend of the symbol address, if it was
- // undefined. This occurs with weak definitions, for example.
- if (!SD->Symbol->isUndefined())
- FixedValue -= Layout.getSymbolOffset(SD);
- } else {
- // The index is the section ordinal (1-based).
- const MCSectionData &SymSD = Asm.getSectionData(
- SD->getSymbol().getSection());
- Index = SymSD.getOrdinal() + 1;
- FixedValue += Writer->getSectionAddress(&SymSD);
- }
- if (IsPCRel)
- FixedValue -= Writer->getSectionAddress(Fragment->getParent());
-
- Type = macho::RIT_Vanilla;
- }
-
- // struct relocation_info (8 bytes)
- macho::RelocationEntry MRE;
- MRE.Word0 = FixupOffset;
- MRE.Word1 = ((Index << 0) |
- (IsPCRel << 24) |
- (Log2Size << 25) |
- (IsExtern << 27) |
- (Type << 28));
- Writer->addRelocation(Fragment->getParent(), MRE);
-}
-
-MCObjectWriter *llvm::createX86MachObjectWriter(raw_ostream &OS,
- bool Is64Bit,
- uint32_t CPUType,
- uint32_t CPUSubtype) {
- return createMachObjectWriter(new X86MachObjectWriter(Is64Bit,
- CPUType,
- CPUSubtype),
- OS, /*IsLittleEndian=*/true);
-}
diff --git a/lib/Target/X86/X86MachineFunctionInfo.h b/lib/Target/X86/X86MachineFunctionInfo.h
index 06043ec..b0bb313 100644
--- a/lib/Target/X86/X86MachineFunctionInfo.h
+++ b/lib/Target/X86/X86MachineFunctionInfo.h
@@ -53,10 +53,6 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
/// relocation models.
unsigned GlobalBaseReg;
- /// ReserveFP - whether the function should reserve the frame pointer
- /// when allocating, even if there may not actually be a frame pointer used.
- bool ReserveFP;
-
/// VarArgsFrameIndex - FrameIndex for start of varargs area.
int VarArgsFrameIndex;
/// RegSaveFrameIndex - X86-64 vararg func register save area.
@@ -65,6 +61,9 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
unsigned VarArgsGPOffset;
/// VarArgsFPOffset - X86-64 vararg func fp reg offset.
unsigned VarArgsFPOffset;
+ /// ArgumentStackSize - The number of bytes on stack consumed by the arguments
+ /// being passed on the stack.
+ unsigned ArgumentStackSize;
public:
X86MachineFunctionInfo() : ForceFramePointer(false),
@@ -77,7 +76,8 @@ public:
VarArgsFrameIndex(0),
RegSaveFrameIndex(0),
VarArgsGPOffset(0),
- VarArgsFPOffset(0) {}
+ VarArgsFPOffset(0),
+ ArgumentStackSize(0) {}
explicit X86MachineFunctionInfo(MachineFunction &MF)
: ForceFramePointer(false),
@@ -87,11 +87,11 @@ public:
TailCallReturnAddrDelta(0),
SRetReturnReg(0),
GlobalBaseReg(0),
- ReserveFP(false),
VarArgsFrameIndex(0),
RegSaveFrameIndex(0),
VarArgsGPOffset(0),
- VarArgsFPOffset(0) {}
+ VarArgsFPOffset(0),
+ ArgumentStackSize(0) {}
bool getForceFramePointer() const { return ForceFramePointer;}
void setForceFramePointer(bool forceFP) { ForceFramePointer = forceFP; }
@@ -114,9 +114,6 @@ public:
unsigned getGlobalBaseReg() const { return GlobalBaseReg; }
void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; }
- bool getReserveFP() const { return ReserveFP; }
- void setReserveFP(bool reserveFP) { ReserveFP = reserveFP; }
-
int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
void setVarArgsFrameIndex(int Idx) { VarArgsFrameIndex = Idx; }
@@ -128,6 +125,9 @@ public:
unsigned getVarArgsFPOffset() const { return VarArgsFPOffset; }
void setVarArgsFPOffset(unsigned Offset) { VarArgsFPOffset = Offset; }
+
+ unsigned getArgumentStackSize() const { return ArgumentStackSize; }
+ void setArgumentStackSize(unsigned size) { ArgumentStackSize = size; }
};
} // End llvm namespace
diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp
index f2faf59..c1ac9f3 100644
--- a/lib/Target/X86/X86RegisterInfo.cpp
+++ b/lib/Target/X86/X86RegisterInfo.cpp
@@ -27,7 +27,6 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -53,7 +52,13 @@ ForceStackAlign("force-align-stack",
X86RegisterInfo::X86RegisterInfo(X86TargetMachine &tm,
const TargetInstrInfo &tii)
- : X86GenRegisterInfo(), TM(tm), TII(tii) {
+ : X86GenRegisterInfo(tm.getSubtarget<X86Subtarget>().is64Bit()
+ ? X86::RIP : X86::EIP,
+ X86_MC::getDwarfRegFlavour(tm.getTargetTriple(), false),
+ X86_MC::getDwarfRegFlavour(tm.getTargetTriple(), true)),
+ TM(tm), TII(tii) {
+ X86_MC::InitLLVM2SEHRegisterMapping(this);
+
// Cache some information.
const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
Is64Bit = Subtarget->is64Bit();
@@ -70,40 +75,6 @@ X86RegisterInfo::X86RegisterInfo(X86TargetMachine &tm,
}
}
-static unsigned getFlavour(const X86Subtarget *Subtarget, bool isEH) {
- if (!Subtarget->is64Bit()) {
- if (Subtarget->isTargetDarwin()) {
- if (isEH)
- return DWARFFlavour::X86_32_DarwinEH;
- else
- return DWARFFlavour::X86_32_Generic;
- } else if (Subtarget->isTargetCygMing()) {
- // Unsupported by now, just quick fallback
- return DWARFFlavour::X86_32_Generic;
- } else {
- return DWARFFlavour::X86_32_Generic;
- }
- }
- return DWARFFlavour::X86_64;
-}
-
-/// getDwarfRegNum - This function maps LLVM register identifiers to the DWARF
-/// specific numbering, used in debug info and exception tables.
-int X86RegisterInfo::getDwarfRegNum(unsigned RegNo, bool isEH) const {
- const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
- unsigned Flavour = getFlavour(Subtarget, isEH);
-
- return X86GenRegisterInfo::getDwarfRegNumFull(RegNo, Flavour);
-}
-
-/// getLLVMRegNum - This function maps DWARF register numbers to LLVM register.
-int X86RegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const {
- const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
- unsigned Flavour = getFlavour(Subtarget, isEH);
-
- return X86GenRegisterInfo::getLLVMRegNumFull(DwarfRegNo, Flavour);
-}
-
/// getCompactUnwindRegNum - This function maps the register to the number for
/// compact unwind encoding. Return -1 if the register isn't valid.
int X86RegisterInfo::getCompactUnwindRegNum(unsigned RegNum, bool isEH) const {
@@ -121,7 +92,7 @@ int X86RegisterInfo::getCompactUnwindRegNum(unsigned RegNum, bool isEH) const {
int
X86RegisterInfo::getSEHRegNum(unsigned i) const {
- int reg = getX86RegNum(i);
+ int reg = X86_MC::getX86RegNum(i);
switch (i) {
case X86::R8: case X86::R8D: case X86::R8W: case X86::R8B:
case X86::R9: case X86::R9D: case X86::R9W: case X86::R9B:
@@ -140,96 +111,16 @@ X86RegisterInfo::getSEHRegNum(unsigned i) const {
return reg;
}
-/// getX86RegNum - This function maps LLVM register identifiers to their X86
-/// specific numbering, which is used in various places encoding instructions.
-unsigned X86RegisterInfo::getX86RegNum(unsigned RegNo) {
- switch(RegNo) {
- case X86::RAX: case X86::EAX: case X86::AX: case X86::AL: return N86::EAX;
- case X86::RCX: case X86::ECX: case X86::CX: case X86::CL: return N86::ECX;
- case X86::RDX: case X86::EDX: case X86::DX: case X86::DL: return N86::EDX;
- case X86::RBX: case X86::EBX: case X86::BX: case X86::BL: return N86::EBX;
- case X86::RSP: case X86::ESP: case X86::SP: case X86::SPL: case X86::AH:
- return N86::ESP;
- case X86::RBP: case X86::EBP: case X86::BP: case X86::BPL: case X86::CH:
- return N86::EBP;
- case X86::RSI: case X86::ESI: case X86::SI: case X86::SIL: case X86::DH:
- return N86::ESI;
- case X86::RDI: case X86::EDI: case X86::DI: case X86::DIL: case X86::BH:
- return N86::EDI;
-
- case X86::R8: case X86::R8D: case X86::R8W: case X86::R8B:
- return N86::EAX;
- case X86::R9: case X86::R9D: case X86::R9W: case X86::R9B:
- return N86::ECX;
- case X86::R10: case X86::R10D: case X86::R10W: case X86::R10B:
- return N86::EDX;
- case X86::R11: case X86::R11D: case X86::R11W: case X86::R11B:
- return N86::EBX;
- case X86::R12: case X86::R12D: case X86::R12W: case X86::R12B:
- return N86::ESP;
- case X86::R13: case X86::R13D: case X86::R13W: case X86::R13B:
- return N86::EBP;
- case X86::R14: case X86::R14D: case X86::R14W: case X86::R14B:
- return N86::ESI;
- case X86::R15: case X86::R15D: case X86::R15W: case X86::R15B:
- return N86::EDI;
-
- case X86::ST0: case X86::ST1: case X86::ST2: case X86::ST3:
- case X86::ST4: case X86::ST5: case X86::ST6: case X86::ST7:
- return RegNo-X86::ST0;
-
- case X86::XMM0: case X86::XMM8:
- case X86::YMM0: case X86::YMM8: case X86::MM0:
- return 0;
- case X86::XMM1: case X86::XMM9:
- case X86::YMM1: case X86::YMM9: case X86::MM1:
- return 1;
- case X86::XMM2: case X86::XMM10:
- case X86::YMM2: case X86::YMM10: case X86::MM2:
- return 2;
- case X86::XMM3: case X86::XMM11:
- case X86::YMM3: case X86::YMM11: case X86::MM3:
- return 3;
- case X86::XMM4: case X86::XMM12:
- case X86::YMM4: case X86::YMM12: case X86::MM4:
- return 4;
- case X86::XMM5: case X86::XMM13:
- case X86::YMM5: case X86::YMM13: case X86::MM5:
- return 5;
- case X86::XMM6: case X86::XMM14:
- case X86::YMM6: case X86::YMM14: case X86::MM6:
- return 6;
- case X86::XMM7: case X86::XMM15:
- case X86::YMM7: case X86::YMM15: case X86::MM7:
- return 7;
-
- case X86::ES: return 0;
- case X86::CS: return 1;
- case X86::SS: return 2;
- case X86::DS: return 3;
- case X86::FS: return 4;
- case X86::GS: return 5;
-
- case X86::CR0: case X86::CR8 : case X86::DR0: return 0;
- case X86::CR1: case X86::CR9 : case X86::DR1: return 1;
- case X86::CR2: case X86::CR10: case X86::DR2: return 2;
- case X86::CR3: case X86::CR11: case X86::DR3: return 3;
- case X86::CR4: case X86::CR12: case X86::DR4: return 4;
- case X86::CR5: case X86::CR13: case X86::DR5: return 5;
- case X86::CR6: case X86::CR14: case X86::DR6: return 6;
- case X86::CR7: case X86::CR15: case X86::DR7: return 7;
-
- // Pseudo index registers are equivalent to a "none"
- // scaled index (See Intel Manual 2A, table 2-3)
- case X86::EIZ:
- case X86::RIZ:
- return 4;
-
- default:
- assert(isVirtualRegister(RegNo) && "Unknown physical register!");
- llvm_unreachable("Register allocator hasn't allocated reg correctly yet!");
- return 0;
- }
+const TargetRegisterClass *
+X86RegisterInfo::getSubClassWithSubReg(const TargetRegisterClass *RC,
+ unsigned Idx) const {
+ // The sub_8bit sub-register index is more constrained in 32-bit mode.
+ // It behaves just like the sub_8bit_hi index.
+ if (!Is64Bit && Idx == X86::sub_8bit)
+ Idx = X86::sub_8bit_hi;
+
+ // Forward to TableGen's default version.
+ return X86GenRegisterInfo::getSubClassWithSubReg(RC, Idx);
}
const TargetRegisterClass *
@@ -355,8 +246,19 @@ X86RegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A,
const TargetRegisterClass*
X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) const{
+ // Don't allow super-classes of GR8_NOREX. This class is only used after
+ // extrating sub_8bit_hi sub-registers. The H sub-registers cannot be copied
+ // to the full GR8 register class in 64-bit mode, so we cannot allow the
+ // reigster class inflation.
+ //
+ // The GR8_NOREX class is always used in a way that won't be constrained to a
+ // sub-class, so sub-classes like GR8_ABCD_L are allowed to expand to the
+ // full GR8 class.
+ if (RC == X86::GR8_NOREXRegisterClass)
+ return RC;
+
const TargetRegisterClass *Super = RC;
- TargetRegisterClass::sc_iterator I = RC->superclasses_begin();
+ TargetRegisterClass::sc_iterator I = RC->getSuperClasses();
do {
switch (Super->getID()) {
case X86::GR8RegClassID:
@@ -741,11 +643,6 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
}
}
-unsigned X86RegisterInfo::getRARegister() const {
- return Is64Bit ? X86::RIP // Should have dwarf #16.
- : X86::EIP; // Should have dwarf #8.
-}
-
unsigned X86RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
return TFI->hasFP(MF) ? FramePtr : StackPtr;
@@ -948,7 +845,7 @@ namespace {
for (unsigned i = 0, e = RI.getNumVirtRegs(); i != e; ++i) {
unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
if (RI.getRegClass(Reg)->getAlignment() > StackAlignment) {
- FuncInfo->setReserveFP(true);
+ FuncInfo->setForceFramePointer(true);
return true;
}
}
diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h
index a12eb12..7d39c68 100644
--- a/lib/Target/X86/X86RegisterInfo.h
+++ b/lib/Target/X86/X86RegisterInfo.h
@@ -24,22 +24,6 @@ namespace llvm {
class TargetInstrInfo;
class X86TargetMachine;
-/// N86 namespace - Native X86 register numbers
-///
-namespace N86 {
- enum {
- EAX = 0, ECX = 1, EDX = 2, EBX = 3, ESP = 4, EBP = 5, ESI = 6, EDI = 7
- };
-}
-
-/// DWARFFlavour - Flavour of dwarf regnumbers
-///
-namespace DWARFFlavour {
- enum {
- X86_64 = 0, X86_32_DarwinEH = 1, X86_32_Generic = 2
- };
-}
-
class X86RegisterInfo : public X86GenRegisterInfo {
public:
X86TargetMachine &TM;
@@ -73,11 +57,6 @@ public:
/// register identifier.
static unsigned getX86RegNum(unsigned RegNo);
- /// getDwarfRegNum - allows modification of X86GenRegisterInfo::getDwarfRegNum
- /// (created by TableGen) for target dependencies.
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- int getLLVMRegNum(unsigned RegNum, bool isEH) const;
-
// FIXME: This should be tablegen'd like getDwarfRegNum is
int getSEHRegNum(unsigned i) const;
@@ -95,6 +74,9 @@ public:
getMatchingSuperRegClass(const TargetRegisterClass *A,
const TargetRegisterClass *B, unsigned Idx) const;
+ virtual const TargetRegisterClass *
+ getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx) const;
+
const TargetRegisterClass*
getLargestLegalSuperClass(const TargetRegisterClass *RC) const;
@@ -136,7 +118,6 @@ public:
int SPAdj, RegScavenger *RS = NULL) const;
// Debug information queries.
- unsigned getRARegister() const;
unsigned getFrameRegister(const MachineFunction &MF) const;
unsigned getStackRegister() const { return StackPtr; }
// FIXME: Move to FrameInfok
diff --git a/lib/Target/X86/X86RegisterInfo.td b/lib/Target/X86/X86RegisterInfo.td
index 203722a..9a7db36 100644
--- a/lib/Target/X86/X86RegisterInfo.td
+++ b/lib/Target/X86/X86RegisterInfo.td
@@ -390,6 +390,13 @@ def GR64_NOREX : RegisterClass<"X86", [i64], 64,
(GR32_NOREX sub_32bit)];
}
+// GR32_NOAX - GR32 registers except EAX. Used by AddRegFrm of XCHG32 in 64-bit
+// mode to prevent encoding using the 0x90 NOP encoding. xchg %eax, %eax needs
+// to clear upper 32-bits of RAX so is not a NOP.
+def GR32_NOAX : RegisterClass<"X86", [i32], 32, (sub GR32, EAX)> {
+ let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi), (GR16 sub_16bit)];
+}
+
// GR32_NOSP - GR32 registers except ESP.
def GR32_NOSP : RegisterClass<"X86", [i32], 32, (sub GR32, ESP)> {
let SubRegClasses = [(GR8 sub_8bit, sub_8bit_hi), (GR16 sub_16bit)];
@@ -455,8 +462,8 @@ def VR128 : RegisterClass<"X86", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64],
let SubRegClasses = [(FR32 sub_ss), (FR64 sub_sd)];
}
-def VR256 : RegisterClass<"X86", [v32i8, v8i32, v4i64, v8f32, v4f64], 256,
- (sequence "YMM%u", 0, 15)> {
+def VR256 : RegisterClass<"X86", [v32i8, v16i16, v8i32, v4i64, v8f32, v4f64],
+ 256, (sequence "YMM%u", 0, 15)> {
let SubRegClasses = [(FR32 sub_ss), (FR64 sub_sd), (VR128 sub_xmm)];
}
diff --git a/lib/Target/X86/X86SelectionDAGInfo.cpp b/lib/Target/X86/X86SelectionDAGInfo.cpp
index 02754f9..6406bce 100644
--- a/lib/Target/X86/X86SelectionDAGInfo.cpp
+++ b/lib/Target/X86/X86SelectionDAGInfo.cpp
@@ -54,7 +54,7 @@ X86SelectionDAGInfo::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl,
if (const char *bzeroEntry = V &&
V->isNullValue() ? Subtarget->getBZeroEntry() : 0) {
EVT IntPtr = TLI.getPointerTy();
- const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
+ Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
Entry.Node = Dst;
diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp
index 5e6c659..7064dd0 100644
--- a/lib/Target/X86/X86Subtarget.cpp
+++ b/lib/Target/X86/X86Subtarget.cpp
@@ -16,9 +16,11 @@
#include "X86InstrInfo.h"
#include "llvm/GlobalValue.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Host.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/SmallVector.h"
#define GET_SUBTARGETINFO_TARGET_DESC
@@ -185,24 +187,53 @@ void X86Subtarget::AutoDetectSubtargetFeatures() {
X86_MC::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
- if ((EDX >> 15) & 1) HasCMov = true; ToggleFeature(X86::FeatureCMOV);
- if ((EDX >> 23) & 1) X86SSELevel = MMX; ToggleFeature(X86::FeatureMMX);
- if ((EDX >> 25) & 1) X86SSELevel = SSE1; ToggleFeature(X86::FeatureSSE1);
- if ((EDX >> 26) & 1) X86SSELevel = SSE2; ToggleFeature(X86::FeatureSSE2);
- if (ECX & 0x1) X86SSELevel = SSE3; ToggleFeature(X86::FeatureSSE3);
- if ((ECX >> 9) & 1) X86SSELevel = SSSE3; ToggleFeature(X86::FeatureSSSE3);
- if ((ECX >> 19) & 1) X86SSELevel = SSE41; ToggleFeature(X86::FeatureSSE41);
- if ((ECX >> 20) & 1) X86SSELevel = SSE42; ToggleFeature(X86::FeatureSSE42);
+ if ((EDX >> 15) & 1) { HasCMov = true; ToggleFeature(X86::FeatureCMOV); }
+ if ((EDX >> 23) & 1) { X86SSELevel = MMX; ToggleFeature(X86::FeatureMMX); }
+ if ((EDX >> 25) & 1) { X86SSELevel = SSE1; ToggleFeature(X86::FeatureSSE1); }
+ if ((EDX >> 26) & 1) { X86SSELevel = SSE2; ToggleFeature(X86::FeatureSSE2); }
+ if (ECX & 0x1) { X86SSELevel = SSE3; ToggleFeature(X86::FeatureSSE3); }
+ if ((ECX >> 9) & 1) { X86SSELevel = SSSE3; ToggleFeature(X86::FeatureSSSE3);}
+ if ((ECX >> 19) & 1) { X86SSELevel = SSE41; ToggleFeature(X86::FeatureSSE41);}
+ if ((ECX >> 20) & 1) { X86SSELevel = SSE42; ToggleFeature(X86::FeatureSSE42);}
// FIXME: AVX codegen support is not ready.
- //if ((ECX >> 28) & 1) { HasAVX = true; } ToggleFeature(X86::FeatureAVX);
+ //if ((ECX >> 28) & 1) { HasAVX = true; ToggleFeature(X86::FeatureAVX); }
bool IsIntel = memcmp(text.c, "GenuineIntel", 12) == 0;
bool IsAMD = !IsIntel && memcmp(text.c, "AuthenticAMD", 12) == 0;
- HasCLMUL = IsIntel && ((ECX >> 1) & 0x1); ToggleFeature(X86::FeatureCLMUL);
- HasFMA3 = IsIntel && ((ECX >> 12) & 0x1); ToggleFeature(X86::FeatureFMA3);
- HasPOPCNT = IsIntel && ((ECX >> 23) & 0x1); ToggleFeature(X86::FeaturePOPCNT);
- HasAES = IsIntel && ((ECX >> 25) & 0x1); ToggleFeature(X86::FeatureAES);
+ if (IsIntel && ((ECX >> 1) & 0x1)) {
+ HasCLMUL = true;
+ ToggleFeature(X86::FeatureCLMUL);
+ }
+ if (IsIntel && ((ECX >> 12) & 0x1)) {
+ HasFMA3 = true;
+ ToggleFeature(X86::FeatureFMA3);
+ }
+ if (IsIntel && ((ECX >> 22) & 0x1)) {
+ HasMOVBE = true;
+ ToggleFeature(X86::FeatureMOVBE);
+ }
+ if (IsIntel && ((ECX >> 23) & 0x1)) {
+ HasPOPCNT = true;
+ ToggleFeature(X86::FeaturePOPCNT);
+ }
+ if (IsIntel && ((ECX >> 25) & 0x1)) {
+ HasAES = true;
+ ToggleFeature(X86::FeatureAES);
+ }
+ if (IsIntel && ((ECX >> 29) & 0x1)) {
+ HasF16C = true;
+ ToggleFeature(X86::FeatureF16C);
+ }
+ if (IsIntel && ((ECX >> 30) & 0x1)) {
+ HasRDRAND = true;
+ ToggleFeature(X86::FeatureRDRAND);
+ }
+
+ if ((ECX >> 13) & 0x1) {
+ HasCmpxchg16b = true;
+ ToggleFeature(X86::FeatureCMPXCHG16B);
+ }
if (IsIntel || IsAMD) {
// Determine if bit test memory instructions are slow.
@@ -224,6 +255,10 @@ void X86Subtarget::AutoDetectSubtargetFeatures() {
HasX86_64 = true;
ToggleFeature(X86::Feature64Bit);
}
+ if ((ECX >> 5) & 0x1) {
+ HasLZCNT = true;
+ ToggleFeature(X86::FeatureLZCNT);
+ }
if (IsAMD && ((ECX >> 6) & 0x1)) {
HasSSE4A = true;
ToggleFeature(X86::FeatureSSE4A);
@@ -251,14 +286,21 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU,
, HasCLMUL(false)
, HasFMA3(false)
, HasFMA4(false)
+ , HasMOVBE(false)
+ , HasRDRAND(false)
+ , HasF16C(false)
+ , HasLZCNT(false)
+ , HasBMI(false)
, IsBTMemSlow(false)
, IsUAMemFast(false)
, HasVectorUAMem(false)
+ , HasCmpxchg16b(false)
, stackAlignment(8)
// FIXME: this is a known good value for Yonah. How about others?
, MaxInlineSizeThreshold(128)
, TargetTriple(TT)
- , In64BitMode(is64Bit) {
+ , In64BitMode(is64Bit)
+ , InNaClMode(false) {
// Determine default and user specified characteristics
if (!FS.empty() || !CPU.empty()) {
std::string CPUName = CPU;
@@ -304,6 +346,11 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU,
if (In64BitMode)
ToggleFeature(X86::Mode64Bit);
+ if (isTargetNaCl()) {
+ InNaClMode = true;
+ ToggleFeature(X86::ModeNaCl);
+ }
+
if (HasAVX)
X86SSELevel = NoMMXSSE;
@@ -313,6 +360,9 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU,
assert((!In64BitMode || HasX86_64) &&
"64-bit code requested on a subtarget that doesn't support it!");
+ if(EnableSegmentedStacks && !isTargetELF())
+ report_fatal_error("Segmented stacks are only implemented on ELF.");
+
// Stack alignment is 16 bytes on Darwin, FreeBSD, Linux and Solaris (both
// 32 and 64 bit) and for all 64-bit targets.
if (StackAlignOverride)
diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h
index 6d22027..3258d3d 100644
--- a/lib/Target/X86/X86Subtarget.h
+++ b/lib/Target/X86/X86Subtarget.h
@@ -90,6 +90,21 @@ protected:
/// HasFMA4 - Target has 4-operand fused multiply-add
bool HasFMA4;
+ /// HasMOVBE - True if the processor has the MOVBE instruction.
+ bool HasMOVBE;
+
+ /// HasRDRAND - True if the processor has the RDRAND instruction.
+ bool HasRDRAND;
+
+ /// HasF16C - Processor has 16-bit floating point conversion instructions.
+ bool HasF16C;
+
+ /// HasLZCNT - Processor has LZCNT instruction.
+ bool HasLZCNT;
+
+ /// HasBMI - Processor has BMI1 instructions.
+ bool HasBMI;
+
/// IsBTMemSlow - True if BT (bit test) of memory instructions are slow.
bool IsBTMemSlow;
@@ -100,6 +115,10 @@ protected:
/// operands. This may require setting a feature bit in the processor.
bool HasVectorUAMem;
+ /// HasCmpxchg16b - True if this processor has the CMPXCHG16B instruction;
+ /// this is true for most x86-64 chips, but not the first AMD chips.
+ bool HasCmpxchg16b;
+
/// stackAlignment - The minimum alignment known to hold of the stack frame on
/// entry to the function and which must be maintained by every function.
unsigned stackAlignment;
@@ -115,6 +134,9 @@ private:
/// In64BitMode - True if compiling for 64-bit, false for 32-bit.
bool In64BitMode;
+ /// InNaClMode - True if compiling for Native Client target.
+ bool InNaClMode;
+
public:
/// This constructor initializes the data members to match that
@@ -165,9 +187,15 @@ public:
bool hasCLMUL() const { return HasCLMUL; }
bool hasFMA3() const { return HasFMA3; }
bool hasFMA4() const { return HasFMA4; }
+ bool hasMOVBE() const { return HasMOVBE; }
+ bool hasRDRAND() const { return HasRDRAND; }
+ bool hasF16C() const { return HasF16C; }
+ bool hasLZCNT() const { return HasLZCNT; }
+ bool hasBMI() const { return HasBMI; }
bool isBTMemSlow() const { return IsBTMemSlow; }
bool isUnalignedMemAccessFast() const { return IsUAMemFast; }
bool hasVectorUAMem() const { return HasVectorUAMem; }
+ bool hasCmpxchg16b() const { return HasCmpxchg16b; }
const Triple &getTargetTriple() const { return TargetTriple; }
@@ -185,6 +213,11 @@ public:
return !isTargetDarwin() && !isTargetWindows() && !isTargetCygMing();
}
bool isTargetLinux() const { return TargetTriple.getOS() == Triple::Linux; }
+ bool isTargetNaCl() const {
+ return TargetTriple.getOS() == Triple::NativeClient;
+ }
+ bool isTargetNaCl32() const { return isTargetNaCl() && !is64Bit(); }
+ bool isTargetNaCl64() const { return isTargetNaCl() && is64Bit(); }
bool isTargetWindows() const { return TargetTriple.getOS() == Triple::Win32; }
bool isTargetMingw() const { return TargetTriple.getOS() == Triple::MinGW32; }
@@ -199,7 +232,8 @@ public:
}
bool isTargetWin64() const {
- return In64BitMode && (isTargetMingw() || isTargetWindows());
+ // FIXME: x86_64-cygwin has not been released yet.
+ return In64BitMode && (isTargetCygMing() || isTargetWindows());
}
bool isTargetEnvMacho() const {
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
index 9cab0e0..15c6c4e 100644
--- a/lib/Target/X86/X86TargetMachine.cpp
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -16,65 +16,32 @@
#include "llvm/PassManager.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
-static MCStreamer *createMCStreamer(const Target &T, const std::string &TT,
- MCContext &Ctx, TargetAsmBackend &TAB,
- raw_ostream &_OS,
- MCCodeEmitter *_Emitter,
- bool RelaxAll,
- bool NoExecStack) {
- Triple TheTriple(TT);
-
- if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO)
- return createMachOStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll);
-
- if (TheTriple.isOSWindows())
- return createWinCOFFStreamer(Ctx, TAB, *_Emitter, _OS, RelaxAll);
-
- return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll, NoExecStack);
-}
-
extern "C" void LLVMInitializeX86Target() {
// Register the target.
RegisterTargetMachine<X86_32TargetMachine> X(TheX86_32Target);
RegisterTargetMachine<X86_64TargetMachine> Y(TheX86_64Target);
-
- // Register the code emitter.
- TargetRegistry::RegisterCodeEmitter(TheX86_32Target,
- createX86MCCodeEmitter);
- TargetRegistry::RegisterCodeEmitter(TheX86_64Target,
- createX86MCCodeEmitter);
-
- // Register the asm backend.
- TargetRegistry::RegisterAsmBackend(TheX86_32Target,
- createX86_32AsmBackend);
- TargetRegistry::RegisterAsmBackend(TheX86_64Target,
- createX86_64AsmBackend);
-
- // Register the object streamer.
- TargetRegistry::RegisterObjectStreamer(TheX86_32Target,
- createMCStreamer);
- TargetRegistry::RegisterObjectStreamer(TheX86_64Target,
- createMCStreamer);
}
-X86_32TargetMachine::X86_32TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : X86TargetMachine(T, TT, CPU, FS, false),
+X86_32TargetMachine::X86_32TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : X86TargetMachine(T, TT, CPU, FS, RM, CM, false),
DataLayout(getSubtargetImpl()->isTargetDarwin() ?
- "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-f128:128:128-n8:16:32" :
+ "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-f128:128:128-"
+ "n8:16:32-S128" :
(getSubtargetImpl()->isTargetCygMing() ||
getSubtargetImpl()->isTargetWindows()) ?
- "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-f128:128:128-n8:16:32" :
- "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-f128:128:128-n8:16:32"),
+ "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-f128:128:128-"
+ "n8:16:32-S32" :
+ "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-f128:128:128-"
+ "n8:16:32-S128"),
InstrInfo(*this),
TSInfo(*this),
TLInfo(*this),
@@ -82,11 +49,12 @@ X86_32TargetMachine::X86_32TargetMachine(const Target &T, const std::string &TT,
}
-X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : X86TargetMachine(T, TT, CPU, FS, true),
- DataLayout("e-p:64:64-s:64-f64:64:64-i64:64:64-f80:128:128-f128:128:128-n8:16:32:64"),
+X86_64TargetMachine::X86_64TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : X86TargetMachine(T, TT, CPU, FS, RM, CM, true),
+ DataLayout("e-p:64:64-s:64-f64:64:64-i64:64:64-f80:128:128-f128:128:128-"
+ "n8:16:32:64-S128"),
InstrInfo(*this),
TSInfo(*this),
TLInfo(*this),
@@ -95,52 +63,14 @@ X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT,
/// X86TargetMachine ctor - Create an X86 target.
///
-X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS, bool is64Bit)
- : LLVMTargetMachine(T, TT, CPU, FS),
+X86TargetMachine::X86TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM,
+ bool is64Bit)
+ : LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
Subtarget(TT, CPU, FS, StackAlignmentOverride, is64Bit),
FrameLowering(*this, Subtarget),
ELFWriterInfo(is64Bit, true) {
- DefRelocModel = getRelocationModel();
-
- // If no relocation model was picked, default as appropriate for the target.
- if (getRelocationModel() == Reloc::Default) {
- // Darwin defaults to PIC in 64 bit mode and dynamic-no-pic in 32 bit mode.
- // Win64 requires rip-rel addressing, thus we force it to PIC. Otherwise we
- // use static relocation model by default.
- if (Subtarget.isTargetDarwin()) {
- if (Subtarget.is64Bit())
- setRelocationModel(Reloc::PIC_);
- else
- setRelocationModel(Reloc::DynamicNoPIC);
- } else if (Subtarget.isTargetWin64())
- setRelocationModel(Reloc::PIC_);
- else
- setRelocationModel(Reloc::Static);
- }
-
- assert(getRelocationModel() != Reloc::Default &&
- "Relocation mode not picked");
-
- // ELF and X86-64 don't have a distinct DynamicNoPIC model. DynamicNoPIC
- // is defined as a model for code which may be used in static or dynamic
- // executables but not necessarily a shared library. On X86-32 we just
- // compile in -static mode, in x86-64 we use PIC.
- if (getRelocationModel() == Reloc::DynamicNoPIC) {
- if (is64Bit)
- setRelocationModel(Reloc::PIC_);
- else if (!Subtarget.isTargetDarwin())
- setRelocationModel(Reloc::Static);
- }
-
- // If we are on Darwin, disallow static relocation model in X86-64 mode, since
- // the Mach-O file format doesn't support it.
- if (getRelocationModel() == Reloc::Static &&
- Subtarget.isTargetDarwin() &&
- is64Bit)
- setRelocationModel(Reloc::PIC_);
-
// Determine the PICStyle based on the target selected.
if (getRelocationModel() == Reloc::Static) {
// Unless we're in PIC or DynamicNoPIC mode, set the PIC style to None.
@@ -161,16 +91,20 @@ X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT,
Subtarget.setPICStyle(PICStyles::GOT);
}
- // Finally, if we have "none" as our PIC style, force to static mode.
- if (Subtarget.getPICStyle() == PICStyles::None)
- setRelocationModel(Reloc::Static);
-
// default to hard float ABI
if (FloatABIType == FloatABI::Default)
FloatABIType = FloatABI::Hard;
}
//===----------------------------------------------------------------------===//
+// Command line options for x86
+//===----------------------------------------------------------------------===//
+static cl::opt<bool>
+UseVZeroUpper("x86-use-vzeroupper",
+ cl::desc("Minimize AVX to SSE transition penalty"),
+ cl::init(false));
+
+//===----------------------------------------------------------------------===//
// Pass Pipeline Configuration
//===----------------------------------------------------------------------===//
@@ -200,46 +134,25 @@ bool X86TargetMachine::addPostRegAlloc(PassManagerBase &PM,
bool X86TargetMachine::addPreEmitPass(PassManagerBase &PM,
CodeGenOpt::Level OptLevel) {
- if (OptLevel != CodeGenOpt::None && Subtarget.hasSSE2()) {
- PM.add(createSSEDomainFixPass());
- return true;
+ bool ShouldPrint = false;
+ if (OptLevel != CodeGenOpt::None &&
+ (Subtarget.hasSSE2() || Subtarget.hasAVX())) {
+ PM.add(createExecutionDependencyFixPass(&X86::VR128RegClass));
+ ShouldPrint = true;
}
- return false;
+
+ if (Subtarget.hasAVX() && UseVZeroUpper) {
+ PM.add(createX86IssueVZeroUpperPass());
+ ShouldPrint = true;
+ }
+
+ return ShouldPrint;
}
bool X86TargetMachine::addCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
JITCodeEmitter &JCE) {
- // FIXME: Move this to TargetJITInfo!
- // On Darwin, do not override 64-bit setting made in X86TargetMachine().
- if (DefRelocModel == Reloc::Default &&
- (!Subtarget.isTargetDarwin() || !Subtarget.is64Bit())) {
- setRelocationModel(Reloc::Static);
- Subtarget.setPICStyle(PICStyles::None);
- }
-
-
PM.add(createX86JITCodeEmitterPass(*this, JCE));
return false;
}
-
-void X86TargetMachine::setCodeModelForStatic() {
-
- if (getCodeModel() != CodeModel::Default) return;
-
- // For static codegen, if we're not already set, use Small codegen.
- setCodeModel(CodeModel::Small);
-}
-
-
-void X86TargetMachine::setCodeModelForJIT() {
-
- if (getCodeModel() != CodeModel::Default) return;
-
- // 64-bit JIT places everything in the same buffer except external functions.
- if (Subtarget.is64Bit())
- setCodeModel(CodeModel::Large);
- else
- setCodeModel(CodeModel::Small);
-}
diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h
index 885334a..d1569aa 100644
--- a/lib/Target/X86/X86TargetMachine.h
+++ b/lib/Target/X86/X86TargetMachine.h
@@ -29,21 +29,17 @@
namespace llvm {
class formatted_raw_ostream;
+class StringRef;
class X86TargetMachine : public LLVMTargetMachine {
X86Subtarget Subtarget;
X86FrameLowering FrameLowering;
X86ELFWriterInfo ELFWriterInfo;
- Reloc::Model DefRelocModel; // Reloc model before it's overridden.
-private:
- // We have specific defaults for X86.
- virtual void setCodeModelForJIT();
- virtual void setCodeModelForStatic();
-
public:
- X86TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS,
+ X86TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM,
bool is64Bit);
virtual const X86InstrInfo *getInstrInfo() const {
@@ -87,8 +83,9 @@ class X86_32TargetMachine : public X86TargetMachine {
X86TargetLowering TLInfo;
X86JITInfo JITInfo;
public:
- X86_32TargetMachine(const Target &T, const std::string &M,
- const std::string &CPU, const std::string &FS);
+ X86_32TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
virtual const TargetData *getTargetData() const { return &DataLayout; }
virtual const X86TargetLowering *getTargetLowering() const {
return &TLInfo;
@@ -113,8 +110,9 @@ class X86_64TargetMachine : public X86TargetMachine {
X86TargetLowering TLInfo;
X86JITInfo JITInfo;
public:
- X86_64TargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ X86_64TargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
virtual const TargetData *getTargetData() const { return &DataLayout; }
virtual const X86TargetLowering *getTargetLowering() const {
return &TLInfo;
diff --git a/lib/Target/X86/X86TargetObjectFile.cpp b/lib/Target/X86/X86TargetObjectFile.cpp
index 1231798..991f322 100644
--- a/lib/Target/X86/X86TargetObjectFile.cpp
+++ b/lib/Target/X86/X86TargetObjectFile.cpp
@@ -43,79 +43,3 @@ getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang,
MachineModuleInfo *MMI) const {
return Mang->getSymbol(GV);
}
-
-unsigned X8632_ELFTargetObjectFile::getPersonalityEncoding() const {
- if (TM.getRelocationModel() == Reloc::PIC_)
- return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4;
- else
- return DW_EH_PE_absptr;
-}
-
-unsigned X8632_ELFTargetObjectFile::getLSDAEncoding() const {
- if (TM.getRelocationModel() == Reloc::PIC_)
- return DW_EH_PE_pcrel | DW_EH_PE_sdata4;
- else
- return DW_EH_PE_absptr;
-}
-
-unsigned X8632_ELFTargetObjectFile::getFDEEncoding(bool FDE) const {
- if (TM.getRelocationModel() == Reloc::PIC_)
- return DW_EH_PE_pcrel | DW_EH_PE_sdata4;
- else
- return DW_EH_PE_absptr;
-}
-
-unsigned X8632_ELFTargetObjectFile::getTTypeEncoding() const {
- if (TM.getRelocationModel() == Reloc::PIC_)
- return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4;
- else
- return DW_EH_PE_absptr;
-}
-
-unsigned X8664_ELFTargetObjectFile::getPersonalityEncoding() const {
- CodeModel::Model Model = TM.getCodeModel();
- if (TM.getRelocationModel() == Reloc::PIC_)
- return DW_EH_PE_indirect | DW_EH_PE_pcrel | (Model == CodeModel::Small ||
- Model == CodeModel::Medium ?
- DW_EH_PE_sdata4 : DW_EH_PE_sdata8);
-
- if (Model == CodeModel::Small || Model == CodeModel::Medium)
- return DW_EH_PE_udata4;
-
- return DW_EH_PE_absptr;
-}
-
-unsigned X8664_ELFTargetObjectFile::getLSDAEncoding() const {
- CodeModel::Model Model = TM.getCodeModel();
- if (TM.getRelocationModel() == Reloc::PIC_)
- return DW_EH_PE_pcrel | (Model == CodeModel::Small ?
- DW_EH_PE_sdata4 : DW_EH_PE_sdata8);
-
- if (Model == CodeModel::Small)
- return DW_EH_PE_udata4;
-
- return DW_EH_PE_absptr;
-}
-
-unsigned X8664_ELFTargetObjectFile::getFDEEncoding(bool CFI) const {
- if (CFI)
- return DW_EH_PE_pcrel | DW_EH_PE_sdata4;
-
- if (TM.getRelocationModel() == Reloc::PIC_)
- return DW_EH_PE_pcrel | DW_EH_PE_sdata4;
-
- return DW_EH_PE_udata4;
-}
-
-unsigned X8664_ELFTargetObjectFile::getTTypeEncoding() const {
- CodeModel::Model Model = TM.getCodeModel();
- if (TM.getRelocationModel() == Reloc::PIC_)
- return DW_EH_PE_indirect | DW_EH_PE_pcrel | (Model == CodeModel::Small ||
- Model == CodeModel::Medium ?
- DW_EH_PE_sdata4 : DW_EH_PE_sdata8);
-
- if (Model == CodeModel::Small)
- return DW_EH_PE_udata4;
-
- return DW_EH_PE_absptr;
-}
diff --git a/lib/Target/X86/X86TargetObjectFile.h b/lib/Target/X86/X86TargetObjectFile.h
index e21b5bf..d7adf27 100644
--- a/lib/Target/X86/X86TargetObjectFile.h
+++ b/lib/Target/X86/X86TargetObjectFile.h
@@ -33,28 +33,6 @@ namespace llvm {
MachineModuleInfo *MMI) const;
};
- class X8632_ELFTargetObjectFile : public TargetLoweringObjectFileELF {
- const X86TargetMachine &TM;
- public:
- X8632_ELFTargetObjectFile(const X86TargetMachine &tm)
- :TM(tm) { }
- virtual unsigned getPersonalityEncoding() const;
- virtual unsigned getLSDAEncoding() const;
- virtual unsigned getFDEEncoding(bool CFI) const;
- virtual unsigned getTTypeEncoding() const;
- };
-
- class X8664_ELFTargetObjectFile : public TargetLoweringObjectFileELF {
- const X86TargetMachine &TM;
- public:
- X8664_ELFTargetObjectFile(const X86TargetMachine &tm)
- :TM(tm) { }
- virtual unsigned getPersonalityEncoding() const;
- virtual unsigned getLSDAEncoding() const;
- virtual unsigned getFDEEncoding(bool CFI) const;
- virtual unsigned getTTypeEncoding() const;
- };
-
} // end namespace llvm
#endif
diff --git a/lib/Target/X86/X86VZeroUpper.cpp b/lib/Target/X86/X86VZeroUpper.cpp
new file mode 100644
index 0000000..3958494
--- /dev/null
+++ b/lib/Target/X86/X86VZeroUpper.cpp
@@ -0,0 +1,105 @@
+//===-- X86VZeroUpper.cpp - AVX vzeroupper instruction inserter -----------===//
+//
+// 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 pass which inserts x86 AVX vzeroupper instructions
+// before calls to SSE encoded functions. This avoids transition latency
+// penalty when tranfering control between AVX encoded instructions and old
+// SSE encoding mode.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "x86-codegen"
+#include "X86.h"
+#include "X86InstrInfo.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/GlobalValue.h"
+#include "llvm/Target/TargetInstrInfo.h"
+using namespace llvm;
+
+STATISTIC(NumVZU, "Number of vzeroupper instructions inserted");
+
+namespace {
+ struct VZeroUpperInserter : public MachineFunctionPass {
+ static char ID;
+ VZeroUpperInserter() : MachineFunctionPass(ID) {}
+
+ virtual bool runOnMachineFunction(MachineFunction &MF);
+
+ bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
+
+ virtual const char *getPassName() const { return "X86 vzeroupper inserter";}
+
+ private:
+ const TargetInstrInfo *TII; // Machine instruction info.
+ MachineBasicBlock *MBB; // Current basic block
+ };
+ char VZeroUpperInserter::ID = 0;
+}
+
+FunctionPass *llvm::createX86IssueVZeroUpperPass() {
+ return new VZeroUpperInserter();
+}
+
+/// runOnMachineFunction - Loop over all of the basic blocks, inserting
+/// vzero upper instructions before function calls.
+bool VZeroUpperInserter::runOnMachineFunction(MachineFunction &MF) {
+ TII = MF.getTarget().getInstrInfo();
+ bool Changed = false;
+
+ // Process any unreachable blocks in arbitrary order now.
+ for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
+ Changed |= processBasicBlock(MF, *BB);
+
+ return Changed;
+}
+
+static bool isCallToModuleFn(const MachineInstr *MI) {
+ assert(MI->getDesc().isCall() && "Isn't a call instruction");
+
+ for (int i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+
+ if (!MO.isGlobal())
+ continue;
+
+ const GlobalValue *GV = MO.getGlobal();
+ GlobalValue::LinkageTypes LT = GV->getLinkage();
+ if (GV->isInternalLinkage(LT) || GV->isPrivateLinkage(LT) ||
+ (GV->isExternalLinkage(LT) && !GV->isDeclaration()))
+ return true;
+
+ return false;
+ }
+ return false;
+}
+
+/// processBasicBlock - Loop over all of the instructions in the basic block,
+/// inserting vzero upper instructions before function calls.
+bool VZeroUpperInserter::processBasicBlock(MachineFunction &MF,
+ MachineBasicBlock &BB) {
+ bool Changed = false;
+ MBB = &BB;
+
+ for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) {
+ MachineInstr *MI = I;
+ DebugLoc dl = I->getDebugLoc();
+
+ // Insert a vzeroupper instruction before each control transfer
+ // to functions outside this module
+ if (MI->getDesc().isCall() && !isCallToModuleFn(MI)) {
+ BuildMI(*MBB, I, dl, TII->get(X86::VZEROUPPER));
+ ++NumVZU;
+ }
+ }
+
+ return Changed;
+}
diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt
index a1d73c6..3dc51e1 100644
--- a/lib/Target/XCore/CMakeLists.txt
+++ b/lib/Target/XCore/CMakeLists.txt
@@ -1,11 +1,12 @@
set(LLVM_TARGET_DEFINITIONS XCore.td)
-tablegen(XCoreGenRegisterInfo.inc -gen-register-info)
-tablegen(XCoreGenInstrInfo.inc -gen-instr-info)
-tablegen(XCoreGenAsmWriter.inc -gen-asm-writer)
-tablegen(XCoreGenDAGISel.inc -gen-dag-isel)
-tablegen(XCoreGenCallingConv.inc -gen-callingconv)
-tablegen(XCoreGenSubtargetInfo.inc -gen-subtarget)
+llvm_tablegen(XCoreGenRegisterInfo.inc -gen-register-info)
+llvm_tablegen(XCoreGenInstrInfo.inc -gen-instr-info)
+llvm_tablegen(XCoreGenAsmWriter.inc -gen-asm-writer)
+llvm_tablegen(XCoreGenDAGISel.inc -gen-dag-isel)
+llvm_tablegen(XCoreGenCallingConv.inc -gen-callingconv)
+llvm_tablegen(XCoreGenSubtargetInfo.inc -gen-subtarget)
+add_public_tablegen_target(XCoreCommonTableGen)
add_llvm_target(XCoreCodeGen
XCoreAsmPrinter.cpp
@@ -20,5 +21,17 @@ add_llvm_target(XCoreCodeGen
XCoreSelectionDAGInfo.cpp
)
+add_llvm_library_dependencies(LLVMXCoreCodeGen
+ LLVMAsmPrinter
+ LLVMCodeGen
+ LLVMCore
+ LLVMMC
+ LLVMSelectionDAG
+ LLVMSupport
+ LLVMTarget
+ LLVMXCoreDesc
+ LLVMXCoreInfo
+ )
+
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
diff --git a/lib/Target/XCore/MCTargetDesc/CMakeLists.txt b/lib/Target/XCore/MCTargetDesc/CMakeLists.txt
index c3b3dc9..269822d 100644
--- a/lib/Target/XCore/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/XCore/MCTargetDesc/CMakeLists.txt
@@ -3,5 +3,12 @@ add_llvm_library(LLVMXCoreDesc
XCoreMCAsmInfo.cpp
)
+add_llvm_library_dependencies(LLVMXCoreDesc
+ LLVMMC
+ LLVMXCoreInfo
+ )
+
+add_dependencies(LLVMXCoreDesc XCoreCommonTableGen)
+
# Hack: we need to include 'main' target directory to grab private headers
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..)
diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp
index 939d97c..276e841 100644
--- a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp
+++ b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp
@@ -13,10 +13,11 @@
#include "XCoreMCTargetDesc.h"
#include "XCoreMCAsmInfo.h"
+#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_MC_DESC
#include "XCoreGenInstrInfo.inc"
@@ -35,8 +36,10 @@ static MCInstrInfo *createXCoreMCInstrInfo() {
return X;
}
-extern "C" void LLVMInitializeXCoreMCInstrInfo() {
- TargetRegistry::RegisterMCInstrInfo(TheXCoreTarget, createXCoreMCInstrInfo);
+static MCRegisterInfo *createXCoreMCRegisterInfo(StringRef TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitXCoreMCRegisterInfo(X, XCore::LR);
+ return X;
}
static MCSubtargetInfo *createXCoreMCSubtargetInfo(StringRef TT, StringRef CPU,
@@ -46,11 +49,40 @@ static MCSubtargetInfo *createXCoreMCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-extern "C" void LLVMInitializeXCoreMCSubtargetInfo() {
- TargetRegistry::RegisterMCSubtargetInfo(TheXCoreTarget,
- createXCoreMCSubtargetInfo);
+static MCAsmInfo *createXCoreMCAsmInfo(const Target &T, StringRef TT) {
+ MCAsmInfo *MAI = new XCoreMCAsmInfo(T, TT);
+
+ // Initial state of the frame pointer is SP.
+ MachineLocation Dst(MachineLocation::VirtualFP);
+ MachineLocation Src(XCore::SP, 0);
+ MAI->addInitialFrameState(0, Dst, Src);
+
+ return MAI;
+}
+
+static MCCodeGenInfo *createXCoreMCCodeGenInfo(StringRef TT, Reloc::Model RM,
+ CodeModel::Model CM) {
+ MCCodeGenInfo *X = new MCCodeGenInfo();
+ X->InitMCCodeGenInfo(RM, CM);
+ return X;
}
-extern "C" void LLVMInitializeXCoreMCAsmInfo() {
- RegisterMCAsmInfo<XCoreMCAsmInfo> X(TheXCoreTarget);
+// Force static initialization.
+extern "C" void LLVMInitializeXCoreTargetMC() {
+ // Register the MC asm info.
+ RegisterMCAsmInfoFn X(TheXCoreTarget, createXCoreMCAsmInfo);
+
+ // Register the MC codegen info.
+ TargetRegistry::RegisterMCCodeGenInfo(TheXCoreTarget,
+ createXCoreMCCodeGenInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheXCoreTarget, createXCoreMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheXCoreTarget, createXCoreMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(TheXCoreTarget,
+ createXCoreMCSubtargetInfo);
}
diff --git a/lib/Target/XCore/TargetInfo/CMakeLists.txt b/lib/Target/XCore/TargetInfo/CMakeLists.txt
index c147b8a..7f84f69 100644
--- a/lib/Target/XCore/TargetInfo/CMakeLists.txt
+++ b/lib/Target/XCore/TargetInfo/CMakeLists.txt
@@ -4,4 +4,10 @@ add_llvm_library(LLVMXCoreInfo
XCoreTargetInfo.cpp
)
-add_dependencies(LLVMXCoreInfo XCoreCodeGenTable_gen)
+add_llvm_library_dependencies(LLVMXCoreInfo
+ LLVMMC
+ LLVMSupport
+ LLVMTarget
+ )
+
+add_dependencies(LLVMXCoreInfo XCoreCommonTableGen)
diff --git a/lib/Target/XCore/TargetInfo/XCoreTargetInfo.cpp b/lib/Target/XCore/TargetInfo/XCoreTargetInfo.cpp
index 7aa8965..9a0971d 100644
--- a/lib/Target/XCore/TargetInfo/XCoreTargetInfo.cpp
+++ b/lib/Target/XCore/TargetInfo/XCoreTargetInfo.cpp
@@ -9,7 +9,7 @@
#include "XCore.h"
#include "llvm/Module.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
Target llvm::TheXCoreTarget;
diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp
index 1a43714..8906b24 100644
--- a/lib/Target/XCore/XCoreAsmPrinter.cpp
+++ b/lib/Target/XCore/XCoreAsmPrinter.cpp
@@ -20,6 +20,7 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
+#include "llvm/Analysis/DebugInfo.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -32,11 +33,11 @@
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cctype>
@@ -51,6 +52,7 @@ static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional,
namespace {
class XCoreAsmPrinter : public AsmPrinter {
const XCoreSubtarget &Subtarget;
+ void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
public:
explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
: AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget<XCoreSubtarget>()){}
@@ -79,6 +81,7 @@ namespace {
void EmitFunctionEntryLabel();
void EmitInstruction(const MachineInstr *MI);
void EmitFunctionBodyEnd();
+ virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const;
};
} // end of anonymous namespace
@@ -88,7 +91,7 @@ void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
assert(((GV->hasExternalLinkage() ||
GV->hasWeakLinkage()) ||
GV->hasLinkOnceLinkage()) && "Unexpected linkage");
- if (const ArrayType *ATy = dyn_cast<ArrayType>(
+ if (ArrayType *ATy = dyn_cast<ArrayType>(
cast<PointerType>(GV->getType())->getElementType())) {
OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global);
// FIXME: MCStreamerize.
@@ -261,16 +264,57 @@ bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
return false;
}
+void XCoreAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
+ raw_ostream &OS) {
+ unsigned NOps = MI->getNumOperands();
+ assert(NOps == 4);
+ OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
+ // cast away const; DIetc do not take const operands for some reason.
+ DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata()));
+ OS << V.getName();
+ OS << " <- ";
+ // Frame address. Currently handles register +- offset only.
+ assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
+ OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS);
+ OS << ']';
+ OS << "+";
+ printOperand(MI, NOps-2, OS);
+}
+
+MachineLocation XCoreAsmPrinter::
+getDebugValueLocation(const MachineInstr *MI) const {
+ // Handles frame addresses emitted in XCoreInstrInfo::emitFrameIndexDebugValue.
+ assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
+ assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm() &&
+ "Unexpected MachineOperand types");
+ return MachineLocation(MI->getOperand(0).getReg(),
+ MI->getOperand(1).getImm());
+}
+
void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) {
SmallString<128> Str;
raw_svector_ostream O(Str);
- // Check for mov mnemonic
- if (MI->getOpcode() == XCore::ADD_2rus && !MI->getOperand(2).getImm())
- O << "\tmov " << getRegisterName(MI->getOperand(0).getReg()) << ", "
- << getRegisterName(MI->getOperand(1).getReg());
- else
- printInstruction(MI, O);
+ switch (MI->getOpcode()) {
+ case XCore::DBG_VALUE: {
+ if (isVerbose() && OutStreamer.hasRawTextSupport()) {
+ SmallString<128> TmpStr;
+ raw_svector_ostream OS(TmpStr);
+ PrintDebugValueComment(MI, OS);
+ OutStreamer.EmitRawText(StringRef(OS.str()));
+ }
+ return;
+ }
+ case XCore::ADD_2rus:
+ if (MI->getOperand(2).getImm() == 0) {
+ O << "\tmov " << getRegisterName(MI->getOperand(0).getReg()) << ", "
+ << getRegisterName(MI->getOperand(1).getReg());
+ OutStreamer.EmitRawText(O.str());
+ return;
+ }
+ break;
+ }
+ printInstruction(MI, O);
OutStreamer.EmitRawText(O.str());
}
diff --git a/lib/Target/XCore/XCoreFrameLowering.cpp b/lib/Target/XCore/XCoreFrameLowering.cpp
index 0578220..7f8b169 100644
--- a/lib/Target/XCore/XCoreFrameLowering.cpp
+++ b/lib/Target/XCore/XCoreFrameLowering.cpp
@@ -100,7 +100,8 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const {
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
bool FP = hasFP(MF);
- bool Nested = MF.getFunction()->getAttributes().hasAttrSomewhere(Attribute::Nest);
+ bool Nested = MF.getFunction()->
+ getAttributes().hasAttrSomewhere(Attribute::Nest);
if (Nested) {
loadFromStack(MBB, MBBI, XCore::R11, 0, dl, TII);
@@ -270,14 +271,6 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF,
}
}
-void XCoreFrameLowering::getInitialFrameState(std::vector<MachineMove> &Moves)
- const {
- // Initial state of the frame pointer is SP.
- MachineLocation Dst(MachineLocation::VirtualFP);
- MachineLocation Src(XCore::SP, 0);
- Moves.push_back(MachineMove(0, Dst, Src));
-}
-
bool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
diff --git a/lib/Target/XCore/XCoreFrameLowering.h b/lib/Target/XCore/XCoreFrameLowering.h
index 7da19f0..c591e93 100644
--- a/lib/Target/XCore/XCoreFrameLowering.h
+++ b/lib/Target/XCore/XCoreFrameLowering.h
@@ -42,8 +42,6 @@ namespace llvm {
bool hasFP(const MachineFunction &MF) const;
- void getInitialFrameState(std::vector<MachineMove> &Moves) const;
-
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS = NULL) const;
diff --git a/lib/Target/XCore/XCoreISelDAGToDAG.cpp b/lib/Target/XCore/XCoreISelDAGToDAG.cpp
index a8dd847..4dac1ce 100644
--- a/lib/Target/XCore/XCoreISelDAGToDAG.cpp
+++ b/lib/Target/XCore/XCoreISelDAGToDAG.cpp
@@ -169,9 +169,14 @@ SDNode *XCoreDAGToDAGISel::Select(SDNode *N) {
CurDAG->getTargetConstantPool(ConstantInt::get(
Type::getInt32Ty(*CurDAG->getContext()), Val),
TLI.getPointerTy());
- return CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32,
- MVT::Other, CPIdx,
- CurDAG->getEntryNode());
+ SDNode *node = CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32,
+ MVT::Other, CPIdx,
+ CurDAG->getEntryNode());
+ MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
+ MemOp[0] = MF->getMachineMemOperand(
+ MachinePointerInfo::getConstantPool(), MachineMemOperand::MOLoad, 4, 4);
+ cast<MachineSDNode>(node)->setMemRefs(MemOp, MemOp + 1);
+ return node;
}
break;
}
diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp
index 6d040e0..2afe0e3 100644
--- a/lib/Target/XCore/XCoreISelLowering.cpp
+++ b/lib/Target/XCore/XCoreISelLowering.cpp
@@ -81,6 +81,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
// Use i32 for setcc operations results (slt, sgt, ...).
setBooleanContents(ZeroOrOneBooleanContent);
+ setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
// XCore does not have the NodeTypes below.
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
@@ -147,7 +148,8 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
// TRAMPOLINE is custom lowered.
- setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom);
+ setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom);
+ setOperationAction(ISD::ADJUST_TRAMPOLINE, MVT::Other, Custom);
maxStoresPerMemset = maxStoresPerMemsetOptSize = 4;
maxStoresPerMemmove = maxStoresPerMemmoveOptSize
@@ -180,7 +182,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::ADD:
case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG);
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
- case ISD::TRAMPOLINE: return LowerTRAMPOLINE(Op, DAG);
+ case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG);
+ case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG);
default:
llvm_unreachable("unimplemented operand");
return SDValue();
@@ -252,8 +255,8 @@ static inline SDValue BuildGetId(SelectionDAG &DAG, DebugLoc dl) {
DAG.getConstant(Intrinsic::xcore_getid, MVT::i32));
}
-static inline bool isZeroLengthArray(const Type *Ty) {
- const ArrayType *AT = dyn_cast_or_null<ArrayType>(Ty);
+static inline bool isZeroLengthArray(Type *Ty) {
+ ArrayType *AT = dyn_cast_or_null<ArrayType>(Ty);
return AT && (AT->getNumElements() == 0);
}
@@ -275,7 +278,7 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
llvm_unreachable("Thread local object not a GlobalVariable?");
return SDValue();
}
- const Type *Ty = cast<PointerType>(GV->getType())->getElementType();
+ Type *Ty = cast<PointerType>(GV->getType())->getElementType();
if (!Ty->isSized() || isZeroLengthArray(Ty)) {
#ifndef NDEBUG
errs() << "Size of thread local object " << GVar->getName()
@@ -465,7 +468,7 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
}
// Lower to a call to __misaligned_load(BasePtr).
- const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
+ Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
@@ -524,7 +527,7 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) const
}
// Lower to a call to __misaligned_store(BasePtr, Value).
- const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
+ Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
@@ -789,7 +792,12 @@ SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op,
}
SDValue XCoreTargetLowering::
-LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
+LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
+ return Op.getOperand(0);
+}
+
+SDValue XCoreTargetLowering::
+LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
SDValue Chain = Op.getOperand(0);
SDValue Trmp = Op.getOperand(1); // trampoline
SDValue FPtr = Op.getOperand(2); // nested function
@@ -841,9 +849,7 @@ LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
MachinePointerInfo(TrmpAddr, 16), false, false,
0);
- SDValue Ops[] =
- { Trmp, DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 5) };
- return DAG.getMergeValues(Ops, 2, dl);
+ return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 5);
}
//===----------------------------------------------------------------------===//
@@ -1148,10 +1154,10 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain,
int offset = 0;
// Save remaining registers, storing higher register numbers at a higher
// address
- for (unsigned i = array_lengthof(ArgRegs) - 1; i >= FirstVAReg; --i) {
+ for (int i = array_lengthof(ArgRegs) - 1; i >= (int)FirstVAReg; --i) {
// Create a stack slot
int FI = MFI->CreateFixedObject(4, offset, true);
- if (i == FirstVAReg) {
+ if (i == (int)FirstVAReg) {
XFI->setVarArgsFrameIndex(FI);
}
offset -= StackSlotSize;
@@ -1409,7 +1415,8 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
// operands are constant canonicalize smallest to RHS.
if ((N0C && !N1C) ||
(N0C && N1C && N0C->getZExtValue() < N1C->getZExtValue()))
- return DAG.getNode(XCoreISD::LMUL, dl, DAG.getVTList(VT, VT), N1, N0, N2, N3);
+ return DAG.getNode(XCoreISD::LMUL, dl, DAG.getVTList(VT, VT),
+ N1, N0, N2, N3);
// lmul(x, 0, a, b)
if (N1C && N1C->isNullValue()) {
@@ -1548,7 +1555,7 @@ static inline bool isImmUs4(int64_t val)
/// by AM is legal for this target, for a load/store of the specified type.
bool
XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM,
- const Type *Ty) const {
+ Type *Ty) const {
if (Ty->getTypeID() == Type::VoidTyID)
return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs);
diff --git a/lib/Target/XCore/XCoreISelLowering.h b/lib/Target/XCore/XCoreISelLowering.h
index 9c803be..d6c5b32 100644
--- a/lib/Target/XCore/XCoreISelLowering.h
+++ b/lib/Target/XCore/XCoreISelLowering.h
@@ -101,7 +101,7 @@ namespace llvm {
MachineBasicBlock *MBB) const;
virtual bool isLegalAddressingMode(const AddrMode &AM,
- const Type *Ty) const;
+ Type *Ty) const;
private:
const XCoreTargetMachine &TM;
@@ -145,7 +145,8 @@ namespace llvm {
SDValue LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
- SDValue LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
// Inline asm support
std::pair<unsigned, const TargetRegisterClass*>
diff --git a/lib/Target/XCore/XCoreInstrInfo.cpp b/lib/Target/XCore/XCoreInstrInfo.cpp
index f90481f..a0946a1 100644
--- a/lib/Target/XCore/XCoreInstrInfo.cpp
+++ b/lib/Target/XCore/XCoreInstrInfo.cpp
@@ -17,11 +17,10 @@
#include "llvm/MC/MCContext.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
-#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_INSTRINFO_CTOR
#include "XCoreGenInstrInfo.inc"
@@ -387,6 +386,15 @@ void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
.addImm(0);
}
+MachineInstr*
+XCoreInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx,
+ uint64_t Offset, const MDNode *MDPtr,
+ DebugLoc DL) const {
+ MachineInstrBuilder MIB = BuildMI(MF, DL, get(XCore::DBG_VALUE))
+ .addFrameIndex(FrameIx).addImm(0).addImm(Offset).addMetadata(MDPtr);
+ return &*MIB;
+}
+
/// ReverseBranchCondition - Return the inverse opcode of the
/// specified Branch instruction.
bool XCoreInstrInfo::
diff --git a/lib/Target/XCore/XCoreInstrInfo.h b/lib/Target/XCore/XCoreInstrInfo.h
index 840b1e1..d354802 100644
--- a/lib/Target/XCore/XCoreInstrInfo.h
+++ b/lib/Target/XCore/XCoreInstrInfo.h
@@ -78,6 +78,11 @@ public:
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const;
+ virtual MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF,
+ int FrameIx,
+ uint64_t Offset,
+ const MDNode *MDPtr,
+ DebugLoc DL) const;
virtual bool ReverseBranchCondition(
SmallVectorImpl<MachineOperand> &Cond) const;
diff --git a/lib/Target/XCore/XCoreInstrInfo.td b/lib/Target/XCore/XCoreInstrInfo.td
index 55c7527..4d2e93b 100644
--- a/lib/Target/XCore/XCoreInstrInfo.td
+++ b/lib/Target/XCore/XCoreInstrInfo.td
@@ -572,7 +572,7 @@ def STWDP_lru6 : _FLRU6<(outs), (ins GRRegs:$val, MEMii:$addr),
[(store GRRegs:$val, ADDRdpii:$addr)]>;
//let Uses = [CP] in ..
-let mayLoad = 1, isReMaterializable = 1 in
+let mayLoad = 1, isReMaterializable = 1, neverHasSideEffects = 1 in
defm LDWCP : FRU6_LRU6_cp<"ldw">;
let Uses = [SP] in {
@@ -739,7 +739,7 @@ def LDAP_lu10_ba : _FLU10<(outs),
let isCall=1,
// All calls clobber the link register and the non-callee-saved registers:
-Defs = [R0, R1, R2, R3, R11, LR] in {
+Defs = [R0, R1, R2, R3, R11, LR], Uses = [SP] in {
def BL_u10 : _FU10<
(outs),
(ins calltarget:$target, variable_ops),
@@ -754,7 +754,7 @@ def BL_lu10 : _FLU10<
}
// Two operand short
-// TODO eet, eef, testwct, tsetmr, sext (reg), zext (reg)
+// TODO eet, eef, tsetmr
def NOT : _F2R<(outs GRRegs:$dst), (ins GRRegs:$b),
"not $dst, $b",
[(set GRRegs:$dst, (not GRRegs:$b))]>;
@@ -764,15 +764,25 @@ def NEG : _F2R<(outs GRRegs:$dst), (ins GRRegs:$b),
[(set GRRegs:$dst, (ineg GRRegs:$b))]>;
let Constraints = "$src1 = $dst" in {
-let neverHasSideEffects = 1 in
def SEXT_rus : _FRUS<(outs GRRegs:$dst), (ins GRRegs:$src1, i32imm:$src2),
- "sext $dst, $src2",
- []>;
+ "sext $dst, $src2",
+ [(set GRRegs:$dst, (int_xcore_sext GRRegs:$src1,
+ immBitp:$src2))]>;
+
+def SEXT_2r : _FRUS<(outs GRRegs:$dst), (ins GRRegs:$src1, GRRegs:$src2),
+ "sext $dst, $src2",
+ [(set GRRegs:$dst, (int_xcore_sext GRRegs:$src1,
+ GRRegs:$src2))]>;
-let neverHasSideEffects = 1 in
def ZEXT_rus : _FRUS<(outs GRRegs:$dst), (ins GRRegs:$src1, i32imm:$src2),
- "zext $dst, $src2",
- []>;
+ "zext $dst, $src2",
+ [(set GRRegs:$dst, (int_xcore_zext GRRegs:$src1,
+ immBitp:$src2))]>;
+
+def ZEXT_2r : _FRUS<(outs GRRegs:$dst), (ins GRRegs:$src1, GRRegs:$src2),
+ "zext $dst, $src2",
+ [(set GRRegs:$dst, (int_xcore_zext GRRegs:$src1,
+ GRRegs:$src2))]>;
def ANDNOT_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$src1, GRRegs:$src2),
"andnot $dst, $src2",
@@ -819,7 +829,8 @@ def OUT_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val),
let Constraints = "$src = $dst" in
def OUTSHR_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r, GRRegs:$src),
"outshr res[$r], $src",
- [(set GRRegs:$dst, (int_xcore_outshr GRRegs:$r, GRRegs:$src))]>;
+ [(set GRRegs:$dst, (int_xcore_outshr GRRegs:$r,
+ GRRegs:$src))]>;
def INCT_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r),
"inct $dst, res[$r]",
@@ -836,7 +847,8 @@ def IN_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r),
let Constraints = "$src = $dst" in
def INSHR_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r, GRRegs:$src),
"inshr $dst, res[$r]",
- [(set GRRegs:$dst, (int_xcore_inshr GRRegs:$r, GRRegs:$src))]>;
+ [(set GRRegs:$dst, (int_xcore_inshr GRRegs:$r,
+ GRRegs:$src))]>;
def CHKCT_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val),
"chkct res[$r], $val",
@@ -846,6 +858,14 @@ def CHKCT_rus : _F2R<(outs), (ins GRRegs:$r, i32imm:$val),
"chkct res[$r], $val",
[(int_xcore_chkct GRRegs:$r, immUs:$val)]>;
+def TESTCT_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$src),
+ "testct $dst, res[$src]",
+ [(set GRRegs:$dst, (int_xcore_testct GRRegs:$src))]>;
+
+def TESTWCT_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$src),
+ "testwct $dst, res[$src]",
+ [(set GRRegs:$dst, (int_xcore_testwct GRRegs:$src))]>;
+
def SETD_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val),
"setd res[$r], $val",
[(int_xcore_setd GRRegs:$r, GRRegs:$val)]>;
@@ -871,7 +891,6 @@ def INITDP_2r : _F2R<(outs), (ins GRRegs:$t, GRRegs:$src),
[(int_xcore_initdp GRRegs:$t, GRRegs:$src)]>;
// Two operand long
-// TODO endin, peek,
// getd, testlcl
def BITREV_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src),
"bitrev $dst, $src",
@@ -917,6 +936,14 @@ def SETPSC_l2r : _FL2R<(outs), (ins GRRegs:$src1, GRRegs:$src2),
"setpsc res[$src1], $src2",
[(int_xcore_setpsc GRRegs:$src1, GRRegs:$src2)]>;
+def PEEK_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src),
+ "peek $dst, res[$src]",
+ [(set GRRegs:$dst, (int_xcore_peek GRRegs:$src))]>;
+
+def ENDIN_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src),
+ "endin $dst, res[$src]",
+ [(set GRRegs:$dst, (int_xcore_endin GRRegs:$src))]>;
+
// One operand short
// TODO edu, eeu, waitet, waitef, tstart, clrtp
// setdp, setcp, setev, kcall
@@ -960,7 +987,7 @@ def ECALLF_1r : _F1R<(outs), (ins GRRegs:$src),
let isCall=1,
// All calls clobber the link register and the non-callee-saved registers:
-Defs = [R0, R1, R2, R3, R11, LR] in {
+Defs = [R0, R1, R2, R3, R11, LR], Uses = [SP] in {
def BLA_1r : _F1R<(outs), (ins GRRegs:$addr, variable_ops),
"bla $addr",
[(XCoreBranchLink GRRegs:$addr)]>;
@@ -974,10 +1001,15 @@ def FREER_1r : _F1R<(outs), (ins GRRegs:$r),
"freer res[$r]",
[(int_xcore_freer GRRegs:$r)]>;
-let Uses=[R11] in
+let Uses=[R11] in {
def SETV_1r : _F1R<(outs), (ins GRRegs:$r),
- "setv res[$r], r11",
- [(int_xcore_setv GRRegs:$r, R11)]>;
+ "setv res[$r], r11",
+ [(int_xcore_setv GRRegs:$r, R11)]>;
+
+def SETEV_1r : _F1R<(outs), (ins GRRegs:$r),
+ "setev res[$r], r11",
+ [(int_xcore_setev GRRegs:$r, R11)]>;
+}
def EEU_1r : _F1R<(outs), (ins GRRegs:$r),
"eeu res[$r]",
@@ -985,15 +1017,24 @@ def EEU_1r : _F1R<(outs), (ins GRRegs:$r),
// Zero operand short
// TODO freet, ldspc, stspc, ldssr, stssr, ldsed, stsed,
-// stet, geted, getet, getkep, getksp, setkep, getid, kret, dcall, dret,
+// stet, getkep, getksp, setkep, getid, kret, dcall, dret,
// dentsp, drestsp
def CLRE_0R : _F0R<(outs), (ins), "clre", [(int_xcore_clre)]>;
-let Defs = [R11] in
+let Defs = [R11] in {
def GETID_0R : _F0R<(outs), (ins),
- "get r11, id",
- [(set R11, (int_xcore_getid))]>;
+ "get r11, id",
+ [(set R11, (int_xcore_getid))]>;
+
+def GETED_0R : _F0R<(outs), (ins),
+ "get r11, ed",
+ [(set R11, (int_xcore_geted))]>;
+
+def GETET_0R : _F0R<(outs), (ins),
+ "get r11, et",
+ [(set R11, (int_xcore_getet))]>;
+}
def SSYNC_0r : _F0R<(outs), (ins),
"ssync",
diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp
index 357a4a0..1b78b37 100644
--- a/lib/Target/XCore/XCoreRegisterInfo.cpp
+++ b/lib/Target/XCore/XCoreRegisterInfo.cpp
@@ -17,7 +17,6 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
@@ -39,7 +38,7 @@
using namespace llvm;
XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii)
- : XCoreGenRegisterInfo(), TII(tii) {
+ : XCoreGenRegisterInfo(XCore::LR), TII(tii) {
}
// helper functions
@@ -321,20 +320,8 @@ loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value);
}
-int XCoreRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
- return XCoreGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
-}
-
-int XCoreRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const {
- return XCoreGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0);
-}
-
unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
}
-
-unsigned XCoreRegisterInfo::getRARegister() const {
- return XCore::LR;
-}
diff --git a/lib/Target/XCore/XCoreRegisterInfo.h b/lib/Target/XCore/XCoreRegisterInfo.h
index 801d9eb..5c28f39 100644
--- a/lib/Target/XCore/XCoreRegisterInfo.h
+++ b/lib/Target/XCore/XCoreRegisterInfo.h
@@ -60,7 +60,6 @@ public:
int SPAdj, RegScavenger *RS = NULL) const;
// Debug information queries.
- unsigned getRARegister() const;
unsigned getFrameRegister(const MachineFunction &MF) const;
//! Return the array of argument passing registers
@@ -74,10 +73,6 @@ public:
//! Return whether to emit frame moves
static bool needsFrameMoves(const MachineFunction &MF);
-
- //! Get DWARF debugging register number
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
- int getLLVMRegNum(unsigned RegNum, bool isEH) const;
};
} // end namespace llvm
diff --git a/lib/Target/XCore/XCoreSubtarget.cpp b/lib/Target/XCore/XCoreSubtarget.cpp
index ad069bf..b4e9927 100644
--- a/lib/Target/XCore/XCoreSubtarget.cpp
+++ b/lib/Target/XCore/XCoreSubtarget.cpp
@@ -13,7 +13,7 @@
#include "XCoreSubtarget.h"
#include "XCore.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
diff --git a/lib/Target/XCore/XCoreTargetMachine.cpp b/lib/Target/XCore/XCoreTargetMachine.cpp
index 342966a..fdc5d35 100644
--- a/lib/Target/XCore/XCoreTargetMachine.cpp
+++ b/lib/Target/XCore/XCoreTargetMachine.cpp
@@ -14,15 +14,15 @@
#include "XCore.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
/// XCoreTargetMachine ctor - Create an ILP32 architecture model
///
-XCoreTargetMachine::XCoreTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU,
- const std::string &FS)
- : LLVMTargetMachine(T, TT, CPU, FS),
+XCoreTargetMachine::XCoreTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM)
+ : LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
Subtarget(TT, CPU, FS),
DataLayout("e-p:32:32:32-a0:0:32-f32:32:32-f64:32:32-i1:8:32-i8:8:32-"
"i16:16:32-i32:32:32-i64:32:32-n32"),
diff --git a/lib/Target/XCore/XCoreTargetMachine.h b/lib/Target/XCore/XCoreTargetMachine.h
index 6235ac3..83d09d6d 100644
--- a/lib/Target/XCore/XCoreTargetMachine.h
+++ b/lib/Target/XCore/XCoreTargetMachine.h
@@ -32,8 +32,9 @@ class XCoreTargetMachine : public LLVMTargetMachine {
XCoreTargetLowering TLInfo;
XCoreSelectionDAGInfo TSInfo;
public:
- XCoreTargetMachine(const Target &T, const std::string &TT,
- const std::string &CPU, const std::string &FS);
+ XCoreTargetMachine(const Target &T, StringRef TT,
+ StringRef CPU, StringRef FS,
+ Reloc::Model RM, CodeModel::Model CM);
virtual const XCoreInstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const XCoreFrameLowering *getFrameLowering() const {
diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp
index fa007cf..e160f63 100644
--- a/lib/Transforms/IPO/ArgumentPromotion.cpp
+++ b/lib/Transforms/IPO/ArgumentPromotion.cpp
@@ -155,12 +155,12 @@ CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) {
for (unsigned i = 0; i != PointerArgs.size(); ++i) {
bool isByVal = F->paramHasAttr(PointerArgs[i].second+1, Attribute::ByVal);
Argument *PtrArg = PointerArgs[i].first;
- const Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType();
+ Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType();
// If this is a byval argument, and if the aggregate type is small, just
// pass the elements, which is always safe.
if (isByVal) {
- if (const StructType *STy = dyn_cast<StructType>(AgTy)) {
+ if (StructType *STy = dyn_cast<StructType>(AgTy)) {
if (maxElements > 0 && STy->getNumElements() > maxElements) {
DEBUG(dbgs() << "argpromotion disable promoting argument '"
<< PtrArg->getName() << "' because it would require adding more"
@@ -190,7 +190,7 @@ CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) {
// If the argument is a recursive type and we're in a recursive
// function, we could end up infinitely peeling the function argument.
if (isSelfRecursive) {
- if (const StructType *STy = dyn_cast<StructType>(AgTy)) {
+ if (StructType *STy = dyn_cast<StructType>(AgTy)) {
bool RecursiveType = false;
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
if (STy->getElementType(i) == PtrArg->getType()) {
@@ -382,7 +382,8 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg, bool isByVal) const {
User *U = *UI;
Operands.clear();
if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
- if (LI->isVolatile()) return false; // Don't hack volatile loads
+ // Don't hack volatile/atomic loads
+ if (!LI->isSimple()) return false;
Loads.push_back(LI);
// Direct loads are equivalent to a GEP with a zero index and then a load.
Operands.push_back(0);
@@ -410,7 +411,8 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg, bool isByVal) const {
for (Value::use_iterator UI = GEP->use_begin(), E = GEP->use_end();
UI != E; ++UI)
if (LoadInst *LI = dyn_cast<LoadInst>(*UI)) {
- if (LI->isVolatile()) return false; // Don't hack volatile loads
+ // Don't hack volatile/atomic loads
+ if (!LI->isSimple()) return false;
Loads.push_back(LI);
} else {
// Other uses than load?
@@ -492,7 +494,7 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F,
// Start by computing a new prototype for the function, which is the same as
// the old function, but has modified arguments.
- const FunctionType *FTy = F->getFunctionType();
+ FunctionType *FTy = F->getFunctionType();
std::vector<Type*> Params;
typedef std::set<IndicesVector> ScalarizeTable;
@@ -527,8 +529,8 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F,
++I, ++ArgIndex) {
if (ByValArgsToTransform.count(I)) {
// Simple byval argument? Just add all the struct element types.
- const Type *AgTy = cast<PointerType>(I->getType())->getElementType();
- const StructType *STy = cast<StructType>(AgTy);
+ Type *AgTy = cast<PointerType>(I->getType())->getElementType();
+ StructType *STy = cast<StructType>(AgTy);
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
Params.push_back(STy->getElementType(i));
++NumByValArgsPromoted;
@@ -576,9 +578,7 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F,
for (ScalarizeTable::iterator SI = ArgIndices.begin(),
E = ArgIndices.end(); SI != E; ++SI) {
// not allowed to dereference ->begin() if size() is 0
- Params.push_back(GetElementPtrInst::getIndexedType(I->getType(),
- SI->begin(),
- SI->end()));
+ Params.push_back(GetElementPtrInst::getIndexedType(I->getType(), *SI));
assert(Params.back());
}
@@ -593,7 +593,7 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F,
if (Attributes attrs = PAL.getFnAttributes())
AttributesVec.push_back(AttributeWithIndex::get(~0, attrs));
- const Type *RetTy = FTy->getReturnType();
+ Type *RetTy = FTy->getReturnType();
// Work around LLVM bug PR56: the CWriter cannot emit varargs functions which
// have zero fixed arguments.
@@ -662,13 +662,13 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F,
} else if (ByValArgsToTransform.count(I)) {
// Emit a GEP and load for each element of the struct.
- const Type *AgTy = cast<PointerType>(I->getType())->getElementType();
- const StructType *STy = cast<StructType>(AgTy);
+ Type *AgTy = cast<PointerType>(I->getType())->getElementType();
+ StructType *STy = cast<StructType>(AgTy);
Value *Idxs[2] = {
ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), 0 };
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i);
- Value *Idx = GetElementPtrInst::Create(*AI, Idxs, Idxs+2,
+ Value *Idx = GetElementPtrInst::Create(*AI, Idxs,
(*AI)->getName()+"."+utostr(i),
Call);
// TODO: Tell AA about the new values?
@@ -686,12 +686,12 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F,
LoadInst *OrigLoad = OriginalLoads[*SI];
if (!SI->empty()) {
Ops.reserve(SI->size());
- const Type *ElTy = V->getType();
+ Type *ElTy = V->getType();
for (IndicesVector::const_iterator II = SI->begin(),
IE = SI->end(); II != IE; ++II) {
// Use i32 to index structs, and i64 for others (pointers/arrays).
// This satisfies GEP constraints.
- const Type *IdxTy = (ElTy->isStructTy() ?
+ Type *IdxTy = (ElTy->isStructTy() ?
Type::getInt32Ty(F->getContext()) :
Type::getInt64Ty(F->getContext()));
Ops.push_back(ConstantInt::get(IdxTy, *II));
@@ -699,8 +699,7 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F,
ElTy = cast<CompositeType>(ElTy)->getTypeAtIndex(*II);
}
// And create a GEP to extract those indices.
- V = GetElementPtrInst::Create(V, Ops.begin(), Ops.end(),
- V->getName()+".idx", Call);
+ V = GetElementPtrInst::Create(V, Ops, V->getName()+".idx", Call);
Ops.clear();
AA.copyValue(OrigLoad->getOperand(0), V);
}
@@ -792,16 +791,16 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F,
Instruction *InsertPt = NF->begin()->begin();
// Just add all the struct element types.
- const Type *AgTy = cast<PointerType>(I->getType())->getElementType();
+ Type *AgTy = cast<PointerType>(I->getType())->getElementType();
Value *TheAlloca = new AllocaInst(AgTy, 0, "", InsertPt);
- const StructType *STy = cast<StructType>(AgTy);
+ StructType *STy = cast<StructType>(AgTy);
Value *Idxs[2] = {
ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), 0 };
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i);
Value *Idx =
- GetElementPtrInst::Create(TheAlloca, Idxs, Idxs+2,
+ GetElementPtrInst::Create(TheAlloca, Idxs,
TheAlloca->getName()+"."+Twine(i),
InsertPt);
I2->setName(I->getName()+"."+Twine(i));
diff --git a/lib/Transforms/IPO/CMakeLists.txt b/lib/Transforms/IPO/CMakeLists.txt
index 3de7bfc..4d8dbc2 100644
--- a/lib/Transforms/IPO/CMakeLists.txt
+++ b/lib/Transforms/IPO/CMakeLists.txt
@@ -13,10 +13,20 @@ add_llvm_library(LLVMipo
Inliner.cpp
Internalize.cpp
LoopExtractor.cpp
- LowerSetJmp.cpp
MergeFunctions.cpp
PartialInlining.cpp
+ PassManagerBuilder.cpp
PruneEH.cpp
StripDeadPrototypes.cpp
StripSymbols.cpp
)
+
+add_llvm_library_dependencies(LLVMipo
+ LLVMAnalysis
+ LLVMCore
+ LLVMScalarOpts
+ LLVMSupport
+ LLVMTarget
+ LLVMTransformUtils
+ LLVMipa
+ )
diff --git a/lib/Transforms/IPO/ConstantMerge.cpp b/lib/Transforms/IPO/ConstantMerge.cpp
index a21efce..c3ecb7a 100644
--- a/lib/Transforms/IPO/ConstantMerge.cpp
+++ b/lib/Transforms/IPO/ConstantMerge.cpp
@@ -23,7 +23,9 @@
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
+#include "llvm/Target/TargetData.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;
@@ -37,10 +39,18 @@ namespace {
initializeConstantMergePass(*PassRegistry::getPassRegistry());
}
- // run - For this pass, process all of the globals in the module,
- // eliminating duplicate constants.
- //
+ // For this pass, process all of the globals in the module, eliminating
+ // duplicate constants.
bool runOnModule(Module &M);
+
+ // Return true iff we can determine the alignment of this global variable.
+ bool hasKnownAlignment(GlobalVariable *GV) const;
+
+ // Return the alignment of the global, including converting the default
+ // alignment to a concrete value.
+ unsigned getAlignment(GlobalVariable *GV) const;
+
+ const TargetData *TD;
};
}
@@ -77,15 +87,28 @@ static bool IsBetterCannonical(const GlobalVariable &A,
return A.hasUnnamedAddr();
}
+bool ConstantMerge::hasKnownAlignment(GlobalVariable *GV) const {
+ return TD || GV->getAlignment() != 0;
+}
+
+unsigned ConstantMerge::getAlignment(GlobalVariable *GV) const {
+ if (TD)
+ return TD->getPreferredAlignment(GV);
+ return GV->getAlignment();
+}
+
bool ConstantMerge::runOnModule(Module &M) {
+ TD = getAnalysisIfAvailable<TargetData>();
+
// Find all the globals that are marked "used". These cannot be merged.
SmallPtrSet<const GlobalValue*, 8> UsedGlobals;
FindUsedValues(M.getGlobalVariable("llvm.used"), UsedGlobals);
FindUsedValues(M.getGlobalVariable("llvm.compiler.used"), UsedGlobals);
- // Map unique constant/section pairs to globals. We don't want to merge
- // globals in different sections.
- DenseMap<Constant*, GlobalVariable*> CMap;
+ // Map unique <constants, has-unknown-alignment> pairs to globals. We don't
+ // want to merge globals of unknown alignment with those of explicit
+ // alignment. If we have TargetData, we always know the alignment.
+ DenseMap<PointerIntPair<Constant*, 1, bool>, GlobalVariable*> CMap;
// Replacements - This vector contains a list of replacements to perform.
SmallVector<std::pair<GlobalVariable*, GlobalVariable*>, 32> Replacements;
@@ -120,7 +143,8 @@ bool ConstantMerge::runOnModule(Module &M) {
Constant *Init = GV->getInitializer();
// Check to see if the initializer is already known.
- GlobalVariable *&Slot = CMap[Init];
+ PointerIntPair<Constant*, 1, bool> Pair(Init, hasKnownAlignment(GV));
+ GlobalVariable *&Slot = CMap[Pair];
// If this is the first constant we find or if the old on is local,
// replace with the current one. It the current is externally visible
@@ -152,7 +176,8 @@ bool ConstantMerge::runOnModule(Module &M) {
Constant *Init = GV->getInitializer();
// Check to see if the initializer is already known.
- GlobalVariable *Slot = CMap[Init];
+ PointerIntPair<Constant*, 1, bool> Pair(Init, hasKnownAlignment(GV));
+ GlobalVariable *Slot = CMap[Pair];
if (!Slot || Slot == GV)
continue;
@@ -175,6 +200,14 @@ bool ConstantMerge::runOnModule(Module &M) {
// now. This avoid invalidating the pointers in CMap, which are unneeded
// now.
for (unsigned i = 0, e = Replacements.size(); i != e; ++i) {
+ // Bump the alignment if necessary.
+ if (Replacements[i].first->getAlignment() ||
+ Replacements[i].second->getAlignment()) {
+ Replacements[i].second->setAlignment(std::max(
+ Replacements[i].first->getAlignment(),
+ Replacements[i].second->getAlignment()));
+ }
+
// Eliminate any uses of the dead global.
Replacements[i].first->replaceAllUsesWith(Replacements[i].second);
diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp
index 1517765..4bb6f7a 100644
--- a/lib/Transforms/IPO/DeadArgumentElimination.cpp
+++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp
@@ -206,7 +206,7 @@ bool DAE::DeleteDeadVarargs(Function &Fn) {
// Start by computing a new prototype for the function, which is the same as
// the old function, but doesn't have isVarArg set.
- const FunctionType *FTy = Fn.getFunctionType();
+ FunctionType *FTy = Fn.getFunctionType();
std::vector<Type*> Params(FTy->param_begin(), FTy->param_end());
FunctionType *NFTy = FunctionType::get(FTy->getReturnType(),
@@ -344,7 +344,7 @@ bool DAE::RemoveDeadArgumentsFromCallers(Function &Fn)
static unsigned NumRetVals(const Function *F) {
if (F->getReturnType()->isVoidTy())
return 0;
- else if (const StructType *STy = dyn_cast<StructType>(F->getReturnType()))
+ else if (StructType *STy = dyn_cast<StructType>(F->getReturnType()))
return STy->getNumElements();
else
return 1;
@@ -491,7 +491,7 @@ void DAE::SurveyFunction(const Function &F) {
// Keep track of the number of live retvals, so we can skip checks once all
// of them turn out to be live.
unsigned NumLiveRetVals = 0;
- const Type *STy = dyn_cast<StructType>(F.getReturnType());
+ Type *STy = dyn_cast<StructType>(F.getReturnType());
// Loop all uses of the function.
for (Value::const_use_iterator I = F.use_begin(), E = F.use_end();
I != E; ++I) {
@@ -646,7 +646,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) {
// Start by computing a new prototype for the function, which is the same as
// the old function, but has fewer arguments and a different return type.
- const FunctionType *FTy = F->getFunctionType();
+ FunctionType *FTy = F->getFunctionType();
std::vector<Type*> Params;
// Set up to build a new list of parameter attributes.
@@ -660,7 +660,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) {
// Find out the new return value.
Type *RetTy = FTy->getReturnType();
- const Type *NRetTy = NULL;
+ Type *NRetTy = NULL;
unsigned RetCount = NumRetVals(F);
// -1 means unused, other numbers are the new index
@@ -669,7 +669,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) {
if (RetTy->isVoidTy()) {
NRetTy = RetTy;
} else {
- const StructType *STy = dyn_cast<StructType>(RetTy);
+ StructType *STy = dyn_cast<StructType>(RetTy);
if (STy)
// Look at each of the original return values individually.
for (unsigned i = 0; i != RetCount; ++i) {
diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp
index 95decec..0edf342 100644
--- a/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -163,14 +163,14 @@ bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) {
ReadsMemory = true;
continue;
} else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
- // Ignore non-volatile loads from local memory.
+ // Ignore non-volatile loads from local memory. (Atomic is okay here.)
if (!LI->isVolatile()) {
AliasAnalysis::Location Loc = AA->getLocation(LI);
if (AA->pointsToConstantMemory(Loc, /*OrLocal=*/true))
continue;
}
} else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
- // Ignore non-volatile stores to local memory.
+ // Ignore non-volatile stores to local memory. (Atomic is okay here.)
if (!SI->isVolatile()) {
AliasAnalysis::Location Loc = AA->getLocation(SI);
if (AA->pointsToConstantMemory(Loc, /*OrLocal=*/true))
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp
index 4ac721d..3552d03 100644
--- a/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/lib/Transforms/IPO/GlobalOpt.cpp
@@ -195,12 +195,14 @@ static bool AnalyzeGlobal(const Value *V, GlobalStatus &GS,
}
if (const LoadInst *LI = dyn_cast<LoadInst>(I)) {
GS.isLoaded = true;
- if (LI->isVolatile()) return true; // Don't hack on volatile loads.
+ // Don't hack on volatile/atomic loads.
+ if (!LI->isSimple()) return true;
} else if (const StoreInst *SI = dyn_cast<StoreInst>(I)) {
// Don't allow a store OF the address, only stores TO the address.
if (SI->getOperand(0) == V) return true;
- if (SI->isVolatile()) return true; // Don't hack on volatile stores.
+ // Don't hack on volatile/atomic stores.
+ if (!SI->isSimple()) return true;
// If this is a direct store to the global (i.e., the global is a scalar
// value, not an aggregate), keep more specific information about
@@ -281,18 +283,18 @@ static Constant *getAggregateConstantElement(Constant *Agg, Constant *Idx) {
} else if (ConstantVector *CP = dyn_cast<ConstantVector>(Agg)) {
if (IdxV < CP->getNumOperands()) return CP->getOperand(IdxV);
} else if (isa<ConstantAggregateZero>(Agg)) {
- if (const StructType *STy = dyn_cast<StructType>(Agg->getType())) {
+ if (StructType *STy = dyn_cast<StructType>(Agg->getType())) {
if (IdxV < STy->getNumElements())
return Constant::getNullValue(STy->getElementType(IdxV));
- } else if (const SequentialType *STy =
+ } else if (SequentialType *STy =
dyn_cast<SequentialType>(Agg->getType())) {
return Constant::getNullValue(STy->getElementType());
}
} else if (isa<UndefValue>(Agg)) {
- if (const StructType *STy = dyn_cast<StructType>(Agg->getType())) {
+ if (StructType *STy = dyn_cast<StructType>(Agg->getType())) {
if (IdxV < STy->getNumElements())
return UndefValue::get(STy->getElementType(IdxV));
- } else if (const SequentialType *STy =
+ } else if (SequentialType *STy =
dyn_cast<SequentialType>(Agg->getType())) {
return UndefValue::get(STy->getElementType());
}
@@ -430,7 +432,7 @@ static bool IsUserOfGlobalSafeForSRA(User *U, GlobalValue *GV) {
++GEPI; // Skip over the pointer index.
// If this is a use of an array allocation, do a bit more checking for sanity.
- if (const ArrayType *AT = dyn_cast<ArrayType>(*GEPI)) {
+ if (ArrayType *AT = dyn_cast<ArrayType>(*GEPI)) {
uint64_t NumElements = AT->getNumElements();
ConstantInt *Idx = cast<ConstantInt>(U->getOperand(2));
@@ -451,9 +453,9 @@ static bool IsUserOfGlobalSafeForSRA(User *U, GlobalValue *GV) {
GEPI != E;
++GEPI) {
uint64_t NumElements;
- if (const ArrayType *SubArrayTy = dyn_cast<ArrayType>(*GEPI))
+ if (ArrayType *SubArrayTy = dyn_cast<ArrayType>(*GEPI))
NumElements = SubArrayTy->getNumElements();
- else if (const VectorType *SubVectorTy = dyn_cast<VectorType>(*GEPI))
+ else if (VectorType *SubVectorTy = dyn_cast<VectorType>(*GEPI))
NumElements = SubVectorTy->getNumElements();
else {
assert((*GEPI)->isStructTy() &&
@@ -498,7 +500,7 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const TargetData &TD) {
assert(GV->hasLocalLinkage() && !GV->isConstant());
Constant *Init = GV->getInitializer();
- const Type *Ty = Init->getType();
+ Type *Ty = Init->getType();
std::vector<GlobalVariable*> NewGlobals;
Module::GlobalListType &Globals = GV->getParent()->getGlobalList();
@@ -508,7 +510,7 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const TargetData &TD) {
if (StartAlignment == 0)
StartAlignment = TD.getABITypeAlignment(GV->getType());
- if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+ if (StructType *STy = dyn_cast<StructType>(Ty)) {
NewGlobals.reserve(STy->getNumElements());
const StructLayout &Layout = *TD.getStructLayout(STy);
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
@@ -531,9 +533,9 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const TargetData &TD) {
if (NewAlign > TD.getABITypeAlignment(STy->getElementType(i)))
NGV->setAlignment(NewAlign);
}
- } else if (const SequentialType *STy = dyn_cast<SequentialType>(Ty)) {
+ } else if (SequentialType *STy = dyn_cast<SequentialType>(Ty)) {
unsigned NumElements = 0;
- if (const ArrayType *ATy = dyn_cast<ArrayType>(STy))
+ if (ArrayType *ATy = dyn_cast<ArrayType>(STy))
NumElements = ATy->getNumElements();
else
NumElements = cast<VectorType>(STy)->getNumElements();
@@ -596,15 +598,14 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const TargetData &TD) {
Idxs.push_back(NullInt);
for (unsigned i = 3, e = CE->getNumOperands(); i != e; ++i)
Idxs.push_back(CE->getOperand(i));
- NewPtr = ConstantExpr::getGetElementPtr(cast<Constant>(NewPtr),
- &Idxs[0], Idxs.size());
+ NewPtr = ConstantExpr::getGetElementPtr(cast<Constant>(NewPtr), Idxs);
} else {
GetElementPtrInst *GEPI = cast<GetElementPtrInst>(GEP);
SmallVector<Value*, 8> Idxs;
Idxs.push_back(NullInt);
for (unsigned i = 3, e = GEPI->getNumOperands(); i != e; ++i)
Idxs.push_back(GEPI->getOperand(i));
- NewPtr = GetElementPtrInst::Create(NewPtr, Idxs.begin(), Idxs.end(),
+ NewPtr = GetElementPtrInst::Create(NewPtr, Idxs,
GEPI->getName()+"."+Twine(Val),GEPI);
}
}
@@ -753,8 +754,7 @@ static bool OptimizeAwayTrappingUsesOfValue(Value *V, Constant *NewV) {
break;
if (Idxs.size() == GEPI->getNumOperands()-1)
Changed |= OptimizeAwayTrappingUsesOfValue(GEPI,
- ConstantExpr::getGetElementPtr(NewV, &Idxs[0],
- Idxs.size()));
+ ConstantExpr::getGetElementPtr(NewV, Idxs));
if (GEPI->use_empty()) {
Changed = true;
GEPI->eraseFromParent();
@@ -846,12 +846,12 @@ static void ConstantPropUsersOf(Value *V) {
/// malloc into a global, and any loads of GV as uses of the new global.
static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV,
CallInst *CI,
- const Type *AllocTy,
+ Type *AllocTy,
ConstantInt *NElements,
TargetData* TD) {
DEBUG(errs() << "PROMOTING GLOBAL: " << *GV << " CALL = " << *CI << '\n');
- const Type *GlobalType;
+ Type *GlobalType;
if (NElements->getZExtValue() == 1)
GlobalType = AllocTy;
else
@@ -1192,7 +1192,7 @@ static Value *GetHeapSROAValue(Value *V, unsigned FieldNo,
} else if (PHINode *PN = dyn_cast<PHINode>(V)) {
// PN's type is pointer to struct. Make a new PHI of pointer to struct
// field.
- const StructType *ST =
+ StructType *ST =
cast<StructType>(cast<PointerType>(PN->getType())->getElementType());
PHINode *NewPN =
@@ -1245,8 +1245,7 @@ static void RewriteHeapSROALoadUser(Instruction *LoadUser,
GEPIdx.push_back(GEPI->getOperand(1));
GEPIdx.append(GEPI->op_begin()+3, GEPI->op_end());
- Value *NGEPI = GetElementPtrInst::Create(NewPtr,
- GEPIdx.begin(), GEPIdx.end(),
+ Value *NGEPI = GetElementPtrInst::Create(NewPtr, GEPIdx,
GEPI->getName(), GEPI);
GEPI->replaceAllUsesWith(NGEPI);
GEPI->eraseFromParent();
@@ -1260,11 +1259,9 @@ static void RewriteHeapSROALoadUser(Instruction *LoadUser,
// already been seen first by another load, so its uses have already been
// processed.
PHINode *PN = cast<PHINode>(LoadUser);
- bool Inserted;
- DenseMap<Value*, std::vector<Value*> >::iterator InsertPos;
- tie(InsertPos, Inserted) =
- InsertedScalarizedValues.insert(std::make_pair(PN, std::vector<Value*>()));
- if (!Inserted) return;
+ if (!InsertedScalarizedValues.insert(std::make_pair(PN,
+ std::vector<Value*>())).second)
+ return;
// If this is the first time we've seen this PHI, recursively process all
// users.
@@ -1298,8 +1295,8 @@ static void RewriteUsesOfLoadForHeapSRoA(LoadInst *Load,
static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI,
Value* NElems, TargetData *TD) {
DEBUG(dbgs() << "SROA HEAP ALLOC: " << *GV << " MALLOC = " << *CI << '\n');
- const Type* MAT = getMallocAllocatedType(CI);
- const StructType *STy = cast<StructType>(MAT);
+ Type* MAT = getMallocAllocatedType(CI);
+ StructType *STy = cast<StructType>(MAT);
// There is guaranteed to be at least one use of the malloc (storing
// it into GV). If there are other uses, change them to be uses of
@@ -1313,8 +1310,8 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI,
std::vector<Value*> FieldMallocs;
for (unsigned FieldNo = 0, e = STy->getNumElements(); FieldNo != e;++FieldNo){
- const Type *FieldTy = STy->getElementType(FieldNo);
- const PointerType *PFieldTy = PointerType::getUnqual(FieldTy);
+ Type *FieldTy = STy->getElementType(FieldNo);
+ PointerType *PFieldTy = PointerType::getUnqual(FieldTy);
GlobalVariable *NGV =
new GlobalVariable(*GV->getParent(),
@@ -1325,9 +1322,9 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI,
FieldGlobals.push_back(NGV);
unsigned TypeSize = TD->getTypeAllocSize(FieldTy);
- if (const StructType *ST = dyn_cast<StructType>(FieldTy))
+ if (StructType *ST = dyn_cast<StructType>(FieldTy))
TypeSize = TD->getStructLayout(ST)->getSizeInBytes();
- const Type *IntPtrTy = TD->getIntPtrType(CI->getContext());
+ Type *IntPtrTy = TD->getIntPtrType(CI->getContext());
Value *NMI = CallInst::CreateMalloc(CI, IntPtrTy, FieldTy,
ConstantInt::get(IntPtrTy, TypeSize),
NElems, 0,
@@ -1379,8 +1376,7 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI,
for (unsigned i = 0, e = FieldGlobals.size(); i != e; ++i) {
Value *GVVal = new LoadInst(FieldGlobals[i], "tmp", NullPtrBlock);
Value *Cmp = new ICmpInst(*NullPtrBlock, ICmpInst::ICMP_NE, GVVal,
- Constant::getNullValue(GVVal->getType()),
- "tmp");
+ Constant::getNullValue(GVVal->getType()));
BasicBlock *FreeBlock = BasicBlock::Create(Cmp->getContext(), "free_it",
OrigBB->getParent());
BasicBlock *NextBlock = BasicBlock::Create(Cmp->getContext(), "next",
@@ -1428,7 +1424,7 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI,
// Insert a store of null into each global.
for (unsigned i = 0, e = FieldGlobals.size(); i != e; ++i) {
- const PointerType *PT = cast<PointerType>(FieldGlobals[i]->getType());
+ PointerType *PT = cast<PointerType>(FieldGlobals[i]->getType());
Constant *Null = Constant::getNullValue(PT->getElementType());
new StoreInst(Null, FieldGlobals[i], SI);
}
@@ -1485,7 +1481,7 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI,
/// cast of malloc.
static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV,
CallInst *CI,
- const Type *AllocTy,
+ Type *AllocTy,
Module::global_iterator &GVI,
TargetData *TD) {
if (!TD)
@@ -1538,10 +1534,10 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV,
// If this is an allocation of a fixed size array of structs, analyze as a
// variable size array. malloc [100 x struct],1 -> malloc struct, 100
if (NElems == ConstantInt::get(CI->getArgOperand(0)->getType(), 1))
- if (const ArrayType *AT = dyn_cast<ArrayType>(AllocTy))
+ if (ArrayType *AT = dyn_cast<ArrayType>(AllocTy))
AllocTy = AT->getElementType();
- const StructType *AllocSTy = dyn_cast<StructType>(AllocTy);
+ StructType *AllocSTy = dyn_cast<StructType>(AllocTy);
if (!AllocSTy)
return false;
@@ -1552,8 +1548,8 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV,
// If this is a fixed size array, transform the Malloc to be an alloc of
// structs. malloc [100 x struct],1 -> malloc struct, 100
- if (const ArrayType *AT = dyn_cast<ArrayType>(getMallocAllocatedType(CI))) {
- const Type *IntPtrTy = TD->getIntPtrType(CI->getContext());
+ if (ArrayType *AT = dyn_cast<ArrayType>(getMallocAllocatedType(CI))) {
+ Type *IntPtrTy = TD->getIntPtrType(CI->getContext());
unsigned TypeSize = TD->getStructLayout(AllocSTy)->getSizeInBytes();
Value *AllocSize = ConstantInt::get(IntPtrTy, TypeSize);
Value *NumElements = ConstantInt::get(IntPtrTy, AT->getNumElements());
@@ -1596,7 +1592,7 @@ static bool OptimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal,
if (OptimizeAwayTrappingUsesOfLoads(GV, SOVC))
return true;
} else if (CallInst *CI = extractMallocCall(StoredOnceVal)) {
- const Type* MallocType = getMallocAllocatedType(CI);
+ Type* MallocType = getMallocAllocatedType(CI);
if (MallocType && TryToOptimizeStoreOfMallocToGlobal(GV, CI, MallocType,
GVI, TD))
return true;
@@ -1611,7 +1607,7 @@ static bool OptimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal,
/// can shrink the global into a boolean and select between the two values
/// whenever it is used. This exposes the values to other scalar optimizations.
static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) {
- const Type *GVElType = GV->getType()->getElementType();
+ Type *GVElType = GV->getType()->getElementType();
// If GVElType is already i1, it is already shrunk. If the type of the GV is
// an FP value, pointer or vector, don't do this optimization because a select
@@ -1761,7 +1757,7 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV,
DEBUG(dbgs() << "LOCALIZING GLOBAL: " << *GV);
Instruction& FirstI = const_cast<Instruction&>(*GS.AccessingFunction
->getEntryBlock().begin());
- const Type* ElemTy = GV->getType()->getElementType();
+ Type* ElemTy = GV->getType()->getElementType();
// FIXME: Pass Global's alignment when globals have alignment
AllocaInst* Alloca = new AllocaInst(ElemTy, NULL, GV->getName(), &FirstI);
if (!isa<UndefValue>(GV->getInitializer()))
@@ -2003,7 +1999,7 @@ static GlobalVariable *InstallGlobalCtors(GlobalVariable *GCL,
CSVals[0] = ConstantInt::get(Type::getInt32Ty(GCL->getContext()), 65535);
CSVals[1] = 0;
- const StructType *StructTy =
+ StructType *StructTy =
cast <StructType>(
cast<ArrayType>(GCL->getType()->getElementType())->getElementType());
@@ -2013,9 +2009,9 @@ static GlobalVariable *InstallGlobalCtors(GlobalVariable *GCL,
if (Ctors[i]) {
CSVals[1] = Ctors[i];
} else {
- const Type *FTy = FunctionType::get(Type::getVoidTy(GCL->getContext()),
+ Type *FTy = FunctionType::get(Type::getVoidTy(GCL->getContext()),
false);
- const PointerType *PFTy = PointerType::getUnqual(FTy);
+ PointerType *PFTy = PointerType::getUnqual(FTy);
CSVals[1] = Constant::getNullValue(PFTy);
CSVals[0] = ConstantInt::get(Type::getInt32Ty(GCL->getContext()),
0x7fffffff);
@@ -2196,7 +2192,7 @@ static Constant *EvaluateStoreInto(Constant *Init, Constant *Val,
}
std::vector<Constant*> Elts;
- if (const StructType *STy = dyn_cast<StructType>(Init->getType())) {
+ if (StructType *STy = dyn_cast<StructType>(Init->getType())) {
// Break up the constant into its elements.
if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Init)) {
@@ -2224,10 +2220,10 @@ static Constant *EvaluateStoreInto(Constant *Init, Constant *Val,
}
ConstantInt *CI = cast<ConstantInt>(Addr->getOperand(OpNo));
- const SequentialType *InitTy = cast<SequentialType>(Init->getType());
+ SequentialType *InitTy = cast<SequentialType>(Init->getType());
uint64_t NumElts;
- if (const ArrayType *ATy = dyn_cast<ArrayType>(InitTy))
+ if (ArrayType *ATy = dyn_cast<ArrayType>(InitTy))
NumElts = ATy->getNumElements();
else
NumElts = cast<VectorType>(InitTy)->getNumElements();
@@ -2338,7 +2334,7 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
Constant *InstResult = 0;
if (StoreInst *SI = dyn_cast<StoreInst>(CurInst)) {
- if (SI->isVolatile()) return false; // no volatile accesses.
+ if (!SI->isSimple()) return false; // no volatile/atomic accesses.
Constant *Ptr = getVal(Values, SI->getOperand(1));
if (!isSimpleEnoughPointerToCommit(Ptr))
// If this is too complex for us to commit, reject it.
@@ -2358,7 +2354,7 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
// stored value.
Ptr = CE->getOperand(0);
- const Type *NewTy=cast<PointerType>(Ptr->getType())->getElementType();
+ Type *NewTy=cast<PointerType>(Ptr->getType())->getElementType();
// In order to push the bitcast onto the stored value, a bitcast
// from NewTy to Val's type must be legal. If it's not, we can try
@@ -2367,14 +2363,14 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
// If NewTy is a struct, we can convert the pointer to the struct
// into a pointer to its first member.
// FIXME: This could be extended to support arrays as well.
- if (const StructType *STy = dyn_cast<StructType>(NewTy)) {
+ if (StructType *STy = dyn_cast<StructType>(NewTy)) {
NewTy = STy->getTypeAtIndex(0U);
- const IntegerType *IdxTy =IntegerType::get(NewTy->getContext(), 32);
+ IntegerType *IdxTy =IntegerType::get(NewTy->getContext(), 32);
Constant *IdxZero = ConstantInt::get(IdxTy, 0, false);
Constant * const IdxList[] = {IdxZero, IdxZero};
- Ptr = ConstantExpr::getGetElementPtr(Ptr, IdxList, 2);
+ Ptr = ConstantExpr::getGetElementPtr(Ptr, IdxList);
// If we can't improve the situation by introspecting NewTy,
// we have to give up.
@@ -2411,17 +2407,17 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end();
i != e; ++i)
GEPOps.push_back(getVal(Values, *i));
- InstResult = cast<GEPOperator>(GEP)->isInBounds() ?
- ConstantExpr::getInBoundsGetElementPtr(P, &GEPOps[0], GEPOps.size()) :
- ConstantExpr::getGetElementPtr(P, &GEPOps[0], GEPOps.size());
+ InstResult =
+ ConstantExpr::getGetElementPtr(P, GEPOps,
+ cast<GEPOperator>(GEP)->isInBounds());
} else if (LoadInst *LI = dyn_cast<LoadInst>(CurInst)) {
- if (LI->isVolatile()) return false; // no volatile accesses.
+ if (!LI->isSimple()) return false; // no volatile/atomic accesses.
InstResult = ComputeLoadResult(getVal(Values, LI->getOperand(0)),
MutatedMemory);
if (InstResult == 0) return false; // Could not evaluate load.
} else if (AllocaInst *AI = dyn_cast<AllocaInst>(CurInst)) {
if (AI->isArrayAllocation()) return false; // Cannot handle array allocs.
- const Type *Ty = AI->getType()->getElementType();
+ Type *Ty = AI->getType()->getElementType();
AllocaTmps.push_back(new GlobalVariable(Ty, false,
GlobalValue::InternalLinkage,
UndefValue::get(Ty),
@@ -2465,8 +2461,7 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
if (Callee->isDeclaration()) {
// If this is a function we can constant fold, do it.
- if (Constant *C = ConstantFoldCall(Callee, Formals.data(),
- Formals.size())) {
+ if (Constant *C = ConstantFoldCall(Callee, Formals)) {
InstResult = C;
} else {
return false;
@@ -2512,7 +2507,7 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,
CallStack.pop_back(); // return from fn.
return true; // We succeeded at evaluating this ctor!
} else {
- // invoke, unwind, unreachable.
+ // invoke, unwind, resume, unreachable.
return false; // Cannot handle this terminator.
}
@@ -2711,7 +2706,7 @@ static Function *FindCXAAtExit(Module &M) {
if (!Fn)
return 0;
- const FunctionType *FTy = Fn->getFunctionType();
+ FunctionType *FTy = Fn->getFunctionType();
// Checking that the function has the right return type, the right number of
// parameters and that they all have pointer types should be enough.
diff --git a/lib/Transforms/IPO/IPConstantPropagation.cpp b/lib/Transforms/IPO/IPConstantPropagation.cpp
index 25c0134..d757e1f 100644
--- a/lib/Transforms/IPO/IPConstantPropagation.cpp
+++ b/lib/Transforms/IPO/IPConstantPropagation.cpp
@@ -167,7 +167,7 @@ bool IPCP::PropagateConstantReturn(Function &F) {
// Check to see if this function returns a constant.
SmallVector<Value *,4> RetVals;
- const StructType *STy = dyn_cast<StructType>(F.getReturnType());
+ StructType *STy = dyn_cast<StructType>(F.getReturnType());
if (STy)
for (unsigned i = 0, e = STy->getNumElements(); i < e; ++i)
RetVals.push_back(UndefValue::get(STy->getElementType(i)));
diff --git a/lib/Transforms/IPO/IPO.cpp b/lib/Transforms/IPO/IPO.cpp
index 31ce95f..6233922 100644
--- a/lib/Transforms/IPO/IPO.cpp
+++ b/lib/Transforms/IPO/IPO.cpp
@@ -13,6 +13,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm-c/Initialization.h"
#include "llvm-c/Transforms/IPO.h"
#include "llvm/InitializePasses.h"
#include "llvm/PassManager.h"
@@ -35,7 +36,6 @@ void llvm::initializeIPO(PassRegistry &Registry) {
initializeLoopExtractorPass(Registry);
initializeBlockExtractorPassPass(Registry);
initializeSingleLoopExtractorPass(Registry);
- initializeLowerSetJmpPass(Registry);
initializeMergeFunctionsPass(Registry);
initializePartialInlinerPass(Registry);
initializePruneEHPass(Registry);
@@ -70,6 +70,10 @@ void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createFunctionInliningPass());
}
+void LLVMAddAlwaysInlinerPass(LLVMPassManagerRef PM) {
+ unwrap(PM)->add(llvm::createAlwaysInlinerPass());
+}
+
void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createGlobalDCEPass());
}
@@ -82,10 +86,6 @@ void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createIPConstantPropagationPass());
}
-void LLVMAddLowerSetJmpPass(LLVMPassManagerRef PM) {
- unwrap(PM)->add(createLowerSetJmpPass());
-}
-
void LLVMAddPruneEHPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createPruneEHPass());
}
@@ -98,11 +98,6 @@ void LLVMAddInternalizePass(LLVMPassManagerRef PM, unsigned AllButMain) {
unwrap(PM)->add(createInternalizePass(AllButMain != 0));
}
-
-void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM) {
- // FIXME: Remove in LLVM 3.0.
-}
-
void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createStripDeadPrototypesPass());
}
diff --git a/lib/Transforms/IPO/InlineAlways.cpp b/lib/Transforms/IPO/InlineAlways.cpp
index ce795b7..c0426da 100644
--- a/lib/Transforms/IPO/InlineAlways.cpp
+++ b/lib/Transforms/IPO/InlineAlways.cpp
@@ -23,6 +23,7 @@
#include "llvm/Support/CallSite.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/InlinerPass.h"
+#include "llvm/Target/TargetData.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;
@@ -32,10 +33,10 @@ namespace {
// AlwaysInliner only inlines functions that are mark as "always inline".
class AlwaysInliner : public Inliner {
// Functions that are never inlined
- SmallPtrSet<const Function*, 16> NeverInline;
+ SmallPtrSet<const Function*, 16> NeverInline;
InlineCostAnalyzer CA;
public:
- // Use extremely low threshold.
+ // Use extremely low threshold.
AlwaysInliner() : Inliner(ID, -2000000000) {
initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry());
}
@@ -52,8 +53,8 @@ namespace {
void growCachedCostInfo(Function* Caller, Function* Callee) {
CA.growCachedCostInfo(Caller, Callee);
}
- virtual bool doFinalization(CallGraph &CG) {
- return removeDeadFunctions(CG, &NeverInline);
+ virtual bool doFinalization(CallGraph &CG) {
+ return removeDeadFunctions(CG, &NeverInline);
}
virtual bool doInitialization(CallGraph &CG);
void releaseMemory() {
@@ -71,11 +72,13 @@ INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); }
-// doInitialization - Initializes the vector of functions that have not
+// doInitialization - Initializes the vector of functions that have not
// been annotated with the "always inline" attribute.
bool AlwaysInliner::doInitialization(CallGraph &CG) {
+ CA.setTargetData(getAnalysisIfAvailable<TargetData>());
+
Module &M = CG.getModule();
-
+
for (Module::iterator I = M.begin(), E = M.end();
I != E; ++I)
if (!I->isDeclaration() && !I->hasFnAttr(Attribute::AlwaysInline))
diff --git a/lib/Transforms/IPO/InlineSimple.cpp b/lib/Transforms/IPO/InlineSimple.cpp
index 0c5b3be..84dd4fd 100644
--- a/lib/Transforms/IPO/InlineSimple.cpp
+++ b/lib/Transforms/IPO/InlineSimple.cpp
@@ -22,6 +22,7 @@
#include "llvm/Support/CallSite.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/InlinerPass.h"
+#include "llvm/Target/TargetData.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;
@@ -30,7 +31,7 @@ namespace {
class SimpleInliner : public Inliner {
// Functions that are never inlined
- SmallPtrSet<const Function*, 16> NeverInline;
+ SmallPtrSet<const Function*, 16> NeverInline;
InlineCostAnalyzer CA;
public:
SimpleInliner() : Inliner(ID) {
@@ -68,16 +69,17 @@ INITIALIZE_PASS_END(SimpleInliner, "inline",
Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); }
-Pass *llvm::createFunctionInliningPass(int Threshold) {
+Pass *llvm::createFunctionInliningPass(int Threshold) {
return new SimpleInliner(Threshold);
}
// doInitialization - Initializes the vector of functions that have been
// annotated with the noinline attribute.
bool SimpleInliner::doInitialization(CallGraph &CG) {
-
+ CA.setTargetData(getAnalysisIfAvailable<TargetData>());
+
Module &M = CG.getModule();
-
+
for (Module::iterator I = M.begin(), E = M.end();
I != E; ++I)
if (!I->isDeclaration() && I->hasFnAttr(Attribute::NoInline))
@@ -85,34 +87,34 @@ bool SimpleInliner::doInitialization(CallGraph &CG) {
// Get llvm.noinline
GlobalVariable *GV = M.getNamedGlobal("llvm.noinline");
-
+
if (GV == 0)
return false;
// Don't crash on invalid code
if (!GV->hasDefinitiveInitializer())
return false;
-
+
const ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
-
+
if (InitList == 0)
return false;
// Iterate over each element and add to the NeverInline set
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
-
+
// Get Source
const Constant *Elt = InitList->getOperand(i);
-
+
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(Elt))
- if (CE->getOpcode() == Instruction::BitCast)
+ if (CE->getOpcode() == Instruction::BitCast)
Elt = CE->getOperand(0);
-
+
// Insert into set of functions to never inline
if (const Function *F = dyn_cast<Function>(Elt))
NeverInline.insert(F);
}
-
+
return false;
}
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp
index 57f3e77..f00935b 100644
--- a/lib/Transforms/IPO/Inliner.cpp
+++ b/lib/Transforms/IPO/Inliner.cpp
@@ -62,7 +62,7 @@ void Inliner::getAnalysisUsage(AnalysisUsage &Info) const {
}
-typedef DenseMap<const ArrayType*, std::vector<AllocaInst*> >
+typedef DenseMap<ArrayType*, std::vector<AllocaInst*> >
InlinedArrayAllocasTy;
/// InlineCallIfPossible - If it is possible to inline the specified call site,
@@ -139,7 +139,7 @@ static bool InlineCallIfPossible(CallSite CS, InlineFunctionInfo &IFI,
// Don't bother trying to merge array allocations (they will usually be
// canonicalized to be an allocation *of* an array), or allocations whose
// type is not itself an array (because we're afraid of pessimizing SRoA).
- const ArrayType *ATy = dyn_cast<ArrayType>(AI->getAllocatedType());
+ ArrayType *ATy = dyn_cast<ArrayType>(AI->getAllocatedType());
if (ATy == 0 || AI->isArrayAllocation())
continue;
diff --git a/lib/Transforms/IPO/LoopExtractor.cpp b/lib/Transforms/IPO/LoopExtractor.cpp
index 848944d..4f96afe4 100644
--- a/lib/Transforms/IPO/LoopExtractor.cpp
+++ b/lib/Transforms/IPO/LoopExtractor.cpp
@@ -23,6 +23,7 @@
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/FunctionUtils.h"
#include "llvm/ADT/Statistic.h"
#include <fstream>
@@ -53,12 +54,12 @@ namespace {
char LoopExtractor::ID = 0;
INITIALIZE_PASS_BEGIN(LoopExtractor, "loop-extract",
- "Extract loops into new functions", false, false)
+ "Extract loops into new functions", false, false)
INITIALIZE_PASS_DEPENDENCY(BreakCriticalEdges)
INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
INITIALIZE_PASS_DEPENDENCY(DominatorTree)
INITIALIZE_PASS_END(LoopExtractor, "loop-extract",
- "Extract loops into new functions", false, false)
+ "Extract loops into new functions", false, false)
namespace {
/// SingleLoopExtractor - For bugpoint.
@@ -100,9 +101,9 @@ bool LoopExtractor::runOnLoop(Loop *L, LPPassManager &LPM) {
L->getHeader()->getParent()->getEntryBlock().getTerminator();
if (!isa<BranchInst>(EntryTI) ||
!cast<BranchInst>(EntryTI)->isUnconditional() ||
- EntryTI->getSuccessor(0) != L->getHeader())
+ EntryTI->getSuccessor(0) != L->getHeader()) {
ShouldExtractLoop = true;
- else {
+ } else {
// Check to see if any exits from the loop are more than just return
// blocks.
SmallVector<BasicBlock*, 8> ExitBlocks;
@@ -113,6 +114,21 @@ bool LoopExtractor::runOnLoop(Loop *L, LPPassManager &LPM) {
break;
}
}
+
+ if (ShouldExtractLoop) {
+ // We must omit landing pads. Landing pads must accompany the invoke
+ // instruction. But this would result in a loop in the extracted
+ // function. An infinite cycle occurs when it tries to extract that loop as
+ // well.
+ SmallVector<BasicBlock*, 8> ExitBlocks;
+ L->getExitBlocks(ExitBlocks);
+ for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
+ if (ExitBlocks[i]->isLandingPad()) {
+ ShouldExtractLoop = false;
+ break;
+ }
+ }
+
if (ShouldExtractLoop) {
if (NumLoops == 0) return Changed;
--NumLoops;
@@ -149,6 +165,7 @@ namespace {
/// BlocksToNotExtract list.
class BlockExtractorPass : public ModulePass {
void LoadFile(const char *Filename);
+ void SplitLandingPadPreds(Function *F);
std::vector<BasicBlock*> BlocksToNotExtract;
std::vector<std::pair<std::string, std::string> > BlocksToNotExtractByName;
@@ -171,8 +188,7 @@ INITIALIZE_PASS(BlockExtractorPass, "extract-blocks",
// createBlockExtractorPass - This pass extracts all blocks (except those
// specified in the argument list) from the functions in the module.
//
-ModulePass *llvm::createBlockExtractorPass()
-{
+ModulePass *llvm::createBlockExtractorPass() {
return new BlockExtractorPass();
}
@@ -194,6 +210,37 @@ void BlockExtractorPass::LoadFile(const char *Filename) {
}
}
+/// SplitLandingPadPreds - The landing pad needs to be extracted with the invoke
+/// instruction. The critical edge breaker will refuse to break critical edges
+/// to a landing pad. So do them here. After this method runs, all landing pads
+/// should have only one predecessor.
+void BlockExtractorPass::SplitLandingPadPreds(Function *F) {
+ for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
+ InvokeInst *II = dyn_cast<InvokeInst>(I);
+ if (!II) continue;
+ BasicBlock *Parent = II->getParent();
+ BasicBlock *LPad = II->getUnwindDest();
+
+ // Look through the landing pad's predecessors. If one of them ends in an
+ // 'invoke', then we want to split the landing pad.
+ bool Split = false;
+ for (pred_iterator
+ PI = pred_begin(LPad), PE = pred_end(LPad); PI != PE; ++PI) {
+ BasicBlock *BB = *PI;
+ if (BB->isLandingPad() && BB != Parent &&
+ isa<InvokeInst>(Parent->getTerminator())) {
+ Split = true;
+ break;
+ }
+ }
+
+ if (!Split) continue;
+
+ SmallVector<BasicBlock*, 2> NewBBs;
+ SplitLandingPadPredecessors(LPad, Parent, ".1", ".2", 0, NewBBs);
+ }
+}
+
bool BlockExtractorPass::runOnModule(Module &M) {
std::set<BasicBlock*> TranslatedBlocksToNotExtract;
for (unsigned i = 0, e = BlocksToNotExtract.size(); i != e; ++i) {
@@ -236,13 +283,21 @@ bool BlockExtractorPass::runOnModule(Module &M) {
// Now that we know which blocks to not extract, figure out which ones we WANT
// to extract.
std::vector<BasicBlock*> BlocksToExtract;
- for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
+ for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
+ SplitLandingPadPreds(&*F);
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
if (!TranslatedBlocksToNotExtract.count(BB))
BlocksToExtract.push_back(BB);
+ }
- for (unsigned i = 0, e = BlocksToExtract.size(); i != e; ++i)
- ExtractBasicBlock(BlocksToExtract[i]);
+ for (unsigned i = 0, e = BlocksToExtract.size(); i != e; ++i) {
+ SmallVector<BasicBlock*, 2> BlocksToExtractVec;
+ BlocksToExtractVec.push_back(BlocksToExtract[i]);
+ if (const InvokeInst *II =
+ dyn_cast<InvokeInst>(BlocksToExtract[i]->getTerminator()))
+ BlocksToExtractVec.push_back(II->getUnwindDest());
+ ExtractBasicBlock(BlocksToExtractVec);
+ }
return !BlocksToExtract.empty();
}
diff --git a/lib/Transforms/IPO/LowerSetJmp.cpp b/lib/Transforms/IPO/LowerSetJmp.cpp
deleted file mode 100644
index 659476b..0000000
--- a/lib/Transforms/IPO/LowerSetJmp.cpp
+++ /dev/null
@@ -1,547 +0,0 @@
-//===- LowerSetJmp.cpp - Code pertaining to lowering set/long jumps -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the lowering of setjmp and longjmp to use the
-// LLVM invoke and unwind instructions as necessary.
-//
-// Lowering of longjmp is fairly trivial. We replace the call with a
-// call to the LLVM library function "__llvm_sjljeh_throw_longjmp()".
-// This unwinds the stack for us calling all of the destructors for
-// objects allocated on the stack.
-//
-// At a setjmp call, the basic block is split and the setjmp removed.
-// The calls in a function that have a setjmp are converted to invoke
-// where the except part checks to see if it's a longjmp exception and,
-// if so, if it's handled in the function. If it is, then it gets the
-// value returned by the longjmp and goes to where the basic block was
-// split. Invoke instructions are handled in a similar fashion with the
-// original except block being executed if it isn't a longjmp except
-// that is handled by that function.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// FIXME: This pass doesn't deal with PHI statements just yet. That is,
-// we expect this to occur before SSAification is done. This would seem
-// to make sense, but in general, it might be a good idea to make this
-// pass invokable via the "opt" command at will.
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "lowersetjmp"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Instructions.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/CallSite.h"
-#include "llvm/Support/CFG.h"
-#include "llvm/Support/InstVisitor.h"
-#include "llvm/Transforms/Utils/Local.h"
-#include "llvm/ADT/DepthFirstIterator.h"
-#include "llvm/ADT/Statistic.h"
-#include <map>
-using namespace llvm;
-
-STATISTIC(LongJmpsTransformed, "Number of longjmps transformed");
-STATISTIC(SetJmpsTransformed , "Number of setjmps transformed");
-STATISTIC(CallsTransformed , "Number of calls invokified");
-STATISTIC(InvokesTransformed , "Number of invokes modified");
-
-namespace {
- //===--------------------------------------------------------------------===//
- // LowerSetJmp pass implementation.
- class LowerSetJmp : public ModulePass, public InstVisitor<LowerSetJmp> {
- // LLVM library functions...
- Constant *InitSJMap; // __llvm_sjljeh_init_setjmpmap
- Constant *DestroySJMap; // __llvm_sjljeh_destroy_setjmpmap
- Constant *AddSJToMap; // __llvm_sjljeh_add_setjmp_to_map
- Constant *ThrowLongJmp; // __llvm_sjljeh_throw_longjmp
- Constant *TryCatchLJ; // __llvm_sjljeh_try_catching_longjmp_exception
- Constant *IsLJException; // __llvm_sjljeh_is_longjmp_exception
- Constant *GetLJValue; // __llvm_sjljeh_get_longjmp_value
-
- typedef std::pair<SwitchInst*, CallInst*> SwitchValuePair;
-
- // Keep track of those basic blocks reachable via a depth-first search of
- // the CFG from a setjmp call. We only need to transform those "call" and
- // "invoke" instructions that are reachable from the setjmp call site.
- std::set<BasicBlock*> DFSBlocks;
-
- // The setjmp map is going to hold information about which setjmps
- // were called (each setjmp gets its own number) and with which
- // buffer it was called.
- std::map<Function*, AllocaInst*> SJMap;
-
- // The rethrow basic block map holds the basic block to branch to if
- // the exception isn't handled in the current function and needs to
- // be rethrown.
- std::map<const Function*, BasicBlock*> RethrowBBMap;
-
- // The preliminary basic block map holds a basic block that grabs the
- // exception and determines if it's handled by the current function.
- std::map<const Function*, BasicBlock*> PrelimBBMap;
-
- // The switch/value map holds a switch inst/call inst pair. The
- // switch inst controls which handler (if any) gets called and the
- // value is the value returned to that handler by the call to
- // __llvm_sjljeh_get_longjmp_value.
- std::map<const Function*, SwitchValuePair> SwitchValMap;
-
- // A map of which setjmps we've seen so far in a function.
- std::map<const Function*, unsigned> SetJmpIDMap;
-
- AllocaInst* GetSetJmpMap(Function* Func);
- BasicBlock* GetRethrowBB(Function* Func);
- SwitchValuePair GetSJSwitch(Function* Func, BasicBlock* Rethrow);
-
- void TransformLongJmpCall(CallInst* Inst);
- void TransformSetJmpCall(CallInst* Inst);
-
- bool IsTransformableFunction(StringRef Name);
- public:
- static char ID; // Pass identification, replacement for typeid
- LowerSetJmp() : ModulePass(ID) {
- initializeLowerSetJmpPass(*PassRegistry::getPassRegistry());
- }
-
- void visitCallInst(CallInst& CI);
- void visitInvokeInst(InvokeInst& II);
- void visitReturnInst(ReturnInst& RI);
- void visitUnwindInst(UnwindInst& UI);
-
- bool runOnModule(Module& M);
- bool doInitialization(Module& M);
- };
-} // end anonymous namespace
-
-char LowerSetJmp::ID = 0;
-INITIALIZE_PASS(LowerSetJmp, "lowersetjmp", "Lower Set Jump", false, false)
-
-// run - Run the transformation on the program. We grab the function
-// prototypes for longjmp and setjmp. If they are used in the program,
-// then we can go directly to the places they're at and transform them.
-bool LowerSetJmp::runOnModule(Module& M) {
- bool Changed = false;
-
- // These are what the functions are called.
- Function* SetJmp = M.getFunction("llvm.setjmp");
- Function* LongJmp = M.getFunction("llvm.longjmp");
-
- // This program doesn't have longjmp and setjmp calls.
- if ((!LongJmp || LongJmp->use_empty()) &&
- (!SetJmp || SetJmp->use_empty())) return false;
-
- // Initialize some values and functions we'll need to transform the
- // setjmp/longjmp functions.
- doInitialization(M);
-
- if (SetJmp) {
- for (Value::use_iterator B = SetJmp->use_begin(), E = SetJmp->use_end();
- B != E; ++B) {
- BasicBlock* BB = cast<Instruction>(*B)->getParent();
- for (df_ext_iterator<BasicBlock*> I = df_ext_begin(BB, DFSBlocks),
- E = df_ext_end(BB, DFSBlocks); I != E; ++I)
- /* empty */;
- }
-
- while (!SetJmp->use_empty()) {
- assert(isa<CallInst>(SetJmp->use_back()) &&
- "User of setjmp intrinsic not a call?");
- TransformSetJmpCall(cast<CallInst>(SetJmp->use_back()));
- Changed = true;
- }
- }
-
- if (LongJmp)
- while (!LongJmp->use_empty()) {
- assert(isa<CallInst>(LongJmp->use_back()) &&
- "User of longjmp intrinsic not a call?");
- TransformLongJmpCall(cast<CallInst>(LongJmp->use_back()));
- Changed = true;
- }
-
- // Now go through the affected functions and convert calls and invokes
- // to new invokes...
- for (std::map<Function*, AllocaInst*>::iterator
- B = SJMap.begin(), E = SJMap.end(); B != E; ++B) {
- Function* F = B->first;
- for (Function::iterator BB = F->begin(), BE = F->end(); BB != BE; ++BB)
- for (BasicBlock::iterator IB = BB->begin(), IE = BB->end(); IB != IE; ) {
- visit(*IB++);
- if (IB != BB->end() && IB->getParent() != BB)
- break; // The next instruction got moved to a different block!
- }
- }
-
- DFSBlocks.clear();
- SJMap.clear();
- RethrowBBMap.clear();
- PrelimBBMap.clear();
- SwitchValMap.clear();
- SetJmpIDMap.clear();
-
- return Changed;
-}
-
-// doInitialization - For the lower long/setjmp pass, this ensures that a
-// module contains a declaration for the intrisic functions we are going
-// to call to convert longjmp and setjmp calls.
-//
-// This function is always successful, unless it isn't.
-bool LowerSetJmp::doInitialization(Module& M)
-{
- const Type *SBPTy = Type::getInt8PtrTy(M.getContext());
- const Type *SBPPTy = PointerType::getUnqual(SBPTy);
-
- // N.B. See llvm/runtime/GCCLibraries/libexception/SJLJ-Exception.h for
- // a description of the following library functions.
-
- // void __llvm_sjljeh_init_setjmpmap(void**)
- InitSJMap = M.getOrInsertFunction("__llvm_sjljeh_init_setjmpmap",
- Type::getVoidTy(M.getContext()),
- SBPPTy, (Type *)0);
- // void __llvm_sjljeh_destroy_setjmpmap(void**)
- DestroySJMap = M.getOrInsertFunction("__llvm_sjljeh_destroy_setjmpmap",
- Type::getVoidTy(M.getContext()),
- SBPPTy, (Type *)0);
-
- // void __llvm_sjljeh_add_setjmp_to_map(void**, void*, unsigned)
- AddSJToMap = M.getOrInsertFunction("__llvm_sjljeh_add_setjmp_to_map",
- Type::getVoidTy(M.getContext()),
- SBPPTy, SBPTy,
- Type::getInt32Ty(M.getContext()),
- (Type *)0);
-
- // void __llvm_sjljeh_throw_longjmp(int*, int)
- ThrowLongJmp = M.getOrInsertFunction("__llvm_sjljeh_throw_longjmp",
- Type::getVoidTy(M.getContext()), SBPTy,
- Type::getInt32Ty(M.getContext()),
- (Type *)0);
-
- // unsigned __llvm_sjljeh_try_catching_longjmp_exception(void **)
- TryCatchLJ =
- M.getOrInsertFunction("__llvm_sjljeh_try_catching_longjmp_exception",
- Type::getInt32Ty(M.getContext()), SBPPTy, (Type *)0);
-
- // bool __llvm_sjljeh_is_longjmp_exception()
- IsLJException = M.getOrInsertFunction("__llvm_sjljeh_is_longjmp_exception",
- Type::getInt1Ty(M.getContext()),
- (Type *)0);
-
- // int __llvm_sjljeh_get_longjmp_value()
- GetLJValue = M.getOrInsertFunction("__llvm_sjljeh_get_longjmp_value",
- Type::getInt32Ty(M.getContext()),
- (Type *)0);
- return true;
-}
-
-// IsTransformableFunction - Return true if the function name isn't one
-// of the ones we don't want transformed. Currently, don't transform any
-// "llvm.{setjmp,longjmp}" functions and none of the setjmp/longjmp error
-// handling functions (beginning with __llvm_sjljeh_...they don't throw
-// exceptions).
-bool LowerSetJmp::IsTransformableFunction(StringRef Name) {
- return !Name.startswith("__llvm_sjljeh_");
-}
-
-// TransformLongJmpCall - Transform a longjmp call into a call to the
-// internal __llvm_sjljeh_throw_longjmp function. It then takes care of
-// throwing the exception for us.
-void LowerSetJmp::TransformLongJmpCall(CallInst* Inst)
-{
- const Type* SBPTy = Type::getInt8PtrTy(Inst->getContext());
-
- // Create the call to "__llvm_sjljeh_throw_longjmp". This takes the
- // same parameters as "longjmp", except that the buffer is cast to a
- // char*. It returns "void", so it doesn't need to replace any of
- // Inst's uses and doesn't get a name.
- CastInst* CI =
- new BitCastInst(Inst->getArgOperand(0), SBPTy, "LJBuf", Inst);
- Value *Args[] = { CI, Inst->getArgOperand(1) };
- CallInst::Create(ThrowLongJmp, Args, "", Inst);
-
- SwitchValuePair& SVP = SwitchValMap[Inst->getParent()->getParent()];
-
- // If the function has a setjmp call in it (they are transformed first)
- // we should branch to the basic block that determines if this longjmp
- // is applicable here. Otherwise, issue an unwind.
- if (SVP.first)
- BranchInst::Create(SVP.first->getParent(), Inst);
- else
- new UnwindInst(Inst->getContext(), Inst);
-
- // Remove all insts after the branch/unwind inst. Go from back to front to
- // avoid replaceAllUsesWith if possible.
- BasicBlock *BB = Inst->getParent();
- Instruction *Removed;
- do {
- Removed = &BB->back();
- // If the removed instructions have any users, replace them now.
- if (!Removed->use_empty())
- Removed->replaceAllUsesWith(UndefValue::get(Removed->getType()));
- Removed->eraseFromParent();
- } while (Removed != Inst);
-
- ++LongJmpsTransformed;
-}
-
-// GetSetJmpMap - Retrieve (create and initialize, if necessary) the
-// setjmp map. This map is going to hold information about which setjmps
-// were called (each setjmp gets its own number) and with which buffer it
-// was called. There can be only one!
-AllocaInst* LowerSetJmp::GetSetJmpMap(Function* Func)
-{
- if (SJMap[Func]) return SJMap[Func];
-
- // Insert the setjmp map initialization before the first instruction in
- // the function.
- Instruction* Inst = Func->getEntryBlock().begin();
- assert(Inst && "Couldn't find even ONE instruction in entry block!");
-
- // Fill in the alloca and call to initialize the SJ map.
- const Type *SBPTy =
- Type::getInt8PtrTy(Func->getContext());
- AllocaInst* Map = new AllocaInst(SBPTy, 0, "SJMap", Inst);
- CallInst::Create(InitSJMap, Map, "", Inst);
- return SJMap[Func] = Map;
-}
-
-// GetRethrowBB - Only one rethrow basic block is needed per function.
-// If this is a longjmp exception but not handled in this block, this BB
-// performs the rethrow.
-BasicBlock* LowerSetJmp::GetRethrowBB(Function* Func)
-{
- if (RethrowBBMap[Func]) return RethrowBBMap[Func];
-
- // The basic block we're going to jump to if we need to rethrow the
- // exception.
- BasicBlock* Rethrow =
- BasicBlock::Create(Func->getContext(), "RethrowExcept", Func);
-
- // Fill in the "Rethrow" BB with a call to rethrow the exception. This
- // is the last instruction in the BB since at this point the runtime
- // should exit this function and go to the next function.
- new UnwindInst(Func->getContext(), Rethrow);
- return RethrowBBMap[Func] = Rethrow;
-}
-
-// GetSJSwitch - Return the switch statement that controls which handler
-// (if any) gets called and the value returned to that handler.
-LowerSetJmp::SwitchValuePair LowerSetJmp::GetSJSwitch(Function* Func,
- BasicBlock* Rethrow)
-{
- if (SwitchValMap[Func].first) return SwitchValMap[Func];
-
- BasicBlock* LongJmpPre =
- BasicBlock::Create(Func->getContext(), "LongJmpBlkPre", Func);
-
- // Keep track of the preliminary basic block for some of the other
- // transformations.
- PrelimBBMap[Func] = LongJmpPre;
-
- // Grab the exception.
- CallInst* Cond = CallInst::Create(IsLJException, "IsLJExcept", LongJmpPre);
-
- // The "decision basic block" gets the number associated with the
- // setjmp call returning to switch on and the value returned by
- // longjmp.
- BasicBlock* DecisionBB =
- BasicBlock::Create(Func->getContext(), "LJDecisionBB", Func);
-
- BranchInst::Create(DecisionBB, Rethrow, Cond, LongJmpPre);
-
- // Fill in the "decision" basic block.
- CallInst* LJVal = CallInst::Create(GetLJValue, "LJVal", DecisionBB);
- CallInst* SJNum = CallInst::Create(TryCatchLJ, GetSetJmpMap(Func), "SJNum",
- DecisionBB);
-
- SwitchInst* SI = SwitchInst::Create(SJNum, Rethrow, 0, DecisionBB);
- return SwitchValMap[Func] = SwitchValuePair(SI, LJVal);
-}
-
-// TransformSetJmpCall - The setjmp call is a bit trickier to transform.
-// We're going to convert all setjmp calls to nops. Then all "call" and
-// "invoke" instructions in the function are converted to "invoke" where
-// the "except" branch is used when returning from a longjmp call.
-void LowerSetJmp::TransformSetJmpCall(CallInst* Inst)
-{
- BasicBlock* ABlock = Inst->getParent();
- Function* Func = ABlock->getParent();
-
- // Add this setjmp to the setjmp map.
- const Type* SBPTy =
- Type::getInt8PtrTy(Inst->getContext());
- CastInst* BufPtr =
- new BitCastInst(Inst->getArgOperand(0), SBPTy, "SBJmpBuf", Inst);
- Value *Args[] = {
- GetSetJmpMap(Func), BufPtr,
- ConstantInt::get(Type::getInt32Ty(Inst->getContext()), SetJmpIDMap[Func]++)
- };
- CallInst::Create(AddSJToMap, Args, "", Inst);
-
- // We are guaranteed that there are no values live across basic blocks
- // (because we are "not in SSA form" yet), but there can still be values live
- // in basic blocks. Because of this, splitting the setjmp block can cause
- // values above the setjmp to not dominate uses which are after the setjmp
- // call. For all of these occasions, we must spill the value to the stack.
- //
- std::set<Instruction*> InstrsAfterCall;
-
- // The call is probably very close to the end of the basic block, for the
- // common usage pattern of: 'if (setjmp(...))', so keep track of the
- // instructions after the call.
- for (BasicBlock::iterator I = ++BasicBlock::iterator(Inst), E = ABlock->end();
- I != E; ++I)
- InstrsAfterCall.insert(I);
-
- for (BasicBlock::iterator II = ABlock->begin();
- II != BasicBlock::iterator(Inst); ++II)
- // Loop over all of the uses of instruction. If any of them are after the
- // call, "spill" the value to the stack.
- for (Value::use_iterator UI = II->use_begin(), E = II->use_end();
- UI != E; ++UI) {
- User *U = *UI;
- if (cast<Instruction>(U)->getParent() != ABlock ||
- InstrsAfterCall.count(cast<Instruction>(U))) {
- DemoteRegToStack(*II);
- break;
- }
- }
- InstrsAfterCall.clear();
-
- // Change the setjmp call into a branch statement. We'll remove the
- // setjmp call in a little bit. No worries.
- BasicBlock* SetJmpContBlock = ABlock->splitBasicBlock(Inst);
- assert(SetJmpContBlock && "Couldn't split setjmp BB!!");
-
- SetJmpContBlock->setName(ABlock->getName()+"SetJmpCont");
-
- // Add the SetJmpContBlock to the set of blocks reachable from a setjmp.
- DFSBlocks.insert(SetJmpContBlock);
-
- // This PHI node will be in the new block created from the
- // splitBasicBlock call.
- PHINode* PHI = PHINode::Create(Type::getInt32Ty(Inst->getContext()), 2,
- "SetJmpReturn", Inst);
-
- // Coming from a call to setjmp, the return is 0.
- PHI->addIncoming(Constant::getNullValue(Type::getInt32Ty(Inst->getContext())),
- ABlock);
-
- // Add the case for this setjmp's number...
- SwitchValuePair SVP = GetSJSwitch(Func, GetRethrowBB(Func));
- SVP.first->addCase(ConstantInt::get(Type::getInt32Ty(Inst->getContext()),
- SetJmpIDMap[Func] - 1),
- SetJmpContBlock);
-
- // Value coming from the handling of the exception.
- PHI->addIncoming(SVP.second, SVP.second->getParent());
-
- // Replace all uses of this instruction with the PHI node created by
- // the eradication of setjmp.
- Inst->replaceAllUsesWith(PHI);
- Inst->eraseFromParent();
-
- ++SetJmpsTransformed;
-}
-
-// visitCallInst - This converts all LLVM call instructions into invoke
-// instructions. The except part of the invoke goes to the "LongJmpBlkPre"
-// that grabs the exception and proceeds to determine if it's a longjmp
-// exception or not.
-void LowerSetJmp::visitCallInst(CallInst& CI)
-{
- if (CI.getCalledFunction())
- if (!IsTransformableFunction(CI.getCalledFunction()->getName()) ||
- CI.getCalledFunction()->isIntrinsic()) return;
-
- BasicBlock* OldBB = CI.getParent();
-
- // If not reachable from a setjmp call, don't transform.
- if (!DFSBlocks.count(OldBB)) return;
-
- BasicBlock* NewBB = OldBB->splitBasicBlock(CI);
- assert(NewBB && "Couldn't split BB of \"call\" instruction!!");
- DFSBlocks.insert(NewBB);
- NewBB->setName("Call2Invoke");
-
- Function* Func = OldBB->getParent();
-
- // Construct the new "invoke" instruction.
- TerminatorInst* Term = OldBB->getTerminator();
- CallSite CS(&CI);
- std::vector<Value*> Params(CS.arg_begin(), CS.arg_end());
- InvokeInst* II =
- InvokeInst::Create(CI.getCalledValue(), NewBB, PrelimBBMap[Func],
- Params, CI.getName(), Term);
- II->setCallingConv(CI.getCallingConv());
- II->setAttributes(CI.getAttributes());
-
- // Replace the old call inst with the invoke inst and remove the call.
- CI.replaceAllUsesWith(II);
- CI.eraseFromParent();
-
- // The old terminator is useless now that we have the invoke inst.
- Term->eraseFromParent();
- ++CallsTransformed;
-}
-
-// visitInvokeInst - Converting the "invoke" instruction is fairly
-// straight-forward. The old exception part is replaced by a query asking
-// if this is a longjmp exception. If it is, then it goes to the longjmp
-// exception blocks. Otherwise, control is passed the old exception.
-void LowerSetJmp::visitInvokeInst(InvokeInst& II)
-{
- if (II.getCalledFunction())
- if (!IsTransformableFunction(II.getCalledFunction()->getName()) ||
- II.getCalledFunction()->isIntrinsic()) return;
-
- BasicBlock* BB = II.getParent();
-
- // If not reachable from a setjmp call, don't transform.
- if (!DFSBlocks.count(BB)) return;
-
- BasicBlock* ExceptBB = II.getUnwindDest();
-
- Function* Func = BB->getParent();
- BasicBlock* NewExceptBB = BasicBlock::Create(II.getContext(),
- "InvokeExcept", Func);
-
- // If this is a longjmp exception, then branch to the preliminary BB of
- // the longjmp exception handling. Otherwise, go to the old exception.
- CallInst* IsLJExcept = CallInst::Create(IsLJException, "IsLJExcept",
- NewExceptBB);
-
- BranchInst::Create(PrelimBBMap[Func], ExceptBB, IsLJExcept, NewExceptBB);
-
- II.setUnwindDest(NewExceptBB);
- ++InvokesTransformed;
-}
-
-// visitReturnInst - We want to destroy the setjmp map upon exit from the
-// function.
-void LowerSetJmp::visitReturnInst(ReturnInst &RI) {
- Function* Func = RI.getParent()->getParent();
- CallInst::Create(DestroySJMap, GetSetJmpMap(Func), "", &RI);
-}
-
-// visitUnwindInst - We want to destroy the setjmp map upon exit from the
-// function.
-void LowerSetJmp::visitUnwindInst(UnwindInst &UI) {
- Function* Func = UI.getParent()->getParent();
- CallInst::Create(DestroySJMap, GetSetJmpMap(Func), "", &UI);
-}
-
-ModulePass *llvm::createLowerSetJmpPass() {
- return new LowerSetJmp();
-}
-
diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp
index 7796d05..0b01c38 100644
--- a/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/lib/Transforms/IPO/MergeFunctions.cpp
@@ -76,7 +76,7 @@ STATISTIC(NumDoubleWeak, "Number of new functions created");
/// functions that will compare equal, without looking at the instructions
/// inside the function.
static unsigned profileFunction(const Function *F) {
- const FunctionType *FTy = F->getFunctionType();
+ FunctionType *FTy = F->getFunctionType();
FoldingSetNodeID ID;
ID.AddInteger(F->size());
@@ -185,7 +185,7 @@ private:
}
/// Compare two Types, treating all pointer types as equal.
- bool isEquivalentType(const Type *Ty1, const Type *Ty2) const;
+ bool isEquivalentType(Type *Ty1, Type *Ty2) const;
// The two functions undergoing comparison.
const Function *F1, *F2;
@@ -200,8 +200,8 @@ private:
// Any two pointers in the same address space are equivalent, intptr_t and
// pointers are equivalent. Otherwise, standard type equivalence rules apply.
-bool FunctionComparator::isEquivalentType(const Type *Ty1,
- const Type *Ty2) const {
+bool FunctionComparator::isEquivalentType(Type *Ty1,
+ Type *Ty2) const {
if (Ty1 == Ty2)
return true;
if (Ty1->getTypeID() != Ty2->getTypeID()) {
@@ -233,14 +233,14 @@ bool FunctionComparator::isEquivalentType(const Type *Ty1,
return true;
case Type::PointerTyID: {
- const PointerType *PTy1 = cast<PointerType>(Ty1);
- const PointerType *PTy2 = cast<PointerType>(Ty2);
+ PointerType *PTy1 = cast<PointerType>(Ty1);
+ PointerType *PTy2 = cast<PointerType>(Ty2);
return PTy1->getAddressSpace() == PTy2->getAddressSpace();
}
case Type::StructTyID: {
- const StructType *STy1 = cast<StructType>(Ty1);
- const StructType *STy2 = cast<StructType>(Ty2);
+ StructType *STy1 = cast<StructType>(Ty1);
+ StructType *STy2 = cast<StructType>(Ty2);
if (STy1->getNumElements() != STy2->getNumElements())
return false;
@@ -255,8 +255,8 @@ bool FunctionComparator::isEquivalentType(const Type *Ty1,
}
case Type::FunctionTyID: {
- const FunctionType *FTy1 = cast<FunctionType>(Ty1);
- const FunctionType *FTy2 = cast<FunctionType>(Ty2);
+ FunctionType *FTy1 = cast<FunctionType>(Ty1);
+ FunctionType *FTy2 = cast<FunctionType>(Ty2);
if (FTy1->getNumParams() != FTy2->getNumParams() ||
FTy1->isVarArg() != FTy2->isVarArg())
return false;
@@ -272,8 +272,8 @@ bool FunctionComparator::isEquivalentType(const Type *Ty1,
}
case Type::ArrayTyID: {
- const ArrayType *ATy1 = cast<ArrayType>(Ty1);
- const ArrayType *ATy2 = cast<ArrayType>(Ty2);
+ ArrayType *ATy1 = cast<ArrayType>(Ty1);
+ ArrayType *ATy2 = cast<ArrayType>(Ty2);
return ATy1->getNumElements() == ATy2->getNumElements() &&
isEquivalentType(ATy1->getElementType(), ATy2->getElementType());
}
@@ -305,10 +305,14 @@ bool FunctionComparator::isEquivalentOperation(const Instruction *I1,
// Check special state that is a part of some instructions.
if (const LoadInst *LI = dyn_cast<LoadInst>(I1))
return LI->isVolatile() == cast<LoadInst>(I2)->isVolatile() &&
- LI->getAlignment() == cast<LoadInst>(I2)->getAlignment();
+ LI->getAlignment() == cast<LoadInst>(I2)->getAlignment() &&
+ LI->getOrdering() == cast<LoadInst>(I2)->getOrdering() &&
+ LI->getSynchScope() == cast<LoadInst>(I2)->getSynchScope();
if (const StoreInst *SI = dyn_cast<StoreInst>(I1))
return SI->isVolatile() == cast<StoreInst>(I2)->isVolatile() &&
- SI->getAlignment() == cast<StoreInst>(I2)->getAlignment();
+ SI->getAlignment() == cast<StoreInst>(I2)->getAlignment() &&
+ SI->getOrdering() == cast<StoreInst>(I2)->getOrdering() &&
+ SI->getSynchScope() == cast<StoreInst>(I2)->getSynchScope();
if (const CmpInst *CI = dyn_cast<CmpInst>(I1))
return CI->getPredicate() == cast<CmpInst>(I2)->getPredicate();
if (const CallInst *CI = dyn_cast<CallInst>(I1))
@@ -317,22 +321,22 @@ bool FunctionComparator::isEquivalentOperation(const Instruction *I1,
if (const InvokeInst *CI = dyn_cast<InvokeInst>(I1))
return CI->getCallingConv() == cast<InvokeInst>(I2)->getCallingConv() &&
CI->getAttributes() == cast<InvokeInst>(I2)->getAttributes();
- if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(I1)) {
- if (IVI->getNumIndices() != cast<InsertValueInst>(I2)->getNumIndices())
- return false;
- for (unsigned i = 0, e = IVI->getNumIndices(); i != e; ++i)
- if (IVI->idx_begin()[i] != cast<InsertValueInst>(I2)->idx_begin()[i])
- return false;
- return true;
- }
- if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(I1)) {
- if (EVI->getNumIndices() != cast<ExtractValueInst>(I2)->getNumIndices())
- return false;
- for (unsigned i = 0, e = EVI->getNumIndices(); i != e; ++i)
- if (EVI->idx_begin()[i] != cast<ExtractValueInst>(I2)->idx_begin()[i])
- return false;
- return true;
- }
+ if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(I1))
+ return IVI->getIndices() == cast<InsertValueInst>(I2)->getIndices();
+ if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(I1))
+ return EVI->getIndices() == cast<ExtractValueInst>(I2)->getIndices();
+ if (const FenceInst *FI = dyn_cast<FenceInst>(I1))
+ return FI->getOrdering() == cast<FenceInst>(I2)->getOrdering() &&
+ FI->getSynchScope() == cast<FenceInst>(I2)->getSynchScope();
+ if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(I1))
+ return CXI->isVolatile() == cast<AtomicCmpXchgInst>(I2)->isVolatile() &&
+ CXI->getOrdering() == cast<AtomicCmpXchgInst>(I2)->getOrdering() &&
+ CXI->getSynchScope() == cast<AtomicCmpXchgInst>(I2)->getSynchScope();
+ if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I1))
+ return RMWI->getOperation() == cast<AtomicRMWInst>(I2)->getOperation() &&
+ RMWI->isVolatile() == cast<AtomicRMWInst>(I2)->isVolatile() &&
+ RMWI->getOrdering() == cast<AtomicRMWInst>(I2)->getOrdering() &&
+ RMWI->getSynchScope() == cast<AtomicRMWInst>(I2)->getSynchScope();
return true;
}
@@ -346,9 +350,9 @@ bool FunctionComparator::isEquivalentGEP(const GEPOperator *GEP1,
SmallVector<Value *, 8> Indices1(GEP1->idx_begin(), GEP1->idx_end());
SmallVector<Value *, 8> Indices2(GEP2->idx_begin(), GEP2->idx_end());
uint64_t Offset1 = TD->getIndexedOffset(GEP1->getPointerOperandType(),
- Indices1.data(), Indices1.size());
+ Indices1);
uint64_t Offset2 = TD->getIndexedOffset(GEP2->getPointerOperandType(),
- Indices2.data(), Indices2.size());
+ Indices2);
return Offset1 == Offset2;
}
@@ -725,7 +729,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) {
SmallVector<Value *, 16> Args;
unsigned i = 0;
- const FunctionType *FFTy = F->getFunctionType();
+ FunctionType *FFTy = F->getFunctionType();
for (Function::arg_iterator AI = NewG->arg_begin(), AE = NewG->arg_end();
AI != AE; ++AI) {
Args.push_back(Builder.CreateBitCast(AI, FFTy->getParamType(i)));
diff --git a/lib/Transforms/IPO/PassManagerBuilder.cpp b/lib/Transforms/IPO/PassManagerBuilder.cpp
new file mode 100644
index 0000000..8fdfd72
--- /dev/null
+++ b/lib/Transforms/IPO/PassManagerBuilder.cpp
@@ -0,0 +1,343 @@
+//===- PassManagerBuilder.cpp - Build Standard Pass -----------------------===//
+//
+// 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++.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+
+#include "llvm-c/Transforms/PassManagerBuilder.h"
+
+#include "llvm/PassManager.h"
+#include "llvm/DefaultPasses.h"
+#include "llvm/PassManager.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"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ManagedStatic.h"
+
+using namespace llvm;
+
+PassManagerBuilder::PassManagerBuilder() {
+ OptLevel = 2;
+ SizeLevel = 0;
+ LibraryInfo = 0;
+ Inliner = 0;
+ DisableSimplifyLibCalls = false;
+ DisableUnitAtATime = false;
+ DisableUnrollLoops = false;
+}
+
+PassManagerBuilder::~PassManagerBuilder() {
+ delete LibraryInfo;
+ delete Inliner;
+}
+
+/// Set of global extensions, automatically added as part of the standard set.
+static ManagedStatic<SmallVector<std::pair<PassManagerBuilder::ExtensionPointTy,
+ PassManagerBuilder::ExtensionFn>, 8> > GlobalExtensions;
+
+void PassManagerBuilder::addGlobalExtension(
+ PassManagerBuilder::ExtensionPointTy Ty,
+ PassManagerBuilder::ExtensionFn Fn) {
+ GlobalExtensions->push_back(std::make_pair(Ty, Fn));
+}
+
+void PassManagerBuilder::addExtension(ExtensionPointTy Ty, ExtensionFn Fn) {
+ Extensions.push_back(std::make_pair(Ty, Fn));
+}
+
+void PassManagerBuilder::addExtensionsToPM(ExtensionPointTy ETy,
+ PassManagerBase &PM) const {
+ for (unsigned i = 0, e = GlobalExtensions->size(); i != e; ++i)
+ if ((*GlobalExtensions)[i].first == ETy)
+ (*GlobalExtensions)[i].second(*this, PM);
+ for (unsigned i = 0, e = Extensions.size(); i != e; ++i)
+ if (Extensions[i].first == ETy)
+ Extensions[i].second(*this, PM);
+}
+
+void
+PassManagerBuilder::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());
+}
+
+void PassManagerBuilder::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());
+}
+
+void PassManagerBuilder::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 PassManagerBuilder::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());
+}
+
+LLVMPassManagerBuilderRef LLVMPassManagerBuilderCreate(void) {
+ PassManagerBuilder *PMB = new PassManagerBuilder();
+ return wrap(PMB);
+}
+
+void LLVMPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) {
+ PassManagerBuilder *Builder = unwrap(PMB);
+ delete Builder;
+}
+
+void
+LLVMPassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB,
+ unsigned OptLevel) {
+ PassManagerBuilder *Builder = unwrap(PMB);
+ Builder->OptLevel = OptLevel;
+}
+
+void
+LLVMPassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB,
+ unsigned SizeLevel) {
+ PassManagerBuilder *Builder = unwrap(PMB);
+ Builder->SizeLevel = SizeLevel;
+}
+
+void
+LLVMPassManagerBuilderSetDisableUnitAtATime(LLVMPassManagerBuilderRef PMB,
+ LLVMBool Value) {
+ PassManagerBuilder *Builder = unwrap(PMB);
+ Builder->DisableUnitAtATime = Value;
+}
+
+void
+LLVMPassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB,
+ LLVMBool Value) {
+ PassManagerBuilder *Builder = unwrap(PMB);
+ Builder->DisableUnrollLoops = Value;
+}
+
+void
+LLVMPassManagerBuilderSetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef PMB,
+ LLVMBool Value) {
+ PassManagerBuilder *Builder = unwrap(PMB);
+ Builder->DisableSimplifyLibCalls = Value;
+}
+
+void
+LLVMPassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB,
+ unsigned Threshold) {
+ PassManagerBuilder *Builder = unwrap(PMB);
+ Builder->Inliner = createFunctionInliningPass(Threshold);
+}
+
+void
+LLVMPassManagerBuilderPopulateFunctionPassManager(LLVMPassManagerBuilderRef PMB,
+ LLVMPassManagerRef PM) {
+ PassManagerBuilder *Builder = unwrap(PMB);
+ FunctionPassManager *FPM = unwrap<FunctionPassManager>(PM);
+ Builder->populateFunctionPassManager(*FPM);
+}
+
+void
+LLVMPassManagerBuilderPopulateModulePassManager(LLVMPassManagerBuilderRef PMB,
+ LLVMPassManagerRef PM) {
+ PassManagerBuilder *Builder = unwrap(PMB);
+ PassManagerBase *MPM = unwrap(PM);
+ Builder->populateModulePassManager(*MPM);
+}
+
+void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB,
+ LLVMPassManagerRef PM,
+ bool Internalize,
+ bool RunInliner) {
+ PassManagerBuilder *Builder = unwrap(PMB);
+ PassManagerBase *LPM = unwrap(PM);
+ Builder->populateLTOPassManager(*LPM, Internalize, RunInliner);
+}
+
diff --git a/lib/Transforms/IPO/PruneEH.cpp b/lib/Transforms/IPO/PruneEH.cpp
index b7e63dc..cbb80f0 100644
--- a/lib/Transforms/IPO/PruneEH.cpp
+++ b/lib/Transforms/IPO/PruneEH.cpp
@@ -101,8 +101,9 @@ bool PruneEH::runOnSCC(CallGraphSCC &SCC) {
// Check to see if this function performs an unwind or calls an
// unwinding function.
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
- if (CheckUnwind && isa<UnwindInst>(BB->getTerminator())) {
- // Uses unwind!
+ if (CheckUnwind && (isa<UnwindInst>(BB->getTerminator()) ||
+ isa<ResumeInst>(BB->getTerminator()))) {
+ // Uses unwind / resume!
SCCMightUnwind = true;
} else if (CheckReturn && isa<ReturnInst>(BB->getTerminator())) {
SCCMightReturn = true;
diff --git a/lib/Transforms/IPO/StripSymbols.cpp b/lib/Transforms/IPO/StripSymbols.cpp
index 0fbaff1..b5caa9a 100644
--- a/lib/Transforms/IPO/StripSymbols.cpp
+++ b/lib/Transforms/IPO/StripSymbols.cpp
@@ -180,7 +180,7 @@ static void StripTypeNames(Module &M, bool PreserveDbgInfo) {
for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) {
StructType *STy = StructTypes[i];
- if (STy->isAnonymous() || STy->getName().empty()) continue;
+ if (STy->isLiteral() || STy->getName().empty()) continue;
if (PreserveDbgInfo && STy->getName().startswith("llvm.dbg"))
continue;
diff --git a/lib/Transforms/InstCombine/CMakeLists.txt b/lib/Transforms/InstCombine/CMakeLists.txt
index d070ccc..a46d5ad 100644
--- a/lib/Transforms/InstCombine/CMakeLists.txt
+++ b/lib/Transforms/InstCombine/CMakeLists.txt
@@ -13,3 +13,11 @@ add_llvm_library(LLVMInstCombine
InstCombineSimplifyDemanded.cpp
InstCombineVectorOps.cpp
)
+
+add_llvm_library_dependencies(LLVMInstCombine
+ LLVMAnalysis
+ LLVMCore
+ LLVMSupport
+ LLVMTarget
+ LLVMTransformUtils
+ )
diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h
index 8257d6b..3808278 100644
--- a/lib/Transforms/InstCombine/InstCombine.h
+++ b/lib/Transforms/InstCombine/InstCombine.h
@@ -11,6 +11,7 @@
#define INSTCOMBINE_INSTCOMBINE_H
#include "InstCombineWorklist.h"
+#include "llvm/IntrinsicInst.h"
#include "llvm/Operator.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/ValueTracking.h"
@@ -103,7 +104,7 @@ public:
//
Instruction *visitAdd(BinaryOperator &I);
Instruction *visitFAdd(BinaryOperator &I);
- Value *OptimizePointerDifference(Value *LHS, Value *RHS, const Type *Ty);
+ Value *OptimizePointerDifference(Value *LHS, Value *RHS, Type *Ty);
Instruction *visitSub(BinaryOperator &I);
Instruction *visitFSub(BinaryOperator &I);
Instruction *visitMul(BinaryOperator &I);
@@ -192,15 +193,16 @@ public:
Instruction *visitExtractElementInst(ExtractElementInst &EI);
Instruction *visitShuffleVectorInst(ShuffleVectorInst &SVI);
Instruction *visitExtractValueInst(ExtractValueInst &EV);
+ Instruction *visitLandingPadInst(LandingPadInst &LI);
// visitInstruction - Specify what to return for unhandled instructions...
Instruction *visitInstruction(Instruction &I) { return 0; }
private:
- bool ShouldChangeType(const Type *From, const Type *To) const;
+ bool ShouldChangeType(Type *From, Type *To) const;
Value *dyn_castNegVal(Value *V) const;
Value *dyn_castFNegVal(Value *V) const;
- const Type *FindElementAtOffset(const Type *Ty, int64_t Offset,
+ Type *FindElementAtOffset(Type *Ty, int64_t Offset,
SmallVectorImpl<Value*> &NewIndices);
Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI);
@@ -209,12 +211,13 @@ private:
/// the cast can be eliminated by some other simple transformation, we prefer
/// to do the simplification first.
bool ShouldOptimizeCast(Instruction::CastOps opcode,const Value *V,
- const Type *Ty);
+ Type *Ty);
Instruction *visitCallSite(CallSite CS);
Instruction *tryOptimizeCall(CallInst *CI, const TargetData *TD);
bool transformConstExprCastCall(CallSite CS);
- Instruction *transformCallThroughTrampoline(CallSite CS);
+ Instruction *transformCallThroughTrampoline(CallSite CS,
+ IntrinsicInst *Tramp);
Instruction *transformZExtICmp(ICmpInst *ICI, Instruction &CI,
bool DoXform = true);
Instruction *transformSExtICmp(ICmpInst *ICI, Instruction &CI);
@@ -357,7 +360,7 @@ private:
Instruction *SimplifyMemSet(MemSetInst *MI);
- Value *EvaluateInDifferentType(Value *V, const Type *Ty, bool isSigned);
+ Value *EvaluateInDifferentType(Value *V, Type *Ty, bool isSigned);
};
diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index c36a955..d10046c 100644
--- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -188,7 +188,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
return BinaryOperator::CreateMul(LHS, AddOne(C2));
// A+B --> A|B iff A and B have no bits set in common.
- if (const IntegerType *IT = dyn_cast<IntegerType>(I.getType())) {
+ if (IntegerType *IT = dyn_cast<IntegerType>(I.getType())) {
APInt Mask = APInt::getAllOnesValue(IT->getBitWidth());
APInt LHSKnownOne(IT->getBitWidth(), 0);
APInt LHSKnownZero(IT->getBitWidth(), 0);
@@ -401,7 +401,7 @@ Instruction *InstCombiner::visitFAdd(BinaryOperator &I) {
Value *InstCombiner::EmitGEPOffset(User *GEP) {
TargetData &TD = *getTargetData();
gep_type_iterator GTI = gep_type_begin(GEP);
- const Type *IntPtrTy = TD.getIntPtrType(GEP->getContext());
+ Type *IntPtrTy = TD.getIntPtrType(GEP->getContext());
Value *Result = Constant::getNullValue(IntPtrTy);
// If the GEP is inbounds, we know that none of the addressing operations will
@@ -420,7 +420,7 @@ Value *InstCombiner::EmitGEPOffset(User *GEP) {
if (OpC->isZero()) continue;
// Handle a struct index, which adds its field offset to the pointer.
- if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
+ if (StructType *STy = dyn_cast<StructType>(*GTI)) {
Size = TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue());
if (Size)
@@ -460,7 +460,7 @@ Value *InstCombiner::EmitGEPOffset(User *GEP) {
/// operands to the ptrtoint instructions for the LHS/RHS of the subtract.
///
Value *InstCombiner::OptimizePointerDifference(Value *LHS, Value *RHS,
- const Type *Ty) {
+ Type *Ty) {
assert(TD && "Must have target data info for this");
// If LHS is a gep based on RHS or RHS is a gep based on LHS, we can optimize
diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 64ea36f..5e0bfe8 100644
--- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1174,30 +1174,31 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
((A == C && B == D) || (A == D && B == C)))
return BinaryOperator::CreateXor(A, B);
- if (Op0->hasOneUse() &&
- match(Op0, m_Xor(m_Value(A), m_Value(B)))) {
- if (A == Op1) { // (A^B)&A -> A&(A^B)
- I.swapOperands(); // Simplify below
- std::swap(Op0, Op1);
- } else if (B == Op1) { // (A^B)&B -> B&(B^A)
- cast<BinaryOperator>(Op0)->swapOperands();
- I.swapOperands(); // Simplify below
- std::swap(Op0, Op1);
+ // A&(A^B) => A & ~B
+ {
+ Value *tmpOp0 = Op0;
+ Value *tmpOp1 = Op1;
+ if (Op0->hasOneUse() &&
+ match(Op0, m_Xor(m_Value(A), m_Value(B)))) {
+ if (A == Op1 || B == Op1 ) {
+ tmpOp1 = Op0;
+ tmpOp0 = Op1;
+ // Simplify below
+ }
}
- }
- if (Op1->hasOneUse() &&
- match(Op1, m_Xor(m_Value(A), m_Value(B)))) {
- if (B == Op0) { // B&(A^B) -> B&(B^A)
- cast<BinaryOperator>(Op1)->swapOperands();
- std::swap(A, B);
+ if (tmpOp1->hasOneUse() &&
+ match(tmpOp1, m_Xor(m_Value(A), m_Value(B)))) {
+ if (B == tmpOp0) {
+ std::swap(A, B);
+ }
+ // Notice that the patten (A&(~B)) is actually (A&(-1^B)), so if
+ // A is originally -1 (or a vector of -1 and undefs), then we enter
+ // an endless loop. By checking that A is non-constant we ensure that
+ // we will never get to the loop.
+ if (A == tmpOp0 && !isa<Constant>(A)) // A&(A^B) -> A & ~B
+ return BinaryOperator::CreateAnd(A, Builder->CreateNot(B));
}
- // Notice that the patten (A&(~B)) is actually (A&(-1^B)), so if
- // A is originally -1 (or a vector of -1 and undefs), then we enter
- // an endless loop. By checking that A is non-constant we ensure that
- // we will never get to the loop.
- if (A == Op0 && !isa<Constant>(A)) // A&(A^B) -> A & ~B
- return BinaryOperator::CreateAnd(A, Builder->CreateNot(B, "tmp"));
}
// (A&((~A)|B)) -> A&B
@@ -1224,7 +1225,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
// fold (and (cast A), (cast B)) -> (cast (and A, B))
if (CastInst *Op0C = dyn_cast<CastInst>(Op0))
if (CastInst *Op1C = dyn_cast<CastInst>(Op1)) {
- const Type *SrcTy = Op0C->getOperand(0)->getType();
+ Type *SrcTy = Op0C->getOperand(0)->getType();
if (Op0C->getOpcode() == Op1C->getOpcode() && // same cast kind ?
SrcTy == Op1C->getOperand(0)->getType() &&
SrcTy->isIntOrIntVectorTy()) {
@@ -2008,7 +2009,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
CastInst *Op1C = dyn_cast<CastInst>(Op1);
if (Op1C && Op0C->getOpcode() == Op1C->getOpcode()) {// same cast kind ?
- const Type *SrcTy = Op0C->getOperand(0)->getType();
+ Type *SrcTy = Op0C->getOperand(0)->getType();
if (SrcTy == Op1C->getOperand(0)->getType() &&
SrcTy->isIntOrIntVectorTy()) {
Value *Op0COp = Op0C->getOperand(0), *Op1COp = Op1C->getOperand(0);
@@ -2227,14 +2228,14 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
if (A == Op1) // (B|A)^B == (A|B)^B
std::swap(A, B);
if (B == Op1) // (A|B)^B == A & ~B
- return BinaryOperator::CreateAnd(A, Builder->CreateNot(Op1, "tmp"));
+ return BinaryOperator::CreateAnd(A, Builder->CreateNot(Op1));
} else if (match(Op0I, m_And(m_Value(A), m_Value(B))) &&
Op0I->hasOneUse()){
if (A == Op1) // (A&B)^A -> (B&A)^A
std::swap(A, B);
if (B == Op1 && // (B&A)^A == ~B & A
!isa<ConstantInt>(Op1)) { // Canonical form is (B&C)^C
- return BinaryOperator::CreateAnd(Builder->CreateNot(A, "tmp"), Op1);
+ return BinaryOperator::CreateAnd(Builder->CreateNot(A), Op1);
}
}
}
@@ -2288,7 +2289,7 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
if (CastInst *Op1C = dyn_cast<CastInst>(Op1))
if (Op0C->getOpcode() == Op1C->getOpcode()) { // same cast kind?
- const Type *SrcTy = Op0C->getOperand(0)->getType();
+ Type *SrcTy = Op0C->getOperand(0)->getType();
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegerTy() &&
// Only do this if the casts both really cause code to be generated.
ShouldOptimizeCast(Op0C->getOpcode(), Op0C->getOperand(0),
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 537f2b3..c7b3ff8 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "InstCombine.h"
-#include "llvm/IntrinsicInst.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Analysis/MemoryBuiltins.h"
@@ -22,8 +21,8 @@ using namespace llvm;
/// getPromotedType - Return the specified type promoted as it would be to pass
/// though a va_arg area.
-static const Type *getPromotedType(const Type *Ty) {
- if (const IntegerType* ITy = dyn_cast<IntegerType>(Ty)) {
+static Type *getPromotedType(Type *Ty) {
+ if (IntegerType* ITy = dyn_cast<IntegerType>(Ty)) {
if (ITy->getBitWidth() < 32)
return Type::getInt32Ty(Ty->getContext());
}
@@ -64,7 +63,7 @@ Instruction *InstCombiner::SimplifyMemTransfer(MemIntrinsic *MI) {
unsigned DstAddrSp =
cast<PointerType>(MI->getArgOperand(0)->getType())->getAddressSpace();
- const IntegerType* IntType = IntegerType::get(MI->getContext(), Size<<3);
+ IntegerType* IntType = IntegerType::get(MI->getContext(), Size<<3);
Type *NewSrcPtrTy = PointerType::get(IntType, SrcAddrSp);
Type *NewDstPtrTy = PointerType::get(IntType, DstAddrSp);
@@ -76,18 +75,18 @@ Instruction *InstCombiner::SimplifyMemTransfer(MemIntrinsic *MI) {
// integer datatype.
Value *StrippedDest = MI->getArgOperand(0)->stripPointerCasts();
if (StrippedDest != MI->getArgOperand(0)) {
- const Type *SrcETy = cast<PointerType>(StrippedDest->getType())
+ Type *SrcETy = cast<PointerType>(StrippedDest->getType())
->getElementType();
if (TD && SrcETy->isSized() && TD->getTypeStoreSize(SrcETy) == Size) {
// The SrcETy might be something like {{{double}}} or [1 x double]. Rip
// down through these levels if so.
while (!SrcETy->isSingleValueType()) {
- if (const StructType *STy = dyn_cast<StructType>(SrcETy)) {
+ if (StructType *STy = dyn_cast<StructType>(SrcETy)) {
if (STy->getNumElements() == 1)
SrcETy = STy->getElementType(0);
else
break;
- } else if (const ArrayType *ATy = dyn_cast<ArrayType>(SrcETy)) {
+ } else if (ArrayType *ATy = dyn_cast<ArrayType>(SrcETy)) {
if (ATy->getNumElements() == 1)
SrcETy = ATy->getElementType();
else
@@ -142,7 +141,7 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) {
// memset(s,c,n) -> store s, c (for n=1,2,4,8)
if (Len <= 8 && isPowerOf2_32((uint32_t)Len)) {
- const Type *ITy = IntegerType::get(MI->getContext(), Len*8); // n=1 -> i8.
+ Type *ITy = IntegerType::get(MI->getContext(), Len*8); // n=1 -> i8.
Value *Dest = MI->getDest();
unsigned DstAddrSp = cast<PointerType>(Dest->getType())->getAddressSpace();
@@ -250,7 +249,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
// We need target data for just about everything so depend on it.
if (!TD) break;
- const Type *ReturnTy = CI.getType();
+ Type *ReturnTy = CI.getType();
uint64_t DontKnow = II->getArgOperand(1) == Builder->getTrue() ? 0 : -1ULL;
// Get to the real allocated thing and offset as fast as possible.
@@ -266,8 +265,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
// Get the current byte offset into the thing. Use the original
// operand in case we're looking through a bitcast.
SmallVector<Value*, 8> Ops(GEP->idx_begin(), GEP->idx_end());
- Offset = TD->getIndexedOffset(GEP->getPointerOperandType(),
- Ops.data(), Ops.size());
+ Offset = TD->getIndexedOffset(GEP->getPointerOperandType(), Ops);
Op1 = GEP->getPointerOperand()->stripPointerCasts();
@@ -300,7 +298,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
}
} else if (CallInst *MI = extractMallocCall(Op1)) {
// Get allocation size.
- const Type* MallocType = getMallocAllocatedType(MI);
+ Type* MallocType = getMallocAllocatedType(MI);
if (MallocType && MallocType->isSized())
if (Value *NElems = getMallocArraySize(MI, TD, true))
if (ConstantInt *NElements = dyn_cast<ConstantInt>(NElems))
@@ -355,7 +353,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
case Intrinsic::cttz: {
// If all bits below the first known one are known zero,
// this value is constant.
- const IntegerType *IT = dyn_cast<IntegerType>(II->getArgOperand(0)->getType());
+ IntegerType *IT = dyn_cast<IntegerType>(II->getArgOperand(0)->getType());
// FIXME: Try to simplify vectors of integers.
if (!IT) break;
uint32_t BitWidth = IT->getBitWidth();
@@ -374,7 +372,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
case Intrinsic::ctlz: {
// If all bits above the first known one are known zero,
// this value is constant.
- const IntegerType *IT = dyn_cast<IntegerType>(II->getArgOperand(0)->getType());
+ IntegerType *IT = dyn_cast<IntegerType>(II->getArgOperand(0)->getType());
// FIXME: Try to simplify vectors of integers.
if (!IT) break;
uint32_t BitWidth = IT->getBitWidth();
@@ -392,7 +390,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
break;
case Intrinsic::uadd_with_overflow: {
Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1);
- const IntegerType *IT = cast<IntegerType>(II->getArgOperand(0)->getType());
+ IntegerType *IT = cast<IntegerType>(II->getArgOperand(0)->getType());
uint32_t BitWidth = IT->getBitWidth();
APInt Mask = APInt::getSignBit(BitWidth);
APInt LHSKnownZero(BitWidth, 0);
@@ -416,7 +414,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
UndefValue::get(LHS->getType()),
ConstantInt::getTrue(II->getContext())
};
- const StructType *ST = cast<StructType>(II->getType());
+ StructType *ST = cast<StructType>(II->getType());
Constant *Struct = ConstantStruct::get(ST, V);
return InsertValueInst::Create(Struct, Add, 0);
}
@@ -430,7 +428,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
UndefValue::get(LHS->getType()),
ConstantInt::getFalse(II->getContext())
};
- const StructType *ST = cast<StructType>(II->getType());
+ StructType *ST = cast<StructType>(II->getType());
Constant *Struct = ConstantStruct::get(ST, V);
return InsertValueInst::Create(Struct, Add, 0);
}
@@ -559,7 +557,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
case Intrinsic::ppc_altivec_stvxl:
// Turn stvx -> store if the pointer is known aligned.
if (getOrEnforceKnownAlignment(II->getArgOperand(1), 16, TD) >= 16) {
- const Type *OpPtrTy =
+ Type *OpPtrTy =
PointerType::getUnqual(II->getArgOperand(0)->getType());
Value *Ptr = Builder->CreateBitCast(II->getArgOperand(1), OpPtrTy);
return new StoreInst(II->getArgOperand(0), Ptr);
@@ -570,7 +568,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
case Intrinsic::x86_sse2_storeu_dq:
// Turn X86 storeu -> store if the pointer is known aligned.
if (getOrEnforceKnownAlignment(II->getArgOperand(0), 16, TD) >= 16) {
- const Type *OpPtrTy =
+ Type *OpPtrTy =
PointerType::getUnqual(II->getArgOperand(1)->getType());
Value *Ptr = Builder->CreateBitCast(II->getArgOperand(0), OpPtrTy);
return new StoreInst(II->getArgOperand(1), Ptr);
@@ -656,15 +654,13 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
if (ExtractedElts[Idx] == 0) {
ExtractedElts[Idx] =
- Builder->CreateExtractElement(Idx < 16 ? Op0 : Op1,
- ConstantInt::get(Type::getInt32Ty(II->getContext()),
- Idx&15, false), "tmp");
+ Builder->CreateExtractElement(Idx < 16 ? Op0 : Op1,
+ Builder->getInt32(Idx&15));
}
// Insert this value into the result vector.
Result = Builder->CreateInsertElement(Result, ExtractedElts[Idx],
- ConstantInt::get(Type::getInt32Ty(II->getContext()),
- i, false), "tmp");
+ Builder->getInt32(i));
}
return CastInst::Create(Instruction::BitCast, Result, CI.getType());
}
@@ -733,9 +729,11 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
}
}
- // If the stack restore is in a return/unwind block and if there are no
- // allocas or calls between the restore and the return, nuke the restore.
- if (!CannotRemove && (isa<ReturnInst>(TI) || isa<UnwindInst>(TI)))
+ // If the stack restore is in a return, resume, or unwind block and if there
+ // are no allocas or calls between the restore and the return, nuke the
+ // restore.
+ if (!CannotRemove && (isa<ReturnInst>(TI) || isa<ResumeInst>(TI) ||
+ isa<UnwindInst>(TI)))
return EraseInstFromFunction(CI);
break;
}
@@ -765,9 +763,9 @@ static bool isSafeToEliminateVarargsCast(const CallSite CS,
if (!CS.paramHasAttr(ix, Attribute::ByVal))
return true;
- const Type* SrcTy =
+ Type* SrcTy =
cast<PointerType>(CI->getOperand(0)->getType())->getElementType();
- const Type* DstTy = cast<PointerType>(CI->getType())->getElementType();
+ Type* DstTy = cast<PointerType>(CI->getType())->getElementType();
if (!SrcTy->isSized() || !DstTy->isSized())
return false;
if (!TD || TD->getTypeAllocSize(SrcTy) != TD->getTypeAllocSize(DstTy))
@@ -820,6 +818,83 @@ Instruction *InstCombiner::tryOptimizeCall(CallInst *CI, const TargetData *TD) {
return Simplifier.NewInstruction;
}
+static IntrinsicInst *FindInitTrampolineFromAlloca(Value *TrampMem) {
+ // Strip off at most one level of pointer casts, looking for an alloca. This
+ // is good enough in practice and simpler than handling any number of casts.
+ Value *Underlying = TrampMem->stripPointerCasts();
+ if (Underlying != TrampMem &&
+ (!Underlying->hasOneUse() || *Underlying->use_begin() != TrampMem))
+ return 0;
+ if (!isa<AllocaInst>(Underlying))
+ return 0;
+
+ IntrinsicInst *InitTrampoline = 0;
+ for (Value::use_iterator I = TrampMem->use_begin(), E = TrampMem->use_end();
+ I != E; I++) {
+ IntrinsicInst *II = dyn_cast<IntrinsicInst>(*I);
+ if (!II)
+ return 0;
+ if (II->getIntrinsicID() == Intrinsic::init_trampoline) {
+ if (InitTrampoline)
+ // More than one init_trampoline writes to this value. Give up.
+ return 0;
+ InitTrampoline = II;
+ continue;
+ }
+ if (II->getIntrinsicID() == Intrinsic::adjust_trampoline)
+ // Allow any number of calls to adjust.trampoline.
+ continue;
+ return 0;
+ }
+
+ // No call to init.trampoline found.
+ if (!InitTrampoline)
+ return 0;
+
+ // Check that the alloca is being used in the expected way.
+ if (InitTrampoline->getOperand(0) != TrampMem)
+ return 0;
+
+ return InitTrampoline;
+}
+
+static IntrinsicInst *FindInitTrampolineFromBB(IntrinsicInst *AdjustTramp,
+ Value *TrampMem) {
+ // Visit all the previous instructions in the basic block, and try to find a
+ // init.trampoline which has a direct path to the adjust.trampoline.
+ for (BasicBlock::iterator I = AdjustTramp,
+ E = AdjustTramp->getParent()->begin(); I != E; ) {
+ Instruction *Inst = --I;
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
+ if (II->getIntrinsicID() == Intrinsic::init_trampoline &&
+ II->getOperand(0) == TrampMem)
+ return II;
+ if (Inst->mayWriteToMemory())
+ return 0;
+ }
+ return 0;
+}
+
+// Given a call to llvm.adjust.trampoline, find and return the corresponding
+// call to llvm.init.trampoline if the call to the trampoline can be optimized
+// to a direct call to a function. Otherwise return NULL.
+//
+static IntrinsicInst *FindInitTrampoline(Value *Callee) {
+ Callee = Callee->stripPointerCasts();
+ IntrinsicInst *AdjustTramp = dyn_cast<IntrinsicInst>(Callee);
+ if (!AdjustTramp ||
+ AdjustTramp->getIntrinsicID() != Intrinsic::adjust_trampoline)
+ return 0;
+
+ Value *TrampMem = AdjustTramp->getOperand(0);
+
+ if (IntrinsicInst *IT = FindInitTrampolineFromAlloca(TrampMem))
+ return IT;
+ if (IntrinsicInst *IT = FindInitTrampolineFromBB(AdjustTramp, TrampMem))
+ return IT;
+ return 0;
+}
+
// visitCallSite - Improvements for call and invoke instructions.
//
Instruction *InstCombiner::visitCallSite(CallSite CS) {
@@ -879,13 +954,11 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) {
return EraseInstFromFunction(*CS.getInstruction());
}
- if (BitCastInst *BC = dyn_cast<BitCastInst>(Callee))
- if (IntrinsicInst *In = dyn_cast<IntrinsicInst>(BC->getOperand(0)))
- if (In->getIntrinsicID() == Intrinsic::init_trampoline)
- return transformCallThroughTrampoline(CS);
+ if (IntrinsicInst *II = FindInitTrampoline(Callee))
+ return transformCallThroughTrampoline(CS, II);
- const PointerType *PTy = cast<PointerType>(Callee->getType());
- const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+ PointerType *PTy = cast<PointerType>(Callee->getType());
+ FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
if (FTy->isVarArg()) {
int ix = FTy->getNumParams() + (isa<InvokeInst>(Callee) ? 3 : 1);
// See if we can optimize any arguments passed through the varargs area of
@@ -934,9 +1007,9 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
// would cause a type conversion of one of our arguments, change this call to
// be a direct call with arguments casted to the appropriate types.
//
- const FunctionType *FT = Callee->getFunctionType();
- const Type *OldRetTy = Caller->getType();
- const Type *NewRetTy = FT->getReturnType();
+ FunctionType *FT = Callee->getFunctionType();
+ Type *OldRetTy = Caller->getType();
+ Type *NewRetTy = FT->getReturnType();
if (NewRetTy->isStructTy())
return false; // TODO: Handle multiple return values.
@@ -982,8 +1055,8 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
CallSite::arg_iterator AI = CS.arg_begin();
for (unsigned i = 0, e = NumCommonArgs; i != e; ++i, ++AI) {
- const Type *ParamTy = FT->getParamType(i);
- const Type *ActTy = (*AI)->getType();
+ Type *ParamTy = FT->getParamType(i);
+ Type *ActTy = (*AI)->getType();
if (!CastInst::isCastable(ActTy, ParamTy))
return false; // Cannot transform this parameter value.
@@ -995,11 +1068,11 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
// If the parameter is passed as a byval argument, then we have to have a
// sized type and the sized type has to have the same size as the old type.
if (ParamTy != ActTy && (Attrs & Attribute::ByVal)) {
- const PointerType *ParamPTy = dyn_cast<PointerType>(ParamTy);
+ PointerType *ParamPTy = dyn_cast<PointerType>(ParamTy);
if (ParamPTy == 0 || !ParamPTy->getElementType()->isSized() || TD == 0)
return false;
- const Type *CurElTy = cast<PointerType>(ActTy)->getElementType();
+ Type *CurElTy = cast<PointerType>(ActTy)->getElementType();
if (TD->getTypeAllocSize(CurElTy) !=
TD->getTypeAllocSize(ParamPTy->getElementType()))
return false;
@@ -1023,7 +1096,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
// If the callee is just a declaration, don't change the varargsness of the
// call. We don't want to introduce a varargs call where one doesn't
// already exist.
- const PointerType *APTy = cast<PointerType>(CS.getCalledValue()->getType());
+ PointerType *APTy = cast<PointerType>(CS.getCalledValue()->getType());
if (FT->isVarArg()!=cast<FunctionType>(APTy->getElementType())->isVarArg())
return false;
}
@@ -1062,13 +1135,13 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
AI = CS.arg_begin();
for (unsigned i = 0; i != NumCommonArgs; ++i, ++AI) {
- const Type *ParamTy = FT->getParamType(i);
+ Type *ParamTy = FT->getParamType(i);
if ((*AI)->getType() == ParamTy) {
Args.push_back(*AI);
} else {
Instruction::CastOps opcode = CastInst::getCastOpcode(*AI,
false, ParamTy, false);
- Args.push_back(Builder->CreateCast(opcode, *AI, ParamTy, "tmp"));
+ Args.push_back(Builder->CreateCast(opcode, *AI, ParamTy));
}
// Add any parameter attributes.
@@ -1089,12 +1162,12 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
} else {
// Add all of the arguments in their promoted form to the arg list.
for (unsigned i = FT->getNumParams(); i != NumActualArgs; ++i, ++AI) {
- const Type *PTy = getPromotedType((*AI)->getType());
+ Type *PTy = getPromotedType((*AI)->getType());
if (PTy != (*AI)->getType()) {
// Must promote to pass through va_arg area!
Instruction::CastOps opcode =
CastInst::getCastOpcode(*AI, false, PTy, false);
- Args.push_back(Builder->CreateCast(opcode, *AI, PTy, "tmp"));
+ Args.push_back(Builder->CreateCast(opcode, *AI, PTy));
} else {
Args.push_back(*AI);
}
@@ -1138,13 +1211,13 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
if (!NV->getType()->isVoidTy()) {
Instruction::CastOps opcode =
CastInst::getCastOpcode(NC, false, OldRetTy, false);
- NV = NC = CastInst::Create(opcode, NC, OldRetTy, "tmp");
+ NV = NC = CastInst::Create(opcode, NC, OldRetTy);
NC->setDebugLoc(Caller->getDebugLoc());
// If this is an invoke instruction, we should insert it after the first
// non-phi, instruction in the normal successor block.
if (InvokeInst *II = dyn_cast<InvokeInst>(Caller)) {
- BasicBlock::iterator I = II->getNormalDest()->getFirstNonPHI();
+ BasicBlock::iterator I = II->getNormalDest()->getFirstInsertionPt();
InsertNewInstBefore(NC, *I);
} else {
// Otherwise, it's a call, just insert cast right after the call.
@@ -1163,13 +1236,16 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) {
return true;
}
-// transformCallThroughTrampoline - Turn a call to a function created by the
-// init_trampoline intrinsic into a direct call to the underlying function.
+// transformCallThroughTrampoline - Turn a call to a function created by
+// init_trampoline / adjust_trampoline intrinsic pair into a direct call to the
+// underlying function.
//
-Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) {
+Instruction *
+InstCombiner::transformCallThroughTrampoline(CallSite CS,
+ IntrinsicInst *Tramp) {
Value *Callee = CS.getCalledValue();
- const PointerType *PTy = cast<PointerType>(Callee->getType());
- const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+ PointerType *PTy = cast<PointerType>(Callee->getType());
+ FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
const AttrListPtr &Attrs = CS.getAttributes();
// If the call already has the 'nest' attribute somewhere then give up -
@@ -1177,12 +1253,12 @@ Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) {
if (Attrs.hasAttrSomewhere(Attribute::Nest))
return 0;
- IntrinsicInst *Tramp =
- cast<IntrinsicInst>(cast<BitCastInst>(Callee)->getOperand(0));
+ assert(Tramp &&
+ "transformCallThroughTrampoline called with incorrect CallSite.");
Function *NestF =cast<Function>(Tramp->getArgOperand(1)->stripPointerCasts());
- const PointerType *NestFPTy = cast<PointerType>(NestF->getType());
- const FunctionType *NestFTy = cast<FunctionType>(NestFPTy->getElementType());
+ PointerType *NestFPTy = cast<PointerType>(NestF->getType());
+ FunctionType *NestFTy = cast<FunctionType>(NestFPTy->getElementType());
const AttrListPtr &NestAttrs = NestF->getAttributes();
if (!NestAttrs.isEmpty()) {
diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 82c734e..f10e48a 100644
--- a/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "InstCombine.h"
+#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/PatternMatch.h"
using namespace llvm;
@@ -79,14 +80,14 @@ Instruction *InstCombiner::PromoteCastOfAllocation(BitCastInst &CI,
// This requires TargetData to get the alloca alignment and size information.
if (!TD) return 0;
- const PointerType *PTy = cast<PointerType>(CI.getType());
+ PointerType *PTy = cast<PointerType>(CI.getType());
BuilderTy AllocaBuilder(*Builder);
AllocaBuilder.SetInsertPoint(AI.getParent(), &AI);
// Get the type really allocated and the type casted to.
- const Type *AllocElTy = AI.getAllocatedType();
- const Type *CastElTy = PTy->getElementType();
+ Type *AllocElTy = AI.getAllocatedType();
+ Type *CastElTy = PTy->getElementType();
if (!AllocElTy->isSized() || !CastElTy->isSized()) return 0;
unsigned AllocElTyAlign = TD->getABITypeAlignment(AllocElTy);
@@ -121,13 +122,13 @@ Instruction *InstCombiner::PromoteCastOfAllocation(BitCastInst &CI,
} else {
Amt = ConstantInt::get(AI.getArraySize()->getType(), Scale);
// Insert before the alloca, not before the cast.
- Amt = AllocaBuilder.CreateMul(Amt, NumElements, "tmp");
+ Amt = AllocaBuilder.CreateMul(Amt, NumElements);
}
if (uint64_t Offset = (AllocElTySize*ArrayOffset)/CastElTySize) {
Value *Off = ConstantInt::get(AI.getArraySize()->getType(),
Offset, true);
- Amt = AllocaBuilder.CreateAdd(Amt, Off, "tmp");
+ Amt = AllocaBuilder.CreateAdd(Amt, Off);
}
AllocaInst *New = AllocaBuilder.CreateAlloca(CastElTy, Amt);
@@ -151,7 +152,7 @@ Instruction *InstCombiner::PromoteCastOfAllocation(BitCastInst &CI,
/// EvaluateInDifferentType - Given an expression that
/// CanEvaluateTruncated or CanEvaluateSExtd returns true for, actually
/// insert the code to evaluate the expression.
-Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty,
+Value *InstCombiner::EvaluateInDifferentType(Value *V, Type *Ty,
bool isSigned) {
if (Constant *C = dyn_cast<Constant>(V)) {
C = ConstantExpr::getIntegerCast(C, Ty, isSigned /*Sext or ZExt*/);
@@ -229,12 +230,12 @@ static Instruction::CastOps
isEliminableCastPair(
const CastInst *CI, ///< The first cast instruction
unsigned opcode, ///< The opcode of the second cast instruction
- const Type *DstTy, ///< The target type for the second cast instruction
+ Type *DstTy, ///< The target type for the second cast instruction
TargetData *TD ///< The target data for pointer size
) {
- const Type *SrcTy = CI->getOperand(0)->getType(); // A from above
- const Type *MidTy = CI->getType(); // B from above
+ Type *SrcTy = CI->getOperand(0)->getType(); // A from above
+ Type *MidTy = CI->getType(); // B from above
// Get the opcodes of the two Cast instructions
Instruction::CastOps firstOp = Instruction::CastOps(CI->getOpcode());
@@ -260,7 +261,7 @@ isEliminableCastPair(
/// the cast can be eliminated by some other simple transformation, we prefer
/// to do the simplification first.
bool InstCombiner::ShouldOptimizeCast(Instruction::CastOps opc, const Value *V,
- const Type *Ty) {
+ Type *Ty) {
// Noop casts and casts of constants should be eliminated trivially.
if (V->getType() == Ty || isa<Constant>(V)) return false;
@@ -324,7 +325,7 @@ Instruction *InstCombiner::commonCastTransforms(CastInst &CI) {
///
/// This function works on both vectors and scalars.
///
-static bool CanEvaluateTruncated(Value *V, const Type *Ty) {
+static bool CanEvaluateTruncated(Value *V, Type *Ty) {
// We can always evaluate constants in another type.
if (isa<Constant>(V))
return true;
@@ -332,7 +333,7 @@ static bool CanEvaluateTruncated(Value *V, const Type *Ty) {
Instruction *I = dyn_cast<Instruction>(V);
if (!I) return false;
- const Type *OrigTy = V->getType();
+ Type *OrigTy = V->getType();
// If this is an extension from the dest type, we can eliminate it, even if it
// has multiple uses.
@@ -435,7 +436,7 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
return &CI;
Value *Src = CI.getOperand(0);
- const Type *DestTy = CI.getType(), *SrcTy = Src->getType();
+ Type *DestTy = CI.getType(), *SrcTy = Src->getType();
// Attempt to truncate the entire input expression tree to the destination
// type. Only do this if the dest type is a simple type, don't convert the
@@ -456,7 +457,7 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
// Canonicalize trunc x to i1 -> (icmp ne (and x, 1), 0), likewise for vector.
if (DestTy->getScalarSizeInBits() == 1) {
Constant *One = ConstantInt::get(Src->getType(), 1);
- Src = Builder->CreateAnd(Src, One, "tmp");
+ Src = Builder->CreateAnd(Src, One);
Value *Zero = Constant::getNullValue(Src->getType());
return new ICmpInst(ICmpInst::ICMP_NE, Src, Zero);
}
@@ -518,7 +519,7 @@ Instruction *InstCombiner::transformZExtICmp(ICmpInst *ICI, Instruction &CI,
In->getType()->getScalarSizeInBits()-1);
In = Builder->CreateLShr(In, Sh, In->getName()+".lobit");
if (In->getType() != CI.getType())
- In = Builder->CreateIntCast(In, CI.getType(), false/*ZExt*/, "tmp");
+ In = Builder->CreateIntCast(In, CI.getType(), false/*ZExt*/);
if (ICI->getPredicate() == ICmpInst::ICMP_SGT) {
Constant *One = ConstantInt::get(In->getType(), 1);
@@ -572,7 +573,7 @@ Instruction *InstCombiner::transformZExtICmp(ICmpInst *ICI, Instruction &CI,
if ((Op1CV != 0) == isNE) { // Toggle the low bit.
Constant *One = ConstantInt::get(In->getType(), 1);
- In = Builder->CreateXor(In, One, "tmp");
+ In = Builder->CreateXor(In, One);
}
if (CI.getType() == In->getType())
@@ -586,7 +587,7 @@ Instruction *InstCombiner::transformZExtICmp(ICmpInst *ICI, Instruction &CI,
// It is also profitable to transform icmp eq into not(xor(A, B)) because that
// may lead to additional simplifications.
if (ICI->isEquality() && CI.getType() == ICI->getOperand(0)->getType()) {
- if (const IntegerType *ITy = dyn_cast<IntegerType>(CI.getType())) {
+ if (IntegerType *ITy = dyn_cast<IntegerType>(CI.getType())) {
uint32_t BitWidth = ITy->getBitWidth();
Value *LHS = ICI->getOperand(0);
Value *RHS = ICI->getOperand(1);
@@ -644,7 +645,7 @@ Instruction *InstCombiner::transformZExtICmp(ICmpInst *ICI, Instruction &CI,
/// clear the top bits anyway, doing this has no extra cost.
///
/// This function works on both vectors and scalars.
-static bool CanEvaluateZExtd(Value *V, const Type *Ty, unsigned &BitsToClear) {
+static bool CanEvaluateZExtd(Value *V, Type *Ty, unsigned &BitsToClear) {
BitsToClear = 0;
if (isa<Constant>(V))
return true;
@@ -758,7 +759,7 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) {
return &CI;
Value *Src = CI.getOperand(0);
- const Type *SrcTy = Src->getType(), *DestTy = CI.getType();
+ Type *SrcTy = Src->getType(), *DestTy = CI.getType();
// Attempt to extend the entire input expression tree to the destination
// type. Only do this if the dest type is a simple type, don't convert the
@@ -820,7 +821,7 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) {
AndValue));
}
if (SrcSize > DstSize) {
- Value *Trunc = Builder->CreateTrunc(A, CI.getType(), "tmp");
+ Value *Trunc = Builder->CreateTrunc(A, CI.getType());
APInt AndValue(APInt::getLowBitsSet(DstSize, MidSize));
return BinaryOperator::CreateAnd(Trunc,
ConstantInt::get(Trunc->getType(),
@@ -867,7 +868,7 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) {
Value *TI0 = TI->getOperand(0);
if (TI0->getType() == CI.getType()) {
Constant *ZC = ConstantExpr::getZExt(C, CI.getType());
- Value *NewAnd = Builder->CreateAnd(TI0, ZC, "tmp");
+ Value *NewAnd = Builder->CreateAnd(TI0, ZC);
return BinaryOperator::CreateXor(NewAnd, ZC);
}
}
@@ -900,7 +901,7 @@ Instruction *InstCombiner::transformSExtICmp(ICmpInst *ICI, Instruction &CI) {
Op0->getType()->getScalarSizeInBits()-1);
Value *In = Builder->CreateAShr(Op0, Sh, Op0->getName()+".lobit");
if (In->getType() != CI.getType())
- In = Builder->CreateIntCast(In, CI.getType(), true/*SExt*/, "tmp");
+ In = Builder->CreateIntCast(In, CI.getType(), true/*SExt*/);
if (Pred == ICmpInst::ICMP_SGT)
In = Builder->CreateNot(In, In->getName()+".not");
@@ -965,10 +966,10 @@ Instruction *InstCombiner::transformSExtICmp(ICmpInst *ICI, Instruction &CI) {
}
// vector (x <s 0) ? -1 : 0 -> ashr x, 31 -> all ones if signed.
- if (const VectorType *VTy = dyn_cast<VectorType>(CI.getType())) {
+ if (VectorType *VTy = dyn_cast<VectorType>(CI.getType())) {
if (Pred == ICmpInst::ICMP_SLT && match(Op1, m_Zero()) &&
Op0->getType() == CI.getType()) {
- const Type *EltTy = VTy->getElementType();
+ Type *EltTy = VTy->getElementType();
// splat the shift constant to a constant vector.
Constant *VSh = ConstantInt::get(VTy, EltTy->getScalarSizeInBits()-1);
@@ -988,7 +989,7 @@ Instruction *InstCombiner::transformSExtICmp(ICmpInst *ICI, Instruction &CI) {
///
/// This function works on both vectors and scalars.
///
-static bool CanEvaluateSExtd(Value *V, const Type *Ty) {
+static bool CanEvaluateSExtd(Value *V, Type *Ty) {
assert(V->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits() &&
"Can't sign extend type to a smaller type");
// If this is a constant, it can be trivially promoted.
@@ -1063,7 +1064,7 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) {
return &CI;
Value *Src = CI.getOperand(0);
- const Type *SrcTy = Src->getType(), *DestTy = CI.getType();
+ Type *SrcTy = Src->getType(), *DestTy = CI.getType();
// Attempt to extend the entire input expression tree to the destination
// type. Only do this if the dest type is a simple type, don't convert the
@@ -1192,7 +1193,7 @@ Instruction *InstCombiner::visitFPTrunc(FPTruncInst &CI) {
case Instruction::FMul:
case Instruction::FDiv:
case Instruction::FRem:
- const Type *SrcTy = OpI->getType();
+ Type *SrcTy = OpI->getType();
Value *LHSTrunc = LookThroughFPExtensions(OpI->getOperand(0));
Value *RHSTrunc = LookThroughFPExtensions(OpI->getOperand(1));
if (LHSTrunc->getType() != SrcTy &&
@@ -1306,13 +1307,13 @@ Instruction *InstCombiner::visitIntToPtr(IntToPtrInst &CI) {
if (CI.getOperand(0)->getType()->getScalarSizeInBits() >
TD->getPointerSizeInBits()) {
Value *P = Builder->CreateTrunc(CI.getOperand(0),
- TD->getIntPtrType(CI.getContext()), "tmp");
+ TD->getIntPtrType(CI.getContext()));
return new IntToPtrInst(P, CI.getType());
}
if (CI.getOperand(0)->getType()->getScalarSizeInBits() <
TD->getPointerSizeInBits()) {
Value *P = Builder->CreateZExt(CI.getOperand(0),
- TD->getIntPtrType(CI.getContext()), "tmp");
+ TD->getIntPtrType(CI.getContext()));
return new IntToPtrInst(P, CI.getType());
}
}
@@ -1351,7 +1352,7 @@ Instruction *InstCombiner::commonPointerCastTransforms(CastInst &CI) {
// Get the base pointer input of the bitcast, and the type it points to.
Value *OrigBase = cast<BitCastInst>(GEP->getOperand(0))->getOperand(0);
- const Type *GEPIdxTy =
+ Type *GEPIdxTy =
cast<PointerType>(OrigBase->getType())->getElementType();
SmallVector<Value*, 8> NewIndices;
if (FindElementAtOffset(GEPIdxTy, Offset, NewIndices)) {
@@ -1359,9 +1360,8 @@ Instruction *InstCombiner::commonPointerCastTransforms(CastInst &CI) {
// and bitcast the result. This eliminates one bitcast, potentially
// two.
Value *NGEP = cast<GEPOperator>(GEP)->isInBounds() ?
- Builder->CreateInBoundsGEP(OrigBase,
- NewIndices.begin(), NewIndices.end()) :
- Builder->CreateGEP(OrigBase, NewIndices.begin(), NewIndices.end());
+ Builder->CreateInBoundsGEP(OrigBase, NewIndices) :
+ Builder->CreateGEP(OrigBase, NewIndices);
NGEP->takeName(GEP);
if (isa<BitCastInst>(CI))
@@ -1382,14 +1382,12 @@ Instruction *InstCombiner::visitPtrToInt(PtrToIntInst &CI) {
if (TD) {
if (CI.getType()->getScalarSizeInBits() < TD->getPointerSizeInBits()) {
Value *P = Builder->CreatePtrToInt(CI.getOperand(0),
- TD->getIntPtrType(CI.getContext()),
- "tmp");
+ TD->getIntPtrType(CI.getContext()));
return new TruncInst(P, CI.getType());
}
if (CI.getType()->getScalarSizeInBits() > TD->getPointerSizeInBits()) {
Value *P = Builder->CreatePtrToInt(CI.getOperand(0),
- TD->getIntPtrType(CI.getContext()),
- "tmp");
+ TD->getIntPtrType(CI.getContext()));
return new ZExtInst(P, CI.getType());
}
}
@@ -1402,12 +1400,12 @@ Instruction *InstCombiner::visitPtrToInt(PtrToIntInst &CI) {
/// replace it with a shuffle (and vector/vector bitcast) if possible.
///
/// The source and destination vector types may have different element types.
-static Instruction *OptimizeVectorResize(Value *InVal, const VectorType *DestTy,
+static Instruction *OptimizeVectorResize(Value *InVal, VectorType *DestTy,
InstCombiner &IC) {
// We can only do this optimization if the output is a multiple of the input
// element size, or the input is a multiple of the output element size.
// Convert the input type to have the same element type as the output.
- const VectorType *SrcTy = cast<VectorType>(InVal->getType());
+ VectorType *SrcTy = cast<VectorType>(InVal->getType());
if (SrcTy->getElementType() != DestTy->getElementType()) {
// The input types don't need to be identical, but for now they must be the
@@ -1427,7 +1425,7 @@ static Instruction *OptimizeVectorResize(Value *InVal, const VectorType *DestTy,
// size of the input.
SmallVector<Constant*, 16> ShuffleMask;
Value *V2;
- const IntegerType *Int32Ty = Type::getInt32Ty(SrcTy->getContext());
+ IntegerType *Int32Ty = Type::getInt32Ty(SrcTy->getContext());
if (SrcTy->getNumElements() > DestTy->getNumElements()) {
// If we're shrinking the number of elements, just shuffle in the low
@@ -1453,11 +1451,11 @@ static Instruction *OptimizeVectorResize(Value *InVal, const VectorType *DestTy,
return new ShuffleVectorInst(InVal, V2, ConstantVector::get(ShuffleMask));
}
-static bool isMultipleOfTypeSize(unsigned Value, const Type *Ty) {
+static bool isMultipleOfTypeSize(unsigned Value, Type *Ty) {
return Value % Ty->getPrimitiveSizeInBits() == 0;
}
-static unsigned getTypeSizeIndex(unsigned Value, const Type *Ty) {
+static unsigned getTypeSizeIndex(unsigned Value, Type *Ty) {
return Value / Ty->getPrimitiveSizeInBits();
}
@@ -1471,7 +1469,7 @@ static unsigned getTypeSizeIndex(unsigned Value, const Type *Ty) {
/// filling in Elements with the elements found here.
static bool CollectInsertionElements(Value *V, unsigned ElementIndex,
SmallVectorImpl<Value*> &Elements,
- const Type *VecEltTy) {
+ Type *VecEltTy) {
// Undef values never contribute useful bits to the result.
if (isa<UndefValue>(V)) return true;
@@ -1508,7 +1506,7 @@ static bool CollectInsertionElements(Value *V, unsigned ElementIndex,
C = ConstantExpr::getBitCast(C, IntegerType::get(V->getContext(),
C->getType()->getPrimitiveSizeInBits()));
unsigned ElementSize = VecEltTy->getPrimitiveSizeInBits();
- const Type *ElementIntTy = IntegerType::get(C->getContext(), ElementSize);
+ Type *ElementIntTy = IntegerType::get(C->getContext(), ElementSize);
for (unsigned i = 0; i != NumElts; ++i) {
Constant *Piece = ConstantExpr::getLShr(C, ConstantInt::get(C->getType(),
@@ -1572,7 +1570,7 @@ static bool CollectInsertionElements(Value *V, unsigned ElementIndex,
/// Into two insertelements that do "buildvector{%inc, %inc5}".
static Value *OptimizeIntegerToVectorInsertions(BitCastInst &CI,
InstCombiner &IC) {
- const VectorType *DestVecTy = cast<VectorType>(CI.getType());
+ VectorType *DestVecTy = cast<VectorType>(CI.getType());
Value *IntInput = CI.getOperand(0);
SmallVector<Value*, 8> Elements(DestVecTy->getNumElements());
@@ -1599,7 +1597,7 @@ static Value *OptimizeIntegerToVectorInsertions(BitCastInst &CI,
/// bitcast. The various long double bitcasts can't get in here.
static Instruction *OptimizeIntToFloatBitCast(BitCastInst &CI,InstCombiner &IC){
Value *Src = CI.getOperand(0);
- const Type *DestTy = CI.getType();
+ Type *DestTy = CI.getType();
// If this is a bitcast from int to float, check to see if the int is an
// extraction from a vector.
@@ -1607,7 +1605,7 @@ static Instruction *OptimizeIntToFloatBitCast(BitCastInst &CI,InstCombiner &IC){
// bitcast(trunc(bitcast(somevector)))
if (match(Src, m_Trunc(m_BitCast(m_Value(VecInput)))) &&
isa<VectorType>(VecInput->getType())) {
- const VectorType *VecTy = cast<VectorType>(VecInput->getType());
+ VectorType *VecTy = cast<VectorType>(VecInput->getType());
unsigned DestWidth = DestTy->getPrimitiveSizeInBits();
if (VecTy->getPrimitiveSizeInBits() % DestWidth == 0) {
@@ -1628,7 +1626,7 @@ static Instruction *OptimizeIntToFloatBitCast(BitCastInst &CI,InstCombiner &IC){
if (match(Src, m_Trunc(m_LShr(m_BitCast(m_Value(VecInput)),
m_ConstantInt(ShAmt)))) &&
isa<VectorType>(VecInput->getType())) {
- const VectorType *VecTy = cast<VectorType>(VecInput->getType());
+ VectorType *VecTy = cast<VectorType>(VecInput->getType());
unsigned DestWidth = DestTy->getPrimitiveSizeInBits();
if (VecTy->getPrimitiveSizeInBits() % DestWidth == 0 &&
ShAmt->getZExtValue() % DestWidth == 0) {
@@ -1651,18 +1649,18 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) {
// If the operands are integer typed then apply the integer transforms,
// otherwise just apply the common ones.
Value *Src = CI.getOperand(0);
- const Type *SrcTy = Src->getType();
- const Type *DestTy = CI.getType();
+ Type *SrcTy = Src->getType();
+ Type *DestTy = CI.getType();
// Get rid of casts from one type to the same type. These are useless and can
// be replaced by the operand.
if (DestTy == Src->getType())
return ReplaceInstUsesWith(CI, Src);
- if (const PointerType *DstPTy = dyn_cast<PointerType>(DestTy)) {
- const PointerType *SrcPTy = cast<PointerType>(SrcTy);
- const Type *DstElTy = DstPTy->getElementType();
- const Type *SrcElTy = SrcPTy->getElementType();
+ if (PointerType *DstPTy = dyn_cast<PointerType>(DestTy)) {
+ PointerType *SrcPTy = cast<PointerType>(SrcTy);
+ Type *DstElTy = DstPTy->getElementType();
+ Type *SrcElTy = SrcPTy->getElementType();
// If the address spaces don't match, don't eliminate the bitcast, which is
// required for changing types.
@@ -1693,7 +1691,7 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) {
// If we found a path from the src to dest, create the getelementptr now.
if (SrcElTy == DstElTy) {
SmallVector<Value*, 8> Idxs(NumZeros+1, ZeroUInt);
- return GetElementPtrInst::CreateInBounds(Src, Idxs.begin(), Idxs.end());
+ return GetElementPtrInst::CreateInBounds(Src, Idxs);
}
}
@@ -1702,7 +1700,7 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) {
if (Instruction *I = OptimizeIntToFloatBitCast(CI, *this))
return I;
- if (const VectorType *DestVTy = dyn_cast<VectorType>(DestTy)) {
+ if (VectorType *DestVTy = dyn_cast<VectorType>(DestTy)) {
if (DestVTy->getNumElements() == 1 && !SrcTy->isVectorTy()) {
Value *Elem = Builder->CreateBitCast(Src, DestVTy->getElementType());
return InsertElementInst::Create(UndefValue::get(DestTy), Elem,
@@ -1731,7 +1729,7 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) {
}
}
- if (const VectorType *SrcVTy = dyn_cast<VectorType>(SrcTy)) {
+ if (VectorType *SrcVTy = dyn_cast<VectorType>(SrcTy)) {
if (SrcVTy->getNumElements() == 1 && !DestTy->isVectorTy()) {
Value *Elem =
Builder->CreateExtractElement(Src,
diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp
index c78760b..bb1cbfa 100644
--- a/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -13,6 +13,7 @@
#include "InstCombine.h"
#include "llvm/IntrinsicInst.h"
+#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Target/TargetData.h"
@@ -56,7 +57,7 @@ static bool AddWithOverflow(Constant *&Result, Constant *In1,
Constant *In2, bool IsSigned = false) {
Result = ConstantExpr::getAdd(In1, In2);
- if (const VectorType *VTy = dyn_cast<VectorType>(In1->getType())) {
+ if (VectorType *VTy = dyn_cast<VectorType>(In1->getType())) {
for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) {
Constant *Idx = ConstantInt::get(Type::getInt32Ty(In1->getContext()), i);
if (HasAddOverflow(ExtractElement(Result, Idx),
@@ -78,7 +79,7 @@ static bool HasSubOverflow(ConstantInt *Result,
bool IsSigned) {
if (!IsSigned)
return Result->getValue().ugt(In1->getValue());
-
+
if (In2->isNegative())
return Result->getValue().slt(In1->getValue());
@@ -91,7 +92,7 @@ static bool SubWithOverflow(Constant *&Result, Constant *In1,
Constant *In2, bool IsSigned = false) {
Result = ConstantExpr::getSub(In1, In2);
- if (const VectorType *VTy = dyn_cast<VectorType>(In1->getType())) {
+ if (VectorType *VTy = dyn_cast<VectorType>(In1->getType())) {
for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) {
Constant *Idx = ConstantInt::get(Type::getInt32Ty(In1->getContext()), i);
if (HasSubOverflow(ExtractElement(Result, Idx),
@@ -128,7 +129,7 @@ static bool isSignBitCheck(ICmpInst::Predicate pred, ConstantInt *RHS,
// True if LHS u> RHS and RHS == high-bit-mask - 1
TrueIfSigned = true;
return RHS->isMaxValue(true);
- case ICmpInst::ICMP_UGE:
+ case ICmpInst::ICMP_UGE:
// True if LHS u>= RHS and RHS == high-bit-mask (2^7, 2^15, 2^31, etc)
TrueIfSigned = true;
return RHS->getValue().isSignBit();
@@ -143,7 +144,7 @@ static bool isHighOnes(const ConstantInt *CI) {
return (~CI->getValue() + 1).isPowerOf2();
}
-/// ComputeSignedMinMaxValuesFromKnownBits - Given a signed integer type and a
+/// ComputeSignedMinMaxValuesFromKnownBits - Given a signed integer type and a
/// set of known zero and one bits, compute the maximum and minimum values that
/// could have the specified known zero and known one bits, returning them in
/// min/max.
@@ -160,7 +161,7 @@ static void ComputeSignedMinMaxValuesFromKnownBits(const APInt& KnownZero,
// bit if it is unknown.
Min = KnownOne;
Max = KnownOne|UnknownBits;
-
+
if (UnknownBits.isNegative()) { // Sign bit is unknown
Min.setBit(Min.getBitWidth()-1);
Max.clearBit(Max.getBitWidth()-1);
@@ -179,7 +180,7 @@ static void ComputeUnsignedMinMaxValuesFromKnownBits(const APInt &KnownZero,
KnownZero.getBitWidth() == Max.getBitWidth() &&
"Ty, KnownZero, KnownOne and Min, Max must have equal bitwidth.");
APInt UnknownBits = ~(KnownZero|KnownOne);
-
+
// The minimum value is when the unknown bits are all zeros.
Min = KnownOne;
// The maximum value is when the unknown bits are all ones.
@@ -201,10 +202,10 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
CmpInst &ICI, ConstantInt *AndCst) {
// We need TD information to know the pointer size unless this is inbounds.
if (!GEP->isInBounds() && TD == 0) return 0;
-
+
ConstantArray *Init = dyn_cast<ConstantArray>(GV->getInitializer());
if (Init == 0 || Init->getNumOperands() > 1024) return 0;
-
+
// There are many forms of this optimization we can handle, for now, just do
// the simple index into a single-dimensional array.
//
@@ -219,31 +220,31 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
// type they index. Collect the indices. This is typically for arrays of
// structs.
SmallVector<unsigned, 4> LaterIndices;
-
- const Type *EltTy = cast<ArrayType>(Init->getType())->getElementType();
+
+ Type *EltTy = cast<ArrayType>(Init->getType())->getElementType();
for (unsigned i = 3, e = GEP->getNumOperands(); i != e; ++i) {
ConstantInt *Idx = dyn_cast<ConstantInt>(GEP->getOperand(i));
if (Idx == 0) return 0; // Variable index.
-
+
uint64_t IdxVal = Idx->getZExtValue();
if ((unsigned)IdxVal != IdxVal) return 0; // Too large array index.
-
- if (const StructType *STy = dyn_cast<StructType>(EltTy))
+
+ if (StructType *STy = dyn_cast<StructType>(EltTy))
EltTy = STy->getElementType(IdxVal);
- else if (const ArrayType *ATy = dyn_cast<ArrayType>(EltTy)) {
+ else if (ArrayType *ATy = dyn_cast<ArrayType>(EltTy)) {
if (IdxVal >= ATy->getNumElements()) return 0;
EltTy = ATy->getElementType();
} else {
return 0; // Unknown type.
}
-
+
LaterIndices.push_back(IdxVal);
}
-
+
enum { Overdefined = -3, Undefined = -2 };
// Variables for our state machines.
-
+
// FirstTrueElement/SecondTrueElement - Used to emit a comparison of the form
// "i == 47 | i == 87", where 47 is the first index the condition is true for,
// and 87 is the second (and last) index. FirstTrueElement is -2 when
@@ -254,7 +255,7 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
// FirstFalseElement/SecondFalseElement - Used to emit a comparison of the
// form "i != 47 & i != 87". Same state transitions as for true elements.
int FirstFalseElement = Undefined, SecondFalseElement = Undefined;
-
+
/// TrueRangeEnd/FalseRangeEnd - In conjunction with First*Element, these
/// define a state machine that triggers for ranges of values that the index
/// is true or false for. This triggers on things like "abbbbc"[i] == 'b'.
@@ -262,25 +263,25 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
/// index in the range (inclusive). We use -2 for undefined here because we
/// use relative comparisons and don't want 0-1 to match -1.
int TrueRangeEnd = Undefined, FalseRangeEnd = Undefined;
-
+
// MagicBitvector - This is a magic bitvector where we set a bit if the
// comparison is true for element 'i'. If there are 64 elements or less in
// the array, this will fully represent all the comparison results.
uint64_t MagicBitvector = 0;
-
-
+
+
// Scan the array and see if one of our patterns matches.
Constant *CompareRHS = cast<Constant>(ICI.getOperand(1));
for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) {
Constant *Elt = Init->getOperand(i);
-
+
// If this is indexing an array of structures, get the structure element.
if (!LaterIndices.empty())
Elt = ConstantExpr::getExtractValue(Elt, LaterIndices);
-
+
// If the element is masked, handle it.
if (AndCst) Elt = ConstantExpr::getAnd(Elt, AndCst);
-
+
// Find out if the comparison would be true or false for the i'th element.
Constant *C = ConstantFoldCompareInstOperands(ICI.getPredicate(), Elt,
CompareRHS, TD);
@@ -294,15 +295,15 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
FalseRangeEnd = i;
continue;
}
-
+
// If we can't compute the result for any of the elements, we have to give
// up evaluating the entire conditional.
if (!isa<ConstantInt>(C)) return 0;
-
+
// Otherwise, we know if the comparison is true or false for this element,
// update our state machines.
bool IsTrueForElt = !cast<ConstantInt>(C)->isZero();
-
+
// State machine for single/double/range index comparison.
if (IsTrueForElt) {
// Update the TrueElement state machine.
@@ -314,7 +315,7 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
SecondTrueElement = i;
else
SecondTrueElement = Overdefined;
-
+
// Update range state machine.
if (TrueRangeEnd == (int)i-1)
TrueRangeEnd = i;
@@ -331,7 +332,7 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
SecondFalseElement = i;
else
SecondFalseElement = Overdefined;
-
+
// Update range state machine.
if (FalseRangeEnd == (int)i-1)
FalseRangeEnd = i;
@@ -339,12 +340,12 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
FalseRangeEnd = Overdefined;
}
}
-
-
+
+
// If this element is in range, update our magic bitvector.
if (i < 64 && IsTrueForElt)
MagicBitvector |= 1ULL << i;
-
+
// If all of our states become overdefined, bail out early. Since the
// predicate is expensive, only check it every 8 elements. This is only
// really useful for really huge arrays.
@@ -364,20 +365,20 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
if (!GEP->isInBounds() &&
Idx->getType()->getPrimitiveSizeInBits() > TD->getPointerSizeInBits())
Idx = Builder->CreateTrunc(Idx, TD->getIntPtrType(Idx->getContext()));
-
+
// If the comparison is only true for one or two elements, emit direct
// comparisons.
if (SecondTrueElement != Overdefined) {
// None true -> false.
if (FirstTrueElement == Undefined)
return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(GEP->getContext()));
-
+
Value *FirstTrueIdx = ConstantInt::get(Idx->getType(), FirstTrueElement);
-
+
// True for one element -> 'i == 47'.
if (SecondTrueElement == Undefined)
return new ICmpInst(ICmpInst::ICMP_EQ, Idx, FirstTrueIdx);
-
+
// True for two elements -> 'i == 47 | i == 72'.
Value *C1 = Builder->CreateICmpEQ(Idx, FirstTrueIdx);
Value *SecondTrueIdx = ConstantInt::get(Idx->getType(), SecondTrueElement);
@@ -391,36 +392,36 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
// None false -> true.
if (FirstFalseElement == Undefined)
return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(GEP->getContext()));
-
+
Value *FirstFalseIdx = ConstantInt::get(Idx->getType(), FirstFalseElement);
// False for one element -> 'i != 47'.
if (SecondFalseElement == Undefined)
return new ICmpInst(ICmpInst::ICMP_NE, Idx, FirstFalseIdx);
-
+
// False for two elements -> 'i != 47 & i != 72'.
Value *C1 = Builder->CreateICmpNE(Idx, FirstFalseIdx);
Value *SecondFalseIdx = ConstantInt::get(Idx->getType(),SecondFalseElement);
Value *C2 = Builder->CreateICmpNE(Idx, SecondFalseIdx);
return BinaryOperator::CreateAnd(C1, C2);
}
-
+
// If the comparison can be replaced with a range comparison for the elements
// where it is true, emit the range check.
if (TrueRangeEnd != Overdefined) {
assert(TrueRangeEnd != FirstTrueElement && "Should emit single compare");
-
+
// Generate (i-FirstTrue) <u (TrueRangeEnd-FirstTrue+1).
if (FirstTrueElement) {
Value *Offs = ConstantInt::get(Idx->getType(), -FirstTrueElement);
Idx = Builder->CreateAdd(Idx, Offs);
}
-
+
Value *End = ConstantInt::get(Idx->getType(),
TrueRangeEnd-FirstTrueElement+1);
return new ICmpInst(ICmpInst::ICMP_ULT, Idx, End);
}
-
+
// False range check.
if (FalseRangeEnd != Overdefined) {
assert(FalseRangeEnd != FirstFalseElement && "Should emit single compare");
@@ -429,19 +430,19 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
Value *Offs = ConstantInt::get(Idx->getType(), -FirstFalseElement);
Idx = Builder->CreateAdd(Idx, Offs);
}
-
+
Value *End = ConstantInt::get(Idx->getType(),
FalseRangeEnd-FirstFalseElement);
return new ICmpInst(ICmpInst::ICMP_UGT, Idx, End);
}
-
-
+
+
// If a 32-bit or 64-bit magic bitvector captures the entire comparison state
// of this load, replace it with computation that does:
// ((magic_cst >> i) & 1) != 0
if (Init->getNumOperands() <= 32 ||
(TD && Init->getNumOperands() <= 64 && TD->isLegalInteger(64))) {
- const Type *Ty;
+ Type *Ty;
if (Init->getNumOperands() <= 32)
Ty = Type::getInt32Ty(Init->getContext());
else
@@ -451,7 +452,7 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
V = Builder->CreateAnd(ConstantInt::get(Ty, 1), V);
return new ICmpInst(ICmpInst::ICMP_NE, V, ConstantInt::get(Ty, 0));
}
-
+
return 0;
}
@@ -465,11 +466,11 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
/// to generate the first by knowing that pointer arithmetic doesn't overflow.
///
/// If we can't emit an optimized form for this expression, this returns null.
-///
+///
static Value *EvaluateGEPOffsetExpression(User *GEP, InstCombiner &IC) {
TargetData &TD = *IC.getTargetData();
gep_type_iterator GTI = gep_type_begin(GEP);
-
+
// Check to see if this gep only has a single variable index. If so, and if
// any constant indices are a multiple of its scale, then we can compute this
// in terms of the scale of the variable index. For example, if the GEP
@@ -481,9 +482,9 @@ static Value *EvaluateGEPOffsetExpression(User *GEP, InstCombiner &IC) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(i))) {
// Compute the aggregate offset of constant indices.
if (CI->isZero()) continue;
-
+
// Handle a struct index, which adds its field offset to the pointer.
- if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
+ if (StructType *STy = dyn_cast<StructType>(*GTI)) {
Offset += TD.getStructLayout(STy)->getElementOffset(CI->getZExtValue());
} else {
uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType());
@@ -494,33 +495,33 @@ static Value *EvaluateGEPOffsetExpression(User *GEP, InstCombiner &IC) {
break;
}
}
-
+
// If there are no variable indices, we must have a constant offset, just
// evaluate it the general way.
if (i == e) return 0;
-
+
Value *VariableIdx = GEP->getOperand(i);
// Determine the scale factor of the variable element. For example, this is
// 4 if the variable index is into an array of i32.
uint64_t VariableScale = TD.getTypeAllocSize(GTI.getIndexedType());
-
+
// Verify that there are no other variable indices. If so, emit the hard way.
for (++i, ++GTI; i != e; ++i, ++GTI) {
ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(i));
if (!CI) return 0;
-
+
// Compute the aggregate offset of constant indices.
if (CI->isZero()) continue;
-
+
// Handle a struct index, which adds its field offset to the pointer.
- if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
+ if (StructType *STy = dyn_cast<StructType>(*GTI)) {
Offset += TD.getStructLayout(STy)->getElementOffset(CI->getZExtValue());
} else {
uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType());
Offset += Size*CI->getSExtValue();
}
}
-
+
// Okay, we know we have a single variable index, which must be a
// pointer/array/vector index. If there is no offset, life is simple, return
// the index.
@@ -530,19 +531,19 @@ static Value *EvaluateGEPOffsetExpression(User *GEP, InstCombiner &IC) {
// we don't need to bother extending: the extension won't affect where the
// computation crosses zero.
if (VariableIdx->getType()->getPrimitiveSizeInBits() > IntPtrWidth) {
- const Type *IntPtrTy = TD.getIntPtrType(VariableIdx->getContext());
+ Type *IntPtrTy = TD.getIntPtrType(VariableIdx->getContext());
VariableIdx = IC.Builder->CreateTrunc(VariableIdx, IntPtrTy);
}
return VariableIdx;
}
-
+
// Otherwise, there is an index. The computation we will do will be modulo
// the pointer size, so get it.
uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth);
-
+
Offset &= PtrSizeMask;
VariableScale &= PtrSizeMask;
-
+
// To do this transformation, any constant index must be a multiple of the
// variable scale factor. For example, we can evaluate "12 + 4*i" as "3 + i",
// but we can't evaluate "10 + 3*i" in terms of i. Check that the offset is a
@@ -550,9 +551,9 @@ static Value *EvaluateGEPOffsetExpression(User *GEP, InstCombiner &IC) {
int64_t NewOffs = Offset / (int64_t)VariableScale;
if (Offset != NewOffs*(int64_t)VariableScale)
return 0;
-
+
// Okay, we can do this evaluation. Start by converting the index to intptr.
- const Type *IntPtrTy = TD.getIntPtrType(VariableIdx->getContext());
+ Type *IntPtrTy = TD.getIntPtrType(VariableIdx->getContext());
if (VariableIdx->getType() != IntPtrTy)
VariableIdx = IC.Builder->CreateIntCast(VariableIdx, IntPtrTy,
true /*Signed*/);
@@ -576,7 +577,7 @@ Instruction *InstCombiner::FoldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
// know pointers can't overflow since the gep is inbounds. See if we can
// output an optimized form.
Value *Offset = EvaluateGEPOffsetExpression(GEPLHS, *this);
-
+
// If not, synthesize the offset the hard way.
if (Offset == 0)
Offset = EmitGEPOffset(GEPLHS);
@@ -686,7 +687,7 @@ Instruction *InstCombiner::FoldICmpAddOpCst(ICmpInst &ICI,
bool isTrue = ICmpInst::isTrueWhenEqual(Pred);
return ReplaceInstUsesWith(ICI, ConstantInt::get(ICI.getType(), isTrue));
}
-
+
// (X+4) == X -> false.
if (Pred == ICmpInst::ICMP_EQ)
return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(X->getContext()));
@@ -698,22 +699,22 @@ Instruction *InstCombiner::FoldICmpAddOpCst(ICmpInst &ICI,
// From this point on, we know that (X+C <= X) --> (X+C < X) because C != 0,
// so the values can never be equal. Similarly for all other "or equals"
// operators.
-
+
// (X+1) <u X --> X >u (MAXUINT-1) --> X == 255
// (X+2) <u X --> X >u (MAXUINT-2) --> X > 253
// (X+MAXUINT) <u X --> X >u (MAXUINT-MAXUINT) --> X != 0
if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE) {
- Value *R =
+ Value *R =
ConstantExpr::getSub(ConstantInt::getAllOnesValue(CI->getType()), CI);
return new ICmpInst(ICmpInst::ICMP_UGT, X, R);
}
-
+
// (X+1) >u X --> X <u (0-1) --> X != 255
// (X+2) >u X --> X <u (0-2) --> X <u 254
// (X+MAXUINT) >u X --> X <u (0-MAXUINT) --> X <u 1 --> X == 0
if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE)
return new ICmpInst(ICmpInst::ICMP_ULT, X, ConstantExpr::getNeg(CI));
-
+
unsigned BitWidth = CI->getType()->getPrimitiveSizeInBits();
ConstantInt *SMax = ConstantInt::get(X->getContext(),
APInt::getSignedMaxValue(BitWidth));
@@ -726,14 +727,14 @@ Instruction *InstCombiner::FoldICmpAddOpCst(ICmpInst &ICI,
// (X+ -1) <s X --> X >s (MAXSINT- -1) --> X != 127
if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE)
return new ICmpInst(ICmpInst::ICMP_SGT, X, ConstantExpr::getSub(SMax, CI));
-
+
// (X+ 1) >s X --> X <s (MAXSINT-(1-1)) --> X != 127
// (X+ 2) >s X --> X <s (MAXSINT-(2-1)) --> X <s 126
// (X+MAXSINT) >s X --> X <s (MAXSINT-(MAXSINT-1)) --> X <s 1
// (X+MINSINT) >s X --> X <s (MAXSINT-(MINSINT-1)) --> X <s -2
// (X+ -2) >s X --> X <s (MAXSINT-(-2-1)) --> X <s -126
// (X+ -1) >s X --> X <s (MAXSINT-(-1-1)) --> X == -128
-
+
assert(Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE);
Constant *C = ConstantInt::get(X->getContext(), CI->getValue()-1);
return new ICmpInst(ICmpInst::ICMP_SLT, X, ConstantExpr::getSub(SMax, C));
@@ -745,14 +746,14 @@ Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI,
ConstantInt *DivRHS) {
ConstantInt *CmpRHS = cast<ConstantInt>(ICI.getOperand(1));
const APInt &CmpRHSV = CmpRHS->getValue();
-
- // FIXME: If the operand types don't match the type of the divide
+
+ // FIXME: If the operand types don't match the type of the divide
// then don't attempt this transform. The code below doesn't have the
// logic to deal with a signed divide and an unsigned compare (and
- // vice versa). This is because (x /s C1) <s C2 produces different
+ // vice versa). This is because (x /s C1) <s C2 produces different
// results than (x /s C1) <u C2 or (x /u C1) <s C2 or even
- // (x /u C1) <u C2. Simply casting the operands and result won't
- // work. :( The if statement below tests that condition and bails
+ // (x /u C1) <u C2. Simply casting the operands and result won't
+ // work. :( The if statement below tests that condition and bails
// if it finds it.
bool DivIsSigned = DivI->getOpcode() == Instruction::SDiv;
if (!ICI.isEquality() && DivIsSigned != ICI.isSigned())
@@ -768,14 +769,14 @@ Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI,
}
// Compute Prod = CI * DivRHS. We are essentially solving an equation
- // of form X/C1=C2. We solve for X by multiplying C1 (DivRHS) and
- // C2 (CI). By solving for X we can turn this into a range check
- // instead of computing a divide.
+ // of form X/C1=C2. We solve for X by multiplying C1 (DivRHS) and
+ // C2 (CI). By solving for X we can turn this into a range check
+ // instead of computing a divide.
Constant *Prod = ConstantExpr::getMul(CmpRHS, DivRHS);
// Determine if the product overflows by seeing if the product is
// not equal to the divide. Make sure we do the same kind of divide
- // as in the LHS instruction that we're folding.
+ // as in the LHS instruction that we're folding.
bool ProdOV = (DivIsSigned ? ConstantExpr::getSDiv(Prod, DivRHS) :
ConstantExpr::getUDiv(Prod, DivRHS)) != CmpRHS;
@@ -785,9 +786,9 @@ Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI,
/// If the division is known to be exact, then there is no remainder from the
/// divide, so the covered range size is unit, otherwise it is the divisor.
ConstantInt *RangeSize = DivI->isExact() ? getOne(Prod) : DivRHS;
-
+
// Figure out the interval that is being checked. For example, a comparison
- // like "X /u 5 == 0" is really checking that X is in the interval [0, 5).
+ // like "X /u 5 == 0" is really checking that X is in the interval [0, 5).
// Compute this interval based on the constants involved and the signedness of
// the compare/divide. This computes a half-open interval, keeping track of
// whether either value in the interval overflows. After analysis each
@@ -805,7 +806,7 @@ Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI,
// to the same result value.
HiOverflow = AddWithOverflow(HiBound, LoBound, RangeSize, false);
}
-
+
} else if (DivRHS->getValue().isStrictlyPositive()) { // Divisor is > 0.
if (CmpRHSV == 0) { // (X / pos) op 0
// Can't overflow. e.g. X/2 op 0 --> [-1, 2)
@@ -848,7 +849,7 @@ Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI,
if (!HiOverflow)
HiOverflow = SubWithOverflow(HiBound, Prod, RangeSize, true);
}
-
+
// Dividing by a negative swaps the condition. LT <-> GT
Pred = ICmpInst::getSwappedPredicate(Pred);
}
@@ -901,7 +902,7 @@ Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI,
Instruction *InstCombiner::FoldICmpShrCst(ICmpInst &ICI, BinaryOperator *Shr,
ConstantInt *ShAmt) {
const APInt &CmpRHSV = cast<ConstantInt>(ICI.getOperand(1))->getValue();
-
+
// Check that the shift amount is in range. If not, don't perform
// undefined shifts. When the shift is visited it will be
// simplified.
@@ -909,48 +910,48 @@ Instruction *InstCombiner::FoldICmpShrCst(ICmpInst &ICI, BinaryOperator *Shr,
uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits);
if (ShAmtVal >= TypeBits || ShAmtVal == 0)
return 0;
-
+
if (!ICI.isEquality()) {
// If we have an unsigned comparison and an ashr, we can't simplify this.
// Similarly for signed comparisons with lshr.
if (ICI.isSigned() != (Shr->getOpcode() == Instruction::AShr))
return 0;
-
+
// Otherwise, all lshr and most exact ashr's are equivalent to a udiv/sdiv
// by a power of 2. Since we already have logic to simplify these,
// transform to div and then simplify the resultant comparison.
if (Shr->getOpcode() == Instruction::AShr &&
(!Shr->isExact() || ShAmtVal == TypeBits - 1))
return 0;
-
+
// Revisit the shift (to delete it).
Worklist.Add(Shr);
-
+
Constant *DivCst =
ConstantInt::get(Shr->getType(), APInt::getOneBitSet(TypeBits, ShAmtVal));
-
+
Value *Tmp =
Shr->getOpcode() == Instruction::AShr ?
Builder->CreateSDiv(Shr->getOperand(0), DivCst, "", Shr->isExact()) :
Builder->CreateUDiv(Shr->getOperand(0), DivCst, "", Shr->isExact());
-
+
ICI.setOperand(0, Tmp);
-
+
// If the builder folded the binop, just return it.
BinaryOperator *TheDiv = dyn_cast<BinaryOperator>(Tmp);
if (TheDiv == 0)
return &ICI;
-
+
// Otherwise, fold this div/compare.
assert(TheDiv->getOpcode() == Instruction::SDiv ||
TheDiv->getOpcode() == Instruction::UDiv);
-
+
Instruction *Res = FoldICmpDivCst(ICI, TheDiv, cast<ConstantInt>(DivCst));
assert(Res && "This div/cst should have folded!");
return Res;
}
-
-
+
+
// If we are comparing against bits always shifted out, the
// comparison cannot succeed.
APInt Comp = CmpRHSV << ShAmtVal;
@@ -959,25 +960,25 @@ Instruction *InstCombiner::FoldICmpShrCst(ICmpInst &ICI, BinaryOperator *Shr,
Comp = Comp.lshr(ShAmtVal);
else
Comp = Comp.ashr(ShAmtVal);
-
+
if (Comp != CmpRHSV) { // Comparing against a bit that we know is zero.
bool IsICMP_NE = ICI.getPredicate() == ICmpInst::ICMP_NE;
Constant *Cst = ConstantInt::get(Type::getInt1Ty(ICI.getContext()),
IsICMP_NE);
return ReplaceInstUsesWith(ICI, Cst);
}
-
+
// Otherwise, check to see if the bits shifted out are known to be zero.
// If so, we can compare against the unshifted value:
// (X & 4) >> 1 == 2 --> (X & 4) == 4.
if (Shr->hasOneUse() && Shr->isExact())
return new ICmpInst(ICI.getPredicate(), Shr->getOperand(0), ShiftedCmpRHS);
-
+
if (Shr->hasOneUse()) {
// Otherwise strength reduce the shift into an and.
APInt Val(APInt::getHighBitsSet(TypeBits, TypeBits - ShAmtVal));
Constant *Mask = ConstantInt::get(ICI.getContext(), Val);
-
+
Value *And = Builder->CreateAnd(Shr->getOperand(0),
Mask, Shr->getName()+".mask");
return new ICmpInst(ICI.getPredicate(), And, ShiftedCmpRHS);
@@ -992,7 +993,7 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
Instruction *LHSI,
ConstantInt *RHS) {
const APInt &RHSV = RHS->getValue();
-
+
switch (LHSI->getOpcode()) {
case Instruction::Trunc:
if (ICI.isEquality() && LHSI->hasOneUse()) {
@@ -1003,7 +1004,7 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
APInt Mask(APInt::getHighBitsSet(SrcBits, SrcBits-DstBits));
APInt KnownZero(SrcBits, 0), KnownOne(SrcBits, 0);
ComputeMaskedBits(LHSI->getOperand(0), Mask, KnownZero, KnownOne);
-
+
// If all the high bits are known, we can do this xform.
if ((KnownZero|KnownOne).countLeadingOnes() >= SrcBits-DstBits) {
// Pull in the high bits from known-ones set.
@@ -1014,7 +1015,7 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
}
}
break;
-
+
case Instruction::Xor: // (icmp pred (xor X, XorCST), CI)
if (ConstantInt *XorCST = dyn_cast<ConstantInt>(LHSI->getOperand(1))) {
// If this is a comparison that tests the signbit (X < 0) or (x > -1),
@@ -1022,7 +1023,7 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
if ((ICI.getPredicate() == ICmpInst::ICMP_SLT && RHSV == 0) ||
(ICI.getPredicate() == ICmpInst::ICMP_SGT && RHSV.isAllOnesValue())) {
Value *CompareVal = LHSI->getOperand(0);
-
+
// If the sign bit of the XorCST is not set, there is no change to
// the operation, just stop using the Xor.
if (!XorCST->isNegative()) {
@@ -1030,13 +1031,13 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
Worklist.Add(LHSI);
return &ICI;
}
-
+
// Was the old condition true if the operand is positive?
bool isTrueIfPositive = ICI.getPredicate() == ICmpInst::ICMP_SGT;
-
+
// If so, the new one isn't.
isTrueIfPositive ^= true;
-
+
if (isTrueIfPositive)
return new ICmpInst(ICmpInst::ICMP_SGT, CompareVal,
SubOne(RHS));
@@ -1075,13 +1076,13 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
if (LHSI->hasOneUse() && isa<ConstantInt>(LHSI->getOperand(1)) &&
LHSI->getOperand(0)->hasOneUse()) {
ConstantInt *AndCST = cast<ConstantInt>(LHSI->getOperand(1));
-
+
// If the LHS is an AND of a truncating cast, we can widen the
// and/compare to be the input width without changing the value
// produced, eliminating a cast.
if (TruncInst *Cast = dyn_cast<TruncInst>(LHSI->getOperand(0))) {
// We can do this transformation if either the AND constant does not
- // have its sign bit set or if it is an equality comparison.
+ // have its sign bit set or if it is an equality comparison.
// Extending a relational comparison when we're checking the sign
// bit would not work.
if (ICI.isEquality() ||
@@ -1098,7 +1099,7 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
// If the LHS is an AND of a zext, and we have an equality compare, we can
// shrink the and/compare to the smaller type, eliminating the cast.
if (ZExtInst *Cast = dyn_cast<ZExtInst>(LHSI->getOperand(0))) {
- const IntegerType *Ty = cast<IntegerType>(Cast->getSrcTy());
+ IntegerType *Ty = cast<IntegerType>(Cast->getSrcTy());
// Make sure we don't compare the upper bits, SimplifyDemandedBits
// should fold the icmp to true/false in that case.
if (ICI.isEquality() && RHSV.getActiveBits() <= Ty->getBitWidth()) {
@@ -1118,12 +1119,12 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
BinaryOperator *Shift = dyn_cast<BinaryOperator>(LHSI->getOperand(0));
if (Shift && !Shift->isShift())
Shift = 0;
-
+
ConstantInt *ShAmt;
ShAmt = Shift ? dyn_cast<ConstantInt>(Shift->getOperand(1)) : 0;
- const Type *Ty = Shift ? Shift->getType() : 0; // Type of the shift.
- const Type *AndTy = AndCST->getType(); // Type of the and.
-
+ Type *Ty = Shift ? Shift->getType() : 0; // Type of the shift.
+ Type *AndTy = AndCST->getType(); // Type of the and.
+
// We can fold this as long as we can't shift unknown bits
// into the mask. This can only happen with signed shift
// rights, as they sign-extend.
@@ -1134,20 +1135,20 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
// of the bits shifted in could be tested after the mask.
uint32_t TyBits = Ty->getPrimitiveSizeInBits();
int ShAmtVal = TyBits - ShAmt->getLimitedValue(TyBits);
-
+
uint32_t BitWidth = AndTy->getPrimitiveSizeInBits();
- if ((APInt::getHighBitsSet(BitWidth, BitWidth-ShAmtVal) &
+ if ((APInt::getHighBitsSet(BitWidth, BitWidth-ShAmtVal) &
AndCST->getValue()) == 0)
CanFold = true;
}
-
+
if (CanFold) {
Constant *NewCst;
if (Shift->getOpcode() == Instruction::Shl)
NewCst = ConstantExpr::getLShr(RHS, ShAmt);
else
NewCst = ConstantExpr::getShl(RHS, ShAmt);
-
+
// Check to see if we are shifting out any of the bits being
// compared.
if (ConstantExpr::get(Shift->getOpcode(),
@@ -1175,7 +1176,7 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
}
}
}
-
+
// Turn ((X >> Y) & C) == 0 into (X & (C << Y)) == 0. The later is
// preferable because it allows the C<<Y expression to be hoisted out
// of a loop if Y is invariant and X is not.
@@ -1185,21 +1186,21 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
// Compute C << Y.
Value *NS;
if (Shift->getOpcode() == Instruction::LShr) {
- NS = Builder->CreateShl(AndCST, Shift->getOperand(1), "tmp");
+ NS = Builder->CreateShl(AndCST, Shift->getOperand(1));
} else {
// Insert a logical shift.
- NS = Builder->CreateLShr(AndCST, Shift->getOperand(1), "tmp");
+ NS = Builder->CreateLShr(AndCST, Shift->getOperand(1));
}
-
+
// Compute X & (C << Y).
- Value *NewAnd =
+ Value *NewAnd =
Builder->CreateAnd(Shift->getOperand(0), NS, LHSI->getName());
-
+
ICI.setOperand(0, NewAnd);
return &ICI;
}
}
-
+
// Try to optimize things like "A[i]&42 == 0" to index computations.
if (LoadInst *LI = dyn_cast<LoadInst>(LHSI->getOperand(0))) {
if (GetElementPtrInst *GEP =
@@ -1234,19 +1235,19 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
}
break;
}
-
+
case Instruction::Shl: { // (icmp pred (shl X, ShAmt), CI)
ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1));
if (!ShAmt) break;
-
+
uint32_t TypeBits = RHSV.getBitWidth();
-
+
// Check that the shift amount is in range. If not, don't perform
// undefined shifts. When the shift is visited it will be
// simplified.
if (ShAmt->uge(TypeBits))
break;
-
+
if (ICI.isEquality()) {
// If we are comparing against bits always shifted out, the
// comparison cannot succeed.
@@ -1259,34 +1260,34 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
ConstantInt::get(Type::getInt1Ty(ICI.getContext()), IsICMP_NE);
return ReplaceInstUsesWith(ICI, Cst);
}
-
+
// If the shift is NUW, then it is just shifting out zeros, no need for an
// AND.
if (cast<BinaryOperator>(LHSI)->hasNoUnsignedWrap())
return new ICmpInst(ICI.getPredicate(), LHSI->getOperand(0),
ConstantExpr::getLShr(RHS, ShAmt));
-
+
if (LHSI->hasOneUse()) {
// Otherwise strength reduce the shift into an and.
uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits);
Constant *Mask =
- ConstantInt::get(ICI.getContext(), APInt::getLowBitsSet(TypeBits,
+ ConstantInt::get(ICI.getContext(), APInt::getLowBitsSet(TypeBits,
TypeBits-ShAmtVal));
-
+
Value *And =
Builder->CreateAnd(LHSI->getOperand(0),Mask, LHSI->getName()+".mask");
return new ICmpInst(ICI.getPredicate(), And,
ConstantExpr::getLShr(RHS, ShAmt));
}
}
-
+
// Otherwise, if this is a comparison of the sign bit, simplify to and/test.
bool TrueIfSigned = false;
if (LHSI->hasOneUse() &&
isSignBitCheck(ICI.getPredicate(), RHS, TrueIfSigned)) {
// (X << 31) <s 0 --> (X&1) != 0
Constant *Mask = ConstantInt::get(LHSI->getOperand(0)->getType(),
- APInt::getOneBitSet(TypeBits,
+ APInt::getOneBitSet(TypeBits,
TypeBits-ShAmt->getZExtValue()-1));
Value *And =
Builder->CreateAnd(LHSI->getOperand(0), Mask, LHSI->getName()+".mask");
@@ -1295,7 +1296,7 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
}
break;
}
-
+
case Instruction::LShr: // (icmp pred (shr X, ShAmt), CI)
case Instruction::AShr: {
// Handle equality comparisons of shift-by-constant.
@@ -1312,13 +1313,13 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
}
break;
}
-
+
case Instruction::SDiv:
case Instruction::UDiv:
// Fold: icmp pred ([us]div X, C1), C2 -> range test
- // Fold this div into the comparison, producing a range check.
- // Determine, based on the divide type, what the range is being
- // checked. If there is an overflow on the low or high side, remember
+ // Fold this div into the comparison, producing a range check.
+ // Determine, based on the divide type, what the range is being
+ // checked. If there is an overflow on the low or high side, remember
// it, otherwise compute the range [low, hi) bounding the new value.
// See: InsertRangeTest above for the kinds of replacements possible.
if (ConstantInt *DivRHS = dyn_cast<ConstantInt>(LHSI->getOperand(1)))
@@ -1357,12 +1358,12 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
}
break;
}
-
+
// Simplify icmp_eq and icmp_ne instructions with integer constant RHS.
if (ICI.isEquality()) {
bool isICMP_NE = ICI.getPredicate() == ICmpInst::ICMP_NE;
-
- // If the first operand is (add|sub|and|or|xor|rem) with a constant, and
+
+ // If the first operand is (add|sub|and|or|xor|rem) with a constant, and
// the second operand is a constant, simplify a bit.
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(LHSI)) {
switch (BO->getOpcode()) {
@@ -1389,7 +1390,7 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
// Replace ((add A, B) != 0) with (A != -B) if A or B is
// efficiently invertible, or if the add has just this one use.
Value *BOp0 = BO->getOperand(0), *BOp1 = BO->getOperand(1);
-
+
if (Value *NegVal = dyn_castNegVal(BOp1))
return new ICmpInst(ICI.getPredicate(), BOp0, NegVal);
if (Value *NegVal = dyn_castNegVal(BOp0))
@@ -1432,11 +1433,11 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
Constant *NotCI = ConstantExpr::getNot(RHS);
if (!ConstantExpr::getAnd(BOC, NotCI)->isNullValue())
return ReplaceInstUsesWith(ICI,
- ConstantInt::get(Type::getInt1Ty(ICI.getContext()),
+ ConstantInt::get(Type::getInt1Ty(ICI.getContext()),
isICMP_NE));
}
break;
-
+
case Instruction::And:
if (ConstantInt *BOC = dyn_cast<ConstantInt>(BO->getOperand(1))) {
// If bits are being compared against that are and'd out, then the
@@ -1445,7 +1446,7 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
return ReplaceInstUsesWith(ICI,
ConstantInt::get(Type::getInt1Ty(ICI.getContext()),
isICMP_NE));
-
+
// If we have ((X & C) == C), turn it into ((X & C) != 0).
if (RHS == BOC && RHSV.isPowerOf2())
return new ICmpInst(isICMP_NE ? ICmpInst::ICMP_EQ :
@@ -1460,16 +1461,16 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
if (BOC->getValue().isSignBit()) {
Value *X = BO->getOperand(0);
Constant *Zero = Constant::getNullValue(X->getType());
- ICmpInst::Predicate pred = isICMP_NE ?
+ ICmpInst::Predicate pred = isICMP_NE ?
ICmpInst::ICMP_SLT : ICmpInst::ICMP_SGE;
return new ICmpInst(pred, X, Zero);
}
-
+
// ((X & ~7) == 0) --> X < 8
if (RHSV == 0 && isHighOnes(BOC)) {
Value *X = BO->getOperand(0);
Constant *NegX = ConstantExpr::getNeg(BOC);
- ICmpInst::Predicate pred = isICMP_NE ?
+ ICmpInst::Predicate pred = isICMP_NE ?
ICmpInst::ICMP_UGE : ICmpInst::ICMP_ULT;
return new ICmpInst(pred, X, NegX);
}
@@ -1517,11 +1518,11 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
Instruction *InstCombiner::visitICmpInstWithCastAndCast(ICmpInst &ICI) {
const CastInst *LHSCI = cast<CastInst>(ICI.getOperand(0));
Value *LHSCIOp = LHSCI->getOperand(0);
- const Type *SrcTy = LHSCIOp->getType();
- const Type *DestTy = LHSCI->getType();
+ Type *SrcTy = LHSCIOp->getType();
+ Type *DestTy = LHSCI->getType();
Value *RHSCIOp;
- // Turn icmp (ptrtoint x), (ptrtoint/c) into a compare of the input if the
+ // Turn icmp (ptrtoint x), (ptrtoint/c) into a compare of the input if the
// integer type is the same size as the pointer type.
if (TD && LHSCI->getOpcode() == Instruction::PtrToInt &&
TD->getPointerSizeInBits() ==
@@ -1539,7 +1540,7 @@ Instruction *InstCombiner::visitICmpInstWithCastAndCast(ICmpInst &ICI) {
if (RHSOp)
return new ICmpInst(ICI.getPredicate(), LHSCIOp, RHSOp);
}
-
+
// The code below only handles extension cast instructions, so far.
// Enforce this.
if (LHSCI->getOpcode() != Instruction::ZExt &&
@@ -1552,9 +1553,9 @@ Instruction *InstCombiner::visitICmpInstWithCastAndCast(ICmpInst &ICI) {
if (CastInst *CI = dyn_cast<CastInst>(ICI.getOperand(1))) {
// Not an extension from the same type?
RHSCIOp = CI->getOperand(0);
- if (RHSCIOp->getType() != LHSCIOp->getType())
+ if (RHSCIOp->getType() != LHSCIOp->getType())
return 0;
-
+
// If the signedness of the two casts doesn't agree (i.e. one is a sext
// and the other is a zext), then we can't handle this.
if (CI->getOpcode() != LHSCI->getOpcode())
@@ -1599,7 +1600,7 @@ Instruction *InstCombiner::visitICmpInstWithCastAndCast(ICmpInst &ICI) {
return new ICmpInst(ICI.getUnsignedPredicate(), LHSCIOp, Res1);
}
- // The re-extended constant changed so the constant cannot be represented
+ // The re-extended constant changed so the constant cannot be represented
// in the shorter type. Consequently, we cannot emit a simple comparison.
// All the cases that fold to true or false will have already been handled
// by SimplifyICmpInst, so only deal with the tricky case.
@@ -1637,26 +1638,26 @@ static Instruction *ProcessUGT_ADDCST_ADD(ICmpInst &I, Value *A, Value *B,
// llvm.sadd.with.overflow. To do this, we have to replace the original add
// with a narrower add, and discard the add-with-constant that is part of the
// range check (if we can't eliminate it, this isn't profitable).
-
+
// In order to eliminate the add-with-constant, the compare can be its only
// use.
Instruction *AddWithCst = cast<Instruction>(I.getOperand(0));
if (!AddWithCst->hasOneUse()) return 0;
-
+
// If CI2 is 2^7, 2^15, 2^31, then it might be an sadd.with.overflow.
if (!CI2->getValue().isPowerOf2()) return 0;
unsigned NewWidth = CI2->getValue().countTrailingZeros();
if (NewWidth != 7 && NewWidth != 15 && NewWidth != 31) return 0;
-
+
// The width of the new add formed is 1 more than the bias.
++NewWidth;
-
+
// Check to see that CI1 is an all-ones value with NewWidth bits.
if (CI1->getBitWidth() == NewWidth ||
CI1->getValue() != APInt::getLowBitsSet(CI1->getBitWidth(), NewWidth))
return 0;
-
- // In order to replace the original add with a narrower
+
+ // In order to replace the original add with a narrower
// llvm.sadd.with.overflow, the only uses allowed are the add-with-constant
// and truncates that discard the high bits of the add. Verify that this is
// the case.
@@ -1664,7 +1665,7 @@ static Instruction *ProcessUGT_ADDCST_ADD(ICmpInst &I, Value *A, Value *B,
for (Value::use_iterator UI = OrigAdd->use_begin(), E = OrigAdd->use_end();
UI != E; ++UI) {
if (*UI == AddWithCst) continue;
-
+
// Only accept truncates for now. We would really like a nice recursive
// predicate like SimplifyDemandedBits, but which goes downwards the use-def
// chain to see which bits of a value are actually demanded. If the
@@ -1674,32 +1675,32 @@ static Instruction *ProcessUGT_ADDCST_ADD(ICmpInst &I, Value *A, Value *B,
if (TI == 0 ||
TI->getType()->getPrimitiveSizeInBits() > NewWidth) return 0;
}
-
+
// If the pattern matches, truncate the inputs to the narrower type and
// use the sadd_with_overflow intrinsic to efficiently compute both the
// result and the overflow bit.
Module *M = I.getParent()->getParent()->getParent();
-
+
Type *NewType = IntegerType::get(OrigAdd->getContext(), NewWidth);
Value *F = Intrinsic::getDeclaration(M, Intrinsic::sadd_with_overflow,
NewType);
InstCombiner::BuilderTy *Builder = IC.Builder;
-
+
// Put the new code above the original add, in case there are any uses of the
// add between the add and the compare.
Builder->SetInsertPoint(OrigAdd);
-
+
Value *TruncA = Builder->CreateTrunc(A, NewType, A->getName()+".trunc");
Value *TruncB = Builder->CreateTrunc(B, NewType, B->getName()+".trunc");
CallInst *Call = Builder->CreateCall2(F, TruncA, TruncB, "sadd");
Value *Add = Builder->CreateExtractValue(Call, 0, "sadd.result");
Value *ZExt = Builder->CreateZExt(Add, OrigAdd->getType());
-
+
// The inner add was the result of the narrow add, zero extended to the
// wider type. Replace it with the result computed by the intrinsic.
IC.ReplaceInstUsesWith(*OrigAdd, ZExt);
-
+
// The original icmp gets replaced with the overflow value.
return ExtractValueInst::Create(Call, 1, "sadd.overflow");
}
@@ -1709,13 +1710,13 @@ static Instruction *ProcessUAddIdiom(Instruction &I, Value *OrigAddV,
// Don't bother doing this transformation for pointers, don't do it for
// vectors.
if (!isa<IntegerType>(OrigAddV->getType())) return 0;
-
+
// If the add is a constant expr, then we don't bother transforming it.
Instruction *OrigAdd = dyn_cast<Instruction>(OrigAddV);
if (OrigAdd == 0) return 0;
-
+
Value *LHS = OrigAdd->getOperand(0), *RHS = OrigAdd->getOperand(1);
-
+
// Put the new code above the original add, in case there are any uses of the
// add between the add and the compare.
InstCombiner::BuilderTy *Builder = IC.Builder;
@@ -1740,13 +1741,13 @@ static APInt DemandedBitsLHSMask(ICmpInst &I,
unsigned BitWidth, bool isSignCheck) {
if (isSignCheck)
return APInt::getSignBit(BitWidth);
-
+
ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1));
if (!CI) return APInt::getAllOnesValue(BitWidth);
const APInt &RHS = CI->getValue();
-
+
switch (I.getPredicate()) {
- // For a UGT comparison, we don't care about any bits that
+ // For a UGT comparison, we don't care about any bits that
// correspond to the trailing ones of the comparand. The value of these
// bits doesn't impact the outcome of the comparison, because any value
// greater than the RHS must differ in a bit higher than these due to carry.
@@ -1755,7 +1756,7 @@ static APInt DemandedBitsLHSMask(ICmpInst &I,
APInt lowBitsSet = APInt::getLowBitsSet(BitWidth, trailingOnes);
return ~lowBitsSet;
}
-
+
// Similarly, for a ULT comparison, we don't care about the trailing zeros.
// Any value less than the RHS must differ in a higher bit because of carries.
case ICmpInst::ICMP_ULT: {
@@ -1763,17 +1764,17 @@ static APInt DemandedBitsLHSMask(ICmpInst &I,
APInt lowBitsSet = APInt::getLowBitsSet(BitWidth, trailingZeros);
return ~lowBitsSet;
}
-
+
default:
return APInt::getAllOnesValue(BitWidth);
}
-
+
}
Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
bool Changed = false;
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
-
+
/// Orders the operands of the compare so that they are listed from most
/// complex to least complex. This puts constants before unary operators,
/// before binary operators.
@@ -1782,11 +1783,11 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
std::swap(Op0, Op1);
Changed = true;
}
-
+
if (Value *V = SimplifyICmpInst(I.getPredicate(), Op0, Op1, TD))
return ReplaceInstUsesWith(I, V);
-
- const Type *Ty = Op0->getType();
+
+ Type *Ty = Op0->getType();
// icmp's with boolean values can always be turned into bitwise operations
if (Ty->isIntegerTy(1)) {
@@ -1835,13 +1836,13 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
BitWidth = Ty->getScalarSizeInBits();
else if (TD) // Pointers require TD info to get their size.
BitWidth = TD->getTypeSizeInBits(Ty->getScalarType());
-
+
bool isSignBit = false;
// See if we are doing a comparison with a constant.
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
Value *A = 0, *B = 0;
-
+
// Match the following pattern, which is a common idiom when writing
// overflow-safe integer arithmetic function. The source performs an
// addition in wider type, and explicitly checks for overflow using
@@ -1849,9 +1850,9 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
// sadd_with_overflow intrinsic.
//
// TODO: This could probably be generalized to handle other overflow-safe
- // operations if we worked out the formulas to compute the appropriate
+ // operations if we worked out the formulas to compute the appropriate
// magic constants.
- //
+ //
// sum = a + b
// if (sum+128 >u 255) ... -> llvm.sadd.with.overflow.i8
{
@@ -1861,14 +1862,14 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
if (Instruction *Res = ProcessUGT_ADDCST_ADD(I, A, B, CI2, CI, *this))
return Res;
}
-
+
// (icmp ne/eq (sub A B) 0) -> (icmp ne/eq A, B)
if (I.isEquality() && CI->isZero() &&
match(Op0, m_Sub(m_Value(A), m_Value(B)))) {
// (icmp cond A B) if cond is equality
return new ICmpInst(I.getPredicate(), A, B);
}
-
+
// If we have an icmp le or icmp ge instruction, turn it into the
// appropriate icmp lt or icmp gt instruction. This allows us to rely on
// them being folded in the code below. The SimplifyICmpInst code has
@@ -1892,7 +1893,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
return new ICmpInst(ICmpInst::ICMP_SGT, Op0,
ConstantInt::get(CI->getContext(), CI->getValue()-1));
}
-
+
// If this comparison is a normal comparison, it demands all
// bits, if it is a sign bit comparison, it only demands the sign bit.
bool UnusedBit;
@@ -1948,7 +1949,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
case ICmpInst::ICMP_EQ: {
if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max))
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getType()));
-
+
// If all bits are known zero except for one, then we know at most one
// bit is set. If the comparison is against zero, then this is a check
// to see if *that* bit is set.
@@ -1960,7 +1961,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
if (!match(Op0, m_And(m_Value(LHS), m_ConstantInt(LHSC))) ||
LHSC->getValue() != Op0KnownZeroInverted)
LHS = Op0;
-
+
// If the LHS is 1 << x, and we know the result is a power of 2 like 8,
// then turn "((1 << x)&8) == 0" into "x != 3".
Value *X = 0;
@@ -1969,7 +1970,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
return new ICmpInst(ICmpInst::ICMP_NE, X,
ConstantInt::get(X->getType(), CmpVal));
}
-
+
// If the LHS is 8 >>u x, and we know the result is a power of 2 like 1,
// then turn "((8 >>u x)&1) == 0" into "x != 3".
const APInt *CI;
@@ -1979,13 +1980,13 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
ConstantInt::get(X->getType(),
CI->countTrailingZeros()));
}
-
+
break;
}
case ICmpInst::ICMP_NE: {
if (Op0Max.ult(Op1Min) || Op0Min.ugt(Op1Max))
return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getType()));
-
+
// If all bits are known zero except for one, then we know at most one
// bit is set. If the comparison is against zero, then this is a check
// to see if *that* bit is set.
@@ -1997,7 +1998,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
if (!match(Op0, m_And(m_Value(LHS), m_ConstantInt(LHSC))) ||
LHSC->getValue() != Op0KnownZeroInverted)
LHS = Op0;
-
+
// If the LHS is 1 << x, and we know the result is a power of 2 like 8,
// then turn "((1 << x)&8) != 0" into "x == 3".
Value *X = 0;
@@ -2006,7 +2007,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
return new ICmpInst(ICmpInst::ICMP_EQ, X,
ConstantInt::get(X->getType(), CmpVal));
}
-
+
// If the LHS is 8 >>u x, and we know the result is a power of 2 like 1,
// then turn "((8 >>u x)&1) != 0" into "x == 3".
const APInt *CI;
@@ -2016,7 +2017,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
ConstantInt::get(X->getType(),
CI->countTrailingZeros()));
}
-
+
break;
}
case ICmpInst::ICMP_ULT:
@@ -2137,9 +2138,9 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
// See if we are doing a comparison between a constant and an instruction that
// can be folded into the comparison.
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
- // Since the RHS is a ConstantInt (CI), if the left hand side is an
- // instruction, see if that instruction also has constants so that the
- // instruction can be folded into the icmp
+ // Since the RHS is a ConstantInt (CI), if the left hand side is an
+ // instruction, see if that instruction also has constants so that the
+ // instruction can be folded into the icmp
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
if (Instruction *Res = visitICmpInstWithInstAndIntCst(I, LHSI, CI))
return Res;
@@ -2194,7 +2195,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
case Instruction::IntToPtr:
// icmp pred inttoptr(X), null -> icmp pred X, 0
if (RHSC->isNullValue() && TD &&
- TD->getIntPtrType(RHSC->getContext()) ==
+ TD->getIntPtrType(RHSC->getContext()) ==
LHSI->getOperand(0)->getType())
return new ICmpInst(I.getPredicate(), LHSI->getOperand(0),
Constant::getNullValue(LHSI->getOperand(0)->getType()));
@@ -2227,8 +2228,8 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
// values. If the ptr->ptr cast can be stripped off both arguments, we do so
// now.
if (BitCastInst *CI = dyn_cast<BitCastInst>(Op0)) {
- if (Op0->getType()->isPointerTy() &&
- (isa<Constant>(Op1) || isa<BitCastInst>(Op1))) {
+ if (Op0->getType()->isPointerTy() &&
+ (isa<Constant>(Op1) || isa<BitCastInst>(Op1))) {
// We keep moving the cast from the left operand over to the right
// operand, where it can often be eliminated completely.
Op0 = CI->getOperand(0);
@@ -2250,7 +2251,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
return new ICmpInst(I.getPredicate(), Op0, Op1);
}
}
-
+
if (isa<CastInst>(Op0)) {
// Handle the special case of: icmp (cast bool to X), <cst>
// This comes up when you have code like
@@ -2384,7 +2385,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
return new ICmpInst(Pred, BO0->getOperand(0),
BO1->getOperand(0));
}
-
+
if (CI->isMaxValue(true)) {
ICmpInst::Predicate Pred = I.isSigned()
? I.getUnsignedPredicate()
@@ -2404,7 +2405,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
// Mask = -1 >> count-trailing-zeros(Cst).
if (!CI->isZero() && !CI->isOne()) {
const APInt &AP = CI->getValue();
- ConstantInt *Mask = ConstantInt::get(I.getContext(),
+ ConstantInt *Mask = ConstantInt::get(I.getContext(),
APInt::getLowBitsSet(AP.getBitWidth(),
AP.getBitWidth() -
AP.countTrailingZeros()));
@@ -2438,7 +2439,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
}
}
}
-
+
{ Value *A, *B;
// ~x < ~y --> y < x
// ~x < cst --> ~cst < x
@@ -2452,11 +2453,11 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
// (a+b) <u a --> llvm.uadd.with.overflow.
// (a+b) <u b --> llvm.uadd.with.overflow.
if (I.getPredicate() == ICmpInst::ICMP_ULT &&
- match(Op0, m_Add(m_Value(A), m_Value(B))) &&
+ match(Op0, m_Add(m_Value(A), m_Value(B))) &&
(Op1 == A || Op1 == B))
if (Instruction *R = ProcessUAddIdiom(I, Op0, *this))
return R;
-
+
// a >u (a+b) --> llvm.uadd.with.overflow.
// b >u (a+b) --> llvm.uadd.with.overflow.
if (I.getPredicate() == ICmpInst::ICMP_UGT &&
@@ -2465,7 +2466,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
if (Instruction *R = ProcessUAddIdiom(I, Op1, *this))
return R;
}
-
+
if (I.isEquality()) {
Value *A, *B, *C, *D;
@@ -2483,10 +2484,10 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
match(D, m_ConstantInt(C2)) && Op1->hasOneUse()) {
Constant *NC = ConstantInt::get(I.getContext(),
C1->getValue() ^ C2->getValue());
- Value *Xor = Builder->CreateXor(C, NC, "tmp");
+ Value *Xor = Builder->CreateXor(C, NC);
return new ICmpInst(I.getPredicate(), A, Xor);
}
-
+
// A^B == A^D -> B == D
if (A == C) return new ICmpInst(I.getPredicate(), B, D);
if (A == D) return new ICmpInst(I.getPredicate(), B, C);
@@ -2494,7 +2495,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
if (B == D) return new ICmpInst(I.getPredicate(), A, C);
}
}
-
+
if (match(Op1, m_Xor(m_Value(A), m_Value(B))) &&
(A == Op0 || B == Op0)) {
// A == (A^B) -> B == 0
@@ -2504,10 +2505,10 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
}
// (X&Z) == (Y&Z) -> (X^Y) & Z == 0
- if (match(Op0, m_OneUse(m_And(m_Value(A), m_Value(B)))) &&
+ if (match(Op0, m_OneUse(m_And(m_Value(A), m_Value(B)))) &&
match(Op1, m_OneUse(m_And(m_Value(C), m_Value(D))))) {
Value *X = 0, *Y = 0, *Z = 0;
-
+
if (A == C) {
X = B; Y = D; Z = A;
} else if (A == D) {
@@ -2517,16 +2518,16 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
} else if (B == D) {
X = A; Y = C; Z = B;
}
-
+
if (X) { // Build (X^Y) & Z
- Op1 = Builder->CreateXor(X, Y, "tmp");
- Op1 = Builder->CreateAnd(Op1, Z, "tmp");
+ Op1 = Builder->CreateXor(X, Y);
+ Op1 = Builder->CreateAnd(Op1, Z);
I.setOperand(0, Op1);
I.setOperand(1, Constant::getNullValue(Op1->getType()));
return &I;
}
}
-
+
// Transform "icmp eq (trunc (lshr(X, cst1)), cst" to
// "icmp (and X, mask), cst"
uint64_t ShAmt = 0;
@@ -2539,21 +2540,21 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
// when it exposes other optimizations.
!A->hasOneUse()) {
unsigned ASize =cast<IntegerType>(A->getType())->getPrimitiveSizeInBits();
-
+
if (ShAmt < ASize) {
APInt MaskV =
APInt::getLowBitsSet(ASize, Op0->getType()->getPrimitiveSizeInBits());
MaskV <<= ShAmt;
-
+
APInt CmpV = Cst1->getValue().zext(ASize);
CmpV <<= ShAmt;
-
+
Value *Mask = Builder->CreateAnd(A, Builder->getInt(MaskV));
return new ICmpInst(I.getPredicate(), Mask, Builder->getInt(CmpV));
}
}
}
-
+
{
Value *X; ConstantInt *Cst;
// icmp X+Cst, X
@@ -2579,31 +2580,31 @@ Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I,
Constant *RHSC) {
if (!isa<ConstantFP>(RHSC)) return 0;
const APFloat &RHS = cast<ConstantFP>(RHSC)->getValueAPF();
-
+
// Get the width of the mantissa. We don't want to hack on conversions that
// might lose information from the integer, e.g. "i64 -> float"
int MantissaWidth = LHSI->getType()->getFPMantissaWidth();
if (MantissaWidth == -1) return 0; // Unknown.
-
+
// Check to see that the input is converted from an integer type that is small
// enough that preserves all bits. TODO: check here for "known" sign bits.
// This would allow us to handle (fptosi (x >>s 62) to float) if x is i64 f.e.
unsigned InputSize = LHSI->getOperand(0)->getType()->getScalarSizeInBits();
-
+
// If this is a uitofp instruction, we need an extra bit to hold the sign.
bool LHSUnsigned = isa<UIToFPInst>(LHSI);
if (LHSUnsigned)
++InputSize;
-
+
// If the conversion would lose info, don't hack on this.
if ((int)InputSize > MantissaWidth)
return 0;
-
+
// Otherwise, we can potentially simplify the comparison. We know that it
// will always come through as an integer value and we know the constant is
// not a NAN (it would have been previously simplified).
assert(!RHS.isNaN() && "NaN comparison not already folded!");
-
+
ICmpInst::Predicate Pred;
switch (I.getPredicate()) {
default: llvm_unreachable("Unexpected predicate!");
@@ -2636,15 +2637,15 @@ Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I,
case FCmpInst::FCMP_UNO:
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
}
-
- const IntegerType *IntTy = cast<IntegerType>(LHSI->getOperand(0)->getType());
-
+
+ IntegerType *IntTy = cast<IntegerType>(LHSI->getOperand(0)->getType());
+
// Now we know that the APFloat is a normal number, zero or inf.
-
+
// See if the FP constant is too large for the integer. For example,
// comparing an i8 to 300.0.
unsigned IntWidth = IntTy->getScalarSizeInBits();
-
+
if (!LHSUnsigned) {
// If the RHS value is > SignedMax, fold the comparison. This handles +INF
// and large values.
@@ -2670,7 +2671,7 @@ Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I,
return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext()));
}
}
-
+
if (!LHSUnsigned) {
// See if the RHS value is < SignedMin.
APFloat SMin(RHS.getSemantics(), APFloat::fcZero, false);
@@ -2766,7 +2767,7 @@ Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I,
Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
bool Changed = false;
-
+
/// Orders the operands of the compare so that they are listed from most
/// complex to least complex. This puts constants before unary operators,
/// before binary operators.
@@ -2776,7 +2777,7 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
}
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
-
+
if (Value *V = SimplifyFCmpInst(I.getPredicate(), Op0, Op1, TD))
return ReplaceInstUsesWith(I, V);
@@ -2792,7 +2793,7 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
I.setPredicate(FCmpInst::FCMP_UNO);
I.setOperand(1, Constant::getNullValue(Op0->getType()));
return &I;
-
+
case FCmpInst::FCMP_ORD: // True if ordered (no nans)
case FCmpInst::FCMP_OEQ: // True if ordered and equal
case FCmpInst::FCMP_OGE: // True if ordered and greater than or equal
@@ -2803,7 +2804,7 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
return &I;
}
}
-
+
// Handle fcmp with constant RHS
if (Constant *RHSC = dyn_cast<Constant>(Op1)) {
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
@@ -2836,10 +2837,14 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
APFloat F = RHSF->getValueAPF();
F.convert(*Sem, APFloat::rmNearestTiesToEven, &Lossy);
- // Avoid lossy conversions and denormals.
+ // Avoid lossy conversions and denormals. Zero is a special case
+ // that's OK to convert.
+ APFloat Fabs = F;
+ Fabs.clearSign();
if (!Lossy &&
- F.compare(APFloat::getSmallestNormalized(*Sem)) !=
- APFloat::cmpLessThan)
+ ((Fabs.compare(APFloat::getSmallestNormalized(*Sem)) !=
+ APFloat::cmpLessThan) || Fabs.isZero()))
+
return new FCmpInst(I.getPredicate(), LHSExt->getOperand(0),
ConstantFP::get(RHSC->getContext(), F));
break;
diff --git a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index f499290..7446a51 100644
--- a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -26,7 +26,7 @@ Instruction *InstCombiner::visitAllocaInst(AllocaInst &AI) {
// Ensure that the alloca array size argument has type intptr_t, so that
// any casting is exposed early.
if (TD) {
- const Type *IntPtrTy = TD->getIntPtrType(AI.getContext());
+ Type *IntPtrTy = TD->getIntPtrType(AI.getContext());
if (AI.getArraySize()->getType() != IntPtrTy) {
Value *V = Builder->CreateIntCast(AI.getArraySize(),
IntPtrTy, false);
@@ -38,7 +38,7 @@ Instruction *InstCombiner::visitAllocaInst(AllocaInst &AI) {
// Convert: alloca Ty, C - where C is a constant != 1 into: alloca [C x Ty], 1
if (AI.isArrayAllocation()) { // Check C != 1
if (const ConstantInt *C = dyn_cast<ConstantInt>(AI.getArraySize())) {
- const Type *NewTy =
+ Type *NewTy =
ArrayType::get(AI.getAllocatedType(), C->getZExtValue());
assert(isa<AllocaInst>(AI) && "Unknown type of allocation inst!");
AllocaInst *New = Builder->CreateAlloca(NewTy, 0, AI.getName());
@@ -58,8 +58,7 @@ Instruction *InstCombiner::visitAllocaInst(AllocaInst &AI) {
Idx[0] = NullIdx;
Idx[1] = NullIdx;
Instruction *GEP =
- GetElementPtrInst::CreateInBounds(New, Idx, Idx + 2,
- New->getName()+".sub");
+ GetElementPtrInst::CreateInBounds(New, Idx, New->getName()+".sub");
InsertNewInstBefore(GEP, *It);
// Now make everything use the getelementptr instead of the original
@@ -92,28 +91,28 @@ static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI,
User *CI = cast<User>(LI.getOperand(0));
Value *CastOp = CI->getOperand(0);
- const PointerType *DestTy = cast<PointerType>(CI->getType());
- const Type *DestPTy = DestTy->getElementType();
- if (const PointerType *SrcTy = dyn_cast<PointerType>(CastOp->getType())) {
+ PointerType *DestTy = cast<PointerType>(CI->getType());
+ Type *DestPTy = DestTy->getElementType();
+ if (PointerType *SrcTy = dyn_cast<PointerType>(CastOp->getType())) {
// If the address spaces don't match, don't eliminate the cast.
if (DestTy->getAddressSpace() != SrcTy->getAddressSpace())
return 0;
- const Type *SrcPTy = SrcTy->getElementType();
+ Type *SrcPTy = SrcTy->getElementType();
if (DestPTy->isIntegerTy() || DestPTy->isPointerTy() ||
DestPTy->isVectorTy()) {
// If the source is an array, the code below will not succeed. Check to
// see if a trivial 'gep P, 0, 0' will help matters. Only do this for
// constants.
- if (const ArrayType *ASrcTy = dyn_cast<ArrayType>(SrcPTy))
+ if (ArrayType *ASrcTy = dyn_cast<ArrayType>(SrcPTy))
if (Constant *CSrc = dyn_cast<Constant>(CastOp))
if (ASrcTy->getNumElements() != 0) {
Value *Idxs[2];
Idxs[0] = Constant::getNullValue(Type::getInt32Ty(LI.getContext()));
Idxs[1] = Idxs[0];
- CastOp = ConstantExpr::getGetElementPtr(CSrc, Idxs, 2);
+ CastOp = ConstantExpr::getGetElementPtr(CSrc, Idxs);
SrcTy = cast<PointerType>(CastOp->getType());
SrcPTy = SrcTy->getElementType();
}
@@ -133,6 +132,7 @@ static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI,
LoadInst *NewLoad =
IC.Builder->CreateLoad(CastOp, LI.isVolatile(), CI->getName());
NewLoad->setAlignment(LI.getAlignment());
+ NewLoad->setAtomic(LI.getOrdering(), LI.getSynchScope());
// Now cast the result of the load.
return new BitCastInst(NewLoad, LI.getType());
}
@@ -163,8 +163,9 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) {
if (Instruction *Res = InstCombineLoadCast(*this, LI, TD))
return Res;
- // None of the following transforms are legal for volatile loads.
- if (LI.isVolatile()) return 0;
+ // None of the following transforms are legal for volatile/atomic loads.
+ // FIXME: Some of it is okay for atomic loads; needs refactoring.
+ if (!LI.isSimple()) return 0;
// Do really simple store-to-load forwarding and load CSE, to catch cases
// where there are several consecutive memory accesses to the same location,
@@ -256,11 +257,11 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) {
User *CI = cast<User>(SI.getOperand(1));
Value *CastOp = CI->getOperand(0);
- const Type *DestPTy = cast<PointerType>(CI->getType())->getElementType();
- const PointerType *SrcTy = dyn_cast<PointerType>(CastOp->getType());
+ Type *DestPTy = cast<PointerType>(CI->getType())->getElementType();
+ PointerType *SrcTy = dyn_cast<PointerType>(CastOp->getType());
if (SrcTy == 0) return 0;
- const Type *SrcPTy = SrcTy->getElementType();
+ Type *SrcPTy = SrcTy->getElementType();
if (!DestPTy->isIntegerTy() && !DestPTy->isPointerTy())
return 0;
@@ -280,12 +281,12 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) {
NewGEPIndices.push_back(Zero);
while (1) {
- if (const StructType *STy = dyn_cast<StructType>(SrcPTy)) {
+ if (StructType *STy = dyn_cast<StructType>(SrcPTy)) {
if (!STy->getNumElements()) /* Struct can be empty {} */
break;
NewGEPIndices.push_back(Zero);
SrcPTy = STy->getElementType(0);
- } else if (const ArrayType *ATy = dyn_cast<ArrayType>(SrcPTy)) {
+ } else if (ArrayType *ATy = dyn_cast<ArrayType>(SrcPTy)) {
NewGEPIndices.push_back(Zero);
SrcPTy = ATy->getElementType();
} else {
@@ -314,8 +315,8 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) {
Value *NewCast;
Value *SIOp0 = SI.getOperand(0);
Instruction::CastOps opcode = Instruction::BitCast;
- const Type* CastSrcTy = SIOp0->getType();
- const Type* CastDstTy = SrcPTy;
+ Type* CastSrcTy = SIOp0->getType();
+ Type* CastDstTy = SrcPTy;
if (CastDstTy->isPointerTy()) {
if (CastSrcTy->isIntegerTy())
opcode = Instruction::IntToPtr;
@@ -327,8 +328,7 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) {
// SIOp0 is a pointer to aggregate and this is a store to the first field,
// emit a GEP to index into its first field.
if (!NewGEPIndices.empty())
- CastOp = IC.Builder->CreateInBoundsGEP(CastOp, NewGEPIndices.begin(),
- NewGEPIndices.end());
+ CastOp = IC.Builder->CreateInBoundsGEP(CastOp, NewGEPIndices);
NewCast = IC.Builder->CreateCast(opcode, SIOp0, CastDstTy,
SIOp0->getName()+".c");
@@ -370,21 +370,6 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) {
Value *Val = SI.getOperand(0);
Value *Ptr = SI.getOperand(1);
- // If the RHS is an alloca with a single use, zapify the store, making the
- // alloca dead.
- if (!SI.isVolatile()) {
- if (Ptr->hasOneUse()) {
- if (isa<AllocaInst>(Ptr))
- return EraseInstFromFunction(SI);
- if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr)) {
- if (isa<AllocaInst>(GEP->getOperand(0))) {
- if (GEP->getOperand(0)->hasOneUse())
- return EraseInstFromFunction(SI);
- }
- }
- }
- }
-
// Attempt to improve the alignment.
if (TD) {
unsigned KnownAlign =
@@ -400,6 +385,23 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) {
SI.setAlignment(EffectiveStoreAlign);
}
+ // Don't hack volatile/atomic stores.
+ // FIXME: Some bits are legal for atomic stores; needs refactoring.
+ if (!SI.isSimple()) return 0;
+
+ // If the RHS is an alloca with a single use, zapify the store, making the
+ // alloca dead.
+ if (Ptr->hasOneUse()) {
+ if (isa<AllocaInst>(Ptr))
+ return EraseInstFromFunction(SI);
+ if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr)) {
+ if (isa<AllocaInst>(GEP->getOperand(0))) {
+ if (GEP->getOperand(0)->hasOneUse())
+ return EraseInstFromFunction(SI);
+ }
+ }
+ }
+
// Do really simple DSE, to catch cases where there are several consecutive
// stores to the same location, separated by a few arithmetic operations. This
// situation often occurs with bitfield accesses.
@@ -417,8 +419,8 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) {
if (StoreInst *PrevSI = dyn_cast<StoreInst>(BBI)) {
// Prev store isn't volatile, and stores to the same location?
- if (!PrevSI->isVolatile() &&equivalentAddressValues(PrevSI->getOperand(1),
- SI.getOperand(1))) {
+ if (PrevSI->isSimple() && equivalentAddressValues(PrevSI->getOperand(1),
+ SI.getOperand(1))) {
++NumDeadStore;
++BBI;
EraseInstFromFunction(*PrevSI);
@@ -432,7 +434,7 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) {
// then *this* store is dead (X = load P; store X -> P).
if (LoadInst *LI = dyn_cast<LoadInst>(BBI)) {
if (LI == Val && equivalentAddressValues(LI->getOperand(0), Ptr) &&
- !SI.isVolatile())
+ LI->isSimple())
return EraseInstFromFunction(SI);
// Otherwise, this is a load from some other location. Stores before it
@@ -444,9 +446,6 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) {
if (BBI->mayWriteToMemory() || BBI->mayReadFromMemory())
break;
}
-
-
- if (SI.isVolatile()) return 0; // Don't hack volatile stores.
// store X, null -> turns into 'unreachable' in SimplifyCFG
if (isa<ConstantPointerNull>(Ptr) && SI.getPointerAddressSpace() == 0) {
@@ -549,11 +548,11 @@ bool InstCombiner::SimplifyStoreAtEndOfBlock(StoreInst &SI) {
return false;
--BBI;
}
- // If this isn't a store, isn't a store to the same location, or if the
- // alignments differ, bail out.
+ // If this isn't a store, isn't a store to the same location, or is not the
+ // right kind of store, bail out.
OtherStore = dyn_cast<StoreInst>(BBI);
if (!OtherStore || OtherStore->getOperand(1) != SI.getOperand(1) ||
- OtherStore->getAlignment() != SI.getAlignment())
+ !SI.isSameOperationAs(OtherStore))
return false;
} else {
// Otherwise, the other block ended with a conditional branch. If one of the
@@ -569,7 +568,7 @@ bool InstCombiner::SimplifyStoreAtEndOfBlock(StoreInst &SI) {
// Check to see if we find the matching store.
if ((OtherStore = dyn_cast<StoreInst>(BBI))) {
if (OtherStore->getOperand(1) != SI.getOperand(1) ||
- OtherStore->getAlignment() != SI.getAlignment())
+ !SI.isSameOperationAs(OtherStore))
return false;
break;
}
@@ -601,10 +600,12 @@ bool InstCombiner::SimplifyStoreAtEndOfBlock(StoreInst &SI) {
// Advance to a place where it is safe to insert the new store and
// insert it.
- BBI = DestBB->getFirstNonPHI();
+ BBI = DestBB->getFirstInsertionPt();
StoreInst *NewSI = new StoreInst(MergedVal, SI.getOperand(1),
- OtherStore->isVolatile(),
- SI.getAlignment());
+ SI.isVolatile(),
+ SI.getAlignment(),
+ SI.getOrdering(),
+ SI.getSynchScope());
InsertNewInstBefore(NewSI, *BBI);
NewSI->setDebugLoc(OtherStore->getDebugLoc());
diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 630a6fe..7f48125 100644
--- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -38,7 +38,7 @@ static Value *simplifyValueKnownNonZero(Value *V, InstCombiner &IC) {
m_Value(B))) &&
// The "1" can be any value known to be a power of 2.
isPowerOfTwo(PowerOf2, IC.getTargetData())) {
- A = IC.Builder->CreateSub(A, B, "tmp");
+ A = IC.Builder->CreateSub(A, B);
return IC.Builder->CreateShl(PowerOf2, A);
}
@@ -131,7 +131,7 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
{ Value *X; ConstantInt *C1;
if (Op0->hasOneUse() &&
match(Op0, m_Add(m_Value(X), m_ConstantInt(C1)))) {
- Value *Add = Builder->CreateMul(X, CI, "tmp");
+ Value *Add = Builder->CreateMul(X, CI);
return BinaryOperator::CreateAdd(Add, Builder->CreateMul(C1, CI));
}
}
@@ -244,7 +244,7 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
if (BoolCast) {
Value *V = Builder->CreateSub(Constant::getNullValue(I.getType()),
- BoolCast, "tmp");
+ BoolCast);
return BinaryOperator::CreateAnd(V, OtherOp);
}
}
@@ -421,7 +421,7 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) {
/// dyn_castZExtVal - Checks if V is a zext or constant that can
/// be truncated to Ty without losing bits.
-static Value *dyn_castZExtVal(Value *V, const Type *Ty) {
+static Value *dyn_castZExtVal(Value *V, Type *Ty) {
if (ZExtInst *Z = dyn_cast<ZExtInst>(V)) {
if (Z->getSrcTy() == Ty)
return Z->getOperand(0);
@@ -466,8 +466,7 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
{ const APInt *CI; Value *N;
if (match(Op1, m_Shl(m_Power2(CI), m_Value(N)))) {
if (*CI != 1)
- N = Builder->CreateAdd(N, ConstantInt::get(I.getType(), CI->logBase2()),
- "tmp");
+ N = Builder->CreateAdd(N, ConstantInt::get(I.getType(),CI->logBase2()));
if (I.isExact())
return BinaryOperator::CreateExactLShr(Op0, N);
return BinaryOperator::CreateLShr(Op0, N);
@@ -630,7 +629,7 @@ Instruction *InstCombiner::visitURem(BinaryOperator &I) {
// Turn A % (C << N), where C is 2^k, into A & ((C << N)-1)
if (match(Op1, m_Shl(m_Power2(), m_Value()))) {
Constant *N1 = Constant::getAllOnesValue(I.getType());
- Value *Add = Builder->CreateAdd(Op1, N1, "tmp");
+ Value *Add = Builder->CreateAdd(Op1, N1);
return BinaryOperator::CreateAnd(Op0, Add);
}
diff --git a/lib/Transforms/InstCombine/InstCombinePHI.cpp b/lib/Transforms/InstCombine/InstCombinePHI.cpp
index 3777340..664546c 100644
--- a/lib/Transforms/InstCombine/InstCombinePHI.cpp
+++ b/lib/Transforms/InstCombine/InstCombinePHI.cpp
@@ -28,8 +28,8 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) {
Value *LHSVal = FirstInst->getOperand(0);
Value *RHSVal = FirstInst->getOperand(1);
- const Type *LHSType = LHSVal->getType();
- const Type *RHSType = RHSVal->getType();
+ Type *LHSType = LHSVal->getType();
+ Type *RHSType = RHSVal->getType();
bool isNUW = false, isNSW = false, isExact = false;
if (OverflowingBinaryOperator *BO =
@@ -229,8 +229,7 @@ Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) {
Value *Base = FixedOperands[0];
GetElementPtrInst *NewGEP =
- GetElementPtrInst::Create(Base, FixedOperands.begin()+1,
- FixedOperands.end());
+ GetElementPtrInst::Create(Base, makeArrayRef(FixedOperands).slice(1));
if (AllInBounds) NewGEP->setIsInBounds();
NewGEP->setDebugLoc(FirstInst->getDebugLoc());
return NewGEP;
@@ -287,7 +286,12 @@ static bool isSafeAndProfitableToSinkLoad(LoadInst *L) {
Instruction *InstCombiner::FoldPHIArgLoadIntoPHI(PHINode &PN) {
LoadInst *FirstLI = cast<LoadInst>(PN.getIncomingValue(0));
-
+
+ // FIXME: This is overconservative; this transform is allowed in some cases
+ // for atomic operations.
+ if (FirstLI->isAtomic())
+ return 0;
+
// When processing loads, we need to propagate two bits of information to the
// sunk load: whether it is volatile, and what its alignment is. We currently
// don't sink loads when some have their alignment specified and some don't.
@@ -397,7 +401,7 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
// the same type or "+42") we can pull the operation through the PHI, reducing
// code size and simplifying code.
Constant *ConstantOp = 0;
- const Type *CastSrcTy = 0;
+ Type *CastSrcTy = 0;
bool isNUW = false, isNSW = false, isExact = false;
if (isa<CastInst>(FirstInst)) {
@@ -572,7 +576,7 @@ struct LoweredPHIRecord {
unsigned Shift; // The amount shifted.
unsigned Width; // The width extracted.
- LoweredPHIRecord(PHINode *pn, unsigned Sh, const Type *Ty)
+ LoweredPHIRecord(PHINode *pn, unsigned Sh, Type *Ty)
: PN(pn), Shift(Sh), Width(Ty->getPrimitiveSizeInBits()) {}
// Ctor form used by DenseMap.
@@ -701,7 +705,7 @@ Instruction *InstCombiner::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) {
unsigned PHIId = PHIUsers[UserI].PHIId;
PHINode *PN = PHIsToSlice[PHIId];
unsigned Offset = PHIUsers[UserI].Shift;
- const Type *Ty = PHIUsers[UserI].Inst->getType();
+ Type *Ty = PHIUsers[UserI].Inst->getType();
PHINode *EltPHI;
diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 5733c20..91e60a4 100644
--- a/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -13,6 +13,7 @@
#include "InstCombine.h"
#include "llvm/Support/PatternMatch.h"
+#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstructionSimplify.h"
using namespace llvm;
using namespace PatternMatch;
@@ -323,9 +324,14 @@ static Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
}
// All operands were constants, fold it.
- if (ConstOps.size() == I->getNumOperands())
+ if (ConstOps.size() == I->getNumOperands()) {
+ if (LoadInst *LI = dyn_cast<LoadInst>(I))
+ if (!LI->isVolatile())
+ return ConstantFoldLoadFromConstPtr(ConstOps[0], TD);
+
return ConstantFoldInstOperands(I->getOpcode(), I->getType(),
- ConstOps.data(), ConstOps.size(), TD);
+ ConstOps, TD);
+ }
}
return 0;
@@ -363,7 +369,7 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI,
case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_SGT: {
// These transformations only work for selects over integers.
- const IntegerType *SelectTy = dyn_cast<IntegerType>(SI.getType());
+ IntegerType *SelectTy = dyn_cast<IntegerType>(SI.getType());
if (!SelectTy)
break;
@@ -443,7 +449,7 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI,
// FIXME: Type and constness constraints could be lifted, but we have to
// watch code size carefully. We should consider xor instead of
// sub/add when we decide to do that.
- if (const IntegerType *Ty = dyn_cast<IntegerType>(CmpLHS->getType())) {
+ if (IntegerType *Ty = dyn_cast<IntegerType>(CmpLHS->getType())) {
if (TrueVal->getType() == Ty) {
if (ConstantInt *Cmp = dyn_cast<ConstantInt>(CmpRHS)) {
ConstantInt *C1 = NULL, *C2 = NULL;
@@ -476,10 +482,16 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI,
if (SimplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, TD) == TrueVal ||
SimplifyWithOpReplaced(FalseVal, CmpRHS, CmpLHS, TD) == TrueVal)
return ReplaceInstUsesWith(SI, FalseVal);
+ if (SimplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, TD) == FalseVal ||
+ SimplifyWithOpReplaced(TrueVal, CmpRHS, CmpLHS, TD) == FalseVal)
+ return ReplaceInstUsesWith(SI, FalseVal);
} else if (Pred == ICmpInst::ICMP_NE) {
if (SimplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, TD) == FalseVal ||
SimplifyWithOpReplaced(TrueVal, CmpRHS, CmpLHS, TD) == FalseVal)
return ReplaceInstUsesWith(SI, TrueVal);
+ if (SimplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, TD) == TrueVal ||
+ SimplifyWithOpReplaced(FalseVal, CmpRHS, CmpLHS, TD) == TrueVal)
+ return ReplaceInstUsesWith(SI, TrueVal);
}
// NOTE: if we wanted to, this is where to detect integer MIN/MAX
diff --git a/lib/Transforms/InstCombine/InstCombineShifts.cpp b/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 811f949..6d85add 100644
--- a/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -13,6 +13,7 @@
#include "InstCombine.h"
#include "llvm/IntrinsicInst.h"
+#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Support/PatternMatch.h"
using namespace llvm;
@@ -207,11 +208,12 @@ static Value *GetShiftedValue(Value *V, unsigned NumBits, bool isLeftShift,
return I;
case Instruction::Shl: {
- unsigned TypeWidth = I->getType()->getScalarSizeInBits();
+ BinaryOperator *BO = cast<BinaryOperator>(I);
+ unsigned TypeWidth = BO->getType()->getScalarSizeInBits();
// We only accept shifts-by-a-constant in CanEvaluateShifted.
- ConstantInt *CI = cast<ConstantInt>(I->getOperand(1));
-
+ ConstantInt *CI = cast<ConstantInt>(BO->getOperand(1));
+
// We can always fold shl(c1)+shl(c2) -> shl(c1+c2).
if (isLeftShift) {
// If this is oversized composite shift, then unsigned shifts get 0.
@@ -219,7 +221,9 @@ static Value *GetShiftedValue(Value *V, unsigned NumBits, bool isLeftShift,
if (NewShAmt >= TypeWidth)
return Constant::getNullValue(I->getType());
- I->setOperand(1, ConstantInt::get(I->getType(), NewShAmt));
+ BO->setOperand(1, ConstantInt::get(BO->getType(), NewShAmt));
+ BO->setHasNoUnsignedWrap(false);
+ BO->setHasNoSignedWrap(false);
return I;
}
@@ -227,11 +231,11 @@ static Value *GetShiftedValue(Value *V, unsigned NumBits, bool isLeftShift,
// zeros.
if (CI->getValue() == NumBits) {
APInt Mask(APInt::getLowBitsSet(TypeWidth, TypeWidth - NumBits));
- V = IC.Builder->CreateAnd(I->getOperand(0),
- ConstantInt::get(I->getContext(), Mask));
+ V = IC.Builder->CreateAnd(BO->getOperand(0),
+ ConstantInt::get(BO->getContext(), Mask));
if (Instruction *VI = dyn_cast<Instruction>(V)) {
- VI->moveBefore(I);
- VI->takeName(I);
+ VI->moveBefore(BO);
+ VI->takeName(BO);
}
return V;
}
@@ -239,23 +243,27 @@ static Value *GetShiftedValue(Value *V, unsigned NumBits, bool isLeftShift,
// We turn shl(c1)+shr(c2) -> shl(c3)+and(c4), but only when we know that
// the and won't be needed.
assert(CI->getZExtValue() > NumBits);
- I->setOperand(1, ConstantInt::get(I->getType(),
- CI->getZExtValue() - NumBits));
- return I;
+ BO->setOperand(1, ConstantInt::get(BO->getType(),
+ CI->getZExtValue() - NumBits));
+ BO->setHasNoUnsignedWrap(false);
+ BO->setHasNoSignedWrap(false);
+ return BO;
}
case Instruction::LShr: {
- unsigned TypeWidth = I->getType()->getScalarSizeInBits();
+ BinaryOperator *BO = cast<BinaryOperator>(I);
+ unsigned TypeWidth = BO->getType()->getScalarSizeInBits();
// We only accept shifts-by-a-constant in CanEvaluateShifted.
- ConstantInt *CI = cast<ConstantInt>(I->getOperand(1));
+ ConstantInt *CI = cast<ConstantInt>(BO->getOperand(1));
// We can always fold lshr(c1)+lshr(c2) -> lshr(c1+c2).
if (!isLeftShift) {
// If this is oversized composite shift, then unsigned shifts get 0.
unsigned NewShAmt = NumBits+CI->getZExtValue();
if (NewShAmt >= TypeWidth)
- return Constant::getNullValue(I->getType());
+ return Constant::getNullValue(BO->getType());
- I->setOperand(1, ConstantInt::get(I->getType(), NewShAmt));
+ BO->setOperand(1, ConstantInt::get(BO->getType(), NewShAmt));
+ BO->setIsExact(false);
return I;
}
@@ -264,7 +272,7 @@ static Value *GetShiftedValue(Value *V, unsigned NumBits, bool isLeftShift,
if (CI->getValue() == NumBits) {
APInt Mask(APInt::getHighBitsSet(TypeWidth, TypeWidth - NumBits));
V = IC.Builder->CreateAnd(I->getOperand(0),
- ConstantInt::get(I->getContext(), Mask));
+ ConstantInt::get(BO->getContext(), Mask));
if (Instruction *VI = dyn_cast<Instruction>(V)) {
VI->moveBefore(I);
VI->takeName(I);
@@ -275,9 +283,10 @@ static Value *GetShiftedValue(Value *V, unsigned NumBits, bool isLeftShift,
// We turn lshr(c1)+shl(c2) -> lshr(c3)+and(c4), but only when we know that
// the and won't be needed.
assert(CI->getZExtValue() > NumBits);
- I->setOperand(1, ConstantInt::get(I->getType(),
- CI->getZExtValue() - NumBits));
- return I;
+ BO->setOperand(1, ConstantInt::get(BO->getType(),
+ CI->getZExtValue() - NumBits));
+ BO->setIsExact(false);
+ return BO;
}
case Instruction::Select:
@@ -528,7 +537,7 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
uint32_t AmtSum = ShiftAmt1+ShiftAmt2; // Fold into one big shift.
- const IntegerType *Ty = cast<IntegerType>(I.getType());
+ IntegerType *Ty = cast<IntegerType>(I.getType());
// Check for (X << c1) << c2 and (X >> c1) >> c2
if (I.getOpcode() == ShiftOp->getOpcode()) {
diff --git a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 8fea8eb..5cd9a4b 100644
--- a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -103,7 +103,7 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
assert(V != 0 && "Null pointer of Value???");
assert(Depth <= 6 && "Limit Search Depth");
uint32_t BitWidth = DemandedMask.getBitWidth();
- const Type *VTy = V->getType();
+ Type *VTy = V->getType();
assert((TD || !VTy->isPointerTy()) &&
"SimplifyDemandedBits needs to know bit widths!");
assert((!TD || TD->getTypeSizeInBits(VTy->getScalarType()) == BitWidth) &&
@@ -325,8 +325,7 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
if ((RHSKnownOne & LHSKnownOne) == RHSKnownOne) {
Constant *AndC = Constant::getIntegerValue(VTy,
~RHSKnownOne & DemandedMask);
- Instruction *And =
- BinaryOperator::CreateAnd(I->getOperand(0), AndC, "tmp");
+ Instruction *And = BinaryOperator::CreateAnd(I->getOperand(0), AndC);
return InsertNewInstWith(And, *I);
}
}
@@ -351,14 +350,12 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
Constant *AndC =
ConstantInt::get(I->getType(), NewMask & AndRHS->getValue());
- Instruction *NewAnd =
- BinaryOperator::CreateAnd(I->getOperand(0), AndC, "tmp");
+ Instruction *NewAnd = BinaryOperator::CreateAnd(I->getOperand(0), AndC);
InsertNewInstWith(NewAnd, *I);
Constant *XorC =
ConstantInt::get(I->getType(), NewMask & XorRHS->getValue());
- Instruction *NewXor =
- BinaryOperator::CreateXor(NewAnd, XorC, "tmp");
+ Instruction *NewXor = BinaryOperator::CreateXor(NewAnd, XorC);
return InsertNewInstWith(NewXor, *I);
}
@@ -404,8 +401,8 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
if (!I->getOperand(0)->getType()->isIntOrIntVectorTy())
return 0; // vector->int or fp->int?
- if (const VectorType *DstVTy = dyn_cast<VectorType>(I->getType())) {
- if (const VectorType *SrcVTy =
+ if (VectorType *DstVTy = dyn_cast<VectorType>(I->getType())) {
+ if (VectorType *SrcVTy =
dyn_cast<VectorType>(I->getOperand(0)->getType())) {
if (DstVTy->getNumElements() != SrcVTy->getNumElements())
// Don't touch a bitcast between vectors of different element counts.
@@ -826,7 +823,7 @@ Value *InstCombiner::SimplifyDemandedVectorElts(Value *V, APInt DemandedElts,
UndefElts = 0;
if (ConstantVector *CV = dyn_cast<ConstantVector>(V)) {
- const Type *EltTy = cast<VectorType>(V->getType())->getElementType();
+ Type *EltTy = cast<VectorType>(V->getType())->getElementType();
Constant *Undef = UndefValue::get(EltTy);
std::vector<Constant*> Elts;
@@ -855,7 +852,7 @@ Value *InstCombiner::SimplifyDemandedVectorElts(Value *V, APInt DemandedElts,
if (DemandedElts.isAllOnesValue())
return 0;
- const Type *EltTy = cast<VectorType>(V->getType())->getElementType();
+ Type *EltTy = cast<VectorType>(V->getType())->getElementType();
Constant *Zero = Constant::getNullValue(EltTy);
Constant *Undef = UndefValue::get(EltTy);
std::vector<Constant*> Elts;
@@ -962,6 +959,9 @@ Value *InstCombiner::SimplifyDemandedVectorElts(Value *V, APInt DemandedElts,
unsigned MaskVal = Shuffle->getMaskValue(i);
if (MaskVal == -1u) {
UndefElts.setBit(i);
+ } else if (!DemandedElts[i]) {
+ NewUndefElts = true;
+ UndefElts.setBit(i);
} else if (MaskVal < LHSVWidth) {
if (UndefElts4[MaskVal]) {
NewUndefElts = true;
@@ -992,7 +992,7 @@ Value *InstCombiner::SimplifyDemandedVectorElts(Value *V, APInt DemandedElts,
}
case Instruction::BitCast: {
// Vector->vector casts only.
- const VectorType *VTy = dyn_cast<VectorType>(I->getOperand(0)->getType());
+ VectorType *VTy = dyn_cast<VectorType>(I->getOperand(0)->getType());
if (!VTy) break;
unsigned InVWidth = VTy->getNumElements();
APInt InputDemandedElts(InVWidth, 0);
diff --git a/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index ad6a8d0..154267c 100644
--- a/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -77,7 +77,7 @@ static std::vector<int> getShuffleMask(const ShuffleVectorInst *SVI) {
/// extracted from the vector.
static Value *FindScalarElement(Value *V, unsigned EltNo) {
assert(V->getType()->isVectorTy() && "Not looking at a vector?");
- const VectorType *PTy = cast<VectorType>(V->getType());
+ VectorType *PTy = cast<VectorType>(V->getType());
unsigned Width = PTy->getNumElements();
if (EltNo >= Width) // Out of range access.
return UndefValue::get(PTy->getElementType());
@@ -175,7 +175,7 @@ Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) {
// the same number of elements, see if we can find the source element from
// it. In this case, we will end up needing to bitcast the scalars.
if (BitCastInst *BCI = dyn_cast<BitCastInst>(EI.getOperand(0))) {
- if (const VectorType *VT =
+ if (VectorType *VT =
dyn_cast<VectorType>(BCI->getOperand(0)->getType()))
if (VT->getNumElements() == VectorWidth)
if (Value *Elt = FindScalarElement(BCI->getOperand(0), IndexVal))
@@ -225,7 +225,7 @@ Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) {
SrcIdx -= LHSWidth;
Src = SVI->getOperand(1);
}
- const Type *Int32Ty = Type::getInt32Ty(EI.getContext());
+ Type *Int32Ty = Type::getInt32Ty(EI.getContext());
return ExtractElementInst::Create(Src,
ConstantInt::get(Int32Ty,
SrcIdx, false));
@@ -555,7 +555,7 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
// shuffle mask, do the replacement.
if (isSplat || NewMask == LHSMask || NewMask == Mask) {
std::vector<Constant*> Elts;
- const Type *Int32Ty = Type::getInt32Ty(SVI.getContext());
+ Type *Int32Ty = Type::getInt32Ty(SVI.getContext());
for (unsigned i = 0, e = NewMask.size(); i != e; ++i) {
if (NewMask[i] < 0) {
Elts.push_back(UndefValue::get(Int32Ty));
diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp
index ab98ef9..92874b9 100644
--- a/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -46,8 +46,10 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/PatternMatch.h"
+#include "llvm/Support/ValueHandle.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm-c/Initialization.h"
#include <algorithm>
#include <climits>
@@ -83,7 +85,7 @@ void InstCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
/// ShouldChangeType - Return true if it is desirable to convert a computation
/// from 'From' to 'To'. We don't want to convert from a legal to an illegal
/// type for example, or from a smaller to a larger illegal type.
-bool InstCombiner::ShouldChangeType(const Type *From, const Type *To) const {
+bool InstCombiner::ShouldChangeType(Type *From, Type *To) const {
assert(From->isIntegerTy() && To->isIntegerTy());
// If we don't have TD, we don't know if the source/dest are legal.
@@ -107,6 +109,43 @@ bool InstCombiner::ShouldChangeType(const Type *From, const Type *To) const {
return true;
}
+// Return true, if No Signed Wrap should be maintained for I.
+// The No Signed Wrap flag can be kept if the operation "B (I.getOpcode) C",
+// where both B and C should be ConstantInts, results in a constant that does
+// not overflow. This function only handles the Add and Sub opcodes. For
+// all other opcodes, the function conservatively returns false.
+static bool MaintainNoSignedWrap(BinaryOperator &I, Value *B, Value *C) {
+ OverflowingBinaryOperator *OBO = dyn_cast<OverflowingBinaryOperator>(&I);
+ if (!OBO || !OBO->hasNoSignedWrap()) {
+ return false;
+ }
+
+ // We reason about Add and Sub Only.
+ Instruction::BinaryOps Opcode = I.getOpcode();
+ if (Opcode != Instruction::Add &&
+ Opcode != Instruction::Sub) {
+ return false;
+ }
+
+ ConstantInt *CB = dyn_cast<ConstantInt>(B);
+ ConstantInt *CC = dyn_cast<ConstantInt>(C);
+
+ if (!CB || !CC) {
+ return false;
+ }
+
+ const APInt &BVal = CB->getValue();
+ const APInt &CVal = CC->getValue();
+ bool Overflow = false;
+
+ if (Opcode == Instruction::Add) {
+ BVal.sadd_ov(CVal, Overflow);
+ } else {
+ BVal.ssub_ov(CVal, Overflow);
+ }
+
+ return !Overflow;
+}
/// SimplifyAssociativeOrCommutative - This performs a few simplifications for
/// operators which are associative or commutative:
@@ -158,7 +197,16 @@ bool InstCombiner::SimplifyAssociativeOrCommutative(BinaryOperator &I) {
I.setOperand(1, V);
// Conservatively clear the optional flags, since they may not be
// preserved by the reassociation.
- I.clearSubclassOptionalData();
+ if (MaintainNoSignedWrap(I, B, C) &&
+ (!Op0 || (isa<BinaryOperator>(Op0) && Op0->hasNoSignedWrap()))) {
+ // Note: this is only valid because SimplifyBinOp doesn't look at
+ // the operands to Op0.
+ I.clearSubclassOptionalData();
+ I.setHasNoSignedWrap(true);
+ } else {
+ I.clearSubclassOptionalData();
+ }
+
Changed = true;
++NumReassoc;
continue;
@@ -240,7 +288,7 @@ bool InstCombiner::SimplifyAssociativeOrCommutative(BinaryOperator &I) {
Constant *C2 = cast<Constant>(Op1->getOperand(1));
Constant *Folded = ConstantExpr::get(Opcode, C1, C2);
- Instruction *New = BinaryOperator::Create(Opcode, A, B);
+ BinaryOperator *New = BinaryOperator::Create(Opcode, A, B);
InsertNewInstWith(New, I);
New->takeName(Op1);
I.setOperand(0, New);
@@ -248,6 +296,7 @@ bool InstCombiner::SimplifyAssociativeOrCommutative(BinaryOperator &I) {
// Conservatively clear the optional flags, since they may not be
// preserved by the reassociation.
I.clearSubclassOptionalData();
+
Changed = true;
continue;
}
@@ -516,8 +565,8 @@ Instruction *InstCombiner::FoldOpIntoSelect(Instruction &Op, SelectInst *SI) {
// If it's a bitcast involving vectors, make sure it has the same number of
// elements on both sides.
if (BitCastInst *BC = dyn_cast<BitCastInst>(&Op)) {
- const VectorType *DestTy = dyn_cast<VectorType>(BC->getDestTy());
- const VectorType *SrcTy = dyn_cast<VectorType>(BC->getSrcTy());
+ VectorType *DestTy = dyn_cast<VectorType>(BC->getDestTy());
+ VectorType *SrcTy = dyn_cast<VectorType>(BC->getSrcTy());
// Verify that either both or neither are vectors.
if ((SrcTy == NULL) != (DestTy == NULL)) return 0;
@@ -654,7 +703,7 @@ Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
}
} else {
CastInst *CI = cast<CastInst>(&I);
- const Type *RetTy = CI->getType();
+ Type *RetTy = CI->getType();
for (unsigned i = 0; i != NumPHIValues; ++i) {
Value *InV;
if (Constant *InC = dyn_cast<Constant>(PN->getIncomingValue(i)))
@@ -680,7 +729,7 @@ Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
/// or not there is a sequence of GEP indices into the type that will land us at
/// the specified offset. If so, fill them into NewIndices and return the
/// resultant element type, otherwise return null.
-const Type *InstCombiner::FindElementAtOffset(const Type *Ty, int64_t Offset,
+Type *InstCombiner::FindElementAtOffset(Type *Ty, int64_t Offset,
SmallVectorImpl<Value*> &NewIndices) {
if (!TD) return 0;
if (!Ty->isSized()) return 0;
@@ -688,7 +737,7 @@ const Type *InstCombiner::FindElementAtOffset(const Type *Ty, int64_t Offset,
// Start with the index over the outer type. Note that the type size
// might be zero (even if the offset isn't zero) if the indexed type
// is something like [0 x {int, int}]
- const Type *IntPtrTy = TD->getIntPtrType(Ty->getContext());
+ Type *IntPtrTy = TD->getIntPtrType(Ty->getContext());
int64_t FirstIdx = 0;
if (int64_t TySize = TD->getTypeAllocSize(Ty)) {
FirstIdx = Offset/TySize;
@@ -711,7 +760,7 @@ const Type *InstCombiner::FindElementAtOffset(const Type *Ty, int64_t Offset,
if (uint64_t(Offset*8) >= TD->getTypeSizeInBits(Ty))
return 0;
- if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+ if (StructType *STy = dyn_cast<StructType>(Ty)) {
const StructLayout *SL = TD->getStructLayout(STy);
assert(Offset < (int64_t)SL->getSizeInBytes() &&
"Offset must stay within the indexed type");
@@ -722,7 +771,7 @@ const Type *InstCombiner::FindElementAtOffset(const Type *Ty, int64_t Offset,
Offset -= SL->getElementOffset(Elt);
Ty = STy->getElementType(Elt);
- } else if (const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
+ } else if (ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
uint64_t EltSize = TD->getTypeAllocSize(AT->getElementType());
assert(EltSize && "Cannot index into a zero-sized array");
NewIndices.push_back(ConstantInt::get(IntPtrTy,Offset/EltSize));
@@ -737,12 +786,20 @@ const Type *InstCombiner::FindElementAtOffset(const Type *Ty, int64_t Offset,
return Ty;
}
-
+static bool shouldMergeGEPs(GEPOperator &GEP, GEPOperator &Src) {
+ // If this GEP has only 0 indices, it is the same pointer as
+ // Src. If Src is not a trivial GEP too, don't combine
+ // the indices.
+ if (GEP.hasAllZeroIndices() && !Src.hasAllZeroIndices() &&
+ !Src.hasOneUse())
+ return false;
+ return true;
+}
Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
SmallVector<Value*, 8> Ops(GEP.op_begin(), GEP.op_end());
- if (Value *V = SimplifyGEPInst(&Ops[0], Ops.size(), TD))
+ if (Value *V = SimplifyGEPInst(Ops, TD))
return ReplaceInstUsesWith(GEP, V);
Value *PtrOp = GEP.getOperand(0);
@@ -751,13 +808,13 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
// by multiples of a zero size type with zero.
if (TD) {
bool MadeChange = false;
- const Type *IntPtrTy = TD->getIntPtrType(GEP.getContext());
+ Type *IntPtrTy = TD->getIntPtrType(GEP.getContext());
gep_type_iterator GTI = gep_type_begin(GEP);
for (User::op_iterator I = GEP.op_begin() + 1, E = GEP.op_end();
I != E; ++I, ++GTI) {
// Skip indices into struct types.
- const SequentialType *SeqTy = dyn_cast<SequentialType>(*GTI);
+ SequentialType *SeqTy = dyn_cast<SequentialType>(*GTI);
if (!SeqTy) continue;
// If the element type has zero size then any index over it is equivalent
@@ -785,21 +842,15 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
// getelementptr instructions into a single instruction.
//
if (GEPOperator *Src = dyn_cast<GEPOperator>(PtrOp)) {
-
- // If this GEP has only 0 indices, it is the same pointer as
- // Src. If Src is not a trivial GEP too, don't combine
- // the indices.
- if (GEP.hasAllZeroIndices() && !Src->hasAllZeroIndices() &&
- !Src->hasOneUse())
+ if (!shouldMergeGEPs(*cast<GEPOperator>(&GEP), *Src))
return 0;
// Note that if our source is a gep chain itself that we wait for that
// chain to be resolved before we perform this transformation. This
// avoids us creating a TON of code in some cases.
- //
- if (GetElementPtrInst *SrcGEP =
- dyn_cast<GetElementPtrInst>(Src->getOperand(0)))
- if (SrcGEP->getNumOperands() == 2)
+ if (GEPOperator *SrcGEP =
+ dyn_cast<GEPOperator>(Src->getOperand(0)))
+ if (SrcGEP->getNumOperands() == 2 && shouldMergeGEPs(*Src, *SrcGEP))
return 0; // Wait until our source is folded to completion.
SmallVector<Value*, 8> Indices;
@@ -851,15 +902,14 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
if (!Indices.empty())
return (GEP.isInBounds() && Src->isInBounds()) ?
- GetElementPtrInst::CreateInBounds(Src->getOperand(0), Indices.begin(),
- Indices.end(), GEP.getName()) :
- GetElementPtrInst::Create(Src->getOperand(0), Indices.begin(),
- Indices.end(), GEP.getName());
+ GetElementPtrInst::CreateInBounds(Src->getOperand(0), Indices,
+ GEP.getName()) :
+ GetElementPtrInst::Create(Src->getOperand(0), Indices, GEP.getName());
}
// Handle gep(bitcast x) and gep(gep x, 0, 0, 0).
Value *StrippedPtr = PtrOp->stripPointerCasts();
- const PointerType *StrippedPtrTy =cast<PointerType>(StrippedPtr->getType());
+ PointerType *StrippedPtrTy =cast<PointerType>(StrippedPtr->getType());
if (StrippedPtr != PtrOp &&
StrippedPtrTy->getAddressSpace() == GEP.getPointerAddressSpace()) {
@@ -875,21 +925,20 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
//
// This occurs when the program declares an array extern like "int X[];"
if (HasZeroPointerIndex) {
- const PointerType *CPTy = cast<PointerType>(PtrOp->getType());
- if (const ArrayType *CATy =
+ PointerType *CPTy = cast<PointerType>(PtrOp->getType());
+ if (ArrayType *CATy =
dyn_cast<ArrayType>(CPTy->getElementType())) {
// GEP (bitcast i8* X to [0 x i8]*), i32 0, ... ?
if (CATy->getElementType() == StrippedPtrTy->getElementType()) {
// -> GEP i8* X, ...
SmallVector<Value*, 8> Idx(GEP.idx_begin()+1, GEP.idx_end());
GetElementPtrInst *Res =
- GetElementPtrInst::Create(StrippedPtr, Idx.begin(),
- Idx.end(), GEP.getName());
+ GetElementPtrInst::Create(StrippedPtr, Idx, GEP.getName());
Res->setIsInBounds(GEP.isInBounds());
return Res;
}
- if (const ArrayType *XATy =
+ if (ArrayType *XATy =
dyn_cast<ArrayType>(StrippedPtrTy->getElementType())){
// GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ... ?
if (CATy->getElementType() == XATy->getElementType()) {
@@ -907,8 +956,8 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
// Transform things like:
// %t = getelementptr i32* bitcast ([2 x i32]* %str to i32*), i32 %V
// into: %t1 = getelementptr [2 x i32]* %str, i32 0, i32 %V; bitcast
- const Type *SrcElTy = StrippedPtrTy->getElementType();
- const Type *ResElTy=cast<PointerType>(PtrOp->getType())->getElementType();
+ Type *SrcElTy = StrippedPtrTy->getElementType();
+ Type *ResElTy=cast<PointerType>(PtrOp->getType())->getElementType();
if (TD && SrcElTy->isArrayTy() &&
TD->getTypeAllocSize(cast<ArrayType>(SrcElTy)->getElementType()) ==
TD->getTypeAllocSize(ResElTy)) {
@@ -916,8 +965,8 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
Idx[0] = Constant::getNullValue(Type::getInt32Ty(GEP.getContext()));
Idx[1] = GEP.getOperand(1);
Value *NewGEP = GEP.isInBounds() ?
- Builder->CreateInBoundsGEP(StrippedPtr, Idx, Idx + 2, GEP.getName()) :
- Builder->CreateGEP(StrippedPtr, Idx, Idx + 2, GEP.getName());
+ Builder->CreateInBoundsGEP(StrippedPtr, Idx, GEP.getName()) :
+ Builder->CreateGEP(StrippedPtr, Idx, GEP.getName());
// V and GEP are both pointer types --> BitCast
return new BitCastInst(NewGEP, GEP.getType());
}
@@ -975,8 +1024,8 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
Idx[0] = Constant::getNullValue(Type::getInt32Ty(GEP.getContext()));
Idx[1] = NewIdx;
Value *NewGEP = GEP.isInBounds() ?
- Builder->CreateInBoundsGEP(StrippedPtr, Idx, Idx + 2,GEP.getName()):
- Builder->CreateGEP(StrippedPtr, Idx, Idx + 2, GEP.getName());
+ Builder->CreateInBoundsGEP(StrippedPtr, Idx, GEP.getName()):
+ Builder->CreateGEP(StrippedPtr, Idx, GEP.getName());
// The NewGEP must be pointer typed, so must the old one -> BitCast
return new BitCastInst(NewGEP, GEP.getType());
}
@@ -1023,14 +1072,12 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
// field at Offset in 'A's type. If so, we can pull the cast through the
// GEP.
SmallVector<Value*, 8> NewIndices;
- const Type *InTy =
+ Type *InTy =
cast<PointerType>(BCI->getOperand(0)->getType())->getElementType();
if (FindElementAtOffset(InTy, Offset, NewIndices)) {
Value *NGEP = GEP.isInBounds() ?
- Builder->CreateInBoundsGEP(BCI->getOperand(0), NewIndices.begin(),
- NewIndices.end()) :
- Builder->CreateGEP(BCI->getOperand(0), NewIndices.begin(),
- NewIndices.end());
+ Builder->CreateInBoundsGEP(BCI->getOperand(0), NewIndices) :
+ Builder->CreateGEP(BCI->getOperand(0), NewIndices);
if (NGEP->getType() == GEP.getType())
return ReplaceInstUsesWith(GEP, NGEP);
@@ -1045,15 +1092,43 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
-static bool IsOnlyNullComparedAndFreed(const Value &V) {
- for (Value::const_use_iterator UI = V.use_begin(), UE = V.use_end();
+static bool IsOnlyNullComparedAndFreed(Value *V, SmallVectorImpl<WeakVH> &Users,
+ int Depth = 0) {
+ if (Depth == 8)
+ return false;
+
+ for (Value::use_iterator UI = V->use_begin(), UE = V->use_end();
UI != UE; ++UI) {
- const User *U = *UI;
- if (isFreeCall(U))
+ User *U = *UI;
+ if (isFreeCall(U)) {
+ Users.push_back(U);
continue;
- if (const ICmpInst *ICI = dyn_cast<ICmpInst>(U))
- if (ICI->isEquality() && isa<ConstantPointerNull>(ICI->getOperand(1)))
+ }
+ if (ICmpInst *ICI = dyn_cast<ICmpInst>(U)) {
+ if (ICI->isEquality() && isa<ConstantPointerNull>(ICI->getOperand(1))) {
+ Users.push_back(ICI);
+ continue;
+ }
+ }
+ if (BitCastInst *BCI = dyn_cast<BitCastInst>(U)) {
+ if (IsOnlyNullComparedAndFreed(BCI, Users, Depth+1)) {
+ Users.push_back(BCI);
+ continue;
+ }
+ }
+ if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(U)) {
+ if (IsOnlyNullComparedAndFreed(GEPI, Users, Depth+1)) {
+ Users.push_back(GEPI);
+ continue;
+ }
+ }
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
+ if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
+ II->getIntrinsicID() == Intrinsic::lifetime_end) {
+ Users.push_back(II);
continue;
+ }
+ }
return false;
}
return true;
@@ -1063,25 +1138,20 @@ Instruction *InstCombiner::visitMalloc(Instruction &MI) {
// If we have a malloc call which is only used in any amount of comparisons
// to null and free calls, delete the calls and replace the comparisons with
// true or false as appropriate.
- if (IsOnlyNullComparedAndFreed(MI)) {
- for (Value::use_iterator UI = MI.use_begin(), UE = MI.use_end();
- UI != UE;) {
- // We can assume that every remaining use is a free call or an icmp eq/ne
- // to null, so the cast is safe.
- Instruction *I = cast<Instruction>(*UI);
-
- // Early increment here, as we're about to get rid of the user.
- ++UI;
-
- if (isFreeCall(I)) {
- EraseInstFromFunction(*cast<CallInst>(I));
- continue;
+ SmallVector<WeakVH, 64> Users;
+ if (IsOnlyNullComparedAndFreed(&MI, Users)) {
+ for (unsigned i = 0, e = Users.size(); i != e; ++i) {
+ Instruction *I = cast_or_null<Instruction>(&*Users[i]);
+ if (!I) continue;
+
+ if (ICmpInst *C = dyn_cast<ICmpInst>(I)) {
+ ReplaceInstUsesWith(*C,
+ ConstantInt::get(Type::getInt1Ty(C->getContext()),
+ C->isFalseWhenEqual()));
+ } else if (isa<BitCastInst>(I) || isa<GetElementPtrInst>(I)) {
+ ReplaceInstUsesWith(*I, UndefValue::get(I->getType()));
}
- // Again, the cast is safe.
- ICmpInst *C = cast<ICmpInst>(I);
- ReplaceInstUsesWith(*C, ConstantInt::get(Type::getInt1Ty(C->getContext()),
- C->isFalseWhenEqual()));
- EraseInstFromFunction(*C);
+ EraseInstFromFunction(*I);
}
return EraseInstFromFunction(MI);
}
@@ -1120,8 +1190,7 @@ Instruction *InstCombiner::visitBranchInst(BranchInst &BI) {
!isa<Constant>(X)) {
// Swap Destinations and condition...
BI.setCondition(X);
- BI.setSuccessor(0, FalseDest);
- BI.setSuccessor(1, TrueDest);
+ BI.swapSuccessors();
return &BI;
}
@@ -1136,8 +1205,7 @@ Instruction *InstCombiner::visitBranchInst(BranchInst &BI) {
Cond->setPredicate(FCmpInst::getInversePredicate(FPred));
// Swap Destinations and condition.
- BI.setSuccessor(0, FalseDest);
- BI.setSuccessor(1, TrueDest);
+ BI.swapSuccessors();
Worklist.Add(Cond);
return &BI;
}
@@ -1153,8 +1221,7 @@ Instruction *InstCombiner::visitBranchInst(BranchInst &BI) {
ICmpInst *Cond = cast<ICmpInst>(BI.getCondition());
Cond->setPredicate(ICmpInst::getInversePredicate(IPred));
// Swap Destinations and condition.
- BI.setSuccessor(0, FalseDest);
- BI.setSuccessor(1, TrueDest);
+ BI.swapSuccessors();
Worklist.Add(Cond);
return &BI;
}
@@ -1168,11 +1235,17 @@ Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) {
if (I->getOpcode() == Instruction::Add)
if (ConstantInt *AddRHS = dyn_cast<ConstantInt>(I->getOperand(1))) {
// change 'switch (X+4) case 1:' into 'switch (X) case -3'
- for (unsigned i = 2, e = SI.getNumOperands(); i != e; i += 2)
- SI.setOperand(i,
- ConstantExpr::getSub(cast<Constant>(SI.getOperand(i)),
- AddRHS));
- SI.setOperand(0, I->getOperand(0));
+ unsigned NumCases = SI.getNumCases();
+ // Skip the first item since that's the default case.
+ for (unsigned i = 1; i < NumCases; ++i) {
+ ConstantInt* CaseVal = SI.getCaseValue(i);
+ Constant* NewCaseVal = ConstantExpr::getSub(cast<Constant>(CaseVal),
+ AddRHS);
+ assert(isa<ConstantInt>(NewCaseVal) &&
+ "Result of expression should be constant");
+ SI.setSuccessorValue(i, cast<ConstantInt>(NewCaseVal));
+ }
+ SI.setCondition(I->getOperand(0));
Worklist.Add(I);
return &SI;
}
@@ -1242,7 +1315,7 @@ Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) {
Value *NewEV = Builder->CreateExtractValue(IV->getAggregateOperand(),
EV.getIndices());
return InsertValueInst::Create(NewEV, IV->getInsertedValueOperand(),
- ArrayRef<unsigned>(insi, inse));
+ makeArrayRef(insi, inse));
}
if (insi == inse)
// The insert list is a prefix of the extract list
@@ -1254,7 +1327,7 @@ Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) {
// with
// %E extractvalue { i32 } { i32 42 }, 0
return ExtractValueInst::Create(IV->getInsertedValueOperand(),
- ArrayRef<unsigned>(exti, exte));
+ makeArrayRef(exti, exte));
}
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Agg)) {
// We're extracting from an intrinsic, see if we're the only user, which
@@ -1310,7 +1383,7 @@ Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) {
// load from a GEP. This reduces the size of the load.
// FIXME: If a load is used only by extractvalue instructions then this
// could be done regardless of having multiple uses.
- if (!L->isVolatile() && L->hasOneUse()) {
+ if (L->isSimple() && L->hasOneUse()) {
// extractvalue has integer indices, getelementptr has Value*s. Convert.
SmallVector<Value*, 4> Indices;
// Prefix an i32 0 since we need the first element.
@@ -1322,8 +1395,7 @@ Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) {
// We need to insert these at the location of the old load, not at that of
// the extractvalue.
Builder->SetInsertPoint(L->getParent(), L);
- Value *GEP = Builder->CreateInBoundsGEP(L->getPointerOperand(),
- Indices.begin(), Indices.end());
+ Value *GEP = Builder->CreateInBoundsGEP(L->getPointerOperand(), Indices);
// Returning the load directly will cause the main loop to insert it in
// the wrong spot, so use ReplaceInstUsesWith().
return ReplaceInstUsesWith(EV, Builder->CreateLoad(GEP));
@@ -1339,6 +1411,342 @@ Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) {
return 0;
}
+enum Personality_Type {
+ Unknown_Personality,
+ GNU_Ada_Personality,
+ GNU_CXX_Personality
+};
+
+/// RecognizePersonality - See if the given exception handling personality
+/// function is one that we understand. If so, return a description of it;
+/// otherwise return Unknown_Personality.
+static Personality_Type RecognizePersonality(Value *Pers) {
+ Function *F = dyn_cast<Function>(Pers->stripPointerCasts());
+ if (!F)
+ return Unknown_Personality;
+ return StringSwitch<Personality_Type>(F->getName())
+ .Case("__gnat_eh_personality", GNU_Ada_Personality)
+ .Case("__gxx_personality_v0", GNU_CXX_Personality)
+ .Default(Unknown_Personality);
+}
+
+/// isCatchAll - Return 'true' if the given typeinfo will match anything.
+static bool isCatchAll(Personality_Type Personality, Constant *TypeInfo) {
+ switch (Personality) {
+ case Unknown_Personality:
+ return false;
+ case GNU_Ada_Personality:
+ // While __gnat_all_others_value will match any Ada exception, it doesn't
+ // match foreign exceptions (or didn't, before gcc-4.7).
+ return false;
+ case GNU_CXX_Personality:
+ return TypeInfo->isNullValue();
+ }
+ llvm_unreachable("Unknown personality!");
+}
+
+static bool shorter_filter(const Value *LHS, const Value *RHS) {
+ return
+ cast<ArrayType>(LHS->getType())->getNumElements()
+ <
+ cast<ArrayType>(RHS->getType())->getNumElements();
+}
+
+Instruction *InstCombiner::visitLandingPadInst(LandingPadInst &LI) {
+ // The logic here should be correct for any real-world personality function.
+ // However if that turns out not to be true, the offending logic can always
+ // be conditioned on the personality function, like the catch-all logic is.
+ Personality_Type Personality = RecognizePersonality(LI.getPersonalityFn());
+
+ // Simplify the list of clauses, eg by removing repeated catch clauses
+ // (these are often created by inlining).
+ bool MakeNewInstruction = false; // If true, recreate using the following:
+ SmallVector<Value *, 16> NewClauses; // - Clauses for the new instruction;
+ bool CleanupFlag = LI.isCleanup(); // - The new instruction is a cleanup.
+
+ SmallPtrSet<Value *, 16> AlreadyCaught; // Typeinfos known caught already.
+ for (unsigned i = 0, e = LI.getNumClauses(); i != e; ++i) {
+ bool isLastClause = i + 1 == e;
+ if (LI.isCatch(i)) {
+ // A catch clause.
+ Value *CatchClause = LI.getClause(i);
+ Constant *TypeInfo = cast<Constant>(CatchClause->stripPointerCasts());
+
+ // If we already saw this clause, there is no point in having a second
+ // copy of it.
+ if (AlreadyCaught.insert(TypeInfo)) {
+ // This catch clause was not already seen.
+ NewClauses.push_back(CatchClause);
+ } else {
+ // Repeated catch clause - drop the redundant copy.
+ MakeNewInstruction = true;
+ }
+
+ // If this is a catch-all then there is no point in keeping any following
+ // clauses or marking the landingpad as having a cleanup.
+ if (isCatchAll(Personality, TypeInfo)) {
+ if (!isLastClause)
+ MakeNewInstruction = true;
+ CleanupFlag = false;
+ break;
+ }
+ } else {
+ // A filter clause. If any of the filter elements were already caught
+ // then they can be dropped from the filter. It is tempting to try to
+ // exploit the filter further by saying that any typeinfo that does not
+ // occur in the filter can't be caught later (and thus can be dropped).
+ // However this would be wrong, since typeinfos can match without being
+ // equal (for example if one represents a C++ class, and the other some
+ // class derived from it).
+ assert(LI.isFilter(i) && "Unsupported landingpad clause!");
+ Value *FilterClause = LI.getClause(i);
+ ArrayType *FilterType = cast<ArrayType>(FilterClause->getType());
+ unsigned NumTypeInfos = FilterType->getNumElements();
+
+ // An empty filter catches everything, so there is no point in keeping any
+ // following clauses or marking the landingpad as having a cleanup. By
+ // dealing with this case here the following code is made a bit simpler.
+ if (!NumTypeInfos) {
+ NewClauses.push_back(FilterClause);
+ if (!isLastClause)
+ MakeNewInstruction = true;
+ CleanupFlag = false;
+ break;
+ }
+
+ bool MakeNewFilter = false; // If true, make a new filter.
+ SmallVector<Constant *, 16> NewFilterElts; // New elements.
+ if (isa<ConstantAggregateZero>(FilterClause)) {
+ // Not an empty filter - it contains at least one null typeinfo.
+ assert(NumTypeInfos > 0 && "Should have handled empty filter already!");
+ Constant *TypeInfo =
+ Constant::getNullValue(FilterType->getElementType());
+ // If this typeinfo is a catch-all then the filter can never match.
+ if (isCatchAll(Personality, TypeInfo)) {
+ // Throw the filter away.
+ MakeNewInstruction = true;
+ continue;
+ }
+
+ // There is no point in having multiple copies of this typeinfo, so
+ // discard all but the first copy if there is more than one.
+ NewFilterElts.push_back(TypeInfo);
+ if (NumTypeInfos > 1)
+ MakeNewFilter = true;
+ } else {
+ ConstantArray *Filter = cast<ConstantArray>(FilterClause);
+ SmallPtrSet<Value *, 16> SeenInFilter; // For uniquing the elements.
+ NewFilterElts.reserve(NumTypeInfos);
+
+ // Remove any filter elements that were already caught or that already
+ // occurred in the filter. While there, see if any of the elements are
+ // catch-alls. If so, the filter can be discarded.
+ bool SawCatchAll = false;
+ for (unsigned j = 0; j != NumTypeInfos; ++j) {
+ Value *Elt = Filter->getOperand(j);
+ Constant *TypeInfo = cast<Constant>(Elt->stripPointerCasts());
+ if (isCatchAll(Personality, TypeInfo)) {
+ // This element is a catch-all. Bail out, noting this fact.
+ SawCatchAll = true;
+ break;
+ }
+ if (AlreadyCaught.count(TypeInfo))
+ // Already caught by an earlier clause, so having it in the filter
+ // is pointless.
+ continue;
+ // There is no point in having multiple copies of the same typeinfo in
+ // a filter, so only add it if we didn't already.
+ if (SeenInFilter.insert(TypeInfo))
+ NewFilterElts.push_back(cast<Constant>(Elt));
+ }
+ // A filter containing a catch-all cannot match anything by definition.
+ if (SawCatchAll) {
+ // Throw the filter away.
+ MakeNewInstruction = true;
+ continue;
+ }
+
+ // If we dropped something from the filter, make a new one.
+ if (NewFilterElts.size() < NumTypeInfos)
+ MakeNewFilter = true;
+ }
+ if (MakeNewFilter) {
+ FilterType = ArrayType::get(FilterType->getElementType(),
+ NewFilterElts.size());
+ FilterClause = ConstantArray::get(FilterType, NewFilterElts);
+ MakeNewInstruction = true;
+ }
+
+ NewClauses.push_back(FilterClause);
+
+ // If the new filter is empty then it will catch everything so there is
+ // no point in keeping any following clauses or marking the landingpad
+ // as having a cleanup. The case of the original filter being empty was
+ // already handled above.
+ if (MakeNewFilter && !NewFilterElts.size()) {
+ assert(MakeNewInstruction && "New filter but not a new instruction!");
+ CleanupFlag = false;
+ break;
+ }
+ }
+ }
+
+ // If several filters occur in a row then reorder them so that the shortest
+ // filters come first (those with the smallest number of elements). This is
+ // advantageous because shorter filters are more likely to match, speeding up
+ // unwinding, but mostly because it increases the effectiveness of the other
+ // filter optimizations below.
+ for (unsigned i = 0, e = NewClauses.size(); i + 1 < e; ) {
+ unsigned j;
+ // Find the maximal 'j' s.t. the range [i, j) consists entirely of filters.
+ for (j = i; j != e; ++j)
+ if (!isa<ArrayType>(NewClauses[j]->getType()))
+ break;
+
+ // Check whether the filters are already sorted by length. We need to know
+ // if sorting them is actually going to do anything so that we only make a
+ // new landingpad instruction if it does.
+ for (unsigned k = i; k + 1 < j; ++k)
+ if (shorter_filter(NewClauses[k+1], NewClauses[k])) {
+ // Not sorted, so sort the filters now. Doing an unstable sort would be
+ // correct too but reordering filters pointlessly might confuse users.
+ std::stable_sort(NewClauses.begin() + i, NewClauses.begin() + j,
+ shorter_filter);
+ MakeNewInstruction = true;
+ break;
+ }
+
+ // Look for the next batch of filters.
+ i = j + 1;
+ }
+
+ // If typeinfos matched if and only if equal, then the elements of a filter L
+ // that occurs later than a filter F could be replaced by the intersection of
+ // the elements of F and L. In reality two typeinfos can match without being
+ // equal (for example if one represents a C++ class, and the other some class
+ // derived from it) so it would be wrong to perform this transform in general.
+ // However the transform is correct and useful if F is a subset of L. In that
+ // case L can be replaced by F, and thus removed altogether since repeating a
+ // filter is pointless. So here we look at all pairs of filters F and L where
+ // L follows F in the list of clauses, and remove L if every element of F is
+ // an element of L. This can occur when inlining C++ functions with exception
+ // specifications.
+ for (unsigned i = 0; i + 1 < NewClauses.size(); ++i) {
+ // Examine each filter in turn.
+ Value *Filter = NewClauses[i];
+ ArrayType *FTy = dyn_cast<ArrayType>(Filter->getType());
+ if (!FTy)
+ // Not a filter - skip it.
+ continue;
+ unsigned FElts = FTy->getNumElements();
+ // Examine each filter following this one. Doing this backwards means that
+ // we don't have to worry about filters disappearing under us when removed.
+ for (unsigned j = NewClauses.size() - 1; j != i; --j) {
+ Value *LFilter = NewClauses[j];
+ ArrayType *LTy = dyn_cast<ArrayType>(LFilter->getType());
+ if (!LTy)
+ // Not a filter - skip it.
+ continue;
+ // If Filter is a subset of LFilter, i.e. every element of Filter is also
+ // an element of LFilter, then discard LFilter.
+ SmallVector<Value *, 16>::iterator J = NewClauses.begin() + j;
+ // If Filter is empty then it is a subset of LFilter.
+ if (!FElts) {
+ // Discard LFilter.
+ NewClauses.erase(J);
+ MakeNewInstruction = true;
+ // Move on to the next filter.
+ continue;
+ }
+ unsigned LElts = LTy->getNumElements();
+ // If Filter is longer than LFilter then it cannot be a subset of it.
+ if (FElts > LElts)
+ // Move on to the next filter.
+ continue;
+ // At this point we know that LFilter has at least one element.
+ if (isa<ConstantAggregateZero>(LFilter)) { // LFilter only contains zeros.
+ // Filter is a subset of LFilter iff Filter contains only zeros (as we
+ // already know that Filter is not longer than LFilter).
+ if (isa<ConstantAggregateZero>(Filter)) {
+ assert(FElts <= LElts && "Should have handled this case earlier!");
+ // Discard LFilter.
+ NewClauses.erase(J);
+ MakeNewInstruction = true;
+ }
+ // Move on to the next filter.
+ continue;
+ }
+ ConstantArray *LArray = cast<ConstantArray>(LFilter);
+ if (isa<ConstantAggregateZero>(Filter)) { // Filter only contains zeros.
+ // Since Filter is non-empty and contains only zeros, it is a subset of
+ // LFilter iff LFilter contains a zero.
+ assert(FElts > 0 && "Should have eliminated the empty filter earlier!");
+ for (unsigned l = 0; l != LElts; ++l)
+ if (LArray->getOperand(l)->isNullValue()) {
+ // LFilter contains a zero - discard it.
+ NewClauses.erase(J);
+ MakeNewInstruction = true;
+ break;
+ }
+ // Move on to the next filter.
+ continue;
+ }
+ // At this point we know that both filters are ConstantArrays. Loop over
+ // operands to see whether every element of Filter is also an element of
+ // LFilter. Since filters tend to be short this is probably faster than
+ // using a method that scales nicely.
+ ConstantArray *FArray = cast<ConstantArray>(Filter);
+ bool AllFound = true;
+ for (unsigned f = 0; f != FElts; ++f) {
+ Value *FTypeInfo = FArray->getOperand(f)->stripPointerCasts();
+ AllFound = false;
+ for (unsigned l = 0; l != LElts; ++l) {
+ Value *LTypeInfo = LArray->getOperand(l)->stripPointerCasts();
+ if (LTypeInfo == FTypeInfo) {
+ AllFound = true;
+ break;
+ }
+ }
+ if (!AllFound)
+ break;
+ }
+ if (AllFound) {
+ // Discard LFilter.
+ NewClauses.erase(J);
+ MakeNewInstruction = true;
+ }
+ // Move on to the next filter.
+ }
+ }
+
+ // If we changed any of the clauses, replace the old landingpad instruction
+ // with a new one.
+ if (MakeNewInstruction) {
+ LandingPadInst *NLI = LandingPadInst::Create(LI.getType(),
+ LI.getPersonalityFn(),
+ NewClauses.size());
+ for (unsigned i = 0, e = NewClauses.size(); i != e; ++i)
+ NLI->addClause(NewClauses[i]);
+ // A landing pad with no clauses must have the cleanup flag set. It is
+ // theoretically possible, though highly unlikely, that we eliminated all
+ // clauses. If so, force the cleanup flag to true.
+ if (NewClauses.empty())
+ CleanupFlag = true;
+ NLI->setCleanup(CleanupFlag);
+ return NLI;
+ }
+
+ // Even if none of the clauses changed, we may nonetheless have understood
+ // that the cleanup flag is pointless. Clear it if so.
+ if (LI.isCleanup() != CleanupFlag) {
+ assert(!CleanupFlag && "Adding a cleanup, not removing one?!");
+ LI.setCleanup(CleanupFlag);
+ return &LI;
+ }
+
+ return 0;
+}
+
@@ -1350,7 +1758,8 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) {
assert(I->hasOneUse() && "Invariants didn't hold!");
// Cannot move control-flow-involving, volatile loads, vaarg, etc.
- if (isa<PHINode>(I) || I->mayHaveSideEffects() || isa<TerminatorInst>(I))
+ if (isa<PHINode>(I) || isa<LandingPadInst>(I) || I->mayHaveSideEffects() ||
+ isa<TerminatorInst>(I))
return false;
// Do not sink alloca instructions out of the entry block.
@@ -1367,8 +1776,7 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) {
return false;
}
- BasicBlock::iterator InsertPos = DestBlock->getFirstNonPHI();
-
+ BasicBlock::iterator InsertPos = DestBlock->getFirstInsertionPt();
I->moveBefore(InsertPos);
++NumSunkInst;
return true;
@@ -1503,27 +1911,29 @@ bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) {
// Do a quick scan over the function. If we find any blocks that are
// unreachable, remove any instructions inside of them. This prevents
// the instcombine code from having to deal with some bad special cases.
- for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
- if (!Visited.count(BB)) {
- Instruction *Term = BB->getTerminator();
- while (Term != BB->begin()) { // Remove instrs bottom-up
- BasicBlock::iterator I = Term; --I;
-
- DEBUG(errs() << "IC: DCE: " << *I << '\n');
- // A debug intrinsic shouldn't force another iteration if we weren't
- // going to do one without it.
- if (!isa<DbgInfoIntrinsic>(I)) {
- ++NumDeadInst;
- MadeIRChange = true;
- }
-
- // If I is not void type then replaceAllUsesWith undef.
- // This allows ValueHandlers and custom metadata to adjust itself.
- if (!I->getType()->isVoidTy())
- I->replaceAllUsesWith(UndefValue::get(I->getType()));
- I->eraseFromParent();
+ for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
+ if (Visited.count(BB)) continue;
+
+ // Delete the instructions backwards, as it has a reduced likelihood of
+ // having to update as many def-use and use-def chains.
+ Instruction *EndInst = BB->getTerminator(); // Last not to be deleted.
+ while (EndInst != BB->begin()) {
+ // Delete the next to last instruction.
+ BasicBlock::iterator I = EndInst;
+ Instruction *Inst = --I;
+ if (!Inst->use_empty())
+ Inst->replaceAllUsesWith(UndefValue::get(Inst->getType()));
+ if (isa<LandingPadInst>(Inst)) {
+ EndInst = Inst;
+ continue;
}
+ if (!isa<DbgInfoIntrinsic>(Inst)) {
+ ++NumDeadInst;
+ MadeIRChange = true;
+ }
+ Inst->eraseFromParent();
}
+ }
}
while (!Worklist.isEmpty()) {
@@ -1604,13 +2014,13 @@ bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) {
// Everything uses the new instruction now.
I->replaceAllUsesWith(Result);
+ // Move the name to the new instruction first.
+ Result->takeName(I);
+
// Push the new instruction and any users onto the worklist.
Worklist.Add(Result);
Worklist.AddUsersToWorkList(*Result);
- // Move the name to the new instruction first.
- Result->takeName(I);
-
// Insert the new instruction into the basic block...
BasicBlock *InstParent = I->getParent();
BasicBlock::iterator InsertPos = I;
diff --git a/lib/Transforms/Instrumentation/CMakeLists.txt b/lib/Transforms/Instrumentation/CMakeLists.txt
index 5700ac8..7b3a927a 100644
--- a/lib/Transforms/Instrumentation/CMakeLists.txt
+++ b/lib/Transforms/Instrumentation/CMakeLists.txt
@@ -6,3 +6,10 @@ add_llvm_library(LLVMInstrumentation
PathProfiling.cpp
ProfilingUtils.cpp
)
+
+add_llvm_library_dependencies(LLVMInstrumentation
+ LLVMAnalysis
+ LLVMCore
+ LLVMSupport
+ LLVMTransformUtils
+ )
diff --git a/lib/Transforms/Instrumentation/EdgeProfiling.cpp b/lib/Transforms/Instrumentation/EdgeProfiling.cpp
index 1d31fcc..e8ef265 100644
--- a/lib/Transforms/Instrumentation/EdgeProfiling.cpp
+++ b/lib/Transforms/Instrumentation/EdgeProfiling.cpp
@@ -74,7 +74,7 @@ bool EdgeProfiler::runOnModule(Module &M) {
}
}
- const Type *ATy = ArrayType::get(Type::getInt32Ty(M.getContext()), NumEdges);
+ Type *ATy = ArrayType::get(Type::getInt32Ty(M.getContext()), NumEdges);
GlobalVariable *Counters =
new GlobalVariable(M, ATy, false, GlobalValue::InternalLinkage,
Constant::getNullValue(ATy), "EdgeProfCounters");
diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index 3f2c412..ccf7e11 100644
--- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -60,11 +60,11 @@ namespace {
bool runOnModule(Module &M);
// Create the GCNO files for the Module based on DebugInfo.
- void emitGCNO(DebugInfoFinder &DIF);
+ void emitGCNO();
// Modify the program to track transitions along edges and call into the
// profiling runtime to emit .gcda files when run.
- bool emitProfileArcs(DebugInfoFinder &DIF);
+ bool emitProfileArcs();
// Get pointers to the functions in the runtime library.
Constant *getStartFileFunc();
@@ -86,8 +86,7 @@ namespace {
// Add the function to write out all our counters to the global destructor
// list.
- void insertCounterWriteout(DebugInfoFinder &,
- SmallVector<std::pair<GlobalVariable *,
+ void insertCounterWriteout(SmallVector<std::pair<GlobalVariable *,
MDNode *>, 8> &);
std::string mangleName(DICompileUnit CU, std::string NewStem);
@@ -110,15 +109,6 @@ ModulePass *llvm::createGCOVProfilerPass(bool EmitNotes, bool EmitData,
return new GCOVProfiler(EmitNotes, EmitData, Use402Format);
}
-static DISubprogram findSubprogram(DIScope Scope) {
- while (!Scope.isSubprogram()) {
- assert(Scope.isLexicalBlock() &&
- "Debug location not lexical block or subprogram");
- Scope = DILexicalBlock(Scope).getContext();
- }
- return DISubprogram(Scope);
-}
-
namespace {
class GCOVRecord {
protected:
@@ -177,18 +167,24 @@ namespace {
}
uint32_t length() {
+ // Here 2 = 1 for string lenght + 1 for '0' id#.
return lengthOfGCOVString(Filename) + 2 + Lines.size();
}
- private:
- friend class GCOVBlock;
+ void writeOut() {
+ write(0);
+ writeGCOVString(Filename);
+ for (int i = 0, e = Lines.size(); i != e; ++i)
+ write(Lines[i]);
+ }
- GCOVLines(std::string Filename, raw_ostream *os)
- : Filename(Filename) {
+ GCOVLines(StringRef F, raw_ostream *os)
+ : Filename(F) {
this->os = os;
}
- std::string Filename;
+ private:
+ StringRef Filename;
SmallVector<uint32_t, 32> Lines;
};
@@ -197,7 +193,7 @@ namespace {
// other blocks.
class GCOVBlock : public GCOVRecord {
public:
- GCOVLines &getFile(std::string Filename) {
+ GCOVLines &getFile(StringRef Filename) {
GCOVLines *&Lines = LinesByFile[Filename];
if (!Lines) {
Lines = new GCOVLines(Filename, os);
@@ -220,13 +216,8 @@ namespace {
write(Len);
write(Number);
for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(),
- E = LinesByFile.end(); I != E; ++I) {
- write(0);
- writeGCOVString(I->second->Filename);
- for (int i = 0, e = I->second->Lines.size(); i != e; ++i) {
- write(I->second->Lines[i]);
- }
- }
+ E = LinesByFile.end(); I != E; ++I)
+ I->second->writeOut();
write(0);
write(0);
}
@@ -353,66 +344,66 @@ bool GCOVProfiler::runOnModule(Module &M) {
this->M = &M;
Ctx = &M.getContext();
- DebugInfoFinder DIF;
- DIF.processModule(M);
-
- if (EmitNotes) emitGCNO(DIF);
- if (EmitData) return emitProfileArcs(DIF);
+ if (EmitNotes) emitGCNO();
+ if (EmitData) return emitProfileArcs();
return false;
}
-void GCOVProfiler::emitGCNO(DebugInfoFinder &DIF) {
+void GCOVProfiler::emitGCNO() {
DenseMap<const MDNode *, raw_fd_ostream *> GcnoFiles;
- for (DebugInfoFinder::iterator I = DIF.compile_unit_begin(),
- E = DIF.compile_unit_end(); I != E; ++I) {
- // Each compile unit gets its own .gcno file. This means that whether we run
- // this pass over the original .o's as they're produced, or run it after
- // LTO, we'll generate the same .gcno files.
-
- DICompileUnit CU(*I);
- raw_fd_ostream *&out = GcnoFiles[CU];
- std::string ErrorInfo;
- out = new raw_fd_ostream(mangleName(CU, "gcno").c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary);
- if (!Use402Format)
- out->write("oncg*404MVLL", 12);
- else
- out->write("oncg*402MVLL", 12);
- }
-
- for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(),
- SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) {
- DISubprogram SP(*SPI);
- raw_fd_ostream *&os = GcnoFiles[SP.getCompileUnit()];
-
- Function *F = SP.getFunction();
- if (!F) continue;
- GCOVFunction Func(SP, os, Use402Format);
-
- for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
- GCOVBlock &Block = Func.getBlock(BB);
- TerminatorInst *TI = BB->getTerminator();
- if (int successors = TI->getNumSuccessors()) {
- for (int i = 0; i != successors; ++i) {
- Block.addEdge(Func.getBlock(TI->getSuccessor(i)));
+ NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
+ if (CU_Nodes) {
+ for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
+ // Each compile unit gets its own .gcno file. This means that whether we run
+ // this pass over the original .o's as they're produced, or run it after
+ // LTO, we'll generate the same .gcno files.
+
+ DICompileUnit CU(CU_Nodes->getOperand(i));
+ raw_fd_ostream *&out = GcnoFiles[CU];
+ std::string ErrorInfo;
+ out = new raw_fd_ostream(mangleName(CU, "gcno").c_str(), ErrorInfo,
+ raw_fd_ostream::F_Binary);
+ if (!Use402Format)
+ out->write("oncg*404MVLL", 12);
+ else
+ out->write("oncg*204MVLL", 12);
+
+ DIArray SPs = CU.getSubprograms();
+ for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
+ DISubprogram SP(SPs.getElement(i));
+ if (!SP.Verify()) continue;
+ raw_fd_ostream *&os = GcnoFiles[CU];
+
+ Function *F = SP.getFunction();
+ if (!F) continue;
+ GCOVFunction Func(SP, os, Use402Format);
+
+ for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
+ GCOVBlock &Block = Func.getBlock(BB);
+ TerminatorInst *TI = BB->getTerminator();
+ if (int successors = TI->getNumSuccessors()) {
+ for (int i = 0; i != successors; ++i) {
+ Block.addEdge(Func.getBlock(TI->getSuccessor(i)));
+ }
+ } else if (isa<ReturnInst>(TI)) {
+ Block.addEdge(Func.getReturnBlock());
+ }
+
+ uint32_t Line = 0;
+ for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); I != IE; ++I) {
+ const DebugLoc &Loc = I->getDebugLoc();
+ if (Loc.isUnknown()) continue;
+ if (Line == Loc.getLine()) continue;
+ Line = Loc.getLine();
+ if (SP != getDISubprogram(Loc.getScope(*Ctx))) continue;
+
+ GCOVLines &Lines = Block.getFile(SP.getFilename());
+ Lines.addLine(Loc.getLine());
+ }
}
- } else if (isa<ReturnInst>(TI)) {
- Block.addEdge(Func.getReturnBlock());
- }
-
- uint32_t Line = 0;
- for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); I != IE; ++I) {
- const DebugLoc &Loc = I->getDebugLoc();
- if (Loc.isUnknown()) continue;
- if (Line == Loc.getLine()) continue;
- Line = Loc.getLine();
- if (SP != findSubprogram(DIScope(Loc.getScope(*Ctx)))) continue;
-
- GCOVLines &Lines = Block.getFile(SP.getFilename());
- Lines.addLine(Loc.getLine());
+ Func.writeOut();
}
}
- Func.writeOut();
}
for (DenseMap<const MDNode *, raw_fd_ostream *>::iterator
@@ -424,103 +415,107 @@ void GCOVProfiler::emitGCNO(DebugInfoFinder &DIF) {
}
}
-bool GCOVProfiler::emitProfileArcs(DebugInfoFinder &DIF) {
- if (DIF.subprogram_begin() == DIF.subprogram_end())
- return false;
-
- SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP;
- for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(),
- SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) {
- DISubprogram SP(*SPI);
- Function *F = SP.getFunction();
- if (!F) continue;
-
- unsigned Edges = 0;
- for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
- TerminatorInst *TI = BB->getTerminator();
- if (isa<ReturnInst>(TI))
- ++Edges;
- else
- Edges += TI->getNumSuccessors();
- }
-
- const ArrayType *CounterTy =
+bool GCOVProfiler::emitProfileArcs() {
+ NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
+ if (!CU_Nodes) return false;
+
+ bool Result = false;
+ for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
+ DICompileUnit CU(CU_Nodes->getOperand(i));
+ DIArray SPs = CU.getSubprograms();
+ SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP;
+ for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
+ DISubprogram SP(SPs.getElement(i));
+ if (!SP.Verify()) continue;
+ Function *F = SP.getFunction();
+ if (!F) continue;
+ if (!Result) Result = true;
+ unsigned Edges = 0;
+ for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
+ TerminatorInst *TI = BB->getTerminator();
+ if (isa<ReturnInst>(TI))
+ ++Edges;
+ else
+ Edges += TI->getNumSuccessors();
+ }
+
+ ArrayType *CounterTy =
ArrayType::get(Type::getInt64Ty(*Ctx), Edges);
- GlobalVariable *Counters =
+ GlobalVariable *Counters =
new GlobalVariable(*M, CounterTy, false,
GlobalValue::InternalLinkage,
Constant::getNullValue(CounterTy),
"__llvm_gcov_ctr", 0, false, 0);
- CountersBySP.push_back(std::make_pair(Counters, (MDNode*)SP));
-
- UniqueVector<BasicBlock *> ComplexEdgePreds;
- UniqueVector<BasicBlock *> ComplexEdgeSuccs;
-
- unsigned Edge = 0;
- for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
- TerminatorInst *TI = BB->getTerminator();
- int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors();
- if (Successors) {
- IRBuilder<> Builder(TI);
-
- if (Successors == 1) {
- Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
- Edge);
- Value *Count = Builder.CreateLoad(Counter);
- Count = Builder.CreateAdd(Count,
- ConstantInt::get(Type::getInt64Ty(*Ctx),1));
- Builder.CreateStore(Count, Counter);
- } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
- Value *Sel = Builder.CreateSelect(
+ CountersBySP.push_back(std::make_pair(Counters, (MDNode*)SP));
+
+ UniqueVector<BasicBlock *> ComplexEdgePreds;
+ UniqueVector<BasicBlock *> ComplexEdgeSuccs;
+
+ unsigned Edge = 0;
+ for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
+ TerminatorInst *TI = BB->getTerminator();
+ int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors();
+ if (Successors) {
+ IRBuilder<> Builder(TI);
+
+ if (Successors == 1) {
+ Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
+ Edge);
+ Value *Count = Builder.CreateLoad(Counter);
+ Count = Builder.CreateAdd(Count,
+ ConstantInt::get(Type::getInt64Ty(*Ctx),1));
+ Builder.CreateStore(Count, Counter);
+ } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
+ Value *Sel = Builder.CreateSelect(
BI->getCondition(),
ConstantInt::get(Type::getInt64Ty(*Ctx), Edge),
ConstantInt::get(Type::getInt64Ty(*Ctx), Edge + 1));
- SmallVector<Value *, 2> Idx;
- Idx.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx)));
- Idx.push_back(Sel);
- Value *Counter = Builder.CreateInBoundsGEP(Counters,
- Idx.begin(), Idx.end());
- Value *Count = Builder.CreateLoad(Counter);
- Count = Builder.CreateAdd(Count,
- ConstantInt::get(Type::getInt64Ty(*Ctx),1));
- Builder.CreateStore(Count, Counter);
- } else {
- ComplexEdgePreds.insert(BB);
- for (int i = 0; i != Successors; ++i)
- ComplexEdgeSuccs.insert(TI->getSuccessor(i));
+ SmallVector<Value *, 2> Idx;
+ Idx.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx)));
+ Idx.push_back(Sel);
+ Value *Counter = Builder.CreateInBoundsGEP(Counters, Idx);
+ Value *Count = Builder.CreateLoad(Counter);
+ Count = Builder.CreateAdd(Count,
+ ConstantInt::get(Type::getInt64Ty(*Ctx),1));
+ Builder.CreateStore(Count, Counter);
+ } else {
+ ComplexEdgePreds.insert(BB);
+ for (int i = 0; i != Successors; ++i)
+ ComplexEdgeSuccs.insert(TI->getSuccessor(i));
+ }
+ Edge += Successors;
}
- Edge += Successors;
}
- }
-
- if (!ComplexEdgePreds.empty()) {
- GlobalVariable *EdgeTable =
+
+ if (!ComplexEdgePreds.empty()) {
+ GlobalVariable *EdgeTable =
buildEdgeLookupTable(F, Counters,
ComplexEdgePreds, ComplexEdgeSuccs);
- GlobalVariable *EdgeState = getEdgeStateValue();
-
- const Type *Int32Ty = Type::getInt32Ty(*Ctx);
- for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) {
- IRBuilder<> Builder(ComplexEdgePreds[i+1]->getTerminator());
- Builder.CreateStore(ConstantInt::get(Int32Ty, i), EdgeState);
- }
- for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) {
- // call runtime to perform increment
- IRBuilder<> Builder(ComplexEdgeSuccs[i+1]->getFirstNonPHI());
- Value *CounterPtrArray =
+ GlobalVariable *EdgeState = getEdgeStateValue();
+
+ Type *Int32Ty = Type::getInt32Ty(*Ctx);
+ for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) {
+ IRBuilder<> Builder(ComplexEdgePreds[i+1]->getTerminator());
+ Builder.CreateStore(ConstantInt::get(Int32Ty, i), EdgeState);
+ }
+ for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) {
+ // call runtime to perform increment
+ BasicBlock::iterator InsertPt =
+ ComplexEdgeSuccs[i+1]->getFirstInsertionPt();
+ IRBuilder<> Builder(InsertPt);
+ Value *CounterPtrArray =
Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0,
i * ComplexEdgePreds.size());
- Builder.CreateCall2(getIncrementIndirectCounterFunc(),
- EdgeState, CounterPtrArray);
- // clear the predecessor number
- Builder.CreateStore(ConstantInt::get(Int32Ty, 0xffffffff), EdgeState);
+ Builder.CreateCall2(getIncrementIndirectCounterFunc(),
+ EdgeState, CounterPtrArray);
+ // clear the predecessor number
+ Builder.CreateStore(ConstantInt::get(Int32Ty, 0xffffffff), EdgeState);
+ }
}
}
+ insertCounterWriteout(CountersBySP);
}
-
- insertCounterWriteout(DIF, CountersBySP);
-
- return true;
+ return Result;
}
// All edges with successors that aren't branches are "complex", because it
@@ -535,8 +530,8 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable(
// read it. Threads and invoke make this untrue.
// emit [(succs * preds) x i64*], logically [succ x [pred x i64*]].
- const Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx);
- const ArrayType *EdgeTableTy = ArrayType::get(
+ Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx);
+ ArrayType *EdgeTableTy = ArrayType::get(
Int64PtrTy, Succs.size() * Preds.size());
Constant **EdgeTable = new Constant*[Succs.size() * Preds.size()];
@@ -572,7 +567,7 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable(
}
Constant *GCOVProfiler::getStartFileFunc() {
- const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
Type::getInt8PtrTy(*Ctx), false);
return M->getOrInsertFunction("llvm_gcda_start_file", FTy);
}
@@ -582,7 +577,7 @@ Constant *GCOVProfiler::getIncrementIndirectCounterFunc() {
Type::getInt32PtrTy(*Ctx), // uint32_t *predecessor
Type::getInt64PtrTy(*Ctx)->getPointerTo(), // uint64_t **state_table_row
};
- const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
Args, false);
return M->getOrInsertFunction("llvm_gcda_increment_indirect_counter", FTy);
}
@@ -592,7 +587,7 @@ Constant *GCOVProfiler::getEmitFunctionFunc() {
Type::getInt32Ty(*Ctx), // uint32_t ident
Type::getInt8PtrTy(*Ctx), // const char *function_name
};
- const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
Args, false);
return M->getOrInsertFunction("llvm_gcda_emit_function", FTy);
}
@@ -602,13 +597,13 @@ Constant *GCOVProfiler::getEmitArcsFunc() {
Type::getInt32Ty(*Ctx), // uint32_t num_counters
Type::getInt64PtrTy(*Ctx), // uint64_t *counters
};
- const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
Args, false);
return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy);
}
Constant *GCOVProfiler::getEndFileFunc() {
- const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
return M->getOrInsertFunction("llvm_gcda_end_file", FTy);
}
@@ -626,9 +621,8 @@ GlobalVariable *GCOVProfiler::getEdgeStateValue() {
}
void GCOVProfiler::insertCounterWriteout(
- DebugInfoFinder &DIF,
SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> &CountersBySP) {
- const FunctionType *WriteoutFTy =
+ FunctionType *WriteoutFTy =
FunctionType::get(Type::getVoidTy(*Ctx), false);
Function *WriteoutF = Function::Create(WriteoutFTy,
GlobalValue::InternalLinkage,
@@ -642,29 +636,31 @@ void GCOVProfiler::insertCounterWriteout(
Constant *EmitArcs = getEmitArcsFunc();
Constant *EndFile = getEndFileFunc();
- for (DebugInfoFinder::iterator CUI = DIF.compile_unit_begin(),
- CUE = DIF.compile_unit_end(); CUI != CUE; ++CUI) {
- DICompileUnit compile_unit(*CUI);
- std::string FilenameGcda = mangleName(compile_unit, "gcda");
- Builder.CreateCall(StartFile,
- Builder.CreateGlobalStringPtr(FilenameGcda));
- for (SmallVector<std::pair<GlobalVariable *, MDNode *>, 8>::iterator
+ NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
+ if (CU_Nodes) {
+ for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
+ DICompileUnit compile_unit(CU_Nodes->getOperand(i));
+ std::string FilenameGcda = mangleName(compile_unit, "gcda");
+ Builder.CreateCall(StartFile,
+ Builder.CreateGlobalStringPtr(FilenameGcda));
+ for (SmallVector<std::pair<GlobalVariable *, MDNode *>, 8>::iterator
I = CountersBySP.begin(), E = CountersBySP.end();
- I != E; ++I) {
- DISubprogram SP(I->second);
- intptr_t ident = reinterpret_cast<intptr_t>(I->second);
- Builder.CreateCall2(EmitFunction,
- ConstantInt::get(Type::getInt32Ty(*Ctx), ident),
- Builder.CreateGlobalStringPtr(SP.getName()));
-
- GlobalVariable *GV = I->first;
- unsigned Arcs =
+ I != E; ++I) {
+ DISubprogram SP(I->second);
+ intptr_t ident = reinterpret_cast<intptr_t>(I->second);
+ Builder.CreateCall2(EmitFunction,
+ ConstantInt::get(Type::getInt32Ty(*Ctx), ident),
+ Builder.CreateGlobalStringPtr(SP.getName()));
+
+ GlobalVariable *GV = I->first;
+ unsigned Arcs =
cast<ArrayType>(GV->getType()->getElementType())->getNumElements();
- Builder.CreateCall2(EmitArcs,
- ConstantInt::get(Type::getInt32Ty(*Ctx), Arcs),
- Builder.CreateConstGEP2_64(GV, 0, 0));
+ Builder.CreateCall2(EmitArcs,
+ ConstantInt::get(Type::getInt32Ty(*Ctx), Arcs),
+ Builder.CreateConstGEP2_64(GV, 0, 0));
+ }
+ Builder.CreateCall(EndFile);
}
- Builder.CreateCall(EndFile);
}
Builder.CreateRetVoid();
diff --git a/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp b/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp
index e09f882..62c21b8 100644
--- a/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp
+++ b/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp
@@ -112,8 +112,8 @@ bool OptimalEdgeProfiler::runOnModule(Module &M) {
// be calculated from other edge counters on reading the profile info back
// in.
- const Type *Int32 = Type::getInt32Ty(M.getContext());
- const ArrayType *ATy = ArrayType::get(Int32, NumEdges);
+ Type *Int32 = Type::getInt32Ty(M.getContext());
+ ArrayType *ATy = ArrayType::get(Int32, NumEdges);
GlobalVariable *Counters =
new GlobalVariable(M, ATy, false, GlobalValue::InternalLinkage,
Constant::getNullValue(ATy), "OptEdgeProfCounters");
diff --git a/lib/Transforms/Instrumentation/PathProfiling.cpp b/lib/Transforms/Instrumentation/PathProfiling.cpp
index 7541663..23915d3 100644
--- a/lib/Transforms/Instrumentation/PathProfiling.cpp
+++ b/lib/Transforms/Instrumentation/PathProfiling.cpp
@@ -374,7 +374,7 @@ namespace llvm {
template<bool xcompile> class TypeBuilder<PathProfilingFunctionTable,
xcompile> {
public:
- static const StructType *get(LLVMContext& C) {
+ static StructType *get(LLVMContext& C) {
return( StructType::get(
TypeBuilder<types::i<32>, xcompile>::get(C), // type
TypeBuilder<types::i<32>, xcompile>::get(C), // array size
@@ -909,7 +909,7 @@ BasicBlock::iterator PathProfiler::getInsertionPoint(BasicBlock* block, Value*
pathNumber) {
if(pathNumber == NULL || isa<ConstantInt>(pathNumber)
|| (((Instruction*)(pathNumber))->getParent()) != block) {
- return(block->getFirstNonPHI());
+ return(block->getFirstInsertionPt());
} else {
Instruction* pathNumberInst = (Instruction*) (pathNumber);
BasicBlock::iterator insertPoint;
@@ -930,7 +930,7 @@ BasicBlock::iterator PathProfiler::getInsertionPoint(BasicBlock* block, Value*
// A PHINode is created in the node, and its values initialized to -1U.
void PathProfiler::preparePHI(BLInstrumentationNode* node) {
BasicBlock* block = node->getBlock();
- BasicBlock::iterator insertPoint = block->getFirstNonPHI();
+ BasicBlock::iterator insertPoint = block->getFirstInsertionPt();
pred_iterator PB = pred_begin(node->getBlock()),
PE = pred_end(node->getBlock());
PHINode* phi = PHINode::Create(Type::getInt32Ty(*Context),
@@ -999,7 +999,7 @@ void PathProfiler::insertNumberIncrement(BLInstrumentationNode* node,
BasicBlock::iterator insertPoint;
if( atBeginning )
- insertPoint = block->getFirstNonPHI();
+ insertPoint = block->getFirstInsertionPt();
else
insertPoint = block->getTerminator();
@@ -1029,8 +1029,7 @@ void PathProfiler::insertCounterIncrement(Value* incValue,
gepIndices[1] = incValue;
GetElementPtrInst* pcPointer =
- GetElementPtrInst::Create(dag->getCounterArray(),
- gepIndices.begin(), gepIndices.end(),
+ GetElementPtrInst::Create(dag->getCounterArray(), gepIndices,
"counterInc", insertPoint);
// Load from the array - call it oldPC
@@ -1140,7 +1139,7 @@ void PathProfiler::insertInstrumentationStartingAt(BLInstrumentationEdge* edge,
}
BasicBlock::iterator insertPoint = atBeginning ?
- instrumentNode->getBlock()->getFirstNonPHI() :
+ instrumentNode->getBlock()->getFirstInsertionPt() :
instrumentNode->getBlock()->getTerminator();
// add information from the bottom edge, if it exists
@@ -1172,7 +1171,7 @@ void PathProfiler::insertInstrumentationStartingAt(BLInstrumentationEdge* edge,
// Insert instrumentation if this is a normal edge
else {
BasicBlock::iterator insertPoint = atBeginning ?
- instrumentNode->getBlock()->getFirstNonPHI() :
+ instrumentNode->getBlock()->getFirstInsertionPt() :
instrumentNode->getBlock()->getTerminator();
if( edge->isInitialization() ) { // initialize path number
@@ -1233,7 +1232,7 @@ void PathProfiler::insertInstrumentation(
end = callEdges.end(); edge != end; edge++ ) {
BLInstrumentationNode* node =
(BLInstrumentationNode*)(*edge)->getSource();
- BasicBlock::iterator insertPoint = node->getBlock()->getFirstNonPHI();
+ BasicBlock::iterator insertPoint = node->getBlock()->getFirstInsertionPt();
// Find the first function call
while( ((Instruction&)(*insertPoint)).getOpcode() != Instruction::Call )
@@ -1289,7 +1288,7 @@ void PathProfiler::runOnFunction(std::vector<Constant*> &ftInit,
// Should we store the information in an array or hash
if( dag.getNumberOfPaths() <= HASH_THRESHHOLD ) {
- const Type* t = ArrayType::get(Type::getInt32Ty(*Context),
+ Type* t = ArrayType::get(Type::getInt32Ty(*Context),
dag.getNumberOfPaths());
dag.setCounterArray(new GlobalVariable(M, t, false,
@@ -1301,7 +1300,7 @@ void PathProfiler::runOnFunction(std::vector<Constant*> &ftInit,
// Add to global function reference table
unsigned type;
- const Type* voidPtr = TypeBuilder<types::i<8>*, true>::get(*Context);
+ Type* voidPtr = TypeBuilder<types::i<8>*, true>::get(*Context);
if( dag.getNumberOfPaths() <= HASH_THRESHHOLD )
type = ProfilingArray;
@@ -1315,7 +1314,7 @@ void PathProfiler::runOnFunction(std::vector<Constant*> &ftInit,
ConstantExpr::getBitCast(dag.getCounterArray(), voidPtr) :
Constant::getNullValue(voidPtr);
- const StructType* at = ftEntryTypeBuilder::get(*Context);
+ StructType* at = ftEntryTypeBuilder::get(*Context);
ConstantStruct* functionEntry =
(ConstantStruct*)ConstantStruct::get(at, entryArray);
ftInit.push_back(functionEntry);
@@ -1379,8 +1378,8 @@ bool PathProfiler::runOnModule(Module &M) {
runOnFunction(ftInit, *F, M);
}
- const Type *t = ftEntryTypeBuilder::get(*Context);
- const ArrayType* ftArrayType = ArrayType::get(t, ftInit.size());
+ Type *t = ftEntryTypeBuilder::get(*Context);
+ ArrayType* ftArrayType = ArrayType::get(t, ftInit.size());
Constant* ftInitConstant = ConstantArray::get(ftArrayType, ftInit);
DEBUG(dbgs() << " ftArrayType:" << *ftArrayType << "\n");
@@ -1388,7 +1387,7 @@ bool PathProfiler::runOnModule(Module &M) {
GlobalVariable* functionTable =
new GlobalVariable(M, ftArrayType, false, GlobalValue::InternalLinkage,
ftInitConstant, "functionPathTable");
- const Type *eltType = ftArrayType->getTypeAtIndex((unsigned)0);
+ Type *eltType = ftArrayType->getTypeAtIndex((unsigned)0);
InsertProfilingInitCall(Main, "llvm_start_path_profiling", functionTable,
PointerType::getUnqual(eltType));
diff --git a/lib/Transforms/Instrumentation/ProfilingUtils.cpp b/lib/Transforms/Instrumentation/ProfilingUtils.cpp
index 445a5b6..de57cd1 100644
--- a/lib/Transforms/Instrumentation/ProfilingUtils.cpp
+++ b/lib/Transforms/Instrumentation/ProfilingUtils.cpp
@@ -25,9 +25,9 @@ void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName,
GlobalValue *Array,
PointerType *arrayType) {
LLVMContext &Context = MainFn->getContext();
- const Type *ArgVTy =
+ Type *ArgVTy =
PointerType::getUnqual(Type::getInt8PtrTy(Context));
- const PointerType *UIntPtr = arrayType ? arrayType :
+ PointerType *UIntPtr = arrayType ? arrayType :
Type::getInt32PtrTy(Context);
Module &M = *MainFn->getParent();
Constant *InitFn = M.getOrInsertFunction(FnName, Type::getInt32Ty(Context),
@@ -51,8 +51,7 @@ void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName,
Constant::getNullValue(Type::getInt32Ty(Context)));
unsigned NumElements = 0;
if (Array) {
- Args[2] = ConstantExpr::getGetElementPtr(Array, &GEPIndices[0],
- GEPIndices.size());
+ Args[2] = ConstantExpr::getGetElementPtr(Array, GEPIndices);
NumElements =
cast<ArrayType>(Array->getType()->getElementType())->getNumElements();
} else {
@@ -108,7 +107,7 @@ void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName,
void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum,
GlobalValue *CounterArray, bool beginning) {
// Insert the increment after any alloca or PHI instructions...
- BasicBlock::iterator InsertPos = beginning ? BB->getFirstNonPHI() :
+ BasicBlock::iterator InsertPos = beginning ? BB->getFirstInsertionPt() :
BB->getTerminator();
while (isa<AllocaInst>(InsertPos))
++InsertPos;
@@ -120,7 +119,7 @@ void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum,
Indices[0] = Constant::getNullValue(Type::getInt32Ty(Context));
Indices[1] = ConstantInt::get(Type::getInt32Ty(Context), CounterNum);
Constant *ElementPtr =
- ConstantExpr::getGetElementPtr(CounterArray, &Indices[0], Indices.size());
+ ConstantExpr::getGetElementPtr(CounterArray, Indices);
// Load, increment and store the value back.
Value *OldVal = new LoadInst(ElementPtr, "OldFuncCounter", InsertPos);
@@ -137,7 +136,7 @@ void llvm::InsertProfilingShutdownCall(Function *Callee, Module *Mod) {
Type::getInt32Ty(Mod->getContext()),
FunctionType::get(Type::getVoidTy(Mod->getContext()), false)->getPointerTo()
};
- const StructType *GlobalDtorElemTy =
+ StructType *GlobalDtorElemTy =
StructType::get(Mod->getContext(), GlobalDtorElems, false);
// Construct the new element we'll be adding.
diff --git a/lib/Transforms/Scalar/ADCE.cpp b/lib/Transforms/Scalar/ADCE.cpp
index a5adb5e..ba214d1 100644
--- a/lib/Transforms/Scalar/ADCE.cpp
+++ b/lib/Transforms/Scalar/ADCE.cpp
@@ -57,6 +57,7 @@ bool ADCE::runOnFunction(Function& F) {
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
if (isa<TerminatorInst>(I.getInstructionIterator()) ||
isa<DbgInfoIntrinsic>(I.getInstructionIterator()) ||
+ isa<LandingPadInst>(I.getInstructionIterator()) ||
I->mayHaveSideEffects()) {
alive.insert(I.getInstructionIterator());
worklist.push_back(I.getInstructionIterator());
@@ -65,7 +66,6 @@ bool ADCE::runOnFunction(Function& F) {
// Propagate liveness backwards to operands.
while (!worklist.empty()) {
Instruction* curr = worklist.pop_back_val();
-
for (Instruction::op_iterator OI = curr->op_begin(), OE = curr->op_end();
OI != OE; ++OI)
if (Instruction* Inst = dyn_cast<Instruction>(OI))
diff --git a/lib/Transforms/Scalar/CMakeLists.txt b/lib/Transforms/Scalar/CMakeLists.txt
index c223da6..79bcae5 100644
--- a/lib/Transforms/Scalar/CMakeLists.txt
+++ b/lib/Transforms/Scalar/CMakeLists.txt
@@ -29,6 +29,14 @@ add_llvm_library(LLVMScalarOpts
SimplifyCFGPass.cpp
SimplifyLibCalls.cpp
Sink.cpp
- TailDuplication.cpp
TailRecursionElimination.cpp
)
+
+add_llvm_library_dependencies(LLVMScalarOpts
+ LLVMAnalysis
+ LLVMCore
+ LLVMInstCombine
+ LLVMSupport
+ LLVMTarget
+ LLVMTransformUtils
+ )
diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp
index 0af14ed..f8f18b2 100644
--- a/lib/Transforms/Scalar/CodeGenPrepare.cpp
+++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp
@@ -58,6 +58,7 @@ STATISTIC(NumMemoryInsts, "Number of memory instructions whose address "
STATISTIC(NumExtsMoved, "Number of [s|z]ext instructions combined with loads");
STATISTIC(NumExtUses, "Number of uses of [s|z]ext instructions optimized");
STATISTIC(NumRetsDup, "Number of return instructions duplicated");
+STATISTIC(NumDbgValueMoved, "Number of debug value instructions moved");
static cl::opt<bool> DisableBranchOpts(
"disable-cgp-branch-opts", cl::Hidden, cl::init(false),
@@ -104,12 +105,13 @@ namespace {
void EliminateMostlyEmptyBlock(BasicBlock *BB);
bool OptimizeBlock(BasicBlock &BB);
bool OptimizeInst(Instruction *I);
- bool OptimizeMemoryInst(Instruction *I, Value *Addr, const Type *AccessTy);
+ bool OptimizeMemoryInst(Instruction *I, Value *Addr, Type *AccessTy);
bool OptimizeInlineAsmInst(CallInst *CS);
bool OptimizeCallInst(CallInst *CI);
bool MoveExtToFormExtLoad(Instruction *I);
bool OptimizeExtUses(Instruction *I);
bool DupRetToEnableTailCallOpts(ReturnInst *RI);
+ bool PlaceDbgValues(Function &F);
};
}
@@ -132,6 +134,11 @@ bool CodeGenPrepare::runOnFunction(Function &F) {
// unconditional branch.
EverMadeChange |= EliminateMostlyEmptyBlocks(F);
+ // llvm.dbg.value is far away from the value then iSel may not be able
+ // handle it properly. iSel will drop llvm.dbg.value if it can not
+ // find a node corresponding to the value.
+ EverMadeChange |= PlaceDbgValues(F);
+
bool MadeChange = true;
while (MadeChange) {
MadeChange = false;
@@ -410,8 +417,7 @@ static bool OptimizeNoopCopyExpression(CastInst *CI, const TargetLowering &TLI){
CastInst *&InsertedCast = InsertedCasts[UserBB];
if (!InsertedCast) {
- BasicBlock::iterator InsertPt = UserBB->getFirstNonPHI();
-
+ BasicBlock::iterator InsertPt = UserBB->getFirstInsertionPt();
InsertedCast =
CastInst::Create(CI->getOpcode(), CI->getOperand(0), CI->getType(), "",
InsertPt);
@@ -467,8 +473,7 @@ static bool OptimizeCmpExpression(CmpInst *CI) {
CmpInst *&InsertedCmp = InsertedCmps[UserBB];
if (!InsertedCmp) {
- BasicBlock::iterator InsertPt = UserBB->getFirstNonPHI();
-
+ BasicBlock::iterator InsertPt = UserBB->getFirstInsertionPt();
InsertedCmp =
CmpInst::Create(CI->getOpcode(),
CI->getPredicate(), CI->getOperand(0),
@@ -528,7 +533,7 @@ bool CodeGenPrepare::OptimizeCallInst(CallInst *CI) {
IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI);
if (II && II->getIntrinsicID() == Intrinsic::objectsize) {
bool Min = (cast<ConstantInt>(II->getArgOperand(1))->getZExtValue() == 1);
- const Type *ReturnTy = CI->getType();
+ Type *ReturnTy = CI->getType();
Constant *RetVal = ConstantInt::get(ReturnTy, Min ? 0 : -1ULL);
// Substituting this can cause recursive simplifications, which can
@@ -551,22 +556,6 @@ bool CodeGenPrepare::OptimizeCallInst(CallInst *CI) {
// From here on out we're working with named functions.
if (CI->getCalledFunction() == 0) return false;
- // llvm.dbg.value is far away from the value then iSel may not be able
- // handle it properly. iSel will drop llvm.dbg.value if it can not
- // find a node corresponding to the value.
- if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(CI))
- if (Instruction *VI = dyn_cast_or_null<Instruction>(DVI->getValue()))
- if (!VI->isTerminator() &&
- (DVI->getParent() != VI->getParent() || DT->dominates(DVI, VI))) {
- DEBUG(dbgs() << "Moving Debug Value before :\n" << *DVI << ' ' << *VI);
- DVI->removeFromParent();
- if (isa<PHINode>(VI))
- DVI->insertBefore(VI->getParent()->getFirstNonPHI());
- else
- DVI->insertAfter(VI);
- return true;
- }
-
// We'll need TargetData from here on out.
const TargetData *TD = TLI ? TLI->getTargetData() : 0;
if (!TD) return false;
@@ -724,7 +713,7 @@ static bool IsNonLocalValue(Value *V, BasicBlock *BB) {
/// This method is used to optimize both load/store and inline asms with memory
/// operands.
bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
- const Type *AccessTy) {
+ Type *AccessTy) {
Value *Repl = Addr;
// Try to collapse single-value PHI nodes. This is necessary to undo
@@ -746,13 +735,11 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
worklist.pop_back();
// Break use-def graph loops.
- if (Visited.count(V)) {
+ if (!Visited.insert(V)) {
Consensus = 0;
break;
}
- Visited.insert(V);
-
// For a PHI node, push all of its incoming values.
if (PHINode *P = dyn_cast<PHINode>(V)) {
for (unsigned i = 0, e = P->getNumIncomingValues(); i != e; ++i)
@@ -763,7 +750,7 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
// For non-PHIs, determine the addressing mode being computed.
SmallVector<Instruction*, 16> NewAddrModeInsts;
ExtAddrMode NewAddrMode =
- AddressingModeMatcher::Match(V, AccessTy,MemoryInst,
+ AddressingModeMatcher::Match(V, AccessTy, MemoryInst,
NewAddrModeInsts, *TLI);
// This check is broken into two cases with very similar code to avoid using
@@ -822,7 +809,7 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
// Insert this computation right after this user. Since our caller is
// scanning from the top of the BB to the bottom, reuse of the expr are
// guaranteed to happen later.
- BasicBlock::iterator InsertPt = MemoryInst;
+ IRBuilder<> Builder(MemoryInst);
// Now that we determined the addressing expression we want to use and know
// that we have to sink it into this block. Check to see if we have already
@@ -833,11 +820,11 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
DEBUG(dbgs() << "CGP: Reusing nonlocal addrmode: " << AddrMode << " for "
<< *MemoryInst);
if (SunkAddr->getType() != Addr->getType())
- SunkAddr = new BitCastInst(SunkAddr, Addr->getType(), "tmp", InsertPt);
+ SunkAddr = Builder.CreateBitCast(SunkAddr, Addr->getType());
} else {
DEBUG(dbgs() << "CGP: SINKING nonlocal addrmode: " << AddrMode << " for "
<< *MemoryInst);
- const Type *IntPtrTy =
+ Type *IntPtrTy =
TLI->getTargetData()->getIntPtrType(AccessTy->getContext());
Value *Result = 0;
@@ -850,10 +837,9 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
if (AddrMode.BaseReg) {
Value *V = AddrMode.BaseReg;
if (V->getType()->isPointerTy())
- V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt);
+ V = Builder.CreatePtrToInt(V, IntPtrTy, "sunkaddr");
if (V->getType() != IntPtrTy)
- V = CastInst::CreateIntegerCast(V, IntPtrTy, /*isSigned=*/true,
- "sunkaddr", InsertPt);
+ V = Builder.CreateIntCast(V, IntPtrTy, /*isSigned=*/true, "sunkaddr");
Result = V;
}
@@ -863,29 +849,27 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
if (V->getType() == IntPtrTy) {
// done.
} else if (V->getType()->isPointerTy()) {
- V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt);
+ V = Builder.CreatePtrToInt(V, IntPtrTy, "sunkaddr");
} else if (cast<IntegerType>(IntPtrTy)->getBitWidth() <
cast<IntegerType>(V->getType())->getBitWidth()) {
- V = new TruncInst(V, IntPtrTy, "sunkaddr", InsertPt);
+ V = Builder.CreateTrunc(V, IntPtrTy, "sunkaddr");
} else {
- V = new SExtInst(V, IntPtrTy, "sunkaddr", InsertPt);
+ V = Builder.CreateSExt(V, IntPtrTy, "sunkaddr");
}
if (AddrMode.Scale != 1)
- V = BinaryOperator::CreateMul(V, ConstantInt::get(IntPtrTy,
- AddrMode.Scale),
- "sunkaddr", InsertPt);
+ V = Builder.CreateMul(V, ConstantInt::get(IntPtrTy, AddrMode.Scale),
+ "sunkaddr");
if (Result)
- Result = BinaryOperator::CreateAdd(Result, V, "sunkaddr", InsertPt);
+ Result = Builder.CreateAdd(Result, V, "sunkaddr");
else
Result = V;
}
// Add in the BaseGV if present.
if (AddrMode.BaseGV) {
- Value *V = new PtrToIntInst(AddrMode.BaseGV, IntPtrTy, "sunkaddr",
- InsertPt);
+ Value *V = Builder.CreatePtrToInt(AddrMode.BaseGV, IntPtrTy, "sunkaddr");
if (Result)
- Result = BinaryOperator::CreateAdd(Result, V, "sunkaddr", InsertPt);
+ Result = Builder.CreateAdd(Result, V, "sunkaddr");
else
Result = V;
}
@@ -894,7 +878,7 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
if (AddrMode.BaseOffs) {
Value *V = ConstantInt::get(IntPtrTy, AddrMode.BaseOffs);
if (Result)
- Result = BinaryOperator::CreateAdd(Result, V, "sunkaddr", InsertPt);
+ Result = Builder.CreateAdd(Result, V, "sunkaddr");
else
Result = V;
}
@@ -902,7 +886,7 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
if (Result == 0)
SunkAddr = Constant::getNullValue(Addr->getType());
else
- SunkAddr = new IntToPtrInst(Result, Addr->getType(), "sunkaddr",InsertPt);
+ SunkAddr = Builder.CreateIntToPtr(Result, Addr->getType(), "sunkaddr");
}
MemoryInst->replaceUsesOfWith(Repl, SunkAddr);
@@ -1059,8 +1043,7 @@ bool CodeGenPrepare::OptimizeExtUses(Instruction *I) {
Instruction *&InsertedTrunc = InsertedTruncs[UserBB];
if (!InsertedTrunc) {
- BasicBlock::iterator InsertPt = UserBB->getFirstNonPHI();
-
+ BasicBlock::iterator InsertPt = UserBB->getFirstInsertionPt();
InsertedTrunc = new TruncInst(I, Src->getType(), "", InsertPt);
}
@@ -1159,3 +1142,34 @@ bool CodeGenPrepare::OptimizeBlock(BasicBlock &BB) {
return MadeChange;
}
+
+// llvm.dbg.value is far away from the value then iSel may not be able
+// handle it properly. iSel will drop llvm.dbg.value if it can not
+// find a node corresponding to the value.
+bool CodeGenPrepare::PlaceDbgValues(Function &F) {
+ bool MadeChange = false;
+ for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
+ Instruction *PrevNonDbgInst = NULL;
+ for (BasicBlock::iterator BI = I->begin(), BE = I->end(); BI != BE;) {
+ Instruction *Insn = BI; ++BI;
+ DbgValueInst *DVI = dyn_cast<DbgValueInst>(Insn);
+ if (!DVI) {
+ PrevNonDbgInst = Insn;
+ continue;
+ }
+
+ Instruction *VI = dyn_cast_or_null<Instruction>(DVI->getValue());
+ if (VI && VI != PrevNonDbgInst && !VI->isTerminator()) {
+ DEBUG(dbgs() << "Moving Debug Value before :\n" << *DVI << ' ' << *VI);
+ DVI->removeFromParent();
+ if (isa<PHINode>(VI))
+ DVI->insertBefore(VI->getParent()->getFirstInsertionPt());
+ else
+ DVI->insertAfter(VI);
+ MadeChange = true;
+ ++NumDbgValueMoved;
+ }
+ }
+ }
+ return MadeChange;
+}
diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp
index cb9b5be..a593d0f 100644
--- a/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -52,18 +52,18 @@ namespace {
AA = &getAnalysis<AliasAnalysis>();
MD = &getAnalysis<MemoryDependenceAnalysis>();
DominatorTree &DT = getAnalysis<DominatorTree>();
-
+
bool Changed = false;
for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
// Only check non-dead blocks. Dead blocks may have strange pointer
// cycles that will confuse alias analysis.
if (DT.isReachableFromEntry(I))
Changed |= runOnBasicBlock(*I);
-
+
AA = 0; MD = 0;
return Changed;
}
-
+
bool runOnBasicBlock(BasicBlock &BB);
bool HandleFree(CallInst *F);
bool handleEndBlock(BasicBlock &BB);
@@ -105,34 +105,34 @@ static void DeleteDeadInstruction(Instruction *I,
MemoryDependenceAnalysis &MD,
SmallPtrSet<Value*, 16> *ValueSet = 0) {
SmallVector<Instruction*, 32> NowDeadInsts;
-
+
NowDeadInsts.push_back(I);
--NumFastOther;
-
+
// Before we touch this instruction, remove it from memdep!
do {
Instruction *DeadInst = NowDeadInsts.pop_back_val();
++NumFastOther;
-
+
// This instruction is dead, zap it, in stages. Start by removing it from
// MemDep, which needs to know the operands and needs it to be in the
// function.
MD.removeInstruction(DeadInst);
-
+
for (unsigned op = 0, e = DeadInst->getNumOperands(); op != e; ++op) {
Value *Op = DeadInst->getOperand(op);
DeadInst->setOperand(op, 0);
-
+
// If this operand just became dead, add it to the NowDeadInsts list.
if (!Op->use_empty()) continue;
-
+
if (Instruction *OpI = dyn_cast<Instruction>(Op))
if (isInstructionTriviallyDead(OpI))
NowDeadInsts.push_back(OpI);
}
-
+
DeadInst->eraseFromParent();
-
+
if (ValueSet) ValueSet->erase(DeadInst);
} while (!NowDeadInsts.empty());
}
@@ -159,11 +159,13 @@ static bool hasMemoryWrite(Instruction *I) {
}
/// getLocForWrite - Return a Location stored to by the specified instruction.
+/// If isRemovable returns true, this function and getLocForRead completely
+/// describe the memory operations for this instruction.
static AliasAnalysis::Location
getLocForWrite(Instruction *Inst, AliasAnalysis &AA) {
if (StoreInst *SI = dyn_cast<StoreInst>(Inst))
return AA.getLocation(SI);
-
+
if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(Inst)) {
// memcpy/memmove/memset.
AliasAnalysis::Location Loc = AA.getLocationForDest(MI);
@@ -174,10 +176,10 @@ getLocForWrite(Instruction *Inst, AliasAnalysis &AA) {
return AliasAnalysis::Location();
return Loc;
}
-
+
IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst);
if (II == 0) return AliasAnalysis::Location();
-
+
switch (II->getIntrinsicID()) {
default: return AliasAnalysis::Location(); // Unhandled intrinsic.
case Intrinsic::init_trampoline:
@@ -185,7 +187,7 @@ getLocForWrite(Instruction *Inst, AliasAnalysis &AA) {
// that we should use the size of the pointee type. This isn't valid for
// init.trampoline, which writes more than an i8.
if (AA.getTargetData() == 0) return AliasAnalysis::Location();
-
+
// FIXME: We don't know the size of the trampoline, so we can't really
// handle it here.
return AliasAnalysis::Location(II->getArgOperand(0));
@@ -198,10 +200,10 @@ getLocForWrite(Instruction *Inst, AliasAnalysis &AA) {
/// getLocForRead - Return the location read by the specified "hasMemoryWrite"
/// instruction if any.
-static AliasAnalysis::Location
+static AliasAnalysis::Location
getLocForRead(Instruction *Inst, AliasAnalysis &AA) {
assert(hasMemoryWrite(Inst) && "Unknown instruction case");
-
+
// The only instructions that both read and write are the mem transfer
// instructions (memcpy/memmove).
if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(Inst))
@@ -213,10 +215,10 @@ getLocForRead(Instruction *Inst, AliasAnalysis &AA) {
/// isRemovable - If the value of this instruction and the memory it writes to
/// is unused, may we delete this instruction?
static bool isRemovable(Instruction *I) {
- // Don't remove volatile stores.
+ // Don't remove volatile/atomic stores.
if (StoreInst *SI = dyn_cast<StoreInst>(I))
- return !SI->isVolatile();
-
+ return SI->isUnordered();
+
IntrinsicInst *II = cast<IntrinsicInst>(I);
switch (II->getIntrinsicID()) {
default: assert(0 && "doesn't pass 'hasMemoryWrite' predicate");
@@ -227,7 +229,7 @@ static bool isRemovable(Instruction *I) {
case Intrinsic::init_trampoline:
// Always safe to remove init_trampoline.
return true;
-
+
case Intrinsic::memset:
case Intrinsic::memmove:
case Intrinsic::memcpy:
@@ -255,16 +257,16 @@ static uint64_t getPointerSize(Value *V, AliasAnalysis &AA) {
const TargetData *TD = AA.getTargetData();
if (TD == 0)
return AliasAnalysis::UnknownSize;
-
+
if (AllocaInst *A = dyn_cast<AllocaInst>(V)) {
// Get size information for the alloca
if (ConstantInt *C = dyn_cast<ConstantInt>(A->getArraySize()))
return C->getZExtValue() * TD->getTypeAllocSize(A->getAllocatedType());
return AliasAnalysis::UnknownSize;
}
-
+
assert(isa<Argument>(V) && "Expected AllocaInst or Argument!");
- const PointerType *PT = cast<PointerType>(V->getType());
+ PointerType *PT = cast<PointerType>(V->getType());
return TD->getTypeAllocSize(PT->getElementType());
}
@@ -287,7 +289,7 @@ static bool isCompleteOverwrite(const AliasAnalysis::Location &Later,
AliasAnalysis &AA) {
const Value *P1 = Earlier.Ptr->stripPointerCasts();
const Value *P2 = Later.Ptr->stripPointerCasts();
-
+
// If the start pointers are the same, we just have to compare sizes to see if
// the later store was larger than the earlier store.
if (P1 == P2) {
@@ -302,33 +304,33 @@ static bool isCompleteOverwrite(const AliasAnalysis::Location &Later,
return Later.Ptr->getType() == Earlier.Ptr->getType();
return false;
}
-
+
// Make sure that the Later size is >= the Earlier size.
if (Later.Size < Earlier.Size)
return false;
return true;
}
-
+
// Otherwise, we have to have size information, and the later store has to be
// larger than the earlier one.
if (Later.Size == AliasAnalysis::UnknownSize ||
Earlier.Size == AliasAnalysis::UnknownSize ||
Later.Size <= Earlier.Size || AA.getTargetData() == 0)
return false;
-
+
// Check to see if the later store is to the entire object (either a global,
// an alloca, or a byval argument). If so, then it clearly overwrites any
// other store to the same object.
const TargetData &TD = *AA.getTargetData();
-
+
const Value *UO1 = GetUnderlyingObject(P1, &TD),
*UO2 = GetUnderlyingObject(P2, &TD);
-
+
// If we can't resolve the same pointers to the same object, then we can't
// analyze them at all.
if (UO1 != UO2)
return false;
-
+
// If the "Later" store is to a recognizable object, get its size.
if (isObjectPointerWithTrustworthySize(UO2)) {
uint64_t ObjectSize =
@@ -336,26 +338,26 @@ static bool isCompleteOverwrite(const AliasAnalysis::Location &Later,
if (ObjectSize == Later.Size)
return true;
}
-
+
// Okay, we have stores to two completely different pointers. Try to
// decompose the pointer into a "base + constant_offset" form. If the base
// pointers are equal, then we can reason about the two stores.
int64_t EarlierOff = 0, LaterOff = 0;
const Value *BP1 = GetPointerBaseWithConstantOffset(P1, EarlierOff, TD);
const Value *BP2 = GetPointerBaseWithConstantOffset(P2, LaterOff, TD);
-
+
// If the base pointers still differ, we have two completely different stores.
if (BP1 != BP2)
return false;
// The later store completely overlaps the earlier store if:
- //
+ //
// 1. Both start at the same offset and the later one's size is greater than
// or equal to the earlier one's, or
//
// |--earlier--|
// |-- later --|
- //
+ //
// 2. The earlier store has an offset greater than the later offset, but which
// still lies completely within the later store.
//
@@ -373,7 +375,7 @@ static bool isCompleteOverwrite(const AliasAnalysis::Location &Later,
/// isPossibleSelfRead - If 'Inst' might be a self read (i.e. a noop copy of a
/// memory region into an identical pointer) then it doesn't actually make its
-/// input dead in the traditional sense. Consider this case:
+/// input dead in the traditional sense. Consider this case:
///
/// memcpy(A <- B)
/// memcpy(A <- A)
@@ -391,10 +393,10 @@ static bool isPossibleSelfRead(Instruction *Inst,
// location read.
AliasAnalysis::Location InstReadLoc = getLocForRead(Inst, AA);
if (InstReadLoc.Ptr == 0) return false; // Not a reading instruction.
-
+
// If the read and written loc obviously don't alias, it isn't a read.
if (AA.isNoAlias(InstReadLoc, InstStoreLoc)) return false;
-
+
// Okay, 'Inst' may copy over itself. However, we can still remove a the
// DepWrite instruction if we can prove that it reads from the same location
// as Inst. This handles useful cases like:
@@ -404,10 +406,10 @@ static bool isPossibleSelfRead(Instruction *Inst,
// aliases, so removing the first memcpy is safe (assuming it writes <= #
// bytes as the second one.
AliasAnalysis::Location DepReadLoc = getLocForRead(DepWrite, AA);
-
+
if (DepReadLoc.Ptr && AA.isMustAlias(InstReadLoc.Ptr, DepReadLoc.Ptr))
return false;
-
+
// If DepWrite doesn't read memory or if we can't prove it is a must alias,
// then it can't be considered dead.
return true;
@@ -420,43 +422,43 @@ static bool isPossibleSelfRead(Instruction *Inst,
bool DSE::runOnBasicBlock(BasicBlock &BB) {
bool MadeChange = false;
-
+
// Do a top-down walk on the BB.
for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ) {
Instruction *Inst = BBI++;
-
+
// Handle 'free' calls specially.
if (CallInst *F = isFreeCall(Inst)) {
MadeChange |= HandleFree(F);
continue;
}
-
+
// If we find something that writes memory, get its memory dependence.
if (!hasMemoryWrite(Inst))
continue;
MemDepResult InstDep = MD->getDependency(Inst);
-
+
// Ignore any store where we can't find a local dependence.
// FIXME: cross-block DSE would be fun. :)
- if (InstDep.isNonLocal() || InstDep.isUnknown())
+ if (!InstDep.isDef() && !InstDep.isClobber())
continue;
-
+
// If we're storing the same value back to a pointer that we just
// loaded from, then the store can be removed.
if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
if (LoadInst *DepLoad = dyn_cast<LoadInst>(InstDep.getInst())) {
if (SI->getPointerOperand() == DepLoad->getPointerOperand() &&
- SI->getOperand(0) == DepLoad && !SI->isVolatile()) {
+ SI->getOperand(0) == DepLoad && isRemovable(SI)) {
DEBUG(dbgs() << "DSE: Remove Store Of Load from same pointer:\n "
<< "LOAD: " << *DepLoad << "\n STORE: " << *SI << '\n');
-
+
// DeleteDeadInstruction can delete the current instruction. Save BBI
// in case we need it.
WeakVH NextInst(BBI);
-
+
DeleteDeadInstruction(SI, *MD);
-
+
if (NextInst == 0) // Next instruction deleted.
BBI = BB.begin();
else if (BBI != BB.begin()) // Revisit this instruction if possible.
@@ -467,15 +469,15 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
}
}
}
-
+
// Figure out what location is being stored to.
AliasAnalysis::Location Loc = getLocForWrite(Inst, *AA);
// If we didn't get a useful location, fail.
if (Loc.Ptr == 0)
continue;
-
- while (!InstDep.isNonLocal() && !InstDep.isUnknown()) {
+
+ while (InstDep.isDef() || InstDep.isClobber()) {
// Get the memory clobbered by the instruction we depend on. MemDep will
// skip any instructions that 'Loc' clearly doesn't interact with. If we
// end up depending on a may- or must-aliased load, then we can't optimize
@@ -496,12 +498,12 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
!isPossibleSelfRead(Inst, Loc, DepWrite, *AA)) {
DEBUG(dbgs() << "DSE: Remove Dead Store:\n DEAD: "
<< *DepWrite << "\n KILLER: " << *Inst << '\n');
-
+
// Delete the store and now-dead instructions that feed it.
DeleteDeadInstruction(DepWrite, *MD);
++NumFastStores;
MadeChange = true;
-
+
// DeleteDeadInstruction can delete the current instruction in loop
// cases, reset BBI.
BBI = Inst;
@@ -509,7 +511,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
--BBI;
break;
}
-
+
// If this is a may-aliased store that is clobbering the store value, we
// can keep searching past it for another must-aliased pointer that stores
// to the same location. For example, in:
@@ -519,20 +521,20 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
// we can remove the first store to P even though we don't know if P and Q
// alias.
if (DepWrite == &BB.front()) break;
-
+
// Can't look past this instruction if it might read 'Loc'.
if (AA->getModRefInfo(DepWrite, Loc) & AliasAnalysis::Ref)
break;
-
+
InstDep = MD->getPointerDependencyFrom(Loc, false, DepWrite, &BB);
}
}
-
+
// If this block ends in a return, unwind, or unreachable, all allocas are
// dead at its end, which means stores to them are also dead.
if (BB.getTerminator()->getNumSuccessors() == 0)
MadeChange |= handleEndBlock(BB);
-
+
return MadeChange;
}
@@ -543,18 +545,18 @@ bool DSE::HandleFree(CallInst *F) {
MemDepResult Dep = MD->getDependency(F);
- while (!Dep.isNonLocal() && !Dep.isUnknown()) {
+ while (Dep.isDef() || Dep.isClobber()) {
Instruction *Dependency = Dep.getInst();
if (!hasMemoryWrite(Dependency) || !isRemovable(Dependency))
return MadeChange;
-
+
Value *DepPointer =
GetUnderlyingObject(getStoredPointerOperand(Dependency));
// Check for aliasing.
if (!AA->isMustAlias(F->getArgOperand(0), DepPointer))
return MadeChange;
-
+
// DCE instructions only used to calculate that store
DeleteDeadInstruction(Dependency, *MD);
++NumFastStores;
@@ -567,7 +569,7 @@ bool DSE::HandleFree(CallInst *F) {
// free(s);
Dep = MD->getDependency(F);
};
-
+
return MadeChange;
}
@@ -579,28 +581,28 @@ bool DSE::HandleFree(CallInst *F) {
/// ret void
bool DSE::handleEndBlock(BasicBlock &BB) {
bool MadeChange = false;
-
+
// Keep track of all of the stack objects that are dead at the end of the
// function.
SmallPtrSet<Value*, 16> DeadStackObjects;
-
+
// Find all of the alloca'd pointers in the entry block.
BasicBlock *Entry = BB.getParent()->begin();
for (BasicBlock::iterator I = Entry->begin(), E = Entry->end(); I != E; ++I)
if (AllocaInst *AI = dyn_cast<AllocaInst>(I))
DeadStackObjects.insert(AI);
-
+
// Treat byval arguments the same, stores to them are dead at the end of the
// function.
for (Function::arg_iterator AI = BB.getParent()->arg_begin(),
AE = BB.getParent()->arg_end(); AI != AE; ++AI)
if (AI->hasByValAttr())
DeadStackObjects.insert(AI);
-
+
// Scan the basic block backwards
for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){
--BBI;
-
+
// If we find a store, check to see if it points into a dead stack value.
if (hasMemoryWrite(BBI) && isRemovable(BBI)) {
// See through pointer-to-pointer bitcasts
@@ -609,10 +611,10 @@ bool DSE::handleEndBlock(BasicBlock &BB) {
// Stores to stack values are valid candidates for removal.
if (DeadStackObjects.count(Pointer)) {
Instruction *Dead = BBI++;
-
+
DEBUG(dbgs() << "DSE: Dead Store at End of Block:\n DEAD: "
<< *Dead << "\n Object: " << *Pointer << '\n');
-
+
// DCE instructions only used to calculate that store.
DeleteDeadInstruction(Dead, *MD, &DeadStackObjects);
++NumFastStores;
@@ -620,7 +622,7 @@ bool DSE::handleEndBlock(BasicBlock &BB) {
continue;
}
}
-
+
// Remove any dead non-memory-mutating instructions.
if (isInstructionTriviallyDead(BBI)) {
Instruction *Inst = BBI++;
@@ -629,55 +631,61 @@ bool DSE::handleEndBlock(BasicBlock &BB) {
MadeChange = true;
continue;
}
-
+
if (AllocaInst *A = dyn_cast<AllocaInst>(BBI)) {
DeadStackObjects.erase(A);
continue;
}
-
+
if (CallSite CS = cast<Value>(BBI)) {
// If this call does not access memory, it can't be loading any of our
// pointers.
if (AA->doesNotAccessMemory(CS))
continue;
-
+
// If the call might load from any of our allocas, then any store above
// the call is live.
SmallVector<Value*, 8> LiveAllocas;
for (SmallPtrSet<Value*, 16>::iterator I = DeadStackObjects.begin(),
E = DeadStackObjects.end(); I != E; ++I) {
// See if the call site touches it.
- AliasAnalysis::ModRefResult A =
+ AliasAnalysis::ModRefResult A =
AA->getModRefInfo(CS, *I, getPointerSize(*I, *AA));
-
+
if (A == AliasAnalysis::ModRef || A == AliasAnalysis::Ref)
LiveAllocas.push_back(*I);
}
-
+
for (SmallVector<Value*, 8>::iterator I = LiveAllocas.begin(),
E = LiveAllocas.end(); I != E; ++I)
DeadStackObjects.erase(*I);
-
+
// If all of the allocas were clobbered by the call then we're not going
// to find anything else to process.
if (DeadStackObjects.empty())
return MadeChange;
-
+
continue;
}
-
+
AliasAnalysis::Location LoadedLoc;
-
+
// If we encounter a use of the pointer, it is no longer considered dead
if (LoadInst *L = dyn_cast<LoadInst>(BBI)) {
+ if (!L->isUnordered()) // Be conservative with atomic/volatile load
+ break;
LoadedLoc = AA->getLocation(L);
} else if (VAArgInst *V = dyn_cast<VAArgInst>(BBI)) {
LoadedLoc = AA->getLocation(V);
} else if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(BBI)) {
LoadedLoc = AA->getLocationForSource(MTI);
- } else {
- // Not a loading instruction.
+ } else if (!BBI->mayReadFromMemory()) {
+ // Instruction doesn't read memory. Note that stores that weren't removed
+ // above will hit this case.
continue;
+ } else {
+ // Unknown inst; assume it clobbers everything.
+ break;
}
// Remove any allocas from the DeadPointer set that are loaded, as this
@@ -689,7 +697,7 @@ bool DSE::handleEndBlock(BasicBlock &BB) {
if (DeadStackObjects.empty())
break;
}
-
+
return MadeChange;
}
@@ -703,14 +711,14 @@ void DSE::RemoveAccessedObjects(const AliasAnalysis::Location &LoadedLoc,
// A constant can't be in the dead pointer set.
if (isa<Constant>(UnderlyingPointer))
return;
-
+
// If the kill pointer can be easily reduced to an alloca, don't bother doing
// extraneous AA queries.
if (isa<AllocaInst>(UnderlyingPointer) || isa<Argument>(UnderlyingPointer)) {
DeadStackObjects.erase(const_cast<Value*>(UnderlyingPointer));
return;
}
-
+
SmallVector<Value*, 16> NowLive;
for (SmallPtrSet<Value*, 16>::iterator I = DeadStackObjects.begin(),
E = DeadStackObjects.end(); I != E; ++I) {
diff --git a/lib/Transforms/Scalar/EarlyCSE.cpp b/lib/Transforms/Scalar/EarlyCSE.cpp
index 3d3f17b..c0223d2 100644
--- a/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -92,7 +92,7 @@ unsigned DenseMapInfo<SimpleValue>::getHashValue(SimpleValue Val) {
// Hash in all of the operands as pointers.
unsigned Res = 0;
for (unsigned i = 0, e = Inst->getNumOperands(); i != e; ++i)
- Res ^= getHash(Inst->getOperand(i)) << i;
+ Res ^= getHash(Inst->getOperand(i)) << (i & 0xF);
if (CastInst *CI = dyn_cast<CastInst>(Inst))
Res ^= getHash(CI->getType());
@@ -185,7 +185,7 @@ unsigned DenseMapInfo<CallValue>::getHashValue(CallValue Val) {
for (unsigned i = 0, e = Inst->getNumOperands(); i != e; ++i) {
assert(!Inst->getOperand(i)->getType()->isMetadataTy() &&
"Cannot value number calls with metadata operands");
- Res ^= getHash(Inst->getOperand(i)) << i;
+ Res ^= getHash(Inst->getOperand(i)) << (i & 0xF);
}
// Mix in the opcode.
@@ -357,7 +357,7 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
// If this is a non-volatile load, process it.
if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
// Ignore volatile loads.
- if (LI->isVolatile()) {
+ if (!LI->isSimple()) {
LastStore = 0;
continue;
}
@@ -437,7 +437,7 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
std::pair<Value*, unsigned>(SI->getValueOperand(), CurrentGeneration));
// Remember that this was the last store we saw for DSE.
- if (!SI->isVolatile())
+ if (SI->isSimple())
LastStore = SI;
}
}
diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp
index 87b7317..cbfdbcd 100644
--- a/lib/Transforms/Scalar/GVN.cpp
+++ b/lib/Transforms/Scalar/GVN.cpp
@@ -41,12 +41,16 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/IRBuilder.h"
+#include "llvm/Support/PatternMatch.h"
using namespace llvm;
+using namespace PatternMatch;
STATISTIC(NumGVNInstr, "Number of instructions deleted");
STATISTIC(NumGVNLoad, "Number of loads deleted");
STATISTIC(NumGVNPRE, "Number of instructions PRE'd");
STATISTIC(NumGVNBlocks, "Number of blocks merged");
+STATISTIC(NumGVNSimpl, "Number of instructions simplified");
+STATISTIC(NumGVNEqProp, "Number of equalities propagated");
STATISTIC(NumPRELoad, "Number of loads PRE'd");
static cl::opt<bool> EnablePRE("enable-pre",
@@ -63,7 +67,7 @@ static cl::opt<bool> EnableLoadPRE("enable-load-pre", cl::init(true));
namespace {
struct Expression {
uint32_t opcode;
- const Type *type;
+ Type *type;
SmallVector<uint32_t, 4> varargs;
Expression(uint32_t o = ~2U) : opcode(o) { }
@@ -548,6 +552,9 @@ namespace {
void cleanupGlobalSets();
void verifyRemoved(const Instruction *I) const;
bool splitCriticalEdges();
+ unsigned replaceAllDominatedUsesWith(Value *From, Value *To,
+ BasicBlock *Root);
+ bool propagateEquality(Value *LHS, Value *RHS, BasicBlock *Root);
};
char GVN::ID = 0;
@@ -655,7 +662,7 @@ SpeculationFailure:
/// CanCoerceMustAliasedValueToLoad - Return true if
/// CoerceAvailableValueToLoadType will succeed.
static bool CanCoerceMustAliasedValueToLoad(Value *StoredVal,
- const Type *LoadTy,
+ Type *LoadTy,
const TargetData &TD) {
// If the loaded or stored value is an first class array or struct, don't try
// to transform them. We need to be able to bitcast to integer.
@@ -680,17 +687,17 @@ static bool CanCoerceMustAliasedValueToLoad(Value *StoredVal,
///
/// If we can't do it, return null.
static Value *CoerceAvailableValueToLoadType(Value *StoredVal,
- const Type *LoadedTy,
+ Type *LoadedTy,
Instruction *InsertPt,
const TargetData &TD) {
if (!CanCoerceMustAliasedValueToLoad(StoredVal, LoadedTy, TD))
return 0;
// If this is already the right type, just return it.
- const Type *StoredValTy = StoredVal->getType();
+ Type *StoredValTy = StoredVal->getType();
- uint64_t StoreSize = TD.getTypeStoreSizeInBits(StoredValTy);
- uint64_t LoadSize = TD.getTypeStoreSizeInBits(LoadedTy);
+ uint64_t StoreSize = TD.getTypeSizeInBits(StoredValTy);
+ uint64_t LoadSize = TD.getTypeSizeInBits(LoadedTy);
// If the store and reload are the same size, we can always reuse it.
if (StoreSize == LoadSize) {
@@ -704,7 +711,7 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal,
StoredVal = new PtrToIntInst(StoredVal, StoredValTy, "", InsertPt);
}
- const Type *TypeToCastTo = LoadedTy;
+ Type *TypeToCastTo = LoadedTy;
if (TypeToCastTo->isPointerTy())
TypeToCastTo = TD.getIntPtrType(StoredValTy->getContext());
@@ -743,7 +750,7 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal,
}
// Truncate the integer to the right size now.
- const Type *NewIntTy = IntegerType::get(StoredValTy->getContext(), LoadSize);
+ Type *NewIntTy = IntegerType::get(StoredValTy->getContext(), LoadSize);
StoredVal = new TruncInst(StoredVal, NewIntTy, "trunc", InsertPt);
if (LoadedTy == NewIntTy)
@@ -765,7 +772,7 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal,
/// Check this case to see if there is anything more we can do before we give
/// up. This returns -1 if we have to give up, or a byte number in the stored
/// value of the piece that feeds the load.
-static int AnalyzeLoadFromClobberingWrite(const Type *LoadTy, Value *LoadPtr,
+static int AnalyzeLoadFromClobberingWrite(Type *LoadTy, Value *LoadPtr,
Value *WritePtr,
uint64_t WriteSizeInBits,
const TargetData &TD) {
@@ -839,7 +846,7 @@ static int AnalyzeLoadFromClobberingWrite(const Type *LoadTy, Value *LoadPtr,
/// AnalyzeLoadFromClobberingStore - This function is called when we have a
/// memdep query of a load that ends up being a clobbering store.
-static int AnalyzeLoadFromClobberingStore(const Type *LoadTy, Value *LoadPtr,
+static int AnalyzeLoadFromClobberingStore(Type *LoadTy, Value *LoadPtr,
StoreInst *DepSI,
const TargetData &TD) {
// Cannot handle reading from store of first-class aggregate yet.
@@ -856,7 +863,7 @@ static int AnalyzeLoadFromClobberingStore(const Type *LoadTy, Value *LoadPtr,
/// AnalyzeLoadFromClobberingLoad - This function is called when we have a
/// memdep query of a load that ends up being clobbered by another load. See if
/// the other load can feed into the second load.
-static int AnalyzeLoadFromClobberingLoad(const Type *LoadTy, Value *LoadPtr,
+static int AnalyzeLoadFromClobberingLoad(Type *LoadTy, Value *LoadPtr,
LoadInst *DepLI, const TargetData &TD){
// Cannot handle reading from store of first-class aggregate yet.
if (DepLI->getType()->isStructTy() || DepLI->getType()->isArrayTy())
@@ -883,7 +890,7 @@ static int AnalyzeLoadFromClobberingLoad(const Type *LoadTy, Value *LoadPtr,
-static int AnalyzeLoadFromClobberingMemInst(const Type *LoadTy, Value *LoadPtr,
+static int AnalyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr,
MemIntrinsic *MI,
const TargetData &TD) {
// If the mem operation is a non-constant size, we can't handle it.
@@ -920,7 +927,7 @@ static int AnalyzeLoadFromClobberingMemInst(const Type *LoadTy, Value *LoadPtr,
llvm::Type::getInt8PtrTy(Src->getContext()));
Constant *OffsetCst =
ConstantInt::get(Type::getInt64Ty(Src->getContext()), (unsigned)Offset);
- Src = ConstantExpr::getGetElementPtr(Src, &OffsetCst, 1);
+ Src = ConstantExpr::getGetElementPtr(Src, OffsetCst);
Src = ConstantExpr::getBitCast(Src, PointerType::getUnqual(LoadTy));
if (ConstantFoldLoadFromConstPtr(Src, &TD))
return Offset;
@@ -934,7 +941,7 @@ static int AnalyzeLoadFromClobberingMemInst(const Type *LoadTy, Value *LoadPtr,
/// mustalias. Check this case to see if there is anything more we can do
/// before we give up.
static Value *GetStoreValueForLoad(Value *SrcVal, unsigned Offset,
- const Type *LoadTy,
+ Type *LoadTy,
Instruction *InsertPt, const TargetData &TD){
LLVMContext &Ctx = SrcVal->getType()->getContext();
@@ -946,10 +953,9 @@ static Value *GetStoreValueForLoad(Value *SrcVal, unsigned Offset,
// Compute which bits of the stored value are being used by the load. Convert
// to an integer type to start with.
if (SrcVal->getType()->isPointerTy())
- SrcVal = Builder.CreatePtrToInt(SrcVal, TD.getIntPtrType(Ctx), "tmp");
+ SrcVal = Builder.CreatePtrToInt(SrcVal, TD.getIntPtrType(Ctx));
if (!SrcVal->getType()->isIntegerTy())
- SrcVal = Builder.CreateBitCast(SrcVal, IntegerType::get(Ctx, StoreSize*8),
- "tmp");
+ SrcVal = Builder.CreateBitCast(SrcVal, IntegerType::get(Ctx, StoreSize*8));
// Shift the bits to the least significant depending on endianness.
unsigned ShiftAmt;
@@ -959,11 +965,10 @@ static Value *GetStoreValueForLoad(Value *SrcVal, unsigned Offset,
ShiftAmt = (StoreSize-LoadSize-Offset)*8;
if (ShiftAmt)
- SrcVal = Builder.CreateLShr(SrcVal, ShiftAmt, "tmp");
+ SrcVal = Builder.CreateLShr(SrcVal, ShiftAmt);
if (LoadSize != StoreSize)
- SrcVal = Builder.CreateTrunc(SrcVal, IntegerType::get(Ctx, LoadSize*8),
- "tmp");
+ SrcVal = Builder.CreateTrunc(SrcVal, IntegerType::get(Ctx, LoadSize*8));
return CoerceAvailableValueToLoadType(SrcVal, LoadTy, InsertPt, TD);
}
@@ -974,7 +979,7 @@ static Value *GetStoreValueForLoad(Value *SrcVal, unsigned Offset,
/// because the pointers don't mustalias. Check this case to see if there is
/// anything more we can do before we give up.
static Value *GetLoadValueForLoad(LoadInst *SrcVal, unsigned Offset,
- const Type *LoadTy, Instruction *InsertPt,
+ Type *LoadTy, Instruction *InsertPt,
GVN &gvn) {
const TargetData &TD = *gvn.getTargetData();
// If Offset+LoadTy exceeds the size of SrcVal, then we must be wanting to
@@ -982,8 +987,8 @@ static Value *GetLoadValueForLoad(LoadInst *SrcVal, unsigned Offset,
unsigned SrcValSize = TD.getTypeStoreSize(SrcVal->getType());
unsigned LoadSize = TD.getTypeStoreSize(LoadTy);
if (Offset+LoadSize > SrcValSize) {
- assert(!SrcVal->isVolatile() && "Cannot widen volatile load!");
- assert(isa<IntegerType>(SrcVal->getType())&&"Can't widen non-integer load");
+ assert(SrcVal->isSimple() && "Cannot widen volatile/atomic load!");
+ assert(SrcVal->getType()->isIntegerTy() && "Can't widen non-integer load");
// If we have a load/load clobber an DepLI can be widened to cover this
// load, then we should widen it to the next power of 2 size big enough!
unsigned NewLoadSize = Offset+LoadSize;
@@ -996,7 +1001,7 @@ static Value *GetLoadValueForLoad(LoadInst *SrcVal, unsigned Offset,
// memdep queries will find the new load. We can't easily remove the old
// load completely because it is already in the value numbering table.
IRBuilder<> Builder(SrcVal->getParent(), ++BasicBlock::iterator(SrcVal));
- const Type *DestPTy =
+ Type *DestPTy =
IntegerType::get(LoadTy->getContext(), NewLoadSize*8);
DestPTy = PointerType::get(DestPTy,
cast<PointerType>(PtrVal->getType())->getAddressSpace());
@@ -1034,7 +1039,7 @@ static Value *GetLoadValueForLoad(LoadInst *SrcVal, unsigned Offset,
/// GetMemInstValueForLoad - This function is called when we have a
/// memdep query of a load that ends up being a clobbering mem intrinsic.
static Value *GetMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset,
- const Type *LoadTy, Instruction *InsertPt,
+ Type *LoadTy, Instruction *InsertPt,
const TargetData &TD){
LLVMContext &Ctx = LoadTy->getContext();
uint64_t LoadSize = TD.getTypeSizeInBits(LoadTy)/8;
@@ -1081,7 +1086,7 @@ static Value *GetMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset,
llvm::Type::getInt8PtrTy(Src->getContext()));
Constant *OffsetCst =
ConstantInt::get(Type::getInt64Ty(Src->getContext()), (unsigned)Offset);
- Src = ConstantExpr::getGetElementPtr(Src, &OffsetCst, 1);
+ Src = ConstantExpr::getGetElementPtr(Src, OffsetCst);
Src = ConstantExpr::getBitCast(Src, PointerType::getUnqual(LoadTy));
return ConstantFoldLoadFromConstPtr(Src, &TD);
}
@@ -1154,7 +1159,7 @@ struct AvailableValueInBlock {
/// MaterializeAdjustedValue - Emit code into this block to adjust the value
/// defined here to the specified type. This handles various coercion cases.
- Value *MaterializeAdjustedValue(const Type *LoadTy, GVN &gvn) const {
+ Value *MaterializeAdjustedValue(Type *LoadTy, GVN &gvn) const {
Value *Res;
if (isSimpleValue()) {
Res = getSimpleValue();
@@ -1213,7 +1218,7 @@ static Value *ConstructSSAForLoadSet(LoadInst *LI,
SSAUpdater SSAUpdate(&NewPHIs);
SSAUpdate.Initialize(LI->getType(), LI->getName());
- const Type *LoadTy = LI->getType();
+ Type *LoadTy = LI->getType();
for (unsigned i = 0, e = ValuesPerBlock.size(); i != e; ++i) {
const AvailableValueInBlock &AV = ValuesPerBlock[i];
@@ -1274,7 +1279,9 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
// If we had a phi translation failure, we'll have a single entry which is a
// clobber in the current block. Reject this early.
- if (Deps.size() == 1 && Deps[0].getResult().isUnknown()) {
+ if (Deps.size() == 1
+ && !Deps[0].getResult().isDef() && !Deps[0].getResult().isClobber())
+ {
DEBUG(
dbgs() << "GVN: non-local load ";
WriteAsOperand(dbgs(), LI);
@@ -1294,7 +1301,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
BasicBlock *DepBB = Deps[i].getBB();
MemDepResult DepInfo = Deps[i].getResult();
- if (DepInfo.isUnknown()) {
+ if (!DepInfo.isDef() && !DepInfo.isClobber()) {
UnavailableBlocks.push_back(DepBB);
continue;
}
@@ -1359,7 +1366,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
continue;
}
- assert(DepInfo.isDef() && "Expecting def here");
+ // DepInfo.isDef() here
Instruction *DepInst = DepInfo.getInst();
@@ -1446,8 +1453,8 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
for (unsigned i = 0, e = UnavailableBlocks.size(); i != e; ++i)
Blockers.insert(UnavailableBlocks[i]);
- // Lets find first basic block with more than one predecessor. Walk backwards
- // through predecessors if needed.
+ // Let's find the first basic block with more than one predecessor. Walk
+ // backwards through predecessors if needed.
BasicBlock *LoadBB = LI->getParent();
BasicBlock *TmpBB = LoadBB;
@@ -1519,10 +1526,19 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
<< Pred->getName() << "': " << *LI << '\n');
return false;
}
+
+ if (LoadBB->isLandingPad()) {
+ DEBUG(dbgs()
+ << "COULD NOT PRE LOAD BECAUSE OF LANDING PAD CRITICAL EDGE '"
+ << Pred->getName() << "': " << *LI << '\n');
+ return false;
+ }
+
unsigned SuccNum = GetSuccessorNumber(Pred, LoadBB);
NeedToSplit.push_back(std::make_pair(Pred->getTerminator(), SuccNum));
}
}
+
if (!NeedToSplit.empty()) {
toSplit.append(NeedToSplit.begin(), NeedToSplit.end());
return false;
@@ -1660,7 +1676,7 @@ bool GVN::processLoad(LoadInst *L) {
if (!MD)
return false;
- if (L->isVolatile())
+ if (!L->isSimple())
return false;
if (L->use_empty()) {
@@ -1747,7 +1763,11 @@ bool GVN::processLoad(LoadInst *L) {
return false;
}
- if (Dep.isUnknown()) {
+ // If it is defined in another block, try harder.
+ if (Dep.isNonLocal())
+ return processNonLocalLoad(L);
+
+ if (!Dep.isDef()) {
DEBUG(
// fast print dep, using operator<< on instruction is too slow.
dbgs() << "GVN: load ";
@@ -1757,12 +1777,6 @@ bool GVN::processLoad(LoadInst *L) {
return false;
}
- // If it is defined in another block, try harder.
- if (Dep.isNonLocal())
- return processNonLocalLoad(L);
-
- assert(Dep.isDef() && "Expecting def here");
-
Instruction *DepInst = Dep.getInst();
if (StoreInst *DepSI = dyn_cast<StoreInst>(DepInst)) {
Value *StoredVal = DepSI->getValueOperand();
@@ -1874,6 +1888,133 @@ Value *GVN::findLeader(BasicBlock *BB, uint32_t num) {
return Val;
}
+/// replaceAllDominatedUsesWith - Replace all uses of 'From' with 'To' if the
+/// use is dominated by the given basic block. Returns the number of uses that
+/// were replaced.
+unsigned GVN::replaceAllDominatedUsesWith(Value *From, Value *To,
+ BasicBlock *Root) {
+ unsigned Count = 0;
+ for (Value::use_iterator UI = From->use_begin(), UE = From->use_end();
+ UI != UE; ) {
+ Instruction *User = cast<Instruction>(*UI);
+ unsigned OpNum = UI.getOperandNo();
+ ++UI;
+
+ if (DT->dominates(Root, User->getParent())) {
+ User->setOperand(OpNum, To);
+ ++Count;
+ }
+ }
+ return Count;
+}
+
+/// propagateEquality - The given values are known to be equal in every block
+/// dominated by 'Root'. Exploit this, for example by replacing 'LHS' with
+/// 'RHS' everywhere in the scope. Returns whether a change was made.
+bool GVN::propagateEquality(Value *LHS, Value *RHS, BasicBlock *Root) {
+ if (LHS == RHS) return false;
+ assert(LHS->getType() == RHS->getType() && "Equal but types differ!");
+
+ // Don't try to propagate equalities between constants.
+ if (isa<Constant>(LHS) && isa<Constant>(RHS))
+ return false;
+
+ // Make sure that any constants are on the right-hand side. In general the
+ // best results are obtained by placing the longest lived value on the RHS.
+ if (isa<Constant>(LHS))
+ std::swap(LHS, RHS);
+
+ // If neither term is constant then bail out. This is not for correctness,
+ // it's just that the non-constant case is much less useful: it occurs just
+ // as often as the constant case but handling it hardly ever results in an
+ // improvement.
+ if (!isa<Constant>(RHS))
+ return false;
+
+ // If value numbering later deduces that an instruction in the scope is equal
+ // to 'LHS' then ensure it will be turned into 'RHS'.
+ addToLeaderTable(VN.lookup_or_add(LHS), RHS, Root);
+
+ // Replace all occurrences of 'LHS' with 'RHS' everywhere in the scope.
+ unsigned NumReplacements = replaceAllDominatedUsesWith(LHS, RHS, Root);
+ bool Changed = NumReplacements > 0;
+ NumGVNEqProp += NumReplacements;
+
+ // Now try to deduce additional equalities from this one. For example, if the
+ // known equality was "(A != B)" == "false" then it follows that A and B are
+ // equal in the scope. Only boolean equalities with an explicit true or false
+ // RHS are currently supported.
+ if (!RHS->getType()->isIntegerTy(1))
+ // Not a boolean equality - bail out.
+ return Changed;
+ ConstantInt *CI = dyn_cast<ConstantInt>(RHS);
+ if (!CI)
+ // RHS neither 'true' nor 'false' - bail out.
+ return Changed;
+ // Whether RHS equals 'true'. Otherwise it equals 'false'.
+ bool isKnownTrue = CI->isAllOnesValue();
+ bool isKnownFalse = !isKnownTrue;
+
+ // If "A && B" is known true then both A and B are known true. If "A || B"
+ // is known false then both A and B are known false.
+ Value *A, *B;
+ if ((isKnownTrue && match(LHS, m_And(m_Value(A), m_Value(B)))) ||
+ (isKnownFalse && match(LHS, m_Or(m_Value(A), m_Value(B))))) {
+ Changed |= propagateEquality(A, RHS, Root);
+ Changed |= propagateEquality(B, RHS, Root);
+ return Changed;
+ }
+
+ // If we are propagating an equality like "(A == B)" == "true" then also
+ // propagate the equality A == B.
+ if (ICmpInst *Cmp = dyn_cast<ICmpInst>(LHS)) {
+ // Only equality comparisons are supported.
+ if ((isKnownTrue && Cmp->getPredicate() == CmpInst::ICMP_EQ) ||
+ (isKnownFalse && Cmp->getPredicate() == CmpInst::ICMP_NE)) {
+ Value *Op0 = Cmp->getOperand(0), *Op1 = Cmp->getOperand(1);
+ Changed |= propagateEquality(Op0, Op1, Root);
+ }
+ return Changed;
+ }
+
+ return Changed;
+}
+
+/// isOnlyReachableViaThisEdge - There is an edge from 'Src' to 'Dst'. Return
+/// true if every path from the entry block to 'Dst' passes via this edge. In
+/// particular 'Dst' must not be reachable via another edge from 'Src'.
+static bool isOnlyReachableViaThisEdge(BasicBlock *Src, BasicBlock *Dst,
+ DominatorTree *DT) {
+ // First off, there must not be more than one edge from Src to Dst, there
+ // should be exactly one. So keep track of the number of times Src occurs
+ // as a predecessor of Dst and fail if it's more than once. Secondly, any
+ // other predecessors of Dst should be dominated by Dst (see logic below).
+ bool SawEdgeFromSrc = false;
+ for (pred_iterator PI = pred_begin(Dst), PE = pred_end(Dst); PI != PE; ++PI) {
+ BasicBlock *Pred = *PI;
+ if (Pred == Src) {
+ // An edge from Src to Dst.
+ if (SawEdgeFromSrc)
+ // There are multiple edges from Src to Dst - fail.
+ return false;
+ SawEdgeFromSrc = true;
+ continue;
+ }
+ // If the predecessor is not dominated by Dst, then it must be possible to
+ // reach it either without passing through Src (and thus not via the edge)
+ // or by passing through Src but taking a different edge out of Src. Either
+ // way it is possible to reach Dst without passing via the edge, so fail.
+ if (!DT->dominates(Dst, *PI))
+ return false;
+ }
+ assert(SawEdgeFromSrc && "No edge between these basic blocks!");
+
+ // Every path from the entry block to Dst must at some point pass to Dst from
+ // a predecessor that is not dominated by Dst. This predecessor can only be
+ // Src, since all others are dominated by Dst. As there is only one edge from
+ // Src to Dst, the path passes by this edge.
+ return true;
+}
/// processInstruction - When calculating availability, handle an instruction
/// by inserting it into the appropriate sets
@@ -1891,6 +2032,7 @@ bool GVN::processInstruction(Instruction *I) {
if (MD && V->getType()->isPointerTy())
MD->invalidateCachedPointerInfo(V);
markInstructionForDeletion(I);
+ ++NumGVNSimpl;
return true;
}
@@ -1903,30 +2045,45 @@ bool GVN::processInstruction(Instruction *I) {
return false;
}
- // For conditions branches, we can perform simple conditional propagation on
+ // For conditional branches, we can perform simple conditional propagation on
// the condition value itself.
if (BranchInst *BI = dyn_cast<BranchInst>(I)) {
if (!BI->isConditional() || isa<Constant>(BI->getCondition()))
return false;
-
+
Value *BranchCond = BI->getCondition();
- uint32_t CondVN = VN.lookup_or_add(BranchCond);
-
+
BasicBlock *TrueSucc = BI->getSuccessor(0);
BasicBlock *FalseSucc = BI->getSuccessor(1);
-
- if (TrueSucc->getSinglePredecessor())
- addToLeaderTable(CondVN,
- ConstantInt::getTrue(TrueSucc->getContext()),
- TrueSucc);
- if (FalseSucc->getSinglePredecessor())
- addToLeaderTable(CondVN,
- ConstantInt::getFalse(TrueSucc->getContext()),
- FalseSucc);
-
- return false;
+ BasicBlock *Parent = BI->getParent();
+ bool Changed = false;
+
+ if (isOnlyReachableViaThisEdge(Parent, TrueSucc, DT))
+ Changed |= propagateEquality(BranchCond,
+ ConstantInt::getTrue(TrueSucc->getContext()),
+ TrueSucc);
+
+ if (isOnlyReachableViaThisEdge(Parent, FalseSucc, DT))
+ Changed |= propagateEquality(BranchCond,
+ ConstantInt::getFalse(FalseSucc->getContext()),
+ FalseSucc);
+
+ return Changed;
}
-
+
+ // For switches, propagate the case values into the case destinations.
+ if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) {
+ Value *SwitchCond = SI->getCondition();
+ BasicBlock *Parent = SI->getParent();
+ bool Changed = false;
+ for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) {
+ BasicBlock *Dst = SI->getSuccessor(i);
+ if (isOnlyReachableViaThisEdge(Parent, Dst, DT))
+ Changed |= propagateEquality(SwitchCond, SI->getCaseValue(i), Dst);
+ }
+ return Changed;
+ }
+
// Instructions with void type don't return a value, so there's
// no point in trying to find redudancies in them.
if (I->getType()->isVoidTy()) return false;
@@ -2071,6 +2228,9 @@ bool GVN::performPRE(Function &F) {
// Nothing to PRE in the entry block.
if (CurrentBlock == &F.getEntryBlock()) continue;
+ // Don't perform PRE on a landing pad.
+ if (CurrentBlock->isLandingPad()) continue;
+
for (BasicBlock::iterator BI = CurrentBlock->begin(),
BE = CurrentBlock->end(); BI != BE; ) {
Instruction *CurInst = BI++;
diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp
index dee3d38..75fa011 100644
--- a/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -11,17 +11,6 @@
// computations derived from them) into simpler forms suitable for subsequent
// analysis and transformation.
//
-// This transformation makes the following changes to each loop with an
-// identifiable induction variable:
-// 1. All loops are transformed to have a SINGLE canonical induction variable
-// which starts at zero and steps by one.
-// 2. The canonical induction variable is guaranteed to be the first PHI node
-// in the loop header block.
-// 3. The canonical induction variable is guaranteed to be in a wide enough
-// type so that IV expressions need not be (directly) zero-extended or
-// sign-extended.
-// 4. Any pointer arithmetic recurrences are raised to use array subscripts.
-//
// If the trip count of a loop is computable, this pass also makes the following
// changes:
// 1. The exit condition for the loop is canonicalized to compare the
@@ -33,9 +22,6 @@
// purpose of the loop is to compute the exit value of some derived
// expression, this transformation will make the loop dead.
//
-// This transformation should be followed by strength reduction after all of the
-// desired loop transformations have been performed.
-//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "indvars"
@@ -57,11 +43,11 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/SimplifyIndVar.h"
#include "llvm/Target/TargetData.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/STLExtras.h"
using namespace llvm;
STATISTIC(NumRemoved , "Number of aux indvars removed");
@@ -69,15 +55,21 @@ STATISTIC(NumWidened , "Number of indvars widened");
STATISTIC(NumInserted , "Number of canonical indvars added");
STATISTIC(NumReplaced , "Number of exit values replaced");
STATISTIC(NumLFTR , "Number of loop exit tests replaced");
-STATISTIC(NumElimIdentity, "Number of IV identities eliminated");
STATISTIC(NumElimExt , "Number of IV sign/zero extends eliminated");
-STATISTIC(NumElimRem , "Number of IV remainder operations eliminated");
-STATISTIC(NumElimCmp , "Number of IV comparisons eliminated");
STATISTIC(NumElimIV , "Number of congruent IVs eliminated");
-static cl::opt<bool> DisableIVRewrite(
- "disable-iv-rewrite", cl::Hidden,
- cl::desc("Disable canonical induction variable rewriting"));
+namespace llvm {
+ cl::opt<bool> EnableIVRewrite(
+ "enable-iv-rewrite", cl::Hidden,
+ cl::desc("Enable canonical induction variable rewriting"));
+
+ // Trip count verification can be enabled by default under NDEBUG if we
+ // implement a strong expression equivalence checker in SCEV. Until then, we
+ // use the verify-indvars flag, which may assert in some cases.
+ cl::opt<bool> VerifyIndvars(
+ "verify-indvars", cl::Hidden,
+ cl::desc("Verify the ScalarEvolution result after running indvars"));
+}
namespace {
class IndVarSimplify : public LoopPass {
@@ -105,12 +97,12 @@ namespace {
AU.addRequired<ScalarEvolution>();
AU.addRequiredID(LoopSimplifyID);
AU.addRequiredID(LCSSAID);
- if (!DisableIVRewrite)
+ if (EnableIVRewrite)
AU.addRequired<IVUsers>();
AU.addPreserved<ScalarEvolution>();
AU.addPreservedID(LoopSimplifyID);
AU.addPreservedID(LCSSAID);
- if (!DisableIVRewrite)
+ if (EnableIVRewrite)
AU.addPreserved<IVUsers>();
AU.setPreservesCFG();
}
@@ -125,24 +117,14 @@ namespace {
void HandleFloatingPointIV(Loop *L, PHINode *PH);
void RewriteNonIntegerIVs(Loop *L);
- void RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter);
-
- void SimplifyIVUsers(SCEVExpander &Rewriter);
- void SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander &Rewriter);
+ void SimplifyAndExtend(Loop *L, SCEVExpander &Rewriter, LPPassManager &LPM);
- bool EliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
- void EliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
- void EliminateIVRemainder(BinaryOperator *Rem,
- Value *IVOperand,
- bool IsSigned);
-
- void SimplifyCongruentIVs(Loop *L);
+ void RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter);
void RewriteIVExpressions(Loop *L, SCEVExpander &Rewriter);
- ICmpInst *LinearFunctionTestReplace(Loop *L, const SCEV *BackedgeTakenCount,
- PHINode *IndVar,
- SCEVExpander &Rewriter);
+ Value *LinearFunctionTestReplace(Loop *L, const SCEV *BackedgeTakenCount,
+ PHINode *IndVar, SCEVExpander &Rewriter);
void SinkUnusedInvariants(Loop *L);
};
@@ -211,6 +193,36 @@ bool IndVarSimplify::isValidRewrite(Value *FromVal, Value *ToVal) {
return true;
}
+/// Determine the insertion point for this user. By default, insert immediately
+/// before the user. SCEVExpander or LICM will hoist loop invariants out of the
+/// loop. For PHI nodes, there may be multiple uses, so compute the nearest
+/// common dominator for the incoming blocks.
+static Instruction *getInsertPointForUses(Instruction *User, Value *Def,
+ DominatorTree *DT) {
+ PHINode *PHI = dyn_cast<PHINode>(User);
+ if (!PHI)
+ return User;
+
+ Instruction *InsertPt = 0;
+ for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i) {
+ if (PHI->getIncomingValue(i) != Def)
+ continue;
+
+ BasicBlock *InsertBB = PHI->getIncomingBlock(i);
+ if (!InsertPt) {
+ InsertPt = InsertBB->getTerminator();
+ continue;
+ }
+ InsertBB = DT->findNearestCommonDominator(InsertPt->getParent(), InsertBB);
+ InsertPt = InsertBB->getTerminator();
+ }
+ assert(InsertPt && "Missing phi operand");
+ assert((!isa<Instruction>(Def) ||
+ DT->dominates(cast<Instruction>(Def), InsertPt)) &&
+ "def does not dominate all uses");
+ return InsertPt;
+}
+
//===----------------------------------------------------------------------===//
// RewriteNonIntegerIVs and helpers. Prefer integer IVs.
//===----------------------------------------------------------------------===//
@@ -337,14 +349,14 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PN) {
// Positive and negative strides have different safety conditions.
if (IncValue > 0) {
// If we have a positive stride, we require the init to be less than the
- // exit value and an equality or less than comparison.
- if (InitValue >= ExitValue ||
- NewPred == CmpInst::ICMP_SGT || NewPred == CmpInst::ICMP_SGE)
+ // exit value.
+ if (InitValue >= ExitValue)
return;
uint32_t Range = uint32_t(ExitValue-InitValue);
- if (NewPred == CmpInst::ICMP_SLE) {
- // Normalize SLE -> SLT, check for infinite loop.
+ // Check for infinite loop, either:
+ // while (i <= Exit) or until (i > Exit)
+ if (NewPred == CmpInst::ICMP_SLE || NewPred == CmpInst::ICMP_SGT) {
if (++Range == 0) return; // Range overflows.
}
@@ -364,14 +376,14 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PN) {
} else {
// If we have a negative stride, we require the init to be greater than the
- // exit value and an equality or greater than comparison.
- if (InitValue >= ExitValue ||
- NewPred == CmpInst::ICMP_SLT || NewPred == CmpInst::ICMP_SLE)
+ // exit value.
+ if (InitValue <= ExitValue)
return;
uint32_t Range = uint32_t(InitValue-ExitValue);
- if (NewPred == CmpInst::ICMP_SGE) {
- // Normalize SGE -> SGT, check for infinite loop.
+ // Check for infinite loop, either:
+ // while (i >= Exit) or until (i < Exit)
+ if (NewPred == CmpInst::ICMP_SGE || NewPred == CmpInst::ICMP_SLT) {
if (++Range == 0) return; // Range overflows.
}
@@ -390,7 +402,7 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PN) {
return;
}
- const IntegerType *Int32Ty = Type::getInt32Ty(PN->getContext());
+ IntegerType *Int32Ty = Type::getInt32Ty(PN->getContext());
// Insert new integer induction variable.
PHINode *NewPHI = PHINode::Create(Int32Ty, 2, PN->getName()+".int", PN);
@@ -429,7 +441,7 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PN) {
// platforms.
if (WeakPH) {
Value *Conv = new SIToFPInst(NewPHI, PN->getType(), "indvar.conv",
- PN->getParent()->getFirstNonPHI());
+ PN->getParent()->getFirstInsertionPt());
PN->replaceAllUsesWith(Conv);
RecursivelyDeleteTriviallyDeadInstructions(PN);
}
@@ -437,6 +449,8 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PN) {
// Add a new IVUsers entry for the newly-created integer PHI.
if (IU)
IU->AddUsersIfInteresting(NewPHI);
+
+ Changed = true;
}
void IndVarSimplify::RewriteNonIntegerIVs(Loop *L) {
@@ -582,45 +596,15 @@ void IndVarSimplify::RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter) {
//===----------------------------------------------------------------------===//
// Rewrite IV users based on a canonical IV.
-// To be replaced by -disable-iv-rewrite.
+// Only for use with -enable-iv-rewrite.
//===----------------------------------------------------------------------===//
-/// SimplifyIVUsers - Iteratively perform simplification on IVUsers within this
-/// loop. IVUsers is treated as a worklist. Each successive simplification may
-/// push more users which may themselves be candidates for simplification.
-///
-/// This is the old approach to IV simplification to be replaced by
-/// SimplifyIVUsersNoRewrite.
-///
-void IndVarSimplify::SimplifyIVUsers(SCEVExpander &Rewriter) {
- // Each round of simplification involves a round of eliminating operations
- // followed by a round of widening IVs. A single IVUsers worklist is used
- // across all rounds. The inner loop advances the user. If widening exposes
- // more uses, then another pass through the outer loop is triggered.
- for (IVUsers::iterator I = IU->begin(); I != IU->end(); ++I) {
- Instruction *UseInst = I->getUser();
- Value *IVOperand = I->getOperandValToReplace();
-
- if (ICmpInst *ICmp = dyn_cast<ICmpInst>(UseInst)) {
- EliminateIVComparison(ICmp, IVOperand);
- continue;
- }
- if (BinaryOperator *Rem = dyn_cast<BinaryOperator>(UseInst)) {
- bool IsSigned = Rem->getOpcode() == Instruction::SRem;
- if (IsSigned || Rem->getOpcode() == Instruction::URem) {
- EliminateIVRemainder(Rem, IVOperand, IsSigned);
- continue;
- }
- }
- }
-}
-
-// FIXME: It is an extremely bad idea to indvar substitute anything more
-// complex than affine induction variables. Doing so will put expensive
-// polynomial evaluations inside of the loop, and the str reduction pass
-// currently can only reduce affine polynomials. For now just disable
-// indvar subst on anything more complex than an affine addrec, unless
-// it can be expanded to a trivial value.
+/// FIXME: It is an extremely bad idea to indvar substitute anything more
+/// complex than affine induction variables. Doing so will put expensive
+/// polynomial evaluations inside of the loop, and the str reduction pass
+/// currently can only reduce affine polynomials. For now just disable
+/// indvar subst on anything more complex than an affine addrec, unless
+/// it can be expanded to a trivial value.
static bool isSafe(const SCEV *S, const Loop *L, ScalarEvolution *SE) {
// Loop-invariant values are safe.
if (SE->isLoopInvariant(S, L)) return true;
@@ -631,7 +615,8 @@ static bool isSafe(const SCEV *S, const Loop *L, ScalarEvolution *SE) {
return AR->isAffine();
// An add is safe it all its operands are safe.
- if (const SCEVCommutativeExpr *Commutative = dyn_cast<SCEVCommutativeExpr>(S)) {
+ if (const SCEVCommutativeExpr *Commutative
+ = dyn_cast<SCEVCommutativeExpr>(S)) {
for (SCEVCommutativeExpr::op_iterator I = Commutative->op_begin(),
E = Commutative->op_end(); I != E; ++I)
if (!isSafe(*I, L, SE)) return false;
@@ -665,7 +650,7 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, SCEVExpander &Rewriter) {
// of different sizes.
for (IVUsers::iterator UI = IU->begin(), E = IU->end(); UI != E; ++UI) {
Value *Op = UI->getOperandValToReplace();
- const Type *UseTy = Op->getType();
+ Type *UseTy = Op->getType();
Instruction *User = UI->getUser();
// Compute the final addrec to expand into code.
@@ -692,18 +677,7 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, SCEVExpander &Rewriter) {
// hoist loop invariants out of the loop. For PHI nodes, there may be
// multiple uses, so compute the nearest common dominator for the
// incoming blocks.
- Instruction *InsertPt = User;
- if (PHINode *PHI = dyn_cast<PHINode>(InsertPt))
- for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i)
- if (PHI->getIncomingValue(i) == Op) {
- if (InsertPt == User)
- InsertPt = PHI->getIncomingBlock(i)->getTerminator();
- else
- InsertPt =
- DT->findNearestCommonDominator(InsertPt->getParent(),
- PHI->getIncomingBlock(i))
- ->getTerminator();
- }
+ Instruction *InsertPt = getInsertPointForUses(User, Op, DT);
// Now expand it into actual Instructions and patch it into place.
Value *NewVal = Rewriter.expandCodeFor(AR, UseTy, InsertPt);
@@ -747,19 +721,38 @@ namespace {
// extend operations. This information is recorded by CollectExtend and
// provides the input to WidenIV.
struct WideIVInfo {
- const Type *WidestNativeType; // Widest integer type created [sz]ext
- bool IsSigned; // Was an sext user seen before a zext?
+ PHINode *NarrowIV;
+ Type *WidestNativeType; // Widest integer type created [sz]ext
+ bool IsSigned; // Was an sext user seen before a zext?
- WideIVInfo() : WidestNativeType(0), IsSigned(false) {}
+ WideIVInfo() : NarrowIV(0), WidestNativeType(0), IsSigned(false) {}
+ };
+
+ class WideIVVisitor : public IVVisitor {
+ ScalarEvolution *SE;
+ const TargetData *TD;
+
+ public:
+ WideIVInfo WI;
+
+ WideIVVisitor(PHINode *NarrowIV, ScalarEvolution *SCEV,
+ const TargetData *TData) :
+ SE(SCEV), TD(TData) { WI.NarrowIV = NarrowIV; }
+
+ // Implement the interface used by simplifyUsersOfIV.
+ virtual void visitCast(CastInst *Cast);
};
}
-/// CollectExtend - Update information about the induction variable that is
+/// visitCast - Update information about the induction variable that is
/// extended by this sign or zero extend operation. This is used to determine
/// the final width of the IV before actually widening it.
-static void CollectExtend(CastInst *Cast, bool IsSigned, WideIVInfo &WI,
- ScalarEvolution *SE, const TargetData *TD) {
- const Type *Ty = Cast->getType();
+void WideIVVisitor::visitCast(CastInst *Cast) {
+ bool IsSigned = Cast->getOpcode() == Instruction::SExt;
+ if (!IsSigned && Cast->getOpcode() != Instruction::ZExt)
+ return;
+
+ Type *Ty = Cast->getType();
uint64_t Width = SE->getTypeSizeInBits(Ty);
if (TD && !TD->isLegalInteger(Width))
return;
@@ -779,6 +772,21 @@ static void CollectExtend(CastInst *Cast, bool IsSigned, WideIVInfo &WI,
}
namespace {
+
+/// NarrowIVDefUse - Record a link in the Narrow IV def-use chain along with the
+/// WideIV that computes the same value as the Narrow IV def. This avoids
+/// caching Use* pointers.
+struct NarrowIVDefUse {
+ Instruction *NarrowDef;
+ Instruction *NarrowUse;
+ Instruction *WideDef;
+
+ NarrowIVDefUse(): NarrowDef(0), NarrowUse(0), WideDef(0) {}
+
+ NarrowIVDefUse(Instruction *ND, Instruction *NU, Instruction *WD):
+ NarrowDef(ND), NarrowUse(NU), WideDef(WD) {}
+};
+
/// WidenIV - The goal of this transform is to remove sign and zero extends
/// without creating any new induction variables. To do this, it creates a new
/// phi of the wider type and redirects all users, either removing extends or
@@ -787,7 +795,7 @@ namespace {
class WidenIV {
// Parameters
PHINode *OrigPhi;
- const Type *WideType;
+ Type *WideType;
bool IsSigned;
// Context
@@ -803,13 +811,13 @@ class WidenIV {
SmallVectorImpl<WeakVH> &DeadInsts;
SmallPtrSet<Instruction*,16> Widened;
- SmallVector<std::pair<Use *, Instruction *>, 8> NarrowIVUsers;
+ SmallVector<NarrowIVDefUse, 8> NarrowIVUsers;
public:
- WidenIV(PHINode *PN, const WideIVInfo &WI, LoopInfo *LInfo,
+ WidenIV(const WideIVInfo &WI, LoopInfo *LInfo,
ScalarEvolution *SEv, DominatorTree *DTree,
SmallVectorImpl<WeakVH> &DI) :
- OrigPhi(PN),
+ OrigPhi(WI.NarrowIV),
WideType(WI.WidestNativeType),
IsSigned(WI.IsSigned),
LI(LInfo),
@@ -826,21 +834,42 @@ public:
PHINode *CreateWideIV(SCEVExpander &Rewriter);
protected:
- Instruction *CloneIVUser(Instruction *NarrowUse,
- Instruction *NarrowDef,
- Instruction *WideDef);
+ Value *getExtend(Value *NarrowOper, Type *WideType, bool IsSigned,
+ Instruction *Use);
+
+ Instruction *CloneIVUser(NarrowIVDefUse DU);
const SCEVAddRecExpr *GetWideRecurrence(Instruction *NarrowUse);
- Instruction *WidenIVUse(Use &NarrowDefUse, Instruction *NarrowDef,
- Instruction *WideDef);
+ const SCEVAddRecExpr* GetExtendedOperandRecurrence(NarrowIVDefUse DU);
+
+ Instruction *WidenIVUse(NarrowIVDefUse DU);
void pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef);
};
} // anonymous namespace
-static Value *getExtend( Value *NarrowOper, const Type *WideType,
- bool IsSigned, IRBuilder<> &Builder) {
+/// isLoopInvariant - Perform a quick domtree based check for loop invariance
+/// assuming that V is used within the loop. LoopInfo::isLoopInvariant() seems
+/// gratuitous for this purpose.
+static bool isLoopInvariant(Value *V, const Loop *L, const DominatorTree *DT) {
+ Instruction *Inst = dyn_cast<Instruction>(V);
+ if (!Inst)
+ return true;
+
+ return DT->properlyDominates(Inst->getParent(), L->getHeader());
+}
+
+Value *WidenIV::getExtend(Value *NarrowOper, Type *WideType, bool IsSigned,
+ Instruction *Use) {
+ // Set the debug location and conservative insertion point.
+ IRBuilder<> Builder(Use);
+ // Hoist the insertion point into loop preheaders as far as possible.
+ for (const Loop *L = LI->getLoopFor(Use->getParent());
+ L && L->getLoopPreheader() && isLoopInvariant(NarrowOper, L, DT);
+ L = L->getParentLoop())
+ Builder.SetInsertPoint(L->getLoopPreheader()->getTerminator());
+
return IsSigned ? Builder.CreateSExt(NarrowOper, WideType) :
Builder.CreateZExt(NarrowOper, WideType);
}
@@ -848,10 +877,8 @@ static Value *getExtend( Value *NarrowOper, const Type *WideType,
/// CloneIVUser - Instantiate a wide operation to replace a narrow
/// operation. This only needs to handle operations that can evaluation to
/// SCEVAddRec. It can safely return 0 for any operation we decide not to clone.
-Instruction *WidenIV::CloneIVUser(Instruction *NarrowUse,
- Instruction *NarrowDef,
- Instruction *WideDef) {
- unsigned Opcode = NarrowUse->getOpcode();
+Instruction *WidenIV::CloneIVUser(NarrowIVDefUse DU) {
+ unsigned Opcode = DU.NarrowUse->getOpcode();
switch (Opcode) {
default:
return 0;
@@ -865,24 +892,23 @@ Instruction *WidenIV::CloneIVUser(Instruction *NarrowUse,
case Instruction::Shl:
case Instruction::LShr:
case Instruction::AShr:
- DEBUG(dbgs() << "Cloning IVUser: " << *NarrowUse << "\n");
-
- IRBuilder<> Builder(NarrowUse);
+ DEBUG(dbgs() << "Cloning IVUser: " << *DU.NarrowUse << "\n");
// Replace NarrowDef operands with WideDef. Otherwise, we don't know
// anything about the narrow operand yet so must insert a [sz]ext. It is
// probably loop invariant and will be folded or hoisted. If it actually
// comes from a widened IV, it should be removed during a future call to
// WidenIVUse.
- Value *LHS = (NarrowUse->getOperand(0) == NarrowDef) ? WideDef :
- getExtend(NarrowUse->getOperand(0), WideType, IsSigned, Builder);
- Value *RHS = (NarrowUse->getOperand(1) == NarrowDef) ? WideDef :
- getExtend(NarrowUse->getOperand(1), WideType, IsSigned, Builder);
+ Value *LHS = (DU.NarrowUse->getOperand(0) == DU.NarrowDef) ? DU.WideDef :
+ getExtend(DU.NarrowUse->getOperand(0), WideType, IsSigned, DU.NarrowUse);
+ Value *RHS = (DU.NarrowUse->getOperand(1) == DU.NarrowDef) ? DU.WideDef :
+ getExtend(DU.NarrowUse->getOperand(1), WideType, IsSigned, DU.NarrowUse);
- BinaryOperator *NarrowBO = cast<BinaryOperator>(NarrowUse);
+ BinaryOperator *NarrowBO = cast<BinaryOperator>(DU.NarrowUse);
BinaryOperator *WideBO = BinaryOperator::Create(NarrowBO->getOpcode(),
LHS, RHS,
NarrowBO->getName());
+ IRBuilder<> Builder(DU.NarrowUse);
Builder.Insert(WideBO);
if (const OverflowingBinaryOperator *OBO =
dyn_cast<OverflowingBinaryOperator>(NarrowBO)) {
@@ -894,45 +920,46 @@ Instruction *WidenIV::CloneIVUser(Instruction *NarrowUse,
llvm_unreachable(0);
}
-/// 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.
-static bool HoistStep(Instruction *IncV, Instruction *InsertPos,
- const DominatorTree *DT)
-{
- if (DT->dominates(IncV, InsertPos))
- return true;
+/// No-wrap operations can transfer sign extension of their result to their
+/// operands. Generate the SCEV value for the widened operation without
+/// actually modifying the IR yet. If the expression after extending the
+/// operands is an AddRec for this loop, return it.
+const SCEVAddRecExpr* WidenIV::GetExtendedOperandRecurrence(NarrowIVDefUse DU) {
+ // Handle the common case of add<nsw/nuw>
+ if (DU.NarrowUse->getOpcode() != Instruction::Add)
+ return 0;
- if (!DT->dominates(InsertPos->getParent(), IncV->getParent()))
- return false;
+ // One operand (NarrowDef) has already been extended to WideDef. Now determine
+ // if extending the other will lead to a recurrence.
+ unsigned ExtendOperIdx = DU.NarrowUse->getOperand(0) == DU.NarrowDef ? 1 : 0;
+ assert(DU.NarrowUse->getOperand(1-ExtendOperIdx) == DU.NarrowDef && "bad DU");
+
+ const SCEV *ExtendOperExpr = 0;
+ const OverflowingBinaryOperator *OBO =
+ cast<OverflowingBinaryOperator>(DU.NarrowUse);
+ if (IsSigned && OBO->hasNoSignedWrap())
+ ExtendOperExpr = SE->getSignExtendExpr(
+ SE->getSCEV(DU.NarrowUse->getOperand(ExtendOperIdx)), WideType);
+ else if(!IsSigned && OBO->hasNoUnsignedWrap())
+ ExtendOperExpr = SE->getZeroExtendExpr(
+ SE->getSCEV(DU.NarrowUse->getOperand(ExtendOperIdx)), WideType);
+ else
+ return 0;
- if (IncV->mayHaveSideEffects())
- return false;
+ const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(
+ SE->getAddExpr(SE->getSCEV(DU.WideDef), ExtendOperExpr,
+ IsSigned ? SCEV::FlagNSW : SCEV::FlagNUW));
- // Attempt to hoist IncV
- for (User::op_iterator OI = IncV->op_begin(), OE = IncV->op_end();
- OI != OE; ++OI) {
- Instruction *OInst = dyn_cast<Instruction>(OI);
- if (OInst && !DT->dominates(OInst, InsertPos))
- return false;
- }
- IncV->moveBefore(InsertPos);
- return true;
+ if (!AddRec || AddRec->getLoop() != L)
+ return 0;
+ return AddRec;
}
-// GetWideRecurrence - Is this instruction potentially interesting from IVUsers'
-// perspective after widening it's type? In other words, can the extend be
-// safely hoisted out of the loop with SCEV reducing the value to a recurrence
-// on the same loop. If so, return the sign or zero extended
-// recurrence. Otherwise return NULL.
+/// GetWideRecurrence - Is this instruction potentially interesting from
+/// IVUsers' perspective after widening it's type? In other words, can the
+/// extend be safely hoisted out of the loop with SCEV reducing the value to a
+/// recurrence on the same loop. If so, return the sign or zero extended
+/// recurrence. Otherwise return NULL.
const SCEVAddRecExpr *WidenIV::GetWideRecurrence(Instruction *NarrowUse) {
if (!SE->isSCEVable(NarrowUse->getType()))
return 0;
@@ -951,47 +978,45 @@ const SCEVAddRecExpr *WidenIV::GetWideRecurrence(Instruction *NarrowUse) {
const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(WideExpr);
if (!AddRec || AddRec->getLoop() != L)
return 0;
-
return AddRec;
}
/// WidenIVUse - Determine whether an individual user of the narrow IV can be
/// widened. If so, return the wide clone of the user.
-Instruction *WidenIV::WidenIVUse(Use &NarrowDefUse, Instruction *NarrowDef,
- Instruction *WideDef) {
- Instruction *NarrowUse = cast<Instruction>(NarrowDefUse.getUser());
+Instruction *WidenIV::WidenIVUse(NarrowIVDefUse DU) {
// Stop traversing the def-use chain at inner-loop phis or post-loop phis.
- if (isa<PHINode>(NarrowUse) && LI->getLoopFor(NarrowUse->getParent()) != L)
+ if (isa<PHINode>(DU.NarrowUse) &&
+ LI->getLoopFor(DU.NarrowUse->getParent()) != L)
return 0;
// Our raison d'etre! Eliminate sign and zero extension.
- if (IsSigned ? isa<SExtInst>(NarrowUse) : isa<ZExtInst>(NarrowUse)) {
- Value *NewDef = WideDef;
- if (NarrowUse->getType() != WideType) {
- unsigned CastWidth = SE->getTypeSizeInBits(NarrowUse->getType());
+ if (IsSigned ? isa<SExtInst>(DU.NarrowUse) : isa<ZExtInst>(DU.NarrowUse)) {
+ Value *NewDef = DU.WideDef;
+ if (DU.NarrowUse->getType() != WideType) {
+ unsigned CastWidth = SE->getTypeSizeInBits(DU.NarrowUse->getType());
unsigned IVWidth = SE->getTypeSizeInBits(WideType);
if (CastWidth < IVWidth) {
// The cast isn't as wide as the IV, so insert a Trunc.
- IRBuilder<> Builder(NarrowDefUse);
- NewDef = Builder.CreateTrunc(WideDef, NarrowUse->getType());
+ IRBuilder<> Builder(DU.NarrowUse);
+ NewDef = Builder.CreateTrunc(DU.WideDef, DU.NarrowUse->getType());
}
else {
// A wider extend was hidden behind a narrower one. This may induce
// another round of IV widening in which the intermediate IV becomes
// dead. It should be very rare.
DEBUG(dbgs() << "INDVARS: New IV " << *WidePhi
- << " not wide enough to subsume " << *NarrowUse << "\n");
- NarrowUse->replaceUsesOfWith(NarrowDef, WideDef);
- NewDef = NarrowUse;
+ << " not wide enough to subsume " << *DU.NarrowUse << "\n");
+ DU.NarrowUse->replaceUsesOfWith(DU.NarrowDef, DU.WideDef);
+ NewDef = DU.NarrowUse;
}
}
- if (NewDef != NarrowUse) {
- DEBUG(dbgs() << "INDVARS: eliminating " << *NarrowUse
- << " replaced by " << *WideDef << "\n");
+ if (NewDef != DU.NarrowUse) {
+ DEBUG(dbgs() << "INDVARS: eliminating " << *DU.NarrowUse
+ << " replaced by " << *DU.WideDef << "\n");
++NumElimExt;
- NarrowUse->replaceAllUsesWith(NewDef);
- DeadInsts.push_back(NarrowUse);
+ DU.NarrowUse->replaceAllUsesWith(NewDef);
+ DeadInsts.push_back(DU.NarrowUse);
}
// Now that the extend is gone, we want to expose it's uses for potential
// further simplification. We don't need to directly inform SimplifyIVUsers
@@ -1004,29 +1029,32 @@ Instruction *WidenIV::WidenIVUse(Use &NarrowDefUse, Instruction *NarrowDef,
}
// Does this user itself evaluate to a recurrence after widening?
- const SCEVAddRecExpr *WideAddRec = GetWideRecurrence(NarrowUse);
+ const SCEVAddRecExpr *WideAddRec = GetWideRecurrence(DU.NarrowUse);
+ if (!WideAddRec) {
+ WideAddRec = GetExtendedOperandRecurrence(DU);
+ }
if (!WideAddRec) {
// This user does not evaluate to a recurence after widening, so don't
// follow it. Instead insert a Trunc to kill off the original use,
// eventually isolating the original narrow IV so it can be removed.
- IRBuilder<> Builder(NarrowDefUse);
- Value *Trunc = Builder.CreateTrunc(WideDef, NarrowDef->getType());
- NarrowUse->replaceUsesOfWith(NarrowDef, Trunc);
+ IRBuilder<> Builder(getInsertPointForUses(DU.NarrowUse, DU.NarrowDef, DT));
+ Value *Trunc = Builder.CreateTrunc(DU.WideDef, DU.NarrowDef->getType());
+ DU.NarrowUse->replaceUsesOfWith(DU.NarrowDef, Trunc);
return 0;
}
- // We assume that block terminators are not SCEVable. We wouldn't want to
+ // Assume block terminators cannot evaluate to a recurrence. We can't to
// insert a Trunc after a terminator if there happens to be a critical edge.
- assert(NarrowUse != NarrowUse->getParent()->getTerminator() &&
+ assert(DU.NarrowUse != DU.NarrowUse->getParent()->getTerminator() &&
"SCEV is not expected to evaluate a block terminator");
// Reuse the IV increment that SCEVExpander created as long as it dominates
// NarrowUse.
Instruction *WideUse = 0;
- if (WideAddRec == WideIncExpr && HoistStep(WideInc, NarrowUse, DT)) {
+ if (WideAddRec == WideIncExpr
+ && SCEVExpander::hoistStep(WideInc, DU.NarrowUse, DT))
WideUse = WideInc;
- }
else {
- WideUse = CloneIVUser(NarrowUse, NarrowDef, WideDef);
+ WideUse = CloneIVUser(DU);
if (!WideUse)
return 0;
}
@@ -1051,13 +1079,13 @@ Instruction *WidenIV::WidenIVUse(Use &NarrowDefUse, Instruction *NarrowDef,
void WidenIV::pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef) {
for (Value::use_iterator UI = NarrowDef->use_begin(),
UE = NarrowDef->use_end(); UI != UE; ++UI) {
- Use &U = UI.getUse();
+ Instruction *NarrowUse = cast<Instruction>(*UI);
// Handle data flow merges and bizarre phi cycles.
- if (!Widened.insert(cast<Instruction>(U.getUser())))
+ if (!Widened.insert(NarrowUse))
continue;
- NarrowIVUsers.push_back(std::make_pair(&UI.getUse(), WideDef));
+ NarrowIVUsers.push_back(NarrowIVDefUse(NarrowDef, NarrowUse, WideDef));
}
}
@@ -1124,23 +1152,19 @@ PHINode *WidenIV::CreateWideIV(SCEVExpander &Rewriter) {
pushNarrowIVUsers(OrigPhi, WidePhi);
while (!NarrowIVUsers.empty()) {
- Use *UsePtr;
- Instruction *WideDef;
- tie(UsePtr, WideDef) = NarrowIVUsers.pop_back_val();
- Use &NarrowDefUse = *UsePtr;
+ NarrowIVDefUse DU = NarrowIVUsers.pop_back_val();
// Process a def-use edge. This may replace the use, so don't hold a
// use_iterator across it.
- Instruction *NarrowDef = cast<Instruction>(NarrowDefUse.get());
- Instruction *WideUse = WidenIVUse(NarrowDefUse, NarrowDef, WideDef);
+ Instruction *WideUse = WidenIVUse(DU);
// Follow all def-use edges from the previous narrow use.
if (WideUse)
- pushNarrowIVUsers(cast<Instruction>(NarrowDefUse.getUser()), WideUse);
+ pushNarrowIVUsers(DU.NarrowUse, WideUse);
// WidenIVUse may have removed the def-use edge.
- if (NarrowDef->use_empty())
- DeadInsts.push_back(NarrowDef);
+ if (DU.NarrowDef->use_empty())
+ DeadInsts.push_back(DU.NarrowDef);
}
return WidePhi;
}
@@ -1149,187 +1173,17 @@ PHINode *WidenIV::CreateWideIV(SCEVExpander &Rewriter) {
// Simplification of IV users based on SCEV evaluation.
//===----------------------------------------------------------------------===//
-void IndVarSimplify::EliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) {
- unsigned IVOperIdx = 0;
- ICmpInst::Predicate Pred = ICmp->getPredicate();
- if (IVOperand != ICmp->getOperand(0)) {
- // Swapped
- assert(IVOperand == ICmp->getOperand(1) && "Can't find IVOperand");
- IVOperIdx = 1;
- Pred = ICmpInst::getSwappedPredicate(Pred);
- }
-
- // Get the SCEVs for the ICmp operands.
- const SCEV *S = SE->getSCEV(ICmp->getOperand(IVOperIdx));
- const SCEV *X = SE->getSCEV(ICmp->getOperand(1 - IVOperIdx));
-
- // Simplify unnecessary loops away.
- const Loop *ICmpLoop = LI->getLoopFor(ICmp->getParent());
- S = SE->getSCEVAtScope(S, ICmpLoop);
- X = SE->getSCEVAtScope(X, ICmpLoop);
-
- // If the condition is always true or always false, replace it with
- // a constant value.
- if (SE->isKnownPredicate(Pred, S, X))
- ICmp->replaceAllUsesWith(ConstantInt::getTrue(ICmp->getContext()));
- else if (SE->isKnownPredicate(ICmpInst::getInversePredicate(Pred), S, X))
- ICmp->replaceAllUsesWith(ConstantInt::getFalse(ICmp->getContext()));
- else
- return;
-
- DEBUG(dbgs() << "INDVARS: Eliminated comparison: " << *ICmp << '\n');
- ++NumElimCmp;
- Changed = true;
- DeadInsts.push_back(ICmp);
-}
-
-void IndVarSimplify::EliminateIVRemainder(BinaryOperator *Rem,
- Value *IVOperand,
- bool IsSigned) {
- // We're only interested in the case where we know something about
- // the numerator.
- if (IVOperand != Rem->getOperand(0))
- return;
-
- // Get the SCEVs for the ICmp operands.
- const SCEV *S = SE->getSCEV(Rem->getOperand(0));
- const SCEV *X = SE->getSCEV(Rem->getOperand(1));
-
- // Simplify unnecessary loops away.
- const Loop *ICmpLoop = LI->getLoopFor(Rem->getParent());
- S = SE->getSCEVAtScope(S, ICmpLoop);
- X = SE->getSCEVAtScope(X, ICmpLoop);
-
- // i % n --> i if i is in [0,n).
- if ((!IsSigned || SE->isKnownNonNegative(S)) &&
- SE->isKnownPredicate(IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
- S, X))
- Rem->replaceAllUsesWith(Rem->getOperand(0));
- else {
- // (i+1) % n --> (i+1)==n?0:(i+1) if i is in [0,n).
- const SCEV *LessOne =
- SE->getMinusSCEV(S, SE->getConstant(S->getType(), 1));
- if (IsSigned && !SE->isKnownNonNegative(LessOne))
- return;
-
- if (!SE->isKnownPredicate(IsSigned ?
- ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
- LessOne, X))
- return;
-
- ICmpInst *ICmp = new ICmpInst(Rem, ICmpInst::ICMP_EQ,
- Rem->getOperand(0), Rem->getOperand(1),
- "tmp");
- SelectInst *Sel =
- SelectInst::Create(ICmp,
- ConstantInt::get(Rem->getType(), 0),
- Rem->getOperand(0), "tmp", Rem);
- Rem->replaceAllUsesWith(Sel);
- }
-
- // Inform IVUsers about the new users.
- if (IU) {
- if (Instruction *I = dyn_cast<Instruction>(Rem->getOperand(0)))
- IU->AddUsersIfInteresting(I);
- }
- DEBUG(dbgs() << "INDVARS: Simplified rem: " << *Rem << '\n');
- ++NumElimRem;
- Changed = true;
- DeadInsts.push_back(Rem);
-}
-
-/// EliminateIVUser - Eliminate an operation that consumes a simple IV and has
-/// no observable side-effect given the range of IV values.
-bool IndVarSimplify::EliminateIVUser(Instruction *UseInst,
- Instruction *IVOperand) {
- if (ICmpInst *ICmp = dyn_cast<ICmpInst>(UseInst)) {
- EliminateIVComparison(ICmp, IVOperand);
- return true;
- }
- if (BinaryOperator *Rem = dyn_cast<BinaryOperator>(UseInst)) {
- bool IsSigned = Rem->getOpcode() == Instruction::SRem;
- if (IsSigned || Rem->getOpcode() == Instruction::URem) {
- EliminateIVRemainder(Rem, IVOperand, IsSigned);
- return true;
- }
- }
-
- // Eliminate any operation that SCEV can prove is an identity function.
- if (!SE->isSCEVable(UseInst->getType()) ||
- (UseInst->getType() != IVOperand->getType()) ||
- (SE->getSCEV(UseInst) != SE->getSCEV(IVOperand)))
- return false;
-
- DEBUG(dbgs() << "INDVARS: Eliminated identity: " << *UseInst << '\n');
-
- UseInst->replaceAllUsesWith(IVOperand);
- ++NumElimIdentity;
- Changed = true;
- DeadInsts.push_back(UseInst);
- return true;
-}
-
-/// pushIVUsers - Add all uses of Def to the current IV's worklist.
-///
-static void pushIVUsers(
- Instruction *Def,
- SmallPtrSet<Instruction*,16> &Simplified,
- SmallVectorImpl< std::pair<Instruction*,Instruction*> > &SimpleIVUsers) {
-
- for (Value::use_iterator UI = Def->use_begin(), E = Def->use_end();
- UI != E; ++UI) {
- Instruction *User = cast<Instruction>(*UI);
-
- // Avoid infinite or exponential worklist processing.
- // Also ensure unique worklist users.
- // If Def is a LoopPhi, it may not be in the Simplified set, so check for
- // self edges first.
- if (User != Def && Simplified.insert(User))
- SimpleIVUsers.push_back(std::make_pair(User, Def));
- }
-}
-
-/// isSimpleIVUser - Return true if this instruction generates a simple SCEV
-/// expression in terms of that IV.
-///
-/// This is similar to IVUsers' isInsteresting() but processes each instruction
-/// non-recursively when the operand is already known to be a simpleIVUser.
-///
-static bool isSimpleIVUser(Instruction *I, const Loop *L, ScalarEvolution *SE) {
- if (!SE->isSCEVable(I->getType()))
- return false;
-
- // Get the symbolic expression for this instruction.
- const SCEV *S = SE->getSCEV(I);
-
- // We assume that terminators are not SCEVable.
- assert((!S || I != I->getParent()->getTerminator()) &&
- "can't fold terminators");
-
- // Only consider affine recurrences.
- const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S);
- if (AR && AR->getLoop() == L)
- return true;
-
- return false;
-}
-/// SimplifyIVUsersNoRewrite - Iteratively perform simplification on a worklist
-/// of IV users. Each successive simplification may push more users which may
+/// SimplifyAndExtend - Iteratively perform simplification on a worklist of IV
+/// users. Each successive simplification may push more users which may
/// themselves be candidates for simplification.
///
-/// The "NoRewrite" algorithm does not require IVUsers analysis. Instead, it
-/// simplifies instructions in-place during analysis. Rather than rewriting
-/// induction variables bottom-up from their users, it transforms a chain of
-/// IVUsers top-down, updating the IR only when it encouters a clear
-/// optimization opportunitiy. A SCEVExpander "Rewriter" instance is still
-/// needed, but only used to generate a new IV (phi) of wider type for sign/zero
-/// extend elimination.
+/// Sign/Zero extend elimination is interleaved with IV simplification.
///
-/// Once DisableIVRewrite is default, LSR will be the only client of IVUsers.
-///
-void IndVarSimplify::SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander &Rewriter) {
- std::map<PHINode *, WideIVInfo> WideIVMap;
+void IndVarSimplify::SimplifyAndExtend(Loop *L,
+ SCEVExpander &Rewriter,
+ LPPassManager &LPM) {
+ SmallVector<WideIVInfo, 8> WideIVs;
SmallVector<PHINode*, 8> LoopPhis;
for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) {
@@ -1345,108 +1199,81 @@ void IndVarSimplify::SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander &Rewriter) {
// extension. The first time SCEV attempts to normalize sign/zero extension,
// the result becomes final. So for the most predictable results, we delay
// evaluation of sign/zero extend evaluation until needed, and avoid running
- // other SCEV based analysis prior to SimplifyIVUsersNoRewrite.
+ // other SCEV based analysis prior to SimplifyAndExtend.
do {
PHINode *CurrIV = LoopPhis.pop_back_val();
// Information about sign/zero extensions of CurrIV.
- WideIVInfo WI;
-
- // Instructions processed by SimplifyIVUsers for CurrIV.
- SmallPtrSet<Instruction*,16> Simplified;
-
- // Use-def pairs if IV users waiting to be processed for CurrIV.
- SmallVector<std::pair<Instruction*, Instruction*>, 8> SimpleIVUsers;
-
- // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
- // called multiple times for the same LoopPhi. This is the proper thing to
- // do for loop header phis that use each other.
- pushIVUsers(CurrIV, Simplified, SimpleIVUsers);
+ WideIVVisitor WIV(CurrIV, SE, TD);
- while (!SimpleIVUsers.empty()) {
- Instruction *UseInst, *Operand;
- tie(UseInst, Operand) = SimpleIVUsers.pop_back_val();
- // Bypass back edges to avoid extra work.
- if (UseInst == CurrIV) continue;
+ Changed |= simplifyUsersOfIV(CurrIV, SE, &LPM, DeadInsts, &WIV);
- if (EliminateIVUser(UseInst, Operand)) {
- pushIVUsers(Operand, Simplified, SimpleIVUsers);
- continue;
- }
- if (CastInst *Cast = dyn_cast<CastInst>(UseInst)) {
- bool IsSigned = Cast->getOpcode() == Instruction::SExt;
- if (IsSigned || Cast->getOpcode() == Instruction::ZExt) {
- CollectExtend(Cast, IsSigned, WI, SE, TD);
- }
- continue;
- }
- if (isSimpleIVUser(UseInst, L, SE)) {
- pushIVUsers(UseInst, Simplified, SimpleIVUsers);
- }
- }
- if (WI.WidestNativeType) {
- WideIVMap[CurrIV] = WI;
+ if (WIV.WI.WidestNativeType) {
+ WideIVs.push_back(WIV.WI);
}
} while(!LoopPhis.empty());
- for (std::map<PHINode *, WideIVInfo>::const_iterator I = WideIVMap.begin(),
- E = WideIVMap.end(); I != E; ++I) {
- WidenIV Widener(I->first, I->second, LI, SE, DT, DeadInsts);
+ for (; !WideIVs.empty(); WideIVs.pop_back()) {
+ WidenIV Widener(WideIVs.back(), LI, SE, DT, DeadInsts);
if (PHINode *WidePhi = Widener.CreateWideIV(Rewriter)) {
Changed = true;
LoopPhis.push_back(WidePhi);
}
}
- WideIVMap.clear();
}
}
-/// SimplifyCongruentIVs - Check for congruent phis in this loop header and
-/// populate ExprToIVMap for use later.
-///
-void IndVarSimplify::SimplifyCongruentIVs(Loop *L) {
- DenseMap<const SCEV *, PHINode *> ExprToIVMap;
- for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) {
- PHINode *Phi = cast<PHINode>(I);
- if (!SE->isSCEVable(Phi->getType()))
- continue;
+//===----------------------------------------------------------------------===//
+// LinearFunctionTestReplace and its kin. Rewrite the loop exit condition.
+//===----------------------------------------------------------------------===//
- const SCEV *S = SE->getSCEV(Phi);
- DenseMap<const SCEV *, PHINode *>::const_iterator Pos;
- bool Inserted;
- tie(Pos, Inserted) = ExprToIVMap.insert(std::make_pair(S, Phi));
- if (Inserted)
- continue;
- PHINode *OrigPhi = Pos->second;
- // 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 almost certain to be 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 (BasicBlock *LatchBlock = L->getLoopLatch()) {
- Instruction *OrigInc =
- cast<Instruction>(OrigPhi->getIncomingValueForBlock(LatchBlock));
- Instruction *IsomorphicInc =
- cast<Instruction>(Phi->getIncomingValueForBlock(LatchBlock));
- if (OrigInc != IsomorphicInc &&
- SE->getSCEV(OrigInc) == SE->getSCEV(IsomorphicInc) &&
- HoistStep(OrigInc, IsomorphicInc, DT)) {
- DEBUG(dbgs() << "INDVARS: Eliminated congruent iv.inc: "
- << *IsomorphicInc << '\n');
- IsomorphicInc->replaceAllUsesWith(OrigInc);
- DeadInsts.push_back(IsomorphicInc);
- }
+/// Check for expressions that ScalarEvolution generates to compute
+/// BackedgeTakenInfo. If these expressions have not been reduced, then
+/// expanding them may incur additional cost (albeit in the loop preheader).
+static bool isHighCostExpansion(const SCEV *S, BranchInst *BI,
+ ScalarEvolution *SE) {
+ // If the backedge-taken count is a UDiv, it's very likely a UDiv that
+ // ScalarEvolution's HowFarToZero or HowManyLessThans produced to compute a
+ // precise expression, rather than a UDiv from the user's code. If we can't
+ // find a UDiv in the code with some simple searching, assume the former and
+ // forego rewriting the loop.
+ if (isa<SCEVUDivExpr>(S)) {
+ ICmpInst *OrigCond = dyn_cast<ICmpInst>(BI->getCondition());
+ if (!OrigCond) return true;
+ const SCEV *R = SE->getSCEV(OrigCond->getOperand(1));
+ R = SE->getMinusSCEV(R, SE->getConstant(R->getType(), 1));
+ if (R != S) {
+ const SCEV *L = SE->getSCEV(OrigCond->getOperand(0));
+ L = SE->getMinusSCEV(L, SE->getConstant(L->getType(), 1));
+ if (L != S)
+ return true;
}
- DEBUG(dbgs() << "INDVARS: Eliminated congruent iv: " << *Phi << '\n');
- ++NumElimIV;
- Phi->replaceAllUsesWith(OrigPhi);
- DeadInsts.push_back(Phi);
}
-}
-//===----------------------------------------------------------------------===//
-// LinearFunctionTestReplace and its kin. Rewrite the loop exit condition.
-//===----------------------------------------------------------------------===//
+ if (EnableIVRewrite)
+ return false;
+
+ // Recurse past add expressions, which commonly occur in the
+ // BackedgeTakenCount. They may already exist in program code, and if not,
+ // they are not too expensive rematerialize.
+ if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
+ for (SCEVAddExpr::op_iterator I = Add->op_begin(), E = Add->op_end();
+ I != E; ++I) {
+ if (isHighCostExpansion(*I, BI, SE))
+ return true;
+ }
+ return false;
+ }
+
+ // HowManyLessThans uses a Max expression whenever the loop is not guarded by
+ // the exit condition.
+ if (isa<SCEVSMaxExpr>(S) || isa<SCEVUMaxExpr>(S))
+ return true;
+
+ // If we haven't recognized an expensive SCEV patter, assume its an expression
+ // produced by program code.
+ return false;
+}
/// canExpandBackedgeTakenCount - Return true if this loop's backedge taken
/// count expression can be safely and cheaply expanded into an instruction
@@ -1465,31 +1292,17 @@ static bool canExpandBackedgeTakenCount(Loop *L, ScalarEvolution *SE) {
if (!BI)
return false;
- // Special case: If the backedge-taken count is a UDiv, it's very likely a
- // UDiv that ScalarEvolution produced in order to compute a precise
- // expression, rather than a UDiv from the user's code. If we can't find a
- // UDiv in the code with some simple searching, assume the former and forego
- // rewriting the loop.
- if (isa<SCEVUDivExpr>(BackedgeTakenCount)) {
- ICmpInst *OrigCond = dyn_cast<ICmpInst>(BI->getCondition());
- if (!OrigCond) return false;
- const SCEV *R = SE->getSCEV(OrigCond->getOperand(1));
- R = SE->getMinusSCEV(R, SE->getConstant(R->getType(), 1));
- if (R != BackedgeTakenCount) {
- const SCEV *L = SE->getSCEV(OrigCond->getOperand(0));
- L = SE->getMinusSCEV(L, SE->getConstant(L->getType(), 1));
- if (L != BackedgeTakenCount)
- return false;
- }
- }
+ if (isHighCostExpansion(BackedgeTakenCount, BI, SE))
+ return false;
+
return true;
}
/// getBackedgeIVType - Get the widest type used by the loop test after peeking
/// through Truncs.
///
-/// TODO: Unnecessary if LFTR does not force a canonical IV.
-static const Type *getBackedgeIVType(Loop *L) {
+/// TODO: Unnecessary when ForceLFTR is removed.
+static Type *getBackedgeIVType(Loop *L) {
if (!L->getExitingBlock())
return 0;
@@ -1502,7 +1315,7 @@ static const Type *getBackedgeIVType(Loop *L) {
if (!Cond)
return 0;
- const Type *Ty = 0;
+ Type *Ty = 0;
for(User::op_iterator OI = Cond->op_begin(), OE = Cond->op_end();
OI != OE; ++OI) {
assert((!Ty || Ty == (*OI)->getType()) && "bad icmp operand types");
@@ -1515,12 +1328,187 @@ static const Type *getBackedgeIVType(Loop *L) {
return Ty;
}
+/// getLoopPhiForCounter - Return the loop header phi IFF IncV adds a loop
+/// invariant value to the phi.
+static PHINode *getLoopPhiForCounter(Value *IncV, Loop *L, DominatorTree *DT) {
+ Instruction *IncI = dyn_cast<Instruction>(IncV);
+ if (!IncI)
+ return 0;
+
+ switch (IncI->getOpcode()) {
+ case Instruction::Add:
+ case Instruction::Sub:
+ break;
+ case Instruction::GetElementPtr:
+ // An IV counter must preserve its type.
+ if (IncI->getNumOperands() == 2)
+ break;
+ default:
+ return 0;
+ }
+
+ PHINode *Phi = dyn_cast<PHINode>(IncI->getOperand(0));
+ if (Phi && Phi->getParent() == L->getHeader()) {
+ if (isLoopInvariant(IncI->getOperand(1), L, DT))
+ return Phi;
+ return 0;
+ }
+ if (IncI->getOpcode() == Instruction::GetElementPtr)
+ return 0;
+
+ // Allow add/sub to be commuted.
+ Phi = dyn_cast<PHINode>(IncI->getOperand(1));
+ if (Phi && Phi->getParent() == L->getHeader()) {
+ if (isLoopInvariant(IncI->getOperand(0), L, DT))
+ return Phi;
+ }
+ return 0;
+}
+
+/// needsLFTR - LinearFunctionTestReplace policy. Return true unless we can show
+/// that the current exit test is already sufficiently canonical.
+static bool needsLFTR(Loop *L, DominatorTree *DT) {
+ assert(L->getExitingBlock() && "expected loop exit");
+
+ BasicBlock *LatchBlock = L->getLoopLatch();
+ // Don't bother with LFTR if the loop is not properly simplified.
+ if (!LatchBlock)
+ return false;
+
+ BranchInst *BI = dyn_cast<BranchInst>(L->getExitingBlock()->getTerminator());
+ assert(BI && "expected exit branch");
+
+ // Do LFTR to simplify the exit condition to an ICMP.
+ ICmpInst *Cond = dyn_cast<ICmpInst>(BI->getCondition());
+ if (!Cond)
+ return true;
+
+ // Do LFTR to simplify the exit ICMP to EQ/NE
+ ICmpInst::Predicate Pred = Cond->getPredicate();
+ if (Pred != ICmpInst::ICMP_NE && Pred != ICmpInst::ICMP_EQ)
+ return true;
+
+ // Look for a loop invariant RHS
+ Value *LHS = Cond->getOperand(0);
+ Value *RHS = Cond->getOperand(1);
+ if (!isLoopInvariant(RHS, L, DT)) {
+ if (!isLoopInvariant(LHS, L, DT))
+ return true;
+ std::swap(LHS, RHS);
+ }
+ // Look for a simple IV counter LHS
+ PHINode *Phi = dyn_cast<PHINode>(LHS);
+ if (!Phi)
+ Phi = getLoopPhiForCounter(LHS, L, DT);
+
+ if (!Phi)
+ return true;
+
+ // Do LFTR if the exit condition's IV is *not* a simple counter.
+ Value *IncV = Phi->getIncomingValueForBlock(L->getLoopLatch());
+ return Phi != getLoopPhiForCounter(IncV, L, DT);
+}
+
+/// AlmostDeadIV - Return true if this IV has any uses other than the (soon to
+/// be rewritten) loop exit test.
+static bool AlmostDeadIV(PHINode *Phi, BasicBlock *LatchBlock, Value *Cond) {
+ int LatchIdx = Phi->getBasicBlockIndex(LatchBlock);
+ Value *IncV = Phi->getIncomingValue(LatchIdx);
+
+ for (Value::use_iterator UI = Phi->use_begin(), UE = Phi->use_end();
+ UI != UE; ++UI) {
+ if (*UI != Cond && *UI != IncV) return false;
+ }
+
+ for (Value::use_iterator UI = IncV->use_begin(), UE = IncV->use_end();
+ UI != UE; ++UI) {
+ if (*UI != Cond && *UI != Phi) return false;
+ }
+ return true;
+}
+
+/// FindLoopCounter - Find an affine IV in canonical form.
+///
+/// FIXME: Accept -1 stride and set IVLimit = IVInit - BECount
+///
+/// FIXME: Accept non-unit stride as long as SCEV can reduce BECount * Stride.
+/// This is difficult in general for SCEV because of potential overflow. But we
+/// could at least handle constant BECounts.
+static PHINode *
+FindLoopCounter(Loop *L, const SCEV *BECount,
+ ScalarEvolution *SE, DominatorTree *DT, const TargetData *TD) {
+ // I'm not sure how BECount could be a pointer type, but we definitely don't
+ // want to LFTR that.
+ if (BECount->getType()->isPointerTy())
+ return 0;
+
+ uint64_t BCWidth = SE->getTypeSizeInBits(BECount->getType());
+
+ Value *Cond =
+ cast<BranchInst>(L->getExitingBlock()->getTerminator())->getCondition();
+
+ // Loop over all of the PHI nodes, looking for a simple counter.
+ PHINode *BestPhi = 0;
+ const SCEV *BestInit = 0;
+ BasicBlock *LatchBlock = L->getLoopLatch();
+ assert(LatchBlock && "needsLFTR should guarantee a loop latch");
+
+ for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) {
+ PHINode *Phi = cast<PHINode>(I);
+ if (!SE->isSCEVable(Phi->getType()))
+ continue;
+
+ const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(SE->getSCEV(Phi));
+ if (!AR || AR->getLoop() != L || !AR->isAffine())
+ continue;
+
+ // AR may be a pointer type, while BECount is an integer type.
+ // AR may be wider than BECount. With eq/ne tests overflow is immaterial.
+ // AR may not be a narrower type, or we may never exit.
+ uint64_t PhiWidth = SE->getTypeSizeInBits(AR->getType());
+ if (PhiWidth < BCWidth || (TD && !TD->isLegalInteger(PhiWidth)))
+ continue;
+
+ const SCEV *Step = dyn_cast<SCEVConstant>(AR->getStepRecurrence(*SE));
+ if (!Step || !Step->isOne())
+ continue;
+
+ int LatchIdx = Phi->getBasicBlockIndex(LatchBlock);
+ Value *IncV = Phi->getIncomingValue(LatchIdx);
+ if (getLoopPhiForCounter(IncV, L, DT) != Phi)
+ continue;
+
+ const SCEV *Init = AR->getStart();
+
+ if (BestPhi && !AlmostDeadIV(BestPhi, LatchBlock, Cond)) {
+ // Don't force a live loop counter if another IV can be used.
+ if (AlmostDeadIV(Phi, LatchBlock, Cond))
+ continue;
+
+ // Prefer to count-from-zero. This is a more "canonical" counter form. It
+ // also prefers integer to pointer IVs.
+ if (BestInit->isZero() != Init->isZero()) {
+ if (BestInit->isZero())
+ continue;
+ }
+ // If two IVs both count from zero or both count from nonzero then the
+ // narrower is likely a dead phi that has been widened. Use the wider phi
+ // to allow the other to be eliminated.
+ if (PhiWidth <= SE->getTypeSizeInBits(BestPhi->getType()))
+ continue;
+ }
+ BestPhi = Phi;
+ BestInit = Init;
+ }
+ return BestPhi;
+}
+
/// LinearFunctionTestReplace - This method rewrites the exit condition of the
/// loop to be a canonical != comparison against the incremented loop induction
/// variable. This pass is able to rewrite the exit tests of any loop where the
/// SCEV analysis can determine a loop-invariant trip count of the loop, which
/// is actually a much broader range than just linear tests.
-ICmpInst *IndVarSimplify::
+Value *IndVarSimplify::
LinearFunctionTestReplace(Loop *L,
const SCEV *BackedgeTakenCount,
PHINode *IndVar,
@@ -1528,62 +1516,117 @@ LinearFunctionTestReplace(Loop *L,
assert(canExpandBackedgeTakenCount(L, SE) && "precondition");
BranchInst *BI = cast<BranchInst>(L->getExitingBlock()->getTerminator());
+ // LFTR can ignore IV overflow and truncate to the width of
+ // BECount. This avoids materializing the add(zext(add)) expression.
+ Type *CntTy = !EnableIVRewrite ?
+ BackedgeTakenCount->getType() : IndVar->getType();
+
+ const SCEV *IVLimit = BackedgeTakenCount;
+
// If the exiting block is not the same as the backedge block, we must compare
// against the preincremented value, otherwise we prefer to compare against
// the post-incremented value.
Value *CmpIndVar;
- const SCEV *RHS = BackedgeTakenCount;
if (L->getExitingBlock() == L->getLoopLatch()) {
// Add one to the "backedge-taken" count to get the trip count.
// If this addition may overflow, we have to be more pessimistic and
// cast the induction variable before doing the add.
- const SCEV *Zero = SE->getConstant(BackedgeTakenCount->getType(), 0);
const SCEV *N =
- SE->getAddExpr(BackedgeTakenCount,
- SE->getConstant(BackedgeTakenCount->getType(), 1));
- if ((isa<SCEVConstant>(N) && !N->isZero()) ||
- SE->isLoopEntryGuardedByCond(L, ICmpInst::ICMP_NE, N, Zero)) {
- // No overflow. Cast the sum.
- RHS = SE->getTruncateOrZeroExtend(N, IndVar->getType());
- } else {
- // Potential overflow. Cast before doing the add.
- RHS = SE->getTruncateOrZeroExtend(BackedgeTakenCount,
- IndVar->getType());
- RHS = SE->getAddExpr(RHS,
- SE->getConstant(IndVar->getType(), 1));
+ SE->getAddExpr(IVLimit, SE->getConstant(IVLimit->getType(), 1));
+ if (CntTy == IVLimit->getType())
+ IVLimit = N;
+ else {
+ const SCEV *Zero = SE->getConstant(IVLimit->getType(), 0);
+ if ((isa<SCEVConstant>(N) && !N->isZero()) ||
+ SE->isLoopEntryGuardedByCond(L, ICmpInst::ICMP_NE, N, Zero)) {
+ // No overflow. Cast the sum.
+ IVLimit = SE->getTruncateOrZeroExtend(N, CntTy);
+ } else {
+ // Potential overflow. Cast before doing the add.
+ IVLimit = SE->getTruncateOrZeroExtend(IVLimit, CntTy);
+ IVLimit = SE->getAddExpr(IVLimit, SE->getConstant(CntTy, 1));
+ }
}
-
// The BackedgeTaken expression contains the number of times that the
// backedge branches to the loop header. This is one less than the
// number of times the loop executes, so use the incremented indvar.
CmpIndVar = IndVar->getIncomingValueForBlock(L->getExitingBlock());
} else {
// We have to use the preincremented value...
- RHS = SE->getTruncateOrZeroExtend(BackedgeTakenCount,
- IndVar->getType());
+ IVLimit = SE->getTruncateOrZeroExtend(IVLimit, CntTy);
CmpIndVar = IndVar;
}
+ // For unit stride, IVLimit = Start + BECount with 2's complement overflow.
+ // So for, non-zero start compute the IVLimit here.
+ bool isPtrIV = false;
+ Type *CmpTy = CntTy;
+ const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(SE->getSCEV(IndVar));
+ assert(AR && AR->getLoop() == L && AR->isAffine() && "bad loop counter");
+ if (!AR->getStart()->isZero()) {
+ assert(AR->getStepRecurrence(*SE)->isOne() && "only handles unit stride");
+ const SCEV *IVInit = AR->getStart();
+
+ // For pointer types, sign extend BECount in order to materialize a GEP.
+ // Note that for without EnableIVRewrite, we never run SCEVExpander on a
+ // pointer type, because we must preserve the existing GEPs. Instead we
+ // directly generate a GEP later.
+ if (IVInit->getType()->isPointerTy()) {
+ isPtrIV = true;
+ CmpTy = SE->getEffectiveSCEVType(IVInit->getType());
+ IVLimit = SE->getTruncateOrSignExtend(IVLimit, CmpTy);
+ }
+ // For integer types, truncate the IV before computing IVInit + BECount.
+ else {
+ if (SE->getTypeSizeInBits(IVInit->getType())
+ > SE->getTypeSizeInBits(CmpTy))
+ IVInit = SE->getTruncateExpr(IVInit, CmpTy);
+
+ IVLimit = SE->getAddExpr(IVInit, IVLimit);
+ }
+ }
// Expand the code for the iteration count.
- assert(SE->isLoopInvariant(RHS, L) &&
+ IRBuilder<> Builder(BI);
+
+ assert(SE->isLoopInvariant(IVLimit, L) &&
"Computed iteration count is not loop invariant!");
- Value *ExitCnt = Rewriter.expandCodeFor(RHS, IndVar->getType(), BI);
+ Value *ExitCnt = Rewriter.expandCodeFor(IVLimit, CmpTy, BI);
+
+ // Create a gep for IVInit + IVLimit from on an existing pointer base.
+ assert(isPtrIV == IndVar->getType()->isPointerTy() &&
+ "IndVar type must match IVInit type");
+ if (isPtrIV) {
+ Value *IVStart = IndVar->getIncomingValueForBlock(L->getLoopPreheader());
+ assert(AR->getStart() == SE->getSCEV(IVStart) && "bad loop counter");
+ assert(SE->getSizeOfExpr(
+ cast<PointerType>(IVStart->getType())->getElementType())->isOne()
+ && "unit stride pointer IV must be i8*");
+
+ Builder.SetInsertPoint(L->getLoopPreheader()->getTerminator());
+ ExitCnt = Builder.CreateGEP(IVStart, ExitCnt, "lftr.limit");
+ Builder.SetInsertPoint(BI);
+ }
// Insert a new icmp_ne or icmp_eq instruction before the branch.
- ICmpInst::Predicate Opcode;
+ ICmpInst::Predicate P;
if (L->contains(BI->getSuccessor(0)))
- Opcode = ICmpInst::ICMP_NE;
+ P = ICmpInst::ICMP_NE;
else
- Opcode = ICmpInst::ICMP_EQ;
+ P = ICmpInst::ICMP_EQ;
DEBUG(dbgs() << "INDVARS: Rewriting loop exit condition to:\n"
<< " LHS:" << *CmpIndVar << '\n'
<< " op:\t"
- << (Opcode == ICmpInst::ICMP_NE ? "!=" : "==") << "\n"
- << " RHS:\t" << *RHS << "\n");
+ << (P == ICmpInst::ICMP_NE ? "!=" : "==") << "\n"
+ << " RHS:\t" << *ExitCnt << "\n"
+ << " Expr:\t" << *IVLimit << "\n");
+
+ if (SE->getTypeSizeInBits(CmpIndVar->getType())
+ > SE->getTypeSizeInBits(CmpTy)) {
+ CmpIndVar = Builder.CreateTrunc(CmpIndVar, CmpTy, "lftr.wideiv");
+ }
- ICmpInst *Cond = new ICmpInst(BI, Opcode, CmpIndVar, ExitCnt, "exitcond");
- Cond->setDebugLoc(BI->getDebugLoc());
+ Value *Cond = Builder.CreateICmp(P, CmpIndVar, ExitCnt, "exitcond");
Value *OrigCond = BI->getCondition();
// It's tempting to use replaceAllUsesWith here to fully replace the old
// comparison, but that's not immediately safe, since users of the old
@@ -1612,7 +1655,7 @@ void IndVarSimplify::SinkUnusedInvariants(Loop *L) {
BasicBlock *Preheader = L->getLoopPreheader();
if (!Preheader) return;
- Instruction *InsertPt = ExitBlock->getFirstNonPHI();
+ Instruction *InsertPt = ExitBlock->getFirstInsertionPt();
BasicBlock::iterator I = Preheader->getTerminator();
while (I != Preheader->begin()) {
--I;
@@ -1633,6 +1676,10 @@ void IndVarSimplify::SinkUnusedInvariants(Loop *L) {
if (isa<DbgInfoIntrinsic>(I))
continue;
+ // Skip landingpad instructions.
+ if (isa<LandingPadInst>(I))
+ continue;
+
// Don't sink static AllocaInsts out of the entry block, which would
// turn them into dynamic allocas!
if (AllocaInst *AI = dyn_cast<AllocaInst>(I))
@@ -1699,7 +1746,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
if (!L->isLoopSimplifyForm())
return false;
- if (!DisableIVRewrite)
+ if (EnableIVRewrite)
IU = &getAnalysis<IVUsers>();
LI = &getAnalysis<LoopInfo>();
SE = &getAnalysis<ScalarEvolution>();
@@ -1717,6 +1764,9 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
// Create a rewriter object which we'll use to transform the code with.
SCEVExpander Rewriter(*SE, "indvars");
+#ifndef NDEBUG
+ Rewriter.setDebugType(DEBUG_TYPE);
+#endif
// Eliminate redundant IV users.
//
@@ -1724,9 +1774,9 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
// attempt to avoid evaluating SCEVs for sign/zero extend operations until
// other expressions involving loop IVs have been evaluated. This helps SCEV
// set no-wrap flags before normalizing sign/zero extension.
- if (DisableIVRewrite) {
+ if (!EnableIVRewrite) {
Rewriter.disableCanonicalMode();
- SimplifyIVUsersNoRewrite(L, Rewriter);
+ SimplifyAndExtend(L, Rewriter, LPM);
}
// Check to see if this loop has a computable loop-invariant execution count.
@@ -1739,25 +1789,25 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
RewriteLoopExitValues(L, Rewriter);
// Eliminate redundant IV users.
- if (!DisableIVRewrite)
- SimplifyIVUsers(Rewriter);
+ if (EnableIVRewrite)
+ Changed |= simplifyIVUsers(IU, SE, &LPM, DeadInsts);
// Eliminate redundant IV cycles.
- if (DisableIVRewrite)
- SimplifyCongruentIVs(L);
+ if (!EnableIVRewrite)
+ NumElimIV += Rewriter.replaceCongruentIVs(L, DT, DeadInsts);
// Compute the type of the largest recurrence expression, and decide whether
// a canonical induction variable should be inserted.
- const Type *LargestType = 0;
+ Type *LargestType = 0;
bool NeedCannIV = false;
bool ExpandBECount = canExpandBackedgeTakenCount(L, SE);
- if (ExpandBECount) {
+ if (EnableIVRewrite && ExpandBECount) {
// If we have a known trip count and a single exit block, we'll be
// rewriting the loop exit test condition below, which requires a
// canonical induction variable.
NeedCannIV = true;
- const Type *Ty = BackedgeTakenCount->getType();
- if (DisableIVRewrite) {
+ Type *Ty = BackedgeTakenCount->getType();
+ if (!EnableIVRewrite) {
// In this mode, SimplifyIVUsers may have already widened the IV used by
// the backedge test and inserted a Trunc on the compare's operand. Get
// the wider type to avoid creating a redundant narrow IV only used by the
@@ -1769,10 +1819,10 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
SE->getTypeSizeInBits(LargestType))
LargestType = SE->getEffectiveSCEVType(Ty);
}
- if (!DisableIVRewrite) {
+ if (EnableIVRewrite) {
for (IVUsers::const_iterator I = IU->begin(), E = IU->end(); I != E; ++I) {
NeedCannIV = true;
- const Type *Ty =
+ Type *Ty =
SE->getEffectiveSCEVType(I->getOperandValToReplace()->getType());
if (!LargestType ||
SE->getTypeSizeInBits(Ty) >
@@ -1811,18 +1861,16 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
// the end of the pass.
while (!OldCannIVs.empty()) {
PHINode *OldCannIV = OldCannIVs.pop_back_val();
- OldCannIV->insertBefore(L->getHeader()->getFirstNonPHI());
+ OldCannIV->insertBefore(L->getHeader()->getFirstInsertionPt());
}
}
-
+ else if (!EnableIVRewrite && ExpandBECount && needsLFTR(L, DT)) {
+ IndVar = FindLoopCounter(L, BackedgeTakenCount, SE, DT, TD);
+ }
// If we have a trip count expression, rewrite the loop's exit condition
// using it. We can currently only handle loops with a single exit.
- ICmpInst *NewICmp = 0;
- if (ExpandBECount) {
- assert(canExpandBackedgeTakenCount(L, SE) &&
- "canonical IV disrupted BackedgeTaken expansion");
- assert(NeedCannIV &&
- "LinearFunctionTestReplace requires a canonical induction variable");
+ Value *NewICmp = 0;
+ if (ExpandBECount && IndVar) {
// Check preconditions for proper SCEVExpander operation. SCEV does not
// express SCEVExpander's dependencies, such as LoopSimplify. Instead any
// pass that uses the SCEVExpander must do it. This does not work well for
@@ -1837,7 +1885,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
LinearFunctionTestReplace(L, BackedgeTakenCount, IndVar, Rewriter);
}
// Rewrite IV-derived expressions.
- if (!DisableIVRewrite)
+ if (EnableIVRewrite)
RewriteIVExpressions(L, Rewriter);
// Clear the rewriter cache, because values that are in the rewriter's cache
@@ -1860,12 +1908,34 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
// For completeness, inform IVUsers of the IV use in the newly-created
// loop exit test instruction.
- if (NewICmp && IU)
- IU->AddUsersIfInteresting(cast<Instruction>(NewICmp->getOperand(0)));
-
+ if (IU && NewICmp) {
+ ICmpInst *NewICmpInst = dyn_cast<ICmpInst>(NewICmp);
+ if (NewICmpInst)
+ IU->AddUsersIfInteresting(cast<Instruction>(NewICmpInst->getOperand(0)));
+ }
// Clean up dead instructions.
Changed |= DeleteDeadPHIs(L->getHeader());
// Check a post-condition.
- assert(L->isLCSSAForm(*DT) && "Indvars did not leave the loop in lcssa form!");
+ assert(L->isLCSSAForm(*DT) &&
+ "Indvars did not leave the loop in lcssa form!");
+
+ // Verify that LFTR, and any other change have not interfered with SCEV's
+ // ability to compute trip count.
+#ifndef NDEBUG
+ if (!EnableIVRewrite && VerifyIndvars &&
+ !isa<SCEVCouldNotCompute>(BackedgeTakenCount)) {
+ SE->forgetLoop(L);
+ const SCEV *NewBECount = SE->getBackedgeTakenCount(L);
+ if (SE->getTypeSizeInBits(BackedgeTakenCount->getType()) <
+ SE->getTypeSizeInBits(NewBECount->getType()))
+ NewBECount = SE->getTruncateOrNoop(NewBECount,
+ BackedgeTakenCount->getType());
+ else
+ BackedgeTakenCount = SE->getTruncateOrNoop(BackedgeTakenCount,
+ NewBECount->getType());
+ assert(BackedgeTakenCount == NewBECount && "indvars must preserve SCEV");
+ }
+#endif
+
return Changed;
}
diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp
index b500d5b..f410af3 100644
--- a/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/lib/Transforms/Scalar/JumpThreading.cpp
@@ -811,8 +811,8 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) {
/// important optimization that encourages jump threading, and needs to be run
/// interlaced with other jump threading tasks.
bool JumpThreading::SimplifyPartiallyRedundantLoad(LoadInst *LI) {
- // Don't hack volatile loads.
- if (LI->isVolatile()) return false;
+ // Don't hack volatile/atomic loads.
+ if (!LI->isSimple()) return false;
// If the load is defined in a block with exactly one predecessor, it can't be
// partially redundant.
diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp
index 66add6c..b79bb13 100644
--- a/lib/Transforms/Scalar/LICM.cpp
+++ b/lib/Transforms/Scalar/LICM.cpp
@@ -151,6 +151,11 @@ namespace {
///
bool isSafeToExecuteUnconditionally(Instruction &I);
+ /// isGuaranteedToExecute - Check that the instruction is guaranteed to
+ /// execute.
+ ///
+ bool isGuaranteedToExecute(Instruction &I);
+
/// pointerInvalidatedByLoop - Return true if the body of this loop may
/// store into the memory location pointed to by V.
///
@@ -357,8 +362,8 @@ void LICM::HoistRegion(DomTreeNode *N) {
bool LICM::canSinkOrHoistInst(Instruction &I) {
// Loads have extra constraints we have to verify before we can hoist them.
if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
- if (LI->isVolatile())
- return false; // Don't hoist volatile loads!
+ if (!LI->isUnordered())
+ return false; // Don't hoist volatile/atomic loads!
// Loads from constant memory are always safe to move, even if they end up
// in the same alias set as something that ends up being modified.
@@ -461,7 +466,7 @@ void LICM::sink(Instruction &I) {
} else {
// Move the instruction to the start of the exit block, after any PHI
// nodes in it.
- I.moveBefore(ExitBlocks[0]->getFirstNonPHI());
+ I.moveBefore(ExitBlocks[0]->getFirstInsertionPt());
// This instruction is no longer in the AST for the current loop, because
// we just sunk it out of the loop. If we just sunk it into an outer
@@ -504,7 +509,7 @@ void LICM::sink(Instruction &I) {
continue;
// Insert the code after the last PHI node.
- BasicBlock::iterator InsertPt = ExitBlock->getFirstNonPHI();
+ BasicBlock::iterator InsertPt = ExitBlock->getFirstInsertionPt();
// If this is the first exit block processed, just move the original
// instruction, otherwise clone the original instruction and insert
@@ -577,6 +582,10 @@ bool LICM::isSafeToExecuteUnconditionally(Instruction &Inst) {
if (Inst.isSafeToSpeculativelyExecute())
return true;
+ return isGuaranteedToExecute(Inst);
+}
+
+bool LICM::isGuaranteedToExecute(Instruction &Inst) {
// Otherwise we have to check to make sure that the instruction dominates all
// of the exit blocks. If it doesn't, then there is a path out of the loop
// which does not execute this instruction, so we can't hoist it.
@@ -635,7 +644,7 @@ namespace {
for (unsigned i = 0, e = LoopExitBlocks.size(); i != e; ++i) {
BasicBlock *ExitBlock = LoopExitBlocks[i];
Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);
- Instruction *InsertPos = ExitBlock->getFirstNonPHI();
+ Instruction *InsertPos = ExitBlock->getFirstInsertionPt();
StoreInst *NewSI = new StoreInst(LiveInValue, SomePtr, InsertPos);
NewSI->setAlignment(Alignment);
NewSI->setDebugLoc(DL);
@@ -713,34 +722,41 @@ void LICM::PromoteAliasSet(AliasSet &AS) {
// If there is an non-load/store instruction in the loop, we can't promote
// it.
- unsigned InstAlignment;
if (LoadInst *load = dyn_cast<LoadInst>(Use)) {
- assert(!cast<LoadInst>(Use)->isVolatile() && "AST broken");
- InstAlignment = load->getAlignment();
+ assert(!load->isVolatile() && "AST broken");
+ if (!load->isSimple())
+ return;
} else if (StoreInst *store = dyn_cast<StoreInst>(Use)) {
// Stores *of* the pointer are not interesting, only stores *to* the
// pointer.
if (Use->getOperand(1) != ASIV)
continue;
- InstAlignment = store->getAlignment();
- assert(!cast<StoreInst>(Use)->isVolatile() && "AST broken");
+ assert(!store->isVolatile() && "AST broken");
+ if (!store->isSimple())
+ return;
+
+ // Note that we only check GuaranteedToExecute inside the store case
+ // so that we do not introduce stores where they did not exist before
+ // (which would break the LLVM concurrency model).
+
+ // If the alignment of this instruction allows us to specify a more
+ // restrictive (and performant) alignment and if we are sure this
+ // instruction will be executed, update the alignment.
+ // Larger is better, with the exception of 0 being the best alignment.
+ unsigned InstAlignment = store->getAlignment();
+ if ((InstAlignment > Alignment || InstAlignment == 0)
+ && (Alignment != 0))
+ if (isGuaranteedToExecute(*Use)) {
+ GuaranteedToExecute = true;
+ Alignment = InstAlignment;
+ }
+
+ if (!GuaranteedToExecute)
+ GuaranteedToExecute = isGuaranteedToExecute(*Use);
+
} else
return; // Not a load or store.
- // If the alignment of this instruction allows us to specify a more
- // restrictive (and performant) alignment and if we are sure this
- // instruction will be executed, update the alignment.
- // Larger is better, with the exception of 0 being the best alignment.
- if ((InstAlignment > Alignment || InstAlignment == 0)
- && (Alignment != 0))
- if (isSafeToExecuteUnconditionally(*Use)) {
- GuaranteedToExecute = true;
- Alignment = InstAlignment;
- }
-
- if (!GuaranteedToExecute)
- GuaranteedToExecute = isSafeToExecuteUnconditionally(*Use);
-
LoopUses.push_back(Use);
}
}
diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index a0e41d9..ad15cbb 100644
--- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -267,7 +267,7 @@ bool LoopIdiomRecognize::runOnLoopBlock(BasicBlock *BB, const SCEV *BECount,
/// processLoopStore - See if this store can be promoted to a memset or memcpy.
bool LoopIdiomRecognize::processLoopStore(StoreInst *SI, const SCEV *BECount) {
- if (SI->isVolatile()) return false;
+ if (!SI->isSimple()) return false;
Value *StoredVal = SI->getValueOperand();
Value *StorePtr = SI->getPointerOperand();
@@ -314,7 +314,7 @@ bool LoopIdiomRecognize::processLoopStore(StoreInst *SI, const SCEV *BECount) {
const SCEVAddRecExpr *LoadEv =
dyn_cast<SCEVAddRecExpr>(SE->getSCEV(LI->getOperand(0)));
if (LoadEv && LoadEv->getLoop() == CurLoop && LoadEv->isAffine() &&
- StoreEv->getOperand(1) == LoadEv->getOperand(1) && !LI->isVolatile())
+ StoreEv->getOperand(1) == LoadEv->getOperand(1) && LI->isSimple())
if (processLoopStoreOfLoopLoad(SI, StoreSize, StoreEv, LoadEv, BECount))
return true;
}
@@ -463,7 +463,7 @@ processLoopStridedStore(Value *DestPtr, unsigned StoreSize,
SplatValue = 0;
} else {
// Otherwise, this isn't an idiom we can transform. For example, we can't
- // do anything with a 3-byte store, for example.
+ // do anything with a 3-byte store.
return false;
}
@@ -498,7 +498,7 @@ processLoopStridedStore(Value *DestPtr, unsigned StoreSize,
// The # stored bytes is (BECount+1)*Size. Expand the trip count out to
// pointer size if it isn't already.
- const Type *IntPtr = TD->getIntPtrType(DestPtr->getContext());
+ Type *IntPtr = TD->getIntPtrType(DestPtr->getContext());
BECount = SE->getTruncateOrZeroExtend(BECount, IntPtr);
const SCEV *NumBytesS = SE->getAddExpr(BECount, SE->getConstant(IntPtr, 1),
@@ -604,7 +604,7 @@ processLoopStoreOfLoopLoad(StoreInst *SI, unsigned StoreSize,
// The # stored bytes is (BECount+1)*Size. Expand the trip count out to
// pointer size if it isn't already.
- const Type *IntPtr = TD->getIntPtrType(SI->getContext());
+ Type *IntPtr = TD->getIntPtrType(SI->getContext());
BECount = SE->getTruncateOrZeroExtend(BECount, IntPtr);
const SCEV *NumBytesS = SE->getAddExpr(BECount, SE->getConstant(IntPtr, 1),
diff --git a/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 509d026..3e122c2 100644
--- a/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -70,12 +70,27 @@
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetLowering.h"
#include <algorithm>
using namespace llvm;
+namespace llvm {
+cl::opt<bool> EnableNested(
+ "enable-lsr-nested", cl::Hidden, cl::desc("Enable LSR on nested loops"));
+
+cl::opt<bool> EnableRetry(
+ "enable-lsr-retry", cl::Hidden, cl::desc("Enable LSR retry"));
+
+// Temporary flag to cleanup congruent phis after LSR phi expansion.
+// It's currently disabled until we can determine whether it's truly useful or
+// not. The flag should be removed after the v3.0 release.
+cl::opt<bool> EnablePhiElim(
+ "enable-lsr-phielim", cl::Hidden, cl::desc("Enable LSR phi elimination"));
+}
+
namespace {
/// RegSortData - This class holds data which is used to order reuse candidates.
@@ -219,7 +234,7 @@ struct Formula {
void InitialMatch(const SCEV *S, Loop *L, ScalarEvolution &SE);
unsigned getNumRegs() const;
- const Type *getType() const;
+ Type *getType() const;
void DeleteBaseReg(const SCEV *&S);
@@ -319,7 +334,7 @@ unsigned Formula::getNumRegs() const {
/// getType - Return the type of this formula, if it has one, or null
/// otherwise. This type is meaningless except for the bit size.
-const Type *Formula::getType() const {
+Type *Formula::getType() const {
return !BaseRegs.empty() ? BaseRegs.front()->getType() :
ScaledReg ? ScaledReg->getType() :
AM.BaseGV ? AM.BaseGV->getType() :
@@ -397,7 +412,7 @@ void Formula::dump() const {
/// isAddRecSExtable - Return true if the given addrec can be sign-extended
/// without changing its value.
static bool isAddRecSExtable(const SCEVAddRecExpr *AR, ScalarEvolution &SE) {
- const Type *WideTy =
+ Type *WideTy =
IntegerType::get(SE.getContext(), SE.getTypeSizeInBits(AR->getType()) + 1);
return isa<SCEVAddRecExpr>(SE.getSignExtendExpr(AR, WideTy));
}
@@ -405,7 +420,7 @@ static bool isAddRecSExtable(const SCEVAddRecExpr *AR, ScalarEvolution &SE) {
/// isAddSExtable - Return true if the given add can be sign-extended
/// without changing its value.
static bool isAddSExtable(const SCEVAddExpr *A, ScalarEvolution &SE) {
- const Type *WideTy =
+ Type *WideTy =
IntegerType::get(SE.getContext(), SE.getTypeSizeInBits(A->getType()) + 1);
return isa<SCEVAddExpr>(SE.getSignExtendExpr(A, WideTy));
}
@@ -413,7 +428,7 @@ static bool isAddSExtable(const SCEVAddExpr *A, ScalarEvolution &SE) {
/// isMulSExtable - Return true if the given mul can be sign-extended
/// without changing its value.
static bool isMulSExtable(const SCEVMulExpr *M, ScalarEvolution &SE) {
- const Type *WideTy =
+ Type *WideTy =
IntegerType::get(SE.getContext(),
SE.getTypeSizeInBits(M->getType()) * M->getNumOperands());
return isa<SCEVMulExpr>(SE.getSignExtendExpr(M, WideTy));
@@ -594,8 +609,8 @@ static bool isAddressUse(Instruction *Inst, Value *OperandVal) {
}
/// getAccessType - Return the type of the memory being accessed.
-static const Type *getAccessType(const Instruction *Inst) {
- const Type *AccessTy = Inst->getType();
+static Type *getAccessType(const Instruction *Inst) {
+ Type *AccessTy = Inst->getType();
if (const StoreInst *SI = dyn_cast<StoreInst>(Inst))
AccessTy = SI->getOperand(0)->getType();
else if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {
@@ -614,7 +629,7 @@ static const Type *getAccessType(const Instruction *Inst) {
// All pointers have the same requirements, so canonicalize them to an
// arbitrary pointer type to minimize variation.
- if (const PointerType *PTy = dyn_cast<PointerType>(AccessTy))
+ if (PointerType *PTy = dyn_cast<PointerType>(AccessTy))
AccessTy = PointerType::get(IntegerType::get(PTy->getContext(), 1),
PTy->getAddressSpace());
@@ -670,6 +685,21 @@ public:
void Loose();
+#ifndef NDEBUG
+ // Once any of the metrics loses, they must all remain losers.
+ bool isValid() {
+ return ((NumRegs | AddRecCost | NumIVMuls | NumBaseAdds
+ | ImmCost | SetupCost) != ~0u)
+ || ((NumRegs & AddRecCost & NumIVMuls & NumBaseAdds
+ & ImmCost & SetupCost) == ~0u);
+ }
+#endif
+
+ bool isLoser() {
+ assert(isValid() && "invalid cost");
+ return NumRegs == ~0u;
+ }
+
void RateFormula(const Formula &F,
SmallPtrSet<const SCEV *, 16> &Regs,
const DenseSet<const SCEV *> &VisitedRegs,
@@ -702,34 +732,48 @@ void Cost::RateRegister(const SCEV *Reg,
if (AR->getLoop() == L)
AddRecCost += 1; /// TODO: This should be a function of the stride.
- // If this is an addrec for a loop that's already been visited by LSR,
- // don't second-guess its addrec phi nodes. LSR isn't currently smart
- // enough to reason about more than one loop at a time. Consider these
- // registers free and leave them alone.
- else if (L->contains(AR->getLoop()) ||
+ // If this is an addrec for another loop, don't second-guess its addrec phi
+ // nodes. LSR isn't currently smart enough to reason about more than one
+ // loop at a time. LSR has either already run on inner loops, will not run
+ // on other loops, and cannot be expected to change sibling loops. If the
+ // AddRec exists, consider it's register free and leave it alone. Otherwise,
+ // do not consider this formula at all.
+ // FIXME: why do we need to generate such fomulae?
+ else if (!EnableNested || L->contains(AR->getLoop()) ||
(!AR->getLoop()->contains(L) &&
DT.dominates(L->getHeader(), AR->getLoop()->getHeader()))) {
for (BasicBlock::iterator I = AR->getLoop()->getHeader()->begin();
- PHINode *PN = dyn_cast<PHINode>(I); ++I)
+ PHINode *PN = dyn_cast<PHINode>(I); ++I) {
if (SE.isSCEVable(PN->getType()) &&
(SE.getEffectiveSCEVType(PN->getType()) ==
SE.getEffectiveSCEVType(AR->getType())) &&
SE.getSCEV(PN) == AR)
return;
-
+ }
+ if (!EnableNested) {
+ Loose();
+ return;
+ }
// If this isn't one of the addrecs that the loop already has, it
// would require a costly new phi and add. TODO: This isn't
// precisely modeled right now.
++NumBaseAdds;
- if (!Regs.count(AR->getStart()))
+ if (!Regs.count(AR->getStart())) {
RateRegister(AR->getStart(), Regs, L, SE, DT);
+ if (isLoser())
+ return;
+ }
}
// Add the step value register, if it needs one.
// TODO: The non-affine case isn't precisely modeled here.
- if (!AR->isAffine() || !isa<SCEVConstant>(AR->getOperand(1)))
- if (!Regs.count(AR->getStart()))
+ if (!AR->isAffine() || !isa<SCEVConstant>(AR->getOperand(1))) {
+ if (!Regs.count(AR->getOperand(1))) {
RateRegister(AR->getOperand(1), Regs, L, SE, DT);
+ if (isLoser())
+ return;
+ }
+ }
}
++NumRegs;
@@ -769,6 +813,8 @@ void Cost::RateFormula(const Formula &F,
return;
}
RatePrimaryRegister(ScaledReg, Regs, L, SE, DT);
+ if (isLoser())
+ return;
}
for (SmallVectorImpl<const SCEV *>::const_iterator I = F.BaseRegs.begin(),
E = F.BaseRegs.end(); I != E; ++I) {
@@ -778,6 +824,8 @@ void Cost::RateFormula(const Formula &F,
return;
}
RatePrimaryRegister(BaseReg, Regs, L, SE, DT);
+ if (isLoser())
+ return;
}
// Determine how many (unfolded) adds we'll need inside the loop.
@@ -795,6 +843,7 @@ void Cost::RateFormula(const Formula &F,
else if (Offset != 0)
ImmCost += APInt(64, Offset, true).getMinSignedBits();
}
+ assert(isValid() && "invalid cost");
}
/// Loose - Set this cost to a losing value.
@@ -980,7 +1029,7 @@ public:
};
KindType Kind;
- const Type *AccessTy;
+ Type *AccessTy;
SmallVector<int64_t, 8> Offsets;
int64_t MinOffset;
@@ -995,7 +1044,7 @@ public:
/// this LSRUse. FindUseWithSimilarFormula can't consider uses with different
/// max fixup widths to be equivalent, because the narrower one may be relying
/// on the implicit truncation to truncate away bogus bits.
- const Type *WidestFixupType;
+ Type *WidestFixupType;
/// Formulae - A list of ways to build a value that can satisfy this user.
/// After the list is populated, one of these is selected heuristically and
@@ -1005,7 +1054,7 @@ public:
/// Regs - The set of register candidates used by all formulae in this LSRUse.
SmallPtrSet<const SCEV *, 4> Regs;
- LSRUse(KindType K, const Type *T) : Kind(K), AccessTy(T),
+ LSRUse(KindType K, Type *T) : Kind(K), AccessTy(T),
MinOffset(INT64_MAX),
MaxOffset(INT64_MIN),
AllFixupsOutsideLoop(true),
@@ -1127,7 +1176,7 @@ void LSRUse::dump() const {
/// be completely folded into the user instruction at isel time. This includes
/// address-mode folding and special icmp tricks.
static bool isLegalUse(const TargetLowering::AddrMode &AM,
- LSRUse::KindType Kind, const Type *AccessTy,
+ LSRUse::KindType Kind, Type *AccessTy,
const TargetLowering *TLI) {
switch (Kind) {
case LSRUse::Address:
@@ -1156,7 +1205,7 @@ static bool isLegalUse(const TargetLowering::AddrMode &AM,
// If we have low-level target information, ask the target if it can fold an
// integer immediate on an icmp.
if (AM.BaseOffs != 0) {
- if (TLI) return TLI->isLegalICmpImmediate(-AM.BaseOffs);
+ if (TLI) return TLI->isLegalICmpImmediate(-(uint64_t)AM.BaseOffs);
return false;
}
@@ -1176,7 +1225,7 @@ static bool isLegalUse(const TargetLowering::AddrMode &AM,
static bool isLegalUse(TargetLowering::AddrMode AM,
int64_t MinOffset, int64_t MaxOffset,
- LSRUse::KindType Kind, const Type *AccessTy,
+ LSRUse::KindType Kind, Type *AccessTy,
const TargetLowering *TLI) {
// Check for overflow.
if (((int64_t)((uint64_t)AM.BaseOffs + MinOffset) > AM.BaseOffs) !=
@@ -1198,7 +1247,7 @@ static bool isLegalUse(TargetLowering::AddrMode AM,
static bool isAlwaysFoldable(int64_t BaseOffs,
GlobalValue *BaseGV,
bool HasBaseReg,
- LSRUse::KindType Kind, const Type *AccessTy,
+ LSRUse::KindType Kind, Type *AccessTy,
const TargetLowering *TLI) {
// Fast-path: zero is always foldable.
if (BaseOffs == 0 && !BaseGV) return true;
@@ -1224,7 +1273,7 @@ static bool isAlwaysFoldable(int64_t BaseOffs,
static bool isAlwaysFoldable(const SCEV *S,
int64_t MinOffset, int64_t MaxOffset,
bool HasBaseReg,
- LSRUse::KindType Kind, const Type *AccessTy,
+ LSRUse::KindType Kind, Type *AccessTy,
const TargetLowering *TLI,
ScalarEvolution &SE) {
// Fast-path: zero is always foldable.
@@ -1299,7 +1348,7 @@ class LSRInstance {
SmallSetVector<int64_t, 8> Factors;
/// Types - Interesting use types, to facilitate truncation reuse.
- SmallSetVector<const Type *, 4> Types;
+ SmallSetVector<Type *, 4> Types;
/// Fixups - The list of operands which are to be replaced.
SmallVector<LSRFixup, 16> Fixups;
@@ -1330,11 +1379,11 @@ class LSRInstance {
UseMapTy UseMap;
bool reconcileNewOffset(LSRUse &LU, int64_t NewOffset, bool HasBaseReg,
- LSRUse::KindType Kind, const Type *AccessTy);
+ LSRUse::KindType Kind, Type *AccessTy);
std::pair<size_t, int64_t> getUse(const SCEV *&Expr,
LSRUse::KindType Kind,
- const Type *AccessTy);
+ Type *AccessTy);
void DeleteUse(LSRUse &LU, size_t LUIdx);
@@ -1426,7 +1475,8 @@ void LSRInstance::OptimizeShadowIV() {
IVUsers::const_iterator CandidateUI = UI;
++UI;
Instruction *ShadowUse = CandidateUI->getUser();
- const Type *DestTy = NULL;
+ Type *DestTy = NULL;
+ bool IsSigned = false;
/* If shadow use is a int->float cast then insert a second IV
to eliminate this cast.
@@ -1440,10 +1490,14 @@ void LSRInstance::OptimizeShadowIV() {
for (unsigned i = 0; i < n; ++i, ++d)
foo(d);
*/
- if (UIToFPInst *UCast = dyn_cast<UIToFPInst>(CandidateUI->getUser()))
+ if (UIToFPInst *UCast = dyn_cast<UIToFPInst>(CandidateUI->getUser())) {
+ IsSigned = false;
DestTy = UCast->getDestTy();
- else if (SIToFPInst *SCast = dyn_cast<SIToFPInst>(CandidateUI->getUser()))
+ }
+ else if (SIToFPInst *SCast = dyn_cast<SIToFPInst>(CandidateUI->getUser())) {
+ IsSigned = true;
DestTy = SCast->getDestTy();
+ }
if (!DestTy) continue;
if (TLI) {
@@ -1457,7 +1511,7 @@ void LSRInstance::OptimizeShadowIV() {
if (!PH) continue;
if (PH->getNumIncomingValues() != 2) continue;
- const Type *SrcTy = PH->getType();
+ Type *SrcTy = PH->getType();
int Mantissa = DestTy->getFPMantissaWidth();
if (Mantissa == -1) continue;
if ((int)SE.getTypeSizeInBits(SrcTy) > Mantissa)
@@ -1474,7 +1528,9 @@ void LSRInstance::OptimizeShadowIV() {
ConstantInt *Init = dyn_cast<ConstantInt>(PH->getIncomingValue(Entry));
if (!Init) continue;
- Constant *NewInit = ConstantFP::get(DestTy, Init->getZExtValue());
+ Constant *NewInit = ConstantFP::get(DestTy, IsSigned ?
+ (double)Init->getSExtValue() :
+ (double)Init->getZExtValue());
BinaryOperator *Incr =
dyn_cast<BinaryOperator>(PH->getIncomingValue(Latch));
@@ -1776,7 +1832,7 @@ LSRInstance::OptimizeLoopTermCond() {
if (!TLI)
goto decline_post_inc;
// Check for possible scaled-address reuse.
- const Type *AccessTy = getAccessType(UI->getUser());
+ Type *AccessTy = getAccessType(UI->getUser());
TargetLowering::AddrMode AM;
AM.Scale = C->getSExtValue();
if (TLI->isLegalAddressingMode(AM, AccessTy))
@@ -1840,10 +1896,10 @@ LSRInstance::OptimizeLoopTermCond() {
/// return true.
bool
LSRInstance::reconcileNewOffset(LSRUse &LU, int64_t NewOffset, bool HasBaseReg,
- LSRUse::KindType Kind, const Type *AccessTy) {
+ LSRUse::KindType Kind, Type *AccessTy) {
int64_t NewMinOffset = LU.MinOffset;
int64_t NewMaxOffset = LU.MaxOffset;
- const Type *NewAccessTy = AccessTy;
+ Type *NewAccessTy = AccessTy;
// Check for a mismatched kind. It's tempting to collapse mismatched kinds to
// something conservative, however this can pessimize in the case that one of
@@ -1882,7 +1938,7 @@ LSRInstance::reconcileNewOffset(LSRUse &LU, int64_t NewOffset, bool HasBaseReg,
/// Either reuse an existing use or create a new one, as needed.
std::pair<size_t, int64_t>
LSRInstance::getUse(const SCEV *&Expr,
- LSRUse::KindType Kind, const Type *AccessTy) {
+ LSRUse::KindType Kind, Type *AccessTy) {
const SCEV *Copy = Expr;
int64_t Offset = ExtractImmediate(Expr, SE);
@@ -2044,7 +2100,7 @@ void LSRInstance::CollectFixupsAndInitialFormulae() {
LF.PostIncLoops = UI->getPostIncLoops();
LSRUse::KindType Kind = LSRUse::Basic;
- const Type *AccessTy = 0;
+ Type *AccessTy = 0;
if (isAddressUse(LF.UserInst, LF.OperandValToReplace)) {
Kind = LSRUse::Address;
AccessTy = getAccessType(LF.UserInst);
@@ -2464,7 +2520,7 @@ void LSRInstance::GenerateICmpZeroScales(LSRUse &LU, unsigned LUIdx,
if (LU.Kind != LSRUse::ICmpZero) return;
// Determine the integer type for the base formula.
- const Type *IntTy = Base.getType();
+ Type *IntTy = Base.getType();
if (!IntTy) return;
if (SE.getTypeSizeInBits(IntTy) > 64) return;
@@ -2538,7 +2594,7 @@ void LSRInstance::GenerateICmpZeroScales(LSRUse &LU, unsigned LUIdx,
/// scaled-offset address modes, for example.
void LSRInstance::GenerateScales(LSRUse &LU, unsigned LUIdx, Formula Base) {
// Determine the integer type for the base formula.
- const Type *IntTy = Base.getType();
+ Type *IntTy = Base.getType();
if (!IntTy) return;
// If this Formula already has a scaled register, we can't add another one.
@@ -2598,13 +2654,13 @@ void LSRInstance::GenerateTruncates(LSRUse &LU, unsigned LUIdx, Formula Base) {
if (Base.AM.BaseGV) return;
// Determine the integer type for the base formula.
- const Type *DstTy = Base.getType();
+ Type *DstTy = Base.getType();
if (!DstTy) return;
DstTy = SE.getEffectiveSCEVType(DstTy);
- for (SmallSetVector<const Type *, 4>::const_iterator
+ for (SmallSetVector<Type *, 4>::const_iterator
I = Types.begin(), E = Types.end(); I != E; ++I) {
- const Type *SrcTy = *I;
+ Type *SrcTy = *I;
if (SrcTy != DstTy && TLI->isTruncateFree(SrcTy, DstTy)) {
Formula F = Base;
@@ -2741,7 +2797,7 @@ void LSRInstance::GenerateCrossUseConstantOffsets() {
int64_t Imm = WI.Imm;
const SCEV *OrigReg = WI.OrigReg;
- const Type *IntTy = SE.getEffectiveSCEVType(OrigReg->getType());
+ Type *IntTy = SE.getEffectiveSCEVType(OrigReg->getType());
const SCEV *NegImmS = SE.getSCEV(ConstantInt::get(IntTy, -(uint64_t)Imm));
unsigned BitWidth = SE.getTypeSizeInBits(IntTy);
@@ -3275,6 +3331,9 @@ retry:
skip:;
}
+ if (!EnableRetry && !AnySatisfiedReqRegs)
+ return;
+
// If none of the formulae had all of the required registers, relax the
// constraint so that we don't exclude all formulae.
if (!AnySatisfiedReqRegs) {
@@ -3298,6 +3357,10 @@ void LSRInstance::Solve(SmallVectorImpl<const Formula *> &Solution) const {
// SolveRecurse does all the work.
SolveRecurse(Solution, SolutionCost, Workspace, CurCost,
CurRegs, VisitedRegs);
+ if (Solution.empty()) {
+ DEBUG(dbgs() << "\nNo Satisfactory Solution\n");
+ return;
+ }
// Ok, we've now made all our decisions.
DEBUG(dbgs() << "\n"
@@ -3416,6 +3479,9 @@ LSRInstance::AdjustInsertPositionForExpand(BasicBlock::iterator IP,
// Don't insert instructions before PHI nodes.
while (isa<PHINode>(IP)) ++IP;
+ // Ignore landingpad instructions.
+ while (isa<LandingPadInst>(IP)) ++IP;
+
// Ignore debug intrinsics.
while (isa<DbgInfoIntrinsic>(IP)) ++IP;
@@ -3440,9 +3506,9 @@ Value *LSRInstance::Expand(const LSRFixup &LF,
Rewriter.setPostInc(LF.PostIncLoops);
// This is the type that the user actually needs.
- const Type *OpTy = LF.OperandValToReplace->getType();
+ Type *OpTy = LF.OperandValToReplace->getType();
// This will be the type that we'll initially expand to.
- const Type *Ty = F.getType();
+ Type *Ty = F.getType();
if (!Ty)
// No type known; just expand directly to the ultimate type.
Ty = OpTy;
@@ -3450,7 +3516,7 @@ Value *LSRInstance::Expand(const LSRFixup &LF,
// Expand directly to the ultimate type if it's the right size.
Ty = OpTy;
// This is the type to do integer arithmetic in.
- const Type *IntTy = SE.getEffectiveSCEVType(Ty);
+ Type *IntTy = SE.getEffectiveSCEVType(Ty);
// Build up a list of operands to add together to form the full base.
SmallVector<const SCEV *, 8> Ops;
@@ -3527,7 +3593,7 @@ Value *LSRInstance::Expand(const LSRFixup &LF,
// The other interesting way of "folding" with an ICmpZero is to use a
// negated immediate.
if (!ICmpScaledV)
- ICmpScaledV = ConstantInt::get(IntTy, -Offset);
+ ICmpScaledV = ConstantInt::get(IntTy, -(uint64_t)Offset);
else {
Ops.push_back(SE.getUnknown(ICmpScaledV));
ICmpScaledV = ConstantInt::get(IntTy, Offset);
@@ -3611,10 +3677,20 @@ void LSRInstance::RewriteForPHI(PHINode *PN,
// users.
if (e != 1 && BB->getTerminator()->getNumSuccessors() > 1 &&
!isa<IndirectBrInst>(BB->getTerminator())) {
- Loop *PNLoop = LI.getLoopFor(PN->getParent());
- if (!PNLoop || PN->getParent() != PNLoop->getHeader()) {
+ BasicBlock *Parent = PN->getParent();
+ Loop *PNLoop = LI.getLoopFor(Parent);
+ if (!PNLoop || Parent != PNLoop->getHeader()) {
// Split the critical edge.
- BasicBlock *NewBB = SplitCriticalEdge(BB, PN->getParent(), P);
+ BasicBlock *NewBB = 0;
+ if (!Parent->isLandingPad()) {
+ NewBB = SplitCriticalEdge(BB, Parent, P,
+ /*MergeIdenticalEdges=*/true,
+ /*DontDeleteUselessPhis=*/true);
+ } else {
+ SmallVector<BasicBlock*, 2> NewBBs;
+ SplitLandingPadPredecessors(Parent, BB, "", "", P, NewBBs);
+ NewBB = NewBBs[0];
+ }
// If PN is outside of the loop and BB is in the loop, we want to
// move the block to be immediately before the PHI block, not
@@ -3637,7 +3713,7 @@ void LSRInstance::RewriteForPHI(PHINode *PN,
Value *FullV = Expand(LF, F, BB->getTerminator(), Rewriter, DeadInsts);
// If this is reuse-by-noop-cast, insert the noop cast.
- const Type *OpTy = LF.OperandValToReplace->getType();
+ Type *OpTy = LF.OperandValToReplace->getType();
if (FullV->getType() != OpTy)
FullV =
CastInst::Create(CastInst::getCastOpcode(FullV, false,
@@ -3667,7 +3743,7 @@ void LSRInstance::Rewrite(const LSRFixup &LF,
Value *FullV = Expand(LF, F, LF.UserInst, Rewriter, DeadInsts);
// If this is reuse-by-noop-cast, insert the noop cast.
- const Type *OpTy = LF.OperandValToReplace->getType();
+ Type *OpTy = LF.OperandValToReplace->getType();
if (FullV->getType() != OpTy) {
Instruction *Cast =
CastInst::Create(CastInst::getCastOpcode(FullV, false, OpTy, false),
@@ -3700,6 +3776,7 @@ LSRInstance::ImplementSolution(const SmallVectorImpl<const Formula *> &Solution,
SCEVExpander Rewriter(SE, "lsr");
Rewriter.disableCanonicalMode();
+ Rewriter.enableLSRMode();
Rewriter.setIVIncInsertPos(L, IVIncInsertPos);
// Expand the new value definitions and update the users.
@@ -3740,6 +3817,23 @@ LSRInstance::LSRInstance(const TargetLowering *tli, Loop *l, Pass *P)
OptimizeShadowIV();
OptimizeLoopTermCond();
+ // If loop preparation eliminates all interesting IV users, bail.
+ if (IU.empty()) return;
+
+ // Skip nested loops until we can model them better with formulae.
+ if (!EnableNested && !L->empty()) {
+
+ if (EnablePhiElim) {
+ // Remove any extra phis created by processing inner loops.
+ SmallVector<WeakVH, 16> DeadInsts;
+ SCEVExpander Rewriter(SE, "lsr");
+ Changed |= Rewriter.replaceCongruentIVs(L, &DT, DeadInsts);
+ Changed |= DeleteTriviallyDeadInstructions(DeadInsts);
+ }
+ DEBUG(dbgs() << "LSR skipping outer loop " << *L << "\n");
+ return;
+ }
+
// Start collecting data and preparing for the solver.
CollectInterestingTypesAndFactors();
CollectFixupsAndInitialFormulae();
@@ -3763,6 +3857,9 @@ LSRInstance::LSRInstance(const TargetLowering *tli, Loop *l, Pass *P)
Types.clear();
RegUses.clear();
+ if (Solution.empty())
+ return;
+
#ifndef NDEBUG
// Formulae should be legal.
for (SmallVectorImpl<LSRUse>::const_iterator I = Uses.begin(),
@@ -3778,6 +3875,14 @@ LSRInstance::LSRInstance(const TargetLowering *tli, Loop *l, Pass *P)
// Now that we've decided what we want, make it so.
ImplementSolution(Solution, P);
+
+ if (EnablePhiElim) {
+ // Remove any extra phis created by processing inner loops.
+ SmallVector<WeakVH, 16> DeadInsts;
+ SCEVExpander Rewriter(SE, "lsr");
+ Changed |= Rewriter.replaceCongruentIVs(L, &DT, DeadInsts);
+ Changed |= DeleteTriviallyDeadInstructions(DeadInsts);
+ }
}
void LSRInstance::print_factors_and_types(raw_ostream &OS) const {
@@ -3793,7 +3898,7 @@ void LSRInstance::print_factors_and_types(raw_ostream &OS) const {
OS << '*' << *I;
}
- for (SmallSetVector<const Type *, 4>::const_iterator
+ for (SmallSetVector<Type *, 4>::const_iterator
I = Types.begin(), E = Types.end(); I != E; ++I) {
if (!First) OS << ", ";
First = false;
diff --git a/lib/Transforms/Scalar/LoopUnrollPass.cpp b/lib/Transforms/Scalar/LoopUnrollPass.cpp
index fef6bc3..91395b2 100644
--- a/lib/Transforms/Scalar/LoopUnrollPass.cpp
+++ b/lib/Transforms/Scalar/LoopUnrollPass.cpp
@@ -22,6 +22,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/UnrollLoop.h"
+#include "llvm/Target/TargetData.h"
#include <climits>
using namespace llvm;
@@ -39,6 +40,11 @@ UnrollAllowPartial("unroll-allow-partial", cl::init(false), cl::Hidden,
cl::desc("Allows loops to be partially unrolled until "
"-unroll-threshold loop size is reached."));
+// Temporary flag to be removed in 3.0
+static cl::opt<bool>
+NoSCEVUnroll("disable-unroll-scev", cl::init(false), cl::Hidden,
+ cl::desc("Use ScalarEvolution to analyze loop trip counts for unrolling"));
+
namespace {
class LoopUnroll : public LoopPass {
public:
@@ -49,7 +55,7 @@ namespace {
CurrentAllowPartial = (P == -1) ? UnrollAllowPartial : (bool)P;
UserThreshold = (T != -1) || (UnrollThreshold.getNumOccurrences() > 0);
-
+
initializeLoopUnrollPass(*PassRegistry::getPassRegistry());
}
@@ -57,11 +63,11 @@ namespace {
/// that the loop unroll should be performed regardless of how much
/// code expansion would result.
static const unsigned NoThreshold = UINT_MAX;
-
+
// Threshold to use when optsize is specified (and there is no
// explicit -unroll-threshold).
static const unsigned OptSizeUnrollThreshold = 50;
-
+
unsigned CurrentCount;
unsigned CurrentThreshold;
bool CurrentAllowPartial;
@@ -79,6 +85,7 @@ namespace {
AU.addPreservedID(LoopSimplifyID);
AU.addRequiredID(LCSSAID);
AU.addPreservedID(LCSSAID);
+ AU.addRequired<ScalarEvolution>();
AU.addPreserved<ScalarEvolution>();
// FIXME: Loop unroll requires LCSSA. And LCSSA requires dom info.
// If loop unroll does not preserve dom info then LCSSA pass on next
@@ -101,45 +108,62 @@ Pass *llvm::createLoopUnrollPass(int Threshold, int Count, int AllowPartial) {
}
/// ApproximateLoopSize - Approximate the size of the loop.
-static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls) {
+static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls,
+ const TargetData *TD) {
CodeMetrics Metrics;
for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
I != E; ++I)
- Metrics.analyzeBasicBlock(*I);
+ Metrics.analyzeBasicBlock(*I, TD);
NumCalls = Metrics.NumInlineCandidates;
-
+
unsigned LoopSize = Metrics.NumInsts;
-
+
// Don't allow an estimate of size zero. This would allows unrolling of loops
// with huge iteration counts, which is a compile time problem even if it's
// not a problem for code quality.
if (LoopSize == 0) LoopSize = 1;
-
+
return LoopSize;
}
bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
LoopInfo *LI = &getAnalysis<LoopInfo>();
+ ScalarEvolution *SE = &getAnalysis<ScalarEvolution>();
BasicBlock *Header = L->getHeader();
DEBUG(dbgs() << "Loop Unroll: F[" << Header->getParent()->getName()
<< "] Loop %" << Header->getName() << "\n");
(void)Header;
-
+
// Determine the current unrolling threshold. While this is normally set
// from UnrollThreshold, it is overridden to a smaller value if the current
// function is marked as optimize-for-size, and the unroll threshold was
// not user specified.
unsigned Threshold = CurrentThreshold;
- if (!UserThreshold &&
+ if (!UserThreshold &&
Header->getParent()->hasFnAttr(Attribute::OptimizeForSize))
Threshold = OptSizeUnrollThreshold;
- // Find trip count
- unsigned TripCount = L->getSmallConstantTripCount();
- unsigned Count = CurrentCount;
-
+ // Find trip count and trip multiple if count is not available
+ unsigned TripCount = 0;
+ unsigned TripMultiple = 1;
+ if (!NoSCEVUnroll) {
+ // Find "latch trip count". UnrollLoop assumes that control cannot exit
+ // via the loop latch on any iteration prior to TripCount. The loop may exit
+ // early via an earlier branch.
+ BasicBlock *LatchBlock = L->getLoopLatch();
+ if (LatchBlock) {
+ TripCount = SE->getSmallConstantTripCount(L, LatchBlock);
+ TripMultiple = SE->getSmallConstantTripMultiple(L, LatchBlock);
+ }
+ }
+ else {
+ TripCount = L->getSmallConstantTripCount();
+ if (TripCount == 0)
+ TripMultiple = L->getSmallConstantTripMultiple();
+ }
// Automatically select an unroll count.
+ unsigned Count = CurrentCount;
if (Count == 0) {
// Conservative heuristic: if we know the trip count, see if we can
// completely unroll (subject to the threshold, checked below); otherwise
@@ -152,8 +176,9 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
// Enforce the threshold.
if (Threshold != NoThreshold) {
+ const TargetData *TD = getAnalysisIfAvailable<TargetData>();
unsigned NumInlineCandidates;
- unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates);
+ unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates, TD);
DEBUG(dbgs() << " Loop Size = " << LoopSize << "\n");
if (NumInlineCandidates != 0) {
DEBUG(dbgs() << " Not unrolling loop with inlinable calls.\n");
@@ -182,12 +207,8 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
}
// Unroll the loop.
- Function *F = L->getHeader()->getParent();
- if (!UnrollLoop(L, Count, LI, &LPM))
+ if (!UnrollLoop(L, Count, TripCount, TripMultiple, LI, &LPM))
return false;
- // FIXME: Reconstruct dom info, because it is not preserved properly.
- if (DominatorTree *DT = getAnalysisIfAvailable<DominatorTree>())
- DT->runOnFunction(*F);
return true;
}
diff --git a/lib/Transforms/Scalar/LoopUnswitch.cpp b/lib/Transforms/Scalar/LoopUnswitch.cpp
index 840c4b6..458949c 100644
--- a/lib/Transforms/Scalar/LoopUnswitch.cpp
+++ b/lib/Transforms/Scalar/LoopUnswitch.cpp
@@ -492,7 +492,7 @@ void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
Value *BranchVal = LIC;
if (!isa<ConstantInt>(Val) ||
Val->getType() != Type::getInt1Ty(LIC->getContext()))
- BranchVal = new ICmpInst(InsertPt, ICmpInst::ICMP_EQ, LIC, Val, "tmp");
+ BranchVal = new ICmpInst(InsertPt, ICmpInst::ICMP_EQ, LIC, Val);
else if (Val != ConstantInt::getTrue(Val->getContext()))
// We want to enter the new loop when the condition is true.
std::swap(TrueDest, FalseDest);
@@ -561,10 +561,17 @@ void LoopUnswitch::SplitExitEdges(Loop *L,
BasicBlock *ExitBlock = ExitBlocks[i];
SmallVector<BasicBlock *, 4> Preds(pred_begin(ExitBlock),
pred_end(ExitBlock));
+
// Although SplitBlockPredecessors doesn't preserve loop-simplify in
// general, if we call it on all predecessors of all exits then it does.
- SplitBlockPredecessors(ExitBlock, Preds.data(), Preds.size(),
- ".us-lcssa", this);
+ if (!ExitBlock->isLandingPad()) {
+ SplitBlockPredecessors(ExitBlock, Preds.data(), Preds.size(),
+ ".us-lcssa", this);
+ } else {
+ SmallVector<BasicBlock*, 2> NewBBs;
+ SplitLandingPadPredecessors(ExitBlock, Preds, ".us-lcssa", ".us-lcssa",
+ this, NewBBs);
+ }
}
}
@@ -632,7 +639,7 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val,
// as well.
ParentLoop->addBasicBlockToLoop(NewBlocks[0], LI->getBase());
}
-
+
for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {
BasicBlock *NewExit = cast<BasicBlock>(VMap[ExitBlocks[i]]);
// The new exit block should be in the same loop as the old one.
@@ -653,6 +660,19 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val,
if (It != VMap.end()) V = It->second;
PN->addIncoming(V, NewExit);
}
+
+ if (LandingPadInst *LPad = NewExit->getLandingPadInst()) {
+ PN = PHINode::Create(LPad->getType(), 0, "",
+ ExitSucc->getFirstInsertionPt());
+
+ for (pred_iterator I = pred_begin(ExitSucc), E = pred_end(ExitSucc);
+ I != E; ++I) {
+ BasicBlock *BB = *I;
+ LandingPadInst *LPI = BB->getLandingPadInst();
+ LPI->replaceAllUsesWith(PN);
+ PN->addIncoming(LPI, BB);
+ }
+ }
}
// Rewrite the code to refer to itself.
diff --git a/lib/Transforms/Scalar/LowerAtomic.cpp b/lib/Transforms/Scalar/LowerAtomic.cpp
index 9087b46..689bbe9 100644
--- a/lib/Transforms/Scalar/LowerAtomic.cpp
+++ b/lib/Transforms/Scalar/LowerAtomic.cpp
@@ -20,98 +20,88 @@
#include "llvm/Support/IRBuilder.h"
using namespace llvm;
-static bool LowerAtomicIntrinsic(IntrinsicInst *II) {
- IRBuilder<> Builder(II->getParent(), II);
- unsigned IID = II->getIntrinsicID();
- switch (IID) {
- case Intrinsic::memory_barrier:
- break;
+static bool LowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI) {
+ IRBuilder<> Builder(CXI->getParent(), CXI);
+ Value *Ptr = CXI->getPointerOperand();
+ Value *Cmp = CXI->getCompareOperand();
+ Value *Val = CXI->getNewValOperand();
+
+ LoadInst *Orig = Builder.CreateLoad(Ptr);
+ Value *Equal = Builder.CreateICmpEQ(Orig, Cmp);
+ Value *Res = Builder.CreateSelect(Equal, Val, Orig);
+ Builder.CreateStore(Res, Ptr);
+
+ CXI->replaceAllUsesWith(Orig);
+ CXI->eraseFromParent();
+ return true;
+}
- 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: {
- Value *Ptr = II->getArgOperand(0), *Delta = II->getArgOperand(1);
+static bool LowerAtomicRMWInst(AtomicRMWInst *RMWI) {
+ IRBuilder<> Builder(RMWI->getParent(), RMWI);
+ Value *Ptr = RMWI->getPointerOperand();
+ Value *Val = RMWI->getValOperand();
- LoadInst *Orig = Builder.CreateLoad(Ptr);
- Value *Res = NULL;
- switch (IID) {
- default: assert(0 && "Unrecognized atomic modify operation");
- case Intrinsic::atomic_load_add:
- Res = Builder.CreateAdd(Orig, Delta);
- break;
- case Intrinsic::atomic_load_sub:
- Res = Builder.CreateSub(Orig, Delta);
- break;
- case Intrinsic::atomic_load_and:
- Res = Builder.CreateAnd(Orig, Delta);
- break;
- case Intrinsic::atomic_load_nand:
- Res = Builder.CreateNot(Builder.CreateAnd(Orig, Delta));
- break;
- case Intrinsic::atomic_load_or:
- Res = Builder.CreateOr(Orig, Delta);
- break;
- case Intrinsic::atomic_load_xor:
- Res = Builder.CreateXor(Orig, Delta);
- break;
- case Intrinsic::atomic_load_max:
- Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Delta),
- Delta, Orig);
- break;
- case Intrinsic::atomic_load_min:
- Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Delta),
- Orig, Delta);
- break;
- case Intrinsic::atomic_load_umax:
- Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Delta),
- Delta, Orig);
- break;
- case Intrinsic::atomic_load_umin:
- Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Delta),
- Orig, Delta);
- break;
- }
- Builder.CreateStore(Res, Ptr);
+ LoadInst *Orig = Builder.CreateLoad(Ptr);
+ Value *Res = NULL;
- II->replaceAllUsesWith(Orig);
+ switch (RMWI->getOperation()) {
+ default: llvm_unreachable("Unexpected RMW operation");
+ case AtomicRMWInst::Xchg:
+ Res = Val;
break;
- }
-
- case Intrinsic::atomic_swap: {
- Value *Ptr = II->getArgOperand(0), *Val = II->getArgOperand(1);
- LoadInst *Orig = Builder.CreateLoad(Ptr);
- Builder.CreateStore(Val, Ptr);
- II->replaceAllUsesWith(Orig);
+ case AtomicRMWInst::Add:
+ Res = Builder.CreateAdd(Orig, Val);
break;
- }
-
- case Intrinsic::atomic_cmp_swap: {
- Value *Ptr = II->getArgOperand(0), *Cmp = II->getArgOperand(1);
- Value *Val = II->getArgOperand(2);
-
- LoadInst *Orig = Builder.CreateLoad(Ptr);
- Value *Equal = Builder.CreateICmpEQ(Orig, Cmp);
- Value *Res = Builder.CreateSelect(Equal, Val, Orig);
- Builder.CreateStore(Res, Ptr);
- II->replaceAllUsesWith(Orig);
+ case AtomicRMWInst::Sub:
+ Res = Builder.CreateSub(Orig, Val);
+ break;
+ case AtomicRMWInst::And:
+ Res = Builder.CreateAnd(Orig, Val);
+ break;
+ case AtomicRMWInst::Nand:
+ Res = Builder.CreateNot(Builder.CreateAnd(Orig, Val));
+ break;
+ case AtomicRMWInst::Or:
+ Res = Builder.CreateOr(Orig, Val);
+ break;
+ case AtomicRMWInst::Xor:
+ Res = Builder.CreateXor(Orig, Val);
+ break;
+ case AtomicRMWInst::Max:
+ Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val),
+ Val, Orig);
+ break;
+ case AtomicRMWInst::Min:
+ Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val),
+ Orig, Val);
+ break;
+ case AtomicRMWInst::UMax:
+ Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val),
+ Val, Orig);
+ break;
+ case AtomicRMWInst::UMin:
+ Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val),
+ Orig, Val);
break;
}
+ Builder.CreateStore(Res, Ptr);
+ RMWI->replaceAllUsesWith(Orig);
+ RMWI->eraseFromParent();
+ return true;
+}
- default:
- return false;
- }
+static bool LowerFenceInst(FenceInst *FI) {
+ FI->eraseFromParent();
+ return true;
+}
- assert(II->use_empty() &&
- "Lowering should have eliminated any uses of the intrinsic call!");
- II->eraseFromParent();
+static bool LowerLoadInst(LoadInst *LI) {
+ LI->setAtomic(NotAtomic);
+ return true;
+}
+static bool LowerStoreInst(StoreInst *SI) {
+ SI->setAtomic(NotAtomic);
return true;
}
@@ -123,9 +113,22 @@ namespace {
}
bool runOnBasicBlock(BasicBlock &BB) {
bool Changed = false;
- for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; )
- if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(DI++))
- Changed |= LowerAtomicIntrinsic(II);
+ for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) {
+ Instruction *Inst = DI++;
+ if (FenceInst *FI = dyn_cast<FenceInst>(Inst))
+ Changed |= LowerFenceInst(FI);
+ else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(Inst))
+ Changed |= LowerAtomicCmpXchgInst(CXI);
+ else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(Inst))
+ Changed |= LowerAtomicRMWInst(RMWI);
+ else if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
+ if (LI->isAtomic())
+ LowerLoadInst(LI);
+ } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
+ if (SI->isAtomic())
+ LowerStoreInst(SI);
+ }
+ }
return Changed;
}
};
diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 7ed3db6..eeb8931 100644
--- a/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -54,7 +54,7 @@ static int64_t GetOffsetFromIndex(const GetElementPtrInst *GEP, unsigned Idx,
if (OpC->isZero()) continue; // No offset.
// Handle struct indices, which add their field offset to the pointer.
- if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
+ if (StructType *STy = dyn_cast<StructType>(*GTI)) {
Offset += TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue());
continue;
}
@@ -384,7 +384,7 @@ Instruction *MemCpyOpt::tryMergingIntoMemset(Instruction *StartInst,
if (StoreInst *NextStore = dyn_cast<StoreInst>(BI)) {
// If this is a store, see if we can merge it in.
- if (NextStore->isVolatile()) break;
+ if (!NextStore->isSimple()) break;
// Check to see if this stored value is of the same byte-splattable value.
if (ByteVal != isBytewiseValue(NextStore->getOperand(0)))
@@ -448,7 +448,7 @@ Instruction *MemCpyOpt::tryMergingIntoMemset(Instruction *StartInst,
// Determine alignment
unsigned Alignment = Range.Alignment;
if (Alignment == 0) {
- const Type *EltType =
+ Type *EltType =
cast<PointerType>(StartPtr->getType())->getElementType();
Alignment = TD->getABITypeAlignment(EltType);
}
@@ -479,7 +479,7 @@ Instruction *MemCpyOpt::tryMergingIntoMemset(Instruction *StartInst,
bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
- if (SI->isVolatile()) return false;
+ if (!SI->isSimple()) return false;
if (TD == 0) return false;
@@ -487,7 +487,7 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
// happen to be using a load-store pair to implement it, rather than
// a memcpy.
if (LoadInst *LI = dyn_cast<LoadInst>(SI->getOperand(0))) {
- if (!LI->isVolatile() && LI->hasOneUse() &&
+ if (LI->isSimple() && LI->hasOneUse() &&
LI->getParent() == SI->getParent()) {
MemDepResult ldep = MD->getDependency(LI);
CallInst *C = 0;
@@ -616,7 +616,7 @@ bool MemCpyOpt::performCallSlotOptzn(Instruction *cpy,
if (!A->hasStructRetAttr())
return false;
- const Type *StructTy = cast<PointerType>(A->getType())->getElementType();
+ Type *StructTy = cast<PointerType>(A->getType())->getElementType();
uint64_t destSize = TD->getTypeAllocSize(StructTy);
if (destSize < srcSize)
@@ -860,7 +860,7 @@ bool MemCpyOpt::processByValArgument(CallSite CS, unsigned ArgNo) {
// Find out what feeds this byval argument.
Value *ByValArg = CS.getArgument(ArgNo);
- const Type *ByValTy =cast<PointerType>(ByValArg->getType())->getElementType();
+ Type *ByValTy = cast<PointerType>(ByValArg->getType())->getElementType();
uint64_t ByValSize = TD->getTypeAllocSize(ByValTy);
MemDepResult DepInfo =
MD->getPointerDependencyFrom(AliasAnalysis::Location(ByValArg, ByValSize),
diff --git a/lib/Transforms/Scalar/ObjCARC.cpp b/lib/Transforms/Scalar/ObjCARC.cpp
index ee132d3..da74e9c 100644
--- a/lib/Transforms/Scalar/ObjCARC.cpp
+++ b/lib/Transforms/Scalar/ObjCARC.cpp
@@ -180,7 +180,7 @@ static bool IsPotentialUse(const Value *Op) {
Arg->hasStructRetAttr())
return false;
// Only consider values with pointer types, and not function pointers.
- const PointerType *Ty = dyn_cast<PointerType>(Op->getType());
+ PointerType *Ty = dyn_cast<PointerType>(Op->getType());
if (!Ty || isa<FunctionType>(Ty->getElementType()))
return false;
// Conservatively assume anything else is a potential use.
@@ -213,8 +213,8 @@ static InstructionClass GetFunctionClass(const Function *F) {
const Argument *A0 = AI++;
if (AI == AE)
// Argument is a pointer.
- if (const PointerType *PTy = dyn_cast<PointerType>(A0->getType())) {
- const Type *ETy = PTy->getElementType();
+ if (PointerType *PTy = dyn_cast<PointerType>(A0->getType())) {
+ Type *ETy = PTy->getElementType();
// Argument is i8*.
if (ETy->isIntegerTy(8))
return StringSwitch<InstructionClass>(F->getName())
@@ -234,7 +234,7 @@ static InstructionClass GetFunctionClass(const Function *F) {
.Default(IC_CallOrUser);
// Argument is i8**
- if (const PointerType *Pte = dyn_cast<PointerType>(ETy))
+ if (PointerType *Pte = dyn_cast<PointerType>(ETy))
if (Pte->getElementType()->isIntegerTy(8))
return StringSwitch<InstructionClass>(F->getName())
.Case("objc_loadWeakRetained", IC_LoadWeakRetained)
@@ -246,11 +246,11 @@ static InstructionClass GetFunctionClass(const Function *F) {
// Two arguments, first is i8**.
const Argument *A1 = AI++;
if (AI == AE)
- if (const PointerType *PTy = dyn_cast<PointerType>(A0->getType()))
- if (const PointerType *Pte = dyn_cast<PointerType>(PTy->getElementType()))
+ if (PointerType *PTy = dyn_cast<PointerType>(A0->getType()))
+ if (PointerType *Pte = dyn_cast<PointerType>(PTy->getElementType()))
if (Pte->getElementType()->isIntegerTy(8))
- if (const PointerType *PTy1 = dyn_cast<PointerType>(A1->getType())) {
- const Type *ETy1 = PTy1->getElementType();
+ if (PointerType *PTy1 = dyn_cast<PointerType>(A1->getType())) {
+ Type *ETy1 = PTy1->getElementType();
// Second argument is i8*
if (ETy1->isIntegerTy(8))
return StringSwitch<InstructionClass>(F->getName())
@@ -258,7 +258,7 @@ static InstructionClass GetFunctionClass(const Function *F) {
.Case("objc_initWeak", IC_InitWeak)
.Default(IC_CallOrUser);
// Second argument is i8**.
- if (const PointerType *Pte1 = dyn_cast<PointerType>(ETy1))
+ if (PointerType *Pte1 = dyn_cast<PointerType>(ETy1))
if (Pte1->getElementType()->isIntegerTy(8))
return StringSwitch<InstructionClass>(F->getName())
.Case("objc_moveWeak", IC_MoveWeak)
@@ -344,6 +344,10 @@ static InstructionClass GetInstructionClass(const Value *V) {
break;
default:
// For anything else, check all the operands.
+ // Note that this includes both operands of a Store: while the first
+ // operand isn't actually being dereferenced, it is being stored to
+ // memory where we can no longer track who might read it and dereference
+ // it, so we have to consider it potentially used.
for (User::const_op_iterator OI = I->op_begin(), OE = I->op_end();
OI != OE; ++OI)
if (IsPotentialUse(*OI))
@@ -421,9 +425,10 @@ static bool IsAlwaysTail(InstructionClass Class) {
/// IsNoThrow - Test if the given class represents instructions which are always
/// safe to mark with the nounwind attribute..
static bool IsNoThrow(InstructionClass Class) {
+ // objc_retainBlock is not nounwind because it calls user copy constructors
+ // which could theoretically throw.
return Class == IC_Retain ||
Class == IC_RetainRV ||
- Class == IC_RetainBlock ||
Class == IC_Release ||
Class == IC_Autorelease ||
Class == IC_AutoreleaseRV ||
@@ -515,6 +520,10 @@ static bool IsObjCIdentifiedObject(const Value *V) {
const Value *Pointer =
StripPointerCastsAndObjCCalls(LI->getPointerOperand());
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Pointer)) {
+ // A constant pointer can't be pointing to an object on the heap. It may
+ // be reference-counted, but it won't be deleted.
+ if (GV->isConstant())
+ return true;
StringRef Name = GV->getName();
// These special variables are known to hold values which are not
// reference-counted pointers.
@@ -738,7 +747,6 @@ ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS, const Location &Loc) {
switch (GetBasicInstructionClass(CS.getInstruction())) {
case IC_Retain:
case IC_RetainRV:
- case IC_RetainBlock:
case IC_Autorelease:
case IC_AutoreleaseRV:
case IC_NoopCast:
@@ -746,6 +754,8 @@ ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS, const Location &Loc) {
case IC_FusedRetainAutorelease:
case IC_FusedRetainAutoreleaseRV:
// These functions don't access any memory visible to the compiler.
+ // Note that this doesn't include objc_retainBlock, becuase it updates
+ // pointers when it copies block data.
return NoModRef;
default:
break;
@@ -877,7 +887,9 @@ bool ObjCARCExpand::runOnFunction(Function &F) {
// usually can't sink them past other calls, which would be the main
// case where it would be useful.
-/// TODO: The pointer returned from objc_loadWeakRetained is retained.
+// TODO: The pointer returned from objc_loadWeakRetained is retained.
+
+// TODO: Delete release+retain pairs (rare).
#include "llvm/GlobalAlias.h"
#include "llvm/Constants.h"
@@ -1098,16 +1110,16 @@ static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
if (A == S_None || B == S_None)
return S_None;
- // Note that we can't merge S_CanRelease and S_Use.
if (A > B) std::swap(A, B);
if (TopDown) {
// Choose the side which is further along in the sequence.
- if (A == S_Retain && (B == S_CanRelease || B == S_Use))
+ if ((A == S_Retain || A == S_CanRelease) &&
+ (B == S_CanRelease || B == S_Use))
return B;
} else {
// Choose the side which is further along in the sequence.
if ((A == S_Use || A == S_CanRelease) &&
- (B == S_Release || B == S_Stop || B == S_MovableRelease))
+ (B == S_Use || B == S_Release || B == S_Stop || B == S_MovableRelease))
return A;
// If both sides are releases, choose the more conservative one.
if (A == S_Stop && (B == S_Release || B == S_MovableRelease))
@@ -1124,13 +1136,19 @@ namespace {
/// retain-decrement-use-release sequence or release-use-decrement-retain
/// reverese sequence.
struct RRInfo {
- /// KnownIncremented - After an objc_retain, the reference count of the
- /// referenced object is known to be positive. Similarly, before an
- /// objc_release, the reference count of the referenced object is known to
- /// be positive. If there are retain-release pairs in code regions where the
- /// retain count is known to be positive, they can be eliminated, regardless
- /// of any side effects between them.
- bool KnownIncremented;
+ /// KnownSafe - After an objc_retain, the reference count of the referenced
+ /// object is known to be positive. Similarly, before an objc_release, the
+ /// reference count of the referenced object is known to be positive. If
+ /// there are retain-release pairs in code regions where the retain count
+ /// is known to be positive, they can be eliminated, regardless of any side
+ /// effects between them.
+ ///
+ /// Also, a retain+release pair nested within another retain+release
+ /// pair all on the known same pointer value can be eliminated, regardless
+ /// of any intervening side effects.
+ ///
+ /// KnownSafe is true when either of these conditions is satisfied.
+ bool KnownSafe;
/// IsRetainBlock - True if the Calls are objc_retainBlock calls (as
/// opposed to objc_retain calls).
@@ -1153,7 +1171,7 @@ namespace {
SmallPtrSet<Instruction *, 2> ReverseInsertPts;
RRInfo() :
- KnownIncremented(false), IsRetainBlock(false), IsTailCallRelease(false),
+ KnownSafe(false), IsRetainBlock(false), IsTailCallRelease(false),
ReleaseMetadata(0) {}
void clear();
@@ -1161,7 +1179,7 @@ namespace {
}
void RRInfo::clear() {
- KnownIncremented = false;
+ KnownSafe = false;
IsRetainBlock = false;
IsTailCallRelease = false;
ReleaseMetadata = 0;
@@ -1176,6 +1194,9 @@ namespace {
/// RefCount - The known minimum number of reference count increments.
unsigned RefCount;
+ /// NestCount - The known minimum level of retain+release nesting.
+ unsigned NestCount;
+
/// Seq - The current position in the sequence.
Sequence Seq;
@@ -1184,7 +1205,11 @@ namespace {
/// TODO: Encapsulate this better.
RRInfo RRI;
- PtrState() : RefCount(0), Seq(S_None) {}
+ PtrState() : RefCount(0), NestCount(0), Seq(S_None) {}
+
+ void SetAtLeastOneRefCount() {
+ if (RefCount == 0) RefCount = 1;
+ }
void IncrementRefCount() {
if (RefCount != UINT_MAX) ++RefCount;
@@ -1194,14 +1219,22 @@ namespace {
if (RefCount != 0) --RefCount;
}
- void ClearRefCount() {
- RefCount = 0;
- }
-
bool IsKnownIncremented() const {
return RefCount > 0;
}
+ void IncrementNestCount() {
+ if (NestCount != UINT_MAX) ++NestCount;
+ }
+
+ void DecrementNestCount() {
+ if (NestCount != 0) --NestCount;
+ }
+
+ bool IsKnownNested() const {
+ return NestCount > 0;
+ }
+
void SetSeq(Sequence NewSeq) {
Seq = NewSeq;
}
@@ -1233,6 +1266,7 @@ void
PtrState::Merge(const PtrState &Other, bool TopDown) {
Seq = MergeSeqs(Seq, Other.Seq, TopDown);
RefCount = std::min(RefCount, Other.RefCount);
+ NestCount = std::min(NestCount, Other.NestCount);
// We can't merge a plain objc_retain with an objc_retainBlock.
if (RRI.IsRetainBlock != Other.RRI.IsRetainBlock)
@@ -1245,7 +1279,7 @@ PtrState::Merge(const PtrState &Other, bool TopDown) {
if (RRI.ReleaseMetadata != Other.RRI.ReleaseMetadata)
RRI.ReleaseMetadata = 0;
- RRI.KnownIncremented = RRI.KnownIncremented && Other.RRI.KnownIncremented;
+ RRI.KnownSafe = RRI.KnownSafe && Other.RRI.KnownSafe;
RRI.IsTailCallRelease = RRI.IsTailCallRelease && Other.RRI.IsTailCallRelease;
RRI.Calls.insert(Other.RRI.Calls.begin(), Other.RRI.Calls.end());
RRI.ReverseInsertPts.insert(Other.RRI.ReverseInsertPts.begin(),
@@ -1316,7 +1350,7 @@ namespace {
}
void clearBottomUpPointers() {
- PerPtrTopDown.clear();
+ PerPtrBottomUp.clear();
}
void clearTopDownPointers() {
@@ -1334,6 +1368,12 @@ namespace {
unsigned GetAllPathCount() const {
return TopDownPathCount * BottomUpPathCount;
}
+
+ /// IsVisitedTopDown - Test whether the block for this BBState has been
+ /// visited by the top-down portion of the algorithm.
+ bool isVisitedTopDown() const {
+ return TopDownPathCount != 0;
+ }
};
}
@@ -1364,7 +1404,7 @@ void BBState::MergePred(const BBState &Other) {
/*TopDown=*/true);
}
- // For each entry in our set, if the other set doens't have an entry with the
+ // For each entry in our set, if the other set doesn't have an entry with the
// same key, force it to merge with an empty entry.
for (ptr_iterator MI = top_down_ptr_begin(),
ME = top_down_ptr_end(); MI != ME; ++MI)
@@ -1389,7 +1429,7 @@ void BBState::MergeSucc(const BBState &Other) {
/*TopDown=*/false);
}
- // For each entry in our set, if the other set doens't have an entry
+ // For each entry in our set, if the other set doesn't have an entry
// with the same key, force it to merge with an empty entry.
for (ptr_iterator MI = bottom_up_ptr_begin(),
ME = bottom_up_ptr_end(); MI != ME; ++MI)
@@ -1406,15 +1446,11 @@ namespace {
/// Run - A flag indicating whether this optimization pass should run.
bool Run;
- /// RetainFunc, RelaseFunc - Declarations for objc_retain,
- /// objc_retainBlock, and objc_release.
- Function *RetainFunc, *RetainBlockFunc, *RetainRVFunc, *ReleaseFunc;
-
/// RetainRVCallee, etc. - Declarations for ObjC runtime
/// functions, for use in creating calls to them. These are initialized
/// lazily to avoid cluttering up the Module with unused declarations.
Constant *RetainRVCallee, *AutoreleaseRVCallee, *ReleaseCallee,
- *RetainCallee, *AutoreleaseCallee;
+ *RetainCallee, *RetainBlockCallee, *AutoreleaseCallee;
/// UsedInThisFunciton - Flags which determine whether each of the
/// interesting runtine functions is in fact used in the current function.
@@ -1428,6 +1464,7 @@ namespace {
Constant *getAutoreleaseRVCallee(Module *M);
Constant *getReleaseCallee(Module *M);
Constant *getRetainCallee(Module *M);
+ Constant *getRetainBlockCallee(Module *M);
Constant *getAutoreleaseCallee(Module *M);
void OptimizeRetainCall(Function &F, Instruction *Retain);
@@ -1452,11 +1489,13 @@ namespace {
void MoveCalls(Value *Arg, RRInfo &RetainsToMove, RRInfo &ReleasesToMove,
MapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases,
- SmallVectorImpl<Instruction *> &DeadInsts);
+ SmallVectorImpl<Instruction *> &DeadInsts,
+ Module *M);
bool PerformCodePlacement(DenseMap<const BasicBlock *, BBState> &BBStates,
MapVector<Value *, RRInfo> &Retains,
- DenseMap<Value *, RRInfo> &Releases);
+ DenseMap<Value *, RRInfo> &Releases,
+ Module *M);
void OptimizeWeakCalls(Function &F);
@@ -1501,7 +1540,7 @@ Constant *ObjCARCOpt::getRetainRVCallee(Module *M) {
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
std::vector<Type *> Params;
Params.push_back(I8X);
- const FunctionType *FTy =
+ FunctionType *FTy =
FunctionType::get(I8X, Params, /*isVarArg=*/false);
AttrListPtr Attributes;
Attributes.addAttr(~0u, Attribute::NoUnwind);
@@ -1518,7 +1557,7 @@ Constant *ObjCARCOpt::getAutoreleaseRVCallee(Module *M) {
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
std::vector<Type *> Params;
Params.push_back(I8X);
- const FunctionType *FTy =
+ FunctionType *FTy =
FunctionType::get(I8X, Params, /*isVarArg=*/false);
AttrListPtr Attributes;
Attributes.addAttr(~0u, Attribute::NoUnwind);
@@ -1561,6 +1600,23 @@ Constant *ObjCARCOpt::getRetainCallee(Module *M) {
return RetainCallee;
}
+Constant *ObjCARCOpt::getRetainBlockCallee(Module *M) {
+ if (!RetainBlockCallee) {
+ LLVMContext &C = M->getContext();
+ std::vector<Type *> Params;
+ Params.push_back(PointerType::getUnqual(Type::getInt8Ty(C)));
+ AttrListPtr Attributes;
+ // objc_retainBlock is not nounwind because it calls user copy constructors
+ // which could theoretically throw.
+ RetainBlockCallee =
+ M->getOrInsertFunction(
+ "objc_retainBlock",
+ FunctionType::get(Params[0], Params, /*isVarArg=*/false),
+ Attributes);
+ }
+ return RetainBlockCallee;
+}
+
Constant *ObjCARCOpt::getAutoreleaseCallee(Module *M) {
if (!AutoreleaseCallee) {
LLVMContext &C = M->getContext();
@@ -1904,12 +1960,19 @@ void
ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV) {
// Check for a return of the pointer value.
const Value *Ptr = GetObjCArg(AutoreleaseRV);
- for (Value::const_use_iterator UI = Ptr->use_begin(), UE = Ptr->use_end();
- UI != UE; ++UI) {
- const User *I = *UI;
- if (isa<ReturnInst>(I) || GetBasicInstructionClass(I) == IC_RetainRV)
- return;
- }
+ SmallVector<const Value *, 2> Users;
+ Users.push_back(Ptr);
+ do {
+ Ptr = Users.pop_back_val();
+ for (Value::const_use_iterator UI = Ptr->use_begin(), UE = Ptr->use_end();
+ UI != UE; ++UI) {
+ const User *I = *UI;
+ if (isa<ReturnInst>(I) || GetBasicInstructionClass(I) == IC_RetainRV)
+ return;
+ if (isa<BitCastInst>(I))
+ Users.push_back(I);
+ }
+ } while (!Users.empty());
Changed = true;
++NumPeeps;
@@ -1953,7 +2016,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
case IC_DestroyWeak: {
CallInst *CI = cast<CallInst>(Inst);
if (isNullOrUndef(CI->getArgOperand(0))) {
- const Type *Ty = CI->getArgOperand(0)->getType();
+ Type *Ty = CI->getArgOperand(0)->getType();
new StoreInst(UndefValue::get(cast<PointerType>(Ty)->getElementType()),
Constant::getNullValue(Ty),
CI);
@@ -1968,7 +2031,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
CallInst *CI = cast<CallInst>(Inst);
if (isNullOrUndef(CI->getArgOperand(0)) ||
isNullOrUndef(CI->getArgOperand(1))) {
- const Type *Ty = CI->getArgOperand(0)->getType();
+ Type *Ty = CI->getArgOperand(0)->getType();
new StoreInst(UndefValue::get(cast<PointerType>(Ty)->getElementType()),
Constant::getNullValue(Ty),
CI);
@@ -2090,7 +2153,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
++NumPartialNoops;
// Clone the call into each predecessor that has a non-null value.
CallInst *CInst = cast<CallInst>(Inst);
- const Type *ParamTy = CInst->getArgOperand(0)->getType();
+ Type *ParamTy = CInst->getArgOperand(0)->getType();
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
Value *Incoming =
StripPointerCastsAndObjCCalls(PN->getIncomingValue(i));
@@ -2132,41 +2195,49 @@ ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,
const TerminatorInst *TI = cast<TerminatorInst>(&BB->back());
bool SomeSuccHasSame = false;
bool AllSuccsHaveSame = true;
- for (succ_const_iterator SI(TI), SE(TI, false); SI != SE; ++SI)
- switch (BBStates[*SI].getPtrBottomUpState(Arg).GetSeq()) {
+ PtrState &S = MyStates.getPtrTopDownState(Arg);
+ for (succ_const_iterator SI(TI), SE(TI, false); SI != SE; ++SI) {
+ PtrState &SuccS = BBStates[*SI].getPtrBottomUpState(Arg);
+ switch (SuccS.GetSeq()) {
case S_None:
- case S_CanRelease:
- MyStates.getPtrTopDownState(Arg).ClearSequenceProgress();
- SomeSuccHasSame = false;
- break;
+ case S_CanRelease: {
+ if (!S.RRI.KnownSafe && !SuccS.RRI.KnownSafe)
+ S.ClearSequenceProgress();
+ continue;
+ }
case S_Use:
SomeSuccHasSame = true;
break;
case S_Stop:
case S_Release:
case S_MovableRelease:
- AllSuccsHaveSame = false;
+ if (!S.RRI.KnownSafe && !SuccS.RRI.KnownSafe)
+ AllSuccsHaveSame = false;
break;
case S_Retain:
llvm_unreachable("bottom-up pointer in retain state!");
}
+ }
// If the state at the other end of any of the successor edges
// matches the current state, require all edges to match. This
// guards against loops in the middle of a sequence.
if (SomeSuccHasSame && !AllSuccsHaveSame)
- MyStates.getPtrTopDownState(Arg).ClearSequenceProgress();
+ S.ClearSequenceProgress();
}
case S_CanRelease: {
const Value *Arg = I->first;
const TerminatorInst *TI = cast<TerminatorInst>(&BB->back());
bool SomeSuccHasSame = false;
bool AllSuccsHaveSame = true;
- for (succ_const_iterator SI(TI), SE(TI, false); SI != SE; ++SI)
- switch (BBStates[*SI].getPtrBottomUpState(Arg).GetSeq()) {
- case S_None:
- MyStates.getPtrTopDownState(Arg).ClearSequenceProgress();
- SomeSuccHasSame = false;
- break;
+ PtrState &S = MyStates.getPtrTopDownState(Arg);
+ for (succ_const_iterator SI(TI), SE(TI, false); SI != SE; ++SI) {
+ PtrState &SuccS = BBStates[*SI].getPtrBottomUpState(Arg);
+ switch (SuccS.GetSeq()) {
+ case S_None: {
+ if (!S.RRI.KnownSafe && !SuccS.RRI.KnownSafe)
+ S.ClearSequenceProgress();
+ continue;
+ }
case S_CanRelease:
SomeSuccHasSame = true;
break;
@@ -2174,16 +2245,18 @@ ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,
case S_Release:
case S_MovableRelease:
case S_Use:
- AllSuccsHaveSame = false;
+ if (!S.RRI.KnownSafe && !SuccS.RRI.KnownSafe)
+ AllSuccsHaveSame = false;
break;
case S_Retain:
llvm_unreachable("bottom-up pointer in retain state!");
}
+ }
// If the state at the other end of any of the successor edges
// matches the current state, require all edges to match. This
// guards against loops in the middle of a sequence.
if (SomeSuccHasSame && !AllSuccsHaveSame)
- MyStates.getPtrTopDownState(Arg).ClearSequenceProgress();
+ S.ClearSequenceProgress();
}
}
}
@@ -2207,6 +2280,8 @@ ObjCARCOpt::VisitBottomUp(BasicBlock *BB,
if (Succ == BB)
continue;
DenseMap<const BasicBlock *, BBState>::iterator I = BBStates.find(Succ);
+ // If we haven't seen this node yet, then we've found a CFG cycle.
+ // Be optimistic here; it's CheckForCFGHazards' job detect trouble.
if (I == BBStates.end())
continue;
MyStates.InitFromSucc(I->second);
@@ -2245,11 +2320,12 @@ ObjCARCOpt::VisitBottomUp(BasicBlock *BB,
S.SetSeqToRelease(Inst->getMetadata(ImpreciseReleaseMDKind));
S.RRI.clear();
- S.RRI.KnownIncremented = S.IsKnownIncremented();
+ S.RRI.KnownSafe = S.IsKnownNested() || S.IsKnownIncremented();
S.RRI.IsTailCallRelease = cast<CallInst>(Inst)->isTailCall();
S.RRI.Calls.insert(Inst);
S.IncrementRefCount();
+ S.IncrementNestCount();
break;
}
case IC_RetainBlock:
@@ -2259,6 +2335,13 @@ ObjCARCOpt::VisitBottomUp(BasicBlock *BB,
PtrState &S = MyStates.getPtrBottomUpState(Arg);
S.DecrementRefCount();
+ S.SetAtLeastOneRefCount();
+ S.DecrementNestCount();
+
+ // An objc_retainBlock call with just a use still needs to be kept,
+ // because it may be copying a block from the stack to the heap.
+ if (Class == IC_RetainBlock && S.GetSeq() == S_Use)
+ S.SetSeq(S_CanRelease);
switch (S.GetSeq()) {
case S_Stop:
@@ -2281,7 +2364,7 @@ ObjCARCOpt::VisitBottomUp(BasicBlock *BB,
case S_Retain:
llvm_unreachable("bottom-up pointer in retain state!");
}
- break;
+ continue;
}
case IC_AutoreleasepoolPop:
// Conservatively, clear MyStates for all known pointers.
@@ -2305,26 +2388,22 @@ ObjCARCOpt::VisitBottomUp(BasicBlock *BB,
PtrState &S = MI->second;
Sequence Seq = S.GetSeq();
- // Check for possible retains and releases.
+ // Check for possible releases.
if (CanAlterRefCount(Inst, Ptr, PA, Class)) {
- // Check for a retain (we're going bottom-up here).
S.DecrementRefCount();
-
- // Check for a release.
- if (!IsRetain(Class) && Class != IC_RetainBlock)
- switch (Seq) {
- case S_Use:
- S.SetSeq(S_CanRelease);
- continue;
- case S_CanRelease:
- case S_Release:
- case S_MovableRelease:
- case S_Stop:
- case S_None:
- break;
- case S_Retain:
- llvm_unreachable("bottom-up pointer in retain state!");
- }
+ switch (Seq) {
+ case S_Use:
+ S.SetSeq(S_CanRelease);
+ continue;
+ case S_CanRelease:
+ case S_Release:
+ case S_MovableRelease:
+ case S_Stop:
+ case S_None:
+ break;
+ case S_Retain:
+ llvm_unreachable("bottom-up pointer in retain state!");
+ }
}
// Check for possible direct uses.
@@ -2332,14 +2411,14 @@ ObjCARCOpt::VisitBottomUp(BasicBlock *BB,
case S_Release:
case S_MovableRelease:
if (CanUse(Inst, Ptr, PA, Class)) {
- S.RRI.ReverseInsertPts.clear();
+ assert(S.RRI.ReverseInsertPts.empty());
S.RRI.ReverseInsertPts.insert(Inst);
S.SetSeq(S_Use);
} else if (Seq == S_Release &&
(Class == IC_User || Class == IC_CallOrUser)) {
// Non-movable releases depend on any possible objc pointer use.
S.SetSeq(S_Stop);
- S.RRI.ReverseInsertPts.clear();
+ assert(S.RRI.ReverseInsertPts.empty());
S.RRI.ReverseInsertPts.insert(Inst);
}
break;
@@ -2378,14 +2457,18 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB,
if (Pred == BB)
continue;
DenseMap<const BasicBlock *, BBState>::iterator I = BBStates.find(Pred);
- if (I == BBStates.end())
+ assert(I != BBStates.end());
+ // If we haven't seen this node yet, then we've found a CFG cycle.
+ // Be optimistic here; it's CheckForCFGHazards' job detect trouble.
+ if (!I->second.isVisitedTopDown())
continue;
MyStates.InitFromPred(I->second);
while (PI != PE) {
Pred = *PI++;
if (Pred != BB) {
I = BBStates.find(Pred);
- if (I != BBStates.end())
+ assert(I != BBStates.end());
+ if (I->second.isVisitedTopDown())
MyStates.MergePred(I->second);
}
}
@@ -2422,18 +2505,23 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB,
S.SetSeq(S_Retain);
S.RRI.clear();
S.RRI.IsRetainBlock = Class == IC_RetainBlock;
- S.RRI.KnownIncremented = S.IsKnownIncremented();
+ // Don't check S.IsKnownIncremented() here because it's not
+ // sufficient.
+ S.RRI.KnownSafe = S.IsKnownNested();
S.RRI.Calls.insert(Inst);
}
+ S.SetAtLeastOneRefCount();
S.IncrementRefCount();
- break;
+ S.IncrementNestCount();
+ continue;
}
case IC_Release: {
Arg = GetObjCArg(Inst);
PtrState &S = MyStates.getPtrTopDownState(Arg);
S.DecrementRefCount();
+ S.DecrementNestCount();
switch (S.GetSeq()) {
case S_Retain:
@@ -2478,16 +2566,12 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB,
Sequence Seq = S.GetSeq();
// Check for possible releases.
- if (!IsRetain(Class) && Class != IC_RetainBlock &&
- CanAlterRefCount(Inst, Ptr, PA, Class)) {
- // Check for a release.
+ if (CanAlterRefCount(Inst, Ptr, PA, Class)) {
S.DecrementRefCount();
-
- // Check for a release.
switch (Seq) {
case S_Retain:
S.SetSeq(S_CanRelease);
- S.RRI.ReverseInsertPts.clear();
+ assert(S.RRI.ReverseInsertPts.empty());
S.RRI.ReverseInsertPts.insert(Inst);
// One call can't cause a transition from S_Retain to S_CanRelease
@@ -2511,8 +2595,18 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB,
if (CanUse(Inst, Ptr, PA, Class))
S.SetSeq(S_Use);
break;
- case S_Use:
case S_Retain:
+ // An objc_retainBlock call may be responsible for copying the block
+ // data from the stack to the heap. Model this by moving it straight
+ // from S_Retain to S_Use.
+ if (S.RRI.IsRetainBlock &&
+ CanUse(Inst, Ptr, PA, Class)) {
+ assert(S.RRI.ReverseInsertPts.empty());
+ S.RRI.ReverseInsertPts.insert(Inst);
+ S.SetSeq(S_Use);
+ }
+ break;
+ case S_Use:
case S_None:
break;
case S_Stop:
@@ -2533,28 +2627,43 @@ ObjCARCOpt::Visit(Function &F,
DenseMap<const BasicBlock *, BBState> &BBStates,
MapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases) {
- // Use postorder for bottom-up, and reverse-postorder for top-down, because we
+ // Use reverse-postorder on the reverse CFG for bottom-up, because we
// magically know that loops will be well behaved, i.e. they won't repeatedly
- // call retain on a single pointer without doing a release.
+ // call retain on a single pointer without doing a release. We can't use
+ // ReversePostOrderTraversal here because we want to walk up from each
+ // function exit point.
+ SmallPtrSet<BasicBlock *, 16> Visited;
+ SmallVector<std::pair<BasicBlock *, pred_iterator>, 16> Stack;
+ SmallVector<BasicBlock *, 16> Order;
+ for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
+ BasicBlock *BB = I;
+ if (BB->getTerminator()->getNumSuccessors() == 0)
+ Stack.push_back(std::make_pair(BB, pred_begin(BB)));
+ }
+ while (!Stack.empty()) {
+ pred_iterator End = pred_end(Stack.back().first);
+ while (Stack.back().second != End) {
+ BasicBlock *BB = *Stack.back().second++;
+ if (Visited.insert(BB))
+ Stack.push_back(std::make_pair(BB, pred_begin(BB)));
+ }
+ Order.push_back(Stack.pop_back_val().first);
+ }
bool BottomUpNestingDetected = false;
- SmallVector<BasicBlock *, 8> PostOrder;
- for (po_iterator<Function *> I = po_begin(&F), E = po_end(&F); I != E; ++I) {
+ for (SmallVectorImpl<BasicBlock *>::const_reverse_iterator I =
+ Order.rbegin(), E = Order.rend(); I != E; ++I) {
BasicBlock *BB = *I;
- PostOrder.push_back(BB);
-
BottomUpNestingDetected |= VisitBottomUp(BB, BBStates, Retains);
}
- // Iterate through the post-order in reverse order, achieving a
- // reverse-postorder traversal. We don't use the ReversePostOrderTraversal
- // class here because it works by computing its own full postorder iteration,
- // recording the sequence, and playing it back in reverse. Since we're already
- // doing a full iteration above, we can just record the sequence manually and
- // avoid the cost of having ReversePostOrderTraversal compute it.
+ // Use regular reverse-postorder for top-down.
bool TopDownNestingDetected = false;
- for (SmallVectorImpl<BasicBlock *>::const_reverse_iterator
- RI = PostOrder.rbegin(), RE = PostOrder.rend(); RI != RE; ++RI)
- TopDownNestingDetected |= VisitTopDown(*RI, BBStates, Releases);
+ typedef ReversePostOrderTraversal<Function *> RPOTType;
+ RPOTType RPOT(&F);
+ for (RPOTType::rpo_iterator I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
+ BasicBlock *BB = *I;
+ TopDownNestingDetected |= VisitTopDown(BB, BBStates, Releases);
+ }
return TopDownNestingDetected && BottomUpNestingDetected;
}
@@ -2565,12 +2674,10 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
RRInfo &ReleasesToMove,
MapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases,
- SmallVectorImpl<Instruction *> &DeadInsts) {
- const Type *ArgTy = Arg->getType();
- const Type *ParamTy =
- (RetainRVFunc ? RetainRVFunc :
- RetainFunc ? RetainFunc :
- RetainBlockFunc)->arg_begin()->getType();
+ SmallVectorImpl<Instruction *> &DeadInsts,
+ Module *M) {
+ Type *ArgTy = Arg->getType();
+ Type *ParamTy = PointerType::getUnqual(Type::getInt8Ty(ArgTy->getContext()));
// Insert the new retain and release calls.
for (SmallPtrSet<Instruction *, 2>::const_iterator
@@ -2581,7 +2688,7 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
new BitCastInst(Arg, ParamTy, "", InsertPt);
CallInst *Call =
CallInst::Create(RetainsToMove.IsRetainBlock ?
- RetainBlockFunc : RetainFunc,
+ getRetainBlockCallee(M) : getRetainCallee(M),
MyArg, "", InsertPt);
Call->setDoesNotThrow();
if (!RetainsToMove.IsRetainBlock)
@@ -2598,8 +2705,8 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
// The invoke's return value isn't available in the unwind block,
// but our releases will never depend on it, because they must be
// paired with retains from before the invoke.
- InsertPts[0] = II->getNormalDest()->getFirstNonPHI();
- InsertPts[1] = II->getUnwindDest()->getFirstNonPHI();
+ InsertPts[0] = II->getNormalDest()->getFirstInsertionPt();
+ InsertPts[1] = II->getUnwindDest()->getFirstInsertionPt();
} else {
// Insert code immediately after the last use.
InsertPts[0] = llvm::next(BasicBlock::iterator(LastUse));
@@ -2609,7 +2716,8 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
Instruction *InsertPt = *I;
Value *MyArg = ArgTy == ParamTy ? Arg :
new BitCastInst(Arg, ParamTy, "", InsertPt);
- CallInst *Call = CallInst::Create(ReleaseFunc, MyArg, "", InsertPt);
+ CallInst *Call = CallInst::Create(getReleaseCallee(M), MyArg,
+ "", InsertPt);
// Attach a clang.imprecise_release metadata tag, if appropriate.
if (MDNode *M = ReleasesToMove.ReleaseMetadata)
Call->setMetadata(ImpreciseReleaseMDKind, M);
@@ -2640,7 +2748,8 @@ bool
ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
&BBStates,
MapVector<Value *, RRInfo> &Retains,
- DenseMap<Value *, RRInfo> &Releases) {
+ DenseMap<Value *, RRInfo> &Releases,
+ Module *M) {
bool AnyPairsCompletelyEliminated = false;
RRInfo RetainsToMove;
RRInfo ReleasesToMove;
@@ -2649,21 +2758,36 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
SmallVector<Instruction *, 8> DeadInsts;
for (MapVector<Value *, RRInfo>::const_iterator I = Retains.begin(),
- E = Retains.end(); I != E; ) {
- Value *V = (I++)->first;
+ E = Retains.end(); I != E; ++I) {
+ Value *V = I->first;
if (!V) continue; // blotted
Instruction *Retain = cast<Instruction>(V);
Value *Arg = GetObjCArg(Retain);
- // If the object being released is in static or stack storage, we know it's
+ // If the object being released is in static storage, we know it's
// not being managed by ObjC reference counting, so we can delete pairs
// regardless of what possible decrements or uses lie between them.
- bool KnownSafe = isa<Constant>(Arg) || isa<AllocaInst>(Arg);
+ bool KnownSafe = isa<Constant>(Arg);
+
+ // Same for stack storage, unless this is an objc_retainBlock call,
+ // which is responsible for copying the block data from the stack to
+ // the heap.
+ if (!I->second.IsRetainBlock && isa<AllocaInst>(Arg))
+ KnownSafe = true;
+
+ // A constant pointer can't be pointing to an object on the heap. It may
+ // be reference-counted, but it won't be deleted.
+ if (const LoadInst *LI = dyn_cast<LoadInst>(Arg))
+ if (const GlobalVariable *GV =
+ dyn_cast<GlobalVariable>(
+ StripPointerCastsAndObjCCalls(LI->getPointerOperand())))
+ if (GV->isConstant())
+ KnownSafe = true;
// If a pair happens in a region where it is known that the reference count
// is already incremented, we can similarly ignore possible decrements.
- bool KnownIncrementedTD = true, KnownIncrementedBU = true;
+ bool KnownSafeTD = true, KnownSafeBU = true;
// Connect the dots between the top-down-collected RetainsToMove and
// bottom-up-collected ReleasesToMove to form sets of related calls.
@@ -2683,7 +2807,7 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
MapVector<Value *, RRInfo>::const_iterator It = Retains.find(NewRetain);
assert(It != Retains.end());
const RRInfo &NewRetainRRI = It->second;
- KnownIncrementedTD &= NewRetainRRI.KnownIncremented;
+ KnownSafeTD &= NewRetainRRI.KnownSafe;
for (SmallPtrSet<Instruction *, 2>::const_iterator
LI = NewRetainRRI.Calls.begin(),
LE = NewRetainRRI.Calls.end(); LI != LE; ++LI) {
@@ -2739,7 +2863,7 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
Releases.find(NewRelease);
assert(It != Releases.end());
const RRInfo &NewReleaseRRI = It->second;
- KnownIncrementedBU &= NewReleaseRRI.KnownIncremented;
+ KnownSafeBU &= NewReleaseRRI.KnownSafe;
for (SmallPtrSet<Instruction *, 2>::const_iterator
LI = NewReleaseRRI.Calls.begin(),
LE = NewReleaseRRI.Calls.end(); LI != LE; ++LI) {
@@ -2787,12 +2911,19 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
if (NewRetains.empty()) break;
}
- // If the pointer is known incremented, we can safely delete the pair
- // regardless of what's between them.
- if (KnownIncrementedTD || KnownIncrementedBU) {
+ // If the pointer is known incremented or nested, we can safely delete the
+ // pair regardless of what's between them.
+ if (KnownSafeTD || KnownSafeBU) {
RetainsToMove.ReverseInsertPts.clear();
ReleasesToMove.ReverseInsertPts.clear();
NewCount = 0;
+ } else {
+ // Determine whether the new insertion points we computed preserve the
+ // balance of retain and release calls through the program.
+ // TODO: If the fully aggressive solution isn't valid, try to find a
+ // less aggressive solution which is.
+ if (NewDelta != 0)
+ goto next_retain;
}
// Determine whether the original call points are balanced in the retain and
@@ -2803,18 +2934,12 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
if (OldDelta != 0)
goto next_retain;
- // Determine whether the new insertion points we computed preserve the
- // balance of retain and release calls through the program.
- // TODO: If the fully aggressive solution isn't valid, try to find a
- // less aggressive solution which is.
- if (NewDelta != 0)
- goto next_retain;
-
// Ok, everything checks out and we're all set. Let's move some code!
Changed = true;
AnyPairsCompletelyEliminated = NewCount == 0;
NumRRs += OldCount - NewCount;
- MoveCalls(Arg, RetainsToMove, ReleasesToMove, Retains, Releases, DeadInsts);
+ MoveCalls(Arg, RetainsToMove, ReleasesToMove,
+ Retains, Releases, DeadInsts, M);
next_retain:
NewReleases.clear();
@@ -2993,7 +3118,8 @@ bool ObjCARCOpt::OptimizeSequences(Function &F) {
bool NestingDetected = Visit(F, BBStates, Retains, Releases);
// Transform.
- return PerformCodePlacement(BBStates, Retains, Releases) && NestingDetected;
+ return PerformCodePlacement(BBStates, Retains, Releases, F.getParent()) &&
+ NestingDetected;
}
/// OptimizeReturns - Look for this pattern:
@@ -3072,7 +3198,8 @@ void ObjCARCOpt::OptimizeReturns(Function &F) {
// Check that there is nothing that can affect the reference
// count between the retain and the call.
- FindDependencies(CanChangeRetainCount, Arg, BB, Retain,
+ // Note that Retain need not be in BB.
+ FindDependencies(CanChangeRetainCount, Arg, Retain->getParent(), Retain,
DependingInstructions, Visited, PA);
if (DependingInstructions.size() != 1)
goto next_block;
@@ -3117,12 +3244,6 @@ bool ObjCARCOpt::doInitialization(Module &M) {
ImpreciseReleaseMDKind =
M.getContext().getMDKindID("clang.imprecise_release");
- // Identify the declarations for objc_retain and friends.
- RetainFunc = M.getFunction("objc_retain");
- RetainBlockFunc = M.getFunction("objc_retainBlock");
- RetainRVFunc = M.getFunction("objc_retainAutoreleasedReturnValue");
- ReleaseFunc = M.getFunction("objc_release");
-
// Intuitively, objc_retain and others are nocapture, however in practice
// they are not, because they return their argument value. And objc_release
// calls finalizers.
@@ -3132,6 +3253,7 @@ bool ObjCARCOpt::doInitialization(Module &M) {
AutoreleaseRVCallee = 0;
ReleaseCallee = 0;
RetainCallee = 0;
+ RetainBlockCallee = 0;
AutoreleaseCallee = 0;
return false;
@@ -3294,7 +3416,7 @@ Constant *ObjCARCContract::getRetainAutoreleaseCallee(Module *M) {
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
std::vector<Type *> Params;
Params.push_back(I8X);
- const FunctionType *FTy =
+ FunctionType *FTy =
FunctionType::get(I8X, Params, /*isVarArg=*/false);
AttrListPtr Attributes;
Attributes.addAttr(~0u, Attribute::NoUnwind);
@@ -3310,7 +3432,7 @@ Constant *ObjCARCContract::getRetainAutoreleaseRVCallee(Module *M) {
Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
std::vector<Type *> Params;
Params.push_back(I8X);
- const FunctionType *FTy =
+ FunctionType *FTy =
FunctionType::get(I8X, Params, /*isVarArg=*/false);
AttrListPtr Attributes;
Attributes.addAttr(~0u, Attribute::NoUnwind);
@@ -3377,7 +3499,7 @@ ObjCARCContract::ContractAutorelease(Function &F, Instruction *Autorelease,
void ObjCARCContract::ContractRelease(Instruction *Release,
inst_iterator &Iter) {
LoadInst *Load = dyn_cast<LoadInst>(GetObjCArg(Release));
- if (!Load || Load->isVolatile()) return;
+ if (!Load || !Load->isSimple()) return;
// For now, require everything to be in one basic block.
BasicBlock *BB = Release->getParent();
@@ -3393,7 +3515,7 @@ void ObjCARCContract::ContractRelease(Instruction *Release,
!(AA->getModRefInfo(I, Loc) & AliasAnalysis::Mod)))
++I;
StoreInst *Store = dyn_cast<StoreInst>(I);
- if (!Store || Store->isVolatile()) return;
+ if (!Store || !Store->isSimple()) return;
if (Store->getPointerOperand() != Loc.Ptr) return;
Value *New = StripPointerCastsAndObjCCalls(Store->getValueOperand());
@@ -3411,8 +3533,8 @@ void ObjCARCContract::ContractRelease(Instruction *Release,
++NumStoreStrongs;
LLVMContext &C = Release->getContext();
- const Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
- const Type *I8XX = PointerType::getUnqual(I8X);
+ Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
+ Type *I8XX = PointerType::getUnqual(I8X);
Value *Args[] = { Load->getPointerOperand(), New };
if (Args[0]->getType() != I8XX)
@@ -3548,7 +3670,7 @@ bool ObjCARCContract::runOnFunction(Function &F) {
if (Inst != UserInst && DT->dominates(Inst, UserInst)) {
Changed = true;
Instruction *Replacement = Inst;
- const Type *UseTy = U.get()->getType();
+ Type *UseTy = U.get()->getType();
if (PHINode *PHI = dyn_cast<PHINode>(UserInst)) {
// For PHI nodes, insert the bitcast in the predecessor block.
unsigned ValNo =
diff --git a/lib/Transforms/Scalar/Reassociate.cpp b/lib/Transforms/Scalar/Reassociate.cpp
index e6341ae..8f98a5b 100644
--- a/lib/Transforms/Scalar/Reassociate.cpp
+++ b/lib/Transforms/Scalar/Reassociate.cpp
@@ -309,7 +309,7 @@ void Reassociate::LinearizeExprTree(BinaryOperator *I,
std::swap(LHS, RHS);
bool Success = !I->swapOperands();
assert(Success && "swapOperands failed");
- Success = false;
+ (void)Success;
MadeChange = true;
} else if (RHSBO) {
// Turn (A+B)+(C+D) -> (((A+B)+C)+D). This guarantees the RHS is not
diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp
index 083412e..196a847 100644
--- a/lib/Transforms/Scalar/SCCP.cpp
+++ b/lib/Transforms/Scalar/SCCP.cpp
@@ -156,7 +156,7 @@ namespace {
///
class SCCPSolver : public InstVisitor<SCCPSolver> {
const TargetData *TD;
- SmallPtrSet<BasicBlock*, 8> BBExecutable;// The BBs that are executable.
+ SmallPtrSet<BasicBlock*, 8> BBExecutable; // The BBs that are executable.
DenseMap<Value*, LatticeVal> ValueState; // The state each value is in.
/// StructValueState - This maintains ValueState for values that have
@@ -241,7 +241,7 @@ public:
/// this method must be called.
void AddTrackedFunction(Function *F) {
// Add an entry, F -> undef.
- if (const StructType *STy = dyn_cast<StructType>(F->getReturnType())) {
+ if (StructType *STy = dyn_cast<StructType>(F->getReturnType())) {
MRVFunctionsTracked.insert(F);
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
TrackedMultipleRetVals.insert(std::make_pair(std::make_pair(F, i),
@@ -302,7 +302,7 @@ public:
/// markAnythingOverdefined - Mark the specified value overdefined. This
/// works with both scalars and structs.
void markAnythingOverdefined(Value *V) {
- if (const StructType *STy = dyn_cast<StructType>(V->getType()))
+ if (StructType *STy = dyn_cast<StructType>(V->getType()))
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
markOverdefined(getStructValueState(V, i), V);
else
@@ -417,7 +417,7 @@ private:
else if (ConstantStruct *CS = dyn_cast<ConstantStruct>(C))
LV.markConstant(CS->getOperand(i)); // Constants are constant.
else if (isa<ConstantAggregateZero>(C)) {
- const Type *FieldTy = cast<StructType>(V->getType())->getElementType(i);
+ Type *FieldTy = cast<StructType>(V->getType())->getElementType(i);
LV.markConstant(Constant::getNullValue(FieldTy));
} else
LV.markOverdefined(); // Unknown sort of constant.
@@ -471,9 +471,9 @@ private:
/// UsersOfOverdefinedPHIs map for PN, remove them now.
void RemoveFromOverdefinedPHIs(Instruction *I, PHINode *PN) {
if (UsersOfOverdefinedPHIs.empty()) return;
- std::multimap<PHINode*, Instruction*>::iterator It, E;
- tie(It, E) = UsersOfOverdefinedPHIs.equal_range(PN);
- while (It != E) {
+ typedef std::multimap<PHINode*, Instruction*>::iterator ItTy;
+ std::pair<ItTy, ItTy> Range = UsersOfOverdefinedPHIs.equal_range(PN);
+ for (ItTy It = Range.first, E = Range.second; It != E;) {
if (It->second == I)
UsersOfOverdefinedPHIs.erase(It++);
else
@@ -486,9 +486,9 @@ private:
/// (Duplicate entries do not break anything directly, but can lead to
/// exponential growth of the table in rare cases.)
void InsertInOverdefinedPHIs(Instruction *I, PHINode *PN) {
- std::multimap<PHINode*, Instruction*>::iterator J, E;
- tie(J, E) = UsersOfOverdefinedPHIs.equal_range(PN);
- for (; J != E; ++J)
+ typedef std::multimap<PHINode*, Instruction*>::iterator ItTy;
+ std::pair<ItTy, ItTy> Range = UsersOfOverdefinedPHIs.equal_range(PN);
+ for (ItTy J = Range.first, E = Range.second; J != E; ++J)
if (J->second == I)
return;
UsersOfOverdefinedPHIs.insert(std::make_pair(PN, I));
@@ -515,6 +515,7 @@ private:
void visitShuffleVectorInst(ShuffleVectorInst &I);
void visitExtractValueInst(ExtractValueInst &EVI);
void visitInsertValueInst(InsertValueInst &IVI);
+ void visitLandingPadInst(LandingPadInst &I) { markAnythingOverdefined(&I); }
// Instructions that cannot be folded away.
void visitStoreInst (StoreInst &I);
@@ -528,8 +529,12 @@ private:
visitTerminatorInst(II);
}
void visitCallSite (CallSite CS);
+ void visitResumeInst (TerminatorInst &I) { /*returns void*/ }
void visitUnwindInst (TerminatorInst &I) { /*returns void*/ }
void visitUnreachableInst(TerminatorInst &I) { /*returns void*/ }
+ void visitFenceInst (FenceInst &I) { /*returns void*/ }
+ void visitAtomicCmpXchgInst (AtomicCmpXchgInst &I) { markOverdefined(&I); }
+ void visitAtomicRMWInst (AtomicRMWInst &I) { markOverdefined(&I); }
void visitAllocaInst (Instruction &I) { markOverdefined(&I); }
void visitVAArgInst (Instruction &I) { markAnythingOverdefined(&I); }
@@ -577,6 +582,10 @@ void SCCPSolver::getFeasibleSuccessors(TerminatorInst &TI,
}
if (SwitchInst *SI = dyn_cast<SwitchInst>(&TI)) {
+ if (TI.getNumSuccessors() < 2) {
+ Succs[0] = true;
+ return;
+ }
LatticeVal SCValue = getValueState(SI->getCondition());
ConstantInt *CI = SCValue.getConstantInt();
@@ -637,6 +646,9 @@ bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) {
return true;
if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
+ if (SI->getNumSuccessors() < 2)
+ return true;
+
LatticeVal SCValue = getValueState(SI->getCondition());
ConstantInt *CI = SCValue.getConstantInt();
@@ -692,13 +704,14 @@ void SCCPSolver::visitPHINode(PHINode &PN) {
// There may be instructions using this PHI node that are not overdefined
// themselves. If so, make sure that they know that the PHI node operand
// changed.
- std::multimap<PHINode*, Instruction*>::iterator I, E;
- tie(I, E) = UsersOfOverdefinedPHIs.equal_range(&PN);
- if (I == E)
+ typedef std::multimap<PHINode*, Instruction*>::iterator ItTy;
+ std::pair<ItTy, ItTy> Range = UsersOfOverdefinedPHIs.equal_range(&PN);
+
+ if (Range.first == Range.second)
return;
SmallVector<Instruction*, 16> Users;
- for (; I != E; ++I)
+ for (ItTy I = Range.first, E = Range.second; I != E; ++I)
Users.push_back(I->second);
while (!Users.empty())
visit(Users.pop_back_val());
@@ -772,7 +785,7 @@ void SCCPSolver::visitReturnInst(ReturnInst &I) {
// Handle functions that return multiple values.
if (!TrackedMultipleRetVals.empty()) {
- if (const StructType *STy = dyn_cast<StructType>(ResultOp->getType()))
+ if (StructType *STy = dyn_cast<StructType>(ResultOp->getType()))
if (MRVFunctionsTracked.count(F))
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
mergeInValue(TrackedMultipleRetVals[std::make_pair(F, i)], F,
@@ -825,7 +838,7 @@ void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) {
}
void SCCPSolver::visitInsertValueInst(InsertValueInst &IVI) {
- const StructType *STy = dyn_cast<StructType>(IVI.getType());
+ StructType *STy = dyn_cast<StructType>(IVI.getType());
if (STy == 0)
return markOverdefined(&IVI);
@@ -925,7 +938,7 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
// Could annihilate value.
if (I.getOpcode() == Instruction::And)
markConstant(IV, &I, Constant::getNullValue(I.getType()));
- else if (const VectorType *PT = dyn_cast<VectorType>(I.getType()))
+ else if (VectorType *PT = dyn_cast<VectorType>(I.getType()))
markConstant(IV, &I, Constant::getAllOnesValue(PT));
else
markConstant(IV, &I,
@@ -1179,8 +1192,8 @@ void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) {
}
Constant *Ptr = Operands[0];
- markConstant(&I, ConstantExpr::getGetElementPtr(Ptr, &Operands[0]+1,
- Operands.size()-1));
+ ArrayRef<Constant *> Indices(Operands.begin() + 1, Operands.end());
+ markConstant(&I, ConstantExpr::getGetElementPtr(Ptr, Indices));
}
void SCCPSolver::visitStoreInst(StoreInst &SI) {
@@ -1278,7 +1291,7 @@ CallOverdefined:
// If we can constant fold this, mark the result of the call as a
// constant.
- if (Constant *C = ConstantFoldCall(F, Operands.data(), Operands.size()))
+ if (Constant *C = ConstantFoldCall(F, Operands))
return markConstant(I, C);
}
@@ -1303,7 +1316,7 @@ CallOverdefined:
continue;
}
- if (const StructType *STy = dyn_cast<StructType>(AI->getType())) {
+ if (StructType *STy = dyn_cast<StructType>(AI->getType())) {
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
LatticeVal CallArg = getStructValueState(*CAI, i);
mergeInValue(getStructValueState(AI, i), AI, CallArg);
@@ -1315,7 +1328,7 @@ CallOverdefined:
}
// If this is a single/zero retval case, see if we're tracking the function.
- if (const StructType *STy = dyn_cast<StructType>(F->getReturnType())) {
+ if (StructType *STy = dyn_cast<StructType>(F->getReturnType())) {
if (!MRVFunctionsTracked.count(F))
goto CallOverdefined; // Not tracking this callee.
@@ -1419,67 +1432,116 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// Look for instructions which produce undef values.
if (I->getType()->isVoidTy()) continue;
- if (const StructType *STy = dyn_cast<StructType>(I->getType())) {
- // Only a few things that can be structs matter for undef. Just send
- // all their results to overdefined. We could be more precise than this
- // but it isn't worth bothering.
- if (isa<CallInst>(I) || isa<SelectInst>(I)) {
- for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- LatticeVal &LV = getStructValueState(I, i);
- if (LV.isUndefined())
- markOverdefined(LV, I);
- }
+ if (StructType *STy = dyn_cast<StructType>(I->getType())) {
+ // Only a few things that can be structs matter for undef.
+
+ // Tracked calls must never be marked overdefined in ResolvedUndefsIn.
+ if (CallSite CS = CallSite(I))
+ if (Function *F = CS.getCalledFunction())
+ if (MRVFunctionsTracked.count(F))
+ continue;
+
+ // extractvalue and insertvalue don't need to be marked; they are
+ // tracked as precisely as their operands.
+ if (isa<ExtractValueInst>(I) || isa<InsertValueInst>(I))
+ continue;
+
+ // Send the results of everything else to overdefined. We could be
+ // more precise than this but it isn't worth bothering.
+ for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+ LatticeVal &LV = getStructValueState(I, i);
+ if (LV.isUndefined())
+ markOverdefined(LV, I);
}
continue;
}
-
+
LatticeVal &LV = getValueState(I);
if (!LV.isUndefined()) continue;
- // No instructions using structs need disambiguation.
- if (I->getOperand(0)->getType()->isStructTy())
+ // extractvalue is safe; check here because the argument is a struct.
+ if (isa<ExtractValueInst>(I))
continue;
- // Get the lattice values of the first two operands for use below.
+ // Compute the operand LatticeVals, for convenience below.
+ // Anything taking a struct is conservatively assumed to require
+ // overdefined markings.
+ if (I->getOperand(0)->getType()->isStructTy()) {
+ markOverdefined(I);
+ return true;
+ }
LatticeVal Op0LV = getValueState(I->getOperand(0));
LatticeVal Op1LV;
if (I->getNumOperands() == 2) {
- // No instructions using structs need disambiguation.
- if (I->getOperand(1)->getType()->isStructTy())
- continue;
-
- // If this is a two-operand instruction, and if both operands are
- // undefs, the result stays undef.
+ if (I->getOperand(1)->getType()->isStructTy()) {
+ markOverdefined(I);
+ return true;
+ }
+
Op1LV = getValueState(I->getOperand(1));
- if (Op0LV.isUndefined() && Op1LV.isUndefined())
- continue;
}
-
// If this is an instructions whose result is defined even if the input is
// not fully defined, propagate the information.
- const Type *ITy = I->getType();
+ Type *ITy = I->getType();
switch (I->getOpcode()) {
- default: break; // Leave the instruction as an undef.
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Trunc:
+ case Instruction::FPTrunc:
+ case Instruction::BitCast:
+ break; // Any undef -> undef
+ case Instruction::FSub:
+ case Instruction::FAdd:
+ case Instruction::FMul:
+ case Instruction::FDiv:
+ case Instruction::FRem:
+ // Floating-point binary operation: be conservative.
+ if (Op0LV.isUndefined() && Op1LV.isUndefined())
+ markForcedConstant(I, Constant::getNullValue(ITy));
+ else
+ markOverdefined(I);
+ return true;
case Instruction::ZExt:
- // After a zero extend, we know the top part is zero. SExt doesn't have
- // to be handled here, because we don't know whether the top part is 1's
- // or 0's.
- case Instruction::SIToFP: // some FP values are not possible, just use 0.
- case Instruction::UIToFP: // some FP values are not possible, just use 0.
+ case Instruction::SExt:
+ case Instruction::FPToUI:
+ case Instruction::FPToSI:
+ case Instruction::FPExt:
+ case Instruction::PtrToInt:
+ case Instruction::IntToPtr:
+ case Instruction::SIToFP:
+ case Instruction::UIToFP:
+ // undef -> 0; some outputs are impossible
markForcedConstant(I, Constant::getNullValue(ITy));
return true;
case Instruction::Mul:
case Instruction::And:
+ // Both operands undef -> undef
+ if (Op0LV.isUndefined() && Op1LV.isUndefined())
+ break;
// undef * X -> 0. X could be zero.
// undef & X -> 0. X could be zero.
markForcedConstant(I, Constant::getNullValue(ITy));
return true;
case Instruction::Or:
+ // Both operands undef -> undef
+ if (Op0LV.isUndefined() && Op1LV.isUndefined())
+ break;
// undef | X -> -1. X could be -1.
markForcedConstant(I, Constant::getAllOnesValue(ITy));
return true;
+ case Instruction::Xor:
+ // undef ^ undef -> 0; strictly speaking, this is not strictly
+ // necessary, but we try to be nice to people who expect this
+ // behavior in simple cases
+ if (Op0LV.isUndefined() && Op1LV.isUndefined()) {
+ markForcedConstant(I, Constant::getNullValue(ITy));
+ return true;
+ }
+ // undef ^ X -> undef
+ break;
+
case Instruction::SDiv:
case Instruction::UDiv:
case Instruction::SRem:
@@ -1494,26 +1556,24 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
return true;
case Instruction::AShr:
- // undef >>s X -> undef. No change.
- if (Op0LV.isUndefined()) break;
-
- // X >>s undef -> X. X could be 0, X could have the high-bit known set.
- if (Op0LV.isConstant())
- markForcedConstant(I, Op0LV.getConstant());
- else
- markOverdefined(I);
+ // X >>a undef -> undef.
+ if (Op1LV.isUndefined()) break;
+
+ // undef >>a X -> all ones
+ markForcedConstant(I, Constant::getAllOnesValue(ITy));
return true;
case Instruction::LShr:
case Instruction::Shl:
- // undef >> X -> undef. No change.
- // undef << X -> undef. No change.
- if (Op0LV.isUndefined()) break;
-
- // X >> undef -> 0. X could be 0.
- // X << undef -> 0. X could be 0.
+ // X << undef -> undef.
+ // X >> undef -> undef.
+ if (Op1LV.isUndefined()) break;
+
+ // undef << X -> 0
+ // undef >> X -> 0
markForcedConstant(I, Constant::getNullValue(ITy));
return true;
case Instruction::Select:
+ Op1LV = getValueState(I->getOperand(1));
// undef ? X : Y -> X or Y. There could be commonality between X/Y.
if (Op0LV.isUndefined()) {
if (!Op1LV.isConstant()) // Pick the constant one if there is any.
@@ -1533,9 +1593,35 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
else
markOverdefined(I);
return true;
+ case Instruction::Load:
+ // A load here means one of two things: a load of undef from a global,
+ // a load from an unknown pointer. Either way, having it return undef
+ // is okay.
+ break;
+ case Instruction::ICmp:
+ // X == undef -> undef. Other comparisons get more complicated.
+ if (cast<ICmpInst>(I)->isEquality())
+ break;
+ markOverdefined(I);
+ return true;
case Instruction::Call:
- // If a call has an undef result, it is because it is constant foldable
- // but one of the inputs was undef. Just force the result to
+ case Instruction::Invoke: {
+ // There are two reasons a call can have an undef result
+ // 1. It could be tracked.
+ // 2. It could be constant-foldable.
+ // Because of the way we solve return values, tracked calls must
+ // never be marked overdefined in ResolvedUndefsIn.
+ if (Function *F = CallSite(I).getCalledFunction())
+ if (TrackedRetVals.count(F))
+ break;
+
+ // If the call is constant-foldable, we mark it overdefined because
+ // we do not know what return values are valid.
+ markOverdefined(I);
+ return true;
+ }
+ default:
+ // If we don't know what should happen here, conservatively mark it
// overdefined.
markOverdefined(I);
return true;
@@ -1621,15 +1707,25 @@ FunctionPass *llvm::createSCCPPass() {
static void DeleteInstructionInBlock(BasicBlock *BB) {
DEBUG(dbgs() << " BasicBlock Dead:" << *BB);
++NumDeadBlocks;
-
- // Delete the instructions backwards, as it has a reduced likelihood of
- // having to update as many def-use and use-def chains.
- while (!isa<TerminatorInst>(BB->begin())) {
- Instruction *I = --BasicBlock::iterator(BB->getTerminator());
-
- if (!I->use_empty())
- I->replaceAllUsesWith(UndefValue::get(I->getType()));
- BB->getInstList().erase(I);
+
+ // Check to see if there are non-terminating instructions to delete.
+ if (isa<TerminatorInst>(BB->begin()))
+ return;
+
+ // Delete the instructions backwards, as it has a reduced likelihood of having
+ // to update as many def-use and use-def chains.
+ Instruction *EndInst = BB->getTerminator(); // Last not to be deleted.
+ while (EndInst != BB->begin()) {
+ // Delete the next to last instruction.
+ BasicBlock::iterator I = EndInst;
+ Instruction *Inst = --I;
+ if (!Inst->use_empty())
+ Inst->replaceAllUsesWith(UndefValue::get(Inst->getType()));
+ if (isa<LandingPadInst>(Inst)) {
+ EndInst = Inst;
+ continue;
+ }
+ BB->getInstList().erase(Inst);
++NumInstRemoved;
}
}
diff --git a/lib/Transforms/Scalar/Scalar.cpp b/lib/Transforms/Scalar/Scalar.cpp
index 302c287..f6918de 100644
--- a/lib/Transforms/Scalar/Scalar.cpp
+++ b/lib/Transforms/Scalar/Scalar.cpp
@@ -63,7 +63,6 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) {
initializeCFGSimplifyPassPass(Registry);
initializeSimplifyLibCallsPass(Registry);
initializeSinkingPass(Registry);
- initializeTailDupPass(Registry);
initializeTailCallElimPass(Registry);
}
@@ -187,3 +186,7 @@ void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM) {
void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createBasicAliasAnalysisPass());
}
+
+void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM) {
+ unwrap(PM)->add(createLowerExpectIntrinsicPass());
+}
diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp
index 7d6349c..c6d9123 100644
--- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp
+++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp
@@ -129,11 +129,11 @@ namespace {
AllocaInfo &Info);
void isSafeGEP(GetElementPtrInst *GEPI, uint64_t &Offset, AllocaInfo &Info);
void isSafeMemAccess(uint64_t Offset, uint64_t MemSize,
- const Type *MemOpType, bool isStore, AllocaInfo &Info,
+ Type *MemOpType, bool isStore, AllocaInfo &Info,
Instruction *TheAccess, bool AllowWholeAccess);
- bool TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size);
- uint64_t FindElementAndOffset(const Type *&T, uint64_t &Offset,
- const Type *&IdxTy);
+ bool TypeHasComponent(Type *T, uint64_t Offset, uint64_t Size);
+ uint64_t FindElementAndOffset(Type *&T, uint64_t &Offset,
+ Type *&IdxTy);
void DoScalarReplacement(AllocaInst *AI,
std::vector<AllocaInst*> &WorkList);
@@ -145,6 +145,9 @@ namespace {
SmallVector<AllocaInst*, 32> &NewElts);
void RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset,
SmallVector<AllocaInst*, 32> &NewElts);
+ void RewriteLifetimeIntrinsic(IntrinsicInst *II, AllocaInst *AI,
+ uint64_t Offset,
+ SmallVector<AllocaInst*, 32> &NewElts);
void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
AllocaInst *AI,
SmallVector<AllocaInst*, 32> &NewElts);
@@ -253,7 +256,7 @@ class ConvertToScalarInfo {
/// VectorTy - This tracks the type that we should promote the vector to if
/// it is possible to turn it into a vector. This starts out null, and if it
/// isn't possible to turn into a vector type, it gets set to VoidTy.
- const VectorType *VectorTy;
+ VectorType *VectorTy;
/// HadNonMemTransferAccess - True if there is at least one access to the
/// alloca that is not a MemTransferInst. We don't want to turn structs into
@@ -269,11 +272,11 @@ public:
private:
bool CanConvertToScalar(Value *V, uint64_t Offset);
- void MergeInTypeForLoadOrStore(const Type *In, uint64_t Offset);
- bool MergeInVectorType(const VectorType *VInTy, uint64_t Offset);
+ void MergeInTypeForLoadOrStore(Type *In, uint64_t Offset);
+ bool MergeInVectorType(VectorType *VInTy, uint64_t Offset);
void ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset);
- Value *ConvertScalar_ExtractValue(Value *NV, const Type *ToType,
+ Value *ConvertScalar_ExtractValue(Value *NV, Type *ToType,
uint64_t Offset, IRBuilder<> &Builder);
Value *ConvertScalar_InsertValue(Value *StoredVal, Value *ExistingVal,
uint64_t Offset, IRBuilder<> &Builder);
@@ -295,8 +298,6 @@ AllocaInst *ConvertToScalarInfo::TryConvert(AllocaInst *AI) {
if (ScalarKind == Unknown)
ScalarKind = Integer;
- // FIXME: It should be possible to promote the vector type up to the alloca's
- // size.
if (ScalarKind == Vector && VectorTy->getBitWidth() != AllocaSize * 8)
ScalarKind = Integer;
@@ -306,7 +307,7 @@ AllocaInst *ConvertToScalarInfo::TryConvert(AllocaInst *AI) {
// random stuff that doesn't use vectors (e.g. <9 x double>) because then
// we just get a lot of insert/extracts. If at least one vector is
// involved, then we probably really do have a union of vector/array.
- const Type *NewTy;
+ Type *NewTy;
if (ScalarKind == Vector) {
assert(VectorTy && "Missing type for vector scalar.");
DEBUG(dbgs() << "CONVERT TO VECTOR: " << *AI << "\n TYPE = "
@@ -331,20 +332,16 @@ AllocaInst *ConvertToScalarInfo::TryConvert(AllocaInst *AI) {
/// (VectorTy) so far at the offset specified by Offset (which is specified in
/// bytes).
///
-/// There are three cases we handle here:
+/// There are two cases we handle here:
/// 1) A union of vector types of the same size and potentially its elements.
/// Here we turn element accesses into insert/extract element operations.
/// This promotes a <4 x float> with a store of float to the third element
/// into a <4 x float> that uses insert element.
-/// 2) A union of vector types with power-of-2 size differences, e.g. a float,
-/// <2 x float> and <4 x float>. Here we turn element accesses into insert
-/// and extract element operations, and <2 x float> accesses into a cast to
-/// <2 x double>, an extract, and a cast back to <2 x float>.
-/// 3) A fully general blob of memory, which we turn into some (potentially
+/// 2) A fully general blob of memory, which we turn into some (potentially
/// large) integer type with extract and insert operations where the loads
/// and stores would mutate the memory. We mark this by setting VectorTy
/// to VoidTy.
-void ConvertToScalarInfo::MergeInTypeForLoadOrStore(const Type *In,
+void ConvertToScalarInfo::MergeInTypeForLoadOrStore(Type *In,
uint64_t Offset) {
// If we already decided to turn this into a blob of integer memory, there is
// nothing to be done.
@@ -355,7 +352,7 @@ void ConvertToScalarInfo::MergeInTypeForLoadOrStore(const Type *In,
// If the In type is a vector that is the same size as the alloca, see if it
// matches the existing VecTy.
- if (const VectorType *VInTy = dyn_cast<VectorType>(In)) {
+ if (VectorType *VInTy = dyn_cast<VectorType>(In)) {
if (MergeInVectorType(VInTy, Offset))
return;
} else if (In->isFloatTy() || In->isDoubleTy() ||
@@ -371,20 +368,13 @@ void ConvertToScalarInfo::MergeInTypeForLoadOrStore(const Type *In,
// if the implied vector agrees with what we already have and if Offset is
// compatible with it.
if (Offset % EltSize == 0 && AllocaSize % EltSize == 0 &&
- (!VectorTy || Offset * 8 < VectorTy->getPrimitiveSizeInBits())) {
+ (!VectorTy || EltSize == VectorTy->getElementType()
+ ->getPrimitiveSizeInBits()/8)) {
if (!VectorTy) {
ScalarKind = ImplicitVector;
VectorTy = VectorType::get(In, AllocaSize/EltSize);
- return;
}
-
- unsigned CurrentEltSize = VectorTy->getElementType()
- ->getPrimitiveSizeInBits()/8;
- if (EltSize == CurrentEltSize)
- return;
-
- if (In->isIntegerTy() && isPowerOf2_32(AllocaSize / EltSize))
- return;
+ return;
}
}
@@ -395,74 +385,21 @@ void ConvertToScalarInfo::MergeInTypeForLoadOrStore(const Type *In,
/// MergeInVectorType - Handles the vector case of MergeInTypeForLoadOrStore,
/// returning true if the type was successfully merged and false otherwise.
-bool ConvertToScalarInfo::MergeInVectorType(const VectorType *VInTy,
+bool ConvertToScalarInfo::MergeInVectorType(VectorType *VInTy,
uint64_t Offset) {
- // TODO: Support nonzero offsets?
- if (Offset != 0)
- return false;
-
- // Only allow vectors that are a power-of-2 away from the size of the alloca.
- if (!isPowerOf2_64(AllocaSize / (VInTy->getBitWidth() / 8)))
- return false;
-
- // If this the first vector we see, remember the type so that we know the
- // element size.
- if (!VectorTy) {
+ if (VInTy->getBitWidth()/8 == AllocaSize && Offset == 0) {
+ // If we're storing/loading a vector of the right size, allow it as a
+ // vector. If this the first vector we see, remember the type so that
+ // we know the element size. If this is a subsequent access, ignore it
+ // even if it is a differing type but the same size. Worst case we can
+ // bitcast the resultant vectors.
+ if (!VectorTy)
+ VectorTy = VInTy;
ScalarKind = Vector;
- VectorTy = VInTy;
return true;
}
- unsigned BitWidth = VectorTy->getBitWidth();
- unsigned InBitWidth = VInTy->getBitWidth();
-
- // Vectors of the same size can be converted using a simple bitcast.
- if (InBitWidth == BitWidth && AllocaSize == (InBitWidth / 8)) {
- ScalarKind = Vector;
- return true;
- }
-
- const Type *ElementTy = VectorTy->getElementType();
- const Type *InElementTy = VInTy->getElementType();
-
- // Do not allow mixed integer and floating-point accesses from vectors of
- // different sizes.
- if (ElementTy->isFloatingPointTy() != InElementTy->isFloatingPointTy())
- return false;
-
- if (ElementTy->isFloatingPointTy()) {
- // Only allow floating-point vectors of different sizes if they have the
- // same element type.
- // TODO: This could be loosened a bit, but would anything benefit?
- if (ElementTy != InElementTy)
- return false;
-
- // There are no arbitrary-precision floating-point types, which limits the
- // number of legal vector types with larger element types that we can form
- // to bitcast and extract a subvector.
- // TODO: We could support some more cases with mixed fp128 and double here.
- if (!(BitWidth == 64 || BitWidth == 128) ||
- !(InBitWidth == 64 || InBitWidth == 128))
- return false;
- } else {
- assert(ElementTy->isIntegerTy() && "Vector elements must be either integer "
- "or floating-point.");
- unsigned BitWidth = ElementTy->getPrimitiveSizeInBits();
- unsigned InBitWidth = InElementTy->getPrimitiveSizeInBits();
-
- // Do not allow integer types smaller than a byte or types whose widths are
- // not a multiple of a byte.
- if (BitWidth < 8 || InBitWidth < 8 ||
- BitWidth % 8 != 0 || InBitWidth % 8 != 0)
- return false;
- }
-
- // Pick the largest of the two vector types.
- ScalarKind = Vector;
- if (InBitWidth > BitWidth)
- VectorTy = VInTy;
-
- return true;
+ return false;
}
/// CanConvertToScalar - V is a pointer. If we can convert the pointee and all
@@ -480,7 +417,7 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) {
if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
// Don't break volatile loads.
- if (LI->isVolatile())
+ if (!LI->isSimple())
return false;
// Don't touch MMX operations.
if (LI->getType()->isX86_MMXTy())
@@ -492,7 +429,7 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) {
if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
// Storing the pointer, not into the value?
- if (SI->getOperand(0) == V || SI->isVolatile()) return false;
+ if (SI->getOperand(0) == V || !SI->isSimple()) return false;
// Don't touch MMX operations.
if (SI->getOperand(0)->getType()->isX86_MMXTy())
return false;
@@ -502,7 +439,8 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) {
}
if (BitCastInst *BCI = dyn_cast<BitCastInst>(User)) {
- IsNotTrivial = true; // Can't be mem2reg'd.
+ if (!onlyUsedByLifetimeMarkers(BCI))
+ IsNotTrivial = true; // Can't be mem2reg'd.
if (!CanConvertToScalar(BCI, Offset))
return false;
continue;
@@ -516,7 +454,7 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) {
// Compute the offset that this GEP adds to the pointer.
SmallVector<Value*, 8> Indices(GEP->op_begin()+1, GEP->op_end());
uint64_t GEPOffset = TD.getIndexedOffset(GEP->getPointerOperandType(),
- &Indices[0], Indices.size());
+ Indices);
// See if all uses can be converted.
if (!CanConvertToScalar(GEP, Offset+GEPOffset))
return false;
@@ -560,6 +498,14 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) {
continue;
}
+ // If this is a lifetime intrinsic, we can handle it.
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(User)) {
+ if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
+ II->getIntrinsicID() == Intrinsic::lifetime_end) {
+ continue;
+ }
+ }
+
// Otherwise, we cannot handle this!
return false;
}
@@ -589,7 +535,7 @@ void ConvertToScalarInfo::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI,
// Compute the offset that this GEP adds to the pointer.
SmallVector<Value*, 8> Indices(GEP->op_begin()+1, GEP->op_end());
uint64_t GEPOffset = TD.getIndexedOffset(GEP->getPointerOperandType(),
- &Indices[0], Indices.size());
+ Indices);
ConvertUsesToScalar(GEP, NewAI, Offset+GEPOffset*8);
GEP->eraseFromParent();
continue;
@@ -599,7 +545,7 @@ void ConvertToScalarInfo::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI,
if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
// The load is a bit extract from NewAI shifted right by Offset bits.
- Value *LoadedVal = Builder.CreateLoad(NewAI, "tmp");
+ Value *LoadedVal = Builder.CreateLoad(NewAI);
Value *NewLoadVal
= ConvertScalar_ExtractValue(LoadedVal, LI->getType(), Offset, Builder);
LI->replaceAllUsesWith(NewLoadVal);
@@ -668,8 +614,8 @@ void ConvertToScalarInfo::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI,
// pointer (bitcasted), then a store to our new alloca.
assert(MTI->getRawDest() == Ptr && "Neither use is of pointer?");
Value *SrcPtr = MTI->getSource();
- const PointerType* SPTy = cast<PointerType>(SrcPtr->getType());
- const PointerType* AIPTy = cast<PointerType>(NewAI->getType());
+ PointerType* SPTy = cast<PointerType>(SrcPtr->getType());
+ PointerType* AIPTy = cast<PointerType>(NewAI->getType());
if (SPTy->getAddressSpace() != AIPTy->getAddressSpace()) {
AIPTy = PointerType::get(AIPTy->getElementType(),
SPTy->getAddressSpace());
@@ -685,8 +631,8 @@ void ConvertToScalarInfo::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI,
assert(MTI->getRawSource() == Ptr && "Neither use is of pointer?");
LoadInst *SrcVal = Builder.CreateLoad(NewAI, "srcval");
- const PointerType* DPTy = cast<PointerType>(MTI->getDest()->getType());
- const PointerType* AIPTy = cast<PointerType>(NewAI->getType());
+ PointerType* DPTy = cast<PointerType>(MTI->getDest()->getType());
+ PointerType* AIPTy = cast<PointerType>(NewAI->getType());
if (DPTy->getAddressSpace() != AIPTy->getAddressSpace()) {
AIPTy = PointerType::get(AIPTy->getElementType(),
DPTy->getAddressSpace());
@@ -703,65 +649,18 @@ void ConvertToScalarInfo::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI,
continue;
}
- llvm_unreachable("Unsupported operation!");
- }
-}
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(User)) {
+ if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
+ II->getIntrinsicID() == Intrinsic::lifetime_end) {
+ // There's no need to preserve these, as the resulting alloca will be
+ // converted to a register anyways.
+ II->eraseFromParent();
+ continue;
+ }
+ }
-/// getScaledElementType - Gets a scaled element type for a partial vector
-/// access of an alloca. The input types must be integer or floating-point
-/// scalar or vector types, and the resulting type is an integer, float or
-/// double.
-static const Type *getScaledElementType(const Type *Ty1, const Type *Ty2,
- unsigned NewBitWidth) {
- bool IsFP1 = Ty1->isFloatingPointTy() ||
- (Ty1->isVectorTy() &&
- cast<VectorType>(Ty1)->getElementType()->isFloatingPointTy());
- bool IsFP2 = Ty2->isFloatingPointTy() ||
- (Ty2->isVectorTy() &&
- cast<VectorType>(Ty2)->getElementType()->isFloatingPointTy());
-
- LLVMContext &Context = Ty1->getContext();
-
- // Prefer floating-point types over integer types, as integer types may have
- // been created by earlier scalar replacement.
- if (IsFP1 || IsFP2) {
- if (NewBitWidth == 32)
- return Type::getFloatTy(Context);
- if (NewBitWidth == 64)
- return Type::getDoubleTy(Context);
+ llvm_unreachable("Unsupported operation!");
}
-
- return Type::getIntNTy(Context, NewBitWidth);
-}
-
-/// CreateShuffleVectorCast - Creates a shuffle vector to convert one vector
-/// to another vector of the same element type which has the same allocation
-/// size but different primitive sizes (e.g. <3 x i32> and <4 x i32>).
-static Value *CreateShuffleVectorCast(Value *FromVal, const Type *ToType,
- IRBuilder<> &Builder) {
- const Type *FromType = FromVal->getType();
- const VectorType *FromVTy = cast<VectorType>(FromType);
- const VectorType *ToVTy = cast<VectorType>(ToType);
- assert((ToVTy->getElementType() == FromVTy->getElementType()) &&
- "Vectors must have the same element type");
- Value *UnV = UndefValue::get(FromType);
- unsigned numEltsFrom = FromVTy->getNumElements();
- unsigned numEltsTo = ToVTy->getNumElements();
-
- SmallVector<Constant*, 3> Args;
- const Type* Int32Ty = Builder.getInt32Ty();
- unsigned minNumElts = std::min(numEltsFrom, numEltsTo);
- unsigned i;
- for (i=0; i != minNumElts; ++i)
- Args.push_back(ConstantInt::get(Int32Ty, i));
-
- if (i < numEltsTo) {
- Constant* UnC = UndefValue::get(Int32Ty);
- for (; i != numEltsTo; ++i)
- Args.push_back(UnC);
- }
- Constant *Mask = ConstantVector::get(Args);
- return Builder.CreateShuffleVector(FromVal, UnV, Mask, "tmpV");
}
/// ConvertScalar_ExtractValue - Extract a value of type ToType from an integer
@@ -775,50 +674,20 @@ static Value *CreateShuffleVectorCast(Value *FromVal, const Type *ToType,
/// Offset is an offset from the original alloca, in bits that need to be
/// shifted to the right.
Value *ConvertToScalarInfo::
-ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType,
+ConvertScalar_ExtractValue(Value *FromVal, Type *ToType,
uint64_t Offset, IRBuilder<> &Builder) {
// If the load is of the whole new alloca, no conversion is needed.
- const Type *FromType = FromVal->getType();
+ Type *FromType = FromVal->getType();
if (FromType == ToType && Offset == 0)
return FromVal;
// If the result alloca is a vector type, this is either an element
// access or a bitcast to another vector type of the same size.
- if (const VectorType *VTy = dyn_cast<VectorType>(FromType)) {
+ if (VectorType *VTy = dyn_cast<VectorType>(FromType)) {
unsigned FromTypeSize = TD.getTypeAllocSize(FromType);
unsigned ToTypeSize = TD.getTypeAllocSize(ToType);
- if (FromTypeSize == ToTypeSize) {
- // If the two types have the same primitive size, use a bit cast.
- // Otherwise, it is two vectors with the same element type that has
- // the same allocation size but different number of elements so use
- // a shuffle vector.
- if (FromType->getPrimitiveSizeInBits() ==
- ToType->getPrimitiveSizeInBits())
- return Builder.CreateBitCast(FromVal, ToType, "tmp");
- else
- return CreateShuffleVectorCast(FromVal, ToType, Builder);
- }
-
- if (isPowerOf2_64(FromTypeSize / ToTypeSize)) {
- assert(!(ToType->isVectorTy() && Offset != 0) && "Can't extract a value "
- "of a smaller vector type at a nonzero offset.");
-
- const Type *CastElementTy = getScaledElementType(FromType, ToType,
- ToTypeSize * 8);
- unsigned NumCastVectorElements = FromTypeSize / ToTypeSize;
-
- LLVMContext &Context = FromVal->getContext();
- const Type *CastTy = VectorType::get(CastElementTy,
- NumCastVectorElements);
- Value *Cast = Builder.CreateBitCast(FromVal, CastTy, "tmp");
-
- unsigned EltSize = TD.getTypeAllocSizeInBits(CastElementTy);
- unsigned Elt = Offset/EltSize;
- assert(EltSize*Elt == Offset && "Invalid modulus in validity checking");
- Value *Extract = Builder.CreateExtractElement(Cast, ConstantInt::get(
- Type::getInt32Ty(Context), Elt), "tmp");
- return Builder.CreateBitCast(Extract, ToType, "tmp");
- }
+ if (FromTypeSize == ToTypeSize)
+ return Builder.CreateBitCast(FromVal, ToType);
// Otherwise it must be an element access.
unsigned Elt = 0;
@@ -828,40 +697,39 @@ ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType,
assert(EltSize*Elt == Offset && "Invalid modulus in validity checking");
}
// Return the element extracted out of it.
- Value *V = Builder.CreateExtractElement(FromVal, ConstantInt::get(
- Type::getInt32Ty(FromVal->getContext()), Elt), "tmp");
+ Value *V = Builder.CreateExtractElement(FromVal, Builder.getInt32(Elt));
if (V->getType() != ToType)
- V = Builder.CreateBitCast(V, ToType, "tmp");
+ V = Builder.CreateBitCast(V, ToType);
return V;
}
// If ToType is a first class aggregate, extract out each of the pieces and
// use insertvalue's to form the FCA.
- if (const StructType *ST = dyn_cast<StructType>(ToType)) {
+ if (StructType *ST = dyn_cast<StructType>(ToType)) {
const StructLayout &Layout = *TD.getStructLayout(ST);
Value *Res = UndefValue::get(ST);
for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {
Value *Elt = ConvertScalar_ExtractValue(FromVal, ST->getElementType(i),
Offset+Layout.getElementOffsetInBits(i),
Builder);
- Res = Builder.CreateInsertValue(Res, Elt, i, "tmp");
+ Res = Builder.CreateInsertValue(Res, Elt, i);
}
return Res;
}
- if (const ArrayType *AT = dyn_cast<ArrayType>(ToType)) {
+ if (ArrayType *AT = dyn_cast<ArrayType>(ToType)) {
uint64_t EltSize = TD.getTypeAllocSizeInBits(AT->getElementType());
Value *Res = UndefValue::get(AT);
for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) {
Value *Elt = ConvertScalar_ExtractValue(FromVal, AT->getElementType(),
Offset+i*EltSize, Builder);
- Res = Builder.CreateInsertValue(Res, Elt, i, "tmp");
+ Res = Builder.CreateInsertValue(Res, Elt, i);
}
return Res;
}
// Otherwise, this must be a union that was converted to an integer value.
- const IntegerType *NTy = cast<IntegerType>(FromVal->getType());
+ IntegerType *NTy = cast<IntegerType>(FromVal->getType());
// If this is a big-endian system and the load is narrower than the
// full alloca type, we need to do a shift to get the right bits.
@@ -881,33 +749,31 @@ ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType,
// only some bits are used.
if (ShAmt > 0 && (unsigned)ShAmt < NTy->getBitWidth())
FromVal = Builder.CreateLShr(FromVal,
- ConstantInt::get(FromVal->getType(),
- ShAmt), "tmp");
+ ConstantInt::get(FromVal->getType(), ShAmt));
else if (ShAmt < 0 && (unsigned)-ShAmt < NTy->getBitWidth())
FromVal = Builder.CreateShl(FromVal,
- ConstantInt::get(FromVal->getType(),
- -ShAmt), "tmp");
+ ConstantInt::get(FromVal->getType(), -ShAmt));
// Finally, unconditionally truncate the integer to the right width.
unsigned LIBitWidth = TD.getTypeSizeInBits(ToType);
if (LIBitWidth < NTy->getBitWidth())
FromVal =
Builder.CreateTrunc(FromVal, IntegerType::get(FromVal->getContext(),
- LIBitWidth), "tmp");
+ LIBitWidth));
else if (LIBitWidth > NTy->getBitWidth())
FromVal =
Builder.CreateZExt(FromVal, IntegerType::get(FromVal->getContext(),
- LIBitWidth), "tmp");
+ LIBitWidth));
// If the result is an integer, this is a trunc or bitcast.
if (ToType->isIntegerTy()) {
// Should be done.
} else if (ToType->isFloatingPointTy() || ToType->isVectorTy()) {
// Just do a bitcast, we know the sizes match up.
- FromVal = Builder.CreateBitCast(FromVal, ToType, "tmp");
+ FromVal = Builder.CreateBitCast(FromVal, ToType);
} else {
// Otherwise must be a pointer.
- FromVal = Builder.CreateIntToPtr(FromVal, ToType, "tmp");
+ FromVal = Builder.CreateIntToPtr(FromVal, ToType);
}
assert(FromVal->getType() == ToType && "Didn't convert right?");
return FromVal;
@@ -927,65 +793,30 @@ ConvertScalar_InsertValue(Value *SV, Value *Old,
uint64_t Offset, IRBuilder<> &Builder) {
// Convert the stored type to the actual type, shift it left to insert
// then 'or' into place.
- const Type *AllocaType = Old->getType();
+ Type *AllocaType = Old->getType();
LLVMContext &Context = Old->getContext();
- if (const VectorType *VTy = dyn_cast<VectorType>(AllocaType)) {
+ if (VectorType *VTy = dyn_cast<VectorType>(AllocaType)) {
uint64_t VecSize = TD.getTypeAllocSizeInBits(VTy);
uint64_t ValSize = TD.getTypeAllocSizeInBits(SV->getType());
// Changing the whole vector with memset or with an access of a different
// vector type?
- if (ValSize == VecSize) {
- // If the two types have the same primitive size, use a bit cast.
- // Otherwise, it is two vectors with the same element type that has
- // the same allocation size but different number of elements so use
- // a shuffle vector.
- if (VTy->getPrimitiveSizeInBits() ==
- SV->getType()->getPrimitiveSizeInBits())
- return Builder.CreateBitCast(SV, AllocaType, "tmp");
- else
- return CreateShuffleVectorCast(SV, VTy, Builder);
- }
-
- if (isPowerOf2_64(VecSize / ValSize)) {
- assert(!(SV->getType()->isVectorTy() && Offset != 0) && "Can't insert a "
- "value of a smaller vector type at a nonzero offset.");
-
- const Type *CastElementTy = getScaledElementType(VTy, SV->getType(),
- ValSize);
- unsigned NumCastVectorElements = VecSize / ValSize;
-
- LLVMContext &Context = SV->getContext();
- const Type *OldCastTy = VectorType::get(CastElementTy,
- NumCastVectorElements);
- Value *OldCast = Builder.CreateBitCast(Old, OldCastTy, "tmp");
-
- Value *SVCast = Builder.CreateBitCast(SV, CastElementTy, "tmp");
-
- unsigned EltSize = TD.getTypeAllocSizeInBits(CastElementTy);
- unsigned Elt = Offset/EltSize;
- assert(EltSize*Elt == Offset && "Invalid modulus in validity checking");
- Value *Insert =
- Builder.CreateInsertElement(OldCast, SVCast, ConstantInt::get(
- Type::getInt32Ty(Context), Elt), "tmp");
- return Builder.CreateBitCast(Insert, AllocaType, "tmp");
- }
+ if (ValSize == VecSize)
+ return Builder.CreateBitCast(SV, AllocaType);
// Must be an element insertion.
assert(SV->getType() == VTy->getElementType());
uint64_t EltSize = TD.getTypeAllocSizeInBits(VTy->getElementType());
unsigned Elt = Offset/EltSize;
- return Builder.CreateInsertElement(Old, SV,
- ConstantInt::get(Type::getInt32Ty(SV->getContext()), Elt),
- "tmp");
+ return Builder.CreateInsertElement(Old, SV, Builder.getInt32(Elt));
}
// If SV is a first-class aggregate value, insert each value recursively.
- if (const StructType *ST = dyn_cast<StructType>(SV->getType())) {
+ if (StructType *ST = dyn_cast<StructType>(SV->getType())) {
const StructLayout &Layout = *TD.getStructLayout(ST);
for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {
- Value *Elt = Builder.CreateExtractValue(SV, i, "tmp");
+ Value *Elt = Builder.CreateExtractValue(SV, i);
Old = ConvertScalar_InsertValue(Elt, Old,
Offset+Layout.getElementOffsetInBits(i),
Builder);
@@ -993,10 +824,10 @@ ConvertScalar_InsertValue(Value *SV, Value *Old,
return Old;
}
- if (const ArrayType *AT = dyn_cast<ArrayType>(SV->getType())) {
+ if (ArrayType *AT = dyn_cast<ArrayType>(SV->getType())) {
uint64_t EltSize = TD.getTypeAllocSizeInBits(AT->getElementType());
for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) {
- Value *Elt = Builder.CreateExtractValue(SV, i, "tmp");
+ Value *Elt = Builder.CreateExtractValue(SV, i);
Old = ConvertScalar_InsertValue(Elt, Old, Offset+i*EltSize, Builder);
}
return Old;
@@ -1009,20 +840,19 @@ ConvertScalar_InsertValue(Value *SV, Value *Old,
unsigned SrcStoreWidth = TD.getTypeStoreSizeInBits(SV->getType());
unsigned DestStoreWidth = TD.getTypeStoreSizeInBits(AllocaType);
if (SV->getType()->isFloatingPointTy() || SV->getType()->isVectorTy())
- SV = Builder.CreateBitCast(SV,
- IntegerType::get(SV->getContext(),SrcWidth), "tmp");
+ SV = Builder.CreateBitCast(SV, IntegerType::get(SV->getContext(),SrcWidth));
else if (SV->getType()->isPointerTy())
- SV = Builder.CreatePtrToInt(SV, TD.getIntPtrType(SV->getContext()), "tmp");
+ SV = Builder.CreatePtrToInt(SV, TD.getIntPtrType(SV->getContext()));
// Zero extend or truncate the value if needed.
if (SV->getType() != AllocaType) {
if (SV->getType()->getPrimitiveSizeInBits() <
AllocaType->getPrimitiveSizeInBits())
- SV = Builder.CreateZExt(SV, AllocaType, "tmp");
+ SV = Builder.CreateZExt(SV, AllocaType);
else {
// Truncation may be needed if storing more than the alloca can hold
// (undefined behavior).
- SV = Builder.CreateTrunc(SV, AllocaType, "tmp");
+ SV = Builder.CreateTrunc(SV, AllocaType);
SrcWidth = DestWidth;
SrcStoreWidth = DestStoreWidth;
}
@@ -1045,12 +875,10 @@ ConvertScalar_InsertValue(Value *SV, Value *Old,
// only some bits in the structure are set.
APInt Mask(APInt::getLowBitsSet(DestWidth, SrcWidth));
if (ShAmt > 0 && (unsigned)ShAmt < DestWidth) {
- SV = Builder.CreateShl(SV, ConstantInt::get(SV->getType(),
- ShAmt), "tmp");
+ SV = Builder.CreateShl(SV, ConstantInt::get(SV->getType(), ShAmt));
Mask <<= ShAmt;
} else if (ShAmt < 0 && (unsigned)-ShAmt < DestWidth) {
- SV = Builder.CreateLShr(SV, ConstantInt::get(SV->getType(),
- -ShAmt), "tmp");
+ SV = Builder.CreateLShr(SV, ConstantInt::get(SV->getType(), -ShAmt));
Mask = Mask.lshr(-ShAmt);
}
@@ -1196,7 +1024,7 @@ static bool isSafeSelectToSpeculate(SelectInst *SI, const TargetData *TD) {
for (Value::use_iterator UI = SI->use_begin(), UE = SI->use_end();
UI != UE; ++UI) {
LoadInst *LI = dyn_cast<LoadInst>(*UI);
- if (LI == 0 || LI->isVolatile()) return false;
+ if (LI == 0 || !LI->isSimple()) return false;
// Both operands to the select need to be dereferencable, either absolutely
// (e.g. allocas) or at this point because we can see other accesses to it.
@@ -1237,7 +1065,7 @@ static bool isSafePHIToSpeculate(PHINode *PN, const TargetData *TD) {
for (Value::use_iterator UI = PN->use_begin(), UE = PN->use_end();
UI != UE; ++UI) {
LoadInst *LI = dyn_cast<LoadInst>(*UI);
- if (LI == 0 || LI->isVolatile()) return false;
+ if (LI == 0 || !LI->isSimple()) return false;
// For now we only allow loads in the same block as the PHI. This is a
// common case that happens when instcombine merges two loads through a PHI.
@@ -1258,17 +1086,21 @@ static bool isSafePHIToSpeculate(PHINode *PN, const TargetData *TD) {
// trapping load in the predecessor if it is a critical edge.
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
BasicBlock *Pred = PN->getIncomingBlock(i);
+ Value *InVal = PN->getIncomingValue(i);
+
+ // If the terminator of the predecessor has side-effects (an invoke),
+ // there is no safe place to put a load in the predecessor.
+ if (Pred->getTerminator()->mayHaveSideEffects())
+ return false;
+
+ // If the value is produced by the terminator of the predecessor
+ // (an invoke), there is no valid place to put a load in the predecessor.
+ if (Pred->getTerminator() == InVal)
+ return false;
// If the predecessor has a single successor, then the edge isn't critical.
if (Pred->getTerminator()->getNumSuccessors() == 1)
continue;
-
- Value *InVal = PN->getIncomingValue(i);
-
- // If the InVal is an invoke in the pred, we can't put a load on the edge.
- if (InvokeInst *II = dyn_cast<InvokeInst>(InVal))
- if (II->getParent() == Pred)
- return false;
// If this pointer is always safe to load, or if we can prove that there is
// already a load in the block, then we can move the load to the pred block.
@@ -1295,13 +1127,13 @@ static bool tryToMakeAllocaBePromotable(AllocaInst *AI, const TargetData *TD) {
UI != UE; ++UI) {
User *U = *UI;
if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
- if (LI->isVolatile())
+ if (!LI->isSimple())
return false;
continue;
}
if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
- if (SI->getOperand(0) == AI || SI->isVolatile())
+ if (SI->getOperand(0) == AI || !SI->isSimple())
return false; // Don't allow a store OF the AI, only INTO the AI.
continue;
}
@@ -1343,6 +1175,13 @@ static bool tryToMakeAllocaBePromotable(AllocaInst *AI, const TargetData *TD) {
continue;
}
+ if (BitCastInst *BCI = dyn_cast<BitCastInst>(U)) {
+ if (onlyUsedByLifetimeMarkers(BCI)) {
+ InstsToRewrite.insert(BCI);
+ continue;
+ }
+ }
+
return false;
}
@@ -1354,6 +1193,18 @@ static bool tryToMakeAllocaBePromotable(AllocaInst *AI, const TargetData *TD) {
// If we have instructions that need to be rewritten for this to be promotable
// take care of it now.
for (unsigned i = 0, e = InstsToRewrite.size(); i != e; ++i) {
+ if (BitCastInst *BCI = dyn_cast<BitCastInst>(InstsToRewrite[i])) {
+ // This could only be a bitcast used by nothing but lifetime intrinsics.
+ for (BitCastInst::use_iterator I = BCI->use_begin(), E = BCI->use_end();
+ I != E;) {
+ Use &U = I.getUse();
+ ++I;
+ cast<Instruction>(U.getUser())->eraseFromParent();
+ }
+ BCI->eraseFromParent();
+ continue;
+ }
+
if (SelectInst *SI = dyn_cast<SelectInst>(InstsToRewrite[i])) {
// Selects in InstsToRewrite only have load uses. Rewrite each as two
// loads with a new select.
@@ -1393,7 +1244,7 @@ static bool tryToMakeAllocaBePromotable(AllocaInst *AI, const TargetData *TD) {
continue;
}
- const Type *LoadTy = cast<PointerType>(PN->getType())->getElementType();
+ Type *LoadTy = cast<PointerType>(PN->getType())->getElementType();
PHINode *NewPN = PHINode::Create(LoadTy, PN->getNumIncomingValues(),
PN->getName()+".ld", PN);
@@ -1483,13 +1334,13 @@ bool SROA::performPromotion(Function &F) {
/// ShouldAttemptScalarRepl - Decide if an alloca is a good candidate for
/// SROA. It must be a struct or array type with a small number of elements.
static bool ShouldAttemptScalarRepl(AllocaInst *AI) {
- const Type *T = AI->getAllocatedType();
+ Type *T = AI->getAllocatedType();
// Do not promote any struct into more than 32 separate vars.
- if (const StructType *ST = dyn_cast<StructType>(T))
+ if (StructType *ST = dyn_cast<StructType>(T))
return ST->getNumElements() <= 32;
// Arrays are much less likely to be safe for SROA; only consider
// them if they are very small.
- if (const ArrayType *AT = dyn_cast<ArrayType>(T))
+ if (ArrayType *AT = dyn_cast<ArrayType>(T))
return AT->getNumElements() <= 8;
return false;
}
@@ -1594,7 +1445,7 @@ void SROA::DoScalarReplacement(AllocaInst *AI,
std::vector<AllocaInst*> &WorkList) {
DEBUG(dbgs() << "Found inst to SROA: " << *AI << '\n');
SmallVector<AllocaInst*, 32> ElementAllocas;
- if (const StructType *ST = dyn_cast<StructType>(AI->getAllocatedType())) {
+ if (StructType *ST = dyn_cast<StructType>(AI->getAllocatedType())) {
ElementAllocas.reserve(ST->getNumContainedTypes());
for (unsigned i = 0, e = ST->getNumContainedTypes(); i != e; ++i) {
AllocaInst *NA = new AllocaInst(ST->getContainedType(i), 0,
@@ -1604,9 +1455,9 @@ void SROA::DoScalarReplacement(AllocaInst *AI,
WorkList.push_back(NA); // Add to worklist for recursive processing
}
} else {
- const ArrayType *AT = cast<ArrayType>(AI->getAllocatedType());
+ ArrayType *AT = cast<ArrayType>(AI->getAllocatedType());
ElementAllocas.reserve(AT->getNumElements());
- const Type *ElTy = AT->getElementType();
+ Type *ElTy = AT->getElementType();
for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) {
AllocaInst *NA = new AllocaInst(ElTy, 0, AI->getAlignment(),
AI->getName() + "." + Twine(i), AI);
@@ -1670,22 +1521,26 @@ void SROA::isSafeForScalarRepl(Instruction *I, uint64_t Offset,
UI.getOperandNo() == 0, Info, MI,
true /*AllowWholeAccess*/);
} else if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
- if (LI->isVolatile())
+ if (!LI->isSimple())
return MarkUnsafe(Info, User);
- const Type *LIType = LI->getType();
+ Type *LIType = LI->getType();
isSafeMemAccess(Offset, TD->getTypeAllocSize(LIType),
LIType, false, Info, LI, true /*AllowWholeAccess*/);
Info.hasALoadOrStore = true;
} else if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
// Store is ok if storing INTO the pointer, not storing the pointer
- if (SI->isVolatile() || SI->getOperand(0) == I)
+ if (!SI->isSimple() || SI->getOperand(0) == I)
return MarkUnsafe(Info, User);
- const Type *SIType = SI->getOperand(0)->getType();
+ Type *SIType = SI->getOperand(0)->getType();
isSafeMemAccess(Offset, TD->getTypeAllocSize(SIType),
SIType, true, Info, SI, true /*AllowWholeAccess*/);
Info.hasALoadOrStore = true;
+ } else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(User)) {
+ if (II->getIntrinsicID() != Intrinsic::lifetime_start &&
+ II->getIntrinsicID() != Intrinsic::lifetime_end)
+ return MarkUnsafe(Info, User);
} else if (isa<PHINode>(User) || isa<SelectInst>(User)) {
isSafePHISelectUseForScalarRepl(User, Offset, Info);
} else {
@@ -1725,19 +1580,19 @@ void SROA::isSafePHISelectUseForScalarRepl(Instruction *I, uint64_t Offset,
return MarkUnsafe(Info, User);
isSafePHISelectUseForScalarRepl(GEPI, Offset, Info);
} else if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
- if (LI->isVolatile())
+ if (!LI->isSimple())
return MarkUnsafe(Info, User);
- const Type *LIType = LI->getType();
+ Type *LIType = LI->getType();
isSafeMemAccess(Offset, TD->getTypeAllocSize(LIType),
LIType, false, Info, LI, false /*AllowWholeAccess*/);
Info.hasALoadOrStore = true;
} else if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
// Store is ok if storing INTO the pointer, not storing the pointer
- if (SI->isVolatile() || SI->getOperand(0) == I)
+ if (!SI->isSimple() || SI->getOperand(0) == I)
return MarkUnsafe(Info, User);
- const Type *SIType = SI->getOperand(0)->getType();
+ Type *SIType = SI->getOperand(0)->getType();
isSafeMemAccess(Offset, TD->getTypeAllocSize(SIType),
SIType, true, Info, SI, false /*AllowWholeAccess*/);
Info.hasALoadOrStore = true;
@@ -1776,8 +1631,7 @@ void SROA::isSafeGEP(GetElementPtrInst *GEPI,
// Compute the offset due to this GEP and check if the alloca has a
// component element at that offset.
SmallVector<Value*, 8> Indices(GEPI->op_begin() + 1, GEPI->op_end());
- Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(),
- &Indices[0], Indices.size());
+ Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(), Indices);
if (!TypeHasComponent(Info.AI->getAllocatedType(), Offset, 0))
MarkUnsafe(Info, GEPI);
}
@@ -1786,14 +1640,14 @@ void SROA::isSafeGEP(GetElementPtrInst *GEPI,
/// elements of the same type (which is always true for arrays). If so,
/// return true with NumElts and EltTy set to the number of elements and the
/// element type, respectively.
-static bool isHomogeneousAggregate(const Type *T, unsigned &NumElts,
- const Type *&EltTy) {
- if (const ArrayType *AT = dyn_cast<ArrayType>(T)) {
+static bool isHomogeneousAggregate(Type *T, unsigned &NumElts,
+ Type *&EltTy) {
+ if (ArrayType *AT = dyn_cast<ArrayType>(T)) {
NumElts = AT->getNumElements();
EltTy = (NumElts == 0 ? 0 : AT->getElementType());
return true;
}
- if (const StructType *ST = dyn_cast<StructType>(T)) {
+ if (StructType *ST = dyn_cast<StructType>(T)) {
NumElts = ST->getNumContainedTypes();
EltTy = (NumElts == 0 ? 0 : ST->getContainedType(0));
for (unsigned n = 1; n < NumElts; ++n) {
@@ -1807,12 +1661,12 @@ static bool isHomogeneousAggregate(const Type *T, unsigned &NumElts,
/// isCompatibleAggregate - Check if T1 and T2 are either the same type or are
/// "homogeneous" aggregates with the same element type and number of elements.
-static bool isCompatibleAggregate(const Type *T1, const Type *T2) {
+static bool isCompatibleAggregate(Type *T1, Type *T2) {
if (T1 == T2)
return true;
unsigned NumElts1, NumElts2;
- const Type *EltTy1, *EltTy2;
+ Type *EltTy1, *EltTy2;
if (isHomogeneousAggregate(T1, NumElts1, EltTy1) &&
isHomogeneousAggregate(T2, NumElts2, EltTy2) &&
NumElts1 == NumElts2 &&
@@ -1830,7 +1684,7 @@ static bool isCompatibleAggregate(const Type *T1, const Type *T2) {
/// If AllowWholeAccess is true, then this allows uses of the entire alloca as a
/// unit. If false, it only allows accesses known to be in a single element.
void SROA::isSafeMemAccess(uint64_t Offset, uint64_t MemSize,
- const Type *MemOpType, bool isStore,
+ Type *MemOpType, bool isStore,
AllocaInfo &Info, Instruction *TheAccess,
bool AllowWholeAccess) {
// Check if this is a load/store of the entire alloca.
@@ -1857,7 +1711,7 @@ void SROA::isSafeMemAccess(uint64_t Offset, uint64_t MemSize,
}
}
// Check if the offset/size correspond to a component within the alloca type.
- const Type *T = Info.AI->getAllocatedType();
+ Type *T = Info.AI->getAllocatedType();
if (TypeHasComponent(T, Offset, MemSize)) {
Info.hasSubelementAccess = true;
return;
@@ -1868,16 +1722,16 @@ void SROA::isSafeMemAccess(uint64_t Offset, uint64_t MemSize,
/// TypeHasComponent - Return true if T has a component type with the
/// specified offset and size. If Size is zero, do not check the size.
-bool SROA::TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size) {
- const Type *EltTy;
+bool SROA::TypeHasComponent(Type *T, uint64_t Offset, uint64_t Size) {
+ Type *EltTy;
uint64_t EltSize;
- if (const StructType *ST = dyn_cast<StructType>(T)) {
+ if (StructType *ST = dyn_cast<StructType>(T)) {
const StructLayout *Layout = TD->getStructLayout(ST);
unsigned EltIdx = Layout->getElementContainingOffset(Offset);
EltTy = ST->getContainedType(EltIdx);
EltSize = TD->getTypeAllocSize(EltTy);
Offset -= Layout->getElementOffset(EltIdx);
- } else if (const ArrayType *AT = dyn_cast<ArrayType>(T)) {
+ } else if (ArrayType *AT = dyn_cast<ArrayType>(T)) {
EltTy = AT->getElementType();
EltSize = TD->getTypeAllocSize(EltTy);
if (Offset >= AT->getNumElements() * EltSize)
@@ -1924,9 +1778,17 @@ void SROA::RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset,
// address operand will be updated, so nothing else needs to be done.
continue;
}
+
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(User)) {
+ if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
+ II->getIntrinsicID() == Intrinsic::lifetime_end) {
+ RewriteLifetimeIntrinsic(II, AI, Offset, NewElts);
+ }
+ continue;
+ }
if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
- const Type *LIType = LI->getType();
+ Type *LIType = LI->getType();
if (isCompatibleAggregate(LIType, AI->getAllocatedType())) {
// Replace:
@@ -1956,7 +1818,7 @@ void SROA::RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset,
if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
Value *Val = SI->getOperand(0);
- const Type *SIType = Val->getType();
+ Type *SIType = Val->getType();
if (isCompatibleAggregate(SIType, AI->getAllocatedType())) {
// Replace:
// store { i32, i32 } %val, { i32, i32 }* %alloc
@@ -2026,10 +1888,10 @@ void SROA::RewriteBitCast(BitCastInst *BC, AllocaInst *AI, uint64_t Offset,
/// Sets T to the type of the element and Offset to the offset within that
/// element. IdxTy is set to the type of the index result to be used in a
/// GEP instruction.
-uint64_t SROA::FindElementAndOffset(const Type *&T, uint64_t &Offset,
- const Type *&IdxTy) {
+uint64_t SROA::FindElementAndOffset(Type *&T, uint64_t &Offset,
+ Type *&IdxTy) {
uint64_t Idx = 0;
- if (const StructType *ST = dyn_cast<StructType>(T)) {
+ if (StructType *ST = dyn_cast<StructType>(T)) {
const StructLayout *Layout = TD->getStructLayout(ST);
Idx = Layout->getElementContainingOffset(Offset);
T = ST->getContainedType(Idx);
@@ -2037,7 +1899,7 @@ uint64_t SROA::FindElementAndOffset(const Type *&T, uint64_t &Offset,
IdxTy = Type::getInt32Ty(T->getContext());
return Idx;
}
- const ArrayType *AT = cast<ArrayType>(T);
+ ArrayType *AT = cast<ArrayType>(T);
T = AT->getElementType();
uint64_t EltSize = TD->getTypeAllocSize(T);
Idx = Offset / EltSize;
@@ -2053,13 +1915,12 @@ void SROA::RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset,
SmallVector<AllocaInst*, 32> &NewElts) {
uint64_t OldOffset = Offset;
SmallVector<Value*, 8> Indices(GEPI->op_begin() + 1, GEPI->op_end());
- Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(),
- &Indices[0], Indices.size());
+ Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(), Indices);
RewriteForScalarRepl(GEPI, AI, Offset, NewElts);
- const Type *T = AI->getAllocatedType();
- const Type *IdxTy;
+ Type *T = AI->getAllocatedType();
+ Type *IdxTy;
uint64_t OldIdx = FindElementAndOffset(T, OldOffset, IdxTy);
if (GEPI->getOperand(0) == AI)
OldIdx = ~0ULL; // Force the GEP to be rewritten.
@@ -2073,7 +1934,7 @@ void SROA::RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset,
if (Idx == OldIdx)
return;
- const Type *i32Ty = Type::getInt32Ty(AI->getContext());
+ Type *i32Ty = Type::getInt32Ty(AI->getContext());
SmallVector<Value*, 8> NewArgs;
NewArgs.push_back(Constant::getNullValue(i32Ty));
while (EltOffset != 0) {
@@ -2082,8 +1943,7 @@ void SROA::RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset,
}
Instruction *Val = NewElts[Idx];
if (NewArgs.size() > 1) {
- Val = GetElementPtrInst::CreateInBounds(Val, NewArgs.begin(),
- NewArgs.end(), "", GEPI);
+ Val = GetElementPtrInst::CreateInBounds(Val, NewArgs, "", GEPI);
Val->takeName(GEPI);
}
if (Val->getType() != GEPI->getType())
@@ -2092,6 +1952,62 @@ void SROA::RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset,
DeadInsts.push_back(GEPI);
}
+/// RewriteLifetimeIntrinsic - II is a lifetime.start/lifetime.end. Rewrite it
+/// to mark the lifetime of the scalarized memory.
+void SROA::RewriteLifetimeIntrinsic(IntrinsicInst *II, AllocaInst *AI,
+ uint64_t Offset,
+ SmallVector<AllocaInst*, 32> &NewElts) {
+ ConstantInt *OldSize = cast<ConstantInt>(II->getArgOperand(0));
+ // Put matching lifetime markers on everything from Offset up to
+ // Offset+OldSize.
+ Type *AIType = AI->getAllocatedType();
+ uint64_t NewOffset = Offset;
+ Type *IdxTy;
+ uint64_t Idx = FindElementAndOffset(AIType, NewOffset, IdxTy);
+
+ IRBuilder<> Builder(II);
+ uint64_t Size = OldSize->getLimitedValue();
+
+ if (NewOffset) {
+ // Splice the first element and index 'NewOffset' bytes in. SROA will
+ // split the alloca again later.
+ Value *V = Builder.CreateBitCast(NewElts[Idx], Builder.getInt8PtrTy());
+ V = Builder.CreateGEP(V, Builder.getInt64(NewOffset));
+
+ IdxTy = NewElts[Idx]->getAllocatedType();
+ uint64_t EltSize = TD->getTypeAllocSize(IdxTy) - NewOffset;
+ if (EltSize > Size) {
+ EltSize = Size;
+ Size = 0;
+ } else {
+ Size -= EltSize;
+ }
+ if (II->getIntrinsicID() == Intrinsic::lifetime_start)
+ Builder.CreateLifetimeStart(V, Builder.getInt64(EltSize));
+ else
+ Builder.CreateLifetimeEnd(V, Builder.getInt64(EltSize));
+ ++Idx;
+ }
+
+ for (; Idx != NewElts.size() && Size; ++Idx) {
+ IdxTy = NewElts[Idx]->getAllocatedType();
+ uint64_t EltSize = TD->getTypeAllocSize(IdxTy);
+ if (EltSize > Size) {
+ EltSize = Size;
+ Size = 0;
+ } else {
+ Size -= EltSize;
+ }
+ if (II->getIntrinsicID() == Intrinsic::lifetime_start)
+ Builder.CreateLifetimeStart(NewElts[Idx],
+ Builder.getInt64(EltSize));
+ else
+ Builder.CreateLifetimeEnd(NewElts[Idx],
+ Builder.getInt64(EltSize));
+ }
+ DeadInsts.push_back(II);
+}
+
/// RewriteMemIntrinUserOfAlloca - MI is a memcpy/memset/memmove from or to AI.
/// Rewrite it to copy or set the elements of the scalarized memory.
void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
@@ -2139,7 +2055,7 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
// If the pointer is not the right type, insert a bitcast to the right
// type.
- const Type *NewTy =
+ Type *NewTy =
PointerType::get(AI->getType()->getElementType(), AddrSpace);
if (OtherPtr->getType() != NewTy)
@@ -2159,16 +2075,16 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
if (OtherPtr) {
Value *Idx[2] = { Zero,
ConstantInt::get(Type::getInt32Ty(MI->getContext()), i) };
- OtherElt = GetElementPtrInst::CreateInBounds(OtherPtr, Idx, Idx + 2,
+ OtherElt = GetElementPtrInst::CreateInBounds(OtherPtr, Idx,
OtherPtr->getName()+"."+Twine(i),
MI);
uint64_t EltOffset;
- const PointerType *OtherPtrTy = cast<PointerType>(OtherPtr->getType());
- const Type *OtherTy = OtherPtrTy->getElementType();
- if (const StructType *ST = dyn_cast<StructType>(OtherTy)) {
+ PointerType *OtherPtrTy = cast<PointerType>(OtherPtr->getType());
+ Type *OtherTy = OtherPtrTy->getElementType();
+ if (StructType *ST = dyn_cast<StructType>(OtherTy)) {
EltOffset = TD->getStructLayout(ST)->getElementOffset(i);
} else {
- const Type *EltTy = cast<SequentialType>(OtherTy)->getElementType();
+ Type *EltTy = cast<SequentialType>(OtherTy)->getElementType();
EltOffset = TD->getTypeAllocSize(EltTy)*i;
}
@@ -2181,7 +2097,7 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
}
Value *EltPtr = NewElts[i];
- const Type *EltTy = cast<PointerType>(EltPtr->getType())->getElementType();
+ Type *EltTy = cast<PointerType>(EltPtr->getType())->getElementType();
// If we got down to a scalar, insert a load or store as appropriate.
if (EltTy->isSingleValueType()) {
@@ -2207,7 +2123,7 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
StoreVal = Constant::getNullValue(EltTy); // 0.0, null, 0, <0,0>
} else {
// If EltTy is a vector type, get the element type.
- const Type *ValTy = EltTy->getScalarType();
+ Type *ValTy = EltTy->getScalarType();
// Construct an integer with the right value.
unsigned EltSize = TD->getTypeSizeInBits(ValTy);
@@ -2228,8 +2144,8 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
assert(StoreVal->getType() == ValTy && "Type mismatch!");
// If the requested value was a vector constant, create it.
- if (EltTy != ValTy) {
- unsigned NumElts = cast<VectorType>(ValTy)->getNumElements();
+ if (EltTy->isVectorTy()) {
+ unsigned NumElts = cast<VectorType>(EltTy)->getNumElements();
SmallVector<Constant*, 16> Elts(NumElts, StoreVal);
StoreVal = ConstantVector::get(Elts);
}
@@ -2271,7 +2187,7 @@ void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI,
// Extract each element out of the integer according to its structure offset
// and store the element value to the individual alloca.
Value *SrcVal = SI->getOperand(0);
- const Type *AllocaEltTy = AI->getAllocatedType();
+ Type *AllocaEltTy = AI->getAllocatedType();
uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy);
IRBuilder<> Builder(SI);
@@ -2286,12 +2202,12 @@ void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI,
// There are two forms here: AI could be an array or struct. Both cases
// have different ways to compute the element offset.
- if (const StructType *EltSTy = dyn_cast<StructType>(AllocaEltTy)) {
+ if (StructType *EltSTy = dyn_cast<StructType>(AllocaEltTy)) {
const StructLayout *Layout = TD->getStructLayout(EltSTy);
for (unsigned i = 0, e = NewElts.size(); i != e; ++i) {
// Get the number of bits to shift SrcVal to get the value.
- const Type *FieldTy = EltSTy->getElementType(i);
+ Type *FieldTy = EltSTy->getElementType(i);
uint64_t Shift = Layout->getElementOffsetInBits(i);
if (TD->isBigEndian())
@@ -2327,8 +2243,8 @@ void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI,
}
} else {
- const ArrayType *ATy = cast<ArrayType>(AllocaEltTy);
- const Type *ArrayEltTy = ATy->getElementType();
+ ArrayType *ATy = cast<ArrayType>(AllocaEltTy);
+ Type *ArrayEltTy = ATy->getElementType();
uint64_t ElementOffset = TD->getTypeAllocSizeInBits(ArrayEltTy);
uint64_t ElementSizeBits = TD->getTypeSizeInBits(ArrayEltTy);
@@ -2384,7 +2300,7 @@ void SROA::RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI,
SmallVector<AllocaInst*, 32> &NewElts) {
// Extract each element out of the NewElts according to its structure offset
// and form the result value.
- const Type *AllocaEltTy = AI->getAllocatedType();
+ Type *AllocaEltTy = AI->getAllocatedType();
uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy);
DEBUG(dbgs() << "PROMOTING LOAD OF WHOLE ALLOCA: " << *AI << '\n' << *LI
@@ -2394,10 +2310,10 @@ void SROA::RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI,
// have different ways to compute the element offset.
const StructLayout *Layout = 0;
uint64_t ArrayEltBitOffset = 0;
- if (const StructType *EltSTy = dyn_cast<StructType>(AllocaEltTy)) {
+ if (StructType *EltSTy = dyn_cast<StructType>(AllocaEltTy)) {
Layout = TD->getStructLayout(EltSTy);
} else {
- const Type *ArrayEltTy = cast<ArrayType>(AllocaEltTy)->getElementType();
+ Type *ArrayEltTy = cast<ArrayType>(AllocaEltTy)->getElementType();
ArrayEltBitOffset = TD->getTypeAllocSizeInBits(ArrayEltTy);
}
@@ -2408,14 +2324,14 @@ void SROA::RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI,
// Load the value from the alloca. If the NewElt is an aggregate, cast
// the pointer to an integer of the same size before doing the load.
Value *SrcField = NewElts[i];
- const Type *FieldTy =
+ Type *FieldTy =
cast<PointerType>(SrcField->getType())->getElementType();
uint64_t FieldSizeBits = TD->getTypeSizeInBits(FieldTy);
// Ignore zero sized fields like {}, they obviously contain no data.
if (FieldSizeBits == 0) continue;
- const IntegerType *FieldIntTy = IntegerType::get(LI->getContext(),
+ IntegerType *FieldIntTy = IntegerType::get(LI->getContext(),
FieldSizeBits);
if (!FieldTy->isIntegerTy() && !FieldTy->isFloatingPointTy() &&
!FieldTy->isVectorTy())
@@ -2468,14 +2384,14 @@ void SROA::RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI,
/// HasPadding - Return true if the specified type has any structure or
/// alignment padding in between the elements that would be split apart
/// by SROA; return false otherwise.
-static bool HasPadding(const Type *Ty, const TargetData &TD) {
- if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
+static bool HasPadding(Type *Ty, const TargetData &TD) {
+ if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
Ty = ATy->getElementType();
return TD.getTypeSizeInBits(Ty) != TD.getTypeAllocSizeInBits(Ty);
}
// SROA currently handles only Arrays and Structs.
- const StructType *STy = cast<StructType>(Ty);
+ StructType *STy = cast<StructType>(Ty);
const StructLayout *SL = TD.getStructLayout(STy);
unsigned PrevFieldBitOffset = 0;
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
@@ -2530,7 +2446,7 @@ bool SROA::isSafeAllocaToScalarRepl(AllocaInst *AI) {
// and fusion code.
if (!Info.hasSubelementAccess && Info.hasALoadOrStore) {
// If the struct/array just has one element, use basic SRoA.
- if (const StructType *ST = dyn_cast<StructType>(AI->getAllocatedType())) {
+ if (StructType *ST = dyn_cast<StructType>(AI->getAllocatedType())) {
if (ST->getNumElements() > 1) return false;
} else {
if (cast<ArrayType>(AI->getAllocatedType())->getNumElements() > 1)
@@ -2576,7 +2492,7 @@ isOnlyCopiedFromConstantGlobal(Value *V, MemTransferInst *&TheCopy,
if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
// Ignore non-volatile loads, they are always ok.
- if (LI->isVolatile()) return false;
+ if (!LI->isSimple()) return false;
continue;
}
diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
index 7c415e5..fbb9465 100644
--- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp
+++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
@@ -134,7 +134,7 @@ namespace {
struct StrCatOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strcat" function prototype.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
FT->getReturnType() != B.getInt8PtrTy() ||
FT->getParamType(0) != FT->getReturnType() ||
@@ -184,7 +184,7 @@ struct StrCatOpt : public LibCallOptimization {
struct StrNCatOpt : public StrCatOpt {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strncat" function prototype.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 ||
FT->getReturnType() != B.getInt8PtrTy() ||
FT->getParamType(0) != FT->getReturnType() ||
@@ -232,7 +232,7 @@ struct StrNCatOpt : public StrCatOpt {
struct StrChrOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strchr" function prototype.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
FT->getReturnType() != B.getInt8PtrTy() ||
FT->getParamType(0) != FT->getReturnType() ||
@@ -282,7 +282,7 @@ struct StrChrOpt : public LibCallOptimization {
struct StrRChrOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strrchr" function prototype.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
FT->getReturnType() != B.getInt8PtrTy() ||
FT->getParamType(0) != FT->getReturnType() ||
@@ -323,7 +323,7 @@ struct StrRChrOpt : public LibCallOptimization {
struct StrCmpOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strcmp" function prototype.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
!FT->getReturnType()->isIntegerTy(32) ||
FT->getParamType(0) != FT->getParamType(1) ||
@@ -338,16 +338,17 @@ struct StrCmpOpt : public LibCallOptimization {
bool HasStr1 = GetConstantStringInfo(Str1P, Str1);
bool HasStr2 = GetConstantStringInfo(Str2P, Str2);
- if (HasStr1 && Str1.empty()) // strcmp("", x) -> *x
- return B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"), CI->getType());
-
- if (HasStr2 && Str2.empty()) // strcmp(x,"") -> *x
- return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"), CI->getType());
-
// strcmp(x, y) -> cnst (if both x and y are constant strings)
if (HasStr1 && HasStr2)
return ConstantInt::get(CI->getType(),
- strcmp(Str1.c_str(),Str2.c_str()));
+ StringRef(Str1).compare(Str2));
+
+ if (HasStr1 && Str1.empty()) // strcmp("", x) -> -*x
+ return B.CreateNeg(B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"),
+ CI->getType()));
+
+ if (HasStr2 && Str2.empty()) // strcmp(x,"") -> *x
+ return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"), CI->getType());
// strcmp(P, "x") -> memcmp(P, "x", 2)
uint64_t Len1 = GetStringLength(Str1P);
@@ -371,7 +372,7 @@ struct StrCmpOpt : public LibCallOptimization {
struct StrNCmpOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strncmp" function prototype.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 ||
!FT->getReturnType()->isIntegerTy(32) ||
FT->getParamType(0) != FT->getParamType(1) ||
@@ -400,16 +401,20 @@ struct StrNCmpOpt : public LibCallOptimization {
bool HasStr1 = GetConstantStringInfo(Str1P, Str1);
bool HasStr2 = GetConstantStringInfo(Str2P, Str2);
- if (HasStr1 && Str1.empty()) // strncmp("", x, n) -> *x
- return B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"), CI->getType());
+ // strncmp(x, y) -> cnst (if both x and y are constant strings)
+ if (HasStr1 && HasStr2) {
+ StringRef SubStr1 = StringRef(Str1).substr(0, Length);
+ StringRef SubStr2 = StringRef(Str2).substr(0, Length);
+ return ConstantInt::get(CI->getType(), SubStr1.compare(SubStr2));
+ }
+
+ if (HasStr1 && Str1.empty()) // strncmp("", x, n) -> -*x
+ return B.CreateNeg(B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"),
+ CI->getType()));
if (HasStr2 && Str2.empty()) // strncmp(x, "", n) -> *x
return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"), CI->getType());
- // strncmp(x, y) -> cnst (if both x and y are constant strings)
- if (HasStr1 && HasStr2)
- return ConstantInt::get(CI->getType(),
- strncmp(Str1.c_str(), Str2.c_str(), Length));
return 0;
}
};
@@ -426,7 +431,7 @@ struct StrCpyOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Verify the "strcpy" function prototype.
unsigned NumParams = OptChkCall ? 3 : 2;
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != NumParams ||
FT->getReturnType() != FT->getParamType(0) ||
FT->getParamType(0) != FT->getParamType(1) ||
@@ -462,7 +467,7 @@ struct StrCpyOpt : public LibCallOptimization {
struct StrNCpyOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) ||
FT->getParamType(0) != FT->getParamType(1) ||
FT->getParamType(0) != B.getInt8PtrTy() ||
@@ -511,7 +516,7 @@ struct StrNCpyOpt : public LibCallOptimization {
struct StrLenOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 1 ||
FT->getParamType(0) != B.getInt8PtrTy() ||
!FT->getReturnType()->isIntegerTy())
@@ -537,7 +542,7 @@ struct StrLenOpt : public LibCallOptimization {
struct StrPBrkOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
FT->getParamType(0) != B.getInt8PtrTy() ||
FT->getParamType(1) != FT->getParamType(0) ||
@@ -575,7 +580,7 @@ struct StrPBrkOpt : public LibCallOptimization {
struct StrToOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if ((FT->getNumParams() != 2 && FT->getNumParams() != 3) ||
!FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy())
@@ -597,7 +602,7 @@ struct StrToOpt : public LibCallOptimization {
struct StrSpnOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
FT->getParamType(0) != B.getInt8PtrTy() ||
FT->getParamType(1) != FT->getParamType(0) ||
@@ -626,7 +631,7 @@ struct StrSpnOpt : public LibCallOptimization {
struct StrCSpnOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
FT->getParamType(0) != B.getInt8PtrTy() ||
FT->getParamType(1) != FT->getParamType(0) ||
@@ -658,7 +663,7 @@ struct StrCSpnOpt : public LibCallOptimization {
struct StrStrOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 ||
!FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy() ||
@@ -722,7 +727,7 @@ struct StrStrOpt : public LibCallOptimization {
struct MemCmpOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || !FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy() ||
!FT->getReturnType()->isIntegerTy(32))
@@ -773,7 +778,7 @@ struct MemCpyOpt : public LibCallOptimization {
// These optimizations require TargetData.
if (!TD) return 0;
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) ||
!FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy() ||
@@ -795,7 +800,7 @@ struct MemMoveOpt : public LibCallOptimization {
// These optimizations require TargetData.
if (!TD) return 0;
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) ||
!FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy() ||
@@ -817,7 +822,7 @@ struct MemSetOpt : public LibCallOptimization {
// These optimizations require TargetData.
if (!TD) return 0;
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) ||
!FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isIntegerTy() ||
@@ -840,7 +845,7 @@ struct MemSetOpt : public LibCallOptimization {
struct PowOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
// Just make sure this has 2 arguments of the same FP type, which match the
// result type.
if (FT->getNumParams() != 2 || FT->getReturnType() != FT->getParamType(0) ||
@@ -874,8 +879,8 @@ struct PowOpt : public LibCallOptimization {
Callee->getAttributes());
Value *FAbs = EmitUnaryFloatFnCall(Sqrt, "fabs", B,
Callee->getAttributes());
- Value *FCmp = B.CreateFCmpOEQ(Op1, NegInf, "tmp");
- Value *Sel = B.CreateSelect(FCmp, Inf, FAbs, "tmp");
+ Value *FCmp = B.CreateFCmpOEQ(Op1, NegInf);
+ Value *Sel = B.CreateSelect(FCmp, Inf, FAbs);
return Sel;
}
@@ -895,7 +900,7 @@ struct PowOpt : public LibCallOptimization {
struct Exp2Opt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
// Just make sure this has 1 argument of FP type, which matches the
// result type.
if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) ||
@@ -908,10 +913,10 @@ struct Exp2Opt : public LibCallOptimization {
Value *LdExpArg = 0;
if (SIToFPInst *OpC = dyn_cast<SIToFPInst>(Op)) {
if (OpC->getOperand(0)->getType()->getPrimitiveSizeInBits() <= 32)
- LdExpArg = B.CreateSExt(OpC->getOperand(0), B.getInt32Ty(), "tmp");
+ LdExpArg = B.CreateSExt(OpC->getOperand(0), B.getInt32Ty());
} else if (UIToFPInst *OpC = dyn_cast<UIToFPInst>(Op)) {
if (OpC->getOperand(0)->getType()->getPrimitiveSizeInBits() < 32)
- LdExpArg = B.CreateZExt(OpC->getOperand(0), B.getInt32Ty(), "tmp");
+ LdExpArg = B.CreateZExt(OpC->getOperand(0), B.getInt32Ty());
}
if (LdExpArg) {
@@ -946,7 +951,7 @@ struct Exp2Opt : public LibCallOptimization {
struct UnaryDoubleFPOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 1 || !FT->getReturnType()->isDoubleTy() ||
!FT->getParamType(0)->isDoubleTy())
return 0;
@@ -973,7 +978,7 @@ struct UnaryDoubleFPOpt : public LibCallOptimization {
struct FFSOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
// Just make sure this has 2 arguments of the same FP type, which match the
// result type.
if (FT->getNumParams() != 1 ||
@@ -996,10 +1001,10 @@ struct FFSOpt : public LibCallOptimization {
Value *F = Intrinsic::getDeclaration(Callee->getParent(),
Intrinsic::cttz, ArgType);
Value *V = B.CreateCall(F, Op, "cttz");
- V = B.CreateAdd(V, ConstantInt::get(V->getType(), 1), "tmp");
- V = B.CreateIntCast(V, B.getInt32Ty(), false, "tmp");
+ V = B.CreateAdd(V, ConstantInt::get(V->getType(), 1));
+ V = B.CreateIntCast(V, B.getInt32Ty(), false);
- Value *Cond = B.CreateICmpNE(Op, Constant::getNullValue(ArgType), "tmp");
+ Value *Cond = B.CreateICmpNE(Op, Constant::getNullValue(ArgType));
return B.CreateSelect(Cond, V, B.getInt32(0));
}
};
@@ -1009,7 +1014,7 @@ struct FFSOpt : public LibCallOptimization {
struct IsDigitOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
// We require integer(i32)
if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
!FT->getParamType(0)->isIntegerTy(32))
@@ -1028,7 +1033,7 @@ struct IsDigitOpt : public LibCallOptimization {
struct IsAsciiOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
// We require integer(i32)
if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
!FT->getParamType(0)->isIntegerTy(32))
@@ -1046,7 +1051,7 @@ struct IsAsciiOpt : public LibCallOptimization {
struct AbsOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
// We require integer(integer) where the types agree.
if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
FT->getParamType(0) != FT->getReturnType())
@@ -1067,7 +1072,7 @@ struct AbsOpt : public LibCallOptimization {
struct ToAsciiOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
// We require i32(i32)
if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) ||
!FT->getParamType(0)->isIntegerTy(32))
@@ -1147,7 +1152,7 @@ struct PrintFOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Require one fixed pointer argument and an integer/void result.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() ||
!(FT->getReturnType()->isIntegerTy() ||
FT->getReturnType()->isVoidTy()))
@@ -1241,7 +1246,7 @@ struct SPrintFOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Require two fixed pointer arguments and an integer result.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy() ||
!FT->getReturnType()->isIntegerTy())
@@ -1272,7 +1277,7 @@ struct SPrintFOpt : public LibCallOptimization {
struct FWriteOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Require a pointer, an integer, an integer, a pointer, returning integer.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 4 || !FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isIntegerTy() ||
!FT->getParamType(2)->isIntegerTy() ||
@@ -1310,7 +1315,7 @@ struct FPutsOpt : public LibCallOptimization {
if (!TD) return 0;
// Require two pointers. Also, we can't optimize if return value is used.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy() ||
!CI->use_empty())
@@ -1379,7 +1384,7 @@ struct FPrintFOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Require two fixed paramters as pointers and integer result.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
!FT->getParamType(1)->isPointerTy() ||
!FT->getReturnType()->isIntegerTy())
@@ -1410,7 +1415,7 @@ struct FPrintFOpt : public LibCallOptimization {
struct PutsOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
// Require one fixed pointer argument and an integer/void result.
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() ||
!(FT->getReturnType()->isIntegerTy() ||
FT->getReturnType()->isVoidTy()))
@@ -1685,7 +1690,7 @@ void SimplifyLibCalls::setDoesNotAlias(Function &F, unsigned n) {
void SimplifyLibCalls::inferPrototypeAttributes(Function &F) {
- const FunctionType *FTy = F.getFunctionType();
+ FunctionType *FTy = F.getFunctionType();
StringRef Name = F.getName();
switch (Name[0]) {
diff --git a/lib/Transforms/Scalar/Sink.cpp b/lib/Transforms/Scalar/Sink.cpp
index 705f442..c83f56c 100644
--- a/lib/Transforms/Scalar/Sink.cpp
+++ b/lib/Transforms/Scalar/Sink.cpp
@@ -153,9 +153,13 @@ bool Sinking::ProcessBlock(BasicBlock &BB) {
static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA,
SmallPtrSet<Instruction *, 8> &Stores) {
- if (LoadInst *L = dyn_cast<LoadInst>(Inst)) {
- if (L->isVolatile()) return false;
+ if (Inst->mayWriteToMemory()) {
+ Stores.insert(Inst);
+ return false;
+ }
+
+ if (LoadInst *L = dyn_cast<LoadInst>(Inst)) {
AliasAnalysis::Location Loc = AA->getLocation(L);
for (SmallPtrSet<Instruction *, 8>::iterator I = Stores.begin(),
E = Stores.end(); I != E; ++I)
@@ -163,11 +167,6 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA,
return false;
}
- if (Inst->mayWriteToMemory()) {
- Stores.insert(Inst);
- return false;
- }
-
if (isa<TerminatorInst>(Inst) || isa<PHINode>(Inst))
return false;
diff --git a/lib/Transforms/Scalar/TailDuplication.cpp b/lib/Transforms/Scalar/TailDuplication.cpp
deleted file mode 100644
index 9dd83c0..0000000
--- a/lib/Transforms/Scalar/TailDuplication.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-//===- TailDuplication.cpp - Simplify CFG through tail duplication --------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This pass performs a limited form of tail duplication, intended to simplify
-// CFGs by removing some unconditional branches. This pass is necessary to
-// straighten out loops created by the C front-end, but also is capable of
-// making other code nicer. After this pass is run, the CFG simplify pass
-// should be run to clean up the mess.
-//
-// This pass could be enhanced in the future to use profile information to be
-// more aggressive.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "tailduplicate"
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Constant.h"
-#include "llvm/Function.h"
-#include "llvm/Instructions.h"
-#include "llvm/IntrinsicInst.h"
-#include "llvm/Pass.h"
-#include "llvm/Type.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/Analysis/InstructionSimplify.h"
-#include "llvm/Support/CFG.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/Utils/Local.h"
-#include <map>
-using namespace llvm;
-
-STATISTIC(NumEliminated, "Number of unconditional branches eliminated");
-
-static cl::opt<unsigned>
-TailDupThreshold("taildup-threshold",
- cl::desc("Max block size to tail duplicate"),
- cl::init(1), cl::Hidden);
-
-namespace {
- class TailDup : public FunctionPass {
- bool runOnFunction(Function &F);
- public:
- static char ID; // Pass identification, replacement for typeid
- TailDup() : FunctionPass(ID) {
- initializeTailDupPass(*PassRegistry::getPassRegistry());
- }
-
- private:
- inline bool shouldEliminateUnconditionalBranch(TerminatorInst *, unsigned);
- inline void eliminateUnconditionalBranch(BranchInst *BI);
- SmallPtrSet<BasicBlock*, 4> CycleDetector;
- };
-}
-
-char TailDup::ID = 0;
-INITIALIZE_PASS(TailDup, "tailduplicate", "Tail Duplication", false, false)
-
-// Public interface to the Tail Duplication pass
-FunctionPass *llvm::createTailDuplicationPass() { return new TailDup(); }
-
-/// runOnFunction - Top level algorithm - Loop over each unconditional branch in
-/// the function, eliminating it if it looks attractive enough. CycleDetector
-/// prevents infinite loops by checking that we aren't redirecting a branch to
-/// a place it already pointed to earlier; see PR 2323.
-bool TailDup::runOnFunction(Function &F) {
- bool Changed = false;
- CycleDetector.clear();
- for (Function::iterator I = F.begin(), E = F.end(); I != E; ) {
- if (shouldEliminateUnconditionalBranch(I->getTerminator(),
- TailDupThreshold)) {
- eliminateUnconditionalBranch(cast<BranchInst>(I->getTerminator()));
- Changed = true;
- } else {
- ++I;
- CycleDetector.clear();
- }
- }
- return Changed;
-}
-
-/// shouldEliminateUnconditionalBranch - Return true if this branch looks
-/// attractive to eliminate. We eliminate the branch if the destination basic
-/// block has <= 5 instructions in it, not counting PHI nodes. In practice,
-/// since one of these is a terminator instruction, this means that we will add
-/// up to 4 instructions to the new block.
-///
-/// We don't count PHI nodes in the count since they will be removed when the
-/// contents of the block are copied over.
-///
-bool TailDup::shouldEliminateUnconditionalBranch(TerminatorInst *TI,
- unsigned Threshold) {
- BranchInst *BI = dyn_cast<BranchInst>(TI);
- if (!BI || !BI->isUnconditional()) return false; // Not an uncond branch!
-
- BasicBlock *Dest = BI->getSuccessor(0);
- if (Dest == BI->getParent()) return false; // Do not loop infinitely!
-
- // Do not inline a block if we will just get another branch to the same block!
- TerminatorInst *DTI = Dest->getTerminator();
- if (BranchInst *DBI = dyn_cast<BranchInst>(DTI))
- if (DBI->isUnconditional() && DBI->getSuccessor(0) == Dest)
- return false; // Do not loop infinitely!
-
- // FIXME: DemoteRegToStack cannot yet demote invoke instructions to the stack,
- // because doing so would require breaking critical edges. This should be
- // fixed eventually.
- if (!DTI->use_empty())
- return false;
-
- // Do not bother with blocks with only a single predecessor: simplify
- // CFG will fold these two blocks together!
- pred_iterator PI = pred_begin(Dest), PE = pred_end(Dest);
- ++PI;
- if (PI == PE) return false; // Exactly one predecessor!
-
- BasicBlock::iterator I = Dest->getFirstNonPHI();
-
- for (unsigned Size = 0; I != Dest->end(); ++I) {
- if (Size == Threshold) return false; // The block is too large.
-
- // Don't tail duplicate call instructions. They are very large compared to
- // other instructions.
- if (isa<CallInst>(I) || isa<InvokeInst>(I)) return false;
-
- // Also alloca and malloc.
- if (isa<AllocaInst>(I)) return false;
-
- // Some vector instructions can expand into a number of instructions.
- if (isa<ShuffleVectorInst>(I) || isa<ExtractElementInst>(I) ||
- isa<InsertElementInst>(I)) return false;
-
- // Only count instructions that are not debugger intrinsics.
- if (!isa<DbgInfoIntrinsic>(I)) ++Size;
- }
-
- // Do not tail duplicate a block that has thousands of successors into a block
- // with a single successor if the block has many other predecessors. This can
- // cause an N^2 explosion in CFG edges (and PHI node entries), as seen in
- // cases that have a large number of indirect gotos.
- unsigned NumSuccs = DTI->getNumSuccessors();
- if (NumSuccs > 8) {
- unsigned TooMany = 128;
- if (NumSuccs >= TooMany) return false;
- TooMany = TooMany/NumSuccs;
- for (; PI != PE; ++PI)
- if (TooMany-- == 0) return false;
- }
-
- // If this unconditional branch is a fall-through, be careful about
- // tail duplicating it. In particular, we don't want to taildup it if the
- // original block will still be there after taildup is completed: doing so
- // would eliminate the fall-through, requiring unconditional branches.
- Function::iterator DestI = Dest;
- if (&*--DestI == BI->getParent()) {
- // The uncond branch is a fall-through. Tail duplication of the block is
- // will eliminate the fall-through-ness and end up cloning the terminator
- // at the end of the Dest block. Since the original Dest block will
- // continue to exist, this means that one or the other will not be able to
- // fall through. One typical example that this helps with is code like:
- // if (a)
- // foo();
- // if (b)
- // foo();
- // Cloning the 'if b' block into the end of the first foo block is messy.
-
- // The messy case is when the fall-through block falls through to other
- // blocks. This is what we would be preventing if we cloned the block.
- DestI = Dest;
- if (++DestI != Dest->getParent()->end()) {
- BasicBlock *DestSucc = DestI;
- // If any of Dest's successors are fall-throughs, don't do this xform.
- for (succ_iterator SI = succ_begin(Dest), SE = succ_end(Dest);
- SI != SE; ++SI)
- if (*SI == DestSucc)
- return false;
- }
- }
-
- // Finally, check that we haven't redirected to this target block earlier;
- // there are cases where we loop forever if we don't check this (PR 2323).
- if (!CycleDetector.insert(Dest))
- return false;
-
- return true;
-}
-
-/// FindObviousSharedDomOf - We know there is a branch from SrcBlock to
-/// DestBlock, and that SrcBlock is not the only predecessor of DstBlock. If we
-/// can find a predecessor of SrcBlock that is a dominator of both SrcBlock and
-/// DstBlock, return it.
-static BasicBlock *FindObviousSharedDomOf(BasicBlock *SrcBlock,
- BasicBlock *DstBlock) {
- // SrcBlock must have a single predecessor.
- pred_iterator PI = pred_begin(SrcBlock), PE = pred_end(SrcBlock);
- if (PI == PE || ++PI != PE) return 0;
-
- BasicBlock *SrcPred = *pred_begin(SrcBlock);
-
- // Look at the predecessors of DstBlock. One of them will be SrcBlock. If
- // there is only one other pred, get it, otherwise we can't handle it.
- PI = pred_begin(DstBlock); PE = pred_end(DstBlock);
- BasicBlock *DstOtherPred = 0;
- BasicBlock *P = *PI;
- if (P == SrcBlock) {
- if (++PI == PE) return 0;
- DstOtherPred = *PI;
- if (++PI != PE) return 0;
- } else {
- DstOtherPred = P;
- if (++PI == PE || *PI != SrcBlock || ++PI != PE) return 0;
- }
-
- // We can handle two situations here: "if then" and "if then else" blocks. An
- // 'if then' situation is just where DstOtherPred == SrcPred.
- if (DstOtherPred == SrcPred)
- return SrcPred;
-
- // Check to see if we have an "if then else" situation, which means that
- // DstOtherPred will have a single predecessor and it will be SrcPred.
- PI = pred_begin(DstOtherPred); PE = pred_end(DstOtherPred);
- if (PI != PE && *PI == SrcPred) {
- if (++PI != PE) return 0; // Not a single pred.
- return SrcPred; // Otherwise, it's an "if then" situation. Return the if.
- }
-
- // Otherwise, this is something we can't handle.
- return 0;
-}
-
-
-/// eliminateUnconditionalBranch - Clone the instructions from the destination
-/// block into the source block, eliminating the specified unconditional branch.
-/// If the destination block defines values used by successors of the dest
-/// block, we may need to insert PHI nodes.
-///
-void TailDup::eliminateUnconditionalBranch(BranchInst *Branch) {
- BasicBlock *SourceBlock = Branch->getParent();
- BasicBlock *DestBlock = Branch->getSuccessor(0);
- assert(SourceBlock != DestBlock && "Our predicate is broken!");
-
- DEBUG(dbgs() << "TailDuplication[" << SourceBlock->getParent()->getName()
- << "]: Eliminating branch: " << *Branch);
-
- // See if we can avoid duplicating code by moving it up to a dominator of both
- // blocks.
- if (BasicBlock *DomBlock = FindObviousSharedDomOf(SourceBlock, DestBlock)) {
- DEBUG(dbgs() << "Found shared dominator: " << DomBlock->getName() << "\n");
-
- // If there are non-phi instructions in DestBlock that have no operands
- // defined in DestBlock, and if the instruction has no side effects, we can
- // move the instruction to DomBlock instead of duplicating it.
- BasicBlock::iterator BBI = DestBlock->getFirstNonPHI();
- while (!isa<TerminatorInst>(BBI)) {
- Instruction *I = BBI++;
-
- bool CanHoist = I->isSafeToSpeculativelyExecute() &&
- !I->mayReadFromMemory();
- if (CanHoist) {
- for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
- if (Instruction *OpI = dyn_cast<Instruction>(I->getOperand(op)))
- if (OpI->getParent() == DestBlock ||
- (isa<InvokeInst>(OpI) && OpI->getParent() == DomBlock)) {
- CanHoist = false;
- break;
- }
- if (CanHoist) {
- // Remove from DestBlock, move right before the term in DomBlock.
- DestBlock->getInstList().remove(I);
- DomBlock->getInstList().insert(DomBlock->getTerminator(), I);
- DEBUG(dbgs() << "Hoisted: " << *I);
- }
- }
- }
- }
-
- // Tail duplication can not update SSA properties correctly if the values
- // defined in the duplicated tail are used outside of the tail itself. For
- // this reason, we spill all values that are used outside of the tail to the
- // stack.
- for (BasicBlock::iterator I = DestBlock->begin(); I != DestBlock->end(); ++I)
- if (I->isUsedOutsideOfBlock(DestBlock)) {
- // We found a use outside of the tail. Create a new stack slot to
- // break this inter-block usage pattern.
- DemoteRegToStack(*I);
- }
-
- // We are going to have to map operands from the original block B to the new
- // copy of the block B'. If there are PHI nodes in the DestBlock, these PHI
- // nodes also define part of this mapping. Loop over these PHI nodes, adding
- // them to our mapping.
- //
- std::map<Value*, Value*> ValueMapping;
-
- BasicBlock::iterator BI = DestBlock->begin();
- bool HadPHINodes = isa<PHINode>(BI);
- for (; PHINode *PN = dyn_cast<PHINode>(BI); ++BI)
- ValueMapping[PN] = PN->getIncomingValueForBlock(SourceBlock);
-
- // Clone the non-phi instructions of the dest block into the source block,
- // keeping track of the mapping...
- //
- for (; BI != DestBlock->end(); ++BI) {
- Instruction *New = BI->clone();
- New->setName(BI->getName());
- SourceBlock->getInstList().push_back(New);
- ValueMapping[BI] = New;
- }
-
- // Now that we have built the mapping information and cloned all of the
- // instructions (giving us a new terminator, among other things), walk the new
- // instructions, rewriting references of old instructions to use new
- // instructions.
- //
- BI = Branch; ++BI; // Get an iterator to the first new instruction
- for (; BI != SourceBlock->end(); ++BI)
- for (unsigned i = 0, e = BI->getNumOperands(); i != e; ++i) {
- std::map<Value*, Value*>::const_iterator I =
- ValueMapping.find(BI->getOperand(i));
- if (I != ValueMapping.end())
- BI->setOperand(i, I->second);
- }
-
- // Next we check to see if any of the successors of DestBlock had PHI nodes.
- // If so, we need to add entries to the PHI nodes for SourceBlock now.
- for (succ_iterator SI = succ_begin(DestBlock), SE = succ_end(DestBlock);
- SI != SE; ++SI) {
- BasicBlock *Succ = *SI;
- for (BasicBlock::iterator PNI = Succ->begin(); isa<PHINode>(PNI); ++PNI) {
- PHINode *PN = cast<PHINode>(PNI);
- // Ok, we have a PHI node. Figure out what the incoming value was for the
- // DestBlock.
- Value *IV = PN->getIncomingValueForBlock(DestBlock);
-
- // Remap the value if necessary...
- std::map<Value*, Value*>::const_iterator I = ValueMapping.find(IV);
- if (I != ValueMapping.end())
- IV = I->second;
- PN->addIncoming(IV, SourceBlock);
- }
- }
-
- // Next, remove the old branch instruction, and any PHI node entries that we
- // had.
- BI = Branch; ++BI; // Get an iterator to the first new instruction
- DestBlock->removePredecessor(SourceBlock); // Remove entries in PHI nodes...
- SourceBlock->getInstList().erase(Branch); // Destroy the uncond branch...
-
- // Final step: now that we have finished everything up, walk the cloned
- // instructions one last time, constant propagating and DCE'ing them, because
- // they may not be needed anymore.
- //
- if (HadPHINodes) {
- while (BI != SourceBlock->end()) {
- Instruction *Inst = BI++;
- if (isInstructionTriviallyDead(Inst))
- Inst->eraseFromParent();
- else if (Value *V = SimplifyInstruction(Inst)) {
- Inst->replaceAllUsesWith(V);
- Inst->eraseFromParent();
- }
- }
- }
-
- ++NumEliminated; // We just killed a branch!
-}
diff --git a/lib/Transforms/Utils/AddrModeMatcher.cpp b/lib/Transforms/Utils/AddrModeMatcher.cpp
index be7bed1..8e5a1eb 100644
--- a/lib/Transforms/Utils/AddrModeMatcher.cpp
+++ b/lib/Transforms/Utils/AddrModeMatcher.cpp
@@ -222,7 +222,7 @@ bool AddressingModeMatcher::MatchOperationAddr(User *AddrInst, unsigned Opcode,
const TargetData *TD = TLI.getTargetData();
gep_type_iterator GTI = gep_type_begin(AddrInst);
for (unsigned i = 1, e = AddrInst->getNumOperands(); i != e; ++i, ++GTI) {
- if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
+ if (StructType *STy = dyn_cast<StructType>(*GTI)) {
const StructLayout *SL = TD->getStructLayout(STy);
unsigned Idx =
cast<ConstantInt>(AddrInst->getOperand(i))->getZExtValue();
@@ -557,7 +557,7 @@ IsProfitableToFoldIntoAddressingMode(Instruction *I, ExtAddrMode &AMBefore,
Value *Address = User->getOperand(OpNo);
if (!Address->getType()->isPointerTy())
return false;
- const Type *AddressAccessTy =
+ Type *AddressAccessTy =
cast<PointerType>(Address->getType())->getElementType();
// Do a match against the root of this address, ignoring profitability. This
diff --git a/lib/Transforms/Utils/BasicBlockUtils.cpp b/lib/Transforms/Utils/BasicBlockUtils.cpp
index b4f74f9..a7f9efd 100644
--- a/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -287,7 +287,7 @@ BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, Pass *P) {
///
BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P) {
BasicBlock::iterator SplitIt = SplitPt;
- while (isa<PHINode>(SplitIt))
+ while (isa<PHINode>(SplitIt) || isa<LandingPadInst>(SplitIt))
++SplitIt;
BasicBlock *New = Old->splitBasicBlock(SplitIt, Old->getName()+".split");
@@ -299,138 +299,114 @@ BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P) {
if (DominatorTree *DT = P->getAnalysisIfAvailable<DominatorTree>()) {
// Old dominates New. New node dominates all other nodes dominated by Old.
- DomTreeNode *OldNode = DT->getNode(Old);
- std::vector<DomTreeNode *> Children;
- for (DomTreeNode::iterator I = OldNode->begin(), E = OldNode->end();
- I != E; ++I)
- Children.push_back(*I);
+ if (DomTreeNode *OldNode = DT->getNode(Old)) {
+ std::vector<DomTreeNode *> Children;
+ for (DomTreeNode::iterator I = OldNode->begin(), E = OldNode->end();
+ I != E; ++I)
+ Children.push_back(*I);
DomTreeNode *NewNode = DT->addNewBlock(New,Old);
for (std::vector<DomTreeNode *>::iterator I = Children.begin(),
E = Children.end(); I != E; ++I)
DT->changeImmediateDominator(*I, NewNode);
+ }
}
return New;
}
+/// UpdateAnalysisInformation - Update DominatorTree, LoopInfo, and LCCSA
+/// analysis information.
+static void UpdateAnalysisInformation(BasicBlock *OldBB, BasicBlock *NewBB,
+ ArrayRef<BasicBlock *> Preds,
+ Pass *P, bool &HasLoopExit) {
+ if (!P) return;
-/// SplitBlockPredecessors - This method transforms BB by introducing a new
-/// basic block into the function, and moving some of the predecessors of BB to
-/// be predecessors of the new block. The new predecessors are indicated by the
-/// Preds array, which has NumPreds elements in it. The new block is given a
-/// suffix of 'Suffix'.
-///
-/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree,
-/// 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).
-///
-BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
- BasicBlock *const *Preds,
- unsigned NumPreds, const char *Suffix,
- Pass *P) {
- // Create new basic block, insert right before the original block.
- BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), BB->getName()+Suffix,
- BB->getParent(), BB);
-
- // The new block unconditionally branches to the old block.
- BranchInst *BI = BranchInst::Create(BB, NewBB);
-
- LoopInfo *LI = P ? P->getAnalysisIfAvailable<LoopInfo>() : 0;
- Loop *L = LI ? LI->getLoopFor(BB) : 0;
- bool PreserveLCSSA = P->mustPreserveAnalysisID(LCSSAID);
+ LoopInfo *LI = P->getAnalysisIfAvailable<LoopInfo>();
+ Loop *L = LI ? LI->getLoopFor(OldBB) : 0;
- // Move the edges from Preds to point to NewBB instead of BB.
- // While here, if we need to preserve loop analyses, collect
- // some information about how this split will affect loops.
- bool HasLoopExit = false;
+ // If we need to preserve loop analyses, collect some information about how
+ // this split will affect loops.
bool IsLoopEntry = !!L;
bool SplitMakesNewLoopHeader = false;
- for (unsigned i = 0; i != NumPreds; ++i) {
- // This is slightly more strict than necessary; the minimum requirement
- // is that there be no more than one indirectbr branching to BB. And
- // all BlockAddress uses would need to be updated.
- assert(!isa<IndirectBrInst>(Preds[i]->getTerminator()) &&
- "Cannot split an edge from an IndirectBrInst");
-
- Preds[i]->getTerminator()->replaceUsesOfWith(BB, NewBB);
-
- if (LI) {
- // If we need to preserve LCSSA, determine if any of
- // the preds is a loop exit.
+ if (LI) {
+ bool PreserveLCSSA = P->mustPreserveAnalysisID(LCSSAID);
+ for (ArrayRef<BasicBlock*>::iterator
+ i = Preds.begin(), e = Preds.end(); i != e; ++i) {
+ BasicBlock *Pred = *i;
+
+ // If we need to preserve LCSSA, determine if any of the preds is a loop
+ // exit.
if (PreserveLCSSA)
- if (Loop *PL = LI->getLoopFor(Preds[i]))
- if (!PL->contains(BB))
+ if (Loop *PL = LI->getLoopFor(Pred))
+ if (!PL->contains(OldBB))
HasLoopExit = true;
- // If we need to preserve LoopInfo, note whether any of the
- // preds crosses an interesting loop boundary.
- if (L) {
- if (L->contains(Preds[i]))
- IsLoopEntry = false;
- else
- SplitMakesNewLoopHeader = true;
- }
+
+ // If we need to preserve LoopInfo, note whether any of the preds crosses
+ // an interesting loop boundary.
+ if (!L) continue;
+ if (L->contains(Pred))
+ IsLoopEntry = false;
+ else
+ SplitMakesNewLoopHeader = true;
}
}
// Update dominator tree if available.
- DominatorTree *DT = P ? P->getAnalysisIfAvailable<DominatorTree>() : 0;
+ DominatorTree *DT = P->getAnalysisIfAvailable<DominatorTree>();
if (DT)
DT->splitBlock(NewBB);
- // Insert a new PHI node into NewBB for every PHI node in BB and that new PHI
- // node becomes an incoming value for BB's phi node. However, if the Preds
- // list is empty, we need to insert dummy entries into the PHI nodes in BB to
- // account for the newly created predecessor.
- if (NumPreds == 0) {
- // Insert dummy values as the incoming value.
- for (BasicBlock::iterator I = BB->begin(); isa<PHINode>(I); ++I)
- cast<PHINode>(I)->addIncoming(UndefValue::get(I->getType()), NewBB);
- return NewBB;
+ if (!L) return;
+
+ if (IsLoopEntry) {
+ // Add the new block to the nearest enclosing loop (and not an adjacent
+ // loop). To find this, examine each of the predecessors and determine which
+ // loops enclose them, and select the most-nested loop which contains the
+ // loop containing the block being split.
+ Loop *InnermostPredLoop = 0;
+ for (ArrayRef<BasicBlock*>::iterator
+ i = Preds.begin(), e = Preds.end(); i != e; ++i) {
+ BasicBlock *Pred = *i;
+ if (Loop *PredLoop = LI->getLoopFor(Pred)) {
+ // Seek a loop which actually contains the block being split (to avoid
+ // adjacent loops).
+ while (PredLoop && !PredLoop->contains(OldBB))
+ PredLoop = PredLoop->getParentLoop();
+
+ // Select the most-nested of these loops which contains the block.
+ if (PredLoop && PredLoop->contains(OldBB) &&
+ (!InnermostPredLoop ||
+ InnermostPredLoop->getLoopDepth() < PredLoop->getLoopDepth()))
+ InnermostPredLoop = PredLoop;
+ }
+ }
+
+ if (InnermostPredLoop)
+ InnermostPredLoop->addBasicBlockToLoop(NewBB, LI->getBase());
+ } else {
+ L->addBasicBlockToLoop(NewBB, LI->getBase());
+ if (SplitMakesNewLoopHeader)
+ L->moveToHeader(NewBB);
}
+}
+/// UpdatePHINodes - Update the PHI nodes in OrigBB to include the values coming
+/// from NewBB. This also updates AliasAnalysis, if available.
+static void UpdatePHINodes(BasicBlock *OrigBB, BasicBlock *NewBB,
+ ArrayRef<BasicBlock*> Preds, BranchInst *BI,
+ Pass *P, bool HasLoopExit) {
+ // Otherwise, create a new PHI node in NewBB for each PHI node in OrigBB.
AliasAnalysis *AA = P ? P->getAnalysisIfAvailable<AliasAnalysis>() : 0;
-
- if (L) {
- if (IsLoopEntry) {
- // Add the new block to the nearest enclosing loop (and not an
- // adjacent loop). To find this, examine each of the predecessors and
- // determine which loops enclose them, and select the most-nested loop
- // which contains the loop containing the block being split.
- Loop *InnermostPredLoop = 0;
- for (unsigned i = 0; i != NumPreds; ++i)
- if (Loop *PredLoop = LI->getLoopFor(Preds[i])) {
- // Seek a loop which actually contains the block being split (to
- // avoid adjacent loops).
- while (PredLoop && !PredLoop->contains(BB))
- PredLoop = PredLoop->getParentLoop();
- // Select the most-nested of these loops which contains the block.
- if (PredLoop &&
- PredLoop->contains(BB) &&
- (!InnermostPredLoop ||
- InnermostPredLoop->getLoopDepth() < PredLoop->getLoopDepth()))
- InnermostPredLoop = PredLoop;
- }
- if (InnermostPredLoop)
- InnermostPredLoop->addBasicBlockToLoop(NewBB, LI->getBase());
- } else {
- L->addBasicBlockToLoop(NewBB, LI->getBase());
- if (SplitMakesNewLoopHeader)
- L->moveToHeader(NewBB);
- }
- }
-
- // Otherwise, create a new PHI node in NewBB for each PHI node in BB.
- for (BasicBlock::iterator I = BB->begin(); isa<PHINode>(I); ) {
+ for (BasicBlock::iterator I = OrigBB->begin(); isa<PHINode>(I); ) {
PHINode *PN = cast<PHINode>(I++);
-
+
// Check to see if all of the values coming in are the same. If so, we
// don't need to create a new PHI node, unless it's needed for LCSSA.
Value *InVal = 0;
if (!HasLoopExit) {
InVal = PN->getIncomingValueForBlock(Preds[0]);
- for (unsigned i = 1; i != NumPreds; ++i)
+ for (unsigned i = 1, e = Preds.size(); i != e; ++i)
if (InVal != PN->getIncomingValueForBlock(Preds[i])) {
InVal = 0;
break;
@@ -441,31 +417,191 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
// If all incoming values for the new PHI would be the same, just don't
// make a new PHI. Instead, just remove the incoming values from the old
// PHI.
- for (unsigned i = 0; i != NumPreds; ++i)
+ for (unsigned i = 0, e = Preds.size(); i != e; ++i)
PN->removeIncomingValue(Preds[i], false);
} else {
// If the values coming into the block are not the same, we need a PHI.
// Create the new PHI node, insert it into NewBB at the end of the block
PHINode *NewPHI =
- PHINode::Create(PN->getType(), NumPreds, PN->getName()+".ph", BI);
+ PHINode::Create(PN->getType(), Preds.size(), PN->getName() + ".ph", BI);
if (AA) AA->copyValue(PN, NewPHI);
// Move all of the PHI values for 'Preds' to the new PHI.
- for (unsigned i = 0; i != NumPreds; ++i) {
+ for (unsigned i = 0, e = Preds.size(); i != e; ++i) {
Value *V = PN->removeIncomingValue(Preds[i], false);
NewPHI->addIncoming(V, Preds[i]);
}
+
InVal = NewPHI;
}
-
+
// Add an incoming value to the PHI node in the loop for the preheader
// edge.
PN->addIncoming(InVal, NewBB);
}
+}
+
+/// SplitBlockPredecessors - This method transforms BB by introducing a new
+/// basic block into the function, and moving some of the predecessors of BB to
+/// be predecessors of the new block. The new predecessors are indicated by the
+/// Preds array, which has NumPreds elements in it. The new block is given a
+/// suffix of 'Suffix'.
+///
+/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree,
+/// 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).
+///
+BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
+ BasicBlock *const *Preds,
+ unsigned NumPreds, const char *Suffix,
+ Pass *P) {
+ // Create new basic block, insert right before the original block.
+ BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), BB->getName()+Suffix,
+ BB->getParent(), BB);
+ // The new block unconditionally branches to the old block.
+ BranchInst *BI = BranchInst::Create(BB, NewBB);
+
+ // Move the edges from Preds to point to NewBB instead of BB.
+ for (unsigned i = 0; i != NumPreds; ++i) {
+ // This is slightly more strict than necessary; the minimum requirement
+ // is that there be no more than one indirectbr branching to BB. And
+ // all BlockAddress uses would need to be updated.
+ assert(!isa<IndirectBrInst>(Preds[i]->getTerminator()) &&
+ "Cannot split an edge from an IndirectBrInst");
+ Preds[i]->getTerminator()->replaceUsesOfWith(BB, NewBB);
+ }
+
+ // Insert a new PHI node into NewBB for every PHI node in BB and that new PHI
+ // node becomes an incoming value for BB's phi node. However, if the Preds
+ // list is empty, we need to insert dummy entries into the PHI nodes in BB to
+ // account for the newly created predecessor.
+ if (NumPreds == 0) {
+ // Insert dummy values as the incoming value.
+ for (BasicBlock::iterator I = BB->begin(); isa<PHINode>(I); ++I)
+ cast<PHINode>(I)->addIncoming(UndefValue::get(I->getType()), NewBB);
+ return NewBB;
+ }
+
+ // Update DominatorTree, LoopInfo, and LCCSA analysis information.
+ bool HasLoopExit = false;
+ UpdateAnalysisInformation(BB, NewBB, ArrayRef<BasicBlock*>(Preds, NumPreds),
+ P, HasLoopExit);
+
+ // Update the PHI nodes in BB with the values coming from NewBB.
+ UpdatePHINodes(BB, NewBB, ArrayRef<BasicBlock*>(Preds, NumPreds), BI,
+ P, HasLoopExit);
return NewBB;
}
+/// 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 llvm::SplitLandingPadPredecessors(BasicBlock *OrigBB,
+ ArrayRef<BasicBlock*> Preds,
+ const char *Suffix1, const char *Suffix2,
+ Pass *P,
+ SmallVectorImpl<BasicBlock*> &NewBBs) {
+ assert(OrigBB->isLandingPad() && "Trying to split a non-landing pad!");
+
+ // Create a new basic block for OrigBB's predecessors listed in Preds. Insert
+ // it right before the original block.
+ BasicBlock *NewBB1 = BasicBlock::Create(OrigBB->getContext(),
+ OrigBB->getName() + Suffix1,
+ OrigBB->getParent(), OrigBB);
+ NewBBs.push_back(NewBB1);
+
+ // The new block unconditionally branches to the old block.
+ BranchInst *BI1 = BranchInst::Create(OrigBB, NewBB1);
+
+ // Move the edges from Preds to point to NewBB1 instead of OrigBB.
+ for (unsigned i = 0, e = Preds.size(); i != e; ++i) {
+ // This is slightly more strict than necessary; the minimum requirement
+ // is that there be no more than one indirectbr branching to BB. And
+ // all BlockAddress uses would need to be updated.
+ assert(!isa<IndirectBrInst>(Preds[i]->getTerminator()) &&
+ "Cannot split an edge from an IndirectBrInst");
+ Preds[i]->getTerminator()->replaceUsesOfWith(OrigBB, NewBB1);
+ }
+
+ // Update DominatorTree, LoopInfo, and LCCSA analysis information.
+ bool HasLoopExit = false;
+ UpdateAnalysisInformation(OrigBB, NewBB1, Preds, P, HasLoopExit);
+
+ // Update the PHI nodes in OrigBB with the values coming from NewBB1.
+ UpdatePHINodes(OrigBB, NewBB1, Preds, BI1, P, HasLoopExit);
+
+ // Move the remaining edges from OrigBB to point to NewBB2.
+ SmallVector<BasicBlock*, 8> NewBB2Preds;
+ for (pred_iterator i = pred_begin(OrigBB), e = pred_end(OrigBB);
+ i != e; ) {
+ BasicBlock *Pred = *i++;
+ if (Pred == NewBB1) continue;
+ assert(!isa<IndirectBrInst>(Pred->getTerminator()) &&
+ "Cannot split an edge from an IndirectBrInst");
+ NewBB2Preds.push_back(Pred);
+ e = pred_end(OrigBB);
+ }
+
+ BasicBlock *NewBB2 = 0;
+ if (!NewBB2Preds.empty()) {
+ // Create another basic block for the rest of OrigBB's predecessors.
+ NewBB2 = BasicBlock::Create(OrigBB->getContext(),
+ OrigBB->getName() + Suffix2,
+ OrigBB->getParent(), OrigBB);
+ NewBBs.push_back(NewBB2);
+
+ // The new block unconditionally branches to the old block.
+ BranchInst *BI2 = BranchInst::Create(OrigBB, NewBB2);
+
+ // Move the remaining edges from OrigBB to point to NewBB2.
+ for (SmallVectorImpl<BasicBlock*>::iterator
+ i = NewBB2Preds.begin(), e = NewBB2Preds.end(); i != e; ++i)
+ (*i)->getTerminator()->replaceUsesOfWith(OrigBB, NewBB2);
+
+ // Update DominatorTree, LoopInfo, and LCCSA analysis information.
+ HasLoopExit = false;
+ UpdateAnalysisInformation(OrigBB, NewBB2, NewBB2Preds, P, HasLoopExit);
+
+ // Update the PHI nodes in OrigBB with the values coming from NewBB2.
+ UpdatePHINodes(OrigBB, NewBB2, NewBB2Preds, BI2, P, HasLoopExit);
+ }
+
+ LandingPadInst *LPad = OrigBB->getLandingPadInst();
+ Instruction *Clone1 = LPad->clone();
+ Clone1->setName(Twine("lpad") + Suffix1);
+ NewBB1->getInstList().insert(NewBB1->getFirstInsertionPt(), Clone1);
+
+ if (NewBB2) {
+ Instruction *Clone2 = LPad->clone();
+ Clone2->setName(Twine("lpad") + Suffix2);
+ NewBB2->getInstList().insert(NewBB2->getFirstInsertionPt(), Clone2);
+
+ // Create a PHI node for the two cloned landingpad instructions.
+ PHINode *PN = PHINode::Create(LPad->getType(), 2, "lpad.phi", LPad);
+ PN->addIncoming(Clone1, NewBB1);
+ PN->addIncoming(Clone2, NewBB2);
+ LPad->replaceAllUsesWith(PN);
+ LPad->eraseFromParent();
+ } else {
+ // There is no second clone. Just replace the landing pad with the first
+ // clone.
+ LPad->replaceAllUsesWith(Clone1);
+ LPad->eraseFromParent();
+ }
+}
+
/// FindFunctionBackedges - Analyze the specified function to find all of the
/// loop backedges in the function and return them. This is a relatively cheap
/// (compared to computing dominators and loop info) analysis.
diff --git a/lib/Transforms/Utils/BreakCriticalEdges.cpp b/lib/Transforms/Utils/BreakCriticalEdges.cpp
index 92ce500..c052910 100644
--- a/lib/Transforms/Utils/BreakCriticalEdges.cpp
+++ b/lib/Transforms/Utils/BreakCriticalEdges.cpp
@@ -102,7 +102,7 @@ bool llvm::isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
++I; // Skip one edge due to the incoming arc from TI.
if (!AllowIdenticalEdges)
return I != E;
-
+
// If AllowIdenticalEdges is true, then we allow this edge to be considered
// non-critical iff all preds come from TI's block.
while (I != E) {
@@ -155,10 +155,10 @@ static void CreatePHIsForSplitLoopExit(SmallVectorImpl<BasicBlock *> &Preds,
/// This returns the new block if the edge was split, null otherwise.
///
/// If MergeIdenticalEdges is true (not the default), *all* edges from TI to the
-/// specified successor will be merged into the same critical edge block.
-/// This is most commonly interesting with switch instructions, which may
+/// 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
@@ -167,15 +167,20 @@ static void CreatePHIsForSplitLoopExit(SmallVectorImpl<BasicBlock *> &Preds,
/// to.
///
BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
- Pass *P, bool MergeIdenticalEdges) {
+ Pass *P, bool MergeIdenticalEdges,
+ bool DontDeleteUselessPhis) {
if (!isCriticalEdge(TI, SuccNum, MergeIdenticalEdges)) return 0;
-
+
assert(!isa<IndirectBrInst>(TI) &&
"Cannot split critical edge from IndirectBrInst");
-
+
BasicBlock *TIBB = TI->getParent();
BasicBlock *DestBB = TI->getSuccessor(SuccNum);
+ // Splitting the critical edge to a landing pad block is non-trivial. Don't do
+ // it in this generic function.
+ if (DestBB->isLandingPad()) return 0;
+
// Create a new basic block, linking it into the CFG.
BasicBlock *NewBB = BasicBlock::Create(TI->getContext(),
TIBB->getName() + "." + DestBB->getName() + "_crit_edge");
@@ -190,7 +195,7 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
Function &F = *TIBB->getParent();
Function::iterator FBBI = TIBB;
F.getBasicBlockList().insert(++FBBI, NewBB);
-
+
// If there are any PHI nodes in DestBB, we need to update them so that they
// merge incoming values from NewBB instead of from TIBB.
{
@@ -207,35 +212,35 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
// happens because the BB list of PHI nodes are usually in the same
// order.
if (PN->getIncomingBlock(BBIdx) != TIBB)
- BBIdx = PN->getBasicBlockIndex(TIBB);
+ BBIdx = PN->getBasicBlockIndex(TIBB);
PN->setIncomingBlock(BBIdx, NewBB);
}
}
-
+
// If there are any other edges from TIBB to DestBB, update those to go
// through the split block, making those edges non-critical as well (and
// reducing the number of phi entries in the DestBB if relevant).
if (MergeIdenticalEdges) {
for (unsigned i = SuccNum+1, e = TI->getNumSuccessors(); i != e; ++i) {
if (TI->getSuccessor(i) != DestBB) continue;
-
+
// Remove an entry for TIBB from DestBB phi nodes.
- DestBB->removePredecessor(TIBB);
-
+ DestBB->removePredecessor(TIBB, DontDeleteUselessPhis);
+
// We found another edge to DestBB, go to NewBB instead.
TI->setSuccessor(i, NewBB);
}
}
-
-
+
+
// If we don't have a pass object, we can't update anything...
if (P == 0) return NewBB;
-
+
DominatorTree *DT = P->getAnalysisIfAvailable<DominatorTree>();
LoopInfo *LI = P->getAnalysisIfAvailable<LoopInfo>();
ProfileInfo *PI = P->getAnalysisIfAvailable<ProfileInfo>();
-
+
// If we have nothing to update, just return.
if (DT == 0 && LI == 0 && PI == 0)
return NewBB;
@@ -263,7 +268,7 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
}
bool NewBBDominatesDestBB = true;
-
+
// Should we update DominatorTree information?
if (DT) {
DomTreeNode *TINode = DT->getNode(TIBB);
@@ -274,7 +279,7 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
if (TINode) { // Don't break unreachable code!
DomTreeNode *NewBBNode = DT->addNewBlock(NewBB, TIBB);
DomTreeNode *DestBBNode = 0;
-
+
// If NewBBDominatesDestBB hasn't been computed yet, do so with DT.
if (!OtherPreds.empty()) {
DestBBNode = DT->getNode(DestBB);
@@ -285,7 +290,7 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
}
OtherPreds.clear();
}
-
+
// If NewBBDominatesDestBB, then NewBB dominates DestBB, otherwise it
// doesn't dominate anything.
if (NewBBDominatesDestBB) {
@@ -337,6 +342,8 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
}
// For each unique exit block...
+ // FIXME: This code is functionally equivalent to the corresponding
+ // loop in LoopSimplify.
SmallVector<BasicBlock *, 4> ExitBlocks;
TIL->getExitBlocks(ExitBlocks);
for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {
@@ -348,10 +355,15 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
for (pred_iterator I = pred_begin(Exit), E = pred_end(Exit);
I != E; ++I) {
BasicBlock *P = *I;
- if (TIL->contains(P))
+ if (TIL->contains(P)) {
+ if (isa<IndirectBrInst>(P->getTerminator())) {
+ Preds.clear();
+ break;
+ }
Preds.push_back(P);
- else
+ } else {
HasPredOutsideOfLoop = true;
+ }
}
// If there are any preds not in the loop, we'll need to split
// the edges. The Preds.empty() check is needed because a block
diff --git a/lib/Transforms/Utils/BuildLibCalls.cpp b/lib/Transforms/Utils/BuildLibCalls.cpp
index 14bb17f..4b5f45b 100644
--- a/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -58,8 +58,8 @@ Value *llvm::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B,
AttributeWithIndex AWI =
AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind);
- const Type *I8Ptr = B.getInt8PtrTy();
- const Type *I32Ty = B.getInt32Ty();
+ Type *I8Ptr = B.getInt8PtrTy();
+ Type *I32Ty = B.getInt32Ty();
Constant *StrChr = M->getOrInsertFunction("strchr", AttrListPtr::get(&AWI, 1),
I8Ptr, I8Ptr, I32Ty, NULL);
CallInst *CI = B.CreateCall2(StrChr, CastToCStr(Ptr, B),
@@ -102,7 +102,7 @@ Value *llvm::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B,
AttributeWithIndex AWI[2];
AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
- const Type *I8Ptr = B.getInt8PtrTy();
+ Type *I8Ptr = B.getInt8PtrTy();
Value *StrCpy = M->getOrInsertFunction(Name, AttrListPtr::get(AWI, 2),
I8Ptr, I8Ptr, I8Ptr, NULL);
CallInst *CI = B.CreateCall2(StrCpy, CastToCStr(Dst, B), CastToCStr(Src, B),
@@ -120,7 +120,7 @@ Value *llvm::EmitStrNCpy(Value *Dst, Value *Src, Value *Len,
AttributeWithIndex AWI[2];
AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
- const Type *I8Ptr = B.getInt8PtrTy();
+ Type *I8Ptr = B.getInt8PtrTy();
Value *StrNCpy = M->getOrInsertFunction(Name, AttrListPtr::get(AWI, 2),
I8Ptr, I8Ptr, I8Ptr,
Len->getType(), NULL);
@@ -361,7 +361,7 @@ bool SimplifyFortifiedLibCalls::fold(CallInst *CI, const TargetData *TD) {
this->CI = CI;
Function *Callee = CI->getCalledFunction();
StringRef Name = Callee->getName();
- const FunctionType *FT = Callee->getFunctionType();
+ FunctionType *FT = Callee->getFunctionType();
LLVMContext &Context = CI->getParent()->getContext();
IRBuilder<> B(CI);
diff --git a/lib/Transforms/Utils/CMakeLists.txt b/lib/Transforms/Utils/CMakeLists.txt
index 204c2c6..7adc5f1 100644
--- a/lib/Transforms/Utils/CMakeLists.txt
+++ b/lib/Transforms/Utils/CMakeLists.txt
@@ -21,9 +21,17 @@ add_llvm_library(LLVMTransformUtils
PromoteMemoryToRegister.cpp
SSAUpdater.cpp
SimplifyCFG.cpp
+ SimplifyIndVar.cpp
SimplifyInstructions.cpp
UnifyFunctionExitNodes.cpp
Utils.cpp
ValueMapper.cpp
)
+add_llvm_library_dependencies(LLVMTransformUtils
+ LLVMAnalysis
+ LLVMCore
+ LLVMSupport
+ LLVMTarget
+ LLVMipa
+ )
diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp
index 6ea831f..cf21f1e 100644
--- a/lib/Transforms/Utils/CloneFunction.cpp
+++ b/lib/Transforms/Utils/CloneFunction.cpp
@@ -331,15 +331,10 @@ ConstantFoldMappedInstruction(const Instruction *I) {
TD);
if (const LoadInst *LI = dyn_cast<LoadInst>(I))
- if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ops[0]))
- if (!LI->isVolatile() && CE->getOpcode() == Instruction::GetElementPtr)
- if (GlobalVariable *GV = dyn_cast<GlobalVariable>(CE->getOperand(0)))
- if (GV->isConstant() && GV->hasDefinitiveInitializer())
- return ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(),
- CE);
-
- return ConstantFoldInstOperands(I->getOpcode(), I->getType(), &Ops[0],
- Ops.size(), TD);
+ if (!LI->isVolatile())
+ return ConstantFoldLoadFromConstPtr(Ops[0], TD);
+
+ return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops, TD);
}
/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto,
diff --git a/lib/Transforms/Utils/CloneModule.cpp b/lib/Transforms/Utils/CloneModule.cpp
index a08fa35..a0e027b 100644
--- a/lib/Transforms/Utils/CloneModule.cpp
+++ b/lib/Transforms/Utils/CloneModule.cpp
@@ -50,10 +50,12 @@ Module *llvm::CloneModule(const Module *M, ValueToValueMapTy &VMap) {
I != E; ++I) {
GlobalVariable *GV = new GlobalVariable(*New,
I->getType()->getElementType(),
- false,
- GlobalValue::ExternalLinkage, 0,
- I->getName());
- GV->setAlignment(I->getAlignment());
+ I->isConstant(), I->getLinkage(),
+ (Constant*) 0, I->getName(),
+ (GlobalVariable*) 0,
+ I->isThreadLocal(),
+ I->getType()->getAddressSpace());
+ GV->copyAttributesFrom(I);
VMap[I] = GV;
}
@@ -61,16 +63,19 @@ Module *llvm::CloneModule(const Module *M, ValueToValueMapTy &VMap) {
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) {
Function *NF =
Function::Create(cast<FunctionType>(I->getType()->getElementType()),
- GlobalValue::ExternalLinkage, I->getName(), New);
+ I->getLinkage(), I->getName(), New);
NF->copyAttributesFrom(I);
VMap[I] = NF;
}
// Loop over the aliases in the module
for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end();
- I != E; ++I)
- VMap[I] = new GlobalAlias(I->getType(), GlobalAlias::ExternalLinkage,
- I->getName(), NULL, New);
+ I != E; ++I) {
+ GlobalAlias *GA = new GlobalAlias(I->getType(), I->getLinkage(),
+ I->getName(), NULL, New);
+ GA->copyAttributesFrom(I);
+ VMap[I] = GA;
+ }
// Now that all of the things that global variable initializer can refer to
// have been created, loop through and copy the global variable referrers
@@ -81,9 +86,6 @@ Module *llvm::CloneModule(const Module *M, ValueToValueMapTy &VMap) {
GlobalVariable *GV = cast<GlobalVariable>(VMap[I]);
if (I->hasInitializer())
GV->setInitializer(MapValue(I->getInitializer(), VMap));
- GV->setLinkage(I->getLinkage());
- GV->setThreadLocal(I->isThreadLocal());
- GV->setConstant(I->isConstant());
}
// Similarly, copy over function bodies now...
@@ -101,15 +103,12 @@ Module *llvm::CloneModule(const Module *M, ValueToValueMapTy &VMap) {
SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned.
CloneFunctionInto(F, I, VMap, /*ModuleLevelChanges=*/true, Returns);
}
-
- F->setLinkage(I->getLinkage());
}
// And aliases
for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end();
I != E; ++I) {
GlobalAlias *GA = cast<GlobalAlias>(VMap[I]);
- GA->setLinkage(I->getLinkage());
if (const Constant *C = I->getAliasee())
GA->setAliasee(MapValue(C, VMap));
}
diff --git a/lib/Transforms/Utils/CodeExtractor.cpp b/lib/Transforms/Utils/CodeExtractor.cpp
index 0813523..5f47ebb 100644
--- a/lib/Transforms/Utils/CodeExtractor.cpp
+++ b/lib/Transforms/Utils/CodeExtractor.cpp
@@ -50,14 +50,14 @@ namespace {
DominatorTree* DT;
bool AggregateArgs;
unsigned NumExitBlocks;
- const Type *RetTy;
+ Type *RetTy;
public:
CodeExtractor(DominatorTree* dt = 0, bool AggArgs = false)
: DT(dt), AggregateArgs(AggArgs||AggregateArgsOpt), NumExitBlocks(~0U) {}
- Function *ExtractCodeRegion(const std::vector<BasicBlock*> &code);
+ Function *ExtractCodeRegion(ArrayRef<BasicBlock*> code);
- bool isEligible(const std::vector<BasicBlock*> &code);
+ bool isEligible(ArrayRef<BasicBlock*> code);
private:
/// definedInRegion - Return true if the specified value is defined in the
@@ -290,7 +290,7 @@ Function *CodeExtractor::constructFunction(const Values &inputs,
paramTy.clear();
paramTy.push_back(StructPtr);
}
- const FunctionType *funcType =
+ FunctionType *funcType =
FunctionType::get(RetTy, paramTy, false);
// Create the new function
@@ -317,8 +317,7 @@ Function *CodeExtractor::constructFunction(const Values &inputs,
Idx[1] = ConstantInt::get(Type::getInt32Ty(header->getContext()), i);
TerminatorInst *TI = newFunction->begin()->getTerminator();
GetElementPtrInst *GEP =
- GetElementPtrInst::Create(AI, Idx, Idx+2,
- "gep_" + inputs[i]->getName(), TI);
+ GetElementPtrInst::Create(AI, Idx, "gep_" + inputs[i]->getName(), TI);
RewriteVal = new LoadInst(GEP, "loadgep_" + inputs[i]->getName(), TI);
} else
RewriteVal = AI++;
@@ -420,7 +419,7 @@ emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer,
Idx[0] = Constant::getNullValue(Type::getInt32Ty(Context));
Idx[1] = ConstantInt::get(Type::getInt32Ty(Context), i);
GetElementPtrInst *GEP =
- GetElementPtrInst::Create(Struct, Idx, Idx + 2,
+ GetElementPtrInst::Create(Struct, Idx,
"gep_" + StructValues[i]->getName());
codeReplacer->getInstList().push_back(GEP);
StoreInst *SI = new StoreInst(StructValues[i], GEP);
@@ -446,7 +445,7 @@ emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer,
Idx[0] = Constant::getNullValue(Type::getInt32Ty(Context));
Idx[1] = ConstantInt::get(Type::getInt32Ty(Context), FirstOut + i);
GetElementPtrInst *GEP
- = GetElementPtrInst::Create(Struct, Idx, Idx + 2,
+ = GetElementPtrInst::Create(Struct, Idx,
"gep_reload_" + outputs[i]->getName());
codeReplacer->getInstList().push_back(GEP);
Output = GEP;
@@ -561,7 +560,7 @@ emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer,
Idx[1] = ConstantInt::get(Type::getInt32Ty(Context),
FirstOut+out);
GetElementPtrInst *GEP =
- GetElementPtrInst::Create(OAI, Idx, Idx + 2,
+ GetElementPtrInst::Create(OAI, Idx,
"gep_" + outputs[out]->getName(),
NTRet);
new StoreInst(outputs[out], GEP, NTRet);
@@ -580,7 +579,7 @@ emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer,
}
// Now that we've done the deed, simplify the switch instruction.
- const Type *OldFnRetTy = TheSwitch->getParent()->getParent()->getReturnType();
+ Type *OldFnRetTy = TheSwitch->getParent()->getParent()->getReturnType();
switch (NumExitBlocks) {
case 0:
// There are no successors (the block containing the switch itself), which
@@ -655,7 +654,7 @@ void CodeExtractor::moveCodeToFunction(Function *newFunction) {
/// computed result back into memory.
///
Function *CodeExtractor::
-ExtractCodeRegion(const std::vector<BasicBlock*> &code) {
+ExtractCodeRegion(ArrayRef<BasicBlock*> code) {
if (!isEligible(code))
return 0;
@@ -755,9 +754,13 @@ ExtractCodeRegion(const std::vector<BasicBlock*> &code) {
return newFunction;
}
-bool CodeExtractor::isEligible(const std::vector<BasicBlock*> &code) {
+bool CodeExtractor::isEligible(ArrayRef<BasicBlock*> code) {
+ // Deny a single basic block that's a landing pad block.
+ if (code.size() == 1 && code[0]->isLandingPad())
+ return false;
+
// Deny code region if it contains allocas or vastarts.
- for (std::vector<BasicBlock*>::const_iterator BB = code.begin(), e=code.end();
+ for (ArrayRef<BasicBlock*>::iterator BB = code.begin(), e=code.end();
BB != e; ++BB)
for (BasicBlock::const_iterator I = (*BB)->begin(), Ie = (*BB)->end();
I != Ie; ++I)
@@ -771,25 +774,23 @@ bool CodeExtractor::isEligible(const std::vector<BasicBlock*> &code) {
}
-/// ExtractCodeRegion - slurp a sequence of basic blocks into a brand new
-/// function
+/// ExtractCodeRegion - Slurp a sequence of basic blocks into a brand new
+/// function.
///
Function* llvm::ExtractCodeRegion(DominatorTree &DT,
- const std::vector<BasicBlock*> &code,
+ ArrayRef<BasicBlock*> code,
bool AggregateArgs) {
return CodeExtractor(&DT, AggregateArgs).ExtractCodeRegion(code);
}
-/// ExtractBasicBlock - slurp a natural loop into a brand new function
+/// ExtractLoop - Slurp a natural loop into a brand new function.
///
Function* llvm::ExtractLoop(DominatorTree &DT, Loop *L, bool AggregateArgs) {
return CodeExtractor(&DT, AggregateArgs).ExtractCodeRegion(L->getBlocks());
}
-/// ExtractBasicBlock - slurp a basic block into a brand new function
+/// ExtractBasicBlock - Slurp a basic block into a brand new function.
///
-Function* llvm::ExtractBasicBlock(BasicBlock *BB, bool AggregateArgs) {
- std::vector<BasicBlock*> Blocks;
- Blocks.push_back(BB);
- return CodeExtractor(0, AggregateArgs).ExtractCodeRegion(Blocks);
+Function* llvm::ExtractBasicBlock(ArrayRef<BasicBlock*> BBs, bool AggregateArgs){
+ return CodeExtractor(0, AggregateArgs).ExtractCodeRegion(BBs);
}
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index d5b382e..5464dbc 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -45,6 +45,9 @@ bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI) {
return InlineFunction(CallSite(II), IFI);
}
+// FIXME: New EH - Remove the functions marked [LIBUNWIND] when new EH is
+// turned on.
+
/// [LIBUNWIND] Look for an llvm.eh.exception call in the given block.
static EHExceptionInst *findExceptionInBlock(BasicBlock *bb) {
for (BasicBlock::iterator i = bb->begin(), e = bb->end(); i != e; i++) {
@@ -250,20 +253,32 @@ namespace {
PHINode *InnerSelectorPHI;
SmallVector<Value*, 8> UnwindDestPHIValues;
+ // FIXME: New EH - These will replace the analogous ones above.
+ BasicBlock *OuterResumeDest; //< Destination of the invoke's unwind.
+ BasicBlock *InnerResumeDest; //< Destination for the callee's resume.
+ LandingPadInst *CallerLPad; //< LandingPadInst associated with the invoke.
+ PHINode *InnerEHValuesPHI; //< PHI for EH values from landingpad insts.
+
public:
- InvokeInliningInfo(InvokeInst *II) :
- OuterUnwindDest(II->getUnwindDest()), OuterSelector(0),
- InnerUnwindDest(0), InnerExceptionPHI(0), InnerSelectorPHI(0) {
-
- // If there are PHI nodes in the unwind destination block, we
- // need to keep track of which values came into them from the
- // invoke before removing the edge from this block.
- llvm::BasicBlock *invokeBB = II->getParent();
- for (BasicBlock::iterator I = OuterUnwindDest->begin();
- isa<PHINode>(I); ++I) {
+ InvokeInliningInfo(InvokeInst *II)
+ : OuterUnwindDest(II->getUnwindDest()), OuterSelector(0),
+ InnerUnwindDest(0), InnerExceptionPHI(0), InnerSelectorPHI(0),
+ OuterResumeDest(II->getUnwindDest()), InnerResumeDest(0),
+ CallerLPad(0), InnerEHValuesPHI(0) {
+ // If there are PHI nodes in the unwind destination block, we need to keep
+ // track of which values came into them from the invoke before removing
+ // the edge from this block.
+ llvm::BasicBlock *InvokeBB = II->getParent();
+ BasicBlock::iterator I = OuterUnwindDest->begin();
+ for (; isa<PHINode>(I); ++I) {
// Save the value to use for this edge.
- PHINode *phi = cast<PHINode>(I);
- UnwindDestPHIValues.push_back(phi->getIncomingValueForBlock(invokeBB));
+ PHINode *PHI = cast<PHINode>(I);
+ UnwindDestPHIValues.push_back(PHI->getIncomingValueForBlock(InvokeBB));
+ }
+
+ // FIXME: With the new EH, this if/dyn_cast should be a 'cast'.
+ if (LandingPadInst *LPI = dyn_cast<LandingPadInst>(I)) {
+ CallerLPad = LPI;
}
}
@@ -281,11 +296,23 @@ namespace {
BasicBlock *getInnerUnwindDest();
+ // FIXME: New EH - Rename when new EH is turned on.
+ BasicBlock *getInnerUnwindDestNewEH();
+
+ LandingPadInst *getLandingPadInst() const { return CallerLPad; }
+
bool forwardEHResume(CallInst *call, BasicBlock *src);
- /// Add incoming-PHI values to the unwind destination block for
- /// the given basic block, using the values for the original
- /// invoke's source block.
+ /// forwardResume - Forward the 'resume' instruction to the caller's landing
+ /// pad block. When the landing pad block has only one predecessor, this is
+ /// a simple branch. When there is more than one predecessor, we need to
+ /// split the landing pad block after the landingpad instruction and jump
+ /// to there.
+ void forwardResume(ResumeInst *RI);
+
+ /// addIncomingPHIValuesFor - Add incoming-PHI values to the unwind
+ /// destination block for the given basic block, using the values for the
+ /// original invoke's source block.
void addIncomingPHIValuesFor(BasicBlock *BB) const {
addIncomingPHIValuesForInto(BB, OuterUnwindDest);
}
@@ -300,7 +327,7 @@ namespace {
};
}
-/// Get or create a target for the branch out of rewritten calls to
+/// [LIBUNWIND] Get or create a target for the branch out of rewritten calls to
/// llvm.eh.resume.
BasicBlock *InvokeInliningInfo::getInnerUnwindDest() {
if (InnerUnwindDest) return InnerUnwindDest;
@@ -404,6 +431,60 @@ bool InvokeInliningInfo::forwardEHResume(CallInst *call, BasicBlock *src) {
return true;
}
+/// Get or create a target for the branch from ResumeInsts.
+BasicBlock *InvokeInliningInfo::getInnerUnwindDestNewEH() {
+ // FIXME: New EH - rename this function when new EH is turned on.
+ if (InnerResumeDest) return InnerResumeDest;
+
+ // Split the landing pad.
+ BasicBlock::iterator SplitPoint = CallerLPad; ++SplitPoint;
+ InnerResumeDest =
+ OuterResumeDest->splitBasicBlock(SplitPoint,
+ OuterResumeDest->getName() + ".body");
+
+ // The number of incoming edges we expect to the inner landing pad.
+ const unsigned PHICapacity = 2;
+
+ // Create corresponding new PHIs for all the PHIs in the outer landing pad.
+ BasicBlock::iterator InsertPoint = InnerResumeDest->begin();
+ BasicBlock::iterator I = OuterResumeDest->begin();
+ for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
+ PHINode *OuterPHI = cast<PHINode>(I);
+ PHINode *InnerPHI = PHINode::Create(OuterPHI->getType(), PHICapacity,
+ OuterPHI->getName() + ".lpad-body",
+ InsertPoint);
+ OuterPHI->replaceAllUsesWith(InnerPHI);
+ InnerPHI->addIncoming(OuterPHI, OuterResumeDest);
+ }
+
+ // Create a PHI for the exception values.
+ InnerEHValuesPHI = PHINode::Create(CallerLPad->getType(), PHICapacity,
+ "eh.lpad-body", InsertPoint);
+ CallerLPad->replaceAllUsesWith(InnerEHValuesPHI);
+ InnerEHValuesPHI->addIncoming(CallerLPad, OuterResumeDest);
+
+ // All done.
+ return InnerResumeDest;
+}
+
+/// forwardResume - Forward the 'resume' instruction to the caller's landing pad
+/// block. When the landing pad block has only one predecessor, this is a simple
+/// branch. When there is more than one predecessor, we need to split the
+/// landing pad block after the landingpad instruction and jump to there.
+void InvokeInliningInfo::forwardResume(ResumeInst *RI) {
+ BasicBlock *Dest = getInnerUnwindDestNewEH();
+ BasicBlock *Src = RI->getParent();
+
+ BranchInst::Create(Dest, Src);
+
+ // Update the PHIs in the destination. They were inserted in an order which
+ // makes this work.
+ addIncomingPHIValuesForInto(Src, Dest);
+
+ InnerEHValuesPHI->addIncoming(RI->getOperand(0), Src);
+ RI->eraseFromParent();
+}
+
/// [LIBUNWIND] Check whether this selector is "only cleanups":
/// call i32 @llvm.eh.selector(blah, blah, i32 0)
static bool isCleanupOnlySelector(EHSelectorInst *selector) {
@@ -421,9 +502,19 @@ static bool isCleanupOnlySelector(EHSelectorInst *selector) {
/// Returns true to indicate that the next block should be skipped.
static bool HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
InvokeInliningInfo &Invoke) {
+ LandingPadInst *LPI = Invoke.getLandingPadInst();
+
for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) {
Instruction *I = BBI++;
-
+
+ if (LPI) // FIXME: New EH - This won't be NULL in the new EH.
+ if (LandingPadInst *L = dyn_cast<LandingPadInst>(I)) {
+ unsigned NumClauses = LPI->getNumClauses();
+ L->reserveClauses(NumClauses);
+ for (unsigned i = 0; i != NumClauses; ++i)
+ L->addClause(LPI->getClause(i));
+ }
+
// We only need to check for function calls: inlined invoke
// instructions require no special handling.
CallInst *CI = dyn_cast<CallInst>(I);
@@ -557,6 +648,10 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
// there is now a new entry in them.
Invoke.addIncomingPHIValuesFor(BB);
}
+
+ if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator())) {
+ Invoke.forwardResume(RI);
+ }
}
// Now that everything is happy, we have one final detail. The PHI nodes in
@@ -636,7 +731,7 @@ static Value *HandleByValArgument(Value *Arg, Instruction *TheCall,
const Function *CalledFunc,
InlineFunctionInfo &IFI,
unsigned ByValAlignment) {
- const Type *AggTy = cast<PointerType>(Arg->getType())->getElementType();
+ Type *AggTy = cast<PointerType>(Arg->getType())->getElementType();
// If the called function is readonly, then it could not mutate the caller's
// copy of the byval'd memory. In this case, it is safe to elide the copy and
@@ -726,7 +821,7 @@ static bool isUsedByLifetimeMarker(Value *V) {
// hasLifetimeMarkers - Check whether the given alloca already has
// lifetime.start or lifetime.end intrinsics.
static bool hasLifetimeMarkers(AllocaInst *AI) {
- const Type *Int8PtrTy = Type::getInt8PtrTy(AI->getType()->getContext());
+ Type *Int8PtrTy = Type::getInt8PtrTy(AI->getType()->getContext());
if (AI->getType() == Int8PtrTy)
return isUsedByLifetimeMarker(AI);
@@ -770,8 +865,15 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI,
for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();
BI != BE; ++BI) {
DebugLoc DL = BI->getDebugLoc();
- if (!DL.isUnknown())
+ if (!DL.isUnknown()) {
BI->setDebugLoc(updateInlinedAtInfo(DL, TheCallDL, BI->getContext()));
+ if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) {
+ LLVMContext &Ctx = BI->getContext();
+ MDNode *InlinedAt = BI->getDebugLoc().getInlinedAt(Ctx);
+ DVI->setOperand(2, createInlinedVariable(DVI->getVariable(),
+ InlinedAt, Ctx));
+ }
+ }
}
}
}
@@ -822,6 +924,40 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI) {
return false;
}
+ // Find the personality function used by the landing pads of the caller. If it
+ // exists, then check to see that it matches the personality function used in
+ // the callee.
+ for (Function::const_iterator
+ I = Caller->begin(), E = Caller->end(); I != E; ++I)
+ if (const InvokeInst *II = dyn_cast<InvokeInst>(I->getTerminator())) {
+ const BasicBlock *BB = II->getUnwindDest();
+ // FIXME: This 'isa' here should become go away once the new EH system is
+ // in place.
+ if (!isa<LandingPadInst>(BB->getFirstNonPHI()))
+ continue;
+ const LandingPadInst *LP = cast<LandingPadInst>(BB->getFirstNonPHI());
+ const Value *CallerPersFn = LP->getPersonalityFn();
+
+ // If the personality functions match, then we can perform the
+ // inlining. Otherwise, we can't inline.
+ // TODO: This isn't 100% true. Some personality functions are proper
+ // supersets of others and can be used in place of the other.
+ for (Function::const_iterator
+ I = CalledFunc->begin(), E = CalledFunc->end(); I != E; ++I)
+ if (const InvokeInst *II = dyn_cast<InvokeInst>(I->getTerminator())) {
+ const BasicBlock *BB = II->getUnwindDest();
+ // FIXME: This 'if/dyn_cast' here should become a normal 'cast' once
+ // the new EH system is in place.
+ if (const LandingPadInst *LP =
+ dyn_cast<LandingPadInst>(BB->getFirstNonPHI()))
+ if (CallerPersFn != LP->getPersonalityFn())
+ return false;
+ break;
+ }
+
+ break;
+ }
+
// Get an iterator to the last basic block in the function, which will have
// the new function inlined after it.
//
@@ -1090,7 +1226,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI) {
// Handle all of the return instructions that we just cloned in, and eliminate
// any users of the original call/invoke instruction.
- const Type *RTy = CalledFunc->getReturnType();
+ Type *RTy = CalledFunc->getReturnType();
PHINode *PHI = 0;
if (Returns.size() > 1) {
diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp
index 0f6d9ae..7034feb 100644
--- a/lib/Transforms/Utils/Local.cpp
+++ b/lib/Transforms/Utils/Local.cpp
@@ -27,7 +27,6 @@
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Analysis/DIBuilder.h"
#include "llvm/Analysis/Dominators.h"
-#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/ProfileInfo.h"
#include "llvm/Analysis/ValueTracking.h"
@@ -227,13 +226,17 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions) {
bool llvm::isInstructionTriviallyDead(Instruction *I) {
if (!I->use_empty() || isa<TerminatorInst>(I)) return false;
+ // We don't want the landingpad instruction removed by anything this general.
+ if (isa<LandingPadInst>(I))
+ return false;
+
// We don't want debug info removed by anything this general, unless
// debug info is empty.
if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) {
- if (DDI->getAddress())
+ if (DDI->getAddress())
return false;
return true;
- }
+ }
if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {
if (DVI->getValue())
return false;
@@ -244,10 +247,16 @@ bool llvm::isInstructionTriviallyDead(Instruction *I) {
// Special case intrinsics that "may have side effects" but can be deleted
// when dead.
- if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
// Safe to delete llvm.stacksave if dead.
if (II->getIntrinsicID() == Intrinsic::stacksave)
return true;
+
+ // Lifetime intrinsics are dead when their right-hand is undef.
+ if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
+ II->getIntrinsicID() == Intrinsic::lifetime_end)
+ return isa<UndefValue>(II->getArgOperand(1));
+ }
return false;
}
@@ -712,10 +721,14 @@ bool llvm::EliminateDuplicatePHINodes(BasicBlock *BB) {
/// their preferred alignment from the beginning.
///
static unsigned enforceKnownAlignment(Value *V, unsigned Align,
- unsigned PrefAlign) {
+ unsigned PrefAlign, const TargetData *TD) {
V = V->stripPointerCasts();
if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
+ // If the preferred alignment is greater than the natural stack alignment
+ // then don't round up. This avoids dynamic stack realignment.
+ if (TD && TD->exceedsNaturalStackAlignment(PrefAlign))
+ return Align;
// If there is a requested alignment and if this is an alloca, round up.
if (AI->getAlignment() >= PrefAlign)
return AI->getAlignment();
@@ -766,7 +779,7 @@ unsigned llvm::getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign,
Align = std::min(Align, +Value::MaximumAlignment);
if (PrefAlign > Align)
- Align = enforceKnownAlignment(V, Align, PrefAlign);
+ Align = enforceKnownAlignment(V, Align, PrefAlign, TD);
// We don't need to make any adjustment.
return Align;
diff --git a/lib/Transforms/Utils/LoopSimplify.cpp b/lib/Transforms/Utils/LoopSimplify.cpp
index e79fb5a..cbd54a8 100644
--- a/lib/Transforms/Utils/LoopSimplify.cpp
+++ b/lib/Transforms/Utils/LoopSimplify.cpp
@@ -213,7 +213,7 @@ ReprocessLoop:
// predecessors from outside of the loop, split the edge now.
SmallVector<BasicBlock*, 8> ExitBlocks;
L->getExitBlocks(ExitBlocks);
-
+
SmallSetVector<BasicBlock *, 8> ExitBlockSet(ExitBlocks.begin(),
ExitBlocks.end());
for (SmallSetVector<BasicBlock *, 8>::iterator I = ExitBlockSet.begin(),
@@ -325,6 +325,14 @@ ReprocessLoop:
DEBUG(dbgs() << "LoopSimplify: Eliminating exiting block "
<< ExitingBlock->getName() << "\n");
+ // If any reachable control flow within this loop has changed, notify
+ // ScalarEvolution. Currently assume the parent loop doesn't change
+ // (spliting edges doesn't count). If blocks, CFG edges, or other values
+ // in the parent loop change, then we need call to forgetLoop() for the
+ // parent instead.
+ if (SE)
+ SE->forgetLoop(L);
+
assert(pred_begin(ExitingBlock) == pred_end(ExitingBlock));
Changed = true;
LI->removeBlock(ExitingBlock);
@@ -402,13 +410,24 @@ BasicBlock *LoopSimplify::RewriteLoopExitBlock(Loop *L, BasicBlock *Exit) {
}
assert(!LoopBlocks.empty() && "No edges coming in from outside the loop?");
- BasicBlock *NewBB = SplitBlockPredecessors(Exit, &LoopBlocks[0],
- LoopBlocks.size(), ".loopexit",
- this);
+ BasicBlock *NewExitBB = 0;
+
+ if (Exit->isLandingPad()) {
+ SmallVector<BasicBlock*, 2> NewBBs;
+ SplitLandingPadPredecessors(Exit, ArrayRef<BasicBlock*>(&LoopBlocks[0],
+ LoopBlocks.size()),
+ ".loopexit", ".nonloopexit",
+ this, NewBBs);
+ NewExitBB = NewBBs[0];
+ } else {
+ NewExitBB = SplitBlockPredecessors(Exit, &LoopBlocks[0],
+ LoopBlocks.size(), ".loopexit",
+ this);
+ }
DEBUG(dbgs() << "LoopSimplify: Creating dedicated exit block "
- << NewBB->getName() << "\n");
- return NewBB;
+ << NewExitBB->getName() << "\n");
+ return NewExitBB;
}
/// AddBlockAndPredsToSet - Add the specified block, and all of its
@@ -467,23 +486,23 @@ void LoopSimplify::PlaceSplitBlockCarefully(BasicBlock *NewBB,
if (&*BBI == SplitPreds[i])
return;
}
-
+
// If it isn't already after an outside block, move it after one. This is
// always good as it makes the uncond branch from the outside block into a
// fall-through.
-
+
// Figure out *which* outside block to put this after. Prefer an outside
// block that neighbors a BB actually in the loop.
BasicBlock *FoundBB = 0;
for (unsigned i = 0, e = SplitPreds.size(); i != e; ++i) {
Function::iterator BBI = SplitPreds[i];
- if (++BBI != NewBB->getParent()->end() &&
+ if (++BBI != NewBB->getParent()->end() &&
L->contains(BBI)) {
FoundBB = SplitPreds[i];
break;
}
}
-
+
// If our heuristic for a *good* bb to place this after doesn't find
// anything, just pick something. It's likely better than leaving it within
// the loop.
@@ -544,7 +563,7 @@ Loop *LoopSimplify::SeparateNestedLoop(Loop *L, LPPassManager &LPM) {
// Make sure that NewBB is put someplace intelligent, which doesn't mess up
// code layout too horribly.
PlaceSplitBlockCarefully(NewBB, OuterLoopPreds, L);
-
+
// Create the new outer loop.
Loop *NewOuter = new Loop();
@@ -735,6 +754,7 @@ void LoopSimplify::verifyAnalysis() const {
}
assert(HasIndBrPred &&
"LoopSimplify has no excuse for missing loop header info!");
+ (void)HasIndBrPred;
}
// Indirectbr can interfere with exit block canonicalization.
@@ -742,12 +762,15 @@ void LoopSimplify::verifyAnalysis() const {
bool HasIndBrExiting = false;
SmallVector<BasicBlock*, 8> ExitingBlocks;
L->getExitingBlocks(ExitingBlocks);
- for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i)
+ for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) {
if (isa<IndirectBrInst>((ExitingBlocks[i])->getTerminator())) {
HasIndBrExiting = true;
break;
}
+ }
+
assert(HasIndBrExiting &&
"LoopSimplify has no excuse for missing exit block info!");
+ (void)HasIndBrExiting;
}
}
diff --git a/lib/Transforms/Utils/LoopUnroll.cpp b/lib/Transforms/Utils/LoopUnroll.cpp
index 6772511..62e4fa2 100644
--- a/lib/Transforms/Utils/LoopUnroll.cpp
+++ b/lib/Transforms/Utils/LoopUnroll.cpp
@@ -11,9 +11,6 @@
// actual pass or policy, but provides a single function to perform loop
// unrolling.
//
-// It works best when loops have been canonicalized by the -indvars pass,
-// allowing it to determine the trip counts of loops easily.
-//
// The process of unrolling can produce extraneous basic blocks linked with
// unconditional branches. This will be corrected in the future.
//
@@ -24,6 +21,7 @@
#include "llvm/BasicBlock.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/Analysis/LoopIterator.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Support/Debug.h"
@@ -31,6 +29,7 @@
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/Transforms/Utils/SimplifyIndVar.h"
using namespace llvm;
// TODO: Should these be here or in LoopUnroll?
@@ -61,7 +60,8 @@ static inline void RemapInstruction(Instruction *I,
/// only has one predecessor, and that predecessor only has one successor.
/// The LoopInfo Analysis that is passed will be kept consistent.
/// Returns the new combined block.
-static BasicBlock *FoldBlockIntoPredecessor(BasicBlock *BB, LoopInfo* LI) {
+static BasicBlock *FoldBlockIntoPredecessor(BasicBlock *BB, LoopInfo* LI,
+ LPPassManager *LPM) {
// Merge basic blocks into their predecessor if there is only one distinct
// pred, and if there is only one distinct successor of the predecessor, and
// if there are no PHI nodes.
@@ -93,6 +93,12 @@ static BasicBlock *FoldBlockIntoPredecessor(BasicBlock *BB, LoopInfo* LI) {
std::string OldName = BB->getName();
// Erase basic block from the function...
+
+ // ScalarEvolution holds references to loop exit blocks.
+ if (ScalarEvolution *SE = LPM->getAnalysisIfAvailable<ScalarEvolution>()) {
+ if (Loop *L = LI->getLoopFor(BB))
+ SE->forgetLoop(L);
+ }
LI->removeBlock(BB);
BB->eraseFromParent();
@@ -109,12 +115,27 @@ static BasicBlock *FoldBlockIntoPredecessor(BasicBlock *BB, LoopInfo* LI) {
/// branch instruction. However, if the trip count (and multiple) are not known,
/// loop unrolling will mostly produce more code that is no faster.
///
+/// TripCount is generally defined as the number of times the loop header
+/// executes. UnrollLoop relaxes the definition to permit early exits: here
+/// TripCount is the iteration on which control exits LatchBlock if no early
+/// exits were taken. Note that UnrollLoop assumes that the loop counter test
+/// terminates LatchBlock in order to remove unnecesssary instances of the
+/// test. In other words, control may exit the loop prior to TripCount
+/// iterations via an early branch, but control may not exit the loop from the
+/// LatchBlock's terminator prior to TripCount iterations.
+///
+/// Similarly, TripMultiple divides the number of times that the LatchBlock may
+/// execute without exiting the loop.
+///
/// The LoopInfo Analysis that is passed will be kept consistent.
///
/// If a LoopPassManager is passed in, and the loop is fully removed, it will be
/// removed from the LoopPassManager as well. LPM can also be NULL.
-bool llvm::UnrollLoop(Loop *L, unsigned Count,
- LoopInfo *LI, LPPassManager *LPM) {
+///
+/// This utility preserves LoopInfo. If DominatorTree or ScalarEvolution are
+/// available it must also preserve those analyses.
+bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount,
+ unsigned TripMultiple, LoopInfo *LI, LPPassManager *LPM) {
BasicBlock *Preheader = L->getLoopPreheader();
if (!Preheader) {
DEBUG(dbgs() << " Can't unroll; loop preheader-insertion failed.\n");
@@ -129,14 +150,14 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count,
BasicBlock *Header = L->getHeader();
BranchInst *BI = dyn_cast<BranchInst>(LatchBlock->getTerminator());
-
+
if (!BI || BI->isUnconditional()) {
// The loop-rotate pass can be helpful to avoid this in many cases.
DEBUG(dbgs() <<
" Can't unroll; loop not terminated by a conditional branch.\n");
return false;
}
-
+
if (Header->hasAddressTaken()) {
// The loop-rotate pass can be helpful to avoid this in many cases.
DEBUG(dbgs() <<
@@ -146,16 +167,10 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count,
// Notify ScalarEvolution that the loop will be substantially changed,
// if not outright eliminated.
- if (ScalarEvolution *SE = LPM->getAnalysisIfAvailable<ScalarEvolution>())
+ ScalarEvolution *SE = LPM->getAnalysisIfAvailable<ScalarEvolution>();
+ if (SE)
SE->forgetLoop(L);
- // Find trip count
- unsigned TripCount = L->getSmallConstantTripCount();
- // Find trip multiple if count is not available
- unsigned TripMultiple = 1;
- if (TripCount == 0)
- TripMultiple = L->getSmallConstantTripMultiple();
-
if (TripCount != 0)
DEBUG(dbgs() << " Trip Count = " << TripCount << "\n");
if (TripMultiple != 1)
@@ -208,12 +223,7 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count,
ValueToValueMapTy LastValueMap;
std::vector<PHINode*> OrigPHINode;
for (BasicBlock::iterator I = Header->begin(); isa<PHINode>(I); ++I) {
- PHINode *PN = cast<PHINode>(I);
- OrigPHINode.push_back(PN);
- if (Instruction *I =
- dyn_cast<Instruction>(PN->getIncomingValueForBlock(LatchBlock)))
- if (L->contains(I))
- LastValueMap[I] = I;
+ OrigPHINode.push_back(cast<PHINode>(I));
}
std::vector<BasicBlock*> Headers;
@@ -221,11 +231,20 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count,
Headers.push_back(Header);
Latches.push_back(LatchBlock);
+ // The current on-the-fly SSA update requires blocks to be processed in
+ // reverse postorder so that LastValueMap contains the correct value at each
+ // exit.
+ LoopBlocksDFS DFS(L);
+ DFS.perform(LI);
+
+ // Stash the DFS iterators before adding blocks to the loop.
+ LoopBlocksDFS::RPOIterator BlockBegin = DFS.beginRPO();
+ LoopBlocksDFS::RPOIterator BlockEnd = DFS.endRPO();
+
for (unsigned It = 1; It != Count; ++It) {
std::vector<BasicBlock*> NewBlocks;
-
- for (std::vector<BasicBlock*>::iterator BB = LoopBlocks.begin(),
- E = LoopBlocks.end(); BB != E; ++BB) {
+
+ for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) {
ValueToValueMapTy VMap;
BasicBlock *New = CloneBasicBlock(*BB, VMap, "." + Twine(It));
Header->getParent()->getBasicBlockList().push_back(New);
@@ -251,75 +270,55 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count,
L->addBasicBlockToLoop(New, LI->getBase());
- // Add phi entries for newly created values to all exit blocks except
- // the successor of the latch block. The successor of the exit block will
- // be updated specially after unrolling all the way.
- if (*BB != LatchBlock)
- for (succ_iterator SI = succ_begin(*BB), SE = succ_end(*BB); SI != SE;
- ++SI)
- if (!L->contains(*SI))
- for (BasicBlock::iterator BBI = (*SI)->begin();
- PHINode *phi = dyn_cast<PHINode>(BBI); ++BBI) {
- Value *Incoming = phi->getIncomingValueForBlock(*BB);
- phi->addIncoming(Incoming, New);
- }
-
+ // Add phi entries for newly created values to all exit blocks.
+ for (succ_iterator SI = succ_begin(*BB), SE = succ_end(*BB);
+ SI != SE; ++SI) {
+ if (L->contains(*SI))
+ continue;
+ for (BasicBlock::iterator BBI = (*SI)->begin();
+ PHINode *phi = dyn_cast<PHINode>(BBI); ++BBI) {
+ Value *Incoming = phi->getIncomingValueForBlock(*BB);
+ ValueToValueMapTy::iterator It = LastValueMap.find(Incoming);
+ if (It != LastValueMap.end())
+ Incoming = It->second;
+ phi->addIncoming(Incoming, New);
+ }
+ }
// Keep track of new headers and latches as we create them, so that
// we can insert the proper branches later.
if (*BB == Header)
Headers.push_back(New);
- if (*BB == LatchBlock) {
+ if (*BB == LatchBlock)
Latches.push_back(New);
- // Also, clear out the new latch's back edge so that it doesn't look
- // like a new loop, so that it's amenable to being merged with adjacent
- // blocks later on.
- TerminatorInst *Term = New->getTerminator();
- assert(L->contains(Term->getSuccessor(!ContinueOnTrue)));
- assert(Term->getSuccessor(ContinueOnTrue) == LoopExit);
- Term->setSuccessor(!ContinueOnTrue, NULL);
- }
-
NewBlocks.push_back(New);
}
-
+
// Remap all instructions in the most recent iteration
for (unsigned i = 0; i < NewBlocks.size(); ++i)
for (BasicBlock::iterator I = NewBlocks[i]->begin(),
E = NewBlocks[i]->end(); I != E; ++I)
::RemapInstruction(I, LastValueMap);
}
-
- // The latch block exits the loop. If there are any PHI nodes in the
- // successor blocks, update them to use the appropriate values computed as the
- // last iteration of the loop.
- if (Count != 1) {
- BasicBlock *LastIterationBB = cast<BasicBlock>(LastValueMap[LatchBlock]);
- for (succ_iterator SI = succ_begin(LatchBlock), SE = succ_end(LatchBlock);
- SI != SE; ++SI) {
- for (BasicBlock::iterator BBI = (*SI)->begin();
- PHINode *PN = dyn_cast<PHINode>(BBI); ++BBI) {
- Value *InVal = PN->removeIncomingValue(LatchBlock, false);
- // If this value was defined in the loop, take the value defined by the
- // last iteration of the loop.
- if (Instruction *InValI = dyn_cast<Instruction>(InVal)) {
- if (L->contains(InValI))
- InVal = LastValueMap[InVal];
- }
- PN->addIncoming(InVal, LastIterationBB);
- }
- }
- }
- // Now, if we're doing complete unrolling, loop over the PHI nodes in the
- // original block, setting them to their incoming values.
- if (CompletelyUnroll) {
- BasicBlock *Preheader = L->getLoopPreheader();
- for (unsigned i = 0, e = OrigPHINode.size(); i != e; ++i) {
- PHINode *PN = OrigPHINode[i];
+ // Loop over the PHI nodes in the original block, setting incoming values.
+ for (unsigned i = 0, e = OrigPHINode.size(); i != e; ++i) {
+ PHINode *PN = OrigPHINode[i];
+ if (CompletelyUnroll) {
PN->replaceAllUsesWith(PN->getIncomingValueForBlock(Preheader));
Header->getInstList().erase(PN);
}
+ else if (Count > 1) {
+ Value *InVal = PN->removeIncomingValue(LatchBlock, false);
+ // If this value was defined in the loop, take the value defined by the
+ // last iteration of the loop.
+ if (Instruction *InValI = dyn_cast<Instruction>(InVal)) {
+ if (L->contains(InValI))
+ InVal = LastValueMap[InVal];
+ }
+ assert(Latches.back() == LastValueMap[LatchBlock] && "bad last latch");
+ PN->addIncoming(InVal, Latches.back());
+ }
}
// Now that all the basic blocks for the unrolled iterations are in place,
@@ -351,6 +350,19 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count,
// iteration.
Term->setSuccessor(!ContinueOnTrue, Dest);
} else {
+ // Remove phi operands at this loop exit
+ if (Dest != LoopExit) {
+ BasicBlock *BB = Latches[i];
+ for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB);
+ SI != SE; ++SI) {
+ if (*SI == Headers[i])
+ continue;
+ for (BasicBlock::iterator BBI = (*SI)->begin();
+ PHINode *Phi = dyn_cast<PHINode>(BBI); ++BBI) {
+ Phi->removeIncomingValue(BB, false);
+ }
+ }
+ }
// Replace the conditional branch with an unconditional one.
BranchInst::Create(Dest, Term);
Term->eraseFromParent();
@@ -362,11 +374,29 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count,
BranchInst *Term = cast<BranchInst>(Latches[i]->getTerminator());
if (Term->isUnconditional()) {
BasicBlock *Dest = Term->getSuccessor(0);
- if (BasicBlock *Fold = FoldBlockIntoPredecessor(Dest, LI))
+ if (BasicBlock *Fold = FoldBlockIntoPredecessor(Dest, LI, LPM))
std::replace(Latches.begin(), Latches.end(), Dest, Fold);
}
}
-
+
+ // FIXME: Reconstruct dom info, because it is not preserved properly.
+ // Incrementally updating domtree after loop unrolling would be easy.
+ if (DominatorTree *DT = LPM->getAnalysisIfAvailable<DominatorTree>())
+ DT->runOnFunction(*L->getHeader()->getParent());
+
+ // Simplify any new induction variables in the partially unrolled loop.
+ if (SE && !CompletelyUnroll) {
+ SmallVector<WeakVH, 16> DeadInsts;
+ simplifyLoopIVs(L, SE, LPM, DeadInsts);
+
+ // Aggressively clean up dead instructions that simplifyLoopIVs already
+ // identified. Any remaining should be cleaned up below.
+ while (!DeadInsts.empty())
+ if (Instruction *Inst =
+ dyn_cast_or_null<Instruction>(&*DeadInsts.pop_back_val()))
+ RecursivelyDeleteTriviallyDeadInstructions(Inst);
+ }
+
// At this point, the code is well formed. We now do a quick sweep over the
// inserted code, doing constant propagation and dead code elimination as we
// go.
diff --git a/lib/Transforms/Utils/LowerExpectIntrinsic.cpp b/lib/Transforms/Utils/LowerExpectIntrinsic.cpp
index c1213fa..61ab3f6 100644
--- a/lib/Transforms/Utils/LowerExpectIntrinsic.cpp
+++ b/lib/Transforms/Utils/LowerExpectIntrinsic.cpp
@@ -58,7 +58,7 @@ bool LowerExpectIntrinsic::HandleSwitchExpect(SwitchInst *SI) {
return false;
LLVMContext &Context = CI->getContext();
- const Type *Int32Ty = Type::getInt32Ty(Context);
+ Type *Int32Ty = Type::getInt32Ty(Context);
unsigned caseNo = SI->findCaseValue(ExpectedValue);
std::vector<Value *> Vec;
@@ -105,7 +105,7 @@ bool LowerExpectIntrinsic::HandleIfExpect(BranchInst *BI) {
return false;
LLVMContext &Context = CI->getContext();
- const Type *Int32Ty = Type::getInt32Ty(Context);
+ Type *Int32Ty = Type::getInt32Ty(Context);
bool Likely = ExpectedValue->isOne();
// If expect value is equal to 1 it means that we are more likely to take
diff --git a/lib/Transforms/Utils/LowerInvoke.cpp b/lib/Transforms/Utils/LowerInvoke.cpp
index f77d19d..c96c8fc 100644
--- a/lib/Transforms/Utils/LowerInvoke.cpp
+++ b/lib/Transforms/Utils/LowerInvoke.cpp
@@ -120,18 +120,18 @@ FunctionPass *llvm::createLowerInvokePass(const TargetLowering *TLI,
// doInitialization - Make sure that there is a prototype for abort in the
// current module.
bool LowerInvoke::doInitialization(Module &M) {
- const Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext());
+ Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext());
if (useExpensiveEHSupport) {
// Insert a type for the linked list of jump buffers.
unsigned JBSize = TLI ? TLI->getJumpBufSize() : 0;
JBSize = JBSize ? JBSize : 200;
Type *JmpBufTy = ArrayType::get(VoidPtrTy, JBSize);
- JBLinkTy = StructType::createNamed(M.getContext(), "llvm.sjljeh.jmpbufty");
+ JBLinkTy = StructType::create(M.getContext(), "llvm.sjljeh.jmpbufty");
Type *Elts[] = { JmpBufTy, PointerType::getUnqual(JBLinkTy) };
JBLinkTy->setBody(Elts);
- const Type *PtrJBList = PointerType::getUnqual(JBLinkTy);
+ Type *PtrJBList = PointerType::getUnqual(JBLinkTy);
// Now that we've done that, insert the jmpbuf list head global, unless it
// already exists.
@@ -240,14 +240,14 @@ void LowerInvoke::rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo,
CallInst* StackSaveRet = CallInst::Create(StackSaveFn, "ssret", II);
new StoreInst(StackSaveRet, StackPtr, true, II); // volatile
- BasicBlock::iterator NI = II->getNormalDest()->getFirstNonPHI();
+ BasicBlock::iterator NI = II->getNormalDest()->getFirstInsertionPt();
// nonvolatile.
new StoreInst(Constant::getNullValue(Type::getInt32Ty(II->getContext())),
InvokeNum, false, NI);
- Instruction* StackPtrLoad = new LoadInst(StackPtr, "stackptr.restore", true,
- II->getUnwindDest()->getFirstNonPHI()
- );
+ Instruction* StackPtrLoad =
+ new LoadInst(StackPtr, "stackptr.restore", true,
+ II->getUnwindDest()->getFirstInsertionPt());
CallInst::Create(StackRestoreFn, StackPtrLoad, "")->insertAfter(StackPtrLoad);
// Add a switch case to our unwind block.
@@ -305,7 +305,7 @@ splitLiveRangesLiveAcrossInvokes(SmallVectorImpl<InvokeInst*> &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.
@@ -406,6 +406,7 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
SmallVector<ReturnInst*,16> Returns;
SmallVector<UnwindInst*,16> Unwinds;
SmallVector<InvokeInst*,16> Invokes;
+ UnreachableInst* UnreachablePlaceholder = 0;
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
@@ -455,8 +456,7 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
Value *Idx[] = { Constant::getNullValue(Type::getInt32Ty(F.getContext())),
ConstantInt::get(Type::getInt32Ty(F.getContext()), 1) };
- OldJmpBufPtr = GetElementPtrInst::Create(JmpBuf, &Idx[0], &Idx[2],
- "OldBuf",
+ OldJmpBufPtr = GetElementPtrInst::Create(JmpBuf, Idx, "OldBuf",
EntryBB->getTerminator());
// Copy the JBListHead to the alloca.
@@ -487,9 +487,10 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
// Insert a load in the Catch block, and a switch on its value. By default,
// we go to a block that just does an unwind (which is the correct action
- // for a standard call).
+ // for a standard call). We insert an unreachable instruction here and
+ // modify the block to jump to the correct unwinding pad later.
BasicBlock *UnwindBB = BasicBlock::Create(F.getContext(), "unwindbb", &F);
- Unwinds.push_back(new UnwindInst(F.getContext(), UnwindBB));
+ UnreachablePlaceholder = new UnreachableInst(F.getContext(), UnwindBB);
Value *CatchLoad = new LoadInst(InvokeNum, "invoke.num", true, CatchBB);
SwitchInst *CatchSwitch =
@@ -502,8 +503,7 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
"setjmp.cont");
Idx[1] = ConstantInt::get(Type::getInt32Ty(F.getContext()), 0);
- Value *JmpBufPtr = GetElementPtrInst::Create(JmpBuf, &Idx[0], &Idx[2],
- "TheJmpBuf",
+ Value *JmpBufPtr = GetElementPtrInst::Create(JmpBuf, Idx, "TheJmpBuf",
EntryBB->getTerminator());
JmpBufPtr = new BitCastInst(JmpBufPtr,
Type::getInt8PtrTy(F.getContext()),
@@ -557,8 +557,7 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
// Get a pointer to the jmpbuf and longjmp.
Value *Idx[] = { Constant::getNullValue(Type::getInt32Ty(F.getContext())),
ConstantInt::get(Type::getInt32Ty(F.getContext()), 0) };
- Idx[0] = GetElementPtrInst::Create(BufPtr, &Idx[0], &Idx[2], "JmpBuf",
- UnwindBlock);
+ Idx[0] = GetElementPtrInst::Create(BufPtr, Idx, "JmpBuf", UnwindBlock);
Idx[0] = new BitCastInst(Idx[0],
Type::getInt8PtrTy(F.getContext()),
"tmp", UnwindBlock);
@@ -580,6 +579,12 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
Unwinds[i]->eraseFromParent();
}
+ // Replace the inserted unreachable with a branch to the unwind handler.
+ if (UnreachablePlaceholder) {
+ BranchInst::Create(UnwindHandler, UnreachablePlaceholder);
+ UnreachablePlaceholder->eraseFromParent();
+ }
+
// Finally, for any returns from this function, if this function contains an
// invoke, restore the old jmpbuf pointer to its input value.
if (OldJmpBufPtr) {
diff --git a/lib/Transforms/Utils/LowerSwitch.cpp b/lib/Transforms/Utils/LowerSwitch.cpp
index ed733d3..686178c 100644
--- a/lib/Transforms/Utils/LowerSwitch.cpp
+++ b/lib/Transforms/Utils/LowerSwitch.cpp
@@ -277,11 +277,11 @@ void LowerSwitch::processSwitchInst(SwitchInst *SI) {
BasicBlock *CurBlock = SI->getParent();
BasicBlock *OrigBlock = CurBlock;
Function *F = CurBlock->getParent();
- Value *Val = SI->getOperand(0); // The value we are switching on...
+ Value *Val = SI->getCondition(); // The value we are switching on...
BasicBlock* Default = SI->getDefaultDest();
// If there is only the default destination, don't bother with the code below.
- if (SI->getNumOperands() == 2) {
+ if (SI->getNumCases() == 1) {
BranchInst::Create(SI->getDefaultDest(), CurBlock);
CurBlock->getInstList().erase(SI);
return;
diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
index e5a00f4..db3e942 100644
--- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
+++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
@@ -86,11 +86,15 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) {
UI != UE; ++UI) { // Loop over all of the uses of the alloca
const User *U = *UI;
if (const LoadInst *LI = dyn_cast<LoadInst>(U)) {
+ // Note that atomic loads can be transformed; atomic semantics do
+ // not have any meaning for a local alloca.
if (LI->isVolatile())
return false;
} else if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
if (SI->getOperand(0) == AI)
return false; // Don't allow a store OF the AI, only INTO the AI.
+ // Note that atomic stores can be transformed; atomic semantics do
+ // not have any meaning for a local alloca.
if (SI->isVolatile())
return false;
} else if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
diff --git a/lib/Transforms/Utils/SSAUpdater.cpp b/lib/Transforms/Utils/SSAUpdater.cpp
index b47a7cc..fa8061c 100644
--- a/lib/Transforms/Utils/SSAUpdater.cpp
+++ b/lib/Transforms/Utils/SSAUpdater.cpp
@@ -16,6 +16,7 @@
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Allocator.h"
@@ -43,7 +44,7 @@ SSAUpdater::~SSAUpdater() {
/// 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 SSAUpdater::Initialize(const Type *Ty, StringRef Name) {
+void SSAUpdater::Initialize(Type *Ty, StringRef Name) {
if (AV == 0)
AV = new AvailableValsTy();
else
@@ -378,8 +379,7 @@ run(const SmallVectorImpl<Instruction*> &Insts) const {
// First step: bucket up uses of the alloca by the block they occur in.
// This is important because we have to handle multiple defs/uses in a block
// ourselves: SSAUpdater is purely for cross-block references.
- // FIXME: Want a TinyVector<Instruction*> since there is often 0/1 element.
- DenseMap<BasicBlock*, std::vector<Instruction*> > UsesByBlock;
+ DenseMap<BasicBlock*, TinyPtrVector<Instruction*> > UsesByBlock;
for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
Instruction *User = Insts[i];
@@ -395,7 +395,7 @@ run(const SmallVectorImpl<Instruction*> &Insts) const {
for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
Instruction *User = Insts[i];
BasicBlock *BB = User->getParent();
- std::vector<Instruction*> &BlockUses = UsesByBlock[BB];
+ TinyPtrVector<Instruction*> &BlockUses = UsesByBlock[BB];
// If this block has already been processed, ignore this repeat use.
if (BlockUses.empty()) continue;
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp
index 9d9c324..b8c3ab4 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -63,6 +63,7 @@ class SimplifyCFGOpt {
bool FoldValueComparisonIntoPredecessors(TerminatorInst *TI,
IRBuilder<> &Builder);
+ bool SimplifyResume(ResumeInst *RI, IRBuilder<> &Builder);
bool SimplifyReturn(ReturnInst *RI, IRBuilder<> &Builder);
bool SimplifyUnwind(UnwindInst *UI, IRBuilder<> &Builder);
bool SimplifyUnreachable(UnreachableInst *UI);
@@ -322,7 +323,7 @@ static ConstantInt *GetConstantInt(Value *V, const TargetData *TD) {
// This is some kind of pointer constant. Turn it into a pointer-sized
// ConstantInt if possible.
- const IntegerType *PtrTy = TD->getIntPtrType(V->getContext());
+ IntegerType *PtrTy = TD->getIntPtrType(V->getContext());
// Null pointer means 0, see SelectionDAGBuilder::getValue(const Value*).
if (isa<ConstantPointerNull>(V))
@@ -2138,6 +2139,52 @@ static bool SimplifyBranchOnICmpChain(BranchInst *BI, const TargetData *TD,
return true;
}
+bool SimplifyCFGOpt::SimplifyResume(ResumeInst *RI, IRBuilder<> &Builder) {
+ // If this is a trivial landing pad that just continues unwinding the caught
+ // exception then zap the landing pad, turning its invokes into calls.
+ BasicBlock *BB = RI->getParent();
+ LandingPadInst *LPInst = dyn_cast<LandingPadInst>(BB->getFirstNonPHI());
+ if (RI->getValue() != LPInst)
+ // Not a landing pad, or the resume is not unwinding the exception that
+ // caused control to branch here.
+ return false;
+
+ // Check that there are no other instructions except for debug intrinsics.
+ BasicBlock::iterator I = LPInst, E = RI;
+ while (++I != E)
+ if (!isa<DbgInfoIntrinsic>(I))
+ return false;
+
+ // Turn all invokes that unwind here into calls and delete the basic block.
+ for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE;) {
+ InvokeInst *II = cast<InvokeInst>((*PI++)->getTerminator());
+ SmallVector<Value*, 8> Args(II->op_begin(), II->op_end() - 3);
+ // Insert a call instruction before the invoke.
+ CallInst *Call = CallInst::Create(II->getCalledValue(), Args, "", II);
+ Call->takeName(II);
+ Call->setCallingConv(II->getCallingConv());
+ Call->setAttributes(II->getAttributes());
+ Call->setDebugLoc(II->getDebugLoc());
+
+ // Anything that used the value produced by the invoke instruction now uses
+ // the value produced by the call instruction. Note that we do this even
+ // for void functions and calls with no uses so that the callgraph edge is
+ // updated.
+ II->replaceAllUsesWith(Call);
+ BB->removePredecessor(II->getParent());
+
+ // Insert a branch to the normal destination right before the invoke.
+ BranchInst::Create(II->getNormalDest(), II);
+
+ // Finally, delete the invoke instruction!
+ II->eraseFromParent();
+ }
+
+ // The landingpad is now unreachable. Zap it.
+ BB->eraseFromParent();
+ return true;
+}
+
bool SimplifyCFGOpt::SimplifyReturn(ReturnInst *RI, IRBuilder<> &Builder) {
BasicBlock *BB = RI->getParent();
if (!BB->getFirstNonPHIOrDbg()->isTerminator()) return false;
@@ -2244,18 +2291,34 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) {
while (UI != BB->begin()) {
BasicBlock::iterator BBI = UI;
--BBI;
- // Do not delete instructions that can have side effects, like calls
- // (which may never return) and volatile loads and stores.
+ // Do not delete instructions that can have side effects which might cause
+ // the unreachable to not be reachable; specifically, calls and volatile
+ // operations may have this effect.
if (isa<CallInst>(BBI) && !isa<DbgInfoIntrinsic>(BBI)) break;
-
- if (StoreInst *SI = dyn_cast<StoreInst>(BBI))
- if (SI->isVolatile())
- break;
-
- if (LoadInst *LI = dyn_cast<LoadInst>(BBI))
- if (LI->isVolatile())
+
+ if (BBI->mayHaveSideEffects()) {
+ if (StoreInst *SI = dyn_cast<StoreInst>(BBI)) {
+ if (SI->isVolatile())
+ break;
+ } else if (LoadInst *LI = dyn_cast<LoadInst>(BBI)) {
+ if (LI->isVolatile())
+ break;
+ } else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(BBI)) {
+ if (RMWI->isVolatile())
+ break;
+ } else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(BBI)) {
+ if (CXI->isVolatile())
+ break;
+ } else if (!isa<FenceInst>(BBI) && !isa<VAArgInst>(BBI) &&
+ !isa<LandingPadInst>(BBI)) {
break;
-
+ }
+ // Note that deleting LandingPad's here is in fact okay, although it
+ // involves a bit of subtle reasoning. If this inst is a LandingPad,
+ // all the predecessors of this block will be the unwind edges of Invokes,
+ // and we can therefore guarantee this block will be erased.
+ }
+
// Delete this instruction (any uses are guaranteed to be dead)
if (!BBI->use_empty())
BBI->replaceAllUsesWith(UndefValue::get(BBI->getType()));
@@ -2707,6 +2770,71 @@ bool SimplifyCFGOpt::SimplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
return false;
}
+/// Check if passing a value to an instruction will cause undefined behavior.
+static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I) {
+ Constant *C = dyn_cast<Constant>(V);
+ if (!C)
+ return false;
+
+ if (!I->hasOneUse()) // Only look at single-use instructions, for compile time
+ return false;
+
+ if (C->isNullValue()) {
+ Instruction *Use = I->use_back();
+
+ // Now make sure that there are no instructions in between that can alter
+ // control flow (eg. calls)
+ for (BasicBlock::iterator i = ++BasicBlock::iterator(I); &*i != Use; ++i)
+ if (i == I->getParent()->end() || i->mayHaveSideEffects())
+ return false;
+
+ // Look through GEPs. A load from a GEP derived from NULL is still undefined
+ if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Use))
+ if (GEP->getPointerOperand() == I)
+ return passingValueIsAlwaysUndefined(V, GEP);
+
+ // Look through bitcasts.
+ if (BitCastInst *BC = dyn_cast<BitCastInst>(Use))
+ return passingValueIsAlwaysUndefined(V, BC);
+
+ // Load from null is undefined.
+ if (LoadInst *LI = dyn_cast<LoadInst>(Use))
+ return LI->getPointerAddressSpace() == 0;
+
+ // Store to null is undefined.
+ if (StoreInst *SI = dyn_cast<StoreInst>(Use))
+ return SI->getPointerAddressSpace() == 0 && SI->getPointerOperand() == I;
+ }
+ return false;
+}
+
+/// If BB has an incoming value that will always trigger undefined behavior
+/// (eg. null pointer derefence), remove the branch leading here.
+static bool removeUndefIntroducingPredecessor(BasicBlock *BB) {
+ for (BasicBlock::iterator i = BB->begin();
+ PHINode *PHI = dyn_cast<PHINode>(i); ++i)
+ for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i)
+ if (passingValueIsAlwaysUndefined(PHI->getIncomingValue(i), PHI)) {
+ TerminatorInst *T = PHI->getIncomingBlock(i)->getTerminator();
+ IRBuilder<> Builder(T);
+ if (BranchInst *BI = dyn_cast<BranchInst>(T)) {
+ BB->removePredecessor(PHI->getIncomingBlock(i));
+ // Turn uncoditional branches into unreachables and remove the dead
+ // destination from conditional branches.
+ if (BI->isUnconditional())
+ Builder.CreateUnreachable();
+ else
+ Builder.CreateBr(BI->getSuccessor(0) == BB ? BI->getSuccessor(1) :
+ BI->getSuccessor(0));
+ BI->eraseFromParent();
+ return true;
+ }
+ // TODO: SwitchInst.
+ }
+
+ return false;
+}
+
bool SimplifyCFGOpt::run(BasicBlock *BB) {
bool Changed = false;
@@ -2730,6 +2858,9 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) {
// Check for and eliminate duplicate PHI nodes in this block.
Changed |= EliminateDuplicatePHINodes(BB);
+ // Check for and remove branches that will always cause undefined behavior.
+ Changed |= removeUndefIntroducingPredecessor(BB);
+
// Merge basic blocks into their predecessor if there is only one distinct
// pred, and if there is only one distinct successor of the predecessor, and
// if there are no PHI nodes.
@@ -2752,6 +2883,8 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) {
} else {
if (SimplifyCondBranch(BI, Builder)) return true;
}
+ } else if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator())) {
+ if (SimplifyResume(RI, Builder)) return true;
} else if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
if (SimplifyReturn(RI, Builder)) return true;
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) {
diff --git a/lib/Transforms/Utils/SimplifyIndVar.cpp b/lib/Transforms/Utils/SimplifyIndVar.cpp
new file mode 100644
index 0000000..76289c0
--- /dev/null
+++ b/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -0,0 +1,432 @@
+//===-- SimplifyIndVar.cpp - Induction variable simplification ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements 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.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "indvars"
+
+#include "llvm/Instructions.h"
+#include "llvm/Analysis/Dominators.h"
+#include "llvm/Analysis/IVUsers.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils/SimplifyIndVar.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+
+using namespace llvm;
+
+STATISTIC(NumElimIdentity, "Number of IV identities eliminated");
+STATISTIC(NumElimOperand, "Number of IV operands folded into a use");
+STATISTIC(NumElimRem , "Number of IV remainder operations eliminated");
+STATISTIC(NumElimCmp , "Number of IV comparisons eliminated");
+
+namespace {
+ /// SimplifyIndvar - This is a utility for simplifying induction variables
+ /// based on ScalarEvolution. It is the primary instrument of the
+ /// IndvarSimplify pass, but it may also be directly invoked to cleanup after
+ /// other loop passes that preserve SCEV.
+ class SimplifyIndvar {
+ Loop *L;
+ LoopInfo *LI;
+ DominatorTree *DT;
+ ScalarEvolution *SE;
+ IVUsers *IU; // NULL for DisableIVRewrite
+ const TargetData *TD; // May be NULL
+
+ SmallVectorImpl<WeakVH> &DeadInsts;
+
+ bool Changed;
+
+ public:
+ SimplifyIndvar(Loop *Loop, ScalarEvolution *SE, LPPassManager *LPM,
+ SmallVectorImpl<WeakVH> &Dead, IVUsers *IVU = NULL) :
+ L(Loop),
+ LI(LPM->getAnalysisIfAvailable<LoopInfo>()),
+ SE(SE),
+ IU(IVU),
+ TD(LPM->getAnalysisIfAvailable<TargetData>()),
+ DeadInsts(Dead),
+ Changed(false) {
+ assert(LI && "IV simplification requires LoopInfo");
+ }
+
+ bool hasChanged() const { return Changed; }
+
+ /// Iteratively perform simplification on a worklist of users of the
+ /// specified induction variable. This is the top-level driver that applies
+ /// all simplicitions to users of an IV.
+ void simplifyUsers(PHINode *CurrIV, IVVisitor *V = NULL);
+
+ Value *foldIVUser(Instruction *UseInst, Instruction *IVOperand);
+
+ bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
+ void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
+ void eliminateIVRemainder(BinaryOperator *Rem, Value *IVOperand,
+ bool IsSigned);
+ };
+}
+
+/// foldIVUser - Fold an IV operand into its use. This removes increments of an
+/// aligned IV when used by a instruction that ignores the low bits.
+///
+/// IVOperand is guaranteed SCEVable, but UseInst may not be.
+///
+/// Return the operand of IVOperand for this induction variable if IVOperand can
+/// be folded (in case more folding opportunities have been exposed).
+/// Otherwise return null.
+Value *SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
+ Value *IVSrc = 0;
+ unsigned OperIdx = 0;
+ const SCEV *FoldedExpr = 0;
+ switch (UseInst->getOpcode()) {
+ default:
+ return 0;
+ case Instruction::UDiv:
+ case Instruction::LShr:
+ // We're only interested in the case where we know something about
+ // the numerator and have a constant denominator.
+ if (IVOperand != UseInst->getOperand(OperIdx) ||
+ !isa<ConstantInt>(UseInst->getOperand(1)))
+ return 0;
+
+ // Attempt to fold a binary operator with constant operand.
+ // e.g. ((I + 1) >> 2) => I >> 2
+ if (IVOperand->getNumOperands() != 2 ||
+ !isa<ConstantInt>(IVOperand->getOperand(1)))
+ return 0;
+
+ IVSrc = IVOperand->getOperand(0);
+ // IVSrc must be the (SCEVable) IV, since the other operand is const.
+ assert(SE->isSCEVable(IVSrc->getType()) && "Expect SCEVable IV operand");
+
+ ConstantInt *D = cast<ConstantInt>(UseInst->getOperand(1));
+ if (UseInst->getOpcode() == Instruction::LShr) {
+ // Get a constant for the divisor. See createSCEV.
+ uint32_t BitWidth = cast<IntegerType>(UseInst->getType())->getBitWidth();
+ if (D->getValue().uge(BitWidth))
+ return 0;
+
+ D = ConstantInt::get(UseInst->getContext(),
+ APInt(BitWidth, 1).shl(D->getZExtValue()));
+ }
+ FoldedExpr = SE->getUDivExpr(SE->getSCEV(IVSrc), SE->getSCEV(D));
+ }
+ // We have something that might fold it's operand. Compare SCEVs.
+ if (!SE->isSCEVable(UseInst->getType()))
+ return 0;
+
+ // Bypass the operand if SCEV can prove it has no effect.
+ if (SE->getSCEV(UseInst) != FoldedExpr)
+ return 0;
+
+ DEBUG(dbgs() << "INDVARS: Eliminated IV operand: " << *IVOperand
+ << " -> " << *UseInst << '\n');
+
+ UseInst->setOperand(OperIdx, IVSrc);
+ assert(SE->getSCEV(UseInst) == FoldedExpr && "bad SCEV with folded oper");
+
+ ++NumElimOperand;
+ Changed = true;
+ if (IVOperand->use_empty())
+ DeadInsts.push_back(IVOperand);
+ return IVSrc;
+}
+
+/// eliminateIVComparison - SimplifyIVUsers helper for eliminating useless
+/// comparisons against an induction variable.
+void SimplifyIndvar::eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) {
+ unsigned IVOperIdx = 0;
+ ICmpInst::Predicate Pred = ICmp->getPredicate();
+ if (IVOperand != ICmp->getOperand(0)) {
+ // Swapped
+ assert(IVOperand == ICmp->getOperand(1) && "Can't find IVOperand");
+ IVOperIdx = 1;
+ Pred = ICmpInst::getSwappedPredicate(Pred);
+ }
+
+ // Get the SCEVs for the ICmp operands.
+ const SCEV *S = SE->getSCEV(ICmp->getOperand(IVOperIdx));
+ const SCEV *X = SE->getSCEV(ICmp->getOperand(1 - IVOperIdx));
+
+ // Simplify unnecessary loops away.
+ const Loop *ICmpLoop = LI->getLoopFor(ICmp->getParent());
+ S = SE->getSCEVAtScope(S, ICmpLoop);
+ X = SE->getSCEVAtScope(X, ICmpLoop);
+
+ // If the condition is always true or always false, replace it with
+ // a constant value.
+ if (SE->isKnownPredicate(Pred, S, X))
+ ICmp->replaceAllUsesWith(ConstantInt::getTrue(ICmp->getContext()));
+ else if (SE->isKnownPredicate(ICmpInst::getInversePredicate(Pred), S, X))
+ ICmp->replaceAllUsesWith(ConstantInt::getFalse(ICmp->getContext()));
+ else
+ return;
+
+ DEBUG(dbgs() << "INDVARS: Eliminated comparison: " << *ICmp << '\n');
+ ++NumElimCmp;
+ Changed = true;
+ DeadInsts.push_back(ICmp);
+}
+
+/// eliminateIVRemainder - SimplifyIVUsers helper for eliminating useless
+/// remainder operations operating on an induction variable.
+void SimplifyIndvar::eliminateIVRemainder(BinaryOperator *Rem,
+ Value *IVOperand,
+ bool IsSigned) {
+ // We're only interested in the case where we know something about
+ // the numerator.
+ if (IVOperand != Rem->getOperand(0))
+ return;
+
+ // Get the SCEVs for the ICmp operands.
+ const SCEV *S = SE->getSCEV(Rem->getOperand(0));
+ const SCEV *X = SE->getSCEV(Rem->getOperand(1));
+
+ // Simplify unnecessary loops away.
+ const Loop *ICmpLoop = LI->getLoopFor(Rem->getParent());
+ S = SE->getSCEVAtScope(S, ICmpLoop);
+ X = SE->getSCEVAtScope(X, ICmpLoop);
+
+ // i % n --> i if i is in [0,n).
+ if ((!IsSigned || SE->isKnownNonNegative(S)) &&
+ SE->isKnownPredicate(IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
+ S, X))
+ Rem->replaceAllUsesWith(Rem->getOperand(0));
+ else {
+ // (i+1) % n --> (i+1)==n?0:(i+1) if i is in [0,n).
+ const SCEV *LessOne =
+ SE->getMinusSCEV(S, SE->getConstant(S->getType(), 1));
+ if (IsSigned && !SE->isKnownNonNegative(LessOne))
+ return;
+
+ if (!SE->isKnownPredicate(IsSigned ?
+ ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
+ LessOne, X))
+ return;
+
+ ICmpInst *ICmp = new ICmpInst(Rem, ICmpInst::ICMP_EQ,
+ Rem->getOperand(0), Rem->getOperand(1));
+ SelectInst *Sel =
+ SelectInst::Create(ICmp,
+ ConstantInt::get(Rem->getType(), 0),
+ Rem->getOperand(0), "tmp", Rem);
+ Rem->replaceAllUsesWith(Sel);
+ }
+
+ // Inform IVUsers about the new users.
+ if (IU) {
+ if (Instruction *I = dyn_cast<Instruction>(Rem->getOperand(0)))
+ IU->AddUsersIfInteresting(I);
+ }
+ DEBUG(dbgs() << "INDVARS: Simplified rem: " << *Rem << '\n');
+ ++NumElimRem;
+ Changed = true;
+ DeadInsts.push_back(Rem);
+}
+
+/// eliminateIVUser - Eliminate an operation that consumes a simple IV and has
+/// no observable side-effect given the range of IV values.
+/// IVOperand is guaranteed SCEVable, but UseInst may not be.
+bool SimplifyIndvar::eliminateIVUser(Instruction *UseInst,
+ Instruction *IVOperand) {
+ if (ICmpInst *ICmp = dyn_cast<ICmpInst>(UseInst)) {
+ eliminateIVComparison(ICmp, IVOperand);
+ return true;
+ }
+ if (BinaryOperator *Rem = dyn_cast<BinaryOperator>(UseInst)) {
+ bool IsSigned = Rem->getOpcode() == Instruction::SRem;
+ if (IsSigned || Rem->getOpcode() == Instruction::URem) {
+ eliminateIVRemainder(Rem, IVOperand, IsSigned);
+ return true;
+ }
+ }
+
+ // Eliminate any operation that SCEV can prove is an identity function.
+ if (!SE->isSCEVable(UseInst->getType()) ||
+ (UseInst->getType() != IVOperand->getType()) ||
+ (SE->getSCEV(UseInst) != SE->getSCEV(IVOperand)))
+ return false;
+
+ DEBUG(dbgs() << "INDVARS: Eliminated identity: " << *UseInst << '\n');
+
+ UseInst->replaceAllUsesWith(IVOperand);
+ ++NumElimIdentity;
+ Changed = true;
+ DeadInsts.push_back(UseInst);
+ return true;
+}
+
+/// pushIVUsers - Add all uses of Def to the current IV's worklist.
+///
+static void pushIVUsers(
+ Instruction *Def,
+ SmallPtrSet<Instruction*,16> &Simplified,
+ SmallVectorImpl< std::pair<Instruction*,Instruction*> > &SimpleIVUsers) {
+
+ for (Value::use_iterator UI = Def->use_begin(), E = Def->use_end();
+ UI != E; ++UI) {
+ Instruction *User = cast<Instruction>(*UI);
+
+ // Avoid infinite or exponential worklist processing.
+ // Also ensure unique worklist users.
+ // If Def is a LoopPhi, it may not be in the Simplified set, so check for
+ // self edges first.
+ if (User != Def && Simplified.insert(User))
+ SimpleIVUsers.push_back(std::make_pair(User, Def));
+ }
+}
+
+/// isSimpleIVUser - Return true if this instruction generates a simple SCEV
+/// expression in terms of that IV.
+///
+/// This is similar to IVUsers' isInteresting() but processes each instruction
+/// non-recursively when the operand is already known to be a simpleIVUser.
+///
+static bool isSimpleIVUser(Instruction *I, const Loop *L, ScalarEvolution *SE) {
+ if (!SE->isSCEVable(I->getType()))
+ return false;
+
+ // Get the symbolic expression for this instruction.
+ const SCEV *S = SE->getSCEV(I);
+
+ // Only consider affine recurrences.
+ const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S);
+ if (AR && AR->getLoop() == L)
+ return true;
+
+ return false;
+}
+
+/// simplifyUsers - Iteratively perform simplification on a worklist of users
+/// of the specified induction variable. Each successive simplification may push
+/// more users which may themselves be candidates for simplification.
+///
+/// This algorithm does not require IVUsers analysis. Instead, it simplifies
+/// instructions in-place during analysis. Rather than rewriting induction
+/// variables bottom-up from their users, it transforms a chain of IVUsers
+/// top-down, updating the IR only when it encouters a clear optimization
+/// opportunitiy.
+///
+/// Once DisableIVRewrite is default, LSR will be the only client of IVUsers.
+///
+void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
+ if (!SE->isSCEVable(CurrIV->getType()))
+ return;
+
+ // Instructions processed by SimplifyIndvar for CurrIV.
+ SmallPtrSet<Instruction*,16> Simplified;
+
+ // Use-def pairs if IV users waiting to be processed for CurrIV.
+ SmallVector<std::pair<Instruction*, Instruction*>, 8> SimpleIVUsers;
+
+ // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
+ // called multiple times for the same LoopPhi. This is the proper thing to
+ // do for loop header phis that use each other.
+ pushIVUsers(CurrIV, Simplified, SimpleIVUsers);
+
+ while (!SimpleIVUsers.empty()) {
+ std::pair<Instruction*, Instruction*> UseOper =
+ SimpleIVUsers.pop_back_val();
+ // Bypass back edges to avoid extra work.
+ if (UseOper.first == CurrIV) continue;
+
+ Instruction *IVOperand = UseOper.second;
+ for (unsigned N = 0; IVOperand; ++N) {
+ assert(N <= Simplified.size() && "runaway iteration");
+
+ Value *NewOper = foldIVUser(UseOper.first, IVOperand);
+ if (!NewOper)
+ break; // done folding
+ IVOperand = dyn_cast<Instruction>(NewOper);
+ }
+ if (!IVOperand)
+ continue;
+
+ if (eliminateIVUser(UseOper.first, IVOperand)) {
+ pushIVUsers(IVOperand, Simplified, SimpleIVUsers);
+ continue;
+ }
+ CastInst *Cast = dyn_cast<CastInst>(UseOper.first);
+ if (V && Cast) {
+ V->visitCast(Cast);
+ continue;
+ }
+ if (isSimpleIVUser(UseOper.first, L, SE)) {
+ pushIVUsers(UseOper.first, Simplified, SimpleIVUsers);
+ }
+ }
+}
+
+namespace llvm {
+
+/// 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<WeakVH> &Dead, IVVisitor *V)
+{
+ LoopInfo *LI = &LPM->getAnalysis<LoopInfo>();
+ SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), SE, LPM, Dead);
+ SIV.simplifyUsers(CurrIV, V);
+ return SIV.hasChanged();
+}
+
+/// 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<WeakVH> &Dead) {
+ bool Changed = false;
+ for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) {
+ Changed |= simplifyUsersOfIV(cast<PHINode>(I), SE, LPM, Dead);
+ }
+ return Changed;
+}
+
+/// simplifyIVUsers - Perform simplification on instructions recorded by the
+/// IVUsers pass.
+///
+/// This is the old approach to IV simplification to be replaced by
+/// SimplifyLoopIVs.
+bool simplifyIVUsers(IVUsers *IU, ScalarEvolution *SE, LPPassManager *LPM,
+ SmallVectorImpl<WeakVH> &Dead) {
+ SimplifyIndvar SIV(IU->getLoop(), SE, LPM, Dead);
+
+ // Each round of simplification involves a round of eliminating operations
+ // followed by a round of widening IVs. A single IVUsers worklist is used
+ // across all rounds. The inner loop advances the user. If widening exposes
+ // more uses, then another pass through the outer loop is triggered.
+ for (IVUsers::iterator I = IU->begin(); I != IU->end(); ++I) {
+ Instruction *UseInst = I->getUser();
+ Value *IVOperand = I->getOperandValToReplace();
+
+ if (ICmpInst *ICmp = dyn_cast<ICmpInst>(UseInst)) {
+ SIV.eliminateIVComparison(ICmp, IVOperand);
+ continue;
+ }
+ if (BinaryOperator *Rem = dyn_cast<BinaryOperator>(UseInst)) {
+ bool IsSigned = Rem->getOpcode() == Instruction::SRem;
+ if (IsSigned || Rem->getOpcode() == Instruction::URem) {
+ SIV.eliminateIVRemainder(Rem, IVOperand, IsSigned);
+ continue;
+ }
+ }
+ }
+ return SIV.hasChanged();
+}
+
+} // namespace llvm
diff --git a/lib/Transforms/Utils/ValueMapper.cpp b/lib/Transforms/Utils/ValueMapper.cpp
index 973b105..fc2538d 100644
--- a/lib/Transforms/Utils/ValueMapper.cpp
+++ b/lib/Transforms/Utils/ValueMapper.cpp
@@ -183,10 +183,9 @@ void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap,
}
}
- // Remap attached metadata. Don't bother remapping DebugLoc, it can never
- // have mappings to do.
+ // Remap attached metadata.
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
- I->getAllMetadataOtherThanDebugLoc(MDs);
+ I->getAllMetadata(MDs);
for (SmallVectorImpl<std::pair<unsigned, MDNode *> >::iterator
MI = MDs.begin(), ME = MDs.end(); MI != ME; ++MI) {
MDNode *Old = MI->second;
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 94794c3..18308f2 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -58,7 +58,7 @@ static const Module *getModuleFromVal(const Value *V) {
const Function *M = I->getParent() ? I->getParent()->getParent() : 0;
return M ? M->getParent() : 0;
}
-
+
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
return GV->getParent();
return 0;
@@ -142,18 +142,18 @@ public:
/// NamedTypes - The named types that are used by the current module.
std::vector<StructType*> NamedTypes;
-
+
/// NumberedTypes - The numbered types, along with their value.
DenseMap<StructType*, unsigned> NumberedTypes;
-
+
TypePrinting() {}
~TypePrinting() {}
-
+
void incorporateTypes(const Module &M);
-
+
void print(Type *Ty, raw_ostream &OS);
-
+
void printStructBody(StructType *Ty, raw_ostream &OS);
};
} // end anonymous namespace.
@@ -161,25 +161,25 @@ public:
void TypePrinting::incorporateTypes(const Module &M) {
M.findUsedStructTypes(NamedTypes);
-
+
// The list of struct types we got back includes all the struct types, split
// the unnamed ones out to a numbering and remove the anonymous structs.
unsigned NextNumber = 0;
-
+
std::vector<StructType*>::iterator NextToUse = NamedTypes.begin(), I, E;
for (I = NamedTypes.begin(), E = NamedTypes.end(); I != E; ++I) {
StructType *STy = *I;
-
+
// Ignore anonymous types.
- if (STy->isAnonymous())
+ if (STy->isLiteral())
continue;
-
+
if (STy->getName().empty())
NumberedTypes[STy] = NextNumber++;
else
*NextToUse++ = STy;
}
-
+
NamedTypes.erase(NextToUse, NamedTypes.end());
}
@@ -220,13 +220,13 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) {
}
case Type::StructTyID: {
StructType *STy = cast<StructType>(Ty);
-
- if (STy->isAnonymous())
+
+ if (STy->isLiteral())
return printStructBody(STy, OS);
if (!STy->getName().empty())
return PrintLLVMName(OS, STy->getName(), LocalPrefix);
-
+
DenseMap<StructType*, unsigned>::iterator I = NumberedTypes.find(STy);
if (I != NumberedTypes.end())
OS << '%' << I->second;
@@ -267,10 +267,10 @@ void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) {
OS << "opaque";
return;
}
-
+
if (STy->isPacked())
OS << '<';
-
+
if (STy->getNumElements() == 0) {
OS << "{}";
} else {
@@ -281,7 +281,7 @@ void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) {
OS << ", ";
print(*I, OS);
}
-
+
OS << " }";
}
if (STy->isPacked())
@@ -386,7 +386,8 @@ static SlotTracker *createSlotTracker(const Value *V) {
return new SlotTracker(FA->getParent());
if (const Instruction *I = dyn_cast<Instruction>(V))
- return new SlotTracker(I->getParent()->getParent());
+ if (I->getParent())
+ return new SlotTracker(I->getParent()->getParent());
if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
return new SlotTracker(BB->getParent());
@@ -419,7 +420,7 @@ static SlotTracker *createSlotTracker(const Value *V) {
// Module level constructor. Causes the contents of the Module (sans functions)
// to be added to the slot table.
SlotTracker::SlotTracker(const Module *M)
- : TheModule(M), TheFunction(0), FunctionProcessed(false),
+ : TheModule(M), TheFunction(0), FunctionProcessed(false),
mNext(0), fNext(0), mdnNext(0) {
}
@@ -490,12 +491,12 @@ void SlotTracker::processFunction() {
E = TheFunction->end(); BB != E; ++BB) {
if (!BB->hasName())
CreateFunctionSlot(BB);
-
+
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E;
++I) {
if (!I->getType()->isVoidTy() && !I->hasName())
CreateFunctionSlot(I);
-
+
// Intrinsics can directly use metadata. We allow direct calls to any
// llvm.foo function here, because the target may not be linked into the
// optimizer.
@@ -658,6 +659,23 @@ static const char *getPredicateText(unsigned predicate) {
return pred;
}
+static void writeAtomicRMWOperation(raw_ostream &Out,
+ AtomicRMWInst::BinOp Op) {
+ switch (Op) {
+ default: Out << " <unknown operation " << Op << ">"; break;
+ case AtomicRMWInst::Xchg: Out << " xchg"; break;
+ case AtomicRMWInst::Add: Out << " add"; break;
+ case AtomicRMWInst::Sub: Out << " sub"; break;
+ case AtomicRMWInst::And: Out << " and"; break;
+ case AtomicRMWInst::Nand: Out << " nand"; break;
+ case AtomicRMWInst::Or: Out << " or"; break;
+ case AtomicRMWInst::Xor: Out << " xor"; break;
+ case AtomicRMWInst::Max: Out << " max"; break;
+ case AtomicRMWInst::Min: Out << " min"; break;
+ case AtomicRMWInst::UMax: Out << " umax"; break;
+ case AtomicRMWInst::UMin: Out << " umin"; break;
+ }
+}
static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {
if (const OverflowingBinaryOperator *OBO =
@@ -792,7 +810,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
Out << "zeroinitializer";
return;
}
-
+
if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV)) {
Out << "blockaddress(";
WriteAsOperandInternal(Out, BA->getFunction(), &TypePrinter, Machine,
@@ -939,13 +957,13 @@ static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
else {
TypePrinter->print(V->getType(), Out);
Out << ' ';
- WriteAsOperandInternal(Out, Node->getOperand(mi),
+ WriteAsOperandInternal(Out, Node->getOperand(mi),
TypePrinter, Machine, Context);
}
if (mi + 1 != me)
Out << ", ";
}
-
+
Out << "}";
}
@@ -990,7 +1008,7 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
WriteMDNodeBodyInternal(Out, N, TypePrinter, Machine, Context);
return;
}
-
+
if (!Machine) {
if (N->isFunctionLocal())
Machine = new SlotTracker(N->getFunction());
@@ -1020,26 +1038,35 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
char Prefix = '%';
int Slot;
+ // If we have a SlotTracker, use it.
if (Machine) {
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
Slot = Machine->getGlobalSlot(GV);
Prefix = '@';
} else {
Slot = Machine->getLocalSlot(V);
+
+ // If the local value didn't succeed, then we may be referring to a value
+ // from a different function. Translate it, as this can happen when using
+ // address of blocks.
+ if (Slot == -1)
+ if ((Machine = createSlotTracker(V))) {
+ Slot = Machine->getLocalSlot(V);
+ delete Machine;
+ }
}
- } else {
- Machine = createSlotTracker(V);
- if (Machine) {
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
- Slot = Machine->getGlobalSlot(GV);
- Prefix = '@';
- } else {
- Slot = Machine->getLocalSlot(V);
- }
- delete Machine;
+ } else if ((Machine = createSlotTracker(V))) {
+ // Otherwise, create one to get the # and then destroy it.
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
+ Slot = Machine->getGlobalSlot(GV);
+ Prefix = '@';
} else {
- Slot = -1;
+ Slot = Machine->getLocalSlot(V);
}
+ delete Machine;
+ Machine = 0;
+ } else {
+ Slot = -1;
}
if (Slot != -1)
@@ -1081,7 +1108,7 @@ class AssemblyWriter {
const Module *TheModule;
TypePrinting TypePrinter;
AssemblyAnnotationWriter *AnnotationWriter;
-
+
public:
inline AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
const Module *M,
@@ -1093,11 +1120,12 @@ public:
void printMDNodeBody(const MDNode *MD);
void printNamedMDNode(const NamedMDNode *NMD);
-
+
void printModule(const Module *M);
void writeOperand(const Value *Op, bool PrintType);
void writeParamOperand(const Value *Operand, Attributes Attrs);
+ void writeAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope);
void writeAllMDNodes();
@@ -1128,6 +1156,28 @@ void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) {
WriteAsOperandInternal(Out, Operand, &TypePrinter, &Machine, TheModule);
}
+void AssemblyWriter::writeAtomic(AtomicOrdering Ordering,
+ SynchronizationScope SynchScope) {
+ if (Ordering == NotAtomic)
+ return;
+
+ switch (SynchScope) {
+ default: Out << " <bad scope " << int(SynchScope) << ">"; break;
+ case SingleThread: Out << " singlethread"; break;
+ case CrossThread: break;
+ }
+
+ switch (Ordering) {
+ default: Out << " <bad ordering " << int(Ordering) << ">"; break;
+ case Unordered: Out << " unordered"; break;
+ case Monotonic: Out << " monotonic"; break;
+ case Acquire: Out << " acquire"; break;
+ case Release: Out << " release"; break;
+ case AcquireRelease: Out << " acq_rel"; break;
+ case SequentiallyConsistent: Out << " seq_cst"; break;
+ }
+}
+
void AssemblyWriter::writeParamOperand(const Value *Operand,
Attributes Attrs) {
if (Operand == 0) {
@@ -1216,7 +1266,7 @@ void AssemblyWriter::printModule(const Module *M) {
// Output named metadata.
if (!M->named_metadata_empty()) Out << '\n';
-
+
for (Module::const_named_metadata_iterator I = M->named_metadata_begin(),
E = M->named_metadata_end(); I != E; ++I)
printNamedMDNode(I);
@@ -1357,26 +1407,8 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) {
if (Aliasee == 0) {
TypePrinter.print(GA->getType(), Out);
Out << " <<NULL ALIASEE>>";
- } else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Aliasee)) {
- TypePrinter.print(GV->getType(), Out);
- Out << ' ';
- PrintLLVMName(Out, GV);
- } else if (const Function *F = dyn_cast<Function>(Aliasee)) {
- TypePrinter.print(F->getFunctionType(), Out);
- Out << "* ";
-
- WriteAsOperandInternal(Out, F, &TypePrinter, &Machine, F->getParent());
- } else if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(Aliasee)) {
- TypePrinter.print(GA->getType(), Out);
- Out << ' ';
- PrintLLVMName(Out, GA);
} else {
- const ConstantExpr *CE = cast<ConstantExpr>(Aliasee);
- // The only valid GEP is an all zero GEP.
- assert((CE->getOpcode() == Instruction::BitCast ||
- CE->getOpcode() == Instruction::GetElementPtr) &&
- "Unsupported aliasee");
- writeOperand(CE, false);
+ writeOperand(Aliasee, !isa<ConstantExpr>(Aliasee));
}
printInfoComment(*GA);
@@ -1387,29 +1419,29 @@ void AssemblyWriter::printTypeIdentities() {
if (TypePrinter.NumberedTypes.empty() &&
TypePrinter.NamedTypes.empty())
return;
-
+
Out << '\n';
-
+
// We know all the numbers that each type is used and we know that it is a
// dense assignment. Convert the map to an index table.
std::vector<StructType*> NumberedTypes(TypePrinter.NumberedTypes.size());
- for (DenseMap<StructType*, unsigned>::iterator I =
+ for (DenseMap<StructType*, unsigned>::iterator I =
TypePrinter.NumberedTypes.begin(), E = TypePrinter.NumberedTypes.end();
I != E; ++I) {
assert(I->second < NumberedTypes.size() && "Didn't get a dense numbering?");
NumberedTypes[I->second] = I->first;
}
-
+
// Emit all numbered types.
for (unsigned i = 0, e = NumberedTypes.size(); i != e; ++i) {
Out << '%' << i << " = type ";
-
+
// Make sure we print out at least one level of the type structure, so
// that we do not get %2 = type %2
TypePrinter.printStructBody(NumberedTypes[i], Out);
Out << '\n';
}
-
+
for (unsigned i = 0, e = TypePrinter.NamedTypes.size(); i != e; ++i) {
PrintLLVMName(Out, TypePrinter.NamedTypes[i]->getName(), LocalPrefix);
Out << " = type ";
@@ -1457,7 +1489,7 @@ void AssemblyWriter::printFunction(const Function *F) {
default: Out << "cc" << F->getCallingConv() << " "; break;
}
- const FunctionType *FT = F->getFunctionType();
+ FunctionType *FT = F->getFunctionType();
const AttrListPtr &Attrs = F->getAttributes();
Attributes RetAttrs = Attrs.getRetAttributes();
if (RetAttrs != Attribute::None)
@@ -1628,18 +1660,24 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
Out << '%' << SlotNum << " = ";
}
- // If this is a volatile load or store, print out the volatile marker.
- if ((isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) ||
- (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile())) {
- Out << "volatile ";
- } else if (isa<CallInst>(I) && cast<CallInst>(I).isTailCall()) {
- // If this is a call, check if it's a tail call.
+ if (isa<CallInst>(I) && cast<CallInst>(I).isTailCall())
Out << "tail ";
- }
// Print out the opcode...
Out << I.getOpcodeName();
+ // If this is an atomic load or store, print out the atomic marker.
+ if ((isa<LoadInst>(I) && cast<LoadInst>(I).isAtomic()) ||
+ (isa<StoreInst>(I) && cast<StoreInst>(I).isAtomic()))
+ Out << " atomic";
+
+ // If this is a volatile operation, print out the volatile marker.
+ if ((isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) ||
+ (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()) ||
+ (isa<AtomicCmpXchgInst>(I) && cast<AtomicCmpXchgInst>(I).isVolatile()) ||
+ (isa<AtomicRMWInst>(I) && cast<AtomicRMWInst>(I).isVolatile()))
+ Out << " volatile";
+
// Print out optimization information.
WriteOptimizationInfo(Out, &I);
@@ -1647,6 +1685,10 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
if (const CmpInst *CI = dyn_cast<CmpInst>(&I))
Out << ' ' << getPredicateText(CI->getPredicate());
+ // Print out the atomicrmw operation
+ if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&I))
+ writeAtomicRMWOperation(Out, RMWI->getOperation());
+
// Print out the type of the operands...
const Value *Operand = I.getNumOperands() ? I.getOperand(0) : 0;
@@ -1661,18 +1703,20 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
writeOperand(BI.getSuccessor(1), true);
} else if (isa<SwitchInst>(I)) {
+ SwitchInst& SI(cast<SwitchInst>(I));
// Special case switch instruction to get formatting nice and correct.
Out << ' ';
- writeOperand(Operand , true);
+ writeOperand(SI.getCondition(), true);
Out << ", ";
- writeOperand(I.getOperand(1), true);
+ writeOperand(SI.getDefaultDest(), true);
Out << " [";
-
- for (unsigned op = 2, Eop = I.getNumOperands(); op < Eop; op += 2) {
+ // Skip the first item since that's the default case.
+ unsigned NumCases = SI.getNumCases();
+ for (unsigned i = 1; i < NumCases; ++i) {
Out << "\n ";
- writeOperand(I.getOperand(op ), true);
+ writeOperand(SI.getCaseValue(i), true);
Out << ", ";
- writeOperand(I.getOperand(op+1), true);
+ writeOperand(SI.getSuccessor(i), true);
}
Out << "\n ]";
} else if (isa<IndirectBrInst>(I)) {
@@ -1680,7 +1724,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
Out << ' ';
writeOperand(Operand, true);
Out << ", [";
-
+
for (unsigned i = 1, e = I.getNumOperands(); i != e; ++i) {
if (i != 1)
Out << ", ";
@@ -1709,6 +1753,24 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
writeOperand(I.getOperand(1), true);
for (const unsigned *i = IVI->idx_begin(), *e = IVI->idx_end(); i != e; ++i)
Out << ", " << *i;
+ } else if (const LandingPadInst *LPI = dyn_cast<LandingPadInst>(&I)) {
+ Out << ' ';
+ TypePrinter.print(I.getType(), Out);
+ Out << " personality ";
+ writeOperand(I.getOperand(0), true); Out << '\n';
+
+ if (LPI->isCleanup())
+ Out << " cleanup";
+
+ for (unsigned i = 0, e = LPI->getNumClauses(); i != e; ++i) {
+ if (i != 0 || LPI->isCleanup()) Out << "\n";
+ if (LPI->isCatch(i))
+ Out << " catch ";
+ else
+ Out << " filter ";
+
+ writeOperand(LPI->getClause(i), true);
+ }
} else if (isa<ReturnInst>(I) && !Operand) {
Out << " void";
} else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
@@ -1878,11 +1940,23 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
}
}
- // Print post operand alignment for load/store.
- if (isa<LoadInst>(I) && cast<LoadInst>(I).getAlignment()) {
- Out << ", align " << cast<LoadInst>(I).getAlignment();
- } else if (isa<StoreInst>(I) && cast<StoreInst>(I).getAlignment()) {
- Out << ", align " << cast<StoreInst>(I).getAlignment();
+ // Print atomic ordering/alignment for memory operations
+ if (const LoadInst *LI = dyn_cast<LoadInst>(&I)) {
+ if (LI->isAtomic())
+ writeAtomic(LI->getOrdering(), LI->getSynchScope());
+ if (LI->getAlignment())
+ Out << ", align " << LI->getAlignment();
+ } else if (const StoreInst *SI = dyn_cast<StoreInst>(&I)) {
+ if (SI->isAtomic())
+ writeAtomic(SI->getOrdering(), SI->getSynchScope());
+ if (SI->getAlignment())
+ Out << ", align " << SI->getAlignment();
+ } else if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(&I)) {
+ writeAtomic(CXI->getOrdering(), CXI->getSynchScope());
+ } else if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&I)) {
+ writeAtomic(RMWI->getOrdering(), RMWI->getSynchScope());
+ } else if (const FenceInst *FI = dyn_cast<FenceInst>(&I)) {
+ writeAtomic(FI->getOrdering(), FI->getSynchScope());
}
// Print Metadata info.
@@ -1916,7 +1990,7 @@ static void WriteMDNodeComment(const MDNode *Node,
APInt Tag = Val & ~APInt(Val.getBitWidth(), LLVMDebugVersionMask);
if (Val.ult(LLVMDebugVersion))
return;
-
+
Out.PadToColumn(50);
if (Tag == dwarf::DW_TAG_user_base)
Out << "; [ DW_TAG_user_base ]";
@@ -1932,7 +2006,7 @@ void AssemblyWriter::writeAllMDNodes() {
for (SlotTracker::mdn_iterator I = Machine.mdn_begin(), E = Machine.mdn_end();
I != E; ++I)
Nodes[I->second] = cast<MDNode>(I->first);
-
+
for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
Out << '!' << i << " = metadata ";
printMDNodeBody(Nodes[i]);
@@ -1970,10 +2044,10 @@ void Type::print(raw_ostream &OS) const {
}
TypePrinting TP;
TP.print(const_cast<Type*>(this), OS);
-
+
// If the type is a named struct type, print the body as well.
if (StructType *STy = dyn_cast<StructType>(const_cast<Type*>(this)))
- if (!STy->isAnonymous()) {
+ if (!STy->isLiteral()) {
OS << " = type ";
TP.printStructBody(STy, OS);
}
diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp
index bf6efa1..485be75 100644
--- a/lib/VMCore/Attributes.cpp
+++ b/lib/VMCore/Attributes.cpp
@@ -38,6 +38,8 @@ std::string Attribute::getAsString(Attributes Attrs) {
Result += "nounwind ";
if (Attrs & Attribute::UWTable)
Result += "uwtable ";
+ if (Attrs & Attribute::ReturnsTwice)
+ Result += "returns_twice ";
if (Attrs & Attribute::InReg)
Result += "inreg ";
if (Attrs & Attribute::NoAlias)
@@ -72,8 +74,6 @@ std::string Attribute::getAsString(Attributes Attrs) {
Result += "noimplicitfloat ";
if (Attrs & Attribute::Naked)
Result += "naked ";
- if (Attrs & Attribute::Hotpatch)
- Result += "hotpatch ";
if (Attrs & Attribute::NonLazyBind)
Result += "nonlazybind ";
if (Attrs & Attribute::StackAlignment) {
@@ -92,7 +92,7 @@ std::string Attribute::getAsString(Attributes Attrs) {
return Result;
}
-Attributes Attribute::typeIncompatible(const Type *Ty) {
+Attributes Attribute::typeIncompatible(Type *Ty) {
Attributes Incompatible = None;
if (!Ty->isIntegerTy())
diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp
index 9e93ff3..b849d3e 100644
--- a/lib/VMCore/AutoUpgrade.cpp
+++ b/lib/VMCore/AutoUpgrade.cpp
@@ -14,11 +14,15 @@
#include "llvm/AutoUpgrade.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
+#include "llvm/Instruction.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/IntrinsicInst.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CallSite.h"
+#include "llvm/Support/CFG.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/IRBuilder.h"
#include <cstring>
@@ -34,11 +38,48 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
return false;
Name = Name.substr(5); // Strip off "llvm."
- const FunctionType *FTy = F->getFunctionType();
+ FunctionType *FTy = F->getFunctionType();
Module *M = F->getParent();
switch (Name[0]) {
default: break;
+ case 'a':
+ if (Name.startswith("atomic.cmp.swap") ||
+ Name.startswith("atomic.swap") ||
+ Name.startswith("atomic.load.add") ||
+ Name.startswith("atomic.load.sub") ||
+ Name.startswith("atomic.load.and") ||
+ Name.startswith("atomic.load.nand") ||
+ Name.startswith("atomic.load.or") ||
+ Name.startswith("atomic.load.xor") ||
+ Name.startswith("atomic.load.max") ||
+ Name.startswith("atomic.load.min") ||
+ Name.startswith("atomic.load.umax") ||
+ Name.startswith("atomic.load.umin"))
+ return true;
+ case 'i':
+ // This upgrades the old llvm.init.trampoline to the new
+ // llvm.init.trampoline and llvm.adjust.trampoline pair.
+ if (Name == "init.trampoline") {
+ // The new llvm.init.trampoline returns nothing.
+ if (FTy->getReturnType()->isVoidTy())
+ break;
+
+ assert(FTy->getNumParams() == 3 && "old init.trampoline takes 3 args!");
+
+ // Change the name of the old intrinsic so that we can play with its type.
+ std::string NameTmp = F->getName();
+ F->setName("");
+ NewFn = cast<Function>(M->getOrInsertFunction(
+ NameTmp,
+ Type::getVoidTy(M->getContext()),
+ FTy->getParamType(0), FTy->getParamType(1),
+ FTy->getParamType(2), (Type *)0));
+ return true;
+ }
+ case 'm':
+ if (Name == "memory.barrier")
+ return true;
case 'p':
// This upgrades the llvm.prefetch intrinsic to accept one more parameter,
// which is a instruction / data cache identifier. The old version only
@@ -139,8 +180,8 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
F->getName() == "llvm.x86.sse2.loadu.dq" ||
F->getName() == "llvm.x86.sse2.loadu.pd") {
// Convert to a native, unaligned load.
- const Type *VecTy = CI->getType();
- const Type *IntTy = IntegerType::get(C, 128);
+ Type *VecTy = CI->getType();
+ Type *IntTy = IntegerType::get(C, 128);
IRBuilder<> Builder(C);
Builder.SetInsertPoint(CI->getParent(), CI);
@@ -182,6 +223,80 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
// Remove intrinsic.
CI->eraseFromParent();
+ } else if (F->getName().startswith("llvm.atomic.cmp.swap")) {
+ IRBuilder<> Builder(C);
+ Builder.SetInsertPoint(CI->getParent(), CI);
+ Value *Val = Builder.CreateAtomicCmpXchg(CI->getArgOperand(0),
+ CI->getArgOperand(1),
+ CI->getArgOperand(2),
+ Monotonic);
+
+ // Replace intrinsic.
+ Val->takeName(CI);
+ if (!CI->use_empty())
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (F->getName().startswith("llvm.atomic")) {
+ IRBuilder<> Builder(C);
+ Builder.SetInsertPoint(CI->getParent(), CI);
+
+ AtomicRMWInst::BinOp Op;
+ if (F->getName().startswith("llvm.atomic.swap"))
+ Op = AtomicRMWInst::Xchg;
+ else if (F->getName().startswith("llvm.atomic.load.add"))
+ Op = AtomicRMWInst::Add;
+ else if (F->getName().startswith("llvm.atomic.load.sub"))
+ Op = AtomicRMWInst::Sub;
+ else if (F->getName().startswith("llvm.atomic.load.and"))
+ Op = AtomicRMWInst::And;
+ else if (F->getName().startswith("llvm.atomic.load.nand"))
+ Op = AtomicRMWInst::Nand;
+ else if (F->getName().startswith("llvm.atomic.load.or"))
+ Op = AtomicRMWInst::Or;
+ else if (F->getName().startswith("llvm.atomic.load.xor"))
+ Op = AtomicRMWInst::Xor;
+ else if (F->getName().startswith("llvm.atomic.load.max"))
+ Op = AtomicRMWInst::Max;
+ else if (F->getName().startswith("llvm.atomic.load.min"))
+ Op = AtomicRMWInst::Min;
+ else if (F->getName().startswith("llvm.atomic.load.umax"))
+ Op = AtomicRMWInst::UMax;
+ else if (F->getName().startswith("llvm.atomic.load.umin"))
+ Op = AtomicRMWInst::UMin;
+ else
+ llvm_unreachable("Unknown atomic");
+
+ Value *Val = Builder.CreateAtomicRMW(Op, CI->getArgOperand(0),
+ CI->getArgOperand(1),
+ Monotonic);
+
+ // Replace intrinsic.
+ Val->takeName(CI);
+ if (!CI->use_empty())
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (F->getName() == "llvm.memory.barrier") {
+ IRBuilder<> Builder(C);
+ Builder.SetInsertPoint(CI->getParent(), CI);
+
+ // Note that this conversion ignores the "device" bit; it was not really
+ // well-defined, and got abused because nobody paid enough attention to
+ // get it right. In practice, this probably doesn't matter; application
+ // code generally doesn't need anything stronger than
+ // SequentiallyConsistent (and realistically, SequentiallyConsistent
+ // is lowered to a strong enough barrier for almost anything).
+
+ if (cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue())
+ Builder.CreateFence(SequentiallyConsistent);
+ else if (!cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue())
+ Builder.CreateFence(Release);
+ else if (!cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue())
+ Builder.CreateFence(Acquire);
+ else
+ Builder.CreateFence(AcquireRelease);
+
+ // Remove intrinsic.
+ CI->eraseFromParent();
} else {
llvm_unreachable("Unknown function for CallInst upgrade.");
}
@@ -192,7 +307,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
case Intrinsic::prefetch: {
IRBuilder<> Builder(C);
Builder.SetInsertPoint(CI->getParent(), CI);
- const llvm::Type *I32Ty = llvm::Type::getInt32Ty(CI->getContext());
+ llvm::Type *I32Ty = llvm::Type::getInt32Ty(CI->getContext());
// Add the extra "data cache" argument
Value *Operands[4] = { CI->getArgOperand(0), CI->getArgOperand(1),
@@ -212,6 +327,32 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
CI->eraseFromParent();
break;
}
+ case Intrinsic::init_trampoline: {
+
+ // Transform
+ // %tramp = call i8* llvm.init.trampoline (i8* x, i8* y, i8* z)
+ // to
+ // call void llvm.init.trampoline (i8* %x, i8* %y, i8* %z)
+ // %tramp = call i8* llvm.adjust.trampoline (i8* %x)
+
+ Function *AdjustTrampolineFn =
+ cast<Function>(Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::adjust_trampoline));
+
+ IRBuilder<> Builder(C);
+ Builder.SetInsertPoint(CI);
+
+ Builder.CreateCall3(NewFn, CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2));
+
+ CallInst *AdjustCall = Builder.CreateCall(AdjustTrampolineFn,
+ CI->getArgOperand(0),
+ CI->getName());
+ if (!CI->use_empty())
+ CI->replaceAllUsesWith(AdjustCall);
+ CI->eraseFromParent();
+ break;
+ }
}
}
@@ -279,3 +420,249 @@ void llvm::CheckDebugInfoIntrinsics(Module *M) {
}
}
}
+
+/// FindExnAndSelIntrinsics - Find the eh_exception and eh_selector intrinsic
+/// calls reachable from the unwind basic block.
+static void FindExnAndSelIntrinsics(BasicBlock *BB, CallInst *&Exn,
+ CallInst *&Sel,
+ SmallPtrSet<BasicBlock*, 8> &Visited) {
+ if (!Visited.insert(BB)) return;
+
+ for (BasicBlock::iterator
+ I = BB->begin(), E = BB->end(); I != E; ++I) {
+ if (CallInst *CI = dyn_cast<CallInst>(I)) {
+ switch (CI->getCalledFunction()->getIntrinsicID()) {
+ default: break;
+ case Intrinsic::eh_exception:
+ assert(!Exn && "Found more than one eh.exception call!");
+ Exn = CI;
+ break;
+ case Intrinsic::eh_selector:
+ assert(!Sel && "Found more than one eh.selector call!");
+ Sel = CI;
+ break;
+ }
+
+ if (Exn && Sel) return;
+ }
+ }
+
+ if (Exn && Sel) return;
+
+ for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
+ FindExnAndSelIntrinsics(*I, Exn, Sel, Visited);
+ if (Exn && Sel) return;
+ }
+}
+
+/// TransferClausesToLandingPadInst - Transfer the exception handling clauses
+/// from the eh_selector call to the new landingpad instruction.
+static void TransferClausesToLandingPadInst(LandingPadInst *LPI,
+ CallInst *EHSel) {
+ LLVMContext &Context = LPI->getContext();
+ unsigned N = EHSel->getNumArgOperands();
+
+ for (unsigned i = N - 1; i > 1; --i) {
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(EHSel->getArgOperand(i))){
+ unsigned FilterLength = CI->getZExtValue();
+ unsigned FirstCatch = i + FilterLength + !FilterLength;
+ assert(FirstCatch <= N && "Invalid filter length");
+
+ if (FirstCatch < N)
+ for (unsigned j = FirstCatch; j < N; ++j) {
+ Value *Val = EHSel->getArgOperand(j);
+ if (!Val->hasName() || Val->getName() != "llvm.eh.catch.all.value") {
+ LPI->addClause(EHSel->getArgOperand(j));
+ } else {
+ GlobalVariable *GV = cast<GlobalVariable>(Val);
+ LPI->addClause(GV->getInitializer());
+ }
+ }
+
+ if (!FilterLength) {
+ // Cleanup.
+ LPI->setCleanup(true);
+ } else {
+ // Filter.
+ SmallVector<Constant *, 4> TyInfo;
+ TyInfo.reserve(FilterLength - 1);
+ for (unsigned j = i + 1; j < FirstCatch; ++j)
+ TyInfo.push_back(cast<Constant>(EHSel->getArgOperand(j)));
+ ArrayType *AType =
+ ArrayType::get(!TyInfo.empty() ? TyInfo[0]->getType() :
+ PointerType::getUnqual(Type::getInt8Ty(Context)),
+ TyInfo.size());
+ LPI->addClause(ConstantArray::get(AType, TyInfo));
+ }
+
+ N = i;
+ }
+ }
+
+ if (N > 2)
+ for (unsigned j = 2; j < N; ++j) {
+ Value *Val = EHSel->getArgOperand(j);
+ if (!Val->hasName() || Val->getName() != "llvm.eh.catch.all.value") {
+ LPI->addClause(EHSel->getArgOperand(j));
+ } else {
+ GlobalVariable *GV = cast<GlobalVariable>(Val);
+ LPI->addClause(GV->getInitializer());
+ }
+ }
+}
+
+/// 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 llvm::UpgradeExceptionHandling(Module *M) {
+ Function *EHException = M->getFunction("llvm.eh.exception");
+ Function *EHSelector = M->getFunction("llvm.eh.selector");
+ if (!EHException || !EHSelector)
+ return;
+
+ LLVMContext &Context = M->getContext();
+ Type *ExnTy = PointerType::getUnqual(Type::getInt8Ty(Context));
+ Type *SelTy = Type::getInt32Ty(Context);
+ Type *LPadSlotTy = StructType::get(ExnTy, SelTy, NULL);
+
+ // This map links the invoke instruction with the eh.exception and eh.selector
+ // calls associated with it.
+ DenseMap<InvokeInst*, std::pair<Value*, Value*> > InvokeToIntrinsicsMap;
+ for (Module::iterator
+ I = M->begin(), E = M->end(); I != E; ++I) {
+ Function &F = *I;
+
+ for (Function::iterator
+ II = F.begin(), IE = F.end(); II != IE; ++II) {
+ BasicBlock *BB = &*II;
+ InvokeInst *Inst = dyn_cast<InvokeInst>(BB->getTerminator());
+ if (!Inst) continue;
+ BasicBlock *UnwindDest = Inst->getUnwindDest();
+ if (UnwindDest->isLandingPad()) continue; // Already converted.
+
+ SmallPtrSet<BasicBlock*, 8> Visited;
+ CallInst *Exn = 0;
+ CallInst *Sel = 0;
+ FindExnAndSelIntrinsics(UnwindDest, Exn, Sel, Visited);
+ assert(Exn && Sel && "Cannot find eh.exception and eh.selector calls!");
+ InvokeToIntrinsicsMap[Inst] = std::make_pair(Exn, Sel);
+ }
+ }
+
+ // This map stores the slots where the exception object and selector value are
+ // stored within a function.
+ DenseMap<Function*, std::pair<Value*, Value*> > FnToLPadSlotMap;
+ SmallPtrSet<Instruction*, 32> DeadInsts;
+ for (DenseMap<InvokeInst*, std::pair<Value*, Value*> >::iterator
+ I = InvokeToIntrinsicsMap.begin(), E = InvokeToIntrinsicsMap.end();
+ I != E; ++I) {
+ InvokeInst *Invoke = I->first;
+ BasicBlock *UnwindDest = Invoke->getUnwindDest();
+ Function *F = UnwindDest->getParent();
+ std::pair<Value*, Value*> EHIntrinsics = I->second;
+ CallInst *Exn = cast<CallInst>(EHIntrinsics.first);
+ CallInst *Sel = cast<CallInst>(EHIntrinsics.second);
+
+ // Store the exception object and selector value in the entry block.
+ Value *ExnSlot = 0;
+ Value *SelSlot = 0;
+ if (!FnToLPadSlotMap[F].first) {
+ BasicBlock *Entry = &F->front();
+ ExnSlot = new AllocaInst(ExnTy, "exn", Entry->getTerminator());
+ SelSlot = new AllocaInst(SelTy, "sel", Entry->getTerminator());
+ FnToLPadSlotMap[F] = std::make_pair(ExnSlot, SelSlot);
+ } else {
+ ExnSlot = FnToLPadSlotMap[F].first;
+ SelSlot = FnToLPadSlotMap[F].second;
+ }
+
+ if (!UnwindDest->getSinglePredecessor()) {
+ // The unwind destination doesn't have a single predecessor. Create an
+ // unwind destination which has only one predecessor.
+ BasicBlock *NewBB = BasicBlock::Create(Context, "new.lpad",
+ UnwindDest->getParent());
+ BranchInst::Create(UnwindDest, NewBB);
+ Invoke->setUnwindDest(NewBB);
+
+ // Fix up any PHIs in the original unwind destination block.
+ for (BasicBlock::iterator
+ II = UnwindDest->begin(); isa<PHINode>(II); ++II) {
+ PHINode *PN = cast<PHINode>(II);
+ int Idx = PN->getBasicBlockIndex(Invoke->getParent());
+ if (Idx == -1) continue;
+ PN->setIncomingBlock(Idx, NewBB);
+ }
+
+ UnwindDest = NewBB;
+ }
+
+ IRBuilder<> Builder(Context);
+ Builder.SetInsertPoint(UnwindDest, UnwindDest->getFirstInsertionPt());
+
+ Value *PersFn = Sel->getArgOperand(1);
+ LandingPadInst *LPI = Builder.CreateLandingPad(LPadSlotTy, PersFn, 0);
+ Value *LPExn = Builder.CreateExtractValue(LPI, 0);
+ Value *LPSel = Builder.CreateExtractValue(LPI, 1);
+ Builder.CreateStore(LPExn, ExnSlot);
+ Builder.CreateStore(LPSel, SelSlot);
+
+ TransferClausesToLandingPadInst(LPI, Sel);
+
+ DeadInsts.insert(Exn);
+ DeadInsts.insert(Sel);
+ }
+
+ // Replace the old intrinsic calls with the values from the landingpad
+ // instruction(s). These values were stored in allocas for us to use here.
+ for (DenseMap<InvokeInst*, std::pair<Value*, Value*> >::iterator
+ I = InvokeToIntrinsicsMap.begin(), E = InvokeToIntrinsicsMap.end();
+ I != E; ++I) {
+ std::pair<Value*, Value*> EHIntrinsics = I->second;
+ CallInst *Exn = cast<CallInst>(EHIntrinsics.first);
+ CallInst *Sel = cast<CallInst>(EHIntrinsics.second);
+ BasicBlock *Parent = Exn->getParent();
+
+ std::pair<Value*,Value*> ExnSelSlots = FnToLPadSlotMap[Parent->getParent()];
+
+ IRBuilder<> Builder(Context);
+ Builder.SetInsertPoint(Parent, Exn);
+ LoadInst *LPExn = Builder.CreateLoad(ExnSelSlots.first, "exn.load");
+ LoadInst *LPSel = Builder.CreateLoad(ExnSelSlots.second, "sel.load");
+
+ Exn->replaceAllUsesWith(LPExn);
+ Sel->replaceAllUsesWith(LPSel);
+ }
+
+ // Remove the dead instructions.
+ for (SmallPtrSet<Instruction*, 32>::iterator
+ I = DeadInsts.begin(), E = DeadInsts.end(); I != E; ++I) {
+ Instruction *Inst = *I;
+ Inst->eraseFromParent();
+ }
+
+ // Replace calls to "llvm.eh.resume" with the 'resume' instruction. Load the
+ // exception and selector values from the stored place.
+ Function *EHResume = M->getFunction("llvm.eh.resume");
+ if (!EHResume) return;
+
+ while (!EHResume->use_empty()) {
+ CallInst *Resume = cast<CallInst>(EHResume->use_back());
+ BasicBlock *BB = Resume->getParent();
+
+ IRBuilder<> Builder(Context);
+ Builder.SetInsertPoint(BB, Resume);
+
+ Value *LPadVal =
+ Builder.CreateInsertValue(UndefValue::get(LPadSlotTy),
+ Resume->getArgOperand(0), 0, "lpad.val");
+ LPadVal = Builder.CreateInsertValue(LPadVal, Resume->getArgOperand(1),
+ 1, "lpad.val");
+ Builder.CreateResume(LPadVal);
+
+ // Remove all instructions after the 'resume.'
+ BasicBlock::iterator I = Resume;
+ while (I != BB->end()) {
+ Instruction *Inst = &*I++;
+ Inst->eraseFromParent();
+ }
+ }
+}
diff --git a/lib/VMCore/BasicBlock.cpp b/lib/VMCore/BasicBlock.cpp
index 70265c8..d0aa275 100644
--- a/lib/VMCore/BasicBlock.cpp
+++ b/lib/VMCore/BasicBlock.cpp
@@ -53,7 +53,7 @@ BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent,
} else if (NewParent) {
NewParent->getBasicBlockList().push_back(this);
}
-
+
setName(Name);
}
@@ -76,7 +76,7 @@ BasicBlock::~BasicBlock() {
BA->destroyConstant();
}
}
-
+
assert(getParent() == 0 && "BasicBlock still linked into the program!");
dropAllReferences();
InstList.clear();
@@ -167,6 +167,12 @@ Instruction* BasicBlock::getFirstNonPHIOrDbgOrLifetime() {
return &*i;
}
+BasicBlock::iterator BasicBlock::getFirstInsertionPt() {
+ iterator InsertPt = getFirstNonPHI();
+ if (isa<LandingPadInst>(InsertPt)) ++InsertPt;
+ return InsertPt;
+}
+
void BasicBlock::dropAllReferences() {
for(iterator I = begin(), E = end(); I != E; ++I)
I->dropAllReferences();
@@ -184,8 +190,8 @@ BasicBlock *BasicBlock::getSinglePredecessor() {
/// getUniquePredecessor - If this basic block has a unique predecessor block,
/// return the block, otherwise return a null pointer.
-/// Note that unique predecessor doesn't mean single edge, there can be
-/// multiple edges from the unique predecessor to this block (for example
+/// Note that unique predecessor doesn't mean single edge, there can be
+/// multiple edges from the unique predecessor to this block (for example
/// a switch statement with multiple cases having the same destination).
BasicBlock *BasicBlock::getUniquePredecessor() {
pred_iterator PI = pred_begin(this), E = pred_end(this);
@@ -336,11 +342,27 @@ void BasicBlock::replaceSuccessorsPhiUsesWith(BasicBlock *New) {
return;
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) {
BasicBlock *Succ = TI->getSuccessor(i);
- for (iterator II = Succ->begin(); PHINode *PN = dyn_cast<PHINode>(II);
- ++II) {
+ // N.B. Succ might not be a complete BasicBlock, so don't assume
+ // that it ends with a non-phi instruction.
+ for (iterator II = Succ->begin(), IE = Succ->end(); II != IE; ++II) {
+ PHINode *PN = dyn_cast<PHINode>(II);
+ if (!PN)
+ break;
int i;
while ((i = PN->getBasicBlockIndex(this)) >= 0)
PN->setIncomingBlock(i, 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 BasicBlock::isLandingPad() const {
+ return isa<LandingPadInst>(getFirstNonPHI());
+}
+
+/// getLandingPadInst() - Return the landingpad instruction associated with
+/// the landing pad.
+LandingPadInst *BasicBlock::getLandingPadInst() {
+ return dyn_cast<LandingPadInst>(getFirstNonPHI());
+}
diff --git a/lib/VMCore/CMakeLists.txt b/lib/VMCore/CMakeLists.txt
index f60dd06..0404297 100644
--- a/lib/VMCore/CMakeLists.txt
+++ b/lib/VMCore/CMakeLists.txt
@@ -8,10 +8,11 @@ add_llvm_library(LLVMCore
ConstantFold.cpp
Constants.cpp
Core.cpp
- DebugLoc.cpp
DebugInfoProbe.cpp
+ DebugLoc.cpp
Dominators.cpp
Function.cpp
+ GCOV.cpp
GVMaterializer.cpp
Globals.cpp
IRBuilder.cpp
@@ -36,3 +37,5 @@ add_llvm_library(LLVMCore
ValueTypes.cpp
Verifier.cpp
)
+
+add_llvm_library_dependencies(LLVMCore LLVMSupport)
diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp
index 323e2a2..30bae71 100644
--- a/lib/VMCore/ConstantFold.cpp
+++ b/lib/VMCore/ConstantFold.cpp
@@ -42,7 +42,7 @@ using namespace llvm;
/// specified vector type. At this point, we know that the elements of the
/// input vector constant are all simple integer or FP values.
static Constant *BitCastConstantVector(ConstantVector *CV,
- const VectorType *DstTy) {
+ VectorType *DstTy) {
if (CV->isAllOnesValue()) return Constant::getAllOnesValue(DstTy);
if (CV->isNullValue()) return Constant::getNullValue(DstTy);
@@ -63,7 +63,7 @@ static Constant *BitCastConstantVector(ConstantVector *CV,
// Bitcast each element now.
std::vector<Constant*> Result;
- const Type *DstEltTy = DstTy->getElementType();
+ Type *DstEltTy = DstTy->getElementType();
for (unsigned i = 0; i != NumElts; ++i)
Result.push_back(ConstantExpr::getBitCast(CV->getOperand(i),
DstEltTy));
@@ -78,15 +78,15 @@ static unsigned
foldConstantCastPair(
unsigned opc, ///< opcode of the second cast constant expression
ConstantExpr *Op, ///< the first cast constant expression
- const Type *DstTy ///< desintation type of the first cast
+ Type *DstTy ///< desintation type of the first cast
) {
assert(Op && Op->isCast() && "Can't fold cast of cast without a cast!");
assert(DstTy && DstTy->isFirstClassType() && "Invalid cast destination type");
assert(CastInst::isCast(opc) && "Invalid cast opcode");
// The the types and opcodes for the two Cast constant expressions
- const Type *SrcTy = Op->getOperand(0)->getType();
- const Type *MidTy = Op->getType();
+ Type *SrcTy = Op->getOperand(0)->getType();
+ Type *MidTy = Op->getType();
Instruction::CastOps firstOp = Instruction::CastOps(Op->getOpcode());
Instruction::CastOps secondOp = Instruction::CastOps(opc);
@@ -95,27 +95,27 @@ foldConstantCastPair(
Type::getInt64Ty(DstTy->getContext()));
}
-static Constant *FoldBitCast(Constant *V, const Type *DestTy) {
- const Type *SrcTy = V->getType();
+static Constant *FoldBitCast(Constant *V, Type *DestTy) {
+ Type *SrcTy = V->getType();
if (SrcTy == DestTy)
return V; // no-op cast
// Check to see if we are casting a pointer to an aggregate to a pointer to
// the first element. If so, return the appropriate GEP instruction.
- if (const PointerType *PTy = dyn_cast<PointerType>(V->getType()))
- if (const PointerType *DPTy = dyn_cast<PointerType>(DestTy))
+ if (PointerType *PTy = dyn_cast<PointerType>(V->getType()))
+ if (PointerType *DPTy = dyn_cast<PointerType>(DestTy))
if (PTy->getAddressSpace() == DPTy->getAddressSpace()) {
SmallVector<Value*, 8> IdxList;
Value *Zero =
Constant::getNullValue(Type::getInt32Ty(DPTy->getContext()));
IdxList.push_back(Zero);
- const Type *ElTy = PTy->getElementType();
+ Type *ElTy = PTy->getElementType();
while (ElTy != DPTy->getElementType()) {
- if (const StructType *STy = dyn_cast<StructType>(ElTy)) {
+ if (StructType *STy = dyn_cast<StructType>(ElTy)) {
if (STy->getNumElements() == 0) break;
ElTy = STy->getElementType(0);
IdxList.push_back(Zero);
- } else if (const SequentialType *STy =
+ } else if (SequentialType *STy =
dyn_cast<SequentialType>(ElTy)) {
if (ElTy->isPointerTy()) break; // Can't index into pointers!
ElTy = STy->getElementType();
@@ -127,14 +127,13 @@ static Constant *FoldBitCast(Constant *V, const Type *DestTy) {
if (ElTy == DPTy->getElementType())
// This GEP is inbounds because all indices are zero.
- return ConstantExpr::getInBoundsGetElementPtr(V, &IdxList[0],
- IdxList.size());
+ return ConstantExpr::getInBoundsGetElementPtr(V, IdxList);
}
// Handle casts from one vector constant to another. We know that the src
// and dest type have the same size (otherwise its an illegal cast).
- if (const VectorType *DestPTy = dyn_cast<VectorType>(DestTy)) {
- if (const VectorType *SrcTy = dyn_cast<VectorType>(V->getType())) {
+ if (VectorType *DestPTy = dyn_cast<VectorType>(DestTy)) {
+ if (VectorType *SrcTy = dyn_cast<VectorType>(V->getType())) {
assert(DestPTy->getBitWidth() == SrcTy->getBitWidth() &&
"Not cast between same sized vectors!");
SrcTy = NULL;
@@ -332,15 +331,15 @@ static Constant *ExtractConstantBytes(Constant *C, unsigned ByteStart,
/// return null if no factoring was possible, to avoid endlessly
/// bouncing an unfoldable expression back into the top-level folder.
///
-static Constant *getFoldedSizeOf(const Type *Ty, const Type *DestTy,
+static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy,
bool Folded) {
- if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
+ if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
Constant *N = ConstantInt::get(DestTy, ATy->getNumElements());
Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true);
return ConstantExpr::getNUWMul(E, N);
}
- if (const StructType *STy = dyn_cast<StructType>(Ty))
+ if (StructType *STy = dyn_cast<StructType>(Ty))
if (!STy->isPacked()) {
unsigned NumElems = STy->getNumElements();
// An empty struct has size zero.
@@ -364,7 +363,7 @@ static Constant *getFoldedSizeOf(const Type *Ty, const Type *DestTy,
// Pointer size doesn't depend on the pointee type, so canonicalize them
// to an arbitrary pointee.
- if (const PointerType *PTy = dyn_cast<PointerType>(Ty))
+ if (PointerType *PTy = dyn_cast<PointerType>(Ty))
if (!PTy->getElementType()->isIntegerTy(1))
return
getFoldedSizeOf(PointerType::get(IntegerType::get(PTy->getContext(), 1),
@@ -389,11 +388,11 @@ static Constant *getFoldedSizeOf(const Type *Ty, const Type *DestTy,
/// return null if no factoring was possible, to avoid endlessly
/// bouncing an unfoldable expression back into the top-level folder.
///
-static Constant *getFoldedAlignOf(const Type *Ty, const Type *DestTy,
+static Constant *getFoldedAlignOf(Type *Ty, Type *DestTy,
bool Folded) {
// The alignment of an array is equal to the alignment of the
// array element. Note that this is not always true for vectors.
- if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
+ if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
Constant *C = ConstantExpr::getAlignOf(ATy->getElementType());
C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false,
DestTy,
@@ -402,7 +401,7 @@ static Constant *getFoldedAlignOf(const Type *Ty, const Type *DestTy,
return C;
}
- if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+ if (StructType *STy = dyn_cast<StructType>(Ty)) {
// Packed structs always have an alignment of 1.
if (STy->isPacked())
return ConstantInt::get(DestTy, 1);
@@ -429,7 +428,7 @@ static Constant *getFoldedAlignOf(const Type *Ty, const Type *DestTy,
// Pointer alignment doesn't depend on the pointee type, so canonicalize them
// to an arbitrary pointee.
- if (const PointerType *PTy = dyn_cast<PointerType>(Ty))
+ if (PointerType *PTy = dyn_cast<PointerType>(Ty))
if (!PTy->getElementType()->isIntegerTy(1))
return
getFoldedAlignOf(PointerType::get(IntegerType::get(PTy->getContext(),
@@ -455,10 +454,10 @@ static Constant *getFoldedAlignOf(const Type *Ty, const Type *DestTy,
/// return null if no factoring was possible, to avoid endlessly
/// bouncing an unfoldable expression back into the top-level folder.
///
-static Constant *getFoldedOffsetOf(const Type *Ty, Constant *FieldNo,
- const Type *DestTy,
+static Constant *getFoldedOffsetOf(Type *Ty, Constant *FieldNo,
+ Type *DestTy,
bool Folded) {
- if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
+ if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
Constant *N = ConstantExpr::getCast(CastInst::getCastOpcode(FieldNo, false,
DestTy, false),
FieldNo, DestTy);
@@ -466,7 +465,7 @@ static Constant *getFoldedOffsetOf(const Type *Ty, Constant *FieldNo,
return ConstantExpr::getNUWMul(E, N);
}
- if (const StructType *STy = dyn_cast<StructType>(Ty))
+ if (StructType *STy = dyn_cast<StructType>(Ty))
if (!STy->isPacked()) {
unsigned NumElems = STy->getNumElements();
// An empty struct has no members.
@@ -506,7 +505,7 @@ static Constant *getFoldedOffsetOf(const Type *Ty, Constant *FieldNo,
}
Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
- const Type *DestTy) {
+ Type *DestTy) {
if (isa<UndefValue>(V)) {
// zext(undef) = 0, because the top bits will be zero.
// sext(undef) = 0, because the top bits will all be the same.
@@ -554,8 +553,8 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
cast<VectorType>(DestTy)->getNumElements() ==
CV->getType()->getNumElements()) {
std::vector<Constant*> res;
- const VectorType *DestVecTy = cast<VectorType>(DestTy);
- const Type *DstEltTy = DestVecTy->getElementType();
+ VectorType *DestVecTy = cast<VectorType>(DestTy);
+ Type *DstEltTy = DestVecTy->getElementType();
for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i)
res.push_back(ConstantExpr::getCast(opc,
CV->getOperand(i), DstEltTy));
@@ -590,7 +589,7 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
uint32_t DestBitWidth = cast<IntegerType>(DestTy)->getBitWidth();
(void) V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI,
APFloat::rmTowardZero, &ignored);
- APInt Val(DestBitWidth, 2, x);
+ APInt Val(DestBitWidth, x);
return ConstantInt::get(FPC->getContext(), Val);
}
return 0; // Can't fold.
@@ -608,7 +607,7 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
if (CE->getOpcode() == Instruction::GetElementPtr &&
CE->getOperand(0)->isNullValue()) {
- const Type *Ty =
+ Type *Ty =
cast<PointerType>(CE->getOperand(0)->getType())->getElementType();
if (CE->getNumOperands() == 2) {
// Handle a sizeof-like expression.
@@ -623,7 +622,7 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
} else if (CE->getNumOperands() == 3 &&
CE->getOperand(1)->isNullValue()) {
// Handle an alignof-like expression.
- if (const StructType *STy = dyn_cast<StructType>(Ty))
+ if (StructType *STy = dyn_cast<StructType>(Ty))
if (!STy->isPacked()) {
ConstantInt *CI = cast<ConstantInt>(CE->getOperand(2));
if (CI->isOne() &&
@@ -701,7 +700,7 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
if (CondV->isAllOnesValue()) return V1;
- const VectorType *VTy = cast<VectorType>(V1->getType());
+ VectorType *VTy = cast<VectorType>(V1->getType());
ConstantVector *CP1 = dyn_cast<ConstantVector>(V1);
ConstantVector *CP2 = dyn_cast<ConstantVector>(V2);
@@ -709,7 +708,7 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
(CP2 || isa<ConstantAggregateZero>(V2))) {
// Find the element type of the returned vector
- const Type *EltTy = VTy->getElementType();
+ Type *EltTy = VTy->getElementType();
unsigned NumElem = VTy->getNumElements();
std::vector<Constant*> Res(NumElem);
@@ -762,10 +761,14 @@ Constant *llvm::ConstantFoldExtractElementInstruction(Constant *Val,
if (ConstantVector *CVal = dyn_cast<ConstantVector>(Val)) {
if (ConstantInt *CIdx = dyn_cast<ConstantInt>(Idx)) {
+ uint64_t Index = CIdx->getZExtValue();
+ if (Index >= CVal->getNumOperands())
+ // ee({w,x,y,z}, wrong_value) -> undef
+ return UndefValue::get(cast<VectorType>(Val->getType())->getElementType());
return CVal->getOperand(CIdx->getZExtValue());
} else if (isa<UndefValue>(Idx)) {
- // ee({w,x,y,z}, undef) -> w (an arbitrary value).
- return CVal->getOperand(0);
+ // ee({w,x,y,z}, undef) -> undef
+ return UndefValue::get(cast<VectorType>(Val->getType())->getElementType());
}
}
return 0;
@@ -834,7 +837,7 @@ static Constant *GetVectorElement(Constant *C, unsigned EltNo) {
if (ConstantVector *CV = dyn_cast<ConstantVector>(C))
return CV->getOperand(EltNo);
- const Type *EltTy = cast<VectorType>(C->getType())->getElementType();
+ Type *EltTy = cast<VectorType>(C->getType())->getElementType();
if (isa<ConstantAggregateZero>(C))
return Constant::getNullValue(EltTy);
if (isa<UndefValue>(C))
@@ -850,7 +853,7 @@ Constant *llvm::ConstantFoldShuffleVectorInstruction(Constant *V1,
unsigned MaskNumElts = cast<VectorType>(Mask->getType())->getNumElements();
unsigned SrcNumElts = cast<VectorType>(V1->getType())->getNumElements();
- const Type *EltTy = cast<VectorType>(V1->getType())->getElementType();
+ Type *EltTy = cast<VectorType>(V1->getType())->getElementType();
// Loop over the shuffle mask, evaluating each element.
SmallVector<Constant*, 32> Result;
@@ -922,16 +925,16 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
// Otherwise break the aggregate undef into multiple undefs and do
// the insertion.
- const CompositeType *AggTy = cast<CompositeType>(Agg->getType());
+ CompositeType *AggTy = cast<CompositeType>(Agg->getType());
unsigned numOps;
- if (const ArrayType *AR = dyn_cast<ArrayType>(AggTy))
+ if (ArrayType *AR = dyn_cast<ArrayType>(AggTy))
numOps = AR->getNumElements();
else
numOps = cast<StructType>(AggTy)->getNumElements();
std::vector<Constant*> Ops(numOps);
for (unsigned i = 0; i < numOps; ++i) {
- const Type *MemberTy = AggTy->getTypeAtIndex(i);
+ Type *MemberTy = AggTy->getTypeAtIndex(i);
Constant *Op =
(Idxs[0] == i) ?
ConstantFoldInsertValueInstruction(UndefValue::get(MemberTy),
@@ -940,7 +943,7 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
Ops[i] = Op;
}
- if (const StructType* ST = dyn_cast<StructType>(AggTy))
+ if (StructType* ST = dyn_cast<StructType>(AggTy))
return ConstantStruct::get(ST, Ops);
return ConstantArray::get(cast<ArrayType>(AggTy), Ops);
}
@@ -953,16 +956,16 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
// Otherwise break the aggregate zero into multiple zeros and do
// the insertion.
- const CompositeType *AggTy = cast<CompositeType>(Agg->getType());
+ CompositeType *AggTy = cast<CompositeType>(Agg->getType());
unsigned numOps;
- if (const ArrayType *AR = dyn_cast<ArrayType>(AggTy))
+ if (ArrayType *AR = dyn_cast<ArrayType>(AggTy))
numOps = AR->getNumElements();
else
numOps = cast<StructType>(AggTy)->getNumElements();
std::vector<Constant*> Ops(numOps);
for (unsigned i = 0; i < numOps; ++i) {
- const Type *MemberTy = AggTy->getTypeAtIndex(i);
+ Type *MemberTy = AggTy->getTypeAtIndex(i);
Constant *Op =
(Idxs[0] == i) ?
ConstantFoldInsertValueInstruction(Constant::getNullValue(MemberTy),
@@ -971,7 +974,7 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
Ops[i] = Op;
}
- if (const StructType *ST = dyn_cast<StructType>(AggTy))
+ if (StructType *ST = dyn_cast<StructType>(AggTy))
return ConstantStruct::get(ST, Ops);
return ConstantArray::get(cast<ArrayType>(AggTy), Ops);
}
@@ -986,7 +989,7 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
Ops[i] = Op;
}
- if (const StructType* ST = dyn_cast<StructType>(Agg->getType()))
+ if (StructType* ST = dyn_cast<StructType>(Agg->getType()))
return ConstantStruct::get(ST, Ops);
return ConstantArray::get(cast<ArrayType>(Agg->getType()), Ops);
}
@@ -1265,13 +1268,13 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
return ConstantFP::get(C1->getContext(), C3V);
}
}
- } else if (const VectorType *VTy = dyn_cast<VectorType>(C1->getType())) {
+ } else if (VectorType *VTy = dyn_cast<VectorType>(C1->getType())) {
ConstantVector *CP1 = dyn_cast<ConstantVector>(C1);
ConstantVector *CP2 = dyn_cast<ConstantVector>(C2);
if ((CP1 != NULL || isa<ConstantAggregateZero>(C1)) &&
(CP2 != NULL || isa<ConstantAggregateZero>(C2))) {
std::vector<Constant*> Res;
- const Type* EltTy = VTy->getElementType();
+ Type* EltTy = VTy->getElementType();
Constant *C1 = 0;
Constant *C2 = 0;
switch (Opcode) {
@@ -1461,8 +1464,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
/// isZeroSizedType - This type is zero sized if its an array or structure of
/// zero sized types. The only leaf zero sized type is an empty structure.
-static bool isMaybeZeroSizedType(const Type *Ty) {
- if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+static bool isMaybeZeroSizedType(Type *Ty) {
+ if (StructType *STy = dyn_cast<StructType>(Ty)) {
if (STy->isOpaque()) return true; // Can't say.
// If all of elements have zero size, this does too.
@@ -1470,7 +1473,7 @@ static bool isMaybeZeroSizedType(const Type *Ty) {
if (!isMaybeZeroSizedType(STy->getElementType(i))) return false;
return true;
- } else if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
+ } else if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
return isMaybeZeroSizedType(ATy->getElementType());
}
return false;
@@ -1483,7 +1486,7 @@ static bool isMaybeZeroSizedType(const Type *Ty) {
/// first is less than the second, return -1, if the second is less than the
/// first, return 1. If the constants are not integral, return -2.
///
-static int IdxCompare(Constant *C1, Constant *C2, const Type *ElTy) {
+static int IdxCompare(Constant *C1, Constant *C2, Type *ElTy) {
if (C1 == C2) return 0;
// Ok, we found a different index. If they are not ConstantInt, we can't do
@@ -1832,8 +1835,8 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2,
Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
Constant *C1, Constant *C2) {
- const Type *ResultTy;
- if (const VectorType *VT = dyn_cast<VectorType>(C1->getType()))
+ Type *ResultTy;
+ if (VectorType *VT = dyn_cast<VectorType>(C1->getType()))
ResultTy = VectorType::get(Type::getInt1Ty(C1->getContext()),
VT->getNumElements());
else
@@ -2146,9 +2149,9 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
/// isInBoundsIndices - Test whether the given sequence of *normalized* indices
/// is "inbounds".
template<typename IndexTy>
-static bool isInBoundsIndices(IndexTy const *Idxs, size_t NumIdx) {
+static bool isInBoundsIndices(ArrayRef<IndexTy> Idxs) {
// No indices means nothing that could be out of bounds.
- if (NumIdx == 0) return true;
+ if (Idxs.empty()) return true;
// If the first index is zero, it's in bounds.
if (cast<Constant>(Idxs[0])->isNullValue()) return true;
@@ -2157,7 +2160,7 @@ static bool isInBoundsIndices(IndexTy const *Idxs, size_t NumIdx) {
// by the one-past-the-end rule.
if (!cast<ConstantInt>(Idxs[0])->isOne())
return false;
- for (unsigned i = 1, e = NumIdx; i != e; ++i)
+ for (unsigned i = 1, e = Idxs.size(); i != e; ++i)
if (!cast<Constant>(Idxs[i])->isNullValue())
return false;
return true;
@@ -2166,31 +2169,29 @@ static bool isInBoundsIndices(IndexTy const *Idxs, size_t NumIdx) {
template<typename IndexTy>
static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
bool inBounds,
- IndexTy const *Idxs,
- unsigned NumIdx) {
- if (NumIdx == 0) return C;
+ ArrayRef<IndexTy> Idxs) {
+ if (Idxs.empty()) return C;
Constant *Idx0 = cast<Constant>(Idxs[0]);
- if ((NumIdx == 1 && Idx0->isNullValue()))
+ if ((Idxs.size() == 1 && Idx0->isNullValue()))
return C;
if (isa<UndefValue>(C)) {
- const PointerType *Ptr = cast<PointerType>(C->getType());
- const Type *Ty = GetElementPtrInst::getIndexedType(Ptr, Idxs, Idxs+NumIdx);
+ PointerType *Ptr = cast<PointerType>(C->getType());
+ Type *Ty = GetElementPtrInst::getIndexedType(Ptr, Idxs);
assert(Ty != 0 && "Invalid indices for GEP!");
return UndefValue::get(PointerType::get(Ty, Ptr->getAddressSpace()));
}
if (C->isNullValue()) {
bool isNull = true;
- for (unsigned i = 0, e = NumIdx; i != e; ++i)
+ for (unsigned i = 0, e = Idxs.size(); i != e; ++i)
if (!cast<Constant>(Idxs[i])->isNullValue()) {
isNull = false;
break;
}
if (isNull) {
- const PointerType *Ptr = cast<PointerType>(C->getType());
- const Type *Ty = GetElementPtrInst::getIndexedType(Ptr, Idxs,
- Idxs+NumIdx);
+ PointerType *Ptr = cast<PointerType>(C->getType());
+ Type *Ty = GetElementPtrInst::getIndexedType(Ptr, Idxs);
assert(Ty != 0 && "Invalid indices for GEP!");
return ConstantPointerNull::get(PointerType::get(Ty,
Ptr->getAddressSpace()));
@@ -2203,14 +2204,14 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
// getelementptr instructions into a single instruction.
//
if (CE->getOpcode() == Instruction::GetElementPtr) {
- const Type *LastTy = 0;
+ Type *LastTy = 0;
for (gep_type_iterator I = gep_type_begin(CE), E = gep_type_end(CE);
I != E; ++I)
LastTy = *I;
if ((LastTy && LastTy->isArrayTy()) || Idx0->isNullValue()) {
SmallVector<Value*, 16> NewIndices;
- NewIndices.reserve(NumIdx + CE->getNumOperands());
+ NewIndices.reserve(Idxs.size() + CE->getNumOperands());
for (unsigned i = 1, e = CE->getNumOperands()-1; i != e; ++i)
NewIndices.push_back(CE->getOperand(i));
@@ -2219,9 +2220,9 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
Constant *Combined = CE->getOperand(CE->getNumOperands()-1);
// Otherwise it must be an array.
if (!Idx0->isNullValue()) {
- const Type *IdxTy = Combined->getType();
+ Type *IdxTy = Combined->getType();
if (IdxTy != Idx0->getType()) {
- const Type *Int64Ty = Type::getInt64Ty(IdxTy->getContext());
+ Type *Int64Ty = Type::getInt64Ty(IdxTy->getContext());
Constant *C1 = ConstantExpr::getSExtOrBitCast(Idx0, Int64Ty);
Constant *C2 = ConstantExpr::getSExtOrBitCast(Combined, Int64Ty);
Combined = ConstantExpr::get(Instruction::Add, C1, C2);
@@ -2232,14 +2233,11 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
}
NewIndices.push_back(Combined);
- NewIndices.append(Idxs+1, Idxs+NumIdx);
- return (inBounds && cast<GEPOperator>(CE)->isInBounds()) ?
- ConstantExpr::getInBoundsGetElementPtr(CE->getOperand(0),
- &NewIndices[0],
- NewIndices.size()) :
- ConstantExpr::getGetElementPtr(CE->getOperand(0),
- &NewIndices[0],
- NewIndices.size());
+ NewIndices.append(Idxs.begin() + 1, Idxs.end());
+ return
+ ConstantExpr::getGetElementPtr(CE->getOperand(0), NewIndices,
+ inBounds &&
+ cast<GEPOperator>(CE)->isInBounds());
}
}
@@ -2248,18 +2246,16 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
// i64 0, i64 0)
// To: i32* getelementptr ([3 x i32]* %X, i64 0, i64 0)
//
- if (CE->isCast() && NumIdx > 1 && Idx0->isNullValue()) {
- if (const PointerType *SPT =
+ if (CE->isCast() && Idxs.size() > 1 && Idx0->isNullValue()) {
+ if (PointerType *SPT =
dyn_cast<PointerType>(CE->getOperand(0)->getType()))
- if (const ArrayType *SAT = dyn_cast<ArrayType>(SPT->getElementType()))
- if (const ArrayType *CAT =
+ if (ArrayType *SAT = dyn_cast<ArrayType>(SPT->getElementType()))
+ if (ArrayType *CAT =
dyn_cast<ArrayType>(cast<PointerType>(C->getType())->getElementType()))
if (CAT->getElementType() == SAT->getElementType())
- return inBounds ?
- ConstantExpr::getInBoundsGetElementPtr(
- (Constant*)CE->getOperand(0), Idxs, NumIdx) :
- ConstantExpr::getGetElementPtr(
- (Constant*)CE->getOperand(0), Idxs, NumIdx);
+ return
+ ConstantExpr::getGetElementPtr((Constant*)CE->getOperand(0),
+ Idxs, inBounds);
}
}
@@ -2268,19 +2264,19 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
// out into preceding dimensions.
bool Unknown = false;
SmallVector<Constant *, 8> NewIdxs;
- const Type *Ty = C->getType();
- const Type *Prev = 0;
- for (unsigned i = 0; i != NumIdx;
+ Type *Ty = C->getType();
+ Type *Prev = 0;
+ for (unsigned i = 0, e = Idxs.size(); i != e;
Prev = Ty, Ty = cast<CompositeType>(Ty)->getTypeAtIndex(Idxs[i]), ++i) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(Idxs[i])) {
- if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty))
+ if (ArrayType *ATy = dyn_cast<ArrayType>(Ty))
if (ATy->getNumElements() <= INT64_MAX &&
ATy->getNumElements() != 0 &&
CI->getSExtValue() >= (int64_t)ATy->getNumElements()) {
if (isa<SequentialType>(Prev)) {
// It's out of range, but we can factor it into the prior
// dimension.
- NewIdxs.resize(NumIdx);
+ NewIdxs.resize(Idxs.size());
ConstantInt *Factor = ConstantInt::get(CI->getType(),
ATy->getNumElements());
NewIdxs[i] = ConstantExpr::getSRem(CI, Factor);
@@ -2312,33 +2308,28 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
// If we did any factoring, start over with the adjusted indices.
if (!NewIdxs.empty()) {
- for (unsigned i = 0; i != NumIdx; ++i)
+ for (unsigned i = 0, e = Idxs.size(); i != e; ++i)
if (!NewIdxs[i]) NewIdxs[i] = cast<Constant>(Idxs[i]);
- return inBounds ?
- ConstantExpr::getInBoundsGetElementPtr(C, NewIdxs.data(),
- NewIdxs.size()) :
- ConstantExpr::getGetElementPtr(C, NewIdxs.data(), NewIdxs.size());
+ return ConstantExpr::getGetElementPtr(C, NewIdxs, inBounds);
}
// If all indices are known integers and normalized, we can do a simple
// check for the "inbounds" property.
if (!Unknown && !inBounds &&
- isa<GlobalVariable>(C) && isInBoundsIndices(Idxs, NumIdx))
- return ConstantExpr::getInBoundsGetElementPtr(C, Idxs, NumIdx);
+ isa<GlobalVariable>(C) && isInBoundsIndices(Idxs))
+ return ConstantExpr::getInBoundsGetElementPtr(C, Idxs);
return 0;
}
Constant *llvm::ConstantFoldGetElementPtr(Constant *C,
bool inBounds,
- Constant* const *Idxs,
- unsigned NumIdx) {
- return ConstantFoldGetElementPtrImpl(C, inBounds, Idxs, NumIdx);
+ ArrayRef<Constant *> Idxs) {
+ return ConstantFoldGetElementPtrImpl(C, inBounds, Idxs);
}
Constant *llvm::ConstantFoldGetElementPtr(Constant *C,
bool inBounds,
- Value* const *Idxs,
- unsigned NumIdx) {
- return ConstantFoldGetElementPtrImpl(C, inBounds, Idxs, NumIdx);
+ ArrayRef<Value *> Idxs) {
+ return ConstantFoldGetElementPtrImpl(C, inBounds, Idxs);
}
diff --git a/lib/VMCore/ConstantFold.h b/lib/VMCore/ConstantFold.h
index 653a1c3..e12f27a 100644
--- a/lib/VMCore/ConstantFold.h
+++ b/lib/VMCore/ConstantFold.h
@@ -30,7 +30,7 @@ namespace llvm {
Constant *ConstantFoldCastInstruction(
unsigned opcode, ///< The opcode of the cast
Constant *V, ///< The source constant
- const Type *DestTy ///< The destination type
+ Type *DestTy ///< The destination type
);
Constant *ConstantFoldSelectInstruction(Constant *Cond,
Constant *V1, Constant *V2);
@@ -48,9 +48,9 @@ namespace llvm {
Constant *ConstantFoldCompareInstruction(unsigned short predicate,
Constant *C1, Constant *C2);
Constant *ConstantFoldGetElementPtr(Constant *C, bool inBounds,
- Constant* const *Idxs, unsigned NumIdx);
+ ArrayRef<Constant *> Idxs);
Constant *ConstantFoldGetElementPtr(Constant *C, bool inBounds,
- Value* const *Idxs, unsigned NumIdx);
+ ArrayRef<Value *> Idxs);
} // End llvm namespace
#endif
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index 316c884..a84a046 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -62,8 +62,23 @@ bool Constant::isNullValue() const {
return isa<ConstantAggregateZero>(this) || isa<ConstantPointerNull>(this);
}
+bool Constant::isAllOnesValue() const {
+ // Check for -1 integers
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
+ return CI->isMinusOne();
+
+ // Check for FP which are bitcasted from -1 integers
+ if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
+ return CFP->getValueAPF().bitcastToAPInt().isAllOnesValue();
+
+ // Check for constant vectors
+ if (const ConstantVector *CV = dyn_cast<ConstantVector>(this))
+ return CV->isAllOnesValue();
+
+ return false;
+}
// Constructor to create a '0' constant of arbitrary type...
-Constant *Constant::getNullValue(const Type *Ty) {
+Constant *Constant::getNullValue(Type *Ty) {
switch (Ty->getTypeID()) {
case Type::IntegerTyID:
return ConstantInt::get(Ty, 0);
@@ -90,30 +105,30 @@ Constant *Constant::getNullValue(const Type *Ty) {
return ConstantAggregateZero::get(Ty);
default:
// Function, Label, or Opaque type?
- assert(!"Cannot create a null constant of that type!");
+ assert(0 && "Cannot create a null constant of that type!");
return 0;
}
}
-Constant *Constant::getIntegerValue(const Type *Ty, const APInt &V) {
- const Type *ScalarTy = Ty->getScalarType();
+Constant *Constant::getIntegerValue(Type *Ty, const APInt &V) {
+ Type *ScalarTy = Ty->getScalarType();
// Create the base integer constant.
Constant *C = ConstantInt::get(Ty->getContext(), V);
// Convert an integer to a pointer, if necessary.
- if (const PointerType *PTy = dyn_cast<PointerType>(ScalarTy))
+ if (PointerType *PTy = dyn_cast<PointerType>(ScalarTy))
C = ConstantExpr::getIntToPtr(C, PTy);
// Broadcast a scalar to a vector, if necessary.
- if (const VectorType *VTy = dyn_cast<VectorType>(Ty))
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
C = ConstantVector::get(std::vector<Constant *>(VTy->getNumElements(), C));
return C;
}
-Constant *Constant::getAllOnesValue(const Type *Ty) {
- if (const IntegerType *ITy = dyn_cast<IntegerType>(Ty))
+Constant *Constant::getAllOnesValue(Type *Ty) {
+ if (IntegerType *ITy = dyn_cast<IntegerType>(Ty))
return ConstantInt::get(Ty->getContext(),
APInt::getAllOnesValue(ITy->getBitWidth()));
@@ -124,9 +139,9 @@ Constant *Constant::getAllOnesValue(const Type *Ty) {
}
SmallVector<Constant*, 16> Elts;
- const VectorType *VTy = cast<VectorType>(Ty);
+ VectorType *VTy = cast<VectorType>(Ty);
Elts.resize(VTy->getNumElements(), getAllOnesValue(VTy->getElementType()));
- assert(Elts[0] && "Not a vector integer type!");
+ assert(Elts[0] && "Invalid AllOnes value!");
return cast<ConstantVector>(ConstantVector::get(Elts));
}
@@ -269,7 +284,7 @@ void Constant::getVectorElements(SmallVectorImpl<Constant*> &Elts) const {
return;
}
- const VectorType *VT = cast<VectorType>(getType());
+ VectorType *VT = cast<VectorType>(getType());
if (isa<ConstantAggregateZero>(this)) {
Elts.assign(VT->getNumElements(),
Constant::getNullValue(VT->getElementType()));
@@ -343,7 +358,7 @@ void Constant::removeDeadConstantUsers() const {
// ConstantInt
//===----------------------------------------------------------------------===//
-ConstantInt::ConstantInt(const IntegerType *Ty, const APInt& V)
+ConstantInt::ConstantInt(IntegerType *Ty, const APInt& V)
: Constant(Ty, ConstantIntVal, 0, 0), Val(V) {
assert(V.getBitWidth() == Ty->getBitWidth() && "Invalid constant for type");
}
@@ -362,8 +377,8 @@ ConstantInt *ConstantInt::getFalse(LLVMContext &Context) {
return pImpl->TheFalseVal;
}
-Constant *ConstantInt::getTrue(const Type *Ty) {
- const VectorType *VTy = dyn_cast<VectorType>(Ty);
+Constant *ConstantInt::getTrue(Type *Ty) {
+ VectorType *VTy = dyn_cast<VectorType>(Ty);
if (!VTy) {
assert(Ty->isIntegerTy(1) && "True must be i1 or vector of i1.");
return ConstantInt::getTrue(Ty->getContext());
@@ -375,8 +390,8 @@ Constant *ConstantInt::getTrue(const Type *Ty) {
return ConstantVector::get(Splat);
}
-Constant *ConstantInt::getFalse(const Type *Ty) {
- const VectorType *VTy = dyn_cast<VectorType>(Ty);
+Constant *ConstantInt::getFalse(Type *Ty) {
+ VectorType *VTy = dyn_cast<VectorType>(Ty);
if (!VTy) {
assert(Ty->isIntegerTy(1) && "False must be i1 or vector of i1.");
return ConstantInt::getFalse(Ty->getContext());
@@ -396,7 +411,7 @@ Constant *ConstantInt::getFalse(const Type *Ty) {
// invariant which generates an assertion.
ConstantInt *ConstantInt::get(LLVMContext &Context, const APInt &V) {
// Get the corresponding integer type for the bit width of the value.
- const IntegerType *ITy = IntegerType::get(Context, V.getBitWidth());
+ IntegerType *ITy = IntegerType::get(Context, V.getBitWidth());
// get an existing value or the insertion position
DenseMapAPIntKeyInfo::KeyTy Key(V, ITy);
ConstantInt *&Slot = Context.pImpl->IntConstants[Key];
@@ -404,44 +419,44 @@ ConstantInt *ConstantInt::get(LLVMContext &Context, const APInt &V) {
return Slot;
}
-Constant *ConstantInt::get(const Type *Ty, uint64_t V, bool isSigned) {
+Constant *ConstantInt::get(Type *Ty, uint64_t V, bool isSigned) {
Constant *C = get(cast<IntegerType>(Ty->getScalarType()), V, isSigned);
// For vectors, broadcast the value.
- if (const VectorType *VTy = dyn_cast<VectorType>(Ty))
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
return ConstantVector::get(SmallVector<Constant*,
16>(VTy->getNumElements(), C));
return C;
}
-ConstantInt* ConstantInt::get(const IntegerType* Ty, uint64_t V,
+ConstantInt* ConstantInt::get(IntegerType* Ty, uint64_t V,
bool isSigned) {
return get(Ty->getContext(), APInt(Ty->getBitWidth(), V, isSigned));
}
-ConstantInt* ConstantInt::getSigned(const IntegerType* Ty, int64_t V) {
+ConstantInt* ConstantInt::getSigned(IntegerType* Ty, int64_t V) {
return get(Ty, V, true);
}
-Constant *ConstantInt::getSigned(const Type *Ty, int64_t V) {
+Constant *ConstantInt::getSigned(Type *Ty, int64_t V) {
return get(Ty, V, true);
}
-Constant *ConstantInt::get(const Type* Ty, const APInt& V) {
+Constant *ConstantInt::get(Type* Ty, const APInt& V) {
ConstantInt *C = get(Ty->getContext(), V);
assert(C->getType() == Ty->getScalarType() &&
"ConstantInt type doesn't match the type implied by its value!");
// For vectors, broadcast the value.
- if (const VectorType *VTy = dyn_cast<VectorType>(Ty))
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
return ConstantVector::get(
SmallVector<Constant *, 16>(VTy->getNumElements(), C));
return C;
}
-ConstantInt* ConstantInt::get(const IntegerType* Ty, StringRef Str,
+ConstantInt* ConstantInt::get(IntegerType* Ty, StringRef Str,
uint8_t radix) {
return get(Ty->getContext(), APInt(Ty->getBitWidth(), Str, radix));
}
@@ -450,7 +465,7 @@ ConstantInt* ConstantInt::get(const IntegerType* Ty, StringRef Str,
// ConstantFP
//===----------------------------------------------------------------------===//
-static const fltSemantics *TypeToFloatSemantics(const Type *Ty) {
+static const fltSemantics *TypeToFloatSemantics(Type *Ty) {
if (Ty->isFloatTy())
return &APFloat::IEEEsingle;
if (Ty->isDoubleTy())
@@ -467,7 +482,7 @@ static const fltSemantics *TypeToFloatSemantics(const Type *Ty) {
/// get() - This returns a constant fp 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 double and as the target format.
-Constant *ConstantFP::get(const Type* Ty, double V) {
+Constant *ConstantFP::get(Type* Ty, double V) {
LLVMContext &Context = Ty->getContext();
APFloat FV(V);
@@ -477,7 +492,7 @@ Constant *ConstantFP::get(const Type* Ty, double V) {
Constant *C = get(Context, FV);
// For vectors, broadcast the value.
- if (const VectorType *VTy = dyn_cast<VectorType>(Ty))
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
return ConstantVector::get(
SmallVector<Constant *, 16>(VTy->getNumElements(), C));
@@ -485,14 +500,14 @@ Constant *ConstantFP::get(const Type* Ty, double V) {
}
-Constant *ConstantFP::get(const Type* Ty, StringRef Str) {
+Constant *ConstantFP::get(Type* Ty, StringRef Str) {
LLVMContext &Context = Ty->getContext();
APFloat FV(*TypeToFloatSemantics(Ty->getScalarType()), Str);
Constant *C = get(Context, FV);
// For vectors, broadcast the value.
- if (const VectorType *VTy = dyn_cast<VectorType>(Ty))
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
return ConstantVector::get(
SmallVector<Constant *, 16>(VTy->getNumElements(), C));
@@ -500,7 +515,7 @@ Constant *ConstantFP::get(const Type* Ty, StringRef Str) {
}
-ConstantFP* ConstantFP::getNegativeZero(const Type* Ty) {
+ConstantFP* ConstantFP::getNegativeZero(Type* Ty) {
LLVMContext &Context = Ty->getContext();
APFloat apf = cast <ConstantFP>(Constant::getNullValue(Ty))->getValueAPF();
apf.changeSign();
@@ -508,8 +523,8 @@ ConstantFP* ConstantFP::getNegativeZero(const Type* Ty) {
}
-Constant *ConstantFP::getZeroValueForNegation(const Type* Ty) {
- if (const VectorType *PTy = dyn_cast<VectorType>(Ty))
+Constant *ConstantFP::getZeroValueForNegation(Type* Ty) {
+ if (VectorType *PTy = dyn_cast<VectorType>(Ty))
if (PTy->getElementType()->isFloatingPointTy()) {
SmallVector<Constant*, 16> zeros(PTy->getNumElements(),
getNegativeZero(PTy->getElementType()));
@@ -532,7 +547,7 @@ ConstantFP* ConstantFP::get(LLVMContext &Context, const APFloat& V) {
ConstantFP *&Slot = pImpl->FPConstants[Key];
if (!Slot) {
- const Type *Ty;
+ Type *Ty;
if (&V.getSemantics() == &APFloat::IEEEsingle)
Ty = Type::getFloatTy(Context);
else if (&V.getSemantics() == &APFloat::IEEEdouble)
@@ -552,13 +567,13 @@ ConstantFP* ConstantFP::get(LLVMContext &Context, const APFloat& V) {
return Slot;
}
-ConstantFP *ConstantFP::getInfinity(const Type *Ty, bool Negative) {
+ConstantFP *ConstantFP::getInfinity(Type *Ty, bool Negative) {
const fltSemantics &Semantics = *TypeToFloatSemantics(Ty);
return ConstantFP::get(Ty->getContext(),
APFloat::getInf(Semantics, Negative));
}
-ConstantFP::ConstantFP(const Type *Ty, const APFloat& V)
+ConstantFP::ConstantFP(Type *Ty, const APFloat& V)
: Constant(Ty, ConstantFPVal, 0, 0), Val(V) {
assert(&V.getSemantics() == TypeToFloatSemantics(Ty) &&
"FP type Mismatch");
@@ -573,24 +588,19 @@ bool ConstantFP::isExactlyValue(const APFloat &V) const {
//===----------------------------------------------------------------------===//
-ConstantArray::ConstantArray(const ArrayType *T,
- const std::vector<Constant*> &V)
+ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V)
: Constant(T, ConstantArrayVal,
OperandTraits<ConstantArray>::op_end(this) - V.size(),
V.size()) {
assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant array");
- Use *OL = OperandList;
- for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
- I != E; ++I, ++OL) {
- Constant *C = *I;
- assert(C->getType() == T->getElementType() &&
+ for (unsigned i = 0, e = V.size(); i != e; ++i)
+ assert(V[i]->getType() == T->getElementType() &&
"Initializer for array element doesn't match array element type!");
- *OL = C;
- }
+ std::copy(V.begin(), V.end(), op_begin());
}
-Constant *ConstantArray::get(const ArrayType *Ty, ArrayRef<Constant*> V) {
+Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) {
for (unsigned i = 0, e = V.size(); i != e; ++i) {
assert(V[i]->getType() == Ty->getElementType() &&
"Wrong type in array element initializer");
@@ -653,25 +663,20 @@ StructType *ConstantStruct::getTypeForElements(ArrayRef<Constant*> V,
}
-ConstantStruct::ConstantStruct(const StructType *T,
- const std::vector<Constant*> &V)
+ConstantStruct::ConstantStruct(StructType *T, ArrayRef<Constant *> V)
: Constant(T, ConstantStructVal,
OperandTraits<ConstantStruct>::op_end(this) - V.size(),
V.size()) {
- assert((T->isOpaque() || V.size() == T->getNumElements()) &&
+ assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant structure");
- Use *OL = OperandList;
- for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
- I != E; ++I, ++OL) {
- Constant *C = *I;
- assert((T->isOpaque() || C->getType() == T->getElementType(I-V.begin())) &&
+ for (unsigned i = 0, e = V.size(); i != e; ++i)
+ assert((T->isOpaque() || V[i]->getType() == T->getElementType(i)) &&
"Initializer for struct element doesn't match struct element type!");
- *OL = C;
- }
+ std::copy(V.begin(), V.end(), op_begin());
}
// ConstantStruct accessors.
-Constant *ConstantStruct::get(const StructType *ST, ArrayRef<Constant*> V) {
+Constant *ConstantStruct::get(StructType *ST, ArrayRef<Constant*> V) {
// Create a ConstantAggregateZero value if all elements are zeros.
for (unsigned i = 0, e = V.size(); i != e; ++i)
if (!V[i]->isNullValue())
@@ -682,7 +687,7 @@ Constant *ConstantStruct::get(const StructType *ST, ArrayRef<Constant*> V) {
return ConstantAggregateZero::get(ST);
}
-Constant* ConstantStruct::get(const StructType *T, ...) {
+Constant *ConstantStruct::get(StructType *T, ...) {
va_list ap;
SmallVector<Constant*, 8> Values;
va_start(ap, T);
@@ -692,25 +697,20 @@ Constant* ConstantStruct::get(const StructType *T, ...) {
return get(T, Values);
}
-ConstantVector::ConstantVector(const VectorType *T,
- const std::vector<Constant*> &V)
+ConstantVector::ConstantVector(VectorType *T, ArrayRef<Constant *> V)
: Constant(T, ConstantVectorVal,
OperandTraits<ConstantVector>::op_end(this) - V.size(),
V.size()) {
- Use *OL = OperandList;
- for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
- I != E; ++I, ++OL) {
- Constant *C = *I;
- assert(C->getType() == T->getElementType() &&
+ for (size_t i = 0, e = V.size(); i != e; i++)
+ assert(V[i]->getType() == T->getElementType() &&
"Initializer for vector element doesn't match vector element type!");
- *OL = C;
- }
+ std::copy(V.begin(), V.end(), op_begin());
}
// ConstantVector accessors.
Constant *ConstantVector::get(ArrayRef<Constant*> V) {
assert(!V.empty() && "Vectors can't be empty");
- const VectorType *T = VectorType::get(V.front()->getType(), V.size());
+ VectorType *T = VectorType::get(V.front()->getType(), V.size());
LLVMContextImpl *pImpl = T->getContext().pImpl;
// If this is an all-undef or all-zero vector, return a
@@ -761,7 +761,7 @@ bool ConstantExpr::isGEPWithNoNotionalOverIndexing() const {
for (; GEPI != E; ++GEPI, ++OI) {
ConstantInt *CI = dyn_cast<ConstantInt>(*OI);
if (!CI) return false;
- if (const ArrayType *ATy = dyn_cast<ArrayType>(*GEPI))
+ if (ArrayType *ATy = dyn_cast<ArrayType>(*GEPI))
if (CI->getValue().getActiveBits() > 64 ||
CI->getZExtValue() >= ATy->getNumElements())
return false;
@@ -839,13 +839,13 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
Ops[i-1] = getOperand(i);
if (OpNo == 0)
- return cast<GEPOperator>(this)->isInBounds() ?
- ConstantExpr::getInBoundsGetElementPtr(Op, &Ops[0], Ops.size()) :
- ConstantExpr::getGetElementPtr(Op, &Ops[0], Ops.size());
+ return
+ ConstantExpr::getGetElementPtr(Op, Ops,
+ cast<GEPOperator>(this)->isInBounds());
Ops[OpNo-1] = Op;
- return cast<GEPOperator>(this)->isInBounds() ?
- ConstantExpr::getInBoundsGetElementPtr(getOperand(0), &Ops[0],Ops.size()):
- ConstantExpr::getGetElementPtr(getOperand(0), &Ops[0], Ops.size());
+ return
+ ConstantExpr::getGetElementPtr(getOperand(0), Ops,
+ cast<GEPOperator>(this)->isInBounds());
}
default:
assert(getNumOperands() == 2 && "Must be binary operator?");
@@ -859,7 +859,7 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
/// operands replaced with the specified values. The specified array must
/// have the same number of operands as our current one.
Constant *ConstantExpr::
-getWithOperands(ArrayRef<Constant*> Ops, const Type *Ty) const {
+getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const {
assert(Ops.size() == getNumOperands() && "Operand count mismatch!");
bool AnyChange = Ty != getType();
for (unsigned i = 0; i != Ops.size(); ++i)
@@ -891,9 +891,9 @@ getWithOperands(ArrayRef<Constant*> Ops, const Type *Ty) const {
case Instruction::ShuffleVector:
return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]);
case Instruction::GetElementPtr:
- return cast<GEPOperator>(this)->isInBounds() ?
- ConstantExpr::getInBoundsGetElementPtr(Ops[0], &Ops[1], Ops.size()-1) :
- ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], Ops.size()-1);
+ return
+ ConstantExpr::getGetElementPtr(Ops[0], Ops.slice(1),
+ cast<GEPOperator>(this)->isInBounds());
case Instruction::ICmp:
case Instruction::FCmp:
return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1]);
@@ -907,7 +907,7 @@ getWithOperands(ArrayRef<Constant*> Ops, const Type *Ty) const {
//===----------------------------------------------------------------------===//
// isValueValidForType implementations
-bool ConstantInt::isValueValidForType(const Type *Ty, uint64_t Val) {
+bool ConstantInt::isValueValidForType(Type *Ty, uint64_t Val) {
unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth(); // assert okay
if (Ty == Type::getInt1Ty(Ty->getContext()))
return Val == 0 || Val == 1;
@@ -917,7 +917,7 @@ bool ConstantInt::isValueValidForType(const Type *Ty, uint64_t Val) {
return Val <= Max;
}
-bool ConstantInt::isValueValidForType(const Type *Ty, int64_t Val) {
+bool ConstantInt::isValueValidForType(Type *Ty, int64_t Val) {
unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth(); // assert okay
if (Ty == Type::getInt1Ty(Ty->getContext()))
return Val == 0 || Val == 1 || Val == -1;
@@ -928,7 +928,7 @@ bool ConstantInt::isValueValidForType(const Type *Ty, int64_t Val) {
return (Val >= Min && Val <= Max);
}
-bool ConstantFP::isValueValidForType(const Type *Ty, const APFloat& Val) {
+bool ConstantFP::isValueValidForType(Type *Ty, const APFloat& Val) {
// convert modifies in place, so make a copy.
APFloat Val2 = APFloat(Val);
bool losesInfo;
@@ -968,7 +968,7 @@ bool ConstantFP::isValueValidForType(const Type *Ty, const APFloat& Val) {
//===----------------------------------------------------------------------===//
// Factory Function Implementation
-ConstantAggregateZero* ConstantAggregateZero::get(const Type* Ty) {
+ConstantAggregateZero* ConstantAggregateZero::get(Type* Ty) {
assert((Ty->isStructTy() || Ty->isArrayTy() || Ty->isVectorTy()) &&
"Cannot create an aggregate zero of non-aggregate type!");
@@ -1079,13 +1079,16 @@ bool ConstantVector::isAllOnesValue() const {
// Check out first element.
const Constant *Elt = getOperand(0);
const ConstantInt *CI = dyn_cast<ConstantInt>(Elt);
- if (!CI || !CI->isAllOnesValue()) return false;
+ const ConstantFP *CF = dyn_cast<ConstantFP>(Elt);
+
// Then make sure all remaining elements point to the same value.
for (unsigned I = 1, E = getNumOperands(); I < E; ++I)
if (getOperand(I) != Elt)
return false;
- return true;
+ // First value is all-ones.
+ return (CI && CI->isAllOnesValue()) ||
+ (CF && CF->isAllOnesValue());
}
/// getSplatValue - If this is a splat constant, where all of the
@@ -1103,7 +1106,7 @@ Constant *ConstantVector::getSplatValue() const {
//---- ConstantPointerNull::get() implementation.
//
-ConstantPointerNull *ConstantPointerNull::get(const PointerType *Ty) {
+ConstantPointerNull *ConstantPointerNull::get(PointerType *Ty) {
return Ty->getContext().pImpl->NullPtrConstants.getOrCreate(Ty, 0);
}
@@ -1118,7 +1121,7 @@ void ConstantPointerNull::destroyConstant() {
//---- UndefValue::get() implementation.
//
-UndefValue *UndefValue::get(const Type *Ty) {
+UndefValue *UndefValue::get(Type *Ty) {
return Ty->getContext().pImpl->UndefValueConstants.getOrCreate(Ty, 0);
}
@@ -1209,7 +1212,7 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
/// This is a utility function to handle folding of casts and lookup of the
/// cast in the ExprConstants map. It is used by the various get* methods below.
static inline Constant *getFoldedCast(
- Instruction::CastOps opc, Constant *C, const Type *Ty) {
+ Instruction::CastOps opc, Constant *C, Type *Ty) {
assert(Ty->isFirstClassType() && "Cannot cast to an aggregate type!");
// Fold a few common cases
if (Constant *FC = ConstantFoldCastInstruction(opc, C, Ty))
@@ -1224,7 +1227,7 @@ static inline Constant *getFoldedCast(
return pImpl->ExprConstants.getOrCreate(Ty, Key);
}
-Constant *ConstantExpr::getCast(unsigned oc, Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty) {
Instruction::CastOps opc = Instruction::CastOps(oc);
assert(Instruction::isCast(opc) && "opcode out of range");
assert(C && Ty && "Null arguments to getCast");
@@ -1250,25 +1253,25 @@ Constant *ConstantExpr::getCast(unsigned oc, Constant *C, const Type *Ty) {
return 0;
}
-Constant *ConstantExpr::getZExtOrBitCast(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getZExtOrBitCast(Constant *C, Type *Ty) {
if (C->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
return getBitCast(C, Ty);
return getZExt(C, Ty);
}
-Constant *ConstantExpr::getSExtOrBitCast(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getSExtOrBitCast(Constant *C, Type *Ty) {
if (C->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
return getBitCast(C, Ty);
return getSExt(C, Ty);
}
-Constant *ConstantExpr::getTruncOrBitCast(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getTruncOrBitCast(Constant *C, Type *Ty) {
if (C->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
return getBitCast(C, Ty);
return getTrunc(C, Ty);
}
-Constant *ConstantExpr::getPointerCast(Constant *S, const Type *Ty) {
+Constant *ConstantExpr::getPointerCast(Constant *S, Type *Ty) {
assert(S->getType()->isPointerTy() && "Invalid cast");
assert((Ty->isIntegerTy() || Ty->isPointerTy()) && "Invalid cast");
@@ -1277,7 +1280,7 @@ Constant *ConstantExpr::getPointerCast(Constant *S, const Type *Ty) {
return getBitCast(S, Ty);
}
-Constant *ConstantExpr::getIntegerCast(Constant *C, const Type *Ty,
+Constant *ConstantExpr::getIntegerCast(Constant *C, Type *Ty,
bool isSigned) {
assert(C->getType()->isIntOrIntVectorTy() &&
Ty->isIntOrIntVectorTy() && "Invalid cast");
@@ -1290,7 +1293,7 @@ Constant *ConstantExpr::getIntegerCast(Constant *C, const Type *Ty,
return getCast(opcode, C, Ty);
}
-Constant *ConstantExpr::getFPCast(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getFPCast(Constant *C, Type *Ty) {
assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() &&
"Invalid cast");
unsigned SrcBits = C->getType()->getScalarSizeInBits();
@@ -1302,7 +1305,7 @@ Constant *ConstantExpr::getFPCast(Constant *C, const Type *Ty) {
return getCast(opcode, C, Ty);
}
-Constant *ConstantExpr::getTrunc(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1316,7 +1319,7 @@ Constant *ConstantExpr::getTrunc(Constant *C, const Type *Ty) {
return getFoldedCast(Instruction::Trunc, C, Ty);
}
-Constant *ConstantExpr::getSExt(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getSExt(Constant *C, Type *Ty) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1330,7 +1333,7 @@ Constant *ConstantExpr::getSExt(Constant *C, const Type *Ty) {
return getFoldedCast(Instruction::SExt, C, Ty);
}
-Constant *ConstantExpr::getZExt(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getZExt(Constant *C, Type *Ty) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1344,7 +1347,7 @@ Constant *ConstantExpr::getZExt(Constant *C, const Type *Ty) {
return getFoldedCast(Instruction::ZExt, C, Ty);
}
-Constant *ConstantExpr::getFPTrunc(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getFPTrunc(Constant *C, Type *Ty) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1356,7 +1359,7 @@ Constant *ConstantExpr::getFPTrunc(Constant *C, const Type *Ty) {
return getFoldedCast(Instruction::FPTrunc, C, Ty);
}
-Constant *ConstantExpr::getFPExtend(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getFPExtend(Constant *C, Type *Ty) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1368,7 +1371,7 @@ Constant *ConstantExpr::getFPExtend(Constant *C, const Type *Ty) {
return getFoldedCast(Instruction::FPExt, C, Ty);
}
-Constant *ConstantExpr::getUIToFP(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getUIToFP(Constant *C, Type *Ty) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1379,7 +1382,7 @@ Constant *ConstantExpr::getUIToFP(Constant *C, const Type *Ty) {
return getFoldedCast(Instruction::UIToFP, C, Ty);
}
-Constant *ConstantExpr::getSIToFP(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getSIToFP(Constant *C, Type *Ty) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1390,7 +1393,7 @@ Constant *ConstantExpr::getSIToFP(Constant *C, const Type *Ty) {
return getFoldedCast(Instruction::SIToFP, C, Ty);
}
-Constant *ConstantExpr::getFPToUI(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getFPToUI(Constant *C, Type *Ty) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1401,7 +1404,7 @@ Constant *ConstantExpr::getFPToUI(Constant *C, const Type *Ty) {
return getFoldedCast(Instruction::FPToUI, C, Ty);
}
-Constant *ConstantExpr::getFPToSI(Constant *C, const Type *Ty) {
+Constant *ConstantExpr::getFPToSI(Constant *C, Type *Ty) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1412,19 +1415,19 @@ Constant *ConstantExpr::getFPToSI(Constant *C, const Type *Ty) {
return getFoldedCast(Instruction::FPToSI, C, Ty);
}
-Constant *ConstantExpr::getPtrToInt(Constant *C, const Type *DstTy) {
+Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy) {
assert(C->getType()->isPointerTy() && "PtrToInt source must be pointer");
assert(DstTy->isIntegerTy() && "PtrToInt destination must be integral");
return getFoldedCast(Instruction::PtrToInt, C, DstTy);
}
-Constant *ConstantExpr::getIntToPtr(Constant *C, const Type *DstTy) {
+Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy) {
assert(C->getType()->isIntegerTy() && "IntToPtr source must be integral");
assert(DstTy->isPointerTy() && "IntToPtr destination must be a pointer");
return getFoldedCast(Instruction::IntToPtr, C, DstTy);
}
-Constant *ConstantExpr::getBitCast(Constant *C, const Type *DstTy) {
+Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy) {
assert(CastInst::castIsValid(Instruction::BitCast, C, DstTy) &&
"Invalid constantexpr bitcast!");
@@ -1513,36 +1516,36 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
return pImpl->ExprConstants.getOrCreate(C1->getType(), Key);
}
-Constant *ConstantExpr::getSizeOf(const Type* Ty) {
+Constant *ConstantExpr::getSizeOf(Type* Ty) {
// sizeof is implemented as: (i64) gep (Ty*)null, 1
// Note that a non-inbounds gep is used, as null isn't within any object.
Constant *GEPIdx = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1);
Constant *GEP = getGetElementPtr(
- Constant::getNullValue(PointerType::getUnqual(Ty)), &GEPIdx, 1);
+ Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx);
return getPtrToInt(GEP,
Type::getInt64Ty(Ty->getContext()));
}
-Constant *ConstantExpr::getAlignOf(const Type* Ty) {
+Constant *ConstantExpr::getAlignOf(Type* Ty) {
// alignof is implemented as: (i64) gep ({i1,Ty}*)null, 0, 1
// Note that a non-inbounds gep is used, as null isn't within any object.
- const Type *AligningTy =
+ Type *AligningTy =
StructType::get(Type::getInt1Ty(Ty->getContext()), Ty, NULL);
Constant *NullPtr = Constant::getNullValue(AligningTy->getPointerTo());
Constant *Zero = ConstantInt::get(Type::getInt64Ty(Ty->getContext()), 0);
Constant *One = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1);
Constant *Indices[2] = { Zero, One };
- Constant *GEP = getGetElementPtr(NullPtr, Indices, 2);
+ Constant *GEP = getGetElementPtr(NullPtr, Indices);
return getPtrToInt(GEP,
Type::getInt64Ty(Ty->getContext()));
}
-Constant *ConstantExpr::getOffsetOf(const StructType* STy, unsigned FieldNo) {
+Constant *ConstantExpr::getOffsetOf(StructType* STy, unsigned FieldNo) {
return getOffsetOf(STy, ConstantInt::get(Type::getInt32Ty(STy->getContext()),
FieldNo));
}
-Constant *ConstantExpr::getOffsetOf(const Type* Ty, Constant *FieldNo) {
+Constant *ConstantExpr::getOffsetOf(Type* Ty, Constant *FieldNo) {
// offsetof is implemented as: (i64) gep (Ty*)null, 0, FieldNo
// Note that a non-inbounds gep is used, as null isn't within any object.
Constant *GEPIdx[] = {
@@ -1550,7 +1553,7 @@ Constant *ConstantExpr::getOffsetOf(const Type* Ty, Constant *FieldNo) {
FieldNo
};
Constant *GEP = getGetElementPtr(
- Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx, 2);
+ Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx);
return getPtrToInt(GEP,
Type::getInt64Ty(Ty->getContext()));
}
@@ -1592,14 +1595,13 @@ Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2) {
return pImpl->ExprConstants.getOrCreate(V1->getType(), Key);
}
-Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs,
- unsigned NumIdx, bool InBounds) {
- if (Constant *FC = ConstantFoldGetElementPtr(C, InBounds, Idxs, NumIdx))
+Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs,
+ bool InBounds) {
+ if (Constant *FC = ConstantFoldGetElementPtr(C, InBounds, Idxs))
return FC; // Fold a few common cases.
// Get the result type of the getelementptr!
- const Type *Ty =
- GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx);
+ Type *Ty = GetElementPtrInst::getIndexedType(C->getType(), Idxs);
assert(Ty && "GEP indices invalid!");
unsigned AS = cast<PointerType>(C->getType())->getAddressSpace();
Type *ReqTy = Ty->getPointerTo(AS);
@@ -1608,9 +1610,9 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs,
"Non-pointer type for constant GetElementPtr expression");
// Look up the constant in the table first to ensure uniqueness
std::vector<Constant*> ArgVec;
- ArgVec.reserve(NumIdx+1);
+ ArgVec.reserve(1 + Idxs.size());
ArgVec.push_back(C);
- for (unsigned i = 0; i != NumIdx; ++i)
+ for (unsigned i = 0, e = Idxs.size(); i != e; ++i)
ArgVec.push_back(cast<Constant>(Idxs[i]));
const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
InBounds ? GEPOperator::IsInBounds : 0);
@@ -1635,8 +1637,8 @@ ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) {
// Get the key type with both the opcode and predicate
const ExprMapKeyType Key(Instruction::ICmp, ArgVec, pred);
- const Type *ResultTy = Type::getInt1Ty(LHS->getContext());
- if (const VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
+ Type *ResultTy = Type::getInt1Ty(LHS->getContext());
+ if (VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
ResultTy = VectorType::get(ResultTy, VT->getNumElements());
LLVMContextImpl *pImpl = LHS->getType()->getContext().pImpl;
@@ -1658,8 +1660,8 @@ ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, Constant *RHS) {
// Get the key type with both the opcode and predicate
const ExprMapKeyType Key(Instruction::FCmp, ArgVec, pred);
- const Type *ResultTy = Type::getInt1Ty(LHS->getContext());
- if (const VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
+ Type *ResultTy = Type::getInt1Ty(LHS->getContext());
+ if (VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
ResultTy = VectorType::get(ResultTy, VT->getNumElements());
LLVMContextImpl *pImpl = LHS->getType()->getContext().pImpl;
@@ -1715,8 +1717,8 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2,
return FC; // Fold a few common cases.
unsigned NElts = cast<VectorType>(Mask->getType())->getNumElements();
- const Type *EltTy = cast<VectorType>(V1->getType())->getElementType();
- const Type *ShufTy = VectorType::get(EltTy, NElts);
+ Type *EltTy = cast<VectorType>(V1->getType())->getElementType();
+ Type *ShufTy = VectorType::get(EltTy, NElts);
// Look up the constant in the table first to ensure uniqueness
std::vector<Constant*> ArgVec(1, V1);
@@ -1745,7 +1747,7 @@ Constant *ConstantExpr::getExtractValue(Constant *Agg,
assert(Agg->getType()->isFirstClassType() &&
"Tried to create extractelement operation on non-first-class type!");
- const Type *ReqTy = ExtractValueInst::getIndexedType(Agg->getType(), Idxs);
+ Type *ReqTy = ExtractValueInst::getIndexedType(Agg->getType(), Idxs);
(void)ReqTy;
assert(ReqTy && "extractvalue indices invalid!");
@@ -1878,7 +1880,7 @@ const char *ConstantExpr::getOpcodeName() const {
GetElementPtrConstantExpr::
GetElementPtrConstantExpr(Constant *C, const std::vector<Constant*> &IdxList,
- const Type *DestTy)
+ Type *DestTy)
: ConstantExpr(DestTy, Instruction::GetElementPtr,
OperandTraits<GetElementPtrConstantExpr>::op_end(this)
- (IdxList.size()+1), IdxList.size()+1) {
@@ -2091,8 +2093,7 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
if (Val == From) Val = To;
Indices.push_back(Val);
}
- Replacement = ConstantExpr::getGetElementPtr(Pointer,
- &Indices[0], Indices.size(),
+ Replacement = ConstantExpr::getGetElementPtr(Pointer, Indices,
cast<GEPOperator>(this)->isInBounds());
} else if (getOpcode() == Instruction::ExtractValue) {
Constant *Agg = getOperand(0);
diff --git a/lib/VMCore/ConstantsContext.h b/lib/VMCore/ConstantsContext.h
index bd134d9..1077004 100644
--- a/lib/VMCore/ConstantsContext.h
+++ b/lib/VMCore/ConstantsContext.h
@@ -36,7 +36,7 @@ public:
void *operator new(size_t s) {
return User::operator new(s, 1);
}
- UnaryConstantExpr(unsigned Opcode, Constant *C, const Type *Ty)
+ UnaryConstantExpr(unsigned Opcode, Constant *C, Type *Ty)
: ConstantExpr(Ty, Opcode, &Op<0>(), 1) {
Op<0>() = C;
}
@@ -159,7 +159,7 @@ public:
}
ExtractValueConstantExpr(Constant *Agg,
const SmallVector<unsigned, 4> &IdxList,
- const Type *DestTy)
+ Type *DestTy)
: ConstantExpr(DestTy, Instruction::ExtractValue, &Op<0>(), 1),
Indices(IdxList) {
Op<0>() = Agg;
@@ -184,7 +184,7 @@ public:
}
InsertValueConstantExpr(Constant *Agg, Constant *Val,
const SmallVector<unsigned, 4> &IdxList,
- const Type *DestTy)
+ Type *DestTy)
: ConstantExpr(DestTy, Instruction::InsertValue, &Op<0>(), 2),
Indices(IdxList) {
Op<0>() = Agg;
@@ -203,11 +203,11 @@ public:
/// used behind the scenes to implement getelementpr constant exprs.
class GetElementPtrConstantExpr : public ConstantExpr {
GetElementPtrConstantExpr(Constant *C, const std::vector<Constant*> &IdxList,
- const Type *DestTy);
+ Type *DestTy);
public:
static GetElementPtrConstantExpr *Create(Constant *C,
const std::vector<Constant*>&IdxList,
- const Type *DestTy,
+ Type *DestTy,
unsigned Flags) {
GetElementPtrConstantExpr *Result =
new(IdxList.size() + 1) GetElementPtrConstantExpr(C, IdxList, DestTy);
@@ -228,7 +228,7 @@ struct CompareConstantExpr : public ConstantExpr {
return User::operator new(s, 2);
}
unsigned short predicate;
- CompareConstantExpr(const Type *ty, Instruction::OtherOps opc,
+ CompareConstantExpr(Type *ty, Instruction::OtherOps opc,
unsigned short pred, Constant* LHS, Constant* RHS)
: ConstantExpr(ty, opc, &Op<0>(), 2), predicate(pred) {
Op<0>() = LHS;
@@ -392,7 +392,7 @@ struct ConstantTraits<Constant *> {
template<class ConstantClass, class TypeClass, class ValType>
struct ConstantCreator {
- static ConstantClass *create(const TypeClass *Ty, const ValType &V) {
+ static ConstantClass *create(TypeClass *Ty, const ValType &V) {
return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V);
}
};
@@ -407,7 +407,7 @@ struct ConstantKeyData {
template<>
struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> {
- static ConstantExpr *create(const Type *Ty, const ExprMapKeyType &V,
+ static ConstantExpr *create(Type *Ty, const ExprMapKeyType &V,
unsigned short pred = 0) {
if (Instruction::isCast(V.opcode))
return new UnaryConstantExpr(V.opcode, V.operands[0], Ty);
@@ -470,7 +470,7 @@ struct ConstantKeyData<ConstantExpr> {
// ConstantAggregateZero does not take extra "value" argument...
template<class ValType>
struct ConstantCreator<ConstantAggregateZero, Type, ValType> {
- static ConstantAggregateZero *create(const Type *Ty, const ValType &V){
+ static ConstantAggregateZero *create(Type *Ty, const ValType &V){
return new ConstantAggregateZero(Ty);
}
};
@@ -522,7 +522,7 @@ struct ConstantKeyData<ConstantStruct> {
// ConstantPointerNull does not take extra "value" argument...
template<class ValType>
struct ConstantCreator<ConstantPointerNull, PointerType, ValType> {
- static ConstantPointerNull *create(const PointerType *Ty, const ValType &V){
+ static ConstantPointerNull *create(PointerType *Ty, const ValType &V){
return new ConstantPointerNull(Ty);
}
};
@@ -538,7 +538,7 @@ struct ConstantKeyData<ConstantPointerNull> {
// UndefValue does not take extra "value" argument...
template<class ValType>
struct ConstantCreator<UndefValue, Type, ValType> {
- static UndefValue *create(const Type *Ty, const ValType &V) {
+ static UndefValue *create(Type *Ty, const ValType &V) {
return new UndefValue(Ty);
}
};
@@ -553,7 +553,7 @@ struct ConstantKeyData<UndefValue> {
template<>
struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType> {
- static InlineAsm *create(const PointerType *Ty, const InlineAsmKeyType &Key) {
+ static InlineAsm *create(PointerType *Ty, const InlineAsmKeyType &Key) {
return new InlineAsm(Ty, Key.asm_string, Key.constraints,
Key.has_side_effects, Key.is_align_stack);
}
@@ -572,7 +572,7 @@ template<class ValType, class ValRefType, class TypeClass, class ConstantClass,
bool HasLargeKey = false /*true for arrays and structs*/ >
class ConstantUniqueMap {
public:
- typedef std::pair<const TypeClass*, ValType> MapKey;
+ typedef std::pair<TypeClass*, ValType> MapKey;
typedef std::map<MapKey, ConstantClass *> MapTy;
typedef std::map<ConstantClass *, typename MapTy::iterator> InverseMapTy;
private:
@@ -623,7 +623,7 @@ private:
}
typename MapTy::iterator I =
- Map.find(MapKey(static_cast<const TypeClass*>(CP->getType()),
+ Map.find(MapKey(static_cast<TypeClass*>(CP->getType()),
ConstantKeyData<ConstantClass>::getValType(CP)));
if (I == Map.end() || I->second != CP) {
// FIXME: This should not use a linear scan. If this gets to be a
@@ -634,7 +634,7 @@ private:
return I;
}
- ConstantClass *Create(const TypeClass *Ty, ValRefType V,
+ ConstantClass *Create(TypeClass *Ty, ValRefType V,
typename MapTy::iterator I) {
ConstantClass* Result =
ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V);
@@ -651,7 +651,7 @@ public:
/// getOrCreate - Return the specified constant from the map, creating it if
/// necessary.
- ConstantClass *getOrCreate(const TypeClass *Ty, ValRefType V) {
+ ConstantClass *getOrCreate(TypeClass *Ty, ValRefType V) {
MapKey Lookup(Ty, V);
ConstantClass* Result = 0;
diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp
index 2a816e1..a505e4b 100644
--- a/lib/VMCore/Core.cpp
+++ b/lib/VMCore/Core.cpp
@@ -167,6 +167,11 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) {
}
}
+LLVMBool LLVMTypeIsSized(LLVMTypeRef Ty)
+{
+ return unwrap(Ty)->isSized();
+}
+
LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty) {
return wrap(&unwrap(Ty)->getContext());
}
@@ -299,7 +304,15 @@ LLVMTypeRef LLVMStructType(LLVMTypeRef *ElementTypes,
LLVMTypeRef LLVMStructCreateNamed(LLVMContextRef C, const char *Name)
{
- return wrap(StructType::createNamed(*unwrap(C), Name));
+ return wrap(StructType::create(*unwrap(C), Name));
+}
+
+const char *LLVMGetStructName(LLVMTypeRef Ty)
+{
+ StructType *Type = unwrap<StructType>(Ty);
+ if (!Type->hasName())
+ return 0;
+ return Type->getName().data();
}
void LLVMStructSetBody(LLVMTypeRef StructTy, LLVMTypeRef *ElementTypes,
@@ -448,7 +461,10 @@ LLVMValueRef LLVMGetUsedValue(LLVMUseRef U) {
/*--.. Operations on Users .................................................--*/
LLVMValueRef LLVMGetOperand(LLVMValueRef Val, unsigned Index) {
- return wrap(unwrap<User>(Val)->getOperand(Index));
+ Value *V = unwrap(Val);
+ if (MDNode *MD = dyn_cast<MDNode>(V))
+ return wrap(MD->getOperand(Index));
+ return wrap(cast<User>(V)->getOperand(Index));
}
void LLVMSetOperand(LLVMValueRef Val, unsigned Index, LLVMValueRef Op) {
@@ -456,7 +472,10 @@ void LLVMSetOperand(LLVMValueRef Val, unsigned Index, LLVMValueRef Op) {
}
int LLVMGetNumOperands(LLVMValueRef Val) {
- return unwrap<User>(Val)->getNumOperands();
+ Value *V = unwrap(Val);
+ if (MDNode *MD = dyn_cast<MDNode>(V))
+ return MD->getNumOperands();
+ return cast<User>(V)->getNumOperands();
}
/*--.. Operations on constants of any type .................................--*/
@@ -506,13 +525,39 @@ LLVMValueRef LLVMMDString(const char *Str, unsigned SLen) {
LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals,
unsigned Count) {
return wrap(MDNode::get(*unwrap(C),
- ArrayRef<Value*>(unwrap<Value>(Vals, Count), Count)));
+ makeArrayRef(unwrap<Value>(Vals, Count), Count)));
}
LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count) {
return LLVMMDNodeInContext(LLVMGetGlobalContext(), Vals, Count);
}
+const char *LLVMGetMDString(LLVMValueRef V, unsigned* Len) {
+ if (const MDString *S = dyn_cast<MDString>(unwrap(V))) {
+ *Len = S->getString().size();
+ return S->getString().data();
+ }
+ *Len = 0;
+ return 0;
+}
+
+unsigned LLVMGetNamedMetadataNumOperands(LLVMModuleRef M, const char* name)
+{
+ if (NamedMDNode *N = unwrap(M)->getNamedMetadata(name)) {
+ return N->getNumOperands();
+ }
+ return 0;
+}
+
+void LLVMGetNamedMetadataOperands(LLVMModuleRef M, const char* name, LLVMValueRef *Dest)
+{
+ NamedMDNode *N = unwrap(M)->getNamedMetadata(name);
+ if (!N)
+ return;
+ for (unsigned i=0;i<N->getNumOperands();i++)
+ Dest[i] = wrap(N->getOperand(i));
+}
+
/*--.. Operations on scalar constants ......................................--*/
LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N,
@@ -525,7 +570,8 @@ LLVMValueRef LLVMConstIntOfArbitraryPrecision(LLVMTypeRef IntTy,
const uint64_t Words[]) {
IntegerType *Ty = unwrap<IntegerType>(IntTy);
return wrap(ConstantInt::get(Ty->getContext(),
- APInt(Ty->getBitWidth(), NumWords, Words)));
+ APInt(Ty->getBitWidth(),
+ makeArrayRef(Words, NumWords))));
}
LLVMValueRef LLVMConstIntOfString(LLVMTypeRef IntTy, const char Str[],
@@ -575,8 +621,7 @@ LLVMValueRef LLVMConstStructInContext(LLVMContextRef C,
LLVMValueRef *ConstantVals,
unsigned Count, LLVMBool Packed) {
Constant **Elements = unwrap<Constant>(ConstantVals, Count);
- return wrap(ConstantStruct::getAnon(*unwrap(C),
- ArrayRef<Constant*>(Elements, Count),
+ return wrap(ConstantStruct::getAnon(*unwrap(C), makeArrayRef(Elements, Count),
Packed != 0));
}
@@ -600,19 +645,44 @@ LLVMValueRef LLVMConstNamedStruct(LLVMTypeRef StructTy,
LLVMValueRef *ConstantVals,
unsigned Count) {
Constant **Elements = unwrap<Constant>(ConstantVals, Count);
- const StructType *Ty = cast<StructType>(unwrap(StructTy));
+ StructType *Ty = cast<StructType>(unwrap(StructTy));
- return wrap(ConstantStruct::get(Ty, ArrayRef<Constant*>(Elements, Count)));
+ return wrap(ConstantStruct::get(Ty, makeArrayRef(Elements, Count)));
}
LLVMValueRef LLVMConstVector(LLVMValueRef *ScalarConstantVals, unsigned Size) {
- return wrap(ConstantVector::get(ArrayRef<Constant*>(
+ return wrap(ConstantVector::get(makeArrayRef(
unwrap<Constant>(ScalarConstantVals, Size), Size)));
}
+
+/*-- Opcode mapping */
+
+static LLVMOpcode map_to_llvmopcode(int opcode)
+{
+ switch (opcode) {
+ default:
+ assert(0 && "Unhandled Opcode.");
+#define HANDLE_INST(num, opc, clas) case num: return LLVM##opc;
+#include "llvm/Instruction.def"
+#undef HANDLE_INST
+ }
+}
+
+static int map_from_llvmopcode(LLVMOpcode code)
+{
+ switch (code) {
+ default:
+ assert(0 && "Unhandled Opcode.");
+#define HANDLE_INST(num, opc, clas) case LLVM##opc: return num;
+#include "llvm/Instruction.def"
+#undef HANDLE_INST
+ }
+}
+
/*--.. Constant expressions ................................................--*/
LLVMOpcode LLVMGetConstOpcode(LLVMValueRef ConstantVal) {
- return (LLVMOpcode)unwrap<ConstantExpr>(ConstantVal)->getOpcode();
+ return map_to_llvmopcode(unwrap<ConstantExpr>(ConstantVal)->getOpcode());
}
LLVMValueRef LLVMAlignOf(LLVMTypeRef Ty) {
@@ -792,18 +862,19 @@ LLVMValueRef LLVMConstAShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant) {
LLVMValueRef LLVMConstGEP(LLVMValueRef ConstantVal,
LLVMValueRef *ConstantIndices, unsigned NumIndices) {
+ ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
+ NumIndices);
return wrap(ConstantExpr::getGetElementPtr(unwrap<Constant>(ConstantVal),
- unwrap<Constant>(ConstantIndices,
- NumIndices),
- NumIndices));
+ IdxList));
}
LLVMValueRef LLVMConstInBoundsGEP(LLVMValueRef ConstantVal,
LLVMValueRef *ConstantIndices,
unsigned NumIndices) {
Constant* Val = unwrap<Constant>(ConstantVal);
- Constant** Idxs = unwrap<Constant>(ConstantIndices, NumIndices);
- return wrap(ConstantExpr::getInBoundsGetElementPtr(Val, Idxs, NumIndices));
+ ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
+ NumIndices);
+ return wrap(ConstantExpr::getInBoundsGetElementPtr(Val, IdxList));
}
LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType) {
@@ -934,8 +1005,7 @@ LLVMValueRef LLVMConstShuffleVector(LLVMValueRef VectorAConstant,
LLVMValueRef LLVMConstExtractValue(LLVMValueRef AggConstant, unsigned *IdxList,
unsigned NumIdx) {
return wrap(ConstantExpr::getExtractValue(unwrap<Constant>(AggConstant),
- ArrayRef<unsigned>(IdxList,
- NumIdx)));
+ makeArrayRef(IdxList, NumIdx)));
}
LLVMValueRef LLVMConstInsertValue(LLVMValueRef AggConstant,
@@ -943,8 +1013,7 @@ LLVMValueRef LLVMConstInsertValue(LLVMValueRef AggConstant,
unsigned *IdxList, unsigned NumIdx) {
return wrap(ConstantExpr::getInsertValue(unwrap<Constant>(AggConstant),
unwrap<Constant>(ElementValueConstant),
- ArrayRef<unsigned>(IdxList,
- NumIdx)));
+ makeArrayRef(IdxList, NumIdx)));
}
LLVMValueRef LLVMConstInlineAsm(LLVMTypeRef Ty, const char *AsmString,
@@ -1383,6 +1452,10 @@ LLVMValueRef LLVMGetBasicBlockParent(LLVMBasicBlockRef BB) {
return wrap(unwrap(BB)->getParent());
}
+LLVMValueRef LLVMGetBasicBlockTerminator(LLVMBasicBlockRef BB) {
+ return wrap(unwrap(BB)->getTerminator());
+}
+
unsigned LLVMCountBasicBlocks(LLVMValueRef FnRef) {
return unwrap<Function>(FnRef)->size();
}
@@ -1455,6 +1528,10 @@ void LLVMDeleteBasicBlock(LLVMBasicBlockRef BBRef) {
unwrap(BBRef)->eraseFromParent();
}
+void LLVMRemoveBasicBlockFromParent(LLVMBasicBlockRef BBRef) {
+ unwrap(BBRef)->removeFromParent();
+}
+
void LLVMMoveBasicBlockBefore(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos) {
unwrap(BB)->moveBefore(unwrap(MovePos));
}
@@ -1501,6 +1578,25 @@ LLVMValueRef LLVMGetPreviousInstruction(LLVMValueRef Inst) {
return wrap(--I);
}
+void LLVMInstructionEraseFromParent(LLVMValueRef Inst) {
+ unwrap<Instruction>(Inst)->eraseFromParent();
+}
+
+LLVMIntPredicate LLVMGetICmpPredicate(LLVMValueRef Inst) {
+ if (ICmpInst *I = dyn_cast<ICmpInst>(unwrap(Inst)))
+ return (LLVMIntPredicate)I->getPredicate();
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(unwrap(Inst)))
+ if (CE->getOpcode() == Instruction::ICmp)
+ return (LLVMIntPredicate)CE->getPredicate();
+ return (LLVMIntPredicate)0;
+}
+
+LLVMOpcode LLVMGetInstructionOpcode(LLVMValueRef Inst) {
+ if (Instruction *C = dyn_cast<Instruction>(unwrap(Inst)))
+ return map_to_llvmopcode(C->getOpcode());
+ return (LLVMOpcode)0;
+}
+
/*--.. Call and invoke instructions ........................................--*/
unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr) {
@@ -1554,6 +1650,12 @@ void LLVMSetTailCall(LLVMValueRef Call, LLVMBool isTailCall) {
unwrap<CallInst>(Call)->setTailCall(isTailCall);
}
+/*--.. Operations on switch instructions (only) ............................--*/
+
+LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef Switch) {
+ return wrap(unwrap<SwitchInst>(Switch)->getDefaultDest());
+}
+
/*--.. Operations on phi nodes .............................................--*/
void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues,
@@ -1680,12 +1782,20 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
const char *Name) {
return wrap(unwrap(B)->CreateInvoke(unwrap(Fn), unwrap(Then), unwrap(Catch),
- ArrayRef<Value *>(unwrap(Args), NumArgs),
+ makeArrayRef(unwrap(Args), NumArgs),
Name));
}
-LLVMValueRef LLVMBuildUnwind(LLVMBuilderRef B) {
- return wrap(unwrap(B)->CreateUnwind());
+LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
+ LLVMValueRef PersFn, unsigned NumClauses,
+ const char *Name) {
+ return wrap(unwrap(B)->CreateLandingPad(unwrap(Ty),
+ cast<Function>(unwrap(PersFn)),
+ NumClauses, Name));
+}
+
+LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn) {
+ return wrap(unwrap(B)->CreateResume(unwrap(Exn)));
}
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef B) {
@@ -1701,6 +1811,15 @@ void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest) {
unwrap<IndirectBrInst>(IndirectBr)->addDestination(unwrap(Dest));
}
+void LLVMAddClause(LLVMValueRef LandingPad, LLVMValueRef ClauseVal) {
+ unwrap<LandingPadInst>(LandingPad)->
+ addClause(cast<Constant>(unwrap(ClauseVal)));
+}
+
+void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val) {
+ unwrap<LandingPadInst>(LandingPad)->setCleanup(Val);
+}
+
/*--.. Arithmetic ..........................................................--*/
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS,
@@ -1831,7 +1950,7 @@ LLVMValueRef LLVMBuildXor(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS,
LLVMValueRef LLVMBuildBinOp(LLVMBuilderRef B, LLVMOpcode Op,
LLVMValueRef LHS, LLVMValueRef RHS,
const char *Name) {
- return wrap(unwrap(B)->CreateBinOp(Instruction::BinaryOps(Op), unwrap(LHS),
+ return wrap(unwrap(B)->CreateBinOp(Instruction::BinaryOps(map_from_llvmopcode(Op)), unwrap(LHS),
unwrap(RHS), Name));
}
@@ -1861,7 +1980,7 @@ LLVMValueRef LLVMBuildNot(LLVMBuilderRef B, LLVMValueRef V, const char *Name) {
LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef B, LLVMTypeRef Ty,
const char *Name) {
- const Type* ITy = Type::getInt32Ty(unwrap(B)->GetInsertBlock()->getContext());
+ Type* ITy = Type::getInt32Ty(unwrap(B)->GetInsertBlock()->getContext());
Constant* AllocSize = ConstantExpr::getSizeOf(unwrap(Ty));
AllocSize = ConstantExpr::getTruncOrBitCast(AllocSize, ITy);
Instruction* Malloc = CallInst::CreateMalloc(unwrap(B)->GetInsertBlock(),
@@ -1872,7 +1991,7 @@ LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef LLVMBuildArrayMalloc(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef Val, const char *Name) {
- const Type* ITy = Type::getInt32Ty(unwrap(B)->GetInsertBlock()->getContext());
+ Type* ITy = Type::getInt32Ty(unwrap(B)->GetInsertBlock()->getContext());
Constant* AllocSize = ConstantExpr::getSizeOf(unwrap(Ty));
AllocSize = ConstantExpr::getTruncOrBitCast(AllocSize, ITy);
Instruction* Malloc = CallInst::CreateMalloc(unwrap(B)->GetInsertBlock(),
@@ -1910,15 +2029,15 @@ LLVMValueRef LLVMBuildStore(LLVMBuilderRef B, LLVMValueRef Val,
LLVMValueRef LLVMBuildGEP(LLVMBuilderRef B, LLVMValueRef Pointer,
LLVMValueRef *Indices, unsigned NumIndices,
const char *Name) {
- return wrap(unwrap(B)->CreateGEP(unwrap(Pointer), unwrap(Indices),
- unwrap(Indices) + NumIndices, Name));
+ ArrayRef<Value *> IdxList(unwrap(Indices), NumIndices);
+ return wrap(unwrap(B)->CreateGEP(unwrap(Pointer), IdxList, Name));
}
LLVMValueRef LLVMBuildInBoundsGEP(LLVMBuilderRef B, LLVMValueRef Pointer,
LLVMValueRef *Indices, unsigned NumIndices,
const char *Name) {
- return wrap(unwrap(B)->CreateInBoundsGEP(unwrap(Pointer), unwrap(Indices),
- unwrap(Indices) + NumIndices, Name));
+ ArrayRef<Value *> IdxList(unwrap(Indices), NumIndices);
+ return wrap(unwrap(B)->CreateInBoundsGEP(unwrap(Pointer), IdxList, Name));
}
LLVMValueRef LLVMBuildStructGEP(LLVMBuilderRef B, LLVMValueRef Pointer,
@@ -2018,7 +2137,7 @@ LLVMValueRef LLVMBuildTruncOrBitCast(LLVMBuilderRef B, LLVMValueRef Val,
LLVMValueRef LLVMBuildCast(LLVMBuilderRef B, LLVMOpcode Op, LLVMValueRef Val,
LLVMTypeRef DestTy, const char *Name) {
- return wrap(unwrap(B)->CreateCast(Instruction::CastOps(Op), unwrap(Val),
+ return wrap(unwrap(B)->CreateCast(Instruction::CastOps(map_from_llvmopcode(Op)), unwrap(Val),
unwrap(DestTy), Name));
}
@@ -2064,7 +2183,7 @@ LLVMValueRef LLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
const char *Name) {
return wrap(unwrap(B)->CreateCall(unwrap(Fn),
- ArrayRef<Value *>(unwrap(Args), NumArgs),
+ makeArrayRef(unwrap(Args), NumArgs),
Name));
}
diff --git a/lib/VMCore/DebugLoc.cpp b/lib/VMCore/DebugLoc.cpp
index 4ff6b2c..328244f 100644
--- a/lib/VMCore/DebugLoc.cpp
+++ b/lib/VMCore/DebugLoc.cpp
@@ -104,7 +104,7 @@ MDNode *DebugLoc::getAsMDNode(const LLVMContext &Ctx) const {
assert(Scope && "If scope is null, this should be isUnknown()");
LLVMContext &Ctx2 = Scope->getContext();
- const Type *Int32 = Type::getInt32Ty(Ctx2);
+ Type *Int32 = Type::getInt32Ty(Ctx2);
Value *Elts[] = {
ConstantInt::get(Int32, getLine()), ConstantInt::get(Int32, getCol()),
Scope, IA
@@ -240,7 +240,7 @@ int LLVMContextImpl::getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,
/// deleted - The MDNode this is pointing to got deleted, so this pointer needs
/// to drop to null and we need remove our entry from the DenseMap.
void DebugRecVH::deleted() {
- // If this is a non-canonical reference, just drop the value to null, we know
+ // If this is a non-canonical reference, just drop the value to null, we know
// it doesn't have a map entry.
if (Idx == 0) {
setValPtr(0);
diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp
index 6536bcd..1215e6a 100644
--- a/lib/VMCore/Function.cpp
+++ b/lib/VMCore/Function.cpp
@@ -17,6 +17,7 @@
#include "llvm/LLVMContext.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/CallSite.h"
+#include "llvm/Support/InstIterator.h"
#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/StringPool.h"
@@ -38,7 +39,7 @@ template class llvm::SymbolTableListTraits<BasicBlock, Function>;
// Argument Implementation
//===----------------------------------------------------------------------===//
-Argument::Argument(const Type *Ty, const Twine &Name, Function *Par)
+Argument::Argument(Type *Ty, const Twine &Name, Function *Par)
: Value(Ty, Value::ArgumentVal) {
Parent = 0;
@@ -158,7 +159,7 @@ void Function::eraseFromParent() {
// Function Implementation
//===----------------------------------------------------------------------===//
-Function::Function(const FunctionType *Ty, LinkageTypes Linkage,
+Function::Function(FunctionType *Ty, LinkageTypes Linkage,
const Twine &name, Module *ParentModule)
: GlobalValue(PointerType::getUnqual(Ty),
Value::FunctionVal, 0, 0, Linkage, name) {
@@ -195,7 +196,7 @@ Function::~Function() {
void Function::BuildLazyArguments() const {
// Create the arguments vector, all arguments start out unnamed.
- const FunctionType *FT = getFunctionType();
+ FunctionType *FT = getFunctionType();
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
assert(!FT->getParamType(i)->isVoidTy() &&
"Cannot have void typed arguments!");
@@ -345,7 +346,7 @@ std::string Intrinsic::getName(ID id, ArrayRef<Type*> Tys) {
return Table[id];
std::string Result(Table[id]);
for (unsigned i = 0; i < Tys.size(); ++i) {
- if (const PointerType* PTyp = dyn_cast<PointerType>(Tys[i])) {
+ if (PointerType* PTyp = dyn_cast<PointerType>(Tys[i])) {
Result += ".p" + llvm::utostr(PTyp->getAddressSpace()) +
EVT::getEVT(PTyp->getElementType()).getEVTString();
}
@@ -355,9 +356,9 @@ std::string Intrinsic::getName(ID id, ArrayRef<Type*> Tys) {
return Result;
}
-const FunctionType *Intrinsic::getType(LLVMContext &Context,
+FunctionType *Intrinsic::getType(LLVMContext &Context,
ID id, ArrayRef<Type*> Tys) {
- const Type *ResultTy = NULL;
+ Type *ResultTy = NULL;
std::vector<Type*> ArgTys;
bool IsVarArg = false;
@@ -416,8 +417,7 @@ bool Function::hasAddressTaken(const User* *PutOffender) const {
/// FIXME: Remove after <rdar://problem/8031714> is fixed.
/// FIXME: Is the above FIXME valid?
bool Function::callsFunctionThatReturnsTwice() const {
- const Module *M = this->getParent();
- static const char *ReturnsTwiceFns[] = {
+ static const char *const ReturnsTwiceFns[] = {
"_setjmp",
"setjmp",
"sigsetjmp",
@@ -428,16 +428,25 @@ bool Function::callsFunctionThatReturnsTwice() const {
"getcontext"
};
- for (unsigned I = 0; I < array_lengthof(ReturnsTwiceFns); ++I)
- if (const Function *Callee = M->getFunction(ReturnsTwiceFns[I])) {
- if (!Callee->use_empty())
- for (Value::const_use_iterator
- I = Callee->use_begin(), E = Callee->use_end();
- I != E; ++I)
- if (const CallInst *CI = dyn_cast<CallInst>(*I))
- if (CI->getParent()->getParent() == this)
- return true;
+ for (const_inst_iterator I = inst_begin(this), E = inst_end(this); I != E;
+ ++I) {
+ const CallInst* callInst = dyn_cast<CallInst>(&*I);
+ if (!callInst)
+ continue;
+ if (callInst->canReturnTwice())
+ return true;
+
+ // check for known function names.
+ // FIXME: move this to clang.
+ Function *F = callInst->getCalledFunction();
+ if (!F)
+ continue;
+ StringRef Name = F->getName();
+ for (unsigned J = 0, e = array_lengthof(ReturnsTwiceFns); J != e; ++J) {
+ if (Name == ReturnsTwiceFns[J])
+ return true;
}
+ }
return false;
}
diff --git a/lib/VMCore/GCOV.cpp b/lib/VMCore/GCOV.cpp
new file mode 100644
index 0000000..fc7f96f
--- /dev/null
+++ b/lib/VMCore/GCOV.cpp
@@ -0,0 +1,281 @@
+//===- GCOVr.cpp - LLVM coverage tool -------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// GCOV implements the interface to read and write coverage files that use
+// 'gcov' format.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/GCOV.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/system_error.h"
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// GCOVFile implementation.
+
+/// ~GCOVFile - Delete GCOVFile and its content.
+GCOVFile::~GCOVFile() {
+ DeleteContainerPointers(Functions);
+}
+
+/// isGCDAFile - Return true if Format identifies a .gcda file.
+static bool isGCDAFile(GCOVFormat Format) {
+ return Format == GCDA_402 || Format == GCDA_404;
+}
+
+/// isGCNOFile - Return true if Format identifies a .gcno file.
+static bool isGCNOFile(GCOVFormat Format) {
+ return Format == GCNO_402 || Format == GCNO_404;
+}
+
+/// read - Read GCOV buffer.
+bool GCOVFile::read(GCOVBuffer &Buffer) {
+ GCOVFormat Format = Buffer.readGCOVFormat();
+ if (Format == InvalidGCOV)
+ return false;
+
+ unsigned i = 0;
+ while (1) {
+ GCOVFunction *GFun = NULL;
+ if (isGCDAFile(Format)) {
+ // Use existing function while reading .gcda file.
+ assert (i < Functions.size() && ".gcda data does not match .gcno data");
+ GFun = Functions[i];
+ } else if (isGCNOFile(Format)){
+ GFun = new GCOVFunction();
+ Functions.push_back(GFun);
+ }
+ if (!GFun || !GFun->read(Buffer, Format))
+ break;
+ ++i;
+ }
+ return true;
+}
+
+/// dump - Dump GCOVFile content on standard out for debugging purposes.
+void GCOVFile::dump() {
+ for (SmallVector<GCOVFunction *, 16>::iterator I = Functions.begin(),
+ E = Functions.end(); I != E; ++I)
+ (*I)->dump();
+}
+
+/// collectLineCounts - Collect line counts. This must be used after
+/// reading .gcno and .gcda files.
+void GCOVFile::collectLineCounts(FileInfo &FI) {
+ for (SmallVector<GCOVFunction *, 16>::iterator I = Functions.begin(),
+ E = Functions.end(); I != E; ++I)
+ (*I)->collectLineCounts(FI);
+ FI.print();
+}
+
+//===----------------------------------------------------------------------===//
+// GCOVFunction implementation.
+
+/// ~GCOVFunction - Delete GCOVFunction and its content.
+GCOVFunction::~GCOVFunction() {
+ DeleteContainerPointers(Blocks);
+}
+
+/// read - Read a aunction from the buffer. Return false if buffer cursor
+/// does not point to a function tag.
+bool GCOVFunction::read(GCOVBuffer &Buff, GCOVFormat Format) {
+ if (!Buff.readFunctionTag())
+ return false;
+
+ Buff.readInt(); // Function header length
+ Ident = Buff.readInt();
+ Buff.readInt(); // Checksum #1
+ if (Format != GCNO_402)
+ Buff.readInt(); // Checksum #2
+
+ Name = Buff.readString();
+ if (Format == GCNO_402 || Format == GCNO_404)
+ Filename = Buff.readString();
+
+ if (Format == GCDA_402 || Format == GCDA_404) {
+ Buff.readArcTag();
+ uint32_t Count = Buff.readInt() / 2;
+ for (unsigned i = 0, e = Count; i != e; ++i) {
+ Blocks[i]->addCount(Buff.readInt64());
+ }
+ return true;;
+ }
+
+ LineNumber = Buff.readInt();
+
+ // read blocks.
+ assert (Buff.readBlockTag() && "Block Tag not found!");
+ uint32_t BlockCount = Buff.readInt();
+ for (int i = 0, e = BlockCount; i != e; ++i) {
+ Buff.readInt(); // Block flags;
+ Blocks.push_back(new GCOVBlock(i));
+ }
+
+ // read edges.
+ while (Buff.readEdgeTag()) {
+ uint32_t EdgeCount = (Buff.readInt() - 1) / 2;
+ uint32_t BlockNo = Buff.readInt();
+ assert (BlockNo < BlockCount && "Unexpected Block number!");
+ for (int i = 0, e = EdgeCount; i != e; ++i) {
+ Blocks[BlockNo]->addEdge(Buff.readInt());
+ Buff.readInt(); // Edge flag
+ }
+ }
+
+ // read line table.
+ while (Buff.readLineTag()) {
+ uint32_t LineTableLength = Buff.readInt();
+ uint32_t Size = Buff.getCursor() + LineTableLength*4;
+ uint32_t BlockNo = Buff.readInt();
+ assert (BlockNo < BlockCount && "Unexpected Block number!");
+ GCOVBlock *Block = Blocks[BlockNo];
+ Buff.readInt(); // flag
+ while (Buff.getCursor() != (Size - 4)) {
+ StringRef Filename = Buff.readString();
+ if (Buff.getCursor() == (Size - 4)) break;
+ while (uint32_t L = Buff.readInt())
+ Block->addLine(Filename, L);
+ }
+ Buff.readInt(); // flag
+ }
+ return true;
+}
+
+/// dump - Dump GCOVFunction content on standard out for debugging purposes.
+void GCOVFunction::dump() {
+ outs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n";
+ for (SmallVector<GCOVBlock *, 16>::iterator I = Blocks.begin(),
+ E = Blocks.end(); I != E; ++I)
+ (*I)->dump();
+}
+
+/// collectLineCounts - Collect line counts. This must be used after
+/// reading .gcno and .gcda files.
+void GCOVFunction::collectLineCounts(FileInfo &FI) {
+ for (SmallVector<GCOVBlock *, 16>::iterator I = Blocks.begin(),
+ E = Blocks.end(); I != E; ++I)
+ (*I)->collectLineCounts(FI);
+}
+
+//===----------------------------------------------------------------------===//
+// GCOVBlock implementation.
+
+/// ~GCOVBlock - Delete GCOVBlock and its content.
+GCOVBlock::~GCOVBlock() {
+ Edges.clear();
+ DeleteContainerSeconds(Lines);
+}
+
+void GCOVBlock::addLine(StringRef Filename, uint32_t LineNo) {
+ GCOVLines *&LinesForFile = Lines[Filename];
+ if (!LinesForFile)
+ LinesForFile = new GCOVLines();
+ LinesForFile->add(LineNo);
+}
+
+/// collectLineCounts - Collect line counts. This must be used after
+/// reading .gcno and .gcda files.
+void GCOVBlock::collectLineCounts(FileInfo &FI) {
+ for (StringMap<GCOVLines *>::iterator I = Lines.begin(),
+ E = Lines.end(); I != E; ++I)
+ I->second->collectLineCounts(FI, I->first(), Counter);
+}
+
+/// dump - Dump GCOVBlock content on standard out for debugging purposes.
+void GCOVBlock::dump() {
+ outs() << "Block : " << Number << " Counter : " << Counter << "\n";
+ if (!Edges.empty()) {
+ outs() << "\tEdges : ";
+ for (SmallVector<uint32_t, 16>::iterator I = Edges.begin(), E = Edges.end();
+ I != E; ++I)
+ outs() << (*I) << ",";
+ outs() << "\n";
+ }
+ if (!Lines.empty()) {
+ outs() << "\tLines : ";
+ for (StringMap<GCOVLines *>::iterator LI = Lines.begin(),
+ LE = Lines.end(); LI != LE; ++LI) {
+ outs() << LI->first() << " -> ";
+ LI->second->dump();
+ outs() << "\n";
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// GCOVLines implementation.
+
+/// collectLineCounts - Collect line counts. This must be used after
+/// reading .gcno and .gcda files.
+void GCOVLines::collectLineCounts(FileInfo &FI, StringRef Filename,
+ uint32_t Count) {
+ for (SmallVector<uint32_t, 16>::iterator I = Lines.begin(),
+ E = Lines.end(); I != E; ++I)
+ FI.addLineCount(Filename, *I, Count);
+}
+
+/// dump - Dump GCOVLines content on standard out for debugging purposes.
+void GCOVLines::dump() {
+ for (SmallVector<uint32_t, 16>::iterator I = Lines.begin(),
+ E = Lines.end(); I != E; ++I)
+ outs() << (*I) << ",";
+}
+
+//===----------------------------------------------------------------------===//
+// FileInfo implementation.
+
+/// addLineCount - Add line count for the given line number in a file.
+void FileInfo::addLineCount(StringRef Filename, uint32_t Line, uint32_t Count) {
+ if (LineInfo.find(Filename) == LineInfo.end()) {
+ OwningPtr<MemoryBuffer> Buff;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
+ errs() << Filename << ": " << ec.message() << "\n";
+ return;
+ }
+ StringRef AllLines = Buff.take()->getBuffer();
+ LineCounts L(AllLines.count('\n')+2);
+ L[Line-1] = Count;
+ LineInfo[Filename] = L;
+ return;
+ }
+ LineCounts &L = LineInfo[Filename];
+ L[Line-1] = Count;
+}
+
+/// print - Print source files with collected line count information.
+void FileInfo::print() {
+ for (StringMap<LineCounts>::iterator I = LineInfo.begin(), E = LineInfo.end();
+ I != E; ++I) {
+ StringRef Filename = I->first();
+ outs() << Filename << "\n";
+ LineCounts &L = LineInfo[Filename];
+ OwningPtr<MemoryBuffer> Buff;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
+ errs() << Filename << ": " << ec.message() << "\n";
+ return;
+ }
+ StringRef AllLines = Buff.take()->getBuffer();
+ for (unsigned i = 0, e = L.size(); i != e; ++i) {
+ if (L[i])
+ outs() << L[i] << ":\t";
+ else
+ outs() << " :\t";
+ std::pair<StringRef, StringRef> P = AllLines.split('\n');
+ if (AllLines != P.first)
+ outs() << P.first;
+ outs() << "\n";
+ AllLines = P.second;
+ }
+ }
+}
+
+
diff --git a/lib/VMCore/Globals.cpp b/lib/VMCore/Globals.cpp
index db008e0..4254fb2 100644
--- a/lib/VMCore/Globals.cpp
+++ b/lib/VMCore/Globals.cpp
@@ -80,7 +80,7 @@ bool GlobalValue::isDeclaration() const {
// GlobalVariable Implementation
//===----------------------------------------------------------------------===//
-GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link,
+GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link,
Constant *InitVal, const Twine &Name,
bool ThreadLocal, unsigned AddressSpace)
: GlobalValue(PointerType::get(Ty, AddressSpace),
@@ -97,7 +97,7 @@ GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link,
LeakDetector::addGarbageObject(this);
}
-GlobalVariable::GlobalVariable(Module &M, const Type *Ty, bool constant,
+GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant,
LinkageTypes Link, Constant *InitVal,
const Twine &Name,
GlobalVariable *Before, bool ThreadLocal,
@@ -186,7 +186,7 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) {
// GlobalAlias Implementation
//===----------------------------------------------------------------------===//
-GlobalAlias::GlobalAlias(const Type *Ty, LinkageTypes Link,
+GlobalAlias::GlobalAlias(Type *Ty, LinkageTypes Link,
const Twine &Name, Constant* aliasee,
Module *ParentModule)
: GlobalValue(Ty, Value::GlobalAliasVal, &Op<0>(), 1, Link, Name) {
@@ -235,7 +235,7 @@ const GlobalValue *GlobalAlias::getAliasedGlobal() const {
CE->getOpcode() == Instruction::GetElementPtr) &&
"Unsupported aliasee");
- return dyn_cast<GlobalValue>(CE->getOperand(0));
+ return cast<GlobalValue>(CE->getOperand(0));
}
const GlobalValue *GlobalAlias::resolveAliasedGlobal(bool stopOnWeak) const {
diff --git a/lib/VMCore/IRBuilder.cpp b/lib/VMCore/IRBuilder.cpp
index ffe961f..5114e2d 100644
--- a/lib/VMCore/IRBuilder.cpp
+++ b/lib/VMCore/IRBuilder.cpp
@@ -40,7 +40,7 @@ Type *IRBuilderBase::getCurrentFunctionReturnType() const {
}
Value *IRBuilderBase::getCastedInt8PtrValue(Value *Ptr) {
- const PointerType *PT = cast<PointerType>(Ptr->getType());
+ PointerType *PT = cast<PointerType>(Ptr->getType());
if (PT->getElementType()->isIntegerTy(8))
return Ptr;
diff --git a/lib/VMCore/InlineAsm.cpp b/lib/VMCore/InlineAsm.cpp
index 4a03b39..736e370 100644
--- a/lib/VMCore/InlineAsm.cpp
+++ b/lib/VMCore/InlineAsm.cpp
@@ -25,7 +25,7 @@ InlineAsm::~InlineAsm() {
}
-InlineAsm *InlineAsm::get(const FunctionType *Ty, StringRef AsmString,
+InlineAsm *InlineAsm::get(FunctionType *Ty, StringRef AsmString,
StringRef Constraints, bool hasSideEffects,
bool isAlignStack) {
InlineAsmKeyType Key(AsmString, Constraints, hasSideEffects, isAlignStack);
@@ -33,7 +33,7 @@ InlineAsm *InlineAsm::get(const FunctionType *Ty, StringRef AsmString,
return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(Ty), Key);
}
-InlineAsm::InlineAsm(const PointerType *Ty, const std::string &asmString,
+InlineAsm::InlineAsm(PointerType *Ty, const std::string &asmString,
const std::string &constraints, bool hasSideEffects,
bool isAlignStack)
: Value(Ty, Value::InlineAsmVal),
@@ -242,7 +242,7 @@ InlineAsm::ParseConstraints(StringRef Constraints) {
/// Verify - Verify that the specified constraint string is reasonable for the
/// specified function type, and otherwise validate the constraint string.
-bool InlineAsm::Verify(const FunctionType *Ty, StringRef ConstStr) {
+bool InlineAsm::Verify(FunctionType *Ty, StringRef ConstStr) {
if (Ty->isVarArg()) return false;
ConstraintInfoVector Constraints = ParseConstraints(ConstStr);
@@ -282,7 +282,7 @@ bool InlineAsm::Verify(const FunctionType *Ty, StringRef ConstStr) {
if (Ty->getReturnType()->isStructTy()) return false;
break;
default:
- const StructType *STy = dyn_cast<StructType>(Ty->getReturnType());
+ StructType *STy = dyn_cast<StructType>(Ty->getReturnType());
if (STy == 0 || STy->getNumElements() != NumOutputs)
return false;
break;
diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp
index 02c0757..73191c1 100644
--- a/lib/VMCore/Instruction.cpp
+++ b/lib/VMCore/Instruction.cpp
@@ -20,7 +20,7 @@
#include "llvm/Support/LeakDetector.h"
using namespace llvm;
-Instruction::Instruction(const Type *ty, unsigned it, Use *Ops, unsigned NumOps,
+Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
Instruction *InsertBefore)
: User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(0) {
// Make sure that we get added to a basicblock
@@ -34,7 +34,7 @@ Instruction::Instruction(const Type *ty, unsigned it, Use *Ops, unsigned NumOps,
}
}
-Instruction::Instruction(const Type *ty, unsigned it, Use *Ops, unsigned NumOps,
+Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
BasicBlock *InsertAtEnd)
: User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(0) {
// Make sure that we get added to a basicblock
@@ -101,6 +101,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case Switch: return "switch";
case IndirectBr: return "indirectbr";
case Invoke: return "invoke";
+ case Resume: return "resume";
case Unwind: return "unwind";
case Unreachable: return "unreachable";
@@ -127,6 +128,9 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case Alloca: return "alloca";
case Load: return "load";
case Store: return "store";
+ case AtomicCmpXchg: return "cmpxchg";
+ case AtomicRMW: return "atomicrmw";
+ case Fence: return "fence";
case GetElementPtr: return "getelementptr";
// Convert instructions...
@@ -158,6 +162,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case ShuffleVector: return "shufflevector";
case ExtractValue: return "extractvalue";
case InsertValue: return "insertvalue";
+ case LandingPad: return "landingpad";
default: return "<Invalid operator> ";
}
@@ -191,10 +196,14 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const {
// Check special state that is a part of some instructions.
if (const LoadInst *LI = dyn_cast<LoadInst>(this))
return LI->isVolatile() == cast<LoadInst>(I)->isVolatile() &&
- LI->getAlignment() == cast<LoadInst>(I)->getAlignment();
+ LI->getAlignment() == cast<LoadInst>(I)->getAlignment() &&
+ LI->getOrdering() == cast<LoadInst>(I)->getOrdering() &&
+ LI->getSynchScope() == cast<LoadInst>(I)->getSynchScope();
if (const StoreInst *SI = dyn_cast<StoreInst>(this))
return SI->isVolatile() == cast<StoreInst>(I)->isVolatile() &&
- SI->getAlignment() == cast<StoreInst>(I)->getAlignment();
+ SI->getAlignment() == cast<StoreInst>(I)->getAlignment() &&
+ SI->getOrdering() == cast<StoreInst>(I)->getOrdering() &&
+ SI->getSynchScope() == cast<StoreInst>(I)->getSynchScope();
if (const CmpInst *CI = dyn_cast<CmpInst>(this))
return CI->getPredicate() == cast<CmpInst>(I)->getPredicate();
if (const CallInst *CI = dyn_cast<CallInst>(this))
@@ -208,6 +217,18 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const {
return IVI->getIndices() == cast<InsertValueInst>(I)->getIndices();
if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(this))
return EVI->getIndices() == cast<ExtractValueInst>(I)->getIndices();
+ if (const FenceInst *FI = dyn_cast<FenceInst>(this))
+ return FI->getOrdering() == cast<FenceInst>(FI)->getOrdering() &&
+ FI->getSynchScope() == cast<FenceInst>(FI)->getSynchScope();
+ if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(this))
+ return CXI->isVolatile() == cast<AtomicCmpXchgInst>(I)->isVolatile() &&
+ CXI->getOrdering() == cast<AtomicCmpXchgInst>(I)->getOrdering() &&
+ CXI->getSynchScope() == cast<AtomicCmpXchgInst>(I)->getSynchScope();
+ if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(this))
+ return RMWI->getOperation() == cast<AtomicRMWInst>(I)->getOperation() &&
+ RMWI->isVolatile() == cast<AtomicRMWInst>(I)->isVolatile() &&
+ RMWI->getOrdering() == cast<AtomicRMWInst>(I)->getOrdering() &&
+ RMWI->getSynchScope() == cast<AtomicRMWInst>(I)->getSynchScope();
return true;
}
@@ -230,10 +251,14 @@ bool Instruction::isSameOperationAs(const Instruction *I) const {
// Check special state that is a part of some instructions.
if (const LoadInst *LI = dyn_cast<LoadInst>(this))
return LI->isVolatile() == cast<LoadInst>(I)->isVolatile() &&
- LI->getAlignment() == cast<LoadInst>(I)->getAlignment();
+ LI->getAlignment() == cast<LoadInst>(I)->getAlignment() &&
+ LI->getOrdering() == cast<LoadInst>(I)->getOrdering() &&
+ LI->getSynchScope() == cast<LoadInst>(I)->getSynchScope();
if (const StoreInst *SI = dyn_cast<StoreInst>(this))
return SI->isVolatile() == cast<StoreInst>(I)->isVolatile() &&
- SI->getAlignment() == cast<StoreInst>(I)->getAlignment();
+ SI->getAlignment() == cast<StoreInst>(I)->getAlignment() &&
+ SI->getOrdering() == cast<StoreInst>(I)->getOrdering() &&
+ SI->getSynchScope() == cast<StoreInst>(I)->getSynchScope();
if (const CmpInst *CI = dyn_cast<CmpInst>(this))
return CI->getPredicate() == cast<CmpInst>(I)->getPredicate();
if (const CallInst *CI = dyn_cast<CallInst>(this))
@@ -248,6 +273,18 @@ bool Instruction::isSameOperationAs(const Instruction *I) const {
return IVI->getIndices() == cast<InsertValueInst>(I)->getIndices();
if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(this))
return EVI->getIndices() == cast<ExtractValueInst>(I)->getIndices();
+ if (const FenceInst *FI = dyn_cast<FenceInst>(this))
+ return FI->getOrdering() == cast<FenceInst>(I)->getOrdering() &&
+ FI->getSynchScope() == cast<FenceInst>(I)->getSynchScope();
+ if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(this))
+ return CXI->isVolatile() == cast<AtomicCmpXchgInst>(I)->isVolatile() &&
+ CXI->getOrdering() == cast<AtomicCmpXchgInst>(I)->getOrdering() &&
+ CXI->getSynchScope() == cast<AtomicCmpXchgInst>(I)->getSynchScope();
+ if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(this))
+ return RMWI->getOperation() == cast<AtomicRMWInst>(I)->getOperation() &&
+ RMWI->isVolatile() == cast<AtomicRMWInst>(I)->isVolatile() &&
+ RMWI->getOrdering() == cast<AtomicRMWInst>(I)->getOrdering() &&
+ RMWI->getSynchScope() == cast<AtomicRMWInst>(I)->getSynchScope();
return true;
}
@@ -280,13 +317,16 @@ bool Instruction::mayReadFromMemory() const {
default: return false;
case Instruction::VAArg:
case Instruction::Load:
+ case Instruction::Fence: // FIXME: refine definition of mayReadFromMemory
+ case Instruction::AtomicCmpXchg:
+ case Instruction::AtomicRMW:
return true;
case Instruction::Call:
return !cast<CallInst>(this)->doesNotAccessMemory();
case Instruction::Invoke:
return !cast<InvokeInst>(this)->doesNotAccessMemory();
case Instruction::Store:
- return cast<StoreInst>(this)->isVolatile();
+ return !cast<StoreInst>(this)->isUnordered();
}
}
@@ -295,15 +335,18 @@ bool Instruction::mayReadFromMemory() const {
bool Instruction::mayWriteToMemory() const {
switch (getOpcode()) {
default: return false;
+ case Instruction::Fence: // FIXME: refine definition of mayWriteToMemory
case Instruction::Store:
case Instruction::VAArg:
+ case Instruction::AtomicCmpXchg:
+ case Instruction::AtomicRMW:
return true;
case Instruction::Call:
return !cast<CallInst>(this)->onlyReadsMemory();
case Instruction::Invoke:
return !cast<InvokeInst>(this)->onlyReadsMemory();
case Instruction::Load:
- return cast<LoadInst>(this)->isVolatile();
+ return !cast<LoadInst>(this)->isUnordered();
}
}
@@ -312,7 +355,7 @@ bool Instruction::mayWriteToMemory() const {
bool Instruction::mayThrow() const {
if (const CallInst *CI = dyn_cast<CallInst>(this))
return !CI->doesNotThrow();
- return false;
+ return isa<ResumeInst>(this);
}
/// isAssociative - Return true if the instruction is associative:
@@ -372,7 +415,7 @@ bool Instruction::isSafeToSpeculativelyExecute() const {
}
case Load: {
const LoadInst *LI = cast<LoadInst>(this);
- if (LI->isVolatile())
+ if (!LI->isUnordered())
return false;
return LI->getPointerOperand()->isDereferenceablePointer();
}
@@ -392,6 +435,11 @@ bool Instruction::isSafeToSpeculativelyExecute() const {
case Switch:
case Unwind:
case Unreachable:
+ case Fence:
+ case LandingPad:
+ case AtomicRMW:
+ case AtomicCmpXchg:
+ case Resume:
return false; // Misc instructions which have effects
}
}
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp
index 9baad09..b3a7205 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -62,11 +62,11 @@ const char *SelectInst::areInvalidOperands(Value *Op0, Value *Op1, Value *Op2) {
if (Op1->getType() != Op2->getType())
return "both values to select must have same type";
- if (const VectorType *VT = dyn_cast<VectorType>(Op0->getType())) {
+ if (VectorType *VT = dyn_cast<VectorType>(Op0->getType())) {
// Vector select.
if (VT->getElementType() != Type::getInt1Ty(Op0->getContext()))
return "vector select condition element type must be i1";
- const VectorType *ET = dyn_cast<VectorType>(Op1->getType());
+ VectorType *ET = dyn_cast<VectorType>(Op1->getType());
if (ET == 0)
return "selected values for vector select must be vectors";
if (ET->getNumElements() != VT->getNumElements())
@@ -166,6 +166,88 @@ Value *PHINode::hasConstantValue() const {
return ConstantValue;
}
+//===----------------------------------------------------------------------===//
+// LandingPadInst Implementation
+//===----------------------------------------------------------------------===//
+
+LandingPadInst::LandingPadInst(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedValues, const Twine &NameStr,
+ Instruction *InsertBefore)
+ : Instruction(RetTy, Instruction::LandingPad, 0, 0, InsertBefore) {
+ init(PersonalityFn, 1 + NumReservedValues, NameStr);
+}
+
+LandingPadInst::LandingPadInst(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedValues, const Twine &NameStr,
+ BasicBlock *InsertAtEnd)
+ : Instruction(RetTy, Instruction::LandingPad, 0, 0, InsertAtEnd) {
+ init(PersonalityFn, 1 + NumReservedValues, NameStr);
+}
+
+LandingPadInst::LandingPadInst(const LandingPadInst &LP)
+ : Instruction(LP.getType(), Instruction::LandingPad,
+ allocHungoffUses(LP.getNumOperands()), LP.getNumOperands()),
+ ReservedSpace(LP.getNumOperands()) {
+ Use *OL = OperandList, *InOL = LP.OperandList;
+ for (unsigned I = 0, E = ReservedSpace; I != E; ++I)
+ OL[I] = InOL[I];
+
+ setCleanup(LP.isCleanup());
+}
+
+LandingPadInst::~LandingPadInst() {
+ dropHungoffUses();
+}
+
+LandingPadInst *LandingPadInst::Create(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedClauses,
+ const Twine &NameStr,
+ Instruction *InsertBefore) {
+ return new LandingPadInst(RetTy, PersonalityFn, NumReservedClauses, NameStr,
+ InsertBefore);
+}
+
+LandingPadInst *LandingPadInst::Create(Type *RetTy, Value *PersonalityFn,
+ unsigned NumReservedClauses,
+ const Twine &NameStr,
+ BasicBlock *InsertAtEnd) {
+ return new LandingPadInst(RetTy, PersonalityFn, NumReservedClauses, NameStr,
+ InsertAtEnd);
+}
+
+void LandingPadInst::init(Value *PersFn, unsigned NumReservedValues,
+ const Twine &NameStr) {
+ ReservedSpace = NumReservedValues;
+ NumOperands = 1;
+ OperandList = allocHungoffUses(ReservedSpace);
+ OperandList[0] = PersFn;
+ setName(NameStr);
+ setCleanup(false);
+}
+
+/// growOperands - grow operands - This grows the operand list in response to a
+/// push_back style of operation. This grows the number of ops by 2 times.
+void LandingPadInst::growOperands(unsigned Size) {
+ unsigned e = getNumOperands();
+ if (ReservedSpace >= e + Size) return;
+ ReservedSpace = (e + Size / 2) * 2;
+
+ Use *NewOps = allocHungoffUses(ReservedSpace);
+ Use *OldOps = OperandList;
+ for (unsigned i = 0; i != e; ++i)
+ NewOps[i] = OldOps[i];
+
+ OperandList = NewOps;
+ Use::zap(OldOps, OldOps + e, true);
+}
+
+void LandingPadInst::addClause(Value *Val) {
+ unsigned OpNo = getNumOperands();
+ growOperands(1);
+ assert(OpNo < ReservedSpace && "Growing didn't work!");
+ ++NumOperands;
+ OperandList[OpNo] = Val;
+}
//===----------------------------------------------------------------------===//
// CallInst Implementation
@@ -179,7 +261,7 @@ void CallInst::init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr) {
Op<-1>() = Func;
#ifndef NDEBUG
- const FunctionType *FTy =
+ FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
assert((Args.size() == FTy->getNumParams() ||
@@ -201,7 +283,7 @@ void CallInst::init(Value *Func, const Twine &NameStr) {
Op<-1>() = Func;
#ifndef NDEBUG
- const FunctionType *FTy =
+ FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
assert(FTy->getNumParams() == 0 && "Calling a function with bad signature");
@@ -269,8 +351,8 @@ static bool IsConstantOne(Value *val) {
}
static Instruction *createMalloc(Instruction *InsertBefore,
- BasicBlock *InsertAtEnd, const Type *IntPtrTy,
- const Type *AllocTy, Value *AllocSize,
+ BasicBlock *InsertAtEnd, Type *IntPtrTy,
+ Type *AllocTy, Value *AllocSize,
Value *ArraySize, Function *MallocF,
const Twine &Name) {
assert(((!InsertBefore && InsertAtEnd) || (InsertBefore && !InsertAtEnd)) &&
@@ -319,7 +401,7 @@ static Instruction *createMalloc(Instruction *InsertBefore,
if (!MallocFunc)
// prototype malloc as "void *malloc(size_t)"
MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy, NULL);
- const PointerType *AllocPtrType = PointerType::getUnqual(AllocTy);
+ PointerType *AllocPtrType = PointerType::getUnqual(AllocTy);
CallInst *MCall = NULL;
Instruction *Result = NULL;
if (InsertBefore) {
@@ -354,7 +436,7 @@ static Instruction *createMalloc(Instruction *InsertBefore,
/// 2. Call malloc with that argument.
/// 3. Bitcast the result of the malloc call to the specified type.
Instruction *CallInst::CreateMalloc(Instruction *InsertBefore,
- const Type *IntPtrTy, const Type *AllocTy,
+ Type *IntPtrTy, Type *AllocTy,
Value *AllocSize, Value *ArraySize,
Function * MallocF,
const Twine &Name) {
@@ -371,7 +453,7 @@ Instruction *CallInst::CreateMalloc(Instruction *InsertBefore,
/// Note: This function does not add the bitcast to the basic block, that is the
/// responsibility of the caller.
Instruction *CallInst::CreateMalloc(BasicBlock *InsertAtEnd,
- const Type *IntPtrTy, const Type *AllocTy,
+ Type *IntPtrTy, Type *AllocTy,
Value *AllocSize, Value *ArraySize,
Function *MallocF, const Twine &Name) {
return createMalloc(NULL, InsertAtEnd, IntPtrTy, AllocTy, AllocSize,
@@ -388,8 +470,8 @@ static Instruction* createFree(Value* Source, Instruction *InsertBefore,
BasicBlock* BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
Module* M = BB->getParent()->getParent();
- const Type *VoidTy = Type::getVoidTy(M->getContext());
- const Type *IntPtrTy = Type::getInt8PtrTy(M->getContext());
+ Type *VoidTy = Type::getVoidTy(M->getContext());
+ Type *IntPtrTy = Type::getInt8PtrTy(M->getContext());
// prototype free as "void free(void*)"
Value *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy, NULL);
CallInst* Result = NULL;
@@ -436,7 +518,7 @@ void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException,
Op<-1>() = IfException;
#ifndef NDEBUG
- const FunctionType *FTy =
+ FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType());
assert(((Args.size() == FTy->getNumParams()) ||
@@ -494,6 +576,9 @@ void InvokeInst::removeAttribute(unsigned i, Attributes attr) {
setAttributes(PAL);
}
+LandingPadInst *InvokeInst::getLandingPadInst() const {
+ return cast<LandingPadInst>(getUnwindDest()->getFirstNonPHI());
+}
//===----------------------------------------------------------------------===//
// ReturnInst Implementation
@@ -574,6 +659,41 @@ BasicBlock *UnwindInst::getSuccessorV(unsigned idx) const {
}
//===----------------------------------------------------------------------===//
+// ResumeInst Implementation
+//===----------------------------------------------------------------------===//
+
+ResumeInst::ResumeInst(const ResumeInst &RI)
+ : TerminatorInst(Type::getVoidTy(RI.getContext()), Instruction::Resume,
+ OperandTraits<ResumeInst>::op_begin(this), 1) {
+ Op<0>() = RI.Op<0>();
+}
+
+ResumeInst::ResumeInst(Value *Exn, Instruction *InsertBefore)
+ : TerminatorInst(Type::getVoidTy(Exn->getContext()), Instruction::Resume,
+ OperandTraits<ResumeInst>::op_begin(this), 1, InsertBefore) {
+ Op<0>() = Exn;
+}
+
+ResumeInst::ResumeInst(Value *Exn, BasicBlock *InsertAtEnd)
+ : TerminatorInst(Type::getVoidTy(Exn->getContext()), Instruction::Resume,
+ OperandTraits<ResumeInst>::op_begin(this), 1, InsertAtEnd) {
+ Op<0>() = Exn;
+}
+
+unsigned ResumeInst::getNumSuccessorsV() const {
+ return getNumSuccessors();
+}
+
+void ResumeInst::setSuccessorV(unsigned idx, BasicBlock *NewSucc) {
+ llvm_unreachable("ResumeInst has no successors!");
+}
+
+BasicBlock *ResumeInst::getSuccessorV(unsigned idx) const {
+ llvm_unreachable("ResumeInst has no successors!");
+ return 0;
+}
+
+//===----------------------------------------------------------------------===//
// UnreachableInst Implementation
//===----------------------------------------------------------------------===//
@@ -665,6 +785,27 @@ BranchInst::BranchInst(const BranchInst &BI) :
SubclassOptionalData = BI.SubclassOptionalData;
}
+void BranchInst::swapSuccessors() {
+ assert(isConditional() &&
+ "Cannot swap successors of an unconditional branch");
+ Op<-1>().swap(Op<-2>());
+
+ // Update profile metadata if present and it matches our structural
+ // expectations.
+ MDNode *ProfileData = getMetadata(LLVMContext::MD_prof);
+ if (!ProfileData || ProfileData->getNumOperands() != 3)
+ return;
+
+ // The first operand is the name. Fetch them backwards and build a new one.
+ Value *Ops[] = {
+ ProfileData->getOperand(0),
+ ProfileData->getOperand(2),
+ ProfileData->getOperand(1)
+ };
+ setMetadata(LLVMContext::MD_prof,
+ MDNode::get(ProfileData->getContext(), Ops));
+}
+
BasicBlock *BranchInst::getSuccessorV(unsigned idx) const {
return getSuccessor(idx);
}
@@ -692,7 +833,7 @@ static Value *getAISize(LLVMContext &Context, Value *Amt) {
return Amt;
}
-AllocaInst::AllocaInst(const Type *Ty, Value *ArraySize,
+AllocaInst::AllocaInst(Type *Ty, Value *ArraySize,
const Twine &Name, Instruction *InsertBefore)
: UnaryInstruction(PointerType::getUnqual(Ty), Alloca,
getAISize(Ty->getContext(), ArraySize), InsertBefore) {
@@ -701,7 +842,7 @@ AllocaInst::AllocaInst(const Type *Ty, Value *ArraySize,
setName(Name);
}
-AllocaInst::AllocaInst(const Type *Ty, Value *ArraySize,
+AllocaInst::AllocaInst(Type *Ty, Value *ArraySize,
const Twine &Name, BasicBlock *InsertAtEnd)
: UnaryInstruction(PointerType::getUnqual(Ty), Alloca,
getAISize(Ty->getContext(), ArraySize), InsertAtEnd) {
@@ -710,7 +851,7 @@ AllocaInst::AllocaInst(const Type *Ty, Value *ArraySize,
setName(Name);
}
-AllocaInst::AllocaInst(const Type *Ty, const Twine &Name,
+AllocaInst::AllocaInst(Type *Ty, const Twine &Name,
Instruction *InsertBefore)
: UnaryInstruction(PointerType::getUnqual(Ty), Alloca,
getAISize(Ty->getContext(), 0), InsertBefore) {
@@ -719,7 +860,7 @@ AllocaInst::AllocaInst(const Type *Ty, const Twine &Name,
setName(Name);
}
-AllocaInst::AllocaInst(const Type *Ty, const Twine &Name,
+AllocaInst::AllocaInst(Type *Ty, const Twine &Name,
BasicBlock *InsertAtEnd)
: UnaryInstruction(PointerType::getUnqual(Ty), Alloca,
getAISize(Ty->getContext(), 0), InsertAtEnd) {
@@ -728,7 +869,7 @@ AllocaInst::AllocaInst(const Type *Ty, const Twine &Name,
setName(Name);
}
-AllocaInst::AllocaInst(const Type *Ty, Value *ArraySize, unsigned Align,
+AllocaInst::AllocaInst(Type *Ty, Value *ArraySize, unsigned Align,
const Twine &Name, Instruction *InsertBefore)
: UnaryInstruction(PointerType::getUnqual(Ty), Alloca,
getAISize(Ty->getContext(), ArraySize), InsertBefore) {
@@ -737,7 +878,7 @@ AllocaInst::AllocaInst(const Type *Ty, Value *ArraySize, unsigned Align,
setName(Name);
}
-AllocaInst::AllocaInst(const Type *Ty, Value *ArraySize, unsigned Align,
+AllocaInst::AllocaInst(Type *Ty, Value *ArraySize, unsigned Align,
const Twine &Name, BasicBlock *InsertAtEnd)
: UnaryInstruction(PointerType::getUnqual(Ty), Alloca,
getAISize(Ty->getContext(), ArraySize), InsertAtEnd) {
@@ -787,6 +928,8 @@ bool AllocaInst::isStaticAlloca() const {
void LoadInst::AssertOK() {
assert(getOperand(0)->getType()->isPointerTy() &&
"Ptr must have pointer type.");
+ assert(!(isAtomic() && getAlignment() == 0) &&
+ "Alignment required for atomic load");
}
LoadInst::LoadInst(Value *Ptr, const Twine &Name, Instruction *InsertBef)
@@ -794,6 +937,7 @@ LoadInst::LoadInst(Value *Ptr, const Twine &Name, Instruction *InsertBef)
Load, Ptr, InsertBef) {
setVolatile(false);
setAlignment(0);
+ setAtomic(NotAtomic);
AssertOK();
setName(Name);
}
@@ -803,6 +947,7 @@ LoadInst::LoadInst(Value *Ptr, const Twine &Name, BasicBlock *InsertAE)
Load, Ptr, InsertAE) {
setVolatile(false);
setAlignment(0);
+ setAtomic(NotAtomic);
AssertOK();
setName(Name);
}
@@ -813,6 +958,18 @@ LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
Load, Ptr, InsertBef) {
setVolatile(isVolatile);
setAlignment(0);
+ setAtomic(NotAtomic);
+ AssertOK();
+ setName(Name);
+}
+
+LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
+ BasicBlock *InsertAE)
+ : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(),
+ Load, Ptr, InsertAE) {
+ setVolatile(isVolatile);
+ setAlignment(0);
+ setAtomic(NotAtomic);
AssertOK();
setName(Name);
}
@@ -823,6 +980,7 @@ LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
Load, Ptr, InsertBef) {
setVolatile(isVolatile);
setAlignment(Align);
+ setAtomic(NotAtomic);
AssertOK();
setName(Name);
}
@@ -833,27 +991,43 @@ LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
Load, Ptr, InsertAE) {
setVolatile(isVolatile);
setAlignment(Align);
+ setAtomic(NotAtomic);
AssertOK();
setName(Name);
}
-LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
+LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
+ unsigned Align, AtomicOrdering Order,
+ SynchronizationScope SynchScope,
+ Instruction *InsertBef)
+ : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(),
+ Load, Ptr, InsertBef) {
+ setVolatile(isVolatile);
+ setAlignment(Align);
+ setAtomic(Order, SynchScope);
+ AssertOK();
+ setName(Name);
+}
+
+LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
+ unsigned Align, AtomicOrdering Order,
+ SynchronizationScope SynchScope,
BasicBlock *InsertAE)
: UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(),
Load, Ptr, InsertAE) {
setVolatile(isVolatile);
- setAlignment(0);
+ setAlignment(Align);
+ setAtomic(Order, SynchScope);
AssertOK();
setName(Name);
}
-
-
LoadInst::LoadInst(Value *Ptr, const char *Name, Instruction *InsertBef)
: UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(),
Load, Ptr, InsertBef) {
setVolatile(false);
setAlignment(0);
+ setAtomic(NotAtomic);
AssertOK();
if (Name && Name[0]) setName(Name);
}
@@ -863,6 +1037,7 @@ LoadInst::LoadInst(Value *Ptr, const char *Name, BasicBlock *InsertAE)
Load, Ptr, InsertAE) {
setVolatile(false);
setAlignment(0);
+ setAtomic(NotAtomic);
AssertOK();
if (Name && Name[0]) setName(Name);
}
@@ -873,6 +1048,7 @@ LoadInst::LoadInst(Value *Ptr, const char *Name, bool isVolatile,
Load, Ptr, InsertBef) {
setVolatile(isVolatile);
setAlignment(0);
+ setAtomic(NotAtomic);
AssertOK();
if (Name && Name[0]) setName(Name);
}
@@ -883,6 +1059,7 @@ LoadInst::LoadInst(Value *Ptr, const char *Name, bool isVolatile,
Load, Ptr, InsertAE) {
setVolatile(isVolatile);
setAlignment(0);
+ setAtomic(NotAtomic);
AssertOK();
if (Name && Name[0]) setName(Name);
}
@@ -891,7 +1068,7 @@ void LoadInst::setAlignment(unsigned Align) {
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
assert(Align <= MaximumAlignment &&
"Alignment is greater than MaximumAlignment!");
- setInstructionSubclassData((getSubclassDataFromInstruction() & 1) |
+ setInstructionSubclassData((getSubclassDataFromInstruction() & ~(31 << 1)) |
((Log2_32(Align)+1)<<1));
assert(getAlignment() == Align && "Alignment representation error!");
}
@@ -907,6 +1084,8 @@ void StoreInst::AssertOK() {
assert(getOperand(0)->getType() ==
cast<PointerType>(getOperand(1)->getType())->getElementType()
&& "Ptr must be a pointer to Val type!");
+ assert(!(isAtomic() && getAlignment() == 0) &&
+ "Alignment required for atomic load");
}
@@ -919,6 +1098,7 @@ StoreInst::StoreInst(Value *val, Value *addr, Instruction *InsertBefore)
Op<1>() = addr;
setVolatile(false);
setAlignment(0);
+ setAtomic(NotAtomic);
AssertOK();
}
@@ -931,6 +1111,7 @@ StoreInst::StoreInst(Value *val, Value *addr, BasicBlock *InsertAtEnd)
Op<1>() = addr;
setVolatile(false);
setAlignment(0);
+ setAtomic(NotAtomic);
AssertOK();
}
@@ -944,6 +1125,7 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
Op<1>() = addr;
setVolatile(isVolatile);
setAlignment(0);
+ setAtomic(NotAtomic);
AssertOK();
}
@@ -957,6 +1139,37 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
Op<1>() = addr;
setVolatile(isVolatile);
setAlignment(Align);
+ setAtomic(NotAtomic);
+ AssertOK();
+}
+
+StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
+ unsigned Align, AtomicOrdering Order,
+ SynchronizationScope SynchScope,
+ Instruction *InsertBefore)
+ : Instruction(Type::getVoidTy(val->getContext()), Store,
+ OperandTraits<StoreInst>::op_begin(this),
+ OperandTraits<StoreInst>::operands(this),
+ InsertBefore) {
+ Op<0>() = val;
+ Op<1>() = addr;
+ setVolatile(isVolatile);
+ setAlignment(Align);
+ setAtomic(Order, SynchScope);
+ AssertOK();
+}
+
+StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
+ BasicBlock *InsertAtEnd)
+ : Instruction(Type::getVoidTy(val->getContext()), Store,
+ OperandTraits<StoreInst>::op_begin(this),
+ OperandTraits<StoreInst>::operands(this),
+ InsertAtEnd) {
+ Op<0>() = val;
+ Op<1>() = addr;
+ setVolatile(isVolatile);
+ setAlignment(0);
+ setAtomic(NotAtomic);
AssertOK();
}
@@ -970,10 +1183,13 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
Op<1>() = addr;
setVolatile(isVolatile);
setAlignment(Align);
+ setAtomic(NotAtomic);
AssertOK();
}
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
+ unsigned Align, AtomicOrdering Order,
+ SynchronizationScope SynchScope,
BasicBlock *InsertAtEnd)
: Instruction(Type::getVoidTy(val->getContext()), Store,
OperandTraits<StoreInst>::op_begin(this),
@@ -982,7 +1198,8 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
Op<0>() = val;
Op<1>() = addr;
setVolatile(isVolatile);
- setAlignment(0);
+ setAlignment(Align);
+ setAtomic(Order, SynchScope);
AssertOK();
}
@@ -990,37 +1207,135 @@ void StoreInst::setAlignment(unsigned Align) {
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
assert(Align <= MaximumAlignment &&
"Alignment is greater than MaximumAlignment!");
- setInstructionSubclassData((getSubclassDataFromInstruction() & 1) |
+ setInstructionSubclassData((getSubclassDataFromInstruction() & ~(31 << 1)) |
((Log2_32(Align)+1) << 1));
assert(getAlignment() == Align && "Alignment representation error!");
}
//===----------------------------------------------------------------------===//
-// GetElementPtrInst Implementation
+// AtomicCmpXchgInst Implementation
//===----------------------------------------------------------------------===//
-static unsigned retrieveAddrSpace(const Value *Val) {
- return cast<PointerType>(Val->getType())->getAddressSpace();
+void AtomicCmpXchgInst::Init(Value *Ptr, Value *Cmp, Value *NewVal,
+ AtomicOrdering Ordering,
+ SynchronizationScope SynchScope) {
+ Op<0>() = Ptr;
+ Op<1>() = Cmp;
+ Op<2>() = NewVal;
+ setOrdering(Ordering);
+ setSynchScope(SynchScope);
+
+ assert(getOperand(0) && getOperand(1) && getOperand(2) &&
+ "All operands must be non-null!");
+ assert(getOperand(0)->getType()->isPointerTy() &&
+ "Ptr must have pointer type!");
+ assert(getOperand(1)->getType() ==
+ cast<PointerType>(getOperand(0)->getType())->getElementType()
+ && "Ptr must be a pointer to Cmp type!");
+ assert(getOperand(2)->getType() ==
+ cast<PointerType>(getOperand(0)->getType())->getElementType()
+ && "Ptr must be a pointer to NewVal type!");
+ assert(Ordering != NotAtomic &&
+ "AtomicCmpXchg instructions must be atomic!");
+}
+
+AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
+ AtomicOrdering Ordering,
+ SynchronizationScope SynchScope,
+ Instruction *InsertBefore)
+ : Instruction(Cmp->getType(), AtomicCmpXchg,
+ OperandTraits<AtomicCmpXchgInst>::op_begin(this),
+ OperandTraits<AtomicCmpXchgInst>::operands(this),
+ InsertBefore) {
+ Init(Ptr, Cmp, NewVal, Ordering, SynchScope);
}
-void GetElementPtrInst::init(Value *Ptr, Value* const *Idx, unsigned NumIdx,
- const Twine &Name) {
- assert(NumOperands == 1+NumIdx && "NumOperands not initialized?");
- Use *OL = OperandList;
- OL[0] = Ptr;
+AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
+ AtomicOrdering Ordering,
+ SynchronizationScope SynchScope,
+ BasicBlock *InsertAtEnd)
+ : Instruction(Cmp->getType(), AtomicCmpXchg,
+ OperandTraits<AtomicCmpXchgInst>::op_begin(this),
+ OperandTraits<AtomicCmpXchgInst>::operands(this),
+ InsertAtEnd) {
+ Init(Ptr, Cmp, NewVal, Ordering, SynchScope);
+}
+
+//===----------------------------------------------------------------------===//
+// AtomicRMWInst Implementation
+//===----------------------------------------------------------------------===//
- for (unsigned i = 0; i != NumIdx; ++i)
- OL[i+1] = Idx[i];
+void AtomicRMWInst::Init(BinOp Operation, Value *Ptr, Value *Val,
+ AtomicOrdering Ordering,
+ SynchronizationScope SynchScope) {
+ Op<0>() = Ptr;
+ Op<1>() = Val;
+ setOperation(Operation);
+ setOrdering(Ordering);
+ setSynchScope(SynchScope);
- setName(Name);
+ assert(getOperand(0) && getOperand(1) &&
+ "All operands must be non-null!");
+ assert(getOperand(0)->getType()->isPointerTy() &&
+ "Ptr must have pointer type!");
+ assert(getOperand(1)->getType() ==
+ cast<PointerType>(getOperand(0)->getType())->getElementType()
+ && "Ptr must be a pointer to Val type!");
+ assert(Ordering != NotAtomic &&
+ "AtomicRMW instructions must be atomic!");
}
-void GetElementPtrInst::init(Value *Ptr, Value *Idx, const Twine &Name) {
- assert(NumOperands == 2 && "NumOperands not initialized?");
- Use *OL = OperandList;
- OL[0] = Ptr;
- OL[1] = Idx;
+AtomicRMWInst::AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
+ AtomicOrdering Ordering,
+ SynchronizationScope SynchScope,
+ Instruction *InsertBefore)
+ : Instruction(Val->getType(), AtomicRMW,
+ OperandTraits<AtomicRMWInst>::op_begin(this),
+ OperandTraits<AtomicRMWInst>::operands(this),
+ InsertBefore) {
+ Init(Operation, Ptr, Val, Ordering, SynchScope);
+}
+
+AtomicRMWInst::AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
+ AtomicOrdering Ordering,
+ SynchronizationScope SynchScope,
+ BasicBlock *InsertAtEnd)
+ : Instruction(Val->getType(), AtomicRMW,
+ OperandTraits<AtomicRMWInst>::op_begin(this),
+ OperandTraits<AtomicRMWInst>::operands(this),
+ InsertAtEnd) {
+ Init(Operation, Ptr, Val, Ordering, SynchScope);
+}
+
+//===----------------------------------------------------------------------===//
+// FenceInst Implementation
+//===----------------------------------------------------------------------===//
+
+FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering,
+ SynchronizationScope SynchScope,
+ Instruction *InsertBefore)
+ : Instruction(Type::getVoidTy(C), Fence, 0, 0, InsertBefore) {
+ setOrdering(Ordering);
+ setSynchScope(SynchScope);
+}
+FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering,
+ SynchronizationScope SynchScope,
+ BasicBlock *InsertAtEnd)
+ : Instruction(Type::getVoidTy(C), Fence, 0, 0, InsertAtEnd) {
+ setOrdering(Ordering);
+ setSynchScope(SynchScope);
+}
+
+//===----------------------------------------------------------------------===//
+// GetElementPtrInst Implementation
+//===----------------------------------------------------------------------===//
+
+void GetElementPtrInst::init(Value *Ptr, ArrayRef<Value *> IdxList,
+ const Twine &Name) {
+ assert(NumOperands == 1 + IdxList.size() && "NumOperands not initialized?");
+ OperandList[0] = Ptr;
+ std::copy(IdxList.begin(), IdxList.end(), op_begin() + 1);
setName(Name);
}
@@ -1029,34 +1344,10 @@ GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI)
OperandTraits<GetElementPtrInst>::op_end(this)
- GEPI.getNumOperands(),
GEPI.getNumOperands()) {
- Use *OL = OperandList;
- Use *GEPIOL = GEPI.OperandList;
- for (unsigned i = 0, E = NumOperands; i != E; ++i)
- OL[i] = GEPIOL[i];
+ std::copy(GEPI.op_begin(), GEPI.op_end(), op_begin());
SubclassOptionalData = GEPI.SubclassOptionalData;
}
-GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
- const Twine &Name, Instruction *InBe)
- : Instruction(PointerType::get(
- checkGEPType(getIndexedType(Ptr->getType(),Idx)), retrieveAddrSpace(Ptr)),
- GetElementPtr,
- OperandTraits<GetElementPtrInst>::op_end(this) - 2,
- 2, InBe) {
- init(Ptr, Idx, Name);
-}
-
-GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
- const Twine &Name, BasicBlock *IAE)
- : Instruction(PointerType::get(
- checkGEPType(getIndexedType(Ptr->getType(),Idx)),
- retrieveAddrSpace(Ptr)),
- GetElementPtr,
- OperandTraits<GetElementPtrInst>::op_end(this) - 2,
- 2, IAE) {
- init(Ptr, Idx, Name);
-}
-
/// getIndexedType - Returns the type of the element that would be accessed with
/// a gep instruction with the specified parameters.
///
@@ -1067,14 +1358,13 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
/// pointer type.
///
template <typename IndexTy>
-static Type *getIndexedTypeInternal(const Type *Ptr, IndexTy const *Idxs,
- unsigned NumIdx) {
- const PointerType *PTy = dyn_cast<PointerType>(Ptr);
+static Type *getIndexedTypeInternal(Type *Ptr, ArrayRef<IndexTy> IdxList) {
+ PointerType *PTy = dyn_cast<PointerType>(Ptr);
if (!PTy) return 0; // Type isn't a pointer type!
Type *Agg = PTy->getElementType();
// Handle the special case of the empty set index set, which is always valid.
- if (NumIdx == 0)
+ if (IdxList.empty())
return Agg;
// If there is at least one index, the top level type must be sized, otherwise
@@ -1083,44 +1373,29 @@ static Type *getIndexedTypeInternal(const Type *Ptr, IndexTy const *Idxs,
return 0;
unsigned CurIdx = 1;
- for (; CurIdx != NumIdx; ++CurIdx) {
+ for (; CurIdx != IdxList.size(); ++CurIdx) {
CompositeType *CT = dyn_cast<CompositeType>(Agg);
if (!CT || CT->isPointerTy()) return 0;
- IndexTy Index = Idxs[CurIdx];
+ IndexTy Index = IdxList[CurIdx];
if (!CT->indexValid(Index)) return 0;
Agg = CT->getTypeAtIndex(Index);
}
- return CurIdx == NumIdx ? Agg : 0;
+ return CurIdx == IdxList.size() ? Agg : 0;
}
-Type *GetElementPtrInst::getIndexedType(const Type *Ptr, Value* const *Idxs,
- unsigned NumIdx) {
- return getIndexedTypeInternal(Ptr, Idxs, NumIdx);
+Type *GetElementPtrInst::getIndexedType(Type *Ptr, ArrayRef<Value *> IdxList) {
+ return getIndexedTypeInternal(Ptr, IdxList);
}
-Type *GetElementPtrInst::getIndexedType(const Type *Ptr,
- Constant* const *Idxs,
- unsigned NumIdx) {
- return getIndexedTypeInternal(Ptr, Idxs, NumIdx);
+Type *GetElementPtrInst::getIndexedType(Type *Ptr,
+ ArrayRef<Constant *> IdxList) {
+ return getIndexedTypeInternal(Ptr, IdxList);
}
-Type *GetElementPtrInst::getIndexedType(const Type *Ptr,
- uint64_t const *Idxs,
- unsigned NumIdx) {
- return getIndexedTypeInternal(Ptr, Idxs, NumIdx);
+Type *GetElementPtrInst::getIndexedType(Type *Ptr, ArrayRef<uint64_t> IdxList) {
+ return getIndexedTypeInternal(Ptr, IdxList);
}
-Type *GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) {
- const PointerType *PTy = dyn_cast<PointerType>(Ptr);
- if (!PTy) return 0; // Type isn't a pointer type!
-
- // Check the pointer index.
- if (!PTy->indexValid(Idx)) return 0;
-
- return PTy->getElementType();
-}
-
-
/// hasAllZeroIndices - Return true if all of the indices of this GEP are
/// zeros. If so, the result pointer and the first operand have the same
/// value, just potentially different types.
@@ -1286,13 +1561,13 @@ bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2,
if (!V1->getType()->isVectorTy() || V1->getType() != V2->getType())
return false;
- const VectorType *MaskTy = dyn_cast<VectorType>(Mask->getType());
+ VectorType *MaskTy = dyn_cast<VectorType>(Mask->getType());
if (MaskTy == 0 || !MaskTy->getElementType()->isIntegerTy(32))
return false;
// Check to see if Mask is valid.
if (const ConstantVector *MV = dyn_cast<ConstantVector>(Mask)) {
- const VectorType *VTy = cast<VectorType>(V1->getType());
+ VectorType *VTy = cast<VectorType>(V1->getType());
for (unsigned i = 0, e = MV->getNumOperands(); i != e; ++i) {
if (ConstantInt* CI = dyn_cast<ConstantInt>(MV->getOperand(i))) {
if (CI->uge(VTy->getNumElements()*2))
@@ -1382,7 +1657,7 @@ ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
// A null type is returned if the indices are invalid for the specified
// pointer type.
//
-Type *ExtractValueInst::getIndexedType(const Type *Agg,
+Type *ExtractValueInst::getIndexedType(Type *Agg,
ArrayRef<unsigned> Idxs) {
for (unsigned CurIdx = 0; CurIdx != Idxs.size(); ++CurIdx) {
unsigned Index = Idxs[CurIdx];
@@ -1392,10 +1667,10 @@ Type *ExtractValueInst::getIndexedType(const Type *Agg,
// insertvalue we need to check array indexing manually.
// Since the only other types we can index into are struct types it's just
// as easy to check those manually as well.
- if (const ArrayType *AT = dyn_cast<ArrayType>(Agg)) {
+ if (ArrayType *AT = dyn_cast<ArrayType>(Agg)) {
if (Index >= AT->getNumElements())
return 0;
- } else if (const StructType *ST = dyn_cast<StructType>(Agg)) {
+ } else if (StructType *ST = dyn_cast<StructType>(Agg)) {
if (Index >= ST->getNumElements())
return 0;
} else {
@@ -1413,7 +1688,7 @@ Type *ExtractValueInst::getIndexedType(const Type *Agg,
//===----------------------------------------------------------------------===//
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
- const Type *Ty, const Twine &Name,
+ Type *Ty, const Twine &Name,
Instruction *InsertBefore)
: Instruction(Ty, iType,
OperandTraits<BinaryOperator>::op_begin(this),
@@ -1426,7 +1701,7 @@ BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
}
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
- const Type *Ty, const Twine &Name,
+ Type *Ty, const Twine &Name,
BasicBlock *InsertAtEnd)
: Instruction(Ty, iType,
OperandTraits<BinaryOperator>::op_begin(this),
@@ -1589,7 +1864,7 @@ BinaryOperator *BinaryOperator::CreateFNeg(Value *Op, const Twine &Name,
BinaryOperator *BinaryOperator::CreateNot(Value *Op, const Twine &Name,
Instruction *InsertBefore) {
Constant *C;
- if (const VectorType *PTy = dyn_cast<VectorType>(Op->getType())) {
+ if (VectorType *PTy = dyn_cast<VectorType>(Op->getType())) {
C = Constant::getAllOnesValue(PTy->getElementType());
C = ConstantVector::get(
std::vector<Constant*>(PTy->getNumElements(), C));
@@ -1604,7 +1879,7 @@ BinaryOperator *BinaryOperator::CreateNot(Value *Op, const Twine &Name,
BinaryOperator *BinaryOperator::CreateNot(Value *Op, const Twine &Name,
BasicBlock *InsertAtEnd) {
Constant *AllOnes;
- if (const VectorType *PTy = dyn_cast<VectorType>(Op->getType())) {
+ if (VectorType *PTy = dyn_cast<VectorType>(Op->getType())) {
// Create a vector of all ones values.
Constant *Elt = Constant::getAllOnesValue(PTy->getElementType());
AllOnes = ConstantVector::get(
@@ -1743,8 +2018,8 @@ bool CastInst::isLosslessCast() const {
return false;
// Identity cast is always lossless
- const Type* SrcTy = getOperand(0)->getType();
- const Type* DstTy = getType();
+ Type* SrcTy = getOperand(0)->getType();
+ Type* DstTy = getType();
if (SrcTy == DstTy)
return true;
@@ -1763,12 +2038,12 @@ bool CastInst::isLosslessCast() const {
/// # ptrtoint i32* %x to i32 ; on 32-bit plaforms only
/// @brief Determine if the described cast is a no-op.
bool CastInst::isNoopCast(Instruction::CastOps Opcode,
- const Type *SrcTy,
- const Type *DestTy,
- const Type *IntPtrTy) {
+ Type *SrcTy,
+ Type *DestTy,
+ Type *IntPtrTy) {
switch (Opcode) {
default:
- assert(!"Invalid CastOp");
+ assert(0 && "Invalid CastOp");
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
@@ -1791,7 +2066,7 @@ bool CastInst::isNoopCast(Instruction::CastOps Opcode,
}
/// @brief Determine if a cast is a no-op.
-bool CastInst::isNoopCast(const Type *IntPtrTy) const {
+bool CastInst::isNoopCast(Type *IntPtrTy) const {
return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), IntPtrTy);
}
@@ -1805,8 +2080,7 @@ bool CastInst::isNoopCast(const Type *IntPtrTy) const {
/// If no such cast is permited, the function returns 0.
unsigned CastInst::isEliminableCastPair(
Instruction::CastOps firstOp, Instruction::CastOps secondOp,
- const Type *SrcTy, const Type *MidTy, const Type *DstTy, const Type *IntPtrTy)
-{
+ Type *SrcTy, Type *MidTy, Type *DstTy, Type *IntPtrTy) {
// Define the 144 possibilities for these two cast instructions. The values
// in this matrix determine what to do in a given situation and select the
// case in the switch below. The rows correspond to firstOp, the columns
@@ -1859,12 +2133,16 @@ unsigned CastInst::isEliminableCastPair(
};
// If either of the casts are a bitcast from scalar to vector, disallow the
- // merging.
- if ((firstOp == Instruction::BitCast &&
- isa<VectorType>(SrcTy) != isa<VectorType>(MidTy)) ||
- (secondOp == Instruction::BitCast &&
- isa<VectorType>(MidTy) != isa<VectorType>(DstTy)))
- return 0; // Disallowed
+ // merging. However, bitcast of A->B->A are allowed.
+ bool isFirstBitcast = (firstOp == Instruction::BitCast);
+ bool isSecondBitcast = (secondOp == Instruction::BitCast);
+ bool chainedBitcast = (SrcTy == DstTy && isFirstBitcast && isSecondBitcast);
+
+ // Check if any of the bitcasts convert scalars<->vectors.
+ if ((isFirstBitcast && isa<VectorType>(SrcTy) != isa<VectorType>(MidTy)) ||
+ (isSecondBitcast && isa<VectorType>(MidTy) != isa<VectorType>(DstTy)))
+ // Unless we are bitcasing to the original type, disallow optimizations.
+ if (!chainedBitcast) return 0;
int ElimCase = CastResults[firstOp-Instruction::CastOpsBegin]
[secondOp-Instruction::CastOpsBegin];
@@ -1958,16 +2236,16 @@ unsigned CastInst::isEliminableCastPair(
case 99:
// cast combination can't happen (error in input). This is for all cases
// where the MidTy is not the same for the two cast instructions.
- assert(!"Invalid Cast Combination");
+ assert(0 && "Invalid Cast Combination");
return 0;
default:
- assert(!"Error in CastResults table!!!");
+ assert(0 && "Error in CastResults table!!!");
return 0;
}
return 0;
}
-CastInst *CastInst::Create(Instruction::CastOps op, Value *S, const Type *Ty,
+CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
const Twine &Name, Instruction *InsertBefore) {
assert(castIsValid(op, S, Ty) && "Invalid cast!");
// Construct and return the appropriate CastInst subclass
@@ -1985,12 +2263,12 @@ CastInst *CastInst::Create(Instruction::CastOps op, Value *S, const Type *Ty,
case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertBefore);
case BitCast: return new BitCastInst (S, Ty, Name, InsertBefore);
default:
- assert(!"Invalid opcode provided");
+ assert(0 && "Invalid opcode provided");
}
return 0;
}
-CastInst *CastInst::Create(Instruction::CastOps op, Value *S, const Type *Ty,
+CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
const Twine &Name, BasicBlock *InsertAtEnd) {
assert(castIsValid(op, S, Ty) && "Invalid cast!");
// Construct and return the appropriate CastInst subclass
@@ -2008,12 +2286,12 @@ CastInst *CastInst::Create(Instruction::CastOps op, Value *S, const Type *Ty,
case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertAtEnd);
case BitCast: return new BitCastInst (S, Ty, Name, InsertAtEnd);
default:
- assert(!"Invalid opcode provided");
+ assert(0 && "Invalid opcode provided");
}
return 0;
}
-CastInst *CastInst::CreateZExtOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateZExtOrBitCast(Value *S, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
@@ -2021,7 +2299,7 @@ CastInst *CastInst::CreateZExtOrBitCast(Value *S, const Type *Ty,
return Create(Instruction::ZExt, S, Ty, Name, InsertBefore);
}
-CastInst *CastInst::CreateZExtOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateZExtOrBitCast(Value *S, Type *Ty,
const Twine &Name,
BasicBlock *InsertAtEnd) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
@@ -2029,7 +2307,7 @@ CastInst *CastInst::CreateZExtOrBitCast(Value *S, const Type *Ty,
return Create(Instruction::ZExt, S, Ty, Name, InsertAtEnd);
}
-CastInst *CastInst::CreateSExtOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateSExtOrBitCast(Value *S, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
@@ -2037,7 +2315,7 @@ CastInst *CastInst::CreateSExtOrBitCast(Value *S, const Type *Ty,
return Create(Instruction::SExt, S, Ty, Name, InsertBefore);
}
-CastInst *CastInst::CreateSExtOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateSExtOrBitCast(Value *S, Type *Ty,
const Twine &Name,
BasicBlock *InsertAtEnd) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
@@ -2045,7 +2323,7 @@ CastInst *CastInst::CreateSExtOrBitCast(Value *S, const Type *Ty,
return Create(Instruction::SExt, S, Ty, Name, InsertAtEnd);
}
-CastInst *CastInst::CreateTruncOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateTruncOrBitCast(Value *S, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
@@ -2053,7 +2331,7 @@ CastInst *CastInst::CreateTruncOrBitCast(Value *S, const Type *Ty,
return Create(Instruction::Trunc, S, Ty, Name, InsertBefore);
}
-CastInst *CastInst::CreateTruncOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateTruncOrBitCast(Value *S, Type *Ty,
const Twine &Name,
BasicBlock *InsertAtEnd) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
@@ -2061,7 +2339,7 @@ CastInst *CastInst::CreateTruncOrBitCast(Value *S, const Type *Ty,
return Create(Instruction::Trunc, S, Ty, Name, InsertAtEnd);
}
-CastInst *CastInst::CreatePointerCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty,
const Twine &Name,
BasicBlock *InsertAtEnd) {
assert(S->getType()->isPointerTy() && "Invalid cast");
@@ -2074,7 +2352,7 @@ CastInst *CastInst::CreatePointerCast(Value *S, const Type *Ty,
}
/// @brief Create a BitCast or a PtrToInt cast instruction
-CastInst *CastInst::CreatePointerCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
assert(S->getType()->isPointerTy() && "Invalid cast");
@@ -2086,7 +2364,7 @@ CastInst *CastInst::CreatePointerCast(Value *S, const Type *Ty,
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
}
-CastInst *CastInst::CreateIntegerCast(Value *C, const Type *Ty,
+CastInst *CastInst::CreateIntegerCast(Value *C, Type *Ty,
bool isSigned, const Twine &Name,
Instruction *InsertBefore) {
assert(C->getType()->isIntOrIntVectorTy() && Ty->isIntOrIntVectorTy() &&
@@ -2100,7 +2378,7 @@ CastInst *CastInst::CreateIntegerCast(Value *C, const Type *Ty,
return Create(opcode, C, Ty, Name, InsertBefore);
}
-CastInst *CastInst::CreateIntegerCast(Value *C, const Type *Ty,
+CastInst *CastInst::CreateIntegerCast(Value *C, Type *Ty,
bool isSigned, const Twine &Name,
BasicBlock *InsertAtEnd) {
assert(C->getType()->isIntOrIntVectorTy() && Ty->isIntOrIntVectorTy() &&
@@ -2114,7 +2392,7 @@ CastInst *CastInst::CreateIntegerCast(Value *C, const Type *Ty,
return Create(opcode, C, Ty, Name, InsertAtEnd);
}
-CastInst *CastInst::CreateFPCast(Value *C, const Type *Ty,
+CastInst *CastInst::CreateFPCast(Value *C, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() &&
@@ -2127,7 +2405,7 @@ CastInst *CastInst::CreateFPCast(Value *C, const Type *Ty,
return Create(opcode, C, Ty, Name, InsertBefore);
}
-CastInst *CastInst::CreateFPCast(Value *C, const Type *Ty,
+CastInst *CastInst::CreateFPCast(Value *C, Type *Ty,
const Twine &Name,
BasicBlock *InsertAtEnd) {
assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() &&
@@ -2142,15 +2420,15 @@ CastInst *CastInst::CreateFPCast(Value *C, const Type *Ty,
// Check whether it is valid to call getCastOpcode for these types.
// This routine must be kept in sync with getCastOpcode.
-bool CastInst::isCastable(const Type *SrcTy, const Type *DestTy) {
+bool CastInst::isCastable(Type *SrcTy, Type *DestTy) {
if (!SrcTy->isFirstClassType() || !DestTy->isFirstClassType())
return false;
if (SrcTy == DestTy)
return true;
- if (const VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy))
- if (const VectorType *DestVecTy = dyn_cast<VectorType>(DestTy))
+ if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy))
+ if (VectorType *DestVecTy = dyn_cast<VectorType>(DestTy))
if (SrcVecTy->getNumElements() == DestVecTy->getNumElements()) {
// An element by element cast. Valid if casting the elements is valid.
SrcTy = SrcVecTy->getElementType();
@@ -2212,8 +2490,8 @@ bool CastInst::isCastable(const Type *SrcTy, const Type *DestTy) {
// This routine must be kept in sync with isCastable.
Instruction::CastOps
CastInst::getCastOpcode(
- const Value *Src, bool SrcIsSigned, const Type *DestTy, bool DestIsSigned) {
- const Type *SrcTy = Src->getType();
+ const Value *Src, bool SrcIsSigned, Type *DestTy, bool DestIsSigned) {
+ Type *SrcTy = Src->getType();
assert(SrcTy->isFirstClassType() && DestTy->isFirstClassType() &&
"Only first class types are castable!");
@@ -2221,8 +2499,8 @@ CastInst::getCastOpcode(
if (SrcTy == DestTy)
return BitCast;
- if (const VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy))
- if (const VectorType *DestVecTy = dyn_cast<VectorType>(DestTy))
+ if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy))
+ if (VectorType *DestVecTy = dyn_cast<VectorType>(DestTy))
if (SrcVecTy->getNumElements() == DestVecTy->getNumElements()) {
// An element by element cast. Find the appropriate opcode based on the
// element types.
@@ -2292,17 +2570,17 @@ CastInst::getCastOpcode(
} else if (SrcTy->isIntegerTy()) {
return IntToPtr; // int -> ptr
} else {
- assert(!"Casting pointer to other than pointer or int");
+ assert(0 && "Casting pointer to other than pointer or int");
}
} else if (DestTy->isX86_MMXTy()) {
if (SrcTy->isVectorTy()) {
assert(DestBits == SrcBits && "Casting vector of wrong width to X86_MMX");
return BitCast; // 64-bit vector to MMX
} else {
- assert(!"Illegal cast to X86_MMX");
+ assert(0 && "Illegal cast to X86_MMX");
}
} else {
- assert(!"Casting to type that is not first-class");
+ assert(0 && "Casting to type that is not first-class");
}
// If we fall through to here we probably hit an assertion cast above
@@ -2320,10 +2598,10 @@ CastInst::getCastOpcode(
/// it in one place and to eliminate the redundant code for getting the sizes
/// of the types involved.
bool
-CastInst::castIsValid(Instruction::CastOps op, Value *S, const Type *DstTy) {
+CastInst::castIsValid(Instruction::CastOps op, Value *S, Type *DstTy) {
// Check for type sanity on the arguments
- const Type *SrcTy = S->getType();
+ Type *SrcTy = S->getType();
if (!SrcTy->isFirstClassType() || !DstTy->isFirstClassType() ||
SrcTy->isAggregateType() || DstTy->isAggregateType())
return false;
@@ -2384,144 +2662,144 @@ CastInst::castIsValid(Instruction::CastOps op, Value *S, const Type *DstTy) {
}
TruncInst::TruncInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, Trunc, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal Trunc");
}
TruncInst::TruncInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, Trunc, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal Trunc");
}
ZExtInst::ZExtInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, ZExt, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal ZExt");
}
ZExtInst::ZExtInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, ZExt, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal ZExt");
}
SExtInst::SExtInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, SExt, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SExt");
}
SExtInst::SExtInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, SExt, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SExt");
}
FPTruncInst::FPTruncInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, FPTrunc, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPTrunc");
}
FPTruncInst::FPTruncInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPTrunc, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPTrunc");
}
FPExtInst::FPExtInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, FPExt, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPExt");
}
FPExtInst::FPExtInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPExt, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPExt");
}
UIToFPInst::UIToFPInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, UIToFP, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal UIToFP");
}
UIToFPInst::UIToFPInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, UIToFP, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal UIToFP");
}
SIToFPInst::SIToFPInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, SIToFP, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SIToFP");
}
SIToFPInst::SIToFPInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, SIToFP, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SIToFP");
}
FPToUIInst::FPToUIInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, FPToUI, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToUI");
}
FPToUIInst::FPToUIInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPToUI, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToUI");
}
FPToSIInst::FPToSIInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, FPToSI, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToSI");
}
FPToSIInst::FPToSIInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPToSI, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToSI");
}
PtrToIntInst::PtrToIntInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, PtrToInt, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal PtrToInt");
}
PtrToIntInst::PtrToIntInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, PtrToInt, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal PtrToInt");
}
IntToPtrInst::IntToPtrInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, IntToPtr, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal IntToPtr");
}
IntToPtrInst::IntToPtrInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, IntToPtr, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal IntToPtr");
}
BitCastInst::BitCastInst(
- Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, BitCast, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal BitCast");
}
BitCastInst::BitCastInst(
- Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, BitCast, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal BitCast");
}
@@ -2532,7 +2810,7 @@ BitCastInst::BitCastInst(
void CmpInst::Anchor() const {}
-CmpInst::CmpInst(const Type *ty, OtherOps op, unsigned short predicate,
+CmpInst::CmpInst(Type *ty, OtherOps op, unsigned short predicate,
Value *LHS, Value *RHS, const Twine &Name,
Instruction *InsertBefore)
: Instruction(ty, op,
@@ -2545,7 +2823,7 @@ CmpInst::CmpInst(const Type *ty, OtherOps op, unsigned short predicate,
setName(Name);
}
-CmpInst::CmpInst(const Type *ty, OtherOps op, unsigned short predicate,
+CmpInst::CmpInst(Type *ty, OtherOps op, unsigned short predicate,
Value *LHS, Value *RHS, const Twine &Name,
BasicBlock *InsertAtEnd)
: Instruction(ty, op,
@@ -2612,7 +2890,7 @@ bool CmpInst::isEquality() const {
CmpInst::Predicate CmpInst::getInversePredicate(Predicate pred) {
switch (pred) {
- default: assert(!"Unknown cmp predicate!");
+ default: assert(0 && "Unknown cmp predicate!");
case ICMP_EQ: return ICMP_NE;
case ICMP_NE: return ICMP_EQ;
case ICMP_UGT: return ICMP_ULE;
@@ -2645,7 +2923,7 @@ CmpInst::Predicate CmpInst::getInversePredicate(Predicate pred) {
ICmpInst::Predicate ICmpInst::getSignedPredicate(Predicate pred) {
switch (pred) {
- default: assert(! "Unknown icmp predicate!");
+ default: assert(0 && "Unknown icmp predicate!");
case ICMP_EQ: case ICMP_NE:
case ICMP_SGT: case ICMP_SLT: case ICMP_SGE: case ICMP_SLE:
return pred;
@@ -2658,7 +2936,7 @@ ICmpInst::Predicate ICmpInst::getSignedPredicate(Predicate pred) {
ICmpInst::Predicate ICmpInst::getUnsignedPredicate(Predicate pred) {
switch (pred) {
- default: assert(! "Unknown icmp predicate!");
+ default: assert(0 && "Unknown icmp predicate!");
case ICMP_EQ: case ICMP_NE:
case ICMP_UGT: case ICMP_ULT: case ICMP_UGE: case ICMP_ULE:
return pred;
@@ -2734,7 +3012,7 @@ ICmpInst::makeConstantRange(Predicate pred, const APInt &C) {
CmpInst::Predicate CmpInst::getSwappedPredicate(Predicate pred) {
switch (pred) {
- default: assert(!"Unknown cmp predicate!");
+ default: assert(0 && "Unknown cmp predicate!");
case ICMP_EQ: case ICMP_NE:
return pred;
case ICMP_SGT: return ICMP_SLT;
@@ -3065,14 +3343,34 @@ AllocaInst *AllocaInst::clone_impl() const {
}
LoadInst *LoadInst::clone_impl() const {
- return new LoadInst(getOperand(0),
- Twine(), isVolatile(),
- getAlignment());
+ return new LoadInst(getOperand(0), Twine(), isVolatile(),
+ getAlignment(), getOrdering(), getSynchScope());
}
StoreInst *StoreInst::clone_impl() const {
- return new StoreInst(getOperand(0), getOperand(1),
- isVolatile(), getAlignment());
+ return new StoreInst(getOperand(0), getOperand(1), isVolatile(),
+ getAlignment(), getOrdering(), getSynchScope());
+
+}
+
+AtomicCmpXchgInst *AtomicCmpXchgInst::clone_impl() const {
+ AtomicCmpXchgInst *Result =
+ new AtomicCmpXchgInst(getOperand(0), getOperand(1), getOperand(2),
+ getOrdering(), getSynchScope());
+ Result->setVolatile(isVolatile());
+ return Result;
+}
+
+AtomicRMWInst *AtomicRMWInst::clone_impl() const {
+ AtomicRMWInst *Result =
+ new AtomicRMWInst(getOperation(),getOperand(0), getOperand(1),
+ getOrdering(), getSynchScope());
+ Result->setVolatile(isVolatile());
+ return Result;
+}
+
+FenceInst *FenceInst::clone_impl() const {
+ return new FenceInst(getContext(), getOrdering(), getSynchScope());
}
TruncInst *TruncInst::clone_impl() const {
@@ -3155,6 +3453,10 @@ PHINode *PHINode::clone_impl() const {
return new PHINode(*this);
}
+LandingPadInst *LandingPadInst::clone_impl() const {
+ return new LandingPadInst(*this);
+}
+
ReturnInst *ReturnInst::clone_impl() const {
return new(getNumOperands()) ReturnInst(*this);
}
@@ -3176,6 +3478,10 @@ InvokeInst *InvokeInst::clone_impl() const {
return new(getNumOperands()) InvokeInst(*this);
}
+ResumeInst *ResumeInst::clone_impl() const {
+ return new(1) ResumeInst(*this);
+}
+
UnwindInst *UnwindInst::clone_impl() const {
LLVMContext &Context = getContext();
return new UnwindInst(Context);
diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h
index 06a6f2a..a3f68fe 100644
--- a/lib/VMCore/LLVMContextImpl.h
+++ b/lib/VMCore/LLVMContextImpl.h
@@ -42,8 +42,8 @@ class Value;
struct DenseMapAPIntKeyInfo {
struct KeyTy {
APInt val;
- const Type* type;
- KeyTy(const APInt& V, const Type* Ty) : val(V), type(Ty) {}
+ Type* type;
+ KeyTy(const APInt& V, Type* Ty) : val(V), type(Ty) {}
KeyTy(const KeyTy& that) : val(that.val), type(that.type) {}
bool operator==(const KeyTy& that) const {
return type == that.type && this->val == that.val;
diff --git a/lib/VMCore/Makefile b/lib/VMCore/Makefile
index 03a4fc7..2b9b0f2 100644
--- a/lib/VMCore/Makefile
+++ b/lib/VMCore/Makefile
@@ -20,9 +20,9 @@ GENFILE:=$(PROJ_OBJ_ROOT)/include/llvm/Intrinsics.gen
INTRINSICTD := $(PROJ_SRC_ROOT)/include/llvm/Intrinsics.td
INTRINSICTDS := $(wildcard $(PROJ_SRC_ROOT)/include/llvm/Intrinsics*.td)
-$(ObjDir)/Intrinsics.gen.tmp: $(ObjDir)/.dir $(INTRINSICTDS) $(TBLGEN)
+$(ObjDir)/Intrinsics.gen.tmp: $(ObjDir)/.dir $(INTRINSICTDS) $(LLVM_TBLGEN)
$(Echo) Building Intrinsics.gen.tmp from Intrinsics.td
- $(Verb) $(TableGen) $(call SYSPATH, $(INTRINSICTD)) -o $(call SYSPATH, $@) -gen-intrinsic
+ $(Verb) $(LLVMTableGen) $(call SYSPATH, $(INTRINSICTD)) -o $(call SYSPATH, $@) -gen-intrinsic
$(GENFILE): $(ObjDir)/Intrinsics.gen.tmp
$(Verb) $(CMP) -s $@ $< || ( $(CP) $< $@ && \
diff --git a/lib/VMCore/Module.cpp b/lib/VMCore/Module.cpp
index be2fcb8..c29029b 100644
--- a/lib/VMCore/Module.cpp
+++ b/lib/VMCore/Module.cpp
@@ -32,25 +32,10 @@ using namespace llvm;
// Methods to implement the globals and functions lists.
//
-GlobalVariable *ilist_traits<GlobalVariable>::createSentinel() {
- GlobalVariable *Ret = new GlobalVariable(Type::getInt32Ty(getGlobalContext()),
- false, GlobalValue::ExternalLinkage);
- // This should not be garbage monitored.
- LeakDetector::removeGarbageObject(Ret);
- return Ret;
-}
-GlobalAlias *ilist_traits<GlobalAlias>::createSentinel() {
- GlobalAlias *Ret = new GlobalAlias(Type::getInt32Ty(getGlobalContext()),
- GlobalValue::ExternalLinkage);
- // This should not be garbage monitored.
- LeakDetector::removeGarbageObject(Ret);
- return Ret;
-}
-
// Explicit instantiations of SymbolTableListTraits since some of the methods
// are not in the public header file.
-template class llvm::SymbolTableListTraits<GlobalVariable, Module>;
template class llvm::SymbolTableListTraits<Function, Module>;
+template class llvm::SymbolTableListTraits<GlobalVariable, Module>;
template class llvm::SymbolTableListTraits<GlobalAlias, Module>;
//===----------------------------------------------------------------------===//
@@ -82,8 +67,10 @@ Module::Endianness Module::getEndianness() const {
Module::Endianness ret = AnyEndianness;
while (!temp.empty()) {
- StringRef token = DataLayout;
- tie(token, temp) = getToken(temp, "-");
+ std::pair<StringRef, StringRef> P = getToken(temp, "-");
+
+ StringRef token = P.first;
+ temp = P.second;
if (token[0] == 'e') {
ret = LittleEndian;
@@ -95,15 +82,16 @@ Module::Endianness Module::getEndianness() const {
return ret;
}
-/// Target Pointer Size information...
+/// Target Pointer Size information.
Module::PointerSize Module::getPointerSize() const {
StringRef temp = DataLayout;
Module::PointerSize ret = AnyPointerSize;
while (!temp.empty()) {
- StringRef token, signalToken;
- tie(token, temp) = getToken(temp, "-");
- tie(signalToken, token) = getToken(token, ":");
+ std::pair<StringRef, StringRef> TmpP = getToken(temp, "-");
+ temp = TmpP.second;
+ TmpP = getToken(TmpP.first, ":");
+ StringRef token = TmpP.second, signalToken = TmpP.first;
if (signalToken[0] == 'p') {
int size = 0;
@@ -149,7 +137,7 @@ void Module::getMDKindNames(SmallVectorImpl<StringRef> &Result) const {
// the symbol table directly for this common task.
//
Constant *Module::getOrInsertFunction(StringRef Name,
- const FunctionType *Ty,
+ FunctionType *Ty,
AttrListPtr AttributeList) {
// See if we have a definition for the specified function already.
GlobalValue *F = getNamedValue(Name);
@@ -182,7 +170,7 @@ Constant *Module::getOrInsertFunction(StringRef Name,
}
Constant *Module::getOrInsertTargetIntrinsic(StringRef Name,
- const FunctionType *Ty,
+ FunctionType *Ty,
AttrListPtr AttributeList) {
// See if we have a definition for the specified function already.
GlobalValue *F = getNamedValue(Name);
@@ -199,7 +187,7 @@ Constant *Module::getOrInsertTargetIntrinsic(StringRef Name,
}
Constant *Module::getOrInsertFunction(StringRef Name,
- const FunctionType *Ty) {
+ FunctionType *Ty) {
AttrListPtr AttributeList = AttrListPtr::get((AttributeWithIndex *)0, 0);
return getOrInsertFunction(Name, Ty, AttributeList);
}
@@ -211,7 +199,7 @@ Constant *Module::getOrInsertFunction(StringRef Name,
//
Constant *Module::getOrInsertFunction(StringRef Name,
AttrListPtr AttributeList,
- const Type *RetTy, ...) {
+ Type *RetTy, ...) {
va_list Args;
va_start(Args, RetTy);
@@ -229,7 +217,7 @@ Constant *Module::getOrInsertFunction(StringRef Name,
}
Constant *Module::getOrInsertFunction(StringRef Name,
- const Type *RetTy, ...) {
+ Type *RetTy, ...) {
va_list Args;
va_start(Args, RetTy);
@@ -279,7 +267,7 @@ GlobalVariable *Module::getGlobalVariable(StringRef Name,
/// with a constantexpr cast to the right type.
/// 3. Finally, if the existing global is the correct delclaration, return the
/// existing global.
-Constant *Module::getOrInsertGlobal(StringRef Name, const Type *Ty) {
+Constant *Module::getOrInsertGlobal(StringRef Name, Type *Ty) {
// See if we have a definition for the specified global already.
GlobalVariable *GV = dyn_cast_or_null<GlobalVariable>(getNamedValue(Name));
if (GV == 0) {
@@ -436,7 +424,7 @@ namespace {
// To avoid walking constant expressions multiple times and other IR
// objects, we keep several helper maps.
DenseSet<const Value*> VisitedConstants;
- DenseSet<const Type*> VisitedTypes;
+ DenseSet<Type*> VisitedTypes;
std::vector<StructType*> &StructTypes;
public:
@@ -549,5 +537,3 @@ namespace {
void Module::findUsedStructTypes(std::vector<StructType*> &StructTypes) const {
TypeFinder(StructTypes).run(*this);
}
-
-
diff --git a/lib/VMCore/PassManager.cpp b/lib/VMCore/PassManager.cpp
index 5cf2905..ecedb1d 100644
--- a/lib/VMCore/PassManager.cpp
+++ b/lib/VMCore/PassManager.cpp
@@ -28,7 +28,6 @@
#include "llvm/Support/Mutex.h"
#include "llvm/ADT/StringMap.h"
#include <algorithm>
-#include <cstdio>
#include <map>
using namespace llvm;
@@ -167,8 +166,8 @@ class BBPassManager : public PMDataManager, public FunctionPass {
public:
static char ID;
- explicit BBPassManager(int Depth)
- : PMDataManager(Depth), FunctionPass(ID) {}
+ explicit BBPassManager()
+ : PMDataManager(), FunctionPass(ID) {}
/// Execute all of the passes scheduled for execution. Keep track of
/// whether any of the passes modifies the function, and if so, return true.
@@ -193,7 +192,7 @@ public:
// Print passes managed by this manager
void dumpPassStructure(unsigned Offset) {
- llvm::dbgs() << std::string(Offset*2, ' ') << "BasicBlockPass Manager\n";
+ llvm::dbgs().indent(Offset*2) << "BasicBlockPass Manager\n";
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
BasicBlockPass *BP = getContainedPass(Index);
BP->dumpPassStructure(Offset + 1);
@@ -228,9 +227,9 @@ private:
bool wasRun;
public:
static char ID;
- explicit FunctionPassManagerImpl(int Depth) :
- Pass(PT_PassManager, ID), PMDataManager(Depth),
- PMTopLevelManager(new FPPassManager(1)), wasRun(false) {}
+ explicit FunctionPassManagerImpl() :
+ Pass(PT_PassManager, ID), PMDataManager(),
+ PMTopLevelManager(new FPPassManager()), wasRun(false) {}
/// add - Add a pass to the queue of passes to run. This passes ownership of
/// the Pass to the PassManager. When the PassManager is destroyed, the pass
@@ -303,8 +302,8 @@ char FunctionPassManagerImpl::ID = 0;
class MPPassManager : public Pass, public PMDataManager {
public:
static char ID;
- explicit MPPassManager(int Depth) :
- Pass(PT_PassManager, ID), PMDataManager(Depth) { }
+ explicit MPPassManager() :
+ Pass(PT_PassManager, ID), PMDataManager() { }
// Delete on the fly managers.
virtual ~MPPassManager() {
@@ -349,7 +348,7 @@ public:
// Print passes managed by this manager
void dumpPassStructure(unsigned Offset) {
- llvm::dbgs() << std::string(Offset*2, ' ') << "ModulePass Manager\n";
+ llvm::dbgs().indent(Offset*2) << "ModulePass Manager\n";
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
ModulePass *MP = getContainedPass(Index);
MP->dumpPassStructure(Offset + 1);
@@ -388,9 +387,9 @@ class PassManagerImpl : public Pass,
public:
static char ID;
- explicit PassManagerImpl(int Depth) :
- Pass(PT_PassManager, ID), PMDataManager(Depth),
- PMTopLevelManager(new MPPassManager(1)) {}
+ explicit PassManagerImpl() :
+ Pass(PT_PassManager, ID), PMDataManager(),
+ PMTopLevelManager(new MPPassManager()) {}
/// add - Add a pass to the queue of passes to run. This passes ownership of
/// the Pass to the PassManager. When the PassManager is destroyed, the pass
@@ -1340,7 +1339,7 @@ bool BBPassManager::doFinalization(Function &F) {
/// Create new Function pass manager
FunctionPassManager::FunctionPassManager(Module *m) : M(m) {
- FPM = new FunctionPassManagerImpl(0);
+ FPM = new FunctionPassManagerImpl();
// FPM is the top level manager.
FPM->setTopLevelManager(FPM);
@@ -1532,7 +1531,7 @@ bool FPPassManager::runOnModule(Module &M) {
bool Changed = doInitialization(M);
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
- runOnFunction(*I);
+ Changed |= runOnFunction(*I);
return doFinalization(M) || Changed;
}
@@ -1626,7 +1625,7 @@ void MPPassManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) {
FunctionPassManagerImpl *FPP = OnTheFlyManagers[P];
if (!FPP) {
- FPP = new FunctionPassManagerImpl(0);
+ FPP = new FunctionPassManagerImpl();
// FPP is the top level manager.
FPP->setTopLevelManager(FPP);
@@ -1635,9 +1634,11 @@ void MPPassManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) {
FPP->add(RequiredPass);
// Register P as the last user of RequiredPass.
- SmallVector<Pass *, 1> LU;
- LU.push_back(RequiredPass);
- FPP->setLastUser(LU, P);
+ if (RequiredPass) {
+ SmallVector<Pass *, 1> LU;
+ LU.push_back(RequiredPass);
+ FPP->setLastUser(LU, P);
+ }
}
/// Return function pass corresponding to PassInfo PI, that is
@@ -1677,7 +1678,7 @@ bool PassManagerImpl::run(Module &M) {
/// Create new pass manager
PassManager::PassManager() {
- PM = new PassManagerImpl(0);
+ PM = new PassManagerImpl();
// PM is the top level manager
PM->setTopLevelManager(PM);
}
@@ -1761,13 +1762,23 @@ void PMStack::pop() {
// Push PM on the stack and set its top level manager.
void PMStack::push(PMDataManager *PM) {
assert(PM && "Unable to push. Pass Manager expected");
+ assert(PM->getDepth()==0 && "Pass Manager depth set too early");
if (!this->empty()) {
+ assert(PM->getPassManagerType() > this->top()->getPassManagerType()
+ && "pushing bad pass manager to PMStack");
PMTopLevelManager *TPM = this->top()->getTopLevelManager();
assert(TPM && "Unable to find top level manager");
TPM->addIndirectPassManager(PM);
PM->setTopLevelManager(TPM);
+ PM->setDepth(this->top()->getDepth()+1);
+ }
+ else {
+ assert((PM->getPassManagerType() == PMT_ModulePassManager
+ || PM->getPassManagerType() == PMT_FunctionPassManager)
+ && "pushing bad pass manager to PMStack");
+ PM->setDepth(1);
}
S.push_back(PM);
@@ -1777,10 +1788,10 @@ void PMStack::push(PMDataManager *PM) {
void PMStack::dump() const {
for (std::vector<PMDataManager *>::const_iterator I = S.begin(),
E = S.end(); I != E; ++I)
- printf("%s ", (*I)->getAsPass()->getPassName());
+ dbgs() << (*I)->getAsPass()->getPassName() << ' ';
if (!S.empty())
- printf("\n");
+ dbgs() << '\n';
}
/// Find appropriate Module Pass Manager in the PM Stack and
@@ -1823,7 +1834,7 @@ void FunctionPass::assignPassManager(PMStack &PMS,
PMDataManager *PMD = PMS.top();
// [1] Create new Function Pass Manager
- FPP = new FPPassManager(PMD->getDepth() + 1);
+ FPP = new FPPassManager();
FPP->populateInheritedAnalysis(PMS);
// [2] Set up new manager's top level manager
@@ -1860,7 +1871,7 @@ void BasicBlockPass::assignPassManager(PMStack &PMS,
PMDataManager *PMD = PMS.top();
// [1] Create new Basic Block Manager
- BBP = new BBPassManager(PMD->getDepth() + 1);
+ BBP = new BBPassManager();
// [2] Set up new manager's top level manager
// Basic Block Pass Manager does not live by itself
diff --git a/lib/VMCore/PassRegistry.cpp b/lib/VMCore/PassRegistry.cpp
index fa92620..2df6557 100644
--- a/lib/VMCore/PassRegistry.cpp
+++ b/lib/VMCore/PassRegistry.cpp
@@ -20,6 +20,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/Function.h"
#include <vector>
using namespace llvm;
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp
index f874d1b..10184bc 100644
--- a/lib/VMCore/Type.cpp
+++ b/lib/VMCore/Type.cpp
@@ -40,8 +40,8 @@ Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) {
/// getScalarType - If this is a vector type, return the element type,
/// otherwise return this.
-const Type *Type::getScalarType() const {
- if (const VectorType *VTy = dyn_cast<VectorType>(this))
+Type *Type::getScalarType() {
+ if (VectorType *VTy = dyn_cast<VectorType>(this))
return VTy->getElementType();
return this;
}
@@ -77,7 +77,7 @@ bool Type::isFPOrFPVectorTy() const {
// canLosslesslyBitCastTo - Return true if this type can be converted to
// 'Ty' without any reinterpretation of bits. For example, i8* to i32*.
//
-bool Type::canLosslesslyBitCastTo(const Type *Ty) const {
+bool Type::canLosslesslyBitCastTo(Type *Ty) const {
// Identity cast means no change so return true
if (this == Ty)
return true;
@@ -146,7 +146,7 @@ unsigned Type::getPrimitiveSizeInBits() const {
/// getScalarSizeInBits - If this is a vector type, return the
/// getPrimitiveSizeInBits value for the element type. Otherwise return the
/// getPrimitiveSizeInBits value for this type.
-unsigned Type::getScalarSizeInBits() const {
+unsigned Type::getScalarSizeInBits() {
return getScalarType()->getPrimitiveSizeInBits();
}
@@ -306,7 +306,7 @@ APInt IntegerType::getMask() const {
// FunctionType Implementation
//===----------------------------------------------------------------------===//
-FunctionType::FunctionType(const Type *Result, ArrayRef<Type*> Params,
+FunctionType::FunctionType(Type *Result, ArrayRef<Type*> Params,
bool IsVarArgs)
: Type(Result->getContext(), FunctionTyID) {
Type **SubTys = reinterpret_cast<Type**>(this+1);
@@ -326,7 +326,7 @@ FunctionType::FunctionType(const Type *Result, ArrayRef<Type*> Params,
}
// FunctionType::get - The factory function for the FunctionType class.
-FunctionType *FunctionType::get(const Type *ReturnType,
+FunctionType *FunctionType::get(Type *ReturnType,
ArrayRef<Type*> Params, bool isVarArg) {
// TODO: This is brutally slow.
std::vector<Type*> Key;
@@ -351,21 +351,21 @@ FunctionType *FunctionType::get(const Type *ReturnType,
}
-FunctionType *FunctionType::get(const Type *Result, bool isVarArg) {
+FunctionType *FunctionType::get(Type *Result, bool isVarArg) {
return get(Result, ArrayRef<Type *>(), isVarArg);
}
/// isValidReturnType - Return true if the specified type is valid as a return
/// type.
-bool FunctionType::isValidReturnType(const Type *RetTy) {
+bool FunctionType::isValidReturnType(Type *RetTy) {
return !RetTy->isFunctionTy() && !RetTy->isLabelTy() &&
!RetTy->isMetadataTy();
}
/// isValidArgumentType - Return true if the specified type is valid as an
/// argument type.
-bool FunctionType::isValidArgumentType(const Type *ArgTy) {
+bool FunctionType::isValidArgumentType(Type *ArgTy) {
return ArgTy->isFirstClassType();
}
@@ -392,7 +392,7 @@ StructType *StructType::get(LLVMContext &Context, ArrayRef<Type*> ETypes,
// Value not found. Create a new type!
ST = new (Context.pImpl->TypeAllocator) StructType(Context);
- ST->setSubclassData(SCDB_IsAnonymous); // Anonymous struct.
+ ST->setSubclassData(SCDB_IsLiteral); // Literal struct.
ST->setBody(ETypes, isPacked);
return ST;
}
@@ -412,13 +412,6 @@ void StructType::setBody(ArrayRef<Type*> Elements, bool isPacked) {
NumContainedTys = Elements.size();
}
-StructType *StructType::createNamed(LLVMContext &Context, StringRef Name) {
- StructType *ST = new (Context.pImpl->TypeAllocator) StructType(Context);
- if (!Name.empty())
- ST->setName(Name);
- return ST;
-}
-
void StructType::setName(StringRef Name) {
if (Name == getName()) return;
@@ -461,6 +454,13 @@ void StructType::setName(StringRef Name) {
//===----------------------------------------------------------------------===//
// StructType Helper functions.
+StructType *StructType::create(LLVMContext &Context, StringRef Name) {
+ StructType *ST = new (Context.pImpl->TypeAllocator) StructType(Context);
+ if (!Name.empty())
+ ST->setName(Name);
+ return ST;
+}
+
StructType *StructType::get(LLVMContext &Context, bool isPacked) {
return get(Context, llvm::ArrayRef<Type*>(), isPacked);
}
@@ -478,21 +478,36 @@ StructType *StructType::get(Type *type, ...) {
return llvm::StructType::get(Ctx, StructFields);
}
-StructType *StructType::createNamed(LLVMContext &Context, StringRef Name,
- ArrayRef<Type*> Elements, bool isPacked) {
- StructType *ST = createNamed(Context, Name);
+StructType *StructType::create(LLVMContext &Context, ArrayRef<Type*> Elements,
+ StringRef Name, bool isPacked) {
+ StructType *ST = create(Context, Name);
ST->setBody(Elements, isPacked);
return ST;
}
-StructType *StructType::createNamed(StringRef Name, ArrayRef<Type*> Elements,
- bool isPacked) {
+StructType *StructType::create(LLVMContext &Context, ArrayRef<Type*> Elements) {
+ return create(Context, Elements, StringRef());
+}
+
+StructType *StructType::create(LLVMContext &Context) {
+ return create(Context, StringRef());
+}
+
+
+StructType *StructType::create(ArrayRef<Type*> Elements, StringRef Name,
+ bool isPacked) {
+ assert(!Elements.empty() &&
+ "This method may not be invoked with an empty list");
+ return create(Elements[0]->getContext(), Elements, Name, isPacked);
+}
+
+StructType *StructType::create(ArrayRef<Type*> Elements) {
assert(!Elements.empty() &&
"This method may not be invoked with an empty list");
- return createNamed(Elements[0]->getContext(), Name, Elements, isPacked);
+ return create(Elements[0]->getContext(), Elements, StringRef());
}
-StructType *StructType::createNamed(StringRef Name, Type *type, ...) {
+StructType *StructType::create(StringRef Name, Type *type, ...) {
assert(type != 0 && "Cannot create a struct type with no elements with this");
LLVMContext &Ctx = type->getContext();
va_list ap;
@@ -502,11 +517,12 @@ StructType *StructType::createNamed(StringRef Name, Type *type, ...) {
StructFields.push_back(type);
type = va_arg(ap, llvm::Type*);
}
- return llvm::StructType::createNamed(Ctx, Name, StructFields);
+ return llvm::StructType::create(Ctx, StructFields, Name);
}
+
StringRef StructType::getName() const {
- assert(!isAnonymous() && "Anonymous structs never have names");
+ assert(!isLiteral() && "Literal structs never have names");
if (SymbolTableEntry == 0) return StringRef();
return ((StringMapEntry<StructType*> *)SymbolTableEntry)->getKey();
@@ -524,14 +540,14 @@ void StructType::setBody(Type *type, ...) {
setBody(StructFields);
}
-bool StructType::isValidElementType(const Type *ElemTy) {
+bool StructType::isValidElementType(Type *ElemTy) {
return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
!ElemTy->isMetadataTy() && !ElemTy->isFunctionTy();
}
/// isLayoutIdentical - Return true if this is layout identical to the
/// specified struct.
-bool StructType::isLayoutIdentical(const StructType *Other) const {
+bool StructType::isLayoutIdentical(StructType *Other) const {
if (this == Other) return true;
if (isPacked() != Other->isPacked() ||
@@ -557,8 +573,8 @@ StructType *Module::getTypeByName(StringRef Name) const {
// CompositeType Implementation
//===----------------------------------------------------------------------===//
-Type *CompositeType::getTypeAtIndex(const Value *V) const {
- if (const StructType *STy = dyn_cast<StructType>(this)) {
+Type *CompositeType::getTypeAtIndex(const Value *V) {
+ if (StructType *STy = dyn_cast<StructType>(this)) {
unsigned Idx = (unsigned)cast<ConstantInt>(V)->getZExtValue();
assert(indexValid(Idx) && "Invalid structure index!");
return STy->getElementType(Idx);
@@ -566,8 +582,8 @@ Type *CompositeType::getTypeAtIndex(const Value *V) const {
return cast<SequentialType>(this)->getElementType();
}
-Type *CompositeType::getTypeAtIndex(unsigned Idx) const {
- if (const StructType *STy = dyn_cast<StructType>(this)) {
+Type *CompositeType::getTypeAtIndex(unsigned Idx) {
+ if (StructType *STy = dyn_cast<StructType>(this)) {
assert(indexValid(Idx) && "Invalid structure index!");
return STy->getElementType(Idx);
}
@@ -605,7 +621,7 @@ ArrayType::ArrayType(Type *ElType, uint64_t NumEl)
}
-ArrayType *ArrayType::get(const Type *elementType, uint64_t NumElements) {
+ArrayType *ArrayType::get(Type *elementType, uint64_t NumElements) {
Type *ElementType = const_cast<Type*>(elementType);
assert(isValidElementType(ElementType) && "Invalid type for array element!");
@@ -618,7 +634,7 @@ ArrayType *ArrayType::get(const Type *elementType, uint64_t NumElements) {
return Entry;
}
-bool ArrayType::isValidElementType(const Type *ElemTy) {
+bool ArrayType::isValidElementType(Type *ElemTy) {
return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
!ElemTy->isMetadataTy() && !ElemTy->isFunctionTy();
}
@@ -632,7 +648,7 @@ VectorType::VectorType(Type *ElType, unsigned NumEl)
NumElements = NumEl;
}
-VectorType *VectorType::get(const Type *elementType, unsigned NumElements) {
+VectorType *VectorType::get(Type *elementType, unsigned NumElements) {
Type *ElementType = const_cast<Type*>(elementType);
assert(NumElements > 0 && "#Elements of a VectorType must be greater than 0");
assert(isValidElementType(ElementType) &&
@@ -647,7 +663,7 @@ VectorType *VectorType::get(const Type *elementType, unsigned NumElements) {
return Entry;
}
-bool VectorType::isValidElementType(const Type *ElemTy) {
+bool VectorType::isValidElementType(Type *ElemTy) {
return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy();
}
@@ -655,8 +671,7 @@ bool VectorType::isValidElementType(const Type *ElemTy) {
// PointerType Implementation
//===----------------------------------------------------------------------===//
-PointerType *PointerType::get(const Type *eltTy, unsigned AddressSpace) {
- Type *EltTy = const_cast<Type*>(eltTy);
+PointerType *PointerType::get(Type *EltTy, unsigned AddressSpace) {
assert(EltTy && "Can't get a pointer to <null> type!");
assert(isValidElementType(EltTy) && "Invalid type for pointer element!");
@@ -677,11 +692,11 @@ PointerType::PointerType(Type *E, unsigned AddrSpace)
setSubclassData(AddrSpace);
}
-PointerType *Type::getPointerTo(unsigned addrs) const {
+PointerType *Type::getPointerTo(unsigned addrs) {
return PointerType::get(this, addrs);
}
-bool PointerType::isValidElementType(const Type *ElemTy) {
+bool PointerType::isValidElementType(Type *ElemTy) {
return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
!ElemTy->isMetadataTy();
}
diff --git a/lib/VMCore/Value.cpp b/lib/VMCore/Value.cpp
index f1815e3..2fa5f08 100644
--- a/lib/VMCore/Value.cpp
+++ b/lib/VMCore/Value.cpp
@@ -35,12 +35,12 @@ using namespace llvm;
// Value Class
//===----------------------------------------------------------------------===//
-static inline Type *checkType(const Type *Ty) {
+static inline Type *checkType(Type *Ty) {
assert(Ty && "Value defined with a null type: Error!");
return const_cast<Type*>(Ty);
}
-Value::Value(const Type *ty, unsigned scid)
+Value::Value(Type *ty, unsigned scid)
: SubclassID(scid), HasValueHandle(0),
SubclassOptionalData(0), SubclassData(0), VTy((Type*)checkType(ty)),
UseList(0), Name(0) {
@@ -369,7 +369,7 @@ bool Value::isDereferenceablePointer() const {
for (User::const_op_iterator I = GEP->op_begin()+1,
E = GEP->op_end(); I != E; ++I) {
Value *Index = *I;
- const Type *Ty = *GTI++;
+ Type *Ty = *GTI++;
// Struct indices can't be out of bounds.
if (isa<StructType>(Ty))
continue;
@@ -380,7 +380,7 @@ bool Value::isDereferenceablePointer() const {
if (CI->isZero())
continue;
// Check to see that it's within the bounds of an array.
- const ArrayType *ATy = dyn_cast<ArrayType>(Ty);
+ ArrayType *ATy = dyn_cast<ArrayType>(Ty);
if (!ATy)
return false;
if (CI->getValue().getActiveBits() > 64)
diff --git a/lib/VMCore/ValueTypes.cpp b/lib/VMCore/ValueTypes.cpp
index 21a1f03..e13bd7d 100644
--- a/lib/VMCore/ValueTypes.cpp
+++ b/lib/VMCore/ValueTypes.cpp
@@ -19,6 +19,12 @@
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
+EVT EVT::changeExtendedVectorElementTypeToInteger() const {
+ LLVMContext &Context = LLVMTy->getContext();
+ EVT IntTy = getIntegerVT(Context, getVectorElementType().getSizeInBits());
+ return getVectorVT(Context, IntTy, getVectorNumElements());
+}
+
EVT EVT::getExtendedIntegerVT(LLVMContext &Context, unsigned BitWidth) {
EVT VT;
VT.LLVMTy = IntegerType::get(Context, BitWidth);
@@ -77,9 +83,9 @@ unsigned EVT::getExtendedVectorNumElements() const {
unsigned EVT::getExtendedSizeInBits() const {
assert(isExtended() && "Type is not extended!");
- if (const IntegerType *ITy = dyn_cast<IntegerType>(LLVMTy))
+ if (IntegerType *ITy = dyn_cast<IntegerType>(LLVMTy))
return ITy->getBitWidth();
- if (const VectorType *VTy = dyn_cast<VectorType>(LLVMTy))
+ if (VectorType *VTy = dyn_cast<VectorType>(LLVMTy))
return VTy->getBitWidth();
assert(false && "Unrecognized extended type!");
return 0; // Suppress warnings.
@@ -140,7 +146,7 @@ std::string EVT::getEVTString() const {
/// getTypeForEVT - This method returns an LLVM type corresponding to the
/// specified EVT. For integer types, this returns an unsigned type. Note
/// that this will abort for types that cannot be represented.
-const Type *EVT::getTypeForEVT(LLVMContext &Context) const {
+Type *EVT::getTypeForEVT(LLVMContext &Context) const {
switch (V.SimpleTy) {
default:
assert(isExtended() && "Type is not extended!");
@@ -186,7 +192,7 @@ const Type *EVT::getTypeForEVT(LLVMContext &Context) const {
/// getEVT - Return the value type corresponding to the specified type. This
/// returns all pointers as MVT::iPTR. If HandleUnknown is true, unknown types
/// are returned as Other, otherwise they are invalid.
-EVT EVT::getEVT(const Type *Ty, bool HandleUnknown){
+EVT EVT::getEVT(Type *Ty, bool HandleUnknown){
switch (Ty->getTypeID()) {
default:
if (HandleUnknown) return MVT(MVT::Other);
@@ -204,7 +210,7 @@ EVT EVT::getEVT(const Type *Ty, bool HandleUnknown){
case Type::PPC_FP128TyID: return MVT(MVT::ppcf128);
case Type::PointerTyID: return MVT(MVT::iPTR);
case Type::VectorTyID: {
- const VectorType *VTy = cast<VectorType>(Ty);
+ VectorType *VTy = cast<VectorType>(Ty);
return getVectorVT(Ty->getContext(), getEVT(VTy->getElementType(), false),
VTy->getNumElements());
}
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index b146b89..9564b7d 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -35,6 +35,12 @@
// * It is illegal to have a ret instruction that returns a value that does not
// agree with the function return value type.
// * Function call argument types match the function prototype
+// * A landing pad is defined by a landingpad instruction, and can be jumped to
+// only by the unwind edge of an invoke instruction.
+// * A landingpad instruction must be the first non-PHI instruction in the
+// block.
+// * All landingpad instructions must use the same personality function with
+// the same function.
// * All other things that are tested by asserts spread about the code...
//
//===----------------------------------------------------------------------===//
@@ -131,18 +137,22 @@ namespace {
/// already.
SmallPtrSet<MDNode *, 32> MDNodes;
+ /// PersonalityFn - The personality function referenced by the
+ /// LandingPadInsts. All LandingPadInsts within the same function must use
+ /// the same personality function.
+ const Value *PersonalityFn;
+
Verifier()
- : FunctionPass(ID),
- Broken(false), RealPass(true), action(AbortProcessAction),
- Mod(0), Context(0), DT(0), MessagesStr(Messages) {
- initializeVerifierPass(*PassRegistry::getPassRegistry());
- }
+ : FunctionPass(ID), Broken(false), RealPass(true),
+ action(AbortProcessAction), Mod(0), Context(0), DT(0),
+ MessagesStr(Messages), PersonalityFn(0) {
+ initializeVerifierPass(*PassRegistry::getPassRegistry());
+ }
explicit Verifier(VerifierFailureAction ctn)
- : FunctionPass(ID),
- Broken(false), RealPass(true), action(ctn), Mod(0), Context(0), DT(0),
- MessagesStr(Messages) {
- initializeVerifierPass(*PassRegistry::getPassRegistry());
- }
+ : FunctionPass(ID), Broken(false), RealPass(true), action(ctn), Mod(0),
+ Context(0), DT(0), MessagesStr(Messages), PersonalityFn(0) {
+ initializeVerifierPass(*PassRegistry::getPassRegistry());
+ }
bool doInitialization(Module &M) {
Mod = &M;
@@ -165,6 +175,7 @@ namespace {
visit(F);
InstsInThisBlock.clear();
+ PersonalityFn = 0;
// If this is a real pass, in a pass manager, we must abort before
// returning back to the pass manager, or else the pass manager may try to
@@ -278,18 +289,22 @@ namespace {
void visitUserOp1(Instruction &I);
void visitUserOp2(Instruction &I) { visitUserOp1(I); }
void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI);
+ void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI);
+ void visitAtomicRMWInst(AtomicRMWInst &RMWI);
+ void visitFenceInst(FenceInst &FI);
void visitAllocaInst(AllocaInst &AI);
void visitExtractValueInst(ExtractValueInst &EVI);
void visitInsertValueInst(InsertValueInst &IVI);
+ void visitLandingPadInst(LandingPadInst &LPI);
void VerifyCallSite(CallSite CS);
- bool PerformTypeCheck(Intrinsic::ID ID, Function *F, const Type *Ty,
+ bool PerformTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty,
int VT, unsigned ArgNo, std::string &Suffix);
void VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F,
unsigned RetNum, unsigned ParamNum, ...);
- void VerifyParameterAttrs(Attributes Attrs, const Type *Ty,
+ void VerifyParameterAttrs(Attributes Attrs, Type *Ty,
bool isReturnValue, const Value *V);
- void VerifyFunctionAttrs(const FunctionType *FT, const AttrListPtr &Attrs,
+ void VerifyFunctionAttrs(FunctionType *FT, const AttrListPtr &Attrs,
const Value *V);
void WriteValue(const Value *V) {
@@ -302,7 +317,7 @@ namespace {
}
}
- void WriteType(const Type *T) {
+ void WriteType(Type *T) {
if (!T) return;
MessagesStr << ' ' << *T;
}
@@ -323,7 +338,7 @@ namespace {
}
void CheckFailed(const Twine &Message, const Value *V1,
- const Type *T2, const Value *V3 = 0) {
+ Type *T2, const Value *V3 = 0) {
MessagesStr << Message.str() << "\n";
WriteValue(V1);
WriteType(T2);
@@ -331,8 +346,8 @@ namespace {
Broken = true;
}
- void CheckFailed(const Twine &Message, const Type *T1,
- const Type *T2 = 0, const Type *T3 = 0) {
+ void CheckFailed(const Twine &Message, Type *T1,
+ Type *T2 = 0, Type *T3 = 0) {
MessagesStr << Message.str() << "\n";
WriteType(T1);
WriteType(T2);
@@ -421,9 +436,9 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
"invalid linkage for intrinsic global variable", &GV);
// Don't worry about emitting an error for it not being an array,
// visitGlobalValue will complain on appending non-array.
- if (const ArrayType *ATy = dyn_cast<ArrayType>(GV.getType())) {
- const StructType *STy = dyn_cast<StructType>(ATy->getElementType());
- const PointerType *FuncPtrTy =
+ if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getType())) {
+ StructType *STy = dyn_cast<StructType>(ATy->getElementType());
+ PointerType *FuncPtrTy =
FunctionType::get(Type::getVoidTy(*Context), false)->getPointerTo();
Assert1(STy && STy->getNumElements() == 2 &&
STy->getTypeAtIndex(0u)->isIntegerTy(32) &&
@@ -514,7 +529,7 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) {
// VerifyParameterAttrs - Check the given attributes for an argument or return
// value of the specified type. The value V is printed in error messages.
-void Verifier::VerifyParameterAttrs(Attributes Attrs, const Type *Ty,
+void Verifier::VerifyParameterAttrs(Attributes Attrs, Type *Ty,
bool isReturnValue, const Value *V) {
if (Attrs == Attribute::None)
return;
@@ -541,7 +556,7 @@ void Verifier::VerifyParameterAttrs(Attributes Attrs, const Type *Ty,
Attribute::getAsString(TypeI), V);
Attributes ByValI = Attrs & Attribute::ByVal;
- if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
+ if (PointerType *PTy = dyn_cast<PointerType>(Ty)) {
Assert1(!ByValI || PTy->getElementType()->isSized(),
"Attribute " + Attribute::getAsString(ByValI) +
" does not support unsized types!", V);
@@ -554,7 +569,7 @@ void Verifier::VerifyParameterAttrs(Attributes Attrs, const Type *Ty,
// VerifyFunctionAttrs - Check parameter attributes against a function type.
// The value V is printed in error messages.
-void Verifier::VerifyFunctionAttrs(const FunctionType *FT,
+void Verifier::VerifyFunctionAttrs(FunctionType *FT,
const AttrListPtr &Attrs,
const Value *V) {
if (Attrs.isEmpty())
@@ -565,7 +580,7 @@ void Verifier::VerifyFunctionAttrs(const FunctionType *FT,
for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) {
const AttributeWithIndex &Attr = Attrs.getSlot(i);
- const Type *Ty;
+ Type *Ty;
if (Attr.Index == 0)
Ty = FT->getReturnType();
else if (Attr.Index-1 < FT->getNumParams())
@@ -615,7 +630,7 @@ static bool VerifyAttributeCount(const AttrListPtr &Attrs, unsigned Params) {
//
void Verifier::visitFunction(Function &F) {
// Check function arguments.
- const FunctionType *FT = F.getFunctionType();
+ FunctionType *FT = F.getFunctionType();
unsigned NumArgs = F.arg_size();
Assert1(Context == &F.getContext(),
@@ -795,7 +810,7 @@ void Verifier::visitReturnInst(ReturnInst &RI) {
void Verifier::visitSwitchInst(SwitchInst &SI) {
// Check to make sure that all of the constants in the switch instruction
// have the same type as the switched-on value.
- const Type *SwitchTy = SI.getCondition()->getType();
+ Type *SwitchTy = SI.getCondition()->getType();
SmallPtrSet<ConstantInt*, 32> Constants;
for (unsigned i = 1, e = SI.getNumCases(); i != e; ++i) {
Assert1(SI.getCaseValue(i)->getType() == SwitchTy,
@@ -836,8 +851,8 @@ void Verifier::visitUserOp1(Instruction &I) {
void Verifier::visitTruncInst(TruncInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getScalarSizeInBits();
@@ -854,8 +869,8 @@ void Verifier::visitTruncInst(TruncInst &I) {
void Verifier::visitZExtInst(ZExtInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
Assert1(SrcTy->isIntOrIntVectorTy(), "ZExt only operates on integer", &I);
@@ -872,8 +887,8 @@ void Verifier::visitZExtInst(ZExtInst &I) {
void Verifier::visitSExtInst(SExtInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getScalarSizeInBits();
@@ -890,8 +905,8 @@ void Verifier::visitSExtInst(SExtInst &I) {
void Verifier::visitFPTruncInst(FPTruncInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getScalarSizeInBits();
unsigned DestBitSize = DestTy->getScalarSizeInBits();
@@ -907,8 +922,8 @@ void Verifier::visitFPTruncInst(FPTruncInst &I) {
void Verifier::visitFPExtInst(FPExtInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getScalarSizeInBits();
@@ -925,8 +940,8 @@ void Verifier::visitFPExtInst(FPExtInst &I) {
void Verifier::visitUIToFPInst(UIToFPInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
bool SrcVec = SrcTy->isVectorTy();
bool DstVec = DestTy->isVectorTy();
@@ -948,8 +963,8 @@ void Verifier::visitUIToFPInst(UIToFPInst &I) {
void Verifier::visitSIToFPInst(SIToFPInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
bool SrcVec = SrcTy->isVectorTy();
bool DstVec = DestTy->isVectorTy();
@@ -971,8 +986,8 @@ void Verifier::visitSIToFPInst(SIToFPInst &I) {
void Verifier::visitFPToUIInst(FPToUIInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
bool SrcVec = SrcTy->isVectorTy();
bool DstVec = DestTy->isVectorTy();
@@ -994,8 +1009,8 @@ void Verifier::visitFPToUIInst(FPToUIInst &I) {
void Verifier::visitFPToSIInst(FPToSIInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
bool SrcVec = SrcTy->isVectorTy();
bool DstVec = DestTy->isVectorTy();
@@ -1017,8 +1032,8 @@ void Verifier::visitFPToSIInst(FPToSIInst &I) {
void Verifier::visitPtrToIntInst(PtrToIntInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
Assert1(SrcTy->isPointerTy(), "PtrToInt source must be pointer", &I);
Assert1(DestTy->isIntegerTy(), "PtrToInt result must be integral", &I);
@@ -1028,8 +1043,8 @@ void Verifier::visitPtrToIntInst(PtrToIntInst &I) {
void Verifier::visitIntToPtrInst(IntToPtrInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
Assert1(SrcTy->isIntegerTy(), "IntToPtr source must be an integral", &I);
Assert1(DestTy->isPointerTy(), "IntToPtr result must be a pointer",&I);
@@ -1039,8 +1054,8 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) {
void Verifier::visitBitCastInst(BitCastInst &I) {
// Get the source and destination types
- const Type *SrcTy = I.getOperand(0)->getType();
- const Type *DestTy = I.getType();
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
@@ -1090,11 +1105,11 @@ void Verifier::VerifyCallSite(CallSite CS) {
Assert1(CS.getCalledValue()->getType()->isPointerTy(),
"Called function must be a pointer!", I);
- const PointerType *FPTy = cast<PointerType>(CS.getCalledValue()->getType());
+ PointerType *FPTy = cast<PointerType>(CS.getCalledValue()->getType());
Assert1(FPTy->getElementType()->isFunctionTy(),
"Called function is not pointer to function type!", I);
- const FunctionType *FTy = cast<FunctionType>(FPTy->getElementType());
+ FunctionType *FTy = cast<FunctionType>(FPTy->getElementType());
// Verify that the correct number of arguments are being passed
if (FTy->isVarArg())
@@ -1152,6 +1167,12 @@ void Verifier::visitCallInst(CallInst &CI) {
void Verifier::visitInvokeInst(InvokeInst &II) {
VerifyCallSite(&II);
+
+ // Verify that there is a landingpad instruction as the first non-PHI
+ // instruction of the 'unwind' destination.
+ Assert1(II.getUnwindDest()->isLandingPad(),
+ "The unwind destination does not have a landingpad instruction!",&II);
+
visitTerminatorInst(II);
}
@@ -1219,8 +1240,8 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) {
void Verifier::visitICmpInst(ICmpInst &IC) {
// Check that the operands are the same type
- const Type *Op0Ty = IC.getOperand(0)->getType();
- const Type *Op1Ty = IC.getOperand(1)->getType();
+ Type *Op0Ty = IC.getOperand(0)->getType();
+ Type *Op1Ty = IC.getOperand(1)->getType();
Assert1(Op0Ty == Op1Ty,
"Both operands to ICmp instruction are not of the same type!", &IC);
// Check that the operands are the right type
@@ -1236,8 +1257,8 @@ void Verifier::visitICmpInst(ICmpInst &IC) {
void Verifier::visitFCmpInst(FCmpInst &FC) {
// Check that the operands are the same type
- const Type *Op0Ty = FC.getOperand(0)->getType();
- const Type *Op1Ty = FC.getOperand(1)->getType();
+ Type *Op0Ty = FC.getOperand(0)->getType();
+ Type *Op1Ty = FC.getOperand(1)->getType();
Assert1(Op0Ty == Op1Ty,
"Both operands to FCmp instruction are not of the same type!", &FC);
// Check that the operands are the right type
@@ -1274,10 +1295,13 @@ void Verifier::visitShuffleVectorInst(ShuffleVectorInst &SV) {
}
void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) {
+ Assert1(cast<PointerType>(GEP.getOperand(0)->getType())
+ ->getElementType()->isSized(),
+ "GEP into unsized type!", &GEP);
+
SmallVector<Value*, 16> Idxs(GEP.idx_begin(), GEP.idx_end());
- const Type *ElTy =
- GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(),
- Idxs.begin(), Idxs.end());
+ Type *ElTy =
+ GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(), Idxs);
Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP);
Assert2(GEP.getType()->isPointerTy() &&
cast<PointerType>(GEP.getType())->getElementType() == ElTy,
@@ -1286,26 +1310,44 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) {
}
void Verifier::visitLoadInst(LoadInst &LI) {
- const PointerType *PTy = dyn_cast<PointerType>(LI.getOperand(0)->getType());
+ PointerType *PTy = dyn_cast<PointerType>(LI.getOperand(0)->getType());
Assert1(PTy, "Load operand must be a pointer.", &LI);
- const Type *ElTy = PTy->getElementType();
+ Type *ElTy = PTy->getElementType();
Assert2(ElTy == LI.getType(),
"Load result type does not match pointer operand type!", &LI, ElTy);
+ if (LI.isAtomic()) {
+ Assert1(LI.getOrdering() != Release && LI.getOrdering() != AcquireRelease,
+ "Load cannot have Release ordering", &LI);
+ Assert1(LI.getAlignment() != 0,
+ "Atomic load must specify explicit alignment", &LI);
+ } else {
+ Assert1(LI.getSynchScope() == CrossThread,
+ "Non-atomic load cannot have SynchronizationScope specified", &LI);
+ }
visitInstruction(LI);
}
void Verifier::visitStoreInst(StoreInst &SI) {
- const PointerType *PTy = dyn_cast<PointerType>(SI.getOperand(1)->getType());
+ PointerType *PTy = dyn_cast<PointerType>(SI.getOperand(1)->getType());
Assert1(PTy, "Store operand must be a pointer.", &SI);
- const Type *ElTy = PTy->getElementType();
+ Type *ElTy = PTy->getElementType();
Assert2(ElTy == SI.getOperand(0)->getType(),
"Stored value type does not match pointer operand type!",
&SI, ElTy);
+ if (SI.isAtomic()) {
+ Assert1(SI.getOrdering() != Acquire && SI.getOrdering() != AcquireRelease,
+ "Store cannot have Acquire ordering", &SI);
+ Assert1(SI.getAlignment() != 0,
+ "Atomic store must specify explicit alignment", &SI);
+ } else {
+ Assert1(SI.getSynchScope() == CrossThread,
+ "Non-atomic store cannot have SynchronizationScope specified", &SI);
+ }
visitInstruction(SI);
}
void Verifier::visitAllocaInst(AllocaInst &AI) {
- const PointerType *PTy = AI.getType();
+ PointerType *PTy = AI.getType();
Assert1(PTy->getAddressSpace() == 0,
"Allocation instruction pointer not in the generic address space!",
&AI);
@@ -1316,6 +1358,49 @@ void Verifier::visitAllocaInst(AllocaInst &AI) {
visitInstruction(AI);
}
+void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) {
+ Assert1(CXI.getOrdering() != NotAtomic,
+ "cmpxchg instructions must be atomic.", &CXI);
+ Assert1(CXI.getOrdering() != Unordered,
+ "cmpxchg instructions cannot be unordered.", &CXI);
+ PointerType *PTy = dyn_cast<PointerType>(CXI.getOperand(0)->getType());
+ Assert1(PTy, "First cmpxchg operand must be a pointer.", &CXI);
+ Type *ElTy = PTy->getElementType();
+ Assert2(ElTy == CXI.getOperand(1)->getType(),
+ "Expected value type does not match pointer operand type!",
+ &CXI, ElTy);
+ Assert2(ElTy == CXI.getOperand(2)->getType(),
+ "Stored value type does not match pointer operand type!",
+ &CXI, ElTy);
+ visitInstruction(CXI);
+}
+
+void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) {
+ Assert1(RMWI.getOrdering() != NotAtomic,
+ "atomicrmw instructions must be atomic.", &RMWI);
+ Assert1(RMWI.getOrdering() != Unordered,
+ "atomicrmw instructions cannot be unordered.", &RMWI);
+ PointerType *PTy = dyn_cast<PointerType>(RMWI.getOperand(0)->getType());
+ Assert1(PTy, "First atomicrmw operand must be a pointer.", &RMWI);
+ Type *ElTy = PTy->getElementType();
+ Assert2(ElTy == RMWI.getOperand(1)->getType(),
+ "Argument value type does not match pointer operand type!",
+ &RMWI, ElTy);
+ Assert1(AtomicRMWInst::FIRST_BINOP <= RMWI.getOperation() &&
+ RMWI.getOperation() <= AtomicRMWInst::LAST_BINOP,
+ "Invalid binary operation!", &RMWI);
+ visitInstruction(RMWI);
+}
+
+void Verifier::visitFenceInst(FenceInst &FI) {
+ const AtomicOrdering Ordering = FI.getOrdering();
+ Assert1(Ordering == Acquire || Ordering == Release ||
+ Ordering == AcquireRelease || Ordering == SequentiallyConsistent,
+ "fence instructions may only have "
+ "acquire, release, acq_rel, or seq_cst ordering.", &FI);
+ visitInstruction(FI);
+}
+
void Verifier::visitExtractValueInst(ExtractValueInst &EVI) {
Assert1(ExtractValueInst::getIndexedType(EVI.getAggregateOperand()->getType(),
EVI.getIndices()) ==
@@ -1334,6 +1419,55 @@ void Verifier::visitInsertValueInst(InsertValueInst &IVI) {
visitInstruction(IVI);
}
+void Verifier::visitLandingPadInst(LandingPadInst &LPI) {
+ BasicBlock *BB = LPI.getParent();
+
+ // The landingpad instruction is ill-formed if it doesn't have any clauses and
+ // isn't a cleanup.
+ Assert1(LPI.getNumClauses() > 0 || LPI.isCleanup(),
+ "LandingPadInst needs at least one clause or to be a cleanup.", &LPI);
+
+ // The landingpad instruction defines its parent as a landing pad block. The
+ // landing pad block may be branched to only by the unwind edge of an invoke.
+ for (pred_iterator I = pred_begin(BB), E = pred_end(BB); I != E; ++I) {
+ const InvokeInst *II = dyn_cast<InvokeInst>((*I)->getTerminator());
+ Assert1(II && II->getUnwindDest() == BB,
+ "Block containing LandingPadInst must be jumped to "
+ "only by the unwind edge of an invoke.", &LPI);
+ }
+
+ // The landingpad instruction must be the first non-PHI instruction in the
+ // block.
+ Assert1(LPI.getParent()->getLandingPadInst() == &LPI,
+ "LandingPadInst not the first non-PHI instruction in the block.",
+ &LPI);
+
+ // The personality functions for all landingpad instructions within the same
+ // function should match.
+ if (PersonalityFn)
+ Assert1(LPI.getPersonalityFn() == PersonalityFn,
+ "Personality function doesn't match others in function", &LPI);
+ PersonalityFn = LPI.getPersonalityFn();
+
+ // All operands must be constants.
+ Assert1(isa<Constant>(PersonalityFn), "Personality function is not constant!",
+ &LPI);
+ for (unsigned i = 0, e = LPI.getNumClauses(); i < e; ++i) {
+ Value *Clause = LPI.getClause(i);
+ Assert1(isa<Constant>(Clause), "Clause is not constant!", &LPI);
+ if (LPI.isCatch(i)) {
+ Assert1(isa<PointerType>(Clause->getType()),
+ "Catch operand does not have pointer type!", &LPI);
+ } else {
+ Assert1(LPI.isFilter(i), "Clause is neither catch nor filter!", &LPI);
+ Assert1(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero>(Clause),
+ "Filter operand is not an array of constants!", &LPI);
+ }
+ }
+
+ visitInstruction(LPI);
+}
+
/// verifyInstruction - Verify that an instruction is well formed.
///
void Verifier::visitInstruction(Instruction &I) {
@@ -1588,20 +1722,20 @@ static std::string IntrinsicParam(unsigned ArgNo, unsigned NumRets) {
return "Intrinsic result type #" + utostr(ArgNo);
}
-bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, const Type *Ty,
+bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty,
int VT, unsigned ArgNo, std::string &Suffix) {
- const FunctionType *FTy = F->getFunctionType();
+ FunctionType *FTy = F->getFunctionType();
unsigned NumElts = 0;
- const Type *EltTy = Ty;
- const VectorType *VTy = dyn_cast<VectorType>(Ty);
+ Type *EltTy = Ty;
+ VectorType *VTy = dyn_cast<VectorType>(Ty);
if (VTy) {
EltTy = VTy->getElementType();
NumElts = VTy->getNumElements();
}
- const Type *RetTy = FTy->getReturnType();
- const StructType *ST = dyn_cast<StructType>(RetTy);
+ Type *RetTy = FTy->getReturnType();
+ StructType *ST = dyn_cast<StructType>(RetTy);
unsigned NumRetVals;
if (RetTy->isVoidTy())
NumRetVals = 0;
@@ -1618,7 +1752,7 @@ bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, const Type *Ty,
// type.
if ((Match & (ExtendedElementVectorType |
TruncatedElementVectorType)) != 0) {
- const IntegerType *IEltTy = dyn_cast<IntegerType>(EltTy);
+ IntegerType *IEltTy = dyn_cast<IntegerType>(EltTy);
if (!VTy || !IEltTy) {
CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " is not "
"an integral vector type.", F);
@@ -1709,7 +1843,7 @@ bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, const Type *Ty,
// Outside of TableGen, we don't distinguish iPTRAny (to any address space)
// and iPTR. In the verifier, we can not distinguish which case we have so
// allow either case to be legal.
- if (const PointerType* PTyp = dyn_cast<PointerType>(Ty)) {
+ if (PointerType* PTyp = dyn_cast<PointerType>(Ty)) {
EVT PointeeVT = EVT::getEVT(PTyp->getElementType(), true);
if (PointeeVT == MVT::Other) {
CheckFailed("Intrinsic has pointer to complex type.");
@@ -1757,7 +1891,7 @@ void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F,
unsigned NumParams, ...) {
va_list VA;
va_start(VA, NumParams);
- const FunctionType *FTy = F->getFunctionType();
+ FunctionType *FTy = F->getFunctionType();
// For overloaded intrinsics, the Suffix of the function name must match the
// types of the arguments. This variable keeps track of the expected
@@ -1769,8 +1903,8 @@ void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F,
return;
}
- const Type *Ty = FTy->getReturnType();
- const StructType *ST = dyn_cast<StructType>(Ty);
+ Type *Ty = FTy->getReturnType();
+ StructType *ST = dyn_cast<StructType>(Ty);
if (NumRetVals == 0 && !Ty->isVoidTy()) {
CheckFailed("Intrinsic should return void", F);
diff --git a/runtime/libprofile/CommonProfiling.c b/runtime/libprofile/CommonProfiling.c
index 210a5e5..fbc1ef4 100644
--- a/runtime/libprofile/CommonProfiling.c
+++ b/runtime/libprofile/CommonProfiling.c
@@ -102,12 +102,19 @@ int getOutFile() {
{
int PTy = ArgumentInfo;
int Zeros = 0;
- write(OutFile, &PTy, sizeof(int));
- write(OutFile, &SavedArgsLength, sizeof(unsigned));
- write(OutFile, SavedArgs, SavedArgsLength);
+ if (write(OutFile, &PTy, sizeof(int)) < 0 ||
+ write(OutFile, &SavedArgsLength, sizeof(unsigned)) < 0 ||
+ write(OutFile, SavedArgs, SavedArgsLength) < 0 ) {
+ fprintf(stderr,"error: unable to write to output file.");
+ exit(0);
+ }
/* Pad out to a multiple of four bytes */
- if (SavedArgsLength & 3)
- write(OutFile, &Zeros, 4-(SavedArgsLength&3));
+ if (SavedArgsLength & 3) {
+ if (write(OutFile, &Zeros, 4-(SavedArgsLength&3)) < 0) {
+ fprintf(stderr,"error: unable to write to output file.");
+ exit(0);
+ }
+ }
}
}
return(OutFile);
diff --git a/runtime/libprofile/GCDAProfiling.c b/runtime/libprofile/GCDAProfiling.c
index e066b22..4ffb12b 100644
--- a/runtime/libprofile/GCDAProfiling.c
+++ b/runtime/libprofile/GCDAProfiling.c
@@ -26,7 +26,7 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
-#ifdef _MSC_VER
+#ifdef _WIN32
#include <direct.h>
#endif
@@ -114,7 +114,11 @@ void llvm_gcda_start_file(const char *orig_filename) {
output_file = fopen(filename, "wb");
/* gcda file, version 404*, stamp LLVM. */
+#ifdef __APPLE__
+ fwrite("adcg*204MVLL", 12, 1, output_file);
+#else
fwrite("adcg*404MVLL", 12, 1, output_file);
+#endif
#ifdef DEBUG_GCDAPROFILING
printf("llvmgcda: [%s]\n", orig_filename);
diff --git a/runtime/libprofile/Makefile b/runtime/libprofile/Makefile
index cf31e46..d851149 100644
--- a/runtime/libprofile/Makefile
+++ b/runtime/libprofile/Makefile
@@ -19,6 +19,10 @@ SHARED_LIBRARY = 1
EXTRA_DIST = libprofile.exports
EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/libprofile.exports
+# Build and install this archive.
+BUILD_ARCHIVE = 1
+override NO_INSTALL_ARCHIVES =
+
include $(LEVEL)/Makefile.common
ifeq ($(HOST_OS),Darwin)
diff --git a/test/Analysis/BasicAA/2009-10-13-AtomicModRef.ll b/test/Analysis/BasicAA/2009-10-13-AtomicModRef.ll
index 5078dd5..4b6a12e 100644
--- a/test/Analysis/BasicAA/2009-10-13-AtomicModRef.ll
+++ b/test/Analysis/BasicAA/2009-10-13-AtomicModRef.ll
@@ -1,14 +1,12 @@
; RUN: opt -basicaa -gvn -instcombine -S < %s | FileCheck %s
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
-declare i8 @llvm.atomic.load.add.i8.p0i8(i8*, i8)
-
define i8 @foo(i8* %ptr) {
%P = getelementptr i8* %ptr, i32 0
%Q = getelementptr i8* %ptr, i32 1
; CHECK: getelementptr
%X = load i8* %P
- %Y = call i8 @llvm.atomic.load.add.i8.p0i8(i8* %Q, i8 1)
+ %Y = atomicrmw add i8* %Q, i8 1 monotonic
%Z = load i8* %P
; CHECK-NOT: = load
%A = sub i8 %X, %Z
diff --git a/test/Analysis/BasicAA/cas.ll b/test/Analysis/BasicAA/cas.ll
index 8dd3695..754309c 100644
--- a/test/Analysis/BasicAA/cas.ll
+++ b/test/Analysis/BasicAA/cas.ll
@@ -6,10 +6,8 @@
define i32 @main() {
%a = load i32* @flag0
- %b = tail call i32 @llvm.atomic.swap.i32.p0i32(i32* @turn, i32 1)
+ %b = atomicrmw xchg i32* @turn, i32 1 monotonic
%c = load i32* @flag0
%d = sub i32 %a, %c
ret i32 %d
}
-
-declare i32 @llvm.atomic.swap.i32.p0i32(i32*, i32) nounwind
diff --git a/test/Analysis/BasicAA/gep-alias.ll b/test/Analysis/BasicAA/gep-alias.ll
index 69f7faf..4bb2832 100644
--- a/test/Analysis/BasicAA/gep-alias.ll
+++ b/test/Analysis/BasicAA/gep-alias.ll
@@ -169,3 +169,35 @@ define i8 @test10([4 x i8] *%P, i32 %i) {
; CHECK: @test10
; CHECK: ret i8 0
}
+
+; (This was a miscompilation.)
+define float @test11(i32 %indvar, [4 x [2 x float]]* %q) nounwind ssp {
+ %tmp = mul i32 %indvar, -1
+ %dec = add i32 %tmp, 3
+ %scevgep = getelementptr [4 x [2 x float]]* %q, i32 0, i32 %dec
+ %scevgep35 = bitcast [2 x float]* %scevgep to i64*
+ %arrayidx28 = getelementptr inbounds [4 x [2 x float]]* %q, i32 0, i32 0
+ %y29 = getelementptr inbounds [2 x float]* %arrayidx28, i32 0, i32 1
+ store float 1.0, float* %y29, align 4
+ store i64 0, i64* %scevgep35, align 4
+ %tmp30 = load float* %y29, align 4
+ ret float %tmp30
+ ; CHECK: @test11
+ ; CHECK: ret float %tmp30
+}
+
+; (This was a miscompilation.)
+define i32 @test12(i32 %x, i32 %y, i8* %p) nounwind {
+ %a = bitcast i8* %p to [13 x i8]*
+ %b = getelementptr [13 x i8]* %a, i32 %x
+ %c = bitcast [13 x i8]* %b to [15 x i8]*
+ %d = getelementptr [15 x i8]* %c, i32 %y, i32 8
+ %castd = bitcast i8* %d to i32*
+ %castp = bitcast i8* %p to i32*
+ store i32 1, i32* %castp
+ store i32 0, i32* %castd
+ %r = load i32* %castp
+ ret i32 %r
+ ; CHECK: @test12
+ ; CHECK: ret i32 %r
+}
diff --git a/test/Analysis/BasicAA/memset_pattern.ll b/test/Analysis/BasicAA/memset_pattern.ll
new file mode 100644
index 0000000..590664c5
--- /dev/null
+++ b/test/Analysis/BasicAA/memset_pattern.ll
@@ -0,0 +1,21 @@
+; RUN: opt -S -basicaa -gvn < %s | FileCheck %s
+; PR10872
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7"
+
+@z = internal global i32 0, align 4
+@y = internal global i32 0, align 4
+@x = internal constant i32 0, align 4
+
+; CHECK: @test
+define i32 @test() nounwind uwtable ssp {
+entry:
+ store i32 1, i32* @z
+ tail call void @memset_pattern16(i8* bitcast (i32* @y to i8*), i8* bitcast (i32* @x to i8*), i64 4) nounwind
+; CHECK-NOT: load
+ %l = load i32* @z
+; CHECK: ret i32 1
+ ret i32 %l
+}
+
+declare void @memset_pattern16(i8*, i8*, i64)
diff --git a/test/Analysis/BasicAA/modref.ll b/test/Analysis/BasicAA/modref.ll
index 233396b..8421faf 100644
--- a/test/Analysis/BasicAA/modref.ll
+++ b/test/Analysis/BasicAA/modref.ll
@@ -129,8 +129,23 @@ define i8 @test6(i8* %p, i8* noalias %a) {
; CHECK: ret
}
+; PR10628
+declare void @test7decl(i32* nocapture %x)
+define i32 @test7() nounwind uwtable ssp {
+entry:
+ %x = alloca i32, align 4
+ store i32 0, i32* %x, align 4
+ %add.ptr = getelementptr inbounds i32* %x, i64 1
+ call void @test7decl(i32* %add.ptr)
+ %tmp = load i32* %x, align 4
+ ret i32 %tmp
+; CHECK: @test7(
+; CHECK: store i32 0
+; CHECK: call void @test7decl
+; CHECK: load i32*
+}
+
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) nounwind
declare void @llvm.memset.p0i8.i8(i8* nocapture, i8, i8, i32, i1) nounwind
declare void @llvm.memcpy.p0i8.p0i8.i8(i8* nocapture, i8* nocapture, i8, i32, i1) nounwind
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
-
diff --git a/test/Analysis/BlockFrequencyInfo/basic.ll b/test/Analysis/BlockFrequencyInfo/basic.ll
new file mode 100644
index 0000000..540d06b
--- /dev/null
+++ b/test/Analysis/BlockFrequencyInfo/basic.ll
@@ -0,0 +1,92 @@
+; RUN: opt < %s -analyze -block-freq | FileCheck %s
+
+define i32 @test1(i32 %i, i32* %a) {
+; CHECK: Printing analysis {{.*}} for function 'test1'
+; CHECK: entry = 1024
+entry:
+ br label %body
+
+; Loop backedges are weighted and thus their bodies have a greater frequency.
+; CHECK: body = 31744
+body:
+ %iv = phi i32 [ 0, %entry ], [ %next, %body ]
+ %base = phi i32 [ 0, %entry ], [ %sum, %body ]
+ %arrayidx = getelementptr inbounds i32* %a, i32 %iv
+ %0 = load i32* %arrayidx
+ %sum = add nsw i32 %0, %base
+ %next = add i32 %iv, 1
+ %exitcond = icmp eq i32 %next, %i
+ br i1 %exitcond, label %exit, label %body
+
+; CHECK: exit = 1024
+exit:
+ ret i32 %sum
+}
+
+define i32 @test2(i32 %i, i32 %a, i32 %b) {
+; CHECK: Printing analysis {{.*}} for function 'test2'
+; CHECK: entry = 1024
+entry:
+ %cond = icmp ult i32 %i, 42
+ br i1 %cond, label %then, label %else, !prof !0
+
+; The 'then' branch is predicted more likely via branch weight metadata.
+; CHECK: then = 963
+then:
+ br label %exit
+
+; CHECK: else = 60
+else:
+ br label %exit
+
+; FIXME: It may be a bug that we don't sum back to 1024.
+; CHECK: exit = 1023
+exit:
+ %result = phi i32 [ %a, %then ], [ %b, %else ]
+ ret i32 %result
+}
+
+!0 = metadata !{metadata !"branch_weights", i32 64, i32 4}
+
+define i32 @test3(i32 %i, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
+; CHECK: Printing analysis {{.*}} for function 'test3'
+; CHECK: entry = 1024
+entry:
+ switch i32 %i, label %case_a [ i32 1, label %case_b
+ i32 2, label %case_c
+ i32 3, label %case_d
+ i32 4, label %case_e ], !prof !1
+
+; CHECK: case_a = 51
+case_a:
+ br label %exit
+
+; CHECK: case_b = 51
+case_b:
+ br label %exit
+
+; The 'case_c' branch is predicted more likely via branch weight metadata.
+; CHECK: case_c = 819
+case_c:
+ br label %exit
+
+; CHECK: case_d = 51
+case_d:
+ br label %exit
+
+; CHECK: case_e = 51
+case_e:
+ br label %exit
+
+; FIXME: It may be a bug that we don't sum back to 1024.
+; CHECK: exit = 1023
+exit:
+ %result = phi i32 [ %a, %case_a ],
+ [ %b, %case_b ],
+ [ %c, %case_c ],
+ [ %d, %case_d ],
+ [ %e, %case_e ]
+ ret i32 %result
+}
+
+!1 = metadata !{metadata !"branch_weights", i32 4, i32 4, i32 64, i32 4, i32 4}
diff --git a/test/Transforms/LowerSetJmp/dg.exp b/test/Analysis/BlockFrequencyInfo/dg.exp
index f200589..f200589 100644
--- a/test/Transforms/LowerSetJmp/dg.exp
+++ b/test/Analysis/BlockFrequencyInfo/dg.exp
diff --git a/test/Analysis/ScalarEvolution/2011-10-04-ConstEvolve.ll b/test/Analysis/ScalarEvolution/2011-10-04-ConstEvolve.ll
new file mode 100644
index 0000000..29bb64a
--- /dev/null
+++ b/test/Analysis/ScalarEvolution/2011-10-04-ConstEvolve.ll
@@ -0,0 +1,50 @@
+; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s
+
+; Exercise getConstantEvolvingPHIOperands on an interesting loop.
+; This should complete in milliseconds, not minutes.
+
+; Just check that it actually ran trip count analysis.
+; CHECK: Determining loop execution counts for: @test
+define void @test() nounwind {
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i32 [ %30, %loop ], [ 0, %entry ]
+ %0 = add i32 %iv, 1
+ %1 = add i32 %0, 2
+ %2 = add i32 %1, %0
+ %3 = add i32 %2, %1
+ %4 = add i32 %3, %2
+ %5 = add i32 %4, %3
+ %6 = add i32 %5, %4
+ %7 = add i32 %6, %5
+ %8 = add i32 %7, %6
+ %9 = add i32 %8, %7
+ %10 = add i32 %9, %8
+ %11 = add i32 %10, %9
+ %12 = add i32 %11, %10
+ %13 = add i32 %12, %11
+ %14 = add i32 %13, %12
+ %15 = add i32 %14, %13
+ %16 = add i32 %15, %14
+ %17 = add i32 %16, %15
+ %18 = add i32 %17, %16
+ %19 = add i32 %18, %17
+ %20 = add i32 %19, %18
+ %21 = add i32 %20, %19
+ %22 = add i32 %21, %20
+ %23 = add i32 %22, %21
+ %24 = add i32 %23, %22
+ %25 = add i32 %24, %23
+ %26 = add i32 %25, %24
+ %27 = add i32 %26, %25
+ %28 = add i32 %27, %26
+ %29 = add i32 %28, %27
+ %30 = add i32 %29, %28
+ %cmp = icmp eq i32 %30, -108
+ br i1 %cmp, label %exit, label %loop
+
+exit:
+ unreachable
+}
diff --git a/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll b/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll
index ec95141..06f1b6f 100644
--- a/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll
+++ b/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll
@@ -1,11 +1,11 @@
; RUN: opt < %s -analyze -scalar-evolution \
-; RUN: -scalar-evolution-max-iterations=0 | grep {backedge-taken count is 100}
+; RUN: -scalar-evolution-max-iterations=0 | FileCheck %s
+
; PR1101
@A = weak global [1000 x i32] zeroinitializer, align 32
-
-define void @test(i32 %N) {
+define void @test1(i32 %N) {
entry:
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
br label %bb3
@@ -30,3 +30,53 @@ bb5: ; preds = %bb3
return: ; preds = %bb5
ret void
}
+; CHECK: Determining loop execution counts for: @test1
+; CHECK-NEXT: backedge-taken count is 100
+
+
+; PR10383
+; These next two used to crash.
+
+define void @test2(i1 %cmp, i64 %n) {
+entry:
+ br label %for.body1
+
+for.body1:
+ %a0.08 = phi i64 [ 0, %entry ], [ %inc512, %for.body1 ]
+ %inc512 = add i64 %a0.08, 1
+ br i1 %cmp, label %preheader, label %for.body1
+
+preheader:
+ br label %for.body2
+
+for.body2:
+ %indvar = phi i64 [ 0, %preheader ], [ %indvar.next, %for.body2 ]
+ %tmp111 = add i64 %n, %indvar
+ %tmp114 = mul i64 %a0.08, %indvar
+ %mul542 = mul i64 %tmp114, %tmp111
+ %indvar.next = add i64 %indvar, 1
+ br i1 undef, label %end, label %for.body2
+
+end:
+ ret void
+}
+; CHECK: Determining loop execution counts for: @test2
+
+define i32 @test3() {
+if.then466:
+ br i1 undef, label %for.cond539.preheader, label %for.inc479
+
+for.inc479:
+ %a2.07 = phi i32 [ %add495, %for.inc479 ], [ 0, %if.then466 ]
+ %j.36 = phi i32 [ %inc497, %for.inc479 ], [ undef, %if.then466 ]
+ %mul484 = mul nsw i32 %j.36, %j.36
+ %mul491 = mul i32 %j.36, %j.36
+ %mul493 = mul i32 %mul491, %mul484
+ %add495 = add nsw i32 %mul493, %a2.07
+ %inc497 = add nsw i32 %j.36, 1
+ br i1 undef, label %for.cond539.preheader, label %for.inc479
+
+for.cond539.preheader:
+ unreachable
+}
+; CHECK: Determining loop execution counts for: @test3
diff --git a/test/Analysis/ScalarEvolution/avoid-smax-1.ll b/test/Analysis/ScalarEvolution/avoid-smax-1.ll
index 474d564..e90a555 100644
--- a/test/Analysis/ScalarEvolution/avoid-smax-1.ll
+++ b/test/Analysis/ScalarEvolution/avoid-smax-1.ll
@@ -1,6 +1,4 @@
-; RUN: opt < %s -indvars -S > %t
-; RUN: grep select %t | count 2
-; RUN: grep {icmp ne i32.\* } %t
+; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s
; Indvars should be able to insert a canonical induction variable
; for the bb6 loop without using a maximum calculation (icmp, select)
@@ -8,6 +6,9 @@
; by an appropriate conditional branch. Unfortunately, indvars is
; not yet able to find the comparison for the other two loops in
; this testcase.
+; CHECK: entry:
+; CHECK-NOT: select
+; CHECK: bb6:
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin9"
diff --git a/test/Analysis/ScalarEvolution/max-trip-count.ll b/test/Analysis/ScalarEvolution/max-trip-count.ll
index 843fb07..0cdbdf5 100644
--- a/test/Analysis/ScalarEvolution/max-trip-count.ll
+++ b/test/Analysis/ScalarEvolution/max-trip-count.ll
@@ -70,3 +70,31 @@ for.end: ; preds = %for.body, %for.cond
}
declare i32 @printf(i8*, ...)
+
+define void @test(i8* %a, i32 %n) nounwind {
+entry:
+ %cmp1 = icmp sgt i32 %n, 0
+ br i1 %cmp1, label %for.body.lr.ph, label %for.end
+
+for.body.lr.ph: ; preds = %entry
+ %tmp = zext i32 %n to i64
+ br label %for.body
+
+for.body: ; preds = %for.body, %for.body.lr.ph
+ %indvar = phi i64 [ %indvar.next, %for.body ], [ 0, %for.body.lr.ph ]
+ %arrayidx = getelementptr i8* %a, i64 %indvar
+ store i8 0, i8* %arrayidx, align 1
+ %indvar.next = add i64 %indvar, 1
+ %exitcond = icmp ne i64 %indvar.next, %tmp
+ br i1 %exitcond, label %for.body, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge: ; preds = %for.body
+ br label %for.end
+
+for.end: ; preds = %for.cond.for.end_crit_edge, %entry
+ ret void
+}
+
+; CHECK: Determining loop execution counts for: @test
+; CHECK-NEXT: backedge-taken count is
+; CHECK-NEXT: max backedge-taken count is -1
diff --git a/test/Assembler/2003-06-17-InvokeDisassemble.ll b/test/Assembler/2003-06-17-InvokeDisassemble.ll
index 922a996..8a9670e 100644
--- a/test/Assembler/2003-06-17-InvokeDisassemble.ll
+++ b/test/Assembler/2003-06-17-InvokeDisassemble.ll
@@ -1,9 +1,13 @@
; RUN: llvm-as < %s | llvm-dis
define void @test() {
- invoke void @test( )
- to label %Next unwind label %Next
+ invoke void @test( )
+ to label %Next unwind label %Next
Next: ; preds = %0, %0
- ret void
+ %lpad = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ ret void
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Assembler/AutoUpgradeIntrinsics.ll b/test/Assembler/AutoUpgradeIntrinsics.ll
index eb4ac76..daffa3d 100644
--- a/test/Assembler/AutoUpgradeIntrinsics.ll
+++ b/test/Assembler/AutoUpgradeIntrinsics.ll
@@ -40,3 +40,16 @@ define void @p(i8* %ptr) {
tail call void @llvm.prefetch(i8* %ptr, i32 0, i32 1)
ret void
}
+
+declare i32 @nest_f(i8* nest, i32)
+declare i8* @llvm.init.trampoline(i8*, i8*, i8*)
+
+define void @test_trampolines() {
+; CHECK: call void @llvm.init.trampoline(i8* null, i8* bitcast (i32 (i8*, i32)* @nest_f to i8*), i8* null)
+; CHECK: call i8* @llvm.adjust.trampoline(i8* null)
+
+ call i8* @llvm.init.trampoline(i8* null,
+ i8* bitcast (i32 (i8*, i32)* @nest_f to i8*),
+ i8* null)
+ ret void
+}
diff --git a/test/Assembler/atomic.ll b/test/Assembler/atomic.ll
new file mode 100644
index 0000000..b245cde
--- /dev/null
+++ b/test/Assembler/atomic.ll
@@ -0,0 +1,26 @@
+; RUN: opt < %s | opt -S | FileCheck %s
+; Basic smoke test for atomic operations.
+
+define void @f(i32* %x) {
+ ; CHECK: load atomic i32* %x unordered, align 4
+ load atomic i32* %x unordered, align 4
+ ; CHECK: load atomic volatile i32* %x singlethread acquire, align 4
+ load atomic volatile i32* %x singlethread acquire, align 4
+ ; CHECK: store atomic i32 3, i32* %x release, align 4
+ store atomic i32 3, i32* %x release, align 4
+ ; CHECK: store atomic volatile i32 3, i32* %x singlethread monotonic, align 4
+ store atomic volatile i32 3, i32* %x singlethread monotonic, align 4
+ ; CHECK: cmpxchg i32* %x, i32 1, i32 0 singlethread monotonic
+ cmpxchg i32* %x, i32 1, i32 0 singlethread monotonic
+ ; CHECK: cmpxchg volatile i32* %x, i32 0, i32 1 acq_rel
+ cmpxchg volatile i32* %x, i32 0, i32 1 acq_rel
+ ; CHECK: atomicrmw add i32* %x, i32 10 seq_cst
+ atomicrmw add i32* %x, i32 10 seq_cst
+ ; CHECK: atomicrmw volatile xchg i32* %x, i32 10 monotonic
+ atomicrmw volatile xchg i32* %x, i32 10 monotonic
+ ; CHECK: fence singlethread release
+ fence singlethread release
+ ; CHECK: fence seq_cst
+ fence seq_cst
+ ret void
+}
diff --git a/test/Bindings/Ocaml/ipo_opts.ml b/test/Bindings/Ocaml/ipo_opts.ml
new file mode 100644
index 0000000..3a36231
--- /dev/null
+++ b/test/Bindings/Ocaml/ipo_opts.ml
@@ -0,0 +1,73 @@
+(* RUN: %ocamlopt -warn-error A llvm.cmxa llvm_ipo.cmxa llvm_target.cmxa %s -o %t
+ * RUN: %t %t.bc
+ * XFAIL: vg_leak
+ *)
+
+(* Note: It takes several seconds for ocamlopt to link an executable with
+ libLLVMCore.a, so it's better to write a big test than a bunch of
+ little ones. *)
+
+open Llvm
+open Llvm_ipo
+open Llvm_target
+
+let context = global_context ()
+let void_type = Llvm.void_type context
+let i8_type = Llvm.i8_type context
+
+(* Tiny unit test framework - really just to help find which line is busted *)
+let print_checkpoints = false
+
+let suite name f =
+ if print_checkpoints then
+ prerr_endline (name ^ ":");
+ f ()
+
+
+(*===-- Fixture -----------------------------------------------------------===*)
+
+let filename = Sys.argv.(1)
+let m = create_module context filename
+
+
+(*===-- Transforms --------------------------------------------------------===*)
+
+let test_transforms () =
+ let (++) x f = ignore (f x); x in
+
+ let fty = function_type i8_type [| |] in
+ let fn = define_function "fn" fty m in
+ let fn2 = define_function "fn2" fty m in begin
+ ignore (build_ret (const_int i8_type 4) (builder_at_end context (entry_block fn)));
+ let b = builder_at_end context (entry_block fn2) in
+ ignore (build_ret (build_call fn [| |] "" b) b);
+ end;
+
+ let td = TargetData.create (target_triple m) in
+
+ ignore (PassManager.create ()
+ ++ TargetData.add td
+ ++ add_argument_promotion
+ ++ add_constant_merge
+ ++ add_dead_arg_elimination
+ ++ add_function_attrs
+ ++ add_function_inlining
+ ++ add_global_dce
+ ++ add_global_optimizer
+ ++ add_ipc_propagation
+ ++ add_prune_eh
+ ++ add_ipsccp
+ ++ add_internalize
+ ++ add_strip_dead_prototypes
+ ++ add_strip_symbols
+ ++ PassManager.run_module m
+ ++ PassManager.dispose);
+
+ TargetData.dispose td
+
+
+(*===-- Driver ------------------------------------------------------------===*)
+
+let _ =
+ suite "transforms" test_transforms;
+ dispose_module m
diff --git a/test/Bindings/Ocaml/scalar_opts.ml b/test/Bindings/Ocaml/scalar_opts.ml
index 1ea9785..34a7a6a 100644
--- a/test/Bindings/Ocaml/scalar_opts.ml
+++ b/test/Bindings/Ocaml/scalar_opts.ml
@@ -42,11 +42,14 @@ let test_transforms () =
ignore (PassManager.create_function m
++ TargetData.add td
+ ++ add_verifier
++ add_constant_propagation
++ add_sccp
++ add_dead_store_elimination
++ add_aggressive_dce
++ add_scalar_repl_aggregation
+ ++ add_scalar_repl_aggregation_ssa
+ ++ add_scalar_repl_aggregation_with_threshold 4
++ add_ind_var_simplification
++ add_instruction_combination
++ add_licm
@@ -62,7 +65,14 @@ let test_transforms () =
++ add_gvn
++ add_memcpy_opt
++ add_loop_deletion
+ ++ add_loop_idiom
++ add_lib_call_simplification
+ ++ add_correlated_value_propagation
+ ++ add_early_cse
+ ++ add_lower_expect_intrinsic
+ ++ add_type_based_alias_analysis
+ ++ add_basic_alias_analysis
+ ++ add_verifier
++ PassManager.initialize
++ PassManager.run_function fn
++ PassManager.finalize
diff --git a/test/Bindings/Ocaml/target.ml b/test/Bindings/Ocaml/target.ml
index 5e3ab4b..1b6b71e 100644
--- a/test/Bindings/Ocaml/target.ml
+++ b/test/Bindings/Ocaml/target.ml
@@ -37,7 +37,6 @@ let test_target_data () =
let sty = struct_type context [| i32_type; i64_type |] in
ignore (TargetData.as_string td);
- ignore (TargetData.invalidate_struct_layout td sty);
ignore (byte_order td);
ignore (pointer_size td);
ignore (intptr_type td);
diff --git a/test/Bindings/Ocaml/vmcore.ml b/test/Bindings/Ocaml/vmcore.ml
index bff04a1..9329286 100644
--- a/test/Bindings/Ocaml/vmcore.ml
+++ b/test/Bindings/Ocaml/vmcore.ml
@@ -337,6 +337,16 @@ let test_constants () =
"{cx},{ax},{di},~{dirflag},~{fpsr},~{flags},~{edi},~{ecx}"
true
false)
+ end;
+
+ group "recursive struct"; begin
+ let nsty = named_struct_type context "rec" in
+ let pty = pointer_type nsty in
+ struct_set_body nsty [| i32_type; pty |] false;
+ let elts = [| const_int i32_type 4; const_pointer_null pty |] in
+ let grec_init = const_named_struct nsty elts in
+ ignore (define_global "grec" grec_init m);
+ ignore (string_of_lltype nsty);
end
@@ -822,6 +832,18 @@ let test_builder () =
let b = builder_at_end context (append_block context "Bb01" fn) in
ignore (build_ret_void b)
end;
+
+ group "ret aggregate";
+ begin
+ (* RUN: grep {ret \{ i8, i64 \} \{ i8 4, i64 5 \}} < %t.ll
+ *)
+ let sty = struct_type context [| i8_type; i64_type |] in
+ let fty = function_type sty [| |] in
+ let fn = declare_function "XA6" fty m in
+ let b = builder_at_end context (append_block context "Bb01" fn) in
+ let agg = [| const_int i8_type 4; const_int i64_type 5 |] in
+ ignore (build_aggregate_ret agg b)
+ end;
(* The rest of the tests will use one big function. *)
let fty = function_type i32_type [| i32_type; i32_type |] in
@@ -834,7 +856,44 @@ let test_builder () =
let bb00 = append_block context "Bb00" fn in
ignore (build_unreachable (builder_at_end context bb00));
-
+
+ group "function attribute";
+ begin
+ ignore (add_function_attr fn Attribute.UWTable);
+ (* RUN: grep "X7.*uwtable" < %t.ll
+ *)
+ insist ([Attribute.UWTable] = function_attr fn);
+ end;
+
+ (* see test/Feature/exception.ll *)
+ let bblpad = append_block context "Bblpad" fn in
+ let rt = struct_type context [| pointer_type i8_type; i32_type |] in
+ let ft = var_arg_function_type i32_type [||] in
+ let personality = declare_function "__gxx_personality_v0" ft m in
+ let ztic = declare_global (pointer_type i8_type) "_ZTIc" m in
+ let ztid = declare_global (pointer_type i8_type) "_ZTId" m in
+ let ztipkc = declare_global (pointer_type i8_type) "_ZTIPKc" m in
+ begin
+ set_global_constant true ztic;
+ set_global_constant true ztid;
+ set_global_constant true ztipkc;
+ let lp = build_landingpad rt personality 0 "lpad"
+ (builder_at_end context bblpad) in begin
+ set_cleanup lp true;
+ add_clause lp ztic;
+ insist((pointer_type (pointer_type i8_type)) = type_of ztid);
+ let ety = pointer_type (pointer_type i8_type) in
+ add_clause lp (const_array ety [| ztipkc; ztid |]);
+ ignore (build_resume lp (builder_at_end context bblpad));
+ end;
+ (* RUN: grep "landingpad.*personality.*__gxx_personality_v0" < %t.ll
+ * RUN: grep "cleanup" < %t.ll
+ * RUN: grep "catch.*i8\*\*.*@_ZTIc" < %t.ll
+ * RUN: grep "filter.*@_ZTIPKc.*@_ZTId" < %t.ll
+ * RUN: grep "resume " < %t.ll
+ * *)
+ end;
+
group "ret"; begin
(* RUN: grep {ret.*P1} < %t.ll
*)
@@ -868,8 +927,23 @@ let test_builder () =
ignore (build_unreachable (builder_at_end context bb2));
let bb3 = append_block context "SwiBlock3" fn in
ignore (build_unreachable (builder_at_end context bb3));
- let si = build_switch p1 bb3 1 (builder_at_end context bb1) in
- ignore (add_case si (const_int i32_type 2) bb2)
+ let si = build_switch p1 bb3 1 (builder_at_end context bb1) in begin
+ ignore (add_case si (const_int i32_type 2) bb2);
+ insist (switch_default_dest si = bb3);
+ end;
+ end;
+
+ group "malloc/free"; begin
+ (* RUN: grep {call.*@malloc(i32 ptrtoint} < %t.ll
+ * RUN: grep {call.*@free(i8\*} < %t.ll
+ * RUN: grep {call.*@malloc(i32 %} < %t.ll
+ *)
+ let bb1 = append_block context "MallocBlock1" fn in
+ let m1 = (build_malloc (pointer_type i32_type) "m1"
+ (builder_at_end context bb1)) in
+ ignore (build_free m1 (builder_at_end context bb1));
+ ignore (build_array_malloc i32_type p1 "m2" (builder_at_end context bb1));
+ ignore (build_unreachable (builder_at_end context bb1));
end;
group "indirectbr"; begin
@@ -891,19 +965,11 @@ let test_builder () =
group "invoke"; begin
(* RUN: grep {build_invoke.*invoke.*P1.*P2} < %t.ll
- * RUN: grep {to.*Bb04.*unwind.*Bb00} < %t.ll
+ * RUN: grep {to.*Bb04.*unwind.*Bblpad} < %t.ll
*)
let bb04 = append_block context "Bb04" fn in
let b = builder_at_end context bb04 in
- ignore (build_invoke fn [| p1; p2 |] bb04 bb00 "build_invoke" b)
- end;
-
- group "unwind"; begin
- (* RUN: grep {unwind} < %t.ll
- *)
- let bb05 = append_block context "Bb05" fn in
- let b = builder_at_end context bb05 in
- ignore (build_unwind b)
+ ignore (build_invoke fn [| p1; p2 |] bb04 bblpad "build_invoke" b)
end;
group "unreachable"; begin
@@ -991,30 +1057,63 @@ let test_builder () =
* RUN: grep {%build_load = load i32\\* %build_array_alloca} < %t.ll
* RUN: grep {store i32 %P2, i32\\* %build_alloca} < %t.ll
* RUN: grep {%build_gep = getelementptr i32\\* %build_array_alloca, i32 %P2} < %t.ll
+ * RUN: grep {%build_in_bounds_gep = getelementptr inbounds i32\\* %build_array_alloca, i32 %P2} < %t.ll
+ * RUN: grep {%build_struct_gep = getelementptr inbounds.*%build_alloca2, i32 0, i32 1} < %t.ll
*)
let alloca = build_alloca i32_type "build_alloca" b in
let array_alloca = build_array_alloca i32_type p2 "build_array_alloca" b in
ignore(build_load array_alloca "build_load" b);
ignore(build_store p2 alloca b);
ignore(build_gep array_alloca [| p2 |] "build_gep" b);
+ ignore(build_in_bounds_gep array_alloca [| p2 |] "build_in_bounds_gep" b);
+
+ let sty = struct_type context [| i32_type; i8_type |] in
+ let alloca2 = build_alloca sty "build_alloca2" b in
+ ignore(build_struct_gep alloca2 1 "build_struct_gep" b);
+
ignore(build_unreachable b)
end;
-
+
+ group "string"; begin
+ let bb09 = append_block context "Bb09" fn in
+ let b = builder_at_end context bb09 in
+ let p = build_alloca (pointer_type i8_type) "p" b in
+ (* RUN: grep "build_global_string.*stringval" < %t.ll
+ * RUN: grep "store.*build_global_string1.*p" < %t.ll
+ * *)
+ ignore (build_global_string "stringval" "build_global_string" b);
+ let g = build_global_stringptr "stringval" "build_global_string1" b in
+ ignore (build_store g p b);
+ ignore(build_unreachable b);
+ end;
+
group "casts"; begin
let void_ptr = pointer_type i8_type in
(* RUN: grep {%build_trunc = trunc i32 %P1 to i8} < %t.ll
+ * RUN: grep {%build_trunc2 = trunc i32 %P1 to i8} < %t.ll
+ * RUN: grep {%build_trunc3 = trunc i32 %P1 to i8} < %t.ll
* RUN: grep {%build_zext = zext i8 %build_trunc to i32} < %t.ll
+ * RUN: grep {%build_zext2 = zext i8 %build_trunc to i32} < %t.ll
* RUN: grep {%build_sext = sext i32 %build_zext to i64} < %t.ll
+ * RUN: grep {%build_sext2 = sext i32 %build_zext to i64} < %t.ll
+ * RUN: grep {%build_sext3 = sext i32 %build_zext to i64} < %t.ll
* RUN: grep {%build_uitofp = uitofp i64 %build_sext to float} < %t.ll
* RUN: grep {%build_sitofp = sitofp i32 %build_zext to double} < %t.ll
* RUN: grep {%build_fptoui = fptoui float %build_uitofp to i32} < %t.ll
* RUN: grep {%build_fptosi = fptosi double %build_sitofp to i64} < %t.ll
* RUN: grep {%build_fptrunc = fptrunc double %build_sitofp to float} < %t.ll
+ * RUN: grep {%build_fptrunc2 = fptrunc double %build_sitofp to float} < %t.ll
* RUN: grep {%build_fpext = fpext float %build_fptrunc to double} < %t.ll
+ * RUN: grep {%build_fpext2 = fpext float %build_fptrunc to double} < %t.ll
* RUN: grep {%build_inttoptr = inttoptr i32 %P1 to i8\\*} < %t.ll
* RUN: grep {%build_ptrtoint = ptrtoint i8\\* %build_inttoptr to i64} < %t.ll
+ * RUN: grep {%build_ptrtoint2 = ptrtoint i8\\* %build_inttoptr to i64} < %t.ll
* RUN: grep {%build_bitcast = bitcast i64 %build_ptrtoint to double} < %t.ll
+ * RUN: grep {%build_bitcast2 = bitcast i64 %build_ptrtoint to double} < %t.ll
+ * RUN: grep {%build_bitcast3 = bitcast i64 %build_ptrtoint to double} < %t.ll
+ * RUN: grep {%build_bitcast4 = bitcast i64 %build_ptrtoint to double} < %t.ll
+ * RUN: grep {%build_pointercast = bitcast i8\\* %build_inttoptr to i16\\*} < %t.ll
*)
let inst28 = build_trunc p1 i8_type "build_trunc" atentry in
let inst29 = build_zext inst28 i32_type "build_zext" atentry in
@@ -1027,7 +1126,20 @@ let test_builder () =
ignore(build_fpext inst35 double_type "build_fpext" atentry);
let inst37 = build_inttoptr p1 void_ptr "build_inttoptr" atentry in
let inst38 = build_ptrtoint inst37 i64_type "build_ptrtoint" atentry in
- ignore(build_bitcast inst38 double_type "build_bitcast" atentry)
+ ignore(build_bitcast inst38 double_type "build_bitcast" atentry);
+ ignore(build_zext_or_bitcast inst38 double_type "build_bitcast2" atentry);
+ ignore(build_sext_or_bitcast inst38 double_type "build_bitcast3" atentry);
+ ignore(build_trunc_or_bitcast inst38 double_type "build_bitcast4" atentry);
+ ignore(build_pointercast inst37 (pointer_type i16_type) "build_pointercast" atentry);
+
+ ignore(build_zext_or_bitcast inst28 i32_type "build_zext2" atentry);
+ ignore(build_sext_or_bitcast inst29 i64_type "build_sext2" atentry);
+ ignore(build_trunc_or_bitcast p1 i8_type "build_trunc2" atentry);
+ ignore(build_pointercast inst37 i64_type "build_ptrtoint2" atentry);
+ ignore(build_intcast inst29 i64_type "build_sext3" atentry);
+ ignore(build_intcast p1 i8_type "build_trunc3" atentry);
+ ignore(build_fpcast inst35 double_type "build_fpext2" atentry);
+ ignore(build_fpcast inst32 float_type "build_fptrunc2" atentry);
end;
group "comparisons"; begin
@@ -1035,11 +1147,21 @@ let test_builder () =
* RUN: grep {%build_icmp_sle = icmp sle i32 %P2, %P1} < %t.ll
* RUN: grep {%build_fcmp_false = fcmp false float %F1, %F2} < %t.ll
* RUN: grep {%build_fcmp_true = fcmp true float %F2, %F1} < %t.ll
+ * RUN: grep {%build_is_null.*= icmp eq.*%X0,.*null} < %t.ll
+ * RUN: grep {%build_is_not_null = icmp ne i8\\* %X1, null} < %t.ll
+ * RUN: grep {%build_ptrdiff} < %t.ll
*)
ignore (build_icmp Icmp.Ne p1 p2 "build_icmp_ne" atentry);
ignore (build_icmp Icmp.Sle p2 p1 "build_icmp_sle" atentry);
ignore (build_fcmp Fcmp.False f1 f2 "build_fcmp_false" atentry);
- ignore (build_fcmp Fcmp.True f2 f1 "build_fcmp_true" atentry)
+ ignore (build_fcmp Fcmp.True f2 f1 "build_fcmp_true" atentry);
+ let g0 = declare_global (pointer_type i8_type) "g0" m in
+ let g1 = declare_global (pointer_type i8_type) "g1" m in
+ let p0 = build_load g0 "X0" atentry in
+ let p1 = build_load g1 "X1" atentry in
+ ignore (build_is_null p0 "build_is_null" atentry);
+ ignore (build_is_not_null p1 "build_is_not_null" atentry);
+ ignore (build_ptrdiff p1 p0 "build_ptrdiff" atentry);
end;
group "miscellaneous"; begin
@@ -1049,6 +1171,8 @@ let test_builder () =
* RUN: grep {%build_extractelement = extractelement <4 x i32> %Vec1, i32 %P2} < %t.ll
* RUN: grep {%build_insertelement = insertelement <4 x i32> %Vec1, i32 %P1, i32 %P2} < %t.ll
* RUN: grep {%build_shufflevector = shufflevector <4 x i32> %Vec1, <4 x i32> %Vec2, <4 x i32> <i32 1, i32 1, i32 0, i32 0>} < %t.ll
+ * RUN: grep {%build_insertvalue0 = insertvalue.*%bl, i32 1, 0} < %t.ll
+ * RUN: grep {%build_extractvalue = extractvalue.*%build_insertvalue1, 1} < %t.ll
*)
let ci = build_call fn [| p2; p1 |] "build_call" atentry in
insist (CallConv.c = instruction_call_conv ci);
@@ -1075,10 +1199,19 @@ let test_builder () =
let t3 = const_vector [| one; one; zero; zero |] in
let vec1 = build_insertelement t1 p1 p2 "Vec1" atentry in
let vec2 = build_insertelement t2 p1 p2 "Vec2" atentry in
+ let sty = struct_type context [| i32_type; i8_type |] in
ignore (build_extractelement vec1 p2 "build_extractelement" atentry);
ignore (build_insertelement vec1 p1 p2 "build_insertelement" atentry);
ignore (build_shufflevector vec1 vec2 t3 "build_shufflevector" atentry);
+
+ let p = build_alloca sty "ba" atentry in
+ let agg = build_load p "bl" atentry in
+ let agg0 = build_insertvalue agg (const_int i32_type 1) 0
+ "build_insertvalue0" atentry in
+ let agg1 = build_insertvalue agg0 (const_int i8_type 2) 1
+ "build_insertvalue1" atentry in
+ ignore (build_extractvalue agg1 1 "build_extractvalue" atentry)
end;
group "metadata"; begin
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 9fc76a9..7bb1bdd 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -114,7 +114,7 @@ if(PYTHONINTERP_FOUND)
UnitTests
BugpointPasses LLVMHello
llc lli llvm-ar llvm-as llvm-dis llvm-extract
- llvm-ld llvm-link llvm-mc llvm-nm macho-dump opt
+ llvm-ld llvm-link llvm-mc llvm-nm llvm-objdump macho-dump opt
FileCheck count not)
set_target_properties(check.deps PROPERTIES FOLDER "Tests")
diff --git a/test/CodeGen/ARM/2009-10-16-Scope.ll b/test/CodeGen/ARM/2009-10-16-Scope.ll
index ce440e9..a2e7ff7 100644
--- a/test/CodeGen/ARM/2009-10-16-Scope.ll
+++ b/test/CodeGen/ARM/2009-10-16-Scope.ll
@@ -23,10 +23,10 @@ declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
declare i32 @foo(i32) ssp
!0 = metadata !{i32 5, i32 2, metadata !1, null}
-!1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
+!1 = metadata !{i32 458763, metadata !2, i32 1, i32 1}; [DW_TAG_lexical_block ]
!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"bar", metadata !"bar", metadata !"bar", metadata !3, i32 4, null, i1 false, i1 true}; [DW_TAG_subprogram ]
!3 = metadata !{i32 458769, i32 0, i32 12, metadata !"genmodes.i", metadata !"/Users/yash/Downloads", metadata !"clang 1.1", i1 true, i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
!4 = metadata !{i32 459008, metadata !5, metadata !"count_", metadata !3, i32 5, metadata !6}; [ DW_TAG_auto_variable ]
-!5 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ]
+!5 = metadata !{i32 458763, metadata !1, i32 1, i32 1}; [DW_TAG_lexical_block ]
!6 = metadata !{i32 458788, metadata !3, metadata !"int", metadata !3, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5}; [DW_TAG_base_type ]
!7 = metadata !{i32 6, i32 1, metadata !2, null}
diff --git a/test/CodeGen/ARM/2010-11-30-reloc-movt.ll b/test/CodeGen/ARM/2010-11-30-reloc-movt.ll
index 930cd8d..8b164c5 100644
--- a/test/CodeGen/ARM/2010-11-30-reloc-movt.ll
+++ b/test/CodeGen/ARM/2010-11-30-reloc-movt.ll
@@ -21,20 +21,20 @@ entry:
; OBJ-NEXT: 'sh_entsize'
; OBJ-NEXT: '_section_data', '00482de9 000000e3 000040e3 feffffeb 0088bde8'
-; OBJ: Relocation 0x00000000
+; OBJ: Relocation 0
; OBJ-NEXT: 'r_offset', 0x00000004
-; OBJ-NEXT: 'r_sym', 0x00000007
-; OBJ-NEXT: 'r_type', 0x0000002b
+; OBJ-NEXT: 'r_sym', 0x000007
+; OBJ-NEXT: 'r_type', 0x2b
-; OBJ: Relocation 0x00000001
+; OBJ: Relocation 1
; OBJ-NEXT: 'r_offset', 0x00000008
; OBJ-NEXT: 'r_sym'
-; OBJ-NEXT: 'r_type', 0x0000002c
+; OBJ-NEXT: 'r_type', 0x2c
-; OBJ: # Relocation 0x00000002
+; OBJ: # Relocation 2
; OBJ-NEXT: 'r_offset', 0x0000000c
-; OBJ-NEXT: 'r_sym', 0x00000008
-; OBJ-NEXT: 'r_type', 0x0000001c
+; OBJ-NEXT: 'r_sym', 0x000008
+; OBJ-NEXT: 'r_type', 0x1c
}
diff --git a/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll b/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll
index 69d4a14..5cfbb4f 100644
--- a/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll
+++ b/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll
@@ -5,7 +5,7 @@
@dummy = internal global i32 666
-@array00 = internal global [20 x i32] zeroinitializer
+@array00 = internal global [80 x i8] zeroinitializer, align 1
@sum = internal global i32 55
@STRIDE = internal global i32 8
@@ -15,21 +15,22 @@
-; OBJ: Section 0x00000004
+; OBJ: Section 4
; OBJ-NEXT: '.bss'
; OBJ: 'array00'
; OBJ-NEXT: 'st_value', 0x00000000
; OBJ-NEXT: 'st_size', 0x00000050
-; OBJ-NEXT: 'st_bind', 0x00000000
-; OBJ-NEXT: 'st_type', 0x00000001
-; OBJ-NEXT: 'st_other', 0x00000000
-; OBJ-NEXT: 'st_shndx', 0x00000004
+; OBJ-NEXT: 'st_bind', 0x0
+; OBJ-NEXT: 'st_type', 0x1
+; OBJ-NEXT: 'st_other', 0x00
+; OBJ-NEXT: 'st_shndx', 0x0004
define i32 @main(i32 %argc) nounwind {
%1 = load i32* @sum, align 4
- %2 = getelementptr [20 x i32]* @array00, i32 0, i32 %argc
- %3 = load i32* %2, align 4
- %4 = add i32 %1, %3
- ret i32 %4;
+ %2 = getelementptr [80 x i8]* @array00, i32 0, i32 %argc
+ %3 = load i8* %2
+ %4 = zext i8 %3 to i32
+ %5 = add i32 %1, %4
+ ret i32 %5
}
diff --git a/test/CodeGen/ARM/2011-06-09-TailCallByVal.ll b/test/CodeGen/ARM/2011-06-09-TailCallByVal.ll
index 4db3acf..7f0f795 100644
--- a/test/CodeGen/ARM/2011-06-09-TailCallByVal.ll
+++ b/test/CodeGen/ARM/2011-06-09-TailCallByVal.ll
@@ -1,4 +1,5 @@
; RUN: llc < %s -relocation-model=pic -mcpu=cortex-a8 -arm-tail-calls=1 | FileCheck %s
+
target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
target triple = "thumbv7-apple-darwin10"
diff --git a/test/CodeGen/ARM/2011-08-02-MergedGlobalDbg.ll b/test/CodeGen/ARM/2011-08-02-MergedGlobalDbg.ll
new file mode 100644
index 0000000..f681c34
--- /dev/null
+++ b/test/CodeGen/ARM/2011-08-02-MergedGlobalDbg.ll
@@ -0,0 +1,124 @@
+; RUN: llc < %s | FileCheck %s
+
+; Check debug info output for merged global.
+; DW_AT_location
+; DW_OP_addr
+; DW_OP_plus
+; .long __MergedGlobals
+; DW_OP_constu
+; offset
+
+;CHECK: .ascii "x2" @ DW_AT_name
+;CHECK-NEXT: .byte 0
+;CHECK-NEXT: @ DW_AT_type
+;CHECK-NEXT: @ DW_AT_decl_file
+;CHECK-NEXT: @ DW_AT_decl_line
+;CHECK-NEXT: @ DW_AT_location
+;CHECK-NEXT: .byte 3
+;CHECK-NEXT: .long __MergedGlobals
+;CHECK-NEXT: .byte 16
+; 4 is byte offset of x2 in __MergedGobals
+;CHECK-NEXT: .byte 4
+;CHECK-NEXT: .byte 34
+
+
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32"
+target triple = "thumbv7-apple-macosx10.7.0"
+
+@x1 = internal unnamed_addr global i32 1, align 4
+@x2 = internal unnamed_addr global i32 2, align 4
+@x3 = internal unnamed_addr global i32 3, align 4
+@x4 = internal unnamed_addr global i32 4, align 4
+@x5 = global i32 0, align 4
+
+define i32 @get1(i32 %a) nounwind optsize ssp {
+ tail call void @llvm.dbg.value(metadata !{i32 %a}, i64 0, metadata !10), !dbg !30
+ %1 = load i32* @x1, align 4, !dbg !31
+ tail call void @llvm.dbg.value(metadata !{i32 %1}, i64 0, metadata !11), !dbg !31
+ store i32 %a, i32* @x1, align 4, !dbg !31
+ ret i32 %1, !dbg !31
+}
+
+define i32 @get2(i32 %a) nounwind optsize ssp {
+ tail call void @llvm.dbg.value(metadata !{i32 %a}, i64 0, metadata !13), !dbg !32
+ %1 = load i32* @x2, align 4, !dbg !33
+ tail call void @llvm.dbg.value(metadata !{i32 %1}, i64 0, metadata !14), !dbg !33
+ store i32 %a, i32* @x2, align 4, !dbg !33
+ ret i32 %1, !dbg !33
+}
+
+define i32 @get3(i32 %a) nounwind optsize ssp {
+ tail call void @llvm.dbg.value(metadata !{i32 %a}, i64 0, metadata !16), !dbg !34
+ %1 = load i32* @x3, align 4, !dbg !35
+ tail call void @llvm.dbg.value(metadata !{i32 %1}, i64 0, metadata !17), !dbg !35
+ store i32 %a, i32* @x3, align 4, !dbg !35
+ ret i32 %1, !dbg !35
+}
+
+define i32 @get4(i32 %a) nounwind optsize ssp {
+ tail call void @llvm.dbg.value(metadata !{i32 %a}, i64 0, metadata !19), !dbg !36
+ %1 = load i32* @x4, align 4, !dbg !37
+ tail call void @llvm.dbg.value(metadata !{i32 %1}, i64 0, metadata !20), !dbg !37
+ store i32 %a, i32* @x4, align 4, !dbg !37
+ ret i32 %1, !dbg !37
+}
+
+define i32 @get5(i32 %a) nounwind optsize ssp {
+ tail call void @llvm.dbg.value(metadata !{i32 %a}, i64 0, metadata !27), !dbg !38
+ %1 = load i32* @x5, align 4, !dbg !39
+ tail call void @llvm.dbg.value(metadata !{i32 %1}, i64 0, metadata !28), !dbg !39
+ store i32 %a, i32* @x5, align 4, !dbg !39
+ ret i32 %1, !dbg !39
+}
+
+declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone
+
+!llvm.dbg.cu = !{!0}
+!llvm.dbg.sp = !{!1, !6, !7, !8, !9}
+!llvm.dbg.lv.get1 = !{!10, !11}
+!llvm.dbg.lv.get2 = !{!13, !14}
+!llvm.dbg.lv.get3 = !{!16, !17}
+!llvm.dbg.lv.get4 = !{!19, !20}
+!llvm.dbg.gv = !{!22, !23, !24, !25, !26}
+!llvm.dbg.lv.get5 = !{!27, !28}
+
+!0 = metadata !{i32 589841, i32 0, i32 12, metadata !"ss3.c", metadata !"/private/tmp", metadata !"clang", i1 true, i1 true, metadata !"", i32 0} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{i32 589870, i32 0, metadata !2, metadata !"get1", metadata !"get1", metadata !"", metadata !2, i32 5, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, i32 (i32)* @get1, null, null} ; [ DW_TAG_subprogram ]
+!2 = metadata !{i32 589865, metadata !"ss3.c", metadata !"/private/tmp", metadata !0} ; [ DW_TAG_file_type ]
+!3 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 589860, metadata !0, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!6 = metadata !{i32 589870, i32 0, metadata !2, metadata !"get2", metadata !"get2", metadata !"", metadata !2, i32 8, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, i32 (i32)* @get2, null, null} ; [ DW_TAG_subprogram ]
+!7 = metadata !{i32 589870, i32 0, metadata !2, metadata !"get3", metadata !"get3", metadata !"", metadata !2, i32 11, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, i32 (i32)* @get3, null, null} ; [ DW_TAG_subprogram ]
+!8 = metadata !{i32 589870, i32 0, metadata !2, metadata !"get4", metadata !"get4", metadata !"", metadata !2, i32 14, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, i32 (i32)* @get4, null, null} ; [ DW_TAG_subprogram ]
+!9 = metadata !{i32 589870, i32 0, metadata !2, metadata !"get5", metadata !"get5", metadata !"", metadata !2, i32 17, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, i32 (i32)* @get5, null, null} ; [ DW_TAG_subprogram ]
+!10 = metadata !{i32 590081, metadata !1, metadata !"a", metadata !2, i32 16777221, metadata !5, i32 0} ; [ DW_TAG_arg_variable ]
+!11 = metadata !{i32 590080, metadata !12, metadata !"b", metadata !2, i32 5, metadata !5, i32 0} ; [ DW_TAG_auto_variable ]
+!12 = metadata !{i32 589835, metadata !1, i32 5, i32 19, metadata !2, i32 0} ; [ DW_TAG_lexical_block ]
+!13 = metadata !{i32 590081, metadata !6, metadata !"a", metadata !2, i32 16777224, metadata !5, i32 0} ; [ DW_TAG_arg_variable ]
+!14 = metadata !{i32 590080, metadata !15, metadata !"b", metadata !2, i32 8, metadata !5, i32 0} ; [ DW_TAG_auto_variable ]
+!15 = metadata !{i32 589835, metadata !6, i32 8, i32 17, metadata !2, i32 1} ; [ DW_TAG_lexical_block ]
+!16 = metadata !{i32 590081, metadata !7, metadata !"a", metadata !2, i32 16777227, metadata !5, i32 0} ; [ DW_TAG_arg_variable ]
+!17 = metadata !{i32 590080, metadata !18, metadata !"b", metadata !2, i32 11, metadata !5, i32 0} ; [ DW_TAG_auto_variable ]
+!18 = metadata !{i32 589835, metadata !7, i32 11, i32 19, metadata !2, i32 2} ; [ DW_TAG_lexical_block ]
+!19 = metadata !{i32 590081, metadata !8, metadata !"a", metadata !2, i32 16777230, metadata !5, i32 0} ; [ DW_TAG_arg_variable ]
+!20 = metadata !{i32 590080, metadata !21, metadata !"b", metadata !2, i32 14, metadata !5, i32 0} ; [ DW_TAG_auto_variable ]
+!21 = metadata !{i32 589835, metadata !8, i32 14, i32 19, metadata !2, i32 3} ; [ DW_TAG_lexical_block ]
+!22 = metadata !{i32 589876, i32 0, metadata !0, metadata !"x5", metadata !"x5", metadata !"", metadata !2, i32 16, metadata !5, i32 0, i32 1, i32* @x5} ; [ DW_TAG_variable ]
+!23 = metadata !{i32 589876, i32 0, metadata !0, metadata !"x4", metadata !"x4", metadata !"", metadata !2, i32 13, metadata !5, i32 1, i32 1, i32* @x4} ; [ DW_TAG_variable ]
+!24 = metadata !{i32 589876, i32 0, metadata !0, metadata !"x3", metadata !"x3", metadata !"", metadata !2, i32 10, metadata !5, i32 1, i32 1, i32* @x3} ; [ DW_TAG_variable ]
+!25 = metadata !{i32 589876, i32 0, metadata !0, metadata !"x2", metadata !"x2", metadata !"", metadata !2, i32 7, metadata !5, i32 1, i32 1, i32* @x2} ; [ DW_TAG_variable ]
+!26 = metadata !{i32 589876, i32 0, metadata !0, metadata !"x1", metadata !"x1", metadata !"", metadata !2, i32 4, metadata !5, i32 1, i32 1, i32* @x1} ; [ DW_TAG_variable ]
+!27 = metadata !{i32 590081, metadata !9, metadata !"a", metadata !2, i32 16777233, metadata !5, i32 0} ; [ DW_TAG_arg_variable ]
+!28 = metadata !{i32 590080, metadata !29, metadata !"b", metadata !2, i32 17, metadata !5, i32 0} ; [ DW_TAG_auto_variable ]
+!29 = metadata !{i32 589835, metadata !9, i32 17, i32 19, metadata !2, i32 4} ; [ DW_TAG_lexical_block ]
+!30 = metadata !{i32 5, i32 16, metadata !1, null}
+!31 = metadata !{i32 5, i32 32, metadata !12, null}
+!32 = metadata !{i32 8, i32 14, metadata !6, null}
+!33 = metadata !{i32 8, i32 29, metadata !15, null}
+!34 = metadata !{i32 11, i32 16, metadata !7, null}
+!35 = metadata !{i32 11, i32 32, metadata !18, null}
+!36 = metadata !{i32 14, i32 16, metadata !8, null}
+!37 = metadata !{i32 14, i32 32, metadata !21, null}
+!38 = metadata !{i32 17, i32 16, metadata !9, null}
+!39 = metadata !{i32 17, i32 32, metadata !29, null}
diff --git a/test/CodeGen/ARM/2011-08-12-vmovqqqq-pseudo.ll b/test/CodeGen/ARM/2011-08-12-vmovqqqq-pseudo.ll
new file mode 100644
index 0000000..3cbc4cd
--- /dev/null
+++ b/test/CodeGen/ARM/2011-08-12-vmovqqqq-pseudo.ll
@@ -0,0 +1,12 @@
+; RUN: llc %s -mtriple=thumbv7-apple-darwin -verify-machineinstrs -mcpu=cortex-a9 -O0 -o -
+; Make sure that the VMOVQQQQ pseudo instruction is handled properly
+; by codegen.
+
+define void @test_vmovqqqq_pseudo() nounwind ssp {
+entry:
+ %vld3_lane = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3lane.v8i16(i8* undef, <8 x i16> undef, <8 x i16> undef, <8 x i16> zeroinitializer, i32 7, i32 2)
+ store { <8 x i16>, <8 x i16>, <8 x i16> } %vld3_lane, { <8 x i16>, <8 x i16>, <8 x i16> }* undef
+ ret void
+}
+
+declare { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3lane.v8i16(i8*, <8 x i16>, <8 x i16>, <8 x i16>, i32, i32) nounwind readonly
diff --git a/test/CodeGen/ARM/2011-08-25-ldmia_ret.ll b/test/CodeGen/ARM/2011-08-25-ldmia_ret.ll
new file mode 100644
index 0000000..17264ee
--- /dev/null
+++ b/test/CodeGen/ARM/2011-08-25-ldmia_ret.ll
@@ -0,0 +1,100 @@
+; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a9 | FileCheck %s
+; Test that ldmia_ret preserves implicit operands for return values.
+;
+; This CFG is reduced from a benchmark miscompile. With current
+; if-conversion heuristics, one of the return paths is if-converted
+; into sw.bb18 resulting in an ldmia_ret in the middle of the
+; block. The postra scheduler needs to know that the return implicitly
+; uses the return register, otherwise its antidep breaker scavenges
+; the register in order to hoist the constant load required to test
+; the switch.
+
+declare i32 @getint()
+declare i1 @getbool()
+declare void @foo(i32)
+declare i32 @bar(i32)
+
+define i32 @test(i32 %in1, i32 %in2) nounwind {
+entry:
+ %call = tail call zeroext i1 @getbool() nounwind
+ br i1 %call, label %sw.bb18, label %sw.bb2
+
+sw.bb2: ; preds = %entry
+ %cmp = tail call zeroext i1 @getbool() nounwind
+ br i1 %cmp, label %sw.epilog58, label %land.lhs.true
+
+land.lhs.true: ; preds = %sw.bb2
+ %cmp13 = tail call zeroext i1 @getbool() nounwind
+ br i1 %cmp13, label %if.then, label %sw.epilog58
+
+if.then: ; preds = %land.lhs.true
+ tail call void @foo(i32 %in1) nounwind
+ br label %sw.epilog58
+
+; load the return value
+; CHECK: movs [[RRET:r.]], #2
+; hoist the switch constant without clobbering RRET
+; CHECK: movw
+; CHECK-NOT: [[RRET]]
+; CHECK: , #63707
+; CHECK-NOT: [[RRET]]
+; CHECK: tst
+; If-convert the return
+; CHECK: it ne
+; Fold the CSR+return into a pop
+; CHECK: popne {r4, r5, r7, pc}
+sw.bb18:
+ %call20 = tail call i32 @bar(i32 %in2) nounwind
+ switch i32 %call20, label %sw.default56 [
+ i32 168, label %sw.bb21
+ i32 165, label %sw.bb21
+ i32 261, label %sw.epilog58
+ i32 188, label %sw.epilog58
+ i32 187, label %sw.epilog58
+ i32 186, label %sw.epilog58
+ i32 185, label %sw.epilog58
+ i32 184, label %sw.epilog58
+ i32 175, label %sw.epilog58
+ i32 174, label %sw.epilog58
+ i32 173, label %sw.epilog58
+ i32 172, label %sw.epilog58
+ i32 171, label %sw.epilog58
+ i32 167, label %sw.epilog58
+ i32 166, label %sw.epilog58
+ i32 164, label %sw.epilog58
+ i32 163, label %sw.epilog58
+ i32 161, label %sw.epilog58
+ i32 160, label %sw.epilog58
+ i32 -1, label %sw.bb33
+ ]
+
+sw.bb21: ; preds = %sw.bb18, %sw.bb18
+ tail call void @foo(i32 %in2) nounwind
+ %call28 = tail call i32 @getint() nounwind
+ %tobool = icmp eq i32 %call28, 0
+ br i1 %tobool, label %if.then29, label %sw.epilog58
+
+if.then29: ; preds = %sw.bb21
+ tail call void @foo(i32 %in2) nounwind
+ br label %sw.epilog58
+
+sw.bb33: ; preds = %sw.bb18
+ %cmp42 = tail call zeroext i1 @getbool() nounwind
+ br i1 %cmp42, label %sw.default56, label %land.lhs.true44
+
+land.lhs.true44: ; preds = %sw.bb33
+ %call50 = tail call i32 @getint() nounwind
+ %cmp51 = icmp slt i32 %call50, 0
+ br i1 %cmp51, label %if.then53, label %sw.default56
+
+if.then53: ; preds = %land.lhs.true44
+ tail call void @foo(i32 %in2) nounwind
+ br label %sw.default56
+
+sw.default56: ; preds = %sw.bb33, %land.lhs.true44, %if.then53, %sw.bb18
+ br label %sw.epilog58
+
+sw.epilog58:
+ %retval.0 = phi i32 [ 4, %sw.default56 ], [ 2, %sw.bb21 ], [ 2, %if.then29 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb18 ], [ 2, %sw.bb2 ], [ 2, %land.lhs.true ], [ 2, %if.then ]
+ ret i32 %retval.0
+}
diff --git a/test/CodeGen/ARM/2011-08-29-SchedCycle.ll b/test/CodeGen/ARM/2011-08-29-SchedCycle.ll
new file mode 100644
index 0000000..be188ef
--- /dev/null
+++ b/test/CodeGen/ARM/2011-08-29-SchedCycle.ll
@@ -0,0 +1,45 @@
+; RUN: llc %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a8 -o -
+
+; When a i64 sub is expanded to subc + sube.
+; libcall #1
+; \
+; \ subc
+; \ / \
+; \ / \
+; \ / libcall #2
+; sube
+;
+; If the libcalls are not serialized (i.e. both have chains which are dag
+; entry), legalizer can serialize them in arbitrary orders. If it's
+; unlucky, it can force libcall #2 before libcall #1 in the above case.
+;
+; subc
+; |
+; libcall #2
+; |
+; libcall #1
+; |
+; sube
+;
+; However since subc and sube are "glued" together, this ends up being a
+; cycle when the scheduler combine subc and sube as a single scheduling
+; unit.
+;
+; The right solution is to fix LegalizeType too chains the libcalls together.
+; However, LegalizeType is not processing nodes in order. The fix now is to
+; fix subc / sube (and addc / adde) to use physical register dependency instead.
+; rdar://10019576
+
+define void @t() nounwind {
+entry:
+ %tmp = load i64* undef, align 4
+ %tmp5 = udiv i64 %tmp, 30
+ %tmp13 = and i64 %tmp5, 64739244643450880
+ %tmp16 = sub i64 0, %tmp13
+ %tmp19 = and i64 %tmp16, 63
+ %tmp20 = urem i64 %tmp19, 3
+ %tmp22 = and i64 %tmp16, -272346829004752
+ store i64 %tmp22, i64* undef, align 4
+ store i64 %tmp20, i64* undef, align 4
+ ret void
+}
diff --git a/test/CodeGen/ARM/2011-08-29-ldr_pre_imm.ll b/test/CodeGen/ARM/2011-08-29-ldr_pre_imm.ll
new file mode 100644
index 0000000..6647ed8
--- /dev/null
+++ b/test/CodeGen/ARM/2011-08-29-ldr_pre_imm.ll
@@ -0,0 +1,34 @@
+; RUN: llc -O3 -mtriple=armv6-apple-darwin -relocation-model=pic < %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:64-n32"
+
+define void @compdecomp() nounwind {
+entry:
+ %heap = alloca [256 x i32], align 4
+ br i1 undef, label %bb25.lr.ph, label %bb17
+
+bb17: ; preds = %bb17, %entry
+ br label %bb17
+
+bb25.lr.ph: ; preds = %entry
+ %0 = sdiv i32 undef, 2
+ br label %bb5.i
+
+bb.i: ; preds = %bb5.i
+ %1 = shl nsw i32 %k_addr.0.i, 1
+ %.sum8.i = add i32 %1, -1
+ %2 = getelementptr inbounds [256 x i32]* %heap, i32 0, i32 %.sum8.i
+ %3 = load i32* %2, align 4
+ br i1 false, label %bb5.i, label %bb4.i
+
+bb4.i: ; preds = %bb.i
+ %.sum10.i = add i32 %k_addr.0.i, -1
+ %4 = getelementptr inbounds [256 x i32]* %heap, i32 0, i32 %.sum10.i
+ store i32 %3, i32* %4, align 4
+ br label %bb5.i
+
+bb5.i: ; preds = %bb5.i, %bb4.i, %bb.i, %bb25.lr.ph
+ %k_addr.0.i = phi i32 [ %1, %bb4.i ], [ undef, %bb25.lr.ph ], [ undef, %bb5.i ], [ undef, %bb.i ]
+ %5 = icmp slt i32 %0, %k_addr.0.i
+ br i1 %5, label %bb5.i, label %bb.i
+}
diff --git a/test/CodeGen/ARM/2011-09-09-OddVectorDivision.ll b/test/CodeGen/ARM/2011-09-09-OddVectorDivision.ll
new file mode 100644
index 0000000..8fe9102
--- /dev/null
+++ b/test/CodeGen/ARM/2011-09-09-OddVectorDivision.ll
@@ -0,0 +1,23 @@
+; RUN: llc -mtriple=armv7-- < %s -mattr=-neon
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32"
+target triple = "armv7-none-linux-gnueabi"
+
+@x1 = common global <3 x i16> zeroinitializer
+@y1 = common global <3 x i16> zeroinitializer
+@z1 = common global <3 x i16> zeroinitializer
+@x2 = common global <4 x i16> zeroinitializer
+@y2 = common global <4 x i16> zeroinitializer
+@z2 = common global <4 x i16> zeroinitializer
+
+define void @f() {
+ %1 = load <3 x i16>* @x1
+ %2 = load <3 x i16>* @y1
+ %3 = sdiv <3 x i16> %1, %2
+ store <3 x i16> %3, <3 x i16>* @z1
+ %4 = load <4 x i16>* @x2
+ %5 = load <4 x i16>* @y2
+ %6 = sdiv <4 x i16> %4, %5
+ store <4 x i16> %6, <4 x i16>* @z2
+ ret void
+}
diff --git a/test/CodeGen/ARM/2011-09-19-cpsr.ll b/test/CodeGen/ARM/2011-09-19-cpsr.ll
new file mode 100644
index 0000000..749a6d2
--- /dev/null
+++ b/test/CodeGen/ARM/2011-09-19-cpsr.ll
@@ -0,0 +1,54 @@
+; RUN: llc -march=thumb -mcpu=cortex-a8 < %s
+; rdar://problem/10137436: sqlite3 miscompile
+;
+; CHECK: subs
+; CHECK: cmp
+; CHECK: it
+
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32"
+target triple = "thumbv7-apple-ios4.0.0"
+
+declare i8* @__memset_chk(i8*, i32, i32, i32) nounwind
+
+define hidden fastcc i32 @sqlite3VdbeExec(i32* %p) nounwind {
+entry:
+ br label %sqlite3VarintLen.exit7424
+
+sqlite3VarintLen.exit7424: ; preds = %do.body.i7423
+ br label %do.body.i
+
+do.body.i: ; preds = %do.body.i, %sqlite3VarintLen.exit7424
+ br i1 undef, label %do.body.i, label %sqlite3VarintLen.exit
+
+sqlite3VarintLen.exit: ; preds = %do.body.i
+ %sub2322 = add i64 undef, undef
+ br i1 undef, label %too_big, label %if.end2327
+
+if.end2327: ; preds = %sqlite3VarintLen.exit
+ br i1 undef, label %if.end2341, label %no_mem
+
+if.end2341: ; preds = %if.end2327
+ br label %for.body2355
+
+for.body2355: ; preds = %for.body2355, %if.end2341
+ %add2366 = add nsw i32 undef, undef
+ br i1 undef, label %for.body2377, label %for.body2355
+
+for.body2377: ; preds = %for.body2355
+ %conv23836154 = zext i32 %add2366 to i64
+ %sub2384 = sub i64 %sub2322, %conv23836154
+ %conv2385 = trunc i64 %sub2384 to i32
+ %len.0.i = select i1 undef, i32 %conv2385, i32 undef
+ %sub.i7384 = sub nsw i32 %len.0.i, 0
+ %call.i.i7385 = call i8* @__memset_chk(i8* undef, i32 0, i32 %sub.i7384, i32 undef) nounwind
+ unreachable
+
+too_big: ; preds = %sqlite3VarintLen.exit
+ unreachable
+
+no_mem: ; preds = %if.end2327, %for.body, %entry.no_mem_crit_edge
+ unreachable
+
+sqlite3ErrStr.exit: ; preds = %if.then82
+ unreachable
+}
diff --git a/test/CodeGen/ARM/2011-09-28-CMovCombineBug.ll b/test/CodeGen/ARM/2011-09-28-CMovCombineBug.ll
new file mode 100644
index 0000000..c6f4a93
--- /dev/null
+++ b/test/CodeGen/ARM/2011-09-28-CMovCombineBug.ll
@@ -0,0 +1,30 @@
+; RUN: llc -mtriple=thumbv7-apple-ios -mcpu=cortex-a8 < %s
+
+; rdar://10196296
+; ARM target specific dag combine created a cycle in DAG.
+
+define void @t() nounwind ssp {
+ %1 = load i64* undef, align 4
+ %2 = shl i32 5, 0
+ %3 = zext i32 %2 to i64
+ %4 = and i64 %1, %3
+ %5 = lshr i64 %4, undef
+ switch i64 %5, label %8 [
+ i64 0, label %9
+ i64 1, label %6
+ i64 4, label %9
+ i64 5, label %7
+ ]
+
+; <label>:6 ; preds = %0
+ unreachable
+
+; <label>:7 ; preds = %0
+ unreachable
+
+; <label>:8 ; preds = %0
+ unreachable
+
+; <label>:9 ; preds = %0, %0
+ ret void
+}
diff --git a/test/CodeGen/ARM/atomic-64bit.ll b/test/CodeGen/ARM/atomic-64bit.ll
new file mode 100644
index 0000000..e9609ac
--- /dev/null
+++ b/test/CodeGen/ARM/atomic-64bit.ll
@@ -0,0 +1,128 @@
+; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s
+
+define i64 @test1(i64* %ptr, i64 %val) {
+; CHECK: test1
+; CHECK: dmb ish
+; CHECK: ldrexd r2, r3
+; CHECK: adds r0, r2
+; CHECK: adc r1, r3
+; CHECK: strexd {{[a-z0-9]+}}, r0, r1
+; CHECK: cmp
+; CHECK: bne
+; CHECK: dmb ish
+ %r = atomicrmw add i64* %ptr, i64 %val seq_cst
+ ret i64 %r
+}
+
+define i64 @test2(i64* %ptr, i64 %val) {
+; CHECK: test2
+; CHECK: dmb ish
+; CHECK: ldrexd r2, r3
+; CHECK: subs r0, r2
+; CHECK: sbc r1, r3
+; CHECK: strexd {{[a-z0-9]+}}, r0, r1
+; CHECK: cmp
+; CHECK: bne
+; CHECK: dmb ish
+ %r = atomicrmw sub i64* %ptr, i64 %val seq_cst
+ ret i64 %r
+}
+
+define i64 @test3(i64* %ptr, i64 %val) {
+; CHECK: test3
+; CHECK: dmb ish
+; CHECK: ldrexd r2, r3
+; CHECK: and r0, r2
+; CHECK: and r1, r3
+; CHECK: strexd {{[a-z0-9]+}}, r0, r1
+; CHECK: cmp
+; CHECK: bne
+; CHECK: dmb ish
+ %r = atomicrmw and i64* %ptr, i64 %val seq_cst
+ ret i64 %r
+}
+
+define i64 @test4(i64* %ptr, i64 %val) {
+; CHECK: test4
+; CHECK: dmb ish
+; CHECK: ldrexd r2, r3
+; CHECK: orr r0, r2
+; CHECK: orr r1, r3
+; CHECK: strexd {{[a-z0-9]+}}, r0, r1
+; CHECK: cmp
+; CHECK: bne
+; CHECK: dmb ish
+ %r = atomicrmw or i64* %ptr, i64 %val seq_cst
+ ret i64 %r
+}
+
+define i64 @test5(i64* %ptr, i64 %val) {
+; CHECK: test5
+; CHECK: dmb ish
+; CHECK: ldrexd r2, r3
+; CHECK: eor r0, r2
+; CHECK: eor r1, r3
+; CHECK: strexd {{[a-z0-9]+}}, r0, r1
+; CHECK: cmp
+; CHECK: bne
+; CHECK: dmb ish
+ %r = atomicrmw xor i64* %ptr, i64 %val seq_cst
+ ret i64 %r
+}
+
+define i64 @test6(i64* %ptr, i64 %val) {
+; CHECK: test6
+; CHECK: dmb ish
+; CHECK: ldrexd r2, r3
+; CHECK: strexd {{[a-z0-9]+}}, r0, r1
+; CHECK: cmp
+; CHECK: bne
+; CHECK: dmb ish
+ %r = atomicrmw xchg i64* %ptr, i64 %val seq_cst
+ ret i64 %r
+}
+
+define i64 @test7(i64* %ptr, i64 %val1, i64 %val2) {
+; CHECK: test7
+; CHECK: dmb ish
+; CHECK: ldrexd r2, r3
+; CHECK: cmp r2
+; CHECK: cmpeq r3
+; CHECK: bne
+; CHECK: strexd {{[a-z0-9]+}}, r0, r1
+; CHECK: cmp
+; CHECK: bne
+; CHECK: dmb ish
+ %r = cmpxchg i64* %ptr, i64 %val1, i64 %val2 seq_cst
+ ret i64 %r
+}
+
+; Compiles down to cmpxchg
+; FIXME: Should compile to a single ldrexd
+define i64 @test8(i64* %ptr) {
+; CHECK: test8
+; CHECK: ldrexd r2, r3
+; CHECK: cmp r2
+; CHECK: cmpeq r3
+; CHECK: bne
+; CHECK: strexd {{[a-z0-9]+}}, r0, r1
+; CHECK: cmp
+; CHECK: bne
+; CHECK: dmb ish
+ %r = load atomic i64* %ptr seq_cst, align 8
+ ret i64 %r
+}
+
+; Compiles down to atomicrmw xchg; there really isn't any more efficient
+; way to write it.
+define void @test9(i64* %ptr, i64 %val) {
+; CHECK: test9
+; CHECK: dmb ish
+; CHECK: ldrexd r2, r3
+; CHECK: strexd {{[a-z0-9]+}}, r0, r1
+; CHECK: cmp
+; CHECK: bne
+; CHECK: dmb ish
+ store atomic i64 %val, i64* %ptr seq_cst, align 8
+ ret void
+}
diff --git a/test/CodeGen/ARM/atomic-cmp.ll b/test/CodeGen/ARM/atomic-cmp.ll
index f31aa7b..82726da 100644
--- a/test/CodeGen/ARM/atomic-cmp.ll
+++ b/test/CodeGen/ARM/atomic-cmp.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mtriple=armv7-apple-darwin | FileCheck %s -check-prefix=ARM
-; RUN: llc < %s -mtriple=thumbv7-apple-darwin | FileCheck %s -check-prefix=T2
+; RUN: llc < %s -mtriple=armv7-apple-darwin -verify-machineinstrs | FileCheck %s -check-prefix=ARM
+; RUN: llc < %s -mtriple=thumbv7-apple-darwin -verify-machineinstrs | FileCheck %s -check-prefix=T2
; rdar://8964854
define i8 @t(i8* %a, i8 %b, i8 %c) nounwind {
@@ -10,8 +10,6 @@ define i8 @t(i8* %a, i8 %b, i8 %c) nounwind {
; T2: t:
; T2: ldrexb
; T2: strexb
- %tmp0 = tail call i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* %a, i8 %b, i8 %c)
+ %tmp0 = cmpxchg i8* %a, i8 %b, i8 %c monotonic
ret i8 %tmp0
}
-
-declare i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* nocapture, i8, i8) nounwind
diff --git a/test/CodeGen/ARM/atomic-load-store.ll b/test/CodeGen/ARM/atomic-load-store.ll
new file mode 100644
index 0000000..12a8fe4
--- /dev/null
+++ b/test/CodeGen/ARM/atomic-load-store.ll
@@ -0,0 +1,56 @@
+; RUN: llc < %s -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s -check-prefix=ARM
+; RUN: llc < %s -mtriple=armv7-apple-ios -O0 | FileCheck %s -check-prefix=ARM
+; RUN: llc < %s -mtriple=thumbv7-apple-ios | FileCheck %s -check-prefix=THUMBTWO
+; RUN: llc < %s -mtriple=thumbv6-apple-ios | FileCheck %s -check-prefix=THUMBONE
+
+define void @test1(i32* %ptr, i32 %val1) {
+; ARM: test1
+; ARM: dmb ish
+; ARM-NEXT: str
+; ARM-NEXT: dmb ish
+; THUMBONE: test1
+; THUMBONE: __sync_lock_test_and_set_4
+; THUMBTWO: test1
+; THUMBTWO: dmb ish
+; THUMBTWO-NEXT: str
+; THUMBTWO-NEXT: dmb ish
+ store atomic i32 %val1, i32* %ptr seq_cst, align 4
+ ret void
+}
+
+define i32 @test2(i32* %ptr) {
+; ARM: test2
+; ARM: ldr
+; ARM-NEXT: dmb ish
+; THUMBONE: test2
+; THUMBONE: __sync_val_compare_and_swap_4
+; THUMBTWO: test2
+; THUMBTWO: ldr
+; THUMBTWO-NEXT: dmb ish
+ %val = load atomic i32* %ptr seq_cst, align 4
+ ret i32 %val
+}
+
+define void @test3(i8* %ptr1, i8* %ptr2) {
+; ARM: test3
+; ARM: ldrb
+; ARM: strb
+; THUMBTWO: test3
+; THUMBTWO: ldrb
+; THUMBTWO: strb
+; THUMBONE: test3
+; THUMBONE: ldrb
+; THUMBONE: strb
+ %val = load atomic i8* %ptr1 unordered, align 1
+ store atomic i8 %val, i8* %ptr2 unordered, align 1
+ ret void
+}
+
+define void @test4(i8* %ptr1, i8* %ptr2) {
+; THUMBONE: test4
+; THUMBONE: ___sync_val_compare_and_swap_1
+; THUMBONE: ___sync_lock_test_and_set_1
+ %val = load atomic i8* %ptr1 seq_cst, align 1
+ store atomic i8 %val, i8* %ptr2 seq_cst, align 1
+ ret void
+}
diff --git a/test/CodeGen/ARM/atomic-op.ll b/test/CodeGen/ARM/atomic-op.ll
index 03940e3..02ce5a1 100644
--- a/test/CodeGen/ARM/atomic-op.ll
+++ b/test/CodeGen/ARM/atomic-op.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mtriple=armv7-apple-darwin10 | FileCheck %s
-; RUN: llc < %s -mtriple=thumbv7-apple-darwin10 | FileCheck %s
+; RUN: llc < %s -mtriple=armv7-apple-darwin10 -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -mtriple=thumbv7-apple-darwin10 -verify-machineinstrs | FileCheck %s
define void @func(i32 %argc, i8** %argv) nounwind {
entry:
@@ -24,80 +24,58 @@ entry:
; CHECK: ldrex
; CHECK: add
; CHECK: strex
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %val1, i32 %tmp ) ; <i32>:0 [#uses=1]
+ %0 = atomicrmw add i32* %val1, i32 %tmp monotonic
store i32 %0, i32* %old
; CHECK: ldrex
; CHECK: sub
; CHECK: strex
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %val2, i32 30 ) ; <i32>:1 [#uses=1]
+ %1 = atomicrmw sub i32* %val2, i32 30 monotonic
store i32 %1, i32* %old
; CHECK: ldrex
; CHECK: add
; CHECK: strex
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %val2, i32 1 ) ; <i32>:2 [#uses=1]
+ %2 = atomicrmw add i32* %val2, i32 1 monotonic
store i32 %2, i32* %old
; CHECK: ldrex
; CHECK: sub
; CHECK: strex
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %val2, i32 1 ) ; <i32>:3 [#uses=1]
+ %3 = atomicrmw sub i32* %val2, i32 1 monotonic
store i32 %3, i32* %old
; CHECK: ldrex
; CHECK: and
; CHECK: strex
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %andt, i32 4080 ) ; <i32>:4 [#uses=1]
+ %4 = atomicrmw and i32* %andt, i32 4080 monotonic
store i32 %4, i32* %old
; CHECK: ldrex
; CHECK: or
; CHECK: strex
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %ort, i32 4080 ) ; <i32>:5 [#uses=1]
+ %5 = atomicrmw or i32* %ort, i32 4080 monotonic
store i32 %5, i32* %old
; CHECK: ldrex
; CHECK: eor
; CHECK: strex
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %xort, i32 4080 ) ; <i32>:6 [#uses=1]
+ %6 = atomicrmw xor i32* %xort, i32 4080 monotonic
store i32 %6, i32* %old
; CHECK: ldrex
; CHECK: cmp
; CHECK: strex
- call i32 @llvm.atomic.load.min.i32.p0i32( i32* %val2, i32 16 ) ; <i32>:7 [#uses=1]
+ %7 = atomicrmw min i32* %val2, i32 16 monotonic
store i32 %7, i32* %old
%neg = sub i32 0, 1 ; <i32> [#uses=1]
; CHECK: ldrex
; CHECK: cmp
; CHECK: strex
- call i32 @llvm.atomic.load.min.i32.p0i32( i32* %val2, i32 %neg ) ; <i32>:8 [#uses=1]
+ %8 = atomicrmw min i32* %val2, i32 %neg monotonic
store i32 %8, i32* %old
; CHECK: ldrex
; CHECK: cmp
; CHECK: strex
- call i32 @llvm.atomic.load.max.i32.p0i32( i32* %val2, i32 1 ) ; <i32>:9 [#uses=1]
+ %9 = atomicrmw max i32* %val2, i32 1 monotonic
store i32 %9, i32* %old
; CHECK: ldrex
; CHECK: cmp
; CHECK: strex
- call i32 @llvm.atomic.load.max.i32.p0i32( i32* %val2, i32 0 ) ; <i32>:10 [#uses=1]
+ %10 = atomicrmw max i32* %val2, i32 0 monotonic
store i32 %10, i32* %old
ret void
}
-
-declare i32 @llvm.atomic.load.add.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.sub.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.and.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.or.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.xor.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.min.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.max.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.umax.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.umin.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.swap.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32*, i32, i32) nounwind
diff --git a/test/CodeGen/ARM/avoid-cpsr-rmw.ll b/test/CodeGen/ARM/avoid-cpsr-rmw.ll
index d0c4f3a..92aff70 100644
--- a/test/CodeGen/ARM/avoid-cpsr-rmw.ll
+++ b/test/CodeGen/ARM/avoid-cpsr-rmw.ll
@@ -6,9 +6,9 @@
define i32 @t(i32 %a, i32 %b, i32 %c, i32 %d) nounwind readnone {
entry:
; CHECK: t:
-; CHECK: muls r2, r3, r2
-; CHECK-NEXT: mul r0, r0, r1
-; CHECK-NEXT: muls r0, r2, r0
+; CHECK: muls [[REG:(r[0-9]+)]], r2, r3
+; CHECK-NEXT: mul [[REG2:(r[0-9]+)]], r0, r1
+; CHECK-NEXT: muls r0, [[REG2]], [[REG]]
%0 = mul nsw i32 %a, %b
%1 = mul nsw i32 %c, %d
%2 = mul nsw i32 %0, %1
diff --git a/test/CodeGen/ARM/call-tc.ll b/test/CodeGen/ARM/call-tc.ll
index e01750b..f78d998 100644
--- a/test/CodeGen/ARM/call-tc.ll
+++ b/test/CodeGen/ARM/call-tc.ll
@@ -1,6 +1,10 @@
; RUN: llc < %s -mtriple=armv6-apple-darwin -mattr=+vfp2 -arm-tail-calls | FileCheck %s -check-prefix=CHECKV6
; RUN: llc < %s -mtriple=armv6-linux-gnueabi -relocation-model=pic -mattr=+vfp2 -arm-tail-calls | FileCheck %s -check-prefix=CHECKELF
; RUN: llc < %s -mtriple=thumbv7-apple-darwin -arm-tail-calls | FileCheck %s -check-prefix=CHECKT2D
+; RUN: llc < %s -mtriple=thumbv7-apple-ios5.0 | FileCheck %s -check-prefix=CHECKT2D
+
+; Enable tailcall optimization for iOS 5.0
+; rdar://9120031
@t = weak global i32 ()* null ; <i32 ()**> [#uses=1]
diff --git a/test/CodeGen/ARM/carry.ll b/test/CodeGen/ARM/carry.ll
index 06b459e..f84774d 100644
--- a/test/CodeGen/ARM/carry.ll
+++ b/test/CodeGen/ARM/carry.ll
@@ -35,3 +35,13 @@ entry:
%dw = add i64 %ch, %bw
ret i64 %dw
}
+
+; rdar://10073745
+define i64 @f4(i64 %x) nounwind readnone {
+entry:
+; CHECK: f4:
+; CHECK: rsbs r
+; CHECK: rsc r
+ %0 = sub nsw i64 0, %x
+ ret i64 %0
+}
diff --git a/test/CodeGen/ARM/crash-greedy-v6.ll b/test/CodeGen/ARM/crash-greedy-v6.ll
new file mode 100644
index 0000000..fd42254
--- /dev/null
+++ b/test/CodeGen/ARM/crash-greedy-v6.ll
@@ -0,0 +1,32 @@
+; RUN: llc -disable-fp-elim -relocation-model=pic < %s
+target triple = "armv6-apple-ios"
+
+; Reduced from 177.mesa. This test causes a live range split before an LDR_POST instruction.
+; That requires leaveIntvBefore to be very accurate about the redefined value number.
+define internal void @sample_nearest_3d(i8* nocapture %tObj, i32 %n, float* nocapture %s, float* nocapture %t, float* nocapture %u, float* nocapture %lambda, i8* nocapture %red, i8* nocapture %green, i8* nocapture %blue, i8* nocapture %alpha) nounwind ssp {
+entry:
+ br i1 undef, label %for.end, label %for.body.lr.ph
+
+for.body.lr.ph: ; preds = %entry
+ br label %for.body
+
+for.body: ; preds = %for.body, %for.body.lr.ph
+ %i.031 = phi i32 [ 0, %for.body.lr.ph ], [ %0, %for.body ]
+ %arrayidx11 = getelementptr float* %t, i32 %i.031
+ %arrayidx15 = getelementptr float* %u, i32 %i.031
+ %arrayidx19 = getelementptr i8* %red, i32 %i.031
+ %arrayidx22 = getelementptr i8* %green, i32 %i.031
+ %arrayidx25 = getelementptr i8* %blue, i32 %i.031
+ %arrayidx28 = getelementptr i8* %alpha, i32 %i.031
+ %tmp12 = load float* %arrayidx11, align 4
+ tail call fastcc void @sample_3d_nearest(i8* %tObj, i8* undef, float undef, float %tmp12, float undef, i8* %arrayidx19, i8* %arrayidx22, i8* %arrayidx25, i8* %arrayidx28)
+ %0 = add i32 %i.031, 1
+ %exitcond = icmp eq i32 %0, %n
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body, %entry
+ ret void
+}
+
+declare fastcc void @sample_3d_nearest(i8* nocapture, i8* nocapture, float, float, float, i8* nocapture, i8* nocapture, i8* nocapture, i8* nocapture) nounwind ssp
+
diff --git a/test/CodeGen/ARM/crash.ll b/test/CodeGen/ARM/crash.ll
index 4b6876d..0f6f33e 100644
--- a/test/CodeGen/ARM/crash.ll
+++ b/test/CodeGen/ARM/crash.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -mtriple=thumbv7-apple-darwin10
+; RUN: llc < %s -mtriple=thumbv7-apple-darwin10 -verify-arm-pseudo-expand
; <rdar://problem/8529919>
%struct.foo = type { i32, i32 }
@@ -27,3 +27,45 @@ bb3:
exit:
ret void
}
+
+; PR10520 - REG_SEQUENCE with implicit-def operands.
+define arm_aapcs_vfpcc void @foo() nounwind align 2 {
+bb:
+ %tmp = shufflevector <2 x i64> undef, <2 x i64> undef, <1 x i32> <i32 1>
+ %tmp8 = bitcast <1 x i64> %tmp to <2 x float>
+ %tmp9 = shufflevector <2 x float> %tmp8, <2 x float> %tmp8, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+ %tmp10 = fmul <4 x float> undef, %tmp9
+ %tmp11 = fadd <4 x float> %tmp10, undef
+ %tmp12 = fadd <4 x float> undef, %tmp11
+ %tmp13 = bitcast <4 x float> %tmp12 to i128
+ %tmp14 = bitcast i128 %tmp13 to <4 x float>
+ %tmp15 = bitcast <4 x float> %tmp14 to i128
+ %tmp16 = bitcast i128 %tmp15 to <4 x float>
+ %tmp17 = bitcast <4 x float> %tmp16 to i128
+ %tmp18 = bitcast i128 %tmp17 to <4 x float>
+ %tmp19 = bitcast <4 x float> %tmp18 to i128
+ %tmp20 = bitcast i128 %tmp19 to <4 x float>
+ store <4 x float> %tmp20, <4 x float>* undef, align 16
+ ret void
+}
+
+; PR10520, second bug. NEONMoveFixPass needs to preserve implicit operands.
+define arm_aapcs_vfpcc void @pr10520_2() nounwind align 2 {
+bb:
+ %tmp76 = shufflevector <2 x i64> zeroinitializer, <2 x i64> zeroinitializer, <1 x i32> <i32 1>
+ %tmp77 = bitcast <1 x i64> %tmp76 to <2 x float>
+ %tmp78 = shufflevector <2 x float> %tmp77, <2 x float> %tmp77, <4 x i32> zeroinitializer
+ %tmp81 = fmul <4 x float> undef, %tmp78
+ %tmp82 = fadd <4 x float> %tmp81, undef
+ %tmp85 = fadd <4 x float> %tmp82, undef
+ %tmp86 = bitcast <4 x float> %tmp85 to i128
+ %tmp136 = bitcast i128 %tmp86 to <4 x float>
+ %tmp137 = bitcast <4 x float> %tmp136 to i128
+ %tmp138 = bitcast i128 %tmp137 to <4 x float>
+ %tmp139 = bitcast <4 x float> %tmp138 to i128
+ %tmp152 = bitcast i128 %tmp139 to <4 x float>
+ %tmp153 = bitcast <4 x float> %tmp152 to i128
+ %tmp154 = bitcast i128 %tmp153 to <4 x float>
+ store <4 x float> %tmp154, <4 x float>* undef, align 16
+ ret void
+}
diff --git a/test/CodeGen/ARM/debug-info-arg.ll b/test/CodeGen/ARM/debug-info-arg.ll
new file mode 100644
index 0000000..b0270f9
--- /dev/null
+++ b/test/CodeGen/ARM/debug-info-arg.ll
@@ -0,0 +1,65 @@
+; RUN: llc < %s | FileCheck %s
+; Test to check argument y's debug info uses FI
+; Radar 10048772
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32"
+target triple = "thumbv7-apple-macosx10.7.0"
+
+%struct.tag_s = type { i32, i32, i32 }
+
+define void @foo(%struct.tag_s* nocapture %this, %struct.tag_s* %c, i64 %x, i64 %y, %struct.tag_s* nocapture %ptr1, %struct.tag_s* nocapture %ptr2) nounwind ssp {
+ tail call void @llvm.dbg.value(metadata !{%struct.tag_s* %this}, i64 0, metadata !5), !dbg !20
+ tail call void @llvm.dbg.value(metadata !{%struct.tag_s* %c}, i64 0, metadata !13), !dbg !21
+ tail call void @llvm.dbg.value(metadata !{i64 %x}, i64 0, metadata !14), !dbg !22
+ tail call void @llvm.dbg.value(metadata !{i64 %y}, i64 0, metadata !17), !dbg !23
+;CHECK: @DEBUG_VALUE: foo:y <- R7+4294967295
+ tail call void @llvm.dbg.value(metadata !{%struct.tag_s* %ptr1}, i64 0, metadata !18), !dbg !24
+ tail call void @llvm.dbg.value(metadata !{%struct.tag_s* %ptr2}, i64 0, metadata !19), !dbg !25
+ %1 = icmp eq %struct.tag_s* %c, null, !dbg !26
+ br i1 %1, label %3, label %2, !dbg !26
+
+; <label>:2 ; preds = %0
+ tail call void @foobar(i64 %x, i64 %y) nounwind, !dbg !28
+ br label %3, !dbg !28
+
+; <label>:3 ; preds = %0, %2
+ ret void, !dbg !29
+}
+
+declare void @foobar(i64, i64)
+
+declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone
+
+!llvm.dbg.cu = !{!0}
+!llvm.dbg.sp = !{!1}
+!llvm.dbg.lv.foo = !{!5, !13, !14, !17, !18, !19}
+
+!0 = metadata !{i32 589841, i32 0, i32 12, metadata !"one.c", metadata !"/Volumes/Athwagate/R10048772", metadata !"Apple clang version 3.0 (tags/Apple/clang-211.10.1) (based on LLVM 3.0svn)", i1 true, i1 true, metadata !"", i32 0} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{i32 589870, i32 0, metadata !2, metadata !"foo", metadata !"foo", metadata !"", metadata !2, i32 11, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, void (%struct.tag_s*, %struct.tag_s*, i64, i64, %struct.tag_s*, %struct.tag_s*)* @foo, null, null} ; [ DW_TAG_subprogram ]
+!2 = metadata !{i32 589865, metadata !"one.c", metadata !"/Volumes/Athwagate/R10048772", metadata !0} ; [ DW_TAG_file_type ]
+!3 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!4 = metadata !{null}
+!5 = metadata !{i32 590081, metadata !1, metadata !"this", metadata !2, i32 16777227, metadata !6, i32 0} ; [ DW_TAG_arg_variable ]
+!6 = metadata !{i32 589839, metadata !0, metadata !"", null, i32 0, i64 32, i64 32, i64 0, i32 0, metadata !7} ; [ DW_TAG_pointer_type ]
+!7 = metadata !{i32 589843, metadata !0, metadata !"tag_s", metadata !2, i32 5, i64 96, i64 32, i32 0, i32 0, i32 0, metadata !8, i32 0, i32 0} ; [ DW_TAG_structure_type ]
+!8 = metadata !{metadata !9, metadata !11, metadata !12}
+!9 = metadata !{i32 589837, metadata !7, metadata !"x", metadata !2, i32 6, i64 32, i64 32, i64 0, i32 0, metadata !10} ; [ DW_TAG_member ]
+!10 = metadata !{i32 589860, metadata !0, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!11 = metadata !{i32 589837, metadata !7, metadata !"y", metadata !2, i32 7, i64 32, i64 32, i64 32, i32 0, metadata !10} ; [ DW_TAG_member ]
+!12 = metadata !{i32 589837, metadata !7, metadata !"z", metadata !2, i32 8, i64 32, i64 32, i64 64, i32 0, metadata !10} ; [ DW_TAG_member ]
+!13 = metadata !{i32 590081, metadata !1, metadata !"c", metadata !2, i32 33554443, metadata !6, i32 0} ; [ DW_TAG_arg_variable ]
+!14 = metadata !{i32 590081, metadata !1, metadata !"x", metadata !2, i32 50331659, metadata !15, i32 0} ; [ DW_TAG_arg_variable ]
+!15 = metadata !{i32 589846, metadata !0, metadata !"UInt64", metadata !2, i32 1, i64 0, i64 0, i64 0, i32 0, metadata !16} ; [ DW_TAG_typedef ]
+!16 = metadata !{i32 589860, metadata !0, metadata !"long long unsigned int", null, i32 0, i64 64, i64 32, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ]
+!17 = metadata !{i32 590081, metadata !1, metadata !"y", metadata !2, i32 67108875, metadata !15, i32 0} ; [ DW_TAG_arg_variable ]
+!18 = metadata !{i32 590081, metadata !1, metadata !"ptr1", metadata !2, i32 83886091, metadata !6, i32 0} ; [ DW_TAG_arg_variable ]
+!19 = metadata !{i32 590081, metadata !1, metadata !"ptr2", metadata !2, i32 100663307, metadata !6, i32 0} ; [ DW_TAG_arg_variable ]
+!20 = metadata !{i32 11, i32 24, metadata !1, null}
+!21 = metadata !{i32 11, i32 44, metadata !1, null}
+!22 = metadata !{i32 11, i32 54, metadata !1, null}
+!23 = metadata !{i32 11, i32 64, metadata !1, null}
+!24 = metadata !{i32 11, i32 81, metadata !1, null}
+!25 = metadata !{i32 11, i32 101, metadata !1, null}
+!26 = metadata !{i32 12, i32 3, metadata !27, null}
+!27 = metadata !{i32 589835, metadata !1, i32 11, i32 107, metadata !2, i32 0} ; [ DW_TAG_lexical_block ]
+!28 = metadata !{i32 13, i32 5, metadata !27, null}
+!29 = metadata !{i32 14, i32 1, metadata !27, null}
diff --git a/test/CodeGen/ARM/debug-info-blocks.ll b/test/CodeGen/ARM/debug-info-blocks.ll
index 519c40e..2c59316 100644
--- a/test/CodeGen/ARM/debug-info-blocks.ll
+++ b/test/CodeGen/ARM/debug-info-blocks.ll
@@ -1,5 +1,5 @@
; RUN: llc -O0 < %s | FileCheck %s
-; CHECK: @DEBUG_VALUE: mydata <- [sp+#8]+#0
+; CHECK: @DEBUG_VALUE: mydata <- [sp+#4]+#0
; Radar 9331779
target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
target triple = "thumbv7-apple-macosx10.7.0"
diff --git a/test/CodeGen/ARM/debug-info-sreg2.ll b/test/CodeGen/ARM/debug-info-sreg2.ll
index 16aeab3..ee777ce 100644
--- a/test/CodeGen/ARM/debug-info-sreg2.ll
+++ b/test/CodeGen/ARM/debug-info-sreg2.ll
@@ -5,9 +5,9 @@ target triple = "thumbv7-apple-macosx10.6.7"
;CHECK: Ldebug_loc0:
;CHECK-NEXT: .long Ltmp1
-;CHECK-NEXT: .long Ltmp3
-;CHECK-NEXT: Lset9 = Ltmp10-Ltmp9 @ Loc expr size
-;CHECK-NEXT: .short Lset9
+;CHECK-NEXT: .long Ltmp2
+;CHECK-NEXT: Lset8 = Ltmp10-Ltmp9 @ Loc expr size
+;CHECK-NEXT: .short Lset8
;CHECK-NEXT: Ltmp9:
;CHECK-NEXT: .byte 144 @ DW_OP_regx for S register
diff --git a/test/CodeGen/ARM/divmod.ll b/test/CodeGen/ARM/divmod.ll
new file mode 100644
index 0000000..49c4103
--- /dev/null
+++ b/test/CodeGen/ARM/divmod.ll
@@ -0,0 +1,58 @@
+; RUN: llc < %s -mtriple=arm-apple-ios5.0 | FileCheck %s
+
+define void @foo(i32 %x, i32 %y, i32* nocapture %P) nounwind ssp {
+entry:
+; CHECK: foo:
+; CHECK: bl ___divmodsi4
+; CHECK-NOT: bl ___divmodsi4
+ %div = sdiv i32 %x, %y
+ store i32 %div, i32* %P, align 4
+ %rem = srem i32 %x, %y
+ %arrayidx6 = getelementptr inbounds i32* %P, i32 1
+ store i32 %rem, i32* %arrayidx6, align 4
+ ret void
+}
+
+define void @bar(i32 %x, i32 %y, i32* nocapture %P) nounwind ssp {
+entry:
+; CHECK: bar:
+; CHECK: bl ___udivmodsi4
+; CHECK-NOT: bl ___udivmodsi4
+ %div = udiv i32 %x, %y
+ store i32 %div, i32* %P, align 4
+ %rem = urem i32 %x, %y
+ %arrayidx6 = getelementptr inbounds i32* %P, i32 1
+ store i32 %rem, i32* %arrayidx6, align 4
+ ret void
+}
+
+; rdar://9280991
+@flags = external unnamed_addr global i32
+@tabsize = external unnamed_addr global i32
+
+define void @do_indent(i32 %cols) nounwind {
+entry:
+; CHECK: do_indent:
+ %0 = load i32* @flags, align 4
+ %1 = and i32 %0, 67108864
+ %2 = icmp eq i32 %1, 0
+ br i1 %2, label %bb1, label %bb
+
+bb:
+; CHECK: bl ___divmodsi4
+ %3 = load i32* @tabsize, align 4
+ %4 = srem i32 %cols, %3
+ %5 = sdiv i32 %cols, %3
+ %6 = tail call i32 @llvm.objectsize.i32(i8* null, i1 false)
+ %7 = tail call i8* @__memset_chk(i8* null, i32 9, i32 %5, i32 %6) nounwind
+ br label %bb1
+
+bb1:
+ %line_indent_len.0 = phi i32 [ %4, %bb ], [ 0, %entry ]
+ %8 = getelementptr inbounds i8* null, i32 %line_indent_len.0
+ store i8 0, i8* %8, align 1
+ ret void
+}
+
+declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readnone
+declare i8* @__memset_chk(i8*, i32, i32, i32) nounwind
diff --git a/test/CodeGen/ARM/elf-lcomm-align.ll b/test/CodeGen/ARM/elf-lcomm-align.ll
new file mode 100644
index 0000000..4679299
--- /dev/null
+++ b/test/CodeGen/ARM/elf-lcomm-align.ll
@@ -0,0 +1,14 @@
+; RUN: llc < %s -mtriple=arm-linux-gnueabi -O0 | FileCheck %s
+; run with -O0 to avoid arm global merging.
+
+@c = internal global i8 0, align 1
+@x = internal global i32 0, align 4
+
+; CHECK: .lcomm c,1
+; .lcomm doesn't support alignment.
+; CHECK: .local x
+; CHECK-NEXT: .comm x,4,4
+
+define i32 @foo() nounwind {
+ ret i32 sub (i32 ptrtoint (i8* @c to i32), i32 ptrtoint (i32* @x to i32))
+}
diff --git a/test/CodeGen/ARM/fabss.ll b/test/CodeGen/ARM/fabss.ll
index 51efe51..45c322d 100644
--- a/test/CodeGen/ARM/fabss.ll
+++ b/test/CodeGen/ARM/fabss.ll
@@ -22,6 +22,8 @@ declare float @fabsf(float)
; NFP0: vabs.f32 s1, s1
; CORTEXA8: test:
-; CORTEXA8: vabs.f32 d1, d1
+; CORTEXA8: vadd.f32 [[D1:d[0-9]+]]
+; CORTEXA8: vabs.f32 {{d[0-9]+}}, [[D1]]
+
; CORTEXA9: test:
; CORTEXA9: vabs.f32 s{{.}}, s{{.}}
diff --git a/test/CodeGen/ARM/fast-isel.ll b/test/CodeGen/ARM/fast-isel.ll
index eb0c5c8..465e85f 100644
--- a/test/CodeGen/ARM/fast-isel.ll
+++ b/test/CodeGen/ARM/fast-isel.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -O0 -fast-isel-abort -mtriple=armv7-apple-darwin | FileCheck %s --check-prefix=ARM
-; RUN: llc < %s -O0 -fast-isel-abort -mtriple=thumbv7-apple-darwin | FileCheck %s --check-prefix=THUMB
+; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=armv7-apple-darwin | FileCheck %s --check-prefix=ARM
+; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-darwin | FileCheck %s --check-prefix=THUMB
; Very basic fast-isel functionality.
define i32 @add(i32 %a, i32 %b) nounwind {
diff --git a/test/CodeGen/ARM/fp_convert.ll b/test/CodeGen/ARM/fp_convert.ll
index 86c06f1..7002cec 100644
--- a/test/CodeGen/ARM/fp_convert.ll
+++ b/test/CodeGen/ARM/fp_convert.ll
@@ -7,7 +7,8 @@ define i32 @test1(float %a, float %b) {
; VFP2: test1:
; VFP2: vcvt.s32.f32 s{{.}}, s{{.}}
; NEON: test1:
-; NEON: vcvt.s32.f32 d0, d0
+; NEON: vadd.f32 [[D0:d[0-9]+]]
+; NEON: vcvt.s32.f32 d0, [[D0]]
entry:
%0 = fadd float %a, %b
%1 = fptosi float %0 to i32
@@ -18,7 +19,8 @@ define i32 @test2(float %a, float %b) {
; VFP2: test2:
; VFP2: vcvt.u32.f32 s{{.}}, s{{.}}
; NEON: test2:
-; NEON: vcvt.u32.f32 d0, d0
+; NEON: vadd.f32 [[D0:d[0-9]+]]
+; NEON: vcvt.u32.f32 d0, [[D0]]
entry:
%0 = fadd float %a, %b
%1 = fptoui float %0 to i32
diff --git a/test/CodeGen/ARM/fpmem.ll b/test/CodeGen/ARM/fpmem.ll
index c3cff18..3833933 100644
--- a/test/CodeGen/ARM/fpmem.ll
+++ b/test/CodeGen/ARM/fpmem.ll
@@ -14,6 +14,24 @@ define float @f2(float* %v, float %u) {
ret float %tmp1
}
+define float @f2offset(float* %v, float %u) {
+; CHECK: f2offset:
+; CHECK: vldr.32{{.*}}, #4]
+ %addr = getelementptr float* %v, i32 1
+ %tmp = load float* %addr
+ %tmp1 = fadd float %tmp, %u
+ ret float %tmp1
+}
+
+define float @f2noffset(float* %v, float %u) {
+; CHECK: f2noffset:
+; CHECK: vldr.32{{.*}}, #-4]
+ %addr = getelementptr float* %v, i32 -1
+ %tmp = load float* %addr
+ %tmp1 = fadd float %tmp, %u
+ ret float %tmp1
+}
+
define void @f3(float %a, float %b, float* %v) {
; CHECK: f3:
; CHECK: vstr.32{{.*}}[
diff --git a/test/CodeGen/ARM/hidden-vis-2.ll b/test/CodeGen/ARM/hidden-vis-2.ll
index 90f5308..8bb2c6e 100644
--- a/test/CodeGen/ARM/hidden-vis-2.ll
+++ b/test/CodeGen/ARM/hidden-vis-2.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -mtriple=arm-apple-darwin | FileCheck %s
+; RUN: llc < %s -relocation-model=dynamic-no-pic -mtriple=arm-apple-darwin | FileCheck %s
@x = weak hidden global i32 0 ; <i32*> [#uses=1]
diff --git a/test/CodeGen/ARM/hidden-vis-3.ll b/test/CodeGen/ARM/hidden-vis-3.ll
index fc8b2fe..3bc3312 100644
--- a/test/CodeGen/ARM/hidden-vis-3.ll
+++ b/test/CodeGen/ARM/hidden-vis-3.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -mtriple=arm-apple-darwin9 | FileCheck %s
+; RUN: llc < %s -relocation-model=dynamic-no-pic -mtriple=arm-apple-darwin9 | FileCheck %s
@x = external hidden global i32 ; <i32*> [#uses=1]
@y = extern_weak hidden global i32 ; <i32*> [#uses=1]
diff --git a/test/CodeGen/ARM/iabs.ll b/test/CodeGen/ARM/iabs.ll
index c01c041..89e309d 100644
--- a/test/CodeGen/ARM/iabs.ll
+++ b/test/CodeGen/ARM/iabs.ll
@@ -1,8 +1,8 @@
; RUN: llc < %s -march=arm -mattr=+v4t | FileCheck %s
;; Integer absolute value, should produce something as good as: ARM:
-;; add r3, r0, r0, asr #31
-;; eor r0, r3, r0, asr #31
+;; movs r0, r0
+;; rsbmi r0, r0, #0
;; bx lr
define i32 @test(i32 %a) {
@@ -10,7 +10,7 @@ define i32 @test(i32 %a) {
%b = icmp sgt i32 %a, -1
%abs = select i1 %b, i32 %a, i32 %tmp1neg
ret i32 %abs
-; CHECK: add r1, r0, r0, asr #31
-; CHECK: eor r0, r1, r0, asr #31
+; CHECK: movs r0, r0
+; CHECK: rsbmi r0, r0, #0
; CHECK: bx lr
}
diff --git a/test/CodeGen/ARM/ifcvt4.ll b/test/CodeGen/ARM/ifcvt4.ll
index f28c61b..d247f14 100644
--- a/test/CodeGen/ARM/ifcvt4.ll
+++ b/test/CodeGen/ARM/ifcvt4.ll
@@ -1,8 +1,10 @@
-; RUN: llc < %s -march=arm
-; RUN: llc < %s -march=arm | grep subgt | count 1
-; RUN: llc < %s -march=arm | grep suble | count 1
-; FIXME: Check for # of unconditional branch after adding branch folding post ifcvt.
+; RUN: llc < %s -march=arm | FileCheck %s
+; Do not if-convert when branches go to the different loops.
+; CHECK: t:
+; CHECK-NOT: subgt
+; CHECK-NOT: suble
+; Don't use
define i32 @t(i32 %a, i32 %b) {
entry:
%tmp1434 = icmp eq i32 %a, %b ; <i1> [#uses=1]
diff --git a/test/CodeGen/ARM/indirectbr.ll b/test/CodeGen/ARM/indirectbr.ll
index 25a0f93..341c33f 100644
--- a/test/CodeGen/ARM/indirectbr.ll
+++ b/test/CodeGen/ARM/indirectbr.ll
@@ -22,7 +22,6 @@ bb2: ; preds = %entry, %bb3
%gotovar.4.0 = phi i8* [ %gotovar.4.0.pre, %bb3 ], [ %0, %entry ] ; <i8*> [#uses=1]
; ARM: bx
; THUMB: mov pc,
-; THUMB2: mov pc,
indirectbr i8* %gotovar.4.0, [label %L5, label %L4, label %L3, label %L2, label %L1]
bb3: ; preds = %entry
diff --git a/test/CodeGen/ARM/inlineasm3.ll b/test/CodeGen/ARM/inlineasm3.ll
index 853585d..cb5243c 100644
--- a/test/CodeGen/ARM/inlineasm3.ll
+++ b/test/CodeGen/ARM/inlineasm3.ll
@@ -98,3 +98,15 @@ entry:
%0 = tail call i32 asm "movw $0, $1", "=r,j"(i32 27182) nounwind
ret i32 %0
}
+
+; Radar 9866494
+
+define void @t10(i8* %f, i32 %g) nounwind {
+entry:
+; CHECK: t10
+; CHECK: str r1, [r0]
+ %f.addr = alloca i8*, align 4
+ store i8* %f, i8** %f.addr, align 4
+ call void asm "str $1, $0", "=*Q,r"(i8** %f.addr, i32 %g) nounwind
+ ret void
+}
diff --git a/test/CodeGen/ARM/inlineasm4.ll b/test/CodeGen/ARM/inlineasm4.ll
new file mode 100644
index 0000000..9ed4b99
--- /dev/null
+++ b/test/CodeGen/ARM/inlineasm4.ll
@@ -0,0 +1,17 @@
+; RUN: llc < %s -march=arm | FileCheck %s
+
+define double @f(double %x) {
+entry:
+ %0 = tail call double asm "mov ${0:R}, #4\0A", "=&r"()
+ ret double %0
+; CHECK: f:
+; CHECK: mov r1, #4
+}
+
+define double @g(double %x) {
+entry:
+ %0 = tail call double asm "mov ${0:Q}, #4\0A", "=&r"()
+ ret double %0
+; CHECK: g:
+; CHECK: mov r0, #4
+}
diff --git a/test/CodeGen/ARM/lsr-on-unrolled-loops.ll b/test/CodeGen/ARM/lsr-on-unrolled-loops.ll
index c1318ec..4737901 100644
--- a/test/CodeGen/ARM/lsr-on-unrolled-loops.ll
+++ b/test/CodeGen/ARM/lsr-on-unrolled-loops.ll
@@ -1,4 +1,4 @@
-; RUN: llc -mtriple=thumbv7-apple-darwin10 -mcpu=cortex-a8 < %s | FileCheck %s
+; RUN: llc -mtriple=thumbv7-apple-darwin10 -mcpu=cortex-a8 -enable-lsr-nested < %s | FileCheck %s
; LSR should recognize that this is an unrolled loop which can use
; constant offset addressing, so that each of the following stores
@@ -8,6 +8,9 @@
; CHECK: vstr.32 s{{.*}}, [{{(r[0-9]+)|(lr)}}, #64]
; CHECK: vstr.32 s{{.*}}, [{{(r[0-9]+)|(lr)}}, #96]
+; We can also save a register in the outer loop, but that requires
+; performing LSR on the outer loop.
+
target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32"
%0 = type { %1*, %3*, %6*, i8*, i32, i32, %8*, i32, i32, i32, i32, i32, i32, i32, double, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i8**, i32, i32, i32, i32, i32, [64 x i32]*, [4 x %9*], [4 x %10*], [4 x %10*], i32, %11*, i32, i32, [16 x i8], [16 x i8], [16 x i8], i32, i32, i8, i8, i8, i16, i16, i32, i8, i32, %12*, i32, i32, i32, i32, i8*, i32, [4 x %11*], i32, i32, i32, [10 x i32], i32, i32, i32, i32, i32, %13*, %14*, %15*, %16*, %17*, %18*, %19*, %20*, %21*, %22*, %23* }
@@ -37,107 +40,107 @@ target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-
define void @test(%0* nocapture %a0, %11* nocapture %a1, i16* nocapture %a2, i8** nocapture %a3, i32 %a4) nounwind {
bb:
- %t = alloca [64 x float], align 4
+ %t = alloca [64 x float], align 4
%t5 = getelementptr inbounds %0* %a0, i32 0, i32 65
- %t6 = load i8** %t5, align 4
+ %t6 = load i8** %t5, align 4
%t7 = getelementptr inbounds %11* %a1, i32 0, i32 20
- %t8 = load i8** %t7, align 4
+ %t8 = load i8** %t7, align 4
br label %bb9
-bb9:
+bb9:
%t10 = phi i32 [ 0, %bb ], [ %t157, %bb156 ]
- %t11 = add i32 %t10, 8
+ %t11 = add i32 %t10, 8
%t12 = getelementptr [64 x float]* %t, i32 0, i32 %t11
- %t13 = add i32 %t10, 16
+ %t13 = add i32 %t10, 16
%t14 = getelementptr [64 x float]* %t, i32 0, i32 %t13
- %t15 = add i32 %t10, 24
+ %t15 = add i32 %t10, 24
%t16 = getelementptr [64 x float]* %t, i32 0, i32 %t15
- %t17 = add i32 %t10, 32
+ %t17 = add i32 %t10, 32
%t18 = getelementptr [64 x float]* %t, i32 0, i32 %t17
- %t19 = add i32 %t10, 40
+ %t19 = add i32 %t10, 40
%t20 = getelementptr [64 x float]* %t, i32 0, i32 %t19
- %t21 = add i32 %t10, 48
+ %t21 = add i32 %t10, 48
%t22 = getelementptr [64 x float]* %t, i32 0, i32 %t21
- %t23 = add i32 %t10, 56
+ %t23 = add i32 %t10, 56
%t24 = getelementptr [64 x float]* %t, i32 0, i32 %t23
%t25 = getelementptr [64 x float]* %t, i32 0, i32 %t10
- %t26 = shl i32 %t10, 5
- %t27 = or i32 %t26, 8
- %t28 = getelementptr i8* %t8, i32 %t27
- %t29 = bitcast i8* %t28 to float*
- %t30 = or i32 %t26, 16
- %t31 = getelementptr i8* %t8, i32 %t30
- %t32 = bitcast i8* %t31 to float*
- %t33 = or i32 %t26, 24
- %t34 = getelementptr i8* %t8, i32 %t33
- %t35 = bitcast i8* %t34 to float*
- %t36 = or i32 %t26, 4
- %t37 = getelementptr i8* %t8, i32 %t36
- %t38 = bitcast i8* %t37 to float*
- %t39 = or i32 %t26, 12
- %t40 = getelementptr i8* %t8, i32 %t39
- %t41 = bitcast i8* %t40 to float*
- %t42 = or i32 %t26, 20
- %t43 = getelementptr i8* %t8, i32 %t42
- %t44 = bitcast i8* %t43 to float*
- %t45 = or i32 %t26, 28
- %t46 = getelementptr i8* %t8, i32 %t45
- %t47 = bitcast i8* %t46 to float*
- %t48 = getelementptr i8* %t8, i32 %t26
- %t49 = bitcast i8* %t48 to float*
- %t50 = shl i32 %t10, 3
- %t51 = or i32 %t50, 1
- %t52 = getelementptr i16* %a2, i32 %t51
- %t53 = or i32 %t50, 2
- %t54 = getelementptr i16* %a2, i32 %t53
- %t55 = or i32 %t50, 3
- %t56 = getelementptr i16* %a2, i32 %t55
- %t57 = or i32 %t50, 4
- %t58 = getelementptr i16* %a2, i32 %t57
- %t59 = or i32 %t50, 5
- %t60 = getelementptr i16* %a2, i32 %t59
- %t61 = or i32 %t50, 6
- %t62 = getelementptr i16* %a2, i32 %t61
- %t63 = or i32 %t50, 7
- %t64 = getelementptr i16* %a2, i32 %t63
- %t65 = getelementptr i16* %a2, i32 %t50
- %t66 = load i16* %t52, align 2
- %t67 = icmp eq i16 %t66, 0
- %t68 = load i16* %t54, align 2
- %t69 = icmp eq i16 %t68, 0
- %t70 = and i1 %t67, %t69
+ %t26 = shl i32 %t10, 5
+ %t27 = or i32 %t26, 8
+ %t28 = getelementptr i8* %t8, i32 %t27
+ %t29 = bitcast i8* %t28 to float*
+ %t30 = or i32 %t26, 16
+ %t31 = getelementptr i8* %t8, i32 %t30
+ %t32 = bitcast i8* %t31 to float*
+ %t33 = or i32 %t26, 24
+ %t34 = getelementptr i8* %t8, i32 %t33
+ %t35 = bitcast i8* %t34 to float*
+ %t36 = or i32 %t26, 4
+ %t37 = getelementptr i8* %t8, i32 %t36
+ %t38 = bitcast i8* %t37 to float*
+ %t39 = or i32 %t26, 12
+ %t40 = getelementptr i8* %t8, i32 %t39
+ %t41 = bitcast i8* %t40 to float*
+ %t42 = or i32 %t26, 20
+ %t43 = getelementptr i8* %t8, i32 %t42
+ %t44 = bitcast i8* %t43 to float*
+ %t45 = or i32 %t26, 28
+ %t46 = getelementptr i8* %t8, i32 %t45
+ %t47 = bitcast i8* %t46 to float*
+ %t48 = getelementptr i8* %t8, i32 %t26
+ %t49 = bitcast i8* %t48 to float*
+ %t50 = shl i32 %t10, 3
+ %t51 = or i32 %t50, 1
+ %t52 = getelementptr i16* %a2, i32 %t51
+ %t53 = or i32 %t50, 2
+ %t54 = getelementptr i16* %a2, i32 %t53
+ %t55 = or i32 %t50, 3
+ %t56 = getelementptr i16* %a2, i32 %t55
+ %t57 = or i32 %t50, 4
+ %t58 = getelementptr i16* %a2, i32 %t57
+ %t59 = or i32 %t50, 5
+ %t60 = getelementptr i16* %a2, i32 %t59
+ %t61 = or i32 %t50, 6
+ %t62 = getelementptr i16* %a2, i32 %t61
+ %t63 = or i32 %t50, 7
+ %t64 = getelementptr i16* %a2, i32 %t63
+ %t65 = getelementptr i16* %a2, i32 %t50
+ %t66 = load i16* %t52, align 2
+ %t67 = icmp eq i16 %t66, 0
+ %t68 = load i16* %t54, align 2
+ %t69 = icmp eq i16 %t68, 0
+ %t70 = and i1 %t67, %t69
br i1 %t70, label %bb71, label %bb91
-bb71:
- %t72 = load i16* %t56, align 2
- %t73 = icmp eq i16 %t72, 0
+bb71:
+ %t72 = load i16* %t56, align 2
+ %t73 = icmp eq i16 %t72, 0
br i1 %t73, label %bb74, label %bb91
-bb74:
- %t75 = load i16* %t58, align 2
- %t76 = icmp eq i16 %t75, 0
+bb74:
+ %t75 = load i16* %t58, align 2
+ %t76 = icmp eq i16 %t75, 0
br i1 %t76, label %bb77, label %bb91
-bb77:
- %t78 = load i16* %t60, align 2
- %t79 = icmp eq i16 %t78, 0
+bb77:
+ %t78 = load i16* %t60, align 2
+ %t79 = icmp eq i16 %t78, 0
br i1 %t79, label %bb80, label %bb91
-bb80:
- %t81 = load i16* %t62, align 2
- %t82 = icmp eq i16 %t81, 0
+bb80:
+ %t81 = load i16* %t62, align 2
+ %t82 = icmp eq i16 %t81, 0
br i1 %t82, label %bb83, label %bb91
-bb83:
- %t84 = load i16* %t64, align 2
- %t85 = icmp eq i16 %t84, 0
+bb83:
+ %t84 = load i16* %t64, align 2
+ %t85 = icmp eq i16 %t84, 0
br i1 %t85, label %bb86, label %bb91
-bb86:
- %t87 = load i16* %t65, align 2
- %t88 = sitofp i16 %t87 to float
- %t89 = load float* %t49, align 4
- %t90 = fmul float %t88, %t89
+bb86:
+ %t87 = load i16* %t65, align 2
+ %t88 = sitofp i16 %t87 to float
+ %t89 = load float* %t49, align 4
+ %t90 = fmul float %t88, %t89
store float %t90, float* %t25, align 4
store float %t90, float* %t12, align 4
store float %t90, float* %t14, align 4
@@ -148,235 +151,235 @@ bb86:
store float %t90, float* %t24, align 4
br label %bb156
-bb91:
- %t92 = load i16* %t65, align 2
- %t93 = sitofp i16 %t92 to float
- %t94 = load float* %t49, align 4
- %t95 = fmul float %t93, %t94
- %t96 = sitofp i16 %t68 to float
- %t97 = load float* %t29, align 4
- %t98 = fmul float %t96, %t97
- %t99 = load i16* %t58, align 2
- %t100 = sitofp i16 %t99 to float
- %t101 = load float* %t32, align 4
- %t102 = fmul float %t100, %t101
- %t103 = load i16* %t62, align 2
- %t104 = sitofp i16 %t103 to float
- %t105 = load float* %t35, align 4
- %t106 = fmul float %t104, %t105
- %t107 = fadd float %t95, %t102
- %t108 = fsub float %t95, %t102
- %t109 = fadd float %t98, %t106
- %t110 = fsub float %t98, %t106
+bb91:
+ %t92 = load i16* %t65, align 2
+ %t93 = sitofp i16 %t92 to float
+ %t94 = load float* %t49, align 4
+ %t95 = fmul float %t93, %t94
+ %t96 = sitofp i16 %t68 to float
+ %t97 = load float* %t29, align 4
+ %t98 = fmul float %t96, %t97
+ %t99 = load i16* %t58, align 2
+ %t100 = sitofp i16 %t99 to float
+ %t101 = load float* %t32, align 4
+ %t102 = fmul float %t100, %t101
+ %t103 = load i16* %t62, align 2
+ %t104 = sitofp i16 %t103 to float
+ %t105 = load float* %t35, align 4
+ %t106 = fmul float %t104, %t105
+ %t107 = fadd float %t95, %t102
+ %t108 = fsub float %t95, %t102
+ %t109 = fadd float %t98, %t106
+ %t110 = fsub float %t98, %t106
%t111 = fmul float %t110, 0x3FF6A09E60000000
- %t112 = fsub float %t111, %t109
- %t113 = fadd float %t107, %t109
- %t114 = fsub float %t107, %t109
- %t115 = fadd float %t108, %t112
- %t116 = fsub float %t108, %t112
- %t117 = sitofp i16 %t66 to float
- %t118 = load float* %t38, align 4
- %t119 = fmul float %t117, %t118
- %t120 = load i16* %t56, align 2
- %t121 = sitofp i16 %t120 to float
- %t122 = load float* %t41, align 4
- %t123 = fmul float %t121, %t122
- %t124 = load i16* %t60, align 2
- %t125 = sitofp i16 %t124 to float
- %t126 = load float* %t44, align 4
- %t127 = fmul float %t125, %t126
- %t128 = load i16* %t64, align 2
- %t129 = sitofp i16 %t128 to float
- %t130 = load float* %t47, align 4
- %t131 = fmul float %t129, %t130
- %t132 = fadd float %t127, %t123
- %t133 = fsub float %t127, %t123
- %t134 = fadd float %t119, %t131
- %t135 = fsub float %t119, %t131
- %t136 = fadd float %t134, %t132
- %t137 = fsub float %t134, %t132
+ %t112 = fsub float %t111, %t109
+ %t113 = fadd float %t107, %t109
+ %t114 = fsub float %t107, %t109
+ %t115 = fadd float %t108, %t112
+ %t116 = fsub float %t108, %t112
+ %t117 = sitofp i16 %t66 to float
+ %t118 = load float* %t38, align 4
+ %t119 = fmul float %t117, %t118
+ %t120 = load i16* %t56, align 2
+ %t121 = sitofp i16 %t120 to float
+ %t122 = load float* %t41, align 4
+ %t123 = fmul float %t121, %t122
+ %t124 = load i16* %t60, align 2
+ %t125 = sitofp i16 %t124 to float
+ %t126 = load float* %t44, align 4
+ %t127 = fmul float %t125, %t126
+ %t128 = load i16* %t64, align 2
+ %t129 = sitofp i16 %t128 to float
+ %t130 = load float* %t47, align 4
+ %t131 = fmul float %t129, %t130
+ %t132 = fadd float %t127, %t123
+ %t133 = fsub float %t127, %t123
+ %t134 = fadd float %t119, %t131
+ %t135 = fsub float %t119, %t131
+ %t136 = fadd float %t134, %t132
+ %t137 = fsub float %t134, %t132
%t138 = fmul float %t137, 0x3FF6A09E60000000
- %t139 = fadd float %t133, %t135
+ %t139 = fadd float %t133, %t135
%t140 = fmul float %t139, 0x3FFD906BC0000000
%t141 = fmul float %t135, 0x3FF1517A80000000
- %t142 = fsub float %t141, %t140
+ %t142 = fsub float %t141, %t140
%t143 = fmul float %t133, 0xC004E7AEA0000000
- %t144 = fadd float %t143, %t140
- %t145 = fsub float %t144, %t136
- %t146 = fsub float %t138, %t145
- %t147 = fadd float %t142, %t146
- %t148 = fadd float %t113, %t136
+ %t144 = fadd float %t143, %t140
+ %t145 = fsub float %t144, %t136
+ %t146 = fsub float %t138, %t145
+ %t147 = fadd float %t142, %t146
+ %t148 = fadd float %t113, %t136
store float %t148, float* %t25, align 4
- %t149 = fsub float %t113, %t136
+ %t149 = fsub float %t113, %t136
store float %t149, float* %t24, align 4
- %t150 = fadd float %t115, %t145
+ %t150 = fadd float %t115, %t145
store float %t150, float* %t12, align 4
- %t151 = fsub float %t115, %t145
+ %t151 = fsub float %t115, %t145
store float %t151, float* %t22, align 4
- %t152 = fadd float %t116, %t146
+ %t152 = fadd float %t116, %t146
store float %t152, float* %t14, align 4
- %t153 = fsub float %t116, %t146
+ %t153 = fsub float %t116, %t146
store float %t153, float* %t20, align 4
- %t154 = fadd float %t114, %t147
+ %t154 = fadd float %t114, %t147
store float %t154, float* %t18, align 4
- %t155 = fsub float %t114, %t147
+ %t155 = fsub float %t114, %t147
store float %t155, float* %t16, align 4
br label %bb156
-bb156:
- %t157 = add i32 %t10, 1
- %t158 = icmp eq i32 %t157, 8
+bb156:
+ %t157 = add i32 %t10, 1
+ %t158 = icmp eq i32 %t157, 8
br i1 %t158, label %bb159, label %bb9
-bb159:
- %t160 = add i32 %a4, 7
- %t161 = add i32 %a4, 1
- %t162 = add i32 %a4, 6
- %t163 = add i32 %a4, 2
- %t164 = add i32 %a4, 5
- %t165 = add i32 %a4, 4
- %t166 = add i32 %a4, 3
+bb159:
+ %t160 = add i32 %a4, 7
+ %t161 = add i32 %a4, 1
+ %t162 = add i32 %a4, 6
+ %t163 = add i32 %a4, 2
+ %t164 = add i32 %a4, 5
+ %t165 = add i32 %a4, 4
+ %t166 = add i32 %a4, 3
br label %bb167
-bb167:
+bb167:
%t168 = phi i32 [ 0, %bb159 ], [ %t293, %bb167 ]
%t169 = getelementptr i8** %a3, i32 %t168
- %t170 = shl i32 %t168, 3
- %t171 = or i32 %t170, 4
+ %t170 = shl i32 %t168, 3
+ %t171 = or i32 %t170, 4
%t172 = getelementptr [64 x float]* %t, i32 0, i32 %t171
- %t173 = or i32 %t170, 2
+ %t173 = or i32 %t170, 2
%t174 = getelementptr [64 x float]* %t, i32 0, i32 %t173
- %t175 = or i32 %t170, 6
+ %t175 = or i32 %t170, 6
%t176 = getelementptr [64 x float]* %t, i32 0, i32 %t175
- %t177 = or i32 %t170, 5
+ %t177 = or i32 %t170, 5
%t178 = getelementptr [64 x float]* %t, i32 0, i32 %t177
- %t179 = or i32 %t170, 3
+ %t179 = or i32 %t170, 3
%t180 = getelementptr [64 x float]* %t, i32 0, i32 %t179
- %t181 = or i32 %t170, 1
+ %t181 = or i32 %t170, 1
%t182 = getelementptr [64 x float]* %t, i32 0, i32 %t181
- %t183 = or i32 %t170, 7
+ %t183 = or i32 %t170, 7
%t184 = getelementptr [64 x float]* %t, i32 0, i32 %t183
%t185 = getelementptr [64 x float]* %t, i32 0, i32 %t170
- %t186 = load i8** %t169, align 4
+ %t186 = load i8** %t169, align 4
%t187 = getelementptr inbounds i8* %t186, i32 %a4
- %t188 = load float* %t185, align 4
- %t189 = load float* %t172, align 4
- %t190 = fadd float %t188, %t189
- %t191 = fsub float %t188, %t189
- %t192 = load float* %t174, align 4
- %t193 = load float* %t176, align 4
- %t194 = fadd float %t192, %t193
- %t195 = fsub float %t192, %t193
+ %t188 = load float* %t185, align 4
+ %t189 = load float* %t172, align 4
+ %t190 = fadd float %t188, %t189
+ %t191 = fsub float %t188, %t189
+ %t192 = load float* %t174, align 4
+ %t193 = load float* %t176, align 4
+ %t194 = fadd float %t192, %t193
+ %t195 = fsub float %t192, %t193
%t196 = fmul float %t195, 0x3FF6A09E60000000
- %t197 = fsub float %t196, %t194
- %t198 = fadd float %t190, %t194
- %t199 = fsub float %t190, %t194
- %t200 = fadd float %t191, %t197
- %t201 = fsub float %t191, %t197
- %t202 = load float* %t178, align 4
- %t203 = load float* %t180, align 4
- %t204 = fadd float %t202, %t203
- %t205 = fsub float %t202, %t203
- %t206 = load float* %t182, align 4
- %t207 = load float* %t184, align 4
- %t208 = fadd float %t206, %t207
- %t209 = fsub float %t206, %t207
- %t210 = fadd float %t208, %t204
- %t211 = fsub float %t208, %t204
+ %t197 = fsub float %t196, %t194
+ %t198 = fadd float %t190, %t194
+ %t199 = fsub float %t190, %t194
+ %t200 = fadd float %t191, %t197
+ %t201 = fsub float %t191, %t197
+ %t202 = load float* %t178, align 4
+ %t203 = load float* %t180, align 4
+ %t204 = fadd float %t202, %t203
+ %t205 = fsub float %t202, %t203
+ %t206 = load float* %t182, align 4
+ %t207 = load float* %t184, align 4
+ %t208 = fadd float %t206, %t207
+ %t209 = fsub float %t206, %t207
+ %t210 = fadd float %t208, %t204
+ %t211 = fsub float %t208, %t204
%t212 = fmul float %t211, 0x3FF6A09E60000000
- %t213 = fadd float %t205, %t209
+ %t213 = fadd float %t205, %t209
%t214 = fmul float %t213, 0x3FFD906BC0000000
%t215 = fmul float %t209, 0x3FF1517A80000000
- %t216 = fsub float %t215, %t214
+ %t216 = fsub float %t215, %t214
%t217 = fmul float %t205, 0xC004E7AEA0000000
- %t218 = fadd float %t217, %t214
- %t219 = fsub float %t218, %t210
- %t220 = fsub float %t212, %t219
- %t221 = fadd float %t216, %t220
- %t222 = fadd float %t198, %t210
- %t223 = fptosi float %t222 to i32
- %t224 = add nsw i32 %t223, 4
- %t225 = lshr i32 %t224, 3
- %t226 = and i32 %t225, 1023
- %t227 = add i32 %t226, 128
+ %t218 = fadd float %t217, %t214
+ %t219 = fsub float %t218, %t210
+ %t220 = fsub float %t212, %t219
+ %t221 = fadd float %t216, %t220
+ %t222 = fadd float %t198, %t210
+ %t223 = fptosi float %t222 to i32
+ %t224 = add nsw i32 %t223, 4
+ %t225 = lshr i32 %t224, 3
+ %t226 = and i32 %t225, 1023
+ %t227 = add i32 %t226, 128
%t228 = getelementptr inbounds i8* %t6, i32 %t227
- %t229 = load i8* %t228, align 1
+ %t229 = load i8* %t228, align 1
store i8 %t229, i8* %t187, align 1
- %t230 = fsub float %t198, %t210
- %t231 = fptosi float %t230 to i32
- %t232 = add nsw i32 %t231, 4
- %t233 = lshr i32 %t232, 3
- %t234 = and i32 %t233, 1023
- %t235 = add i32 %t234, 128
+ %t230 = fsub float %t198, %t210
+ %t231 = fptosi float %t230 to i32
+ %t232 = add nsw i32 %t231, 4
+ %t233 = lshr i32 %t232, 3
+ %t234 = and i32 %t233, 1023
+ %t235 = add i32 %t234, 128
%t236 = getelementptr inbounds i8* %t6, i32 %t235
- %t237 = load i8* %t236, align 1
+ %t237 = load i8* %t236, align 1
%t238 = getelementptr inbounds i8* %t186, i32 %t160
store i8 %t237, i8* %t238, align 1
- %t239 = fadd float %t200, %t219
- %t240 = fptosi float %t239 to i32
- %t241 = add nsw i32 %t240, 4
- %t242 = lshr i32 %t241, 3
- %t243 = and i32 %t242, 1023
- %t244 = add i32 %t243, 128
+ %t239 = fadd float %t200, %t219
+ %t240 = fptosi float %t239 to i32
+ %t241 = add nsw i32 %t240, 4
+ %t242 = lshr i32 %t241, 3
+ %t243 = and i32 %t242, 1023
+ %t244 = add i32 %t243, 128
%t245 = getelementptr inbounds i8* %t6, i32 %t244
- %t246 = load i8* %t245, align 1
+ %t246 = load i8* %t245, align 1
%t247 = getelementptr inbounds i8* %t186, i32 %t161
store i8 %t246, i8* %t247, align 1
- %t248 = fsub float %t200, %t219
- %t249 = fptosi float %t248 to i32
- %t250 = add nsw i32 %t249, 4
- %t251 = lshr i32 %t250, 3
- %t252 = and i32 %t251, 1023
- %t253 = add i32 %t252, 128
+ %t248 = fsub float %t200, %t219
+ %t249 = fptosi float %t248 to i32
+ %t250 = add nsw i32 %t249, 4
+ %t251 = lshr i32 %t250, 3
+ %t252 = and i32 %t251, 1023
+ %t253 = add i32 %t252, 128
%t254 = getelementptr inbounds i8* %t6, i32 %t253
- %t255 = load i8* %t254, align 1
+ %t255 = load i8* %t254, align 1
%t256 = getelementptr inbounds i8* %t186, i32 %t162
store i8 %t255, i8* %t256, align 1
- %t257 = fadd float %t201, %t220
- %t258 = fptosi float %t257 to i32
- %t259 = add nsw i32 %t258, 4
- %t260 = lshr i32 %t259, 3
- %t261 = and i32 %t260, 1023
- %t262 = add i32 %t261, 128
+ %t257 = fadd float %t201, %t220
+ %t258 = fptosi float %t257 to i32
+ %t259 = add nsw i32 %t258, 4
+ %t260 = lshr i32 %t259, 3
+ %t261 = and i32 %t260, 1023
+ %t262 = add i32 %t261, 128
%t263 = getelementptr inbounds i8* %t6, i32 %t262
- %t264 = load i8* %t263, align 1
+ %t264 = load i8* %t263, align 1
%t265 = getelementptr inbounds i8* %t186, i32 %t163
store i8 %t264, i8* %t265, align 1
- %t266 = fsub float %t201, %t220
- %t267 = fptosi float %t266 to i32
- %t268 = add nsw i32 %t267, 4
- %t269 = lshr i32 %t268, 3
- %t270 = and i32 %t269, 1023
- %t271 = add i32 %t270, 128
+ %t266 = fsub float %t201, %t220
+ %t267 = fptosi float %t266 to i32
+ %t268 = add nsw i32 %t267, 4
+ %t269 = lshr i32 %t268, 3
+ %t270 = and i32 %t269, 1023
+ %t271 = add i32 %t270, 128
%t272 = getelementptr inbounds i8* %t6, i32 %t271
- %t273 = load i8* %t272, align 1
+ %t273 = load i8* %t272, align 1
%t274 = getelementptr inbounds i8* %t186, i32 %t164
store i8 %t273, i8* %t274, align 1
- %t275 = fadd float %t199, %t221
- %t276 = fptosi float %t275 to i32
- %t277 = add nsw i32 %t276, 4
- %t278 = lshr i32 %t277, 3
- %t279 = and i32 %t278, 1023
- %t280 = add i32 %t279, 128
+ %t275 = fadd float %t199, %t221
+ %t276 = fptosi float %t275 to i32
+ %t277 = add nsw i32 %t276, 4
+ %t278 = lshr i32 %t277, 3
+ %t279 = and i32 %t278, 1023
+ %t280 = add i32 %t279, 128
%t281 = getelementptr inbounds i8* %t6, i32 %t280
- %t282 = load i8* %t281, align 1
+ %t282 = load i8* %t281, align 1
%t283 = getelementptr inbounds i8* %t186, i32 %t165
store i8 %t282, i8* %t283, align 1
- %t284 = fsub float %t199, %t221
- %t285 = fptosi float %t284 to i32
- %t286 = add nsw i32 %t285, 4
- %t287 = lshr i32 %t286, 3
- %t288 = and i32 %t287, 1023
- %t289 = add i32 %t288, 128
+ %t284 = fsub float %t199, %t221
+ %t285 = fptosi float %t284 to i32
+ %t286 = add nsw i32 %t285, 4
+ %t287 = lshr i32 %t286, 3
+ %t288 = and i32 %t287, 1023
+ %t289 = add i32 %t288, 128
%t290 = getelementptr inbounds i8* %t6, i32 %t289
- %t291 = load i8* %t290, align 1
+ %t291 = load i8* %t290, align 1
%t292 = getelementptr inbounds i8* %t186, i32 %t166
store i8 %t291, i8* %t292, align 1
- %t293 = add nsw i32 %t168, 1
- %t294 = icmp eq i32 %t293, 8
+ %t293 = add nsw i32 %t168, 1
+ %t294 = icmp eq i32 %t293, 8
br i1 %t294, label %bb295, label %bb167
-bb295:
+bb295:
ret void
}
diff --git a/test/CodeGen/ARM/lsr-unfolded-offset.ll b/test/CodeGen/ARM/lsr-unfolded-offset.ll
index 61b25bb..bf26a96 100644
--- a/test/CodeGen/ARM/lsr-unfolded-offset.ll
+++ b/test/CodeGen/ARM/lsr-unfolded-offset.ll
@@ -4,12 +4,11 @@
; register pressure and therefore spilling. There is more room for improvement
; here.
-; CHECK: sub sp, #{{32|28|24}}
+; CHECK: sub sp, #{{40|32|28|24}}
; CHECK: %for.inc
; CHECK: ldr{{(.w)?}} r{{.*}}, [sp, #
; CHECK: ldr{{(.w)?}} r{{.*}}, [sp, #
-; CHECK: ldr{{(.w)?}} r{{.*}}, [sp, #
; CHECK: add
target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
diff --git a/test/CodeGen/ARM/mulhi.ll b/test/CodeGen/ARM/mulhi.ll
index 148f291..932004c 100644
--- a/test/CodeGen/ARM/mulhi.ll
+++ b/test/CodeGen/ARM/mulhi.ll
@@ -1,9 +1,16 @@
-; RUN: llc < %s -march=arm -mattr=+v6
-; RUN: llc < %s -march=arm -mattr=+v6 | \
-; RUN: grep smmul | count 1
-; RUN: llc < %s -march=arm | grep umull | count 1
+; RUN: llc < %s -march=arm -mattr=+v6 | FileCheck %s -check-prefix=V6
+; RUN: llc < %s -march=arm | FileCheck %s -check-prefix=V4
+; RUN: llc < %s -march=thumb -mcpu=cortex-m3 | FileCheck %s -check-prefix=M3
-define i32 @smulhi(i32 %x, i32 %y) {
+define i32 @smulhi(i32 %x, i32 %y) nounwind {
+; V6: smulhi:
+; V6: smmul
+
+; V4: smulhi:
+; V4: smull
+
+; M3: smulhi:
+; M3: smull
%tmp = sext i32 %x to i64 ; <i64> [#uses=1]
%tmp1 = sext i32 %y to i64 ; <i64> [#uses=1]
%tmp2 = mul i64 %tmp1, %tmp ; <i64> [#uses=1]
@@ -12,7 +19,15 @@ define i32 @smulhi(i32 %x, i32 %y) {
ret i32 %tmp3.upgrd.1
}
-define i32 @umulhi(i32 %x, i32 %y) {
+define i32 @umulhi(i32 %x, i32 %y) nounwind {
+; V6: umulhi:
+; V6: umull
+
+; V4: umulhi:
+; V4: umull
+
+; M3: umulhi:
+; M3: umull
%tmp = zext i32 %x to i64 ; <i64> [#uses=1]
%tmp1 = zext i32 %y to i64 ; <i64> [#uses=1]
%tmp2 = mul i64 %tmp1, %tmp ; <i64> [#uses=1]
@@ -20,3 +35,20 @@ define i32 @umulhi(i32 %x, i32 %y) {
%tmp3.upgrd.2 = trunc i64 %tmp3 to i32 ; <i32> [#uses=1]
ret i32 %tmp3.upgrd.2
}
+
+; rdar://r10152911
+define i32 @t3(i32 %a) nounwind {
+; V6: t3:
+; V6: smmla
+
+; V4: t3:
+; V4: smull
+
+; M3: t3:
+; M3-NOT: smmla
+; M3: smull
+entry:
+ %tmp1 = mul nsw i32 %a, 3
+ %tmp2 = sdiv i32 %tmp1, 23
+ ret i32 %tmp2
+}
diff --git a/test/CodeGen/ARM/select.ll b/test/CodeGen/ARM/select.ll
index d1493ee..f1bd7ee 100644
--- a/test/CodeGen/ARM/select.ll
+++ b/test/CodeGen/ARM/select.ll
@@ -76,12 +76,12 @@ define double @f7(double %a, double %b) {
; block generated, odds are good that we have close to the ideal code for this:
;
; CHECK-NEON: _f8:
-; CHECK-NEON: movw [[REGISTER_1:r[0-9]+]], #1123
-; CHECK-NEON-NEXT: movs [[REGISTER_2:r[0-9]+]], #0
-; CHECK-NEON-NEXT: cmp r0, [[REGISTER_1]]
-; CHECK-NEON-NEXT: it eq
-; CHECK-NEON-NEXT: moveq [[REGISTER_2]], #4
-; CHECK-NEON-NEXT: adr [[REGISTER_3:r[0-9]+]], #LCPI
+; CHECK-NEON: adr r2, LCPI7_0
+; CHECK-NEON-NEXT: movw r3, #1123
+; CHECK-NEON-NEXT: adds r1, r2, #4
+; CHECK-NEON-NEXT: cmp r0, r3
+; CHECK-NEON-NEXT: it ne
+; CHECK-NEON-NEXT: movne r1, r2
; CHECK-NEON-NEXT: ldr
; CHECK-NEON: bx
diff --git a/test/CodeGen/ARM/shifter_operand.ll b/test/CodeGen/ARM/shifter_operand.ll
index f0e2d10..964cef0 100644
--- a/test/CodeGen/ARM/shifter_operand.ll
+++ b/test/CodeGen/ARM/shifter_operand.ll
@@ -54,13 +54,12 @@ declare i8* @malloc(...)
define fastcc void @test4(i16 %addr) nounwind {
entry:
; A8: test4:
-; A8: ldr r2, [r0, r1, lsl #2]
-; A8: str r2, [r0, r1, lsl #2]
+; A8: ldr [[REG:r[0-9]+]], [r0, r1, lsl #2]
+; A8: str [[REG]], [r0, r1, lsl #2]
; A9: test4:
-; A9: add r0, r0, r{{[0-9]+}}, lsl #2
-; A9: ldr r1, [r0]
-; A9: str r1, [r0]
+; A9: ldr [[REG:r[0-9]+]], [r0, r1, lsl #2]
+; A9: str [[REG]], [r0, r1, lsl #2]
%0 = tail call i8* (...)* @malloc(i32 undef) nounwind
%1 = bitcast i8* %0 to i32*
%2 = sext i16 %addr to i32
diff --git a/test/CodeGen/ARM/str_pre-2.ll b/test/CodeGen/ARM/str_pre-2.ll
index b24f75a..f4e3a44 100644
--- a/test/CodeGen/ARM/str_pre-2.ll
+++ b/test/CodeGen/ARM/str_pre-2.ll
@@ -7,8 +7,8 @@
define i64 @t(i64 %a) nounwind readonly {
entry:
-; CHECK: str lr, [sp, #-4]!
-; CHECK: ldr lr, [sp], #4
+; CHECK: push {lr}
+; CHECK: pop {lr}
%0 = load i64** @b, align 4
%1 = load i64* %0, align 4
%2 = mul i64 %1, %a
diff --git a/test/CodeGen/ARM/subreg-remat.ll b/test/CodeGen/ARM/subreg-remat.ll
new file mode 100644
index 0000000..993d7ec
--- /dev/null
+++ b/test/CodeGen/ARM/subreg-remat.ll
@@ -0,0 +1,52 @@
+; RUN: llc < %s -relocation-model=pic -disable-fp-elim -mcpu=cortex-a8 -pre-RA-sched=source | FileCheck %s
+target triple = "thumbv7-apple-ios"
+; <rdar://problem/10032939>
+;
+; The vector %v2 is built like this:
+;
+; %vreg6:ssub_1<def> = VMOVSR %vreg0<kill>, pred:14, pred:%noreg, %vreg6<imp-def>; DPR_VFP2:%vreg6 GPR:%vreg0
+; %vreg6:ssub_0<def> = VLDRS <cp#0>, 0, pred:14, pred:%noreg; mem:LD4[ConstantPool] DPR_VFP2:%vreg6
+;
+; When %vreg6 spills, the VLDRS constant pool load cannot be rematerialized
+; since it implicitly reads the ssub_1 sub-register.
+;
+; CHECK: f1
+; CHECK: vmov s1, r0
+; CHECK: vldr.32 s0, LCPI
+; The vector must be spilled:
+; CHECK: vstr.64 d0,
+; CHECK: asm clobber d0
+; And reloaded after the asm:
+; CHECK: vldr.64 [[D16:d[0-9]+]],
+; CHECK: vstr.64 [[D16]], [r1]
+define void @f1(float %x, <2 x float>* %p) {
+ %v1 = insertelement <2 x float> undef, float %x, i32 1
+ %v2 = insertelement <2 x float> %v1, float 0x400921FB60000000, i32 0
+ %y = call double asm sideeffect "asm clobber $0", "=w,0,~{d1},~{d2},~{d3},~{d4},~{d5},~{d6},~{d7},~{d8},~{d9},~{d10},~{d11},~{d12},~{d13},~{d14},~{d15},~{d16},~{d17},~{d18},~{d19},~{d20},~{d21},~{d22},~{d23},~{d24},~{d25},~{d26},~{d27},~{d28},~{d29},~{d30},~{d31}"(<2 x float> %v2) nounwind
+ store <2 x float> %v2, <2 x float>* %p, align 8
+ ret void
+}
+
+; On the other hand, when the partial redef doesn't read the full register
+; because the bits are undef, we should rematerialize. The vector is now built
+; like this:
+;
+; %vreg2:ssub_0<def> = VLDRS <cp#0>, 0, pred:14, pred:%noreg, %vreg2<imp-def>; mem:LD4[ConstantPool]
+;
+; The extra <imp-def> operand indicates that the instruction fully defines the
+; virtual register. It doesn't read the old value.
+;
+; CHECK: f2
+; CHECK: vldr.32 s0, LCPI
+; The vector must not be spilled:
+; CHECK-NOT: vstr.64
+; CHECK: asm clobber d0
+; But instead rematerialize after the asm:
+; CHECK: vldr.32 [[S0:s[0-9]+]], LCPI
+; CHECK: vstr.64 [[D0:d[0-9]+]], [r0]
+define void @f2(<2 x float>* %p) {
+ %v2 = insertelement <2 x float> undef, float 0x400921FB60000000, i32 0
+ %y = call double asm sideeffect "asm clobber $0", "=w,0,~{d1},~{d2},~{d3},~{d4},~{d5},~{d6},~{d7},~{d8},~{d9},~{d10},~{d11},~{d12},~{d13},~{d14},~{d15},~{d16},~{d17},~{d18},~{d19},~{d20},~{d21},~{d22},~{d23},~{d24},~{d25},~{d26},~{d27},~{d28},~{d29},~{d30},~{d31}"(<2 x float> %v2) nounwind
+ store <2 x float> %v2, <2 x float>* %p, align 8
+ ret void
+}
diff --git a/test/CodeGen/ARM/sxt_rot.ll b/test/CodeGen/ARM/sxt_rot.ll
index 355fee3..656cd93 100644
--- a/test/CodeGen/ARM/sxt_rot.ll
+++ b/test/CodeGen/ARM/sxt_rot.ll
@@ -1,29 +1,30 @@
-; RUN: llc < %s -march=arm -mattr=+v6 | \
-; RUN: grep sxtb | count 2
-; RUN: llc < %s -march=arm -mattr=+v6 | \
-; RUN: grep sxtb | grep ror | count 1
-; RUN: llc < %s -march=arm -mattr=+v6 | \
-; RUN: grep sxtab | count 1
+; RUN: llc < %s -march=arm -mattr=+v6 | FileCheck %s
define i32 @test0(i8 %A) {
- %B = sext i8 %A to i32
- ret i32 %B
+; CHECK: test0
+; CHECK: sxtb r0, r0
+ %B = sext i8 %A to i32
+ ret i32 %B
}
define signext i8 @test1(i32 %A) {
- %B = lshr i32 %A, 8
- %C = shl i32 %A, 24
- %D = or i32 %B, %C
- %E = trunc i32 %D to i8
- ret i8 %E
+; CHECK: test1
+; CHECK: sxtb r0, r0, ror #8
+ %B = lshr i32 %A, 8
+ %C = shl i32 %A, 24
+ %D = or i32 %B, %C
+ %E = trunc i32 %D to i8
+ ret i8 %E
}
define signext i32 @test2(i32 %A, i32 %X) {
- %B = lshr i32 %A, 8
- %C = shl i32 %A, 24
- %D = or i32 %B, %C
- %E = trunc i32 %D to i8
- %F = sext i8 %E to i32
- %G = add i32 %F, %X
- ret i32 %G
+; CHECK: test2
+; CHECK: sxtab r0, r1, r0
+ %B = lshr i32 %A, 8
+ %C = shl i32 %A, 24
+ %D = or i32 %B, %C
+ %E = trunc i32 %D to i8
+ %F = sext i8 %E to i32
+ %G = add i32 %F, %X
+ ret i32 %G
}
diff --git a/test/CodeGen/ARM/tail-opts.ll b/test/CodeGen/ARM/tail-opts.ll
index 5b3dce3..3dc77e2 100644
--- a/test/CodeGen/ARM/tail-opts.ll
+++ b/test/CodeGen/ARM/tail-opts.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -mtriple=arm-apple-darwin -mcpu=cortex-a8 -asm-verbose=false | FileCheck %s
+; RUN: llc < %s -mtriple=arm-apple-darwin -relocation-model=dynamic-no-pic -mcpu=cortex-a8 -asm-verbose=false | FileCheck %s
declare void @bar(i32)
declare void @car(i32)
diff --git a/test/CodeGen/ARM/thumb2-it-block.ll b/test/CodeGen/ARM/thumb2-it-block.ll
new file mode 100644
index 0000000..28fd469
--- /dev/null
+++ b/test/CodeGen/ARM/thumb2-it-block.ll
@@ -0,0 +1,20 @@
+; RUN: llc < %s -march=thumb -mattr=+thumb2 | FileCheck %s
+; PR11107
+
+define i32 @test(i32 %a, i32 %b) {
+entry:
+; CHECK: movs.w
+; CHECK-NEXT: it mi
+; CHECK-NEXT: rsbmi
+; CHECK-NEXT: movs.w
+; CHECK-NEXT: it mi
+; CHECK-NEXT: rsbmi
+ %cmp1 = icmp slt i32 %a, 0
+ %sub1 = sub nsw i32 0, %a
+ %abs1 = select i1 %cmp1, i32 %sub1, i32 %a
+ %cmp2 = icmp slt i32 %b, 0
+ %sub2 = sub nsw i32 0, %b
+ %abs2 = select i1 %cmp2, i32 %sub2, i32 %b
+ %add = add nsw i32 %abs1, %abs2
+ ret i32 %add
+}
diff --git a/test/CodeGen/ARM/va_arg.ll b/test/CodeGen/ARM/va_arg.ll
index bb40453..af477b4 100644
--- a/test/CodeGen/ARM/va_arg.ll
+++ b/test/CodeGen/ARM/va_arg.ll
@@ -30,6 +30,7 @@ entry:
%ap1 = bitcast i8** %ap to i8* ; <i8*> [#uses=2]
call void @llvm.va_start(i8* %ap1)
%0 = va_arg i8** %ap, i32 ; <i32> [#uses=0]
+ store i32 %0, i32* undef
%1 = va_arg i8** %ap, double ; <double> [#uses=1]
call void @llvm.va_end(i8* %ap1)
ret double %1
diff --git a/test/CodeGen/ARM/vext.ll b/test/CodeGen/ARM/vext.ll
index 49a042b..65b5913 100644
--- a/test/CodeGen/ARM/vext.ll
+++ b/test/CodeGen/ARM/vext.ll
@@ -133,3 +133,20 @@ define <8 x i16> @test_illegal(<8 x i16>* %A, <8 x i16>* %B) nounwind {
%tmp3 = shufflevector <8 x i16> %tmp1, <8 x i16> %tmp2, <8 x i32> <i32 0, i32 7, i32 5, i32 13, i32 3, i32 2, i32 2, i32 9>
ret <8 x i16> %tmp3
}
+
+; PR11129
+; Make sure this doesn't crash
+define arm_aapcscc void @test_elem_mismatch(<2 x i64>* nocapture %src, <4 x i16>* nocapture %dest) nounwind {
+; CHECK: test_elem_mismatch:
+; CHECK: vstr.64
+ %tmp0 = load <2 x i64>* %src, align 16
+ %tmp1 = bitcast <2 x i64> %tmp0 to <4 x i32>
+ %tmp2 = extractelement <4 x i32> %tmp1, i32 0
+ %tmp3 = extractelement <4 x i32> %tmp1, i32 2
+ %tmp4 = trunc i32 %tmp2 to i16
+ %tmp5 = trunc i32 %tmp3 to i16
+ %tmp6 = insertelement <4 x i16> undef, i16 %tmp4, i32 0
+ %tmp7 = insertelement <4 x i16> %tmp6, i16 %tmp5, i32 1
+ store <4 x i16> %tmp7, <4 x i16>* %dest, align 4
+ ret void
+}
diff --git a/test/CodeGen/ARM/widen-vmovs.ll b/test/CodeGen/ARM/widen-vmovs.ll
new file mode 100644
index 0000000..8fd99ba
--- /dev/null
+++ b/test/CodeGen/ARM/widen-vmovs.ll
@@ -0,0 +1,35 @@
+; RUN: llc < %s -widen-vmovs -mcpu=cortex-a8 -verify-machineinstrs | FileCheck %s
+target triple = "thumbv7-apple-ios"
+
+; The 0.0 constant is loaded from the constant pool and kept in a register.
+; CHECK: %entry
+; CHECK: vldr.32 s
+; The float loop variable is initialized with a vmovs from the constant register.
+; The vmovs is first widened to a vmovd, and then converted to a vorr because of the v2f32 vadd.f32.
+; CHECK: vorr [[DL:d[0-9]+]], [[DN:d[0-9]+]]
+; CHECK: , [[DN]]
+; CHECK: %for.body.i
+; CHECK: vadd.f32 [[DL]], [[DL]], [[DN]]
+;
+; This test is verifying:
+; - The VMOVS widening is happening.
+; - Register liveness is verified.
+; - The execution domain switch to vorr works across basic blocks.
+
+define void @Mm() nounwind {
+entry:
+ br label %for.body4
+
+for.body4:
+ br label %for.body.i
+
+for.body.i:
+ %tmp3.i = phi float [ 0.000000e+00, %for.body4 ], [ %add.i, %for.body.i ]
+ %add.i = fadd float %tmp3.i, 0.000000e+00
+ %exitcond.i = icmp eq i32 undef, 41
+ br i1 %exitcond.i, label %rInnerproduct.exit, label %for.body.i
+
+rInnerproduct.exit:
+ store float %add.i, float* undef, align 4
+ br label %for.body4
+}
diff --git a/test/CodeGen/Alpha/2006-04-04-zextload.ll b/test/CodeGen/Alpha/2006-04-04-zextload.ll
index 2b28903..671d39e 100644
--- a/test/CodeGen/Alpha/2006-04-04-zextload.ll
+++ b/test/CodeGen/Alpha/2006-04-04-zextload.ll
@@ -2,7 +2,6 @@
target datalayout = "e-p:64:64"
target triple = "alphaev67-unknown-linux-gnu"
- %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i32, i8*, i8*, i8* }
%struct._Callback_list = type { %struct._Callback_list*, void (i32, %struct.ios_base*, i32)*, i32, i32 }
%struct._Impl = type { i32, %struct.facet**, i64, %struct.facet**, i8** }
%struct._Words = type { i8*, i64 }
@@ -12,7 +11,6 @@ target triple = "alphaev67-unknown-linux-gnu"
%struct.ios_base = type { i32 (...)**, i64, i64, i32, i32, i32, %struct._Callback_list*, %struct._Words, [8 x %struct._Words], i32, %struct._Words*, %struct.locale }
%struct.locale = type { %struct._Impl* }
%"struct.ostreambuf_iterator<char,std::char_traits<char> >" = type { %"struct.basic_streambuf<char,std::char_traits<char> >"*, i1 }
-@llvm.dbg.compile_unit1047 = external global %llvm.dbg.compile_unit.type ; <%llvm.dbg.compile_unit.type*> [#uses=1]
define void @_ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE15_M_insert_floatIdEES3_S3_RSt8ios_baseccT_() {
entry:
@@ -26,9 +24,7 @@ cond_next243: ; preds = %entry
%tmp428 = load i64* null ; <i64> [#uses=1]
%tmp428.upgrd.1 = trunc i64 %tmp428 to i32 ; <i32> [#uses=1]
%tmp429 = alloca i8, i32 %tmp428.upgrd.1 ; <i8*> [#uses=0]
- call void @llvm.dbg.stoppoint( i32 1146, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit1047 to { }*) )
unreachable
}
-declare void @llvm.dbg.stoppoint(i32, i32, { }*)
diff --git a/test/CodeGen/Alpha/mb.ll b/test/CodeGen/Alpha/mb.ll
index 93e8b1b..3268c54 100644
--- a/test/CodeGen/Alpha/mb.ll
+++ b/test/CodeGen/Alpha/mb.ll
@@ -1,8 +1,6 @@
; RUN: llc < %s -march=alpha | grep mb
-declare void @llvm.memory.barrier( i1 , i1 , i1 , i1 , i1)
-
define void @test() {
- call void @llvm.memory.barrier( i1 true, i1 true, i1 true, i1 true , i1 true)
+ fence seq_cst
ret void
}
diff --git a/test/CodeGen/Alpha/wmb.ll b/test/CodeGen/Alpha/wmb.ll
deleted file mode 100644
index a3e2ccf..0000000
--- a/test/CodeGen/Alpha/wmb.ll
+++ /dev/null
@@ -1,8 +0,0 @@
-; RUN: llc < %s -march=alpha | grep wmb
-
-declare void @llvm.memory.barrier( i1 , i1 , i1 , i1 , i1)
-
-define void @test() {
- call void @llvm.memory.barrier( i1 false, i1 false, i1 false, i1 true , i1 true)
- ret void
-}
diff --git a/test/CodeGen/CBackend/X86/dg.exp b/test/CodeGen/CBackend/X86/dg.exp
index 833bcc5..44e3a5e 100644
--- a/test/CodeGen/CBackend/X86/dg.exp
+++ b/test/CodeGen/CBackend/X86/dg.exp
@@ -1,5 +1,5 @@
load_lib llvm.exp
-if { [llvm_supports_target X86] && [llvm_gcc_supports c] } {
+if { [llvm_supports_target X86] && [llvm_supports_target CBackend] } {
RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp,s}]]
}
diff --git a/test/CodeGen/CellSPU/jumptable.ll b/test/CodeGen/CellSPU/jumptable.ll
index 87376ef..66c2fde 100644
--- a/test/CodeGen/CellSPU/jumptable.ll
+++ b/test/CodeGen/CellSPU/jumptable.ll
@@ -4,18 +4,18 @@ define i32 @test(i32 %param) {
entry:
;CHECK: ai {{\$.}}, $3, -1
;CHECK: clgti {{\$., \$.}}, 3
-;CHECK: brnz {{\$.}},.LBB0_2
- switch i32 %param, label %bb1 [
- i32 1, label %bb3
+;CHECK: brnz {{\$.}},.LBB0_
+ switch i32 %param, label %bb2 [
+ i32 1, label %bb1
i32 2, label %bb2
i32 3, label %bb3
- i32 4, label %bb1
+ i32 4, label %bb2
]
-
+;CHECK-NOT: # BB#2
bb1:
ret i32 1
bb2:
ret i32 2
bb3:
- ret i32 3
+ ret i32 %param
}
diff --git a/test/CodeGen/CellSPU/or_ops.ll b/test/CodeGen/CellSPU/or_ops.ll
index 46349b9..4f1febb 100644
--- a/test/CodeGen/CellSPU/or_ops.ll
+++ b/test/CodeGen/CellSPU/or_ops.ll
@@ -1,9 +1,11 @@
; RUN: llc < %s -march=cellspu > %t1.s
; RUN: grep and %t1.s | count 2
; RUN: grep orc %t1.s | count 85
-; RUN: grep ori %t1.s | count 30
+; RUN: grep ori %t1.s | count 34
; RUN: grep orhi %t1.s | count 30
; RUN: grep orbi %t1.s | count 15
+; RUN: FileCheck %s < %t1.s
+
target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128"
target triple = "spu"
@@ -210,6 +212,15 @@ define signext i32 @ori_i32(i32 signext %in) {
ret i32 %tmp38
}
+define i32 @ori_i32_600(i32 %in) {
+ ;600 does not fit into 'ori' immediate field
+ ;CHECK: ori_i32_600
+ ;CHECK: il
+ ;CHECK: ori
+ %tmp = or i32 %in, 600
+ ret i32 %tmp
+}
+
; ORHI instruction generation (i16 data type):
define <8 x i16> @orhi_v8i16_1(<8 x i16> %in) {
%tmp2 = or <8 x i16> %in, < i16 511, i16 511, i16 511, i16 511,
diff --git a/test/CodeGen/Generic/2004-02-08-UnwindSupport.ll b/test/CodeGen/Generic/2004-02-08-UnwindSupport.ll
deleted file mode 100644
index 393062a..0000000
--- a/test/CodeGen/Generic/2004-02-08-UnwindSupport.ll
+++ /dev/null
@@ -1,17 +0,0 @@
-; RUN: llc < %s -enable-correct-eh-support
-
-define i32 @test() {
- unwind
-}
-
-define i32 @main() {
- %X = invoke i32 @test( )
- to label %cont unwind label %EH ; <i32> [#uses=0]
-
-cont: ; preds = %0
- ret i32 1
-
-EH: ; preds = %0
- ret i32 0
-}
-
diff --git a/test/CodeGen/Generic/2007-02-25-invoke.ll b/test/CodeGen/Generic/2007-02-25-invoke.ll
index 6e20eaa..7850cec 100644
--- a/test/CodeGen/Generic/2007-02-25-invoke.ll
+++ b/test/CodeGen/Generic/2007-02-25-invoke.ll
@@ -8,5 +8,9 @@ define i32 @test2() {
invcont:
ret i32 %A
blat:
- ret i32 0
+ %lpad = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ ret i32 0
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/Generic/2007-04-30-LandingPadBranchFolding.ll b/test/CodeGen/Generic/2007-04-30-LandingPadBranchFolding.ll
index 2a2cf6c..407696f 100644
--- a/test/CodeGen/Generic/2007-04-30-LandingPadBranchFolding.ll
+++ b/test/CodeGen/Generic/2007-04-30-LandingPadBranchFolding.ll
@@ -45,7 +45,9 @@ cond_next1328: ; preds = %cond_true235, %cond_true
ret void
cond_true1402: ; preds = %invcont282, %cond_false280, %cond_true235, %cond_true
- ret void
+ %lpad = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ ret void
}
declare void @_ZNSs14_M_replace_auxEjjjc()
@@ -57,3 +59,5 @@ declare void @_ZNSs6assignEPKcj()
declare void @_ZNSs7reserveEj()
declare void @_ZNSs6appendEPKcj()
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll b/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll
index 5df2200..27c7162 100644
--- a/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll
+++ b/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll
@@ -2,12 +2,16 @@
define fastcc void @bc__support__high_resolution_time__initialize_clock_rate() {
entry:
- invoke void asm "rdtsc\0A\09movl %eax, $0\0A\09movl %edx, $1", "=*imr,=*imr,~{dirflag},~{fpsr},~{flags},~{dx},~{ax}"( i32* null, i32* null )
- to label %.noexc unwind label %cleanup144
+ invoke void asm "rdtsc\0A\09movl %eax, $0\0A\09movl %edx, $1", "=*imr,=*imr,~{dirflag},~{fpsr},~{flags},~{dx},~{ax}"( i32* null, i32* null )
+ to label %.noexc unwind label %cleanup144
.noexc: ; preds = %entry
- ret void
+ ret void
cleanup144: ; preds = %entry
- unwind
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ resume { i8*, i32 } %exn
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/Generic/2007-12-31-UnusedSelector.ll b/test/CodeGen/Generic/2007-12-31-UnusedSelector.ll
index 00e027b..943ed88 100644
--- a/test/CodeGen/Generic/2007-12-31-UnusedSelector.ll
+++ b/test/CodeGen/Generic/2007-12-31-UnusedSelector.ll
@@ -14,11 +14,14 @@ bb14: ; preds = %lpad
unreachable
lpad: ; preds = %entry
+ %lpad1 = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
invoke void @__cxa_end_catch( )
to label %bb14 unwind label %lpad17
lpad17: ; preds = %lpad
- %eh_select20 = tail call i32 (i8*, i8*, ...)* @llvm.eh.selector.i32( i8* null, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null ) ; <i32> [#uses=0]
+ %lpad2 = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
unreachable
UnifiedUnreachableBlock: ; preds = %entry
diff --git a/test/CodeGen/Generic/2009-06-03-UnreachableSplitPad.ll b/test/CodeGen/Generic/2009-06-03-UnreachableSplitPad.ll
index 112cac4..ad418f7 100644
--- a/test/CodeGen/Generic/2009-06-03-UnreachableSplitPad.ll
+++ b/test/CodeGen/Generic/2009-06-03-UnreachableSplitPad.ll
@@ -11,5 +11,9 @@ dummy:
invoke i32 @b() to label %reg unwind label %reg
reg:
+ %lpad = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
ret void
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/Generic/2009-11-16-BadKillsCrash.ll b/test/CodeGen/Generic/2009-11-16-BadKillsCrash.ll
index 22bd4d7..3cbf4c5 100644
--- a/test/CodeGen/Generic/2009-11-16-BadKillsCrash.ll
+++ b/test/CodeGen/Generic/2009-11-16-BadKillsCrash.ll
@@ -64,10 +64,16 @@ invcont38: ; preds = %invcont25, %bb1.i,
lpad: ; preds = %bb.i93, %invcont24, %bb1.i, %invcont8
%__extracted.1 = phi i32 [ 0, %invcont8 ], [ %2, %bb1.i ], [ undef, %bb.i93 ], [ undef, %invcont24 ] ; <i32> [#uses=0]
- %eh_ptr = call i8* @llvm.eh.exception() ; <i8*> [#uses=1]
+ %lpad1 = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
+ %eh_ptr = extractvalue { i8*, i32 } %lpad1, 0
%6 = call i8* @__cxa_begin_catch(i8* %eh_ptr) nounwind ; <i8*> [#uses=0]
unreachable
lpad74: ; preds = %entry
+ %lpad2 = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/Generic/2011-07-07-ScheduleDAGCrash.ll b/test/CodeGen/Generic/2011-07-07-ScheduleDAGCrash.ll
index cd446d5..da26504 100644
--- a/test/CodeGen/Generic/2011-07-07-ScheduleDAGCrash.ll
+++ b/test/CodeGen/Generic/2011-07-07-ScheduleDAGCrash.ll
@@ -3,6 +3,9 @@
; the uses of a copy to a physical register without ignoring non-data
; dependence, PR10220.
+; The ARM backend can't handle i256 math at the moment.
+; XFAIL: arm
+
define void @f(i256* nocapture %a, i256* nocapture %b, i256* nocapture %cc, i256* nocapture %dd) nounwind uwtable noinline ssp {
entry:
%c = load i256* %cc
diff --git a/test/CodeGen/Generic/exception-handling.ll b/test/CodeGen/Generic/exception-handling.ll
new file mode 100644
index 0000000..376e1f1
--- /dev/null
+++ b/test/CodeGen/Generic/exception-handling.ll
@@ -0,0 +1,29 @@
+; RUN: llc < %s
+; PR10733
+declare void @_Znam()
+
+define void @_ZNK14gIndexOdometer15AfterExcisionOfERi() uwtable align 2 {
+_ZN6Gambit5ArrayIiEC2Ej.exit36:
+ br label %"9"
+
+"9": ; preds = %"10", %_ZN6Gambit5ArrayIiEC2Ej.exit36
+ %indvar82 = phi i64 [ 0, %_ZN6Gambit5ArrayIiEC2Ej.exit36 ], [ %tmp85, %"10" ]
+ %tmp85 = add i64 %indvar82, 1
+ %tmp = trunc i64 %tmp85 to i32
+ invoke void @_ZNK14gIndexOdometer9NoIndicesEv()
+ to label %"10" unwind label %lpad27
+
+"10": ; preds = %"9"
+ invoke void @_Znam()
+ to label %"9" unwind label %lpad27
+
+lpad27: ; preds = %"10", %"9"
+ %0 = phi i32 [ undef, %"9" ], [ %tmp, %"10" ]
+ %1 = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0
+ cleanup
+ resume { i8*, i32 } zeroinitializer
+}
+
+declare void @_ZNK14gIndexOdometer9NoIndicesEv()
+
+declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)
diff --git a/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll b/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll
index a3cab5d..e709080 100644
--- a/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll
+++ b/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll
@@ -13,6 +13,9 @@ normal:
ret void
handler:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
ret void
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/Generic/promote-integers.ll b/test/CodeGen/Generic/promote-integers.ll
deleted file mode 100644
index 5812592..0000000
--- a/test/CodeGen/Generic/promote-integers.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; Test that vectors are scalarized/lowered correctly.
-; RUN: llc -march=x86 -promote-elements < %s | FileCheck %s
-
-; This test is the poster-child for integer-element-promotion.
-; Until this feature is complete, we mark this test as expected to fail.
-; XFAIL: *
-; CHECK: vector_code
-; CHECK: ret
-define <4 x float> @vector_code(<4 x i64> %A, <4 x i64> %B, <4 x float> %R0, <4 x float> %R1 ) {
- %C = icmp eq <4 x i64> %A, %B
- %K = xor <4 x i1> <i1 1, i1 1, i1 1, i1 1>, %C
- %D = select <4 x i1> %K, <4 x float> %R1, <4 x float> %R0
- ret <4 x float> %D
-}
-
diff --git a/test/CodeGen/Mips/2008-07-05-ByVal.ll b/test/CodeGen/Mips/2008-07-05-ByVal.ll
deleted file mode 100644
index a1f0504..0000000
--- a/test/CodeGen/Mips/2008-07-05-ByVal.ll
+++ /dev/null
@@ -1,18 +0,0 @@
-; RUN: llc < %s -march=mips | grep {lw.*(\$4)} | count 2
-
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
-target triple = "mipsallegrexel-unknown-psp-elf"
- %struct.byval0 = type { i32, i32 }
-
-define i64 @test0(%struct.byval0* byval %b, i64 %sum) nounwind {
-entry:
- getelementptr %struct.byval0* %b, i32 0, i32 0 ; <i32*>:0 [#uses=1]
- load i32* %0, align 4 ; <i32>:1 [#uses=1]
- getelementptr %struct.byval0* %b, i32 0, i32 1 ; <i32*>:2 [#uses=1]
- load i32* %2, align 4 ; <i32>:3 [#uses=1]
- add i32 %3, %1 ; <i32>:4 [#uses=1]
- sext i32 %4 to i64 ; <i64>:5 [#uses=1]
- add i64 %5, %sum ; <i64>:6 [#uses=1]
- ret i64 %6
-}
-
diff --git a/test/CodeGen/Mips/2008-07-06-fadd64.ll b/test/CodeGen/Mips/2008-07-06-fadd64.ll
index ecd8521..ff8ed4d 100644
--- a/test/CodeGen/Mips/2008-07-06-fadd64.ll
+++ b/test/CodeGen/Mips/2008-07-06-fadd64.ll
@@ -1,10 +1,8 @@
-; RUN: llc < %s -march=mips | grep __adddf3
-
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
-target triple = "mipsallegrexel-unknown-psp-elf"
+; RUN: llc -march=mips -mattr=single-float < %s | FileCheck %s
define double @dofloat(double %a, double %b) nounwind {
entry:
+; CHECK: __adddf3
fadd double %a, %b ; <double>:0 [#uses=1]
ret double %0
}
diff --git a/test/CodeGen/Mips/2008-07-07-FPExtend.ll b/test/CodeGen/Mips/2008-07-07-FPExtend.ll
index 681788e..29c8e84 100644
--- a/test/CodeGen/Mips/2008-07-07-FPExtend.ll
+++ b/test/CodeGen/Mips/2008-07-07-FPExtend.ll
@@ -1,10 +1,8 @@
-; RUN: llc < %s -march=mips | grep __extendsfdf2
-
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
-target triple = "mipsallegrexel-unknown-psp-elf"
+; RUN: llc -march=mips -mattr=single-float < %s | FileCheck %s
define double @dofloat(float %a) nounwind {
entry:
+; CHECK: __extendsfdf2
fpext float %a to double ; <double>:0 [#uses=1]
ret double %0
}
diff --git a/test/CodeGen/Mips/2008-07-07-IntDoubleConvertions.ll b/test/CodeGen/Mips/2008-07-07-IntDoubleConvertions.ll
index b8b4c5c..9a6bbdf 100644
--- a/test/CodeGen/Mips/2008-07-07-IntDoubleConvertions.ll
+++ b/test/CodeGen/Mips/2008-07-07-IntDoubleConvertions.ll
@@ -1,32 +1,33 @@
-; RUN: llc < %s -march=mips -o %t
-; RUN: grep __floatsidf %t | count 1
-; RUN: grep __floatunsidf %t | count 1
-; RUN: grep __fixdfsi %t | count 1
-; RUN: grep __fixunsdfsi %t | count 1
-
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
-target triple = "mipsallegrexel-unknown-psp-elf"
+; RUN: llc -march=mips -mattr=single-float < %s | FileCheck %s
define double @int2fp(i32 %a) nounwind {
entry:
+; CHECK: int2fp
+; CHECK: __floatsidf
sitofp i32 %a to double ; <double>:0 [#uses=1]
ret double %0
}
define double @uint2double(i32 %a) nounwind {
entry:
+; CHECK: uint2double
+; CHECK: __floatunsidf
uitofp i32 %a to double ; <double>:0 [#uses=1]
ret double %0
}
define i32 @double2int(double %a) nounwind {
entry:
+; CHECK: double2int
+; CHECK: __fixdfsi
fptosi double %a to i32 ; <i32>:0 [#uses=1]
ret i32 %0
}
define i32 @double2uint(double %a) nounwind {
entry:
+; CHECK: double2uint
+; CHECK: __fixunsdfsi
fptoui double %a to i32 ; <i32>:0 [#uses=1]
ret i32 %0
}
diff --git a/test/CodeGen/Mips/2008-07-15-InternalConstant.ll b/test/CodeGen/Mips/2008-07-15-InternalConstant.ll
index c3db638..29a7b5c 100644
--- a/test/CodeGen/Mips/2008-07-15-InternalConstant.ll
+++ b/test/CodeGen/Mips/2008-07-15-InternalConstant.ll
@@ -1,22 +1,23 @@
-; RUN: llc < %s -march=mips -o %t
-; RUN: grep {rodata.str1.4,"aMS",@progbits} %t | count 1
-; RUN: grep {r.data,} %t | count 1
-; RUN: grep {\%hi} %t | count 2
-; RUN: grep {\%lo} %t | count 2
-; RUN: not grep {gp_rel} %t
+; RUN: llc -march=mips -relocation-model=static < %s | FileCheck %s
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
-target triple = "mipsallegrexel-unknown-psp-elf"
@.str = internal unnamed_addr constant [10 x i8] c"AAAAAAAAA\00"
-@i0 = internal unnamed_addr constant [5 x i32] [ i32 0, i32 1, i32 2, i32 3, i32 4 ]
+@i0 = internal unnamed_addr constant [5 x i32] [ i32 0, i32 1, i32 2, i32 3, i32 4 ]
define i8* @foo() nounwind {
entry:
+; CHECK: foo
+; CHECK: %hi(.str)
+; CHECK: %lo(.str)
ret i8* getelementptr ([10 x i8]* @.str, i32 0, i32 0)
}
define i32* @bar() nounwind {
entry:
+; CHECK: bar
+; CHECK: %hi(i0)
+; CHECK: %lo(i0)
ret i32* getelementptr ([5 x i32]* @i0, i32 0, i32 0)
}
+; CHECK: rodata.str1.4,"aMS",@progbits
+; CHECK: rodata,"a",@progbits
diff --git a/test/CodeGen/Mips/2008-07-15-SmallSection.ll b/test/CodeGen/Mips/2008-07-15-SmallSection.ll
index 4795e47..cbc3ecf 100644
--- a/test/CodeGen/Mips/2008-07-15-SmallSection.ll
+++ b/test/CodeGen/Mips/2008-07-15-SmallSection.ll
@@ -1,13 +1,16 @@
-; RUN: llc < %s -mips-ssection-threshold=8 -march=mips -o %t0
-; RUN: llc < %s -mips-ssection-threshold=0 -march=mips -o %t1
-; RUN: grep {sdata} %t0 | count 1
-; RUN: grep {sbss} %t0 | count 1
-; RUN: grep {gp_rel} %t0 | count 2
-; RUN: not grep {sdata} %t1
-; RUN: not grep {sbss} %t1
-; RUN: not grep {gp_rel} %t1
-; RUN: grep {\%hi} %t1 | count 2
-; RUN: grep {\%lo} %t1 | count 3
+; DISABLED: llc < %s -mips-ssection-threshold=8 -march=mips -o %t0
+; DISABLED: llc < %s -mips-ssection-threshold=0 -march=mips -o %t1
+; DISABLED: grep {sdata} %t0 | count 1
+; DISABLED: grep {sbss} %t0 | count 1
+; DISABLED: grep {gp_rel} %t0 | count 2
+; DISABLED: not grep {sdata} %t1
+; DISABLED: not grep {sbss} %t1
+; DISABLED: not grep {gp_rel} %t1
+; DISABLED: grep {\%hi} %t1 | count 2
+; DISABLED: grep {\%lo} %t1 | count 3
+; RUN: false
+; XFAIL: *
+
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
target triple = "mipsallegrexel-unknown-psp-elf"
diff --git a/test/CodeGen/Mips/2008-07-16-SignExtInReg.ll b/test/CodeGen/Mips/2008-07-16-SignExtInReg.ll
index 855194a..e0c745f 100644
--- a/test/CodeGen/Mips/2008-07-16-SignExtInReg.ll
+++ b/test/CodeGen/Mips/2008-07-16-SignExtInReg.ll
@@ -1,6 +1,8 @@
-; RUN: llc < %s -march=mips -o %t
-; RUN: grep seh %t | count 1
-; RUN: grep seb %t | count 1
+; DISABLED: llc < %s -march=mips -o %t
+; DISABLED: grep seh %t | count 1
+; DISABLED: grep seb %t | count 1
+; RUN: false
+; XFAIL: *
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
target triple = "mipsallegrexel-unknown-psp-elf"
diff --git a/test/CodeGen/Mips/2008-08-03-fabs64.ll b/test/CodeGen/Mips/2008-08-03-fabs64.ll
index 0fc45f7..2b1713c 100644
--- a/test/CodeGen/Mips/2008-08-03-fabs64.ll
+++ b/test/CodeGen/Mips/2008-08-03-fabs64.ll
@@ -1,6 +1,8 @@
-; RUN: llc < %s -march=mips -o %t
-; RUN: grep {lui.*32767} %t | count 1
-; RUN: grep {ori.*65535} %t | count 1
+; DISABLED: llc < %s -march=mips -o %t
+; DISABLED: grep {lui.*32767} %t | count 1
+; DISABLED: grep {ori.*65535} %t | count 1
+; RUN: false
+; XFAIL: *
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
target triple = "mipsallegrexel-unknown-psp-elf"
diff --git a/test/CodeGen/Mips/2008-08-07-FPRound.ll b/test/CodeGen/Mips/2008-08-07-FPRound.ll
index 67f86d7..4fa43b6 100644
--- a/test/CodeGen/Mips/2008-08-07-FPRound.ll
+++ b/test/CodeGen/Mips/2008-08-07-FPRound.ll
@@ -1,10 +1,8 @@
-; RUN: llc < %s -march=mips | grep __truncdfsf2 | count 1
-
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
-target triple = "mipsallegrexel-unknown-psp-elf"
+; RUN: llc -march=mips -mattr=single-float < %s | FileCheck %s
define float @round2float(double %a) nounwind {
entry:
+; CHECK: __truncdfsf2
fptrunc double %a to float ; <float>:0 [#uses=1]
ret float %0
}
diff --git a/test/CodeGen/Mips/2008-08-08-bswap.ll b/test/CodeGen/Mips/2008-08-08-bswap.ll
index 83289d9..596da24 100644
--- a/test/CodeGen/Mips/2008-08-08-bswap.ll
+++ b/test/CodeGen/Mips/2008-08-08-bswap.ll
@@ -1,4 +1,7 @@
-; RUN: llc < %s | grep wsbw | count 1
+; DISABLED: llc < %s | grep wsbw | count 1
+; RUN: false
+; XFAIL: *
+
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
target triple = "psp"
diff --git a/test/CodeGen/Mips/2010-07-20-Select.ll b/test/CodeGen/Mips/2010-07-20-Select.ll
deleted file mode 100644
index e5e2c54..0000000
--- a/test/CodeGen/Mips/2010-07-20-Select.ll
+++ /dev/null
@@ -1,22 +0,0 @@
-; RUN: llc < %s -march=mips -relocation-model=static | FileCheck %s
-; RUN: llc < %s -march=mips -relocation-model=static -regalloc=basic | FileCheck %s
-; Fix PR7473
-
-define i32 @main() nounwind readnone {
-entry:
- %a = alloca i32, align 4 ; <i32*> [#uses=2]
- %c = alloca i32, align 4 ; <i32*> [#uses=2]
- volatile store i32 1, i32* %a, align 4
- volatile store i32 0, i32* %c, align 4
- %0 = volatile load i32* %a, align 4 ; <i32> [#uses=1]
- %1 = icmp eq i32 %0, 0 ; <i1> [#uses=1]
-; CHECK: addiu $[[R1:[0-9]+]], $zero, 0
- %iftmp.0.0 = select i1 %1, i32 3, i32 0 ; <i32> [#uses=1]
- %2 = volatile load i32* %c, align 4 ; <i32> [#uses=1]
- %3 = icmp eq i32 %2, 0 ; <i1> [#uses=1]
-; CHECK: addiu $[[R1]], $zero, 3
-; CHECK: addu $2, ${{.}}, $[[R1]]
- %iftmp.2.0 = select i1 %3, i32 0, i32 5 ; <i32> [#uses=1]
- %4 = add nsw i32 %iftmp.2.0, %iftmp.0.0 ; <i32> [#uses=1]
- ret i32 %4
-}
diff --git a/test/CodeGen/Mips/2010-11-09-CountLeading.ll b/test/CodeGen/Mips/2010-11-09-CountLeading.ll
index d592fef..c592b31 100644
--- a/test/CodeGen/Mips/2010-11-09-CountLeading.ll
+++ b/test/CodeGen/Mips/2010-11-09-CountLeading.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=mips -mcpu=4ke < %s | FileCheck %s
+; RUN: llc -march=mips < %s | FileCheck %s
; CHECK: clz $2, $4
define i32 @t1(i32 %X) nounwind readnone {
diff --git a/test/CodeGen/Mips/2010-11-09-Mul.ll b/test/CodeGen/Mips/2010-11-09-Mul.ll
index 65a10b5..dcade3c 100644
--- a/test/CodeGen/Mips/2010-11-09-Mul.ll
+++ b/test/CodeGen/Mips/2010-11-09-Mul.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=mips -mcpu=4ke < %s | FileCheck %s
+; RUN: llc -march=mips < %s | FileCheck %s
; CHECK: mul $2, $5, $4
define i32 @mul1(i32 %a, i32 %b) nounwind readnone {
diff --git a/test/CodeGen/Mips/alloca.ll b/test/CodeGen/Mips/alloca.ll
index fb4f56c..15c73e2 100644
--- a/test/CodeGen/Mips/alloca.ll
+++ b/test/CodeGen/Mips/alloca.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=mipsel -mcpu=4ke < %s | FileCheck %s
+; RUN: llc -march=mipsel < %s | FileCheck %s
define i32 @twoalloca(i32 %size) nounwind {
entry:
diff --git a/test/CodeGen/Mips/atomic.ll b/test/CodeGen/Mips/atomic.ll
index 2d5555b..a4763b1 100644
--- a/test/CodeGen/Mips/atomic.ll
+++ b/test/CodeGen/Mips/atomic.ll
@@ -1,30 +1,16 @@
-; RUN: llc -march=mipsel -mcpu=mips2 < %s | FileCheck %s
-
-
-declare i32 @llvm.atomic.load.add.i32.p0i32(i32* nocapture, i32) nounwind
-declare i32 @llvm.atomic.load.nand.i32.p0i32(i32* nocapture, i32) nounwind
-declare i32 @llvm.atomic.swap.i32.p0i32(i32* nocapture, i32) nounwind
-declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* nocapture, i32, i32) nounwind
-
-declare i8 @llvm.atomic.load.add.i8.p0i8(i8* nocapture, i8) nounwind
-declare i8 @llvm.atomic.load.sub.i8.p0i8(i8* nocapture, i8) nounwind
-declare i8 @llvm.atomic.load.nand.i8.p0i8(i8* nocapture, i8) nounwind
-declare i8 @llvm.atomic.swap.i8.p0i8(i8* nocapture, i8) nounwind
-declare i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* nocapture, i8, i8) nounwind
-
+; RUN: llc -march=mipsel < %s | FileCheck %s
@x = common global i32 0, align 4
define i32 @AtomicLoadAdd32(i32 %incr) nounwind {
entry:
- %0 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* @x, i32 %incr)
+ %0 = atomicrmw add i32* @x, i32 %incr monotonic
ret i32 %0
; CHECK: AtomicLoadAdd32:
; CHECK: lw $[[R0:[0-9]+]], %got(x)($gp)
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $[[R1:[0-9]+]], 0($[[R0]])
-; CHECK: or $2, $zero, $[[R1]]
; CHECK: addu $[[R2:[0-9]+]], $[[R1]], $4
; CHECK: sc $[[R2]], 0($[[R0]])
; CHECK: beq $[[R2]], $zero, $[[BB0]]
@@ -32,51 +18,49 @@ entry:
define i32 @AtomicLoadNand32(i32 %incr) nounwind {
entry:
- %0 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* @x, i32 %incr)
+ %0 = atomicrmw nand i32* @x, i32 %incr monotonic
ret i32 %0
; CHECK: AtomicLoadNand32:
; CHECK: lw $[[R0:[0-9]+]], %got(x)($gp)
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $[[R1:[0-9]+]], 0($[[R0]])
-; CHECK: or $2, $zero, $[[R1]]
-; CHECK: and $[[R1]], $[[R1]], $4
-; CHECK: nor $[[R2:[0-9]+]], $zero, $[[R1]]
+; CHECK: and $[[R3:[0-9]+]], $[[R1]], $4
+; CHECK: nor $[[R2:[0-9]+]], $zero, $[[R3]]
; CHECK: sc $[[R2]], 0($[[R0]])
; CHECK: beq $[[R2]], $zero, $[[BB0]]
}
-define i32 @AtomicSwap32(i32 %oldval) nounwind {
+define i32 @AtomicSwap32(i32 %newval) nounwind {
entry:
- %0 = call i32 @llvm.atomic.swap.i32.p0i32(i32* @x, i32 %oldval)
+ %newval.addr = alloca i32, align 4
+ store i32 %newval, i32* %newval.addr, align 4
+ %tmp = load i32* %newval.addr, align 4
+ %0 = atomicrmw xchg i32* @x, i32 %tmp monotonic
ret i32 %0
; CHECK: AtomicSwap32:
; CHECK: lw $[[R0:[0-9]+]], %got(x)($gp)
-; CHECK: sw $4, [[OFFSET:[0-9]+]]($sp)
; CHECK: $[[BB0:[A-Z_0-9]+]]:
-; CHECK: ll $[[R1:[0-9]+]], 0($[[R0]])
-; CHECK: or $2, $zero, $[[R1]]
-; CHECK: lw $[[R2:[0-9]+]], [[OFFSET]]($sp)
-; CHECK: or $[[R3:[0-9]+]], $zero, $[[R2]]
-; CHECK: sc $[[R3]], 0($[[R0]])
-; CHECK: beq $[[R3]], $zero, $[[BB0]]
+; CHECK: ll ${{[0-9]+}}, 0($[[R0]])
+; CHECK: sc $[[R2:[0-9]+]], 0($[[R0]])
+; CHECK: beq $[[R2]], $zero, $[[BB0]]
}
define i32 @AtomicCmpSwap32(i32 %oldval, i32 %newval) nounwind {
entry:
- %0 = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* @x, i32 %oldval, i32 %newval)
+ %newval.addr = alloca i32, align 4
+ store i32 %newval, i32* %newval.addr, align 4
+ %tmp = load i32* %newval.addr, align 4
+ %0 = cmpxchg i32* @x, i32 %oldval, i32 %tmp monotonic
ret i32 %0
; CHECK: AtomicCmpSwap32:
; CHECK: lw $[[R0:[0-9]+]], %got(x)($gp)
-; CHECK: sw $5, [[OFFSET:[0-9]+]]($sp)
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $2, 0($[[R0]])
; CHECK: bne $2, $4, $[[BB1:[A-Z_0-9]+]]
-; CHECK: lw $[[R1:[0-9]+]], [[OFFSET]]($sp)
-; CHECK: or $[[R2:[0-9]+]], $zero, $[[R1]]
-; CHECK: sc $[[R2]], 0($[[R0]])
+; CHECK: sc $[[R2:[0-9]+]], 0($[[R0]])
; CHECK: beq $[[R2]], $zero, $[[BB0]]
; CHECK: $[[BB1]]:
}
@@ -87,7 +71,7 @@ entry:
define signext i8 @AtomicLoadAdd8(i8 signext %incr) nounwind {
entry:
- %0 = call i8 @llvm.atomic.load.add.i8.p0i8(i8* @y, i8 %incr)
+ %0 = atomicrmw add i8* @y, i8 %incr monotonic
ret i8 %0
; CHECK: AtomicLoadAdd8:
@@ -97,10 +81,9 @@ entry:
; CHECK: andi $[[R3:[0-9]+]], $[[R0]], 3
; CHECK: sll $[[R4:[0-9]+]], $[[R3]], 3
; CHECK: ori $[[R5:[0-9]+]], $zero, 255
-; CHECK: sll $[[R6:[0-9]+]], $[[R5]], $[[R4]]
+; CHECK: sllv $[[R6:[0-9]+]], $[[R5]], $[[R4]]
; CHECK: nor $[[R7:[0-9]+]], $zero, $[[R6]]
-; CHECK: andi $[[R8:[0-9]+]], $4, 255
-; CHECK: sll $[[R9:[0-9]+]], $[[R8]], $[[R4]]
+; CHECK: sllv $[[R9:[0-9]+]], $4, $[[R4]]
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $[[R10:[0-9]+]], 0($[[R2]])
@@ -112,14 +95,14 @@ entry:
; CHECK: beq $[[R14]], $zero, $[[BB0]]
; CHECK: and $[[R15:[0-9]+]], $[[R10]], $[[R6]]
-; CHECK: srl $[[R16:[0-9]+]], $[[R15]], $[[R4]]
+; CHECK: srlv $[[R16:[0-9]+]], $[[R15]], $[[R4]]
; CHECK: sll $[[R17:[0-9]+]], $[[R16]], 24
; CHECK: sra $2, $[[R17]], 24
}
define signext i8 @AtomicLoadSub8(i8 signext %incr) nounwind {
entry:
- %0 = call i8 @llvm.atomic.load.sub.i8.p0i8(i8* @y, i8 %incr)
+ %0 = atomicrmw sub i8* @y, i8 %incr monotonic
ret i8 %0
; CHECK: AtomicLoadSub8:
@@ -129,15 +112,13 @@ entry:
; CHECK: andi $[[R3:[0-9]+]], $[[R0]], 3
; CHECK: sll $[[R4:[0-9]+]], $[[R3]], 3
; CHECK: ori $[[R5:[0-9]+]], $zero, 255
-; CHECK: sll $[[R6:[0-9]+]], $[[R5]], $[[R4]]
+; CHECK: sllv $[[R6:[0-9]+]], $[[R5]], $[[R4]]
; CHECK: nor $[[R7:[0-9]+]], $zero, $[[R6]]
-; CHECK: subu $[[R18:[0-9]+]], $zero, $4
-; CHECK: andi $[[R8:[0-9]+]], $[[R18]], 255
-; CHECK: sll $[[R9:[0-9]+]], $[[R8]], $[[R4]]
+; CHECK: sllv $[[R9:[0-9]+]], $4, $[[R4]]
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $[[R10:[0-9]+]], 0($[[R2]])
-; CHECK: addu $[[R11:[0-9]+]], $[[R10]], $[[R9]]
+; CHECK: subu $[[R11:[0-9]+]], $[[R10]], $[[R9]]
; CHECK: and $[[R12:[0-9]+]], $[[R11]], $[[R6]]
; CHECK: and $[[R13:[0-9]+]], $[[R10]], $[[R7]]
; CHECK: or $[[R14:[0-9]+]], $[[R13]], $[[R12]]
@@ -145,14 +126,14 @@ entry:
; CHECK: beq $[[R14]], $zero, $[[BB0]]
; CHECK: and $[[R15:[0-9]+]], $[[R10]], $[[R6]]
-; CHECK: srl $[[R16:[0-9]+]], $[[R15]], $[[R4]]
+; CHECK: srlv $[[R16:[0-9]+]], $[[R15]], $[[R4]]
; CHECK: sll $[[R17:[0-9]+]], $[[R16]], 24
; CHECK: sra $2, $[[R17]], 24
}
define signext i8 @AtomicLoadNand8(i8 signext %incr) nounwind {
entry:
- %0 = call i8 @llvm.atomic.load.nand.i8.p0i8(i8* @y, i8 %incr)
+ %0 = atomicrmw nand i8* @y, i8 %incr monotonic
ret i8 %0
; CHECK: AtomicLoadNand8:
@@ -162,10 +143,9 @@ entry:
; CHECK: andi $[[R3:[0-9]+]], $[[R0]], 3
; CHECK: sll $[[R4:[0-9]+]], $[[R3]], 3
; CHECK: ori $[[R5:[0-9]+]], $zero, 255
-; CHECK: sll $[[R6:[0-9]+]], $[[R5]], $[[R4]]
+; CHECK: sllv $[[R6:[0-9]+]], $[[R5]], $[[R4]]
; CHECK: nor $[[R7:[0-9]+]], $zero, $[[R6]]
-; CHECK: andi $[[R8:[0-9]+]], $4, 255
-; CHECK: sll $[[R9:[0-9]+]], $[[R8]], $[[R4]]
+; CHECK: sllv $[[R9:[0-9]+]], $4, $[[R4]]
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $[[R10:[0-9]+]], 0($[[R2]])
@@ -178,14 +158,14 @@ entry:
; CHECK: beq $[[R14]], $zero, $[[BB0]]
; CHECK: and $[[R15:[0-9]+]], $[[R10]], $[[R6]]
-; CHECK: srl $[[R16:[0-9]+]], $[[R15]], $[[R4]]
+; CHECK: srlv $[[R16:[0-9]+]], $[[R15]], $[[R4]]
; CHECK: sll $[[R17:[0-9]+]], $[[R16]], 24
; CHECK: sra $2, $[[R17]], 24
}
-define signext i8 @AtomicSwap8(i8 signext %oldval) nounwind {
+define signext i8 @AtomicSwap8(i8 signext %newval) nounwind {
entry:
- %0 = call i8 @llvm.atomic.swap.i8.p0i8(i8* @y, i8 %oldval)
+ %0 = atomicrmw xchg i8* @y, i8 %newval monotonic
ret i8 %0
; CHECK: AtomicSwap8:
@@ -195,31 +175,26 @@ entry:
; CHECK: andi $[[R3:[0-9]+]], $[[R0]], 3
; CHECK: sll $[[R4:[0-9]+]], $[[R3]], 3
; CHECK: ori $[[R5:[0-9]+]], $zero, 255
-; CHECK: sll $[[R6:[0-9]+]], $[[R5]], $[[R4]]
+; CHECK: sllv $[[R6:[0-9]+]], $[[R5]], $[[R4]]
; CHECK: nor $[[R7:[0-9]+]], $zero, $[[R6]]
-; CHECK: andi $[[R8:[0-9]+]], $4, 255
-; CHECK: sll $[[R9:[0-9]+]], $[[R8]], $[[R4]]
-; CHECK: sw $[[R9]], [[OFFSET:[0-9]+]]($sp)
+; CHECK: sllv $[[R9:[0-9]+]], $4, $[[R4]]
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $[[R10:[0-9]+]], 0($[[R2]])
-; CHECK: lw $[[R18:[0-9]+]], [[OFFSET]]($sp)
-; CHECK: or $[[R11:[0-9]+]], $zero, $[[R18]]
-; CHECK: and $[[R12:[0-9]+]], $[[R11]], $[[R6]]
; CHECK: and $[[R13:[0-9]+]], $[[R10]], $[[R7]]
-; CHECK: or $[[R14:[0-9]+]], $[[R13]], $[[R12]]
+; CHECK: or $[[R14:[0-9]+]], $[[R13]], $[[R9]]
; CHECK: sc $[[R14]], 0($[[R2]])
; CHECK: beq $[[R14]], $zero, $[[BB0]]
; CHECK: and $[[R15:[0-9]+]], $[[R10]], $[[R6]]
-; CHECK: srl $[[R16:[0-9]+]], $[[R15]], $[[R4]]
+; CHECK: srlv $[[R16:[0-9]+]], $[[R15]], $[[R4]]
; CHECK: sll $[[R17:[0-9]+]], $[[R16]], 24
; CHECK: sra $2, $[[R17]], 24
}
define signext i8 @AtomicCmpSwap8(i8 signext %oldval, i8 signext %newval) nounwind {
entry:
- %0 = call i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* @y, i8 %oldval, i8 %newval)
+ %0 = cmpxchg i8* @y, i8 %oldval, i8 %newval monotonic
ret i8 %0
; CHECK: AtomicCmpSwap8:
@@ -229,12 +204,12 @@ entry:
; CHECK: andi $[[R3:[0-9]+]], $[[R0]], 3
; CHECK: sll $[[R4:[0-9]+]], $[[R3]], 3
; CHECK: ori $[[R5:[0-9]+]], $zero, 255
-; CHECK: sll $[[R6:[0-9]+]], $[[R5]], $[[R4]]
+; CHECK: sllv $[[R6:[0-9]+]], $[[R5]], $[[R4]]
; CHECK: nor $[[R7:[0-9]+]], $zero, $[[R6]]
; CHECK: andi $[[R8:[0-9]+]], $4, 255
-; CHECK: sll $[[R9:[0-9]+]], $[[R8]], $[[R4]]
+; CHECK: sllv $[[R9:[0-9]+]], $[[R8]], $[[R4]]
; CHECK: andi $[[R10:[0-9]+]], $5, 255
-; CHECK: sll $[[R11:[0-9]+]], $[[R10]], $[[R4]]
+; CHECK: sllv $[[R11:[0-9]+]], $[[R10]], $[[R4]]
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $[[R12:[0-9]+]], 0($[[R2]])
@@ -247,7 +222,23 @@ entry:
; CHECK: beq $[[R15]], $zero, $[[BB0]]
; CHECK: $[[BB1]]:
-; CHECK: srl $[[R16:[0-9]+]], $[[R13]], $[[R4]]
+; CHECK: srlv $[[R16:[0-9]+]], $[[R13]], $[[R4]]
; CHECK: sll $[[R17:[0-9]+]], $[[R16]], 24
; CHECK: sra $2, $[[R17]], 24
}
+
+@countsint = common global i32 0, align 4
+
+define i32 @CheckSync(i32 %v) nounwind noinline {
+entry:
+ %0 = atomicrmw add i32* @countsint, i32 %v seq_cst
+ ret i32 %0
+
+; CHECK: CheckSync:
+; CHECK: sync 0
+; CHECK: ll
+; CHECK: sc
+; CHECK: beq
+; CHECK: sync 0
+}
+
diff --git a/test/CodeGen/Mips/brdelayslot.ll b/test/CodeGen/Mips/brdelayslot.ll
new file mode 100644
index 0000000..b266ce6
--- /dev/null
+++ b/test/CodeGen/Mips/brdelayslot.ll
@@ -0,0 +1,15 @@
+; RUN: llc -march=mipsel -enable-mips-delay-filler < %s | FileCheck %s
+
+define void @foo1() nounwind {
+entry:
+; CHECK: jalr
+; CHECK-NOT: nop
+; CHECK: jr
+; CHECK-NOT: nop
+; CHECK: .end
+
+ tail call void @foo2(i32 3) nounwind
+ ret void
+}
+
+declare void @foo2(i32)
diff --git a/test/CodeGen/Mips/cmov.ll b/test/CodeGen/Mips/cmov.ll
index ec37961..7851ba9 100755
--- a/test/CodeGen/Mips/cmov.ll
+++ b/test/CodeGen/Mips/cmov.ll
@@ -1,5 +1,5 @@
-; RUN: llc -march=mips -mcpu=4ke < %s | FileCheck %s
-; RUN: llc -march=mips -mcpu=4ke -regalloc=basic < %s | FileCheck %s
+; RUN: llc -march=mips < %s | FileCheck %s
+; RUN: llc -march=mips -regalloc=basic < %s | FileCheck %s
@i1 = global [3 x i32] [i32 1, i32 2, i32 3], align 4
@i3 = common global i32* null, align 4
diff --git a/test/CodeGen/Mips/constantfp0.ll b/test/CodeGen/Mips/constantfp0.ll
new file mode 100644
index 0000000..191f31d
--- /dev/null
+++ b/test/CodeGen/Mips/constantfp0.ll
@@ -0,0 +1,11 @@
+; RUN: llc -march=mips < %s | FileCheck %s
+
+define i32 @branch(double %d) nounwind readnone {
+entry:
+; CHECK: mtc1 $zero, $f[[R0:[0-9]+]]
+; CHECK: c.eq.d $f{{[0-9]+}}, $f[[R0]]
+
+ %tobool = fcmp une double %d, 0.000000e+00
+ %. = zext i1 %tobool to i32
+ ret i32 %.
+}
diff --git a/test/CodeGen/Mips/cprestore.ll b/test/CodeGen/Mips/cprestore.ll
new file mode 100644
index 0000000..391f5c7
--- /dev/null
+++ b/test/CodeGen/Mips/cprestore.ll
@@ -0,0 +1,20 @@
+; DISABLED: llc -march=mipsel < %s | FileCheck %s
+; RUN: false
+
+; byval is currently unsupported.
+; XFAIL: *
+
+; CHECK: .set macro
+; CHECK-NEXT: .cprestore
+; CHECK-NEXT: .set nomacro
+
+%struct.S = type { [16384 x i32] }
+
+define void @foo2() nounwind {
+entry:
+ %s = alloca %struct.S, align 4
+ call void @foo1(%struct.S* byval %s)
+ ret void
+}
+
+declare void @foo1(%struct.S* byval)
diff --git a/test/CodeGen/Mips/double2int.ll b/test/CodeGen/Mips/double2int.ll
index 3d033e1..445ccb3 100644
--- a/test/CodeGen/Mips/double2int.ll
+++ b/test/CodeGen/Mips/double2int.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=mips -mcpu=4ke < %s | FileCheck %s
+; RUN: llc -march=mips < %s | FileCheck %s
define i32 @f1(double %d) nounwind readnone {
entry:
diff --git a/test/CodeGen/Mips/eh.ll b/test/CodeGen/Mips/eh.ll
index 765b778..9cd3413 100644
--- a/test/CodeGen/Mips/eh.ll
+++ b/test/CodeGen/Mips/eh.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -march=mipsel -mcpu=4ke | FileCheck %s -check-prefix=CHECK-EL
-; RUN: llc < %s -march=mips -mcpu=4ke | FileCheck %s -check-prefix=CHECK-EB
+; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=CHECK-EL
+; RUN: llc < %s -march=mips | FileCheck %s -check-prefix=CHECK-EB
@g1 = global double 0.000000e+00, align 8
@_ZTId = external constant i8*
@@ -32,10 +32,12 @@ lpad: ; preds = %entry
; CHECK-EL: lw $gp
; CHECK-EL: beq $5
- %exn = tail call i8* @llvm.eh.exception() nounwind
- %eh.selector = tail call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTId to i8*)) nounwind
+ %exn.val = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ catch i8* bitcast (i8** @_ZTId to i8*)
+ %exn = extractvalue { i8*, i32 } %exn.val, 0
+ %sel = extractvalue { i8*, i32 } %exn.val, 1
%1 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*)) nounwind
- %2 = icmp eq i32 %eh.selector, %1
+ %2 = icmp eq i32 %sel, %1
br i1 %2, label %catch, label %eh.resume
catch: ; preds = %lpad
@@ -48,8 +50,7 @@ catch: ; preds = %lpad
ret void
eh.resume: ; preds = %lpad
- tail call void @llvm.eh.resume(i8* %exn, i32 %eh.selector) noreturn
- unreachable
+ resume { i8*, i32 } %exn.val
unreachable: ; preds = %entry
unreachable
diff --git a/test/CodeGen/Mips/extins.ll b/test/CodeGen/Mips/extins.ll
new file mode 100644
index 0000000..69f53e5
--- /dev/null
+++ b/test/CodeGen/Mips/extins.ll
@@ -0,0 +1,21 @@
+; RUN: llc -march=mips -mcpu=4ke < %s | FileCheck %s
+
+define i32 @ext0_5_9(i32 %s, i32 %pos, i32 %sz) nounwind readnone {
+entry:
+; CHECK: ext ${{[0-9]+}}, $4, 5, 9
+ %shr = lshr i32 %s, 5
+ %and = and i32 %shr, 511
+ ret i32 %and
+}
+
+define void @ins2_5_9(i32 %s, i32* nocapture %d) nounwind {
+entry:
+; CHECK: ins ${{[0-9]+}}, $4, 5, 9
+ %and = shl i32 %s, 5
+ %shl = and i32 %and, 16352
+ %tmp3 = load i32* %d, align 4
+ %and5 = and i32 %tmp3, -16353
+ %or = or i32 %and5, %shl
+ store i32 %or, i32* %d, align 4
+ ret void
+}
diff --git a/test/CodeGen/Mips/fcopysign.ll b/test/CodeGen/Mips/fcopysign.ll
index 14c6507..79f956d 100644
--- a/test/CodeGen/Mips/fcopysign.ll
+++ b/test/CodeGen/Mips/fcopysign.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -march=mipsel -mcpu=4ke | FileCheck %s -check-prefix=CHECK-EL
-; RUN: llc < %s -march=mips -mcpu=4ke | FileCheck %s -check-prefix=CHECK-EB
+; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=CHECK-EL
+; RUN: llc < %s -march=mips | FileCheck %s -check-prefix=CHECK-EB
define double @func0(double %d0, double %d1) nounwind readnone {
entry:
diff --git a/test/CodeGen/Mips/fpcmp.ll b/test/CodeGen/Mips/fpcmp.ll
index c89ffe6..86545e3 100644
--- a/test/CodeGen/Mips/fpcmp.ll
+++ b/test/CodeGen/Mips/fpcmp.ll
@@ -1,18 +1,13 @@
-; RUN: llc < %s -march=mipsel -mcpu=4ke | FileCheck %s -check-prefix=CHECK-MIPS32R2
-; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=CHECK-MIPS1
+; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=CHECK-MIPS32
@g1 = external global i32
define i32 @f(float %f0, float %f1) nounwind {
entry:
-; CHECK-MIPS32R2: c.olt.s
-; CHECK-MIPS32R2: movt
-; CHECK-MIPS32R2: c.olt.s
-; CHECK-MIPS32R2: movt
-; CHECK-MIPS1: c.olt.s
-; CHECK-MIPS1: bc1t
-; CHECK-MIPS1: c.olt.s
-; CHECK-MIPS1: bc1t
+; CHECK-MIPS32: c.olt.s
+; CHECK-MIPS32: movt
+; CHECK-MIPS32: c.olt.s
+; CHECK-MIPS32: movt
%cmp = fcmp olt float %f0, %f1
%conv = zext i1 %cmp to i32
%tmp2 = load i32* @g1, align 4
diff --git a/test/CodeGen/Mips/frame-address.ll b/test/CodeGen/Mips/frame-address.ll
index c48ce7e..9df1808 100644
--- a/test/CodeGen/Mips/frame-address.ll
+++ b/test/CodeGen/Mips/frame-address.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=mipsel -mcpu=mips2 < %s | FileCheck %s
+; RUN: llc -march=mipsel < %s | FileCheck %s
declare i8* @llvm.frameaddress(i32) nounwind readnone
diff --git a/test/CodeGen/Mips/i64arg.ll b/test/CodeGen/Mips/i64arg.ll
index 560f2e9..87cf2a6 100644
--- a/test/CodeGen/Mips/i64arg.ll
+++ b/test/CodeGen/Mips/i64arg.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=mips -mcpu=4ke < %s | FileCheck %s
+; RUN: llc -march=mips < %s | FileCheck %s
define void @f1(i64 %ll1, float %f, i64 %ll, i32 %i, float %f2) nounwind {
entry:
diff --git a/test/CodeGen/Mips/inlineasmmemop.ll b/test/CodeGen/Mips/inlineasmmemop.ll
index c565892..b5db58a 100644
--- a/test/CodeGen/Mips/inlineasmmemop.ll
+++ b/test/CodeGen/Mips/inlineasmmemop.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=mipsel -mcpu=4ke < %s | FileCheck %s
+; RUN: llc -march=mipsel < %s | FileCheck %s
@g1 = external global i32
diff --git a/test/CodeGen/Mips/internalfunc.ll b/test/CodeGen/Mips/internalfunc.ll
index c2a4e5c..434b386 100644
--- a/test/CodeGen/Mips/internalfunc.ll
+++ b/test/CodeGen/Mips/internalfunc.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -march=mipsel -mcpu=4ke | FileCheck %s
+; RUN: llc < %s -march=mipsel | FileCheck %s
@caller.sf1 = internal unnamed_addr global void (...)* null, align 4
@gf1 = external global void (...)*
diff --git a/test/CodeGen/Mips/largeimmprinting.ll b/test/CodeGen/Mips/largeimmprinting.ll
index fcc20f7..579a319 100644
--- a/test/CodeGen/Mips/largeimmprinting.ll
+++ b/test/CodeGen/Mips/largeimmprinting.ll
@@ -1,4 +1,8 @@
-; RUN: llc -march=mipsel -mcpu=4ke < %s | FileCheck %s
+; DISABLED: llc -march=mipsel -mcpu=4ke < %s | FileCheck %s
+; RUN: false
+
+; byval is currently unsupported.
+; XFAIL: *
%struct.S1 = type { [65536 x i8] }
diff --git a/test/CodeGen/Mips/madd-msub.ll b/test/CodeGen/Mips/madd-msub.ll
index 4a205b1..0aeabb3 100644
--- a/test/CodeGen/Mips/madd-msub.ll
+++ b/test/CodeGen/Mips/madd-msub.ll
@@ -1,6 +1,6 @@
-; RUN: llc -march=mips -mcpu=4ke < %s | FileCheck %s
+; RUN: llc -march=mips < %s | FileCheck %s
-; CHECK: madd $5, $4
+; CHECK: madd
define i64 @madd1(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = sext i32 %a to i64
@@ -11,7 +11,7 @@ entry:
ret i64 %add
}
-; CHECK: maddu $5, $4
+; CHECK: maddu
define i64 @madd2(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = zext i32 %a to i64
@@ -22,7 +22,7 @@ entry:
ret i64 %add
}
-; CHECK: madd $5, $4
+; CHECK: madd
define i64 @madd3(i32 %a, i32 %b, i64 %c) nounwind readnone {
entry:
%conv = sext i32 %a to i64
@@ -32,7 +32,7 @@ entry:
ret i64 %add
}
-; CHECK: msub $5, $4
+; CHECK: msub
define i64 @msub1(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = sext i32 %c to i64
@@ -43,7 +43,7 @@ entry:
ret i64 %sub
}
-; CHECK: msubu $5, $4
+; CHECK: msubu
define i64 @msub2(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = zext i32 %c to i64
@@ -54,7 +54,7 @@ entry:
ret i64 %sub
}
-; CHECK: msub $5, $4
+; CHECK: msub
define i64 @msub3(i32 %a, i32 %b, i64 %c) nounwind readnone {
entry:
%conv = sext i32 %a to i64
diff --git a/test/CodeGen/Mips/mips64fpldst.ll b/test/CodeGen/Mips/mips64fpldst.ll
new file mode 100644
index 0000000..b8f3ca9
--- /dev/null
+++ b/test/CodeGen/Mips/mips64fpldst.ll
@@ -0,0 +1,58 @@
+; RUN: llc < %s -march=mips64el -mcpu=mips64r1 -mattr=n64 | FileCheck %s -check-prefix=CHECK-N64
+; RUN: llc < %s -march=mips64el -mcpu=mips64r1 -mattr=n32 | FileCheck %s -check-prefix=CHECK-N32
+
+@f0 = common global float 0.000000e+00, align 4
+@d0 = common global double 0.000000e+00, align 8
+@f1 = common global float 0.000000e+00, align 4
+@d1 = common global double 0.000000e+00, align 8
+
+define float @funcfl1() nounwind readonly {
+entry:
+; CHECK-N64: funcfl1
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(f0)
+; CHECK-N64: lwc1 $f{{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: funcfl1
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(f0)
+; CHECK-N32: lwc1 $f{{[0-9]+}}, 0($[[R0]])
+ %0 = load float* @f0, align 4
+ ret float %0
+}
+
+define double @funcfl2() nounwind readonly {
+entry:
+; CHECK-N64: funcfl2
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(d0)
+; CHECK-N64: ldc1 $f{{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: funcfl2
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(d0)
+; CHECK-N32: ldc1 $f{{[0-9]+}}, 0($[[R0]])
+ %0 = load double* @d0, align 8
+ ret double %0
+}
+
+define void @funcfs1() nounwind {
+entry:
+; CHECK-N64: funcfs1
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(f0)
+; CHECK-N64: swc1 $f{{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: funcfs1
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(f0)
+; CHECK-N32: swc1 $f{{[0-9]+}}, 0($[[R0]])
+ %0 = load float* @f1, align 4
+ store float %0, float* @f0, align 4
+ ret void
+}
+
+define void @funcfs2() nounwind {
+entry:
+; CHECK-N64: funcfs2
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(d0)
+; CHECK-N64: sdc1 $f{{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: funcfs2
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(d0)
+; CHECK-N32: sdc1 $f{{[0-9]+}}, 0($[[R0]])
+ %0 = load double* @d1, align 8
+ store double %0, double* @d0, align 8
+ ret void
+}
+
diff --git a/test/CodeGen/Mips/mips64instrs.ll b/test/CodeGen/Mips/mips64instrs.ll
new file mode 100644
index 0000000..c9812a2
--- /dev/null
+++ b/test/CodeGen/Mips/mips64instrs.ll
@@ -0,0 +1,143 @@
+; RUN: llc -march=mips64el -mcpu=mips64r1 < %s | FileCheck %s
+
+define i64 @f0(i64 %a0, i64 %a1) nounwind readnone {
+entry:
+; CHECK: daddu
+ %add = add nsw i64 %a1, %a0
+ ret i64 %add
+}
+
+define i64 @f1(i64 %a0, i64 %a1) nounwind readnone {
+entry:
+; CHECK: dsubu
+ %sub = sub nsw i64 %a0, %a1
+ ret i64 %sub
+}
+
+define i64 @f4(i64 %a0, i64 %a1) nounwind readnone {
+entry:
+; CHECK: and
+ %and = and i64 %a1, %a0
+ ret i64 %and
+}
+
+define i64 @f5(i64 %a0, i64 %a1) nounwind readnone {
+entry:
+; CHECK: or
+ %or = or i64 %a1, %a0
+ ret i64 %or
+}
+
+define i64 @f6(i64 %a0, i64 %a1) nounwind readnone {
+entry:
+; CHECK: xor
+ %xor = xor i64 %a1, %a0
+ ret i64 %xor
+}
+
+define i64 @f7(i64 %a0) nounwind readnone {
+entry:
+; CHECK: daddiu ${{[0-9]+}}, ${{[0-9]+}}, 20
+ %add = add nsw i64 %a0, 20
+ ret i64 %add
+}
+
+define i64 @f8(i64 %a0) nounwind readnone {
+entry:
+; CHECK: daddiu ${{[0-9]+}}, ${{[0-9]+}}, -20
+ %sub = add nsw i64 %a0, -20
+ ret i64 %sub
+}
+
+define i64 @f9(i64 %a0) nounwind readnone {
+entry:
+; CHECK: andi ${{[0-9]+}}, ${{[0-9]+}}, 20
+ %and = and i64 %a0, 20
+ ret i64 %and
+}
+
+define i64 @f10(i64 %a0) nounwind readnone {
+entry:
+; CHECK: ori ${{[0-9]+}}, ${{[0-9]+}}, 20
+ %or = or i64 %a0, 20
+ ret i64 %or
+}
+
+define i64 @f11(i64 %a0) nounwind readnone {
+entry:
+; CHECK: xori ${{[0-9]+}}, ${{[0-9]+}}, 20
+ %xor = xor i64 %a0, 20
+ ret i64 %xor
+}
+
+define i64 @f12(i64 %a, i64 %b) nounwind readnone {
+entry:
+; CHECK: mult
+ %mul = mul nsw i64 %b, %a
+ ret i64 %mul
+}
+
+define i64 @f13(i64 %a, i64 %b) nounwind readnone {
+entry:
+; CHECK: mult
+ %mul = mul i64 %b, %a
+ ret i64 %mul
+}
+
+define i64 @f14(i64 %a, i64 %b) nounwind readnone {
+entry:
+; CHECK: ddiv $zero
+; CHECK: mflo
+ %div = sdiv i64 %a, %b
+ ret i64 %div
+}
+
+define i64 @f15(i64 %a, i64 %b) nounwind readnone {
+entry:
+; CHECK: ddivu $zero
+; CHECK: mflo
+ %div = udiv i64 %a, %b
+ ret i64 %div
+}
+
+define i64 @f16(i64 %a, i64 %b) nounwind readnone {
+entry:
+; CHECK: ddiv $zero
+; CHECK: mfhi
+ %rem = srem i64 %a, %b
+ ret i64 %rem
+}
+
+define i64 @f17(i64 %a, i64 %b) nounwind readnone {
+entry:
+; CHECK: ddivu $zero
+; CHECK: mfhi
+ %rem = urem i64 %a, %b
+ ret i64 %rem
+}
+
+declare i64 @llvm.ctlz.i64(i64) nounwind readnone
+
+define i64 @f18(i64 %X) nounwind readnone {
+entry:
+; CHECK: dclz $2, $4
+ %tmp1 = tail call i64 @llvm.ctlz.i64(i64 %X)
+ ret i64 %tmp1
+}
+
+define i64 @f19(i64 %X) nounwind readnone {
+entry:
+; CHECK: dclo $2, $4
+ %neg = xor i64 %X, -1
+ %tmp1 = tail call i64 @llvm.ctlz.i64(i64 %neg)
+ ret i64 %tmp1
+}
+
+define i64 @f20(i64 %a, i64 %b) nounwind readnone {
+entry:
+; CHECK: nor
+ %or = or i64 %b, %a
+ %neg = xor i64 %or, -1
+ ret i64 %neg
+}
+
diff --git a/test/CodeGen/Mips/mips64intldst.ll b/test/CodeGen/Mips/mips64intldst.ll
new file mode 100644
index 0000000..fdf496b
--- /dev/null
+++ b/test/CodeGen/Mips/mips64intldst.ll
@@ -0,0 +1,157 @@
+; RUN: llc < %s -march=mips64el -mcpu=mips64r1 -mattr=n64 | FileCheck %s -check-prefix=CHECK-N64
+; RUN: llc < %s -march=mips64el -mcpu=mips64r1 -mattr=n32 | FileCheck %s -check-prefix=CHECK-N32
+
+@c = common global i8 0, align 4
+@s = common global i16 0, align 4
+@i = common global i32 0, align 4
+@l = common global i64 0, align 8
+@uc = common global i8 0, align 4
+@us = common global i16 0, align 4
+@ui = common global i32 0, align 4
+@l1 = common global i64 0, align 8
+
+define i64 @func1() nounwind readonly {
+entry:
+; CHECK-N64: func1
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(c)
+; CHECK-N64: lb ${{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: func1
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(c)
+; CHECK-N32: lb ${{[0-9]+}}, 0($[[R0]])
+ %0 = load i8* @c, align 4
+ %conv = sext i8 %0 to i64
+ ret i64 %conv
+}
+
+define i64 @func2() nounwind readonly {
+entry:
+; CHECK-N64: func2
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(s)
+; CHECK-N64: lh ${{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: func2
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(s)
+; CHECK-N32: lh ${{[0-9]+}}, 0($[[R0]])
+ %0 = load i16* @s, align 4
+ %conv = sext i16 %0 to i64
+ ret i64 %conv
+}
+
+define i64 @func3() nounwind readonly {
+entry:
+; CHECK-N64: func3
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(i)
+; CHECK-N64: lw ${{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: func3
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(i)
+; CHECK-N32: lw ${{[0-9]+}}, 0($[[R0]])
+ %0 = load i32* @i, align 4
+ %conv = sext i32 %0 to i64
+ ret i64 %conv
+}
+
+define i64 @func4() nounwind readonly {
+entry:
+; CHECK-N64: func4
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(l)
+; CHECK-N64: ld ${{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: func4
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(l)
+; CHECK-N32: ld ${{[0-9]+}}, 0($[[R0]])
+ %0 = load i64* @l, align 8
+ ret i64 %0
+}
+
+define i64 @ufunc1() nounwind readonly {
+entry:
+; CHECK-N64: ufunc1
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(uc)
+; CHECK-N64: lbu ${{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: ufunc1
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(uc)
+; CHECK-N32: lbu ${{[0-9]+}}, 0($[[R0]])
+ %0 = load i8* @uc, align 4
+ %conv = zext i8 %0 to i64
+ ret i64 %conv
+}
+
+define i64 @ufunc2() nounwind readonly {
+entry:
+; CHECK-N64: ufunc2
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(us)
+; CHECK-N64: lhu ${{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: ufunc2
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(us)
+; CHECK-N32: lhu ${{[0-9]+}}, 0($[[R0]])
+ %0 = load i16* @us, align 4
+ %conv = zext i16 %0 to i64
+ ret i64 %conv
+}
+
+define i64 @ufunc3() nounwind readonly {
+entry:
+; CHECK-N64: ufunc3
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(ui)
+; CHECK-N64: lwu ${{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: ufunc3
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(ui)
+; CHECK-N32: lwu ${{[0-9]+}}, 0($[[R0]])
+ %0 = load i32* @ui, align 4
+ %conv = zext i32 %0 to i64
+ ret i64 %conv
+}
+
+define void @sfunc1() nounwind {
+entry:
+; CHECK-N64: sfunc1
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(c)
+; CHECK-N64: sb ${{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: sfunc1
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(c)
+; CHECK-N32: sb ${{[0-9]+}}, 0($[[R0]])
+ %0 = load i64* @l1, align 8
+ %conv = trunc i64 %0 to i8
+ store i8 %conv, i8* @c, align 4
+ ret void
+}
+
+define void @sfunc2() nounwind {
+entry:
+; CHECK-N64: sfunc2
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(s)
+; CHECK-N64: sh ${{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: sfunc2
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(s)
+; CHECK-N32: sh ${{[0-9]+}}, 0($[[R0]])
+ %0 = load i64* @l1, align 8
+ %conv = trunc i64 %0 to i16
+ store i16 %conv, i16* @s, align 4
+ ret void
+}
+
+define void @sfunc3() nounwind {
+entry:
+; CHECK-N64: sfunc3
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(i)
+; CHECK-N64: sw ${{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: sfunc3
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(i)
+; CHECK-N32: sw ${{[0-9]+}}, 0($[[R0]])
+ %0 = load i64* @l1, align 8
+ %conv = trunc i64 %0 to i32
+ store i32 %conv, i32* @i, align 4
+ ret void
+}
+
+define void @sfunc4() nounwind {
+entry:
+; CHECK-N64: sfunc4
+; CHECK-N64: ld $[[R0:[0-9]+]], %got_disp(l)
+; CHECK-N64: sd ${{[0-9]+}}, 0($[[R0]])
+; CHECK-N32: sfunc4
+; CHECK-N32: lw $[[R0:[0-9]+]], %got(l)
+; CHECK-N32: sd ${{[0-9]+}}, 0($[[R0]])
+ %0 = load i64* @l1, align 8
+ store i64 %0, i64* @l, align 8
+ ret void
+}
+
diff --git a/test/CodeGen/Mips/mips64shift.ll b/test/CodeGen/Mips/mips64shift.ll
new file mode 100644
index 0000000..cc5e508
--- /dev/null
+++ b/test/CodeGen/Mips/mips64shift.ll
@@ -0,0 +1,104 @@
+; RUN: llc -march=mips64el -mcpu=mips64r2 < %s | FileCheck %s
+
+define i64 @f0(i64 %a0, i64 %a1) nounwind readnone {
+entry:
+; CHECK: dsllv
+ %shl = shl i64 %a0, %a1
+ ret i64 %shl
+}
+
+define i64 @f1(i64 %a0, i64 %a1) nounwind readnone {
+entry:
+; CHECK: dsrav
+ %shr = ashr i64 %a0, %a1
+ ret i64 %shr
+}
+
+define i64 @f2(i64 %a0, i64 %a1) nounwind readnone {
+entry:
+; CHECK: dsrlv
+ %shr = lshr i64 %a0, %a1
+ ret i64 %shr
+}
+
+define i64 @f3(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsll ${{[0-9]+}}, ${{[0-9]+}}, 10
+ %shl = shl i64 %a0, 10
+ ret i64 %shl
+}
+
+define i64 @f4(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsra ${{[0-9]+}}, ${{[0-9]+}}, 10
+ %shr = ashr i64 %a0, 10
+ ret i64 %shr
+}
+
+define i64 @f5(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsrl ${{[0-9]+}}, ${{[0-9]+}}, 10
+ %shr = lshr i64 %a0, 10
+ ret i64 %shr
+}
+
+define i64 @f6(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsll32 ${{[0-9]+}}, ${{[0-9]+}}, 8
+ %shl = shl i64 %a0, 40
+ ret i64 %shl
+}
+
+define i64 @f7(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsra32 ${{[0-9]+}}, ${{[0-9]+}}, 8
+ %shr = ashr i64 %a0, 40
+ ret i64 %shr
+}
+
+define i64 @f8(i64 %a0) nounwind readnone {
+entry:
+; CHECK: dsrl32 ${{[0-9]+}}, ${{[0-9]+}}, 8
+ %shr = lshr i64 %a0, 40
+ ret i64 %shr
+}
+
+define i64 @f9(i64 %a0, i64 %a1) nounwind readnone {
+entry:
+; CHECK: drotrv
+ %shr = lshr i64 %a0, %a1
+ %sub = sub i64 64, %a1
+ %shl = shl i64 %a0, %sub
+ %or = or i64 %shl, %shr
+ ret i64 %or
+}
+
+define i64 @f10(i64 %a0, i64 %a1) nounwind readnone {
+entry:
+; CHECK: drotrv
+ %shl = shl i64 %a0, %a1
+ %sub = sub i64 64, %a1
+ %shr = lshr i64 %a0, %sub
+ %or = or i64 %shr, %shl
+ ret i64 %or
+}
+
+define i64 @f11(i64 %a0) nounwind readnone {
+entry:
+; CHECK: drotr ${{[0-9]+}}, ${{[0-9]+}}, 10
+ %shr = lshr i64 %a0, 10
+ %shl = shl i64 %a0, 54
+ %or = or i64 %shr, %shl
+ ret i64 %or
+}
+
+define i64 @f12(i64 %a0) nounwind readnone {
+entry:
+; CHECK: drotr32 ${{[0-9]+}}, ${{[0-9]+}}, 22
+ %shl = shl i64 %a0, 10
+ %shr = lshr i64 %a0, 54
+ %or = or i64 %shl, %shr
+ ret i64 %or
+}
+
+
diff --git a/test/CodeGen/Mips/mipslopat.ll b/test/CodeGen/Mips/mipslopat.ll
new file mode 100644
index 0000000..0279828
--- /dev/null
+++ b/test/CodeGen/Mips/mipslopat.ll
@@ -0,0 +1,19 @@
+; This test does not check the machine code output.
+; RUN: llc -march=mips < %s
+
+@stat_vol_ptr_int = internal global i32* null, align 4
+@stat_ptr_vol_int = internal global i32* null, align 4
+
+define void @simple_vol_file() nounwind {
+entry:
+ %tmp = volatile load i32** @stat_vol_ptr_int, align 4
+ %0 = bitcast i32* %tmp to i8*
+ call void @llvm.prefetch(i8* %0, i32 0, i32 0, i32 1)
+ %tmp1 = load i32** @stat_ptr_vol_int, align 4
+ %1 = bitcast i32* %tmp1 to i8*
+ call void @llvm.prefetch(i8* %1, i32 0, i32 0, i32 1)
+ ret void
+}
+
+declare void @llvm.prefetch(i8* nocapture, i32, i32, i32) nounwind
+
diff --git a/test/CodeGen/Mips/o32_cc.ll b/test/CodeGen/Mips/o32_cc.ll
index 3974cd4..70b66ef 100644
--- a/test/CodeGen/Mips/o32_cc.ll
+++ b/test/CodeGen/Mips/o32_cc.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=mips -mcpu=4ke < %s | FileCheck %s
+; RUN: llc -march=mips < %s | FileCheck %s
; FIXME: Disabled because it unpredictably fails on certain platforms.
; REQUIRES: disabled
diff --git a/test/CodeGen/Mips/o32_cc_byval.ll b/test/CodeGen/Mips/o32_cc_byval.ll
index f5e1a87..e673480 100644
--- a/test/CodeGen/Mips/o32_cc_byval.ll
+++ b/test/CodeGen/Mips/o32_cc_byval.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=mipsel -mcpu=4ke < %s | FileCheck %s
+; RUN: llc -march=mipsel < %s | FileCheck %s
%0 = type { i8, i16, i32, i64, double, i32, [4 x i8] }
%struct.S1 = type { i8, i16, i32, i64, double, i32 }
diff --git a/test/CodeGen/Mips/o32_cc_vararg.ll b/test/CodeGen/Mips/o32_cc_vararg.ll
index 14ce04b..4a3d9ab 100644
--- a/test/CodeGen/Mips/o32_cc_vararg.ll
+++ b/test/CodeGen/Mips/o32_cc_vararg.ll
@@ -1,4 +1,4 @@
-; RUN: llc -march=mipsel -mcpu=mips2 -pre-RA-sched=source < %s | FileCheck %s
+; RUN: llc -march=mipsel -pre-RA-sched=source < %s | FileCheck %s
; All test functions do the same thing - they return the first variable
diff --git a/test/CodeGen/Mips/rotate.ll b/test/CodeGen/Mips/rotate.ll
index e7dc309..8e27f4a 100644
--- a/test/CodeGen/Mips/rotate.ll
+++ b/test/CodeGen/Mips/rotate.ll
@@ -1,6 +1,6 @@
; RUN: llc -march=mips -mcpu=4ke < %s | FileCheck %s
-; CHECK: rotrv $2, $4, $2
+; CHECK: rotrv $2, $4
define i32 @rot0(i32 %a, i32 %b) nounwind readnone {
entry:
%shl = shl i32 %a, %b
diff --git a/test/CodeGen/Mips/select.ll b/test/CodeGen/Mips/select.ll
index c83fa3e..40115be 100644
--- a/test/CodeGen/Mips/select.ll
+++ b/test/CodeGen/Mips/select.ll
@@ -1,13 +1,11 @@
-; RUN: llc < %s -march=mipsel -mcpu=4ke | FileCheck %s -check-prefix=CHECK-MIPS32R2
-; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=CHECK-MIPS1
+; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=CHECK
@d2 = external global double
@d3 = external global double
define i32 @sel1(i32 %s, i32 %f0, i32 %f1) nounwind readnone {
entry:
-; CHECK-MIPS32R2: movn
-; CHECK-MIPS1: beq
+; CHECK: movn
%tobool = icmp ne i32 %s, 0
%cond = select i1 %tobool, i32 %f1, i32 %f0
ret i32 %cond
@@ -15,8 +13,7 @@ entry:
define float @sel2(i32 %s, float %f0, float %f1) nounwind readnone {
entry:
-; CHECK-MIPS32R2: movn.s
-; CHECK-MIPS1: beq
+; CHECK: movn.s
%tobool = icmp ne i32 %s, 0
%cond = select i1 %tobool, float %f0, float %f1
ret float %cond
@@ -24,8 +21,7 @@ entry:
define double @sel2_1(i32 %s, double %f0, double %f1) nounwind readnone {
entry:
-; CHECK-MIPS32R2: movn.d
-; CHECK-MIPS1: beq
+; CHECK: movn.d
%tobool = icmp ne i32 %s, 0
%cond = select i1 %tobool, double %f0, double %f1
ret double %cond
@@ -33,10 +29,8 @@ entry:
define float @sel3(float %f0, float %f1, float %f2, float %f3) nounwind readnone {
entry:
-; CHECK-MIPS32R2: c.eq.s
-; CHECK-MIPS32R2: movt.s
-; CHECK-MIPS1: c.eq.s
-; CHECK-MIPS1: bc1f
+; CHECK: c.eq.s
+; CHECK: movt.s
%cmp = fcmp oeq float %f2, %f3
%cond = select i1 %cmp, float %f0, float %f1
ret float %cond
@@ -44,10 +38,8 @@ entry:
define float @sel4(float %f0, float %f1, float %f2, float %f3) nounwind readnone {
entry:
-; CHECK-MIPS32R2: c.olt.s
-; CHECK-MIPS32R2: movt.s
-; CHECK-MIPS1: c.olt.s
-; CHECK-MIPS1: bc1f
+; CHECK: c.olt.s
+; CHECK: movt.s
%cmp = fcmp olt float %f2, %f3
%cond = select i1 %cmp, float %f0, float %f1
ret float %cond
@@ -55,10 +47,8 @@ entry:
define float @sel5(float %f0, float %f1, float %f2, float %f3) nounwind readnone {
entry:
-; CHECK-MIPS32R2: c.ule.s
-; CHECK-MIPS32R2: movf.s
-; CHECK-MIPS1: c.ule.s
-; CHECK-MIPS1: bc1t
+; CHECK: c.ule.s
+; CHECK: movf.s
%cmp = fcmp ogt float %f2, %f3
%cond = select i1 %cmp, float %f0, float %f1
ret float %cond
@@ -66,10 +56,8 @@ entry:
define double @sel5_1(double %f0, double %f1, float %f2, float %f3) nounwind readnone {
entry:
-; CHECK-MIPS32R2: c.ule.s
-; CHECK-MIPS32R2: movf.d
-; CHECK-MIPS1: c.ule.s
-; CHECK-MIPS1: bc1t
+; CHECK: c.ule.s
+; CHECK: movf.d
%cmp = fcmp ogt float %f2, %f3
%cond = select i1 %cmp, double %f0, double %f1
ret double %cond
@@ -77,10 +65,8 @@ entry:
define double @sel6(double %f0, double %f1, double %f2, double %f3) nounwind readnone {
entry:
-; CHECK-MIPS32R2: c.eq.d
-; CHECK-MIPS32R2: movt.d
-; CHECK-MIPS1: c.eq.d
-; CHECK-MIPS1: bc1f
+; CHECK: c.eq.d
+; CHECK: movt.d
%cmp = fcmp oeq double %f2, %f3
%cond = select i1 %cmp, double %f0, double %f1
ret double %cond
@@ -88,10 +74,8 @@ entry:
define double @sel7(double %f0, double %f1, double %f2, double %f3) nounwind readnone {
entry:
-; CHECK-MIPS32R2: c.olt.d
-; CHECK-MIPS32R2: movt.d
-; CHECK-MIPS1: c.olt.d
-; CHECK-MIPS1: bc1f
+; CHECK: c.olt.d
+; CHECK: movt.d
%cmp = fcmp olt double %f2, %f3
%cond = select i1 %cmp, double %f0, double %f1
ret double %cond
@@ -99,10 +83,8 @@ entry:
define double @sel8(double %f0, double %f1, double %f2, double %f3) nounwind readnone {
entry:
-; CHECK-MIPS32R2: c.ule.d
-; CHECK-MIPS32R2: movf.d
-; CHECK-MIPS1: c.ule.d
-; CHECK-MIPS1: bc1t
+; CHECK: c.ule.d
+; CHECK: movf.d
%cmp = fcmp ogt double %f2, %f3
%cond = select i1 %cmp, double %f0, double %f1
ret double %cond
@@ -110,10 +92,8 @@ entry:
define float @sel8_1(float %f0, float %f1, double %f2, double %f3) nounwind readnone {
entry:
-; CHECK-MIPS32R2: c.ule.d
-; CHECK-MIPS32R2: movf.s
-; CHECK-MIPS1: c.ule.d
-; CHECK-MIPS1: bc1t
+; CHECK: c.ule.d
+; CHECK: movf.s
%cmp = fcmp ogt double %f2, %f3
%cond = select i1 %cmp, float %f0, float %f1
ret float %cond
@@ -121,10 +101,8 @@ entry:
define i32 @sel9(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone {
entry:
-; CHECK-MIPS32R2: c.eq.s
-; CHECK-MIPS32R2: movt
-; CHECK-MIPS1: c.eq.s
-; CHECK-MIPS1: bc1f
+; CHECK: c.eq.s
+; CHECK: movt
%cmp = fcmp oeq float %f2, %f3
%cond = select i1 %cmp, i32 %f0, i32 %f1
ret i32 %cond
@@ -132,10 +110,8 @@ entry:
define i32 @sel10(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone {
entry:
-; CHECK-MIPS32R2: c.olt.s
-; CHECK-MIPS32R2: movt
-; CHECK-MIPS1: c.olt.s
-; CHECK-MIPS1: bc1f
+; CHECK: c.olt.s
+; CHECK: movt
%cmp = fcmp olt float %f2, %f3
%cond = select i1 %cmp, i32 %f0, i32 %f1
ret i32 %cond
@@ -143,10 +119,8 @@ entry:
define i32 @sel11(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone {
entry:
-; CHECK-MIPS32R2: c.ule.s
-; CHECK-MIPS32R2: movf
-; CHECK-MIPS1: c.ule.s
-; CHECK-MIPS1: bc1t
+; CHECK: c.ule.s
+; CHECK: movf
%cmp = fcmp ogt float %f2, %f3
%cond = select i1 %cmp, i32 %f0, i32 %f1
ret i32 %cond
@@ -154,10 +128,8 @@ entry:
define i32 @sel12(i32 %f0, i32 %f1) nounwind readonly {
entry:
-; CHECK-MIPS32R2: c.eq.d
-; CHECK-MIPS32R2: movt
-; CHECK-MIPS1: c.eq.d
-; CHECK-MIPS1: bc1f
+; CHECK: c.eq.d
+; CHECK: movt
%tmp = load double* @d2, align 8, !tbaa !0
%tmp1 = load double* @d3, align 8, !tbaa !0
%cmp = fcmp oeq double %tmp, %tmp1
@@ -167,10 +139,8 @@ entry:
define i32 @sel13(i32 %f0, i32 %f1) nounwind readonly {
entry:
-; CHECK-MIPS32R2: c.olt.d
-; CHECK-MIPS32R2: movt
-; CHECK-MIPS1: c.olt.d
-; CHECK-MIPS1: bc1f
+; CHECK: c.olt.d
+; CHECK: movt
%tmp = load double* @d2, align 8, !tbaa !0
%tmp1 = load double* @d3, align 8, !tbaa !0
%cmp = fcmp olt double %tmp, %tmp1
@@ -180,10 +150,8 @@ entry:
define i32 @sel14(i32 %f0, i32 %f1) nounwind readonly {
entry:
-; CHECK-MIPS32R2: c.ule.d
-; CHECK-MIPS32R2: movf
-; CHECK-MIPS1: c.ule.d
-; CHECK-MIPS1: bc1t
+; CHECK: c.ule.d
+; CHECK: movf
%tmp = load double* @d2, align 8, !tbaa !0
%tmp1 = load double* @d3, align 8, !tbaa !0
%cmp = fcmp ogt double %tmp, %tmp1
diff --git a/test/CodeGen/Mips/tls.ll b/test/CodeGen/Mips/tls.ll
index 034738b..b0474b4 100644
--- a/test/CodeGen/Mips/tls.ll
+++ b/test/CodeGen/Mips/tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc -march=mipsel -mcpu=mips2 < %s | FileCheck %s -check-prefix=PIC
-; RUN: llc -march=mipsel -mcpu=mips2 -relocation-model=static < %s \
+; RUN: llc -march=mipsel < %s | FileCheck %s -check-prefix=PIC
+; RUN: llc -march=mipsel -relocation-model=static < %s \
; RUN: | FileCheck %s -check-prefix=STATIC
diff --git a/test/CodeGen/Mips/unalignedload.ll b/test/CodeGen/Mips/unalignedload.ll
new file mode 100644
index 0000000..433e896
--- /dev/null
+++ b/test/CodeGen/Mips/unalignedload.ll
@@ -0,0 +1,41 @@
+; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=CHECK-EL
+; RUN: llc < %s -march=mips | FileCheck %s -check-prefix=CHECK-EB
+%struct.S2 = type { %struct.S1, %struct.S1 }
+%struct.S1 = type { i8, i8 }
+%struct.S4 = type { [7 x i8] }
+
+@s2 = common global %struct.S2 zeroinitializer, align 1
+@s4 = common global %struct.S4 zeroinitializer, align 1
+
+define void @foo1() nounwind {
+entry:
+; CHECK-EL: lw $25, %call16(foo2)
+; CHECK-EL: ulhu $4, 2
+; CHECK-EL: lw $[[R0:[0-9]+]], %got(s4)
+; CHECK-EL: lbu $[[R1:[0-9]+]], 6($[[R0]])
+; CHECK-EL: ulhu $[[R2:[0-9]+]], 4($[[R0]])
+; CHECK-EL: sll $[[R3:[0-9]+]], $[[R1]], 16
+; CHECK-EL: ulw $4, 0($[[R0]])
+; CHECK-EL: lw $25, %call16(foo4)
+; CHECK-EL: or $5, $[[R2]], $[[R3]]
+
+; CHECK-EB: ulhu $[[R0:[0-9]+]], 2
+; CHECK-EB: lw $25, %call16(foo2)
+; CHECK-EB: sll $4, $[[R0]], 16
+; CHECK-EB: lw $[[R1:[0-9]+]], %got(s4)
+; CHECK-EB: ulhu $[[R2:[0-9]+]], 4($[[R1]])
+; CHECK-EB: lbu $[[R3:[0-9]+]], 6($[[R1]])
+; CHECK-EB: sll $[[R4:[0-9]+]], $[[R2]], 16
+; CHECK-EB: sll $[[R5:[0-9]+]], $[[R3]], 8
+; CHECK-EB: ulw $4, 0($[[R1]])
+; CHECK-EB: lw $25, %call16(foo4)
+; CHECK-EB: or $5, $[[R4]], $[[R5]]
+
+ tail call void @foo2(%struct.S1* byval getelementptr inbounds (%struct.S2* @s2, i32 0, i32 1)) nounwind
+ tail call void @foo4(%struct.S4* byval @s4) nounwind
+ ret void
+}
+
+declare void @foo2(%struct.S1* byval)
+
+declare void @foo4(%struct.S4* byval)
diff --git a/test/CodeGen/PTX/20110926-sitofp.ll b/test/CodeGen/PTX/20110926-sitofp.ll
new file mode 100644
index 0000000..38d35c5
--- /dev/null
+++ b/test/CodeGen/PTX/20110926-sitofp.ll
@@ -0,0 +1,24 @@
+; RUN: llc < %s -march=ptx32 | FileCheck %s
+
+@A = common global [1536 x [1536 x float]] zeroinitializer, align 4
+@B = common global [1536 x [1536 x float]] zeroinitializer, align 4
+
+define internal ptx_device void @init_array(i32 %x, i32 %y) {
+ %arrayidx103 = getelementptr [1536 x [1536 x float]]* @A, i32 0, i32 %x, i32 %y
+ %arrayidx224 = getelementptr [1536 x [1536 x float]]* @B, i32 0, i32 %x, i32 %y
+ %mul5 = mul i32 %x, %y
+ %rem = srem i32 %mul5, 1024
+ %add = add nsw i32 %rem, 1
+; CHECK: cvt.rn.f64.s32 %fd{{[0-9]+}}, %r{{[0-9]+}}
+ %conv = sitofp i32 %add to double
+ %div = fmul double %conv, 5.000000e-01
+ %conv7 = fptrunc double %div to float
+ store float %conv7, float* %arrayidx103, align 4
+ %rem14 = srem i32 %mul5, 1024
+ %add15 = add nsw i32 %rem14, 1
+ %conv16 = sitofp i32 %add15 to double
+ %div17 = fmul double %conv16, 5.000000e-01
+ %conv18 = fptrunc double %div17 to float
+ store float %conv18, float* %arrayidx224, align 4
+ ret void
+}
diff --git a/test/CodeGen/PTX/add.ll b/test/CodeGen/PTX/add.ll
index 293aebe..8b10d11 100644
--- a/test/CodeGen/PTX/add.ll
+++ b/test/CodeGen/PTX/add.ll
@@ -1,71 +1,71 @@
; RUN: llc < %s -march=ptx32 | FileCheck %s
define ptx_device i16 @t1_u16(i16 %x, i16 %y) {
-; CHECK: add.u16 rh{{[0-9]+}}, rh{{[0-9]+}}, rh{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: add.u16 %ret{{[0-9]+}}, %rh{{[0-9]+}}, %rh{{[0-9]+}};
+; CHECK: ret;
%z = add i16 %x, %y
ret i16 %z
}
define ptx_device i32 @t1_u32(i32 %x, i32 %y) {
-; CHECK: add.u32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: add.u32 %ret{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: ret;
%z = add i32 %x, %y
ret i32 %z
}
define ptx_device i64 @t1_u64(i64 %x, i64 %y) {
-; CHECK: add.u64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: add.u64 %ret{{[0-9]+}}, %rd{{[0-9]+}}, %rd{{[0-9]+}};
+; CHECK: ret;
%z = add i64 %x, %y
ret i64 %z
}
define ptx_device float @t1_f32(float %x, float %y) {
-; CHECK: add.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}
-; CHECK-NEXT: ret;
+; CHECK: add.rn.f32 %ret{{[0-9]+}}, %f{{[0-9]+}}, %f{{[0-9]+}}
+; CHECK: ret;
%z = fadd float %x, %y
ret float %z
}
define ptx_device double @t1_f64(double %x, double %y) {
-; CHECK: add.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}
-; CHECK-NEXT: ret;
+; CHECK: add.rn.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}}, %fd{{[0-9]+}}
+; CHECK: ret;
%z = fadd double %x, %y
ret double %z
}
define ptx_device i16 @t2_u16(i16 %x) {
-; CHECK: add.u16 rh{{[0-9]+}}, rh{{[0-9]+}}, 1;
-; CHECK-NEXT: ret;
+; CHECK: add.u16 %ret{{[0-9]+}}, %rh{{[0-9]+}}, 1;
+; CHECK: ret;
%z = add i16 %x, 1
ret i16 %z
}
define ptx_device i32 @t2_u32(i32 %x) {
-; CHECK: add.u32 r{{[0-9]+}}, r{{[0-9]+}}, 1;
-; CHECK-NEXT: ret;
+; CHECK: add.u32 %ret{{[0-9]+}}, %r{{[0-9]+}}, 1;
+; CHECK: ret;
%z = add i32 %x, 1
ret i32 %z
}
define ptx_device i64 @t2_u64(i64 %x) {
-; CHECK: add.u64 rd{{[0-9]+}}, rd{{[0-9]+}}, 1;
-; CHECK-NEXT: ret;
+; CHECK: add.u64 %ret{{[0-9]+}}, %rd{{[0-9]+}}, 1;
+; CHECK: ret;
%z = add i64 %x, 1
ret i64 %z
}
define ptx_device float @t2_f32(float %x) {
-; CHECK: add.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, 0F3F800000;
-; CHECK-NEXT: ret;
+; CHECK: add.rn.f32 %ret{{[0-9]+}}, %f{{[0-9]+}}, 0D3FF0000000000000;
+; CHECK: ret;
%z = fadd float %x, 1.0
ret float %z
}
define ptx_device double @t2_f64(double %x) {
-; CHECK: add.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, 0D3FF0000000000000;
-; CHECK-NEXT: ret;
+; CHECK: add.rn.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}}, 0D3FF0000000000000;
+; CHECK: ret;
%z = fadd double %x, 1.0
ret double %z
}
diff --git a/test/CodeGen/PTX/aggregates.ll b/test/CodeGen/PTX/aggregates.ll
index 23f28a7..3fc0c40 100644
--- a/test/CodeGen/PTX/aggregates.ll
+++ b/test/CodeGen/PTX/aggregates.ll
@@ -1,4 +1,5 @@
; RUN: llc < %s -march=ptx32 -mattr=sm20 | FileCheck %s
+; XFAIL: *
%complex = type { float, float }
diff --git a/test/CodeGen/PTX/bitwise.ll b/test/CodeGen/PTX/bitwise.ll
index 3859280..1403a23 100644
--- a/test/CodeGen/PTX/bitwise.ll
+++ b/test/CodeGen/PTX/bitwise.ll
@@ -3,21 +3,21 @@
; preds
define ptx_device i32 @t1_and_preds(i1 %x, i1 %y) {
-; CHECK: and.pred p{{[0-9]+}}, p{{[0-9]+}}, p{{[0-9]+}}
+; CHECK: and.pred %p{{[0-9]+}}, %p{{[0-9]+}}, %p{{[0-9]+}}
%c = and i1 %x, %y
%d = zext i1 %c to i32
ret i32 %d
}
define ptx_device i32 @t1_or_preds(i1 %x, i1 %y) {
-; CHECK: or.pred p{{[0-9]+}}, p{{[0-9]+}}, p{{[0-9]+}}
+; CHECK: or.pred %p{{[0-9]+}}, %p{{[0-9]+}}, %p{{[0-9]+}}
%a = or i1 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
define ptx_device i32 @t1_xor_preds(i1 %x, i1 %y) {
-; CHECK: xor.pred p{{[0-9]+}}, p{{[0-9]+}}, p{{[0-9]+}}
+; CHECK: xor.pred %p{{[0-9]+}}, %p{{[0-9]+}}, %p{{[0-9]+}}
%a = xor i1 %x, %y
%b = zext i1 %a to i32
ret i32 %b
diff --git a/test/CodeGen/PTX/bra.ll b/test/CodeGen/PTX/bra.ll
index 7cc9444..464c29c 100644
--- a/test/CodeGen/PTX/bra.ll
+++ b/test/CodeGen/PTX/bra.ll
@@ -10,15 +10,15 @@ loop:
define ptx_device i32 @test_bra_cond_direct(i32 %x, i32 %y) {
entry:
-; CHECK: setp.le.u32 p0, r[[R0:[0-9]+]], r[[R1:[0-9]+]]
+; CHECK: setp.le.u32 %p0, %r[[R0:[0-9]+]], %r[[R1:[0-9]+]]
%p = icmp ugt i32 %x, %y
-; CHECK-NEXT: @p0 bra
+; CHECK-NEXT: @%p0 bra
; CHECK-NOT: bra
br i1 %p, label %clause.if, label %clause.else
clause.if:
-; CHECK: mov.u32 r{{[0-9]+}}, r[[R0]]
+; CHECK: mov.u32 %ret{{[0-9]+}}, %r[[R0]]
ret i32 %x
clause.else:
-; CHECK: mov.u32 r{{[0-9]+}}, r[[R1]]
+; CHECK: mov.u32 %ret{{[0-9]+}}, %r[[R1]]
ret i32 %y
}
diff --git a/test/CodeGen/PTX/cvt.ll b/test/CodeGen/PTX/cvt.ll
index 853abaf..a643d25 100644
--- a/test/CodeGen/PTX/cvt.ll
+++ b/test/CodeGen/PTX/cvt.ll
@@ -1,13 +1,13 @@
; RUN: llc < %s -march=ptx32 | FileCheck %s
-; preds
+; preds
; (note: we convert back to i32 to return)
define ptx_device i32 @cvt_pred_i16(i16 %x, i1 %y) {
-; CHECK: setp.gt.u16 p[[P0:[0-9]+]], rh{{[0-9]+}}, 0
-; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.u16 %p[[P0:[0-9]+]], %rh{{[0-9]+}}, 0
+; CHECK: and.pred %p2, %p[[P0:[0-9]+]], %p{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0:[0-9]+]];
+; CHECK: ret;
%a = trunc i16 %x to i1
%b = and i1 %a, %y
%c = zext i1 %b to i32
@@ -15,10 +15,10 @@ define ptx_device i32 @cvt_pred_i16(i16 %x, i1 %y) {
}
define ptx_device i32 @cvt_pred_i32(i32 %x, i1 %y) {
-; CHECK: setp.gt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0
-; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 0
+; CHECK: and.pred %p2, %p[[P0:[0-9]+]], %p{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0:[0-9]+]];
+; CHECK: ret;
%a = trunc i32 %x to i1
%b = and i1 %a, %y
%c = zext i1 %b to i32
@@ -26,10 +26,10 @@ define ptx_device i32 @cvt_pred_i32(i32 %x, i1 %y) {
}
define ptx_device i32 @cvt_pred_i64(i64 %x, i1 %y) {
-; CHECK: setp.gt.u64 p[[P0:[0-9]+]], rd{{[0-9]+}}, 0
-; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.u64 %p[[P0:[0-9]+]], %rd{{[0-9]+}}, 0
+; CHECK: and.pred %p2, %p[[P0:[0-9]+]], %p{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0:[0-9]+]];
+; CHECK: ret;
%a = trunc i64 %x to i1
%b = and i1 %a, %y
%c = zext i1 %b to i32
@@ -37,10 +37,10 @@ define ptx_device i32 @cvt_pred_i64(i64 %x, i1 %y) {
}
define ptx_device i32 @cvt_pred_f32(float %x, i1 %y) {
-; CHECK: setp.gt.f32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0
-; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 0
+; CHECK: and.pred %p2, %p[[P0:[0-9]+]], %p{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0:[0-9]+]];
+; CHECK: ret;
%a = fptoui float %x to i1
%b = and i1 %a, %y
%c = zext i1 %b to i32
@@ -48,10 +48,10 @@ define ptx_device i32 @cvt_pred_f32(float %x, i1 %y) {
}
define ptx_device i32 @cvt_pred_f64(double %x, i1 %y) {
-; CHECK: setp.gt.f64 p[[P0:[0-9]+]], rd{{[0-9]+}}, 0
-; CHECK-NEXT: and.pred p0, p[[P0:[0-9]+]], p{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0:[0-9]+]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.u64 %p[[P0:[0-9]+]], %rd{{[0-9]+}}, 0
+; CHECK: and.pred %p2, %p[[P0:[0-9]+]], %p{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0:[0-9]+]];
+; CHECK: ret;
%a = fptoui double %x to i1
%b = and i1 %a, %y
%c = zext i1 %b to i32
@@ -61,36 +61,36 @@ define ptx_device i32 @cvt_pred_f64(double %x, i1 %y) {
; i16
define ptx_device i16 @cvt_i16_preds(i1 %x) {
-; CHECK: selp.u16 rh{{[0-9]+}}, 1, 0, p{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: selp.u16 %ret{{[0-9]+}}, 1, 0, %p{{[0-9]+}};
+; CHECK: ret;
%a = zext i1 %x to i16
ret i16 %a
}
define ptx_device i16 @cvt_i16_i32(i32 %x) {
-; CHECK: cvt.u16.u32 rh{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.u16.u32 %ret{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: ret;
%a = trunc i32 %x to i16
ret i16 %a
}
define ptx_device i16 @cvt_i16_i64(i64 %x) {
-; CHECK: cvt.u16.u64 rh{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.u16.u64 %ret{{[0-9]+}}, %rd{{[0-9]+}};
+; CHECK: ret;
%a = trunc i64 %x to i16
ret i16 %a
}
define ptx_device i16 @cvt_i16_f32(float %x) {
-; CHECK: cvt.rzi.u16.f32 rh{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rzi.u16.f32 %ret{{[0-9]+}}, %f{{[0-9]+}};
+; CHECK: ret;
%a = fptoui float %x to i16
ret i16 %a
}
define ptx_device i16 @cvt_i16_f64(double %x) {
-; CHECK: cvt.rzi.u16.f64 rh{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rzi.u16.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}};
+; CHECK: ret;
%a = fptoui double %x to i16
ret i16 %a
}
@@ -98,36 +98,36 @@ define ptx_device i16 @cvt_i16_f64(double %x) {
; i32
define ptx_device i32 @cvt_i32_preds(i1 %x) {
-; CHECK: selp.u32 r{{[0-9]+}}, 1, 0, p{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p{{[0-9]+}};
+; CHECK: ret;
%a = zext i1 %x to i32
ret i32 %a
}
define ptx_device i32 @cvt_i32_i16(i16 %x) {
-; CHECK: cvt.u32.u16 r{{[0-9]+}}, rh{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.u32.u16 %ret{{[0-9]+}}, %rh{{[0-9]+}};
+; CHECK: ret;
%a = zext i16 %x to i32
ret i32 %a
}
define ptx_device i32 @cvt_i32_i64(i64 %x) {
-; CHECK: cvt.u32.u64 r{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.u32.u64 %ret{{[0-9]+}}, %rd{{[0-9]+}};
+; CHECK: ret;
%a = trunc i64 %x to i32
ret i32 %a
}
define ptx_device i32 @cvt_i32_f32(float %x) {
-; CHECK: cvt.rzi.u32.f32 r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rzi.u32.f32 %ret{{[0-9]+}}, %f{{[0-9]+}};
+; CHECK: ret;
%a = fptoui float %x to i32
ret i32 %a
}
define ptx_device i32 @cvt_i32_f64(double %x) {
-; CHECK: cvt.rzi.u32.f64 r{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rzi.u32.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}};
+; CHECK: ret;
%a = fptoui double %x to i32
ret i32 %a
}
@@ -135,35 +135,35 @@ define ptx_device i32 @cvt_i32_f64(double %x) {
; i64
define ptx_device i64 @cvt_i64_preds(i1 %x) {
-; CHECK: selp.u64 rd{{[0-9]+}}, 1, 0, p{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: selp.u64 %ret{{[0-9]+}}, 1, 0, %p{{[0-9]+}};
+; CHECK: ret;
%a = zext i1 %x to i64
ret i64 %a
}
define ptx_device i64 @cvt_i64_i16(i16 %x) {
-; CHECK: cvt.u64.u16 rd{{[0-9]+}}, rh{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.u64.u16 %ret{{[0-9]+}}, %rh{{[0-9]+}};
+; CHECK: ret;
%a = zext i16 %x to i64
ret i64 %a
}
define ptx_device i64 @cvt_i64_i32(i32 %x) {
-; CHECK: cvt.u64.u32 rd{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.u64.u32 %ret{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: ret;
%a = zext i32 %x to i64
ret i64 %a
}
define ptx_device i64 @cvt_i64_f32(float %x) {
-; CHECK: cvt.rzi.u64.f32 rd{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rzi.u64.f32 %ret{{[0-9]+}}, %f{{[0-9]+}};
+; CHECK: ret;
%a = fptoui float %x to i64
ret i64 %a
}
define ptx_device i64 @cvt_i64_f64(double %x) {
-; CHECK: cvt.rzi.u64.f64 rd{{[0-9]+}}, rd{{[0-9]+}};
+; CHECK: cvt.rzi.u64.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}};
; CHECK: ret;
%a = fptoui double %x to i64
ret i64 %a
@@ -172,73 +172,119 @@ define ptx_device i64 @cvt_i64_f64(double %x) {
; f32
define ptx_device float @cvt_f32_preds(i1 %x) {
-; CHECK: selp.f32 r{{[0-9]+}}, 0F3F800000, 0F00000000, p{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: mov.b32 %f0, 1065353216;
+; CHECK: mov.b32 %f1, 0;
+; CHECK: selp.f32 %ret{{[0-9]+}}, %f0, %f1, %p{{[0-9]+}};
+; CHECK: ret;
%a = uitofp i1 %x to float
ret float %a
}
define ptx_device float @cvt_f32_i16(i16 %x) {
-; CHECK: cvt.rn.f32.u16 r{{[0-9]+}}, rh{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rn.f32.u16 %ret{{[0-9]+}}, %rh{{[0-9]+}};
+; CHECK: ret;
%a = uitofp i16 %x to float
ret float %a
}
define ptx_device float @cvt_f32_i32(i32 %x) {
-; CHECK: cvt.rn.f32.u32 r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rn.f32.u32 %ret{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: ret;
%a = uitofp i32 %x to float
ret float %a
}
define ptx_device float @cvt_f32_i64(i64 %x) {
-; CHECK: cvt.rn.f32.u64 r{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rn.f32.u64 %ret{{[0-9]+}}, %rd{{[0-9]+}};
+; CHECK: ret;
%a = uitofp i64 %x to float
ret float %a
}
define ptx_device float @cvt_f32_f64(double %x) {
-; CHECK: cvt.rn.f32.f64 r{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rn.f32.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}};
+; CHECK: ret;
%a = fptrunc double %x to float
ret float %a
}
+define ptx_device float @cvt_f32_s16(i16 %x) {
+; CHECK: cvt.rn.f32.s16 %ret{{[0-9]+}}, %rh{{[0-9]+}}
+; CHECK: ret
+ %a = sitofp i16 %x to float
+ ret float %a
+}
+
+define ptx_device float @cvt_f32_s32(i32 %x) {
+; CHECK: cvt.rn.f32.s32 %ret{{[0-9]+}}, %r{{[0-9]+}}
+; CHECK: ret
+ %a = sitofp i32 %x to float
+ ret float %a
+}
+
+define ptx_device float @cvt_f32_s64(i64 %x) {
+; CHECK: cvt.rn.f32.s64 %ret{{[0-9]+}}, %rd{{[0-9]+}}
+; CHECK: ret
+ %a = sitofp i64 %x to float
+ ret float %a
+}
+
; f64
define ptx_device double @cvt_f64_preds(i1 %x) {
-; CHECK: selp.f64 rd{{[0-9]+}}, 0D3F80000000000000, 0D0000000000000000, p{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: mov.b64 %fd0, 4575657221408423936;
+; CHECK: mov.b64 %fd1, 0;
+; CHECK: selp.f64 %ret{{[0-9]+}}, %fd0, %fd1, %p{{[0-9]+}};
+; CHECK: ret;
%a = uitofp i1 %x to double
ret double %a
}
define ptx_device double @cvt_f64_i16(i16 %x) {
-; CHECK: cvt.rn.f64.u16 rd{{[0-9]+}}, rh{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rn.f64.u16 %ret{{[0-9]+}}, %rh{{[0-9]+}};
+; CHECK: ret;
%a = uitofp i16 %x to double
ret double %a
}
define ptx_device double @cvt_f64_i32(i32 %x) {
-; CHECK: cvt.rn.f64.u32 rd{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rn.f64.u32 %ret{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: ret;
%a = uitofp i32 %x to double
ret double %a
}
define ptx_device double @cvt_f64_i64(i64 %x) {
-; CHECK: cvt.rn.f64.u64 rd{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.rn.f64.u64 %ret{{[0-9]+}}, %rd{{[0-9]+}};
+; CHECK: ret;
%a = uitofp i64 %x to double
ret double %a
}
define ptx_device double @cvt_f64_f32(float %x) {
-; CHECK: cvt.f64.f32 rd{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cvt.f64.f32 %ret{{[0-9]+}}, %f{{[0-9]+}};
+; CHECK: ret;
%a = fpext float %x to double
ret double %a
}
+
+define ptx_device double @cvt_f64_s16(i16 %x) {
+; CHECK: cvt.rn.f64.s16 %ret{{[0-9]+}}, %rh{{[0-9]+}}
+; CHECK: ret
+ %a = sitofp i16 %x to double
+ ret double %a
+}
+
+define ptx_device double @cvt_f64_s32(i32 %x) {
+; CHECK: cvt.rn.f64.s32 %ret{{[0-9]+}}, %r{{[0-9]+}}
+; CHECK: ret
+ %a = sitofp i32 %x to double
+ ret double %a
+}
+
+define ptx_device double @cvt_f64_s64(i64 %x) {
+; CHECK: cvt.rn.f64.s64 %ret{{[0-9]+}}, %rd{{[0-9]+}}
+; CHECK: ret
+ %a = sitofp i64 %x to double
+ ret double %a
+}
diff --git a/test/CodeGen/PTX/fdiv-sm10.ll b/test/CodeGen/PTX/fdiv-sm10.ll
index 049d891..e1013be 100644
--- a/test/CodeGen/PTX/fdiv-sm10.ll
+++ b/test/CodeGen/PTX/fdiv-sm10.ll
@@ -1,15 +1,15 @@
; RUN: llc < %s -march=ptx32 -mattr=+sm10 | FileCheck %s
define ptx_device float @t1_f32(float %x, float %y) {
-; CHECK: div.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: div.f32 %ret{{[0-9]+}}, %f{{[0-9]+}}, %f{{[0-9]+}};
+; CHECK: ret;
%a = fdiv float %x, %y
ret float %a
}
define ptx_device double @t1_f64(double %x, double %y) {
-; CHECK: div.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: div.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}}, %fd{{[0-9]+}};
+; CHECK: ret;
%a = fdiv double %x, %y
ret double %a
}
diff --git a/test/CodeGen/PTX/fdiv-sm13.ll b/test/CodeGen/PTX/fdiv-sm13.ll
index 2d95339..1afa2eb 100644
--- a/test/CodeGen/PTX/fdiv-sm13.ll
+++ b/test/CodeGen/PTX/fdiv-sm13.ll
@@ -1,15 +1,15 @@
; RUN: llc < %s -march=ptx32 -mattr=+sm13 | FileCheck %s
define ptx_device float @t1_f32(float %x, float %y) {
-; CHECK: div.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: div.rn.f32 %ret{{[0-9]+}}, %f{{[0-9]+}}, %f{{[0-9]+}};
+; CHECK: ret;
%a = fdiv float %x, %y
ret float %a
}
define ptx_device double @t1_f64(double %x, double %y) {
-; CHECK: div.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: div.rn.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}}, %fd{{[0-9]+}};
+; CHECK: ret;
%a = fdiv double %x, %y
ret double %a
}
diff --git a/test/CodeGen/PTX/fneg.ll b/test/CodeGen/PTX/fneg.ll
index 66ca74a..2b76e63 100644
--- a/test/CodeGen/PTX/fneg.ll
+++ b/test/CodeGen/PTX/fneg.ll
@@ -1,15 +1,15 @@
; RUN: llc < %s -march=ptx32 | FileCheck %s
define ptx_device float @t1_f32(float %x) {
-; CHECK: neg.f32 r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: neg.f32 %ret{{[0-9]+}}, %f{{[0-9]+}};
+; CHECK: ret;
%y = fsub float -0.000000e+00, %x
ret float %y
}
define ptx_device double @t1_f64(double %x) {
-; CHECK: neg.f64 rd{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: neg.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}};
+; CHECK: ret;
%y = fsub double -0.000000e+00, %x
ret double %y
}
diff --git a/test/CodeGen/PTX/intrinsic.ll b/test/CodeGen/PTX/intrinsic.ll
index af987d6..9f37ead 100644
--- a/test/CodeGen/PTX/intrinsic.ll
+++ b/test/CodeGen/PTX/intrinsic.ll
@@ -1,239 +1,239 @@
; RUN: llc < %s -march=ptx32 -mattr=+ptx20 | FileCheck %s
define ptx_device i32 @test_tid_x() {
-; CHECK: mov.u32 r0, %tid.x;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %tid.x;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.tid.x()
ret i32 %x
}
define ptx_device i32 @test_tid_y() {
-; CHECK: mov.u32 r0, %tid.y;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %tid.y;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.tid.y()
ret i32 %x
}
define ptx_device i32 @test_tid_z() {
-; CHECK: mov.u32 r0, %tid.z;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %tid.z;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.tid.z()
ret i32 %x
}
define ptx_device i32 @test_tid_w() {
-; CHECK: mov.u32 r0, %tid.w;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %tid.w;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.tid.w()
ret i32 %x
}
define ptx_device i32 @test_ntid_x() {
-; CHECK: mov.u32 r0, %ntid.x;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %ntid.x;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.ntid.x()
ret i32 %x
}
define ptx_device i32 @test_ntid_y() {
-; CHECK: mov.u32 r0, %ntid.y;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %ntid.y;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.ntid.y()
ret i32 %x
}
define ptx_device i32 @test_ntid_z() {
-; CHECK: mov.u32 r0, %ntid.z;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %ntid.z;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.ntid.z()
ret i32 %x
}
define ptx_device i32 @test_ntid_w() {
-; CHECK: mov.u32 r0, %ntid.w;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %ntid.w;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.ntid.w()
ret i32 %x
}
define ptx_device i32 @test_laneid() {
-; CHECK: mov.u32 r0, %laneid;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %laneid;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.laneid()
ret i32 %x
}
define ptx_device i32 @test_warpid() {
-; CHECK: mov.u32 r0, %warpid;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %warpid;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.warpid()
ret i32 %x
}
define ptx_device i32 @test_nwarpid() {
-; CHECK: mov.u32 r0, %nwarpid;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %nwarpid;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.nwarpid()
ret i32 %x
}
define ptx_device i32 @test_ctaid_x() {
-; CHECK: mov.u32 r0, %ctaid.x;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %ctaid.x;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.ctaid.x()
ret i32 %x
}
define ptx_device i32 @test_ctaid_y() {
-; CHECK: mov.u32 r0, %ctaid.y;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %ctaid.y;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.ctaid.y()
ret i32 %x
}
define ptx_device i32 @test_ctaid_z() {
-; CHECK: mov.u32 r0, %ctaid.z;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %ctaid.z;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.ctaid.z()
ret i32 %x
}
define ptx_device i32 @test_ctaid_w() {
-; CHECK: mov.u32 r0, %ctaid.w;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %ctaid.w;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.ctaid.w()
ret i32 %x
}
define ptx_device i32 @test_nctaid_x() {
-; CHECK: mov.u32 r0, %nctaid.x;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %nctaid.x;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.nctaid.x()
ret i32 %x
}
define ptx_device i32 @test_nctaid_y() {
-; CHECK: mov.u32 r0, %nctaid.y;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %nctaid.y;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.nctaid.y()
ret i32 %x
}
define ptx_device i32 @test_nctaid_z() {
-; CHECK: mov.u32 r0, %nctaid.z;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %nctaid.z;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.nctaid.z()
ret i32 %x
}
define ptx_device i32 @test_nctaid_w() {
-; CHECK: mov.u32 r0, %nctaid.w;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %nctaid.w;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.nctaid.w()
ret i32 %x
}
define ptx_device i32 @test_smid() {
-; CHECK: mov.u32 r0, %smid;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %smid;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.smid()
ret i32 %x
}
define ptx_device i32 @test_nsmid() {
-; CHECK: mov.u32 r0, %nsmid;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %nsmid;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.nsmid()
ret i32 %x
}
define ptx_device i32 @test_gridid() {
-; CHECK: mov.u32 r0, %gridid;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %gridid;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.gridid()
ret i32 %x
}
define ptx_device i32 @test_lanemask_eq() {
-; CHECK: mov.u32 r0, %lanemask_eq;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %lanemask_eq;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.lanemask.eq()
ret i32 %x
}
define ptx_device i32 @test_lanemask_le() {
-; CHECK: mov.u32 r0, %lanemask_le;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %lanemask_le;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.lanemask.le()
ret i32 %x
}
define ptx_device i32 @test_lanemask_lt() {
-; CHECK: mov.u32 r0, %lanemask_lt;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %lanemask_lt;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.lanemask.lt()
ret i32 %x
}
define ptx_device i32 @test_lanemask_ge() {
-; CHECK: mov.u32 r0, %lanemask_ge;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %lanemask_ge;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.lanemask.ge()
ret i32 %x
}
define ptx_device i32 @test_lanemask_gt() {
-; CHECK: mov.u32 r0, %lanemask_gt;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %lanemask_gt;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.lanemask.gt()
ret i32 %x
}
define ptx_device i32 @test_clock() {
-; CHECK: mov.u32 r0, %clock;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %clock;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.clock()
ret i32 %x
}
define ptx_device i64 @test_clock64() {
-; CHECK: mov.u64 rd0, %clock64;
-; CHECK-NEXT: ret;
+; CHECK: mov.u64 %ret0, %clock64;
+; CHECK: ret;
%x = call i64 @llvm.ptx.read.clock64()
ret i64 %x
}
define ptx_device i32 @test_pm0() {
-; CHECK: mov.u32 r0, %pm0;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %pm0;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.pm0()
ret i32 %x
}
define ptx_device i32 @test_pm1() {
-; CHECK: mov.u32 r0, %pm1;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %pm1;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.pm1()
ret i32 %x
}
define ptx_device i32 @test_pm2() {
-; CHECK: mov.u32 r0, %pm2;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %pm2;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.pm2()
ret i32 %x
}
define ptx_device i32 @test_pm3() {
-; CHECK: mov.u32 r0, %pm3;
-; CHECK-NEXT: ret;
+; CHECK: mov.u32 %ret0, %pm3;
+; CHECK: ret;
%x = call i32 @llvm.ptx.read.pm3()
ret i32 %x
}
define ptx_device void @test_bar_sync() {
; CHECK: bar.sync 0
-; CHECK-NEXT: ret;
+; CHECK: ret;
call void @llvm.ptx.bar.sync(i32 0)
ret void
}
diff --git a/test/CodeGen/PTX/ld.ll b/test/CodeGen/PTX/ld.ll
index d184d12..81fd33a 100644
--- a/test/CodeGen/PTX/ld.ll
+++ b/test/CodeGen/PTX/ld.ll
@@ -6,9 +6,6 @@
;CHECK: .extern .const .b8 array_constant_i16[20];
@array_constant_i16 = external addrspace(1) constant [10 x i16]
-;CHECK: .extern .local .b8 array_local_i16[20];
-@array_local_i16 = external addrspace(2) global [10 x i16]
-
;CHECK: .extern .shared .b8 array_shared_i16[20];
@array_shared_i16 = external addrspace(4) global [10 x i16]
@@ -18,9 +15,6 @@
;CHECK: .extern .const .b8 array_constant_i32[40];
@array_constant_i32 = external addrspace(1) constant [10 x i32]
-;CHECK: .extern .local .b8 array_local_i32[40];
-@array_local_i32 = external addrspace(2) global [10 x i32]
-
;CHECK: .extern .shared .b8 array_shared_i32[40];
@array_shared_i32 = external addrspace(4) global [10 x i32]
@@ -30,9 +24,6 @@
;CHECK: .extern .const .b8 array_constant_i64[80];
@array_constant_i64 = external addrspace(1) constant [10 x i64]
-;CHECK: .extern .local .b8 array_local_i64[80];
-@array_local_i64 = external addrspace(2) global [10 x i64]
-
;CHECK: .extern .shared .b8 array_shared_i64[80];
@array_shared_i64 = external addrspace(4) global [10 x i64]
@@ -42,9 +33,6 @@
;CHECK: .extern .const .b8 array_constant_float[40];
@array_constant_float = external addrspace(1) constant [10 x float]
-;CHECK: .extern .local .b8 array_local_float[40];
-@array_local_float = external addrspace(2) global [10 x float]
-
;CHECK: .extern .shared .b8 array_shared_float[40];
@array_shared_float = external addrspace(4) global [10 x float]
@@ -54,57 +42,54 @@
;CHECK: .extern .const .b8 array_constant_double[80];
@array_constant_double = external addrspace(1) constant [10 x double]
-;CHECK: .extern .local .b8 array_local_double[80];
-@array_local_double = external addrspace(2) global [10 x double]
-
;CHECK: .extern .shared .b8 array_shared_double[80];
@array_shared_double = external addrspace(4) global [10 x double]
define ptx_device i16 @t1_u16(i16* %p) {
entry:
-;CHECK: ld.global.u16 rh{{[0-9]+}}, [r{{[0-9]+}}];
-;CHECK-NEXT: ret;
+;CHECK: ld.global.u16 %ret{{[0-9]+}}, [%r{{[0-9]+}}];
+;CHECK: ret;
%x = load i16* %p
ret i16 %x
}
define ptx_device i32 @t1_u32(i32* %p) {
entry:
-;CHECK: ld.global.u32 r{{[0-9]+}}, [r{{[0-9]+}}];
-;CHECK-NEXT: ret;
+;CHECK: ld.global.u32 %ret{{[0-9]+}}, [%r{{[0-9]+}}];
+;CHECK: ret;
%x = load i32* %p
ret i32 %x
}
define ptx_device i64 @t1_u64(i64* %p) {
entry:
-;CHECK: ld.global.u64 rd{{[0-9]+}}, [r{{[0-9]+}}];
-;CHECK-NEXT: ret;
+;CHECK: ld.global.u64 %ret{{[0-9]+}}, [%r{{[0-9]+}}];
+;CHECK: ret;
%x = load i64* %p
ret i64 %x
}
define ptx_device float @t1_f32(float* %p) {
entry:
-;CHECK: ld.global.f32 r{{[0-9]+}}, [r{{[0-9]+}}];
-;CHECK-NEXT: ret;
+;CHECK: ld.global.f32 %ret{{[0-9]+}}, [%r{{[0-9]+}}];
+;CHECK: ret;
%x = load float* %p
ret float %x
}
define ptx_device double @t1_f64(double* %p) {
entry:
-;CHECK: ld.global.f64 rd{{[0-9]+}}, [r{{[0-9]+}}];
-;CHECK-NEXT: ret;
+;CHECK: ld.global.f64 %ret{{[0-9]+}}, [%r{{[0-9]+}}];
+;CHECK: ret;
%x = load double* %p
ret double %x
}
define ptx_device i16 @t2_u16(i16* %p) {
entry:
-;CHECK: ld.global.u16 rh{{[0-9]+}}, [r{{[0-9]+}}+2];
-;CHECK-NEXT: ret;
+;CHECK: ld.global.u16 %ret{{[0-9]+}}, [%r{{[0-9]+}}+2];
+;CHECK: ret;
%i = getelementptr i16* %p, i32 1
%x = load i16* %i
ret i16 %x
@@ -112,8 +97,8 @@ entry:
define ptx_device i32 @t2_u32(i32* %p) {
entry:
-;CHECK: ld.global.u32 r{{[0-9]+}}, [r{{[0-9]+}}+4];
-;CHECK-NEXT: ret;
+;CHECK: ld.global.u32 %ret{{[0-9]+}}, [%r{{[0-9]+}}+4];
+;CHECK: ret;
%i = getelementptr i32* %p, i32 1
%x = load i32* %i
ret i32 %x
@@ -121,8 +106,8 @@ entry:
define ptx_device i64 @t2_u64(i64* %p) {
entry:
-;CHECK: ld.global.u64 rd{{[0-9]+}}, [r{{[0-9]+}}+8];
-;CHECK-NEXT: ret;
+;CHECK: ld.global.u64 %ret{{[0-9]+}}, [%r{{[0-9]+}}+8];
+;CHECK: ret;
%i = getelementptr i64* %p, i32 1
%x = load i64* %i
ret i64 %x
@@ -130,8 +115,8 @@ entry:
define ptx_device float @t2_f32(float* %p) {
entry:
-;CHECK: ld.global.f32 r{{[0-9]+}}, [r{{[0-9]+}}+4];
-;CHECK-NEXT: ret;
+;CHECK: ld.global.f32 %ret{{[0-9]+}}, [%r{{[0-9]+}}+4];
+;CHECK: ret;
%i = getelementptr float* %p, i32 1
%x = load float* %i
ret float %x
@@ -139,8 +124,8 @@ entry:
define ptx_device double @t2_f64(double* %p) {
entry:
-;CHECK: ld.global.f64 rd{{[0-9]+}}, [r{{[0-9]+}}+8];
-;CHECK-NEXT: ret;
+;CHECK: ld.global.f64 %ret{{[0-9]+}}, [%r{{[0-9]+}}+8];
+;CHECK: ret;
%i = getelementptr double* %p, i32 1
%x = load double* %i
ret double %x
@@ -148,9 +133,9 @@ entry:
define ptx_device i16 @t3_u16(i16* %p, i32 %q) {
entry:
-;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 1;
-;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]];
-;CHECK-NEXT: ld.global.u16 rh{{[0-9]+}}, [r[[R0]]];
+;CHECK: shl.b32 %r[[R0:[0-9]+]], %r{{[0-9]+}}, 1;
+;CHECK: add.u32 %r{{[0-9]+}}, %r{{[0-9]+}}, %r[[R0]];
+;CHECK: ld.global.u16 %ret{{[0-9]+}}, [%r{{[0-9]+}}];
%i = getelementptr i16* %p, i32 %q
%x = load i16* %i
ret i16 %x
@@ -158,9 +143,9 @@ entry:
define ptx_device i32 @t3_u32(i32* %p, i32 %q) {
entry:
-;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 2;
-;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]];
-;CHECK-NEXT: ld.global.u32 r{{[0-9]+}}, [r[[R0]]];
+;CHECK: shl.b32 %r[[R0:[0-9]+]], %r{{[0-9]+}}, 2;
+;CHECK: add.u32 %r{{[0-9]+}}, %r{{[0-9]+}}, %r[[R0]];
+;CHECK: ld.global.u32 %ret{{[0-9]+}}, [%r{{[0-9]+}}];
%i = getelementptr i32* %p, i32 %q
%x = load i32* %i
ret i32 %x
@@ -168,9 +153,9 @@ entry:
define ptx_device i64 @t3_u64(i64* %p, i32 %q) {
entry:
-;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 3;
-;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]];
-;CHECK-NEXT: ld.global.u64 rd{{[0-9]+}}, [r[[R0]]];
+;CHECK: shl.b32 %r[[R0:[0-9]+]], %r{{[0-9]+}}, 3;
+;CHECK: add.u32 %r{{[0-9]+}}, %r{{[0-9]+}}, %r[[R0]];
+;CHECK: ld.global.u64 %ret{{[0-9]+}}, [%r{{[0-9]+}}];
%i = getelementptr i64* %p, i32 %q
%x = load i64* %i
ret i64 %x
@@ -178,9 +163,9 @@ entry:
define ptx_device float @t3_f32(float* %p, i32 %q) {
entry:
-;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 2;
-;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]];
-;CHECK-NEXT: ld.global.f32 r{{[0-9]+}}, [r[[R0]]];
+;CHECK: shl.b32 %r[[R0:[0-9]+]], %r{{[0-9]+}}, 2;
+;CHECK: add.u32 %r{{[0-9]+}}, %r{{[0-9]+}}, %r[[R0]];
+;CHECK: ld.global.f32 %ret{{[0-9]+}}, [%r{{[0-9]+}}];
%i = getelementptr float* %p, i32 %q
%x = load float* %i
ret float %x
@@ -188,9 +173,9 @@ entry:
define ptx_device double @t3_f64(double* %p, i32 %q) {
entry:
-;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 3;
-;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]];
-;CHECK-NEXT: ld.global.f64 rd{{[0-9]+}}, [r[[R0]]];
+;CHECK: shl.b32 %r[[R0:[0-9]+]], %r{{[0-9]+}}, 3;
+;CHECK: add.u32 %r{{[0-9]+}}, %r{{[0-9]+}}, %r[[R0]];
+;CHECK: ld.global.f64 %ret{{[0-9]+}}, [%r{{[0-9]+}}];
%i = getelementptr double* %p, i32 %q
%x = load double* %i
ret double %x
@@ -198,9 +183,9 @@ entry:
define ptx_device i16 @t4_global_u16() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16;
-;CHECK-NEXT: ld.global.u16 rh{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i16;
+;CHECK: ld.global.u16 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x i16]* @array_i16, i32 0, i32 0
%x = load i16* %i
ret i16 %x
@@ -208,9 +193,9 @@ entry:
define ptx_device i32 @t4_global_u32() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i32;
-;CHECK-NEXT: ld.global.u32 r{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i32;
+;CHECK: ld.global.u32 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x i32]* @array_i32, i32 0, i32 0
%x = load i32* %i
ret i32 %x
@@ -218,9 +203,9 @@ entry:
define ptx_device i64 @t4_global_u64() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i64;
-;CHECK-NEXT: ld.global.u64 rd{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i64;
+;CHECK: ld.global.u64 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x i64]* @array_i64, i32 0, i32 0
%x = load i64* %i
ret i64 %x
@@ -228,9 +213,9 @@ entry:
define ptx_device float @t4_global_f32() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_float;
-;CHECK-NEXT: ld.global.f32 r{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_float;
+;CHECK: ld.global.f32 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x float]* @array_float, i32 0, i32 0
%x = load float* %i
ret float %x
@@ -238,9 +223,9 @@ entry:
define ptx_device double @t4_global_f64() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_double;
-;CHECK-NEXT: ld.global.f64 rd{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_double;
+;CHECK: ld.global.f64 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x double]* @array_double, i32 0, i32 0
%x = load double* %i
ret double %x
@@ -248,9 +233,9 @@ entry:
define ptx_device i16 @t4_const_u16() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_constant_i16;
-;CHECK-NEXT: ld.const.u16 rh{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_constant_i16;
+;CHECK: ld.const.u16 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x i16] addrspace(1)* @array_constant_i16, i32 0, i32 0
%x = load i16 addrspace(1)* %i
ret i16 %x
@@ -258,9 +243,9 @@ entry:
define ptx_device i32 @t4_const_u32() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_constant_i32;
-;CHECK-NEXT: ld.const.u32 r{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_constant_i32;
+;CHECK: ld.const.u32 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x i32] addrspace(1)* @array_constant_i32, i32 0, i32 0
%x = load i32 addrspace(1)* %i
ret i32 %x
@@ -268,9 +253,9 @@ entry:
define ptx_device i64 @t4_const_u64() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_constant_i64;
-;CHECK-NEXT: ld.const.u64 rd{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_constant_i64;
+;CHECK: ld.const.u64 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x i64] addrspace(1)* @array_constant_i64, i32 0, i32 0
%x = load i64 addrspace(1)* %i
ret i64 %x
@@ -278,9 +263,9 @@ entry:
define ptx_device float @t4_const_f32() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_constant_float;
-;CHECK-NEXT: ld.const.f32 r{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_constant_float;
+;CHECK: ld.const.f32 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x float] addrspace(1)* @array_constant_float, i32 0, i32 0
%x = load float addrspace(1)* %i
ret float %x
@@ -288,69 +273,19 @@ entry:
define ptx_device double @t4_const_f64() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_constant_double;
-;CHECK-NEXT: ld.const.f64 rd{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_constant_double;
+;CHECK: ld.const.f64 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x double] addrspace(1)* @array_constant_double, i32 0, i32 0
%x = load double addrspace(1)* %i
ret double %x
}
-define ptx_device i16 @t4_local_u16() {
-entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i16;
-;CHECK-NEXT: ld.local.u16 rh{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
- %i = getelementptr [10 x i16] addrspace(2)* @array_local_i16, i32 0, i32 0
- %x = load i16 addrspace(2)* %i
- ret i16 %x
-}
-
-define ptx_device i32 @t4_local_u32() {
-entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i32;
-;CHECK-NEXT: ld.local.u32 r{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
- %i = getelementptr [10 x i32] addrspace(2)* @array_local_i32, i32 0, i32 0
- %x = load i32 addrspace(2)* %i
- ret i32 %x
-}
-
-define ptx_device i64 @t4_local_u64() {
-entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i64;
-;CHECK-NEXT: ld.local.u64 rd{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
- %i = getelementptr [10 x i64] addrspace(2)* @array_local_i64, i32 0, i32 0
- %x = load i64 addrspace(2)* %i
- ret i64 %x
-}
-
-define ptx_device float @t4_local_f32() {
-entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_float;
-;CHECK-NEXT: ld.local.f32 r{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
- %i = getelementptr [10 x float] addrspace(2)* @array_local_float, i32 0, i32 0
- %x = load float addrspace(2)* %i
- ret float %x
-}
-
-define ptx_device double @t4_local_f64() {
-entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_double;
-;CHECK-NEXT: ld.local.f64 rd{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
- %i = getelementptr [10 x double] addrspace(2)* @array_local_double, i32 0, i32 0
- %x = load double addrspace(2)* %i
- ret double %x
-}
-
define ptx_device i16 @t4_shared_u16() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i16;
-;CHECK-NEXT: ld.shared.u16 rh{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_shared_i16;
+;CHECK: ld.shared.u16 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x i16] addrspace(4)* @array_shared_i16, i32 0, i32 0
%x = load i16 addrspace(4)* %i
ret i16 %x
@@ -358,9 +293,9 @@ entry:
define ptx_device i32 @t4_shared_u32() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i32;
-;CHECK-NEXT: ld.shared.u32 r{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_shared_i32;
+;CHECK: ld.shared.u32 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x i32] addrspace(4)* @array_shared_i32, i32 0, i32 0
%x = load i32 addrspace(4)* %i
ret i32 %x
@@ -368,9 +303,9 @@ entry:
define ptx_device i64 @t4_shared_u64() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i64;
-;CHECK-NEXT: ld.shared.u64 rd{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_shared_i64;
+;CHECK: ld.shared.u64 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x i64] addrspace(4)* @array_shared_i64, i32 0, i32 0
%x = load i64 addrspace(4)* %i
ret i64 %x
@@ -378,9 +313,9 @@ entry:
define ptx_device float @t4_shared_f32() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_float;
-;CHECK-NEXT: ld.shared.f32 r{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_shared_float;
+;CHECK: ld.shared.f32 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x float] addrspace(4)* @array_shared_float, i32 0, i32 0
%x = load float addrspace(4)* %i
ret float %x
@@ -388,9 +323,9 @@ entry:
define ptx_device double @t4_shared_f64() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_double;
-;CHECK-NEXT: ld.shared.f64 rd{{[0-9]+}}, [r[[R0]]];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_shared_double;
+;CHECK: ld.shared.f64 %ret{{[0-9]+}}, [%r[[R0]]];
+;CHECK: ret;
%i = getelementptr [10 x double] addrspace(4)* @array_shared_double, i32 0, i32 0
%x = load double addrspace(4)* %i
ret double %x
@@ -398,9 +333,9 @@ entry:
define ptx_device i16 @t5_u16() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16;
-;CHECK-NEXT: ld.global.u16 rh{{[0-9]+}}, [r[[R0]]+2];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i16;
+;CHECK: ld.global.u16 %ret{{[0-9]+}}, [%r[[R0]]+2];
+;CHECK: ret;
%i = getelementptr [10 x i16]* @array_i16, i32 0, i32 1
%x = load i16* %i
ret i16 %x
@@ -408,9 +343,9 @@ entry:
define ptx_device i32 @t5_u32() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i32;
-;CHECK-NEXT: ld.global.u32 r{{[0-9]+}}, [r[[R0]]+4];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i32;
+;CHECK: ld.global.u32 %ret{{[0-9]+}}, [%r[[R0]]+4];
+;CHECK: ret;
%i = getelementptr [10 x i32]* @array_i32, i32 0, i32 1
%x = load i32* %i
ret i32 %x
@@ -418,9 +353,9 @@ entry:
define ptx_device i64 @t5_u64() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i64;
-;CHECK-NEXT: ld.global.u64 rd{{[0-9]+}}, [r[[R0]]+8];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i64;
+;CHECK: ld.global.u64 %ret{{[0-9]+}}, [%r[[R0]]+8];
+;CHECK: ret;
%i = getelementptr [10 x i64]* @array_i64, i32 0, i32 1
%x = load i64* %i
ret i64 %x
@@ -428,9 +363,9 @@ entry:
define ptx_device float @t5_f32() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_float;
-;CHECK-NEXT: ld.global.f32 r{{[0-9]+}}, [r[[R0]]+4];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_float;
+;CHECK: ld.global.f32 %ret{{[0-9]+}}, [%r[[R0]]+4];
+;CHECK: ret;
%i = getelementptr [10 x float]* @array_float, i32 0, i32 1
%x = load float* %i
ret float %x
@@ -438,9 +373,9 @@ entry:
define ptx_device double @t5_f64() {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_double;
-;CHECK-NEXT: ld.global.f64 rd{{[0-9]+}}, [r[[R0]]+8];
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_double;
+;CHECK: ld.global.f64 %ret{{[0-9]+}}, [%r[[R0]]+8];
+;CHECK: ret;
%i = getelementptr [10 x double]* @array_double, i32 0, i32 1
%x = load double* %i
ret double %x
diff --git a/test/CodeGen/PTX/llvm-intrinsic.ll b/test/CodeGen/PTX/llvm-intrinsic.ll
index 4611c54..e73ad25 100644
--- a/test/CodeGen/PTX/llvm-intrinsic.ll
+++ b/test/CodeGen/PTX/llvm-intrinsic.ll
@@ -2,48 +2,48 @@
define ptx_device float @test_sqrt_f32(float %x) {
entry:
-; CHECK: sqrt.rn.f32 r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: sqrt.rn.f32 %ret{{[0-9]+}}, %f{{[0-9]+}};
+; CHECK: ret;
%y = call float @llvm.sqrt.f32(float %x)
ret float %y
}
define ptx_device double @test_sqrt_f64(double %x) {
entry:
-; CHECK: sqrt.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: sqrt.rn.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}};
+; CHECK: ret;
%y = call double @llvm.sqrt.f64(double %x)
ret double %y
}
define ptx_device float @test_sin_f32(float %x) {
entry:
-; CHECK: sin.approx.f32 r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: sin.approx.f32 %ret{{[0-9]+}}, %f{{[0-9]+}};
+; CHECK: ret;
%y = call float @llvm.sin.f32(float %x)
ret float %y
}
define ptx_device double @test_sin_f64(double %x) {
entry:
-; CHECK: sin.approx.f64 rd{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: sin.approx.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}};
+; CHECK: ret;
%y = call double @llvm.sin.f64(double %x)
ret double %y
}
define ptx_device float @test_cos_f32(float %x) {
entry:
-; CHECK: cos.approx.f32 r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cos.approx.f32 %ret{{[0-9]+}}, %f{{[0-9]+}};
+; CHECK: ret;
%y = call float @llvm.cos.f32(float %x)
ret float %y
}
define ptx_device double @test_cos_f64(double %x) {
entry:
-; CHECK: cos.approx.f64 rd{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: cos.approx.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}};
+; CHECK: ret;
%y = call double @llvm.cos.f64(double %x)
ret double %y
}
diff --git a/test/CodeGen/PTX/mad.ll b/test/CodeGen/PTX/mad.ll
index 0e4d3f9..cc28e3f 100644
--- a/test/CodeGen/PTX/mad.ll
+++ b/test/CodeGen/PTX/mad.ll
@@ -1,16 +1,16 @@
; RUN: llc < %s -march=ptx32 -mattr=+sm13 | FileCheck %s
define ptx_device float @t1_f32(float %x, float %y, float %z) {
-; CHECK: mad.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: mad.rn.f32 %ret{{[0-9]+}}, %f{{[0-9]+}}, %f{{[0-9]+}}, %f{{[0-9]+}};
+; CHECK: ret;
%a = fmul float %x, %y
%b = fadd float %a, %z
ret float %b
}
define ptx_device double @t1_f64(double %x, double %y, double %z) {
-; CHECK: mad.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: mad.rn.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}}, %fd{{[0-9]+}}, %fd{{[0-9]+}};
+; CHECK: ret;
%a = fmul double %x, %y
%b = fadd double %a, %z
ret double %b
diff --git a/test/CodeGen/PTX/mov.ll b/test/CodeGen/PTX/mov.ll
index cce6a5b..75555a7 100644
--- a/test/CodeGen/PTX/mov.ll
+++ b/test/CodeGen/PTX/mov.ll
@@ -1,62 +1,62 @@
; RUN: llc < %s -march=ptx32 | FileCheck %s
define ptx_device i16 @t1_u16() {
-; CHECK: mov.u16 rh{{[0-9]+}}, 0;
+; CHECK: mov.u16 %ret{{[0-9]+}}, 0;
; CHECK: ret;
ret i16 0
}
define ptx_device i32 @t1_u32() {
-; CHECK: mov.u32 r{{[0-9]+}}, 0;
+; CHECK: mov.u32 %ret{{[0-9]+}}, 0;
; CHECK: ret;
ret i32 0
}
define ptx_device i64 @t1_u64() {
-; CHECK: mov.u64 rd{{[0-9]+}}, 0;
+; CHECK: mov.u64 %ret{{[0-9]+}}, 0;
; CHECK: ret;
ret i64 0
}
define ptx_device float @t1_f32() {
-; CHECK: mov.f32 r{{[0-9]+}}, 0F00000000;
+; CHECK: mov.f32 %ret{{[0-9]+}}, 0D0000000000000000;
; CHECK: ret;
ret float 0.0
}
define ptx_device double @t1_f64() {
-; CHECK: mov.f64 rd{{[0-9]+}}, 0D0000000000000000;
+; CHECK: mov.f64 %ret{{[0-9]+}}, 0D0000000000000000;
; CHECK: ret;
ret double 0.0
}
define ptx_device i16 @t2_u16(i16 %x) {
-; CHECK: mov.u16 rh{{[0-9]+}}, rh{{[0-9]+}};
+; CHECK: mov.b16 %ret{{[0-9]+}}, %param{{[0-9]+}};
; CHECK: ret;
ret i16 %x
}
define ptx_device i32 @t2_u32(i32 %x) {
-; CHECK: mov.u32 r{{[0-9]+}}, r{{[0-9]+}};
+; CHECK: mov.b32 %ret{{[0-9]+}}, %param{{[0-9]+}};
; CHECK: ret;
ret i32 %x
}
define ptx_device i64 @t2_u64(i64 %x) {
-; CHECK: mov.u64 rd{{[0-9]+}}, rd{{[0-9]+}};
+; CHECK: mov.b64 %ret{{[0-9]+}}, %param{{[0-9]+}};
; CHECK: ret;
ret i64 %x
}
define ptx_device float @t3_f32(float %x) {
-; CHECK: mov.u32 r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: mov.f32 %ret{{[0-9]+}}, %param{{[0-9]+}};
+; CHECK: ret;
ret float %x
}
define ptx_device double @t3_f64(double %x) {
-; CHECK: mov.u64 rd{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: mov.f64 %ret{{[0-9]+}}, %param{{[0-9]+}};
+; CHECK: ret;
ret double %x
}
diff --git a/test/CodeGen/PTX/mul.ll b/test/CodeGen/PTX/mul.ll
index 491cc74..91949db 100644
--- a/test/CodeGen/PTX/mul.ll
+++ b/test/CodeGen/PTX/mul.ll
@@ -11,29 +11,29 @@
;}
define ptx_device float @t1_f32(float %x, float %y) {
-; CHECK: mul.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}
-; CHECK-NEXT: ret;
+; CHECK: mul.rn.f32 %ret{{[0-9]+}}, %f{{[0-9]+}}, %f{{[0-9]+}}
+; CHECK: ret;
%z = fmul float %x, %y
ret float %z
}
define ptx_device double @t1_f64(double %x, double %y) {
-; CHECK: mul.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}
-; CHECK-NEXT: ret;
+; CHECK: mul.rn.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}}, %fd{{[0-9]+}}
+; CHECK: ret;
%z = fmul double %x, %y
ret double %z
}
define ptx_device float @t2_f32(float %x) {
-; CHECK: mul.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, 0F40A00000;
-; CHECK-NEXT: ret;
+; CHECK: mul.rn.f32 %ret{{[0-9]+}}, %f{{[0-9]+}}, 0D4014000000000000;
+; CHECK: ret;
%z = fmul float %x, 5.0
ret float %z
}
define ptx_device double @t2_f64(double %x) {
-; CHECK: mul.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, 0D4014000000000000;
-; CHECK-NEXT: ret;
+; CHECK: mul.rn.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}}, 0D4014000000000000;
+; CHECK: ret;
%z = fmul double %x, 5.0
ret double %z
}
diff --git a/test/CodeGen/PTX/parameter-order.ll b/test/CodeGen/PTX/parameter-order.ll
index b16556e..09015da 100644
--- a/test/CodeGen/PTX/parameter-order.ll
+++ b/test/CodeGen/PTX/parameter-order.ll
@@ -1,8 +1,8 @@
; RUN: llc < %s -march=ptx32 | FileCheck %s
-; CHECK: .func (.reg .b32 r{{[0-9]+}}) test_parameter_order (.reg .b32 r{{[0-9]+}}, .reg .b32 r{{[0-9]+}}, .reg .b32 r{{[0-9]+}}, .reg .b32 r{{[0-9]+}})
+; CHECK: .func (.reg .b32 %ret{{[0-9]+}}) test_parameter_order (.reg .b32 %param{{[0-9]+}}, .reg .b32 %param{{[0-9]+}}, .reg .b32 %param{{[0-9]+}}, .reg .b32 %param{{[0-9]+}})
define ptx_device i32 @test_parameter_order(float %a, i32 %b, i32 %c, float %d) {
-; CHECK: sub.u32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}
+; CHECK: sub.u32 %ret{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}
%result = sub i32 %b, %c
ret i32 %result
}
diff --git a/test/CodeGen/PTX/selp.ll b/test/CodeGen/PTX/selp.ll
index e705fbe..aa7ce85 100644
--- a/test/CodeGen/PTX/selp.ll
+++ b/test/CodeGen/PTX/selp.ll
@@ -1,25 +1,25 @@
; RUN: llc < %s -march=ptx32 | FileCheck %s
define ptx_device i32 @test_selp_i32(i1 %x, i32 %y, i32 %z) {
-; CHECK: selp.u32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, p{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}, %p{{[0-9]+}};
%a = select i1 %x, i32 %y, i32 %z
ret i32 %a
}
define ptx_device i64 @test_selp_i64(i1 %x, i64 %y, i64 %z) {
-; CHECK: selp.u64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}, p{{[0-9]+}};
+; CHECK: selp.u64 %ret{{[0-9]+}}, %rd{{[0-9]+}}, %rd{{[0-9]+}}, %p{{[0-9]+}};
%a = select i1 %x, i64 %y, i64 %z
ret i64 %a
}
define ptx_device float @test_selp_f32(i1 %x, float %y, float %z) {
-; CHECK: selp.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, p{{[0-9]+}};
+; CHECK: selp.f32 %ret{{[0-9]+}}, %f{{[0-9]+}}, %f{{[0-9]+}}, %p{{[0-9]+}};
%a = select i1 %x, float %y, float %z
ret float %a
}
define ptx_device double @test_selp_f64(i1 %x, double %y, double %z) {
-; CHECK: selp.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}, p{{[0-9]+}};
+; CHECK: selp.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}}, %fd{{[0-9]+}}, %p{{[0-9]+}};
%a = select i1 %x, double %y, double %z
ret double %a
}
diff --git a/test/CodeGen/PTX/setp.ll b/test/CodeGen/PTX/setp.ll
index e0044d6..646abab 100644
--- a/test/CodeGen/PTX/setp.ll
+++ b/test/CodeGen/PTX/setp.ll
@@ -1,190 +1,190 @@
; RUN: llc < %s -march=ptx32 | FileCheck %s
define ptx_device i32 @test_setp_eq_u32_rr(i32 %x, i32 %y) {
-; CHECK: setp.eq.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.eq.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp eq i32 %x, %y
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_ne_u32_rr(i32 %x, i32 %y) {
-; CHECK: setp.ne.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.ne.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp ne i32 %x, %y
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_lt_u32_rr(i32 %x, i32 %y) {
-; CHECK: setp.lt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.lt.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp ult i32 %x, %y
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_le_u32_rr(i32 %x, i32 %y) {
-; CHECK: setp.le.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.le.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp ule i32 %x, %y
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_gt_u32_rr(i32 %x, i32 %y) {
-; CHECK: setp.gt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp ugt i32 %x, %y
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_ge_u32_rr(i32 %x, i32 %y) {
-; CHECK: setp.ge.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.ge.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp uge i32 %x, %y
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_lt_s32_rr(i32 %x, i32 %y) {
-; CHECK: setp.lt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.lt.s32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp slt i32 %x, %y
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_le_s32_rr(i32 %x, i32 %y) {
-; CHECK: setp.le.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.le.s32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp sle i32 %x, %y
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_gt_s32_rr(i32 %x, i32 %y) {
-; CHECK: setp.gt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.s32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp sgt i32 %x, %y
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_ge_s32_rr(i32 %x, i32 %y) {
-; CHECK: setp.ge.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.ge.s32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp sge i32 %x, %y
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_eq_u32_ri(i32 %x) {
-; CHECK: setp.eq.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 1;
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.eq.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 1;
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp eq i32 %x, 1
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_ne_u32_ri(i32 %x) {
-; CHECK: setp.ne.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 1;
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.ne.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 1;
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp ne i32 %x, 1
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_lt_u32_ri(i32 %x) {
-; CHECK: setp.eq.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0;
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.eq.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 0;
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp ult i32 %x, 1
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_le_u32_ri(i32 %x) {
-; CHECK: setp.lt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 2;
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.lt.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 2;
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp ule i32 %x, 1
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_gt_u32_ri(i32 %x) {
-; CHECK: setp.gt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 1;
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 1;
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp ugt i32 %x, 1
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_ge_u32_ri(i32 %x) {
-; CHECK: setp.ne.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0;
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.ne.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 0;
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp uge i32 %x, 1
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_lt_s32_ri(i32 %x) {
-; CHECK: setp.lt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, 1;
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.lt.s32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 1;
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp slt i32 %x, 1
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_le_s32_ri(i32 %x) {
-; CHECK: setp.lt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, 2;
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.lt.s32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 2;
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp sle i32 %x, 1
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_gt_s32_ri(i32 %x) {
-; CHECK: setp.gt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, 1;
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.s32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 1;
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp sgt i32 %x, 1
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_ge_s32_ri(i32 %x) {
-; CHECK: setp.gt.s32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0;
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.s32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 0;
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p[[P0]];
+; CHECK: ret;
%p = icmp sge i32 %x, 1
%z = zext i1 %p to i32
ret i32 %z
}
define ptx_device i32 @test_setp_4_op_format_1(i32 %x, i32 %y, i32 %u, i32 %v) {
-; CHECK: setp.gt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: setp.eq.and.u32 p[[P0]], r{{[0-9]+}}, r{{[0-9]+}}, p[[P0]];
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: setp.eq.and.u32 %p1, %r{{[0-9]+}}, %r{{[0-9]+}}, %p[[P0]];
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p1;
+; CHECK: ret;
%c = icmp eq i32 %x, %y
%d = icmp ugt i32 %u, %v
%e = and i1 %c, %d
@@ -193,10 +193,10 @@ define ptx_device i32 @test_setp_4_op_format_1(i32 %x, i32 %y, i32 %u, i32 %v) {
}
define ptx_device i32 @test_setp_4_op_format_2(i32 %x, i32 %y, i32 %w) {
-; CHECK: setp.gt.u32 p[[P0:[0-9]+]], r{{[0-9]+}}, 0;
-; CHECK-NEXT: setp.eq.and.u32 p[[P0]], r{{[0-9]+}}, r{{[0-9]+}}, !p[[P0]];
-; CHECK-NEXT: selp.u32 r{{[0-9]+}}, 1, 0, p[[P0]];
-; CHECK-NEXT: ret;
+; CHECK: setp.gt.u32 %p[[P0:[0-9]+]], %r{{[0-9]+}}, 0;
+; CHECK: setp.eq.and.u32 %p1, %r{{[0-9]+}}, %r{{[0-9]+}}, !%p[[P0]];
+; CHECK: selp.u32 %ret{{[0-9]+}}, 1, 0, %p1;
+; CHECK: ret;
%c = trunc i32 %w to i1
%d = icmp eq i32 %x, %y
%e = xor i1 %c, 1
diff --git a/test/CodeGen/PTX/shl.ll b/test/CodeGen/PTX/shl.ll
index b3818e1..d9fe2cd 100644
--- a/test/CodeGen/PTX/shl.ll
+++ b/test/CodeGen/PTX/shl.ll
@@ -1,21 +1,21 @@
; RUN: llc < %s -march=ptx32 | FileCheck %s
define ptx_device i32 @t1(i32 %x, i32 %y) {
-; CHECK: shl.b32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}
+; CHECK: shl.b32 %ret{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}
%z = shl i32 %x, %y
; CHECK: ret;
ret i32 %z
}
define ptx_device i32 @t2(i32 %x) {
-; CHECK: shl.b32 r{{[0-9]+}}, r{{[0-9]+}}, 3
+; CHECK: shl.b32 %ret{{[0-9]+}}, %r{{[0-9]+}}, 3
%z = shl i32 %x, 3
; CHECK: ret;
ret i32 %z
}
define ptx_device i32 @t3(i32 %x) {
-; CHECK: shl.b32 r{{[0-9]+}}, 3, r{{[0-9]+}}
+; CHECK: shl.b32 %ret{{[0-9]+}}, 3, %r{{[0-9]+}}
%z = shl i32 3, %x
; CHECK: ret;
ret i32 %z
diff --git a/test/CodeGen/PTX/shr.ll b/test/CodeGen/PTX/shr.ll
index cb57546..eb4666f 100644
--- a/test/CodeGen/PTX/shr.ll
+++ b/test/CodeGen/PTX/shr.ll
@@ -1,42 +1,42 @@
; RUN: llc < %s -march=ptx32 | FileCheck %s
define ptx_device i32 @t1(i32 %x, i32 %y) {
-; CHECK: shr.u32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}
+; CHECK: shr.u32 %ret{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}
%z = lshr i32 %x, %y
; CHECK: ret;
ret i32 %z
}
define ptx_device i32 @t2(i32 %x) {
-; CHECK: shr.u32 r{{[0-9]+}}, r{{[0-9]+}}, 3
+; CHECK: shr.u32 %ret{{[0-9]+}}, %r{{[0-9]+}}, 3
%z = lshr i32 %x, 3
; CHECK: ret;
ret i32 %z
}
define ptx_device i32 @t3(i32 %x) {
-; CHECK: shr.u32 r{{[0-9]+}}, 3, r{{[0-9]+}}
+; CHECK: shr.u32 %ret{{[0-9]+}}, 3, %r{{[0-9]+}}
%z = lshr i32 3, %x
; CHECK: ret;
ret i32 %z
}
define ptx_device i32 @t4(i32 %x, i32 %y) {
-; CHECK: shr.s32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}
+; CHECK: shr.s32 %ret{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}
%z = ashr i32 %x, %y
; CHECK: ret;
ret i32 %z
}
define ptx_device i32 @t5(i32 %x) {
-; CHECK: shr.s32 r{{[0-9]+}}, r{{[0-9]+}}, 3
+; CHECK: shr.s32 %ret{{[0-9]+}}, %r{{[0-9]+}}, 3
%z = ashr i32 %x, 3
; CHECK: ret;
ret i32 %z
}
define ptx_device i32 @t6(i32 %x) {
-; CHECK: shr.s32 r{{[0-9]+}}, -3, r{{[0-9]+}}
+; CHECK: shr.s32 %ret{{[0-9]+}}, -3, %r{{[0-9]+}}
%z = ashr i32 -3, %x
; CHECK: ret;
ret i32 %z
diff --git a/test/CodeGen/PTX/simple-call.ll b/test/CodeGen/PTX/simple-call.ll
new file mode 100644
index 0000000..77ea29e
--- /dev/null
+++ b/test/CodeGen/PTX/simple-call.ll
@@ -0,0 +1,27 @@
+; RUN: llc < %s -march=ptx32 -mattr=sm20 | FileCheck %s
+
+define ptx_device void @test_add(float %x, float %y) {
+; CHECK: ret;
+ %z = fadd float %x, %y
+ ret void
+}
+
+define ptx_device float @test_call(float %x, float %y) {
+ %a = fadd float %x, %y
+; CHECK: call.uni test_add, (__localparam_{{[0-9]+}}, __localparam_{{[0-9]+}});
+ call void @test_add(float %a, float %y)
+ ret float %a
+}
+
+define ptx_device float @test_compute(float %x, float %y) {
+; CHECK: ret;
+ %z = fadd float %x, %y
+ ret float %z
+}
+
+define ptx_device float @test_call_compute(float %x, float %y) {
+; CHECK: call.uni (__localparam_{{[0-9]+}}), test_compute, (__localparam_{{[0-9]+}}, __localparam_{{[0-9]+}})
+ %z = call float @test_compute(float %x, float %y)
+ ret float %z
+}
+
diff --git a/test/CodeGen/PTX/st.ll b/test/CodeGen/PTX/st.ll
index b08528e..63ef58c 100644
--- a/test/CodeGen/PTX/st.ll
+++ b/test/CodeGen/PTX/st.ll
@@ -6,9 +6,6 @@
;CHECK: .extern .const .b8 array_constant_i16[20];
@array_constant_i16 = external addrspace(1) constant [10 x i16]
-;CHECK: .extern .local .b8 array_local_i16[20];
-@array_local_i16 = external addrspace(2) global [10 x i16]
-
;CHECK: .extern .shared .b8 array_shared_i16[20];
@array_shared_i16 = external addrspace(4) global [10 x i16]
@@ -18,9 +15,6 @@
;CHECK: .extern .const .b8 array_constant_i32[40];
@array_constant_i32 = external addrspace(1) constant [10 x i32]
-;CHECK: .extern .local .b8 array_local_i32[40];
-@array_local_i32 = external addrspace(2) global [10 x i32]
-
;CHECK: .extern .shared .b8 array_shared_i32[40];
@array_shared_i32 = external addrspace(4) global [10 x i32]
@@ -30,9 +24,6 @@
;CHECK: .extern .const .b8 array_constant_i64[80];
@array_constant_i64 = external addrspace(1) constant [10 x i64]
-;CHECK: .extern .local .b8 array_local_i64[80];
-@array_local_i64 = external addrspace(2) global [10 x i64]
-
;CHECK: .extern .shared .b8 array_shared_i64[80];
@array_shared_i64 = external addrspace(4) global [10 x i64]
@@ -42,9 +33,6 @@
;CHECK: .extern .const .b8 array_constant_float[40];
@array_constant_float = external addrspace(1) constant [10 x float]
-;CHECK: .extern .local .b8 array_local_float[40];
-@array_local_float = external addrspace(2) global [10 x float]
-
;CHECK: .extern .shared .b8 array_shared_float[40];
@array_shared_float = external addrspace(4) global [10 x float]
@@ -54,57 +42,54 @@
;CHECK: .extern .const .b8 array_constant_double[80];
@array_constant_double = external addrspace(1) constant [10 x double]
-;CHECK: .extern .local .b8 array_local_double[80];
-@array_local_double = external addrspace(2) global [10 x double]
-
;CHECK: .extern .shared .b8 array_shared_double[80];
@array_shared_double = external addrspace(4) global [10 x double]
define ptx_device void @t1_u16(i16* %p, i16 %x) {
entry:
-;CHECK: st.global.u16 [r{{[0-9]+}}], rh{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: st.global.u16 [%r{{[0-9]+}}], %rh{{[0-9]+}};
+;CHECK: ret;
store i16 %x, i16* %p
ret void
}
define ptx_device void @t1_u32(i32* %p, i32 %x) {
entry:
-;CHECK: st.global.u32 [r{{[0-9]+}}], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: st.global.u32 [%r{{[0-9]+}}], %r{{[0-9]+}};
+;CHECK: ret;
store i32 %x, i32* %p
ret void
}
define ptx_device void @t1_u64(i64* %p, i64 %x) {
entry:
-;CHECK: st.global.u64 [r{{[0-9]+}}], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: st.global.u64 [%r{{[0-9]+}}], %rd{{[0-9]+}};
+;CHECK: ret;
store i64 %x, i64* %p
ret void
}
define ptx_device void @t1_f32(float* %p, float %x) {
entry:
-;CHECK: st.global.f32 [r{{[0-9]+}}], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: st.global.f32 [%r{{[0-9]+}}], %f{{[0-9]+}};
+;CHECK: ret;
store float %x, float* %p
ret void
}
define ptx_device void @t1_f64(double* %p, double %x) {
entry:
-;CHECK: st.global.f64 [r{{[0-9]+}}], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: st.global.f64 [%r{{[0-9]+}}], %fd{{[0-9]+}};
+;CHECK: ret;
store double %x, double* %p
ret void
}
define ptx_device void @t2_u16(i16* %p, i16 %x) {
entry:
-;CHECK: st.global.u16 [r{{[0-9]+}}+2], rh{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: st.global.u16 [%r{{[0-9]+}}+2], %rh{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr i16* %p, i32 1
store i16 %x, i16* %i
ret void
@@ -112,8 +97,8 @@ entry:
define ptx_device void @t2_u32(i32* %p, i32 %x) {
entry:
-;CHECK: st.global.u32 [r{{[0-9]+}}+4], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: st.global.u32 [%r{{[0-9]+}}+4], %r{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr i32* %p, i32 1
store i32 %x, i32* %i
ret void
@@ -121,8 +106,8 @@ entry:
define ptx_device void @t2_u64(i64* %p, i64 %x) {
entry:
-;CHECK: st.global.u64 [r{{[0-9]+}}+8], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: st.global.u64 [%r{{[0-9]+}}+8], %rd{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr i64* %p, i32 1
store i64 %x, i64* %i
ret void
@@ -130,8 +115,8 @@ entry:
define ptx_device void @t2_f32(float* %p, float %x) {
entry:
-;CHECK: st.global.f32 [r{{[0-9]+}}+4], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: st.global.f32 [%r{{[0-9]+}}+4], %f{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr float* %p, i32 1
store float %x, float* %i
ret void
@@ -139,8 +124,8 @@ entry:
define ptx_device void @t2_f64(double* %p, double %x) {
entry:
-;CHECK: st.global.f64 [r{{[0-9]+}}+8], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: st.global.f64 [%r{{[0-9]+}}+8], %fd{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr double* %p, i32 1
store double %x, double* %i
ret void
@@ -148,10 +133,10 @@ entry:
define ptx_device void @t3_u16(i16* %p, i32 %q, i16 %x) {
entry:
-;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 1;
-;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]];
-;CHECK-NEXT: st.global.u16 [r[[R0]]], rh{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: shl.b32 %r[[R0:[0-9]+]], %r{{[0-9]+}}, 1;
+;CHECK: add.u32 %r{{[0-9]+}}, %r{{[0-9]+}}, %r[[R0]];
+;CHECK: st.global.u16 [%r{{[0-9]+}}], %rh{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr i16* %p, i32 %q
store i16 %x, i16* %i
ret void
@@ -159,10 +144,10 @@ entry:
define ptx_device void @t3_u32(i32* %p, i32 %q, i32 %x) {
entry:
-;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 2;
-;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]];
-;CHECK-NEXT: st.global.u32 [r[[R0]]], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: shl.b32 %r[[R0:[0-9]+]], %r{{[0-9]+}}, 2;
+;CHECK: add.u32 %r{{[0-9]+}}, %r{{[0-9]+}}, %r[[R0]];
+;CHECK: st.global.u32 [%r{{[0-9]+}}], %r{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr i32* %p, i32 %q
store i32 %x, i32* %i
ret void
@@ -170,10 +155,10 @@ entry:
define ptx_device void @t3_u64(i64* %p, i32 %q, i64 %x) {
entry:
-;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 3;
-;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]];
-;CHECK-NEXT: st.global.u64 [r[[R0]]], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: shl.b32 %r[[R0:[0-9]+]], %r{{[0-9]+}}, 3;
+;CHECK: add.u32 %r{{[0-9]+}}, %r{{[0-9]+}}, %r[[R0]];
+;CHECK: st.global.u64 [%r{{[0-9]+}}], %rd{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr i64* %p, i32 %q
store i64 %x, i64* %i
ret void
@@ -181,10 +166,10 @@ entry:
define ptx_device void @t3_f32(float* %p, i32 %q, float %x) {
entry:
-;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 2;
-;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]];
-;CHECK-NEXT: st.global.f32 [r[[R0]]], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: shl.b32 %r[[R0:[0-9]+]], %r{{[0-9]+}}, 2;
+;CHECK: add.u32 %r{{[0-9]+}}, %r{{[0-9]+}}, %r[[R0]];
+;CHECK: st.global.f32 [%r{{[0-9]+}}], %f{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr float* %p, i32 %q
store float %x, float* %i
ret void
@@ -192,10 +177,10 @@ entry:
define ptx_device void @t3_f64(double* %p, i32 %q, double %x) {
entry:
-;CHECK: shl.b32 r[[R0:[0-9]+]], r{{[0-9]+}}, 3;
-;CHECK-NEXT: add.u32 r[[R0]], r{{[0-9]+}}, r[[R0]];
-;CHECK-NEXT: st.global.f64 [r[[R0]]], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: shl.b32 %r[[R0:[0-9]+]], %r{{[0-9]+}}, 3;
+;CHECK: add.u32 %r{{[0-9]+}}, %r{{[0-9]+}}, %r[[R0]];
+;CHECK: st.global.f64 [%r{{[0-9]+}}], %fd{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr double* %p, i32 %q
store double %x, double* %i
ret void
@@ -203,9 +188,9 @@ entry:
define ptx_device void @t4_global_u16(i16 %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16;
-;CHECK-NEXT: st.global.u16 [r[[R0]]], rh{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i16;
+;CHECK: st.global.u16 [%r[[R0]]], %rh{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x i16]* @array_i16, i16 0, i16 0
store i16 %x, i16* %i
ret void
@@ -213,9 +198,9 @@ entry:
define ptx_device void @t4_global_u32(i32 %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i32;
-;CHECK-NEXT: st.global.u32 [r[[R0]]], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i32;
+;CHECK: st.global.u32 [%r[[R0]]], %r{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x i32]* @array_i32, i32 0, i32 0
store i32 %x, i32* %i
ret void
@@ -223,9 +208,9 @@ entry:
define ptx_device void @t4_global_u64(i64 %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i64;
-;CHECK-NEXT: st.global.u64 [r[[R0]]], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i64;
+;CHECK: st.global.u64 [%r[[R0]]], %rd{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x i64]* @array_i64, i32 0, i32 0
store i64 %x, i64* %i
ret void
@@ -233,9 +218,9 @@ entry:
define ptx_device void @t4_global_f32(float %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_float;
-;CHECK-NEXT: st.global.f32 [r[[R0]]], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_float;
+;CHECK: st.global.f32 [%r[[R0]]], %f{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x float]* @array_float, i32 0, i32 0
store float %x, float* %i
ret void
@@ -243,69 +228,19 @@ entry:
define ptx_device void @t4_global_f64(double %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_double;
-;CHECK-NEXT: st.global.f64 [r[[R0]]], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_double;
+;CHECK: st.global.f64 [%r[[R0]]], %fd{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x double]* @array_double, i32 0, i32 0
store double %x, double* %i
ret void
}
-define ptx_device void @t4_local_u16(i16 %x) {
-entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i16;
-;CHECK-NEXT: st.local.u16 [r[[R0]]], rh{{[0-9]+}};
-;CHECK-NEXT: ret;
- %i = getelementptr [10 x i16] addrspace(2)* @array_local_i16, i32 0, i32 0
- store i16 %x, i16 addrspace(2)* %i
- ret void
-}
-
-define ptx_device void @t4_local_u32(i32 %x) {
-entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i32;
-;CHECK-NEXT: st.local.u32 [r[[R0]]], r{{[0-9]+}};
-;CHECK-NEXT: ret;
- %i = getelementptr [10 x i32] addrspace(2)* @array_local_i32, i32 0, i32 0
- store i32 %x, i32 addrspace(2)* %i
- ret void
-}
-
-define ptx_device void @t4_local_u64(i64 %x) {
-entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_i64;
-;CHECK-NEXT: st.local.u64 [r[[R0]]], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
- %i = getelementptr [10 x i64] addrspace(2)* @array_local_i64, i32 0, i32 0
- store i64 %x, i64 addrspace(2)* %i
- ret void
-}
-
-define ptx_device void @t4_local_f32(float %x) {
-entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_float;
-;CHECK-NEXT: st.local.f32 [r[[R0]]], r{{[0-9]+}};
-;CHECK-NEXT: ret;
- %i = getelementptr [10 x float] addrspace(2)* @array_local_float, i32 0, i32 0
- store float %x, float addrspace(2)* %i
- ret void
-}
-
-define ptx_device void @t4_local_f64(double %x) {
-entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_local_double;
-;CHECK-NEXT: st.local.f64 [r[[R0]]], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
- %i = getelementptr [10 x double] addrspace(2)* @array_local_double, i32 0, i32 0
- store double %x, double addrspace(2)* %i
- ret void
-}
-
define ptx_device void @t4_shared_u16(i16 %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i16;
-;CHECK-NEXT: st.shared.u16 [r[[R0]]], rh{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_shared_i16;
+;CHECK: st.shared.u16 [%r[[R0]]], %rh{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x i16] addrspace(4)* @array_shared_i16, i32 0, i32 0
store i16 %x, i16 addrspace(4)* %i
ret void
@@ -313,9 +248,9 @@ entry:
define ptx_device void @t4_shared_u32(i32 %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i32;
-;CHECK-NEXT: st.shared.u32 [r[[R0]]], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_shared_i32;
+;CHECK: st.shared.u32 [%r[[R0]]], %r{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x i32] addrspace(4)* @array_shared_i32, i32 0, i32 0
store i32 %x, i32 addrspace(4)* %i
ret void
@@ -323,9 +258,9 @@ entry:
define ptx_device void @t4_shared_u64(i64 %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_i64;
-;CHECK-NEXT: st.shared.u64 [r[[R0]]], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_shared_i64;
+;CHECK: st.shared.u64 [%r[[R0]]], %rd{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x i64] addrspace(4)* @array_shared_i64, i32 0, i32 0
store i64 %x, i64 addrspace(4)* %i
ret void
@@ -333,9 +268,9 @@ entry:
define ptx_device void @t4_shared_f32(float %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_float;
-;CHECK-NEXT: st.shared.f32 [r[[R0]]], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_shared_float;
+;CHECK: st.shared.f32 [%r[[R0]]], %f{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x float] addrspace(4)* @array_shared_float, i32 0, i32 0
store float %x, float addrspace(4)* %i
ret void
@@ -343,9 +278,9 @@ entry:
define ptx_device void @t4_shared_f64(double %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_shared_double;
-;CHECK-NEXT: st.shared.f64 [r[[R0]]], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_shared_double;
+;CHECK: st.shared.f64 [%r[[R0]]], %fd{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x double] addrspace(4)* @array_shared_double, i32 0, i32 0
store double %x, double addrspace(4)* %i
ret void
@@ -353,9 +288,9 @@ entry:
define ptx_device void @t5_u16(i16 %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i16;
-;CHECK-NEXT: st.global.u16 [r[[R0]]+2], rh{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i16;
+;CHECK: st.global.u16 [%r[[R0]]+2], %rh{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x i16]* @array_i16, i32 0, i32 1
store i16 %x, i16* %i
ret void
@@ -363,9 +298,9 @@ entry:
define ptx_device void @t5_u32(i32 %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i32;
-;CHECK-NEXT: st.global.u32 [r[[R0]]+4], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i32;
+;CHECK: st.global.u32 [%r[[R0]]+4], %r{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x i32]* @array_i32, i32 0, i32 1
store i32 %x, i32* %i
ret void
@@ -373,9 +308,9 @@ entry:
define ptx_device void @t5_u64(i64 %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_i64;
-;CHECK-NEXT: st.global.u64 [r[[R0]]+8], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_i64;
+;CHECK: st.global.u64 [%r[[R0]]+8], %rd{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x i64]* @array_i64, i32 0, i32 1
store i64 %x, i64* %i
ret void
@@ -383,9 +318,9 @@ entry:
define ptx_device void @t5_f32(float %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_float;
-;CHECK-NEXT: st.global.f32 [r[[R0]]+4], r{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_float;
+;CHECK: st.global.f32 [%r[[R0]]+4], %f{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x float]* @array_float, i32 0, i32 1
store float %x, float* %i
ret void
@@ -393,9 +328,9 @@ entry:
define ptx_device void @t5_f64(double %x) {
entry:
-;CHECK: mov.u32 r[[R0:[0-9]+]], array_double;
-;CHECK-NEXT: st.global.f64 [r[[R0]]+8], rd{{[0-9]+}};
-;CHECK-NEXT: ret;
+;CHECK: mov.u32 %r[[R0:[0-9]+]], array_double;
+;CHECK: st.global.f64 [%r[[R0]]+8], %fd{{[0-9]+}};
+;CHECK: ret;
%i = getelementptr [10 x double]* @array_double, i32 0, i32 1
store double %x, double* %i
ret void
diff --git a/test/CodeGen/PTX/stack-object.ll b/test/CodeGen/PTX/stack-object.ll
new file mode 100644
index 0000000..65f8ee2
--- /dev/null
+++ b/test/CodeGen/PTX/stack-object.ll
@@ -0,0 +1,19 @@
+; RUN: llc < %s -march=ptx32 -mattr=sm20 | FileCheck %s
+
+define ptx_device float @stack1(float %a) {
+ ; CHECK: .local .align 4 .b8 __local0[4];
+ %a.2 = alloca float, align 4
+ ; CHECK: st.local.f32 [__local0], %f0
+ store float %a, float* %a.2
+ %a.3 = load float* %a.2
+ ret float %a.3
+}
+
+define ptx_device float @stack1_align8(float %a) {
+ ; CHECK: .local .align 8 .b8 __local0[4];
+ %a.2 = alloca float, align 8
+ ; CHECK: st.local.f32 [__local0], %f0
+ store float %a, float* %a.2
+ %a.3 = load float* %a.2
+ ret float %a.3
+}
diff --git a/test/CodeGen/PTX/sub.ll b/test/CodeGen/PTX/sub.ll
index acef396..7ac886a 100644
--- a/test/CodeGen/PTX/sub.ll
+++ b/test/CodeGen/PTX/sub.ll
@@ -1,71 +1,71 @@
; RUN: llc < %s -march=ptx32 | FileCheck %s
define ptx_device i16 @t1_u16(i16 %x, i16 %y) {
-; CHECK: sub.u16 rh{{[0-9]+}}, rh{{[0-9]+}}, rh{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: sub.u16 %ret{{[0-9]+}}, %rh{{[0-9]+}}, %rh{{[0-9]+}};
+; CHECK: ret;
%z = sub i16 %x, %y
ret i16 %z
}
define ptx_device i32 @t1_u32(i32 %x, i32 %y) {
-; CHECK: sub.u32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: sub.u32 %ret{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}};
+; CHECK: ret;
%z = sub i32 %x, %y
ret i32 %z
}
define ptx_device i64 @t1_u64(i64 %x, i64 %y) {
-; CHECK: sub.u64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}};
-; CHECK-NEXT: ret;
+; CHECK: sub.u64 %ret{{[0-9]+}}, %rd{{[0-9]+}}, %rd{{[0-9]+}};
+; CHECK: ret;
%z = sub i64 %x, %y
ret i64 %z
}
define ptx_device float @t1_f32(float %x, float %y) {
-; CHECK: sub.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}
-; CHECK-NEXT: ret;
+; CHECK: sub.rn.f32 %ret{{[0-9]+}}, %f{{[0-9]+}}, %f{{[0-9]+}}
+; CHECK: ret;
%z = fsub float %x, %y
ret float %z
}
define ptx_device double @t1_f64(double %x, double %y) {
-; CHECK: sub.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, rd{{[0-9]+}}
-; CHECK-NEXT: ret;
+; CHECK: sub.rn.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}}, %fd{{[0-9]+}}
+; CHECK: ret;
%z = fsub double %x, %y
ret double %z
}
define ptx_device i16 @t2_u16(i16 %x) {
-; CHECK: add.u16 rh{{[0-9]+}}, rh{{[0-9]+}}, -1;
-; CHECK-NEXT: ret;
+; CHECK: add.u16 %ret{{[0-9]+}}, %rh{{[0-9]+}}, -1;
+; CHECK: ret;
%z = sub i16 %x, 1
ret i16 %z
}
define ptx_device i32 @t2_u32(i32 %x) {
-; CHECK: add.u32 r{{[0-9]+}}, r{{[0-9]+}}, -1;
-; CHECK-NEXT: ret;
+; CHECK: add.u32 %ret{{[0-9]+}}, %r{{[0-9]+}}, -1;
+; CHECK: ret;
%z = sub i32 %x, 1
ret i32 %z
}
define ptx_device i64 @t2_u64(i64 %x) {
-; CHECK: add.u64 rd{{[0-9]+}}, rd{{[0-9]+}}, -1;
-; CHECK-NEXT: ret;
+; CHECK: add.u64 %ret{{[0-9]+}}, %rd{{[0-9]+}}, -1;
+; CHECK: ret;
%z = sub i64 %x, 1
ret i64 %z
}
define ptx_device float @t2_f32(float %x) {
-; CHECK: add.rn.f32 r{{[0-9]+}}, r{{[0-9]+}}, 0FBF800000;
-; CHECK-NEXT: ret;
+; CHECK: add.rn.f32 %ret{{[0-9]+}}, %f{{[0-9]+}}, 0DBFF0000000000000;
+; CHECK: ret;
%z = fsub float %x, 1.0
ret float %z
}
define ptx_device double @t2_f64(double %x) {
-; CHECK: add.rn.f64 rd{{[0-9]+}}, rd{{[0-9]+}}, 0DBFF0000000000000;
-; CHECK-NEXT: ret;
+; CHECK: add.rn.f64 %ret{{[0-9]+}}, %fd{{[0-9]+}}, 0DBFF0000000000000;
+; CHECK: ret;
%z = fsub double %x, 1.0
ret double %z
}
diff --git a/test/CodeGen/PowerPC/2007-11-16-landingpad-split.ll b/test/CodeGen/PowerPC/2007-11-16-landingpad-split.ll
index 0c11674..ecf45ef 100644
--- a/test/CodeGen/PowerPC/2007-11-16-landingpad-split.ll
+++ b/test/CodeGen/PowerPC/2007-11-16-landingpad-split.ll
@@ -18,11 +18,10 @@ bb30.preheader: ; preds = %entry
br label %bb30
unwind: ; preds = %cond_true, %entry
- %eh_ptr = call i8* @llvm.eh.exception() ; <i8*> [#uses=2]
- %eh_select = call i64 (i8*, i8*, ...)* @llvm.eh.selector.i64(i8* %eh_ptr, i8* bitcast (void ()* @__gxx_personality_v0 to i8*), i8* null) ; <i64> [#uses=0]
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
call void @llvm.stackrestore(i8* %tmp4)
- call void @_Unwind_Resume(i8* %eh_ptr)
- unreachable
+ resume { i8*, i32 } %exn
invcont23: ; preds = %cond_true
%tmp27 = load i64* %tmp26, align 8 ; <i64> [#uses=1]
@@ -46,14 +45,8 @@ declare i8* @llvm.stacksave() nounwind
declare void @Foo(i8**)
-declare i8* @llvm.eh.exception() nounwind
-
-declare i64 @llvm.eh.selector.i64(i8*, i8*, ...) nounwind
-
-declare void @__gxx_personality_v0()
-
-declare void @_Unwind_Resume(i8*)
-
declare void @Bar(i64, %struct.Range*)
declare void @llvm.stackrestore(i8*) nounwind
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/PowerPC/2009-01-16-DeclareISelBug.ll b/test/CodeGen/PowerPC/2009-01-16-DeclareISelBug.ll
index d49d58d..ce8e72d 100644
--- a/test/CodeGen/PowerPC/2009-01-16-DeclareISelBug.ll
+++ b/test/CodeGen/PowerPC/2009-01-16-DeclareISelBug.ll
@@ -1,13 +1,6 @@
; RUN: llc < %s -mtriple=powerpc-apple-darwin9.5
; rdar://6499616
- %llvm.dbg.anchor.type = type { i32, i32 }
- %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8* }
-@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 17 } ; <%llvm.dbg.anchor.type*> [#uses=1]
-@.str = internal constant [11 x i8] c"testcase.c\00" ; <[11 x i8]*> [#uses=1]
-@.str1 = internal constant [30 x i8] c"/Volumes/SandBox/NightlyTest/\00" ; <[30 x i8]*> [#uses=1]
-@.str2 = internal constant [57 x i8] c"4.2.1 (Based on Apple Inc. build 5628) (LLVM build 9999)\00" ; <[57 x i8]*> [#uses=1]
-@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { i32 458769, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to { }*), i32 1, i8* getelementptr ([11 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([30 x i8]* @.str1, i32 0, i32 0), i8* getelementptr ([57 x i8]* @.str2, i32 0, i32 0) } ; <%llvm.dbg.compile_unit.type*> [#uses=0]
@"\01LC" = internal constant [13 x i8] c"conftest.val\00" ; <[13 x i8]*> [#uses=1]
define i32 @main() nounwind {
diff --git a/test/CodeGen/PowerPC/2009-08-23-linkerprivate.ll b/test/CodeGen/PowerPC/2009-08-23-linkerprivate.ll
index 0bde2d5..ae2acd4 100644
--- a/test/CodeGen/PowerPC/2009-08-23-linkerprivate.ll
+++ b/test/CodeGen/PowerPC/2009-08-23-linkerprivate.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -march=ppc32 -mtriple=ppc-apple-darwin | FileCheck %s
+; RUN: llc < %s -march=ppc32 -mtriple=powerpc-apple-darwin | FileCheck %s
; ModuleID = '/Volumes/MacOS9/tests/WebKit/JavaScriptCore/profiler/ProfilerServer.mm'
diff --git a/test/CodeGen/PowerPC/Atomics-32.ll b/test/CodeGen/PowerPC/Atomics-32.ll
index 03905a3..64f1495 100644
--- a/test/CodeGen/PowerPC/Atomics-32.ll
+++ b/test/CodeGen/PowerPC/Atomics-32.ll
@@ -1,749 +1,699 @@
; RUN: llc < %s -march=ppc32
-; ModuleID = 'Atomics.c'
target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f128:64:128"
target triple = "powerpc-apple-darwin9"
-@sc = common global i8 0 ; <i8*> [#uses=52]
-@uc = common global i8 0 ; <i8*> [#uses=100]
-@ss = common global i16 0 ; <i16*> [#uses=15]
-@us = common global i16 0 ; <i16*> [#uses=15]
-@si = common global i32 0 ; <i32*> [#uses=15]
-@ui = common global i32 0 ; <i32*> [#uses=23]
-@sl = common global i32 0 ; <i32*> [#uses=15]
-@ul = common global i32 0 ; <i32*> [#uses=15]
-@sll = common global i64 0, align 8 ; <i64*> [#uses=1]
-@ull = common global i64 0, align 8 ; <i64*> [#uses=1]
+
+@sc = common global i8 0
+@uc = common global i8 0
+@ss = common global i16 0
+@us = common global i16 0
+@si = common global i32 0
+@ui = common global i32 0
+@sl = common global i32 0
+@ul = common global i32 0
+@sll = common global i64 0, align 8
+@ull = common global i64 0, align 8
define void @test_op_ignore() nounwind {
entry:
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:0 [#uses=0]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:1 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %2, i16 1 ) ; <i16>:3 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %4, i16 1 ) ; <i16>:5 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %6, i32 1 ) ; <i32>:7 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %8, i32 1 ) ; <i32>:9 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:10 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %10, i32 1 ) ; <i32>:11 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:12 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %12, i32 1 ) ; <i32>:13 [#uses=0]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:14 [#uses=0]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:15 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:16 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %16, i16 1 ) ; <i16>:17 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:18 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %18, i16 1 ) ; <i16>:19 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:20 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %20, i32 1 ) ; <i32>:21 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:22 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %22, i32 1 ) ; <i32>:23 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:24 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %24, i32 1 ) ; <i32>:25 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:26 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %26, i32 1 ) ; <i32>:27 [#uses=0]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:28 [#uses=0]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:29 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:30 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %30, i16 1 ) ; <i16>:31 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:32 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %32, i16 1 ) ; <i16>:33 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:34 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %34, i32 1 ) ; <i32>:35 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:36 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %36, i32 1 ) ; <i32>:37 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:38 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %38, i32 1 ) ; <i32>:39 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:40 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %40, i32 1 ) ; <i32>:41 [#uses=0]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:42 [#uses=0]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:43 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:44 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %44, i16 1 ) ; <i16>:45 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:46 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %46, i16 1 ) ; <i16>:47 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:48 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %48, i32 1 ) ; <i32>:49 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:50 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %50, i32 1 ) ; <i32>:51 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:52 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %52, i32 1 ) ; <i32>:53 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:54 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %54, i32 1 ) ; <i32>:55 [#uses=0]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:56 [#uses=0]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:57 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:58 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %58, i16 1 ) ; <i16>:59 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:60 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %60, i16 1 ) ; <i16>:61 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:62 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %62, i32 1 ) ; <i32>:63 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:64 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %64, i32 1 ) ; <i32>:65 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:66 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %66, i32 1 ) ; <i32>:67 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:68 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %68, i32 1 ) ; <i32>:69 [#uses=0]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:70 [#uses=0]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:71 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:72 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %72, i16 1 ) ; <i16>:73 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:74 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %74, i16 1 ) ; <i16>:75 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:76 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %76, i32 1 ) ; <i32>:77 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:78 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %78, i32 1 ) ; <i32>:79 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:80 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %80, i32 1 ) ; <i32>:81 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:82 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %82, i32 1 ) ; <i32>:83 [#uses=0]
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = atomicrmw add i8* @sc, i8 1 monotonic
+ %1 = atomicrmw add i8* @uc, i8 1 monotonic
+ %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %3 = atomicrmw add i16* %2, i16 1 monotonic
+ %4 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %5 = atomicrmw add i16* %4, i16 1 monotonic
+ %6 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %7 = atomicrmw add i32* %6, i32 1 monotonic
+ %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %9 = atomicrmw add i32* %8, i32 1 monotonic
+ %10 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %11 = atomicrmw add i32* %10, i32 1 monotonic
+ %12 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %13 = atomicrmw add i32* %12, i32 1 monotonic
+ %14 = atomicrmw sub i8* @sc, i8 1 monotonic
+ %15 = atomicrmw sub i8* @uc, i8 1 monotonic
+ %16 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %17 = atomicrmw sub i16* %16, i16 1 monotonic
+ %18 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %19 = atomicrmw sub i16* %18, i16 1 monotonic
+ %20 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %21 = atomicrmw sub i32* %20, i32 1 monotonic
+ %22 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %23 = atomicrmw sub i32* %22, i32 1 monotonic
+ %24 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %25 = atomicrmw sub i32* %24, i32 1 monotonic
+ %26 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %27 = atomicrmw sub i32* %26, i32 1 monotonic
+ %28 = atomicrmw or i8* @sc, i8 1 monotonic
+ %29 = atomicrmw or i8* @uc, i8 1 monotonic
+ %30 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %31 = atomicrmw or i16* %30, i16 1 monotonic
+ %32 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %33 = atomicrmw or i16* %32, i16 1 monotonic
+ %34 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %35 = atomicrmw or i32* %34, i32 1 monotonic
+ %36 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %37 = atomicrmw or i32* %36, i32 1 monotonic
+ %38 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %39 = atomicrmw or i32* %38, i32 1 monotonic
+ %40 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %41 = atomicrmw or i32* %40, i32 1 monotonic
+ %42 = atomicrmw xor i8* @sc, i8 1 monotonic
+ %43 = atomicrmw xor i8* @uc, i8 1 monotonic
+ %44 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %45 = atomicrmw xor i16* %44, i16 1 monotonic
+ %46 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %47 = atomicrmw xor i16* %46, i16 1 monotonic
+ %48 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %49 = atomicrmw xor i32* %48, i32 1 monotonic
+ %50 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %51 = atomicrmw xor i32* %50, i32 1 monotonic
+ %52 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %53 = atomicrmw xor i32* %52, i32 1 monotonic
+ %54 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %55 = atomicrmw xor i32* %54, i32 1 monotonic
+ %56 = atomicrmw and i8* @sc, i8 1 monotonic
+ %57 = atomicrmw and i8* @uc, i8 1 monotonic
+ %58 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %59 = atomicrmw and i16* %58, i16 1 monotonic
+ %60 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %61 = atomicrmw and i16* %60, i16 1 monotonic
+ %62 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %63 = atomicrmw and i32* %62, i32 1 monotonic
+ %64 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %65 = atomicrmw and i32* %64, i32 1 monotonic
+ %66 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %67 = atomicrmw and i32* %66, i32 1 monotonic
+ %68 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %69 = atomicrmw and i32* %68, i32 1 monotonic
+ %70 = atomicrmw nand i8* @sc, i8 1 monotonic
+ %71 = atomicrmw nand i8* @uc, i8 1 monotonic
+ %72 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %73 = atomicrmw nand i16* %72, i16 1 monotonic
+ %74 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %75 = atomicrmw nand i16* %74, i16 1 monotonic
+ %76 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %77 = atomicrmw nand i32* %76, i32 1 monotonic
+ %78 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %79 = atomicrmw nand i32* %78, i32 1 monotonic
+ %80 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %81 = atomicrmw nand i32* %80, i32 1 monotonic
+ %82 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %83 = atomicrmw nand i32* %82, i32 1 monotonic
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
-declare i8 @llvm.atomic.load.add.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.add.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.add.i32.p0i32(i32*, i32) nounwind
-
-declare i8 @llvm.atomic.load.sub.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.sub.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.sub.i32.p0i32(i32*, i32) nounwind
-
-declare i8 @llvm.atomic.load.or.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.or.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.or.i32.p0i32(i32*, i32) nounwind
-
-declare i8 @llvm.atomic.load.xor.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.xor.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.xor.i32.p0i32(i32*, i32) nounwind
-
-declare i8 @llvm.atomic.load.and.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.and.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.and.i32.p0i32(i32*, i32) nounwind
-
-declare i8 @llvm.atomic.load.nand.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.nand.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.nand.i32.p0i32(i32*, i32) nounwind
-
define void @test_fetch_and_op() nounwind {
entry:
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:0 [#uses=1]
- store i8 %0, i8* @sc, align 1
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:1 [#uses=1]
- store i8 %1, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %2, i16 11 ) ; <i16>:3 [#uses=1]
- store i16 %3, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %4, i16 11 ) ; <i16>:5 [#uses=1]
- store i16 %5, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %6, i32 11 ) ; <i32>:7 [#uses=1]
- store i32 %7, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %8, i32 11 ) ; <i32>:9 [#uses=1]
- store i32 %9, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:10 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %10, i32 11 ) ; <i32>:11 [#uses=1]
- store i32 %11, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:12 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %12, i32 11 ) ; <i32>:13 [#uses=1]
- store i32 %13, i32* @ul, align 4
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:14 [#uses=1]
- store i8 %14, i8* @sc, align 1
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:15 [#uses=1]
- store i8 %15, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:16 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %16, i16 11 ) ; <i16>:17 [#uses=1]
- store i16 %17, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:18 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %18, i16 11 ) ; <i16>:19 [#uses=1]
- store i16 %19, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:20 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %20, i32 11 ) ; <i32>:21 [#uses=1]
- store i32 %21, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:22 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %22, i32 11 ) ; <i32>:23 [#uses=1]
- store i32 %23, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:24 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %24, i32 11 ) ; <i32>:25 [#uses=1]
- store i32 %25, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:26 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %26, i32 11 ) ; <i32>:27 [#uses=1]
- store i32 %27, i32* @ul, align 4
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:28 [#uses=1]
- store i8 %28, i8* @sc, align 1
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:29 [#uses=1]
- store i8 %29, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:30 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %30, i16 11 ) ; <i16>:31 [#uses=1]
- store i16 %31, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:32 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %32, i16 11 ) ; <i16>:33 [#uses=1]
- store i16 %33, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:34 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %34, i32 11 ) ; <i32>:35 [#uses=1]
- store i32 %35, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:36 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %36, i32 11 ) ; <i32>:37 [#uses=1]
- store i32 %37, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:38 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %38, i32 11 ) ; <i32>:39 [#uses=1]
- store i32 %39, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:40 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %40, i32 11 ) ; <i32>:41 [#uses=1]
- store i32 %41, i32* @ul, align 4
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:42 [#uses=1]
- store i8 %42, i8* @sc, align 1
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:43 [#uses=1]
- store i8 %43, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:44 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %44, i16 11 ) ; <i16>:45 [#uses=1]
- store i16 %45, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:46 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %46, i16 11 ) ; <i16>:47 [#uses=1]
- store i16 %47, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:48 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %48, i32 11 ) ; <i32>:49 [#uses=1]
- store i32 %49, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:50 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %50, i32 11 ) ; <i32>:51 [#uses=1]
- store i32 %51, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:52 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %52, i32 11 ) ; <i32>:53 [#uses=1]
- store i32 %53, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:54 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %54, i32 11 ) ; <i32>:55 [#uses=1]
- store i32 %55, i32* @ul, align 4
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:56 [#uses=1]
- store i8 %56, i8* @sc, align 1
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:57 [#uses=1]
- store i8 %57, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:58 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %58, i16 11 ) ; <i16>:59 [#uses=1]
- store i16 %59, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:60 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %60, i16 11 ) ; <i16>:61 [#uses=1]
- store i16 %61, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:62 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %62, i32 11 ) ; <i32>:63 [#uses=1]
- store i32 %63, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:64 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %64, i32 11 ) ; <i32>:65 [#uses=1]
- store i32 %65, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:66 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %66, i32 11 ) ; <i32>:67 [#uses=1]
- store i32 %67, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:68 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %68, i32 11 ) ; <i32>:69 [#uses=1]
- store i32 %69, i32* @ul, align 4
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:70 [#uses=1]
- store i8 %70, i8* @sc, align 1
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:71 [#uses=1]
- store i8 %71, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:72 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %72, i16 11 ) ; <i16>:73 [#uses=1]
- store i16 %73, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:74 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %74, i16 11 ) ; <i16>:75 [#uses=1]
- store i16 %75, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:76 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %76, i32 11 ) ; <i32>:77 [#uses=1]
- store i32 %77, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:78 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %78, i32 11 ) ; <i32>:79 [#uses=1]
- store i32 %79, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:80 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %80, i32 11 ) ; <i32>:81 [#uses=1]
- store i32 %81, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:82 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %82, i32 11 ) ; <i32>:83 [#uses=1]
- store i32 %83, i32* @ul, align 4
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = atomicrmw add i8* @sc, i8 11 monotonic
+ store i8 %0, i8* @sc, align 1
+ %1 = atomicrmw add i8* @uc, i8 11 monotonic
+ store i8 %1, i8* @uc, align 1
+ %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %3 = atomicrmw add i16* %2, i16 11 monotonic
+ store i16 %3, i16* @ss, align 2
+ %4 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %5 = atomicrmw add i16* %4, i16 11 monotonic
+ store i16 %5, i16* @us, align 2
+ %6 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %7 = atomicrmw add i32* %6, i32 11 monotonic
+ store i32 %7, i32* @si, align 4
+ %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %9 = atomicrmw add i32* %8, i32 11 monotonic
+ store i32 %9, i32* @ui, align 4
+ %10 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %11 = atomicrmw add i32* %10, i32 11 monotonic
+ store i32 %11, i32* @sl, align 4
+ %12 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %13 = atomicrmw add i32* %12, i32 11 monotonic
+ store i32 %13, i32* @ul, align 4
+ %14 = atomicrmw sub i8* @sc, i8 11 monotonic
+ store i8 %14, i8* @sc, align 1
+ %15 = atomicrmw sub i8* @uc, i8 11 monotonic
+ store i8 %15, i8* @uc, align 1
+ %16 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %17 = atomicrmw sub i16* %16, i16 11 monotonic
+ store i16 %17, i16* @ss, align 2
+ %18 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %19 = atomicrmw sub i16* %18, i16 11 monotonic
+ store i16 %19, i16* @us, align 2
+ %20 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %21 = atomicrmw sub i32* %20, i32 11 monotonic
+ store i32 %21, i32* @si, align 4
+ %22 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %23 = atomicrmw sub i32* %22, i32 11 monotonic
+ store i32 %23, i32* @ui, align 4
+ %24 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %25 = atomicrmw sub i32* %24, i32 11 monotonic
+ store i32 %25, i32* @sl, align 4
+ %26 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %27 = atomicrmw sub i32* %26, i32 11 monotonic
+ store i32 %27, i32* @ul, align 4
+ %28 = atomicrmw or i8* @sc, i8 11 monotonic
+ store i8 %28, i8* @sc, align 1
+ %29 = atomicrmw or i8* @uc, i8 11 monotonic
+ store i8 %29, i8* @uc, align 1
+ %30 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %31 = atomicrmw or i16* %30, i16 11 monotonic
+ store i16 %31, i16* @ss, align 2
+ %32 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %33 = atomicrmw or i16* %32, i16 11 monotonic
+ store i16 %33, i16* @us, align 2
+ %34 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %35 = atomicrmw or i32* %34, i32 11 monotonic
+ store i32 %35, i32* @si, align 4
+ %36 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %37 = atomicrmw or i32* %36, i32 11 monotonic
+ store i32 %37, i32* @ui, align 4
+ %38 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %39 = atomicrmw or i32* %38, i32 11 monotonic
+ store i32 %39, i32* @sl, align 4
+ %40 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %41 = atomicrmw or i32* %40, i32 11 monotonic
+ store i32 %41, i32* @ul, align 4
+ %42 = atomicrmw xor i8* @sc, i8 11 monotonic
+ store i8 %42, i8* @sc, align 1
+ %43 = atomicrmw xor i8* @uc, i8 11 monotonic
+ store i8 %43, i8* @uc, align 1
+ %44 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %45 = atomicrmw xor i16* %44, i16 11 monotonic
+ store i16 %45, i16* @ss, align 2
+ %46 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %47 = atomicrmw xor i16* %46, i16 11 monotonic
+ store i16 %47, i16* @us, align 2
+ %48 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %49 = atomicrmw xor i32* %48, i32 11 monotonic
+ store i32 %49, i32* @si, align 4
+ %50 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %51 = atomicrmw xor i32* %50, i32 11 monotonic
+ store i32 %51, i32* @ui, align 4
+ %52 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %53 = atomicrmw xor i32* %52, i32 11 monotonic
+ store i32 %53, i32* @sl, align 4
+ %54 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %55 = atomicrmw xor i32* %54, i32 11 monotonic
+ store i32 %55, i32* @ul, align 4
+ %56 = atomicrmw and i8* @sc, i8 11 monotonic
+ store i8 %56, i8* @sc, align 1
+ %57 = atomicrmw and i8* @uc, i8 11 monotonic
+ store i8 %57, i8* @uc, align 1
+ %58 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %59 = atomicrmw and i16* %58, i16 11 monotonic
+ store i16 %59, i16* @ss, align 2
+ %60 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %61 = atomicrmw and i16* %60, i16 11 monotonic
+ store i16 %61, i16* @us, align 2
+ %62 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %63 = atomicrmw and i32* %62, i32 11 monotonic
+ store i32 %63, i32* @si, align 4
+ %64 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %65 = atomicrmw and i32* %64, i32 11 monotonic
+ store i32 %65, i32* @ui, align 4
+ %66 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %67 = atomicrmw and i32* %66, i32 11 monotonic
+ store i32 %67, i32* @sl, align 4
+ %68 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %69 = atomicrmw and i32* %68, i32 11 monotonic
+ store i32 %69, i32* @ul, align 4
+ %70 = atomicrmw nand i8* @sc, i8 11 monotonic
+ store i8 %70, i8* @sc, align 1
+ %71 = atomicrmw nand i8* @uc, i8 11 monotonic
+ store i8 %71, i8* @uc, align 1
+ %72 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %73 = atomicrmw nand i16* %72, i16 11 monotonic
+ store i16 %73, i16* @ss, align 2
+ %74 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %75 = atomicrmw nand i16* %74, i16 11 monotonic
+ store i16 %75, i16* @us, align 2
+ %76 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %77 = atomicrmw nand i32* %76, i32 11 monotonic
+ store i32 %77, i32* @si, align 4
+ %78 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %79 = atomicrmw nand i32* %78, i32 11 monotonic
+ store i32 %79, i32* @ui, align 4
+ %80 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %81 = atomicrmw nand i32* %80, i32 11 monotonic
+ store i32 %81, i32* @sl, align 4
+ %82 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %83 = atomicrmw nand i32* %82, i32 11 monotonic
+ store i32 %83, i32* @ul, align 4
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
define void @test_op_and_fetch() nounwind {
entry:
- load i8* @uc, align 1 ; <i8>:0 [#uses=2]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 %0 ) ; <i8>:1 [#uses=1]
- add i8 %1, %0 ; <i8>:2 [#uses=1]
- store i8 %2, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:3 [#uses=2]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 %3 ) ; <i8>:4 [#uses=1]
- add i8 %4, %3 ; <i8>:5 [#uses=1]
- store i8 %5, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:6 [#uses=1]
- zext i8 %6 to i16 ; <i16>:7 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:8 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %8, i16 %7 ) ; <i16>:9 [#uses=1]
- add i16 %9, %7 ; <i16>:10 [#uses=1]
- store i16 %10, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:11 [#uses=1]
- zext i8 %11 to i16 ; <i16>:12 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:13 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %13, i16 %12 ) ; <i16>:14 [#uses=1]
- add i16 %14, %12 ; <i16>:15 [#uses=1]
- store i16 %15, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:16 [#uses=1]
- zext i8 %16 to i32 ; <i32>:17 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:18 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %18, i32 %17 ) ; <i32>:19 [#uses=1]
- add i32 %19, %17 ; <i32>:20 [#uses=1]
- store i32 %20, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:21 [#uses=1]
- zext i8 %21 to i32 ; <i32>:22 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:23 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %23, i32 %22 ) ; <i32>:24 [#uses=1]
- add i32 %24, %22 ; <i32>:25 [#uses=1]
- store i32 %25, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:26 [#uses=1]
- zext i8 %26 to i32 ; <i32>:27 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:28 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %28, i32 %27 ) ; <i32>:29 [#uses=1]
- add i32 %29, %27 ; <i32>:30 [#uses=1]
- store i32 %30, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:31 [#uses=1]
- zext i8 %31 to i32 ; <i32>:32 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:33 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %33, i32 %32 ) ; <i32>:34 [#uses=1]
- add i32 %34, %32 ; <i32>:35 [#uses=1]
- store i32 %35, i32* @ul, align 4
- load i8* @uc, align 1 ; <i8>:36 [#uses=2]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 %36 ) ; <i8>:37 [#uses=1]
- sub i8 %37, %36 ; <i8>:38 [#uses=1]
- store i8 %38, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:39 [#uses=2]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 %39 ) ; <i8>:40 [#uses=1]
- sub i8 %40, %39 ; <i8>:41 [#uses=1]
- store i8 %41, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:42 [#uses=1]
- zext i8 %42 to i16 ; <i16>:43 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:44 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %44, i16 %43 ) ; <i16>:45 [#uses=1]
- sub i16 %45, %43 ; <i16>:46 [#uses=1]
- store i16 %46, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:47 [#uses=1]
- zext i8 %47 to i16 ; <i16>:48 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:49 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %49, i16 %48 ) ; <i16>:50 [#uses=1]
- sub i16 %50, %48 ; <i16>:51 [#uses=1]
- store i16 %51, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:52 [#uses=1]
- zext i8 %52 to i32 ; <i32>:53 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:54 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %54, i32 %53 ) ; <i32>:55 [#uses=1]
- sub i32 %55, %53 ; <i32>:56 [#uses=1]
- store i32 %56, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:57 [#uses=1]
- zext i8 %57 to i32 ; <i32>:58 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:59 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %59, i32 %58 ) ; <i32>:60 [#uses=1]
- sub i32 %60, %58 ; <i32>:61 [#uses=1]
- store i32 %61, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:62 [#uses=1]
- zext i8 %62 to i32 ; <i32>:63 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:64 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %64, i32 %63 ) ; <i32>:65 [#uses=1]
- sub i32 %65, %63 ; <i32>:66 [#uses=1]
- store i32 %66, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:67 [#uses=1]
- zext i8 %67 to i32 ; <i32>:68 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:69 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %69, i32 %68 ) ; <i32>:70 [#uses=1]
- sub i32 %70, %68 ; <i32>:71 [#uses=1]
- store i32 %71, i32* @ul, align 4
- load i8* @uc, align 1 ; <i8>:72 [#uses=2]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 %72 ) ; <i8>:73 [#uses=1]
- or i8 %73, %72 ; <i8>:74 [#uses=1]
- store i8 %74, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:75 [#uses=2]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 %75 ) ; <i8>:76 [#uses=1]
- or i8 %76, %75 ; <i8>:77 [#uses=1]
- store i8 %77, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:78 [#uses=1]
- zext i8 %78 to i16 ; <i16>:79 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:80 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %80, i16 %79 ) ; <i16>:81 [#uses=1]
- or i16 %81, %79 ; <i16>:82 [#uses=1]
- store i16 %82, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:83 [#uses=1]
- zext i8 %83 to i16 ; <i16>:84 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:85 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %85, i16 %84 ) ; <i16>:86 [#uses=1]
- or i16 %86, %84 ; <i16>:87 [#uses=1]
- store i16 %87, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:88 [#uses=1]
- zext i8 %88 to i32 ; <i32>:89 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:90 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %90, i32 %89 ) ; <i32>:91 [#uses=1]
- or i32 %91, %89 ; <i32>:92 [#uses=1]
- store i32 %92, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:93 [#uses=1]
- zext i8 %93 to i32 ; <i32>:94 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:95 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %95, i32 %94 ) ; <i32>:96 [#uses=1]
- or i32 %96, %94 ; <i32>:97 [#uses=1]
- store i32 %97, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:98 [#uses=1]
- zext i8 %98 to i32 ; <i32>:99 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:100 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %100, i32 %99 ) ; <i32>:101 [#uses=1]
- or i32 %101, %99 ; <i32>:102 [#uses=1]
- store i32 %102, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:103 [#uses=1]
- zext i8 %103 to i32 ; <i32>:104 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:105 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %105, i32 %104 ) ; <i32>:106 [#uses=1]
- or i32 %106, %104 ; <i32>:107 [#uses=1]
- store i32 %107, i32* @ul, align 4
- load i8* @uc, align 1 ; <i8>:108 [#uses=2]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 %108 ) ; <i8>:109 [#uses=1]
- xor i8 %109, %108 ; <i8>:110 [#uses=1]
- store i8 %110, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:111 [#uses=2]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 %111 ) ; <i8>:112 [#uses=1]
- xor i8 %112, %111 ; <i8>:113 [#uses=1]
- store i8 %113, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:114 [#uses=1]
- zext i8 %114 to i16 ; <i16>:115 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:116 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %116, i16 %115 ) ; <i16>:117 [#uses=1]
- xor i16 %117, %115 ; <i16>:118 [#uses=1]
- store i16 %118, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:119 [#uses=1]
- zext i8 %119 to i16 ; <i16>:120 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:121 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %121, i16 %120 ) ; <i16>:122 [#uses=1]
- xor i16 %122, %120 ; <i16>:123 [#uses=1]
- store i16 %123, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:124 [#uses=1]
- zext i8 %124 to i32 ; <i32>:125 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:126 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %126, i32 %125 ) ; <i32>:127 [#uses=1]
- xor i32 %127, %125 ; <i32>:128 [#uses=1]
- store i32 %128, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:129 [#uses=1]
- zext i8 %129 to i32 ; <i32>:130 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:131 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %131, i32 %130 ) ; <i32>:132 [#uses=1]
- xor i32 %132, %130 ; <i32>:133 [#uses=1]
- store i32 %133, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:134 [#uses=1]
- zext i8 %134 to i32 ; <i32>:135 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:136 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %136, i32 %135 ) ; <i32>:137 [#uses=1]
- xor i32 %137, %135 ; <i32>:138 [#uses=1]
- store i32 %138, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:139 [#uses=1]
- zext i8 %139 to i32 ; <i32>:140 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:141 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %141, i32 %140 ) ; <i32>:142 [#uses=1]
- xor i32 %142, %140 ; <i32>:143 [#uses=1]
- store i32 %143, i32* @ul, align 4
- load i8* @uc, align 1 ; <i8>:144 [#uses=2]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 %144 ) ; <i8>:145 [#uses=1]
- and i8 %145, %144 ; <i8>:146 [#uses=1]
- store i8 %146, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:147 [#uses=2]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 %147 ) ; <i8>:148 [#uses=1]
- and i8 %148, %147 ; <i8>:149 [#uses=1]
- store i8 %149, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:150 [#uses=1]
- zext i8 %150 to i16 ; <i16>:151 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:152 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %152, i16 %151 ) ; <i16>:153 [#uses=1]
- and i16 %153, %151 ; <i16>:154 [#uses=1]
- store i16 %154, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:155 [#uses=1]
- zext i8 %155 to i16 ; <i16>:156 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:157 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %157, i16 %156 ) ; <i16>:158 [#uses=1]
- and i16 %158, %156 ; <i16>:159 [#uses=1]
- store i16 %159, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:160 [#uses=1]
- zext i8 %160 to i32 ; <i32>:161 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:162 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %162, i32 %161 ) ; <i32>:163 [#uses=1]
- and i32 %163, %161 ; <i32>:164 [#uses=1]
- store i32 %164, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:165 [#uses=1]
- zext i8 %165 to i32 ; <i32>:166 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:167 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %167, i32 %166 ) ; <i32>:168 [#uses=1]
- and i32 %168, %166 ; <i32>:169 [#uses=1]
- store i32 %169, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:170 [#uses=1]
- zext i8 %170 to i32 ; <i32>:171 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:172 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %172, i32 %171 ) ; <i32>:173 [#uses=1]
- and i32 %173, %171 ; <i32>:174 [#uses=1]
- store i32 %174, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:175 [#uses=1]
- zext i8 %175 to i32 ; <i32>:176 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:177 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %177, i32 %176 ) ; <i32>:178 [#uses=1]
- and i32 %178, %176 ; <i32>:179 [#uses=1]
- store i32 %179, i32* @ul, align 4
- load i8* @uc, align 1 ; <i8>:180 [#uses=2]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 %180 ) ; <i8>:181 [#uses=1]
- xor i8 %181, -1 ; <i8>:182 [#uses=1]
- and i8 %182, %180 ; <i8>:183 [#uses=1]
- store i8 %183, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:184 [#uses=2]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 %184 ) ; <i8>:185 [#uses=1]
- xor i8 %185, -1 ; <i8>:186 [#uses=1]
- and i8 %186, %184 ; <i8>:187 [#uses=1]
- store i8 %187, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:188 [#uses=1]
- zext i8 %188 to i16 ; <i16>:189 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:190 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %190, i16 %189 ) ; <i16>:191 [#uses=1]
- xor i16 %191, -1 ; <i16>:192 [#uses=1]
- and i16 %192, %189 ; <i16>:193 [#uses=1]
- store i16 %193, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:194 [#uses=1]
- zext i8 %194 to i16 ; <i16>:195 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:196 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %196, i16 %195 ) ; <i16>:197 [#uses=1]
- xor i16 %197, -1 ; <i16>:198 [#uses=1]
- and i16 %198, %195 ; <i16>:199 [#uses=1]
- store i16 %199, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:200 [#uses=1]
- zext i8 %200 to i32 ; <i32>:201 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:202 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %202, i32 %201 ) ; <i32>:203 [#uses=1]
- xor i32 %203, -1 ; <i32>:204 [#uses=1]
- and i32 %204, %201 ; <i32>:205 [#uses=1]
- store i32 %205, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:206 [#uses=1]
- zext i8 %206 to i32 ; <i32>:207 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:208 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %208, i32 %207 ) ; <i32>:209 [#uses=1]
- xor i32 %209, -1 ; <i32>:210 [#uses=1]
- and i32 %210, %207 ; <i32>:211 [#uses=1]
- store i32 %211, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:212 [#uses=1]
- zext i8 %212 to i32 ; <i32>:213 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:214 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %214, i32 %213 ) ; <i32>:215 [#uses=1]
- xor i32 %215, -1 ; <i32>:216 [#uses=1]
- and i32 %216, %213 ; <i32>:217 [#uses=1]
- store i32 %217, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:218 [#uses=1]
- zext i8 %218 to i32 ; <i32>:219 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:220 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %220, i32 %219 ) ; <i32>:221 [#uses=1]
- xor i32 %221, -1 ; <i32>:222 [#uses=1]
- and i32 %222, %219 ; <i32>:223 [#uses=1]
- store i32 %223, i32* @ul, align 4
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = load i8* @uc, align 1
+ %1 = atomicrmw add i8* @sc, i8 %0 monotonic
+ %2 = add i8 %1, %0
+ store i8 %2, i8* @sc, align 1
+ %3 = load i8* @uc, align 1
+ %4 = atomicrmw add i8* @uc, i8 %3 monotonic
+ %5 = add i8 %4, %3
+ store i8 %5, i8* @uc, align 1
+ %6 = load i8* @uc, align 1
+ %7 = zext i8 %6 to i16
+ %8 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %9 = atomicrmw add i16* %8, i16 %7 monotonic
+ %10 = add i16 %9, %7
+ store i16 %10, i16* @ss, align 2
+ %11 = load i8* @uc, align 1
+ %12 = zext i8 %11 to i16
+ %13 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %14 = atomicrmw add i16* %13, i16 %12 monotonic
+ %15 = add i16 %14, %12
+ store i16 %15, i16* @us, align 2
+ %16 = load i8* @uc, align 1
+ %17 = zext i8 %16 to i32
+ %18 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %19 = atomicrmw add i32* %18, i32 %17 monotonic
+ %20 = add i32 %19, %17
+ store i32 %20, i32* @si, align 4
+ %21 = load i8* @uc, align 1
+ %22 = zext i8 %21 to i32
+ %23 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %24 = atomicrmw add i32* %23, i32 %22 monotonic
+ %25 = add i32 %24, %22
+ store i32 %25, i32* @ui, align 4
+ %26 = load i8* @uc, align 1
+ %27 = zext i8 %26 to i32
+ %28 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %29 = atomicrmw add i32* %28, i32 %27 monotonic
+ %30 = add i32 %29, %27
+ store i32 %30, i32* @sl, align 4
+ %31 = load i8* @uc, align 1
+ %32 = zext i8 %31 to i32
+ %33 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %34 = atomicrmw add i32* %33, i32 %32 monotonic
+ %35 = add i32 %34, %32
+ store i32 %35, i32* @ul, align 4
+ %36 = load i8* @uc, align 1
+ %37 = atomicrmw sub i8* @sc, i8 %36 monotonic
+ %38 = sub i8 %37, %36
+ store i8 %38, i8* @sc, align 1
+ %39 = load i8* @uc, align 1
+ %40 = atomicrmw sub i8* @uc, i8 %39 monotonic
+ %41 = sub i8 %40, %39
+ store i8 %41, i8* @uc, align 1
+ %42 = load i8* @uc, align 1
+ %43 = zext i8 %42 to i16
+ %44 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %45 = atomicrmw sub i16* %44, i16 %43 monotonic
+ %46 = sub i16 %45, %43
+ store i16 %46, i16* @ss, align 2
+ %47 = load i8* @uc, align 1
+ %48 = zext i8 %47 to i16
+ %49 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %50 = atomicrmw sub i16* %49, i16 %48 monotonic
+ %51 = sub i16 %50, %48
+ store i16 %51, i16* @us, align 2
+ %52 = load i8* @uc, align 1
+ %53 = zext i8 %52 to i32
+ %54 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %55 = atomicrmw sub i32* %54, i32 %53 monotonic
+ %56 = sub i32 %55, %53
+ store i32 %56, i32* @si, align 4
+ %57 = load i8* @uc, align 1
+ %58 = zext i8 %57 to i32
+ %59 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %60 = atomicrmw sub i32* %59, i32 %58 monotonic
+ %61 = sub i32 %60, %58
+ store i32 %61, i32* @ui, align 4
+ %62 = load i8* @uc, align 1
+ %63 = zext i8 %62 to i32
+ %64 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %65 = atomicrmw sub i32* %64, i32 %63 monotonic
+ %66 = sub i32 %65, %63
+ store i32 %66, i32* @sl, align 4
+ %67 = load i8* @uc, align 1
+ %68 = zext i8 %67 to i32
+ %69 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %70 = atomicrmw sub i32* %69, i32 %68 monotonic
+ %71 = sub i32 %70, %68
+ store i32 %71, i32* @ul, align 4
+ %72 = load i8* @uc, align 1
+ %73 = atomicrmw or i8* @sc, i8 %72 monotonic
+ %74 = or i8 %73, %72
+ store i8 %74, i8* @sc, align 1
+ %75 = load i8* @uc, align 1
+ %76 = atomicrmw or i8* @uc, i8 %75 monotonic
+ %77 = or i8 %76, %75
+ store i8 %77, i8* @uc, align 1
+ %78 = load i8* @uc, align 1
+ %79 = zext i8 %78 to i16
+ %80 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %81 = atomicrmw or i16* %80, i16 %79 monotonic
+ %82 = or i16 %81, %79
+ store i16 %82, i16* @ss, align 2
+ %83 = load i8* @uc, align 1
+ %84 = zext i8 %83 to i16
+ %85 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %86 = atomicrmw or i16* %85, i16 %84 monotonic
+ %87 = or i16 %86, %84
+ store i16 %87, i16* @us, align 2
+ %88 = load i8* @uc, align 1
+ %89 = zext i8 %88 to i32
+ %90 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %91 = atomicrmw or i32* %90, i32 %89 monotonic
+ %92 = or i32 %91, %89
+ store i32 %92, i32* @si, align 4
+ %93 = load i8* @uc, align 1
+ %94 = zext i8 %93 to i32
+ %95 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %96 = atomicrmw or i32* %95, i32 %94 monotonic
+ %97 = or i32 %96, %94
+ store i32 %97, i32* @ui, align 4
+ %98 = load i8* @uc, align 1
+ %99 = zext i8 %98 to i32
+ %100 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %101 = atomicrmw or i32* %100, i32 %99 monotonic
+ %102 = or i32 %101, %99
+ store i32 %102, i32* @sl, align 4
+ %103 = load i8* @uc, align 1
+ %104 = zext i8 %103 to i32
+ %105 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %106 = atomicrmw or i32* %105, i32 %104 monotonic
+ %107 = or i32 %106, %104
+ store i32 %107, i32* @ul, align 4
+ %108 = load i8* @uc, align 1
+ %109 = atomicrmw xor i8* @sc, i8 %108 monotonic
+ %110 = xor i8 %109, %108
+ store i8 %110, i8* @sc, align 1
+ %111 = load i8* @uc, align 1
+ %112 = atomicrmw xor i8* @uc, i8 %111 monotonic
+ %113 = xor i8 %112, %111
+ store i8 %113, i8* @uc, align 1
+ %114 = load i8* @uc, align 1
+ %115 = zext i8 %114 to i16
+ %116 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %117 = atomicrmw xor i16* %116, i16 %115 monotonic
+ %118 = xor i16 %117, %115
+ store i16 %118, i16* @ss, align 2
+ %119 = load i8* @uc, align 1
+ %120 = zext i8 %119 to i16
+ %121 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %122 = atomicrmw xor i16* %121, i16 %120 monotonic
+ %123 = xor i16 %122, %120
+ store i16 %123, i16* @us, align 2
+ %124 = load i8* @uc, align 1
+ %125 = zext i8 %124 to i32
+ %126 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %127 = atomicrmw xor i32* %126, i32 %125 monotonic
+ %128 = xor i32 %127, %125
+ store i32 %128, i32* @si, align 4
+ %129 = load i8* @uc, align 1
+ %130 = zext i8 %129 to i32
+ %131 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %132 = atomicrmw xor i32* %131, i32 %130 monotonic
+ %133 = xor i32 %132, %130
+ store i32 %133, i32* @ui, align 4
+ %134 = load i8* @uc, align 1
+ %135 = zext i8 %134 to i32
+ %136 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %137 = atomicrmw xor i32* %136, i32 %135 monotonic
+ %138 = xor i32 %137, %135
+ store i32 %138, i32* @sl, align 4
+ %139 = load i8* @uc, align 1
+ %140 = zext i8 %139 to i32
+ %141 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %142 = atomicrmw xor i32* %141, i32 %140 monotonic
+ %143 = xor i32 %142, %140
+ store i32 %143, i32* @ul, align 4
+ %144 = load i8* @uc, align 1
+ %145 = atomicrmw and i8* @sc, i8 %144 monotonic
+ %146 = and i8 %145, %144
+ store i8 %146, i8* @sc, align 1
+ %147 = load i8* @uc, align 1
+ %148 = atomicrmw and i8* @uc, i8 %147 monotonic
+ %149 = and i8 %148, %147
+ store i8 %149, i8* @uc, align 1
+ %150 = load i8* @uc, align 1
+ %151 = zext i8 %150 to i16
+ %152 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %153 = atomicrmw and i16* %152, i16 %151 monotonic
+ %154 = and i16 %153, %151
+ store i16 %154, i16* @ss, align 2
+ %155 = load i8* @uc, align 1
+ %156 = zext i8 %155 to i16
+ %157 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %158 = atomicrmw and i16* %157, i16 %156 monotonic
+ %159 = and i16 %158, %156
+ store i16 %159, i16* @us, align 2
+ %160 = load i8* @uc, align 1
+ %161 = zext i8 %160 to i32
+ %162 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %163 = atomicrmw and i32* %162, i32 %161 monotonic
+ %164 = and i32 %163, %161
+ store i32 %164, i32* @si, align 4
+ %165 = load i8* @uc, align 1
+ %166 = zext i8 %165 to i32
+ %167 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %168 = atomicrmw and i32* %167, i32 %166 monotonic
+ %169 = and i32 %168, %166
+ store i32 %169, i32* @ui, align 4
+ %170 = load i8* @uc, align 1
+ %171 = zext i8 %170 to i32
+ %172 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %173 = atomicrmw and i32* %172, i32 %171 monotonic
+ %174 = and i32 %173, %171
+ store i32 %174, i32* @sl, align 4
+ %175 = load i8* @uc, align 1
+ %176 = zext i8 %175 to i32
+ %177 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %178 = atomicrmw and i32* %177, i32 %176 monotonic
+ %179 = and i32 %178, %176
+ store i32 %179, i32* @ul, align 4
+ %180 = load i8* @uc, align 1
+ %181 = atomicrmw nand i8* @sc, i8 %180 monotonic
+ %182 = xor i8 %181, -1
+ %183 = and i8 %182, %180
+ store i8 %183, i8* @sc, align 1
+ %184 = load i8* @uc, align 1
+ %185 = atomicrmw nand i8* @uc, i8 %184 monotonic
+ %186 = xor i8 %185, -1
+ %187 = and i8 %186, %184
+ store i8 %187, i8* @uc, align 1
+ %188 = load i8* @uc, align 1
+ %189 = zext i8 %188 to i16
+ %190 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %191 = atomicrmw nand i16* %190, i16 %189 monotonic
+ %192 = xor i16 %191, -1
+ %193 = and i16 %192, %189
+ store i16 %193, i16* @ss, align 2
+ %194 = load i8* @uc, align 1
+ %195 = zext i8 %194 to i16
+ %196 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %197 = atomicrmw nand i16* %196, i16 %195 monotonic
+ %198 = xor i16 %197, -1
+ %199 = and i16 %198, %195
+ store i16 %199, i16* @us, align 2
+ %200 = load i8* @uc, align 1
+ %201 = zext i8 %200 to i32
+ %202 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %203 = atomicrmw nand i32* %202, i32 %201 monotonic
+ %204 = xor i32 %203, -1
+ %205 = and i32 %204, %201
+ store i32 %205, i32* @si, align 4
+ %206 = load i8* @uc, align 1
+ %207 = zext i8 %206 to i32
+ %208 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %209 = atomicrmw nand i32* %208, i32 %207 monotonic
+ %210 = xor i32 %209, -1
+ %211 = and i32 %210, %207
+ store i32 %211, i32* @ui, align 4
+ %212 = load i8* @uc, align 1
+ %213 = zext i8 %212 to i32
+ %214 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %215 = atomicrmw nand i32* %214, i32 %213 monotonic
+ %216 = xor i32 %215, -1
+ %217 = and i32 %216, %213
+ store i32 %217, i32* @sl, align 4
+ %218 = load i8* @uc, align 1
+ %219 = zext i8 %218 to i32
+ %220 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %221 = atomicrmw nand i32* %220, i32 %219 monotonic
+ %222 = xor i32 %221, -1
+ %223 = and i32 %222, %219
+ store i32 %223, i32* @ul, align 4
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
define void @test_compare_and_swap() nounwind {
entry:
- load i8* @uc, align 1 ; <i8>:0 [#uses=1]
- load i8* @sc, align 1 ; <i8>:1 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @sc, i8 %0, i8 %1 ) ; <i8>:2 [#uses=1]
- store i8 %2, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:3 [#uses=1]
- load i8* @sc, align 1 ; <i8>:4 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @uc, i8 %3, i8 %4 ) ; <i8>:5 [#uses=1]
- store i8 %5, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:6 [#uses=1]
- zext i8 %6 to i16 ; <i16>:7 [#uses=1]
- load i8* @sc, align 1 ; <i8>:8 [#uses=1]
- sext i8 %8 to i16 ; <i16>:9 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:10 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %10, i16 %7, i16 %9 ) ; <i16>:11 [#uses=1]
- store i16 %11, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:12 [#uses=1]
- zext i8 %12 to i16 ; <i16>:13 [#uses=1]
- load i8* @sc, align 1 ; <i8>:14 [#uses=1]
- sext i8 %14 to i16 ; <i16>:15 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:16 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %16, i16 %13, i16 %15 ) ; <i16>:17 [#uses=1]
- store i16 %17, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:18 [#uses=1]
- zext i8 %18 to i32 ; <i32>:19 [#uses=1]
- load i8* @sc, align 1 ; <i8>:20 [#uses=1]
- sext i8 %20 to i32 ; <i32>:21 [#uses=1]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:22 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %22, i32 %19, i32 %21 ) ; <i32>:23 [#uses=1]
- store i32 %23, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:24 [#uses=1]
- zext i8 %24 to i32 ; <i32>:25 [#uses=1]
- load i8* @sc, align 1 ; <i8>:26 [#uses=1]
- sext i8 %26 to i32 ; <i32>:27 [#uses=1]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:28 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %28, i32 %25, i32 %27 ) ; <i32>:29 [#uses=1]
- store i32 %29, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:30 [#uses=1]
- zext i8 %30 to i32 ; <i32>:31 [#uses=1]
- load i8* @sc, align 1 ; <i8>:32 [#uses=1]
- sext i8 %32 to i32 ; <i32>:33 [#uses=1]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:34 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %34, i32 %31, i32 %33 ) ; <i32>:35 [#uses=1]
- store i32 %35, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:36 [#uses=1]
- zext i8 %36 to i32 ; <i32>:37 [#uses=1]
- load i8* @sc, align 1 ; <i8>:38 [#uses=1]
- sext i8 %38 to i32 ; <i32>:39 [#uses=1]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:40 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %40, i32 %37, i32 %39 ) ; <i32>:41 [#uses=1]
- store i32 %41, i32* @ul, align 4
- load i8* @uc, align 1 ; <i8>:42 [#uses=2]
- load i8* @sc, align 1 ; <i8>:43 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @sc, i8 %42, i8 %43 ) ; <i8>:44 [#uses=1]
- icmp eq i8 %44, %42 ; <i1>:45 [#uses=1]
- zext i1 %45 to i32 ; <i32>:46 [#uses=1]
- store i32 %46, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:47 [#uses=2]
- load i8* @sc, align 1 ; <i8>:48 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @uc, i8 %47, i8 %48 ) ; <i8>:49 [#uses=1]
- icmp eq i8 %49, %47 ; <i1>:50 [#uses=1]
- zext i1 %50 to i32 ; <i32>:51 [#uses=1]
- store i32 %51, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:52 [#uses=1]
- zext i8 %52 to i16 ; <i16>:53 [#uses=2]
- load i8* @sc, align 1 ; <i8>:54 [#uses=1]
- sext i8 %54 to i16 ; <i16>:55 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:56 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %56, i16 %53, i16 %55 ) ; <i16>:57 [#uses=1]
- icmp eq i16 %57, %53 ; <i1>:58 [#uses=1]
- zext i1 %58 to i32 ; <i32>:59 [#uses=1]
- store i32 %59, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:60 [#uses=1]
- zext i8 %60 to i16 ; <i16>:61 [#uses=2]
- load i8* @sc, align 1 ; <i8>:62 [#uses=1]
- sext i8 %62 to i16 ; <i16>:63 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:64 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %64, i16 %61, i16 %63 ) ; <i16>:65 [#uses=1]
- icmp eq i16 %65, %61 ; <i1>:66 [#uses=1]
- zext i1 %66 to i32 ; <i32>:67 [#uses=1]
- store i32 %67, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:68 [#uses=1]
- zext i8 %68 to i32 ; <i32>:69 [#uses=2]
- load i8* @sc, align 1 ; <i8>:70 [#uses=1]
- sext i8 %70 to i32 ; <i32>:71 [#uses=1]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:72 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %72, i32 %69, i32 %71 ) ; <i32>:73 [#uses=1]
- icmp eq i32 %73, %69 ; <i1>:74 [#uses=1]
- zext i1 %74 to i32 ; <i32>:75 [#uses=1]
- store i32 %75, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:76 [#uses=1]
- zext i8 %76 to i32 ; <i32>:77 [#uses=2]
- load i8* @sc, align 1 ; <i8>:78 [#uses=1]
- sext i8 %78 to i32 ; <i32>:79 [#uses=1]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:80 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %80, i32 %77, i32 %79 ) ; <i32>:81 [#uses=1]
- icmp eq i32 %81, %77 ; <i1>:82 [#uses=1]
- zext i1 %82 to i32 ; <i32>:83 [#uses=1]
- store i32 %83, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:84 [#uses=1]
- zext i8 %84 to i32 ; <i32>:85 [#uses=2]
- load i8* @sc, align 1 ; <i8>:86 [#uses=1]
- sext i8 %86 to i32 ; <i32>:87 [#uses=1]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:88 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %88, i32 %85, i32 %87 ) ; <i32>:89 [#uses=1]
- icmp eq i32 %89, %85 ; <i1>:90 [#uses=1]
- zext i1 %90 to i32 ; <i32>:91 [#uses=1]
- store i32 %91, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:92 [#uses=1]
- zext i8 %92 to i32 ; <i32>:93 [#uses=2]
- load i8* @sc, align 1 ; <i8>:94 [#uses=1]
- sext i8 %94 to i32 ; <i32>:95 [#uses=1]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:96 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %96, i32 %93, i32 %95 ) ; <i32>:97 [#uses=1]
- icmp eq i32 %97, %93 ; <i1>:98 [#uses=1]
- zext i1 %98 to i32 ; <i32>:99 [#uses=1]
- store i32 %99, i32* @ui, align 4
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = load i8* @uc, align 1
+ %1 = load i8* @sc, align 1
+ %2 = cmpxchg i8* @sc, i8 %0, i8 %1 monotonic
+ store i8 %2, i8* @sc, align 1
+ %3 = load i8* @uc, align 1
+ %4 = load i8* @sc, align 1
+ %5 = cmpxchg i8* @uc, i8 %3, i8 %4 monotonic
+ store i8 %5, i8* @uc, align 1
+ %6 = load i8* @uc, align 1
+ %7 = zext i8 %6 to i16
+ %8 = load i8* @sc, align 1
+ %9 = sext i8 %8 to i16
+ %10 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %11 = cmpxchg i16* %10, i16 %7, i16 %9 monotonic
+ store i16 %11, i16* @ss, align 2
+ %12 = load i8* @uc, align 1
+ %13 = zext i8 %12 to i16
+ %14 = load i8* @sc, align 1
+ %15 = sext i8 %14 to i16
+ %16 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %17 = cmpxchg i16* %16, i16 %13, i16 %15 monotonic
+ store i16 %17, i16* @us, align 2
+ %18 = load i8* @uc, align 1
+ %19 = zext i8 %18 to i32
+ %20 = load i8* @sc, align 1
+ %21 = sext i8 %20 to i32
+ %22 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %23 = cmpxchg i32* %22, i32 %19, i32 %21 monotonic
+ store i32 %23, i32* @si, align 4
+ %24 = load i8* @uc, align 1
+ %25 = zext i8 %24 to i32
+ %26 = load i8* @sc, align 1
+ %27 = sext i8 %26 to i32
+ %28 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %29 = cmpxchg i32* %28, i32 %25, i32 %27 monotonic
+ store i32 %29, i32* @ui, align 4
+ %30 = load i8* @uc, align 1
+ %31 = zext i8 %30 to i32
+ %32 = load i8* @sc, align 1
+ %33 = sext i8 %32 to i32
+ %34 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %35 = cmpxchg i32* %34, i32 %31, i32 %33 monotonic
+ store i32 %35, i32* @sl, align 4
+ %36 = load i8* @uc, align 1
+ %37 = zext i8 %36 to i32
+ %38 = load i8* @sc, align 1
+ %39 = sext i8 %38 to i32
+ %40 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %41 = cmpxchg i32* %40, i32 %37, i32 %39 monotonic
+ store i32 %41, i32* @ul, align 4
+ %42 = load i8* @uc, align 1
+ %43 = load i8* @sc, align 1
+ %44 = cmpxchg i8* @sc, i8 %42, i8 %43 monotonic
+ %45 = icmp eq i8 %44, %42
+ %46 = zext i1 %45 to i32
+ store i32 %46, i32* @ui, align 4
+ %47 = load i8* @uc, align 1
+ %48 = load i8* @sc, align 1
+ %49 = cmpxchg i8* @uc, i8 %47, i8 %48 monotonic
+ %50 = icmp eq i8 %49, %47
+ %51 = zext i1 %50 to i32
+ store i32 %51, i32* @ui, align 4
+ %52 = load i8* @uc, align 1
+ %53 = zext i8 %52 to i16
+ %54 = load i8* @sc, align 1
+ %55 = sext i8 %54 to i16
+ %56 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %57 = cmpxchg i16* %56, i16 %53, i16 %55 monotonic
+ %58 = icmp eq i16 %57, %53
+ %59 = zext i1 %58 to i32
+ store i32 %59, i32* @ui, align 4
+ %60 = load i8* @uc, align 1
+ %61 = zext i8 %60 to i16
+ %62 = load i8* @sc, align 1
+ %63 = sext i8 %62 to i16
+ %64 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %65 = cmpxchg i16* %64, i16 %61, i16 %63 monotonic
+ %66 = icmp eq i16 %65, %61
+ %67 = zext i1 %66 to i32
+ store i32 %67, i32* @ui, align 4
+ %68 = load i8* @uc, align 1
+ %69 = zext i8 %68 to i32
+ %70 = load i8* @sc, align 1
+ %71 = sext i8 %70 to i32
+ %72 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %73 = cmpxchg i32* %72, i32 %69, i32 %71 monotonic
+ %74 = icmp eq i32 %73, %69
+ %75 = zext i1 %74 to i32
+ store i32 %75, i32* @ui, align 4
+ %76 = load i8* @uc, align 1
+ %77 = zext i8 %76 to i32
+ %78 = load i8* @sc, align 1
+ %79 = sext i8 %78 to i32
+ %80 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %81 = cmpxchg i32* %80, i32 %77, i32 %79 monotonic
+ %82 = icmp eq i32 %81, %77
+ %83 = zext i1 %82 to i32
+ store i32 %83, i32* @ui, align 4
+ %84 = load i8* @uc, align 1
+ %85 = zext i8 %84 to i32
+ %86 = load i8* @sc, align 1
+ %87 = sext i8 %86 to i32
+ %88 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %89 = cmpxchg i32* %88, i32 %85, i32 %87 monotonic
+ %90 = icmp eq i32 %89, %85
+ %91 = zext i1 %90 to i32
+ store i32 %91, i32* @ui, align 4
+ %92 = load i8* @uc, align 1
+ %93 = zext i8 %92 to i32
+ %94 = load i8* @sc, align 1
+ %95 = sext i8 %94 to i32
+ %96 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %97 = cmpxchg i32* %96, i32 %93, i32 %95 monotonic
+ %98 = icmp eq i32 %97, %93
+ %99 = zext i1 %98 to i32
+ store i32 %99, i32* @ui, align 4
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
-declare i8 @llvm.atomic.cmp.swap.i8.p0i8(i8*, i8, i8) nounwind
-
-declare i16 @llvm.atomic.cmp.swap.i16.p0i16(i16*, i16, i16) nounwind
-
-declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32*, i32, i32) nounwind
-
define void @test_lock() nounwind {
entry:
- call i8 @llvm.atomic.swap.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:0 [#uses=1]
- store i8 %0, i8* @sc, align 1
- call i8 @llvm.atomic.swap.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:1 [#uses=1]
- store i8 %1, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.swap.i16.p0i16( i16* %2, i16 1 ) ; <i16>:3 [#uses=1]
- store i16 %3, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.swap.i16.p0i16( i16* %4, i16 1 ) ; <i16>:5 [#uses=1]
- store i16 %5, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %6, i32 1 ) ; <i32>:7 [#uses=1]
- store i32 %7, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %8, i32 1 ) ; <i32>:9 [#uses=1]
- store i32 %9, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:10 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %10, i32 1 ) ; <i32>:11 [#uses=1]
- store i32 %11, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:12 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %12, i32 1 ) ; <i32>:13 [#uses=1]
- store i32 %13, i32* @ul, align 4
- call void @llvm.memory.barrier( i1 true, i1 true, i1 true, i1 true, i1 false )
- volatile store i8 0, i8* @sc, align 1
- volatile store i8 0, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:14 [#uses=1]
- volatile store i16 0, i16* %14, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:15 [#uses=1]
- volatile store i16 0, i16* %15, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:16 [#uses=1]
- volatile store i32 0, i32* %16, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:17 [#uses=1]
- volatile store i32 0, i32* %17, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:18 [#uses=1]
- volatile store i32 0, i32* %18, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:19 [#uses=1]
- volatile store i32 0, i32* %19, align 4
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:20 [#uses=1]
- volatile store i64 0, i64* %20, align 8
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:21 [#uses=1]
- volatile store i64 0, i64* %21, align 8
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = atomicrmw xchg i8* @sc, i8 1 monotonic
+ store i8 %0, i8* @sc, align 1
+ %1 = atomicrmw xchg i8* @uc, i8 1 monotonic
+ store i8 %1, i8* @uc, align 1
+ %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %3 = atomicrmw xchg i16* %2, i16 1 monotonic
+ store i16 %3, i16* @ss, align 2
+ %4 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %5 = atomicrmw xchg i16* %4, i16 1 monotonic
+ store i16 %5, i16* @us, align 2
+ %6 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %7 = atomicrmw xchg i32* %6, i32 1 monotonic
+ store i32 %7, i32* @si, align 4
+ %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %9 = atomicrmw xchg i32* %8, i32 1 monotonic
+ store i32 %9, i32* @ui, align 4
+ %10 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ %11 = atomicrmw xchg i32* %10, i32 1 monotonic
+ store i32 %11, i32* @sl, align 4
+ %12 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ %13 = atomicrmw xchg i32* %12, i32 1 monotonic
+ store i32 %13, i32* @ul, align 4
+ fence seq_cst
+ store volatile i8 0, i8* @sc, align 1
+ store volatile i8 0, i8* @uc, align 1
+ %14 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ store volatile i16 0, i16* %14, align 2
+ %15 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ store volatile i16 0, i16* %15, align 2
+ %16 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ store volatile i32 0, i32* %16, align 4
+ %17 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ store volatile i32 0, i32* %17, align 4
+ %18 = bitcast i8* bitcast (i32* @sl to i8*) to i32*
+ store volatile i32 0, i32* %18, align 4
+ %19 = bitcast i8* bitcast (i32* @ul to i8*) to i32*
+ store volatile i32 0, i32* %19, align 4
+ %20 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ store volatile i64 0, i64* %20, align 8
+ %21 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ store volatile i64 0, i64* %21, align 8
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
-
-declare i8 @llvm.atomic.swap.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.swap.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.swap.i32.p0i32(i32*, i32) nounwind
-
-declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
diff --git a/test/CodeGen/PowerPC/Atomics-64.ll b/test/CodeGen/PowerPC/Atomics-64.ll
index cfc1eb9..d35b848 100644
--- a/test/CodeGen/PowerPC/Atomics-64.ll
+++ b/test/CodeGen/PowerPC/Atomics-64.ll
@@ -8,772 +8,707 @@
target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f128:64:128"
target triple = "powerpc64-apple-darwin9"
-@sc = common global i8 0 ; <i8*> [#uses=52]
-@uc = common global i8 0 ; <i8*> [#uses=100]
-@ss = common global i16 0 ; <i16*> [#uses=15]
-@us = common global i16 0 ; <i16*> [#uses=15]
-@si = common global i32 0 ; <i32*> [#uses=15]
-@ui = common global i32 0 ; <i32*> [#uses=23]
-@sl = common global i64 0, align 8 ; <i64*> [#uses=15]
-@ul = common global i64 0, align 8 ; <i64*> [#uses=15]
-@sll = common global i64 0, align 8 ; <i64*> [#uses=1]
-@ull = common global i64 0, align 8 ; <i64*> [#uses=1]
+
+@sc = common global i8 0
+@uc = common global i8 0
+@ss = common global i16 0
+@us = common global i16 0
+@si = common global i32 0
+@ui = common global i32 0
+@sl = common global i64 0, align 8
+@ul = common global i64 0, align 8
+@sll = common global i64 0, align 8
+@ull = common global i64 0, align 8
define void @test_op_ignore() nounwind {
entry:
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:0 [#uses=0]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:1 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %2, i16 1 ) ; <i16>:3 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %4, i16 1 ) ; <i16>:5 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %6, i32 1 ) ; <i32>:7 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %8, i32 1 ) ; <i32>:9 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:10 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %10, i64 1 ) ; <i64>:11 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:12 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %12, i64 1 ) ; <i64>:13 [#uses=0]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:14 [#uses=0]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:15 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:16 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %16, i16 1 ) ; <i16>:17 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:18 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %18, i16 1 ) ; <i16>:19 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:20 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %20, i32 1 ) ; <i32>:21 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:22 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %22, i32 1 ) ; <i32>:23 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:24 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %24, i64 1 ) ; <i64>:25 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:26 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %26, i64 1 ) ; <i64>:27 [#uses=0]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:28 [#uses=0]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:29 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:30 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %30, i16 1 ) ; <i16>:31 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:32 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %32, i16 1 ) ; <i16>:33 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:34 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %34, i32 1 ) ; <i32>:35 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:36 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %36, i32 1 ) ; <i32>:37 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:38 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %38, i64 1 ) ; <i64>:39 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:40 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %40, i64 1 ) ; <i64>:41 [#uses=0]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:42 [#uses=0]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:43 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:44 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %44, i16 1 ) ; <i16>:45 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:46 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %46, i16 1 ) ; <i16>:47 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:48 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %48, i32 1 ) ; <i32>:49 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:50 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %50, i32 1 ) ; <i32>:51 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:52 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %52, i64 1 ) ; <i64>:53 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:54 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %54, i64 1 ) ; <i64>:55 [#uses=0]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:56 [#uses=0]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:57 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:58 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %58, i16 1 ) ; <i16>:59 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:60 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %60, i16 1 ) ; <i16>:61 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:62 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %62, i32 1 ) ; <i32>:63 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:64 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %64, i32 1 ) ; <i32>:65 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:66 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %66, i64 1 ) ; <i64>:67 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:68 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %68, i64 1 ) ; <i64>:69 [#uses=0]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:70 [#uses=0]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:71 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:72 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %72, i16 1 ) ; <i16>:73 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:74 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %74, i16 1 ) ; <i16>:75 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:76 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %76, i32 1 ) ; <i32>:77 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:78 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %78, i32 1 ) ; <i32>:79 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:80 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %80, i64 1 ) ; <i64>:81 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:82 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %82, i64 1 ) ; <i64>:83 [#uses=0]
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = atomicrmw add i8* @sc, i8 1 monotonic
+ %1 = atomicrmw add i8* @uc, i8 1 monotonic
+ %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %3 = atomicrmw add i16* %2, i16 1 monotonic
+ %4 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %5 = atomicrmw add i16* %4, i16 1 monotonic
+ %6 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %7 = atomicrmw add i32* %6, i32 1 monotonic
+ %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %9 = atomicrmw add i32* %8, i32 1 monotonic
+ %10 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %11 = atomicrmw add i64* %10, i64 1 monotonic
+ %12 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %13 = atomicrmw add i64* %12, i64 1 monotonic
+ %14 = atomicrmw sub i8* @sc, i8 1 monotonic
+ %15 = atomicrmw sub i8* @uc, i8 1 monotonic
+ %16 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %17 = atomicrmw sub i16* %16, i16 1 monotonic
+ %18 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %19 = atomicrmw sub i16* %18, i16 1 monotonic
+ %20 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %21 = atomicrmw sub i32* %20, i32 1 monotonic
+ %22 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %23 = atomicrmw sub i32* %22, i32 1 monotonic
+ %24 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %25 = atomicrmw sub i64* %24, i64 1 monotonic
+ %26 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %27 = atomicrmw sub i64* %26, i64 1 monotonic
+ %28 = atomicrmw or i8* @sc, i8 1 monotonic
+ %29 = atomicrmw or i8* @uc, i8 1 monotonic
+ %30 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %31 = atomicrmw or i16* %30, i16 1 monotonic
+ %32 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %33 = atomicrmw or i16* %32, i16 1 monotonic
+ %34 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %35 = atomicrmw or i32* %34, i32 1 monotonic
+ %36 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %37 = atomicrmw or i32* %36, i32 1 monotonic
+ %38 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %39 = atomicrmw or i64* %38, i64 1 monotonic
+ %40 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %41 = atomicrmw or i64* %40, i64 1 monotonic
+ %42 = atomicrmw xor i8* @sc, i8 1 monotonic
+ %43 = atomicrmw xor i8* @uc, i8 1 monotonic
+ %44 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %45 = atomicrmw xor i16* %44, i16 1 monotonic
+ %46 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %47 = atomicrmw xor i16* %46, i16 1 monotonic
+ %48 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %49 = atomicrmw xor i32* %48, i32 1 monotonic
+ %50 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %51 = atomicrmw xor i32* %50, i32 1 monotonic
+ %52 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %53 = atomicrmw xor i64* %52, i64 1 monotonic
+ %54 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %55 = atomicrmw xor i64* %54, i64 1 monotonic
+ %56 = atomicrmw and i8* @sc, i8 1 monotonic
+ %57 = atomicrmw and i8* @uc, i8 1 monotonic
+ %58 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %59 = atomicrmw and i16* %58, i16 1 monotonic
+ %60 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %61 = atomicrmw and i16* %60, i16 1 monotonic
+ %62 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %63 = atomicrmw and i32* %62, i32 1 monotonic
+ %64 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %65 = atomicrmw and i32* %64, i32 1 monotonic
+ %66 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %67 = atomicrmw and i64* %66, i64 1 monotonic
+ %68 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %69 = atomicrmw and i64* %68, i64 1 monotonic
+ %70 = atomicrmw nand i8* @sc, i8 1 monotonic
+ %71 = atomicrmw nand i8* @uc, i8 1 monotonic
+ %72 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %73 = atomicrmw nand i16* %72, i16 1 monotonic
+ %74 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %75 = atomicrmw nand i16* %74, i16 1 monotonic
+ %76 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %77 = atomicrmw nand i32* %76, i32 1 monotonic
+ %78 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %79 = atomicrmw nand i32* %78, i32 1 monotonic
+ %80 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %81 = atomicrmw nand i64* %80, i64 1 monotonic
+ %82 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %83 = atomicrmw nand i64* %82, i64 1 monotonic
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
-declare i8 @llvm.atomic.load.add.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.add.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.add.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.add.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.sub.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.sub.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.sub.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.sub.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.or.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.or.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.or.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.or.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.xor.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.xor.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.xor.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.xor.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.and.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.and.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.and.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.and.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.nand.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.nand.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.nand.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.nand.i64.p0i64(i64*, i64) nounwind
-
define void @test_fetch_and_op() nounwind {
entry:
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:0 [#uses=1]
- store i8 %0, i8* @sc, align 1
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:1 [#uses=1]
- store i8 %1, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %2, i16 11 ) ; <i16>:3 [#uses=1]
- store i16 %3, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %4, i16 11 ) ; <i16>:5 [#uses=1]
- store i16 %5, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %6, i32 11 ) ; <i32>:7 [#uses=1]
- store i32 %7, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %8, i32 11 ) ; <i32>:9 [#uses=1]
- store i32 %9, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:10 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %10, i64 11 ) ; <i64>:11 [#uses=1]
- store i64 %11, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:12 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %12, i64 11 ) ; <i64>:13 [#uses=1]
- store i64 %13, i64* @ul, align 8
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:14 [#uses=1]
- store i8 %14, i8* @sc, align 1
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:15 [#uses=1]
- store i8 %15, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:16 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %16, i16 11 ) ; <i16>:17 [#uses=1]
- store i16 %17, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:18 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %18, i16 11 ) ; <i16>:19 [#uses=1]
- store i16 %19, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:20 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %20, i32 11 ) ; <i32>:21 [#uses=1]
- store i32 %21, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:22 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %22, i32 11 ) ; <i32>:23 [#uses=1]
- store i32 %23, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:24 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %24, i64 11 ) ; <i64>:25 [#uses=1]
- store i64 %25, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:26 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %26, i64 11 ) ; <i64>:27 [#uses=1]
- store i64 %27, i64* @ul, align 8
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:28 [#uses=1]
- store i8 %28, i8* @sc, align 1
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:29 [#uses=1]
- store i8 %29, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:30 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %30, i16 11 ) ; <i16>:31 [#uses=1]
- store i16 %31, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:32 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %32, i16 11 ) ; <i16>:33 [#uses=1]
- store i16 %33, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:34 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %34, i32 11 ) ; <i32>:35 [#uses=1]
- store i32 %35, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:36 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %36, i32 11 ) ; <i32>:37 [#uses=1]
- store i32 %37, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:38 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %38, i64 11 ) ; <i64>:39 [#uses=1]
- store i64 %39, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:40 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %40, i64 11 ) ; <i64>:41 [#uses=1]
- store i64 %41, i64* @ul, align 8
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:42 [#uses=1]
- store i8 %42, i8* @sc, align 1
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:43 [#uses=1]
- store i8 %43, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:44 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %44, i16 11 ) ; <i16>:45 [#uses=1]
- store i16 %45, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:46 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %46, i16 11 ) ; <i16>:47 [#uses=1]
- store i16 %47, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:48 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %48, i32 11 ) ; <i32>:49 [#uses=1]
- store i32 %49, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:50 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %50, i32 11 ) ; <i32>:51 [#uses=1]
- store i32 %51, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:52 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %52, i64 11 ) ; <i64>:53 [#uses=1]
- store i64 %53, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:54 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %54, i64 11 ) ; <i64>:55 [#uses=1]
- store i64 %55, i64* @ul, align 8
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:56 [#uses=1]
- store i8 %56, i8* @sc, align 1
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:57 [#uses=1]
- store i8 %57, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:58 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %58, i16 11 ) ; <i16>:59 [#uses=1]
- store i16 %59, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:60 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %60, i16 11 ) ; <i16>:61 [#uses=1]
- store i16 %61, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:62 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %62, i32 11 ) ; <i32>:63 [#uses=1]
- store i32 %63, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:64 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %64, i32 11 ) ; <i32>:65 [#uses=1]
- store i32 %65, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:66 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %66, i64 11 ) ; <i64>:67 [#uses=1]
- store i64 %67, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:68 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %68, i64 11 ) ; <i64>:69 [#uses=1]
- store i64 %69, i64* @ul, align 8
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:70 [#uses=1]
- store i8 %70, i8* @sc, align 1
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:71 [#uses=1]
- store i8 %71, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:72 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %72, i16 11 ) ; <i16>:73 [#uses=1]
- store i16 %73, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:74 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %74, i16 11 ) ; <i16>:75 [#uses=1]
- store i16 %75, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:76 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %76, i32 11 ) ; <i32>:77 [#uses=1]
- store i32 %77, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:78 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %78, i32 11 ) ; <i32>:79 [#uses=1]
- store i32 %79, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:80 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %80, i64 11 ) ; <i64>:81 [#uses=1]
- store i64 %81, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:82 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %82, i64 11 ) ; <i64>:83 [#uses=1]
- store i64 %83, i64* @ul, align 8
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = atomicrmw add i8* @sc, i8 11 monotonic
+ store i8 %0, i8* @sc, align 1
+ %1 = atomicrmw add i8* @uc, i8 11 monotonic
+ store i8 %1, i8* @uc, align 1
+ %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %3 = atomicrmw add i16* %2, i16 11 monotonic
+ store i16 %3, i16* @ss, align 2
+ %4 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %5 = atomicrmw add i16* %4, i16 11 monotonic
+ store i16 %5, i16* @us, align 2
+ %6 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %7 = atomicrmw add i32* %6, i32 11 monotonic
+ store i32 %7, i32* @si, align 4
+ %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %9 = atomicrmw add i32* %8, i32 11 monotonic
+ store i32 %9, i32* @ui, align 4
+ %10 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %11 = atomicrmw add i64* %10, i64 11 monotonic
+ store i64 %11, i64* @sl, align 8
+ %12 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %13 = atomicrmw add i64* %12, i64 11 monotonic
+ store i64 %13, i64* @ul, align 8
+ %14 = atomicrmw sub i8* @sc, i8 11 monotonic
+ store i8 %14, i8* @sc, align 1
+ %15 = atomicrmw sub i8* @uc, i8 11 monotonic
+ store i8 %15, i8* @uc, align 1
+ %16 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %17 = atomicrmw sub i16* %16, i16 11 monotonic
+ store i16 %17, i16* @ss, align 2
+ %18 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %19 = atomicrmw sub i16* %18, i16 11 monotonic
+ store i16 %19, i16* @us, align 2
+ %20 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %21 = atomicrmw sub i32* %20, i32 11 monotonic
+ store i32 %21, i32* @si, align 4
+ %22 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %23 = atomicrmw sub i32* %22, i32 11 monotonic
+ store i32 %23, i32* @ui, align 4
+ %24 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %25 = atomicrmw sub i64* %24, i64 11 monotonic
+ store i64 %25, i64* @sl, align 8
+ %26 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %27 = atomicrmw sub i64* %26, i64 11 monotonic
+ store i64 %27, i64* @ul, align 8
+ %28 = atomicrmw or i8* @sc, i8 11 monotonic
+ store i8 %28, i8* @sc, align 1
+ %29 = atomicrmw or i8* @uc, i8 11 monotonic
+ store i8 %29, i8* @uc, align 1
+ %30 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %31 = atomicrmw or i16* %30, i16 11 monotonic
+ store i16 %31, i16* @ss, align 2
+ %32 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %33 = atomicrmw or i16* %32, i16 11 monotonic
+ store i16 %33, i16* @us, align 2
+ %34 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %35 = atomicrmw or i32* %34, i32 11 monotonic
+ store i32 %35, i32* @si, align 4
+ %36 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %37 = atomicrmw or i32* %36, i32 11 monotonic
+ store i32 %37, i32* @ui, align 4
+ %38 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %39 = atomicrmw or i64* %38, i64 11 monotonic
+ store i64 %39, i64* @sl, align 8
+ %40 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %41 = atomicrmw or i64* %40, i64 11 monotonic
+ store i64 %41, i64* @ul, align 8
+ %42 = atomicrmw xor i8* @sc, i8 11 monotonic
+ store i8 %42, i8* @sc, align 1
+ %43 = atomicrmw xor i8* @uc, i8 11 monotonic
+ store i8 %43, i8* @uc, align 1
+ %44 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %45 = atomicrmw xor i16* %44, i16 11 monotonic
+ store i16 %45, i16* @ss, align 2
+ %46 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %47 = atomicrmw xor i16* %46, i16 11 monotonic
+ store i16 %47, i16* @us, align 2
+ %48 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %49 = atomicrmw xor i32* %48, i32 11 monotonic
+ store i32 %49, i32* @si, align 4
+ %50 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %51 = atomicrmw xor i32* %50, i32 11 monotonic
+ store i32 %51, i32* @ui, align 4
+ %52 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %53 = atomicrmw xor i64* %52, i64 11 monotonic
+ store i64 %53, i64* @sl, align 8
+ %54 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %55 = atomicrmw xor i64* %54, i64 11 monotonic
+ store i64 %55, i64* @ul, align 8
+ %56 = atomicrmw and i8* @sc, i8 11 monotonic
+ store i8 %56, i8* @sc, align 1
+ %57 = atomicrmw and i8* @uc, i8 11 monotonic
+ store i8 %57, i8* @uc, align 1
+ %58 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %59 = atomicrmw and i16* %58, i16 11 monotonic
+ store i16 %59, i16* @ss, align 2
+ %60 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %61 = atomicrmw and i16* %60, i16 11 monotonic
+ store i16 %61, i16* @us, align 2
+ %62 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %63 = atomicrmw and i32* %62, i32 11 monotonic
+ store i32 %63, i32* @si, align 4
+ %64 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %65 = atomicrmw and i32* %64, i32 11 monotonic
+ store i32 %65, i32* @ui, align 4
+ %66 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %67 = atomicrmw and i64* %66, i64 11 monotonic
+ store i64 %67, i64* @sl, align 8
+ %68 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %69 = atomicrmw and i64* %68, i64 11 monotonic
+ store i64 %69, i64* @ul, align 8
+ %70 = atomicrmw nand i8* @sc, i8 11 monotonic
+ store i8 %70, i8* @sc, align 1
+ %71 = atomicrmw nand i8* @uc, i8 11 monotonic
+ store i8 %71, i8* @uc, align 1
+ %72 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %73 = atomicrmw nand i16* %72, i16 11 monotonic
+ store i16 %73, i16* @ss, align 2
+ %74 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %75 = atomicrmw nand i16* %74, i16 11 monotonic
+ store i16 %75, i16* @us, align 2
+ %76 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %77 = atomicrmw nand i32* %76, i32 11 monotonic
+ store i32 %77, i32* @si, align 4
+ %78 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %79 = atomicrmw nand i32* %78, i32 11 monotonic
+ store i32 %79, i32* @ui, align 4
+ %80 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %81 = atomicrmw nand i64* %80, i64 11 monotonic
+ store i64 %81, i64* @sl, align 8
+ %82 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %83 = atomicrmw nand i64* %82, i64 11 monotonic
+ store i64 %83, i64* @ul, align 8
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
define void @test_op_and_fetch() nounwind {
entry:
- load i8* @uc, align 1 ; <i8>:0 [#uses=2]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 %0 ) ; <i8>:1 [#uses=1]
- add i8 %1, %0 ; <i8>:2 [#uses=1]
- store i8 %2, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:3 [#uses=2]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 %3 ) ; <i8>:4 [#uses=1]
- add i8 %4, %3 ; <i8>:5 [#uses=1]
- store i8 %5, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:6 [#uses=1]
- zext i8 %6 to i16 ; <i16>:7 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:8 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %8, i16 %7 ) ; <i16>:9 [#uses=1]
- add i16 %9, %7 ; <i16>:10 [#uses=1]
- store i16 %10, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:11 [#uses=1]
- zext i8 %11 to i16 ; <i16>:12 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:13 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %13, i16 %12 ) ; <i16>:14 [#uses=1]
- add i16 %14, %12 ; <i16>:15 [#uses=1]
- store i16 %15, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:16 [#uses=1]
- zext i8 %16 to i32 ; <i32>:17 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:18 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %18, i32 %17 ) ; <i32>:19 [#uses=1]
- add i32 %19, %17 ; <i32>:20 [#uses=1]
- store i32 %20, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:21 [#uses=1]
- zext i8 %21 to i32 ; <i32>:22 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:23 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %23, i32 %22 ) ; <i32>:24 [#uses=1]
- add i32 %24, %22 ; <i32>:25 [#uses=1]
- store i32 %25, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:26 [#uses=1]
- zext i8 %26 to i64 ; <i64>:27 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:28 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %28, i64 %27 ) ; <i64>:29 [#uses=1]
- add i64 %29, %27 ; <i64>:30 [#uses=1]
- store i64 %30, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:31 [#uses=1]
- zext i8 %31 to i64 ; <i64>:32 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:33 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %33, i64 %32 ) ; <i64>:34 [#uses=1]
- add i64 %34, %32 ; <i64>:35 [#uses=1]
- store i64 %35, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:36 [#uses=2]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 %36 ) ; <i8>:37 [#uses=1]
- sub i8 %37, %36 ; <i8>:38 [#uses=1]
- store i8 %38, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:39 [#uses=2]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 %39 ) ; <i8>:40 [#uses=1]
- sub i8 %40, %39 ; <i8>:41 [#uses=1]
- store i8 %41, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:42 [#uses=1]
- zext i8 %42 to i16 ; <i16>:43 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:44 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %44, i16 %43 ) ; <i16>:45 [#uses=1]
- sub i16 %45, %43 ; <i16>:46 [#uses=1]
- store i16 %46, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:47 [#uses=1]
- zext i8 %47 to i16 ; <i16>:48 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:49 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %49, i16 %48 ) ; <i16>:50 [#uses=1]
- sub i16 %50, %48 ; <i16>:51 [#uses=1]
- store i16 %51, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:52 [#uses=1]
- zext i8 %52 to i32 ; <i32>:53 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:54 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %54, i32 %53 ) ; <i32>:55 [#uses=1]
- sub i32 %55, %53 ; <i32>:56 [#uses=1]
- store i32 %56, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:57 [#uses=1]
- zext i8 %57 to i32 ; <i32>:58 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:59 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %59, i32 %58 ) ; <i32>:60 [#uses=1]
- sub i32 %60, %58 ; <i32>:61 [#uses=1]
- store i32 %61, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:62 [#uses=1]
- zext i8 %62 to i64 ; <i64>:63 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:64 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %64, i64 %63 ) ; <i64>:65 [#uses=1]
- sub i64 %65, %63 ; <i64>:66 [#uses=1]
- store i64 %66, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:67 [#uses=1]
- zext i8 %67 to i64 ; <i64>:68 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:69 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %69, i64 %68 ) ; <i64>:70 [#uses=1]
- sub i64 %70, %68 ; <i64>:71 [#uses=1]
- store i64 %71, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:72 [#uses=2]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 %72 ) ; <i8>:73 [#uses=1]
- or i8 %73, %72 ; <i8>:74 [#uses=1]
- store i8 %74, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:75 [#uses=2]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 %75 ) ; <i8>:76 [#uses=1]
- or i8 %76, %75 ; <i8>:77 [#uses=1]
- store i8 %77, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:78 [#uses=1]
- zext i8 %78 to i16 ; <i16>:79 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:80 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %80, i16 %79 ) ; <i16>:81 [#uses=1]
- or i16 %81, %79 ; <i16>:82 [#uses=1]
- store i16 %82, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:83 [#uses=1]
- zext i8 %83 to i16 ; <i16>:84 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:85 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %85, i16 %84 ) ; <i16>:86 [#uses=1]
- or i16 %86, %84 ; <i16>:87 [#uses=1]
- store i16 %87, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:88 [#uses=1]
- zext i8 %88 to i32 ; <i32>:89 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:90 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %90, i32 %89 ) ; <i32>:91 [#uses=1]
- or i32 %91, %89 ; <i32>:92 [#uses=1]
- store i32 %92, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:93 [#uses=1]
- zext i8 %93 to i32 ; <i32>:94 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:95 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %95, i32 %94 ) ; <i32>:96 [#uses=1]
- or i32 %96, %94 ; <i32>:97 [#uses=1]
- store i32 %97, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:98 [#uses=1]
- zext i8 %98 to i64 ; <i64>:99 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:100 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %100, i64 %99 ) ; <i64>:101 [#uses=1]
- or i64 %101, %99 ; <i64>:102 [#uses=1]
- store i64 %102, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:103 [#uses=1]
- zext i8 %103 to i64 ; <i64>:104 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:105 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %105, i64 %104 ) ; <i64>:106 [#uses=1]
- or i64 %106, %104 ; <i64>:107 [#uses=1]
- store i64 %107, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:108 [#uses=2]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 %108 ) ; <i8>:109 [#uses=1]
- xor i8 %109, %108 ; <i8>:110 [#uses=1]
- store i8 %110, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:111 [#uses=2]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 %111 ) ; <i8>:112 [#uses=1]
- xor i8 %112, %111 ; <i8>:113 [#uses=1]
- store i8 %113, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:114 [#uses=1]
- zext i8 %114 to i16 ; <i16>:115 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:116 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %116, i16 %115 ) ; <i16>:117 [#uses=1]
- xor i16 %117, %115 ; <i16>:118 [#uses=1]
- store i16 %118, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:119 [#uses=1]
- zext i8 %119 to i16 ; <i16>:120 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:121 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %121, i16 %120 ) ; <i16>:122 [#uses=1]
- xor i16 %122, %120 ; <i16>:123 [#uses=1]
- store i16 %123, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:124 [#uses=1]
- zext i8 %124 to i32 ; <i32>:125 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:126 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %126, i32 %125 ) ; <i32>:127 [#uses=1]
- xor i32 %127, %125 ; <i32>:128 [#uses=1]
- store i32 %128, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:129 [#uses=1]
- zext i8 %129 to i32 ; <i32>:130 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:131 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %131, i32 %130 ) ; <i32>:132 [#uses=1]
- xor i32 %132, %130 ; <i32>:133 [#uses=1]
- store i32 %133, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:134 [#uses=1]
- zext i8 %134 to i64 ; <i64>:135 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:136 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %136, i64 %135 ) ; <i64>:137 [#uses=1]
- xor i64 %137, %135 ; <i64>:138 [#uses=1]
- store i64 %138, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:139 [#uses=1]
- zext i8 %139 to i64 ; <i64>:140 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:141 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %141, i64 %140 ) ; <i64>:142 [#uses=1]
- xor i64 %142, %140 ; <i64>:143 [#uses=1]
- store i64 %143, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:144 [#uses=2]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 %144 ) ; <i8>:145 [#uses=1]
- and i8 %145, %144 ; <i8>:146 [#uses=1]
- store i8 %146, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:147 [#uses=2]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 %147 ) ; <i8>:148 [#uses=1]
- and i8 %148, %147 ; <i8>:149 [#uses=1]
- store i8 %149, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:150 [#uses=1]
- zext i8 %150 to i16 ; <i16>:151 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:152 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %152, i16 %151 ) ; <i16>:153 [#uses=1]
- and i16 %153, %151 ; <i16>:154 [#uses=1]
- store i16 %154, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:155 [#uses=1]
- zext i8 %155 to i16 ; <i16>:156 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:157 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %157, i16 %156 ) ; <i16>:158 [#uses=1]
- and i16 %158, %156 ; <i16>:159 [#uses=1]
- store i16 %159, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:160 [#uses=1]
- zext i8 %160 to i32 ; <i32>:161 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:162 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %162, i32 %161 ) ; <i32>:163 [#uses=1]
- and i32 %163, %161 ; <i32>:164 [#uses=1]
- store i32 %164, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:165 [#uses=1]
- zext i8 %165 to i32 ; <i32>:166 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:167 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %167, i32 %166 ) ; <i32>:168 [#uses=1]
- and i32 %168, %166 ; <i32>:169 [#uses=1]
- store i32 %169, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:170 [#uses=1]
- zext i8 %170 to i64 ; <i64>:171 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:172 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %172, i64 %171 ) ; <i64>:173 [#uses=1]
- and i64 %173, %171 ; <i64>:174 [#uses=1]
- store i64 %174, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:175 [#uses=1]
- zext i8 %175 to i64 ; <i64>:176 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:177 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %177, i64 %176 ) ; <i64>:178 [#uses=1]
- and i64 %178, %176 ; <i64>:179 [#uses=1]
- store i64 %179, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:180 [#uses=2]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 %180 ) ; <i8>:181 [#uses=1]
- xor i8 %181, -1 ; <i8>:182 [#uses=1]
- and i8 %182, %180 ; <i8>:183 [#uses=1]
- store i8 %183, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:184 [#uses=2]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 %184 ) ; <i8>:185 [#uses=1]
- xor i8 %185, -1 ; <i8>:186 [#uses=1]
- and i8 %186, %184 ; <i8>:187 [#uses=1]
- store i8 %187, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:188 [#uses=1]
- zext i8 %188 to i16 ; <i16>:189 [#uses=2]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:190 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %190, i16 %189 ) ; <i16>:191 [#uses=1]
- xor i16 %191, -1 ; <i16>:192 [#uses=1]
- and i16 %192, %189 ; <i16>:193 [#uses=1]
- store i16 %193, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:194 [#uses=1]
- zext i8 %194 to i16 ; <i16>:195 [#uses=2]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:196 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %196, i16 %195 ) ; <i16>:197 [#uses=1]
- xor i16 %197, -1 ; <i16>:198 [#uses=1]
- and i16 %198, %195 ; <i16>:199 [#uses=1]
- store i16 %199, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:200 [#uses=1]
- zext i8 %200 to i32 ; <i32>:201 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:202 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %202, i32 %201 ) ; <i32>:203 [#uses=1]
- xor i32 %203, -1 ; <i32>:204 [#uses=1]
- and i32 %204, %201 ; <i32>:205 [#uses=1]
- store i32 %205, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:206 [#uses=1]
- zext i8 %206 to i32 ; <i32>:207 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:208 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %208, i32 %207 ) ; <i32>:209 [#uses=1]
- xor i32 %209, -1 ; <i32>:210 [#uses=1]
- and i32 %210, %207 ; <i32>:211 [#uses=1]
- store i32 %211, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:212 [#uses=1]
- zext i8 %212 to i64 ; <i64>:213 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:214 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %214, i64 %213 ) ; <i64>:215 [#uses=1]
- xor i64 %215, -1 ; <i64>:216 [#uses=1]
- and i64 %216, %213 ; <i64>:217 [#uses=1]
- store i64 %217, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:218 [#uses=1]
- zext i8 %218 to i64 ; <i64>:219 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:220 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %220, i64 %219 ) ; <i64>:221 [#uses=1]
- xor i64 %221, -1 ; <i64>:222 [#uses=1]
- and i64 %222, %219 ; <i64>:223 [#uses=1]
- store i64 %223, i64* @ul, align 8
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = load i8* @uc, align 1
+ %1 = atomicrmw add i8* @sc, i8 %0 monotonic
+ %2 = add i8 %1, %0
+ store i8 %2, i8* @sc, align 1
+ %3 = load i8* @uc, align 1
+ %4 = atomicrmw add i8* @uc, i8 %3 monotonic
+ %5 = add i8 %4, %3
+ store i8 %5, i8* @uc, align 1
+ %6 = load i8* @uc, align 1
+ %7 = zext i8 %6 to i16
+ %8 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %9 = atomicrmw add i16* %8, i16 %7 monotonic
+ %10 = add i16 %9, %7
+ store i16 %10, i16* @ss, align 2
+ %11 = load i8* @uc, align 1
+ %12 = zext i8 %11 to i16
+ %13 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %14 = atomicrmw add i16* %13, i16 %12 monotonic
+ %15 = add i16 %14, %12
+ store i16 %15, i16* @us, align 2
+ %16 = load i8* @uc, align 1
+ %17 = zext i8 %16 to i32
+ %18 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %19 = atomicrmw add i32* %18, i32 %17 monotonic
+ %20 = add i32 %19, %17
+ store i32 %20, i32* @si, align 4
+ %21 = load i8* @uc, align 1
+ %22 = zext i8 %21 to i32
+ %23 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %24 = atomicrmw add i32* %23, i32 %22 monotonic
+ %25 = add i32 %24, %22
+ store i32 %25, i32* @ui, align 4
+ %26 = load i8* @uc, align 1
+ %27 = zext i8 %26 to i64
+ %28 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %29 = atomicrmw add i64* %28, i64 %27 monotonic
+ %30 = add i64 %29, %27
+ store i64 %30, i64* @sl, align 8
+ %31 = load i8* @uc, align 1
+ %32 = zext i8 %31 to i64
+ %33 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %34 = atomicrmw add i64* %33, i64 %32 monotonic
+ %35 = add i64 %34, %32
+ store i64 %35, i64* @ul, align 8
+ %36 = load i8* @uc, align 1
+ %37 = atomicrmw sub i8* @sc, i8 %36 monotonic
+ %38 = sub i8 %37, %36
+ store i8 %38, i8* @sc, align 1
+ %39 = load i8* @uc, align 1
+ %40 = atomicrmw sub i8* @uc, i8 %39 monotonic
+ %41 = sub i8 %40, %39
+ store i8 %41, i8* @uc, align 1
+ %42 = load i8* @uc, align 1
+ %43 = zext i8 %42 to i16
+ %44 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %45 = atomicrmw sub i16* %44, i16 %43 monotonic
+ %46 = sub i16 %45, %43
+ store i16 %46, i16* @ss, align 2
+ %47 = load i8* @uc, align 1
+ %48 = zext i8 %47 to i16
+ %49 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %50 = atomicrmw sub i16* %49, i16 %48 monotonic
+ %51 = sub i16 %50, %48
+ store i16 %51, i16* @us, align 2
+ %52 = load i8* @uc, align 1
+ %53 = zext i8 %52 to i32
+ %54 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %55 = atomicrmw sub i32* %54, i32 %53 monotonic
+ %56 = sub i32 %55, %53
+ store i32 %56, i32* @si, align 4
+ %57 = load i8* @uc, align 1
+ %58 = zext i8 %57 to i32
+ %59 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %60 = atomicrmw sub i32* %59, i32 %58 monotonic
+ %61 = sub i32 %60, %58
+ store i32 %61, i32* @ui, align 4
+ %62 = load i8* @uc, align 1
+ %63 = zext i8 %62 to i64
+ %64 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %65 = atomicrmw sub i64* %64, i64 %63 monotonic
+ %66 = sub i64 %65, %63
+ store i64 %66, i64* @sl, align 8
+ %67 = load i8* @uc, align 1
+ %68 = zext i8 %67 to i64
+ %69 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %70 = atomicrmw sub i64* %69, i64 %68 monotonic
+ %71 = sub i64 %70, %68
+ store i64 %71, i64* @ul, align 8
+ %72 = load i8* @uc, align 1
+ %73 = atomicrmw or i8* @sc, i8 %72 monotonic
+ %74 = or i8 %73, %72
+ store i8 %74, i8* @sc, align 1
+ %75 = load i8* @uc, align 1
+ %76 = atomicrmw or i8* @uc, i8 %75 monotonic
+ %77 = or i8 %76, %75
+ store i8 %77, i8* @uc, align 1
+ %78 = load i8* @uc, align 1
+ %79 = zext i8 %78 to i16
+ %80 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %81 = atomicrmw or i16* %80, i16 %79 monotonic
+ %82 = or i16 %81, %79
+ store i16 %82, i16* @ss, align 2
+ %83 = load i8* @uc, align 1
+ %84 = zext i8 %83 to i16
+ %85 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %86 = atomicrmw or i16* %85, i16 %84 monotonic
+ %87 = or i16 %86, %84
+ store i16 %87, i16* @us, align 2
+ %88 = load i8* @uc, align 1
+ %89 = zext i8 %88 to i32
+ %90 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %91 = atomicrmw or i32* %90, i32 %89 monotonic
+ %92 = or i32 %91, %89
+ store i32 %92, i32* @si, align 4
+ %93 = load i8* @uc, align 1
+ %94 = zext i8 %93 to i32
+ %95 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %96 = atomicrmw or i32* %95, i32 %94 monotonic
+ %97 = or i32 %96, %94
+ store i32 %97, i32* @ui, align 4
+ %98 = load i8* @uc, align 1
+ %99 = zext i8 %98 to i64
+ %100 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %101 = atomicrmw or i64* %100, i64 %99 monotonic
+ %102 = or i64 %101, %99
+ store i64 %102, i64* @sl, align 8
+ %103 = load i8* @uc, align 1
+ %104 = zext i8 %103 to i64
+ %105 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %106 = atomicrmw or i64* %105, i64 %104 monotonic
+ %107 = or i64 %106, %104
+ store i64 %107, i64* @ul, align 8
+ %108 = load i8* @uc, align 1
+ %109 = atomicrmw xor i8* @sc, i8 %108 monotonic
+ %110 = xor i8 %109, %108
+ store i8 %110, i8* @sc, align 1
+ %111 = load i8* @uc, align 1
+ %112 = atomicrmw xor i8* @uc, i8 %111 monotonic
+ %113 = xor i8 %112, %111
+ store i8 %113, i8* @uc, align 1
+ %114 = load i8* @uc, align 1
+ %115 = zext i8 %114 to i16
+ %116 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %117 = atomicrmw xor i16* %116, i16 %115 monotonic
+ %118 = xor i16 %117, %115
+ store i16 %118, i16* @ss, align 2
+ %119 = load i8* @uc, align 1
+ %120 = zext i8 %119 to i16
+ %121 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %122 = atomicrmw xor i16* %121, i16 %120 monotonic
+ %123 = xor i16 %122, %120
+ store i16 %123, i16* @us, align 2
+ %124 = load i8* @uc, align 1
+ %125 = zext i8 %124 to i32
+ %126 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %127 = atomicrmw xor i32* %126, i32 %125 monotonic
+ %128 = xor i32 %127, %125
+ store i32 %128, i32* @si, align 4
+ %129 = load i8* @uc, align 1
+ %130 = zext i8 %129 to i32
+ %131 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %132 = atomicrmw xor i32* %131, i32 %130 monotonic
+ %133 = xor i32 %132, %130
+ store i32 %133, i32* @ui, align 4
+ %134 = load i8* @uc, align 1
+ %135 = zext i8 %134 to i64
+ %136 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %137 = atomicrmw xor i64* %136, i64 %135 monotonic
+ %138 = xor i64 %137, %135
+ store i64 %138, i64* @sl, align 8
+ %139 = load i8* @uc, align 1
+ %140 = zext i8 %139 to i64
+ %141 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %142 = atomicrmw xor i64* %141, i64 %140 monotonic
+ %143 = xor i64 %142, %140
+ store i64 %143, i64* @ul, align 8
+ %144 = load i8* @uc, align 1
+ %145 = atomicrmw and i8* @sc, i8 %144 monotonic
+ %146 = and i8 %145, %144
+ store i8 %146, i8* @sc, align 1
+ %147 = load i8* @uc, align 1
+ %148 = atomicrmw and i8* @uc, i8 %147 monotonic
+ %149 = and i8 %148, %147
+ store i8 %149, i8* @uc, align 1
+ %150 = load i8* @uc, align 1
+ %151 = zext i8 %150 to i16
+ %152 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %153 = atomicrmw and i16* %152, i16 %151 monotonic
+ %154 = and i16 %153, %151
+ store i16 %154, i16* @ss, align 2
+ %155 = load i8* @uc, align 1
+ %156 = zext i8 %155 to i16
+ %157 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %158 = atomicrmw and i16* %157, i16 %156 monotonic
+ %159 = and i16 %158, %156
+ store i16 %159, i16* @us, align 2
+ %160 = load i8* @uc, align 1
+ %161 = zext i8 %160 to i32
+ %162 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %163 = atomicrmw and i32* %162, i32 %161 monotonic
+ %164 = and i32 %163, %161
+ store i32 %164, i32* @si, align 4
+ %165 = load i8* @uc, align 1
+ %166 = zext i8 %165 to i32
+ %167 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %168 = atomicrmw and i32* %167, i32 %166 monotonic
+ %169 = and i32 %168, %166
+ store i32 %169, i32* @ui, align 4
+ %170 = load i8* @uc, align 1
+ %171 = zext i8 %170 to i64
+ %172 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %173 = atomicrmw and i64* %172, i64 %171 monotonic
+ %174 = and i64 %173, %171
+ store i64 %174, i64* @sl, align 8
+ %175 = load i8* @uc, align 1
+ %176 = zext i8 %175 to i64
+ %177 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %178 = atomicrmw and i64* %177, i64 %176 monotonic
+ %179 = and i64 %178, %176
+ store i64 %179, i64* @ul, align 8
+ %180 = load i8* @uc, align 1
+ %181 = atomicrmw nand i8* @sc, i8 %180 monotonic
+ %182 = xor i8 %181, -1
+ %183 = and i8 %182, %180
+ store i8 %183, i8* @sc, align 1
+ %184 = load i8* @uc, align 1
+ %185 = atomicrmw nand i8* @uc, i8 %184 monotonic
+ %186 = xor i8 %185, -1
+ %187 = and i8 %186, %184
+ store i8 %187, i8* @uc, align 1
+ %188 = load i8* @uc, align 1
+ %189 = zext i8 %188 to i16
+ %190 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %191 = atomicrmw nand i16* %190, i16 %189 monotonic
+ %192 = xor i16 %191, -1
+ %193 = and i16 %192, %189
+ store i16 %193, i16* @ss, align 2
+ %194 = load i8* @uc, align 1
+ %195 = zext i8 %194 to i16
+ %196 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %197 = atomicrmw nand i16* %196, i16 %195 monotonic
+ %198 = xor i16 %197, -1
+ %199 = and i16 %198, %195
+ store i16 %199, i16* @us, align 2
+ %200 = load i8* @uc, align 1
+ %201 = zext i8 %200 to i32
+ %202 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %203 = atomicrmw nand i32* %202, i32 %201 monotonic
+ %204 = xor i32 %203, -1
+ %205 = and i32 %204, %201
+ store i32 %205, i32* @si, align 4
+ %206 = load i8* @uc, align 1
+ %207 = zext i8 %206 to i32
+ %208 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %209 = atomicrmw nand i32* %208, i32 %207 monotonic
+ %210 = xor i32 %209, -1
+ %211 = and i32 %210, %207
+ store i32 %211, i32* @ui, align 4
+ %212 = load i8* @uc, align 1
+ %213 = zext i8 %212 to i64
+ %214 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %215 = atomicrmw nand i64* %214, i64 %213 monotonic
+ %216 = xor i64 %215, -1
+ %217 = and i64 %216, %213
+ store i64 %217, i64* @sl, align 8
+ %218 = load i8* @uc, align 1
+ %219 = zext i8 %218 to i64
+ %220 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %221 = atomicrmw nand i64* %220, i64 %219 monotonic
+ %222 = xor i64 %221, -1
+ %223 = and i64 %222, %219
+ store i64 %223, i64* @ul, align 8
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
define void @test_compare_and_swap() nounwind {
entry:
- load i8* @uc, align 1 ; <i8>:0 [#uses=1]
- load i8* @sc, align 1 ; <i8>:1 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @sc, i8 %0, i8 %1 ) ; <i8>:2 [#uses=1]
- store i8 %2, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:3 [#uses=1]
- load i8* @sc, align 1 ; <i8>:4 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @uc, i8 %3, i8 %4 ) ; <i8>:5 [#uses=1]
- store i8 %5, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:6 [#uses=1]
- zext i8 %6 to i16 ; <i16>:7 [#uses=1]
- load i8* @sc, align 1 ; <i8>:8 [#uses=1]
- sext i8 %8 to i16 ; <i16>:9 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:10 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %10, i16 %7, i16 %9 ) ; <i16>:11 [#uses=1]
- store i16 %11, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:12 [#uses=1]
- zext i8 %12 to i16 ; <i16>:13 [#uses=1]
- load i8* @sc, align 1 ; <i8>:14 [#uses=1]
- sext i8 %14 to i16 ; <i16>:15 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:16 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %16, i16 %13, i16 %15 ) ; <i16>:17 [#uses=1]
- store i16 %17, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:18 [#uses=1]
- zext i8 %18 to i32 ; <i32>:19 [#uses=1]
- load i8* @sc, align 1 ; <i8>:20 [#uses=1]
- sext i8 %20 to i32 ; <i32>:21 [#uses=1]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:22 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %22, i32 %19, i32 %21 ) ; <i32>:23 [#uses=1]
- store i32 %23, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:24 [#uses=1]
- zext i8 %24 to i32 ; <i32>:25 [#uses=1]
- load i8* @sc, align 1 ; <i8>:26 [#uses=1]
- sext i8 %26 to i32 ; <i32>:27 [#uses=1]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:28 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %28, i32 %25, i32 %27 ) ; <i32>:29 [#uses=1]
- store i32 %29, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:30 [#uses=1]
- zext i8 %30 to i64 ; <i64>:31 [#uses=1]
- load i8* @sc, align 1 ; <i8>:32 [#uses=1]
- sext i8 %32 to i64 ; <i64>:33 [#uses=1]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:34 [#uses=1]
- call i64 @llvm.atomic.cmp.swap.i64.p0i64( i64* %34, i64 %31, i64 %33 ) ; <i64>:35 [#uses=1]
- store i64 %35, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:36 [#uses=1]
- zext i8 %36 to i64 ; <i64>:37 [#uses=1]
- load i8* @sc, align 1 ; <i8>:38 [#uses=1]
- sext i8 %38 to i64 ; <i64>:39 [#uses=1]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:40 [#uses=1]
- call i64 @llvm.atomic.cmp.swap.i64.p0i64( i64* %40, i64 %37, i64 %39 ) ; <i64>:41 [#uses=1]
- store i64 %41, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:42 [#uses=2]
- load i8* @sc, align 1 ; <i8>:43 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @sc, i8 %42, i8 %43 ) ; <i8>:44 [#uses=1]
- icmp eq i8 %44, %42 ; <i1>:45 [#uses=1]
- zext i1 %45 to i8 ; <i8>:46 [#uses=1]
- zext i8 %46 to i32 ; <i32>:47 [#uses=1]
- store i32 %47, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:48 [#uses=2]
- load i8* @sc, align 1 ; <i8>:49 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @uc, i8 %48, i8 %49 ) ; <i8>:50 [#uses=1]
- icmp eq i8 %50, %48 ; <i1>:51 [#uses=1]
- zext i1 %51 to i8 ; <i8>:52 [#uses=1]
- zext i8 %52 to i32 ; <i32>:53 [#uses=1]
- store i32 %53, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:54 [#uses=1]
- zext i8 %54 to i16 ; <i16>:55 [#uses=2]
- load i8* @sc, align 1 ; <i8>:56 [#uses=1]
- sext i8 %56 to i16 ; <i16>:57 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:58 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %58, i16 %55, i16 %57 ) ; <i16>:59 [#uses=1]
- icmp eq i16 %59, %55 ; <i1>:60 [#uses=1]
- zext i1 %60 to i8 ; <i8>:61 [#uses=1]
- zext i8 %61 to i32 ; <i32>:62 [#uses=1]
- store i32 %62, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:63 [#uses=1]
- zext i8 %63 to i16 ; <i16>:64 [#uses=2]
- load i8* @sc, align 1 ; <i8>:65 [#uses=1]
- sext i8 %65 to i16 ; <i16>:66 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:67 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %67, i16 %64, i16 %66 ) ; <i16>:68 [#uses=1]
- icmp eq i16 %68, %64 ; <i1>:69 [#uses=1]
- zext i1 %69 to i8 ; <i8>:70 [#uses=1]
- zext i8 %70 to i32 ; <i32>:71 [#uses=1]
- store i32 %71, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:72 [#uses=1]
- zext i8 %72 to i32 ; <i32>:73 [#uses=2]
- load i8* @sc, align 1 ; <i8>:74 [#uses=1]
- sext i8 %74 to i32 ; <i32>:75 [#uses=1]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:76 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %76, i32 %73, i32 %75 ) ; <i32>:77 [#uses=1]
- icmp eq i32 %77, %73 ; <i1>:78 [#uses=1]
- zext i1 %78 to i8 ; <i8>:79 [#uses=1]
- zext i8 %79 to i32 ; <i32>:80 [#uses=1]
- store i32 %80, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:81 [#uses=1]
- zext i8 %81 to i32 ; <i32>:82 [#uses=2]
- load i8* @sc, align 1 ; <i8>:83 [#uses=1]
- sext i8 %83 to i32 ; <i32>:84 [#uses=1]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:85 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %85, i32 %82, i32 %84 ) ; <i32>:86 [#uses=1]
- icmp eq i32 %86, %82 ; <i1>:87 [#uses=1]
- zext i1 %87 to i8 ; <i8>:88 [#uses=1]
- zext i8 %88 to i32 ; <i32>:89 [#uses=1]
- store i32 %89, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:90 [#uses=1]
- zext i8 %90 to i64 ; <i64>:91 [#uses=2]
- load i8* @sc, align 1 ; <i8>:92 [#uses=1]
- sext i8 %92 to i64 ; <i64>:93 [#uses=1]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:94 [#uses=1]
- call i64 @llvm.atomic.cmp.swap.i64.p0i64( i64* %94, i64 %91, i64 %93 ) ; <i64>:95 [#uses=1]
- icmp eq i64 %95, %91 ; <i1>:96 [#uses=1]
- zext i1 %96 to i8 ; <i8>:97 [#uses=1]
- zext i8 %97 to i32 ; <i32>:98 [#uses=1]
- store i32 %98, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:99 [#uses=1]
- zext i8 %99 to i64 ; <i64>:100 [#uses=2]
- load i8* @sc, align 1 ; <i8>:101 [#uses=1]
- sext i8 %101 to i64 ; <i64>:102 [#uses=1]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:103 [#uses=1]
- call i64 @llvm.atomic.cmp.swap.i64.p0i64( i64* %103, i64 %100, i64 %102 ) ; <i64>:104 [#uses=1]
- icmp eq i64 %104, %100 ; <i1>:105 [#uses=1]
- zext i1 %105 to i8 ; <i8>:106 [#uses=1]
- zext i8 %106 to i32 ; <i32>:107 [#uses=1]
- store i32 %107, i32* @ui, align 4
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = load i8* @uc, align 1
+ %1 = load i8* @sc, align 1
+ %2 = cmpxchg i8* @sc, i8 %0, i8 %1 monotonic
+ store i8 %2, i8* @sc, align 1
+ %3 = load i8* @uc, align 1
+ %4 = load i8* @sc, align 1
+ %5 = cmpxchg i8* @uc, i8 %3, i8 %4 monotonic
+ store i8 %5, i8* @uc, align 1
+ %6 = load i8* @uc, align 1
+ %7 = zext i8 %6 to i16
+ %8 = load i8* @sc, align 1
+ %9 = sext i8 %8 to i16
+ %10 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %11 = cmpxchg i16* %10, i16 %7, i16 %9 monotonic
+ store i16 %11, i16* @ss, align 2
+ %12 = load i8* @uc, align 1
+ %13 = zext i8 %12 to i16
+ %14 = load i8* @sc, align 1
+ %15 = sext i8 %14 to i16
+ %16 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %17 = cmpxchg i16* %16, i16 %13, i16 %15 monotonic
+ store i16 %17, i16* @us, align 2
+ %18 = load i8* @uc, align 1
+ %19 = zext i8 %18 to i32
+ %20 = load i8* @sc, align 1
+ %21 = sext i8 %20 to i32
+ %22 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %23 = cmpxchg i32* %22, i32 %19, i32 %21 monotonic
+ store i32 %23, i32* @si, align 4
+ %24 = load i8* @uc, align 1
+ %25 = zext i8 %24 to i32
+ %26 = load i8* @sc, align 1
+ %27 = sext i8 %26 to i32
+ %28 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %29 = cmpxchg i32* %28, i32 %25, i32 %27 monotonic
+ store i32 %29, i32* @ui, align 4
+ %30 = load i8* @uc, align 1
+ %31 = zext i8 %30 to i64
+ %32 = load i8* @sc, align 1
+ %33 = sext i8 %32 to i64
+ %34 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %35 = cmpxchg i64* %34, i64 %31, i64 %33 monotonic
+ store i64 %35, i64* @sl, align 8
+ %36 = load i8* @uc, align 1
+ %37 = zext i8 %36 to i64
+ %38 = load i8* @sc, align 1
+ %39 = sext i8 %38 to i64
+ %40 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %41 = cmpxchg i64* %40, i64 %37, i64 %39 monotonic
+ store i64 %41, i64* @ul, align 8
+ %42 = load i8* @uc, align 1
+ %43 = load i8* @sc, align 1
+ %44 = cmpxchg i8* @sc, i8 %42, i8 %43 monotonic
+ %45 = icmp eq i8 %44, %42
+ %46 = zext i1 %45 to i8
+ %47 = zext i8 %46 to i32
+ store i32 %47, i32* @ui, align 4
+ %48 = load i8* @uc, align 1
+ %49 = load i8* @sc, align 1
+ %50 = cmpxchg i8* @uc, i8 %48, i8 %49 monotonic
+ %51 = icmp eq i8 %50, %48
+ %52 = zext i1 %51 to i8
+ %53 = zext i8 %52 to i32
+ store i32 %53, i32* @ui, align 4
+ %54 = load i8* @uc, align 1
+ %55 = zext i8 %54 to i16
+ %56 = load i8* @sc, align 1
+ %57 = sext i8 %56 to i16
+ %58 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %59 = cmpxchg i16* %58, i16 %55, i16 %57 monotonic
+ %60 = icmp eq i16 %59, %55
+ %61 = zext i1 %60 to i8
+ %62 = zext i8 %61 to i32
+ store i32 %62, i32* @ui, align 4
+ %63 = load i8* @uc, align 1
+ %64 = zext i8 %63 to i16
+ %65 = load i8* @sc, align 1
+ %66 = sext i8 %65 to i16
+ %67 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %68 = cmpxchg i16* %67, i16 %64, i16 %66 monotonic
+ %69 = icmp eq i16 %68, %64
+ %70 = zext i1 %69 to i8
+ %71 = zext i8 %70 to i32
+ store i32 %71, i32* @ui, align 4
+ %72 = load i8* @uc, align 1
+ %73 = zext i8 %72 to i32
+ %74 = load i8* @sc, align 1
+ %75 = sext i8 %74 to i32
+ %76 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %77 = cmpxchg i32* %76, i32 %73, i32 %75 monotonic
+ %78 = icmp eq i32 %77, %73
+ %79 = zext i1 %78 to i8
+ %80 = zext i8 %79 to i32
+ store i32 %80, i32* @ui, align 4
+ %81 = load i8* @uc, align 1
+ %82 = zext i8 %81 to i32
+ %83 = load i8* @sc, align 1
+ %84 = sext i8 %83 to i32
+ %85 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %86 = cmpxchg i32* %85, i32 %82, i32 %84 monotonic
+ %87 = icmp eq i32 %86, %82
+ %88 = zext i1 %87 to i8
+ %89 = zext i8 %88 to i32
+ store i32 %89, i32* @ui, align 4
+ %90 = load i8* @uc, align 1
+ %91 = zext i8 %90 to i64
+ %92 = load i8* @sc, align 1
+ %93 = sext i8 %92 to i64
+ %94 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %95 = cmpxchg i64* %94, i64 %91, i64 %93 monotonic
+ %96 = icmp eq i64 %95, %91
+ %97 = zext i1 %96 to i8
+ %98 = zext i8 %97 to i32
+ store i32 %98, i32* @ui, align 4
+ %99 = load i8* @uc, align 1
+ %100 = zext i8 %99 to i64
+ %101 = load i8* @sc, align 1
+ %102 = sext i8 %101 to i64
+ %103 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %104 = cmpxchg i64* %103, i64 %100, i64 %102 monotonic
+ %105 = icmp eq i64 %104, %100
+ %106 = zext i1 %105 to i8
+ %107 = zext i8 %106 to i32
+ store i32 %107, i32* @ui, align 4
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
-declare i8 @llvm.atomic.cmp.swap.i8.p0i8(i8*, i8, i8) nounwind
-
-declare i16 @llvm.atomic.cmp.swap.i16.p0i16(i16*, i16, i16) nounwind
-
-declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32*, i32, i32) nounwind
-
-declare i64 @llvm.atomic.cmp.swap.i64.p0i64(i64*, i64, i64) nounwind
-
define void @test_lock() nounwind {
entry:
- call i8 @llvm.atomic.swap.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:0 [#uses=1]
- store i8 %0, i8* @sc, align 1
- call i8 @llvm.atomic.swap.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:1 [#uses=1]
- store i8 %1, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.swap.i16.p0i16( i16* %2, i16 1 ) ; <i16>:3 [#uses=1]
- store i16 %3, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.swap.i16.p0i16( i16* %4, i16 1 ) ; <i16>:5 [#uses=1]
- store i16 %5, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %6, i32 1 ) ; <i32>:7 [#uses=1]
- store i32 %7, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %8, i32 1 ) ; <i32>:9 [#uses=1]
- store i32 %9, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:10 [#uses=1]
- call i64 @llvm.atomic.swap.i64.p0i64( i64* %10, i64 1 ) ; <i64>:11 [#uses=1]
- store i64 %11, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:12 [#uses=1]
- call i64 @llvm.atomic.swap.i64.p0i64( i64* %12, i64 1 ) ; <i64>:13 [#uses=1]
- store i64 %13, i64* @ul, align 8
- call void @llvm.memory.barrier( i1 true, i1 true, i1 true, i1 true, i1 false )
- volatile store i8 0, i8* @sc, align 1
- volatile store i8 0, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:14 [#uses=1]
- volatile store i16 0, i16* %14, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:15 [#uses=1]
- volatile store i16 0, i16* %15, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:16 [#uses=1]
- volatile store i32 0, i32* %16, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:17 [#uses=1]
- volatile store i32 0, i32* %17, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:18 [#uses=1]
- volatile store i64 0, i64* %18, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:19 [#uses=1]
- volatile store i64 0, i64* %19, align 8
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:20 [#uses=1]
- volatile store i64 0, i64* %20, align 8
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:21 [#uses=1]
- volatile store i64 0, i64* %21, align 8
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = atomicrmw xchg i8* @sc, i8 1 monotonic
+ store i8 %0, i8* @sc, align 1
+ %1 = atomicrmw xchg i8* @uc, i8 1 monotonic
+ store i8 %1, i8* @uc, align 1
+ %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %3 = atomicrmw xchg i16* %2, i16 1 monotonic
+ store i16 %3, i16* @ss, align 2
+ %4 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %5 = atomicrmw xchg i16* %4, i16 1 monotonic
+ store i16 %5, i16* @us, align 2
+ %6 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %7 = atomicrmw xchg i32* %6, i32 1 monotonic
+ store i32 %7, i32* @si, align 4
+ %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %9 = atomicrmw xchg i32* %8, i32 1 monotonic
+ store i32 %9, i32* @ui, align 4
+ %10 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %11 = atomicrmw xchg i64* %10, i64 1 monotonic
+ store i64 %11, i64* @sl, align 8
+ %12 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %13 = atomicrmw xchg i64* %12, i64 1 monotonic
+ store i64 %13, i64* @ul, align 8
+ fence seq_cst
+ store volatile i8 0, i8* @sc, align 1
+ store volatile i8 0, i8* @uc, align 1
+ %14 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ store volatile i16 0, i16* %14, align 2
+ %15 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ store volatile i16 0, i16* %15, align 2
+ %16 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ store volatile i32 0, i32* %16, align 4
+ %17 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ store volatile i32 0, i32* %17, align 4
+ %18 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ store volatile i64 0, i64* %18, align 8
+ %19 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ store volatile i64 0, i64* %19, align 8
+ %20 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ store volatile i64 0, i64* %20, align 8
+ %21 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ store volatile i64 0, i64* %21, align 8
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
-
-declare i8 @llvm.atomic.swap.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.swap.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.swap.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.swap.i64.p0i64(i64*, i64) nounwind
-
-declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
diff --git a/test/CodeGen/PowerPC/atomic-1.ll b/test/CodeGen/PowerPC/atomic-1.ll
index a2cf170..cbfa4094 100644
--- a/test/CodeGen/PowerPC/atomic-1.ll
+++ b/test/CodeGen/PowerPC/atomic-1.ll
@@ -1,23 +1,26 @@
-; RUN: llc < %s -march=ppc32 | grep lwarx | count 3
-; RUN: llc < %s -march=ppc32 | grep stwcx. | count 4
+; RUN: llc < %s -march=ppc32 | FileCheck %s
define i32 @exchange_and_add(i32* %mem, i32 %val) nounwind {
- %tmp = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %mem, i32 %val)
+; CHECK: exchange_and_add:
+; CHECK: lwarx
+ %tmp = atomicrmw add i32* %mem, i32 %val monotonic
+; CHECK: stwcx.
ret i32 %tmp
}
define i32 @exchange_and_cmp(i32* %mem) nounwind {
- %tmp = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %mem, i32 0, i32 1)
+; CHECK: exchange_and_cmp:
+; CHECK: lwarx
+ %tmp = cmpxchg i32* %mem, i32 0, i32 1 monotonic
+; CHECK: stwcx.
+; CHECK: stwcx.
ret i32 %tmp
}
define i32 @exchange(i32* %mem, i32 %val) nounwind {
- %tmp = call i32 @llvm.atomic.swap.i32.p0i32(i32* %mem, i32 1)
+; CHECK: exchange:
+; CHECK: lwarx
+ %tmp = atomicrmw xchg i32* %mem, i32 1 monotonic
+; CHECK: stwcx.
ret i32 %tmp
}
-
-declare i32 @llvm.atomic.load.add.i32.p0i32(i32* nocapture, i32) nounwind
-
-declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* nocapture, i32, i32) nounwind
-
-declare i32 @llvm.atomic.swap.i32.p0i32(i32* nocapture, i32) nounwind
diff --git a/test/CodeGen/PowerPC/atomic-2.ll b/test/CodeGen/PowerPC/atomic-2.ll
index 0fa2a29..a427379 100644
--- a/test/CodeGen/PowerPC/atomic-2.ll
+++ b/test/CodeGen/PowerPC/atomic-2.ll
@@ -1,23 +1,26 @@
-; RUN: llc < %s -march=ppc64 | grep ldarx | count 3
-; RUN: llc < %s -march=ppc64 | grep stdcx. | count 4
+; RUN: llc < %s -march=ppc64 | FileCheck %s
define i64 @exchange_and_add(i64* %mem, i64 %val) nounwind {
- %tmp = call i64 @llvm.atomic.load.add.i64.p0i64(i64* %mem, i64 %val)
+; CHECK: exchange_and_add:
+; CHECK: ldarx
+ %tmp = atomicrmw add i64* %mem, i64 %val monotonic
+; CHECK: stdcx.
ret i64 %tmp
}
define i64 @exchange_and_cmp(i64* %mem) nounwind {
- %tmp = call i64 @llvm.atomic.cmp.swap.i64.p0i64(i64* %mem, i64 0, i64 1)
+; CHECK: exchange_and_cmp:
+; CHECK: ldarx
+ %tmp = cmpxchg i64* %mem, i64 0, i64 1 monotonic
+; CHECK: stdcx.
+; CHECK: stdcx.
ret i64 %tmp
}
define i64 @exchange(i64* %mem, i64 %val) nounwind {
- %tmp = call i64 @llvm.atomic.swap.i64.p0i64(i64* %mem, i64 1)
+; CHECK: exchange:
+; CHECK: ldarx
+ %tmp = atomicrmw xchg i64* %mem, i64 1 monotonic
+; CHECK: stdcx.
ret i64 %tmp
}
-
-declare i64 @llvm.atomic.load.add.i64.p0i64(i64* nocapture, i64) nounwind
-
-declare i64 @llvm.atomic.cmp.swap.i64.p0i64(i64* nocapture, i64, i64) nounwind
-
-declare i64 @llvm.atomic.swap.i64.p0i64(i64* nocapture, i64) nounwind
diff --git a/test/CodeGen/PowerPC/cr1eq.ll b/test/CodeGen/PowerPC/cr1eq.ll
new file mode 100644
index 0000000..fb9c969
--- /dev/null
+++ b/test/CodeGen/PowerPC/cr1eq.ll
@@ -0,0 +1,18 @@
+; RUN: llc < %s | FileCheck %s
+; ModuleID = 'test.c'
+target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32"
+target triple = "powerpc-unknown-freebsd"
+
+@.str = private unnamed_addr constant [4 x i8] c"%i\0A\00", align 1
+@.str1 = private unnamed_addr constant [4 x i8] c"%f\0A\00", align 1
+
+define void @foo() nounwind {
+entry:
+; CHECK: crxor 6, 6, 6
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 1)
+; CHECK: creqv 6, 6, 6
+ %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str1, i32 0, i32 0), double 1.100000e+00)
+ ret void
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/test/CodeGen/PowerPC/trampoline.ll b/test/CodeGen/PowerPC/trampoline.ll
index bc05bb1..91b2011 100644
--- a/test/CodeGen/PowerPC/trampoline.ll
+++ b/test/CodeGen/PowerPC/trampoline.ll
@@ -67,7 +67,8 @@ entry:
store %struct.NSBitmapImageRep* %4, %struct.NSBitmapImageRep** %3, align 4
%TRAMP.91 = bitcast %struct.__builtin_trampoline* %TRAMP.9 to i8* ; <i8*> [#uses=1]
%FRAME.72 = bitcast %"struct.FRAME.-[NSBitmapImageRep copyWithZone:]"* %FRAME.7 to i8* ; <i8*> [#uses=1]
- %tramp = call i8* @llvm.init.trampoline(i8* %TRAMP.91, i8* bitcast (void (%"struct.FRAME.-[NSBitmapImageRep copyWithZone:]"*, %struct.__block_1*, %struct.CGImage*)* @__helper_1.1632 to i8*), i8* %FRAME.72) ; <i8*> [#uses=1]
+ call void @llvm.init.trampoline(i8* %TRAMP.91, i8* bitcast (void (%"struct.FRAME.-[NSBitmapImageRep copyWithZone:]"*, %struct.__block_1*, %struct.CGImage*)* @__helper_1.1632 to i8*), i8* %FRAME.72) ; <i8*> [#uses=1]
+ %tramp = call i8* @llvm.adjust.trampoline(i8* %TRAMP.91)
store i8* %tramp, i8** %0, align 4
%5 = getelementptr %"struct.FRAME.-[NSBitmapImageRep copyWithZone:]"* %FRAME.7, i32 0, i32 1 ; <void (%struct.__block_1*, %struct.CGImage*)**> [#uses=1]
%6 = load i8** %0, align 4 ; <i8*> [#uses=1]
@@ -113,7 +114,8 @@ return: ; preds = %entry
ret %struct.objc_object* %retval5
}
-declare i8* @llvm.init.trampoline(i8*, i8*, i8*) nounwind
+declare void @llvm.init.trampoline(i8*, i8*, i8*) nounwind
+declare i8* @llvm.adjust.trampoline(i8*) nounwind
define internal void @__helper_1.1632(%"struct.FRAME.-[NSBitmapImageRep copyWithZone:]"* nest %CHAIN.8, %struct.__block_1* %_self, %struct.CGImage* %cgImage) nounwind {
entry:
diff --git a/test/CodeGen/Thumb/2011-05-11-DAGLegalizer.ll b/test/CodeGen/Thumb/2011-05-11-DAGLegalizer.ll
index ed55bb5..2890c22 100644
--- a/test/CodeGen/Thumb/2011-05-11-DAGLegalizer.ll
+++ b/test/CodeGen/Thumb/2011-05-11-DAGLegalizer.ll
@@ -1,7 +1,11 @@
-; RUN: llc -mtriple=thumbv6-apple-darwin < %s
+; DISABLED: llc -mtriple=thumbv6-apple-darwin < %s
+; RUN: false
; rdar://problem/9416774
; ModuleID = 'reduced.ll'
+; byval is currently unsupported.
+; XFAIL: *
+
target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
target triple = "thumbv7-apple-ios"
diff --git a/test/CodeGen/Thumb/barrier.ll b/test/CodeGen/Thumb/barrier.ll
index d39b50f..50d138f 100644
--- a/test/CodeGen/Thumb/barrier.ll
+++ b/test/CodeGen/Thumb/barrier.ll
@@ -2,24 +2,12 @@
; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mattr=-db | FileCheck %s -check-prefix=V6
; RUN: llc < %s -march=thumb -mcpu=cortex-m0 | FileCheck %s -check-prefix=V6M
-declare void @llvm.memory.barrier(i1 , i1 , i1 , i1 , i1)
-
define void @t1() {
; V6: t1:
; V6: blx {{_*}}sync_synchronize
; V6M: t1:
-; V6M: dmb st
- call void @llvm.memory.barrier(i1 false, i1 false, i1 false, i1 true, i1 true)
- ret void
-}
-
-define void @t2() {
-; V6: t2:
-; V6: blx {{_*}}sync_synchronize
-
-; V6M: t2:
; V6M: dmb ish
- call void @llvm.memory.barrier(i1 true, i1 false, i1 false, i1 true, i1 false)
+ fence seq_cst
ret void
}
diff --git a/test/CodeGen/Thumb/iabs.ll b/test/CodeGen/Thumb/iabs.ll
index d7cdcd8..d03b5b2 100644
--- a/test/CodeGen/Thumb/iabs.ll
+++ b/test/CodeGen/Thumb/iabs.ll
@@ -3,9 +3,9 @@
;; Integer absolute value, should produce something as good as:
;; Thumb:
-;; asr r2, r0, #31
-;; add r0, r0, r2
-;; eor r0, r2
+;; movs r0, r0
+;; bpl
+;; rsb r0, r0, #0 (with opitmization, bpl + rsb is if-converted into rsbmi)
;; bx lr
define i32 @test(i32 %a) {
@@ -13,5 +13,10 @@ define i32 @test(i32 %a) {
%b = icmp sgt i32 %a, -1
%abs = select i1 %b, i32 %a, i32 %tmp1neg
ret i32 %abs
+; CHECK: movs r0, r0
+; CHECK: bpl
+; CHECK: rsb r0, r0, #0
+; CHECK: bx lr
}
+
diff --git a/test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll b/test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll
index 8ca001c..034a28f 100644
--- a/test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll
+++ b/test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll
@@ -6,8 +6,8 @@ entry:
; -- The loop following the load should only use a single add-literation
; instruction.
; CHECK: ldr.64
-; CHECK: adds r{{[0-9]+}}, #1
-; CHECK-NOT: adds r{{[0-9]+}}, #1
+; CHECK: adds r{{[0-9]+.*}}#1
+; CHECK-NOT: adds
; CHECK: subsections_via_symbols
diff --git a/test/CodeGen/Thumb2/2010-06-21-TailMergeBug.ll b/test/CodeGen/Thumb2/2010-06-21-TailMergeBug.ll
index f91e1c9..244d0bb 100644
--- a/test/CodeGen/Thumb2/2010-06-21-TailMergeBug.ll
+++ b/test/CodeGen/Thumb2/2010-06-21-TailMergeBug.ll
@@ -32,15 +32,15 @@
define fastcc i32 @parse_percent_token() nounwind {
entry:
-; CHECK: ittt eq
-; CHECK: ittt eq
-; CHECK: ittt eq
-; CHECK: ittt eq
-; CHECK: ittt eq
-; CHECK: moveq r0
-; CHECK-NOT: LBB0_
-; CHECK: ldreq
-; CHECK: popeq
+; CHECK: pop
+; CHECK: pop
+; CHECK: pop
+; CHECK: pop
+; CHECK: pop
+; CHECK: pop
+; CHECK: pop
+; Do not convert into single stream code. BranchProbability Analysis assumes
+; that branches which goes to "ret" intruction have lower probabilities.
switch i32 undef, label %bb7 [
i32 37, label %bb43
i32 48, label %bb5
diff --git a/test/CodeGen/Thumb2/machine-licm.ll b/test/CodeGen/Thumb2/machine-licm.ll
index b199d69..46937fc 100644
--- a/test/CodeGen/Thumb2/machine-licm.ll
+++ b/test/CodeGen/Thumb2/machine-licm.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a8 -disable-fp-elim | FileCheck %s
+; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a8 -relocation-model=dynamic-no-pic -disable-fp-elim | FileCheck %s
; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a8 -relocation-model=pic -disable-fp-elim | FileCheck %s --check-prefix=PIC
; rdar://7353541
; rdar://7354376
diff --git a/test/CodeGen/Thumb2/thumb2-barrier.ll b/test/CodeGen/Thumb2/thumb2-barrier.ll
deleted file mode 100644
index 93ae7c4..0000000
--- a/test/CodeGen/Thumb2/thumb2-barrier.ll
+++ /dev/null
@@ -1,31 +0,0 @@
-; RUN: llc < %s -march=thumb -mcpu=cortex-a8 | FileCheck %s
-
-declare void @llvm.memory.barrier(i1 , i1 , i1 , i1 , i1)
-
-define void @t_st() {
-; CHECK: t_st:
-; CHECK: dmb st
- call void @llvm.memory.barrier(i1 false, i1 false, i1 false, i1 true, i1 true)
- ret void
-}
-
-define void @t_sy() {
-; CHECK: t_sy:
-; CHECK: dmb sy
- call void @llvm.memory.barrier(i1 true, i1 false, i1 false, i1 true, i1 true)
- ret void
-}
-
-define void @t_ishst() {
-; CHECK: t_ishst:
-; CHECK: dmb ishst
- call void @llvm.memory.barrier(i1 false, i1 false, i1 false, i1 true, i1 false)
- ret void
-}
-
-define void @t_ish() {
-; CHECK: t_ish:
-; CHECK: dmb ish
- call void @llvm.memory.barrier(i1 true, i1 false, i1 false, i1 true, i1 false)
- ret void
-}
diff --git a/test/CodeGen/Thumb2/thumb2-bcc.ll b/test/CodeGen/Thumb2/thumb2-bcc.ll
index 70febc06..4a2d600 100644
--- a/test/CodeGen/Thumb2/thumb2-bcc.ll
+++ b/test/CodeGen/Thumb2/thumb2-bcc.ll
@@ -1,5 +1,4 @@
; RUN: llc < %s -march=thumb -mattr=+thumb2 | FileCheck %s
-; RUN: llc < %s -march=thumb -mattr=+thumb2 | not grep it
; If-conversion defeats the purpose of this test, which is to check CBZ
; generation, so use memory barrier instruction to make sure it doesn't
; happen and we get actual branches.
@@ -7,20 +6,18 @@
define i32 @t1(i32 %a, i32 %b, i32 %c) {
; CHECK: t1:
; CHECK: cbz
- %tmp2 = icmp eq i32 %a, 0
- br i1 %tmp2, label %cond_false, label %cond_true
+ %tmp2 = icmp eq i32 %a, 0
+ br i1 %tmp2, label %cond_false, label %cond_true
cond_true:
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
- %tmp5 = add i32 %b, 1
- %tmp6 = and i32 %tmp5, %c
- ret i32 %tmp6
+ fence seq_cst
+ %tmp5 = add i32 %b, 1
+ %tmp6 = and i32 %tmp5, %c
+ ret i32 %tmp6
cond_false:
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
- %tmp7 = add i32 %b, -1
- %tmp8 = xor i32 %tmp7, %c
- ret i32 %tmp8
+ fence seq_cst
+ %tmp7 = add i32 %b, -1
+ %tmp8 = xor i32 %tmp7, %c
+ ret i32 %tmp8
}
-
-declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
diff --git a/test/CodeGen/Thumb2/thumb2-branch.ll b/test/CodeGen/Thumb2/thumb2-branch.ll
index 4d9eda0..27d8e8f 100644
--- a/test/CodeGen/Thumb2/thumb2-branch.ll
+++ b/test/CodeGen/Thumb2/thumb2-branch.ll
@@ -11,12 +11,12 @@ entry:
br i1 %tmp, label %cond_true, label %return
cond_true: ; preds = %entry
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ fence seq_cst
store i32 0, i32* %v
ret i32 0
return: ; preds = %entry
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ fence seq_cst
ret i32 1
}
@@ -28,12 +28,12 @@ entry:
br i1 %tmp, label %cond_true, label %return
cond_true: ; preds = %entry
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ fence seq_cst
store i32 0, i32* %v
ret i32 0
return: ; preds = %entry
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ fence seq_cst
ret i32 1
}
@@ -45,12 +45,12 @@ entry:
br i1 %tmp, label %cond_true, label %return
cond_true: ; preds = %entry
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ fence seq_cst
store i32 0, i32* %v
ret i32 0
return: ; preds = %entry
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ fence seq_cst
ret i32 1
}
@@ -62,13 +62,11 @@ entry:
br i1 %tmp, label %return, label %cond_true
cond_true: ; preds = %entry
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ fence seq_cst
store i32 0, i32* %v
ret i32 0
return: ; preds = %entry
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
+ fence seq_cst
ret i32 1
}
-
-declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
diff --git a/test/CodeGen/Thumb2/thumb2-ifcvt1.ll b/test/CodeGen/Thumb2/thumb2-ifcvt1.ll
index a4035bb..af8fcc6 100644
--- a/test/CodeGen/Thumb2/thumb2-ifcvt1.ll
+++ b/test/CodeGen/Thumb2/thumb2-ifcvt1.ll
@@ -21,13 +21,13 @@ cond_next:
ret i32 %tmp15
}
-; FIXME: Check for # of unconditional branch after adding branch folding post ifcvt.
define i32 @t2(i32 %a, i32 %b) nounwind {
entry:
+; Do not if-convert when branches go to the different loops.
; CHECK: t2:
-; CHECK: ite gt
-; CHECK: subgt
-; CHECK: suble
+; CHECK-NOT: ite gt
+; CHECK-NOT: subgt
+; CHECK-NOT: suble
%tmp1434 = icmp eq i32 %a, %b ; <i1> [#uses=1]
br i1 %tmp1434, label %bb17, label %bb.outer
diff --git a/test/CodeGen/Thumb2/thumb2-ldm.ll b/test/CodeGen/Thumb2/thumb2-ldm.ll
index c5f7e84..4f2b7c1 100644
--- a/test/CodeGen/Thumb2/thumb2-ldm.ll
+++ b/test/CodeGen/Thumb2/thumb2-ldm.ll
@@ -15,7 +15,7 @@ define i32 @t1() {
define i32 @t2() {
; CHECK: t2:
; CHECK: push {r7, lr}
-; CHECK: ldmia
+; CHECK: ldm
; CHECK: pop {r7, pc}
%tmp = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 2) ; <i32> [#uses=1]
%tmp3 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 3) ; <i32> [#uses=1]
diff --git a/test/CodeGen/Thumb2/thumb2-mls.ll b/test/CodeGen/Thumb2/thumb2-mls.ll
index fc9e6ba..24c45c5 100644
--- a/test/CodeGen/Thumb2/thumb2-mls.ll
+++ b/test/CodeGen/Thumb2/thumb2-mls.ll
@@ -15,5 +15,5 @@ define i32 @f2(i32 %a, i32 %b, i32 %c) {
ret i32 %tmp2
}
; CHECK: f2:
-; CHECK: muls r0, r1
+; CHECK: muls r0, r0, r1
diff --git a/test/CodeGen/Thumb2/thumb2-mul.ll b/test/CodeGen/Thumb2/thumb2-mul.ll
index 8d1de55..bb97d97 100644
--- a/test/CodeGen/Thumb2/thumb2-mul.ll
+++ b/test/CodeGen/Thumb2/thumb2-mul.ll
@@ -2,7 +2,7 @@
define i32 @f1(i32 %a, i32 %b, i32 %c) {
; CHECK: f1:
-; CHECK: muls r0, r1
+; CHECK: muls r0, r0, r1
%tmp = mul i32 %a, %b
ret i32 %tmp
}
diff --git a/test/CodeGen/Thumb2/thumb2-sxt-uxt.ll b/test/CodeGen/Thumb2/thumb2-sxt-uxt.ll
new file mode 100644
index 0000000..ab888e6
--- /dev/null
+++ b/test/CodeGen/Thumb2/thumb2-sxt-uxt.ll
@@ -0,0 +1,29 @@
+; RUN: llc < %s -march=thumb -mcpu=cortex-m3 | FileCheck %s
+
+define i32 @test1(i16 zeroext %z) nounwind {
+; CHECK: test1:
+; CHECK: sxth
+ %r = sext i16 %z to i32
+ ret i32 %r
+}
+
+define i32 @test2(i8 zeroext %z) nounwind {
+; CHECK: test2:
+; CHECK: sxtb
+ %r = sext i8 %z to i32
+ ret i32 %r
+}
+
+define i32 @test3(i16 signext %z) nounwind {
+; CHECK: test3:
+; CHECK: uxth
+ %r = zext i16 %z to i32
+ ret i32 %r
+}
+
+define i32 @test4(i8 signext %z) nounwind {
+; CHECK: test4:
+; CHECK: uxtb
+ %r = zext i8 %z to i32
+ ret i32 %r
+}
diff --git a/test/CodeGen/X86/2006-05-11-InstrSched.ll b/test/CodeGen/X86/2006-05-11-InstrSched.ll
index 56d6aa9..a871ea1 100644
--- a/test/CodeGen/X86/2006-05-11-InstrSched.ll
+++ b/test/CodeGen/X86/2006-05-11-InstrSched.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -march=x86 -mattr=+sse2 -stats -realign-stack=0 |&\
+; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu -mattr=+sse2 -stats -realign-stack=0 |&\
; RUN: grep {asm-printer} | grep 34
target datalayout = "e-p:32:32"
diff --git a/test/CodeGen/X86/2006-07-19-ATTAsm.ll b/test/CodeGen/X86/2006-07-19-ATTAsm.ll
deleted file mode 100644
index c8fd10f..0000000
--- a/test/CodeGen/X86/2006-07-19-ATTAsm.ll
+++ /dev/null
@@ -1,49 +0,0 @@
-; RUN: llc < %s -march=x86 -x86-asm-syntax=att
-; PR834
-; END.
-
-target datalayout = "e-p:32:32"
-target triple = "i386-unknown-freebsd6.1"
- %llvm.dbg.anchor.type = type { i32, i32 }
- %llvm.dbg.basictype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, i32 }
- %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8* }
- %llvm.dbg.global_variable.type = type { i32, { }*, { }*, i8*, i8 *, i8*, { }*, i32, { }*, i1, i1, { }* }
-@x = global i32 0 ; <i32*> [#uses=1]
-@llvm.dbg.global_variable = internal constant %llvm.dbg.global_variable.type {
- i32 327732,
- { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.global_variables to { }*),
- { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*),
- i8* getelementptr ([2 x i8]* @str, i64 0, i64 0),
- i8* getelementptr ([2 x i8]* @str, i64 0, i64 0),
- i8* null,
- { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*),
- i32 1,
- { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*),
- i1 false,
- i1 true,
- { }* bitcast (i32* @x to { }*) }, section "llvm.metadata" ; <%llvm.dbg.global_variable.type*> [#uses=0]
-@llvm.dbg.global_variables = linkonce constant %llvm.dbg.anchor.type { i32 327680, i32 52 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1]
-@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type {
- i32 327697,
- { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to { }*),
- i32 4,
- i8* getelementptr ([10 x i8]* @str1, i64 0, i64 0),
- i8* getelementptr ([32 x i8]* @str2, i64 0, i64 0),
- i8* getelementptr ([45 x i8]* @str3, i64 0, i64 0) }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1]
-@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 327680, i32 17 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1]
-@str1 = internal constant [10 x i8] c"testb.cpp\00", section "llvm.metadata" ; <[10 x i8]*> [#uses=1]
-@str2 = internal constant [32 x i8] c"/Sources/Projects/DwarfTesting/\00", section "llvm.metadata" ; <[32 x i8]*> [#uses=1]
-@str3 = internal constant [45 x i8] c"4.0.1 LLVM (Apple Computer, Inc. build 5400)\00", section "llvm.metadata" ; <[45 x i8]*> [#uses=1]
-@str = internal constant [2 x i8] c"x\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1]
-@llvm.dbg.basictype = internal constant %llvm.dbg.basictype.type {
- i32 327716,
- { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*),
- i8* getelementptr ([4 x i8]* @str4, i64 0, i64 0),
- { }* null,
- i32 0,
- i64 32,
- i64 32,
- i64 0,
- i32 0,
- i32 5 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1]
-@str4 = internal constant [4 x i8] c"int\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1]
diff --git a/test/CodeGen/X86/2007-05-07-InvokeSRet.ll b/test/CodeGen/X86/2007-05-07-InvokeSRet.ll
index 22e2750..deb3999 100644
--- a/test/CodeGen/X86/2007-05-07-InvokeSRet.ll
+++ b/test/CodeGen/X86/2007-05-07-InvokeSRet.ll
@@ -11,5 +11,9 @@ entry:
to label %return unwind label %return
return: ; preds = %entry, %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret void
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/2008-01-08-SchedulerCrash.ll b/test/CodeGen/X86/2008-01-08-SchedulerCrash.ll
index b040095..266fd7b 100644
--- a/test/CodeGen/X86/2008-01-08-SchedulerCrash.ll
+++ b/test/CodeGen/X86/2008-01-08-SchedulerCrash.ll
@@ -1,4 +1,12 @@
-; RUN: llc < %s -march=x86 | not grep pushf
+; RUN: llc < %s -march=x86 -mattr=+cmov | FileCheck %s
+;
+; Test scheduling a multi-use compare. We should neither spill flags
+; nor clone the compare.
+; CHECK: cmp
+; CHECK-NOT: pushf
+; CHECK: cmov
+; CHECK-NOT: cmp
+; CHECK: cmov
%struct.indexentry = type { i32, i8*, i8*, i8*, i8*, i8* }
diff --git a/test/CodeGen/X86/2008-04-17-CoalescerBug.ll b/test/CodeGen/X86/2008-04-17-CoalescerBug.ll
index 77720aa..859041e 100644
--- a/test/CodeGen/X86/2008-04-17-CoalescerBug.ll
+++ b/test/CodeGen/X86/2008-04-17-CoalescerBug.ll
@@ -151,8 +151,12 @@ bb7819: ; preds = %bb3314
bb7834: ; preds = %bb7806, %invcont5831
br label %bb3261
lpad: ; preds = %bb7806, %bb5968, %invcont5814, %bb440.i8663, %bb155.i8541, %bb5657, %bb3306
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret void
lpad8185: ; preds = %invcont5831
+ %exn8185 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret void
}
@@ -169,3 +173,5 @@ declare %struct.wxStringBase* @_ZN12wxStringBase6appendEmw(%struct.wxStringBase*
declare %struct.wxStringBase* @_ZN12wxStringBaseaSEPKw(%struct.wxStringBase*, i32*)
declare void @_ZN8wxString6FormatEPKwz(%struct.wxString* noalias sret , i32*, ...)
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/2008-05-28-LocalRegAllocBug.ll b/test/CodeGen/X86/2008-05-28-LocalRegAllocBug.ll
index 94c95d4..0d11546 100644
--- a/test/CodeGen/X86/2008-05-28-LocalRegAllocBug.ll
+++ b/test/CodeGen/X86/2008-05-28-LocalRegAllocBug.ll
@@ -23,8 +23,12 @@ tmp12.i.i.i.i.i.noexc65: ; preds = %bb37
unreachable
lpad243: ; preds = %bb37
- %eh_ptr244 = call i8* @llvm.eh.exception( ) ; <i8*> [#uses=1]
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ %eh_ptr244 = extractvalue { i8*, i32 } %exn, 0
store i32 (...)** getelementptr ([5 x i32 (...)*]* @_ZTVN10Evaluation10GridOutputILi3EEE, i32 0, i32 2), i32 (...)*** null, align 8
%tmp133 = call i8* @__cxa_begin_catch( i8* %eh_ptr244 ) nounwind ; <i8*> [#uses=0]
unreachable
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/2008-08-19-SubAndFetch.ll b/test/CodeGen/X86/2008-08-19-SubAndFetch.ll
index 8475e8d..360ec73 100644
--- a/test/CodeGen/X86/2008-08-19-SubAndFetch.ll
+++ b/test/CodeGen/X86/2008-08-19-SubAndFetch.ll
@@ -7,8 +7,6 @@ entry:
; CHECK: main:
; CHECK: lock
; CHECK: decq
- tail call i64 @llvm.atomic.load.sub.i64.p0i64( i64* @var, i64 1 ) ; <i64>:0 [#uses=0]
+ atomicrmw sub i64* @var, i64 1 monotonic
unreachable
}
-
-declare i64 @llvm.atomic.load.sub.i64.p0i64(i64*, i64) nounwind
diff --git a/test/CodeGen/X86/2008-09-18-inline-asm-2.ll b/test/CodeGen/X86/2008-09-18-inline-asm-2.ll
index dfd165c..511c7b5 100644
--- a/test/CodeGen/X86/2008-09-18-inline-asm-2.ll
+++ b/test/CodeGen/X86/2008-09-18-inline-asm-2.ll
@@ -18,7 +18,7 @@
; CHECK-NOT: [[A3]]
; CHECK: 5th=[[A5:%...]]
; CHECK-NOT: [[A1]]
-; CHECK-NOT; [[A5]]
+; CHECK-NOT: [[A5]]
; CHECK: =4th
; The 6th operand is an 8-bit register, and it mustn't alias the 1st and 5th.
diff --git a/test/CodeGen/X86/2008-10-02-Atomics32-2.ll b/test/CodeGen/X86/2008-10-02-Atomics32-2.ll
deleted file mode 100644
index b48c4ad..0000000
--- a/test/CodeGen/X86/2008-10-02-Atomics32-2.ll
+++ /dev/null
@@ -1,969 +0,0 @@
-; RUN: llc < %s -march=x86 > %t
-;; This version includes 64-bit version of binary operators (in 32-bit mode).
-;; Swap, cmp-and-swap not supported yet in this mode.
-; ModuleID = 'Atomics.c'
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
-target triple = "i386-apple-darwin8"
-@sc = common global i8 0 ; <i8*> [#uses=52]
-@uc = common global i8 0 ; <i8*> [#uses=112]
-@ss = common global i16 0 ; <i16*> [#uses=15]
-@us = common global i16 0 ; <i16*> [#uses=15]
-@si = common global i32 0 ; <i32*> [#uses=15]
-@ui = common global i32 0 ; <i32*> [#uses=23]
-@sl = common global i32 0 ; <i32*> [#uses=15]
-@ul = common global i32 0 ; <i32*> [#uses=15]
-@sll = common global i64 0, align 8 ; <i64*> [#uses=13]
-@ull = common global i64 0, align 8 ; <i64*> [#uses=13]
-
-define void @test_op_ignore() nounwind {
-entry:
- %0 = call i8 @llvm.atomic.load.add.i8.p0i8(i8* @sc, i8 1) ; <i8> [#uses=0]
- %1 = call i8 @llvm.atomic.load.add.i8.p0i8(i8* @uc, i8 1) ; <i8> [#uses=0]
- %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %3 = call i16 @llvm.atomic.load.add.i16.p0i16(i16* %2, i16 1) ; <i16> [#uses=0]
- %4 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %5 = call i16 @llvm.atomic.load.add.i16.p0i16(i16* %4, i16 1) ; <i16> [#uses=0]
- %6 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %7 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %6, i32 1) ; <i32> [#uses=0]
- %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %9 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %8, i32 1) ; <i32> [#uses=0]
- %10 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %11 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %10, i32 1) ; <i32> [#uses=0]
- %12 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %13 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %12, i32 1) ; <i32> [#uses=0]
- %14 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %15 = call i64 @llvm.atomic.load.add.i64.p0i64(i64* %14, i64 1) ; <i64> [#uses=0]
- %16 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %17 = call i64 @llvm.atomic.load.add.i64.p0i64(i64* %16, i64 1) ; <i64> [#uses=0]
- %18 = call i8 @llvm.atomic.load.sub.i8.p0i8(i8* @sc, i8 1) ; <i8> [#uses=0]
- %19 = call i8 @llvm.atomic.load.sub.i8.p0i8(i8* @uc, i8 1) ; <i8> [#uses=0]
- %20 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %21 = call i16 @llvm.atomic.load.sub.i16.p0i16(i16* %20, i16 1) ; <i16> [#uses=0]
- %22 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %23 = call i16 @llvm.atomic.load.sub.i16.p0i16(i16* %22, i16 1) ; <i16> [#uses=0]
- %24 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %25 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %24, i32 1) ; <i32> [#uses=0]
- %26 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %27 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %26, i32 1) ; <i32> [#uses=0]
- %28 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %29 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %28, i32 1) ; <i32> [#uses=0]
- %30 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %31 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %30, i32 1) ; <i32> [#uses=0]
- %32 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %33 = call i64 @llvm.atomic.load.sub.i64.p0i64(i64* %32, i64 1) ; <i64> [#uses=0]
- %34 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %35 = call i64 @llvm.atomic.load.sub.i64.p0i64(i64* %34, i64 1) ; <i64> [#uses=0]
- %36 = call i8 @llvm.atomic.load.or.i8.p0i8(i8* @sc, i8 1) ; <i8> [#uses=0]
- %37 = call i8 @llvm.atomic.load.or.i8.p0i8(i8* @uc, i8 1) ; <i8> [#uses=0]
- %38 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %39 = call i16 @llvm.atomic.load.or.i16.p0i16(i16* %38, i16 1) ; <i16> [#uses=0]
- %40 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %41 = call i16 @llvm.atomic.load.or.i16.p0i16(i16* %40, i16 1) ; <i16> [#uses=0]
- %42 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %43 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %42, i32 1) ; <i32> [#uses=0]
- %44 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %45 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %44, i32 1) ; <i32> [#uses=0]
- %46 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %47 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %46, i32 1) ; <i32> [#uses=0]
- %48 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %49 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %48, i32 1) ; <i32> [#uses=0]
- %50 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %51 = call i64 @llvm.atomic.load.or.i64.p0i64(i64* %50, i64 1) ; <i64> [#uses=0]
- %52 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %53 = call i64 @llvm.atomic.load.or.i64.p0i64(i64* %52, i64 1) ; <i64> [#uses=0]
- %54 = call i8 @llvm.atomic.load.xor.i8.p0i8(i8* @sc, i8 1) ; <i8> [#uses=0]
- %55 = call i8 @llvm.atomic.load.xor.i8.p0i8(i8* @uc, i8 1) ; <i8> [#uses=0]
- %56 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %57 = call i16 @llvm.atomic.load.xor.i16.p0i16(i16* %56, i16 1) ; <i16> [#uses=0]
- %58 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %59 = call i16 @llvm.atomic.load.xor.i16.p0i16(i16* %58, i16 1) ; <i16> [#uses=0]
- %60 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %61 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %60, i32 1) ; <i32> [#uses=0]
- %62 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %63 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %62, i32 1) ; <i32> [#uses=0]
- %64 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %65 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %64, i32 1) ; <i32> [#uses=0]
- %66 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %67 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %66, i32 1) ; <i32> [#uses=0]
- %68 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %69 = call i64 @llvm.atomic.load.xor.i64.p0i64(i64* %68, i64 1) ; <i64> [#uses=0]
- %70 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %71 = call i64 @llvm.atomic.load.xor.i64.p0i64(i64* %70, i64 1) ; <i64> [#uses=0]
- %72 = call i8 @llvm.atomic.load.and.i8.p0i8(i8* @sc, i8 1) ; <i8> [#uses=0]
- %73 = call i8 @llvm.atomic.load.and.i8.p0i8(i8* @uc, i8 1) ; <i8> [#uses=0]
- %74 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %75 = call i16 @llvm.atomic.load.and.i16.p0i16(i16* %74, i16 1) ; <i16> [#uses=0]
- %76 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %77 = call i16 @llvm.atomic.load.and.i16.p0i16(i16* %76, i16 1) ; <i16> [#uses=0]
- %78 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %79 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %78, i32 1) ; <i32> [#uses=0]
- %80 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %81 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %80, i32 1) ; <i32> [#uses=0]
- %82 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %83 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %82, i32 1) ; <i32> [#uses=0]
- %84 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %85 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %84, i32 1) ; <i32> [#uses=0]
- %86 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %87 = call i64 @llvm.atomic.load.and.i64.p0i64(i64* %86, i64 1) ; <i64> [#uses=0]
- %88 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %89 = call i64 @llvm.atomic.load.and.i64.p0i64(i64* %88, i64 1) ; <i64> [#uses=0]
- %90 = call i8 @llvm.atomic.load.nand.i8.p0i8(i8* @sc, i8 1) ; <i8> [#uses=0]
- %91 = call i8 @llvm.atomic.load.nand.i8.p0i8(i8* @uc, i8 1) ; <i8> [#uses=0]
- %92 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %93 = call i16 @llvm.atomic.load.nand.i16.p0i16(i16* %92, i16 1) ; <i16> [#uses=0]
- %94 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %95 = call i16 @llvm.atomic.load.nand.i16.p0i16(i16* %94, i16 1) ; <i16> [#uses=0]
- %96 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %97 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %96, i32 1) ; <i32> [#uses=0]
- %98 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %99 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %98, i32 1) ; <i32> [#uses=0]
- %100 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %101 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %100, i32 1) ; <i32> [#uses=0]
- %102 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %103 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %102, i32 1) ; <i32> [#uses=0]
- %104 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %105 = call i64 @llvm.atomic.load.nand.i64.p0i64(i64* %104, i64 1) ; <i64> [#uses=0]
- %106 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %107 = call i64 @llvm.atomic.load.nand.i64.p0i64(i64* %106, i64 1) ; <i64> [#uses=0]
- br label %return
-
-return: ; preds = %entry
- ret void
-}
-
-declare i8 @llvm.atomic.load.add.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.add.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.add.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.add.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.sub.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.sub.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.sub.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.sub.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.or.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.or.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.or.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.or.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.xor.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.xor.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.xor.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.xor.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.and.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.and.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.and.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.and.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.nand.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.nand.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.nand.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.nand.i64.p0i64(i64*, i64) nounwind
-
-define void @test_fetch_and_op() nounwind {
-entry:
- %0 = call i8 @llvm.atomic.load.add.i8.p0i8(i8* @sc, i8 11) ; <i8> [#uses=1]
- store i8 %0, i8* @sc, align 1
- %1 = call i8 @llvm.atomic.load.add.i8.p0i8(i8* @uc, i8 11) ; <i8> [#uses=1]
- store i8 %1, i8* @uc, align 1
- %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %3 = call i16 @llvm.atomic.load.add.i16.p0i16(i16* %2, i16 11) ; <i16> [#uses=1]
- store i16 %3, i16* @ss, align 2
- %4 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %5 = call i16 @llvm.atomic.load.add.i16.p0i16(i16* %4, i16 11) ; <i16> [#uses=1]
- store i16 %5, i16* @us, align 2
- %6 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %7 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %6, i32 11) ; <i32> [#uses=1]
- store i32 %7, i32* @si, align 4
- %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %9 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %8, i32 11) ; <i32> [#uses=1]
- store i32 %9, i32* @ui, align 4
- %10 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %11 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %10, i32 11) ; <i32> [#uses=1]
- store i32 %11, i32* @sl, align 4
- %12 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %13 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %12, i32 11) ; <i32> [#uses=1]
- store i32 %13, i32* @ul, align 4
- %14 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %15 = call i64 @llvm.atomic.load.add.i64.p0i64(i64* %14, i64 11) ; <i64> [#uses=1]
- store i64 %15, i64* @sll, align 8
- %16 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %17 = call i64 @llvm.atomic.load.add.i64.p0i64(i64* %16, i64 11) ; <i64> [#uses=1]
- store i64 %17, i64* @ull, align 8
- %18 = call i8 @llvm.atomic.load.sub.i8.p0i8(i8* @sc, i8 11) ; <i8> [#uses=1]
- store i8 %18, i8* @sc, align 1
- %19 = call i8 @llvm.atomic.load.sub.i8.p0i8(i8* @uc, i8 11) ; <i8> [#uses=1]
- store i8 %19, i8* @uc, align 1
- %20 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %21 = call i16 @llvm.atomic.load.sub.i16.p0i16(i16* %20, i16 11) ; <i16> [#uses=1]
- store i16 %21, i16* @ss, align 2
- %22 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %23 = call i16 @llvm.atomic.load.sub.i16.p0i16(i16* %22, i16 11) ; <i16> [#uses=1]
- store i16 %23, i16* @us, align 2
- %24 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %25 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %24, i32 11) ; <i32> [#uses=1]
- store i32 %25, i32* @si, align 4
- %26 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %27 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %26, i32 11) ; <i32> [#uses=1]
- store i32 %27, i32* @ui, align 4
- %28 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %29 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %28, i32 11) ; <i32> [#uses=1]
- store i32 %29, i32* @sl, align 4
- %30 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %31 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %30, i32 11) ; <i32> [#uses=1]
- store i32 %31, i32* @ul, align 4
- %32 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %33 = call i64 @llvm.atomic.load.sub.i64.p0i64(i64* %32, i64 11) ; <i64> [#uses=1]
- store i64 %33, i64* @sll, align 8
- %34 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %35 = call i64 @llvm.atomic.load.sub.i64.p0i64(i64* %34, i64 11) ; <i64> [#uses=1]
- store i64 %35, i64* @ull, align 8
- %36 = call i8 @llvm.atomic.load.or.i8.p0i8(i8* @sc, i8 11) ; <i8> [#uses=1]
- store i8 %36, i8* @sc, align 1
- %37 = call i8 @llvm.atomic.load.or.i8.p0i8(i8* @uc, i8 11) ; <i8> [#uses=1]
- store i8 %37, i8* @uc, align 1
- %38 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %39 = call i16 @llvm.atomic.load.or.i16.p0i16(i16* %38, i16 11) ; <i16> [#uses=1]
- store i16 %39, i16* @ss, align 2
- %40 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %41 = call i16 @llvm.atomic.load.or.i16.p0i16(i16* %40, i16 11) ; <i16> [#uses=1]
- store i16 %41, i16* @us, align 2
- %42 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %43 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %42, i32 11) ; <i32> [#uses=1]
- store i32 %43, i32* @si, align 4
- %44 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %45 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %44, i32 11) ; <i32> [#uses=1]
- store i32 %45, i32* @ui, align 4
- %46 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %47 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %46, i32 11) ; <i32> [#uses=1]
- store i32 %47, i32* @sl, align 4
- %48 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %49 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %48, i32 11) ; <i32> [#uses=1]
- store i32 %49, i32* @ul, align 4
- %50 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %51 = call i64 @llvm.atomic.load.or.i64.p0i64(i64* %50, i64 11) ; <i64> [#uses=1]
- store i64 %51, i64* @sll, align 8
- %52 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %53 = call i64 @llvm.atomic.load.or.i64.p0i64(i64* %52, i64 11) ; <i64> [#uses=1]
- store i64 %53, i64* @ull, align 8
- %54 = call i8 @llvm.atomic.load.xor.i8.p0i8(i8* @sc, i8 11) ; <i8> [#uses=1]
- store i8 %54, i8* @sc, align 1
- %55 = call i8 @llvm.atomic.load.xor.i8.p0i8(i8* @uc, i8 11) ; <i8> [#uses=1]
- store i8 %55, i8* @uc, align 1
- %56 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %57 = call i16 @llvm.atomic.load.xor.i16.p0i16(i16* %56, i16 11) ; <i16> [#uses=1]
- store i16 %57, i16* @ss, align 2
- %58 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %59 = call i16 @llvm.atomic.load.xor.i16.p0i16(i16* %58, i16 11) ; <i16> [#uses=1]
- store i16 %59, i16* @us, align 2
- %60 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %61 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %60, i32 11) ; <i32> [#uses=1]
- store i32 %61, i32* @si, align 4
- %62 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %63 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %62, i32 11) ; <i32> [#uses=1]
- store i32 %63, i32* @ui, align 4
- %64 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %65 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %64, i32 11) ; <i32> [#uses=1]
- store i32 %65, i32* @sl, align 4
- %66 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %67 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %66, i32 11) ; <i32> [#uses=1]
- store i32 %67, i32* @ul, align 4
- %68 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %69 = call i64 @llvm.atomic.load.xor.i64.p0i64(i64* %68, i64 11) ; <i64> [#uses=1]
- store i64 %69, i64* @sll, align 8
- %70 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %71 = call i64 @llvm.atomic.load.xor.i64.p0i64(i64* %70, i64 11) ; <i64> [#uses=1]
- store i64 %71, i64* @ull, align 8
- %72 = call i8 @llvm.atomic.load.and.i8.p0i8(i8* @sc, i8 11) ; <i8> [#uses=1]
- store i8 %72, i8* @sc, align 1
- %73 = call i8 @llvm.atomic.load.and.i8.p0i8(i8* @uc, i8 11) ; <i8> [#uses=1]
- store i8 %73, i8* @uc, align 1
- %74 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %75 = call i16 @llvm.atomic.load.and.i16.p0i16(i16* %74, i16 11) ; <i16> [#uses=1]
- store i16 %75, i16* @ss, align 2
- %76 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %77 = call i16 @llvm.atomic.load.and.i16.p0i16(i16* %76, i16 11) ; <i16> [#uses=1]
- store i16 %77, i16* @us, align 2
- %78 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %79 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %78, i32 11) ; <i32> [#uses=1]
- store i32 %79, i32* @si, align 4
- %80 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %81 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %80, i32 11) ; <i32> [#uses=1]
- store i32 %81, i32* @ui, align 4
- %82 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %83 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %82, i32 11) ; <i32> [#uses=1]
- store i32 %83, i32* @sl, align 4
- %84 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %85 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %84, i32 11) ; <i32> [#uses=1]
- store i32 %85, i32* @ul, align 4
- %86 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %87 = call i64 @llvm.atomic.load.and.i64.p0i64(i64* %86, i64 11) ; <i64> [#uses=1]
- store i64 %87, i64* @sll, align 8
- %88 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %89 = call i64 @llvm.atomic.load.and.i64.p0i64(i64* %88, i64 11) ; <i64> [#uses=1]
- store i64 %89, i64* @ull, align 8
- %90 = call i8 @llvm.atomic.load.nand.i8.p0i8(i8* @sc, i8 11) ; <i8> [#uses=1]
- store i8 %90, i8* @sc, align 1
- %91 = call i8 @llvm.atomic.load.nand.i8.p0i8(i8* @uc, i8 11) ; <i8> [#uses=1]
- store i8 %91, i8* @uc, align 1
- %92 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %93 = call i16 @llvm.atomic.load.nand.i16.p0i16(i16* %92, i16 11) ; <i16> [#uses=1]
- store i16 %93, i16* @ss, align 2
- %94 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %95 = call i16 @llvm.atomic.load.nand.i16.p0i16(i16* %94, i16 11) ; <i16> [#uses=1]
- store i16 %95, i16* @us, align 2
- %96 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %97 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %96, i32 11) ; <i32> [#uses=1]
- store i32 %97, i32* @si, align 4
- %98 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %99 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %98, i32 11) ; <i32> [#uses=1]
- store i32 %99, i32* @ui, align 4
- %100 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %101 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %100, i32 11) ; <i32> [#uses=1]
- store i32 %101, i32* @sl, align 4
- %102 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %103 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %102, i32 11) ; <i32> [#uses=1]
- store i32 %103, i32* @ul, align 4
- %104 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %105 = call i64 @llvm.atomic.load.nand.i64.p0i64(i64* %104, i64 11) ; <i64> [#uses=1]
- store i64 %105, i64* @sll, align 8
- %106 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %107 = call i64 @llvm.atomic.load.nand.i64.p0i64(i64* %106, i64 11) ; <i64> [#uses=1]
- store i64 %107, i64* @ull, align 8
- br label %return
-
-return: ; preds = %entry
- ret void
-}
-
-define void @test_op_and_fetch() nounwind {
-entry:
- %0 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %1 = zext i8 %0 to i32 ; <i32> [#uses=1]
- %2 = trunc i32 %1 to i8 ; <i8> [#uses=2]
- %3 = call i8 @llvm.atomic.load.add.i8.p0i8(i8* @sc, i8 %2) ; <i8> [#uses=1]
- %4 = add i8 %3, %2 ; <i8> [#uses=1]
- store i8 %4, i8* @sc, align 1
- %5 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %6 = zext i8 %5 to i32 ; <i32> [#uses=1]
- %7 = trunc i32 %6 to i8 ; <i8> [#uses=2]
- %8 = call i8 @llvm.atomic.load.add.i8.p0i8(i8* @uc, i8 %7) ; <i8> [#uses=1]
- %9 = add i8 %8, %7 ; <i8> [#uses=1]
- store i8 %9, i8* @uc, align 1
- %10 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %11 = zext i8 %10 to i32 ; <i32> [#uses=1]
- %12 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %13 = trunc i32 %11 to i16 ; <i16> [#uses=2]
- %14 = call i16 @llvm.atomic.load.add.i16.p0i16(i16* %12, i16 %13) ; <i16> [#uses=1]
- %15 = add i16 %14, %13 ; <i16> [#uses=1]
- store i16 %15, i16* @ss, align 2
- %16 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %17 = zext i8 %16 to i32 ; <i32> [#uses=1]
- %18 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %19 = trunc i32 %17 to i16 ; <i16> [#uses=2]
- %20 = call i16 @llvm.atomic.load.add.i16.p0i16(i16* %18, i16 %19) ; <i16> [#uses=1]
- %21 = add i16 %20, %19 ; <i16> [#uses=1]
- store i16 %21, i16* @us, align 2
- %22 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %23 = zext i8 %22 to i32 ; <i32> [#uses=2]
- %24 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %25 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %24, i32 %23) ; <i32> [#uses=1]
- %26 = add i32 %25, %23 ; <i32> [#uses=1]
- store i32 %26, i32* @si, align 4
- %27 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %28 = zext i8 %27 to i32 ; <i32> [#uses=2]
- %29 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %30 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %29, i32 %28) ; <i32> [#uses=1]
- %31 = add i32 %30, %28 ; <i32> [#uses=1]
- store i32 %31, i32* @ui, align 4
- %32 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %33 = zext i8 %32 to i32 ; <i32> [#uses=2]
- %34 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %35 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %34, i32 %33) ; <i32> [#uses=1]
- %36 = add i32 %35, %33 ; <i32> [#uses=1]
- store i32 %36, i32* @sl, align 4
- %37 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %38 = zext i8 %37 to i32 ; <i32> [#uses=2]
- %39 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %40 = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %39, i32 %38) ; <i32> [#uses=1]
- %41 = add i32 %40, %38 ; <i32> [#uses=1]
- store i32 %41, i32* @ul, align 4
- %42 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %43 = zext i8 %42 to i64 ; <i64> [#uses=2]
- %44 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %45 = call i64 @llvm.atomic.load.add.i64.p0i64(i64* %44, i64 %43) ; <i64> [#uses=1]
- %46 = add i64 %45, %43 ; <i64> [#uses=1]
- store i64 %46, i64* @sll, align 8
- %47 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %48 = zext i8 %47 to i64 ; <i64> [#uses=2]
- %49 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %50 = call i64 @llvm.atomic.load.add.i64.p0i64(i64* %49, i64 %48) ; <i64> [#uses=1]
- %51 = add i64 %50, %48 ; <i64> [#uses=1]
- store i64 %51, i64* @ull, align 8
- %52 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %53 = zext i8 %52 to i32 ; <i32> [#uses=1]
- %54 = trunc i32 %53 to i8 ; <i8> [#uses=2]
- %55 = call i8 @llvm.atomic.load.sub.i8.p0i8(i8* @sc, i8 %54) ; <i8> [#uses=1]
- %56 = sub i8 %55, %54 ; <i8> [#uses=1]
- store i8 %56, i8* @sc, align 1
- %57 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %58 = zext i8 %57 to i32 ; <i32> [#uses=1]
- %59 = trunc i32 %58 to i8 ; <i8> [#uses=2]
- %60 = call i8 @llvm.atomic.load.sub.i8.p0i8(i8* @uc, i8 %59) ; <i8> [#uses=1]
- %61 = sub i8 %60, %59 ; <i8> [#uses=1]
- store i8 %61, i8* @uc, align 1
- %62 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %63 = zext i8 %62 to i32 ; <i32> [#uses=1]
- %64 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %65 = trunc i32 %63 to i16 ; <i16> [#uses=2]
- %66 = call i16 @llvm.atomic.load.sub.i16.p0i16(i16* %64, i16 %65) ; <i16> [#uses=1]
- %67 = sub i16 %66, %65 ; <i16> [#uses=1]
- store i16 %67, i16* @ss, align 2
- %68 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %69 = zext i8 %68 to i32 ; <i32> [#uses=1]
- %70 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %71 = trunc i32 %69 to i16 ; <i16> [#uses=2]
- %72 = call i16 @llvm.atomic.load.sub.i16.p0i16(i16* %70, i16 %71) ; <i16> [#uses=1]
- %73 = sub i16 %72, %71 ; <i16> [#uses=1]
- store i16 %73, i16* @us, align 2
- %74 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %75 = zext i8 %74 to i32 ; <i32> [#uses=2]
- %76 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %77 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %76, i32 %75) ; <i32> [#uses=1]
- %78 = sub i32 %77, %75 ; <i32> [#uses=1]
- store i32 %78, i32* @si, align 4
- %79 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %80 = zext i8 %79 to i32 ; <i32> [#uses=2]
- %81 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %82 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %81, i32 %80) ; <i32> [#uses=1]
- %83 = sub i32 %82, %80 ; <i32> [#uses=1]
- store i32 %83, i32* @ui, align 4
- %84 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %85 = zext i8 %84 to i32 ; <i32> [#uses=2]
- %86 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %87 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %86, i32 %85) ; <i32> [#uses=1]
- %88 = sub i32 %87, %85 ; <i32> [#uses=1]
- store i32 %88, i32* @sl, align 4
- %89 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %90 = zext i8 %89 to i32 ; <i32> [#uses=2]
- %91 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %92 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %91, i32 %90) ; <i32> [#uses=1]
- %93 = sub i32 %92, %90 ; <i32> [#uses=1]
- store i32 %93, i32* @ul, align 4
- %94 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %95 = zext i8 %94 to i64 ; <i64> [#uses=2]
- %96 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %97 = call i64 @llvm.atomic.load.sub.i64.p0i64(i64* %96, i64 %95) ; <i64> [#uses=1]
- %98 = sub i64 %97, %95 ; <i64> [#uses=1]
- store i64 %98, i64* @sll, align 8
- %99 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %100 = zext i8 %99 to i64 ; <i64> [#uses=2]
- %101 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %102 = call i64 @llvm.atomic.load.sub.i64.p0i64(i64* %101, i64 %100) ; <i64> [#uses=1]
- %103 = sub i64 %102, %100 ; <i64> [#uses=1]
- store i64 %103, i64* @ull, align 8
- %104 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %105 = zext i8 %104 to i32 ; <i32> [#uses=1]
- %106 = trunc i32 %105 to i8 ; <i8> [#uses=2]
- %107 = call i8 @llvm.atomic.load.or.i8.p0i8(i8* @sc, i8 %106) ; <i8> [#uses=1]
- %108 = or i8 %107, %106 ; <i8> [#uses=1]
- store i8 %108, i8* @sc, align 1
- %109 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %110 = zext i8 %109 to i32 ; <i32> [#uses=1]
- %111 = trunc i32 %110 to i8 ; <i8> [#uses=2]
- %112 = call i8 @llvm.atomic.load.or.i8.p0i8(i8* @uc, i8 %111) ; <i8> [#uses=1]
- %113 = or i8 %112, %111 ; <i8> [#uses=1]
- store i8 %113, i8* @uc, align 1
- %114 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %115 = zext i8 %114 to i32 ; <i32> [#uses=1]
- %116 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %117 = trunc i32 %115 to i16 ; <i16> [#uses=2]
- %118 = call i16 @llvm.atomic.load.or.i16.p0i16(i16* %116, i16 %117) ; <i16> [#uses=1]
- %119 = or i16 %118, %117 ; <i16> [#uses=1]
- store i16 %119, i16* @ss, align 2
- %120 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %121 = zext i8 %120 to i32 ; <i32> [#uses=1]
- %122 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %123 = trunc i32 %121 to i16 ; <i16> [#uses=2]
- %124 = call i16 @llvm.atomic.load.or.i16.p0i16(i16* %122, i16 %123) ; <i16> [#uses=1]
- %125 = or i16 %124, %123 ; <i16> [#uses=1]
- store i16 %125, i16* @us, align 2
- %126 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %127 = zext i8 %126 to i32 ; <i32> [#uses=2]
- %128 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %129 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %128, i32 %127) ; <i32> [#uses=1]
- %130 = or i32 %129, %127 ; <i32> [#uses=1]
- store i32 %130, i32* @si, align 4
- %131 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %132 = zext i8 %131 to i32 ; <i32> [#uses=2]
- %133 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %134 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %133, i32 %132) ; <i32> [#uses=1]
- %135 = or i32 %134, %132 ; <i32> [#uses=1]
- store i32 %135, i32* @ui, align 4
- %136 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %137 = zext i8 %136 to i32 ; <i32> [#uses=2]
- %138 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %139 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %138, i32 %137) ; <i32> [#uses=1]
- %140 = or i32 %139, %137 ; <i32> [#uses=1]
- store i32 %140, i32* @sl, align 4
- %141 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %142 = zext i8 %141 to i32 ; <i32> [#uses=2]
- %143 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %144 = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %143, i32 %142) ; <i32> [#uses=1]
- %145 = or i32 %144, %142 ; <i32> [#uses=1]
- store i32 %145, i32* @ul, align 4
- %146 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %147 = zext i8 %146 to i64 ; <i64> [#uses=2]
- %148 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %149 = call i64 @llvm.atomic.load.or.i64.p0i64(i64* %148, i64 %147) ; <i64> [#uses=1]
- %150 = or i64 %149, %147 ; <i64> [#uses=1]
- store i64 %150, i64* @sll, align 8
- %151 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %152 = zext i8 %151 to i64 ; <i64> [#uses=2]
- %153 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %154 = call i64 @llvm.atomic.load.or.i64.p0i64(i64* %153, i64 %152) ; <i64> [#uses=1]
- %155 = or i64 %154, %152 ; <i64> [#uses=1]
- store i64 %155, i64* @ull, align 8
- %156 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %157 = zext i8 %156 to i32 ; <i32> [#uses=1]
- %158 = trunc i32 %157 to i8 ; <i8> [#uses=2]
- %159 = call i8 @llvm.atomic.load.xor.i8.p0i8(i8* @sc, i8 %158) ; <i8> [#uses=1]
- %160 = xor i8 %159, %158 ; <i8> [#uses=1]
- store i8 %160, i8* @sc, align 1
- %161 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %162 = zext i8 %161 to i32 ; <i32> [#uses=1]
- %163 = trunc i32 %162 to i8 ; <i8> [#uses=2]
- %164 = call i8 @llvm.atomic.load.xor.i8.p0i8(i8* @uc, i8 %163) ; <i8> [#uses=1]
- %165 = xor i8 %164, %163 ; <i8> [#uses=1]
- store i8 %165, i8* @uc, align 1
- %166 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %167 = zext i8 %166 to i32 ; <i32> [#uses=1]
- %168 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %169 = trunc i32 %167 to i16 ; <i16> [#uses=2]
- %170 = call i16 @llvm.atomic.load.xor.i16.p0i16(i16* %168, i16 %169) ; <i16> [#uses=1]
- %171 = xor i16 %170, %169 ; <i16> [#uses=1]
- store i16 %171, i16* @ss, align 2
- %172 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %173 = zext i8 %172 to i32 ; <i32> [#uses=1]
- %174 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %175 = trunc i32 %173 to i16 ; <i16> [#uses=2]
- %176 = call i16 @llvm.atomic.load.xor.i16.p0i16(i16* %174, i16 %175) ; <i16> [#uses=1]
- %177 = xor i16 %176, %175 ; <i16> [#uses=1]
- store i16 %177, i16* @us, align 2
- %178 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %179 = zext i8 %178 to i32 ; <i32> [#uses=2]
- %180 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %181 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %180, i32 %179) ; <i32> [#uses=1]
- %182 = xor i32 %181, %179 ; <i32> [#uses=1]
- store i32 %182, i32* @si, align 4
- %183 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %184 = zext i8 %183 to i32 ; <i32> [#uses=2]
- %185 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %186 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %185, i32 %184) ; <i32> [#uses=1]
- %187 = xor i32 %186, %184 ; <i32> [#uses=1]
- store i32 %187, i32* @ui, align 4
- %188 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %189 = zext i8 %188 to i32 ; <i32> [#uses=2]
- %190 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %191 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %190, i32 %189) ; <i32> [#uses=1]
- %192 = xor i32 %191, %189 ; <i32> [#uses=1]
- store i32 %192, i32* @sl, align 4
- %193 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %194 = zext i8 %193 to i32 ; <i32> [#uses=2]
- %195 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %196 = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %195, i32 %194) ; <i32> [#uses=1]
- %197 = xor i32 %196, %194 ; <i32> [#uses=1]
- store i32 %197, i32* @ul, align 4
- %198 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %199 = zext i8 %198 to i64 ; <i64> [#uses=2]
- %200 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %201 = call i64 @llvm.atomic.load.xor.i64.p0i64(i64* %200, i64 %199) ; <i64> [#uses=1]
- %202 = xor i64 %201, %199 ; <i64> [#uses=1]
- store i64 %202, i64* @sll, align 8
- %203 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %204 = zext i8 %203 to i64 ; <i64> [#uses=2]
- %205 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %206 = call i64 @llvm.atomic.load.xor.i64.p0i64(i64* %205, i64 %204) ; <i64> [#uses=1]
- %207 = xor i64 %206, %204 ; <i64> [#uses=1]
- store i64 %207, i64* @ull, align 8
- %208 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %209 = zext i8 %208 to i32 ; <i32> [#uses=1]
- %210 = trunc i32 %209 to i8 ; <i8> [#uses=2]
- %211 = call i8 @llvm.atomic.load.and.i8.p0i8(i8* @sc, i8 %210) ; <i8> [#uses=1]
- %212 = and i8 %211, %210 ; <i8> [#uses=1]
- store i8 %212, i8* @sc, align 1
- %213 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %214 = zext i8 %213 to i32 ; <i32> [#uses=1]
- %215 = trunc i32 %214 to i8 ; <i8> [#uses=2]
- %216 = call i8 @llvm.atomic.load.and.i8.p0i8(i8* @uc, i8 %215) ; <i8> [#uses=1]
- %217 = and i8 %216, %215 ; <i8> [#uses=1]
- store i8 %217, i8* @uc, align 1
- %218 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %219 = zext i8 %218 to i32 ; <i32> [#uses=1]
- %220 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %221 = trunc i32 %219 to i16 ; <i16> [#uses=2]
- %222 = call i16 @llvm.atomic.load.and.i16.p0i16(i16* %220, i16 %221) ; <i16> [#uses=1]
- %223 = and i16 %222, %221 ; <i16> [#uses=1]
- store i16 %223, i16* @ss, align 2
- %224 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %225 = zext i8 %224 to i32 ; <i32> [#uses=1]
- %226 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %227 = trunc i32 %225 to i16 ; <i16> [#uses=2]
- %228 = call i16 @llvm.atomic.load.and.i16.p0i16(i16* %226, i16 %227) ; <i16> [#uses=1]
- %229 = and i16 %228, %227 ; <i16> [#uses=1]
- store i16 %229, i16* @us, align 2
- %230 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %231 = zext i8 %230 to i32 ; <i32> [#uses=2]
- %232 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %233 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %232, i32 %231) ; <i32> [#uses=1]
- %234 = and i32 %233, %231 ; <i32> [#uses=1]
- store i32 %234, i32* @si, align 4
- %235 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %236 = zext i8 %235 to i32 ; <i32> [#uses=2]
- %237 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %238 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %237, i32 %236) ; <i32> [#uses=1]
- %239 = and i32 %238, %236 ; <i32> [#uses=1]
- store i32 %239, i32* @ui, align 4
- %240 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %241 = zext i8 %240 to i32 ; <i32> [#uses=2]
- %242 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %243 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %242, i32 %241) ; <i32> [#uses=1]
- %244 = and i32 %243, %241 ; <i32> [#uses=1]
- store i32 %244, i32* @sl, align 4
- %245 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %246 = zext i8 %245 to i32 ; <i32> [#uses=2]
- %247 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %248 = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %247, i32 %246) ; <i32> [#uses=1]
- %249 = and i32 %248, %246 ; <i32> [#uses=1]
- store i32 %249, i32* @ul, align 4
- %250 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %251 = zext i8 %250 to i64 ; <i64> [#uses=2]
- %252 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %253 = call i64 @llvm.atomic.load.and.i64.p0i64(i64* %252, i64 %251) ; <i64> [#uses=1]
- %254 = and i64 %253, %251 ; <i64> [#uses=1]
- store i64 %254, i64* @sll, align 8
- %255 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %256 = zext i8 %255 to i64 ; <i64> [#uses=2]
- %257 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %258 = call i64 @llvm.atomic.load.and.i64.p0i64(i64* %257, i64 %256) ; <i64> [#uses=1]
- %259 = and i64 %258, %256 ; <i64> [#uses=1]
- store i64 %259, i64* @ull, align 8
- %260 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %261 = zext i8 %260 to i32 ; <i32> [#uses=1]
- %262 = trunc i32 %261 to i8 ; <i8> [#uses=2]
- %263 = call i8 @llvm.atomic.load.nand.i8.p0i8(i8* @sc, i8 %262) ; <i8> [#uses=1]
- %264 = xor i8 %263, -1 ; <i8> [#uses=1]
- %265 = and i8 %264, %262 ; <i8> [#uses=1]
- store i8 %265, i8* @sc, align 1
- %266 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %267 = zext i8 %266 to i32 ; <i32> [#uses=1]
- %268 = trunc i32 %267 to i8 ; <i8> [#uses=2]
- %269 = call i8 @llvm.atomic.load.nand.i8.p0i8(i8* @uc, i8 %268) ; <i8> [#uses=1]
- %270 = xor i8 %269, -1 ; <i8> [#uses=1]
- %271 = and i8 %270, %268 ; <i8> [#uses=1]
- store i8 %271, i8* @uc, align 1
- %272 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %273 = zext i8 %272 to i32 ; <i32> [#uses=1]
- %274 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %275 = trunc i32 %273 to i16 ; <i16> [#uses=2]
- %276 = call i16 @llvm.atomic.load.nand.i16.p0i16(i16* %274, i16 %275) ; <i16> [#uses=1]
- %277 = xor i16 %276, -1 ; <i16> [#uses=1]
- %278 = and i16 %277, %275 ; <i16> [#uses=1]
- store i16 %278, i16* @ss, align 2
- %279 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %280 = zext i8 %279 to i32 ; <i32> [#uses=1]
- %281 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %282 = trunc i32 %280 to i16 ; <i16> [#uses=2]
- %283 = call i16 @llvm.atomic.load.nand.i16.p0i16(i16* %281, i16 %282) ; <i16> [#uses=1]
- %284 = xor i16 %283, -1 ; <i16> [#uses=1]
- %285 = and i16 %284, %282 ; <i16> [#uses=1]
- store i16 %285, i16* @us, align 2
- %286 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %287 = zext i8 %286 to i32 ; <i32> [#uses=2]
- %288 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %289 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %288, i32 %287) ; <i32> [#uses=1]
- %290 = xor i32 %289, -1 ; <i32> [#uses=1]
- %291 = and i32 %290, %287 ; <i32> [#uses=1]
- store i32 %291, i32* @si, align 4
- %292 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %293 = zext i8 %292 to i32 ; <i32> [#uses=2]
- %294 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %295 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %294, i32 %293) ; <i32> [#uses=1]
- %296 = xor i32 %295, -1 ; <i32> [#uses=1]
- %297 = and i32 %296, %293 ; <i32> [#uses=1]
- store i32 %297, i32* @ui, align 4
- %298 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %299 = zext i8 %298 to i32 ; <i32> [#uses=2]
- %300 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %301 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %300, i32 %299) ; <i32> [#uses=1]
- %302 = xor i32 %301, -1 ; <i32> [#uses=1]
- %303 = and i32 %302, %299 ; <i32> [#uses=1]
- store i32 %303, i32* @sl, align 4
- %304 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %305 = zext i8 %304 to i32 ; <i32> [#uses=2]
- %306 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %307 = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %306, i32 %305) ; <i32> [#uses=1]
- %308 = xor i32 %307, -1 ; <i32> [#uses=1]
- %309 = and i32 %308, %305 ; <i32> [#uses=1]
- store i32 %309, i32* @ul, align 4
- %310 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %311 = zext i8 %310 to i64 ; <i64> [#uses=2]
- %312 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- %313 = call i64 @llvm.atomic.load.nand.i64.p0i64(i64* %312, i64 %311) ; <i64> [#uses=1]
- %314 = xor i64 %313, -1 ; <i64> [#uses=1]
- %315 = and i64 %314, %311 ; <i64> [#uses=1]
- store i64 %315, i64* @sll, align 8
- %316 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %317 = zext i8 %316 to i64 ; <i64> [#uses=2]
- %318 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- %319 = call i64 @llvm.atomic.load.nand.i64.p0i64(i64* %318, i64 %317) ; <i64> [#uses=1]
- %320 = xor i64 %319, -1 ; <i64> [#uses=1]
- %321 = and i64 %320, %317 ; <i64> [#uses=1]
- store i64 %321, i64* @ull, align 8
- br label %return
-
-return: ; preds = %entry
- ret void
-}
-
-define void @test_compare_and_swap() nounwind {
-entry:
- %0 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %1 = zext i8 %0 to i32 ; <i32> [#uses=1]
- %2 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %3 = zext i8 %2 to i32 ; <i32> [#uses=1]
- %4 = trunc i32 %3 to i8 ; <i8> [#uses=1]
- %5 = trunc i32 %1 to i8 ; <i8> [#uses=1]
- %6 = call i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* @sc, i8 %4, i8 %5) ; <i8> [#uses=1]
- store i8 %6, i8* @sc, align 1
- %7 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %8 = zext i8 %7 to i32 ; <i32> [#uses=1]
- %9 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %10 = zext i8 %9 to i32 ; <i32> [#uses=1]
- %11 = trunc i32 %10 to i8 ; <i8> [#uses=1]
- %12 = trunc i32 %8 to i8 ; <i8> [#uses=1]
- %13 = call i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* @uc, i8 %11, i8 %12) ; <i8> [#uses=1]
- store i8 %13, i8* @uc, align 1
- %14 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %15 = sext i8 %14 to i16 ; <i16> [#uses=1]
- %16 = zext i16 %15 to i32 ; <i32> [#uses=1]
- %17 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %18 = zext i8 %17 to i32 ; <i32> [#uses=1]
- %19 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %20 = trunc i32 %18 to i16 ; <i16> [#uses=1]
- %21 = trunc i32 %16 to i16 ; <i16> [#uses=1]
- %22 = call i16 @llvm.atomic.cmp.swap.i16.p0i16(i16* %19, i16 %20, i16 %21) ; <i16> [#uses=1]
- store i16 %22, i16* @ss, align 2
- %23 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %24 = sext i8 %23 to i16 ; <i16> [#uses=1]
- %25 = zext i16 %24 to i32 ; <i32> [#uses=1]
- %26 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %27 = zext i8 %26 to i32 ; <i32> [#uses=1]
- %28 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %29 = trunc i32 %27 to i16 ; <i16> [#uses=1]
- %30 = trunc i32 %25 to i16 ; <i16> [#uses=1]
- %31 = call i16 @llvm.atomic.cmp.swap.i16.p0i16(i16* %28, i16 %29, i16 %30) ; <i16> [#uses=1]
- store i16 %31, i16* @us, align 2
- %32 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %33 = sext i8 %32 to i32 ; <i32> [#uses=1]
- %34 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %35 = zext i8 %34 to i32 ; <i32> [#uses=1]
- %36 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %37 = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %36, i32 %35, i32 %33) ; <i32> [#uses=1]
- store i32 %37, i32* @si, align 4
- %38 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %39 = sext i8 %38 to i32 ; <i32> [#uses=1]
- %40 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %41 = zext i8 %40 to i32 ; <i32> [#uses=1]
- %42 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %43 = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %42, i32 %41, i32 %39) ; <i32> [#uses=1]
- store i32 %43, i32* @ui, align 4
- %44 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %45 = sext i8 %44 to i32 ; <i32> [#uses=1]
- %46 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %47 = zext i8 %46 to i32 ; <i32> [#uses=1]
- %48 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %49 = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %48, i32 %47, i32 %45) ; <i32> [#uses=1]
- store i32 %49, i32* @sl, align 4
- %50 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %51 = sext i8 %50 to i32 ; <i32> [#uses=1]
- %52 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %53 = zext i8 %52 to i32 ; <i32> [#uses=1]
- %54 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %55 = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %54, i32 %53, i32 %51) ; <i32> [#uses=1]
- store i32 %55, i32* @ul, align 4
- %56 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %57 = zext i8 %56 to i32 ; <i32> [#uses=1]
- %58 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %59 = zext i8 %58 to i32 ; <i32> [#uses=1]
- %60 = trunc i32 %59 to i8 ; <i8> [#uses=2]
- %61 = trunc i32 %57 to i8 ; <i8> [#uses=1]
- %62 = call i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* @sc, i8 %60, i8 %61) ; <i8> [#uses=1]
- %63 = icmp eq i8 %62, %60 ; <i1> [#uses=1]
- %64 = zext i1 %63 to i8 ; <i8> [#uses=1]
- %65 = zext i8 %64 to i32 ; <i32> [#uses=1]
- store i32 %65, i32* @ui, align 4
- %66 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %67 = zext i8 %66 to i32 ; <i32> [#uses=1]
- %68 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %69 = zext i8 %68 to i32 ; <i32> [#uses=1]
- %70 = trunc i32 %69 to i8 ; <i8> [#uses=2]
- %71 = trunc i32 %67 to i8 ; <i8> [#uses=1]
- %72 = call i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* @uc, i8 %70, i8 %71) ; <i8> [#uses=1]
- %73 = icmp eq i8 %72, %70 ; <i1> [#uses=1]
- %74 = zext i1 %73 to i8 ; <i8> [#uses=1]
- %75 = zext i8 %74 to i32 ; <i32> [#uses=1]
- store i32 %75, i32* @ui, align 4
- %76 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %77 = sext i8 %76 to i16 ; <i16> [#uses=1]
- %78 = zext i16 %77 to i32 ; <i32> [#uses=1]
- %79 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %80 = zext i8 %79 to i32 ; <i32> [#uses=1]
- %81 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %82 = trunc i32 %80 to i16 ; <i16> [#uses=2]
- %83 = trunc i32 %78 to i16 ; <i16> [#uses=1]
- %84 = call i16 @llvm.atomic.cmp.swap.i16.p0i16(i16* %81, i16 %82, i16 %83) ; <i16> [#uses=1]
- %85 = icmp eq i16 %84, %82 ; <i1> [#uses=1]
- %86 = zext i1 %85 to i8 ; <i8> [#uses=1]
- %87 = zext i8 %86 to i32 ; <i32> [#uses=1]
- store i32 %87, i32* @ui, align 4
- %88 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %89 = sext i8 %88 to i16 ; <i16> [#uses=1]
- %90 = zext i16 %89 to i32 ; <i32> [#uses=1]
- %91 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %92 = zext i8 %91 to i32 ; <i32> [#uses=1]
- %93 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %94 = trunc i32 %92 to i16 ; <i16> [#uses=2]
- %95 = trunc i32 %90 to i16 ; <i16> [#uses=1]
- %96 = call i16 @llvm.atomic.cmp.swap.i16.p0i16(i16* %93, i16 %94, i16 %95) ; <i16> [#uses=1]
- %97 = icmp eq i16 %96, %94 ; <i1> [#uses=1]
- %98 = zext i1 %97 to i8 ; <i8> [#uses=1]
- %99 = zext i8 %98 to i32 ; <i32> [#uses=1]
- store i32 %99, i32* @ui, align 4
- %100 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %101 = sext i8 %100 to i32 ; <i32> [#uses=1]
- %102 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %103 = zext i8 %102 to i32 ; <i32> [#uses=2]
- %104 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %105 = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %104, i32 %103, i32 %101) ; <i32> [#uses=1]
- %106 = icmp eq i32 %105, %103 ; <i1> [#uses=1]
- %107 = zext i1 %106 to i8 ; <i8> [#uses=1]
- %108 = zext i8 %107 to i32 ; <i32> [#uses=1]
- store i32 %108, i32* @ui, align 4
- %109 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %110 = sext i8 %109 to i32 ; <i32> [#uses=1]
- %111 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %112 = zext i8 %111 to i32 ; <i32> [#uses=2]
- %113 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %114 = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %113, i32 %112, i32 %110) ; <i32> [#uses=1]
- %115 = icmp eq i32 %114, %112 ; <i1> [#uses=1]
- %116 = zext i1 %115 to i8 ; <i8> [#uses=1]
- %117 = zext i8 %116 to i32 ; <i32> [#uses=1]
- store i32 %117, i32* @ui, align 4
- %118 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %119 = sext i8 %118 to i32 ; <i32> [#uses=1]
- %120 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %121 = zext i8 %120 to i32 ; <i32> [#uses=2]
- %122 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %123 = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %122, i32 %121, i32 %119) ; <i32> [#uses=1]
- %124 = icmp eq i32 %123, %121 ; <i1> [#uses=1]
- %125 = zext i1 %124 to i8 ; <i8> [#uses=1]
- %126 = zext i8 %125 to i32 ; <i32> [#uses=1]
- store i32 %126, i32* @ui, align 4
- %127 = load i8* @sc, align 1 ; <i8> [#uses=1]
- %128 = sext i8 %127 to i32 ; <i32> [#uses=1]
- %129 = load i8* @uc, align 1 ; <i8> [#uses=1]
- %130 = zext i8 %129 to i32 ; <i32> [#uses=2]
- %131 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %132 = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %131, i32 %130, i32 %128) ; <i32> [#uses=1]
- %133 = icmp eq i32 %132, %130 ; <i1> [#uses=1]
- %134 = zext i1 %133 to i8 ; <i8> [#uses=1]
- %135 = zext i8 %134 to i32 ; <i32> [#uses=1]
- store i32 %135, i32* @ui, align 4
- br label %return
-
-return: ; preds = %entry
- ret void
-}
-
-declare i8 @llvm.atomic.cmp.swap.i8.p0i8(i8*, i8, i8) nounwind
-
-declare i16 @llvm.atomic.cmp.swap.i16.p0i16(i16*, i16, i16) nounwind
-
-declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32*, i32, i32) nounwind
-
-define void @test_lock() nounwind {
-entry:
- %0 = call i8 @llvm.atomic.swap.i8.p0i8(i8* @sc, i8 1) ; <i8> [#uses=1]
- store i8 %0, i8* @sc, align 1
- %1 = call i8 @llvm.atomic.swap.i8.p0i8(i8* @uc, i8 1) ; <i8> [#uses=1]
- store i8 %1, i8* @uc, align 1
- %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- %3 = call i16 @llvm.atomic.swap.i16.p0i16(i16* %2, i16 1) ; <i16> [#uses=1]
- store i16 %3, i16* @ss, align 2
- %4 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- %5 = call i16 @llvm.atomic.swap.i16.p0i16(i16* %4, i16 1) ; <i16> [#uses=1]
- store i16 %5, i16* @us, align 2
- %6 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- %7 = call i32 @llvm.atomic.swap.i32.p0i32(i32* %6, i32 1) ; <i32> [#uses=1]
- store i32 %7, i32* @si, align 4
- %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- %9 = call i32 @llvm.atomic.swap.i32.p0i32(i32* %8, i32 1) ; <i32> [#uses=1]
- store i32 %9, i32* @ui, align 4
- %10 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- %11 = call i32 @llvm.atomic.swap.i32.p0i32(i32* %10, i32 1) ; <i32> [#uses=1]
- store i32 %11, i32* @sl, align 4
- %12 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- %13 = call i32 @llvm.atomic.swap.i32.p0i32(i32* %12, i32 1) ; <i32> [#uses=1]
- store i32 %13, i32* @ul, align 4
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false)
- volatile store i8 0, i8* @sc, align 1
- volatile store i8 0, i8* @uc, align 1
- %14 = bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*> [#uses=1]
- volatile store i16 0, i16* %14, align 2
- %15 = bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*> [#uses=1]
- volatile store i16 0, i16* %15, align 2
- %16 = bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*> [#uses=1]
- volatile store i32 0, i32* %16, align 4
- %17 = bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*> [#uses=1]
- volatile store i32 0, i32* %17, align 4
- %18 = bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*> [#uses=1]
- volatile store i32 0, i32* %18, align 4
- %19 = bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*> [#uses=1]
- volatile store i32 0, i32* %19, align 4
- %20 = bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*> [#uses=1]
- volatile store i64 0, i64* %20, align 8
- %21 = bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*> [#uses=1]
- volatile store i64 0, i64* %21, align 8
- br label %return
-
-return: ; preds = %entry
- ret void
-}
-
-declare i8 @llvm.atomic.swap.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.swap.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.swap.i32.p0i32(i32*, i32) nounwind
-
-declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
diff --git a/test/CodeGen/X86/2009-03-13-PHIElimBug.ll b/test/CodeGen/X86/2009-03-13-PHIElimBug.ll
index 45fc269..e14c30a 100644
--- a/test/CodeGen/X86/2009-03-13-PHIElimBug.ll
+++ b/test/CodeGen/X86/2009-03-13-PHIElimBug.ll
@@ -24,9 +24,13 @@ cont2: ; preds = %cont
lpad: ; preds = %cont, %entry
%y = phi i32 [ %a, %entry ], [ %aa, %cont ] ; <i32> [#uses=1]
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i32 %y
}
; CHECK: call{{.*}}f
; CHECK: movl %eax, %esi
; CHECK: call{{.*}}g
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll b/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
index b13d33e..f8c7a15 100644
--- a/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
+++ b/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
@@ -17,8 +17,12 @@ cont2: ; preds = %cont
lpad: ; preds = %cont, %entry
%v = phi i32 [ %x, %entry ], [ %a, %cont ] ; <i32> [#uses=1]
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i32 %v
}
; CHECK: lpad
; CHECK-NEXT: Ltmp
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/2009-06-05-ScalarToVectorByteMMX.ll b/test/CodeGen/X86/2009-06-05-ScalarToVectorByteMMX.ll
index 01852a6..3076322 100644
--- a/test/CodeGen/X86/2009-06-05-ScalarToVectorByteMMX.ll
+++ b/test/CodeGen/X86/2009-06-05-ScalarToVectorByteMMX.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -march=x86 -mattr=+mmx,+sse2 | not grep movl
+; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu -mattr=+mmx,+sse2 | not grep movl
define <8 x i8> @a(i8 zeroext %x) nounwind {
%r = insertelement <8 x i8> undef, i8 %x, i32 0
diff --git a/test/CodeGen/X86/2009-06-18-movlp-shuffle-register.ll b/test/CodeGen/X86/2009-06-18-movlp-shuffle-register.ll
index 228cd48..8ea70b4 100644
--- a/test/CodeGen/X86/2009-06-18-movlp-shuffle-register.ll
+++ b/test/CodeGen/X86/2009-06-18-movlp-shuffle-register.ll
@@ -1,8 +1,9 @@
-; RUN: llc < %s -march=x86 -mattr=+sse,-sse2
+; RUN: llc < %s -march=x86 -mattr=+sse,-sse2 | FileCheck %s
; PR2484
define <4 x float> @f4523(<4 x float> %a,<4 x float> %b) nounwind {
entry:
+; CHECK: shufps $-28, %xmm
%shuffle = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 4,i32
5,i32 2,i32 3>
ret <4 x float> %shuffle
diff --git a/test/CodeGen/X86/2009-09-10-LoadFoldingBug.ll b/test/CodeGen/X86/2009-09-10-LoadFoldingBug.ll
index 7b5e871..5483b73 100644
--- a/test/CodeGen/X86/2009-09-10-LoadFoldingBug.ll
+++ b/test/CodeGen/X86/2009-09-10-LoadFoldingBug.ll
@@ -34,6 +34,8 @@ invcont2: ; preds = %invcont1
ret i32 0
lpad: ; preds = %invcont1, %invcont, %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
%8 = call i32 @vm_deallocate(i32 undef, i64 0, i64 %0) ; <i32> [#uses=0]
unreachable
}
@@ -45,3 +47,5 @@ declare i8* @pluginInstance(i8*, i32)
declare zeroext i8 @invoke(i8*, i32, i8*, i64, i32, i64*, i32*)
declare void @booleanAndDataReply(i32, i32, i32, i32, i64, i32)
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/2009-10-16-Scope.ll b/test/CodeGen/X86/2009-10-16-Scope.ll
index 86c2024..e41038d 100644
--- a/test/CodeGen/X86/2009-10-16-Scope.ll
+++ b/test/CodeGen/X86/2009-10-16-Scope.ll
@@ -23,10 +23,10 @@ declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
declare i32 @foo(i32) ssp
!0 = metadata !{i32 5, i32 2, metadata !1, null}
-!1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
+!1 = metadata !{i32 458763, metadata !2, i32 1, i32 1}; [DW_TAG_lexical_block ]
!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"bar", metadata !"bar", metadata !"bar", metadata !3, i32 4, null, i1 false, i1 true}; [DW_TAG_subprogram ]
!3 = metadata !{i32 458769, i32 0, i32 12, metadata !"genmodes.i", metadata !"/Users/yash/Downloads", metadata !"clang 1.1", i1 true, i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
!4 = metadata !{i32 459008, metadata !5, metadata !"count_", metadata !3, i32 5, metadata !6}; [ DW_TAG_auto_variable ]
-!5 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ]
+!5 = metadata !{i32 458763, metadata !1, i32 1, i32 1}; [DW_TAG_lexical_block ]
!6 = metadata !{i32 458788, metadata !3, metadata !"int", metadata !3, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5}; [DW_TAG_base_type ]
!7 = metadata !{i32 6, i32 1, metadata !2, null}
diff --git a/test/CodeGen/X86/2009-10-19-atomic-cmp-eflags.ll b/test/CodeGen/X86/2009-10-19-atomic-cmp-eflags.ll
index d7f0c1a..006a02a 100644
--- a/test/CodeGen/X86/2009-10-19-atomic-cmp-eflags.ll
+++ b/test/CodeGen/X86/2009-10-19-atomic-cmp-eflags.ll
@@ -36,7 +36,7 @@ lt_init.exit: ; preds = %if.end.i, %if.then.
call void asm sideeffect "cpuid", "~{ax},~{bx},~{cx},~{dx},~{memory},~{dirflag},~{fpsr},~{flags}"() nounwind
%4 = call i64 @llvm.readcyclecounter() nounwind ; <i64> [#uses=1]
%5 = sub i64 %4, %2 ; <i64> [#uses=1]
- %6 = call i64 @llvm.atomic.load.add.i64.p0i64(i64* getelementptr inbounds ([1216 x i64]* @__profiling_callsite_timestamps_live, i32 0, i32 51), i64 %5) nounwind ; <i64> [#uses=0]
+ %6 = atomicrmw add i64* getelementptr inbounds ([1216 x i64]* @__profiling_callsite_timestamps_live, i32 0, i32 51), i64 %5 monotonic
;CHECK: lock
;CHECK-NEXT: {{xadd|addq}} %rdx, __profiling_callsite_timestamps_live
;CHECK-NEXT: cmpl $0,
@@ -54,7 +54,7 @@ if.end: ; preds = %if.then, %lt_init.e
tail call void asm sideeffect "cpuid", "~{ax},~{bx},~{cx},~{dx},~{memory},~{dirflag},~{fpsr},~{flags}"() nounwind
%8 = tail call i64 @llvm.readcyclecounter() nounwind ; <i64> [#uses=1]
%9 = sub i64 %8, %0 ; <i64> [#uses=1]
- %10 = call i64 @llvm.atomic.load.add.i64.p0i64(i64* getelementptr inbounds ([1216 x i64]* @__profiling_callsite_timestamps_live, i32 0, i32 50), i64 %9) ; <i64> [#uses=0]
+ %10 = atomicrmw add i64* getelementptr inbounds ([1216 x i64]* @__profiling_callsite_timestamps_live, i32 0, i32 50), i64 %9 monotonic
ret i32 %7
}
@@ -64,6 +64,4 @@ declare i32 @lt_dlinit()
declare i32 @warn_dlerror(i8*) nounwind
-declare i64 @llvm.atomic.load.add.i64.p0i64(i64* nocapture, i64) nounwind
-
declare i64 @llvm.readcyclecounter() nounwind
diff --git a/test/CodeGen/X86/2009-11-25-ImpDefBug.ll b/test/CodeGen/X86/2009-11-25-ImpDefBug.ll
index 7606c0e..396638f 100644
--- a/test/CodeGen/X86/2009-11-25-ImpDefBug.ll
+++ b/test/CodeGen/X86/2009-11-25-ImpDefBug.ll
@@ -46,6 +46,8 @@ bb1.i5: ; preds = %bb.i1
lpad: ; preds = %bb1.i.fragment.cl, %bb1.i.fragment, %bb5
%.SV10.phi807 = phi i8* [ undef, %bb1.i.fragment.cl ], [ undef, %bb1.i.fragment ], [ undef, %bb5 ] ; <i8*> [#uses=1]
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
%1 = load i8* %.SV10.phi807, align 8 ; <i8> [#uses=0]
br i1 undef, label %meshBB81.bbcl.disp, label %bb13.fragment.bbcl.disp
@@ -114,3 +116,5 @@ meshBB81.bbcl.disp: ; preds = %meshBB81.cl141, %me
i8 51, label %meshBB81.cl141
]
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/2010-01-08-Atomic64Bug.ll b/test/CodeGen/X86/2010-01-08-Atomic64Bug.ll
index c693636..8b55bd7 100644
--- a/test/CodeGen/X86/2010-01-08-Atomic64Bug.ll
+++ b/test/CodeGen/X86/2010-01-08-Atomic64Bug.ll
@@ -18,12 +18,6 @@ entry:
; CHECK: lock
; CHECK: cmpxchg8b
; CHECK: jne
- tail call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
- %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1) ; <i64> [#uses=0]
- tail call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
+ %0 = atomicrmw add i64* %p, i64 1 seq_cst
ret void
}
-
-declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
-
-declare i64 @llvm.atomic.load.add.i64.p0i64(i64* nocapture, i64) nounwind
diff --git a/test/CodeGen/X86/2010-04-06-SSEDomainFixCrash.ll b/test/CodeGen/X86/2010-04-06-SSEDomainFixCrash.ll
index ef1798d..864ebf1 100644
--- a/test/CodeGen/X86/2010-04-06-SSEDomainFixCrash.ll
+++ b/test/CodeGen/X86/2010-04-06-SSEDomainFixCrash.ll
@@ -60,5 +60,9 @@ bb92: ; preds = %entry
unreachable
lpad159: ; preds = %bb58
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/2010-04-30-LocalAlloc-LandingPad.ll b/test/CodeGen/X86/2010-04-30-LocalAlloc-LandingPad.ll
index 3738f80..7af58dc 100644
--- a/test/CodeGen/X86/2010-04-30-LocalAlloc-LandingPad.ll
+++ b/test/CodeGen/X86/2010-04-30-LocalAlloc-LandingPad.ll
@@ -84,8 +84,6 @@ cleanup.switch: ; preds = %invoke.cont5
]
cleanup.end: ; preds = %cleanup.switch
- %exc6 = call i8* @llvm.eh.exception() ; <i8*> [#uses=1]
- store i8* %exc6, i8** %_rethrow
store i32 2, i32* %cleanup.dst7
br label %finally
diff --git a/test/CodeGen/X86/2010-10-08-cmpxchg8b.ll b/test/CodeGen/X86/2010-10-08-cmpxchg8b.ll
index 40e7f01..0e4118a 100644
--- a/test/CodeGen/X86/2010-10-08-cmpxchg8b.ll
+++ b/test/CodeGen/X86/2010-10-08-cmpxchg8b.ll
@@ -18,11 +18,9 @@ entry:
loop:
; CHECK: lock
; CHECK-NEXT: cmpxchg8b
- %r = call i64 @llvm.atomic.cmp.swap.i64.p0i64(i64* %ptr, i64 0, i64 1)
+ %r = cmpxchg i64* %ptr, i64 0, i64 1 monotonic
%stored1 = icmp eq i64 %r, 0
br i1 %stored1, label %loop, label %continue
continue:
ret void
}
-
-declare i64 @llvm.atomic.cmp.swap.i64.p0i64(i64* nocapture, i64, i64) nounwind
diff --git a/test/CodeGen/X86/2011-05-31-movmsk.ll b/test/CodeGen/X86/2011-05-31-movmsk.ll
deleted file mode 100644
index 2b54d5c..0000000
--- a/test/CodeGen/X86/2011-05-31-movmsk.ll
+++ /dev/null
@@ -1,79 +0,0 @@
-; RUN: llc -mcpu=core2 < %s | FileCheck %s
-; ModuleID = '<stdin>'
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
-target triple = "x86_64-apple-macosx10.6.6"
-
-%0 = type { double }
-%union.anon = type { float }
-
-define i32 @double_signbit(double %d1) nounwind uwtable readnone ssp {
-entry:
- %__x.addr.i = alloca double, align 8
- %__u.i = alloca %0, align 8
- %0 = bitcast double* %__x.addr.i to i8*
- %1 = bitcast %0* %__u.i to i8*
- store double %d1, double* %__x.addr.i, align 8
- %__f.i = getelementptr inbounds %0* %__u.i, i64 0, i32 0
- store double %d1, double* %__f.i, align 8
- %tmp = bitcast double %d1 to i64
-; CHECK-NOT: shr
-; CHECK: movmskpd
-; CHECK-NEXT: and
- %tmp1 = lshr i64 %tmp, 63
- %shr.i = trunc i64 %tmp1 to i32
- ret i32 %shr.i
-}
-
-define i32 @double_add_signbit(double %d1, double %d2) nounwind uwtable readnone ssp {
-entry:
- %__x.addr.i = alloca double, align 8
- %__u.i = alloca %0, align 8
- %add = fadd double %d1, %d2
- %0 = bitcast double* %__x.addr.i to i8*
- %1 = bitcast %0* %__u.i to i8*
- store double %add, double* %__x.addr.i, align 8
- %__f.i = getelementptr inbounds %0* %__u.i, i64 0, i32 0
- store double %add, double* %__f.i, align 8
- %tmp = bitcast double %add to i64
-; CHECK-NOT: shr
-; CHECK: movmskpd
-; CHECK-NEXT: and
- %tmp1 = lshr i64 %tmp, 63
- %shr.i = trunc i64 %tmp1 to i32
- ret i32 %shr.i
-}
-
-define i32 @float_signbit(float %f1) nounwind uwtable readnone ssp {
-entry:
- %__x.addr.i = alloca float, align 4
- %__u.i = alloca %union.anon, align 4
- %0 = bitcast float* %__x.addr.i to i8*
- %1 = bitcast %union.anon* %__u.i to i8*
- store float %f1, float* %__x.addr.i, align 4
- %__f.i = getelementptr inbounds %union.anon* %__u.i, i64 0, i32 0
- store float %f1, float* %__f.i, align 4
- %2 = bitcast float %f1 to i32
-; CHECK-NOT: shr
-; CHECK: movmskps
-; CHECK-NEXT: and
- %shr.i = lshr i32 %2, 31
- ret i32 %shr.i
-}
-
-define i32 @float_add_signbit(float %f1, float %f2) nounwind uwtable readnone ssp {
-entry:
- %__x.addr.i = alloca float, align 4
- %__u.i = alloca %union.anon, align 4
- %add = fadd float %f1, %f2
- %0 = bitcast float* %__x.addr.i to i8*
- %1 = bitcast %union.anon* %__u.i to i8*
- store float %add, float* %__x.addr.i, align 4
- %__f.i = getelementptr inbounds %union.anon* %__u.i, i64 0, i32 0
- store float %add, float* %__f.i, align 4
- %2 = bitcast float %add to i32
-; CHECK-NOT: shr
-; CHECK: movmskps
-; CHECK-NEXT: and
- %shr.i = lshr i32 %2, 31
- ret i32 %shr.i
-}
diff --git a/test/CodeGen/X86/2011-08-23-PerformSubCombine128.ll b/test/CodeGen/X86/2011-08-23-PerformSubCombine128.ll
new file mode 100644
index 0000000..12171ac
--- /dev/null
+++ b/test/CodeGen/X86/2011-08-23-PerformSubCombine128.ll
@@ -0,0 +1,18 @@
+; RUN: llc -march=x86-64 -O2 < %s
+
+define void @test(i64 %add127.tr.i2686) {
+entry:
+ %conv143.i2687 = and i64 %add127.tr.i2686, 72057594037927935
+ %conv76.i2623 = zext i64 %conv143.i2687 to i128
+ %mul148.i2338 = mul i128 0, %conv76.i2623
+ %add149.i2339 = add i128 %mul148.i2338, 0
+ %add.i2303 = add i128 0, 170141183460469229370468033484042534912
+ %add6.i2270 = add i128 %add.i2303, 0
+ %sub58.i2271 = sub i128 %add6.i2270, %add149.i2339
+ %add71.i2272 = add i128 %sub58.i2271, 0
+ %add105.i2273 = add i128 %add71.i2272, 0
+ %add116.i2274 = add i128 %add105.i2273, 0
+ %shr124.i2277 = lshr i128 %add116.i2274, 56
+ %add116.tr.i2280 = trunc i128 %add116.i2274 to i64
+ ret void
+}
diff --git a/test/CodeGen/X86/2011-08-23-Trampoline.ll b/test/CodeGen/X86/2011-08-23-Trampoline.ll
new file mode 100644
index 0000000..7a5a0f8
--- /dev/null
+++ b/test/CodeGen/X86/2011-08-23-Trampoline.ll
@@ -0,0 +1,16 @@
+; RUN: llc < %s -march=x86
+; RUN: llc < %s -march=x86-64
+
+ %struct.FRAME.gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets = type { i32, i32, void (i32, i32)*, i8 (i32, i32)* }
+
+define fastcc i32 @gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets.5146(i64 %table.0.0, i64 %table.0.1, i32 %last, i32 %pos) {
+entry:
+ call void @llvm.init.trampoline( i8* null, i8* bitcast (void (%struct.FRAME.gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets*, i32, i32)* @gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets__move.5177 to i8*), i8* null ) ; <i8*> [#uses=0]
+ %tramp22 = call i8* @llvm.adjust.trampoline( i8* null)
+ unreachable
+}
+
+declare void @gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets__move.5177(%struct.FRAME.gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets* nest , i32, i32) nounwind
+
+declare void @llvm.init.trampoline(i8*, i8*, i8*) nounwind
+declare i8* @llvm.adjust.trampoline(i8*) nounwind
diff --git a/test/CodeGen/X86/2011-08-29-BlockConstant.ll b/test/CodeGen/X86/2011-08-29-BlockConstant.ll
new file mode 100644
index 0000000..83e4bcc
--- /dev/null
+++ b/test/CodeGen/X86/2011-08-29-BlockConstant.ll
@@ -0,0 +1,34 @@
+; RUN: llc -march=x86-64 < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@x = global [500 x i64] zeroinitializer, align 64 ; <[500 x i64]*>
+; CHECK: x:
+; CHECK: .zero 4000
+
+@y = global [63 x i64] [
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262,
+ i64 6799976246779207262, i64 6799976246779207262, i64 6799976246779207262],
+ align 64 ; <[63 x i64]*> 0x5e5e5e5e
+; CHECK: y:
+; CHECK: .zero 504,94
diff --git a/test/CodeGen/X86/2011-08-29-InitOrder.ll b/test/CodeGen/X86/2011-08-29-InitOrder.ll
new file mode 100644
index 0000000..72c79d2
--- /dev/null
+++ b/test/CodeGen/X86/2011-08-29-InitOrder.ll
@@ -0,0 +1,28 @@
+; RUN: llc < %s -mtriple=i386-linux-gnu | FileCheck %s --check-prefix=CHECK-DEFAULT
+; RUN: llc < %s -mtriple=i386-apple-darwin | FileCheck %s --check-prefix=CHECK-DARWIN
+; PR5329
+
+@llvm.global_ctors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 2000, void ()* @construct_2 }, { i32, void ()* } { i32 3000, void ()* @construct_3 }, { i32, void ()* } { i32 1000, void ()* @construct_1 }]
+; CHECK-DEFAULT: construct_3
+; CHECK-DEFAULT: construct_2
+; CHECK-DEFAULT: construct_1
+
+; CHECK-DARWIN: construct_1
+; CHECK-DARWIN: construct_2
+; CHECK-DARWIN: construct_3
+
+@llvm.global_dtors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 2000, void ()* @destruct_2 }, { i32, void ()* } { i32 1000, void ()* @destruct_1 }, { i32, void ()* } { i32 3000, void ()* @destruct_3 }]
+; CHECK-DEFAULT: destruct_3
+; CHECK-DEFAULT: destruct_2
+; CHECK-DEFAULT: destruct_1
+
+; CHECK-DARWIN: destruct_1
+; CHECK-DARWIN: destruct_2
+; CHECK-DARWIN: destruct_3
+
+declare void @construct_1()
+declare void @construct_2()
+declare void @construct_3()
+declare void @destruct_1()
+declare void @destruct_2()
+declare void @destruct_3()
diff --git a/test/CodeGen/X86/2011-09-14-valcoalesce.ll b/test/CodeGen/X86/2011-09-14-valcoalesce.ll
new file mode 100644
index 0000000..1068d1b
--- /dev/null
+++ b/test/CodeGen/X86/2011-09-14-valcoalesce.ll
@@ -0,0 +1,174 @@
+; RUN: llc < %s -march=x86 | FileCheck %s
+;
+; Test RegistersDefinedFromSameValue. We have multiple copies of the same vreg:
+; while.body85.i:
+; vreg1 = copy vreg2
+; vreg2 = add
+; critical edge from land.lhs.true.i -> if.end117.i:
+; vreg27 = vreg2
+; critical edge from land.lhs.true103.i -> if.end117.i:
+; vreg27 = vreg2
+; if.then108.i:
+; vreg27 = vreg1
+;
+; Prior to fixing PR10920 401.bzip miscompile, the coalescer would
+; consider vreg1 and vreg27 to be copies of the same value. It would
+; then remove one of the critical edge copes, which cannot safely be removed.
+;
+; CHECK: # %while.body85.i
+; CHECK-NOT: # %
+; CHECK-NOT: add
+; CHECK: movl %[[POSTR:e[abcdxi]+]], %[[PRER:e[abcdxi]+]]
+; CHECK: addl %{{.*}}, %[[POSTR]]
+; CHECK: # %while.end.i
+; CHECK: movl %[[POSTR]], %[[USER:e[abcdxi]+]]
+; CHECK: # %land.lhs.true.i
+; CHECK: movl %[[POSTR]], %[[USER]]
+; CHECK: # %land.lhs.true103.i
+; CHECK: movl %[[POSTR]], %[[USER]]
+; CHECK: # %if.then108.i
+; [[PRER] live out, so nothing on this path should define it.
+; CHECK-NOT: , %[[PRER]]
+; CHECK: # %if.end117.i
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
+
+@.str3 = external unnamed_addr constant [59 x i8], align 1
+
+define void @BZ2_compressBlock() nounwind ssp {
+entry:
+ br i1 undef, label %if.then68, label %if.end85
+
+if.then68: ; preds = %entry
+ br label %for.body.i.i
+
+for.body.i.i: ; preds = %for.inc.i.i, %if.then68
+ br i1 undef, label %for.inc.i.i, label %if.then.i.i
+
+if.then.i.i: ; preds = %for.body.i.i
+ br label %for.inc.i.i
+
+for.inc.i.i: ; preds = %if.then.i.i, %for.body.i.i
+ br i1 undef, label %makeMaps_e.exit.i, label %for.body.i.i
+
+makeMaps_e.exit.i: ; preds = %for.inc.i.i
+ br i1 undef, label %for.cond19.preheader.i, label %for.cond.for.cond19.preheader_crit_edge.i
+
+for.cond.for.cond19.preheader_crit_edge.i: ; preds = %makeMaps_e.exit.i
+ unreachable
+
+for.cond19.preheader.i: ; preds = %makeMaps_e.exit.i
+ br i1 undef, label %for.body25.lr.ph.i, label %for.cond33.preheader.i
+
+for.body25.lr.ph.i: ; preds = %for.cond19.preheader.i
+ br label %for.body25.i
+
+for.cond33.preheader.i: ; preds = %for.body25.i, %for.cond19.preheader.i
+ br i1 undef, label %if.then.i, label %if.end.i
+
+for.body25.i: ; preds = %for.body25.i, %for.body25.lr.ph.i
+ br i1 undef, label %for.body25.i, label %for.cond33.preheader.i
+
+if.then.i: ; preds = %for.cond33.preheader.i
+ br label %if.end.i
+
+if.end.i: ; preds = %if.then.i, %for.cond33.preheader.i
+ br i1 undef, label %for.inc27.us.5.i, label %for.end30.i
+
+for.end30.i: ; preds = %for.inc27.us.5.i, %if.end.i
+ br i1 undef, label %if.end36.i, label %if.then35.i
+
+if.then35.i: ; preds = %for.end30.i
+ unreachable
+
+if.end36.i: ; preds = %for.end30.i
+ %sub83.i = add nsw i32 undef, 1
+ br label %while.body.i188
+
+for.cond182.preheader.i: ; preds = %for.end173.i
+ br i1 undef, label %for.inc220.us.i, label %while.body300.preheader.i
+
+while.body.i188: ; preds = %for.end173.i, %if.end36.i
+ %gs.0526.i = phi i32 [ 0, %if.end36.i ], [ %add177.i, %for.end173.i ]
+ %or.cond514517.i = and i1 false, undef
+ br i1 %or.cond514517.i, label %while.body85.i, label %if.end117.i
+
+while.body85.i: ; preds = %while.body85.i, %while.body.i188
+ %aFreq.0518.i = phi i32 [ %add93.i, %while.body85.i ], [ 0, %while.body.i188 ]
+ %inc87.i = add nsw i32 0, 1
+ %tmp91.i = load i32* undef, align 4, !tbaa !0
+ %add93.i = add nsw i32 %tmp91.i, %aFreq.0518.i
+ %or.cond514.i = and i1 undef, false
+ br i1 %or.cond514.i, label %while.body85.i, label %while.end.i
+
+while.end.i: ; preds = %while.body85.i
+ br i1 undef, label %land.lhs.true.i, label %if.end117.i
+
+land.lhs.true.i: ; preds = %while.end.i
+ br i1 undef, label %land.lhs.true103.i, label %if.end117.i
+
+land.lhs.true103.i: ; preds = %land.lhs.true.i
+ br i1 undef, label %if.then108.i, label %if.end117.i
+
+if.then108.i: ; preds = %land.lhs.true103.i
+ br label %if.end117.i
+
+if.end117.i: ; preds = %if.then108.i, %land.lhs.true103.i, %land.lhs.true.i, %while.end.i, %while.body.i188
+ %aFreq.1.i = phi i32 [ %aFreq.0518.i, %if.then108.i ], [ %add93.i, %land.lhs.true103.i ], [ %add93.i, %land.lhs.true.i ], [ %add93.i, %while.end.i ], [ 0, %while.body.i188 ]
+ %ge.1.i = phi i32 [ 0, %if.then108.i ], [ %inc87.i, %land.lhs.true103.i ], [ %inc87.i, %land.lhs.true.i ], [ %inc87.i, %while.end.i ], [ 0, %while.body.i188 ]
+ br i1 undef, label %if.then122.i, label %for.cond138.preheader.i
+
+if.then122.i: ; preds = %if.end117.i
+ call void (...)* @fprintf(i32 undef, i32 %gs.0526.i, i32 %ge.1.i, i32 %aFreq.1.i, double undef) nounwind
+ br label %for.cond138.preheader.i
+
+for.cond138.preheader.i: ; preds = %if.then122.i, %if.end117.i
+ br i1 undef, label %for.body143.lr.ph.i, label %for.end173.i
+
+for.body143.lr.ph.i: ; preds = %for.cond138.preheader.i
+ br label %for.body143.i
+
+for.body143.i: ; preds = %for.body143.i, %for.body143.lr.ph.i
+ br i1 undef, label %for.end173.i, label %for.body143.i
+
+for.end173.i: ; preds = %for.body143.i, %for.cond138.preheader.i
+ %add177.i = add nsw i32 %ge.1.i, 1
+ %cmp73.i = icmp sgt i32 undef, 0
+ br i1 %cmp73.i, label %while.body.i188, label %for.cond182.preheader.i
+
+for.inc220.us.i: ; preds = %for.cond182.preheader.i
+ unreachable
+
+while.body300.preheader.i: ; preds = %for.cond182.preheader.i
+ br i1 undef, label %for.end335.i, label %while.end2742.i
+
+for.end335.i: ; preds = %for.end2039.i, %while.body300.preheader.i
+ br label %for.body2021.i
+
+for.body2021.i: ; preds = %for.body2021.i, %for.end335.i
+ br i1 undef, label %for.body2021.i, label %for.end2039.i
+
+for.end2039.i: ; preds = %for.body2021.i
+ br label %for.end335.i
+
+while.end2742.i: ; preds = %while.body300.preheader.i
+ br i1 undef, label %if.then2748.i, label %for.body2778.i
+
+if.then2748.i: ; preds = %while.end2742.i
+ unreachable
+
+for.body2778.i: ; preds = %while.end2742.i
+ unreachable
+
+for.inc27.us.5.i: ; preds = %if.end.i
+ br label %for.end30.i
+
+if.end85: ; preds = %entry
+ ret void
+}
+
+declare void @fprintf(...) nounwind
+
+!0 = metadata !{metadata !"int", metadata !1}
+!1 = metadata !{metadata !"omnipotent char", metadata !2}
+!2 = metadata !{metadata !"Simple C/C++ TBAA", null}
diff --git a/test/CodeGen/X86/2011-09-18-sse2cmp.ll b/test/CodeGen/X86/2011-09-18-sse2cmp.ll
new file mode 100644
index 0000000..844d674
--- /dev/null
+++ b/test/CodeGen/X86/2011-09-18-sse2cmp.ll
@@ -0,0 +1,12 @@
+;RUN: llc < %s -march=x86 -mcpu=yonah -promote-elements -mattr=+sse2,-sse41 | FileCheck %s
+
+;CHECK: @max
+;CHECK: cmplepd
+;CHECK: ret
+
+define <2 x double> @max(<2 x double> %x, <2 x double> %y) {
+ %max_is_x = fcmp oge <2 x double> %x, %y
+ %max = select <2 x i1> %max_is_x, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %max
+}
+
diff --git a/test/CodeGen/X86/2011-09-21-setcc-bug.ll b/test/CodeGen/X86/2011-09-21-setcc-bug.ll
new file mode 100644
index 0000000..ed5649c
--- /dev/null
+++ b/test/CodeGen/X86/2011-09-21-setcc-bug.ll
@@ -0,0 +1,27 @@
+; RUN: llc < %s -march=x86-64 -mcpu=corei7 -promote-elements -mattr=+sse41
+
+; Make sure we are not crashing on this code.
+
+define void @load_4_i8(<4 x i8>* %k, <4 x i8>* %y, <4 x double>* %A1, <4 x double>* %A0) {
+ %A = load <4 x i8>* %k
+ %B = load <4 x i8>* %y
+ %C = load <4 x double>* %A0
+ %D= load <4 x double>* %A1
+ %M = icmp uge <4 x i8> %A, %B
+ %T = select <4 x i1> %M, <4 x double> %C, <4 x double> %D
+ store <4 x double> %T, <4 x double>* undef
+ ret void
+}
+
+
+define void @load_256_i8(<256 x i8>* %k, <256 x i8>* %y, <256 x double>* %A1, <256 x double>* %A0) {
+ %A = load <256 x i8>* %k
+ %B = load <256 x i8>* %y
+ %C = load <256 x double>* %A0
+ %D= load <256 x double>* %A1
+ %M = icmp uge <256 x i8> %A, %B
+ %T = select <256 x i1> %M, <256 x double> %C, <256 x double> %D
+ store <256 x double> %T, <256 x double>* undef
+ ret void
+}
+
diff --git a/test/CodeGen/X86/2011-10-11-SpillDead.ll b/test/CodeGen/X86/2011-10-11-SpillDead.ll
new file mode 100644
index 0000000..8e70d65
--- /dev/null
+++ b/test/CodeGen/X86/2011-10-11-SpillDead.ll
@@ -0,0 +1,19 @@
+; RUN: llc < %s -verify-regalloc
+; PR11125
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.7"
+
+; The inline asm takes %x as a GR32_ABCD virtual register.
+; The call to @g forces a spill of that register.
+;
+; The asm has a dead output tied to %x.
+; Verify that the spiller creates a value number for that dead def.
+;
+define void @f(i32 %x) nounwind uwtable ssp {
+entry:
+ tail call void @g() nounwind
+ %0 = tail call i32 asm sideeffect "foo $0", "=Q,0,~{ebx},~{dirflag},~{fpsr},~{flags}"(i32 %x) nounwind
+ ret void
+}
+
+declare void @g()
diff --git a/test/CodeGen/X86/2011-10-11-srl.ll b/test/CodeGen/X86/2011-10-11-srl.ll
new file mode 100644
index 0000000..cf9d36f
--- /dev/null
+++ b/test/CodeGen/X86/2011-10-11-srl.ll
@@ -0,0 +1,11 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -promote-elements -mattr=-sse41
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @m387(<2 x i8>* %p, <2 x i16>* %q) {
+ %t = load <2 x i8>* %p
+ %r = sext <2 x i8> %t to <2 x i16>
+ store <2 x i16> %r, <2 x i16>* %q
+ ret void
+}
+
diff --git a/test/CodeGen/X86/2011-10-12-MachineCSE.ll b/test/CodeGen/X86/2011-10-12-MachineCSE.ll
new file mode 100644
index 0000000..cd15f84
--- /dev/null
+++ b/test/CodeGen/X86/2011-10-12-MachineCSE.ll
@@ -0,0 +1,116 @@
+; RUN: llc -verify-machineinstrs < %s
+; <rdar://problem/10270968>
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.7.2"
+
+%struct.optab = type { i32, [59 x %struct.anon.3] }
+%struct.anon.3 = type { i32, %struct.rtx_def* }
+%struct.rtx_def = type { [2 x i8], i8, i8, [1 x %union.rtunion_def] }
+%union.rtunion_def = type { i64 }
+%struct.insn_data = type { i8*, i8*, %struct.rtx_def* (%struct.rtx_def*, ...)*, %struct.insn_operand_data*, i8, i8, i8, i8 }
+%struct.insn_operand_data = type { i32 (%struct.rtx_def*, i32)*, i8*, [2 x i8], i8, i8 }
+
+@optab_table = external global [49 x %struct.optab*], align 16
+@insn_data = external constant [0 x %struct.insn_data]
+
+define %struct.rtx_def* @gen_add3_insn(%struct.rtx_def* %r0, %struct.rtx_def* %r1, %struct.rtx_def* %c) nounwind uwtable ssp {
+entry:
+ %0 = bitcast %struct.rtx_def* %r0 to i32*
+ %1 = load i32* %0, align 8
+ %2 = lshr i32 %1, 16
+ %bf.clear = and i32 %2, 255
+ %idxprom = sext i32 %bf.clear to i64
+ %3 = load %struct.optab** getelementptr inbounds ([49 x %struct.optab*]* @optab_table, i32 0, i64 0), align 8, !tbaa !0
+ %handlers = getelementptr inbounds %struct.optab* %3, i32 0, i32 1
+ %arrayidx = getelementptr inbounds [59 x %struct.anon.3]* %handlers, i32 0, i64 %idxprom
+ %insn_code = getelementptr inbounds %struct.anon.3* %arrayidx, i32 0, i32 0
+ %4 = load i32* %insn_code, align 4, !tbaa !3
+ %cmp = icmp eq i32 %4, 1317
+ br i1 %cmp, label %if.then, label %lor.lhs.false
+
+lor.lhs.false: ; preds = %entry
+ %idxprom1 = sext i32 %4 to i64
+ %arrayidx2 = getelementptr inbounds [0 x %struct.insn_data]* @insn_data, i32 0, i64 %idxprom1
+ %operand = getelementptr inbounds %struct.insn_data* %arrayidx2, i32 0, i32 3
+ %5 = load %struct.insn_operand_data** %operand, align 8, !tbaa !0
+ %arrayidx3 = getelementptr inbounds %struct.insn_operand_data* %5, i64 0
+ %predicate = getelementptr inbounds %struct.insn_operand_data* %arrayidx3, i32 0, i32 0
+ %6 = load i32 (%struct.rtx_def*, i32)** %predicate, align 8, !tbaa !0
+ %idxprom4 = sext i32 %4 to i64
+ %arrayidx5 = getelementptr inbounds [0 x %struct.insn_data]* @insn_data, i32 0, i64 %idxprom4
+ %operand6 = getelementptr inbounds %struct.insn_data* %arrayidx5, i32 0, i32 3
+ %7 = load %struct.insn_operand_data** %operand6, align 8, !tbaa !0
+ %arrayidx7 = getelementptr inbounds %struct.insn_operand_data* %7, i64 0
+ %8 = bitcast %struct.insn_operand_data* %arrayidx7 to i8*
+ %bf.field.offs = getelementptr i8* %8, i32 16
+ %9 = bitcast i8* %bf.field.offs to i32*
+ %10 = load i32* %9, align 8
+ %bf.clear8 = and i32 %10, 65535
+ %call = tail call i32 %6(%struct.rtx_def* %r0, i32 %bf.clear8)
+ %tobool = icmp ne i32 %call, 0
+ br i1 %tobool, label %lor.lhs.false9, label %if.then
+
+lor.lhs.false9: ; preds = %lor.lhs.false
+ %idxprom10 = sext i32 %4 to i64
+ %arrayidx11 = getelementptr inbounds [0 x %struct.insn_data]* @insn_data, i32 0, i64 %idxprom10
+ %operand12 = getelementptr inbounds %struct.insn_data* %arrayidx11, i32 0, i32 3
+ %11 = load %struct.insn_operand_data** %operand12, align 8, !tbaa !0
+ %arrayidx13 = getelementptr inbounds %struct.insn_operand_data* %11, i64 1
+ %predicate14 = getelementptr inbounds %struct.insn_operand_data* %arrayidx13, i32 0, i32 0
+ %12 = load i32 (%struct.rtx_def*, i32)** %predicate14, align 8, !tbaa !0
+ %idxprom15 = sext i32 %4 to i64
+ %arrayidx16 = getelementptr inbounds [0 x %struct.insn_data]* @insn_data, i32 0, i64 %idxprom15
+ %operand17 = getelementptr inbounds %struct.insn_data* %arrayidx16, i32 0, i32 3
+ %13 = load %struct.insn_operand_data** %operand17, align 8, !tbaa !0
+ %arrayidx18 = getelementptr inbounds %struct.insn_operand_data* %13, i64 1
+ %14 = bitcast %struct.insn_operand_data* %arrayidx18 to i8*
+ %bf.field.offs19 = getelementptr i8* %14, i32 16
+ %15 = bitcast i8* %bf.field.offs19 to i32*
+ %16 = load i32* %15, align 8
+ %bf.clear20 = and i32 %16, 65535
+ %call21 = tail call i32 %12(%struct.rtx_def* %r1, i32 %bf.clear20)
+ %tobool22 = icmp ne i32 %call21, 0
+ br i1 %tobool22, label %lor.lhs.false23, label %if.then
+
+lor.lhs.false23: ; preds = %lor.lhs.false9
+ %idxprom24 = sext i32 %4 to i64
+ %arrayidx25 = getelementptr inbounds [0 x %struct.insn_data]* @insn_data, i32 0, i64 %idxprom24
+ %operand26 = getelementptr inbounds %struct.insn_data* %arrayidx25, i32 0, i32 3
+ %17 = load %struct.insn_operand_data** %operand26, align 8, !tbaa !0
+ %arrayidx27 = getelementptr inbounds %struct.insn_operand_data* %17, i64 2
+ %predicate28 = getelementptr inbounds %struct.insn_operand_data* %arrayidx27, i32 0, i32 0
+ %18 = load i32 (%struct.rtx_def*, i32)** %predicate28, align 8, !tbaa !0
+ %idxprom29 = sext i32 %4 to i64
+ %arrayidx30 = getelementptr inbounds [0 x %struct.insn_data]* @insn_data, i32 0, i64 %idxprom29
+ %operand31 = getelementptr inbounds %struct.insn_data* %arrayidx30, i32 0, i32 3
+ %19 = load %struct.insn_operand_data** %operand31, align 8, !tbaa !0
+ %arrayidx32 = getelementptr inbounds %struct.insn_operand_data* %19, i64 2
+ %20 = bitcast %struct.insn_operand_data* %arrayidx32 to i8*
+ %bf.field.offs33 = getelementptr i8* %20, i32 16
+ %21 = bitcast i8* %bf.field.offs33 to i32*
+ %22 = load i32* %21, align 8
+ %bf.clear34 = and i32 %22, 65535
+ %call35 = tail call i32 %18(%struct.rtx_def* %c, i32 %bf.clear34)
+ %tobool36 = icmp ne i32 %call35, 0
+ br i1 %tobool36, label %if.end, label %if.then
+
+if.then: ; preds = %lor.lhs.false23, %lor.lhs.false9, %lor.lhs.false, %entry
+ br label %return
+
+if.end: ; preds = %lor.lhs.false23
+ %idxprom37 = sext i32 %4 to i64
+ %arrayidx38 = getelementptr inbounds [0 x %struct.insn_data]* @insn_data, i32 0, i64 %idxprom37
+ %genfun = getelementptr inbounds %struct.insn_data* %arrayidx38, i32 0, i32 2
+ %23 = load %struct.rtx_def* (%struct.rtx_def*, ...)** %genfun, align 8, !tbaa !0
+ %call39 = tail call %struct.rtx_def* (%struct.rtx_def*, ...)* %23(%struct.rtx_def* %r0, %struct.rtx_def* %r1, %struct.rtx_def* %c)
+ br label %return
+
+return: ; preds = %if.end, %if.then
+ %24 = phi %struct.rtx_def* [ %call39, %if.end ], [ null, %if.then ]
+ ret %struct.rtx_def* %24
+}
+
+!0 = metadata !{metadata !"any pointer", metadata !1}
+!1 = metadata !{metadata !"omnipotent char", metadata !2}
+!2 = metadata !{metadata !"Simple C/C++ TBAA", null}
+!3 = metadata !{metadata !"_ZTS9insn_code", metadata !1}
diff --git a/test/CodeGen/X86/Atomics-32.ll b/test/CodeGen/X86/Atomics-32.ll
deleted file mode 100644
index 0e9b73e..0000000
--- a/test/CodeGen/X86/Atomics-32.ll
+++ /dev/null
@@ -1,818 +0,0 @@
-; RUN: llc < %s -march=x86 > %t
-;; Note the 64-bit variants are not supported yet (in 32-bit mode).
-; ModuleID = 'Atomics.c'
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
-target triple = "i386-apple-darwin8"
-@sc = common global i8 0 ; <i8*> [#uses=52]
-@uc = common global i8 0 ; <i8*> [#uses=100]
-@ss = common global i16 0 ; <i16*> [#uses=15]
-@us = common global i16 0 ; <i16*> [#uses=15]
-@si = common global i32 0 ; <i32*> [#uses=15]
-@ui = common global i32 0 ; <i32*> [#uses=23]
-@sl = common global i32 0 ; <i32*> [#uses=15]
-@ul = common global i32 0 ; <i32*> [#uses=15]
-
-define void @test_op_ignore() nounwind {
-entry:
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:0 [#uses=0]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:1 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %2, i16 1 ) ; <i16>:3 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %4, i16 1 ) ; <i16>:5 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %6, i32 1 ) ; <i32>:7 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %8, i32 1 ) ; <i32>:9 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:10 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %10, i32 1 ) ; <i32>:11 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:12 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %12, i32 1 ) ; <i32>:13 [#uses=0]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:14 [#uses=0]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:15 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:16 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %16, i16 1 ) ; <i16>:17 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:18 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %18, i16 1 ) ; <i16>:19 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:20 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %20, i32 1 ) ; <i32>:21 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:22 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %22, i32 1 ) ; <i32>:23 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:24 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %24, i32 1 ) ; <i32>:25 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:26 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %26, i32 1 ) ; <i32>:27 [#uses=0]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:28 [#uses=0]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:29 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:30 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %30, i16 1 ) ; <i16>:31 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:32 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %32, i16 1 ) ; <i16>:33 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:34 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %34, i32 1 ) ; <i32>:35 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:36 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %36, i32 1 ) ; <i32>:37 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:38 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %38, i32 1 ) ; <i32>:39 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:40 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %40, i32 1 ) ; <i32>:41 [#uses=0]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:42 [#uses=0]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:43 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:44 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %44, i16 1 ) ; <i16>:45 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:46 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %46, i16 1 ) ; <i16>:47 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:48 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %48, i32 1 ) ; <i32>:49 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:50 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %50, i32 1 ) ; <i32>:51 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:52 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %52, i32 1 ) ; <i32>:53 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:54 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %54, i32 1 ) ; <i32>:55 [#uses=0]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:56 [#uses=0]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:57 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:58 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %58, i16 1 ) ; <i16>:59 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:60 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %60, i16 1 ) ; <i16>:61 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:62 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %62, i32 1 ) ; <i32>:63 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:64 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %64, i32 1 ) ; <i32>:65 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:66 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %66, i32 1 ) ; <i32>:67 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:68 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %68, i32 1 ) ; <i32>:69 [#uses=0]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:70 [#uses=0]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:71 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:72 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %72, i16 1 ) ; <i16>:73 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:74 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %74, i16 1 ) ; <i16>:75 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:76 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %76, i32 1 ) ; <i32>:77 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:78 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %78, i32 1 ) ; <i32>:79 [#uses=0]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:80 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %80, i32 1 ) ; <i32>:81 [#uses=0]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:82 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %82, i32 1 ) ; <i32>:83 [#uses=0]
- br label %return
-
-return: ; preds = %entry
- ret void
-}
-
-declare i8 @llvm.atomic.load.add.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.add.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.add.i32.p0i32(i32*, i32) nounwind
-
-declare i8 @llvm.atomic.load.sub.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.sub.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.sub.i32.p0i32(i32*, i32) nounwind
-
-declare i8 @llvm.atomic.load.or.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.or.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.or.i32.p0i32(i32*, i32) nounwind
-
-declare i8 @llvm.atomic.load.xor.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.xor.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.xor.i32.p0i32(i32*, i32) nounwind
-
-declare i8 @llvm.atomic.load.and.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.and.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.and.i32.p0i32(i32*, i32) nounwind
-
-declare i8 @llvm.atomic.load.nand.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.nand.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.nand.i32.p0i32(i32*, i32) nounwind
-
-define void @test_fetch_and_op() nounwind {
-entry:
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:0 [#uses=1]
- store i8 %0, i8* @sc, align 1
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:1 [#uses=1]
- store i8 %1, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %2, i16 11 ) ; <i16>:3 [#uses=1]
- store i16 %3, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %4, i16 11 ) ; <i16>:5 [#uses=1]
- store i16 %5, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %6, i32 11 ) ; <i32>:7 [#uses=1]
- store i32 %7, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %8, i32 11 ) ; <i32>:9 [#uses=1]
- store i32 %9, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:10 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %10, i32 11 ) ; <i32>:11 [#uses=1]
- store i32 %11, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:12 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %12, i32 11 ) ; <i32>:13 [#uses=1]
- store i32 %13, i32* @ul, align 4
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:14 [#uses=1]
- store i8 %14, i8* @sc, align 1
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:15 [#uses=1]
- store i8 %15, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:16 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %16, i16 11 ) ; <i16>:17 [#uses=1]
- store i16 %17, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:18 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %18, i16 11 ) ; <i16>:19 [#uses=1]
- store i16 %19, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:20 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %20, i32 11 ) ; <i32>:21 [#uses=1]
- store i32 %21, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:22 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %22, i32 11 ) ; <i32>:23 [#uses=1]
- store i32 %23, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:24 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %24, i32 11 ) ; <i32>:25 [#uses=1]
- store i32 %25, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:26 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %26, i32 11 ) ; <i32>:27 [#uses=1]
- store i32 %27, i32* @ul, align 4
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:28 [#uses=1]
- store i8 %28, i8* @sc, align 1
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:29 [#uses=1]
- store i8 %29, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:30 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %30, i16 11 ) ; <i16>:31 [#uses=1]
- store i16 %31, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:32 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %32, i16 11 ) ; <i16>:33 [#uses=1]
- store i16 %33, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:34 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %34, i32 11 ) ; <i32>:35 [#uses=1]
- store i32 %35, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:36 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %36, i32 11 ) ; <i32>:37 [#uses=1]
- store i32 %37, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:38 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %38, i32 11 ) ; <i32>:39 [#uses=1]
- store i32 %39, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:40 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %40, i32 11 ) ; <i32>:41 [#uses=1]
- store i32 %41, i32* @ul, align 4
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:42 [#uses=1]
- store i8 %42, i8* @sc, align 1
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:43 [#uses=1]
- store i8 %43, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:44 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %44, i16 11 ) ; <i16>:45 [#uses=1]
- store i16 %45, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:46 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %46, i16 11 ) ; <i16>:47 [#uses=1]
- store i16 %47, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:48 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %48, i32 11 ) ; <i32>:49 [#uses=1]
- store i32 %49, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:50 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %50, i32 11 ) ; <i32>:51 [#uses=1]
- store i32 %51, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:52 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %52, i32 11 ) ; <i32>:53 [#uses=1]
- store i32 %53, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:54 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %54, i32 11 ) ; <i32>:55 [#uses=1]
- store i32 %55, i32* @ul, align 4
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:56 [#uses=1]
- store i8 %56, i8* @sc, align 1
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:57 [#uses=1]
- store i8 %57, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:58 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %58, i16 11 ) ; <i16>:59 [#uses=1]
- store i16 %59, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:60 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %60, i16 11 ) ; <i16>:61 [#uses=1]
- store i16 %61, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:62 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %62, i32 11 ) ; <i32>:63 [#uses=1]
- store i32 %63, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:64 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %64, i32 11 ) ; <i32>:65 [#uses=1]
- store i32 %65, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:66 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %66, i32 11 ) ; <i32>:67 [#uses=1]
- store i32 %67, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:68 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %68, i32 11 ) ; <i32>:69 [#uses=1]
- store i32 %69, i32* @ul, align 4
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:70 [#uses=1]
- store i8 %70, i8* @sc, align 1
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:71 [#uses=1]
- store i8 %71, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:72 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %72, i16 11 ) ; <i16>:73 [#uses=1]
- store i16 %73, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:74 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %74, i16 11 ) ; <i16>:75 [#uses=1]
- store i16 %75, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:76 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %76, i32 11 ) ; <i32>:77 [#uses=1]
- store i32 %77, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:78 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %78, i32 11 ) ; <i32>:79 [#uses=1]
- store i32 %79, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:80 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %80, i32 11 ) ; <i32>:81 [#uses=1]
- store i32 %81, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:82 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %82, i32 11 ) ; <i32>:83 [#uses=1]
- store i32 %83, i32* @ul, align 4
- br label %return
-
-return: ; preds = %entry
- ret void
-}
-
-define void @test_op_and_fetch() nounwind {
-entry:
- load i8* @uc, align 1 ; <i8>:0 [#uses=1]
- zext i8 %0 to i32 ; <i32>:1 [#uses=1]
- trunc i32 %1 to i8 ; <i8>:2 [#uses=2]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 %2 ) ; <i8>:3 [#uses=1]
- add i8 %3, %2 ; <i8>:4 [#uses=1]
- store i8 %4, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:5 [#uses=1]
- zext i8 %5 to i32 ; <i32>:6 [#uses=1]
- trunc i32 %6 to i8 ; <i8>:7 [#uses=2]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 %7 ) ; <i8>:8 [#uses=1]
- add i8 %8, %7 ; <i8>:9 [#uses=1]
- store i8 %9, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:10 [#uses=1]
- zext i8 %10 to i32 ; <i32>:11 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:12 [#uses=1]
- trunc i32 %11 to i16 ; <i16>:13 [#uses=2]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %12, i16 %13 ) ; <i16>:14 [#uses=1]
- add i16 %14, %13 ; <i16>:15 [#uses=1]
- store i16 %15, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:16 [#uses=1]
- zext i8 %16 to i32 ; <i32>:17 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:18 [#uses=1]
- trunc i32 %17 to i16 ; <i16>:19 [#uses=2]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %18, i16 %19 ) ; <i16>:20 [#uses=1]
- add i16 %20, %19 ; <i16>:21 [#uses=1]
- store i16 %21, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:22 [#uses=1]
- zext i8 %22 to i32 ; <i32>:23 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:24 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %24, i32 %23 ) ; <i32>:25 [#uses=1]
- add i32 %25, %23 ; <i32>:26 [#uses=1]
- store i32 %26, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:27 [#uses=1]
- zext i8 %27 to i32 ; <i32>:28 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:29 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %29, i32 %28 ) ; <i32>:30 [#uses=1]
- add i32 %30, %28 ; <i32>:31 [#uses=1]
- store i32 %31, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:32 [#uses=1]
- zext i8 %32 to i32 ; <i32>:33 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:34 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %34, i32 %33 ) ; <i32>:35 [#uses=1]
- add i32 %35, %33 ; <i32>:36 [#uses=1]
- store i32 %36, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:37 [#uses=1]
- zext i8 %37 to i32 ; <i32>:38 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:39 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %39, i32 %38 ) ; <i32>:40 [#uses=1]
- add i32 %40, %38 ; <i32>:41 [#uses=1]
- store i32 %41, i32* @ul, align 4
- load i8* @uc, align 1 ; <i8>:42 [#uses=1]
- zext i8 %42 to i32 ; <i32>:43 [#uses=1]
- trunc i32 %43 to i8 ; <i8>:44 [#uses=2]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 %44 ) ; <i8>:45 [#uses=1]
- sub i8 %45, %44 ; <i8>:46 [#uses=1]
- store i8 %46, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:47 [#uses=1]
- zext i8 %47 to i32 ; <i32>:48 [#uses=1]
- trunc i32 %48 to i8 ; <i8>:49 [#uses=2]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 %49 ) ; <i8>:50 [#uses=1]
- sub i8 %50, %49 ; <i8>:51 [#uses=1]
- store i8 %51, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:52 [#uses=1]
- zext i8 %52 to i32 ; <i32>:53 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:54 [#uses=1]
- trunc i32 %53 to i16 ; <i16>:55 [#uses=2]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %54, i16 %55 ) ; <i16>:56 [#uses=1]
- sub i16 %56, %55 ; <i16>:57 [#uses=1]
- store i16 %57, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:58 [#uses=1]
- zext i8 %58 to i32 ; <i32>:59 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:60 [#uses=1]
- trunc i32 %59 to i16 ; <i16>:61 [#uses=2]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %60, i16 %61 ) ; <i16>:62 [#uses=1]
- sub i16 %62, %61 ; <i16>:63 [#uses=1]
- store i16 %63, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:64 [#uses=1]
- zext i8 %64 to i32 ; <i32>:65 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:66 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %66, i32 %65 ) ; <i32>:67 [#uses=1]
- sub i32 %67, %65 ; <i32>:68 [#uses=1]
- store i32 %68, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:69 [#uses=1]
- zext i8 %69 to i32 ; <i32>:70 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:71 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %71, i32 %70 ) ; <i32>:72 [#uses=1]
- sub i32 %72, %70 ; <i32>:73 [#uses=1]
- store i32 %73, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:74 [#uses=1]
- zext i8 %74 to i32 ; <i32>:75 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:76 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %76, i32 %75 ) ; <i32>:77 [#uses=1]
- sub i32 %77, %75 ; <i32>:78 [#uses=1]
- store i32 %78, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:79 [#uses=1]
- zext i8 %79 to i32 ; <i32>:80 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:81 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %81, i32 %80 ) ; <i32>:82 [#uses=1]
- sub i32 %82, %80 ; <i32>:83 [#uses=1]
- store i32 %83, i32* @ul, align 4
- load i8* @uc, align 1 ; <i8>:84 [#uses=1]
- zext i8 %84 to i32 ; <i32>:85 [#uses=1]
- trunc i32 %85 to i8 ; <i8>:86 [#uses=2]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 %86 ) ; <i8>:87 [#uses=1]
- or i8 %87, %86 ; <i8>:88 [#uses=1]
- store i8 %88, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:89 [#uses=1]
- zext i8 %89 to i32 ; <i32>:90 [#uses=1]
- trunc i32 %90 to i8 ; <i8>:91 [#uses=2]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 %91 ) ; <i8>:92 [#uses=1]
- or i8 %92, %91 ; <i8>:93 [#uses=1]
- store i8 %93, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:94 [#uses=1]
- zext i8 %94 to i32 ; <i32>:95 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:96 [#uses=1]
- trunc i32 %95 to i16 ; <i16>:97 [#uses=2]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %96, i16 %97 ) ; <i16>:98 [#uses=1]
- or i16 %98, %97 ; <i16>:99 [#uses=1]
- store i16 %99, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:100 [#uses=1]
- zext i8 %100 to i32 ; <i32>:101 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:102 [#uses=1]
- trunc i32 %101 to i16 ; <i16>:103 [#uses=2]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %102, i16 %103 ) ; <i16>:104 [#uses=1]
- or i16 %104, %103 ; <i16>:105 [#uses=1]
- store i16 %105, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:106 [#uses=1]
- zext i8 %106 to i32 ; <i32>:107 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:108 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %108, i32 %107 ) ; <i32>:109 [#uses=1]
- or i32 %109, %107 ; <i32>:110 [#uses=1]
- store i32 %110, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:111 [#uses=1]
- zext i8 %111 to i32 ; <i32>:112 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:113 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %113, i32 %112 ) ; <i32>:114 [#uses=1]
- or i32 %114, %112 ; <i32>:115 [#uses=1]
- store i32 %115, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:116 [#uses=1]
- zext i8 %116 to i32 ; <i32>:117 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:118 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %118, i32 %117 ) ; <i32>:119 [#uses=1]
- or i32 %119, %117 ; <i32>:120 [#uses=1]
- store i32 %120, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:121 [#uses=1]
- zext i8 %121 to i32 ; <i32>:122 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:123 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %123, i32 %122 ) ; <i32>:124 [#uses=1]
- or i32 %124, %122 ; <i32>:125 [#uses=1]
- store i32 %125, i32* @ul, align 4
- load i8* @uc, align 1 ; <i8>:126 [#uses=1]
- zext i8 %126 to i32 ; <i32>:127 [#uses=1]
- trunc i32 %127 to i8 ; <i8>:128 [#uses=2]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 %128 ) ; <i8>:129 [#uses=1]
- xor i8 %129, %128 ; <i8>:130 [#uses=1]
- store i8 %130, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:131 [#uses=1]
- zext i8 %131 to i32 ; <i32>:132 [#uses=1]
- trunc i32 %132 to i8 ; <i8>:133 [#uses=2]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 %133 ) ; <i8>:134 [#uses=1]
- xor i8 %134, %133 ; <i8>:135 [#uses=1]
- store i8 %135, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:136 [#uses=1]
- zext i8 %136 to i32 ; <i32>:137 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:138 [#uses=1]
- trunc i32 %137 to i16 ; <i16>:139 [#uses=2]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %138, i16 %139 ) ; <i16>:140 [#uses=1]
- xor i16 %140, %139 ; <i16>:141 [#uses=1]
- store i16 %141, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:142 [#uses=1]
- zext i8 %142 to i32 ; <i32>:143 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:144 [#uses=1]
- trunc i32 %143 to i16 ; <i16>:145 [#uses=2]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %144, i16 %145 ) ; <i16>:146 [#uses=1]
- xor i16 %146, %145 ; <i16>:147 [#uses=1]
- store i16 %147, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:148 [#uses=1]
- zext i8 %148 to i32 ; <i32>:149 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:150 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %150, i32 %149 ) ; <i32>:151 [#uses=1]
- xor i32 %151, %149 ; <i32>:152 [#uses=1]
- store i32 %152, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:153 [#uses=1]
- zext i8 %153 to i32 ; <i32>:154 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:155 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %155, i32 %154 ) ; <i32>:156 [#uses=1]
- xor i32 %156, %154 ; <i32>:157 [#uses=1]
- store i32 %157, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:158 [#uses=1]
- zext i8 %158 to i32 ; <i32>:159 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:160 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %160, i32 %159 ) ; <i32>:161 [#uses=1]
- xor i32 %161, %159 ; <i32>:162 [#uses=1]
- store i32 %162, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:163 [#uses=1]
- zext i8 %163 to i32 ; <i32>:164 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:165 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %165, i32 %164 ) ; <i32>:166 [#uses=1]
- xor i32 %166, %164 ; <i32>:167 [#uses=1]
- store i32 %167, i32* @ul, align 4
- load i8* @uc, align 1 ; <i8>:168 [#uses=1]
- zext i8 %168 to i32 ; <i32>:169 [#uses=1]
- trunc i32 %169 to i8 ; <i8>:170 [#uses=2]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 %170 ) ; <i8>:171 [#uses=1]
- and i8 %171, %170 ; <i8>:172 [#uses=1]
- store i8 %172, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:173 [#uses=1]
- zext i8 %173 to i32 ; <i32>:174 [#uses=1]
- trunc i32 %174 to i8 ; <i8>:175 [#uses=2]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 %175 ) ; <i8>:176 [#uses=1]
- and i8 %176, %175 ; <i8>:177 [#uses=1]
- store i8 %177, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:178 [#uses=1]
- zext i8 %178 to i32 ; <i32>:179 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:180 [#uses=1]
- trunc i32 %179 to i16 ; <i16>:181 [#uses=2]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %180, i16 %181 ) ; <i16>:182 [#uses=1]
- and i16 %182, %181 ; <i16>:183 [#uses=1]
- store i16 %183, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:184 [#uses=1]
- zext i8 %184 to i32 ; <i32>:185 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:186 [#uses=1]
- trunc i32 %185 to i16 ; <i16>:187 [#uses=2]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %186, i16 %187 ) ; <i16>:188 [#uses=1]
- and i16 %188, %187 ; <i16>:189 [#uses=1]
- store i16 %189, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:190 [#uses=1]
- zext i8 %190 to i32 ; <i32>:191 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:192 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %192, i32 %191 ) ; <i32>:193 [#uses=1]
- and i32 %193, %191 ; <i32>:194 [#uses=1]
- store i32 %194, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:195 [#uses=1]
- zext i8 %195 to i32 ; <i32>:196 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:197 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %197, i32 %196 ) ; <i32>:198 [#uses=1]
- and i32 %198, %196 ; <i32>:199 [#uses=1]
- store i32 %199, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:200 [#uses=1]
- zext i8 %200 to i32 ; <i32>:201 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:202 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %202, i32 %201 ) ; <i32>:203 [#uses=1]
- and i32 %203, %201 ; <i32>:204 [#uses=1]
- store i32 %204, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:205 [#uses=1]
- zext i8 %205 to i32 ; <i32>:206 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:207 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %207, i32 %206 ) ; <i32>:208 [#uses=1]
- and i32 %208, %206 ; <i32>:209 [#uses=1]
- store i32 %209, i32* @ul, align 4
- load i8* @uc, align 1 ; <i8>:210 [#uses=1]
- zext i8 %210 to i32 ; <i32>:211 [#uses=1]
- trunc i32 %211 to i8 ; <i8>:212 [#uses=2]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 %212 ) ; <i8>:213 [#uses=1]
- xor i8 %213, -1 ; <i8>:214 [#uses=1]
- and i8 %214, %212 ; <i8>:215 [#uses=1]
- store i8 %215, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:216 [#uses=1]
- zext i8 %216 to i32 ; <i32>:217 [#uses=1]
- trunc i32 %217 to i8 ; <i8>:218 [#uses=2]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 %218 ) ; <i8>:219 [#uses=1]
- xor i8 %219, -1 ; <i8>:220 [#uses=1]
- and i8 %220, %218 ; <i8>:221 [#uses=1]
- store i8 %221, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:222 [#uses=1]
- zext i8 %222 to i32 ; <i32>:223 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:224 [#uses=1]
- trunc i32 %223 to i16 ; <i16>:225 [#uses=2]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %224, i16 %225 ) ; <i16>:226 [#uses=1]
- xor i16 %226, -1 ; <i16>:227 [#uses=1]
- and i16 %227, %225 ; <i16>:228 [#uses=1]
- store i16 %228, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:229 [#uses=1]
- zext i8 %229 to i32 ; <i32>:230 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:231 [#uses=1]
- trunc i32 %230 to i16 ; <i16>:232 [#uses=2]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %231, i16 %232 ) ; <i16>:233 [#uses=1]
- xor i16 %233, -1 ; <i16>:234 [#uses=1]
- and i16 %234, %232 ; <i16>:235 [#uses=1]
- store i16 %235, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:236 [#uses=1]
- zext i8 %236 to i32 ; <i32>:237 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:238 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %238, i32 %237 ) ; <i32>:239 [#uses=1]
- xor i32 %239, -1 ; <i32>:240 [#uses=1]
- and i32 %240, %237 ; <i32>:241 [#uses=1]
- store i32 %241, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:242 [#uses=1]
- zext i8 %242 to i32 ; <i32>:243 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:244 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %244, i32 %243 ) ; <i32>:245 [#uses=1]
- xor i32 %245, -1 ; <i32>:246 [#uses=1]
- and i32 %246, %243 ; <i32>:247 [#uses=1]
- store i32 %247, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:248 [#uses=1]
- zext i8 %248 to i32 ; <i32>:249 [#uses=2]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:250 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %250, i32 %249 ) ; <i32>:251 [#uses=1]
- xor i32 %251, -1 ; <i32>:252 [#uses=1]
- and i32 %252, %249 ; <i32>:253 [#uses=1]
- store i32 %253, i32* @sl, align 4
- load i8* @uc, align 1 ; <i8>:254 [#uses=1]
- zext i8 %254 to i32 ; <i32>:255 [#uses=2]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:256 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %256, i32 %255 ) ; <i32>:257 [#uses=1]
- xor i32 %257, -1 ; <i32>:258 [#uses=1]
- and i32 %258, %255 ; <i32>:259 [#uses=1]
- store i32 %259, i32* @ul, align 4
- br label %return
-
-return: ; preds = %entry
- ret void
-}
-
-define void @test_compare_and_swap() nounwind {
-entry:
- load i8* @sc, align 1 ; <i8>:0 [#uses=1]
- zext i8 %0 to i32 ; <i32>:1 [#uses=1]
- load i8* @uc, align 1 ; <i8>:2 [#uses=1]
- zext i8 %2 to i32 ; <i32>:3 [#uses=1]
- trunc i32 %3 to i8 ; <i8>:4 [#uses=1]
- trunc i32 %1 to i8 ; <i8>:5 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @sc, i8 %4, i8 %5 ) ; <i8>:6 [#uses=1]
- store i8 %6, i8* @sc, align 1
- load i8* @sc, align 1 ; <i8>:7 [#uses=1]
- zext i8 %7 to i32 ; <i32>:8 [#uses=1]
- load i8* @uc, align 1 ; <i8>:9 [#uses=1]
- zext i8 %9 to i32 ; <i32>:10 [#uses=1]
- trunc i32 %10 to i8 ; <i8>:11 [#uses=1]
- trunc i32 %8 to i8 ; <i8>:12 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @uc, i8 %11, i8 %12 ) ; <i8>:13 [#uses=1]
- store i8 %13, i8* @uc, align 1
- load i8* @sc, align 1 ; <i8>:14 [#uses=1]
- sext i8 %14 to i16 ; <i16>:15 [#uses=1]
- zext i16 %15 to i32 ; <i32>:16 [#uses=1]
- load i8* @uc, align 1 ; <i8>:17 [#uses=1]
- zext i8 %17 to i32 ; <i32>:18 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:19 [#uses=1]
- trunc i32 %18 to i16 ; <i16>:20 [#uses=1]
- trunc i32 %16 to i16 ; <i16>:21 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %19, i16 %20, i16 %21 ) ; <i16>:22 [#uses=1]
- store i16 %22, i16* @ss, align 2
- load i8* @sc, align 1 ; <i8>:23 [#uses=1]
- sext i8 %23 to i16 ; <i16>:24 [#uses=1]
- zext i16 %24 to i32 ; <i32>:25 [#uses=1]
- load i8* @uc, align 1 ; <i8>:26 [#uses=1]
- zext i8 %26 to i32 ; <i32>:27 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:28 [#uses=1]
- trunc i32 %27 to i16 ; <i16>:29 [#uses=1]
- trunc i32 %25 to i16 ; <i16>:30 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %28, i16 %29, i16 %30 ) ; <i16>:31 [#uses=1]
- store i16 %31, i16* @us, align 2
- load i8* @sc, align 1 ; <i8>:32 [#uses=1]
- sext i8 %32 to i32 ; <i32>:33 [#uses=1]
- load i8* @uc, align 1 ; <i8>:34 [#uses=1]
- zext i8 %34 to i32 ; <i32>:35 [#uses=1]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:36 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %36, i32 %35, i32 %33 ) ; <i32>:37 [#uses=1]
- store i32 %37, i32* @si, align 4
- load i8* @sc, align 1 ; <i8>:38 [#uses=1]
- sext i8 %38 to i32 ; <i32>:39 [#uses=1]
- load i8* @uc, align 1 ; <i8>:40 [#uses=1]
- zext i8 %40 to i32 ; <i32>:41 [#uses=1]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:42 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %42, i32 %41, i32 %39 ) ; <i32>:43 [#uses=1]
- store i32 %43, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:44 [#uses=1]
- sext i8 %44 to i32 ; <i32>:45 [#uses=1]
- load i8* @uc, align 1 ; <i8>:46 [#uses=1]
- zext i8 %46 to i32 ; <i32>:47 [#uses=1]
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:48 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %48, i32 %47, i32 %45 ) ; <i32>:49 [#uses=1]
- store i32 %49, i32* @sl, align 4
- load i8* @sc, align 1 ; <i8>:50 [#uses=1]
- sext i8 %50 to i32 ; <i32>:51 [#uses=1]
- load i8* @uc, align 1 ; <i8>:52 [#uses=1]
- zext i8 %52 to i32 ; <i32>:53 [#uses=1]
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:54 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %54, i32 %53, i32 %51 ) ; <i32>:55 [#uses=1]
- store i32 %55, i32* @ul, align 4
- load i8* @sc, align 1 ; <i8>:56 [#uses=1]
- zext i8 %56 to i32 ; <i32>:57 [#uses=1]
- load i8* @uc, align 1 ; <i8>:58 [#uses=1]
- zext i8 %58 to i32 ; <i32>:59 [#uses=1]
- trunc i32 %59 to i8 ; <i8>:60 [#uses=2]
- trunc i32 %57 to i8 ; <i8>:61 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @sc, i8 %60, i8 %61 ) ; <i8>:62 [#uses=1]
- icmp eq i8 %62, %60 ; <i1>:63 [#uses=1]
- zext i1 %63 to i8 ; <i8>:64 [#uses=1]
- zext i8 %64 to i32 ; <i32>:65 [#uses=1]
- store i32 %65, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:66 [#uses=1]
- zext i8 %66 to i32 ; <i32>:67 [#uses=1]
- load i8* @uc, align 1 ; <i8>:68 [#uses=1]
- zext i8 %68 to i32 ; <i32>:69 [#uses=1]
- trunc i32 %69 to i8 ; <i8>:70 [#uses=2]
- trunc i32 %67 to i8 ; <i8>:71 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @uc, i8 %70, i8 %71 ) ; <i8>:72 [#uses=1]
- icmp eq i8 %72, %70 ; <i1>:73 [#uses=1]
- zext i1 %73 to i8 ; <i8>:74 [#uses=1]
- zext i8 %74 to i32 ; <i32>:75 [#uses=1]
- store i32 %75, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:76 [#uses=1]
- sext i8 %76 to i16 ; <i16>:77 [#uses=1]
- zext i16 %77 to i32 ; <i32>:78 [#uses=1]
- load i8* @uc, align 1 ; <i8>:79 [#uses=1]
- zext i8 %79 to i32 ; <i32>:80 [#uses=1]
- trunc i32 %80 to i8 ; <i8>:81 [#uses=2]
- trunc i32 %78 to i8 ; <i8>:82 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i16* @ss to i8*), i8 %81, i8 %82 ) ; <i8>:83 [#uses=1]
- icmp eq i8 %83, %81 ; <i1>:84 [#uses=1]
- zext i1 %84 to i8 ; <i8>:85 [#uses=1]
- zext i8 %85 to i32 ; <i32>:86 [#uses=1]
- store i32 %86, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:87 [#uses=1]
- sext i8 %87 to i16 ; <i16>:88 [#uses=1]
- zext i16 %88 to i32 ; <i32>:89 [#uses=1]
- load i8* @uc, align 1 ; <i8>:90 [#uses=1]
- zext i8 %90 to i32 ; <i32>:91 [#uses=1]
- trunc i32 %91 to i8 ; <i8>:92 [#uses=2]
- trunc i32 %89 to i8 ; <i8>:93 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i16* @us to i8*), i8 %92, i8 %93 ) ; <i8>:94 [#uses=1]
- icmp eq i8 %94, %92 ; <i1>:95 [#uses=1]
- zext i1 %95 to i8 ; <i8>:96 [#uses=1]
- zext i8 %96 to i32 ; <i32>:97 [#uses=1]
- store i32 %97, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:98 [#uses=1]
- sext i8 %98 to i32 ; <i32>:99 [#uses=1]
- load i8* @uc, align 1 ; <i8>:100 [#uses=1]
- zext i8 %100 to i32 ; <i32>:101 [#uses=1]
- trunc i32 %101 to i8 ; <i8>:102 [#uses=2]
- trunc i32 %99 to i8 ; <i8>:103 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i32* @si to i8*), i8 %102, i8 %103 ) ; <i8>:104 [#uses=1]
- icmp eq i8 %104, %102 ; <i1>:105 [#uses=1]
- zext i1 %105 to i8 ; <i8>:106 [#uses=1]
- zext i8 %106 to i32 ; <i32>:107 [#uses=1]
- store i32 %107, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:108 [#uses=1]
- sext i8 %108 to i32 ; <i32>:109 [#uses=1]
- load i8* @uc, align 1 ; <i8>:110 [#uses=1]
- zext i8 %110 to i32 ; <i32>:111 [#uses=1]
- trunc i32 %111 to i8 ; <i8>:112 [#uses=2]
- trunc i32 %109 to i8 ; <i8>:113 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i32* @ui to i8*), i8 %112, i8 %113 ) ; <i8>:114 [#uses=1]
- icmp eq i8 %114, %112 ; <i1>:115 [#uses=1]
- zext i1 %115 to i8 ; <i8>:116 [#uses=1]
- zext i8 %116 to i32 ; <i32>:117 [#uses=1]
- store i32 %117, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:118 [#uses=1]
- sext i8 %118 to i32 ; <i32>:119 [#uses=1]
- load i8* @uc, align 1 ; <i8>:120 [#uses=1]
- zext i8 %120 to i32 ; <i32>:121 [#uses=1]
- trunc i32 %121 to i8 ; <i8>:122 [#uses=2]
- trunc i32 %119 to i8 ; <i8>:123 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i32* @sl to i8*), i8 %122, i8 %123 ) ; <i8>:124 [#uses=1]
- icmp eq i8 %124, %122 ; <i1>:125 [#uses=1]
- zext i1 %125 to i8 ; <i8>:126 [#uses=1]
- zext i8 %126 to i32 ; <i32>:127 [#uses=1]
- store i32 %127, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:128 [#uses=1]
- sext i8 %128 to i32 ; <i32>:129 [#uses=1]
- load i8* @uc, align 1 ; <i8>:130 [#uses=1]
- zext i8 %130 to i32 ; <i32>:131 [#uses=1]
- trunc i32 %131 to i8 ; <i8>:132 [#uses=2]
- trunc i32 %129 to i8 ; <i8>:133 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i32* @ul to i8*), i8 %132, i8 %133 ) ; <i8>:134 [#uses=1]
- icmp eq i8 %134, %132 ; <i1>:135 [#uses=1]
- zext i1 %135 to i8 ; <i8>:136 [#uses=1]
- zext i8 %136 to i32 ; <i32>:137 [#uses=1]
- store i32 %137, i32* @ui, align 4
- br label %return
-
-return: ; preds = %entry
- ret void
-}
-
-declare i8 @llvm.atomic.cmp.swap.i8.p0i8(i8*, i8, i8) nounwind
-
-declare i16 @llvm.atomic.cmp.swap.i16.p0i16(i16*, i16, i16) nounwind
-
-declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32*, i32, i32) nounwind
-
-define void @test_lock() nounwind {
-entry:
- call i8 @llvm.atomic.swap.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:0 [#uses=1]
- store i8 %0, i8* @sc, align 1
- call i8 @llvm.atomic.swap.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:1 [#uses=1]
- store i8 %1, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.swap.i16.p0i16( i16* %2, i16 1 ) ; <i16>:3 [#uses=1]
- store i16 %3, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.swap.i16.p0i16( i16* %4, i16 1 ) ; <i16>:5 [#uses=1]
- store i16 %5, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %6, i32 1 ) ; <i32>:7 [#uses=1]
- store i32 %7, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %8, i32 1 ) ; <i32>:9 [#uses=1]
- store i32 %9, i32* @ui, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:10 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %10, i32 1 ) ; <i32>:11 [#uses=1]
- store i32 %11, i32* @sl, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:12 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %12, i32 1 ) ; <i32>:13 [#uses=1]
- store i32 %13, i32* @ul, align 4
- call void @llvm.memory.barrier( i1 true, i1 true, i1 true, i1 true, i1 false )
- volatile store i8 0, i8* @sc, align 1
- volatile store i8 0, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:14 [#uses=1]
- volatile store i16 0, i16* %14, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:15 [#uses=1]
- volatile store i16 0, i16* %15, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:16 [#uses=1]
- volatile store i32 0, i32* %16, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:17 [#uses=1]
- volatile store i32 0, i32* %17, align 4
- bitcast i8* bitcast (i32* @sl to i8*) to i32* ; <i32*>:18 [#uses=1]
- volatile store i32 0, i32* %18, align 4
- bitcast i8* bitcast (i32* @ul to i8*) to i32* ; <i32*>:19 [#uses=1]
- volatile store i32 0, i32* %19, align 4
- br label %return
-
-return: ; preds = %entry
- ret void
-}
-
-declare i8 @llvm.atomic.swap.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.swap.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.swap.i32.p0i32(i32*, i32) nounwind
-
-declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
diff --git a/test/CodeGen/X86/Atomics-64.ll b/test/CodeGen/X86/Atomics-64.ll
index ac174b9..8e93762 100644
--- a/test/CodeGen/X86/Atomics-64.ll
+++ b/test/CodeGen/X86/Atomics-64.ll
@@ -1,1015 +1,950 @@
; RUN: llc < %s -march=x86-64 > %t
-; ModuleID = 'Atomics.c'
+; RUN: llc < %s -march=x86 > %t
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
target triple = "x86_64-apple-darwin8"
-@sc = common global i8 0 ; <i8*> [#uses=56]
-@uc = common global i8 0 ; <i8*> [#uses=116]
-@ss = common global i16 0 ; <i16*> [#uses=15]
-@us = common global i16 0 ; <i16*> [#uses=15]
-@si = common global i32 0 ; <i32*> [#uses=15]
-@ui = common global i32 0 ; <i32*> [#uses=25]
-@sl = common global i64 0 ; <i64*> [#uses=15]
-@ul = common global i64 0 ; <i64*> [#uses=15]
-@sll = common global i64 0 ; <i64*> [#uses=15]
-@ull = common global i64 0 ; <i64*> [#uses=15]
+
+@sc = common global i8 0
+@uc = common global i8 0
+@ss = common global i16 0
+@us = common global i16 0
+@si = common global i32 0
+@ui = common global i32 0
+@sl = common global i64 0
+@ul = common global i64 0
+@sll = common global i64 0
+@ull = common global i64 0
define void @test_op_ignore() nounwind {
entry:
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:0 [#uses=0]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:1 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %2, i16 1 ) ; <i16>:3 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %4, i16 1 ) ; <i16>:5 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %6, i32 1 ) ; <i32>:7 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %8, i32 1 ) ; <i32>:9 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:10 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %10, i64 1 ) ; <i64>:11 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:12 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %12, i64 1 ) ; <i64>:13 [#uses=0]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:14 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %14, i64 1 ) ; <i64>:15 [#uses=0]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:16 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %16, i64 1 ) ; <i64>:17 [#uses=0]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:18 [#uses=0]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:19 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:20 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %20, i16 1 ) ; <i16>:21 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:22 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %22, i16 1 ) ; <i16>:23 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:24 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %24, i32 1 ) ; <i32>:25 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:26 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %26, i32 1 ) ; <i32>:27 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:28 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %28, i64 1 ) ; <i64>:29 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:30 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %30, i64 1 ) ; <i64>:31 [#uses=0]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:32 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %32, i64 1 ) ; <i64>:33 [#uses=0]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:34 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %34, i64 1 ) ; <i64>:35 [#uses=0]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:36 [#uses=0]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:37 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:38 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %38, i16 1 ) ; <i16>:39 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:40 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %40, i16 1 ) ; <i16>:41 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:42 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %42, i32 1 ) ; <i32>:43 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:44 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %44, i32 1 ) ; <i32>:45 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:46 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %46, i64 1 ) ; <i64>:47 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:48 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %48, i64 1 ) ; <i64>:49 [#uses=0]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:50 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %50, i64 1 ) ; <i64>:51 [#uses=0]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:52 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %52, i64 1 ) ; <i64>:53 [#uses=0]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:54 [#uses=0]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:55 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:56 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %56, i16 1 ) ; <i16>:57 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:58 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %58, i16 1 ) ; <i16>:59 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:60 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %60, i32 1 ) ; <i32>:61 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:62 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %62, i32 1 ) ; <i32>:63 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:64 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %64, i64 1 ) ; <i64>:65 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:66 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %66, i64 1 ) ; <i64>:67 [#uses=0]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:68 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %68, i64 1 ) ; <i64>:69 [#uses=0]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:70 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %70, i64 1 ) ; <i64>:71 [#uses=0]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:72 [#uses=0]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:73 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:74 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %74, i16 1 ) ; <i16>:75 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:76 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %76, i16 1 ) ; <i16>:77 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:78 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %78, i32 1 ) ; <i32>:79 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:80 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %80, i32 1 ) ; <i32>:81 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:82 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %82, i64 1 ) ; <i64>:83 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:84 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %84, i64 1 ) ; <i64>:85 [#uses=0]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:86 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %86, i64 1 ) ; <i64>:87 [#uses=0]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:88 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %88, i64 1 ) ; <i64>:89 [#uses=0]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:90 [#uses=0]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:91 [#uses=0]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:92 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %92, i16 1 ) ; <i16>:93 [#uses=0]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:94 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %94, i16 1 ) ; <i16>:95 [#uses=0]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:96 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %96, i32 1 ) ; <i32>:97 [#uses=0]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:98 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %98, i32 1 ) ; <i32>:99 [#uses=0]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:100 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %100, i64 1 ) ; <i64>:101 [#uses=0]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:102 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %102, i64 1 ) ; <i64>:103 [#uses=0]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:104 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %104, i64 1 ) ; <i64>:105 [#uses=0]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:106 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %106, i64 1 ) ; <i64>:107 [#uses=0]
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = atomicrmw add i8* @sc, i8 1 monotonic
+ %1 = atomicrmw add i8* @uc, i8 1 monotonic
+ %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %3 = atomicrmw add i16* %2, i16 1 monotonic
+ %4 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %5 = atomicrmw add i16* %4, i16 1 monotonic
+ %6 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %7 = atomicrmw add i32* %6, i32 1 monotonic
+ %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %9 = atomicrmw add i32* %8, i32 1 monotonic
+ %10 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %11 = atomicrmw add i64* %10, i64 1 monotonic
+ %12 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %13 = atomicrmw add i64* %12, i64 1 monotonic
+ %14 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %15 = atomicrmw add i64* %14, i64 1 monotonic
+ %16 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %17 = atomicrmw add i64* %16, i64 1 monotonic
+ %18 = atomicrmw sub i8* @sc, i8 1 monotonic
+ %19 = atomicrmw sub i8* @uc, i8 1 monotonic
+ %20 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %21 = atomicrmw sub i16* %20, i16 1 monotonic
+ %22 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %23 = atomicrmw sub i16* %22, i16 1 monotonic
+ %24 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %25 = atomicrmw sub i32* %24, i32 1 monotonic
+ %26 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %27 = atomicrmw sub i32* %26, i32 1 monotonic
+ %28 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %29 = atomicrmw sub i64* %28, i64 1 monotonic
+ %30 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %31 = atomicrmw sub i64* %30, i64 1 monotonic
+ %32 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %33 = atomicrmw sub i64* %32, i64 1 monotonic
+ %34 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %35 = atomicrmw sub i64* %34, i64 1 monotonic
+ %36 = atomicrmw or i8* @sc, i8 1 monotonic
+ %37 = atomicrmw or i8* @uc, i8 1 monotonic
+ %38 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %39 = atomicrmw or i16* %38, i16 1 monotonic
+ %40 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %41 = atomicrmw or i16* %40, i16 1 monotonic
+ %42 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %43 = atomicrmw or i32* %42, i32 1 monotonic
+ %44 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %45 = atomicrmw or i32* %44, i32 1 monotonic
+ %46 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %47 = atomicrmw or i64* %46, i64 1 monotonic
+ %48 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %49 = atomicrmw or i64* %48, i64 1 monotonic
+ %50 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %51 = atomicrmw or i64* %50, i64 1 monotonic
+ %52 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %53 = atomicrmw or i64* %52, i64 1 monotonic
+ %54 = atomicrmw xor i8* @sc, i8 1 monotonic
+ %55 = atomicrmw xor i8* @uc, i8 1 monotonic
+ %56 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %57 = atomicrmw xor i16* %56, i16 1 monotonic
+ %58 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %59 = atomicrmw xor i16* %58, i16 1 monotonic
+ %60 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %61 = atomicrmw xor i32* %60, i32 1 monotonic
+ %62 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %63 = atomicrmw xor i32* %62, i32 1 monotonic
+ %64 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %65 = atomicrmw xor i64* %64, i64 1 monotonic
+ %66 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %67 = atomicrmw xor i64* %66, i64 1 monotonic
+ %68 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %69 = atomicrmw xor i64* %68, i64 1 monotonic
+ %70 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %71 = atomicrmw xor i64* %70, i64 1 monotonic
+ %72 = atomicrmw and i8* @sc, i8 1 monotonic
+ %73 = atomicrmw and i8* @uc, i8 1 monotonic
+ %74 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %75 = atomicrmw and i16* %74, i16 1 monotonic
+ %76 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %77 = atomicrmw and i16* %76, i16 1 monotonic
+ %78 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %79 = atomicrmw and i32* %78, i32 1 monotonic
+ %80 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %81 = atomicrmw and i32* %80, i32 1 monotonic
+ %82 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %83 = atomicrmw and i64* %82, i64 1 monotonic
+ %84 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %85 = atomicrmw and i64* %84, i64 1 monotonic
+ %86 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %87 = atomicrmw and i64* %86, i64 1 monotonic
+ %88 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %89 = atomicrmw and i64* %88, i64 1 monotonic
+ %90 = atomicrmw nand i8* @sc, i8 1 monotonic
+ %91 = atomicrmw nand i8* @uc, i8 1 monotonic
+ %92 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %93 = atomicrmw nand i16* %92, i16 1 monotonic
+ %94 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %95 = atomicrmw nand i16* %94, i16 1 monotonic
+ %96 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %97 = atomicrmw nand i32* %96, i32 1 monotonic
+ %98 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %99 = atomicrmw nand i32* %98, i32 1 monotonic
+ %100 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %101 = atomicrmw nand i64* %100, i64 1 monotonic
+ %102 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %103 = atomicrmw nand i64* %102, i64 1 monotonic
+ %104 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %105 = atomicrmw nand i64* %104, i64 1 monotonic
+ %106 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %107 = atomicrmw nand i64* %106, i64 1 monotonic
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
-declare i8 @llvm.atomic.load.add.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.add.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.add.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.add.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.sub.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.sub.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.sub.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.sub.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.or.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.or.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.or.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.or.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.xor.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.xor.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.xor.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.xor.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.and.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.and.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.and.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.and.i64.p0i64(i64*, i64) nounwind
-
-declare i8 @llvm.atomic.load.nand.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.load.nand.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.load.nand.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.load.nand.i64.p0i64(i64*, i64) nounwind
-
define void @test_fetch_and_op() nounwind {
entry:
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:0 [#uses=1]
- store i8 %0, i8* @sc, align 1
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:1 [#uses=1]
- store i8 %1, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %2, i16 11 ) ; <i16>:3 [#uses=1]
- store i16 %3, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %4, i16 11 ) ; <i16>:5 [#uses=1]
- store i16 %5, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %6, i32 11 ) ; <i32>:7 [#uses=1]
- store i32 %7, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %8, i32 11 ) ; <i32>:9 [#uses=1]
- store i32 %9, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:10 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %10, i64 11 ) ; <i64>:11 [#uses=1]
- store i64 %11, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:12 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %12, i64 11 ) ; <i64>:13 [#uses=1]
- store i64 %13, i64* @ul, align 8
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:14 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %14, i64 11 ) ; <i64>:15 [#uses=1]
- store i64 %15, i64* @sll, align 8
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:16 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %16, i64 11 ) ; <i64>:17 [#uses=1]
- store i64 %17, i64* @ull, align 8
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:18 [#uses=1]
- store i8 %18, i8* @sc, align 1
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:19 [#uses=1]
- store i8 %19, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:20 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %20, i16 11 ) ; <i16>:21 [#uses=1]
- store i16 %21, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:22 [#uses=1]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %22, i16 11 ) ; <i16>:23 [#uses=1]
- store i16 %23, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:24 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %24, i32 11 ) ; <i32>:25 [#uses=1]
- store i32 %25, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:26 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %26, i32 11 ) ; <i32>:27 [#uses=1]
- store i32 %27, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:28 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %28, i64 11 ) ; <i64>:29 [#uses=1]
- store i64 %29, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:30 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %30, i64 11 ) ; <i64>:31 [#uses=1]
- store i64 %31, i64* @ul, align 8
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:32 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %32, i64 11 ) ; <i64>:33 [#uses=1]
- store i64 %33, i64* @sll, align 8
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:34 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %34, i64 11 ) ; <i64>:35 [#uses=1]
- store i64 %35, i64* @ull, align 8
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:36 [#uses=1]
- store i8 %36, i8* @sc, align 1
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:37 [#uses=1]
- store i8 %37, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:38 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %38, i16 11 ) ; <i16>:39 [#uses=1]
- store i16 %39, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:40 [#uses=1]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %40, i16 11 ) ; <i16>:41 [#uses=1]
- store i16 %41, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:42 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %42, i32 11 ) ; <i32>:43 [#uses=1]
- store i32 %43, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:44 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %44, i32 11 ) ; <i32>:45 [#uses=1]
- store i32 %45, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:46 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %46, i64 11 ) ; <i64>:47 [#uses=1]
- store i64 %47, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:48 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %48, i64 11 ) ; <i64>:49 [#uses=1]
- store i64 %49, i64* @ul, align 8
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:50 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %50, i64 11 ) ; <i64>:51 [#uses=1]
- store i64 %51, i64* @sll, align 8
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:52 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %52, i64 11 ) ; <i64>:53 [#uses=1]
- store i64 %53, i64* @ull, align 8
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:54 [#uses=1]
- store i8 %54, i8* @sc, align 1
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:55 [#uses=1]
- store i8 %55, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:56 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %56, i16 11 ) ; <i16>:57 [#uses=1]
- store i16 %57, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:58 [#uses=1]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %58, i16 11 ) ; <i16>:59 [#uses=1]
- store i16 %59, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:60 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %60, i32 11 ) ; <i32>:61 [#uses=1]
- store i32 %61, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:62 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %62, i32 11 ) ; <i32>:63 [#uses=1]
- store i32 %63, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:64 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %64, i64 11 ) ; <i64>:65 [#uses=1]
- store i64 %65, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:66 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %66, i64 11 ) ; <i64>:67 [#uses=1]
- store i64 %67, i64* @ul, align 8
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:68 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %68, i64 11 ) ; <i64>:69 [#uses=1]
- store i64 %69, i64* @sll, align 8
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:70 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %70, i64 11 ) ; <i64>:71 [#uses=1]
- store i64 %71, i64* @ull, align 8
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:72 [#uses=1]
- store i8 %72, i8* @sc, align 1
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:73 [#uses=1]
- store i8 %73, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:74 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %74, i16 11 ) ; <i16>:75 [#uses=1]
- store i16 %75, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:76 [#uses=1]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %76, i16 11 ) ; <i16>:77 [#uses=1]
- store i16 %77, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:78 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %78, i32 11 ) ; <i32>:79 [#uses=1]
- store i32 %79, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:80 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %80, i32 11 ) ; <i32>:81 [#uses=1]
- store i32 %81, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:82 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %82, i64 11 ) ; <i64>:83 [#uses=1]
- store i64 %83, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:84 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %84, i64 11 ) ; <i64>:85 [#uses=1]
- store i64 %85, i64* @ul, align 8
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:86 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %86, i64 11 ) ; <i64>:87 [#uses=1]
- store i64 %87, i64* @sll, align 8
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:88 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %88, i64 11 ) ; <i64>:89 [#uses=1]
- store i64 %89, i64* @ull, align 8
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 11 ) ; <i8>:90 [#uses=1]
- store i8 %90, i8* @sc, align 1
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 11 ) ; <i8>:91 [#uses=1]
- store i8 %91, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:92 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %92, i16 11 ) ; <i16>:93 [#uses=1]
- store i16 %93, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:94 [#uses=1]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %94, i16 11 ) ; <i16>:95 [#uses=1]
- store i16 %95, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:96 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %96, i32 11 ) ; <i32>:97 [#uses=1]
- store i32 %97, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:98 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %98, i32 11 ) ; <i32>:99 [#uses=1]
- store i32 %99, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:100 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %100, i64 11 ) ; <i64>:101 [#uses=1]
- store i64 %101, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:102 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %102, i64 11 ) ; <i64>:103 [#uses=1]
- store i64 %103, i64* @ul, align 8
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:104 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %104, i64 11 ) ; <i64>:105 [#uses=1]
- store i64 %105, i64* @sll, align 8
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:106 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %106, i64 11 ) ; <i64>:107 [#uses=1]
- store i64 %107, i64* @ull, align 8
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = atomicrmw add i8* @sc, i8 11 monotonic
+ store i8 %0, i8* @sc, align 1
+ %1 = atomicrmw add i8* @uc, i8 11 monotonic
+ store i8 %1, i8* @uc, align 1
+ %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %3 = atomicrmw add i16* %2, i16 11 monotonic
+ store i16 %3, i16* @ss, align 2
+ %4 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %5 = atomicrmw add i16* %4, i16 11 monotonic
+ store i16 %5, i16* @us, align 2
+ %6 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %7 = atomicrmw add i32* %6, i32 11 monotonic
+ store i32 %7, i32* @si, align 4
+ %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %9 = atomicrmw add i32* %8, i32 11 monotonic
+ store i32 %9, i32* @ui, align 4
+ %10 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %11 = atomicrmw add i64* %10, i64 11 monotonic
+ store i64 %11, i64* @sl, align 8
+ %12 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %13 = atomicrmw add i64* %12, i64 11 monotonic
+ store i64 %13, i64* @ul, align 8
+ %14 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %15 = atomicrmw add i64* %14, i64 11 monotonic
+ store i64 %15, i64* @sll, align 8
+ %16 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %17 = atomicrmw add i64* %16, i64 11 monotonic
+ store i64 %17, i64* @ull, align 8
+ %18 = atomicrmw sub i8* @sc, i8 11 monotonic
+ store i8 %18, i8* @sc, align 1
+ %19 = atomicrmw sub i8* @uc, i8 11 monotonic
+ store i8 %19, i8* @uc, align 1
+ %20 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %21 = atomicrmw sub i16* %20, i16 11 monotonic
+ store i16 %21, i16* @ss, align 2
+ %22 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %23 = atomicrmw sub i16* %22, i16 11 monotonic
+ store i16 %23, i16* @us, align 2
+ %24 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %25 = atomicrmw sub i32* %24, i32 11 monotonic
+ store i32 %25, i32* @si, align 4
+ %26 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %27 = atomicrmw sub i32* %26, i32 11 monotonic
+ store i32 %27, i32* @ui, align 4
+ %28 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %29 = atomicrmw sub i64* %28, i64 11 monotonic
+ store i64 %29, i64* @sl, align 8
+ %30 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %31 = atomicrmw sub i64* %30, i64 11 monotonic
+ store i64 %31, i64* @ul, align 8
+ %32 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %33 = atomicrmw sub i64* %32, i64 11 monotonic
+ store i64 %33, i64* @sll, align 8
+ %34 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %35 = atomicrmw sub i64* %34, i64 11 monotonic
+ store i64 %35, i64* @ull, align 8
+ %36 = atomicrmw or i8* @sc, i8 11 monotonic
+ store i8 %36, i8* @sc, align 1
+ %37 = atomicrmw or i8* @uc, i8 11 monotonic
+ store i8 %37, i8* @uc, align 1
+ %38 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %39 = atomicrmw or i16* %38, i16 11 monotonic
+ store i16 %39, i16* @ss, align 2
+ %40 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %41 = atomicrmw or i16* %40, i16 11 monotonic
+ store i16 %41, i16* @us, align 2
+ %42 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %43 = atomicrmw or i32* %42, i32 11 monotonic
+ store i32 %43, i32* @si, align 4
+ %44 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %45 = atomicrmw or i32* %44, i32 11 monotonic
+ store i32 %45, i32* @ui, align 4
+ %46 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %47 = atomicrmw or i64* %46, i64 11 monotonic
+ store i64 %47, i64* @sl, align 8
+ %48 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %49 = atomicrmw or i64* %48, i64 11 monotonic
+ store i64 %49, i64* @ul, align 8
+ %50 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %51 = atomicrmw or i64* %50, i64 11 monotonic
+ store i64 %51, i64* @sll, align 8
+ %52 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %53 = atomicrmw or i64* %52, i64 11 monotonic
+ store i64 %53, i64* @ull, align 8
+ %54 = atomicrmw xor i8* @sc, i8 11 monotonic
+ store i8 %54, i8* @sc, align 1
+ %55 = atomicrmw xor i8* @uc, i8 11 monotonic
+ store i8 %55, i8* @uc, align 1
+ %56 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %57 = atomicrmw xor i16* %56, i16 11 monotonic
+ store i16 %57, i16* @ss, align 2
+ %58 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %59 = atomicrmw xor i16* %58, i16 11 monotonic
+ store i16 %59, i16* @us, align 2
+ %60 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %61 = atomicrmw xor i32* %60, i32 11 monotonic
+ store i32 %61, i32* @si, align 4
+ %62 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %63 = atomicrmw xor i32* %62, i32 11 monotonic
+ store i32 %63, i32* @ui, align 4
+ %64 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %65 = atomicrmw xor i64* %64, i64 11 monotonic
+ store i64 %65, i64* @sl, align 8
+ %66 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %67 = atomicrmw xor i64* %66, i64 11 monotonic
+ store i64 %67, i64* @ul, align 8
+ %68 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %69 = atomicrmw xor i64* %68, i64 11 monotonic
+ store i64 %69, i64* @sll, align 8
+ %70 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %71 = atomicrmw xor i64* %70, i64 11 monotonic
+ store i64 %71, i64* @ull, align 8
+ %72 = atomicrmw and i8* @sc, i8 11 monotonic
+ store i8 %72, i8* @sc, align 1
+ %73 = atomicrmw and i8* @uc, i8 11 monotonic
+ store i8 %73, i8* @uc, align 1
+ %74 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %75 = atomicrmw and i16* %74, i16 11 monotonic
+ store i16 %75, i16* @ss, align 2
+ %76 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %77 = atomicrmw and i16* %76, i16 11 monotonic
+ store i16 %77, i16* @us, align 2
+ %78 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %79 = atomicrmw and i32* %78, i32 11 monotonic
+ store i32 %79, i32* @si, align 4
+ %80 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %81 = atomicrmw and i32* %80, i32 11 monotonic
+ store i32 %81, i32* @ui, align 4
+ %82 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %83 = atomicrmw and i64* %82, i64 11 monotonic
+ store i64 %83, i64* @sl, align 8
+ %84 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %85 = atomicrmw and i64* %84, i64 11 monotonic
+ store i64 %85, i64* @ul, align 8
+ %86 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %87 = atomicrmw and i64* %86, i64 11 monotonic
+ store i64 %87, i64* @sll, align 8
+ %88 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %89 = atomicrmw and i64* %88, i64 11 monotonic
+ store i64 %89, i64* @ull, align 8
+ %90 = atomicrmw nand i8* @sc, i8 11 monotonic
+ store i8 %90, i8* @sc, align 1
+ %91 = atomicrmw nand i8* @uc, i8 11 monotonic
+ store i8 %91, i8* @uc, align 1
+ %92 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %93 = atomicrmw nand i16* %92, i16 11 monotonic
+ store i16 %93, i16* @ss, align 2
+ %94 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %95 = atomicrmw nand i16* %94, i16 11 monotonic
+ store i16 %95, i16* @us, align 2
+ %96 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %97 = atomicrmw nand i32* %96, i32 11 monotonic
+ store i32 %97, i32* @si, align 4
+ %98 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %99 = atomicrmw nand i32* %98, i32 11 monotonic
+ store i32 %99, i32* @ui, align 4
+ %100 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %101 = atomicrmw nand i64* %100, i64 11 monotonic
+ store i64 %101, i64* @sl, align 8
+ %102 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %103 = atomicrmw nand i64* %102, i64 11 monotonic
+ store i64 %103, i64* @ul, align 8
+ %104 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %105 = atomicrmw nand i64* %104, i64 11 monotonic
+ store i64 %105, i64* @sll, align 8
+ %106 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %107 = atomicrmw nand i64* %106, i64 11 monotonic
+ store i64 %107, i64* @ull, align 8
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
define void @test_op_and_fetch() nounwind {
entry:
- load i8* @uc, align 1 ; <i8>:0 [#uses=1]
- zext i8 %0 to i32 ; <i32>:1 [#uses=1]
- trunc i32 %1 to i8 ; <i8>:2 [#uses=2]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @sc, i8 %2 ) ; <i8>:3 [#uses=1]
- add i8 %3, %2 ; <i8>:4 [#uses=1]
- store i8 %4, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:5 [#uses=1]
- zext i8 %5 to i32 ; <i32>:6 [#uses=1]
- trunc i32 %6 to i8 ; <i8>:7 [#uses=2]
- call i8 @llvm.atomic.load.add.i8.p0i8( i8* @uc, i8 %7 ) ; <i8>:8 [#uses=1]
- add i8 %8, %7 ; <i8>:9 [#uses=1]
- store i8 %9, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:10 [#uses=1]
- zext i8 %10 to i32 ; <i32>:11 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:12 [#uses=1]
- trunc i32 %11 to i16 ; <i16>:13 [#uses=2]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %12, i16 %13 ) ; <i16>:14 [#uses=1]
- add i16 %14, %13 ; <i16>:15 [#uses=1]
- store i16 %15, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:16 [#uses=1]
- zext i8 %16 to i32 ; <i32>:17 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:18 [#uses=1]
- trunc i32 %17 to i16 ; <i16>:19 [#uses=2]
- call i16 @llvm.atomic.load.add.i16.p0i16( i16* %18, i16 %19 ) ; <i16>:20 [#uses=1]
- add i16 %20, %19 ; <i16>:21 [#uses=1]
- store i16 %21, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:22 [#uses=1]
- zext i8 %22 to i32 ; <i32>:23 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:24 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %24, i32 %23 ) ; <i32>:25 [#uses=1]
- add i32 %25, %23 ; <i32>:26 [#uses=1]
- store i32 %26, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:27 [#uses=1]
- zext i8 %27 to i32 ; <i32>:28 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:29 [#uses=1]
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %29, i32 %28 ) ; <i32>:30 [#uses=1]
- add i32 %30, %28 ; <i32>:31 [#uses=1]
- store i32 %31, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:32 [#uses=1]
- zext i8 %32 to i64 ; <i64>:33 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:34 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %34, i64 %33 ) ; <i64>:35 [#uses=1]
- add i64 %35, %33 ; <i64>:36 [#uses=1]
- store i64 %36, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:37 [#uses=1]
- zext i8 %37 to i64 ; <i64>:38 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:39 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %39, i64 %38 ) ; <i64>:40 [#uses=1]
- add i64 %40, %38 ; <i64>:41 [#uses=1]
- store i64 %41, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:42 [#uses=1]
- zext i8 %42 to i64 ; <i64>:43 [#uses=2]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:44 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %44, i64 %43 ) ; <i64>:45 [#uses=1]
- add i64 %45, %43 ; <i64>:46 [#uses=1]
- store i64 %46, i64* @sll, align 8
- load i8* @uc, align 1 ; <i8>:47 [#uses=1]
- zext i8 %47 to i64 ; <i64>:48 [#uses=2]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:49 [#uses=1]
- call i64 @llvm.atomic.load.add.i64.p0i64( i64* %49, i64 %48 ) ; <i64>:50 [#uses=1]
- add i64 %50, %48 ; <i64>:51 [#uses=1]
- store i64 %51, i64* @ull, align 8
- load i8* @uc, align 1 ; <i8>:52 [#uses=1]
- zext i8 %52 to i32 ; <i32>:53 [#uses=1]
- trunc i32 %53 to i8 ; <i8>:54 [#uses=2]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @sc, i8 %54 ) ; <i8>:55 [#uses=1]
- sub i8 %55, %54 ; <i8>:56 [#uses=1]
- store i8 %56, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:57 [#uses=1]
- zext i8 %57 to i32 ; <i32>:58 [#uses=1]
- trunc i32 %58 to i8 ; <i8>:59 [#uses=2]
- call i8 @llvm.atomic.load.sub.i8.p0i8( i8* @uc, i8 %59 ) ; <i8>:60 [#uses=1]
- sub i8 %60, %59 ; <i8>:61 [#uses=1]
- store i8 %61, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:62 [#uses=1]
- zext i8 %62 to i32 ; <i32>:63 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:64 [#uses=1]
- trunc i32 %63 to i16 ; <i16>:65 [#uses=2]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %64, i16 %65 ) ; <i16>:66 [#uses=1]
- sub i16 %66, %65 ; <i16>:67 [#uses=1]
- store i16 %67, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:68 [#uses=1]
- zext i8 %68 to i32 ; <i32>:69 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:70 [#uses=1]
- trunc i32 %69 to i16 ; <i16>:71 [#uses=2]
- call i16 @llvm.atomic.load.sub.i16.p0i16( i16* %70, i16 %71 ) ; <i16>:72 [#uses=1]
- sub i16 %72, %71 ; <i16>:73 [#uses=1]
- store i16 %73, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:74 [#uses=1]
- zext i8 %74 to i32 ; <i32>:75 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:76 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %76, i32 %75 ) ; <i32>:77 [#uses=1]
- sub i32 %77, %75 ; <i32>:78 [#uses=1]
- store i32 %78, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:79 [#uses=1]
- zext i8 %79 to i32 ; <i32>:80 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:81 [#uses=1]
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %81, i32 %80 ) ; <i32>:82 [#uses=1]
- sub i32 %82, %80 ; <i32>:83 [#uses=1]
- store i32 %83, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:84 [#uses=1]
- zext i8 %84 to i64 ; <i64>:85 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:86 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %86, i64 %85 ) ; <i64>:87 [#uses=1]
- sub i64 %87, %85 ; <i64>:88 [#uses=1]
- store i64 %88, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:89 [#uses=1]
- zext i8 %89 to i64 ; <i64>:90 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:91 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %91, i64 %90 ) ; <i64>:92 [#uses=1]
- sub i64 %92, %90 ; <i64>:93 [#uses=1]
- store i64 %93, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:94 [#uses=1]
- zext i8 %94 to i64 ; <i64>:95 [#uses=2]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:96 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %96, i64 %95 ) ; <i64>:97 [#uses=1]
- sub i64 %97, %95 ; <i64>:98 [#uses=1]
- store i64 %98, i64* @sll, align 8
- load i8* @uc, align 1 ; <i8>:99 [#uses=1]
- zext i8 %99 to i64 ; <i64>:100 [#uses=2]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:101 [#uses=1]
- call i64 @llvm.atomic.load.sub.i64.p0i64( i64* %101, i64 %100 ) ; <i64>:102 [#uses=1]
- sub i64 %102, %100 ; <i64>:103 [#uses=1]
- store i64 %103, i64* @ull, align 8
- load i8* @uc, align 1 ; <i8>:104 [#uses=1]
- zext i8 %104 to i32 ; <i32>:105 [#uses=1]
- trunc i32 %105 to i8 ; <i8>:106 [#uses=2]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @sc, i8 %106 ) ; <i8>:107 [#uses=1]
- or i8 %107, %106 ; <i8>:108 [#uses=1]
- store i8 %108, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:109 [#uses=1]
- zext i8 %109 to i32 ; <i32>:110 [#uses=1]
- trunc i32 %110 to i8 ; <i8>:111 [#uses=2]
- call i8 @llvm.atomic.load.or.i8.p0i8( i8* @uc, i8 %111 ) ; <i8>:112 [#uses=1]
- or i8 %112, %111 ; <i8>:113 [#uses=1]
- store i8 %113, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:114 [#uses=1]
- zext i8 %114 to i32 ; <i32>:115 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:116 [#uses=1]
- trunc i32 %115 to i16 ; <i16>:117 [#uses=2]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %116, i16 %117 ) ; <i16>:118 [#uses=1]
- or i16 %118, %117 ; <i16>:119 [#uses=1]
- store i16 %119, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:120 [#uses=1]
- zext i8 %120 to i32 ; <i32>:121 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:122 [#uses=1]
- trunc i32 %121 to i16 ; <i16>:123 [#uses=2]
- call i16 @llvm.atomic.load.or.i16.p0i16( i16* %122, i16 %123 ) ; <i16>:124 [#uses=1]
- or i16 %124, %123 ; <i16>:125 [#uses=1]
- store i16 %125, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:126 [#uses=1]
- zext i8 %126 to i32 ; <i32>:127 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:128 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %128, i32 %127 ) ; <i32>:129 [#uses=1]
- or i32 %129, %127 ; <i32>:130 [#uses=1]
- store i32 %130, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:131 [#uses=1]
- zext i8 %131 to i32 ; <i32>:132 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:133 [#uses=1]
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %133, i32 %132 ) ; <i32>:134 [#uses=1]
- or i32 %134, %132 ; <i32>:135 [#uses=1]
- store i32 %135, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:136 [#uses=1]
- zext i8 %136 to i64 ; <i64>:137 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:138 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %138, i64 %137 ) ; <i64>:139 [#uses=1]
- or i64 %139, %137 ; <i64>:140 [#uses=1]
- store i64 %140, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:141 [#uses=1]
- zext i8 %141 to i64 ; <i64>:142 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:143 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %143, i64 %142 ) ; <i64>:144 [#uses=1]
- or i64 %144, %142 ; <i64>:145 [#uses=1]
- store i64 %145, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:146 [#uses=1]
- zext i8 %146 to i64 ; <i64>:147 [#uses=2]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:148 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %148, i64 %147 ) ; <i64>:149 [#uses=1]
- or i64 %149, %147 ; <i64>:150 [#uses=1]
- store i64 %150, i64* @sll, align 8
- load i8* @uc, align 1 ; <i8>:151 [#uses=1]
- zext i8 %151 to i64 ; <i64>:152 [#uses=2]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:153 [#uses=1]
- call i64 @llvm.atomic.load.or.i64.p0i64( i64* %153, i64 %152 ) ; <i64>:154 [#uses=1]
- or i64 %154, %152 ; <i64>:155 [#uses=1]
- store i64 %155, i64* @ull, align 8
- load i8* @uc, align 1 ; <i8>:156 [#uses=1]
- zext i8 %156 to i32 ; <i32>:157 [#uses=1]
- trunc i32 %157 to i8 ; <i8>:158 [#uses=2]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @sc, i8 %158 ) ; <i8>:159 [#uses=1]
- xor i8 %159, %158 ; <i8>:160 [#uses=1]
- store i8 %160, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:161 [#uses=1]
- zext i8 %161 to i32 ; <i32>:162 [#uses=1]
- trunc i32 %162 to i8 ; <i8>:163 [#uses=2]
- call i8 @llvm.atomic.load.xor.i8.p0i8( i8* @uc, i8 %163 ) ; <i8>:164 [#uses=1]
- xor i8 %164, %163 ; <i8>:165 [#uses=1]
- store i8 %165, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:166 [#uses=1]
- zext i8 %166 to i32 ; <i32>:167 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:168 [#uses=1]
- trunc i32 %167 to i16 ; <i16>:169 [#uses=2]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %168, i16 %169 ) ; <i16>:170 [#uses=1]
- xor i16 %170, %169 ; <i16>:171 [#uses=1]
- store i16 %171, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:172 [#uses=1]
- zext i8 %172 to i32 ; <i32>:173 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:174 [#uses=1]
- trunc i32 %173 to i16 ; <i16>:175 [#uses=2]
- call i16 @llvm.atomic.load.xor.i16.p0i16( i16* %174, i16 %175 ) ; <i16>:176 [#uses=1]
- xor i16 %176, %175 ; <i16>:177 [#uses=1]
- store i16 %177, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:178 [#uses=1]
- zext i8 %178 to i32 ; <i32>:179 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:180 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %180, i32 %179 ) ; <i32>:181 [#uses=1]
- xor i32 %181, %179 ; <i32>:182 [#uses=1]
- store i32 %182, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:183 [#uses=1]
- zext i8 %183 to i32 ; <i32>:184 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:185 [#uses=1]
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %185, i32 %184 ) ; <i32>:186 [#uses=1]
- xor i32 %186, %184 ; <i32>:187 [#uses=1]
- store i32 %187, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:188 [#uses=1]
- zext i8 %188 to i64 ; <i64>:189 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:190 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %190, i64 %189 ) ; <i64>:191 [#uses=1]
- xor i64 %191, %189 ; <i64>:192 [#uses=1]
- store i64 %192, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:193 [#uses=1]
- zext i8 %193 to i64 ; <i64>:194 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:195 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %195, i64 %194 ) ; <i64>:196 [#uses=1]
- xor i64 %196, %194 ; <i64>:197 [#uses=1]
- store i64 %197, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:198 [#uses=1]
- zext i8 %198 to i64 ; <i64>:199 [#uses=2]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:200 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %200, i64 %199 ) ; <i64>:201 [#uses=1]
- xor i64 %201, %199 ; <i64>:202 [#uses=1]
- store i64 %202, i64* @sll, align 8
- load i8* @uc, align 1 ; <i8>:203 [#uses=1]
- zext i8 %203 to i64 ; <i64>:204 [#uses=2]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:205 [#uses=1]
- call i64 @llvm.atomic.load.xor.i64.p0i64( i64* %205, i64 %204 ) ; <i64>:206 [#uses=1]
- xor i64 %206, %204 ; <i64>:207 [#uses=1]
- store i64 %207, i64* @ull, align 8
- load i8* @uc, align 1 ; <i8>:208 [#uses=1]
- zext i8 %208 to i32 ; <i32>:209 [#uses=1]
- trunc i32 %209 to i8 ; <i8>:210 [#uses=2]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @sc, i8 %210 ) ; <i8>:211 [#uses=1]
- and i8 %211, %210 ; <i8>:212 [#uses=1]
- store i8 %212, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:213 [#uses=1]
- zext i8 %213 to i32 ; <i32>:214 [#uses=1]
- trunc i32 %214 to i8 ; <i8>:215 [#uses=2]
- call i8 @llvm.atomic.load.and.i8.p0i8( i8* @uc, i8 %215 ) ; <i8>:216 [#uses=1]
- and i8 %216, %215 ; <i8>:217 [#uses=1]
- store i8 %217, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:218 [#uses=1]
- zext i8 %218 to i32 ; <i32>:219 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:220 [#uses=1]
- trunc i32 %219 to i16 ; <i16>:221 [#uses=2]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %220, i16 %221 ) ; <i16>:222 [#uses=1]
- and i16 %222, %221 ; <i16>:223 [#uses=1]
- store i16 %223, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:224 [#uses=1]
- zext i8 %224 to i32 ; <i32>:225 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:226 [#uses=1]
- trunc i32 %225 to i16 ; <i16>:227 [#uses=2]
- call i16 @llvm.atomic.load.and.i16.p0i16( i16* %226, i16 %227 ) ; <i16>:228 [#uses=1]
- and i16 %228, %227 ; <i16>:229 [#uses=1]
- store i16 %229, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:230 [#uses=1]
- zext i8 %230 to i32 ; <i32>:231 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:232 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %232, i32 %231 ) ; <i32>:233 [#uses=1]
- and i32 %233, %231 ; <i32>:234 [#uses=1]
- store i32 %234, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:235 [#uses=1]
- zext i8 %235 to i32 ; <i32>:236 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:237 [#uses=1]
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %237, i32 %236 ) ; <i32>:238 [#uses=1]
- and i32 %238, %236 ; <i32>:239 [#uses=1]
- store i32 %239, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:240 [#uses=1]
- zext i8 %240 to i64 ; <i64>:241 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:242 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %242, i64 %241 ) ; <i64>:243 [#uses=1]
- and i64 %243, %241 ; <i64>:244 [#uses=1]
- store i64 %244, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:245 [#uses=1]
- zext i8 %245 to i64 ; <i64>:246 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:247 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %247, i64 %246 ) ; <i64>:248 [#uses=1]
- and i64 %248, %246 ; <i64>:249 [#uses=1]
- store i64 %249, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:250 [#uses=1]
- zext i8 %250 to i64 ; <i64>:251 [#uses=2]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:252 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %252, i64 %251 ) ; <i64>:253 [#uses=1]
- and i64 %253, %251 ; <i64>:254 [#uses=1]
- store i64 %254, i64* @sll, align 8
- load i8* @uc, align 1 ; <i8>:255 [#uses=1]
- zext i8 %255 to i64 ; <i64>:256 [#uses=2]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:257 [#uses=1]
- call i64 @llvm.atomic.load.and.i64.p0i64( i64* %257, i64 %256 ) ; <i64>:258 [#uses=1]
- and i64 %258, %256 ; <i64>:259 [#uses=1]
- store i64 %259, i64* @ull, align 8
- load i8* @uc, align 1 ; <i8>:260 [#uses=1]
- zext i8 %260 to i32 ; <i32>:261 [#uses=1]
- trunc i32 %261 to i8 ; <i8>:262 [#uses=2]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @sc, i8 %262 ) ; <i8>:263 [#uses=1]
- xor i8 %263, -1 ; <i8>:264 [#uses=1]
- and i8 %264, %262 ; <i8>:265 [#uses=1]
- store i8 %265, i8* @sc, align 1
- load i8* @uc, align 1 ; <i8>:266 [#uses=1]
- zext i8 %266 to i32 ; <i32>:267 [#uses=1]
- trunc i32 %267 to i8 ; <i8>:268 [#uses=2]
- call i8 @llvm.atomic.load.nand.i8.p0i8( i8* @uc, i8 %268 ) ; <i8>:269 [#uses=1]
- xor i8 %269, -1 ; <i8>:270 [#uses=1]
- and i8 %270, %268 ; <i8>:271 [#uses=1]
- store i8 %271, i8* @uc, align 1
- load i8* @uc, align 1 ; <i8>:272 [#uses=1]
- zext i8 %272 to i32 ; <i32>:273 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:274 [#uses=1]
- trunc i32 %273 to i16 ; <i16>:275 [#uses=2]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %274, i16 %275 ) ; <i16>:276 [#uses=1]
- xor i16 %276, -1 ; <i16>:277 [#uses=1]
- and i16 %277, %275 ; <i16>:278 [#uses=1]
- store i16 %278, i16* @ss, align 2
- load i8* @uc, align 1 ; <i8>:279 [#uses=1]
- zext i8 %279 to i32 ; <i32>:280 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:281 [#uses=1]
- trunc i32 %280 to i16 ; <i16>:282 [#uses=2]
- call i16 @llvm.atomic.load.nand.i16.p0i16( i16* %281, i16 %282 ) ; <i16>:283 [#uses=1]
- xor i16 %283, -1 ; <i16>:284 [#uses=1]
- and i16 %284, %282 ; <i16>:285 [#uses=1]
- store i16 %285, i16* @us, align 2
- load i8* @uc, align 1 ; <i8>:286 [#uses=1]
- zext i8 %286 to i32 ; <i32>:287 [#uses=2]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:288 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %288, i32 %287 ) ; <i32>:289 [#uses=1]
- xor i32 %289, -1 ; <i32>:290 [#uses=1]
- and i32 %290, %287 ; <i32>:291 [#uses=1]
- store i32 %291, i32* @si, align 4
- load i8* @uc, align 1 ; <i8>:292 [#uses=1]
- zext i8 %292 to i32 ; <i32>:293 [#uses=2]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:294 [#uses=1]
- call i32 @llvm.atomic.load.nand.i32.p0i32( i32* %294, i32 %293 ) ; <i32>:295 [#uses=1]
- xor i32 %295, -1 ; <i32>:296 [#uses=1]
- and i32 %296, %293 ; <i32>:297 [#uses=1]
- store i32 %297, i32* @ui, align 4
- load i8* @uc, align 1 ; <i8>:298 [#uses=1]
- zext i8 %298 to i64 ; <i64>:299 [#uses=2]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:300 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %300, i64 %299 ) ; <i64>:301 [#uses=1]
- xor i64 %301, -1 ; <i64>:302 [#uses=1]
- and i64 %302, %299 ; <i64>:303 [#uses=1]
- store i64 %303, i64* @sl, align 8
- load i8* @uc, align 1 ; <i8>:304 [#uses=1]
- zext i8 %304 to i64 ; <i64>:305 [#uses=2]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:306 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %306, i64 %305 ) ; <i64>:307 [#uses=1]
- xor i64 %307, -1 ; <i64>:308 [#uses=1]
- and i64 %308, %305 ; <i64>:309 [#uses=1]
- store i64 %309, i64* @ul, align 8
- load i8* @uc, align 1 ; <i8>:310 [#uses=1]
- zext i8 %310 to i64 ; <i64>:311 [#uses=2]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:312 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %312, i64 %311 ) ; <i64>:313 [#uses=1]
- xor i64 %313, -1 ; <i64>:314 [#uses=1]
- and i64 %314, %311 ; <i64>:315 [#uses=1]
- store i64 %315, i64* @sll, align 8
- load i8* @uc, align 1 ; <i8>:316 [#uses=1]
- zext i8 %316 to i64 ; <i64>:317 [#uses=2]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:318 [#uses=1]
- call i64 @llvm.atomic.load.nand.i64.p0i64( i64* %318, i64 %317 ) ; <i64>:319 [#uses=1]
- xor i64 %319, -1 ; <i64>:320 [#uses=1]
- and i64 %320, %317 ; <i64>:321 [#uses=1]
- store i64 %321, i64* @ull, align 8
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = load i8* @uc, align 1
+ %1 = zext i8 %0 to i32
+ %2 = trunc i32 %1 to i8
+ %3 = atomicrmw add i8* @sc, i8 %2 monotonic
+ %4 = add i8 %3, %2
+ store i8 %4, i8* @sc, align 1
+ %5 = load i8* @uc, align 1
+ %6 = zext i8 %5 to i32
+ %7 = trunc i32 %6 to i8
+ %8 = atomicrmw add i8* @uc, i8 %7 monotonic
+ %9 = add i8 %8, %7
+ store i8 %9, i8* @uc, align 1
+ %10 = load i8* @uc, align 1
+ %11 = zext i8 %10 to i32
+ %12 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %13 = trunc i32 %11 to i16
+ %14 = atomicrmw add i16* %12, i16 %13 monotonic
+ %15 = add i16 %14, %13
+ store i16 %15, i16* @ss, align 2
+ %16 = load i8* @uc, align 1
+ %17 = zext i8 %16 to i32
+ %18 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %19 = trunc i32 %17 to i16
+ %20 = atomicrmw add i16* %18, i16 %19 monotonic
+ %21 = add i16 %20, %19
+ store i16 %21, i16* @us, align 2
+ %22 = load i8* @uc, align 1
+ %23 = zext i8 %22 to i32
+ %24 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %25 = atomicrmw add i32* %24, i32 %23 monotonic
+ %26 = add i32 %25, %23
+ store i32 %26, i32* @si, align 4
+ %27 = load i8* @uc, align 1
+ %28 = zext i8 %27 to i32
+ %29 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %30 = atomicrmw add i32* %29, i32 %28 monotonic
+ %31 = add i32 %30, %28
+ store i32 %31, i32* @ui, align 4
+ %32 = load i8* @uc, align 1
+ %33 = zext i8 %32 to i64
+ %34 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %35 = atomicrmw add i64* %34, i64 %33 monotonic
+ %36 = add i64 %35, %33
+ store i64 %36, i64* @sl, align 8
+ %37 = load i8* @uc, align 1
+ %38 = zext i8 %37 to i64
+ %39 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %40 = atomicrmw add i64* %39, i64 %38 monotonic
+ %41 = add i64 %40, %38
+ store i64 %41, i64* @ul, align 8
+ %42 = load i8* @uc, align 1
+ %43 = zext i8 %42 to i64
+ %44 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %45 = atomicrmw add i64* %44, i64 %43 monotonic
+ %46 = add i64 %45, %43
+ store i64 %46, i64* @sll, align 8
+ %47 = load i8* @uc, align 1
+ %48 = zext i8 %47 to i64
+ %49 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %50 = atomicrmw add i64* %49, i64 %48 monotonic
+ %51 = add i64 %50, %48
+ store i64 %51, i64* @ull, align 8
+ %52 = load i8* @uc, align 1
+ %53 = zext i8 %52 to i32
+ %54 = trunc i32 %53 to i8
+ %55 = atomicrmw sub i8* @sc, i8 %54 monotonic
+ %56 = sub i8 %55, %54
+ store i8 %56, i8* @sc, align 1
+ %57 = load i8* @uc, align 1
+ %58 = zext i8 %57 to i32
+ %59 = trunc i32 %58 to i8
+ %60 = atomicrmw sub i8* @uc, i8 %59 monotonic
+ %61 = sub i8 %60, %59
+ store i8 %61, i8* @uc, align 1
+ %62 = load i8* @uc, align 1
+ %63 = zext i8 %62 to i32
+ %64 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %65 = trunc i32 %63 to i16
+ %66 = atomicrmw sub i16* %64, i16 %65 monotonic
+ %67 = sub i16 %66, %65
+ store i16 %67, i16* @ss, align 2
+ %68 = load i8* @uc, align 1
+ %69 = zext i8 %68 to i32
+ %70 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %71 = trunc i32 %69 to i16
+ %72 = atomicrmw sub i16* %70, i16 %71 monotonic
+ %73 = sub i16 %72, %71
+ store i16 %73, i16* @us, align 2
+ %74 = load i8* @uc, align 1
+ %75 = zext i8 %74 to i32
+ %76 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %77 = atomicrmw sub i32* %76, i32 %75 monotonic
+ %78 = sub i32 %77, %75
+ store i32 %78, i32* @si, align 4
+ %79 = load i8* @uc, align 1
+ %80 = zext i8 %79 to i32
+ %81 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %82 = atomicrmw sub i32* %81, i32 %80 monotonic
+ %83 = sub i32 %82, %80
+ store i32 %83, i32* @ui, align 4
+ %84 = load i8* @uc, align 1
+ %85 = zext i8 %84 to i64
+ %86 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %87 = atomicrmw sub i64* %86, i64 %85 monotonic
+ %88 = sub i64 %87, %85
+ store i64 %88, i64* @sl, align 8
+ %89 = load i8* @uc, align 1
+ %90 = zext i8 %89 to i64
+ %91 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %92 = atomicrmw sub i64* %91, i64 %90 monotonic
+ %93 = sub i64 %92, %90
+ store i64 %93, i64* @ul, align 8
+ %94 = load i8* @uc, align 1
+ %95 = zext i8 %94 to i64
+ %96 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %97 = atomicrmw sub i64* %96, i64 %95 monotonic
+ %98 = sub i64 %97, %95
+ store i64 %98, i64* @sll, align 8
+ %99 = load i8* @uc, align 1
+ %100 = zext i8 %99 to i64
+ %101 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %102 = atomicrmw sub i64* %101, i64 %100 monotonic
+ %103 = sub i64 %102, %100
+ store i64 %103, i64* @ull, align 8
+ %104 = load i8* @uc, align 1
+ %105 = zext i8 %104 to i32
+ %106 = trunc i32 %105 to i8
+ %107 = atomicrmw or i8* @sc, i8 %106 monotonic
+ %108 = or i8 %107, %106
+ store i8 %108, i8* @sc, align 1
+ %109 = load i8* @uc, align 1
+ %110 = zext i8 %109 to i32
+ %111 = trunc i32 %110 to i8
+ %112 = atomicrmw or i8* @uc, i8 %111 monotonic
+ %113 = or i8 %112, %111
+ store i8 %113, i8* @uc, align 1
+ %114 = load i8* @uc, align 1
+ %115 = zext i8 %114 to i32
+ %116 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %117 = trunc i32 %115 to i16
+ %118 = atomicrmw or i16* %116, i16 %117 monotonic
+ %119 = or i16 %118, %117
+ store i16 %119, i16* @ss, align 2
+ %120 = load i8* @uc, align 1
+ %121 = zext i8 %120 to i32
+ %122 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %123 = trunc i32 %121 to i16
+ %124 = atomicrmw or i16* %122, i16 %123 monotonic
+ %125 = or i16 %124, %123
+ store i16 %125, i16* @us, align 2
+ %126 = load i8* @uc, align 1
+ %127 = zext i8 %126 to i32
+ %128 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %129 = atomicrmw or i32* %128, i32 %127 monotonic
+ %130 = or i32 %129, %127
+ store i32 %130, i32* @si, align 4
+ %131 = load i8* @uc, align 1
+ %132 = zext i8 %131 to i32
+ %133 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %134 = atomicrmw or i32* %133, i32 %132 monotonic
+ %135 = or i32 %134, %132
+ store i32 %135, i32* @ui, align 4
+ %136 = load i8* @uc, align 1
+ %137 = zext i8 %136 to i64
+ %138 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %139 = atomicrmw or i64* %138, i64 %137 monotonic
+ %140 = or i64 %139, %137
+ store i64 %140, i64* @sl, align 8
+ %141 = load i8* @uc, align 1
+ %142 = zext i8 %141 to i64
+ %143 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %144 = atomicrmw or i64* %143, i64 %142 monotonic
+ %145 = or i64 %144, %142
+ store i64 %145, i64* @ul, align 8
+ %146 = load i8* @uc, align 1
+ %147 = zext i8 %146 to i64
+ %148 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %149 = atomicrmw or i64* %148, i64 %147 monotonic
+ %150 = or i64 %149, %147
+ store i64 %150, i64* @sll, align 8
+ %151 = load i8* @uc, align 1
+ %152 = zext i8 %151 to i64
+ %153 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %154 = atomicrmw or i64* %153, i64 %152 monotonic
+ %155 = or i64 %154, %152
+ store i64 %155, i64* @ull, align 8
+ %156 = load i8* @uc, align 1
+ %157 = zext i8 %156 to i32
+ %158 = trunc i32 %157 to i8
+ %159 = atomicrmw xor i8* @sc, i8 %158 monotonic
+ %160 = xor i8 %159, %158
+ store i8 %160, i8* @sc, align 1
+ %161 = load i8* @uc, align 1
+ %162 = zext i8 %161 to i32
+ %163 = trunc i32 %162 to i8
+ %164 = atomicrmw xor i8* @uc, i8 %163 monotonic
+ %165 = xor i8 %164, %163
+ store i8 %165, i8* @uc, align 1
+ %166 = load i8* @uc, align 1
+ %167 = zext i8 %166 to i32
+ %168 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %169 = trunc i32 %167 to i16
+ %170 = atomicrmw xor i16* %168, i16 %169 monotonic
+ %171 = xor i16 %170, %169
+ store i16 %171, i16* @ss, align 2
+ %172 = load i8* @uc, align 1
+ %173 = zext i8 %172 to i32
+ %174 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %175 = trunc i32 %173 to i16
+ %176 = atomicrmw xor i16* %174, i16 %175 monotonic
+ %177 = xor i16 %176, %175
+ store i16 %177, i16* @us, align 2
+ %178 = load i8* @uc, align 1
+ %179 = zext i8 %178 to i32
+ %180 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %181 = atomicrmw xor i32* %180, i32 %179 monotonic
+ %182 = xor i32 %181, %179
+ store i32 %182, i32* @si, align 4
+ %183 = load i8* @uc, align 1
+ %184 = zext i8 %183 to i32
+ %185 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %186 = atomicrmw xor i32* %185, i32 %184 monotonic
+ %187 = xor i32 %186, %184
+ store i32 %187, i32* @ui, align 4
+ %188 = load i8* @uc, align 1
+ %189 = zext i8 %188 to i64
+ %190 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %191 = atomicrmw xor i64* %190, i64 %189 monotonic
+ %192 = xor i64 %191, %189
+ store i64 %192, i64* @sl, align 8
+ %193 = load i8* @uc, align 1
+ %194 = zext i8 %193 to i64
+ %195 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %196 = atomicrmw xor i64* %195, i64 %194 monotonic
+ %197 = xor i64 %196, %194
+ store i64 %197, i64* @ul, align 8
+ %198 = load i8* @uc, align 1
+ %199 = zext i8 %198 to i64
+ %200 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %201 = atomicrmw xor i64* %200, i64 %199 monotonic
+ %202 = xor i64 %201, %199
+ store i64 %202, i64* @sll, align 8
+ %203 = load i8* @uc, align 1
+ %204 = zext i8 %203 to i64
+ %205 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %206 = atomicrmw xor i64* %205, i64 %204 monotonic
+ %207 = xor i64 %206, %204
+ store i64 %207, i64* @ull, align 8
+ %208 = load i8* @uc, align 1
+ %209 = zext i8 %208 to i32
+ %210 = trunc i32 %209 to i8
+ %211 = atomicrmw and i8* @sc, i8 %210 monotonic
+ %212 = and i8 %211, %210
+ store i8 %212, i8* @sc, align 1
+ %213 = load i8* @uc, align 1
+ %214 = zext i8 %213 to i32
+ %215 = trunc i32 %214 to i8
+ %216 = atomicrmw and i8* @uc, i8 %215 monotonic
+ %217 = and i8 %216, %215
+ store i8 %217, i8* @uc, align 1
+ %218 = load i8* @uc, align 1
+ %219 = zext i8 %218 to i32
+ %220 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %221 = trunc i32 %219 to i16
+ %222 = atomicrmw and i16* %220, i16 %221 monotonic
+ %223 = and i16 %222, %221
+ store i16 %223, i16* @ss, align 2
+ %224 = load i8* @uc, align 1
+ %225 = zext i8 %224 to i32
+ %226 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %227 = trunc i32 %225 to i16
+ %228 = atomicrmw and i16* %226, i16 %227 monotonic
+ %229 = and i16 %228, %227
+ store i16 %229, i16* @us, align 2
+ %230 = load i8* @uc, align 1
+ %231 = zext i8 %230 to i32
+ %232 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %233 = atomicrmw and i32* %232, i32 %231 monotonic
+ %234 = and i32 %233, %231
+ store i32 %234, i32* @si, align 4
+ %235 = load i8* @uc, align 1
+ %236 = zext i8 %235 to i32
+ %237 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %238 = atomicrmw and i32* %237, i32 %236 monotonic
+ %239 = and i32 %238, %236
+ store i32 %239, i32* @ui, align 4
+ %240 = load i8* @uc, align 1
+ %241 = zext i8 %240 to i64
+ %242 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %243 = atomicrmw and i64* %242, i64 %241 monotonic
+ %244 = and i64 %243, %241
+ store i64 %244, i64* @sl, align 8
+ %245 = load i8* @uc, align 1
+ %246 = zext i8 %245 to i64
+ %247 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %248 = atomicrmw and i64* %247, i64 %246 monotonic
+ %249 = and i64 %248, %246
+ store i64 %249, i64* @ul, align 8
+ %250 = load i8* @uc, align 1
+ %251 = zext i8 %250 to i64
+ %252 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %253 = atomicrmw and i64* %252, i64 %251 monotonic
+ %254 = and i64 %253, %251
+ store i64 %254, i64* @sll, align 8
+ %255 = load i8* @uc, align 1
+ %256 = zext i8 %255 to i64
+ %257 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %258 = atomicrmw and i64* %257, i64 %256 monotonic
+ %259 = and i64 %258, %256
+ store i64 %259, i64* @ull, align 8
+ %260 = load i8* @uc, align 1
+ %261 = zext i8 %260 to i32
+ %262 = trunc i32 %261 to i8
+ %263 = atomicrmw nand i8* @sc, i8 %262 monotonic
+ %264 = xor i8 %263, -1
+ %265 = and i8 %264, %262
+ store i8 %265, i8* @sc, align 1
+ %266 = load i8* @uc, align 1
+ %267 = zext i8 %266 to i32
+ %268 = trunc i32 %267 to i8
+ %269 = atomicrmw nand i8* @uc, i8 %268 monotonic
+ %270 = xor i8 %269, -1
+ %271 = and i8 %270, %268
+ store i8 %271, i8* @uc, align 1
+ %272 = load i8* @uc, align 1
+ %273 = zext i8 %272 to i32
+ %274 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %275 = trunc i32 %273 to i16
+ %276 = atomicrmw nand i16* %274, i16 %275 monotonic
+ %277 = xor i16 %276, -1
+ %278 = and i16 %277, %275
+ store i16 %278, i16* @ss, align 2
+ %279 = load i8* @uc, align 1
+ %280 = zext i8 %279 to i32
+ %281 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %282 = trunc i32 %280 to i16
+ %283 = atomicrmw nand i16* %281, i16 %282 monotonic
+ %284 = xor i16 %283, -1
+ %285 = and i16 %284, %282
+ store i16 %285, i16* @us, align 2
+ %286 = load i8* @uc, align 1
+ %287 = zext i8 %286 to i32
+ %288 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %289 = atomicrmw nand i32* %288, i32 %287 monotonic
+ %290 = xor i32 %289, -1
+ %291 = and i32 %290, %287
+ store i32 %291, i32* @si, align 4
+ %292 = load i8* @uc, align 1
+ %293 = zext i8 %292 to i32
+ %294 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %295 = atomicrmw nand i32* %294, i32 %293 monotonic
+ %296 = xor i32 %295, -1
+ %297 = and i32 %296, %293
+ store i32 %297, i32* @ui, align 4
+ %298 = load i8* @uc, align 1
+ %299 = zext i8 %298 to i64
+ %300 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %301 = atomicrmw nand i64* %300, i64 %299 monotonic
+ %302 = xor i64 %301, -1
+ %303 = and i64 %302, %299
+ store i64 %303, i64* @sl, align 8
+ %304 = load i8* @uc, align 1
+ %305 = zext i8 %304 to i64
+ %306 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %307 = atomicrmw nand i64* %306, i64 %305 monotonic
+ %308 = xor i64 %307, -1
+ %309 = and i64 %308, %305
+ store i64 %309, i64* @ul, align 8
+ %310 = load i8* @uc, align 1
+ %311 = zext i8 %310 to i64
+ %312 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %313 = atomicrmw nand i64* %312, i64 %311 monotonic
+ %314 = xor i64 %313, -1
+ %315 = and i64 %314, %311
+ store i64 %315, i64* @sll, align 8
+ %316 = load i8* @uc, align 1
+ %317 = zext i8 %316 to i64
+ %318 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %319 = atomicrmw nand i64* %318, i64 %317 monotonic
+ %320 = xor i64 %319, -1
+ %321 = and i64 %320, %317
+ store i64 %321, i64* @ull, align 8
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
define void @test_compare_and_swap() nounwind {
entry:
- load i8* @sc, align 1 ; <i8>:0 [#uses=1]
- zext i8 %0 to i32 ; <i32>:1 [#uses=1]
- load i8* @uc, align 1 ; <i8>:2 [#uses=1]
- zext i8 %2 to i32 ; <i32>:3 [#uses=1]
- trunc i32 %3 to i8 ; <i8>:4 [#uses=1]
- trunc i32 %1 to i8 ; <i8>:5 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @sc, i8 %4, i8 %5 ) ; <i8>:6 [#uses=1]
- store i8 %6, i8* @sc, align 1
- load i8* @sc, align 1 ; <i8>:7 [#uses=1]
- zext i8 %7 to i32 ; <i32>:8 [#uses=1]
- load i8* @uc, align 1 ; <i8>:9 [#uses=1]
- zext i8 %9 to i32 ; <i32>:10 [#uses=1]
- trunc i32 %10 to i8 ; <i8>:11 [#uses=1]
- trunc i32 %8 to i8 ; <i8>:12 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @uc, i8 %11, i8 %12 ) ; <i8>:13 [#uses=1]
- store i8 %13, i8* @uc, align 1
- load i8* @sc, align 1 ; <i8>:14 [#uses=1]
- sext i8 %14 to i16 ; <i16>:15 [#uses=1]
- zext i16 %15 to i32 ; <i32>:16 [#uses=1]
- load i8* @uc, align 1 ; <i8>:17 [#uses=1]
- zext i8 %17 to i32 ; <i32>:18 [#uses=1]
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:19 [#uses=1]
- trunc i32 %18 to i16 ; <i16>:20 [#uses=1]
- trunc i32 %16 to i16 ; <i16>:21 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %19, i16 %20, i16 %21 ) ; <i16>:22 [#uses=1]
- store i16 %22, i16* @ss, align 2
- load i8* @sc, align 1 ; <i8>:23 [#uses=1]
- sext i8 %23 to i16 ; <i16>:24 [#uses=1]
- zext i16 %24 to i32 ; <i32>:25 [#uses=1]
- load i8* @uc, align 1 ; <i8>:26 [#uses=1]
- zext i8 %26 to i32 ; <i32>:27 [#uses=1]
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:28 [#uses=1]
- trunc i32 %27 to i16 ; <i16>:29 [#uses=1]
- trunc i32 %25 to i16 ; <i16>:30 [#uses=1]
- call i16 @llvm.atomic.cmp.swap.i16.p0i16( i16* %28, i16 %29, i16 %30 ) ; <i16>:31 [#uses=1]
- store i16 %31, i16* @us, align 2
- load i8* @sc, align 1 ; <i8>:32 [#uses=1]
- sext i8 %32 to i32 ; <i32>:33 [#uses=1]
- load i8* @uc, align 1 ; <i8>:34 [#uses=1]
- zext i8 %34 to i32 ; <i32>:35 [#uses=1]
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:36 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %36, i32 %35, i32 %33 ) ; <i32>:37 [#uses=1]
- store i32 %37, i32* @si, align 4
- load i8* @sc, align 1 ; <i8>:38 [#uses=1]
- sext i8 %38 to i32 ; <i32>:39 [#uses=1]
- load i8* @uc, align 1 ; <i8>:40 [#uses=1]
- zext i8 %40 to i32 ; <i32>:41 [#uses=1]
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:42 [#uses=1]
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %42, i32 %41, i32 %39 ) ; <i32>:43 [#uses=1]
- store i32 %43, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:44 [#uses=1]
- sext i8 %44 to i64 ; <i64>:45 [#uses=1]
- load i8* @uc, align 1 ; <i8>:46 [#uses=1]
- zext i8 %46 to i64 ; <i64>:47 [#uses=1]
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:48 [#uses=1]
- call i64 @llvm.atomic.cmp.swap.i64.p0i64( i64* %48, i64 %47, i64 %45 ) ; <i64>:49 [#uses=1]
- store i64 %49, i64* @sl, align 8
- load i8* @sc, align 1 ; <i8>:50 [#uses=1]
- sext i8 %50 to i64 ; <i64>:51 [#uses=1]
- load i8* @uc, align 1 ; <i8>:52 [#uses=1]
- zext i8 %52 to i64 ; <i64>:53 [#uses=1]
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:54 [#uses=1]
- call i64 @llvm.atomic.cmp.swap.i64.p0i64( i64* %54, i64 %53, i64 %51 ) ; <i64>:55 [#uses=1]
- store i64 %55, i64* @ul, align 8
- load i8* @sc, align 1 ; <i8>:56 [#uses=1]
- sext i8 %56 to i64 ; <i64>:57 [#uses=1]
- load i8* @uc, align 1 ; <i8>:58 [#uses=1]
- zext i8 %58 to i64 ; <i64>:59 [#uses=1]
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:60 [#uses=1]
- call i64 @llvm.atomic.cmp.swap.i64.p0i64( i64* %60, i64 %59, i64 %57 ) ; <i64>:61 [#uses=1]
- store i64 %61, i64* @sll, align 8
- load i8* @sc, align 1 ; <i8>:62 [#uses=1]
- sext i8 %62 to i64 ; <i64>:63 [#uses=1]
- load i8* @uc, align 1 ; <i8>:64 [#uses=1]
- zext i8 %64 to i64 ; <i64>:65 [#uses=1]
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:66 [#uses=1]
- call i64 @llvm.atomic.cmp.swap.i64.p0i64( i64* %66, i64 %65, i64 %63 ) ; <i64>:67 [#uses=1]
- store i64 %67, i64* @ull, align 8
- load i8* @sc, align 1 ; <i8>:68 [#uses=1]
- zext i8 %68 to i32 ; <i32>:69 [#uses=1]
- load i8* @uc, align 1 ; <i8>:70 [#uses=1]
- zext i8 %70 to i32 ; <i32>:71 [#uses=1]
- trunc i32 %71 to i8 ; <i8>:72 [#uses=2]
- trunc i32 %69 to i8 ; <i8>:73 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @sc, i8 %72, i8 %73 ) ; <i8>:74 [#uses=1]
- icmp eq i8 %74, %72 ; <i1>:75 [#uses=1]
- zext i1 %75 to i8 ; <i8>:76 [#uses=1]
- zext i8 %76 to i32 ; <i32>:77 [#uses=1]
- store i32 %77, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:78 [#uses=1]
- zext i8 %78 to i32 ; <i32>:79 [#uses=1]
- load i8* @uc, align 1 ; <i8>:80 [#uses=1]
- zext i8 %80 to i32 ; <i32>:81 [#uses=1]
- trunc i32 %81 to i8 ; <i8>:82 [#uses=2]
- trunc i32 %79 to i8 ; <i8>:83 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* @uc, i8 %82, i8 %83 ) ; <i8>:84 [#uses=1]
- icmp eq i8 %84, %82 ; <i1>:85 [#uses=1]
- zext i1 %85 to i8 ; <i8>:86 [#uses=1]
- zext i8 %86 to i32 ; <i32>:87 [#uses=1]
- store i32 %87, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:88 [#uses=1]
- sext i8 %88 to i16 ; <i16>:89 [#uses=1]
- zext i16 %89 to i32 ; <i32>:90 [#uses=1]
- load i8* @uc, align 1 ; <i8>:91 [#uses=1]
- zext i8 %91 to i32 ; <i32>:92 [#uses=1]
- trunc i32 %92 to i8 ; <i8>:93 [#uses=2]
- trunc i32 %90 to i8 ; <i8>:94 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i16* @ss to i8*), i8 %93, i8 %94 ) ; <i8>:95 [#uses=1]
- icmp eq i8 %95, %93 ; <i1>:96 [#uses=1]
- zext i1 %96 to i8 ; <i8>:97 [#uses=1]
- zext i8 %97 to i32 ; <i32>:98 [#uses=1]
- store i32 %98, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:99 [#uses=1]
- sext i8 %99 to i16 ; <i16>:100 [#uses=1]
- zext i16 %100 to i32 ; <i32>:101 [#uses=1]
- load i8* @uc, align 1 ; <i8>:102 [#uses=1]
- zext i8 %102 to i32 ; <i32>:103 [#uses=1]
- trunc i32 %103 to i8 ; <i8>:104 [#uses=2]
- trunc i32 %101 to i8 ; <i8>:105 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i16* @us to i8*), i8 %104, i8 %105 ) ; <i8>:106 [#uses=1]
- icmp eq i8 %106, %104 ; <i1>:107 [#uses=1]
- zext i1 %107 to i8 ; <i8>:108 [#uses=1]
- zext i8 %108 to i32 ; <i32>:109 [#uses=1]
- store i32 %109, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:110 [#uses=1]
- sext i8 %110 to i32 ; <i32>:111 [#uses=1]
- load i8* @uc, align 1 ; <i8>:112 [#uses=1]
- zext i8 %112 to i32 ; <i32>:113 [#uses=1]
- trunc i32 %113 to i8 ; <i8>:114 [#uses=2]
- trunc i32 %111 to i8 ; <i8>:115 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i32* @si to i8*), i8 %114, i8 %115 ) ; <i8>:116 [#uses=1]
- icmp eq i8 %116, %114 ; <i1>:117 [#uses=1]
- zext i1 %117 to i8 ; <i8>:118 [#uses=1]
- zext i8 %118 to i32 ; <i32>:119 [#uses=1]
- store i32 %119, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:120 [#uses=1]
- sext i8 %120 to i32 ; <i32>:121 [#uses=1]
- load i8* @uc, align 1 ; <i8>:122 [#uses=1]
- zext i8 %122 to i32 ; <i32>:123 [#uses=1]
- trunc i32 %123 to i8 ; <i8>:124 [#uses=2]
- trunc i32 %121 to i8 ; <i8>:125 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i32* @ui to i8*), i8 %124, i8 %125 ) ; <i8>:126 [#uses=1]
- icmp eq i8 %126, %124 ; <i1>:127 [#uses=1]
- zext i1 %127 to i8 ; <i8>:128 [#uses=1]
- zext i8 %128 to i32 ; <i32>:129 [#uses=1]
- store i32 %129, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:130 [#uses=1]
- sext i8 %130 to i64 ; <i64>:131 [#uses=1]
- load i8* @uc, align 1 ; <i8>:132 [#uses=1]
- zext i8 %132 to i64 ; <i64>:133 [#uses=1]
- trunc i64 %133 to i8 ; <i8>:134 [#uses=2]
- trunc i64 %131 to i8 ; <i8>:135 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i64* @sl to i8*), i8 %134, i8 %135 ) ; <i8>:136 [#uses=1]
- icmp eq i8 %136, %134 ; <i1>:137 [#uses=1]
- zext i1 %137 to i8 ; <i8>:138 [#uses=1]
- zext i8 %138 to i32 ; <i32>:139 [#uses=1]
- store i32 %139, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:140 [#uses=1]
- sext i8 %140 to i64 ; <i64>:141 [#uses=1]
- load i8* @uc, align 1 ; <i8>:142 [#uses=1]
- zext i8 %142 to i64 ; <i64>:143 [#uses=1]
- trunc i64 %143 to i8 ; <i8>:144 [#uses=2]
- trunc i64 %141 to i8 ; <i8>:145 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i64* @ul to i8*), i8 %144, i8 %145 ) ; <i8>:146 [#uses=1]
- icmp eq i8 %146, %144 ; <i1>:147 [#uses=1]
- zext i1 %147 to i8 ; <i8>:148 [#uses=1]
- zext i8 %148 to i32 ; <i32>:149 [#uses=1]
- store i32 %149, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:150 [#uses=1]
- sext i8 %150 to i64 ; <i64>:151 [#uses=1]
- load i8* @uc, align 1 ; <i8>:152 [#uses=1]
- zext i8 %152 to i64 ; <i64>:153 [#uses=1]
- trunc i64 %153 to i8 ; <i8>:154 [#uses=2]
- trunc i64 %151 to i8 ; <i8>:155 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i64* @sll to i8*), i8 %154, i8 %155 ) ; <i8>:156 [#uses=1]
- icmp eq i8 %156, %154 ; <i1>:157 [#uses=1]
- zext i1 %157 to i8 ; <i8>:158 [#uses=1]
- zext i8 %158 to i32 ; <i32>:159 [#uses=1]
- store i32 %159, i32* @ui, align 4
- load i8* @sc, align 1 ; <i8>:160 [#uses=1]
- sext i8 %160 to i64 ; <i64>:161 [#uses=1]
- load i8* @uc, align 1 ; <i8>:162 [#uses=1]
- zext i8 %162 to i64 ; <i64>:163 [#uses=1]
- trunc i64 %163 to i8 ; <i8>:164 [#uses=2]
- trunc i64 %161 to i8 ; <i8>:165 [#uses=1]
- call i8 @llvm.atomic.cmp.swap.i8.p0i8( i8* bitcast (i64* @ull to i8*), i8 %164, i8 %165 ) ; <i8>:166 [#uses=1]
- icmp eq i8 %166, %164 ; <i1>:167 [#uses=1]
- zext i1 %167 to i8 ; <i8>:168 [#uses=1]
- zext i8 %168 to i32 ; <i32>:169 [#uses=1]
- store i32 %169, i32* @ui, align 4
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = load i8* @sc, align 1
+ %1 = zext i8 %0 to i32
+ %2 = load i8* @uc, align 1
+ %3 = zext i8 %2 to i32
+ %4 = trunc i32 %3 to i8
+ %5 = trunc i32 %1 to i8
+ %6 = cmpxchg i8* @sc, i8 %4, i8 %5 monotonic
+ store i8 %6, i8* @sc, align 1
+ %7 = load i8* @sc, align 1
+ %8 = zext i8 %7 to i32
+ %9 = load i8* @uc, align 1
+ %10 = zext i8 %9 to i32
+ %11 = trunc i32 %10 to i8
+ %12 = trunc i32 %8 to i8
+ %13 = cmpxchg i8* @uc, i8 %11, i8 %12 monotonic
+ store i8 %13, i8* @uc, align 1
+ %14 = load i8* @sc, align 1
+ %15 = sext i8 %14 to i16
+ %16 = zext i16 %15 to i32
+ %17 = load i8* @uc, align 1
+ %18 = zext i8 %17 to i32
+ %19 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %20 = trunc i32 %18 to i16
+ %21 = trunc i32 %16 to i16
+ %22 = cmpxchg i16* %19, i16 %20, i16 %21 monotonic
+ store i16 %22, i16* @ss, align 2
+ %23 = load i8* @sc, align 1
+ %24 = sext i8 %23 to i16
+ %25 = zext i16 %24 to i32
+ %26 = load i8* @uc, align 1
+ %27 = zext i8 %26 to i32
+ %28 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %29 = trunc i32 %27 to i16
+ %30 = trunc i32 %25 to i16
+ %31 = cmpxchg i16* %28, i16 %29, i16 %30 monotonic
+ store i16 %31, i16* @us, align 2
+ %32 = load i8* @sc, align 1
+ %33 = sext i8 %32 to i32
+ %34 = load i8* @uc, align 1
+ %35 = zext i8 %34 to i32
+ %36 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %37 = cmpxchg i32* %36, i32 %35, i32 %33 monotonic
+ store i32 %37, i32* @si, align 4
+ %38 = load i8* @sc, align 1
+ %39 = sext i8 %38 to i32
+ %40 = load i8* @uc, align 1
+ %41 = zext i8 %40 to i32
+ %42 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %43 = cmpxchg i32* %42, i32 %41, i32 %39 monotonic
+ store i32 %43, i32* @ui, align 4
+ %44 = load i8* @sc, align 1
+ %45 = sext i8 %44 to i64
+ %46 = load i8* @uc, align 1
+ %47 = zext i8 %46 to i64
+ %48 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %49 = cmpxchg i64* %48, i64 %47, i64 %45 monotonic
+ store i64 %49, i64* @sl, align 8
+ %50 = load i8* @sc, align 1
+ %51 = sext i8 %50 to i64
+ %52 = load i8* @uc, align 1
+ %53 = zext i8 %52 to i64
+ %54 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %55 = cmpxchg i64* %54, i64 %53, i64 %51 monotonic
+ store i64 %55, i64* @ul, align 8
+ %56 = load i8* @sc, align 1
+ %57 = sext i8 %56 to i64
+ %58 = load i8* @uc, align 1
+ %59 = zext i8 %58 to i64
+ %60 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %61 = cmpxchg i64* %60, i64 %59, i64 %57 monotonic
+ store i64 %61, i64* @sll, align 8
+ %62 = load i8* @sc, align 1
+ %63 = sext i8 %62 to i64
+ %64 = load i8* @uc, align 1
+ %65 = zext i8 %64 to i64
+ %66 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %67 = cmpxchg i64* %66, i64 %65, i64 %63 monotonic
+ store i64 %67, i64* @ull, align 8
+ %68 = load i8* @sc, align 1
+ %69 = zext i8 %68 to i32
+ %70 = load i8* @uc, align 1
+ %71 = zext i8 %70 to i32
+ %72 = trunc i32 %71 to i8
+ %73 = trunc i32 %69 to i8
+ %74 = cmpxchg i8* @sc, i8 %72, i8 %73 monotonic
+ %75 = icmp eq i8 %74, %72
+ %76 = zext i1 %75 to i8
+ %77 = zext i8 %76 to i32
+ store i32 %77, i32* @ui, align 4
+ %78 = load i8* @sc, align 1
+ %79 = zext i8 %78 to i32
+ %80 = load i8* @uc, align 1
+ %81 = zext i8 %80 to i32
+ %82 = trunc i32 %81 to i8
+ %83 = trunc i32 %79 to i8
+ %84 = cmpxchg i8* @uc, i8 %82, i8 %83 monotonic
+ %85 = icmp eq i8 %84, %82
+ %86 = zext i1 %85 to i8
+ %87 = zext i8 %86 to i32
+ store i32 %87, i32* @ui, align 4
+ %88 = load i8* @sc, align 1
+ %89 = sext i8 %88 to i16
+ %90 = zext i16 %89 to i32
+ %91 = load i8* @uc, align 1
+ %92 = zext i8 %91 to i32
+ %93 = trunc i32 %92 to i8
+ %94 = trunc i32 %90 to i8
+ %95 = cmpxchg i8* bitcast (i16* @ss to i8*), i8 %93, i8 %94 monotonic
+ %96 = icmp eq i8 %95, %93
+ %97 = zext i1 %96 to i8
+ %98 = zext i8 %97 to i32
+ store i32 %98, i32* @ui, align 4
+ %99 = load i8* @sc, align 1
+ %100 = sext i8 %99 to i16
+ %101 = zext i16 %100 to i32
+ %102 = load i8* @uc, align 1
+ %103 = zext i8 %102 to i32
+ %104 = trunc i32 %103 to i8
+ %105 = trunc i32 %101 to i8
+ %106 = cmpxchg i8* bitcast (i16* @us to i8*), i8 %104, i8 %105 monotonic
+ %107 = icmp eq i8 %106, %104
+ %108 = zext i1 %107 to i8
+ %109 = zext i8 %108 to i32
+ store i32 %109, i32* @ui, align 4
+ %110 = load i8* @sc, align 1
+ %111 = sext i8 %110 to i32
+ %112 = load i8* @uc, align 1
+ %113 = zext i8 %112 to i32
+ %114 = trunc i32 %113 to i8
+ %115 = trunc i32 %111 to i8
+ %116 = cmpxchg i8* bitcast (i32* @si to i8*), i8 %114, i8 %115 monotonic
+ %117 = icmp eq i8 %116, %114
+ %118 = zext i1 %117 to i8
+ %119 = zext i8 %118 to i32
+ store i32 %119, i32* @ui, align 4
+ %120 = load i8* @sc, align 1
+ %121 = sext i8 %120 to i32
+ %122 = load i8* @uc, align 1
+ %123 = zext i8 %122 to i32
+ %124 = trunc i32 %123 to i8
+ %125 = trunc i32 %121 to i8
+ %126 = cmpxchg i8* bitcast (i32* @ui to i8*), i8 %124, i8 %125 monotonic
+ %127 = icmp eq i8 %126, %124
+ %128 = zext i1 %127 to i8
+ %129 = zext i8 %128 to i32
+ store i32 %129, i32* @ui, align 4
+ %130 = load i8* @sc, align 1
+ %131 = sext i8 %130 to i64
+ %132 = load i8* @uc, align 1
+ %133 = zext i8 %132 to i64
+ %134 = trunc i64 %133 to i8
+ %135 = trunc i64 %131 to i8
+ %136 = cmpxchg i8* bitcast (i64* @sl to i8*), i8 %134, i8 %135 monotonic
+ %137 = icmp eq i8 %136, %134
+ %138 = zext i1 %137 to i8
+ %139 = zext i8 %138 to i32
+ store i32 %139, i32* @ui, align 4
+ %140 = load i8* @sc, align 1
+ %141 = sext i8 %140 to i64
+ %142 = load i8* @uc, align 1
+ %143 = zext i8 %142 to i64
+ %144 = trunc i64 %143 to i8
+ %145 = trunc i64 %141 to i8
+ %146 = cmpxchg i8* bitcast (i64* @ul to i8*), i8 %144, i8 %145 monotonic
+ %147 = icmp eq i8 %146, %144
+ %148 = zext i1 %147 to i8
+ %149 = zext i8 %148 to i32
+ store i32 %149, i32* @ui, align 4
+ %150 = load i8* @sc, align 1
+ %151 = sext i8 %150 to i64
+ %152 = load i8* @uc, align 1
+ %153 = zext i8 %152 to i64
+ %154 = trunc i64 %153 to i8
+ %155 = trunc i64 %151 to i8
+ %156 = cmpxchg i8* bitcast (i64* @sll to i8*), i8 %154, i8 %155 monotonic
+ %157 = icmp eq i8 %156, %154
+ %158 = zext i1 %157 to i8
+ %159 = zext i8 %158 to i32
+ store i32 %159, i32* @ui, align 4
+ %160 = load i8* @sc, align 1
+ %161 = sext i8 %160 to i64
+ %162 = load i8* @uc, align 1
+ %163 = zext i8 %162 to i64
+ %164 = trunc i64 %163 to i8
+ %165 = trunc i64 %161 to i8
+ %166 = cmpxchg i8* bitcast (i64* @ull to i8*), i8 %164, i8 %165 monotonic
+ %167 = icmp eq i8 %166, %164
+ %168 = zext i1 %167 to i8
+ %169 = zext i8 %168 to i32
+ store i32 %169, i32* @ui, align 4
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
-declare i8 @llvm.atomic.cmp.swap.i8.p0i8(i8*, i8, i8) nounwind
-
-declare i16 @llvm.atomic.cmp.swap.i16.p0i16(i16*, i16, i16) nounwind
-
-declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32*, i32, i32) nounwind
-
-declare i64 @llvm.atomic.cmp.swap.i64.p0i64(i64*, i64, i64) nounwind
-
define void @test_lock() nounwind {
entry:
- call i8 @llvm.atomic.swap.i8.p0i8( i8* @sc, i8 1 ) ; <i8>:0 [#uses=1]
- store i8 %0, i8* @sc, align 1
- call i8 @llvm.atomic.swap.i8.p0i8( i8* @uc, i8 1 ) ; <i8>:1 [#uses=1]
- store i8 %1, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:2 [#uses=1]
- call i16 @llvm.atomic.swap.i16.p0i16( i16* %2, i16 1 ) ; <i16>:3 [#uses=1]
- store i16 %3, i16* @ss, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:4 [#uses=1]
- call i16 @llvm.atomic.swap.i16.p0i16( i16* %4, i16 1 ) ; <i16>:5 [#uses=1]
- store i16 %5, i16* @us, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:6 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %6, i32 1 ) ; <i32>:7 [#uses=1]
- store i32 %7, i32* @si, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:8 [#uses=1]
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %8, i32 1 ) ; <i32>:9 [#uses=1]
- store i32 %9, i32* @ui, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:10 [#uses=1]
- call i64 @llvm.atomic.swap.i64.p0i64( i64* %10, i64 1 ) ; <i64>:11 [#uses=1]
- store i64 %11, i64* @sl, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:12 [#uses=1]
- call i64 @llvm.atomic.swap.i64.p0i64( i64* %12, i64 1 ) ; <i64>:13 [#uses=1]
- store i64 %13, i64* @ul, align 8
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:14 [#uses=1]
- call i64 @llvm.atomic.swap.i64.p0i64( i64* %14, i64 1 ) ; <i64>:15 [#uses=1]
- store i64 %15, i64* @sll, align 8
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:16 [#uses=1]
- call i64 @llvm.atomic.swap.i64.p0i64( i64* %16, i64 1 ) ; <i64>:17 [#uses=1]
- store i64 %17, i64* @ull, align 8
- call void @llvm.memory.barrier( i1 true, i1 true, i1 true, i1 true, i1 false )
- volatile store i8 0, i8* @sc, align 1
- volatile store i8 0, i8* @uc, align 1
- bitcast i8* bitcast (i16* @ss to i8*) to i16* ; <i16*>:18 [#uses=1]
- volatile store i16 0, i16* %18, align 2
- bitcast i8* bitcast (i16* @us to i8*) to i16* ; <i16*>:19 [#uses=1]
- volatile store i16 0, i16* %19, align 2
- bitcast i8* bitcast (i32* @si to i8*) to i32* ; <i32*>:20 [#uses=1]
- volatile store i32 0, i32* %20, align 4
- bitcast i8* bitcast (i32* @ui to i8*) to i32* ; <i32*>:21 [#uses=1]
- volatile store i32 0, i32* %21, align 4
- bitcast i8* bitcast (i64* @sl to i8*) to i64* ; <i64*>:22 [#uses=1]
- volatile store i64 0, i64* %22, align 8
- bitcast i8* bitcast (i64* @ul to i8*) to i64* ; <i64*>:23 [#uses=1]
- volatile store i64 0, i64* %23, align 8
- bitcast i8* bitcast (i64* @sll to i8*) to i64* ; <i64*>:24 [#uses=1]
- volatile store i64 0, i64* %24, align 8
- bitcast i8* bitcast (i64* @ull to i8*) to i64* ; <i64*>:25 [#uses=1]
- volatile store i64 0, i64* %25, align 8
- br label %return
-
-return: ; preds = %entry
- ret void
+ %0 = atomicrmw xchg i8* @sc, i8 1 monotonic
+ store i8 %0, i8* @sc, align 1
+ %1 = atomicrmw xchg i8* @uc, i8 1 monotonic
+ store i8 %1, i8* @uc, align 1
+ %2 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ %3 = atomicrmw xchg i16* %2, i16 1 monotonic
+ store i16 %3, i16* @ss, align 2
+ %4 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ %5 = atomicrmw xchg i16* %4, i16 1 monotonic
+ store i16 %5, i16* @us, align 2
+ %6 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ %7 = atomicrmw xchg i32* %6, i32 1 monotonic
+ store i32 %7, i32* @si, align 4
+ %8 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ %9 = atomicrmw xchg i32* %8, i32 1 monotonic
+ store i32 %9, i32* @ui, align 4
+ %10 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ %11 = atomicrmw xchg i64* %10, i64 1 monotonic
+ store i64 %11, i64* @sl, align 8
+ %12 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ %13 = atomicrmw xchg i64* %12, i64 1 monotonic
+ store i64 %13, i64* @ul, align 8
+ %14 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ %15 = atomicrmw xchg i64* %14, i64 1 monotonic
+ store i64 %15, i64* @sll, align 8
+ %16 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ %17 = atomicrmw xchg i64* %16, i64 1 monotonic
+ store i64 %17, i64* @ull, align 8
+ fence seq_cst
+ store volatile i8 0, i8* @sc, align 1
+ store volatile i8 0, i8* @uc, align 1
+ %18 = bitcast i8* bitcast (i16* @ss to i8*) to i16*
+ store volatile i16 0, i16* %18, align 2
+ %19 = bitcast i8* bitcast (i16* @us to i8*) to i16*
+ store volatile i16 0, i16* %19, align 2
+ %20 = bitcast i8* bitcast (i32* @si to i8*) to i32*
+ store volatile i32 0, i32* %20, align 4
+ %21 = bitcast i8* bitcast (i32* @ui to i8*) to i32*
+ store volatile i32 0, i32* %21, align 4
+ %22 = bitcast i8* bitcast (i64* @sl to i8*) to i64*
+ store volatile i64 0, i64* %22, align 8
+ %23 = bitcast i8* bitcast (i64* @ul to i8*) to i64*
+ store volatile i64 0, i64* %23, align 8
+ %24 = bitcast i8* bitcast (i64* @sll to i8*) to i64*
+ store volatile i64 0, i64* %24, align 8
+ %25 = bitcast i8* bitcast (i64* @ull to i8*) to i64*
+ store volatile i64 0, i64* %25, align 8
+ br label %return
+
+return: ; preds = %entry
+ ret void
}
-
-declare i8 @llvm.atomic.swap.i8.p0i8(i8*, i8) nounwind
-
-declare i16 @llvm.atomic.swap.i16.p0i16(i16*, i16) nounwind
-
-declare i32 @llvm.atomic.swap.i32.p0i32(i32*, i32) nounwind
-
-declare i64 @llvm.atomic.swap.i64.p0i64(i64*, i64) nounwind
-
-declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
diff --git a/test/CodeGen/X86/MachineSink-DbgValue.ll b/test/CodeGen/X86/MachineSink-DbgValue.ll
new file mode 100644
index 0000000..ea791a3
--- /dev/null
+++ b/test/CodeGen/X86/MachineSink-DbgValue.ll
@@ -0,0 +1,49 @@
+; RUN: llc < %s | FileCheck %s
+; Should sink matching DBG_VALUEs also.
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+define i32 @foo(i32 %i, i32* nocapture %c) nounwind uwtable readonly ssp {
+ tail call void @llvm.dbg.value(metadata !{i32 %i}, i64 0, metadata !6), !dbg !12
+ %ab = load i32* %c, align 1, !dbg !14
+ tail call void @llvm.dbg.value(metadata !{i32* %c}, i64 0, metadata !7), !dbg !13
+ tail call void @llvm.dbg.value(metadata !{i32 %ab}, i64 0, metadata !10), !dbg !14
+ %cd = icmp eq i32 %i, 42, !dbg !15
+ br i1 %cd, label %bb1, label %bb2, !dbg !15
+
+bb1: ; preds = %0
+;CHECK: DEBUG_VALUE: a
+;CHECK-NEXT: .loc 1 5 5
+;CHECK-NEXT: addl
+ %gh = add nsw i32 %ab, 2, !dbg !16
+ br label %bb2, !dbg !16
+
+bb2:
+ %.0 = phi i32 [ %gh, %bb1 ], [ 0, %0 ]
+ ret i32 %.0, !dbg !17
+}
+
+declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone
+
+!llvm.dbg.cu = !{!0}
+!llvm.dbg.sp = !{!1}
+!llvm.dbg.lv.foo = !{!6, !7, !10}
+
+!0 = metadata !{i32 589841, i32 0, i32 12, metadata !"a.c", metadata !"/private/tmp", metadata !"Apple clang version 3.0 (tags/Apple/clang-211.10.1) (based on LLVM 3.0svn)", i1 true, i1 true, metadata !"", i32 0} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{i32 589870, i32 0, metadata !2, metadata !"foo", metadata !"foo", metadata !"", metadata !2, i32 2, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, i32 (i32, i32*)* @foo, null, null} ; [ DW_TAG_subprogram ]
+!2 = metadata !{i32 589865, metadata !"a.c", metadata !"/private/tmp", metadata !0} ; [ DW_TAG_file_type ]
+!3 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 589860, metadata !0, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!6 = metadata !{i32 590081, metadata !1, metadata !"i", metadata !2, i32 16777218, metadata !5, i32 0} ; [ DW_TAG_arg_variable ]
+!7 = metadata !{i32 590081, metadata !1, metadata !"c", metadata !2, i32 33554434, metadata !8, i32 0} ; [ DW_TAG_arg_variable ]
+!8 = metadata !{i32 589839, metadata !0, metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !9} ; [ DW_TAG_pointer_type ]
+!9 = metadata !{i32 589860, metadata !0, metadata !"char", null, i32 0, i64 8, i64 8, i64 0, i32 0, i32 6} ; [ DW_TAG_base_type ]
+!10 = metadata !{i32 590080, metadata !11, metadata !"a", metadata !2, i32 3, metadata !9, i32 0} ; [ DW_TAG_auto_variable ]
+!11 = metadata !{i32 589835, metadata !1, i32 2, i32 25, metadata !2, i32 0} ; [ DW_TAG_lexical_block ]
+!12 = metadata !{i32 2, i32 13, metadata !1, null}
+!13 = metadata !{i32 2, i32 22, metadata !1, null}
+!14 = metadata !{i32 3, i32 14, metadata !11, null}
+!15 = metadata !{i32 4, i32 3, metadata !11, null}
+!16 = metadata !{i32 5, i32 5, metadata !11, null}
+!17 = metadata !{i32 7, i32 1, metadata !11, null}
diff --git a/test/CodeGen/X86/MachineSink-eflags.ll b/test/CodeGen/X86/MachineSink-eflags.ll
new file mode 100644
index 0000000..5b8c7b2
--- /dev/null
+++ b/test/CodeGen/X86/MachineSink-eflags.ll
@@ -0,0 +1,74 @@
+; RUN: llc < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-pc-linux"
+
+
+%0 = type <{ i64, i64, %1, %1, [21 x %2] }>
+%1 = type <{ i64, i64, i64 }>
+%2 = type <{ i32, i32, i8 addrspace(2)* }>
+%3 = type { i8*, i8*, i8*, i8*, i32 }
+%4 = type <{ %5*, i8*, i32, i32, [4 x i64], [4 x i64], [4 x i64], [4 x i64], [4 x i64] }>
+%5 = type <{ void (i32)*, i8*, i32 (i8*, ...)* }>
+
+define void @foo(i8* nocapture %_stubArgs) nounwind {
+entry:
+ %i0 = alloca i8*, align 8
+ %i2 = alloca i8*, align 8
+ %b.i = alloca [16 x <2 x double>], align 16
+ %conv = bitcast i8* %_stubArgs to i32*
+ %tmp1 = load i32* %conv, align 4
+ %ptr8 = getelementptr i8* %_stubArgs, i64 16
+ %i4 = bitcast i8* %ptr8 to <2 x double>*
+ %ptr20 = getelementptr i8* %_stubArgs, i64 48
+ %i7 = bitcast i8* %ptr20 to <2 x double> addrspace(1)**
+ %tmp21 = load <2 x double> addrspace(1)** %i7, align 8
+ %ptr28 = getelementptr i8* %_stubArgs, i64 64
+ %i9 = bitcast i8* %ptr28 to i32*
+ %tmp29 = load i32* %i9, align 4
+ %ptr32 = getelementptr i8* %_stubArgs, i64 68
+ %i10 = bitcast i8* %ptr32 to i32*
+ %tmp33 = load i32* %i10, align 4
+ %tmp17.i = mul i32 10, 20
+ %tmp19.i = add i32 %tmp17.i, %tmp33
+ %conv21.i = zext i32 %tmp19.i to i64
+ %tmp6.i = and i32 42, -32
+ %tmp42.i = add i32 %tmp6.i, 17
+ %tmp44.i = insertelement <2 x i32> undef, i32 %tmp42.i, i32 1
+ %tmp96676677.i = or i32 17, -4
+ %ptr4438.i = getelementptr inbounds [16 x <2 x double>]* %b.i, i64 0, i64 0
+ %arrayidx4506.i = getelementptr [16 x <2 x double>]* %b.i, i64 0, i64 4
+ %tmp52.i = insertelement <2 x i32> %tmp44.i, i32 0, i32 0
+ %tmp78.i = extractelement <2 x i32> %tmp44.i, i32 1
+ %tmp97.i = add i32 %tmp78.i, %tmp96676677.i
+ %tmp99.i = insertelement <2 x i32> %tmp52.i, i32 %tmp97.i, i32 1
+ %tmp154.i = extractelement <2 x i32> %tmp99.i, i32 1
+ %tmp156.i = extractelement <2 x i32> %tmp52.i, i32 0
+ %tmp158.i = urem i32 %tmp156.i, %tmp1
+ %i38 = mul i32 %tmp154.i, %tmp29
+ %i39 = add i32 %tmp158.i, %i38
+ %conv160.i = zext i32 %i39 to i64
+ %tmp22.sum652.i = add i64 %conv160.i, %conv21.i
+ %arrayidx161.i = getelementptr <2 x double> addrspace(1)* %tmp21, i64 %tmp22.sum652.i
+ %tmp162.i = load <2 x double> addrspace(1)* %arrayidx161.i, align 16
+ %tmp222.i = add i32 %tmp154.i, 1
+ %i43 = mul i32 %tmp222.i, %tmp29
+ %i44 = add i32 %tmp158.i, %i43
+ %conv228.i = zext i32 %i44 to i64
+ %tmp22.sum656.i = add i64 %conv228.i, %conv21.i
+ %arrayidx229.i = getelementptr <2 x double> addrspace(1)* %tmp21, i64 %tmp22.sum656.i
+ %tmp230.i = load <2 x double> addrspace(1)* %arrayidx229.i, align 16
+ %cmp432.i = icmp ult i32 %tmp156.i, %tmp1
+
+; %shl.i should not be sinked below the compare.
+; CHECK: cmpl
+; CHECK-NOT: shlq
+
+ %cond.i = select i1 %cmp432.i, <2 x double> %tmp162.i, <2 x double> zeroinitializer
+ store <2 x double> %cond.i, <2 x double>* %ptr4438.i, align 16
+ %cond448.i = select i1 %cmp432.i, <2 x double> %tmp230.i, <2 x double> zeroinitializer
+ store <2 x double> %cond448.i, <2 x double>* %arrayidx4506.i, align 16
+ ret void
+}
+
+
+
diff --git a/test/CodeGen/X86/SIMD/dg.exp b/test/CodeGen/X86/SIMD/dg.exp
deleted file mode 100644
index 629a147..0000000
--- a/test/CodeGen/X86/SIMD/dg.exp
+++ /dev/null
@@ -1,5 +0,0 @@
-load_lib llvm.exp
-
-if { [llvm_supports_target X86] } {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
-}
diff --git a/test/CodeGen/X86/SIMD/notvunpcklpd.ll b/test/CodeGen/X86/SIMD/notvunpcklpd.ll
deleted file mode 100644
index 3afc2f2..0000000
--- a/test/CodeGen/X86/SIMD/notvunpcklpd.ll
+++ /dev/null
@@ -1,20 +0,0 @@
-; RUN: llc < %s -mattr=+avx | FileCheck %s
-
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
-target triple = "x86_64-unknown-linux-gnu"
-
-define void @try_([2 x <4 x double>]* noalias %incarray, [2 x <4 x double>]* noalias %incarrayb ) {
-entry:
- %incarray1 = alloca [2 x <4 x double>]*, align 8
- %incarrayb1 = alloca [2 x <4 x double>]*, align 8
- %carray = alloca [2 x <4 x double>], align 16
- %r = getelementptr [2 x <4 x double>]* %incarray, i32 0, i32 0
- %rb = getelementptr [2 x <4 x double>]* %incarrayb, i32 0, i32 0
- %r3 = load <4 x double>* %r, align 8
- %r4 = load <4 x double>* %rb, align 8
- %r11 = shufflevector <4 x double> %r3, <4 x double> %r4, <4 x i32> < i32 0, i32 4, i32 1, i32 5 > ; <<4 x double>> [#uses=1]
-; CHECK-NOT: vunpcklpd
- %r12 = getelementptr [2 x <4 x double>]* %carray, i32 0, i32 1
- store <4 x double> %r11, <4 x double>* %r12, align 4
- ret void
-}
diff --git a/test/CodeGen/X86/SIMD/notvunpcklps.ll b/test/CodeGen/X86/SIMD/notvunpcklps.ll
deleted file mode 100644
index 19daa3e..0000000
--- a/test/CodeGen/X86/SIMD/notvunpcklps.ll
+++ /dev/null
@@ -1,20 +0,0 @@
-; RUN: llc < %s -mattr=+avx | FileCheck %s
-
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
-target triple = "x86_64-unknown-linux-gnu"
-
-define void @try_([2 x <8 x float>]* noalias %incarray, [2 x <8 x float>]* noalias %incarrayb ) {
-enmtry:
- %incarray1 = alloca [2 x <8 x float>]*, align 8
- %incarrayb1 = alloca [2 x <8 x float>]*, align 8
- %carray = alloca [2 x <8 x float>], align 16
- %r = getelementptr [2 x <8 x float>]* %incarray, i32 0, i32 0
- %rb = getelementptr [2 x <8 x float>]* %incarrayb, i32 0, i32 0
- %r3 = load <8 x float>* %r, align 8
- %r4 = load <8 x float>* %rb, align 8
- %r8 = shufflevector <8 x float> %r3, <8 x float> %r4, <8 x i32> < i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11 > ; <<8 x float>> [#uses=1]
-; CHECK-NOT: vunpcklps
- %r9 = getelementptr [2 x <8 x float>]* %carray, i32 0, i32 0
- store <8 x float> %r8, <8 x float>* %r9, align 4
- ret void
-}
diff --git a/test/CodeGen/X86/SIMD/vunpcklpd.ll b/test/CodeGen/X86/SIMD/vunpcklpd.ll
deleted file mode 100644
index 60d23a4..0000000
--- a/test/CodeGen/X86/SIMD/vunpcklpd.ll
+++ /dev/null
@@ -1,20 +0,0 @@
-; RUN: llc < %s -mattr=+avx | FileCheck %s
-
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
-target triple = "x86_64-unknown-linux-gnu"
-
-define void @try_([2 x <4 x double>]* noalias %incarray, [2 x <4 x double>]* noalias %incarrayb ) {
-entry:
- %incarray1 = alloca [2 x <4 x double>]*, align 8
- %incarrayb1 = alloca [2 x <4 x double>]*, align 8
- %carray = alloca [2 x <4 x double>], align 16
- %r = getelementptr [2 x <4 x double>]* %incarray, i32 0, i32 0
- %rb = getelementptr [2 x <4 x double>]* %incarrayb, i32 0, i32 0
- %r3 = load <4 x double>* %r, align 8
- %r4 = load <4 x double>* %rb, align 8
- %r11 = shufflevector <4 x double> %r3, <4 x double> %r4, <4 x i32> < i32 0, i32 4, i32 2, i32 6 > ; <<4 x double>> [#uses=1]
-; CHECK: vunpcklpd
- %r12 = getelementptr [2 x <4 x double>]* %carray, i32 0, i32 1
- store <4 x double> %r11, <4 x double>* %r12, align 4
- ret void
-}
diff --git a/test/CodeGen/X86/SIMD/vunpcklps.ll b/test/CodeGen/X86/SIMD/vunpcklps.ll
deleted file mode 100644
index a87b299..0000000
--- a/test/CodeGen/X86/SIMD/vunpcklps.ll
+++ /dev/null
@@ -1,20 +0,0 @@
-; RUN: llc < %s -mattr=+avx | FileCheck %s
-
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
-target triple = "x86_64-unknown-linux-gnu"
-
-define void @try_([2 x <8 x float>]* noalias %incarray, [2 x <8 x float>]* noalias %incarrayb ) {
-entry:
- %incarray1 = alloca [2 x <8 x float>]*, align 8
- %incarrayb1 = alloca [2 x <8 x float>]*, align 8
- %carray = alloca [2 x <8 x float>], align 16
- %r = getelementptr [2 x <8 x float>]* %incarray, i32 0, i32 0
- %rb = getelementptr [2 x <8 x float>]* %incarrayb, i32 0, i32 0
- %r3 = load <8 x float>* %r, align 8
- %r4 = load <8 x float>* %rb, align 8
- %r11 = shufflevector <8 x float> %r3, <8 x float> %r4, <8 x i32> < i32 0, i32 8, i32 1, i32 9, i32 4, i32 12, i32 5, i32 13 > ; <<8 x float>> [#uses=1]
-; CHECK: vunpcklps
- %r12 = getelementptr [2 x <8 x float>]* %carray, i32 0, i32 1
- store <8 x float> %r11, <8 x float>* %r12, align 4
- ret void
-}
diff --git a/test/CodeGen/X86/alignment-2.ll b/test/CodeGen/X86/alignment-2.ll
new file mode 100644
index 0000000..cc709b5
--- /dev/null
+++ b/test/CodeGen/X86/alignment-2.ll
@@ -0,0 +1,28 @@
+; RUN: llc < %s -mtriple i386-apple-darwin10 | FileCheck %s
+; <rdar://problem/10058036>
+
+%struct._psqlSettings = type { %struct.pg_conn*, i32, %struct.__sFILE*, i8, %struct.printQueryOpt, i8*, i8, i32, %struct.__sFILE*, i8, i32, i8*, i8*, i8*, i64, i8, %struct.__sFILE*, %struct._variable*, i8, i8, i8, i8, i8, i32, i32, i32, i32, i32, i8*, i8*, i8*, i32 }
+%struct.pg_conn = type opaque
+%struct.__sFILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 }
+%struct.__sbuf = type { i8*, i32 }
+%struct.__sFILEX = type opaque
+%struct.printQueryOpt = type { %struct.printTableOpt, i8*, i8, i8*, i8**, i8, i8, i8* }
+%struct.printTableOpt = type { i32, i8, i16, i16, i8, i8, i8, i32, %struct.printTextFormat*, i8*, i8*, i8, i8*, i32, i32, i32 }
+%struct.printTextFormat = type { i8*, [4 x %struct.printTextLineFormat], i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8 }
+%struct.printTextLineFormat = type { i8*, i8*, i8*, i8* }
+%struct._variable = type { i8*, i8*, void (i8*)*, %struct._variable* }
+%struct.pg_result = type opaque
+
+@pset = external global %struct._psqlSettings
+
+define signext i8 @do_lo_list() nounwind optsize ssp {
+bb:
+; CHECK: do_lo_list
+; CHECK-NOT: movaps
+ %myopt = alloca %struct.printQueryOpt, align 4
+ %tmp = bitcast %struct.printQueryOpt* %myopt to i8*
+ call void @llvm.memcpy.p0i8.p0i8.i32(i8* %tmp, i8* bitcast (%struct.printQueryOpt* getelementptr inbounds (%struct._psqlSettings* @pset, i32 0, i32 4) to i8*), i32 76, i32 4, i1 false)
+ ret i8 0
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
diff --git a/test/CodeGen/X86/alignment.ll b/test/CodeGen/X86/alignment.ll
index 7e91115..5908c0c 100644
--- a/test/CodeGen/X86/alignment.ll
+++ b/test/CodeGen/X86/alignment.ll
@@ -40,4 +40,4 @@
; CHECK: .comm GlobalBS,384,8
@GlobalCS = common global { [384 x i8] } zeroinitializer, align 2, section "foo"
-; CHECK: .comm GlobalCS,384,2 \ No newline at end of file
+; CHECK: .comm GlobalCS,384,2
diff --git a/test/CodeGen/X86/asm-label2.ll b/test/CodeGen/X86/asm-label2.ll
index 0b5de34..8715aa9 100644
--- a/test/CodeGen/X86/asm-label2.ll
+++ b/test/CodeGen/X86/asm-label2.ll
@@ -16,7 +16,11 @@ invoke.cont: ; preds = %entry
ret void
lpad: ; preds = %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
declare void @_zed() ssp align 2
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/atomic-load-store-wide.ll b/test/CodeGen/X86/atomic-load-store-wide.ll
new file mode 100644
index 0000000..a9ebfef
--- /dev/null
+++ b/test/CodeGen/X86/atomic-load-store-wide.ll
@@ -0,0 +1,19 @@
+; RUN: llc < %s -march=x86 | FileCheck %s
+
+; 64-bit load/store on x86-32
+; FIXME: The generated code can be substantially improved.
+
+define void @test1(i64* %ptr, i64 %val1) {
+; CHECK: test1
+; CHECK: cmpxchg8b
+; CHECK-NEXT: jne
+ store atomic i64 %val1, i64* %ptr seq_cst, align 8
+ ret void
+}
+
+define i64 @test2(i64* %ptr) {
+; CHECK: test2
+; CHECK: cmpxchg8b
+ %val = load atomic i64* %ptr seq_cst, align 8
+ ret i64 %val
+}
diff --git a/test/CodeGen/X86/atomic-load-store.ll b/test/CodeGen/X86/atomic-load-store.ll
new file mode 100644
index 0000000..fee4585
--- /dev/null
+++ b/test/CodeGen/X86/atomic-load-store.ll
@@ -0,0 +1,23 @@
+; RUN: llc < %s -mtriple=x86_64-apple-macosx10.7.0 -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-apple-macosx10.7.0 -O0 | FileCheck %s
+
+define void @test1(i32* %ptr, i32 %val1) {
+; CHECK: test1
+; CHECK: xchgl %esi, (%rdi)
+ store atomic i32 %val1, i32* %ptr seq_cst, align 4
+ ret void
+}
+
+define void @test2(i32* %ptr, i32 %val1) {
+; CHECK: test2
+; CHECK: movl %esi, (%rdi)
+ store atomic i32 %val1, i32* %ptr release, align 4
+ ret void
+}
+
+define i32 @test3(i32* %ptr) {
+; CHECK: test3
+; CHECK: movl (%rdi), %eax
+ %val = load atomic i32* %ptr seq_cst, align 4
+ ret i32 %val
+}
diff --git a/test/CodeGen/X86/atomic-or.ll b/test/CodeGen/X86/atomic-or.ll
index 164252d..3f02eaf 100644
--- a/test/CodeGen/X86/atomic-or.ll
+++ b/test/CodeGen/X86/atomic-or.ll
@@ -7,13 +7,11 @@ entry:
%p.addr = alloca i64*, align 8
store i64* %p, i64** %p.addr, align 8
%tmp = load i64** %p.addr, align 8
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
; CHECK: t1:
; CHECK: movl $2147483648, %eax
; CHECK: lock
; CHECK-NEXT: orq %r{{.*}}, (%r{{.*}})
- %0 = call i64 @llvm.atomic.load.or.i64.p0i64(i64* %tmp, i64 2147483648)
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
+ %0 = atomicrmw or i64* %tmp, i64 2147483648 seq_cst
ret void
}
@@ -22,15 +20,9 @@ entry:
%p.addr = alloca i64*, align 8
store i64* %p, i64** %p.addr, align 8
%tmp = load i64** %p.addr, align 8
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
; CHECK: t2:
-; CHECK-NOT: movl
; CHECK: lock
; CHECK-NEXT: orq $2147483644, (%r{{.*}})
- %0 = call i64 @llvm.atomic.load.or.i64.p0i64(i64* %tmp, i64 2147483644)
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
+ %0 = atomicrmw or i64* %tmp, i64 2147483644 seq_cst
ret void
}
-
-declare i64 @llvm.atomic.load.or.i64.p0i64(i64* nocapture, i64) nounwind
-declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
diff --git a/test/CodeGen/X86/atomic_add.ll b/test/CodeGen/X86/atomic_add.ll
index 26d25e2..1fce256 100644
--- a/test/CodeGen/X86/atomic_add.ll
+++ b/test/CodeGen/X86/atomic_add.ll
@@ -6,80 +6,74 @@ define void @sub1(i32* nocapture %p, i32 %v) nounwind ssp {
entry:
; CHECK: sub1:
; CHECK: subl
- %0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 %v) ; <i32> [#uses=0]
- ret void
+ %0 = atomicrmw sub i32* %p, i32 %v monotonic
+ ret void
}
define void @inc4(i64* nocapture %p) nounwind ssp {
entry:
; CHECK: inc4:
; CHECK: incq
- %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1) ; <i64> [#uses=0]
- ret void
+ %0 = atomicrmw add i64* %p, i64 1 monotonic
+ ret void
}
-declare i64 @llvm.atomic.load.add.i64.p0i64(i64* nocapture, i64) nounwind
-
define void @add8(i64* nocapture %p) nounwind ssp {
entry:
; CHECK: add8:
; CHECK: addq $2
- %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 2) ; <i64> [#uses=0]
- ret void
+ %0 = atomicrmw add i64* %p, i64 2 monotonic
+ ret void
}
define void @add4(i64* nocapture %p, i32 %v) nounwind ssp {
entry:
; CHECK: add4:
; CHECK: addq
- %0 = sext i32 %v to i64 ; <i64> [#uses=1]
- %1 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 %0) ; <i64> [#uses=0]
- ret void
+ %0 = sext i32 %v to i64 ; <i64> [#uses=1]
+ %1 = atomicrmw add i64* %p, i64 %0 monotonic
+ ret void
}
define void @inc3(i8* nocapture %p) nounwind ssp {
entry:
; CHECK: inc3:
; CHECK: incb
- %0 = tail call i8 @llvm.atomic.load.add.i8.p0i8(i8* %p, i8 1) ; <i8> [#uses=0]
- ret void
+ %0 = atomicrmw add i8* %p, i8 1 monotonic
+ ret void
}
-declare i8 @llvm.atomic.load.add.i8.p0i8(i8* nocapture, i8) nounwind
-
define void @add7(i8* nocapture %p) nounwind ssp {
entry:
; CHECK: add7:
; CHECK: addb $2
- %0 = tail call i8 @llvm.atomic.load.add.i8.p0i8(i8* %p, i8 2) ; <i8> [#uses=0]
- ret void
+ %0 = atomicrmw add i8* %p, i8 2 monotonic
+ ret void
}
define void @add3(i8* nocapture %p, i32 %v) nounwind ssp {
entry:
; CHECK: add3:
; CHECK: addb
- %0 = trunc i32 %v to i8 ; <i8> [#uses=1]
- %1 = tail call i8 @llvm.atomic.load.add.i8.p0i8(i8* %p, i8 %0) ; <i8> [#uses=0]
- ret void
+ %0 = trunc i32 %v to i8 ; <i8> [#uses=1]
+ %1 = atomicrmw add i8* %p, i8 %0 monotonic
+ ret void
}
define void @inc2(i16* nocapture %p) nounwind ssp {
entry:
; CHECK: inc2:
; CHECK: incw
- %0 = tail call i16 @llvm.atomic.load.add.i16.p0i16(i16* %p, i16 1) ; <i16> [#uses=0]
- ret void
+ %0 = atomicrmw add i16* %p, i16 1 monotonic
+ ret void
}
-declare i16 @llvm.atomic.load.add.i16.p0i16(i16* nocapture, i16) nounwind
-
define void @add6(i16* nocapture %p) nounwind ssp {
entry:
; CHECK: add6:
; CHECK: addw $2
- %0 = tail call i16 @llvm.atomic.load.add.i16.p0i16(i16* %p, i16 2) ; <i16> [#uses=0]
- ret void
+ %0 = atomicrmw add i16* %p, i16 2 monotonic
+ ret void
}
define void @add2(i16* nocapture %p, i32 %v) nounwind ssp {
@@ -87,52 +81,48 @@ entry:
; CHECK: add2:
; CHECK: addw
%0 = trunc i32 %v to i16 ; <i16> [#uses=1]
- %1 = tail call i16 @llvm.atomic.load.add.i16.p0i16(i16* %p, i16 %0) ; <i16> [#uses=0]
- ret void
+ %1 = atomicrmw add i16* %p, i16 %0 monotonic
+ ret void
}
define void @inc1(i32* nocapture %p) nounwind ssp {
entry:
; CHECK: inc1:
; CHECK: incl
- %0 = tail call i32 @llvm.atomic.load.add.i32.p0i32(i32* %p, i32 1) ; <i32> [#uses=0]
- ret void
+ %0 = atomicrmw add i32* %p, i32 1 monotonic
+ ret void
}
-declare i32 @llvm.atomic.load.add.i32.p0i32(i32* nocapture, i32) nounwind
-
define void @add5(i32* nocapture %p) nounwind ssp {
entry:
; CHECK: add5:
; CHECK: addl $2
- %0 = tail call i32 @llvm.atomic.load.add.i32.p0i32(i32* %p, i32 2) ; <i32> [#uses=0]
- ret void
+ %0 = atomicrmw add i32* %p, i32 2 monotonic
+ ret void
}
define void @add1(i32* nocapture %p, i32 %v) nounwind ssp {
entry:
; CHECK: add1:
; CHECK: addl
- %0 = tail call i32 @llvm.atomic.load.add.i32.p0i32(i32* %p, i32 %v) ; <i32> [#uses=0]
- ret void
+ %0 = atomicrmw add i32* %p, i32 %v monotonic
+ ret void
}
define void @dec4(i64* nocapture %p) nounwind ssp {
entry:
; CHECK: dec4:
; CHECK: decq
- %0 = tail call i64 @llvm.atomic.load.sub.i64.p0i64(i64* %p, i64 1) ; <i64> [#uses=0]
- ret void
+ %0 = atomicrmw sub i64* %p, i64 1 monotonic
+ ret void
}
-declare i64 @llvm.atomic.load.sub.i64.p0i64(i64* nocapture, i64) nounwind
-
define void @sub8(i64* nocapture %p) nounwind ssp {
entry:
; CHECK: sub8:
; CHECK: subq $2
- %0 = tail call i64 @llvm.atomic.load.sub.i64.p0i64(i64* %p, i64 2) ; <i64> [#uses=0]
- ret void
+ %0 = atomicrmw sub i64* %p, i64 2 monotonic
+ ret void
}
define void @sub4(i64* nocapture %p, i32 %v) nounwind ssp {
@@ -140,26 +130,24 @@ entry:
; CHECK: sub4:
; CHECK: subq
%0 = sext i32 %v to i64 ; <i64> [#uses=1]
- %1 = tail call i64 @llvm.atomic.load.sub.i64.p0i64(i64* %p, i64 %0) ; <i64> [#uses=0]
- ret void
+ %1 = atomicrmw sub i64* %p, i64 %0 monotonic
+ ret void
}
define void @dec3(i8* nocapture %p) nounwind ssp {
entry:
; CHECK: dec3:
; CHECK: decb
- %0 = tail call i8 @llvm.atomic.load.sub.i8.p0i8(i8* %p, i8 1) ; <i8> [#uses=0]
- ret void
+ %0 = atomicrmw sub i8* %p, i8 1 monotonic
+ ret void
}
-declare i8 @llvm.atomic.load.sub.i8.p0i8(i8* nocapture, i8) nounwind
-
define void @sub7(i8* nocapture %p) nounwind ssp {
entry:
; CHECK: sub7:
; CHECK: subb $2
- %0 = tail call i8 @llvm.atomic.load.sub.i8.p0i8(i8* %p, i8 2) ; <i8> [#uses=0]
- ret void
+ %0 = atomicrmw sub i8* %p, i8 2 monotonic
+ ret void
}
define void @sub3(i8* nocapture %p, i32 %v) nounwind ssp {
@@ -167,26 +155,24 @@ entry:
; CHECK: sub3:
; CHECK: subb
%0 = trunc i32 %v to i8 ; <i8> [#uses=1]
- %1 = tail call i8 @llvm.atomic.load.sub.i8.p0i8(i8* %p, i8 %0) ; <i8> [#uses=0]
- ret void
+ %1 = atomicrmw sub i8* %p, i8 %0 monotonic
+ ret void
}
define void @dec2(i16* nocapture %p) nounwind ssp {
entry:
; CHECK: dec2:
; CHECK: decw
- %0 = tail call i16 @llvm.atomic.load.sub.i16.p0i16(i16* %p, i16 1) ; <i16> [#uses=0]
- ret void
+ %0 = atomicrmw sub i16* %p, i16 1 monotonic
+ ret void
}
-declare i16 @llvm.atomic.load.sub.i16.p0i16(i16* nocapture, i16) nounwind
-
define void @sub6(i16* nocapture %p) nounwind ssp {
entry:
; CHECK: sub6:
; CHECK: subw $2
- %0 = tail call i16 @llvm.atomic.load.sub.i16.p0i16(i16* %p, i16 2) ; <i16> [#uses=0]
- ret void
+ %0 = atomicrmw sub i16* %p, i16 2 monotonic
+ ret void
}
define void @sub2(i16* nocapture %p, i32 %v) nounwind ssp {
@@ -194,24 +180,22 @@ entry:
; CHECK: sub2:
; CHECK: negl
%0 = trunc i32 %v to i16 ; <i16> [#uses=1]
- %1 = tail call i16 @llvm.atomic.load.sub.i16.p0i16(i16* %p, i16 %0) ; <i16> [#uses=0]
- ret void
+ %1 = atomicrmw sub i16* %p, i16 %0 monotonic
+ ret void
}
define void @dec1(i32* nocapture %p) nounwind ssp {
entry:
; CHECK: dec1:
; CHECK: decl
- %0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 1) ; <i32> [#uses=0]
- ret void
+ %0 = atomicrmw sub i32* %p, i32 1 monotonic
+ ret void
}
-declare i32 @llvm.atomic.load.sub.i32.p0i32(i32* nocapture, i32) nounwind
-
define void @sub5(i32* nocapture %p) nounwind ssp {
entry:
; CHECK: sub5:
; CHECK: subl $2
- %0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 2) ; <i32> [#uses=0]
- ret void
+ %0 = atomicrmw sub i32* %p, i32 2 monotonic
+ ret void
}
diff --git a/test/CodeGen/X86/atomic_op.ll b/test/CodeGen/X86/atomic_op.ll
index f3ade93..972dab2 100644
--- a/test/CodeGen/X86/atomic_op.ll
+++ b/test/CodeGen/X86/atomic_op.ll
@@ -24,87 +24,87 @@ entry:
%tmp = load i32* %temp
; CHECK: lock
; CHECK: xaddl
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %val1, i32 %tmp ) ; <i32>:0 [#uses=1]
+ %0 = atomicrmw add i32* %val1, i32 %tmp monotonic
store i32 %0, i32* %old
; CHECK: lock
; CHECK: xaddl
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %val2, i32 30 ) ; <i32>:1 [#uses=1]
+ %1 = atomicrmw sub i32* %val2, i32 30 monotonic
store i32 %1, i32* %old
; CHECK: lock
; CHECK: xaddl
- call i32 @llvm.atomic.load.add.i32.p0i32( i32* %val2, i32 1 ) ; <i32>:2 [#uses=1]
+ %2 = atomicrmw add i32* %val2, i32 1 monotonic
store i32 %2, i32* %old
; CHECK: lock
; CHECK: xaddl
- call i32 @llvm.atomic.load.sub.i32.p0i32( i32* %val2, i32 1 ) ; <i32>:3 [#uses=1]
+ %3 = atomicrmw sub i32* %val2, i32 1 monotonic
store i32 %3, i32* %old
; CHECK: andl
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.load.and.i32.p0i32( i32* %andt, i32 4080 ) ; <i32>:4 [#uses=1]
+ %4 = atomicrmw and i32* %andt, i32 4080 monotonic
store i32 %4, i32* %old
; CHECK: orl
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.load.or.i32.p0i32( i32* %ort, i32 4080 ) ; <i32>:5 [#uses=1]
+ %5 = atomicrmw or i32* %ort, i32 4080 monotonic
store i32 %5, i32* %old
; CHECK: xorl
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.load.xor.i32.p0i32( i32* %xort, i32 4080 ) ; <i32>:6 [#uses=1]
+ %6 = atomicrmw xor i32* %xort, i32 4080 monotonic
store i32 %6, i32* %old
; CHECK: cmov
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.load.min.i32.p0i32( i32* %val2, i32 16 ) ; <i32>:7 [#uses=1]
+ %7 = atomicrmw min i32* %val2, i32 16 monotonic
store i32 %7, i32* %old
%neg = sub i32 0, 1 ; <i32> [#uses=1]
; CHECK: cmov
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.load.min.i32.p0i32( i32* %val2, i32 %neg ) ; <i32>:8 [#uses=1]
+ %8 = atomicrmw min i32* %val2, i32 %neg monotonic
store i32 %8, i32* %old
; CHECK: cmov
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.load.max.i32.p0i32( i32* %val2, i32 1 ) ; <i32>:9 [#uses=1]
+ %9 = atomicrmw max i32* %val2, i32 1 monotonic
store i32 %9, i32* %old
; CHECK: cmov
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.load.max.i32.p0i32( i32* %val2, i32 0 ) ; <i32>:10 [#uses=1]
+ %10 = atomicrmw max i32* %val2, i32 0 monotonic
store i32 %10, i32* %old
; CHECK: cmov
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.load.umax.i32.p0i32( i32* %val2, i32 65535 ) ; <i32>:11 [#uses=1]
+ %11 = atomicrmw umax i32* %val2, i32 65535 monotonic
store i32 %11, i32* %old
; CHECK: cmov
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.load.umax.i32.p0i32( i32* %val2, i32 10 ) ; <i32>:12 [#uses=1]
+ %12 = atomicrmw umax i32* %val2, i32 10 monotonic
store i32 %12, i32* %old
; CHECK: cmov
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.load.umin.i32.p0i32( i32* %val2, i32 1 ) ; <i32>:13 [#uses=1]
+ %13 = atomicrmw umin i32* %val2, i32 1 monotonic
store i32 %13, i32* %old
; CHECK: cmov
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.load.umin.i32.p0i32( i32* %val2, i32 10 ) ; <i32>:14 [#uses=1]
+ %14 = atomicrmw umin i32* %val2, i32 10 monotonic
store i32 %14, i32* %old
; CHECK: xchgl %{{.*}}, {{.*}}(%esp)
- call i32 @llvm.atomic.swap.i32.p0i32( i32* %val2, i32 1976 ) ; <i32>:15 [#uses=1]
+ %15 = atomicrmw xchg i32* %val2, i32 1976 monotonic
store i32 %15, i32* %old
%neg1 = sub i32 0, 10 ; <i32> [#uses=1]
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %val2, i32 %neg1, i32 1 ) ; <i32>:16 [#uses=1]
+ %16 = cmpxchg i32* %val2, i32 %neg1, i32 1 monotonic
store i32 %16, i32* %old
; CHECK: lock
; CHECK: cmpxchgl
- call i32 @llvm.atomic.cmp.swap.i32.p0i32( i32* %val2, i32 1976, i32 1 ) ; <i32>:17 [#uses=1]
+ %17 = cmpxchg i32* %val2, i32 1976, i32 1 monotonic
store i32 %17, i32* %old
ret void
}
@@ -114,30 +114,6 @@ entry:
; CHECK: lock
; CHECK: cmpxchgl %{{.*}}, %gs:(%{{.*}})
- %0 = tail call i32 @llvm.atomic.cmp.swap.i32.p256i32(i32 addrspace(256)* %P, i32 0, i32 1)
+ %0 = cmpxchg i32 addrspace(256)* %P, i32 0, i32 1 monotonic
ret void
}
-
-declare i32 @llvm.atomic.cmp.swap.i32.p256i32(i32 addrspace(256)* nocapture, i32, i32) nounwind
-
-declare i32 @llvm.atomic.load.add.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.sub.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.and.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.or.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.xor.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.min.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.max.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.umax.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.load.umin.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.swap.i32.p0i32(i32*, i32) nounwind
-
-declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32*, i32, i32) nounwind
diff --git a/test/CodeGen/X86/avx-128.ll b/test/CodeGen/X86/avx-128.ll
deleted file mode 100644
index 57a3826..0000000
--- a/test/CodeGen/X86/avx-128.ll
+++ /dev/null
@@ -1,54 +0,0 @@
-; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
-
-@z = common global <4 x float> zeroinitializer, align 16
-
-define void @zero() nounwind ssp {
-entry:
- ; CHECK: vxorps
- ; CHECK: vmovaps
- store <4 x float> zeroinitializer, <4 x float>* @z, align 16
- ret void
-}
-
-define void @fpext() nounwind uwtable {
-entry:
- %f = alloca float, align 4
- %d = alloca double, align 8
- %tmp = load float* %f, align 4
- ; CHECK: vcvtss2sd
- %conv = fpext float %tmp to double
- store double %conv, double* %d, align 8
- ret void
-}
-
-; CHECK: vcvtsi2sdq (%
-define double @funcA(i64* nocapture %e) nounwind uwtable readonly ssp {
-entry:
- %tmp1 = load i64* %e, align 8
- %conv = sitofp i64 %tmp1 to double
- ret double %conv
-}
-
-; CHECK: vcvtsi2sd (%
-define double @funcB(i32* nocapture %e) nounwind uwtable readonly ssp {
-entry:
- %tmp1 = load i32* %e, align 4
- %conv = sitofp i32 %tmp1 to double
- ret double %conv
-}
-
-; CHECK: vcvtsi2ss (%
-define float @funcC(i32* nocapture %e) nounwind uwtable readonly ssp {
-entry:
- %tmp1 = load i32* %e, align 4
- %conv = sitofp i32 %tmp1 to float
- ret float %conv
-}
-
-; CHECK: vcvtsi2ssq (%
-define float @funcD(i64* nocapture %e) nounwind uwtable readonly ssp {
-entry:
- %tmp1 = load i64* %e, align 8
- %conv = sitofp i64 %tmp1 to float
- ret float %conv
-}
diff --git a/test/CodeGen/X86/avx-256-arith.ll b/test/CodeGen/X86/avx-256-arith.ll
deleted file mode 100644
index 5c512db..0000000
--- a/test/CodeGen/X86/avx-256-arith.ll
+++ /dev/null
@@ -1,116 +0,0 @@
-; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
-
-; CHECK: vaddpd
-define <4 x double> @addpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
-entry:
- %add.i = fadd <4 x double> %x, %y
- ret <4 x double> %add.i
-}
-
-; CHECK: vaddpd LCP{{.*}}(%rip)
-define <4 x double> @addpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
-entry:
- %add.i = fadd <4 x double> %y, <double 4.500000e+00, double 3.400000e+00, double 2.300000e+00, double 1.200000e+00>
- ret <4 x double> %add.i
-}
-
-; CHECK: vaddps
-define <8 x float> @addps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
-entry:
- %add.i = fadd <8 x float> %x, %y
- ret <8 x float> %add.i
-}
-
-; CHECK: vaddps LCP{{.*}}(%rip)
-define <8 x float> @addps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
-entry:
- %add.i = fadd <8 x float> %y, <float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000, float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000>
- ret <8 x float> %add.i
-}
-
-; CHECK: vsubpd
-define <4 x double> @subpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
-entry:
- %sub.i = fsub <4 x double> %x, %y
- ret <4 x double> %sub.i
-}
-
-; CHECK: vsubpd (%
-define <4 x double> @subpd256fold(<4 x double> %y, <4 x double>* nocapture %x) nounwind uwtable readonly ssp {
-entry:
- %tmp2 = load <4 x double>* %x, align 32
- %sub.i = fsub <4 x double> %y, %tmp2
- ret <4 x double> %sub.i
-}
-
-; CHECK: vsubps
-define <8 x float> @subps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
-entry:
- %sub.i = fsub <8 x float> %x, %y
- ret <8 x float> %sub.i
-}
-
-; CHECK: vsubps (%
-define <8 x float> @subps256fold(<8 x float> %y, <8 x float>* nocapture %x) nounwind uwtable readonly ssp {
-entry:
- %tmp2 = load <8 x float>* %x, align 32
- %sub.i = fsub <8 x float> %y, %tmp2
- ret <8 x float> %sub.i
-}
-
-; CHECK: vmulpd
-define <4 x double> @mulpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
-entry:
- %mul.i = fmul <4 x double> %x, %y
- ret <4 x double> %mul.i
-}
-
-; CHECK: vmulpd LCP{{.*}}(%rip)
-define <4 x double> @mulpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
-entry:
- %mul.i = fmul <4 x double> %y, <double 4.500000e+00, double 3.400000e+00, double 2.300000e+00, double 1.200000e+00>
- ret <4 x double> %mul.i
-}
-
-; CHECK: vmulps
-define <8 x float> @mulps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
-entry:
- %mul.i = fmul <8 x float> %x, %y
- ret <8 x float> %mul.i
-}
-
-; CHECK: vmulps LCP{{.*}}(%rip)
-define <8 x float> @mulps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
-entry:
- %mul.i = fmul <8 x float> %y, <float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000, float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000>
- ret <8 x float> %mul.i
-}
-
-; CHECK: vdivpd
-define <4 x double> @divpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
-entry:
- %div.i = fdiv <4 x double> %x, %y
- ret <4 x double> %div.i
-}
-
-; CHECK: vdivpd LCP{{.*}}(%rip)
-define <4 x double> @divpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
-entry:
- %div.i = fdiv <4 x double> %y, <double 4.500000e+00, double 3.400000e+00, double 2.300000e+00, double 1.200000e+00>
- ret <4 x double> %div.i
-}
-
-; CHECK: vdivps
-define <8 x float> @divps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
-entry:
- %div.i = fdiv <8 x float> %x, %y
- ret <8 x float> %div.i
-}
-
-; CHECK: vdivps LCP{{.*}}(%rip)
-define <8 x float> @divps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
-entry:
- %div.i = fdiv <8 x float> %y, <float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000, float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000>
- ret <8 x float> %div.i
-}
-
diff --git a/test/CodeGen/X86/avx-256-arith.s b/test/CodeGen/X86/avx-256-arith.s
deleted file mode 100644
index e69de29..0000000
--- a/test/CodeGen/X86/avx-256-arith.s
+++ /dev/null
diff --git a/test/CodeGen/X86/avx-256-logic.ll b/test/CodeGen/X86/avx-256-logic.ll
deleted file mode 100644
index d9e5d08..0000000
--- a/test/CodeGen/X86/avx-256-logic.ll
+++ /dev/null
@@ -1,161 +0,0 @@
-; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
-
-; CHECK: vandpd
-define <4 x double> @andpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <4 x double> %x to <4 x i64>
- %1 = bitcast <4 x double> %y to <4 x i64>
- %and.i = and <4 x i64> %0, %1
- %2 = bitcast <4 x i64> %and.i to <4 x double>
- ret <4 x double> %2
-}
-
-; CHECK: vandpd LCP{{.*}}(%rip)
-define <4 x double> @andpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <4 x double> %y to <4 x i64>
- %and.i = and <4 x i64> %0, <i64 4616752568008179712, i64 4614838538166547251, i64 4612361558371493478, i64 4608083138725491507>
- %1 = bitcast <4 x i64> %and.i to <4 x double>
- ret <4 x double> %1
-}
-
-; CHECK: vandps
-define <8 x float> @andps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <8 x float> %x to <8 x i32>
- %1 = bitcast <8 x float> %y to <8 x i32>
- %and.i = and <8 x i32> %0, %1
- %2 = bitcast <8 x i32> %and.i to <8 x float>
- ret <8 x float> %2
-}
-
-; CHECK: vandps LCP{{.*}}(%rip)
-define <8 x float> @andps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <8 x float> %y to <8 x i32>
- %and.i = and <8 x i32> %0, <i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938, i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938>
- %1 = bitcast <8 x i32> %and.i to <8 x float>
- ret <8 x float> %1
-}
-
-; CHECK: vxorpd
-define <4 x double> @xorpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <4 x double> %x to <4 x i64>
- %1 = bitcast <4 x double> %y to <4 x i64>
- %xor.i = xor <4 x i64> %0, %1
- %2 = bitcast <4 x i64> %xor.i to <4 x double>
- ret <4 x double> %2
-}
-
-; CHECK: vxorpd LCP{{.*}}(%rip)
-define <4 x double> @xorpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <4 x double> %y to <4 x i64>
- %xor.i = xor <4 x i64> %0, <i64 4616752568008179712, i64 4614838538166547251, i64 4612361558371493478, i64 4608083138725491507>
- %1 = bitcast <4 x i64> %xor.i to <4 x double>
- ret <4 x double> %1
-}
-
-; CHECK: vxorps
-define <8 x float> @xorps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <8 x float> %x to <8 x i32>
- %1 = bitcast <8 x float> %y to <8 x i32>
- %xor.i = xor <8 x i32> %0, %1
- %2 = bitcast <8 x i32> %xor.i to <8 x float>
- ret <8 x float> %2
-}
-
-; CHECK: vxorps LCP{{.*}}(%rip)
-define <8 x float> @xorps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <8 x float> %y to <8 x i32>
- %xor.i = xor <8 x i32> %0, <i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938, i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938>
- %1 = bitcast <8 x i32> %xor.i to <8 x float>
- ret <8 x float> %1
-}
-
-; CHECK: vorpd
-define <4 x double> @orpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <4 x double> %x to <4 x i64>
- %1 = bitcast <4 x double> %y to <4 x i64>
- %or.i = or <4 x i64> %0, %1
- %2 = bitcast <4 x i64> %or.i to <4 x double>
- ret <4 x double> %2
-}
-
-; CHECK: vorpd LCP{{.*}}(%rip)
-define <4 x double> @orpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <4 x double> %y to <4 x i64>
- %or.i = or <4 x i64> %0, <i64 4616752568008179712, i64 4614838538166547251, i64 4612361558371493478, i64 4608083138725491507>
- %1 = bitcast <4 x i64> %or.i to <4 x double>
- ret <4 x double> %1
-}
-
-; CHECK: vorps
-define <8 x float> @orps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <8 x float> %x to <8 x i32>
- %1 = bitcast <8 x float> %y to <8 x i32>
- %or.i = or <8 x i32> %0, %1
- %2 = bitcast <8 x i32> %or.i to <8 x float>
- ret <8 x float> %2
-}
-
-; CHECK: vorps LCP{{.*}}(%rip)
-define <8 x float> @orps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <8 x float> %y to <8 x i32>
- %or.i = or <8 x i32> %0, <i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938, i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938>
- %1 = bitcast <8 x i32> %or.i to <8 x float>
- ret <8 x float> %1
-}
-
-; CHECK: vandnpd
-define <4 x double> @andnotpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <4 x double> %x to <4 x i64>
- %neg.i = xor <4 x i64> %0, <i64 -1, i64 -1, i64 -1, i64 -1>
- %1 = bitcast <4 x double> %y to <4 x i64>
- %and.i = and <4 x i64> %1, %neg.i
- %2 = bitcast <4 x i64> %and.i to <4 x double>
- ret <4 x double> %2
-}
-
-; CHECK: vandnpd (%
-define <4 x double> @andnotpd256fold(<4 x double> %y, <4 x double>* nocapture %x) nounwind uwtable readonly ssp {
-entry:
- %tmp2 = load <4 x double>* %x, align 32
- %0 = bitcast <4 x double> %y to <4 x i64>
- %neg.i = xor <4 x i64> %0, <i64 -1, i64 -1, i64 -1, i64 -1>
- %1 = bitcast <4 x double> %tmp2 to <4 x i64>
- %and.i = and <4 x i64> %1, %neg.i
- %2 = bitcast <4 x i64> %and.i to <4 x double>
- ret <4 x double> %2
-}
-
-; CHECK: vandnps
-define <8 x float> @andnotps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
-entry:
- %0 = bitcast <8 x float> %x to <8 x i32>
- %neg.i = xor <8 x i32> %0, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
- %1 = bitcast <8 x float> %y to <8 x i32>
- %and.i = and <8 x i32> %1, %neg.i
- %2 = bitcast <8 x i32> %and.i to <8 x float>
- ret <8 x float> %2
-}
-
-; CHECK: vandnps (%
-define <8 x float> @andnotps256fold(<8 x float> %y, <8 x float>* nocapture %x) nounwind uwtable readonly ssp {
-entry:
- %tmp2 = load <8 x float>* %x, align 32
- %0 = bitcast <8 x float> %y to <8 x i32>
- %neg.i = xor <8 x i32> %0, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
- %1 = bitcast <8 x float> %tmp2 to <8 x i32>
- %and.i = and <8 x i32> %1, %neg.i
- %2 = bitcast <8 x i32> %and.i to <8 x float>
- ret <8 x float> %2
-}
diff --git a/test/CodeGen/X86/avx-256.ll b/test/CodeGen/X86/avx-256.ll
deleted file mode 100644
index 20d31e7..0000000
--- a/test/CodeGen/X86/avx-256.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; RUN: llc < %s -mtriple=x86_64-apple-darwin -march=x86 -mcpu=corei7 -mattr=avx | FileCheck %s
-
-@x = common global <8 x float> zeroinitializer, align 32
-@y = common global <4 x double> zeroinitializer, align 32
-
-define void @zero() nounwind ssp {
-entry:
- ; CHECK: vxorps
- ; CHECK: vmovaps
- ; CHECK: vmovaps
- store <8 x float> zeroinitializer, <8 x float>* @x, align 32
- store <4 x double> zeroinitializer, <4 x double>* @y, align 32
- ret void
-}
-
diff --git a/test/CodeGen/X86/avx-arith.ll b/test/CodeGen/X86/avx-arith.ll
new file mode 100644
index 0000000..59988ca
--- /dev/null
+++ b/test/CodeGen/X86/avx-arith.ll
@@ -0,0 +1,261 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vaddpd
+define <4 x double> @addpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
+entry:
+ %add.i = fadd <4 x double> %x, %y
+ ret <4 x double> %add.i
+}
+
+; CHECK: vaddpd LCP{{.*}}(%rip)
+define <4 x double> @addpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
+entry:
+ %add.i = fadd <4 x double> %y, <double 4.500000e+00, double 3.400000e+00, double 2.300000e+00, double 1.200000e+00>
+ ret <4 x double> %add.i
+}
+
+; CHECK: vaddps
+define <8 x float> @addps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
+entry:
+ %add.i = fadd <8 x float> %x, %y
+ ret <8 x float> %add.i
+}
+
+; CHECK: vaddps LCP{{.*}}(%rip)
+define <8 x float> @addps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
+entry:
+ %add.i = fadd <8 x float> %y, <float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000, float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000>
+ ret <8 x float> %add.i
+}
+
+; CHECK: vsubpd
+define <4 x double> @subpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
+entry:
+ %sub.i = fsub <4 x double> %x, %y
+ ret <4 x double> %sub.i
+}
+
+; CHECK: vsubpd (%
+define <4 x double> @subpd256fold(<4 x double> %y, <4 x double>* nocapture %x) nounwind uwtable readonly ssp {
+entry:
+ %tmp2 = load <4 x double>* %x, align 32
+ %sub.i = fsub <4 x double> %y, %tmp2
+ ret <4 x double> %sub.i
+}
+
+; CHECK: vsubps
+define <8 x float> @subps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
+entry:
+ %sub.i = fsub <8 x float> %x, %y
+ ret <8 x float> %sub.i
+}
+
+; CHECK: vsubps (%
+define <8 x float> @subps256fold(<8 x float> %y, <8 x float>* nocapture %x) nounwind uwtable readonly ssp {
+entry:
+ %tmp2 = load <8 x float>* %x, align 32
+ %sub.i = fsub <8 x float> %y, %tmp2
+ ret <8 x float> %sub.i
+}
+
+; CHECK: vmulpd
+define <4 x double> @mulpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
+entry:
+ %mul.i = fmul <4 x double> %x, %y
+ ret <4 x double> %mul.i
+}
+
+; CHECK: vmulpd LCP{{.*}}(%rip)
+define <4 x double> @mulpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
+entry:
+ %mul.i = fmul <4 x double> %y, <double 4.500000e+00, double 3.400000e+00, double 2.300000e+00, double 1.200000e+00>
+ ret <4 x double> %mul.i
+}
+
+; CHECK: vmulps
+define <8 x float> @mulps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
+entry:
+ %mul.i = fmul <8 x float> %x, %y
+ ret <8 x float> %mul.i
+}
+
+; CHECK: vmulps LCP{{.*}}(%rip)
+define <8 x float> @mulps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
+entry:
+ %mul.i = fmul <8 x float> %y, <float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000, float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000>
+ ret <8 x float> %mul.i
+}
+
+; CHECK: vdivpd
+define <4 x double> @divpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
+entry:
+ %div.i = fdiv <4 x double> %x, %y
+ ret <4 x double> %div.i
+}
+
+; CHECK: vdivpd LCP{{.*}}(%rip)
+define <4 x double> @divpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
+entry:
+ %div.i = fdiv <4 x double> %y, <double 4.500000e+00, double 3.400000e+00, double 2.300000e+00, double 1.200000e+00>
+ ret <4 x double> %div.i
+}
+
+; CHECK: vdivps
+define <8 x float> @divps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
+entry:
+ %div.i = fdiv <8 x float> %x, %y
+ ret <8 x float> %div.i
+}
+
+; CHECK: vdivps LCP{{.*}}(%rip)
+define <8 x float> @divps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
+entry:
+ %div.i = fdiv <8 x float> %y, <float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000, float 4.500000e+00, float 0x400B333340000000, float 0x4002666660000000, float 0x3FF3333340000000>
+ ret <8 x float> %div.i
+}
+
+; CHECK: vsqrtss
+define float @sqrtA(float %a) nounwind uwtable readnone ssp {
+entry:
+ %conv1 = tail call float @sqrtf(float %a) nounwind readnone
+ ret float %conv1
+}
+
+declare double @sqrt(double) readnone
+
+; CHECK: vsqrtsd
+define double @sqrtB(double %a) nounwind uwtable readnone ssp {
+entry:
+ %call = tail call double @sqrt(double %a) nounwind readnone
+ ret double %call
+}
+
+declare float @sqrtf(float) readnone
+
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vpaddq %xmm
+; CHECK-NEXT: vpaddq %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <4 x i64> @vpaddq(<4 x i64> %i, <4 x i64> %j) nounwind readnone {
+ %x = add <4 x i64> %i, %j
+ ret <4 x i64> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vpaddd %xmm
+; CHECK-NEXT: vpaddd %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <8 x i32> @vpaddd(<8 x i32> %i, <8 x i32> %j) nounwind readnone {
+ %x = add <8 x i32> %i, %j
+ ret <8 x i32> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vpaddw %xmm
+; CHECK-NEXT: vpaddw %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <16 x i16> @vpaddw(<16 x i16> %i, <16 x i16> %j) nounwind readnone {
+ %x = add <16 x i16> %i, %j
+ ret <16 x i16> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vpaddb %xmm
+; CHECK-NEXT: vpaddb %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <32 x i8> @vpaddb(<32 x i8> %i, <32 x i8> %j) nounwind readnone {
+ %x = add <32 x i8> %i, %j
+ ret <32 x i8> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vpsubq %xmm
+; CHECK-NEXT: vpsubq %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <4 x i64> @vpsubq(<4 x i64> %i, <4 x i64> %j) nounwind readnone {
+ %x = sub <4 x i64> %i, %j
+ ret <4 x i64> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vpsubd %xmm
+; CHECK-NEXT: vpsubd %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <8 x i32> @vpsubd(<8 x i32> %i, <8 x i32> %j) nounwind readnone {
+ %x = sub <8 x i32> %i, %j
+ ret <8 x i32> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vpsubw %xmm
+; CHECK-NEXT: vpsubw %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <16 x i16> @vpsubw(<16 x i16> %i, <16 x i16> %j) nounwind readnone {
+ %x = sub <16 x i16> %i, %j
+ ret <16 x i16> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vpsubb %xmm
+; CHECK-NEXT: vpsubb %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <32 x i8> @vpsubb(<32 x i8> %i, <32 x i8> %j) nounwind readnone {
+ %x = sub <32 x i8> %i, %j
+ ret <32 x i8> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vpmulld %xmm
+; CHECK-NEXT: vpmulld %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <8 x i32> @vpmulld(<8 x i32> %i, <8 x i32> %j) nounwind readnone {
+ %x = mul <8 x i32> %i, %j
+ ret <8 x i32> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vpmullw %xmm
+; CHECK-NEXT: vpmullw %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <16 x i16> @vpmullw(<16 x i16> %i, <16 x i16> %j) nounwind readnone {
+ %x = mul <16 x i16> %i, %j
+ ret <16 x i16> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vpmuludq %xmm
+; CHECK-NEXT: vpsrlq $32, %xmm
+; CHECK-NEXT: vpmuludq %xmm
+; CHECK-NEXT: vpsllq $32, %xmm
+; CHECK-NEXT: vpaddq %xmm
+; CHECK-NEXT: vpmuludq %xmm
+; CHECK-NEXT: vpsrlq $32, %xmm
+; CHECK-NEXT: vpmuludq %xmm
+; CHECK-NEXT: vpsllq $32, %xmm
+; CHECK-NEXT: vpsrlq $32, %xmm
+; CHECK-NEXT: vpmuludq %xmm
+; CHECK-NEXT: vpsllq $32, %xmm
+; CHECK-NEXT: vpaddq %xmm
+; CHECK-NEXT: vpaddq %xmm
+; CHECK-NEXT: vpsrlq $32, %xmm
+; CHECK-NEXT: vpmuludq %xmm
+; CHECK-NEXT: vpsllq $32, %xmm
+; CHECK-NEXT: vpaddq %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <4 x i64> @mul-v4i64(<4 x i64> %i, <4 x i64> %j) nounwind readnone {
+ %x = mul <4 x i64> %i, %j
+ ret <4 x i64> %x
+}
+
diff --git a/test/CodeGen/X86/avx-basic.ll b/test/CodeGen/X86/avx-basic.ll
new file mode 100644
index 0000000..0a46b08
--- /dev/null
+++ b/test/CodeGen/X86/avx-basic.ll
@@ -0,0 +1,107 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+@x = common global <8 x float> zeroinitializer, align 32
+@y = common global <4 x double> zeroinitializer, align 32
+@z = common global <4 x float> zeroinitializer, align 16
+
+define void @zero128() nounwind ssp {
+entry:
+ ; CHECK: vpxor
+ ; CHECK: vmovaps
+ store <4 x float> zeroinitializer, <4 x float>* @z, align 16
+ ret void
+}
+
+define void @zero256() nounwind ssp {
+entry:
+ ; CHECK: vxorps
+ ; CHECK: vmovaps
+ ; CHECK: vmovaps
+ store <8 x float> zeroinitializer, <8 x float>* @x, align 32
+ store <4 x double> zeroinitializer, <4 x double>* @y, align 32
+ ret void
+}
+
+; CHECK: vpcmpeqd
+; CHECK: vinsertf128 $1
+define void @ones([0 x float]* nocapture %RET, [0 x float]* nocapture %aFOO) nounwind {
+allocas:
+ %ptr2vec615 = bitcast [0 x float]* %RET to <8 x float>*
+ store <8 x float> <float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float
+0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float
+0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000>, <8 x
+float>* %ptr2vec615, align 32
+ ret void
+}
+
+; CHECK: vpcmpeqd
+; CHECK: vinsertf128 $1
+define void @ones2([0 x i32]* nocapture %RET, [0 x i32]* nocapture %aFOO) nounwind {
+allocas:
+ %ptr2vec615 = bitcast [0 x i32]* %RET to <8 x i32>*
+ store <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, <8 x i32>* %ptr2vec615, align 32
+ ret void
+}
+
+;;; Just make sure this doesn't crash
+; CHECK: _ISelCrash
+define <4 x i64> @ISelCrash(<4 x i64> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <4 x i64> %a, <4 x i64> undef, <4 x i32> <i32 2, i32 3, i32 4, i32 4>
+ ret <4 x i64> %shuffle
+}
+
+;;;
+;;; Check that some 256-bit vectors are xformed into 128 ops
+; CHECK: _A
+; CHECK: vshufpd $1
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: vshufpd $1
+; CHECK-NEXT: vinsertf128 $1
+define <4 x i64> @A(<4 x i64> %a, <4 x i64> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <4 x i64> %a, <4 x i64> %b, <4 x i32> <i32 1, i32 0, i32 7, i32 6>
+ ret <4 x i64> %shuffle
+}
+
+; CHECK: _B
+; CHECK: vshufpd $1, %ymm
+define <4 x i64> @B(<4 x i64> %a, <4 x i64> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <4 x i64> %a, <4 x i64> %b, <4 x i32> <i32 1, i32 undef, i32 undef, i32 6>
+ ret <4 x i64> %shuffle
+}
+
+; CHECK: movlhps
+; CHECK-NEXT: vextractf128 $1
+; CHECK-NEXT: movlhps
+; CHECK-NEXT: vinsertf128 $1
+define <4 x i64> @C(<4 x i64> %a, <4 x i64> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <4 x i64> %a, <4 x i64> %b, <4 x i32> <i32 undef, i32 0, i32 undef, i32 6>
+ ret <4 x i64> %shuffle
+}
+
+; CHECK: vpshufd $-96
+; CHECK: vpshufd $-6
+; CHECK: vinsertf128 $1
+define <8 x i32> @D(<8 x i32> %a, <8 x i32> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x i32> %a, <8 x i32> %b, <8 x i32> <i32 0, i32 0, i32 2, i32 2, i32 10, i32 10, i32 11, i32 11>
+ ret <8 x i32> %shuffle
+}
+
+;;; Don't crash on movd
+; CHECK: _VMOVZQI2PQI
+; CHECK: vmovd (%
+define <8 x i32> @VMOVZQI2PQI([0 x float]* nocapture %aFOO) nounwind {
+allocas:
+ %ptrcast.i33.i = bitcast [0 x float]* %aFOO to i32*
+ %val.i34.i = load i32* %ptrcast.i33.i, align 4
+ %ptroffset.i22.i992 = getelementptr [0 x float]* %aFOO, i64 0, i64 1
+ %ptrcast.i23.i = bitcast float* %ptroffset.i22.i992 to i32*
+ %val.i24.i = load i32* %ptrcast.i23.i, align 4
+ %updatedret.i30.i = insertelement <8 x i32> undef, i32 %val.i34.i, i32 1
+ ret <8 x i32> %updatedret.i30.i
+}
+
diff --git a/test/CodeGen/X86/avx-bitcast.ll b/test/CodeGen/X86/avx-bitcast.ll
new file mode 100644
index 0000000..ecc71be
--- /dev/null
+++ b/test/CodeGen/X86/avx-bitcast.ll
@@ -0,0 +1,10 @@
+; RUN: llc < %s -O0 -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vmovsd (%
+; CHECK-NEXT: vmovd %xmm
+define i64 @bitcasti64tof64() {
+ %a = load double* undef
+ %b = bitcast double %a to i64
+ ret i64 %b
+}
+
diff --git a/test/CodeGen/X86/avx-blend.ll b/test/CodeGen/X86/avx-blend.ll
new file mode 100644
index 0000000..7729491
--- /dev/null
+++ b/test/CodeGen/X86/avx-blend.ll
@@ -0,0 +1,104 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -promote-elements -mattr=+avx | FileCheck %s
+
+; AVX128 tests:
+
+;CHECK: vsel_float
+;CHECK: vblendvps
+;CHECK: ret
+define <4 x float> @vsel_float(<4 x float> %v1, <4 x float> %v2) {
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x float> %v1, <4 x float> %v2
+ ret <4 x float> %vsel
+}
+
+
+;CHECK: vsel_i32
+;CHECK: vblendvps
+;CHECK: ret
+define <4 x i32> @vsel_i32(<4 x i32> %v1, <4 x i32> %v2) {
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x i32> %v1, <4 x i32> %v2
+ ret <4 x i32> %vsel
+}
+
+
+;CHECK: vsel_double
+;CHECK: vblendvpd
+;CHECK: ret
+define <2 x double> @vsel_double(<2 x double> %v1, <2 x double> %v2) {
+ %vsel = select <2 x i1> <i1 true, i1 false>, <2 x double> %v1, <2 x double> %v2
+ ret <2 x double> %vsel
+}
+
+
+;CHECK: vsel_i64
+;CHECK: vblendvpd
+;CHECK: ret
+define <2 x i64> @vsel_i64(<2 x i64> %v1, <2 x i64> %v2) {
+ %vsel = select <2 x i1> <i1 true, i1 false>, <2 x i64> %v1, <2 x i64> %v2
+ ret <2 x i64> %vsel
+}
+
+
+;CHECK: vsel_i8
+;CHECK: vpblendvb
+;CHECK: ret
+define <16 x i8> @vsel_i8(<16 x i8> %v1, <16 x i8> %v2) {
+ %vsel = select <16 x i1> <i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false>, <16 x i8> %v1, <16 x i8> %v2
+ ret <16 x i8> %vsel
+}
+
+
+; AVX256 tests:
+
+
+;CHECK: vsel_float
+;CHECK: vblendvps
+;CHECK: ret
+define <8 x float> @vsel_float8(<8 x float> %v1, <8 x float> %v2) {
+ %vsel = select <8 x i1> <i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false>, <8 x float> %v1, <8 x float> %v2
+ ret <8 x float> %vsel
+}
+
+;CHECK: vsel_i32
+;CHECK: vblendvps
+;CHECK: ret
+define <8 x i32> @vsel_i328(<8 x i32> %v1, <8 x i32> %v2) {
+ %vsel = select <8 x i1> <i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false>, <8 x i32> %v1, <8 x i32> %v2
+ ret <8 x i32> %vsel
+}
+
+;CHECK: vsel_double
+;CHECK: vblendvpd
+;CHECK: ret
+define <8 x double> @vsel_double8(<8 x double> %v1, <8 x double> %v2) {
+ %vsel = select <8 x i1> <i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false>, <8 x double> %v1, <8 x double> %v2
+ ret <8 x double> %vsel
+}
+
+;CHECK: vsel_i64
+;CHECK: vblendvpd
+;CHECK: ret
+define <8 x i64> @vsel_i648(<8 x i64> %v1, <8 x i64> %v2) {
+ %vsel = select <8 x i1> <i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false>, <8 x i64> %v1, <8 x i64> %v2
+ ret <8 x i64> %vsel
+}
+
+;; TEST blend + compares
+; CHECK: A
+define <2 x double> @A(<2 x double> %x, <2 x double> %y) {
+ ; CHECK: vcmplepd
+ ; CHECK: vblendvpd
+ %max_is_x = fcmp oge <2 x double> %x, %y
+ %max = select <2 x i1> %max_is_x, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %max
+}
+
+; CHECK: B
+define <2 x double> @B(<2 x double> %x, <2 x double> %y) {
+ ; CHECK: vcmpnlepd
+ ; CHECK: vblendvpd
+ %min_is_x = fcmp ult <2 x double> %x, %y
+ %min = select <2 x i1> %min_is_x, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %min
+}
+
+
diff --git a/test/CodeGen/X86/avx-cast.ll b/test/CodeGen/X86/avx-cast.ll
new file mode 100644
index 0000000..d6d2415
--- /dev/null
+++ b/test/CodeGen/X86/avx-cast.ll
@@ -0,0 +1,47 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vxorps
+; CHECK-NEXT: vinsertf128 $0
+define <8 x float> @castA(<4 x float> %m) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <4 x float> %m, <4 x float> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 4, i32 4, i32 4>
+ ret <8 x float> %shuffle.i
+}
+
+; CHECK: vxorps
+; CHECK-NEXT: vinsertf128 $0
+define <4 x double> @castB(<2 x double> %m) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <2 x double> %m, <2 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 2>
+ ret <4 x double> %shuffle.i
+}
+
+; CHECK: vpxor
+; CHECK-NEXT: vinsertf128 $0
+define <4 x i64> @castC(<2 x i64> %m) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <2 x i64> %m, <2 x i64> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 2>
+ ret <4 x i64> %shuffle.i
+}
+
+; CHECK-NOT: vextractf128 $0
+define <4 x float> @castD(<8 x float> %m) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <8 x float> %m, <8 x float> %m, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ ret <4 x float> %shuffle.i
+}
+
+; CHECK-NOT: vextractf128 $0
+define <2 x i64> @castE(<4 x i64> %m) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <4 x i64> %m, <4 x i64> %m, <2 x i32> <i32 0, i32 1>
+ ret <2 x i64> %shuffle.i
+}
+
+; CHECK-NOT: vextractf128 $0
+define <2 x double> @castF(<4 x double> %m) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <4 x double> %m, <4 x double> %m, <2 x i32> <i32 0, i32 1>
+ ret <2 x double> %shuffle.i
+}
+
diff --git a/test/CodeGen/X86/avx-cmp.ll b/test/CodeGen/X86/avx-cmp.ll
new file mode 100644
index 0000000..a050d6ab
--- /dev/null
+++ b/test/CodeGen/X86/avx-cmp.ll
@@ -0,0 +1,150 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vcmpltps %ymm
+; CHECK-NOT: vucomiss
+define <8 x i32> @cmp00(<8 x float> %a, <8 x float> %b) nounwind readnone {
+ %bincmp = fcmp olt <8 x float> %a, %b
+ %s = sext <8 x i1> %bincmp to <8 x i32>
+ ret <8 x i32> %s
+}
+
+; CHECK: vcmpltpd %ymm
+; CHECK-NOT: vucomisd
+define <4 x i64> @cmp01(<4 x double> %a, <4 x double> %b) nounwind readnone {
+ %bincmp = fcmp olt <4 x double> %a, %b
+ %s = sext <4 x i1> %bincmp to <4 x i64>
+ ret <4 x i64> %s
+}
+
+declare void @scale() nounwind uwtable
+
+; CHECK: vucomisd
+define void @render() nounwind uwtable {
+entry:
+ br i1 undef, label %for.cond5, label %for.end52
+
+for.cond5:
+ %or.cond = and i1 undef, false
+ br i1 %or.cond, label %for.body33, label %for.cond5
+
+for.cond30:
+ br i1 false, label %for.body33, label %for.cond5
+
+for.body33:
+ %tobool = fcmp une double undef, 0.000000e+00
+ br i1 %tobool, label %if.then, label %for.cond30
+
+if.then:
+ call void @scale()
+ br label %for.cond30
+
+for.end52:
+ ret void
+}
+
+; CHECK: vextractf128 $1
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vpcmpgtd %xmm
+; CHECK-NEXT: vpcmpgtd %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <8 x i32> @int256-cmp(<8 x i32> %i, <8 x i32> %j) nounwind readnone {
+ %bincmp = icmp slt <8 x i32> %i, %j
+ %x = sext <8 x i1> %bincmp to <8 x i32>
+ ret <8 x i32> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vpcmpgtq %xmm
+; CHECK-NEXT: vpcmpgtq %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <4 x i64> @v4i64-cmp(<4 x i64> %i, <4 x i64> %j) nounwind readnone {
+ %bincmp = icmp slt <4 x i64> %i, %j
+ %x = sext <4 x i1> %bincmp to <4 x i64>
+ ret <4 x i64> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vpcmpgtw %xmm
+; CHECK-NEXT: vpcmpgtw %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <16 x i16> @v16i16-cmp(<16 x i16> %i, <16 x i16> %j) nounwind readnone {
+ %bincmp = icmp slt <16 x i16> %i, %j
+ %x = sext <16 x i1> %bincmp to <16 x i16>
+ ret <16 x i16> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vpcmpgtb %xmm
+; CHECK-NEXT: vpcmpgtb %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <32 x i8> @v32i8-cmp(<32 x i8> %i, <32 x i8> %j) nounwind readnone {
+ %bincmp = icmp slt <32 x i8> %i, %j
+ %x = sext <32 x i1> %bincmp to <32 x i8>
+ ret <32 x i8> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vpcmpeqd %xmm
+; CHECK-NEXT: vpcmpeqd %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <8 x i32> @int256-cmpeq(<8 x i32> %i, <8 x i32> %j) nounwind readnone {
+ %bincmp = icmp eq <8 x i32> %i, %j
+ %x = sext <8 x i1> %bincmp to <8 x i32>
+ ret <8 x i32> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vpcmpeqq %xmm
+; CHECK-NEXT: vpcmpeqq %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <4 x i64> @v4i64-cmpeq(<4 x i64> %i, <4 x i64> %j) nounwind readnone {
+ %bincmp = icmp eq <4 x i64> %i, %j
+ %x = sext <4 x i1> %bincmp to <4 x i64>
+ ret <4 x i64> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vpcmpeqw %xmm
+; CHECK-NEXT: vpcmpeqw %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <16 x i16> @v16i16-cmpeq(<16 x i16> %i, <16 x i16> %j) nounwind readnone {
+ %bincmp = icmp eq <16 x i16> %i, %j
+ %x = sext <16 x i1> %bincmp to <16 x i16>
+ ret <16 x i16> %x
+}
+
+; CHECK: vextractf128 $1
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vpcmpeqb %xmm
+; CHECK-NEXT: vpcmpeqb %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <32 x i8> @v32i8-cmpeq(<32 x i8> %i, <32 x i8> %j) nounwind readnone {
+ %bincmp = icmp eq <32 x i8> %i, %j
+ %x = sext <32 x i1> %bincmp to <32 x i8>
+ ret <32 x i8> %x
+}
+
+;; Scalar comparison
+
+; CHECK: scalarcmpA
+; CHECK: vcmpeqsd
+define i32 @scalarcmpA() uwtable ssp {
+ %cmp29 = fcmp oeq double undef, 0.000000e+00
+ %res = zext i1 %cmp29 to i32
+ ret i32 %res
+}
+
+; CHECK: scalarcmpB
+; CHECK: vcmpeqss
+define i32 @scalarcmpB() uwtable ssp {
+ %cmp29 = fcmp oeq float undef, 0.000000e+00
+ %res = zext i1 %cmp29 to i32
+ ret i32 %res
+}
+
diff --git a/test/CodeGen/X86/avx-cvt.ll b/test/CodeGen/X86/avx-cvt.ll
new file mode 100644
index 0000000..6c0bd58
--- /dev/null
+++ b/test/CodeGen/X86/avx-cvt.ll
@@ -0,0 +1,83 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vcvtdq2ps %ymm
+define <8 x float> @sitofp00(<8 x i32> %a) nounwind {
+ %b = sitofp <8 x i32> %a to <8 x float>
+ ret <8 x float> %b
+}
+
+; CHECK: vcvttps2dq %ymm
+define <8 x i32> @fptosi00(<8 x float> %a) nounwind {
+ %b = fptosi <8 x float> %a to <8 x i32>
+ ret <8 x i32> %b
+}
+
+; CHECK: vcvtdq2pd %xmm
+define <4 x double> @sitofp01(<4 x i32> %a) {
+ %b = sitofp <4 x i32> %a to <4 x double>
+ ret <4 x double> %b
+}
+
+; CHECK: vcvtpd2dqy %ymm
+define <4 x i32> @fptosi01(<4 x double> %a) {
+ %b = fptosi <4 x double> %a to <4 x i32>
+ ret <4 x i32> %b
+}
+
+; CHECK: vcvtpd2psy %ymm
+; CHECK-NEXT: vcvtpd2psy %ymm
+; CHECK-NEXT: vinsertf128 $1
+define <8 x float> @fptrunc00(<8 x double> %b) nounwind {
+ %a = fptrunc <8 x double> %b to <8 x float>
+ ret <8 x float> %a
+}
+
+; CHECK: vcvtps2pd %xmm
+define <4 x double> @fpext00(<4 x float> %b) nounwind {
+ %a = fpext <4 x float> %b to <4 x double>
+ ret <4 x double> %a
+}
+
+; CHECK: vcvtsi2sdq (%
+define double @funcA(i64* nocapture %e) nounwind uwtable readonly ssp {
+entry:
+ %tmp1 = load i64* %e, align 8
+ %conv = sitofp i64 %tmp1 to double
+ ret double %conv
+}
+
+; CHECK: vcvtsi2sd (%
+define double @funcB(i32* nocapture %e) nounwind uwtable readonly ssp {
+entry:
+ %tmp1 = load i32* %e, align 4
+ %conv = sitofp i32 %tmp1 to double
+ ret double %conv
+}
+
+; CHECK: vcvtsi2ss (%
+define float @funcC(i32* nocapture %e) nounwind uwtable readonly ssp {
+entry:
+ %tmp1 = load i32* %e, align 4
+ %conv = sitofp i32 %tmp1 to float
+ ret float %conv
+}
+
+; CHECK: vcvtsi2ssq (%
+define float @funcD(i64* nocapture %e) nounwind uwtable readonly ssp {
+entry:
+ %tmp1 = load i64* %e, align 8
+ %conv = sitofp i64 %tmp1 to float
+ ret float %conv
+}
+
+; CHECK: vcvtss2sd
+define void @fpext() nounwind uwtable {
+entry:
+ %f = alloca float, align 4
+ %d = alloca double, align 8
+ %tmp = load float* %f, align 4
+ %conv = fpext float %tmp to double
+ store double %conv, double* %d, align 8
+ ret void
+}
+
diff --git a/test/CodeGen/X86/avx-load-store.ll b/test/CodeGen/X86/avx-load-store.ll
index 5196089..07a63ef 100644
--- a/test/CodeGen/X86/avx-load-store.ll
+++ b/test/CodeGen/X86/avx-load-store.ll
@@ -1,9 +1,10 @@
; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+; RUN: llc -O0 < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s -check-prefix=CHECK_O0
; CHECK: vmovaps
; CHECK: vmovaps
-; CHECK: vmovapd
-; CHECK: vmovapd
+; CHECK: vmovaps
+; CHECK: vmovaps
; CHECK: vmovaps
; CHECK: vmovaps
define void @test_256_load(double* nocapture %d, float* nocapture %f, <4 x i64>* nocapture %i) nounwind uwtable ssp {
@@ -22,3 +23,83 @@ entry:
declare void @dummy(<4 x double>, <8 x float>, <4 x i64>)
+;;
+;; The two tests below check that we must fold load + scalar_to_vector
+;; + ins_subvec+ zext into only a single vmovss or vmovsd
+
+; CHECK: vmovss (%
+define <8 x float> @mov00(<8 x float> %v, float * %ptr) nounwind {
+ %val = load float* %ptr
+ %i0 = insertelement <8 x float> zeroinitializer, float %val, i32 0
+ ret <8 x float> %i0
+}
+
+; CHECK: vmovsd (%
+define <4 x double> @mov01(<4 x double> %v, double * %ptr) nounwind {
+ %val = load double* %ptr
+ %i0 = insertelement <4 x double> zeroinitializer, double %val, i32 0
+ ret <4 x double> %i0
+}
+
+; CHECK: vmovaps %ymm
+define void @storev16i16(<16 x i16> %a) nounwind {
+ store <16 x i16> %a, <16 x i16>* undef, align 32
+ unreachable
+}
+
+; CHECK: vmovups %ymm
+define void @storev16i16_01(<16 x i16> %a) nounwind {
+ store <16 x i16> %a, <16 x i16>* undef, align 4
+ unreachable
+}
+
+; CHECK: vmovaps %ymm
+define void @storev32i8(<32 x i8> %a) nounwind {
+ store <32 x i8> %a, <32 x i8>* undef, align 32
+ unreachable
+}
+
+; CHECK: vmovups %ymm
+define void @storev32i8_01(<32 x i8> %a) nounwind {
+ store <32 x i8> %a, <32 x i8>* undef, align 4
+ unreachable
+}
+
+; It is faster to make two saves, if the data is already in XMM registers. For
+; example, after making an integer operation.
+; CHECK: _double_save
+; CHECK-NOT: vinsertf128 $1
+; CHECK-NOT: vinsertf128 $0
+; CHECK: vmovaps %xmm
+; CHECK: vmovaps %xmm
+define void @double_save(<4 x i32> %A, <4 x i32> %B, <8 x i32>* %P) nounwind ssp {
+entry:
+ %Z = shufflevector <4 x i32>%A, <4 x i32>%B, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ store <8 x i32> %Z, <8 x i32>* %P, align 16
+ ret void
+}
+
+declare void @llvm.x86.avx.maskstore.ps.256(i8*, <8 x float>, <8 x float>) nounwind
+
+; CHECK_O0: _f_f
+; CHECK-O0: vmovss LCPI
+; CHECK-O0: vxorps %xmm
+; CHECK-O0: vmovss %xmm
+define void @f_f() nounwind {
+allocas:
+ br i1 undef, label %cif_mask_all, label %cif_mask_mixed
+
+cif_mask_all: ; preds = %allocas
+ unreachable
+
+cif_mask_mixed: ; preds = %allocas
+ br i1 undef, label %cif_mixed_test_all, label %cif_mixed_test_any_check
+
+cif_mixed_test_all: ; preds = %cif_mask_mixed
+ call void @llvm.x86.avx.maskstore.ps.256(i8* undef, <8 x float> <float 0xFFFFFFFFE0000000, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00>, <8 x float> undef) nounwind
+ unreachable
+
+cif_mixed_test_any_check: ; preds = %cif_mask_mixed
+ unreachable
+}
+
diff --git a/test/CodeGen/X86/avx-logic.ll b/test/CodeGen/X86/avx-logic.ll
new file mode 100644
index 0000000..518c09c
--- /dev/null
+++ b/test/CodeGen/X86/avx-logic.ll
@@ -0,0 +1,179 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vandpd
+define <4 x double> @andpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <4 x double> %x to <4 x i64>
+ %1 = bitcast <4 x double> %y to <4 x i64>
+ %and.i = and <4 x i64> %0, %1
+ %2 = bitcast <4 x i64> %and.i to <4 x double>
+ ret <4 x double> %2
+}
+
+; CHECK: vandpd LCP{{.*}}(%rip)
+define <4 x double> @andpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <4 x double> %y to <4 x i64>
+ %and.i = and <4 x i64> %0, <i64 4616752568008179712, i64 4614838538166547251, i64 4612361558371493478, i64 4608083138725491507>
+ %1 = bitcast <4 x i64> %and.i to <4 x double>
+ ret <4 x double> %1
+}
+
+; CHECK: vandps
+define <8 x float> @andps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <8 x float> %x to <8 x i32>
+ %1 = bitcast <8 x float> %y to <8 x i32>
+ %and.i = and <8 x i32> %0, %1
+ %2 = bitcast <8 x i32> %and.i to <8 x float>
+ ret <8 x float> %2
+}
+
+; CHECK: vandps LCP{{.*}}(%rip)
+define <8 x float> @andps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <8 x float> %y to <8 x i32>
+ %and.i = and <8 x i32> %0, <i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938, i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938>
+ %1 = bitcast <8 x i32> %and.i to <8 x float>
+ ret <8 x float> %1
+}
+
+; CHECK: vxorpd
+define <4 x double> @xorpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <4 x double> %x to <4 x i64>
+ %1 = bitcast <4 x double> %y to <4 x i64>
+ %xor.i = xor <4 x i64> %0, %1
+ %2 = bitcast <4 x i64> %xor.i to <4 x double>
+ ret <4 x double> %2
+}
+
+; CHECK: vxorpd LCP{{.*}}(%rip)
+define <4 x double> @xorpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <4 x double> %y to <4 x i64>
+ %xor.i = xor <4 x i64> %0, <i64 4616752568008179712, i64 4614838538166547251, i64 4612361558371493478, i64 4608083138725491507>
+ %1 = bitcast <4 x i64> %xor.i to <4 x double>
+ ret <4 x double> %1
+}
+
+; CHECK: vxorps
+define <8 x float> @xorps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <8 x float> %x to <8 x i32>
+ %1 = bitcast <8 x float> %y to <8 x i32>
+ %xor.i = xor <8 x i32> %0, %1
+ %2 = bitcast <8 x i32> %xor.i to <8 x float>
+ ret <8 x float> %2
+}
+
+; CHECK: vxorps LCP{{.*}}(%rip)
+define <8 x float> @xorps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <8 x float> %y to <8 x i32>
+ %xor.i = xor <8 x i32> %0, <i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938, i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938>
+ %1 = bitcast <8 x i32> %xor.i to <8 x float>
+ ret <8 x float> %1
+}
+
+; CHECK: vorpd
+define <4 x double> @orpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <4 x double> %x to <4 x i64>
+ %1 = bitcast <4 x double> %y to <4 x i64>
+ %or.i = or <4 x i64> %0, %1
+ %2 = bitcast <4 x i64> %or.i to <4 x double>
+ ret <4 x double> %2
+}
+
+; CHECK: vorpd LCP{{.*}}(%rip)
+define <4 x double> @orpd256fold(<4 x double> %y) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <4 x double> %y to <4 x i64>
+ %or.i = or <4 x i64> %0, <i64 4616752568008179712, i64 4614838538166547251, i64 4612361558371493478, i64 4608083138725491507>
+ %1 = bitcast <4 x i64> %or.i to <4 x double>
+ ret <4 x double> %1
+}
+
+; CHECK: vorps
+define <8 x float> @orps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <8 x float> %x to <8 x i32>
+ %1 = bitcast <8 x float> %y to <8 x i32>
+ %or.i = or <8 x i32> %0, %1
+ %2 = bitcast <8 x i32> %or.i to <8 x float>
+ ret <8 x float> %2
+}
+
+; CHECK: vorps LCP{{.*}}(%rip)
+define <8 x float> @orps256fold(<8 x float> %y) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <8 x float> %y to <8 x i32>
+ %or.i = or <8 x i32> %0, <i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938, i32 1083179008, i32 1079613850, i32 1075000115, i32 1067030938>
+ %1 = bitcast <8 x i32> %or.i to <8 x float>
+ ret <8 x float> %1
+}
+
+; CHECK: vandnpd
+define <4 x double> @andnotpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <4 x double> %x to <4 x i64>
+ %neg.i = xor <4 x i64> %0, <i64 -1, i64 -1, i64 -1, i64 -1>
+ %1 = bitcast <4 x double> %y to <4 x i64>
+ %and.i = and <4 x i64> %1, %neg.i
+ %2 = bitcast <4 x i64> %and.i to <4 x double>
+ ret <4 x double> %2
+}
+
+; CHECK: vandnpd (%
+define <4 x double> @andnotpd256fold(<4 x double> %y, <4 x double>* nocapture %x) nounwind uwtable readonly ssp {
+entry:
+ %tmp2 = load <4 x double>* %x, align 32
+ %0 = bitcast <4 x double> %y to <4 x i64>
+ %neg.i = xor <4 x i64> %0, <i64 -1, i64 -1, i64 -1, i64 -1>
+ %1 = bitcast <4 x double> %tmp2 to <4 x i64>
+ %and.i = and <4 x i64> %1, %neg.i
+ %2 = bitcast <4 x i64> %and.i to <4 x double>
+ ret <4 x double> %2
+}
+
+; CHECK: vandnps
+define <8 x float> @andnotps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <8 x float> %x to <8 x i32>
+ %neg.i = xor <8 x i32> %0, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
+ %1 = bitcast <8 x float> %y to <8 x i32>
+ %and.i = and <8 x i32> %1, %neg.i
+ %2 = bitcast <8 x i32> %and.i to <8 x float>
+ ret <8 x float> %2
+}
+
+; CHECK: vandnps (%
+define <8 x float> @andnotps256fold(<8 x float> %y, <8 x float>* nocapture %x) nounwind uwtable readonly ssp {
+entry:
+ %tmp2 = load <8 x float>* %x, align 32
+ %0 = bitcast <8 x float> %y to <8 x i32>
+ %neg.i = xor <8 x i32> %0, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
+ %1 = bitcast <8 x float> %tmp2 to <8 x i32>
+ %and.i = and <8 x i32> %1, %neg.i
+ %2 = bitcast <8 x i32> %and.i to <8 x float>
+ ret <8 x float> %2
+}
+
+;;; Test that basic 2 x i64 logic use the integer version on AVX
+
+; CHECK: vpandn %xmm
+define <2 x i64> @vpandn(<2 x i64> %a, <2 x i64> %b) nounwind uwtable readnone ssp {
+entry:
+ %y = xor <2 x i64> %a, <i64 -1, i64 -1>
+ %x = and <2 x i64> %a, %y
+ ret <2 x i64> %x
+}
+
+; CHECK: vpand %xmm
+define <2 x i64> @vpand(<2 x i64> %a, <2 x i64> %b) nounwind uwtable readnone ssp {
+entry:
+ %x = and <2 x i64> %a, %b
+ ret <2 x i64> %x
+}
+
diff --git a/test/CodeGen/X86/avx-minmax.ll b/test/CodeGen/X86/avx-minmax.ll
new file mode 100644
index 0000000..f36ba7b
--- /dev/null
+++ b/test/CodeGen/X86/avx-minmax.ll
@@ -0,0 +1,65 @@
+; RUN: llc < %s -march=x86-64 -mattr=+avx -asm-verbose=false -join-physregs -enable-unsafe-fp-math -enable-no-nans-fp-math -promote-elements | FileCheck -check-prefix=UNSAFE %s
+
+; UNSAFE: maxpd:
+; UNSAFE: vmaxpd {{.+}}, %xmm
+define <2 x double> @maxpd(<2 x double> %x, <2 x double> %y) {
+ %max_is_x = fcmp oge <2 x double> %x, %y
+ %max = select <2 x i1> %max_is_x, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %max
+}
+
+; UNSAFE: minpd:
+; UNSAFE: vminpd {{.+}}, %xmm
+define <2 x double> @minpd(<2 x double> %x, <2 x double> %y) {
+ %min_is_x = fcmp ole <2 x double> %x, %y
+ %min = select <2 x i1> %min_is_x, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %min
+}
+
+; UNSAFE: maxps:
+; UNSAFE: vmaxps {{.+}}, %xmm
+define <4 x float> @maxps(<4 x float> %x, <4 x float> %y) {
+ %max_is_x = fcmp oge <4 x float> %x, %y
+ %max = select <4 x i1> %max_is_x, <4 x float> %x, <4 x float> %y
+ ret <4 x float> %max
+}
+
+; UNSAFE: minps:
+; UNSAFE: vminps {{.+}}, %xmm
+define <4 x float> @minps(<4 x float> %x, <4 x float> %y) {
+ %min_is_x = fcmp ole <4 x float> %x, %y
+ %min = select <4 x i1> %min_is_x, <4 x float> %x, <4 x float> %y
+ ret <4 x float> %min
+}
+
+; UNSAFE: vmaxpd:
+; UNSAFE: vmaxpd %ymm
+define <4 x double> @vmaxpd(<4 x double> %x, <4 x double> %y) {
+ %max_is_x = fcmp oge <4 x double> %x, %y
+ %max = select <4 x i1> %max_is_x, <4 x double> %x, <4 x double> %y
+ ret <4 x double> %max
+}
+
+; UNSAFE: vminpd:
+; UNSAFE: vminpd %ymm
+define <4 x double> @vminpd(<4 x double> %x, <4 x double> %y) {
+ %min_is_x = fcmp ole <4 x double> %x, %y
+ %min = select <4 x i1> %min_is_x, <4 x double> %x, <4 x double> %y
+ ret <4 x double> %min
+}
+
+; UNSAFE: vmaxps:
+; UNSAFE: vmaxps %ymm
+define <8 x float> @vmaxps(<8 x float> %x, <8 x float> %y) {
+ %max_is_x = fcmp oge <8 x float> %x, %y
+ %max = select <8 x i1> %max_is_x, <8 x float> %x, <8 x float> %y
+ ret <8 x float> %max
+}
+
+; UNSAFE: vminps:
+; UNSAFE: vminps %ymm
+define <8 x float> @vminps(<8 x float> %x, <8 x float> %y) {
+ %min_is_x = fcmp ole <8 x float> %x, %y
+ %min = select <8 x i1> %min_is_x, <8 x float> %x, <8 x float> %y
+ ret <8 x float> %min
+}
diff --git a/test/CodeGen/X86/avx-movdup.ll b/test/CodeGen/X86/avx-movdup.ll
new file mode 100644
index 0000000..42d84de
--- /dev/null
+++ b/test/CodeGen/X86/avx-movdup.ll
@@ -0,0 +1,34 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vmovsldup
+define <8 x float> @movdupA(<8 x float> %src) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <8 x float> %src, <8 x float> undef, <8 x i32> <i32 0, i32 0, i32 2, i32 2, i32 4, i32 4, i32 6, i32 6>
+ ret <8 x float> %shuffle.i
+}
+
+; CHECK: vmovshdup
+define <8 x float> @movdupB(<8 x float> %src) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <8 x float> %src, <8 x float> undef, <8 x i32> <i32 1, i32 1, i32 3, i32 3, i32 5, i32 5, i32 7, i32 7>
+ ret <8 x float> %shuffle.i
+}
+
+; CHECK: vmovsldup
+define <4 x i64> @movdupC(<4 x i64> %src) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <4 x i64> %src to <8 x float>
+ %shuffle.i = shufflevector <8 x float> %0, <8 x float> undef, <8 x i32> <i32 0, i32 0, i32 2, i32 2, i32 4, i32 4, i32 6, i32 6>
+ %1 = bitcast <8 x float> %shuffle.i to <4 x i64>
+ ret <4 x i64> %1
+}
+
+; CHECK: vmovshdup
+define <4 x i64> @movdupD(<4 x i64> %src) nounwind uwtable readnone ssp {
+entry:
+ %0 = bitcast <4 x i64> %src to <8 x float>
+ %shuffle.i = shufflevector <8 x float> %0, <8 x float> undef, <8 x i32> <i32 1, i32 1, i32 3, i32 3, i32 5, i32 5, i32 7, i32 7>
+ %1 = bitcast <8 x float> %shuffle.i to <4 x i64>
+ ret <4 x i64> %1
+}
+
diff --git a/test/CodeGen/X86/avx-select.ll b/test/CodeGen/X86/avx-select.ll
new file mode 100644
index 0000000..58a75ef
--- /dev/null
+++ b/test/CodeGen/X86/avx-select.ll
@@ -0,0 +1,22 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: _select00
+; CHECK: vmovaps
+; CHECK-NEXT: LBB
+define <8 x i32> @select00(i32 %a, <8 x i32> %b) nounwind {
+ %cmpres = icmp eq i32 %a, 255
+ %selres = select i1 %cmpres, <8 x i32> zeroinitializer, <8 x i32> %b
+ %res = xor <8 x i32> %b, %selres
+ ret <8 x i32> %res
+}
+
+; CHECK: _select01
+; CHECK: vmovaps
+; CHECK-NEXT: LBB
+define <4 x i64> @select01(i32 %a, <4 x i64> %b) nounwind {
+ %cmpres = icmp eq i32 %a, 255
+ %selres = select i1 %cmpres, <4 x i64> zeroinitializer, <4 x i64> %b
+ %res = xor <4 x i64> %b, %selres
+ ret <4 x i64> %res
+}
+
diff --git a/test/CodeGen/X86/avx-shift.ll b/test/CodeGen/X86/avx-shift.ll
new file mode 100644
index 0000000..3ea39a2
--- /dev/null
+++ b/test/CodeGen/X86/avx-shift.ll
@@ -0,0 +1,75 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+;;; Shift left
+; CHECK: vpslld
+; CHECK: vpslld
+define <8 x i32> @vshift00(<8 x i32> %a) nounwind readnone {
+ %s = shl <8 x i32> %a, <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32
+2>
+ ret <8 x i32> %s
+}
+
+; CHECK: vpsllw
+; CHECK: vpsllw
+define <16 x i16> @vshift01(<16 x i16> %a) nounwind readnone {
+ %s = shl <16 x i16> %a, <i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2>
+ ret <16 x i16> %s
+}
+
+; CHECK: vpsllq
+; CHECK: vpsllq
+define <4 x i64> @vshift02(<4 x i64> %a) nounwind readnone {
+ %s = shl <4 x i64> %a, <i64 2, i64 2, i64 2, i64 2>
+ ret <4 x i64> %s
+}
+
+;;; Logical Shift right
+; CHECK: vpsrld
+; CHECK: vpsrld
+define <8 x i32> @vshift03(<8 x i32> %a) nounwind readnone {
+ %s = lshr <8 x i32> %a, <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32
+2>
+ ret <8 x i32> %s
+}
+
+; CHECK: vpsrlw
+; CHECK: vpsrlw
+define <16 x i16> @vshift04(<16 x i16> %a) nounwind readnone {
+ %s = lshr <16 x i16> %a, <i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2>
+ ret <16 x i16> %s
+}
+
+; CHECK: vpsrlq
+; CHECK: vpsrlq
+define <4 x i64> @vshift05(<4 x i64> %a) nounwind readnone {
+ %s = lshr <4 x i64> %a, <i64 2, i64 2, i64 2, i64 2>
+ ret <4 x i64> %s
+}
+
+;;; Arithmetic Shift right
+; CHECK: vpsrad
+; CHECK: vpsrad
+define <8 x i32> @vshift06(<8 x i32> %a) nounwind readnone {
+ %s = ashr <8 x i32> %a, <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32
+2>
+ ret <8 x i32> %s
+}
+
+; CHECK: vpsraw
+; CHECK: vpsraw
+define <16 x i16> @vshift07(<16 x i16> %a) nounwind readnone {
+ %s = ashr <16 x i16> %a, <i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2>
+ ret <16 x i16> %s
+}
+
+;;; Support variable shifts
+; CHECK: _vshift08
+; CHECK: vextractf128 $1
+; CHECK: vpslld $23
+; CHECK: vextractf128 $1
+; CHECK: vpslld $23
+define <8 x i32> @vshift08(<8 x i32> %a) nounwind {
+ %bitop = shl <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, %a
+ ret <8 x i32> %bitop
+}
+
diff --git a/test/CodeGen/X86/avx-shuffle.ll b/test/CodeGen/X86/avx-shuffle.ll
new file mode 100644
index 0000000..0db334d
--- /dev/null
+++ b/test/CodeGen/X86/avx-shuffle.ll
@@ -0,0 +1,10 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; PR11102
+define <4 x float> @test1(<4 x float> %a) nounwind {
+ %b = shufflevector <4 x float> zeroinitializer, <4 x float> %a, <4 x i32> <i32 2, i32 5, i32 undef, i32 undef>
+ ret <4 x float> %b
+; CHECK: test1:
+; CHECK: vshufps
+; CHECK: vpshufd
+}
diff --git a/test/CodeGen/X86/avx-splat.ll b/test/CodeGen/X86/avx-splat.ll
new file mode 100644
index 0000000..af20b90
--- /dev/null
+++ b/test/CodeGen/X86/avx-splat.ll
@@ -0,0 +1,103 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+
+; CHECK: vpunpcklbw %xmm
+; CHECK-NEXT: vpunpckhbw %xmm
+; CHECK-NEXT: vinsertf128 $1
+; CHECK-NEXT: vpermilps $85
+define <32 x i8> @funcA(<32 x i8> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <32 x i8> %a, <32 x i8> undef, <32 x i32> <i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5>
+ ret <32 x i8> %shuffle
+}
+
+; CHECK: vpunpckhwd %xmm
+; CHECK-NEXT: vinsertf128 $1
+; CHECK-NEXT: vpermilps $85
+define <16 x i16> @funcB(<16 x i16> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <16 x i16> %a, <16 x i16> undef, <16 x i32> <i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5>
+ ret <16 x i16> %shuffle
+}
+
+; CHECK: vmovd
+; CHECK-NEXT: vmovlhps %xmm
+; CHECK-NEXT: vinsertf128 $1
+define <4 x i64> @funcC(i64 %q) nounwind uwtable readnone ssp {
+entry:
+ %vecinit.i = insertelement <4 x i64> undef, i64 %q, i32 0
+ %vecinit2.i = insertelement <4 x i64> %vecinit.i, i64 %q, i32 1
+ %vecinit4.i = insertelement <4 x i64> %vecinit2.i, i64 %q, i32 2
+ %vecinit6.i = insertelement <4 x i64> %vecinit4.i, i64 %q, i32 3
+ ret <4 x i64> %vecinit6.i
+}
+
+; CHECK: vshufpd $0
+; CHECK-NEXT: vinsertf128 $1
+define <4 x double> @funcD(double %q) nounwind uwtable readnone ssp {
+entry:
+ %vecinit.i = insertelement <4 x double> undef, double %q, i32 0
+ %vecinit2.i = insertelement <4 x double> %vecinit.i, double %q, i32 1
+ %vecinit4.i = insertelement <4 x double> %vecinit2.i, double %q, i32 2
+ %vecinit6.i = insertelement <4 x double> %vecinit4.i, double %q, i32 3
+ ret <4 x double> %vecinit6.i
+}
+
+; Test this simple opt:
+; shuffle (scalar_to_vector (load (ptr + 4))), undef, <0, 0, 0, 0>
+; To:
+; shuffle (vload ptr)), undef, <1, 1, 1, 1>
+; CHECK: vmovdqa
+; CHECK-NEXT: vinsertf128 $1
+; CHECK-NEXT: vpermilps $-1
+define <8 x float> @funcE() nounwind {
+allocas:
+ %udx495 = alloca [18 x [18 x float]], align 32
+ br label %for_test505.preheader
+
+for_test505.preheader: ; preds = %for_test505.preheader, %allocas
+ br i1 undef, label %for_exit499, label %for_test505.preheader
+
+for_exit499: ; preds = %for_test505.preheader
+ br i1 undef, label %__load_and_broadcast_32.exit1249, label %load.i1247
+
+load.i1247: ; preds = %for_exit499
+ %ptr1227 = getelementptr [18 x [18 x float]]* %udx495, i64 0, i64 1, i64 1
+ %ptr.i1237 = bitcast float* %ptr1227 to i32*
+ %val.i1238 = load i32* %ptr.i1237, align 4
+ %ret6.i1245 = insertelement <8 x i32> undef, i32 %val.i1238, i32 6
+ %ret7.i1246 = insertelement <8 x i32> %ret6.i1245, i32 %val.i1238, i32 7
+ %phitmp = bitcast <8 x i32> %ret7.i1246 to <8 x float>
+ br label %__load_and_broadcast_32.exit1249
+
+__load_and_broadcast_32.exit1249: ; preds = %load.i1247, %for_exit499
+ %load_broadcast12281250 = phi <8 x float> [ %phitmp, %load.i1247 ], [ undef, %for_exit499 ]
+ ret <8 x float> %load_broadcast12281250
+}
+
+; CHECK: vinsertf128 $1
+; CHECK-NEXT: vpermilps $0
+define <8 x float> @funcF(i32 %val) nounwind {
+ %ret6 = insertelement <8 x i32> undef, i32 %val, i32 6
+ %ret7 = insertelement <8 x i32> %ret6, i32 %val, i32 7
+ %tmp = bitcast <8 x i32> %ret7 to <8 x float>
+ ret <8 x float> %tmp
+}
+
+; CHECK: vinsertf128 $1
+; CHECK-NEXT: vpermilps $0
+define <8 x float> @funcG(<8 x float> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> undef, <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
+ ret <8 x float> %shuffle
+}
+
+; CHECK: vextractf128 $1
+; CHECK-NEXT: vinsertf128 $1
+; CHECK-NEXT: vpermilps $85
+define <8 x float> @funcH(<8 x float> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> undef, <8 x i32> <i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5, i32 5>
+ ret <8 x float> %shuffle
+}
+
diff --git a/test/CodeGen/X86/avx-unpack.ll b/test/CodeGen/X86/avx-unpack.ll
new file mode 100644
index 0000000..d420101
--- /dev/null
+++ b/test/CodeGen/X86/avx-unpack.ll
@@ -0,0 +1,89 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vunpckhps
+define <8 x float> @unpackhips(<8 x float> %src1, <8 x float> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <8 x float> %src1, <8 x float> %src2, <8 x i32> <i32 2, i32 10, i32 3, i32 11, i32 6, i32 14, i32 7, i32 15>
+ ret <8 x float> %shuffle.i
+}
+
+; CHECK: vunpckhpd
+define <4 x double> @unpackhipd(<4 x double> %src1, <4 x double> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <4 x double> %src1, <4 x double> %src2, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+ ret <4 x double> %shuffle.i
+}
+
+; CHECK: vunpcklps
+define <8 x float> @unpacklops(<8 x float> %src1, <8 x float> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <8 x float> %src1, <8 x float> %src2, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 4, i32 12, i32 5, i32 13>
+ ret <8 x float> %shuffle.i
+}
+
+; CHECK: vunpcklpd
+define <4 x double> @unpacklopd(<4 x double> %src1, <4 x double> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <4 x double> %src1, <4 x double> %src2, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+ ret <4 x double> %shuffle.i
+}
+
+; CHECK-NOT: vunpcklps %ymm
+define <8 x float> @unpacklops-not(<8 x float> %src1, <8 x float> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <8 x float> %src1, <8 x float> %src2, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+ ret <8 x float> %shuffle.i
+}
+
+; CHECK-NOT: vunpcklpd %ymm
+define <4 x double> @unpacklopd-not(<4 x double> %src1, <4 x double> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <4 x double> %src1, <4 x double> %src2, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+ ret <4 x double> %shuffle.i
+}
+
+; CHECK-NOT: vunpckhps %ymm
+define <8 x float> @unpackhips-not(<8 x float> %src1, <8 x float> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <8 x float> %src1, <8 x float> %src2, <8 x i32> <i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13>
+ ret <8 x float> %shuffle.i
+}
+
+; CHECK-NOT: vunpckhpd %ymm
+define <4 x double> @unpackhipd-not(<4 x double> %src1, <4 x double> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <4 x double> %src1, <4 x double> %src2, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
+ ret <4 x double> %shuffle.i
+}
+
+;;;;
+;;;; Unpack versions using the fp unit for int unpacking
+;;;;
+
+; CHECK: vunpckhps
+define <8 x i32> @unpackhips1(<8 x i32> %src1, <8 x i32> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <8 x i32> %src1, <8 x i32> %src2, <8 x i32> <i32 2, i32 10, i32 3, i32 11, i32 6, i32 14, i32 7, i32 15>
+ ret <8 x i32> %shuffle.i
+}
+
+; CHECK: vunpckhpd
+define <4 x i64> @unpackhipd1(<4 x i64> %src1, <4 x i64> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <4 x i64> %src1, <4 x i64> %src2, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+ ret <4 x i64> %shuffle.i
+}
+
+; CHECK: vunpcklps
+define <8 x i32> @unpacklops1(<8 x i32> %src1, <8 x i32> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <8 x i32> %src1, <8 x i32> %src2, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 4, i32 12, i32 5, i32 13>
+ ret <8 x i32> %shuffle.i
+}
+
+; CHECK: vunpcklpd
+define <4 x i64> @unpacklopd1(<4 x i64> %src1, <4 x i64> %src2) nounwind uwtable readnone ssp {
+entry:
+ %shuffle.i = shufflevector <4 x i64> %src1, <4 x i64> %src2, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+ ret <4 x i64> %shuffle.i
+}
diff --git a/test/CodeGen/X86/avx-vbroadcast.ll b/test/CodeGen/X86/avx-vbroadcast.ll
new file mode 100644
index 0000000..89b4188
--- /dev/null
+++ b/test/CodeGen/X86/avx-vbroadcast.ll
@@ -0,0 +1,94 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+; XFAIL: *
+
+; xfail this file for now because of PR8156, when it gets solved merge this with avx-splat.ll
+
+; CHECK: vbroadcastsd (%
+define <4 x i64> @A(i64* %ptr) nounwind uwtable readnone ssp {
+entry:
+ %q = load i64* %ptr, align 8
+ %vecinit.i = insertelement <4 x i64> undef, i64 %q, i32 0
+ %vecinit2.i = insertelement <4 x i64> %vecinit.i, i64 %q, i32 1
+ %vecinit4.i = insertelement <4 x i64> %vecinit2.i, i64 %q, i32 2
+ %vecinit6.i = insertelement <4 x i64> %vecinit4.i, i64 %q, i32 3
+ ret <4 x i64> %vecinit6.i
+}
+
+; CHECK: vbroadcastss (%
+define <8 x i32> @B(i32* %ptr) nounwind uwtable readnone ssp {
+entry:
+ %q = load i32* %ptr, align 4
+ %vecinit.i = insertelement <8 x i32> undef, i32 %q, i32 0
+ %vecinit2.i = insertelement <8 x i32> %vecinit.i, i32 %q, i32 1
+ %vecinit4.i = insertelement <8 x i32> %vecinit2.i, i32 %q, i32 2
+ %vecinit6.i = insertelement <8 x i32> %vecinit4.i, i32 %q, i32 3
+ ret <8 x i32> %vecinit6.i
+}
+
+; CHECK: vbroadcastsd (%
+define <4 x double> @C(double* %ptr) nounwind uwtable readnone ssp {
+entry:
+ %q = load double* %ptr, align 8
+ %vecinit.i = insertelement <4 x double> undef, double %q, i32 0
+ %vecinit2.i = insertelement <4 x double> %vecinit.i, double %q, i32 1
+ %vecinit4.i = insertelement <4 x double> %vecinit2.i, double %q, i32 2
+ %vecinit6.i = insertelement <4 x double> %vecinit4.i, double %q, i32 3
+ ret <4 x double> %vecinit6.i
+}
+
+; CHECK: vbroadcastss (%
+define <8 x float> @D(float* %ptr) nounwind uwtable readnone ssp {
+entry:
+ %q = load float* %ptr, align 4
+ %vecinit.i = insertelement <8 x float> undef, float %q, i32 0
+ %vecinit2.i = insertelement <8 x float> %vecinit.i, float %q, i32 1
+ %vecinit4.i = insertelement <8 x float> %vecinit2.i, float %q, i32 2
+ %vecinit6.i = insertelement <8 x float> %vecinit4.i, float %q, i32 3
+ ret <8 x float> %vecinit6.i
+}
+
+;;;; 128-bit versions
+
+; CHECK: vbroadcastss (%
+define <4 x float> @E(float* %ptr) nounwind uwtable readnone ssp {
+entry:
+ %q = load float* %ptr, align 4
+ %vecinit.i = insertelement <4 x float> undef, float %q, i32 0
+ %vecinit2.i = insertelement <4 x float> %vecinit.i, float %q, i32 1
+ %vecinit4.i = insertelement <4 x float> %vecinit2.i, float %q, i32 2
+ %vecinit6.i = insertelement <4 x float> %vecinit4.i, float %q, i32 3
+ ret <4 x float> %vecinit6.i
+}
+
+; CHECK: vbroadcastss (%
+define <4 x i32> @F(i32* %ptr) nounwind uwtable readnone ssp {
+entry:
+ %q = load i32* %ptr, align 4
+ %vecinit.i = insertelement <4 x i32> undef, i32 %q, i32 0
+ %vecinit2.i = insertelement <4 x i32> %vecinit.i, i32 %q, i32 1
+ %vecinit4.i = insertelement <4 x i32> %vecinit2.i, i32 %q, i32 2
+ %vecinit6.i = insertelement <4 x i32> %vecinit4.i, i32 %q, i32 3
+ ret <4 x i32> %vecinit6.i
+}
+
+; Unsupported vbroadcasts
+
+; CHECK: _G
+; CHECK-NOT: vbroadcastsd (%
+; CHECK: ret
+define <2 x i64> @G(i64* %ptr) nounwind uwtable readnone ssp {
+entry:
+ %q = load i64* %ptr, align 8
+ %vecinit.i = insertelement <2 x i64> undef, i64 %q, i32 0
+ %vecinit2.i = insertelement <2 x i64> %vecinit.i, i64 %q, i32 1
+ ret <2 x i64> %vecinit2.i
+}
+
+; CHECK: _H
+; CHECK-NOT: vbroadcastss
+; CHECK: ret
+define <4 x i32> @H(<4 x i32> %a) {
+ %x = shufflevector <4 x i32> %a, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
+ ret <4 x i32> %x
+}
+
diff --git a/test/CodeGen/X86/avx-vextractf128.ll b/test/CodeGen/X86/avx-vextractf128.ll
new file mode 100644
index 0000000..dccf901
--- /dev/null
+++ b/test/CodeGen/X86/avx-vextractf128.ll
@@ -0,0 +1,18 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK-NOT: vunpck
+; CHECK: vextractf128 $1
+define <8 x float> @A(<8 x float> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 8, i32 8, i32 8, i32 8>
+ ret <8 x float> %shuffle
+}
+
+; CHECK-NOT: vunpck
+; CHECK: vextractf128 $1
+define <4 x double> @B(<4 x double> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <4 x double> %a, <4 x double> undef, <4 x i32> <i32 2, i32 3, i32 4, i32 4>
+ ret <4 x double> %shuffle
+}
+
diff --git a/test/CodeGen/X86/avx-vinsertf128.ll b/test/CodeGen/X86/avx-vinsertf128.ll
new file mode 100644
index 0000000..cda1331
--- /dev/null
+++ b/test/CodeGen/X86/avx-vinsertf128.ll
@@ -0,0 +1,58 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck -check-prefix=CHECK-SSE %s
+
+; CHECK-NOT: vunpck
+; CHECK: vinsertf128 $1
+define <8 x float> @A(<8 x float> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> undef, <8 x i32> <i32 8, i32 8, i32 8, i32 8, i32 0, i32 1, i32 2, i32 3>
+ ret <8 x float> %shuffle
+}
+
+; CHECK-NOT: vunpck
+; CHECK: vinsertf128 $1
+define <4 x double> @B(<4 x double> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <4 x double> %a, <4 x double> undef, <4 x i32> <i32 4, i32 4, i32 0, i32 1>
+ ret <4 x double> %shuffle
+}
+
+declare <2 x double> @llvm.x86.sse2.min.pd(<2 x double>, <2 x double>) nounwind readnone
+
+declare <2 x double> @llvm.x86.sse2.min.sd(<2 x double>, <2 x double>) nounwind readnone
+
+; Just check that no crash happens
+; CHECK-SSE: _insert_crash
+define void @insert_crash() nounwind {
+allocas:
+ %v1.i.i451 = shufflevector <4 x double> zeroinitializer, <4 x double> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
+ %ret_0a.i.i.i452 = shufflevector <4 x double> %v1.i.i451, <4 x double> undef, <2 x i32> <i32 0, i32 1>
+ %vret_0.i.i.i454 = tail call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> %ret_0a.i.i.i452, <2 x double> undef) nounwind
+ %ret_val.i.i.i463 = tail call <2 x double> @llvm.x86.sse2.min.sd(<2 x double> %vret_0.i.i.i454, <2 x double> undef) nounwind
+ %ret.i1.i.i464 = extractelement <2 x double> %ret_val.i.i.i463, i32 0
+ %double2float = fptrunc double %ret.i1.i.i464 to float
+ %smearinsert50 = insertelement <4 x float> undef, float %double2float, i32 3
+ %blendAsInt.i503 = bitcast <4 x float> %smearinsert50 to <4 x i32>
+ store <4 x i32> %blendAsInt.i503, <4 x i32>* undef, align 4
+ ret void
+}
+
+;; DAG Combine must remove useless vinsertf128 instructions
+
+; CHECK: DAGCombineA
+; CHECK-NOT: vinsertf128 $1
+define <4 x i32> @DAGCombineA(<4 x i32> %v1) nounwind readonly {
+ %1 = shufflevector <4 x i32> %v1, <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %2 = shufflevector <8 x i32> %1, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ ret <4 x i32> %2
+}
+
+; CHECK: DAGCombineB
+; CHECK: vpaddd %xmm
+; CHECK-NOT: vinsertf128 $1
+; CHECK: vpaddd %xmm
+define <8 x i32> @DAGCombineB(<8 x i32> %v1, <8 x i32> %v2) nounwind readonly {
+ %1 = add <8 x i32> %v1, %v2
+ %2 = add <8 x i32> %1, %v1
+ ret <8 x i32> %2
+}
diff --git a/test/CodeGen/X86/avx-vmovddup.ll b/test/CodeGen/X86/avx-vmovddup.ll
new file mode 100644
index 0000000..1c56fe2
--- /dev/null
+++ b/test/CodeGen/X86/avx-vmovddup.ll
@@ -0,0 +1,14 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vmovddup %ymm
+define <4 x i64> @A(<4 x i64> %a) {
+ %c = shufflevector <4 x i64> %a, <4 x i64> undef, <4 x i32> <i32 0, i32 0, i32 2, i32 2>
+ ret <4 x i64> %c
+}
+
+; CHECK: vmovddup (%
+define <4 x i64> @B(<4 x i64>* %ptr) {
+ %a = load <4 x i64>* %ptr
+ %c = shufflevector <4 x i64> %a, <4 x i64> undef, <4 x i32> <i32 0, i32 0, i32 2, i32 2>
+ ret <4 x i64> %c
+}
diff --git a/test/CodeGen/X86/avx-vperm2f128.ll b/test/CodeGen/X86/avx-vperm2f128.ll
new file mode 100644
index 0000000..3550a90
--- /dev/null
+++ b/test/CodeGen/X86/avx-vperm2f128.ll
@@ -0,0 +1,62 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vperm2f128 $1
+define <8 x float> @A(<8 x float> %a, <8 x float> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> %b, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
+ ret <8 x float> %shuffle
+}
+
+; CHECK: vperm2f128 $48
+define <8 x float> @B(<8 x float> %a, <8 x float> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
+ ret <8 x float> %shuffle
+}
+
+; CHECK: vperm2f128 $0
+define <8 x float> @C(<8 x float> %a, <8 x float> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3>
+ ret <8 x float> %shuffle
+}
+
+; CHECK: vperm2f128 $17
+define <8 x float> @D(<8 x float> %a, <8 x float> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> %b, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 4, i32 5, i32 6, i32 7>
+ ret <8 x float> %shuffle
+}
+
+; CHECK: vperm2f128 $17
+define <32 x i8> @E(<32 x i8> %a, <32 x i8> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <32 x i8> %a, <32 x i8> %b, <32 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+ ret <32 x i8> %shuffle
+}
+
+; CHECK: vperm2f128 $33
+define <4 x i64> @E2(<4 x i64> %a, <4 x i64> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <4 x i64> %a, <4 x i64> %b, <4 x i32> <i32 6, i32 7, i32 0, i32 1>
+ ret <4 x i64> %shuffle
+}
+
+;;;; Cases with undef indicies mixed in the mask
+
+; CHECK: vperm2f128 $33
+define <8 x float> @F(<8 x float> %a, <8 x float> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> %b, <8 x i32> <i32 undef, i32 undef, i32 6, i32 7, i32 undef, i32 9, i32 undef, i32 11>
+ ret <8 x float> %shuffle
+}
+
+;;;; Cases we must not select vperm2f128
+
+; CHECK: _G
+; CHECK-NOT: vperm2f128
+define <8 x float> @G(<8 x float> %a, <8 x float> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> %b, <8 x i32> <i32 undef, i32 undef, i32 6, i32 7, i32 undef, i32 12, i32 undef, i32 15>
+ ret <8 x float> %shuffle
+}
diff --git a/test/CodeGen/X86/avx-vpermil.ll b/test/CodeGen/X86/avx-vpermil.ll
new file mode 100644
index 0000000..49b2f54
--- /dev/null
+++ b/test/CodeGen/X86/avx-vpermil.ll
@@ -0,0 +1,45 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vpermilps
+define <8 x float> @funcA(<8 x float> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> undef, <8 x i32> <i32 1, i32 2, i32 3, i32 1, i32 5, i32 6, i32 7, i32 5>
+ ret <8 x float> %shuffle
+}
+
+; CHECK: vpermilpd
+define <4 x double> @funcB(<4 x double> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <4 x double> %a, <4 x double> undef, <4 x i32> <i32 1, i32 0, i32 3, i32 3>
+ ret <4 x double> %shuffle
+}
+
+; CHECK: vpermilps
+define <8 x i32> @funcC(<8 x i32> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x i32> %a, <8 x i32> undef, <8 x i32> <i32 1, i32 2, i32 3, i32 1, i32 5, i32 6, i32 7, i32 5>
+ ret <8 x i32> %shuffle
+}
+
+; CHECK: vpermilpd
+define <4 x i64> @funcD(<4 x i64> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <4 x i64> %a, <4 x i64> undef, <4 x i32> <i32 1, i32 0, i32 3, i32 3>
+ ret <4 x i64> %shuffle
+}
+
+; vpermil should match masks like this: <u,3,1,2,4,u,5,6>. Check that the
+; target specific mask was correctly generated.
+; CHECK: vpermilps $-100
+define <8 x float> @funcE(<8 x float> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> undef, <8 x i32> <i32 8, i32 3, i32 1, i32 2, i32 4, i32 8, i32 5, i32 6>
+ ret <8 x float> %shuffle
+}
+
+; CHECK-NOT: vpermilps
+define <8 x float> @funcF(<8 x float> %a) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> zeroinitializer, <8 x i32> <i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9>
+ ret <8 x float> %shuffle
+}
diff --git a/test/CodeGen/X86/avx-vshufp.ll b/test/CodeGen/X86/avx-vshufp.ll
new file mode 100644
index 0000000..f06548d
--- /dev/null
+++ b/test/CodeGen/X86/avx-vshufp.ll
@@ -0,0 +1,29 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+; CHECK: vshufps $-53, %ymm
+define <8 x float> @A(<8 x float> %a, <8 x float> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> %b, <8 x i32> <i32 3, i32 2, i32 8, i32 11, i32 7, i32 6, i32 12, i32 15>
+ ret <8 x float> %shuffle
+}
+
+; CHECK: vshufpd $10, %ymm
+define <4 x double> @B(<4 x double> %a, <4 x double> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <4 x double> %a, <4 x double> %b, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+ ret <4 x double> %shuffle
+}
+
+; CHECK: vshufps $-53, %ymm
+define <8 x float> @C(<8 x float> %a, <8 x float> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <8 x float> %a, <8 x float> %b, <8 x i32> <i32 3, i32 undef, i32 undef, i32 11, i32 undef, i32 6, i32 12, i32 undef>
+ ret <8 x float> %shuffle
+}
+
+; CHECK: vshufpd $2, %ymm
+define <4 x double> @D(<4 x double> %a, <4 x double> %b) nounwind uwtable readnone ssp {
+entry:
+ %shuffle = shufflevector <4 x double> %a, <4 x double> %b, <4 x i32> <i32 0, i32 5, i32 2, i32 undef>
+ ret <4 x double> %shuffle
+}
diff --git a/test/CodeGen/X86/avx-vzeroupper.ll b/test/CodeGen/X86/avx-vzeroupper.ll
new file mode 100644
index 0000000..eaf236c
--- /dev/null
+++ b/test/CodeGen/X86/avx-vzeroupper.ll
@@ -0,0 +1,26 @@
+; RUN: llc < %s -x86-use-vzeroupper -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
+
+define <4 x float> @do_sse_local(<4 x float> %a) nounwind uwtable readnone ssp {
+entry:
+ %add.i = fadd <4 x float> %a, %a
+ ret <4 x float> %add.i
+}
+
+; CHECK: _test00
+define <4 x float> @test00(<4 x float> %a, <4 x float> %b) nounwind uwtable ssp {
+entry:
+ %add.i = fadd <4 x float> %a, %b
+ ; CHECK: vzeroupper
+ ; CHECK-NEXT: callq _do_sse
+ %call3 = tail call <4 x float> @do_sse(<4 x float> %add.i) nounwind
+ %sub.i = fsub <4 x float> %call3, %add.i
+ ; CHECK-NOT: vzeroupper
+ ; CHECK: callq _do_sse_local
+ %call8 = tail call <4 x float> @do_sse_local(<4 x float> %sub.i)
+ ; CHECK: vzeroupper
+ ; CHECK-NEXT: jmp _do_sse
+ %call10 = tail call <4 x float> @do_sse(<4 x float> %call8) nounwind
+ ret <4 x float> %call10
+}
+
+declare <4 x float> @do_sse(<4 x float>)
diff --git a/test/CodeGen/X86/barrier-sse.ll b/test/CodeGen/X86/barrier-sse.ll
index 6190c36..bbfeea6 100644
--- a/test/CodeGen/X86/barrier-sse.ll
+++ b/test/CodeGen/X86/barrier-sse.ll
@@ -3,19 +3,9 @@
; RUN: llc < %s -march=x86 -mattr=+sse2 | not grep mfence
; RUN: llc < %s -march=x86 -mattr=+sse2 | grep MEMBARRIER
-
-declare void @llvm.memory.barrier( i1 , i1 , i1 , i1 , i1)
-
define void @test() {
- call void @llvm.memory.barrier( i1 true, i1 true, i1 false, i1 false, i1 false)
- call void @llvm.memory.barrier( i1 true, i1 false, i1 true, i1 false, i1 false)
- call void @llvm.memory.barrier( i1 true, i1 false, i1 false, i1 true, i1 false)
-
- call void @llvm.memory.barrier( i1 true, i1 true, i1 true, i1 false, i1 false)
- call void @llvm.memory.barrier( i1 true, i1 true, i1 false, i1 true, i1 false)
- call void @llvm.memory.barrier( i1 true, i1 false, i1 true, i1 true, i1 false)
-
- call void @llvm.memory.barrier( i1 true, i1 true, i1 true, i1 true , i1 false)
- call void @llvm.memory.barrier( i1 false, i1 false, i1 false, i1 false , i1 false)
- ret void
+ fence acquire
+ fence release
+ fence acq_rel
+ ret void
}
diff --git a/test/CodeGen/X86/barrier.ll b/test/CodeGen/X86/barrier.ll
index fad6ef6..4769b39 100644
--- a/test/CodeGen/X86/barrier.ll
+++ b/test/CodeGen/X86/barrier.ll
@@ -1,7 +1,6 @@
; RUN: llc < %s -march=x86 -mattr=-sse2 | grep lock
-declare void @llvm.memory.barrier( i1 , i1 , i1 , i1 , i1)
define void @test() {
- call void @llvm.memory.barrier( i1 true, i1 true, i1 false, i1 false, i1 false)
+ fence seq_cst
ret void
-} \ No newline at end of file
+}
diff --git a/test/CodeGen/X86/bmi.ll b/test/CodeGen/X86/bmi.ll
new file mode 100644
index 0000000..88c09e3
--- /dev/null
+++ b/test/CodeGen/X86/bmi.ll
@@ -0,0 +1,53 @@
+; RUN: llc < %s -march=x86-64 -mattr=+bmi | FileCheck %s
+
+define i32 @t1(i32 %x) nounwind {
+ %tmp = tail call i32 @llvm.cttz.i32( i32 %x )
+ ret i32 %tmp
+; CHECK: t1:
+; CHECK: tzcntl
+}
+
+declare i32 @llvm.cttz.i32(i32) nounwind readnone
+
+define i16 @t2(i16 %x) nounwind {
+ %tmp = tail call i16 @llvm.cttz.i16( i16 %x )
+ ret i16 %tmp
+; CHECK: t2:
+; CHECK: tzcntw
+}
+
+declare i16 @llvm.cttz.i16(i16) nounwind readnone
+
+define i64 @t3(i64 %x) nounwind {
+ %tmp = tail call i64 @llvm.cttz.i64( i64 %x )
+ ret i64 %tmp
+; CHECK: t3:
+; CHECK: tzcntq
+}
+
+declare i64 @llvm.cttz.i64(i64) nounwind readnone
+
+define i8 @t4(i8 %x) nounwind {
+ %tmp = tail call i8 @llvm.cttz.i8( i8 %x )
+ ret i8 %tmp
+; CHECK: t4:
+; CHECK: tzcntw
+}
+
+declare i8 @llvm.cttz.i8(i8) nounwind readnone
+
+define i32 @andn32(i32 %x, i32 %y) nounwind readnone {
+ %tmp1 = xor i32 %x, -1
+ %tmp2 = and i32 %y, %tmp1
+ ret i32 %tmp2
+; CHECK: andn32:
+; CHECK: andnl
+}
+
+define i64 @andn64(i64 %x, i64 %y) nounwind readnone {
+ %tmp1 = xor i64 %x, -1
+ %tmp2 = and i64 %tmp1, %y
+ ret i64 %tmp2
+; CHECK: andn64:
+; CHECK: andnq
+}
diff --git a/test/CodeGen/X86/bswap.ll b/test/CodeGen/X86/bswap.ll
index a7540aa..d2d6f90 100644
--- a/test/CodeGen/X86/bswap.ll
+++ b/test/CodeGen/X86/bswap.ll
@@ -1,6 +1,6 @@
; bswap should be constant folded when it is passed a constant argument
-; RUN: llc < %s -march=x86 | FileCheck %s
+; RUN: llc < %s -march=x86 -mcpu=i686 | FileCheck %s
declare i16 @llvm.bswap.i16(i16)
diff --git a/test/CodeGen/X86/change-compare-stride-0.ll b/test/CodeGen/X86/change-compare-stride-0.ll
index 3a383ee..439f7b0 100644
--- a/test/CodeGen/X86/change-compare-stride-0.ll
+++ b/test/CodeGen/X86/change-compare-stride-0.ll
@@ -1,4 +1,7 @@
-; RUN: llc < %s -march=x86 | FileCheck %s
+; RUN: llc < %s -march=x86 -enable-lsr-nested | FileCheck %s
+;
+; Nested LSR is required to optimize this case.
+; We do not expect to see this form of IR without -enable-iv-rewrite.
define void @borf(i8* nocapture %in, i8* nocapture %out) nounwind {
; CHECK: borf:
diff --git a/test/CodeGen/X86/change-compare-stride-1.ll b/test/CodeGen/X86/change-compare-stride-1.ll
index eee3b79..8b53ae2 100644
--- a/test/CodeGen/X86/change-compare-stride-1.ll
+++ b/test/CodeGen/X86/change-compare-stride-1.ll
@@ -1,4 +1,7 @@
-; RUN: llc < %s -march=x86-64 | FileCheck %s
+; RUN: llc < %s -march=x86-64 -enable-lsr-nested | FileCheck %s
+;
+; Nested LSR is required to optimize this case.
+; We do not expect to see this form of IR without -enable-iv-rewrite.
define void @borf(i8* nocapture %in, i8* nocapture %out) nounwind {
; CHECK: borf:
diff --git a/test/CodeGen/X86/cmov.ll b/test/CodeGen/X86/cmov.ll
index 39d9d1e..7a8d6e6 100644
--- a/test/CodeGen/X86/cmov.ll
+++ b/test/CodeGen/X86/cmov.ll
@@ -90,8 +90,8 @@ bb.i.i.i: ; preds = %entry
; CHECK: test4:
; CHECK: g_100
; CHECK: testb
-; CHECK: testb %al, %al
-; CHECK-NEXT: setne %al
+; CHECK-NOT: xor
+; CHECK: setne
; CHECK-NEXT: testb
func_4.exit.i: ; preds = %bb.i.i.i, %entry
diff --git a/test/CodeGen/X86/cmpxchg16b.ll b/test/CodeGen/X86/cmpxchg16b.ll
new file mode 100644
index 0000000..ba1c4ef
--- /dev/null
+++ b/test/CodeGen/X86/cmpxchg16b.ll
@@ -0,0 +1,13 @@
+; RUN: llc < %s -march=x86-64 -mcpu=core2 | FileCheck %s
+
+; Basic 128-bit cmpxchg
+define void @t1(i128* nocapture %p) nounwind ssp {
+entry:
+; CHECK movl $1, %ebx
+; CHECK: lock
+; CHECK-NEXT: cmpxchg16b
+ %r = cmpxchg i128* %p, i128 0, i128 1 seq_cst
+ ret void
+}
+
+; FIXME: Handle 128-bit atomicrmw/load atomic/store atomic
diff --git a/test/CodeGen/X86/coalescer-dce.ll b/test/CodeGen/X86/coalescer-dce.ll
new file mode 100644
index 0000000..7f72e3d
--- /dev/null
+++ b/test/CodeGen/X86/coalescer-dce.ll
@@ -0,0 +1,80 @@
+; RUN: llc < %s -disable-fp-elim -disable-machine-dce -verify-coalescing
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+; This test case has a sub-register join followed by a remat:
+;
+; 256L %vreg2<def> = COPY %vreg7:sub_32bit<kill>; GR32:%vreg2 GR64:%vreg7
+; Considering merging %vreg2 with %vreg7:sub_32bit
+; Cross-class to GR64.
+; RHS = %vreg2 = [256d,272d:0) 0@256d
+; LHS = %vreg7 = [208d,256d:0)[304L,480L:0) 0@208d
+; updated: 272L %vreg0<def> = COPY %vreg7:sub_32bit<kill>; GR32:%vreg0 GR64:%vreg7
+; Joined. Result = %vreg7 = [208d,272d:0)[304L,480L:0) 0@208d
+;
+; 272L %vreg10:sub_32bit<def> = COPY %vreg7:sub_32bit<kill>, %vreg10<imp-def>; GR64:%vreg10,%vreg7
+; Considering merging %vreg7 with %vreg10
+; RHS = %vreg7 = [208d,272d:0)[304L,480L:0) 0@208d
+; LHS = %vreg10 = [16d,64L:2)[64L,160L:1)[192L,240L:1)[272d,304L:3)[304L,352d:1)[352d,400d:0)[400d,400S:4) 0@352d 1@64L-phidef 2@16d-phikill 3@272d-phikill 4@400d
+; Remat: %vreg10<def> = MOV64r0 %vreg10<imp-def>, %EFLAGS<imp-def,dead>, %vreg10<imp-def>; GR64:%vreg10
+; Shrink: %vreg7 = [208d,272d:0)[304L,480L:0) 0@208d
+; live-in at 240L
+; live-in at 416L
+; live-in at 320L
+; live-in at 304L
+; Shrunk: %vreg7 = [208d,256d:0)[304L,480L:0) 0@208d
+;
+; The COPY at 256L is rewritten as a partial def, and that would artificially
+; extend the live range of %vreg7 to end at 256d. When the joined copy is
+; removed, -verify-coalescing complains about the dangling kill.
+;
+; <rdar://problem/9967101>
+
+define void @f1() nounwind uwtable ssp {
+bb:
+ br label %bb1
+
+bb1:
+ %tmp = phi i32 [ 0, %bb ], [ %tmp21, %bb20 ]
+ br label %bb2
+
+bb2:
+ br i1 undef, label %bb5, label %bb8
+
+bb4:
+ br i1 undef, label %bb2, label %bb20
+
+bb5:
+ br i1 undef, label %bb4, label %bb20
+
+bb8:
+ %tmp9 = phi i32 [ %tmp24, %bb23 ], [ 0, %bb2 ]
+ br i1 false, label %bb41, label %bb10
+
+bb10:
+ %tmp11 = sub nsw i32 %tmp9, %tmp
+ br i1 false, label %bb2, label %bb26
+
+bb20:
+ %tmp21 = phi i32 [ undef, %bb4 ], [ undef, %bb5 ], [ %tmp9, %bb27 ], [ undef, %bb32 ]
+ %tmp22 = phi i32 [ undef, %bb4 ], [ undef, %bb5 ], [ %tmp11, %bb27 ], [ undef, %bb32 ]
+ br label %bb1
+
+bb23:
+ %tmp24 = add nsw i32 %tmp9, 1
+ br label %bb8
+
+bb26:
+ br i1 undef, label %bb27, label %bb32
+
+bb27:
+ %tmp28 = zext i32 %tmp11 to i64
+ %tmp30 = icmp eq i64 undef, %tmp28
+ br i1 %tmp30, label %bb20, label %bb27
+
+bb32:
+ br i1 undef, label %bb20, label %bb23
+
+bb41:
+ ret void
+}
diff --git a/test/CodeGen/X86/coalescer-remat.ll b/test/CodeGen/X86/coalescer-remat.ll
index 4db520f..eb7b7a8 100644
--- a/test/CodeGen/X86/coalescer-remat.ll
+++ b/test/CodeGen/X86/coalescer-remat.ll
@@ -1,15 +1,13 @@
; RUN: llc < %s -mtriple=x86_64-apple-darwin | grep xor | count 3
-@val = internal global i64 0 ; <i64*> [#uses=1]
-@"\01LC" = internal constant [7 x i8] c"0x%lx\0A\00" ; <[7 x i8]*> [#uses=1]
+@val = internal global i64 0
+@"\01LC" = internal constant [7 x i8] c"0x%lx\0A\00"
define i32 @main() nounwind {
entry:
- %0 = tail call i64 @llvm.atomic.cmp.swap.i64.p0i64(i64* @val, i64 0, i64 1) ; <i64> [#uses=1]
- %1 = tail call i32 (i8*, ...)* @printf(i8* getelementptr ([7 x i8]* @"\01LC", i32 0, i64 0), i64 %0) nounwind ; <i32> [#uses=0]
- ret i32 0
+ %0 = cmpxchg i64* @val, i64 0, i64 1 monotonic
+ %1 = tail call i32 (i8*, ...)* @printf(i8* getelementptr ([7 x i8]* @"\01LC", i32 0, i64 0), i64 %0) nounwind
+ ret i32 0
}
-declare i64 @llvm.atomic.cmp.swap.i64.p0i64(i64*, i64, i64) nounwind
-
declare i32 @printf(i8*, ...) nounwind
diff --git a/test/CodeGen/X86/code_placement_eh.ll b/test/CodeGen/X86/code_placement_eh.ll
index 172d591..2da3f9f 100644
--- a/test/CodeGen/X86/code_placement_eh.ll
+++ b/test/CodeGen/X86/code_placement_eh.ll
@@ -22,11 +22,13 @@ bb18.i5.i: ; preds = %.noexc6.i.i, %bb51.
to label %.noexc6.i.i unwind label %lpad.i.i ; <float> [#uses=0]
lpad.i.i: ; preds = %bb18.i5.i, %.noexc6.i.i
- %eh_ptr.i.i = call i8* @llvm.eh.exception() ; <i8*> [#uses=1]
+ %lpadval.i.i = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
unreachable
lpad59.i: ; preds = %bb15
- %eh_ptr60.i = call i8* @llvm.eh.exception() ; <i8*> [#uses=1]
+ %lpadval60.i.i = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
unreachable
bb15: ; preds = %.noexc3, %invcont5
@@ -34,9 +36,7 @@ bb15: ; preds = %.noexc3, %invcont5
to label %.noexc3 unwind label %lpad59.i
}
-declare i8* @llvm.eh.exception() nounwind readonly
-
-declare i32 @llvm.eh.selector(i8*, i8*, ...) nounwind
+declare i32 @__gxx_personality_v0(...)
declare float @sinf(float) readonly
diff --git a/test/CodeGen/X86/crash-nosse.ll b/test/CodeGen/X86/crash-nosse.ll
new file mode 100644
index 0000000..1cec25b
--- /dev/null
+++ b/test/CodeGen/X86/crash-nosse.ll
@@ -0,0 +1,27 @@
+; RUN: llc < %s -mattr=-sse2,-sse41 -verify-machineinstrs
+target triple = "x86_64-unknown-linux-gnu"
+
+; PR10503
+; This test case produces INSERT_SUBREG 0, <undef> instructions that
+; ProcessImplicitDefs doesn't eliminate.
+define void @autogen_136178_500() {
+BB:
+ %Shuff6 = shufflevector <32 x i32> undef, <32 x i32> undef, <32 x i32> <i32 27, i32 29, i32 31, i32 undef, i32 undef, i32 37, i32 39, i32 41, i32 undef, i32 45, i32 47, i32 49, i32 51, i32 53, i32 55, i32 57, i32 undef, i32 61, i32 63, i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 undef, i32 15, i32 17, i32 19, i32 21, i32 23, i32 25>
+ %S17 = select i1 true, <8 x float>* null, <8 x float>* null
+ br label %CF
+
+CF: ; preds = %CF, %BB
+ %L19 = load <8 x float>* %S17
+ %BC = bitcast <32 x i32> %Shuff6 to <32 x float>
+ %S28 = fcmp ord double 0x3ED1A1F787BB2185, 0x3EE59DE55A8DF890
+ br i1 %S28, label %CF, label %CF39
+
+CF39: ; preds = %CF39, %CF
+ store <8 x float> %L19, <8 x float>* %S17
+ %I35 = insertelement <32 x float> %BC, float 0x3EC2489F60000000, i32 9
+ %S38 = fcmp ule double 0x3EE59DE55A8DF890, 0x3EC4AB0CBB986A1A
+ br i1 %S38, label %CF39, label %CF40
+
+CF40: ; preds = %CF39
+ ret void
+}
diff --git a/test/CodeGen/X86/crash.ll b/test/CodeGen/X86/crash.ll
index b5b1ad4..1531457 100644
--- a/test/CodeGen/X86/crash.ll
+++ b/test/CodeGen/X86/crash.ll
@@ -316,3 +316,78 @@ declare void @_ZNSt6vectorIN4llvm11MachineMoveESaIS1_EE13_M_insert_auxEN9__gnu_c
declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind
declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind
+
+; PR10463
+; Spilling a virtual register with <undef> uses.
+define void @autogen_239_1000() {
+BB:
+ %Shuff = shufflevector <8 x double> undef, <8 x double> undef, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 undef, i32 undef>
+ br label %CF
+
+CF:
+ %B16 = frem <8 x double> zeroinitializer, %Shuff
+ %E19 = extractelement <8 x double> %Shuff, i32 5
+ br i1 undef, label %CF, label %CF75
+
+CF75:
+ br i1 undef, label %CF75, label %CF76
+
+CF76:
+ store double %E19, double* undef
+ br i1 undef, label %CF76, label %CF77
+
+CF77:
+ %B55 = fmul <8 x double> %B16, undef
+ br label %CF77
+}
+
+; PR10527
+define void @pr10527() nounwind uwtable {
+entry:
+ br label %"4"
+
+"3":
+ %0 = load <2 x i32>* null, align 8
+ %1 = xor <2 x i32> zeroinitializer, %0
+ %2 = and <2 x i32> %1, %6
+ %3 = or <2 x i32> undef, %2
+ %4 = and <2 x i32> %3, undef
+ store <2 x i32> %4, <2 x i32>* undef
+ %5 = load <2 x i32>* undef, align 1
+ br label %"4"
+
+"4":
+ %6 = phi <2 x i32> [ %5, %"3" ], [ zeroinitializer, %entry ]
+ %7 = icmp ult i32 undef, undef
+ br i1 %7, label %"3", label %"5"
+
+"5":
+ ret void
+}
+
+; PR11078
+;
+; A virtual register used by the "foo" inline asm memory operand gets
+; constrained to GR32_ABCD during coalescing. This makes the inline asm
+; impossible to allocate without splitting the live range and reinflating the
+; register class around the inline asm.
+;
+; The constraint originally comes from the TEST8ri optimization of (icmp (and %t0, 1), 0).
+
+@__force_order = external hidden global i32, align 4
+define void @pr11078(i32* %pgd) nounwind {
+entry:
+ %t0 = load i32* %pgd, align 4
+ %and2 = and i32 %t0, 1
+ %tobool = icmp eq i32 %and2, 0
+ br i1 %tobool, label %if.then, label %if.end
+
+if.then:
+ %t1 = tail call i32 asm sideeffect "bar", "=r,=*m,~{dirflag},~{fpsr},~{flags}"(i32* @__force_order) nounwind
+ br label %if.end
+
+if.end:
+ %t6 = inttoptr i32 %t0 to i64*
+ %t11 = tail call i64 asm sideeffect "foo", "=*m,=A,{bx},{cx},1,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %t6, i32 0, i32 0, i64 0) nounwind
+ ret void
+}
diff --git a/test/CodeGen/X86/dbg-at-specficiation.ll b/test/CodeGen/X86/dbg-at-specficiation.ll
new file mode 100644
index 0000000..aa5e6ef
--- /dev/null
+++ b/test/CodeGen/X86/dbg-at-specficiation.ll
@@ -0,0 +1,20 @@
+; RUN: llc < %s | FileCheck %s
+; Radar 10147769
+; Do not unnecessarily use AT_specification DIE.
+; CHECK-NOT: AT_specification
+
+@a = common global [10 x i32] zeroinitializer, align 16
+
+!llvm.dbg.cu = !{!0}
+
+!0 = metadata !{i32 720913, i32 0, i32 12, metadata !"x.c", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 140253)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !1, metadata !3} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 720948, i32 0, null, metadata !"a", metadata !"a", metadata !"", metadata !6, i32 1, metadata !7, i32 0, i32 1, [10 x i32]* @a} ; [ DW_TAG_variable ]
+!6 = metadata !{i32 720937, metadata !"x.c", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 720897, null, metadata !"", null, i32 0, i64 320, i64 32, i32 0, i32 0, metadata !8, metadata !9, i32 0, i32 0} ; [ DW_TAG_array_type ]
+!8 = metadata !{i32 720932, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!9 = metadata !{metadata !10}
+!10 = metadata !{i32 720929, i64 0, i64 9} ; [ DW_TAG_subrange_type ]
diff --git a/test/CodeGen/X86/dbg-inline.ll b/test/CodeGen/X86/dbg-inline.ll
new file mode 100644
index 0000000..523c62e
--- /dev/null
+++ b/test/CodeGen/X86/dbg-inline.ll
@@ -0,0 +1,140 @@
+; RUN: llc < %s | FileCheck %s
+; Radar 7881628, 9747970
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+%class.APFloat = type { i32 }
+
+define i32 @_ZNK7APFloat9partCountEv(%class.APFloat* nocapture %this) nounwind uwtable readonly optsize ssp align 2 {
+entry:
+ tail call void @llvm.dbg.value(metadata !{%class.APFloat* %this}, i64 0, metadata !28), !dbg !41
+ %prec = getelementptr inbounds %class.APFloat* %this, i64 0, i32 0, !dbg !42
+ %tmp = load i32* %prec, align 4, !dbg !42, !tbaa !44
+ tail call void @llvm.dbg.value(metadata !{i32 %tmp}, i64 0, metadata !47), !dbg !48
+ %add.i = add i32 %tmp, 42, !dbg !49
+ ret i32 %add.i, !dbg !42
+}
+
+define zeroext i1 @_ZNK7APFloat14bitwiseIsEqualERKS_(%class.APFloat* %this, %class.APFloat* %rhs) uwtable optsize ssp align 2 {
+entry:
+ tail call void @llvm.dbg.value(metadata !{%class.APFloat* %this}, i64 0, metadata !29), !dbg !51
+ tail call void @llvm.dbg.value(metadata !{%class.APFloat* %rhs}, i64 0, metadata !30), !dbg !52
+ tail call void @llvm.dbg.value(metadata !{%class.APFloat* %this}, i64 0, metadata !53), !dbg !55
+ %prec.i = getelementptr inbounds %class.APFloat* %this, i64 0, i32 0, !dbg !56
+;CHECK: DW_TAG_inlined_subroutine
+;CHECK: DW_AT_abstract_origin
+;CHECK: DW_AT_ranges
+ %tmp.i = load i32* %prec.i, align 4, !dbg !56, !tbaa !44
+ tail call void @llvm.dbg.value(metadata !{i32 %tmp.i}, i64 0, metadata !57), !dbg !58
+ %add.i.i = add i32 %tmp.i, 42, !dbg !59
+ tail call void @llvm.dbg.value(metadata !{i32 %add.i.i}, i64 0, metadata !31), !dbg !54
+ %call2 = tail call i64* @_ZNK7APFloat16significandPartsEv(%class.APFloat* %this) optsize, !dbg !60
+ tail call void @llvm.dbg.value(metadata !{i64* %call2}, i64 0, metadata !34), !dbg !60
+ %call3 = tail call i64* @_ZNK7APFloat16significandPartsEv(%class.APFloat* %rhs) optsize, !dbg !61
+ tail call void @llvm.dbg.value(metadata !{i64* %call3}, i64 0, metadata !37), !dbg !61
+ %tmp = zext i32 %add.i.i to i64
+ br label %for.cond, !dbg !62
+
+for.cond: ; preds = %for.inc, %entry
+ %indvar = phi i64 [ %indvar.next, %for.inc ], [ 0, %entry ]
+ %tmp13 = sub i64 %tmp, %indvar, !dbg !62
+ %i.0 = trunc i64 %tmp13 to i32, !dbg !62
+ %cmp = icmp sgt i32 %i.0, 0, !dbg !62
+ br i1 %cmp, label %for.body, label %return, !dbg !62
+
+for.body: ; preds = %for.cond
+ %p.0 = getelementptr i64* %call2, i64 %indvar, !dbg !63
+ %tmp6 = load i64* %p.0, align 8, !dbg !63, !tbaa !66
+ %tmp8 = load i64* %call3, align 8, !dbg !63, !tbaa !66
+ %cmp9 = icmp eq i64 %tmp6, %tmp8, !dbg !63
+ br i1 %cmp9, label %for.inc, label %return, !dbg !63
+
+for.inc: ; preds = %for.body
+ %indvar.next = add i64 %indvar, 1, !dbg !67
+ br label %for.cond, !dbg !67
+
+return: ; preds = %for.cond, %for.body
+ %retval.0 = phi i1 [ false, %for.body ], [ true, %for.cond ]
+ ret i1 %retval.0, !dbg !68
+}
+
+declare i64* @_ZNK7APFloat16significandPartsEv(%class.APFloat*) optsize
+
+declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone
+
+!llvm.dbg.cu = !{!0}
+!llvm.dbg.sp = !{!1, !7, !12, !23, !24, !25}
+!llvm.dbg.lv._ZNK7APFloat9partCountEv = !{!28}
+!llvm.dbg.lv._ZNK7APFloat14bitwiseIsEqualERKS_ = !{!29, !30, !31, !34, !37}
+!llvm.dbg.lv._ZL16partCountForBitsj = !{!38}
+!llvm.dbg.gv = !{!39}
+
+!0 = metadata !{i32 655377, i32 0, i32 4, metadata !"/Volumes/Athwagate/R9747970/apf.cc", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 136149)", i1 true, i1 true, metadata !"", i32 0} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{i32 655406, i32 0, metadata !2, metadata !"bitwiseIsEqual", metadata !"bitwiseIsEqual", metadata !"_ZNK7APFloat14bitwiseIsEqualERKS_", metadata !3, i32 8, metadata !19, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 true, null, null} ; [ DW_TAG_subprogram ]
+!2 = metadata !{i32 655362, metadata !0, metadata !"APFloat", metadata !3, i32 6, i64 32, i64 32, i32 0, i32 0, null, metadata !4, i32 0, null, null} ; [ DW_TAG_class_type ]
+!3 = metadata !{i32 655401, metadata !"/Volumes/Athwagate/R9747970/apf.cc", metadata !"/private/tmp", metadata !0} ; [ DW_TAG_file_type ]
+!4 = metadata !{metadata !5, metadata !1, metadata !7, metadata !12}
+!5 = metadata !{i32 655373, metadata !2, metadata !"prec", metadata !3, i32 13, i64 32, i64 32, i64 0, i32 0, metadata !6} ; [ DW_TAG_member ]
+!6 = metadata !{i32 655396, metadata !0, metadata !"unsigned int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ]
+!7 = metadata !{i32 655406, i32 0, metadata !2, metadata !"partCount", metadata !"partCount", metadata !"_ZNK7APFloat9partCountEv", metadata !3, i32 9, metadata !8, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 true, null, null} ; [ DW_TAG_subprogram ]
+!8 = metadata !{i32 655381, metadata !3, metadata !"", metadata !3, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !9, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!9 = metadata !{metadata !6, metadata !10}
+!10 = metadata !{i32 655375, metadata !0, metadata !"", i32 0, i32 0, i64 64, i64 64, i64 0, i32 64, metadata !11} ; [ DW_TAG_pointer_type ]
+!11 = metadata !{i32 655398, metadata !0, metadata !"", null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !2} ; [ DW_TAG_const_type ]
+!12 = metadata !{i32 655406, i32 0, metadata !2, metadata !"significandParts", metadata !"significandParts", metadata !"_ZNK7APFloat16significandPartsEv", metadata !3, i32 11, metadata !13, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 true, null, null} ; [ DW_TAG_subprogram ]
+!13 = metadata !{i32 655381, metadata !3, metadata !"", metadata !3, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !14, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!14 = metadata !{metadata !15, metadata !10}
+!15 = metadata !{i32 655375, metadata !0, metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !16} ; [ DW_TAG_pointer_type ]
+!16 = metadata !{i32 655382, metadata !0, metadata !"integerPart", metadata !3, i32 2, i64 0, i64 0, i64 0, i32 0, metadata !17} ; [ DW_TAG_typedef ]
+!17 = metadata !{i32 655382, metadata !0, metadata !"uint64_t", metadata !3, i32 1, i64 0, i64 0, i64 0, i32 0, metadata !18} ; [ DW_TAG_typedef ]
+!18 = metadata !{i32 655396, metadata !0, metadata !"long long unsigned int", null, i32 0, i64 64, i64 64, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ]
+!19 = metadata !{i32 655381, metadata !3, metadata !"", metadata !3, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !20, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!20 = metadata !{metadata !21, metadata !10, metadata !22}
+!21 = metadata !{i32 655396, metadata !0, metadata !"bool", null, i32 0, i64 8, i64 8, i64 0, i32 0, i32 2} ; [ DW_TAG_base_type ]
+!22 = metadata !{i32 655376, metadata !0, null, null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !11} ; [ DW_TAG_reference_type ]
+!23 = metadata !{i32 655406, i32 0, metadata !0, metadata !"partCount", metadata !"partCount", metadata !"_ZNK7APFloat9partCountEv", metadata !3, i32 23, metadata !8, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, i32 (%class.APFloat*)* @_ZNK7APFloat9partCountEv, null, metadata !7} ; [ DW_TAG_subprogram ]
+!24 = metadata !{i32 655406, i32 0, metadata !0, metadata !"bitwiseIsEqual", metadata !"bitwiseIsEqual", metadata !"_ZNK7APFloat14bitwiseIsEqualERKS_", metadata !3, i32 28, metadata !19, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, i1 (%class.APFloat*, %class.APFloat*)* @_ZNK7APFloat14bitwiseIsEqualERKS_, null, metadata !1} ; [ DW_TAG_subprogram ]
+!25 = metadata !{i32 655406, i32 0, metadata !3, metadata !"partCountForBits", metadata !"partCountForBits", metadata !"", metadata !3, i32 17, metadata !26, i1 true, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, null, null, null} ; [ DW_TAG_subprogram ]
+!26 = metadata !{i32 655381, metadata !3, metadata !"", metadata !3, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !27, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!27 = metadata !{metadata !6}
+!28 = metadata !{i32 655617, metadata !23, metadata !"this", metadata !3, i32 16777238, metadata !10, i32 64, i32 0} ; [ DW_TAG_arg_variable ]
+!29 = metadata !{i32 655617, metadata !24, metadata !"this", metadata !3, i32 16777244, metadata !10, i32 64, i32 0} ; [ DW_TAG_arg_variable ]
+!30 = metadata !{i32 655617, metadata !24, metadata !"rhs", metadata !3, i32 33554460, metadata !22, i32 0, i32 0} ; [ DW_TAG_arg_variable ]
+!31 = metadata !{i32 655616, metadata !32, metadata !"i", metadata !3, i32 29, metadata !33, i32 0, i32 0} ; [ DW_TAG_auto_variable ]
+!32 = metadata !{i32 655371, metadata !24, i32 28, i32 56, metadata !3, i32 1} ; [ DW_TAG_lexical_block ]
+!33 = metadata !{i32 655396, metadata !0, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!34 = metadata !{i32 655616, metadata !32, metadata !"p", metadata !3, i32 30, metadata !35, i32 0, i32 0} ; [ DW_TAG_auto_variable ]
+!35 = metadata !{i32 655375, metadata !0, metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !36} ; [ DW_TAG_pointer_type ]
+!36 = metadata !{i32 655398, metadata !0, metadata !"", null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !16} ; [ DW_TAG_const_type ]
+!37 = metadata !{i32 655616, metadata !32, metadata !"q", metadata !3, i32 31, metadata !35, i32 0, i32 0} ; [ DW_TAG_auto_variable ]
+!38 = metadata !{i32 655617, metadata !25, metadata !"bits", metadata !3, i32 16777232, metadata !6, i32 0, i32 0} ; [ DW_TAG_arg_variable ]
+!39 = metadata !{i32 655412, i32 0, metadata !3, metadata !"integerPartWidth", metadata !"integerPartWidth", metadata !"integerPartWidth", metadata !3, i32 3, metadata !40, i32 1, i32 1, i32 42} ; [ DW_TAG_variable ]
+!40 = metadata !{i32 655398, metadata !0, metadata !"", null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !6} ; [ DW_TAG_const_type ]
+!41 = metadata !{i32 22, i32 23, metadata !23, null}
+!42 = metadata !{i32 24, i32 10, metadata !43, null}
+!43 = metadata !{i32 655371, metadata !23, i32 23, i32 1, metadata !3, i32 0} ; [ DW_TAG_lexical_block ]
+!44 = metadata !{metadata !"int", metadata !45}
+!45 = metadata !{metadata !"omnipotent char", metadata !46}
+!46 = metadata !{metadata !"Simple C/C++ TBAA", null}
+!47 = metadata !{i32 655617, metadata !25, metadata !"bits", metadata !3, i32 16777232, metadata !6, i32 0, metadata !42} ; [ DW_TAG_arg_variable ]
+!48 = metadata !{i32 16, i32 58, metadata !25, metadata !42}
+!49 = metadata !{i32 18, i32 3, metadata !50, metadata !42}
+!50 = metadata !{i32 655371, metadata !25, i32 17, i32 1, metadata !3, i32 4} ; [ DW_TAG_lexical_block ]
+!51 = metadata !{i32 28, i32 15, metadata !24, null}
+!52 = metadata !{i32 28, i32 45, metadata !24, null}
+!53 = metadata !{i32 655617, metadata !23, metadata !"this", metadata !3, i32 16777238, metadata !10, i32 64, metadata !54} ; [ DW_TAG_arg_variable ]
+!54 = metadata !{i32 29, i32 10, metadata !32, null}
+!55 = metadata !{i32 22, i32 23, metadata !23, metadata !54}
+!56 = metadata !{i32 24, i32 10, metadata !43, metadata !54}
+!57 = metadata !{i32 655617, metadata !25, metadata !"bits", metadata !3, i32 16777232, metadata !6, i32 0, metadata !56} ; [ DW_TAG_arg_variable ]
+!58 = metadata !{i32 16, i32 58, metadata !25, metadata !56}
+!59 = metadata !{i32 18, i32 3, metadata !50, metadata !56}
+!60 = metadata !{i32 30, i32 24, metadata !32, null}
+!61 = metadata !{i32 31, i32 24, metadata !32, null}
+!62 = metadata !{i32 32, i32 3, metadata !32, null}
+!63 = metadata !{i32 33, i32 5, metadata !64, null}
+!64 = metadata !{i32 655371, metadata !65, i32 32, i32 25, metadata !3, i32 3} ; [ DW_TAG_lexical_block ]
+!65 = metadata !{i32 655371, metadata !32, i32 32, i32 3, metadata !3, i32 2} ; [ DW_TAG_lexical_block ]
+!66 = metadata !{metadata !"long long", metadata !45}
+!67 = metadata !{i32 32, i32 15, metadata !65, null}
+!68 = metadata !{i32 37, i32 1, metadata !32, null}
diff --git a/test/CodeGen/X86/dbg-large-unsigned-const.ll b/test/CodeGen/X86/dbg-large-unsigned-const.ll
new file mode 100644
index 0000000..fc295c6
--- /dev/null
+++ b/test/CodeGen/X86/dbg-large-unsigned-const.ll
@@ -0,0 +1,61 @@
+; RUN: llc -filetype=obj %s -o /dev/null
+; Hanle large unsigned constant values.
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
+target triple = "i386-apple-macosx10.7.0"
+
+define zeroext i1 @_Z3iseRKxS0_(i64* nocapture %LHS, i64* nocapture %RHS) nounwind readonly optsize ssp {
+entry:
+ tail call void @llvm.dbg.value(metadata !{i64* %LHS}, i64 0, metadata !7), !dbg !13
+ tail call void @llvm.dbg.value(metadata !{i64* %RHS}, i64 0, metadata !11), !dbg !14
+ %tmp1 = load i64* %LHS, align 4, !dbg !15, !tbaa !17
+ %tmp3 = load i64* %RHS, align 4, !dbg !15, !tbaa !17
+ %cmp = icmp eq i64 %tmp1, %tmp3, !dbg !15
+ ret i1 %cmp, !dbg !15
+}
+
+define zeroext i1 @_Z2fnx(i64 %a) nounwind readnone optsize ssp {
+entry:
+ tail call void @llvm.dbg.value(metadata !{i64 %a}, i64 0, metadata !12), !dbg !20
+ tail call void @llvm.dbg.value(metadata !{i64 %a}, i64 0, metadata !12), !dbg !20
+ tail call void @llvm.dbg.value(metadata !{i64 %a}, i64 0, metadata !21), !dbg !24
+ tail call void @llvm.dbg.value(metadata !25, i64 0, metadata !26), !dbg !27
+ %cmp.i = icmp eq i64 %a, 9223372036854775807, !dbg !28
+ ret i1 %cmp.i, !dbg !22
+}
+
+declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone
+
+!llvm.dbg.cu = !{!0}
+!llvm.dbg.sp = !{!1, !6}
+!llvm.dbg.lv._Z3iseRKxS0_ = !{!7, !11}
+!llvm.dbg.lv._Z2fnx = !{!12}
+
+!0 = metadata !{i32 655377, i32 0, i32 4, metadata !"lli.cc", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 135593)", i1 true, i1 true, metadata !"", i32 0} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{i32 655406, i32 0, metadata !2, metadata !"ise", metadata !"ise", metadata !"_Z3iseRKxS0_", metadata !2, i32 2, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, i1 (i64*, i64*)* @_Z3iseRKxS0_, null, null} ; [ DW_TAG_subprogram ]
+!2 = metadata !{i32 655401, metadata !"lli.cc", metadata !"/private/tmp", metadata !0} ; [ DW_TAG_file_type ]
+!3 = metadata !{i32 655381, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 655396, metadata !0, metadata !"bool", null, i32 0, i64 8, i64 8, i64 0, i32 0, i32 2} ; [ DW_TAG_base_type ]
+!6 = metadata !{i32 655406, i32 0, metadata !2, metadata !"fn", metadata !"fn", metadata !"_Z2fnx", metadata !2, i32 6, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, i1 (i64)* @_Z2fnx, null, null} ; [ DW_TAG_subprogram ]
+!7 = metadata !{i32 655617, metadata !1, metadata !"LHS", metadata !2, i32 16777218, metadata !8, i32 0, i32 0} ; [ DW_TAG_arg_variable ]
+!8 = metadata !{i32 655376, metadata !0, null, null, i32 0, i64 32, i64 32, i64 0, i32 0, metadata !9} ; [ DW_TAG_reference_type ]
+!9 = metadata !{i32 655398, metadata !0, metadata !"", null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !10} ; [ DW_TAG_const_type ]
+!10 = metadata !{i32 655396, metadata !0, metadata !"long long int", null, i32 0, i64 64, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!11 = metadata !{i32 655617, metadata !1, metadata !"RHS", metadata !2, i32 33554434, metadata !8, i32 0, i32 0} ; [ DW_TAG_arg_variable ]
+!12 = metadata !{i32 655617, metadata !6, metadata !"a", metadata !2, i32 16777222, metadata !10, i32 0, i32 0} ; [ DW_TAG_arg_variable ]
+!13 = metadata !{i32 2, i32 27, metadata !1, null}
+!14 = metadata !{i32 2, i32 49, metadata !1, null}
+!15 = metadata !{i32 3, i32 3, metadata !16, null}
+!16 = metadata !{i32 655371, metadata !1, i32 2, i32 54, metadata !2, i32 0} ; [ DW_TAG_lexical_block ]
+!17 = metadata !{metadata !"long long", metadata !18}
+!18 = metadata !{metadata !"omnipotent char", metadata !19}
+!19 = metadata !{metadata !"Simple C/C++ TBAA", null}
+!20 = metadata !{i32 6, i32 19, metadata !6, null}
+!21 = metadata !{i32 655617, metadata !1, metadata !"LHS", metadata !2, i32 16777218, metadata !8, i32 0, metadata !22} ; [ DW_TAG_arg_variable ]
+!22 = metadata !{i32 7, i32 10, metadata !23, null}
+!23 = metadata !{i32 655371, metadata !6, i32 6, i32 22, metadata !2, i32 1} ; [ DW_TAG_lexical_block ]
+!24 = metadata !{i32 2, i32 27, metadata !1, metadata !22}
+!25 = metadata !{i64 9223372036854775807}
+!26 = metadata !{i32 655617, metadata !1, metadata !"RHS", metadata !2, i32 33554434, metadata !8, i32 0, metadata !22} ; [ DW_TAG_arg_variable ]
+!27 = metadata !{i32 2, i32 49, metadata !1, metadata !22}
+!28 = metadata !{i32 3, i32 3, metadata !16, metadata !22}
diff --git a/test/CodeGen/X86/dbg-value-isel.ll b/test/CodeGen/X86/dbg-value-isel.ll
index d1a9e57..f1101e6 100644
--- a/test/CodeGen/X86/dbg-value-isel.ll
+++ b/test/CodeGen/X86/dbg-value-isel.ll
@@ -29,8 +29,8 @@ entry:
get_local_id.exit: ; preds = %4
%6 = phi i32 [ %5, %4 ]
call void @llvm.dbg.value(metadata !{i32 %6}, i64 0, metadata !10), !dbg !12
- %7 = call <4 x i32> @__amdil_get_global_id_int() nounwind
- %8 = extractelement <4 x i32> %7, i32 0
+ %7 = call <4 x i32> @__amdil_get_global_id_int() nounwind, !dbg !12
+ %8 = extractelement <4 x i32> %7, i32 0, !dbg !12
br label %9
; <label>:9 ; preds = %get_local_id.exit
diff --git a/test/CodeGen/X86/extractelement-load.ll b/test/CodeGen/X86/extractelement-load.ll
index ee57d9b..06d739c 100644
--- a/test/CodeGen/X86/extractelement-load.ll
+++ b/test/CodeGen/X86/extractelement-load.ll
@@ -1,9 +1,25 @@
-; RUN: llc < %s -march=x86 -mattr=+sse2 -mcpu=yonah | not grep movd
-; RUN: llc < %s -march=x86-64 -mattr=+sse2 -mcpu=core2 | not grep movd
+; RUN: llc < %s -march=x86 -mattr=+sse2 -mcpu=yonah | FileCheck %s
+; RUN: llc < %s -march=x86-64 -mattr=+sse2 -mcpu=core2 | FileCheck %s
define i32 @t(<2 x i64>* %val) nounwind {
+; CHECK: t:
+; CHECK-NOT: movd
+; CHECK: movl 8(
+; CHECK-NEXT: ret
%tmp2 = load <2 x i64>* %val, align 16 ; <<2 x i64>> [#uses=1]
%tmp3 = bitcast <2 x i64> %tmp2 to <4 x i32> ; <<4 x i32>> [#uses=1]
%tmp4 = extractelement <4 x i32> %tmp3, i32 2 ; <i32> [#uses=1]
ret i32 %tmp4
}
+
+; Case where extractelement of load ends up as undef.
+; (Making sure this doesn't crash.)
+define i32 @t2(<8 x i32>* %xp) {
+; CHECK: t2:
+; CHECK: ret
+ %x = load <8 x i32>* %xp
+ %Shuff68 = shufflevector <8 x i32> %x, <8 x i32> undef, <8 x i32> <i32
+undef, i32 7, i32 9, i32 undef, i32 13, i32 15, i32 1, i32 3>
+ %y = extractelement <8 x i32> %Shuff68, i32 0
+ ret i32 %y
+}
diff --git a/test/CodeGen/X86/fast-isel-atomic.ll b/test/CodeGen/X86/fast-isel-atomic.ll
index 74c5868..5f761dd 100644
--- a/test/CodeGen/X86/fast-isel-atomic.ll
+++ b/test/CodeGen/X86/fast-isel-atomic.ll
@@ -5,13 +5,11 @@
@sc = external global i8
@uc = external global i8
-declare i8 @llvm.atomic.load.and.i8.p0i8(i8* nocapture, i8) nounwind
-
define void @test_fetch_and_op() nounwind {
entry:
- %tmp40 = call i8 @llvm.atomic.load.and.i8.p0i8(i8* @sc, i8 11) ; <i8> [#uses=1]
+ %tmp40 = atomicrmw and i8* @sc, i8 11 monotonic
store i8 %tmp40, i8* @sc
- %tmp41 = call i8 @llvm.atomic.load.and.i8.p0i8(i8* @uc, i8 11) ; <i8> [#uses=1]
+ %tmp41 = atomicrmw and i8* @uc, i8 11 monotonic
store i8 %tmp41, i8* @uc
ret void
}
diff --git a/test/CodeGen/X86/fast-isel-cmp-branch.ll b/test/CodeGen/X86/fast-isel-cmp-branch.ll
index 12312e8..6e408f8 100644
--- a/test/CodeGen/X86/fast-isel-cmp-branch.ll
+++ b/test/CodeGen/X86/fast-isel-cmp-branch.ll
@@ -26,5 +26,9 @@ true:
return:
ret void
unw:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/fast-isel-gep.ll b/test/CodeGen/X86/fast-isel-gep.ll
index 1a2e34e..91d1f5d 100644
--- a/test/CodeGen/X86/fast-isel-gep.ll
+++ b/test/CodeGen/X86/fast-isel-gep.ll
@@ -104,6 +104,36 @@ invoke.cont16: ; preds = %if.then14
unreachable
lpad: ; preds = %if.end19, %if.then14, %if.end, %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
declare i8* @_ZNK18G__FastAllocString4dataEv() nounwind
+
+
+; PR10605 / rdar://9930964 - Don't fold loads incorrectly. The load should
+; happen before the store.
+define i32 @test7({i32,i32,i32}* %tmp1, i32 %tmp71, i32 %tmp63) nounwind {
+; X64: test7:
+; X64: movl 8({{%rdi|%rcx}}), %eax
+; X64: movl $4, 8({{%rdi|%rcx}})
+
+
+ %tmp29 = getelementptr inbounds {i32,i32,i32}* %tmp1, i32 0, i32 2
+ %tmp30 = load i32* %tmp29, align 4
+
+ %p2 = getelementptr inbounds {i32,i32,i32}* %tmp1, i32 0, i32 2
+ store i32 4, i32* %p2
+
+ %tmp72 = or i32 %tmp71, %tmp30
+ %tmp73 = icmp ne i32 %tmp63, 32
+ br i1 %tmp73, label %T, label %F
+
+T:
+ ret i32 %tmp72
+
+F:
+ ret i32 4
+}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/fast-isel-tls.ll b/test/CodeGen/X86/fast-isel-tls.ll
index a5e6642..0963c52 100644
--- a/test/CodeGen/X86/fast-isel-tls.ll
+++ b/test/CodeGen/X86/fast-isel-tls.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -march=x86 -relocation-model=pic -mtriple=i686-unknown-linux-gnu -fast-isel | grep __tls_get_addr
+; RUN: llc < %s -march=x86 -relocation-model=pic -mtriple=i686-unknown-linux-gnu -fast-isel | FileCheck %s
; PR3654
@v = thread_local global i32 0
@@ -8,3 +8,19 @@ entry:
%s = add i32 %t, 1
ret i32 %s
}
+
+; CHECK: f:
+; CHECK: leal v@TLSGD
+; CHECK: __tls_get_addr
+
+@alias = alias internal i32* @v
+define i32 @f_alias() nounwind {
+entry:
+ %t = load i32* @v
+ %s = add i32 %t, 1
+ ret i32 %s
+}
+
+; CHECK: f_alias:
+; CHECK: leal v@TLSGD
+; CHECK: __tls_get_addr
diff --git a/test/CodeGen/X86/fast-isel-x86-64.ll b/test/CodeGen/X86/fast-isel-x86-64.ll
index c4afc10..6a5a102 100644
--- a/test/CodeGen/X86/fast-isel-x86-64.ll
+++ b/test/CodeGen/X86/fast-isel-x86-64.ll
@@ -259,4 +259,27 @@ define void @test21(double* %p1) {
; CHECK: test21:
; CHECK-NOT: pxor
; CHECK: movsd LCPI
-} \ No newline at end of file
+}
+
+; Check that immediate arguments to a function
+; do not cause massive spilling and are used
+; as immediates just before the call.
+define void @test22() nounwind {
+entry:
+ call void @foo22(i32 0)
+ call void @foo22(i32 1)
+ call void @foo22(i32 2)
+ call void @foo22(i32 3)
+ ret void
+; CHECK: test22:
+; CHECK: movl $0, %edi
+; CHECK: callq _foo22
+; CHECK: movl $1, %edi
+; CHECK: callq _foo22
+; CHECK: movl $2, %edi
+; CHECK: callq _foo22
+; CHECK: movl $3, %edi
+; CHECK: callq _foo22
+}
+
+declare void @foo22(i32)
diff --git a/test/CodeGen/X86/fp-stack-O0-crash.ll b/test/CodeGen/X86/fp-stack-O0-crash.ll
index 9b629c0..ae83a02 100644
--- a/test/CodeGen/X86/fp-stack-O0-crash.ll
+++ b/test/CodeGen/X86/fp-stack-O0-crash.ll
@@ -1,4 +1,4 @@
-; RUN: llc %s -O0 -fast-isel -regalloc=fast -o -
+; RUN: llc %s -O0 -fast-isel -regalloc=fast -mcpu=i386 -o -
; PR4767
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
@@ -28,3 +28,22 @@ if.then: ; preds = %cond.false, %cond.t
if.end: ; preds = %if.then, %cond.false, %cond.true
ret void
}
+
+; PR10575
+; This produces a FP0 = IMPLICIT_DEF instruction.
+define void @__m_rankmerge_MOD_dindexmerge_() nounwind {
+entry:
+ br label %"20"
+
+"20": ; preds = %"23", %entry
+ %0 = phi double [ undef, %entry ], [ %0, %"23" ]
+ %1 = phi double [ 0.000000e+00, %entry ], [ %2, %"23" ]
+ br i1 undef, label %"21", label %"23"
+
+"21": ; preds = %"20"
+ ret void
+
+"23": ; preds = %"20"
+ %2 = select i1 undef, double %0, double %1
+ br label %"20"
+}
diff --git a/test/CodeGen/X86/global-sections.ll b/test/CodeGen/X86/global-sections.ll
index d0a1b4d..194f597 100644
--- a/test/CodeGen/X86/global-sections.ll
+++ b/test/CodeGen/X86/global-sections.ll
@@ -43,7 +43,7 @@
; _Complex long long const G4 = 34;
@G4 = unnamed_addr constant {i64,i64} { i64 34, i64 0 }
-; DARWIN: .section __TEXT,__const
+; DARWIN: .section __TEXT,__literal16,16byte_literals
; DARWIN: _G4:
; DARWIN: .long 34
diff --git a/test/CodeGen/X86/haddsub.ll b/test/CodeGen/X86/haddsub.ll
new file mode 100644
index 0000000..91758ea
--- /dev/null
+++ b/test/CodeGen/X86/haddsub.ll
@@ -0,0 +1,194 @@
+; RUN: llc < %s -march=x86-64 -mattr=+sse3,-avx | FileCheck %s -check-prefix=SSE3
+; RUN: llc < %s -march=x86-64 -mattr=-sse3,+avx | FileCheck %s -check-prefix=AVX
+
+; SSE3: haddpd1:
+; SSE3-NOT: vhaddpd
+; SSE3: haddpd
+; AVX: haddpd1:
+; AVX: vhaddpd
+define <2 x double> @haddpd1(<2 x double> %x, <2 x double> %y) {
+ %a = shufflevector <2 x double> %x, <2 x double> %y, <2 x i32> <i32 0, i32 2>
+ %b = shufflevector <2 x double> %x, <2 x double> %y, <2 x i32> <i32 1, i32 3>
+ %r = fadd <2 x double> %a, %b
+ ret <2 x double> %r
+}
+
+; SSE3: haddpd2:
+; SSE3-NOT: vhaddpd
+; SSE3: haddpd
+; AVX: haddpd2:
+; AVX: vhaddpd
+define <2 x double> @haddpd2(<2 x double> %x, <2 x double> %y) {
+ %a = shufflevector <2 x double> %x, <2 x double> %y, <2 x i32> <i32 1, i32 2>
+ %b = shufflevector <2 x double> %y, <2 x double> %x, <2 x i32> <i32 2, i32 1>
+ %r = fadd <2 x double> %a, %b
+ ret <2 x double> %r
+}
+
+; SSE3: haddpd3:
+; SSE3-NOT: vhaddpd
+; SSE3: haddpd
+; AVX: haddpd3:
+; AVX: vhaddpd
+define <2 x double> @haddpd3(<2 x double> %x) {
+ %a = shufflevector <2 x double> %x, <2 x double> undef, <2 x i32> <i32 0, i32 undef>
+ %b = shufflevector <2 x double> %x, <2 x double> undef, <2 x i32> <i32 1, i32 undef>
+ %r = fadd <2 x double> %a, %b
+ ret <2 x double> %r
+}
+
+; SSE3: haddps1:
+; SSE3-NOT: vhaddps
+; SSE3: haddps
+; AVX: haddps1:
+; AVX: vhaddps
+define <4 x float> @haddps1(<4 x float> %x, <4 x float> %y) {
+ %a = shufflevector <4 x float> %x, <4 x float> %y, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+ %b = shufflevector <4 x float> %x, <4 x float> %y, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+ %r = fadd <4 x float> %a, %b
+ ret <4 x float> %r
+}
+
+; SSE3: haddps2:
+; SSE3-NOT: vhaddps
+; SSE3: haddps
+; AVX: haddps2:
+; AVX: vhaddps
+define <4 x float> @haddps2(<4 x float> %x, <4 x float> %y) {
+ %a = shufflevector <4 x float> %x, <4 x float> %y, <4 x i32> <i32 1, i32 2, i32 5, i32 6>
+ %b = shufflevector <4 x float> %y, <4 x float> %x, <4 x i32> <i32 4, i32 7, i32 0, i32 3>
+ %r = fadd <4 x float> %a, %b
+ ret <4 x float> %r
+}
+
+; SSE3: haddps3:
+; SSE3-NOT: vhaddps
+; SSE3: haddps
+; AVX: haddps3:
+; AVX: vhaddps
+define <4 x float> @haddps3(<4 x float> %x) {
+ %a = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 undef, i32 2, i32 4, i32 6>
+ %b = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 undef, i32 3, i32 5, i32 7>
+ %r = fadd <4 x float> %a, %b
+ ret <4 x float> %r
+}
+
+; SSE3: haddps4:
+; SSE3-NOT: vhaddps
+; SSE3: haddps
+; AVX: haddps4:
+; AVX: vhaddps
+define <4 x float> @haddps4(<4 x float> %x) {
+ %a = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 0, i32 2, i32 undef, i32 undef>
+ %b = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 1, i32 3, i32 undef, i32 undef>
+ %r = fadd <4 x float> %a, %b
+ ret <4 x float> %r
+}
+
+; SSE3: haddps5:
+; SSE3-NOT: vhaddps
+; SSE3: haddps
+; AVX: haddps5:
+; AVX: vhaddps
+define <4 x float> @haddps5(<4 x float> %x) {
+ %a = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 0, i32 3, i32 undef, i32 undef>
+ %b = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 1, i32 2, i32 undef, i32 undef>
+ %r = fadd <4 x float> %a, %b
+ ret <4 x float> %r
+}
+
+; SSE3: haddps6:
+; SSE3-NOT: vhaddps
+; SSE3: haddps
+; AVX: haddps6:
+; AVX: vhaddps
+define <4 x float> @haddps6(<4 x float> %x) {
+ %a = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
+ %b = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
+ %r = fadd <4 x float> %a, %b
+ ret <4 x float> %r
+}
+
+; SSE3: haddps7:
+; SSE3-NOT: vhaddps
+; SSE3: haddps
+; AVX: haddps7:
+; AVX: vhaddps
+define <4 x float> @haddps7(<4 x float> %x) {
+ %a = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 undef, i32 3, i32 undef, i32 undef>
+ %b = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 undef, i32 2, i32 undef, i32 undef>
+ %r = fadd <4 x float> %a, %b
+ ret <4 x float> %r
+}
+
+; SSE3: hsubpd1:
+; SSE3-NOT: vhsubpd
+; SSE3: hsubpd
+; AVX: hsubpd1:
+; AVX: vhsubpd
+define <2 x double> @hsubpd1(<2 x double> %x, <2 x double> %y) {
+ %a = shufflevector <2 x double> %x, <2 x double> %y, <2 x i32> <i32 0, i32 2>
+ %b = shufflevector <2 x double> %x, <2 x double> %y, <2 x i32> <i32 1, i32 3>
+ %r = fsub <2 x double> %a, %b
+ ret <2 x double> %r
+}
+
+; SSE3: hsubpd2:
+; SSE3-NOT: vhsubpd
+; SSE3: hsubpd
+; AVX: hsubpd2:
+; AVX: vhsubpd
+define <2 x double> @hsubpd2(<2 x double> %x) {
+ %a = shufflevector <2 x double> %x, <2 x double> undef, <2 x i32> <i32 0, i32 undef>
+ %b = shufflevector <2 x double> %x, <2 x double> undef, <2 x i32> <i32 1, i32 undef>
+ %r = fsub <2 x double> %a, %b
+ ret <2 x double> %r
+}
+
+; SSE3: hsubps1:
+; SSE3-NOT: vhsubps
+; SSE3: hsubps
+; AVX: hsubps1:
+; AVX: vhsubps
+define <4 x float> @hsubps1(<4 x float> %x, <4 x float> %y) {
+ %a = shufflevector <4 x float> %x, <4 x float> %y, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+ %b = shufflevector <4 x float> %x, <4 x float> %y, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+ %r = fsub <4 x float> %a, %b
+ ret <4 x float> %r
+}
+
+; SSE3: hsubps2:
+; SSE3-NOT: vhsubps
+; SSE3: hsubps
+; AVX: hsubps2:
+; AVX: vhsubps
+define <4 x float> @hsubps2(<4 x float> %x) {
+ %a = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 undef, i32 2, i32 4, i32 6>
+ %b = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 undef, i32 3, i32 5, i32 7>
+ %r = fsub <4 x float> %a, %b
+ ret <4 x float> %r
+}
+
+; SSE3: hsubps3:
+; SSE3-NOT: vhsubps
+; SSE3: hsubps
+; AVX: hsubps3:
+; AVX: vhsubps
+define <4 x float> @hsubps3(<4 x float> %x) {
+ %a = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 0, i32 2, i32 undef, i32 undef>
+ %b = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 1, i32 3, i32 undef, i32 undef>
+ %r = fsub <4 x float> %a, %b
+ ret <4 x float> %r
+}
+
+; SSE3: hsubps4:
+; SSE3-NOT: vhsubps
+; SSE3: hsubps
+; AVX: hsubps4:
+; AVX: vhsubps
+define <4 x float> @hsubps4(<4 x float> %x) {
+ %a = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
+ %b = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
+ %r = fsub <4 x float> %a, %b
+ ret <4 x float> %r
+}
diff --git a/test/CodeGen/X86/hidden-vis.ll b/test/CodeGen/X86/hidden-vis.ll
index a948bdf..fcb74fc 100644
--- a/test/CodeGen/X86/hidden-vis.ll
+++ b/test/CodeGen/X86/hidden-vis.ll
@@ -1,8 +1,11 @@
; RUN: llc < %s -mtriple=i686-pc-linux-gnu | FileCheck %s -check-prefix=LINUX
; RUN: llc < %s -mtriple=i686-apple-darwin8 | FileCheck %s -check-prefix=DARWIN
+; RUN: llc < %s -mtriple=x86_64-w64-mingw32 | FileCheck %s -check-prefix=WINDOWS
+
@a = hidden global i32 0
-@b = external global i32
+@b = external hidden global i32
+@c = global i32* @b
define weak hidden void @t1() nounwind {
; LINUX: .hidden t1
@@ -10,15 +13,19 @@ define weak hidden void @t1() nounwind {
; DARWIN: .private_extern _t1
; DARWIN: t1:
+
+; WINDOWS: t1:
+; WINDOWS-NOT: hidden
ret void
}
define weak void @t2() nounwind {
-; LINUX: t2:
-; LINUX: .hidden a
-
-; DARWIN: t2:
-; DARWIN: .private_extern _a
+; DARWIN: .weak_definition _t2
ret void
}
+; LINUX: .hidden a
+; LINUX: .hidden b
+
+; DARWIN: .private_extern _a
+; DARWIN-NOT: private_extern
diff --git a/test/CodeGen/X86/inline-asm-fpstack.ll b/test/CodeGen/X86/inline-asm-fpstack.ll
index 8e48bbe..c9a1c1c 100644
--- a/test/CodeGen/X86/inline-asm-fpstack.ll
+++ b/test/CodeGen/X86/inline-asm-fpstack.ll
@@ -329,3 +329,14 @@ entry:
%asmresult = extractvalue %complex %0, 0
ret float %asmresult
}
+
+; Pass the same value in two fixed stack slots.
+; CHECK: PR10602
+; CHECK: flds LCPI
+; CHECK: fld %st(0)
+; CHECK: fcomi %st(1), %st(0)
+define i32 @PR10602() nounwind ssp {
+entry:
+ %0 = tail call i32 asm "fcomi $2, $1; pushf; pop $0", "=r,{st},{st(1)},~{dirflag},~{fpsr},~{flags}"(double 2.000000e+00, double 2.000000e+00) nounwind
+ ret i32 %0
+}
diff --git a/test/CodeGen/X86/iv-users-in-other-loops.ll b/test/CodeGen/X86/iv-users-in-other-loops.ll
index 8385a29..8f79fb8 100644
--- a/test/CodeGen/X86/iv-users-in-other-loops.ll
+++ b/test/CodeGen/X86/iv-users-in-other-loops.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -march=x86-64 -o %t
+; RUN: llc < %s -march=x86-64 -enable-lsr-nested -o %t
; RUN: not grep inc %t
; RUN: grep dec %t | count 2
; RUN: grep addq %t | count 12
@@ -11,6 +11,10 @@
; to insert new induction variables. Previously it would create a
; flood of new induction variables.
; Also, the loop reversal should kick in once.
+;
+; In this example, performing LSR on the entire loop nest,
+; as opposed to only the inner loop can further reduce induction variables,
+; and their related instructions and registers.
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
target triple = "x86_64-unknown-linux-gnu"
diff --git a/test/CodeGen/X86/lfence.ll b/test/CodeGen/X86/lfence.ll
index 7a96ca3..1903a1e 100644
--- a/test/CodeGen/X86/lfence.ll
+++ b/test/CodeGen/X86/lfence.ll
@@ -1,8 +1,8 @@
; RUN: llc < %s -march=x86 -mattr=+sse2 | grep lfence
-declare void @llvm.memory.barrier( i1 , i1 , i1 , i1 , i1)
+declare void @llvm.x86.sse2.lfence() nounwind
define void @test() {
- call void @llvm.memory.barrier( i1 true, i1 false, i1 false, i1 false, i1 true)
- ret void
+ call void @llvm.x86.sse2.lfence()
+ ret void
}
diff --git a/test/CodeGen/X86/licm-dominance.ll b/test/CodeGen/X86/licm-dominance.ll
new file mode 100644
index 0000000..8a0958d
--- /dev/null
+++ b/test/CodeGen/X86/licm-dominance.ll
@@ -0,0 +1,36 @@
+; RUN: llc -asm-verbose=false < %s | FileCheck %s
+
+; MachineLICM should check dominance before hoisting instructions.
+; CHECK: jne LBB0_3
+; CHECK-NEXT: xorb %al, %al
+; CHECK-NEXT: testb %al, %al
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.2"
+
+define void @CMSColorWorldCreateParametricData() nounwind uwtable optsize ssp {
+entry:
+ br label %for.body.i
+
+for.body.i:
+ br i1 undef, label %for.inc.i, label %if.then26.i
+
+if.then26.i:
+ br i1 undef, label %if.else.i.i, label %lor.lhs.false.i.i
+
+if.else.i.i:
+ br i1 undef, label %lor.lhs.false.i.i, label %if.then116.i.i
+
+lor.lhs.false.i.i:
+ br i1 undef, label %for.inc.i, label %if.then116.i.i
+
+if.then116.i.i:
+ unreachable
+
+for.inc.i:
+ %cmp17.i = icmp ult i64 undef, undef
+ br i1 %cmp17.i, label %for.body.i, label %if.end28.i
+
+if.end28.i:
+ ret void
+}
diff --git a/test/CodeGen/X86/licm-nested.ll b/test/CodeGen/X86/licm-nested.ll
index b0105ac..c3f991d 100644
--- a/test/CodeGen/X86/licm-nested.ll
+++ b/test/CodeGen/X86/licm-nested.ll
@@ -1,4 +1,4 @@
-; RUN: llc -mtriple=x86_64-apple-darwin -march=x86-64 < %s -o /dev/null -stats -info-output-file - | grep machine-licm | grep 3
+; RUN: llc -mtriple=x86_64-apple-darwin -march=x86-64 < %s -o /dev/null -stats -info-output-file - | grep "hoisted out of loops" | grep 3
; MachineLICM should be able to hoist the symbolic addresses out of
; the inner loops.
diff --git a/test/CodeGen/X86/lock-inst-encoding.ll b/test/CodeGen/X86/lock-inst-encoding.ll
index 2d10fbc..9765fae 100644
--- a/test/CodeGen/X86/lock-inst-encoding.ll
+++ b/test/CodeGen/X86/lock-inst-encoding.ll
@@ -3,19 +3,42 @@
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin10.0.0"
-; CHECK: f0:
-; CHECK: addq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0,
+; CHECK: f1:
+; CHECK: addq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0,0x48,0x01,0x37]
; CHECK: ret
-define void @f0(i64* %a0) nounwind {
- %t0 = and i64 1, 1
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) nounwind
- %1 = call i64 @llvm.atomic.load.add.i64.p0i64(i64* %a0, i64 %t0) nounwind
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) nounwind
+define void @f1(i64* %a, i64 %b) nounwind {
+ %1 = atomicrmw add i64* %a, i64 %b monotonic
ret void
}
-declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
+; CHECK: f2:
+; CHECK: subq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0,0x48,0x29,0x37]
+; CHECK: ret
+define void @f2(i64* %a, i64 %b) nounwind {
+ %1 = atomicrmw sub i64* %a, i64 %b monotonic
+ ret void
+}
-declare i32 @llvm.atomic.load.and.i32.p0i32(i32* nocapture, i32) nounwind
+; CHECK: f3:
+; CHECK: andq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0,0x48,0x21,0x37]
+; CHECK: ret
+define void @f3(i64* %a, i64 %b) nounwind {
+ %1 = atomicrmw and i64* %a, i64 %b monotonic
+ ret void
+}
-declare i64 @llvm.atomic.load.add.i64.p0i64(i64* nocapture, i64) nounwind
+; CHECK: f4:
+; CHECK: orq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0,0x48,0x09,0x37]
+; CHECK: ret
+define void @f4(i64* %a, i64 %b) nounwind {
+ %1 = atomicrmw or i64* %a, i64 %b monotonic
+ ret void
+}
+
+; CHECK: f5:
+; CHECK: xorq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0,0x48,0x31,0x37]
+; CHECK: ret
+define void @f5(i64* %a, i64 %b) nounwind {
+ %1 = atomicrmw xor i64* %a, i64 %b monotonic
+ ret void
+}
diff --git a/test/CodeGen/X86/loop-strength-reduce3.ll b/test/CodeGen/X86/loop-strength-reduce3.ll
index c45a374..d6c265f 100644
--- a/test/CodeGen/X86/loop-strength-reduce3.ll
+++ b/test/CodeGen/X86/loop-strength-reduce3.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -march=x86 | grep cmp | grep 240
-; RUN: llc < %s -march=x86 | grep inc | count 1
+; RUN: llc < %s -march=x86 -enable-lsr-nested | grep cmp | grep 240
+; RUN: llc < %s -march=x86 -enable-lsr-nested | grep inc | count 1
define i32 @foo(i32 %A, i32 %B, i32 %C, i32 %D) nounwind {
entry:
diff --git a/test/CodeGen/X86/lzcnt.ll b/test/CodeGen/X86/lzcnt.ll
new file mode 100644
index 0000000..e5a55ab
--- /dev/null
+++ b/test/CodeGen/X86/lzcnt.ll
@@ -0,0 +1,38 @@
+; RUN: llc < %s -march=x86-64 -mattr=+lzcnt | FileCheck %s
+
+define i32 @t1(i32 %x) nounwind {
+ %tmp = tail call i32 @llvm.ctlz.i32( i32 %x )
+ ret i32 %tmp
+; CHECK: t1:
+; CHECK: lzcntl
+}
+
+declare i32 @llvm.ctlz.i32(i32) nounwind readnone
+
+define i16 @t2(i16 %x) nounwind {
+ %tmp = tail call i16 @llvm.ctlz.i16( i16 %x )
+ ret i16 %tmp
+; CHECK: t2:
+; CHECK: lzcntw
+}
+
+declare i16 @llvm.ctlz.i16(i16) nounwind readnone
+
+define i64 @t3(i64 %x) nounwind {
+ %tmp = tail call i64 @llvm.ctlz.i64( i64 %x )
+ ret i64 %tmp
+; CHECK: t3:
+; CHECK: lzcntq
+}
+
+declare i64 @llvm.ctlz.i64(i64) nounwind readnone
+
+define i8 @t4(i8 %x) nounwind {
+ %tmp = tail call i8 @llvm.ctlz.i8( i8 %x )
+ ret i8 %tmp
+; CHECK: t4:
+; CHECK: lzcntw
+}
+
+declare i8 @llvm.ctlz.i8(i8) nounwind readnone
+
diff --git a/test/CodeGen/X86/membarrier.ll b/test/CodeGen/X86/membarrier.ll
index 42f8ef5..5e569aa 100644
--- a/test/CodeGen/X86/membarrier.ll
+++ b/test/CodeGen/X86/membarrier.ll
@@ -5,11 +5,8 @@ define i32 @t() {
entry:
%i = alloca i32, align 4
store i32 1, i32* %i, align 4
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
- %0 = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %i, i32 1)
- call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
+ fence seq_cst
+ %0 = atomicrmw sub i32* %i, i32 1 monotonic
+ fence seq_cst
ret i32 0
}
-
-declare i32 @llvm.atomic.load.sub.i32.p0i32(i32* nocapture, i32) nounwind
-declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind
diff --git a/test/CodeGen/X86/mfence.ll b/test/CodeGen/X86/mfence.ll
index a1b2283..6056add 100644
--- a/test/CodeGen/X86/mfence.ll
+++ b/test/CodeGen/X86/mfence.ll
@@ -2,19 +2,7 @@
; RUN: llc < %s -march=x86 -mattr=+sse2 | not grep lfence
; RUN: llc < %s -march=x86 -mattr=+sse2 | grep mfence
-
-declare void @llvm.memory.barrier( i1 , i1 , i1 , i1 , i1)
-
define void @test() {
- call void @llvm.memory.barrier( i1 true, i1 true, i1 false, i1 false, i1 true)
- call void @llvm.memory.barrier( i1 true, i1 false, i1 true, i1 false, i1 true)
- call void @llvm.memory.barrier( i1 true, i1 false, i1 false, i1 true, i1 true)
-
- call void @llvm.memory.barrier( i1 true, i1 true, i1 true, i1 false, i1 true)
- call void @llvm.memory.barrier( i1 true, i1 true, i1 false, i1 true, i1 true)
- call void @llvm.memory.barrier( i1 true, i1 false, i1 true, i1 true, i1 true)
-
- call void @llvm.memory.barrier( i1 true, i1 true, i1 true, i1 true , i1 true)
- call void @llvm.memory.barrier( i1 false, i1 false, i1 false, i1 false , i1 true)
- ret void
+ fence seq_cst
+ ret void
}
diff --git a/test/CodeGen/X86/movbe.ll b/test/CodeGen/X86/movbe.ll
new file mode 100644
index 0000000..3d3d8cf
--- /dev/null
+++ b/test/CodeGen/X86/movbe.ll
@@ -0,0 +1,36 @@
+; RUN: llc -mtriple=x86_64-linux -mcpu=atom < %s | FileCheck %s
+
+declare i32 @llvm.bswap.i32(i32) nounwind readnone
+declare i64 @llvm.bswap.i64(i64) nounwind readnone
+
+define void @test1(i32* nocapture %x, i32 %y) nounwind {
+ %bswap = call i32 @llvm.bswap.i32(i32 %y)
+ store i32 %bswap, i32* %x, align 4
+ ret void
+; CHECK: test1:
+; CHECK: movbel %esi, (%rdi)
+}
+
+define i32 @test2(i32* %x) nounwind {
+ %load = load i32* %x, align 4
+ %bswap = call i32 @llvm.bswap.i32(i32 %load)
+ ret i32 %bswap
+; CHECK: test2:
+; CHECK: movbel (%rdi), %eax
+}
+
+define void @test3(i64* %x, i64 %y) nounwind {
+ %bswap = call i64 @llvm.bswap.i64(i64 %y)
+ store i64 %bswap, i64* %x, align 8
+ ret void
+; CHECK: test3:
+; CHECK: movbeq %rsi, (%rdi)
+}
+
+define i64 @test4(i64* %x) nounwind {
+ %load = load i64* %x, align 8
+ %bswap = call i64 @llvm.bswap.i64(i64 %load)
+ ret i64 %bswap
+; CHECK: test4:
+; CHECK: movbeq (%rdi), %rax
+}
diff --git a/test/CodeGen/X86/movgs.ll b/test/CodeGen/X86/movgs.ll
index 97b7fe7..aeb540f 100644
--- a/test/CodeGen/X86/movgs.ll
+++ b/test/CodeGen/X86/movgs.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -march=x86 -mattr=sse41 | FileCheck %s --check-prefix=X32
+; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu -mattr=sse41 | FileCheck %s --check-prefix=X32
; RUN: llc < %s -mtriple=x86_64-linux -mattr=sse41 | FileCheck %s --check-prefix=X64
; RUN: llc < %s -mtriple=x86_64-win32 -mattr=sse41 | FileCheck %s --check-prefix=X64
diff --git a/test/CodeGen/X86/movmsk.ll b/test/CodeGen/X86/movmsk.ll
new file mode 100644
index 0000000..2368548
--- /dev/null
+++ b/test/CodeGen/X86/movmsk.ll
@@ -0,0 +1,110 @@
+; RUN: llc -mcpu=core2 < %s | FileCheck %s
+; ModuleID = '<stdin>'
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.6.6"
+
+%0 = type { double }
+%union.anon = type { float }
+
+define i32 @double_signbit(double %d1) nounwind uwtable readnone ssp {
+entry:
+ %__x.addr.i = alloca double, align 8
+ %__u.i = alloca %0, align 8
+ %0 = bitcast double* %__x.addr.i to i8*
+ %1 = bitcast %0* %__u.i to i8*
+ store double %d1, double* %__x.addr.i, align 8
+ %__f.i = getelementptr inbounds %0* %__u.i, i64 0, i32 0
+ store double %d1, double* %__f.i, align 8
+ %tmp = bitcast double %d1 to i64
+; CHECK-NOT: shr
+; CHECK: movmskpd
+; CHECK-NEXT: and
+ %tmp1 = lshr i64 %tmp, 63
+ %shr.i = trunc i64 %tmp1 to i32
+ ret i32 %shr.i
+}
+
+define i32 @double_add_signbit(double %d1, double %d2) nounwind uwtable readnone ssp {
+entry:
+ %__x.addr.i = alloca double, align 8
+ %__u.i = alloca %0, align 8
+ %add = fadd double %d1, %d2
+ %0 = bitcast double* %__x.addr.i to i8*
+ %1 = bitcast %0* %__u.i to i8*
+ store double %add, double* %__x.addr.i, align 8
+ %__f.i = getelementptr inbounds %0* %__u.i, i64 0, i32 0
+ store double %add, double* %__f.i, align 8
+ %tmp = bitcast double %add to i64
+; CHECK-NOT: shr
+; CHECK: movmskpd
+; CHECK-NEXT: and
+ %tmp1 = lshr i64 %tmp, 63
+ %shr.i = trunc i64 %tmp1 to i32
+ ret i32 %shr.i
+}
+
+define i32 @float_signbit(float %f1) nounwind uwtable readnone ssp {
+entry:
+ %__x.addr.i = alloca float, align 4
+ %__u.i = alloca %union.anon, align 4
+ %0 = bitcast float* %__x.addr.i to i8*
+ %1 = bitcast %union.anon* %__u.i to i8*
+ store float %f1, float* %__x.addr.i, align 4
+ %__f.i = getelementptr inbounds %union.anon* %__u.i, i64 0, i32 0
+ store float %f1, float* %__f.i, align 4
+ %2 = bitcast float %f1 to i32
+; CHECK-NOT: shr
+; CHECK: movmskps
+; CHECK-NEXT: and
+ %shr.i = lshr i32 %2, 31
+ ret i32 %shr.i
+}
+
+define i32 @float_add_signbit(float %f1, float %f2) nounwind uwtable readnone ssp {
+entry:
+ %__x.addr.i = alloca float, align 4
+ %__u.i = alloca %union.anon, align 4
+ %add = fadd float %f1, %f2
+ %0 = bitcast float* %__x.addr.i to i8*
+ %1 = bitcast %union.anon* %__u.i to i8*
+ store float %add, float* %__x.addr.i, align 4
+ %__f.i = getelementptr inbounds %union.anon* %__u.i, i64 0, i32 0
+ store float %add, float* %__f.i, align 4
+ %2 = bitcast float %add to i32
+; CHECK-NOT: shr
+; CHECK: movmskps
+; CHECK-NEXT: and
+ %shr.i = lshr i32 %2, 31
+ ret i32 %shr.i
+}
+
+; rdar://10247336
+; movmskp{s|d} only set low 4/2 bits, high bits are known zero
+
+define i32 @t1(<4 x float> %x, i32* nocapture %indexTable) nounwind uwtable readonly ssp {
+entry:
+; CHECK: t1:
+; CHECK: movmskps
+; CHECK-NOT: movslq
+ %0 = tail call i32 @llvm.x86.sse.movmsk.ps(<4 x float> %x) nounwind
+ %idxprom = sext i32 %0 to i64
+ %arrayidx = getelementptr inbounds i32* %indexTable, i64 %idxprom
+ %1 = load i32* %arrayidx, align 4
+ ret i32 %1
+}
+
+define i32 @t2(<4 x float> %x, i32* nocapture %indexTable) nounwind uwtable readonly ssp {
+entry:
+; CHECK: t2:
+; CHECK: movmskpd
+; CHECK-NOT: movslq
+ %0 = bitcast <4 x float> %x to <2 x double>
+ %1 = tail call i32 @llvm.x86.sse2.movmsk.pd(<2 x double> %0) nounwind
+ %idxprom = sext i32 %1 to i64
+ %arrayidx = getelementptr inbounds i32* %indexTable, i64 %idxprom
+ %2 = load i32* %arrayidx, align 4
+ ret i32 %2
+}
+
+declare i32 @llvm.x86.sse2.movmsk.pd(<2 x double>) nounwind readnone
+declare i32 @llvm.x86.sse.movmsk.ps(<4 x float>) nounwind readnone
diff --git a/test/CodeGen/X86/nofence.ll b/test/CodeGen/X86/nofence.ll
deleted file mode 100644
index 244d2e9..0000000
--- a/test/CodeGen/X86/nofence.ll
+++ /dev/null
@@ -1,27 +0,0 @@
-; RUN: llc < %s -march=x86 -mattr=+sse2 | not grep fence
-
-declare void @llvm.memory.barrier( i1 , i1 , i1 , i1 , i1)
-
-define void @test() {
- call void @llvm.memory.barrier( i1 true, i1 false, i1 false, i1 false, i1 false)
- call void @llvm.memory.barrier( i1 false, i1 true, i1 false, i1 false, i1 false)
- call void @llvm.memory.barrier( i1 false, i1 false, i1 true, i1 false, i1 false)
- call void @llvm.memory.barrier( i1 false, i1 false, i1 false, i1 true, i1 false)
-
- call void @llvm.memory.barrier( i1 true, i1 true, i1 false, i1 false, i1 false)
- call void @llvm.memory.barrier( i1 true, i1 false, i1 true, i1 false, i1 false)
- call void @llvm.memory.barrier( i1 true, i1 false, i1 false, i1 true, i1 false)
- call void @llvm.memory.barrier( i1 false, i1 true, i1 true, i1 false, i1 false)
- call void @llvm.memory.barrier( i1 false, i1 true, i1 false, i1 true, i1 false)
- call void @llvm.memory.barrier( i1 false, i1 false, i1 true, i1 true, i1 false)
-
- call void @llvm.memory.barrier( i1 true, i1 true, i1 true, i1 false, i1 false)
- call void @llvm.memory.barrier( i1 true, i1 true, i1 false, i1 true, i1 false)
- call void @llvm.memory.barrier( i1 true, i1 false, i1 true, i1 true, i1 false)
- call void @llvm.memory.barrier( i1 false, i1 true, i1 true, i1 true, i1 false)
-
-
- call void @llvm.memory.barrier( i1 true, i1 true, i1 true, i1 true , i1 false)
- call void @llvm.memory.barrier( i1 false, i1 false, i1 false, i1 false , i1 false)
- ret void
-}
diff --git a/test/CodeGen/X86/norex-subreg.ll b/test/CodeGen/X86/norex-subreg.ll
new file mode 100644
index 0000000..2c529fd
--- /dev/null
+++ b/test/CodeGen/X86/norex-subreg.ll
@@ -0,0 +1,80 @@
+; RUN: llc -O0 < %s
+; RUN: llc < %s
+target triple = "x86_64-apple-macosx10.7"
+
+; This test case extracts a sub_8bit_hi sub-register:
+;
+; %R8B<def> = COPY %BH, %EBX<imp-use,kill>
+; %ESI<def> = MOVZX32_NOREXrr8 %R8B<kill>
+;
+; The register allocation above is invalid, %BH can only be encoded without an
+; REX prefix, so the destination register must be GR8_NOREX. The code above
+; triggers an assertion in copyPhysReg.
+;
+; <rdar://problem/10248099>
+
+define void @f() nounwind uwtable ssp {
+entry:
+ %0 = load i32* undef, align 4
+ %add = add i32 0, %0
+ %conv1 = trunc i32 %add to i16
+ %bf.value = and i16 %conv1, 255
+ %1 = and i16 %bf.value, 255
+ %2 = shl i16 %1, 8
+ %3 = load i16* undef, align 1
+ %4 = and i16 %3, 255
+ %5 = or i16 %4, %2
+ store i16 %5, i16* undef, align 1
+ %6 = load i16* undef, align 1
+ %7 = lshr i16 %6, 8
+ %bf.clear2 = and i16 %7, 255
+ %conv3 = zext i16 %bf.clear2 to i32
+ %rem = srem i32 %conv3, 15
+ %conv4 = trunc i32 %rem to i16
+ %bf.value5 = and i16 %conv4, 255
+ %8 = and i16 %bf.value5, 255
+ %9 = shl i16 %8, 8
+ %10 = or i16 undef, %9
+ store i16 %10, i16* undef, align 1
+ ret void
+}
+
+; This test case extracts a sub_8bit_hi sub-register:
+;
+; %vreg2<def> = COPY %vreg1:sub_8bit_hi; GR8:%vreg2 GR64_ABCD:%vreg1
+; TEST8ri %vreg2, 1, %EFLAGS<imp-def>; GR8:%vreg2
+;
+; %vreg2 must be constrained to GR8_NOREX, or the COPY could become impossible.
+;
+; PR11088
+
+define fastcc i32 @g(i64 %FB) nounwind uwtable readnone align 2 {
+entry:
+ %and32 = and i64 %FB, 256
+ %cmp33 = icmp eq i64 %and32, 0
+ %Features.6.or35 = select i1 %cmp33, i32 0, i32 undef
+ %cmp38 = icmp eq i64 undef, 0
+ %or40 = or i32 %Features.6.or35, 4
+ %Features.8 = select i1 %cmp38, i32 %Features.6.or35, i32 %or40
+ %and42 = and i64 %FB, 32
+ %or45 = or i32 %Features.8, 2
+ %cmp43 = icmp eq i64 %and42, 0
+ %Features.8.or45 = select i1 %cmp43, i32 %Features.8, i32 %or45
+ %and47 = and i64 %FB, 8192
+ %cmp48 = icmp eq i64 %and47, 0
+ %or50 = or i32 %Features.8.or45, 32
+ %Features.10 = select i1 %cmp48, i32 %Features.8.or45, i32 %or50
+ %or55 = or i32 %Features.10, 64
+ %Features.10.or55 = select i1 undef, i32 %Features.10, i32 %or55
+ %and57 = lshr i64 %FB, 2
+ %and57.tr = trunc i64 %and57 to i32
+ %or60 = and i32 %and57.tr, 1
+ %Features.12 = or i32 %Features.10.or55, %or60
+ %and62 = and i64 %FB, 128
+ %or65 = or i32 %Features.12, 8
+ %cmp63 = icmp eq i64 %and62, 0
+ %Features.12.or65 = select i1 %cmp63, i32 %Features.12, i32 %or65
+ %Features.14 = select i1 undef, i32 undef, i32 %Features.12.or65
+ %Features.16 = select i1 undef, i32 undef, i32 %Features.14
+ ret i32 %Features.16
+}
diff --git a/test/CodeGen/X86/opt-shuff-tstore.ll b/test/CodeGen/X86/opt-shuff-tstore.ll
new file mode 100644
index 0000000..fc24913
--- /dev/null
+++ b/test/CodeGen/X86/opt-shuff-tstore.ll
@@ -0,0 +1,39 @@
+; RUN: llc -mcpu=corei7 -mtriple=x86_64-linux < %s -promote-elements -mattr=+sse2,+sse41 | FileCheck %s
+
+; CHECK: func_4_8
+; A single memory write
+; CHECK: movd
+; CHECK-NEXT: ret
+define void @func_4_8(<4 x i8> %param, <4 x i8>* %p) {
+ %r = add <4 x i8> %param, <i8 1, i8 2, i8 3, i8 4>
+ store <4 x i8> %r, <4 x i8>* %p
+ ret void
+}
+
+; CHECK: func_4_16
+; CHECK: movq
+; CHECK-NEXT: ret
+define void @func_4_16(<4 x i16> %param, <4 x i16>* %p) {
+ %r = add <4 x i16> %param, <i16 1, i16 2, i16 3, i16 4>
+ store <4 x i16> %r, <4 x i16>* %p
+ ret void
+}
+
+; CHECK: func_8_8
+; CHECK: movq
+; CHECK-NEXT: ret
+define void @func_8_8(<8 x i8> %param, <8 x i8>* %p) {
+ %r = add <8 x i8> %param, <i8 1, i8 2, i8 3, i8 4, i8 1, i8 2, i8 3, i8 4>
+ store <8 x i8> %r, <8 x i8>* %p
+ ret void
+}
+
+; CHECK: func_2_32
+; CHECK: movq
+; CHECK-NEXT: ret
+define void @func_2_32(<2 x i32> %param, <2 x i32>* %p) {
+ %r = add <2 x i32> %param, <i32 1, i32 2>
+ store <2 x i32> %r, <2 x i32>* %p
+ ret void
+}
+
diff --git a/test/CodeGen/X86/or-address.ll b/test/CodeGen/X86/or-address.ll
index b3fc627..f866e41 100644
--- a/test/CodeGen/X86/or-address.ll
+++ b/test/CodeGen/X86/or-address.ll
@@ -47,10 +47,10 @@ return: ; preds = %bb
}
; CHECK: test1:
-; CHECK: movl %{{.*}}, (%rdi,%rcx,4)
-; CHECK: movl %{{.*}}, 8(%rdi,%rcx,4)
-; CHECK: movl %{{.*}}, 4(%rdi,%rcx,4)
-; CHECK: movl %{{.*}}, 12(%rdi,%rcx,4)
+; CHECK: movl %{{.*}}, (%[[RDI:...]],%[[RCX:...]],4)
+; CHECK: movl %{{.*}}, 8(%[[RDI]],%[[RCX]],4)
+; CHECK: movl %{{.*}}, 4(%[[RDI]],%[[RCX]],4)
+; CHECK: movl %{{.*}}, 12(%[[RDI]],%[[RCX]],4)
define void @test1(i32* nocapture %array, i32 %r0, i8 signext %k, i8 signext %i0) nounwind {
bb.nph:
diff --git a/test/CodeGen/X86/palignr.ll b/test/CodeGen/X86/palignr.ll
index 3812c72..6875fb3 100644
--- a/test/CodeGen/X86/palignr.ll
+++ b/test/CodeGen/X86/palignr.ll
@@ -1,7 +1,8 @@
-; RUN: llc < %s -march=x86 -mcpu=core2 | FileCheck %s
+; RUN: llc < %s -march=x86 -mcpu=core2 -mattr=+ssse3 | FileCheck %s
; RUN: llc < %s -march=x86 -mcpu=yonah | FileCheck --check-prefix=YONAH %s
define <4 x i32> @test1(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK: test1:
; CHECK: pshufd
; CHECK-YONAH: pshufd
%C = shufflevector <4 x i32> %A, <4 x i32> undef, <4 x i32> < i32 1, i32 2, i32 3, i32 0 >
@@ -9,6 +10,7 @@ define <4 x i32> @test1(<4 x i32> %A, <4 x i32> %B) nounwind {
}
define <4 x i32> @test2(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK: test2:
; CHECK: palignr
; CHECK-YONAH: shufps
%C = shufflevector <4 x i32> %A, <4 x i32> %B, <4 x i32> < i32 1, i32 2, i32 3, i32 4 >
@@ -16,43 +18,56 @@ define <4 x i32> @test2(<4 x i32> %A, <4 x i32> %B) nounwind {
}
define <4 x i32> @test3(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK: test3:
; CHECK: palignr
%C = shufflevector <4 x i32> %A, <4 x i32> %B, <4 x i32> < i32 1, i32 2, i32 undef, i32 4 >
ret <4 x i32> %C
}
define <4 x i32> @test4(<4 x i32> %A, <4 x i32> %B) nounwind {
+; CHECK: test4:
; CHECK: palignr
%C = shufflevector <4 x i32> %A, <4 x i32> %B, <4 x i32> < i32 6, i32 7, i32 undef, i32 1 >
ret <4 x i32> %C
}
define <4 x float> @test5(<4 x float> %A, <4 x float> %B) nounwind {
+; CHECK: test5:
; CHECK: palignr
%C = shufflevector <4 x float> %A, <4 x float> %B, <4 x i32> < i32 6, i32 7, i32 undef, i32 1 >
ret <4 x float> %C
}
define <8 x i16> @test6(<8 x i16> %A, <8 x i16> %B) nounwind {
+; CHECK: test6:
; CHECK: palignr
%C = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> < i32 3, i32 4, i32 undef, i32 6, i32 7, i32 8, i32 9, i32 10 >
ret <8 x i16> %C
}
define <8 x i16> @test7(<8 x i16> %A, <8 x i16> %B) nounwind {
+; CHECK: test7:
; CHECK: palignr
%C = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> < i32 undef, i32 6, i32 undef, i32 8, i32 9, i32 10, i32 11, i32 12 >
ret <8 x i16> %C
}
-define <8 x i16> @test8(<8 x i16> %A, <8 x i16> %B) nounwind {
-; CHECK: palignr
- %C = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> < i32 undef, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 0 >
- ret <8 x i16> %C
-}
-
-define <16 x i8> @test9(<16 x i8> %A, <16 x i8> %B) nounwind {
+define <16 x i8> @test8(<16 x i8> %A, <16 x i8> %B) nounwind {
+; CHECK: test8:
; CHECK: palignr
%C = shufflevector <16 x i8> %A, <16 x i8> %B, <16 x i32> < i32 5, i32 6, i32 7, i32 undef, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20 >
ret <16 x i8> %C
}
+
+; Check that we don't do unary (circular on single operand) palignr incorrectly.
+; (It is possible, but before this testcase was committed, it was being done
+; incorrectly. In particular, one of the operands of the palignr node
+; was an UNDEF.)
+define <8 x i16> @test9(<8 x i16> %A, <8 x i16> %B) nounwind {
+; CHECK: test9:
+; CHECK-NOT: palignr
+; CHECK: pshufb
+ %C = shufflevector <8 x i16> %B, <8 x i16> %A, <8 x i32> < i32 undef, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 0 >
+ ret <8 x i16> %C
+}
+
diff --git a/test/CodeGen/X86/personality.ll b/test/CodeGen/X86/personality.ll
index d3d8e3f..51be7bc 100644
--- a/test/CodeGen/X86/personality.ll
+++ b/test/CodeGen/X86/personality.ll
@@ -8,6 +8,8 @@ entry:
to label %return unwind label %unwind
unwind: ; preds = %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
br i1 false, label %eh_then, label %cleanup20
eh_then: ; preds = %unwind
@@ -15,7 +17,9 @@ eh_then: ; preds = %unwind
to label %return unwind label %unwind10
unwind10: ; preds = %eh_then
- %upgraded.eh_select13 = tail call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* null, i8* bitcast (void ()* @__gxx_personality_v0 to i8*), i32 1)
+ %exn10 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ %upgraded.eh_select13 = extractvalue { i8*, i32 } %exn10, 1
%upgraded.eh_select131 = sext i32 %upgraded.eh_select13 to i64
%tmp18 = icmp slt i64 %upgraded.eh_select131, 0
br i1 %tmp18, label %filter, label %cleanup20
@@ -33,11 +37,9 @@ return: ; preds = %eh_then, %entry
declare void @_Z1gv()
-declare void @__gxx_personality_v0()
-
declare void @__cxa_end_catch()
-declare i32 @llvm.eh.selector(i8*, i8*, ...) nounwind
+declare i32 @__gxx_personality_v0(...)
; X64: zPLR
; X64: .byte 155
diff --git a/test/CodeGen/X86/pr10420.ll b/test/CodeGen/X86/pr10420.ll
new file mode 100644
index 0000000..3993f24
--- /dev/null
+++ b/test/CodeGen/X86/pr10420.ll
@@ -0,0 +1,21 @@
+; RUN: llc < %s -mtriple=x86_64-apple-macosx -disable-cfi | FileCheck %s
+
+define private void @foo() {
+ ret void
+}
+
+define void @bar() {
+ call void @foo()
+ ret void;
+}
+
+; CHECK: _bar: ## @bar
+; CHECK-NEXT: Ltmp2:
+
+; CHECK: Ltmp12:
+; CHECK-NEXT: Ltmp13 = L_foo-Ltmp12 ## FDE initial location
+; CHECK-NEXT: .quad Ltmp13
+
+; CHECK: Ltmp19:
+; CHECK-NEXT: Ltmp20 = Ltmp2-Ltmp19 ## FDE initial location
+; CHECK-NEXT: .quad Ltmp20
diff --git a/test/CodeGen/X86/pr3495.ll b/test/CodeGen/X86/pr3495.ll
index c612a6e..7efd35b 100644
--- a/test/CodeGen/X86/pr3495.ll
+++ b/test/CodeGen/X86/pr3495.ll
@@ -1,7 +1,9 @@
-; RUN: llc < %s -march=x86 -stats -regalloc=linearscan |& grep {Number of loads added} | grep 2
-; RUN: llc < %s -march=x86 -stats -regalloc=linearscan |& grep {Number of register spills} | grep 1
-; RUN: llc < %s -march=x86 -stats -regalloc=linearscan |& grep {Number of machine instrs printed} | grep 34
+; RUN: llc < %s -march=x86 -stats -regalloc=linearscan -enable-lsr-nested |& grep {Number of loads added} | grep 2
+; RUN: llc < %s -march=x86 -stats -regalloc=linearscan -enable-lsr-nested |& grep {Number of spill slots allocated} | grep 1
+; RUN: llc < %s -march=x86 -stats -regalloc=linearscan -enable-lsr-nested |& grep {Number of machine instrs printed} | grep 34
; PR3495
+;
+; Note: this should not spill at all with either good LSR or good regalloc.
target triple = "i386-pc-linux-gnu"
@x = external global [8 x i32], align 32 ; <[8 x i32]*> [#uses=1]
diff --git a/test/CodeGen/X86/pr3522.ll b/test/CodeGen/X86/pr3522.ll
index da16237..1122530 100644
--- a/test/CodeGen/X86/pr3522.ll
+++ b/test/CodeGen/X86/pr3522.ll
@@ -21,6 +21,8 @@ return: ; preds = %lpad
ret void
lpad: ; preds = %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
%2 = icmp eq i8 %1, 90 ; <i1> [#uses=1]
br i1 %2, label %return, label %bb22
}
@@ -28,3 +30,5 @@ lpad: ; preds = %entry
declare void @__gnat_rcheck_12(i8*, i32) noreturn
declare i32 @report__ident_int(i32)
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/ptr-rotate.ll b/test/CodeGen/X86/ptr-rotate.ll
new file mode 100644
index 0000000..6debd16
--- /dev/null
+++ b/test/CodeGen/X86/ptr-rotate.ll
@@ -0,0 +1,11 @@
+; RUN: llc -mtriple=i386-apple-darwin -o - < %s | FileCheck %s
+
+define i32 @func(i8* %A) nounwind readnone {
+entry:
+ %tmp = ptrtoint i8* %A to i32
+ %shr = lshr i32 %tmp, 5
+ %shl = shl i32 %tmp, 27
+ %or = or i32 %shr, %shl
+; CHECK: roll $27
+ ret i32 %or
+}
diff --git a/test/CodeGen/X86/scev-interchange.ll b/test/CodeGen/X86/scev-interchange.ll
index 81c919f..71a4d21 100644
--- a/test/CodeGen/X86/scev-interchange.ll
+++ b/test/CodeGen/X86/scev-interchange.ll
@@ -149,6 +149,8 @@ bb71.i: ; preds = %bb.i.i.i262.i, %bb66.i
to label %_ZNSt12_Vector_baseIjSaIjEEC2EmRKS0_.exit.i.i.i.i.i unwind label %lpad.i.i.i.i.i.i ; <i8*> [#uses=0]
lpad.i.i.i.i.i.i: ; preds = %bb71.i
+ %exn.i.i.i.i.i.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
_ZNSt12_Vector_baseIjSaIjEEC2EmRKS0_.exit.i.i.i.i.i: ; preds = %bb71.i
@@ -162,6 +164,8 @@ _ZNSt6vectorIjSaIjEED1Ev.exit.i.i: ; preds = %_ZNSt12_Vector_baseIjSaIjEEC2EmRK
to label %_ZNSt12_Vector_baseIjSaIjEEC2EmRKS0_.exit.i.i.i12.i.i unwind label %lpad.i.i.i.i8.i.i ; <i8*> [#uses=0]
lpad.i.i.i.i8.i.i: ; preds = %_ZNSt6vectorIjSaIjEED1Ev.exit.i.i
+ %exn.i.i.i.i8.i.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
invoke void @_Unwind_Resume(i8* undef)
to label %.noexc.i9.i.i unwind label %lpad.i19.i.i
@@ -179,6 +183,8 @@ bb50.i.i.i: ; preds = %bb.i.i.i.i.i.i.i.i.i.i, %_ZNSt12_Vector_baseIjSaIjEEC2Em
to label %bb83.i unwind label %lpad188.i
lpad.i19.i.i: ; preds = %lpad.i.i.i.i8.i.i
+ %exn.i19.i.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
bb83.i: ; preds = %bb50.i.i.i
@@ -192,6 +198,8 @@ invcont84.i: ; preds = %bb83.i
to label %_ZNSt12_Vector_baseIjSaIjEEC2EmRKS0_.exit.i.i.i.i unwind label %lpad.i.i.i.i315.i ; <i8*> [#uses=0]
lpad.i.i.i.i315.i: ; preds = %invcont84.i
+ %exn.i.i.i.i315.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
invoke void @_Unwind_Resume(i8* undef)
to label %.noexc.i316.i unwind label %lpad.i352.i
@@ -209,6 +217,8 @@ bb50.i.i: ; preds = %bb.i.i.i.i.i.i.i.i320.i, %_ZNSt12_Vector_baseIjSaIjEEC2EmR
to label %invcont86.i unwind label %lpad200.i
lpad.i352.i: ; preds = %lpad.i.i.i.i315.i
+ %exn.i352.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
invcont86.i: ; preds = %bb50.i.i
@@ -232,6 +242,8 @@ invcont101.i: ; preds = %bb100.i
to label %_ZN10FullMatrixIdEC1Ejj.exit.i.i unwind label %lpad.i.i.i.i.i
lpad.i.i.i.i.i: ; preds = %invcont101.i
+ %exn.i.i.i.i.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
_ZN10FullMatrixIdEC1Ejj.exit.i.i: ; preds = %invcont101.i
@@ -239,6 +251,8 @@ _ZN10FullMatrixIdEC1Ejj.exit.i.i: ; preds = %invcont101.i
to label %_ZN10FullMatrixIdEC1Ejj.exit28.i.i unwind label %lpad.i.i.i27.i.i
lpad.i.i.i27.i.i: ; preds = %_ZN10FullMatrixIdEC1Ejj.exit.i.i
+ %exn.i.i.i27.i.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
invoke void @_Unwind_Resume(i8* undef)
to label %.noexc.i.i unwind label %lpad.i.i
@@ -258,6 +272,8 @@ bb.i.i.i297.i.i: ; preds = %bb58.i.i
unreachable
lpad.i.i: ; preds = %lpad.i.i.i27.i.i
+ %exn.i.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
bb.i191.i: ; preds = %.noexc232.i, %bb58.i.i
@@ -296,43 +312,71 @@ bb29.loopexit.i.i: ; preds = %.noexc232.i
br label %bb9.i216.i
lpad.i: ; preds = %entry
+ %exn.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad120.i: ; preds = %invcont.i
+ %exn120.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad124.i: ; preds = %invcont1.i
+ %exn124.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad128.i: ; preds = %invcont3.i
+ %exn128.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad132.i: ; preds = %invcont4.i
+ %exn132.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad136.i: ; preds = %invcont6.i
+ %exn136.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad140.i: ; preds = %bb21.i, %invcont7.i
+ %exn140.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad144.i: ; preds = %bb10.i168.i, %invcont9.i
+ %exn144.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad148.i: ; preds = %invcont10.i
+ %exn148.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad188.i: ; preds = %bb50.i.i.i
+ %exn188.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad196.i: ; preds = %bb.i191.i
+ %exn196 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad200.i: ; preds = %bb50.i.i
+ %exn200.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad204.i: ; preds = %invcont86.i
+ %exn204.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
declare fastcc void @_ZN11Polynomials19LagrangeEquidistant23generate_complete_basisEj(%"struct.std::vector<Polynomials::Polynomial<double>,std::allocator<Polynomials::Polynomial<double> > >"* noalias nocapture sret, i32)
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/segmented-stacks.ll b/test/CodeGen/X86/segmented-stacks.ll
new file mode 100644
index 0000000..ecdb00d
--- /dev/null
+++ b/test/CodeGen/X86/segmented-stacks.ll
@@ -0,0 +1,87 @@
+; RUN: llc < %s -mtriple=i686-linux -segmented-stacks | FileCheck %s -check-prefix=X32
+; RUN: llc < %s -mtriple=x86_64-linux -segmented-stacks | FileCheck %s -check-prefix=X64
+
+; Just to prevent the alloca from being optimized away
+declare void @dummy_use(i32*, i32)
+
+define i32 @test_basic(i32 %l) {
+ %mem = alloca i32, i32 %l
+ call void @dummy_use (i32* %mem, i32 %l)
+ %terminate = icmp eq i32 %l, 0
+ br i1 %terminate, label %true, label %false
+
+true:
+ ret i32 0
+
+false:
+ %newlen = sub i32 %l, 1
+ %retvalue = call i32 @test_basic(i32 %newlen)
+ ret i32 %retvalue
+
+; X32: test_basic:
+
+; X32: leal -12(%esp), %ecx
+; X32-NEXT: cmpl %gs:48, %ecx
+
+; X32: subl $8, %esp
+; X32-NEXT: pushl $4
+; X32-NEXT: pushl $12
+; X32-NEXT: calll __morestack
+; X32-NEXT: addl $8, %esp
+; X32-NEXT: ret
+
+; X32: movl %eax, %esp
+
+; X32: subl $12, %esp
+; X32-NEXT: pushl %ecx
+; X32-NEXT: calll __morestack_allocate_stack_space
+; X32-NEXT: addl $16, %esp
+
+; X64: test_basic:
+
+; X64: leaq -24(%rsp), %r11
+; X64-NEXT: cmpq %fs:112, %r11
+
+; X64: movabsq $24, %r10
+; X64-NEXT: movabsq $0, %r11
+; X64-NEXT: callq __morestack
+; X64-NEXT: ret
+
+; X64: movq %rsp, %rax
+; X64-NEXT: subq %rcx, %rax
+; X64-NEXT: cmpq %rax, %fs:112
+
+; X64: movq %rax, %rsp
+
+; X64: movq %rcx, %rdi
+; X64-NEXT: callq __morestack_allocate_stack_space
+
+}
+
+define i32 @test_nested(i32 * nest %closure, i32 %other) {
+ %addend = load i32 * %closure
+ %result = add i32 %other, %addend
+ ret i32 %result
+
+; X32: leal (%esp), %edx
+; X32-NEXT: cmpl %gs:48, %edx
+
+
+; X32: subl $8, %esp
+; X32-NEXT: pushl $4
+; X32-NEXT: pushl $0
+; X32-NEXT: calll __morestack
+; X32-NEXT: addl $8, %esp
+; X32-NEXT: ret
+
+; X64: leaq (%rsp), %r11
+; X64-NEXT: cmpq %fs:112, %r11
+
+; X64: movq %r10, %rax
+; X64-NEXT: movabsq $0, %r10
+; X64-NEXT: movabsq $0, %r11
+; X64-NEXT: callq __morestack
+; X64-NEXT: ret
+; X64: movq %rax, %r10
+
+}
diff --git a/test/CodeGen/X86/sfence.ll b/test/CodeGen/X86/sfence.ll
index 4782879..0c28407 100644
--- a/test/CodeGen/X86/sfence.ll
+++ b/test/CodeGen/X86/sfence.ll
@@ -1,8 +1,8 @@
; RUN: llc < %s -march=x86 -mattr=+sse2 | grep sfence
-declare void @llvm.memory.barrier( i1 , i1 , i1 , i1 , i1)
+declare void @llvm.x86.sse.sfence() nounwind
define void @test() {
- call void @llvm.memory.barrier( i1 false, i1 false, i1 false, i1 true, i1 true)
- ret void
+ call void @llvm.x86.sse.sfence()
+ ret void
}
diff --git a/test/CodeGen/X86/sink-hoist.ll b/test/CodeGen/X86/sink-hoist.ll
index 31f41ee..e13a817 100644
--- a/test/CodeGen/X86/sink-hoist.ll
+++ b/test/CodeGen/X86/sink-hoist.ll
@@ -102,6 +102,7 @@ entry:
br label %bb60
bb: ; preds = %bb60
+ %i.0 = phi i32 [ 0, %bb60 ] ; <i32> [#uses=2]
%0 = bitcast float* %x_addr.0 to <4 x float>* ; <<4 x float>*> [#uses=1]
%1 = load <4 x float>* %0, align 16 ; <<4 x float>> [#uses=4]
%tmp20 = bitcast <4 x float> %1 to <4 x i32> ; <<4 x i32>> [#uses=1]
@@ -129,15 +130,14 @@ bb: ; preds = %bb60
%5 = getelementptr float* %x_addr.0, i64 4 ; <float*> [#uses=1]
%6 = getelementptr float* %y_addr.0, i64 4 ; <float*> [#uses=1]
%7 = add i32 %i.0, 4 ; <i32> [#uses=1]
- br label %bb60
+ %8 = load i32* %n, align 4 ; <i32> [#uses=1]
+ %9 = icmp sgt i32 %8, %7 ; <i1> [#uses=1]
+ br i1 %9, label %bb60, label %return
bb60: ; preds = %bb, %entry
- %i.0 = phi i32 [ 0, %entry ], [ %7, %bb ] ; <i32> [#uses=2]
%x_addr.0 = phi float* [ %x, %entry ], [ %5, %bb ] ; <float*> [#uses=2]
%y_addr.0 = phi float* [ %y, %entry ], [ %6, %bb ] ; <float*> [#uses=2]
- %8 = load i32* %n, align 4 ; <i32> [#uses=1]
- %9 = icmp sgt i32 %8, %i.0 ; <i1> [#uses=1]
- br i1 %9, label %bb, label %return
+ br label %bb
return: ; preds = %bb60
ret void
diff --git a/test/CodeGen/X86/split-eh-lpad-edges.ll b/test/CodeGen/X86/split-eh-lpad-edges.ll
index fd40a7f..756a3dd 100644
--- a/test/CodeGen/X86/split-eh-lpad-edges.ll
+++ b/test/CodeGen/X86/split-eh-lpad-edges.ll
@@ -28,7 +28,11 @@ invcont27: ; preds = %invcont26
lpad: ; preds = %invcont26, %invcont, %entry
%pool.1 = phi %struct.NSAutoreleasePool* [ null, %entry ], [ null, %invcont ], [ null, %invcont26 ] ; <%struct.NSAutoreleasePool*> [#uses=0]
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
declare %struct.NSObject* @objc_msgSend(%struct.NSObject*, %struct.objc_selector*, ...)
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/CodeGen/X86/split-vector-bitcast.ll b/test/CodeGen/X86/split-vector-bitcast.ll
new file mode 100644
index 0000000..fae15cf
--- /dev/null
+++ b/test/CodeGen/X86/split-vector-bitcast.ll
@@ -0,0 +1,12 @@
+; RUN: llc < %s -march=x86 -mattr=-sse2,+sse | grep addps
+
+; PR10497 + another isel issue with sse2 disabled
+; (This is primarily checking that this construct doesn't crash.)
+define void @a(<2 x float>* %a, <2 x i32>* %b) {
+ %cc = load <2 x float>* %a
+ %c = fadd <2 x float> %cc, %cc
+ %dd = bitcast <2 x float> %c to <2 x i32>
+ %d = add <2 x i32> %dd, %dd
+ store <2 x i32> %d, <2 x i32>* %b
+ ret void
+}
diff --git a/test/CodeGen/X86/sse-minmax.ll b/test/CodeGen/X86/sse-minmax.ll
index ff0af25..af1a73b 100644
--- a/test/CodeGen/X86/sse-minmax.ll
+++ b/test/CodeGen/X86/sse-minmax.ll
@@ -1,6 +1,6 @@
-; RUN: llc < %s -march=x86-64 -asm-verbose=false -join-physregs | FileCheck %s
-; RUN: llc < %s -march=x86-64 -asm-verbose=false -join-physregs -enable-unsafe-fp-math -enable-no-nans-fp-math | FileCheck -check-prefix=UNSAFE %s
-; RUN: llc < %s -march=x86-64 -asm-verbose=false -join-physregs -enable-no-nans-fp-math | FileCheck -check-prefix=FINITE %s
+; RUN: llc < %s -march=x86-64 -asm-verbose=false -join-physregs -promote-elements | FileCheck %s
+; RUN: llc < %s -march=x86-64 -asm-verbose=false -join-physregs -enable-unsafe-fp-math -enable-no-nans-fp-math -promote-elements | FileCheck -check-prefix=UNSAFE %s
+; RUN: llc < %s -march=x86-64 -asm-verbose=false -join-physregs -enable-no-nans-fp-math -promote-elements | FileCheck -check-prefix=FINITE %s
; Some of these patterns can be matched as SSE min or max. Some of
; then can be matched provided that the operands are swapped.
@@ -933,3 +933,35 @@ entry:
%x_addr.0 = select i1 %0, double 3.000000e+03, double %x ; <double> [#uses=1]
ret double %x_addr.0
}
+
+; UNSAFE: maxpd:
+; UNSAFE: maxpd
+define <2 x double> @maxpd(<2 x double> %x, <2 x double> %y) {
+ %max_is_x = fcmp oge <2 x double> %x, %y
+ %max = select <2 x i1> %max_is_x, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %max
+}
+
+; UNSAFE: minpd:
+; UNSAFE: minpd
+define <2 x double> @minpd(<2 x double> %x, <2 x double> %y) {
+ %min_is_x = fcmp ole <2 x double> %x, %y
+ %min = select <2 x i1> %min_is_x, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %min
+}
+
+; UNSAFE: maxps:
+; UNSAFE: maxps
+define <4 x float> @maxps(<4 x float> %x, <4 x float> %y) {
+ %max_is_x = fcmp oge <4 x float> %x, %y
+ %max = select <4 x i1> %max_is_x, <4 x float> %x, <4 x float> %y
+ ret <4 x float> %max
+}
+
+; UNSAFE: minps:
+; UNSAFE: minps
+define <4 x float> @minps(<4 x float> %x, <4 x float> %y) {
+ %min_is_x = fcmp ole <4 x float> %x, %y
+ %min = select <4 x i1> %min_is_x, <4 x float> %x, <4 x float> %y
+ ret <4 x float> %min
+}
diff --git a/test/CodeGen/X86/sse2-blend.ll b/test/CodeGen/X86/sse2-blend.ll
new file mode 100644
index 0000000..56b099e
--- /dev/null
+++ b/test/CodeGen/X86/sse2-blend.ll
@@ -0,0 +1,55 @@
+; RUN: llc < %s -march=x86 -mcpu=yonah -promote-elements -mattr=+sse2,-sse41 | FileCheck %s
+
+
+; currently (xor v4i32) is defined as illegal, so we scalarize the code.
+
+define void@vsel_float(<4 x float>* %v1, <4 x float>* %v2) {
+ %A = load <4 x float>* %v1
+ %B = load <4 x float>* %v2
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x float> %A, <4 x float> %B
+ store <4 x float > %vsel, <4 x float>* %v1
+ ret void
+}
+
+; currently (xor v4i32) is defined as illegal, so we scalarize the code.
+
+define void@vsel_i32(<4 x i32>* %v1, <4 x i32>* %v2) {
+ %A = load <4 x i32>* %v1
+ %B = load <4 x i32>* %v2
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x i32> %A, <4 x i32> %B
+ store <4 x i32 > %vsel, <4 x i32>* %v1
+ ret void
+}
+
+; CHECK: vsel_i64
+; CHECK: pxor
+; CHECK: pand
+; CHECK: andnps
+; CHECK: orps
+; CHECK: ret
+
+define void@vsel_i64(<4 x i64>* %v1, <4 x i64>* %v2) {
+ %A = load <4 x i64>* %v1
+ %B = load <4 x i64>* %v2
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x i64> %A, <4 x i64> %B
+ store <4 x i64 > %vsel, <4 x i64>* %v1
+ ret void
+}
+
+; CHECK: vsel_double
+; CHECK: pxor
+; CHECK: pand
+; CHECK: andnps
+; CHECK: orps
+; CHECK: ret
+
+
+define void@vsel_double(<4 x double>* %v1, <4 x double>* %v2) {
+ %A = load <4 x double>* %v1
+ %B = load <4 x double>* %v2
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x double> %A, <4 x double> %B
+ store <4 x double > %vsel, <4 x double>* %v1
+ ret void
+}
+
+
diff --git a/test/CodeGen/X86/sse41-blend.ll b/test/CodeGen/X86/sse41-blend.ll
new file mode 100644
index 0000000..78604a0
--- /dev/null
+++ b/test/CodeGen/X86/sse41-blend.ll
@@ -0,0 +1,82 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 -promote-elements -mattr=+sse41 | FileCheck %s
+
+;CHECK: vsel_float
+;CHECK: blendvps
+;CHECK: ret
+define <4 x float> @vsel_float(<4 x float> %v1, <4 x float> %v2) {
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x float> %v1, <4 x float> %v2
+ ret <4 x float> %vsel
+}
+
+
+;CHECK: vsel_4xi8
+;CHECK: blendvps
+;CHECK: ret
+define <4 x i8> @vsel_4xi8(<4 x i8> %v1, <4 x i8> %v2) {
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x i8> %v1, <4 x i8> %v2
+ ret <4 x i8> %vsel
+}
+
+;CHECK: vsel_4xi16
+;CHECK: blendvps
+;CHECK: ret
+define <4 x i16> @vsel_4xi16(<4 x i16> %v1, <4 x i16> %v2) {
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x i16> %v1, <4 x i16> %v2
+ ret <4 x i16> %vsel
+}
+
+
+;CHECK: vsel_i32
+;CHECK: blendvps
+;CHECK: ret
+define <4 x i32> @vsel_i32(<4 x i32> %v1, <4 x i32> %v2) {
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x i32> %v1, <4 x i32> %v2
+ ret <4 x i32> %vsel
+}
+
+
+;CHECK: vsel_double
+;CHECK: blendvpd
+;CHECK: ret
+define <4 x double> @vsel_double(<4 x double> %v1, <4 x double> %v2) {
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x double> %v1, <4 x double> %v2
+ ret <4 x double> %vsel
+}
+
+
+;CHECK: vsel_i64
+;CHECK: blendvpd
+;CHECK: ret
+define <4 x i64> @vsel_i64(<4 x i64> %v1, <4 x i64> %v2) {
+ %vsel = select <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x i64> %v1, <4 x i64> %v2
+ ret <4 x i64> %vsel
+}
+
+
+;CHECK: vsel_i8
+;CHECK: pblendvb
+;CHECK: ret
+define <16 x i8> @vsel_i8(<16 x i8> %v1, <16 x i8> %v2) {
+ %vsel = select <16 x i1> <i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false>, <16 x i8> %v1, <16 x i8> %v2
+ ret <16 x i8> %vsel
+}
+
+;; TEST blend + compares
+; CHECK: A
+define <2 x double> @A(<2 x double> %x, <2 x double> %y) {
+ ; CHECK: cmplepd
+ ; CHECK: blendvpd
+ %max_is_x = fcmp oge <2 x double> %x, %y
+ %max = select <2 x i1> %max_is_x, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %max
+}
+
+; CHECK: B
+define <2 x double> @B(<2 x double> %x, <2 x double> %y) {
+ ; CHECK: cmpnlepd
+ ; CHECK: blendvpd
+ %min_is_x = fcmp ult <2 x double> %x, %y
+ %min = select <2 x i1> %min_is_x, <2 x double> %x, <2 x double> %y
+ ret <2 x double> %min
+}
+
diff --git a/test/CodeGen/X86/sub.ll b/test/CodeGen/X86/sub.ll
new file mode 100644
index 0000000..ee5ea1d
--- /dev/null
+++ b/test/CodeGen/X86/sub.ll
@@ -0,0 +1,11 @@
+; RUN: llc -march=x86 < %s | FileCheck %s
+
+define i32 @test1(i32 %x) {
+ %xor = xor i32 %x, 31
+ %sub = sub i32 32, %xor
+ ret i32 %sub
+; CHECK: test1:
+; CHECK: xorl $-32
+; CHECK-NEXT: addl $33
+; CHECK-NEXT: ret
+}
diff --git a/test/CodeGen/X86/tail-call-got.ll b/test/CodeGen/X86/tail-call-got.ll
new file mode 100644
index 0000000..1d7eb2e
--- /dev/null
+++ b/test/CodeGen/X86/tail-call-got.ll
@@ -0,0 +1,24 @@
+; RUN: llc < %s -relocation-model=pic -mattr=+sse2 | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-unknown-freebsd9.0"
+
+define double @test1(double %x) nounwind readnone {
+; CHECK: test1:
+; CHECK: movl foo@GOT
+; CHECK-NEXT: jmpl
+ %1 = tail call double @foo(double %x) nounwind readnone
+ ret double %1
+}
+
+declare double @foo(double) readnone
+
+define double @test2(double %x) nounwind readnone {
+; CHECK: test2:
+; CHECK: movl sin@GOT
+; CHECK-NEXT: jmpl
+ %1 = tail call double @sin(double %x) nounwind readnone
+ ret double %1
+}
+
+declare double @sin(double) readnone
diff --git a/test/CodeGen/X86/tlv-1.ll b/test/CodeGen/X86/tlv-1.ll
index 5773260..92dac30 100644
--- a/test/CodeGen/X86/tlv-1.ll
+++ b/test/CodeGen/X86/tlv-1.ll
@@ -5,6 +5,7 @@
@c = external thread_local global %struct.A, align 4
define void @main() nounwind ssp {
+; CHECK: main:
entry:
call void @llvm.memset.p0i8.i64(i8* getelementptr inbounds (%struct.A* @c, i32 0, i32 0, i32 0), i8 0, i64 60, i32 1, i1 false)
unreachable
@@ -14,6 +15,22 @@ entry:
; CHECK-NEXT: movq $0, 48(%rax)
}
+; rdar://10291355
+define i32 @test() nounwind readonly ssp {
+entry:
+; CHECK: test:
+; CHECK: movq _a@TLVP(%rip),
+; CHECK: callq *
+; CHECK: movl (%rax), [[REGISTER:%[a-z]+]]
+; CHECK: movq _b@TLVP(%rip),
+; CHECK: callq *
+; CHECK: subl (%rax), [[REGISTER]]
+ %0 = load i32* @a, align 4
+ %1 = load i32* @b, align 4
+ %sub = sub nsw i32 %0, %1
+ ret i32 %sub
+}
+
declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
@a = thread_local global i32 0 ; <i32*> [#uses=0]
diff --git a/test/CodeGen/X86/trunc-ext-ld-st.ll b/test/CodeGen/X86/trunc-ext-ld-st.ll
new file mode 100644
index 0000000..57d6e97
--- /dev/null
+++ b/test/CodeGen/X86/trunc-ext-ld-st.ll
@@ -0,0 +1,82 @@
+; RUN: llc < %s -march=x86-64 -mcpu=corei7 -promote-elements -mattr=+sse41 | FileCheck %s
+
+;CHECK: load_2_i8
+; A single 16-bit load
+;CHECK: movzwl
+;CHECK: pshufb
+;CHECK: paddq
+;CHECK: pshufb
+; A single 16-bit store
+;CHECK: movw
+;CHECK: ret
+
+define void @load_2_i8(<2 x i8>* %A) {
+ %T = load <2 x i8>* %A
+ %G = add <2 x i8> %T, <i8 9, i8 7>
+ store <2 x i8> %G, <2 x i8>* %A
+ ret void
+}
+
+;CHECK: load_2_i16
+; Read 32-bits
+;CHECK: movd
+;CHECK: pshufb
+;CHECK: paddq
+;CHECK: pshufb
+;CHECK: movd
+;CHECK: ret
+define void @load_2_i16(<2 x i16>* %A) {
+ %T = load <2 x i16>* %A
+ %G = add <2 x i16> %T, <i16 9, i16 7>
+ store <2 x i16> %G, <2 x i16>* %A
+ ret void
+}
+
+;CHECK: load_2_i32
+;CHECK: pshufd
+;CHECK: paddq
+;CHECK: pshufd
+;CHECK: ret
+define void @load_2_i32(<2 x i32>* %A) {
+ %T = load <2 x i32>* %A
+ %G = add <2 x i32> %T, <i32 9, i32 7>
+ store <2 x i32> %G, <2 x i32>* %A
+ ret void
+}
+
+;CHECK: load_4_i8
+;CHECK: movd
+;CHECK: pshufb
+;CHECK: paddd
+;CHECK: pshufb
+;CHECK: ret
+define void @load_4_i8(<4 x i8>* %A) {
+ %T = load <4 x i8>* %A
+ %G = add <4 x i8> %T, <i8 1, i8 4, i8 9, i8 7>
+ store <4 x i8> %G, <4 x i8>* %A
+ ret void
+}
+
+;CHECK: load_4_i16
+;CHECK: punpcklwd
+;CHECK: paddd
+;CHECK: pshufb
+;CHECK: ret
+define void @load_4_i16(<4 x i16>* %A) {
+ %T = load <4 x i16>* %A
+ %G = add <4 x i16> %T, <i16 1, i16 4, i16 9, i16 7>
+ store <4 x i16> %G, <4 x i16>* %A
+ ret void
+}
+
+;CHECK: load_8_i8
+;CHECK: punpcklbw
+;CHECK: paddw
+;CHECK: pshufb
+;CHECK: ret
+define void @load_8_i8(<8 x i8>* %A) {
+ %T = load <8 x i8>* %A
+ %G = add <8 x i8> %T, %T
+ store <8 x i8> %G, <8 x i8>* %A
+ ret void
+}
diff --git a/test/CodeGen/X86/twoaddr-sink-terminator.ll b/test/CodeGen/X86/twoaddr-sink-terminator.ll
new file mode 100644
index 0000000..209d474
--- /dev/null
+++ b/test/CodeGen/X86/twoaddr-sink-terminator.ll
@@ -0,0 +1,43 @@
+; RUN: llc < %s -verify-coalescing
+; PR10998
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-unknown-freebsd8.2"
+
+define void @test(i32 %arg1) nounwind align 2 {
+bb11:
+ %tmp13 = and i32 %arg1, 7
+ %tmp14 = add i32 %tmp13, -5
+ switch i32 %tmp13, label %bb18 [
+ i32 0, label %bb21
+ i32 4, label %bb22
+ i32 3, label %bb21
+ i32 2, label %bb19
+ ]
+
+bb18:
+ %tmp202 = call i32 @f() nounwind
+ unreachable
+
+bb19:
+ %tmp20 = call i32 @f() nounwind
+ br label %bb24
+
+bb21:
+ %tmp203 = call i32 @f() nounwind
+ br label %bb24
+
+bb22:
+ %tmp23 = call i32 @f() nounwind
+ br label %bb24
+
+bb24:
+ %tmp15 = icmp ult i32 %tmp14, 2
+ %tmp55 = select i1 %tmp15, i32 45, i32 44
+ %tmp56 = call i32 @f2(i32 %tmp55)
+ unreachable
+}
+
+declare i32 @f()
+
+declare i32 @f2(i32)
diff --git a/test/CodeGen/X86/uint64-to-float.ll b/test/CodeGen/X86/uint64-to-float.ll
index d9f753c..1dbbdcf 100644
--- a/test/CodeGen/X86/uint64-to-float.ll
+++ b/test/CodeGen/X86/uint64-to-float.ll
@@ -6,12 +6,37 @@
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin10.0.0"
-; CHECK: testq %rdi, %rdi
-; CHECK-NEXT: jns LBB0_2
+; FIXME: This test could generate this code:
+;
+; ## BB#0: ## %entry
+; testq %rdi, %rdi
+; jns LBB0_2
+; ## BB#1:
+; movq %rdi, %rax
+; shrq %rax
+; andq $1, %rdi
+; orq %rax, %rdi
+; cvtsi2ssq %rdi, %xmm0
+; addss %xmm0, %xmm0
+; ret
+; LBB0_2: ## %entry
+; cvtsi2ssq %rdi, %xmm0
+; ret
+;
+; The blocks come from lowering:
+;
+; %vreg7<def> = CMOV_FR32 %vreg6<kill>, %vreg5<kill>, 15, %EFLAGS<imp-use>; FR32:%vreg7,%vreg6,%vreg5
+;
+; If the instruction had an EFLAGS<kill> flag, it wouldn't need to mark EFLAGS
+; as live-in on the new blocks, and machine sinking would be able to sink
+; everything below the test.
+
; CHECK: shrq
-; CHECK-NEXT: andq
+; CHECK: andq
; CHECK-NEXT: orq
-; CHECK-NEXT: cvtsi2ss
+; CHECK: testq %rdi, %rdi
+; CHECK-NEXT: jns LBB0_2
+; CHECK: cvtsi2ss
; CHECK: LBB0_2
; CHECK-NEXT: cvtsi2ss
define float @test(i64 %a) {
diff --git a/test/CodeGen/X86/uint_to_fp-2.ll b/test/CodeGen/X86/uint_to_fp-2.ll
index da5105d..7536fb8 100644
--- a/test/CodeGen/X86/uint_to_fp-2.ll
+++ b/test/CodeGen/X86/uint_to_fp-2.ll
@@ -1,8 +1,33 @@
-; RUN: llc < %s -march=x86 -mattr=+sse2 | grep movsd | count 1
-; rdar://6504833
+; RUN: llc < %s -march=x86 -mattr=+sse2 | FileCheck %s
-define float @f(i32 %x) nounwind readnone {
+; rdar://6504833
+define float @test1(i32 %x) nounwind readnone {
+; CHECK: test1
+; CHECK: movd
+; CHECK: orpd
+; CHECK: subsd
+; CHECK: cvtsd2ss
+; CHECK: movss
+; CHECK: flds
+; CHECK: ret
entry:
%0 = uitofp i32 %x to float
ret float %0
}
+
+; PR10802
+define float @test2(<4 x i32> %x) nounwind readnone ssp {
+; CHECK: test2
+; CHECK: xorps [[ZERO:%xmm[0-9]+]]
+; CHECK: movss {{.*}}, [[ZERO]]
+; CHECK: orps
+; CHECK: subsd
+; CHECK: cvtsd2ss
+; CHECK: movss
+; CHECK: flds
+; CHECK: ret
+entry:
+ %vecext = extractelement <4 x i32> %x, i32 0
+ %conv = uitofp i32 %vecext to float
+ ret float %conv
+}
diff --git a/test/CodeGen/X86/v2f32.ll b/test/CodeGen/X86/v2f32.ll
index 6d14099..ba54833 100644
--- a/test/CodeGen/X86/v2f32.ll
+++ b/test/CodeGen/X86/v2f32.ll
@@ -1,6 +1,6 @@
; RUN: llc < %s -mtriple=x86_64-linux -mcpu=penryn -asm-verbose=0 -o - | FileCheck %s -check-prefix=X64
; RUN: llc < %s -mtriple=x86_64-win32 -mcpu=penryn -asm-verbose=0 -o - | FileCheck %s -check-prefix=W64
-; RUN: llc < %s -mcpu=yonah -march=x86 -asm-verbose=0 -o - | FileCheck %s -check-prefix=X32
+; RUN: llc < %s -mcpu=yonah -march=x86 -mtriple=i386-linux-gnu -asm-verbose=0 -o - | FileCheck %s -check-prefix=X32
; PR7518
define void @test1(<2 x float> %Q, float *%P2) nounwind {
diff --git a/test/CodeGen/X86/vec_compare-sse4.ll b/test/CodeGen/X86/vec_compare-sse4.ll
new file mode 100644
index 0000000..b4a4a4c
--- /dev/null
+++ b/test/CodeGen/X86/vec_compare-sse4.ll
@@ -0,0 +1,35 @@
+; RUN: llc < %s -march=x86 -mattr=-sse3,+sse2 | FileCheck %s -check-prefix=SSE2
+; RUN: llc < %s -march=x86 -mattr=-sse42,+sse41 | FileCheck %s -check-prefix=SSE41
+; RUN: llc < %s -march=x86 -mattr=+sse42 | FileCheck %s -check-prefix=SSE42
+
+define <2 x i64> @test1(<2 x i64> %A, <2 x i64> %B) nounwind {
+; SSE42: test1:
+; SSE42: pcmpgtq
+; SSE42: ret
+; SSE41: test1:
+; SSE41-NOT: pcmpgtq
+; SSE41: ret
+; SSE2: test1:
+; SSE2-NOT: pcmpgtq
+; SSE2: ret
+
+ %C = icmp sgt <2 x i64> %A, %B
+ %D = sext <2 x i1> %C to <2 x i64>
+ ret <2 x i64> %D
+}
+
+define <2 x i64> @test2(<2 x i64> %A, <2 x i64> %B) nounwind {
+; SSE42: test2:
+; SSE42: pcmpeqq
+; SSE42: ret
+; SSE41: test2:
+; SSE41: pcmpeqq
+; SSE41: ret
+; SSE2: test2:
+; SSE2-NOT: pcmpeqq
+; SSE2: ret
+
+ %C = icmp eq <2 x i64> %A, %B
+ %D = sext <2 x i1> %C to <2 x i64>
+ ret <2 x i64> %D
+}
diff --git a/test/CodeGen/X86/vec_set-C.ll b/test/CodeGen/X86/vec_set-C.ll
index 7636ac3..133f23b 100644
--- a/test/CodeGen/X86/vec_set-C.ll
+++ b/test/CodeGen/X86/vec_set-C.ll
@@ -1,6 +1,6 @@
-; RUN: llc < %s -march=x86 -mattr=+sse2 | grep movq
-; RUN: llc < %s -march=x86 -mattr=+sse2 | grep mov | count 1
-; RUN: llc < %s -march=x86-64 -mattr=+sse2 | grep movd
+; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu -mattr=+sse2 | grep movq
+; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu -mattr=+sse2 | grep mov | count 1
+; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-linux -mattr=+sse2 | grep movd
define <2 x i64> @t1(i64 %x) nounwind {
%tmp8 = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0
diff --git a/test/CodeGen/X86/vec_shuffle-37.ll b/test/CodeGen/X86/vec_shuffle-37.ll
index 2efdb14..950040a 100644
--- a/test/CodeGen/X86/vec_shuffle-37.ll
+++ b/test/CodeGen/X86/vec_shuffle-37.ll
@@ -5,8 +5,8 @@
define <4 x i32> @t00(<4 x i32>* %a0) nounwind ssp {
entry:
; CHECK: movaps ({{%rdi|%rcx}}), %xmm0
-; CHECK-NEXT: movaps %xmm0, %xmm1
-; CHECK-NEXT: movlps (%rax), %xmm1
+; CHECK: movaps %xmm0, %xmm1
+; CHECK-NEXT: movss %xmm2, %xmm1
; CHECK-NEXT: shufps $36, %xmm1, %xmm0
%0 = load <4 x i32>* undef, align 16
%1 = load <4 x i32>* %a0, align 16
@@ -23,3 +23,23 @@ entry:
store <2 x double> %vecinit94, <2 x double>* undef
ret void
}
+
+define void @t02(<8 x i32>* %source, <2 x i32>* %dest) nounwind noinline {
+entry:
+; CHECK: movaps 32({{%rdi|%rcx}}), %xmm0
+; CHECK-NEXT: movaps 48({{%rdi|%rcx}}), %xmm1
+; CHECK-NEXT: movss %xmm1, %xmm0
+; CHECK-NEXT: movq %xmm0, ({{%rsi|%rdx}})
+ %0 = bitcast <8 x i32>* %source to <4 x i32>*
+ %arrayidx = getelementptr inbounds <4 x i32>* %0, i64 3
+ %tmp2 = load <4 x i32>* %arrayidx, align 16
+ %tmp3 = extractelement <4 x i32> %tmp2, i32 0
+ %tmp5 = insertelement <2 x i32> <i32 undef, i32 0>, i32 %tmp3, i32 0
+ %arrayidx7 = getelementptr inbounds <8 x i32>* %source, i64 1
+ %1 = bitcast <8 x i32>* %arrayidx7 to <4 x i32>*
+ %tmp8 = load <4 x i32>* %1, align 16
+ %tmp9 = extractelement <4 x i32> %tmp8, i32 1
+ %tmp11 = insertelement <2 x i32> %tmp5, i32 %tmp9, i32 1
+ store <2 x i32> %tmp11, <2 x i32>* %dest, align 8
+ ret void
+}
diff --git a/test/CodeGen/X86/vec_shuffle-38.ll b/test/CodeGen/X86/vec_shuffle-38.ll
new file mode 100644
index 0000000..69a2ede
--- /dev/null
+++ b/test/CodeGen/X86/vec_shuffle-38.ll
@@ -0,0 +1,59 @@
+; RUN: llc < %s -march=x86-64 | FileCheck %s
+
+define <2 x double> @ld(<2 x double> %p) nounwind optsize ssp {
+; CHECK: unpcklpd
+ %shuffle = shufflevector <2 x double> %p, <2 x double> undef, <2 x i32> zeroinitializer
+ ret <2 x double> %shuffle
+}
+
+define <2 x double> @hd(<2 x double> %p) nounwind optsize ssp {
+; CHECK: unpckhpd
+ %shuffle = shufflevector <2 x double> %p, <2 x double> undef, <2 x i32> <i32 1, i32 1>
+ ret <2 x double> %shuffle
+}
+
+define <2 x i64> @ldi(<2 x i64> %p) nounwind optsize ssp {
+; CHECK: punpcklqdq
+ %shuffle = shufflevector <2 x i64> %p, <2 x i64> undef, <2 x i32> zeroinitializer
+ ret <2 x i64> %shuffle
+}
+
+define <2 x i64> @hdi(<2 x i64> %p) nounwind optsize ssp {
+; CHECK: punpckhqdq
+ %shuffle = shufflevector <2 x i64> %p, <2 x i64> undef, <2 x i32> <i32 1, i32 1>
+ ret <2 x i64> %shuffle
+}
+
+; rdar://10050549
+%struct.Float2 = type { float, float }
+
+define <4 x float> @loadhpi(%struct.Float2* %vPtr, <4 x float> %vecin1) nounwind readonly ssp {
+entry:
+; CHECK: loadhpi
+; CHECK-NOT: movq
+; CHECK: movhps (
+ %tmp1 = bitcast %struct.Float2* %vPtr to <1 x i64>*
+ %addptr7 = getelementptr inbounds <1 x i64>* %tmp1, i64 0
+ %tmp2 = bitcast <1 x i64>* %addptr7 to float*
+ %tmp3 = load float* %tmp2, align 4
+ %vec = insertelement <4 x float> undef, float %tmp3, i32 0
+ %addptr.i12 = getelementptr inbounds float* %tmp2, i64 1
+ %tmp4 = load float* %addptr.i12, align 4
+ %vecin2 = insertelement <4 x float> %vec, float %tmp4, i32 1
+ %shuffle = shufflevector <4 x float> %vecin1, <4 x float> %vecin2, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ ret <4 x float> %shuffle
+}
+
+; rdar://10119696
+; CHECK: f
+define <4 x float> @f(<4 x float> %x, double* nocapture %y) nounwind uwtable readonly ssp {
+entry:
+ ; CHECK: movsd (%
+ ; CHECK-NEXT: movsd %xmm
+ %u110.i = load double* %y, align 1
+ %tmp8.i = insertelement <2 x double> undef, double %u110.i, i32 0
+ %tmp9.i = bitcast <2 x double> %tmp8.i to <4 x float>
+ %shuffle.i = shufflevector <4 x float> %x, <4 x float> %tmp9.i, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
+ ret <4 x float> %shuffle.i
+}
+
diff --git a/test/CodeGen/X86/widen_shuffle-1.ll b/test/CodeGen/X86/widen_shuffle-1.ll
index 034c42c..8e951b7 100644
--- a/test/CodeGen/X86/widen_shuffle-1.ll
+++ b/test/CodeGen/X86/widen_shuffle-1.ll
@@ -30,6 +30,7 @@ entry:
; opA with opB, the DAG will produce new operations with opA.
define void @shuf3(<4 x float> %tmp10, <4 x float> %vecinit15, <4 x float>* %dst) nounwind {
entry:
+; CHECK: shuf3:
; CHECK: pshufd
%shuffle.i.i.i12 = shufflevector <4 x float> %tmp10, <4 x float> %vecinit15, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
%tmp25.i.i = shufflevector <4 x float> %shuffle.i.i.i12, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
@@ -46,3 +47,10 @@ entry:
ret void
}
+; PR10421: make sure we correctly handle extreme widening with CONCAT_VECTORS
+define <8 x i8> @shuf4(<4 x i8> %a, <4 x i8> %b) nounwind readnone {
+; CHECK: shuf4:
+; CHECK: punpckldq
+ %vshuf = shufflevector <4 x i8> %a, <4 x i8> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ ret <8 x i8> %vshuf
+}
diff --git a/test/CodeGen/XCore/2011-08-01-DynamicAllocBug.ll b/test/CodeGen/XCore/2011-08-01-DynamicAllocBug.ll
new file mode 100644
index 0000000..7d6d7ba
--- /dev/null
+++ b/test/CodeGen/XCore/2011-08-01-DynamicAllocBug.ll
@@ -0,0 +1,20 @@
+; RUN: llc < %s -march=xcore | FileCheck %s
+
+declare void @g()
+declare i8* @llvm.stacksave() nounwind
+declare void @llvm.stackrestore(i8*) nounwind
+
+define void @f(i32** %p, i32 %size) {
+allocas:
+ %0 = call i8* @llvm.stacksave()
+ %a = alloca i32, i32 %size
+ store i32* %a, i32** %p
+ call void @g()
+ call void @llvm.stackrestore(i8* %0)
+ ret void
+}
+; CHECK: f:
+; CHECK: ldaw [[REGISTER:r[0-9]+]], {{r[0-9]+}}[-r1]
+; CHECK: set sp, [[REGISTER]]
+; CHECK extsp 1
+; CHECK bl g
diff --git a/test/CodeGen/XCore/2011-08-01-VarargsBug.ll b/test/CodeGen/XCore/2011-08-01-VarargsBug.ll
new file mode 100644
index 0000000..2076057
--- /dev/null
+++ b/test/CodeGen/XCore/2011-08-01-VarargsBug.ll
@@ -0,0 +1,17 @@
+; RUN: llc < %s -march=xcore | FileCheck %s
+define void @_Z1fz(...) {
+entry:
+; CHECK: _Z1fz:
+; CHECK: extsp 3
+; CHECK: stw r[[REG:[0-3]{1,1}]]
+; CHECK: , sp{{\[}}[[REG]]{{\]}}
+; CHECK: stw r[[REG:[0-3]{1,1}]]
+; CHECK: , sp{{\[}}[[REG]]{{\]}}
+; CHECK: stw r[[REG:[0-3]{1,1}]]
+; CHECK: , sp{{\[}}[[REG]]{{\]}}
+; CHECK: stw r[[REG:[0-3]{1,1}]]
+; CHECK: , sp{{\[}}[[REG]]{{\]}}
+; CHECK: ldaw sp, sp[3]
+; CHECK: retsp 0
+ ret void
+}
diff --git a/test/CodeGen/XCore/licm-ldwcp.ll b/test/CodeGen/XCore/licm-ldwcp.ll
new file mode 100644
index 0000000..4884f70
--- /dev/null
+++ b/test/CodeGen/XCore/licm-ldwcp.ll
@@ -0,0 +1,18 @@
+; RUN: llc < %s -march=xcore -asm-verbose=0 | FileCheck %s
+
+; MachineLICM should hoist the LDWCP out of the loop.
+
+; CHECK: f:
+; CHECK-NEXT: ldw [[REG:r[0-9]+]], cp[.LCPI0_0]
+; CHECK-NEXT: .LBB0_1:
+; CHECK-NEXT: stw [[REG]], r0[0]
+; CHECK-NEXT: bu .LBB0_1
+
+define void @f(i32* nocapture %p) noreturn nounwind {
+entry:
+ br label %bb
+
+bb: ; preds = %bb, %entry
+ volatile store i32 525509670, i32* %p, align 4
+ br label %bb
+}
diff --git a/test/CodeGen/XCore/misc-intrinsics.ll b/test/CodeGen/XCore/misc-intrinsics.ll
index f504a2e..6d39d77 100644
--- a/test/CodeGen/XCore/misc-intrinsics.ll
+++ b/test/CodeGen/XCore/misc-intrinsics.ll
@@ -4,6 +4,10 @@
declare i32 @llvm.xcore.bitrev(i32)
declare i32 @llvm.xcore.crc32(i32, i32, i32)
declare %0 @llvm.xcore.crc8(i32, i32, i32)
+declare i32 @llvm.xcore.zext(i32, i32)
+declare i32 @llvm.xcore.sext(i32, i32)
+declare i32 @llvm.xcore.geted()
+declare i32 @llvm.xcore.getet()
define i32 @bitrev(i32 %val) {
; CHECK: bitrev:
@@ -25,3 +29,47 @@ define %0 @crc8(i32 %crc, i32 %data, i32 %poly) {
%result = call %0 @llvm.xcore.crc8(i32 %crc, i32 %data, i32 %poly)
ret %0 %result
}
+
+define i32 @zext(i32 %a, i32 %b) {
+; CHECK: zext:
+; CHECK: zext r0, r1
+ %result = call i32 @llvm.xcore.zext(i32 %a, i32 %b)
+ ret i32 %result
+}
+
+define i32 @zexti(i32 %a) {
+; CHECK: zexti:
+; CHECK: zext r0, 4
+ %result = call i32 @llvm.xcore.zext(i32 %a, i32 4)
+ ret i32 %result
+}
+
+define i32 @sext(i32 %a, i32 %b) {
+; CHECK: sext:
+; CHECK: sext r0, r1
+ %result = call i32 @llvm.xcore.sext(i32 %a, i32 %b)
+ ret i32 %result
+}
+
+define i32 @sexti(i32 %a) {
+; CHECK: sexti:
+; CHECK: sext r0, 4
+ %result = call i32 @llvm.xcore.sext(i32 %a, i32 4)
+ ret i32 %result
+}
+
+define i32 @geted() {
+; CHECK: geted:
+; CHECK: get r11, ed
+; CHECK-NEXT: mov r0, r11
+ %result = call i32 @llvm.xcore.geted()
+ ret i32 %result
+}
+
+define i32 @getet() {
+; CHECK: getet:
+; CHECK: get r11, et
+; CHECK-NEXT: mov r0, r11
+ %result = call i32 @llvm.xcore.getet()
+ ret i32 %result
+}
diff --git a/test/CodeGen/XCore/resources.ll b/test/CodeGen/XCore/resources.ll
index bd0492c..8f00fed 100644
--- a/test/CodeGen/XCore/resources.ll
+++ b/test/CodeGen/XCore/resources.ll
@@ -9,6 +9,8 @@ declare void @llvm.xcore.out.p1i8(i8 addrspace(1)* %r, i32 %value)
declare void @llvm.xcore.outt.p1i8(i8 addrspace(1)* %r, i32 %value)
declare void @llvm.xcore.outct.p1i8(i8 addrspace(1)* %r, i32 %value)
declare void @llvm.xcore.chkct.p1i8(i8 addrspace(1)* %r, i32 %value)
+declare i32 @llvm.xcore.testct.p1i8(i8 addrspace(1)* %r)
+declare i32 @llvm.xcore.testwct.p1i8(i8 addrspace(1)* %r)
declare void @llvm.xcore.setd.p1i8(i8 addrspace(1)* %r, i32 %value)
declare void @llvm.xcore.setc.p1i8(i8 addrspace(1)* %r, i32 %value)
declare i32 @llvm.xcore.inshr.p1i8(i8 addrspace(1)* %r, i32 %value)
@@ -18,10 +20,13 @@ declare i32 @llvm.xcore.getts.p1i8(i8 addrspace(1)* %r)
declare void @llvm.xcore.syncr.p1i8(i8 addrspace(1)* %r)
declare void @llvm.xcore.settw.p1i8(i8 addrspace(1)* %r, i32 %value)
declare void @llvm.xcore.setv.p1i8(i8 addrspace(1)* %r, i8* %p)
+declare void @llvm.xcore.setev.p1i8(i8 addrspace(1)* %r, i8* %p)
declare void @llvm.xcore.eeu.p1i8(i8 addrspace(1)* %r)
declare void @llvm.xcore.setclk.p1i8.p1i8(i8 addrspace(1)* %a, i8 addrspace(1)* %b)
declare void @llvm.xcore.setrdy.p1i8.p1i8(i8 addrspace(1)* %a, i8 addrspace(1)* %b)
declare void @llvm.xcore.setpsc.p1i8(i8 addrspace(1)* %r, i32 %value)
+declare i32 @llvm.xcore.peek.p1i8(i8 addrspace(1)* %r)
+declare i32 @llvm.xcore.endin.p1i8(i8 addrspace(1)* %r)
define i8 addrspace(1)* @getr() {
; CHECK: getr:
@@ -171,6 +176,14 @@ define void @setv(i8 addrspace(1)* %r, i8* %p) {
ret void
}
+define void @setev(i8 addrspace(1)* %r, i8* %p) {
+; CHECK: setev:
+; CHECK: mov r11, r1
+; CHECK-NEXT: setev res[r0], r11
+ call void @llvm.xcore.setev.p1i8(i8 addrspace(1)* %r, i8* %p)
+ ret void
+}
+
define void @eeu(i8 addrspace(1)* %r) {
; CHECK: eeu:
; CHECK: eeu res[r0]
@@ -198,3 +211,31 @@ define void @setpsc(i8 addrspace(1)* %r, i32 %value) {
call void @llvm.xcore.setpsc.p1i8(i8 addrspace(1)* %r, i32 %value)
ret void
}
+
+define i32 @peek(i8 addrspace(1)* %r) {
+; CHECK: peek:
+; CHECK: peek r0, res[r0]
+ %result = call i32 @llvm.xcore.peek.p1i8(i8 addrspace(1)* %r)
+ ret i32 %result
+}
+
+define i32 @endin(i8 addrspace(1)* %r) {
+; CHECK: endin:
+; CHECK: endin r0, res[r0]
+ %result = call i32 @llvm.xcore.endin.p1i8(i8 addrspace(1)* %r)
+ ret i32 %result
+}
+
+define i32 @testct(i8 addrspace(1)* %r) {
+; CHECK: testct:
+; CHECK: testct r0, res[r0]
+ %result = call i32 @llvm.xcore.testct.p1i8(i8 addrspace(1)* %r)
+ ret i32 %result
+}
+
+define i32 @testwct(i8 addrspace(1)* %r) {
+; CHECK: testwct:
+; CHECK: testwct r0, res[r0]
+ %result = call i32 @llvm.xcore.testwct.p1i8(i8 addrspace(1)* %r)
+ ret i32 %result
+}
diff --git a/test/CodeGen/XCore/trampoline.ll b/test/CodeGen/XCore/trampoline.ll
index 4e1aba0..6b42134 100644
--- a/test/CodeGen/XCore/trampoline.ll
+++ b/test/CodeGen/XCore/trampoline.ll
@@ -11,7 +11,8 @@ entry:
%FRAME.0 = alloca %struct.FRAME.f, align 4
%TRAMP.23.sub = getelementptr inbounds [20 x i8]* %TRAMP.23, i32 0, i32 0
%FRAME.02 = bitcast %struct.FRAME.f* %FRAME.0 to i8*
- %tramp = call i8* @llvm.init.trampoline(i8* %TRAMP.23.sub, i8* bitcast (i32 (%struct.FRAME.f*)* @g.1101 to i8*), i8* %FRAME.02)
+ call void @llvm.init.trampoline(i8* %TRAMP.23.sub, i8* bitcast (i32 (%struct.FRAME.f*)* @g.1101 to i8*), i8* %FRAME.02)
+ %tramp = call i8* @llvm.adjust.trampoline(i8* %TRAMP.23.sub)
%0 = getelementptr inbounds %struct.FRAME.f* %FRAME.0, i32 0, i32 1
%1 = bitcast i8* %tramp to i32 ()*
store i32 ()* %1, i32 ()** %0, align 4
@@ -32,6 +33,7 @@ entry:
ret i32 %1
}
-declare i8* @llvm.init.trampoline(i8*, i8*, i8*) nounwind
+declare void @llvm.init.trampoline(i8*, i8*, i8*) nounwind
+declare i8* @llvm.adjust.trampoline(i8*) nounwind
declare void @h(i32 ()*)
diff --git a/test/DebugInfo/2009-01-15-member.ll b/test/DebugInfo/2009-01-15-member.ll
deleted file mode 100644
index a0fb0db..0000000
--- a/test/DebugInfo/2009-01-15-member.ll
+++ /dev/null
@@ -1,30 +0,0 @@
-; RUN: llc %s -o /dev/null
- %llvm.dbg.anchor.type = type { i32, i32 }
- %llvm.dbg.basictype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, i32, i8*, i8* }
- %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8* }
- %llvm.dbg.composite.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, { }*, { }*, i8*, i8* }
- %llvm.dbg.derivedtype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, { }*, i8*, i8* }
- %llvm.dbg.global_variable.type = type { i32, { }*, { }*, i8*, i8*, i8*, { }*, i32, { }*, i1, i1, { }*, i8*, i8* }
- %struct.f = type opaque
- %struct.s = type { %struct.f*, i32 }
-@s2 = common global %struct.s zeroinitializer ; <%struct.s*> [#uses=1]
-@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 17 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1]
-@.str = internal constant [4 x i8] c"t.c\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1]
-@.str1 = internal constant [6 x i8] c"/tmp/\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1]
-@.str2 = internal constant [57 x i8] c"4.2.1 (Based on Apple Inc. build 5628) (LLVM build 2091)\00", section "llvm.metadata" ; <[57 x i8]*> [#uses=1]
-@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { i32 458769, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to { }*), i32 1, i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([6 x i8]* @.str1, i32 0, i32 0), i8* getelementptr ([57 x i8]* @.str2, i32 0, i32 0) }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1]
-@.str3 = internal constant [2 x i8] c"s\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1]
-@.str4 = internal constant [2 x i8] c"f\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1]
-@llvm.dbg.composite5 = internal constant %llvm.dbg.composite.type { i32 458771, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([2 x i8]* @.str4, i32 0, i32 0), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 2, i64 0, i64 0, i64 0, i32 60, { }* null, { }* null, i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([6 x i8]* @.str1, i32 0, i32 0) }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1]
-@llvm.dbg.derivedtype = internal constant %llvm.dbg.derivedtype.type { i32 458767, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* null, { }* null, i32 0, i64 32, i64 32, i64 0, i32 0, { }* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite5 to { }*), i8* null, i8* null }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1]
-@.str6 = internal constant [3 x i8] c"f1\00", section "llvm.metadata" ; <[3 x i8]*> [#uses=1]
-@llvm.dbg.derivedtype7 = internal constant %llvm.dbg.derivedtype.type { i32 458765, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([3 x i8]* @.str6, i32 0, i32 0), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 4, i64 32, i64 32, i64 0, i32 1, { }* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype to { }*), i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([6 x i8]* @.str1, i32 0, i32 0) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1]
-@.str8 = internal constant [4 x i8] c"int\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1]
-@llvm.dbg.basictype = internal constant %llvm.dbg.basictype.type { i32 458788, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([4 x i8]* @.str8, i32 0, i32 0), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 0, i64 32, i64 32, i64 0, i32 0, i32 5, i8* null, i8* null }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1]
-@.str9 = internal constant [2 x i8] c"a\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1]
-@llvm.dbg.derivedtype10 = internal constant %llvm.dbg.derivedtype.type { i32 458765, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([2 x i8]* @.str9, i32 0, i32 0), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 5, i64 32, i64 32, i64 32, i32 1, { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*), i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([6 x i8]* @.str1, i32 0, i32 0) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1]
-@llvm.dbg.array = internal constant [2 x { }*] [ { }* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype7 to { }*), { }* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype10 to { }*) ], section "llvm.metadata" ; <[2 x { }*]*> [#uses=1]
-@llvm.dbg.composite11 = internal constant %llvm.dbg.composite.type { i32 458771, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([2 x i8]* @.str3, i32 0, i32 0), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 3, i64 64, i64 32, i64 0, i32 0, { }* null, { }* bitcast ([2 x { }*]* @llvm.dbg.array to { }*), i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([6 x i8]* @.str1, i32 0, i32 0) }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1]
-@llvm.dbg.global_variables = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 52 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1]
-@.str12 = internal constant [3 x i8] c"s2\00", section "llvm.metadata" ; <[3 x i8]*> [#uses=1]
-@llvm.dbg.global_variable = internal constant %llvm.dbg.global_variable.type { i32 458804, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.global_variables to { }*), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([3 x i8]* @.str12, i32 0, i32 0), i8* getelementptr ([3 x i8]* @.str12, i32 0, i32 0), i8* null, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 6, { }* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite11 to { }*), i1 false, i1 true, { }* bitcast (%struct.s* @s2 to { }*), i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([6 x i8]* @.str1, i32 0, i32 0) }, section "llvm.metadata" ; <%llvm.dbg.global_variable.type*> [#uses=0]
diff --git a/test/DebugInfo/2009-10-08-DebugInfo-NullGlobalVariable.ll b/test/DebugInfo/2009-10-08-DebugInfo-NullGlobalVariable.ll
deleted file mode 100644
index fc28107..0000000
--- a/test/DebugInfo/2009-10-08-DebugInfo-NullGlobalVariable.ll
+++ /dev/null
@@ -1,72 +0,0 @@
-; RUN: llc < %s
-
-%struct.TConstantDictionary = type { %struct.__CFDictionary* }
-%struct.TSharedGlobalSet_AS = type { [52 x i32], [20 x i32], [22 x i32], [8 x i32], [20 x i32], [146 x i32] }
-%struct.__CFDictionary = type opaque
-
-@llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @func to i8*)], section "llvm.metadata" ; <[1 x i8*]*> [#uses=0]
-
-define void @func() ssp {
-entry:
- tail call void @llvm.dbg.func.start(metadata !13)
- tail call void @llvm.dbg.stoppoint(i32 1001, i32 0, metadata !1)
- %0 = tail call %struct.TSharedGlobalSet_AS* @g1() nounwind ; <%struct.TSharedGlobalSet_AS*> [#uses=1]
- %1 = getelementptr inbounds %struct.TSharedGlobalSet_AS* %0, i32 0, i32 4, i32 4 ; <i32*> [#uses=1]
- %2 = bitcast i32* %1 to %struct.TConstantDictionary* ; <%struct.TConstantDictionary*> [#uses=1]
- tail call void @g2(%struct.TConstantDictionary* %2) ssp
- tail call void @llvm.dbg.stoppoint(i32 1002, i32 0, metadata !1)
- %3 = tail call %struct.TSharedGlobalSet_AS* @g1() nounwind ; <%struct.TSharedGlobalSet_AS*> [#uses=1]
- %4 = getelementptr inbounds %struct.TSharedGlobalSet_AS* %3, i32 0, i32 4, i32 3 ; <i32*> [#uses=1]
- %5 = bitcast i32* %4 to %struct.TConstantDictionary* ; <%struct.TConstantDictionary*> [#uses=1]
- tail call void @g4(%struct.TConstantDictionary* %5) ssp
- tail call void @llvm.dbg.stoppoint(i32 1003, i32 0, metadata !1)
- %6 = tail call %struct.TSharedGlobalSet_AS* @g1() nounwind ; <%struct.TSharedGlobalSet_AS*> [#uses=1]
- %7 = getelementptr inbounds %struct.TSharedGlobalSet_AS* %6, i32 0, i32 4, i32 2 ; <i32*> [#uses=1]
- %8 = bitcast i32* %7 to %struct.TConstantDictionary* ; <%struct.TConstantDictionary*> [#uses=1]
- tail call void @g3(%struct.TConstantDictionary* %8) ssp
- tail call void @llvm.dbg.stoppoint(i32 1004, i32 0, metadata !1)
- %9 = tail call %struct.TSharedGlobalSet_AS* @g1() nounwind ; <%struct.TSharedGlobalSet_AS*> [#uses=1]
- %10 = getelementptr inbounds %struct.TSharedGlobalSet_AS* %9, i32 0, i32 4, i32 1 ; <i32*> [#uses=1]
- %11 = bitcast i32* %10 to %struct.TConstantDictionary* ; <%struct.TConstantDictionary*> [#uses=1]
- tail call void @g4(%struct.TConstantDictionary* %11) ssp
- tail call void @llvm.dbg.stoppoint(i32 1005, i32 0, metadata !1)
- tail call void @g5()
- tail call void @llvm.dbg.stoppoint(i32 1006, i32 0, metadata !1)
- tail call void @llvm.dbg.region.end(metadata !13)
- ret void
-}
-
-declare void @llvm.dbg.func.start(metadata) nounwind readnone
-
-declare void @llvm.dbg.stoppoint(i32, i32, metadata) nounwind readnone
-
-declare void @llvm.dbg.region.end(metadata) nounwind readnone
-
-declare %struct.TSharedGlobalSet_AS* @g1() nounwind readonly ssp
-
-declare void @g2(%struct.TConstantDictionary* nocapture) ssp align 2
-
-declare void @g3(%struct.TConstantDictionary* nocapture) ssp align 2
-
-declare void @g4(%struct.TConstantDictionary* nocapture) ssp align 2
-
-declare void @g5()
-
-!llvm.dbg.gv = !{!0, !9, !10, !11, !12}
-
-!0 = metadata !{i32 458804, i32 0, metadata !1, metadata !"_ZZ7UASInitmmmmmmmmmE5C.408", metadata !"C.408", metadata !"_ZZ7UASInitmmmmmmmmmE5C.408", metadata !1, i32 874, metadata !2, i1 false, i1 true, null}; [DW_TAG_variable ]
-!1 = metadata !{i32 458769, i32 0, i32 4, metadata !"func.cp", metadata !"/tmp/func", metadata !"4.2.1 (Based on Apple Inc. build 5653) (LLVM build 2311)", i1 false, i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
-!2 = metadata !{i32 458753, metadata !3, metadata !"", metadata !3, i32 0, i64 16, i64 16, i64 0, i32 0, metadata !4, metadata !7, i32 0}; [DW_TAG_array_type ]
-!3 = metadata !{i32 458769, i32 0, i32 4, metadata !"testcase.ii", metadata !"/tmp/", metadata !"4.2.1 (Based on Apple Inc. build 5653) (LLVM build 2311)", i1 true, i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
-!4 = metadata !{i32 458774, metadata !3, metadata !"UniChar", metadata !5, i32 417, i64 0, i64 0, i64 0, i32 0, metadata !6}; [DW_TAG_typedef ]
-!5 = metadata !{i32 458769, i32 0, i32 4, metadata !"MacTypes.h", metadata !"/System/Library/Frameworks/CoreServices.framework/Headers/../Frameworks/CarbonCore.framework/Headers", metadata !"4.2.1 (Based on Apple Inc. build 5653) (LLVM build 2311)", i1 false, i1 true, metadata !"", i32 0}; [DW_TAG_compile_unit ]
-!6 = metadata !{i32 458788, metadata !3, metadata !"short unsigned int", metadata !3, i32 0, i64 16, i64 16, i64 0, i32 0, i32 7}; [DW_TAG_base_type ]
-!7 = metadata !{metadata !8}
-!8 = metadata !{i32 458785, i64 0, i64 0}; [DW_TAG_subrange_type ]
-!9 = metadata !{i32 458804, i32 0, metadata !1, metadata !"_ZZ7UASInitmmmmmmmmmE5C.409", metadata !"C.409", metadata !"_ZZ7UASInitmmmmmmmmmE5C.409", metadata !1, i32 877, metadata !2, i1 false, i1 true, null}; [DW_TAG_variable ]
-!10 = metadata !{i32 458804, i32 0, metadata !1, metadata !"_ZZ7UASInitmmmmmmmmmE5C.410", metadata !"C.410", metadata !"_ZZ7UASInitmmmmmmmmmE5C.410", metadata !1, i32 880, metadata !2, i1 false, i1 true, null}; [DW_TAG_variable ]
-!11 = metadata !{i32 458804, i32 0, metadata !1, metadata !"_ZZ7UASInitmmmmmmmmmE5C.411", metadata !"C.411", metadata !"_ZZ7UASInitmmmmmmmmmE5C.411", metadata !1, i32 924, metadata !2, i1 false, i1 true, null}; [DW_TAG_variable ]
-!12 = metadata !{i32 458804, i32 0, metadata !1, metadata !"_ZZ7UASInitmmmmmmmmmE5C.412", metadata !"C.412", metadata !"_ZZ7UASInitmmmmmmmmmE5C.412", metadata !1, i32 928, metadata !2, i1 false, i1 true, null}; [DW_TAG_variable ]
-!13 = metadata !{i32 458798, i32 0, metadata !3, metadata !"UASShutdown", metadata !"UASShutdown", metadata !"_Z11UASShutdownv", metadata !1, i32 999, metadata !14, i1 false, i1 true}; [DW_TAG_subprogram ]
-!14 = metadata !{i32 458773, metadata !3, metadata !"", metadata !3, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !15, i32 0}; [DW_TAG_subroutine_type ]
-!15 = metadata !{null}
diff --git a/test/DebugInfo/2009-11-05-DeadGlobalVariable.ll b/test/DebugInfo/2009-11-05-DeadGlobalVariable.ll
index c7838c5..e0371d6 100644
--- a/test/DebugInfo/2009-11-05-DeadGlobalVariable.ll
+++ b/test/DebugInfo/2009-11-05-DeadGlobalVariable.ll
@@ -1,17 +1,28 @@
; RUN: llc %s -o /dev/null
; Here variable bar is optimzied away. Do not trip over while trying to generate debug info.
-define i32 @foo() nounwind readnone optsize ssp {
+
+define i32 @foo() nounwind uwtable readnone ssp {
entry:
- ret i32 42, !dbg !6
+ ret i32 42, !dbg !15
}
-!llvm.dbg.gv = !{!0}
+!llvm.dbg.cu = !{!0}
-!0 = metadata !{i32 458804, i32 0, metadata !1, metadata !"foo.bar", metadata !"foo.bar", metadata !"foo.bar", metadata !2, i32 3, metadata !5, i1 true, i1 true, null}; [DW_TAG_variable ]
-!1 = metadata !{i32 458798, i32 0, metadata !2, metadata !"foo", metadata !"foo", metadata !"foo", metadata !2, i32 2, metadata !3, i1 false, i1 true}; [DW_TAG_subprogram ]
-!2 = metadata !{i32 458769, i32 0, i32 12, metadata !"st.c", metadata !"/private/tmp", metadata !"clang 1.1", i1 true, i1 true, metadata !"", i32 0}; [DW_TAG_compile_unit ]
-!3 = metadata !{i32 458773, metadata !2, metadata !"", null, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !4, i32 0}; [DW_TAG_subroutine_type ]
+!0 = metadata !{i32 720913, i32 0, i32 12, metadata !"fb.c", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 139632)", i1 true, i1 true, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !12} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
!4 = metadata !{metadata !5}
-!5 = metadata !{i32 458788, metadata !2, metadata !"int", metadata !2, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5}; [DW_TAG_base_type ]
-!6 = metadata !{i32 5, i32 1, metadata !1, null}
+!5 = metadata !{i32 720942, i32 0, metadata !6, metadata !"foo", metadata !"foo", metadata !"", metadata !6, i32 1, metadata !7, i1 false, i1 true, i32 0, i32 0, i32 0, i32 0, i1 true, i32 ()* @foo, null, null, metadata !10} ; [ DW_TAG_subprogram ]
+!6 = metadata !{i32 720937, metadata !"fb.c", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 720917, i32 0, metadata !"", i32 0, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!8 = metadata !{metadata !9}
+!9 = metadata !{i32 720932, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!10 = metadata !{metadata !11}
+!11 = metadata !{i32 720932} ; [ DW_TAG_base_type ]
+!12 = metadata !{metadata !13}
+!13 = metadata !{metadata !14}
+!14 = metadata !{i32 720948, i32 0, metadata !5, metadata !"bar", metadata !"bar", metadata !"", metadata !6, i32 2, metadata !9, i32 1, i32 1, null} ; [ DW_TAG_variable ]
+!15 = metadata !{i32 3, i32 3, metadata !16, null}
+!16 = metadata !{i32 720907, metadata !5, i32 1, i32 11, metadata !6, i32 0} ; [ DW_TAG_lexical_block ]
diff --git a/test/DebugInfo/2009-11-06-InvalidDerivedType.ll b/test/DebugInfo/2009-11-06-InvalidDerivedType.ll
deleted file mode 100644
index 73211bb..0000000
--- a/test/DebugInfo/2009-11-06-InvalidDerivedType.ll
+++ /dev/null
@@ -1,13 +0,0 @@
-; RUN: llc %s -o /dev/null
-%struct._t = type { i32 }
-
-@s1 = common global %struct._t zeroinitializer, align 4 ; <%struct._t*> [#uses=0]
-
-!llvm.dbg.gv = !{!0}
-
-!0 = metadata !{i32 458804, i32 0, metadata !1, metadata !"s1", metadata !"s1", metadata !"s1", metadata !1, i32 3, metadata !2, i1 false, i1 true, %struct._t* @s1}; [DW_TAG_variable ]
-!1 = metadata !{i32 458769, i32 0, i32 12, metadata !"t.c", metadata !"/tmp", metadata !"clang 1.1", i1 true, i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
-!2 = metadata !{i32 458771, metadata !1, metadata !"_t", metadata !1, i32 1, i64 32, i64 32, i64 0, i32 0, null, metadata !3, i32 0}; [DW_TAG_structure_type ]
-!3 = metadata !{metadata !4}
-!4 = metadata !{i32 458765, metadata !1, metadata !"j", metadata !1, i32 2, i64 32, i64 32, i64 0, i32 0, metadata !5}; [DW_TAG_member ]
-!5 = metadata !{i32 458790, metadata !1, metadata !"", null, i32 0, i64 0, i64 0, i64 0, i32 0, null}; [DW_TAG_const_type ]
diff --git a/test/DebugInfo/2009-11-06-NamelessGlobalVariable.ll b/test/DebugInfo/2009-11-06-NamelessGlobalVariable.ll
index 739def8..0b81a01 100644
--- a/test/DebugInfo/2009-11-06-NamelessGlobalVariable.ll
+++ b/test/DebugInfo/2009-11-06-NamelessGlobalVariable.ll
@@ -1,8 +1,13 @@
; RUN: llc %s -o /dev/null
-@0 = internal constant i32 1 ; <i32*> [#uses=1]
+@0 = internal constant i32 1
-!llvm.dbg.gv = !{!0}
+!llvm.dbg.cu = !{!0}
-!0 = metadata !{i32 458804, i32 0, metadata !1, metadata !"", metadata !"", metadata !"", metadata !1, i32 378, metadata !2, i1 true, i1 true, i32* @0}; [DW_TAG_variable ]
-!1 = metadata !{i32 458769, i32 0, i32 1, metadata !"cbdsqr.f", metadata !"/home/duncan/LLVM/dragonegg/unsolved/", metadata !"4.5.0 20091030 (experimental)", i1 true, i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
-!2 = metadata !{i32 458788, metadata !1, metadata !"integer(kind=4)", metadata !1, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5}; [DW_TAG_base_type ]
+!0 = metadata !{i32 720913, i32 0, i32 12, metadata !"g.c", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 139632)", i1 true, i1 true, metadata !"", i32 0, metadata !1, metadata !1, metadata !1, metadata !3} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 720948, i32 0, null, metadata !"", metadata !"", metadata !"", metadata !6, i32 2, metadata !7, i32 0, i32 1, i32* @0} ; [ DW_TAG_variable ]
+!6 = metadata !{i32 720937, metadata !"g.c", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 720932, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
diff --git a/test/DebugInfo/2009-11-10-CurrentFn.ll b/test/DebugInfo/2009-11-10-CurrentFn.ll
index 250395c..01db617 100644
--- a/test/DebugInfo/2009-11-10-CurrentFn.ll
+++ b/test/DebugInfo/2009-11-10-CurrentFn.ll
@@ -1,20 +1,32 @@
; RUN: llc < %s -o /dev/null
-declare void @foo()
-
-define void @bar(i32 %i) nounwind ssp {
+define void @bar(i32 %i) nounwind uwtable ssp {
entry:
- tail call void @foo() nounwind, !dbg !0
- ret void, !dbg !6
+ tail call void (...)* @foo() nounwind, !dbg !14
+ ret void, !dbg !16
}
-!0 = metadata !{i32 9, i32 0, metadata !1, null}
-!1 = metadata !{i32 458798, i32 0, metadata !2, metadata !"baz", metadata !"baz", metadata !"baz", metadata !2, i32 8, metadata !3, i1 true, i1 true}; [DW_TAG_subprogram ]
-!2 = metadata !{i32 458769, i32 0, i32 1, metadata !"2007-12-VarArrayDebug.c", metadata !"/Volumes/Data/ddunbar/llvm/test/FrontendC", metadata !"4.2.1 (Based on Apple Inc. build 5653) (LLVM build)", i1 true, i1 true, metadata !"", i32 0}; [DW_TAG_compile_unit ]
-!3 = metadata !{i32 458773, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !4, i32 0}; [DW_TAG_subroutine_type ]
-!4 = metadata !{null, metadata !5}
-!5 = metadata !{i32 458788, metadata !2, metadata !"int", metadata !2, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5}; [DW_TAG_base_type ]
-!6 = metadata !{i32 18, i32 0, metadata !7, null}
-!7 = metadata !{i32 458798, i32 0, metadata !2, metadata !"bar", metadata !"bar", metadata !"bar", metadata !2, i32 16, metadata !8, i1 false, i1 true}; [DW_TAG_subprogram ]
-!8 = metadata !{i32 458773, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !9, i32 0}; [DW_TAG_subroutine_type ]
-!9 = metadata !{null}
+declare void @foo(...)
+
+declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone
+
+!llvm.dbg.cu = !{!0}
+
+!0 = metadata !{i32 720913, i32 0, i32 12, metadata !"cf.c", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 139632)", i1 true, i1 true, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !1} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 720942, i32 0, metadata !6, metadata !"bar", metadata !"bar", metadata !"", metadata !6, i32 3, metadata !7, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, void (i32)* @bar, null, null, metadata !9} ; [ DW_TAG_subprogram ]
+!6 = metadata !{i32 720937, metadata !"cf.c", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 720917, i32 0, metadata !"", i32 0, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!8 = metadata !{null}
+!9 = metadata !{metadata !10}
+!10 = metadata !{metadata !11}
+!11 = metadata !{i32 721153, metadata !5, metadata !"i", metadata !6, i32 16777219, metadata !12, i32 0, i32 0} ; [ DW_TAG_arg_variable ]
+!12 = metadata !{i32 720932, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!13 = metadata !{i32 3, i32 14, metadata !5, null}
+!14 = metadata !{i32 4, i32 3, metadata !15, null}
+!15 = metadata !{i32 720907, metadata !5, i32 3, i32 17, metadata !6, i32 0} ; [ DW_TAG_lexical_block ]
+!16 = metadata !{i32 5, i32 1, metadata !15, null}
+
diff --git a/test/DebugInfo/2009-11-10-ParentScope.ll b/test/DebugInfo/2009-11-10-ParentScope.ll
deleted file mode 100644
index df5155f..0000000
--- a/test/DebugInfo/2009-11-10-ParentScope.ll
+++ /dev/null
@@ -1,26 +0,0 @@
-; RUN: llc < %s -o /dev/null
-%struct.htab = type { i32 (i8*)*, i32 (i8*, i8*)*, void (i8*)*, i8**, i64, i64, i64, i32, i32, i8* (i64, i64)*, void (i8*)*, i8*, i8* (i8*, i64, i64)*, void (i8*, i8*)*, i32, [4 x i8] }
-
-define i8* @htab_find_with_hash(%struct.htab* %htab, i8* %element, i32 %hash) nounwind {
-entry:
- br i1 undef, label %land.lhs.true, label %if.end, !dbg !0
-
-land.lhs.true: ; preds = %entry
- unreachable
-
-if.end: ; preds = %entry
- store i8* undef, i8** undef, !dbg !7
- ret i8* undef, !dbg !10
-}
-
-!0 = metadata !{i32 571, i32 3, metadata !1, null}
-!1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
-!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"htab_find_with_hash", metadata !"htab_find_with_hash", metadata !"htab_find_with_hash", metadata !3, i32 561, metadata !4, i1 false, i1 true}; [DW_TAG_subprogram ]
-!3 = metadata !{i32 458769, i32 0, i32 12, metadata !"hashtab.c", metadata !"/usr/src/gnu/usr.bin/cc/cc_tools/../../../../contrib/gcclibs/libiberty", metadata !"clang 1.1", i1 true, i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
-!4 = metadata !{i32 458773, metadata !3, metadata !"", null, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !5, i32 0}; [DW_TAG_subroutine_type ]
-!5 = metadata !{metadata !6}
-!6 = metadata !{i32 458767, metadata !3, metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, null}; [DW_TAG_pointer_type ]
-!7 = metadata !{i32 583, i32 7, metadata !8, null}
-!8 = metadata !{i32 458763, metadata !9}; [DW_TAG_lexical_block ]
-!9 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ]
-!10 = metadata !{i32 588, i32 1, metadata !2, null}
diff --git a/test/DebugInfo/2010-01-05-DbgScope.ll b/test/DebugInfo/2010-01-05-DbgScope.ll
index 8cf20e3..ad4c8d7 100644
--- a/test/DebugInfo/2010-01-05-DbgScope.ll
+++ b/test/DebugInfo/2010-01-05-DbgScope.ll
@@ -9,7 +9,7 @@ entry:
}
!0 = metadata !{i32 571, i32 3, metadata !1, null}
-!1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
+!1 = metadata !{i32 458763, metadata !2, i32 1, i32 1}; [DW_TAG_lexical_block ]
!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"foo", metadata !"foo", metadata !"foo", metadata !3, i32 561, metadata !4, i1 false, i1 true}; [DW_TAG_subprogram ]
!3 = metadata !{i32 458769, i32 0, i32 12, metadata !"hashtab.c", metadata !"/usr/src/gnu/usr.bin/cc/cc_tools/../../../../contrib/gcclibs/libiberty", metadata !"clang 1.1", i1 true, i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
!4 = metadata !{i32 458773, metadata !3, metadata !"", null, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !5, i32 0}; [DW_TAG_subroutine_type ]
diff --git a/test/DebugInfo/2010-06-29-InlinedFnLocalVar.ll b/test/DebugInfo/2010-06-29-InlinedFnLocalVar.ll
index 1d67cb4..001e938 100644
--- a/test/DebugInfo/2010-06-29-InlinedFnLocalVar.ll
+++ b/test/DebugInfo/2010-06-29-InlinedFnLocalVar.ll
@@ -26,7 +26,7 @@ entry:
!llvm.dbg.lv.foo = !{!9, !10}
!llvm.dbg.gv = !{!16}
-!0 = metadata !{i32 524334, i32 0, metadata !1, metadata !"foo", metadata !"foo", metadata !"", metadata !1, i32 9, metadata !3, i1 true, i1 true, i32 0, i32 0, null, i1 false, i1 true, null} ; [ DW_TAG_subprogram ]
+!0 = metadata !{i32 524334, i32 0, metadata !1, metadata !"foo", metadata !"foo", metadata !"", metadata !1, i32 9, metadata !3, i1 true, i1 true, i32 0, i32 0, null, i1 false, i1 true, null, null, null, metadata !24} ; [ DW_TAG_subprogram ]
!1 = metadata !{i32 524329, metadata !"bar.c", metadata !"/tmp/", metadata !2} ; [ DW_TAG_file_type ]
!2 = metadata !{i32 524305, i32 0, i32 1, metadata !"bar.c", metadata !"/tmp/", metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", i1 true, i1 true, metadata !"", i32 0} ; [ DW_TAG_compile_unit ]
!3 = metadata !{i32 524309, metadata !1, metadata !"", metadata !1, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !4, i32 0, null} ; [ DW_TAG_subroutine_type ]
@@ -50,3 +50,6 @@ entry:
!21 = metadata !{i32 9, i32 0, metadata !11, metadata !17}
!22 = metadata !{i32 11, i32 0, metadata !11, metadata !17}
!23 = metadata !{i32 16, i32 0, metadata !18, null}
+!24 = metadata !{metadata !25}
+!25 = metadata !{metadata !9, metadata !10}
+
diff --git a/test/DebugInfo/2011-09-26-GlobalVarContext.ll b/test/DebugInfo/2011-09-26-GlobalVarContext.ll
new file mode 100644
index 0000000..3e9fa88
--- /dev/null
+++ b/test/DebugInfo/2011-09-26-GlobalVarContext.ll
@@ -0,0 +1,47 @@
+; RUN: llc -asm-verbose %s -o - | FileCheck %s
+
+; ModuleID = 'test.c'
+
+@GLOBAL = common global i32 0, align 4
+
+define i32 @f() nounwind {
+ %LOCAL = alloca i32, align 4
+ call void @llvm.dbg.declare(metadata !{i32* %LOCAL}, metadata !15), !dbg !17
+ %1 = load i32* @GLOBAL, align 4, !dbg !18
+ store i32 %1, i32* %LOCAL, align 4, !dbg !18
+ %2 = load i32* @GLOBAL, align 4, !dbg !19
+ ret i32 %2, !dbg !19
+}
+
+declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
+
+!llvm.dbg.cu = !{!0}
+
+!0 = metadata !{i32 720913, i32 0, i32 12, metadata !"test.c", metadata !"/work/llvm/vanilla/test/DebugInfo", metadata !"clang version 3.0 (trunk)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !12} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 720942, i32 0, metadata !6, metadata !"f", metadata !"f", metadata !"", metadata !6, i32 3, metadata !7, i1 false, i1 true, i32 0, i32 0, i32 0, i32 0, i1 false, i32 ()* @f, null, null, metadata !10} ; [ DW_TAG_subprogram ]
+!6 = metadata !{i32 720937, metadata !"test.c", metadata !"/work/llvm/vanilla/test/DebugInfo", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 720917, i32 0, metadata !"", i32 0, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!8 = metadata !{metadata !9}
+!9 = metadata !{i32 720932, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!10 = metadata !{metadata !11}
+!11 = metadata !{i32 720932} ; [ DW_TAG_base_type ]
+!12 = metadata !{metadata !13}
+!13 = metadata !{metadata !14}
+!14 = metadata !{i32 720948, i32 0, null, metadata !"GLOBAL", metadata !"GLOBAL", metadata !"", metadata !6, i32 1, metadata !9, i32 0, i32 1, i32* @GLOBAL} ; [ DW_TAG_variable ]
+!15 = metadata !{i32 721152, metadata !16, metadata !"LOCAL", metadata !6, i32 4, metadata !9, i32 0, i32 0} ; [ DW_TAG_auto_variable ]
+!16 = metadata !{i32 720907, metadata !5, i32 3, i32 9, metadata !6, i32 0} ; [ DW_TAG_lexical_block ]
+!17 = metadata !{i32 4, i32 9, metadata !16, null}
+!18 = metadata !{i32 4, i32 23, metadata !16, null}
+!19 = metadata !{i32 5, i32 5, metadata !16, null}
+
+; CHECK: .ascii "GLOBAL"
+; CHECK: .byte 1
+; CHECK: .byte 1
+
+; CHECK: .ascii "LOCAL"
+; CHECK: .byte 1
+; CHECK: .byte 4
diff --git a/test/ExecutionEngine/2003-01-04-ArgumentBug.ll b/test/ExecutionEngine/2003-01-04-ArgumentBug.ll
index 4cfd1eb..577226b 100644
--- a/test/ExecutionEngine/2003-01-04-ArgumentBug.ll
+++ b/test/ExecutionEngine/2003-01-04-ArgumentBug.ll
@@ -1,4 +1,5 @@
; RUN: lli %s > /dev/null
+; XFAIL: arm
define i32 @foo(i32 %X, i32 %Y, double %A) {
%cond212 = fcmp une double %A, 1.000000e+00 ; <i1> [#uses=1]
diff --git a/test/ExecutionEngine/2003-01-04-LoopTest.ll b/test/ExecutionEngine/2003-01-04-LoopTest.ll
index 668c8fd..61b0a1b 100644
--- a/test/ExecutionEngine/2003-01-04-LoopTest.ll
+++ b/test/ExecutionEngine/2003-01-04-LoopTest.ll
@@ -1,4 +1,5 @@
; RUN: lli %s > /dev/null
+; XFAIL: arm
define i32 @main() {
call i32 @mylog( i32 4 ) ; <i32>:1 [#uses=0]
diff --git a/test/ExecutionEngine/2003-01-15-AlignmentTest.ll b/test/ExecutionEngine/2003-01-15-AlignmentTest.ll
index 9df21c1..df15037 100644
--- a/test/ExecutionEngine/2003-01-15-AlignmentTest.ll
+++ b/test/ExecutionEngine/2003-01-15-AlignmentTest.ll
@@ -1,4 +1,5 @@
; RUN: lli %s > /dev/null
+; XFAIL: arm
define i32 @bar(i8* %X) {
; pointer should be 4 byte aligned!
diff --git a/test/ExecutionEngine/2003-05-06-LivenessClobber.ll b/test/ExecutionEngine/2003-05-06-LivenessClobber.ll
index e670d11..26429a0 100644
--- a/test/ExecutionEngine/2003-05-06-LivenessClobber.ll
+++ b/test/ExecutionEngine/2003-05-06-LivenessClobber.ll
@@ -1,6 +1,7 @@
; This testcase should return with an exit code of 1.
;
; RUN: not lli %s
+; XFAIL: arm
@test = global i64 0 ; <i64*> [#uses=1]
diff --git a/test/ExecutionEngine/2003-05-07-ArgumentTest.ll b/test/ExecutionEngine/2003-05-07-ArgumentTest.ll
index baf42e5e..566f3ae3 100644
--- a/test/ExecutionEngine/2003-05-07-ArgumentTest.ll
+++ b/test/ExecutionEngine/2003-05-07-ArgumentTest.ll
@@ -1,4 +1,5 @@
; RUN: lli %s test
+; XFAIL: arm
declare i32 @puts(i8*)
diff --git a/test/ExecutionEngine/2003-08-15-AllocaAssertion.ll b/test/ExecutionEngine/2003-08-15-AllocaAssertion.ll
index 5970628..6c2f340 100644
--- a/test/ExecutionEngine/2003-08-15-AllocaAssertion.ll
+++ b/test/ExecutionEngine/2003-08-15-AllocaAssertion.ll
@@ -1,4 +1,5 @@
; RUN: lli %s > /dev/null
+; XFAIL: arm
; This testcase failed to work because two variable sized allocas confused the
; local register allocator.
diff --git a/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll b/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll
index 9c8ec1d..29cbaac 100644
--- a/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll
+++ b/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll
@@ -1,4 +1,5 @@
; RUN: lli %s > /dev/null
+; XFAIL: arm
;
; Regression Test: EnvironmentTest.ll
diff --git a/test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll b/test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll
index 152482d..6711d4d 100644
--- a/test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll
+++ b/test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll
@@ -1,4 +1,5 @@
; RUN: lli %s > /dev/null
+; XFAIL: arm
; This testcase exposes a bug in the local register allocator where it runs out
; of registers (due to too many overlapping live ranges), but then attempts to
diff --git a/test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll b/test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll
index 97e84cd..fe18211 100644
--- a/test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll
+++ b/test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll
@@ -1,4 +1,5 @@
; RUN: lli %s > /dev/null
+; XFAIL: arm
@A = global i32 0 ; <i32*> [#uses=1]
diff --git a/test/ExecutionEngine/hello.ll b/test/ExecutionEngine/hello.ll
index 0b75c10..92c26a6 100644
--- a/test/ExecutionEngine/hello.ll
+++ b/test/ExecutionEngine/hello.ll
@@ -1,4 +1,5 @@
; RUN: lli %s > /dev/null
+; XFAIL: arm
@.LC0 = internal global [12 x i8] c"Hello World\00" ; <[12 x i8]*> [#uses=1]
diff --git a/test/ExecutionEngine/hello2.ll b/test/ExecutionEngine/hello2.ll
index 9f060be..10557ab 100644
--- a/test/ExecutionEngine/hello2.ll
+++ b/test/ExecutionEngine/hello2.ll
@@ -1,4 +1,5 @@
; RUN: lli %s > /dev/null
+; XFAIL: arm
@X = global i32 7 ; <i32*> [#uses=0]
@msg = internal global [13 x i8] c"Hello World\0A\00" ; <[13 x i8]*> [#uses=1]
diff --git a/test/ExecutionEngine/simpletest.ll b/test/ExecutionEngine/simpletest.ll
index 68eb758..797b359 100644
--- a/test/ExecutionEngine/simpletest.ll
+++ b/test/ExecutionEngine/simpletest.ll
@@ -1,4 +1,5 @@
; RUN: lli %s > /dev/null
+; XFAIL: arm
define i32 @bar() {
ret i32 0
diff --git a/test/ExecutionEngine/stubs.ll b/test/ExecutionEngine/stubs.ll
index bd9f69a..2039ab5 100644
--- a/test/ExecutionEngine/stubs.ll
+++ b/test/ExecutionEngine/stubs.ll
@@ -1,4 +1,5 @@
; RUN: lli -disable-lazy-compilation=false %s
+; XFAIL: arm
define i32 @main() nounwind {
entry:
diff --git a/test/ExecutionEngine/test-loadstore.ll b/test/ExecutionEngine/test-loadstore.ll
index 53155e8..7eb57cb 100644
--- a/test/ExecutionEngine/test-loadstore.ll
+++ b/test/ExecutionEngine/test-loadstore.ll
@@ -1,4 +1,5 @@
; RUN: lli %s > /dev/null
+; XFAIL: arm
define void @test(i8* %P, i16* %P.upgrd.1, i32* %P.upgrd.2, i64* %P.upgrd.3) {
%V = load i8* %P ; <i8> [#uses=1]
diff --git a/test/Feature/callingconventions.ll b/test/Feature/callingconventions.ll
index d2e9de4..192f07a 100644
--- a/test/Feature/callingconventions.ll
+++ b/test/Feature/callingconventions.ll
@@ -26,25 +26,30 @@ define coldcc void @bar2() {
}
define cc42 void @bar3() {
- invoke fastcc void @foo( )
- to label %Ok unwind label %U
+ invoke fastcc void @foo( )
+ to label %Ok unwind label %U
-Ok: ; preds = %0
- ret void
+Ok:
+ ret void
-U: ; preds = %0
- unwind
+U:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ resume { i8*, i32 } %exn
}
define void @bar4() {
- call cc42 void @bar( )
- invoke cc42 void @bar3( )
- to label %Ok unwind label %U
+ call cc42 void @bar( )
+ invoke cc42 void @bar3( )
+ to label %Ok unwind label %U
-Ok: ; preds = %0
- ret void
+Ok:
+ ret void
-U: ; preds = %0
- unwind
+U:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ resume { i8*, i32 } %exn
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Feature/calltest.ll b/test/Feature/calltest.ll
index dcdb1a0..e7d8e8d 100644
--- a/test/Feature/calltest.ll
+++ b/test/Feature/calltest.ll
@@ -5,26 +5,30 @@
%FunTy = type i32 (i32)
define void @invoke(%FunTy* %x) {
- %foo = call i32 %x( i32 123 ) ; <i32> [#uses=0]
- %foo2 = tail call i32 %x( i32 123 ) ; <i32> [#uses=0]
- ret void
+ %foo = call i32 %x( i32 123 ) ; <i32> [#uses=0]
+ %foo2 = tail call i32 %x( i32 123 ) ; <i32> [#uses=0]
+ ret void
}
define i32 @main(i32 %argc) {
- %retval = call i32 @test( i32 %argc ) ; <i32> [#uses=2]
- %two = add i32 %retval, %retval ; <i32> [#uses=1]
- %retval2 = invoke i32 @test( i32 %argc )
- to label %Next unwind label %Error ; <i32> [#uses=1]
+ %retval = call i32 @test( i32 %argc ) ; <i32> [#uses=2]
+ %two = add i32 %retval, %retval ; <i32> [#uses=1]
+ %retval2 = invoke i32 @test( i32 %argc )
+ to label %Next unwind label %Error ; <i32> [#uses=1]
-Next: ; preds = %0
- %two2 = add i32 %two, %retval2 ; <i32> [#uses=1]
- call void @invoke( %FunTy* @test )
- ret i32 %two2
+Next:
+ %two2 = add i32 %two, %retval2 ; <i32> [#uses=1]
+ call void @invoke( %FunTy* @test )
+ ret i32 %two2
-Error: ; preds = %0
- ret i32 -1
+Error:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ ret i32 -1
}
define i32 @test(i32 %i0) {
ret i32 %i0
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Feature/exception.ll b/test/Feature/exception.ll
new file mode 100644
index 0000000..6e18a81
--- /dev/null
+++ b/test/Feature/exception.ll
@@ -0,0 +1,27 @@
+; RUN: llvm-as < %s | llvm-dis > %t1.ll
+; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll
+; RUN: diff %t1.ll %t2.ll
+
+@_ZTIc = external constant i8*
+@_ZTId = external constant i8*
+@_ZTIPKc = external constant i8*
+
+define void @_Z3barv() uwtable optsize ssp {
+entry:
+ invoke void @_Z3quxv() optsize
+ to label %try.cont unwind label %lpad
+
+try.cont: ; preds = %entry, %invoke.cont4
+ ret void
+
+lpad: ; preds = %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ catch i8** @_ZTIc
+ filter [2 x i8**] [i8** @_ZTIPKc, i8** @_ZTId]
+ resume { i8*, i32 } %exn
+}
+
+declare void @_Z3quxv() optsize
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/FrontendAda/Support/element_copy.ads b/test/FrontendAda/Support/element_copy.ads
deleted file mode 100644
index 52c6e49..0000000
--- a/test/FrontendAda/Support/element_copy.ads
+++ /dev/null
@@ -1,8 +0,0 @@
-package Element_Copy is
- type SmallInt is range 1 .. 4;
- type SmallStr is array (SmallInt range <>) of Character;
- type VariableSizedField (D : SmallInt := 2) is record
- S : SmallStr (1 .. D) := "Hi";
- end record;
- function F return VariableSizedField;
-end;
diff --git a/test/FrontendAda/Support/fat_fields.ads b/test/FrontendAda/Support/fat_fields.ads
deleted file mode 100644
index d3eab3e..0000000
--- a/test/FrontendAda/Support/fat_fields.ads
+++ /dev/null
@@ -1,6 +0,0 @@
-package Fat_Fields is
- pragma Elaborate_Body;
- type A is array (Positive range <>) of Boolean;
- type A_Ptr is access A;
- P : A_Ptr := null;
-end;
diff --git a/test/FrontendAda/Support/global_constant.ads b/test/FrontendAda/Support/global_constant.ads
deleted file mode 100644
index cef4b11..0000000
--- a/test/FrontendAda/Support/global_constant.ads
+++ /dev/null
@@ -1,4 +0,0 @@
-package Global_Constant is
- pragma Elaborate_Body;
- An_Error : exception;
-end;
diff --git a/test/FrontendAda/Support/non_lvalue.ads b/test/FrontendAda/Support/non_lvalue.ads
deleted file mode 100644
index 7d4eeed..0000000
--- a/test/FrontendAda/Support/non_lvalue.ads
+++ /dev/null
@@ -1,11 +0,0 @@
-package Non_LValue is
- type T (Length : Natural) is record
- A : String (1 .. Length);
- B : String (1 .. Length);
- end record;
- type T_Ptr is access all T;
- type U is record
- X : T_Ptr;
- end record;
- function A (Y : U) return String;
-end;
diff --git a/test/FrontendAda/Support/real_cst.ads b/test/FrontendAda/Support/real_cst.ads
deleted file mode 100644
index 54a34bc..0000000
--- a/test/FrontendAda/Support/real_cst.ads
+++ /dev/null
@@ -1,4 +0,0 @@
-with Ada.Streams;
-package Real_Cst is
- procedure Write (Stream : access Ada.Streams.Root_Stream_Type'Class);
-end;
diff --git a/test/FrontendAda/Support/unc_constructor.ads b/test/FrontendAda/Support/unc_constructor.ads
deleted file mode 100644
index d6f8db5..0000000
--- a/test/FrontendAda/Support/unc_constructor.ads
+++ /dev/null
@@ -1,8 +0,0 @@
-package Unc_Constructor is
- type C is null record;
- type A is array (Positive range <>) of C;
- A0 : constant A;
- procedure P (X : A);
-private
- A0 : aliased constant A := (1 .. 0 => (null record));
-end;
diff --git a/test/FrontendAda/Support/var_offset.ads b/test/FrontendAda/Support/var_offset.ads
deleted file mode 100644
index 55d0eb2..0000000
--- a/test/FrontendAda/Support/var_offset.ads
+++ /dev/null
@@ -1,9 +0,0 @@
-package Var_Offset is
- pragma Elaborate_Body;
- type T (L : Natural) is record
- Var_Len : String (1 .. L);
- Space : Integer;
- Small : Character;
- Bad_Field : Character;
- end record;
-end;
diff --git a/test/FrontendAda/Support/var_size.ads b/test/FrontendAda/Support/var_size.ads
deleted file mode 100644
index 6a570cb..0000000
--- a/test/FrontendAda/Support/var_size.ads
+++ /dev/null
@@ -1,7 +0,0 @@
-package Var_Size is
- type T (Length : Natural) is record
- A : String (1 .. Length);
- B : String (1 .. Length);
- end record;
- function A (X : T) return String;
-end;
diff --git a/test/FrontendAda/array_constructor.adb b/test/FrontendAda/array_constructor.adb
deleted file mode 100644
index 13517c7..0000000
--- a/test/FrontendAda/array_constructor.adb
+++ /dev/null
@@ -1,6 +0,0 @@
--- RUN: %llvmgcc -S %s
-procedure Array_Constructor is
- A : array (Integer range <>) of Boolean := (True, False);
-begin
- null;
-end;
diff --git a/test/FrontendAda/array_range_ref.adb b/test/FrontendAda/array_range_ref.adb
deleted file mode 100644
index 037c5aa..0000000
--- a/test/FrontendAda/array_range_ref.adb
+++ /dev/null
@@ -1,7 +0,0 @@
--- RUN: %llvmgcc -S %s
-procedure Array_Range_Ref is
- A : String (1 .. 3);
- B : String := A (A'RANGE)(1 .. 3);
-begin
- null;
-end;
diff --git a/test/FrontendAda/array_ref.adb b/test/FrontendAda/array_ref.adb
deleted file mode 100644
index 2bf4b79..0000000
--- a/test/FrontendAda/array_ref.adb
+++ /dev/null
@@ -1,11 +0,0 @@
--- RUN: %llvmgcc -S %s
-procedure Array_Ref is
- type A is array (Natural range <>, Natural range <>) of Boolean;
- type A_Access is access A;
- function Get (X : A_Access) return Boolean is
- begin
- return X (0, 0);
- end;
-begin
- null;
-end;
diff --git a/test/FrontendAda/array_size.adb b/test/FrontendAda/array_size.adb
deleted file mode 100644
index c73616c..0000000
--- a/test/FrontendAda/array_size.adb
+++ /dev/null
@@ -1,10 +0,0 @@
--- RUN: %llvmgcc -S %s
-procedure Array_Size is
- subtype S is String (1 .. 2);
- type R is record
- A : S;
- end record;
- X : R;
-begin
- null;
-end;
diff --git a/test/FrontendAda/asm.adb b/test/FrontendAda/asm.adb
deleted file mode 100644
index 844885e..0000000
--- a/test/FrontendAda/asm.adb
+++ /dev/null
@@ -1,6 +0,0 @@
--- RUN: %llvmgcc -S %s
-with System.Machine_Code;
-procedure Asm is
-begin
- System.Machine_Code.Asm ("");
-end;
diff --git a/test/FrontendAda/constant_fold.ads b/test/FrontendAda/constant_fold.ads
deleted file mode 100644
index 6223e7c..0000000
--- a/test/FrontendAda/constant_fold.ads
+++ /dev/null
@@ -1,4 +0,0 @@
--- RUN: %llvmgcc -S -emit-llvm %s -o - | not grep ptrtoint
-package Constant_Fold is
- Error : exception;
-end;
diff --git a/test/FrontendAda/debug_var_size.ads b/test/FrontendAda/debug_var_size.ads
deleted file mode 100644
index e8863cb..0000000
--- a/test/FrontendAda/debug_var_size.ads
+++ /dev/null
@@ -1,8 +0,0 @@
--- RUN: %llvmgcc -S -g %s
-package Debug_Var_Size is
- subtype Length_Type is Positive range 1 .. 64;
- type T (Length : Length_Type := 1) is record
- Varying_Length : String (1 .. Length);
- Fixed_Length : Boolean;
- end record;
-end;
diff --git a/test/FrontendAda/dg.exp b/test/FrontendAda/dg.exp
deleted file mode 100644
index 2307c3f..0000000
--- a/test/FrontendAda/dg.exp
+++ /dev/null
@@ -1,6 +0,0 @@
-load_lib llvm.exp
-
-if [ llvm_gcc_supports ada ] then {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{adb,ads}]]
-}
-
diff --git a/test/FrontendAda/element_copy.adb b/test/FrontendAda/element_copy.adb
deleted file mode 100644
index 29274fa..0000000
--- a/test/FrontendAda/element_copy.adb
+++ /dev/null
@@ -1,8 +0,0 @@
--- RUN: %llvmgcc -S -O2 %s -I%p/Support -o - | grep 105 | count 2
-package body Element_Copy is
- function F return VariableSizedField is
- X : VariableSizedField;
- begin
- return X;
- end;
-end;
diff --git a/test/FrontendAda/emit_var.ads b/test/FrontendAda/emit_var.ads
deleted file mode 100644
index 47e2538..0000000
--- a/test/FrontendAda/emit_var.ads
+++ /dev/null
@@ -1,5 +0,0 @@
--- RUN: %llvmgcc -S %s
-with Ada.Finalization;
-package Emit_Var is
- type Search_Type is new Ada.Finalization.Controlled with null record;
-end;
diff --git a/test/FrontendAda/fat_fields.adb b/test/FrontendAda/fat_fields.adb
deleted file mode 100644
index 443a9b6..0000000
--- a/test/FrontendAda/fat_fields.adb
+++ /dev/null
@@ -1,10 +0,0 @@
--- RUN: %llvmgcc -S %s -I%p/Support
--- RUN: %llvmgcc -S %s -I%p/Support -O2
-package body Fat_Fields is
- procedure Proc is
- begin
- if P = null then
- null;
- end if;
- end;
-end;
diff --git a/test/FrontendAda/field_order.ads b/test/FrontendAda/field_order.ads
deleted file mode 100644
index 9b2b37c..0000000
--- a/test/FrontendAda/field_order.ads
+++ /dev/null
@@ -1,7 +0,0 @@
--- RUN: %llvmgcc -S %s
-package Field_Order is
- type Tagged_Type is abstract tagged null record;
- type With_Discriminant (L : Positive) is new Tagged_Type with record
- S : String (1 .. L);
- end record;
-end;
diff --git a/test/FrontendAda/global_constant.adb b/test/FrontendAda/global_constant.adb
deleted file mode 100644
index 330f97b..0000000
--- a/test/FrontendAda/global_constant.adb
+++ /dev/null
@@ -1,5 +0,0 @@
--- RUN: %llvmgcc -S %s -I%p/Support
-package body Global_Constant is
-begin
- raise An_Error;
-end;
diff --git a/test/FrontendAda/init_size.ads b/test/FrontendAda/init_size.ads
deleted file mode 100644
index f423682..0000000
--- a/test/FrontendAda/init_size.ads
+++ /dev/null
@@ -1,12 +0,0 @@
--- RUN: %llvmgcc -S %s
-package Init_Size is
- type T (B : Boolean := False) is record
- case B is
- when False =>
- I : Integer;
- when True =>
- J : Long_Long_Integer; -- Bigger than I
- end case;
- end record;
- A_T : constant T := (False, 0);
-end;
diff --git a/test/FrontendAda/negative_field_offset.adb b/test/FrontendAda/negative_field_offset.adb
deleted file mode 100644
index ec8184d..0000000
--- a/test/FrontendAda/negative_field_offset.adb
+++ /dev/null
@@ -1,16 +0,0 @@
--- RUN: %llvmgcc -S %s
-with System;
-procedure Negative_Field_Offset (N : Integer) is
- type String_Pointer is access String;
- -- Force use of a thin pointer.
- for String_Pointer'Size use System.Word_Size;
- P : String_Pointer;
-
- procedure Q (P : String_Pointer) is
- begin
- P (1) := 'Z';
- end;
-begin
- P := new String (1 .. N);
- Q (P);
-end;
diff --git a/test/FrontendAda/non_bitfield.ads b/test/FrontendAda/non_bitfield.ads
deleted file mode 100644
index 8a49d46..0000000
--- a/test/FrontendAda/non_bitfield.ads
+++ /dev/null
@@ -1,12 +0,0 @@
--- RUN: %llvmgcc -S %s
-package Non_Bitfield is
- type SP is access String;
- type E is (A, B, C);
- type T (D : E) is record
- case D is
- when A => X : Boolean;
- when B => Y : SP;
- when C => Z : String (1 .. 2);
- end case;
- end record;
-end;
diff --git a/test/FrontendAda/non_lvalue.adb b/test/FrontendAda/non_lvalue.adb
deleted file mode 100644
index 71e7e10..0000000
--- a/test/FrontendAda/non_lvalue.adb
+++ /dev/null
@@ -1,7 +0,0 @@
--- RUN: %llvmgcc -S %s -I%p/Support
-package body Non_LValue is
- function A (Y : U) return String is
- begin
- return Y.X.B;
- end;
-end;
diff --git a/test/FrontendAda/placeholder.adb b/test/FrontendAda/placeholder.adb
deleted file mode 100644
index 8890826..0000000
--- a/test/FrontendAda/placeholder.adb
+++ /dev/null
@@ -1,12 +0,0 @@
--- RUN: %llvmgcc -S %s
-procedure Placeholder is
- subtype Bounded is Integer range 1 .. 5;
- type Vector is array (Bounded range <>) of Integer;
- type Interval (Length : Bounded := 1) is record
- Points : Vector (1 .. Length);
- end record;
- An_Interval : Interval := (Length => 1, Points => (1 => 1));
- generic The_Interval : Interval; package R is end;
- package body R is end;
- package S is new R (An_Interval);
-begin null; end;
diff --git a/test/FrontendAda/real_cst.adb b/test/FrontendAda/real_cst.adb
deleted file mode 100644
index 75143710..0000000
--- a/test/FrontendAda/real_cst.adb
+++ /dev/null
@@ -1,8 +0,0 @@
--- RUN: %llvmgcc -S -O2 -gnatn %s -I%p/Support
-package body Real_Cst is
- Cst : constant Float := 0.0;
- procedure Write (Stream : access Ada.Streams.Root_Stream_Type'Class) is
- begin
- Float'Write (Stream, Cst);
- end;
-end;
diff --git a/test/FrontendAda/switch.adb b/test/FrontendAda/switch.adb
deleted file mode 100644
index 0c83a2e..0000000
--- a/test/FrontendAda/switch.adb
+++ /dev/null
@@ -1,12 +0,0 @@
--- RUN: %llvmgcc -S %s
-function Switch (N : Integer) return Integer is
-begin
- case N is
- when Integer'First .. -1 =>
- return -1;
- when 0 =>
- return 0;
- when others =>
- return 1;
- end case;
-end;
diff --git a/test/FrontendAda/unc_constructor.adb b/test/FrontendAda/unc_constructor.adb
deleted file mode 100644
index ee10de6..0000000
--- a/test/FrontendAda/unc_constructor.adb
+++ /dev/null
@@ -1,9 +0,0 @@
--- RUN: %llvmgcc -S %s -I%p/Support
-package body Unc_Constructor is
- procedure P (X : A) is
- begin
- if X = A0 then
- null;
- end if;
- end;
-end;
diff --git a/test/FrontendAda/var_offset.adb b/test/FrontendAda/var_offset.adb
deleted file mode 100644
index 1d3ca98..0000000
--- a/test/FrontendAda/var_offset.adb
+++ /dev/null
@@ -1,7 +0,0 @@
--- RUN: %llvmgcc -S %s -I%p/Support
-package body Var_Offset is
- function F (X : T) return Character is
- begin
- return X.Bad_Field;
- end;
-end;
diff --git a/test/FrontendAda/var_size.adb b/test/FrontendAda/var_size.adb
deleted file mode 100644
index 291f91d..0000000
--- a/test/FrontendAda/var_size.adb
+++ /dev/null
@@ -1,7 +0,0 @@
--- RUN: %llvmgcc -S %s -I%p/Support
-package body Var_Size is
- function A (X : T) return String is
- begin
- return X.A;
- end;
-end;
diff --git a/test/FrontendAda/vce.adb b/test/FrontendAda/vce.adb
deleted file mode 100644
index 85cdca0..0000000
--- a/test/FrontendAda/vce.adb
+++ /dev/null
@@ -1,7 +0,0 @@
--- RUN: %llvmgcc -S %s
-procedure VCE is
- S : String (1 .. 2);
- B : Character := 'B';
-begin
- S := 'A' & B;
-end;
diff --git a/test/FrontendAda/vce_lv.adb b/test/FrontendAda/vce_lv.adb
deleted file mode 100644
index d1b9e08..0000000
--- a/test/FrontendAda/vce_lv.adb
+++ /dev/null
@@ -1,9 +0,0 @@
--- RUN: %llvmgcc -S %s
-procedure VCE_LV is
- type P is access String ;
- type T is new P (5 .. 7);
- subtype U is String (5 .. 7);
- X : T := new U'(others => 'A');
-begin
- null;
-end;
diff --git a/test/FrontendC++/2003-11-02-WeakLinkage.cpp b/test/FrontendC++/2003-11-02-WeakLinkage.cpp
deleted file mode 100644
index 748ca63..0000000
--- a/test/FrontendC++/2003-11-02-WeakLinkage.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc -xc++ -S -o - %s | not grep weak
-// The template should compile to linkonce linkage, not weak linkage.
-
-template<class T>
-void thefunc();
-
-template<class T>
-inline void thefunc() {}
-
-void test() {
- thefunc<int>();
-}
-
diff --git a/test/FrontendC++/2003-11-18-PtrMemConstantInitializer.cpp b/test/FrontendC++/2003-11-18-PtrMemConstantInitializer.cpp
deleted file mode 100644
index 72609e7..0000000
--- a/test/FrontendC++/2003-11-18-PtrMemConstantInitializer.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-struct Gfx {
- void opMoveSetShowText();
-};
-
-struct Operator {
- void (Gfx::*func)();
-};
-
-Operator opTab[] = {
- {&Gfx::opMoveSetShowText},
-};
-
diff --git a/test/FrontendC++/2003-11-25-ReturningOpaqueByValue.cpp b/test/FrontendC++/2003-11-25-ReturningOpaqueByValue.cpp
deleted file mode 100644
index 5ea0a2c..0000000
--- a/test/FrontendC++/2003-11-25-ReturningOpaqueByValue.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-#include <vector>
-std::vector<int> my_method ();
-
-int
-main ()
-{
- my_method ();
- return 0;
-}
-
diff --git a/test/FrontendC++/2003-11-27-MultipleInheritanceThunk.cpp b/test/FrontendC++/2003-11-27-MultipleInheritanceThunk.cpp
deleted file mode 100644
index 99cfc8d..0000000
--- a/test/FrontendC++/2003-11-27-MultipleInheritanceThunk.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-
-struct CallSite {
- int X;
-
- CallSite(const CallSite &CS);
-};
-
-struct AliasAnalysis {
- int TD;
-
- virtual int getModRefInfo(CallSite CS);
-};
-
-
-struct Pass {
- int X;
- virtual int foo();
-};
-
-struct AliasAnalysisCounter : public Pass, public AliasAnalysis {
- int getModRefInfo(CallSite CS) {
- return 0;
- }
-};
-
-AliasAnalysisCounter AAC;
diff --git a/test/FrontendC++/2003-11-29-DuplicatedCleanupTest.cpp b/test/FrontendC++/2003-11-29-DuplicatedCleanupTest.cpp
deleted file mode 100644
index 8df95cb..0000000
--- a/test/FrontendC++/2003-11-29-DuplicatedCleanupTest.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-
-void doesntThrow() throw();
-struct F {
- ~F() { doesntThrow(); }
-};
-
-void atest() {
- F A;
-lab:
- F B;
- goto lab;
-}
-
-void test(int val) {
-label: {
- F A;
- F B;
- if (val == 0) goto label;
- if (val == 1) goto label;
-}
-}
-
-void test3(int val) {
-label: {
- F A;
- F B;
- if (val == 0) { doesntThrow(); goto label; }
- if (val == 1) { doesntThrow(); goto label; }
-}
-}
-
-void test4(int val) {
-label: {
- F A;
- F B;
- if (val == 0) { F C; goto label; }
- if (val == 1) { F D; goto label; }
-}
-}
diff --git a/test/FrontendC++/2003-12-08-ArrayOfPtrToMemberFunc.cpp b/test/FrontendC++/2003-12-08-ArrayOfPtrToMemberFunc.cpp
deleted file mode 100644
index b87e786..0000000
--- a/test/FrontendC++/2003-12-08-ArrayOfPtrToMemberFunc.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-struct Evil {
- void fun ();
-};
-int foo();
-typedef void (Evil::*memfunptr) ();
-static memfunptr jumpTable[] = { &Evil::fun };
-
-void Evil::fun() {
- (this->*jumpTable[foo()]) ();
-}
diff --git a/test/FrontendC++/2004-01-11-DynamicInitializedConstant.cpp b/test/FrontendC++/2004-01-11-DynamicInitializedConstant.cpp
deleted file mode 100644
index 8ae15c9..0000000
--- a/test/FrontendC++/2004-01-11-DynamicInitializedConstant.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -xc++ -S -o - %s | not grep { constant }
-
-extern int X;
-const int Y = X;
-const int* foo() { return &Y; }
-
diff --git a/test/FrontendC++/2004-03-08-ReinterpretCastCopy.cpp b/test/FrontendC++/2004-03-08-ReinterpretCastCopy.cpp
deleted file mode 100644
index 35880ab..0000000
--- a/test/FrontendC++/2004-03-08-ReinterpretCastCopy.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-struct A {
- virtual void Method() = 0;
-};
-
-struct B : public A {
- virtual void Method() { }
-};
-
-typedef void (A::*fn_type_a)(void);
-typedef void (B::*fn_type_b)(void);
-
-int main(int argc, char **argv)
-{
- fn_type_a f = reinterpret_cast<fn_type_a>(&B::Method);
- fn_type_b g = reinterpret_cast<fn_type_b>(f);
- B b;
- (b.*g)();
- return 0;
-}
diff --git a/test/FrontendC++/2004-03-09-UnmangledBuiltinMethods.cpp b/test/FrontendC++/2004-03-09-UnmangledBuiltinMethods.cpp
deleted file mode 100644
index a600e84..0000000
--- a/test/FrontendC++/2004-03-09-UnmangledBuiltinMethods.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -xc++ -S -o - %s | grep _ZN11AccessFlags6strlenEv
-
-struct AccessFlags {
- void strlen();
-};
-
-void AccessFlags::strlen() { }
-
diff --git a/test/FrontendC++/2004-03-15-CleanupsAndGotos.cpp b/test/FrontendC++/2004-03-15-CleanupsAndGotos.cpp
deleted file mode 100644
index c2e52f6..0000000
--- a/test/FrontendC++/2004-03-15-CleanupsAndGotos.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-// Testcase from Bug 291
-
-struct X {
- ~X();
-};
-
-void foo() {
- X v;
-
-TryAgain:
- goto TryAgain;
-}
diff --git a/test/FrontendC++/2004-06-08-LateTemplateInstantiation.cpp b/test/FrontendC++/2004-06-08-LateTemplateInstantiation.cpp
deleted file mode 100644
index 4ad4c7d..0000000
--- a/test/FrontendC++/2004-06-08-LateTemplateInstantiation.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-
-
-template<typename Ty>
-struct normal_iterator {
- int FIELD;
-};
-
-void foo(normal_iterator<int>);
-normal_iterator<int> baz();
-
-void bar() {
- foo(baz());
-}
-
-void *bar2() {
- return (void*)foo;
-}
diff --git a/test/FrontendC++/2004-09-27-CompilerCrash.cpp b/test/FrontendC++/2004-09-27-CompilerCrash.cpp
deleted file mode 100644
index f52baaf..0000000
--- a/test/FrontendC++/2004-09-27-CompilerCrash.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-struct Pass {} ;
-template<typename PassName>
-Pass *callDefaultCtor() { return new PassName(); }
-
-void foo(Pass *(*C)());
-
-#include <string>
-
-bool foo(std::string &X) {
- return X.empty();
-}
diff --git a/test/FrontendC++/2004-09-27-DidntEmitTemplate.cpp b/test/FrontendC++/2004-09-27-DidntEmitTemplate.cpp
deleted file mode 100644
index 66b970c..0000000
--- a/test/FrontendC++/2004-09-27-DidntEmitTemplate.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %llvmgxx -xc++ %s -S -o - | grep callDefaultCtor | \
-// RUN: not grep declare
-
-// This is a testcase for LLVM PR445, which was a problem where the
-// instantiation of callDefaultCtor was not being emitted correctly.
-
-struct Pass {};
-
-template<typename PassName>
-Pass *callDefaultCtor() { return new Pass(); }
-
-void foo(Pass *(*C)());
-
-struct basic_string {
- bool empty() const { return true; }
-};
-
-
-bool foo2(basic_string &X) {
- return X.empty();
-}
-void baz() { foo(callDefaultCtor<Pass>); }
-
diff --git a/test/FrontendC++/2004-11-27-EmitsUnusedInlineFunctions.cpp b/test/FrontendC++/2004-11-27-EmitsUnusedInlineFunctions.cpp
deleted file mode 100644
index 794b7d7..0000000
--- a/test/FrontendC++/2004-11-27-EmitsUnusedInlineFunctions.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// The C++ front-end was emitting WAY too many inline functions. This test
-// verifies that it does not emit the body of getchar, because it is not used.
-// This corresponds to PR459
-
-// RUN: %llvmgxx %s -S -o - | not grep {^i32 .getchar}
-
-#include <stdio.h>
diff --git a/test/FrontendC++/2004-11-27-ExceptionCleanupAssertion.cpp b/test/FrontendC++/2004-11-27-ExceptionCleanupAssertion.cpp
deleted file mode 100644
index f3d225e..0000000
--- a/test/FrontendC++/2004-11-27-ExceptionCleanupAssertion.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgxx %s -S -o /dev/null
-
-// This is PR421
-
-struct Strongbad {
- Strongbad(const char *str );
- ~Strongbad();
- operator const char *() const;
-};
-
-void TheCheat () {
- Strongbad foo(0);
- Strongbad dirs[] = { Strongbad(0) + 1};
-}
diff --git a/test/FrontendC++/2004-11-27-FriendDefaultArgCrash.cpp b/test/FrontendC++/2004-11-27-FriendDefaultArgCrash.cpp
deleted file mode 100644
index 731e726..0000000
--- a/test/FrontendC++/2004-11-27-FriendDefaultArgCrash.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgxx %s -o /dev/null -S
-
-// PR447
-
-namespace nm {
- struct str {
- friend int foo(int arg = 0);
- };
-}
diff --git a/test/FrontendC++/2004-11-27-InlineAsmFunctionRedefinition.cpp b/test/FrontendC++/2004-11-27-InlineAsmFunctionRedefinition.cpp
deleted file mode 100644
index 42b223b..0000000
--- a/test/FrontendC++/2004-11-27-InlineAsmFunctionRedefinition.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-// RUN: %llvmgxx %s -S -o /dev/null
-
-// PR397
-
-struct stat { };
-struct stat64 { };
-
-extern "C" {
-
-extern int lstat(const char *, struct stat *) __asm__("lstat64");
-extern int lstat64(const char *, struct stat64 *);
-
-extern int __lxstat(int, const char *, struct stat *) __asm__("__lxstat64");
-extern int __lxstat64(int, const char *, struct stat64 *);
-
-extern __inline__ int lstat(const char *path, struct stat *statbuf) {
- return __lxstat(3, path, statbuf);
-}
-extern __inline__ int lstat64(const char *path, struct stat64 *statbuf) {
- return __lxstat64(3, path, statbuf);
-}
-}
-
-int do_one_file(void) {
- return lstat(0, 0) + lstat64(0,0);
-}
diff --git a/test/FrontendC++/2005-01-03-StaticInitializers.cpp b/test/FrontendC++/2005-01-03-StaticInitializers.cpp
deleted file mode 100644
index da1b005..0000000
--- a/test/FrontendC++/2005-01-03-StaticInitializers.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgxx %s -S -o - | not grep llvm.global_ctor
-
-struct S {
- int A[2];
-};
-
-int XX = (int)(long)&(((struct S*)0)->A[1]);
-
diff --git a/test/FrontendC++/2005-02-11-AnonymousUnion.cpp b/test/FrontendC++/2005-02-11-AnonymousUnion.cpp
deleted file mode 100644
index 87ababc..0000000
--- a/test/FrontendC++/2005-02-11-AnonymousUnion.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// RUN: %llvmgxx %s -S -o -
-
-// Test anonymous union with members of the same size.
-int test1(float F) {
- union {
- float G;
- int i;
- };
- G = F;
- return i;
-}
-
-// test anonymous union with members of differing size.
-int test2(short F) {
- volatile union {
- short G;
- int i;
- };
- G = F;
- return i;
-}
-
-// Make sure that normal unions work. duh :)
-volatile union U_t {
- short S;
- int i;
-} U;
-
-int test3(short s) {
- U.S = s;
- return U.i;
-}
diff --git a/test/FrontendC++/2005-02-13-BadDynamicInit.cpp b/test/FrontendC++/2005-02-13-BadDynamicInit.cpp
deleted file mode 100644
index 84fa565..0000000
--- a/test/FrontendC++/2005-02-13-BadDynamicInit.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgxx %s -S -o - | not grep llvm.global_ctors
-// This testcase corresponds to PR509
-struct Data {
- unsigned *data;
- unsigned array[1];
-};
-
-Data shared_null = { shared_null.array };
-
diff --git a/test/FrontendC++/2005-02-14-BitFieldOffset.cpp b/test/FrontendC++/2005-02-14-BitFieldOffset.cpp
deleted file mode 100644
index 522e20a..0000000
--- a/test/FrontendC++/2005-02-14-BitFieldOffset.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgxx %s -S -o - | not grep {i32 6}
-
-struct QVectorTypedData {
- int size;
- unsigned int sharable : 1;
- unsigned short array[1];
-};
-
-void foo(QVectorTypedData *X) {
- X->array[0] = 123;
-}
diff --git a/test/FrontendC++/2005-02-19-BitfieldStructCrash.cpp b/test/FrontendC++/2005-02-19-BitfieldStructCrash.cpp
deleted file mode 100644
index 8f571e0..0000000
--- a/test/FrontendC++/2005-02-19-BitfieldStructCrash.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgxx -S %s -o -
-
-struct QChar {unsigned short X; QChar(unsigned short); } ;
-
-struct Command {
- Command(QChar c) : c(c) {}
- unsigned int type : 4;
- QChar c;
- };
-
-Command X(QChar('c'));
-
-void Foo(QChar );
-void bar() { Foo(X.c); }
diff --git a/test/FrontendC++/2005-02-19-UnnamedVirtualThunkArgument.cpp b/test/FrontendC++/2005-02-19-UnnamedVirtualThunkArgument.cpp
deleted file mode 100644
index 853fee7..0000000
--- a/test/FrontendC++/2005-02-19-UnnamedVirtualThunkArgument.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-// RUN: %llvmgxx -S %s -o /dev/null
-
-struct Foo {
- Foo();
- virtual ~Foo();
-};
-
-struct Bar {
- Bar();
- virtual ~Bar();
- virtual bool test(bool) const;
-};
-
-struct Baz : public Foo, public Bar {
- Baz();
- virtual ~Baz();
- virtual bool test(bool) const;
-};
-
-bool Baz::test(bool) const {
- return true;
-}
diff --git a/test/FrontendC++/2005-02-20-BrokenReferenceTest.cpp b/test/FrontendC++/2005-02-20-BrokenReferenceTest.cpp
deleted file mode 100644
index 31026d3..0000000
--- a/test/FrontendC++/2005-02-20-BrokenReferenceTest.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgxx %s -S -o /dev/null
-
-void test(unsigned char *b, int rb) {
- typedef unsigned char imgfoo[10][rb];
- imgfoo &br = *(imgfoo *)b;
-
- br[0][0] = 1;
-
- rb = br[0][0];
-}
-
diff --git a/test/FrontendC++/2005-02-27-PlacementArrayNewCrash.cpp b/test/FrontendC++/2005-02-27-PlacementArrayNewCrash.cpp
deleted file mode 100644
index a8fc668..0000000
--- a/test/FrontendC++/2005-02-27-PlacementArrayNewCrash.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgxx -S %s -o -
-
-#include <new>
-typedef double Ty[4];
-
-void foo(Ty *XX) {
- new(XX) Ty();
-}
diff --git a/test/FrontendC++/2005-07-21-VirtualBaseAccess.cpp b/test/FrontendC++/2005-07-21-VirtualBaseAccess.cpp
deleted file mode 100644
index ca600d6..0000000
--- a/test/FrontendC++/2005-07-21-VirtualBaseAccess.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgxx -xc++ %s -S -o - | opt -die -S | not grep cast
-
-void foo(int*);
-
-struct FOO {
- int X;
-};
-
-struct BAR : virtual FOO { BAR(); };
-
-int testfn() {
- BAR B;
- foo(&B.X);
-}
diff --git a/test/FrontendC++/2006-03-01-GimplifyCrash.cpp b/test/FrontendC++/2006-03-01-GimplifyCrash.cpp
deleted file mode 100644
index b0d00fe..0000000
--- a/test/FrontendC++/2006-03-01-GimplifyCrash.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgxx -S %s -o -
-
-struct PrefMapElem {
- virtual ~PrefMapElem();
- unsigned int fPrefId;
-};
-
-int foo() {
- PrefMapElem* fMap;
- if (fMap[0].fPrefId == 1)
- return 1;
-
- return 0;
-}
diff --git a/test/FrontendC++/2006-03-06-C++RecurseCrash.cpp b/test/FrontendC++/2006-03-06-C++RecurseCrash.cpp
deleted file mode 100644
index 2fb3fb7..0000000
--- a/test/FrontendC++/2006-03-06-C++RecurseCrash.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-namespace std {
- class exception { };
-
- class type_info {
- public:
- virtual ~type_info();
- };
-
-}
-
-namespace __cxxabiv1 {
- class __si_class_type_info : public std::type_info {
- ~__si_class_type_info();
- };
-}
-
-class recursive_init: public std::exception {
-public:
- virtual ~recursive_init() throw ();
-};
-
-recursive_init::~recursive_init() throw() { }
-
diff --git a/test/FrontendC++/2006-09-08-powi.cpp b/test/FrontendC++/2006-09-08-powi.cpp
deleted file mode 100644
index 75cbfda..0000000
--- a/test/FrontendC++/2006-09-08-powi.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgxx -O3 -S -o - %s
-
-#include <cmath>
-
-double foo(double X, int Y) {
- return std::pow(X, Y);
-}
diff --git a/test/FrontendC++/2006-09-12-OpaqueStructCrash.cpp b/test/FrontendC++/2006-09-12-OpaqueStructCrash.cpp
deleted file mode 100644
index f3160e8..0000000
--- a/test/FrontendC++/2006-09-12-OpaqueStructCrash.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %llvmgxx -O3 -S -o - %s
-
-struct A {
- virtual ~A();
-};
-
-template <typename Ty>
-struct B : public A {
- ~B () { delete [] val; }
-private:
- Ty* val;
-};
-
-template <typename Ty>
-struct C : public A {
- C ();
- ~C ();
-};
-
-template <typename Ty>
-struct D : public A {
- D () {}
- private:
- B<C<Ty> > blocks;
-};
-
-template class D<double>;
-
diff --git a/test/FrontendC++/2006-09-27-Debug-Protection.cpp b/test/FrontendC++/2006-09-27-Debug-Protection.cpp
deleted file mode 100644
index 2a70a0f..0000000
--- a/test/FrontendC++/2006-09-27-Debug-Protection.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgxx -O0 -S -g -o - %s | grep {i32 1,}
-// RUN: %llvmgxx -O0 -S -g -o - %s | grep {i32 2,}
-class A {
-public:
- int x;
-protected:
- int y;
-private:
- int z;
-};
-
-A a;
diff --git a/test/FrontendC++/2006-10-30-ClassBitfield.cpp b/test/FrontendC++/2006-10-30-ClassBitfield.cpp
deleted file mode 100644
index b3b43fb..0000000
--- a/test/FrontendC++/2006-10-30-ClassBitfield.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgxx %s -S -o -
-// PR954
-
-struct _Refcount_Base {
- unsigned long _M_ref_count;
- int _M_ref_count_lock;
- _Refcount_Base() : _M_ref_count(0) {}
-};
-
-struct _Rope_RopeRep : public _Refcount_Base
-{
-public:
- int _M_tag:8;
-};
-
-int foo(_Rope_RopeRep* r) { return r->_M_tag; }
diff --git a/test/FrontendC++/2006-11-06-StackTrace.cpp b/test/FrontendC++/2006-11-06-StackTrace.cpp
deleted file mode 100644
index 2813c36..0000000
--- a/test/FrontendC++/2006-11-06-StackTrace.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// This is a regression test on debug info to make sure that we can get a
-// meaningful stack trace from a C++ program.
-// RUN: %llvmgcc -S -O0 -g %s -o - | \
-// RUN: llc --disable-cfi --disable-fp-elim -o %t.s -O0 -relocation-model=pic
-// RUN: %compile_c %t.s -o %t.o
-// RUN: %link %t.o -o %t.exe
-// RUN: echo {break DeepStack::deepest\nrun 17\nwhere\n} > %t.in
-// RN: gdb -q -batch -n -x %t.in %t.exe | tee %t.out | \
-// RN: grep {#0 DeepStack::deepest.*(this=.*,.*x=33)}
-// RN: gdb -q -batch -n -x %t.in %t.exe | \
-// RN: grep {#7 0x.* in main.*(argc=\[12\],.*argv=.*)}
-
-// Only works on ppc (but not apple-darwin9), x86 and x86_64. Should
-// generalize?
-// XAIL: alpha,arm,powerpc-apple-darwin9
-
-#include <stdlib.h>
-
-class DeepStack {
- int seedVal;
-public:
- DeepStack(int seed) : seedVal(seed) {}
-
- int shallowest( int x ) { return shallower(x + 1); }
- int shallower ( int x ) { return shallow(x + 2); }
- int shallow ( int x ) { return deep(x + 3); }
- int deep ( int x ) { return deeper(x + 4); }
- int deeper ( int x ) { return deepest(x + 6); }
- int deepest ( int x ) { return x + 7; }
-
- int runit() { return shallowest(seedVal); }
-};
-
-int main ( int argc, char** argv) {
-
- DeepStack DS9( (argc > 1 ? atoi(argv[1]) : 0) );
- return DS9.runit();
-}
diff --git a/test/FrontendC++/2006-11-20-GlobalSymbols.cpp b/test/FrontendC++/2006-11-20-GlobalSymbols.cpp
deleted file mode 100644
index c4afd32..0000000
--- a/test/FrontendC++/2006-11-20-GlobalSymbols.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-// PR1013
-// Check to make sure debug symbols use the correct name for globals and
-// functions. Will not assemble if it fails to.
-// RUN: %llvmgcc_only -O0 -g -c %s
-
-int foo __asm__("f\001oo");
-
-int bar() {
- return foo;
-}
diff --git a/test/FrontendC++/2006-11-30-ConstantExprCrash.cpp b/test/FrontendC++/2006-11-30-ConstantExprCrash.cpp
deleted file mode 100644
index d351b94..0000000
--- a/test/FrontendC++/2006-11-30-ConstantExprCrash.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-// RUN: %llvmgxx %s -S -o -
-// PR1027
-
-struct sys_var {
- unsigned name_length;
-
- bool no_support_one_shot;
- sys_var() {}
-};
-
-
-struct sys_var_thd : public sys_var {
-};
-
-extern sys_var_thd sys_auto_is_null;
-
-sys_var *getsys_variables() {
- return &sys_auto_is_null;
-}
-
-sys_var *sys_variables = &sys_auto_is_null;
-
-
-
-
-
-
diff --git a/test/FrontendC++/2006-11-30-Pubnames.cpp b/test/FrontendC++/2006-11-30-Pubnames.cpp
deleted file mode 100644
index fc7beeb..0000000
--- a/test/FrontendC++/2006-11-30-Pubnames.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-// This is a regression test on debug info to make sure that we can access
-// qualified global names.
-// RUN: %llvmgcc -S -O0 -g %s -o - | \
-// RUN: llc -disable-cfi --disable-fp-elim -o %t.s -O0
-// RUN: %compile_c %t.s -o %t.o
-// RUN: %link %t.o -o %t.exe
-// RUN: %llvmdsymutil %t.exe
-// RUN: echo {break main\nrun\np Pubnames::pubname} > %t.in
-// RUN: gdb -q -batch -n -x %t.in %t.exe | tee %t.out | grep {\$1 = 10}
-//
-// XFAIL: alpha,arm
-
-struct Pubnames {
- static int pubname;
-};
-
-int Pubnames::pubname = 10;
-
-int main (int argc, char** argv) {
- Pubnames p;
- return 0;
-}
diff --git a/test/FrontendC++/2007-01-02-UnboundedArray.cpp b/test/FrontendC++/2007-01-02-UnboundedArray.cpp
deleted file mode 100644
index 3103086..0000000
--- a/test/FrontendC++/2007-01-02-UnboundedArray.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// Make sure unbounded arrays compile with debug information.
-//
-// RUN: %llvmgcc -O0 -S -g %s
-
-// PR1068
-
-struct Object {
- char buffer[];
-};
-
-int main(int argc, char** argv) {
- new Object;
- return 0;
-}
diff --git a/test/FrontendC++/2007-01-06-ELF-Thunk-Sections.cpp b/test/FrontendC++/2007-01-06-ELF-Thunk-Sections.cpp
deleted file mode 100644
index 5206640..0000000
--- a/test/FrontendC++/2007-01-06-ELF-Thunk-Sections.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-// RUN: %llvmgxx %s -S -o - | not grep gnu.linkonce.
-// PR1085
-
-class
-__attribute__((visibility("default"))) QGenericArgument
-{
- public:inline QGenericArgument(const char *aName = 0, const void *aData = 0):_data(aData), _name(aName) {
- }
- private:const void *_data;
- const char *_name;
-};
-struct __attribute__ ((
- visibility("default"))) QMetaObject
-{
- struct {
- }
- d;
-};
-class
-__attribute__((visibility("default"))) QObject
-{
- virtual const QMetaObject *metaObject() const;
-};
-class
-__attribute__((visibility("default"))) QPaintDevice
-{
- public:enum PaintDeviceMetric {
- PdmWidth = 1, PdmHeight, PdmWidthMM, PdmHeightMM, PdmNumColors, PdmDepth, PdmDpiX, PdmDpiY, PdmPhysicalDpiX, PdmPhysicalDpiY
- };
- virtual ~ QPaintDevice();
- union {
- }
- ct;
-};
-class
-__attribute__((visibility("default"))) QWidget:public QObject, public QPaintDevice
-{
-};
-class
-__attribute__((visibility("default"))) QDialog:public QWidget
-{
-};
-class TopicChooser:public QDialog {
- virtual const QMetaObject *metaObject() const;
-};
-const QMetaObject *TopicChooser::
-metaObject() const
-{
-}
diff --git a/test/FrontendC++/2007-01-06-PtrMethodInit.cpp b/test/FrontendC++/2007-01-06-PtrMethodInit.cpp
deleted file mode 100644
index beb7945..0000000
--- a/test/FrontendC++/2007-01-06-PtrMethodInit.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-// RUN: %llvmgxx %s -S -o -
-// PR1084
-
-extern "C"
-{
- typedef unsigned char PRUint8;
- typedef unsigned int PRUint32;
-}
-typedef PRUint32 nsresult;
-struct nsID
-{
-};
-typedef nsID nsIID;
-class nsISupports
-{
-};
-extern "C++"
-{
- template < class T > struct nsCOMTypeInfo
- {
- static const nsIID & GetIID ()
- {
- }
- };
-}
-
-class nsIDOMEvent:public nsISupports
-{
-};
-class nsIDOMEventListener:public nsISupports
-{
-public:static const nsIID & GetIID ()
- {
- }
- virtual nsresult
- __attribute__ ((regparm (0), cdecl)) HandleEvent (nsIDOMEvent * event) =
- 0;
-};
-class nsIDOMMouseListener:public nsIDOMEventListener
-{
-public:static const nsIID & GetIID ()
- {
- static const nsIID iid = {
- };
- }
- virtual nsresult
- __attribute__ ((regparm (0),
- cdecl)) MouseDown (nsIDOMEvent * aMouseEvent) = 0;
-};
-typedef
-typeof (&nsIDOMEventListener::HandleEvent)
- GenericHandler;
- struct EventDispatchData
- {
- PRUint32 message;
- GenericHandler method;
- PRUint8 bits;
- };
- struct EventTypeData
- {
- const EventDispatchData *events;
- int numEvents;
- const nsIID *iid;
- };
- static const EventDispatchData sMouseEvents[] = {
- {
- (300 + 2),
- reinterpret_cast < GenericHandler > (&nsIDOMMouseListener::MouseDown),
- 0x01}
- };
-static const EventTypeData sEventTypes[] = {
- {
- sMouseEvents, (sizeof (sMouseEvents) / sizeof (sMouseEvents[0])),
- &nsCOMTypeInfo < nsIDOMMouseListener >::GetIID ()}
-};
diff --git a/test/FrontendC++/2007-03-27-FunctionVarRename.cpp b/test/FrontendC++/2007-03-27-FunctionVarRename.cpp
deleted file mode 100644
index 6ff1284..0000000
--- a/test/FrontendC++/2007-03-27-FunctionVarRename.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgxx %s -S -o - | not grep eprintf1
-// RUN: %llvmgxx %s -S -o - | grep eprintf
-
-// Only one eprintf should exist in the output
-
-extern "C"
-void __eprintf();
-
-void foo() {
-
- __eprintf();
-}
-
-void *bar() {
- extern void *__eprintf;
- return &__eprintf;
-}
diff --git a/test/FrontendC++/2007-04-05-PackedBitFields-1.cpp b/test/FrontendC++/2007-04-05-PackedBitFields-1.cpp
deleted file mode 100644
index 174dddf..0000000
--- a/test/FrontendC++/2007-04-05-PackedBitFields-1.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-#ifdef PACKED
-#define P __attribute__((packed))
-#else
-#define P
-#endif
-
-struct P M_Packed {
- unsigned int l_Packed;
- unsigned short k_Packed : 6,
- i_Packed : 15,
- j_Packed : 11;
-
-};
-
-struct M_Packed sM_Packed;
-
-int testM_Packed (void) {
- struct M_Packed x;
- return (x.i_Packed != 0);
-}
-
diff --git a/test/FrontendC++/2007-04-05-PackedBitFieldsOverlap-2.cpp b/test/FrontendC++/2007-04-05-PackedBitFieldsOverlap-2.cpp
deleted file mode 100644
index 55da1a6..0000000
--- a/test/FrontendC++/2007-04-05-PackedBitFieldsOverlap-2.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-#ifdef PACKED
-#define P __attribute__((packed))
-#else
-#define P
-#endif
-
-struct P M_Packed {
- unsigned long sorted : 1;
- unsigned long from_array : 1;
- unsigned long mixed_encoding : 1;
- unsigned long encoding : 8;
- unsigned long count : 21;
-
-};
-
-struct M_Packed sM_Packed;
-
-int testM_Packed (void) {
- struct M_Packed x;
- return (x.count != 0);
-}
-
diff --git a/test/FrontendC++/2007-04-05-PackedBitFieldsOverlap.cpp b/test/FrontendC++/2007-04-05-PackedBitFieldsOverlap.cpp
deleted file mode 100644
index 46a8949..0000000
--- a/test/FrontendC++/2007-04-05-PackedBitFieldsOverlap.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-
-#ifdef PACKED
-#define P __attribute__((packed))
-#else
-#define P
-#endif
-
-struct P M_Packed {
- unsigned int l_Packed;
- unsigned short k_Packed : 6,
- i_Packed : 15;
- char c;
-
-};
-
-struct M_Packed sM_Packed;
-
-int testM_Packed (void) {
- struct M_Packed x;
- return (x.i_Packed != 0);
-}
-
diff --git a/test/FrontendC++/2007-04-05-PackedBitFieldsSmall.cpp b/test/FrontendC++/2007-04-05-PackedBitFieldsSmall.cpp
deleted file mode 100644
index 7377b82..0000000
--- a/test/FrontendC++/2007-04-05-PackedBitFieldsSmall.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-
-#ifdef PACKED
-// This is an example where size of Packed struct is smaller then
-// the size of bit field type.
-#define P __attribute__((packed))
-#else
-#define P
-#endif
-
-struct P M_Packed {
- unsigned long long X:50;
- unsigned Y:2;
-};
-
-struct M_Packed sM_Packed;
-
-int testM_Packed (void) {
- struct M_Packed x;
- return (0 != x.Y);
-}
-
-int testM_Packed2 (void) {
- struct M_Packed x;
- return (0 != x.X);
-}
diff --git a/test/FrontendC++/2007-04-05-StructPackedFieldUnpacked.cpp b/test/FrontendC++/2007-04-05-StructPackedFieldUnpacked.cpp
deleted file mode 100644
index b550b5f..0000000
--- a/test/FrontendC++/2007-04-05-StructPackedFieldUnpacked.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | llvm-as -o /dev/null
-
-#ifdef PACKED
-#define P __attribute__((packed))
-#else
-#define P
-#endif
-
-struct UnPacked {
- int X;
- int Y;
-};
-
-struct P M_Packed {
- unsigned char A;
- struct UnPacked B;
-};
-
-struct M_Packed sM_Packed;
-
-int testM_Packed (void) {
- struct M_Packed x;
- return (x.B.Y != 0);
-}
-
diff --git a/test/FrontendC++/2007-04-10-PackedUnion.cpp b/test/FrontendC++/2007-04-10-PackedUnion.cpp
deleted file mode 100644
index b4b8894..0000000
--- a/test/FrontendC++/2007-04-10-PackedUnion.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-// RUN: %llvmgxx -S %s -o /dev/null
-extern "C" {
-
-#pragma pack(push, 2)
- typedef struct ABC* abc;
-
- struct ABCS {
- float red;
- float green;
- float blue;
- float alpha;
- };
-
- typedef void (*XYZ)();
-#pragma pack(pop)
-}
-
-
-union ABCU {
- ABCS color;
- XYZ bg;
-};
-
-struct AData {
- ABCU data;
-};
-
-class L {
- public:
- L() {}
- L(const L& other);
-
- private:
- AData fdata;
-};
-
-
-L::L(const L& other)
-{
- fdata = other.fdata;
-}
diff --git a/test/FrontendC++/2007-04-11-InlineStorageClassC++.cpp b/test/FrontendC++/2007-04-11-InlineStorageClassC++.cpp
deleted file mode 100644
index 4c2aad3..0000000
--- a/test/FrontendC++/2007-04-11-InlineStorageClassC++.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-// RUN: %llvmgxx %s -S -O0 -o - | grep define | \
-// RUN: grep xglobWeak | grep linkonce | count 1
-// RUN: %llvmgxx %s -S -O0 -o - | grep define | \
-// RUN: grep xextWeak | grep linkonce | count 1
-// RUN: %llvmgxx %s -S -O0 -o - | grep define | \
-// RUN: grep xWeaknoinline | grep weak | count 1
-// RUN: %llvmgxx %s -S -O0 -o - | grep define | \
-// RUN: grep xWeakextnoinline | grep weak | count 1
-// RUN: %llvmgxx %s -S -O0 -o - | grep define | \
-// RUN: grep xglobnoWeak | grep linkonce | count 1
-// RUN: %llvmgxx %s -S -O0 -o - | grep define | \
-// RUN: grep xstatnoWeak | grep internal | count 1
-// RUN: %llvmgxx %s -S -O0 -o - | grep define | \
-// RUN: grep xextnoWeak | grep linkonce | count 1
-inline int xglobWeak(int) __attribute__((weak));
-inline int xglobWeak (int i) {
- return i*2;
-}
-inline int xextWeak(int) __attribute__((weak));
-extern inline int xextWeak (int i) {
- return i*4;
-}
-int xWeaknoinline(int) __attribute__((weak));
-int xWeaknoinline(int i) {
- return i*8;
-}
-int xWeakextnoinline(int) __attribute__((weak));
-extern int xWeakextnoinline(int i) {
- return i*16;
-}
-inline int xglobnoWeak (int i) {
- return i*32;
-}
-static inline int xstatnoWeak (int i) {
- return i*64;
-}
-extern inline int xextnoWeak (int i) {
- return i*128;
-}
-int j(int y) {
- return xglobnoWeak(y)+xstatnoWeak(y)+xextnoWeak(y)+
- xglobWeak(y)+xextWeak(y)+
- xWeakextnoinline(y)+xWeaknoinline(y);
-}
diff --git a/test/FrontendC++/2007-04-14-FNoBuiltin.cpp b/test/FrontendC++/2007-04-14-FNoBuiltin.cpp
deleted file mode 100644
index 31e4528..0000000
--- a/test/FrontendC++/2007-04-14-FNoBuiltin.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -O2 -fno-builtin -o - | grep call.*printf
-// Check that -fno-builtin is honored.
-
-extern "C" int printf(const char*, ...);
-void foo(const char *msg) {
- printf("%s\n",msg);
-}
diff --git a/test/FrontendC++/2007-04-31-TryCatch.cpp b/test/FrontendC++/2007-04-31-TryCatch.cpp
deleted file mode 100644
index 8b8254d..0000000
--- a/test/FrontendC++/2007-04-31-TryCatch.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgxx -S %s -o /dev/null
-
-#include <locale>
-
-namespace std
-{
- codecvt<char, char, mbstate_t>::
- codecvt(size_t __refs)
- : __codecvt_abstract_base<char, char, mbstate_t>(__refs),
- _M_c_locale_codecvt(_S_get_c_locale())
- { }
-}
diff --git a/test/FrontendC++/2007-05-03-VectorInit.cpp b/test/FrontendC++/2007-05-03-VectorInit.cpp
deleted file mode 100644
index af56d3a..0000000
--- a/test/FrontendC++/2007-05-03-VectorInit.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgxx %s -S -O0 -o -
-// PR1378
-
-typedef float v4sf __attribute__((vector_size(16)));
-
-typedef v4sf float4;
-
-static float4 splat4(float a)
-{
- float4 tmp = {a,a,a,a};
- return tmp;
-}
-
-float4 foo(float a)
-{
- return splat4(a);
-}
diff --git a/test/FrontendC++/2007-05-16-ReverseBitFieldCrash.cpp b/test/FrontendC++/2007-05-16-ReverseBitFieldCrash.cpp
deleted file mode 100644
index 42342fc..0000000
--- a/test/FrontendC++/2007-05-16-ReverseBitFieldCrash.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgxx %s -S -o -
-
-#pragma reverse_bitfields on
-typedef unsigned long UINT32;
-
-extern void abort(void);
-
-typedef struct TestStruct
-{
- long first: 15,
- second: 17;
-} TestStruct;
-
-int main (int argc, char * const argv[]) {
-
- TestStruct testStruct = {1, 0};
-
- UINT32 dw = *(UINT32 *)(&testStruct);
-
- if(!(dw & 0xFFFF))
- abort ();
-
- return 0;
-}
diff --git a/test/FrontendC++/2007-05-23-TryFinally.cpp b/test/FrontendC++/2007-05-23-TryFinally.cpp
deleted file mode 100644
index c797182..0000000
--- a/test/FrontendC++/2007-05-23-TryFinally.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgxx %s -S -O2 -o - | ignore grep _Unwind_Resume | \
-// RUN: wc -l | grep {\[23\]}
-
-struct One { };
-struct Two { };
-
-void handle_unexpected () {
- try
- {
- throw;
- }
- catch (One &)
- {
- throw Two ();
- }
-}
diff --git a/test/FrontendC++/2007-07-04-NestedCatches.cpp b/test/FrontendC++/2007-07-04-NestedCatches.cpp
deleted file mode 100644
index b10a5db..0000000
--- a/test/FrontendC++/2007-07-04-NestedCatches.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// RUN: %llvmgxx %s -S -O2 -o - | \
-// RUN: ignore grep {eh\.selector.*One.*Two.*Three.*Four.*Five.*Six.*null} | \
-// RUN: wc -l | grep {\[01\]}
-
-extern void X(void);
-
-struct One {};
-struct Two {};
-struct Three {};
-struct Four {};
-struct Five {};
-struct Six {};
-
-static void A(void) throw ()
-{
- X();
-}
-
-static void B(void) throw (Two)
-{
- try { A(); } catch (One) {}
-}
-
-static void C(void) throw (Six, Five)
-{
- try { B(); } catch (Three) {} catch (Four) {}
-}
-
-int main ()
-{
- try { C(); } catch (...) {}
-}
diff --git a/test/FrontendC++/2007-07-29-RestrictPtrArg.cpp b/test/FrontendC++/2007-07-29-RestrictPtrArg.cpp
deleted file mode 100644
index 2e85abd..0000000
--- a/test/FrontendC++/2007-07-29-RestrictPtrArg.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | grep noalias
-
-void foo(int * __restrict myptr1, int * myptr2) {
- myptr1[0] = 0;
- myptr2[0] = 0;
-}
diff --git a/test/FrontendC++/2007-07-29-RestrictRefArg.cpp b/test/FrontendC++/2007-07-29-RestrictRefArg.cpp
deleted file mode 100644
index 128ddb3..0000000
--- a/test/FrontendC++/2007-07-29-RestrictRefArg.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | grep noalias
-
-void foo(int & __restrict myptr1, int & myptr2) {
- myptr1 = 0;
- myptr2 = 0;
-}
diff --git a/test/FrontendC++/2007-08-01-RestrictMethod.cpp b/test/FrontendC++/2007-08-01-RestrictMethod.cpp
deleted file mode 100644
index feefaa1..0000000
--- a/test/FrontendC++/2007-08-01-RestrictMethod.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | grep noalias
-
-
-class foo {
- int member[4];
-
- void bar(int * a);
-
-};
-
-void foo::bar(int * a) __restrict {
- member[3] = *a;
-}
diff --git a/test/FrontendC++/2007-09-10-RecursiveTypeResolution.cpp b/test/FrontendC++/2007-09-10-RecursiveTypeResolution.cpp
deleted file mode 100644
index 1fcf15f..0000000
--- a/test/FrontendC++/2007-09-10-RecursiveTypeResolution.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-// RUN: %llvmgxx -S %s -o -
-// PR1634
-
-namespace Manta
-{
- class CallbackHandle
- {
- protected:virtual ~ CallbackHandle (void)
- {
- }
- };
-template < typename Data1 > class CallbackBase_1Data:public CallbackHandle
- {
- };
-}
-
-namespace __gnu_cxx
-{
- template < typename _Iterator, typename _Container >
- class __normal_iterator
- {
- _Iterator _M_current;
- };
-}
-
-namespace std
-{
- template < typename _Tp > struct allocator
- {
- typedef _Tp *pointer;
- };
- template < typename _InputIterator,
- typename _Tp > inline void find (_InputIterator __last,
- const _Tp & __val)
- {
- };
-}
-
-namespace Manta
-{
- template < typename _Tp, typename _Alloc> struct _Vector_base
- {
- struct _Vector_impl
- {
- _Tp *_M_start;
- };
- public:
- _Vector_impl _M_impl;
- };
- template < typename _Tp, typename _Alloc = std::allocator < _Tp > >
- class vector:protected _Vector_base < _Tp,_Alloc >
- {
- public:
- typedef __gnu_cxx::__normal_iterator < typename _Alloc::pointer,
- vector < _Tp, _Alloc > > iterator;
- iterator end ()
- {
- }
- };
- class MantaInterface
- {
- };
- class RTRT
- {
- virtual CallbackHandle *registerTerminationCallback (CallbackBase_1Data <
- MantaInterface * >*);
- virtual void unregisterCallback (CallbackHandle *);
- typedef vector < CallbackBase_1Data < int >*>PRCallbackMapType;
- PRCallbackMapType parallelPreRenderCallbacks;
- };
-}
-using namespace Manta;
-CallbackHandle *
-RTRT::registerTerminationCallback (CallbackBase_1Data < MantaInterface * >*cb)
-{
- return cb;
-}
-
-void
-RTRT::unregisterCallback (CallbackHandle * callback)
-{
- {
- typedef CallbackBase_1Data < int > callback_t;
- callback_t *cb = static_cast < callback_t * >(callback);
- find (parallelPreRenderCallbacks.end (), cb);
- }
-}
-
diff --git a/test/FrontendC++/2007-10-01-StructResize.cpp b/test/FrontendC++/2007-10-01-StructResize.cpp
deleted file mode 100644
index 71109eb..0000000
--- a/test/FrontendC++/2007-10-01-StructResize.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgxx -S %s -o /dev/null
-
-#pragma pack(4)
-
-struct Bork {
- unsigned int f1 : 3;
- unsigned int f2 : 30;
-};
-
-int Foo(Bork *hdr) {
- hdr->f1 = 7;
- hdr->f2 = 927;
-}
-
diff --git a/test/FrontendC++/2008-01-11-BadWarning.cpp b/test/FrontendC++/2008-01-11-BadWarning.cpp
deleted file mode 100644
index 43f6a71..0000000
--- a/test/FrontendC++/2008-01-11-BadWarning.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -xc++ %s -S -o /dev/null |& not grep warning
-// rdar://5683899
-void** f(void **Buckets, unsigned NumBuckets) {
- return Buckets + NumBuckets;
-}
-
diff --git a/test/FrontendC++/2008-01-12-VecInit.cpp b/test/FrontendC++/2008-01-12-VecInit.cpp
deleted file mode 100644
index e21bbb9..0000000
--- a/test/FrontendC++/2008-01-12-VecInit.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -xc++ %s -S -o -
-// rdar://5685492
-
-typedef int __attribute__((vector_size(16))) v;
-v vt = {1, 2, 3, 4};
-
diff --git a/test/FrontendC++/2008-05-07-CrazyOffsetOf.cpp b/test/FrontendC++/2008-05-07-CrazyOffsetOf.cpp
deleted file mode 100644
index f183197..0000000
--- a/test/FrontendC++/2008-05-07-CrazyOffsetOf.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgxx -S %s -o -
-// rdar://5914926
-
-struct bork {
- struct bork *next_local;
- char * query;
-};
-int offset = (char *) &(((struct bork *) 0x10)->query) - (char *) 0x10;
diff --git a/test/FrontendC++/2008-10-29-WrongOffset.cpp b/test/FrontendC++/2008-10-29-WrongOffset.cpp
deleted file mode 100644
index c261c31..0000000
--- a/test/FrontendC++/2008-10-29-WrongOffset.cpp
+++ /dev/null
@@ -1,489 +0,0 @@
-// RUN: %llvmgxx %s -S -o /dev/null
-// PR2917
-
-#include <complex>
-template < int Dim, class T, class EngineTag > class Engine;
-template < class Subject, class Sub1, bool SV > struct View1Implementation;
-template < class LayoutTag, class PatchTag > struct MultiPatch;
-template < class LayoutTag, class PatchTag, int Dim2 > struct MultiPatchView;
-template < class Engine, class SubDomain > struct NewEngine
-{
-};
-template < class T > class DomainTraits;
-template < class DomT, class T, int Dim > struct DomainTraitsDomain
-{
- typedef DomT NewDomain1_t;
-};
-template < int Dim > class Interval;
-template < int Dim > class Loc;
-template < class DT > class DomainBase
-{
-};
-
-template < int Dim, class DT > class Domain:public DomainBase < DT >
-{
-};
-template < int Dim > struct DomainTraits <Interval < Dim >
- >:public DomainTraitsDomain < Interval < Dim >, int, Dim >
-{
- enum
- {
- singleValued = false
- };
-};
-template < class T1 > struct NewDomain1
-{
- typedef typename DomainTraits < T1 >::NewDomain1_t SliceType_t;
-};
-template < class Domain, class Sub > struct TemporaryNewDomain1
-{
- typedef typename NewDomain1 < Sub >::SliceType_t SliceType_t;
-};
-template < int Dim > class Interval:public Domain < Dim,
- DomainTraits < Interval < Dim > > >
-{
-};
-template < int Dim > class GuardLayers
-{
-};
-template < class T > class Observer
-{
-};
-
-template < class T > class Observable
-{
-private:T & observed_m;
- int count_m;
-};
-
-class RefCounted
-{
-};
-template < class T > class RefCountedPtr
-{
-public:typedef RefCountedPtr < T > This_t;
- RefCountedPtr (T * const pT):ptr_m (pT)
- {
- }
- inline T *operator-> () const
- {
- }
- T *ptr_m;
-};
-
-template < class Dom, class T > class DomainMap
-{
-};
-
-template < class LayoutTag, int Dim > struct MultiPatchLayoutTraits
-{
-};
-template < int Dim > class LayoutBaseData
-{
-public:typedef Interval < Dim > Domain_t;
- Domain_t domain_m;
-};
-template < int Dim, class LBD > class LayoutBase
-{
-public:typedef LayoutBaseData < Dim > LayoutData_t;
- typedef typename LayoutData_t::Domain_t Domain_t;
- typedef GuardLayers < Dim > GuardLayers_t;
- inline const Domain_t & domain () const
- {
- return pdata_m->domain_m;
- }
- inline const Domain_t & innerDomain () const
- {
- }
- inline GuardLayers_t externalGuards () const
- {
- }
- RefCountedPtr < LBD > pdata_m;
-};
-template < class Tag > struct Remote;
-struct Brick
-{
-};
-template < class Thing, class Sub > struct View1
-{
-};
-template < int Dim, class T, class LayoutTag,
- class PatchTag > struct NewEngine <Engine < Dim, T, MultiPatch < LayoutTag,
- PatchTag > >, Interval < Dim > >
-{
- typedef Engine < Dim, T, MultiPatchView < LayoutTag, PatchTag,
- Dim > >Type_t;
-};
-template < int Dim, class T, class LayoutTag, class PatchTag,
- int Dim2 > struct NewEngine <Engine < Dim, T, MultiPatchView < LayoutTag,
- PatchTag, Dim2 > >, Interval < Dim > >
-{
- typedef Engine < Dim, T, MultiPatchView < LayoutTag, PatchTag,
- Dim2 > >Type_t;
-};
-template < int Dim, class T, class LayoutTag,
- class PatchTag > class Engine < Dim, T, MultiPatch < LayoutTag,
- PatchTag > >:public Observer < typename MultiPatchLayoutTraits < LayoutTag,
- Dim >::Layout_t >
-{
-public:typedef MultiPatch < LayoutTag, PatchTag > Tag_t;
- typedef Interval < Dim > Domain_t;
-};
-template < int Dim, class T, class LayoutTag, class PatchTag,
- int Dim2 > class Engine < Dim, T, MultiPatchView < LayoutTag, PatchTag,
- Dim2 > >
-{
-public:typedef MultiPatchView < LayoutTag, PatchTag, Dim2 > Tag_t;
- typedef Interval < Dim > Domain_t;
- typedef T Element_t;
- enum
- {
- dimensions = Dim
- };
-};
-class Full;
-template < int Dim, class T = double, class EngineTag = Full > class Vector {
-};
-
-template < int Dim > inline Interval < Dim >
-shrinkRight (const Interval < Dim > &dom, int s)
-{
-}
-
-template < int Dim > class GridLayout;
-struct GridTag
-{
-};
-template < int Dim > struct MultiPatchLayoutTraits <GridTag, Dim >
-{
- typedef GridLayout < Dim > Layout_t;
-};
-template < int Dim > class GridLayoutData:public LayoutBaseData < Dim >,
- public RefCounted, public Observable < GridLayoutData < Dim > >
-{
- typedef int AxisIndex_t;
- mutable DomainMap < Interval < 1 >, AxisIndex_t > mapAloc_m[Dim];
-};
-template < int Dim > class GridLayout:public LayoutBase < Dim,
- GridLayoutData < Dim > >, public Observable < GridLayout < Dim > >,
- public Observer < GridLayoutData < Dim > >
-{
-public:typedef GridLayout < Dim > This_t;
- GridLayout ();
-};
-template < class MeshTag, class T, class EngineTag > class Field;
-enum CenteringType
-{
- VertexType, EdgeType, FaceType, CellType
-};
-enum ContinuityType
-{
- Continuous = 0, Discontinuous
-};
-template < int Dim > class Centering
-{
-public:typedef Loc < Dim > Orientation;
- inline int size () const
- {
- }
-};
-template < int Dim > const Centering < Dim >
-canonicalCentering (const enum CenteringType type,
- const enum ContinuityType discontinuous,
- const int dimension = 0);
-template < class Mesh, class T, class EngineTag > class FieldEngine
-{
-public:enum
- {
- dimensions = Mesh::dimensions
- };
- enum
- {
- Dim = dimensions
- };
- typedef Engine < Dim, T, EngineTag > Engine_t;
- typedef typename Engine_t::Domain_t Domain_t;
- typedef GuardLayers < Dim > GuardLayers_t;
-template < class Layout2 > FieldEngine (const Centering < Dim > &centering, const Layout2 & layout, const Mesh & mesh, int materials = 1):num_materials_m (materials), centering_m (centering),
- stride_m (centering.size ()), physicalCellDomain_m (layout.domain ()),
- guards_m (layout.externalGuards ()), mesh_m (mesh)
- {
- }
- unsigned int num_materials_m;
- Centering < Dim > centering_m;
- int stride_m;
- Domain_t physicalCellDomain_m;
- GuardLayers_t guards_m;
- Mesh mesh_m;
-};
-
-template < class Subject > class SubFieldView;
-template < class Mesh, class T,
- class EngineTag > class SubFieldView < Field < Mesh, T, EngineTag > >
-{
-public:typedef Field < Mesh, T, EngineTag > Type_t;
-};
-
-template < int Dim, class Mesh, class Domain > struct NewMeshTag
-{
- typedef Mesh Type_t;
-};
-template < class Mesh, class T, class EngineTag,
- class Domain > struct View1Implementation <Field < Mesh, T, EngineTag >,
- Domain, false >
-{
- typedef Field < Mesh, T, EngineTag > Subject_t;
- typedef typename Subject_t::Engine_t Engine_t;
- typedef typename NewEngine < Engine_t, Domain >::Type_t NewEngine_t;
- typedef typename NewEngine_t::Element_t NewT_t;
- typedef typename NewEngine_t::Tag_t NewEngineTag_t;
- typedef typename NewMeshTag < NewEngine_t::dimensions, Mesh,
- Domain >::Type_t NewMeshTag_t;
- typedef Field < NewMeshTag_t, NewT_t, NewEngineTag_t > Type_t;
-};
-template < class Mesh, class T, class EngineTag,
- class Sub1 > struct View1 <Field < Mesh, T, EngineTag >, Sub1 >
-{
- typedef Field < Mesh, T, EngineTag > Subject_t;
- typedef typename Subject_t::Domain_t Domain_t;
- typedef TemporaryNewDomain1 < Domain_t, Sub1 > NewDomain_t;
- typedef typename NewDomain_t::SliceType_t SDomain_t;
- enum
- {
- sv = DomainTraits < SDomain_t >::singleValued
- };
- typedef View1Implementation < Subject_t, SDomain_t, sv > Dispatch_t;
- typedef typename Dispatch_t::Type_t Type_t;
-};
-template < class Mesh, class T = double, class EngineTag = Brick > class Field {
-public:typedef Mesh MeshTag_t;
- typedef Mesh Mesh_t;
- typedef Field < Mesh, T, EngineTag > This_t;
- typedef FieldEngine < Mesh, T, EngineTag > FieldEngine_t;
- enum
- {
- dimensions = FieldEngine_t::dimensions
- };
- typedef Engine < dimensions, T, EngineTag > Engine_t;
- typedef typename Engine_t::Domain_t Domain_t;
- typedef Centering < dimensions > Centering_t;
- template < class Layout2 > Field (const Centering_t & centering,
- const Layout2 & layout,
- const Mesh_t &
- mesh):fieldEngine_m (centering, layout,
- mesh)
- {
- }
- inline typename SubFieldView < This_t >::Type_t center (int c) const
- {
- }
- inline typename View1 < This_t, Domain_t >::Type_t all () const
- {
- }
- template < class T1 > const This_t & operator= (const T1 & rhs) const
- {
- }
-private: FieldEngine_t fieldEngine_m;
-};
-
-struct UniformRectilinearTag
-{
-};
-struct CartesianTag
-{
-};
-template < class MeshTraits > struct CartesianURM;
-template < class MeshTraits > class UniformRectilinearMeshData;
-template < class MeshTraits > class UniformRectilinearMesh;
-template < int Dim, typename T = double, class MeshTag =
- UniformRectilinearTag, class CoordinateSystemTag = CartesianTag, int CDim =
- Dim > struct MeshTraits;
-template < int Dim, typename T, class MeshTag, class CoordinateSystemTag,
- int CDim > struct MeshTraitsBase
-{
- typedef MeshTraits < Dim, T, MeshTag, CoordinateSystemTag,
- CDim > MeshTraits_t;
- enum
- {
- dimensions = Dim
- };
- typedef Vector < CDim, T > PointType_t;
-};
-template < int Dim, typename T, int CDim > struct MeshTraits <Dim, T,
- UniformRectilinearTag, CartesianTag, CDim >:public MeshTraitsBase < Dim, T,
- UniformRectilinearTag, CartesianTag, CDim >
-{
- typedef typename MeshTraitsBase < Dim, T, UniformRectilinearTag,
- CartesianTag, CDim >::MeshTraits_t MeshTraits_t;
- typedef CartesianURM < MeshTraits_t > CoordinateSystem_t;
- typedef UniformRectilinearMeshData < MeshTraits_t > MeshData_t;
- typedef UniformRectilinearMesh < MeshTraits_t > Mesh_t;
- typedef Vector < CDim, T > SpacingsType_t;
-};
-template < int Dim > class NoMeshData:public RefCounted
-{
-public:NoMeshData ()
- {
- }
- template < class Layout >
- explicit NoMeshData (const Layout &
- layout):physicalVertexDomain_m (layout.
- innerDomain ()),
- physicalCellDomain_m (shrinkRight (physicalVertexDomain_m, 1)),
- totalVertexDomain_m (layout.domain ()),
- totalCellDomain_m (shrinkRight (totalVertexDomain_m, 1))
- {
- }
-private:Interval < Dim > physicalVertexDomain_m, physicalCellDomain_m;
- Interval < Dim > totalVertexDomain_m, totalCellDomain_m;
-};
-
-template < class MeshTraits > class UniformRectilinearMeshData:public NoMeshData <
- MeshTraits::
- dimensions >
-{
-public:typedef typename
- MeshTraits::MeshData_t
- MeshData_t;
- typedef typename
- MeshTraits::PointType_t
- PointType_t;
- typedef typename
- MeshTraits::SpacingsType_t
- SpacingsType_t;
- enum
- {
- dimensions = MeshTraits::dimensions
- };
- template < class Layout > UniformRectilinearMeshData (const Layout & layout,
- const PointType_t &
- origin,
- const SpacingsType_t &
- spacings):
- NoMeshData <
- dimensions > (layout),
- origin_m (origin),
- spacings_m (spacings)
- {
- }
-private:PointType_t origin_m;
- SpacingsType_t
- spacings_m;
-};
-
-template < class MeshTraits > class UniformRectilinearMesh:public MeshTraits::
- CoordinateSystem_t
-{
-public:typedef MeshTraits
- MeshTraits_t;
- typedef typename
- MeshTraits::MeshData_t
- MeshData_t;
- typedef typename
- MeshTraits::PointType_t
- PointType_t;
- typedef typename
- MeshTraits::SpacingsType_t
- SpacingsType_t;
- enum
- {
- dimensions = MeshTraits::dimensions
- };
- template < class Layout >
- inline UniformRectilinearMesh (const Layout & layout,
- const PointType_t & origin,
- const SpacingsType_t & spacings):
- data_m (new MeshData_t (layout, origin, spacings))
- {
- }
-private:RefCountedPtr < MeshData_t > data_m;
-};
-
-template < class MeshTraits > struct GenericURM
-{
-};
-template < class MeshTraits > struct CartesianURM:
- public
- GenericURM <
- MeshTraits >
-{
-};
-template < int
- dim,
- class
- MeshTag = UniformRectilinearTag, class CoordinateSystemTag = CartesianTag > struct ParallelTraits {
- enum
- {
- Dim = dim
- };
- typedef
- GridLayout <
- dim >
- Layout_t;
- typedef
- MeshTraits <
- dim, double,
- MeshTag,
- CoordinateSystemTag >
- MeshTraits_t;
- typedef typename
- MeshTraits_t::Mesh_t
- Mesh_t;
- typedef
- MultiPatch <
- GridTag,
- Remote <
- Brick > >
- Engine_t;
-};
-template < class ComputeTraits > struct RhalkTraits:
- public
- ComputeTraits
-{
- typedef typename
- ComputeTraits::Mesh_t
- Mesh_t;
- typedef typename
- ComputeTraits::Engine_t
- Engine_t;
- enum
- {
- Dim = ComputeTraits::Dim
- };
- typedef
- Centering <
- Dim >
- Centering_t;
- typedef typename
- Mesh_t::SpacingsType_t
- Spacings_t;
- typedef
- Field <
- Mesh_t, double,
- Engine_t >
- Scalar_t;
-};
-enum
-{
- Dim = 3
-};
-typedef
- RhalkTraits <
- ParallelTraits <
- Dim,
- UniformRectilinearTag,
-CartesianTag > >
- Traits_t;
-Vector < Dim > origin;
-Traits_t::Spacings_t spacings;
-int
-main (int argc, char **argv)
-{
- Traits_t::Layout_t layout;
- Traits_t::Mesh_t mesh (layout, origin, spacings);
- Traits_t::Centering_t face =
- canonicalCentering < Traits_t::Dim > (FaceType, Continuous);
- Traits_t::Scalar_t v (face, layout, mesh);
- for (int i = 0; i < Dim; ++i)
- v.center (i).all () = std::numeric_limits < double >::signaling_NaN ();
-}
diff --git a/test/FrontendC++/2009-02-07-VolatileArrayRefHack.cpp b/test/FrontendC++/2009-02-07-VolatileArrayRefHack.cpp
deleted file mode 100644
index b8589b0..0000000
--- a/test/FrontendC++/2009-02-07-VolatileArrayRefHack.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | grep {volatile load}
-// PR3320
-
-void test(volatile int *a) {
- // should be a volatile load.
- a[0];
-}
diff --git a/test/FrontendC++/2009-02-16-CtorNames-dbg.cpp b/test/FrontendC++/2009-02-16-CtorNames-dbg.cpp
deleted file mode 100644
index eb69963..0000000
--- a/test/FrontendC++/2009-02-16-CtorNames-dbg.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S -g %s -o - | grep "\~A"
-class A {
- int i;
-public:
- A() { i = 0; }
- ~A() { i = 42; }
-};
-
-A a;
-
diff --git a/test/FrontendC++/2009-03-17-dbg.cpp b/test/FrontendC++/2009-03-17-dbg.cpp
deleted file mode 100644
index 6708e12..0000000
--- a/test/FrontendC++/2009-03-17-dbg.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgxx -S %s -o /dev/null -g
-// XTARGET: darwin,linux
-// XFAIL: *
-template <typename T1,typename T2>
-inline void f(const T1&,const T2&) { }
-
-template <typename T1,typename T2,void F(const T1&,const T2&)>
-struct A {
- template <typename T> void g(T& i) { }
-};
-
-int main() {
- int i;
- A<int,int,f> a;
- a.g(i);
-}
diff --git a/test/FrontendC++/2009-04-21-DtorNames-dbg.cpp b/test/FrontendC++/2009-04-21-DtorNames-dbg.cpp
deleted file mode 100644
index da09c0b..0000000
--- a/test/FrontendC++/2009-04-21-DtorNames-dbg.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// RUN: %llvmgcc -S -g %s -o - | llc --disable-cfi -O0 -o %t.s
-// RUN: %compile_c %t.s -o %t.o
-// PR4025
-
-template <typename _Tp> class vector
-{
-public:
- ~vector ()
- {
- }
-};
-
-class Foo
-{
- ~Foo();
- class FooImpl *impl_;
-};
-
-namespace {
- class Bar;
-}
-
-class FooImpl
-{
- vector<Bar*> thing;
-};
-
-Foo::~Foo()
-{
- delete impl_;
-}
-
diff --git a/test/FrontendC++/2009-04-23-bool2.cpp b/test/FrontendC++/2009-04-23-bool2.cpp
deleted file mode 100644
index 2c76d98..0000000
--- a/test/FrontendC++/2009-04-23-bool2.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgxx -S %s -o /dev/null
-// g++.old-deja/g++.jason/bool2.C from gcc testsuite.
-// Crashed before 67975 went in.
-struct F {
- bool b1 : 1;
- bool b2 : 7;
-};
-
-int main()
-{
- F f = { true, true };
-
- if (int (f.b1) != 1)
- return 1;
-}
diff --git a/test/FrontendC++/2009-05-04-PureConstNounwind.cpp b/test/FrontendC++/2009-05-04-PureConstNounwind.cpp
deleted file mode 100644
index e275c34..0000000
--- a/test/FrontendC++/2009-05-04-PureConstNounwind.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | grep nounwind | count 4
-int c(void) __attribute__((const));
-int p(void) __attribute__((pure));
-int t(void);
-
-int f(void) {
- return c() + p() + t();
-}
diff --git a/test/FrontendC++/2009-06-16-DebugInfoCrash.cpp b/test/FrontendC++/2009-06-16-DebugInfoCrash.cpp
deleted file mode 100644
index c2a841b..0000000
--- a/test/FrontendC++/2009-06-16-DebugInfoCrash.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgxx -S %s -o /dev/null -g
-// This crashes if we try to emit debug info for TEMPLATE_DECL members.
-template <class T> class K2PtrVectorBase {};
-template <class T> class K2Vector {};
-template <class U > class K2Vector<U*> : public K2PtrVectorBase<U*> {};
-class ScriptInfoManager {
- void PostRegister() ;
- template <class SI> short ReplaceExistingElement(K2Vector<SI*>& v);
-};
-void ScriptInfoManager::PostRegister() {}
diff --git a/test/FrontendC++/2009-06-20-DarwinPPCLayout.cpp b/test/FrontendC++/2009-06-20-DarwinPPCLayout.cpp
deleted file mode 100644
index e0bc043..0000000
--- a/test/FrontendC++/2009-06-20-DarwinPPCLayout.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// RUN: %llvmgxx -S -m32 %s -o - | grep baz | grep global | grep {struct.bar}
-// RUN: %llvmgxx -S -m32 %s -o - | grep ccc | grep global | grep {struct.CC}
-// RUN: %llvmgxx -S -m32 %s -o - | grep quux | grep global | grep {struct.bar}
-// RUN: %llvmgxx -S -m32 %s -o - | grep foo | grep global | grep {struct.SRCFilter::FilterEntry}
-// RUN: %llvmgxx -S -m32 %s -o - | grep {struct.bar} | grep {1 x i32}
-// RUN: %llvmgxx -S -m32 %s -o - | grep {struct.CC} | grep {struct.payre<KBFP,float*} | grep {.base.32} | grep {1 x i32}
-// RUN: %llvmgxx -S -m32 %s -o - | grep {struct.SRCFilter::FilterEntry} | not grep {1 x i32}
-// XFAIL: *
-// XTARGET: powerpc-apple-darwin
-
-template<class _T1, class _T2> struct payre {
- _T1 first;
- _T2 second;
- payre() : first(), second() { }
-};
-struct KBFP {
- double mCutoffFrequency;
-};
-class SRCFilter {
- struct FilterEntry: public payre<KBFP, float*>{};
- static FilterEntry foo;
-};
-SRCFilter::FilterEntry SRCFilter::foo; // 12 bytes
-payre<KBFP, float*> baz; // 16 bytes
-class CC { // 16 bytes
- public: payre<KBFP, float*> x;
-};
-class CC ccc;
-
-struct bar { KBFP x; float* y;}; // 16 bytes
-struct bar quux;
-
diff --git a/test/FrontendC++/2009-06-30-ByrefBlock.cpp b/test/FrontendC++/2009-06-30-ByrefBlock.cpp
deleted file mode 100644
index be9c94f..0000000
--- a/test/FrontendC++/2009-06-30-ByrefBlock.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-// Insure __block_holder_tmp is allocated on the stack. Darwin only.
-// RUN: %llvmgxx %s -S -O2 -o - | egrep {__block_holder_tmp.*alloca}
-// XFAIL: *
-// XTARGET: darwin
-// <rdar://problem/5865221>
-// END.
-extern void fubar_dispatch_sync(void (^PP)(void));
-void fubar() {
- __block void *voodoo;
- fubar_dispatch_sync(^(void){voodoo=0;});
-}
diff --git a/test/FrontendC++/2009-07-16-PrivateCopyConstructor.cpp b/test/FrontendC++/2009-07-16-PrivateCopyConstructor.cpp
deleted file mode 100644
index 96e85b2..0000000
--- a/test/FrontendC++/2009-07-16-PrivateCopyConstructor.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgxx %s -S
-// XFAIL: darwin
-
-#include <set>
-
-class A {
-public:
- A();
-private:
- A(const A&);
-};
-void B()
-{
- std::set<void *, A> foo;
-}
diff --git a/test/FrontendC++/2009-07-16-Using.cpp b/test/FrontendC++/2009-07-16-Using.cpp
deleted file mode 100644
index c0e0314..0000000
--- a/test/FrontendC++/2009-07-16-Using.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgxx %s -S -o /dev/null
-
-namespace A {
- typedef int B;
-}
-struct B {
-};
-using ::A::B;
diff --git a/test/FrontendC++/2009-08-05-ZeroInitWidth.cpp b/test/FrontendC++/2009-08-05-ZeroInitWidth.cpp
deleted file mode 100644
index 89a79f2..0000000
--- a/test/FrontendC++/2009-08-05-ZeroInitWidth.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgxx -S %s -o -
-// rdar://7114564
-struct A {
- unsigned long long : (sizeof(unsigned long long) * 8) - 16;
-};
-struct B {
- A a;
-};
-struct B b = {
- {}
-};
-
diff --git a/test/FrontendC++/2009-08-11-VectorRetTy.cpp b/test/FrontendC++/2009-08-11-VectorRetTy.cpp
deleted file mode 100644
index 403b59d..0000000
--- a/test/FrontendC++/2009-08-11-VectorRetTy.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgxx %s -S -o /dev/null
-// <rdar://problem/7096460>
-typedef void (*Func) ();
-typedef long long m64 __attribute__((__vector_size__(8), __may_alias__));
-static inline m64 __attribute__((__always_inline__, __nodebug__)) _mm_set1_pi16() {}
-template <class MM>
-static void Bork() {
- const m64 mmx_0x00ff = _mm_set1_pi16();
-}
-struct A {};
-Func arr[] = {
- Bork<A>
-};
diff --git a/test/FrontendC++/2009-09-04-modify-crash.cpp b/test/FrontendC++/2009-09-04-modify-crash.cpp
deleted file mode 100644
index 89274e0..0000000
--- a/test/FrontendC++/2009-09-04-modify-crash.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgxx %s -fapple-kext -S -o -
-// The extra check in 71555 caused this to crash on Darwin X86
-// in an assert build.
-class foo {
- virtual ~foo ();
-};
-foo::~foo(){}
diff --git a/test/FrontendC++/2009-09-09-packed-layout.cpp b/test/FrontendC++/2009-09-09-packed-layout.cpp
deleted file mode 100644
index 921aad7..0000000
--- a/test/FrontendC++/2009-09-09-packed-layout.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgxx -S -m32 %s -o /dev/null
-class X {
- public:
- virtual ~X();
- short y;
-};
-#pragma pack(push, 1)
-class Z : public X {
- public: enum { foo = ('x') };
- virtual int y() const;
-};
-#pragma pack(pop)
-class Y : public X {
-public: enum { foo = ('y'), bar = 0 };
-};
-X x;
-Y y;
-Z z;
diff --git a/test/FrontendC++/2009-10-27-crash.cpp b/test/FrontendC++/2009-10-27-crash.cpp
deleted file mode 100644
index da73988..0000000
--- a/test/FrontendC++/2009-10-27-crash.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// RUN: %llvmgxx -S %s -o /dev/null
-// Radar 7328944
-
-typedef struct
-{
- unsigned short a : 1;
- unsigned short b : 2;
- unsigned short c : 1;
- unsigned short d : 1;
- unsigned short e : 1;
- unsigned short f : 1;
- unsigned short g : 2;
- unsigned short : 7;
- union
- {
- struct
- {
- unsigned char h : 1;
- unsigned char i : 1;
- unsigned char j : 1;
- unsigned char : 5;
- };
- struct
- {
- unsigned char k : 3;
- unsigned char : 5;
- };
- };
- unsigned char : 8;
-} tt;
-
-typedef struct
-{
- unsigned char s;
- tt t;
- unsigned int u;
-} ttt;
-
-ttt X = {
- 4,
- { 0 },
- 55,
-};
diff --git a/test/FrontendC++/2009-12-23-MissingSext.cpp b/test/FrontendC++/2009-12-23-MissingSext.cpp
deleted file mode 100644
index ee97881..0000000
--- a/test/FrontendC++/2009-12-23-MissingSext.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgxx %s -S -o - | FileCheck %s
-// The store of p.y into the temporary was not
-// getting extended to 32 bits, so uninitialized
-// bits of the temporary were used. 7366161.
-struct foo {
- char x:8;
- signed int y:24;
-};
-int bar(struct foo p, int x) {
-// CHECK: bar
-// CHECK: sext
-// CHECK: sext
- x = (p.y > x ? x : p.y);
- return x;
-// CHECK: return
-}
diff --git a/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp b/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp
deleted file mode 100644
index ff45412..0000000
--- a/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc -g -S %s -o - | FileCheck %s
-// Here, second to last argument "i32 64" indicates that artificial type is set.
-// Test to artificial attribute attahed to "this" pointer type.
-// Radar 7655792 and 7655002
-
-class A {
-public:
- int fn1(int i) const { return i + 2; };
-};
-
-int foo() {
- A a;
- // Matching "i32 64, metadata !<number>} ; [ DW_TAG_pointer_type ]"
- // CHECK: i32 64, metadata {{![0-9]+\} ; \[ DW_TAG_pointer_type \]}}
- return a.fn1(1);
-}
diff --git a/test/FrontendC++/2010-03-22-empty-baseclass.cpp b/test/FrontendC++/2010-03-22-empty-baseclass.cpp
deleted file mode 100644
index bb741c4..0000000
--- a/test/FrontendC++/2010-03-22-empty-baseclass.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-// RUN: %llvmgxx -S %s -o - -O2 | FileCheck %s
-namespace boost {
- namespace detail {
- template <typename T> struct cv_traits_imp {};
- template <typename T> struct cv_traits_imp<T*> {typedef T unqualified_type;};
- }
-}
-namespace mpl_ {}
-namespace boost {
- namespace mpl {using namespace mpl_;}
- template< typename T > struct remove_cv {typedef typename boost::detail::cv_traits_imp<T*>::unqualified_type type;};
- namespace type_traits {
- typedef char yes_type;
- struct no_type {char padding[8];};
- }
-}
-namespace mpl_ {
- template< bool C_ > struct bool_;
- typedef bool_<true> true_;
- typedef bool_<false> false_;
- template< bool C_ > struct bool_ {static const bool value = C_;};
- template< typename T, T N > struct integral_c;
-}
-namespace boost{
- template <class T, T val> struct integral_constant :
- public mpl::integral_c<T, val> {};
- template<> struct integral_constant<bool,true> : public mpl::true_ {};
- template<> struct integral_constant<bool,false> : public mpl::false_ {};
- namespace type_traits {
- template <bool b1, bool b2, bool b3 = false, bool b4 = false,
- bool b5 = false, bool b6 = false, bool b7 = false> struct ice_or;
- template <bool b1, bool b2, bool b3, bool b4, bool b5, bool b6, bool b7>
- struct ice_or {static const bool value = true; };
- template <> struct ice_or<false, false, false, false, false, false, false>
- {static const bool value = false;};
- template <bool b1, bool b2, bool b3 = true, bool b4 = true, bool b5 = true,
- bool b6 = true, bool b7 = true> struct ice_and;
- template <bool b1, bool b2, bool b3, bool b4, bool b5, bool b6, bool b7>
- struct ice_and {static const bool value = false;};
- template <> struct ice_and<true, true, true, true, true, true, true>
- {static const bool value = true;};
- template <bool b> struct ice_not {static const bool value = true;};
- };
- namespace detail {
- template <typename T> struct is_union_impl {static const bool value = false;};
- }
- template< typename T > struct is_union :
- ::boost::integral_constant<bool, ::boost::detail::is_union_impl<T>::value> {};
- namespace detail {
- template <class U> ::boost::type_traits::yes_type is_class_tester(void(U::*)(void));
- template <class U> ::boost::type_traits::no_type is_class_tester(...);
- template <typename T> struct is_class_impl {
- static const bool value = (::boost::type_traits::ice_and< sizeof(is_class_tester<T>(0))
- == sizeof(::boost::type_traits::yes_type),
- ::boost::type_traits::ice_not< ::boost::is_union<T>::value >::value >::value);};
-}
- template<typename T> struct is_class:
- ::boost::integral_constant<bool,::boost::detail::is_class_impl<T>::value> { };
-namespace detail {
- template <typename T> struct empty_helper_t1: public T {int i[256];};
- struct empty_helper_t2 {int i[256];};
- template <typename T, bool is_a_class = false> struct empty_helper
- {static const bool value = false;};
- template <typename T> struct empty_helper<T, true>
- {static const bool value = (sizeof(empty_helper_t1<T>) == sizeof(empty_helper_t2));};
- template <typename T> struct is_empty_impl {
- typedef typename remove_cv<T>::type cvt;
- static const bool value = (::boost::type_traits::ice_or< ::boost::detail::empty_helper
- <cvt,::boost::is_class<T>::value>::value, false>::value);
- };
-}
-template<typename T> struct is_empty:
-::boost::integral_constant<bool,::boost::detail::is_empty_impl<T>::value> {};
-template<typename T, typename U > struct is_same:
-::boost::integral_constant<bool,false> {};
-template<typename T> struct call_traits {typedef T& reference;};
-namespace details {
- template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
- struct compressed_pair_switch;
- template <class T1, class T2>
- struct compressed_pair_switch<T1, T2, false, true, false>
- {static const int value = 1;};
- template <class T1, class T2, int Version> class compressed_pair_imp;
- template <class T1, class T2> class compressed_pair_imp<T1, T2, 1>:
- protected ::boost::remove_cv<T1>::type {
- public:
- typedef T1 first_type;
- typedef T2 second_type;
- typedef typename call_traits<first_type>::reference first_reference;
- typedef typename call_traits<second_type>::reference second_reference;
- first_reference first() {return *this;}
- second_reference second() {return second_;}
- second_type second_;
- };
-}
-template <class T1, class T2> class compressed_pair:
- private ::boost::details::compressed_pair_imp<T1, T2, ::boost::details::compressed_pair_switch<
- T1, T2, ::boost::is_same<typename remove_cv<T1>::type,
- typename remove_cv<T2>::type>::value,
- ::boost::is_empty<T1>::value, ::boost::is_empty<T2>::value>::value>
- {
- private:
- typedef details::compressed_pair_imp<T1, T2, ::boost::details::compressed_pair_switch<
- T1, T2, ::boost::is_same<typename remove_cv<T1>::type,
- typename remove_cv<T2>::type>::value,
- ::boost::is_empty<T1>::value, ::boost::is_empty<T2>::value>::value> base;
- public:
- typedef T1 first_type;
- typedef T2 second_type;
- typedef typename call_traits<first_type>::reference first_reference;
- typedef typename call_traits<second_type>::reference second_reference;
- first_reference first() {return base::first();}
- second_reference second() {return base::second();}
- };
-}
-struct empty_base_t {};
-struct empty_t : empty_base_t {};
-typedef boost::compressed_pair<empty_t, int> data_t;
-extern "C" {int printf(const char * , ...);}
-extern "C" {void abort(void);}
-int main (int argc, char * const argv[]) {
- data_t x;
- x.second() = -3;
- // This store should be elided:
- x.first() = empty_t();
- // If x.second() has been clobbered by the elided store, fail.
- if (x.second() != -3) {
- printf("x.second() was clobbered\n");
- // CHECK-NOT: x.second() was clobbered
- abort();
- }
- return 0;
-}
-// CHECK: ret i32
diff --git a/test/FrontendC++/2010-04-30-OptimizedMethod-Dbg.cpp b/test/FrontendC++/2010-04-30-OptimizedMethod-Dbg.cpp
deleted file mode 100644
index 761c0dc..0000000
--- a/test/FrontendC++/2010-04-30-OptimizedMethod-Dbg.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -g -S -O2 %s -o - | FileCheck %s
-
-class foo {
-public:
- int bar(int x);
- static int baz(int x);
-};
-
-int foo::bar(int x) {
- // CHECK: {{i32 [0-9]+, i1 true(, i[0-9]+ [^\}]+[}]|[}]) ; \[ DW_TAG_subprogram \]}}
- return x*4 + 1;
-}
-
-int foo::baz(int x) {
- // CHECK: {{i32 [0-9]+, i1 true(, i[0-9]+ [^\},]+[}]|[}]) ; \[ DW_TAG_subprogram \]}}
- return x*4 + 1;
-}
-
diff --git a/test/FrontendC++/2010-05-10-Var-DbgInfo.cpp b/test/FrontendC++/2010-05-10-Var-DbgInfo.cpp
deleted file mode 100644
index e6165c0..0000000
--- a/test/FrontendC++/2010-05-10-Var-DbgInfo.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// RUN: %llvmgcc -S -O0 -g %s -o /dev/null
-// PR 7104
-
-struct A {
- int Ai;
-};
-
-struct B : public A {};
-struct C : public B {};
-
-const char * f(int C::*){ return ""; }
-int f(int B::*) { return 1; }
-
-struct D : public C {};
-
-const char * g(int B::*){ return ""; }
-int g(int D::*) { return 1; }
-
-void test()
-{
- int i = f(&A::Ai);
-
- const char * str = g(&A::Ai);
-}
-
-// conversion of B::* to C::* is better than conversion of A::* to C::*
-typedef void (A::*pmfa)();
-typedef void (B::*pmfb)();
-typedef void (C::*pmfc)();
-
-struct X {
- operator pmfa();
- operator pmfb();
-};
-
-
-void g(pmfc);
-
-void test2(X x)
-{
- g(x);
-}
-
diff --git a/test/FrontendC++/2010-05-11-alwaysinlineinstantiation.cpp b/test/FrontendC++/2010-05-11-alwaysinlineinstantiation.cpp
deleted file mode 100644
index 9203dbd..0000000
--- a/test/FrontendC++/2010-05-11-alwaysinlineinstantiation.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-// RUN: %llvmgxx -xc++ %s -S -o - | not grep ZN12basic_stringIcEC1Ev
-// RUN: %llvmgxx -xc++ %s -S -o - | grep ZN12basic_stringIcED1Ev | count 2
-
-template<class charT>
-class basic_string
-{
-public:
- basic_string();
- ~basic_string();
-};
-
-template <class charT>
-__attribute__ ((__visibility__("hidden"), __always_inline__)) inline
-basic_string<charT>::basic_string()
-{
-}
-
-template <class charT>
-inline
-basic_string<charT>::~basic_string()
-{
-}
-
-typedef basic_string<char> string;
-
-extern template class basic_string<char>;
-
-int main()
-{
- string s;
-}
diff --git a/test/FrontendC++/2010-05-12-PtrToMember-Dbg.cpp b/test/FrontendC++/2010-05-12-PtrToMember-Dbg.cpp
deleted file mode 100644
index c2d6abe..0000000
--- a/test/FrontendC++/2010-05-12-PtrToMember-Dbg.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-//RUN: %llvmgxx -O0 -S -g -o - %s | grep DW_TAG_auto_variable
-class Foo
-{
- public:
- int x;
- int y;
- Foo (int i, int j) { x = i; y = j; }
-};
-
-
-Foo foo(10, 11);
-
-int main() {
- int Foo::* pmi = &Foo::y;
- return foo.*pmi;
-}
-
diff --git a/test/FrontendC++/2010-06-21-LocalVarDbg.cpp b/test/FrontendC++/2010-06-21-LocalVarDbg.cpp
deleted file mode 100644
index 48d8215..0000000
--- a/test/FrontendC++/2010-06-21-LocalVarDbg.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgxx -g -Os -S %s -o - | llvm-as -disable-output
-// Do not use function name to create named metadata used to hold
-// local variable info. For example. llvm.dbg.lv.~A is an invalid name.
-class A {
-public:
- ~A() { int i = 0; i++; }
-};
-
-int foo(int i) {
- A a;
- return 0;
-}
-
diff --git a/test/FrontendC++/2010-06-22-BitfieldInit.cpp b/test/FrontendC++/2010-06-22-BitfieldInit.cpp
deleted file mode 100644
index 8dceb78..0000000
--- a/test/FrontendC++/2010-06-22-BitfieldInit.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: %llvmgxx -g -S %s
-struct TEST2
-{
- int subid:32;
- int :0;
-};
-
-typedef struct _TEST3
-{
- TEST2 foo;
- TEST2 foo2;
-} TEST3;
-
-TEST3 test =
- {
- {0},
- {0}
- };
-
-int main() { return 0; }
diff --git a/test/FrontendC++/2010-06-22-ZeroBitfield.cpp b/test/FrontendC++/2010-06-22-ZeroBitfield.cpp
deleted file mode 100644
index 9c4f262..0000000
--- a/test/FrontendC++/2010-06-22-ZeroBitfield.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgxx -g -S %s
-struct s8_0 { unsigned : 0; };
-struct s8_1 { double x; };
-struct s8 { s8_0 a; s8_1 b; };
-s8 f8() { return s8(); }
diff --git a/test/FrontendC++/2010-07-19-nowarn.cpp b/test/FrontendC++/2010-07-19-nowarn.cpp
deleted file mode 100644
index a61a84f..0000000
--- a/test/FrontendC++/2010-07-19-nowarn.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %llvmgcc %s -S -m32 -fasm-blocks -o /dev/null
-// This should not warn about unreferenced label. 8195660.
-// XFAIL: *
-// XTARGET: x86,i386,i686
-
-void quarterAsm(int array[], int len)
-{
- __asm
- {
- mov esi, array;
- mov ecx, len;
- shr ecx, 2;
-loop:
- movdqa xmm0, [esi];
- psrad xmm0, 2;
- movdqa [esi], xmm0;
- add esi, 16;
- sub ecx, 1;
- jnz loop;
- }
-}
diff --git a/test/FrontendC++/2010-07-23-DeclLoc.cpp b/test/FrontendC++/2010-07-23-DeclLoc.cpp
deleted file mode 100644
index 9bf432b..0000000
--- a/test/FrontendC++/2010-07-23-DeclLoc.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-// RUN: %llvmgxx -S -g %s -o - | FileCheck %s
-// Require the template function declaration refer to the correct filename.
-// First, locate the function decl in metadata, and pluck out the file handle:
-// CHECK: {{extract_dwarf_data_from_header.*extract_dwarf_data_from_header.*extract_dwarf_data_from_header.*[^ ]+", metadata !}}[[filehandle:[0-9]+]],
-// Second: Require that filehandle refer to the correct filename:
-// CHECK: {{^!}}[[filehandle]] = metadata {{![{].*}} metadata !"decl_should_be_here.hpp",
-typedef long unsigned int __darwin_size_t;
-typedef __darwin_size_t size_t;
-typedef unsigned char uint8_t;
-typedef unsigned int uint32_t;
-typedef unsigned long long uint64_t;
-namespace std {
- template<typename _Tp> class auto_ptr {
- _Tp* _M_ptr;
- public:
- typedef _Tp element_type;
- auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }
- element_type& operator*() const throw() { }
- };
-}
-class Pointer32 {
-public:
- typedef uint32_t ptr_t;
- typedef uint32_t size_t;
-};
-class Pointer64 {
-public:
- typedef uint64_t ptr_t;
- typedef uint64_t size_t;
-};
-class BigEndian {};
-class LittleEndian {};
-template <typename _SIZE, typename _ENDIANNESS> class SizeAndEndianness {
-public:
- typedef _SIZE SIZE;
-};
-typedef SizeAndEndianness<Pointer32, LittleEndian> ISA32Little;
-typedef SizeAndEndianness<Pointer32, BigEndian> ISA32Big;
-typedef SizeAndEndianness<Pointer64, LittleEndian> ISA64Little;
-typedef SizeAndEndianness<Pointer64, BigEndian> ISA64Big;
-template <typename SIZE> class TRange {
-protected:
- typename SIZE::ptr_t _location;
- typename SIZE::size_t _length;
- TRange(typename SIZE::ptr_t location, typename SIZE::size_t length) : _location(location), _length(length) { }
-};
-template <typename SIZE, typename T> class TRangeValue : public TRange<SIZE> {
- T _value;
-public:
- TRangeValue(typename SIZE::ptr_t location, typename SIZE::size_t length, T value) : TRange<SIZE>(location, length), _value(value) {};
-};
-template <typename SIZE> class TAddressRelocator {};
-class CSCppSymbolOwner{};
-class CSCppSymbolOwnerData{};
-template <typename SIZE> class TRawSymbolOwnerData
-{
- TRangeValue< SIZE, uint8_t* > _TEXT_text_section;
- const char* _dsym_path;
- uint32_t _dylib_current_version;
- uint32_t _dylib_compatibility_version;
-public:
- TRawSymbolOwnerData() :
- _TEXT_text_section(0, 0, __null), _dsym_path(__null), _dylib_current_version(0), _dylib_compatibility_version(0) {}
-};
-template <typename SIZE_AND_ENDIANNESS> class TExtendedMachOHeader {};
-# 16 "decl_should_be_here.hpp"
-template <typename SIZE_AND_ENDIANNESS> void extract_dwarf_data_from_header(TExtendedMachOHeader<SIZE_AND_ENDIANNESS>& header,
- TRawSymbolOwnerData<typename SIZE_AND_ENDIANNESS::SIZE>& symbol_owner_data,
- TAddressRelocator<typename SIZE_AND_ENDIANNESS::SIZE>* address_relocator) {}
-struct CSCppSymbolOwnerHashFunctor {
- size_t operator()(const CSCppSymbolOwner& symbol_owner) const {
-# 97 "wrong_place_for_decl.cpp"
- }
-};
-template <typename SIZE_AND_ENDIANNESS> CSCppSymbolOwnerData* create_symbol_owner_data_arch_specific(CSCppSymbolOwner* symbol_owner, const char* dsym_path) {
- typedef typename SIZE_AND_ENDIANNESS::SIZE SIZE;
- std::auto_ptr< TRawSymbolOwnerData<SIZE> > data(new TRawSymbolOwnerData<SIZE>());
- std::auto_ptr< TExtendedMachOHeader<SIZE_AND_ENDIANNESS> > header;
- extract_dwarf_data_from_header(*header, *data, (TAddressRelocator<typename SIZE_AND_ENDIANNESS::SIZE>*)__null);
-}
-CSCppSymbolOwnerData* create_symbol_owner_data2(CSCppSymbolOwner* symbol_owner, const char* dsym_path) {
- create_symbol_owner_data_arch_specific< ISA32Little >(symbol_owner, dsym_path);
- create_symbol_owner_data_arch_specific< ISA32Big >(symbol_owner, dsym_path);
- create_symbol_owner_data_arch_specific< ISA64Little >(symbol_owner, dsym_path);
- create_symbol_owner_data_arch_specific< ISA64Big >(symbol_owner, dsym_path);
-}
diff --git a/test/FrontendC++/2010-08-31-ByValArg.cpp b/test/FrontendC++/2010-08-31-ByValArg.cpp
deleted file mode 100644
index 4ccaabd..0000000
--- a/test/FrontendC++/2010-08-31-ByValArg.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// This regression test checks byval arguments' debug info.
-// Radar 8367011
-// RUN: %llvmgcc -S -O0 -g %s -o - | \
-// RUN: llc --disable-cfi --disable-fp-elim -o %t.s -O0 -relocation-model=pic
-// RUN: %compile_c %t.s -o %t.o
-// RUN: %link %t.o -o %t.exe
-// RUN: echo {break get\nrun\np missing_arg.b} > %t.in
-// RUN: gdb -q -batch -n -x %t.in %t.exe | tee %t.out | \
-// RUN: grep {1 = 4242}
-
-// XTARGET: x86_64-apple-darwin
-
-class EVT {
-public:
- int a;
- int b;
- int c;
-};
-
-class VAL {
-public:
- int x;
- int y;
-};
-void foo(EVT e);
-EVT bar();
-
-void get(int *i, unsigned dl, VAL v, VAL *p, unsigned n, EVT missing_arg) {
-//CHECK: .ascii "missing_arg"
- EVT e = bar();
- if (dl == n)
- foo(missing_arg);
-}
-
-
-EVT bar() {
- EVT e;
- return e;
-}
-
-void foo(EVT e) {}
-
-int main(){
- VAL v;
- EVT ma;
- ma.a = 1;
- ma.b = 4242;
- ma.c = 3;
- int i = 42;
- get (&i, 1, v, &v, 2, ma);
- return 0;
-}
-
diff --git a/test/FrontendC++/alignstack.cpp b/test/FrontendC++/alignstack.cpp
deleted file mode 100644
index 4f993d6..0000000
--- a/test/FrontendC++/alignstack.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %llvmgxx %s -fasm-blocks -S -o - | FileCheck %s
-// Complicated expression as jump target
-// XFAIL: *
-// XTARGET: x86,i386,i686,darwin
-
-void Method3()
-{
-// CHECK: Method3
-// CHECK-NOT: alignstack
- asm("foo:");
-// CHECK: return
-}
-
-void Method4()
-{
-// CHECK: Method4
-// CHECK: alignstack
- asm {
- bar:
- }
-// CHECK: return
-}
-
diff --git a/test/FrontendC++/dg.exp b/test/FrontendC++/dg.exp
deleted file mode 100644
index fc852e3..0000000
--- a/test/FrontendC++/dg.exp
+++ /dev/null
@@ -1,5 +0,0 @@
-load_lib llvm.exp
-
-if [ llvm_gcc_supports c++ ] then {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
-}
diff --git a/test/FrontendC++/integration-O2.cpp b/test/FrontendC++/integration-O2.cpp
deleted file mode 100644
index bb65ac2..0000000
--- a/test/FrontendC++/integration-O2.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgxx %s -O2 -S -o - | FileCheck %s
-
-// This test verifies that we get expected codegen out of the -O2 optimization
-// level from the full optimizer.
-
-
-
-// Verify that ipsccp is running and can eliminate globals.
-static int test1g = 42;
-void test1f1() {
- if (test1g == 0) test1g = 0;
-}
-int test1f2() {
- return test1g;
-}
-
-// CHECK: @_Z7test1f2v()
-// CHECK: entry:
-// CHECK-NEXT: ret i32 42
diff --git a/test/FrontendC++/m64-ptr.cpp b/test/FrontendC++/m64-ptr.cpp
deleted file mode 100644
index f91e2f4..0000000
--- a/test/FrontendC++/m64-ptr.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgxx %s -S -o - | FileCheck %s
-// XFAIL: powerpc-apple-darwin
-
-// Make sure pointers are passed as pointers, not converted to int.
-// The first load should be of type i8** in either 32 or 64 bit mode.
-// This formerly happened on x86-64, 7375899.
-
-class StringRef {
-public:
- const char *Data;
- long Len;
-};
-void foo(StringRef X);
-void bar(StringRef &A) {
-// CHECK: @_Z3barR9StringRef
-// CHECK: load i8**
- foo(A);
-// CHECK: ret void
-}
diff --git a/test/FrontendC++/member-alignment.cpp b/test/FrontendC++/member-alignment.cpp
deleted file mode 100644
index c5b20b2..0000000
--- a/test/FrontendC++/member-alignment.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | FileCheck %s
-// XFAIL: arm,powerpc
-
-// rdar://7268289
-
-class t {
-public:
- virtual void foo(void);
- void bar(void);
-};
-
-void
-t::bar(void) {
-// CHECK: _ZN1t3barEv{{.*}} align 2
-}
-
-void
-t::foo(void) {
-// CHECK: _ZN1t3fooEv{{.*}} align 2
-}
diff --git a/test/FrontendC++/ptr-to-method-devirt.cpp b/test/FrontendC++/ptr-to-method-devirt.cpp
deleted file mode 100644
index a5ca5c7..0000000
--- a/test/FrontendC++/ptr-to-method-devirt.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// PR1602
-// RUN: %llvmgxx -S %s -o - -O3 | not grep ptrtoint
-// RUN: %llvmgxx -S %s -o - -O3 | grep getelementptr | count 1
-
-
-struct S { virtual void f(); };
-
-typedef void (S::*P)(void);
-
-const P p = &S::f;
-
-void g(S s) {
- (s.*p)();
- }
diff --git a/test/FrontendC++/thunk-linkonce-odr.cpp b/test/FrontendC++/thunk-linkonce-odr.cpp
deleted file mode 100644
index ad72e64..0000000
--- a/test/FrontendC++/thunk-linkonce-odr.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// RUN: %llvmgxx %s -S -o - | FileCheck %s
-// <rdar://problem/7929157> & <rdar://problem/8104369>
-
-struct A {
- virtual int f() { return 1; }
-};
-
-struct B {
- virtual int f() { return 2; }
-};
-
-struct C : A, B {
- virtual int f() { return 3; }
-};
-
-struct D : C {
- virtual int f() { return 4; }
-};
-
-static int f(D* d) {
- B* b = d;
- return b->f();
-};
-
-int g() {
- D d;
- return f(&d);
-}
-
-// Thunks should be marked as "linkonce ODR" not "weak".
-//
-// CHECK: define linkonce_odr i32 @_ZThn{{[48]}}_N1C1fEv
-// CHECK: define linkonce_odr i32 @_ZThn{{[48]}}_N1D1fEv
diff --git a/test/FrontendC++/varargs.cpp b/test/FrontendC++/varargs.cpp
deleted file mode 100644
index c4de76a..0000000
--- a/test/FrontendC++/varargs.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | FileCheck %s
-// rdar://7309675
-// PR4678
-
-// test1 should be compmiled to be a varargs function in the IR even
-// though there is no way to do a va_begin. Otherwise, the optimizer
-// will warn about 'dropped arguments' at the call site.
-
-// CHECK: define i32 @_Z5test1z(...)
-int test1(...) {
- return -1;
-}
-
-// CHECK: call i32 (...)* @_Z5test1z(i32 0)
-void test() {
- test1(0);
-}
-
-
diff --git a/test/FrontendC++/weak-external.cpp b/test/FrontendC++/weak-external.cpp
deleted file mode 100644
index f4f0ba1..0000000
--- a/test/FrontendC++/weak-external.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgxx %s -S -O2 -o - | not grep {_ZNSs12_S_constructIPKcEEPcT_S3_RKSaIcESt20forward_iterator_tag}
-// PR4262
-
-// The "basic_string" extern template instantiation declaration is supposed to
-// suppress the implicit instantiation of non-inline member functions. Make sure
-// that we suppress the implicit instantiation of non-inline member functions
-// defined out-of-line. That we aren't instantiating the basic_string
-// constructor when we shouldn't be. Such an instantiation forces the implicit
-// instantiation of _S_construct<const char*>. Since _S_construct is a member
-// template, it's instantiation is *not* suppressed (despite being in
-// basic_string<char>), so we would emit it as a weak definition.
-
-#include <stdexcept>
-
-void dummysymbol() {
- throw(std::runtime_error("string"));
-}
diff --git a/test/FrontendC++/x86-64-abi-sret-vs-2word-struct-param.cpp b/test/FrontendC++/x86-64-abi-sret-vs-2word-struct-param.cpp
deleted file mode 100644
index f81854e..0000000
--- a/test/FrontendC++/x86-64-abi-sret-vs-2word-struct-param.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-// RUN: %llvmgxx -S %s -o - | grep byval | count 2
-// XTARGET: x86
-// PR4242
-// (PR 4242 bug is on 64-bit only, test passes on x86-32 as well)
-
-struct S {
- void* data[3];
-};
-
-struct T {
- void* data[2];
-};
-
-extern "C" S fail(int, int, int, int, T t, void* p) {
- S s;
- s.data[0] = t.data[0];
- s.data[1] = t.data[1];
- s.data[2] = p;
- return s;
-}
-
-extern "C" S* succeed(S* sret, int, int, int, int, T t, void* p) {
- sret->data[0] = t.data[0];
- sret->data[1] = t.data[1];
- sret->data[2] = p;
- return sret;
-}
diff --git a/test/FrontendC/2002-01-23-LoadQISIReloadFailure.c b/test/FrontendC/2002-01-23-LoadQISIReloadFailure.c
deleted file mode 100644
index 1779a99..0000000
--- a/test/FrontendC/2002-01-23-LoadQISIReloadFailure.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* Regression test. Just compile .c -> .ll to test */
-int foo(void) {
- unsigned char *pp;
- unsigned w_cnt;
-
- w_cnt += *pp;
-
- return w_cnt;
-}
diff --git a/test/FrontendC/2002-01-24-ComplexSpaceInType.c b/test/FrontendC/2002-01-24-ComplexSpaceInType.c
deleted file mode 100644
index 13d92c7..0000000
--- a/test/FrontendC/2002-01-24-ComplexSpaceInType.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-// This caused generation of the following type name:
-// %Array = uninitialized global [10 x %complex int]
-//
-// which caused problems because of the space int the complex int type
-//
-
-struct { int X, Y; } Array[10];
-
-void foo() {}
diff --git a/test/FrontendC/2002-01-24-HandleCallInsnSEGV.c b/test/FrontendC/2002-01-24-HandleCallInsnSEGV.c
deleted file mode 100644
index e619cf4..0000000
--- a/test/FrontendC/2002-01-24-HandleCallInsnSEGV.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-void *dlclose(void*);
-
-void ap_os_dso_unload(void *handle)
-{
- dlclose(handle);
- return; /* This return triggers the bug: Weird */
-}
diff --git a/test/FrontendC/2002-02-13-ConditionalInCall.c b/test/FrontendC/2002-02-13-ConditionalInCall.c
deleted file mode 100644
index f361088..0000000
--- a/test/FrontendC/2002-02-13-ConditionalInCall.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* Test problem where bad code was generated with a ?: statement was
- in a function call argument */
-
-void foo(int, double, float);
-
-void bar(int x) {
- foo(x, x ? 1.0 : 12.5, 1.0f);
-}
-
diff --git a/test/FrontendC/2002-02-13-ReloadProblem.c b/test/FrontendC/2002-02-13-ReloadProblem.c
deleted file mode 100644
index 2ae97b7..0000000
--- a/test/FrontendC/2002-02-13-ReloadProblem.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* This triggered a problem in reload, fixed by disabling most of the
- * steps of compilation in GCC. Before this change, the code went through
- * the entire backend of GCC, even though it was unnecessary for LLVM output
- * now it is skipped entirely, and since reload doesn't run, it can't cause
- * a problem.
- */
-
-extern int tolower(int);
-
-const char *rangematch(const char *pattern, int test, int c) {
-
- if ((c <= test) | (tolower(c) <= tolower((unsigned char)test)))
- return 0;
-
- return pattern;
-}
diff --git a/test/FrontendC/2002-02-13-TypeVarNameCollision.c b/test/FrontendC/2002-02-13-TypeVarNameCollision.c
deleted file mode 100644
index 2dede68..0000000
--- a/test/FrontendC/2002-02-13-TypeVarNameCollision.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* This testcase causes a symbol table collision. Type names and variable
- * names should be in distinct namespaces
- */
-
-typedef struct foo {
- int X, Y;
-} FOO;
-
-static FOO foo[100];
-
-int test() {
- return foo[4].Y;
-}
-
diff --git a/test/FrontendC/2002-02-13-UnnamedLocal.c b/test/FrontendC/2002-02-13-UnnamedLocal.c
deleted file mode 100644
index 85aa615..0000000
--- a/test/FrontendC/2002-02-13-UnnamedLocal.c
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* Testcase for a problem where GCC allocated xqic to a register,
- * and did not have a VAR_DECL that explained the stack slot to LLVM.
- * Now the LLVM code synthesizes a stack slot if one is presented that
- * has not been previously recognized. This is where alloca's named
- * 'local' come from now.
- */
-
-typedef struct {
- short x;
-} foostruct;
-
-int foo(foostruct ic);
-
-void test() {
- foostruct xqic;
- foo(xqic);
-}
-
-
diff --git a/test/FrontendC/2002-02-14-EntryNodePreds.c b/test/FrontendC/2002-02-14-EntryNodePreds.c
deleted file mode 100644
index 851af91..0000000
--- a/test/FrontendC/2002-02-14-EntryNodePreds.c
+++ /dev/null
@@ -1,37 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* GCC Used to generate code that contained a branch to the entry node of
- * the do_merge function. This is illegal LLVM code. To fix this, GCC now
- * inserts an entry node regardless of whether or not it has to insert allocas.
- */
-
-struct edge_rec
-{
- struct VERTEX *v;
- struct edge_rec *next;
- int wasseen;
- int more_data;
-};
-
-typedef struct edge_rec *QUAD_EDGE;
-
-typedef struct {
- QUAD_EDGE left, right;
-} EDGE_PAIR;
-
-struct EDGE_STACK {
- int ptr;
- QUAD_EDGE *elts;
- int stack_size;
-};
-
-int do_merge(QUAD_EDGE ldo, QUAD_EDGE rdo) {
- int lvalid;
- QUAD_EDGE basel,rcand;
- while (1) {
- if (!lvalid) {
- return (int)basel->next;
- }
- }
-}
-
diff --git a/test/FrontendC/2002-02-16-RenamingTest.c b/test/FrontendC/2002-02-16-RenamingTest.c
deleted file mode 100644
index 6042b67..0000000
--- a/test/FrontendC/2002-02-16-RenamingTest.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* test that locals are renamed with . notation */
-
-void abc(void *);
-
-void Test5(double X) {
- abc(&X);
- {
- int X;
- abc(&X);
- {
- float X;
- abc(&X);
- }
- }
-}
-
diff --git a/test/FrontendC/2002-02-17-ArgumentAddress.c b/test/FrontendC/2002-02-17-ArgumentAddress.c
deleted file mode 100644
index acd7e37..0000000
--- a/test/FrontendC/2002-02-17-ArgumentAddress.c
+++ /dev/null
@@ -1,39 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-int test(int X) {
- return X;
-}
-
-void abc(int *X);
-int def(int Y, int Z) {
- abc(&Z);
- return Y;
-}
-
-struct Test { short X, x; int Y, Z; };
-
-int Testing(struct Test *A) {
- return A->X+A->Y;
-}
-
-int Test2(int X, struct Test A, int Y) {
- return X+Y+A.X+A.Y;
-}
-int Test3(struct Test A, struct Test B) {
- return A.X+A.Y+B.Y+B.Z;
-}
-
-struct Test Test4(struct Test A) {
- return A;
-}
-
-int Test6() {
- int B[200];
- return B[4];
-}
-
-struct STest2 { int X; short Y[4]; double Z; };
-
-struct STest2 Test7(struct STest2 X) {
- return X;
-}
diff --git a/test/FrontendC/2002-02-18-64bitConstant.c b/test/FrontendC/2002-02-18-64bitConstant.c
deleted file mode 100644
index a88587a..0000000
--- a/test/FrontendC/2002-02-18-64bitConstant.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* GCC wasn't handling 64 bit constants right fixed */
-
-#include <stdio.h>
-
-int main() {
- long long Var = 123455678902ll;
- printf("%lld\n", Var);
-}
diff --git a/test/FrontendC/2002-02-18-StaticData.c b/test/FrontendC/2002-02-18-StaticData.c
deleted file mode 100644
index 76cb0e6..0000000
--- a/test/FrontendC/2002-02-18-StaticData.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-double FOO = 17;
-double BAR = 12.0;
-float XX = 12.0f;
-
-static char *procnames[] = {
- "EXIT"
-};
-
-void *Data[] = { &FOO, &BAR, &XX };
-
diff --git a/test/FrontendC/2002-03-11-LargeCharInString.c b/test/FrontendC/2002-03-11-LargeCharInString.c
deleted file mode 100644
index b383d03..0000000
--- a/test/FrontendC/2002-03-11-LargeCharInString.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-#include <string.h>
-
-int test(char *X) {
- /* LLVM-GCC used to emit:
- %.LC0 = internal global [3 x sbyte] c"\1F\FFFFFF8B\00"
- */
- return strcmp(X, "\037\213");
-}
diff --git a/test/FrontendC/2002-03-12-ArrayInitialization.c b/test/FrontendC/2002-03-12-ArrayInitialization.c
deleted file mode 100644
index 1997a3c..0000000
--- a/test/FrontendC/2002-03-12-ArrayInitialization.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* GCC would generate bad code if not enough initializers are
- specified for an array.
- */
-
-int a[10] = { 0, 2};
-
-char str[10] = "x";
-
-void *Arr[5] = { 0, 0 };
-
-float F[12] = { 1.23f, 34.7f };
-
-struct Test { int X; double Y; };
-
-struct Test Array[10] = { { 2, 12.0 }, { 3, 24.0 } };
-
-int B[4][4] = { { 1, 2, 3, 4}, { 5, 6, 7 }, { 8, 9 } };
diff --git a/test/FrontendC/2002-03-12-StructInitialize.c b/test/FrontendC/2002-03-12-StructInitialize.c
deleted file mode 100644
index 9eb11e1..0000000
--- a/test/FrontendC/2002-03-12-StructInitialize.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-typedef struct Connection_Type {
- long to;
- char type[10];
- long length;
-} Connection;
-
-Connection link[3]
-= { {1, "link1", 10},
- {2, "link2", 20},
- {3, "link3", 30} };
-
diff --git a/test/FrontendC/2002-03-12-StructInitializer.c b/test/FrontendC/2002-03-12-StructInitializer.c
deleted file mode 100644
index fa333b7..0000000
--- a/test/FrontendC/2002-03-12-StructInitializer.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* GCC was not emitting string constants of the correct length when
- * embedded into a structure field like this. It thought the strlength
- * was -1.
- */
-
-typedef struct Connection_Type {
- long to;
- char type[10];
- long length;
-} Connection;
-
-Connection link[3]
-= { {1, "link1", 10},
- {2, "link2", 20},
- {3, "link3", 30} };
-
diff --git a/test/FrontendC/2002-03-14-BrokenPHINode.c b/test/FrontendC/2002-03-14-BrokenPHINode.c
deleted file mode 100644
index 48d9ab7..0000000
--- a/test/FrontendC/2002-03-14-BrokenPHINode.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* GCC was generating PHI nodes with an arity < #pred of the basic block the
- * PHI node lived in. This was breaking LLVM because the number of entries
- * in a PHI node must equal the number of predecessors for a basic block.
- */
-
-int trys(char *s, int x)
-{
- int asa;
- double Val;
- int LLS;
- if (x) {
- asa = LLS + asa;
- } else {
- }
- return asa+(int)Val;
-}
-
diff --git a/test/FrontendC/2002-03-14-BrokenSSA.c b/test/FrontendC/2002-03-14-BrokenSSA.c
deleted file mode 100644
index 9dc674a..0000000
--- a/test/FrontendC/2002-03-14-BrokenSSA.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* This code used to break GCC's SSA computation code. It would create
- uses of B & C that are not dominated by their definitions. See:
- http://gcc.gnu.org/ml/gcc/2002-03/msg00697.html
- */
-int bar();
-int foo()
-{
- int a,b,c;
-
- a = b + c;
- b = bar();
- c = bar();
- return a + b + c;
-}
-
diff --git a/test/FrontendC/2002-03-14-QuotesInStrConst.c b/test/FrontendC/2002-03-14-QuotesInStrConst.c
deleted file mode 100644
index 63eaeef..0000000
--- a/test/FrontendC/2002-03-14-QuotesInStrConst.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* GCC was not escaping quotes in string constants correctly, so this would
- * get emitted:
- * %.LC1 = internal global [32 x sbyte] c"*** Word "%s" on line %d is not\00"
- */
-
-const char *Foo() {
- return "*** Word \"%s\" on line %d is not";
-}
diff --git a/test/FrontendC/2002-04-07-SwitchStmt.c b/test/FrontendC/2002-04-07-SwitchStmt.c
deleted file mode 100644
index 33e9c3d..0000000
--- a/test/FrontendC/2002-04-07-SwitchStmt.c
+++ /dev/null
@@ -1,22 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-int printf(const char *, ...);
-int foo();
-
-int main() {
- while (foo()) {
- switch (foo()) {
- case 0:
- case 1:
- case 2:
- case 3:
- printf("3");
- case 4: printf("4");
- case 5:
- case 6:
- default:
- break;
- }
- }
- return 0;
-}
diff --git a/test/FrontendC/2002-04-08-LocalArray.c b/test/FrontendC/2002-04-08-LocalArray.c
deleted file mode 100644
index 1dc51a0..0000000
--- a/test/FrontendC/2002-04-08-LocalArray.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* GCC is not outputting the static array to the LLVM backend, so bad things
- * happen. Note that if this is defined static, everything seems fine.
- */
-double test(unsigned X) {
- double student_t[30]={0.0 , 12.706 , 4.303 , 3.182 , 2.776 , 2.571 ,
- 2.447 , 2.365 , 2.306 , 2.262 , 2.228 ,
- 2.201 , 2.179 , 2.160 , 2.145 , 2.131 ,
- 2.120 , 2.110 , 2.101 , 2.093 , 2.086 ,
- 2.080 , 2.074 , 2.069 , 2.064 , 2.060 ,
- 2.056 , 2.052 , 2.048 , 2.045 };
- return student_t[X];
-}
diff --git a/test/FrontendC/2002-04-09-StructRetVal.c b/test/FrontendC/2002-04-09-StructRetVal.c
deleted file mode 100644
index de3b6fc..0000000
--- a/test/FrontendC/2002-04-09-StructRetVal.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct S {
- int i;
- short s1, s2;
-};
-
-struct S func_returning_struct(void);
-
-void loop(void) {
- func_returning_struct();
-}
diff --git a/test/FrontendC/2002-04-10-StructParameters.c b/test/FrontendC/2002-04-10-StructParameters.c
deleted file mode 100644
index aaaba2a..0000000
--- a/test/FrontendC/2002-04-10-StructParameters.c
+++ /dev/null
@@ -1,25 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-typedef struct {
- char p;
- short q;
- char r;
- int X;
- short Y, Z;
- int Q;
-} foo;
-
-int test(foo X, float);
-int testE(char,short,char,int,int,float);
-void test3(foo *X) {
- X->q = 1;
-}
-
-void test2(foo Y) {
- testE(Y.p, Y.q, Y.r, Y.X, Y.Y, 0.1f);
- test(Y, 0.1f);
- test2(Y);
- test3(&Y);
-}
-
diff --git a/test/FrontendC/2002-05-23-StaticValues.c b/test/FrontendC/2002-05-23-StaticValues.c
deleted file mode 100644
index a5753b9..0000000
--- a/test/FrontendC/2002-05-23-StaticValues.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* Make sure the frontend is correctly marking static stuff as internal! */
-
-int X;
-static int Y = 12;
-
-static void foo(int Z) {
- Y = Z;
-}
-
-void *test() {
- foo(12);
- return &Y;
-}
diff --git a/test/FrontendC/2002-05-23-TypeNameCollision.c b/test/FrontendC/2002-05-23-TypeNameCollision.c
deleted file mode 100644
index 25d1149..0000000
--- a/test/FrontendC/2002-05-23-TypeNameCollision.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* Testcase for when struct tag conflicts with typedef name... grr */
-
-typedef struct foo {
- struct foo *X;
- int Y;
-} * foo;
-
-foo F1;
-struct foo *F2;
-
-enum bar { test1, test2 };
-
-typedef float bar;
-
-enum bar B1;
-bar B2;
-
diff --git a/test/FrontendC/2002-05-24-Alloca.c b/test/FrontendC/2002-05-24-Alloca.c
deleted file mode 100644
index 128bc8b..0000000
--- a/test/FrontendC/2002-05-24-Alloca.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char **argv) {
- char *C = (char*)alloca(argc);
- strcpy(C, argv[0]);
- puts(C);
-}
diff --git a/test/FrontendC/2002-06-25-FWriteInterfaceFailure.c b/test/FrontendC/2002-06-25-FWriteInterfaceFailure.c
deleted file mode 100644
index 4380dc7..0000000
--- a/test/FrontendC/2002-06-25-FWriteInterfaceFailure.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-#include <stdio.h>
-
-void test() {
- fprintf(stderr, "testing\n");
-}
diff --git a/test/FrontendC/2002-07-14-MiscListTests.c b/test/FrontendC/2002-07-14-MiscListTests.c
deleted file mode 100644
index 4a5459a..0000000
--- a/test/FrontendC/2002-07-14-MiscListTests.c
+++ /dev/null
@@ -1,71 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-// Test list stuff
-
-void *malloc(unsigned);
-
-// Test opaque structure support. the list type is defined later
-struct list;
-
-struct list *PassThroughList(struct list *L) {
- return L;
-}
-
-
-// Recursive data structure tests...
-
-typedef struct list {
- int Data;
- struct list *Next;
-} list;
-
-list *Data;
-
-void foo() {
- static int Foo = 0; // Test static local variable
- Foo += 1; // Increment static variable
-
- Data = (list*)malloc(12); // This is not a proper list allocation
-}
-
-extern list ListNode1;
-list ListNode3 = { 4, 0 };
-list ListNode2 = { 3, &ListNode3 };
-list ListNode0 = { 1, &ListNode1 };
-list ListNode1 = { 2, &ListNode2 };
-
-
-list ListArray[10];
-
-// Iterative insert fn
-void InsertIntoListTail(list **L, int Data) {
- while (*L)
- L = &(*L)->Next;
- *L = (list*)malloc(sizeof(list));
- (*L)->Data = Data;
- (*L)->Next = 0;
-}
-
-// Recursive list search fn
-list *FindData(list *L, int Data) {
- if (L == 0) return 0;
- if (L->Data == Data) return L;
- return FindData(L->Next, Data);
-}
-
-void foundIt(void);
-
-// Driver fn...
-void DoListStuff() {
- list *MyList = 0;
- InsertIntoListTail(&MyList, 100);
- InsertIntoListTail(&MyList, 12);
- InsertIntoListTail(&MyList, 42);
- InsertIntoListTail(&MyList, 1123);
- InsertIntoListTail(&MyList, 1213);
-
- if (FindData(MyList, 75)) foundIt();
- if (FindData(MyList, 42)) foundIt();
- if (FindData(MyList, 700)) foundIt();
-}
-
diff --git a/test/FrontendC/2002-07-14-MiscTests.c b/test/FrontendC/2002-07-14-MiscTests.c
deleted file mode 100644
index 57c4120..0000000
--- a/test/FrontendC/2002-07-14-MiscTests.c
+++ /dev/null
@@ -1,57 +0,0 @@
-// RUN: %llvmgcc -w -S %s -o - | llvm-as -o /dev/null
-
-/* These are random tests that I used when working on the GCC frontend
- originally. */
-
-// test floating point comparison!
-int floatcomptest(double *X, double *Y, float *x, float *y) {
- return *X < *Y || *x < *y;
-}
-
-extern void *malloc(unsigned);
-
-// Exposed a bug
-void *memset_impl(void *dstpp, int c, unsigned len) {
- long long int dstp = (long long int) dstpp;
-
- while (dstp % 4 != 0)
- {
- ((unsigned char *) dstp)[0] = c;
- dstp += 1;
- len -= 1;
- }
- return dstpp;
-}
-
-// TEST problem with signed/unsigned versions of the same constants being shared
-// incorrectly!
-//
-static char *temp;
-static int remaining;
-static char *localmalloc(int size) {
- char *blah;
-
- if (size>remaining)
- {
- temp = (char *) malloc(32768);
- remaining = 32768;
- return temp;
- }
- return 0;
-}
-
-typedef struct { double X; double Y; int Z; } PBVTest;
-
-PBVTest testRetStruct(float X, double Y, int Z) {
- PBVTest T = { X, Y, Z };
- return T;
-}
-PBVTest testRetStruct2(void); // external func no inlining
-
-
-double CallRetStruct(float X, double Y, int Z) {
- PBVTest T = testRetStruct2();
- return T.X+X+Y+Z;
-}
-
-
diff --git a/test/FrontendC/2002-07-14-MiscTests2.c b/test/FrontendC/2002-07-14-MiscTests2.c
deleted file mode 100644
index f2c7c81..0000000
--- a/test/FrontendC/2002-07-14-MiscTests2.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-// Test ?: in function calls
-extern fp(int, char*);
-char *Ext;
-void
-__bb_exit_func (void)
-{
- fp (12, Ext ? Ext : "<none>");
-}
-
-
diff --git a/test/FrontendC/2002-07-14-MiscTests3.c b/test/FrontendC/2002-07-14-MiscTests3.c
deleted file mode 100644
index 7ef7e23..0000000
--- a/test/FrontendC/2002-07-14-MiscTests3.c
+++ /dev/null
@@ -1,187 +0,0 @@
-// RUN: %llvmgcc -w -S %s -o - | llvm-as -o /dev/null
-
-
-
-void *malloc(unsigned);
-
-//#include <stdio.h>
-int puts(const char *s);
-
-struct FunStructTest {
- int Test1;
- char *Pointer;
- int Array[12];
-};
-
-struct SubStruct {
- short X, Y;
-};
-
-struct Quad {
- int w;
- struct SubStruct SS;
- struct SubStruct *SSP;
- char c;
- int y;
-};
-
-struct Quad GlobalQuad = { 4, {1, 2}, 0, 3, 156 };
-
-typedef int (*FuncPtr)(int);
-
-unsigned PtrFunc(int (*Func)(int), int X) {
- return Func(X);
-}
-
-char PtrFunc2(FuncPtr FuncTab[30], int Num) {
- return FuncTab[Num]('b');
-}
-
-extern char SmallArgs2(char w, char x, long long Zrrk, char y, char z);
-extern int SomeFunc(void);
-char SmallArgs(char w, char x, char y, char z) {
- SomeFunc();
- return SmallArgs2(w-1, x+1, y, z, w);
-}
-
-static int F0(struct Quad Q, int i) { /* Pass Q by value */
- struct Quad R;
- if (i) R.SS = Q.SS;
- Q.SSP = &R.SS;
- Q.w = Q.y = Q.c = 1;
- return Q.SS.Y + i + R.y - Q.c;
-}
-
-int F1(struct Quad *Q, int i) { /* Pass Q by address */
- struct Quad R;
-#if 0
- if (i) R.SS = Q->SS;
-#else
- if (i) R = *Q;
-#endif
- Q->w = Q->y = Q->c = 1;
- return Q->SS.Y+i+R.y-Q->c;
-}
-
-
-int BadFunc(float Val) {
- int Result;
- if (Val > 12.345) Result = 4;
- return Result; /* Test use of undefined value */
-}
-
-int RealFunc(void) {
- return SomeUndefinedFunction(1, 4, 5);
-}
-
-extern int EF1(int *, char *, int *);
-
-int Func(int Param, long long Param2) {
- int Result = Param;
-
- {{{{
- char c; int X;
- EF1(&Result, &c, &X);
- }}}
-
- { // c & X are duplicate names!
- char c; int X;
- EF1(&Result, &c, &X);
- }
-
- }
- return Result;
-}
-
-
-short FunFunc(long long x, char z) {
- return x+z;
-}
-
-unsigned castTest(int X) { return X; }
-
-double TestAdd(double X, float Y) {
- return X+Y+.5;
-}
-
-int func(int i, int j) {
- while (i != 20)
- i += 2;
-
- j += func(2, i);
- return (i * 3 + j*2)*j;
-}
-
-int SumArray(int Array[], int Num) {
- int i, Result = 0;
- for (i = 0; i < Num; ++i)
- Result += Array[i];
-
- return Result;
-}
-
-int ArrayParam(int Values[100]) {
- return EF1((int*)Values[50], (char*)1, &Values[50]);
-}
-
-int ArrayToSum(void) {
- int A[100], i;
- for (i = 0; i < 100; ++i)
- A[i] = i*4;
-
- return A[A[0]]; //SumArray(A, 100);
-}
-
-
-int ExternFunc(long long, unsigned*, short, unsigned char);
-
-int main(int argc, char *argv[]) {
- unsigned i;
- puts("Hello world!\n");
-
- ExternFunc(-1, 0, (short)argc, 2);
- //func(argc, argc);
-
- for (i = 0; i < 10; i++)
- puts(argv[3]);
- return 0;
-}
-
-double MathFunc(double X, double Y, double Z,
- double AA, double BB, double CC, double DD,
- double EE, double FF, double GG, double HH,
- double aAA, double aBB, double aCC, double aDD,
- double aEE, double aFF) {
- return X + Y + Z + AA + BB + CC + DD + EE + FF + GG + HH
- + aAA + aBB + aCC + aDD + aEE + aFF;
-}
-
-
-
-void strcpy(char *s1, char *s2) {
- while (*s1++ = *s2++);
-}
-
-void strcat(char *s1, char *s2) {
- while (*s1++);
- s1--;
- while (*s1++ = *s2++);
-}
-
-int strcmp(char *s1, char *s2) {
- while (*s1++ == *s2++);
- if (*s1 == 0) {
- if (*s2 == 0) {
- return 0;
- } else {
- return -1;
- }
- } else {
- if (*s2 == 0) {
- return 1;
- } else {
- return (*(--s1) - *(--s2));
- }
- }
-}
-
diff --git a/test/FrontendC/2002-07-16-HardStringInit.c b/test/FrontendC/2002-07-16-HardStringInit.c
deleted file mode 100644
index 2785e51..0000000
--- a/test/FrontendC/2002-07-16-HardStringInit.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
- char auto_kibitz_list[100][20] = {
- {"diepx"},
- {"ferret"},
- {"knightc"},
- {"knightcap"}};
-
diff --git a/test/FrontendC/2002-07-17-StringConstant.c b/test/FrontendC/2002-07-17-StringConstant.c
deleted file mode 100644
index 9ba0c25..0000000
--- a/test/FrontendC/2002-07-17-StringConstant.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-char * foo() { return "\\begin{"; }
diff --git a/test/FrontendC/2002-07-29-Casts.c b/test/FrontendC/2002-07-29-Casts.c
deleted file mode 100644
index 44bb610..0000000
--- a/test/FrontendC/2002-07-29-Casts.c
+++ /dev/null
@@ -1,86 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-int
-main(int argc, char** argv)
-{
- char c1;
- short s1, ssf1, ssd1;
- unsigned char ubs0;
- signed char bs0;
- unsigned char ubc0, uc2;
- unsigned short us2, usf1, usd1;
- int ic3, is3, sif1, sid1;
- unsigned int uic4, uis4, uif1, uid1;
- long slf1, sld1;
- unsigned long ulf1, uld1;
- float f1;
- double d1;
-
- /* Test integer to integer conversions */
-
- c1 = (char) (argc >= 2)? atoi(argv[1]) : 0xff64; /* 100 = 'd' */
- s1 = (short) (argc >= 3)? atoi(argv[2]) : -769; /* 0xf7ff = -769 */
-
- ubc0 = (unsigned char) c1; /* 100 = 'd' */
- ubs0 = (unsigned char) s1; /* 0xff = 255 */
- bs0 = (signed char) s1; /* 0xff = -1 */
-
- uc2 = (unsigned char) c1; /* 100 = 'd' */
- us2 = (unsigned short) s1; /* 0xf7ff = 64767 */
-
- ic3 = (int) c1; /* 100 = 'd' */
- is3 = (int) s1; /* 0xfffff7ff = -769 */
-
- uic4 = (unsigned int) c1; /* 100 = 'd' */
- uis4 = (unsigned int) s1; /* 0xfffff7ff = 4294966527 */
-
- printf("ubc0 = '%c'\n", ubc0);
- printf("ubs0 = %u\n", ubs0);
- printf("bs0 = %d\n", bs0);
- printf("c1 = '%c'\n", c1);
- printf("s1 = %d\n", s1);
- printf("uc2 = '%c'\n", uc2);
- printf("us2 = %u\n", us2);
- printf("ic3 = '%c'\n", ic3);
- printf("is3 = %d\n", is3);
- printf("uic4 = '%c'\n", uic4);
- printf("uis4 = %u\n", uis4);
-
- /* Test floating-point to integer conversions */
- f1 = (float) (argc >= 4)? atof(argv[3]) : 1.0;
- d1 = (argc >= 5)? atof(argv[4]) : 2.0;
-
- usf1 = (unsigned short) f1;
- usd1 = (unsigned short) d1;
- uif1 = (unsigned int) f1;
- uid1 = (unsigned int) d1;
- ulf1 = (unsigned long) f1;
- uld1 = (unsigned long) d1;
-
- ssf1 = (short) f1;
- ssd1 = (short) d1;
- sif1 = (int) f1;
- sid1 = (int) d1;
- slf1 = (long) f1;
- sld1 = (long) d1;
-
- printf("usf1 = %u\n", usf1);
- printf("usd1 = %u\n", usd1);
- printf("uif1 = %u\n", uif1);
- printf("uid1 = %u\n", uid1);
- printf("ulf1 = %u\n", ulf1);
- printf("uld1 = %u\n", uld1);
-
- printf("ssf1 = %d\n", ssf1);
- printf("ssd1 = %d\n", ssd1);
- printf("sif1 = %d\n", sif1);
- printf("sid1 = %d\n", sid1);
- printf("slf1 = %d\n", slf1);
- printf("sld1 = %d\n", sld1);
-
- return 0;
-}
diff --git a/test/FrontendC/2002-07-30-SubregSetAssertion.c b/test/FrontendC/2002-07-30-SubregSetAssertion.c
deleted file mode 100644
index af72eda..0000000
--- a/test/FrontendC/2002-07-30-SubregSetAssertion.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-union X {
- void *B;
-};
-
-union X foo() {
- union X A;
- A.B = (void*)123;
- return A;
-}
diff --git a/test/FrontendC/2002-07-30-UnionTest.c b/test/FrontendC/2002-07-30-UnionTest.c
deleted file mode 100644
index c931b80..0000000
--- a/test/FrontendC/2002-07-30-UnionTest.c
+++ /dev/null
@@ -1,22 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-union X;
-struct Empty {};
-union F {};
-union Q { union Q *X; };
-union X {
- char C;
- int A, Z;
- long long B;
- void *b1;
- struct { int A; long long Z; } Q;
-};
-
-union X foo(union X A) {
- A.C = 123;
- A.A = 39249;
- //A.B = (void*)123040123321;
- A.B = 12301230123123LL;
- A.Z = 1;
- return A;
-}
diff --git a/test/FrontendC/2002-07-30-VarArgsCallFailure.c b/test/FrontendC/2002-07-30-VarArgsCallFailure.c
deleted file mode 100644
index 5d93947..0000000
--- a/test/FrontendC/2002-07-30-VarArgsCallFailure.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-int tcount;
-void test(char *, const char*, int);
-void foo() {
- char Buf[10];
- test(Buf, "n%%%d", tcount++);
-}
diff --git a/test/FrontendC/2002-07-31-BadAssert.c b/test/FrontendC/2002-07-31-BadAssert.c
deleted file mode 100644
index 5c3d74c..0000000
--- a/test/FrontendC/2002-07-31-BadAssert.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-typedef struct
-{
- unsigned char type; /* Indicates, NORMAL, SUBNORMAL, etc. */
-} InternalFPF;
-
-
-static void SetInternalFPFZero(InternalFPF *dest) {
- dest->type=0;
-}
-
-void denormalize(InternalFPF *ptr) {
- SetInternalFPFZero(ptr);
-}
-
diff --git a/test/FrontendC/2002-07-31-SubregFailure.c b/test/FrontendC/2002-07-31-SubregFailure.c
deleted file mode 100644
index 72fcb49..0000000
--- a/test/FrontendC/2002-07-31-SubregFailure.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-typedef union {
- long (*ap)[4];
-} ptrs;
-
-void DoAssignIteration() {
- ptrs abase;
- abase.ap+=27;
- Assignment(*abase.ap);
-}
-
-
diff --git a/test/FrontendC/2002-08-02-UnionTest.c b/test/FrontendC/2002-08-02-UnionTest.c
deleted file mode 100644
index e2b8c3d..0000000
--- a/test/FrontendC/2002-08-02-UnionTest.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* In this testcase, the return value of foo() is being promotedto a register
- * which breaks stuff
- */
-#include <stdio.h>
-
-union X { char X; void *B; int a, b, c, d;};
-
-union X foo() {
- union X Global;
- Global.B = (void*)123; /* Interesting part */
- return Global;
-}
-
-int main() {
- union X test = foo();
- printf("0x%p", test.B);
-}
diff --git a/test/FrontendC/2002-08-19-RecursiveLocals.c b/test/FrontendC/2002-08-19-RecursiveLocals.c
deleted file mode 100644
index 59220ac..0000000
--- a/test/FrontendC/2002-08-19-RecursiveLocals.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* This testcase doesn't actually test a bug, it's just the result of me
- * figuring out the syntax for forward declaring a static variable. */
-struct list {
- int x;
- struct list *Next;
-};
-
-static struct list B; /* Forward declare static */
-static struct list A = { 7, &B };
-static struct list B = { 8, &A };
-
-extern struct list D; /* forward declare normal var */
-
-struct list C = { 7, &D };
-struct list D = { 8, &C };
-
diff --git a/test/FrontendC/2002-09-08-PointerShifts.c b/test/FrontendC/2002-09-08-PointerShifts.c
deleted file mode 100644
index 86ff2f9..0000000
--- a/test/FrontendC/2002-09-08-PointerShifts.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-int foo(int *A, unsigned X) {
- return A[X];
-}
diff --git a/test/FrontendC/2002-09-18-UnionProblem.c b/test/FrontendC/2002-09-18-UnionProblem.c
deleted file mode 100644
index 54588f1..0000000
--- a/test/FrontendC/2002-09-18-UnionProblem.c
+++ /dev/null
@@ -1,26 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-struct DWstruct {
- char high, low;
-};
-
-typedef union {
- struct DWstruct s;
- short ll;
-} DWunion;
-
-short __udivmodhi4 (char n1, char bm) {
- DWunion rr;
-
- if (bm == 0)
- {
- rr.s.high = n1;
- }
- else
- {
- rr.s.high = bm;
- }
-
- return rr.ll;
-}
diff --git a/test/FrontendC/2002-09-19-StarInLabel.c b/test/FrontendC/2002-09-19-StarInLabel.c
deleted file mode 100644
index 171acca..0000000
--- a/test/FrontendC/2002-09-19-StarInLabel.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-extern void start() __asm__("start");
-extern void _start() __asm__("_start");
-extern void __start() __asm__("__start");
-void start() {}
-void _start() {}
-void __start() {}
-
diff --git a/test/FrontendC/2002-10-12-TooManyArguments.c b/test/FrontendC/2002-10-12-TooManyArguments.c
deleted file mode 100644
index 73c267a..0000000
--- a/test/FrontendC/2002-10-12-TooManyArguments.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-void foo() {}
-
-void bar() {
- foo(1, 2, 3); /* Too many arguments passed */
-}
diff --git a/test/FrontendC/2002-12-15-GlobalBoolTest.c b/test/FrontendC/2002-12-15-GlobalBoolTest.c
deleted file mode 100644
index c27a23a..0000000
--- a/test/FrontendC/2002-12-15-GlobalBoolTest.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-_Bool X = 0;
-
diff --git a/test/FrontendC/2002-12-15-GlobalConstantTest.c b/test/FrontendC/2002-12-15-GlobalConstantTest.c
deleted file mode 100644
index 26de48f..0000000
--- a/test/FrontendC/2002-12-15-GlobalConstantTest.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-const char *W = "foo";
-const int X = 7;
-int Y = 8;
-const char * const Z = "bar";
-
diff --git a/test/FrontendC/2002-12-15-GlobalRedefinition.c b/test/FrontendC/2002-12-15-GlobalRedefinition.c
deleted file mode 100644
index 3b76953..0000000
--- a/test/FrontendC/2002-12-15-GlobalRedefinition.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-extern char algbrfile[9];
-char algbrfile[9] = "abcdefgh";
-
diff --git a/test/FrontendC/2002-12-15-StructParameters.c b/test/FrontendC/2002-12-15-StructParameters.c
deleted file mode 100644
index 90ab1ff..0000000
--- a/test/FrontendC/2002-12-15-StructParameters.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-typedef struct
-{
- void *stack;
- unsigned size;
- unsigned avail;
-} compile_stack_type;
-
-void foo(void*);
-void bar(compile_stack_type T, unsigned);
-
-void test() {
- compile_stack_type CST;
- foo(&CST);
-
- bar(CST, 12);
-}
diff --git a/test/FrontendC/2003-01-30-UnionInit.c b/test/FrontendC/2003-01-30-UnionInit.c
deleted file mode 100644
index 5769584..0000000
--- a/test/FrontendC/2003-01-30-UnionInit.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o /dev/null
-
-union foo {
- struct { char A, B; } X;
- int C;
-};
-
-union foo V = { {1, 2} };
diff --git a/test/FrontendC/2003-03-03-DeferredType.c b/test/FrontendC/2003-03-03-DeferredType.c
deleted file mode 100644
index 9e60df6..0000000
--- a/test/FrontendC/2003-03-03-DeferredType.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-
-
-struct foo A;
-
-struct foo {
- int x;
-double D;
-};
-
diff --git a/test/FrontendC/2003-06-22-UnionCrash.c b/test/FrontendC/2003-06-22-UnionCrash.c
deleted file mode 100644
index 54d8dc6..0000000
--- a/test/FrontendC/2003-06-22-UnionCrash.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct Blend_Map_Entry {
- union {
- float Colour[5];
- double Point_Slope[2];
- } Vals;
-};
-
-void test(struct Blend_Map_Entry* Foo)
-{
-}
-
diff --git a/test/FrontendC/2003-06-23-GCC-fold-infinite-recursion.c b/test/FrontendC/2003-06-23-GCC-fold-infinite-recursion.c
deleted file mode 100644
index 80562c8..0000000
--- a/test/FrontendC/2003-06-23-GCC-fold-infinite-recursion.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-double Test(double A, double B, double C, double D) {
- return -(A-B) - (C-D);
-}
-
diff --git a/test/FrontendC/2003-06-26-CFECrash.c b/test/FrontendC/2003-06-26-CFECrash.c
deleted file mode 100644
index 10a7ed4..0000000
--- a/test/FrontendC/2003-06-26-CFECrash.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-typedef struct min_info {
- long offset;
- unsigned file_attr;
-} min_info;
-
-typedef struct Globals {
- char answerbuf;
- min_info info[1];
- min_info *pInfo;
-} Uz_Globs;
-
-extern Uz_Globs G;
-
-int extract_or_test_files() {
- G.pInfo = G.info;
-}
-
diff --git a/test/FrontendC/2003-06-29-MultipleFunctionDefinition.c b/test/FrontendC/2003-06-29-MultipleFunctionDefinition.c
deleted file mode 100644
index be042ce..0000000
--- a/test/FrontendC/2003-06-29-MultipleFunctionDefinition.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-/* This is apparently legal C.
- */
-extern __inline__ void test() { }
-
-void test() {
-}
diff --git a/test/FrontendC/2003-07-22-ArrayAccessTypeSafety.c b/test/FrontendC/2003-07-22-ArrayAccessTypeSafety.c
deleted file mode 100644
index 51e66c9..0000000
--- a/test/FrontendC/2003-07-22-ArrayAccessTypeSafety.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/* RUN: %llvmgcc -xc %s -S -o - | grep -v alloca | not grep bitcast
- */
-
-void test(int* array, long long N) {
- array[N] = N[array] = 33;
-}
-
diff --git a/test/FrontendC/2003-08-06-BuiltinSetjmpLongjmp.c b/test/FrontendC/2003-08-06-BuiltinSetjmpLongjmp.c
deleted file mode 100644
index 12b4f7b..0000000
--- a/test/FrontendC/2003-08-06-BuiltinSetjmpLongjmp.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/* RUN: %llvmgcc -xc %s -S -o - | not grep __builtin_
- *
- * __builtin_longjmp/setjmp should get transformed into llvm.setjmp/longjmp
- * just like explicit setjmp/longjmp calls are.
- */
-
-void jumpaway(int *ptr) {
- __builtin_longjmp(ptr,1);
-}
-
-int main(void) {
- __builtin_setjmp(0);
- jumpaway(0);
-}
diff --git a/test/FrontendC/2003-08-17-DeadCodeShortCircuit.c b/test/FrontendC/2003-08-17-DeadCodeShortCircuit.c
deleted file mode 100644
index 9ae633e..0000000
--- a/test/FrontendC/2003-08-17-DeadCodeShortCircuit.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o %t.o
-
-int test(_Bool pos, _Bool color) {
- return 0;
- return (pos && color);
-}
-
diff --git a/test/FrontendC/2003-08-18-SigSetJmp.c b/test/FrontendC/2003-08-18-SigSetJmp.c
deleted file mode 100644
index fc0d765..0000000
--- a/test/FrontendC/2003-08-18-SigSetJmp.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-#include <setjmp.h>
-
-sigjmp_buf B;
-int foo() {
- sigsetjmp(B, 1);
- bar();
-}
diff --git a/test/FrontendC/2003-08-18-StructAsValue.c b/test/FrontendC/2003-08-18-StructAsValue.c
deleted file mode 100644
index 26cb78a..0000000
--- a/test/FrontendC/2003-08-18-StructAsValue.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-typedef struct {
- int op;
-} event_t;
-
-event_t test(int X) {
- event_t foo = { 1 }, bar = { 2 };
- return X ? foo : bar;
-}
diff --git a/test/FrontendC/2003-08-20-BadBitfieldRef.c b/test/FrontendC/2003-08-20-BadBitfieldRef.c
deleted file mode 100644
index ef54d8a..0000000
--- a/test/FrontendC/2003-08-20-BadBitfieldRef.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-void foo()
-{
- char *ap;
- ap[1] == '-' && ap[2] == 0;
-}
-
diff --git a/test/FrontendC/2003-08-20-PrototypeMismatch.c b/test/FrontendC/2003-08-20-PrototypeMismatch.c
deleted file mode 100644
index 85c89f6..0000000
--- a/test/FrontendC/2003-08-20-PrototypeMismatch.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-
-static int foo(int);
-
-static int foo(C)
-char C;
-{
- return C;
-}
-
-void test() {
- foo(7);
-}
diff --git a/test/FrontendC/2003-08-20-vfork-bug.c b/test/FrontendC/2003-08-20-vfork-bug.c
deleted file mode 100644
index cfe3161..0000000
--- a/test/FrontendC/2003-08-20-vfork-bug.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-extern int vfork(void);
-test() {
- vfork();
-}
diff --git a/test/FrontendC/2003-08-21-BinOp-Type-Mismatch.c b/test/FrontendC/2003-08-21-BinOp-Type-Mismatch.c
deleted file mode 100644
index a1d4574..0000000
--- a/test/FrontendC/2003-08-21-BinOp-Type-Mismatch.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct bar;
-
-void foo()
-{
- unsigned int frame, focus;
- (struct bar *) focus == (focus ? ((struct bar *) frame) : 0);
-}
-
diff --git a/test/FrontendC/2003-08-21-StmtExpr.c b/test/FrontendC/2003-08-21-StmtExpr.c
deleted file mode 100644
index 7f7d22e..0000000
--- a/test/FrontendC/2003-08-21-StmtExpr.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-typedef struct {
- unsigned long val;
-} structty;
-
-void bar(structty new_mask);
-static void foo() {
- bar(({ structty mask; mask; }));
-}
-
diff --git a/test/FrontendC/2003-08-21-WideString.c b/test/FrontendC/2003-08-21-WideString.c
deleted file mode 100644
index bf67a21..0000000
--- a/test/FrontendC/2003-08-21-WideString.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-#include <wchar.h>
-
-struct {
- wchar_t *name;
-} syms = { L"NUL" };
diff --git a/test/FrontendC/2003-08-23-LocalUnionTest.c b/test/FrontendC/2003-08-23-LocalUnionTest.c
deleted file mode 100644
index 987accc..0000000
--- a/test/FrontendC/2003-08-23-LocalUnionTest.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-
-union foo { int X; };
-
-int test(union foo* F) {
- {
- union foo { float X; } A;
- }
-}
diff --git a/test/FrontendC/2003-08-29-BitFieldStruct.c b/test/FrontendC/2003-08-29-BitFieldStruct.c
deleted file mode 100644
index 57273cd..0000000
--- a/test/FrontendC/2003-08-29-BitFieldStruct.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct Word {
- short bar;
- short baz;
- int final:1;
- short quux;
-} *word_limit;
-
-void foo ()
-{
- word_limit->final = (word_limit->final && word_limit->final);
-}
diff --git a/test/FrontendC/2003-08-29-HugeCharConst.c b/test/FrontendC/2003-08-29-HugeCharConst.c
deleted file mode 100644
index 236eb2e..0000000
--- a/test/FrontendC/2003-08-29-HugeCharConst.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-void foo() {
- unsigned char int_latin1[] = "f\200\372b\200\343\200\340";
-}
diff --git a/test/FrontendC/2003-08-29-StructLayoutBug.c b/test/FrontendC/2003-08-29-StructLayoutBug.c
deleted file mode 100644
index 1673194..0000000
--- a/test/FrontendC/2003-08-29-StructLayoutBug.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct foo {
- unsigned int I:1;
- unsigned char J[1];
- unsigned int K:1;
- };
-
-void test(struct foo *X) {}
-
diff --git a/test/FrontendC/2003-08-30-AggregateInitializer.c b/test/FrontendC/2003-08-30-AggregateInitializer.c
deleted file mode 100644
index 58c77b6..0000000
--- a/test/FrontendC/2003-08-30-AggregateInitializer.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc -S %s -o /dev/null
-
-struct istruct {
- unsigned char C;
-};
-
-struct foo {
- unsigned int I:1;
- struct istruct J;
- unsigned char L[1];
- unsigned int K:1;
-};
-
-struct foo F = { 1, { 7 }, { 123 } , 1 };
-
-
diff --git a/test/FrontendC/2003-08-30-LargeIntegerBitfieldMember.c b/test/FrontendC/2003-08-30-LargeIntegerBitfieldMember.c
deleted file mode 100644
index e1ca88c..0000000
--- a/test/FrontendC/2003-08-30-LargeIntegerBitfieldMember.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct foo {
- unsigned int I:1;
- unsigned char J[1][123];
- unsigned int K:1;
- };
-
-struct foo F;
diff --git a/test/FrontendC/2003-09-18-BitfieldTests.c b/test/FrontendC/2003-09-18-BitfieldTests.c
deleted file mode 100644
index 2d74cb4..0000000
--- a/test/FrontendC/2003-09-18-BitfieldTests.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// RUN: %llvmgcc -w -S %s -o - | llvm-as -o /dev/null
-
-
-typedef struct BF {
- int A : 1;
- char B;
- int C : 13;
-} BF;
-
-char *test1(BF *b) {
- return &b->B; // Must be able to address non-bitfield
-}
-
-void test2(BF *b) { // Increment and decrement operators
- b->A++;
- --b->C;
-}
-
-void test3(BF *b) {
- b->C = 12345; // Store
-}
-
-int test4(BF *b) {
- return b->C; // Load
-}
-
-void test5(BF *b, int i) { // array ref
- b[i].C = 12345;
-}
-
diff --git a/test/FrontendC/2003-09-30-StructLayout.c b/test/FrontendC/2003-09-30-StructLayout.c
deleted file mode 100644
index 177d1f4..0000000
--- a/test/FrontendC/2003-09-30-StructLayout.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-enum En {
- ENUM_VAL
-};
-
-struct St {
- unsigned char A;
- enum En B;
- unsigned char C;
- enum En D;
- float E;
-};
-
-
-void func(struct St* A) {
- A->D = ENUM_VAL;
-}
diff --git a/test/FrontendC/2003-10-02-UnionLValueError.c b/test/FrontendC/2003-10-02-UnionLValueError.c
deleted file mode 100644
index a4d17a4..0000000
--- a/test/FrontendC/2003-10-02-UnionLValueError.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-#include <stdio.h>
-
-union U{
- int i[8];
- char s[80];
-};
-
-void format_message(char *buffer, union U *u) {
- sprintf(buffer, u->s);
-}
-
diff --git a/test/FrontendC/2003-10-06-NegateExprType.c b/test/FrontendC/2003-10-06-NegateExprType.c
deleted file mode 100644
index fb8329b..0000000
--- a/test/FrontendC/2003-10-06-NegateExprType.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-extern int A[10];
-void Func(int *B) {
- B - &A[5];
-}
-
diff --git a/test/FrontendC/2003-10-09-UnionInitializerBug.c b/test/FrontendC/2003-10-09-UnionInitializerBug.c
deleted file mode 100644
index 57e113a..0000000
--- a/test/FrontendC/2003-10-09-UnionInitializerBug.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct Foo {
- unsigned a;
- unsigned b;
- unsigned c;
-};
-
-struct Bar {
- union {
- void **a;
- struct Foo b;
- }u;
-};
-
-struct Bar test = {0};
-
diff --git a/test/FrontendC/2003-10-28-ident.c b/test/FrontendC/2003-10-28-ident.c
deleted file mode 100644
index 06cacf8..0000000
--- a/test/FrontendC/2003-10-28-ident.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-#ident "foo"
diff --git a/test/FrontendC/2003-10-29-AsmRename.c b/test/FrontendC/2003-10-29-AsmRename.c
deleted file mode 100644
index d07ccf7..0000000
--- a/test/FrontendC/2003-10-29-AsmRename.c
+++ /dev/null
@@ -1,22 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-struct foo { int X; };
-struct bar { int Y; };
-
-extern int Func(struct foo*) __asm__("Func64");
-extern int Func64(struct bar*);
-
-int Func(struct foo *F) {
- return 1;
-}
-
-int Func64(struct bar* B) {
- return 0;
-}
-
-
-int test() {
- Func(0); /* should be renamed to call Func64 */
- Func64(0);
-}
diff --git a/test/FrontendC/2003-11-01-C99-CompoundLiteral.c b/test/FrontendC/2003-11-01-C99-CompoundLiteral.c
deleted file mode 100644
index 2912c97..0000000
--- a/test/FrontendC/2003-11-01-C99-CompoundLiteral.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-typedef struct { int foo; } spinlock_t;
-typedef struct wait_queue_head_t { spinlock_t lock; } wait_queue_head_t;
-void call_usermodehelper(void) {
- struct wait_queue_head_t work = { lock: (spinlock_t) { 0 }, };
-}
-
diff --git a/test/FrontendC/2003-11-01-EmptyStructCrash.c b/test/FrontendC/2003-11-01-EmptyStructCrash.c
deleted file mode 100644
index c116119..0000000
--- a/test/FrontendC/2003-11-01-EmptyStructCrash.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-typedef struct { } the_coolest_struct_in_the_world;
-extern the_coolest_struct_in_the_world xyzzy;
-void *foo() { return &xyzzy; }
-
diff --git a/test/FrontendC/2003-11-01-GlobalUnionInit.c b/test/FrontendC/2003-11-01-GlobalUnionInit.c
deleted file mode 100644
index 7cd7073..0000000
--- a/test/FrontendC/2003-11-01-GlobalUnionInit.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-union bdflush_param {
- struct { int x; } b_un;
- int y[1];
-} bdf_prm = {{30}};
-
diff --git a/test/FrontendC/2003-11-03-AddrArrayElement.c b/test/FrontendC/2003-11-03-AddrArrayElement.c
deleted file mode 100644
index 4337da7..0000000
--- a/test/FrontendC/2003-11-03-AddrArrayElement.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o - | grep getelementptr
-
-// This should be turned into a tasty getelementptr instruction, not a nasty
-// series of casts and address arithmetic.
-
-char Global[100];
-
-char *test1(unsigned i) {
- return &Global[i];
-}
-
diff --git a/test/FrontendC/2003-11-04-EmptyStruct.c b/test/FrontendC/2003-11-04-EmptyStruct.c
deleted file mode 100644
index b4f37be..0000000
--- a/test/FrontendC/2003-11-04-EmptyStruct.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-typedef struct { } rwlock_t;
-struct fs_struct { rwlock_t lock; int umask; };
-void __copy_fs_struct(struct fs_struct *fs) { fs->lock = (rwlock_t) { }; }
-
diff --git a/test/FrontendC/2003-11-04-OutOfMemory.c b/test/FrontendC/2003-11-04-OutOfMemory.c
deleted file mode 100644
index 40cb6c2..0000000
--- a/test/FrontendC/2003-11-04-OutOfMemory.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-void schedule_timeout(signed long timeout)
-{
- switch (timeout)
- {
- case ((long)(~0UL>>1)): break;
- }
-}
diff --git a/test/FrontendC/2003-11-08-PointerSubNotGetelementptr.c b/test/FrontendC/2003-11-08-PointerSubNotGetelementptr.c
deleted file mode 100644
index 58f9f82..0000000
--- a/test/FrontendC/2003-11-08-PointerSubNotGetelementptr.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o - | grep getelementptr
-
-char *test(char* C) {
- return C-1; // Should turn into a GEP
-}
-
-int *test2(int* I) {
- return I-1;
-}
diff --git a/test/FrontendC/2003-11-12-VoidString.c b/test/FrontendC/2003-11-12-VoidString.c
deleted file mode 100644
index 5770b36..0000000
--- a/test/FrontendC/2003-11-12-VoidString.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-void query_newnamebuf(void) { ((void)"query_newnamebuf"); }
-
diff --git a/test/FrontendC/2003-11-13-TypeSafety.c b/test/FrontendC/2003-11-13-TypeSafety.c
deleted file mode 100644
index 9b76bb1..0000000
--- a/test/FrontendC/2003-11-13-TypeSafety.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o - | grep getelementptr
-
-int *test(int *X, int Y) {
- return X + Y;
-}
diff --git a/test/FrontendC/2003-11-16-StaticArrayInit.c b/test/FrontendC/2003-11-16-StaticArrayInit.c
deleted file mode 100644
index eb83b3a..0000000
--- a/test/FrontendC/2003-11-16-StaticArrayInit.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-void bar () {
- static char x[10];
- static char *xend = x + 10;
-}
-
-
diff --git a/test/FrontendC/2003-11-18-CondExprLValue.c b/test/FrontendC/2003-11-18-CondExprLValue.c
deleted file mode 100644
index 68ee622..0000000
--- a/test/FrontendC/2003-11-18-CondExprLValue.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-typedef struct { unsigned long pgprot; } pgprot_t;
-
-void split_large_page(unsigned long addr, pgprot_t prot)
-{
- (addr ? prot : ((pgprot_t) { 0x001 } )).pgprot;
-}
-
diff --git a/test/FrontendC/2003-11-19-AddressOfRegister.c b/test/FrontendC/2003-11-19-AddressOfRegister.c
deleted file mode 100644
index 69dc54d..0000000
--- a/test/FrontendC/2003-11-19-AddressOfRegister.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o /dev/null |& not grep warning
-
-struct item {
- short delta[4];
-};
-
-int TEST(int nt) {
- register struct item *aa;
- aa[nt].delta;
- return 1;
-}
-
diff --git a/test/FrontendC/2003-11-19-BitFieldArray.c b/test/FrontendC/2003-11-19-BitFieldArray.c
deleted file mode 100644
index 250268a..0000000
--- a/test/FrontendC/2003-11-19-BitFieldArray.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct _GIOChannel {
- int write_buf;
- char partial_write_buf[6];
- int d :1;
-};
-
-void g_io_channel_init (struct _GIOChannel *channel) {
- channel->partial_write_buf[0];
-}
-
diff --git a/test/FrontendC/2003-11-20-Bitfields.c b/test/FrontendC/2003-11-20-Bitfields.c
deleted file mode 100644
index 4be9942..0000000
--- a/test/FrontendC/2003-11-20-Bitfields.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct face_cachel {
- unsigned int reverse :1;
- unsigned char font_specified[1];
-};
-
-void
-ensure_face_cachel_contains_charset (struct face_cachel *cachel) {
- cachel->font_specified[0] = 0;
-}
-
diff --git a/test/FrontendC/2003-11-20-ComplexDivision.c b/test/FrontendC/2003-11-20-ComplexDivision.c
deleted file mode 100644
index 172de8c..0000000
--- a/test/FrontendC/2003-11-20-ComplexDivision.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-int test() {
- __complex__ double C;
- double D;
- C / D;
-}
diff --git a/test/FrontendC/2003-11-20-UnionBitfield.c b/test/FrontendC/2003-11-20-UnionBitfield.c
deleted file mode 100644
index f999c20..0000000
--- a/test/FrontendC/2003-11-20-UnionBitfield.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct printf_spec {
- unsigned int minus_flag:1;
- char converter;
-};
-
-void parse_doprnt_spec () {
- struct printf_spec spec;
- spec.minus_flag = 1;
-}
-
diff --git a/test/FrontendC/2003-11-26-PointerShift.c b/test/FrontendC/2003-11-26-PointerShift.c
deleted file mode 100644
index 6b5205a..0000000
--- a/test/FrontendC/2003-11-26-PointerShift.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-unsigned long do_csum(const unsigned char *buff, int len, unsigned long result) {
- if (2 & (unsigned long) buff) result += 1;
- return result;
-}
diff --git a/test/FrontendC/2003-11-27-ConstructorCast.c b/test/FrontendC/2003-11-27-ConstructorCast.c
deleted file mode 100644
index 15eb769..0000000
--- a/test/FrontendC/2003-11-27-ConstructorCast.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct i387_soft_struct {
- long cwd;
-};
-union i387_union {
- struct i387_soft_struct soft;
-};
-struct thread_struct {
- union i387_union i387;
-};
-void _init_task_union(void) {
- struct thread_struct thread = (struct thread_struct) { {{0}} };
-}
diff --git a/test/FrontendC/2003-11-27-UnionCtorInitialization.c b/test/FrontendC/2003-11-27-UnionCtorInitialization.c
deleted file mode 100644
index e3ae1e9..0000000
--- a/test/FrontendC/2003-11-27-UnionCtorInitialization.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-struct i387_soft_struct {
- long cwd;
- long twd;
- long fip;
-};
-union i387_union {
- struct i387_soft_struct soft;
-};
-struct thread_struct {
- union i387_union i387;
-};
-void _init_task_union(void) {
- struct thread_struct thread = (struct thread_struct) { {{0}} };
-}
diff --git a/test/FrontendC/2003-12-14-ExternInlineSupport.c b/test/FrontendC/2003-12-14-ExternInlineSupport.c
deleted file mode 100644
index a45eb98..0000000
--- a/test/FrontendC/2003-12-14-ExternInlineSupport.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o - | not grep dead_function
-
-extern __inline__ void dead_function() {}
diff --git a/test/FrontendC/2004-01-01-UnknownInitSize.c b/test/FrontendC/2004-01-01-UnknownInitSize.c
deleted file mode 100644
index b26b6cd..0000000
--- a/test/FrontendC/2004-01-01-UnknownInitSize.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -S %s -o /dev/null
-
-/*
- * This regression test ensures that the C front end can compile initializers
- * even when it cannot determine the size (as below).
-*/
-struct one
-{
- int a;
- int values [];
-};
-
-struct one hobbit = {5, {1, 2, 3}};
-
diff --git a/test/FrontendC/2004-01-08-ExternInlineRedefine.c b/test/FrontendC/2004-01-08-ExternInlineRedefine.c
deleted file mode 100644
index 4366b9b..0000000
--- a/test/FrontendC/2004-01-08-ExternInlineRedefine.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-extern __inline long int
-__strtol_l (int a)
-{
- return 0;
-}
-
-long int
-__strtol_l (int a)
-{
- return 0;
-}
diff --git a/test/FrontendC/2004-02-12-LargeAggregateCopy.c b/test/FrontendC/2004-02-12-LargeAggregateCopy.c
deleted file mode 100644
index 93b7fe4..0000000
--- a/test/FrontendC/2004-02-12-LargeAggregateCopy.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o - | grep llvm.memcpy
-
-struct X { int V[10000]; };
-struct X Global1, Global2;
-void test() {
- Global2 = Global1;
-}
-
diff --git a/test/FrontendC/2004-02-13-BuiltinFrameReturnAddress.c b/test/FrontendC/2004-02-13-BuiltinFrameReturnAddress.c
deleted file mode 100644
index f115b5a..0000000
--- a/test/FrontendC/2004-02-13-BuiltinFrameReturnAddress.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o - | grep llvm.*address | count 4
-
-void *test1() {
- return __builtin_return_address(1);
-}
-void *test2() {
- return __builtin_frame_address(0);
-}
diff --git a/test/FrontendC/2004-02-13-IllegalVararg.c b/test/FrontendC/2004-02-13-IllegalVararg.c
deleted file mode 100644
index 0d003c8..0000000
--- a/test/FrontendC/2004-02-13-IllegalVararg.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc -xc %s -w -S -o - | llc
-// XFAIL: *
-// See PR2452
-
-#include <stdarg.h>
-
-float test(int X, ...) {
- va_list ap;
- float F;
- va_start(ap, X);
- F = va_arg(ap, float);
- return F;
-}
diff --git a/test/FrontendC/2004-02-13-Memset.c b/test/FrontendC/2004-02-13-Memset.c
deleted file mode 100644
index fb6ed23..0000000
--- a/test/FrontendC/2004-02-13-Memset.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o - | grep llvm.memset | count 3
-
-void *memset(void*, int, long);
-void bzero(void*, long);
-
-void test(int* X, char *Y) {
- memset(X, 4, 1000);
- bzero(Y, 100);
-}
diff --git a/test/FrontendC/2004-02-14-ZeroInitializer.c b/test/FrontendC/2004-02-14-ZeroInitializer.c
deleted file mode 100644
index bede907..0000000
--- a/test/FrontendC/2004-02-14-ZeroInitializer.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o - | grep zeroinitializer
-
-int X[1000];
-
diff --git a/test/FrontendC/2004-02-20-Builtins.c b/test/FrontendC/2004-02-20-Builtins.c
deleted file mode 100644
index c056a84..0000000
--- a/test/FrontendC/2004-02-20-Builtins.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -O3 -xc %s -S -o - | not grep builtin
-
-#include <math.h>
-
-void zsqrtxxx(float num) {
- num = sqrt(num);
-}
-
diff --git a/test/FrontendC/2004-03-07-ComplexDivEquals.c b/test/FrontendC/2004-03-07-ComplexDivEquals.c
deleted file mode 100644
index c6c805a..0000000
--- a/test/FrontendC/2004-03-07-ComplexDivEquals.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-void test(__complex__ double D, double X) {
- D /= X;
-}
diff --git a/test/FrontendC/2004-03-07-ExternalConstant.c b/test/FrontendC/2004-03-07-ExternalConstant.c
deleted file mode 100644
index 4a9094b..0000000
--- a/test/FrontendC/2004-03-07-ExternalConstant.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o - | grep constant
-
-extern const int a[]; // 'a' should be marked constant even though it's external!
-int foo () {
- return a[0];
-}
-
diff --git a/test/FrontendC/2004-03-09-LargeArrayInitializers.c b/test/FrontendC/2004-03-09-LargeArrayInitializers.c
deleted file mode 100644
index 265206f..0000000
--- a/test/FrontendC/2004-03-09-LargeArrayInitializers.c
+++ /dev/null
@@ -1,32 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-// Test that these initializers are handled efficiently
-
-int test(int x) {
- const int XX[1000] = { 0, 0 };
- const char S [1000] = "foo";
-
- const int array[] = {
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49,
- };
- return array[x];
-}
diff --git a/test/FrontendC/2004-03-15-SimpleIndirectGoto.c b/test/FrontendC/2004-03-15-SimpleIndirectGoto.c
deleted file mode 100644
index a3f27b2..0000000
--- a/test/FrontendC/2004-03-15-SimpleIndirectGoto.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-int code[]={0,0,0,0,1};
-void foo(int x) {
- volatile int b;
- b = 0xffffffff;
-}
-void bar(int *pc) {
- static const void *l[] = {&&lab0, &&end};
-
- foo(0);
- goto *l[*pc];
- lab0:
- foo(0);
- pc++;
- goto *l[*pc];
- end:
- return;
-}
-int main() {
- bar(code);
- return 0;
-}
diff --git a/test/FrontendC/2004-03-16-AsmRegisterCrash.c b/test/FrontendC/2004-03-16-AsmRegisterCrash.c
deleted file mode 100644
index f13368c..0000000
--- a/test/FrontendC/2004-03-16-AsmRegisterCrash.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-int foo() {
-#ifdef __ppc__
- register int X __asm__("r1");
-#else
- register int X __asm__("ebx");
-#endif
- return X;
-}
diff --git a/test/FrontendC/2004-05-07-VarArrays.c b/test/FrontendC/2004-05-07-VarArrays.c
deleted file mode 100644
index 3a39c4f..0000000
--- a/test/FrontendC/2004-05-07-VarArrays.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-int foo(int len, char arr[][len], int X) {
- return arr[X][0];
-}
diff --git a/test/FrontendC/2004-05-21-IncompleteEnum.c b/test/FrontendC/2004-05-21-IncompleteEnum.c
deleted file mode 100644
index 958a8d1..0000000
--- a/test/FrontendC/2004-05-21-IncompleteEnum.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc -w -S %s -o - | llvm-as -o /dev/null
-
-void test(enum foo *X) {
-}
-
diff --git a/test/FrontendC/2004-06-08-OpaqueStructArg.c b/test/FrontendC/2004-06-08-OpaqueStructArg.c
deleted file mode 100644
index 5dfdd83..0000000
--- a/test/FrontendC/2004-06-08-OpaqueStructArg.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
- struct fu;
- void foo(struct fu);
- void bar() {
- foo;
- }
diff --git a/test/FrontendC/2004-06-17-UnorderedBuiltins.c b/test/FrontendC/2004-06-17-UnorderedBuiltins.c
deleted file mode 100644
index 02780f0..0000000
--- a/test/FrontendC/2004-06-17-UnorderedBuiltins.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-_Bool A, B, C, D, E, F, G, H;
-void TestF(float X, float Y) {
- A = __builtin_isgreater(X, Y);
- B = __builtin_isgreaterequal(X, Y);
- C = __builtin_isless(X, Y);
- D = __builtin_islessequal(X, Y);
- E = __builtin_islessgreater(X, Y);
- F = __builtin_isunordered(X, Y);
- //G = __builtin_isordered(X, Y); // Our current snapshot of GCC doesn't include this builtin
- H = __builtin_isunordered(X, Y);
-}
-void TestD(double X, double Y) {
- A = __builtin_isgreater(X, Y);
- B = __builtin_isgreaterequal(X, Y);
- C = __builtin_isless(X, Y);
- D = __builtin_islessequal(X, Y);
- E = __builtin_islessgreater(X, Y);
- F = __builtin_isunordered(X, Y);
- //G = __builtin_isordered(X, Y); // Our current snapshot doesn't include this builtin. FIXME
- H = __builtin_isunordered(X, Y);
-}
diff --git a/test/FrontendC/2004-06-17-UnorderedCompares.c b/test/FrontendC/2004-06-17-UnorderedCompares.c
deleted file mode 100644
index 286e7bc..0000000
--- a/test/FrontendC/2004-06-17-UnorderedCompares.c
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %llvmgcc -xc -std=c99 %s -S -o - | grep -v llvm.isunordered | not grep call
-
-#include <math.h>
-
-_Bool A, B, C, D, E, F;
-void TestF(float X, float Y) {
- A = __builtin_isgreater(X, Y);
- B = __builtin_isgreaterequal(X, Y);
- C = __builtin_isless(X, Y);
- D = __builtin_islessequal(X, Y);
- E = __builtin_islessgreater(X, Y);
- F = __builtin_isunordered(X, Y);
-}
-void TestD(double X, double Y) {
- A = __builtin_isgreater(X, Y);
- B = __builtin_isgreaterequal(X, Y);
- C = __builtin_isless(X, Y);
- D = __builtin_islessequal(X, Y);
- E = __builtin_islessgreater(X, Y);
- F = __builtin_isunordered(X, Y);
-}
diff --git a/test/FrontendC/2004-06-18-VariableLengthArrayOfStructures.c b/test/FrontendC/2004-06-18-VariableLengthArrayOfStructures.c
deleted file mode 100644
index 3e450a4..0000000
--- a/test/FrontendC/2004-06-18-VariableLengthArrayOfStructures.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-struct S { };
-
-int xxxx(int a) {
- struct S comps[a];
- comps[0];
-}
-
diff --git a/test/FrontendC/2004-07-06-FunctionCast.c b/test/FrontendC/2004-07-06-FunctionCast.c
deleted file mode 100644
index 6d80f86..0000000
--- a/test/FrontendC/2004-07-06-FunctionCast.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-static int unused_func(void) {
- return 1;
-}
-
-int foo(void) {
- (void)unused_func; /* avoid compiler warning */
- return 2;
-}
diff --git a/test/FrontendC/2004-08-06-LargeStructTest.c b/test/FrontendC/2004-08-06-LargeStructTest.c
deleted file mode 100644
index 8fbb7f8..0000000
--- a/test/FrontendC/2004-08-06-LargeStructTest.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-
-#define A(X) int X;
-#define B(X) A(X##0) A(X##1) A(X##2) A(X##3) A(X##4) A(X##5) A(X##6) A(X##7) \
- A(X##8) A(X##9) A(X##A) A(X##B) A(X##C) A(X##D) A(X##E) A(X##F)
-#define C(X) B(X##0) B(X##1) B(X##2) B(X##3) B(X##4) B(X##5) B(X##6) B(X##7) \
- B(X##8) B(X##9) B(X##A) B(X##B) B(X##C) B(X##D) B(X##E) B(X##F)
-
-struct foo {
- C(x); // 256
- C(y); // 256
- C(z);
-};
-
-
-int test(struct foo *F) {
- return F->xA1 + F->yFF + F->zC4;
-}
diff --git a/test/FrontendC/2004-11-25-UnnamedBitfieldPadding.c b/test/FrontendC/2004-11-25-UnnamedBitfieldPadding.c
deleted file mode 100644
index b3f4a82..0000000
--- a/test/FrontendC/2004-11-25-UnnamedBitfieldPadding.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o /dev/null
-// This is a testcase for PR461
-typedef struct {
- unsigned min_align: 1;
- unsigned : 1;
-} addr_diff_vec_flags;
-
-addr_diff_vec_flags X;
diff --git a/test/FrontendC/2004-11-27-InvalidConstantExpr.c b/test/FrontendC/2004-11-27-InvalidConstantExpr.c
deleted file mode 100644
index ee8642f..0000000
--- a/test/FrontendC/2004-11-27-InvalidConstantExpr.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | not grep {foo\\* sub}
-// This should not produce a subtrace constantexpr of a pointer
-struct foo {
- int Y;
- char X[100];
-} F;
-
-int test(char *Y) {
- return Y - F.X;
-}
diff --git a/test/FrontendC/2004-11-27-StaticFunctionRedeclare.c b/test/FrontendC/2004-11-27-StaticFunctionRedeclare.c
deleted file mode 100644
index 994ac8f..0000000
--- a/test/FrontendC/2004-11-27-StaticFunctionRedeclare.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | \
-// RUN: opt -std-compile-opts -S | not grep {declare i32.*func}
-
-// There should not be an unresolved reference to func here. Believe it or not,
-// the "expected result" is a function named 'func' which is internal and
-// referenced by bar().
-
-// This is PR244
-
-static int func();
-void bar() {
- int func();
- foo(func);
-}
-static int func(char** A, char ** B) {}
diff --git a/test/FrontendC/2004-11-27-VariableSizeInStructure.c b/test/FrontendC/2004-11-27-VariableSizeInStructure.c
deleted file mode 100644
index bd63ae3..0000000
--- a/test/FrontendC/2004-11-27-VariableSizeInStructure.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc %s -S -o /dev/null
-
-// GCC allows variable sized arrays in structures, crazy!
-
-// This is PR360.
-
-int sub1(int i, char *pi) {
- typedef int foo[i];
- struct bar {foo f1; int f2;} *p = (struct bar *) pi;
- return p->f2;
-}
diff --git a/test/FrontendC/2005-01-02-ConstantInits.c b/test/FrontendC/2005-01-02-ConstantInits.c
deleted file mode 100644
index 735278e..0000000
--- a/test/FrontendC/2005-01-02-ConstantInits.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-// This tests all kinds of hard cases with initializers and
-// array subscripts. This corresponds to PR487.
-
-struct X { int a[2]; };
-
-int test() {
- static int i23 = (int) &(((struct X *)0)->a[1]);
- return i23;
-}
-
-int i = (int) &( ((struct X *)0) -> a[1]);
-
-int Arr[100];
-
-int foo(int i) { return bar(&Arr[49])+bar(&Arr[i]); }
-int foo2(int i) {
- static const int *X = &Arr[49];
- static int i23 = (int) &( ((struct X *)0) -> a[0]);
- int *P = Arr;
- ++P;
- return bar(Arr+i);
-}
diff --git a/test/FrontendC/2005-01-02-PointerDifference.c b/test/FrontendC/2005-01-02-PointerDifference.c
deleted file mode 100644
index 2c108e5..0000000
--- a/test/FrontendC/2005-01-02-PointerDifference.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o - | grep -v div
-
-int Diff(int *P, int *Q) { return P-Q; }
diff --git a/test/FrontendC/2005-01-02-VAArgError-ICE.c b/test/FrontendC/2005-01-02-VAArgError-ICE.c
deleted file mode 100644
index db82558..0000000
--- a/test/FrontendC/2005-01-02-VAArgError-ICE.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// This file is erroneous, but should not cause the compiler to ICE.
-// PR481
-// RUN: %llvmgcc %s -S -o /dev/null |& not grep {internal compiler error}
-
-#include <stdarg.h>
-int flags(int a, int b, ...) {
- va_list args;
- va_start(args,a); // not the last named arg
- foo(args);
-}
diff --git a/test/FrontendC/2005-02-20-AggregateSAVEEXPR.c b/test/FrontendC/2005-02-20-AggregateSAVEEXPR.c
deleted file mode 100644
index 7a95533..0000000
--- a/test/FrontendC/2005-02-20-AggregateSAVEEXPR.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgcc %s -o /dev/null -S
-// Note:
-// We fail this on Sparc because the C library seems to be missing complex.h
-// and the corresponding C99 complex support.
-//
-// We could modify the test to use only GCC extensions, but I don't know if
-// that would change the nature of the test.
-//
-// XFAIL: sparc
-
-#ifdef __CYGWIN__
- #include <mingw/complex.h>
-#else
- #include <complex.h>
-#endif
-
-int foo(complex float c) {
- return creal(c);
-}
diff --git a/test/FrontendC/2005-02-27-MarkGlobalConstant.c b/test/FrontendC/2005-02-27-MarkGlobalConstant.c
deleted file mode 100644
index 6806c94..0000000
--- a/test/FrontendC/2005-02-27-MarkGlobalConstant.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -xc %s -S -o - | grep {private unnamed_addr constant }
-
-// The synthetic global made by the CFE for big initializer should be marked
-// constant.
-
-void bar();
-void foo() {
- char Blah[] = "asdlfkajsdlfkajsd;lfkajds;lfkjasd;flkajsd;lkfja;sdlkfjasd";
- bar(Blah);
-}
diff --git a/test/FrontendC/2005-03-05-OffsetOfHack.c b/test/FrontendC/2005-03-05-OffsetOfHack.c
deleted file mode 100644
index 8df7231..0000000
--- a/test/FrontendC/2005-03-05-OffsetOfHack.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-struct s {
- unsigned long int field[0];
-};
-
-#define OFFS \
- (((char *) &((struct s *) 0)->field[0]) - (char *) 0)
-
-int foo[OFFS];
-
-
diff --git a/test/FrontendC/2005-03-06-OffsetOfStructCrash.c b/test/FrontendC/2005-03-06-OffsetOfStructCrash.c
deleted file mode 100644
index 91e6862..0000000
--- a/test/FrontendC/2005-03-06-OffsetOfStructCrash.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-struct Y {};
-struct XXX {
- struct Y F;
-};
-
-void test1() {
- (int)&((struct XXX*)(((void *)0)))->F;
-}
-
-void test2() {
- &((struct XXX*)(((void *)0)))->F;
-}
diff --git a/test/FrontendC/2005-03-11-Prefetch.c b/test/FrontendC/2005-03-11-Prefetch.c
deleted file mode 100644
index bf79653..0000000
--- a/test/FrontendC/2005-03-11-Prefetch.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | llvm-as | llvm-dis | grep llvm.prefetch
-
-void foo(int *P) {
- __builtin_prefetch(P);
- __builtin_prefetch(P, 1);
-}
diff --git a/test/FrontendC/2005-04-09-ComplexOps.c b/test/FrontendC/2005-04-09-ComplexOps.c
deleted file mode 100644
index 2962b74..0000000
--- a/test/FrontendC/2005-04-09-ComplexOps.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-#include <math.h>
-#define I 1.0iF
-
-double __complex test(double X) { return ~-(X*I); }
-
-_Bool EQ(double __complex A, double __complex B) { return A == B; }
-_Bool NE(double __complex A, double __complex B) { return A != B; }
diff --git a/test/FrontendC/2005-05-06-CountBuiltins.c b/test/FrontendC/2005-05-06-CountBuiltins.c
deleted file mode 100644
index da40a14..0000000
--- a/test/FrontendC/2005-05-06-CountBuiltins.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | llvm-as | llvm-dis | not grep call.*__builtin
-
-int G, H, I;
-void foo(int P) {
- G = __builtin_clz(P);
- H = __builtin_ctz(P);
- I = __builtin_popcount(P);
-}
-
-long long g, h, i;
-void fooll(float P) {
- g = __builtin_clzll(P);
- g = __builtin_clzll(P);
- h = __builtin_ctzll(P);
- i = __builtin_popcountll(P);
-}
-
diff --git a/test/FrontendC/2005-05-10-GlobalUnionInit.c b/test/FrontendC/2005-05-10-GlobalUnionInit.c
deleted file mode 100644
index 443064c..0000000
--- a/test/FrontendC/2005-05-10-GlobalUnionInit.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-union A { // { uint }
- union B { double *C; } D;
-} E = { { (double*)12312 } };
-
diff --git a/test/FrontendC/2005-06-15-ExpandGotoInternalProblem.c b/test/FrontendC/2005-06-15-ExpandGotoInternalProblem.c
deleted file mode 100644
index 0f076c9..0000000
--- a/test/FrontendC/2005-06-15-ExpandGotoInternalProblem.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -std=c99 %s -S -o - | \
-// RUN: opt -std-compile-opts -disable-output
-// PR580
-
-int X, Y;
-int foo() {
- int i;
- for (i=0; i<100; i++ )
- {
- break;
- i = ( X || Y ) ;
- }
-}
-
diff --git a/test/FrontendC/2005-07-20-SqrtNoErrno.c b/test/FrontendC/2005-07-20-SqrtNoErrno.c
deleted file mode 100644
index a321a38..0000000
--- a/test/FrontendC/2005-07-20-SqrtNoErrno.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc %s -S -o - -fno-math-errno | FileCheck %s
-// llvm.sqrt has undefined behavior on negative inputs, so it is
-// inappropriate to translate C/C++ sqrt to this.
-#include <math.h>
-
-float foo(float X) {
-// CHECK: foo
-// CHECK: sqrtf(float %1) nounwind readonly
- // Check that this is marked readonly when errno is ignored.
- return sqrtf(X);
-}
diff --git a/test/FrontendC/2005-07-26-UnionInitCrash.c b/test/FrontendC/2005-07-26-UnionInitCrash.c
deleted file mode 100644
index 563278a..0000000
--- a/test/FrontendC/2005-07-26-UnionInitCrash.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// PR607
-// RUN: %llvmgcc %s -S -o -
-union { char bytes[8]; double alignment; }EQ1 = {0,0,0,0,0,0,0,0};
diff --git a/test/FrontendC/2005-07-28-IncorrectWeakGlobal.c b/test/FrontendC/2005-07-28-IncorrectWeakGlobal.c
deleted file mode 100644
index 1a8c409..0000000
--- a/test/FrontendC/2005-07-28-IncorrectWeakGlobal.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | grep TheGlobal | not grep weak
-
-extern int TheGlobal;
-int foo() { return TheGlobal; }
-int TheGlobal = 1;
diff --git a/test/FrontendC/2005-09-20-ComplexConstants.c b/test/FrontendC/2005-09-20-ComplexConstants.c
deleted file mode 100644
index 209adc5..0000000
--- a/test/FrontendC/2005-09-20-ComplexConstants.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | llvm-as -o /dev/null
-
-const double _Complex x[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-
diff --git a/test/FrontendC/2005-09-24-AsmUserPrefix.c b/test/FrontendC/2005-09-24-AsmUserPrefix.c
deleted file mode 100644
index 952c7b3..0000000
--- a/test/FrontendC/2005-09-24-AsmUserPrefix.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | opt -std-compile-opts | llc | \
-// RUN: not grep _foo2
-
-void foo() __asm__("foo2");
-
-void bar() {
- foo();
-}
diff --git a/test/FrontendC/2005-09-24-BitFieldCrash.c b/test/FrontendC/2005-09-24-BitFieldCrash.c
deleted file mode 100644
index b4c85ff..0000000
--- a/test/FrontendC/2005-09-24-BitFieldCrash.c
+++ /dev/null
@@ -1,33 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-struct tree_common {};
-
-struct tree_int_cst {
- struct tree_common common;
- struct tree_int_cst_lowhi {
- unsigned long long low;
- long long high;
- } int_cst;
-};
-
-enum XXX { yyy };
-
-struct tree_function_decl {
- struct tree_common common;
- long long locus, y;
- __extension__ enum XXX built_in_class : 2;
-
-};
-
-
-union tree_node {
- struct tree_int_cst int_cst;
- struct tree_function_decl function_decl;
-};
-
-
-void foo (union tree_node * decl) {
- decl->function_decl.built_in_class != 0;
-}
-
-
diff --git a/test/FrontendC/2005-10-18-VariableSizedElementCrash.c b/test/FrontendC/2005-10-18-VariableSizedElementCrash.c
deleted file mode 100644
index b916662..0000000
--- a/test/FrontendC/2005-10-18-VariableSizedElementCrash.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-int sub1(int i, char *pi) {
- typedef int foo[i];
- struct bar {foo f1; int f2:3; int f3:4;} *p = (struct bar *) pi;
- xxx(p->f1);
- return p->f3;
-}
-
diff --git a/test/FrontendC/2005-12-04-AttributeUsed.c b/test/FrontendC/2005-12-04-AttributeUsed.c
deleted file mode 100644
index f47e977..0000000
--- a/test/FrontendC/2005-12-04-AttributeUsed.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | llvm-as | llvm-dis | \
-// RUN: grep llvm.used | grep foo | grep X
-
-int X __attribute__((used));
-int Y;
-
-__attribute__((used)) void foo() {}
-
diff --git a/test/FrontendC/2005-12-04-DeclarationLineNumbers.c b/test/FrontendC/2005-12-04-DeclarationLineNumbers.c
deleted file mode 100644
index f3f69dd..0000000
--- a/test/FrontendC/2005-12-04-DeclarationLineNumbers.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %llvmgcc %s -S -g -o - | grep DW_TAG_compile_unit | count 1
-// PR664: ensure that line #'s are emitted for declarations
-
-
-short test(short br_data_0,
-short br_data_1,
-short br_data_2,
-short br_data_3,
-short br_data_4,
-short br_data_5,
-short br_data_6,
-short br_data_7) {
-
-short sm07 = br_data_0 + br_data_7;
-short sm16 = br_data_1 + br_data_6;
-short sm25 = br_data_2 + br_data_5;
-short sm34 = br_data_3 + br_data_4;
-short s0734 = sm07 + sm34;
-short s1625 = sm16 + sm25;
-
-return s0734 + s1625;
-}
-
diff --git a/test/FrontendC/2006-01-13-Includes.c b/test/FrontendC/2006-01-13-Includes.c
deleted file mode 100644
index 7fa0b3b..0000000
--- a/test/FrontendC/2006-01-13-Includes.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc %s -g -S -o - | grep {test/FrontendC}
-// PR676
-
-#include <stdio.h>
-
-void test() {
- printf("Hello World\n");
-}
diff --git a/test/FrontendC/2006-01-13-StackSave.c b/test/FrontendC/2006-01-13-StackSave.c
deleted file mode 100644
index ae8d908..0000000
--- a/test/FrontendC/2006-01-13-StackSave.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// PR691
-// RUN: %llvmgcc %s -S -o - | opt -std-compile-opts | \
-// RUN: llvm-dis | grep llvm.stacksave
-
-void test(int N) {
- int i;
- for (i = 0; i < N; ++i) {
- int VLA[i];
- external(VLA);
- }
-}
diff --git a/test/FrontendC/2006-01-16-BitCountIntrinsicsUnsigned.c b/test/FrontendC/2006-01-16-BitCountIntrinsicsUnsigned.c
deleted file mode 100644
index eafcb62..0000000
--- a/test/FrontendC/2006-01-16-BitCountIntrinsicsUnsigned.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep {llvm.ctlz.i32(i32} | count 3
-// RUN: %llvmgcc -S %s -o - | grep {llvm.ctlz.i32(i32} | grep declare | count 1
-
-unsigned t2(unsigned X) {
- return __builtin_clz(X);
-}
-int t1(int X) {
- return __builtin_clz(X);
-}
diff --git a/test/FrontendC/2006-01-23-FileScopeAsm.c b/test/FrontendC/2006-01-23-FileScopeAsm.c
deleted file mode 100644
index 80e7195..0000000
--- a/test/FrontendC/2006-01-23-FileScopeAsm.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | opt -std-compile-opts | \
-// RUN: llvm-dis | grep {foo\[12345\]} | count 5
-
-__asm__ ("foo1");
-__asm__ ("foo2");
-__asm__ ("foo3");
-__asm__ ("foo4");
-__asm__ ("foo5");
diff --git a/test/FrontendC/2006-03-03-MissingInitializer.c b/test/FrontendC/2006-03-03-MissingInitializer.c
deleted file mode 100644
index 5e027b1..0000000
--- a/test/FrontendC/2006-03-03-MissingInitializer.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | opt -std-compile-opts | \
-// RUN: llvm-dis | grep {@nate.*internal unnamed_addr global i32 0}
-
-struct X { int *XX; int Y;};
-
-void foo() {
- static int nate = 0;
- struct X bob = { &nate, 14 };
- bar(&bob);
-}
-
diff --git a/test/FrontendC/2006-03-16-VectorCtor.c b/test/FrontendC/2006-03-16-VectorCtor.c
deleted file mode 100644
index b95593b..0000000
--- a/test/FrontendC/2006-03-16-VectorCtor.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// Test that basic generic vector support works
-// RUN: %llvmgcc %s -S -o -
-
-typedef int v4si __attribute__ ((__vector_size__ (16)));
-void test(v4si *P, v4si *Q, float X) {
- *P = (v4si){ X, X, X, X } * *Q;
-}
-
-v4si G = (v4si){ 0.1, 1.2, 4.2, 17.2 };
-
diff --git a/test/FrontendC/2006-03-17-KnRMismatch.c b/test/FrontendC/2006-03-17-KnRMismatch.c
deleted file mode 100644
index 1939112..0000000
--- a/test/FrontendC/2006-03-17-KnRMismatch.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-void regnode(int op);
-
-void regnode(op)
-char op;
-{
-}
diff --git a/test/FrontendC/2006-05-01-AppleAlignmentPragma.c b/test/FrontendC/2006-05-01-AppleAlignmentPragma.c
deleted file mode 100644
index 233968b..0000000
--- a/test/FrontendC/2006-05-01-AppleAlignmentPragma.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-#ifdef __APPLE__
-/* test that X is laid out correctly when this pragma is used. */
-#pragma options align=mac68k
-#endif
-
-struct S {
- unsigned A;
- unsigned short B;
-} X;
-
diff --git a/test/FrontendC/2006-05-19-SingleEltReturn.c b/test/FrontendC/2006-05-19-SingleEltReturn.c
deleted file mode 100644
index 70c94c6..0000000
--- a/test/FrontendC/2006-05-19-SingleEltReturn.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// Test returning a single element aggregate value containing a double.
-// RUN: %llvmgcc %s -S -o -
-
-struct X {
- double D;
-};
-
-struct Y {
- struct X x;
-};
-
-struct Y bar();
-
-void foo(struct Y *P) {
- *P = bar();
-}
-
-struct Y bar() {
- struct Y a;
- a.x.D = 0;
- return a;
-}
-
diff --git a/test/FrontendC/2006-07-31-PR854.c b/test/FrontendC/2006-07-31-PR854.c
deleted file mode 100644
index 3802de8..0000000
--- a/test/FrontendC/2006-07-31-PR854.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -w %s -S -o -
-// PR854
- struct kernel_symbol {
- unsigned long value;
- };
- unsigned long loops_per_jiffy = (1<<12);
- static const char __kstrtab_loops_per_jiffy[]
-__attribute__((section("__ksymtab_strings"))) = "loops_per_jiffy";
- static const struct kernel_symbol __ksymtab_loops_per_jiffy
-__attribute__((__used__)) __attribute__((section("__ksymtab"))) = { (unsigned
-long)&loops_per_jiffy, __kstrtab_loops_per_jiffy };
diff --git a/test/FrontendC/2006-09-11-BitfieldRefCrash.c b/test/FrontendC/2006-09-11-BitfieldRefCrash.c
deleted file mode 100644
index d06cc3a..0000000
--- a/test/FrontendC/2006-09-11-BitfieldRefCrash.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-// PR906
-
-struct state_struct {
- unsigned long long phys_frame: 50;
- unsigned valid : 2;
-} s;
-
-int mem_access(struct state_struct *p) {
- return p->valid;
-}
-
diff --git a/test/FrontendC/2006-09-18-fwrite-cast-crash.c b/test/FrontendC/2006-09-18-fwrite-cast-crash.c
deleted file mode 100644
index a693c56..0000000
--- a/test/FrontendC/2006-09-18-fwrite-cast-crash.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc %s -S -o /dev/null
-// PR910
-// XFAIL: *
-// See PR2452
-
-struct l_struct_2E_FILE { char x; };
-unsigned fwrite(signed char *, unsigned , unsigned , signed char *);
-static signed char str301[39];
-static void Usage(signed char *ltmp_611_6) {
- struct l_struct_2E_FILE *ltmp_6202_16;
- unsigned ltmp_6203_92;
- ltmp_6203_92 = /*tail*/ ((unsigned (*) (signed char *, unsigned , unsigned ,
-struct l_struct_2E_FILE *))(void*)fwrite)((&(str301[0u])), 38u, 1u, ltmp_6202_16);
-}
-
diff --git a/test/FrontendC/2006-09-21-IncompleteElementType.c b/test/FrontendC/2006-09-21-IncompleteElementType.c
deleted file mode 100644
index a509182..0000000
--- a/test/FrontendC/2006-09-21-IncompleteElementType.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: not %llvmgcc %s -S -o /dev/null |& not grep {internal compiler error}
-
-struct A X[(927 - 37) / sizeof(struct A)];
diff --git a/test/FrontendC/2006-09-25-DebugFilename.c b/test/FrontendC/2006-09-25-DebugFilename.c
deleted file mode 100644
index eea52ba..0000000
--- a/test/FrontendC/2006-09-25-DebugFilename.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: not %llvmgcc -xc %s -S -o /dev/null |& \
-// RUN: grep fluffy | grep 2006-09-25-DebugFilename.c
-#include "2006-09-25-DebugFilename.h"
-int func1() { return hfunc1(); }
-int func2() { fluffy; return hfunc1(); }
-
diff --git a/test/FrontendC/2006-09-25-DebugFilename.h b/test/FrontendC/2006-09-25-DebugFilename.h
deleted file mode 100644
index 9b03666..0000000
--- a/test/FrontendC/2006-09-25-DebugFilename.h
+++ /dev/null
@@ -1,6 +0,0 @@
-extern int exfunc(int a);
-
-static inline int hfunc1()
-{
- return exfunc(1);
-}
diff --git a/test/FrontendC/2006-09-28-SimpleAsm.c b/test/FrontendC/2006-09-28-SimpleAsm.c
deleted file mode 100644
index e304020..0000000
--- a/test/FrontendC/2006-09-28-SimpleAsm.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | grep {ext: xorl %eax, eax; movl}
-// RUN: %llvmgcc %s -S -o - | grep {nonext: xorl %eax, %eax; mov}
-// PR924
-
-void bar() {
- // Extended asm
- asm volatile ("ext: xorl %%eax, eax; movl eax, fs; movl eax, gs %%blah %= %% " : : "r"(1));
- // Non-extended asm.
- asm volatile ("nonext: xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs %%blah %= %% ");
-}
diff --git a/test/FrontendC/2006-10-30-ArrayCrash.c b/test/FrontendC/2006-10-30-ArrayCrash.c
deleted file mode 100644
index 09464dd..0000000
--- a/test/FrontendC/2006-10-30-ArrayCrash.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc -O3 -S -o - %s
-// PR954, PR911
-
-extern void foo();
-
-struct S {
- short f1[3];
- unsigned int f2 : 1;
-};
-
-void bar()
-{
- struct S *A;
-
- if (A->f2)
- foo();
-}
diff --git a/test/FrontendC/2006-12-14-ordered_expr.c b/test/FrontendC/2006-12-14-ordered_expr.c
deleted file mode 100644
index 8ff2eb6..0000000
--- a/test/FrontendC/2006-12-14-ordered_expr.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -O3 -S %s -o - | grep {fcmp ord float %X, %Y}
-
-int test2(float X, float Y) {
- return !__builtin_isunordered(X, Y);
-}
-
diff --git a/test/FrontendC/2007-01-06-KNR-Proto.c b/test/FrontendC/2007-01-06-KNR-Proto.c
deleted file mode 100644
index 6aa74d4..0000000
--- a/test/FrontendC/2007-01-06-KNR-Proto.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S -o - %s
-// PR1083
-
-int svc_register (void (*dispatch) (int));
-
-int svc_register (dispatch)
- void (*dispatch) ();
-{
-}
-
diff --git a/test/FrontendC/2007-01-20-VectorICE.c b/test/FrontendC/2007-01-20-VectorICE.c
deleted file mode 100644
index c2dcdef..0000000
--- a/test/FrontendC/2007-01-20-VectorICE.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-typedef float __m128 __attribute__((__vector_size__(16)));
-typedef long long __v2di __attribute__((__vector_size__(16)));
-typedef int __v4si __attribute__((__vector_size__(16)));
-
-__v2di bar(void);
-void foo(int X, __v4si *P) {
- *P = X == 2 ? bar() : bar();
-}
-
diff --git a/test/FrontendC/2007-01-24-InlineAsmCModifier.c b/test/FrontendC/2007-01-24-InlineAsmCModifier.c
deleted file mode 100644
index c601ccf..0000000
--- a/test/FrontendC/2007-01-24-InlineAsmCModifier.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// Verify that the %c modifier works and strips off any prefixes from
-// immediates.
-// RUN: %llvmgcc -S %s -o - | llc | grep {pickANumber: 789514}
-
-void foo() {
- __asm__ volatile("/* " "pickANumber" ": %c0 */"::"i"(0xC0C0A));
-
- // Check that non-c modifiers work also (not greped for above).
- __asm__ volatile("/* " "pickANumber2 " ": %0 */"::"i"(123));
-}
diff --git a/test/FrontendC/2007-02-04-AddrLValue-2.c b/test/FrontendC/2007-02-04-AddrLValue-2.c
deleted file mode 100644
index fa20faf..0000000
--- a/test/FrontendC/2007-02-04-AddrLValue-2.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc %s -O3 -S -o -
-// PR1173
-
-struct S { char s; };
-struct T { struct S t; };
-
-struct S *const p = &((struct T * const) (0x4000))->t;
-
-void
-foo (void)
-{
- p->s = 0;
-}
diff --git a/test/FrontendC/2007-02-04-AddrLValue.c b/test/FrontendC/2007-02-04-AddrLValue.c
deleted file mode 100644
index 214fce7..0000000
--- a/test/FrontendC/2007-02-04-AddrLValue.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %llvmgcc %s -O3 -S -o -
-// PR1176
-
-typedef struct
-{
- char *key;
- char *value;
-} T1;
-
-typedef struct
-{
- long type;
- char *value;
-} T3;
-
-T1 a[] =
-{
- {
- "",
- ((char *)&((T3) {1, (char *) 1}))
- }
-};
-
diff --git a/test/FrontendC/2007-02-04-EmptyStruct.c b/test/FrontendC/2007-02-04-EmptyStruct.c
deleted file mode 100644
index 5ad2c70..0000000
--- a/test/FrontendC/2007-02-04-EmptyStruct.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc %s -O3 -S -o -
-// PR1175
-
-struct empty { };
-
-void foo(struct empty *p) {
- p++;
-}
-
diff --git a/test/FrontendC/2007-02-04-WITH_SIZE_EXPR.c b/test/FrontendC/2007-02-04-WITH_SIZE_EXPR.c
deleted file mode 100644
index d5a9fbb..0000000
--- a/test/FrontendC/2007-02-04-WITH_SIZE_EXPR.c
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %llvmgcc %s -O3 -S -o -
-// PR1174
-
-void zzz (char *s1, char *s2, int len, int *q)
-{
- int z = 5;
- unsigned int i, b;
- struct { char a[z]; } x;
-
- for (i = 0; i < len; i++)
- s1[i] = s2[i];
-
- b = z & 0x3;
-
- len += (b == 0 ? 0 : 1) + z;
-
- *q = len;
-
- foo (x, x);
-}
-
diff --git a/test/FrontendC/2007-02-05-nested.c b/test/FrontendC/2007-02-05-nested.c
deleted file mode 100644
index bd6d306..0000000
--- a/test/FrontendC/2007-02-05-nested.c
+++ /dev/null
@@ -1,54 +0,0 @@
-// RUN: %llvmgcc -S -fnested-functions -O0 -o - %s
-// PR915
-
-extern void abort(void);
-
-void nest(int n)
-{
- int a = 0;
- int b = 5;
- int c = 0;
- int d = 7;
-
- void o(int i, int j)
- {
- if (i!=j)
- abort();
- }
-
- void f(x)
- int x; /* K&R style */
- {
- int e = 0;
- int f = 2;
- int g = 0;
-
- void y(void)
- {
- c = n;
- e = 1;
- g = x;
- }
-
- void z(void)
- {
- a = 4;
- g = 3;
- }
-
- a = 5;
- y();
- c = x;
- z();
- o(1,e);
- o(2,f);
- o(3,g);
- }
-
- c = 2;
- f(6);
- o(4,a);
- o(5,b);
- o(6,c);
- o(7,d);
-}
diff --git a/test/FrontendC/2007-02-07-AddrLabel.c b/test/FrontendC/2007-02-07-AddrLabel.c
deleted file mode 100644
index 03ed4c9..0000000
--- a/test/FrontendC/2007-02-07-AddrLabel.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// PR947
-// RUN: %llvmgcc %s -S -o -
-
-void foo() {
- void *ptr;
- label:
- ptr = &&label;
-
- goto *ptr;
- }
diff --git a/test/FrontendC/2007-02-16-VariableSizeStructArg.c b/test/FrontendC/2007-02-16-VariableSizeStructArg.c
deleted file mode 100644
index ec6971a..0000000
--- a/test/FrontendC/2007-02-16-VariableSizeStructArg.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S -w %s -o -
-// PR1170
-int f(int a, struct {int b[a];} c) { return c.b[0]; }
-
-int g(struct {int b[1];} c) {
- return c.b[0];
-}
diff --git a/test/FrontendC/2007-02-16-VoidPtrDiff.c b/test/FrontendC/2007-02-16-VoidPtrDiff.c
deleted file mode 100644
index 15df28c..0000000
--- a/test/FrontendC/2007-02-16-VoidPtrDiff.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-void foo(void *ptr, int test) {
- (ptr - ((void *) test + 0x2000));
-}
diff --git a/test/FrontendC/2007-02-16-WritableStrings.c b/test/FrontendC/2007-02-16-WritableStrings.c
deleted file mode 100644
index 8fa7f15..0000000
--- a/test/FrontendC/2007-02-16-WritableStrings.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// Test the -fwritable-strings option.
-
-// RUN: %llvmgcc -O3 -S -o - -fwritable-strings %s | \
-// RUN: grep {internal unnamed_addr global}
-// RUN: %llvmgcc -O3 -S -o - %s | grep {private unnamed_addr constant}
-
-char *X = "foo";
diff --git a/test/FrontendC/2007-02-25-C-DotDotDot.c b/test/FrontendC/2007-02-25-C-DotDotDot.c
deleted file mode 100644
index 3f96fd1..0000000
--- a/test/FrontendC/2007-02-25-C-DotDotDot.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -O0 -S -o - -fno-inline -fno-unit-at-a-time %s | \
-// RUN: grep {call float @foo}
-
-// Make sure the call to foo is compiled as:
-// call float @foo()
-// not
-// call float (...)* bitcast (float ()* @foo to float (...)*)( )
-
-static float foo() { return 0.0; }
-float bar() { return foo()*10.0;}
-
-
diff --git a/test/FrontendC/2007-03-01-VarSizeArrayIdx.c b/test/FrontendC/2007-03-01-VarSizeArrayIdx.c
deleted file mode 100644
index 6ebe796..0000000
--- a/test/FrontendC/2007-03-01-VarSizeArrayIdx.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc %s -O3 -S -o - | grep mul
-// PR1233
-
-float foo(int w, float A[][w], int g, int h) {
- return A[g][0];
-}
-
diff --git a/test/FrontendC/2007-03-05-DataLayout.c b/test/FrontendC/2007-03-05-DataLayout.c
deleted file mode 100644
index 18819f1..0000000
--- a/test/FrontendC/2007-03-05-DataLayout.c
+++ /dev/null
@@ -1,53 +0,0 @@
-// Testcase for PR1242
-// RUN: %llvmgcc -S %s -o - | grep datalayout | \
-// RUN: not grep {"\[Ee\]-p:\[36\]\[24\]:\[36\]\[24\]"}
-// END.
-#include <stdlib.h>
-#define NDIM 3
-#define BODY 01
-typedef double vector[NDIM];
-typedef struct bnode* bodyptr;
-// { i16, double, [3 x double], i32, i32, [3 x double], [3 x double], [3 x
-// double], double, \2 *, \2 * }
-struct bnode {
- short int type;
- double mass;
- vector pos;
- int proc;
- int new_proc;
- vector vel;
- vector acc;
- vector new_acc;
- double phi;
- bodyptr next;
- bodyptr proc_next;
-} body;
-
-#define Type(x) ((x)->type)
-#define Mass(x) ((x)->mass)
-#define Pos(x) ((x)->pos)
-#define Proc(x) ((x)->proc)
-#define New_Proc(x) ((x)->new_proc)
-#define Vel(x) ((x)->vel)
-#define Acc(x) ((x)->acc)
-#define New_Acc(x) ((x)->new_acc)
-#define Phi(x) ((x)->phi)
-#define Next(x) ((x)->next)
-#define Proc_Next(x) ((x)->proc_next)
-
-bodyptr ubody_alloc(int p)
-{
- register bodyptr tmp;
- tmp = (bodyptr)malloc(sizeof(body));
-
- Type(tmp) = BODY;
- Proc(tmp) = p;
- Proc_Next(tmp) = NULL;
- New_Proc(tmp) = p;
- return tmp;
-}
-
-int main(int argc, char** argv) {
- bodyptr b = ubody_alloc(17);
- return 0;
-}
diff --git a/test/FrontendC/2007-03-06-VarSizeInStruct1.c b/test/FrontendC/2007-03-06-VarSizeInStruct1.c
deleted file mode 100644
index b4ae565..0000000
--- a/test/FrontendC/2007-03-06-VarSizeInStruct1.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc %s -w -S -o -
-void* p (int n) {
- struct f {
- char w; char x[n]; char z[];
- } F;
- F.x[0]='x';
- return &F;
-}
diff --git a/test/FrontendC/2007-03-06-VarSizeInStruct2.c b/test/FrontendC/2007-03-06-VarSizeInStruct2.c
deleted file mode 100644
index 13bc3aa..0000000
--- a/test/FrontendC/2007-03-06-VarSizeInStruct2.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-char p (int n) {
- struct f {
- char w; char x[n]; char y[n];
- } F;
-
- return F.x[0];
-}
diff --git a/test/FrontendC/2007-03-26-BitfieldAfterZeroWidth.c b/test/FrontendC/2007-03-26-BitfieldAfterZeroWidth.c
deleted file mode 100644
index 9b6a869..0000000
--- a/test/FrontendC/2007-03-26-BitfieldAfterZeroWidth.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-struct W {};
-struct Y {
- struct W w;
- int i:1;
-} __attribute__ ((packed)) y;
diff --git a/test/FrontendC/2007-03-26-ZeroWidthBitfield.c b/test/FrontendC/2007-03-26-ZeroWidthBitfield.c
deleted file mode 100644
index 89bfb8e..0000000
--- a/test/FrontendC/2007-03-26-ZeroWidthBitfield.c
+++ /dev/null
@@ -1,2 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-struct Z { int :0; } z;
diff --git a/test/FrontendC/2007-03-27-ArrayCompatible.c b/test/FrontendC/2007-03-27-ArrayCompatible.c
deleted file mode 100644
index fa3d2db..0000000
--- a/test/FrontendC/2007-03-27-ArrayCompatible.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S %s -O2 -o - | grep {ret i8 0}
-static char c(int n) {
- char x[2][n];
- x[1][0]=0;
- return *(n+(char *)x);
-}
-
-char d(void) {
- return c(2);
-}
diff --git a/test/FrontendC/2007-03-27-VarLengthArray.c b/test/FrontendC/2007-03-27-VarLengthArray.c
deleted file mode 100644
index b555690..0000000
--- a/test/FrontendC/2007-03-27-VarLengthArray.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep {getelementptr inbounds \\\[0 x i32\\\]}
-extern void f(int *);
-int e(int m, int n) {
- int x[n];
- f(x);
- return x[m];
-}
diff --git a/test/FrontendC/2007-04-05-PackedBitFields-2.c b/test/FrontendC/2007-04-05-PackedBitFields-2.c
deleted file mode 100644
index d9db420..0000000
--- a/test/FrontendC/2007-04-05-PackedBitFields-2.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-# define pck __attribute__((packed))
-
-
-struct pck F {
- unsigned long long i : 12,
- j : 23,
- k : 27,
- l;
-};
-struct F f1;
-
-void foo() {
- f1.l = 5;
-}
diff --git a/test/FrontendC/2007-04-05-PackedBitFields.c b/test/FrontendC/2007-04-05-PackedBitFields.c
deleted file mode 100644
index f9de356..0000000
--- a/test/FrontendC/2007-04-05-PackedBitFields.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-# define pck __attribute__((packed))
-
-
-struct pck E {
- unsigned long long l,
- i : 12,
- j : 23,
- k : 29; };
-
-struct E e1;
-
-void foo() {
- e1.k = 5;
-}
diff --git a/test/FrontendC/2007-04-05-PackedStruct.c b/test/FrontendC/2007-04-05-PackedStruct.c
deleted file mode 100644
index 0d524c4..0000000
--- a/test/FrontendC/2007-04-05-PackedStruct.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-#pragma pack(push, 2)
-
-enum {
- tA = 0,
- tB = 1
-};
-
-struct MyStruct {
- unsigned long A;
- char C;
- void * B;
-};
-
-void bar(){
-struct MyStruct MS = { tB, 0 };
-}
diff --git a/test/FrontendC/2007-04-05-PadBeforeZeroLengthField.c b/test/FrontendC/2007-04-05-PadBeforeZeroLengthField.c
deleted file mode 100644
index acc3821..0000000
--- a/test/FrontendC/2007-04-05-PadBeforeZeroLengthField.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-struct c__ { unsigned int type:4; };
-union A { struct c__ c; } __attribute__((aligned(8)));
-struct B {
- unsigned int retainCount;
- union A objects[];
-};
-void foo(union A * objects, struct B *array, unsigned long k)
-{ array->objects[k] = objects[k]; }
diff --git a/test/FrontendC/2007-04-05-UnPackedStruct.c b/test/FrontendC/2007-04-05-UnPackedStruct.c
deleted file mode 100644
index 9e168ed..0000000
--- a/test/FrontendC/2007-04-05-UnPackedStruct.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-
-enum {
- tA = 0,
- tB = 1
-};
-
-struct MyStruct {
- unsigned long A;
- void * B;
-};
-
-void bar(){
-struct MyStruct MS = { tB, 0 };
-}
diff --git a/test/FrontendC/2007-04-11-InlineAsmStruct.c b/test/FrontendC/2007-04-11-InlineAsmStruct.c
deleted file mode 100644
index 6c6c150..0000000
--- a/test/FrontendC/2007-04-11-InlineAsmStruct.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | llc
-
-struct V { short X, Y; };
-int bar() {
- struct V bar;
- __asm__ volatile("foo %0\n" : "=r"(bar));
- return bar.X;
-}
-
diff --git a/test/FrontendC/2007-04-11-InlineAsmUnion.c b/test/FrontendC/2007-04-11-InlineAsmUnion.c
deleted file mode 100644
index 0144701..0000000
--- a/test/FrontendC/2007-04-11-InlineAsmUnion.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | llc
-
-union U { int x; float p; };
-void foo() {
- union U bar;
- __asm__ volatile("foo %0\n" : "=r"(bar));
-}
diff --git a/test/FrontendC/2007-04-11-InlineStorageClassC89.c b/test/FrontendC/2007-04-11-InlineStorageClassC89.c
deleted file mode 100644
index 834fb07..0000000
--- a/test/FrontendC/2007-04-11-InlineStorageClassC89.c
+++ /dev/null
@@ -1,46 +0,0 @@
-// RUN: %llvmgcc %s -S -O0 -o - | grep define | grep xglobWeak | \
-// RUN: grep weak | count 1
-// RUN: %llvmgcc %s -S -O0 -o - | grep define | grep xextWeak | \
-// RUN: grep weak | count 1
-// RUN: %llvmgcc %s -S -O0 -o - | grep define | \
-// RUN: grep xWeaknoinline | grep weak | count 1
-// RUN: %llvmgcc %s -S -O0 -o - | grep define | \
-// RUN: grep xWeakextnoinline | grep weak | count 1
-// RUN: %llvmgcc %s -S -O0 -o - | grep define | \
-// RUN: grep xglobnoWeak | grep -v internal | grep -v weak | \
-// RUN: grep -v linkonce | count 1
-// RUN: %llvmgcc %s -S -O0 -o - | grep define | \
-// RUN: grep xstatnoWeak | grep internal | count 1
-// RUN: %llvmgcc %s -S -O0 -o - | grep define | \
-// RUN: grep xextnoWeak | grep available_externally | grep -v weak | \
-// RUN: grep -v linkonce | count 1
-inline int xglobWeak(int) __attribute__((weak));
-inline int xglobWeak (int i) {
- return i*2;
-}
-inline int xextWeak(int) __attribute__((weak));
-extern inline int xextWeak (int i) {
- return i*4;
-}
-int xWeaknoinline(int) __attribute__((weak));
-int xWeaknoinline(int i) {
- return i*8;
-}
-int xWeakextnoinline(int) __attribute__((weak));
-extern int xWeakextnoinline(int i) {
- return i*16;
-}
-inline int xglobnoWeak (int i) {
- return i*32;
-}
-static inline int xstatnoWeak (int i) {
- return i*64;
-}
-extern inline int xextnoWeak (int i) {
- return i*128;
-}
-int j(int y) {
- return xglobnoWeak(y)+xstatnoWeak(y)+xextnoWeak(y)+
- xglobWeak(y)+xextWeak(y)+
- xWeakextnoinline(y)+xWeaknoinline(y);
-}
diff --git a/test/FrontendC/2007-04-11-InlineStorageClassC99.c b/test/FrontendC/2007-04-11-InlineStorageClassC99.c
deleted file mode 100644
index 6031071..0000000
--- a/test/FrontendC/2007-04-11-InlineStorageClassC99.c
+++ /dev/null
@@ -1,46 +0,0 @@
-// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep declare | \
-// RUN: grep xglobWeak | grep extern_weak | count 1
-// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \
-// RUN: grep xextWeak | grep weak | count 1
-// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \
-// RUN: grep xWeaknoinline | grep weak | count 1
-// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \
-// RUN: grep xWeakextnoinline | grep weak | count 1
-// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \
-// RUN: grep xglobnoWeak | grep available_externally | grep -v weak | \
-// RUN: grep -v linkonce | count 1
-// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \
-// RUN: grep xstatnoWeak | grep internal | count 1
-// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \
-// RUN: grep xextnoWeak | grep -v available_externally | grep -v weak | \
-// RUN: grep -v linkonce | count 1
-inline int xglobWeak(int) __attribute__((weak));
-inline int xglobWeak (int i) {
- return i*2;
-}
-inline int xextWeak(int) __attribute__((weak));
-extern inline int xextWeak (int i) {
- return i*4;
-}
-int xWeaknoinline(int) __attribute__((weak));
-int xWeaknoinline(int i) {
- return i*8;
-}
-int xWeakextnoinline(int) __attribute__((weak));
-extern int xWeakextnoinline(int i) {
- return i*16;
-}
-inline int xglobnoWeak (int i) {
- return i*32;
-}
-static inline int xstatnoWeak (int i) {
- return i*64;
-}
-extern inline int xextnoWeak (int i) {
- return i*128;
-}
-int j(int y) {
- return xglobnoWeak(y)+xstatnoWeak(y)+xextnoWeak(y)+
- xglobWeak(y)+xextWeak(y)+
- xWeakextnoinline(y)+xWeaknoinline(y);
-}
diff --git a/test/FrontendC/2007-04-11-PR1321.c b/test/FrontendC/2007-04-11-PR1321.c
deleted file mode 100644
index f391329..0000000
--- a/test/FrontendC/2007-04-11-PR1321.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc %s -S -o /dev/null
-
-struct X {
- unsigned int e0 : 17;
- unsigned int e1 : 17;
- unsigned int e2 : 17;
- unsigned int e3 : 17;
- unsigned int e4 : 17;
- unsigned int e5 : 17;
- unsigned int e6 : 17;
- unsigned int e7 : 17;
-} __attribute__((packed)) x;
diff --git a/test/FrontendC/2007-04-13-InlineAsmStruct2.c b/test/FrontendC/2007-04-13-InlineAsmStruct2.c
deleted file mode 100644
index 44ddeb3..0000000
--- a/test/FrontendC/2007-04-13-InlineAsmStruct2.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | grep {call void asm}
-
-struct V { short X, Y; };
-int bar() {
- struct V bar;
- __asm__ volatile("foo %0\n" :: "r"(bar));
- return bar.X;
-}
-
diff --git a/test/FrontendC/2007-04-13-InlineAsmUnion2.c b/test/FrontendC/2007-04-13-InlineAsmUnion2.c
deleted file mode 100644
index a0944a7..0000000
--- a/test/FrontendC/2007-04-13-InlineAsmUnion2.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | grep {call void asm}
-
-union U { int x; char* p; };
-void foo() {
- union U bar;
- __asm__ volatile("foo %0\n" :: "r"(bar));
-}
diff --git a/test/FrontendC/2007-04-14-FNoBuiltin.c b/test/FrontendC/2007-04-14-FNoBuiltin.c
deleted file mode 100644
index 88bf0e0..0000000
--- a/test/FrontendC/2007-04-14-FNoBuiltin.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -O2 -fno-builtin -o - | grep call.*printf
-// Check that -fno-builtin is honored.
-
-extern int printf(const char*, ...);
-void foo(const char *msg) {
- printf("%s\n",msg);
-}
diff --git a/test/FrontendC/2007-04-17-ZeroSizeBitFields.c b/test/FrontendC/2007-04-17-ZeroSizeBitFields.c
deleted file mode 100644
index ec7b7ea..0000000
--- a/test/FrontendC/2007-04-17-ZeroSizeBitFields.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// PR 1332
-// RUN: %llvmgcc %s -S -o /dev/null
-
-struct Z { int a:1; int :0; int c:1; } z;
diff --git a/test/FrontendC/2007-04-24-VolatileStructCopy.c b/test/FrontendC/2007-04-24-VolatileStructCopy.c
deleted file mode 100644
index d49e75e..0000000
--- a/test/FrontendC/2007-04-24-VolatileStructCopy.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -O3 -S -o - %s | grep {volatile store}
-// PR1352
-
-struct foo {
- int x;
-};
-
-void copy(volatile struct foo *p, struct foo *q) {
- *p = *q;
-}
diff --git a/test/FrontendC/2007-04-24-bit-not-expr.c b/test/FrontendC/2007-04-24-bit-not-expr.c
deleted file mode 100644
index fab0b90..0000000
--- a/test/FrontendC/2007-04-24-bit-not-expr.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// PR 1346
-// RUN: %llvmgcc -S %s -o /dev/null
-extern bar(void *);
-
-void f(void *cd) {
- bar(((void *)((unsigned long)(cd) ^ -1)));
-}
diff --git a/test/FrontendC/2007-04-24-str-const.c b/test/FrontendC/2007-04-24-str-const.c
deleted file mode 100644
index 3c3dab3..0000000
--- a/test/FrontendC/2007-04-24-str-const.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc -S %s -o /dev/null
-static char *str;
-
-static const struct {
- const char *name;
- unsigned type;
-} scan_special[] = {
- {"shift", 1},
- {0, 0}
-};
-
-static void
-sb(void)
-{
- while (*str == ' ' || *str == '\t')
- str++;
-}
diff --git a/test/FrontendC/2007-05-07-NestedStructReturn.c b/test/FrontendC/2007-05-07-NestedStructReturn.c
deleted file mode 100644
index aea58e3..0000000
--- a/test/FrontendC/2007-05-07-NestedStructReturn.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc %s -S -fnested-functions -o - | grep {sret *%agg.result}
-
-struct X { long m, n, o, p; };
-
-struct X p(int n) {
- struct X c(int m) {
- struct X x;
- x.m = m;
- x.n = n;
- return x;
- }
- return c(n);
-}
diff --git a/test/FrontendC/2007-05-07-PaddingElements.c b/test/FrontendC/2007-05-07-PaddingElements.c
deleted file mode 100644
index 1e4f4d0..0000000
--- a/test/FrontendC/2007-05-07-PaddingElements.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// PR 1278
-// RUN: %llvmgcc %s -S -O0 -o - | grep {struct.s} | not grep "4 x i8] zeroinitializer"
-// RUN: %llvmgcc %s -S -O0 -o - | not grep "i32 0, i32 2"
-struct s {
- double d1;
- int s1;
-};
-
-struct s foo(void) {
- struct s S = {1.1, 2};
- return S;
-}
diff --git a/test/FrontendC/2007-05-08-PCH.c b/test/FrontendC/2007-05-08-PCH.c
deleted file mode 100644
index aa277ec..0000000
--- a/test/FrontendC/2007-05-08-PCH.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// PR 1400
-// RUN: %llvmgcc -x c-header %s -o /dev/null
-
-int main() {
- return 0;
-}
-
diff --git a/test/FrontendC/2007-05-11-str-const.c b/test/FrontendC/2007-05-11-str-const.c
deleted file mode 100644
index 46a74c1..0000000
--- a/test/FrontendC/2007-05-11-str-const.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc -S -g %s -o /dev/null
-
-static unsigned char out[]={0,1};
-static const unsigned char str1[]="1";
-
diff --git a/test/FrontendC/2007-05-15-PaddingElement.c b/test/FrontendC/2007-05-15-PaddingElement.c
deleted file mode 100644
index bad6a11..0000000
--- a/test/FrontendC/2007-05-15-PaddingElement.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// PR 1419
-
-// RUN: %llvmgcc -xc -O2 %s -S -o - | grep "ret i32 1"
-struct A {
- short x;
- long long :0;
-};
-
-struct B {
- char a;
- char b;
- unsigned char i;
-};
-
-union X { struct A a; struct B b; };
-
-int check(void) {
- union X x, y;
-
- y.b.i = 0xff;
- x = y;
- return (x.b.i == 0xff);
-}
diff --git a/test/FrontendC/2007-05-16-EmptyStruct.c b/test/FrontendC/2007-05-16-EmptyStruct.c
deleted file mode 100644
index 7b2ab61..0000000
--- a/test/FrontendC/2007-05-16-EmptyStruct.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// PR 1417
-
-// RUN: %llvmgcc -xc %s -S -o - | grep "struct.anon = type \{\}"
-
-struct { } *X;
diff --git a/test/FrontendC/2007-05-29-UnionCopy.c b/test/FrontendC/2007-05-29-UnionCopy.c
deleted file mode 100644
index 95ab388..0000000
--- a/test/FrontendC/2007-05-29-UnionCopy.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S -o - %s | grep memcpy
-// PR1421
-
-struct A {
- char c;
- int i;
-};
-
-struct B {
- int c;
- unsigned char x;
-};
-
-union U { struct A a; struct B b; };
-
-void check(union U *u, union U *v) {
- *u = *v;
-}
diff --git a/test/FrontendC/2007-06-05-NoInlineAttribute.c b/test/FrontendC/2007-06-05-NoInlineAttribute.c
deleted file mode 100644
index 9543538..0000000
--- a/test/FrontendC/2007-06-05-NoInlineAttribute.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc -O2 -S %s -o - | grep call
-
-static int bar(int x, int y) __attribute__((noinline));
-
-static int bar(int x, int y)
-{
- return x + y;
-}
-
-int foo(int a, int b) {
- return bar(b, a);
-}
-
diff --git a/test/FrontendC/2007-06-15-AnnotateAttribute.c b/test/FrontendC/2007-06-15-AnnotateAttribute.c
deleted file mode 100644
index 115c3f7..0000000
--- a/test/FrontendC/2007-06-15-AnnotateAttribute.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep llvm.global.annotations
-// RUN: %llvmgcc -S %s -o - | grep llvm.var.annotation | count 3
-
-#include <stdio.h>
-
-/* Global variable with attribute */
-int X __attribute__((annotate("GlobalValAnnotation")));
-
-/* Function with attribute */
-int foo(int y) __attribute__((annotate("GlobalValAnnotation")))
- __attribute__((noinline));
-
-int foo(int y __attribute__((annotate("LocalValAnnotation")))) {
- int x __attribute__((annotate("LocalValAnnotation")));
- x = 34;
- return y + x;
-}
-
-int main() {
- static int a __attribute__((annotate("GlobalValAnnotation")));
- a = foo(2);
- printf("hello world%d\n", a);
- return 0;
-}
diff --git a/test/FrontendC/2007-06-18-SextAttrAggregate.c b/test/FrontendC/2007-06-18-SextAttrAggregate.c
deleted file mode 100644
index c395db2..0000000
--- a/test/FrontendC/2007-06-18-SextAttrAggregate.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc %s -o - -S -O3 | grep {i8 signext}
-// PR1513
-
-struct s{
-long a;
-long b;
-};
-
-void f(struct s a, char *b, signed char C) {
-
-}
diff --git a/test/FrontendC/2007-07-29-RestrictPtrArg.c b/test/FrontendC/2007-07-29-RestrictPtrArg.c
deleted file mode 100644
index 5925d97..0000000
--- a/test/FrontendC/2007-07-29-RestrictPtrArg.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep noalias
-
-void foo(int * __restrict myptr1, int * myptr2) {
- myptr1[0] = 0;
- myptr2[0] = 0;
-}
diff --git a/test/FrontendC/2007-08-01-LoadStoreAlign.c b/test/FrontendC/2007-08-01-LoadStoreAlign.c
deleted file mode 100644
index 5365c06..0000000
--- a/test/FrontendC/2007-08-01-LoadStoreAlign.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc -O3 -S -o - %s | grep {align 1} | count 2
-// RUN: %llvmgcc -O3 -S -o - %s | llc
-
-struct p {
- char a;
- int b;
-} __attribute__ ((packed));
-
-struct p t = { 1, 10 };
-struct p u;
-
-int main () {
- int tmp = t.b;
- u.b = tmp;
- return tmp;
-
-}
diff --git a/test/FrontendC/2007-08-21-ComplexCst.c b/test/FrontendC/2007-08-21-ComplexCst.c
deleted file mode 100644
index ebdee14..0000000
--- a/test/FrontendC/2007-08-21-ComplexCst.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %llvmgcc -O2 -S %s -o /dev/null
-void f(_Complex float z);
-void g() { f(1.0i); }
diff --git a/test/FrontendC/2007-08-22-CTTZ.c b/test/FrontendC/2007-08-22-CTTZ.c
deleted file mode 100644
index 9e74f24..0000000
--- a/test/FrontendC/2007-08-22-CTTZ.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -O2 -S -o - %s | grep {llvm.cttz.i64} | count 2
-// RUN: %llvmgcc -O2 -S -o - %s | not grep {lshr}
-
-int bork(unsigned long long x) {
- return __builtin_ctzll(x);
-}
diff --git a/test/FrontendC/2007-09-05-ConstCtor.c b/test/FrontendC/2007-09-05-ConstCtor.c
deleted file mode 100644
index adae4a6..0000000
--- a/test/FrontendC/2007-09-05-ConstCtor.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -xc -Os -S %s -o /dev/null
-// PR1641
-
-struct A {
- unsigned long l;
-};
-
-void bar(struct A *a);
-
-void bork() {
- const unsigned long vcgt = 1234;
- struct A a = { vcgt };
- bar(&a);
-}
diff --git a/test/FrontendC/2007-09-12-PragmaPack.c b/test/FrontendC/2007-09-12-PragmaPack.c
deleted file mode 100644
index 4fc7f48..0000000
--- a/test/FrontendC/2007-09-12-PragmaPack.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// RUN: %llvmgcc -O3 -S -o - %s | grep {18}
-
-#include <stdint.h>
-
-#pragma pack(push, 1)
-typedef struct
-{
- uint32_t a;
-} foo;
-
-typedef struct {
- uint8_t major;
- uint8_t minor;
- uint16_t build;
-} VERSION;
-
-typedef struct {
- uint8_t a[5];
- VERSION version;
- uint8_t b;
- foo d;
- uint32_t guard;
-} bar;
-#pragma pack(pop)
-
-
-unsigned barsize(void) {
- return sizeof(bar);
-}
-
diff --git a/test/FrontendC/2007-09-14-NegatePointer.c b/test/FrontendC/2007-09-14-NegatePointer.c
deleted file mode 100644
index cb49e46..0000000
--- a/test/FrontendC/2007-09-14-NegatePointer.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -o -
-// PR1662
-
-int foo(unsigned char *test) {
- return 0U - (unsigned int )test;
-}
-
diff --git a/test/FrontendC/2007-09-17-WeakRef.c b/test/FrontendC/2007-09-17-WeakRef.c
deleted file mode 100644
index 6c420ea..0000000
--- a/test/FrontendC/2007-09-17-WeakRef.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -O1 -S %s -o - | grep icmp
-// PR1678
-
-extern void B (void);
-static __typeof(B) A __attribute__ ((__weakref__("B")));
-int active (void)
-{
- static void *const p = __extension__ (void *) &A;
- return p != 0;
-}
diff --git a/test/FrontendC/2007-09-20-GcrootAttribute.c b/test/FrontendC/2007-09-20-GcrootAttribute.c
deleted file mode 100644
index b67b474..0000000
--- a/test/FrontendC/2007-09-20-GcrootAttribute.c
+++ /dev/null
@@ -1,29 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep llvm.gcroot
-// RUN: %llvmgcc -S %s -o - | grep llvm.gcroot | count 6
-// RUN: %llvmgcc -S %s -o - | llvm-as
-
-typedef struct foo_s
-{
- int a;
-} foo, __attribute__ ((gcroot)) *foo_p;
-
-foo my_foo;
-
-int alpha ()
-{
- foo my_foo2 = my_foo;
-
- return my_foo2.a;
-}
-
-int bar (foo a)
-{
- foo_p b;
- return b->a;
-}
-
-foo_p baz (foo_p a, foo_p b, foo_p *c)
-{
- a = b = *c;
- return a;
-}
diff --git a/test/FrontendC/2007-09-26-Alignment.c b/test/FrontendC/2007-09-26-Alignment.c
deleted file mode 100644
index 1638fed..0000000
--- a/test/FrontendC/2007-09-26-Alignment.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep {align 16}
-extern p(int *);
-int q(void) {
- int x __attribute__ ((aligned (16)));
- p(&x);
- return x;
-}
diff --git a/test/FrontendC/2007-09-27-ComplexIntCompare.c b/test/FrontendC/2007-09-27-ComplexIntCompare.c
deleted file mode 100644
index 50626e5..0000000
--- a/test/FrontendC/2007-09-27-ComplexIntCompare.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc -S %s -o -
-// PR1708
-
-#include <stdlib.h>
-
-struct s { _Complex unsigned short x; };
-struct s gs = { 100 + 200i };
-struct s __attribute__((noinline)) foo (void) { return gs; }
-
-int main ()
-{
- if (foo ().x != gs.x)
- abort ();
- exit (0);
-}
-
-
diff --git a/test/FrontendC/2007-09-28-PackedUnionMember.c b/test/FrontendC/2007-09-28-PackedUnionMember.c
deleted file mode 100644
index 79f48ce..0000000
--- a/test/FrontendC/2007-09-28-PackedUnionMember.c
+++ /dev/null
@@ -1,38 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-#pragma pack(push, 2)
-struct H {
- unsigned long f1;
- unsigned long f2;
- union {
- struct opaque1 *f3;
- struct opaque2 *f4;
- struct {
- struct opaque3 *f5;
- unsigned short f6;
- } f7;
- } f8;
-};
-#pragma pack(pop)
-
-struct E {
- unsigned long f1;
- unsigned long f2;
-};
-
-typedef long (*FuncPtr) ();
-
-extern long bork(FuncPtr handler, const struct E *list);
-
-static long hndlr()
-{
- struct H cmd = { 4, 412 };
- return 0;
-}
-void foo(void *inWindow) {
- static const struct E events[] = {
- { 123124, 1 }
- };
- bork(hndlr, events);
-}
-
diff --git a/test/FrontendC/2007-10-01-BuildArrayRef.c b/test/FrontendC/2007-10-01-BuildArrayRef.c
deleted file mode 100644
index e87a5b6..0000000
--- a/test/FrontendC/2007-10-01-BuildArrayRef.c
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: not %llvmgcc_only -c %s -o /dev/null |& FileCheck %s
-// PR 1603
-void func()
-{
- const int *arr;
- arr[0] = 1; // CHECK: error: assignment of read-only location
-}
-
-struct foo {
- int bar;
-};
-struct foo sfoo = { 0 };
-
-int func2()
-{
- const struct foo *fp;
- fp = &sfoo;
- fp[0].bar = 1; // CHECK: error: assignment of read-only member 'bar'
- return sfoo.bar;
-}
diff --git a/test/FrontendC/2007-10-02-VolatileArray.c b/test/FrontendC/2007-10-02-VolatileArray.c
deleted file mode 100644
index 7e8bf24..0000000
--- a/test/FrontendC/2007-10-02-VolatileArray.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep volatile
-// PR1647
-
-void foo(volatile int *p)
-{
-p[0] = 0;
-}
diff --git a/test/FrontendC/2007-10-15-VoidPtr.c b/test/FrontendC/2007-10-15-VoidPtr.c
deleted file mode 100644
index c5948b9..0000000
--- a/test/FrontendC/2007-10-15-VoidPtr.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc -S %s -o /dev/null
-void bork(void **data) {
- (*(unsigned short *) (&(data[37])[927]) = 0);
-}
diff --git a/test/FrontendC/2007-10-30-Volatile.c b/test/FrontendC/2007-10-30-Volatile.c
deleted file mode 100644
index 7a75b05..0000000
--- a/test/FrontendC/2007-10-30-Volatile.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o /dev/null -Wall -Werror
-void bork() {
- char * volatile p;
- volatile int cc;
- p += cc;
-}
diff --git a/test/FrontendC/2007-11-07-AlignedMemcpy.c b/test/FrontendC/2007-11-07-AlignedMemcpy.c
deleted file mode 100644
index eb9d22c..0000000
--- a/test/FrontendC/2007-11-07-AlignedMemcpy.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc -S %s -o /dev/null
-void bork() {
- int Qux[33] = {0};
-}
diff --git a/test/FrontendC/2007-11-07-CopyAggregateAlign.c b/test/FrontendC/2007-11-07-CopyAggregateAlign.c
deleted file mode 100644
index 8bd94b0..0000000
--- a/test/FrontendC/2007-11-07-CopyAggregateAlign.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep "align 2" | count 6
-struct A { char s, t, u, v; short a; };
-void q() { struct A a, b; a = b; }
diff --git a/test/FrontendC/2007-11-07-ZeroAggregateAlign.c b/test/FrontendC/2007-11-07-ZeroAggregateAlign.c
deleted file mode 100644
index 424120d..0000000
--- a/test/FrontendC/2007-11-07-ZeroAggregateAlign.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep "align 2"
-struct A { short s; short t; int i; };
-void q() { struct A a = {0}; }
diff --git a/test/FrontendC/2007-11-27-SExtZExt.c b/test/FrontendC/2007-11-27-SExtZExt.c
deleted file mode 100644
index 8ea4786..0000000
--- a/test/FrontendC/2007-11-27-SExtZExt.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep "signext" | count 4
-
-signed char foo1() { return 1; }
-
-void foo2(signed short a) { }
-
-signed char foo3(void) { return 1; }
-
-void foo4(a) signed short a; { }
-
-
-
diff --git a/test/FrontendC/2007-11-28-GlobalInitializer.c b/test/FrontendC/2007-11-28-GlobalInitializer.c
deleted file mode 100644
index c8c7a59..0000000
--- a/test/FrontendC/2007-11-28-GlobalInitializer.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s -o -
-// PR1744
-typedef struct foo { int x; char *p; } FOO;
-extern FOO yy[];
-
-int *y = &((yy + 1)->x);
-void *z = &((yy + 1)->x);
-
diff --git a/test/FrontendC/2007-12-16-AsmNoUnwind.c b/test/FrontendC/2007-12-16-AsmNoUnwind.c
deleted file mode 100644
index b080e6a..0000000
--- a/test/FrontendC/2007-12-16-AsmNoUnwind.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | grep nounwind
-
-void bar() { asm (""); }
diff --git a/test/FrontendC/2007-12-VarArrayDebug.c b/test/FrontendC/2007-12-VarArrayDebug.c
deleted file mode 100644
index 966789e..0000000
--- a/test/FrontendC/2007-12-VarArrayDebug.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S -g -O %s -o - | llc
-// RUN: %llvmgcc -S -g %s -o - | llc
-
-extern void foo (void);
-
-static
-void baz (int i)
-{
- foo ();
- typedef char A[i];
- struct { A b; } *x = 0;
-}
-
-void
-bar (i)
-{
- baz (i);
-}
diff --git a/test/FrontendC/2008-01-04-WideBitfield.c b/test/FrontendC/2008-01-04-WideBitfield.c
deleted file mode 100644
index a0045a4..0000000
--- a/test/FrontendC/2008-01-04-WideBitfield.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc -S -o - %s
-// PR1386
-#include <stdint.h>
-
-struct X {
- unsigned char pad : 4;
- uint64_t a : 64;
-} __attribute__((packed)) x;
-
-uint64_t f(void)
-{
- return x.a;
-}
diff --git a/test/FrontendC/2008-01-07-UnusualIntSize.c b/test/FrontendC/2008-01-07-UnusualIntSize.c
deleted file mode 100644
index 91beaf3..0000000
--- a/test/FrontendC/2008-01-07-UnusualIntSize.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc %s -S -o - -O | grep i33
-// PR1721
-
-struct s {
- unsigned long long u33: 33;
-} a, b;
-
-// This should turn into a real 33-bit add, not a 64-bit add.
-_Bool test(void) {
- return a.u33 + b.u33 != 0;
-}
diff --git a/test/FrontendC/2008-01-11-ChainConsistency.c b/test/FrontendC/2008-01-11-ChainConsistency.c
deleted file mode 100644
index 13e48a3..0000000
--- a/test/FrontendC/2008-01-11-ChainConsistency.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %llvmgcc -S %s -o - -fnested-functions | not grep nest
-
-void n1(void) { void a(void) { a(); } a(); }
diff --git a/test/FrontendC/2008-01-21-PackedBitFields.c b/test/FrontendC/2008-01-21-PackedBitFields.c
deleted file mode 100644
index 4c38dee..0000000
--- a/test/FrontendC/2008-01-21-PackedBitFields.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-typedef double Al1Double __attribute__((aligned(1)));
-struct x { int a:23; Al1Double v; };
-struct x X = { 5, 3.0 };
-double foo() { return X.v; }
-
diff --git a/test/FrontendC/2008-01-21-PackedStructField.c b/test/FrontendC/2008-01-21-PackedStructField.c
deleted file mode 100644
index 9cc1731..0000000
--- a/test/FrontendC/2008-01-21-PackedStructField.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-struct X { long double b; unsigned char c; double __attribute__((packed)) d; };
-struct X x = { 3.0L, 5, 3.0 };
-
-
-struct S2504 {
- int e:17;
- __attribute__((packed)) unsigned long long int f;
-} ;
-int fails;
- extern struct S2504 s2504;
-void check2504va (int z) {
- struct S2504 arg, *p;
- long long int i = 0;
- arg.f = i;
-}
-
diff --git a/test/FrontendC/2008-01-24-StructAlignAndBitFields.c b/test/FrontendC/2008-01-24-StructAlignAndBitFields.c
deleted file mode 100644
index 380a7ef..0000000
--- a/test/FrontendC/2008-01-24-StructAlignAndBitFields.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-struct U { char a; short b; int c:25; char d; } u;
-
diff --git a/test/FrontendC/2008-01-25-ByValReadNone.c b/test/FrontendC/2008-01-25-ByValReadNone.c
deleted file mode 100644
index 4cb1a63..0000000
--- a/test/FrontendC/2008-01-25-ByValReadNone.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc -O3 -S -o - %s | not grep readonly
-// RUN: %llvmgcc -O3 -S -o - %s | not grep readnone
-
-
-// The struct being passed byval means that we cannot mark the
-// function readnone. Readnone would allow stores to the arg to
-// be deleted in the caller. We also don't allow readonly since
-// the callee might write to the byval parameter. The inliner
-// would have to assume the worse and introduce an explicit
-// temporary when inlining such a function, which is costly for
-// the common case in which the byval argument is not written.
-struct S { int A[1000]; };
-int __attribute__ ((const)) f(struct S x) { x.A[1] = 0; return x.A[0]; }
-int g(struct S x) __attribute__ ((pure));
-int h(struct S x) { return g(x); }
diff --git a/test/FrontendC/2008-01-25-ZeroSizedAggregate.c b/test/FrontendC/2008-01-25-ZeroSizedAggregate.c
deleted file mode 100644
index 643caff..0000000
--- a/test/FrontendC/2008-01-25-ZeroSizedAggregate.c
+++ /dev/null
@@ -1,39 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-// Aggregates of size zero should be dropped from argument list.
-typedef long int Tlong;
-struct S2411 {
- __attribute__((aligned)) Tlong:0;
-};
-
-extern struct S2411 a2411[5];
-extern void checkx2411(struct S2411);
-void test2411(void) {
- checkx2411(a2411[0]);
-}
-
-// Proper handling of zero sized fields during type conversion.
-typedef unsigned long long int Tal2ullong __attribute__((aligned(2)));
-struct S2525 {
- Tal2ullong: 0;
- struct {
- } e;
-};
-struct S2525 s2525;
-
-struct {
- signed char f;
- char :0;
- struct{}h;
- char * i[5];
-} data;
-
-// Taking address of a zero sized field.
-struct Z {};
-struct Y {
- int i;
- struct Z z;
-};
-void *f(struct Y *y) {
- return &y->z;
-}
diff --git a/test/FrontendC/2008-01-28-PragmaMark.c b/test/FrontendC/2008-01-28-PragmaMark.c
deleted file mode 100644
index 6a4b5b5..0000000
--- a/test/FrontendC/2008-01-28-PragmaMark.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -Werror -S %s -o /dev/null
-#pragma mark LLVM's world
-#ifdef DO_ERROR
-#error LLVM's world
-#endif
-int i;
diff --git a/test/FrontendC/2008-01-28-UnionSize.c b/test/FrontendC/2008-01-28-UnionSize.c
deleted file mode 100644
index ea2c863..0000000
--- a/test/FrontendC/2008-01-28-UnionSize.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-// PR 1861
-
-typedef unsigned char __u8;
-typedef unsigned int __u32;
-typedef unsigned short u16;
-typedef __u32 __le32;
-struct bcm43xx_plcp_hdr6 {
- union {
- __le32 data;
- __u8 raw[6];
- }
- __attribute__((__packed__));
-}
- __attribute__((__packed__));
-struct bcm43xx_txhdr {
- union {
- struct {
- struct bcm43xx_plcp_hdr6 plcp;
- };
- };
-}
- __attribute__((__packed__));
-static void bcm43xx_generate_rts(struct bcm43xx_txhdr *txhdr ) { }
diff --git a/test/FrontendC/2008-02-11-AnnotateBuiltin.c b/test/FrontendC/2008-02-11-AnnotateBuiltin.c
deleted file mode 100644
index 32bc7a8..0000000
--- a/test/FrontendC/2008-02-11-AnnotateBuiltin.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | llvm-as | llvm-dis | grep llvm.annotation
-
-int main() {
- int x = 0;
- return __builtin_annotation(x, "annotate");
-}
-
diff --git a/test/FrontendC/2008-03-03-CtorAttrType.c b/test/FrontendC/2008-03-03-CtorAttrType.c
deleted file mode 100644
index 96648f4..0000000
--- a/test/FrontendC/2008-03-03-CtorAttrType.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | grep llvm.global_ctors
-int __attribute__((constructor)) foo(void) {
- return 0;
-}
-void __attribute__((constructor)) bar(void) {}
-
diff --git a/test/FrontendC/2008-03-05-syncPtr.c b/test/FrontendC/2008-03-05-syncPtr.c
deleted file mode 100644
index 7b271f7..0000000
--- a/test/FrontendC/2008-03-05-syncPtr.c
+++ /dev/null
@@ -1,27 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | grep llvm.atomic
-// XFAIL: sparc-sun-solaris2|arm
-// Feature currently implemented only for x86, alpha, powerpc.
-
-int* foo(int** a, int* b, int* c) {
-return __sync_val_compare_and_swap (a, b, c);
-}
-
-int foo2(int** a, int* b, int* c) {
-return __sync_bool_compare_and_swap (a, b, c);
-}
-
-int* foo3(int** a, int b) {
- return __sync_fetch_and_add (a, b);
-}
-
-int* foo4(int** a, int b) {
- return __sync_fetch_and_sub (a, b);
-}
-
-int* foo5(int** a, int* b) {
- return __sync_lock_test_and_set (a, b);
-}
-
-int* foo6(int** a, int*** b) {
- return __sync_lock_test_and_set (a, b);
-}
diff --git a/test/FrontendC/2008-03-24-BitField-And-Alloca.c b/test/FrontendC/2008-03-24-BitField-And-Alloca.c
deleted file mode 100644
index 641bcf1..0000000
--- a/test/FrontendC/2008-03-24-BitField-And-Alloca.c
+++ /dev/null
@@ -1,89 +0,0 @@
-// RUN: %llvmgcc -O2 -S %s -o - | not grep alloca
-// RUN: %llvmgcc -m32 -O2 -S %s -o - | not grep {store }
-
-enum {
- PP_C,
- PP_D,
- PP_R,
- PP_2D,
- PP_1D,
- PP_SR,
- PP_S2D,
- PP_S1D,
- PP_SC
-};
-
-enum {
- G_VP,
- G_FP,
- G_VS,
- G_GS,
- G_FS
-};
-
-enum {
- G_NONE,
- G_B,
- G_R
-};
-
-typedef union _Key {
- struct {
- unsigned int count : 2;
- unsigned int Aconst : 1;
- unsigned int Bconst : 1;
- unsigned int Cconst : 1;
- unsigned int Xused : 1;
- unsigned int Yused : 1;
- unsigned int Zused : 1;
- unsigned int Wused : 1;
- unsigned int ttype : 3;
- unsigned int scalar : 1;
- unsigned int AType : 4;
- unsigned int BType : 4;
- unsigned int CType : 4;
- unsigned int RType : 4;
- unsigned int Size : 2;
- unsigned int prec : 1;
-
- unsigned int ASize : 2;
- unsigned int BSize : 2;
- unsigned int CSize : 2;
- unsigned int tTex : 4;
- unsigned int proj : 1;
- unsigned int lod : 2;
- unsigned int dvts : 1;
- unsigned int uipad : 18;
- } key_io;
- struct {
- unsigned int key0;
- unsigned int key1;
- } key;
- unsigned long long lkey;
-} Key;
-
-static void foo(const Key iospec, int* ret)
-{
- *ret=0;
- if(((iospec.key_io.lod == G_B) &&
- (iospec.key_io.ttype != G_VS) &&
- (iospec.key_io.ttype != G_GS) &&
- (iospec.key_io.ttype != G_FS)) ||
-
- (((iospec.key_io.tTex == PP_C) ||
- (iospec.key_io.tTex == PP_SC)) &&
- ((iospec.key_io.tTex == PP_SR) ||
- (iospec.key_io.tTex == PP_S2D) ||
- (iospec.key_io.tTex == PP_S1D) ||
- (iospec.key_io.tTex == PP_SC))))
- *ret=1;
-}
-
-
-extern int bar(unsigned long long key_token2)
-{
- int ret;
- __attribute__ ((unused)) Key iospec = (Key) key_token2;
- foo(iospec, &ret);
- return ret;
-}
diff --git a/test/FrontendC/2008-03-26-PackedBitFields.c b/test/FrontendC/2008-03-26-PackedBitFields.c
deleted file mode 100644
index 7214281..0000000
--- a/test/FrontendC/2008-03-26-PackedBitFields.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-
-
-struct S1757 {
- long double c;
- long int __attribute__((packed)) e:28;
-} x;
diff --git a/test/FrontendC/2008-04-08-NoExceptions.c b/test/FrontendC/2008-04-08-NoExceptions.c
deleted file mode 100644
index 257fee2..0000000
--- a/test/FrontendC/2008-04-08-NoExceptions.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S -o - %s | grep nounwind | count 2
-// RUN: %llvmgcc -S -o - %s | not grep {declare.*nounwind}
-
-void f(void);
-void g(void) {
- f();
-}
diff --git a/test/FrontendC/2008-05-06-CFECrash.c b/test/FrontendC/2008-05-06-CFECrash.c
deleted file mode 100644
index 94d556c..0000000
--- a/test/FrontendC/2008-05-06-CFECrash.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc -S -O2 %s -o /dev/null
-// PR2292.
-__inline__ __attribute__ ((__pure__)) int g (void) {}
-void f (int k) { k = g (); }
diff --git a/test/FrontendC/2008-05-12-TempUsedBeforeDef.c b/test/FrontendC/2008-05-12-TempUsedBeforeDef.c
deleted file mode 100644
index 21724c1..0000000
--- a/test/FrontendC/2008-05-12-TempUsedBeforeDef.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -w -S -o /dev/null %s
-// PR2264.
-unsigned foo = 8L;
-unsigned bar = 0L;
-volatile unsigned char baz = 6L;
-int test() {
- char qux = 1L;
- for (; baz >= -29; baz--)
- bork(bar && foo, qux);
-}
diff --git a/test/FrontendC/2008-05-19-AlwaysInline.c b/test/FrontendC/2008-05-19-AlwaysInline.c
deleted file mode 100644
index 8dcb57b..0000000
--- a/test/FrontendC/2008-05-19-AlwaysInline.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc %s -S -fno-unit-at-a-time -O0 -o - | not grep sabrina
-// RUN: %llvmgcc %s -S -funit-at-a-time -O0 -o - | not grep sabrina
-
-static inline int sabrina (void) __attribute__((always_inline));
-static inline int sabrina (void)
-{
- return 13;
-}
-int bar (void)
-{
- return sabrina () + 68;
-}
diff --git a/test/FrontendC/2008-07-08-FAbsAttributes.c b/test/FrontendC/2008-07-08-FAbsAttributes.c
deleted file mode 100644
index 1eb01dc..0000000
--- a/test/FrontendC/2008-07-08-FAbsAttributes.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep readnone
-// PR2520
-#include <math.h>
-double f(double *x, double *y) { return fabs(*x + *y); }
diff --git a/test/FrontendC/2008-08-07-AlignPadding1.c b/test/FrontendC/2008-08-07-AlignPadding1.c
deleted file mode 100644
index 6be9fe4..0000000
--- a/test/FrontendC/2008-08-07-AlignPadding1.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* RUN: %llvmgcc %s -S -o - -O0 | grep {zeroinitializer.*zeroinitializer.*zeroinitializer.*zeroinitializer.*zeroinitializer.*zeroinitializer}
-
-The FE must generate padding here both at the end of each PyG_Head and
-between array elements. Reduced from Python. */
-
-typedef union _gc_head {
- struct {
- union _gc_head *gc_next;
- union _gc_head *gc_prev;
- long gc_refs;
- } gc;
- int dummy __attribute__((aligned(16)));
-} PyGC_Head;
-
-struct gc_generation {
- PyGC_Head head;
- int threshold;
- int count;
-};
-
-#define GEN_HEAD(n) (&generations[n].head)
-
-/* linked lists of container objects */
-static struct gc_generation generations[3] = {
- /* PyGC_Head, threshold, count */
- {{{GEN_HEAD(0), GEN_HEAD(0), 0}}, 700, 0},
- {{{GEN_HEAD(1), GEN_HEAD(1), 0}}, 10, 0},
- {{{GEN_HEAD(2), GEN_HEAD(2), 0}}, 10, 0},
-};
diff --git a/test/FrontendC/2008-08-07-AlignPadding2.c b/test/FrontendC/2008-08-07-AlignPadding2.c
deleted file mode 100644
index 51135ba..0000000
--- a/test/FrontendC/2008-08-07-AlignPadding2.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* RUN: %llvmgcc %s -S -o - -O0 | grep zeroinitializer | count 1
-
-The FE must not generate padding here between array elements. PR 2533. */
-
-typedef struct {
- const char *name;
- int flags;
- union {
- int x;
- } u;
-} OptionDef;
-
-const OptionDef options[] = {
- /* main options */
- { "a", 0, {3} },
- { "b", 0, {4} },
- { 0, },
-};
diff --git a/test/FrontendC/2008-08-07-GEPIntToPtr.c b/test/FrontendC/2008-08-07-GEPIntToPtr.c
deleted file mode 100644
index 3ef3b66..0000000
--- a/test/FrontendC/2008-08-07-GEPIntToPtr.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep {i8 1}
-// PR2603
-
-struct A {
- char num_fields;
-};
-
-struct B {
- char a, b[1];
-};
-
-const struct A Foo = {
- (char *)(&( (struct B *)(16) )->b[0]) - (char *)(16)
-};
diff --git a/test/FrontendC/2008-09-03-WeakAlias.c b/test/FrontendC/2008-09-03-WeakAlias.c
deleted file mode 100644
index 2e5f3da..0000000
--- a/test/FrontendC/2008-09-03-WeakAlias.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -S -O1 -o - %s | grep icmp
-// PR1678
-extern void B (void);
-static __typeof(B) A __attribute__ ((__weakref__("B")));
-int active (void)
-{
- static void *const p = __extension__ (void *) &A;
- return p != 0;
-}
diff --git a/test/FrontendC/2008-10-13-FrontendCrash.c b/test/FrontendC/2008-10-13-FrontendCrash.c
deleted file mode 100644
index c9731e3..0000000
--- a/test/FrontendC/2008-10-13-FrontendCrash.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-// PR2797
-
-unsigned int
-func_48 (signed char p_49)
-{
- signed char l_340;
- func_44 (1&((1 ^ 1 == (lshift_u_s (1)) != (l_340 < 1)) & 1L));
-}
diff --git a/test/FrontendC/2008-10-30-ZeroPlacement.c b/test/FrontendC/2008-10-30-ZeroPlacement.c
deleted file mode 100644
index d73442d..0000000
--- a/test/FrontendC/2008-10-30-ZeroPlacement.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -S %s
-// PR2987
-struct S2045
-{
- unsigned short int a;
- union { } b;
- union __attribute__ ((aligned (4))) { } c[0];
-};
-struct S2045 s2045;
diff --git a/test/FrontendC/2008-11-02-WeakAlias.c b/test/FrontendC/2008-11-02-WeakAlias.c
deleted file mode 100644
index d10e57f..0000000
--- a/test/FrontendC/2008-11-02-WeakAlias.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc -S -o - %s | grep weak
-// PR2691
-
-void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
-void native_init_IRQ(void) {}
diff --git a/test/FrontendC/2008-11-08-InstCombineSelect.c b/test/FrontendC/2008-11-08-InstCombineSelect.c
deleted file mode 100644
index b850d3f..0000000
--- a/test/FrontendC/2008-11-08-InstCombineSelect.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc %s -S -O2 -o -
-// PR3028
-
-int g_187;
-int g_204;
-int g_434;
-
-int func_89 (void)
-{
- return 1;
-}
-
-void func_20 (int p_22)
-{
- if (1 & p_22 | g_204 & (1 < g_187) - func_89 ())
- g_434 = 1;
-}
diff --git a/test/FrontendC/2008-11-11-AnnotateStructFieldAttribute.c b/test/FrontendC/2008-11-11-AnnotateStructFieldAttribute.c
deleted file mode 100644
index 8af59d5..0000000
--- a/test/FrontendC/2008-11-11-AnnotateStructFieldAttribute.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep llvm.ptr.annotation | count 3
-
-#include <stdio.h>
-
-/* Struct with element X being annotated */
-struct foo {
- int X __attribute__((annotate("StructAnnotation")));
- int Y;
- int Z;
-};
-
-
-void test(struct foo *F) {
- F->X = 42;
- F->Z = 1;
- F->Y = F->X;
-}
-
diff --git a/test/FrontendC/2008-12-23-AsmIntPointerTie.c b/test/FrontendC/2008-12-23-AsmIntPointerTie.c
deleted file mode 100644
index 5706142..0000000
--- a/test/FrontendC/2008-12-23-AsmIntPointerTie.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc %s -S -O1 -o -
-
-#include <stdint.h>
-
-int test(void *b) {
- intptr_t a;
- __asm__ __volatile__ ("%0 %1 " : "=r" (a): "0" (b));
- return a;
-}
diff --git a/test/FrontendC/2009-01-05-BlockInlining.c b/test/FrontendC/2009-01-05-BlockInlining.c
deleted file mode 100644
index 8fb6e54..0000000
--- a/test/FrontendC/2009-01-05-BlockInlining.c
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %llvmgcc %s -S -O2 -o %t.s
-// RUN: grep {call i32 .*printf.*argc} %t.s | count 3
-// RUN: not grep __block_holder_tmp %t.s
-// rdar://5865221
-
-// All of these should be inlined equivalently into a single printf call.
-
-static int fun(int x) {
- return x+1;
-}
-
-static int block(int x) {
- return (^(int x){return x+1;})(x);
-}
-
-static void print(int result) {
- printf("%d\n", result);
-}
-
-int main (int argc, const char * argv[]) {
- int x = argc-1;
- print(fun(x));
- print(block(x));
- int (^block_inline)(int) = ^(int x){return x+1;};
- print(block_inline(x));
- return 0;
-}
-
diff --git a/test/FrontendC/2009-01-20-k8.c b/test/FrontendC/2009-01-20-k8.c
deleted file mode 100644
index 2cd1538..0000000
--- a/test/FrontendC/2009-01-20-k8.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc %s -S -march=k8 -o /dev/null
-// XFAIL: *
-// XTARGET: x86,i386,i686
-long double x;
diff --git a/test/FrontendC/2009-01-21-InvalidIterator.c b/test/FrontendC/2009-01-21-InvalidIterator.c
deleted file mode 100644
index 6ac61f8..0000000
--- a/test/FrontendC/2009-01-21-InvalidIterator.c
+++ /dev/null
@@ -1,74 +0,0 @@
-// RUN: %llvmgcc %s -S -g -o /dev/null
-
-typedef long unsigned int size_t;
-typedef unsigned short int uint16_t;
-typedef unsigned int uint32_t;
-typedef unsigned long int uint64_t;
-typedef uint16_t Elf64_Half;
-typedef uint32_t Elf64_Word;
-typedef uint64_t Elf64_Xword;
-typedef uint64_t Elf64_Addr;
-typedef uint64_t Elf64_Off;
-typedef struct
-{
- Elf64_Word p_type;
- Elf64_Off p_offset;
- Elf64_Addr p_vaddr;
- Elf64_Xword p_align;
-}
-Elf64_Phdr;
-struct dl_phdr_info
-{
- const char *dlpi_name;
- const Elf64_Phdr *dlpi_phdr;
- Elf64_Half dlpi_phnum;
- unsigned long long int dlpi_adds;
-};
-typedef unsigned _Unwind_Ptr;
-struct object
-{
- union
- {
- const struct dwarf_fde *single;
- struct dwarf_fde **array;
- struct fde_vector *sort;
- }
- u;
- union
- {
- struct
- {
- }
- b;
- }
- s;
- struct object *next;
-};
-typedef int sword;
-typedef unsigned int uword;
-struct dwarf_fde
-{
- uword length;
- sword CIE_delta;
- unsigned char pc_begin[];
-};
-typedef struct dwarf_fde fde;
-struct unw_eh_callback_data
-{
- const fde *ret;
- struct frame_hdr_cache_element *link;
-}
-frame_hdr_cache[8];
-
-_Unwind_Ptr
-base_from_cb_data (struct unw_eh_callback_data *data)
-{
-}
-
-void
-_Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
-{
- const unsigned char *p;
- const struct unw_eh_frame_hdr *hdr;
- struct object ob;
-}
diff --git a/test/FrontendC/2009-02-13-zerosize-union-field-ppc.c b/test/FrontendC/2009-02-13-zerosize-union-field-ppc.c
deleted file mode 100644
index 947166d..0000000
--- a/test/FrontendC/2009-02-13-zerosize-union-field-ppc.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc %s -m32 -S -o - | grep {i32 32} | count 3
-// XFAIL: *
-// XTARGET: powerpc
-// Every printf has 'i32 0' for the GEP of the string; no point counting those.
-typedef unsigned int Foo __attribute__((aligned(32)));
-typedef union{Foo:0;}a;
-typedef union{int x; Foo:0;}b;
-extern int printf(const char*, ...);
-main() {
- printf("%ld\n", sizeof(a));
- printf("%ld\n", __alignof__(a));
- printf("%ld\n", sizeof(b));
- printf("%ld\n", __alignof__(b));
-}
diff --git a/test/FrontendC/2009-02-13-zerosize-union-field.c b/test/FrontendC/2009-02-13-zerosize-union-field.c
deleted file mode 100644
index ad33558..0000000
--- a/test/FrontendC/2009-02-13-zerosize-union-field.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc %s -m32 -S -o - | grep {i32 1} | count 1
-// RUN: %llvmgcc %s -m32 -S -o - | grep {i32 4} | count 2
-// XFAIL: powerpc
-// Every printf has 'i32 0' for the GEP of the string; no point counting those.
-typedef unsigned int Foo __attribute__((aligned(32)));
-typedef union{Foo:0;}a;
-typedef union{int x; Foo:0;}b;
-extern int printf(const char*, ...);
-main() {
- printf("%ld\n", sizeof(a));
- printf("%ld\n", __alignof__(a));
- printf("%ld\n", sizeof(b));
- printf("%ld\n", __alignof__(b));
-}
diff --git a/test/FrontendC/2009-02-17-BitField-dbg.c b/test/FrontendC/2009-02-17-BitField-dbg.c
deleted file mode 100644
index 88d2cbb..0000000
--- a/test/FrontendC/2009-02-17-BitField-dbg.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// Check bitfields.
-// RUN: %llvmgcc -S -O0 -g %s -o - | \
-// RUN: llc -disable-cfi --disable-fp-elim -o 2009-02-17-BitField-dbg.s
-// RUN: %compile_c 2009-02-17-BitField-dbg.s -o 2009-02-17-BitField-dbg.o
-// RUN: echo {ptype mystruct} > %t2
-// RUN: gdb -q -batch -n -x %t2 2009-02-17-BitField-dbg.o | \
-// RUN: tee 2009-02-17-BitField-dbg.out | grep "int a : 4"
-//
-
-struct {
- int a:4;
- int b:2;
-} mystruct;
-
diff --git a/test/FrontendC/2009-03-01-MallocNoAlias.c b/test/FrontendC/2009-03-01-MallocNoAlias.c
deleted file mode 100644
index 22ff6cb..0000000
--- a/test/FrontendC/2009-03-01-MallocNoAlias.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | grep noalias
-
-void * __attribute__ ((malloc)) foo (void) { return 0; }
diff --git a/test/FrontendC/2009-03-08-ZeroEltStructCrash.c b/test/FrontendC/2009-03-08-ZeroEltStructCrash.c
deleted file mode 100644
index 454e0fb..0000000
--- a/test/FrontendC/2009-03-08-ZeroEltStructCrash.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -S %s -o -
-// PR3744
-struct Empty {};
-struct Union {
- union {
- int zero_arr[0];
- } contents;
-};
-static inline void Foo(struct Union *u) {
- int *array = u->contents.zero_arr;
-}
-static void Bar(struct Union *u) {
- Foo(u);
-}
diff --git a/test/FrontendC/2009-03-09-WeakDeclarations-1.c b/test/FrontendC/2009-03-09-WeakDeclarations-1.c
deleted file mode 100644
index 13ea84f..0000000
--- a/test/FrontendC/2009-03-09-WeakDeclarations-1.c
+++ /dev/null
@@ -1,22 +0,0 @@
-// RUN: %llvmgcc_only %s -c -o /dev/null |& \
-// RUN: egrep {(14|15|22): warning:} | \
-// RUN: wc -l | grep --quiet 3
-// XTARGET: darwin,linux
-// XFAIL: *
-// END.
-// Insist upon warnings for inappropriate weak attributes.
-// Note the line numbers (14|15|22) embedded in the check.
-
-// O.K.
-extern int ext_weak_import __attribute__ ((__weak_import__));
-
-// These are inappropriate, and should generate warnings:
-int decl_weak_import __attribute__ ((__weak_import__));
-int decl_initialized_weak_import __attribute__ ((__weak_import__)) = 13;
-
-// O.K.
-extern int ext_f(void) __attribute__ ((__weak_import__));
-
-// These are inappropriate, and should generate warnings:
-int def_f(void) __attribute__ ((__weak_import__));
-int __attribute__ ((__weak_import__)) decl_f(void) {return 0;};
diff --git a/test/FrontendC/2009-03-13-dbg.c b/test/FrontendC/2009-03-13-dbg.c
deleted file mode 100644
index 46abd3a..0000000
--- a/test/FrontendC/2009-03-13-dbg.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc %s -S -g -o /dev/null
-// XTARGET: darwin,linux
-// XFAIL: *
-void foo() {}
-
diff --git a/test/FrontendC/2009-04-22-UnknownSize.c b/test/FrontendC/2009-04-22-UnknownSize.c
deleted file mode 100644
index 7db9c07..0000000
--- a/test/FrontendC/2009-04-22-UnknownSize.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: not %llvmgcc -O1 %s -S -o /dev/null |& grep {error: storage size}
-// PR2958
-static struct foo s;
-struct foo *p = &s;
diff --git a/test/FrontendC/2009-04-28-UnionArrayCrash.c b/test/FrontendC/2009-04-28-UnionArrayCrash.c
deleted file mode 100644
index 75851d0..0000000
--- a/test/FrontendC/2009-04-28-UnionArrayCrash.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -S %s -o -
-// PR4082
-union U {
- int I;
- double F;
-};
-
-union U arr[] = { { .I = 4 }, { .F = 123.} };
-union U *P = &arr[0];
-
-
diff --git a/test/FrontendC/2009-05-04-EnumInreg.c b/test/FrontendC/2009-05-04-EnumInreg.c
deleted file mode 100644
index fb0c03e..0000000
--- a/test/FrontendC/2009-05-04-EnumInreg.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S -m32 -mregparm=3 %s -o - | grep {inreg %action}
-// XFAIL: *
-// XTARGET: x86,i386,i686
-// PR3967
-
-enum kobject_action {
- KOBJ_ADD,
- KOBJ_REMOVE,
- KOBJ_CHANGE,
- KOBJ_MOVE,
- KOBJ_ONLINE,
- KOBJ_OFFLINE,
- KOBJ_MAX
-};
-
-struct kobject;
-
-int kobject_uevent(struct kobject *kobj, enum kobject_action action) {}
diff --git a/test/FrontendC/2009-05-17-AlwaysInline.c b/test/FrontendC/2009-05-17-AlwaysInline.c
deleted file mode 100644
index a93fabe..0000000
--- a/test/FrontendC/2009-05-17-AlwaysInline.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc -S %s -O0 -o - -mllvm -disable-llvm-optzns | grep bar
-// Check that the gcc inliner is turned off.
-
-#include <stdio.h>
-static __inline__ __attribute__ ((always_inline))
- int bar (int x)
-{
- return 4;
-}
-
-void
-foo ()
-{
- long long b = 1;
- int Y = bar (4);
- printf ("%d\n", Y);
-}
diff --git a/test/FrontendC/2009-06-14-HighlyAligned.c b/test/FrontendC/2009-06-14-HighlyAligned.c
deleted file mode 100644
index 227db74..0000000
--- a/test/FrontendC/2009-06-14-HighlyAligned.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc %s -S -o /dev/null
-// PR4332
-
-static int highly_aligned __attribute__((aligned(4096)));
-
-int f() {
- return highly_aligned;
-}
diff --git a/test/FrontendC/2009-06-18-StaticInitTailPadPack.c b/test/FrontendC/2009-06-18-StaticInitTailPadPack.c
deleted file mode 100644
index 17f35c0..0000000
--- a/test/FrontendC/2009-06-18-StaticInitTailPadPack.c
+++ /dev/null
@@ -1,26 +0,0 @@
-// RUN: %llvmgcc %s -S -o -
-// rdar://6983634
-
- typedef struct A *Foo;
-#pragma pack(push, 2)
- struct Bar {
- Foo f1;
- unsigned short f2;
- float f3;
- };
- struct Baz {
- struct Bar f1;
- struct Bar f2;
- };
- struct Qux {
- unsigned long f1;
- struct Baz f2;
- };
-extern const struct Qux Bork;
-const struct Qux Bork = {
- 0,
- {
- {0},
- {0}
- }
-};
diff --git a/test/FrontendC/2009-07-14-VoidPtr.c b/test/FrontendC/2009-07-14-VoidPtr.c
deleted file mode 100644
index 8001c56..0000000
--- a/test/FrontendC/2009-07-14-VoidPtr.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o -
-// PR4556
-
-extern void foo;
-void *bar = &foo;
-
diff --git a/test/FrontendC/2009-07-15-pad-wchar_t-array.c b/test/FrontendC/2009-07-15-pad-wchar_t-array.c
deleted file mode 100644
index 41bdef2..0000000
--- a/test/FrontendC/2009-07-15-pad-wchar_t-array.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-
-#include <stddef.h>
-signed short _iodbcdm_sqlerror( )
-{
- wchar_t _sqlState[6] = { L"\0" };
-}
diff --git a/test/FrontendC/2009-07-17-VoidParameter.c b/test/FrontendC/2009-07-17-VoidParameter.c
deleted file mode 100644
index d576952..0000000
--- a/test/FrontendC/2009-07-17-VoidParameter.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc -S %s -o -
-// PR4214
-typedef void vt;
-void (*func_ptr)(vt my_vt);
diff --git a/test/FrontendC/2009-07-22-StructLayout.c b/test/FrontendC/2009-07-22-StructLayout.c
deleted file mode 100644
index 74904da..0000000
--- a/test/FrontendC/2009-07-22-StructLayout.c
+++ /dev/null
@@ -1,34 +0,0 @@
-// RUN: %llvmgcc %s -S -o /dev/null
-// PR4590
-
-typedef unsigned char __u8;
-typedef unsigned int __le32;
-typedef unsigned int __u32;
-typedef unsigned short __le16;
-typedef unsigned short __u16;
-
-struct usb_cdc_ether_desc {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bDescriptorSubType;
-
- __u8 iMACAddress;
- __le32 bmEthernetStatistics;
- __le16 wMaxSegmentSize;
- __le16 wNumberMCFilters;
- __u8 bNumberPowerFilters;
-} __attribute__ ((packed));
-
-
-static struct usb_cdc_ether_desc ecm_desc __attribute__ ((__section__(".init.data"))) = {
- .bLength = sizeof ecm_desc,
- .bDescriptorType = ((0x01 << 5) | 0x04),
- .bDescriptorSubType = 0x0f,
-
-
-
- .bmEthernetStatistics = (( __le32)(__u32)(0)),
- .wMaxSegmentSize = (( __le16)(__u16)(1514)),
- .wNumberMCFilters = (( __le16)(__u16)(0)),
- .bNumberPowerFilters = 0,
-};
diff --git a/test/FrontendC/2009-08-11-AsmBlocksComplexJumpTarget.c b/test/FrontendC/2009-08-11-AsmBlocksComplexJumpTarget.c
deleted file mode 100644
index e141c9a..0000000
--- a/test/FrontendC/2009-08-11-AsmBlocksComplexJumpTarget.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc %s -fasm-blocks -S -o - | grep {\\\*1192}
-// Complicated expression as jump target
-// XFAIL: *
-// XTARGET: x86,i386,i686
-
-asm void Method3()
-{
- mov eax,[esp+4]
- jmp [eax+(299-1)*4]
-}
diff --git a/test/FrontendC/2009-09-24-SqrtErrno.c b/test/FrontendC/2009-09-24-SqrtErrno.c
deleted file mode 100644
index 09fc876..0000000
--- a/test/FrontendC/2009-09-24-SqrtErrno.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc %s -S -o - -fmath-errno | FileCheck %s
-// llvm.sqrt has undefined behavior on negative inputs, so it is
-// inappropriate to translate C/C++ sqrt to this.
-#include <math.h>
-
-float foo(float X) {
-// CHECK: foo
-// CHECK-NOT: readonly
-// CHECK: return
- // Check that this is not marked readonly when errno is used.
- return sqrtf(X);
-}
diff --git a/test/FrontendC/2009-12-07-BitFieldAlignment.c b/test/FrontendC/2009-12-07-BitFieldAlignment.c
deleted file mode 100644
index 02ff8bc..0000000
--- a/test/FrontendC/2009-12-07-BitFieldAlignment.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc -m32 %s -S -o - | FileCheck %s
-// Set alignment on bitfield accesses.
-
-struct S {
- int a, b;
- void *c;
- unsigned d : 8;
- unsigned e : 8;
-};
-
-void f0(struct S *a) {
-// CHECK: load {{.*}}, align 4
-// CHECK: store {{.*}}, align 4
- a->e = 0;
-}
diff --git a/test/FrontendC/2010-01-05-LinkageName.c b/test/FrontendC/2010-01-05-LinkageName.c
deleted file mode 100644
index 279df03..0000000
--- a/test/FrontendC/2010-01-05-LinkageName.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc -O2 -S -g %s -o - | llc -disable-cfi -o 2010-01-05-LinkageName.s -O0
-// RUN: %compile_c 2010-01-05-LinkageName.s -o 2010-01-05-LinkageName.s
-
-struct tm {};
-long mktime(struct tm *) __asm("_mktime$UNIX2003");
-tzload(name, sp, doextend){}
-long mktime(tmp)
- struct tm *const tmp;
-{
- tzset();
-}
-timelocal(tmp) {
- return mktime(tmp);
-}
-
diff --git a/test/FrontendC/2010-01-13-MemBarrier.c b/test/FrontendC/2010-01-13-MemBarrier.c
deleted file mode 100644
index a540e59..0000000
--- a/test/FrontendC/2010-01-13-MemBarrier.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | FileCheck %s
-// XFAIL: sparc
-// rdar://7536390
-
-unsigned t(unsigned *ptr, unsigned val) {
- // CHECK: @t
- // CHECK: call void @llvm.memory.barrier
- // CHECK-NEXT: call i32 @llvm.atomic.swap.i32
- // CHECK-NEXT: call void @llvm.memory.barrier
- return __sync_lock_test_and_set(ptr, val);
-}
diff --git a/test/FrontendC/2010-01-14-FnType-DebugInfo.c b/test/FrontendC/2010-01-14-FnType-DebugInfo.c
deleted file mode 100644
index beaad91..0000000
--- a/test/FrontendC/2010-01-14-FnType-DebugInfo.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %llvmgcc %s -S -g -o /dev/null
-typedef void (*sigcatch_t)( struct sigcontext *);
-sigcatch_t sigcatch[50] = {(sigcatch_t) 0};
-
diff --git a/test/FrontendC/2010-01-14-StaticVariable.c b/test/FrontendC/2010-01-14-StaticVariable.c
deleted file mode 100644
index 0635900..0000000
--- a/test/FrontendC/2010-01-14-StaticVariable.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// This is a regression test on debug info to make sure that llvm emitted
-// debug info does not crash gdb.
-// RUN: %llvmgcc -S -O0 -g %s -o - | \
-// RUN: llc -disable-cfi --disable-fp-elim -o %t.s -O0 -relocation-model=pic
-// RUN: %compile_c %t.s -o %t.o
-// RUN: echo {quit\n} > %t.in
-// RUN: gdb -q -batch -n -x %t.in %t.o > /dev/null
-
-int foo() {
- static int i = 42;
- return i;
-}
diff --git a/test/FrontendC/2010-01-18-Inlined-Debug.c b/test/FrontendC/2010-01-18-Inlined-Debug.c
deleted file mode 100644
index 4aec7b2..0000000
--- a/test/FrontendC/2010-01-18-Inlined-Debug.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// PR: 6058
-// RUN: %llvmgcc -g -S %s -o - | llc -O0 -o /dev/null
-
-static inline int foo(double) __attribute__ ((always_inline));
-static inline int foo(double __x) { return __x; }
-
-void bar(double x) {
- foo(x);
-}
-
-
-
diff --git a/test/FrontendC/2010-02-10-PointerName.c b/test/FrontendC/2010-02-10-PointerName.c
deleted file mode 100644
index 7880fa8..0000000
--- a/test/FrontendC/2010-02-10-PointerName.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc %s -S -g -o - | grep DW_TAG_pointer_type | grep -v char
-
-char i = 1;
-void foo() {
- char *cp = &i;
-}
-
diff --git a/test/FrontendC/2010-02-15-DbgStaticVar.c b/test/FrontendC/2010-02-15-DbgStaticVar.c
deleted file mode 100644
index 7827d96..0000000
--- a/test/FrontendC/2010-02-15-DbgStaticVar.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %llvmgcc -g -S %s -o - | grep "metadata ..b., metadata ..b., metadata ...,"
-// Test to check intentionally empty linkage name for a static variable.
-// Radar 7651244.
-static int foo(int a)
-{
- static int b = 1;
- return b+a;
-}
-
-int main() {
- int j = foo(1);
- return 0;
-}
diff --git a/test/FrontendC/2010-02-16-DbgVarScope.c b/test/FrontendC/2010-02-16-DbgVarScope.c
deleted file mode 100644
index 24910ad..0000000
--- a/test/FrontendC/2010-02-16-DbgVarScope.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// RUN: %llvmgcc -S -O0 -g %s -o - | \
-// RUN: llc -disable-cfi --disable-fp-elim -o %t.s -O0 -relocation-model=pic
-// RUN: %compile_c %t.s -o %t.o
-// RUN: %link %t.o -o %t.exe
-// RUN: echo {break 24\nrun\np loc\n} > %t.in
-// RN: gdb -q -batch -n -x %t.in %t.exe | tee %t.out | \
-// RN: grep {$1 = 1}
-
-int g1 = 1;
-int g2 = 2;
-
-int __attribute__((always_inline)) bar() {
- return g2 - g1;
-}
-void foobar() {}
-
-void foo(int s) {
- unsigned loc = 0;
- if (s) {
- loc = 1;
- foobar();
- } else {
- loc = bar();
- foobar();
- }
-}
-
-int main() {
- foo(0);
-}
diff --git a/test/FrontendC/2010-02-18-Dbg-VectorType.c b/test/FrontendC/2010-02-18-Dbg-VectorType.c
deleted file mode 100644
index d34031f..0000000
--- a/test/FrontendC/2010-02-18-Dbg-VectorType.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -S -O0 -g %s -o - | grep DW_TAG_typedef | grep float4
-typedef float float4 __attribute__((vector_size(16)));
-
-int main(){
- volatile float4 x = (float4) { 0.0f, 1.0f, 2.0f, 3.0f };
- x += x;
- return 0;
-}
-
diff --git a/test/FrontendC/2010-03-10-arm-asmreg.c b/test/FrontendC/2010-03-10-arm-asmreg.c
deleted file mode 100644
index 70d3681..0000000
--- a/test/FrontendC/2010-03-10-arm-asmreg.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc %s -S -O0 -o - | FileCheck %s
-// pr6552
-
-// XFAIL: *
-// XTARGET: arm
-
-extern void bar(unsigned int ip);
-
-// CHECK: mov r0, r12
-void foo(void)
-{
- register unsigned int ip __asm ("ip");
- bar(ip);
-}
-
diff --git a/test/FrontendC/2010-03-5-LexicalScope.c b/test/FrontendC/2010-03-5-LexicalScope.c
deleted file mode 100644
index 93a841a..0000000
--- a/test/FrontendC/2010-03-5-LexicalScope.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S -O0 -g %s -o - | grep DW_TAG_lexical_block | count 3
-int foo(int i) {
- if (i) {
- int j = 2;
- }
- else {
- int j = 3;
- }
- return i;
-}
diff --git a/test/FrontendC/2010-05-14-Optimized-VarType.c b/test/FrontendC/2010-05-14-Optimized-VarType.c
deleted file mode 100644
index 2aa85b5..0000000
--- a/test/FrontendC/2010-05-14-Optimized-VarType.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %llvmgcc %s -Os -S -g -o - | grep DW_TAG_structure_type | count 1
-// Variable 'a' is optimized but the debug info should preserve its type info.
-#include <stdlib.h>
-
-struct foo {
- int Attribute;
-};
-
-void *getfoo(void) __attribute__((noinline));
-
-void *getfoo(void)
-{
- int *x = malloc(sizeof(int));
- *x = 42;
- return (void *)x;
-}
-
-int main(int argc, char *argv[]) {
- struct foo *a = (struct foo *)getfoo();
-
- return a->Attribute;
-}
-
diff --git a/test/FrontendC/2010-05-18-asmsched.c b/test/FrontendC/2010-05-18-asmsched.c
deleted file mode 100644
index ca7625f..0000000
--- a/test/FrontendC/2010-05-18-asmsched.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc %s -S -O3 -o - | llc -march=x86-64 -mtriple=x86_64-apple-darwin | FileCheck %s
-// r9 used to be clobbered before its value was moved to r10. 7993104.
-
-void foo(int x, int y) {
-// CHECK: bar
-// CHECK-NOT: {{, %r9$}}
-// CHECK: movq %r9,
-// CHECK: movq {{.*}}, %r9
-// CHECK: bar
- register int lr9 asm("r9") = x;
- register int lr10 asm("r10") = y;
- int foo;
- asm volatile("bar" : "=r"(lr9) : "r"(lr9), "r"(lr10));
- foo = lr9;
- lr9 = x;
- lr10 = foo;
- asm volatile("bar" : "=r"(lr9) : "r"(lr9), "r"(lr10));
-}
diff --git a/test/FrontendC/2010-05-18-palignr.c b/test/FrontendC/2010-05-18-palignr.c
deleted file mode 100644
index 0b78eed..0000000
--- a/test/FrontendC/2010-05-18-palignr.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgcc -mssse3 -S -o - %s | llc -mtriple=x86_64-apple-darwin | FileCheck %s
-// XFAIL: *
-// XTARGET: x86,i386,i686
-
-#include <tmmintrin.h>
-
-int main ()
-{
-#if defined( __SSSE3__ )
-
-#define vec_rld_epi16( _a, _i ) ({ vSInt16 _t = _a; _t = _mm_alignr_epi8( _t, _t, _i ); /*return*/ _t; })
- typedef int16_t vSInt16 __attribute__ ((__vector_size__ (16)));
-
- short dtbl[] = {1,2,3,4,5,6,7,8};
- vSInt16 *vdtbl = (vSInt16*) dtbl;
-
- vSInt16 v0;
- v0 = *vdtbl;
- // CHECK: pshufd $57
- v0 = vec_rld_epi16( v0, 4 );
-
- return 0;
-#endif
-}
diff --git a/test/FrontendC/2010-05-26-AsmSideEffect.c b/test/FrontendC/2010-05-26-AsmSideEffect.c
deleted file mode 100644
index acc38b7..0000000
--- a/test/FrontendC/2010-05-26-AsmSideEffect.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | FileCheck %s
-// Radar 8026855
-
-int test (void *src) {
- register int w0 asm ("0");
- // CHECK: call i32 asm sideeffect
- asm ("ldr %0, [%1]": "=r" (w0): "r" (src));
- // The asm to read the value of w0 has a sideeffect for a different reason
- // (see 2010-05-18-asmsched.c) but that's not what this is testing for.
- // CHECK: call i32 asm
- return w0;
-}
diff --git a/test/FrontendC/2010-05-31-palignr.c b/test/FrontendC/2010-05-31-palignr.c
deleted file mode 100644
index 9da3145..0000000
--- a/test/FrontendC/2010-05-31-palignr.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: not %llvmgcc -mssse3 -S -o /dev/null %s |& grep "error: mask must be an immediate"
-// XFAIL: *
-// XTARGET: x86,i386,i686
-
-#include <tmmintrin.h>
-
-extern int i;
-
-int main ()
-{
-#if defined( __SSSE3__ )
-
- typedef int16_t vSInt16 __attribute__ ((__vector_size__ (16)));
-
- short dtbl[] = {1,2,3,4,5,6,7,8};
- vSInt16 *vdtbl = (vSInt16*) dtbl;
-
- vSInt16 v0;
- v0 = *vdtbl;
- v0 = _mm_alignr_epi8(v0, v0, i);
-
- return 0;
-#endif
-}
diff --git a/test/FrontendC/2010-06-11-SaveExpr.c b/test/FrontendC/2010-06-11-SaveExpr.c
deleted file mode 100644
index d1c122d..0000000
--- a/test/FrontendC/2010-06-11-SaveExpr.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %llvmgcc -S %s
-// Test case by Eric Postpischil!
-void foo(void)
-{
- char a[1];
- int t = 1;
- ((char (*)[t]) a)[0][0] = 0;
-}
diff --git a/test/FrontendC/2010-06-17-asmcrash.c b/test/FrontendC/2010-06-17-asmcrash.c
deleted file mode 100644
index 5063054..0000000
--- a/test/FrontendC/2010-06-17-asmcrash.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc -S -o - %s | llc -mtriple=x86_64-apple-darwin | FileCheck %s
-// XFAIL: *
-// XTARGET: x86,i386,i686
-
-typedef long long int64_t;
-typedef unsigned char uint8_t;
-typedef int64_t x86_reg;
-
-void avg_pixels8_mmx2(uint8_t *block, const uint8_t *pixels, int line_size, int h)
-{
- __asm__ volatile("# %0 %1 %2 %3"
- :"+g"(h), "+S"(pixels), "+D"(block)
- :"r" ((x86_reg)line_size)
- :"%""rax", "memory");
-// CHECK: # %ecx %rsi %rdi %rdx
- }
diff --git a/test/FrontendC/2010-06-28-DbgLocalVar.c b/test/FrontendC/2010-06-28-DbgLocalVar.c
deleted file mode 100644
index e5df885..0000000
--- a/test/FrontendC/2010-06-28-DbgLocalVar.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -S -O2 -g %s -o - | llc -O2 -o %t.s
-// RUN: grep DW_TAG_structure_type %t.s | count 2
-// Radar 8122864
-
-// Code is not generated for function foo, but preserve type information of
-// local variable xyz.
-static foo() {
- struct X { int a; int b; } xyz;
-}
-
-int bar() {
- foo();
- return 1;
-}
diff --git a/test/FrontendC/2010-06-28-nowarn.c b/test/FrontendC/2010-06-28-nowarn.c
deleted file mode 100644
index 3db8df1..0000000
--- a/test/FrontendC/2010-06-28-nowarn.c
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %llvmgcc %s -S -m32 -fasm-blocks -o /dev/null
-// This should not warn about unreferenced label. 7729514.
-// XFAIL: *
-// XTARGET: x86,i386,i686
-
-void quarterAsm(int array[], int len)
-{
- __asm
- {
- mov esi, array;
- mov ecx, len;
- shr ecx, 2;
-loop:
- movdqa xmm0, [esi];
- psrad xmm0, 2;
- movdqa [esi], xmm0;
- add esi, 16;
- sub ecx, 1;
- jnz loop;
- }
-}
diff --git a/test/FrontendC/2010-07-08-DeclDebugLineNo.c b/test/FrontendC/2010-07-08-DeclDebugLineNo.c
deleted file mode 100644
index 491b7db..0000000
--- a/test/FrontendC/2010-07-08-DeclDebugLineNo.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -S -O0 -g %s -o - | FileCheck %s
-// Insure that dbg.declare lines for locals refer to correct line number records.
-// Radar 8152866.
-void foo() {
- int l = 0; // line #4: CHECK: {{call.*llvm.dbg.declare.*%l.*\!dbg }}[[variable_l:![0-9]+]]
- int p = 0; // line #5: CHECK: {{call.*llvm.dbg.declare.*%p.*\!dbg }}[[variable_p:![0-9]+]]
-}
-// Now match the line number records:
-// CHECK: {{^}}[[variable_l]]{{ = metadata ![{]i32 5,}}
-// CHECK: {{^}}[[variable_p]]{{ = metadata ![{]i32 6,}}
diff --git a/test/FrontendC/2010-07-14-overconservative-align.c b/test/FrontendC/2010-07-14-overconservative-align.c
deleted file mode 100644
index c4a9caa..0000000
--- a/test/FrontendC/2010-07-14-overconservative-align.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | FileCheck %s
-// PR 5995
-struct s {
- int word;
- struct {
- int filler __attribute__ ((aligned (8)));
- };
-};
-
-void func (struct s *s)
-{
-// CHECK: load %struct.s** %s_addr, align {{[48]}}
- s->word = 0;
-}
diff --git a/test/FrontendC/2010-07-14-ref-off-end.c b/test/FrontendC/2010-07-14-ref-off-end.c
deleted file mode 100644
index c7fdd95..0000000
--- a/test/FrontendC/2010-07-14-ref-off-end.c
+++ /dev/null
@@ -1,27 +0,0 @@
-// RUN: %llvmgcc %s -S -m32 -o - | FileCheck %s
-// Formerly this generated code that did a load past the end of the structure.
-// That was fixed by 46726, but that patch had bad side effects and was
-// reverted. This has been fixed another way in the meantime.
-extern void abort();
-extern void exit(int);
-struct T
-{
-unsigned i:8;
-unsigned c:24;
-};
-f(struct T t)
-{
-struct T s[1];
-s[0]=t;
-return(char)s->c;
-}
-main()
-{
-// CHECK: getelementptr inbounds %struct.T* %t, i32 0, i32 0
-// CHECK: getelementptr inbounds %struct.T* %t, i32 0, i32 0
-struct T t;
-t.i=0xff;
-t.c=0xffff11;
-if(f(t)!=0x11)abort();
-exit(0);
-}
diff --git a/test/FrontendC/2010-07-27-MinNoFoldConst.c b/test/FrontendC/2010-07-27-MinNoFoldConst.c
deleted file mode 100644
index ea711e5..0000000
--- a/test/FrontendC/2010-07-27-MinNoFoldConst.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | FileCheck %s
-extern int printf(const char *, ...);
-static void bad(unsigned int v1, unsigned int v2) {
- printf("%u\n", 1631381461u * (((v2 - 1273463329u <= v1 - 1273463329u) ? v2 : v1) - 1273463329u) + 121322179u);
-}
-// Radar 8198362
-// GCC FE wants to convert the above to
-// 1631381461u * MIN(v2 - 1273463329u, v1 - 1273463329u)
-// and then to
-// MIN(1631381461u * v2 - 4047041419, 1631381461u * v1 - 4047041419)
-//
-// 1631381461u * 1273463329u = 2077504466193943669, but 32-bit overflow clips
-// this to 4047041419. This breaks the comparison implicit in the MIN().
-// Two multiply operations suggests the bad optimization is happening;
-// one multiplication, after the MIN(), is correct.
-// CHECK: mul
-// CHECK-NOT: mul
-// CHECK: ret
diff --git a/test/FrontendC/2010-08-12-asm-aggr-arg.c b/test/FrontendC/2010-08-12-asm-aggr-arg.c
deleted file mode 100644
index 81ec14b..0000000
--- a/test/FrontendC/2010-08-12-asm-aggr-arg.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc %s -S -O0 -o - | FileCheck %s
-// Radar 8288710: A small aggregate can be passed as an integer. Make sure
-// we don't get an error with "input constraint with a matching output
-// constraint of incompatible type!"
-
-struct wrapper {
- int i;
-};
-
-// CHECK: xyz
-int test(int i) {
- struct wrapper w;
- w.i = i;
- __asm__("xyz" : "=r" (w) : "0" (w));
- return w.i;
-}
diff --git a/test/FrontendC/2010-11-16-asmblock.c b/test/FrontendC/2010-11-16-asmblock.c
deleted file mode 100644
index 2d97681..0000000
--- a/test/FrontendC/2010-11-16-asmblock.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc -S %s -fasm-blocks -o - | FileCheck %s
-// XFAIL: *
-// XTARGET: x86,i386,i686
-// 84282548
-
-void foo()
-{
-// CHECK: %0 = call i32 asm sideeffect "", "={ecx}"() nounwind
-// CHECK: %1 = call i32 asm sideeffect alignstack "sall $$3, $0", "={ecx},{ecx},~{dirflag},~{fpsr},~{flags},~{memory}"(i32 %0) nounwind
-// CHECK: store i32 %1, i32* %"%ecx"
- __asm {
- sal ecx, 3;
- add esi, ecx;
- add edi, ecx;
- }
-}
diff --git a/test/FrontendC/2010-12-01-CommonGlobal.c b/test/FrontendC/2010-12-01-CommonGlobal.c
deleted file mode 100644
index 3f6d7e8..0000000
--- a/test/FrontendC/2010-12-01-CommonGlobal.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null
-// Don't crash on a common-linkage constant global.
-extern const int kABSourceTypeProperty;
-int foo(void) {
- return kABSourceTypeProperty;
-}
-const int kABSourceTypeProperty;
diff --git a/test/FrontendC/2011-02-21-DATA-common.c b/test/FrontendC/2011-02-21-DATA-common.c
deleted file mode 100644
index 650ae7e..0000000
--- a/test/FrontendC/2011-02-21-DATA-common.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc -S %s -o /dev/null
-struct rtxc_snapshot {
- int a, b, c, d;
-};
-__attribute__ ((section("__DATA, __common"))) static struct rtxc_snapshot rtxc_log_A[4];
diff --git a/test/FrontendC/2011-03-02-UnionInitializer.c b/test/FrontendC/2011-03-02-UnionInitializer.c
deleted file mode 100644
index a5ea75e..0000000
--- a/test/FrontendC/2011-03-02-UnionInitializer.c
+++ /dev/null
@@ -1,2 +0,0 @@
-// RUN: %llvmgcc -S %s
-union { int :3; double f; } u17_017 = {17.17};
diff --git a/test/FrontendC/2011-03-08-ZeroFieldUnionInitializer.c b/test/FrontendC/2011-03-08-ZeroFieldUnionInitializer.c
deleted file mode 100644
index 1fd8a87..0000000
--- a/test/FrontendC/2011-03-08-ZeroFieldUnionInitializer.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -S %s
-typedef struct {
- union {
- struct { } __attribute((packed));
- };
-} fenv_t;
-const fenv_t _FE_DFL_ENV = {{{ 0, 0, 0, 0 }}};
diff --git a/test/FrontendC/2011-03-31-ArrayRefFolding.c b/test/FrontendC/2011-03-31-ArrayRefFolding.c
deleted file mode 100644
index 4039279..0000000
--- a/test/FrontendC/2011-03-31-ArrayRefFolding.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc -S -o - -m32 -Os %s | FileCheck %s
-// PR9571
-
-struct t {
- int x;
-};
-
-extern struct t *cfun;
-
-int f(void) {
- if (!(cfun + 0))
-// CHECK: icmp eq %struct.t* %0, null
- return 0;
- return cfun->x;
-}
diff --git a/test/FrontendC/ARM/dg.exp b/test/FrontendC/ARM/dg.exp
deleted file mode 100644
index df7d49e..0000000
--- a/test/FrontendC/ARM/dg.exp
+++ /dev/null
@@ -1,5 +0,0 @@
-load_lib llvm.exp
-
-if { [llvm_supports_target ARM] && [llvm_gcc_supports c] } {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp,s}]]
-}
diff --git a/test/FrontendC/ARM/inline-asm-multichar.c b/test/FrontendC/ARM/inline-asm-multichar.c
deleted file mode 100644
index bd88390..0000000
--- a/test/FrontendC/ARM/inline-asm-multichar.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -S -march=armv7a %s | FileCheck %s
-
-// XFAIL: *
-// XTARGET: arm
-
-int t1() {
- static float k = 1.0f;
- // CHECK: "flds s15, $0 \0A", "*^Uv,~{s15}"
- __asm__ volatile ("flds s15, %[k] \n" :: [k] "Uv,m" (k) : "s15");
- return 0;
-}
diff --git a/test/FrontendC/Atomics-no64bit.c b/test/FrontendC/Atomics-no64bit.c
deleted file mode 100644
index 6fb6109..0000000
--- a/test/FrontendC/Atomics-no64bit.c
+++ /dev/null
@@ -1,190 +0,0 @@
-// Test frontend handling of __sync builtins.
-// Modified from a gcc testcase.
-// RUN: %llvmgcc -S %s -o - | grep atomic | count 150
-// RUN: %llvmgcc -S %s -o - | grep p0i8 | count 50
-// RUN: %llvmgcc -S %s -o - | grep p0i16 | count 50
-// RUN: %llvmgcc -S %s -o - | grep p0i32 | count 50
-// RUN: %llvmgcc -S %s -o - | grep volatile | count 6
-
-// Currently this is implemented only for Alpha, X86, PowerPC.
-// Add your target here if it doesn't work.
-// This version of the test does not include long long.
-// XFAIL: sparc,arm
-
-signed char sc;
-unsigned char uc;
-signed short ss;
-unsigned short us;
-signed int si;
-unsigned int ui;
-
-void test_op_ignore (void)
-{
- (void) __sync_fetch_and_add (&sc, 1);
- (void) __sync_fetch_and_add (&uc, 1);
- (void) __sync_fetch_and_add (&ss, 1);
- (void) __sync_fetch_and_add (&us, 1);
- (void) __sync_fetch_and_add (&si, 1);
- (void) __sync_fetch_and_add (&ui, 1);
-
- (void) __sync_fetch_and_sub (&sc, 1);
- (void) __sync_fetch_and_sub (&uc, 1);
- (void) __sync_fetch_and_sub (&ss, 1);
- (void) __sync_fetch_and_sub (&us, 1);
- (void) __sync_fetch_and_sub (&si, 1);
- (void) __sync_fetch_and_sub (&ui, 1);
-
- (void) __sync_fetch_and_or (&sc, 1);
- (void) __sync_fetch_and_or (&uc, 1);
- (void) __sync_fetch_and_or (&ss, 1);
- (void) __sync_fetch_and_or (&us, 1);
- (void) __sync_fetch_and_or (&si, 1);
- (void) __sync_fetch_and_or (&ui, 1);
-
- (void) __sync_fetch_and_xor (&sc, 1);
- (void) __sync_fetch_and_xor (&uc, 1);
- (void) __sync_fetch_and_xor (&ss, 1);
- (void) __sync_fetch_and_xor (&us, 1);
- (void) __sync_fetch_and_xor (&si, 1);
- (void) __sync_fetch_and_xor (&ui, 1);
-
- (void) __sync_fetch_and_and (&sc, 1);
- (void) __sync_fetch_and_and (&uc, 1);
- (void) __sync_fetch_and_and (&ss, 1);
- (void) __sync_fetch_and_and (&us, 1);
- (void) __sync_fetch_and_and (&si, 1);
- (void) __sync_fetch_and_and (&ui, 1);
-
- (void) __sync_fetch_and_nand (&sc, 1);
- (void) __sync_fetch_and_nand (&uc, 1);
- (void) __sync_fetch_and_nand (&ss, 1);
- (void) __sync_fetch_and_nand (&us, 1);
- (void) __sync_fetch_and_nand (&si, 1);
- (void) __sync_fetch_and_nand (&ui, 1);
-}
-
-void test_fetch_and_op (void)
-{
- sc = __sync_fetch_and_add (&sc, 11);
- uc = __sync_fetch_and_add (&uc, 11);
- ss = __sync_fetch_and_add (&ss, 11);
- us = __sync_fetch_and_add (&us, 11);
- si = __sync_fetch_and_add (&si, 11);
- ui = __sync_fetch_and_add (&ui, 11);
-
- sc = __sync_fetch_and_sub (&sc, 11);
- uc = __sync_fetch_and_sub (&uc, 11);
- ss = __sync_fetch_and_sub (&ss, 11);
- us = __sync_fetch_and_sub (&us, 11);
- si = __sync_fetch_and_sub (&si, 11);
- ui = __sync_fetch_and_sub (&ui, 11);
-
- sc = __sync_fetch_and_or (&sc, 11);
- uc = __sync_fetch_and_or (&uc, 11);
- ss = __sync_fetch_and_or (&ss, 11);
- us = __sync_fetch_and_or (&us, 11);
- si = __sync_fetch_and_or (&si, 11);
- ui = __sync_fetch_and_or (&ui, 11);
-
- sc = __sync_fetch_and_xor (&sc, 11);
- uc = __sync_fetch_and_xor (&uc, 11);
- ss = __sync_fetch_and_xor (&ss, 11);
- us = __sync_fetch_and_xor (&us, 11);
- si = __sync_fetch_and_xor (&si, 11);
- ui = __sync_fetch_and_xor (&ui, 11);
-
- sc = __sync_fetch_and_and (&sc, 11);
- uc = __sync_fetch_and_and (&uc, 11);
- ss = __sync_fetch_and_and (&ss, 11);
- us = __sync_fetch_and_and (&us, 11);
- si = __sync_fetch_and_and (&si, 11);
- ui = __sync_fetch_and_and (&ui, 11);
-
- sc = __sync_fetch_and_nand (&sc, 11);
- uc = __sync_fetch_and_nand (&uc, 11);
- ss = __sync_fetch_and_nand (&ss, 11);
- us = __sync_fetch_and_nand (&us, 11);
- si = __sync_fetch_and_nand (&si, 11);
- ui = __sync_fetch_and_nand (&ui, 11);
-}
-
-void test_op_and_fetch (void)
-{
- sc = __sync_add_and_fetch (&sc, uc);
- uc = __sync_add_and_fetch (&uc, uc);
- ss = __sync_add_and_fetch (&ss, uc);
- us = __sync_add_and_fetch (&us, uc);
- si = __sync_add_and_fetch (&si, uc);
- ui = __sync_add_and_fetch (&ui, uc);
-
- sc = __sync_sub_and_fetch (&sc, uc);
- uc = __sync_sub_and_fetch (&uc, uc);
- ss = __sync_sub_and_fetch (&ss, uc);
- us = __sync_sub_and_fetch (&us, uc);
- si = __sync_sub_and_fetch (&si, uc);
- ui = __sync_sub_and_fetch (&ui, uc);
-
- sc = __sync_or_and_fetch (&sc, uc);
- uc = __sync_or_and_fetch (&uc, uc);
- ss = __sync_or_and_fetch (&ss, uc);
- us = __sync_or_and_fetch (&us, uc);
- si = __sync_or_and_fetch (&si, uc);
- ui = __sync_or_and_fetch (&ui, uc);
-
- sc = __sync_xor_and_fetch (&sc, uc);
- uc = __sync_xor_and_fetch (&uc, uc);
- ss = __sync_xor_and_fetch (&ss, uc);
- us = __sync_xor_and_fetch (&us, uc);
- si = __sync_xor_and_fetch (&si, uc);
- ui = __sync_xor_and_fetch (&ui, uc);
-
- sc = __sync_and_and_fetch (&sc, uc);
- uc = __sync_and_and_fetch (&uc, uc);
- ss = __sync_and_and_fetch (&ss, uc);
- us = __sync_and_and_fetch (&us, uc);
- si = __sync_and_and_fetch (&si, uc);
- ui = __sync_and_and_fetch (&ui, uc);
-
- sc = __sync_nand_and_fetch (&sc, uc);
- uc = __sync_nand_and_fetch (&uc, uc);
- ss = __sync_nand_and_fetch (&ss, uc);
- us = __sync_nand_and_fetch (&us, uc);
- si = __sync_nand_and_fetch (&si, uc);
- ui = __sync_nand_and_fetch (&ui, uc);
-}
-
-void test_compare_and_swap (void)
-{
- sc = __sync_val_compare_and_swap (&sc, uc, sc);
- uc = __sync_val_compare_and_swap (&uc, uc, sc);
- ss = __sync_val_compare_and_swap (&ss, uc, sc);
- us = __sync_val_compare_and_swap (&us, uc, sc);
- si = __sync_val_compare_and_swap (&si, uc, sc);
- ui = __sync_val_compare_and_swap (&ui, uc, sc);
-
- ui = __sync_bool_compare_and_swap (&sc, uc, sc);
- ui = __sync_bool_compare_and_swap (&uc, uc, sc);
- ui = __sync_bool_compare_and_swap (&ss, uc, sc);
- ui = __sync_bool_compare_and_swap (&us, uc, sc);
- ui = __sync_bool_compare_and_swap (&si, uc, sc);
- ui = __sync_bool_compare_and_swap (&ui, uc, sc);
-}
-
-void test_lock (void)
-{
- sc = __sync_lock_test_and_set (&sc, 1);
- uc = __sync_lock_test_and_set (&uc, 1);
- ss = __sync_lock_test_and_set (&ss, 1);
- us = __sync_lock_test_and_set (&us, 1);
- si = __sync_lock_test_and_set (&si, 1);
- ui = __sync_lock_test_and_set (&ui, 1);
-
- __sync_synchronize ();
-
- __sync_lock_release (&sc);
- __sync_lock_release (&uc);
- __sync_lock_release (&ss);
- __sync_lock_release (&us);
- __sync_lock_release (&si);
- __sync_lock_release (&ui);
-}
diff --git a/test/FrontendC/Atomics.c b/test/FrontendC/Atomics.c
deleted file mode 100644
index 2b96ae0..0000000
--- a/test/FrontendC/Atomics.c
+++ /dev/null
@@ -1,236 +0,0 @@
-// Test frontend handling of __sync builtins.
-// Modified from a gcc testcase.
-// RUN: %llvmgcc -S %s -o - | grep atomic | count 200
-// RUN: %llvmgcc -S %s -o - | grep p0i8 | count 50
-// RUN: %llvmgcc -S %s -o - | grep p0i16 | count 50
-// RUN: %llvmgcc -S %s -o - | grep p0i32 | count 50
-// RUN: %llvmgcc -S %s -o - | grep volatile | count 8
-
-// Currently this is implemented only for Alpha, X86, PowerPC.
-// Add your target here if it doesn't work.
-// PPC32 does not translate the long long variants, so fails this test.
-// XFAIL: sparc,arm,powerpc
-
-signed char sc;
-unsigned char uc;
-signed short ss;
-unsigned short us;
-signed int si;
-unsigned int ui;
-signed long long sll;
-unsigned long long ull;
-
-void test_op_ignore (void)
-{
- (void) __sync_fetch_and_add (&sc, 1);
- (void) __sync_fetch_and_add (&uc, 1);
- (void) __sync_fetch_and_add (&ss, 1);
- (void) __sync_fetch_and_add (&us, 1);
- (void) __sync_fetch_and_add (&si, 1);
- (void) __sync_fetch_and_add (&ui, 1);
- (void) __sync_fetch_and_add (&sll, 1);
- (void) __sync_fetch_and_add (&ull, 1);
-
- (void) __sync_fetch_and_sub (&sc, 1);
- (void) __sync_fetch_and_sub (&uc, 1);
- (void) __sync_fetch_and_sub (&ss, 1);
- (void) __sync_fetch_and_sub (&us, 1);
- (void) __sync_fetch_and_sub (&si, 1);
- (void) __sync_fetch_and_sub (&ui, 1);
- (void) __sync_fetch_and_sub (&sll, 1);
- (void) __sync_fetch_and_sub (&ull, 1);
-
- (void) __sync_fetch_and_or (&sc, 1);
- (void) __sync_fetch_and_or (&uc, 1);
- (void) __sync_fetch_and_or (&ss, 1);
- (void) __sync_fetch_and_or (&us, 1);
- (void) __sync_fetch_and_or (&si, 1);
- (void) __sync_fetch_and_or (&ui, 1);
- (void) __sync_fetch_and_or (&sll, 1);
- (void) __sync_fetch_and_or (&ull, 1);
-
- (void) __sync_fetch_and_xor (&sc, 1);
- (void) __sync_fetch_and_xor (&uc, 1);
- (void) __sync_fetch_and_xor (&ss, 1);
- (void) __sync_fetch_and_xor (&us, 1);
- (void) __sync_fetch_and_xor (&si, 1);
- (void) __sync_fetch_and_xor (&ui, 1);
- (void) __sync_fetch_and_xor (&sll, 1);
- (void) __sync_fetch_and_xor (&ull, 1);
-
- (void) __sync_fetch_and_and (&sc, 1);
- (void) __sync_fetch_and_and (&uc, 1);
- (void) __sync_fetch_and_and (&ss, 1);
- (void) __sync_fetch_and_and (&us, 1);
- (void) __sync_fetch_and_and (&si, 1);
- (void) __sync_fetch_and_and (&ui, 1);
- (void) __sync_fetch_and_and (&sll, 1);
- (void) __sync_fetch_and_and (&ull, 1);
-
- (void) __sync_fetch_and_nand (&sc, 1);
- (void) __sync_fetch_and_nand (&uc, 1);
- (void) __sync_fetch_and_nand (&ss, 1);
- (void) __sync_fetch_and_nand (&us, 1);
- (void) __sync_fetch_and_nand (&si, 1);
- (void) __sync_fetch_and_nand (&ui, 1);
- (void) __sync_fetch_and_nand (&sll, 1);
- (void) __sync_fetch_and_nand (&ull, 1);
-}
-
-void test_fetch_and_op (void)
-{
- sc = __sync_fetch_and_add (&sc, 11);
- uc = __sync_fetch_and_add (&uc, 11);
- ss = __sync_fetch_and_add (&ss, 11);
- us = __sync_fetch_and_add (&us, 11);
- si = __sync_fetch_and_add (&si, 11);
- ui = __sync_fetch_and_add (&ui, 11);
- sll = __sync_fetch_and_add (&sll, 11);
- ull = __sync_fetch_and_add (&ull, 11);
-
- sc = __sync_fetch_and_sub (&sc, 11);
- uc = __sync_fetch_and_sub (&uc, 11);
- ss = __sync_fetch_and_sub (&ss, 11);
- us = __sync_fetch_and_sub (&us, 11);
- si = __sync_fetch_and_sub (&si, 11);
- ui = __sync_fetch_and_sub (&ui, 11);
- sll = __sync_fetch_and_sub (&sll, 11);
- ull = __sync_fetch_and_sub (&ull, 11);
-
- sc = __sync_fetch_and_or (&sc, 11);
- uc = __sync_fetch_and_or (&uc, 11);
- ss = __sync_fetch_and_or (&ss, 11);
- us = __sync_fetch_and_or (&us, 11);
- si = __sync_fetch_and_or (&si, 11);
- ui = __sync_fetch_and_or (&ui, 11);
- sll = __sync_fetch_and_or (&sll, 11);
- ull = __sync_fetch_and_or (&ull, 11);
-
- sc = __sync_fetch_and_xor (&sc, 11);
- uc = __sync_fetch_and_xor (&uc, 11);
- ss = __sync_fetch_and_xor (&ss, 11);
- us = __sync_fetch_and_xor (&us, 11);
- si = __sync_fetch_and_xor (&si, 11);
- ui = __sync_fetch_and_xor (&ui, 11);
- sll = __sync_fetch_and_xor (&sll, 11);
- ull = __sync_fetch_and_xor (&ull, 11);
-
- sc = __sync_fetch_and_and (&sc, 11);
- uc = __sync_fetch_and_and (&uc, 11);
- ss = __sync_fetch_and_and (&ss, 11);
- us = __sync_fetch_and_and (&us, 11);
- si = __sync_fetch_and_and (&si, 11);
- ui = __sync_fetch_and_and (&ui, 11);
- sll = __sync_fetch_and_and (&sll, 11);
- ull = __sync_fetch_and_and (&ull, 11);
-
- sc = __sync_fetch_and_nand (&sc, 11);
- uc = __sync_fetch_and_nand (&uc, 11);
- ss = __sync_fetch_and_nand (&ss, 11);
- us = __sync_fetch_and_nand (&us, 11);
- si = __sync_fetch_and_nand (&si, 11);
- ui = __sync_fetch_and_nand (&ui, 11);
- sll = __sync_fetch_and_nand (&sll, 11);
- ull = __sync_fetch_and_nand (&ull, 11);
-}
-
-void test_op_and_fetch (void)
-{
- sc = __sync_add_and_fetch (&sc, uc);
- uc = __sync_add_and_fetch (&uc, uc);
- ss = __sync_add_and_fetch (&ss, uc);
- us = __sync_add_and_fetch (&us, uc);
- si = __sync_add_and_fetch (&si, uc);
- ui = __sync_add_and_fetch (&ui, uc);
- sll = __sync_add_and_fetch (&sll, uc);
- ull = __sync_add_and_fetch (&ull, uc);
-
- sc = __sync_sub_and_fetch (&sc, uc);
- uc = __sync_sub_and_fetch (&uc, uc);
- ss = __sync_sub_and_fetch (&ss, uc);
- us = __sync_sub_and_fetch (&us, uc);
- si = __sync_sub_and_fetch (&si, uc);
- ui = __sync_sub_and_fetch (&ui, uc);
- sll = __sync_sub_and_fetch (&sll, uc);
- ull = __sync_sub_and_fetch (&ull, uc);
-
- sc = __sync_or_and_fetch (&sc, uc);
- uc = __sync_or_and_fetch (&uc, uc);
- ss = __sync_or_and_fetch (&ss, uc);
- us = __sync_or_and_fetch (&us, uc);
- si = __sync_or_and_fetch (&si, uc);
- ui = __sync_or_and_fetch (&ui, uc);
- sll = __sync_or_and_fetch (&sll, uc);
- ull = __sync_or_and_fetch (&ull, uc);
-
- sc = __sync_xor_and_fetch (&sc, uc);
- uc = __sync_xor_and_fetch (&uc, uc);
- ss = __sync_xor_and_fetch (&ss, uc);
- us = __sync_xor_and_fetch (&us, uc);
- si = __sync_xor_and_fetch (&si, uc);
- ui = __sync_xor_and_fetch (&ui, uc);
- sll = __sync_xor_and_fetch (&sll, uc);
- ull = __sync_xor_and_fetch (&ull, uc);
-
- sc = __sync_and_and_fetch (&sc, uc);
- uc = __sync_and_and_fetch (&uc, uc);
- ss = __sync_and_and_fetch (&ss, uc);
- us = __sync_and_and_fetch (&us, uc);
- si = __sync_and_and_fetch (&si, uc);
- ui = __sync_and_and_fetch (&ui, uc);
- sll = __sync_and_and_fetch (&sll, uc);
- ull = __sync_and_and_fetch (&ull, uc);
-
- sc = __sync_nand_and_fetch (&sc, uc);
- uc = __sync_nand_and_fetch (&uc, uc);
- ss = __sync_nand_and_fetch (&ss, uc);
- us = __sync_nand_and_fetch (&us, uc);
- si = __sync_nand_and_fetch (&si, uc);
- ui = __sync_nand_and_fetch (&ui, uc);
- sll = __sync_nand_and_fetch (&sll, uc);
- ull = __sync_nand_and_fetch (&ull, uc);
-}
-
-void test_compare_and_swap (void)
-{
- sc = __sync_val_compare_and_swap (&sc, uc, sc);
- uc = __sync_val_compare_and_swap (&uc, uc, sc);
- ss = __sync_val_compare_and_swap (&ss, uc, sc);
- us = __sync_val_compare_and_swap (&us, uc, sc);
- si = __sync_val_compare_and_swap (&si, uc, sc);
- ui = __sync_val_compare_and_swap (&ui, uc, sc);
- sll = __sync_val_compare_and_swap (&sll, uc, sc);
- ull = __sync_val_compare_and_swap (&ull, uc, sc);
-
- ui = __sync_bool_compare_and_swap (&sc, uc, sc);
- ui = __sync_bool_compare_and_swap (&uc, uc, sc);
- ui = __sync_bool_compare_and_swap (&ss, uc, sc);
- ui = __sync_bool_compare_and_swap (&us, uc, sc);
- ui = __sync_bool_compare_and_swap (&si, uc, sc);
- ui = __sync_bool_compare_and_swap (&ui, uc, sc);
- ui = __sync_bool_compare_and_swap (&sll, uc, sc);
- ui = __sync_bool_compare_and_swap (&ull, uc, sc);
-}
-
-void test_lock (void)
-{
- sc = __sync_lock_test_and_set (&sc, 1);
- uc = __sync_lock_test_and_set (&uc, 1);
- ss = __sync_lock_test_and_set (&ss, 1);
- us = __sync_lock_test_and_set (&us, 1);
- si = __sync_lock_test_and_set (&si, 1);
- ui = __sync_lock_test_and_set (&ui, 1);
- sll = __sync_lock_test_and_set (&sll, 1);
- ull = __sync_lock_test_and_set (&ull, 1);
-
- __sync_synchronize ();
-
- __sync_lock_release (&sc);
- __sync_lock_release (&uc);
- __sync_lock_release (&ss);
- __sync_lock_release (&us);
- __sync_lock_release (&si);
- __sync_lock_release (&ui);
- __sync_lock_release (&sll);
- __sync_lock_release (&ull);
-}
diff --git a/test/FrontendC/BasicInstrs.c b/test/FrontendC/BasicInstrs.c
deleted file mode 100644
index ceed17c..0000000
--- a/test/FrontendC/BasicInstrs.c
+++ /dev/null
@@ -1,26 +0,0 @@
-// This file can be used to see what a native C compiler is generating for a
-// variety of interesting operations.
-//
-// RUN: %llvmgcc -S %s -o - | llc
-
-unsigned int udiv(unsigned int X, unsigned int Y) {
- return X/Y;
-}
-int sdiv(int X, int Y) {
- return X/Y;
-}
-unsigned int urem(unsigned int X, unsigned int Y) {
- return X%Y;
-}
-int srem(int X, int Y) {
- return X%Y;
-}
-
-_Bool setlt(int X, int Y) {
- return X < Y;
-}
-
-_Bool setgt(int X, int Y) {
- return X > Y;
-}
-
diff --git a/test/FrontendC/alignstack.c b/test/FrontendC/alignstack.c
deleted file mode 100644
index 30c00ff..0000000
--- a/test/FrontendC/alignstack.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %llvmgcc %s -fasm-blocks -S -o - | FileCheck %s
-// Complicated expression as jump target
-// XFAIL: *
-// XTARGET: x86,i386,i686,darwin
-
-void Method3()
-{
-// CHECK: Method3
-// CHECK-NOT: alignstack
- asm("foo:");
-// CHECK: return
-}
-
-void Method4()
-{
-// CHECK: Method4
-// CHECK: alignstack
- asm {
- bar:
- }
-// CHECK: return
-}
-
diff --git a/test/FrontendC/always-inline.c b/test/FrontendC/always-inline.c
deleted file mode 100644
index 22f6c7a..0000000
--- a/test/FrontendC/always-inline.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep call | not grep foo
-
-void bar() {
-}
-
-inline void __attribute__((__always_inline__)) foo() {
- bar();
-}
-
-void i_want_bar() {
- foo();
-}
diff --git a/test/FrontendC/arrayderef.c b/test/FrontendC/arrayderef.c
deleted file mode 100644
index 66c2e0b..0000000
--- a/test/FrontendC/arrayderef.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc %s -S -O -o - | FileCheck %s
-// The load here was getting lost because this code was close
-// enough to the traditional (wrong) implementation of offsetof
-// to confuse the gcc FE. 8629268.
-
-struct foo {
- int x;
- int *y;
-};
-
-struct foo Foo[1];
-
-int * bar(unsigned int ix) {
-// CHECK: load
- return &Foo->y[ix];
-}
-
diff --git a/test/FrontendC/asm-reg-var-local.c b/test/FrontendC/asm-reg-var-local.c
deleted file mode 100644
index e0be10c..0000000
--- a/test/FrontendC/asm-reg-var-local.c
+++ /dev/null
@@ -1,32 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | FileCheck %s
-// Exercise various use cases for local asm "register variables".
-// XFAIL: *
-// XTARGET: x86_64,i686,i386
-
-int foo() {
-// CHECK: %a = alloca i32
-
- register int a asm("rsi")=5;
-// CHECK: store i32 5, i32* %a, align 4
-
- asm volatile("; %0 This asm defines rsi" : "=r"(a));
-// CHECK: %1 = call i32 asm sideeffect "; $0 This asm defines rsi", "={rsi}
-// CHECK: store i32 %1, i32* %a
-
- a = 42;
-// CHECK: store i32 42, i32* %a, align 4
-
- asm volatile("; %0 This asm uses rsi" : : "r"(a));
-// CHECK: %2 = load i32* %a, align 4
-// CHECK: call void asm sideeffect "", "{rsi}"(i32 %2) nounwind
-// CHECK: %3 = call i32 asm sideeffect "", "={rsi}"() nounwind
-// CHECK: call void asm sideeffect "; $0 This asm uses rsi", "{rsi},~{dirflag},~{fpsr},~{flags}"(i32 %3)
-
- return a;
-// CHECK: %4 = load i32* %a, align 4
-// CHECK: call void asm sideeffect "", "{rsi}"(i32 %4) nounwind
-// CHECK: %5 = call i32 asm sideeffect "", "={rsi}"() nounwind
-// CHECK: store i32 %5, i32* %0, align 4
-// CHECK: %6 = load i32* %0, align 4
-// CHECK: store i32 %6, i32* %retval, align 4
-}
diff --git a/test/FrontendC/attribute_constructor.c b/test/FrontendC/attribute_constructor.c
deleted file mode 100644
index da17a37..0000000
--- a/test/FrontendC/attribute_constructor.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | grep llvm.global_ctors
-
-void foo() __attribute__((constructor));
-void foo() {
- bar();
-}
diff --git a/test/FrontendC/block-copy.c b/test/FrontendC/block-copy.c
deleted file mode 100644
index c088f2d..0000000
--- a/test/FrontendC/block-copy.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/* RUN: %llvmgcc %s -S -o - -O3 | grep {call.*memcpy}
-
- This should compile into a memcpy from a global, not 128 stores. */
-
-
-
-void foo();
-
-float bar() {
- float lookupTable[] = {-1,-1,-1,0, -1,-1,0,-1, -1,-1,0,1, -1,-1,1,0,
- -1,0,-1,-1, -1,0,-1,1, -1,0,1,-1, -1,0,1,1,
- -1,1,-1,0, -1,1,0,-1, -1,1,0,1, -1,1,1,0,
- 0,-1,-1,-1, 0,-1,-1,1, 0,-1,1,-1, 0,-1,1,1,
- 1,-1,-1,0, 1,-1,0,-1, 1,-1,0,1, 1,-1,1,0,
- 1,0,-1,-1, 1,0,-1,1, 1,0,1,-1, 1,0,1,1,
- 1,1,-1,0, 1,1,0,-1, 1,1,0,1, 1,1,1,0,
- 0,1,-1,-1, 0,1,-1,1, 0,1,1,-1, 0,1,1,1};
- foo(lookupTable);
-}
-
diff --git a/test/FrontendC/crash-invalid-array.c b/test/FrontendC/crash-invalid-array.c
deleted file mode 100644
index d602f78..0000000
--- a/test/FrontendC/crash-invalid-array.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: not %llvmgcc -O1 %s -S |& grep {error: invalid use of array with unspecified bounds}
-// PR6913
-
-#include <stdio.h>
-
-int main()
-{
- int x[10][10];
- int (*p)[] = x; // <-- this line is what triggered it
-
- int i;
-
- for(i = 0; i < 10; ++i)
- {
- p[i][i] = i;
- }
-}
diff --git a/test/FrontendC/dg.exp b/test/FrontendC/dg.exp
deleted file mode 100644
index a9be28a..0000000
--- a/test/FrontendC/dg.exp
+++ /dev/null
@@ -1,5 +0,0 @@
-load_lib llvm.exp
-
-if [ llvm_gcc_supports c ] then {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
-}
diff --git a/test/FrontendC/exact-div-expr.c b/test/FrontendC/exact-div-expr.c
deleted file mode 100644
index 9dce922..0000000
--- a/test/FrontendC/exact-div-expr.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o - -O1 | grep ashr
-// RUN: %llvmgcc -S %s -o - -O1 | not grep sdiv
-
-long long test(int *A, int *B) {
- return A-B;
-}
diff --git a/test/FrontendC/extern-weak.c b/test/FrontendC/extern-weak.c
deleted file mode 100644
index 73b59cc..0000000
--- a/test/FrontendC/extern-weak.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -O3 -S -o - %s | grep extern_weak
-// RUN: %llvmgcc -O3 -S -o - %s | llc
-
-#if !defined(__linux__) && !defined(__FreeBSD__) && \
- !defined(__OpenBSD__) && !defined(__CYGWIN__) && !defined(__DragonFly__)
-void foo() __attribute__((weak_import));
-#else
-void foo() __attribute__((weak));
-#endif
-
-void bar() { foo(); }
-
diff --git a/test/FrontendC/fp-logical.c b/test/FrontendC/fp-logical.c
deleted file mode 100644
index 60404f6..0000000
--- a/test/FrontendC/fp-logical.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | grep bitcast | count 14
-
-typedef float vFloat __attribute__ ((__vector_size__ (16)));
-typedef unsigned int vUInt32 __attribute__ ((__vector_size__ (16)));
-void foo(vFloat *X) {
- vFloat NoSignBit = (vFloat) ~ (vUInt32) (vFloat) { -0.f, -0.f, -0.f, -0.f };
- vFloat ExtremeValue = *X & NoSignBit;
- *X = ExtremeValue;
-}
-
-void bar(vFloat *X) {
- vFloat NoSignBit = (vFloat) ~ (vUInt32) (vFloat) { -0.f, -0.f, -0.f, -0.f };
- vFloat ExtremeValue = *X & ~NoSignBit;
- *X = ExtremeValue;
-}
diff --git a/test/FrontendC/func-aligned.c b/test/FrontendC/func-aligned.c
deleted file mode 100644
index 477e824..0000000
--- a/test/FrontendC/func-aligned.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | FileCheck %s
-
-// rdar://7270273
-void foo() __attribute__((aligned (64)));
-void foo() {
-// CHECK: define void @foo() {{.*}} align 64
-}
diff --git a/test/FrontendC/funccall.c b/test/FrontendC/funccall.c
deleted file mode 100644
index 9735e34..0000000
--- a/test/FrontendC/funccall.c
+++ /dev/null
@@ -1,17 +0,0 @@
-
-static int q;
-
-void foo() {
- int t = q;
- q = t + 1;
-}
-int main() {
- q = 0;
- foo();
- q = q - 1;
-
- return q;
-}
-
-// This is the source that corresponds to funccall.ll
-// RUN: echo foo
diff --git a/test/FrontendC/hidden-visibility.c b/test/FrontendC/hidden-visibility.c
deleted file mode 100644
index 589bb53..0000000
--- a/test/FrontendC/hidden-visibility.c
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | grep {hidden unnamed_addr global}
-
-int X __attribute__ ((__visibility__ ("hidden"))) = 123;
diff --git a/test/FrontendC/implicit-arg.c b/test/FrontendC/implicit-arg.c
deleted file mode 100644
index a6cb8bc..0000000
--- a/test/FrontendC/implicit-arg.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc %s -S -O0 -o -
-// RUN: %llvmgcc %s -S -O1 -o -
-// rdar://6518089
-
-static int bar();
-void foo() {
- int a = bar();
-}
-int bar(unsigned a) {
-}
diff --git a/test/FrontendC/inline-asm-function.c b/test/FrontendC/inline-asm-function.c
deleted file mode 100644
index e584840..0000000
--- a/test/FrontendC/inline-asm-function.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -fasm-blocks -o - -O | grep naked
-// 7533078 (partial).
-
-asm int f() {
- xyz
-}
diff --git a/test/FrontendC/inline-asm-mrv.c b/test/FrontendC/inline-asm-mrv.c
deleted file mode 100644
index 6d1df67..0000000
--- a/test/FrontendC/inline-asm-mrv.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -S %s -o - -O | not grep alloca
-// PR2094
-
-int sad16_sse2(void *v, unsigned char *blk2, unsigned char *blk1,
- int stride, int h) {
- int ret;
- asm volatile( "%0 %1 %2 %3"
- : "+r" (h), "+r" (blk1), "+r" (blk2)
- : "r" ((long)stride));
- asm volatile("set %0 %1" : "=r"(ret) : "r"(blk1));
- return ret;
-}
diff --git a/test/FrontendC/libcalls-d.c b/test/FrontendC/libcalls-d.c
deleted file mode 100644
index d92208d..0000000
--- a/test/FrontendC/libcalls-d.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// llvm-gcc -O1+ should run simplify libcalls, O0 shouldn't
-// and -fno-builtins shouldn't.
-// -fno-math-errno should emit an llvm intrinsic, -fmath-errno should not.
-// RUN: %llvmgcc %s -S -fno-math-errno -O0 -o - | grep {call.*exp2\\.f64}
-// RUN: %llvmgcc %s -S -fmath-errno -O0 -o - | grep {call.*exp2}
-// RUN: %llvmgcc %s -S -O1 -o - | grep {call.*ldexp}
-// RUN: %llvmgcc %s -S -O3 -fno-builtin -o - | grep {call.*exp2}
-
-double exp2(double);
-
-double t4(unsigned char x) {
- return exp2(x);
-}
-
diff --git a/test/FrontendC/libcalls-ld.c b/test/FrontendC/libcalls-ld.c
deleted file mode 100644
index cf71d19..0000000
--- a/test/FrontendC/libcalls-ld.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// llvm-gcc -O1+ should run simplify libcalls, O0 shouldn't
-// and -fno-builtins shouldn't.
-// -fno-math-errno should emit an llvm intrinsic, -fmath-errno should not.
-// RUN: %llvmgcc %s -S -fno-math-errno -O0 -o - | grep {call.*exp2\\..*f}
-// RUN: %llvmgcc %s -S -fmath-errno -O0 -o - | grep {call.*exp2l}
-// RUN: %llvmgcc %s -S -O1 -o - | grep {call.*ldexp}
-// RUN: %llvmgcc %s -S -O3 -fno-builtin -o - | grep {call.*exp2l}
-
-// If this fails for you because your target doesn't support long double,
-// please xfail the test.
-
-long double exp2l(long double);
-
-long double t4(unsigned char x) {
- return exp2l(x);
-}
-
diff --git a/test/FrontendC/libcalls.c b/test/FrontendC/libcalls.c
deleted file mode 100644
index 60e22e7..0000000
--- a/test/FrontendC/libcalls.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// llvm-gcc -O1+ should run simplify libcalls, O0 shouldn't
-// and -fno-builtins shouldn't.
-// -fno-math-errno should emit an llvm intrinsic, -fmath-errno should not.
-// RUN: %llvmgcc %s -S -fno-math-errno -O0 -o - | grep {call.*exp2\\.f32}
-// RUN: %llvmgcc %s -S -fmath-errno -O0 -o - | grep {call.*exp2f}
-// RUN: %llvmgcc %s -S -O1 -o - | grep {call.*ldexp}
-// RUN: %llvmgcc %s -S -O3 -fno-builtin -o - | grep {call.*exp2f}
-
-float exp2f(float);
-
-float t4(unsigned char x) {
- return exp2f(x);
-}
-
diff --git a/test/FrontendC/misaligned-param.c b/test/FrontendC/misaligned-param.c
deleted file mode 100644
index b4fcfe3..0000000
--- a/test/FrontendC/misaligned-param.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc %s -m32 -S -o - | FileCheck %s
-// Misaligned parameter must be memcpy'd to correctly aligned temporary.
-// XFAIL: *
-// XTARGET: i386-apple-darwin,i686-apple-darwin,x86_64-apple-darwin
-
-struct s { int x; long double y; };
-long double foo(struct s x, int i, struct s y) {
-// CHECK: foo
-// CHECK: %x_addr = alloca %struct.s, align 16
-// CHECK: %y_addr = alloca %struct.s, align 16
-// CHECK: memcpy
-// CHECK: memcpy
-// CHECK: bar
- return bar(&x, &y);
-}
diff --git a/test/FrontendC/mmx-inline-asm.c b/test/FrontendC/mmx-inline-asm.c
deleted file mode 100644
index 5c09a41..0000000
--- a/test/FrontendC/mmx-inline-asm.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgcc -mmmx -S -o - %s | FileCheck %s
-// XFAIL: *
-// XTARGET: x86,i386,i686
-// <rdar://problem/9091220>
-#include <mmintrin.h>
-#include <stdint.h>
-
-// CHECK: { x86_mmx, x86_mmx, x86_mmx, x86_mmx, x86_mmx, x86_mmx, x86_mmx }
-
-void foo(__m64 vfill) {
- __m64 v1, v2, v3, v4, v5, v6, v7;
-
- __asm__ __volatile__ (
- "\tmovq %7, %0\n"
- "\tmovq %7, %1\n"
- "\tmovq %7, %2\n"
- "\tmovq %7, %3\n"
- "\tmovq %7, %4\n"
- "\tmovq %7, %5\n"
- "\tmovq %7, %6"
- : "=&y" (v1), "=&y" (v2), "=&y" (v3),
- "=&y" (v4), "=&y" (v5), "=&y" (v6), "=y" (v7)
- : "y" (vfill));
-}
diff --git a/test/FrontendC/nested-functions.c b/test/FrontendC/nested-functions.c
deleted file mode 100644
index bccbef3..0000000
--- a/test/FrontendC/nested-functions.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %llvmgcc -S %s -o - -fnested-functions
-// PR1274
-
-void Bork() {
- void Fork(const int *src, int size) {
- int i = 1;
- int x;
-
- while (i < size)
- x = src[i];
- }
-}
-
-void foo(void *a){
- inline void foo_bar() {
- a += 1;
- }
-}
diff --git a/test/FrontendC/pr2394.c b/test/FrontendC/pr2394.c
deleted file mode 100644
index ca8b046..0000000
--- a/test/FrontendC/pr2394.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | FileCheck %s
-struct __attribute((packed)) x {int a : 24;};
-int a(struct x* g) {
- // CHECK: load i24
- return g->a;
-}
diff --git a/test/FrontendC/pr3518.c b/test/FrontendC/pr3518.c
deleted file mode 100644
index 112394a..0000000
--- a/test/FrontendC/pr3518.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgcc %s -S -O0 -o - | grep {= internal unnamed_addr global} | count 4
-// PR 3518
-// Some of the objects were coming out as unintialized (external) before 3518
-// was fixed. Internal names are different between llvm-gcc and clang so they
-// are not tested.
-
-extern void abort (void);
-
-struct A { int i; int j; };
-struct B { struct A *a; struct A *b; };
-struct C { struct B *c; struct A *d; };
-struct C e = { &(struct B) { &(struct A) { 1, 2 }, &(struct A) { 3, 4 } }, &(struct A) { 5, 6 } };
-
-int
-main (void)
-{
- if (e.c->a->i != 1 || e.c->a->j != 2)
- abort ();
- if (e.c->b->i != 3 || e.c->b->j != 4)
- abort ();
- if (e.d->i != 5 || e.d->j != 6)
- abort ();
- return 0;
-}
diff --git a/test/FrontendC/pr4349.c b/test/FrontendC/pr4349.c
deleted file mode 100644
index 49c89e2..0000000
--- a/test/FrontendC/pr4349.c
+++ /dev/null
@@ -1,38 +0,0 @@
-// RUN: %llvmgcc %s -S -O0 -o - | FileCheck %s
-// PR 4349
-
-union reg
-{
- unsigned char b[2][2];
- unsigned short w[2];
- unsigned int d;
-};
-struct cpu
-{
- union reg pc;
-};
-extern struct cpu cpu;
-struct svar
-{
- void *ptr;
-};
-// CHECK: @svars1 = global [1 x %struct.svar] [%struct.svar { i8* bitcast (%struct.cpu* @cpu to i8*) }]
-struct svar svars1[] =
-{
- { &((cpu.pc).w[0]) }
-};
-// CHECK: @svars2 = global [1 x %struct.svar] [%struct.svar { i8* getelementptr ([2 x i8]* bitcast (%struct.cpu* @cpu to [2 x i8]*), i{{[0-9]+}} 0, i{{[0-9]+}} 1) }]
-struct svar svars2[] =
-{
- { &((cpu.pc).b[0][1]) }
-};
-// CHECK: @svars3 = global [1 x %struct.svar] [%struct.svar { i8* bitcast (i16* getelementptr ([2 x i16]* bitcast (%struct.cpu* @cpu to [2 x i16]*), i{{[0-9]+}} 0, i{{[0-9]+}} 1) to i8*) }]
-struct svar svars3[] =
-{
- { &((cpu.pc).w[1]) }
-};
-// CHECK: @svars4 = global [1 x %struct.svar] [%struct.svar { i8* getelementptr ([2 x [2 x i8]]* bitcast (%struct.cpu* @cpu to [2 x [2 x i8]]*), i{{[0-9]+}} 0, i{{[0-9]+}} 1, i{{[0-9]+}} 1) }]
-struct svar svars4[] =
-{
- { &((cpu.pc).b[1][1]) }
-};
diff --git a/test/FrontendC/pr5406.c b/test/FrontendC/pr5406.c
deleted file mode 100644
index 0b1f277..0000000
--- a/test/FrontendC/pr5406.c
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: %llvmgcc %s -S -O0 -o - | FileCheck %s
-// PR 5406
-
-// XFAIL: *
-// XTARGET: arm
-
-typedef struct { char x[3]; } A0;
-void foo (int i, ...);
-
-
-// CHECK: call void (i32, ...)* @foo(i32 1, i32 {{.*}}) nounwind
-int main (void)
-{
- A0 a3;
- a3.x[0] = 0;
- a3.x[0] = 0;
- a3.x[2] = 26;
- foo (1, a3 );
- return 0;
-}
diff --git a/test/FrontendC/ptr-rotate.c b/test/FrontendC/ptr-rotate.c
deleted file mode 100644
index 36d9755..0000000
--- a/test/FrontendC/ptr-rotate.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc %s -S -m32 -o /dev/null
-// RUN: %llvmgcc %s -S -O1 -m32 -o - | llc -march=x86 -mtriple=i386-apple-darwin9.7 | FileCheck %s -check-prefix=DARWIN
-
-unsigned int func(void *A) {
- // DARWIN: roll $27
- return ((((unsigned long long) A) >> 5) | (((unsigned long long) A) << 27));
-}
diff --git a/test/FrontendC/redef-ext-inline.c b/test/FrontendC/redef-ext-inline.c
deleted file mode 100644
index 240beb1..0000000
--- a/test/FrontendC/redef-ext-inline.c
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S %s -o -
-// rdar://7208839
-
-extern inline int f1 (void) {return 1;}
-int f3 (void) {return f1();}
-int f1 (void) {return 0;}
diff --git a/test/FrontendC/sret.c b/test/FrontendC/sret.c
deleted file mode 100644
index 4266691..0000000
--- a/test/FrontendC/sret.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %llvmgcc %s -S -O0 -o - | grep sret | count 5
-
-struct abc {
- long a;
- long b;
- long c;
-};
-
-struct abc foo1(void);
-struct abc foo2();
-
-void bar() {
- struct abc dummy1 = foo1();
- struct abc dummy2 = foo2();
-}
diff --git a/test/FrontendC/sret2.c b/test/FrontendC/sret2.c
deleted file mode 100644
index 0f35b1c..0000000
--- a/test/FrontendC/sret2.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc %s -S -O0 -o - | grep sret | count 2
-
-struct abc {
- long a;
- long b;
- long c;
-};
-
-struct abc foo2(){}
diff --git a/test/FrontendC/struct-matching-constraint.c b/test/FrontendC/struct-matching-constraint.c
deleted file mode 100644
index d002cdd..0000000
--- a/test/FrontendC/struct-matching-constraint.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgcc -S -march=armv7a %s
-
-// XFAIL: *
-// XTARGET: arm
-
-typedef struct __simd128_uint16_t
-{
- __neon_uint16x8_t val;
-} uint16x8_t;
-
-void b(uint16x8_t sat, uint16x8_t luma)
-{
- __asm__("vmov.16 %1, %0 \n\t"
- "vtrn.16 %0, %1 \n\t"
- :"=w"(luma), "=w"(sat)
- :"0"(luma)
- );
-
-}
diff --git a/test/FrontendC/unaligned-memcpy.c b/test/FrontendC/unaligned-memcpy.c
deleted file mode 100644
index 8fb84e4..0000000
--- a/test/FrontendC/unaligned-memcpy.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: %llvmgcc %s -S -o - | llc
-
-void bork() {
- char Qux[33] = {0};
-}
diff --git a/test/FrontendC/union-align.c b/test/FrontendC/union-align.c
deleted file mode 100644
index f99a760..0000000
--- a/test/FrontendC/union-align.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep load | grep "4 x float" | not grep "align 4"
-// RUN: %llvmgcc -S %s -o - | grep load | grep "4 x float" | grep "align 16"
-// PR3432
-// rdar://6536377
-
-typedef float __m128 __attribute__ ((__vector_size__ (16)));
-
-typedef union
-{
- int i[4];
- float f[4];
- __m128 v;
-} u_t;
-
-__m128 t(u_t *a) {
- return a->v;
-}
diff --git a/test/FrontendC/vla-1.c b/test/FrontendC/vla-1.c
deleted file mode 100644
index 77f78a5..0000000
--- a/test/FrontendC/vla-1.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc_only -std=gnu99 %s -S |& grep {warning: alignment for}
-// ppc does not support this feature, and gets a fatal error at runtime.
-// XFAIL: powerpc
-
-int foo(int a)
-{
- int var[a] __attribute__((__aligned__(32)));
- return 4;
-}
diff --git a/test/FrontendC/vla-2.c b/test/FrontendC/vla-2.c
deleted file mode 100644
index 555cfc7..0000000
--- a/test/FrontendC/vla-2.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc -std=gnu99 %s -S -o - | grep ".*alloca.*align 16"
-
-extern void bar(int[]);
-
-void foo(int a)
-{
- int var[a] __attribute__((__aligned__(16)));
- bar(var);
- return;
-}
diff --git a/test/FrontendC/vla-3.c b/test/FrontendC/vla-3.c
deleted file mode 100644
index eca9675..0000000
--- a/test/FrontendC/vla-3.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -std=gnu99 %s -S -o - | grep ".*alloca.*align 16"
-
-void adr(char *);
-
-void vlaalign(int size)
-{
- char __attribute__((aligned(16))) tmp[size+32];
- char tmp2[size+16];
-
- adr(tmp);
-}
diff --git a/test/FrontendC/wchar-const.c b/test/FrontendC/wchar-const.c
deleted file mode 100644
index 7cf3322..0000000
--- a/test/FrontendC/wchar-const.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -S %s -o - | grep {constant \\\[18 x} | grep { 84, }
-// This should pass for any endianness combination of host and target.
-#include <wchar.h>
-extern void foo(const wchar_t* p);
-int main (int argc, const char * argv[])
-{
- foo(L"This is some text");
- return 0;
-}
diff --git a/test/FrontendC/weak_constant.c b/test/FrontendC/weak_constant.c
deleted file mode 100644
index 5337948..0000000
--- a/test/FrontendC/weak_constant.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %llvmgcc -S %s -O1 -o - | grep {ret.*123}
-// Check for bug compatibility with gcc.
-
-const int x __attribute((weak)) = 123;
-
-int* f(void) {
- return &x;
-}
-
-int g(void) {
- return *f();
-}
diff --git a/test/FrontendFortran/2008-11-03-OptionOverride.f90 b/test/FrontendFortran/2008-11-03-OptionOverride.f90
deleted file mode 100644
index d65ba9b..0000000
--- a/test/FrontendFortran/2008-11-03-OptionOverride.f90
+++ /dev/null
@@ -1,4 +0,0 @@
-! RUN: %llvmgcc -S %s -march=k8
-! XTARGET: x86
-! Note: this file intentionally left blank, the problem itself is in
-! frontend initialization routines and march flag!
diff --git a/test/FrontendFortran/2009-02-09-FloorDivExpr.f90 b/test/FrontendFortran/2009-02-09-FloorDivExpr.f90
deleted file mode 100644
index ddd05c5..0000000
--- a/test/FrontendFortran/2009-02-09-FloorDivExpr.f90
+++ /dev/null
@@ -1,32 +0,0 @@
-! RUN: %llvmgcc -S %s
-! PR2437
-program main
- implicit none
- call build (77)
-contains
- subroutine build (order)
- integer :: order, i, j
-
-
- call test (1, order, 3, (/ (i, i = 1, order, 3) /))
- call test (order, 1, -3, (/ (i, i = order, 1, -3) /))
-
- do j = -10, 10
- call test (order + j, order, 5, (/ (i, i = order + j, order, 5) /))
- call test (order + j, order, -5, (/ (i, i = order + j, order, -5) /))
- end do
-
- end subroutine build
-
- subroutine test (from, to, step, values)
- integer, dimension (:) :: values
- integer :: from, to, step, last, i
-
- last = 0
- do i = from, to, step
- last = last + 1
- if (values (last) .ne. i) call abort
- end do
- if (size (values, dim = 1) .ne. last) call abort
- end subroutine test
-end program main
diff --git a/test/FrontendFortran/cpow.f90 b/test/FrontendFortran/cpow.f90
deleted file mode 100644
index 25156fd..0000000
--- a/test/FrontendFortran/cpow.f90
+++ /dev/null
@@ -1,18 +0,0 @@
-! RUN: %llvmgcc -S %s
-! PR2443
-
-! Program to test the power (**) operator
-program testpow
- implicit none
- real(kind=4) r, s, two
- real(kind=8) :: q
- complex(kind=4) :: c, z
- real, parameter :: del = 0.0001
- integer i, j
-
- two = 2.0
-
- c = (2.0, 3.0)
- c = c ** two
- if (abs(c - (-5.0, 12.0)) .gt. del) call abort
-end program
diff --git a/test/FrontendFortran/dg.exp b/test/FrontendFortran/dg.exp
deleted file mode 100644
index 45bffc6..0000000
--- a/test/FrontendFortran/dg.exp
+++ /dev/null
@@ -1,6 +0,0 @@
-load_lib llvm.exp
-
-if [ llvm_gcc_supports fortran ] then {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{f,f90}]]
-}
-
diff --git a/test/FrontendObjC++/2007-10-03-MetadataPointers.mm b/test/FrontendObjC++/2007-10-03-MetadataPointers.mm
deleted file mode 100644
index 2ab76c1..0000000
--- a/test/FrontendObjC++/2007-10-03-MetadataPointers.mm
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %llvmgcc -w -x objective-c++ -S %s -o /dev/null
-
-@class NSImage;
-void bork() {
- NSImage *nsimage;
- [nsimage release];
-}
diff --git a/test/FrontendObjC++/2010-08-02-NonPODObjectValue.mm b/test/FrontendObjC++/2010-08-02-NonPODObjectValue.mm
deleted file mode 100644
index da47ed0..0000000
--- a/test/FrontendObjC++/2010-08-02-NonPODObjectValue.mm
+++ /dev/null
@@ -1,27 +0,0 @@
-// RUN: not %llvmgcc %s -S -o - |& FileCheck %s
-// This tests for a specific diagnostic in LLVM-GCC.
-// Clang compiles this correctly with no diagnostic,
-// ergo this test will fail with a Clang-based front-end.
-class TFENodeVector {
-public:
- TFENodeVector(const TFENodeVector& inNodeVector);
- TFENodeVector();
-};
-
-@interface TWindowHistoryEntry {}
-@property (assign, nonatomic) TFENodeVector targetPath;
-@end
-
-@implementation TWindowHistoryEntry
-@synthesize targetPath;
-- (void) initWithWindowController {
- TWindowHistoryEntry* entry;
- TFENodeVector newPath;
- // CHECK: setting a C++ non-POD object value is not implemented
-#ifdef __clang__
-#error setting a C++ non-POD object value is not implemented
-#endif
- entry.targetPath = newPath;
- [entry setTargetPath:newPath];
-}
-@end
diff --git a/test/FrontendObjC++/2010-08-04-Template.mm b/test/FrontendObjC++/2010-08-04-Template.mm
deleted file mode 100644
index 2ebfd3e..0000000
--- a/test/FrontendObjC++/2010-08-04-Template.mm
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %llvmgcc %s -S
-struct TRunSoon {
- template <class P1> static void Post() {}
-};
-
-@implementation TPrivsTableViewMainController
-- (void) applyToEnclosed {
- TRunSoon::Post<int>();
-}
-@end
diff --git a/test/FrontendObjC++/2010-08-06-X.Y-syntax.mm b/test/FrontendObjC++/2010-08-06-X.Y-syntax.mm
deleted file mode 100644
index 986094c..0000000
--- a/test/FrontendObjC++/2010-08-06-X.Y-syntax.mm
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %llvmgcc %s -S
-struct TFENode {
- TFENode(const TFENode& inNode);
-};
-
-@interface TIconViewController
-- (const TFENode&) target;
-@end
-
-void sortAllChildrenForNode(const TFENode&node);
-
-@implementation TIconViewController
-- (void) setArrangeBy {
- sortAllChildrenForNode(self.target);
-}
-@end
diff --git a/test/FrontendObjC++/dg.exp b/test/FrontendObjC++/dg.exp
deleted file mode 100644
index 41c3db2..0000000
--- a/test/FrontendObjC++/dg.exp
+++ /dev/null
@@ -1,5 +0,0 @@
-load_lib llvm.exp
-
-if [ llvm_gcc_supports obj-c++ ] then {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{mm}]]
-}
diff --git a/test/FrontendObjC/2007-04-03-ObjcEH.m b/test/FrontendObjC/2007-04-03-ObjcEH.m
deleted file mode 100644
index ae744c7..0000000
--- a/test/FrontendObjC/2007-04-03-ObjcEH.m
+++ /dev/null
@@ -1,29 +0,0 @@
-// RUN: %llvmgcc -S %s -o /dev/null
-
-@interface B
--(int)bar;
-@end
-
-@interface A
--(void) Foo:(int) state;
-@end
-
-@implementation A
-- (void) Foo:(int) state {
-
- int wasResponded = 0;
- @try {
- if (state) {
- B * b = 0;
- @try { }
- @finally {
- wasResponded = ![b bar];
- }
- }
- }
- @finally {
- }
-}
-@end
-
-
diff --git a/test/FrontendObjC/2007-05-02-Strong.m b/test/FrontendObjC/2007-05-02-Strong.m
deleted file mode 100644
index 34b41ad..0000000
--- a/test/FrontendObjC/2007-05-02-Strong.m
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %llvmgcc -S %s -fobjc-gc -o /dev/null
-typedef int NSInteger;
-typedef struct _NSRect {
- int origin;
- int size;
-} NSRect;
-
-__attribute__((objc_gc(strong))) NSRect *_cachedRectArray;
-extern const NSRect NSZeroRect;
-@interface A{
-}
--(void)bar:(NSInteger *)rectCount;
-@end
-
-@implementation A
-
--(void)bar:(NSInteger *)rectCount {
- NSRect appendRect = NSZeroRect;
-
- _cachedRectArray[*rectCount - 1] = NSZeroRect;
-}
-
-@end
diff --git a/test/FrontendObjC/2007-09-25-EH.m b/test/FrontendObjC/2007-09-25-EH.m
deleted file mode 100644
index d625584..0000000
--- a/test/FrontendObjC/2007-09-25-EH.m
+++ /dev/null
@@ -1,27 +0,0 @@
-// RUN: %llvmgcc -S -w -m64 -mmacosx-version-min=10.5 %s -o /dev/null
-// XFAIL: *
-// XTARGET: darwin
-@class NSDictionary, DSoBuffer, DSoDirectory, NSMutableArray;
-@interface NSException {}
-@end
-@interface DSoNode {
- DSoDirectory *mDirectory;
-}
-@end
-@implementation DSoNode
-- (void) _findRecordsOfTypes {
- DSoBuffer *dbData;
- void *recInfo;
- NSMutableArray *results;
- @try {
- dsGetRecordEntry([dbData dsDataBuffer], (void**)&recInfo);
- @try {
- [results addObject:37];
- } @finally {
- dsDeallocRecordEntry([mDirectory dsDirRef], recInfo);
- }
- } @catch(NSException * exception) {
- }
-}
-
-
diff --git a/test/FrontendObjC/2007-10-17-SJLJExceptions.m b/test/FrontendObjC/2007-10-17-SJLJExceptions.m
deleted file mode 100644
index 970207e..0000000
--- a/test/FrontendObjC/2007-10-17-SJLJExceptions.m
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %llvmgcc -m32 -x objective-c %s -pipe -std=gnu99 -O2 -fexceptions -S -o - | not grep Unwind_Resume
-#import <stdio.h>
-
-@interface Foo {
- char c;
- short s;
- int i;
- long l;
- float f;
- double d;
-}
--(Foo*)retain;
-@end
-
-struct Foo *bork(Foo *FooArray) {
- struct Foo *result = 0;
- @try {
- result = [FooArray retain];
- } @catch(id any) {
- printf("hello world\n");
- }
-
- return result;
-}
diff --git a/test/FrontendObjC/2007-10-18-ProDescriptor.m b/test/FrontendObjC/2007-10-18-ProDescriptor.m
deleted file mode 100644
index 220fdd2..0000000
--- a/test/FrontendObjC/2007-10-18-ProDescriptor.m
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %llvmgcc -x objective-c -S %s -o /dev/null
-@protocol O
-@end
-@interface O < O > {
-}
-@end
-struct A {
-};
-@protocol AB
-- (unsigned) ver;
-@end
-@interface AGy:O < AB > {
-}
-@end
-@implementation AGy
-- (unsigned) ver {
-}
-@end
-
diff --git a/test/FrontendObjC/2007-10-23-GC-WriteBarrier.m b/test/FrontendObjC/2007-10-23-GC-WriteBarrier.m
deleted file mode 100644
index 4bbe440..0000000
--- a/test/FrontendObjC/2007-10-23-GC-WriteBarrier.m
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -x objective-c -S %s -o /dev/null -fobjc-gc
-// rdar://5541393
-
-typedef unsigned int NSUInteger;
-__attribute__((objc_gc(strong))) float *_scores;
-
-void foo(int i, float f) {
- _scores[i] = f;
-}
diff --git a/test/FrontendObjC/2008-10-3-EhValue.m b/test/FrontendObjC/2008-10-3-EhValue.m
deleted file mode 100644
index c7aabe2..0000000
--- a/test/FrontendObjC/2008-10-3-EhValue.m
+++ /dev/null
@@ -1,50 +0,0 @@
-// RUN: %llvmgcc -w -x objective-c -S %s -o /dev/null
-
-@interface Object {
-@public
- Class isa;
-}
-+initialize;
-+alloc;
-+new;
-+free;
--free;
-+(Class)class;
--(Class)class;
--init;
--superclass;
--(const char *)name;
-@end
-
-@interface Frob: Object
-@end
-
-@implementation Frob: Object
-@end
-
-static Frob* _connection = ((void *)0);
-
-extern void abort(void);
-
-void test (Object* sendPort)
-{
- int cleanupPorts = 1;
- Frob* receivePort = ((void *)0);
-
- @try {
- receivePort = (Frob *) -1;
- _connection = (Frob *) -1;
- receivePort = ((void *)0);
- sendPort = ((void *)0);
- cleanupPorts = 0;
- @throw [Object new];
- }
- @catch(Frob *obj) {
- if(!(0)) abort();
- }
- @catch(id exc) {
- if(!(!receivePort)) abort();
- if(!(!sendPort)) abort();
- if(!(!cleanupPorts)) abort();
- }
-}
diff --git a/test/FrontendObjC/2008-11-12-Metadata.m b/test/FrontendObjC/2008-11-12-Metadata.m
deleted file mode 100644
index be8ee41..0000000
--- a/test/FrontendObjC/2008-11-12-Metadata.m
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -x objective-c -m64 -S %s -o /dev/null
-
-@interface A
-@end
-@protocol P
-@end
-@interface B : A <P>
-{
-}
-@end
-@implementation B
-- (void)test {
-}
-@end
diff --git a/test/FrontendObjC/2008-11-24-ConstCFStrings.m b/test/FrontendObjC/2008-11-24-ConstCFStrings.m
deleted file mode 100644
index 976adc4..0000000
--- a/test/FrontendObjC/2008-11-24-ConstCFStrings.m
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -x objective-c -m64 -S %s -o - | grep {L_unnamed_cfstring_}
-
-@class NSString;
-
-@interface A
-- (void)bork:(NSString*)msg;
-@end
-
-void func(A *a) {
- [a bork:@"Hello world!"];
-}
diff --git a/test/FrontendObjC/2008-11-25-Blocks.m b/test/FrontendObjC/2008-11-25-Blocks.m
deleted file mode 100644
index c5cd3d2..0000000
--- a/test/FrontendObjC/2008-11-25-Blocks.m
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc -S %s -o /dev/null
-// rdar://6394879
-
-@interface bork
-- (id)B:(void (^)())blk;
-- (void)C;
-@end
-@implementation bork
-- (id)B:(void (^)())blk {
- __attribute__((__blocks__(byref))) bork* new = ((void *)0);
- blk();
-}
-- (void)C {
- __attribute__((__blocks__(byref))) id var;
- [self B:^() {}];
-}
-@end
diff --git a/test/FrontendObjC/2009-01-26-WriteBarrier-2.m b/test/FrontendObjC/2009-01-26-WriteBarrier-2.m
deleted file mode 100644
index 32833a8..0000000
--- a/test/FrontendObjC/2009-01-26-WriteBarrier-2.m
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -x objective-c -S %s -fobjc-gc -o - | grep objc_assign_strongCast
-// rdar://5541393
-
-typedef struct {
- void (^ivarBlock)(void);
-} StructWithBlock_t;
-
-int main(char *argc, char *argv[]) {
- StructWithBlock_t *swbp = (StructWithBlock_t *)malloc(sizeof(StructWithBlock_t*));
- __block int i = 10;
- // assigning a Block into an struct slot should elicit a write-barrier under GC
- swbp->ivarBlock = ^ { ++i; };
- return 0;
-}
diff --git a/test/FrontendObjC/2009-02-05-VolatileProp.m b/test/FrontendObjC/2009-02-05-VolatileProp.m
deleted file mode 100644
index 1deef73..0000000
--- a/test/FrontendObjC/2009-02-05-VolatileProp.m
+++ /dev/null
@@ -1,11 +0,0 @@
-/* RUN: %llvmgcc -w -x objective-c -S %s -o /dev/null -pedantic-errors
- rdar://6551276 */
-
-void foo(const unsigned short *);
-void bar() {
- unsigned short *s[3];
- int i;
- @try { } @catch (id anException) { }
- foo(2+s[i]);
-}
-
diff --git a/test/FrontendObjC/2009-04-14-AsmSection.m b/test/FrontendObjC/2009-04-14-AsmSection.m
deleted file mode 100644
index aefe088..0000000
--- a/test/FrontendObjC/2009-04-14-AsmSection.m
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc -S %s -fobjc-abi-version=2 -o %t
-// RUN: grep {OBJC_CLASS_\\\$_A.*section.*__DATA, __objc_data.*align} %t
-// XTARGET: darwin
-
-@interface A
-@end
-
-@implementation A
-@end
diff --git a/test/FrontendObjC/2009-04-27-bitfield-vs-ivar.m b/test/FrontendObjC/2009-04-27-bitfield-vs-ivar.m
deleted file mode 100644
index cada843..0000000
--- a/test/FrontendObjC/2009-04-27-bitfield-vs-ivar.m
+++ /dev/null
@@ -1,44 +0,0 @@
-// RUN: %llvmgcc -S -x objective-c -m64 -fobjc-abi-version=2 %s -o %t
-// RUN: grep {OBJC_CLASS_RO_\\\$_I4} %t | grep {i32 0, i32 1, i32 2, i32 0}
-// RUN: grep {OBJC_CLASS_RO_\\\$_I2} %t | grep {i32 0, i32 1, i32 1, i32 0}
-// RUN: grep {OBJC_CLASS_RO_\\\$_I5} %t | grep {i32 0, i32 0, i32 0, i32 0}
-// XTARGET: darwin
-
-// Test instance variable sizing when base class ends in bitfield
-@interface I3 {
- unsigned int _iv2 :1;
-}
-@end
-
-@interface I4 : I3 {
- char _iv4;
-}
-@end
-
-// Test case with no instance variables in derived class
-@interface I1 {
- unsigned int _iv2 :1;
-}
-@end
-
-@interface I2 : I1 {
-}
-@end
-
-// Test case with no instance variables anywhere
-@interface I6 {
-}
-@end
-
-@interface I5 : I6 {
-}
-@end
-
-@implementation I4
-@end
-
-@implementation I2
-@end
-
-@implementation I5
-@end
diff --git a/test/FrontendObjC/2009-04-28-bitfield-vs-vbc.m b/test/FrontendObjC/2009-04-28-bitfield-vs-vbc.m
deleted file mode 100644
index 8306fcc..0000000
--- a/test/FrontendObjC/2009-04-28-bitfield-vs-vbc.m
+++ /dev/null
@@ -1,127 +0,0 @@
-// RUN: %llvmgcc -S -x objective-c -m32 %s -o %t
-// This used to crash, 6831493.
-#include <stdlib.h>
-
-struct s0 {
- double x;
-};
-
-@interface I2 {
- struct s0 _iv1;
-}
-@end
-
-@interface I3 : I2 {
- unsigned int _iv2 :1;
- unsigned : 0;
- unsigned int _iv3 : 3;
-}
-@end
-
-@interface I4 : I3 {
- char _iv4;
-}
-@end
-
-@interface I5 : I4 {
- char _iv5;
- int _iv6;
- int _iv7;
-}
-
-@property int P1;
-@end
-
-@implementation I2
-@end
-
-@implementation I3
-@end
-
-@implementation I4
-@end
-
-@interface I5 ()
-@property int P2;
-@end
-
-#if 0
-int g2 = sizeof(I2);
-int g3 = sizeof(I3);
-int g4 = sizeof(I4);
-int g5_0 = sizeof(I5);
-#endif
-
-@implementation I5
-#ifdef __x86_64
-@synthesize P1 = _MadeUpName;
-@synthesize P2 = _AnotherMadeUpName;
-#else
-@synthesize P1 = _iv6;
-@synthesize P2 = _iv7;
-#endif
-@end
-
-#if 0
-int g5_1 = sizeof(I5);
-#endif
-
-@interface T0_I0 {
- double iv_A_0;
- char iv_A_1;
-}
-@end
-
-@interface T0_I1 : T0_I0 {
- char iv_B_0;
-}
-@end
-
-@interface T0_I2 : T0_I1 {
- char iv_C_0;
-}
-@end
-
-#if 0
-int g6 = sizeof(T0_I0);
-int g7 = sizeof(T0_I1);
-int g8 = sizeof(T0_I2);
-#endif
-
-@implementation T0_I0 @end
-@implementation T0_I1 @end
-@implementation T0_I2 @end
-
-void f0(I2*i2,I3*i3,I4*i4,I5*i5,T0_I0*t0_i0,T0_I1*t0_i1,T0_I2*t0_i2) {
-}
-
-// Thomas Wang's ui32 hash.
-unsigned hash_ui32_to_ui32(unsigned a) {
- a = (a ^ 61) ^ (a >> 16);
- a = a + (a << 3);
- a = a ^ (a >> 4);
- a = a * 0x27d4eb2d;
- a = a ^ (a >> 15);
- return a;
-}
-
-unsigned char hash_ui32_to_ui8(unsigned ui) {
- ui = hash_ui32_to_ui32(ui);
- ui ^= ui>>8;
- ui ^= ui>>8;
- ui ^= ui>>8;
- return (unsigned char) ui;
-}
-
-void *init() {
- unsigned i, N = 1024;
- unsigned char *p = malloc(N);
- for (i=0; i != N; ++i)
- p[i] = hash_ui32_to_ui8(i);
- return p;
-}
-
-int main(){
- void *p = init();
- f0(p,p,p,p,p,p,p);
-}
diff --git a/test/FrontendObjC/2009-08-05-utf16.m b/test/FrontendObjC/2009-08-05-utf16.m
deleted file mode 100644
index df3745c..0000000
--- a/test/FrontendObjC/2009-08-05-utf16.m
+++ /dev/null
@@ -1,5 +0,0 @@
-/* RUN: %llvmgcc -w -x objective-c -S %s -o - | grep {__utf16_string_1} | grep {internal unnamed_addr constant} | grep {12 x i8}
- rdar://7095855 rdar://7115749 */
-
-void *P = @"iPodâ„¢";
-
diff --git a/test/FrontendObjC/2009-08-17-DebugInfo.m b/test/FrontendObjC/2009-08-17-DebugInfo.m
deleted file mode 100644
index 825bbd7..0000000
--- a/test/FrontendObjC/2009-08-17-DebugInfo.m
+++ /dev/null
@@ -1,28 +0,0 @@
-// This is a regression test on debug info to make sure that we can set a
-// breakpoint on a objective message.
-// RUN: %llvmgcc -S -O0 -g %s -o - | llc -disable-cfi -o %t.s -O0
-// RUN: %compile_c %t.s -o %t.o
-// RUN: %link %t.o -o %t.exe -framework Foundation
-// RUN: echo {break randomFunc\n} > %t.in
-// RUN: gdb -q -batch -n -x %t.in %t.exe | tee %t.out | \
-// RUN: grep {Breakpoint 1 at 0x.*: file .*2009-08-17-DebugInfo.m, line 21}
-// XTARGET: darwin
-@interface MyClass
-{
- int my;
-}
-+ init;
-- randomFunc;
-@end
-
-@implementation MyClass
-+ init {
-}
-- randomFunc { my = 42; }
-@end
-
-int main() {
- id o = [MyClass init];
- [o randomFunc];
- return 0;
-}
diff --git a/test/FrontendObjC/2009-11-30-Objc-ID.m b/test/FrontendObjC/2009-11-30-Objc-ID.m
deleted file mode 100644
index 787bf72..0000000
--- a/test/FrontendObjC/2009-11-30-Objc-ID.m
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %llvmgcc -S -O0 -g %s -o - | \
-// RUN: llc --disable-fp-elim -o %t.s -O0
-// RUN: grep id %t.s | grep DW_AT_name
-@interface A
--(id) blah;
-@end
-
-@implementation A
--(id)blah {
- int i = 1;
- i++;
- return i;
-}
-@end
diff --git a/test/FrontendObjC/2010-02-01-utf16-with-null.m b/test/FrontendObjC/2010-02-01-utf16-with-null.m
deleted file mode 100644
index 86e4637..0000000
--- a/test/FrontendObjC/2010-02-01-utf16-with-null.m
+++ /dev/null
@@ -1,5 +0,0 @@
-/* RUN: %llvmgcc -w -x objective-c -S %s -o - | not grep {__ustring}
- rdar://7589850 */
-
-void *P = @"good\0bye";
-
diff --git a/test/FrontendObjC/2010-02-11-fwritable-stringsBug.m b/test/FrontendObjC/2010-02-11-fwritable-stringsBug.m
deleted file mode 100644
index bb00f6a..0000000
--- a/test/FrontendObjC/2010-02-11-fwritable-stringsBug.m
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %llvmgcc -x objective-c -fwritable-strings -S %s -o - | FileCheck %s
-// CHECK: @.str = private unnamed_addr constant
-// CHECK: @.str1 = internal unnamed_addr global
-
-// rdar://7634471
-
-@class NSString;
-
-@interface A
-- (void)foo:(NSString*)msg;
-- (void)bar:(const char*)msg;
-@end
-
-void func(A *a) {
- [a foo:@"Hello world!"];
- [a bar:"Goodbye world!"];
-}
diff --git a/test/FrontendObjC/2010-02-23-DbgInheritance.m b/test/FrontendObjC/2010-02-23-DbgInheritance.m
deleted file mode 100644
index 7e1cf67..0000000
--- a/test/FrontendObjC/2010-02-23-DbgInheritance.m
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %llvmgcc %s -S -g -o - | grep -v DW_TAG_member
-// Interface P should not be a member of interface I in debug info.
-@interface P
-@end
-
-@interface I : P
-@end
-
-void fn(I *iptr) {}
diff --git a/test/FrontendObjC/2010-03-17-StructRef.m b/test/FrontendObjC/2010-03-17-StructRef.m
deleted file mode 100644
index 3594684..0000000
--- a/test/FrontendObjC/2010-03-17-StructRef.m
+++ /dev/null
@@ -1,43 +0,0 @@
-// RUN: %llvmgcc %s -m64 -S -o - | FileCheck %s
-// Bitfield references must not touch memory outside of the enclosing
-// struct. Radar 7639995
-typedef signed char BOOL;
-@protocol NSObject
-- (id)init;
-@end
-@interface NSObject <NSObject> {}
-@end
-@interface IMAVChatParticipant : NSObject {
- int _ardRole;
- int _state;
- int _avRelayStatus;
- int _chatEndedReason;
- int _chatError;
- unsigned _sendingAudio:1;
- unsigned _sendingVideo:1;
- unsigned _sendingAuxVideo:1;
- unsigned _audioMuted:1;
- unsigned _videoPaused:1;
- unsigned _networkStalled:1;
- unsigned _isInitiator:1;
- unsigned _isAOLInterop:1;
- unsigned _isRecording:1;
- unsigned _isUsingICE:1;
-}
-@end
-@implementation IMAVChatParticipant
-- (id) init {
- self = [super init];
- if ( self ) {
- BOOL blah = (BOOL)1;
- // We're expecting these three bitfield assignments will generate i8 stores.
- _sendingAudio = (BOOL)1;
- _isUsingICE = (BOOL)1;
- _isUsingICE = blah;
- // CHECK: store i8
- // CHECK: store i8
- // CHECK: store i8
- }
- return self;
-}
-@end
diff --git a/test/FrontendObjC/2010-06-04-UnnamedCFString-dbg.m b/test/FrontendObjC/2010-06-04-UnnamedCFString-dbg.m
deleted file mode 100644
index bded9ea..0000000
--- a/test/FrontendObjC/2010-06-04-UnnamedCFString-dbg.m
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %llvmgcc -S -O0 -g %s -o - | grep DW_TAG_variable | count 1
-
-// Do not emit debug info for unnamed builtin CFString variable.
-@interface Foo
-@end
-Foo *FooName = @"FooBar";
diff --git a/test/FrontendObjC/2011-03-02-ConstCFStringLiteralAlign.m b/test/FrontendObjC/2011-03-02-ConstCFStringLiteralAlign.m
deleted file mode 100644
index a5bd2b7..0000000
--- a/test/FrontendObjC/2011-03-02-ConstCFStringLiteralAlign.m
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %llvmgcc -S -w -m64 -mmacosx-version-min=10.5 %s -o - | \
-// RUN: llc --disable-fp-elim -o - | FileCheck %s
-// XFAIL: *
-// XTARGET: darwin
-
-@interface Foo
-@end
-Foo *FooName = @"FooBar";
-
-// CHECK: .section __TEXT,__cstring,cstring_literals
-// CHECK-NEXT: L_.str:
diff --git a/test/FrontendObjC/2011-03-08-IVarLookup.m b/test/FrontendObjC/2011-03-08-IVarLookup.m
deleted file mode 100644
index 939f2a7..0000000
--- a/test/FrontendObjC/2011-03-08-IVarLookup.m
+++ /dev/null
@@ -1,32 +0,0 @@
-// RUN: %llvmgcc -x objective-c -S -fobjc-abi-version=2 %s -o /dev/null
-// XFAIL: *
-// XTARGET: darwin
-
-typedef unsigned int UInt_t;
-
-@interface A
-{
-@protected
- UInt_t _f1;
-}
-@end
-
-@interface B : A { }
-@end
-
-@interface A ()
-@property (assign) UInt_t f1;
-@end
-
-@interface B ()
-@property (assign) int x;
-@end
-
-@implementation B
-@synthesize x;
-- (id) init
-{
- _f1 = 0;
- return self;
-}
-@end
diff --git a/test/FrontendObjC/dg.exp b/test/FrontendObjC/dg.exp
deleted file mode 100644
index 18f73a7..0000000
--- a/test/FrontendObjC/dg.exp
+++ /dev/null
@@ -1,5 +0,0 @@
-load_lib llvm.exp
-
-if [ llvm_gcc_supports objc ] then {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{m}]]
-}
diff --git a/test/LLVMC/Alias.td b/test/LLVMC/Alias.td
deleted file mode 100644
index 5d37889..0000000
--- a/test/LLVMC/Alias.td
+++ /dev/null
@@ -1,24 +0,0 @@
-// Test alias generation.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def OptList : OptionList<[
-
-(switch_option "dummy1", (help "none")),
-// CHECK: cl::alias Alias_dummy2
-(alias_option "dummy2", "dummy1")
-]>;
-
-def dummy_tool : Tool<[
-(command "dummy_cmd"),
-(in_language "dummy_lang"),
-(out_language "dummy_lang"),
-(actions (case
- (switch_on "dummy1"), (forward "dummy1")))
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/AppendCmdHook.td b/test/LLVMC/AppendCmdHook.td
deleted file mode 100644
index c85f002..0000000
--- a/test/LLVMC/AppendCmdHook.td
+++ /dev/null
@@ -1,29 +0,0 @@
-// Check that hooks can be invoked from 'append_cmd'.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-// CHECK: std::string MyHook()
-
-def OptList : OptionList<[
-(switch_option "dummy1", (help "none")),
-(switch_option "dummy2", (help "none"))
-]>;
-
-def dummy_tool : Tool<[
-(command "dummy_cmd"),
-(in_language "dummy_lang"),
-(out_language "dummy_lang"),
-(actions (case
- // CHECK: , "-arg1"));
- // CHECK: , "-arg2"));
- (switch_on "dummy1"), (append_cmd "-arg1 -arg2"),
- // CHECK: , "-arg3"));
- // CHECK: hooks::MyHook()
- (switch_on "dummy2"), (append_cmd "-arg3 $CALL(MyHook)")))
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/C++/dash-x.cpp b/test/LLVMC/C++/dash-x.cpp
deleted file mode 100644
index 7d4cf19..0000000
--- a/test/LLVMC/C++/dash-x.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-// Test that we can compile .c files as C++ and vice versa
-// RUN: llvmc %s -x c++ %p/../test_data/false.c -x c %p/../test_data/false.cpp -x lisp -x whatnot -x none %p/../test_data/false2.cpp -o %t
-// RUN: %abs_tmp | grep hello
-// XFAIL: vg
-
-extern int test_main();
-
-int main() {
- test_main();
-}
diff --git a/test/LLVMC/C++/dg.exp b/test/LLVMC/C++/dg.exp
deleted file mode 100644
index 2093455..0000000
--- a/test/LLVMC/C++/dg.exp
+++ /dev/null
@@ -1,5 +0,0 @@
-load_lib llvm.exp
-
-if [ llvm_gcc_supports c++ ] then {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{unk,ll,c,cpp}]]
-}
diff --git a/test/LLVMC/C++/filelist.cpp b/test/LLVMC/C++/filelist.cpp
deleted file mode 100644
index 6f5f6f7..0000000
--- a/test/LLVMC/C++/filelist.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-// Test that the -filelist option works correctly with -linker=c++.
-// RUN: llvmc --dry-run -filelist DUMMY -linker c++ |& grep llvm-g++
-// XFAIL: vg
diff --git a/test/LLVMC/C++/hello.cpp b/test/LLVMC/C++/hello.cpp
deleted file mode 100644
index 8f38306..0000000
--- a/test/LLVMC/C++/hello.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-// Test that we can compile C++ code.
-// RUN: llvmc %s -o %t
-// RUN: %abs_tmp | grep hello
-// XFAIL: vg
-#include <iostream>
-
-int main() {
- std::cout << "hello" << '\n';
-}
diff --git a/test/LLVMC/C++/just-compile.cpp b/test/LLVMC/C++/just-compile.cpp
deleted file mode 100644
index 771c982..0000000
--- a/test/LLVMC/C++/just-compile.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-// Test that the -c flag works.
-// RUN: llvmc -c %s -o %t.o
-// RUN: llvmc --linker=c++ %t.o -o %t
-// RUN: %abs_tmp | grep hello
-// XFAIL: vg
-#include <iostream>
-
-int main() {
- std::cout << "hello" << '\n';
-}
diff --git a/test/LLVMC/C++/together.cpp b/test/LLVMC/C++/together.cpp
deleted file mode 100644
index 925215a4..0000000
--- a/test/LLVMC/C++/together.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-// Check that we can compile files of different types together.
-// RUN: llvmc %s %p/../test_data/together.c -o %t
-// RUN: %abs_tmp | grep hello
-// XFAIL: vg
-
-extern "C" void test();
-
-int main() {
- test();
-}
diff --git a/test/LLVMC/C++/unknown_suffix.unk b/test/LLVMC/C++/unknown_suffix.unk
deleted file mode 100644
index bf4aea2..0000000
--- a/test/LLVMC/C++/unknown_suffix.unk
+++ /dev/null
@@ -1,9 +0,0 @@
-// Test that the -x option works for files with unknown suffixes.
-// RUN: llvmc -x c++ %s -o %t
-// RUN: %abs_tmp | grep hello
-// XFAIL: vg
-#include <iostream>
-
-int main() {
- std::cout << "hello" << '\n';
-}
diff --git a/test/LLVMC/C/dg.exp b/test/LLVMC/C/dg.exp
deleted file mode 100644
index a9be28a..0000000
--- a/test/LLVMC/C/dg.exp
+++ /dev/null
@@ -1,5 +0,0 @@
-load_lib llvm.exp
-
-if [ llvm_gcc_supports c ] then {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
-}
diff --git a/test/LLVMC/C/emit-llvm-opt.c b/test/LLVMC/C/emit-llvm-opt.c
deleted file mode 100644
index 50710cf..0000000
--- a/test/LLVMC/C/emit-llvm-opt.c
+++ /dev/null
@@ -1,9 +0,0 @@
-// Check that -emit-llvm [-S] works with -opt.
-
-// RUN: llvmc -c -opt -emit-llvm -o - %s | llvm-dis | grep "@f0()" | count 1
-// RUN: llvmc -c -opt -emit-llvm -S -o - %s | grep "@f0()" | count 1
-// RUN: llvmc --dry-run -c -opt -emit-llvm %s |& grep "^opt"
-// XFAIL: vg_leak
-
-int f0(void) {
-}
diff --git a/test/LLVMC/C/emit-llvm.c b/test/LLVMC/C/emit-llvm.c
deleted file mode 100644
index 56a1e30..0000000
--- a/test/LLVMC/C/emit-llvm.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// Check that -emit-llvm [-S] works correctly.
-
-// RUN: llvmc -c -emit-llvm -o - %s | llvm-dis | grep "@f0()" | count 1
-// RUN: llvmc -c -emit-llvm -S -o - %s | grep "@f0()" | count 1
-// XFAIL: vg_leak
-
-int f0(void) {
-}
diff --git a/test/LLVMC/C/hello.c b/test/LLVMC/C/hello.c
deleted file mode 100644
index 29ad39f..0000000
--- a/test/LLVMC/C/hello.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Check that we can compile helloworld
- * RUN: llvmc %s -o %t
- * RUN: %abs_tmp | grep hello
- * XFAIL: vg_leak
- */
-
-#include <stdio.h>
-
-int main() {
- printf("hello\n");
- return 0;
-}
diff --git a/test/LLVMC/C/include.c b/test/LLVMC/C/include.c
deleted file mode 100644
index 9c9530b..0000000
--- a/test/LLVMC/C/include.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Check that the 'include' options work.
- * RUN: echo "int x;\n" > %t1.inc
- * RUN: llvmc -include %t1.inc -fsyntax-only %s
- * XFAIL: vg_leak
- */
-
-int f0(void) {
- return x;
-}
diff --git a/test/LLVMC/C/opt-test.c b/test/LLVMC/C/opt-test.c
deleted file mode 100644
index 7924def..0000000
--- a/test/LLVMC/C/opt-test.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Check that the -opt switch works.
- * RUN: llvmc %s -opt -o %t
- * RUN: %abs_tmp | grep hello
- * XFAIL: vg_leak
- */
-
-#include <stdio.h>
-
-int main() {
- printf("hello\n");
- return 0;
-}
diff --git a/test/LLVMC/C/sink.c b/test/LLVMC/C/sink.c
deleted file mode 100644
index c4f9beb..0000000
--- a/test/LLVMC/C/sink.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Check that the 'sink' options work.
- * RUN: llvmc -v -Wall %s -o %t |& grep "Wall"
- * RUN: %abs_tmp | grep hello
- * XFAIL: vg_leak
- */
-
-#include <stdio.h>
-
-int main() {
- printf("hello\n");
- return 0;
-}
diff --git a/test/LLVMC/C/wall.c b/test/LLVMC/C/wall.c
deleted file mode 100644
index 36813ba..0000000
--- a/test/LLVMC/C/wall.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Check that -Wall works as intended
- * RUN: llvmc -Wall %s -o %t
- * RUN: %abs_tmp | grep hello
- * XFAIL: vg_leak
- */
-
-#include <stdio.h>
-
-int main() {
- printf("hello\n");
- return 0;
-}
diff --git a/test/LLVMC/EmptyCompilationGraph.td b/test/LLVMC/EmptyCompilationGraph.td
deleted file mode 100644
index a52b8a8..0000000
--- a/test/LLVMC/EmptyCompilationGraph.td
+++ /dev/null
@@ -1,8 +0,0 @@
-// Check that the compilation graph can be empty.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def Graph : CompilationGraph<[]>;
diff --git a/test/LLVMC/EnvParentheses.td b/test/LLVMC/EnvParentheses.td
deleted file mode 100644
index ce0cb82..0000000
--- a/test/LLVMC/EnvParentheses.td
+++ /dev/null
@@ -1,18 +0,0 @@
-// Check the fix for PR4157.
-// http://llvm.org/bugs/show_bug.cgi?id=4157
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: not grep {FOO")));} %t
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def dummy_tool : Tool<[
-(command "gcc $ENV(FOO)/bar"),
-(in_language "dummy"),
-(out_language "dummy")
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
-
-def Graph : CompilationGraph<[]>;
diff --git a/test/LLVMC/ForwardAs.td b/test/LLVMC/ForwardAs.td
deleted file mode 100644
index 99b240e..0000000
--- a/test/LLVMC/ForwardAs.td
+++ /dev/null
@@ -1,21 +0,0 @@
-// Check the fix for PR4159.
-// http://llvm.org/bugs/show_bug.cgi?id=4159
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def OptList : OptionList<[(parameter_option "dummy", (help "dummmy"))]>;
-
-def dummy_tool : Tool<[
-(command "dummy_cmd"),
-(in_language "dummy"),
-(out_language "dummy"),
-(actions (case
- // CHECK: "unique_name"));
- (not_empty "dummy"), (forward_as "dummy", "unique_name")))
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/ForwardTransformedValue.td b/test/LLVMC/ForwardTransformedValue.td
deleted file mode 100644
index 9184ede..0000000
--- a/test/LLVMC/ForwardTransformedValue.td
+++ /dev/null
@@ -1,27 +0,0 @@
-// Check that forward_transformed_value works.
-// The dummy tool and graph are required to silence warnings.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def OptList : OptionList<[(parameter_option "a", (help "dummy")),
- (prefix_list_option "b", (help "dummy"))]>;
-
-// CHECK: std::string HookA
-// CHECK: std::string HookB
-
-def dummy_tool : Tool<[
-(command "dummy_cmd"),
-(in_language "dummy"),
-(out_language "dummy"),
-(actions (case
- // CHECK: HookA(autogenerated::Parameter_a
- (not_empty "a"), (forward_transformed_value "a", "HookA"),
- // CHECK: HookB(autogenerated::List_b
- (not_empty "b"), (forward_transformed_value "b", "HookB")))
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/ForwardValue.td b/test/LLVMC/ForwardValue.td
deleted file mode 100644
index a42a3f0..0000000
--- a/test/LLVMC/ForwardValue.td
+++ /dev/null
@@ -1,24 +0,0 @@
-// Check that forward_value works.
-// The dummy tool and graph are required to silence warnings.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def OptList : OptionList<[(parameter_option "a", (help "dummy")),
- (prefix_list_option "b", (help "dummy"))]>;
-
-def dummy_tool : Tool<[
-(command "dummy_cmd"),
-(in_language "dummy"),
-(out_language "dummy"),
-(actions (case
- // CHECK: , autogenerated::Parameter_a));
- (not_empty "a"), (forward_value "a"),
- // CHECK: B = autogenerated::List_b.begin()
- (not_empty "b"), (forward_value "b")))
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/HookWithArguments.td b/test/LLVMC/HookWithArguments.td
deleted file mode 100644
index bbba2e9..0000000
--- a/test/LLVMC/HookWithArguments.td
+++ /dev/null
@@ -1,20 +0,0 @@
-// Check that hooks with arguments work.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-// CHECK: Hook(const char* Arg0, const char* Arg1, const char* Arg2);
-// CHECK: "/path"
-// CHECK: std::getenv("VARIABLE")
-// CHECK: "/2path"
-
-def dummy_tool : Tool<[
-(command "$CALL(Hook, 'Arg1', 'Arg2', 'Arg3 Arg3Cont')/path arg1 $ENV(VARIABLE)/2path arg2"),
-(in_language "dummy"),
-(out_language "dummy")
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/HookWithInFile.td b/test/LLVMC/HookWithInFile.td
deleted file mode 100644
index ed08b53..0000000
--- a/test/LLVMC/HookWithInFile.td
+++ /dev/null
@@ -1,16 +0,0 @@
-// Check that a hook can be given $INFILE as an argument.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def dummy_tool : Tool<[
-// CHECK: Hook(inFile.c_str())
-(command "$CALL(Hook, '$INFILE')/path"),
-(in_language "dummy"),
-(out_language "dummy")
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/Init.td b/test/LLVMC/Init.td
deleted file mode 100644
index c384679..0000000
--- a/test/LLVMC/Init.td
+++ /dev/null
@@ -1,25 +0,0 @@
-// Check that (init true/false) and (init "str") work.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def OptList : OptionList<[
-// CHECK: cl::init(true)
-(switch_option "dummy1", (help "none"), (init true)),
-// CHECK: cl::init("some-string")
-(parameter_option "dummy2", (help "none"), (init "some-string"))
-]>;
-
-def dummy_tool : Tool<[
-(command "dummy_cmd"),
-(in_language "dummy_lang"),
-(out_language "dummy_lang"),
-(actions (case
- (switch_on "dummy1"), (forward "dummy1"),
- (not_empty "dummy2"), (forward "dummy2")))
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/LanguageMap.td b/test/LLVMC/LanguageMap.td
deleted file mode 100644
index a050214..0000000
--- a/test/LLVMC/LanguageMap.td
+++ /dev/null
@@ -1,29 +0,0 @@
-// Check that LanguageMap is processed properly.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def OptList : OptionList<[
-(switch_option "dummy1", (help "none"))
-]>;
-
-def dummy_tool : Tool<[
-(command "dummy_cmd"),
-(in_language "dummy_lang"),
-(out_language "dummy_lang"),
-(actions (case
- (switch_on "dummy1"), (forward "dummy1")))
-]>;
-
-def lang_map : LanguageMap<[
- // CHECK: langMap["dummy"] = "dummy_lang"
- // CHECK: langMap["DUM"] = "dummy_lang"
- (lang_to_suffixes "dummy_lang", ["dummy", "DUM"]),
- // CHECK: langMap["DUM2"] = "dummy_lang_2"
- (lang_to_suffixes "dummy_lang_2", "DUM2")
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/MultiValuedOption.td b/test/LLVMC/MultiValuedOption.td
deleted file mode 100644
index 08c7533..0000000
--- a/test/LLVMC/MultiValuedOption.td
+++ /dev/null
@@ -1,24 +0,0 @@
-// Check that multivalued options work.
-// The dummy tool and graph are required to silence warnings.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def OptList : OptionList<[
- // CHECK: cl::multi_val(2)
- (prefix_list_option "foo", (multi_val 2)),
- (parameter_list_option "baz", (multi_val 2))]>;
-
-def dummy_tool : Tool<[
-(command "dummy_cmd"),
-(in_language "dummy"),
-(out_language "dummy"),
-(actions (case
- (not_empty "foo"), (forward_as "foo", "bar"),
- (not_empty "baz"), (forward "baz")))
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/MultipleCompilationGraphs.td b/test/LLVMC/MultipleCompilationGraphs.td
deleted file mode 100644
index b3746c0..0000000
--- a/test/LLVMC/MultipleCompilationGraphs.td
+++ /dev/null
@@ -1,10 +0,0 @@
-// Check that multiple compilation graphs are allowed.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def Graph1 : CompilationGraph<[]>;
-def Graph2 : CompilationGraph<[]>;
-def Graph3 : CompilationGraph<[]>;
diff --git a/test/LLVMC/MultipleOutputLanguages.td b/test/LLVMC/MultipleOutputLanguages.td
deleted file mode 100644
index ae0c92e..0000000
--- a/test/LLVMC/MultipleOutputLanguages.td
+++ /dev/null
@@ -1,27 +0,0 @@
-// Check that multiple output languages work.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def dummy_tool : Tool<[
- (command "dummy_cmd"),
- (in_language "dummy_lang"),
- (out_language "another_dummy_lang", "yet_another_dummy_lang")
-]>;
-
-def another_dummy_tool : Tool<[
- (command "another_dummy_cmd"),
- (in_language "another_dummy_lang", "some_other_dummy_lang"),
- (out_language "executable"),
- (join)
-]>;
-
-// CHECK: new SimpleEdge("dummy_tool")
-// CHECK: new SimpleEdge("another_dummy_tool")
-def DummyGraph : CompilationGraph<[
- (edge "root", "dummy_tool"),
- (edge "dummy_tool", "another_dummy_tool")
-]>;
diff --git a/test/LLVMC/NoActions.td b/test/LLVMC/NoActions.td
deleted file mode 100644
index 34b4440..0000000
--- a/test/LLVMC/NoActions.td
+++ /dev/null
@@ -1,16 +0,0 @@
-// Check that tools without associated actions are accepted.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-// CHECK: class dummy_tool : public Tool {
-def dummy_tool : Tool<[
-(command "dummy_cmd"),
-(in_language "dummy"),
-(out_language "dummy")
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/NoCompilationGraph.td b/test/LLVMC/NoCompilationGraph.td
deleted file mode 100644
index 4182882..0000000
--- a/test/LLVMC/NoCompilationGraph.td
+++ /dev/null
@@ -1,6 +0,0 @@
-// Check that the compilation graph is not required.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
diff --git a/test/LLVMC/ObjC++/dg.exp b/test/LLVMC/ObjC++/dg.exp
deleted file mode 100644
index 41c3db2..0000000
--- a/test/LLVMC/ObjC++/dg.exp
+++ /dev/null
@@ -1,5 +0,0 @@
-load_lib llvm.exp
-
-if [ llvm_gcc_supports obj-c++ ] then {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{mm}]]
-}
diff --git a/test/LLVMC/ObjC++/hello.mm b/test/LLVMC/ObjC++/hello.mm
deleted file mode 100644
index 2125dc7..0000000
--- a/test/LLVMC/ObjC++/hello.mm
+++ /dev/null
@@ -1,8 +0,0 @@
-// Test that we can compile Objective-C++ code.
-// RUN: llvmc %s -o %t
-// RUN: %abs_tmp | grep hello
-#include <iostream>
-
-int main() {
- std::cout << "hello" << '\n';
-}
diff --git a/test/LLVMC/ObjC/dg.exp b/test/LLVMC/ObjC/dg.exp
deleted file mode 100644
index 18f73a7..0000000
--- a/test/LLVMC/ObjC/dg.exp
+++ /dev/null
@@ -1,5 +0,0 @@
-load_lib llvm.exp
-
-if [ llvm_gcc_supports objc ] then {
- RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{m}]]
-}
diff --git a/test/LLVMC/ObjC/hello.m b/test/LLVMC/ObjC/hello.m
deleted file mode 100644
index b2d903f..0000000
--- a/test/LLVMC/ObjC/hello.m
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Check that we can compile helloworld
- * RUN: llvmc %s -o %t
- * RUN: %abs_tmp | grep hello
- */
-
-#include <stdio.h>
-
-int main() {
- printf("hello\n");
- return 0;
-}
diff --git a/test/LLVMC/OneOrMore.td b/test/LLVMC/OneOrMore.td
deleted file mode 100644
index 54fa62d..0000000
--- a/test/LLVMC/OneOrMore.td
+++ /dev/null
@@ -1,25 +0,0 @@
-// Check that (one_or_more) and (zero_or_one) properties work.
-// The dummy tool and graph are required to silence warnings.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def OptList : OptionList<[
- // CHECK: cl::OneOrMore
- (prefix_list_option "foo", (one_or_more)),
- // CHECK: cl::Optional
- (parameter_list_option "baz", (optional))]>;
-
-def dummy_tool : Tool<[
-(command "dummy_cmd"),
-(in_language "dummy"),
-(out_language "dummy"),
-(actions (case
- (not_empty "foo"), (forward_as "foo", "bar"),
- (not_empty "baz"), (forward "baz")))
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/OptionPreprocessor.td b/test/LLVMC/OptionPreprocessor.td
deleted file mode 100644
index 5fdc35a..0000000
--- a/test/LLVMC/OptionPreprocessor.td
+++ /dev/null
@@ -1,67 +0,0 @@
-// Test for the OptionPreprocessor and related functionality.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def OptList : OptionList<[
-(switch_option "foo", (help "dummy")),
-(switch_option "bar", (help "dummy")),
-(switch_option "baz", (help "dummy")),
-(parameter_option "foo_p", (help "dummy")),
-(parameter_option "bar_p", (help "dummy")),
-(parameter_option "baz_p", (help "dummy")),
-(parameter_list_option "foo_l", (help "dummy"))
-]>;
-
-def Preprocess : OptionPreprocessor<
-(case
- // CHECK: W1
- // CHECK: foo = false;
- // CHECK: foo_p = "";
- // CHECK: foo_l.clear();
- (and (switch_on "foo"), (any_switch_on "bar", "baz")),
- [(warning "W1"), (unset_option "foo"),
- (unset_option "foo_p"), (unset_option "foo_l")],
- // CHECK: W2
- // CHECK: foo = true;
- // CHECK: bar = true;
- // CHECK: baz = false;
- // CHECK: foo_p = "asdf";
- // CHECK: foo_l.clear();
- // CHECK: foo_l.push_back("qwert");
- // CHECK: foo_l.push_back("yuiop");
- // CHECK: foo_l.push_back("asdf");
- (and (switch_on "foo", "bar"), (any_empty "foo_p", "bar_p")),
- [(warning "W2"), (set_option "foo"),
- (set_option "bar", true),
- (set_option "baz", false),
- (set_option "foo_p", "asdf"),
- (set_option "foo_l", ["qwert", "yuiop", "asdf"])],
- // CHECK: W3
- // CHECK: foo = true;
- // CHECK: bar = true;
- // CHECK: baz = true;
- (and (empty "foo_p", "bar_p"), (any_not_empty "baz_p")),
- [(warning "W3"), (set_option "foo", "bar", "baz")])
->;
-
-// Shut up warnings...
-def dummy : Tool<
-[(in_language "dummy"),
- (out_language "dummy"),
- (output_suffix "d"),
- (command "dummy"),
- (actions (case (switch_on "foo"), (error),
- (switch_on "bar"), (error),
- (switch_on "baz"), (error),
- (not_empty "foo_p"), (error),
- (not_empty "bar_p"), (error),
- (not_empty "baz_p"), (error),
- (not_empty "foo_l"), (error)))
-]>;
-
-def Graph : CompilationGraph<[(edge "root", "dummy")]>;
-
diff --git a/test/LLVMC/OutputSuffixHook.td b/test/LLVMC/OutputSuffixHook.td
deleted file mode 100644
index 1f5ecd1..0000000
--- a/test/LLVMC/OutputSuffixHook.td
+++ /dev/null
@@ -1,24 +0,0 @@
-// Check that hooks can be invoked from 'output_suffix'.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t
-// RUN: FileCheck -input-file %t %s
-// RUN: %compile_cxx %t
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-// CHECK: std::string MyHook()
-
-def OptList : OptionList<[
-(switch_option "dummy1", (help "none"))
-]>;
-
-def dummy_tool : Tool<[
-(command "dummy_cmd"),
-(in_language "dummy_lang"),
-(out_language "dummy_lang"),
-(actions (case
- // CHECK: hooks::MyHook()
- (switch_on "dummy1"), (output_suffix "$CALL(MyHook)")))
-]>;
-
-def DummyGraph : CompilationGraph<[(edge "root", "dummy_tool")]>;
diff --git a/test/LLVMC/TestWarnings.td b/test/LLVMC/TestWarnings.td
deleted file mode 100644
index b0f57e9..0000000
--- a/test/LLVMC/TestWarnings.td
+++ /dev/null
@@ -1,8 +0,0 @@
-// Check that warnings about unused options are really emitted.
-// This should fail because the output is printed on stderr.
-// RUN: tblgen -I %p/../../include --gen-llvmc %s |& grep "option '-Wall' has no effect!"
-// XFAIL: vg_leak
-
-include "llvm/CompilerDriver/Common.td"
-
-def OptList : OptionList<[(switch_option "Wall", (help "dummy"))]>;
diff --git a/test/LLVMC/dg.exp b/test/LLVMC/dg.exp
deleted file mode 100644
index f7d275a..0000000
--- a/test/LLVMC/dg.exp
+++ /dev/null
@@ -1,3 +0,0 @@
-load_lib llvm.exp
-
-RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{td}]]
diff --git a/test/LLVMC/test_data/false.c b/test/LLVMC/test_data/false.c
deleted file mode 100644
index 3e4e8a7..0000000
--- a/test/LLVMC/test_data/false.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <iostream>
-
-extern "C" void test();
-extern std::string test2();
-
-int test_main() {
- std::cout << "h";
- test();
- std::cout << test2() << '\n';
-}
diff --git a/test/LLVMC/test_data/false.cpp b/test/LLVMC/test_data/false.cpp
deleted file mode 100644
index 593fcd5..0000000
--- a/test/LLVMC/test_data/false.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-
-/* Make this invalid C++ */
-typedef struct {
- int i;
- char c;
-} a;
-
-static a b = { .i = 65, .c = 'r'};
-
-void test() {
- b.i = 9;
- fflush(stdout);
- printf("el");
-}
-
diff --git a/test/LLVMC/test_data/false2.cpp b/test/LLVMC/test_data/false2.cpp
deleted file mode 100644
index bba064c..0000000
--- a/test/LLVMC/test_data/false2.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <string>
-
-std::string test2() {
- return "lo";
-}
diff --git a/test/LLVMC/test_data/together.c b/test/LLVMC/test_data/together.c
deleted file mode 100644
index a828c47..0000000
--- a/test/LLVMC/test_data/together.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <stdio.h>
-
-void test() {
- printf("hello\n");
-}
diff --git a/test/Linker/2003-01-30-LinkerTypeRename.ll b/test/Linker/2003-01-30-LinkerTypeRename.ll
index 6cd2406..043457d 100644
--- a/test/Linker/2003-01-30-LinkerTypeRename.ll
+++ b/test/Linker/2003-01-30-LinkerTypeRename.ll
@@ -1,9 +1,9 @@
-; This fails because the linker renames the non-opaque type not the opaque
+; This fails because the linker renames the non-opaque type not the opaque
; one...
-; RUN: echo {%Ty = type opaque @GV = external global %Ty*} | llvm-as > %t.1.bc
+; RUN: echo {%%Ty = type opaque @GV = external global %%Ty*} | llvm-as > %t.1.bc
; RUN: llvm-as < %s > %t.2.bc
-; RUN: llvm-link %t.1.bc %t.2.bc -S | grep {%Ty } | not grep opaque
+; RUN: llvm-link %t.1.bc %t.2.bc -S | grep {%%Ty } | not grep opaque
%Ty = type {i32}
diff --git a/test/Linker/2003-04-26-NullPtrLinkProblem.ll b/test/Linker/2003-04-26-NullPtrLinkProblem.ll
index 54ba051..d23df1b 100644
--- a/test/Linker/2003-04-26-NullPtrLinkProblem.ll
+++ b/test/Linker/2003-04-26-NullPtrLinkProblem.ll
@@ -1,7 +1,7 @@
; This one fails because the LLVM runtime is allowing two null pointers of
; the same type to be created!
-; RUN: echo {%T = type i32} | llvm-as > %t.2.bc
+; RUN: echo {%%T = type i32} | llvm-as > %t.2.bc
; RUN: llvm-as %s -o %t.1.bc
; RUN: llvm-link %t.1.bc %t.2.bc
diff --git a/test/Linker/2003-06-02-TypeResolveProblem.ll b/test/Linker/2003-06-02-TypeResolveProblem.ll
index 86979f6..0b0e9c1 100644
--- a/test/Linker/2003-06-02-TypeResolveProblem.ll
+++ b/test/Linker/2003-06-02-TypeResolveProblem.ll
@@ -1,4 +1,4 @@
-; RUN: echo {%T = type opaque} | llvm-as > %t.2.bc
+; RUN: echo {%%T = type opaque} | llvm-as > %t.2.bc
; RUN: llvm-as < %s > %t.1.bc
; RUN: llvm-link %t.1.bc %t.2.bc
diff --git a/test/Linker/2003-06-02-TypeResolveProblem2.ll b/test/Linker/2003-06-02-TypeResolveProblem2.ll
index 42cc040..3f9fd04 100644
--- a/test/Linker/2003-06-02-TypeResolveProblem2.ll
+++ b/test/Linker/2003-06-02-TypeResolveProblem2.ll
@@ -1,4 +1,4 @@
-; RUN: echo {%T = type i32} | llvm-as > %t.1.bc
+; RUN: echo {%%T = type i32} | llvm-as > %t.1.bc
; RUN: llvm-as < %s > %t.2.bc
; RUN: llvm-link %t.1.bc %t.2.bc
diff --git a/test/Linker/2003-08-23-GlobalVarLinking.ll b/test/Linker/2003-08-23-GlobalVarLinking.ll
index 8acbbd2..255cb88 100644
--- a/test/Linker/2003-08-23-GlobalVarLinking.ll
+++ b/test/Linker/2003-08-23-GlobalVarLinking.ll
@@ -1,5 +1,5 @@
; RUN: llvm-as < %s > %t.out1.bc
-; RUN: echo {%T1 = type opaque %T2 = type opaque @S = external global \{ i32, %T1* \} declare void @F(%T2*)}\
+; RUN: echo {%%T1 = type opaque %%T2 = type opaque @S = external global \{ i32, %%T1* \} declare void @F(%%T2*)}\
; RUN: | llvm-as > %t.out2.bc
; RUN: llvm-link %t.out1.bc %t.out2.bc -S | not grep opaque
diff --git a/test/Linker/2003-11-18-TypeResolution.ll b/test/Linker/2003-11-18-TypeResolution.ll
index d3152ed..e7b15fa 100644
--- a/test/Linker/2003-11-18-TypeResolution.ll
+++ b/test/Linker/2003-11-18-TypeResolution.ll
@@ -5,7 +5,7 @@
; own.
; RUN: llvm-as < %s > %t.out2.bc
-; RUN: echo "%T1 = type opaque @GVar = external global %T1*" | llvm-as > %t.out1.bc
+; RUN: echo "%%T1 = type opaque @GVar = external global %%T1*" | llvm-as > %t.out1.bc
; RUN: llvm-link %t.out1.bc %t.out2.bc
%T1 = type opaque
diff --git a/test/Linker/2011-08-04-DebugLoc.ll b/test/Linker/2011-08-04-DebugLoc.ll
new file mode 100644
index 0000000..699f0b5
--- /dev/null
+++ b/test/Linker/2011-08-04-DebugLoc.ll
@@ -0,0 +1,26 @@
+; RUN: llvm-link %s %p/2011-08-04-DebugLoc2.ll -o %t.bc
+; RUN: llvm-dis < %t.bc | FileCheck %s
+; Test if DebugLoc is mapped properly or not.
+
+
+;CHECK-NOT: metadata !{i32 589870, i32 0, metadata !{{[0-9]+}}, metadata !"bar", metadata !"bar", metadata !"", metadata !{{[0-9]+}}, i32 1, metadata !{{[0-9]+}}, i1 false, i1 true, i32 0, i32 0, i32 0, i32 0, i1 false, null, null, null}
+
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+define i32 @foo() nounwind ssp {
+ ret i32 42, !dbg !6
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.dbg.sp = !{!1}
+
+!0 = metadata !{i32 589841, i32 0, i32 12, metadata !"a.c", metadata !"/private/tmp", metadata !"Apple clang version 3.0 (tags/Apple/clang-209.11) (based on LLVM 3.0svn)", i1 true, i1 false, metadata !"", i32 0} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{i32 589870, i32 0, metadata !2, metadata !"foo", metadata !"foo", metadata !"", metadata !2, i32 2, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 0, i1 false, i32 ()* @foo, null, null} ; [ DW_TAG_subprogram ]
+!2 = metadata !{i32 589865, metadata !"a.c", metadata !"/private/tmp", metadata !0} ; [ DW_TAG_file_type ]
+!3 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 589860, metadata !0, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!6 = metadata !{i32 2, i32 13, metadata !7, null}
+!7 = metadata !{i32 589835, metadata !1, i32 2, i32 11, metadata !2, i32 0} ; [ DW_TAG_lexical_block ]
diff --git a/test/Linker/2011-08-04-DebugLoc2.ll b/test/Linker/2011-08-04-DebugLoc2.ll
new file mode 100644
index 0000000..f30e180
--- /dev/null
+++ b/test/Linker/2011-08-04-DebugLoc2.ll
@@ -0,0 +1,23 @@
+; This file is used by 2011-08-04-DebugLoc.ll, so it doesn't actually do anything itself
+;
+; RUN: true
+
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+define i32 @bar() nounwind ssp {
+ ret i32 21, !dbg !6
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.dbg.sp = !{!1}
+
+!0 = metadata !{i32 589841, i32 0, i32 12, metadata !"b.c", metadata !"/private/tmp", metadata !"Apple clang version 3.0 (tags/Apple/clang-209.11) (based on LLVM 3.0svn)", i1 true, i1 false, metadata !"", i32 0} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{i32 589870, i32 0, metadata !2, metadata !"bar", metadata !"bar", metadata !"", metadata !2, i32 1, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 0, i1 false, i32 ()* @bar, null, null} ; [ DW_TAG_subprogram ]
+!2 = metadata !{i32 589865, metadata !"b.c", metadata !"/private/tmp", metadata !0} ; [ DW_TAG_file_type ]
+!3 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 589860, metadata !0, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!6 = metadata !{i32 1, i32 13, metadata !7, null}
+!7 = metadata !{i32 589835, metadata !1, i32 1, i32 11, metadata !2, i32 0} ; [ DW_TAG_lexical_block ]
diff --git a/test/Linker/2011-08-04-Metadata.ll b/test/Linker/2011-08-04-Metadata.ll
new file mode 100644
index 0000000..952eccc
--- /dev/null
+++ b/test/Linker/2011-08-04-Metadata.ll
@@ -0,0 +1,29 @@
+; RUN: llvm-link %s %p/2011-08-04-Metadata2.ll -o %t.bc
+; RUN: llvm-dis < %t.bc | FileCheck %s
+; Test if internal global variable's debug info is merged appropriately or not.
+
+;CHECK: metadata !{i32 589876, i32 0, metadata !{{[0-9]+}}, metadata !"x", metadata !"x", metadata !"", metadata !{{[0-9]+}}, i32 1, metadata !{{[0-9]+}}, i32 1, i32 1, i32* @x1}
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+@x = internal global i32 0, align 4
+
+define void @foo() nounwind uwtable ssp {
+entry:
+ store i32 1, i32* @x, align 4, !dbg !7
+ ret void, !dbg !7
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.dbg.sp = !{!1}
+!llvm.dbg.gv = !{!5}
+
+!0 = metadata !{i32 589841, i32 0, i32 12, metadata !"/tmp/one.c", metadata !"/Volumes/Lalgate/Slate/D", metadata !"clang version 3.0 ()", i1 true, i1 false, metadata !"", i32 0}
+!1 = metadata !{i32 589870, i32 0, metadata !2, metadata !"foo", metadata !"foo", metadata !"", metadata !2, i32 3, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 0, i1 false, void ()* @foo, null, null}
+!2 = metadata !{i32 589865, metadata !"/tmp/one.c", metadata !"/Volumes/Lalgate/Slate/D", metadata !0}
+!3 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0}
+!4 = metadata !{null}
+!5 = metadata !{i32 589876, i32 0, metadata !0, metadata !"x", metadata !"x", metadata !"", metadata !2, i32 2, metadata !6, i32 1, i32 1, i32* @x}
+!6 = metadata !{i32 589860, metadata !0, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5}
+!7 = metadata !{i32 3, i32 14, metadata !8, null}
+!8 = metadata !{i32 589835, metadata !1, i32 3, i32 12, metadata !2, i32 0}
diff --git a/test/Linker/2011-08-04-Metadata2.ll b/test/Linker/2011-08-04-Metadata2.ll
new file mode 100644
index 0000000..fa5e7c9
--- /dev/null
+++ b/test/Linker/2011-08-04-Metadata2.ll
@@ -0,0 +1,29 @@
+; This file is used by 2011-08-04-Metadata.ll, so it doesn't actually do anything itself
+;
+; RUN: true
+
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+@x = internal global i32 0, align 4
+
+define void @bar() nounwind uwtable ssp {
+entry:
+ store i32 1, i32* @x, align 4, !dbg !7
+ ret void, !dbg !7
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.dbg.sp = !{!1}
+!llvm.dbg.gv = !{!5}
+
+!0 = metadata !{i32 589841, i32 0, i32 12, metadata !"/tmp/two.c", metadata !"/Volumes/Lalgate/Slate/D", metadata !"clang version 3.0 ()", i1 true, i1 false, metadata !"", i32 0}
+!1 = metadata !{i32 589870, i32 0, metadata !2, metadata !"bar", metadata !"bar", metadata !"", metadata !2, i32 2, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 0, i1 false, void ()* @bar, null, null}
+!2 = metadata !{i32 589865, metadata !"/tmp/two.c", metadata !"/Volumes/Lalgate/Slate/D", metadata !0}
+!3 = metadata !{i32 589845, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0}
+!4 = metadata !{null}
+!5 = metadata !{i32 589876, i32 0, metadata !0, metadata !"x", metadata !"x", metadata !"", metadata !2, i32 1, metadata !6, i32 1, i32 1, i32* @x}
+!6 = metadata !{i32 589860, metadata !0, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5}
+!7 = metadata !{i32 2, i32 14, metadata !8, null}
+!8 = metadata !{i32 589835, metadata !1, i32 2, i32 12, metadata !2, i32 0}
diff --git a/test/Linker/2011-08-18-unique-class-type.ll b/test/Linker/2011-08-18-unique-class-type.ll
new file mode 100644
index 0000000..cae1245
--- /dev/null
+++ b/test/Linker/2011-08-18-unique-class-type.ll
@@ -0,0 +1,35 @@
+; RUN: llvm-link %s %p/2011-08-18-unique-class-type2.ll -S -o - | grep DW_TAG_class_type | count 1
+; Test to check there is only one MDNode for class A after linking.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+%"class.N1::A" = type { i8 }
+
+define void @_Z3fooN2N11AE() nounwind uwtable ssp {
+entry:
+ %mya = alloca %"class.N1::A", align 1
+ call void @llvm.dbg.declare(metadata !{%"class.N1::A"* %mya}, metadata !9), !dbg !13
+ ret void, !dbg !14
+}
+
+declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
+
+!llvm.dbg.cu = !{!0}
+
+!0 = metadata !{i32 720913, i32 0, i32 4, metadata !"n1.c", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 137954)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !1} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 720942, i32 0, metadata !6, metadata !"foo", metadata !"foo", metadata !"_Z3fooN2N11AE", metadata !6, i32 4, metadata !7, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 false, void ()* @_Z3fooN2N11AE, null, null} ; [ DW_TAG_subprogram ]
+!6 = metadata !{i32 720937, metadata !"n1.c", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 720917, metadata !6, metadata !"", metadata !6, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!8 = metadata !{null}
+!9 = metadata !{i32 721153, metadata !5, metadata !"mya", metadata !6, i32 16777220, metadata !10, i32 0, i32 0} ; [ DW_TAG_arg_variable ]
+!10 = metadata !{i32 720898, metadata !11, metadata !"A", metadata !12, i32 3, i64 8, i64 8, i32 0, i32 0, null, metadata !2, i32 0, null, null} ; [ DW_TAG_class_type ]
+!11 = metadata !{i32 720953, null, metadata !"N1", metadata !12, i32 2} ; [ DW_TAG_namespace ]
+!12 = metadata !{i32 720937, metadata !"./n.h", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
+!13 = metadata !{i32 4, i32 12, metadata !5, null}
+!14 = metadata !{i32 4, i32 18, metadata !15, null}
+!15 = metadata !{i32 720907, metadata !5, i32 4, i32 17, metadata !6, i32 0} ; [ DW_TAG_lexical_block ]
diff --git a/test/Linker/2011-08-18-unique-class-type2.ll b/test/Linker/2011-08-18-unique-class-type2.ll
new file mode 100644
index 0000000..95892a4
--- /dev/null
+++ b/test/Linker/2011-08-18-unique-class-type2.ll
@@ -0,0 +1,35 @@
+; This file is for use with 2011-08-10-unique-class-type.ll
+; RUN: true
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+%"class.N1::A" = type { i8 }
+
+define void @_Z3barN2N11AE() nounwind uwtable ssp {
+entry:
+ %youra = alloca %"class.N1::A", align 1
+ call void @llvm.dbg.declare(metadata !{%"class.N1::A"* %youra}, metadata !9), !dbg !13
+ ret void, !dbg !14
+}
+
+declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
+
+!llvm.dbg.cu = !{!0}
+
+!0 = metadata !{i32 720913, i32 0, i32 4, metadata !"n2.c", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 137954)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !1} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 720942, i32 0, metadata !6, metadata !"bar", metadata !"bar", metadata !"_Z3barN2N11AE", metadata !6, i32 4, metadata !7, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 false, void ()* @_Z3barN2N11AE, null, null} ; [ DW_TAG_subprogram ]
+!6 = metadata !{i32 720937, metadata !"n2.c", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 720917, metadata !6, metadata !"", metadata !6, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!8 = metadata !{null}
+!9 = metadata !{i32 721153, metadata !5, metadata !"youra", metadata !6, i32 16777220, metadata !10, i32 0, i32 0} ; [ DW_TAG_arg_variable ]
+!10 = metadata !{i32 720898, metadata !11, metadata !"A", metadata !12, i32 3, i64 8, i64 8, i32 0, i32 0, null, metadata !2, i32 0, null, null} ; [ DW_TAG_class_type ]
+!11 = metadata !{i32 720953, null, metadata !"N1", metadata !12, i32 2} ; [ DW_TAG_namespace ]
+!12 = metadata !{i32 720937, metadata !"./n.h", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
+!13 = metadata !{i32 4, i32 12, metadata !5, null}
+!14 = metadata !{i32 4, i32 20, metadata !15, null}
+!15 = metadata !{i32 720907, metadata !5, i32 4, i32 19, metadata !6, i32 0} ; [ DW_TAG_lexical_block ]
diff --git a/test/Linker/2011-08-18-unique-debug-type.ll b/test/Linker/2011-08-18-unique-debug-type.ll
new file mode 100644
index 0000000..4ef0e0e
--- /dev/null
+++ b/test/Linker/2011-08-18-unique-debug-type.ll
@@ -0,0 +1,26 @@
+
+; RUN: llvm-link %s %p/2011-08-18-unique-debug-type2.ll -S -o - | grep "int" | count 1
+; Test to check only one MDNode for "int" after linking.
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+define i32 @foo() nounwind uwtable ssp {
+entry:
+ ret i32 1, !dbg !10
+}
+
+!llvm.dbg.cu = !{!0}
+
+!0 = metadata !{i32 720913, i32 0, i32 12, metadata !"one.c", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 137954)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !1} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 720942, i32 0, metadata !6, metadata !"foo", metadata !"foo", metadata !"", metadata !6, i32 1, metadata !7, i1 false, i1 true, i32 0, i32 0, i32 0, i32 0, i1 false, i32 ()* @foo, null, null} ; [ DW_TAG_subprogram ]
+!6 = metadata !{i32 720937, metadata !"one.c", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 720917, metadata !6, metadata !"", metadata !6, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!8 = metadata !{metadata !9}
+!9 = metadata !{i32 720932, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!10 = metadata !{i32 1, i32 13, metadata !11, null}
+!11 = metadata !{i32 720907, metadata !5, i32 1, i32 11, metadata !6, i32 0} ; [ DW_TAG_lexical_block ]
+
diff --git a/test/Linker/2011-08-18-unique-debug-type2.ll b/test/Linker/2011-08-18-unique-debug-type2.ll
new file mode 100644
index 0000000..986da5b
--- /dev/null
+++ b/test/Linker/2011-08-18-unique-debug-type2.ll
@@ -0,0 +1,25 @@
+; This file is for use with 2011-08-10-unique-debug-type.ll
+; RUN: true
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+define i32 @bar() nounwind uwtable ssp {
+entry:
+ ret i32 2, !dbg !10
+}
+
+!llvm.dbg.cu = !{!0}
+
+!0 = metadata !{i32 720913, i32 0, i32 12, metadata !"two.c", metadata !"/private/tmp", metadata !"clang version 3.0 (trunk 137954)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !1} ; [ DW_TAG_compile_unit ]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 720942, i32 0, metadata !6, metadata !"bar", metadata !"bar", metadata !"", metadata !6, i32 1, metadata !7, i1 false, i1 true, i32 0, i32 0, i32 0, i32 0, i1 false, i32 ()* @bar, null, null} ; [ DW_TAG_subprogram ]
+!6 = metadata !{i32 720937, metadata !"two.c", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 720917, metadata !6, metadata !"", metadata !6, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!8 = metadata !{metadata !9}
+!9 = metadata !{i32 720932, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!10 = metadata !{i32 1, i32 13, metadata !11, null}
+!11 = metadata !{i32 720907, metadata !5, i32 1, i32 11, metadata !6, i32 0} ; [ DW_TAG_lexical_block ]
diff --git a/test/Linker/2011-08-22-ResolveAlias.ll b/test/Linker/2011-08-22-ResolveAlias.ll
new file mode 100644
index 0000000..6b99233
--- /dev/null
+++ b/test/Linker/2011-08-22-ResolveAlias.ll
@@ -0,0 +1,89 @@
+; PR10663
+; RUN: llvm-link %s %p/2011-08-22-ResolveAlias2.ll
+
+%union.pthread_attr_t = type { [56 x i8] }
+%union.pthread_mutex_t = type { [40 x i8] }
+%struct.timespec = type { i64, i64 }
+%union.pthread_mutexattr_t = type { [4 x i8] }
+%union.pthread_cond_t = type { [48 x i8] }
+
+@_ZL20__gthrw_pthread_oncePiPFvvE = alias weak i32 (i32*, void ()*)* @pthread_once
+@_ZL27__gthrw_pthread_getspecificj = alias weak i8* (i32)* @pthread_getspecific
+@_ZL27__gthrw_pthread_setspecificjPKv = alias weak i32 (i32, i8*)* @pthread_setspecific
+@_ZL22__gthrw_pthread_createPmPK14pthread_attr_tPFPvS3_ES3_ = alias weak i32 (i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*)* @pthread_create
+@_ZL20__gthrw_pthread_joinmPPv = alias weak i32 (i64, i8**)* @pthread_join
+@_ZL21__gthrw_pthread_equalmm = alias weak i32 (i64, i64)* @pthread_equal
+@_ZL20__gthrw_pthread_selfv = alias weak i64 ()* @pthread_self
+@_ZL22__gthrw_pthread_detachm = alias weak i32 (i64)* @pthread_detach
+@_ZL22__gthrw_pthread_cancelm = alias weak i32 (i64)* @pthread_cancel
+@_ZL19__gthrw_sched_yieldv = alias weak i32 ()* @sched_yield
+@_ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t = alias weak i32 (%union.pthread_mutex_t*)* @pthread_mutex_lock
+@_ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t = alias weak i32 (%union.pthread_mutex_t*)* @pthread_mutex_trylock
+@_ZL31__gthrw_pthread_mutex_timedlockP15pthread_mutex_tPK8timespec = alias weak i32 (%union.pthread_mutex_t*, %struct.timespec*)* @pthread_mutex_timedlock
+@_ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t = alias weak i32 (%union.pthread_mutex_t*)* @pthread_mutex_unlock
+@_ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t = alias weak i32 (%union.pthread_mutex_t*, %union.pthread_mutexattr_t*)* @pthread_mutex_init
+@_ZL29__gthrw_pthread_mutex_destroyP15pthread_mutex_t = alias weak i32 (%union.pthread_mutex_t*)* @pthread_mutex_destroy
+@_ZL30__gthrw_pthread_cond_broadcastP14pthread_cond_t = alias weak i32 (%union.pthread_cond_t*)* @pthread_cond_broadcast
+@_ZL27__gthrw_pthread_cond_signalP14pthread_cond_t = alias weak i32 (%union.pthread_cond_t*)* @pthread_cond_signal
+@_ZL25__gthrw_pthread_cond_waitP14pthread_cond_tP15pthread_mutex_t = alias weak i32 (%union.pthread_cond_t*, %union.pthread_mutex_t*)* @pthread_cond_wait
+@_ZL30__gthrw_pthread_cond_timedwaitP14pthread_cond_tP15pthread_mutex_tPK8timespec = alias weak i32 (%union.pthread_cond_t*, %union.pthread_mutex_t*, %struct.timespec*)* @pthread_cond_timedwait
+@_ZL28__gthrw_pthread_cond_destroyP14pthread_cond_t = alias weak i32 (%union.pthread_cond_t*)* @pthread_cond_destroy
+@_ZL26__gthrw_pthread_key_createPjPFvPvE = alias weak i32 (i32*, void (i8*)*)* @pthread_key_create
+@_ZL26__gthrw_pthread_key_deletej = alias weak i32 (i32)* @pthread_key_delete
+@_ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t = alias weak i32 (%union.pthread_mutexattr_t*)* @pthread_mutexattr_init
+@_ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti = alias weak i32 (%union.pthread_mutexattr_t*, i32)* @pthread_mutexattr_settype
+@_ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t = alias weak i32 (%union.pthread_mutexattr_t*)* @pthread_mutexattr_destroy
+
+declare extern_weak i32 @pthread_once(i32*, void ()*)
+
+declare extern_weak i8* @pthread_getspecific(i32)
+
+declare extern_weak i32 @pthread_setspecific(i32, i8*)
+
+declare extern_weak i32 @pthread_create(i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*)
+
+declare extern_weak i32 @pthread_join(i64, i8**)
+
+declare extern_weak i32 @pthread_equal(i64, i64)
+
+declare extern_weak i64 @pthread_self()
+
+declare extern_weak i32 @pthread_detach(i64)
+
+declare extern_weak i32 @pthread_cancel(i64)
+
+declare extern_weak i32 @sched_yield()
+
+declare extern_weak i32 @pthread_mutex_lock(%union.pthread_mutex_t*)
+
+declare extern_weak i32 @pthread_mutex_trylock(%union.pthread_mutex_t*)
+
+declare extern_weak i32 @pthread_mutex_timedlock(%union.pthread_mutex_t*, %struct.timespec*)
+
+declare extern_weak i32 @pthread_mutex_unlock(%union.pthread_mutex_t*)
+
+declare extern_weak i32 @pthread_mutex_init(%union.pthread_mutex_t*, %union.pthread_mutexattr_t*)
+
+declare extern_weak i32 @pthread_mutex_destroy(%union.pthread_mutex_t*)
+
+declare extern_weak i32 @pthread_cond_broadcast(%union.pthread_cond_t*)
+
+declare extern_weak i32 @pthread_cond_signal(%union.pthread_cond_t*)
+
+declare extern_weak i32 @pthread_cond_wait(%union.pthread_cond_t*, %union.pthread_mutex_t*)
+
+declare extern_weak i32 @pthread_cond_timedwait(%union.pthread_cond_t*, %union.pthread_mutex_t*, %struct.timespec*)
+
+declare extern_weak i32 @pthread_cond_destroy(%union.pthread_cond_t*)
+
+declare extern_weak i32 @pthread_key_create(i32*, void (i8*)*)
+
+declare extern_weak i32 @pthread_key_delete(i32)
+
+declare extern_weak i32 @pthread_mutexattr_init(%union.pthread_mutexattr_t*)
+
+declare extern_weak i32 @pthread_mutexattr_settype(%union.pthread_mutexattr_t*, i32)
+
+declare extern_weak i32 @pthread_mutexattr_destroy(%union.pthread_mutexattr_t*)
+
+declare void @_GLOBAL__sub_I__ZN10BitBoard64coEv() nounwind uwtable
diff --git a/test/Linker/2011-08-22-ResolveAlias2.ll b/test/Linker/2011-08-22-ResolveAlias2.ll
new file mode 100644
index 0000000..2549040
--- /dev/null
+++ b/test/Linker/2011-08-22-ResolveAlias2.ll
@@ -0,0 +1,92 @@
+; This file is used by 2011-08-22-ResolveAlias.ll
+; RUN: true
+
+%struct.HexxagonBoard = type { %struct.BitBoard64, %struct.BitBoard64 }
+%struct.BitBoard64 = type { i32, i32 }
+%union.pthread_attr_t = type { [56 x i8] }
+%union.pthread_mutex_t = type { [40 x i8] }
+%struct.timespec = type { i64, i64 }
+%union.pthread_mutexattr_t = type { [4 x i8] }
+%union.pthread_cond_t = type { [48 x i8] }
+
+@_ZN13HexxagonBoardC1ERKS_ = alias void (%struct.HexxagonBoard*, %struct.HexxagonBoard*)* @_ZN13HexxagonBoardC2ERKS_
+@_ZL20__gthrw_pthread_oncePiPFvvE = alias weak i32 (i32*, void ()*)* @pthread_once
+@_ZL27__gthrw_pthread_getspecificj = alias weak i8* (i32)* @pthread_getspecific
+@_ZL27__gthrw_pthread_setspecificjPKv = alias weak i32 (i32, i8*)* @pthread_setspecific
+@_ZL22__gthrw_pthread_createPmPK14pthread_attr_tPFPvS3_ES3_ = alias weak i32 (i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*)* @pthread_create
+@_ZL20__gthrw_pthread_joinmPPv = alias weak i32 (i64, i8**)* @pthread_join
+@_ZL21__gthrw_pthread_equalmm = alias weak i32 (i64, i64)* @pthread_equal
+@_ZL20__gthrw_pthread_selfv = alias weak i64 ()* @pthread_self
+@_ZL22__gthrw_pthread_detachm = alias weak i32 (i64)* @pthread_detach
+@_ZL22__gthrw_pthread_cancelm = alias weak i32 (i64)* @pthread_cancel
+@_ZL19__gthrw_sched_yieldv = alias weak i32 ()* @sched_yield
+@_ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t = alias weak i32 (%union.pthread_mutex_t*)* @pthread_mutex_lock
+@_ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t = alias weak i32 (%union.pthread_mutex_t*)* @pthread_mutex_trylock
+@_ZL31__gthrw_pthread_mutex_timedlockP15pthread_mutex_tPK8timespec = alias weak i32 (%union.pthread_mutex_t*, %struct.timespec*)* @pthread_mutex_timedlock
+@_ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t = alias weak i32 (%union.pthread_mutex_t*)* @pthread_mutex_unlock
+@_ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t = alias weak i32 (%union.pthread_mutex_t*, %union.pthread_mutexattr_t*)* @pthread_mutex_init
+@_ZL29__gthrw_pthread_mutex_destroyP15pthread_mutex_t = alias weak i32 (%union.pthread_mutex_t*)* @pthread_mutex_destroy
+@_ZL30__gthrw_pthread_cond_broadcastP14pthread_cond_t = alias weak i32 (%union.pthread_cond_t*)* @pthread_cond_broadcast
+@_ZL27__gthrw_pthread_cond_signalP14pthread_cond_t = alias weak i32 (%union.pthread_cond_t*)* @pthread_cond_signal
+@_ZL25__gthrw_pthread_cond_waitP14pthread_cond_tP15pthread_mutex_t = alias weak i32 (%union.pthread_cond_t*, %union.pthread_mutex_t*)* @pthread_cond_wait
+@_ZL30__gthrw_pthread_cond_timedwaitP14pthread_cond_tP15pthread_mutex_tPK8timespec = alias weak i32 (%union.pthread_cond_t*, %union.pthread_mutex_t*, %struct.timespec*)* @pthread_cond_timedwait
+@_ZL28__gthrw_pthread_cond_destroyP14pthread_cond_t = alias weak i32 (%union.pthread_cond_t*)* @pthread_cond_destroy
+@_ZL26__gthrw_pthread_key_createPjPFvPvE = alias weak i32 (i32*, void (i8*)*)* @pthread_key_create
+@_ZL26__gthrw_pthread_key_deletej = alias weak i32 (i32)* @pthread_key_delete
+@_ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t = alias weak i32 (%union.pthread_mutexattr_t*)* @pthread_mutexattr_init
+@_ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti = alias weak i32 (%union.pthread_mutexattr_t*, i32)* @pthread_mutexattr_settype
+@_ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t = alias weak i32 (%union.pthread_mutexattr_t*)* @pthread_mutexattr_destroy
+
+declare void @_ZN13HexxagonBoardC2ERKS_(%struct.HexxagonBoard*, %struct.HexxagonBoard*) uwtable align 2
+
+declare extern_weak i32 @pthread_once(i32*, void ()*)
+
+declare extern_weak i8* @pthread_getspecific(i32)
+
+declare extern_weak i32 @pthread_setspecific(i32, i8*)
+
+declare extern_weak i32 @pthread_create(i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*)
+
+declare extern_weak i32 @pthread_join(i64, i8**)
+
+declare extern_weak i32 @pthread_equal(i64, i64)
+
+declare extern_weak i64 @pthread_self()
+
+declare extern_weak i32 @pthread_detach(i64)
+
+declare extern_weak i32 @pthread_cancel(i64)
+
+declare extern_weak i32 @sched_yield()
+
+declare extern_weak i32 @pthread_mutex_lock(%union.pthread_mutex_t*)
+
+declare extern_weak i32 @pthread_mutex_trylock(%union.pthread_mutex_t*)
+
+declare extern_weak i32 @pthread_mutex_timedlock(%union.pthread_mutex_t*, %struct.timespec*)
+
+declare extern_weak i32 @pthread_mutex_unlock(%union.pthread_mutex_t*)
+
+declare extern_weak i32 @pthread_mutex_init(%union.pthread_mutex_t*, %union.pthread_mutexattr_t*)
+
+declare extern_weak i32 @pthread_mutex_destroy(%union.pthread_mutex_t*)
+
+declare extern_weak i32 @pthread_cond_broadcast(%union.pthread_cond_t*)
+
+declare extern_weak i32 @pthread_cond_signal(%union.pthread_cond_t*)
+
+declare extern_weak i32 @pthread_cond_wait(%union.pthread_cond_t*, %union.pthread_mutex_t*)
+
+declare extern_weak i32 @pthread_cond_timedwait(%union.pthread_cond_t*, %union.pthread_mutex_t*, %struct.timespec*)
+
+declare extern_weak i32 @pthread_cond_destroy(%union.pthread_cond_t*)
+
+declare extern_weak i32 @pthread_key_create(i32*, void (i8*)*)
+
+declare extern_weak i32 @pthread_key_delete(i32)
+
+declare extern_weak i32 @pthread_mutexattr_init(%union.pthread_mutexattr_t*)
+
+declare extern_weak i32 @pthread_mutexattr_settype(%union.pthread_mutexattr_t*, i32)
+
+declare extern_weak i32 @pthread_mutexattr_destroy(%union.pthread_mutexattr_t*)
diff --git a/test/MC/ARM/arm-memory-instructions.s b/test/MC/ARM/arm-memory-instructions.s
new file mode 100644
index 0000000..783ac28
--- /dev/null
+++ b/test/MC/ARM/arm-memory-instructions.s
@@ -0,0 +1,479 @@
+@ RUN: llvm-mc -triple=armv7-apple-darwin -show-encoding < %s | FileCheck %s
+ .syntax unified
+ .globl _func
+
+@ Check that the assembler can handle the documented syntax from the ARM ARM
+@ for loads and stores.
+
+_func:
+@ CHECK: _func
+
+@------------------------------------------------------------------------------
+@ LDR (immediate)
+@------------------------------------------------------------------------------
+ ldr r5, [r7]
+ ldr r6, [r3, #63]
+ ldr r2, [r4, #4095]!
+ ldr r1, [r2], #30
+ ldr r3, [r1], #-30
+
+@ CHECK: ldr r5, [r7] @ encoding: [0x00,0x50,0x97,0xe5]
+@ CHECK: ldr r6, [r3, #63] @ encoding: [0x3f,0x60,0x93,0xe5]
+@ CHECK: ldr r2, [r4, #4095]! @ encoding: [0xff,0x2f,0xb4,0xe5]
+@ CHECK: ldr r1, [r2], #30 @ encoding: [0x1e,0x10,0x92,0xe4]
+@ CHECK: ldr r3, [r1], #-30 @ encoding: [0x1e,0x30,0x11,0xe4]
+
+@------------------------------------------------------------------------------
+@ FIXME: LDR (literal)
+@------------------------------------------------------------------------------
+@ label operands currently assert the show-encoding asm comment helper due
+@ to the use of non-contiguous bit ranges for fixups in ARM. Once that's
+@ cleaned up, we can write useful assembly testcases for these sorts of
+@ instructions.
+
+@------------------------------------------------------------------------------
+@ LDR (register)
+@------------------------------------------------------------------------------
+ ldr r3, [r8, r1]
+ ldr r2, [r5, -r3]
+ ldr r1, [r5, r9]!
+ ldr r6, [r7, -r8]!
+ ldr r1, [r0, r2, lsr #3]!
+ ldr r5, [r9], r2
+ ldr r4, [r3], -r6
+ ldr r3, [r8, -r2, lsl #15]
+ ldr r1, [r5], r3, asr #15
+
+@ CHECK: ldr r3, [r8, r1] @ encoding: [0x01,0x30,0x98,0xe7]
+@ CHECK: ldr r2, [r5, -r3] @ encoding: [0x03,0x20,0x15,0xe7]
+@ CHECK: ldr r1, [r5, r9]! @ encoding: [0x09,0x10,0xb5,0xe7]
+@ CHECK: ldr r6, [r7, -r8]! @ encoding: [0x08,0x60,0x37,0xe7]
+@ CHECK: ldr r1, [r0, r2, lsr #3]! @ encoding: [0xa2,0x11,0xb0,0xe7]
+@ CHECK: ldr r5, [r9], r2 @ encoding: [0x02,0x50,0x99,0xe6]
+@ CHECK: ldr r4, [r3], -r6 @ encoding: [0x06,0x40,0x13,0xe6]
+@ CHECK: ldr r3, [r8, -r2, lsl #15] @ encoding: [0x82,0x37,0x18,0xe7]
+@ CHECK: ldr r1, [r5], r3, asr #15 @ encoding: [0xc3,0x17,0x95,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ LDRB (immediate)
+@------------------------------------------------------------------------------
+ ldrb r3, [r8]
+ ldrb r1, [sp, #63]
+ ldrb r9, [r3, #4095]!
+ ldrb r8, [r1], #22
+ ldrb r2, [r7], #-19
+
+@ CHECK: ldrb r3, [r8] @ encoding: [0x00,0x30,0xd8,0xe5]
+@ CHECK: ldrb r1, [sp, #63] @ encoding: [0x3f,0x10,0xdd,0xe5]
+@ CHECK: ldrb r9, [r3, #4095]! @ encoding: [0xff,0x9f,0xf3,0xe5]
+@ CHECK: ldrb r8, [r1], #22 @ encoding: [0x16,0x80,0xd1,0xe4]
+@ CHECK: ldrb r2, [r7], #-19 @ encoding: [0x13,0x20,0x57,0xe4]
+
+
+@------------------------------------------------------------------------------
+@ LDRB (register)
+@------------------------------------------------------------------------------
+ ldrb r9, [r8, r5]
+ ldrb r1, [r5, -r1]
+ ldrb r3, [r5, r2]!
+ ldrb r6, [r9, -r3]!
+ ldrb r2, [r1], r4
+ ldrb r8, [r4], -r5
+ ldrb r7, [r12, -r1, lsl #15]
+ ldrb r5, [r2], r9, asr #15
+
+@ CHECK: ldrb r9, [r8, r5] @ encoding: [0x05,0x90,0xd8,0xe7]
+@ CHECK: ldrb r1, [r5, -r1] @ encoding: [0x01,0x10,0x55,0xe7]
+@ CHECK: ldrb r3, [r5, r2]! @ encoding: [0x02,0x30,0xf5,0xe7]
+@ CHECK: ldrb r6, [r9, -r3]! @ encoding: [0x03,0x60,0x79,0xe7]
+@ CHECK: ldrb r2, [r1], r4 @ encoding: [0x04,0x20,0xd1,0xe6]
+@ CHECK: ldrb r8, [r4], -r5 @ encoding: [0x05,0x80,0x54,0xe6]
+@ CHECK: ldrb r7, [r12, -r1, lsl #15] @ encoding: [0x81,0x77,0x5c,0xe7]
+@ CHECK: ldrb r5, [r2], r9, asr #15 @ encoding: [0xc9,0x57,0xd2,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ LDRBT
+@------------------------------------------------------------------------------
+@ FIXME: Optional offset operand.
+ ldrbt r3, [r1], #4
+ ldrbt r2, [r8], #-8
+ ldrbt r8, [r7], r6
+ ldrbt r1, [r2], -r6, lsl #12
+
+
+@ CHECK: ldrbt r3, [r1], #4 @ encoding: [0x04,0x30,0xf1,0xe4]
+@ CHECK: ldrbt r2, [r8], #-8 @ encoding: [0x08,0x20,0x78,0xe4]
+@ CHECK: ldrbt r8, [r7], r6 @ encoding: [0x06,0x80,0xf7,0xe6]
+@ CHECK: ldrbt r1, [r2], -r6, lsl #12 @ encoding: [0x06,0x16,0x72,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ LDRD (immediate)
+@------------------------------------------------------------------------------
+ ldrd r3, r4, [r5]
+ ldrd r7, r8, [r2, #15]
+ ldrd r1, r2, [r9, #32]!
+ ldrd r6, r7, [r1], #8
+ ldrd r1, r2, [r8], #0
+ ldrd r1, r2, [r8], #+0
+ ldrd r1, r2, [r8], #-0
+
+@ CHECK: ldrd r3, r4, [r5] @ encoding: [0xd0,0x30,0xc5,0xe1]
+@ CHECK: ldrd r7, r8, [r2, #15] @ encoding: [0xdf,0x70,0xc2,0xe1]
+@ CHECK: ldrd r1, r2, [r9, #32]! @ encoding: [0xd0,0x12,0xe9,0xe1]
+@ CHECK: ldrd r6, r7, [r1], #8 @ encoding: [0xd8,0x60,0xc1,0xe0]
+@ CHECK: ldrd r1, r2, [r8], #0 @ encoding: [0xd0,0x10,0xc8,0xe0]
+@ CHECK: ldrd r1, r2, [r8], #0 @ encoding: [0xd0,0x10,0xc8,0xe0]
+@ CHECK: ldrd r1, r2, [r8], #-0 @ encoding: [0xd0,0x10,0x48,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ FIXME: LDRD (label)
+@------------------------------------------------------------------------------
+
+@------------------------------------------------------------------------------
+@ LDRD (register)
+@------------------------------------------------------------------------------
+ ldrd r3, r4, [r1, r3]
+ ldrd r4, r5, [r7, r2]!
+ ldrd r1, r2, [r8], r12
+ ldrd r1, r2, [r8], -r12
+
+@ CHECK: ldrd r3, r4, [r1, r3] @ encoding: [0xd3,0x30,0x81,0xe1]
+@ CHECK: ldrd r4, r5, [r7, r2]! @ encoding: [0xd2,0x40,0xa7,0xe1]
+@ CHECK: ldrd r1, r2, [r8], r12 @ encoding: [0xdc,0x10,0x88,0xe0]
+@ CHECK: ldrd r1, r2, [r8], -r12 @ encoding: [0xdc,0x10,0x08,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ LDRH (immediate)
+@------------------------------------------------------------------------------
+ ldrh r3, [r4]
+ ldrh r2, [r7, #4]
+ ldrh r1, [r8, #64]!
+ ldrh r12, [sp], #4
+
+@ CHECK: ldrh r3, [r4] @ encoding: [0xb0,0x30,0xd4,0xe1]
+@ CHECK: ldrh r2, [r7, #4] @ encoding: [0xb4,0x20,0xd7,0xe1]
+@ CHECK: ldrh r1, [r8, #64]! @ encoding: [0xb0,0x14,0xf8,0xe1]
+@ CHECK: ldrh r12, [sp], #4 @ encoding: [0xb4,0xc0,0xdd,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ FIXME: LDRH (label)
+@------------------------------------------------------------------------------
+
+
+@------------------------------------------------------------------------------
+@ LDRH (register)
+@------------------------------------------------------------------------------
+ ldrh r6, [r5, r4]
+ ldrh r3, [r8, r11]!
+ ldrh r1, [r2, -r1]!
+ ldrh r9, [r7], r2
+ ldrh r4, [r3], -r2
+
+@ CHECK: ldrh r6, [r5, r4] @ encoding: [0xb4,0x60,0x95,0xe1]
+@ CHECK: ldrh r3, [r8, r11]! @ encoding: [0xbb,0x30,0xb8,0xe1]
+@ CHECK: ldrh r1, [r2, -r1]! @ encoding: [0xb1,0x10,0x32,0xe1]
+@ CHECK: ldrh r9, [r7], r2 @ encoding: [0xb2,0x90,0x97,0xe0]
+@ CHECK: ldrh r4, [r3], -r2 @ encoding: [0xb2,0x40,0x13,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ LDRHT
+@------------------------------------------------------------------------------
+ ldrht r9, [r7], #128
+ ldrht r4, [r3], #-75
+ ldrht r9, [r7], r2
+ ldrht r4, [r3], -r2
+
+@ CHECK: ldrht r9, [r7], #128 @ encoding: [0xb0,0x98,0xf7,0xe0]
+@ CHECK: ldrht r4, [r3], #-75 @ encoding: [0xbb,0x44,0x73,0xe0]
+@ CHECK: ldrht r9, [r7], r2 @ encoding: [0xb2,0x90,0xb7,0xe0]
+@ CHECK: ldrht r4, [r3], -r2 @ encoding: [0xb2,0x40,0x33,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ LDRSB (immediate)
+@------------------------------------------------------------------------------
+ ldrsb r3, [r4]
+ ldrsb r2, [r7, #17]
+ ldrsb r1, [r8, #255]!
+ ldrsb r12, [sp], #9
+
+@ CHECK: ldrsb r3, [r4] @ encoding: [0xd0,0x30,0xd4,0xe1]
+@ CHECK: ldrsb r2, [r7, #17] @ encoding: [0xd1,0x21,0xd7,0xe1]
+@ CHECK: ldrsb r1, [r8, #255]! @ encoding: [0xdf,0x1f,0xf8,0xe1]
+@ CHECK: ldrsb r12, [sp], #9 @ encoding: [0xd9,0xc0,0xdd,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ FIXME: LDRSB (label)
+@------------------------------------------------------------------------------
+
+
+@------------------------------------------------------------------------------
+@ LDRSB (register)
+@------------------------------------------------------------------------------
+ ldrsb r6, [r5, r4]
+ ldrsb r3, [r8, r11]!
+ ldrsb r1, [r2, -r1]!
+ ldrsb r9, [r7], r2
+ ldrsb r4, [r3], -r2
+
+
+@ CHECK: ldrsb r6, [r5, r4] @ encoding: [0xd4,0x60,0x95,0xe1]
+@ CHECK: ldrsb r3, [r8, r11]! @ encoding: [0xdb,0x30,0xb8,0xe1]
+@ CHECK: ldrsb r1, [r2, -r1]! @ encoding: [0xd1,0x10,0x32,0xe1]
+@ CHECK: ldrsb r9, [r7], r2 @ encoding: [0xd2,0x90,0x97,0xe0]
+@ CHECK: ldrsb r4, [r3], -r2 @ encoding: [0xd2,0x40,0x13,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ LDRSBT
+@------------------------------------------------------------------------------
+ ldrsbt r5, [r6], #1
+ ldrsbt r3, [r8], #-12
+ ldrsbt r8, [r9], r5
+ ldrsbt r2, [r1], -r4
+
+@ CHECK: ldrsbt r5, [r6], #1 @ encoding: [0xd1,0x50,0xf6,0xe0]
+@ CHECK: ldrsbt r3, [r8], #-12 @ encoding: [0xdc,0x30,0x78,0xe0]
+@ CHECK: ldrsbt r8, [r9], r5 @ encoding: [0xd5,0x80,0xb9,0xe0]
+@ CHECK: ldrsbt r2, [r1], -r4 @ encoding: [0xd4,0x20,0x31,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ LDRSH (immediate)
+@------------------------------------------------------------------------------
+ ldrsh r5, [r9]
+ ldrsh r4, [r5, #7]
+ ldrsh r3, [r6, #55]!
+ ldrsh r2, [r7], #-9
+
+@ CHECK: ldrsh r5, [r9] @ encoding: [0xf0,0x50,0xd9,0xe1]
+@ CHECK: ldrsh r4, [r5, #7] @ encoding: [0xf7,0x40,0xd5,0xe1]
+@ CHECK: ldrsh r3, [r6, #55]! @ encoding: [0xf7,0x33,0xf6,0xe1]
+@ CHECK: ldrsh r2, [r7], #-9 @ encoding: [0xf9,0x20,0x57,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ FIXME: LDRSH (label)
+@------------------------------------------------------------------------------
+
+
+@------------------------------------------------------------------------------
+@ LDRSH (register)
+@------------------------------------------------------------------------------
+ ldrsh r3, [r1, r5]
+ ldrsh r4, [r6, r1]!
+ ldrsh r5, [r3, -r6]!
+ ldrsh r6, [r9], r8
+ ldrsh r7, [r8], -r3
+
+@ CHECK: ldrsh r3, [r1, r5] @ encoding: [0xf5,0x30,0x91,0xe1]
+@ CHECK: ldrsh r4, [r6, r1]! @ encoding: [0xf1,0x40,0xb6,0xe1]
+@ CHECK: ldrsh r5, [r3, -r6]! @ encoding: [0xf6,0x50,0x33,0xe1]
+@ CHECK: ldrsh r6, [r9], r8 @ encoding: [0xf8,0x60,0x99,0xe0]
+@ CHECK: ldrsh r7, [r8], -r3 @ encoding: [0xf3,0x70,0x18,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ LDRSHT
+@------------------------------------------------------------------------------
+ ldrsht r5, [r6], #1
+ ldrsht r3, [r8], #-12
+ ldrsht r8, [r9], r5
+ ldrsht r2, [r1], -r4
+
+@ CHECK: ldrsht r5, [r6], #1 @ encoding: [0xf1,0x50,0xf6,0xe0]
+@ CHECK: ldrsht r3, [r8], #-12 @ encoding: [0xfc,0x30,0x78,0xe0]
+@ CHECK: ldrsht r8, [r9], r5 @ encoding: [0xf5,0x80,0xb9,0xe0]
+@ CHECK: ldrsht r2, [r1], -r4 @ encoding: [0xf4,0x20,0x31,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ STR (immediate)
+@------------------------------------------------------------------------------
+ str r8, [r12]
+ str r7, [r1, #12]
+ str r3, [r5, #40]!
+ str r9, [sp], #4095
+ str r1, [r7], #-128
+
+@ CHECK: str r8, [r12] @ encoding: [0x00,0x80,0x8c,0xe5]
+@ CHECK: str r7, [r1, #12] @ encoding: [0x0c,0x70,0x81,0xe5]
+@ CHECK: str r3, [r5, #40]! @ encoding: [0x28,0x30,0xa5,0xe5]
+@ CHECK: str r9, [sp], #4095 @ encoding: [0xff,0x9f,0x8d,0xe4]
+@ CHECK: str r1, [r7], #-128 @ encoding: [0x80,0x10,0x07,0xe4]
+
+
+@------------------------------------------------------------------------------
+@ FIXME: STR (literal)
+@------------------------------------------------------------------------------
+
+@------------------------------------------------------------------------------
+@ STR (register)
+@------------------------------------------------------------------------------
+ str r9, [r6, r3]
+ str r8, [r0, -r2]
+ str r7, [r1, r6]!
+ str r6, [sp, -r1]!
+ str r5, [r3], r9
+ str r4, [r2], -r5
+ str r3, [r4, -r2, lsl #2]
+ str r2, [r7], r3, asr #24
+
+@ CHECK: str r9, [r6, r3] @ encoding: [0x03,0x90,0x86,0xe7]
+@ CHECK: str r8, [r0, -r2] @ encoding: [0x02,0x80,0x00,0xe7]
+@ CHECK: str r7, [r1, r6]! @ encoding: [0x06,0x70,0xa1,0xe7]
+@ CHECK: str r6, [sp, -r1]! @ encoding: [0x01,0x60,0x2d,0xe7]
+@ CHECK: str r5, [r3], r9 @ encoding: [0x09,0x50,0x83,0xe6]
+@ CHECK: str r4, [r2], -r5 @ encoding: [0x05,0x40,0x02,0xe6]
+@ CHECK: str r3, [r4, -r2, lsl #2] @ encoding: [0x02,0x31,0x04,0xe7]
+@ CHECK: str r2, [r7], r3, asr #24 @ encoding: [0x43,0x2c,0x87,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ STRB (immediate)
+@------------------------------------------------------------------------------
+ strb r9, [r2]
+ strb r7, [r1, #3]
+ strb r6, [r4, #405]!
+ strb r5, [r7], #72
+ strb r1, [sp], #-1
+
+@ CHECK: strb r9, [r2] @ encoding: [0x00,0x90,0xc2,0xe5]
+@ CHECK: strb r7, [r1, #3] @ encoding: [0x03,0x70,0xc1,0xe5]
+@ CHECK: strb r6, [r4, #405]! @ encoding: [0x95,0x61,0xe4,0xe5]
+@ CHECK: strb r5, [r7], #72 @ encoding: [0x48,0x50,0xc7,0xe4]
+@ CHECK: strb r1, [sp], #-1 @ encoding: [0x01,0x10,0x4d,0xe4]
+
+@------------------------------------------------------------------------------
+@ FIXME: STRB (literal)
+@------------------------------------------------------------------------------
+
+@------------------------------------------------------------------------------
+@ STRB (register)
+@------------------------------------------------------------------------------
+ strb r1, [r2, r9]
+ strb r2, [r3, -r8]
+ strb r3, [r4, r7]!
+ strb r4, [r5, -r6]!
+ strb r5, [r6], r5
+ strb r6, [r2], -r4
+ strb r7, [r12, -r3, lsl #5]
+ strb sp, [r7], r2, asr #12
+
+@ CHECK: strb r1, [r2, r9] @ encoding: [0x09,0x10,0xc2,0xe7]
+@ CHECK: strb r2, [r3, -r8] @ encoding: [0x08,0x20,0x43,0xe7]
+@ CHECK: strb r3, [r4, r7]! @ encoding: [0x07,0x30,0xe4,0xe7]
+@ CHECK: strb r4, [r5, -r6]! @ encoding: [0x06,0x40,0x65,0xe7]
+@ CHECK: strb r5, [r6], r5 @ encoding: [0x05,0x50,0xc6,0xe6]
+@ CHECK: strb r6, [r2], -r4 @ encoding: [0x04,0x60,0x42,0xe6]
+@ CHECK: strb r7, [r12, -r3, lsl #5] @ encoding: [0x83,0x72,0x4c,0xe7]
+@ CHECK: strb sp, [r7], r2, asr #12 @ encoding: [0x42,0xd6,0xc7,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ STRBT
+@------------------------------------------------------------------------------
+@ FIXME: Optional offset operand.
+ strbt r6, [r2], #12
+ strbt r5, [r6], #-13
+ strbt r4, [r9], r5
+ strbt r3, [r8], -r2, lsl #3
+
+@ CHECK: strbt r6, [r2], #12 @ encoding: [0x0c,0x60,0xe2,0xe4]
+@ CHECK: strbt r5, [r6], #-13 @ encoding: [0x0d,0x50,0x66,0xe4]
+@ CHECK: strbt r4, [r9], r5 @ encoding: [0x05,0x40,0xe9,0xe6]
+@ CHECK: strbt r3, [r8], -r2, lsl #3 @ encoding: [0x82,0x31,0x68,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ STRD (immediate)
+@------------------------------------------------------------------------------
+ strd r1, r2, [r4]
+ strd r2, r3, [r6, #1]
+ strd r3, r4, [r7, #22]!
+ strd r4, r5, [r8], #7
+ strd r5, r6, [sp], #0
+ strd r6, r7, [lr], #+0
+ strd r7, r8, [r9], #-0
+
+@ CHECK: strd r1, r2, [r4] @ encoding: [0xf0,0x10,0xc4,0xe1]
+@ CHECK: strd r2, r3, [r6, #1] @ encoding: [0xf1,0x20,0xc6,0xe1]
+@ CHECK: strd r3, r4, [r7, #22]! @ encoding: [0xf6,0x31,0xe7,0xe1]
+@ CHECK: strd r4, r5, [r8], #7 @ encoding: [0xf7,0x40,0xc8,0xe0]
+@ CHECK: strd r5, r6, [sp], #0 @ encoding: [0xf0,0x50,0xcd,0xe0]
+@ CHECK: strd r6, r7, [lr], #0 @ encoding: [0xf0,0x60,0xce,0xe0]
+@ CHECK: strd r7, r8, [r9], #-0 @ encoding: [0xf0,0x70,0x49,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ FIXME: STRD (label)
+@------------------------------------------------------------------------------
+
+@------------------------------------------------------------------------------
+@ STRD (register)
+@------------------------------------------------------------------------------
+ strd r8, r9, [r4, r1]
+ strd r7, r8, [r3, r9]!
+ strd r6, r7, [r5], r8
+ strd r5, r6, [r12], -r10
+
+@ CHECK: strd r8, r9, [r4, r1] @ encoding: [0xf1,0x80,0x84,0xe1]
+@ CHECK: strd r7, r8, [r3, r9]! @ encoding: [0xf9,0x70,0xa3,0xe1]
+@ CHECK: strd r6, r7, [r5], r8 @ encoding: [0xf8,0x60,0x85,0xe0]
+@ CHECK: strd r5, r6, [r12], -r10 @ encoding: [0xfa,0x50,0x0c,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ STRH (immediate)
+@------------------------------------------------------------------------------
+ strh r3, [r4]
+ strh r2, [r7, #4]
+ strh r1, [r8, #64]!
+ strh r12, [sp], #4
+
+@ CHECK: strh r3, [r4] @ encoding: [0xb0,0x30,0xc4,0xe1]
+@ CHECK: strh r2, [r7, #4] @ encoding: [0xb4,0x20,0xc7,0xe1]
+@ CHECK: strh r1, [r8, #64]! @ encoding: [0xb0,0x14,0xe8,0xe1]
+@ CHECK: strh r12, [sp], #4 @ encoding: [0xb4,0xc0,0xcd,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ FIXME: STRH (label)
+@------------------------------------------------------------------------------
+
+
+@------------------------------------------------------------------------------
+@ STRH (register)
+@------------------------------------------------------------------------------
+ strh r6, [r5, r4]
+ strh r3, [r8, r11]!
+ strh r1, [r2, -r1]!
+ strh r9, [r7], r2
+ strh r4, [r3], -r2
+
+@ CHECK: strh r6, [r5, r4] @ encoding: [0xb4,0x60,0x85,0xe1]
+@ CHECK: strh r3, [r8, r11]! @ encoding: [0xbb,0x30,0xa8,0xe1]
+@ CHECK: strh r1, [r2, -r1]! @ encoding: [0xb1,0x10,0x22,0xe1]
+@ CHECK: strh r9, [r7], r2 @ encoding: [0xb2,0x90,0x87,0xe0]
+@ CHECK: strh r4, [r3], -r2 @ encoding: [0xb2,0x40,0x03,0xe0]
+
+@------------------------------------------------------------------------------
+@ STRHT
+@------------------------------------------------------------------------------
+ strht r2, [r5], #76
+ strht r8, [r1], #-25
+ strht r5, [r3], r4
+ strht r6, [r8], -r0
+
+@ CHECK: strht r2, [r5], #76 @ encoding: [0xbc,0x24,0xe5,0xe0]
+@ CHECK: strht r8, [r1], #-25 @ encoding: [0xb9,0x81,0x61,0xe0]
+@ CHECK: strht r5, [r3], r4 @ encoding: [0xb4,0x50,0xa3,0xe0]
+@ CHECK: strht r6, [r8], -r0 @ encoding: [0xb0,0x60,0x28,0xe0]
diff --git a/test/MC/ARM/arm_addrmode3.s b/test/MC/ARM/arm_addrmode3.s
index 0b9639e..e1dc020 100644
--- a/test/MC/ARM/arm_addrmode3.s
+++ b/test/MC/ARM/arm_addrmode3.s
@@ -1,12 +1,12 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding %s | FileCheck %s
-@ CHECK: ldrsbt r1, [r0], +r2 @ encoding: [0xd2,0x10,0xb0,0xe0]
+@ CHECK: ldrsbt r1, [r0], r2 @ encoding: [0xd2,0x10,0xb0,0xe0]
@ CHECK: ldrsbt r1, [r0], #4 @ encoding: [0xd4,0x10,0xf0,0xe0]
-@ CHECK: ldrsht r1, [r0], +r2 @ encoding: [0xf2,0x10,0xb0,0xe0]
+@ CHECK: ldrsht r1, [r0], r2 @ encoding: [0xf2,0x10,0xb0,0xe0]
@ CHECK: ldrsht r1, [r0], #4 @ encoding: [0xf4,0x10,0xf0,0xe0]
-@ CHECK: ldrht r1, [r0], +r2 @ encoding: [0xb2,0x10,0xb0,0xe0]
+@ CHECK: ldrht r1, [r0], r2 @ encoding: [0xb2,0x10,0xb0,0xe0]
@ CHECK: ldrht r1, [r0], #4 @ encoding: [0xb4,0x10,0xf0,0xe0]
-@ CHECK: strht r1, [r0], +r2 @ encoding: [0xb2,0x10,0xa0,0xe0]
+@ CHECK: strht r1, [r0], r2 @ encoding: [0xb2,0x10,0xa0,0xe0]
@ CHECK: strht r1, [r0], #4 @ encoding: [0xb4,0x10,0xe0,0xe0]
ldrsbt r1, [r0], r2
ldrsbt r1, [r0], #4
diff --git a/test/MC/ARM/arm_fixups.s b/test/MC/ARM/arm_fixups.s
index 0dceb83..aba0cd8 100644
--- a/test/MC/ARM/arm_fixups.s
+++ b/test/MC/ARM/arm_fixups.s
@@ -1,7 +1,17 @@
-// RUN: llvm-mc -triple arm-unknown-unknown %s --show-encoding > %t
-// RUN: FileCheck < %t %s
+@ RUN: llvm-mc -triple armv7-unknown-unknown %s --show-encoding > %t
+@ RUN: FileCheck < %t %s
-// CHECK: bl _printf @ encoding: [A,A,A,0xeb]
-// CHECK: @ fixup A - offset: 0, value: _printf, kind: fixup_arm_uncondbranch
-bl _printf
- \ No newline at end of file
+ bl _printf
+@ CHECK: bl _printf @ encoding: [A,A,A,0xeb]
+@ CHECK: @ fixup A - offset: 0, value: _printf, kind: fixup_arm_uncondbranch
+
+ mov r9, :lower16:(_foo)
+ movw r9, :lower16:(_foo)
+ movt r9, :upper16:(_foo)
+
+@ CHECK: movw r9, :lower16:_foo @ encoding: [A,0x90'A',0b0000AAAA,0xe3]
+@ CHECK: @ fixup A - offset: 0, value: _foo, kind: fixup_arm_movw_lo16
+@ CHECK: movw r9, :lower16:_foo @ encoding: [A,0x90'A',0b0000AAAA,0xe3]
+@ CHECK: @ fixup A - offset: 0, value: _foo, kind: fixup_arm_movw_lo16
+@ CHECK: movt r9, :upper16:_foo @ encoding: [A,0x90'A',0b0100AAAA,0xe3]
+@ CHECK: @ fixup A - offset: 0, value: _foo, kind: fixup_arm_movt_hi16
diff --git a/test/MC/ARM/arm_instructions.s b/test/MC/ARM/arm_instructions.s
index 650fcd2..186954c 100644
--- a/test/MC/ARM/arm_instructions.s
+++ b/test/MC/ARM/arm_instructions.s
@@ -1,13 +1,5 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding %s | FileCheck %s
-@ CHECK: nop
-@ CHECK: encoding: [0x00,0xf0,0x20,0xe3]
- nop
-
-@ CHECK: nopeq
-@ CHECK: encoding: [0x00,0xf0,0x20,0x03]
- nopeq
-
@ CHECK: trap
@ CHECK: encoding: [0xfe,0xde,0xff,0xe7]
trap
@@ -47,15 +39,6 @@
@ CHECK: adc r1, r2, r3 @ encoding: [0x03,0x10,0xa2,0xe0]
adc r1,r2,r3
-@ CHECK: sbc r1, r2, r3 @ encoding: [0x03,0x10,0xc2,0xe0]
- sbc r1,r2,r3
-
-@ CHECK: orr r1, r2, r3 @ encoding: [0x03,0x10,0x82,0xe1]
- orr r1,r2,r3
-
-@ CHECK: orrs r1, r2, r3 @ encoding: [0x03,0x10,0x92,0xe1]
- orrs r1,r2,r3
-
@ CHECK: bic r1, r2, r3 @ encoding: [0x03,0x10,0xc2,0xe1]
bic r1,r2,r3
@@ -71,135 +54,23 @@
@ CHECK: mvns r1, r2 @ encoding: [0x02,0x10,0xf0,0xe1]
mvns r1,r2
-@ CHECK: rsb r1, r2, r3 @ encoding: [0x03,0x10,0x62,0xe0]
- rsb r1,r2,r3
-
-@ CHECK: rsc r1, r2, r3 @ encoding: [0x03,0x10,0xe2,0xe0]
- rsc r1,r2,r3
-
@ CHECK: bfi r0, r0, #5, #7 @ encoding: [0x90,0x02,0xcb,0xe7]
bfi r0, r0, #5, #7
@ CHECK: bkpt #10 @ encoding: [0x7a,0x00,0x20,0xe1]
bkpt #10
-@ CHECK: mrs r8, cpsr @ encoding: [0x00,0x80,0x0f,0xe1]
- mrs r8, cpsr
-
-@ CHECK: mrc p14, #0, r1, c1, c2, #4 @ encoding: [0x92,0x1e,0x11,0xee]
- mrc p14, #0, r1, c1, c2, #4
-@ CHECK: mrrc p7, #1, r5, r4, c1 @ encoding: [0x11,0x57,0x54,0xec]
- mrrc p7, #1, r5, r4, c1
-
-@ CHECK: mrc2 p14, #0, r1, c1, c2, #4 @ encoding: [0x92,0x1e,0x11,0xfe]
- mrc2 p14, #0, r1, c1, c2, #4
-@ CHECK: mrrc2 p7, #1, r5, r4, c1 @ encoding: [0x11,0x57,0x54,0xfc]
- mrrc2 p7, #1, r5, r4, c1
-
@ CHECK: cdp p7, #1, c1, c1, c1, #4 @ encoding: [0x81,0x17,0x11,0xee]
cdp p7, #1, c1, c1, c1, #4
@ CHECK: cdp2 p7, #1, c1, c1, c1, #4 @ encoding: [0x81,0x17,0x11,0xfe]
cdp2 p7, #1, c1, c1, c1, #4
-@ CHECK: qadd r1, r2, r3 @ encoding: [0x52,0x10,0x03,0xe1]
- qadd r1, r2, r3
-
-@ CHECK: qsub r1, r2, r3 @ encoding: [0x52,0x10,0x23,0xe1]
- qsub r1, r2, r3
-
-@ CHECK: qdadd r1, r2, r3 @ encoding: [0x52,0x10,0x43,0xe1]
- qdadd r1, r2, r3
-
-@ CHECK: qdsub r1, r2, r3 @ encoding: [0x52,0x10,0x63,0xe1]
- qdsub r1, r2, r3
-
-@ CHECK: wfe @ encoding: [0x02,0xf0,0x20,0xe3]
- wfe
-
-@ CHECK: wfi @ encoding: [0x03,0xf0,0x20,0xe3]
- wfi
-
-@ CHECK: yield @ encoding: [0x01,0xf0,0x20,0xe3]
- yield
-
-@ CHECK: nop @ encoding: [0x00,0xf0,0x20,0xe3]
- nop
-
-@ CHECK: cpsie aif @ encoding: [0xc0,0x01,0x08,0xf1]
- cpsie aif
-
-@ CHECK: cps #15 @ encoding: [0x0f,0x00,0x02,0xf1]
- cps #15
-
-@ CHECK: cpsie if, #10 @ encoding: [0xca,0x00,0x0a,0xf1]
- cpsie if, #10
-
-@ CHECK: msr cpsr_fc, r0 @ encoding: [0x00,0xf0,0x29,0xe1]
- msr apsr, r0
-
-@ CHECK: msr cpsr_s, r0 @ encoding: [0x00,0xf0,0x24,0xe1]
- msr apsr_g, r0
-
-@ CHECK: msr cpsr_f, r0 @ encoding: [0x00,0xf0,0x28,0xe1]
- msr apsr_nzcvq, r0
-
-@ CHECK: msr cpsr_fs, r0 @ encoding: [0x00,0xf0,0x2c,0xe1]
- msr apsr_nzcvqg, r0
-
-@ CHECK: msr cpsr_fc, r0 @ encoding: [0x00,0xf0,0x29,0xe1]
- msr cpsr_fc, r0
-
-@ CHECK: msr cpsr_c, r0 @ encoding: [0x00,0xf0,0x21,0xe1]
- msr cpsr_c, r0
-
-@ CHECK: msr cpsr_x, r0 @ encoding: [0x00,0xf0,0x22,0xe1]
- msr cpsr_x, r0
-
-@ CHECK: msr cpsr_fc, r0 @ encoding: [0x00,0xf0,0x29,0xe1]
- msr cpsr_fc, r0
-
-@ CHECK: msr cpsr_fc, r0 @ encoding: [0x00,0xf0,0x29,0xe1]
- msr cpsr_all, r0
-
-@ CHECK: msr cpsr_fsx, r0 @ encoding: [0x00,0xf0,0x2e,0xe1]
- msr cpsr_fsx, r0
-
-@ CHECK: msr spsr_fc, r0 @ encoding: [0x00,0xf0,0x69,0xe1]
- msr spsr_fc, r0
-
-@ CHECK: msr spsr_fsxc, r0 @ encoding: [0x00,0xf0,0x6f,0xe1]
- msr spsr_fsxc, r0
-
-@ CHECK: msr cpsr_fsxc, r0 @ encoding: [0x00,0xf0,0x2f,0xe1]
- msr cpsr_fsxc, r0
-
@ CHECK: add r1, r2, r3, lsl r4 @ encoding: [0x13,0x14,0x82,0xe0]
add r1, r2, r3, lsl r4
-@ CHECK: strexb r0, r1, [r2] @ encoding: [0x91,0x0f,0xc2,0xe1]
- strexb r0, r1, [r2]
-
-@ CHECK: strexh r0, r1, [r2] @ encoding: [0x91,0x0f,0xe2,0xe1]
- strexh r0, r1, [r2]
-
-@ CHECK: strex r0, r1, [r2] @ encoding: [0x91,0x0f,0x82,0xe1]
- strex r0, r1, [r2]
-
-@ CHECK: strexd r0, r2, r3, [r1] @ encoding: [0x92,0x0f,0xa1,0xe1]
- strexd r0, r2, r3, [r1]
-
-@ CHECK: ldrexb r0, [r0] @ encoding: [0x9f,0x0f,0xd0,0xe1]
- ldrexb r0, [r0]
-
-@ CHECK: ldrexh r0, [r0] @ encoding: [0x9f,0x0f,0xf0,0xe1]
- ldrexh r0, [r0]
-
-@ CHECK: ldrex r0, [r0] @ encoding: [0x9f,0x0f,0x90,0xe1]
- ldrex r0, [r0]
-
-@ CHECK: ldrexd r0, r1, [r0] @ encoding: [0x9f,0x0f,0xb0,0xe1]
- ldrexd r0, r1, [r0]
-
@ CHECK: ssat16 r0, #7, r0 @ encoding: [0x30,0x0f,0xa6,0xe6]
ssat16 r0, #7, r0
+@ CHECK: cpsie none, #0 @ encoding: [0x00,0x00,0x0a,0xf1]
+ cpsie none, #0
+
diff --git a/test/MC/ARM/basic-arm-instructions.s b/test/MC/ARM/basic-arm-instructions.s
index 0b728bc..55d9f02 100644
--- a/test/MC/ARM/basic-arm-instructions.s
+++ b/test/MC/ARM/basic-arm-instructions.s
@@ -14,18 +14,18 @@ _func:
@------------------------------------------------------------------------------
@ ADC (immediate)
@------------------------------------------------------------------------------
- adc r1, r2, #0xf
- adc r1, r2, #0xf0
- adc r1, r2, #0xf00
- adc r1, r2, #0xf000
- adc r1, r2, #0xf0000
- adc r1, r2, #0xf00000
- adc r1, r2, #0xf000000
- adc r1, r2, #0xf0000000
- adc r1, r2, #0xf000000f
- adcs r1, r2, #0xf00
- adcseq r1, r2, #0xf00
- adceq r1, r2, #0xf00
+ adc r1, r2, #0xf
+ adc r1, r2, #0xf0
+ adc r1, r2, #0xf00
+ adc r1, r2, #0xf000
+ adc r1, r2, #0xf0000
+ adc r1, r2, #0xf00000
+ adc r1, r2, #0xf000000
+ adc r1, r2, #0xf0000000
+ adc r1, r2, #0xf000000f
+ adcs r1, r2, #0xf00
+ adcseq r1, r2, #0xf00
+ adceq r1, r2, #0xf00
@ CHECK: adc r1, r2, #15 @ encoding: [0x0f,0x10,0xa2,0xe2]
@ CHECK: adc r1, r2, #240 @ encoding: [0xf0,0x10,0xa2,0xe2]
@@ -45,44 +45,44 @@ _func:
@ ADC (register)
@ ADC (shifted register)
@------------------------------------------------------------------------------
- adc r4, r5, r6
- @ Constant shifts
- adc r4, r5, r6, lsl #1
- adc r4, r5, r6, lsl #31
- adc r4, r5, r6, lsr #1
- adc r4, r5, r6, lsr #31
- adc r4, r5, r6, lsr #32
- adc r4, r5, r6, asr #1
- adc r4, r5, r6, asr #31
- adc r4, r5, r6, asr #32
- adc r4, r5, r6, ror #1
- adc r4, r5, r6, ror #31
-
- @ Register shifts
- adc r6, r7, r8, lsl r9
- adc r6, r7, r8, lsr r9
- adc r6, r7, r8, asr r9
- adc r6, r7, r8, ror r9
- adc r4, r5, r6, rrx
-
- @ Destination register is optional
- adc r5, r6
- adc r4, r5, lsl #1
- adc r4, r5, lsl #31
- adc r4, r5, lsr #1
- adc r4, r5, lsr #31
- adc r4, r5, lsr #32
- adc r4, r5, asr #1
- adc r4, r5, asr #31
- adc r4, r5, asr #32
- adc r4, r5, ror #1
- adc r4, r5, ror #31
- adc r4, r5, rrx
- adc r6, r7, lsl r9
- adc r6, r7, lsr r9
- adc r6, r7, asr r9
- adc r6, r7, ror r9
- adc r4, r5, rrx
+ adc r4, r5, r6
+ @ Constant shifts
+ adc r4, r5, r6, lsl #1
+ adc r4, r5, r6, lsl #31
+ adc r4, r5, r6, lsr #1
+ adc r4, r5, r6, lsr #31
+ adc r4, r5, r6, lsr #32
+ adc r4, r5, r6, asr #1
+ adc r4, r5, r6, asr #31
+ adc r4, r5, r6, asr #32
+ adc r4, r5, r6, ror #1
+ adc r4, r5, r6, ror #31
+
+ @ Register shifts
+ adc r6, r7, r8, lsl r9
+ adc r6, r7, r8, lsr r9
+ adc r6, r7, r8, asr r9
+ adc r6, r7, r8, ror r9
+ adc r4, r5, r6, rrx
+
+ @ Destination register is optional
+ adc r5, r6
+ adc r4, r5, lsl #1
+ adc r4, r5, lsl #31
+ adc r4, r5, lsr #1
+ adc r4, r5, lsr #31
+ adc r4, r5, lsr #32
+ adc r4, r5, asr #1
+ adc r4, r5, asr #31
+ adc r4, r5, asr #32
+ adc r4, r5, ror #1
+ adc r4, r5, ror #31
+ adc r4, r5, rrx
+ adc r6, r7, lsl r9
+ adc r6, r7, lsr r9
+ adc r6, r7, asr r9
+ adc r6, r7, ror r9
+ adc r4, r5, rrx
@ CHECK: adc r4, r5, r6 @ encoding: [0x06,0x40,0xa5,0xe0]
@@ -123,38 +123,54 @@ _func:
@------------------------------------------------------------------------------
-@ FIXME: ADR
+@ ADR
@------------------------------------------------------------------------------
+Lback:
+ adr r2, Lback
+ adr r3, Lforward
+Lforward:
+ adr r2, #3
+ adr r2, #-3
+
+@ CHECK: Lback:
+@ CHECK: adr r2, Lback @ encoding: [0bAAAAAAA0,0x20'A',0x0f'A',0b1110001A]
+@ CHECK: @ fixup A - offset: 0, value: Lback, kind: fixup_arm_adr_pcrel_12
+@ CHECK: adr r3, Lforward @ encoding: [0bAAAAAAA0,0x30'A',0x0f'A',0b1110001A]
+@ CHECK: @ fixup A - offset: 0, value: Lforward, kind: fixup_arm_adr_pcrel_12
+@ CHECK: Lforward:
+@ CHECK: adr r2, #3 @ encoding: [0x03,0x20,0x8f,0xe2]
+@ CHECK: adr r2, #-3 @ encoding: [0x03,0x20,0x4f,0xe2]
+
@------------------------------------------------------------------------------
@ ADD
@------------------------------------------------------------------------------
- add r4, r5, #0xf000
- add r4, r5, r6
- add r4, r5, r6, lsl #5
- add r4, r5, r6, lsr #5
- add r4, r5, r6, lsr #5
- add r4, r5, r6, asr #5
- add r4, r5, r6, ror #5
- add r6, r7, r8, lsl r9
- add r6, r7, r8, lsr r9
- add r6, r7, r8, asr r9
- add r6, r7, r8, ror r9
- add r4, r5, r6, rrx
-
- @ destination register is optional
- add r5, #0xf000
- add r4, r5
- add r4, r5, lsl #5
- add r4, r5, lsr #5
- add r4, r5, lsr #5
- add r4, r5, asr #5
- add r4, r5, ror #5
- add r6, r7, lsl r9
- add r6, r7, lsr r9
- add r6, r7, asr r9
- add r6, r7, ror r9
- add r4, r5, rrx
+ add r4, r5, #0xf000
+ add r4, r5, r6
+ add r4, r5, r6, lsl #5
+ add r4, r5, r6, lsr #5
+ add r4, r5, r6, lsr #5
+ add r4, r5, r6, asr #5
+ add r4, r5, r6, ror #5
+ add r6, r7, r8, lsl r9
+ add r6, r7, r8, lsr r9
+ add r6, r7, r8, asr r9
+ add r6, r7, r8, ror r9
+ add r4, r5, r6, rrx
+
+ @ destination register is optional
+ add r5, #0xf000
+ add r4, r5
+ add r4, r5, lsl #5
+ add r4, r5, lsr #5
+ add r4, r5, lsr #5
+ add r4, r5, asr #5
+ add r4, r5, ror #5
+ add r6, r7, lsl r9
+ add r6, r7, lsr r9
+ add r6, r7, asr r9
+ add r6, r7, ror r9
+ add r4, r5, rrx
@ CHECK: add r4, r5, #61440 @ encoding: [0x0f,0x4a,0x85,0xe2]
@ CHECK: add r4, r5, r6 @ encoding: [0x06,0x40,0x85,0xe0]
@@ -187,32 +203,32 @@ _func:
@------------------------------------------------------------------------------
@ AND
@------------------------------------------------------------------------------
- and r10, r1, #0xf
- and r10, r1, r6
- and r10, r1, r6, lsl #10
- and r10, r1, r6, lsr #10
- and r10, r1, r6, lsr #10
- and r10, r1, r6, asr #10
- and r10, r1, r6, ror #10
- and r6, r7, r8, lsl r2
- and r6, r7, r8, lsr r2
- and r6, r7, r8, asr r2
- and r6, r7, r8, ror r2
- and r10, r1, r6, rrx
-
- @ destination register is optional
- and r1, #0xf
- and r10, r1
- and r10, r1, lsl #10
- and r10, r1, lsr #10
- and r10, r1, lsr #10
- and r10, r1, asr #10
- and r10, r1, ror #10
- and r6, r7, lsl r2
- and r6, r7, lsr r2
- and r6, r7, asr r2
- and r6, r7, ror r2
- and r10, r1, rrx
+ and r10, r1, #0xf
+ and r10, r1, r6
+ and r10, r1, r6, lsl #10
+ and r10, r1, r6, lsr #10
+ and r10, r1, r6, lsr #10
+ and r10, r1, r6, asr #10
+ and r10, r1, r6, ror #10
+ and r6, r7, r8, lsl r2
+ and r6, r7, r8, lsr r2
+ and r6, r7, r8, asr r2
+ and r6, r7, r8, ror r2
+ and r10, r1, r6, rrx
+
+ @ destination register is optional
+ and r1, #0xf
+ and r10, r1
+ and r10, r1, lsl #10
+ and r10, r1, lsr #10
+ and r10, r1, lsr #10
+ and r10, r1, asr #10
+ and r10, r1, ror #10
+ and r6, r7, lsl r2
+ and r6, r7, lsr r2
+ and r6, r7, asr r2
+ and r6, r7, ror r2
+ and r10, r1, rrx
@ CHECK: and r10, r1, #15 @ encoding: [0x0f,0xa0,0x01,0xe2]
@ CHECK: and r10, r1, r6 @ encoding: [0x06,0xa0,0x01,0xe0]
@@ -244,44 +260,66 @@ _func:
@ FIXME: ASR
@------------------------------------------------------------------------------
@------------------------------------------------------------------------------
-@ FIXME: B
+@ B
@------------------------------------------------------------------------------
+ b _bar
+ beq _baz
+
+@ CHECK: b _bar @ encoding: [A,A,A,0xea]
+ @ fixup A - offset: 0, value: _bar, kind: fixup_arm_uncondbranch
+@ CHECK: beq _baz @ encoding: [A,A,A,0x0a]
+ @ fixup A - offset: 0, value: _baz, kind: fixup_arm_condbranch
+
+
@------------------------------------------------------------------------------
-@ FIXME: BFC
+@ BFC
@------------------------------------------------------------------------------
+ bfc r5, #3, #17
+ bfccc r5, #3, #17
+
+@ CHECK: bfc r5, #3, #17 @ encoding: [0x9f,0x51,0xd3,0xe7]
+@ CHECK: bfclo r5, #3, #17 @ encoding: [0x9f,0x51,0xd3,0x37]
+
+
@------------------------------------------------------------------------------
-@ FIXME: BFI
+@ BFI
@------------------------------------------------------------------------------
+ bfi r5, r2, #3, #17
+ bfine r5, r2, #3, #17
+
+@ CHECK: bfi r5, r2, #3, #17 @ encoding: [0x92,0x51,0xd3,0xe7]
+@ CHECK: bfine r5, r2, #3, #17 @ encoding: [0x92,0x51,0xd3,0x17]
+
@------------------------------------------------------------------------------
@ BIC
@------------------------------------------------------------------------------
- bic r10, r1, #0xf
- bic r10, r1, r6
- bic r10, r1, r6, lsl #10
- bic r10, r1, r6, lsr #10
- bic r10, r1, r6, lsr #10
- bic r10, r1, r6, asr #10
- bic r10, r1, r6, ror #10
- bic r6, r7, r8, lsl r2
- bic r6, r7, r8, lsr r2
- bic r6, r7, r8, asr r2
- bic r6, r7, r8, ror r2
- bic r10, r1, r6, rrx
-
- @ destination register is optional
- bic r1, #0xf
- bic r10, r1
- bic r10, r1, lsl #10
- bic r10, r1, lsr #10
- bic r10, r1, lsr #10
- bic r10, r1, asr #10
- bic r10, r1, ror #10
- bic r6, r7, lsl r2
- bic r6, r7, lsr r2
- bic r6, r7, asr r2
- bic r6, r7, ror r2
- bic r10, r1, rrx
+ bic r10, r1, #0xf
+ bic r10, r1, r6
+ bic r10, r1, r6, lsl #10
+ bic r10, r1, r6, lsr #10
+ bic r10, r1, r6, lsr #10
+ bic r10, r1, r6, asr #10
+ bic r10, r1, r6, ror #10
+ bic r6, r7, r8, lsl r2
+ bic r6, r7, r8, lsr r2
+ bic r6, r7, r8, asr r2
+ bic r6, r7, r8, ror r2
+ bic r10, r1, r6, rrx
+
+ @ destination register is optional
+ bic r1, #0xf
+ bic r10, r1
+ bic r10, r1, lsl #10
+ bic r10, r1, lsr #10
+ bic r10, r1, lsr #10
+ bic r10, r1, asr #10
+ bic r10, r1, ror #10
+ bic r6, r7, lsl r2
+ bic r6, r7, lsr r2
+ bic r6, r7, asr r2
+ bic r6, r7, ror r2
+ bic r10, r1, rrx
@ CHECK: bic r10, r1, #15 @ encoding: [0x0f,0xa0,0xc1,0xe3]
@ CHECK: bic r10, r1, r6 @ encoding: [0x06,0xa0,0xc1,0xe1]
@@ -313,8 +351,8 @@ _func:
@------------------------------------------------------------------------------
@ BKPT
@------------------------------------------------------------------------------
- bkpt #10
- bkpt #65535
+ bkpt #10
+ bkpt #65535
@ CHECK: bkpt #10 @ encoding: [0x7a,0x00,0x20,0xe1]
@ CHECK: bkpt #65535 @ encoding: [0x7f,0xff,0x2f,0xe1]
@@ -323,17 +361,24 @@ _func:
@ BL/BLX (immediate)
@------------------------------------------------------------------------------
- bl _bar
- @ FIXME: blx _bar
+ bl _bar
+ blx _bar
+ blls #28634268
+ blx #32424576
+ blx #16212288
@ CHECK: bl _bar @ encoding: [A,A,A,0xeb]
@ CHECK: @ fixup A - offset: 0, value: _bar, kind: fixup_arm_uncondbranch
-
+@ CHECK: blx _bar @ encoding: [A,A,A,0xfa]
+ @ fixup A - offset: 0, value: _bar, kind: fixup_arm_uncondbranch
+@ CHECK: blls #28634268 @ encoding: [0x27,0x3b,0x6d,0x9b]
+@ CHECK: blx #32424576 @ encoding: [0xa0,0xb0,0x7b,0xfa]
+@ CHECK: blx #16212288 @ encoding: [0x50,0xd8,0x3d,0xfa]
@------------------------------------------------------------------------------
@ BLX (register)
@------------------------------------------------------------------------------
- blx r2
- blxne r2
+ blx r2
+ blxne r2
@ CHECK: blx r2 @ encoding: [0x32,0xff,0x2f,0xe1]
@ CHECK: blxne r2 @ encoding: [0x32,0xff,0x2f,0x11]
@@ -341,9 +386,8 @@ _func:
@------------------------------------------------------------------------------
@ BX
@------------------------------------------------------------------------------
-
- bx r2
- bxne r2
+ bx r2
+ bxne r2
@ CHECK: bx r2 @ encoding: [0x12,0xff,0x2f,0xe1]
@ CHECK: bxne r2 @ encoding: [0x12,0xff,0x2f,0x11]
@@ -351,23 +395,18 @@ _func:
@------------------------------------------------------------------------------
@ BXJ
@------------------------------------------------------------------------------
-
- bxj r2
- bxjne r2
+ bxj r2
+ bxjne r2
@ CHECK: bxj r2 @ encoding: [0x22,0xff,0x2f,0xe1]
@ CHECK: bxjne r2 @ encoding: [0x22,0xff,0x2f,0x11]
-@------------------------------------------------------------------------------
-@ FIXME: CBNZ/CBZ
-@------------------------------------------------------------------------------
-
@------------------------------------------------------------------------------
@ CDP/CDP2
@------------------------------------------------------------------------------
- cdp p7, #1, c1, c1, c1, #4
- cdp2 p7, #1, c1, c1, c1, #4
+ cdp p7, #1, c1, c1, c1, #4
+ cdp2 p7, #1, c1, c1, c1, #4
@ CHECK: cdp p7, #1, c1, c1, c1, #4 @ encoding: [0x81,0x17,0x11,0xee]
@ CHECK: cdp2 p7, #1, c1, c1, c1, #4 @ encoding: [0x81,0x17,0x11,0xfe]
@@ -376,7 +415,7 @@ _func:
@------------------------------------------------------------------------------
@ CLREX
@------------------------------------------------------------------------------
- clrex
+ clrex
@ CHECK: clrex @ encoding: [0x1f,0xf0,0x7f,0xf5]
@@ -384,8 +423,8 @@ _func:
@------------------------------------------------------------------------------
@ CLZ
@------------------------------------------------------------------------------
- clz r1, r2
- clzeq r1, r2
+ clz r1, r2
+ clzeq r1, r2
@ CHECK: clz r1, r2 @ encoding: [0x12,0x1f,0x6f,0xe1]
@ CHECK: clzeq r1, r2 @ encoding: [0x12,0x1f,0x6f,0x01]
@@ -393,18 +432,18 @@ _func:
@------------------------------------------------------------------------------
@ CMN
@------------------------------------------------------------------------------
- cmn r1, #0xf
- cmn r1, r6
- cmn r1, r6, lsl #10
- cmn r1, r6, lsr #10
- cmn sp, r6, lsr #10
- cmn r1, r6, asr #10
- cmn r1, r6, ror #10
- cmn r7, r8, lsl r2
- cmn sp, r8, lsr r2
- cmn r7, r8, asr r2
- cmn r7, r8, ror r2
- cmn r1, r6, rrx
+ cmn r1, #0xf
+ cmn r1, r6
+ cmn r1, r6, lsl #10
+ cmn r1, r6, lsr #10
+ cmn sp, r6, lsr #10
+ cmn r1, r6, asr #10
+ cmn r1, r6, ror #10
+ cmn r7, r8, lsl r2
+ cmn sp, r8, lsr r2
+ cmn r7, r8, asr r2
+ cmn r7, r8, ror r2
+ cmn r1, r6, rrx
@ CHECK: cmn r1, #15 @ encoding: [0x0f,0x00,0x71,0xe3]
@ CHECK: cmn r1, r6 @ encoding: [0x06,0x00,0x71,0xe1]
@@ -422,18 +461,18 @@ _func:
@------------------------------------------------------------------------------
@ CMP
@------------------------------------------------------------------------------
- cmp r1, #0xf
- cmp r1, r6
- cmp r1, r6, lsl #10
- cmp r1, r6, lsr #10
- cmp sp, r6, lsr #10
- cmp r1, r6, asr #10
- cmp r1, r6, ror #10
- cmp r7, r8, lsl r2
- cmp sp, r8, lsr r2
- cmp r7, r8, asr r2
- cmp r7, r8, ror r2
- cmp r1, r6, rrx
+ cmp r1, #0xf
+ cmp r1, r6
+ cmp r1, r6, lsl #10
+ cmp r1, r6, lsr #10
+ cmp sp, r6, lsr #10
+ cmp r1, r6, asr #10
+ cmp r1, r6, ror #10
+ cmp r7, r8, lsl r2
+ cmp sp, r8, lsr r2
+ cmp r7, r8, asr r2
+ cmp r7, r8, ror r2
+ cmp r1, r6, rrx
@ CHECK: cmp r1, #15 @ encoding: [0x0f,0x00,0x51,0xe3]
@ CHECK: cmp r1, r6 @ encoding: [0x06,0x00,0x51,0xe1]
@@ -448,12 +487,25 @@ _func:
@ CHECK: cmp r7, r8, ror r2 @ encoding: [0x78,0x02,0x57,0xe1]
@ CHECK: cmp r1, r6, rrx @ encoding: [0x66,0x00,0x51,0xe1]
+
+@------------------------------------------------------------------------------
+@ CPS
+@------------------------------------------------------------------------------
+ cpsie aif
+ cps #15
+ cpsid if, #10
+
+@ CHECK: cpsie aif @ encoding: [0xc0,0x01,0x08,0xf1]
+@ CHECK: cps #15 @ encoding: [0x0f,0x00,0x02,0xf1]
+@ CHECK: cpsid if, #10 @ encoding: [0xca,0x00,0x0e,0xf1]
+
+
@------------------------------------------------------------------------------
@ DBG
@------------------------------------------------------------------------------
- dbg #0
- dbg #5
- dbg #15
+ dbg #0
+ dbg #5
+ dbg #15
@ CHECK: dbg #0 @ encoding: [0xf0,0xf0,0x20,0xe3]
@ CHECK: dbg #5 @ encoding: [0xf5,0xf0,0x20,0xe3]
@@ -463,19 +515,19 @@ _func:
@------------------------------------------------------------------------------
@ DMB
@------------------------------------------------------------------------------
- dmb sy
- dmb st
- dmb sh
- dmb ish
- dmb shst
- dmb ishst
- dmb un
- dmb nsh
- dmb unst
- dmb nshst
- dmb osh
- dmb oshst
- dmb
+ dmb sy
+ dmb st
+ dmb sh
+ dmb ish
+ dmb shst
+ dmb ishst
+ dmb un
+ dmb nsh
+ dmb unst
+ dmb nshst
+ dmb osh
+ dmb oshst
+ dmb
@ CHECK: dmb sy @ encoding: [0x5f,0xf0,0x7f,0xf5]
@ CHECK: dmb st @ encoding: [0x5e,0xf0,0x7f,0xf5]
@@ -494,19 +546,19 @@ _func:
@------------------------------------------------------------------------------
@ DSB
@------------------------------------------------------------------------------
- dsb sy
- dsb st
- dsb sh
- dsb ish
- dsb shst
- dsb ishst
- dsb un
- dsb nsh
- dsb unst
- dsb nshst
- dsb osh
- dsb oshst
- dsb
+ dsb sy
+ dsb st
+ dsb sh
+ dsb ish
+ dsb shst
+ dsb ishst
+ dsb un
+ dsb nsh
+ dsb unst
+ dsb nshst
+ dsb osh
+ dsb oshst
+ dsb
@ CHECK: dsb sy @ encoding: [0x4f,0xf0,0x7f,0xf5]
@ CHECK: dsb st @ encoding: [0x4e,0xf0,0x7f,0xf5]
@@ -525,32 +577,32 @@ _func:
@------------------------------------------------------------------------------
@ EOR
@------------------------------------------------------------------------------
- eor r4, r5, #0xf000
- eor r4, r5, r6
- eor r4, r5, r6, lsl #5
- eor r4, r5, r6, lsr #5
- eor r4, r5, r6, lsr #5
- eor r4, r5, r6, asr #5
- eor r4, r5, r6, ror #5
- eor r6, r7, r8, lsl r9
- eor r6, r7, r8, lsr r9
- eor r6, r7, r8, asr r9
- eor r6, r7, r8, ror r9
- eor r4, r5, r6, rrx
-
- @ destination register is optional
- eor r5, #0xf000
- eor r4, r5
- eor r4, r5, lsl #5
- eor r4, r5, lsr #5
- eor r4, r5, lsr #5
- eor r4, r5, asr #5
- eor r4, r5, ror #5
- eor r6, r7, lsl r9
- eor r6, r7, lsr r9
- eor r6, r7, asr r9
- eor r6, r7, ror r9
- eor r4, r5, rrx
+ eor r4, r5, #0xf000
+ eor r4, r5, r6
+ eor r4, r5, r6, lsl #5
+ eor r4, r5, r6, lsr #5
+ eor r4, r5, r6, lsr #5
+ eor r4, r5, r6, asr #5
+ eor r4, r5, r6, ror #5
+ eor r6, r7, r8, lsl r9
+ eor r6, r7, r8, lsr r9
+ eor r6, r7, r8, asr r9
+ eor r6, r7, r8, ror r9
+ eor r4, r5, r6, rrx
+
+ @ destination register is optional
+ eor r5, #0xf000
+ eor r4, r5
+ eor r4, r5, lsl #5
+ eor r4, r5, lsr #5
+ eor r4, r5, lsr #5
+ eor r4, r5, asr #5
+ eor r4, r5, ror #5
+ eor r6, r7, lsl r9
+ eor r6, r7, lsr r9
+ eor r6, r7, asr r9
+ eor r6, r7, ror r9
+ eor r4, r5, rrx
@ CHECK: eor r4, r5, #61440 @ encoding: [0x0f,0x4a,0x25,0xe2]
@ CHECK: eor r4, r5, r6 @ encoding: [0x06,0x40,0x25,0xe0]
@@ -590,6 +642,91 @@ _func:
@ CHECK: isb sy @ encoding: [0x6f,0xf0,0x7f,0xf5]
+@------------------------------------------------------------------------------
+@ LDC{L}/LDC2{L}
+@------------------------------------------------------------------------------
+ ldc2 p0, c8, [r1, #4]
+ ldc2 p1, c7, [r2]
+ ldc2 p2, c6, [r3, #-224]
+ ldc2 p3, c5, [r4, #-120]!
+ ldc2 p4, c4, [r5], #16
+ ldc2 p5, c3, [r6], #-72
+ ldc2l p6, c2, [r7, #4]
+ ldc2l p7, c1, [r8]
+ ldc2l p8, c0, [r9, #-224]
+ ldc2l p9, c1, [r10, #-120]!
+ ldc2l p10, c2, [r11], #16
+ ldc2l p11, c3, [r12], #-72
+
+ ldc p12, c4, [r0, #4]
+ ldc p13, c5, [r1]
+ ldc p14, c6, [r2, #-224]
+ ldc p15, c7, [r3, #-120]!
+ ldc p5, c8, [r4], #16
+ ldc p4, c9, [r5], #-72
+ ldcl p3, c10, [r6, #4]
+ ldcl p2, c11, [r7]
+ ldcl p1, c12, [r8, #-224]
+ ldcl p0, c13, [r9, #-120]!
+ ldcl p6, c14, [r10], #16
+ ldcl p7, c15, [r11], #-72
+
+ ldclo p12, c4, [r0, #4]
+ ldchi p13, c5, [r1]
+ ldccs p14, c6, [r2, #-224]
+ ldccc p15, c7, [r3, #-120]!
+ ldceq p5, c8, [r4], #16
+ ldcgt p4, c9, [r5], #-72
+ ldcllt p3, c10, [r6, #4]
+ ldclge p2, c11, [r7]
+ ldclle p1, c12, [r8, #-224]
+ ldclne p0, c13, [r9, #-120]!
+ ldcleq p6, c14, [r10], #16
+ ldclhi p7, c15, [r11], #-72
+
+ ldc2 p2, c8, [r1], { 25 }
+
+@ CHECK: ldc2 p0, c8, [r1, #4] @ encoding: [0x01,0x80,0x91,0xfd]
+@ CHECK: ldc2 p1, c7, [r2] @ encoding: [0x00,0x71,0x92,0xfd]
+@ CHECK: ldc2 p2, c6, [r3, #-224] @ encoding: [0x38,0x62,0x13,0xfd]
+@ CHECK: ldc2 p3, c5, [r4, #-120]! @ encoding: [0x1e,0x53,0x34,0xfd]
+@ CHECK: ldc2 p4, c4, [r5], #16 @ encoding: [0x04,0x44,0xb5,0xfc]
+@ CHECK: ldc2 p5, c3, [r6], #-72 @ encoding: [0x12,0x35,0x36,0xfc]
+@ CHECK: ldc2l p6, c2, [r7, #4] @ encoding: [0x01,0x26,0xd7,0xfd]
+@ CHECK: ldc2l p7, c1, [r8] @ encoding: [0x00,0x17,0xd8,0xfd]
+@ CHECK: ldc2l p8, c0, [r9, #-224] @ encoding: [0x38,0x08,0x59,0xfd]
+@ CHECK: ldc2l p9, c1, [r10, #-120]! @ encoding: [0x1e,0x19,0x7a,0xfd]
+@ CHECK: ldc2l p10, c2, [r11], #16 @ encoding: [0x04,0x2a,0xfb,0xfc]
+@ CHECK: ldc2l p11, c3, [r12], #-72 @ encoding: [0x12,0x3b,0x7c,0xfc]
+
+@ CHECK: ldc p12, c4, [r0, #4] @ encoding: [0x01,0x4c,0x90,0xed]
+@ CHECK: ldc p13, c5, [r1] @ encoding: [0x00,0x5d,0x91,0xed]
+@ CHECK: ldc p14, c6, [r2, #-224] @ encoding: [0x38,0x6e,0x12,0xed]
+@ CHECK: ldc p15, c7, [r3, #-120]! @ encoding: [0x1e,0x7f,0x33,0xed]
+@ CHECK: ldc p5, c8, [r4], #16 @ encoding: [0x04,0x85,0xb4,0xec]
+@ CHECK: ldc p4, c9, [r5], #-72 @ encoding: [0x12,0x94,0x35,0xec]
+@ CHECK: ldcl p3, c10, [r6, #4] @ encoding: [0x01,0xa3,0xd6,0xed]
+@ CHECK: ldcl p2, c11, [r7] @ encoding: [0x00,0xb2,0xd7,0xed]
+@ CHECK: ldcl p1, c12, [r8, #-224] @ encoding: [0x38,0xc1,0x58,0xed]
+@ CHECK: ldcl p0, c13, [r9, #-120]! @ encoding: [0x1e,0xd0,0x79,0xed]
+@ CHECK: ldcl p6, c14, [r10], #16 @ encoding: [0x04,0xe6,0xfa,0xec]
+@ CHECK: ldcl p7, c15, [r11], #-72 @ encoding: [0x12,0xf7,0x7b,0xec]
+
+@ CHECK: ldclo p12, c4, [r0, #4] @ encoding: [0x01,0x4c,0x90,0x3d]
+@ CHECK: ldchi p13, c5, [r1] @ encoding: [0x00,0x5d,0x91,0x8d]
+@ CHECK: ldchs p14, c6, [r2, #-224] @ encoding: [0x38,0x6e,0x12,0x2d]
+@ CHECK: ldclo p15, c7, [r3, #-120]! @ encoding: [0x1e,0x7f,0x33,0x3d]
+@ CHECK: ldceq p5, c8, [r4], #16 @ encoding: [0x04,0x85,0xb4,0x0c]
+@ CHECK: ldcgt p4, c9, [r5], #-72 @ encoding: [0x12,0x94,0x35,0xcc]
+@ CHECK: ldcllt p3, c10, [r6, #4] @ encoding: [0x01,0xa3,0xd6,0xbd]
+@ CHECK: ldclge p2, c11, [r7] @ encoding: [0x00,0xb2,0xd7,0xad]
+@ CHECK: ldclle p1, c12, [r8, #-224] @ encoding: [0x38,0xc1,0x58,0xdd]
+@ CHECK: ldclne p0, c13, [r9, #-120]! @ encoding: [0x1e,0xd0,0x79,0x1d]
+@ CHECK: ldcleq p6, c14, [r10], #16 @ encoding: [0x04,0xe6,0xfa,0x0c]
+@ CHECK: ldclhi p7, c15, [r11], #-72 @ encoding: [0x12,0xf7,0x7b,0x8c]
+
+@ CHECK: ldc2 p2, c8, [r1], {25} @ encoding: [0x19,0x82,0x91,0xfc]
+
@------------------------------------------------------------------------------
@ LDM*
@@ -619,9 +756,29 @@ _func:
@ CHECK: ldmda r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x32,0xe8]
@ CHECK: ldmdb r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x32,0xe9]
+
+@------------------------------------------------------------------------------
+@ LDREX/LDREXB/LDREXH/LDREXD
+@------------------------------------------------------------------------------
+ ldrexb r3, [r4]
+ ldrexh r2, [r5]
+ ldrex r1, [r7]
+ ldrexd r6, r7, [r8]
+
+@ CHECK: ldrexb r3, [r4] @ encoding: [0x9f,0x3f,0xd4,0xe1]
+@ CHECK: ldrexh r2, [r5] @ encoding: [0x9f,0x2f,0xf5,0xe1]
+@ CHECK: ldrex r1, [r7] @ encoding: [0x9f,0x1f,0x97,0xe1]
+@ CHECK: ldrexd r6, r7, [r8] @ encoding: [0x9f,0x6f,0xb8,0xe1]
+
@------------------------------------------------------------------------------
-@ FIXME: LDR*
+@ LDRHT
@------------------------------------------------------------------------------
+ ldrhthi r8, [r11], #-0
+ ldrhthi r8, [r11], #0
+
+@ CHECK: ldrhthi r8, [r11], #-0 @ encoding: [0xb0,0x80,0x7b,0x80]
+@ CHECK: ldrhthi r8, [r11], #0 @ encoding: [0xb0,0x80,0xfb,0x80]
+
@------------------------------------------------------------------------------
@ FIXME: LSL
@------------------------------------------------------------------------------
@@ -635,8 +792,8 @@ _func:
mcr p7, #1, r5, c1, c1, #4
mcr2 p7, #1, r5, c1, c1, #4
-@ CHECK: mcr p7, #1, r5, c1, c1, #4 @ encoding: [0x91,0x57,0x21,0xee]
-@ CHECK: mcr2 p7, #1, r5, c1, c1, #4 @ encoding: [0x91,0x57,0x21,0xfe]
+@ CHECK: mcr p7, #1, r5, c1, c1, #4 @ encoding: [0x91,0x57,0x21,0xee]
+@ CHECK: mcr2 p7, #1, r5, c1, c1, #4 @ encoding: [0x91,0x57,0x21,0xfe]
@------------------------------------------------------------------------------
@ MCRR/MCRR2
@@ -644,8 +801,8 @@ _func:
mcrr p7, #15, r5, r4, c1
mcrr2 p7, #15, r5, r4, c1
-@ CHECK: mcrr p7, #15, r5, r4, c1 @ encoding: [0xf1,0x57,0x44,0xec]
-@ CHECK: mcrr2 p7, #15, r5, r4, c1 @ encoding: [0xf1,0x57,0x44,0xfc]
+@ CHECK: mcrr p7, #15, r5, r4, c1 @ encoding: [0xf1,0x57,0x44,0xec]
+@ CHECK: mcrr2 p7, #15, r5, r4, c1 @ encoding: [0xf1,0x57,0x44,0xfc]
@------------------------------------------------------------------------------
@@ -656,10 +813,10 @@ _func:
mlane r1,r2,r3,r4
mlasne r1,r2,r3,r4
-@ CHECK: mla r1, r2, r3, r4 @ encoding: [0x92,0x43,0x21,0xe0]
-@ CHECK: mlas r1, r2, r3, r4 @ encoding: [0x92,0x43,0x31,0xe0]
-@ CHECK: mlane r1, r2, r3, r4 @ encoding: [0x92,0x43,0x21,0x10]
-@ CHECK: mlasne r1, r2, r3, r4 @ encoding: [0x92,0x43,0x31,0x10]
+@ CHECK: mla r1, r2, r3, r4 @ encoding: [0x92,0x43,0x21,0xe0]
+@ CHECK: mlas r1, r2, r3, r4 @ encoding: [0x92,0x43,0x31,0xe0]
+@ CHECK: mlane r1, r2, r3, r4 @ encoding: [0x92,0x43,0x21,0x10]
+@ CHECK: mlasne r1, r2, r3, r4 @ encoding: [0x92,0x43,0x31,0x10]
@------------------------------------------------------------------------------
@ MLS
@@ -671,28 +828,1799 @@ _func:
@ CHECK: mlsne r2, r5, r6, r3 @ encoding: [0x95,0x36,0x62,0x10]
@------------------------------------------------------------------------------
+@ MOV (immediate)
+@------------------------------------------------------------------------------
+ mov r3, #7
+ mov r4, #0xff0
+ mov r5, #0xff0000
+ mov r6, #0xffff
+ movw r9, #0xffff
+ movs r3, #7
+ moveq r4, #0xff0
+ movseq r5, #0xff0000
+
+@ CHECK: mov r3, #7 @ encoding: [0x07,0x30,0xa0,0xe3]
+@ CHECK: mov r4, #4080 @ encoding: [0xff,0x4e,0xa0,0xe3]
+@ CHECK: mov r5, #16711680 @ encoding: [0xff,0x58,0xa0,0xe3]
+@ CHECK: movw r6, #65535 @ encoding: [0xff,0x6f,0x0f,0xe3]
+@ CHECK: movw r9, #65535 @ encoding: [0xff,0x9f,0x0f,0xe3]
+@ CHECK: movs r3, #7 @ encoding: [0x07,0x30,0xb0,0xe3]
+@ CHECK: moveq r4, #4080 @ encoding: [0xff,0x4e,0xa0,0x03]
+@ CHECK: movseq r5, #16711680 @ encoding: [0xff,0x58,0xb0,0x03]
+
+@------------------------------------------------------------------------------
+@ MOV (register)
+@------------------------------------------------------------------------------
+ mov r2, r3
+ movs r2, r3
+ moveq r2, r3
+ movseq r2, r3
+
+@ CHECK: mov r2, r3 @ encoding: [0x03,0x20,0xa0,0xe1]
+@ CHECK: movs r2, r3 @ encoding: [0x03,0x20,0xb0,0xe1]
+@ CHECK: moveq r2, r3 @ encoding: [0x03,0x20,0xa0,0x01]
+@ CHECK: movseq r2, r3 @ encoding: [0x03,0x20,0xb0,0x01]
+
+@------------------------------------------------------------------------------
+@ MOVT
+@------------------------------------------------------------------------------
+ movt r3, #7
+ movt r6, #0xffff
+ movteq r4, #0xff0
+
+@ CHECK: movt r3, #7 @ encoding: [0x07,0x30,0x40,0xe3]
+@ CHECK: movt r6, #65535 @ encoding: [0xff,0x6f,0x4f,0xe3]
+@ CHECK: movteq r4, #4080 @ encoding: [0xf0,0x4f,0x40,0x03]
+
+
+@------------------------------------------------------------------------------
+@ MRC/MRC2
+@------------------------------------------------------------------------------
+ mrc p14, #0, r1, c1, c2, #4
+ mrc2 p14, #0, r1, c1, c2, #4
+
+@ CHECK: mrc p14, #0, r1, c1, c2, #4 @ encoding: [0x92,0x1e,0x11,0xee]
+@ CHECK: mrc2 p14, #0, r1, c1, c2, #4 @ encoding: [0x92,0x1e,0x11,0xfe]
+
+@------------------------------------------------------------------------------
+@ MRRC/MRRC2
+@------------------------------------------------------------------------------
+ mrrc p7, #1, r5, r4, c1
+ mrrc2 p7, #1, r5, r4, c1
+
+@ CHECK: mrrc p7, #1, r5, r4, c1 @ encoding: [0x11,0x57,0x54,0xec]
+@ CHECK: mrrc2 p7, #1, r5, r4, c1 @ encoding: [0x11,0x57,0x54,0xfc]
+
+
+@------------------------------------------------------------------------------
+@ MRS
+@------------------------------------------------------------------------------
+ mrs r8, apsr
+ mrs r8, cpsr
+ mrs r8, spsr
+@ CHECK: mrs r8, apsr @ encoding: [0x00,0x80,0x0f,0xe1]
+@ CHECK: mrs r8, apsr @ encoding: [0x00,0x80,0x0f,0xe1]
+@ CHECK: mrs r8, spsr @ encoding: [0x00,0x80,0x4f,0xe1]
+
+
+
+@------------------------------------------------------------------------------
+@ MSR
+@------------------------------------------------------------------------------
+
+ msr apsr, #5
+ msr apsr_g, #5
+ msr apsr_nzcvq, #5
+ msr APSR_nzcvq, #5
+ msr apsr_nzcvqg, #5
+ msr cpsr_fc, #5
+ msr cpsr_c, #5
+ msr cpsr_x, #5
+ msr cpsr_fc, #5
+ msr cpsr_all, #5
+ msr cpsr_fsx, #5
+ msr spsr_fc, #5
+ msr SPSR_fsxc, #5
+ msr cpsr_fsxc, #5
+
+@ CHECK: msr APSR_nzcvq, #5 @ encoding: [0x05,0xf0,0x28,0xe3]
+@ CHECK: msr APSR_g, #5 @ encoding: [0x05,0xf0,0x24,0xe3]
+@ CHECK: msr APSR_nzcvq, #5 @ encoding: [0x05,0xf0,0x28,0xe3]
+@ CHECK: msr APSR_nzcvq, #5 @ encoding: [0x05,0xf0,0x28,0xe3]
+@ CHECK: msr APSR_nzcvqg, #5 @ encoding: [0x05,0xf0,0x2c,0xe3]
+@ CHECK: msr CPSR_fc, #5 @ encoding: [0x05,0xf0,0x29,0xe3]
+@ CHECK: msr CPSR_c, #5 @ encoding: [0x05,0xf0,0x21,0xe3]
+@ CHECK: msr CPSR_x, #5 @ encoding: [0x05,0xf0,0x22,0xe3]
+@ CHECK: msr CPSR_fc, #5 @ encoding: [0x05,0xf0,0x29,0xe3]
+@ CHECK: msr CPSR_fc, #5 @ encoding: [0x05,0xf0,0x29,0xe3]
+@ CHECK: msr CPSR_fsx, #5 @ encoding: [0x05,0xf0,0x2e,0xe3]
+@ CHECK: msr SPSR_fc, #5 @ encoding: [0x05,0xf0,0x69,0xe3]
+@ CHECK: msr SPSR_fsxc, #5 @ encoding: [0x05,0xf0,0x6f,0xe3]
+@ CHECK: msr CPSR_fsxc, #5 @ encoding: [0x05,0xf0,0x2f,0xe3]
+
+ msr apsr, r0
+ msr apsr_g, r0
+ msr apsr_nzcvq, r0
+ msr APSR_nzcvq, r0
+ msr apsr_nzcvqg, r0
+ msr cpsr_fc, r0
+ msr cpsr_c, r0
+ msr cpsr_x, r0
+ msr cpsr_fc, r0
+ msr cpsr_all, r0
+ msr cpsr_fsx, r0
+ msr spsr_fc, r0
+ msr SPSR_fsxc, r0
+ msr cpsr_fsxc, r0
+
+@ CHECK: msr APSR_nzcvq, r0 @ encoding: [0x00,0xf0,0x28,0xe1]
+@ CHECK: msr APSR_g, r0 @ encoding: [0x00,0xf0,0x24,0xe1]
+@ CHECK: msr APSR_nzcvq, r0 @ encoding: [0x00,0xf0,0x28,0xe1]
+@ CHECK: msr APSR_nzcvq, r0 @ encoding: [0x00,0xf0,0x28,0xe1]
+@ CHECK: msr APSR_nzcvqg, r0 @ encoding: [0x00,0xf0,0x2c,0xe1]
+@ CHECK: msr CPSR_fc, r0 @ encoding: [0x00,0xf0,0x29,0xe1]
+@ CHECK: msr CPSR_c, r0 @ encoding: [0x00,0xf0,0x21,0xe1]
+@ CHECK: msr CPSR_x, r0 @ encoding: [0x00,0xf0,0x22,0xe1]
+@ CHECK: msr CPSR_fc, r0 @ encoding: [0x00,0xf0,0x29,0xe1]
+@ CHECK: msr CPSR_fc, r0 @ encoding: [0x00,0xf0,0x29,0xe1]
+@ CHECK: msr CPSR_fsx, r0 @ encoding: [0x00,0xf0,0x2e,0xe1]
+@ CHECK: msr SPSR_fc, r0 @ encoding: [0x00,0xf0,0x69,0xe1]
+@ CHECK: msr SPSR_fsxc, r0 @ encoding: [0x00,0xf0,0x6f,0xe1]
+@ CHECK: msr CPSR_fsxc, r0 @ encoding: [0x00,0xf0,0x2f,0xe1]
+
+@------------------------------------------------------------------------------
+@ MUL
+@------------------------------------------------------------------------------
+ mul r5, r6, r7
+ muls r5, r6, r7
+ mulgt r5, r6, r7
+ mulsle r5, r6, r7
+
+@ CHECK: mul r5, r6, r7 @ encoding: [0x96,0x07,0x05,0xe0]
+@ CHECK: muls r5, r6, r7 @ encoding: [0x96,0x07,0x15,0xe0]
+@ CHECK: mulgt r5, r6, r7 @ encoding: [0x96,0x07,0x05,0xc0]
+@ CHECK: mulsle r5, r6, r7 @ encoding: [0x96,0x07,0x15,0xd0]
+
+
+@------------------------------------------------------------------------------
+@ MVN (immediate)
+@------------------------------------------------------------------------------
+ mvn r3, #7
+ mvn r4, #0xff0
+ mvn r5, #0xff0000
+ mvns r3, #7
+ mvneq r4, #0xff0
+ mvnseq r5, #0xff0000
+
+@ CHECK: mvn r3, #7 @ encoding: [0x07,0x30,0xe0,0xe3]
+@ CHECK: mvn r4, #4080 @ encoding: [0xff,0x4e,0xe0,0xe3]
+@ CHECK: mvn r5, #16711680 @ encoding: [0xff,0x58,0xe0,0xe3]
+@ CHECK: mvns r3, #7 @ encoding: [0x07,0x30,0xf0,0xe3]
+@ CHECK: mvneq r4, #4080 @ encoding: [0xff,0x4e,0xe0,0x03]
+@ CHECK: mvnseq r5, #16711680 @ encoding: [0xff,0x58,0xf0,0x03]
+
+
+@------------------------------------------------------------------------------
+@ MVN (register)
+@------------------------------------------------------------------------------
+ mvn r2, r3
+ mvns r2, r3
+ mvn r5, r6, lsl #19
+ mvn r5, r6, lsr #9
+ mvn r5, r6, asr #4
+ mvn r5, r6, ror #6
+ mvn r5, r6, rrx
+ mvneq r2, r3
+ mvnseq r2, r3, lsl #10
+
+@ CHECK: mvn r2, r3 @ encoding: [0x03,0x20,0xe0,0xe1]
+@ CHECK: mvns r2, r3 @ encoding: [0x03,0x20,0xf0,0xe1]
+@ CHECK: mvn r5, r6, lsl #19 @ encoding: [0x86,0x59,0xe0,0xe1]
+@ CHECK: mvn r5, r6, lsr #9 @ encoding: [0xa6,0x54,0xe0,0xe1]
+@ CHECK: mvn r5, r6, asr #4 @ encoding: [0x46,0x52,0xe0,0xe1]
+@ CHECK: mvn r5, r6, ror #6 @ encoding: [0x66,0x53,0xe0,0xe1]
+@ CHECK: mvn r5, r6, rrx @ encoding: [0x66,0x50,0xe0,0xe1]
+@ CHECK: mvneq r2, r3 @ encoding: [0x03,0x20,0xe0,0x01]
+@ CHECK: mvnseq r2, r3, lsl #10 @ encoding: [0x03,0x25,0xf0,0x01]
+
+
+@------------------------------------------------------------------------------
+@ MVN (shifted register)
+@------------------------------------------------------------------------------
+ mvn r5, r6, lsl r7
+ mvns r5, r6, lsr r7
+ mvngt r5, r6, asr r7
+ mvnslt r5, r6, ror r7
+
+@ CHECK: mvn r5, r6, lsl r7 @ encoding: [0x16,0x57,0xe0,0xe1]
+@ CHECK: mvns r5, r6, lsr r7 @ encoding: [0x36,0x57,0xf0,0xe1]
+@ CHECK: mvngt r5, r6, asr r7 @ encoding: [0x56,0x57,0xe0,0xc1]
+@ CHECK: mvnslt r5, r6, ror r7 @ encoding: [0x76,0x57,0xf0,0xb1]
+
+@------------------------------------------------------------------------------
+@ NOP
+@------------------------------------------------------------------------------
+ nop
+ nopgt
+
+@ CHECK: nop @ encoding: [0x00,0xf0,0x20,0xe3]
+@ CHECK: nopgt @ encoding: [0x00,0xf0,0x20,0xc3]
+
+
+@------------------------------------------------------------------------------
+@ ORR
+@------------------------------------------------------------------------------
+ orr r4, r5, #0xf000
+ orr r4, r5, r6
+ orr r4, r5, r6, lsl #5
+ orr r4, r5, r6, lsr #5
+ orr r4, r5, r6, lsr #5
+ orr r4, r5, r6, asr #5
+ orr r4, r5, r6, ror #5
+ orr r6, r7, r8, lsl r9
+ orr r6, r7, r8, lsr r9
+ orr r6, r7, r8, asr r9
+ orr r6, r7, r8, ror r9
+ orr r4, r5, r6, rrx
+
+ @ destination register is optional
+ orr r5, #0xf000
+ orr r4, r5
+ orr r4, r5, lsl #5
+ orr r4, r5, lsr #5
+ orr r4, r5, lsr #5
+ orr r4, r5, asr #5
+ orr r4, r5, ror #5
+ orr r6, r7, lsl r9
+ orr r6, r7, lsr r9
+ orr r6, r7, asr r9
+ orr r6, r7, ror r9
+ orr r4, r5, rrx
+
+@ CHECK: orr r4, r5, #61440 @ encoding: [0x0f,0x4a,0x85,0xe3]
+@ CHECK: orr r4, r5, r6 @ encoding: [0x06,0x40,0x85,0xe1]
+@ CHECK: orr r4, r5, r6, lsl #5 @ encoding: [0x86,0x42,0x85,0xe1]
+@ CHECK: orr r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0x85,0xe1]
+@ CHECK: orr r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0x85,0xe1]
+@ CHECK: orr r4, r5, r6, asr #5 @ encoding: [0xc6,0x42,0x85,0xe1]
+@ CHECK: orr r4, r5, r6, ror #5 @ encoding: [0xe6,0x42,0x85,0xe1]
+@ CHECK: orr r6, r7, r8, lsl r9 @ encoding: [0x18,0x69,0x87,0xe1]
+@ CHECK: orr r6, r7, r8, lsr r9 @ encoding: [0x38,0x69,0x87,0xe1]
+@ CHECK: orr r6, r7, r8, asr r9 @ encoding: [0x58,0x69,0x87,0xe1]
+@ CHECK: orr r6, r7, r8, ror r9 @ encoding: [0x78,0x69,0x87,0xe1]
+@ CHECK: orr r4, r5, r6, rrx @ encoding: [0x66,0x40,0x85,0xe1]
+
+@ CHECK: orr r5, r5, #61440 @ encoding: [0x0f,0x5a,0x85,0xe3]
+@ CHECK: orr r4, r4, r5 @ encoding: [0x05,0x40,0x84,0xe1]
+@ CHECK: orr r4, r4, r5, lsl #5 @ encoding: [0x85,0x42,0x84,0xe1]
+@ CHECK: orr r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0x84,0xe1]
+@ CHECK: orr r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0x84,0xe1]
+@ CHECK: orr r4, r4, r5, asr #5 @ encoding: [0xc5,0x42,0x84,0xe1]
+@ CHECK: orr r4, r4, r5, ror #5 @ encoding: [0xe5,0x42,0x84,0xe1]
+@ CHECK: orr r6, r6, r7, lsl r9 @ encoding: [0x17,0x69,0x86,0xe1]
+@ CHECK: orr r6, r6, r7, lsr r9 @ encoding: [0x37,0x69,0x86,0xe1]
+@ CHECK: orr r6, r6, r7, asr r9 @ encoding: [0x57,0x69,0x86,0xe1]
+@ CHECK: orr r6, r6, r7, ror r9 @ encoding: [0x77,0x69,0x86,0xe1]
+@ CHECK: orr r4, r4, r5, rrx @ encoding: [0x65,0x40,0x84,0xe1]
+
+ orrseq r4, r5, #0xf000
+ orrne r4, r5, r6
+ orrseq r4, r5, r6, lsl #5
+ orrlo r6, r7, r8, ror r9
+ orrshi r4, r5, r6, rrx
+ orrcs r5, #0xf000
+ orrseq r4, r5
+ orrne r6, r7, asr r9
+ orrslt r6, r7, ror r9
+ orrsgt r4, r5, rrx
+
+@ CHECK: orrseq r4, r5, #61440 @ encoding: [0x0f,0x4a,0x95,0x03]
+@ CHECK: orrne r4, r5, r6 @ encoding: [0x06,0x40,0x85,0x11]
+@ CHECK: orrseq r4, r5, r6, lsl #5 @ encoding: [0x86,0x42,0x95,0x01]
+@ CHECK: orrlo r6, r7, r8, ror r9 @ encoding: [0x78,0x69,0x87,0x31]
+@ CHECK: orrshi r4, r5, r6, rrx @ encoding: [0x66,0x40,0x95,0x81]
+@ CHECK: orrhs r5, r5, #61440 @ encoding: [0x0f,0x5a,0x85,0x23]
+@ CHECK: orrseq r4, r4, r5 @ encoding: [0x05,0x40,0x94,0x01]
+@ CHECK: orrne r6, r6, r7, asr r9 @ encoding: [0x57,0x69,0x86,0x11]
+@ CHECK: orrslt r6, r6, r7, ror r9 @ encoding: [0x77,0x69,0x96,0xb1]
+@ CHECK: orrsgt r4, r4, r5, rrx @ encoding: [0x65,0x40,0x94,0xc1]
+
+@------------------------------------------------------------------------------
+@ PKH
+@------------------------------------------------------------------------------
+ pkhbt r2, r2, r3
+ pkhbt r2, r2, r3, lsl #31
+ pkhbt r2, r2, r3, lsl #0
+ pkhbt r2, r2, r3, lsl #15
+
+ pkhtb r2, r2, r3
+ pkhtb r2, r2, r3, asr #31
+ pkhtb r2, r2, r3, asr #15
+
+@ CHECK: pkhbt r2, r2, r3 @ encoding: [0x13,0x20,0x82,0xe6]
+@ CHECK: pkhbt r2, r2, r3, lsl #31 @ encoding: [0x93,0x2f,0x82,0xe6]
+@ CHECK: pkhbt r2, r2, r3 @ encoding: [0x13,0x20,0x82,0xe6]
+@ CHECK: pkhbt r2, r2, r3, lsl #15 @ encoding: [0x93,0x27,0x82,0xe6]
+
+@ CHECK: pkhbt r2, r2, r3 @ encoding: [0x13,0x20,0x82,0xe6]
+@ CHECK: pkhtb r2, r2, r3, asr #31 @ encoding: [0xd3,0x2f,0x82,0xe6]
+@ CHECK: pkhtb r2, r2, r3, asr #15 @ encoding: [0xd3,0x27,0x82,0xe6]
+
+@------------------------------------------------------------------------------
+@ FIXME: PLD
+@------------------------------------------------------------------------------
+@------------------------------------------------------------------------------
+@ FIXME: PLI
+@------------------------------------------------------------------------------
+
+
+@------------------------------------------------------------------------------
+@ POP
+@------------------------------------------------------------------------------
+ pop {r7}
+ pop {r7, r8, r9, r10}
+
+@ CHECK: pop {r7} @ encoding: [0x04,0x70,0x9d,0xe4]
+@ CHECK: pop {r7, r8, r9, r10} @ encoding: [0x80,0x07,0xbd,0xe8]
+
+
+@------------------------------------------------------------------------------
+@ PUSH
+@------------------------------------------------------------------------------
+ push {r7}
+ push {r7, r8, r9, r10}
+
+@ CHECK: push {r7} @ encoding: [0x04,0x70,0x2d,0xe5]
+@ CHECK: push {r7, r8, r9, r10} @ encoding: [0x80,0x07,0x2d,0xe9]
+
+
+@------------------------------------------------------------------------------
+@ QADD/QADD16/QADD8
+@------------------------------------------------------------------------------
+ qadd r1, r2, r3
+ qaddne r1, r2, r3
+ qadd16 r1, r2, r3
+ qadd16gt r1, r2, r3
+ qadd8 r1, r2, r3
+ qadd8le r1, r2, r3
+
+@ CHECK: qadd r1, r2, r3 @ encoding: [0x52,0x10,0x03,0xe1]
+@ CHECK: qaddne r1, r2, r3 @ encoding: [0x52,0x10,0x03,0x11]
+@ CHECK: qadd16 r1, r2, r3 @ encoding: [0x13,0x1f,0x22,0xe6]
+@ CHECK: qadd16gt r1, r2, r3 @ encoding: [0x13,0x1f,0x22,0xc6]
+@ CHECK: qadd8 r1, r2, r3 @ encoding: [0x93,0x1f,0x22,0xe6]
+@ CHECK: qadd8le r1, r2, r3 @ encoding: [0x93,0x1f,0x22,0xd6]
+
+
+@------------------------------------------------------------------------------
+@ QDADD/QDSUB
+@------------------------------------------------------------------------------
+ qdadd r6, r7, r8
+ qdaddhi r6, r7, r8
+ qdsub r6, r7, r8
+ qdsubhi r6, r7, r8
+
+@ CHECK: qdadd r6, r7, r8 @ encoding: [0x57,0x60,0x48,0xe1]
+@ CHECK: qdaddhi r6, r7, r8 @ encoding: [0x57,0x60,0x48,0x81]
+@ CHECK: qdsub r6, r7, r8 @ encoding: [0x57,0x60,0x68,0xe1]
+@ CHECK: qdsubhi r6, r7, r8 @ encoding: [0x57,0x60,0x68,0x81]
+
+
+@------------------------------------------------------------------------------
+@ QSAX
+@------------------------------------------------------------------------------
+ qsax r9, r12, r0
+ qsaxeq r9, r12, r0
+
+@ CHECK: qsax r9, r12, r0 @ encoding: [0x50,0x9f,0x2c,0xe6]
+@ CHECK: qsaxeq r9, r12, r0 @ encoding: [0x50,0x9f,0x2c,0x06]
+
+
+@------------------------------------------------------------------------------
+@ QSUB/QSUB16/QSUB8
+@------------------------------------------------------------------------------
+ qsub r1, r2, r3
+ qsubne r1, r2, r3
+ qsub16 r1, r2, r3
+ qsub16gt r1, r2, r3
+ qsub8 r1, r2, r3
+ qsub8le r1, r2, r3
+
+@ CHECK: qsub r1, r2, r3 @ encoding: [0x52,0x10,0x23,0xe1]
+@ CHECK: qsubne r1, r2, r3 @ encoding: [0x52,0x10,0x23,0x11]
+@ CHECK: qsub16 r1, r2, r3 @ encoding: [0x73,0x1f,0x22,0xe6]
+@ CHECK: qsub16gt r1, r2, r3 @ encoding: [0x73,0x1f,0x22,0xc6]
+@ CHECK: qsub8 r1, r2, r3 @ encoding: [0xf3,0x1f,0x22,0xe6]
+@ CHECK: qsub8le r1, r2, r3 @ encoding: [0xf3,0x1f,0x22,0xd6]
+
+
+@------------------------------------------------------------------------------
+@ RBIT
+@------------------------------------------------------------------------------
+ rbit r1, r2
+ rbitne r1, r2
+
+@ CHECK: rbit r1, r2 @ encoding: [0x32,0x1f,0xff,0xe6]
+@ CHECK: rbitne r1, r2 @ encoding: [0x32,0x1f,0xff,0x16]
+
+
+@------------------------------------------------------------------------------
+@ REV/REV16/REVSH
+@------------------------------------------------------------------------------
+ rev r1, r9
+ revne r1, r5
+ rev16 r8, r3
+ rev16ne r12, r4
+ revsh r4, r9
+ revshne r9, r1
+
+@ CHECK: rev r1, r9 @ encoding: [0x39,0x1f,0xbf,0xe6]
+@ CHECK: revne r1, r5 @ encoding: [0x35,0x1f,0xbf,0x16]
+@ CHECK: rev16 r8, r3 @ encoding: [0xb3,0x8f,0xbf,0xe6]
+@ CHECK: rev16ne r12, r4 @ encoding: [0xb4,0xcf,0xbf,0x16]
+@ CHECK: revsh r4, r9 @ encoding: [0xb9,0x4f,0xff,0xe6]
+@ CHECK: revshne r9, r1 @ encoding: [0xb1,0x9f,0xff,0x16]
+
+
+@------------------------------------------------------------------------------
+@ RFE
+@------------------------------------------------------------------------------
+ rfeda r2
+ rfedb r3
+ rfeia r5
+ rfeib r6
+
+ rfeda r4!
+ rfedb r7!
+ rfeia r9!
+ rfeib r8!
+
+ rfefa r2
+ rfeea r3
+ rfefd r5
+ rfeed r6
+
+ rfefa r4!
+ rfeea r7!
+ rfefd r9!
+ rfeed r8!
+
+ rfe r1
+ rfe r1!
+
+@ CHECK: rfeda r2 @ encoding: [0x00,0x0a,0x12,0xf8]
+@ CHECK: rfedb r3 @ encoding: [0x00,0x0a,0x13,0xf9]
+@ CHECK: rfeia r5 @ encoding: [0x00,0x0a,0x95,0xf8]
+@ CHECK: rfeib r6 @ encoding: [0x00,0x0a,0x96,0xf9]
+
+@ CHECK: rfeda r4! @ encoding: [0x00,0x0a,0x34,0xf8]
+@ CHECK: rfedb r7! @ encoding: [0x00,0x0a,0x37,0xf9]
+@ CHECK: rfeia r9! @ encoding: [0x00,0x0a,0xb9,0xf8]
+@ CHECK: rfeib r8! @ encoding: [0x00,0x0a,0xb8,0xf9]
+
+@ CHECK: rfeda r2 @ encoding: [0x00,0x0a,0x12,0xf8]
+@ CHECK: rfedb r3 @ encoding: [0x00,0x0a,0x13,0xf9]
+@ CHECK: rfeia r5 @ encoding: [0x00,0x0a,0x95,0xf8]
+@ CHECK: rfeib r6 @ encoding: [0x00,0x0a,0x96,0xf9]
+
+@ CHECK: rfeda r4! @ encoding: [0x00,0x0a,0x34,0xf8]
+@ CHECK: rfedb r7! @ encoding: [0x00,0x0a,0x37,0xf9]
+@ CHECK: rfeia r9! @ encoding: [0x00,0x0a,0xb9,0xf8]
+@ CHECK: rfeib r8! @ encoding: [0x00,0x0a,0xb8,0xf9]
+
+@ CHECK: rfeia r1 @ encoding: [0x00,0x0a,0x91,0xf8]
+@ CHECK: rfeia r1! @ encoding: [0x00,0x0a,0xb1,0xf8]
+
+
+@------------------------------------------------------------------------------
+@ RSB
+@------------------------------------------------------------------------------
+ rsb r4, r5, #0xf000
+ rsb r4, r5, r6
+ rsb r4, r5, r6, lsl #5
+ rsblo r4, r5, r6, lsr #5
+ rsb r4, r5, r6, lsr #5
+ rsb r4, r5, r6, asr #5
+ rsb r4, r5, r6, ror #5
+ rsb r6, r7, r8, lsl r9
+ rsb r6, r7, r8, lsr r9
+ rsb r6, r7, r8, asr r9
+ rsble r6, r7, r8, ror r9
+ rsb r4, r5, r6, rrx
+
+ @ destination register is optional
+ rsb r5, #0xf000
+ rsb r4, r5
+ rsb r4, r5, lsl #5
+ rsb r4, r5, lsr #5
+ rsbne r4, r5, lsr #5
+ rsb r4, r5, asr #5
+ rsb r4, r5, ror #5
+ rsbgt r6, r7, lsl r9
+ rsb r6, r7, lsr r9
+ rsb r6, r7, asr r9
+ rsb r6, r7, ror r9
+ rsb r4, r5, rrx
+
+@ CHECK: rsb r4, r5, #61440 @ encoding: [0x0f,0x4a,0x65,0xe2]
+@ CHECK: rsb r4, r5, r6 @ encoding: [0x06,0x40,0x65,0xe0]
+@ CHECK: rsb r4, r5, r6, lsl #5 @ encoding: [0x86,0x42,0x65,0xe0]
+@ CHECK: rsblo r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0x65,0x30]
+@ CHECK: rsb r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0x65,0xe0]
+@ CHECK: rsb r4, r5, r6, asr #5 @ encoding: [0xc6,0x42,0x65,0xe0]
+@ CHECK: rsb r4, r5, r6, ror #5 @ encoding: [0xe6,0x42,0x65,0xe0]
+@ CHECK: rsb r6, r7, r8, lsl r9 @ encoding: [0x18,0x69,0x67,0xe0]
+@ CHECK: rsb r6, r7, r8, lsr r9 @ encoding: [0x38,0x69,0x67,0xe0]
+@ CHECK: rsb r6, r7, r8, asr r9 @ encoding: [0x58,0x69,0x67,0xe0]
+@ CHECK: rsble r6, r7, r8, ror r9 @ encoding: [0x78,0x69,0x67,0xd0]
+@ CHECK: rsb r4, r5, r6, rrx @ encoding: [0x66,0x40,0x65,0xe0]
+
+@ CHECK: rsb r5, r5, #61440 @ encoding: [0x0f,0x5a,0x65,0xe2]
+@ CHECK: rsb r4, r4, r5 @ encoding: [0x05,0x40,0x64,0xe0]
+@ CHECK: rsb r4, r4, r5, lsl #5 @ encoding: [0x85,0x42,0x64,0xe0]
+@ CHECK: rsb r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0x64,0xe0]
+@ CHECK: rsbne r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0x64,0x10]
+@ CHECK: rsb r4, r4, r5, asr #5 @ encoding: [0xc5,0x42,0x64,0xe0]
+@ CHECK: rsb r4, r4, r5, ror #5 @ encoding: [0xe5,0x42,0x64,0xe0]
+@ CHECK: rsbgt r6, r6, r7, lsl r9 @ encoding: [0x17,0x69,0x66,0xc0]
+@ CHECK: rsb r6, r6, r7, lsr r9 @ encoding: [0x37,0x69,0x66,0xe0]
+@ CHECK: rsb r6, r6, r7, asr r9 @ encoding: [0x57,0x69,0x66,0xe0]
+@ CHECK: rsb r6, r6, r7, ror r9 @ encoding: [0x77,0x69,0x66,0xe0]
+@ CHECK: rsb r4, r4, r5, rrx @ encoding: [0x65,0x40,0x64,0xe0]
+
+@------------------------------------------------------------------------------
+@ RSC
+@------------------------------------------------------------------------------
+ rsc r4, r5, #0xf000
+ rsc r4, r5, r6
+ rsc r4, r5, r6, lsl #5
+ rsclo r4, r5, r6, lsr #5
+ rsc r4, r5, r6, lsr #5
+ rsc r4, r5, r6, asr #5
+ rsc r4, r5, r6, ror #5
+ rsc r6, r7, r8, lsl r9
+ rsc r6, r7, r8, lsr r9
+ rsc r6, r7, r8, asr r9
+ rscle r6, r7, r8, ror r9
+ rscs r1, r8, #4064
+
+ @ destination register is optional
+ rsc r5, #0xf000
+ rsc r4, r5
+ rsc r4, r5, lsl #5
+ rsc r4, r5, lsr #5
+ rscne r4, r5, lsr #5
+ rsc r4, r5, asr #5
+ rsc r4, r5, ror #5
+ rscgt r6, r7, lsl r9
+ rsc r6, r7, lsr r9
+ rsc r6, r7, asr r9
+ rsc r6, r7, ror r9
+
+@ CHECK: rsc r4, r5, #61440 @ encoding: [0x0f,0x4a,0xe5,0xe2]
+@ CHECK: rsc r4, r5, r6 @ encoding: [0x06,0x40,0xe5,0xe0]
+@ CHECK: rsc r4, r5, r6, lsl #5 @ encoding: [0x86,0x42,0xe5,0xe0]
+@ CHECK: rsclo r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0xe5,0x30]
+@ CHECK: rsc r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0xe5,0xe0]
+@ CHECK: rsc r4, r5, r6, asr #5 @ encoding: [0xc6,0x42,0xe5,0xe0]
+@ CHECK: rsc r4, r5, r6, ror #5 @ encoding: [0xe6,0x42,0xe5,0xe0]
+@ CHECK: rsc r6, r7, r8, lsl r9 @ encoding: [0x18,0x69,0xe7,0xe0]
+@ CHECK: rsc r6, r7, r8, lsr r9 @ encoding: [0x38,0x69,0xe7,0xe0]
+@ CHECK: rsc r6, r7, r8, asr r9 @ encoding: [0x58,0x69,0xe7,0xe0]
+@ CHECK: rscle r6, r7, r8, ror r9 @ encoding: [0x78,0x69,0xe7,0xd0]
+@ CHECK: rscs r1, r8, #4064 @ encoding: [0xfe,0x1e,0xf8,0xe2]
+
+@ CHECK: rsc r5, r5, #61440 @ encoding: [0x0f,0x5a,0xe5,0xe2]
+@ CHECK: rsc r4, r4, r5 @ encoding: [0x05,0x40,0xe4,0xe0]
+@ CHECK: rsc r4, r4, r5, lsl #5 @ encoding: [0x85,0x42,0xe4,0xe0]
+@ CHECK: rsc r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0xe4,0xe0]
+@ CHECK: rscne r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0xe4,0x10]
+@ CHECK: rsc r4, r4, r5, asr #5 @ encoding: [0xc5,0x42,0xe4,0xe0]
+@ CHECK: rsc r4, r4, r5, ror #5 @ encoding: [0xe5,0x42,0xe4,0xe0]
+@ CHECK: rscgt r6, r6, r7, lsl r9 @ encoding: [0x17,0x69,0xe6,0xc0]
+@ CHECK: rsc r6, r6, r7, lsr r9 @ encoding: [0x37,0x69,0xe6,0xe0]
+@ CHECK: rsc r6, r6, r7, asr r9 @ encoding: [0x57,0x69,0xe6,0xe0]
+@ CHECK: rsc r6, r6, r7, ror r9 @ encoding: [0x77,0x69,0xe6,0xe0]
+
+@------------------------------------------------------------------------------
+@ SADD16/SADD8
+@------------------------------------------------------------------------------
+ sadd16 r1, r2, r3
+ sadd16gt r1, r2, r3
+ sadd8 r1, r2, r3
+ sadd8le r1, r2, r3
+
+@ CHECK: sadd16 r1, r2, r3 @ encoding: [0x13,0x1f,0x12,0xe6]
+@ CHECK: sadd16gt r1, r2, r3 @ encoding: [0x13,0x1f,0x12,0xc6]
+@ CHECK: sadd8 r1, r2, r3 @ encoding: [0x93,0x1f,0x12,0xe6]
+@ CHECK: sadd8le r1, r2, r3 @ encoding: [0x93,0x1f,0x12,0xd6]
+
+
+@------------------------------------------------------------------------------
+@ SASX
+@------------------------------------------------------------------------------
+ sasx r9, r12, r0
+ sasxeq r9, r12, r0
+
+@ CHECK: sasx r9, r12, r0 @ encoding: [0x30,0x9f,0x1c,0xe6]
+@ CHECK: sasxeq r9, r12, r0 @ encoding: [0x30,0x9f,0x1c,0x06]
+
+
+@------------------------------------------------------------------------------
+@ SBC
+@------------------------------------------------------------------------------
+ sbc r4, r5, #0xf000
+ sbc r4, r5, r6
+ sbc r4, r5, r6, lsl #5
+ sbc r4, r5, r6, lsr #5
+ sbc r4, r5, r6, lsr #5
+ sbc r4, r5, r6, asr #5
+ sbc r4, r5, r6, ror #5
+ sbc r6, r7, r8, lsl r9
+ sbc r6, r7, r8, lsr r9
+ sbc r6, r7, r8, asr r9
+ sbc r6, r7, r8, ror r9
+
+ @ destination register is optional
+ sbc r5, #0xf000
+ sbc r4, r5
+ sbc r4, r5, lsl #5
+ sbc r4, r5, lsr #5
+ sbc r4, r5, lsr #5
+ sbc r4, r5, asr #5
+ sbc r4, r5, ror #5
+ sbc r6, r7, lsl r9
+ sbc r6, r7, lsr r9
+ sbc r6, r7, asr r9
+ sbc r6, r7, ror r9
+
+@ CHECK: sbc r4, r5, #61440 @ encoding: [0x0f,0x4a,0xc5,0xe2]
+@ CHECK: sbc r4, r5, r6 @ encoding: [0x06,0x40,0xc5,0xe0]
+@ CHECK: sbc r4, r5, r6, lsl #5 @ encoding: [0x86,0x42,0xc5,0xe0]
+@ CHECK: sbc r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0xc5,0xe0]
+@ CHECK: sbc r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0xc5,0xe0]
+@ CHECK: sbc r4, r5, r6, asr #5 @ encoding: [0xc6,0x42,0xc5,0xe0]
+@ CHECK: sbc r4, r5, r6, ror #5 @ encoding: [0xe6,0x42,0xc5,0xe0]
+@ CHECK: sbc r6, r7, r8, lsl r9 @ encoding: [0x18,0x69,0xc7,0xe0]
+@ CHECK: sbc r6, r7, r8, lsr r9 @ encoding: [0x38,0x69,0xc7,0xe0]
+@ CHECK: sbc r6, r7, r8, asr r9 @ encoding: [0x58,0x69,0xc7,0xe0]
+@ CHECK: sbc r6, r7, r8, ror r9 @ encoding: [0x78,0x69,0xc7,0xe0]
+
+@ CHECK: sbc r5, r5, #61440 @ encoding: [0x0f,0x5a,0xc5,0xe2]
+@ CHECK: sbc r4, r4, r5 @ encoding: [0x05,0x40,0xc4,0xe0]
+@ CHECK: sbc r4, r4, r5, lsl #5 @ encoding: [0x85,0x42,0xc4,0xe0]
+@ CHECK: sbc r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0xc4,0xe0]
+@ CHECK: sbc r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0xc4,0xe0]
+@ CHECK: sbc r4, r4, r5, asr #5 @ encoding: [0xc5,0x42,0xc4,0xe0]
+@ CHECK: sbc r4, r4, r5, ror #5 @ encoding: [0xe5,0x42,0xc4,0xe0]
+@ CHECK: sbc r6, r6, r7, lsl r9 @ encoding: [0x17,0x69,0xc6,0xe0]
+@ CHECK: sbc r6, r6, r7, lsr r9 @ encoding: [0x37,0x69,0xc6,0xe0]
+@ CHECK: sbc r6, r6, r7, asr r9 @ encoding: [0x57,0x69,0xc6,0xe0]
+@ CHECK: sbc r6, r6, r7, ror r9 @ encoding: [0x77,0x69,0xc6,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ SBFX
+@------------------------------------------------------------------------------
+ sbfx r4, r5, #16, #1
+ sbfxgt r4, r5, #16, #16
+
+@ CHECK: sbfx r4, r5, #16, #1 @ encoding: [0x55,0x48,0xa0,0xe7]
+@ CHECK: sbfxgt r4, r5, #16, #16 @ encoding: [0x55,0x48,0xaf,0xc7]
+
+
+@------------------------------------------------------------------------------
+@ SEL
+@------------------------------------------------------------------------------
+ sel r9, r2, r1
+ selne r9, r2, r1
+
+@ CHECK: sel r9, r2, r1 @ encoding: [0xb1,0x9f,0x82,0xe6]
+@ CHECK: selne r9, r2, r1 @ encoding: [0xb1,0x9f,0x82,0x16]
+
+
+@------------------------------------------------------------------------------
+@ SETEND
+@------------------------------------------------------------------------------
+ setend be
+ setend le
+
+@ CHECK: setend be @ encoding: [0x00,0x02,0x01,0xf1]
+@ CHECK: setend le @ encoding: [0x00,0x00,0x01,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ SEV
+@------------------------------------------------------------------------------
+ sev
+ seveq
+
+@ CHECK: sev @ encoding: [0x04,0xf0,0x20,0xe3]
+@ CHECK: seveq @ encoding: [0x04,0xf0,0x20,0x03]
+
+
+@------------------------------------------------------------------------------
+@ SHADD16/SHADD8
+@------------------------------------------------------------------------------
+ shadd16 r4, r8, r2
+ shadd16gt r4, r8, r2
+ shadd8 r4, r8, r2
+ shadd8gt r4, r8, r2
+
+@ CHECK: shadd16 r4, r8, r2 @ encoding: [0x12,0x4f,0x38,0xe6]
+@ CHECK: shadd16gt r4, r8, r2 @ encoding: [0x12,0x4f,0x38,0xc6]
+@ CHECK: shadd8 r4, r8, r2 @ encoding: [0x92,0x4f,0x38,0xe6]
+@ CHECK: shadd8gt r4, r8, r2 @ encoding: [0x92,0x4f,0x38,0xc6]
+
+
+@------------------------------------------------------------------------------
+@ SHASX
+@------------------------------------------------------------------------------
+ shasx r4, r8, r2
+ shasxgt r4, r8, r2
+
+@ CHECK: shasx r4, r8, r2 @ encoding: [0x32,0x4f,0x38,0xe6]
+@ CHECK: shasxgt r4, r8, r2 @ encoding: [0x32,0x4f,0x38,0xc6]
+
+
+@------------------------------------------------------------------------------
+@ SHSUB16/SHSUB8
+@------------------------------------------------------------------------------
+ shsub16 r4, r8, r2
+ shsub16gt r4, r8, r2
+ shsub8 r4, r8, r2
+ shsub8gt r4, r8, r2
+
+@ CHECK: shsub16 r4, r8, r2 @ encoding: [0x72,0x4f,0x38,0xe6]
+@ CHECK: shsub16gt r4, r8, r2 @ encoding: [0x72,0x4f,0x38,0xc6]
+@ CHECK: shsub8 r4, r8, r2 @ encoding: [0xf2,0x4f,0x38,0xe6]
+@ CHECK: shsub8gt r4, r8, r2 @ encoding: [0xf2,0x4f,0x38,0xc6]
+
+@------------------------------------------------------------------------------
+@ SMC
+@------------------------------------------------------------------------------
+ smc #0xf
+ smceq #0
+
+@ CHECK: smc #15 @ encoding: [0x7f,0x00,0x60,0xe1]
+@ CHECK: smceq #0 @ encoding: [0x70,0x00,0x60,0x01]
+
+@------------------------------------------------------------------------------
+@ SMLABB/SMLABT/SMLATB/SMLATT
+@------------------------------------------------------------------------------
+ smlabb r3, r1, r9, r0
+ smlabt r5, r6, r4, r1
+ smlatb r4, r2, r3, r2
+ smlatt r8, r3, r8, r4
+ smlabbge r3, r1, r9, r0
+ smlabtle r5, r6, r4, r1
+ smlatbne r4, r2, r3, r2
+ smlatteq r8, r3, r8, r4
+
+@ CHECK: smlabb r3, r1, r9, r0 @ encoding: [0x81,0x09,0x03,0xe1]
+@ CHECK: smlabt r5, r6, r4, r1 @ encoding: [0xc6,0x14,0x05,0xe1]
+@ CHECK: smlatb r4, r2, r3, r2 @ encoding: [0xa2,0x23,0x04,0xe1]
+@ CHECK: smlatt r8, r3, r8, r4 @ encoding: [0xe3,0x48,0x08,0xe1]
+@ CHECK: smlabbge r3, r1, r9, r0 @ encoding: [0x81,0x09,0x03,0xa1]
+@ CHECK: smlabtle r5, r6, r4, r1 @ encoding: [0xc6,0x14,0x05,0xd1]
+@ CHECK: smlatbne r4, r2, r3, r2 @ encoding: [0xa2,0x23,0x04,0x11]
+@ CHECK: smlatteq r8, r3, r8, r4 @ encoding: [0xe3,0x48,0x08,0x01]
+
+@------------------------------------------------------------------------------
+@ SMLAD/SMLADX
+@------------------------------------------------------------------------------
+ smlad r2, r3, r5, r8
+ smladx r2, r3, r5, r8
+ smladeq r2, r3, r5, r8
+ smladxhi r2, r3, r5, r8
+
+@ CHECK: smlad r2, r3, r5, r8 @ encoding: [0x13,0x85,0x02,0xe7]
+@ CHECK: smladx r2, r3, r5, r8 @ encoding: [0x33,0x85,0x02,0xe7]
+@ CHECK: smladeq r2, r3, r5, r8 @ encoding: [0x13,0x85,0x02,0x07]
+@ CHECK: smladxhi r2, r3, r5, r8 @ encoding: [0x33,0x85,0x02,0x87]
+
+
+@------------------------------------------------------------------------------
+@ SMLAL
+@------------------------------------------------------------------------------
+ smlal r2, r3, r5, r8
+ smlals r2, r3, r5, r8
+ smlaleq r2, r3, r5, r8
+ smlalshi r2, r3, r5, r8
+
+@ CHECK: smlal r2, r3, r5, r8 @ encoding: [0x95,0x28,0xe3,0xe0]
+@ CHECK: smlals r2, r3, r5, r8 @ encoding: [0x95,0x28,0xf3,0xe0]
+@ CHECK: smlaleq r2, r3, r5, r8 @ encoding: [0x95,0x28,0xe3,0x00]
+@ CHECK: smlalshi r2, r3, r5, r8 @ encoding: [0x95,0x28,0xf3,0x80]
+
+
+@------------------------------------------------------------------------------
+@ SMLALBB/SMLALBT/SMLALTB/SMLALTT
+@------------------------------------------------------------------------------
+ smlalbb r3, r1, r9, r0
+ smlalbt r5, r6, r4, r1
+ smlaltb r4, r2, r3, r2
+ smlaltt r8, r3, r8, r4
+ smlalbbge r3, r1, r9, r0
+ smlalbtle r5, r6, r4, r1
+ smlaltbne r4, r2, r3, r2
+ smlaltteq r8, r3, r8, r4
+
+@ CHECK: smlalbb r3, r1, r9, r0 @ encoding: [0x89,0x30,0x41,0xe1]
+@ CHECK: smlalbt r5, r6, r4, r1 @ encoding: [0xc4,0x51,0x46,0xe1]
+@ CHECK: smlaltb r4, r2, r3, r2 @ encoding: [0xa3,0x42,0x42,0xe1]
+@ CHECK: smlaltt r8, r3, r8, r4 @ encoding: [0xe8,0x84,0x43,0xe1]
+@ CHECK: smlalbbge r3, r1, r9, r0 @ encoding: [0x89,0x30,0x41,0xa1]
+@ CHECK: smlalbtle r5, r6, r4, r1 @ encoding: [0xc4,0x51,0x46,0xd1]
+@ CHECK: smlaltbne r4, r2, r3, r2 @ encoding: [0xa3,0x42,0x42,0x11]
+@ CHECK: smlaltteq r8, r3, r8, r4 @ encoding: [0xe8,0x84,0x43,0x01]
+
+
+@------------------------------------------------------------------------------
+@ SMLALD/SMLALDX
+@------------------------------------------------------------------------------
+ smlald r2, r3, r5, r8
+ smlaldx r2, r3, r5, r8
+ smlaldeq r2, r3, r5, r8
+ smlaldxhi r2, r3, r5, r8
+
+@ CHECK: smlald r2, r3, r5, r8 @ encoding: [0x15,0x28,0x43,0xe7]
+@ CHECK: smlaldx r2, r3, r5, r8 @ encoding: [0x35,0x28,0x43,0xe7]
+@ CHECK: smlaldeq r2, r3, r5, r8 @ encoding: [0x15,0x28,0x43,0x07]
+@ CHECK: smlaldxhi r2, r3, r5, r8 @ encoding: [0x35,0x28,0x43,0x87]
+
+
+@------------------------------------------------------------------------------
+@ SMLAWB/SMLAWT
+@------------------------------------------------------------------------------
+ smlawb r2, r3, r10, r8
+ smlawt r8, r3, r5, r9
+ smlawbeq r2, r7, r5, r8
+ smlawthi r1, r3, r0, r8
+
+@ CHECK: smlawb r2, r3, r10, r8 @ encoding: [0x83,0x8a,0x22,0xe1]
+@ CHECK: smlawt r8, r3, r5, r9 @ encoding: [0xc3,0x95,0x28,0xe1]
+@ CHECK: smlawbeq r2, r7, r5, r8 @ encoding: [0x87,0x85,0x22,0x01]
+@ CHECK: smlawthi r1, r3, r0, r8 @ encoding: [0xc3,0x80,0x21,0x81]
+
+
+@------------------------------------------------------------------------------
+@ SMLSD/SMLSDX
+@------------------------------------------------------------------------------
+ smlsd r2, r3, r5, r8
+ smlsdx r2, r3, r5, r8
+ smlsdeq r2, r3, r5, r8
+ smlsdxhi r2, r3, r5, r8
+
+@ CHECK: smlsd r2, r3, r5, r8 @ encoding: [0x53,0x85,0x02,0xe7]
+@ CHECK: smlsdx r2, r3, r5, r8 @ encoding: [0x73,0x85,0x02,0xe7]
+@ CHECK: smlsdeq r2, r3, r5, r8 @ encoding: [0x53,0x85,0x02,0x07]
+@ CHECK: smlsdxhi r2, r3, r5, r8 @ encoding: [0x73,0x85,0x02,0x87]
+
+
+@------------------------------------------------------------------------------
+@ SMLSLD/SMLSLDX
+@------------------------------------------------------------------------------
+ smlsld r2, r9, r5, r1
+ smlsldx r4, r11, r2, r8
+ smlsldeq r8, r2, r5, r6
+ smlsldxhi r1, r0, r3, r8
+
+@ CHECK: smlsld r2, r9, r5, r1 @ encoding: [0x55,0x21,0x49,0xe7]
+@ CHECK: smlsldx r4, r11, r2, r8 @ encoding: [0x72,0x48,0x4b,0xe7]
+@ CHECK: smlsldeq r8, r2, r5, r6 @ encoding: [0x55,0x86,0x42,0x07]
+@ CHECK: smlsldxhi r1, r0, r3, r8 @ encoding: [0x73,0x18,0x40,0x87]
+
+
+@------------------------------------------------------------------------------
+@ SMMLA/SMMLAR
+@------------------------------------------------------------------------------
+ smmla r1, r2, r3, r4
+ smmlar r4, r3, r2, r1
+ smmlalo r1, r2, r3, r4
+ smmlarcs r4, r3, r2, r1
+
+@ CHECK: smmla r1, r2, r3, r4 @ encoding: [0x12,0x43,0x51,0xe7]
+@ CHECK: smmlar r4, r3, r2, r1 @ encoding: [0x33,0x12,0x54,0xe7]
+@ CHECK: smmlalo r1, r2, r3, r4 @ encoding: [0x12,0x43,0x51,0x37]
+@ CHECK: smmlarhs r4, r3, r2, r1 @ encoding: [0x33,0x12,0x54,0x27]
+
+
+@------------------------------------------------------------------------------
+@ SMMLS/SMMLSR
+@------------------------------------------------------------------------------
+ smmls r1, r2, r3, r4
+ smmlsr r4, r3, r2, r1
+ smmlslo r1, r2, r3, r4
+ smmlsrcs r4, r3, r2, r1
+
+@ CHECK: smmls r1, r2, r3, r4 @ encoding: [0xd2,0x43,0x51,0xe7]
+@ CHECK: smmlsr r4, r3, r2, r1 @ encoding: [0xf3,0x12,0x54,0xe7]
+@ CHECK: smmlslo r1, r2, r3, r4 @ encoding: [0xd2,0x43,0x51,0x37]
+@ CHECK: smmlsrhs r4, r3, r2, r1 @ encoding: [0xf3,0x12,0x54,0x27]
+
+
+@------------------------------------------------------------------------------
+@ SMMUL/SMMULR
+@------------------------------------------------------------------------------
+ smmul r2, r3, r4
+ smmulr r3, r2, r1
+ smmulcc r2, r3, r4
+ smmulrhs r3, r2, r1
+
+@ CHECK: smmul r2, r3, r4 @ encoding: [0x13,0xf4,0x52,0xe7]
+@ CHECK: smmulr r3, r2, r1 @ encoding: [0x32,0xf1,0x53,0xe7]
+@ CHECK: smmullo r2, r3, r4 @ encoding: [0x13,0xf4,0x52,0x37]
+@ CHECK: smmulrhs r3, r2, r1 @ encoding: [0x32,0xf1,0x53,0x27]
+
+
+@------------------------------------------------------------------------------
+@ SMUAD/SMUADX
+@------------------------------------------------------------------------------
+ smuad r2, r3, r4
+ smuadx r3, r2, r1
+ smuadlt r2, r3, r4
+ smuadxge r3, r2, r1
+
+@ CHECK: smuad r2, r3, r4 @ encoding: [0x13,0xf4,0x02,0xe7]
+@ CHECK: smuadx r3, r2, r1 @ encoding: [0x32,0xf1,0x03,0xe7]
+@ CHECK: smuadlt r2, r3, r4 @ encoding: [0x13,0xf4,0x02,0xb7]
+@ CHECK: smuadxge r3, r2, r1 @ encoding: [0x32,0xf1,0x03,0xa7]
+
+
+@------------------------------------------------------------------------------
+@ SMULBB/SMULBT/SMULTB/SMULTT
+@------------------------------------------------------------------------------
+ smulbb r3, r9, r0
+ smulbt r5, r4, r1
+ smultb r4, r2, r2
+ smultt r8, r3, r4
+ smulbbge r1, r9, r0
+ smulbtle r5, r6, r4
+ smultbne r2, r3, r2
+ smultteq r8, r3, r4
+
+@ CHECK: smulbb r3, r9, r0 @ encoding: [0x89,0x00,0x63,0xe1]
+@ CHECK: smulbt r5, r4, r1 @ encoding: [0xc4,0x01,0x65,0xe1]
+@ CHECK: smultb r4, r2, r2 @ encoding: [0xa2,0x02,0x64,0xe1]
+@ CHECK: smultt r8, r3, r4 @ encoding: [0xe3,0x04,0x68,0xe1]
+@ CHECK: smulbbge r1, r9, r0 @ encoding: [0x89,0x00,0x61,0xa1]
+@ CHECK: smulbtle r5, r6, r4 @ encoding: [0xc6,0x04,0x65,0xd1]
+@ CHECK: smultbne r2, r3, r2 @ encoding: [0xa3,0x02,0x62,0x11]
+@ CHECK: smultteq r8, r3, r4 @ encoding: [0xe3,0x04,0x68,0x01]
+
+
+@------------------------------------------------------------------------------
+@ SMULL
+@------------------------------------------------------------------------------
+ smull r3, r9, r0, r1
+ smulls r3, r9, r0, r2
+ smulleq r8, r3, r4, r5
+ smullseq r8, r3, r4, r3
+
+@ CHECK: smull r3, r9, r0, r1 @ encoding: [0x90,0x31,0xc9,0xe0]
+@ CHECK: smulls r3, r9, r0, r2 @ encoding: [0x90,0x32,0xd9,0xe0]
+@ CHECK: smulleq r8, r3, r4, r5 @ encoding: [0x94,0x85,0xc3,0x00]
+@ CHECK: smullseq r8, r3, r4, r3 @ encoding: [0x94,0x83,0xd3,0x00]
+
+
+@------------------------------------------------------------------------------
+@ SMULWB/SMULWT
+@------------------------------------------------------------------------------
+ smulwb r3, r9, r0
+ smulwt r3, r9, r2
+
+@ CHECK: smulwb r3, r9, r0 @ encoding: [0xa9,0x00,0x23,0xe1]
+@ CHECK: smulwt r3, r9, r2 @ encoding: [0xe9,0x02,0x23,0xe1]
+
+
+@------------------------------------------------------------------------------
+@ SMUSD/SMUSDX
+@------------------------------------------------------------------------------
+ smusd r3, r0, r1
+ smusdx r3, r9, r2
+ smusdeq r8, r3, r2
+ smusdxne r7, r4, r3
+
+@ CHECK: smusd r3, r0, r1 @ encoding: [0x50,0xf1,0x03,0xe7]
+@ CHECK: smusdx r3, r9, r2 @ encoding: [0x79,0xf2,0x03,0xe7]
+@ CHECK: smusdeq r8, r3, r2 @ encoding: [0x53,0xf2,0x08,0x07]
+@ CHECK: smusdxne r7, r4, r3 @ encoding: [0x74,0xf3,0x07,0x17]
+
+
+@------------------------------------------------------------------------------
+@ SRS
+@------------------------------------------------------------------------------
+ srsda sp, #5
+ srsdb sp, #1
+ srsia sp, #0
+ srsib sp, #15
+
+ srsda sp!, #31
+ srsdb sp!, #19
+ srsia sp!, #2
+ srsib sp!, #14
+
+ srsfa sp, #11
+ srsea sp, #10
+ srsfd sp, #9
+ srsed sp, #5
+
+ srsfa sp!, #5
+ srsea sp!, #5
+ srsfd sp!, #5
+ srsed sp!, #5
+
+ srs sp, #5
+ srs sp!, #5
+
+@ CHECK: srsda sp, #5 @ encoding: [0x05,0x05,0x4d,0xf8]
+@ CHECK: srsdb sp, #1 @ encoding: [0x01,0x05,0x4d,0xf9]
+@ CHECK: srsia sp, #0 @ encoding: [0x00,0x05,0xcd,0xf8]
+@ CHECK: srsib sp, #15 @ encoding: [0x0f,0x05,0xcd,0xf9]
+
+@ CHECK: srsda sp!, #31 @ encoding: [0x1f,0x05,0x6d,0xf8]
+@ CHECK: srsdb sp!, #19 @ encoding: [0x13,0x05,0x6d,0xf9]
+@ CHECK: srsia sp!, #2 @ encoding: [0x02,0x05,0xed,0xf8]
+@ CHECK: srsib sp!, #14 @ encoding: [0x0e,0x05,0xed,0xf9]
+
+@ CHECK: srsda sp, #11 @ encoding: [0x0b,0x05,0x4d,0xf8]
+@ CHECK: srsdb sp, #10 @ encoding: [0x0a,0x05,0x4d,0xf9]
+@ CHECK: srsia sp, #9 @ encoding: [0x09,0x05,0xcd,0xf8]
+@ CHECK: srsib sp, #5 @ encoding: [0x05,0x05,0xcd,0xf9]
+
+@ CHECK: srsda sp!, #5 @ encoding: [0x05,0x05,0x6d,0xf8]
+@ CHECK: srsdb sp!, #5 @ encoding: [0x05,0x05,0x6d,0xf9]
+@ CHECK: srsia sp!, #5 @ encoding: [0x05,0x05,0xed,0xf8]
+@ CHECK: srsib sp!, #5 @ encoding: [0x05,0x05,0xed,0xf9]
+
+@ CHECK: srsia sp, #5 @ encoding: [0x05,0x05,0xcd,0xf8]
+@ CHECK: srsia sp!, #5 @ encoding: [0x05,0x05,0xed,0xf8]
+
+
+@------------------------------------------------------------------------------
+@ SSAT
+@------------------------------------------------------------------------------
+ ssat r8, #1, r10
+ ssat r8, #1, r10, lsl #0
+ ssat r8, #1, r10, lsl #31
+ ssat r8, #1, r10, asr #32
+ ssat r8, #1, r10, asr #1
+
+@ CHECK: ssat r8, #1, r10 @ encoding: [0x1a,0x80,0xa0,0xe6]
+@ CHECK: ssat r8, #1, r10 @ encoding: [0x1a,0x80,0xa0,0xe6]
+@ CHECK: ssat r8, #1, r10, lsl #31 @ encoding: [0x9a,0x8f,0xa0,0xe6]
+@ CHECK: ssat r8, #1, r10, asr #32 @ encoding: [0x5a,0x80,0xa0,0xe6]
+@ CHECK: ssat r8, #1, r10, asr #1 @ encoding: [0xda,0x80,0xa0,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ SSAT16
+@------------------------------------------------------------------------------
+ ssat16 r2, #1, r7
+ ssat16 r3, #16, r5
+
+@ CHECK: ssat16 r2, #1, r7 @ encoding: [0x37,0x2f,0xa0,0xe6]
+@ CHECK: ssat16 r3, #16, r5 @ encoding: [0x35,0x3f,0xaf,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ SSAX
+@------------------------------------------------------------------------------
+ ssax r2, r3, r4
+ ssaxlt r2, r3, r4
+
+@ CHECK: ssax r2, r3, r4 @ encoding: [0x54,0x2f,0x13,0xe6]
+@ CHECK: ssaxlt r2, r3, r4 @ encoding: [0x54,0x2f,0x13,0xb6]
+
+@------------------------------------------------------------------------------
+@ SSUB16/SSUB8
+@------------------------------------------------------------------------------
+ ssub16 r1, r0, r6
+ ssub16ne r5, r3, r2
+ ssub8 r9, r2, r4
+ ssub8eq r5, r1, r2
+
+@ CHECK: ssub16 r1, r0, r6 @ encoding: [0x76,0x1f,0x10,0xe6]
+@ CHECK: ssub16ne r5, r3, r2 @ encoding: [0x72,0x5f,0x13,0x16]
+@ CHECK: ssub8 r9, r2, r4 @ encoding: [0xf4,0x9f,0x12,0xe6]
+@ CHECK: ssub8eq r5, r1, r2 @ encoding: [0xf2,0x5f,0x11,0x06]
+
+@------------------------------------------------------------------------------
+@ STC{L}/STC2{L}
+@------------------------------------------------------------------------------
+ stc2 p0, c8, [r1, #4]
+ stc2 p1, c7, [r2]
+ stc2 p2, c6, [r3, #-224]
+ stc2 p3, c5, [r4, #-120]!
+ stc2 p4, c4, [r5], #16
+ stc2 p5, c3, [r6], #-72
+ stc2l p6, c2, [r7, #4]
+ stc2l p7, c1, [r8]
+ stc2l p8, c0, [r9, #-224]
+ stc2l p9, c1, [r10, #-120]!
+ stc2l p10, c2, [r11], #16
+ stc2l p11, c3, [r12], #-72
+
+ stc p12, c4, [r0, #4]
+ stc p13, c5, [r1]
+ stc p14, c6, [r2, #-224]
+ stc p15, c7, [r3, #-120]!
+ stc p5, c8, [r4], #16
+ stc p4, c9, [r5], #-72
+ stcl p3, c10, [r6, #4]
+ stcl p2, c11, [r7]
+ stcl p1, c12, [r8, #-224]
+ stcl p0, c13, [r9, #-120]!
+ stcl p6, c14, [r10], #16
+ stcl p7, c15, [r11], #-72
+
+ stclo p12, c4, [r0, #4]
+ stchi p13, c5, [r1]
+ stccs p14, c6, [r2, #-224]
+ stccc p15, c7, [r3, #-120]!
+ stceq p5, c8, [r4], #16
+ stcgt p4, c9, [r5], #-72
+ stcllt p3, c10, [r6, #4]
+ stclge p2, c11, [r7]
+ stclle p1, c12, [r8, #-224]
+ stclne p0, c13, [r9, #-120]!
+ stcleq p6, c14, [r10], #16
+ stclhi p7, c15, [r11], #-72
+
+ stc2 p2, c8, [r1], { 25 }
+
+@ CHECK: stc2 p0, c8, [r1, #4] @ encoding: [0x01,0x80,0x81,0xfd]
+@ CHECK: stc2 p1, c7, [r2] @ encoding: [0x00,0x71,0x82,0xfd]
+@ CHECK: stc2 p2, c6, [r3, #-224] @ encoding: [0x38,0x62,0x03,0xfd]
+@ CHECK: stc2 p3, c5, [r4, #-120]! @ encoding: [0x1e,0x53,0x24,0xfd]
+@ CHECK: stc2 p4, c4, [r5], #16 @ encoding: [0x04,0x44,0xa5,0xfc]
+@ CHECK: stc2 p5, c3, [r6], #-72 @ encoding: [0x12,0x35,0x26,0xfc]
+@ CHECK: stc2l p6, c2, [r7, #4] @ encoding: [0x01,0x26,0xc7,0xfd]
+@ CHECK: stc2l p7, c1, [r8] @ encoding: [0x00,0x17,0xc8,0xfd]
+@ CHECK: stc2l p8, c0, [r9, #-224] @ encoding: [0x38,0x08,0x49,0xfd]
+@ CHECK: stc2l p9, c1, [r10, #-120]! @ encoding: [0x1e,0x19,0x6a,0xfd]
+@ CHECK: stc2l p10, c2, [r11], #16 @ encoding: [0x04,0x2a,0xeb,0xfc]
+@ CHECK: stc2l p11, c3, [r12], #-72 @ encoding: [0x12,0x3b,0x6c,0xfc]
+
+@ CHECK: stc p12, c4, [r0, #4] @ encoding: [0x01,0x4c,0x80,0xed]
+@ CHECK: stc p13, c5, [r1] @ encoding: [0x00,0x5d,0x81,0xed]
+@ CHECK: stc p14, c6, [r2, #-224] @ encoding: [0x38,0x6e,0x02,0xed]
+@ CHECK: stc p15, c7, [r3, #-120]! @ encoding: [0x1e,0x7f,0x23,0xed]
+@ CHECK: stc p5, c8, [r4], #16 @ encoding: [0x04,0x85,0xa4,0xec]
+@ CHECK: stc p4, c9, [r5], #-72 @ encoding: [0x12,0x94,0x25,0xec]
+@ CHECK: stcl p3, c10, [r6, #4] @ encoding: [0x01,0xa3,0xc6,0xed]
+@ CHECK: stcl p2, c11, [r7] @ encoding: [0x00,0xb2,0xc7,0xed]
+@ CHECK: stcl p1, c12, [r8, #-224] @ encoding: [0x38,0xc1,0x48,0xed]
+@ CHECK: stcl p0, c13, [r9, #-120]! @ encoding: [0x1e,0xd0,0x69,0xed]
+@ CHECK: stcl p6, c14, [r10], #16 @ encoding: [0x04,0xe6,0xea,0xec]
+@ CHECK: stcl p7, c15, [r11], #-72 @ encoding: [0x12,0xf7,0x6b,0xec]
+
+@ CHECK: stclo p12, c4, [r0, #4] @ encoding: [0x01,0x4c,0x80,0x3d]
+@ CHECK: stchi p13, c5, [r1] @ encoding: [0x00,0x5d,0x81,0x8d]
+@ CHECK: stchs p14, c6, [r2, #-224] @ encoding: [0x38,0x6e,0x02,0x2d]
+@ CHECK: stclo p15, c7, [r3, #-120]! @ encoding: [0x1e,0x7f,0x23,0x3d]
+@ CHECK: stceq p5, c8, [r4], #16 @ encoding: [0x04,0x85,0xa4,0x0c]
+@ CHECK: stcgt p4, c9, [r5], #-72 @ encoding: [0x12,0x94,0x25,0xcc]
+@ CHECK: stcllt p3, c10, [r6, #4] @ encoding: [0x01,0xa3,0xc6,0xbd]
+@ CHECK: stclge p2, c11, [r7] @ encoding: [0x00,0xb2,0xc7,0xad]
+@ CHECK: stclle p1, c12, [r8, #-224] @ encoding: [0x38,0xc1,0x48,0xdd]
+@ CHECK: stclne p0, c13, [r9, #-120]! @ encoding: [0x1e,0xd0,0x69,0x1d]
+@ CHECK: stcleq p6, c14, [r10], #16 @ encoding: [0x04,0xe6,0xea,0x0c]
+@ CHECK: stclhi p7, c15, [r11], #-72 @ encoding: [0x12,0xf7,0x6b,0x8c]
+
+@ CHECK: stc2 p2, c8, [r1], {25} @ encoding: [0x19,0x82,0x81,0xfc]
+
+
+@------------------------------------------------------------------------------
@ STM*
@------------------------------------------------------------------------------
stm r2, {r1,r3-r6,sp}
- stmia r2, {r1,r3-r6,sp}
- stmib r2, {r1,r3-r6,sp}
- stmda r2, {r1,r3-r6,sp}
- stmdb r2, {r1,r3-r6,sp}
- stmfd r2, {r1,r3-r6,sp}
+ stmia r3, {r1,r3-r6,lr}
+ stmib r4, {r1,r3-r6,sp}
+ stmda r5, {r1,r3-r6,sp}
+ stmdb r6, {r1,r3-r6,r8}
+ stmfd sp, {r1,r3-r6,sp}
@ with update
- stmia r2!, {r1,r3-r6,sp}
- stmib r2!, {r1,r3-r6,sp}
- stmda r2!, {r1,r3-r6,sp}
- stmdb r2!, {r1,r3-r6,sp}
-@ CHECK: stm r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe8]
-@ CHECK: stm r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe8]
-@ CHECK: stmib r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe9]
-@ CHECK: stmda r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x02,0xe8]
-@ CHECK: stmdb r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x02,0xe9]
-@ CHECK: stmdb r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x02,0xe9]
-
-@ CHECK: stm r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xa2,0xe8]
-@ CHECK: stmib r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xa2,0xe9]
-@ CHECK: stmda r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x22,0xe8]
-@ CHECK: stmdb r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x22,0xe9]
+ stm r8!, {r1,r3-r6,sp}
+ stmib r9!, {r1,r3-r6,sp}
+ stmda sp!, {r1,r3-r6}
+ stmdb r0!, {r1,r5,r7,sp}
+
+@ CHECK: stm r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe8]
+@ CHECK: stm r3, {lr, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x40,0x83,0xe8]
+@ CHECK: stmib r4, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x84,0xe9]
+@ CHECK: stmda r5, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x05,0xe8]
+@ CHECK: stmdb r6, {r1, r3, r4, r5, r6, r8} @ encoding: [0x7a,0x01,0x06,0xe9]
+@ CHECK: stmdb sp, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x0d,0xe9]
+
+@ CHECK: stm r8!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xa8,0xe8]
+@ CHECK: stmib r9!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xa9,0xe9]
+@ CHECK: stmda sp!, {r1, r3, r4, r5, r6} @ encoding: [0x7a,0x00,0x2d,0xe8]
+@ CHECK: stmdb r0!, {r1, r5, r7, sp} @ encoding: [0xa2,0x20,0x20,0xe9]
+
+
+@------------------------------------------------------------------------------
+@ STREX/STREXB/STREXH/STREXD
+@------------------------------------------------------------------------------
+ strexb r1, r3, [r4]
+ strexh r4, r2, [r5]
+ strex r2, r1, [r7]
+ strexd r6, r2, r3, [r8]
+
+@ CHECK: strexb r1, r3, [r4] @ encoding: [0x93,0x1f,0xc4,0xe1]
+@ CHECK: strexh r4, r2, [r5] @ encoding: [0x92,0x4f,0xe5,0xe1]
+@ CHECK: strex r2, r1, [r7] @ encoding: [0x91,0x2f,0x87,0xe1]
+@ CHECK: strexd r6, r2, r3, [r8] @ encoding: [0x92,0x6f,0xa8,0xe1]
+
+@------------------------------------------------------------------------------
+@ STR
+@------------------------------------------------------------------------------
+ strpl r3, [r10, #-0]!
+ strpl r3, [r10, #0]!
+
+@ CHECK: strpl r3, [r10, #-0]! @ encoding: [0x00,0x30,0x2a,0x55]
+@ CHECK: strpl r3, [r10]! @ encoding: [0x00,0x30,0xaa,0x55]
+
+@------------------------------------------------------------------------------
+@ SUB
+@------------------------------------------------------------------------------
+ sub r4, r5, #0xf000
+ sub r4, r5, r6
+ sub r4, r5, r6, lsl #5
+ sub r4, r5, r6, lsr #5
+ sub r4, r5, r6, lsr #5
+ sub r4, r5, r6, asr #5
+ sub r4, r5, r6, ror #5
+ sub r6, r7, r8, lsl r9
+ sub r6, r7, r8, lsr r9
+ sub r6, r7, r8, asr r9
+ sub r6, r7, r8, ror r9
+
+ @ destination register is optional
+ sub r5, #0xf000
+ sub r4, r5
+ sub r4, r5, lsl #5
+ sub r4, r5, lsr #5
+ sub r4, r5, lsr #5
+ sub r4, r5, asr #5
+ sub r4, r5, ror #5
+ sub r6, r7, lsl r9
+ sub r6, r7, lsr r9
+ sub r6, r7, asr r9
+ sub r6, r7, ror r9
+
+@ CHECK: sub r4, r5, #61440 @ encoding: [0x0f,0x4a,0x45,0xe2]
+@ CHECK: sub r4, r5, r6 @ encoding: [0x06,0x40,0x45,0xe0]
+@ CHECK: sub r4, r5, r6, lsl #5 @ encoding: [0x86,0x42,0x45,0xe0]
+@ CHECK: sub r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0x45,0xe0]
+@ CHECK: sub r4, r5, r6, lsr #5 @ encoding: [0xa6,0x42,0x45,0xe0]
+@ CHECK: sub r4, r5, r6, asr #5 @ encoding: [0xc6,0x42,0x45,0xe0]
+@ CHECK: sub r4, r5, r6, ror #5 @ encoding: [0xe6,0x42,0x45,0xe0]
+@ CHECK: sub r6, r7, r8, lsl r9 @ encoding: [0x18,0x69,0x47,0xe0]
+@ CHECK: sub r6, r7, r8, lsr r9 @ encoding: [0x38,0x69,0x47,0xe0]
+@ CHECK: sub r6, r7, r8, asr r9 @ encoding: [0x58,0x69,0x47,0xe0]
+@ CHECK: sub r6, r7, r8, ror r9 @ encoding: [0x78,0x69,0x47,0xe0]
+
+
+@ CHECK: sub r5, r5, #61440 @ encoding: [0x0f,0x5a,0x45,0xe2]
+@ CHECK: sub r4, r4, r5 @ encoding: [0x05,0x40,0x44,0xe0]
+@ CHECK: sub r4, r4, r5, lsl #5 @ encoding: [0x85,0x42,0x44,0xe0]
+@ CHECK: sub r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0x44,0xe0]
+@ CHECK: sub r4, r4, r5, lsr #5 @ encoding: [0xa5,0x42,0x44,0xe0]
+@ CHECK: sub r4, r4, r5, asr #5 @ encoding: [0xc5,0x42,0x44,0xe0]
+@ CHECK: sub r4, r4, r5, ror #5 @ encoding: [0xe5,0x42,0x44,0xe0]
+@ CHECK: sub r6, r6, r7, lsl r9 @ encoding: [0x17,0x69,0x46,0xe0]
+@ CHECK: sub r6, r6, r7, lsr r9 @ encoding: [0x37,0x69,0x46,0xe0]
+@ CHECK: sub r6, r6, r7, asr r9 @ encoding: [0x57,0x69,0x46,0xe0]
+@ CHECK: sub r6, r6, r7, ror r9 @ encoding: [0x77,0x69,0x46,0xe0]
+
+
+@------------------------------------------------------------------------------
+@ SVC
+@------------------------------------------------------------------------------
+ svc #16
+ svc #0
+ svc #0xffffff
+
+@ CHECK: svc #16 @ encoding: [0x10,0x00,0x00,0xef]
+@ CHECK: svc #0 @ encoding: [0x00,0x00,0x00,0xef]
+@ CHECK: svc #16777215 @ encoding: [0xff,0xff,0xff,0xef]
+
+
+@------------------------------------------------------------------------------
+@ SWP/SWPB
+@------------------------------------------------------------------------------
+ swp r1, r2, [r3]
+ swp r4, r4, [r6]
+ swpb r5, r1, [r9]
+
+@ CHECK: swp r1, r2, [r3] @ encoding: [0x92,0x10,0x03,0xe1]
+@ CHECK: swp r4, r4, [r6] @ encoding: [0x94,0x40,0x06,0xe1]
+@ CHECK: swpb r5, r1, [r9] @ encoding: [0x91,0x50,0x49,0xe1]
+
+
+@------------------------------------------------------------------------------
+@ SXTAB
+@------------------------------------------------------------------------------
+ sxtab r2, r3, r4
+ sxtab r4, r5, r6, ror #0
+ sxtablt r6, r2, r9, ror #8
+ sxtab r5, r1, r4, ror #16
+ sxtab r7, r8, r3, ror #24
+
+@ CHECK: sxtab r2, r3, r4 @ encoding: [0x74,0x20,0xa3,0xe6]
+@ CHECK: sxtab r4, r5, r6 @ encoding: [0x76,0x40,0xa5,0xe6]
+@ CHECK: sxtablt r6, r2, r9, ror #8 @ encoding: [0x79,0x64,0xa2,0xb6]
+@ CHECK: sxtab r5, r1, r4, ror #16 @ encoding: [0x74,0x58,0xa1,0xe6]
+@ CHECK: sxtab r7, r8, r3, ror #24 @ encoding: [0x73,0x7c,0xa8,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ SXTAB16
+@------------------------------------------------------------------------------
+ sxtab16ge r0, r1, r4
+ sxtab16 r6, r2, r7, ror #0
+ sxtab16 r3, r5, r8, ror #8
+ sxtab16 r3, r2, r1, ror #16
+ sxtab16eq r1, r2, r3, ror #24
+
+@ CHECK: sxtab16ge r0, r1, r4 @ encoding: [0x74,0x00,0x81,0xa6]
+@ CHECK: sxtab16 r6, r2, r7 @ encoding: [0x77,0x60,0x82,0xe6]
+@ CHECK: sxtab16 r3, r5, r8, ror #8 @ encoding: [0x78,0x34,0x85,0xe6]
+@ CHECK: sxtab16 r3, r2, r1, ror #16 @ encoding: [0x71,0x38,0x82,0xe6]
+@ CHECK: sxtab16eq r1, r2, r3, ror #24 @ encoding: [0x73,0x1c,0x82,0x06]
+
+@------------------------------------------------------------------------------
+@ SXTAH
+@------------------------------------------------------------------------------
+ sxtah r1, r3, r9
+ sxtahhi r6, r1, r6, ror #0
+ sxtah r3, r8, r3, ror #8
+ sxtahlo r2, r2, r4, ror #16
+ sxtah r9, r3, r3, ror #24
+
+@ CHECK: sxtah r1, r3, r9 @ encoding: [0x79,0x10,0xb3,0xe6]
+@ CHECK: sxtahhi r6, r1, r6 @ encoding: [0x76,0x60,0xb1,0x86]
+@ CHECK: sxtah r3, r8, r3, ror #8 @ encoding: [0x73,0x34,0xb8,0xe6]
+@ CHECK: sxtahlo r2, r2, r4, ror #16 @ encoding: [0x74,0x28,0xb2,0x36]
+@ CHECK: sxtah r9, r3, r3, ror #24 @ encoding: [0x73,0x9c,0xb3,0xe6]
+
+@------------------------------------------------------------------------------
+@ SXTB
+@------------------------------------------------------------------------------
+ sxtbge r2, r4
+ sxtb r5, r6, ror #0
+ sxtb r6, r9, ror #8
+ sxtbcc r5, r1, ror #16
+ sxtb r8, r3, ror #24
+
+@ CHECK: sxtbge r2, r4 @ encoding: [0x74,0x20,0xaf,0xa6]
+@ CHECK: sxtb r5, r6 @ encoding: [0x76,0x50,0xaf,0xe6]
+@ CHECK: sxtb r6, r9, ror #8 @ encoding: [0x79,0x64,0xaf,0xe6]
+@ CHECK: sxtblo r5, r1, ror #16 @ encoding: [0x71,0x58,0xaf,0x36]
+@ CHECK: sxtb r8, r3, ror #24 @ encoding: [0x73,0x8c,0xaf,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ SXTB16
+@------------------------------------------------------------------------------
+ sxtb16 r1, r4
+ sxtb16 r6, r7, ror #0
+ sxtb16cs r3, r5, ror #8
+ sxtb16 r3, r1, ror #16
+ sxtb16ge r2, r3, ror #24
+
+@ CHECK: sxtb16 r1, r4 @ encoding: [0x74,0x10,0x8f,0xe6]
+@ CHECK: sxtb16 r6, r7 @ encoding: [0x77,0x60,0x8f,0xe6]
+@ CHECK: sxtb16hs r3, r5, ror #8 @ encoding: [0x75,0x34,0x8f,0x26]
+@ CHECK: sxtb16 r3, r1, ror #16 @ encoding: [0x71,0x38,0x8f,0xe6]
+@ CHECK: sxtb16ge r2, r3, ror #24 @ encoding: [0x73,0x2c,0x8f,0xa6]
+
+
+@------------------------------------------------------------------------------
+@ SXTH
+@------------------------------------------------------------------------------
+ sxthne r3, r9
+ sxth r1, r6, ror #0
+ sxth r3, r8, ror #8
+ sxthle r2, r2, ror #16
+ sxth r9, r3, ror #24
+
+@ CHECK: sxthne r3, r9 @ encoding: [0x79,0x30,0xbf,0x16]
+@ CHECK: sxth r1, r6 @ encoding: [0x76,0x10,0xbf,0xe6]
+@ CHECK: sxth r3, r8, ror #8 @ encoding: [0x78,0x34,0xbf,0xe6]
+@ CHECK: sxthle r2, r2, ror #16 @ encoding: [0x72,0x28,0xbf,0xd6]
+@ CHECK: sxth r9, r3, ror #24 @ encoding: [0x73,0x9c,0xbf,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ TEQ
+@------------------------------------------------------------------------------
+ teq r5, #0xf000
+ teq r4, r5
+ teq r4, r5, lsl #5
+ teq r4, r5, lsr #5
+ teq r4, r5, lsr #5
+ teq r4, r5, asr #5
+ teq r4, r5, ror #5
+ teq r6, r7, lsl r9
+ teq r6, r7, lsr r9
+ teq r6, r7, asr r9
+ teq r6, r7, ror r9
+
+@ CHECK: teq r5, #61440 @ encoding: [0x0f,0x0a,0x35,0xe3]
+@ CHECK: teq r4, r5 @ encoding: [0x05,0x00,0x34,0xe1]
+@ CHECK: teq r4, r5, lsl #5 @ encoding: [0x85,0x02,0x34,0xe1]
+@ CHECK: teq r4, r5, lsr #5 @ encoding: [0xa5,0x02,0x34,0xe1]
+@ CHECK: teq r4, r5, lsr #5 @ encoding: [0xa5,0x02,0x34,0xe1]
+@ CHECK: teq r4, r5, asr #5 @ encoding: [0xc5,0x02,0x34,0xe1]
+@ CHECK: teq r4, r5, ror #5 @ encoding: [0xe5,0x02,0x34,0xe1]
+@ CHECK: teq r6, r7, lsl r9 @ encoding: [0x17,0x09,0x36,0xe1]
+@ CHECK: teq r6, r7, lsr r9 @ encoding: [0x37,0x09,0x36,0xe1]
+@ CHECK: teq r6, r7, asr r9 @ encoding: [0x57,0x09,0x36,0xe1]
+@ CHECK: teq r6, r7, ror r9 @ encoding: [0x77,0x09,0x36,0xe1]
+
+
+@------------------------------------------------------------------------------
+@ TST
+@------------------------------------------------------------------------------
+ tst r5, #0xf000
+ tst r4, r5
+ tst r4, r5, lsl #5
+ tst r4, r5, lsr #5
+ tst r4, r5, lsr #5
+ tst r4, r5, asr #5
+ tst r4, r5, ror #5
+ tst r6, r7, lsl r9
+ tst r6, r7, lsr r9
+ tst r6, r7, asr r9
+ tst r6, r7, ror r9
+
+@ CHECK: tst r5, #61440 @ encoding: [0x0f,0x0a,0x15,0xe3]
+@ CHECK: tst r4, r5 @ encoding: [0x05,0x00,0x14,0xe1]
+@ CHECK: tst r4, r5, lsl #5 @ encoding: [0x85,0x02,0x14,0xe1]
+@ CHECK: tst r4, r5, lsr #5 @ encoding: [0xa5,0x02,0x14,0xe1]
+@ CHECK: tst r4, r5, lsr #5 @ encoding: [0xa5,0x02,0x14,0xe1]
+@ CHECK: tst r4, r5, asr #5 @ encoding: [0xc5,0x02,0x14,0xe1]
+@ CHECK: tst r4, r5, ror #5 @ encoding: [0xe5,0x02,0x14,0xe1]
+@ CHECK: tst r6, r7, lsl r9 @ encoding: [0x17,0x09,0x16,0xe1]
+@ CHECK: tst r6, r7, lsr r9 @ encoding: [0x37,0x09,0x16,0xe1]
+@ CHECK: tst r6, r7, asr r9 @ encoding: [0x57,0x09,0x16,0xe1]
+@ CHECK: tst r6, r7, ror r9 @ encoding: [0x77,0x09,0x16,0xe1]
+
+
+@------------------------------------------------------------------------------
+@ UADD16/UADD8
+@------------------------------------------------------------------------------
+ uadd16 r1, r2, r3
+ uadd16gt r1, r2, r3
+ uadd8 r1, r2, r3
+ uadd8le r1, r2, r3
+
+@ CHECK: uadd16 r1, r2, r3 @ encoding: [0x13,0x1f,0x52,0xe6]
+@ CHECK: uadd16gt r1, r2, r3 @ encoding: [0x13,0x1f,0x52,0xc6]
+@ CHECK: uadd8 r1, r2, r3 @ encoding: [0x93,0x1f,0x52,0xe6]
+@ CHECK: uadd8le r1, r2, r3 @ encoding: [0x93,0x1f,0x52,0xd6]
+
+
+@------------------------------------------------------------------------------
+@ UASX
+@------------------------------------------------------------------------------
+ uasx r9, r12, r0
+ uasxeq r9, r12, r0
+
+@ CHECK: uasx r9, r12, r0 @ encoding: [0x30,0x9f,0x5c,0xe6]
+@ CHECK: uasxeq r9, r12, r0 @ encoding: [0x30,0x9f,0x5c,0x06]
+
+
+@------------------------------------------------------------------------------
+@ UBFX
+@------------------------------------------------------------------------------
+ ubfx r4, r5, #16, #1
+ ubfxgt r4, r5, #16, #16
+
+@ CHECK: ubfx r4, r5, #16, #1 @ encoding: [0x55,0x48,0xe0,0xe7]
+@ CHECK: ubfxgt r4, r5, #16, #16 @ encoding: [0x55,0x48,0xef,0xc7]
+
+
+@------------------------------------------------------------------------------
+@ UHADD16/UHADD8
+@------------------------------------------------------------------------------
+ uhadd16 r4, r8, r2
+ uhadd16gt r4, r8, r2
+ uhadd8 r4, r8, r2
+ uhadd8gt r4, r8, r2
+
+@ CHECK: uhadd16 r4, r8, r2 @ encoding: [0x12,0x4f,0x78,0xe6]
+@ CHECK: uhadd16gt r4, r8, r2 @ encoding: [0x12,0x4f,0x78,0xc6]
+@ CHECK: uhadd8 r4, r8, r2 @ encoding: [0x92,0x4f,0x78,0xe6]
+@ CHECK: uhadd8gt r4, r8, r2 @ encoding: [0x92,0x4f,0x78,0xc6]
+
+
+@------------------------------------------------------------------------------
+@ UHASX
+@------------------------------------------------------------------------------
+ uhasx r4, r8, r2
+ uhasxgt r4, r8, r2
+
+@ CHECK: uhasx r4, r8, r2 @ encoding: [0x32,0x4f,0x78,0xe6]
+@ CHECK: uhasxgt r4, r8, r2 @ encoding: [0x32,0x4f,0x78,0xc6]
+
+
+@------------------------------------------------------------------------------
+@ UHSUB16/UHSUB8
+@------------------------------------------------------------------------------
+ uhsub16 r4, r8, r2
+ uhsub16gt r4, r8, r2
+ uhsub8 r4, r8, r2
+ uhsub8gt r4, r8, r2
+
+@ CHECK: uhsub16 r4, r8, r2 @ encoding: [0x72,0x4f,0x78,0xe6]
+@ CHECK: uhsub16gt r4, r8, r2 @ encoding: [0x72,0x4f,0x78,0xc6]
+@ CHECK: uhsub8 r4, r8, r2 @ encoding: [0xf2,0x4f,0x78,0xe6]
+@ CHECK: uhsub8gt r4, r8, r2 @ encoding: [0xf2,0x4f,0x78,0xc6]
+
+
+@------------------------------------------------------------------------------
+@ UMAAL
+@------------------------------------------------------------------------------
+ umaal r3, r4, r5, r6
+ umaallt r3, r4, r5, r6
+
+@ CHECK: umaal r3, r4, r5, r6 @ encoding: [0x95,0x36,0x44,0xe0]
+@ CHECK: umaallt r3, r4, r5, r6 @ encoding: [0x95,0x36,0x44,0xb0]
+
+
+@------------------------------------------------------------------------------
+@ UMLAL
+@------------------------------------------------------------------------------
+ umlal r2, r4, r6, r8
+ umlalgt r6, r1, r2, r6
+ umlals r2, r9, r2, r3
+ umlalseq r3, r5, r1, r2
+
+@ CHECK: umlal r2, r4, r6, r8 @ encoding: [0x96,0x28,0xa4,0xe0]
+@ CHECK: umlalgt r6, r1, r2, r6 @ encoding: [0x92,0x66,0xa1,0xc0]
+@ CHECK: umlals r2, r9, r2, r3 @ encoding: [0x92,0x23,0xb9,0xe0]
+@ CHECK: umlalseq r3, r5, r1, r2 @ encoding: [0x91,0x32,0xb5,0x00]
+
+
+@------------------------------------------------------------------------------
+@ UMULL
+@------------------------------------------------------------------------------
+ umull r2, r4, r6, r8
+ umullgt r6, r1, r2, r6
+ umulls r2, r9, r2, r3
+ umullseq r3, r5, r1, r2
+
+@ CHECK: umull r2, r4, r6, r8 @ encoding: [0x96,0x28,0x84,0xe0]
+@ CHECK: umullgt r6, r1, r2, r6 @ encoding: [0x92,0x66,0x81,0xc0]
+@ CHECK: umulls r2, r9, r2, r3 @ encoding: [0x92,0x23,0x99,0xe0]
+@ CHECK: umullseq r3, r5, r1, r2 @ encoding: [0x91,0x32,0x95,0x00]
+
+
+@------------------------------------------------------------------------------
+@ UQADD16/UQADD8
+@------------------------------------------------------------------------------
+ uqadd16 r1, r2, r3
+ uqadd16gt r4, r7, r9
+ uqadd8 r3, r4, r8
+ uqadd8le r8, r1, r2
+
+
+@ CHECK: uqadd16 r1, r2, r3 @ encoding: [0x13,0x1f,0x62,0xe6]
+@ CHECK: uqadd16gt r4, r7, r9 @ encoding: [0x19,0x4f,0x67,0xc6]
+@ CHECK: uqadd8 r3, r4, r8 @ encoding: [0x98,0x3f,0x64,0xe6]
+@ CHECK: uqadd8le r8, r1, r2 @ encoding: [0x92,0x8f,0x61,0xd6]
+
+
+@------------------------------------------------------------------------------
+@ UQASX
+@------------------------------------------------------------------------------
+ uqasx r2, r4, r1
+ uqasxhi r5, r2, r9
+
+@ CHECK: uqasx r2, r4, r1 @ encoding: [0x31,0x2f,0x64,0xe6]
+@ CHECK: uqasxhi r5, r2, r9 @ encoding: [0x39,0x5f,0x62,0x86]
+
+
+@------------------------------------------------------------------------------
+@ UQSAX
+@------------------------------------------------------------------------------
+ uqsax r1, r3, r7
+ uqsaxal r3, r6, r2
+
+@ CHECK: uqsax r1, r3, r7 @ encoding: [0x57,0x1f,0x63,0xe6]
+@ CHECK: uqsax r3, r6, r2 @ encoding: [0x52,0x3f,0x66,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ UQSUB16/UQSUB8
+@------------------------------------------------------------------------------
+ uqsub16 r1, r5, r3
+ uqsub16gt r3, r2, r5
+ uqsub8 r2, r1, r4
+ uqsub8le r4, r6, r9
+
+@ CHECK: uqsub16 r1, r5, r3 @ encoding: [0x73,0x1f,0x65,0xe6]
+@ CHECK: uqsub16gt r3, r2, r5 @ encoding: [0x75,0x3f,0x62,0xc6]
+@ CHECK: uqsub8 r2, r1, r4 @ encoding: [0xf4,0x2f,0x61,0xe6]
+@ CHECK: uqsub8le r4, r6, r9 @ encoding: [0xf9,0x4f,0x66,0xd6]
+
+
+@------------------------------------------------------------------------------
+@ USADA8/USAD8
+@------------------------------------------------------------------------------
+ usad8 r2, r1, r4
+ usad8le r4, r6, r9
+ usada8 r1, r5, r3, r7
+ usada8gt r3, r2, r5, r1
+
+@ CHECK: usad8 r2, r1, r4 @ encoding: [0x11,0xf4,0x82,0xe7]
+@ CHECK: usad8le r4, r6, r9 @ encoding: [0x16,0xf9,0x84,0xd7]
+@ CHECK: usada8 r1, r5, r3, r7 @ encoding: [0x15,0x73,0x81,0xe7]
+@ CHECK: usada8gt r3, r2, r5, r1 @ encoding: [0x12,0x15,0x83,0xc7]
+
+
+@------------------------------------------------------------------------------
+@ USAT
+@------------------------------------------------------------------------------
+ usat r8, #1, r10
+ usat r8, #4, r10, lsl #0
+ usat r8, #5, r10, lsl #31
+ usat r8, #31, r10, asr #32
+ usat r8, #16, r10, asr #1
+
+@ CHECK: usat r8, #1, r10 @ encoding: [0x1a,0x80,0xe1,0xe6]
+@ CHECK: usat r8, #4, r10 @ encoding: [0x1a,0x80,0xe4,0xe6]
+@ CHECK: usat r8, #5, r10, lsl #31 @ encoding: [0x9a,0x8f,0xe5,0xe6]
+@ CHECK: usat r8, #31, r10, asr #32 @ encoding: [0x5a,0x80,0xff,0xe6]
+@ CHECK: usat r8, #16, r10, asr #1 @ encoding: [0xda,0x80,0xf0,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ USAT16
+@------------------------------------------------------------------------------
+ usat16 r2, #2, r7
+ usat16 r3, #15, r5
+
+@ CHECK: usat16 r2, #2, r7 @ encoding: [0x37,0x2f,0xe2,0xe6]
+@ CHECK: usat16 r3, #15, r5 @ encoding: [0x35,0x3f,0xef,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ USAX
+@------------------------------------------------------------------------------
+ usax r2, r3, r4
+ usaxne r2, r3, r4
+
+@ CHECK: usax r2, r3, r4 @ encoding: [0x54,0x2f,0x53,0xe6]
+@ CHECK: usaxne r2, r3, r4 @ encoding: [0x54,0x2f,0x53,0x16]
+
+@------------------------------------------------------------------------------
+@ USUB16/USUB8
+@------------------------------------------------------------------------------
+ usub16 r4, r2, r7
+ usub16hi r1, r1, r3
+ usub8 r1, r8, r5
+ usub8le r9, r2, r3
+
+@ CHECK: usub16 r4, r2, r7 @ encoding: [0x77,0x4f,0x52,0xe6]
+@ CHECK: usub16hi r1, r1, r3 @ encoding: [0x73,0x1f,0x51,0x86]
+@ CHECK: usub8 r1, r8, r5 @ encoding: [0xf5,0x1f,0x58,0xe6]
+@ CHECK: usub8le r9, r2, r3 @ encoding: [0xf3,0x9f,0x52,0xd6]
+
+
+@------------------------------------------------------------------------------
+@ UXTAB
+@------------------------------------------------------------------------------
+ uxtab r2, r3, r4
+ uxtab r4, r5, r6, ror #0
+ uxtablt r6, r2, r9, ror #8
+ uxtab r5, r1, r4, ror #16
+ uxtab r7, r8, r3, ror #24
+
+@ CHECK: uxtab r2, r3, r4 @ encoding: [0x74,0x20,0xe3,0xe6]
+@ CHECK: uxtab r4, r5, r6 @ encoding: [0x76,0x40,0xe5,0xe6]
+@ CHECK: uxtablt r6, r2, r9, ror #8 @ encoding: [0x79,0x64,0xe2,0xb6]
+@ CHECK: uxtab r5, r1, r4, ror #16 @ encoding: [0x74,0x58,0xe1,0xe6]
+@ CHECK: uxtab r7, r8, r3, ror #24 @ encoding: [0x73,0x7c,0xe8,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ UXTAB16
+@------------------------------------------------------------------------------
+ uxtab16ge r0, r1, r4
+ uxtab16 r6, r2, r7, ror #0
+ uxtab16 r3, r5, r8, ror #8
+ uxtab16 r3, r2, r1, ror #16
+ uxtab16eq r1, r2, r3, ror #24
+
+@ CHECK: uxtab16ge r0, r1, r4 @ encoding: [0x74,0x00,0xc1,0xa6]
+@ CHECK: uxtab16 r6, r2, r7 @ encoding: [0x77,0x60,0xc2,0xe6]
+@ CHECK: uxtab16 r3, r5, r8, ror #8 @ encoding: [0x78,0x34,0xc5,0xe6]
+@ CHECK: uxtab16 r3, r2, r1, ror #16 @ encoding: [0x71,0x38,0xc2,0xe6]
+@ CHECK: uxtab16eq r1, r2, r3, ror #24 @ encoding: [0x73,0x1c,0xc2,0x06]
+
+
+@------------------------------------------------------------------------------
+@ UXTAH
+@------------------------------------------------------------------------------
+ uxtah r1, r3, r9
+ uxtahhi r6, r1, r6, ror #0
+ uxtah r3, r8, r3, ror #8
+ uxtahlo r2, r2, r4, ror #16
+ uxtah r9, r3, r3, ror #24
+
+@ CHECK: uxtah r1, r3, r9 @ encoding: [0x79,0x10,0xf3,0xe6]
+@ CHECK: uxtahhi r6, r1, r6 @ encoding: [0x76,0x60,0xf1,0x86]
+@ CHECK: uxtah r3, r8, r3, ror #8 @ encoding: [0x73,0x34,0xf8,0xe6]
+@ CHECK: uxtahlo r2, r2, r4, ror #16 @ encoding: [0x74,0x28,0xf2,0x36]
+@ CHECK: uxtah r9, r3, r3, ror #24 @ encoding: [0x73,0x9c,0xf3,0xe6]
+
+@------------------------------------------------------------------------------
+@ UXTB
+@------------------------------------------------------------------------------
+ uxtbge r2, r4
+ uxtb r5, r6, ror #0
+ uxtb r6, r9, ror #8
+ uxtbcc r5, r1, ror #16
+ uxtb r8, r3, ror #24
+
+@ CHECK: uxtbge r2, r4 @ encoding: [0x74,0x20,0xef,0xa6]
+@ CHECK: uxtb r5, r6 @ encoding: [0x76,0x50,0xef,0xe6]
+@ CHECK: uxtb r6, r9, ror #8 @ encoding: [0x79,0x64,0xef,0xe6]
+@ CHECK: uxtblo r5, r1, ror #16 @ encoding: [0x71,0x58,0xef,0x36]
+@ CHECK: uxtb r8, r3, ror #24 @ encoding: [0x73,0x8c,0xef,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ UXTB16
+@------------------------------------------------------------------------------
+ uxtb16 r1, r4
+ uxtb16 r6, r7, ror #0
+ uxtb16cs r3, r5, ror #8
+ uxtb16 r3, r1, ror #16
+ uxtb16ge r2, r3, ror #24
+
+@ CHECK: uxtb16 r1, r4 @ encoding: [0x74,0x10,0xcf,0xe6]
+@ CHECK: uxtb16 r6, r7 @ encoding: [0x77,0x60,0xcf,0xe6]
+@ CHECK: uxtb16hs r3, r5, ror #8 @ encoding: [0x75,0x34,0xcf,0x26]
+@ CHECK: uxtb16 r3, r1, ror #16 @ encoding: [0x71,0x38,0xcf,0xe6]
+@ CHECK: uxtb16ge r2, r3, ror #24 @ encoding: [0x73,0x2c,0xcf,0xa6]
+
+
+@------------------------------------------------------------------------------
+@ UXTH
+@------------------------------------------------------------------------------
+ uxthne r3, r9
+ uxth r1, r6, ror #0
+ uxth r3, r8, ror #8
+ uxthle r2, r2, ror #16
+ uxth r9, r3, ror #24
+
+@ CHECK: uxthne r3, r9 @ encoding: [0x79,0x30,0xff,0x16]
+@ CHECK: uxth r1, r6 @ encoding: [0x76,0x10,0xff,0xe6]
+@ CHECK: uxth r3, r8, ror #8 @ encoding: [0x78,0x34,0xff,0xe6]
+@ CHECK: uxthle r2, r2, ror #16 @ encoding: [0x72,0x28,0xff,0xd6]
+@ CHECK: uxth r9, r3, ror #24 @ encoding: [0x73,0x9c,0xff,0xe6]
+
+
+@------------------------------------------------------------------------------
+@ WFE/WFI/YIELD
+@------------------------------------------------------------------------------
+ wfe
+ wfehi
+ wfi
+ wfilt
+ yield
+ yieldne
+
+@ CHECK: wfe @ encoding: [0x02,0xf0,0x20,0xe3]
+@ CHECK: wfehi @ encoding: [0x02,0xf0,0x20,0x83]
+@ CHECK: wfi @ encoding: [0x03,0xf0,0x20,0xe3]
+@ CHECK: wfilt @ encoding: [0x03,0xf0,0x20,0xb3]
+@ CHECK: yield @ encoding: [0x01,0xf0,0x20,0xe3]
+@ CHECK: yieldne @ encoding: [0x01,0xf0,0x20,0x13]
diff --git a/test/MC/ARM/basic-thumb-instructions.s b/test/MC/ARM/basic-thumb-instructions.s
new file mode 100644
index 0000000..0fa52b0
--- /dev/null
+++ b/test/MC/ARM/basic-thumb-instructions.s
@@ -0,0 +1,623 @@
+@---
+@ Run these test in both Thumb1 and Thumb2 modes, as all of the encodings
+@ should be valid, and parse the same, in both.
+@---
+@ RUN: llvm-mc -triple=thumbv6-apple-darwin -show-encoding < %s | FileCheck %s
+@ RUN: llvm-mc -triple=thumbv7-apple-darwin -show-encoding < %s | FileCheck %s
+ .syntax unified
+ .globl _func
+
+@ Check that the assembler can handle the documented syntax from the ARM ARM.
+@ For complex constructs like shifter operands, check more thoroughly for them
+@ once then spot check that following instructions accept the form generally.
+@ This gives us good coverage while keeping the overall size of the test
+@ more reasonable.
+
+
+@ FIXME: Some 3-operand instructions have a 2-operand assembly syntax.
+
+_func:
+@ CHECK: _func
+
+@------------------------------------------------------------------------------
+@ ADC (register)
+@------------------------------------------------------------------------------
+ adcs r4, r6
+
+@ CHECK: adcs r4, r6 @ encoding: [0x74,0x41]
+
+
+@------------------------------------------------------------------------------
+@ ADD (immediate)
+@------------------------------------------------------------------------------
+ adds r1, r2, #3
+@ When Rd is not explicitly specified, encoding T2 is preferred even though
+@ the literal is in the range [0,7] which would allow encoding T1.
+ adds r2, #3
+ adds r2, #8
+
+@ CHECK: adds r1, r2, #3 @ encoding: [0xd1,0x1c]
+@ CHECK: adds r2, #3 @ encoding: [0x03,0x32]
+@ CHECK: adds r2, #8 @ encoding: [0x08,0x32]
+
+
+@------------------------------------------------------------------------------
+@ ADD (register)
+@------------------------------------------------------------------------------
+ adds r1, r2, r3
+ add r2, r8
+
+@ CHECK: adds r1, r2, r3 @ encoding: [0xd1,0x18]
+@ CHECK: add r2, r8 @ encoding: [0x42,0x44]
+
+
+@------------------------------------------------------------------------------
+@ ADD (SP plus immediate)
+@------------------------------------------------------------------------------
+ add sp, #4
+ add sp, #508
+ add sp, sp, #4
+ add r2, sp, #8
+ add r2, sp, #1020
+
+@ CHECK: add sp, #4 @ encoding: [0x01,0xb0]
+@ CHECK: add sp, #508 @ encoding: [0x7f,0xb0]
+@ CHECK: add sp, #4 @ encoding: [0x01,0xb0]
+@ CHECK: add r2, sp, #8 @ encoding: [0x02,0xaa]
+@ CHECK: add r2, sp, #1020 @ encoding: [0xff,0xaa]
+
+
+@------------------------------------------------------------------------------
+@ ADD (SP plus register)
+@------------------------------------------------------------------------------
+ add sp, r3
+ add r2, sp, r2
+
+@ CHECK: add sp, r3 @ encoding: [0x9d,0x44]
+@ CHECK: add r2, sp, r2 @ encoding: [0x6a,0x44]
+
+
+@------------------------------------------------------------------------------
+@ ADR
+@------------------------------------------------------------------------------
+ adr r2, _baz
+ adr r2, #3
+
+@ CHECK: adr r2, _baz @ encoding: [A,0xa2]
+ @ fixup A - offset: 0, value: _baz, kind: fixup_thumb_adr_pcrel_10
+@ CHECK: adr r2, #3 @ encoding: [0x03,0xa2]
+
+@------------------------------------------------------------------------------
+@ ASR (immediate)
+@------------------------------------------------------------------------------
+ asrs r2, r3, #32
+ asrs r2, r3, #5
+ asrs r2, r3, #1
+
+@ CHECK: asrs r2, r3, #32 @ encoding: [0x1a,0x10]
+@ CHECK: asrs r2, r3, #5 @ encoding: [0x5a,0x11]
+@ CHECK: asrs r2, r3, #1 @ encoding: [0x5a,0x10]
+
+
+@------------------------------------------------------------------------------
+@ ASR (register)
+@------------------------------------------------------------------------------
+ asrs r5, r2
+
+@ CHECK: asrs r5, r2 @ encoding: [0x15,0x41]
+
+
+@------------------------------------------------------------------------------
+@ B
+@------------------------------------------------------------------------------
+ b _baz
+ beq _bar
+ b #1838
+ b #-420
+ beq #336
+ beq #160
+
+@ CHECK: b _baz @ encoding: [A,0xe0'A']
+ @ fixup A - offset: 0, value: _baz, kind: fixup_arm_thumb_br
+@ CHECK: beq _bar @ encoding: [A,0xd0]
+ @ fixup A - offset: 0, value: _bar, kind: fixup_arm_thumb_bcc
+@ CHECK: b #1838 @ encoding: [0x97,0xe3]
+@ CHECK: b #-420 @ encoding: [0x2e,0xe7]
+@ CHECK: beq #336 @ encoding: [0xa8,0xd0]
+@ CHECK: beq #160 @ encoding: [0x50,0xd0]
+
+@------------------------------------------------------------------------------
+@ BL/BLX
+@------------------------------------------------------------------------------
+ blx #884800
+ blx #1769600
+
+@ CHECK: blx #884800 @ encoding: [0xd8,0xf0,0x20,0xe8]
+@ CHECK: blx #1769600 @ encoding: [0xb0,0xf1,0x40,0xe8]
+
+@------------------------------------------------------------------------------
+@ BICS
+@------------------------------------------------------------------------------
+ bics r1, r6
+
+@ CHECK: bics r1, r6 @ encoding: [0xb1,0x43]
+
+
+@------------------------------------------------------------------------------
+@ BKPT
+@------------------------------------------------------------------------------
+ bkpt #0
+ bkpt #255
+
+@ CHECK: bkpt #0 @ encoding: [0x00,0xbe]
+@ CHECK: bkpt #255 @ encoding: [0xff,0xbe]
+
+
+@------------------------------------------------------------------------------
+@ BL/BLX (immediate)
+@------------------------------------------------------------------------------
+ bl _bar
+ blx _baz
+
+@ CHECK: bl _bar @ encoding: [A,0xf0'A',A,0xf8'A']
+ @ fixup A - offset: 0, value: _bar, kind: fixup_arm_thumb_bl
+@ CHECK: blx _baz @ encoding: [A,0xf0'A',A,0xe8'A']
+ @ fixup A - offset: 0, value: _baz, kind: fixup_arm_thumb_blx
+
+
+@------------------------------------------------------------------------------
+@ BLX (register)
+@------------------------------------------------------------------------------
+ blx r4
+
+@ CHECK: blx r4 @ encoding: [0xa0,0x47]
+
+
+@------------------------------------------------------------------------------
+@ BX
+@------------------------------------------------------------------------------
+ bx r2
+
+@ CHECK: bx r2 @ encoding: [0x10,0x47]
+
+
+@------------------------------------------------------------------------------
+@ CMN
+@------------------------------------------------------------------------------
+
+ cmn r5, r1
+
+@ CHECK: cmn r5, r1 @ encoding: [0xcd,0x42]
+
+
+@------------------------------------------------------------------------------
+@ CMP
+@------------------------------------------------------------------------------
+ cmp r6, #32
+ cmp r3, r4
+ cmp r8, r1
+
+@ CHECK: cmp r6, #32 @ encoding: [0x20,0x2e]
+@ CHECK: cmp r3, r4 @ encoding: [0xa3,0x42]
+@ CHECK: cmp r8, r1 @ encoding: [0x88,0x45]
+
+@------------------------------------------------------------------------------
+@ EOR
+@------------------------------------------------------------------------------
+ eors r4, r5
+
+@ CHECK: eors r4, r5 @ encoding: [0x6c,0x40]
+
+
+@------------------------------------------------------------------------------
+@ LDM
+@------------------------------------------------------------------------------
+ ldm r3, {r0, r1, r2, r3, r4, r5, r6, r7}
+ ldm r2!, {r1, r3, r4, r5, r7}
+ ldm r1, {r1}
+
+@ CHECK: ldm r3, {r0, r1, r2, r3, r4, r5, r6, r7} @ encoding: [0xff,0xcb]
+@ CHECK: ldm r2!, {r1, r3, r4, r5, r7} @ encoding: [0xba,0xca]
+@ CHECK: ldm r1, {r1} @ encoding: [0x02,0xc9]
+
+
+@------------------------------------------------------------------------------
+@ LDR (immediate)
+@------------------------------------------------------------------------------
+ ldr r1, [r5]
+ ldr r2, [r6, #32]
+ ldr r3, [r7, #124]
+ ldr r1, [sp]
+ ldr r2, [sp, #24]
+ ldr r3, [sp, #1020]
+
+
+@ CHECK: ldr r1, [r5] @ encoding: [0x29,0x68]
+@ CHECK: ldr r2, [r6, #32] @ encoding: [0x32,0x6a]
+@ CHECK: ldr r3, [r7, #124] @ encoding: [0xfb,0x6f]
+@ CHECK: ldr r1, [sp] @ encoding: [0x00,0x99]
+@ CHECK: ldr r2, [sp, #24] @ encoding: [0x06,0x9a]
+@ CHECK: ldr r3, [sp, #1020] @ encoding: [0xff,0x9b]
+
+
+@------------------------------------------------------------------------------
+@ LDR (literal)
+@------------------------------------------------------------------------------
+ ldr r1, _foo
+ ldr r3, #604
+ ldr r3, #368
+
+@ CHECK: ldr r1, _foo @ encoding: [A,0x49]
+ @ fixup A - offset: 0, value: _foo, kind: fixup_arm_thumb_cp
+@ CHECK: ldr r3, #604 @ encoding: [0x97,0x4b]
+@ CHECK: ldr r3, #368 @ encoding: [0x5c,0x4b]
+
+@------------------------------------------------------------------------------
+@ LDR (register)
+@------------------------------------------------------------------------------
+ ldr r1, [r2, r3]
+
+@ CHECK: ldr r1, [r2, r3] @ encoding: [0xd1,0x58]
+
+
+@------------------------------------------------------------------------------
+@ LDRB (immediate)
+@------------------------------------------------------------------------------
+ ldrb r4, [r3]
+ ldrb r5, [r6, #0]
+ ldrb r6, [r7, #31]
+
+@ CHECK: ldrb r4, [r3] @ encoding: [0x1c,0x78]
+@ CHECK: ldrb r5, [r6] @ encoding: [0x35,0x78]
+@ CHECK: ldrb r6, [r7, #31] @ encoding: [0xfe,0x7f]
+
+
+@------------------------------------------------------------------------------
+@ LDRB (register)
+@------------------------------------------------------------------------------
+ ldrb r6, [r4, r5]
+
+@ CHECK: ldrb r6, [r4, r5] @ encoding: [0x66,0x5d]
+
+
+@------------------------------------------------------------------------------
+@ LDRH (immediate)
+@------------------------------------------------------------------------------
+ ldrh r3, [r3]
+ ldrh r4, [r6, #2]
+ ldrh r5, [r7, #62]
+
+@ CHECK: ldrh r3, [r3] @ encoding: [0x1b,0x88]
+@ CHECK: ldrh r4, [r6, #2] @ encoding: [0x74,0x88]
+@ CHECK: ldrh r5, [r7, #62] @ encoding: [0xfd,0x8f]
+
+
+@------------------------------------------------------------------------------
+@ LDRH (register)
+@------------------------------------------------------------------------------
+ ldrh r6, [r2, r6]
+
+@ CHECK: ldrh r6, [r2, r6] @ encoding: [0x96,0x5b]
+
+
+@------------------------------------------------------------------------------
+@ LDRSB/LDRSH
+@------------------------------------------------------------------------------
+ ldrsb r6, [r2, r6]
+ ldrsh r3, [r7, r1]
+
+@ CHECK: ldrsb r6, [r2, r6] @ encoding: [0x96,0x57]
+@ CHECK: ldrsh r3, [r7, r1] @ encoding: [0x7b,0x5e]
+
+
+@------------------------------------------------------------------------------
+@ LSL (immediate)
+@------------------------------------------------------------------------------
+ lsls r4, r5, #0
+ lsls r4, r5, #4
+
+@ CHECK: lsls r4, r5, #0 @ encoding: [0x2c,0x00]
+@ CHECK: lsls r4, r5, #4 @ encoding: [0x2c,0x01]
+
+
+@------------------------------------------------------------------------------
+@ LSL (register)
+@------------------------------------------------------------------------------
+ lsls r2, r6
+
+@ CHECK: lsls r2, r6 @ encoding: [0xb2,0x40]
+
+
+@------------------------------------------------------------------------------
+@ LSR (immediate)
+@------------------------------------------------------------------------------
+ lsrs r1, r3, #1
+ lsrs r1, r3, #32
+
+@ CHECK: lsrs r1, r3, #1 @ encoding: [0x59,0x08]
+@ CHECK: lsrs r1, r3, #32 @ encoding: [0x19,0x08]
+
+
+@------------------------------------------------------------------------------
+@ LSR (register)
+@------------------------------------------------------------------------------
+ lsrs r2, r6
+
+@ CHECK: lsrs r2, r6 @ encoding: [0xf2,0x40]
+
+
+@------------------------------------------------------------------------------
+@ MOV (immediate)
+@------------------------------------------------------------------------------
+ movs r2, #0
+ movs r2, #255
+ movs r2, #23
+
+@ CHECK: movs r2, #0 @ encoding: [0x00,0x22]
+@ CHECK: movs r2, #255 @ encoding: [0xff,0x22]
+@ CHECK: movs r2, #23 @ encoding: [0x17,0x22]
+
+
+@------------------------------------------------------------------------------
+@ MOV (register)
+@------------------------------------------------------------------------------
+ mov r3, r4
+ movs r1, r3
+
+@ CHECK: mov r3, r4 @ encoding: [0x23,0x46]
+@ CHECK: movs r1, r3 @ encoding: [0x19,0x00]
+
+
+@------------------------------------------------------------------------------
+@ MUL
+@------------------------------------------------------------------------------
+ muls r1, r2, r1
+ muls r3, r4
+
+@ CHECK: muls r1, r2, r1 @ encoding: [0x51,0x43]
+@ CHECK: muls r3, r4, r3 @ encoding: [0x63,0x43]
+
+
+@------------------------------------------------------------------------------
+@ MVN
+@------------------------------------------------------------------------------
+ mvns r6, r3
+
+@ CHECK: mvns r6, r3 @ encoding: [0xde,0x43]
+
+
+@------------------------------------------------------------------------------
+@ NEG
+@------------------------------------------------------------------------------
+ negs r3, r4
+
+@ CHECK: rsbs r3, r4, #0 @ encoding: [0x63,0x42]
+
+@------------------------------------------------------------------------------
+@ ORR
+@------------------------------------------------------------------------------
+ orrs r3, r4
+
+@ CHECK-ERRORS: orrs r3, r4 @ encoding: [0x23,0x43]
+
+
+@------------------------------------------------------------------------------
+@ POP
+@------------------------------------------------------------------------------
+ pop {r2, r3, r6}
+
+@ CHECK: pop {r2, r3, r6} @ encoding: [0x4c,0xbc]
+
+
+@------------------------------------------------------------------------------
+@ PUSH
+@------------------------------------------------------------------------------
+ push {r1, r2, r7}
+
+@ CHECK: push {r1, r2, r7} @ encoding: [0x86,0xb4]
+
+
+@------------------------------------------------------------------------------
+@ REV/REV16/REVSH
+@------------------------------------------------------------------------------
+ rev r6, r3
+ rev16 r7, r2
+ revsh r5, r1
+
+@ CHECK: rev r6, r3 @ encoding: [0x1e,0xba]
+@ CHECK: rev16 r7, r2 @ encoding: [0x57,0xba]
+@ CHECK: revsh r5, r1 @ encoding: [0xcd,0xba]
+
+
+@------------------------------------------------------------------------------
+@ ROR
+@------------------------------------------------------------------------------
+ rors r2, r7
+
+@ CHECK: rors r2, r7 @ encoding: [0xfa,0x41]
+
+
+@------------------------------------------------------------------------------
+@ RSB
+@------------------------------------------------------------------------------
+ rsbs r1, r3, #0
+
+@ CHECK: rsbs r1, r3, #0 @ encoding: [0x59,0x42]
+
+
+@------------------------------------------------------------------------------
+@ SBC
+@------------------------------------------------------------------------------
+ sbcs r4, r3
+
+@ CHECK: sbcs r4, r3 @ encoding: [0x9c,0x41]
+
+
+@------------------------------------------------------------------------------
+@ SETEND
+@------------------------------------------------------------------------------
+ setend be
+ setend le
+
+@ CHECK: setend be @ encoding: [0x58,0xb6]
+@ CHECK: setend le @ encoding: [0x50,0xb6]
+
+
+@------------------------------------------------------------------------------
+@ STM
+@------------------------------------------------------------------------------
+ stm r1!, {r2, r6}
+ stm r1!, {r1, r2, r3, r7}
+
+@ CHECK: stm r1!, {r2, r6} @ encoding: [0x44,0xc1]
+@ CHECK: stm r1!, {r1, r2, r3, r7} @ encoding: [0x8e,0xc1]
+
+
+@------------------------------------------------------------------------------
+@ STR (immediate)
+@------------------------------------------------------------------------------
+ str r2, [r7]
+ str r2, [r7, #0]
+ str r5, [r1, #4]
+ str r3, [r7, #124]
+ str r2, [sp]
+ str r3, [sp, #0]
+ str r4, [sp, #20]
+ str r5, [sp, #1020]
+
+@ CHECK: str r2, [r7] @ encoding: [0x3a,0x60]
+@ CHECK: str r2, [r7] @ encoding: [0x3a,0x60]
+@ CHECK: str r5, [r1, #4] @ encoding: [0x4d,0x60]
+@ CHECK: str r3, [r7, #124] @ encoding: [0xfb,0x67]
+@ CHECK: str r2, [sp] @ encoding: [0x00,0x92]
+@ CHECK: str r3, [sp] @ encoding: [0x00,0x93]
+@ CHECK: str r4, [sp, #20] @ encoding: [0x05,0x94]
+@ CHECK: str r5, [sp, #1020] @ encoding: [0xff,0x95]
+
+
+@------------------------------------------------------------------------------
+@ STR (register)
+@------------------------------------------------------------------------------
+ str r2, [r7, r3]
+
+@ CHECK: str r2, [r7, r3] @ encoding: [0xfa,0x50]
+
+
+@------------------------------------------------------------------------------
+@ STRB (immediate)
+@------------------------------------------------------------------------------
+ strb r4, [r3]
+ strb r5, [r6, #0]
+ strb r6, [r7, #31]
+
+@ CHECK: strb r4, [r3] @ encoding: [0x1c,0x70]
+@ CHECK: strb r5, [r6] @ encoding: [0x35,0x70]
+@ CHECK: strb r6, [r7, #31] @ encoding: [0xfe,0x77]
+
+
+@------------------------------------------------------------------------------
+@ STRB (register)
+@------------------------------------------------------------------------------
+ strb r6, [r4, r5]
+
+@ CHECK: strb r6, [r4, r5] @ encoding: [0x66,0x55]
+
+
+@------------------------------------------------------------------------------
+@ STRH (immediate)
+@------------------------------------------------------------------------------
+ strh r3, [r3]
+ strh r4, [r6, #2]
+ strh r5, [r7, #62]
+
+@ CHECK: strh r3, [r3] @ encoding: [0x1b,0x80]
+@ CHECK: strh r4, [r6, #2] @ encoding: [0x74,0x80]
+@ CHECK: strh r5, [r7, #62] @ encoding: [0xfd,0x87]
+
+
+@------------------------------------------------------------------------------
+@ STRH (register)
+@------------------------------------------------------------------------------
+ strh r6, [r2, r6]
+
+@ CHECK: strh r6, [r2, r6] @ encoding: [0x96,0x53]
+
+
+@------------------------------------------------------------------------------
+@ SUB (immediate)
+@------------------------------------------------------------------------------
+ subs r1, r2, #3
+ subs r2, #3
+ subs r2, #8
+
+@ CHECK: subs r1, r2, #3 @ encoding: [0xd1,0x1e]
+@ CHECK: subs r2, #3 @ encoding: [0x03,0x3a]
+@ CHECK: subs r2, #8 @ encoding: [0x08,0x3a]
+
+
+@------------------------------------------------------------------------------
+@ SUB (SP minus immediate)
+@------------------------------------------------------------------------------
+ sub sp, #12
+ sub sp, sp, #508
+
+@ CHECK: sub sp, #12 @ encoding: [0x83,0xb0]
+@ CHECK: sub sp, #508 @ encoding: [0xff,0xb0]
+
+
+@------------------------------------------------------------------------------
+@ SUB (register)
+@------------------------------------------------------------------------------
+ subs r1, r2, r3
+
+@ CHECK: subs r1, r2, r3 @ encoding: [0xd1,0x1a]
+
+
+@------------------------------------------------------------------------------
+@ SVC
+@------------------------------------------------------------------------------
+ svc #0
+ svc #255
+
+@ CHECK: svc #0 @ encoding: [0x00,0xdf]
+@ CHECK: svc #255 @ encoding: [0xff,0xdf]
+
+
+@------------------------------------------------------------------------------
+@ SXTB/SXTH
+@------------------------------------------------------------------------------
+ sxtb r3, r5
+ sxth r3, r5
+
+@ CHECK: sxtb r3, r5 @ encoding: [0x6b,0xb2]
+@ CHECK: sxth r3, r5 @ encoding: [0x2b,0xb2]
+
+
+@------------------------------------------------------------------------------
+@ TST
+@------------------------------------------------------------------------------
+ tst r6, r1
+
+@ CHECK: tst r6, r1 @ encoding: [0x0e,0x42]
+
+
+@------------------------------------------------------------------------------
+@ UXTB/UXTH
+@------------------------------------------------------------------------------
+ uxtb r7, r2
+ uxth r1, r4
+
+@ CHECK: uxtb r7, r2 @ encoding: [0xd7,0xb2]
+@ CHECK: uxth r1, r4 @ encoding: [0xa1,0xb2]
+
+
+@------------------------------------------------------------------------------
+@ WFE/WFI/YIELD
+@------------------------------------------------------------------------------
+ wfe
+ wfi
+ yield
+
+@ CHECK: wfe @ encoding: [0x20,0xbf]
+@ CHECK: wfi @ encoding: [0x30,0xbf]
+@ CHECK: yield @ encoding: [0x10,0xbf]
diff --git a/test/MC/ARM/basic-thumb2-instructions.s b/test/MC/ARM/basic-thumb2-instructions.s
new file mode 100644
index 0000000..68815da
--- /dev/null
+++ b/test/MC/ARM/basic-thumb2-instructions.s
@@ -0,0 +1,3213 @@
+@ RUN: llvm-mc -triple=thumbv7-apple-darwin -show-encoding < %s | FileCheck %s
+ .syntax unified
+ .globl _func
+
+@ Check that the assembler can handle the documented syntax from the ARM ARM.
+@ For complex constructs like shifter operands, check more thoroughly for them
+@ once then spot check that following instructions accept the form generally.
+@ This gives us good coverage while keeping the overall size of the test
+@ more reasonable.
+
+
+@ FIXME: Some 3-operand instructions have a 2-operand assembly syntax.
+
+_func:
+@ CHECK: _func
+
+@------------------------------------------------------------------------------
+@ ADC (immediate)
+@------------------------------------------------------------------------------
+ adc r0, r1, #4
+ adcs r0, r1, #0
+ adc r1, r2, #255
+ adc r3, r7, #0x00550055
+ adc r8, r12, #0xaa00aa00
+ adc r9, r7, #0xa5a5a5a5
+ adc r5, r3, #0x87000000
+ adc r4, r2, #0x7f800000
+ adc r4, r2, #0x00000680
+
+@ CHECK: adc r0, r1, #4 @ encoding: [0x41,0xf1,0x04,0x00]
+@ CHECK: adcs r0, r1, #0 @ encoding: [0x51,0xf1,0x00,0x00]
+@ CHECK: adc r1, r2, #255 @ encoding: [0x42,0xf1,0xff,0x01]
+@ CHECK: adc r3, r7, #5570645 @ encoding: [0x47,0xf1,0x55,0x13]
+@ CHECK: adc r8, r12, #2852170240 @ encoding: [0x4c,0xf1,0xaa,0x28]
+@ CHECK: adc r9, r7, #2779096485 @ encoding: [0x47,0xf1,0xa5,0x39]
+@ CHECK: adc r5, r3, #2264924160 @ encoding: [0x43,0xf1,0x07,0x45]
+@ CHECK: adc r4, r2, #2139095040 @ encoding: [0x42,0xf1,0xff,0x44]
+@ CHECK: adc r4, r2, #1664 @ encoding: [0x42,0xf5,0xd0,0x64]
+
+@------------------------------------------------------------------------------
+@ ADC (register)
+@------------------------------------------------------------------------------
+ adc r4, r5, r6
+ adcs r4, r5, r6
+ adc.w r9, r1, r3
+ adcs.w r9, r1, r3
+ adc r0, r1, r3, ror #4
+ adcs r0, r1, r3, lsl #7
+ adc.w r0, r1, r3, lsr #31
+ adcs.w r0, r1, r3, asr #32
+
+@ CHECK: adc.w r4, r5, r6 @ encoding: [0x45,0xeb,0x06,0x04]
+@ CHECK: adcs.w r4, r5, r6 @ encoding: [0x55,0xeb,0x06,0x04]
+@ CHECK: adc.w r9, r1, r3 @ encoding: [0x41,0xeb,0x03,0x09]
+@ CHECK: adcs.w r9, r1, r3 @ encoding: [0x51,0xeb,0x03,0x09]
+@ CHECK: adc.w r0, r1, r3, ror #4 @ encoding: [0x41,0xeb,0x33,0x10]
+@ CHECK: adcs.w r0, r1, r3, lsl #7 @ encoding: [0x51,0xeb,0xc3,0x10]
+@ CHECK: adc.w r0, r1, r3, lsr #31 @ encoding: [0x41,0xeb,0xd3,0x70]
+@ CHECK: adcs.w r0, r1, r3, asr #32 @ encoding: [0x51,0xeb,0x23,0x00]
+
+
+@------------------------------------------------------------------------------
+@ ADD (immediate)
+@------------------------------------------------------------------------------
+ itet eq
+ addeq r1, r2, #4
+ addwne r5, r3, #1023
+ addeq r4, r5, #293
+ add r2, sp, #1024
+ add r2, r8, #0xff00
+ add r2, r3, #257
+ addw r2, r3, #257
+ add r12, r6, #0x100
+ addw r12, r6, #0x100
+ adds r1, r2, #0x1f0
+
+@ CHECK: itet eq @ encoding: [0x0a,0xbf]
+@ CHECK: addeq r1, r2, #4 @ encoding: [0x11,0x1d]
+@ CHECK: addwne r5, r3, #1023 @ encoding: [0x03,0xf2,0xff,0x35]
+@ CHECK: addweq r4, r5, #293 @ encoding: [0x05,0xf2,0x25,0x14]
+@ CHECK: add.w r2, sp, #1024 @ encoding: [0x0d,0xf5,0x80,0x62]
+@ CHECK: add.w r2, r8, #65280 @ encoding: [0x08,0xf5,0x7f,0x42]
+@ CHECK: addw r2, r3, #257 @ encoding: [0x03,0xf2,0x01,0x12]
+@ CHECK: addw r2, r3, #257 @ encoding: [0x03,0xf2,0x01,0x12]
+@ CHECK: add.w r12, r6, #256 @ encoding: [0x06,0xf5,0x80,0x7c]
+@ CHECK: addw r12, r6, #256 @ encoding: [0x06,0xf2,0x00,0x1c]
+@ CHECK: adds.w r1, r2, #496 @ encoding: [0x12,0xf5,0xf8,0x71]
+
+
+@------------------------------------------------------------------------------
+@ ADD (register)
+@------------------------------------------------------------------------------
+ add r1, r2, r8
+ add r5, r9, r2, asr #32
+ adds r7, r3, r1, lsl #31
+ adds.w r0, r3, r6, lsr #25
+ add.w r4, r8, r1, ror #12
+
+@ CHECK: add.w r1, r2, r8 @ encoding: [0x02,0xeb,0x08,0x01]
+@ CHECK: add.w r5, r9, r2, asr #32 @ encoding: [0x09,0xeb,0x22,0x05]
+@ CHECK: adds.w r7, r3, r1, lsl #31 @ encoding: [0x13,0xeb,0xc1,0x77]
+@ CHECK: adds.w r0, r3, r6, lsr #25 @ encoding: [0x13,0xeb,0x56,0x60]
+@ CHECK: add.w r4, r8, r1, ror #12 @ encoding: [0x08,0xeb,0x31,0x34]
+
+
+@------------------------------------------------------------------------------
+@ FIXME: ADR
+@------------------------------------------------------------------------------
+
+ subw r11, pc, #3270
+ adr.w r11, #-826
+
+@ CHECK: subw r11, pc, #3270 @ encoding: [0xaf,0xf6,0xc6,0x4b]
+@ CHECK: adr.w r11, #-826 @ encoding: [0xaf,0xf2,0x3a,0x3b]
+
+@------------------------------------------------------------------------------
+@ AND (immediate)
+@------------------------------------------------------------------------------
+ and r2, r5, #0xff000
+ ands r3, r12, #0xf
+ and r1, #0xff
+ and r1, r1, #0xff
+
+@ CHECK: and r2, r5, #1044480 @ encoding: [0x05,0xf4,0x7f,0x22]
+@ CHECK: ands r3, r12, #15 @ encoding: [0x1c,0xf0,0x0f,0x03]
+@ CHECK: and r1, r1, #255 @ encoding: [0x01,0xf0,0xff,0x01]
+@ CHECK: and r1, r1, #255 @ encoding: [0x01,0xf0,0xff,0x01]
+
+
+@------------------------------------------------------------------------------
+@ AND (register)
+@------------------------------------------------------------------------------
+ and r4, r9, r8
+ and r1, r4, r8, asr #3
+ ands r2, r1, r7, lsl #1
+ ands.w r4, r5, r2, lsr #20
+ and.w r9, r12, r1, ror #17
+
+@ CHECK: and.w r4, r9, r8 @ encoding: [0x09,0xea,0x08,0x04]
+@ CHECK: and.w r1, r4, r8, asr #3 @ encoding: [0x04,0xea,0xe8,0x01]
+@ CHECK: ands.w r2, r1, r7, lsl #1 @ encoding: [0x11,0xea,0x47,0x02]
+@ CHECK: ands.w r4, r5, r2, lsr #20 @ encoding: [0x15,0xea,0x12,0x54]
+@ CHECK: and.w r9, r12, r1, ror #17 @ encoding: [0x0c,0xea,0x71,0x49]
+
+@------------------------------------------------------------------------------
+@ ASR (immediate)
+@------------------------------------------------------------------------------
+ asr r2, r3, #12
+ asrs r8, r3, #32
+ asrs.w r2, r3, #1
+ asr r2, r3, #4
+ asrs r2, r12, #15
+
+ asr r3, #19
+ asrs r8, #2
+ asrs.w r7, #5
+ asr.w r12, #21
+
+@ CHECK: asr.w r2, r3, #12 @ encoding: [0x4f,0xea,0x23,0x32]
+@ CHECK: asrs.w r8, r3, #32 @ encoding: [0x5f,0xea,0x23,0x08]
+@ CHECK: asrs.w r2, r3, #1 @ encoding: [0x5f,0xea,0x63,0x02]
+@ CHECK: asr.w r2, r3, #4 @ encoding: [0x4f,0xea,0x23,0x12]
+@ CHECK: asrs.w r2, r12, #15 @ encoding: [0x5f,0xea,0xec,0x32]
+
+@ CHECK: asr.w r3, r3, #19 @ encoding: [0x4f,0xea,0xe3,0x43]
+@ CHECK: asrs.w r8, r8, #2 @ encoding: [0x5f,0xea,0xa8,0x08]
+@ CHECK: asrs.w r7, r7, #5 @ encoding: [0x5f,0xea,0x67,0x17]
+@ CHECK: asr.w r12, r12, #21 @ encoding: [0x4f,0xea,0x6c,0x5c]
+
+
+@------------------------------------------------------------------------------
+@ ASR (register)
+@------------------------------------------------------------------------------
+ asr r3, r4, r2
+ asr.w r1, r2
+ asrs r3, r4, r8
+
+@ CHECK: asr.w r3, r4, r2 @ encoding: [0x44,0xfa,0x02,0xf3]
+@ CHECK: asr.w r1, r1, r2 @ encoding: [0x41,0xfa,0x02,0xf1]
+@ CHECK: asrs.w r3, r4, r8 @ encoding: [0x54,0xfa,0x08,0xf3]
+
+
+@------------------------------------------------------------------------------
+@ B
+@------------------------------------------------------------------------------
+ b.w _bar
+ beq.w _bar
+ it eq
+ beq.w _bar
+ bmi.w #-183396
+
+@ CHECK: b.w _bar @ encoding: [A,0xf0'A',A,0x90'A']
+ @ fixup A - offset: 0, value: _bar, kind: fixup_t2_uncondbranch
+@ CHECK: beq.w _bar @ encoding: [A,0xf0'A',A,0x80'A']
+ @ fixup A - offset: 0, value: _bar, kind: fixup_t2_condbranch
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: beq.w _bar @ encoding: [A,0xf0'A',A,0x90'A']
+ @ fixup A - offset: 0, value: _bar, kind: fixup_t2_uncondbranch
+@ CHECK: bmi.w #-183396 @ encoding: [0x13,0xf5,0xce,0xa9]
+
+
+@------------------------------------------------------------------------------
+@ BFC
+@------------------------------------------------------------------------------
+ bfc r5, #3, #17
+ it lo
+ bfccc r5, #3, #17
+
+@ CHECK: bfc r5, #3, #17 @ encoding: [0x6f,0xf3,0xd3,0x05]
+@ CHECK: it lo @ encoding: [0x38,0xbf]
+@ CHECK: bfclo r5, #3, #17 @ encoding: [0x6f,0xf3,0xd3,0x05]
+
+
+@------------------------------------------------------------------------------
+@ BFI
+@------------------------------------------------------------------------------
+ bfi r5, r2, #3, #17
+ it ne
+ bfine r5, r2, #3, #17
+
+@ CHECK: bfi r5, r2, #3, #17 @ encoding: [0x62,0xf3,0xd3,0x05]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: bfine r5, r2, #3, #17 @ encoding: [0x62,0xf3,0xd3,0x05]
+
+
+@------------------------------------------------------------------------------
+@ BIC
+@------------------------------------------------------------------------------
+ bic r10, r1, #0xf
+ bic r12, r3, r6
+ bic r11, r2, r6, lsl #12
+ bic r8, r4, r1, lsr #11
+ bic r7, r5, r7, lsr #15
+ bic r6, r7, r9, asr #32
+ bic r5, r6, r8, ror #1
+
+ @ destination register is optional
+ bic r1, #0xf
+ bic r1, r1
+ bic r4, r2, lsl #31
+ bic r6, r3, lsr #12
+ bic r7, r4, lsr #7
+ bic r8, r5, asr #15
+ bic r12, r6, ror #29
+
+@ CHECK: bic r10, r1, #15 @ encoding: [0x21,0xf0,0x0f,0x0a]
+@ CHECK: bic.w r12, r3, r6 @ encoding: [0x23,0xea,0x06,0x0c]
+@ CHECK: bic.w r11, r2, r6, lsl #12 @ encoding: [0x22,0xea,0x06,0x3b]
+@ CHECK: bic.w r8, r4, r1, lsr #11 @ encoding: [0x24,0xea,0xd1,0x28]
+@ CHECK: bic.w r7, r5, r7, lsr #15 @ encoding: [0x25,0xea,0xd7,0x37]
+@ CHECK: bic.w r6, r7, r9, asr #32 @ encoding: [0x27,0xea,0x29,0x06]
+@ CHECK: bic.w r5, r6, r8, ror #1 @ encoding: [0x26,0xea,0x78,0x05]
+
+@ CHECK: bic r1, r1, #15 @ encoding: [0x21,0xf0,0x0f,0x01]
+@ CHECK: bic.w r1, r1, r1 @ encoding: [0x21,0xea,0x01,0x01]
+@ CHECK: bic.w r4, r4, r2, lsl #31 @ encoding: [0x24,0xea,0xc2,0x74]
+@ CHECK: bic.w r6, r6, r3, lsr #12 @ encoding: [0x26,0xea,0x13,0x36]
+@ CHECK: bic.w r7, r7, r4, lsr #7 @ encoding: [0x27,0xea,0xd4,0x17]
+@ CHECK: bic.w r8, r8, r5, asr #15 @ encoding: [0x28,0xea,0xe5,0x38]
+@ CHECK: bic.w r12, r12, r6, ror #29 @ encoding: [0x2c,0xea,0x76,0x7c]
+
+@------------------------------------------------------------------------------
+@ BKPT
+@------------------------------------------------------------------------------
+ it pl
+ bkpt #234
+
+@ CHECK: it pl @ encoding: [0x58,0xbf]
+@ CHECK: bkpt #234 @ encoding: [0xea,0xbe]
+
+@------------------------------------------------------------------------------
+@ BXJ
+@------------------------------------------------------------------------------
+ bxj r5
+ it ne
+ bxjne r7
+
+@ CHECK: bxj r5 @ encoding: [0xc5,0xf3,0x00,0x8f]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: bxjne r7 @ encoding: [0xc7,0xf3,0x00,0x8f]
+
+
+@------------------------------------------------------------------------------
+@ CBZ/CBNZ
+@------------------------------------------------------------------------------
+ cbnz r7, #6
+ cbnz r7, #12
+ cbz r6, _bar
+ cbnz r6, _bar
+
+@ CHECK: cbnz r7, #6 @ encoding: [0x1f,0xb9]
+@ CHECK: cbnz r7, #12 @ encoding: [0x37,0xb9]
+@ CHECK: cbz r6, _bar @ encoding: [0x06'A',0xb1'A']
+ @ fixup A - offset: 0, value: _bar, kind: fixup_arm_thumb_cb
+@ CHECK: cbnz r6, _bar @ encoding: [0x06'A',0xb9'A']
+ @ fixup A - offset: 0, value: _bar, kind: fixup_arm_thumb_cb
+
+
+@------------------------------------------------------------------------------
+@ CDP/CDP2
+@------------------------------------------------------------------------------
+ cdp p7, #1, c1, c1, c1, #4
+ cdp2 p7, #1, c1, c1, c1, #4
+
+@ CHECK: cdp p7, #1, c1, c1, c1, #4 @ encoding: [0x11,0xee,0x81,0x17]
+@ CHECK: cdp2 p7, #1, c1, c1, c1, #4 @ encoding: [0x11,0xfe,0x81,0x17]
+
+
+@------------------------------------------------------------------------------
+@ CLREX
+@------------------------------------------------------------------------------
+ clrex
+ it ne
+ clrexne
+
+@ CHECK: clrex @ encoding: [0xbf,0xf3,0x2f,0x8f]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: clrexne @ encoding: [0xbf,0xf3,0x2f,0x8f]
+
+
+@------------------------------------------------------------------------------
+@ CLZ
+@------------------------------------------------------------------------------
+ clz r1, r2
+ it eq
+ clzeq r1, r2
+
+@ CHECK: clz r1, r2 @ encoding: [0xb2,0xfa,0x82,0xf1]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: clzeq r1, r2 @ encoding: [0xb2,0xfa,0x82,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ CMN
+@------------------------------------------------------------------------------
+ cmn r1, #0xf
+ cmn r8, r6
+ cmn r1, r6, lsl #10
+ cmn r1, r6, lsr #10
+ cmn sp, r6, lsr #10
+ cmn r1, r6, asr #10
+ cmn r1, r6, ror #10
+
+@ CHECK: cmn.w r1, #15 @ encoding: [0x11,0xf1,0x0f,0x0f]
+@ CHECK: cmn.w r8, r6 @ encoding: [0x18,0xeb,0x06,0x0f]
+@ CHECK: cmn.w r1, r6, lsl #10 @ encoding: [0x11,0xeb,0x86,0x2f]
+@ CHECK: cmn.w r1, r6, lsr #10 @ encoding: [0x11,0xeb,0x96,0x2f]
+@ CHECK: cmn.w sp, r6, lsr #10 @ encoding: [0x1d,0xeb,0x96,0x2f]
+@ CHECK: cmn.w r1, r6, asr #10 @ encoding: [0x11,0xeb,0xa6,0x2f]
+@ CHECK: cmn.w r1, r6, ror #10 @ encoding: [0x11,0xeb,0xb6,0x2f]
+
+
+@------------------------------------------------------------------------------
+@ CMP
+@------------------------------------------------------------------------------
+ cmp r5, #0xff00
+ cmp.w r4, r12
+ cmp r9, r6, lsl #12
+ cmp r3, r7, lsr #31
+ cmp sp, r6, lsr #1
+ cmp r2, r5, asr #24
+ cmp r1, r4, ror #15
+
+@ CHECK: cmp.w r5, #65280 @ encoding: [0xb5,0xf5,0x7f,0x4f]
+@ CHECK: cmp.w r4, r12 @ encoding: [0xb4,0xeb,0x0c,0x0f]
+@ CHECK: cmp.w r9, r6, lsl #12 @ encoding: [0xb9,0xeb,0x06,0x3f]
+@ CHECK: cmp.w r3, r7, lsr #31 @ encoding: [0xb3,0xeb,0xd7,0x7f]
+@ CHECK: cmp.w sp, r6, lsr #1 @ encoding: [0xbd,0xeb,0x56,0x0f]
+@ CHECK: cmp.w r2, r5, asr #24 @ encoding: [0xb2,0xeb,0x25,0x6f]
+@ CHECK: cmp.w r1, r4, ror #15 @ encoding: [0xb1,0xeb,0xf4,0x3f]
+
+
+@------------------------------------------------------------------------------
+@ DBG
+@------------------------------------------------------------------------------
+ dbg #5
+ dbg #0
+ dbg #15
+
+@ CHECK: dbg #5 @ encoding: [0xaf,0xf3,0xf5,0x80]
+@ CHECK: dbg #0 @ encoding: [0xaf,0xf3,0xf0,0x80]
+@ CHECK: dbg #15 @ encoding: [0xaf,0xf3,0xff,0x80]
+
+
+@------------------------------------------------------------------------------
+@ DMB
+@------------------------------------------------------------------------------
+ dmb sy
+ dmb st
+ dmb sh
+ dmb ish
+ dmb shst
+ dmb ishst
+ dmb un
+ dmb nsh
+ dmb unst
+ dmb nshst
+ dmb osh
+ dmb oshst
+ dmb
+
+@ CHECK: dmb sy @ encoding: [0xbf,0xf3,0x5f,0x8f]
+@ CHECK: dmb st @ encoding: [0xbf,0xf3,0x5e,0x8f]
+@ CHECK: dmb ish @ encoding: [0xbf,0xf3,0x5b,0x8f]
+@ CHECK: dmb ish @ encoding: [0xbf,0xf3,0x5b,0x8f]
+@ CHECK: dmb ishst @ encoding: [0xbf,0xf3,0x5a,0x8f]
+@ CHECK: dmb ishst @ encoding: [0xbf,0xf3,0x5a,0x8f]
+@ CHECK: dmb nsh @ encoding: [0xbf,0xf3,0x57,0x8f]
+@ CHECK: dmb nsh @ encoding: [0xbf,0xf3,0x57,0x8f]
+@ CHECK: dmb nshst @ encoding: [0xbf,0xf3,0x56,0x8f]
+@ CHECK: dmb nshst @ encoding: [0xbf,0xf3,0x56,0x8f]
+@ CHECK: dmb osh @ encoding: [0xbf,0xf3,0x53,0x8f]
+@ CHECK: dmb oshst @ encoding: [0xbf,0xf3,0x52,0x8f]
+@ CHECK: dmb sy @ encoding: [0xbf,0xf3,0x5f,0x8f]
+
+
+@------------------------------------------------------------------------------
+@ DSB
+@------------------------------------------------------------------------------
+ dsb sy
+ dsb st
+ dsb sh
+ dsb ish
+ dsb shst
+ dsb ishst
+ dsb un
+ dsb nsh
+ dsb unst
+ dsb nshst
+ dsb osh
+ dsb oshst
+ dsb
+
+@ CHECK: dsb sy @ encoding: [0xbf,0xf3,0x4f,0x8f]
+@ CHECK: dsb st @ encoding: [0xbf,0xf3,0x4e,0x8f]
+@ CHECK: dsb ish @ encoding: [0xbf,0xf3,0x4b,0x8f]
+@ CHECK: dsb ish @ encoding: [0xbf,0xf3,0x4b,0x8f]
+@ CHECK: dsb ishst @ encoding: [0xbf,0xf3,0x4a,0x8f]
+@ CHECK: dsb ishst @ encoding: [0xbf,0xf3,0x4a,0x8f]
+@ CHECK: dsb nsh @ encoding: [0xbf,0xf3,0x47,0x8f]
+@ CHECK: dsb nsh @ encoding: [0xbf,0xf3,0x47,0x8f]
+@ CHECK: dsb nshst @ encoding: [0xbf,0xf3,0x46,0x8f]
+@ CHECK: dsb nshst @ encoding: [0xbf,0xf3,0x46,0x8f]
+@ CHECK: dsb osh @ encoding: [0xbf,0xf3,0x43,0x8f]
+@ CHECK: dsb oshst @ encoding: [0xbf,0xf3,0x42,0x8f]
+@ CHECK: dsb sy @ encoding: [0xbf,0xf3,0x4f,0x8f]
+
+
+@------------------------------------------------------------------------------
+@ EOR
+@------------------------------------------------------------------------------
+ eor r4, r5, #0xf000
+ eor r4, r5, r6
+ eor r4, r5, r6, lsl #5
+ eor r4, r5, r6, lsr #5
+ eor r4, r5, r6, lsr #5
+ eor r4, r5, r6, asr #5
+ eor r4, r5, r6, ror #5
+
+@ CHECK: eor r4, r5, #61440 @ encoding: [0x85,0xf4,0x70,0x44]
+@ CHECK: eor.w r4, r5, r6 @ encoding: [0x85,0xea,0x06,0x04]
+@ CHECK: eor.w r4, r5, r6, lsl #5 @ encoding: [0x85,0xea,0x46,0x14]
+@ CHECK: eor.w r4, r5, r6, lsr #5 @ encoding: [0x85,0xea,0x56,0x14]
+@ CHECK: eor.w r4, r5, r6, lsr #5 @ encoding: [0x85,0xea,0x56,0x14]
+@ CHECK: eor.w r4, r5, r6, asr #5 @ encoding: [0x85,0xea,0x66,0x14]
+@ CHECK: eor.w r4, r5, r6, ror #5 @ encoding: [0x85,0xea,0x76,0x14]
+
+
+@------------------------------------------------------------------------------
+@ ISB
+@------------------------------------------------------------------------------
+ isb sy
+ isb
+
+@ CHECK: isb sy @ encoding: [0xbf,0xf3,0x6f,0x8f]
+@ CHECK: isb sy @ encoding: [0xbf,0xf3,0x6f,0x8f]
+
+
+@------------------------------------------------------------------------------
+@ IT
+@------------------------------------------------------------------------------
+@ Test encodings of a few full IT blocks, not just the IT instruction
+
+ iteet eq
+ addeq r0, r1, r2
+ nopne
+ subne r5, r6, r7
+ addeq r1, r2, #4
+
+@ CHECK: iteet eq @ encoding: [0x0d,0xbf]
+@ CHECK: addeq r0, r1, r2 @ encoding: [0x88,0x18]
+@ CHECK: nopne @ encoding: [0x00,0xbf]
+@ CHECK: subne r5, r6, r7 @ encoding: [0xf5,0x1b]
+@ CHECK: addeq r1, r2, #4 @ encoding: [0x11,0x1d]
+
+
+@------------------------------------------------------------------------------
+@ LDC{L}/LDC2{L}
+@------------------------------------------------------------------------------
+ ldc2 p0, c8, [r1, #4]
+ ldc2 p1, c7, [r2]
+ ldc2 p2, c6, [r3, #-224]
+ ldc2 p3, c5, [r4, #-120]!
+ ldc2 p4, c4, [r5], #16
+ ldc2 p5, c3, [r6], #-72
+ ldc2l p6, c2, [r7, #4]
+ ldc2l p7, c1, [r8]
+ ldc2l p8, c0, [r9, #-224]
+ ldc2l p9, c1, [r10, #-120]!
+ ldc2l p10, c2, [r11], #16
+ ldc2l p11, c3, [r12], #-72
+
+ ldc p12, c4, [r0, #4]
+ ldc p13, c5, [r1]
+ ldc p14, c6, [r2, #-224]
+ ldc p15, c7, [r3, #-120]!
+ ldc p5, c8, [r4], #16
+ ldc p4, c9, [r5], #-72
+ ldcl p3, c10, [r6, #4]
+ ldcl p2, c11, [r7]
+ ldcl p1, c12, [r8, #-224]
+ ldcl p0, c13, [r9, #-120]!
+ ldcl p6, c14, [r10], #16
+ ldcl p7, c15, [r11], #-72
+
+ ldc2 p2, c8, [r1], { 25 }
+
+@ CHECK: ldc2 p0, c8, [r1, #4] @ encoding: [0x91,0xfd,0x01,0x80]
+@ CHECK: ldc2 p1, c7, [r2] @ encoding: [0x92,0xfd,0x00,0x71]
+@ CHECK: ldc2 p2, c6, [r3, #-224] @ encoding: [0x13,0xfd,0x38,0x62]
+@ CHECK: ldc2 p3, c5, [r4, #-120]! @ encoding: [0x34,0xfd,0x1e,0x53]
+@ CHECK: ldc2 p4, c4, [r5], #16 @ encoding: [0xb5,0xfc,0x04,0x44]
+@ CHECK: ldc2 p5, c3, [r6], #-72 @ encoding: [0x36,0xfc,0x12,0x35]
+@ CHECK: ldc2l p6, c2, [r7, #4] @ encoding: [0xd7,0xfd,0x01,0x26]
+@ CHECK: ldc2l p7, c1, [r8] @ encoding: [0xd8,0xfd,0x00,0x17]
+@ CHECK: ldc2l p8, c0, [r9, #-224] @ encoding: [0x59,0xfd,0x38,0x08]
+@ CHECK: ldc2l p9, c1, [r10, #-120]! @ encoding: [0x7a,0xfd,0x1e,0x19]
+@ CHECK: ldc2l p10, c2, [r11], #16 @ encoding: [0xfb,0xfc,0x04,0x2a]
+@ CHECK: ldc2l p11, c3, [r12], #-72 @ encoding: [0x7c,0xfc,0x12,0x3b]
+
+@ CHECK: ldc p12, c4, [r0, #4] @ encoding: [0x90,0xed,0x01,0x4c]
+@ CHECK: ldc p13, c5, [r1] @ encoding: [0x91,0xed,0x00,0x5d]
+@ CHECK: ldc p14, c6, [r2, #-224] @ encoding: [0x12,0xed,0x38,0x6e]
+@ CHECK: ldc p15, c7, [r3, #-120]! @ encoding: [0x33,0xed,0x1e,0x7f]
+@ CHECK: ldc p5, c8, [r4], #16 @ encoding: [0xb4,0xec,0x04,0x85]
+@ CHECK: ldc p4, c9, [r5], #-72 @ encoding: [0x35,0xec,0x12,0x94]
+@ CHECK: ldcl p3, c10, [r6, #4] @ encoding: [0xd6,0xed,0x01,0xa3]
+@ CHECK: ldcl p2, c11, [r7] @ encoding: [0xd7,0xed,0x00,0xb2]
+@ CHECK: ldcl p1, c12, [r8, #-224] @ encoding: [0x58,0xed,0x38,0xc1]
+@ CHECK: ldcl p0, c13, [r9, #-120]! @ encoding: [0x79,0xed,0x1e,0xd0]
+@ CHECK: ldcl p6, c14, [r10], #16 @ encoding: [0xfa,0xec,0x04,0xe6]
+@ CHECK: ldcl p7, c15, [r11], #-72 @ encoding: [0x7b,0xec,0x12,0xf7]
+
+@ CHECK: ldc2 p2, c8, [r1], {25} @ encoding: [0x91,0xfc,0x19,0x82]
+
+
+@------------------------------------------------------------------------------
+@ LDMIA
+@------------------------------------------------------------------------------
+ ldmia.w r4, {r4, r5, r8, r9}
+ ldmia.w r4, {r5, r6}
+ ldmia.w r5!, {r3, r8}
+ ldm.w r4, {r4, r5, r8, r9}
+ ldm.w r4, {r5, r6}
+ ldm.w r5!, {r3, r8}
+ ldm.w r5!, {r1, r2}
+ ldm.w r2, {r1, r2}
+
+ ldmia r4, {r4, r5, r8, r9}
+ ldmia r4, {r5, r6}
+ ldmia r5!, {r3, r8}
+ ldm r4, {r4, r5, r8, r9}
+ ldm r4, {r5, r6}
+ ldm r5!, {r3, r8}
+ ldmfd r5!, {r3, r8}
+
+@ CHECK: ldm.w r4, {r4, r5, r8, r9} @ encoding: [0x94,0xe8,0x30,0x03]
+@ CHECK: ldm.w r4, {r5, r6} @ encoding: [0x94,0xe8,0x60,0x00]
+@ CHECK: ldm.w r5!, {r3, r8} @ encoding: [0xb5,0xe8,0x08,0x01]
+@ CHECK: ldm.w r4, {r4, r5, r8, r9} @ encoding: [0x94,0xe8,0x30,0x03]
+@ CHECK: ldm.w r4, {r5, r6} @ encoding: [0x94,0xe8,0x60,0x00]
+@ CHECK: ldm.w r5!, {r3, r8} @ encoding: [0xb5,0xe8,0x08,0x01]
+@ CHECK: ldm.w r5!, {r1, r2} @ encoding: [0xb5,0xe8,0x06,0x00]
+@ CHECK: ldm.w r2, {r1, r2} @ encoding: [0x92,0xe8,0x06,0x00]
+
+@ CHECK: ldm.w r4, {r4, r5, r8, r9} @ encoding: [0x94,0xe8,0x30,0x03]
+@ CHECK: ldm.w r4, {r5, r6} @ encoding: [0x94,0xe8,0x60,0x00]
+@ CHECK: ldm.w r5!, {r3, r8} @ encoding: [0xb5,0xe8,0x08,0x01]
+@ CHECK: ldm.w r4, {r4, r5, r8, r9} @ encoding: [0x94,0xe8,0x30,0x03]
+@ CHECK: ldm.w r4, {r5, r6} @ encoding: [0x94,0xe8,0x60,0x00]
+@ CHECK: ldm.w r5!, {r3, r8} @ encoding: [0xb5,0xe8,0x08,0x01]
+@ CHECK: ldm.w r5!, {r3, r8} @ encoding: [0xb5,0xe8,0x08,0x01]
+
+
+@------------------------------------------------------------------------------
+@ LDMDB
+@------------------------------------------------------------------------------
+ ldmdb r4, {r4, r5, r8, r9}
+ ldmdb r4, {r5, r6}
+ ldmdb r5!, {r3, r8}
+ ldmea r5!, {r3, r8}
+
+@ CHECK: ldmdb r4, {r4, r5, r8, r9} @ encoding: [0x14,0xe9,0x30,0x03]
+@ CHECK: ldmdb r4, {r5, r6} @ encoding: [0x14,0xe9,0x60,0x00]
+@ CHECK: ldmdb r5!, {r3, r8} @ encoding: [0x35,0xe9,0x08,0x01]
+@ CHECK: ldmdb r5!, {r3, r8} @ encoding: [0x35,0xe9,0x08,0x01]
+
+
+@------------------------------------------------------------------------------
+@ LDR(immediate)
+@------------------------------------------------------------------------------
+ ldr r5, [r5, #-4]
+ ldr r5, [r6, #32]
+ ldr r5, [r6, #33]
+ ldr r5, [r6, #257]
+ ldr.w pc, [r7, #257]
+ ldr r2, [r4, #255]!
+ ldr r8, [sp, #4]!
+ ldr lr, [sp, #-4]!
+ ldr r2, [r4], #255
+ ldr r8, [sp], #4
+ ldr lr, [sp], #-4
+
+@ CHECK: ldr r5, [r5, #-4] @ encoding: [0x55,0xf8,0x04,0x5c]
+@ CHECK: ldr r5, [r6, #32] @ encoding: [0x35,0x6a]
+@ CHECK: ldr.w r5, [r6, #33] @ encoding: [0xd6,0xf8,0x21,0x50]
+@ CHECK: ldr.w r5, [r6, #257] @ encoding: [0xd6,0xf8,0x01,0x51]
+@ CHECK: ldr.w pc, [r7, #257] @ encoding: [0xd7,0xf8,0x01,0xf1]
+@ CHECK: ldr r2, [r4, #255]! @ encoding: [0x54,0xf8,0xff,0x2f]
+@ CHECK: ldr r8, [sp, #4]! @ encoding: [0x5d,0xf8,0x04,0x8f]
+@ CHECK: ldr lr, [sp, #-4]! @ encoding: [0x5d,0xf8,0x04,0xed]
+@ CHECK: ldr r2, [r4], #255 @ encoding: [0x54,0xf8,0xff,0x2b]
+@ CHECK: ldr r8, [sp], #4 @ encoding: [0x5d,0xf8,0x04,0x8b]
+@ CHECK: ldr lr, [sp], #-4 @ encoding: [0x5d,0xf8,0x04,0xe9]
+
+
+@------------------------------------------------------------------------------
+@ LDR(literal)
+@------------------------------------------------------------------------------
+ ldr.w r5, _foo
+
+@ CHECK: ldr.w r5, _foo @ encoding: [0x5f'A',0xf8'A',A,0x50'A']
+ @ fixup A - offset: 0, value: _foo, kind: fixup_t2_ldst_pcrel_12
+
+
+@------------------------------------------------------------------------------
+@ LDR(register)
+@------------------------------------------------------------------------------
+ ldr r1, [r8, r1]
+ ldr.w r4, [r5, r2]
+ ldr r6, [r0, r2, lsl #3]
+ ldr r8, [r8, r2, lsl #2]
+ ldr r7, [sp, r2, lsl #1]
+ ldr r7, [sp, r2, lsl #0]
+
+@ CHECK: ldr.w r1, [r8, r1] @ encoding: [0x58,0xf8,0x01,0x10]
+@ CHECK: ldr.w r4, [r5, r2] @ encoding: [0x55,0xf8,0x02,0x40]
+@ CHECK: ldr.w r6, [r0, r2, lsl #3] @ encoding: [0x50,0xf8,0x32,0x60]
+@ CHECK: ldr.w r8, [r8, r2, lsl #2] @ encoding: [0x58,0xf8,0x22,0x80]
+@ CHECK: ldr.w r7, [sp, r2, lsl #1] @ encoding: [0x5d,0xf8,0x12,0x70]
+@ CHECK: ldr.w r7, [sp, r2] @ encoding: [0x5d,0xf8,0x02,0x70]
+
+
+@------------------------------------------------------------------------------
+@ LDRB(immediate)
+@------------------------------------------------------------------------------
+ ldrb r5, [r5, #-4]
+ ldrb r5, [r6, #32]
+ ldrb r5, [r6, #33]
+ ldrb r5, [r6, #257]
+ ldrb.w lr, [r7, #257]
+ ldrb r5, [r8, #255]!
+ ldrb r2, [r5, #4]!
+ ldrb r1, [r4, #-4]!
+ ldrb lr, [r3], #255
+ ldrb r9, [r2], #4
+ ldrb r3, [sp], #-4
+
+@ CHECK: ldrb r5, [r5, #-4] @ encoding: [0x15,0xf8,0x04,0x5c]
+@ CHECK: ldrb.w r5, [r6, #32] @ encoding: [0x96,0xf8,0x20,0x50]
+@ CHECK: ldrb.w r5, [r6, #33] @ encoding: [0x96,0xf8,0x21,0x50]
+@ CHECK: ldrb.w r5, [r6, #257] @ encoding: [0x96,0xf8,0x01,0x51]
+@ CHECK: ldrb.w lr, [r7, #257] @ encoding: [0x97,0xf8,0x01,0xe1]
+@ CHECK: ldrb r5, [r8, #255]! @ encoding: [0x18,0xf8,0xff,0x5f]
+@ CHECK: ldrb r2, [r5, #4]! @ encoding: [0x15,0xf8,0x04,0x2f]
+@ CHECK: ldrb r1, [r4, #-4]! @ encoding: [0x14,0xf8,0x04,0x1d]
+@ CHECK: ldrb lr, [r3], #255 @ encoding: [0x13,0xf8,0xff,0xeb]
+@ CHECK: ldrb r9, [r2], #4 @ encoding: [0x12,0xf8,0x04,0x9b]
+@ CHECK: ldrb r3, [sp], #-4 @ encoding: [0x1d,0xf8,0x04,0x39]
+
+
+@------------------------------------------------------------------------------
+@ LDRB(register)
+@------------------------------------------------------------------------------
+ ldrb r1, [r8, r1]
+ ldrb.w r4, [r5, r2]
+ ldrb r6, [r0, r2, lsl #3]
+ ldrb r8, [r8, r2, lsl #2]
+ ldrb r7, [sp, r2, lsl #1]
+ ldrb r7, [sp, r2, lsl #0]
+
+@ CHECK: ldrb.w r1, [r8, r1] @ encoding: [0x18,0xf8,0x01,0x10]
+@ CHECK: ldrb.w r4, [r5, r2] @ encoding: [0x15,0xf8,0x02,0x40]
+@ CHECK: ldrb.w r6, [r0, r2, lsl #3] @ encoding: [0x10,0xf8,0x32,0x60]
+@ CHECK: ldrb.w r8, [r8, r2, lsl #2] @ encoding: [0x18,0xf8,0x22,0x80]
+@ CHECK: ldrb.w r7, [sp, r2, lsl #1] @ encoding: [0x1d,0xf8,0x12,0x70]
+@ CHECK: ldrb.w r7, [sp, r2] @ encoding: [0x1d,0xf8,0x02,0x70]
+
+
+@------------------------------------------------------------------------------
+@ LDRBT
+@------------------------------------------------------------------------------
+ ldrbt r1, [r2]
+ ldrbt r1, [r8, #0]
+ ldrbt r1, [r8, #3]
+ ldrbt r1, [r8, #255]
+
+@ CHECK: ldrbt r1, [r2] @ encoding: [0x12,0xf8,0x00,0x1e]
+@ CHECK: ldrbt r1, [r8] @ encoding: [0x18,0xf8,0x00,0x1e]
+@ CHECK: ldrbt r1, [r8, #3] @ encoding: [0x18,0xf8,0x03,0x1e]
+@ CHECK: ldrbt r1, [r8, #255] @ encoding: [0x18,0xf8,0xff,0x1e]
+
+
+@------------------------------------------------------------------------------
+@ LDRD
+@------------------------------------------------------------------------------
+ ldrd r3, r5, [r6, #24]
+ ldrd r3, r5, [r6, #24]!
+ ldrd r3, r5, [r6], #4
+ ldrd r3, r5, [r6], #-8
+ ldrd r3, r5, [r6]
+ ldrd r8, r1, [r3, #0]
+
+@ CHECK: ldrd r3, r5, [r6, #24] @ encoding: [0xd6,0xe9,0x06,0x35]
+@ CHECK: ldrd r3, r5, [r6, #24]! @ encoding: [0xf6,0xe9,0x06,0x35]
+@ CHECK: ldrd r3, r5, [r6], #4 @ encoding: [0xf6,0xe8,0x01,0x35]
+@ CHECK: ldrd r3, r5, [r6], #-8 @ encoding: [0x76,0xe8,0x02,0x35]
+@ CHECK: ldrd r3, r5, [r6] @ encoding: [0xd6,0xe9,0x00,0x35]
+@ CHECK: ldrd r8, r1, [r3] @ encoding: [0xd3,0xe9,0x00,0x81]
+
+
+@------------------------------------------------------------------------------
+@ FIXME: LDRD(literal)
+@------------------------------------------------------------------------------
+
+
+@------------------------------------------------------------------------------
+@ LDREX/LDREXB/LDREXH/LDREXD
+@------------------------------------------------------------------------------
+ ldrex r1, [r4]
+ ldrex r8, [r4, #0]
+ ldrex r2, [sp, #128]
+ ldrexb r5, [r7]
+ ldrexh r9, [r12]
+ ldrexd r9, r3, [r4]
+
+@ CHECK: ldrex r1, [r4] @ encoding: [0x54,0xe8,0x00,0x1f]
+@ CHECK: ldrex r8, [r4] @ encoding: [0x54,0xe8,0x00,0x8f]
+@ CHECK: ldrex r2, [sp, #128] @ encoding: [0x5d,0xe8,0x20,0x2f]
+@ CHECK: ldrexb r5, [r7] @ encoding: [0xd7,0xe8,0x4f,0x5f]
+@ CHECK: ldrexh r9, [r12] @ encoding: [0xdc,0xe8,0x5f,0x9f]
+@ CHECK: ldrexd r9, r3, [r4] @ encoding: [0xd4,0xe8,0x7f,0x93]
+
+
+@------------------------------------------------------------------------------
+@ LDRH(immediate)
+@------------------------------------------------------------------------------
+ ldrh r5, [r5, #-4]
+ ldrh r5, [r6, #32]
+ ldrh r5, [r6, #33]
+ ldrh r5, [r6, #257]
+ ldrh.w lr, [r7, #257]
+ ldrh r5, [r8, #255]!
+ ldrh r2, [r5, #4]!
+ ldrh r1, [r4, #-4]!
+ ldrh lr, [r3], #255
+ ldrh r9, [r2], #4
+ ldrh r3, [sp], #-4
+
+@ CHECK: ldrh r5, [r5, #-4] @ encoding: [0x35,0xf8,0x04,0x5c]
+@ CHECK: ldrh r5, [r6, #32] @ encoding: [0x35,0x8c]
+@ CHECK: ldrh.w r5, [r6, #33] @ encoding: [0xb6,0xf8,0x21,0x50]
+@ CHECK: ldrh.w r5, [r6, #257] @ encoding: [0xb6,0xf8,0x01,0x51]
+@ CHECK: ldrh.w lr, [r7, #257] @ encoding: [0xb7,0xf8,0x01,0xe1]
+@ CHECK: ldrh r5, [r8, #255]! @ encoding: [0x38,0xf8,0xff,0x5f]
+@ CHECK: ldrh r2, [r5, #4]! @ encoding: [0x35,0xf8,0x04,0x2f]
+@ CHECK: ldrh r1, [r4, #-4]! @ encoding: [0x34,0xf8,0x04,0x1d]
+@ CHECK: ldrh lr, [r3], #255 @ encoding: [0x33,0xf8,0xff,0xeb]
+@ CHECK: ldrh r9, [r2], #4 @ encoding: [0x32,0xf8,0x04,0x9b]
+@ CHECK: ldrh r3, [sp], #-4 @ encoding: [0x3d,0xf8,0x04,0x39]
+
+
+@------------------------------------------------------------------------------
+@ LDRH(register)
+@------------------------------------------------------------------------------
+ ldrh r1, [r8, r1]
+ ldrh.w r4, [r5, r2]
+ ldrh r6, [r0, r2, lsl #3]
+ ldrh r8, [r8, r2, lsl #2]
+ ldrh r7, [sp, r2, lsl #1]
+ ldrh r7, [sp, r2, lsl #0]
+
+@ CHECK: ldrh.w r1, [r8, r1] @ encoding: [0x38,0xf8,0x01,0x10]
+@ CHECK: ldrh.w r4, [r5, r2] @ encoding: [0x35,0xf8,0x02,0x40]
+@ CHECK: ldrh.w r6, [r0, r2, lsl #3] @ encoding: [0x30,0xf8,0x32,0x60]
+@ CHECK: ldrh.w r8, [r8, r2, lsl #2] @ encoding: [0x38,0xf8,0x22,0x80]
+@ CHECK: ldrh.w r7, [sp, r2, lsl #1] @ encoding: [0x3d,0xf8,0x12,0x70]
+@ CHECK: ldrh.w r7, [sp, r2] @ encoding: [0x3d,0xf8,0x02,0x70]
+
+
+@------------------------------------------------------------------------------
+@ LDRH(literal)
+@------------------------------------------------------------------------------
+ ldrh r5, _bar
+
+@ CHECK: ldrh.w r5, _bar @ encoding: [0xbf'A',0xf8'A',A,0x50'A']
+@ CHECK: @ fixup A - offset: 0, value: _bar, kind: fixup_t2_ldst_pcrel_12
+
+
+@------------------------------------------------------------------------------
+@ LDRHT
+@------------------------------------------------------------------------------
+ ldrht r1, [r2]
+ ldrht r1, [r8, #0]
+ ldrht r1, [r8, #3]
+ ldrht r1, [r8, #255]
+
+@ CHECK: ldrht r1, [r2] @ encoding: [0x32,0xf8,0x00,0x1e]
+@ CHECK: ldrht r1, [r8] @ encoding: [0x38,0xf8,0x00,0x1e]
+@ CHECK: ldrht r1, [r8, #3] @ encoding: [0x38,0xf8,0x03,0x1e]
+@ CHECK: ldrht r1, [r8, #255] @ encoding: [0x38,0xf8,0xff,0x1e]
+
+
+@------------------------------------------------------------------------------
+@ LDRSB(immediate)
+@------------------------------------------------------------------------------
+ ldrsb r5, [r5, #-4]
+ ldrsb r5, [r6, #32]
+ ldrsb r5, [r6, #33]
+ ldrsb r5, [r6, #257]
+ ldrsb.w lr, [r7, #257]
+
+@ CHECK: ldrsb r5, [r5, #-4] @ encoding: [0x15,0xf9,0x04,0x5c]
+@ CHECK: ldrsb.w r5, [r6, #32] @ encoding: [0x96,0xf9,0x20,0x50]
+@ CHECK: ldrsb.w r5, [r6, #33] @ encoding: [0x96,0xf9,0x21,0x50]
+@ CHECK: ldrsb.w r5, [r6, #257] @ encoding: [0x96,0xf9,0x01,0x51]
+@ CHECK: ldrsb.w lr, [r7, #257] @ encoding: [0x97,0xf9,0x01,0xe1]
+
+
+@------------------------------------------------------------------------------
+@ LDRSB(register)
+@------------------------------------------------------------------------------
+ ldrsb r1, [r8, r1]
+ ldrsb.w r4, [r5, r2]
+ ldrsb r6, [r0, r2, lsl #3]
+ ldrsb r8, [r8, r2, lsl #2]
+ ldrsb r7, [sp, r2, lsl #1]
+ ldrsb r7, [sp, r2, lsl #0]
+ ldrsb r5, [r8, #255]!
+ ldrsb r2, [r5, #4]!
+ ldrsb r1, [r4, #-4]!
+ ldrsb lr, [r3], #255
+ ldrsb r9, [r2], #4
+ ldrsb r3, [sp], #-4
+
+@ CHECK: ldrsb.w r1, [r8, r1] @ encoding: [0x18,0xf9,0x01,0x10]
+@ CHECK: ldrsb.w r4, [r5, r2] @ encoding: [0x15,0xf9,0x02,0x40]
+@ CHECK: ldrsb.w r6, [r0, r2, lsl #3] @ encoding: [0x10,0xf9,0x32,0x60]
+@ CHECK: ldrsb.w r8, [r8, r2, lsl #2] @ encoding: [0x18,0xf9,0x22,0x80]
+@ CHECK: ldrsb.w r7, [sp, r2, lsl #1] @ encoding: [0x1d,0xf9,0x12,0x70]
+@ CHECK: ldrsb.w r7, [sp, r2] @ encoding: [0x1d,0xf9,0x02,0x70]
+@ CHECK: ldrsb r5, [r8, #255]! @ encoding: [0x18,0xf9,0xff,0x5f]
+@ CHECK: ldrsb r2, [r5, #4]! @ encoding: [0x15,0xf9,0x04,0x2f]
+@ CHECK: ldrsb r1, [r4, #-4]! @ encoding: [0x14,0xf9,0x04,0x1d]
+@ CHECK: ldrsb lr, [r3], #255 @ encoding: [0x13,0xf9,0xff,0xeb]
+@ CHECK: ldrsb r9, [r2], #4 @ encoding: [0x12,0xf9,0x04,0x9b]
+@ CHECK: ldrsb r3, [sp], #-4 @ encoding: [0x1d,0xf9,0x04,0x39]
+
+
+@------------------------------------------------------------------------------
+@ LDRSB(literal)
+@------------------------------------------------------------------------------
+ ldrsb r5, _bar
+
+@ CHECK: ldrsb.w r5, _bar @ encoding: [0x9f'A',0xf9'A',A,0x50'A']
+@ CHECK: @ fixup A - offset: 0, value: _bar, kind: fixup_t2_ldst_pcrel_12
+
+
+@------------------------------------------------------------------------------
+@ LDRSBT
+@------------------------------------------------------------------------------
+ ldrsbt r1, [r2]
+ ldrsbt r1, [r8, #0]
+ ldrsbt r1, [r8, #3]
+ ldrsbt r1, [r8, #255]
+
+@ CHECK: ldrsbt r1, [r2] @ encoding: [0x12,0xf9,0x00,0x1e]
+@ CHECK: ldrsbt r1, [r8] @ encoding: [0x18,0xf9,0x00,0x1e]
+@ CHECK: ldrsbt r1, [r8, #3] @ encoding: [0x18,0xf9,0x03,0x1e]
+@ CHECK: ldrsbt r1, [r8, #255] @ encoding: [0x18,0xf9,0xff,0x1e]
+
+
+@------------------------------------------------------------------------------
+@ LDRSH(immediate)
+@------------------------------------------------------------------------------
+ ldrsh r5, [r5, #-4]
+ ldrsh r5, [r6, #32]
+ ldrsh r5, [r6, #33]
+ ldrsh r5, [r6, #257]
+ ldrsh.w lr, [r7, #257]
+
+@ CHECK: ldrsh r5, [r5, #-4] @ encoding: [0x35,0xf9,0x04,0x5c]
+@ CHECK: ldrsh.w r5, [r6, #32] @ encoding: [0xb6,0xf9,0x20,0x50]
+@ CHECK: ldrsh.w r5, [r6, #33] @ encoding: [0xb6,0xf9,0x21,0x50]
+@ CHECK: ldrsh.w r5, [r6, #257] @ encoding: [0xb6,0xf9,0x01,0x51]
+@ CHECK: ldrsh.w lr, [r7, #257] @ encoding: [0xb7,0xf9,0x01,0xe1]
+
+
+@------------------------------------------------------------------------------
+@ LDRSH(register)
+@------------------------------------------------------------------------------
+ ldrsh r1, [r8, r1]
+ ldrsh.w r4, [r5, r2]
+ ldrsh r6, [r0, r2, lsl #3]
+ ldrsh r8, [r8, r2, lsl #2]
+ ldrsh r7, [sp, r2, lsl #1]
+ ldrsh r7, [sp, r2, lsl #0]
+ ldrsh r5, [r8, #255]!
+ ldrsh r2, [r5, #4]!
+ ldrsh r1, [r4, #-4]!
+ ldrsh lr, [r3], #255
+ ldrsh r9, [r2], #4
+ ldrsh r3, [sp], #-4
+
+@ CHECK: ldrsh.w r1, [r8, r1] @ encoding: [0x38,0xf9,0x01,0x10]
+@ CHECK: ldrsh.w r4, [r5, r2] @ encoding: [0x35,0xf9,0x02,0x40]
+@ CHECK: ldrsh.w r6, [r0, r2, lsl #3] @ encoding: [0x30,0xf9,0x32,0x60]
+@ CHECK: ldrsh.w r8, [r8, r2, lsl #2] @ encoding: [0x38,0xf9,0x22,0x80]
+@ CHECK: ldrsh.w r7, [sp, r2, lsl #1] @ encoding: [0x3d,0xf9,0x12,0x70]
+@ CHECK: ldrsh.w r7, [sp, r2] @ encoding: [0x3d,0xf9,0x02,0x70]
+@ CHECK: ldrsh r5, [r8, #255]! @ encoding: [0x38,0xf9,0xff,0x5f]
+@ CHECK: ldrsh r2, [r5, #4]! @ encoding: [0x35,0xf9,0x04,0x2f]
+@ CHECK: ldrsh r1, [r4, #-4]! @ encoding: [0x34,0xf9,0x04,0x1d]
+@ CHECK: ldrsh lr, [r3], #255 @ encoding: [0x33,0xf9,0xff,0xeb]
+@ CHECK: ldrsh r9, [r2], #4 @ encoding: [0x32,0xf9,0x04,0x9b]
+@ CHECK: ldrsh r3, [sp], #-4 @ encoding: [0x3d,0xf9,0x04,0x39]
+
+
+@------------------------------------------------------------------------------
+@ LDRSH(literal)
+@------------------------------------------------------------------------------
+ ldrsh r5, _bar
+
+@ CHECK: ldrsh.w r5, _bar @ encoding: [0xbf'A',0xf9'A',A,0x50'A']
+@ CHECK: @ fixup A - offset: 0, value: _bar, kind: fixup_t2_ldst_pcrel_12
+
+@ TEMPORARILY DISABLED:
+@ ldrsh.w r4, [pc, #1435]
+@ : ldrsh.w r4, [pc, #1435] @ encoding: [0x3f,0xf9,0x9b,0x45]
+
+@------------------------------------------------------------------------------
+@ LDRSHT
+@------------------------------------------------------------------------------
+ ldrsht r1, [r2]
+ ldrsht r1, [r8, #0]
+ ldrsht r1, [r8, #3]
+ ldrsht r1, [r8, #255]
+
+@ CHECK: ldrsht r1, [r2] @ encoding: [0x32,0xf9,0x00,0x1e]
+@ CHECK: ldrsht r1, [r8] @ encoding: [0x38,0xf9,0x00,0x1e]
+@ CHECK: ldrsht r1, [r8, #3] @ encoding: [0x38,0xf9,0x03,0x1e]
+@ CHECK: ldrsht r1, [r8, #255] @ encoding: [0x38,0xf9,0xff,0x1e]
+
+
+@------------------------------------------------------------------------------
+@ LDRT
+@------------------------------------------------------------------------------
+ ldrt r1, [r2]
+ ldrt r2, [r6, #0]
+ ldrt r3, [r7, #3]
+ ldrt r4, [r9, #255]
+
+@ CHECK: ldrt r1, [r2] @ encoding: [0x52,0xf8,0x00,0x1e]
+@ CHECK: ldrt r2, [r6] @ encoding: [0x56,0xf8,0x00,0x2e]
+@ CHECK: ldrt r3, [r7, #3] @ encoding: [0x57,0xf8,0x03,0x3e]
+@ CHECK: ldrt r4, [r9, #255] @ encoding: [0x59,0xf8,0xff,0x4e]
+
+
+@------------------------------------------------------------------------------
+@ LSL (immediate)
+@------------------------------------------------------------------------------
+ lsl r2, r3, #12
+ lsls r8, r3, #31
+ lsls.w r2, r3, #1
+ lsl r2, r3, #4
+ lsls r2, r12, #15
+
+ lsl r3, #19
+ lsls r8, #2
+ lsls.w r7, #5
+ lsl.w r12, #21
+
+@ CHECK: lsl.w r2, r3, #12 @ encoding: [0x4f,0xea,0x03,0x32]
+@ CHECK: lsls.w r8, r3, #31 @ encoding: [0x5f,0xea,0xc3,0x78]
+@ CHECK: lsls.w r2, r3, #1 @ encoding: [0x5f,0xea,0x43,0x02]
+@ CHECK: lsl.w r2, r3, #4 @ encoding: [0x4f,0xea,0x03,0x12]
+@ CHECK: lsls.w r2, r12, #15 @ encoding: [0x5f,0xea,0xcc,0x32]
+
+@ CHECK: lsl.w r3, r3, #19 @ encoding: [0x4f,0xea,0xc3,0x43]
+@ CHECK: lsls.w r8, r8, #2 @ encoding: [0x5f,0xea,0x88,0x08]
+@ CHECK: lsls.w r7, r7, #5 @ encoding: [0x5f,0xea,0x47,0x17]
+@ CHECK: lsl.w r12, r12, #21 @ encoding: [0x4f,0xea,0x4c,0x5c]
+
+
+@------------------------------------------------------------------------------
+@ LSL (register)
+@------------------------------------------------------------------------------
+ lsl r3, r4, r2
+ lsl.w r1, r2
+ lsls r3, r4, r8
+
+@ CHECK: lsl.w r3, r4, r2 @ encoding: [0x04,0xfa,0x02,0xf3]
+@ CHECK: lsl.w r1, r1, r2 @ encoding: [0x01,0xfa,0x02,0xf1]
+@ CHECK: lsls.w r3, r4, r8 @ encoding: [0x14,0xfa,0x08,0xf3]
+
+
+@------------------------------------------------------------------------------
+@ LSR (immediate)
+@------------------------------------------------------------------------------
+ lsr r2, r3, #12
+ lsrs r8, r3, #32
+ lsrs.w r2, r3, #1
+ lsr r2, r3, #4
+ lsrs r2, r12, #15
+
+ lsr r3, #19
+ lsrs r8, #2
+ lsrs.w r7, #5
+ lsr.w r12, #21
+
+@ CHECK: lsr.w r2, r3, #12 @ encoding: [0x4f,0xea,0x13,0x32]
+@ CHECK: lsrs.w r8, r3, #32 @ encoding: [0x5f,0xea,0x13,0x08]
+@ CHECK: lsrs.w r2, r3, #1 @ encoding: [0x5f,0xea,0x53,0x02]
+@ CHECK: lsr.w r2, r3, #4 @ encoding: [0x4f,0xea,0x13,0x12]
+@ CHECK: lsrs.w r2, r12, #15 @ encoding: [0x5f,0xea,0xdc,0x32]
+
+@ CHECK: lsr.w r3, r3, #19 @ encoding: [0x4f,0xea,0xd3,0x43]
+@ CHECK: lsrs.w r8, r8, #2 @ encoding: [0x5f,0xea,0x98,0x08]
+@ CHECK: lsrs.w r7, r7, #5 @ encoding: [0x5f,0xea,0x57,0x17]
+@ CHECK: lsr.w r12, r12, #21 @ encoding: [0x4f,0xea,0x5c,0x5c]
+
+
+@------------------------------------------------------------------------------
+@ LSR (register)
+@------------------------------------------------------------------------------
+ lsr r3, r4, r2
+ lsr.w r1, r2
+ lsrs r3, r4, r8
+
+@ CHECK: lsr.w r3, r4, r2 @ encoding: [0x24,0xfa,0x02,0xf3]
+@ CHECK: lsr.w r1, r1, r2 @ encoding: [0x21,0xfa,0x02,0xf1]
+@ CHECK: lsrs.w r3, r4, r8 @ encoding: [0x34,0xfa,0x08,0xf3]
+
+@------------------------------------------------------------------------------
+@ MCR/MCR2
+@------------------------------------------------------------------------------
+ mcr p7, #1, r5, c1, c1, #4
+ mcr2 p7, #1, r5, c1, c1, #4
+
+@ CHECK: mcr p7, #1, r5, c1, c1, #4 @ encoding: [0x21,0xee,0x91,0x57]
+@ CHECK: mcr2 p7, #1, r5, c1, c1, #4 @ encoding: [0x21,0xfe,0x91,0x57]
+
+
+@------------------------------------------------------------------------------
+@ MCRR/MCRR2
+@------------------------------------------------------------------------------
+ mcrr p7, #15, r5, r4, c1
+ mcrr2 p7, #15, r5, r4, c1
+
+@ CHECK: mcrr p7, #15, r5, r4, c1 @ encoding: [0x44,0xec,0xf1,0x57]
+@ CHECK: mcrr2 p7, #15, r5, r4, c1 @ encoding: [0x44,0xfc,0xf1,0x57]
+
+
+@------------------------------------------------------------------------------
+@ MLA/MLS
+@------------------------------------------------------------------------------
+ mla r1,r2,r3,r4
+ mls r1,r2,r3,r4
+
+@ CHECK: mla r1, r2, r3, r4 @ encoding: [0x02,0xfb,0x03,0x41]
+@ CHECK: mls r1, r2, r3, r4 @ encoding: [0x02,0xfb,0x13,0x41]
+
+
+@------------------------------------------------------------------------------
+@ MOV(immediate)
+@------------------------------------------------------------------------------
+ movs r1, #21
+ movs.w r1, #21
+ movs r8, #21
+ movw r0, #65535
+ movw r1, #43777
+ movw r1, #43792
+ mov.w r0, #0x3fc0000
+ mov r0, #0x3fc0000
+ movs.w r0, #0x3fc0000
+ itte eq
+ movseq r1, #12
+ moveq r1, #12
+ movne.w r1, #12
+ mov.w r6, #450
+
+@ CHECK: movs r1, #21 @ encoding: [0x15,0x21]
+@ CHECK: movs.w r1, #21 @ encoding: [0x5f,0xf0,0x15,0x01]
+@ CHECK: movs.w r8, #21 @ encoding: [0x5f,0xf0,0x15,0x08]
+@ CHECK: movw r0, #65535 @ encoding: [0x4f,0xf6,0xff,0x70]
+@ CHECK: movw r1, #43777 @ encoding: [0x4a,0xf6,0x01,0x31]
+@ CHECK: movw r1, #43792 @ encoding: [0x4a,0xf6,0x10,0x31]
+@ CHECK: mov.w r0, #66846720 @ encoding: [0x4f,0xf0,0x7f,0x70]
+@ CHECK: mov.w r0, #66846720 @ encoding: [0x4f,0xf0,0x7f,0x70]
+@ CHECK: movs.w r0, #66846720 @ encoding: [0x5f,0xf0,0x7f,0x70]
+@ CHECK: itte eq @ encoding: [0x06,0xbf]
+@ CHECK: movseq.w r1, #12 @ encoding: [0x5f,0xf0,0x0c,0x01]
+@ CHECK: moveq r1, #12 @ encoding: [0x0c,0x21]
+@ CHECK: movne.w r1, #12 @ encoding: [0x4f,0xf0,0x0c,0x01]
+@ CHECK: mov.w r6, #450 @ encoding: [0x4f,0xf4,0xe1,0x76]
+
+
+@------------------------------------------------------------------------------
+@ MOVT
+@------------------------------------------------------------------------------
+ movt r3, #7
+ movt r6, #0xffff
+ it eq
+ movteq r4, #0xff0
+
+@ CHECK: movt r3, #7 @ encoding: [0xc0,0xf2,0x07,0x03]
+@ CHECK: movt r6, #65535 @ encoding: [0xcf,0xf6,0xff,0x76]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: movteq r4, #4080 @ encoding: [0xc0,0xf6,0xf0,0x74]
+
+@------------------------------------------------------------------------------
+@ MRC/MRC2
+@------------------------------------------------------------------------------
+ mrc p14, #0, r1, c1, c2, #4
+ mrc2 p14, #0, r1, c1, c2, #4
+
+@ CHECK: mrc p14, #0, r1, c1, c2, #4 @ encoding: [0x11,0xee,0x92,0x1e]
+@ CHECK: mrc2 p14, #0, r1, c1, c2, #4 @ encoding: [0x11,0xfe,0x92,0x1e]
+
+
+@------------------------------------------------------------------------------
+@ MRRC/MRRC2
+@------------------------------------------------------------------------------
+ mrrc p7, #1, r5, r4, c1
+ mrrc2 p7, #1, r5, r4, c1
+
+@ CHECK: mrrc p7, #1, r5, r4, c1 @ encoding: [0x54,0xec,0x11,0x57]
+@ CHECK: mrrc2 p7, #1, r5, r4, c1 @ encoding: [0x54,0xfc,0x11,0x57]
+
+
+@------------------------------------------------------------------------------
+@ MRS
+@------------------------------------------------------------------------------
+ mrs r8, apsr
+ mrs r8, cpsr
+ mrs r8, spsr
+
+@ CHECK: mrs r8, apsr @ encoding: [0xef,0xf3,0x00,0x88]
+@ CHECK: mrs r8, apsr @ encoding: [0xef,0xf3,0x00,0x88]
+@ CHECK: mrs r8, spsr @ encoding: [0xff,0xf3,0x00,0x88]
+
+
+@------------------------------------------------------------------------------
+@ MSR
+@------------------------------------------------------------------------------
+ msr apsr, r1
+ msr apsr_g, r2
+ msr apsr_nzcvq, r3
+ msr APSR_nzcvq, r4
+ msr apsr_nzcvqg, r5
+ msr cpsr_fc, r6
+ msr cpsr_c, r7
+ msr cpsr_x, r8
+ msr cpsr_fc, r9
+ msr cpsr_all, r11
+ msr cpsr_fsx, r12
+ msr spsr_fc, r0
+ msr SPSR_fsxc, r5
+ msr cpsr_fsxc, r8
+
+@ CHECK: msr APSR_nzcvq, r1 @ encoding: [0x81,0xf3,0x00,0x88]
+@ CHECK: msr APSR_g, r2 @ encoding: [0x82,0xf3,0x00,0x84]
+@ CHECK: msr APSR_nzcvq, r3 @ encoding: [0x83,0xf3,0x00,0x88]
+@ CHECK: msr APSR_nzcvq, r4 @ encoding: [0x84,0xf3,0x00,0x88]
+@ CHECK: msr APSR_nzcvqg, r5 @ encoding: [0x85,0xf3,0x00,0x8c]
+@ CHECK: msr CPSR_fc, r6 @ encoding: [0x86,0xf3,0x00,0x89]
+@ CHECK: msr CPSR_c, r7 @ encoding: [0x87,0xf3,0x00,0x81]
+@ CHECK: msr CPSR_x, r8 @ encoding: [0x88,0xf3,0x00,0x82]
+@ CHECK: msr CPSR_fc, r9 @ encoding: [0x89,0xf3,0x00,0x89]
+@ CHECK: msr CPSR_fc, r11 @ encoding: [0x8b,0xf3,0x00,0x89]
+@ CHECK: msr CPSR_fsx, r12 @ encoding: [0x8c,0xf3,0x00,0x8e]
+@ CHECK: msr SPSR_fc, r0 @ encoding: [0x90,0xf3,0x00,0x89]
+@ CHECK: msr SPSR_fsxc, r5 @ encoding: [0x95,0xf3,0x00,0x8f]
+@ CHECK: msr CPSR_fsxc, r8 @ encoding: [0x88,0xf3,0x00,0x8f]
+
+
+@------------------------------------------------------------------------------
+@ MUL
+@------------------------------------------------------------------------------
+ muls r3, r4, r3
+ mul r3, r4, r3
+ mul r3, r4, r6
+ it eq
+ muleq r3, r4, r5
+
+@ CHECK: muls r3, r4, r3 @ encoding: [0x63,0x43]
+@ CHECK: mul r3, r4, r3 @ encoding: [0x04,0xfb,0x03,0xf3]
+@ CHECK: mul r3, r4, r6 @ encoding: [0x04,0xfb,0x06,0xf3]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: muleq r3, r4, r5 @ encoding: [0x04,0xfb,0x05,0xf3]
+
+
+@------------------------------------------------------------------------------
+@ MVN(immediate)
+@------------------------------------------------------------------------------
+ mvns r8, #21
+ mvn r0, #0x3fc0000
+ mvns r0, #0x3fc0000
+ itte eq
+ mvnseq r1, #12
+ mvneq r1, #12
+ mvnne r1, #12
+
+@ CHECK: mvns r8, #21 @ encoding: [0x7f,0xf0,0x15,0x08]
+@ CHECK: mvn r0, #66846720 @ encoding: [0x6f,0xf0,0x7f,0x70]
+@ CHECK: mvns r0, #66846720 @ encoding: [0x7f,0xf0,0x7f,0x70]
+@ CHECK: itte eq @ encoding: [0x06,0xbf]
+@ CHECK: mvnseq r1, #12 @ encoding: [0x7f,0xf0,0x0c,0x01]
+@ CHECK: mvneq r1, #12 @ encoding: [0x6f,0xf0,0x0c,0x01]
+@ CHECK: mvnne r1, #12 @ encoding: [0x6f,0xf0,0x0c,0x01]
+
+
+@------------------------------------------------------------------------------
+@ MVN(register)
+@------------------------------------------------------------------------------
+ mvn r2, r3
+ mvns r2, r3
+ mvn r5, r6, lsl #19
+ mvn r5, r6, lsr #9
+ mvn r5, r6, asr #4
+ mvn r5, r6, ror #6
+ mvn r5, r6, rrx
+ it eq
+ mvneq r2, r3
+
+@ CHECK: mvn.w r2, r3 @ encoding: [0x6f,0xea,0x03,0x02]
+@ CHECK: mvns r2, r3 @ encoding: [0xda,0x43]
+@ CHECK: mvn.w r5, r6, lsl #19 @ encoding: [0x6f,0xea,0xc6,0x45]
+@ CHECK: mvn.w r5, r6, lsr #9 @ encoding: [0x6f,0xea,0x56,0x25]
+@ CHECK: mvn.w r5, r6, asr #4 @ encoding: [0x6f,0xea,0x26,0x15]
+@ CHECK: mvn.w r5, r6, ror #6 @ encoding: [0x6f,0xea,0xb6,0x15]
+@ CHECK: mvn.w r5, r6, rrx @ encoding: [0x6f,0xea,0x36,0x05]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: mvneq r2, r3 @ encoding: [0xda,0x43]
+
+@------------------------------------------------------------------------------
+@ NOP
+@------------------------------------------------------------------------------
+ nop.w
+
+@ CHECK: nop.w @ encoding: [0xaf,0xf3,0x00,0x80]
+
+
+@------------------------------------------------------------------------------
+@ ORN
+@------------------------------------------------------------------------------
+ orn r4, r5, #0xf000
+ orn r4, r5, r6
+ orns r4, r5, r6
+ orn r4, r5, r6, lsl #5
+ orns r4, r5, r6, lsr #5
+ orn r4, r5, r6, lsr #5
+ orns r4, r5, r6, asr #5
+ orn r4, r5, r6, ror #5
+
+@ CHECK: orn r4, r5, #61440 @ encoding: [0x65,0xf4,0x70,0x44]
+@ CHECK: orn r4, r5, r6 @ encoding: [0x65,0xea,0x06,0x04]
+@ CHECK: orns r4, r5, r6 @ encoding: [0x75,0xea,0x06,0x04]
+@ CHECK: orn r4, r5, r6, lsl #5 @ encoding: [0x65,0xea,0x46,0x14]
+@ CHECK: orns r4, r5, r6, lsr #5 @ encoding: [0x75,0xea,0x56,0x14]
+@ CHECK: orn r4, r5, r6, lsr #5 @ encoding: [0x65,0xea,0x56,0x14]
+@ CHECK: orns r4, r5, r6, asr #5 @ encoding: [0x75,0xea,0x66,0x14]
+@ CHECK: orn r4, r5, r6, ror #5 @ encoding: [0x65,0xea,0x76,0x14]
+
+
+@------------------------------------------------------------------------------
+@ ORR
+@------------------------------------------------------------------------------
+ orr r4, r5, #0xf000
+ orr r4, r5, r6
+ orr r4, r5, r6, lsl #5
+ orrs r4, r5, r6, lsr #5
+ orr r4, r5, r6, lsr #5
+ orrs r4, r5, r6, asr #5
+ orr r4, r5, r6, ror #5
+
+@ CHECK: orr r4, r5, #61440 @ encoding: [0x45,0xf4,0x70,0x44]
+@ CHECK: orr.w r4, r5, r6 @ encoding: [0x45,0xea,0x06,0x04]
+@ CHECK: orr.w r4, r5, r6, lsl #5 @ encoding: [0x45,0xea,0x46,0x14]
+@ CHECK: orrs.w r4, r5, r6, lsr #5 @ encoding: [0x55,0xea,0x56,0x14]
+@ CHECK: orr.w r4, r5, r6, lsr #5 @ encoding: [0x45,0xea,0x56,0x14]
+@ CHECK: orrs.w r4, r5, r6, asr #5 @ encoding: [0x55,0xea,0x66,0x14]
+@ CHECK: orr.w r4, r5, r6, ror #5 @ encoding: [0x45,0xea,0x76,0x14]
+
+
+@------------------------------------------------------------------------------
+@ PKH
+@------------------------------------------------------------------------------
+ pkhbt r2, r2, r3
+ pkhbt r2, r2, r3, lsl #31
+ pkhbt r2, r2, r3, lsl #0
+ pkhbt r2, r2, r3, lsl #15
+
+ pkhtb r2, r2, r3
+ pkhtb r2, r2, r3, asr #31
+ pkhtb r2, r2, r3, asr #15
+
+@ CHECK: pkhbt r2, r2, r3 @ encoding: [0xc2,0xea,0x03,0x02]
+@ CHECK: pkhbt r2, r2, r3, lsl #31 @ encoding: [0xc2,0xea,0xc3,0x72]
+@ CHECK: pkhbt r2, r2, r3 @ encoding: [0xc2,0xea,0x03,0x02]
+@ CHECK: pkhbt r2, r2, r3, lsl #15 @ encoding: [0xc2,0xea,0xc3,0x32]
+
+@ CHECK: pkhbt r2, r2, r3 @ encoding: [0xc2,0xea,0x03,0x02]
+@ CHECK: pkhtb r2, r2, r3, asr #31 @ encoding: [0xc2,0xea,0xe3,0x72]
+@ CHECK: pkhtb r2, r2, r3, asr #15 @ encoding: [0xc2,0xea,0xe3,0x32]
+
+
+@------------------------------------------------------------------------------
+@ PLD(immediate)
+@------------------------------------------------------------------------------
+ pld [r5, #-4]
+ pld [r6, #32]
+ pld [r6, #33]
+ pld [r6, #257]
+ pld [r7, #257]
+
+@ CHECK: pld [r5, #-4] @ encoding: [0x15,0xf8,0x04,0xfc]
+@ CHECK: pld [r6, #32] @ encoding: [0x96,0xf8,0x20,0xf0]
+@ CHECK: pld [r6, #33] @ encoding: [0x96,0xf8,0x21,0xf0]
+@ CHECK: pld [r6, #257] @ encoding: [0x96,0xf8,0x01,0xf1]
+@ CHECK: pld [r7, #257] @ encoding: [0x97,0xf8,0x01,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ PLD(literal)
+@------------------------------------------------------------------------------
+ pld _foo
+
+@ CHECK: pld _foo @ encoding: [0x9f'A',0xf8'A',A,0xf0'A']
+ @ fixup A - offset: 0, value: _foo, kind: fixup_t2_ldst_pcrel_12
+
+
+@------------------------------------------------------------------------------
+@ PLD(register)
+@------------------------------------------------------------------------------
+ pld [r8, r1]
+ pld [r5, r2]
+ pld [r0, r2, lsl #3]
+ pld [r8, r2, lsl #2]
+ pld [sp, r2, lsl #1]
+ pld [sp, r2, lsl #0]
+
+@ CHECK: pld [r8, r1] @ encoding: [0x18,0xf8,0x01,0xf0]
+@ CHECK: pld [r5, r2] @ encoding: [0x15,0xf8,0x02,0xf0]
+@ CHECK: pld [r0, r2, lsl #3] @ encoding: [0x10,0xf8,0x32,0xf0]
+@ CHECK: pld [r8, r2, lsl #2] @ encoding: [0x18,0xf8,0x22,0xf0]
+@ CHECK: pld [sp, r2, lsl #1] @ encoding: [0x1d,0xf8,0x12,0xf0]
+@ CHECK: pld [sp, r2] @ encoding: [0x1d,0xf8,0x02,0xf0]
+
+@------------------------------------------------------------------------------
+@ PLI(immediate)
+@------------------------------------------------------------------------------
+ pli [r5, #-4]
+ pli [r6, #32]
+ pli [r6, #33]
+ pli [r6, #257]
+ pli [r7, #257]
+
+@ CHECK: pli [r5, #-4] @ encoding: [0x15,0xf9,0x04,0xfc]
+@ CHECK: pli [r6, #32] @ encoding: [0x96,0xf9,0x20,0xf0]
+@ CHECK: pli [r6, #33] @ encoding: [0x96,0xf9,0x21,0xf0]
+@ CHECK: pli [r6, #257] @ encoding: [0x96,0xf9,0x01,0xf1]
+@ CHECK: pli [r7, #257] @ encoding: [0x97,0xf9,0x01,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ PLI(literal)
+@------------------------------------------------------------------------------
+ pli _foo
+
+
+@ CHECK: pli _foo @ encoding: [0x9f'A',0xf9'A',A,0xf0'A']
+ @ fixup A - offset: 0, value: _foo, kind: fixup_t2_ldst_pcrel_12
+
+
+@------------------------------------------------------------------------------
+@ PLI(register)
+@------------------------------------------------------------------------------
+ pli [r8, r1]
+ pli [r5, r2]
+ pli [r0, r2, lsl #3]
+ pli [r8, r2, lsl #2]
+ pli [sp, r2, lsl #1]
+ pli [sp, r2, lsl #0]
+
+@ CHECK: pli [r8, r1] @ encoding: [0x18,0xf9,0x01,0xf0]
+@ CHECK: pli [r5, r2] @ encoding: [0x15,0xf9,0x02,0xf0]
+@ CHECK: pli [r0, r2, lsl #3] @ encoding: [0x10,0xf9,0x32,0xf0]
+@ CHECK: pli [r8, r2, lsl #2] @ encoding: [0x18,0xf9,0x22,0xf0]
+@ CHECK: pli [sp, r2, lsl #1] @ encoding: [0x1d,0xf9,0x12,0xf0]
+@ CHECK: pli [sp, r2] @ encoding: [0x1d,0xf9,0x02,0xf0]
+
+
+@------------------------------------------------------------------------------
+@ QADD/QADD16/QADD8
+@------------------------------------------------------------------------------
+ qadd r1, r2, r3
+ qadd16 r1, r2, r3
+ qadd8 r1, r2, r3
+ itte gt
+ qaddgt r1, r2, r3
+ qadd16gt r1, r2, r3
+ qadd8le r1, r2, r3
+
+@ CHECK: qadd r1, r2, r3 @ encoding: [0x83,0xfa,0x82,0xf1]
+@ CHECK: qadd16 r1, r2, r3 @ encoding: [0x92,0xfa,0x13,0xf1]
+@ CHECK: qadd8 r1, r2, r3 @ encoding: [0x82,0xfa,0x13,0xf1]
+@ CHECK: itte gt @ encoding: [0xc6,0xbf]
+@ CHECK: qaddgt r1, r2, r3 @ encoding: [0x83,0xfa,0x82,0xf1]
+@ CHECK: qadd16gt r1, r2, r3 @ encoding: [0x92,0xfa,0x13,0xf1]
+@ CHECK: qadd8le r1, r2, r3 @ encoding: [0x82,0xfa,0x13,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ QDADD/QDSUB
+@------------------------------------------------------------------------------
+ qdadd r6, r7, r8
+ qdsub r6, r7, r8
+ itt hi
+ qdaddhi r6, r7, r8
+ qdsubhi r6, r7, r8
+
+@ CHECK: qdadd r6, r7, r8 @ encoding: [0x88,0xfa,0x97,0xf6]
+@ CHECK: qdsub r6, r7, r8 @ encoding: [0x88,0xfa,0xb7,0xf6]
+@ CHECK: itt hi @ encoding: [0x84,0xbf]
+@ CHECK: qdaddhi r6, r7, r8 @ encoding: [0x88,0xfa,0x97,0xf6]
+@ CHECK: qdsubhi r6, r7, r8 @ encoding: [0x88,0xfa,0xb7,0xf6]
+
+
+@------------------------------------------------------------------------------
+@ QSAX
+@------------------------------------------------------------------------------
+ qsax r9, r12, r0
+ it eq
+ qsaxeq r9, r12, r0
+
+@ CHECK: qsax r9, r12, r0 @ encoding: [0xec,0xfa,0x10,0xf9]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: qsaxeq r9, r12, r0 @ encoding: [0xec,0xfa,0x10,0xf9]
+
+
+@------------------------------------------------------------------------------
+@ QSUB/QSUB16/QSUB8
+@------------------------------------------------------------------------------
+ qsub r1, r2, r3
+ qsub16 r1, r2, r3
+ qsub8 r1, r2, r3
+ itet le
+ qsuble r1, r2, r3
+ qsub16gt r1, r2, r3
+ qsub8le r1, r2, r3
+
+@ CHECK: qsub r1, r2, r3 @ encoding: [0x83,0xfa,0xa2,0xf1]
+@ CHECK: qsub16 r1, r2, r3 @ encoding: [0xd2,0xfa,0x13,0xf1]
+@ CHECK: qsub8 r1, r2, r3 @ encoding: [0xc2,0xfa,0x13,0xf1]
+@ CHECK: itet le @ encoding: [0xd6,0xbf]
+@ CHECK: qsuble r1, r2, r3 @ encoding: [0x83,0xfa,0xa2,0xf1]
+@ CHECK: qsub16gt r1, r2, r3 @ encoding: [0xd2,0xfa,0x13,0xf1]
+@ CHECK: qsub8le r1, r2, r3 @ encoding: [0xc2,0xfa,0x13,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ RBIT
+@------------------------------------------------------------------------------
+ rbit r1, r2
+ it ne
+ rbitne r1, r2
+
+@ CHECK: rbit r1, r2 @ encoding: [0x92,0xfa,0xa2,0xf1]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: rbitne r1, r2 @ encoding: [0x92,0xfa,0xa2,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ REV
+@------------------------------------------------------------------------------
+ rev.w r1, r2
+ rev r2, r8
+ itt ne
+ revne r1, r2
+ revne r1, r8
+
+@ CHECK: rev.w r1, r2 @ encoding: [0x92,0xfa,0x82,0xf1]
+@ CHECK: rev.w r2, r8 @ encoding: [0x98,0xfa,0x88,0xf2]
+@ CHECK: itt ne @ encoding: [0x1c,0xbf]
+@ CHECK: revne r1, r2 @ encoding: [0x11,0xba]
+@ CHECK: revne.w r1, r8 @ encoding: [0x98,0xfa,0x88,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ REV16
+@------------------------------------------------------------------------------
+ rev16.w r1, r2
+ rev16 r2, r8
+ itt ne
+ rev16ne r1, r2
+ rev16ne r1, r8
+
+@ CHECK: rev16.w r1, r2 @ encoding: [0x92,0xfa,0x92,0xf1]
+@ CHECK: rev16.w r2, r8 @ encoding: [0x98,0xfa,0x98,0xf2]
+@ CHECK: itt ne @ encoding: [0x1c,0xbf]
+@ CHECK: rev16ne r1, r2 @ encoding: [0x51,0xba]
+@ CHECK: rev16ne.w r1, r8 @ encoding: [0x98,0xfa,0x98,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ REVSH
+@------------------------------------------------------------------------------
+ revsh.w r1, r2
+ revsh r2, r8
+ itt ne
+ revshne r1, r2
+ revshne r1, r8
+
+@ CHECK: revsh.w r1, r2 @ encoding: [0x92,0xfa,0xb2,0xf1]
+@ CHECK: revsh.w r2, r8 @ encoding: [0x98,0xfa,0xb8,0xf2]
+@ CHECK: itt ne @ encoding: [0x1c,0xbf]
+@ CHECK: revshne r1, r2 @ encoding: [0xd1,0xba]
+@ CHECK: revshne.w r1, r8 @ encoding: [0x98,0xfa,0xb8,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ ROR (immediate)
+@------------------------------------------------------------------------------
+ ror r2, r3, #12
+ rors r8, r3, #31
+ rors.w r2, r3, #1
+ ror r2, r3, #4
+ rors r2, r12, #15
+
+ ror r3, #19
+ rors r8, #2
+ rors.w r7, #5
+ ror.w r12, #21
+
+@ CHECK: ror.w r2, r3, #12 @ encoding: [0x4f,0xea,0x33,0x32]
+@ CHECK: rors.w r8, r3, #31 @ encoding: [0x5f,0xea,0xf3,0x78]
+@ CHECK: rors.w r2, r3, #1 @ encoding: [0x5f,0xea,0x73,0x02]
+@ CHECK: ror.w r2, r3, #4 @ encoding: [0x4f,0xea,0x33,0x12]
+@ CHECK: rors.w r2, r12, #15 @ encoding: [0x5f,0xea,0xfc,0x32]
+
+@ CHECK: ror.w r3, r3, #19 @ encoding: [0x4f,0xea,0xf3,0x43]
+@ CHECK: rors.w r8, r8, #2 @ encoding: [0x5f,0xea,0xb8,0x08]
+@ CHECK: rors.w r7, r7, #5 @ encoding: [0x5f,0xea,0x77,0x17]
+@ CHECK: ror.w r12, r12, #21 @ encoding: [0x4f,0xea,0x7c,0x5c]
+
+
+@------------------------------------------------------------------------------
+@ ROR (register)
+@------------------------------------------------------------------------------
+ ror r3, r4, r2
+ ror.w r1, r2
+ rors r3, r4, r8
+
+@ CHECK: ror.w r3, r4, r2 @ encoding: [0x64,0xfa,0x02,0xf3]
+@ CHECK: ror.w r1, r1, r2 @ encoding: [0x61,0xfa,0x02,0xf1]
+@ CHECK: rors.w r3, r4, r8 @ encoding: [0x74,0xfa,0x08,0xf3]
+
+
+@------------------------------------------------------------------------------
+@ RRX
+@------------------------------------------------------------------------------
+ rrx r1, r2
+ rrxs r1, r2
+ ite lt
+ rrxlt r9, r12
+ rrxsge r8, r3
+
+@ CHECK: rrx r1, r2 @ encoding: [0x4f,0xea,0x32,0x01]
+@ CHECK: rrxs r1, r2 @ encoding: [0x5f,0xea,0x32,0x01]
+@ CHECK: ite lt @ encoding: [0xb4,0xbf]
+@ CHECK: rrxlt r9, r12 @ encoding: [0x4f,0xea,0x3c,0x09]
+@ CHECK: rrxsge r8, r3 @ encoding: [0x5f,0xea,0x33,0x08]
+
+@------------------------------------------------------------------------------
+@ RSB (immediate)
+@------------------------------------------------------------------------------
+ rsb r2, r5, #0xff000
+ rsbs r3, r12, #0xf
+ rsb r1, #0xff
+ rsb r1, r1, #0xff
+
+@ CHECK: rsb.w r2, r5, #1044480 @ encoding: [0xc5,0xf5,0x7f,0x22]
+@ CHECK: rsbs.w r3, r12, #15 @ encoding: [0xdc,0xf1,0x0f,0x03]
+@ CHECK: rsb.w r1, r1, #255 @ encoding: [0xc1,0xf1,0xff,0x01]
+@ CHECK: rsb.w r1, r1, #255 @ encoding: [0xc1,0xf1,0xff,0x01]
+
+
+@------------------------------------------------------------------------------
+@ RSB (register)
+@------------------------------------------------------------------------------
+ rsb r4, r8
+ rsb r4, r9, r8
+ rsb r1, r4, r8, asr #3
+ rsbs r2, r1, r7, lsl #1
+
+@ CHECK: rsb r4, r4, r8 @ encoding: [0xc4,0xeb,0x08,0x04]
+@ CHECK: rsb r4, r9, r8 @ encoding: [0xc9,0xeb,0x08,0x04]
+@ CHECK: rsb r1, r4, r8, asr #3 @ encoding: [0xc4,0xeb,0xe8,0x01]
+@ CHECK: rsbs r2, r1, r7, lsl #1 @ encoding: [0xd1,0xeb,0x47,0x02]
+
+
+@------------------------------------------------------------------------------
+@ SADD16
+@------------------------------------------------------------------------------
+ sadd16 r3, r4, r8
+ it ne
+ sadd16ne r3, r4, r8
+
+@ CHECK: sadd16 r3, r4, r8 @ encoding: [0x94,0xfa,0x08,0xf3]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: sadd16ne r3, r4, r8 @ encoding: [0x94,0xfa,0x08,0xf3]
+
+
+@------------------------------------------------------------------------------
+@ SADD8
+@------------------------------------------------------------------------------
+ sadd8 r3, r4, r8
+ it ne
+ sadd8ne r3, r4, r8
+
+@ CHECK: sadd8 r3, r4, r8 @ encoding: [0x84,0xfa,0x08,0xf3]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: sadd8ne r3, r4, r8 @ encoding: [0x84,0xfa,0x08,0xf3]
+
+
+@------------------------------------------------------------------------------
+@ SASX
+@------------------------------------------------------------------------------
+ saddsubx r9, r2, r7
+ it ne
+ saddsubxne r2, r5, r6
+ sasx r9, r2, r7
+ it ne
+ sasxne r2, r5, r6
+
+@ CHECK: sasx r9, r2, r7 @ encoding: [0xa2,0xfa,0x07,0xf9]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: sasxne r2, r5, r6 @ encoding: [0xa5,0xfa,0x06,0xf2]
+@ CHECK: sasx r9, r2, r7 @ encoding: [0xa2,0xfa,0x07,0xf9]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: sasxne r2, r5, r6 @ encoding: [0xa5,0xfa,0x06,0xf2]
+
+
+@------------------------------------------------------------------------------
+@ SBC (immediate)
+@------------------------------------------------------------------------------
+ sbc r0, r1, #4
+ sbcs r0, r1, #0
+ sbc r1, r2, #255
+ sbc r3, r7, #0x00550055
+ sbc r8, r12, #0xaa00aa00
+ sbc r9, r7, #0xa5a5a5a5
+ sbc r5, r3, #0x87000000
+ sbc r4, r2, #0x7f800000
+ sbc r4, r2, #0x00000680
+
+@ CHECK: sbc r0, r1, #4 @ encoding: [0x61,0xf1,0x04,0x00]
+@ CHECK: sbcs r0, r1, #0 @ encoding: [0x71,0xf1,0x00,0x00]
+@ CHECK: sbc r1, r2, #255 @ encoding: [0x62,0xf1,0xff,0x01]
+@ CHECK: sbc r3, r7, #5570645 @ encoding: [0x67,0xf1,0x55,0x13]
+@ CHECK: sbc r8, r12, #2852170240 @ encoding: [0x6c,0xf1,0xaa,0x28]
+@ CHECK: sbc r9, r7, #2779096485 @ encoding: [0x67,0xf1,0xa5,0x39]
+@ CHECK: sbc r5, r3, #2264924160 @ encoding: [0x63,0xf1,0x07,0x45]
+@ CHECK: sbc r4, r2, #2139095040 @ encoding: [0x62,0xf1,0xff,0x44]
+@ CHECK: sbc r4, r2, #1664 @ encoding: [0x62,0xf5,0xd0,0x64]
+
+
+@------------------------------------------------------------------------------
+@ SBC (register)
+@------------------------------------------------------------------------------
+ sbc r4, r5, r6
+ sbcs r4, r5, r6
+ sbc.w r9, r1, r3
+ sbcs.w r9, r1, r3
+ sbc r0, r1, r3, ror #4
+ sbcs r0, r1, r3, lsl #7
+ sbc.w r0, r1, r3, lsr #31
+ sbcs.w r0, r1, r3, asr #32
+
+@ CHECK: sbc.w r4, r5, r6 @ encoding: [0x65,0xeb,0x06,0x04]
+@ CHECK: sbcs.w r4, r5, r6 @ encoding: [0x75,0xeb,0x06,0x04]
+@ CHECK: sbc.w r9, r1, r3 @ encoding: [0x61,0xeb,0x03,0x09]
+@ CHECK: sbcs.w r9, r1, r3 @ encoding: [0x71,0xeb,0x03,0x09]
+@ CHECK: sbc.w r0, r1, r3, ror #4 @ encoding: [0x61,0xeb,0x33,0x10]
+@ CHECK: sbcs.w r0, r1, r3, lsl #7 @ encoding: [0x71,0xeb,0xc3,0x10]
+@ CHECK: sbc.w r0, r1, r3, lsr #31 @ encoding: [0x61,0xeb,0xd3,0x70]
+@ CHECK: sbcs.w r0, r1, r3, asr #32 @ encoding: [0x71,0xeb,0x23,0x00]
+
+
+@------------------------------------------------------------------------------
+@ SBFX
+@------------------------------------------------------------------------------
+ sbfx r4, r5, #16, #1
+ it gt
+ sbfxgt r4, r5, #16, #16
+
+@ CHECK: sbfx r4, r5, #16, #1 @ encoding: [0x45,0xf3,0x00,0x44]
+@ CHECK: it gt @ encoding: [0xc8,0xbf]
+@ CHECK: sbfxgt r4, r5, #16, #16 @ encoding: [0x45,0xf3,0x0f,0x44]
+
+
+@------------------------------------------------------------------------------
+@ SEL
+@------------------------------------------------------------------------------
+ sel r5, r9, r2
+ it le
+ selle r5, r9, r2
+
+@ CHECK: sel r5, r9, r2 @ encoding: [0xa9,0xfa,0x82,0xf5]
+@ CHECK: it le @ encoding: [0xd8,0xbf]
+@ CHECK: selle r5, r9, r2 @ encoding: [0xa9,0xfa,0x82,0xf5]
+
+
+@------------------------------------------------------------------------------
+@ SEV
+@------------------------------------------------------------------------------
+ sev.w
+ it eq
+ seveq.w
+
+@ CHECK: sev.w @ encoding: [0xaf,0xf3,0x04,0x80]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: seveq.w @ encoding: [0xaf,0xf3,0x04,0x80]
+
+
+@------------------------------------------------------------------------------
+@ SADD16/SADD8
+@------------------------------------------------------------------------------
+ sadd16 r1, r2, r3
+ sadd8 r1, r2, r3
+ ite gt
+ sadd16gt r1, r2, r3
+ sadd8le r1, r2, r3
+
+@ CHECK: sadd16 r1, r2, r3 @ encoding: [0x92,0xfa,0x03,0xf1]
+@ CHECK: sadd8 r1, r2, r3 @ encoding: [0x82,0xfa,0x03,0xf1]
+@ CHECK: ite gt @ encoding: [0xcc,0xbf]
+@ CHECK: sadd16gt r1, r2, r3 @ encoding: [0x92,0xfa,0x03,0xf1]
+@ CHECK: sadd8le r1, r2, r3 @ encoding: [0x82,0xfa,0x03,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ SHASX
+@------------------------------------------------------------------------------
+ shasx r4, r8, r2
+ it gt
+ shasxgt r4, r8, r2
+ shaddsubx r4, r8, r2
+ it gt
+ shaddsubxgt r4, r8, r2
+
+@ CHECK: shasx r4, r8, r2 @ encoding: [0xa8,0xfa,0x22,0xf4]
+@ CHECK: it gt @ encoding: [0xc8,0xbf]
+@ CHECK: shasxgt r4, r8, r2 @ encoding: [0xa8,0xfa,0x22,0xf4]
+@ CHECK: shasx r4, r8, r2 @ encoding: [0xa8,0xfa,0x22,0xf4]
+@ CHECK: it gt @ encoding: [0xc8,0xbf]
+@ CHECK: shasxgt r4, r8, r2 @ encoding: [0xa8,0xfa,0x22,0xf4]
+
+
+@------------------------------------------------------------------------------
+@ SHASX
+@------------------------------------------------------------------------------
+ shsax r4, r8, r2
+ it gt
+ shsaxgt r4, r8, r2
+ shsubaddx r4, r8, r2
+ it gt
+ shsubaddxgt r4, r8, r2
+
+@ CHECK: shsax r4, r8, r2 @ encoding: [0xe8,0xfa,0x22,0xf4]
+@ CHECK: it gt @ encoding: [0xc8,0xbf]
+@ CHECK: shsaxgt r4, r8, r2 @ encoding: [0xe8,0xfa,0x22,0xf4]
+@ CHECK: shsax r4, r8, r2 @ encoding: [0xe8,0xfa,0x22,0xf4]
+@ CHECK: it gt @ encoding: [0xc8,0xbf]
+@ CHECK: shsaxgt r4, r8, r2 @ encoding: [0xe8,0xfa,0x22,0xf4]
+
+
+@------------------------------------------------------------------------------
+@ SHSUB16/SHSUB8
+@------------------------------------------------------------------------------
+ shsub16 r4, r8, r2
+ shsub8 r4, r8, r2
+ itt gt
+ shsub16gt r4, r8, r2
+ shsub8gt r4, r8, r2
+
+@ CHECK: shsub16 r4, r8, r2 @ encoding: [0xd8,0xfa,0x22,0xf4]
+@ CHECK: shsub8 r4, r8, r2 @ encoding: [0xc8,0xfa,0x22,0xf4]
+@ CHECK: itt gt @ encoding: [0xc4,0xbf]
+@ CHECK: shsub16gt r4, r8, r2 @ encoding: [0xd8,0xfa,0x22,0xf4]
+@ CHECK: shsub8gt r4, r8, r2 @ encoding: [0xc8,0xfa,0x22,0xf4]
+
+
+@------------------------------------------------------------------------------
+@ SMLABB/SMLABT/SMLATB/SMLATT
+@------------------------------------------------------------------------------
+ smlabb r3, r1, r9, r0
+ smlabt r5, r6, r4, r1
+ smlatb r4, r2, r3, r2
+ smlatt r8, r3, r8, r4
+ itete gt
+ smlabbgt r3, r1, r9, r0
+ smlabtle r5, r6, r4, r1
+ smlatbgt r4, r2, r3, r2
+ smlattle r8, r3, r8, r4
+
+@ CHECK: smlabb r3, r1, r9, r0 @ encoding: [0x11,0xfb,0x09,0x03]
+@ CHECK: smlabt r5, r6, r4, r1 @ encoding: [0x16,0xfb,0x14,0x15]
+@ CHECK: smlatb r4, r2, r3, r2 @ encoding: [0x12,0xfb,0x23,0x24]
+@ CHECK: smlatt r8, r3, r8, r4 @ encoding: [0x13,0xfb,0x38,0x48]
+@ CHECK: itete gt @ encoding: [0xcb,0xbf]
+@ CHECK: smlabbgt r3, r1, r9, r0 @ encoding: [0x11,0xfb,0x09,0x03]
+@ CHECK: smlabtle r5, r6, r4, r1 @ encoding: [0x16,0xfb,0x14,0x15]
+@ CHECK: smlatbgt r4, r2, r3, r2 @ encoding: [0x12,0xfb,0x23,0x24]
+@ CHECK: smlattle r8, r3, r8, r4 @ encoding: [0x13,0xfb,0x38,0x48]
+
+
+@------------------------------------------------------------------------------
+@ SMLAD/SMLADX
+@------------------------------------------------------------------------------
+ smlad r2, r3, r5, r8
+ smladx r2, r3, r5, r8
+ itt hi
+ smladhi r2, r3, r5, r8
+ smladxhi r2, r3, r5, r8
+
+@ CHECK: smlad r2, r3, r5, r8 @ encoding: [0x23,0xfb,0x05,0x82]
+@ CHECK: smladx r2, r3, r5, r8 @ encoding: [0x23,0xfb,0x15,0x82]
+@ CHECK: itt hi @ encoding: [0x84,0xbf]
+@ CHECK: smladhi r2, r3, r5, r8 @ encoding: [0x23,0xfb,0x05,0x82]
+@ CHECK: smladxhi r2, r3, r5, r8 @ encoding: [0x23,0xfb,0x15,0x82]
+
+
+@------------------------------------------------------------------------------
+@ SMLAL
+@------------------------------------------------------------------------------
+ smlal r2, r3, r5, r8
+ it eq
+ smlaleq r2, r3, r5, r8
+
+@ CHECK: smlal r2, r3, r5, r8 @ encoding: [0xc5,0xfb,0x08,0x23]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: smlaleq r2, r3, r5, r8 @ encoding: [0xc5,0xfb,0x08,0x23]
+
+
+@------------------------------------------------------------------------------
+@ SMLALBB/SMLALBT/SMLALTB/SMLALTT
+@------------------------------------------------------------------------------
+ smlalbb r3, r1, r9, r0
+ smlalbt r5, r6, r4, r1
+ smlaltb r4, r2, r3, r2
+ smlaltt r8, r3, r8, r4
+ iteet ge
+ smlalbbge r3, r1, r9, r0
+ smlalbtlt r5, r6, r4, r1
+ smlaltblt r4, r2, r3, r2
+ smlalttge r8, r3, r8, r4
+
+@ CHECK: smlalbb r3, r1, r9, r0 @ encoding: [0xc9,0xfb,0x80,0x31]
+@ CHECK: smlalbt r5, r6, r4, r1 @ encoding: [0xc4,0xfb,0x91,0x56]
+@ CHECK: smlaltb r4, r2, r3, r2 @ encoding: [0xc3,0xfb,0xa2,0x42]
+@ CHECK: smlaltt r8, r3, r8, r4 @ encoding: [0xc8,0xfb,0xb4,0x83]
+@ CHECK: iteet ge @ encoding: [0xad,0xbf]
+@ CHECK: smlalbbge r3, r1, r9, r0 @ encoding: [0xc9,0xfb,0x80,0x31]
+@ CHECK: smlalbtlt r5, r6, r4, r1 @ encoding: [0xc4,0xfb,0x91,0x56]
+@ CHECK: smlaltblt r4, r2, r3, r2 @ encoding: [0xc3,0xfb,0xa2,0x42]
+@ CHECK: smlalttge r8, r3, r8, r4 @ encoding: [0xc8,0xfb,0xb4,0x83]
+
+
+@------------------------------------------------------------------------------
+@ SMLALD/SMLALDX
+@------------------------------------------------------------------------------
+ smlald r2, r3, r5, r8
+ smlaldx r2, r3, r5, r8
+ ite eq
+ smlaldeq r2, r3, r5, r8
+ smlaldxne r2, r3, r5, r8
+
+@ CHECK: smlald r2, r3, r5, r8 @ encoding: [0xc5,0xfb,0xc8,0x23]
+@ CHECK: smlaldx r2, r3, r5, r8 @ encoding: [0xc5,0xfb,0xd8,0x23]
+@ CHECK: ite eq @ encoding: [0x0c,0xbf]
+@ CHECK: smlaldeq r2, r3, r5, r8 @ encoding: [0xc5,0xfb,0xc8,0x23]
+@ CHECK: smlaldxne r2, r3, r5, r8 @ encoding: [0xc5,0xfb,0xd8,0x23]
+
+
+@------------------------------------------------------------------------------
+@ SMLAWB/SMLAWT
+@------------------------------------------------------------------------------
+ smlawb r2, r3, r10, r8
+ smlawt r8, r3, r5, r9
+ ite eq
+ smlawbeq r2, r7, r5, r8
+ smlawtne r1, r3, r0, r8
+
+@ CHECK: smlawb r2, r3, r10, r8 @ encoding: [0x33,0xfb,0x0a,0x82]
+@ CHECK: smlawt r8, r3, r5, r9 @ encoding: [0x33,0xfb,0x15,0x98]
+@ CHECK: ite eq @ encoding: [0x0c,0xbf]
+@ CHECK: smlawbeq r2, r7, r5, r8 @ encoding: [0x37,0xfb,0x05,0x82]
+@ CHECK: smlawtne r1, r3, r0, r8 @ encoding: [0x33,0xfb,0x10,0x81]
+
+
+@------------------------------------------------------------------------------
+@ SMLSD/SMLSDX
+@------------------------------------------------------------------------------
+ smlsd r2, r3, r5, r8
+ smlsdx r2, r3, r5, r8
+ ite le
+ smlsdle r2, r3, r5, r8
+ smlsdxgt r2, r3, r5, r8
+
+@ CHECK: smlsd r2, r3, r5, r8 @ encoding: [0x43,0xfb,0x05,0x82]
+@ CHECK: smlsdx r2, r3, r5, r8 @ encoding: [0x43,0xfb,0x15,0x82]
+@ CHECK: ite le @ encoding: [0xd4,0xbf]
+@ CHECK: smlsdle r2, r3, r5, r8 @ encoding: [0x43,0xfb,0x05,0x82]
+@ CHECK: smlsdxgt r2, r3, r5, r8 @ encoding: [0x43,0xfb,0x15,0x82]
+
+
+@------------------------------------------------------------------------------
+@ SMLSLD/SMLSLDX
+@------------------------------------------------------------------------------
+ smlsld r2, r9, r5, r1
+ smlsldx r4, r11, r2, r8
+ ite ge
+ smlsldge r8, r2, r5, r6
+ smlsldxlt r1, r0, r3, r8
+
+@ CHECK: smlsld r2, r9, r5, r1 @ encoding: [0xd5,0xfb,0xc1,0x29]
+@ CHECK: smlsldx r4, r11, r2, r8 @ encoding: [0xd2,0xfb,0xd8,0x4b]
+@ CHECK: ite ge @ encoding: [0xac,0xbf]
+@ CHECK: smlsldge r8, r2, r5, r6 @ encoding: [0xd5,0xfb,0xc6,0x82]
+@ CHECK: smlsldxlt r1, r0, r3, r8 @ encoding: [0xd3,0xfb,0xd8,0x10]
+
+
+@------------------------------------------------------------------------------
+@ SMMLA/SMMLAR
+@------------------------------------------------------------------------------
+ smmla r1, r2, r3, r4
+ smmlar r4, r3, r2, r1
+ ite lo
+ smmlalo r1, r2, r3, r4
+ smmlarcs r4, r3, r2, r1
+
+@ CHECK: smmla r1, r2, r3, r4 @ encoding: [0x52,0xfb,0x03,0x41]
+@ CHECK: smmlar r4, r3, r2, r1 @ encoding: [0x53,0xfb,0x12,0x14]
+@ CHECK: ite lo @ encoding: [0x34,0xbf]
+@ CHECK: smmlalo r1, r2, r3, r4 @ encoding: [0x52,0xfb,0x03,0x41]
+@ CHECK: smmlarhs r4, r3, r2, r1 @ encoding: [0x53,0xfb,0x12,0x14]
+
+
+@------------------------------------------------------------------------------
+@ SMMLS/SMMLSR
+@------------------------------------------------------------------------------
+ smmls r1, r2, r3, r4
+ smmlsr r4, r3, r2, r1
+ ite lo
+ smmlslo r1, r2, r3, r4
+ smmlsrcs r4, r3, r2, r1
+
+@ CHECK: smmls r1, r2, r3, r4 @ encoding: [0x62,0xfb,0x03,0x41]
+@ CHECK: smmlsr r4, r3, r2, r1 @ encoding: [0x63,0xfb,0x12,0x14]
+@ CHECK: ite lo @ encoding: [0x34,0xbf]
+@ CHECK: smmlslo r1, r2, r3, r4 @ encoding: [0x62,0xfb,0x03,0x41]
+@ CHECK: smmlsrhs r4, r3, r2, r1 @ encoding: [0x63,0xfb,0x12,0x14]
+
+
+@------------------------------------------------------------------------------
+@ SMMUL/SMMULR
+@------------------------------------------------------------------------------
+ smmul r2, r3, r4
+ smmulr r3, r2, r1
+ ite cc
+ smmulcc r2, r3, r4
+ smmulrhs r3, r2, r1
+
+@ CHECK: smmul r2, r3, r4 @ encoding: [0x53,0xfb,0x04,0xf2]
+@ CHECK: smmulr r3, r2, r1 @ encoding: [0x52,0xfb,0x11,0xf3]
+@ CHECK: ite lo @ encoding: [0x34,0xbf]
+@ CHECK: smmullo r2, r3, r4 @ encoding: [0x53,0xfb,0x04,0xf2]
+@ CHECK: smmulrhs r3, r2, r1 @ encoding: [0x52,0xfb,0x11,0xf3]
+
+
+@------------------------------------------------------------------------------
+@ SMUAD/SMUADX
+@------------------------------------------------------------------------------
+ smuad r2, r3, r4
+ smuadx r3, r2, r1
+ ite lt
+ smuadlt r2, r3, r4
+ smuadxge r3, r2, r1
+
+@ CHECK: smuad r2, r3, r4 @ encoding: [0x23,0xfb,0x04,0xf2]
+@ CHECK: smuadx r3, r2, r1 @ encoding: [0x22,0xfb,0x11,0xf3]
+@ CHECK: ite lt @ encoding: [0xb4,0xbf]
+@ CHECK: smuadlt r2, r3, r4 @ encoding: [0x23,0xfb,0x04,0xf2]
+@ CHECK: smuadxge r3, r2, r1 @ encoding: [0x22,0xfb,0x11,0xf3]
+
+
+@------------------------------------------------------------------------------
+@ SMULBB/SMULBT/SMULTB/SMULTT
+@------------------------------------------------------------------------------
+ smulbb r3, r9, r0
+ smulbt r5, r4, r1
+ smultb r4, r2, r2
+ smultt r8, r3, r4
+ itete ge
+ smulbbge r1, r9, r0
+ smulbtlt r5, r6, r4
+ smultbge r2, r3, r2
+ smulttlt r8, r3, r4
+
+@ CHECK: smulbb r3, r9, r0 @ encoding: [0x19,0xfb,0x00,0xf3]
+@ CHECK: smulbt r5, r4, r1 @ encoding: [0x14,0xfb,0x11,0xf5]
+@ CHECK: smultb r4, r2, r2 @ encoding: [0x12,0xfb,0x22,0xf4]
+@ CHECK: smultt r8, r3, r4 @ encoding: [0x13,0xfb,0x34,0xf8]
+@ CHECK: itete ge @ encoding: [0xab,0xbf]
+@ CHECK: smulbbge r1, r9, r0 @ encoding: [0x19,0xfb,0x00,0xf1]
+@ CHECK: smulbtlt r5, r6, r4 @ encoding: [0x16,0xfb,0x14,0xf5]
+@ CHECK: smultbge r2, r3, r2 @ encoding: [0x13,0xfb,0x22,0xf2]
+@ CHECK: smulttlt r8, r3, r4 @ encoding: [0x13,0xfb,0x34,0xf8]
+
+
+@------------------------------------------------------------------------------
+@ SMULL
+@------------------------------------------------------------------------------
+ smull r3, r9, r0, r1
+ it eq
+ smulleq r8, r3, r4, r5
+
+@ CHECK: smull r3, r9, r0, r1 @ encoding: [0x80,0xfb,0x01,0x39]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: smulleq r8, r3, r4, r5 @ encoding: [0x84,0xfb,0x05,0x83]
+
+
+@------------------------------------------------------------------------------
+@ SMULWB/SMULWT
+@------------------------------------------------------------------------------
+ smulwb r3, r9, r0
+ smulwt r3, r9, r2
+ ite gt
+ smulwbgt r3, r9, r0
+ smulwtle r3, r9, r2
+
+@ CHECK: smulwb r3, r9, r0 @ encoding: [0x39,0xfb,0x00,0xf3]
+@ CHECK: smulwt r3, r9, r2 @ encoding: [0x39,0xfb,0x12,0xf3]
+@ CHECK: ite gt @ encoding: [0xcc,0xbf]
+@ CHECK: smulwbgt r3, r9, r0 @ encoding: [0x39,0xfb,0x00,0xf3]
+@ CHECK: smulwtle r3, r9, r2 @ encoding: [0x39,0xfb,0x12,0xf3]
+
+
+@------------------------------------------------------------------------------
+@ SMUSD/SMUSDX
+@------------------------------------------------------------------------------
+ smusd r3, r0, r1
+ smusdx r3, r9, r2
+ ite eq
+ smusdeq r8, r3, r2
+ smusdxne r7, r4, r3
+
+@ CHECK: smusd r3, r0, r1 @ encoding: [0x40,0xfb,0x01,0xf3]
+@ CHECK: smusdx r3, r9, r2 @ encoding: [0x49,0xfb,0x12,0xf3]
+@ CHECK: ite eq @ encoding: [0x0c,0xbf]
+@ CHECK: smusdeq r8, r3, r2 @ encoding: [0x43,0xfb,0x02,0xf8]
+@ CHECK: smusdxne r7, r4, r3 @ encoding: [0x44,0xfb,0x13,0xf7]
+
+
+@------------------------------------------------------------------------------
+@ SRS
+@------------------------------------------------------------------------------
+ srsdb sp, #1
+ srsia sp, #0
+
+ srsdb sp!, #19
+ srsia sp!, #2
+
+ srsea sp, #10
+ srsfd sp, #9
+
+ srsea sp!, #5
+ srsfd sp!, #5
+
+ srs sp, #5
+ srs sp!, #5
+
+@ CHECK: srsdb sp, #1 @ encoding: [0x0d,0xe8,0x01,0xc0]
+@ CHECK: srsia sp, #0 @ encoding: [0x8d,0xe9,0x00,0xc0]
+@ CHECK: srsdb sp!, #19 @ encoding: [0x2d,0xe8,0x13,0xc0]
+@ CHECK: srsia sp!, #2 @ encoding: [0xad,0xe9,0x02,0xc0]
+@ CHECK: srsdb sp, #10 @ encoding: [0x0d,0xe8,0x0a,0xc0]
+@ CHECK: srsia sp, #9 @ encoding: [0x8d,0xe9,0x09,0xc0]
+@ CHECK: srsdb sp!, #5 @ encoding: [0x2d,0xe8,0x05,0xc0]
+@ CHECK: srsia sp!, #5 @ encoding: [0xad,0xe9,0x05,0xc0]
+@ CHECK: srsia sp, #5 @ encoding: [0x8d,0xe9,0x05,0xc0]
+@ CHECK: srsia sp!, #5 @ encoding: [0xad,0xe9,0x05,0xc0]
+
+
+@------------------------------------------------------------------------------
+@ SSAT
+@------------------------------------------------------------------------------
+ ssat r8, #1, r10
+ ssat r8, #1, r10, lsl #0
+ ssat r8, #1, r10, lsl #31
+ ssat r8, #1, r10, asr #1
+
+@ CHECK: ssat r8, #1, r10 @ encoding: [0x0a,0xf3,0x00,0x08]
+@ CHECK: ssat r8, #1, r10 @ encoding: [0x0a,0xf3,0x00,0x08]
+@ CHECK: ssat r8, #1, r10, lsl #31 @ encoding: [0x0a,0xf3,0xc0,0x78]
+@ CHECK: ssat r8, #1, r10, asr #1 @ encoding: [0x2a,0xf3,0x40,0x08]
+
+
+@------------------------------------------------------------------------------
+@ SSAT16
+@------------------------------------------------------------------------------
+ ssat16 r2, #1, r7
+ ssat16 r3, #16, r5
+
+@ CHECK: ssat16 r2, #1, r7 @ encoding: [0x27,0xf3,0x00,0x02]
+@ CHECK: ssat16 r3, #16, r5 @ encoding: [0x25,0xf3,0x0f,0x03]
+
+
+@------------------------------------------------------------------------------
+@ SSAX
+@------------------------------------------------------------------------------
+ ssubaddx r2, r3, r4
+ it lt
+ ssubaddxlt r2, r3, r4
+ ssax r2, r3, r4
+ it lt
+ ssaxlt r2, r3, r4
+
+@ CHECK: ssax r2, r3, r4 @ encoding: [0xe3,0xfa,0x04,0xf2]
+@ CHECK: it lt @ encoding: [0xb8,0xbf]
+@ CHECK: ssaxlt r2, r3, r4 @ encoding: [0xe3,0xfa,0x04,0xf2]
+@ CHECK: ssax r2, r3, r4 @ encoding: [0xe3,0xfa,0x04,0xf2]
+@ CHECK: it lt @ encoding: [0xb8,0xbf]
+@ CHECK: ssaxlt r2, r3, r4 @ encoding: [0xe3,0xfa,0x04,0xf2]
+
+
+@------------------------------------------------------------------------------
+@ SSUB16/SSUB8
+@------------------------------------------------------------------------------
+ ssub16 r1, r0, r6
+ ssub8 r9, r2, r4
+ ite ne
+ ssub16ne r5, r3, r2
+ ssub8eq r5, r1, r2
+
+@ CHECK: ssub16 r1, r0, r6 @ encoding: [0xd0,0xfa,0x06,0xf1]
+@ CHECK: ssub8 r9, r2, r4 @ encoding: [0xc2,0xfa,0x04,0xf9]
+@ CHECK: ite ne @ encoding: [0x14,0xbf]
+@ CHECK: ssub16ne r5, r3, r2 @ encoding: [0xd3,0xfa,0x02,0xf5]
+@ CHECK: ssub8eq r5, r1, r2 @ encoding: [0xc1,0xfa,0x02,0xf5]
+
+
+@------------------------------------------------------------------------------
+@ STC{L}/STC2{L}
+@------------------------------------------------------------------------------
+ stc2 p0, c8, [r1, #4]
+ stc2 p1, c7, [r2]
+ stc2 p2, c6, [r3, #-224]
+ stc2 p3, c5, [r4, #-120]!
+ stc2 p4, c4, [r5], #16
+ stc2 p5, c3, [r6], #-72
+ stc2l p6, c2, [r7, #4]
+ stc2l p7, c1, [r8]
+ stc2l p8, c0, [r9, #-224]
+ stc2l p9, c1, [r10, #-120]!
+ stc2l p10, c2, [r11], #16
+ stc2l p11, c3, [r12], #-72
+
+ stc p12, c4, [r0, #4]
+ stc p13, c5, [r1]
+ stc p14, c6, [r2, #-224]
+ stc p15, c7, [r3, #-120]!
+ stc p5, c8, [r4], #16
+ stc p4, c9, [r5], #-72
+ stcl p3, c10, [r6, #4]
+ stcl p2, c11, [r7]
+ stcl p1, c12, [r8, #-224]
+ stcl p0, c13, [r9, #-120]!
+ stcl p6, c14, [r10], #16
+ stcl p7, c15, [r11], #-72
+
+ stc2 p2, c8, [r1], { 25 }
+
+@ CHECK: stc2 p0, c8, [r1, #4] @ encoding: [0x81,0xfd,0x01,0x80]
+@ CHECK: stc2 p1, c7, [r2] @ encoding: [0x82,0xfd,0x00,0x71]
+@ CHECK: stc2 p2, c6, [r3, #-224] @ encoding: [0x03,0xfd,0x38,0x62]
+@ CHECK: stc2 p3, c5, [r4, #-120]! @ encoding: [0x24,0xfd,0x1e,0x53]
+@ CHECK: stc2 p4, c4, [r5], #16 @ encoding: [0xa5,0xfc,0x04,0x44]
+@ CHECK: stc2 p5, c3, [r6], #-72 @ encoding: [0x26,0xfc,0x12,0x35]
+@ CHECK: stc2l p6, c2, [r7, #4] @ encoding: [0xc7,0xfd,0x01,0x26]
+@ CHECK: stc2l p7, c1, [r8] @ encoding: [0xc8,0xfd,0x00,0x17]
+@ CHECK: stc2l p8, c0, [r9, #-224] @ encoding: [0x49,0xfd,0x38,0x08]
+@ CHECK: stc2l p9, c1, [r10, #-120]! @ encoding: [0x6a,0xfd,0x1e,0x19]
+@ CHECK: stc2l p10, c2, [r11], #16 @ encoding: [0xeb,0xfc,0x04,0x2a]
+@ CHECK: stc2l p11, c3, [r12], #-72 @ encoding: [0x6c,0xfc,0x12,0x3b]
+
+@ CHECK: stc p12, c4, [r0, #4] @ encoding: [0x80,0xed,0x01,0x4c]
+@ CHECK: stc p13, c5, [r1] @ encoding: [0x81,0xed,0x00,0x5d]
+@ CHECK: stc p14, c6, [r2, #-224] @ encoding: [0x02,0xed,0x38,0x6e]
+@ CHECK: stc p15, c7, [r3, #-120]! @ encoding: [0x23,0xed,0x1e,0x7f]
+@ CHECK: stc p5, c8, [r4], #16 @ encoding: [0xa4,0xec,0x04,0x85]
+@ CHECK: stc p4, c9, [r5], #-72 @ encoding: [0x25,0xec,0x12,0x94]
+@ CHECK: stcl p3, c10, [r6, #4] @ encoding: [0xc6,0xed,0x01,0xa3]
+@ CHECK: stcl p2, c11, [r7] @ encoding: [0xc7,0xed,0x00,0xb2]
+@ CHECK: stcl p1, c12, [r8, #-224] @ encoding: [0x48,0xed,0x38,0xc1]
+@ CHECK: stcl p0, c13, [r9, #-120]! @ encoding: [0x69,0xed,0x1e,0xd0]
+@ CHECK: stcl p6, c14, [r10], #16 @ encoding: [0xea,0xec,0x04,0xe6]
+@ CHECK: stcl p7, c15, [r11], #-72 @ encoding: [0x6b,0xec,0x12,0xf7]
+
+@ CHECK: stc2 p2, c8, [r1], {25} @ encoding: [0x81,0xfc,0x19,0x82]
+
+
+@------------------------------------------------------------------------------
+@ STMIA
+@------------------------------------------------------------------------------
+ stmia.w r4, {r4, r5, r8, r9}
+ stmia.w r4, {r5, r6}
+ stmia.w r5!, {r3, r8}
+ stm.w r4, {r4, r5, r8, r9}
+ stm.w r4, {r5, r6}
+ stm.w r5!, {r3, r8}
+ stm.w r5!, {r1, r2}
+ stm.w r2, {r1, r2}
+
+ stmia r4, {r4, r5, r8, r9}
+ stmia r4, {r5, r6}
+ stmia r5!, {r3, r8}
+ stm r4, {r4, r5, r8, r9}
+ stm r4, {r5, r6}
+ stm r5!, {r3, r8}
+ stmea r5!, {r3, r8}
+
+@ CHECK: stm.w r4, {r4, r5, r8, r9} @ encoding: [0x84,0xe8,0x30,0x03]
+@ CHECK: stm.w r4, {r5, r6} @ encoding: [0x84,0xe8,0x60,0x00]
+@ CHECK: stm.w r5!, {r3, r8} @ encoding: [0xa5,0xe8,0x08,0x01]
+@ CHECK: stm.w r4, {r4, r5, r8, r9} @ encoding: [0x84,0xe8,0x30,0x03]
+@ CHECK: stm.w r4, {r5, r6} @ encoding: [0x84,0xe8,0x60,0x00]
+@ CHECK: stm.w r5!, {r3, r8} @ encoding: [0xa5,0xe8,0x08,0x01]
+@ CHECK: stm.w r5!, {r1, r2} @ encoding: [0xa5,0xe8,0x06,0x00]
+@ CHECK: stm.w r2, {r1, r2} @ encoding: [0x82,0xe8,0x06,0x00]
+
+@ CHECK: stm.w r4, {r4, r5, r8, r9} @ encoding: [0x84,0xe8,0x30,0x03]
+@ CHECK: stm.w r4, {r5, r6} @ encoding: [0x84,0xe8,0x60,0x00]
+@ CHECK: stm.w r5!, {r3, r8} @ encoding: [0xa5,0xe8,0x08,0x01]
+@ CHECK: stm.w r4, {r4, r5, r8, r9} @ encoding: [0x84,0xe8,0x30,0x03]
+@ CHECK: stm.w r4, {r5, r6} @ encoding: [0x84,0xe8,0x60,0x00]
+@ CHECK: stm.w r5!, {r3, r8} @ encoding: [0xa5,0xe8,0x08,0x01]
+@ CHECK: stm.w r5!, {r3, r8} @ encoding: [0xa5,0xe8,0x08,0x01]
+
+
+@------------------------------------------------------------------------------
+@ STMDB
+@------------------------------------------------------------------------------
+ stmdb r4, {r4, r5, r8, r9}
+ stmdb r4, {r5, r6}
+ stmdb r5!, {r3, r8}
+ stmea r5!, {r3, r8}
+
+@ CHECK: stmdb r4, {r4, r5, r8, r9} @ encoding: [0x04,0xe9,0x30,0x03]
+@ CHECK: stmdb r4, {r5, r6} @ encoding: [0x04,0xe9,0x60,0x00]
+@ CHECK: stmdb r5!, {r3, r8} @ encoding: [0x25,0xe9,0x08,0x01]
+@ CHECK: stm.w r5!, {r3, r8} @ encoding: [0xa5,0xe8,0x08,0x01]
+
+
+@------------------------------------------------------------------------------
+@ STR(immediate)
+@------------------------------------------------------------------------------
+ str r5, [r5, #-4]
+ str r5, [r6, #32]
+ str r5, [r6, #33]
+ str r5, [r6, #257]
+ str.w pc, [r7, #257]
+ str r2, [r4, #255]!
+ str r8, [sp, #4]!
+ str lr, [sp, #-4]!
+ str r2, [r4], #255
+ str r8, [sp], #4
+ str lr, [sp], #-4
+
+@ CHECK: str r5, [r5, #-4] @ encoding: [0x45,0xf8,0x04,0x5c]
+@ CHECK: str r5, [r6, #32] @ encoding: [0x35,0x62]
+@ CHECK: str.w r5, [r6, #33] @ encoding: [0xc6,0xf8,0x21,0x50]
+@ CHECK: str.w r5, [r6, #257] @ encoding: [0xc6,0xf8,0x01,0x51]
+@ CHECK: str.w pc, [r7, #257] @ encoding: [0xc7,0xf8,0x01,0xf1]
+@ CHECK: str r2, [r4, #255]! @ encoding: [0x44,0xf8,0xff,0x2f]
+@ CHECK: str r8, [sp, #4]! @ encoding: [0x4d,0xf8,0x04,0x8f]
+@ CHECK: str lr, [sp, #-4]! @ encoding: [0x4d,0xf8,0x04,0xed]
+@ CHECK: str r2, [r4], #255 @ encoding: [0x44,0xf8,0xff,0x2b]
+@ CHECK: str r8, [sp], #4 @ encoding: [0x4d,0xf8,0x04,0x8b]
+@ CHECK: str lr, [sp], #-4 @ encoding: [0x4d,0xf8,0x04,0xe9]
+
+
+@------------------------------------------------------------------------------
+@ STR(register)
+@------------------------------------------------------------------------------
+ str r1, [r8, r1]
+ str.w r4, [r5, r2]
+ str r6, [r0, r2, lsl #3]
+ str r8, [r8, r2, lsl #2]
+ str r7, [sp, r2, lsl #1]
+ str r7, [sp, r2, lsl #0]
+
+@ CHECK: str.w r1, [r8, r1] @ encoding: [0x48,0xf8,0x01,0x10]
+@ CHECK: str.w r4, [r5, r2] @ encoding: [0x45,0xf8,0x02,0x40]
+@ CHECK: str.w r6, [r0, r2, lsl #3] @ encoding: [0x40,0xf8,0x32,0x60]
+@ CHECK: str.w r8, [r8, r2, lsl #2] @ encoding: [0x48,0xf8,0x22,0x80]
+@ CHECK: str.w r7, [sp, r2, lsl #1] @ encoding: [0x4d,0xf8,0x12,0x70]
+@ CHECK: str.w r7, [sp, r2] @ encoding: [0x4d,0xf8,0x02,0x70]
+
+
+@------------------------------------------------------------------------------
+@ STRB(immediate)
+@------------------------------------------------------------------------------
+ strb r5, [r5, #-4]
+ strb r5, [r6, #32]
+ strb r5, [r6, #33]
+ strb r5, [r6, #257]
+ strb.w lr, [r7, #257]
+ strb r5, [r8, #255]!
+ strb r2, [r5, #4]!
+ strb r1, [r4, #-4]!
+ strb lr, [r3], #255
+ strb r9, [r2], #4
+ strb r3, [sp], #-4
+ strb r4, [r8, #-0]!
+
+@ CHECK: strb r5, [r5, #-4] @ encoding: [0x05,0xf8,0x04,0x5c]
+@ CHECK: strb.w r5, [r6, #32] @ encoding: [0x86,0xf8,0x20,0x50]
+@ CHECK: strb.w r5, [r6, #33] @ encoding: [0x86,0xf8,0x21,0x50]
+@ CHECK: strb.w r5, [r6, #257] @ encoding: [0x86,0xf8,0x01,0x51]
+@ CHECK: strb.w lr, [r7, #257] @ encoding: [0x87,0xf8,0x01,0xe1]
+@ CHECK: strb r5, [r8, #255]! @ encoding: [0x08,0xf8,0xff,0x5f]
+@ CHECK: strb r2, [r5, #4]! @ encoding: [0x05,0xf8,0x04,0x2f]
+@ CHECK: strb r1, [r4, #-4]! @ encoding: [0x04,0xf8,0x04,0x1d]
+@ CHECK: strb lr, [r3], #255 @ encoding: [0x03,0xf8,0xff,0xeb]
+@ CHECK: strb r9, [r2], #4 @ encoding: [0x02,0xf8,0x04,0x9b]
+@ CHECK: strb r3, [sp], #-4 @ encoding: [0x0d,0xf8,0x04,0x39]
+@ CHECK: strb r4, [r8, #-0]! @ encoding: [0x08,0xf8,0x00,0x4d]
+
+
+@------------------------------------------------------------------------------
+@ STRB(register)
+@------------------------------------------------------------------------------
+ strb r1, [r8, r1]
+ strb.w r4, [r5, r2]
+ strb r6, [r0, r2, lsl #3]
+ strb r8, [r8, r2, lsl #2]
+ strb r7, [sp, r2, lsl #1]
+ strb r7, [sp, r2, lsl #0]
+
+@ CHECK: strb.w r1, [r8, r1] @ encoding: [0x08,0xf8,0x01,0x10]
+@ CHECK: strb.w r4, [r5, r2] @ encoding: [0x05,0xf8,0x02,0x40]
+@ CHECK: strb.w r6, [r0, r2, lsl #3] @ encoding: [0x00,0xf8,0x32,0x60]
+@ CHECK: strb.w r8, [r8, r2, lsl #2] @ encoding: [0x08,0xf8,0x22,0x80]
+@ CHECK: strb.w r7, [sp, r2, lsl #1] @ encoding: [0x0d,0xf8,0x12,0x70]
+@ CHECK: strb.w r7, [sp, r2] @ encoding: [0x0d,0xf8,0x02,0x70]
+
+
+@------------------------------------------------------------------------------
+@ STRBT
+@------------------------------------------------------------------------------
+ strbt r1, [r2]
+ strbt r1, [r8, #0]
+ strbt r1, [r8, #3]
+ strbt r1, [r8, #255]
+
+@ CHECK: strbt r1, [r2] @ encoding: [0x02,0xf8,0x00,0x1e]
+@ CHECK: strbt r1, [r8] @ encoding: [0x08,0xf8,0x00,0x1e]
+@ CHECK: strbt r1, [r8, #3] @ encoding: [0x08,0xf8,0x03,0x1e]
+@ CHECK: strbt r1, [r8, #255] @ encoding: [0x08,0xf8,0xff,0x1e]
+
+
+@------------------------------------------------------------------------------
+@ STRD
+@------------------------------------------------------------------------------
+ strd r3, r5, [r6, #24]
+ strd r3, r5, [r6, #24]!
+ strd r3, r5, [r6], #4
+ strd r3, r5, [r6], #-8
+ strd r3, r5, [r6]
+ strd r8, r1, [r3, #0]
+
+@ CHECK: strd r3, r5, [r6, #24] @ encoding: [0xc6,0xe9,0x06,0x35]
+@ CHECK: strd r3, r5, [r6, #24]! @ encoding: [0xe6,0xe9,0x06,0x35]
+@ CHECK: strd r3, r5, [r6], #4 @ encoding: [0xe6,0xe8,0x01,0x35]
+@ CHECK: strd r3, r5, [r6], #-8 @ encoding: [0x66,0xe8,0x02,0x35]
+@ CHECK: strd r3, r5, [r6] @ encoding: [0xc6,0xe9,0x00,0x35]
+@ CHECK: strd r8, r1, [r3] @ encoding: [0xc3,0xe9,0x00,0x81]
+
+
+@------------------------------------------------------------------------------
+@ STREX/STREXB/STREXH/STREXD
+@------------------------------------------------------------------------------
+ strex r1, r8, [r4]
+ strex r8, r2, [r4, #0]
+ strex r2, r12, [sp, #128]
+ strexb r5, r1, [r7]
+ strexh r9, r7, [r12]
+ strexd r9, r3, r6, [r4]
+
+@ CHECK: strex r1, r8, [r4] @ encoding: [0x44,0xe8,0x00,0x81]
+@ CHECK: strex r8, r2, [r4] @ encoding: [0x44,0xe8,0x00,0x28]
+@ CHECK: strex r2, r12, [sp, #128] @ encoding: [0x4d,0xe8,0x20,0xc2]
+@ CHECK: strexb r5, r1, [r7] @ encoding: [0xc7,0xe8,0x45,0x1f]
+@ CHECK: strexh r9, r7, [r12] @ encoding: [0xcc,0xe8,0x59,0x7f]
+@ CHECK: strexd r9, r3, r6, [r4] @ encoding: [0xc4,0xe8,0x79,0x36]
+
+
+@------------------------------------------------------------------------------
+@ STRH(immediate)
+@------------------------------------------------------------------------------
+ strh r5, [r5, #-4]
+ strh r5, [r6, #32]
+ strh r5, [r6, #33]
+ strh r5, [r6, #257]
+ strh.w lr, [r7, #257]
+ strh r5, [r8, #255]!
+ strh r2, [r5, #4]!
+ strh r1, [r4, #-4]!
+ strh lr, [r3], #255
+ strh r9, [r2], #4
+ strh r3, [sp], #-4
+
+@ CHECK: strh r5, [r5, #-4] @ encoding: [0x25,0xf8,0x04,0x5c]
+@ CHECK: strh r5, [r6, #32] @ encoding: [0x35,0x84]
+@ CHECK: strh.w r5, [r6, #33] @ encoding: [0xa6,0xf8,0x21,0x50]
+@ CHECK: strh.w r5, [r6, #257] @ encoding: [0xa6,0xf8,0x01,0x51]
+@ CHECK: strh.w lr, [r7, #257] @ encoding: [0xa7,0xf8,0x01,0xe1]
+@ CHECK: strh r5, [r8, #255]! @ encoding: [0x28,0xf8,0xff,0x5f]
+@ CHECK: strh r2, [r5, #4]! @ encoding: [0x25,0xf8,0x04,0x2f]
+@ CHECK: strh r1, [r4, #-4]! @ encoding: [0x24,0xf8,0x04,0x1d]
+@ CHECK: strh lr, [r3], #255 @ encoding: [0x23,0xf8,0xff,0xeb]
+@ CHECK: strh r9, [r2], #4 @ encoding: [0x22,0xf8,0x04,0x9b]
+@ CHECK: strh r3, [sp], #-4 @ encoding: [0x2d,0xf8,0x04,0x39]
+
+
+@------------------------------------------------------------------------------
+@ STRH(register)
+@------------------------------------------------------------------------------
+ strh r1, [r8, r1]
+ strh.w r4, [r5, r2]
+ strh r6, [r0, r2, lsl #3]
+ strh r8, [r8, r2, lsl #2]
+ strh r7, [sp, r2, lsl #1]
+ strh r7, [sp, r2, lsl #0]
+
+@ CHECK: strh.w r1, [r8, r1] @ encoding: [0x28,0xf8,0x01,0x10]
+@ CHECK: strh.w r4, [r5, r2] @ encoding: [0x25,0xf8,0x02,0x40]
+@ CHECK: strh.w r6, [r0, r2, lsl #3] @ encoding: [0x20,0xf8,0x32,0x60]
+@ CHECK: strh.w r8, [r8, r2, lsl #2] @ encoding: [0x28,0xf8,0x22,0x80]
+@ CHECK: strh.w r7, [sp, r2, lsl #1] @ encoding: [0x2d,0xf8,0x12,0x70]
+@ CHECK: strh.w r7, [sp, r2] @ encoding: [0x2d,0xf8,0x02,0x70]
+
+
+@------------------------------------------------------------------------------
+@ STRHT
+@------------------------------------------------------------------------------
+ strht r1, [r2]
+ strht r1, [r8, #0]
+ strht r1, [r8, #3]
+ strht r1, [r8, #255]
+
+@ CHECK: strht r1, [r2] @ encoding: [0x22,0xf8,0x00,0x1e]
+@ CHECK: strht r1, [r8] @ encoding: [0x28,0xf8,0x00,0x1e]
+@ CHECK: strht r1, [r8, #3] @ encoding: [0x28,0xf8,0x03,0x1e]
+@ CHECK: strht r1, [r8, #255] @ encoding: [0x28,0xf8,0xff,0x1e]
+
+
+@------------------------------------------------------------------------------
+@ STRT
+@------------------------------------------------------------------------------
+ strt r1, [r2]
+ strt r1, [r8, #0]
+ strt r1, [r8, #3]
+ strt r1, [r8, #255]
+
+@ CHECK: strt r1, [r2] @ encoding: [0x42,0xf8,0x00,0x1e]
+@ CHECK: strt r1, [r8] @ encoding: [0x48,0xf8,0x00,0x1e]
+@ CHECK: strt r1, [r8, #3] @ encoding: [0x48,0xf8,0x03,0x1e]
+@ CHECK: strt r1, [r8, #255] @ encoding: [0x48,0xf8,0xff,0x1e]
+
+
+@------------------------------------------------------------------------------
+@ SUB (immediate)
+@------------------------------------------------------------------------------
+ itet eq
+ subeq r1, r2, #4
+ subwne r5, r3, #1023
+ subeq r4, r5, #293
+ sub r2, sp, #1024
+ sub r2, r8, #0xff00
+ sub r2, r3, #257
+ subw r2, r3, #257
+ sub r12, r6, #0x100
+ subw r12, r6, #0x100
+ subs r1, r2, #0x1f0
+
+@ CHECK: itet eq @ encoding: [0x0a,0xbf]
+@ CHECK: subeq r1, r2, #4 @ encoding: [0x11,0x1f]
+@ CHECK: subwne r5, r3, #1023 @ encoding: [0xa3,0xf2,0xff,0x35]
+@ CHECK: subweq r4, r5, #293 @ encoding: [0xa5,0xf2,0x25,0x14]
+@ CHECK: sub.w r2, sp, #1024 @ encoding: [0xad,0xf5,0x80,0x62]
+@ CHECK: sub.w r2, r8, #65280 @ encoding: [0xa8,0xf5,0x7f,0x42]
+@ CHECK: subw r2, r3, #257 @ encoding: [0xa3,0xf2,0x01,0x12]
+@ CHECK: subw r2, r3, #257 @ encoding: [0xa3,0xf2,0x01,0x12]
+@ CHECK: sub.w r12, r6, #256 @ encoding: [0xa6,0xf5,0x80,0x7c]
+@ CHECK: subw r12, r6, #256 @ encoding: [0xa6,0xf2,0x00,0x1c]
+@ CHECK: subs.w r1, r2, #496 @ encoding: [0xb2,0xf5,0xf8,0x71]
+
+
+@------------------------------------------------------------------------------
+@ SUB (register)
+@------------------------------------------------------------------------------
+ sub r4, r5, r6
+ sub r4, r5, r6, lsl #5
+ sub r4, r5, r6, lsr #5
+ sub.w r4, r5, r6, lsr #5
+ sub r4, r5, r6, asr #5
+ sub r4, r5, r6, ror #5
+ sub.w r5, r2, r12, rrx
+
+@ CHECK: sub.w r4, r5, r6 @ encoding: [0xa5,0xeb,0x06,0x04]
+@ CHECK: sub.w r4, r5, r6, lsl #5 @ encoding: [0xa5,0xeb,0x46,0x14]
+@ CHECK: sub.w r4, r5, r6, lsr #5 @ encoding: [0xa5,0xeb,0x56,0x14]
+@ CHECK: sub.w r4, r5, r6, lsr #5 @ encoding: [0xa5,0xeb,0x56,0x14]
+@ CHECK: sub.w r4, r5, r6, asr #5 @ encoding: [0xa5,0xeb,0x66,0x14]
+@ CHECK: sub.w r4, r5, r6, ror #5 @ encoding: [0xa5,0xeb,0x76,0x14]
+@ CHECK: sub.w r5, r2, r12, rrx @ encoding: [0xa2,0xeb,0x3c,0x05]
+
+
+@------------------------------------------------------------------------------
+@ SVC
+@------------------------------------------------------------------------------
+ svc #0
+ ite eq
+ svceq #255
+ swine #33
+
+@ CHECK: svc #0 @ encoding: [0x00,0xdf]
+@ CHECK: ite eq @ encoding: [0x0c,0xbf]
+@ CHECK: svceq #255 @ encoding: [0xff,0xdf]
+@ CHECK: svcne #33 @ encoding: [0x21,0xdf]
+
+
+@------------------------------------------------------------------------------
+@ SXTAB
+@------------------------------------------------------------------------------
+ sxtab r2, r3, r4
+ sxtab r4, r5, r6, ror #0
+ it lt
+ sxtablt r6, r2, r9, ror #8
+ sxtab r5, r1, r4, ror #16
+ sxtab r7, r8, r3, ror #24
+
+@ CHECK: sxtab r2, r3, r4 @ encoding: [0x43,0xfa,0x84,0xf2]
+@ CHECK: sxtab r4, r5, r6 @ encoding: [0x45,0xfa,0x86,0xf4]
+@ CHECK: it lt @ encoding: [0xb8,0xbf]
+@ CHECK: sxtablt r6, r2, r9, ror #8 @ encoding: [0x42,0xfa,0x99,0xf6]
+@ CHECK: sxtab r5, r1, r4, ror #16 @ encoding: [0x41,0xfa,0xa4,0xf5]
+@ CHECK: sxtab r7, r8, r3, ror #24 @ encoding: [0x48,0xfa,0xb3,0xf7]
+
+
+@------------------------------------------------------------------------------
+@ SXTAB16
+@------------------------------------------------------------------------------
+ sxtab16 r6, r2, r7, ror #0
+ sxtab16 r3, r5, r8, ror #8
+ sxtab16 r3, r2, r1, ror #16
+ ite ne
+ sxtab16ne r0, r1, r4
+ sxtab16eq r1, r2, r3, ror #24
+
+@ CHECK: sxtab16 r6, r2, r7 @ encoding: [0x22,0xfa,0x87,0xf6]
+@ CHECK: sxtab16 r3, r5, r8, ror #8 @ encoding: [0x25,0xfa,0x98,0xf3]
+@ CHECK: sxtab16 r3, r2, r1, ror #16 @ encoding: [0x22,0xfa,0xa1,0xf3]
+@ CHECK: ite ne @ encoding: [0x14,0xbf]
+@ CHECK: sxtab16ne r0, r1, r4 @ encoding: [0x21,0xfa,0x84,0xf0]
+@ CHECK: sxtab16eq r1, r2, r3, ror #24 @ encoding: [0x22,0xfa,0xb3,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ SXTAH
+@------------------------------------------------------------------------------
+ sxtah r1, r3, r9
+ sxtah r3, r8, r3, ror #8
+ sxtah r9, r3, r3, ror #24
+ ite hi
+ sxtahhi r6, r1, r6, ror #0
+ sxtahls r2, r2, r4, ror #16
+
+@ CHECK: sxtah r1, r3, r9 @ encoding: [0x03,0xfa,0x89,0xf1]
+@ CHECK: sxtah r3, r8, r3, ror #8 @ encoding: [0x08,0xfa,0x93,0xf3]
+@ CHECK: sxtah r9, r3, r3, ror #24 @ encoding: [0x03,0xfa,0xb3,0xf9]
+@ CHECK: ite hi @ encoding: [0x8c,0xbf]
+@ CHECK: sxtahhi r6, r1, r6 @ encoding: [0x01,0xfa,0x86,0xf6]
+@ CHECK: sxtahls r2, r2, r4, ror #16 @ encoding: [0x02,0xfa,0xa4,0xf2]
+
+
+@------------------------------------------------------------------------------
+@ SXTB
+@------------------------------------------------------------------------------
+ sxtb r5, r6, ror #0
+ sxtb r6, r9, ror #8
+ sxtb r8, r3, ror #24
+ ite ge
+ sxtbge r2, r4
+ sxtblt r5, r1, ror #16
+ sxtb.w r7, r8
+
+@ CHECK: sxtb r5, r6 @ encoding: [0x75,0xb2]
+@ CHECK: sxtb.w r6, r9, ror #8 @ encoding: [0x4f,0xfa,0x99,0xf6]
+@ CHECK: sxtb.w r8, r3, ror #24 @ encoding: [0x4f,0xfa,0xb3,0xf8]
+@ CHECK: ite ge @ encoding: [0xac,0xbf]
+@ CHECK: sxtbge r2, r4 @ encoding: [0x62,0xb2]
+@ CHECK: sxtblt.w r5, r1, ror #16 @ encoding: [0x4f,0xfa,0xa1,0xf5]
+@ CHECK: sxtb.w r7, r8 @ encoding: [0x4f,0xfa,0x88,0xf7]
+
+
+@------------------------------------------------------------------------------
+@ SXTB16
+@------------------------------------------------------------------------------
+ sxtb16 r1, r4
+ sxtb16 r6, r7, ror #0
+ sxtb16 r3, r1, ror #16
+ ite cs
+ sxtb16cs r3, r5, ror #8
+ sxtb16lo r2, r3, ror #24
+
+@ CHECK: sxtb16 r1, r4 @ encoding: [0x2f,0xfa,0x84,0xf1]
+@ CHECK: sxtb16 r6, r7 @ encoding: [0x2f,0xfa,0x87,0xf6]
+@ CHECK: sxtb16 r3, r1, ror #16 @ encoding: [0x2f,0xfa,0xa1,0xf3]
+@ CHECK: ite hs @ encoding: [0x2c,0xbf]
+@ CHECK: sxtb16hs r3, r5, ror #8 @ encoding: [0x2f,0xfa,0x95,0xf3]
+@ CHECK: sxtb16lo r2, r3, ror #24 @ encoding: [0x2f,0xfa,0xb3,0xf2]
+
+
+@------------------------------------------------------------------------------
+@ SXTH
+@------------------------------------------------------------------------------
+ sxth r1, r6, ror #0
+ sxth r3, r8, ror #8
+ sxth r9, r3, ror #24
+ itt ne
+ sxthne r3, r9
+ sxthne r2, r2, ror #16
+ sxth.w r7, r8
+
+@ CHECK: sxth r1, r6 @ encoding: [0x31,0xb2]
+@ CHECK: sxth.w r3, r8, ror #8 @ encoding: [0x0f,0xfa,0x98,0xf3]
+@ CHECK: sxth.w r9, r3, ror #24 @ encoding: [0x0f,0xfa,0xb3,0xf9]
+@ CHECK: itt ne @ encoding: [0x1c,0xbf]
+@ CHECK: sxthne.w r3, r9 @ encoding: [0x0f,0xfa,0x89,0xf3]
+@ CHECK: sxthne.w r2, r2, ror #16 @ encoding: [0x0f,0xfa,0xa2,0xf2]
+@ CHECK: sxth.w r7, r8 @ encoding: [0x0f,0xfa,0x88,0xf7]
+
+
+@------------------------------------------------------------------------------
+@ SXTB
+@------------------------------------------------------------------------------
+ sxtb r5, r6, ror #0
+ sxtb.w r6, r9, ror #8
+ sxtb r8, r3, ror #24
+ ite ge
+ sxtbge r2, r4
+ sxtblt r5, r1, ror #16
+
+@ CHECK: sxtb r5, r6 @ encoding: [0x75,0xb2]
+@ CHECK: sxtb.w r6, r9, ror #8 @ encoding: [0x4f,0xfa,0x99,0xf6]
+@ CHECK: sxtb.w r8, r3, ror #24 @ encoding: [0x4f,0xfa,0xb3,0xf8]
+@ CHECK: ite ge @ encoding: [0xac,0xbf]
+@ CHECK: sxtbge r2, r4 @ encoding: [0x62,0xb2]
+@ CHECK: sxtblt.w r5, r1, ror #16 @ encoding: [0x4f,0xfa,0xa1,0xf5]
+
+
+@------------------------------------------------------------------------------
+@ SXTB16
+@------------------------------------------------------------------------------
+ sxtb16 r1, r4
+ sxtb16 r6, r7, ror #0
+ sxtb16 r3, r1, ror #16
+ ite cs
+ sxtb16cs r3, r5, ror #8
+ sxtb16lo r2, r3, ror #24
+
+@ CHECK: sxtb16 r1, r4 @ encoding: [0x2f,0xfa,0x84,0xf1]
+@ CHECK: sxtb16 r6, r7 @ encoding: [0x2f,0xfa,0x87,0xf6]
+@ CHECK: sxtb16 r3, r1, ror #16 @ encoding: [0x2f,0xfa,0xa1,0xf3]
+@ CHECK: ite hs @ encoding: [0x2c,0xbf]
+@ CHECK: sxtb16hs r3, r5, ror #8 @ encoding: [0x2f,0xfa,0x95,0xf3]
+@ CHECK: sxtb16lo r2, r3, ror #24 @ encoding: [0x2f,0xfa,0xb3,0xf2]
+
+
+@------------------------------------------------------------------------------
+@ SXTH
+@------------------------------------------------------------------------------
+ sxth r1, r6, ror #0
+ sxth.w r3, r8, ror #8
+ sxth r9, r3, ror #24
+ itt ne
+ sxthne r3, r9
+ sxthne r2, r2, ror #16
+
+@ CHECK: sxth r1, r6 @ encoding: [0x31,0xb2]
+@ CHECK: sxth.w r3, r8, ror #8 @ encoding: [0x0f,0xfa,0x98,0xf3]
+@ CHECK: sxth.w r9, r3, ror #24 @ encoding: [0x0f,0xfa,0xb3,0xf9]
+@ CHECK: itt ne @ encoding: [0x1c,0xbf]
+@ CHECK: sxthne.w r3, r9 @ encoding: [0x0f,0xfa,0x89,0xf3]
+@ CHECK: sxthne.w r2, r2, ror #16 @ encoding: [0x0f,0xfa,0xa2,0xf2]
+
+
+@------------------------------------------------------------------------------
+@ TBB/TBH
+@------------------------------------------------------------------------------
+ tbb [r3, r8]
+ tbh [r3, r8, lsl #1]
+ it eq
+ tbbeq [r3, r8]
+ it cs
+ tbhcs [r3, r8, lsl #1]
+
+@ CHECK: tbb [r3, r8] @ encoding: [0xd3,0xe8,0x08,0xf0]
+@ CHECK: tbh [r3, r8, lsl #1] @ encoding: [0xd3,0xe8,0x18,0xf0]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: tbbeq [r3, r8] @ encoding: [0xd3,0xe8,0x08,0xf0]
+@ CHECK: it hs @ encoding: [0x28,0xbf]
+@ CHECK: tbhhs [r3, r8, lsl #1] @ encoding: [0xd3,0xe8,0x18,0xf0]
+
+
+@------------------------------------------------------------------------------
+@ TEQ
+@------------------------------------------------------------------------------
+ teq r5, #0xf000
+ teq r4, r5
+ teq r4, r5, lsl #5
+ teq r4, r5, lsr #5
+ teq r4, r5, lsr #5
+ teq r4, r5, asr #5
+ teq r4, r5, ror #5
+
+@ CHECK: teq.w r5, #61440 @ encoding: [0x95,0xf4,0x70,0x4f]
+@ CHECK: teq.w r4, r5 @ encoding: [0x94,0xea,0x05,0x0f]
+@ CHECK: teq.w r4, r5, lsl #5 @ encoding: [0x94,0xea,0x45,0x1f]
+@ CHECK: teq.w r4, r5, lsr #5 @ encoding: [0x94,0xea,0x55,0x1f]
+@ CHECK: teq.w r4, r5, lsr #5 @ encoding: [0x94,0xea,0x55,0x1f]
+@ CHECK: teq.w r4, r5, asr #5 @ encoding: [0x94,0xea,0x65,0x1f]
+@ CHECK: teq.w r4, r5, ror #5 @ encoding: [0x94,0xea,0x75,0x1f]
+
+
+@------------------------------------------------------------------------------
+@ TST
+@------------------------------------------------------------------------------
+ tst r5, #0xf000
+ tst r2, r5
+ tst r3, r12, lsl #5
+ tst r4, r11, lsr #4
+ tst r5, r10, lsr #12
+ tst r6, r9, asr #30
+ tst r7, r8, ror #2
+
+@ CHECK: tst.w r5, #61440 @ encoding: [0x15,0xf4,0x70,0x4f]
+@ CHECK: tst r2, r5 @ encoding: [0x2a,0x42]
+@ CHECK: tst.w r3, r12, lsl #5 @ encoding: [0x13,0xea,0x4c,0x1f]
+@ CHECK: tst.w r4, r11, lsr #4 @ encoding: [0x14,0xea,0x1b,0x1f]
+@ CHECK: tst.w r5, r10, lsr #12 @ encoding: [0x15,0xea,0x1a,0x3f]
+@ CHECK: tst.w r6, r9, asr #30 @ encoding: [0x16,0xea,0xa9,0x7f]
+@ CHECK: tst.w r7, r8, ror #2 @ encoding: [0x17,0xea,0xb8,0x0f]
+
+
+@------------------------------------------------------------------------------
+@ UADD16/UADD8
+@------------------------------------------------------------------------------
+ uadd16 r1, r2, r3
+ uadd8 r1, r2, r3
+ ite gt
+ uadd16gt r1, r2, r3
+ uadd8le r1, r2, r3
+
+@ CHECK: uadd16 r1, r2, r3 @ encoding: [0x92,0xfa,0x43,0xf1]
+@ CHECK: uadd8 r1, r2, r3 @ encoding: [0x82,0xfa,0x43,0xf1]
+@ CHECK: ite gt @ encoding: [0xcc,0xbf]
+@ CHECK: uadd16gt r1, r2, r3 @ encoding: [0x92,0xfa,0x43,0xf1]
+@ CHECK: uadd8le r1, r2, r3 @ encoding: [0x82,0xfa,0x43,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ UASX
+@------------------------------------------------------------------------------
+ uasx r9, r12, r0
+ it eq
+ uasxeq r9, r12, r0
+ uaddsubx r9, r12, r0
+ it eq
+ uaddsubxeq r9, r12, r0
+
+@ CHECK: uasx r9, r12, r0 @ encoding: [0xac,0xfa,0x40,0xf9]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: uasxeq r9, r12, r0 @ encoding: [0xac,0xfa,0x40,0xf9]
+@ CHECK: uasx r9, r12, r0 @ encoding: [0xac,0xfa,0x40,0xf9]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: uasxeq r9, r12, r0 @ encoding: [0xac,0xfa,0x40,0xf9]
+
+
+@------------------------------------------------------------------------------
+@ UBFX
+@------------------------------------------------------------------------------
+ ubfx r4, r5, #16, #1
+ it gt
+ ubfxgt r4, r5, #16, #16
+
+@ CHECK: ubfx r4, r5, #16, #1 @ encoding: [0xc5,0xf3,0x00,0x44]
+@ CHECK: it gt @ encoding: [0xc8,0xbf]
+@ CHECK: ubfxgt r4, r5, #16, #16 @ encoding: [0xc5,0xf3,0x0f,0x44]
+
+
+@------------------------------------------------------------------------------
+@ UHADD16/UHADD8
+@------------------------------------------------------------------------------
+ uhadd16 r4, r8, r2
+ uhadd8 r4, r8, r2
+ itt gt
+ uhadd16gt r4, r8, r2
+ uhadd8gt r4, r8, r2
+
+@ CHECK: uhadd16 r4, r8, r2 @ encoding: [0x98,0xfa,0x62,0xf4]
+@ CHECK: uhadd8 r4, r8, r2 @ encoding: [0x88,0xfa,0x62,0xf4]
+@ CHECK: itt gt @ encoding: [0xc4,0xbf]
+@ CHECK: uhadd16gt r4, r8, r2 @ encoding: [0x98,0xfa,0x62,0xf4]
+@ CHECK: uhadd8gt r4, r8, r2 @ encoding: [0x88,0xfa,0x62,0xf4]
+
+
+@------------------------------------------------------------------------------
+@ UHASX/UHSAX
+@------------------------------------------------------------------------------
+ uhasx r4, r1, r5
+ uhsax r5, r6, r6
+ itt gt
+ uhasxgt r6, r9, r8
+ uhsaxgt r7, r8, r12
+ uhaddsubx r4, r1, r5
+ uhsubaddx r5, r6, r6
+ itt gt
+ uhaddsubxgt r6, r9, r8
+ uhsubaddxgt r7, r8, r12
+
+@ CHECK: uhasx r4, r1, r5 @ encoding: [0xa1,0xfa,0x65,0xf4]
+@ CHECK: uhsax r5, r6, r6 @ encoding: [0xe6,0xfa,0x66,0xf5]
+@ CHECK: itt gt @ encoding: [0xc4,0xbf]
+@ CHECK: uhasxgt r6, r9, r8 @ encoding: [0xa9,0xfa,0x68,0xf6]
+@ CHECK: uhsaxgt r7, r8, r12 @ encoding: [0xe8,0xfa,0x6c,0xf7]
+@ CHECK: uhasx r4, r1, r5 @ encoding: [0xa1,0xfa,0x65,0xf4]
+@ CHECK: uhsax r5, r6, r6 @ encoding: [0xe6,0xfa,0x66,0xf5]
+@ CHECK: itt gt @ encoding: [0xc4,0xbf]
+@ CHECK: uhasxgt r6, r9, r8 @ encoding: [0xa9,0xfa,0x68,0xf6]
+@ CHECK: uhsaxgt r7, r8, r12 @ encoding: [0xe8,0xfa,0x6c,0xf7]
+
+
+@------------------------------------------------------------------------------
+@ UHSUB16/UHSUB8
+@------------------------------------------------------------------------------
+ uhsub16 r5, r8, r3
+ uhsub8 r1, r7, r6
+ itt lt
+ uhsub16lt r4, r9, r12
+ uhsub8lt r3, r1, r5
+
+@ CHECK: uhsub16 r5, r8, r3 @ encoding: [0xd8,0xfa,0x63,0xf5]
+@ CHECK: uhsub8 r1, r7, r6 @ encoding: [0xc7,0xfa,0x66,0xf1]
+@ CHECK: itt lt @ encoding: [0xbc,0xbf]
+@ CHECK: uhsub16lt r4, r9, r12 @ encoding: [0xd9,0xfa,0x6c,0xf4]
+@ CHECK: uhsub8lt r3, r1, r5 @ encoding: [0xc1,0xfa,0x65,0xf3]
+
+
+@------------------------------------------------------------------------------
+@ UMAAL
+@------------------------------------------------------------------------------
+ umaal r3, r4, r5, r6
+ it lt
+ umaallt r3, r4, r5, r6
+
+@ CHECK: umaal r3, r4, r5, r6 @ encoding: [0xe5,0xfb,0x66,0x34]
+@ CHECK: it lt @ encoding: [0xb8,0xbf]
+@ CHECK: umaallt r3, r4, r5, r6 @ encoding: [0xe5,0xfb,0x66,0x34]
+
+
+@------------------------------------------------------------------------------
+@ UMLAL
+@------------------------------------------------------------------------------
+ umlal r2, r4, r6, r8
+ it gt
+ umlalgt r6, r1, r2, r6
+
+@ CHECK: umlal r2, r4, r6, r8 @ encoding: [0xe6,0xfb,0x08,0x24]
+@ CHECK: it gt @ encoding: [0xc8,0xbf]
+@ CHECK: umlalgt r6, r1, r2, r6 @ encoding: [0xe2,0xfb,0x06,0x61]
+
+
+@------------------------------------------------------------------------------
+@ UMULL
+@------------------------------------------------------------------------------
+ umull r2, r4, r6, r8
+ it gt
+ umullgt r6, r1, r2, r6
+
+@ CHECK: umull r2, r4, r6, r8 @ encoding: [0xa6,0xfb,0x08,0x24]
+@ CHECK: it gt @ encoding: [0xc8,0xbf]
+@ CHECK: umullgt r6, r1, r2, r6 @ encoding: [0xa2,0xfb,0x06,0x61]
+
+
+@------------------------------------------------------------------------------
+@ UQADD16/UQADD8
+@------------------------------------------------------------------------------
+ uqadd16 r1, r2, r3
+ uqadd8 r3, r4, r8
+ ite gt
+ uqadd16gt r4, r7, r9
+ uqadd8le r8, r1, r2
+
+@ CHECK: uqadd16 r1, r2, r3 @ encoding: [0x92,0xfa,0x53,0xf1]
+@ CHECK: uqadd8 r3, r4, r8 @ encoding: [0x84,0xfa,0x58,0xf3]
+@ CHECK: ite gt @ encoding: [0xcc,0xbf]
+@ CHECK: uqadd16gt r4, r7, r9 @ encoding: [0x97,0xfa,0x59,0xf4]
+@ CHECK: uqadd8le r8, r1, r2 @ encoding: [0x81,0xfa,0x52,0xf8]
+
+
+@------------------------------------------------------------------------------
+@ UQASX/UQSAX
+@------------------------------------------------------------------------------
+ uqasx r1, r2, r3
+ uqsax r3, r4, r8
+ ite gt
+ uqasxgt r4, r7, r9
+ uqsaxle r8, r1, r2
+
+ uqaddsubx r1, r2, r3
+ uqsubaddx r3, r4, r8
+ ite gt
+ uqaddsubxgt r4, r7, r9
+ uqsubaddxle r8, r1, r2
+
+@ CHECK: uqasx r1, r2, r3 @ encoding: [0xa2,0xfa,0x53,0xf1]
+@ CHECK: uqsax r3, r4, r8 @ encoding: [0xe4,0xfa,0x58,0xf3]
+@ CHECK: ite gt @ encoding: [0xcc,0xbf]
+@ CHECK: uqasxgt r4, r7, r9 @ encoding: [0xa7,0xfa,0x59,0xf4]
+@ CHECK: uqsaxle r8, r1, r2 @ encoding: [0xe1,0xfa,0x52,0xf8]
+
+@ CHECK: uqasx r1, r2, r3 @ encoding: [0xa2,0xfa,0x53,0xf1]
+@ CHECK: uqsax r3, r4, r8 @ encoding: [0xe4,0xfa,0x58,0xf3]
+@ CHECK: ite gt @ encoding: [0xcc,0xbf]
+@ CHECK: uqasxgt r4, r7, r9 @ encoding: [0xa7,0xfa,0x59,0xf4]
+@ CHECK: uqsaxle r8, r1, r2 @ encoding: [0xe1,0xfa,0x52,0xf8]
+
+
+@------------------------------------------------------------------------------
+@ UQSUB16/UQSUB8
+@------------------------------------------------------------------------------
+ uqsub8 r8, r2, r9
+ uqsub16 r1, r9, r7
+ ite gt
+ uqsub8gt r3, r1, r6
+ uqsub16le r4, r6, r4
+
+@ CHECK: uqsub8 r8, r2, r9 @ encoding: [0xc2,0xfa,0x59,0xf8]
+@ CHECK: uqsub16 r1, r9, r7 @ encoding: [0xd9,0xfa,0x57,0xf1]
+@ CHECK: ite gt @ encoding: [0xcc,0xbf]
+@ CHECK: uqsub8gt r3, r1, r6 @ encoding: [0xc1,0xfa,0x56,0xf3]
+@ CHECK: uqsub16le r4, r6, r4 @ encoding: [0xd6,0xfa,0x54,0xf4]
+
+
+@------------------------------------------------------------------------------
+@ UQSUB16/UQSUB8
+@------------------------------------------------------------------------------
+ usad8 r1, r9, r7
+ usada8 r8, r2, r9, r12
+ ite gt
+ usada8gt r3, r1, r6, r9
+ usad8le r4, r6, r4
+
+@ CHECK: usad8 r1, r9, r7 @ encoding: [0x79,0xfb,0x07,0xf1]
+@ CHECK: usada8 r8, r2, r9, r12 @ encoding: [0x72,0xfb,0x09,0xc8]
+@ CHECK: ite gt @ encoding: [0xcc,0xbf]
+@ CHECK: usada8gt r3, r1, r6, r9 @ encoding: [0x71,0xfb,0x06,0x93]
+@ CHECK: usad8le r4, r6, r4 @ encoding: [0x76,0xfb,0x04,0xf4]
+
+
+@------------------------------------------------------------------------------
+@ USAT
+@------------------------------------------------------------------------------
+ usat r8, #1, r10
+ usat r8, #4, r10, lsl #0
+ usat r8, #5, r10, lsl #31
+ usat r8, #16, r10, asr #1
+
+@ CHECK: usat r8, #1, r10 @ encoding: [0x8a,0xf3,0x01,0x08]
+@ CHECK: usat r8, #4, r10 @ encoding: [0x8a,0xf3,0x04,0x08]
+@ CHECK: usat r8, #5, r10, lsl #31 @ encoding: [0x8a,0xf3,0xc5,0x78]
+@ CHECK: usat r8, #16, r10, asr #1 @ encoding: [0xaa,0xf3,0x50,0x08]
+
+
+@------------------------------------------------------------------------------
+@ USAT16
+@------------------------------------------------------------------------------
+ usat16 r2, #2, r7
+ usat16 r3, #15, r5
+
+@ CHECK: usat16 r2, #2, r7 @ encoding: [0xa7,0xf3,0x02,0x02]
+@ CHECK: usat16 r3, #15, r5 @ encoding: [0xa5,0xf3,0x0f,0x03]
+
+
+@------------------------------------------------------------------------------
+@ USAX
+@------------------------------------------------------------------------------
+ usax r2, r3, r4
+ it ne
+ usaxne r6, r1, r9
+ usubaddx r2, r3, r4
+ it ne
+ usubaddxne r6, r1, r9
+
+@ CHECK: usax r2, r3, r4 @ encoding: [0xe3,0xfa,0x44,0xf2]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: usaxne r6, r1, r9 @ encoding: [0xe1,0xfa,0x49,0xf6]
+@ CHECK: usax r2, r3, r4 @ encoding: [0xe3,0xfa,0x44,0xf2]
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: usaxne r6, r1, r9 @ encoding: [0xe1,0xfa,0x49,0xf6]
+
+
+@------------------------------------------------------------------------------
+@ USUB16/USUB8
+@------------------------------------------------------------------------------
+ usub16 r4, r2, r7
+ usub8 r1, r8, r5
+ ite hi
+ usub16hi r1, r1, r3
+ usub8ls r9, r2, r3
+
+@ CHECK: usub16 r4, r2, r7 @ encoding: [0xd2,0xfa,0x47,0xf4]
+@ CHECK: usub8 r1, r8, r5 @ encoding: [0xc8,0xfa,0x45,0xf1]
+@ CHECK: ite hi @ encoding: [0x8c,0xbf]
+@ CHECK: usub16hi r1, r1, r3 @ encoding: [0xd1,0xfa,0x43,0xf1]
+@ CHECK: usub8ls r9, r2, r3 @ encoding: [0xc2,0xfa,0x43,0xf9]
+
+
+@------------------------------------------------------------------------------
+@ UXTAB
+@------------------------------------------------------------------------------
+ uxtab r2, r3, r4
+ uxtab r4, r5, r6, ror #0
+ it lt
+ uxtablt r6, r2, r9, ror #8
+ uxtab r5, r1, r4, ror #16
+ uxtab r7, r8, r3, ror #24
+
+@ CHECK: uxtab r2, r3, r4 @ encoding: [0x53,0xfa,0x84,0xf2]
+@ CHECK: uxtab r4, r5, r6 @ encoding: [0x55,0xfa,0x86,0xf4]
+@ CHECK: it lt @ encoding: [0xb8,0xbf]
+@ CHECK: uxtablt r6, r2, r9, ror #8 @ encoding: [0x52,0xfa,0x99,0xf6]
+@ CHECK: uxtab r5, r1, r4, ror #16 @ encoding: [0x51,0xfa,0xa4,0xf5]
+@ CHECK: uxtab r7, r8, r3, ror #24 @ encoding: [0x58,0xfa,0xb3,0xf7]
+
+
+@------------------------------------------------------------------------------
+@ UXTAB16
+@------------------------------------------------------------------------------
+ it ge
+ uxtab16ge r0, r1, r4
+ uxtab16 r6, r2, r7, ror #0
+ uxtab16 r3, r5, r8, ror #8
+ uxtab16 r3, r2, r1, ror #16
+ it eq
+ uxtab16eq r1, r2, r3, ror #24
+
+@ CHECK: it ge @ encoding: [0xa8,0xbf]
+@ CHECK: uxtab16ge r0, r1, r4 @ encoding: [0x31,0xfa,0x84,0xf0]
+@ CHECK: uxtab16 r6, r2, r7 @ encoding: [0x32,0xfa,0x87,0xf6]
+@ CHECK: uxtab16 r3, r5, r8, ror #8 @ encoding: [0x35,0xfa,0x98,0xf3]
+@ CHECK: uxtab16 r3, r2, r1, ror #16 @ encoding: [0x32,0xfa,0xa1,0xf3]
+@ CHECK: it eq @ encoding: [0x08,0xbf]
+@ CHECK: uxtab16eq r1, r2, r3, ror #24 @ encoding: [0x32,0xfa,0xb3,0xf1]
+
+
+@------------------------------------------------------------------------------
+@ UXTAH
+@------------------------------------------------------------------------------
+ uxtah r1, r3, r9
+ it hi
+ uxtahhi r6, r1, r6, ror #0
+ uxtah r3, r8, r3, ror #8
+ it lo
+ uxtahlo r2, r2, r4, ror #16
+ uxtah r9, r3, r3, ror #24
+
+@ CHECK: uxtah r1, r3, r9 @ encoding: [0x13,0xfa,0x89,0xf1]
+@ CHECK: it hi @ encoding: [0x88,0xbf]
+@ CHECK: uxtahhi r6, r1, r6 @ encoding: [0x11,0xfa,0x86,0xf6]
+@ CHECK: uxtah r3, r8, r3, ror #8 @ encoding: [0x18,0xfa,0x93,0xf3]
+@ CHECK: it lo @ encoding: [0x38,0xbf]
+@ CHECK: uxtahlo r2, r2, r4, ror #16 @ encoding: [0x12,0xfa,0xa4,0xf2]
+@ CHECK: uxtah r9, r3, r3, ror #24 @ encoding: [0x13,0xfa,0xb3,0xf9]
+
+
+@------------------------------------------------------------------------------
+@ UXTB
+@------------------------------------------------------------------------------
+ it ge
+ uxtbge r2, r4
+ uxtb r5, r6, ror #0
+ uxtb r6, r9, ror #8
+ it cc
+ uxtbcc r5, r1, ror #16
+ uxtb r8, r3, ror #24
+ uxtb.w r7, r8
+
+@ CHECK: it ge @ encoding: [0xa8,0xbf]
+@ CHECK: uxtbge r2, r4 @ encoding: [0xe2,0xb2]
+@ CHECK: uxtb r5, r6 @ encoding: [0xf5,0xb2]
+@ CHECK: uxtb.w r6, r9, ror #8 @ encoding: [0x5f,0xfa,0x99,0xf6]
+@ CHECK: it lo @ encoding: [0x38,0xbf]
+@ CHECK: uxtblo.w r5, r1, ror #16 @ encoding: [0x5f,0xfa,0xa1,0xf5]
+@ CHECK: uxtb.w r8, r3, ror #24 @ encoding: [0x5f,0xfa,0xb3,0xf8]
+@ CHECK: uxtb.w r7, r8 @ encoding: [0x5f,0xfa,0x88,0xf7]
+
+
+@------------------------------------------------------------------------------
+@ UXTB16
+@------------------------------------------------------------------------------
+ uxtb16 r1, r4
+ uxtb16 r6, r7, ror #0
+ it cs
+ uxtb16cs r3, r5, ror #8
+ uxtb16 r3, r1, ror #16
+ it ge
+ uxtb16ge r2, r3, ror #24
+
+@ CHECK: uxtb16 r1, r4 @ encoding: [0x3f,0xfa,0x84,0xf1]
+@ CHECK: uxtb16 r6, r7 @ encoding: [0x3f,0xfa,0x87,0xf6]
+@ CHECK: it hs @ encoding: [0x28,0xbf]
+@ CHECK: uxtb16hs r3, r5, ror #8 @ encoding: [0x3f,0xfa,0x95,0xf3]
+@ CHECK: uxtb16 r3, r1, ror #16 @ encoding: [0x3f,0xfa,0xa1,0xf3]
+@ CHECK: it ge @ encoding: [0xa8,0xbf]
+@ CHECK: uxtb16ge r2, r3, ror #24 @ encoding: [0x3f,0xfa,0xb3,0xf2]
+
+
+@------------------------------------------------------------------------------
+@ UXTH
+@------------------------------------------------------------------------------
+ it ne
+ uxthne r3, r9
+ uxth r1, r6, ror #0
+ uxth r3, r8, ror #8
+ it le
+ uxthle r2, r2, ror #16
+ uxth r9, r3, ror #24
+ uxth.w r7, r8
+
+@ CHECK: it ne @ encoding: [0x18,0xbf]
+@ CHECK: uxthne.w r3, r9 @ encoding: [0x1f,0xfa,0x89,0xf3]
+@ CHECK: uxth r1, r6 @ encoding: [0xb1,0xb2]
+@ CHECK: uxth.w r3, r8, ror #8 @ encoding: [0x1f,0xfa,0x98,0xf3]
+@ CHECK: it le @ encoding: [0xd8,0xbf]
+@ CHECK: uxthle.w r2, r2, ror #16 @ encoding: [0x1f,0xfa,0xa2,0xf2]
+@ CHECK: uxth.w r9, r3, ror #24 @ encoding: [0x1f,0xfa,0xb3,0xf9]
+@ CHECK: uxth.w r7, r8 @ encoding: [0x1f,0xfa,0x88,0xf7]
+
+@------------------------------------------------------------------------------
+@ WFE/WFI/YIELD
+@------------------------------------------------------------------------------
+ wfe
+ wfi
+ yield
+ itet lt
+ wfelt
+ wfige
+ yieldlt
+
+@ CHECK: wfe @ encoding: [0x20,0xbf]
+@ CHECK: wfi @ encoding: [0x30,0xbf]
+@ CHECK: yield @ encoding: [0x10,0xbf]
+@ CHECK: itet lt @ encoding: [0xb6,0xbf]
+@ CHECK: wfelt @ encoding: [0x20,0xbf]
+@ CHECK: wfige @ encoding: [0x30,0xbf]
+@ CHECK: yieldlt @ encoding: [0x10,0xbf]
diff --git a/test/MC/ARM/diagnostics.s b/test/MC/ARM/diagnostics.s
index 4537a0f..f722dd7 100644
--- a/test/MC/ARM/diagnostics.s
+++ b/test/MC/ARM/diagnostics.s
@@ -88,3 +88,230 @@
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: error: invalid operand for instruction
+
+
+ @ Out of range immediate for MOV
+ movw r9, 0x10000
+@ CHECK-ERRORS: error: invalid operand for instruction
+
+ @ Invalid 's' bit usage for MOVW
+ movs r6, #0xffff
+ movwseq r9, #0xffff
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: instruction 'movw' can not set flags, but 's' suffix specified
+
+ @ Out of range immediate for MOVT
+ movt r9, 0x10000
+@ CHECK-ERRORS: error: invalid operand for instruction
+
+ @ Out of range immediates for MRC/MRC2/MRRC/MRRC2
+ mrc p14, #8, r1, c1, c2, #4
+ mrc p14, #1, r1, c1, c2, #8
+ mrc2 p14, #8, r1, c1, c2, #4
+ mrc2 p14, #0, r1, c1, c2, #9
+ mrrc p7, #16, r5, r4, c1
+ mrrc2 p7, #17, r5, r4, c1
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: invalid operand for instruction
+
+ @ Shifter operand validation for PKH instructions.
+ pkhbt r2, r2, r3, lsl #-1
+ pkhbt r2, r2, r3, lsl #32
+ pkhtb r2, r2, r3, asr #0
+ pkhtb r2, r2, r3, asr #33
+ pkhbt r2, r2, r3, asr #3
+ pkhtb r2, r2, r3, lsl #3
+
+@ CHECK-ERRORS: error: immediate value out of range
+@ CHECK-ERRORS: pkhbt r2, r2, r3, lsl #-1
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: immediate value out of range
+@ CHECK-ERRORS: pkhbt r2, r2, r3, lsl #32
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: immediate value out of range
+@ CHECK-ERRORS: pkhtb r2, r2, r3, asr #0
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: immediate value out of range
+@ CHECK-ERRORS: pkhtb r2, r2, r3, asr #33
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: lsl operand expected.
+@ CHECK-ERRORS: pkhbt r2, r2, r3, asr #3
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: asr operand expected.
+@ CHECK-ERRORS: pkhtb r2, r2, r3, lsl #3
+@ CHECK-ERRORS: ^
+
+
+ @ bad values for SETEND
+ setendne be
+ setend me
+ setend 1
+
+@ CHECK-ERRORS: error: instruction 'setend' is not predicable, but condition code specified
+@ CHECK-ERRORS: setendne be
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'be' or 'le' operand expected
+@ CHECK-ERRORS: setend me
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'be' or 'le' operand expected
+@ CHECK-ERRORS: setend 1
+@ CHECK-ERRORS: ^
+
+
+ @ Out of range immediates and bad shift types for SSAT
+ ssat r8, #0, r10, lsl #8
+ ssat r8, #33, r10, lsl #8
+ ssat r8, #1, r10, lsl #-1
+ ssat r8, #1, r10, lsl #32
+ ssat r8, #1, r10, asr #0
+ ssat r8, #1, r10, asr #33
+ ssat r8, #1, r10, lsr #5
+ ssat r8, #1, r10, lsl fred
+ ssat r8, #1, r10, lsl #fred
+
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: ssat r8, #0, r10, lsl #8
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: ssat r8, #33, r10, lsl #8
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'lsr' shift amount must be in range [0,31]
+@ CHECK-ERRORS: ssat r8, #1, r10, lsl #-1
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'lsr' shift amount must be in range [0,31]
+@ CHECK-ERRORS: ssat r8, #1, r10, lsl #32
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'asr' shift amount must be in range [1,32]
+@ CHECK-ERRORS: ssat r8, #1, r10, asr #0
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'asr' shift amount must be in range [1,32]
+@ CHECK-ERRORS: ssat r8, #1, r10, asr #33
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: shift operator 'asr' or 'lsl' expected
+@ CHECK-ERRORS: ssat r8, #1, r10, lsr #5
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: '#' expected
+@ CHECK-ERRORS: ssat r8, #1, r10, lsl fred
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: shift amount must be an immediate
+@ CHECK-ERRORS: ssat r8, #1, r10, lsl #fred
+@ CHECK-ERRORS: ^
+
+ @ Out of range immediates for SSAT16
+ ssat16 r2, #0, r7
+ ssat16 r3, #17, r5
+
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: ssat16 r2, #0, r7
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: ssat16 r3, #17, r5
+@ CHECK-ERRORS: ^
+
+
+ @ Out of order STM registers
+ stmda sp!, {r5, r2}
+
+@ CHECK-ERRORS: error: register list not in ascending order
+@ CHECK-ERRORS: stmda sp!, {r5, r2}
+@ CHECK-ERRORS: ^
+
+
+ @ Out of range immediate on SVC
+ svc #0x1000000
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: svc #0x1000000
+@ CHECK-ERRORS: ^
+
+
+ @ Out of order Rt/Rt2 operands for ldrexd/strexd
+ ldrexd r4, r3, [r8]
+ strexd r6, r5, r3, [r8]
+
+@ CHECK-ERRORS: error: destination operands must be sequential
+@ CHECK-ERRORS: ldrexd r4, r3, [r8]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: source operands must be sequential
+@ CHECK-ERRORS: strexd r6, r5, r3, [r8]
+@ CHECK-ERRORS: ^
+
+ @ Illegal rotate operators for extend instructions
+ sxtb r8, r3, #8
+ sxtb r8, r3, ror 24
+ sxtb r8, r3, ror #8 -
+ sxtab r3, r8, r3, ror #(fred - wilma)
+ sxtab r7, r8, r3, ror #25
+ sxtah r9, r3, r3, ror #-8
+ sxtb16ge r2, r3, lsr #24
+
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: sxtb r8, r3, #8
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: '#' expected
+@ CHECK-ERRORS: sxtb r8, r3, ror 24
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: unknown token in expression
+@ CHECK-ERRORS: sxtb r8, r3, ror #8 -
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: malformed rotate expression
+@ CHECK-ERRORS: sxtb r8, r3, ror #8 -
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: rotate amount must be an immediate
+@ CHECK-ERRORS: sxtab r3, r8, r3, ror #(fred - wilma)
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'ror' rotate amount must be 8, 16, or 24
+@ CHECK-ERRORS: sxtab r7, r8, r3, ror #25
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: 'ror' rotate amount must be 8, 16, or 24
+@ CHECK-ERRORS: sxtah r9, r3, r3, ror #-8
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: sxtb16ge r2, r3, lsr #24
+@ CHECK-ERRORS: ^
+
+ @ Out of range width for SBFX/UBFX
+ sbfx r4, r5, #31, #2
+ ubfxgt r4, r5, #16, #17
+
+@ CHECK-ERRORS: error: bitfield width must be in range [1,32-lsb]
+@ CHECK-ERRORS: sbfx r4, r5, #31, #2
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: bitfield width must be in range [1,32-lsb]
+@ CHECK-ERRORS: ubfxgt r4, r5, #16, #17
+@ CHECK-ERRORS: ^
+
+ @ Out of order Rt/Rt2 operands for ldrd
+ ldrd r4, r3, [r8]
+ ldrd r4, r3, [r8, #8]!
+ ldrd r4, r3, [r8], #8
+@ CHECK-ERRORS: error: destination operands must be sequential
+@ CHECK-ERRORS: ldrd r4, r3, [r8]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: destination operands must be sequential
+@ CHECK-ERRORS: ldrd r4, r3, [r8, #8]!
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: destination operands must be sequential
+@ CHECK-ERRORS: ldrd r4, r3, [r8], #8
+@ CHECK-ERRORS: ^
+
+
+ @ Bad register lists for VFP.
+ vpush {s0, s3}
+@ CHECK-ERRORS: error: non-contiguous register range
+@ CHECK-ERRORS: vpush {s0, s3}
+@ CHECK-ERRORS: ^
+
+ @ Out of range coprocessor option immediate.
+ ldc2 p2, c8, [r1], { 256 }
+ ldc2 p2, c8, [r1], { -1 }
+
+@ CHECK-ERRORS: error: coprocessor option must be an immediate in range [0, 255]
+@ CHECK-ERRORS: ldc2 p2, c8, [r1], { 256 }
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: coprocessor option must be an immediate in range [0, 255]
+@ CHECK-ERRORS: ldc2 p2, c8, [r1], { -1 }
+@ CHECK-ERRORS: ^
diff --git a/test/MC/ARM/elf-movt.s b/test/MC/ARM/elf-movt.s
index 18061f5..02bb5a6 100644
--- a/test/MC/ARM/elf-movt.s
+++ b/test/MC/ARM/elf-movt.s
@@ -27,13 +27,13 @@ barf: @ @barf
@ OBJ-NEXT: 'sh_entsize', 0x00000000
@ OBJ-NEXT: '_section_data', 'f00f0fe3 f40f4fe3'
-@ OBJ: Relocation 0x00000000
+@ OBJ: Relocation 0
@ OBJ-NEXT: 'r_offset', 0x00000000
@ OBJ-NEXT: 'r_sym'
-@ OBJ-NEXT: 'r_type', 0x0000002d
+@ OBJ-NEXT: 'r_type', 0x2d
-@ OBJ: Relocation 0x00000001
+@ OBJ: Relocation 1
@ OBJ-NEXT: 'r_offset', 0x00000004
@ OBJ-NEXT: 'r_sym'
-@ OBJ-NEXT: 'r_type', 0x0000002e
+@ OBJ-NEXT: 'r_type', 0x2e
diff --git a/test/MC/ARM/elf-reloc-01.ll b/test/MC/ARM/elf-reloc-01.ll
index eb6e243..e6efe7e 100644
--- a/test/MC/ARM/elf-reloc-01.ll
+++ b/test/MC/ARM/elf-reloc-01.ll
@@ -60,11 +60,11 @@ bb3: ; preds = %bb, %entry
declare void @exit(i32) noreturn nounwind
-;; OBJ: Relocation 0x00000001
+;; OBJ: Relocation 1
;; OBJ-NEXT: 'r_offset',
-;; OBJ-NEXT: 'r_sym', 0x00000002
-;; OBJ-NEXT: 'r_type', 0x0000002b
+;; OBJ-NEXT: 'r_sym', 0x000002
+;; OBJ-NEXT: 'r_type', 0x2b
-;; OBJ: Symbol 0x00000002
+;; OBJ: Symbol 2
;; OBJ-NEXT: '_MergedGlobals'
;; OBJ-NEXT: 'st_value', 0x00000010
diff --git a/test/MC/ARM/elf-reloc-02.ll b/test/MC/ARM/elf-reloc-02.ll
index 091e89f..e51bac3 100644
--- a/test/MC/ARM/elf-reloc-02.ll
+++ b/test/MC/ARM/elf-reloc-02.ll
@@ -41,10 +41,10 @@ declare i32 @write(...)
declare void @exit(i32) noreturn nounwind
-;; OBJ: Relocation 0x00000000
+;; OBJ: Relocation 0
;; OBJ-NEXT: 'r_offset',
-;; OBJ-NEXT: 'r_sym', 0x00000002
-;; OBJ-NEXT: 'r_type', 0x0000002b
+;; OBJ-NEXT: 'r_sym', 0x000002
+;; OBJ-NEXT: 'r_type', 0x2b
-;; OBJ: Symbol 0x00000002
+;; OBJ: Symbol 2
;; OBJ-NEXT: '.L.str'
diff --git a/test/MC/ARM/elf-reloc-03.ll b/test/MC/ARM/elf-reloc-03.ll
index 91dba55..922242f 100644
--- a/test/MC/ARM/elf-reloc-03.ll
+++ b/test/MC/ARM/elf-reloc-03.ll
@@ -88,10 +88,10 @@ entry:
declare void @exit(i32) noreturn nounwind
-;; OBJ: Relocation 0x00000001
+;; OBJ: Relocation 1
;; OBJ-NEXT: 'r_offset',
-;; OBJ-NEXT: 'r_sym', 0x0000000c
-;; OBJ-NEXT: 'r_type', 0x0000002b
+;; OBJ-NEXT: 'r_sym', 0x00000c
+;; OBJ-NEXT: 'r_type', 0x2b
-;; OBJ: Symbol 0x0000000c
+;; OBJ: Symbol 12
;; OBJ-NEXT: 'vtable'
diff --git a/test/MC/ARM/elf-thumbfunc-reloc.ll b/test/MC/ARM/elf-thumbfunc-reloc.ll
index 6fce4038..e7cb01e 100644
--- a/test/MC/ARM/elf-thumbfunc-reloc.ll
+++ b/test/MC/ARM/elf-thumbfunc-reloc.ll
@@ -22,16 +22,16 @@ entry:
; make sure that bl 0 <foo> (fff7feff) is correctly encoded
-; CHECK: '_section_data', '70470000 2de90048 fff7feff bde80088'
+; CHECK: '_section_data', '704700bf 2de90048 fff7feff bde80008'
; Offset Info Type Sym.Value Sym. Name
; 00000008 0000070a R_ARM_THM_CALL 00000001 foo
-; CHECK: Relocation 0x00000000
+; CHECK: Relocation 0
; CHECK-NEXT: 'r_offset', 0x00000008
-; CHECK-NEXT: 'r_sym', 0x00000007
-; CHECK-NEXT: 'r_type', 0x0000000a
+; CHECK-NEXT: 'r_sym', 0x000007
+; CHECK-NEXT: 'r_type', 0x0a
; make sure foo is thumb function: bit 0 = 1
-; CHECK: Symbol 0x00000007
+; CHECK: Symbol 7
; CHECK-NEXT: 'foo'
; CHECK-NEXT: 'st_value', 0x00000001
diff --git a/test/MC/ARM/elf-thumbfunc.s b/test/MC/ARM/elf-thumbfunc.s
index a1b3c31..0aa7f41 100644
--- a/test/MC/ARM/elf-thumbfunc.s
+++ b/test/MC/ARM/elf-thumbfunc.s
@@ -12,9 +12,9 @@ foo:
bx lr
@@ make sure foo is thumb function: bit 0 = 1 (st_value)
-@CHECK: Symbol 0x00000004
+@CHECK: Symbol 4
@CHECK-NEXT: 'st_name', 0x00000001
@CHECK-NEXT: 'st_value', 0x00000001
@CHECK-NEXT: 'st_size', 0x00000000
-@CHECK-NEXT: 'st_bind', 0x00000001
-@CHECK-NEXT: 'st_type', 0x00000002
+@CHECK-NEXT: 'st_bind', 0x1
+@CHECK-NEXT: 'st_type', 0x2
diff --git a/test/MC/ARM/mode-switch.s b/test/MC/ARM/mode-switch.s
index 4cc986a..9d49954 100644
--- a/test/MC/ARM/mode-switch.s
+++ b/test/MC/ARM/mode-switch.s
@@ -1,17 +1,15 @@
@ Test ARM / Thumb mode switching with .code
-@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding < %s | FileCheck %s
-@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s
+@ RUN: llvm-mc -triple armv7-unknown-unknown -show-encoding < %s | FileCheck %s
+@ RUN: llvm-mc -triple thumbv7-unknown-unknown -show-encoding <%s | FileCheck %s
.code 16
-
-@ CHECK: add.w r0, r0, r1 @ encoding: [0x00,0xeb,0x01,0x00]
add.w r0, r0, r1
+@ CHECK: add.w r0, r0, r1 @ encoding: [0x00,0xeb,0x01,0x00]
.code 32
-@ CHECK: add r0, r0, r1 @ encoding: [0x01,0x00,0x80,0xe0]
add r0, r0, r1
+@ CHECK: add r0, r0, r1 @ encoding: [0x01,0x00,0x80,0xe0]
.code 16
-@ CHECK: add r0, r0, r1 @ encoding: [0x40,0x18]
-
- add r0, r0, r1
+ adds r0, r0, r1
+@ CHECK: adds r0, r0, r1 @ encoding: [0x40,0x18]
diff --git a/test/MC/ARM/neon-bitwise-encoding.s b/test/MC/ARM/neon-bitwise-encoding.s
index 8710923..81e2c4d 100644
--- a/test/MC/ARM/neon-bitwise-encoding.s
+++ b/test/MC/ARM/neon-bitwise-encoding.s
@@ -1,47 +1,55 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding < %s | FileCheck %s
-@ XFAIL: *
-@ CHECK: vand d16, d17, d16 @ encoding: [0xb0,0x01,0x41,0xf2]
vand d16, d17, d16
-@ CHECK: vand q8, q8, q9 @ encoding: [0xf2,0x01,0x40,0xf2]
vand q8, q8, q9
-@ CHECK: veor d16, d17, d16 @ encoding: [0xb0,0x01,0x41,0xf3]
+@ CHECK: vand d16, d17, d16 @ encoding: [0xb0,0x01,0x41,0xf2]
+@ CHECK: vand q8, q8, q9 @ encoding: [0xf2,0x01,0x40,0xf2]
+
veor d16, d17, d16
-@ CHECK: veor q8, q8, q9 @ encoding: [0xf2,0x01,0x40,0xf3]
veor q8, q8, q9
-@ CHECK: vorr d16, d17, d16 @ encoding: [0xb0,0x01,0x61,0xf2]
+@ CHECK: veor d16, d17, d16 @ encoding: [0xb0,0x01,0x41,0xf3]
+@ CHECK: veor q8, q8, q9 @ encoding: [0xf2,0x01,0x40,0xf3]
+
vorr d16, d17, d16
-@ CHECK: vorr q8, q8, q9 @ encoding: [0xf2,0x01,0x60,0xf2]
vorr q8, q8, q9
-@ CHECK: vorr.i32 d16, #0x1000000 @ encoding: [0x11,0x07,0xc0,0xf2]
- vorr.i32 d16, #0x1000000
-@ CHECK: vorr.i32 q8, #0x1000000 @ encoding: [0x51,0x07,0xc0,0xf2]
- vorr.i32 q8, #0x1000000
-@ CHECK: vorr.i32 q8, #0x0 @ encoding: [0x50,0x01,0xc0,0xf2]
- vorr.i32 q8, #0x0
-@ CHECK: vbic d16, d17, d16 @ encoding: [0xb0,0x01,0x51,0xf2]
+@ CHECK: vorr d16, d17, d16 @ encoding: [0xb0,0x01,0x61,0xf2]
+@ CHECK: vorr q8, q8, q9 @ encoding: [0xf2,0x01,0x60,0xf2]
+
+ vorr.i32 d16, #0x1000000
+ vorr.i32 q8, #0x1000000
+ vorr.i32 q8, #0x0
+
+@ FIXME: vorr.i32 d16, #0x1000000 @ encoding: [0x11,0x07,0xc0,0xf2]
+@ FIXME: vorr.i32 q8, #0x1000000 @ encoding: [0x51,0x07,0xc0,0xf2]
+@ FIXME: vorr.i32 q8, #0x0 @ encoding: [0x50,0x01,0xc0,0xf2]
+
vbic d16, d17, d16
-@ CHECK: vbic q8, q8, q9 @ encoding: [0xf2,0x01,0x50,0xf2]
vbic q8, q8, q9
-@ CHECK: vbic.i32 d16, #0xFF000000 @ encoding: [0x3f,0x07,0xc7,0xf3]
- vbic.i32 d16, #0xFF000000
-@ CHECK: vbic.i32 q8, #0xFF000000 @ encoding: [0x7f,0x07,0xc7,0xf3]
- vbic.i32 q8, #0xFF000000
+ vbic.i32 d16, #0xFF000000
+ vbic.i32 q8, #0xFF000000
+
+@ CHECK: vbic d16, d17, d16 @ encoding: [0xb0,0x01,0x51,0xf2]
+@ CHECK: vbic q8, q8, q9 @ encoding: [0xf2,0x01,0x50,0xf2]
+@ FIXME: vbic.i32 d16, #0xFF000000 @ encoding: [0x3f,0x07,0xc7,0xf3]
+@ FIXME: vbic.i32 q8, #0xFF000000 @ encoding: [0x7f,0x07,0xc7,0xf3]
-@ CHECK: vorn d16, d17, d16 @ encoding: [0xb0,0x01,0x71,0xf2]
vorn d16, d17, d16
-@ CHECK: vorn q8, q8, q9 @ encoding: [0xf2,0x01,0x70,0xf2]
vorn q8, q8, q9
-@ CHECK: vmvn d16, d16 @ encoding: [0xa0,0x05,0xf0,0xf3]
+@ CHECK: vorn d16, d17, d16 @ encoding: [0xb0,0x01,0x71,0xf2]
+@ CHECK: vorn q8, q8, q9 @ encoding: [0xf2,0x01,0x70,0xf2]
+
vmvn d16, d16
-@ CHECK: vmvn q8, q8 @ encoding: [0xe0,0x05,0xf0,0xf3]
vmvn q8, q8
-@ CHECK: vbsl d18, d17, d16 @ encoding: [0xb0,0x21,0x51,0xf3]
+@ CHECK: vmvn d16, d16 @ encoding: [0xa0,0x05,0xf0,0xf3]
+@ CHECK: vmvn q8, q8 @ encoding: [0xe0,0x05,0xf0,0xf3]
+
vbsl d18, d17, d16
-@ CHECK: vbsl q8, q10, q9 @ encoding: [0xf2,0x01,0x54,0xf3]
vbsl q8, q10, q9
+
+@ CHECK: vbsl d18, d17, d16 @ encoding: [0xb0,0x21,0x51,0xf3]
+@ CHECK: vbsl q8, q10, q9 @ encoding: [0xf2,0x01,0x54,0xf3]
diff --git a/test/MC/ARM/neon-cmp-encoding.s b/test/MC/ARM/neon-cmp-encoding.s
index 6bfc549..d94e2f7 100644
--- a/test/MC/ARM/neon-cmp-encoding.s
+++ b/test/MC/ARM/neon-cmp-encoding.s
@@ -1,115 +1,113 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding < %s | FileCheck %s
-@ XFAIL: *
-@ FIXME: We cannot currently test the following instructions, which are
-@ currently marked as for-disassembly only in the .td files:
-@ - VCEQz
-@ - VCGEz, VCLEz
-@ - VCGTz, VCLTz
-
-@ CHECK: vceq.i8 d16, d16, d17 @ encoding: [0xb1,0x08,0x40,0xf3]
vceq.i8 d16, d16, d17
-@ CHECK: vceq.i16 d16, d16, d17 @ encoding: [0xb1,0x08,0x50,0xf3]
vceq.i16 d16, d16, d17
-@ CHECK: vceq.i32 d16, d16, d17 @ encoding: [0xb1,0x08,0x60,0xf3]
vceq.i32 d16, d16, d17
-@ CHECK: vceq.f32 d16, d16, d17 @ encoding: [0xa1,0x0e,0x40,0xf2]
vceq.f32 d16, d16, d17
-@ CHECK: vceq.i8 q8, q8, q9 @ encoding: [0xf2,0x08,0x40,0xf3]
vceq.i8 q8, q8, q9
-@ CHECK: vceq.i16 q8, q8, q9 @ encoding: [0xf2,0x08,0x50,0xf3]
vceq.i16 q8, q8, q9
-@ CHECK: vceq.i32 q8, q8, q9 @ encoding: [0xf2,0x08,0x60,0xf3]
vceq.i32 q8, q8, q9
-@ CHECK: vceq.f32 q8, q8, q9 @ encoding: [0xe2,0x0e,0x40,0xf2]
vceq.f32 q8, q8, q9
-@ CHECK: vcge.s8 d16, d16, d17 @ encoding: [0xb1,0x03,0x40,0xf2]
+@ CHECK: vceq.i8 d16, d16, d17 @ encoding: [0xb1,0x08,0x40,0xf3]
+@ CHECK: vceq.i16 d16, d16, d17 @ encoding: [0xb1,0x08,0x50,0xf3]
+@ CHECK: vceq.i32 d16, d16, d17 @ encoding: [0xb1,0x08,0x60,0xf3]
+@ CHECK: vceq.f32 d16, d16, d17 @ encoding: [0xa1,0x0e,0x40,0xf2]
+@ CHECK: vceq.i8 q8, q8, q9 @ encoding: [0xf2,0x08,0x40,0xf3]
+@ CHECK: vceq.i16 q8, q8, q9 @ encoding: [0xf2,0x08,0x50,0xf3]
+@ CHECK: vceq.i32 q8, q8, q9 @ encoding: [0xf2,0x08,0x60,0xf3]
+@ CHECK: vceq.f32 q8, q8, q9 @ encoding: [0xe2,0x0e,0x40,0xf2]
+
vcge.s8 d16, d16, d17
-@ CHECK: vcge.s16 d16, d16, d17 @ encoding: [0xb1,0x03,0x50,0xf2]
vcge.s16 d16, d16, d17
-@ CHECK: vcge.s32 d16, d16, d17 @ encoding: [0xb1,0x03,0x60,0xf2]
vcge.s32 d16, d16, d17
-@ CHECK: vcge.u8 d16, d16, d17 @ encoding: [0xb1,0x03,0x40,0xf3]
vcge.u8 d16, d16, d17
-@ CHECK: vcge.u16 d16, d16, d17 @ encoding: [0xb1,0x03,0x50,0xf3]
vcge.u16 d16, d16, d17
-@ CHECK: vcge.u32 d16, d16, d17 @ encoding: [0xb1,0x03,0x60,0xf3]
vcge.u32 d16, d16, d17
-@ CHECK: vcge.f32 d16, d16, d17 @ encoding: [0xa1,0x0e,0x40,0xf3]
vcge.f32 d16, d16, d17
-@ CHECK: vcge.s8 q8, q8, q9 @ encoding: [0xf2,0x03,0x40,0xf2]
vcge.s8 q8, q8, q9
-@ CHECK: vcge.s16 q8, q8, q9 @ encoding: [0xf2,0x03,0x50,0xf2]
vcge.s16 q8, q8, q9
-@ CHECK: vcge.s32 q8, q8, q9 @ encoding: [0xf2,0x03,0x60,0xf2]
vcge.s32 q8, q8, q9
-@ CHECK: vcge.u8 q8, q8, q9 @ encoding: [0xf2,0x03,0x40,0xf3]
vcge.u8 q8, q8, q9
-@ CHECK: vcge.u16 q8, q8, q9 @ encoding: [0xf2,0x03,0x50,0xf3]
vcge.u16 q8, q8, q9
-@ CHECK: vcge.u32 q8, q8, q9 @ encoding: [0xf2,0x03,0x60,0xf3]
vcge.u32 q8, q8, q9
-@ CHECK: vcge.f32 q8, q8, q9 @ encoding: [0xe2,0x0e,0x40,0xf3]
vcge.f32 q8, q8, q9
-@ CHECK: vacge.f32 d16, d16, d17 @ encoding: [0xb1,0x0e,0x40,0xf3]
vacge.f32 d16, d16, d17
-@ CHECK: vacge.f32 q8, q8, q9 @ encoding: [0xf2,0x0e,0x40,0xf3]
vacge.f32 q8, q8, q9
-@ CHECK: vcgt.s8 d16, d16, d17 @ encoding: [0xa1,0x03,0x40,0xf2]
+@ CHECK: vcge.s8 d16, d16, d17 @ encoding: [0xb1,0x03,0x40,0xf2]
+@ CHECK: vcge.s16 d16, d16, d17 @ encoding: [0xb1,0x03,0x50,0xf2]
+@ CHECK: vcge.s32 d16, d16, d17 @ encoding: [0xb1,0x03,0x60,0xf2]
+@ CHECK: vcge.u8 d16, d16, d17 @ encoding: [0xb1,0x03,0x40,0xf3]
+@ CHECK: vcge.u16 d16, d16, d17 @ encoding: [0xb1,0x03,0x50,0xf3]
+@ CHECK: vcge.u32 d16, d16, d17 @ encoding: [0xb1,0x03,0x60,0xf3]
+@ CHECK: vcge.f32 d16, d16, d17 @ encoding: [0xa1,0x0e,0x40,0xf3]
+@ CHECK: vcge.s8 q8, q8, q9 @ encoding: [0xf2,0x03,0x40,0xf2]
+@ CHECK: vcge.s16 q8, q8, q9 @ encoding: [0xf2,0x03,0x50,0xf2]
+@ CHECK: vcge.s32 q8, q8, q9 @ encoding: [0xf2,0x03,0x60,0xf2]
+@ CHECK: vcge.u8 q8, q8, q9 @ encoding: [0xf2,0x03,0x40,0xf3]
+@ CHECK: vcge.u16 q8, q8, q9 @ encoding: [0xf2,0x03,0x50,0xf3]
+@ CHECK: vcge.u32 q8, q8, q9 @ encoding: [0xf2,0x03,0x60,0xf3]
+@ CHECK: vcge.f32 q8, q8, q9 @ encoding: [0xe2,0x0e,0x40,0xf3]
+@ CHECK: vacge.f32 d16, d16, d17 @ encoding: [0xb1,0x0e,0x40,0xf3]
+@ CHECK: vacge.f32 q8, q8, q9 @ encoding: [0xf2,0x0e,0x40,0xf3]
+
vcgt.s8 d16, d16, d17
-@ CHECK: vcgt.s16 d16, d16, d17 @ encoding: [0xa1,0x03,0x50,0xf2]
vcgt.s16 d16, d16, d17
-@ CHECK: vcgt.s32 d16, d16, d17 @ encoding: [0xa1,0x03,0x60,0xf2]
vcgt.s32 d16, d16, d17
-@ CHECK: vcgt.u8 d16, d16, d17 @ encoding: [0xa1,0x03,0x40,0xf3]
vcgt.u8 d16, d16, d17
-@ CHECK: vcgt.u16 d16, d16, d17 @ encoding: [0xa1,0x03,0x50,0xf3]
vcgt.u16 d16, d16, d17
-@ CHECK: vcgt.u32 d16, d16, d17 @ encoding: [0xa1,0x03,0x60,0xf3]
vcgt.u32 d16, d16, d17
-@ CHECK: vcgt.f32 d16, d16, d17 @ encoding: [0xa1,0x0e,0x60,0xf3]
vcgt.f32 d16, d16, d17
-@ CHECK: vcgt.s8 q8, q8, q9 @ encoding: [0xe2,0x03,0x40,0xf2]
vcgt.s8 q8, q8, q9
-@ CHECK: vcgt.s16 q8, q8, q9 @ encoding: [0xe2,0x03,0x50,0xf2]
vcgt.s16 q8, q8, q9
-@ CHECK: vcgt.s32 q8, q8, q9 @ encoding: [0xe2,0x03,0x60,0xf2]
vcgt.s32 q8, q8, q9
-@ CHECK: vcgt.u8 q8, q8, q9 @ encoding: [0xe2,0x03,0x40,0xf3]
vcgt.u8 q8, q8, q9
-@ CHECK: vcgt.u16 q8, q8, q9 @ encoding: [0xe2,0x03,0x50,0xf3]
vcgt.u16 q8, q8, q9
-@ CHECK: vcgt.u32 q8, q8, q9 @ encoding: [0xe2,0x03,0x60,0xf3]
vcgt.u32 q8, q8, q9
-@ CHECK: vcgt.f32 q8, q8, q9 @ encoding: [0xe2,0x0e,0x60,0xf3]
vcgt.f32 q8, q8, q9
-@ CHECK: vacgt.f32 d16, d16, d17 @ encoding: [0xb1,0x0e,0x60,0xf3]
vacgt.f32 d16, d16, d17
-@ CHECK: vacgt.f32 q8, q8, q9 @ encoding: [0xf2,0x0e,0x60,0xf3]
vacgt.f32 q8, q8, q9
-@ CHECK: vtst.8 d16, d16, d17 @ encoding: [0xb1,0x08,0x40,0xf2]
+@ CHECK: vcgt.s8 d16, d16, d17 @ encoding: [0xa1,0x03,0x40,0xf2]
+@ CHECK: vcgt.s16 d16, d16, d17 @ encoding: [0xa1,0x03,0x50,0xf2]
+@ CHECK: vcgt.s32 d16, d16, d17 @ encoding: [0xa1,0x03,0x60,0xf2]
+@ CHECK: vcgt.u8 d16, d16, d17 @ encoding: [0xa1,0x03,0x40,0xf3]
+@ CHECK: vcgt.u16 d16, d16, d17 @ encoding: [0xa1,0x03,0x50,0xf3]
+@ CHECK: vcgt.u32 d16, d16, d17 @ encoding: [0xa1,0x03,0x60,0xf3]
+@ CHECK: vcgt.f32 d16, d16, d17 @ encoding: [0xa1,0x0e,0x60,0xf3]
+@ CHECK: vcgt.s8 q8, q8, q9 @ encoding: [0xe2,0x03,0x40,0xf2]
+@ CHECK: vcgt.s16 q8, q8, q9 @ encoding: [0xe2,0x03,0x50,0xf2]
+@ CHECK: vcgt.s32 q8, q8, q9 @ encoding: [0xe2,0x03,0x60,0xf2]
+@ CHECK: vcgt.u8 q8, q8, q9 @ encoding: [0xe2,0x03,0x40,0xf3]
+@ CHECK: vcgt.u16 q8, q8, q9 @ encoding: [0xe2,0x03,0x50,0xf3]
+@ CHECK: vcgt.u32 q8, q8, q9 @ encoding: [0xe2,0x03,0x60,0xf3]
+@ CHECK: vcgt.f32 q8, q8, q9 @ encoding: [0xe2,0x0e,0x60,0xf3]
+@ CHECK: vacgt.f32 d16, d16, d17 @ encoding: [0xb1,0x0e,0x60,0xf3]
+@ CHECK: vacgt.f32 q8, q8, q9 @ encoding: [0xf2,0x0e,0x60,0xf3]
+
vtst.8 d16, d16, d17
-@ CHECK: vtst.16 d16, d16, d17 @ encoding: [0xb1,0x08,0x50,0xf2]
vtst.16 d16, d16, d17
-@ CHECK: vtst.32 d16, d16, d17 @ encoding: [0xb1,0x08,0x60,0xf2]
vtst.32 d16, d16, d17
-@ CHECK: vtst.8 q8, q8, q9 @ encoding: [0xf2,0x08,0x40,0xf2]
vtst.8 q8, q8, q9
-@ CHECK: vtst.16 q8, q8, q9 @ encoding: [0xf2,0x08,0x50,0xf2]
vtst.16 q8, q8, q9
-@ CHECK: vtst.32 q8, q8, q9 @ encoding: [0xf2,0x08,0x60,0xf2]
vtst.32 q8, q8, q9
-@ CHECK: vceq.i8 d16, d16, #0 @ encoding: [0x20,0x01,0xf1,0xf3]
- vceq.i8 d16, d16, #0
-@ CHECK: vcge.s8 d16, d16, #0 @ encoding: [0xa0,0x00,0xf1,0xf3]
- vcge.s8 d16, d16, #0
-@ CHECK: vcle.s8 d16, d16, #0 @ encoding: [0xa0,0x01,0xf1,0xf3]
- vcle.s8 d16, d16, #0
-@ CHECK: vcgt.s8 d16, d16, #0 @ encoding: [0x20,0x00,0xf1,0xf3]
- vcgt.s8 d16, d16, #0
-@ CHECK: vclt.s8 d16, d16, #0 @ encoding: [0x20,0x02,0xf1,0xf3]
- vclt.s8 d16, d16, #0
+@ CHECK: vtst.8 d16, d16, d17 @ encoding: [0xb1,0x08,0x40,0xf2]
+@ CHECK: vtst.16 d16, d16, d17 @ encoding: [0xb1,0x08,0x50,0xf2]
+@ CHECK: vtst.32 d16, d16, d17 @ encoding: [0xb1,0x08,0x60,0xf2]
+@ CHECK: vtst.8 q8, q8, q9 @ encoding: [0xf2,0x08,0x40,0xf2]
+@ CHECK: vtst.16 q8, q8, q9 @ encoding: [0xf2,0x08,0x50,0xf2]
+@ CHECK: vtst.32 q8, q8, q9 @ encoding: [0xf2,0x08,0x60,0xf2]
+
+ vceq.i8 d16, d16, #0
+ vcge.s8 d16, d16, #0
+ vcle.s8 d16, d16, #0
+ vcgt.s8 d16, d16, #0
+ vclt.s8 d16, d16, #0
+
+@ CHECK: vceq.i8 d16, d16, #0 @ encoding: [0x20,0x01,0xf1,0xf3]
+@ CHECK: vcge.s8 d16, d16, #0 @ encoding: [0xa0,0x00,0xf1,0xf3]
+@ CHECK: vcle.s8 d16, d16, #0 @ encoding: [0xa0,0x01,0xf1,0xf3]
+@ CHECK: vcgt.s8 d16, d16, #0 @ encoding: [0x20,0x00,0xf1,0xf3]
+@ CHECK: vclt.s8 d16, d16, #0 @ encoding: [0x20,0x02,0xf1,0xf3]
diff --git a/test/MC/ARM/neon-dup-encoding.s b/test/MC/ARM/neon-dup-encoding.s
index 0aebdce..31dcf0b 100644
--- a/test/MC/ARM/neon-dup-encoding.s
+++ b/test/MC/ARM/neon-dup-encoding.s
@@ -1,27 +1,33 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding < %s | FileCheck %s
-@ XFAIL: *
-@ CHECK: vdup.8 d16, r0 @ encoding: [0x90,0x0b,0xc0,0xee]
vdup.8 d16, r0
-@ CHECK: vdup.16 d16, r0 @ encoding: [0xb0,0x0b,0x80,0xee]
vdup.16 d16, r0
-@ CHECK: vdup.32 d16, r0 @ encoding: [0x90,0x0b,0x80,0xee]
vdup.32 d16, r0
-@ CHECK: vdup.8 q8, r0 @ encoding: [0x90,0x0b,0xe0,0xee]
+
+@ CHECK: vdup.8 d16, r0 @ encoding: [0x90,0x0b,0xc0,0xee]
+@ CHECK: vdup.16 d16, r0 @ encoding: [0xb0,0x0b,0x80,0xee]
+@ CHECK: vdup.32 d16, r0 @ encoding: [0x90,0x0b,0x80,0xee]
+
vdup.8 q8, r0
-@ CHECK: vdup.16 q8, r0 @ encoding: [0xb0,0x0b,0xa0,0xee]
vdup.16 q8, r0
-@ CHECK: vdup.32 q8, r0 @ encoding: [0x90,0x0b,0xa0,0xee]
vdup.32 q8, r0
-@ CHECK: vdup.8 d16, d16[1] @ encoding: [0x20,0x0c,0xf3,0xf3]
+
+@ CHECK: vdup.8 q8, r0 @ encoding: [0x90,0x0b,0xe0,0xee]
+@ CHECK: vdup.16 q8, r0 @ encoding: [0xb0,0x0b,0xa0,0xee]
+@ CHECK: vdup.32 q8, r0 @ encoding: [0x90,0x0b,0xa0,0xee]
+
vdup.8 d16, d16[1]
-@ CHECK: vdup.16 d16, d16[1] @ encoding: [0x20,0x0c,0xf6,0xf3]
vdup.16 d16, d16[1]
-@ CHECK: vdup.32 d16, d16[1] @ encoding: [0x20,0x0c,0xfc,0xf3]
vdup.32 d16, d16[1]
-@ CHECK: vdup.8 q8, d16[1] @ encoding: [0x60,0x0c,0xf3,0xf3]
+
+@ CHECK: vdup.8 d16, d16[1] @ encoding: [0x20,0x0c,0xf3,0xf3]
+@ CHECK: vdup.16 d16, d16[1] @ encoding: [0x20,0x0c,0xf6,0xf3]
+@ CHECK: vdup.32 d16, d16[1] @ encoding: [0x20,0x0c,0xfc,0xf3]
+
vdup.8 q8, d16[1]
-@ CHECK: vdup.16 q8, d16[1] @ encoding: [0x60,0x0c,0xf6,0xf3]
vdup.16 q8, d16[1]
-@ CHECK: vdup.32 q8, d16[1] @ encoding: [0x60,0x0c,0xfc,0xf3]
vdup.32 q8, d16[1]
+
+@ CHECK: vdup.8 q8, d16[1] @ encoding: [0x60,0x0c,0xf3,0xf3]
+@ CHECK: vdup.16 q8, d16[1] @ encoding: [0x60,0x0c,0xf6,0xf3]
+@ CHECK: vdup.32 q8, d16[1] @ encoding: [0x60,0x0c,0xfc,0xf3]
diff --git a/test/MC/ARM/neon-mov-encoding.s b/test/MC/ARM/neon-mov-encoding.s
index ca678d0..02eec12 100644
--- a/test/MC/ARM/neon-mov-encoding.s
+++ b/test/MC/ARM/neon-mov-encoding.s
@@ -1,117 +1,131 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding < %s | FileCheck %s
@ XFAIL: *
-@ CHECK: vmov.i8 d16, #0x8 @ encoding: [0x18,0x0e,0xc0,0xf2]
- vmov.i8 d16, #0x8
-@ CHECK: vmov.i16 d16, #0x10 @ encoding: [0x10,0x08,0xc1,0xf2]
+ vmov.i8 d16, #0x8
vmov.i16 d16, #0x10
-@ CHECK: vmov.i16 d16, #0x1000 @ encoding: [0x10,0x0a,0xc1,0xf2]
vmov.i16 d16, #0x1000
-@ CHECK: vmov.i32 d16, #0x20 @ encoding: [0x10,0x00,0xc2,0xf2]
vmov.i32 d16, #0x20
-@ CHECK: vmov.i32 d16, #0x2000 @ encoding: [0x10,0x02,0xc2,0xf2]
vmov.i32 d16, #0x2000
-@ CHECK: vmov.i32 d16, #0x200000 @ encoding: [0x10,0x04,0xc2,0xf2]
vmov.i32 d16, #0x200000
-@ CHECK: vmov.i32 d16, #0x20000000 @ encoding: [0x10,0x06,0xc2,0xf2]
vmov.i32 d16, #0x20000000
-@ CHECK: vmov.i32 d16, #0x20FF @ encoding: [0x10,0x0c,0xc2,0xf2]
vmov.i32 d16, #0x20FF
-@ CHECK: vmov.i32 d16, #0x20FFFF @ encoding: [0x10,0x0d,0xc2,0xf2]
vmov.i32 d16, #0x20FFFF
-@ CHECK: vmov.i64 d16, #0xFF0000FF0000FFFF @ encoding: [0x33,0x0e,0xc1,0xf3]
vmov.i64 d16, #0xFF0000FF0000FFFF
-@ CHECK: vmov.i8 q8, #0x8 @ encoding: [0x58,0x0e,0xc0,0xf2]
- vmov.i8 q8, #0x8
-@ CHECK: vmov.i16 q8, #0x10 @ encoding: [0x50,0x08,0xc1,0xf2]
+
+@ CHECK: vmov.i8 d16, #0x8 @ encoding: [0x18,0x0e,0xc0,0xf2]
+@ CHECK: vmov.i16 d16, #0x10 @ encoding: [0x10,0x08,0xc1,0xf2]
+@ CHECK: vmov.i16 d16, #0x1000 @ encoding: [0x10,0x0a,0xc1,0xf2]
+@ CHECK: vmov.i32 d16, #0x20 @ encoding: [0x10,0x00,0xc2,0xf2]
+@ CHECK: vmov.i32 d16, #0x2000 @ encoding: [0x10,0x02,0xc2,0xf2]
+@ CHECK: vmov.i32 d16, #0x200000 @ encoding: [0x10,0x04,0xc2,0xf2]
+@ CHECK: vmov.i32 d16, #0x20000000 @ encoding: [0x10,0x06,0xc2,0xf2]
+@ CHECK: vmov.i32 d16, #0x20FF @ encoding: [0x10,0x0c,0xc2,0xf2]
+@ CHECK: vmov.i32 d16, #0x20FFFF @ encoding: [0x10,0x0d,0xc2,0xf2]
+@ CHECK: vmov.i64 d16, #0xFF0000FF0000FFFF @ encoding: [0x33,0x0e,0xc1,0xf3]
+
+
+
+ vmov.i8 q8, #0x8
vmov.i16 q8, #0x10
-@ CHECK: vmov.i16 q8, #0x1000 @ encoding: [0x50,0x0a,0xc1,0xf2]
vmov.i16 q8, #0x1000
-@ CHECK: vmov.i32 q8, #0x20 @ encoding: [0x50,0x00,0xc2,0xf2]
vmov.i32 q8, #0x20
-@ CHECK: vmov.i32 q8, #0x2000 @ encoding: [0x50,0x02,0xc2,0xf2]
vmov.i32 q8, #0x2000
-@ CHECK: vmov.i32 q8, #0x200000 @ encoding: [0x50,0x04,0xc2,0xf2]
vmov.i32 q8, #0x200000
-@ CHECK: vmov.i32 q8, #0x20000000 @ encoding: [0x50,0x06,0xc2,0xf2]
vmov.i32 q8, #0x20000000
-@ CHECK: vmov.i32 q8, #0x20FF @ encoding: [0x50,0x0c,0xc2,0xf2]
vmov.i32 q8, #0x20FF
-@ CHECK: vmov.i32 q8, #0x20FFFF @ encoding: [0x50,0x0d,0xc2,0xf2]
vmov.i32 q8, #0x20FFFF
-@ CHECK: vmov.i64 q8, #0xFF0000FF0000FFFF @ encoding: [0x73,0x0e,0xc1,0xf3]
vmov.i64 q8, #0xFF0000FF0000FFFF
-@ CHECK: vmvn.i16 d16, #0x10 @ encoding: [0x30,0x08,0xc1,0xf2]
+
+@ CHECK: vmov.i8 q8, #0x8 @ encoding: [0x58,0x0e,0xc0,0xf2]
+@ CHECK: vmov.i16 q8, #0x10 @ encoding: [0x50,0x08,0xc1,0xf2]
+@ CHECK: vmov.i16 q8, #0x1000 @ encoding: [0x50,0x0a,0xc1,0xf2]
+@ CHECK: vmov.i32 q8, #0x20 @ encoding: [0x50,0x00,0xc2,0xf2]
+@ CHECK: vmov.i32 q8, #0x2000 @ encoding: [0x50,0x02,0xc2,0xf2]
+@ CHECK: vmov.i32 q8, #0x200000 @ encoding: [0x50,0x04,0xc2,0xf2]
+@ CHECK: vmov.i32 q8, #0x20000000 @ encoding: [0x50,0x06,0xc2,0xf2]
+@ CHECK: vmov.i32 q8, #0x20FF @ encoding: [0x50,0x0c,0xc2,0xf2]
+@ CHECK: vmov.i32 q8, #0x20FFFF @ encoding: [0x50,0x0d,0xc2,0xf2]
+@ CHECK: vmov.i64 q8, #0xFF0000FF0000FFFF @ encoding: [0x73,0x0e,0xc1,0xf3]
+
vmvn.i16 d16, #0x10
-@ CHECK: vmvn.i16 d16, #0x1000 @ encoding: [0x30,0x0a,0xc1,0xf2]
vmvn.i16 d16, #0x1000
-@ CHECK: vmvn.i32 d16, #0x20 @ encoding: [0x30,0x00,0xc2,0xf2]
vmvn.i32 d16, #0x20
-@ CHECK: vmvn.i32 d16, #0x2000 @ encoding: [0x30,0x02,0xc2,0xf2]
vmvn.i32 d16, #0x2000
-@ CHECK: vmvn.i32 d16, #0x200000 @ encoding: [0x30,0x04,0xc2,0xf2]
vmvn.i32 d16, #0x200000
-@ CHECK: vmvn.i32 d16, #0x20000000 @ encoding: [0x30,0x06,0xc2,0xf2]
vmvn.i32 d16, #0x20000000
-@ CHECK: vmvn.i32 d16, #0x20FF @ encoding: [0x30,0x0c,0xc2,0xf2]
vmvn.i32 d16, #0x20FF
-@ CHECK: vmvn.i32 d16, #0x20FFFF @ encoding: [0x30,0x0d,0xc2,0xf2]
vmvn.i32 d16, #0x20FFFF
-@ CHECK: vmovl.s8 q8, d16 @ encoding: [0x30,0x0a,0xc8,0xf2]
+
+@ CHECK: vmvn.i16 d16, #0x10 @ encoding: [0x30,0x08,0xc1,0xf2]
+@ CHECK: vmvn.i16 d16, #0x1000 @ encoding: [0x30,0x0a,0xc1,0xf2]
+@ CHECK: vmvn.i32 d16, #0x20 @ encoding: [0x30,0x00,0xc2,0xf2]
+@ CHECK: vmvn.i32 d16, #0x2000 @ encoding: [0x30,0x02,0xc2,0xf2]
+@ CHECK: vmvn.i32 d16, #0x200000 @ encoding: [0x30,0x04,0xc2,0xf2]
+@ CHECK: vmvn.i32 d16, #0x20000000 @ encoding: [0x30,0x06,0xc2,0xf2]
+@ CHECK: vmvn.i32 d16, #0x20FF @ encoding: [0x30,0x0c,0xc2,0xf2]
+@ CHECK: vmvn.i32 d16, #0x20FFFF @ encoding: [0x30,0x0d,0xc2,0xf2]
+
vmovl.s8 q8, d16
-@ CHECK: vmovl.s16 q8, d16 @ encoding: [0x30,0x0a,0xd0,0xf2]
vmovl.s16 q8, d16
-@ CHECK: vmovl.s32 q8, d16 @ encoding: [0x30,0x0a,0xe0,0xf2]
vmovl.s32 q8, d16
-@ CHECK: vmovl.u8 q8, d16 @ encoding: [0x30,0x0a,0xc8,0xf3]
vmovl.u8 q8, d16
-@ CHECK: vmovl.u16 q8, d16 @ encoding: [0x30,0x0a,0xd0,0xf3]
vmovl.u16 q8, d16
-@ CHECK: vmovl.u32 q8, d16 @ encoding: [0x30,0x0a,0xe0,0xf3]
vmovl.u32 q8, d16
-@ CHECK: vmovn.i16 d16, q8 @ encoding: [0x20,0x02,0xf2,0xf3]
+
+@ CHECK: vmovl.s8 q8, d16 @ encoding: [0x30,0x0a,0xc8,0xf2]
+@ CHECK: vmovl.s16 q8, d16 @ encoding: [0x30,0x0a,0xd0,0xf2]
+@ CHECK: vmovl.s32 q8, d16 @ encoding: [0x30,0x0a,0xe0,0xf2]
+@ CHECK: vmovl.u8 q8, d16 @ encoding: [0x30,0x0a,0xc8,0xf3]
+@ CHECK: vmovl.u16 q8, d16 @ encoding: [0x30,0x0a,0xd0,0xf3]
+@ CHECK: vmovl.u32 q8, d16 @ encoding: [0x30,0x0a,0xe0,0xf3]
+
+
vmovn.i16 d16, q8
-@ CHECK: vmovn.i32 d16, q8 @ encoding: [0x20,0x02,0xf6,0xf3]
vmovn.i32 d16, q8
-@ CHECK: vmovn.i64 d16, q8 @ encoding: [0x20,0x02,0xfa,0xf3]
vmovn.i64 d16, q8
-@ CHECK: vqmovn.s16 d16, q8 @ encoding: [0xa0,0x02,0xf2,0xf3]
vqmovn.s16 d16, q8
-@ CHECK: vqmovn.s32 d16, q8 @ encoding: [0xa0,0x02,0xf6,0xf3]
vqmovn.s32 d16, q8
-@ CHECK: vqmovn.s64 d16, q8 @ encoding: [0xa0,0x02,0xfa,0xf3]
vqmovn.s64 d16, q8
-@ CHECK: vqmovn.u16 d16, q8 @ encoding: [0xe0,0x02,0xf2,0xf3]
vqmovn.u16 d16, q8
-@ CHECK: vqmovn.u32 d16, q8 @ encoding: [0xe0,0x02,0xf6,0xf3]
vqmovn.u32 d16, q8
-@ CHECK: vqmovn.u64 d16, q8 @ encoding: [0xe0,0x02,0xfa,0xf3]
vqmovn.u64 d16, q8
-@ CHECK: vqmovun.s16 d16, q8 @ encoding: [0x60,0x02,0xf2,0xf3]
vqmovun.s16 d16, q8
-@ CHECK: vqmovun.s32 d16, q8 @ encoding: [0x60,0x02,0xf6,0xf3]
vqmovun.s32 d16, q8
-@ CHECK: vqmovun.s64 d16, q8 @ encoding: [0x60,0x02,0xfa,0xf3]
vqmovun.s64 d16, q8
-@ CHECK: vmov.s8 r0, d16[1] @ encoding: [0xb0,0x0b,0x50,0xee]
- vmov.s8 r0, d16[1]
-@ CHECK: vmov.s16 r0, d16[1] @ encoding: [0xf0,0x0b,0x10,0xee]
+
+@ CHECK: vmovn.i16 d16, q8 @ encoding: [0x20,0x02,0xf2,0xf3]
+@ CHECK: vmovn.i32 d16, q8 @ encoding: [0x20,0x02,0xf6,0xf3]
+@ CHECK: vmovn.i64 d16, q8 @ encoding: [0x20,0x02,0xfa,0xf3]
+@ CHECK: vqmovn.s16 d16, q8 @ encoding: [0xa0,0x02,0xf2,0xf3]
+@ CHECK: vqmovn.s32 d16, q8 @ encoding: [0xa0,0x02,0xf6,0xf3]
+@ CHECK: vqmovn.s64 d16, q8 @ encoding: [0xa0,0x02,0xfa,0xf3]
+@ CHECK: vqmovn.u16 d16, q8 @ encoding: [0xe0,0x02,0xf2,0xf3]
+@ CHECK: vqmovn.u32 d16, q8 @ encoding: [0xe0,0x02,0xf6,0xf3]
+@ CHECK: vqmovn.u64 d16, q8 @ encoding: [0xe0,0x02,0xfa,0xf3]
+@ CHECK: vqmovun.s16 d16, q8 @ encoding: [0x60,0x02,0xf2,0xf3]
+@ CHECK: vqmovun.s32 d16, q8 @ encoding: [0x60,0x02,0xf6,0xf3]
+@ CHECK: vqmovun.s64 d16, q8 @ encoding: [0x60,0x02,0xfa,0xf3]
+
+ vmov.s8 r0, d16[1]
vmov.s16 r0, d16[1]
-@ CHECK: vmov.u8 r0, d16[1] @ encoding: [0xb0,0x0b,0xd0,0xee]
- vmov.u8 r0, d16[1]
-@ CHECK: vmov.u16 r0, d16[1] @ encoding: [0xf0,0x0b,0x90,0xee]
+ vmov.u8 r0, d16[1]
vmov.u16 r0, d16[1]
-@ CHECK: vmov.32 r0, d16[1] @ encoding: [0x90,0x0b,0x30,0xee]
- vmov.32 r0, d16[1]
-@ CHECK: vmov.8 d16[1], r1 @ encoding: [0xb0,0x1b,0x40,0xee]
+ vmov.32 r0, d16[1]
vmov.8 d16[1], r1
-@ CHECK: vmov.16 d16[1], r1 @ encoding: [0xf0,0x1b,0x00,0xee]
vmov.16 d16[1], r1
-@ CHECK: vmov.32 d16[1], r1 @ encoding: [0x90,0x1b,0x20,0xee]
vmov.32 d16[1], r1
-@ CHECK: vmov.8 d18[1], r1 @ encoding: [0xb0,0x1b,0x42,0xee]
vmov.8 d18[1], r1
-@ CHECK: vmov.16 d18[1], r1 @ encoding: [0xf0,0x1b,0x02,0xee]
vmov.16 d18[1], r1
-@ CHECK: vmov.32 d18[1], r1 @ encoding: [0x90,0x1b,0x22,0xee]
vmov.32 d18[1], r1
+
+@ CHECK: vmov.s8 r0, d16[1] @ encoding: [0xb0,0x0b,0x50,0xee]
+@ CHECK: vmov.s16 r0, d16[1] @ encoding: [0xf0,0x0b,0x10,0xee]
+@ CHECK: vmov.u8 r0, d16[1] @ encoding: [0xb0,0x0b,0xd0,0xee]
+@ CHECK: vmov.u16 r0, d16[1] @ encoding: [0xf0,0x0b,0x90,0xee]
+@ CHECK: vmov.32 r0, d16[1] @ encoding: [0x90,0x0b,0x30,0xee]
+@ CHECK: vmov.8 d16[1], r1 @ encoding: [0xb0,0x1b,0x40,0xee]
+@ CHECK: vmov.16 d16[1], r1 @ encoding: [0xf0,0x1b,0x00,0xee]
+@ CHECK: vmov.32 d16[1], r1 @ encoding: [0x90,0x1b,0x20,0xee]
+@ CHECK: vmov.8 d18[1], r1 @ encoding: [0xb0,0x1b,0x42,0xee]
+@ CHECK: vmov.16 d18[1], r1 @ encoding: [0xf0,0x1b,0x02,0xee]
+@ CHECK: vmov.32 d18[1], r1 @ encoding: [0x90,0x1b,0x22,0xee]
diff --git a/test/MC/ARM/neon-mul-accum-encoding.s b/test/MC/ARM/neon-mul-accum-encoding.s
index e269dea..ed9ceb3 100644
--- a/test/MC/ARM/neon-mul-accum-encoding.s
+++ b/test/MC/ARM/neon-mul-accum-encoding.s
@@ -1,11 +1,10 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding < %s | FileCheck %s
-@ XFAIL: *
@ CHECK: vmla.i8 d16, d18, d17 @ encoding: [0xa1,0x09,0x42,0xf2]
vmla.i8 d16, d18, d17
@ CHECK: vmla.i16 d16, d18, d17 @ encoding: [0xa1,0x09,0x52,0xf2]
vmla.i16 d16, d18, d17
-@ CHECK: vmla.i16 d16, d18, d17 @ encoding: [0xa1,0x09,0x52,0xf2]
+@ CHECK: vmla.i32 d16, d18, d17 @ encoding: [0xa1,0x09,0x62,0xf2]
vmla.i32 d16, d18, d17
@ CHECK: vmla.f32 d16, d18, d17 @ encoding: [0xb1,0x0d,0x42,0xf2]
vmla.f32 d16, d18, d17
diff --git a/test/MC/ARM/neon-mul-encoding.s b/test/MC/ARM/neon-mul-encoding.s
index 4ff192f..4dc7803 100644
--- a/test/MC/ARM/neon-mul-encoding.s
+++ b/test/MC/ARM/neon-mul-encoding.s
@@ -1,56 +1,82 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding < %s | FileCheck %s
-@ CHECK: vmul.i8 d16, d16, d17 @ encoding: [0xb1,0x09,0x40,0xf2]
- vmul.i8 d16, d16, d17
-@ CHECK: vmul.i16 d16, d16, d17 @ encoding: [0xb1,0x09,0x50,0xf2]
- vmul.i16 d16, d16, d17
-@ CHECK: vmul.i32 d16, d16, d17 @ encoding: [0xb1,0x09,0x60,0xf2]
- vmul.i32 d16, d16, d17
-@ CHECK: vmul.f32 d16, d16, d17 @ encoding: [0xb1,0x0d,0x40,0xf3]
- vmul.f32 d16, d16, d17
-@ CHECK: vmul.i8 q8, q8, q9 @ encoding: [0xf2,0x09,0x40,0xf2]
- vmul.i8 q8, q8, q9
-@ CHECK: vmul.i16 q8, q8, q9 @ encoding: [0xf2,0x09,0x50,0xf2]
- vmul.i16 q8, q8, q9
-@ CHECK: vmul.i32 q8, q8, q9 @ encoding: [0xf2,0x09,0x60,0xf2]
- vmul.i32 q8, q8, q9
-@ CHECK: vmul.f32 q8, q8, q9 @ encoding: [0xf2,0x0d,0x40,0xf3]
- vmul.f32 q8, q8, q9
-@ CHECK: vmul.p8 d16, d16, d17 @ encoding: [0xb1,0x09,0x40,0xf3]
- vmul.p8 d16, d16, d17
-@ CHECK: vmul.p8 q8, q8, q9 @ encoding: [0xf2,0x09,0x40,0xf3]
- vmul.p8 q8, q8, q9
-@ CHECK: vqdmulh.s16 d16, d16, d17 @ encoding: [0xa1,0x0b,0x50,0xf2]
- vqdmulh.s16 d16, d16, d17
-@ CHECK: vqdmulh.s32 d16, d16, d17 @ encoding: [0xa1,0x0b,0x60,0xf2]
- vqdmulh.s32 d16, d16, d17
-@ CHECK: vqdmulh.s16 q8, q8, q9 @ encoding: [0xe2,0x0b,0x50,0xf2]
- vqdmulh.s16 q8, q8, q9
-@ CHECK: vqdmulh.s32 q8, q8, q9 @ encoding: [0xe2,0x0b,0x60,0xf2]
- vqdmulh.s32 q8, q8, q9
-@ CHECK: vqrdmulh.s16 d16, d16, d17 @ encoding: [0xa1,0x0b,0x50,0xf3]
- vqrdmulh.s16 d16, d16, d17
-@ CHECK: vqrdmulh.s32 d16, d16, d17 @ encoding: [0xa1,0x0b,0x60,0xf3]
- vqrdmulh.s32 d16, d16, d17
-@ CHECK: vqrdmulh.s16 q8, q8, q9 @ encoding: [0xe2,0x0b,0x50,0xf3]
- vqrdmulh.s16 q8, q8, q9
-@ CHECK: vqrdmulh.s32 q8, q8, q9 @ encoding: [0xe2,0x0b,0x60,0xf3]
- vqrdmulh.s32 q8, q8, q9
-@ CHECK: vmull.s8 q8, d16, d17 @ encoding: [0xa1,0x0c,0xc0,0xf2]
- vmull.s8 q8, d16, d17
-@ CHECK: vmull.s16 q8, d16, d17 @ encoding: [0xa1,0x0c,0xd0,0xf2]
- vmull.s16 q8, d16, d17
-@ CHECK: vmull.s32 q8, d16, d17 @ encoding: [0xa1,0x0c,0xe0,0xf2]
- vmull.s32 q8, d16, d17
-@ CHECK: vmull.u8 q8, d16, d17 @ encoding: [0xa1,0x0c,0xc0,0xf3]
- vmull.u8 q8, d16, d17
-@ CHECK: vmull.u16 q8, d16, d17 @ encoding: [0xa1,0x0c,0xd0,0xf3]
- vmull.u16 q8, d16, d17
-@ CHECK: vmull.u32 q8, d16, d17 @ encoding: [0xa1,0x0c,0xe0,0xf3]
- vmull.u32 q8, d16, d17
-@ CHECK: vmull.p8 q8, d16, d17 @ encoding: [0xa1,0x0e,0xc0,0xf2]
- vmull.p8 q8, d16, d17
-@ CHECK: vqdmull.s16 q8, d16, d17 @ encoding: [0xa1,0x0d,0xd0,0xf2]
- vqdmull.s16 q8, d16, d17
-@ CHECK: vqdmull.s32 q8, d16, d17 @ encoding: [0xa1,0x0d,0xe0,0xf2]
- vqdmull.s32 q8, d16, d17
+ vmla.i8 d16, d18, d17
+ vmla.i16 d16, d18, d17
+ vmla.i32 d16, d18, d17
+ vmla.f32 d16, d18, d17
+ vmla.i8 q9, q8, q10
+ vmla.i16 q9, q8, q10
+ vmla.i32 q9, q8, q10
+ vmla.f32 q9, q8, q10
+
+@ CHECK: vmla.i8 d16, d18, d17 @ encoding: [0xa1,0x09,0x42,0xf2]
+@ CHECK: vmla.i16 d16, d18, d17 @ encoding: [0xa1,0x09,0x52,0xf2]
+@ CHECK: vmla.i32 d16, d18, d17 @ encoding: [0xa1,0x09,0x62,0xf2]
+@ CHECK: vmla.f32 d16, d18, d17 @ encoding: [0xb1,0x0d,0x42,0xf2]
+@ CHECK: vmla.i8 q9, q8, q10 @ encoding: [0xe4,0x29,0x40,0xf2]
+@ CHECK: vmla.i16 q9, q8, q10 @ encoding: [0xe4,0x29,0x50,0xf2]
+@ CHECK: vmla.i32 q9, q8, q10 @ encoding: [0xe4,0x29,0x60,0xf2]
+@ CHECK: vmla.f32 q9, q8, q10 @ encoding: [0xf4,0x2d,0x40,0xf2]
+
+
+ vmlal.s8 q8, d19, d18
+ vmlal.s16 q8, d19, d18
+ vmlal.s32 q8, d19, d18
+ vmlal.u8 q8, d19, d18
+ vmlal.u16 q8, d19, d18
+ vmlal.u32 q8, d19, d18
+
+@ CHECK: vmlal.s8 q8, d19, d18 @ encoding: [0xa2,0x08,0xc3,0xf2]
+@ CHECK: vmlal.s16 q8, d19, d18 @ encoding: [0xa2,0x08,0xd3,0xf2]
+@ CHECK: vmlal.s32 q8, d19, d18 @ encoding: [0xa2,0x08,0xe3,0xf2]
+@ CHECK: vmlal.u8 q8, d19, d18 @ encoding: [0xa2,0x08,0xc3,0xf3]
+@ CHECK: vmlal.u16 q8, d19, d18 @ encoding: [0xa2,0x08,0xd3,0xf3]
+@ CHECK: vmlal.u32 q8, d19, d18 @ encoding: [0xa2,0x08,0xe3,0xf3]
+
+
+ vqdmlal.s16 q8, d19, d18
+ vqdmlal.s32 q8, d19, d18
+
+@ CHECK: vqdmlal.s16 q8, d19, d18 @ encoding: [0xa2,0x09,0xd3,0xf2]
+@ CHECK: vqdmlal.s32 q8, d19, d18 @ encoding: [0xa2,0x09,0xe3,0xf2]
+
+
+ vmls.i8 d16, d18, d17
+ vmls.i16 d16, d18, d17
+ vmls.i32 d16, d18, d17
+ vmls.f32 d16, d18, d17
+ vmls.i8 q9, q8, q10
+ vmls.i16 q9, q8, q10
+ vmls.i32 q9, q8, q10
+ vmls.f32 q9, q8, q10
+
+@ CHECK: vmls.i8 d16, d18, d17 @ encoding: [0xa1,0x09,0x42,0xf3]
+@ CHECK: vmls.i16 d16, d18, d17 @ encoding: [0xa1,0x09,0x52,0xf3]
+@ CHECK: vmls.i32 d16, d18, d17 @ encoding: [0xa1,0x09,0x62,0xf3]
+@ CHECK: vmls.f32 d16, d18, d17 @ encoding: [0xb1,0x0d,0x62,0xf2]
+@ CHECK: vmls.i8 q9, q8, q10 @ encoding: [0xe4,0x29,0x40,0xf3]
+@ CHECK: vmls.i16 q9, q8, q10 @ encoding: [0xe4,0x29,0x50,0xf3]
+@ CHECK: vmls.i32 q9, q8, q10 @ encoding: [0xe4,0x29,0x60,0xf3]
+@ CHECK: vmls.f32 q9, q8, q10 @ encoding: [0xf4,0x2d,0x60,0xf2]
+
+
+ vmlsl.s8 q8, d19, d18
+ vmlsl.s16 q8, d19, d18
+ vmlsl.s32 q8, d19, d18
+ vmlsl.u8 q8, d19, d18
+ vmlsl.u16 q8, d19, d18
+ vmlsl.u32 q8, d19, d18
+
+@ CHECK: vmlsl.s8 q8, d19, d18 @ encoding: [0xa2,0x0a,0xc3,0xf2]
+@ CHECK: vmlsl.s16 q8, d19, d18 @ encoding: [0xa2,0x0a,0xd3,0xf2]
+@ CHECK: vmlsl.s32 q8, d19, d18 @ encoding: [0xa2,0x0a,0xe3,0xf2]
+@ CHECK: vmlsl.u8 q8, d19, d18 @ encoding: [0xa2,0x0a,0xc3,0xf3]
+@ CHECK: vmlsl.u16 q8, d19, d18 @ encoding: [0xa2,0x0a,0xd3,0xf3]
+@ CHECK: vmlsl.u32 q8, d19, d18 @ encoding: [0xa2,0x0a,0xe3,0xf3]
+
+
+ vqdmlsl.s16 q8, d19, d18
+ vqdmlsl.s32 q8, d19, d18
+
+@ CHECK: vqdmlsl.s16 q8, d19, d18 @ encoding: [0xa2,0x0b,0xd3,0xf2]
+@ CHECK: vqdmlsl.s32 q8, d19, d18 @ encoding: [0xa2,0x0b,0xe3,0xf2]
diff --git a/test/MC/ARM/neon-vld-encoding.s b/test/MC/ARM/neon-vld-encoding.s
index be55f47..55c8868 100644
--- a/test/MC/ARM/neon-vld-encoding.s
+++ b/test/MC/ARM/neon-vld-encoding.s
@@ -1,110 +1,125 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple armv7-apple-darwin -show-encoding < %s | FileCheck %s
@ XFAIL: *
-@ CHECK: vld1.8 {d16}, [r0, :64] @ encoding: [0x1f,0x07,0x60,0xf4]
vld1.8 {d16}, [r0, :64]
-@ CHECK: vld1.16 {d16}, [r0] @ encoding: [0x4f,0x07,0x60,0xf4]
- vld1.16 {d16}, [r0]
-@ CHECK: vld1.32 {d16}, [r0] @ encoding: [0x8f,0x07,0x60,0xf4]
- vld1.32 {d16}, [r0]
-@ CHECK: vld1.64 {d16}, [r0] @ encoding: [0xcf,0x07,0x60,0xf4]
- vld1.64 {d16}, [r0]
+ vld1.16 {d16}, [r0]
+ vld1.32 {d16}, [r0]
+ vld1.64 {d16}, [r0]
+ vld1.8 {d16, d17}, [r0, :64]
+ vld1.16 {d16, d17}, [r0, :128]
+ vld1.32 {d16, d17}, [r0]
+ vld1.64 {d16, d17}, [r0]
+
+@ CHECK: vld1.8 {d16}, [r0, :64] @ encoding: [0x1f,0x07,0x60,0xf4]
+@ CHECK: vld1.16 {d16}, [r0] @ encoding: [0x4f,0x07,0x60,0xf4]
+@ CHECK: vld1.32 {d16}, [r0] @ encoding: [0x8f,0x07,0x60,0xf4]
+@ CHECK: vld1.64 {d16}, [r0] @ encoding: [0xcf,0x07,0x60,0xf4]
@ CHECK: vld1.8 {d16, d17}, [r0, :64] @ encoding: [0x1f,0x0a,0x60,0xf4]
- vld1.8 {d16, d17}, [r0, :64]
-@ CHECK: vld1.16 {d16, d17}, [r0, :128] @ encoding: [0x6f,0x0a,0x60,0xf4]
- vld1.16 {d16, d17}, [r0, :128]
-@ CHECK: vld1.32 {d16, d17}, [r0] @ encoding: [0x8f,0x0a,0x60,0xf4]
- vld1.32 {d16, d17}, [r0]
-@ CHECK: vld1.64 {d16, d17}, [r0] @ encoding: [0xcf,0x0a,0x60,0xf4]
- vld1.64 {d16, d17}, [r0]
+@ CHECK: vld1.16 {d16, d17}, [r0, :128] @ encoding: [0x6f,0x0a,0x60,0xf4]
+@ CHECK: vld1.32 {d16, d17}, [r0]@ encoding: [0x8f,0x0a,0x60,0xf4]
+@ CHECK: vld1.64 {d16, d17}, [r0]@ encoding: [0xcf,0x0a,0x60,0xf4]
+
+
+ vld2.8 {d16, d17}, [r0, :64]
+ vld2.16 {d16, d17}, [r0, :128]
+ vld2.32 {d16, d17}, [r0]
+ vld2.8 {d16, d17, d18, d19}, [r0, :64]
+ vld2.16 {d16, d17, d18, d19}, [r0, :128]
+ vld2.32 {d16, d17, d18, d19}, [r0, :256]
@ CHECK: vld2.8 {d16, d17}, [r0, :64] @ encoding: [0x1f,0x08,0x60,0xf4]
- vld2.8 {d16, d17}, [r0, :64]
-@ CHECK: vld2.16 {d16, d17}, [r0, :128] @ encoding: [0x6f,0x08,0x60,0xf4]
- vld2.16 {d16, d17}, [r0, :128]
-@ CHECK: vld2.32 {d16, d17}, [r0] @ encoding: [0x8f,0x08,0x60,0xf4]
- vld2.32 {d16, d17}, [r0]
-@ CHECK: vld2.8 {d16, d17, d18, d19}, [r0, :64] @ encoding: [0x1f,0x03,0x60,0xf4]
- vld2.8 {d16, d17, d18, d19}, [r0, :64]
-@ CHECK: vld2.16 {d16, d17, d18, d19}, [r0, :128] @ encoding: [0x6f,0x03,0x60,0xf4]
- vld2.16 {d16, d17, d18, d19}, [r0, :128]
-@ CHECK: vld2.32 {d16, d17, d18, d19}, [r0, :256] @ encoding: [0xbf,0x03,0x60,0xf4]
- vld2.32 {d16, d17, d18, d19}, [r0, :256]
+@ CHECK: vld2.16 {d16, d17}, [r0, :128] @ encoding: [0x6f,0x08,0x60,0xf4]
+@ CHECK: vld2.32 {d16, d17}, [r0]@ encoding: [0x8f,0x08,0x60,0xf4]
+@ CHECK: vld2.8 {d16, d17, d18, d19}, [r0, :64]@ encoding: [0x1f,0x03,0x60,0xf4]
+@ CHECK: vld2.16 {d16, d17, d18, d19}, [r0, :128] @ encoding: [0x6f,0x03,0x60,0xf4]
+@ CHECK: vld2.32 {d16, d17, d18, d19}, [r0, :256] @ encoding: [0xbf,0x03,0x60,0xf4]
+
+
+ vld3.8 {d16, d17, d18}, [r0, :64]
+ vld3.16 {d16, d17, d18}, [r0]
+ vld3.32 {d16, d17, d18}, [r0]
+ vld3.8 {d16, d18, d20}, [r0, :64]!
+ vld3.8 {d17, d19, d21}, [r0, :64]!
+ vld3.16 {d16, d18, d20}, [r0]!
+ vld3.16 {d17, d19, d21}, [r0]!
+ vld3.32 {d16, d18, d20}, [r0]!
+ vld3.32 {d17, d19, d21}, [r0]!
@ CHECK: vld3.8 {d16, d17, d18}, [r0, :64] @ encoding: [0x1f,0x04,0x60,0xf4]
- vld3.8 {d16, d17, d18}, [r0, :64]
-@ CHECK: vld3.16 {d16, d17, d18}, [r0] @ encoding: [0x4f,0x04,0x60,0xf4]
- vld3.16 {d16, d17, d18}, [r0]
-@ CHECK: vld3.32 {d16, d17, d18}, [r0] @ encoding: [0x8f,0x04,0x60,0xf4]
- vld3.32 {d16, d17, d18}, [r0]
+@ CHECK: vld3.16 {d16, d17, d18}, [r0] @ encoding: [0x4f,0x04,0x60,0xf4]
+@ CHECK: vld3.32 {d16, d17, d18}, [r0] @ encoding: [0x8f,0x04,0x60,0xf4]
@ CHECK: vld3.8 {d16, d18, d20}, [r0, :64]! @ encoding: [0x1d,0x05,0x60,0xf4]
- vld3.8 {d16, d18, d20}, [r0, :64]!
@ CHECK: vld3.8 {d17, d19, d21}, [r0, :64]! @ encoding: [0x1d,0x15,0x60,0xf4]
- vld3.8 {d17, d19, d21}, [r0, :64]!
-@ CHECK: vld3.16 {d16, d18, d20}, [r0]! @ encoding: [0x4d,0x05,0x60,0xf4]
- vld3.16 {d16, d18, d20}, [r0]!
-@ CHECK: vld3.16 {d17, d19, d21}, [r0]! @ encoding: [0x4d,0x15,0x60,0xf4]
- vld3.16 {d17, d19, d21}, [r0]!
-@ CHECK: vld3.32 {d16, d18, d20}, [r0]! @ encoding: [0x8d,0x05,0x60,0xf4]
- vld3.32 {d16, d18, d20}, [r0]!
-@ CHECK: vld3.32 {d17, d19, d21}, [r0]! @ encoding: [0x8d,0x15,0x60,0xf4]
- vld3.32 {d17, d19, d21}, [r0]!
-
-@ CHECK: vld4.8 {d16, d17, d18, d19}, [r0, :64] @ encoding: [0x1f,0x00,0x60,0xf4]
- vld4.8 {d16, d17, d18, d19}, [r0, :64]
-@ CHECK: vld4.16 {d16, d17, d18, d19}, [r0, :128] @ encoding: [0x6f,0x00,0x60,0xf4]
- vld4.16 {d16, d17, d18, d19}, [r0, :128]
-@ CHECK: vld4.32 {d16, d17, d18, d19}, [r0, :256] @ encoding: [0xbf,0x00,0x60,0xf4]
- vld4.32 {d16, d17, d18, d19}, [r0, :256]
-@ CHECK: vld4.8 {d16, d18, d20, d22}, [r0, :256]! @ encoding: [0x3d,0x01,0x60,0xf4]
- vld4.8 {d16, d18, d20, d22}, [r0, :256]!
-@ CHECK: vld4.8 {d17, d19, d21, d23}, [r0, :256]! @ encoding: [0x3d,0x11,0x60,0xf4]
- vld4.8 {d17, d19, d21, d23}, [r0, :256]!
-@ CHECK: vld4.16 {d16, d18, d20, d22}, [r0]! @ encoding: [0x4d,0x01,0x60,0xf4]
- vld4.16 {d16, d18, d20, d22}, [r0]!
-@ CHECK: vld4.16 {d17, d19, d21, d23}, [r0]! @ encoding: [0x4d,0x11,0x60,0xf4]
- vld4.16 {d17, d19, d21, d23}, [r0]!
-@ CHECK: vld4.32 {d16, d18, d20, d22}, [r0]! @ encoding: [0x8d,0x01,0x60,0xf4]
- vld4.32 {d16, d18, d20, d22}, [r0]!
-@ CHECK: vld4.32 {d17, d19, d21, d23}, [r0]! @ encoding: [0x8d,0x11,0x60,0xf4]
- vld4.32 {d17, d19, d21, d23}, [r0]!
+@ CHECK: vld3.16 {d16, d18, d20}, [r0]! @ encoding: [0x4d,0x05,0x60,0xf4]
+@ CHECK: vld3.16 {d17, d19, d21}, [r0]! @ encoding: [0x4d,0x15,0x60,0xf4]
+@ CHECK: vld3.32 {d16, d18, d20}, [r0]! @ encoding: [0x8d,0x05,0x60,0xf4]
+@ CHECK: vld3.32 {d17, d19, d21}, [r0]! @ encoding: [0x8d,0x15,0x60,0xf4]
+
+
+ vld4.8 {d16, d17, d18, d19}, [r0, :64]
+ vld4.16 {d16, d17, d18, d19}, [r0, :128]
+ vld4.32 {d16, d17, d18, d19}, [r0, :256]
+ vld4.8 {d16, d18, d20, d22}, [r0, :256]!
+ vld4.8 {d17, d19, d21, d23}, [r0, :256]!
+ vld4.16 {d16, d18, d20, d22}, [r0]!
+ vld4.16 {d17, d19, d21, d23}, [r0]!
+ vld4.32 {d16, d18, d20, d22}, [r0]!
+ vld4.32 {d17, d19, d21, d23}, [r0]!
+
+@ CHECK: vld4.8 {d16, d17, d18, d19}, [r0, :64]@ encoding: [0x1f,0x00,0x60,0xf4]
+@ CHECK: vld4.16 {d16, d17, d18, d19}, [r0,:128]@ encoding:[0x6f,0x00,0x60,0xf4]
+@ CHECK: vld4.32 {d16, d17, d18, d19}, [r0,:256]@ encoding:[0xbf,0x00,0x60,0xf4]
+@ CHECK: vld4.8 {d16, d18, d20, d22}, [r0,:256]!@ encoding:[0x3d,0x01,0x60,0xf4]
+@ CHECK: vld4.8 {d17, d19, d21, d23}, [r0,:256]!@ encoding:[0x3d,0x11,0x60,0xf4]
+@ CHECK: vld4.16 {d16, d18, d20, d22}, [r0]! @ encoding: [0x4d,0x01,0x60,0xf4]
+@ CHECK: vld4.16 {d17, d19, d21, d23}, [r0]! @ encoding: [0x4d,0x11,0x60,0xf4]
+@ CHECK: vld4.32 {d16, d18, d20, d22}, [r0]! @ encoding: [0x8d,0x01,0x60,0xf4]
+@ CHECK: vld4.32 {d17, d19, d21, d23}, [r0]! @ encoding: [0x8d,0x11,0x60,0xf4]
+
+
+ vld1.8 {d16[3]}, [r0]
+ vld1.16 {d16[2]}, [r0, :16]
+ vld1.32 {d16[1]}, [r0, :32]
@ CHECK: vld1.8 {d16[3]}, [r0] @ encoding: [0x6f,0x00,0xe0,0xf4]
- vld1.8 {d16[3]}, [r0]
-@ CHECK: vld1.16 {d16[2]}, [r0, :16] @ encoding: [0x9f,0x04,0xe0,0xf4]
- vld1.16 {d16[2]}, [r0, :16]
-@ CHECK: vld1.32 {d16[1]}, [r0, :32] @ encoding: [0xbf,0x08,0xe0,0xf4]
- vld1.32 {d16[1]}, [r0, :32]
+@ CHECK: vld1.16 {d16[2]}, [r0, :16] @ encoding: [0x9f,0x04,0xe0,0xf4]
+@ CHECK: vld1.32 {d16[1]}, [r0, :32] @ encoding: [0xbf,0x08,0xe0,0xf4]
+
+
+ vld2.8 {d16[1], d17[1]}, [r0, :16]
+ vld2.16 {d16[1], d17[1]}, [r0, :32]
+ vld2.32 {d16[1], d17[1]}, [r0]
+ vld2.16 {d17[1], d19[1]}, [r0]
+ vld2.32 {d17[0], d19[0]}, [r0, :64]
@ CHECK: vld2.8 {d16[1], d17[1]}, [r0, :16] @ encoding: [0x3f,0x01,0xe0,0xf4]
- vld2.8 {d16[1], d17[1]}, [r0, :16]
-@ CHECK: vld2.16 {d16[1], d17[1]}, [r0, :32] @ encoding: [0x5f,0x05,0xe0,0xf4]
- vld2.16 {d16[1], d17[1]}, [r0, :32]
-@ CHECK: vld2.32 {d16[1], d17[1]}, [r0] @ encoding: [0x8f,0x09,0xe0,0xf4]
- vld2.32 {d16[1], d17[1]}, [r0]
-@ CHECK: vld2.16 {d17[1], d19[1]}, [r0] @ encoding: [0x6f,0x15,0xe0,0xf4]
- vld2.16 {d17[1], d19[1]}, [r0]
-@ CHECK: vld2.32 {d17[0], d19[0]}, [r0, :64] @ encoding: [0x5f,0x19,0xe0,0xf4]
- vld2.32 {d17[0], d19[0]}, [r0, :64]
+@ CHECK: vld2.16 {d16[1], d17[1]}, [r0, :32] @ encoding: [0x5f,0x05,0xe0,0xf4]
+@ CHECK: vld2.32 {d16[1], d17[1]}, [r0] @ encoding: [0x8f,0x09,0xe0,0xf4]
+@ CHECK: vld2.16 {d17[1], d19[1]}, [r0] @ encoding: [0x6f,0x15,0xe0,0xf4]
+@ CHECK: vld2.32 {d17[0], d19[0]}, [r0, :64] @ encoding: [0x5f,0x19,0xe0,0xf4]
+
+
+ vld3.8 {d16[1], d17[1], d18[1]}, [r0]
+ vld3.16 {d16[1], d17[1], d18[1]}, [r0]
+ vld3.32 {d16[1], d17[1], d18[1]}, [r0]
+ vld3.16 {d16[1], d18[1], d20[1]}, [r0]
+ vld3.32 {d17[1], d19[1], d21[1]}, [r0]
@ CHECK: vld3.8 {d16[1], d17[1], d18[1]}, [r0] @ encoding: [0x2f,0x02,0xe0,0xf4]
- vld3.8 {d16[1], d17[1], d18[1]}, [r0]
-@ CHECK: vld3.16 {d16[1], d17[1], d18[1]}, [r0] @ encoding: [0x4f,0x06,0xe0,0xf4]
- vld3.16 {d16[1], d17[1], d18[1]}, [r0]
-@ CHECK: vld3.32 {d16[1], d17[1], d18[1]}, [r0] @ encoding: [0x8f,0x0a,0xe0,0xf4]
- vld3.32 {d16[1], d17[1], d18[1]}, [r0]
-@ CHECK: vld3.16 {d16[1], d18[1], d20[1]}, [r0] @ encoding: [0x6f,0x06,0xe0,0xf4]
- vld3.16 {d16[1], d18[1], d20[1]}, [r0]
-@ CHECK: vld3.32 {d17[1], d19[1], d21[1]}, [r0] @ encoding: [0xcf,0x1a,0xe0,0xf4]
- vld3.32 {d17[1], d19[1], d21[1]}, [r0]
+@ CHECK: vld3.16 {d16[1], d17[1], d18[1]}, [r0]@ encoding: [0x4f,0x06,0xe0,0xf4]
+@ CHECK: vld3.32 {d16[1], d17[1], d18[1]}, [r0]@ encoding: [0x8f,0x0a,0xe0,0xf4]
+@ CHECK: vld3.16 {d16[1], d18[1], d20[1]}, [r0]@ encoding: [0x6f,0x06,0xe0,0xf4]
+@ CHECK: vld3.32 {d17[1], d19[1], d21[1]}, [r0]@ encoding: [0xcf,0x1a,0xe0,0xf4]
+
+
+ vld4.8 {d16[1], d17[1], d18[1], d19[1]}, [r0, :32]
+ vld4.16 {d16[1], d17[1], d18[1], d19[1]}, [r0]
+ vld4.32 {d16[1], d17[1], d18[1], d19[1]}, [r0, :128]
+ vld4.16 {d16[1], d18[1], d20[1], d22[1]}, [r0, :64]
+ vld4.32 {d17[0], d19[0], d21[0], d23[0]}, [r0]
@ CHECK: vld4.8 {d16[1], d17[1], d18[1], d19[1]}, [r0, :32] @ encoding: [0x3f,0x03,0xe0,0xf4]
- vld4.8 {d16[1], d17[1], d18[1], d19[1]}, [r0, :32]
-@ CHECK: vld4.16 {d16[1], d17[1], d18[1], d19[1]}, [r0] @ encoding: [0x4f,0x07,0xe0,0xf4]
- vld4.16 {d16[1], d17[1], d18[1], d19[1]}, [r0]
-@ CHECK: vld4.32 {d16[1], d17[1], d18[1], d19[1]}, [r0, :128] @ encoding: [0xaf,0x0b,0xe0,0xf4]
- vld4.32 {d16[1], d17[1], d18[1], d19[1]}, [r0, :128]
-@ CHECK: vld4.16 {d16[1], d18[1], d20[1], d22[1]}, [r0, :64] @ encoding: [0x7f,0x07,0xe0,0xf4]
- vld4.16 {d16[1], d18[1], d20[1], d22[1]}, [r0, :64]
-@ CHECK: vld4.32 {d17[0], d19[0], d21[0], d23[0]}, [r0] @ encoding: [0x4f,0x1b,0xe0,0xf4]
- vld4.32 {d17[0], d19[0], d21[0], d23[0]}, [r0]
+@ CHECK: vld4.16 {d16[1], d17[1], d18[1], d19[1]}, [r0] @ encoding: [0x4f,0x07,0xe0,0xf4]
+@ CHECK: vld4.32 {d16[1], d17[1], d18[1], d19[1]}, [r0, :128] @ encoding: [0xaf,0x0b,0xe0,0xf4]
+@ CHECK: vld4.16 {d16[1], d18[1], d20[1], d22[1]}, [r0, :64] @ encoding: [0x7f,0x07,0xe0,0xf4]
+@ CHECK: vld4.32 {d17[0], d19[0], d21[0], d23[0]}, [r0] @ encoding: [0x4f,0x1b,0xe0,0xf4]
diff --git a/test/MC/ARM/neont2-absdiff-encoding.s b/test/MC/ARM/neont2-absdiff-encoding.s
index 2096357..4313483 100644
--- a/test/MC/ARM/neont2-absdiff-encoding.s
+++ b/test/MC/ARM/neont2-absdiff-encoding.s
@@ -1,86 +1,91 @@
-@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s
-@ XFAIL: *
-@ NOTE: This currently fails because the ASM parser doesn't parse vabal.
+@RUN: llvm-mc -triple thumbv7-unknown-unknown -show-encoding < %s | FileCheck %s
.code 16
-@ CHECK: vabd.s8 d16, d16, d17 @ encoding: [0xa1,0x07,0x40,0xef]
vabd.s8 d16, d16, d17
-@ CHECK: vabd.s16 d16, d16, d17 @ encoding: [0xa1,0x07,0x50,0xef]
vabd.s16 d16, d16, d17
-@ CHECK: vabd.s32 d16, d16, d17 @ encoding: [0xa1,0x07,0x60,0xef]
vabd.s32 d16, d16, d17
-@ CHECK: vabd.u8 d16, d16, d17 @ encoding: [0xa1,0x07,0x40,0xff]
vabd.u8 d16, d16, d17
-@ CHECK: vabd.u16 d16, d16, d17 @ encoding: [0xa1,0x07,0x50,0xff]
vabd.u16 d16, d16, d17
- @ CHECK: vabd.u32 d16, d16, d17 @ encoding: [0xa1,0x07,0x60,0xff]
vabd.u32 d16, d16, d17
-@ CHECK: vabd.f32 d16, d16, d17 @ encoding: [0xa1,0x0d,0x60,0xff]
vabd.f32 d16, d16, d17
-@ CHECK: vabd.s8 q8, q8, q9 @ encoding: [0xe2,0x07,0x40,0xef]
vabd.s8 q8, q8, q9
-@ CHECK: vabd.s16 q8, q8, q9 @ encoding: [0xe2,0x07,0x50,0xef]
vabd.s16 q8, q8, q9
-@ CHECK: vabd.s32 q8, q8, q9 @ encoding: [0xe2,0x07,0x60,0xef]
vabd.s32 q8, q8, q9
-@ CHECK: vabd.u8 q8, q8, q9 @ encoding: [0xe2,0x07,0x40,0xff]
vabd.u8 q8, q8, q9
-@ CHECK: vabd.u16 q8, q8, q9 @ encoding: [0xe2,0x07,0x50,0xff]
vabd.u16 q8, q8, q9
-@ CHECK: vabd.u32 q8, q8, q9 @ encoding: [0xe2,0x07,0x60,0xff]
vabd.u32 q8, q8, q9
-@ CHECK: vabd.f32 q8, q8, q9 @ encoding: [0xe2,0x0d,0x60,0xff]
vabd.f32 q8, q8, q9
-@ CHECK: vabdl.s8 q8, d16, d17 @ encoding: [0xa1,0x07,0xc0,0xef]
+@ CHECK: vabd.s8 d16, d16, d17 @ encoding: [0x40,0xef,0xa1,0x07]
+@ CHECK: vabd.s16 d16, d16, d17 @ encoding: [0x50,0xef,0xa1,0x07]
+@ CHECK: vabd.s32 d16, d16, d17 @ encoding: [0x60,0xef,0xa1,0x07]
+@ CHECK: vabd.u8 d16, d16, d17 @ encoding: [0x40,0xff,0xa1,0x07]
+@ CHECK: vabd.u16 d16, d16, d17 @ encoding: [0x50,0xff,0xa1,0x07]
+@ CHECK: vabd.u32 d16, d16, d17 @ encoding: [0x60,0xff,0xa1,0x07]
+@ CHECK: vabd.f32 d16, d16, d17 @ encoding: [0x60,0xff,0xa1,0x0d]
+@ CHECK: vabd.s8 q8, q8, q9 @ encoding: [0x40,0xef,0xe2,0x07]
+@ CHECK: vabd.s16 q8, q8, q9 @ encoding: [0x50,0xef,0xe2,0x07]
+@ CHECK: vabd.s32 q8, q8, q9 @ encoding: [0x60,0xef,0xe2,0x07]
+@ CHECK: vabd.u8 q8, q8, q9 @ encoding: [0x40,0xff,0xe2,0x07]
+@ CHECK: vabd.u16 q8, q8, q9 @ encoding: [0x50,0xff,0xe2,0x07]
+@ CHECK: vabd.u32 q8, q8, q9 @ encoding: [0x60,0xff,0xe2,0x07]
+@ CHECK: vabd.f32 q8, q8, q9 @ encoding: [0x60,0xff,0xe2,0x0d]
+
+
vabdl.s8 q8, d16, d17
-@ CHECK: vabdl.s16 q8, d16, d17 @ encoding: [0xa1,0x07,0xd0,0xef]
vabdl.s16 q8, d16, d17
-@ CHECK: vabdl.s32 q8, d16, d17 @ encoding: [0xa1,0x07,0xe0,0xef]
vabdl.s32 q8, d16, d17
-@ CHECK: vabdl.u8 q8, d16, d17 @ encoding: [0xa1,0x07,0xc0,0xff]
vabdl.u8 q8, d16, d17
-@ CHECK: vabdl.u16 q8, d16, d17 @ encoding: [0xa1,0x07,0xd0,0xff]
vabdl.u16 q8, d16, d17
-@ CHECK: vabdl.u32 q8, d16, d17 @ encoding: [0xa1,0x07,0xe0,0xff]
vabdl.u32 q8, d16, d17
-@ CHECK: vaba.s8 d16, d18, d17 @ encoding: [0xb1,0x07,0x42,0xef]
+@ CHECK: vabdl.s8 q8, d16, d17 @ encoding: [0xc0,0xef,0xa1,0x07]
+@ CHECK: vabdl.s16 q8, d16, d17 @ encoding: [0xd0,0xef,0xa1,0x07]
+@ CHECK: vabdl.s32 q8, d16, d17 @ encoding: [0xe0,0xef,0xa1,0x07]
+@ CHECK: vabdl.u8 q8, d16, d17 @ encoding: [0xc0,0xff,0xa1,0x07]
+@ CHECK: vabdl.u16 q8, d16, d17 @ encoding: [0xd0,0xff,0xa1,0x07]
+@ CHECK: vabdl.u32 q8, d16, d17 @ encoding: [0xe0,0xff,0xa1,0x07]
+
+
vaba.s8 d16, d18, d17
-@ CHECK: vaba.s16 d16, d18, d17 @ encoding: [0xb1,0x07,0x52,0xef]
vaba.s16 d16, d18, d17
-@ CHECK: vaba.s32 d16, d18, d17 @ encoding: [0xb1,0x07,0x62,0xef]
vaba.s32 d16, d18, d17
-@ CHECK: vaba.u8 d16, d18, d17 @ encoding: [0xb1,0x07,0x42,0xff]
vaba.u8 d16, d18, d17
-@ CHECK: vaba.u16 d16, d18, d17 @ encoding: [0xb1,0x07,0x52,0xff]
vaba.u16 d16, d18, d17
-@ CHECK: vaba.u32 d16, d18, d17 @ encoding: [0xb1,0x07,0x62,0xff]
vaba.u32 d16, d18, d17
-@ CHECK: vaba.s8 q9, q8, q10 @ encoding: [0xf4,0x27,0x40,0xef]
vaba.s8 q9, q8, q10
-@ CHECK: vaba.s16 q9, q8, q10 @ encoding: [0xf4,0x27,0x50,0xef]
vaba.s16 q9, q8, q10
-@ CHECK: vaba.s32 q9, q8, q10 @ encoding: [0xf4,0x27,0x60,0xef]
vaba.s32 q9, q8, q10
-@ CHECK: vaba.u8 q9, q8, q10 @ encoding: [0xf4,0x27,0x40,0xff]
vaba.u8 q9, q8, q10
-@ CHECK: vaba.u16 q9, q8, q10 @ encoding: [0xf4,0x27,0x50,0xff]
vaba.u16 q9, q8, q10
-@ CHECK: vaba.u32 q9, q8, q10 @ encoding: [0xf4,0x27,0x60,0xff]
vaba.u32 q9, q8, q10
-@ CHECK: vabal.s8 q8, d19, d18 @ encoding: [0xa2,0x05,0xc3,0xef]
+@ CHECK: vaba.s8 d16, d18, d17 @ encoding: [0x42,0xef,0xb1,0x07]
+@ CHECK: vaba.s16 d16, d18, d17 @ encoding: [0x52,0xef,0xb1,0x07]
+@ CHECK: vaba.s32 d16, d18, d17 @ encoding: [0x62,0xef,0xb1,0x07]
+@ CHECK: vaba.u8 d16, d18, d17 @ encoding: [0x42,0xff,0xb1,0x07]
+@ CHECK: vaba.u16 d16, d18, d17 @ encoding: [0x52,0xff,0xb1,0x07]
+@ CHECK: vaba.u32 d16, d18, d17 @ encoding: [0x62,0xff,0xb1,0x07]
+@ CHECK: vaba.s8 q9, q8, q10 @ encoding: [0x40,0xef,0xf4,0x27]
+@ CHECK: vaba.s16 q9, q8, q10 @ encoding: [0x50,0xef,0xf4,0x27]
+@ CHECK: vaba.s32 q9, q8, q10 @ encoding: [0x60,0xef,0xf4,0x27]
+@ CHECK: vaba.u8 q9, q8, q10 @ encoding: [0x40,0xff,0xf4,0x27]
+@ CHECK: vaba.u16 q9, q8, q10 @ encoding: [0x50,0xff,0xf4,0x27]
+@ CHECK: vaba.u32 q9, q8, q10 @ encoding: [0x60,0xff,0xf4,0x27]
+
+
vabal.s8 q8, d19, d18
-@ CHECK: vabal.s16 q8, d19, d18 @ encoding: [0xa2,0x05,0xd3,0xef]
vabal.s16 q8, d19, d18
-@ CHECK: vabal.s32 q8, d19, d18 @ encoding: [0xa2,0x05,0xe3,0xef]
vabal.s32 q8, d19, d18
-@ CHECK: vabal.u8 q8, d19, d18 @ encoding: [0xa2,0x05,0xc3,0xff]
vabal.u8 q8, d19, d18
-@ CHECK: vabal.u16 q8, d19, d18 @ encoding: [0xa2,0x05,0xd3,0xff]
vabal.u16 q8, d19, d18
-@ CHECK: vabal.u32 q8, d19, d18 @ encoding: [0xa2,0x05,0xe3,0xff]
vabal.u32 q8, d19, d18
+@ CHECK: vabal.s8 q8, d19, d18 @ encoding: [0xc3,0xef,0xa2,0x05]
+@ CHECK: vabal.s16 q8, d19, d18 @ encoding: [0xd3,0xef,0xa2,0x05]
+@ CHECK: vabal.s32 q8, d19, d18 @ encoding: [0xe3,0xef,0xa2,0x05]
+@ CHECK: vabal.u8 q8, d19, d18 @ encoding: [0xc3,0xff,0xa2,0x05]
+@ CHECK: vabal.u16 q8, d19, d18 @ encoding: [0xd3,0xff,0xa2,0x05]
+@ CHECK: vabal.u32 q8, d19, d18 @ encoding: [0xe3,0xff,0xa2,0x05]
+
diff --git a/test/MC/ARM/neont2-bitcount-encoding.s b/test/MC/ARM/neont2-bitcount-encoding.s
index 4280cbd..bd525f1 100644
--- a/test/MC/ARM/neont2-bitcount-encoding.s
+++ b/test/MC/ARM/neont2-bitcount-encoding.s
@@ -1,34 +1,38 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s
-@ XFAIL: *
.code 16
-@ CHECK: vcnt.8 d16, d16 @ encoding: [0x20,0x05,0xf0,0xff]
vcnt.8 d16, d16
-@ CHECK: vcnt.8 q8, q8 @ encoding: [0x60,0x05,0xf0,0xff]
vcnt.8 q8, q8
-@ CHECK: vclz.i8 d16, d16 @ encoding: [0xa0,0x04,0xf0,0xff]
+
+@ CHECK: vcnt.8 d16, d16 @ encoding: [0xf0,0xff,0x20,0x05]
+@ CHECK: vcnt.8 q8, q8 @ encoding: [0xf0,0xff,0x60,0x05]
+
vclz.i8 d16, d16
-@ CHECK: vclz.i16 d16, d16 @ encoding: [0xa0,0x04,0xf4,0xff]
vclz.i16 d16, d16
-@ CHECK: vclz.i32 d16, d16 @ encoding: [0xa0,0x04,0xf8,0xff]
vclz.i32 d16, d16
-@ CHECK: vclz.i8 q8, q8 @ encoding: [0xe0,0x04,0xf0,0xff]
vclz.i8 q8, q8
-@ CHECK: vclz.i16 q8, q8 @ encoding: [0xe0,0x04,0xf4,0xff]
vclz.i16 q8, q8
-@ CHECK: vclz.i32 q8, q8 @ encoding: [0xe0,0x04,0xf8,0xff]
vclz.i32 q8, q8
-@ CHECK: vcls.s8 d16, d16 @ encoding: [0x20,0x04,0xf0,0xff]
+
+@ CHECK: vclz.i8 d16, d16 @ encoding: [0xf0,0xff,0xa0,0x04]
+@ CHECK: vclz.i16 d16, d16 @ encoding: [0xf4,0xff,0xa0,0x04]
+@ CHECK: vclz.i32 d16, d16 @ encoding: [0xf8,0xff,0xa0,0x04]
+@ CHECK: vclz.i8 q8, q8 @ encoding: [0xf0,0xff,0xe0,0x04]
+@ CHECK: vclz.i16 q8, q8 @ encoding: [0xf4,0xff,0xe0,0x04]
+@ CHECK: vclz.i32 q8, q8 @ encoding: [0xf8,0xff,0xe0,0x04]
+
vcls.s8 d16, d16
-@ CHECK: vcls.s16 d16, d16 @ encoding: [0x20,0x04,0xf4,0xff]
vcls.s16 d16, d16
-@ CHECK: vcls.s32 d16, d16 @ encoding: [0x20,0x04,0xf8,0xff]
vcls.s32 d16, d16
-@ CHECK: vcls.s8 q8, q8 @ encoding: [0x60,0x04,0xf0,0xff]
vcls.s8 q8, q8
-@ CHECK: vcls.s16 q8, q8 @ encoding: [0x60,0x04,0xf4,0xff]
vcls.s16 q8, q8
-@ CHECK: vcls.s32 q8, q8 @ encoding: [0x60,0x04,0xf8,0xff]
vcls.s32 q8, q8
+@ CHECK: vcls.s8 d16, d16 @ encoding: [0xf0,0xff,0x20,0x04]
+@ CHECK: vcls.s16 d16, d16 @ encoding: [0xf4,0xff,0x20,0x04]
+@ CHECK: vcls.s32 d16, d16 @ encoding: [0xf8,0xff,0x20,0x04]
+@ CHECK: vcls.s8 q8, q8 @ encoding: [0xf0,0xff,0x60,0x04]
+@ CHECK: vcls.s16 q8, q8 @ encoding: [0xf4,0xff,0x60,0x04]
+@ CHECK: vcls.s32 q8, q8 @ encoding: [0xf8,0xff,0x60,0x04]
+
diff --git a/test/MC/ARM/neont2-bitwise-encoding.s b/test/MC/ARM/neont2-bitwise-encoding.s
index 3acd7a8..175873b 100644
--- a/test/MC/ARM/neont2-bitwise-encoding.s
+++ b/test/MC/ARM/neont2-bitwise-encoding.s
@@ -1,49 +1,55 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s
-@ XFAIL: *
.code 16
-@ CHECK: vand d16, d17, d16 @ encoding: [0xb0,0x01,0x41,0xef]
vand d16, d17, d16
-@ CHECK: vand q8, q8, q9 @ encoding: [0xf2,0x01,0x40,0xef]
vand q8, q8, q9
-@ CHECK: veor d16, d17, d16 @ encoding: [0xb0,0x01,0x41,0xff]
+@ CHECK: vand d16, d17, d16 @ encoding: [0x41,0xef,0xb0,0x01]
+@ CHECK: vand q8, q8, q9 @ encoding: [0x40,0xef,0xf2,0x01]
+
veor d16, d17, d16
-@ CHECK: veor q8, q8, q9 @ encoding: [0xf2,0x01,0x40,0xff]
veor q8, q8, q9
-@ CHECK: vorr d16, d17, d16 @ encoding: [0xb0,0x01,0x61,0xef]
+@ CHECK: veor d16, d17, d16 @ encoding: [0x41,0xff,0xb0,0x01]
+@ CHECK: veor q8, q8, q9 @ encoding: [0x40,0xff,0xf2,0x01]
+
+
vorr d16, d17, d16
-@ CHECK: vorr q8, q8, q9 @ encoding: [0xf2,0x01,0x60,0xef]
vorr q8, q8, q9
-@ CHECK: vorr.i32 d16, #0x1000000 @ encoding: [0x11,0x07,0xc0,0xef]
- vorr.i32 d16, #0x1000000
-@ CHECK: vorr.i32 q8, #0x1000000 @ encoding: [0x51,0x07,0xc0,0xef]
- vorr.i32 q8, #0x1000000
-@ CHECK: vorr.i32 q8, #0x0 @ encoding: [0x50,0x01,0xc0,0xef]
- vorr.i32 q8, #0x0
-
-@ CHECK: vbic d16, d17, d16 @ encoding: [0xb0,0x01,0x51,0xef]
+@ vorr.i32 d16, #0x1000000
+@ vorr.i32 q8, #0x1000000
+@ vorr.i32 q8, #0x0
+
+@ CHECK: vorr d16, d17, d16 @ encoding: [0x61,0xef,0xb0,0x01]
+@ CHECK: vorr q8, q8, q9 @ encoding: [0x60,0xef,0xf2,0x01]
+
+
vbic d16, d17, d16
-@ CHECK: vbic q8, q8, q9 @ encoding: [0xf2,0x01,0x50,0xef]
vbic q8, q8, q9
-@ CHECK: vbic.i32 d16, #0xFF000000 @ encoding: [0x3f,0x07,0xc7,0xff]
- vbic.i32 d16, #0xFF000000
-@ CHECK: vbic.i32 q8, #0xFF000000 @ encoding: [0x7f,0x07,0xc7,0xff]
- vbic.i32 q8, #0xFF000000
+@ vbic.i32 d16, #0xFF000000
+@ vbic.i32 q8, #0xFF000000
+
+@ CHECK: vbic d16, d17, d16 @ encoding: [0x51,0xef,0xb0,0x01]
+@ CHECK: vbic q8, q8, q9 @ encoding: [0x50,0xef,0xf2,0x01]
+
-@ CHECK: vorn d16, d17, d16 @ encoding: [0xb0,0x01,0x71,0xef]
vorn d16, d17, d16
-@ CHECK: vorn q8, q8, q9 @ encoding: [0xf2,0x01,0x70,0xef]
vorn q8, q8, q9
-@ CHECK: vmvn d16, d16 @ encoding: [0xa0,0x05,0xf0,0xff]
+@ CHECK: vorn d16, d17, d16 @ encoding: [0x71,0xef,0xb0,0x01]
+@ CHECK: vorn q8, q8, q9 @ encoding: [0x70,0xef,0xf2,0x01]
+
+
vmvn d16, d16
-@ CHECK: vmvn q8, q8 @ encoding: [0xe0,0x05,0xf0,0xff]
vmvn q8, q8
-@ CHECK: vbsl d18, d17, d16 @ encoding: [0xb0,0x21,0x51,0xff]
+@ CHECK: vmvn d16, d16 @ encoding: [0xf0,0xff,0xa0,0x05]
+@ CHECK: vmvn q8, q8 @ encoding: [0xf0,0xff,0xe0,0x05]
+
+
vbsl d18, d17, d16
-@ CHECK: vbsl q8, q10, q9 @ encoding: [0xf2,0x01,0x54,0xff]
vbsl q8, q10, q9
+
+@ CHECK: vbsl d18, d17, d16 @ encoding: [0x51,0xff,0xb0,0x21]
+@ CHECK: vbsl q8, q10, q9 @ encoding: [0x54,0xff,0xf2,0x01]
diff --git a/test/MC/ARM/neont2-dup-encoding.s b/test/MC/ARM/neont2-dup-encoding.s
index da6e78f..bf25d70 100644
--- a/test/MC/ARM/neont2-dup-encoding.s
+++ b/test/MC/ARM/neont2-dup-encoding.s
@@ -1,29 +1,43 @@
-@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s
-@ XFAIL: *
+@RUN: llvm-mc -triple thumbv7-unknown-unknown -show-encoding < %s | FileCheck %s
.code 16
-@ CHECK: vdup.8 d16, r0 @ encoding: [0x90,0x0b,0xc0,0xee]
- vdup.8 d16, r0
-@ CHECK: vdup.16 d16, r0 @ encoding: [0xb0,0x0b,0x80,0xee]
- vdup.16 d16, r0
-@ CHECK: vdup.32 d16, r0 @ encoding: [0x90,0x0b,0x80,0xee]
- vdup.32 d16, r0
-@ CHECK: vdup.8 q8, r0 @ encoding: [0x90,0x0b,0xe0,0xee]
- vdup.8 q8, r0
-@ CHECK: vdup.16 q8, r0 @ encoding: [0xb0,0x0b,0xa0,0xee]
- vdup.16 q8, r0
-@ CHECK: vdup.32 q8, r0 @ encoding: [0x90,0x0b,0xa0,0xee]
- vdup.32 q8, r0
-@ CHECK: vdup.8 d16, d16[1] @ encoding: [0x20,0x0c,0xf3,0xff]
- vdup.8 d16, d16[1]
-@ CHECK: vdup.16 d16, d16[1] @ encoding: [0x20,0x0c,0xf6,0xff]
- vdup.16 d16, d16[1]
-@ CHECK: vdup.32 d16, d16[1] @ encoding: [0x20,0x0c,0xfc,0xff]
- vdup.32 d16, d16[1]
-@ CHECK: vdup.8 q8, d16[1] @ encoding: [0x60,0x0c,0xf3,0xff]
- vdup.8 q8, d16[1]
-@ CHECK: vdup.16 q8, d16[1] @ encoding: [0x60,0x0c,0xf6,0xff]
- vdup.16 q8, d16[1]
-@ CHECK: vdup.32 q8, d16[1] @ encoding: [0x60,0x0c,0xfc,0xff]
- vdup.32 q8, d16[1]
+ vdup.8 d16, r1
+ vdup.16 d15, r2
+ vdup.32 d14, r3
+ vdup.8 q9, r4
+ vdup.16 q8, r5
+ vdup.32 q7, r6
+
+@ CHECK: vdup.8 d16, r1 @ encoding: [0xc0,0xee,0x90,0x1b]
+@ CHECK: vdup.16 d15, r2 @ encoding: [0x8f,0xee,0x30,0x2b]
+@ CHECK: vdup.32 d14, r3 @ encoding: [0x8e,0xee,0x10,0x3b]
+@ CHECK: vdup.8 q9, r4 @ encoding: [0xe2,0xee,0x90,0x4b]
+@ CHECK: vdup.16 q8, r5 @ encoding: [0xa0,0xee,0xb0,0x5b]
+@ CHECK: vdup.32 q7, r6 @ encoding: [0xae,0xee,0x10,0x6b]
+
+ vdup.8 d16, d11[0]
+ vdup.16 d17, d12[0]
+ vdup.32 d18, d13[0]
+ vdup.8 q3, d10[0]
+ vdup.16 q9, d9[0]
+ vdup.32 q8, d8[0]
+ vdup.8 d16, d11[1]
+ vdup.16 d17, d12[1]
+ vdup.32 d18, d13[1]
+ vdup.8 q3, d10[1]
+ vdup.16 q9, d9[1]
+ vdup.32 q8, d8[1]
+
+@ CHECK: vdup.8 d16, d11[0] @ encoding: [0xf1,0xff,0x0b,0x0c]
+@ CHECK: vdup.16 d17, d12[0] @ encoding: [0xf2,0xff,0x0c,0x1c]
+@ CHECK: vdup.32 d18, d13[0] @ encoding: [0xf4,0xff,0x0d,0x2c]
+@ CHECK: vdup.8 q3, d10[0] @ encoding: [0xb1,0xff,0x4a,0x6c]
+@ CHECK: vdup.16 q9, d9[0] @ encoding: [0xf2,0xff,0x49,0x2c]
+@ CHECK: vdup.32 q8, d8[0] @ encoding: [0xf4,0xff,0x48,0x0c]
+@ CHECK: vdup.8 d16, d11[1] @ encoding: [0xf3,0xff,0x0b,0x0c]
+@ CHECK: vdup.16 d17, d12[1] @ encoding: [0xf6,0xff,0x0c,0x1c]
+@ CHECK: vdup.32 d18, d13[1] @ encoding: [0xfc,0xff,0x0d,0x2c]
+@ CHECK: vdup.8 q3, d10[1] @ encoding: [0xb3,0xff,0x4a,0x6c]
+@ CHECK: vdup.16 q9, d9[1] @ encoding: [0xf6,0xff,0x49,0x2c]
+@ CHECK: vdup.32 q8, d8[1] @ encoding: [0xfc,0xff,0x48,0x0c]
diff --git a/test/MC/ARM/neont2-mul-accum-encoding.s b/test/MC/ARM/neont2-mul-accum-encoding.s
index e21c67d..be4bf79 100644
--- a/test/MC/ARM/neont2-mul-accum-encoding.s
+++ b/test/MC/ARM/neont2-mul-accum-encoding.s
@@ -1,69 +1,84 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s
-@ XFAIL: *
.code 16
-@ CHECK: vmla.i8 d16, d18, d17 @ encoding: [0xa1,0x09,0x42,0xef]
vmla.i8 d16, d18, d17
-@ CHECK: vmla.i16 d16, d18, d17 @ encoding: [0xa1,0x09,0x52,0xef]
vmla.i16 d16, d18, d17
-@ CHECK: vmla.i16 d16, d18, d17 @ encoding: [0xa1,0x09,0x52,0xef]
vmla.i32 d16, d18, d17
-@ CHECK: vmla.f32 d16, d18, d17 @ encoding: [0xb1,0x0d,0x42,0xef]
vmla.f32 d16, d18, d17
-@ CHECK: vmla.i8 q9, q8, q10 @ encoding: [0xe4,0x29,0x40,0xef]
vmla.i8 q9, q8, q10
-@ CHECK: vmla.i16 q9, q8, q10 @ encoding: [0xe4,0x29,0x50,0xef]
vmla.i16 q9, q8, q10
-@ CHECK: vmla.i32 q9, q8, q10 @ encoding: [0xe4,0x29,0x60,0xef]
vmla.i32 q9, q8, q10
-@ CHECK: vmla.f32 q9, q8, q10 @ encoding: [0xf4,0x2d,0x40,0xef]
vmla.f32 q9, q8, q10
-@ CHECK: vmlal.s8 q8, d19, d18 @ encoding: [0xa2,0x08,0xc3,0xef]
+
+@ CHECK: vmla.i8 d16, d18, d17 @ encoding: [0x42,0xef,0xa1,0x09]
+@ CHECK: vmla.i16 d16, d18, d17 @ encoding: [0x52,0xef,0xa1,0x09]
+@ CHECK: vmla.i32 d16, d18, d17 @ encoding: [0x62,0xef,0xa1,0x09]
+@ CHECK: vmla.f32 d16, d18, d17 @ encoding: [0x42,0xef,0xb1,0x0d]
+@ CHECK: vmla.i8 q9, q8, q10 @ encoding: [0x40,0xef,0xe4,0x29]
+@ CHECK: vmla.i16 q9, q8, q10 @ encoding: [0x50,0xef,0xe4,0x29]
+@ CHECK: vmla.i32 q9, q8, q10 @ encoding: [0x60,0xef,0xe4,0x29]
+@ CHECK: vmla.f32 q9, q8, q10 @ encoding: [0x40,0xef,0xf4,0x2d]
+
+
vmlal.s8 q8, d19, d18
-@ CHECK: vmlal.s16 q8, d19, d18 @ encoding: [0xa2,0x08,0xd3,0xef]
vmlal.s16 q8, d19, d18
-@ CHECK: vmlal.s32 q8, d19, d18 @ encoding: [0xa2,0x08,0xe3,0xef]
vmlal.s32 q8, d19, d18
-@ CHECK: vmlal.u8 q8, d19, d18 @ encoding: [0xa2,0x08,0xc3,0xff]
vmlal.u8 q8, d19, d18
-@ CHECK: vmlal.u16 q8, d19, d18 @ encoding: [0xa2,0x08,0xd3,0xff]
vmlal.u16 q8, d19, d18
-@ CHECK: vmlal.u32 q8, d19, d18 @ encoding: [0xa2,0x08,0xe3,0xff]
vmlal.u32 q8, d19, d18
-@ CHECK: vqdmlal.s16 q8, d19, d18 @ encoding: [0xa2,0x09,0xd3,0xef]
+
+@ CHECK: vmlal.s8 q8, d19, d18 @ encoding: [0xc3,0xef,0xa2,0x08]
+@ CHECK: vmlal.s16 q8, d19, d18 @ encoding: [0xd3,0xef,0xa2,0x08]
+@ CHECK: vmlal.s32 q8, d19, d18 @ encoding: [0xe3,0xef,0xa2,0x08]
+@ CHECK: vmlal.u8 q8, d19, d18 @ encoding: [0xc3,0xff,0xa2,0x08]
+@ CHECK: vmlal.u16 q8, d19, d18 @ encoding: [0xd3,0xff,0xa2,0x08]
+@ CHECK: vmlal.u32 q8, d19, d18 @ encoding: [0xe3,0xff,0xa2,0x08]
+
+
vqdmlal.s16 q8, d19, d18
-@ CHECK: vqdmlal.s32 q8, d19, d18 @ encoding: [0xa2,0x09,0xe3,0xef]
vqdmlal.s32 q8, d19, d18
-@ CHECK: vmls.i8 d16, d18, d17 @ encoding: [0xa1,0x09,0x42,0xff]
+
+@ CHECK: vqdmlal.s16 q8, d19, d18 @ encoding: [0xd3,0xef,0xa2,0x09]
+@ CHECK: vqdmlal.s32 q8, d19, d18 @ encoding: [0xe3,0xef,0xa2,0x09]
+
+
vmls.i8 d16, d18, d17
-@ CHECK: vmls.i16 d16, d18, d17 @ encoding: [0xa1,0x09,0x52,0xff]
vmls.i16 d16, d18, d17
-@ CHECK: vmls.i32 d16, d18, d17 @ encoding: [0xa1,0x09,0x62,0xff]
vmls.i32 d16, d18, d17
-@ CHECK: vmls.f32 d16, d18, d17 @ encoding: [0xb1,0x0d,0x62,0xef]
vmls.f32 d16, d18, d17
-@ CHECK: vmls.i8 q9, q8, q10 @ encoding: [0xe4,0x29,0x40,0xff]
vmls.i8 q9, q8, q10
-@ CHECK: vmls.i16 q9, q8, q10 @ encoding: [0xe4,0x29,0x50,0xff]
vmls.i16 q9, q8, q10
-@ CHECK: vmls.i32 q9, q8, q10 @ encoding: [0xe4,0x29,0x60,0xff]
vmls.i32 q9, q8, q10
-@ CHECK: vmls.f32 q9, q8, q10 @ encoding: [0xf4,0x2d,0x60,0xef]
vmls.f32 q9, q8, q10
-@ CHECK: vmlsl.s8 q8, d19, d18 @ encoding: [0xa2,0x0a,0xc3,0xef]
+
+@ CHECK: vmls.i8 d16, d18, d17 @ encoding: [0x42,0xff,0xa1,0x09]
+@ CHECK: vmls.i16 d16, d18, d17 @ encoding: [0x52,0xff,0xa1,0x09]
+@ CHECK: vmls.i32 d16, d18, d17 @ encoding: [0x62,0xff,0xa1,0x09]
+@ CHECK: vmls.f32 d16, d18, d17 @ encoding: [0x62,0xef,0xb1,0x0d]
+@ CHECK: vmls.i8 q9, q8, q10 @ encoding: [0x40,0xff,0xe4,0x29]
+@ CHECK: vmls.i16 q9, q8, q10 @ encoding: [0x50,0xff,0xe4,0x29]
+@ CHECK: vmls.i32 q9, q8, q10 @ encoding: [0x60,0xff,0xe4,0x29]
+@ CHECK: vmls.f32 q9, q8, q10 @ encoding: [0x60,0xef,0xf4,0x2d]
+
+
vmlsl.s8 q8, d19, d18
-@ CHECK: vmlsl.s16 q8, d19, d18 @ encoding: [0xa2,0x0a,0xd3,0xef]
vmlsl.s16 q8, d19, d18
-@ CHECK: vmlsl.s32 q8, d19, d18 @ encoding: [0xa2,0x0a,0xe3,0xef]
vmlsl.s32 q8, d19, d18
-@ CHECK: vmlsl.u8 q8, d19, d18 @ encoding: [0xa2,0x0a,0xc3,0xff]
vmlsl.u8 q8, d19, d18
-@ CHECK: vmlsl.u16 q8, d19, d18 @ encoding: [0xa2,0x0a,0xd3,0xff]
vmlsl.u16 q8, d19, d18
-@ CHECK: vmlsl.u32 q8, d19, d18 @ encoding: [0xa2,0x0a,0xe3,0xff]
vmlsl.u32 q8, d19, d18
-@ CHECK: vqdmlsl.s16 q8, d19, d18 @ encoding: [0xa2,0x0b,0xd3,0xef]
+
+@ CHECK: vmlsl.s8 q8, d19, d18 @ encoding: [0xc3,0xef,0xa2,0x0a]
+@ CHECK: vmlsl.s16 q8, d19, d18 @ encoding: [0xd3,0xef,0xa2,0x0a]
+@ CHECK: vmlsl.s32 q8, d19, d18 @ encoding: [0xe3,0xef,0xa2,0x0a]
+@ CHECK: vmlsl.u8 q8, d19, d18 @ encoding: [0xc3,0xff,0xa2,0x0a]
+@ CHECK: vmlsl.u16 q8, d19, d18 @ encoding: [0xd3,0xff,0xa2,0x0a]
+@ CHECK: vmlsl.u32 q8, d19, d18 @ encoding: [0xe3,0xff,0xa2,0x0a]
+
+
vqdmlsl.s16 q8, d19, d18
-@ CHECK: vqdmlsl.s32 q8, d19, d18 @ encoding: [0xa2,0x0b,0xe3,0xef]
vqdmlsl.s32 q8, d19, d18
+
+@ CHECK: vqdmlsl.s16 q8, d19, d18 @ encoding: [0xd3,0xef,0xa2,0x0b]
+@ CHECK: vqdmlsl.s32 q8, d19, d18 @ encoding: [0xe3,0xef,0xa2,0x0b]
diff --git a/test/MC/ARM/neont2-pairwise-encoding.s b/test/MC/ARM/neont2-pairwise-encoding.s
index ef90922..29aac36 100644
--- a/test/MC/ARM/neont2-pairwise-encoding.s
+++ b/test/MC/ARM/neont2-pairwise-encoding.s
@@ -1,89 +1,100 @@
@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s
-@ XFAIL: *
.code 16
+ vpadd.i8 d1, d5, d11
+ vpadd.i16 d13, d2, d12
+ vpadd.i32 d14, d1, d13
+ vpadd.f32 d19, d16, d14
-@ CHECK: vpadd.i8 d16, d17, d16 @ encoding: [0xb0,0x0b,0x41,0xef]
- vpadd.i8 d16, d17, d16
-@ CHECK: vpadd.i16 d16, d17, d16 @ encoding: [0xb0,0x0b,0x51,0xef]
- vpadd.i16 d16, d17, d16
-@ CHECK: vpadd.i32 d16, d17, d16 @ encoding: [0xb0,0x0b,0x61,0xef]
- vpadd.i32 d16, d17, d16
-@ CHECK: vpadd.f32 d16, d16, d17 @ encoding: [0xa1,0x0d,0x40,0xff]
- vpadd.f32 d16, d16, d17
-@ CHECK: vpaddl.s8 d16, d16 @ encoding: [0x20,0x02,0xf0,0xff]
- vpaddl.s8 d16, d16
-@ CHECK: vpaddl.s16 d16, d16 @ encoding: [0x20,0x02,0xf4,0xff]
- vpaddl.s16 d16, d16
-@ CHECK: vpaddl.s32 d16, d16 @ encoding: [0x20,0x02,0xf8,0xff]
- vpaddl.s32 d16, d16
-@ CHECK: vpaddl.u8 d16, d16 @ encoding: [0xa0,0x02,0xf0,0xff]
- vpaddl.u8 d16, d16
-@ CHECK: vpaddl.u16 d16, d16 @ encoding: [0xa0,0x02,0xf4,0xff]
- vpaddl.u16 d16, d16
-@ CHECK: vpaddl.u32 d16, d16 @ encoding: [0xa0,0x02,0xf8,0xff]
- vpaddl.u32 d16, d16
-@ CHECK: vpaddl.s8 q8, q8 @ encoding: [0x60,0x02,0xf0,0xff]
- vpaddl.s8 q8, q8
-@ CHECK: vpaddl.s16 q8, q8 @ encoding: [0x60,0x02,0xf4,0xff]
- vpaddl.s16 q8, q8
-@ CHECK: vpaddl.s32 q8, q8 @ encoding: [0x60,0x02,0xf8,0xff]
- vpaddl.s32 q8, q8
-@ CHECK: vpaddl.u8 q8, q8 @ encoding: [0xe0,0x02,0xf0,0xff]
- vpaddl.u8 q8, q8
-@ CHECK: vpaddl.u16 q8, q8 @ encoding: [0xe0,0x02,0xf4,0xff]
- vpaddl.u16 q8, q8
-@ CHECK: vpaddl.u32 q8, q8 @ encoding: [0xe0,0x02,0xf8,0xff]
- vpaddl.u32 q8, q8
-@ CHECK: vpadal.s8 d16, d17 @ encoding: [0x21,0x06,0xf0,0xff]
- vpadal.s8 d16, d17
-@ CHECK: vpadal.s16 d16, d17 @ encoding: [0x21,0x06,0xf4,0xff]
- vpadal.s16 d16, d17
-@ CHECK: vpadal.s32 d16, d17 @ encoding: [0x21,0x06,0xf8,0xff]
- vpadal.s32 d16, d17
-@ CHECK: vpadal.u8 d16, d17 @ encoding: [0xa1,0x06,0xf0,0xff]
- vpadal.u8 d16, d17
-@ CHECK: vpadal.u16 d16, d17 @ encoding: [0xa1,0x06,0xf4,0xff]
- vpadal.u16 d16, d17
-@ CHECK: vpadal.u32 d16, d17 @ encoding: [0xa1,0x06,0xf8,0xff]
- vpadal.u32 d16, d17
-@ CHECK: vpadal.s8 q9, q8 @ encoding: [0x60,0x26,0xf0,0xff]
- vpadal.s8 q9, q8
-@ CHECK: vpadal.s16 q9, q8 @ encoding: [0x60,0x26,0xf4,0xff]
- vpadal.s16 q9, q8
-@ CHECK: vpadal.s32 q9, q8 @ encoding: [0x60,0x26,0xf8,0xff]
- vpadal.s32 q9, q8
-@ CHECK: vpadal.u8 q9, q8 @ encoding: [0xe0,0x26,0xf0,0xff]
- vpadal.u8 q9, q8
-@ CHECK: vpadal.u16 q9, q8 @ encoding: [0xe0,0x26,0xf4,0xff]
- vpadal.u16 q9, q8
-@ CHECK: vpadal.u32 q9, q8 @ encoding: [0xe0,0x26,0xf8,0xff]
- vpadal.u32 q9, q8
-@ CHECK: vpmin.s8 d16, d16, d17 @ encoding: [0xb1,0x0a,0x40,0xef]
- vpmin.s8 d16, d16, d17
-@ CHECK: vpmin.s16 d16, d16, d17 @ encoding: [0xb1,0x0a,0x50,0xef]
- vpmin.s16 d16, d16, d17
-@ CHECK: vpmin.s32 d16, d16, d17 @ encoding: [0xb1,0x0a,0x60,0xef]
- vpmin.s32 d16, d16, d17
-@ CHECK: vpmin.u8 d16, d16, d17 @ encoding: [0xb1,0x0a,0x40,0xff]
- vpmin.u8 d16, d16, d17
-@ CHECK: vpmin.u16 d16, d16, d17 @ encoding: [0xb1,0x0a,0x50,0xff]
- vpmin.u16 d16, d16, d17
-@ CHECK: vpmin.u32 d16, d16, d17 @ encoding: [0xb1,0x0a,0x60,0xff]
- vpmin.u32 d16, d16, d17
-@ CHECK: vpmin.f32 d16, d16, d17 @ encoding: [0xa1,0x0f,0x60,0xff]
- vpmin.f32 d16, d16, d17
-@ CHECK: vpmax.s8 d16, d16, d17 @ encoding: [0xa1,0x0a,0x40,0xef]
- vpmax.s8 d16, d16, d17
-@ CHECK: vpmax.s16 d16, d16, d17 @ encoding: [0xa1,0x0a,0x50,0xef]
- vpmax.s16 d16, d16, d17
-@ CHECK: vpmax.s32 d16, d16, d17 @ encoding: [0xa1,0x0a,0x60,0xef]
- vpmax.s32 d16, d16, d17
-@ CHECK: vpmax.u8 d16, d16, d17 @ encoding: [0xa1,0x0a,0x40,0xff]
- vpmax.u8 d16, d16, d17
-@ CHECK: vpmax.u16 d16, d16, d17 @ encoding: [0xa1,0x0a,0x50,0xff]
- vpmax.u16 d16, d16, d17
-@ CHECK: vpmax.u32 d16, d16, d17 @ encoding: [0xa1,0x0a,0x60,0xff]
- vpmax.u32 d16, d16, d17
-@ CHECK: vpmax.f32 d16, d16, d17 @ encoding: [0xa1,0x0f,0x40,0xff]
- vpmax.f32 d16, d16, d17
+@ CHECK: vpadd.i8 d1, d5, d11 @ encoding: [0x05,0xef,0x1b,0x1b]
+@ CHECK: vpadd.i16 d13, d2, d12 @ encoding: [0x12,0xef,0x1c,0xdb]
+@ CHECK: vpadd.i32 d14, d1, d13 @ encoding: [0x21,0xef,0x1d,0xeb]
+@ CHECK: vpadd.f32 d19, d16, d14 @ encoding: [0x40,0xff,0x8e,0x3d]
+
+
+ vpaddl.s8 d7, d10
+ vpaddl.s16 d8, d11
+ vpaddl.s32 d9, d12
+ vpaddl.u8 d0, d13
+ vpaddl.u16 d5, d14
+ vpaddl.u32 d6, d15
+ vpaddl.s8 q4, q7
+ vpaddl.s16 q5, q6
+ vpaddl.s32 q6, q5
+ vpaddl.u8 q7, q4
+ vpaddl.u16 q8, q3
+ vpaddl.u32 q9, q2
+
+@ CHECK: vpaddl.s8 d7, d10 @ encoding: [0xb0,0xff,0x0a,0x72]
+@ CHECK: vpaddl.s16 d8, d11 @ encoding: [0xb4,0xff,0x0b,0x82]
+@ CHECK: vpaddl.s32 d9, d12 @ encoding: [0xb8,0xff,0x0c,0x92]
+@ CHECK: vpaddl.u8 d0, d13 @ encoding: [0xb0,0xff,0x8d,0x02]
+@ CHECK: vpaddl.u16 d5, d14 @ encoding: [0xb4,0xff,0x8e,0x52]
+@ CHECK: vpaddl.u32 d6, d15 @ encoding: [0xb8,0xff,0x8f,0x62]
+@ CHECK: vpaddl.s8 q4, q7 @ encoding: [0xb0,0xff,0x4e,0x82]
+@ CHECK: vpaddl.s16 q5, q6 @ encoding: [0xb4,0xff,0x4c,0xa2]
+@ CHECK: vpaddl.s32 q6, q5 @ encoding: [0xb8,0xff,0x4a,0xc2]
+@ CHECK: vpaddl.u8 q7, q4 @ encoding: [0xb0,0xff,0xc8,0xe2]
+@ CHECK: vpaddl.u16 q8, q3 @ encoding: [0xf4,0xff,0xc6,0x02]
+@ CHECK: vpaddl.u32 q9, q2 @ encoding: [0xf8,0xff,0xc4,0x22]
+
+
+ vpadal.s8 d16, d4
+ vpadal.s16 d20, d9
+ vpadal.s32 d18, d1
+ vpadal.u8 d14, d25
+ vpadal.u16 d12, d6
+ vpadal.u32 d11, d7
+ vpadal.s8 q4, q10
+ vpadal.s16 q5, q11
+ vpadal.s32 q6, q12
+ vpadal.u8 q7, q13
+ vpadal.u16 q8, q14
+ vpadal.u32 q9, q15
+
+@ CHECK: vpadal.s8 d16, d4 @ encoding: [0xf0,0xff,0x04,0x06]
+@ CHECK: vpadal.s16 d20, d9 @ encoding: [0xf4,0xff,0x09,0x46]
+@ CHECK: vpadal.s32 d18, d1 @ encoding: [0xf8,0xff,0x01,0x26]
+@ CHECK: vpadal.u8 d14, d25 @ encoding: [0xb0,0xff,0xa9,0xe6]
+@ CHECK: vpadal.u16 d12, d6 @ encoding: [0xb4,0xff,0x86,0xc6]
+@ CHECK: vpadal.u32 d11, d7 @ encoding: [0xb8,0xff,0x87,0xb6]
+@ CHECK: vpadal.s8 q4, q10 @ encoding: [0xb0,0xff,0x64,0x86]
+@ CHECK: vpadal.s16 q5, q11 @ encoding: [0xb4,0xff,0x66,0xa6]
+@ CHECK: vpadal.s32 q6, q12 @ encoding: [0xb8,0xff,0x68,0xc6]
+@ CHECK: vpadal.u8 q7, q13 @ encoding: [0xb0,0xff,0xea,0xe6]
+@ CHECK: vpadal.u16 q8, q14 @ encoding: [0xf4,0xff,0xec,0x06]
+@ CHECK: vpadal.u32 q9, q15 @ encoding: [0xf8,0xff,0xee,0x26]
+
+
+ vpmin.s8 d16, d29, d10
+ vpmin.s16 d17, d28, d11
+ vpmin.s32 d18, d27, d12
+ vpmin.u8 d19, d26, d13
+ vpmin.u16 d20, d25, d14
+ vpmin.u32 d21, d24, d15
+ vpmin.f32 d22, d23, d16
+
+@ CHECK: vpmin.s8 d16, d29, d10 @ encoding: [0x4d,0xef,0x9a,0x0a]
+@ CHECK: vpmin.s16 d17, d28, d11 @ encoding: [0x5c,0xef,0x9b,0x1a]
+@ CHECK: vpmin.s32 d18, d27, d12 @ encoding: [0x6b,0xef,0x9c,0x2a]
+@ CHECK: vpmin.u8 d19, d26, d13 @ encoding: [0x4a,0xff,0x9d,0x3a]
+@ CHECK: vpmin.u16 d20, d25, d14 @ encoding: [0x59,0xff,0x9e,0x4a]
+@ CHECK: vpmin.u32 d21, d24, d15 @ encoding: [0x68,0xff,0x9f,0x5a]
+@ CHECK: vpmin.f32 d22, d23, d16 @ encoding: [0x67,0xff,0xa0,0x6f]
+
+
+ vpmax.s8 d3, d20, d17
+ vpmax.s16 d4, d21, d16
+ vpmax.s32 d5, d22, d15
+ vpmax.u8 d6, d23, d14
+ vpmax.u16 d7, d24, d13
+ vpmax.u32 d8, d25, d12
+ vpmax.f32 d9, d26, d11
+
+@ CHECK: vpmax.s8 d3, d20, d17 @ encoding: [0x04,0xef,0xa1,0x3a]
+@ CHECK: vpmax.s16 d4, d21, d16 @ encoding: [0x15,0xef,0xa0,0x4a]
+@ CHECK: vpmax.s32 d5, d22, d15 @ encoding: [0x26,0xef,0x8f,0x5a]
+@ CHECK: vpmax.u8 d6, d23, d14 @ encoding: [0x07,0xff,0x8e,0x6a]
+@ CHECK: vpmax.u16 d7, d24, d13 @ encoding: [0x18,0xff,0x8d,0x7a]
+@ CHECK: vpmax.u32 d8, d25, d12 @ encoding: [0x29,0xff,0x8c,0x8a]
+@ CHECK: vpmax.f32 d9, d26, d11 @ encoding: [0x0a,0xff,0x8b,0x9f]
diff --git a/test/MC/ARM/nop-armv4-padding.s b/test/MC/ARM/nop-armv4-padding.s
new file mode 100644
index 0000000..8f646db
--- /dev/null
+++ b/test/MC/ARM/nop-armv4-padding.s
@@ -0,0 +1,10 @@
+@ RUN: llvm-mc -triple armv4-apple-darwin %s -filetype=obj -o %t.obj
+@ RUN: macho-dump --dump-section-data < %t.obj > %t.dump
+@ RUN: FileCheck %s < %t.dump
+
+x:
+ add r0, r1, r2
+ .align 4
+ add r0, r1, r2
+
+@ CHECK: ('_section_data', '020081e0 00001a0e 00001a0e 00001a0e 020081e0')
diff --git a/test/MC/ARM/nop-armv6t2-padding.s b/test/MC/ARM/nop-armv6t2-padding.s
new file mode 100644
index 0000000..0e25718
--- /dev/null
+++ b/test/MC/ARM/nop-armv6t2-padding.s
@@ -0,0 +1,10 @@
+@ RUN: llvm-mc -triple armv6t2-apple-darwin %s -filetype=obj -o %t.obj
+@ RUN: macho-dump --dump-section-data < %t.obj > %t.dump
+@ RUN: FileCheck %s < %t.dump
+
+x:
+ add r0, r1, r2
+ .align 4
+ add r0, r1, r2
+
+@ CHECK: ('_section_data', '020081e0 007820e3 007820e3 007820e3 020081e0')
diff --git a/test/MC/ARM/nop-thumb-padding.s b/test/MC/ARM/nop-thumb-padding.s
new file mode 100644
index 0000000..1e173f1
--- /dev/null
+++ b/test/MC/ARM/nop-thumb-padding.s
@@ -0,0 +1,12 @@
+@ RUN: llvm-mc -triple armv6-apple-darwin %s -filetype=obj -o %t.obj
+@ RUN: macho-dump --dump-section-data < %t.obj > %t.dump
+@ RUN: FileCheck %s < %t.dump
+
+.thumb_func x
+.code 16
+x:
+ adds r0, r1, r2
+ .align 4
+ adds r0, r1, r2
+
+@ CHECK: ('_section_data', '8818c046 c046c046 c046c046 c046c046 8818')
diff --git a/test/MC/ARM/nop-thumb2-padding.s b/test/MC/ARM/nop-thumb2-padding.s
new file mode 100644
index 0000000..a8aa3a1
--- /dev/null
+++ b/test/MC/ARM/nop-thumb2-padding.s
@@ -0,0 +1,12 @@
+@ RUN: llvm-mc -triple armv7-apple-darwin %s -filetype=obj -o %t.obj
+@ RUN: macho-dump --dump-section-data < %t.obj > %t.dump
+@ RUN: FileCheck %s < %t.dump
+
+.thumb_func x
+.code 16
+x:
+ adds r0, r1, r2
+ .align 4
+ adds r0, r1, r2
+
+@ CHECK: ('_section_data', '881800bf 00bf00bf 00bf00bf 00bf00bf 8818')
diff --git a/test/MC/ARM/reg-list.s b/test/MC/ARM/reg-list.s
deleted file mode 100644
index 4dd392e..0000000
--- a/test/MC/ARM/reg-list.s
+++ /dev/null
@@ -1,8 +0,0 @@
-@ RUN: llvm-mc -triple thumb-apple-darwin10 -show-encoding < %s 2> %t | FileCheck %s
-@ RUN: FileCheck --check-prefix=CHECK-WARNINGS < %t %s
-
- push {r7, lr}
-@ CHECK-WARNINGS: register not in ascending order in register list
-
- push {lr, r7}
-@ CHECK: push {lr, r7}
diff --git a/test/MC/ARM/simple-encoding.ll b/test/MC/ARM/simple-encoding.ll
deleted file mode 100644
index 14ed945..0000000
--- a/test/MC/ARM/simple-encoding.ll
+++ /dev/null
@@ -1,236 +0,0 @@
-;RUN: llc -mtriple=armv7-apple-darwin -show-mc-encoding -disable-cgp-branch-opts -join-physregs < %s | FileCheck %s
-
-
-;FIXME: Once the ARM integrated assembler is up and going, these sorts of tests
-; should run on .s source files rather than using llc to generate the
-; assembly. There's also a large number of instruction encodings the
-; compiler never generates, so we need the integrated assembler to be
-; able to test those at all.
-
-declare void @llvm.trap() nounwind
-declare i32 @llvm.ctlz.i32(i32)
-
-define i32 @foo(i32 %a, i32 %b) {
-; CHECK: foo
-; CHECK: trap @ encoding: [0xfe,0xde,0xff,0xe7]
-; CHECK: bx lr @ encoding: [0x1e,0xff,0x2f,0xe1]
-
- tail call void @llvm.trap()
- ret i32 undef
-}
-
-define i32 @f2(i32 %a, i32 %b) {
-; CHECK: f2
-; CHECK: add r0, r1, r0 @ encoding: [0x00,0x00,0x81,0xe0]
-; CHECK: bx lr @ encoding: [0x1e,0xff,0x2f,0xe1]
- %add = add nsw i32 %b, %a
- ret i32 %add
-}
-
-
-define i32 @f3(i32 %a, i32 %b) {
-; CHECK: f3
-; CHECK: add r0, r0, r1, lsl #3 @ encoding: [0x81,0x01,0x80,0xe0]
-; CHECK: bx lr @ encoding: [0x1e,0xff,0x2f,0xe1]
- %mul = shl i32 %b, 3
- %add = add nsw i32 %mul, %a
- ret i32 %add
-}
-
-define i32 @f4(i32 %a, i32 %b) {
-; CHECK: f4
-; CHECK: add r0, r0, #4064 @ encoding: [0xfe,0x0e,0x80,0xe2]
-; CHECK: bx lr @ encoding: [0x1e,0xff,0x2f,0xe1]
- %add = add nsw i32 %a, 4064
- ret i32 %add
-}
-
-define i32 @f5(i32 %a, i32 %b, i32 %c) {
-; CHECK: f5
-; CHECK: cmp r0, r1 @ encoding: [0x01,0x00,0x50,0xe1]
-; CHECK: mov r0, r2 @ encoding: [0x02,0x00,0xa0,0xe1]
-; CHECK: movgt r0, r1 @ encoding: [0x01,0x00,0xa0,0xc1]
- %cmp = icmp sgt i32 %a, %b
- %retval.0 = select i1 %cmp, i32 %b, i32 %c
- ret i32 %retval.0
-}
-
-define i64 @f6(i64 %a, i64 %b, i64 %c) {
-; CHECK: f6
-; CHECK: adds r0, r2, r0 @ encoding: [0x00,0x00,0x92,0xe0]
-; CHECK: adc r1, r3, r1 @ encoding: [0x01,0x10,0xa3,0xe0]
- %add = add nsw i64 %b, %a
- ret i64 %add
-}
-
-define i32 @f7(i32 %a, i32 %b) {
-; CHECK: f7
-; CHECK: uxtab r0, r0, r1 @ encoding: [0x71,0x00,0xe0,0xe6]
- %and = and i32 %b, 255
- %add = add i32 %and, %a
- ret i32 %add
-}
-
-define i32 @f8(i32 %a) {
-; CHECK: f8
-; CHECK: movt r0, #42405 @ encoding: [0xa5,0x05,0x4a,0xe3]
- %and = and i32 %a, 65535
- %or = or i32 %and, -1515913216
- ret i32 %or
-}
-
-define i32 @f9() {
-; CHECK: f9
-; CHECK: movw r0, #42405 @ encoding: [0xa5,0x05,0x0a,0xe3]
- ret i32 42405
-}
-
-define i64 @f10(i64 %a) {
-; CHECK: f10
-; CHECK: asrs r1, r1, #1 @ encoding: [0xc1,0x10,0xb0,0xe1]
-; CHECK: rrx r0, r0 @ encoding: [0x60,0x00,0xa0,0xe1]
- %shr = ashr i64 %a, 1
- ret i64 %shr
-}
-
-define i32 @f11([1 x i32] %A.coerce0, [1 x i32] %B.coerce0) {
-; CHECK: f11
-; CHECK: ubfx r1, r1, #8, #5 @ encoding: [0x51,0x14,0xe4,0xe7]
-; CHECK: sbfx r0, r0, #13, #7 @ encoding: [0xd0,0x06,0xa6,0xe7]
- %tmp1 = extractvalue [1 x i32] %A.coerce0, 0
- %tmp2 = extractvalue [1 x i32] %B.coerce0, 0
- %tmp3 = shl i32 %tmp1, 12
- %bf.val.sext = ashr i32 %tmp3, 25
- %tmp4 = lshr i32 %tmp2, 8
- %bf.clear2 = and i32 %tmp4, 31
- %mul = mul nsw i32 %bf.val.sext, %bf.clear2
- ret i32 %mul
-}
-
-define i32 @f12(i32 %a) {
-; CHECK: f12:
-; CHECK: bfc r0, #4, #20 @ encoding: [0x1f,0x02,0xd7,0xe7]
- %tmp = and i32 %a, 4278190095
- ret i32 %tmp
-}
-
-define i64 @f13() {
-; CHECK: f13:
-; CHECK: mvn r0, #0 @ encoding: [0x00,0x00,0xe0,0xe3]
-; CHECK: mvn r1, #-2147483648 @ encoding: [0x02,0x11,0xe0,0xe3]
- ret i64 9223372036854775807
-}
-
-define i32 @f14(i32 %x, i32 %y) {
-; CHECK: f14:
-; CHECK: smmul r0, r1, r0 @ encoding: [0x11,0xf0,0x50,0xe7]
- %tmp = sext i32 %x to i64
- %tmp1 = sext i32 %y to i64
- %tmp2 = mul i64 %tmp1, %tmp
- %tmp3 = lshr i64 %tmp2, 32
- %tmp3.upgrd.1 = trunc i64 %tmp3 to i32
- ret i32 %tmp3.upgrd.1
-}
-
-define i32 @f15(i32 %x, i32 %y) {
-; CHECK: f15:
-; CHECK: umull r1, r0, r1, r0 @ encoding: [0x91,0x10,0x80,0xe0]
- %tmp = zext i32 %x to i64
- %tmp1 = zext i32 %y to i64
- %tmp2 = mul i64 %tmp1, %tmp
- %tmp3 = lshr i64 %tmp2, 32
- %tmp3.upgrd.2 = trunc i64 %tmp3 to i32
- ret i32 %tmp3.upgrd.2
-}
-
-define i32 @f16(i16 %x, i32 %y) {
-; CHECK: f16:
-; CHECK: smulbt r0, r0, r1 @ encoding: [0xc0,0x01,0x60,0xe1]
- %tmp1 = add i16 %x, 2
- %tmp2 = sext i16 %tmp1 to i32
- %tmp3 = ashr i32 %y, 16
- %tmp4 = mul i32 %tmp2, %tmp3
- ret i32 %tmp4
-}
-
-define i32 @f17(i32 %x, i32 %y) {
-; CHECK: f17:
-; CHECK: smultt r0, r1, r0 @ encoding: [0xe1,0x00,0x60,0xe1]
- %tmp1 = ashr i32 %x, 16
- %tmp3 = ashr i32 %y, 16
- %tmp4 = mul i32 %tmp3, %tmp1
- ret i32 %tmp4
-}
-
-define i32 @f18(i32 %a, i16 %x, i32 %y) {
-; CHECK: f18:
-; CHECK: smlabt r0, r1, r2, r0 @ encoding: [0xc1,0x02,0x00,0xe1]
- %tmp = sext i16 %x to i32
- %tmp2 = ashr i32 %y, 16
- %tmp3 = mul i32 %tmp2, %tmp
- %tmp5 = add i32 %tmp3, %a
- ret i32 %tmp5
-}
-
-define i32 @f19(i32 %x) {
-; CHECK: f19
-; CHECK: clz r0, r0 @ encoding: [0x10,0x0f,0x6f,0xe1]
- %tmp.1 = call i32 @llvm.ctlz.i32( i32 %x )
- ret i32 %tmp.1
-}
-
-define i32 @f20(i32 %X) {
-; CHECK: f20
-; CHECK: rev16 r0, r0 @ encoding: [0xb0,0x0f,0xbf,0xe6]
- %tmp1 = lshr i32 %X, 8
- %X15 = bitcast i32 %X to i32
- %tmp4 = shl i32 %X15, 8
- %tmp2 = and i32 %tmp1, 16711680
- %tmp5 = and i32 %tmp4, -16777216
- %tmp9 = and i32 %tmp1, 255
- %tmp13 = and i32 %tmp4, 65280
- %tmp6 = or i32 %tmp5, %tmp2
- %tmp10 = or i32 %tmp6, %tmp13
- %tmp14 = or i32 %tmp10, %tmp9
- ret i32 %tmp14
-}
-
-define i32 @f21(i32 %X) {
-; CHECK: f21
-; CHECK: revsh r0, r0 @ encoding: [0xb0,0x0f,0xff,0xe6]
- %tmp1 = lshr i32 %X, 8
- %tmp1.upgrd.1 = trunc i32 %tmp1 to i16
- %tmp3 = trunc i32 %X to i16
- %tmp2 = and i16 %tmp1.upgrd.1, 255
- %tmp4 = shl i16 %tmp3, 8
- %tmp5 = or i16 %tmp2, %tmp4
- %tmp5.upgrd.2 = sext i16 %tmp5 to i32
- ret i32 %tmp5.upgrd.2
-}
-
-define i32 @f22(i32 %X, i32 %Y) {
-; CHECK: f22
-; CHECK: pkhtb r0, r0, r1, asr #22 @ encoding: [0x51,0x0b,0x80,0xe6]
- %tmp1 = and i32 %X, -65536
- %tmp2 = lshr i32 %Y, 22
- %tmp3 = or i32 %tmp2, %tmp1
- ret i32 %tmp3
-}
-
-define i32 @f23(i32 %X, i32 %Y) {
-; CHECK: f23
-; CHECK: pkhbt r0, r0, r1, lsl #18 @ encoding: [0x11,0x09,0x80,0xe6]
- %tmp1 = and i32 %X, 65535
- %tmp2 = shl i32 %Y, 18
- %tmp3 = or i32 %tmp1, %tmp2
- ret i32 %tmp3
-}
-
-define void @f24(i32 %a) {
-; CHECK: f24
-; CHECK: cmp r0, #65536 @ encoding: [0x01,0x08,0x50,0xe3]
- %b = icmp ugt i32 %a, 65536
- br i1 %b, label %r, label %r
-r:
- ret void
-}
diff --git a/test/MC/ARM/simple-fp-encoding.s b/test/MC/ARM/simple-fp-encoding.s
index 8917380..e7d452a 100644
--- a/test/MC/ARM/simple-fp-encoding.s
+++ b/test/MC/ARM/simple-fp-encoding.s
@@ -2,7 +2,7 @@
@ CHECK: vadd.f64 d16, d17, d16 @ encoding: [0xa0,0x0b,0x71,0xee]
vadd.f64 d16, d17, d16
-
+
@ CHECK: vadd.f32 s0, s1, s0 @ encoding: [0x80,0x0a,0x30,0xee]
vadd.f32 s0, s1, s0
@@ -36,18 +36,18 @@
@ CHECK: vcmpe.f32 s1, s0 @ encoding: [0xc0,0x0a,0xf4,0xee]
vcmpe.f32 s1, s0
-@ FIXME: vcmpe.f64 d16, #0 @ encoding: [0xc0,0x0b,0xf5,0xee]
-@ vcmpe.f64 d16, #0
+@ CHECK: vcmpe.f64 d16, #0 @ encoding: [0xc0,0x0b,0xf5,0xee]
+ vcmpe.f64 d16, #0
-@ FIXME: vcmpe.f32 s0, #0 @ encoding: [0xc0,0x0a,0xb5,0xee]
-@ vcmpe.f32 s0, #0
+@ CHECK: vcmpe.f32 s0, #0 @ encoding: [0xc0,0x0a,0xb5,0xee]
+ vcmpe.f32 s0, #0
@ CHECK: vabs.f64 d16, d16 @ encoding: [0xe0,0x0b,0xf0,0xee]
vabs.f64 d16, d16
@ CHECK: vabs.f32 s0, s0 @ encoding: [0xc0,0x0a,0xb0,0xee]
vabs.f32 s0, s0
-
+
@ CHECK: vcvt.f32.f64 s0, d16 @ encoding: [0xe0,0x0b,0xb7,0xee]
vcvt.f32.f64 s0, d16
@@ -114,9 +114,11 @@
@ CHECK: vnmls.f32 s1, s2, s0 @ encoding: [0x00,0x0a,0x51,0xee]
vnmls.f32 s1, s2, s0
-@ FIXME: vmrs apsr_nzcv, fpscr @ encoding: [0x10,0xfa,0xf1,0xee]
-@ vmrs apsr_nzcv, fpscr
-
+@ CHECK: vmrs apsr_nzcv, fpscr @ encoding: [0x10,0xfa,0xf1,0xee]
+@ CHECK: vmrs apsr_nzcv, fpscr @ encoding: [0x10,0xfa,0xf1,0xee]
+ vmrs apsr_nzcv, fpscr
+ fmstat
+
@ CHECK: vnegne.f64 d16, d16 @ encoding: [0x60,0x0b,0xf1,0x1e]
vnegne.f64 d16, d16
@@ -139,11 +141,15 @@
@ CHECK: vmsr fpsid, r0 @ encoding: [0x10,0x0a,0xe0,0xee]
vmsr fpsid, r0
-@ FIXME: vmov.f64 d16, #3.000000e+00 @ encoding: [0x08,0x0b,0xf0,0xee]
-@ vmov.f64 d16, #3.000000e+00
+ vmov.f64 d16, #3.000000e+00
+ vmov.f32 s0, #3.000000e+00
+ vmov.f64 d16, #-3.000000e+00
+ vmov.f32 s0, #-3.000000e+00
-@ FIXME: vmov.f32 s0, #3.000000e+00 @ encoding: [0x08,0x0a,0xb0,0xee]
-@ vmov.f32 s0, #3.000000e+00
+@ CHECK: vmov.f64 d16, #3.000000e+00 @ encoding: [0x08,0x0b,0xf0,0xee]
+@ CHECK: vmov.f32 s0, #3.000000e+00 @ encoding: [0x08,0x0a,0xb0,0xee]
+@ CHECK: vmov.f64 d16, #-3.000000e+00 @ encoding: [0x08,0x0b,0xf8,0xee]
+@ CHECK: vmov.f32 s0, #-3.000000e+00 @ encoding: [0x08,0x0a,0xb8,0xee]
@ CHECK: vmov s0, r0 @ encoding: [0x10,0x0a,0x00,0xee]
@ CHECK: vmov s1, r1 @ encoding: [0x90,0x1a,0x00,0xee]
@@ -173,13 +179,13 @@
@ CHECK: vldr.64 d1, [r2, #-32] @ encoding: [0x08,0x1b,0x12,0xed]
vldr.64 d1, [r2, #32]
vldr.64 d1, [r2, #-32]
-
+
@ CHECK: vldr.64 d2, [r3] @ encoding: [0x00,0x2b,0x93,0xed]
vldr.64 d2, [r3]
@ CHECK: vldr.64 d3, [pc] @ encoding: [0x00,0x3b,0x9f,0xed]
@ CHECK: vldr.64 d3, [pc] @ encoding: [0x00,0x3b,0x9f,0xed]
-@ CHECK: vldr.64 d3, [pc] @ encoding: [0x00,0x3b,0x9f,0xed]
+@ CHECK: vldr.64 d3, [pc, #-0] @ encoding: [0x00,0x3b,0x1f,0xed]
vldr.64 d3, [pc]
vldr.64 d3, [pc,#0]
vldr.64 d3, [pc,#-0]
@@ -191,13 +197,13 @@
@ CHECK: vldr.32 s1, [r2, #-32] @ encoding: [0x08,0x0a,0x52,0xed]
vldr.32 s1, [r2, #32]
vldr.32 s1, [r2, #-32]
-
+
@ CHECK: vldr.32 s2, [r3] @ encoding: [0x00,0x1a,0x93,0xed]
vldr.32 s2, [r3]
@ CHECK: vldr.32 s5, [pc] @ encoding: [0x00,0x2a,0xdf,0xed]
@ CHECK: vldr.32 s5, [pc] @ encoding: [0x00,0x2a,0xdf,0xed]
-@ CHECK: vldr.32 s5, [pc] @ encoding: [0x00,0x2a,0xdf,0xed]
+@ CHECK: vldr.32 s5, [pc, #-0] @ encoding: [0x00,0x2a,0x5f,0xed]
vldr.32 s5, [pc]
vldr.32 s5, [pc,#0]
vldr.32 s5, [pc,#-0]
@@ -234,3 +240,6 @@
vcvtr.s32.f32 s0, s1
vcvtr.u32.f64 s0, d0
vcvtr.u32.f32 s0, s1
+
+@ CHECK: vmovne s25, s26, r2, r5
+ vmovne s25, s26, r2, r5 @ encoding: [0x39,0x2a,0x45,0x1c]
diff --git a/test/MC/ARM/thumb-diagnostics.s b/test/MC/ARM/thumb-diagnostics.s
new file mode 100644
index 0000000..d02c27e
--- /dev/null
+++ b/test/MC/ARM/thumb-diagnostics.s
@@ -0,0 +1,139 @@
+@ RUN: not llvm-mc -triple=thumbv6-apple-darwin < %s 2> %t
+@ RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
+@ RUN: not llvm-mc -triple=thumbv5-apple-darwin < %s 2> %t
+@ RUN: FileCheck --check-prefix=CHECK-ERRORS-V5 < %t %s
+
+@ Check for various assembly diagnostic messages on invalid input.
+
+@ ADD instruction w/o 'S' suffix.
+ add r1, r2, r3
+@ CHECK-ERRORS: error: invalid instruction
+@ CHECK-ERRORS: add r1, r2, r3
+@ CHECK-ERRORS: ^
+
+@ Instructions which require v6+ for both registers to be low regs.
+ add r2, r3
+ mov r2, r3
+@ CHECK-ERRORS: error: instruction variant requires Thumb2
+@ CHECK-ERRORS: add r2, r3
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS-V5: error: instruction variant requires ARMv6 or later
+@ CHECK-ERRORS-V5: mov r2, r3
+@ CHECK-ERRORS-V5: ^
+
+
+@ Out of range immediates for ASR instruction.
+ asrs r2, r3, #33
+ asrs r2, r3, #0
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: asrs r2, r3, #33
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: asrs r2, r3, #0
+@ CHECK-ERRORS: ^
+
+@ Out of range immediates for BKPT instruction.
+ bkpt #256
+ bkpt #-1
+error: invalid operand for instruction
+ bkpt #256
+ ^
+error: invalid operand for instruction
+ bkpt #-1
+ ^
+
+@ Invalid writeback and register lists for LDM
+ ldm r2!, {r5, r8}
+ ldm r2, {r5, r7}
+ ldm r2!, {r2, r3, r4}
+@ CHECK-ERRORS: error: registers must be in range r0-r7
+@ CHECK-ERRORS: ldm r2!, {r5, r8}
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: writeback operator '!' expected
+@ CHECK-ERRORS: ldm r2, {r5, r7}
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: writeback operator '!' not allowed when base register in register list
+@ CHECK-ERRORS: ldm r2!, {r2, r3, r4}
+@ CHECK-ERRORS: ^
+
+
+@ Invalid writeback and register lists for PUSH/POP
+ pop {r1, r2, r10}
+ push {r8, r9}
+@ CHECK-ERRORS: error: registers must be in range r0-r7 or pc
+@ CHECK-ERRORS: pop {r1, r2, r10}
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: registers must be in range r0-r7 or lr
+@ CHECK-ERRORS: push {r8, r9}
+@ CHECK-ERRORS: ^
+
+
+@ Invalid writeback and register lists for STM
+ stm r1, {r2, r6}
+ stm r1!, {r2, r9}
+@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
+@ CHECK-ERRORS: stm r1, {r2, r6}
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: registers must be in range r0-r7
+@ CHECK-ERRORS: stm r1!, {r2, r9}
+@ CHECK-ERRORS: ^
+
+@ Out of range immediates for LSL instruction.
+ lsls r4, r5, #-1
+ lsls r4, r5, #32
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: lsls r4, r5, #-1
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: lsls r4, r5, #32
+@ CHECK-ERRORS: ^
+
+@ Mismatched source/destination operands for MUL instruction.
+ muls r1, r2, r3
+@ CHECK-ERRORS: error: destination register must match source register
+@ CHECK-ERRORS: muls r1, r2, r3
+@ CHECK-ERRORS: ^
+
+
+@ Out of range immediates for STR instruction.
+ str r2, [r7, #-1]
+ str r5, [r1, #3]
+ str r3, [r7, #128]
+@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
+@ CHECK-ERRORS: str r2, [r7, #-1]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
+@ CHECK-ERRORS: str r5, [r1, #3]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
+@ CHECK-ERRORS: str r3, [r7, #128]
+@ CHECK-ERRORS: ^
+
+@ Out of range immediate for SVC instruction.
+ svc #-1
+ svc #256
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: svc #-1
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
+@ CHECK-ERRORS: svc #256
+@ CHECK-ERRORS: ^
+
+
+@ Out of range immediate for ADD SP instructions
+ add sp, #-1
+ add sp, #3
+ add sp, sp, #512
+ add r2, sp, #1024
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: add sp, #-1
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: add sp, #3
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
+@ CHECK-ERRORS: add sp, sp, #512
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: instruction requires a CPU feature not currently enabled
+@ CHECK-ERRORS: add r2, sp, #1024
+@ CHECK-ERRORS: ^
diff --git a/test/MC/ARM/thumb-nop.s b/test/MC/ARM/thumb-nop.s
new file mode 100644
index 0000000..0b580ea
--- /dev/null
+++ b/test/MC/ARM/thumb-nop.s
@@ -0,0 +1,9 @@
+@ RUN: llvm-mc -triple=thumbv6-apple-darwin -show-encoding < %s | FileCheck %s -check-prefix=CHECK-V6
+@ RUN: llvm-mc -triple=thumbv7-apple-darwin -show-encoding < %s | FileCheck %s -check-prefix=CHECK-V7
+
+ .syntax unified
+
+ nop
+
+@ CHECK-V6: nop @ encoding: [0xc0,0x46]
+@ CHECK-V7: nop @ encoding: [0x00,0xbf]
diff --git a/test/MC/ARM/thumb.s b/test/MC/ARM/thumb.s
index 79ea2e4..625882c 100644
--- a/test/MC/ARM/thumb.s
+++ b/test/MC/ARM/thumb.s
@@ -1,60 +1,58 @@
@ RUN: llvm-mc -triple thumbv6-apple-darwin -show-encoding < %s | FileCheck %s
.code 16
-@ CHECK: cmp r1, r2 @ encoding: [0x91,0x42]
cmp r1, r2
+@ CHECK: cmp r1, r2 @ encoding: [0x91,0x42]
-@ CHECK: pop {r1, r2, r4} @ encoding: [0x16,0xbc]
pop {r1, r2, r4}
+@ CHECK: pop {r1, r2, r4} @ encoding: [0x16,0xbc]
-@ CHECK: trap @ encoding: [0xfe,0xde]
trap
+@ CHECK: trap @ encoding: [0xfe,0xde]
-@ CHECK: blx r9 @ encoding: [0xc8,0x47]
blx r9
+ blx r10
+@ CHECK: blx r9 @ encoding: [0xc8,0x47]
@ CHECK: blx r10 @ encoding: [0xd0,0x47]
- blx r10
-@ CHECK: rev r2, r3 @ encoding: [0x1a,0xba]
-@ CHECK: rev16 r3, r4 @ encoding: [0x63,0xba]
-@ CHECK: revsh r5, r6 @ encoding: [0xf5,0xba]
rev r2, r3
rev16 r3, r4
revsh r5, r6
+@ CHECK: rev r2, r3 @ encoding: [0x1a,0xba]
+@ CHECK: rev16 r3, r4 @ encoding: [0x63,0xba]
+@ CHECK: revsh r5, r6 @ encoding: [0xf5,0xba]
-@ CHECK: sxtb r2, r3 @ encoding: [0x5a,0xb2]
-@ CHECK: sxth r2, r3 @ encoding: [0x1a,0xb2]
sxtb r2, r3
sxth r2, r3
+@ CHECK: sxtb r2, r3 @ encoding: [0x5a,0xb2]
+@ CHECK: sxth r2, r3 @ encoding: [0x1a,0xb2]
-@ CHECK: tst r4, r5 @ encoding: [0x2c,0x42]
tst r4, r5
+@ CHECK: tst r4, r5 @ encoding: [0x2c,0x42]
-@ CHECK: uxtb r3, r6 @ encoding: [0xf3,0xb2]
-@ CHECK: uxth r3, r6 @ encoding: [0xb3,0xb2]
uxtb r3, r6
uxth r3, r6
+@ CHECK: uxtb r3, r6 @ encoding: [0xf3,0xb2]
+@ CHECK: uxth r3, r6 @ encoding: [0xb3,0xb2]
-@ CHECK: ldr r3, [r1, r2] @ encoding: [0x8b,0x58]
ldr r3, [r1, r2]
+@ CHECK: ldr r3, [r1, r2] @ encoding: [0x8b,0x58]
-@ CHECK: bkpt #2 @ encoding: [0x02,0xbe]
- bkpt #2
+ bkpt #2
+@ CHECK: bkpt #2 @ encoding: [0x02,0xbe]
-@ CHECK: nop @ encoding: [0x00,0xbf]
nop
+@ CHECK: nop @ encoding: [0xc0,0x46]
-@ CHECK: yield @ encoding: [0x10,0xbf]
- yield
-
-@ CHECK: wfe @ encoding: [0x20,0xbf]
wfe
-
-@ CHECK: wfi @ encoding: [0x30,0xbf]
wfi
+ yield
+@ CHECK: wfe @ encoding: [0x20,0xbf]
+@ CHECK: wfi @ encoding: [0x30,0xbf]
+@ CHECK: yield @ encoding: [0x10,0xbf]
-@ CHECK: cpsie aif @ encoding: [0x67,0xb6]
cpsie aif
+@ CHECK: cpsie aif @ encoding: [0x67,0xb6]
-@ CHECK: mov r0, pc @ encoding: [0x78,0x46]
mov r0, pc
+@ CHECK: mov r0, pc @ encoding: [0x78,0x46]
diff --git a/test/MC/ARM/thumb2-diagnostics.s b/test/MC/ARM/thumb2-diagnostics.s
new file mode 100644
index 0000000..e38f53c
--- /dev/null
+++ b/test/MC/ARM/thumb2-diagnostics.s
@@ -0,0 +1,44 @@
+@ RUN: not llvm-mc -triple=thumbv7-apple-darwin < %s 2> %t
+@ RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
+
+@ Ill-formed IT block instructions.
+ itet eq
+ addle r0, r1, r2
+ nop
+ it le
+ iteeee gt
+ ittfe le
+ nopeq
+
+@ CHECK-ERRORS: error: incorrect condition in IT block; got 'le', but expected 'eq'
+@ CHECK-ERRORS: addle r0, r1, r2
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: incorrect condition in IT block; got 'al', but expected 'ne'
+@ CHECK-ERRORS: nop
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: instructions in IT block must be predicable
+@ CHECK-ERRORS: it le
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: too many conditions on IT instruction
+@ CHECK-ERRORS: iteeee gt
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: illegal IT block condition mask 'tfe'
+@ CHECK-ERRORS: ittfe le
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: predicated instructions must be in IT block
+@ CHECK-ERRORS: nopeq
+@ CHECK-ERRORS: ^
+
+ @ Out of range immediates for MRC/MRC2/MRRC/MRRC2
+ mrc p14, #8, r1, c1, c2, #4
+ mrc p14, #1, r1, c1, c2, #8
+ mrc2 p14, #8, r1, c1, c2, #4
+ mrc2 p14, #0, r1, c1, c2, #9
+ mrrc p7, #16, r5, r4, c1
+ mrrc2 p7, #17, r5, r4, c1
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: invalid operand for instruction
diff --git a/test/MC/ARM/thumb2-mclass.s b/test/MC/ARM/thumb2-mclass.s
new file mode 100644
index 0000000..10460f9
--- /dev/null
+++ b/test/MC/ARM/thumb2-mclass.s
@@ -0,0 +1,74 @@
+@ RUN: llvm-mc -triple=thumbv7m-apple-darwin -show-encoding < %s | FileCheck %s
+ .syntax unified
+ .globl _func
+
+@ Check that the assembler can handle the documented syntax from the ARM ARM.
+@ These tests test instruction encodings specific to v7m & v7m (FeatureMClass).
+
+@------------------------------------------------------------------------------
+@ MRS
+@------------------------------------------------------------------------------
+
+ mrs r0, apsr
+ mrs r0, iapsr
+ mrs r0, eapsr
+ mrs r0, xpsr
+ mrs r0, ipsr
+ mrs r0, epsr
+ mrs r0, iepsr
+ mrs r0, msp
+ mrs r0, psp
+ mrs r0, primask
+ mrs r0, basepri
+ mrs r0, basepri_max
+ mrs r0, faultmask
+ mrs r0, control
+
+@ CHECK: mrs r0, apsr @ encoding: [0xef,0xf3,0x00,0x80]
+@ CHECK: mrs r0, iapsr @ encoding: [0xef,0xf3,0x01,0x80]
+@ CHECK: mrs r0, eapsr @ encoding: [0xef,0xf3,0x02,0x80]
+@ CHECK: mrs r0, xpsr @ encoding: [0xef,0xf3,0x03,0x80]
+@ CHECK: mrs r0, ipsr @ encoding: [0xef,0xf3,0x05,0x80]
+@ CHECK: mrs r0, epsr @ encoding: [0xef,0xf3,0x06,0x80]
+@ CHECK: mrs r0, iepsr @ encoding: [0xef,0xf3,0x07,0x80]
+@ CHECK: mrs r0, msp @ encoding: [0xef,0xf3,0x08,0x80]
+@ CHECK: mrs r0, psp @ encoding: [0xef,0xf3,0x09,0x80]
+@ CHECK: mrs r0, primask @ encoding: [0xef,0xf3,0x10,0x80]
+@ CHECK: mrs r0, basepri @ encoding: [0xef,0xf3,0x11,0x80]
+@ CHECK: mrs r0, basepri_max @ encoding: [0xef,0xf3,0x12,0x80]
+@ CHECK: mrs r0, faultmask @ encoding: [0xef,0xf3,0x13,0x80]
+@ CHECK: mrs r0, control @ encoding: [0xef,0xf3,0x14,0x80]
+
+@------------------------------------------------------------------------------
+@ MSR
+@------------------------------------------------------------------------------
+
+ msr apsr, r0
+ msr iapsr, r0
+ msr eapsr, r0
+ msr xpsr, r0
+ msr ipsr, r0
+ msr epsr, r0
+ msr iepsr, r0
+ msr msp, r0
+ msr psp, r0
+ msr primask, r0
+ msr basepri, r0
+ msr basepri_max, r0
+ msr faultmask, r0
+ msr control, r0
+
+@ CHECK: msr apsr, r0 @ encoding: [0x80,0xf3,0x00,0x80]
+@ CHECK: msr iapsr, r0 @ encoding: [0x80,0xf3,0x01,0x80]
+@ CHECK: msr eapsr, r0 @ encoding: [0x80,0xf3,0x02,0x80]
+@ CHECK: msr xpsr, r0 @ encoding: [0x80,0xf3,0x03,0x80]
+@ CHECK: msr ipsr, r0 @ encoding: [0x80,0xf3,0x05,0x80]
+@ CHECK: msr epsr, r0 @ encoding: [0x80,0xf3,0x06,0x80]
+@ CHECK: msr iepsr, r0 @ encoding: [0x80,0xf3,0x07,0x80]
+@ CHECK: msr msp, r0 @ encoding: [0x80,0xf3,0x08,0x80]
+@ CHECK: msr psp, r0 @ encoding: [0x80,0xf3,0x09,0x80]
+@ CHECK: msr primask, r0 @ encoding: [0x80,0xf3,0x10,0x80]
+@ CHECK: msr basepri, r0 @ encoding: [0x80,0xf3,0x11,0x80]
+@ CHECK: msr basepri_max, r0 @ encoding: [0x80,0xf3,0x12,0x80]
+@ CHECK: msr faultmask, r0 @ encoding: [0x80,0xf3,0x13,0x80]
+@ CHECK: msr control, r0 @ encoding: [0x80,0xf3,0x14,0x80]
diff --git a/test/MC/ARM/thumb2.s b/test/MC/ARM/thumb2.s
deleted file mode 100644
index 7d632db..0000000
--- a/test/MC/ARM/thumb2.s
+++ /dev/null
@@ -1,355 +0,0 @@
-@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s
-@ XFAIL: *
-.code 16
-
-@ CHECK: adc r1, r1, #171 @ encoding: [0xab,0x01,0x41,0xf1]
- adc r1, r1, #171
-@ CHECK: adc r1, r1, #1179666 @ encoding: [0x12,0x11,0x41,0xf1]
- adc r1, r1, #1179666
-@ CHECK: adc r1, r1, #872428544 @ encoding: [0x34,0x21,0x41,0xf1]
- adc r1, r1, #872428544
-@ CHECK: adc r1, r1, #1448498774 @ encoding: [0x56,0x31,0x41,0xf1]
- adc r1, r1, #1448498774
-@ CHECK: adc r1, r1, #66846720 @ encoding: [0x7f,0x71,0x41,0xf1]
- adc r1, r1, #66846720
-
-@ CHECK: mvn r0, #187 @ encoding: [0xbb,0x00,0x6f,0xf0]
- mvn r0, #187
-@ CHECK: mvn r0, #11141290 @ encoding: [0xaa,0x10,0x6f,0xf0]
- mvn r0, #11141290
-@ CHECK: mvn r0, #-872363008 @ encoding: [0xcc,0x20,0x6f,0xf0]
- mvn r0, #-872363008
-@ CHECK: mvn r0, #1114112 @ encoding: [0x88,0x10,0x6f,0xf4]
- mvn r0, #1114112
-
-@ CHECK: cmp.w r0, #11141290 @ encoding: [0xaa,0x1f,0xb0,0xf1]
- cmp.w r0, #11141290
-@ CHECK: cmp.w r0, #-872363008 @ encoding: [0xcc,0x2f,0xb0,0xf1]
- cmp.w r0, #-872363008
-@ CHECK: cmp.w r0, #-572662307 @ encoding: [0xdd,0x3f,0xb0,0xf1]
- cmp.w r0, #-572662307
-@ CHECK: cmp.w r0, #1114112 @ encoding: [0x88,0x1f,0xb0,0xf5]
- cmp.w r0, #1114112
-@ CHECK: cmp.w r0, r1, lsl #5 @ encoding: [0x41,0x1f,0xb0,0xeb]
- cmp.w r0, r1, lsl #5
-
-@ CHECK: sxtab r0, r1, r0 @ encoding: [0x80,0xf0,0x41,0xfa]
- sxtab r0, r1, r0 @ encoding: [0x80,0xf0,0x41,0xfa]
-
-@ CHECK: movw r0, #65535 @ encoding: [0xff,0x70,0x4f,0xf6]
- movw r0, #65535
-@ CHECK: movw r1, #43777 @ encoding: [0x01,0x31,0x4a,0xf6]
- movw r1, #43777
-@ CHECK: movt r1, #427 @ encoding: [0xab,0x11,0xc0,0xf2]
- movt r1, #427
-@ CHECK: movw r1, #43792 @ encoding: [0x10,0x31,0x4a,0xf6]
- movw r1, #43792
-@ CHECK: movt r1, #4267 @ encoding: [0xab,0x01,0xc0,0xf2]
- movt r1, #4267
-@ CHECK: mov.w r0, #66846720 @ encoding: [0x7f,0x70,0x4f,0xf0]
- mov.w r0, #66846720
-
-@ Aliases w/ the vanilla 'mov' mnemonic, and explicit alternative selection.
- mov r2, #0xbf000000
- mov r1, #0x100
- mov r3, #32
- mov.w r3, #32
- movw r3, #32
-
-@ CHECK: mov.w r2, #3204448256 @ encoding: [0x4f,0xf0,0x3f,0x42]
-@ CHECK: mov.w r1, #256 @ encoding: [0x4f,0xf4,0x80,0x71]
-@ CHECK: mov r3, #32 @ encoding: [0x20,0x23]
-@ CHECK: mov.w r3, #32 @ encoding: [0x4f,0xf0,0x20,0x03]
-@ CHECK: movw r3, #32 @ encoding: [0x40,0xf2,0x20,0x03]
-
-
-
-
-@ CHECK: rrx r0, r0 @ encoding: [0x30,0x00,0x4f,0xea]
- rrx r0, r0
-
-@ CHECK: bfc r0, #4, #20 @ encoding: [0x17,0x10,0x6f,0xf3]
- bfc r0, #4, #20
-@ CHECK: bfc r0, #0, #23 @ encoding: [0x16,0x00,0x6f,0xf3]
- bfc r0, #0, #23
-@ CHECK: bfc r0, #12, #20 @ encoding: [0x1f,0x30,0x6f,0xf3]
- bfc r0, #12, #20
-
-@ CHECK: sbfx r0, r0, #7, #11 @ encoding: [0xca,0x10,0x40,0xf3]
- sbfx r0, r0, #7, #11
-@ CHECK: ubfx r0, r0, #7, #11 @ encoding: [0xca,0x10,0xc0,0xf3]
- ubfx r0, r0, #7, #11
-
-@ CHECK: mla r0, r0, r1, r2 @ encoding: [0x01,0x20,0x00,0xfb]
- mla r0, r0, r1, r2
-@ CHECK: mls r0, r0, r1, r2 @ encoding: [0x11,0x20,0x00,0xfb]
- mls r0, r0, r1, r2
-
-@ CHECK: smlabt r0, r1, r2, r0 @ encoding: [0x12,0x00,0x11,0xfb]
- smlabt r0, r1, r2, r0
-
-@ CHECK: clz r0, r0 @ encoding: [0x80,0xf0,0xb0,0xfa]
- clz r0, r0
-
-@ CHECK: pkhbt r0, r0, r1, lsl #16 @ encoding: [0x01,0x40,0xc0,0xea]
- pkhbt r0, r0, r1, lsl #16
-@ CHECK: pkhbt r0, r0, r1, lsl #12 @ encoding: [0x01,0x30,0xc0,0xea]
- pkhbt r0, r0, r1, lsl #16
-@ CHECK: pkhbt r0, r0, r1, lsl #18 @ encoding: [0x81,0x40,0xc0,0xea]
- pkhbt r0, r0, r1, lsl #18
-@ CHECK: pkhbt r0, r0, r1 @ encoding: [0x01,0x00,0xc0,0xea]
- pkhbt r0, r0, r1
-@ CHECK: pkhtb r0, r0, r1, asr #16 @ encoding: [0x21,0x40,0xc0,0xea]
- pkhtb r0, r0, r1, asr #16
-@ CHECK: pkhtb r0, r0, r1, asr #12 @ encoding: [0x21,0x30,0xc0,0xea]
- pkhtb r0, r0, r1, asr #12
-@ CHECK: pkhtb r0, r0, r1, asr #18 @ encoding: [0xa1,0x40,0xc0,0xea]
- pkhtb r0, r0, r1, asr #18
-@ CHECK: pkhtb r0, r0, r1, asr #22 @ encoding: [0xa1,0x50,0xc0,0xea]
- pkhtb r0, r0, r1, asr #22
-
-@ CHECK: str.w r0, [r1, #4092] @ encoding: [0xfc,0x0f,0xc1,0xf8]
- str.w r0, [r1, #4092]
-@ CHECK: str r0, [r1, #-128] @ encoding: [0x80,0x0c,0x41,0xf8]
- str r0, [r1, #-128]
-@ CHECK: str.w r0, [r1, r2, lsl #2] @ encoding: [0x22,0x00,0x41,0xf8
- str.w r0, [r1, r2, lsl #2]
-
-@ CHECK: ldr.w r0, [r0, #4092] @ encoding: [0xfc,0x0f,0xd0,0xf8]
- ldr.w r0, [r0, #4092]
-@ CHECK: ldr r0, [r0, #-128] @ encoding: [0x80,0x0c,0x50,0xf8]
- ldr r0, [r0, #-128]
-@ CHECK: ldr.w r0, [r0, r1, lsl #2] @ encoding: [0x21,0x00,0x50,0xf8]
- ldr.w r0, [r0, r1, lsl #2]
-
-@ CHECK: str r1, [r0, #16]! @ encoding: [0x10,0x1f,0x40,0xf8]
- str r1, [r0, #16]!
-@ CHECK: strh r1, [r0, #8]! @ encoding: [0x08,0x1f,0x20,0xf8]
- strh r1, [r0, #8]!
-@ CHECK: strh r2, [r0], #-4 @ encoding: [0x04,0x29,0x20,0xf8]
- strh r2, [r0], #-4
-@ CHECK: str r2, [r0], #-4 @ encoding: [0x04,0x29,0x40,0xf8]
- str r2, [r0], #-4
-
-@ CHECK: ldr r2, [r0, #16]! @ encoding: [0x10,0x2f,0x50,0xf8]
- ldr r2, [r0, #16]!
-@ CHECK: ldr r2, [r0, #-64]! @ encoding: [0x40,0x2d,0x50,0xf8]
- ldr r2, [r0, #-64]!
-@ CHECK: ldrsb r2, [r0, #4]! @ encoding: [0x04,0x2f,0x10,0xf9]
- ldrsb r2, [r0, #4]!
-
-@ CHECK: strb.w r0, [r1, #4092] @ encoding: [0xfc,0x0f,0x81,0xf8]
- strb.w r0, [r1, #4092]
-@ CHECK: strb r0, [r1, #-128] @ encoding: [0x80,0x0c,0x01,0xf8]
- strb r0, [r1, #-128]
-@ CHECK: strb.w r0, [r1, r2, lsl #2] @ encoding: [0x22,0x00,0x01,0xf8]
- strb.w r0, [r1, r2, lsl #2]
-@ CHECK: strh.w r0, [r1, #4092] @ encoding: [0xfc,0x0f,0xa1,0xf8]
- strh.w r0, [r1, #4092]
-@ CHECK: strh r0, [r1, #-128] @ encoding: [0x80,0x0c,0x21,0xf8]
- strh r0, [r1, #-128]
-@ CHECK: strh r0, [r1, #-128] @ encoding: [0x80,0x0c,0x21,0xf8]
- strh r0, [r1, #-128]
-@ CHECK: strh.w r0, [r1, r2, lsl #2] @ encoding: [0x22,0x00,0x21,0xf8]
- strh.w r0, [r1, r2, lsl #2]
-
-@ CHECK: ldrb r0, [r0, #-1] @ encoding: [0x01,0x0c,0x10,0xf8]
- ldrb r0, [r0, #-1]
-@ CHECK: ldrb r0, [r0, #-128] @ encoding: [0x80,0x0c,0x10,0xf8]
- ldrb r0, [r0, #-128]
-@ CHECK: ldrb.w r0, [r0, r1, lsl #2] @ encoding: [0x21,0x00,0x10,0xf8]
- ldrb.w r0, [r0, r1, lsl #2]
-@ CHECK: ldrh.w r0, [r0, #2046] @ encoding: [0xfe,0x07,0xb0,0xf8]
- ldrh.w r0, [r0, #2046]
-@ CHECK: ldrh r0, [r0, #-128] @ encoding: [0x80,0x0c,0x30,0xf8]
- ldrh r0, [r0, #-128]
-@ CHECK: ldrh.w r0, [r0, r1, lsl #2] @ encoding: [0x21,0x00,0x30,0xf8]
- ldrh.w r0, [r0, r1, lsl #2]
-@ CHECK: ldrsb.w r0, [r0] @ encoding: [0x00,0x00,0x90,0xf9]
- ldrsb.w r0, [r0]
-@ CHECK: ldrsh.w r0, [r0] @ encoding: [0x00,0x00,0xb0,0xf9]
- ldrsh.w r0, [r0]
-@ CHECK: bfi r0, r0, #5, #7 @ encoding: [0x60,0xf3,0x4b,0x10]
- bfi r0, r0, #5, #7
-@ CHECK: isb @ encoding: [0xbf,0xf3,0x6f,0x8f]
- isb
-@ CHECK: mrs r0, cpsr @ encoding: [0xef,0xf3,0x00,0x80]
- mrs r0, cpsr
-@ CHECK: vmrs r0, fpscr @ encoding: [0xf1,0xee,0x10,0x0a]
- vmrs r0, fpscr
-@ CHECK: vmrs r0, fpexc @ encoding: [0xf8,0xee,0x10,0x0a]
- vmrs r0, fpexc
-@ CHECK: vmrs r0, fpsid @ encoding: [0xf0,0xee,0x10,0x0a]
- vmrs r0, fpsid
-
-@ CHECK: vmsr fpscr, r0 @ encoding: [0xe1,0xee,0x10,0x0a]
- vmsr fpscr, r0
-@ CHECK: vmsr fpexc, r0 @ encoding: [0xe8,0xee,0x10,0x0a]
- vmsr fpexc, r0
-@ CHECK: vmsr fpsid, r0 @ encoding: [0xe0,0xee,0x10,0x0a]
- vmsr fpsid, r0
-
-@ CHECK: mcr p7, #1, r5, c1, c1, #4 @ encoding: [0x21,0xee,0x91,0x57]
- mcr p7, #1, r5, c1, c1, #4
-
-@ CHECK: mrc p14, #0, r1, c1, c2, #4 @ encoding: [0x11,0xee,0x92,0x1e]
- mrc p14, #0, r1, c1, c2, #4
-
-@ CHECK: mcrr p7, #1, r5, r4, c1 @ encoding: [0x44,0xec,0x11,0x57]
- mcrr p7, #1, r5, r4, c1
-
-@ CHECK: mrrc p7, #1, r5, r4, c1 @ encoding: [0x54,0xec,0x11,0x57]
- mrrc p7, #1, r5, r4, c1
-
-@ CHECK: mcr2 p7, #1, r5, c1, c1, #4 @ encoding: [0x21,0xfe,0x91,0x57]
- mcr2 p7, #1, r5, c1, c1, #4
-
-@ CHECK: mrc2 p14, #0, r1, c1, c2, #4 @ encoding: [0x11,0xfe,0x92,0x1e]
- mrc2 p14, #0, r1, c1, c2, #4
-
-@ CHECK: mcrr2 p7, #1, r5, r4, c1 @ encoding: [0x44,0xfc,0x11,0x57]
- mcrr2 p7, #1, r5, r4, c1
-
-@ CHECK: mrrc2 p7, #1, r5, r4, c1 @ encoding: [0x54,0xfc,0x11,0x57]
- mrrc2 p7, #1, r5, r4, c1
-
-@ CHECK: cdp p7, #1, c1, c1, c1, #4 @ encoding: [0x11,0xee,0x81,0x17]
- cdp p7, #1, c1, c1, c1, #4
-
-@ CHECK: cdp2 p7, #1, c1, c1, c1, #4 @ encoding: [0x11,0xfe,0x81,0x17]
- cdp2 p7, #1, c1, c1, c1, #4
-
-@ CHECK: clrex @ encoding: [0xbf,0xf3,0x2f,0x8f]
- clrex
-
-@ CHECK: clz r9, r0 @ encoding: [0xb0,0xfa,0x80,0xf9]
- clz r9, r0
-
-@ CHECK: qadd r1, r2, r3 @ encoding: [0x83,0xfa,0x82,0xf1]
- qadd r1, r2, r3
-
-@ CHECK: qsub r1, r2, r3 @ encoding: [0x83,0xfa,0xa2,0xf1]
- qsub r1, r2, r3
-
-@ CHECK: qdadd r1, r2, r3 @ encoding: [0x83,0xfa,0x92,0xf1]
- qdadd r1, r2, r3
-
-@ CHECK: qdsub r1, r2, r3 @ encoding: [0x83,0xfa,0xb2,0xf1]
- qdsub r1, r2, r3
-
-@ CHECK: nop.w @ encoding: [0xaf,0xf3,0x00,0x80]
- nop.w
-
-@ CHECK: yield.w @ encoding: [0xaf,0xf3,0x01,0x80]
- yield.w
-
-@ CHECK: wfe.w @ encoding: [0xaf,0xf3,0x02,0x80]
- wfe.w
-
-@ CHECK: wfi.w @ encoding: [0xaf,0xf3,0x03,0x80]
- wfi.w
-
-@ CHECK: dmb sy @ encoding: [0xbf,0xf3,0x5f,0x8f]
- dmb sy
-@ CHECK: dmb st @ encoding: [0xbf,0xf3,0x5e,0x8f]
- dmb st
-@ CHECK: dmb ish @ encoding: [0xbf,0xf3,0x5b,0x8f]
- dmb ish
-@ CHECK: dmb ishst @ encoding: [0xbf,0xf3,0x5a,0x8f]
- dmb ishst
-@ CHECK: dmb nsh @ encoding: [0xbf,0xf3,0x57,0x8f]
- dmb nsh
-@ CHECK: dmb nshst @ encoding: [0xbf,0xf3,0x56,0x8f]
- dmb nshst
-@ CHECK: dmb osh @ encoding: [0xbf,0xf3,0x53,0x8f]
- dmb osh
-@ CHECK: dmb oshst @ encoding: [0xbf,0xf3,0x52,0x8f]
- dmb oshst
-
-@ CHECK: dsb sy @ encoding: [0xbf,0xf3,0x4f,0x8f]
- dsb sy
-@ CHECK: dsb st @ encoding: [0xbf,0xf3,0x4e,0x8f]
- dsb st
-@ CHECK: dsb ish @ encoding: [0xbf,0xf3,0x4b,0x8f]
- dsb ish
-@ CHECK: dsb ishst @ encoding: [0xbf,0xf3,0x4a,0x8f]
- dsb ishst
-@ CHECK: dsb nsh @ encoding: [0xbf,0xf3,0x47,0x8f]
- dsb nsh
-@ CHECK: dsb nshst @ encoding: [0xbf,0xf3,0x46,0x8f]
- dsb nshst
-@ CHECK: dsb osh @ encoding: [0xbf,0xf3,0x43,0x8f]
- dsb osh
-@ CHECK: dsb oshst @ encoding: [0xbf,0xf3,0x42,0x8f]
- dsb oshst
-
-@ CHECK: cpsie.w aif @ encoding: [0xaf,0xf3,0xe0,0x84]
- cpsie.w aif
-@ CHECK: cps #15 @ encoding: [0xaf,0xf3,0x0f,0x81]
- cps #15
-@ CHECK: cpsie.w if, #10 @ encoding: [0xaf,0xf3,0x6a,0x85]
- cpsie.w if, #10
-
-@ CHECK: msr cpsr_fc, r0 @ encoding: [0x80,0xf3,0x00,0x89]
- msr apsr, r0
-@ CHECK: msr cpsr_s, r0 @ encoding: [0x80,0xf3,0x00,0x84]
- msr apsr_g, r0
-@ CHECK: msr cpsr_f, r0 @ encoding: [0x80,0xf3,0x00,0x88]
- msr apsr_nzcvq, r0
-@ CHECK: msr cpsr_fs, r0 @ encoding: [0x80,0xf3,0x00,0x8c]
- msr apsr_nzcvqg, r0
-@ CHECK: msr cpsr_fc, r0 @ encoding: [0x80,0xf3,0x00,0x89]
- msr cpsr_fc, r0
-@ CHECK: msr cpsr_c, r0 @ encoding: [0x80,0xf3,0x00,0x81]
- msr cpsr_c, r0
-@ CHECK: msr cpsr_x, r0 @ encoding: [0x80,0xf3,0x00,0x82]
- msr cpsr_x, r0
-@ CHECK: msr cpsr_fc, r0 @ encoding: [0x80,0xf3,0x00,0x89]
- msr cpsr_fc, r0
-@ CHECK: msr cpsr_fsx, r0 @ encoding: [0x80,0xf3,0x00,0x8e]
- msr cpsr_fsx, r0
-@ CHECK: msr spsr_fc, r0 @ encoding: [0x90,0xf3,0x00,0x89]
- msr spsr_fc, r0
-@ CHECK: msr spsr_fsxc, r0 @ encoding: [0x90,0xf3,0x00,0x8f]
- msr spsr_fsxc, r0
-@ CHECK: msr cpsr_fsxc, r0 @ encoding: [0x80,0xf3,0x00,0x8f]
- msr cpsr_fsxc, r0
-
-@ CHECK: strexb r0, r1, [r2] @ encoding: [0xc2,0xe8,0x40,0x1f]
- strexb r0, r1, [r2]
-@ CHECK: strexh r0, r1, [r2] @ encoding: [0xc2,0xe8,0x50,0x1f]
- strexh r0, r1, [r2]
-@ CHECK: strex r0, r1, [r2] @ encoding: [0x42,0xe8,0x00,0x10]
- strex r0, r1, [r2]
-@ CHECK: strexd r0, r2, r3, [r1] @ encoding: [0xc1,0xe8,0x70,0x23]
- strexd r0, r2, r3, [r1]
-@ CHECK: ldrexb r0, [r0] @ encoding: [0xd0,0xe8,0x4f,0x0f]
- ldrexb r0, [r0]
-@ CHECK: ldrexh r0, [r0] @ encoding: [0xd0,0xe8,0x5f,0x0f]
- ldrexh r0, [r0]
-@ CHECK: ldrex r0, [r0] @ encoding: [0x50,0xe8,0x00,0x0f]
- ldrex r0, [r0]
-@ CHECK: ldrexd r0, r1, [r0] @ encoding: [0xd0,0xe8,0x7f,0x01]
- ldrexd r0, r1, [r0]
-@ CHECK: ssat16 r0, #7, r0 @ encoding: [0x20,0xf3,0x06,0x00]
- ssat16 r0, #7, r0
-
- and r1, #0xff
- and r1, r1, #0xff
- orr r1, 0x100
- orr r1, r1, 0x100
- eor r1, 0x100
- eor r1, r1, 0x100
- bic r1, 0x100
- bic r1, r1, 0x100
-
-@ CHECK: and r1, r1, #255 @ encoding: [0x01,0xf0,0xff,0x01]
-@ CHECK: and r1, r1, #255 @ encoding: [0x01,0xf0,0xff,0x01]
-@ CHECK: orr r1, r1, #256 @ encoding: [0x41,0xf4,0x80,0x71]
-@ CHECK: orr r1, r1, #256 @ encoding: [0x41,0xf4,0x80,0x71]
-@ CHECK: eor r1, r1, #256 @ encoding: [0x81,0xf4,0x80,0x71]
-@ CHECK: eor r1, r1, #256 @ encoding: [0x81,0xf4,0x80,0x71]
-@ CHECK: bic r1, r1, #256 @ encoding: [0x21,0xf4,0x80,0x71]
-@ CHECK: bic r1, r1, #256 @ encoding: [0x21,0xf4,0x80,0x71]
-
-
diff --git a/test/MC/ARM/thumb2_instructions.s b/test/MC/ARM/thumb2_instructions.s
deleted file mode 100644
index 71cd4ae..0000000
--- a/test/MC/ARM/thumb2_instructions.s
+++ /dev/null
@@ -1,12 +0,0 @@
-@ RUN: llvm-mc -triple thumbv7-unknown-unknown -show-encoding %s > %t
-@ RUN: FileCheck < %t %s
-
- .syntax unified
- .text
-
-@ FIXME: This is not the correct instruction representation, but at least we are
-@ parsing the ldr to something.
-@
-@ CHECK: ldr r0, [r7, #258]
- ldr r0, [r7, #-8]
-
diff --git a/test/MC/ARM/xscale-attributes.ll b/test/MC/ARM/xscale-attributes.ll
index e576278..3ccf02b 100644
--- a/test/MC/ARM/xscale-attributes.ll
+++ b/test/MC/ARM/xscale-attributes.ll
@@ -17,7 +17,7 @@ entry:
; ASM-NEXT: .eabi_attribute 8, 1
; ASM-NEXT: .eabi_attribute 9, 1
-; OBJ: Section 0x00000004
+; OBJ: Section 4
; OBJ-NEXT: 'sh_name', 0x0000000c
; OBJ-NEXT: 'sh_type', 0x70000003
; OBJ-NEXT: 'sh_flags', 0x00000000
diff --git a/test/MC/AsmParser/2011-09-06-NoNewline.s b/test/MC/AsmParser/2011-09-06-NoNewline.s
new file mode 100644
index 0000000..7ecaf68
--- /dev/null
+++ b/test/MC/AsmParser/2011-09-06-NoNewline.s
@@ -0,0 +1,6 @@
+// RUN: llvm-mc %s
+movl %gs:8, %eax
+// RUN: llvm-mc %s
+movl %gs:8, %eax
+// RUN: llvm-mc %s
+movl %gs:8, %eax \ No newline at end of file
diff --git a/test/MC/AsmParser/exprs.s b/test/MC/AsmParser/exprs.s
index 153701d..df075f8 100644
--- a/test/MC/AsmParser/exprs.s
+++ b/test/MC/AsmParser/exprs.s
@@ -5,12 +5,12 @@
.abort Unexpected $0 != $1.
.endif
.endmacro
-
+
.text
g:
h:
j:
-k:
+k:
.data
check_expr !1 + 2, 2
check_expr !0, 1
@@ -44,7 +44,8 @@ k:
check_expr 0 || 1, 1
check_expr 0 || 0, 0
check_expr 1 + 2 < 3 + 4, 1
-
+ check_expr 1 << 8 - 1, 128
+
.set c, 10
check_expr c + 1, 11
@@ -56,15 +57,15 @@ k:
i = (j + 10) - (k + 2)
.long i
-
+
l = m - n + 4
-
+
.text
m:
n:
nop
-
-
+
+
movw $8, (42)+66(%eax)
// "." support:
diff --git a/test/MC/AsmParser/labels.s b/test/MC/AsmParser/labels.s
index 3bc7e63..5609175 100644
--- a/test/MC/AsmParser/labels.s
+++ b/test/MC/AsmParser/labels.s
@@ -35,9 +35,6 @@ foo:
// CHECK: .globl "a 3"
.globl "a 3"
-// CHECK: .weak "a 4"
- .weak "a 4"
-
// CHECK: .desc "a 5",1
.desc "a 5", 1
diff --git a/test/MC/AsmParser/line_with_hash.s b/test/MC/AsmParser/line_with_hash.s
new file mode 100644
index 0000000..6fdab40
--- /dev/null
+++ b/test/MC/AsmParser/line_with_hash.s
@@ -0,0 +1,15 @@
+# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s
+
+// We used to incorrectly parse a line with only a # in it
+
+.zero 42
+#
+.ifndef FOO
+.zero 2
+.else
+.endif
+.zero 24
+
+// CHECK: .zero 42
+// CHECK-NEXT: .zero 2
+// CHECK-NEXT: .zero 24
diff --git a/test/MC/Disassembler/ARM/arm-tests.txt b/test/MC/Disassembler/ARM/arm-tests.txt
index 0536eeb..69a094d 100644
--- a/test/MC/Disassembler/ARM/arm-tests.txt
+++ b/test/MC/Disassembler/ARM/arm-tests.txt
@@ -1,4 +1,4 @@
-# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 | FileCheck %s
+# RUN: llvm-mc --disassemble %s -triple=armv7-apple-darwin9 -mattr +mp | FileCheck %s
# CHECK: addpl r4, pc, #318767104
0x4c 0x45 0x8f 0x52
@@ -45,8 +45,11 @@
# CHECK: isb
0x6f 0xf0 0x7f 0xf5
-# CHECK: ldclvc p5, cr15, [r8], #-0
-0x00 0xf5 0x78 0x7c
+# FIXME: LDC encoding information is incorrect. Re-enable this along with more
+# robust testing for other values when we get it fleshed out and working
+# properly.
+# CHECKx: ldclvc p5, cr15, [r8], #-0
+#0x00 0xf5 0x78 0x7c
# CHECK: ldr r0, [r2], #15
0x0f 0x00 0x92 0xe4
@@ -57,11 +60,14 @@
# CHECK: ldrh r0, [r2], #0
0xb0 0x00 0xd2 0xe0
+# CHECK: ldrh r0, [r2]
+0xb0 0x00 0xd2 0xe1
+
# CHECK: ldrht r0, [r2], #15
0xbf 0x00 0xf2 0xe0
# CHECK: ldrsbtvs lr, [r2], -r9
-0xd9 0xe9 0x32 0x60
+0xd9 0xe0 0x32 0x60
# CHECK: lsls r0, r2, #31
0x82 0x0f 0xb0 0xe1
@@ -101,6 +107,12 @@
# CHECK: rfedb r0!
0x00 0x0a 0x30 0xf9
+# CHECK: srsdb sp!, #19
+0x13 0x05 0x6d 0xf9
+
+# CHECK: srsia sp, #9
+0x09 0x05 0xcd 0xf8
+
# CHECK-NOT: rsbeq r0, r2, r0, lsl #0
# CHECK: rsbeq r0, r2, r0
0x00 0x00 0x62 0x00
@@ -149,10 +161,10 @@
# CHECK: cpsie if, #10
0xca 0x00 0x0a 0xf1
-# CHECK: msr cpsr_fc, r0
+# CHECK: msr CPSR_fc, r0
0x00 0xf0 0x29 0xe1
-# CHECK: msrmi cpsr_c, #4043309056
+# CHECK: msrmi CPSR_c, #4043309056
0xf1 0xf4 0x21 0x43
# CHECK: rsbs r6, r7, r8
@@ -168,7 +180,7 @@
0x15 0xff 0x2f 0x01
# CHECK: uqadd16mi r6, r11, r8
-0x18 0x60 0x6b 0x46
+0x18 0x6F 0x6b 0x46
# CHECK: str r0, [sp, #4]
0x04 0x00 0x8d 0xe5
@@ -221,7 +233,7 @@
# CHECK: umull r1, r2, r3, r4
0x93 0x14 0x82 0xe0
-# CHECK: pld [pc, #-0]
+# CHECK: pldw [pc, #-0]
0x00 0xf0 0x1f 0xf5
# CHECK: pli [pc, #-0]
@@ -230,12 +242,15 @@
# CHECK: pli [r3, r1, lsl #2]
0x01 0xf1 0xd3 0xf6
-# CHECK: stc p2, cr4, [r9], {157}
+# CHECK: stc p2, c4, [r9], {157}
0x9d 0x42 0x89 0xec
-# CHECK: stc2 p2, cr4, [r9], {157}
+# CHECK: stc2 p2, c4, [r9], {157}
0x9d 0x42 0x89 0xfc
+# CHECK: bne #-24
+0xfa 0xff 0xff 0x1a
+
# CHECK: blx #60
0x0f 0x00 0x00 0xfa
@@ -287,3 +302,18 @@
# CHECK: nop
0x00 0xf0 0x20 0xe3
+
+# CHECK: andeq r0, r0, r0, lsr #32
+0x20 0x00 0x00 0x00
+
+# CHECK: strb r3, [r2], #1
+0x01 0x30 0xc2 0xe4
+
+# CHECK: strheq r0, [r0, -r0]
+0xb0 0x00 0x00 0x01
+
+# CHECK: rfedb #4!
+0x14 0x0 0x32 0xf9
+
+# CHECK: stc2l p0, c0, [r2], #-96
+0x18 0x0 0x62 0xfc
diff --git a/test/MC/Disassembler/ARM/basic-arm-instructions.txt b/test/MC/Disassembler/ARM/basic-arm-instructions.txt
new file mode 100644
index 0000000..fc7eda5
--- /dev/null
+++ b/test/MC/Disassembler/ARM/basic-arm-instructions.txt
@@ -0,0 +1,2362 @@
+# RUN: llvm-mc -triple=armv7-apple-darwin -disassemble < %s | FileCheck %s
+
+#------------------------------------------------------------------------------
+# ADC (immediate)
+#------------------------------------------------------------------------------
+# CHECK: adc r1, r2, #15
+# CHECK: adc r1, r2, #240
+# CHECK: adc r1, r2, #3840
+# CHECK: adc r1, r2, #61440
+# CHECK: adc r1, r2, #983040
+# CHECK: adc r1, r2, #15728640
+# CHECK: adc r1, r2, #251658240
+# CHECK: adc r1, r2, #4026531840
+# CHECK: adc r1, r2, #4026531855
+# CHECK: adcs r1, r2, #3840
+# CHECK: adcseq r1, r2, #3840
+# CHECK: adceq r1, r2, #3840
+
+0x0f 0x10 0xa2 0xe2
+0xf0 0x10 0xa2 0xe2
+0x0f 0x1c 0xa2 0xe2
+0x0f 0x1a 0xa2 0xe2
+0x0f 0x18 0xa2 0xe2
+0x0f 0x16 0xa2 0xe2
+0x0f 0x14 0xa2 0xe2
+0x0f 0x12 0xa2 0xe2
+0xff 0x12 0xa2 0xe2
+
+0x0f 0x1c 0xb2 0xe2
+0x0f 0x1c 0xb2 0x02
+0x0f 0x1c 0xa2 0x02
+
+#------------------------------------------------------------------------------
+# ADC (register)
+# ADC (shifted register)
+#------------------------------------------------------------------------------
+# CHECK: adc r4, r5, r6
+
+# CHECK: adc r4, r5, r6, lsl #1
+# CHECK: adc r4, r5, r6, lsl #31
+# CHECK: adc r4, r5, r6, lsr #1
+# CHECK: adc r4, r5, r6, lsr #31
+# CHECK: adc r4, r5, r6, lsr #32
+# CHECK: adc r4, r5, r6, asr #1
+# CHECK: adc r4, r5, r6, asr #31
+# CHECK: adc r4, r5, r6, asr #32
+# CHECK: adc r4, r5, r6, ror #1
+# CHECK: adc r4, r5, r6, ror #31
+
+# CHECK: adc r6, r7, r8, lsl r9
+# CHECK: adc r6, r7, r8, lsr r9
+# CHECK: adc r6, r7, r8, asr r9
+# CHECK: adc r6, r7, r8, ror r9
+# CHECK: adc r4, r5, r6, rrx
+
+# CHECK: adc r5, r5, r6
+# CHECK: adc r4, r4, r5, lsl #1
+# CHECK: adc r4, r4, r5, lsl #31
+# CHECK: adc r4, r4, r5, lsr #1
+# CHECK: adc r4, r4, r5, lsr #31
+# CHECK: adc r4, r4, r5, lsr #32
+# CHECK: adc r4, r4, r5, asr #1
+# CHECK: adc r4, r4, r5, asr #31
+# CHECK: adc r4, r4, r5, asr #32
+# CHECK: adc r4, r4, r5, ror #1
+# CHECK: adc r4, r4, r5, ror #31
+# CHECK: adc r4, r4, r5, rrx
+# CHECK: adc r6, r6, r7, lsl r9
+# CHECK: adc r6, r6, r7, lsr r9
+# CHECK: adc r6, r6, r7, asr r9
+# CHECK: adc r6, r6, r7, ror r9
+# CHECK: adc r4, r4, r5, rrx
+
+0x06 0x40 0xa5 0xe0
+
+0x86 0x40 0xa5 0xe0
+0x86 0x4f 0xa5 0xe0
+0xa6 0x40 0xa5 0xe0
+0xa6 0x4f 0xa5 0xe0
+0x26 0x40 0xa5 0xe0
+0xc6 0x40 0xa5 0xe0
+0xc6 0x4f 0xa5 0xe0
+0x46 0x40 0xa5 0xe0
+0xe6 0x40 0xa5 0xe0
+0xe6 0x4f 0xa5 0xe0
+
+0x18 0x69 0xa7 0xe0
+0x38 0x69 0xa7 0xe0
+0x58 0x69 0xa7 0xe0
+0x78 0x69 0xa7 0xe0
+0x66 0x40 0xa5 0xe0
+
+0x06 0x50 0xa5 0xe0
+0x85 0x40 0xa4 0xe0
+0x85 0x4f 0xa4 0xe0
+0xa5 0x40 0xa4 0xe0
+0xa5 0x4f 0xa4 0xe0
+0x25 0x40 0xa4 0xe0
+0xc5 0x40 0xa4 0xe0
+0xc5 0x4f 0xa4 0xe0
+0x45 0x40 0xa4 0xe0
+0xe5 0x40 0xa4 0xe0
+0xe5 0x4f 0xa4 0xe0
+0x65 0x40 0xa4 0xe0
+0x17 0x69 0xa6 0xe0
+0x37 0x69 0xa6 0xe0
+0x57 0x69 0xa6 0xe0
+0x77 0x69 0xa6 0xe0
+0x65 0x40 0xa4 0xe0
+
+#------------------------------------------------------------------------------
+# ADD
+#------------------------------------------------------------------------------
+# CHECK: add r4, r5, #61440
+# CHECK: add r4, r5, r6
+# CHECK: add r4, r5, r6, lsl #5
+# CHECK: add r4, r5, r6, lsr #5
+# CHECK: add r4, r5, r6, lsr #5
+# CHECK: add r4, r5, r6, asr #5
+# CHECK: add r4, r5, r6, ror #5
+# CHECK: add r6, r7, r8, lsl r9
+# CHECK: add r6, r7, r8, lsr r9
+# CHECK: add r6, r7, r8, asr r9
+# CHECK: add r6, r7, r8, ror r9
+# CHECK: add r4, r5, r6, rrx
+
+# CHECK: add r5, r5, #61440
+# CHECK: add r4, r4, r5
+# CHECK: add r4, r4, r5, lsl #5
+# CHECK: add r4, r4, r5, lsr #5
+# CHECK: add r4, r4, r5, lsr #5
+# CHECK: add r4, r4, r5, asr #5
+# CHECK: add r4, r4, r5, ror #5
+# CHECK: add r6, r6, r7, lsl r9
+# CHECK: add r6, r6, r7, lsr r9
+# CHECK: add r6, r6, r7, asr r9
+# CHECK: add r6, r6, r7, ror r9
+# CHECK: add r4, r4, r5, rrx
+
+0x0f 0x4a 0x85 0xe2
+0x06 0x40 0x85 0xe0
+0x86 0x42 0x85 0xe0
+0xa6 0x42 0x85 0xe0
+0xa6 0x42 0x85 0xe0
+0xc6 0x42 0x85 0xe0
+0xe6 0x42 0x85 0xe0
+0x18 0x69 0x87 0xe0
+0x38 0x69 0x87 0xe0
+0x58 0x69 0x87 0xe0
+0x78 0x69 0x87 0xe0
+0x66 0x40 0x85 0xe0
+
+
+0x0f 0x5a 0x85 0xe2
+0x05 0x40 0x84 0xe0
+0x85 0x42 0x84 0xe0
+0xa5 0x42 0x84 0xe0
+0xa5 0x42 0x84 0xe0
+0xc5 0x42 0x84 0xe0
+0xe5 0x42 0x84 0xe0
+0x17 0x69 0x86 0xe0
+0x37 0x69 0x86 0xe0
+0x57 0x69 0x86 0xe0
+0x77 0x69 0x86 0xe0
+0x65 0x40 0x84 0xe0
+
+#------------------------------------------------------------------------------
+# ADR
+#------------------------------------------------------------------------------
+# CHECK: add r2, pc, #3
+# CHECK: sub r2, pc, #3
+
+0x03 0x20 0x8f 0xe2
+0x03 0x20 0x4f 0xe2
+
+#------------------------------------------------------------------------------
+# AND
+#------------------------------------------------------------------------------
+# CHECK: and r10, r1, #15
+# CHECK: and r10, r1, r6
+# CHECK: and r10, r1, r6, lsl #10
+# CHECK: and r10, r1, r6, lsr #10
+# CHECK: and r10, r1, r6, lsr #10
+# CHECK: and r10, r1, r6, asr #10
+# CHECK: and r10, r1, r6, ror #10
+# CHECK: and r6, r7, r8, lsl r2
+# CHECK: and r6, r7, r8, lsr r2
+# CHECK: and r6, r7, r8, asr r2
+# CHECK: and r6, r7, r8, ror r2
+# CHECK: and r10, r1, r6, rrx
+
+# CHECK: and r1, r1, #15
+# CHECK: and r10, r10, r1
+# CHECK: and r10, r10, r1, lsl #10
+# CHECK: and r10, r10, r1, lsr #10
+# CHECK: and r10, r10, r1, lsr #10
+# CHECK: and r10, r10, r1, asr #10
+# CHECK: and r10, r10, r1, ror #10
+# CHECK: and r6, r6, r7, lsl r2
+# CHECK: and r6, r6, r7, lsr r2
+# CHECK: and r6, r6, r7, asr r2
+# CHECK: and r6, r6, r7, ror r2
+# CHECK: and r10, r10, r1, rrx
+
+0x0f 0xa0 0x01 0xe2
+0x06 0xa0 0x01 0xe0
+0x06 0xa5 0x01 0xe0
+0x26 0xa5 0x01 0xe0
+0x26 0xa5 0x01 0xe0
+0x46 0xa5 0x01 0xe0
+0x66 0xa5 0x01 0xe0
+0x18 0x62 0x07 0xe0
+0x38 0x62 0x07 0xe0
+0x58 0x62 0x07 0xe0
+0x78 0x62 0x07 0xe0
+0x66 0xa0 0x01 0xe0
+
+0x0f 0x10 0x01 0xe2
+0x01 0xa0 0x0a 0xe0
+0x01 0xa5 0x0a 0xe0
+0x21 0xa5 0x0a 0xe0
+0x21 0xa5 0x0a 0xe0
+0x41 0xa5 0x0a 0xe0
+0x61 0xa5 0x0a 0xe0
+0x17 0x62 0x06 0xe0
+0x37 0x62 0x06 0xe0
+0x57 0x62 0x06 0xe0
+0x77 0x62 0x06 0xe0
+0x61 0xa0 0x0a 0xe0
+
+#------------------------------------------------------------------------------
+# FIXME: ASR
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# BFC
+#------------------------------------------------------------------------------
+# CHECK: bfc r5, #3, #17
+# CHECK: bfclo r5, #3, #17
+
+0x9f 0x51 0xd3 0xe7
+0x9f 0x51 0xd3 0x37
+
+
+#------------------------------------------------------------------------------
+# BFI
+#------------------------------------------------------------------------------
+# CHECK: bfi r5, r2, #3, #17
+# CHECK: bfine r5, r2, #3, #17
+
+0x92 0x51 0xd3 0xe7
+0x92 0x51 0xd3 0x17
+
+
+#------------------------------------------------------------------------------
+# BIC
+#------------------------------------------------------------------------------
+# CHECK: bic r10, r1, #15
+# CHECK: bic r10, r1, r6
+# CHECK: bic r10, r1, r6, lsl #10
+# CHECK: bic r10, r1, r6, lsr #10
+# CHECK: bic r10, r1, r6, lsr #10
+# CHECK: bic r10, r1, r6, asr #10
+# CHECK: bic r10, r1, r6, ror #10
+# CHECK: bic r6, r7, r8, lsl r2
+# CHECK: bic r6, r7, r8, lsr r2
+# CHECK: bic r6, r7, r8, asr r2
+# CHECK: bic r6, r7, r8, ror r2
+# CHECK: bic r10, r1, r6, rrx
+
+# CHECK: bic r1, r1, #15
+# CHECK: bic r10, r10, r1
+# CHECK: bic r10, r10, r1, lsl #10
+# CHECK: bic r10, r10, r1, lsr #10
+# CHECK: bic r10, r10, r1, lsr #10
+# CHECK: bic r10, r10, r1, asr #10
+# CHECK: bic r10, r10, r1, ror #10
+# CHECK: bic r6, r6, r7, lsl r2
+# CHECK: bic r6, r6, r7, lsr r2
+# CHECK: bic r6, r6, r7, asr r2
+# CHECK: bic r6, r6, r7, ror r2
+# CHECK: bic r10, r10, r1, rrx
+
+0x0f 0xa0 0xc1 0xe3
+0x06 0xa0 0xc1 0xe1
+0x06 0xa5 0xc1 0xe1
+0x26 0xa5 0xc1 0xe1
+0x26 0xa5 0xc1 0xe1
+0x46 0xa5 0xc1 0xe1
+0x66 0xa5 0xc1 0xe1
+0x18 0x62 0xc7 0xe1
+0x38 0x62 0xc7 0xe1
+0x58 0x62 0xc7 0xe1
+0x78 0x62 0xc7 0xe1
+0x66 0xa0 0xc1 0xe1
+
+
+0x0f 0x10 0xc1 0xe3
+0x01 0xa0 0xca 0xe1
+0x01 0xa5 0xca 0xe1
+0x21 0xa5 0xca 0xe1
+0x21 0xa5 0xca 0xe1
+0x41 0xa5 0xca 0xe1
+0x61 0xa5 0xca 0xe1
+0x17 0x62 0xc6 0xe1
+0x37 0x62 0xc6 0xe1
+0x57 0x62 0xc6 0xe1
+0x77 0x62 0xc6 0xe1
+0x61 0xa0 0xca 0xe1
+
+#------------------------------------------------------------------------------
+# BKPT
+#------------------------------------------------------------------------------
+# CHECK: bkpt #10
+# CHECK: bkpt #65535
+
+0x7a 0x00 0x20 0xe1
+0x7f 0xff 0x2f 0xe1
+
+#------------------------------------------------------------------------------
+# BLX (register)
+#------------------------------------------------------------------------------
+# CHECK: blx r2
+# CHECK: blxne r2
+
+0x32 0xff 0x2f 0xe1
+0x32 0xff 0x2f 0x11
+
+#------------------------------------------------------------------------------
+# BLX (immediate)
+#------------------------------------------------------------------------------
+# CHECK: blx #32424576
+# CHECK: blx #16212288
+
+0xa0 0xb0 0x7b 0xfa
+0x50 0xd8 0x3d 0xfa
+
+#------------------------------------------------------------------------------
+# BX
+#------------------------------------------------------------------------------
+
+# CHECK: bx r2
+# CHECK: bxne r2
+
+0x12 0xff 0x2f 0xe1
+0x12 0xff 0x2f 0x11
+
+#------------------------------------------------------------------------------
+# BXJ
+#------------------------------------------------------------------------------
+
+# CHECK: bxj r2
+# CHECK: bxjne r2
+
+0x22 0xff 0x2f 0xe1
+0x22 0xff 0x2f 0x11
+
+
+#------------------------------------------------------------------------------
+# CDP/CDP2
+#------------------------------------------------------------------------------
+# CHECK: cdp p7, #1, c1, c1, c1, #4
+# CHECK: cdp2 p7, #1, c1, c1, c1, #4
+
+0x81 0x17 0x11 0xee
+0x81 0x17 0x11 0xfe
+
+
+#------------------------------------------------------------------------------
+# CLREX
+#------------------------------------------------------------------------------
+# CHECK: clrex
+
+0x1f 0xf0 0x7f 0xf5
+
+
+#------------------------------------------------------------------------------
+# CLZ
+#------------------------------------------------------------------------------
+# CHECK: clz r1, r2
+# CHECK: clzeq r1, r2
+
+0x12 0x1f 0x6f 0xe1
+0x12 0x1f 0x6f 0x01
+
+#------------------------------------------------------------------------------
+# CMN
+#------------------------------------------------------------------------------
+# CHECK: cmn r1, #15
+# CHECK: cmn r1, r6
+# CHECK: cmn r1, r6, lsl #10
+# CHECK: cmn r1, r6, lsr #10
+# CHECK: cmn sp, r6, lsr #10
+# CHECK: cmn r1, r6, asr #10
+# CHECK: cmn r1, r6, ror #10
+# CHECK: cmn r7, r8, lsl r2
+# CHECK: cmn sp, r8, lsr r2
+# CHECK: cmn r7, r8, asr r2
+# CHECK: cmn r7, r8, ror r2
+# CHECK: cmn r1, r6, rrx
+
+0x0f 0x00 0x71 0xe3
+0x06 0x00 0x71 0xe1
+0x06 0x05 0x71 0xe1
+0x26 0x05 0x71 0xe1
+0x26 0x05 0x7d 0xe1
+0x46 0x05 0x71 0xe1
+0x66 0x05 0x71 0xe1
+0x18 0x02 0x77 0xe1
+0x38 0x02 0x7d 0xe1
+0x58 0x02 0x77 0xe1
+0x78 0x02 0x77 0xe1
+0x66 0x00 0x71 0xe1
+
+#------------------------------------------------------------------------------
+# CMP
+#------------------------------------------------------------------------------
+# CHECK: cmp r1, #15
+# CHECK: cmp r1, r6
+# CHECK: cmp r1, r6, lsl #10
+# CHECK: cmp r1, r6, lsr #10
+# CHECK: cmp sp, r6, lsr #10
+# CHECK: cmp r1, r6, asr #10
+# CHECK: cmp r1, r6, ror #10
+# CHECK: cmp r7, r8, lsl r2
+# CHECK: cmp sp, r8, lsr r2
+# CHECK: cmp r7, r8, asr r2
+# CHECK: cmp r7, r8, ror r2
+# CHECK: cmp r1, r6, rrx
+
+0x0f 0x00 0x51 0xe3
+0x06 0x00 0x51 0xe1
+0x06 0x05 0x51 0xe1
+0x26 0x05 0x51 0xe1
+0x26 0x05 0x5d 0xe1
+0x46 0x05 0x51 0xe1
+0x66 0x05 0x51 0xe1
+0x18 0x02 0x57 0xe1
+0x38 0x02 0x5d 0xe1
+0x58 0x02 0x57 0xe1
+0x78 0x02 0x57 0xe1
+0x66 0x00 0x51 0xe1
+
+
+#------------------------------------------------------------------------------
+# CPS
+#------------------------------------------------------------------------------
+# CHECK: cpsie aif
+# CHECK: cps #15
+# CHECK: cpsid if, #10
+
+0xc0 0x01 0x08 0xf1
+0x0f 0x00 0x02 0xf1
+0xca 0x00 0x0e 0xf1
+
+
+#------------------------------------------------------------------------------
+# DBG
+#------------------------------------------------------------------------------
+# CHECK: dbg #0
+# CHECK: dbg #5
+# CHECK: dbg #15
+
+0xf0 0xf0 0x20 0xe3
+0xf5 0xf0 0x20 0xe3
+0xff 0xf0 0x20 0xe3
+
+
+#------------------------------------------------------------------------------
+# DMB
+#------------------------------------------------------------------------------
+# CHECK: dmb sy
+# CHECK: dmb st
+# CHECK: dmb ish
+# CHECK: dmb ishst
+# CHECK: dmb nsh
+# CHECK: dmb nshst
+# CHECK: dmb osh
+# CHECK: dmb oshst
+# CHECK: dmb
+
+0x5f 0xf0 0x7f 0xf5
+0x5e 0xf0 0x7f 0xf5
+0x5b 0xf0 0x7f 0xf5
+0x5a 0xf0 0x7f 0xf5
+0x57 0xf0 0x7f 0xf5
+0x56 0xf0 0x7f 0xf5
+0x53 0xf0 0x7f 0xf5
+0x52 0xf0 0x7f 0xf5
+0x5f 0xf0 0x7f 0xf5
+
+#------------------------------------------------------------------------------
+# DSB
+#------------------------------------------------------------------------------
+# CHECK: dsb sy
+# CHECK: dsb st
+# CHECK: dsb ish
+# CHECK: dsb ishst
+# CHECK: dsb nsh
+# CHECK: dsb nshst
+# CHECK: dsb osh
+# CHECK: dsb oshst
+# CHECK: dsb
+
+0x4f 0xf0 0x7f 0xf5
+0x4e 0xf0 0x7f 0xf5
+0x4b 0xf0 0x7f 0xf5
+0x4a 0xf0 0x7f 0xf5
+0x47 0xf0 0x7f 0xf5
+0x46 0xf0 0x7f 0xf5
+0x43 0xf0 0x7f 0xf5
+0x42 0xf0 0x7f 0xf5
+0x4f 0xf0 0x7f 0xf5
+
+#------------------------------------------------------------------------------
+# EOR
+#------------------------------------------------------------------------------
+# CHECK: eor r4, r5, #61440
+# CHECK: eor r4, r5, r6
+# CHECK: eor r4, r5, r6, lsl #5
+# CHECK: eor r4, r5, r6, lsr #5
+# CHECK: eor r4, r5, r6, lsr #5
+# CHECK: eor r4, r5, r6, asr #5
+# CHECK: eor r4, r5, r6, ror #5
+# CHECK: eor r6, r7, r8, lsl r9
+# CHECK: eor r6, r7, r8, lsr r9
+# CHECK: eor r6, r7, r8, asr r9
+# CHECK: eor r6, r7, r8, ror r9
+# CHECK: eor r4, r5, r6, rrx
+
+# CHECK: eor r5, r5, #61440
+# CHECK: eor r4, r4, r5
+# CHECK: eor r4, r4, r5, lsl #5
+# CHECK: eor r4, r4, r5, lsr #5
+# CHECK: eor r4, r4, r5, lsr #5
+# CHECK: eor r4, r4, r5, asr #5
+# CHECK: eor r4, r4, r5, ror #5
+# CHECK: eor r6, r6, r7, lsl r9
+# CHECK: eor r6, r6, r7, lsr r9
+# CHECK: eor r6, r6, r7, asr r9
+# CHECK: eor r6, r6, r7, ror r9
+# CHECK: eor r4, r4, r5, rrx
+
+0x0f 0x4a 0x25 0xe2
+0x06 0x40 0x25 0xe0
+0x86 0x42 0x25 0xe0
+0xa6 0x42 0x25 0xe0
+0xa6 0x42 0x25 0xe0
+0xc6 0x42 0x25 0xe0
+0xe6 0x42 0x25 0xe0
+0x18 0x69 0x27 0xe0
+0x38 0x69 0x27 0xe0
+0x58 0x69 0x27 0xe0
+0x78 0x69 0x27 0xe0
+0x66 0x40 0x25 0xe0
+
+
+0x0f 0x5a 0x25 0xe2
+0x05 0x40 0x24 0xe0
+0x85 0x42 0x24 0xe0
+0xa5 0x42 0x24 0xe0
+0xa5 0x42 0x24 0xe0
+0xc5 0x42 0x24 0xe0
+0xe5 0x42 0x24 0xe0
+0x17 0x69 0x26 0xe0
+0x37 0x69 0x26 0xe0
+0x57 0x69 0x26 0xe0
+0x77 0x69 0x26 0xe0
+0x65 0x40 0x24 0xe0
+
+
+#------------------------------------------------------------------------------
+# ISB
+#------------------------------------------------------------------------------
+# CHECK: isb sy
+
+0x6f 0xf0 0x7f 0xf5
+
+
+
+#------------------------------------------------------------------------------
+# LDM*
+#------------------------------------------------------------------------------
+# CHECK: ldm r2, {r1, r3, r4, r5, r6, sp}
+# CHECK: ldmib r2, {r1, r3, r4, r5, r6, sp}
+# CHECK: ldmda r2, {r1, r3, r4, r5, r6, sp}
+# CHECK: ldmdb r2, {r1, r3, r4, r5, r6, sp}
+
+
+# CHECK: ldm r2!, {r1, r3, r4, r5, r6, sp}
+# CHECK: ldmib r2!, {r1, r3, r4, r5, r6, sp}
+# CHECK: ldmda r2!, {r1, r3, r4, r5, r6, sp}
+# CHECK: ldmdb r2!, {r1, r3, r4, r5, r6, sp}
+
+0x7a 0x20 0x92 0xe8
+0x7a 0x20 0x92 0xe9
+0x7a 0x20 0x12 0xe8
+0x7a 0x20 0x12 0xe9
+
+0x7a 0x20 0xb2 0xe8
+0x7a 0x20 0xb2 0xe9
+0x7a 0x20 0x32 0xe8
+0x7a 0x20 0x32 0xe9
+
+
+#------------------------------------------------------------------------------
+# LDREX/LDREXB/LDREXH/LDREXD
+#------------------------------------------------------------------------------
+# CHECK: ldrexb r3, [r4]
+# CHECK: ldrexh r2, [r5]
+# CHECK: ldrex r1, [r7]
+# CHECK: ldrexd r6, r7, [r8]
+
+0x9f 0x3f 0xd4 0xe1
+0x9f 0x2f 0xf5 0xe1
+0x9f 0x1f 0x97 0xe1
+0x9f 0x6f 0xb8 0xe1
+
+
+#------------------------------------------------------------------------------
+# FIXME: LSL
+#------------------------------------------------------------------------------
+#------------------------------------------------------------------------------
+# FIXME: LSR
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# MCR/MCR2
+#------------------------------------------------------------------------------
+# CHECK: mcr p7, #1, r5, c1, c1, #4
+# CHECK: mcr2 p7, #1, r5, c1, c1, #4
+
+0x91 0x57 0x21 0xee
+0x91 0x57 0x21 0xfe
+
+#------------------------------------------------------------------------------
+# MCRR/MCRR2
+#------------------------------------------------------------------------------
+# CHECK: mcrr p7, #15, r5, r4, c1
+# CHECK: mcrr2 p7, #15, r5, r4, c1
+
+0xf1 0x57 0x44 0xec
+0xf1 0x57 0x44 0xfc
+
+
+#------------------------------------------------------------------------------
+# MLA
+#------------------------------------------------------------------------------
+# CHECK: mla r1, r2, r3, r4
+# CHECK: mlas r1, r2, r3, r4
+# CHECK: mlane r1, r2, r3, r4
+# CHECK: mlasne r1, r2, r3, r4
+
+0x92 0x43 0x21 0xe0
+0x92 0x43 0x31 0xe0
+0x92 0x43 0x21 0x10
+0x92 0x43 0x31 0x10
+
+#------------------------------------------------------------------------------
+# MLS
+#------------------------------------------------------------------------------
+# CHECK: mls r2, r5, r6, r3
+# CHECK: mlsne r2, r5, r6, r3
+
+0x95 0x36 0x62 0xe0
+0x95 0x36 0x62 0x10
+
+#------------------------------------------------------------------------------
+# MOV (immediate)
+#------------------------------------------------------------------------------
+# CHECK: mov r3, #7
+# CHECK: mov r4, #4080
+# CHECK: mov r5, #16711680
+# CHECK: movw r6, #65535
+# CHECK: movw r9, #65535
+# CHECK: movs r3, #7
+# CHECK: moveq r4, #4080
+# CHECK: movseq r5, #16711680
+
+0x07 0x30 0xa0 0xe3
+0xff 0x4e 0xa0 0xe3
+0xff 0x58 0xa0 0xe3
+0xff 0x6f 0x0f 0xe3
+0xff 0x9f 0x0f 0xe3
+0x07 0x30 0xb0 0xe3
+0xff 0x4e 0xa0 0x03
+0xff 0x58 0xb0 0x03
+
+#------------------------------------------------------------------------------
+# MOV (register)
+#------------------------------------------------------------------------------
+# CHECK: mov r2, r3
+# CHECK: movs r2, r3
+# CHECK: moveq r2, r3
+# CHECK: movseq r2, r3
+
+0x03 0x20 0xa0 0xe1
+0x03 0x20 0xb0 0xe1
+0x03 0x20 0xa0 0x01
+0x03 0x20 0xb0 0x01
+
+#------------------------------------------------------------------------------
+# MOVT
+#------------------------------------------------------------------------------
+# CHECK: movt r3, #7
+# CHECK: movt r6, #65535
+# CHECK: movteq r4, #4080
+
+0x07 0x30 0x40 0xe3
+0xff 0x6f 0x4f 0xe3
+0xf0 0x4f 0x40 0x03
+
+
+#------------------------------------------------------------------------------
+# MRC/MRC2
+#------------------------------------------------------------------------------
+# CHECK: mrc p14, #0, r1, c1, c2, #4
+# CHECK: mrc2 p14, #0, r1, c1, c2, #4
+
+0x92 0x1e 0x11 0xee
+0x92 0x1e 0x11 0xfe
+
+#------------------------------------------------------------------------------
+# MRRC/MRRC2
+#------------------------------------------------------------------------------
+# CHECK: mrrc p7, #1, r5, r4, c1
+# CHECK: mrrc2 p7, #1, r5, r4, c1
+
+0x11 0x57 0x54 0xec
+0x11 0x57 0x54 0xfc
+
+
+#------------------------------------------------------------------------------
+# MRS
+#------------------------------------------------------------------------------
+# CHECK: mrs r8, apsr
+# CHECK: mrs r8, spsr
+0x00 0x80 0x0f 0xe1
+0x00 0x80 0x4f 0xe1
+
+
+
+#------------------------------------------------------------------------------
+# MSR
+#------------------------------------------------------------------------------
+
+# CHECK: msr CPSR_fc, #5
+# CHECK: msr APSR_g, #5
+# CHECK: msr APSR_nzcvq, #5
+# CHECK: msr APSR_nzcvq, #5
+# CHECK: msr APSR_nzcvqg, #5
+# CHECK: msr CPSR_fc, #5
+# CHECK: msr CPSR_c, #5
+# CHECK: msr CPSR_x, #5
+# CHECK: msr CPSR_fc, #5
+# CHECK: msr CPSR_fc, #5
+# CHECK: msr CPSR_fsx, #5
+# CHECK: msr SPSR_fc, #5
+# CHECK: msr SPSR_fsxc, #5
+# CHECK: msr CPSR_fsxc, #5
+
+0x05 0xf0 0x29 0xe3
+0x05 0xf0 0x24 0xe3
+0x05 0xf0 0x28 0xe3
+0x05 0xf0 0x28 0xe3
+0x05 0xf0 0x2c 0xe3
+0x05 0xf0 0x29 0xe3
+0x05 0xf0 0x21 0xe3
+0x05 0xf0 0x22 0xe3
+0x05 0xf0 0x29 0xe3
+0x05 0xf0 0x29 0xe3
+0x05 0xf0 0x2e 0xe3
+0x05 0xf0 0x69 0xe3
+0x05 0xf0 0x6f 0xe3
+0x05 0xf0 0x2f 0xe3
+
+# CHECK: msr CPSR_fc, r0
+# CHECK: msr APSR_g, r0
+# CHECK: msr APSR_nzcvq, r0
+# CHECK: msr APSR_nzcvq, r0
+# CHECK: msr APSR_nzcvqg, r0
+# CHECK: msr CPSR_fc, r0
+# CHECK: msr CPSR_c, r0
+# CHECK: msr CPSR_x, r0
+# CHECK: msr CPSR_fc, r0
+# CHECK: msr CPSR_fc, r0
+# CHECK: msr CPSR_fsx, r0
+# CHECK: msr SPSR_fc, r0
+# CHECK: msr SPSR_fsxc, r0
+# CHECK: msr CPSR_fsxc, r0
+
+0x00 0xf0 0x29 0xe1
+0x00 0xf0 0x24 0xe1
+0x00 0xf0 0x28 0xe1
+0x00 0xf0 0x28 0xe1
+0x00 0xf0 0x2c 0xe1
+0x00 0xf0 0x29 0xe1
+0x00 0xf0 0x21 0xe1
+0x00 0xf0 0x22 0xe1
+0x00 0xf0 0x29 0xe1
+0x00 0xf0 0x29 0xe1
+0x00 0xf0 0x2e 0xe1
+0x00 0xf0 0x69 0xe1
+0x00 0xf0 0x6f 0xe1
+0x00 0xf0 0x2f 0xe1
+
+#------------------------------------------------------------------------------
+# MUL
+#------------------------------------------------------------------------------
+
+# CHECK: mul r5, r6, r7
+# CHECK: muls r5, r6, r7
+# CHECK: mulgt r5, r6, r7
+# CHECK: mulsle r5, r6, r7
+
+0x96 0x07 0x05 0xe0
+0x96 0x07 0x15 0xe0
+0x96 0x07 0x05 0xc0
+0x96 0x07 0x15 0xd0
+
+
+#------------------------------------------------------------------------------
+# MVN (immediate)
+#------------------------------------------------------------------------------
+# CHECK: mvn r3, #7
+# CHECK: mvn r4, #4080
+# CHECK: mvn r5, #16711680
+# CHECK: mvns r3, #7
+# CHECK: mvneq r4, #4080
+# CHECK: mvnseq r5, #16711680
+
+0x07 0x30 0xe0 0xe3
+0xff 0x4e 0xe0 0xe3
+0xff 0x58 0xe0 0xe3
+0x07 0x30 0xf0 0xe3
+0xff 0x4e 0xe0 0x03
+0xff 0x58 0xf0 0x03
+
+
+#------------------------------------------------------------------------------
+# MVN (register)
+#------------------------------------------------------------------------------
+# CHECK: mvn r2, r3
+# CHECK: mvns r2, r3
+# CHECK: mvn r5, r6, lsl #19
+# CHECK: mvn r5, r6, lsr #9
+# CHECK: mvn r5, r6, asr #4
+# CHECK: mvn r5, r6, ror #6
+# CHECK: mvn r5, r6, rrx
+# CHECK: mvneq r2, r3
+# CHECK: mvnseq r2, r3, lsl #10
+
+0x03 0x20 0xe0 0xe1
+0x03 0x20 0xf0 0xe1
+0x86 0x59 0xe0 0xe1
+0xa6 0x54 0xe0 0xe1
+0x46 0x52 0xe0 0xe1
+0x66 0x53 0xe0 0xe1
+0x66 0x50 0xe0 0xe1
+0x03 0x20 0xe0 0x01
+0x03 0x25 0xf0 0x01
+
+
+#------------------------------------------------------------------------------
+# MVN (shifted register)
+#------------------------------------------------------------------------------
+# CHECK: mvn r5, r6, lsl r7
+# CHECK: mvns r5, r6, lsr r7
+# CHECK: mvngt r5, r6, asr r7
+# CHECK: mvnslt r5, r6, ror r7
+
+0x16 0x57 0xe0 0xe1
+0x36 0x57 0xf0 0xe1
+0x56 0x57 0xe0 0xc1
+0x76 0x57 0xf0 0xb1
+
+#------------------------------------------------------------------------------
+# NOP
+#------------------------------------------------------------------------------
+# CHECK: nop
+# CHECK: nopgt
+
+0x00 0xf0 0x20 0xe3
+0x00 0xf0 0x20 0xc3
+
+
+#------------------------------------------------------------------------------
+# ORR
+#------------------------------------------------------------------------------
+# CHECK: orr r4, r5, #61440
+# CHECK: orr r4, r5, r6
+# CHECK: orr r4, r5, r6, lsl #5
+# CHECK: orr r4, r5, r6, lsr #5
+# CHECK: orr r4, r5, r6, lsr #5
+# CHECK: orr r4, r5, r6, asr #5
+# CHECK: orr r4, r5, r6, ror #5
+# CHECK: orr r6, r7, r8, lsl r9
+# CHECK: orr r6, r7, r8, lsr r9
+# CHECK: orr r6, r7, r8, asr r9
+# CHECK: orr r6, r7, r8, ror r9
+# CHECK: orr r4, r5, r6, rrx
+
+# CHECK: orr r5, r5, #61440
+# CHECK: orr r4, r4, r5
+# CHECK: orr r4, r4, r5, lsl #5
+# CHECK: orr r4, r4, r5, lsr #5
+# CHECK: orr r4, r4, r5, lsr #5
+# CHECK: orr r4, r4, r5, asr #5
+# CHECK: orr r4, r4, r5, ror #5
+# CHECK: orr r6, r6, r7, lsl r9
+# CHECK: orr r6, r6, r7, lsr r9
+# CHECK: orr r6, r6, r7, asr r9
+# CHECK: orr r6, r6, r7, ror r9
+# CHECK: orr r4, r4, r5, rrx
+
+0x0f 0x4a 0x85 0xe3
+0x06 0x40 0x85 0xe1
+0x86 0x42 0x85 0xe1
+0xa6 0x42 0x85 0xe1
+0xa6 0x42 0x85 0xe1
+0xc6 0x42 0x85 0xe1
+0xe6 0x42 0x85 0xe1
+0x18 0x69 0x87 0xe1
+0x38 0x69 0x87 0xe1
+0x58 0x69 0x87 0xe1
+0x78 0x69 0x87 0xe1
+0x66 0x40 0x85 0xe1
+
+0x0f 0x5a 0x85 0xe3
+0x05 0x40 0x84 0xe1
+0x85 0x42 0x84 0xe1
+0xa5 0x42 0x84 0xe1
+0xa5 0x42 0x84 0xe1
+0xc5 0x42 0x84 0xe1
+0xe5 0x42 0x84 0xe1
+0x17 0x69 0x86 0xe1
+0x37 0x69 0x86 0xe1
+0x57 0x69 0x86 0xe1
+0x77 0x69 0x86 0xe1
+0x65 0x40 0x84 0xe1
+
+# CHECK: orrseq r4, r5, #61440
+# CHECK: orrne r4, r5, r6
+# CHECK: orrseq r4, r5, r6, lsl #5
+# CHECK: orrlo r6, r7, r8, ror r9
+# CHECK: orrshi r4, r5, r6, rrx
+# CHECK: orrhs r5, r5, #61440
+# CHECK: orrseq r4, r4, r5
+# CHECK: orrne r6, r6, r7, asr r9
+# CHECK: orrslt r6, r6, r7, ror r9
+# CHECK: orrsgt r4, r4, r5, rrx
+
+0x0f 0x4a 0x95 0x03
+0x06 0x40 0x85 0x11
+0x86 0x42 0x95 0x01
+0x78 0x69 0x87 0x31
+0x66 0x40 0x95 0x81
+0x0f 0x5a 0x85 0x23
+0x05 0x40 0x94 0x01
+0x57 0x69 0x86 0x11
+0x77 0x69 0x96 0xb1
+0x65 0x40 0x94 0xc1
+
+#------------------------------------------------------------------------------
+# PKH
+#------------------------------------------------------------------------------
+# CHECK: pkhbt r2, r2, r3
+# CHECK: pkhbt r2, r2, r3, lsl #31
+# CHECK: pkhbt r2, r2, r3
+# CHECK: pkhbt r2, r2, r3, lsl #15
+
+# CHECK: pkhbt r2, r2, r3
+# CHECK: pkhtb r2, r2, r3, asr #31
+# CHECK: pkhtb r2, r2, r3, asr #15
+
+0x13 0x20 0x82 0xe6
+0x93 0x2f 0x82 0xe6
+0x13 0x20 0x82 0xe6
+0x93 0x27 0x82 0xe6
+
+0x13 0x20 0x82 0xe6
+0xd3 0x2f 0x82 0xe6
+0xd3 0x27 0x82 0xe6
+
+#------------------------------------------------------------------------------
+# FIXME: PLD
+#------------------------------------------------------------------------------
+#------------------------------------------------------------------------------
+# FIXME: PLI
+#------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------
+# POP
+#------------------------------------------------------------------------------
+# CHECK: ldr r7, [sp], #4
+# CHECK: pop {r7, r8, r9, r10}
+
+0x04 0x70 0x9d 0xe4
+0x80 0x07 0xbd 0xe8
+
+
+#------------------------------------------------------------------------------
+# PUSH
+#------------------------------------------------------------------------------
+# CHECK: str r7, [sp, #-4]!
+# CHECK: push {r7, r8, r9, r10}
+
+0x04 0x70 0x2d 0xe5
+0x80 0x07 0x2d 0xe9
+
+
+#------------------------------------------------------------------------------
+# QADD/QADD16/QADD8
+#------------------------------------------------------------------------------
+# CHECK: qadd r1, r2, r3
+# CHECK: qaddne r1, r2, r3
+# CHECK: qadd16 r1, r2, r3
+# CHECK: qadd16gt r1, r2, r3
+# CHECK: qadd8 r1, r2, r3
+# CHECK: qadd8le r1, r2, r3
+
+0x52 0x10 0x03 0xe1
+0x52 0x10 0x03 0x11
+0x13 0x1f 0x22 0xe6
+0x13 0x1f 0x22 0xc6
+0x93 0x1f 0x22 0xe6
+0x93 0x1f 0x22 0xd6
+
+
+#------------------------------------------------------------------------------
+# QDADD/QDSUB
+#------------------------------------------------------------------------------
+# CHECK: qdadd r6, r7, r8
+# CHECK: qdaddhi r6, r7, r8
+# CHECK: qdsub r6, r7, r8
+# CHECK: qdsubhi r6, r7, r8
+
+0x57 0x60 0x48 0xe1
+0x57 0x60 0x48 0x81
+0x57 0x60 0x68 0xe1
+0x57 0x60 0x68 0x81
+
+
+#------------------------------------------------------------------------------
+# QSAX
+#------------------------------------------------------------------------------
+# CHECK: qsax r9, r12, r0
+# CHECK: qsaxeq r9, r12, r0
+
+0x50 0x9f 0x2c 0xe6
+0x50 0x9f 0x2c 0x06
+
+
+#------------------------------------------------------------------------------
+# QSUB/QSUB16/QSUB8
+#------------------------------------------------------------------------------
+# CHECK: qsub r1, r2, r3
+# CHECK: qsubne r1, r2, r3
+# CHECK: qsub16 r1, r2, r3
+# CHECK: qsub16gt r1, r2, r3
+# CHECK: qsub8 r1, r2, r3
+# CHECK: qsub8le r1, r2, r3
+
+0x52 0x10 0x23 0xe1
+0x52 0x10 0x23 0x11
+0x73 0x1f 0x22 0xe6
+0x73 0x1f 0x22 0xc6
+0xf3 0x1f 0x22 0xe6
+0xf3 0x1f 0x22 0xd6
+
+
+#------------------------------------------------------------------------------
+# RBIT
+#------------------------------------------------------------------------------
+# CHECK: rbit r1, r2
+# CHECK: rbitne r1, r2
+
+0x32 0x1f 0xff 0xe6
+0x32 0x1f 0xff 0x16
+
+
+#------------------------------------------------------------------------------
+# REV/REV16/REVSH
+#------------------------------------------------------------------------------
+# CHECK: rev r1, r9
+# CHECK: revne r1, r5
+# CHECK: rev16 r8, r3
+# CHECK: rev16ne r12, r4
+# CHECK: revsh r4, r9
+# CHECK: revshne r9, r1
+
+0x39 0x1f 0xbf 0xe6
+0x35 0x1f 0xbf 0x16
+0xb3 0x8f 0xbf 0xe6
+0xb4 0xcf 0xbf 0x16
+0xb9 0x4f 0xff 0xe6
+0xb1 0x9f 0xff 0x16
+
+
+#------------------------------------------------------------------------------
+# RFE
+#------------------------------------------------------------------------------
+# CHECK: rfeda r2
+# CHECK: rfedb r3
+# CHECK: rfeia r5
+# CHECK: rfeib r6
+
+# CHECK: rfeda r4!
+# CHECK: rfedb r7!
+# CHECK: rfeia r9!
+# CHECK: rfeib r8!
+
+# CHECK: rfeda r2
+# CHECK: rfedb r3
+# CHECK: rfeia r5
+# CHECK: rfeib r6
+
+# CHECK: rfeda r4!
+# CHECK: rfedb r7!
+# CHECK: rfeia r9!
+# CHECK: rfeib r8!
+
+# CHECK: rfeia r1
+# CHECK: rfeia r1!
+
+0x00 0x0a 0x12 0xf8
+0x00 0x0a 0x13 0xf9
+0x00 0x0a 0x95 0xf8
+0x00 0x0a 0x96 0xf9
+
+0x00 0x0a 0x34 0xf8
+0x00 0x0a 0x37 0xf9
+0x00 0x0a 0xb9 0xf8
+0x00 0x0a 0xb8 0xf9
+
+0x00 0x0a 0x12 0xf8
+0x00 0x0a 0x13 0xf9
+0x00 0x0a 0x95 0xf8
+0x00 0x0a 0x96 0xf9
+
+0x00 0x0a 0x34 0xf8
+0x00 0x0a 0x37 0xf9
+0x00 0x0a 0xb9 0xf8
+0x00 0x0a 0xb8 0xf9
+
+0x00 0x0a 0x91 0xf8
+0x00 0x0a 0xb1 0xf8
+
+
+#------------------------------------------------------------------------------
+# RSB
+#------------------------------------------------------------------------------
+# CHECK: rsb r4, r5, #61440
+# CHECK: rsb r4, r5, r6
+# CHECK: rsb r4, r5, r6, lsl #5
+# CHECK: rsblo r4, r5, r6, lsr #5
+# CHECK: rsb r4, r5, r6, lsr #5
+# CHECK: rsb r4, r5, r6, asr #5
+# CHECK: rsb r4, r5, r6, ror #5
+# CHECK: rsb r6, r7, r8, lsl r9
+# CHECK: rsb r6, r7, r8, lsr r9
+# CHECK: rsb r6, r7, r8, asr r9
+# CHECK: rsble r6, r7, r8, ror r9
+# CHECK: rsb r4, r5, r6, rrx
+
+# CHECK: rsb r5, r5, #61440
+# CHECK: rsb r4, r4, r5
+# CHECK: rsb r4, r4, r5, lsl #5
+# CHECK: rsb r4, r4, r5, lsr #5
+# CHECK: rsbne r4, r4, r5, lsr #5
+# CHECK: rsb r4, r4, r5, asr #5
+# CHECK: rsb r4, r4, r5, ror #5
+# CHECK: rsbgt r6, r6, r7, lsl r9
+# CHECK: rsb r6, r6, r7, lsr r9
+# CHECK: rsb r6, r6, r7, asr r9
+# CHECK: rsb r6, r6, r7, ror r9
+# CHECK: rsb r4, r4, r5, rrx
+
+0x0f 0x4a 0x65 0xe2
+0x06 0x40 0x65 0xe0
+0x86 0x42 0x65 0xe0
+0xa6 0x42 0x65 0x30
+0xa6 0x42 0x65 0xe0
+0xc6 0x42 0x65 0xe0
+0xe6 0x42 0x65 0xe0
+0x18 0x69 0x67 0xe0
+0x38 0x69 0x67 0xe0
+0x58 0x69 0x67 0xe0
+0x78 0x69 0x67 0xd0
+0x66 0x40 0x65 0xe0
+
+0x0f 0x5a 0x65 0xe2
+0x05 0x40 0x64 0xe0
+0x85 0x42 0x64 0xe0
+0xa5 0x42 0x64 0xe0
+0xa5 0x42 0x64 0x10
+0xc5 0x42 0x64 0xe0
+0xe5 0x42 0x64 0xe0
+0x17 0x69 0x66 0xc0
+0x37 0x69 0x66 0xe0
+0x57 0x69 0x66 0xe0
+0x77 0x69 0x66 0xe0
+0x65 0x40 0x64 0xe0
+
+#------------------------------------------------------------------------------
+# RSC
+#------------------------------------------------------------------------------
+# CHECK: rsc r4, r5, #61440
+# CHECK: rsc r4, r5, r6
+# CHECK: rsc r4, r5, r6, lsl #5
+# CHECK: rsclo r4, r5, r6, lsr #5
+# CHECK: rsc r4, r5, r6, lsr #5
+# CHECK: rsc r4, r5, r6, asr #5
+# CHECK: rsc r4, r5, r6, ror #5
+# CHECK: rsc r6, r7, r8, lsl r9
+# CHECK: rsc r6, r7, r8, lsr r9
+# CHECK: rsc r6, r7, r8, asr r9
+# CHECK: rscle r6, r7, r8, ror r9
+
+# CHECK: rsc r5, r5, #61440
+# CHECK: rsc r4, r4, r5
+# CHECK: rsc r4, r4, r5, lsl #5
+# CHECK: rsc r4, r4, r5, lsr #5
+# CHECK: rscne r4, r4, r5, lsr #5
+# CHECK: rsc r4, r4, r5, asr #5
+# CHECK: rsc r4, r4, r5, ror #5
+# CHECK: rscgt r6, r6, r7, lsl r9
+# CHECK: rsc r6, r6, r7, lsr r9
+# CHECK: rsc r6, r6, r7, asr r9
+# CHECK: rsc r6, r6, r7, ror r9
+
+0x0f 0x4a 0xe5 0xe2
+0x06 0x40 0xe5 0xe0
+0x86 0x42 0xe5 0xe0
+0xa6 0x42 0xe5 0x30
+0xa6 0x42 0xe5 0xe0
+0xc6 0x42 0xe5 0xe0
+0xe6 0x42 0xe5 0xe0
+0x18 0x69 0xe7 0xe0
+0x38 0x69 0xe7 0xe0
+0x58 0x69 0xe7 0xe0
+0x78 0x69 0xe7 0xd0
+
+0x0f 0x5a 0xe5 0xe2
+0x05 0x40 0xe4 0xe0
+0x85 0x42 0xe4 0xe0
+0xa5 0x42 0xe4 0xe0
+0xa5 0x42 0xe4 0x10
+0xc5 0x42 0xe4 0xe0
+0xe5 0x42 0xe4 0xe0
+0x17 0x69 0xe6 0xc0
+0x37 0x69 0xe6 0xe0
+0x57 0x69 0xe6 0xe0
+0x77 0x69 0xe6 0xe0
+
+#------------------------------------------------------------------------------
+# SADD16/SADD8
+#------------------------------------------------------------------------------
+# CHECK: sadd16 r1, r2, r3
+# CHECK: sadd16gt r1, r2, r3
+# CHECK: sadd8 r1, r2, r3
+# CHECK: sadd8le r1, r2, r3
+
+0x13 0x1f 0x12 0xe6
+0x13 0x1f 0x12 0xc6
+0x93 0x1f 0x12 0xe6
+0x93 0x1f 0x12 0xd6
+
+
+#------------------------------------------------------------------------------
+# SASX
+#------------------------------------------------------------------------------
+# CHECK: sasx r9, r12, r0
+# CHECK: sasxeq r9, r12, r0
+
+0x30 0x9f 0x1c 0xe6
+0x30 0x9f 0x1c 0x06
+
+
+#------------------------------------------------------------------------------
+# SBC
+#------------------------------------------------------------------------------
+# CHECK: sbc r4, r5, #61440
+# CHECK: sbc r4, r5, r6
+# CHECK: sbc r4, r5, r6, lsl #5
+# CHECK: sbc r4, r5, r6, lsr #5
+# CHECK: sbc r4, r5, r6, lsr #5
+# CHECK: sbc r4, r5, r6, asr #5
+# CHECK: sbc r4, r5, r6, ror #5
+# CHECK: sbc r6, r7, r8, lsl r9
+# CHECK: sbc r6, r7, r8, lsr r9
+# CHECK: sbc r6, r7, r8, asr r9
+# CHECK: sbc r6, r7, r8, ror r9
+
+# CHECK: sbc r5, r5, #61440
+# CHECK: sbc r4, r4, r5
+# CHECK: sbc r4, r4, r5, lsl #5
+# CHECK: sbc r4, r4, r5, lsr #5
+# CHECK: sbc r4, r4, r5, lsr #5
+# CHECK: sbc r4, r4, r5, asr #5
+# CHECK: sbc r4, r4, r5, ror #5
+# CHECK: sbc r6, r6, r7, lsl r9
+# CHECK: sbc r6, r6, r7, lsr r9
+# CHECK: sbc r6, r6, r7, asr r9
+# CHECK: sbc r6, r6, r7, ror r9
+
+0x0f 0x4a 0xc5 0xe2
+0x06 0x40 0xc5 0xe0
+0x86 0x42 0xc5 0xe0
+0xa6 0x42 0xc5 0xe0
+0xa6 0x42 0xc5 0xe0
+0xc6 0x42 0xc5 0xe0
+0xe6 0x42 0xc5 0xe0
+0x18 0x69 0xc7 0xe0
+0x38 0x69 0xc7 0xe0
+0x58 0x69 0xc7 0xe0
+0x78 0x69 0xc7 0xe0
+
+0x0f 0x5a 0xc5 0xe2
+0x05 0x40 0xc4 0xe0
+0x85 0x42 0xc4 0xe0
+0xa5 0x42 0xc4 0xe0
+0xa5 0x42 0xc4 0xe0
+0xc5 0x42 0xc4 0xe0
+0xe5 0x42 0xc4 0xe0
+0x17 0x69 0xc6 0xe0
+0x37 0x69 0xc6 0xe0
+0x57 0x69 0xc6 0xe0
+0x77 0x69 0xc6 0xe0
+
+
+#------------------------------------------------------------------------------
+# SBFX
+#------------------------------------------------------------------------------
+# CHECK: sbfx r4, r5, #16, #1
+# CHECK: sbfxgt r4, r5, #16, #16
+
+0x55 0x48 0xa0 0xe7
+0x55 0x48 0xaf 0xc7
+
+
+#------------------------------------------------------------------------------
+# SEL
+#------------------------------------------------------------------------------
+# CHECK: sel r9, r2, r1
+# CHECK: selne r9, r2, r1
+
+0xb1 0x9f 0x82 0xe6
+0xb1 0x9f 0x82 0x16
+
+
+#------------------------------------------------------------------------------
+# SETEND
+#------------------------------------------------------------------------------
+# CHECK: setend be
+# CHECK: setend le
+
+0x00 0x02 0x01 0xf1
+0x00 0x00 0x01 0xf1
+
+#------------------------------------------------------------------------------
+# SEV
+#------------------------------------------------------------------------------
+# CHECK: sev
+# CHECK: seveq
+
+0x04 0xf0 0x20 0xe3
+0x04 0xf0 0x20 0x03
+
+#------------------------------------------------------------------------------
+# SHADD16/SHADD8
+#------------------------------------------------------------------------------
+# CHECK: shadd16 r4, r8, r2
+# CHECK: shadd16gt r4, r8, r2
+# CHECK: shadd8 r4, r8, r2
+# CHECK: shadd8gt r4, r8, r2
+
+0x12 0x4f 0x38 0xe6
+0x12 0x4f 0x38 0xc6
+0x92 0x4f 0x38 0xe6
+0x92 0x4f 0x38 0xc6
+
+
+#------------------------------------------------------------------------------
+# SHASX
+#------------------------------------------------------------------------------
+# CHECK: shasx r4, r8, r2
+# CHECK: shasxgt r4, r8, r2
+
+0x32 0x4f 0x38 0xe6
+0x32 0x4f 0x38 0xc6
+
+
+#------------------------------------------------------------------------------
+# SHSUB16/SHSUB8
+#------------------------------------------------------------------------------
+# CHECK: shsub16 r4, r8, r2
+# CHECK: shsub16gt r4, r8, r2
+# CHECK: shsub8 r4, r8, r2
+# CHECK: shsub8gt r4, r8, r2
+
+0x72 0x4f 0x38 0xe6
+0x72 0x4f 0x38 0xc6
+0xf2 0x4f 0x38 0xe6
+0xf2 0x4f 0x38 0xc6
+
+#------------------------------------------------------------------------------
+# SMC
+#------------------------------------------------------------------------------
+# CHECK: smc #15
+# CHECK: smceq #0
+
+0x7f 0x00 0x60 0xe1
+0x70 0x00 0x60 0x01
+
+#------------------------------------------------------------------------------
+# SMLABB/SMLABT/SMLATB/SMLATT
+#------------------------------------------------------------------------------
+# CHECK: smlabb r3, r1, r9, r0
+# CHECK: smlabt r5, r6, r4, r1
+# CHECK: smlatb r4, r2, r3, r2
+# CHECK: smlatt r8, r3, r8, r4
+# CHECK: smlabbge r3, r1, r9, r0
+# CHECK: smlabtle r5, r6, r4, r1
+# CHECK: smlatbne r4, r2, r3, r2
+# CHECK: smlatteq r8, r3, r8, r4
+
+0x81 0x09 0x03 0xe1
+0xc6 0x14 0x05 0xe1
+0xa2 0x23 0x04 0xe1
+0xe3 0x48 0x08 0xe1
+0x81 0x09 0x03 0xa1
+0xc6 0x14 0x05 0xd1
+0xa2 0x23 0x04 0x11
+0xe3 0x48 0x08 0x01
+
+#------------------------------------------------------------------------------
+# SMLAD/SMLADX
+#------------------------------------------------------------------------------
+# CHECK: smlad r2, r3, r5, r8
+# CHECK: smladx r2, r3, r5, r8
+# CHECK: smladeq r2, r3, r5, r8
+# CHECK: smladxhi r2, r3, r5, r8
+
+0x13 0x85 0x02 0xe7
+0x33 0x85 0x02 0xe7
+0x13 0x85 0x02 0x07
+0x33 0x85 0x02 0x87
+
+
+#------------------------------------------------------------------------------
+# SMLAL
+#------------------------------------------------------------------------------
+# CHECK: smlal r2, r3, r5, r8
+# CHECK: smlals r2, r3, r5, r8
+# CHECK: smlaleq r2, r3, r5, r8
+# CHECK: smlalshi r2, r3, r5, r8
+
+0x95 0x28 0xe3 0xe0
+0x95 0x28 0xf3 0xe0
+0x95 0x28 0xe3 0x00
+0x95 0x28 0xf3 0x80
+
+
+#------------------------------------------------------------------------------
+# SMLALBB/SMLALBT/SMLALTB/SMLALTT
+#------------------------------------------------------------------------------
+# CHECK: smlalbb r3, r1, r9, r0
+# CHECK: smlalbt r5, r6, r4, r1
+# CHECK: smlaltb r4, r2, r3, r2
+# CHECK: smlaltt r8, r3, r8, r4
+# CHECK: smlalbbge r3, r1, r9, r0
+# CHECK: smlalbtle r5, r6, r4, r1
+# CHECK: smlaltbne r4, r2, r3, r2
+# CHECK: smlaltteq r8, r3, r8, r4
+
+0x89 0x30 0x41 0xe1
+0xc4 0x51 0x46 0xe1
+0xa3 0x42 0x42 0xe1
+0xe8 0x84 0x43 0xe1
+0x89 0x30 0x41 0xa1
+0xc4 0x51 0x46 0xd1
+0xa3 0x42 0x42 0x11
+0xe8 0x84 0x43 0x01
+
+
+#------------------------------------------------------------------------------
+# SMLALD/SMLALDX
+#------------------------------------------------------------------------------
+# CHECK: smlald r2, r3, r5, r8
+# CHECK: smlaldx r2, r3, r5, r8
+# CHECK: smlaldeq r2, r3, r5, r8
+# CHECK: smlaldxhi r2, r3, r5, r8
+
+0x15 0x28 0x43 0xe7
+0x35 0x28 0x43 0xe7
+0x15 0x28 0x43 0x07
+0x35 0x28 0x43 0x87
+
+
+#------------------------------------------------------------------------------
+# SMLAWB/SMLAWT
+#------------------------------------------------------------------------------
+# CHECK: smlawb r2, r3, r10, r8
+# CHECK: smlawt r8, r3, r5, r9
+# CHECK: smlawbeq r2, r7, r5, r8
+# CHECK: smlawthi r1, r3, r0, r8
+
+0x83 0x8a 0x22 0xe1
+0xc3 0x95 0x28 0xe1
+0x87 0x85 0x22 0x01
+0xc3 0x80 0x21 0x81
+
+
+#------------------------------------------------------------------------------
+# SMLSD/SMLSDX
+#------------------------------------------------------------------------------
+# CHECK: smlsd r2, r3, r5, r8
+# CHECK: smlsdx r2, r3, r5, r8
+# CHECK: smlsdeq r2, r3, r5, r8
+# CHECK: smlsdxhi r2, r3, r5, r8
+
+0x53 0x85 0x02 0xe7
+0x73 0x85 0x02 0xe7
+0x53 0x85 0x02 0x07
+0x73 0x85 0x02 0x87
+
+
+#------------------------------------------------------------------------------
+# SMLSLD/SMLSLDX
+#------------------------------------------------------------------------------
+# CHECK: smlsld r2, r9, r5, r1
+# CHECK: smlsldx r4, r11, r2, r8
+# CHECK: smlsldeq r8, r2, r5, r6
+# CHECK: smlsldxhi r1, r0, r3, r8
+
+0x55 0x21 0x49 0xe7
+0x72 0x48 0x4b 0xe7
+0x55 0x86 0x42 0x07
+0x73 0x18 0x40 0x87
+
+
+#------------------------------------------------------------------------------
+# SMMLA/SMMLAR
+#------------------------------------------------------------------------------
+# CHECK: smmla r1, r2, r3, r4
+# CHECK: smmlar r4, r3, r2, r1
+# CHECK: smmlalo r1, r2, r3, r4
+# CHECK: smmlarhs r4, r3, r2, r1
+
+0x12 0x43 0x51 0xe7
+0x33 0x12 0x54 0xe7
+0x12 0x43 0x51 0x37
+0x33 0x12 0x54 0x27
+
+
+#------------------------------------------------------------------------------
+# SMMLS/SMMLSR
+#------------------------------------------------------------------------------
+# CHECK: smmls r1, r2, r3, r4
+# CHECK: smmlsr r4, r3, r2, r1
+# CHECK: smmlslo r1, r2, r3, r4
+# CHECK: smmlsrhs r4, r3, r2, r1
+
+0xd2 0x43 0x51 0xe7
+0xf3 0x12 0x54 0xe7
+0xd2 0x43 0x51 0x37
+0xf3 0x12 0x54 0x27
+
+
+#------------------------------------------------------------------------------
+# SMMUL/SMMULR
+#------------------------------------------------------------------------------
+# CHECK: smmul r2, r3, r4
+# CHECK: smmulr r3, r2, r1
+# CHECK: smmullo r2, r3, r4
+# CHECK: smmulrhs r3, r2, r1
+
+0x13 0xf4 0x52 0xe7
+0x32 0xf1 0x53 0xe7
+0x13 0xf4 0x52 0x37
+0x32 0xf1 0x53 0x27
+
+
+#------------------------------------------------------------------------------
+# SMUAD/SMUADX
+#------------------------------------------------------------------------------
+# CHECK: smuad r2, r3, r4
+# CHECK: smuadx r3, r2, r1
+# CHECK: smuadlt r2, r3, r4
+# CHECK: smuadxge r3, r2, r1
+
+0x13 0xf4 0x02 0xe7
+0x32 0xf1 0x03 0xe7
+0x13 0xf4 0x02 0xb7
+0x32 0xf1 0x03 0xa7
+
+
+#------------------------------------------------------------------------------
+# SMULBB/SMLALBT/SMLALTB/SMLALTT
+#------------------------------------------------------------------------------
+# CHECK: smulbb r3, r9, r0
+# CHECK: smulbt r5, r4, r1
+# CHECK: smultb r4, r2, r2
+# CHECK: smultt r8, r3, r4
+# CHECK: smulbbge r1, r9, r0
+# CHECK: smulbtle r5, r6, r4
+# CHECK: smultbne r2, r3, r2
+# CHECK: smultteq r8, r3, r4
+
+0x89 0x00 0x63 0xe1
+0xc4 0x01 0x65 0xe1
+0xa2 0x02 0x64 0xe1
+0xe3 0x04 0x68 0xe1
+0x89 0x00 0x61 0xa1
+0xc6 0x04 0x65 0xd1
+0xa3 0x02 0x62 0x11
+0xe3 0x04 0x68 0x01
+
+
+#------------------------------------------------------------------------------
+# SMULL
+#------------------------------------------------------------------------------
+# CHECK: smull r3, r9, r0, r1
+# CHECK: smulls r3, r9, r0, r2
+# CHECK: smulleq r8, r3, r4, r5
+# CHECK: smullseq r8, r3, r4, r3
+
+0x90 0x31 0xc9 0xe0
+0x90 0x32 0xd9 0xe0
+0x94 0x85 0xc3 0x00
+0x94 0x83 0xd3 0x00
+
+
+#------------------------------------------------------------------------------
+# SMULWB/SMULWT
+#------------------------------------------------------------------------------
+# CHECK: smulwb r3, r9, r0
+# CHECK: smulwt r3, r9, r2
+
+0xa9 0x00 0x23 0xe1
+0xe9 0x02 0x23 0xe1
+
+
+#------------------------------------------------------------------------------
+# SMUSD/SMUSDX
+#------------------------------------------------------------------------------
+# CHECK: smusd r3, r0, r1
+# CHECK: smusdx r3, r9, r2
+# CHECK: smusdeq r8, r3, r2
+# CHECK: smusdxne r7, r4, r3
+
+0x50 0xf1 0x03 0xe7
+0x79 0xf2 0x03 0xe7
+0x53 0xf2 0x08 0x07
+0x74 0xf3 0x07 0x17
+
+
+#------------------------------------------------------------------------------
+# SRS
+#------------------------------------------------------------------------------
+# CHECK: srsda sp, #5
+# CHECK: srsdb sp, #1
+# CHECK: srsia sp, #0
+# CHECK: srsib sp, #15
+
+# CHECK: srsda sp!, #31
+# CHECK: srsdb sp!, #19
+# CHECK: srsia sp!, #2
+# CHECK: srsib sp!, #14
+
+# CHECK: srsda sp, #11
+# CHECK: srsdb sp, #10
+# CHECK: srsia sp, #9
+# CHECK: srsib sp, #5
+
+# CHECK: srsda sp!, #5
+# CHECK: srsdb sp!, #5
+# CHECK: srsia sp!, #5
+# CHECK: srsib sp!, #5
+
+# CHECK: srsia sp, #5
+# CHECK: srsia sp!, #5
+
+0x05 0x05 0x4d 0xf8
+0x01 0x05 0x4d 0xf9
+0x00 0x05 0xcd 0xf8
+0x0f 0x05 0xcd 0xf9
+
+0x1f 0x05 0x6d 0xf8
+0x13 0x05 0x6d 0xf9
+0x02 0x05 0xed 0xf8
+0x0e 0x05 0xed 0xf9
+
+0x0b 0x05 0x4d 0xf8
+0x0a 0x05 0x4d 0xf9
+0x09 0x05 0xcd 0xf8
+0x05 0x05 0xcd 0xf9
+
+0x05 0x05 0x6d 0xf8
+0x05 0x05 0x6d 0xf9
+0x05 0x05 0xed 0xf8
+0x05 0x05 0xed 0xf9
+
+0x05 0x05 0xcd 0xf8
+0x05 0x05 0xed 0xf8
+
+
+#------------------------------------------------------------------------------
+# SSAT
+#------------------------------------------------------------------------------
+# CHECK: ssat r8, #1, r10
+# CHECK: ssat r8, #1, r10, lsl #31
+# CHECK: ssat r8, #1, r10, asr #32
+# CHECK: ssat r8, #1, r10, asr #1
+
+0x1a 0x80 0xa0 0xe6
+0x9a 0x8f 0xa0 0xe6
+0x5a 0x80 0xa0 0xe6
+0xda 0x80 0xa0 0xe6
+
+
+#------------------------------------------------------------------------------
+# SSAT16
+#------------------------------------------------------------------------------
+# CHECK: ssat16 r2, #1, r7
+# CHECK: ssat16 r3, #16, r5
+
+0x37 0x2f 0xa0 0xe6
+0x35 0x3f 0xaf 0xe6
+
+
+#------------------------------------------------------------------------------
+# SSAX
+#------------------------------------------------------------------------------
+# CHECK: ssax r2, r3, r4
+# CHECK: ssaxlt r2, r3, r4
+
+0x54 0x2f 0x13 0xe6
+0x54 0x2f 0x13 0xb6
+
+#------------------------------------------------------------------------------
+# SSUB16/SSUB8
+#------------------------------------------------------------------------------
+# CHECK: ssub16 r1, r0, r6
+# CHECK: ssub16ne r5, r3, r2
+# CHECK: ssub8 r9, r2, r4
+# CHECK: ssub8eq r5, r1, r2
+
+0x76 0x1f 0x10 0xe6
+0x72 0x5f 0x13 0x16
+0xf4 0x9f 0x12 0xe6
+0xf2 0x5f 0x11 0x06
+
+
+#------------------------------------------------------------------------------
+# STM*
+#------------------------------------------------------------------------------
+# CHECK: stm r2, {r1, r3, r4, r5, r6, sp}
+# CHECK: stm r3, {r1, r3, r4, r5, r6, lr}
+# CHECK: stmib r4, {r1, r3, r4, r5, r6, sp}
+# CHECK: stmda r5, {r1, r3, r4, r5, r6, sp}
+# CHECK: stmdb r6, {r1, r3, r4, r5, r6, r8}
+# CHECK: stmdb sp, {r1, r3, r4, r5, r6, sp}
+
+
+# CHECK: stm r8!, {r1, r3, r4, r5, r6, sp}
+# CHECK: stmib r9!, {r1, r3, r4, r5, r6, sp}
+# CHECK: stmda sp!, {r1, r3, r4, r5, r6}
+# CHECK: stmdb r0!, {r1, r5, r7, sp}
+
+0x7a 0x20 0x82 0xe8
+0x7a 0x40 0x83 0xe8
+0x7a 0x20 0x84 0xe9
+0x7a 0x20 0x05 0xe8
+0x7a 0x01 0x06 0xe9
+0x7a 0x20 0x0d 0xe9
+
+0x7a 0x20 0xa8 0xe8
+0x7a 0x20 0xa9 0xe9
+0x7a 0x00 0x2d 0xe8
+0xa2 0x20 0x20 0xe9
+
+
+#------------------------------------------------------------------------------
+# STREX/STREXB/STREXH/STREXD
+#------------------------------------------------------------------------------
+# CHECK: strexb r1, r3, [r4
+# CHECK: strexh r4, r2, [r5
+# CHECK: strex r2, r1, [r7
+# CHECK: strexd r6, r2, r3, [r8
+
+0x93 0x1f 0xc4 0xe1
+0x92 0x4f 0xe5 0xe1
+0x91 0x2f 0x87 0xe1
+0x92 0x6f 0xa8 0xe1
+
+
+#------------------------------------------------------------------------------
+# SUB
+#------------------------------------------------------------------------------
+# CHECK: sub r4, r5, #61440
+# CHECK: sub r4, r5, r6
+# CHECK: sub r4, r5, r6, lsl #5
+# CHECK: sub r4, r5, r6, lsr #5
+# CHECK: sub r4, r5, r6, lsr #5
+# CHECK: sub r4, r5, r6, asr #5
+# CHECK: sub r4, r5, r6, ror #5
+# CHECK: sub r6, r7, r8, lsl r9
+# CHECK: sub r6, r7, r8, lsr r9
+# CHECK: sub r6, r7, r8, asr r9
+# CHECK: sub r6, r7, r8, ror r9
+
+# CHECK: sub r5, r5, #61440
+# CHECK: sub r4, r4, r5
+# CHECK: sub r4, r4, r5, lsl #5
+# CHECK: sub r4, r4, r5, lsr #5
+# CHECK: sub r4, r4, r5, lsr #5
+# CHECK: sub r4, r4, r5, asr #5
+# CHECK: sub r4, r4, r5, ror #5
+# CHECK: sub r6, r6, r7, lsl r9
+# CHECK: sub r6, r6, r7, lsr r9
+# CHECK: sub r6, r6, r7, asr r9
+# CHECK: sub r6, r6, r7, ror r9
+
+0x0f 0x4a 0x45 0xe2
+0x06 0x40 0x45 0xe0
+0x86 0x42 0x45 0xe0
+0xa6 0x42 0x45 0xe0
+0xa6 0x42 0x45 0xe0
+0xc6 0x42 0x45 0xe0
+0xe6 0x42 0x45 0xe0
+0x18 0x69 0x47 0xe0
+0x38 0x69 0x47 0xe0
+0x58 0x69 0x47 0xe0
+0x78 0x69 0x47 0xe0
+
+
+0x0f 0x5a 0x45 0xe2
+0x05 0x40 0x44 0xe0
+0x85 0x42 0x44 0xe0
+0xa5 0x42 0x44 0xe0
+0xa5 0x42 0x44 0xe0
+0xc5 0x42 0x44 0xe0
+0xe5 0x42 0x44 0xe0
+0x17 0x69 0x46 0xe0
+0x37 0x69 0x46 0xe0
+0x57 0x69 0x46 0xe0
+0x77 0x69 0x46 0xe0
+
+
+#------------------------------------------------------------------------------
+# SVC
+#------------------------------------------------------------------------------
+# CHECK: svc #16
+# CHECK: svc #0
+# CHECK: svc #16777215
+
+0x10 0x00 0x00 0xef
+0x00 0x00 0x00 0xef
+0xff 0xff 0xff 0xef
+
+
+#------------------------------------------------------------------------------
+# SWP/SWPB
+#------------------------------------------------------------------------------
+# CHECK: swp r1, r2, [r3
+# CHECK: swp r4, r4, [r6
+# CHECK: swpb r5, r1, [r9
+
+0x92 0x10 0x03 0xe1
+0x94 0x40 0x06 0xe1
+0x91 0x50 0x49 0xe1
+
+
+#------------------------------------------------------------------------------
+# SXTAB
+#------------------------------------------------------------------------------
+# CHECK: sxtab r2, r3, r4
+# CHECK: sxtab r4, r5, r6
+# CHECK: sxtablt r6, r2, r9, ror #8
+# CHECK: sxtab r5, r1, r4, ror #16
+# CHECK: sxtab r7, r8, r3, ror #24
+
+0x74 0x20 0xa3 0xe6
+0x76 0x40 0xa5 0xe6
+0x79 0x64 0xa2 0xb6
+0x74 0x58 0xa1 0xe6
+0x73 0x7c 0xa8 0xe6
+
+
+#------------------------------------------------------------------------------
+# SXTAB16
+#------------------------------------------------------------------------------
+# CHECK: sxtab16ge r0, r1, r4
+# CHECK: sxtab16 r6, r2, r7
+# CHECK: sxtab16 r3, r5, r8, ror #8
+# CHECK: sxtab16 r3, r2, r1, ror #16
+# CHECK: sxtab16eq r1, r2, r3, ror #24
+
+0x74 0x00 0x81 0xa6
+0x77 0x60 0x82 0xe6
+0x78 0x34 0x85 0xe6
+0x71 0x38 0x82 0xe6
+0x73 0x1c 0x82 0x06
+
+#------------------------------------------------------------------------------
+# SXTAH
+#------------------------------------------------------------------------------
+# CHECK: sxtah r1, r3, r9
+# CHECK: sxtahhi r6, r1, r6
+# CHECK: sxtah r3, r8, r3, ror #8
+# CHECK: sxtahlo r2, r2, r4, ror #16
+# CHECK: sxtah r9, r3, r3, ror #24
+
+0x79 0x10 0xb3 0xe6
+0x76 0x60 0xb1 0x86
+0x73 0x34 0xb8 0xe6
+0x74 0x28 0xb2 0x36
+0x73 0x9c 0xb3 0xe6
+
+#------------------------------------------------------------------------------
+# SXTB
+#------------------------------------------------------------------------------
+# CHECK: sxtbge r2, r4
+# CHECK: sxtb r5, r6
+# CHECK: sxtb r6, r9, ror #8
+# CHECK: sxtblo r5, r1, ror #16
+# CHECK: sxtb r8, r3, ror #24
+
+0x74 0x20 0xaf 0xa6
+0x76 0x50 0xaf 0xe6
+0x79 0x64 0xaf 0xe6
+0x71 0x58 0xaf 0x36
+0x73 0x8c 0xaf 0xe6
+
+
+#------------------------------------------------------------------------------
+# SXTB16
+#------------------------------------------------------------------------------
+# CHECK: sxtb16 r1, r4
+# CHECK: sxtb16 r6, r7
+# CHECK: sxtb16hs r3, r5, ror #8
+# CHECK: sxtb16 r3, r1, ror #16
+# CHECK: sxtb16ge r2, r3, ror #24
+
+0x74 0x10 0x8f 0xe6
+0x77 0x60 0x8f 0xe6
+0x75 0x34 0x8f 0x26
+0x71 0x38 0x8f 0xe6
+0x73 0x2c 0x8f 0xa6
+
+
+#------------------------------------------------------------------------------
+# SXTH
+#------------------------------------------------------------------------------
+# CHECK: sxthne r3, r9
+# CHECK: sxth r1, r6
+# CHECK: sxth r3, r8, ror #8
+# CHECK: sxthle r2, r2, ror #16
+# CHECK: sxth r9, r3, ror #24
+
+0x79 0x30 0xbf 0x16
+0x76 0x10 0xbf 0xe6
+0x78 0x34 0xbf 0xe6
+0x72 0x28 0xbf 0xd6
+0x73 0x9c 0xbf 0xe6
+
+
+#------------------------------------------------------------------------------
+# FIXME: TBB/TBH
+#------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------
+# TEQ
+#------------------------------------------------------------------------------
+# CHECK: teq r5, #61440
+# CHECK: teq r4, r5
+# CHECK: teq r4, r5, lsl #5
+# CHECK: teq r4, r5, lsr #5
+# CHECK: teq r4, r5, lsr #5
+# CHECK: teq r4, r5, asr #5
+# CHECK: teq r4, r5, ror #5
+# CHECK: teq r6, r7, lsl r9
+# CHECK: teq r6, r7, lsr r9
+# CHECK: teq r6, r7, asr r9
+# CHECK: teq r6, r7, ror r9
+
+0x0f 0x0a 0x35 0xe3
+0x05 0x00 0x34 0xe1
+0x85 0x02 0x34 0xe1
+0xa5 0x02 0x34 0xe1
+0xa5 0x02 0x34 0xe1
+0xc5 0x02 0x34 0xe1
+0xe5 0x02 0x34 0xe1
+0x17 0x09 0x36 0xe1
+0x37 0x09 0x36 0xe1
+0x57 0x09 0x36 0xe1
+0x77 0x09 0x36 0xe1
+
+
+#------------------------------------------------------------------------------
+# TST
+#------------------------------------------------------------------------------
+# CHECK: tst r5, #61440
+# CHECK: tst r4, r5
+# CHECK: tst r4, r5, lsl #5
+# CHECK: tst r4, r5, lsr #5
+# CHECK: tst r4, r5, lsr #5
+# CHECK: tst r4, r5, asr #5
+# CHECK: tst r4, r5, ror #5
+# CHECK: tst r6, r7, lsl r9
+# CHECK: tst r6, r7, lsr r9
+# CHECK: tst r6, r7, asr r9
+# CHECK: tst r6, r7, ror r9
+
+0x0f 0x0a 0x15 0xe3
+0x05 0x00 0x14 0xe1
+0x85 0x02 0x14 0xe1
+0xa5 0x02 0x14 0xe1
+0xa5 0x02 0x14 0xe1
+0xc5 0x02 0x14 0xe1
+0xe5 0x02 0x14 0xe1
+0x17 0x09 0x16 0xe1
+0x37 0x09 0x16 0xe1
+0x57 0x09 0x16 0xe1
+0x77 0x09 0x16 0xe1
+
+
+#------------------------------------------------------------------------------
+# UADD16/UADD8
+#------------------------------------------------------------------------------
+# CHECK: uadd16 r1, r2, r3
+# CHECK: uadd16gt r1, r2, r3
+# CHECK: uadd8 r1, r2, r3
+# CHECK: uadd8le r1, r2, r3
+
+0x13 0x1f 0x52 0xe6
+0x13 0x1f 0x52 0xc6
+0x93 0x1f 0x52 0xe6
+0x93 0x1f 0x52 0xd6
+
+
+#------------------------------------------------------------------------------
+# UASX
+#------------------------------------------------------------------------------
+# CHECK: uasx r9, r12, r0
+# CHECK: uasxeq r9, r12, r0
+
+0x30 0x9f 0x5c 0xe6
+0x30 0x9f 0x5c 0x06
+
+
+#------------------------------------------------------------------------------
+# UBFX
+#------------------------------------------------------------------------------
+# CHECK: ubfx r4, r5, #16, #1
+# CHECK: ubfxgt r4, r5, #16, #16
+
+0x55 0x48 0xe0 0xe7
+0x55 0x48 0xef 0xc7
+
+
+#------------------------------------------------------------------------------
+# UHADD16/UHADD8
+#------------------------------------------------------------------------------
+# CHECK: uhadd16 r4, r8, r2
+# CHECK: uhadd16gt r4, r8, r2
+# CHECK: uhadd8 r4, r8, r2
+# CHECK: uhadd8gt r4, r8, r2
+
+0x12 0x4f 0x78 0xe6
+0x12 0x4f 0x78 0xc6
+0x92 0x4f 0x78 0xe6
+0x92 0x4f 0x78 0xc6
+
+
+#------------------------------------------------------------------------------
+# UHASX
+#------------------------------------------------------------------------------
+# CHECK: uhasx r4, r8, r2
+# CHECK: uhasxgt r4, r8, r2
+
+0x32 0x4f 0x78 0xe6
+0x32 0x4f 0x78 0xc6
+
+
+#------------------------------------------------------------------------------
+# UHSUB16/UHSUB8
+#------------------------------------------------------------------------------
+# CHECK: uhsub16 r4, r8, r2
+# CHECK: uhsub16gt r4, r8, r2
+# CHECK: uhsub8 r4, r8, r2
+# CHECK: uhsub8gt r4, r8, r2
+
+0x72 0x4f 0x78 0xe6
+0x72 0x4f 0x78 0xc6
+0xf2 0x4f 0x78 0xe6
+0xf2 0x4f 0x78 0xc6
+
+
+#------------------------------------------------------------------------------
+# UMAAL
+#------------------------------------------------------------------------------
+# CHECK: umaal r3, r4, r5, r6
+# CHECK: umaallt r3, r4, r5, r6
+
+0x95 0x36 0x44 0xe0
+0x95 0x36 0x44 0xb0
+
+
+#------------------------------------------------------------------------------
+# UMLAL
+#------------------------------------------------------------------------------
+# CHECK: umlal r2, r4, r6, r8
+# CHECK: umlalgt r6, r1, r2, r6
+# CHECK: umlals r2, r9, r2, r3
+# CHECK: umlalseq r3, r5, r1, r2
+
+0x96 0x28 0xa4 0xe0
+0x92 0x66 0xa1 0xc0
+0x92 0x23 0xb9 0xe0
+0x91 0x32 0xb5 0x00
+
+
+#------------------------------------------------------------------------------
+# UMULL
+#------------------------------------------------------------------------------
+# CHECK: umull r2, r4, r6, r8
+# CHECK: umullgt r6, r1, r2, r6
+# CHECK: umulls r2, r9, r2, r3
+# CHECK: umullseq r3, r5, r1, r2
+
+0x96 0x28 0x84 0xe0
+0x92 0x66 0x81 0xc0
+0x92 0x23 0x99 0xe0
+0x91 0x32 0x95 0x00
+
+
+#------------------------------------------------------------------------------
+# UQADD16/UQADD8
+#------------------------------------------------------------------------------
+# CHECK: uqadd16 r1, r2, r3
+# CHECK: uqadd16gt r4, r7, r9
+# CHECK: uqadd8 r3, r4, r8
+# CHECK: uqadd8le r8, r1, r2
+
+
+0x13 0x1f 0x62 0xe6
+0x19 0x4f 0x67 0xc6
+0x98 0x3f 0x64 0xe6
+0x92 0x8f 0x61 0xd6
+
+
+#------------------------------------------------------------------------------
+# UQASX
+#------------------------------------------------------------------------------
+# CHECK: uqasx r2, r4, r1
+# CHECK: uqasxhi r5, r2, r9
+
+0x31 0x2f 0x64 0xe6
+0x39 0x5f 0x62 0x86
+
+
+#------------------------------------------------------------------------------
+# UQSAX
+#------------------------------------------------------------------------------
+# CHECK: uqsax r1, r3, r7
+# CHECK: uqsax r3, r6, r2
+
+0x57 0x1f 0x63 0xe6
+0x52 0x3f 0x66 0xe6
+
+
+#------------------------------------------------------------------------------
+# UQSUB16/UQSUB8
+#------------------------------------------------------------------------------
+# CHECK: uqsub16 r1, r5, r3
+# CHECK: uqsub16gt r3, r2, r5
+# CHECK: uqsub8 r2, r1, r4
+# CHECK: uqsub8le r4, r6, r9
+
+0x73 0x1f 0x65 0xe6
+0x75 0x3f 0x62 0xc6
+0xf4 0x2f 0x61 0xe6
+0xf9 0x4f 0x66 0xd6
+
+
+#------------------------------------------------------------------------------
+# USADA8/USAD8
+#------------------------------------------------------------------------------
+# CHECK: usad8 r2, r1, r4
+# CHECK: usad8le r4, r6, r9
+# CHECK: usada8 r1, r5, r3, r7
+# CHECK: usada8gt r3, r2, r5, r1
+
+0x11 0xf4 0x82 0xe7
+0x16 0xf9 0x84 0xd7
+0x15 0x73 0x81 0xe7
+0x12 0x15 0x83 0xc7
+
+
+#------------------------------------------------------------------------------
+# USAT
+#------------------------------------------------------------------------------
+
+# CHECK: usat r8, #1, r10
+# CHECK: usat r8, #4, r10
+# CHECK: usat r8, #5, r10, lsl #31
+# CHECK: usat r8, #31, r10, asr #32
+# CHECK: usat r8, #16, r10, asr #1
+
+0x1a 0x80 0xe1 0xe6
+0x1a 0x80 0xe4 0xe6
+0x9a 0x8f 0xe5 0xe6
+0x5a 0x80 0xff 0xe6
+0xda 0x80 0xf0 0xe6
+
+#------------------------------------------------------------------------------
+# USAT16
+#------------------------------------------------------------------------------
+# CHECK: usat16 r2, #2, r7
+# CHECK: usat16 r3, #15, r5
+
+0x37 0x2f 0xe2 0xe6
+0x35 0x3f 0xef 0xe6
+
+
+#------------------------------------------------------------------------------
+# USAX
+#------------------------------------------------------------------------------
+# CHECK: usax r2, r3, r4
+# CHECK: usaxne r2, r3, r4
+
+0x54 0x2f 0x53 0xe6
+0x54 0x2f 0x53 0x16
+
+#------------------------------------------------------------------------------
+# USUB16/USUB8
+#------------------------------------------------------------------------------
+# CHECK: usub16 r4, r2, r7
+# CHECK: usub16hi r1, r1, r3
+# CHECK: usub8 r1, r8, r5
+# CHECK: usub8le r9, r2, r3
+
+0x77 0x4f 0x52 0xe6
+0x73 0x1f 0x51 0x86
+0xf5 0x1f 0x58 0xe6
+0xf3 0x9f 0x52 0xd6
+
+
+#------------------------------------------------------------------------------
+# UXTAB
+#------------------------------------------------------------------------------
+# CHECK: uxtab r2, r3, r4
+# CHECK: uxtab r4, r5, r6
+# CHECK: uxtablt r6, r2, r9, ror #8
+# CHECK: uxtab r5, r1, r4, ror #16
+# CHECK: uxtab r7, r8, r3, ror #24
+
+0x74 0x20 0xe3 0xe6
+0x76 0x40 0xe5 0xe6
+0x79 0x64 0xe2 0xb6
+0x74 0x58 0xe1 0xe6
+0x73 0x7c 0xe8 0xe6
+
+
+#------------------------------------------------------------------------------
+# UXTAB16
+#------------------------------------------------------------------------------
+# CHECK: uxtab16ge r0, r1, r4
+# CHECK: uxtab16 r6, r2, r7
+# CHECK: uxtab16 r3, r5, r8, ror #8
+# CHECK: uxtab16 r3, r2, r1, ror #16
+# CHECK: uxtab16eq r1, r2, r3, ror #24
+
+0x74 0x00 0xc1 0xa6
+0x77 0x60 0xc2 0xe6
+0x78 0x34 0xc5 0xe6
+0x71 0x38 0xc2 0xe6
+0x73 0x1c 0xc2 0x06
+
+#------------------------------------------------------------------------------
+# UXTAH
+#------------------------------------------------------------------------------
+# CHECK: uxtah r1, r3, r9
+# CHECK: uxtahhi r6, r1, r6
+# CHECK: uxtah r3, r8, r3, ror #8
+# CHECK: uxtahlo r2, r2, r4, ror #16
+# CHECK: uxtah r9, r3, r3, ror #24
+
+0x79 0x10 0xf3 0xe6
+0x76 0x60 0xf1 0x86
+0x73 0x34 0xf8 0xe6
+0x74 0x28 0xf2 0x36
+0x73 0x9c 0xf3 0xe6
+
+#------------------------------------------------------------------------------
+# UXTB
+#------------------------------------------------------------------------------
+# CHECK: uxtbge r2, r4
+# CHECK: uxtb r5, r6
+# CHECK: uxtb r6, r9, ror #8
+# CHECK: uxtblo r5, r1, ror #16
+# CHECK: uxtb r8, r3, ror #24
+
+0x74 0x20 0xef 0xa6
+0x76 0x50 0xef 0xe6
+0x79 0x64 0xef 0xe6
+0x71 0x58 0xef 0x36
+0x73 0x8c 0xef 0xe6
+
+
+#------------------------------------------------------------------------------
+# UXTB16
+#------------------------------------------------------------------------------
+# CHECK: uxtb16 r1, r4
+# CHECK: uxtb16 r6, r7
+# CHECK: uxtb16hs r3, r5, ror #8
+# CHECK: uxtb16 r3, r1, ror #16
+# CHECK: uxtb16ge r2, r3, ror #24
+
+0x74 0x10 0xcf 0xe6
+0x77 0x60 0xcf 0xe6
+0x75 0x34 0xcf 0x26
+0x71 0x38 0xcf 0xe6
+0x73 0x2c 0xcf 0xa6
+
+
+#------------------------------------------------------------------------------
+# UXTH
+#------------------------------------------------------------------------------
+# CHECK: uxthne r3, r9
+# CHECK: uxth r1, r6
+# CHECK: uxth r3, r8, ror #8
+# CHECK: uxthle r2, r2, ror #16
+# CHECK: uxth r9, r3, ror #24
+
+0x79 0x30 0xff 0x16
+0x76 0x10 0xff 0xe6
+0x78 0x34 0xff 0xe6
+0x72 0x28 0xff 0xd6
+0x73 0x9c 0xff 0xe6
+
+#------------------------------------------------------------------------------
+# WFE/WFI/YIELD
+#------------------------------------------------------------------------------
+# CHECK: wfe
+# CHECK: wfehi
+# CHECK: wfi
+# CHECK: wfilt
+# CHECK: yield
+# CHECK: yieldne
+
+0x02 0xf0 0x20 0xe3
+0x02 0xf0 0x20 0x83
+0x03 0xf0 0x20 0xe3
+0x03 0xf0 0x20 0xb3
+0x01 0xf0 0x20 0xe3
+0x01 0xf0 0x20 0x13
diff --git a/test/MC/Disassembler/ARM/fp-encoding.txt b/test/MC/Disassembler/ARM/fp-encoding.txt
new file mode 100644
index 0000000..f3e0261
--- /dev/null
+++ b/test/MC/Disassembler/ARM/fp-encoding.txt
@@ -0,0 +1,213 @@
+# RUN: llvm-mc -triple armv7-apple-darwin -disassemble < %s | FileCheck %s
+
+0xa0 0x0b 0x71 0xee
+# CHECK: vadd.f64 d16, d17, d16
+
+0x80 0x0a 0x30 0xee
+# CHECK: vadd.f32 s0, s1, s0
+
+0xe0 0x0b 0x71 0xee
+# CHECK: vsub.f64 d16, d17, d16
+
+0xc0 0x0a 0x30 0xee
+# CHECK: vsub.f32 s0, s1, s0
+
+0xa0 0x0b 0xc1 0xee
+# CHECK: vdiv.f64 d16, d17, d16
+
+0x80 0x0a 0x80 0xee
+# CHECK: vdiv.f32 s0, s1, s0
+
+0xa0 0x0b 0x61 0xee
+# CHECK: vmul.f64 d16, d17, d16
+
+0x80 0x0a 0x20 0xee
+# CHECK: vmul.f32 s0, s1, s0
+
+0xe0 0x0b 0x61 0xee
+# CHECK: vnmul.f64 d16, d17, d16
+
+0xc0 0x0a 0x20 0xee
+# CHECK: vnmul.f32 s0, s1, s0
+
+0xe0 0x1b 0xf4 0xee
+# CHECK: vcmpe.f64 d17, d16
+
+0xc0 0x0a 0xf4 0xee
+# CHECK: vcmpe.f32 s1, s0
+
+0xe0 0x0b 0xf0 0xee
+# CHECK: vabs.f64 d16, d16
+
+0xc0 0x0a 0xb0 0xee
+# CHECK: vabs.f32 s0, s0
+
+0xe0 0x0b 0xb7 0xee
+# CHECK: vcvt.f32.f64 s0, d16
+
+0xc0 0x0a 0xf7 0xee
+# CHECK: vcvt.f64.f32 d16, s0
+
+0x60 0x0b 0xf1 0xee
+# CHECK: vneg.f64 d16, d16
+
+0x40 0x0a 0xb1 0xee
+# CHECK: vneg.f32 s0, s0
+
+0xe0 0x0b 0xf1 0xee
+# CHECK: vsqrt.f64 d16, d16
+
+0xc0 0x0a 0xb1 0xee
+# CHECK: vsqrt.f32 s0, s0
+
+0xc0 0x0b 0xf8 0xee
+# CHECK: vcvt.f64.s32 d16, s0
+
+0xc0 0x0a 0xb8 0xee
+# CHECK: vcvt.f32.s32 s0, s0
+
+0x40 0x0b 0xf8 0xee
+# CHECK: vcvt.f64.u32 d16, s0
+
+0x40 0x0a 0xb8 0xee
+# CHECK: vcvt.f32.u32 s0, s0
+
+0xe0 0x0b 0xbd 0xee
+# CHECK: vcvt.s32.f64 s0, d16
+
+0xc0 0x0a 0xbd 0xee
+# CHECK: vcvt.s32.f32 s0, s0
+
+0xe0 0x0b 0xbc 0xee
+# CHECK: vcvt.u32.f64 s0, d16
+
+0xc0 0x0a 0xbc 0xee
+# CHECK: vcvt.u32.f32 s0, s0
+
+0xa1 0x0b 0x42 0xee
+# CHECK: vmla.f64 d16, d18, d17
+
+0x00 0x0a 0x41 0xee
+# CHECK: vmla.f32 s1, s2, s0
+
+0xe1 0x0b 0x42 0xee
+# CHECK: vmls.f64 d16, d18, d17
+
+0x40 0x0a 0x41 0xee
+# CHECK: vmls.f32 s1, s2, s0
+
+0xe1 0x0b 0x52 0xee
+# CHECK: vnmla.f64 d16, d18, d17
+
+0x40 0x0a 0x51 0xee
+# CHECK: vnmla.f32 s1, s2, s0
+
+0xa1 0x0b 0x52 0xee
+# CHECK: vnmls.f64 d16, d18, d17
+
+0x00 0x0a 0x51 0xee
+# CHECK: vnmls.f32 s1, s2, s0
+
+0x60 0x0b 0xf1 0x1e
+# CHECK: vnegne.f64 d16, d16
+
+0x10 0x0a 0x00 0x1e
+0x10 0x1a 0x00 0x0e
+# CHECK: vmovne s0, r0
+# CHECK: vmoveq s0, r1
+
+0x10 0x0a 0xf1 0xee
+# CHECK: vmrs r0, fpscr
+0x10 0x0a 0xf8 0xee
+# CHECK: vmrs r0, fpexc
+0x10 0x0a 0xf0 0xee
+# CHECK: vmrs r0, fpsid
+
+0x10 0x0a 0xe1 0xee
+# CHECK: vmsr fpscr, r0
+0x10 0x0a 0xe8 0xee
+# CHECK: vmsr fpexc, r0
+0x10 0x0a 0xe0 0xee
+# CHECK: vmsr fpsid, r0
+
+0x10 0x0a 0x00 0xee
+0x90 0x1a 0x00 0xee
+0x10 0x2a 0x01 0xee
+0x90 0x3a 0x01 0xee
+# CHECK: vmov s0, r0
+# CHECK: vmov s1, r1
+# CHECK: vmov s2, r2
+# CHECK: vmov s3, r3
+
+0x10 0x0a 0x10 0xee
+0x90 0x1a 0x10 0xee
+0x10 0x2a 0x11 0xee
+0x90 0x3a 0x11 0xee
+# CHECK: vmov r0, s0
+# CHECK: vmov r1, s1
+# CHECK: vmov r2, s2
+# CHECK: vmov r3, s3
+
+0x30 0x0b 0x51 0xec
+# CHECK: vmov r0, r1, d16
+
+0x00 0x1b 0xd0 0xed
+# CHECK: vldr.64 d17, [r0]
+
+0x08 0x1b 0x92 0xed
+0x08 0x1b 0x12 0xed
+# CHECK: vldr.64 d1, [r2, #32]
+# CHECK: vldr.64 d1, [r2, #-32]
+
+0x00 0x2b 0x93 0xed
+# CHECK: vldr.64 d2, [r3]
+
+0x00 0x3b 0x9f 0xed
+# CHECK: vldr.64 d3, [pc]
+
+0x00 0x6a 0xd0 0xed
+# CHECK: vldr.32 s13, [r0]
+
+0x08 0x0a 0xd2 0xed
+0x08 0x0a 0x52 0xed
+# CHECK: vldr.32 s1, [r2, #32]
+# CHECK: vldr.32 s1, [r2, #-32]
+
+0x00 0x1a 0x93 0xed
+# CHECK: vldr.32 s2, [r3]
+
+0x00 0x2a 0xdf 0xed
+# CHECK: vldr.32 s5, [pc]
+
+0x00 0x4b 0x81 0xed
+0x06 0x4b 0x81 0xed
+0x06 0x4b 0x01 0xed
+# CHECK: vstr.64 d4, [r1]
+# CHECK: vstr.64 d4, [r1, #24]
+# CHECK: vstr.64 d4, [r1, #-24]
+
+0x00 0x2a 0x81 0xed
+0x06 0x2a 0x81 0xed
+0x06 0x2a 0x01 0xed
+# CHECK: vstr.32 s4, [r1]
+# CHECK: vstr.32 s4, [r1, #24]
+# CHECK: vstr.32 s4, [r1, #-24]
+
+0x0c 0x2b 0x91 0xec
+0x06 0x1a 0x91 0xec
+# CHECK: vldmia r1, {d2, d3, d4, d5, d6, d7}
+# CHECK: vldmia r1, {s2, s3, s4, s5, s6, s7}
+
+0x0c 0x2b 0x81 0xec
+0x06 0x1a 0x81 0xec
+# CHECK: vstmia r1, {d2, d3, d4, d5, d6, d7}
+# CHECK: vstmia r1, {s2, s3, s4, s5, s6, s7}
+
+0x40 0x0b 0xbd 0xee
+0x60 0x0a 0xbd 0xee
+0x40 0x0b 0xbc 0xee
+0x60 0x0a 0xbc 0xee
+# CHECK: vcvtr.s32.f64 s0, d0
+# CHECK: vcvtr.s32.f32 s0, s1
+# CHECK: vcvtr.u32.f64 s0, d0
+# CHECK: vcvtr.u32.f32 s0, s1
diff --git a/test/MC/Disassembler/ARM/invalid-BFI-arm.txt b/test/MC/Disassembler/ARM/invalid-BFI-arm.txt
index ca0c1ab..a0d5944 100644
--- a/test/MC/Disassembler/ARM/invalid-BFI-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-BFI-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=60 Name=BFI Format=ARM_FORMAT_DPFRM(4)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 0: 1: 1: 1| 1: 1: 0: 0| 1: 1: 1: 1| 1: 1: 1: 1| 0: 0: 0: 0| 0: 0: 0: 1| 0: 1: 1: 0|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt b/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt
index 66c43c2..d2d424c 100644
--- a/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt
@@ -1,10 +1,10 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=2249 Name=tBcc Format=ARM_FORMAT_THUMBFRM(25)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 1: 0: 1| 1: 1: 1: 0| 0: 1: 1: 0| 1: 1: 1: 1|
# -------------------------------------------------------------------------------------------------
-#
+#
# if cond = '1110' then UNDEFINED
0x6f 0xde
diff --git a/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt b/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt
index 5202217..6fdb55e 100644
--- a/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt
@@ -1,4 +1,4 @@
-# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
+# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {potentially undefined instruction encoding}
# invalid (imod, M, iflags) combination
0x93 0x1c 0x02 0xf1
diff --git a/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt b/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt
index 0a4be68..b441485 100644
--- a/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt
@@ -1,11 +1,11 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=1908 Name=t2DMB Format=ARM_FORMAT_THUMBFRM(25)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 0: 0: 1: 1| 1: 0: 1: 1| 1: 1: 1: 1| 1: 0: 0: 0| 1: 1: 1: 1| 0: 1: 0: 1| 0: 0: 0: 1|
# -------------------------------------------------------------------------------------------------
-#
+#
# Inst{3-0} encodes the option: SY, ST, ISH, ISHST, NSH, NSHST, OSH, OSHST.
# Reject invalid encodings.
#
diff --git a/test/MC/Disassembler/ARM/invalid-DSB-arm.txt b/test/MC/Disassembler/ARM/invalid-DSB-arm.txt
index afa2baf..de042a97 100644
--- a/test/MC/Disassembler/ARM/invalid-DSB-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-DSB-arm.txt
@@ -1,11 +1,11 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=102 Name=DSB Format=ARM_FORMAT_MISCFRM(26)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 0: 1: 0: 1| 0: 1: 1: 1| 1: 1: 1: 1| 1: 1: 1: 1| 0: 0: 0: 0| 0: 1: 0: 0| 0: 0: 0: 0|
# -------------------------------------------------------------------------------------------------
-#
+#
# Inst{3-0} encodes the option: SY, ST, ISH, ISHST, NSH, NSHST, OSH, OSHST.
# Reject invalid encodings.
#
diff --git a/test/MC/Disassembler/ARM/invalid-IT-CBNZ-thumb.txt b/test/MC/Disassembler/ARM/invalid-IT-CBNZ-thumb.txt
new file mode 100644
index 0000000..6174e92
--- /dev/null
+++ b/test/MC/Disassembler/ARM/invalid-IT-CBNZ-thumb.txt
@@ -0,0 +1,5 @@
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {potentially undefined instruction encoding}
+
+# CBZ / CBNZ not allowed in IT block.
+
+0xdb 0xbf 0x42 0xbb
diff --git a/test/MC/Disassembler/ARM/invalid-IT-thumb.txt b/test/MC/Disassembler/ARM/invalid-IT-thumb.txt
new file mode 100644
index 0000000..9b571b3
--- /dev/null
+++ b/test/MC/Disassembler/ARM/invalid-IT-thumb.txt
@@ -0,0 +1,3 @@
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-unknown-unknown |& grep {potentially undefined instruction encoding}
+
+0xff 0xbf 0x6b 0x80 0x00 0x75
diff --git a/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt b/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt
index b966a9d..0b0426b 100644
--- a/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=0 Name=PHI Format=(42)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 0: 1| 1: 1: 0: 0| 0: 0: 0: 1| 1: 1: 1: 1| 1: 0: 1: 1| 0: 1: 0: 0| 1: 0: 0: 1| 0: 0: 1: 0|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-LDM-thumb.txt b/test/MC/Disassembler/ARM/invalid-LDM-thumb.txt
new file mode 100644
index 0000000..a42b248
--- /dev/null
+++ b/test/MC/Disassembler/ARM/invalid-LDM-thumb.txt
@@ -0,0 +1,5 @@
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {potentially undefined instruction encoding}
+
+# Writeback is not allowed is Rn is in the target register list.
+
+0xb4 0xe8 0x34 0x04
diff --git a/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt b/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt
index 7a35c2d..6b695b9 100644
--- a/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt
@@ -1,10 +1,10 @@
-# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
+# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {potentially undefined instruction encoding}
# Opcode=140 Name=LDRB_POST Format=ARM_FORMAT_LDFRM(6)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 0: 1: 1: 0| 1: 1: 0: 1| 0: 1: 1: 1| 0: 1: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 1|
# -------------------------------------------------------------------------------------------------
-#
+#
# if wback && (n == 15 || n == t) then UNPREDICTABLE
0x05 0x70 0xd7 0xe6
diff --git a/test/MC/Disassembler/ARM/invalid-LDRD-arm.txt b/test/MC/Disassembler/ARM/invalid-LDRD-arm.txt
new file mode 100644
index 0000000..f8f23ed
--- /dev/null
+++ b/test/MC/Disassembler/ARM/invalid-LDRD-arm.txt
@@ -0,0 +1,10 @@
+# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
+
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# -------------------------------------------------------------------------------------------------
+# | 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| X: X: X: 1| X: X: X: X| 1: 1: X: 1| X: X: X: X|
+# -------------------------------------------------------------------------------------------------
+#
+# A8.6.68 LDRD (register)
+# if Rt{0} = 1 then UNDEFINED;
+0xd0 0x10 0x00 0x00
diff --git a/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt b/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt
index da2e6be..7ea1b46 100644
--- a/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt
@@ -1,4 +1,4 @@
-# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=1930 Name=t2LDRD_PRE Format=ARM_FORMAT_THUMBFRM(25)
# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
diff --git a/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt b/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt
index fb2ce20..067dcb3 100644
--- a/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=0 Name=PHI Format=(42)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 0: 1: 1: 0| 0: 0: 1: 1| 0: 1: 1: 1| 0: 1: 0: 1| 0: 0: 0: 1| 0: 0: 0: 1| 0: 0: 0: 0|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt b/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt
index ad79986..eef2c45 100644
--- a/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt
@@ -1,4 +1,5 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
+# XFAIL: *
# LDR_PRE/POST has encoding Inst{4} = 0.
0xde 0x69 0x18 0x46
diff --git a/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt b/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt
index 36c1124..e42e0de 100644
--- a/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt
@@ -1,10 +1,10 @@
-# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
+# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {potentially undefined instruction encoding}
# Opcode=165 Name=LDR_PRE Format=ARM_FORMAT_LDFRM(6)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 0: 1: 1: 1| 1: 0: 1: 1| 0: 1: 1: 1| 0: 1: 1: 0| 0: 0: 0: 0| 1: 0: 0: 0| 1: 1: 1: 1|
# -------------------------------------------------------------------------------------------------
-#
+#
# if m == 15 then UNPREDICTABLE
0x8f 0x60 0xb7 0xe7
diff --git a/test/MC/Disassembler/ARM/invalid-LSL-regform.txt b/test/MC/Disassembler/ARM/invalid-LSL-regform.txt
index 20293ad..6a1f11f 100644
--- a/test/MC/Disassembler/ARM/invalid-LSL-regform.txt
+++ b/test/MC/Disassembler/ARM/invalid-LSL-regform.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=196 Name=MOVs Format=ARM_FORMAT_DPSOREGFRM(5)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 0: 0: 0: 1| 1: 0: 1: 0| 0: 0: 0: 0| 1: 1: 1: 1| 0: 0: 0: 1| 0: 0: 0: 1| 0: 0: 1: 0|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-MCR-arm.txt b/test/MC/Disassembler/ARM/invalid-MCR-arm.txt
index d39b9c1..8343d54 100644
--- a/test/MC/Disassembler/ARM/invalid-MCR-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-MCR-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=171 Name=MCR Format=ARM_FORMAT_BRFRM(2)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 0: 0: 1: 0| 1: 1: 1: 0| 1: 0: 1: 0| 0: 0: 0: 0| 0: 0: 0: 1| 1: 0: 1: 1| 0: 0: 0: 1| 1: 0: 1: 1|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt b/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
index 0b8a077..235952f 100644
--- a/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
@@ -1,10 +1,10 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=185 Name=MOVTi16 Format=ARM_FORMAT_DPFRM(4)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 0: 0: 1: 1| 0: 1: 0: 0| 0: 0: 0: 1| 1: 1: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0|
# -------------------------------------------------------------------------------------------------
-#
+#
# if d == 15 then UNPREDICTABLE
0x00 0xf0 0x41 0xe3
diff --git a/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt b/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt
index f82d3cb..01c1466 100644
--- a/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=0 Name=PHI Format=(42)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 0: 0: 0: 1| 1: 0: 1: 1| 1: 1: 0: 0| 1: 1: 0: 1| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 1: 0|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt b/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt
index 3165ff7..757d167 100644
--- a/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=196 Name=MOVs Format=ARM_FORMAT_DPSOREGFRM(5)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 0: 1| 0: 0: 0: 1| 1: 0: 1: 0| 0: 0: 0: 0| 0: 1: 0: 0| 0: 0: 1: 0| 1: 0: 0: 1| 0: 0: 1: 1|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt b/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt
index cfbba43..ba48877 100644
--- a/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=0 Name=PHI Format=(42)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 0: 0: 0: 1| 1: 0: 1: 1| 1: 1: 0: 0| 1: 1: 0: 1| 0: 0: 0: 1| 0: 0: 0: 0| 0: 0: 1: 0|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt b/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt
index e9d5deb..3765b1f 100644
--- a/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=206 Name=MSRi Format=ARM_FORMAT_BRFRM(2)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 0: 0: 0: 0| 0: 0: 1: 1| 0: 0: 1: 0| 0: 0: 0: 0| 1: 1: 1: 1| 0: 0: 0: 1| 1: 0: 1: 0| 0: 1: 1: 1|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt b/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt
index 1fdfa82..cffd86d 100644
--- a/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=134 Name=LDMIA Format=ARM_FORMAT_LDSTMULFRM(10)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 1: 0: 0: 0| 1: 0: 0: 1| 1: 0: 0: 1| 1: 0: 1: 1| 0: 0: 0: 1| 0: 0: 1: 1| 0: 0: 1: 0|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-RSC-arm.txt b/test/MC/Disassembler/ARM/invalid-RSC-arm.txt
index e7992ae..096b909 100644
--- a/test/MC/Disassembler/ARM/invalid-RSC-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-RSC-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=261 Name=RSCrs Format=ARM_FORMAT_DPSOREGFRM(5)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 0: 0: 1: 1| 0: 0: 0: 0| 1: 1: 1: 0| 0: 1: 0: 0| 1: 1: 1: 1| 1: 0: 0: 0| 0: 1: 0: 1| 1: 1: 1: 1|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt b/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
index 1ecd87d..9e16536 100644
--- a/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=271 Name=SBFX Format=ARM_FORMAT_DPFRM(4)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 0: 1: 1: 1| 1: 0: 1: 0| 0: 1: 1: 1| 0: 1: 0: 1| 0: 1: 0: 0| 0: 1: 0: 1| 1: 1: 1: 1|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt b/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
index c3dcf83..91f3d58 100644
--- a/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=284 Name=SMLAD Format=ARM_FORMAT_MULFRM(1)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 0: 0: 1| 0: 1: 1: 1| 0: 0: 0: 0| 1: 1: 1: 1| 0: 1: 1: 0| 1: 0: 0: 0| 0: 0: 0: 1| 1: 0: 1: 1|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-SRS-arm.txt b/test/MC/Disassembler/ARM/invalid-SRS-arm.txt
index fdca9f9..fc5c711 100644
--- a/test/MC/Disassembler/ARM/invalid-SRS-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-SRS-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=0 Name=PHI Format=(42)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 1: 0: 0: 0| 1: 1: 0: 0| 0: 1: 0: 1| 0: 0: 0: 1| 1: 1: 0: 0| 1: 0: 0: 0| 0: 0: 1: 1|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt b/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
index 9cc8351..b236f8e 100644
--- a/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=322 Name=SSAT Format=ARM_FORMAT_SATFRM(13)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 0: 1: 1: 0| 1: 0: 1: 0| 0: 0: 0: 0| 1: 1: 1: 1| 0: 1: 0: 0| 0: 0: 0: 1| 1: 0: 1: 0|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt b/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt
index 0000c60..ca16724 100644
--- a/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt
@@ -1,10 +1,10 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=2313 Name=tSTMIA_UPD Format=ARM_FORMAT_THUMBFRM(25)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 1: 0: 0| 0: 1: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0|
# -------------------------------------------------------------------------------------------------
-#
+#
# if BitCount(registers) < 1 then UNPREDICTABLE
0x00 0xc7
diff --git a/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt b/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt
index 5209323..d3998bd 100644
--- a/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt
@@ -1,10 +1,10 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=355 Name=STRBrs Format=ARM_FORMAT_STFRM(7)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 0: 1: 1: 1| 1: 1: 0: 0| 1: 1: 1: 1| 1: 1: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0|
# -------------------------------------------------------------------------------------------------
-#
+#
# if t == 15 then UNPREDICTABLE
0x00 0xf0 0xcf 0xe7
diff --git a/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt b/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
index 4ec681d..400d44c 100644
--- a/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
@@ -1,7 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=390 Name=SXTBr_rot Format=ARM_FORMAT_EXTFRM(14)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 0: 1: 1: 0| 1: 0: 1: 0| 1: 1: 1: 1| 1: 1: 1: 1| 0: 1: 0: 0| 0: 1: 1: 1| 0: 1: 0: 1|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt b/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt
index 7a3ef33..c7cbd84 100644
--- a/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt
@@ -1,11 +1,11 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=419 Name=UMAAL Format=ARM_FORMAT_MULFRM(1)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 0: 0: 0: 0| 0: 1: 0: 0| 1: 1: 1: 1| 1: 0: 1: 1| 1: 1: 1: 1| 1: 0: 0: 1| 1: 0: 0: 0|
# -------------------------------------------------------------------------------------------------
#
# A8.6.244 UMAAL
# if dLo == 15 || dHi == 15 || n == 15 || m == 15 then UNPREDICTABLE;
-0x98 0xbf 0x4f 0xf0
+0x98 0xbf 0x4f 0xf0
diff --git a/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt b/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
index d3f508a..fb3e711 100644
--- a/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
@@ -1,11 +1,11 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=426 Name=UQADD8 Format=ARM_FORMAT_DPFRM(4)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 0: 1: 1: 0| 0: 1: 1: 0| 0: 1: 1: 0| 0: 1: 0: 1| 1: 1: 1: 1| 1: 0: 0: 1| 1: 1: 1: 1|
# -------------------------------------------------------------------------------------------------
-#
+#
# DPFrm with bad reg specifier(s)
#
# if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
diff --git a/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt b/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt
index 56d9ad7..12da869 100644
--- a/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt
@@ -1,4 +1,5 @@
-# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
+# RUN: llvm-mc --disassemble %s -triple=armv7-apple-darwin9 |& grep {invalid instruction encoding}
+# XFAIL: *
# Opcode=737 Name=VLD1DUPq8_UPD Format=ARM_FORMAT_NLdSt(30)
# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
diff --git a/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt b/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt
index 5fd0251..bab32ca 100644
--- a/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt
@@ -1,11 +1,11 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=871 Name=VLD3DUPd32_UPD Format=ARM_FORMAT_NLdSt(30)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 0: 1: 0: 0| 1: 0: 1: 0| 0: 0: 1: 0| 0: 0: 1: 0| 1: 1: 1: 0| 1: 0: 0: 1| 0: 0: 1: 0|
# -------------------------------------------------------------------------------------------------
-#
+#
# A8.6.315 VLD3 (single 3-element structure to all lanes)
# The a bit must be encoded as 0.
0xa2 0xf9 0x92 0x2e
diff --git a/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt b/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt
index eed012b..a53f940 100644
--- a/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt
@@ -1,4 +1,5 @@
-# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
+# RUN: llvm-mc --disassemble %s -triple=armv7-apple-darwin9 |& grep {invalid instruction encoding}
+# XFAIL: *
# Opcode=1225 Name=VQADDsv16i8 Format=ARM_FORMAT_N3Reg(37)
# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
diff --git a/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt b/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt
index 506250c..a12ca95 100644
--- a/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt
+++ b/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt
@@ -1,7 +1,8 @@
-# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
+# RUN: llvm-mc --disassemble %s -triple=armv7-apple-darwin9 |& grep {invalid instruction encoding}
+# XFAIL: *
# Opcode=1641 Name=VST2b32_UPD Format=ARM_FORMAT_NLdSt(30)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 0: 1: 0: 0| 0: 0: 0: 0| 0: 0: 1: 1| 0: 0: 0: 0| 1: 0: 0: 1| 1: 0: 1: 1| 0: 0: 1: 1|
# -------------------------------------------------------------------------------------------------
diff --git a/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt b/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt
index d0bc51e..df0a642 100644
--- a/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt
@@ -1,11 +1,11 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=1894 Name=t2Bcc Format=ARM_FORMAT_THUMBFRM(25)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 0: 1: 1: 1| 1: 0: 1: 0| 1: 1: 1: 1| 1: 0: 0: 0| 1: 0: 1: 1| 0: 1: 0: 0| 0: 1: 0: 0|
# -------------------------------------------------------------------------------------------------
-#
+#
# A8.6.16 B
# if cond<3:1> == '111' then SEE "Related Encodings"
0xaf 0xf7 0x44 0x8b
diff --git a/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt b/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt
index 9befbd6..e1f841b8 100644
--- a/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt
@@ -1,10 +1,10 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=1922 Name=t2LDRBT Format=ARM_FORMAT_THUMBFRM(25)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 1: 0: 0: 0| 0: 0: 0: 1| 0: 0: 0: 0| 1: 1: 1: 1| 1: 1: 1: 0| 0: 0: 0: 0| 0: 0: 1: 1|
# -------------------------------------------------------------------------------------------------
-#
+#
# The unpriviledged Load/Store cannot have SP or PC as Rt.
0x10 0xf8 0x3 0xfe
diff --git a/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt b/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt
index 598efd1..7c0efab 100644
--- a/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt
@@ -1,4 +1,5 @@
-# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {invalid instruction encoding}
+# XFAIL: *
# Opcode=1934 Name=t2LDREXD Format=ARM_FORMAT_THUMBFRM(25)
# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
diff --git a/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt b/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt
index a501eb9..a63d121 100644
--- a/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt
@@ -1,10 +1,10 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=1953 Name=t2LDRSHi12 Format=ARM_FORMAT_THUMBFRM(25)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 1: 0: 0: 1| 1: 0: 1: 1| 0: 0: 1: 1| 1: 1: 1: 1| 1: 0: 0: 0| 1: 1: 0: 1| 1: 1: 1: 1|
# -------------------------------------------------------------------------------------------------
-#
+#
# if Rt = '1111' then SEE "Unallocated memory hints"
0xb3 0xf9 0xdf 0xf8
diff --git a/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt b/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt
index f886a6f..f126ff0 100644
--- a/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt
@@ -1,10 +1,10 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=1954 Name=t2LDRSHi8 Format=ARM_FORMAT_THUMBFRM(25)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 1: 0: 0: 1| 0: 0: 1: 1| 0: 1: 0: 1| 1: 1: 1: 1| 1: 1: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0|
# -------------------------------------------------------------------------------------------------
-#
+#
# if Rt == '1111' and PUW == '100' then SEE "Unallocated memory hints"
0x35 0xf9 0x00 0xfc
diff --git a/test/MC/Disassembler/ARM/invalid-t2PUSH-thumb.txt b/test/MC/Disassembler/ARM/invalid-t2PUSH-thumb.txt
new file mode 100644
index 0000000..b3daa9a
--- /dev/null
+++ b/test/MC/Disassembler/ARM/invalid-t2PUSH-thumb.txt
@@ -0,0 +1,5 @@
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {invalid instruction encoding}
+
+# SP and PC are not allowed in the register list on STM instructions in Thumb2.
+
+0x2d 0xe9 0xf7 0xb6
diff --git a/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt b/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt
index c8f8ec2..2198efc 100644
--- a/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt
@@ -1,4 +1,5 @@
-# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {invalid instruction encoding}
+# XFAIL: *
# Opcode=2124 Name=t2STRD_PRE Format=ARM_FORMAT_THUMBFRM(25)
# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
diff --git a/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt b/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt
index 35ea651..3f406d4 100644
--- a/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt
@@ -1,4 +1,5 @@
-# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 |& grep {invalid instruction encoding}
+# XFAIL: *
# Opcode=2127 Name=t2STREXB Format=ARM_FORMAT_THUMBFRM(25)
# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
diff --git a/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt b/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt
index 9b0cf24..0f9a16e 100644
--- a/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt
@@ -1,10 +1,10 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=2128 Name=t2STREXD Format=ARM_FORMAT_THUMBFRM(25)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 0| 1: 0: 0: 0| 1: 1: 0: 0| 0: 0: 1: 0| 0: 1: 1: 1| 1: 0: 0: 0| 0: 1: 1: 1| 1: 0: 0: 0|
# -------------------------------------------------------------------------------------------------
-#
+#
# if d == n || d == t || d == t2 then UNPREDICTABLE
mc-input.txt:1:1: warning: invalid instruction encoding
diff --git a/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt b/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt
index 129a270..548ad05 100644
--- a/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt
+++ b/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt
@@ -1,10 +1,10 @@
# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
# Opcode=2137 Name=t2STR_POST Format=ARM_FORMAT_THUMBFRM(25)
-# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# -------------------------------------------------------------------------------------------------
# | 1: 1: 1: 1| 1: 0: 0: 0| 0: 1: 0: 0| 1: 1: 1: 1| 1: 1: 1: 0| 1: 0: 1: 1| 1: 1: 1: 1| 1: 1: 1: 1|
# -------------------------------------------------------------------------------------------------
-#
+#
# if Rn == '1111' then UNDEFINED
0x4f 0xf8 0xff 0xeb
diff --git a/test/MC/Disassembler/ARM/memory-arm-instructions.txt b/test/MC/Disassembler/ARM/memory-arm-instructions.txt
new file mode 100644
index 0000000..4fa2897
--- /dev/null
+++ b/test/MC/Disassembler/ARM/memory-arm-instructions.txt
@@ -0,0 +1,470 @@
+# RUN: llvm-mc -triple=armv7-apple-darwin -disassemble < %s | FileCheck %s
+
+#------------------------------------------------------------------------------
+# LDR (immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldr r5, [r7]
+# CHECK: ldr r6, [r3, #63]
+# CHECK: ldr r2, [r4, #4095]!
+# CHECK: ldr r1, [r2], #30
+# CHECK: ldr r3, [r1], #-30
+
+0x00 0x50 0x97 0xe5
+0x3f 0x60 0x93 0xe5
+0xff 0x2f 0xb4 0xe5
+0x1e 0x10 0x92 0xe4
+0x1e 0x30 0x11 0xe4
+
+#------------------------------------------------------------------------------
+# FIXME: LDR (literal)
+#------------------------------------------------------------------------------
+# label operands currently assert the show-encoding asm comment helper due
+# to the use of non-contiguous bit ranges for fixups in ARM. Once that's
+# cleaned up, we can write useful assembly testcases for these sorts of
+# instructions.
+
+#------------------------------------------------------------------------------
+# LDR (register)
+#------------------------------------------------------------------------------
+# CHECK: ldr r3, [r8, r1]
+# CHECK: ldr r2, [r5, -r3]
+# CHECK: ldr r1, [r5, r9]!
+# CHECK: ldr r6, [r7, -r8]!
+# CHECK: ldr r1, [r0, r2, lsr #3]!
+# CHECK: ldr r5, [r9], r2
+# CHECK: ldr r4, [r3], -r6
+# CHECK: ldr r3, [r8, -r2, lsl #15
+# CHECK: ldr r1, [r5], r3, asr #15
+
+0x01 0x30 0x98 0xe7
+0x03 0x20 0x15 0xe7
+0x09 0x10 0xb5 0xe7
+0x08 0x60 0x37 0xe7
+0xa2 0x11 0xb0 0xe7
+0x02 0x50 0x99 0xe6
+0x06 0x40 0x13 0xe6
+0x82 0x37 0x18 0xe7
+0xc3 0x17 0x95 0xe6
+
+
+#------------------------------------------------------------------------------
+# LDRB (immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrb r3, [r8]
+# CHECK: ldrb r1, [sp, #63]
+# CHECK: ldrb r9, [r3, #4095]!
+# CHECK: ldrb r8, [r1], #22
+# CHECK: ldrb r2, [r7], #-19
+
+0x00 0x30 0xd8 0xe5
+0x3f 0x10 0xdd 0xe5
+0xff 0x9f 0xf3 0xe5
+0x16 0x80 0xd1 0xe4
+0x13 0x20 0x57 0xe4
+
+
+#------------------------------------------------------------------------------
+# LDRB (register)
+#------------------------------------------------------------------------------
+# CHECK: ldrb r9, [r8, r5]
+# CHECK: ldrb r1, [r5, -r1]
+# CHECK: ldrb r3, [r5, r2]!
+# CHECK: ldrb r6, [r9, -r3]!
+# CHECK: ldrb r2, [r1], r4
+# CHECK: ldrb r8, [r4], -r5
+# CHECK: ldrb r7, [r12, -r1, lsl #15
+# CHECK: ldrb r5, [r2], r9, asr #15
+
+0x05 0x90 0xd8 0xe7
+0x01 0x10 0x55 0xe7
+0x02 0x30 0xf5 0xe7
+0x03 0x60 0x79 0xe7
+0x04 0x20 0xd1 0xe6
+0x05 0x80 0x54 0xe6
+0x81 0x77 0x5c 0xe7
+0xc9 0x57 0xd2 0xe6
+
+
+#------------------------------------------------------------------------------
+# LDRBT
+#------------------------------------------------------------------------------
+# FIXME: Optional offset operand.
+# CHECK: ldrbt r3, [r1], #4
+# CHECK: ldrbt r2, [r8], #-8
+# CHECK: ldrbt r8, [r7], r6
+# CHECK: ldrbt r1, [r2], -r6, lsl #12
+
+
+0x04 0x30 0xf1 0xe4
+0x08 0x20 0x78 0xe4
+0x06 0x80 0xf7 0xe6
+0x06 0x16 0x72 0xe6
+
+
+#------------------------------------------------------------------------------
+# LDRD (immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrd r0, r1, [r5]
+# CHECK: ldrd r8, r9, [r2, #15]
+# CHECK: ldrd r2, r3, [r9, #32]!
+# CHECK: ldrd r6, r7, [r1], #8
+# CHECK: ldrd r2, r3, [r8], #0
+# CHECK: ldrd r2, r3, [r8], #0
+# CHECK: ldrd r2, r3, [r8], #-0
+
+0xd0 0x00 0xc5 0xe1
+0xdf 0x80 0xc2 0xe1
+0xd0 0x22 0xe9 0xe1
+0xd8 0x60 0xc1 0xe0
+0xd0 0x20 0xc8 0xe0
+0xd0 0x20 0xc8 0xe0
+0xd0 0x20 0x48 0xe0
+
+
+#------------------------------------------------------------------------------
+# FIXME: LDRD (label)
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# LDRD (register)
+#------------------------------------------------------------------------------
+# CHECK: ldrd r4, r5, [r1, r3]
+# CHECK: ldrd r4, r5, [r7, r2]!
+# CHECK: ldrd r0, r1, [r8], r12
+# CHECK: ldrd r0, r1, [r8], -r12
+
+0xd3 0x40 0x81 0xe1
+0xd2 0x40 0xa7 0xe1
+0xdc 0x00 0x88 0xe0
+0xdc 0x00 0x08 0xe0
+
+
+#------------------------------------------------------------------------------
+# LDRH (immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrh r3, [r4
+# CHECK: ldrh r2, [r7, #4
+# CHECK: ldrh r1, [r8, #64]!
+# CHECK: ldrh r12, [sp], #4
+
+0xb0 0x30 0xd4 0xe1
+0xb4 0x20 0xd7 0xe1
+0xb0 0x14 0xf8 0xe1
+0xb4 0xc0 0xdd 0xe0
+
+
+#------------------------------------------------------------------------------
+# FIXME: LDRH (label)
+#------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------
+# LDRH (register)
+#------------------------------------------------------------------------------
+# CHECK: ldrh r6, [r5, r4
+# CHECK: ldrh r3, [r8, r11]!
+# CHECK: ldrh r1, [r2, -r1]!
+# CHECK: ldrh r9, [r7], r2
+# CHECK: ldrh r4, [r3], -r2
+
+0xb4 0x60 0x95 0xe1
+0xbb 0x30 0xb8 0xe1
+0xb1 0x10 0x32 0xe1
+0xb2 0x90 0x97 0xe0
+0xb2 0x40 0x13 0xe0
+
+
+#------------------------------------------------------------------------------
+# LDRHT
+#------------------------------------------------------------------------------
+# CHECK: ldrht r9, [r7], #128
+# CHECK: ldrht r4, [r3], #-75
+# CHECK: ldrht r9, [r7], r2
+# CHECK: ldrht r4, [r3], -r2
+
+0xb0 0x98 0xf7 0xe0
+0xbb 0x44 0x73 0xe0
+0xb2 0x90 0xb7 0xe0
+0xb2 0x40 0x33 0xe0
+
+
+#------------------------------------------------------------------------------
+# LDRSB (immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrsb r3, [r4
+# CHECK: ldrsb r2, [r7, #17
+# CHECK: ldrsb r1, [r8, #255]!
+# CHECK: ldrsb r12, [sp], #9
+
+0xd0 0x30 0xd4 0xe1
+0xd1 0x21 0xd7 0xe1
+0xdf 0x1f 0xf8 0xe1
+0xd9 0xc0 0xdd 0xe0
+
+
+#------------------------------------------------------------------------------
+# FIXME: LDRSB (label)
+#------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------
+# LDRSB (register)
+#------------------------------------------------------------------------------
+# CHECK: ldrsb r6, [r5, r4
+# CHECK: ldrsb r3, [r8, r11]!
+# CHECK: ldrsb r1, [r2, -r1]!
+# CHECK: ldrsb r9, [r7], r2
+# CHECK: ldrsb r4, [r3], -r2
+
+
+0xd4 0x60 0x95 0xe1
+0xdb 0x30 0xb8 0xe1
+0xd1 0x10 0x32 0xe1
+0xd2 0x90 0x97 0xe0
+0xd2 0x40 0x13 0xe0
+
+
+#------------------------------------------------------------------------------
+# LDRSBT
+#------------------------------------------------------------------------------
+# CHECK: ldrsbt r5, [r6], #1
+# CHECK: ldrsbt r3, [r8], #-12
+# CHECK: ldrsbt r8, [r9], r5
+# CHECK: ldrsbt r2, [r1], -r4
+
+0xd1 0x50 0xf6 0xe0
+0xdc 0x30 0x78 0xe0
+0xd5 0x80 0xb9 0xe0
+0xd4 0x20 0x31 0xe0
+
+
+#------------------------------------------------------------------------------
+# LDRSH (immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrsh r5, [r9
+# CHECK: ldrsh r4, [r5, #7
+# CHECK: ldrsh r3, [r6, #55]!
+# CHECK: ldrsh r2, [r7], #-9
+
+0xf0 0x50 0xd9 0xe1
+0xf7 0x40 0xd5 0xe1
+0xf7 0x33 0xf6 0xe1
+0xf9 0x20 0x57 0xe0
+
+
+#------------------------------------------------------------------------------
+# FIXME: LDRSH (label)
+#------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------
+# LDRSH (register)
+#------------------------------------------------------------------------------
+# CHECK: ldrsh r3, [r1, r5
+# CHECK: ldrsh r4, [r6, r1]!
+# CHECK: ldrsh r5, [r3, -r6]!
+# CHECK: ldrsh r6, [r9], r8
+# CHECK: ldrsh r7, [r8], -r3
+
+0xf5 0x30 0x91 0xe1
+0xf1 0x40 0xb6 0xe1
+0xf6 0x50 0x33 0xe1
+0xf8 0x60 0x99 0xe0
+0xf3 0x70 0x18 0xe0
+
+
+#------------------------------------------------------------------------------
+# LDRSHT
+#------------------------------------------------------------------------------
+# CHECK: ldrsht r5, [r6], #1
+# CHECK: ldrsht r3, [r8], #-12
+# CHECK: ldrsht r8, [r9], r5
+# CHECK: ldrsht r2, [r1], -r4
+
+0xf1 0x50 0xf6 0xe0
+0xfc 0x30 0x78 0xe0
+0xf5 0x80 0xb9 0xe0
+0xf4 0x20 0x31 0xe0
+
+
+#------------------------------------------------------------------------------
+# STR (immediate)
+#------------------------------------------------------------------------------
+# CHECK: str r8, [r12
+# CHECK: str r7, [r1, #12
+# CHECK: str r3, [r5, #40]!
+# CHECK: str r9, [sp], #4095
+# CHECK: str r1, [r7], #-128
+
+0x00 0x80 0x8c 0xe5
+0x0c 0x70 0x81 0xe5
+0x28 0x30 0xa5 0xe5
+0xff 0x9f 0x8d 0xe4
+0x80 0x10 0x07 0xe4
+
+
+#------------------------------------------------------------------------------
+# FIXME: STR (literal)
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# STR (register)
+#------------------------------------------------------------------------------
+# CHECK: str r9, [r6, r3
+# CHECK: str r8, [r0, -r2
+# CHECK: str r7, [r1, r6]!
+# CHECK: str r6, [sp, -r1]!
+# CHECK: str r5, [r3], r9
+# CHECK: str r4, [r2], -r5
+# CHECK: str r3, [r4, -r2, lsl #2
+# CHECK: str r2, [r7], r3, asr #24
+
+0x03 0x90 0x86 0xe7
+0x02 0x80 0x00 0xe7
+0x06 0x70 0xa1 0xe7
+0x01 0x60 0x2d 0xe7
+0x09 0x50 0x83 0xe6
+0x05 0x40 0x02 0xe6
+0x02 0x31 0x04 0xe7
+0x43 0x2c 0x87 0xe6
+
+
+#------------------------------------------------------------------------------
+# STRB (immediate)
+#------------------------------------------------------------------------------
+# CHECK: strb r9, [r2
+# CHECK: strb r7, [r1, #3
+# CHECK: strb r6, [r4, #405]!
+# CHECK: strb r5, [r7], #72
+# CHECK: strb r1, [sp], #-1
+
+0x00 0x90 0xc2 0xe5
+0x03 0x70 0xc1 0xe5
+0x95 0x61 0xe4 0xe5
+0x48 0x50 0xc7 0xe4
+0x01 0x10 0x4d 0xe4
+
+#------------------------------------------------------------------------------
+# FIXME: STRB (literal)
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# STRB (register)
+#------------------------------------------------------------------------------
+# CHECK: strb r1, [r2, r9
+# CHECK: strb r2, [r3, -r8
+# CHECK: strb r3, [r4, r7]!
+# CHECK: strb r4, [r5, -r6]!
+# CHECK: strb r5, [r6], r5
+# CHECK: strb r6, [r2], -r4
+# CHECK: strb r7, [r12, -r3, lsl #5
+# CHECK: strb sp, [r7], r2, asr #12
+
+0x09 0x10 0xc2 0xe7
+0x08 0x20 0x43 0xe7
+0x07 0x30 0xe4 0xe7
+0x06 0x40 0x65 0xe7
+0x05 0x50 0xc6 0xe6
+0x04 0x60 0x42 0xe6
+0x83 0x72 0x4c 0xe7
+0x42 0xd6 0xc7 0xe6
+
+
+#------------------------------------------------------------------------------
+# STRBT
+#------------------------------------------------------------------------------
+# FIXME: Optional offset operand.
+# CHECK: strbt r6, [r2], #12
+# CHECK: strbt r5, [r6], #-13
+# CHECK: strbt r4, [r9], r5
+# CHECK: strbt r3, [r8], -r2, lsl #3
+
+0x0c 0x60 0xe2 0xe4
+0x0d 0x50 0x66 0xe4
+0x05 0x40 0xe9 0xe6
+0x82 0x31 0x68 0xe6
+
+
+#------------------------------------------------------------------------------
+# STRD (immediate)
+#------------------------------------------------------------------------------
+# CHECK: strd r0, r1, [r4]
+# CHECK: strd r2, r3, [r6, #1]
+# CHECK: strd r2, r3, [r7, #22]!
+# CHECK: strd r4, r5, [r8], #7
+# CHECK: strd r4, r5, [sp], #0
+# CHECK: strd r6, r7, [lr], #0
+# CHECK: strd r6, r7, [r9], #-0
+
+0xf0 0x00 0xc4 0xe1
+0xf1 0x20 0xc6 0xe1
+0xf6 0x21 0xe7 0xe1
+0xf7 0x40 0xc8 0xe0
+0xf0 0x40 0xcd 0xe0
+0xf0 0x60 0xce 0xe0
+0xf0 0x60 0x49 0xe0
+
+
+#------------------------------------------------------------------------------
+# FIXME: STRD (label)
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# STRD (register)
+#------------------------------------------------------------------------------
+# CHECK: strd r8, r9, [r4, r1]
+# CHECK: strd r6, r7, [r3, r9]!
+# CHECK: strd r6, r7, [r5], r8
+# CHECK: strd r4, r5, [r12], -r10
+
+0xf1 0x80 0x84 0xe1
+0xf9 0x60 0xa3 0xe1
+0xf8 0x60 0x85 0xe0
+0xfa 0x40 0x0c 0xe0
+
+#------------------------------------------------------------------------------
+# STRH (immediate)
+#------------------------------------------------------------------------------
+# CHECK: strh r3, [r4
+# CHECK: strh r2, [r7, #4
+# CHECK: strh r1, [r8, #64]!
+# CHECK: strh r12, [sp], #4
+
+0xb0 0x30 0xc4 0xe1
+0xb4 0x20 0xc7 0xe1
+0xb0 0x14 0xe8 0xe1
+0xb4 0xc0 0xcd 0xe0
+
+
+#------------------------------------------------------------------------------
+# FIXME: STRH (label)
+#------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------
+# STRH (register)
+#------------------------------------------------------------------------------
+# CHECK: strh r6, [r5, r4
+# CHECK: strh r3, [r8, r11]!
+# CHECK: strh r1, [r2, -r1]!
+# CHECK: strh r9, [r7], r2
+# CHECK: strh r4, [r3], -r2
+
+0xb4 0x60 0x85 0xe1
+0xbb 0x30 0xa8 0xe1
+0xb1 0x10 0x22 0xe1
+0xb2 0x90 0x87 0xe0
+0xb2 0x40 0x03 0xe0
+
+#------------------------------------------------------------------------------
+# STRHT
+#------------------------------------------------------------------------------
+# CHECK: strht r2, [r5], #76
+# CHECK: strht r8, [r1], #-25
+# CHECK: strht r5, [r3], r4
+# CHECK: strht r6, [r8], -r0
+
+0xbc 0x24 0xe5 0xe0
+0xb9 0x81 0x61 0xe0
+0xb4 0x50 0xa3 0xe0
+0xb0 0x60 0x28 0xe0
diff --git a/test/MC/Disassembler/ARM/neon-tests.txt b/test/MC/Disassembler/ARM/neon-tests.txt
index 4fa5723..1e03deb 100644
--- a/test/MC/Disassembler/ARM/neon-tests.txt
+++ b/test/MC/Disassembler/ARM/neon-tests.txt
@@ -1,4 +1,4 @@
-# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 | FileCheck %s
+# RUN: llvm-mc --disassemble %s -triple=armv7-apple-darwin9 | FileCheck %s
# CHECK: vbif q15, q7, q0
0x50 0xe1 0x7e 0xf3
@@ -24,7 +24,7 @@
# CHECK: vld1.32 {d3[], d4[]}, [r0, :32]!
0xbd 0x3c 0xa0 0xf4
-# CHECK: vld4.16 {d3[], d4[], d5[], d6[]}, [r0, :64]!
+# CHECK: vld4.16 {d3[], d5[], d7[], d9[]}, [r0, :64]!
0x7d 0x3f 0xa0 0xf4
# CHECK: vorr d0, d15, d15
@@ -87,5 +87,5 @@
# CHECK: usada8mi r8, r9, r5, r9
0x19 0x95 0x88 0x47
-# CHECK: vext.8 q4, q2, q1, #4
+# CHECK: vext.32 q4, q2, q1, #1
0x42 0x84 0xb4 0xf2
diff --git a/test/MC/Disassembler/ARM/neon.txt b/test/MC/Disassembler/ARM/neon.txt
new file mode 100644
index 0000000..5d2df93
--- /dev/null
+++ b/test/MC/Disassembler/ARM/neon.txt
@@ -0,0 +1,1858 @@
+# RUN: llvm-mc -triple armv7-unknown-unknown -disassemble -mattr +fp16 < %s | FileCheck %s
+
+0x20 0x03 0xf1 0xf3
+# CHECK: vabs.s8 d16, d16
+0x20 0x03 0xf5 0xf3
+# CHECK: vabs.s16 d16, d16
+0x20 0x03 0xf9 0xf3
+# CHECK: vabs.s32 d16, d16
+0x20 0x07 0xf9 0xf3
+# CHECK: vabs.f32 d16, d16
+0x60 0x03 0xf1 0xf3
+# CHECK: vabs.s8 q8, q8
+0x60 0x03 0xf5 0xf3
+# CHECK: vabs.s16 q8, q8
+0x60 0x03 0xf9 0xf3
+# CHECK: vabs.s32 q8, q8
+0x60 0x07 0xf9 0xf3
+# CHECK: vabs.f32 q8, q8
+
+0x20 0x07 0xf0 0xf3
+# CHECK: vqabs.s8 d16, d16
+0x20 0x07 0xf4 0xf3
+# CHECK: vqabs.s16 d16, d16
+0x20 0x07 0xf8 0xf3
+# CHECK: vqabs.s32 d16, d16
+0x60 0x07 0xf0 0xf3
+# CHECK: vqabs.s8 q8, q8
+0x60 0x07 0xf4 0xf3
+# CHECK: vqabs.s16 q8, q8
+0x60 0x07 0xf8 0xf3
+# CHECK: vqabs.s32 q8, q8
+
+0xa1 0x07 0x40 0xf2
+# CHECK: vabd.s8 d16, d16, d17
+0xa1 0x07 0x50 0xf2
+# CHECK: vabd.s16 d16, d16, d17
+0xa1 0x07 0x60 0xf2
+# CHECK: vabd.s32 d16, d16, d17
+0xa1 0x07 0x40 0xf3
+# CHECK: vabd.u8 d16, d16, d17
+0xa1 0x07 0x50 0xf3
+# CHECK: vabd.u16 d16, d16, d17
+ 0xa1 0x07 0x60 0xf3
+# CHECK: vabd.u32 d16, d16, d17
+0xa1 0x0d 0x60 0xf3
+# CHECK: vabd.f32 d16, d16, d17
+0xe2 0x07 0x40 0xf2
+# CHECK: vabd.s8 q8, q8, q9
+0xe2 0x07 0x50 0xf2
+# CHECK: vabd.s16 q8, q8, q9
+0xe2 0x07 0x60 0xf2
+# CHECK: vabd.s32 q8, q8, q9
+0xe2 0x07 0x40 0xf3
+# CHECK: vabd.u8 q8, q8, q9
+0xe2 0x07 0x50 0xf3
+# CHECK: vabd.u16 q8, q8, q9
+0xe2 0x07 0x60 0xf3
+# CHECK: vabd.u32 q8, q8, q9
+0xe2 0x0d 0x60 0xf3
+# CHECK: vabd.f32 q8, q8, q9
+
+0xa1 0x07 0xc0 0xf2
+# CHECK: vabdl.s8 q8, d16, d17
+0xa1 0x07 0xd0 0xf2
+# CHECK: vabdl.s16 q8, d16, d17
+0xa1 0x07 0xe0 0xf2
+# CHECK: vabdl.s32 q8, d16, d17
+0xa1 0x07 0xc0 0xf3
+# CHECK: vabdl.u8 q8, d16, d17
+0xa1 0x07 0xd0 0xf3
+# CHECK: vabdl.u16 q8, d16, d17
+0xa1 0x07 0xe0 0xf3
+# CHECK: vabdl.u32 q8, d16, d17
+
+0xb1 0x07 0x42 0xf2
+# CHECK: vaba.s8 d16, d18, d17
+0xb1 0x07 0x52 0xf2
+# CHECK: vaba.s16 d16, d18, d17
+0xb1 0x07 0x62 0xf2
+# CHECK: vaba.s32 d16, d18, d17
+0xb1 0x07 0x42 0xf3
+# CHECK: vaba.u8 d16, d18, d17
+0xb1 0x07 0x52 0xf3
+# CHECK: vaba.u16 d16, d18, d17
+0xb1 0x07 0x62 0xf3
+# CHECK: vaba.u32 d16, d18, d17
+0xf4 0x27 0x40 0xf2
+# CHECK: vaba.s8 q9, q8, q10
+0xf4 0x27 0x50 0xf2
+# CHECK: vaba.s16 q9, q8, q10
+0xf4 0x27 0x60 0xf2
+# CHECK: vaba.s32 q9, q8, q10
+0xf4 0x27 0x40 0xf3
+# CHECK: vaba.u8 q9, q8, q10
+0xf4 0x27 0x50 0xf3
+# CHECK: vaba.u16 q9, q8, q10
+0xf4 0x27 0x60 0xf3
+# CHECK: vaba.u32 q9, q8, q10
+
+0xa2 0x05 0xc3 0xf2
+# CHECK: vabal.s8 q8, d19, d18
+0xa2 0x05 0xd3 0xf2
+# CHECK: vabal.s16 q8, d19, d18
+0xa2 0x05 0xe3 0xf2
+# CHECK: vabal.s32 q8, d19, d18
+0xa2 0x05 0xc3 0xf3
+# CHECK: vabal.u8 q8, d19, d18
+0xa2 0x05 0xd3 0xf3
+# CHECK: vabal.u16 q8, d19, d18
+0xa2 0x05 0xe3 0xf3
+# CHECK: vabal.u32 q8, d19, d18
+
+
+
+
+0xa0 0x08 0x41 0xf2
+# CHECK: vadd.i8 d16, d17, d16
+0xa0 0x08 0x51 0xf2
+# CHECK: vadd.i16 d16, d17, d16
+0xa0 0x08 0x71 0xf2
+# CHECK: vadd.i64 d16, d17, d16
+0xa0 0x08 0x61 0xf2
+# CHECK: vadd.i32 d16, d17, d16
+0xa1 0x0d 0x40 0xf2
+# CHECK: vadd.f32 d16, d16, d17
+0xe2 0x0d 0x40 0xf2
+# CHECK: vadd.f32 q8, q8, q9
+
+0xa0 0x00 0xc1 0xf2
+# CHECK: vaddl.s8 q8, d17, d16
+0xa0 0x00 0xd1 0xf2
+# CHECK: vaddl.s16 q8, d17, d16
+0xa0 0x00 0xe1 0xf2
+# CHECK: vaddl.s32 q8, d17, d16
+0xa0 0x00 0xc1 0xf3
+# CHECK: vaddl.u8 q8, d17, d16
+0xa0 0x00 0xd1 0xf3
+# CHECK: vaddl.u16 q8, d17, d16
+0xa0 0x00 0xe1 0xf3
+# CHECK: vaddl.u32 q8, d17, d16
+
+0xa2 0x01 0xc0 0xf2
+# CHECK: vaddw.s8 q8, q8, d18
+0xa2 0x01 0xd0 0xf2
+# CHECK: vaddw.s16 q8, q8, d18
+0xa2 0x01 0xe0 0xf2
+# CHECK: vaddw.s32 q8, q8, d18
+0xa2 0x01 0xc0 0xf3
+# CHECK: vaddw.u8 q8, q8, d18
+0xa2 0x01 0xd0 0xf3
+# CHECK: vaddw.u16 q8, q8, d18
+0xa2 0x01 0xe0 0xf3
+# CHECK: vaddw.u32 q8, q8, d18
+
+0xa1 0x00 0x40 0xf2
+# CHECK: vhadd.s8 d16, d16, d17
+0xa1 0x00 0x50 0xf2
+# CHECK: vhadd.s16 d16, d16, d17
+0xa1 0x00 0x60 0xf2
+# CHECK: vhadd.s32 d16, d16, d17
+0xa1 0x00 0x40 0xf3
+# CHECK: vhadd.u8 d16, d16, d17
+0xa1 0x00 0x50 0xf3
+# CHECK: vhadd.u16 d16, d16, d17
+0xa1 0x00 0x60 0xf3
+# CHECK: vhadd.u32 d16, d16, d17
+0xe2 0x00 0x40 0xf2
+# CHECK: vhadd.s8 q8, q8, q9
+0xe2 0x00 0x50 0xf2
+# CHECK: vhadd.s16 q8, q8, q9
+0xe2 0x00 0x60 0xf2
+# CHECK: vhadd.s32 q8, q8, q9
+ 0xe2 0x00 0x40 0xf3
+# CHECK: vhadd.u8 q8, q8, q9
+0xe2 0x00 0x50 0xf3
+# CHECK: vhadd.u16 q8, q8, q9
+0xe2 0x00 0x60 0xf3
+# CHECK: vhadd.u32 q8, q8, q9
+
+0xa1 0x01 0x40 0xf2
+# CHECK: vrhadd.s8 d16, d16, d17
+0xa1 0x01 0x50 0xf2
+# CHECK: vrhadd.s16 d16, d16, d17
+0xa1 0x01 0x60 0xf2
+# CHECK: vrhadd.s32 d16, d16, d17
+0xa1 0x01 0x40 0xf3
+# CHECK: vrhadd.u8 d16, d16, d17
+0xa1 0x01 0x50 0xf3
+# CHECK: vrhadd.u16 d16, d16, d17
+0xa1 0x01 0x60 0xf3
+# CHECK: vrhadd.u32 d16, d16, d17
+0xe2 0x01 0x40 0xf2
+# CHECK: vrhadd.s8 q8, q8, q9
+0xe2 0x01 0x50 0xf2
+# CHECK: vrhadd.s16 q8, q8, q9
+0xe2 0x01 0x60 0xf2
+# CHECK: vrhadd.s32 q8, q8, q9
+0xe2 0x01 0x40 0xf3
+# CHECK: vrhadd.u8 q8, q8, q9
+0xe2 0x01 0x50 0xf3
+# CHECK: vrhadd.u16 q8, q8, q9
+0xe2 0x01 0x60 0xf3
+# CHECK: vrhadd.u32 q8, q8, q9
+
+0xb1 0x00 0x40 0xf2
+# CHECK: vqadd.s8 d16, d16, d17
+0xb1 0x00 0x50 0xf2
+# CHECK: vqadd.s16 d16, d16, d17
+0xb1 0x00 0x60 0xf2
+# CHECK: vqadd.s32 d16, d16, d17
+0xb1 0x00 0x70 0xf2
+# CHECK: vqadd.s64 d16, d16, d17
+0xb1 0x00 0x40 0xf3
+# CHECK: vqadd.u8 d16, d16, d17
+0xb1 0x00 0x50 0xf3
+# CHECK: vqadd.u16 d16, d16, d17
+0xb1 0x00 0x60 0xf3
+# CHECK: vqadd.u32 d16, d16, d17
+0xb1 0x00 0x70 0xf3
+# CHECK: vqadd.u64 d16, d16, d17
+0xf2 0x00 0x40 0xf2
+# CHECK: vqadd.s8 q8, q8, q9
+0xf2 0x00 0x50 0xf2
+# CHECK: vqadd.s16 q8, q8, q9
+0xf2 0x00 0x60 0xf2
+# CHECK: vqadd.s32 q8, q8, q9
+0xf2 0x00 0x70 0xf2
+# CHECK: vqadd.s64 q8, q8, q9
+0xf2 0x00 0x40 0xf3
+# CHECK: vqadd.u8 q8, q8, q9
+0xf2 0x00 0x50 0xf3
+# CHECK: vqadd.u16 q8, q8, q9
+0xf2 0x00 0x60 0xf3
+# CHECK: vqadd.u32 q8, q8, q9
+0xf2 0x00 0x70 0xf3
+# CHECK: vqadd.u64 q8, q8, q9
+
+0xa2 0x04 0xc0 0xf2
+# CHECK: vaddhn.i16 d16, q8, q9
+0xa2 0x04 0xd0 0xf2
+# CHECK: vaddhn.i32 d16, q8, q9
+0xa2 0x04 0xe0 0xf2
+# CHECK: vaddhn.i64 d16, q8, q9
+0xa2 0x04 0xc0 0xf3
+# CHECK: vraddhn.i16 d16, q8, q9
+0xa2 0x04 0xd0 0xf3
+# CHECK: vraddhn.i32 d16, q8, q9
+0xa2 0x04 0xe0 0xf3
+# CHECK: vraddhn.i64 d16, q8, q9
+
+
+0x20 0x05 0xf0 0xf3
+# CHECK: vcnt.8 d16, d16
+0x60 0x05 0xf0 0xf3
+# CHECK: vcnt.8 q8, q8
+0xa0 0x04 0xf0 0xf3
+# CHECK: vclz.i8 d16, d16
+0xa0 0x04 0xf4 0xf3
+# CHECK: vclz.i16 d16, d16
+0xa0 0x04 0xf8 0xf3
+# CHECK: vclz.i32 d16, d16
+0xe0 0x04 0xf0 0xf3
+# CHECK: vclz.i8 q8, q8
+0xe0 0x04 0xf4 0xf3
+# CHECK: vclz.i16 q8, q8
+0xe0 0x04 0xf8 0xf3
+# CHECK: vclz.i32 q8, q8
+0x20 0x04 0xf0 0xf3
+# CHECK: vcls.s8 d16, d16
+0x20 0x04 0xf4 0xf3
+# CHECK: vcls.s16 d16, d16
+0x20 0x04 0xf8 0xf3
+# CHECK: vcls.s32 d16, d16
+0x60 0x04 0xf0 0xf3
+# CHECK: vcls.s8 q8, q8
+0x60 0x04 0xf4 0xf3
+# CHECK: vcls.s16 q8, q8
+0x60 0x04 0xf8 0xf3
+# CHECK: vcls.s32 q8, q8
+
+
+
+
+0xb0 0x01 0x41 0xf2
+# CHECK: vand d16, d17, d16
+0xf2 0x01 0x40 0xf2
+# CHECK: vand q8, q8, q9
+
+0xb0 0x01 0x41 0xf3
+# CHECK: veor d16, d17, d16
+0xf2 0x01 0x40 0xf3
+# CHECK: veor q8, q8, q9
+
+0xb0 0x01 0x61 0xf2
+# CHECK: vorr d16, d17, d16
+0xf2 0x01 0x60 0xf2
+# CHECK: vorr q8, q8, q9
+0x11 0x07 0xc0 0xf2
+# CHECK: vorr.i32 d16, #0x1000000
+0x51 0x07 0xc0 0xf2
+# CHECK: vorr.i32 q8, #0x1000000
+0x50 0x01 0xc0 0xf2
+# CHECK: vorr.i32 q8, #0x0
+
+0xb0 0x01 0x51 0xf2
+# CHECK: vbic d16, d17, d16
+0xf2 0x01 0x50 0xf2
+# CHECK: vbic q8, q8, q9
+0x3f 0x07 0xc7 0xf3
+# CHECK: vbic.i32 d16, #0xFF000000
+0x7f 0x07 0xc7 0xf3
+# CHECK: vbic.i32 q8, #0xFF000000
+
+0xb0 0x01 0x71 0xf2
+# CHECK: vorn d16, d17, d16
+0xf2 0x01 0x70 0xf2
+# CHECK: vorn q8, q8, q9
+
+0xa0 0x05 0xf0 0xf3
+# CHECK: vmvn d16, d16
+0xe0 0x05 0xf0 0xf3
+# CHECK: vmvn q8, q8
+
+0xb0 0x21 0x51 0xf3
+# CHECK: vbsl d18, d17, d16
+0xf2 0x01 0x54 0xf3
+# CHECK: vbsl q8, q10, q9
+
+
+# CHECK: vceq.i8 d16, d16, d17
+# CHECK: vceq.i16 d16, d16, d17
+# CHECK: vceq.i32 d16, d16, d17
+# CHECK: vceq.f32 d16, d16, d17
+# CHECK: vceq.i8 q8, q8, q9
+# CHECK: vceq.i16 q8, q8, q9
+# CHECK: vceq.i32 q8, q8, q9
+# CHECK: vceq.f32 q8, q8, q9
+
+0xb1 0x08 0x40 0xf3
+0xb1 0x08 0x50 0xf3
+0xb1 0x08 0x60 0xf3
+0xa1 0x0e 0x40 0xf2
+0xf2 0x08 0x40 0xf3
+0xf2 0x08 0x50 0xf3
+0xf2 0x08 0x60 0xf3
+0xe2 0x0e 0x40 0xf2
+
+# CHECK: vcge.s8 d16, d16, d17
+# CHECK: vcge.s16 d16, d16, d17
+# CHECK: vcge.s32 d16, d16, d17
+# CHECK: vcge.u8 d16, d16, d17
+# CHECK: vcge.u16 d16, d16, d17
+# CHECK: vcge.u32 d16, d16, d17
+# CHECK: vcge.f32 d16, d16, d17
+# CHECK: vcge.s8 q8, q8, q9
+# CHECK: vcge.s16 q8, q8, q9
+# CHECK: vcge.s32 q8, q8, q9
+# CHECK: vcge.u8 q8, q8, q9
+# CHECK: vcge.u16 q8, q8, q9
+# CHECK: vcge.u32 q8, q8, q9
+# CHECK: vcge.f32 q8, q8, q9
+# CHECK: vacge.f32 d16, d16, d17
+# CHECK: vacge.f32 q8, q8, q9
+
+0xb1 0x03 0x40 0xf2
+0xb1 0x03 0x50 0xf2
+0xb1 0x03 0x60 0xf2
+0xb1 0x03 0x40 0xf3
+0xb1 0x03 0x50 0xf3
+0xb1 0x03 0x60 0xf3
+0xa1 0x0e 0x40 0xf3
+0xf2 0x03 0x40 0xf2
+0xf2 0x03 0x50 0xf2
+0xf2 0x03 0x60 0xf2
+0xf2 0x03 0x40 0xf3
+0xf2 0x03 0x50 0xf3
+0xf2 0x03 0x60 0xf3
+0xe2 0x0e 0x40 0xf3
+0xb1 0x0e 0x40 0xf3
+0xf2 0x0e 0x40 0xf3
+
+# CHECK: vcgt.s8 d16, d16, d17
+# CHECK: vcgt.s16 d16, d16, d17
+# CHECK: vcgt.s32 d16, d16, d17
+# CHECK: vcgt.u8 d16, d16, d17
+# CHECK: vcgt.u16 d16, d16, d17
+# CHECK: vcgt.u32 d16, d16, d17
+# CHECK: vcgt.f32 d16, d16, d17
+# CHECK: vcgt.s8 q8, q8, q9
+# CHECK: vcgt.s16 q8, q8, q9
+# CHECK: vcgt.s32 q8, q8, q9
+# CHECK: vcgt.u8 q8, q8, q9
+# CHECK: vcgt.u16 q8, q8, q9
+# CHECK: vcgt.u32 q8, q8, q9
+# CHECK: vcgt.f32 q8, q8, q9
+# CHECK: vacgt.f32 d16, d16, d17
+# CHECK: vacgt.f32 q8, q8, q9
+
+0xa1 0x03 0x40 0xf2
+0xa1 0x03 0x50 0xf2
+0xa1 0x03 0x60 0xf2
+0xa1 0x03 0x40 0xf3
+0xa1 0x03 0x50 0xf3
+0xa1 0x03 0x60 0xf3
+0xa1 0x0e 0x60 0xf3
+0xe2 0x03 0x40 0xf2
+0xe2 0x03 0x50 0xf2
+0xe2 0x03 0x60 0xf2
+0xe2 0x03 0x40 0xf3
+0xe2 0x03 0x50 0xf3
+0xe2 0x03 0x60 0xf3
+0xe2 0x0e 0x60 0xf3
+0xb1 0x0e 0x60 0xf3
+0xf2 0x0e 0x60 0xf3
+
+# CHECK: vtst.8 d16, d16, d17
+# CHECK: vtst.16 d16, d16, d17
+# CHECK: vtst.32 d16, d16, d17
+# CHECK: vtst.8 q8, q8, q9
+# CHECK: vtst.16 q8, q8, q9
+# CHECK: vtst.32 q8, q8, q9
+
+0xb1 0x08 0x40 0xf2
+0xb1 0x08 0x50 0xf2
+0xb1 0x08 0x60 0xf2
+0xf2 0x08 0x40 0xf2
+0xf2 0x08 0x50 0xf2
+0xf2 0x08 0x60 0xf2
+
+# CHECK: vceq.i8 d16, d16, #0
+# CHECK: vcge.s8 d16, d16, #0
+# CHECK: vcle.s8 d16, d16, #0
+# CHECK: vcgt.s8 d16, d16, #0
+# CHECK: vclt.s8 d16, d16, #0
+
+0x20 0x01 0xf1 0xf3
+0xa0 0x00 0xf1 0xf3
+0xa0 0x01 0xf1 0xf3
+0x20 0x00 0xf1 0xf3
+0x20 0x02 0xf1 0xf3
+
+
+0x20 0x07 0xfb 0xf3
+# CHECK: vcvt.s32.f32 d16, d16
+0xa0 0x07 0xfb 0xf3
+# CHECK: vcvt.u32.f32 d16, d16
+0x20 0x06 0xfb 0xf3
+# CHECK: vcvt.f32.s32 d16, d16
+0xa0 0x06 0xfb 0xf3
+# CHECK: vcvt.f32.u32 d16, d16
+0x60 0x07 0xfb 0xf3
+# CHECK: vcvt.s32.f32 q8, q8
+0xe0 0x07 0xfb 0xf3
+# CHECK: vcvt.u32.f32 q8, q8
+0x60 0x06 0xfb 0xf3
+# CHECK: vcvt.f32.s32 q8, q8
+0xe0 0x06 0xfb 0xf3
+# CHECK: vcvt.f32.u32 q8, q8
+0x30 0x0f 0xff 0xf2
+# CHECK: vcvt.s32.f32 d16, d16, #1
+0x30 0x0f 0xff 0xf3
+# CHECK: vcvt.u32.f32 d16, d16, #1
+0x30 0x0e 0xff 0xf2
+# CHECK: vcvt.f32.s32 d16, d16, #1
+0x30 0x0e 0xff 0xf3
+# CHECK: vcvt.f32.u32 d16, d16, #1
+0x70 0x0f 0xff 0xf2
+# CHECK: vcvt.s32.f32 q8, q8, #1
+0x70 0x0f 0xff 0xf3
+# CHECK: vcvt.u32.f32 q8, q8, #1
+0x70 0x0e 0xff 0xf2
+# CHECK: vcvt.f32.s32 q8, q8, #1
+0x70 0x0e 0xff 0xf3
+# CHECK: vcvt.f32.u32 q8, q8, #1
+0x20 0x07 0xf6 0xf3
+# CHECK: vcvt.f32.f16 q8, d16
+0x20 0x06 0xf6 0xf3
+# CHECK: vcvt.f16.f32 d16, q8
+
+
+
+
+# CHECK: vdup.8 d16, r0
+# CHECK: vdup.16 d16, r0
+# CHECK: vdup.32 d16, r0
+
+0x90 0x0b 0xc0 0xee
+0xb0 0x0b 0x80 0xee
+0x90 0x0b 0x80 0xee
+
+# CHECK: vdup.8 q8, r0
+# CHECK: vdup.16 q8, r0
+# CHECK: vdup.32 q8, r0
+
+0x90 0x0b 0xe0 0xee
+0xb0 0x0b 0xa0 0xee
+0x90 0x0b 0xa0 0xee
+
+# CHECK: vdup.8 d16, d16[1
+# CHECK: vdup.16 d16, d16[1
+# CHECK: vdup.32 d16, d16[1
+
+0x20 0x0c 0xf3 0xf3
+0x20 0x0c 0xf6 0xf3
+0x20 0x0c 0xfc 0xf3
+
+# CHECK: vdup.8 q8, d16[1
+# CHECK: vdup.16 q8, d16[1
+# CHECK: vdup.32 q8, d16[1
+
+0x60 0x0c 0xf3 0xf3
+0x60 0x0c 0xf6 0xf3
+0x60 0x0c 0xfc 0xf3
+
+
+0xb1 0x06 0x40 0xf2
+# CHECK: vmin.s8 d16, d16, d17
+0xb1 0x06 0x50 0xf2
+# CHECK: vmin.s16 d16, d16, d17
+0xb1 0x06 0x60 0xf2
+# CHECK: vmin.s32 d16, d16, d17
+0xb1 0x06 0x40 0xf3
+# CHECK: vmin.u8 d16, d16, d17
+0xb1 0x06 0x50 0xf3
+# CHECK: vmin.u16 d16, d16, d17
+0xb1 0x06 0x60 0xf3
+# CHECK: vmin.u32 d16, d16, d17
+0xa1 0x0f 0x60 0xf2
+# CHECK: vmin.f32 d16, d16, d17
+0xf2 0x06 0x40 0xf2
+# CHECK: vmin.s8 q8, q8, q9
+0xf2 0x06 0x50 0xf2
+# CHECK: vmin.s16 q8, q8, q9
+0xf2 0x06 0x60 0xf2
+# CHECK: vmin.s32 q8, q8, q9
+0xf2 0x06 0x40 0xf3
+# CHECK: vmin.u8 q8, q8, q9
+0xf2 0x06 0x50 0xf3
+# CHECK: vmin.u16 q8, q8, q9
+0xf2 0x06 0x60 0xf3
+# CHECK: vmin.u32 q8, q8, q9
+0xe2 0x0f 0x60 0xf2
+# CHECK: vmin.f32 q8, q8, q9
+0xa1 0x06 0x40 0xf2
+# CHECK: vmax.s8 d16, d16, d17
+0xa1 0x06 0x50 0xf2
+# CHECK: vmax.s16 d16, d16, d17
+0xa1 0x06 0x60 0xf2
+# CHECK: vmax.s32 d16, d16, d17
+0xa1 0x06 0x40 0xf3
+# CHECK: vmax.u8 d16, d16, d17
+0xa1 0x06 0x50 0xf3
+# CHECK: vmax.u16 d16, d16, d17
+0xa1 0x06 0x60 0xf3
+# CHECK: vmax.u32 d16, d16, d17
+0xa1 0x0f 0x40 0xf2
+# CHECK: vmax.f32 d16, d16, d17
+0xe2 0x06 0x40 0xf2
+# CHECK: vmax.s8 q8, q8, q9
+0xe2 0x06 0x50 0xf2
+# CHECK: vmax.s16 q8, q8, q9
+0xe2 0x06 0x60 0xf2
+# CHECK: vmax.s32 q8, q8, q9
+0xe2 0x06 0x40 0xf3
+# CHECK: vmax.u8 q8, q8, q9
+0xe2 0x06 0x50 0xf3
+# CHECK: vmax.u16 q8, q8, q9
+0xe2 0x06 0x60 0xf3
+# CHECK: vmax.u32 q8, q8, q9
+0xe2 0x0f 0x40 0xf2
+# CHECK: vmax.f32 q8, q8, q9
+
+
+
+0x18 0x0e 0xc0 0xf2
+# CHECK: vmov.i8 d16, #0x8
+0x10 0x08 0xc1 0xf2
+# CHECK: vmov.i16 d16, #0x10
+0x10 0x0a 0xc1 0xf2
+# CHECK: vmov.i16 d16, #0x1000
+0x10 0x00 0xc2 0xf2
+# CHECK: vmov.i32 d16, #0x20
+0x10 0x02 0xc2 0xf2
+# CHECK: vmov.i32 d16, #0x2000
+0x10 0x04 0xc2 0xf2
+# CHECK: vmov.i32 d16, #0x200000
+0x10 0x06 0xc2 0xf2
+# CHECK: vmov.i32 d16, #0x20000000
+0x10 0x0c 0xc2 0xf2
+# CHECK: vmov.i32 d16, #0x20FF
+0x10 0x0d 0xc2 0xf2
+# CHECK: vmov.i32 d16, #0x20FFFF
+0x33 0x0e 0xc1 0xf3
+# CHECK: vmov.i64 d16, #0xFF0000FF0000FFFF
+0x58 0x0e 0xc0 0xf2
+# CHECK: vmov.i8 q8, #0x8
+0x50 0x08 0xc1 0xf2
+# CHECK: vmov.i16 q8, #0x10
+0x50 0x0a 0xc1 0xf2
+# CHECK: vmov.i16 q8, #0x1000
+0x50 0x00 0xc2 0xf2
+# CHECK: vmov.i32 q8, #0x20
+0x50 0x02 0xc2 0xf2
+# CHECK: vmov.i32 q8, #0x2000
+0x50 0x04 0xc2 0xf2
+# CHECK: vmov.i32 q8, #0x200000
+0x50 0x06 0xc2 0xf2
+# CHECK: vmov.i32 q8, #0x20000000
+0x50 0x0c 0xc2 0xf2
+# CHECK: vmov.i32 q8, #0x20FF
+0x50 0x0d 0xc2 0xf2
+# CHECK: vmov.i32 q8, #0x20FFFF
+0x73 0x0e 0xc1 0xf3
+# CHECK: vmov.i64 q8, #0xFF0000FF0000FFFF
+0x30 0x08 0xc1 0xf2
+# CHECK: vmvn.i16 d16, #0x10
+0x30 0x0a 0xc1 0xf2
+# CHECK: vmvn.i16 d16, #0x1000
+0x30 0x00 0xc2 0xf2
+# CHECK: vmvn.i32 d16, #0x20
+0x30 0x02 0xc2 0xf2
+# CHECK: vmvn.i32 d16, #0x2000
+0x30 0x04 0xc2 0xf2
+# CHECK: vmvn.i32 d16, #0x200000
+0x30 0x06 0xc2 0xf2
+# CHECK: vmvn.i32 d16, #0x20000000
+0x30 0x0c 0xc2 0xf2
+# CHECK: vmvn.i32 d16, #0x20FF
+0x30 0x0d 0xc2 0xf2
+# CHECK: vmvn.i32 d16, #0x20FFFF
+0x30 0x0a 0xc8 0xf2
+# CHECK: vmovl.s8 q8, d16
+0x30 0x0a 0xd0 0xf2
+# CHECK: vmovl.s16 q8, d16
+0x30 0x0a 0xe0 0xf2
+# CHECK: vmovl.s32 q8, d16
+0x30 0x0a 0xc8 0xf3
+# CHECK: vmovl.u8 q8, d16
+0x30 0x0a 0xd0 0xf3
+# CHECK: vmovl.u16 q8, d16
+0x30 0x0a 0xe0 0xf3
+# CHECK: vmovl.u32 q8, d16
+0x20 0x02 0xf2 0xf3
+# CHECK: vmovn.i16 d16, q8
+0x20 0x02 0xf6 0xf3
+# CHECK: vmovn.i32 d16, q8
+0x20 0x02 0xfa 0xf3
+# CHECK: vmovn.i64 d16, q8
+0xa0 0x02 0xf2 0xf3
+# CHECK: vqmovn.s16 d16, q8
+0xa0 0x02 0xf6 0xf3
+# CHECK: vqmovn.s32 d16, q8
+0xa0 0x02 0xfa 0xf3
+# CHECK: vqmovn.s64 d16, q8
+0xe0 0x02 0xf2 0xf3
+# CHECK: vqmovn.u16 d16, q8
+0xe0 0x02 0xf6 0xf3
+# CHECK: vqmovn.u32 d16, q8
+0xe0 0x02 0xfa 0xf3
+# CHECK: vqmovn.u64 d16, q8
+0x60 0x02 0xf2 0xf3
+# CHECK: vqmovun.s16 d16, q8
+0x60 0x02 0xf6 0xf3
+# CHECK: vqmovun.s32 d16, q8
+0x60 0x02 0xfa 0xf3
+# CHECK: vqmovun.s64 d16, q8
+0xb0 0x0b 0x50 0xee
+# CHECK: vmov.s8 r0, d16[1
+0xf0 0x0b 0x10 0xee
+# CHECK: vmov.s16 r0, d16[1
+0xb0 0x0b 0xd0 0xee
+# CHECK: vmov.u8 r0, d16[1
+0xf0 0x0b 0x90 0xee
+# CHECK: vmov.u16 r0, d16[1
+0x90 0x0b 0x30 0xee
+# CHECK: vmov.32 r0, d16[1
+0xb0 0x1b 0x40 0xee
+# CHECK: vmov.8 d16[1], r1
+0xf0 0x1b 0x00 0xee
+# CHECK: vmov.16 d16[1], r1
+0x90 0x1b 0x20 0xee
+# CHECK: vmov.32 d16[1], r1
+0xb0 0x1b 0x42 0xee
+# CHECK: vmov.8 d18[1], r1
+0xf0 0x1b 0x02 0xee
+# CHECK: vmov.16 d18[1], r1
+0x90 0x1b 0x22 0xee
+# CHECK: vmov.32 d18[1], r1
+
+
+
+0xa1 0x09 0x42 0xf2
+# CHECK: vmla.i8 d16, d18, d17
+0xa1 0x09 0x52 0xf2
+# CHECK: vmla.i16 d16, d18, d17
+0xa1 0x09 0x62 0xf2
+# CHECK: vmla.i32 d16, d18, d17
+0xb1 0x0d 0x42 0xf2
+# CHECK: vmla.f32 d16, d18, d17
+0xe4 0x29 0x40 0xf2
+# CHECK: vmla.i8 q9, q8, q10
+0xe4 0x29 0x50 0xf2
+# CHECK: vmla.i16 q9, q8, q10
+0xe4 0x29 0x60 0xf2
+# CHECK: vmla.i32 q9, q8, q10
+0xf4 0x2d 0x40 0xf2
+# CHECK: vmla.f32 q9, q8, q10
+0xa2 0x08 0xc3 0xf2
+# CHECK: vmlal.s8 q8, d19, d18
+0xa2 0x08 0xd3 0xf2
+# CHECK: vmlal.s16 q8, d19, d18
+0xa2 0x08 0xe3 0xf2
+# CHECK: vmlal.s32 q8, d19, d18
+0xa2 0x08 0xc3 0xf3
+# CHECK: vmlal.u8 q8, d19, d18
+0xa2 0x08 0xd3 0xf3
+# CHECK: vmlal.u16 q8, d19, d18
+0xa2 0x08 0xe3 0xf3
+# CHECK: vmlal.u32 q8, d19, d18
+0xa2 0x09 0xd3 0xf2
+# CHECK: vqdmlal.s16 q8, d19, d18
+0xa2 0x09 0xe3 0xf2
+# CHECK: vqdmlal.s32 q8, d19, d18
+0xa1 0x09 0x42 0xf3
+# CHECK: vmls.i8 d16, d18, d17
+0xa1 0x09 0x52 0xf3
+# CHECK: vmls.i16 d16, d18, d17
+0xa1 0x09 0x62 0xf3
+# CHECK: vmls.i32 d16, d18, d17
+0xb1 0x0d 0x62 0xf2
+# CHECK: vmls.f32 d16, d18, d17
+0xe4 0x29 0x40 0xf3
+# CHECK: vmls.i8 q9, q8, q10
+0xe4 0x29 0x50 0xf3
+# CHECK: vmls.i16 q9, q8, q10
+0xe4 0x29 0x60 0xf3
+# CHECK: vmls.i32 q9, q8, q10
+0xf4 0x2d 0x60 0xf2
+# CHECK: vmls.f32 q9, q8, q10
+0xa2 0x0a 0xc3 0xf2
+# CHECK: vmlsl.s8 q8, d19, d18
+0xa2 0x0a 0xd3 0xf2
+# CHECK: vmlsl.s16 q8, d19, d18
+0xa2 0x0a 0xe3 0xf2
+# CHECK: vmlsl.s32 q8, d19, d18
+0xa2 0x0a 0xc3 0xf3
+# CHECK: vmlsl.u8 q8, d19, d18
+0xa2 0x0a 0xd3 0xf3
+# CHECK: vmlsl.u16 q8, d19, d18
+0xa2 0x0a 0xe3 0xf3
+# CHECK: vmlsl.u32 q8, d19, d18
+0xa2 0x0b 0xd3 0xf2
+# CHECK: vqdmlsl.s16 q8, d19, d18
+0xa2 0x0b 0xe3 0xf2
+# CHECK: vqdmlsl.s32 q8, d19, d18
+
+
+0xb1 0x09 0x40 0xf2
+# CHECK: vmul.i8 d16, d16, d17
+0xb1 0x09 0x50 0xf2
+# CHECK: vmul.i16 d16, d16, d17
+0xb1 0x09 0x60 0xf2
+# CHECK: vmul.i32 d16, d16, d17
+0xb1 0x0d 0x40 0xf3
+# CHECK: vmul.f32 d16, d16, d17
+0xf2 0x09 0x40 0xf2
+# CHECK: vmul.i8 q8, q8, q9
+0xf2 0x09 0x50 0xf2
+# CHECK: vmul.i16 q8, q8, q9
+0xf2 0x09 0x60 0xf2
+# CHECK: vmul.i32 q8, q8, q9
+0xf2 0x0d 0x40 0xf3
+# CHECK: vmul.f32 q8, q8, q9
+0xb1 0x09 0x40 0xf3
+# CHECK: vmul.p8 d16, d16, d17
+0xf2 0x09 0x40 0xf3
+# CHECK: vmul.p8 q8, q8, q9
+0xa1 0x0b 0x50 0xf2
+# CHECK: vqdmulh.s16 d16, d16, d17
+0xa1 0x0b 0x60 0xf2
+# CHECK: vqdmulh.s32 d16, d16, d17
+0xe2 0x0b 0x50 0xf2
+# CHECK: vqdmulh.s16 q8, q8, q9
+0xe2 0x0b 0x60 0xf2
+# CHECK: vqdmulh.s32 q8, q8, q9
+0xa1 0x0b 0x50 0xf3
+# CHECK: vqrdmulh.s16 d16, d16, d17
+0xa1 0x0b 0x60 0xf3
+# CHECK: vqrdmulh.s32 d16, d16, d17
+0xe2 0x0b 0x50 0xf3
+# CHECK: vqrdmulh.s16 q8, q8, q9
+0xe2 0x0b 0x60 0xf3
+# CHECK: vqrdmulh.s32 q8, q8, q9
+0xa1 0x0c 0xc0 0xf2
+# CHECK: vmull.s8 q8, d16, d17
+0xa1 0x0c 0xd0 0xf2
+# CHECK: vmull.s16 q8, d16, d17
+0xa1 0x0c 0xe0 0xf2
+# CHECK: vmull.s32 q8, d16, d17
+0xa1 0x0c 0xc0 0xf3
+# CHECK: vmull.u8 q8, d16, d17
+0xa1 0x0c 0xd0 0xf3
+# CHECK: vmull.u16 q8, d16, d17
+0xa1 0x0c 0xe0 0xf3
+# CHECK: vmull.u32 q8, d16, d17
+0xa1 0x0e 0xc0 0xf2
+# CHECK: vmull.p8 q8, d16, d17
+0xa1 0x0d 0xd0 0xf2
+# CHECK: vqdmull.s16 q8, d16, d17
+0xa1 0x0d 0xe0 0xf2
+# CHECK: vqdmull.s32 q8, d16, d17
+
+
+0xa0 0x03 0xf1 0xf3
+# CHECK: vneg.s8 d16, d16
+0xa0 0x03 0xf5 0xf3
+# CHECK: vneg.s16 d16, d16
+0xa0 0x03 0xf9 0xf3
+# CHECK: vneg.s32 d16, d16
+0xa0 0x07 0xf9 0xf3
+# CHECK: vneg.f32 d16, d16
+0xe0 0x03 0xf1 0xf3
+# CHECK: vneg.s8 q8, q8
+0xe0 0x03 0xf5 0xf3
+# CHECK: vneg.s16 q8, q8
+0xe0 0x03 0xf9 0xf3
+# CHECK: vneg.s32 q8, q8
+0xe0 0x07 0xf9 0xf3
+# CHECK: vneg.f32 q8, q8
+0xa0 0x07 0xf0 0xf3
+# CHECK: vqneg.s8 d16, d16
+0xa0 0x07 0xf4 0xf3
+# CHECK: vqneg.s16 d16, d16
+0xa0 0x07 0xf8 0xf3
+# CHECK: vqneg.s32 d16, d16
+0xe0 0x07 0xf0 0xf3
+# CHECK: vqneg.s8 q8, q8
+0xe0 0x07 0xf4 0xf3
+# CHECK: vqneg.s16 q8, q8
+0xe0 0x07 0xf8 0xf3
+# CHECK: vqneg.s32 q8, q8
+
+
+0xb0 0x0b 0x41 0xf2
+# CHECK: vpadd.i8 d16, d17, d16
+0xb0 0x0b 0x51 0xf2
+# CHECK: vpadd.i16 d16, d17, d16
+0xb0 0x0b 0x61 0xf2
+# CHECK: vpadd.i32 d16, d17, d16
+0xa1 0x0d 0x40 0xf3
+# CHECK: vpadd.f32 d16, d16, d17
+0x20 0x02 0xf0 0xf3
+# CHECK: vpaddl.s8 d16, d16
+0x20 0x02 0xf4 0xf3
+# CHECK: vpaddl.s16 d16, d16
+0x20 0x02 0xf8 0xf3
+# CHECK: vpaddl.s32 d16, d16
+0xa0 0x02 0xf0 0xf3
+# CHECK: vpaddl.u8 d16, d16
+0xa0 0x02 0xf4 0xf3
+# CHECK: vpaddl.u16 d16, d16
+0xa0 0x02 0xf8 0xf3
+# CHECK: vpaddl.u32 d16, d16
+0x60 0x02 0xf0 0xf3
+# CHECK: vpaddl.s8 q8, q8
+0x60 0x02 0xf4 0xf3
+# CHECK: vpaddl.s16 q8, q8
+0x60 0x02 0xf8 0xf3
+# CHECK: vpaddl.s32 q8, q8
+0xe0 0x02 0xf0 0xf3
+# CHECK: vpaddl.u8 q8, q8
+0xe0 0x02 0xf4 0xf3
+# CHECK: vpaddl.u16 q8, q8
+0xe0 0x02 0xf8 0xf3
+# CHECK: vpaddl.u32 q8, q8
+0x21 0x06 0xf0 0xf3
+# CHECK: vpadal.s8 d16, d17
+0x21 0x06 0xf4 0xf3
+# CHECK: vpadal.s16 d16, d17
+0x21 0x06 0xf8 0xf3
+# CHECK: vpadal.s32 d16, d17
+0xa1 0x06 0xf0 0xf3
+# CHECK: vpadal.u8 d16, d17
+0xa1 0x06 0xf4 0xf3
+# CHECK: vpadal.u16 d16, d17
+0xa1 0x06 0xf8 0xf3
+# CHECK: vpadal.u32 d16, d17
+0x60 0x26 0xf0 0xf3
+# CHECK: vpadal.s8 q9, q8
+0x60 0x26 0xf4 0xf3
+# CHECK: vpadal.s16 q9, q8
+0x60 0x26 0xf8 0xf3
+# CHECK: vpadal.s32 q9, q8
+0xe0 0x26 0xf0 0xf3
+# CHECK: vpadal.u8 q9, q8
+0xe0 0x26 0xf4 0xf3
+# CHECK: vpadal.u16 q9, q8
+0xe0 0x26 0xf8 0xf3
+# CHECK: vpadal.u32 q9, q8
+0xb1 0x0a 0x40 0xf2
+# CHECK: vpmin.s8 d16, d16, d17
+0xb1 0x0a 0x50 0xf2
+# CHECK: vpmin.s16 d16, d16, d17
+0xb1 0x0a 0x60 0xf2
+# CHECK: vpmin.s32 d16, d16, d17
+0xb1 0x0a 0x40 0xf3
+# CHECK: vpmin.u8 d16, d16, d17
+0xb1 0x0a 0x50 0xf3
+# CHECK: vpmin.u16 d16, d16, d17
+0xb1 0x0a 0x60 0xf3
+# CHECK: vpmin.u32 d16, d16, d17
+0xa1 0x0f 0x60 0xf3
+# CHECK: vpmin.f32 d16, d16, d17
+0xa1 0x0a 0x40 0xf2
+# CHECK: vpmax.s8 d16, d16, d17
+0xa1 0x0a 0x50 0xf2
+# CHECK: vpmax.s16 d16, d16, d17
+0xa1 0x0a 0x60 0xf2
+# CHECK: vpmax.s32 d16, d16, d17
+0xa1 0x0a 0x40 0xf3
+# CHECK: vpmax.u8 d16, d16, d17
+0xa1 0x0a 0x50 0xf3
+# CHECK: vpmax.u16 d16, d16, d17
+0xa1 0x0a 0x60 0xf3
+# CHECK: vpmax.u32 d16, d16, d17
+0xa1 0x0f 0x40 0xf3
+# CHECK: vpmax.f32 d16, d16, d17
+
+
+0x20 0x04 0xfb 0xf3
+# CHECK: vrecpe.u32 d16, d16
+0x60 0x04 0xfb 0xf3
+# CHECK: vrecpe.u32 q8, q8
+0x20 0x05 0xfb 0xf3
+# CHECK: vrecpe.f32 d16, d16
+0x60 0x05 0xfb 0xf3
+# CHECK: vrecpe.f32 q8, q8
+0xb1 0x0f 0x40 0xf2
+# CHECK: vrecps.f32 d16, d16, d17
+0xf2 0x0f 0x40 0xf2
+# CHECK: vrecps.f32 q8, q8, q9
+0xa0 0x04 0xfb 0xf3
+# CHECK: vrsqrte.u32 d16, d16
+0xe0 0x04 0xfb 0xf3
+# CHECK: vrsqrte.u32 q8, q8
+0xa0 0x05 0xfb 0xf3
+# CHECK: vrsqrte.f32 d16, d16
+0xe0 0x05 0xfb 0xf3
+# CHECK: vrsqrte.f32 q8, q8
+0xb1 0x0f 0x60 0xf2
+# CHECK: vrsqrts.f32 d16, d16, d17
+0xf2 0x0f 0x60 0xf2
+# CHECK: vrsqrts.f32 q8, q8, q9
+
+
+0x20 0x00 0xf0 0xf3
+# CHECK: vrev64.8 d16, d16
+0x20 0x00 0xf4 0xf3
+# CHECK: vrev64.16 d16, d16
+0x20 0x00 0xf8 0xf3
+# CHECK: vrev64.32 d16, d16
+0x60 0x00 0xf0 0xf3
+# CHECK: vrev64.8 q8, q8
+0x60 0x00 0xf4 0xf3
+# CHECK: vrev64.16 q8, q8
+0x60 0x00 0xf8 0xf3
+# CHECK: vrev64.32 q8, q8
+0xa0 0x00 0xf0 0xf3
+# CHECK: vrev32.8 d16, d16
+0xa0 0x00 0xf4 0xf3
+# CHECK: vrev32.16 d16, d16
+0xe0 0x00 0xf0 0xf3
+# CHECK: vrev32.8 q8, q8
+0xe0 0x00 0xf4 0xf3
+# CHECK: vrev32.16 q8, q8
+0x20 0x01 0xf0 0xf3
+# CHECK: vrev16.8 d16, d16
+0x60 0x01 0xf0 0xf3
+# CHECK: vrev16.8 q8, q8
+
+
+0xb0 0x04 0x41 0xf2
+# CHECK: vqshl.s8 d16, d16, d17
+0xb0 0x04 0x51 0xf2
+# CHECK: vqshl.s16 d16, d16, d17
+0xb0 0x04 0x61 0xf2
+# CHECK: vqshl.s32 d16, d16, d17
+0xb0 0x04 0x71 0xf2
+# CHECK: vqshl.s64 d16, d16, d17
+0xb0 0x04 0x41 0xf3
+# CHECK: vqshl.u8 d16, d16, d17
+0xb0 0x04 0x51 0xf3
+# CHECK: vqshl.u16 d16, d16, d17
+0xb0 0x04 0x61 0xf3
+# CHECK: vqshl.u32 d16, d16, d17
+0xb0 0x04 0x71 0xf3
+# CHECK: vqshl.u64 d16, d16, d17
+0xf0 0x04 0x42 0xf2
+# CHECK: vqshl.s8 q8, q8, q9
+0xf0 0x04 0x52 0xf2
+# CHECK: vqshl.s16 q8, q8, q9
+0xf0 0x04 0x62 0xf2
+# CHECK: vqshl.s32 q8, q8, q9
+0xf0 0x04 0x72 0xf2
+# CHECK: vqshl.s64 q8, q8, q9
+0xf0 0x04 0x42 0xf3
+# CHECK: vqshl.u8 q8, q8, q9
+0xf0 0x04 0x52 0xf3
+# CHECK: vqshl.u16 q8, q8, q9
+0xf0 0x04 0x62 0xf3
+# CHECK: vqshl.u32 q8, q8, q9
+0xf0 0x04 0x72 0xf3
+# CHECK: vqshl.u64 q8, q8, q9
+0x30 0x07 0xcf 0xf2
+# CHECK: vqshl.s8 d16, d16, #7
+0x30 0x07 0xdf 0xf2
+# CHECK: vqshl.s16 d16, d16, #15
+0x30 0x07 0xff 0xf2
+# CHECK: vqshl.s32 d16, d16, #31
+0xb0 0x07 0xff 0xf2
+# CHECK: vqshl.s64 d16, d16, #63
+0x30 0x07 0xcf 0xf3
+# CHECK: vqshl.u8 d16, d16, #7
+0x30 0x07 0xdf 0xf3
+# CHECK: vqshl.u16 d16, d16, #15
+0x30 0x07 0xff 0xf3
+# CHECK: vqshl.u32 d16, d16, #31
+0xb0 0x07 0xff 0xf3
+# CHECK: vqshl.u64 d16, d16, #63
+0x30 0x06 0xcf 0xf3
+# CHECK: vqshlu.s8 d16, d16, #7
+0x30 0x06 0xdf 0xf3
+# CHECK: vqshlu.s16 d16, d16, #15
+0x30 0x06 0xff 0xf3
+# CHECK: vqshlu.s32 d16, d16, #31
+0xb0 0x06 0xff 0xf3
+# CHECK: vqshlu.s64 d16, d16, #63
+0x70 0x07 0xcf 0xf2
+# CHECK: vqshl.s8 q8, q8, #7
+0x70 0x07 0xdf 0xf2
+# CHECK: vqshl.s16 q8, q8, #15
+0x70 0x07 0xff 0xf2
+# CHECK: vqshl.s32 q8, q8, #31
+0xf0 0x07 0xff 0xf2
+# CHECK: vqshl.s64 q8, q8, #63
+0x70 0x07 0xcf 0xf3
+# CHECK: vqshl.u8 q8, q8, #7
+0x70 0x07 0xdf 0xf3
+# CHECK: vqshl.u16 q8, q8, #15
+0x70 0x07 0xff 0xf3
+# CHECK: vqshl.u32 q8, q8, #31
+0xf0 0x07 0xff 0xf3
+# CHECK: vqshl.u64 q8, q8, #63
+0x70 0x06 0xcf 0xf3
+# CHECK: vqshlu.s8 q8, q8, #7
+0x70 0x06 0xdf 0xf3
+# CHECK: vqshlu.s16 q8, q8, #15
+0x70 0x06 0xff 0xf3
+# CHECK: vqshlu.s32 q8, q8, #31
+0xf0 0x06 0xff 0xf3
+# CHECK: vqshlu.s64 q8, q8, #63
+0xb0 0x05 0x41 0xf2
+# CHECK: vqrshl.s8 d16, d16, d17
+0xb0 0x05 0x51 0xf2
+# CHECK: vqrshl.s16 d16, d16, d17
+0xb0 0x05 0x61 0xf2
+# CHECK: vqrshl.s32 d16, d16, d17
+0xb0 0x05 0x71 0xf2
+# CHECK: vqrshl.s64 d16, d16, d17
+0xb0 0x05 0x41 0xf3
+# CHECK: vqrshl.u8 d16, d16, d17
+0xb0 0x05 0x51 0xf3
+# CHECK: vqrshl.u16 d16, d16, d17
+0xb0 0x05 0x61 0xf3
+# CHECK: vqrshl.u32 d16, d16, d17
+0xb0 0x05 0x71 0xf3
+# CHECK: vqrshl.u64 d16, d16, d17
+0xf0 0x05 0x42 0xf2
+# CHECK: vqrshl.s8 q8, q8, q9
+0xf0 0x05 0x52 0xf2
+# CHECK: vqrshl.s16 q8, q8, q9
+0xf0 0x05 0x62 0xf2
+# CHECK: vqrshl.s32 q8, q8, q9
+0xf0 0x05 0x72 0xf2
+# CHECK: vqrshl.s64 q8, q8, q9
+0xf0 0x05 0x42 0xf3
+# CHECK: vqrshl.u8 q8, q8, q9
+0xf0 0x05 0x52 0xf3
+# CHECK: vqrshl.u16 q8, q8, q9
+0xf0 0x05 0x62 0xf3
+# CHECK: vqrshl.u32 q8, q8, q9
+0xf0 0x05 0x72 0xf3
+# CHECK: vqrshl.u64 q8, q8, q9
+0x30 0x09 0xc8 0xf2
+# CHECK: vqshrn.s16 d16, q8, #8
+0x30 0x09 0xd0 0xf2
+# CHECK: vqshrn.s32 d16, q8, #16
+0x30 0x09 0xe0 0xf2
+# CHECK: vqshrn.s64 d16, q8, #32
+0x30 0x09 0xc8 0xf3
+# CHECK: vqshrn.u16 d16, q8, #8
+0x30 0x09 0xd0 0xf3
+# CHECK: vqshrn.u32 d16, q8, #16
+0x30 0x09 0xe0 0xf3
+# CHECK: vqshrn.u64 d16, q8, #32
+0x30 0x08 0xc8 0xf3
+# CHECK: vqshrun.s16 d16, q8, #8
+0x30 0x08 0xd0 0xf3
+# CHECK: vqshrun.s32 d16, q8, #16
+0x30 0x08 0xe0 0xf3
+# CHECK: vqshrun.s64 d16, q8, #32
+0x70 0x09 0xc8 0xf2
+# CHECK: vqrshrn.s16 d16, q8, #8
+0x70 0x09 0xd0 0xf2
+# CHECK: vqrshrn.s32 d16, q8, #16
+0x70 0x09 0xe0 0xf2
+# CHECK: vqrshrn.s64 d16, q8, #32
+0x70 0x09 0xc8 0xf3
+# CHECK: vqrshrn.u16 d16, q8, #8
+0x70 0x09 0xd0 0xf3
+# CHECK: vqrshrn.u32 d16, q8, #16
+0x70 0x09 0xe0 0xf3
+# CHECK: vqrshrn.u64 d16, q8, #32
+0x70 0x08 0xc8 0xf3
+# CHECK: vqrshrun.s16 d16, q8, #8
+0x70 0x08 0xd0 0xf3
+# CHECK: vqrshrun.s32 d16, q8, #16
+0x70 0x08 0xe0 0xf3
+# CHECK: vqrshrun.s64 d16, q8, #32
+
+
+0xa1 0x04 0x40 0xf3
+# CHECK: vshl.u8 d16, d17, d16
+0xa1 0x04 0x50 0xf3
+# CHECK: vshl.u16 d16, d17, d16
+0xa1 0x04 0x60 0xf3
+# CHECK: vshl.u32 d16, d17, d16
+0xa1 0x04 0x70 0xf3
+# CHECK: vshl.u64 d16, d17, d16
+0x30 0x05 0xcf 0xf2
+# CHECK: vshl.i8 d16, d16, #7
+0x30 0x05 0xdf 0xf2
+# CHECK: vshl.i16 d16, d16, #15
+0x30 0x05 0xff 0xf2
+# CHECK: vshl.i32 d16, d16, #31
+0xb0 0x05 0xff 0xf2
+# CHECK: vshl.i64 d16, d16, #63
+0xe2 0x04 0x40 0xf3
+# CHECK: vshl.u8 q8, q9, q8
+0xe2 0x04 0x50 0xf3
+# CHECK: vshl.u16 q8, q9, q8
+0xe2 0x04 0x60 0xf3
+# CHECK: vshl.u32 q8, q9, q8
+0xe2 0x04 0x70 0xf3
+# CHECK: vshl.u64 q8, q9, q8
+0x70 0x05 0xcf 0xf2
+# CHECK: vshl.i8 q8, q8, #7
+0x70 0x05 0xdf 0xf2
+# CHECK: vshl.i16 q8, q8, #15
+0x70 0x05 0xff 0xf2
+# CHECK: vshl.i32 q8, q8, #31
+0xf0 0x05 0xff 0xf2
+# CHECK: vshl.i64 q8, q8, #63
+0x30 0x00 0xc9 0xf3
+# CHECK: vshr.u8 d16, d16, #7
+0x30 0x00 0xd1 0xf3
+# CHECK: vshr.u16 d16, d16, #15
+0x30 0x00 0xe1 0xf3
+# CHECK: vshr.u32 d16, d16, #31
+0xb0 0x00 0xc1 0xf3
+# CHECK: vshr.u64 d16, d16, #63
+0x70 0x00 0xc9 0xf3
+# CHECK: vshr.u8 q8, q8, #7
+0x70 0x00 0xd1 0xf3
+# CHECK: vshr.u16 q8, q8, #15
+0x70 0x00 0xe1 0xf3
+# CHECK: vshr.u32 q8, q8, #31
+0xf0 0x00 0xc1 0xf3
+# CHECK: vshr.u64 q8, q8, #63
+0x30 0x00 0xc9 0xf2
+# CHECK: vshr.s8 d16, d16, #7
+0x30 0x00 0xd1 0xf2
+# CHECK: vshr.s16 d16, d16, #15
+0x30 0x00 0xe1 0xf2
+# CHECK: vshr.s32 d16, d16, #31
+0xb0 0x00 0xc1 0xf2
+# CHECK: vshr.s64 d16, d16, #63
+0x70 0x00 0xc9 0xf2
+# CHECK: vshr.s8 q8, q8, #7
+0x70 0x00 0xd1 0xf2
+# CHECK: vshr.s16 q8, q8, #15
+0x70 0x00 0xe1 0xf2
+# CHECK: vshr.s32 q8, q8, #31
+0xf0 0x00 0xc1 0xf2
+# CHECK: vshr.s64 q8, q8, #63
+0x30 0x01 0xc9 0xf3
+# CHECK: vsra.u8 d16, d16, #7
+0x30 0x01 0xd1 0xf3
+# CHECK: vsra.u16 d16, d16, #15
+0x30 0x01 0xe1 0xf3
+# CHECK: vsra.u32 d16, d16, #31
+0xb0 0x01 0xc1 0xf3
+# CHECK: vsra.u64 d16, d16, #63
+0x70 0x01 0xc9 0xf3
+# CHECK: vsra.u8 q8, q8, #7
+0x70 0x01 0xd1 0xf3
+# CHECK: vsra.u16 q8, q8, #15
+0x70 0x01 0xe1 0xf3
+# CHECK: vsra.u32 q8, q8, #31
+0xf0 0x01 0xc1 0xf3
+# CHECK: vsra.u64 q8, q8, #63
+0x30 0x01 0xc9 0xf2
+# CHECK: vsra.s8 d16, d16, #7
+0x30 0x01 0xd1 0xf2
+# CHECK: vsra.s16 d16, d16, #15
+0x30 0x01 0xe1 0xf2
+# CHECK: vsra.s32 d16, d16, #31
+0xb0 0x01 0xc1 0xf2
+# CHECK: vsra.s64 d16, d16, #63
+0x70 0x01 0xc9 0xf2
+# CHECK: vsra.s8 q8, q8, #7
+0x70 0x01 0xd1 0xf2
+# CHECK: vsra.s16 q8, q8, #15
+0x70 0x01 0xe1 0xf2
+# CHECK: vsra.s32 q8, q8, #31
+0xf0 0x01 0xc1 0xf2
+# CHECK: vsra.s64 q8, q8, #63
+0x30 0x04 0xc9 0xf3
+# CHECK: vsri.8 d16, d16, #7
+0x30 0x04 0xd1 0xf3
+# CHECK: vsri.16 d16, d16, #15
+0x30 0x04 0xe1 0xf3
+# CHECK: vsri.32 d16, d16, #31
+0xb0 0x04 0xc1 0xf3
+# CHECK: vsri.64 d16, d16, #63
+0x70 0x04 0xc9 0xf3
+# CHECK: vsri.8 q8, q8, #7
+0x70 0x04 0xd1 0xf3
+# CHECK: vsri.16 q8, q8, #15
+0x70 0x04 0xe1 0xf3
+# CHECK: vsri.32 q8, q8, #31
+0xf0 0x04 0xc1 0xf3
+# CHECK: vsri.64 q8, q8, #63
+0x30 0x05 0xcf 0xf3
+# CHECK: vsli.8 d16, d16, #7
+0x30 0x05 0xdf 0xf3
+# CHECK: vsli.16 d16, d16, #15
+0x30 0x05 0xff 0xf3
+# CHECK: vsli.32 d16, d16, #31
+0xb0 0x05 0xff 0xf3
+# CHECK: vsli.64 d16, d16, #63
+0x70 0x05 0xcf 0xf3
+# CHECK: vsli.8 q8, q8, #7
+0x70 0x05 0xdf 0xf3
+# CHECK: vsli.16 q8, q8, #15
+0x70 0x05 0xff 0xf3
+# CHECK: vsli.32 q8, q8, #31
+0xf0 0x05 0xff 0xf3
+# CHECK: vsli.64 q8, q8, #63
+0x30 0x0a 0xcf 0xf2
+# CHECK: vshll.s8 q8, d16, #7
+0x30 0x0a 0xdf 0xf2
+# CHECK: vshll.s16 q8, d16, #15
+0x30 0x0a 0xff 0xf2
+# CHECK: vshll.s32 q8, d16, #31
+0x30 0x0a 0xcf 0xf3
+# CHECK: vshll.u8 q8, d16, #7
+0x30 0x0a 0xdf 0xf3
+# CHECK: vshll.u16 q8, d16, #15
+0x30 0x0a 0xff 0xf3
+# CHECK: vshll.u32 q8, d16, #31
+0x20 0x03 0xf2 0xf3
+# CHECK: vshll.i8 q8, d16, #8
+0x20 0x03 0xf6 0xf3
+# CHECK: vshll.i16 q8, d16, #16
+0x20 0x03 0xfa 0xf3
+# CHECK: vshll.i32 q8, d16, #32
+0x30 0x08 0xc8 0xf2
+# CHECK: vshrn.i16 d16, q8, #8
+0x30 0x08 0xd0 0xf2
+# CHECK: vshrn.i32 d16, q8, #16
+0x30 0x08 0xe0 0xf2
+# CHECK: vshrn.i64 d16, q8, #32
+0xa1 0x05 0x40 0xf2
+# CHECK: vrshl.s8 d16, d17, d16
+0xa1 0x05 0x50 0xf2
+# CHECK: vrshl.s16 d16, d17, d16
+0xa1 0x05 0x60 0xf2
+# CHECK: vrshl.s32 d16, d17, d16
+0xa1 0x05 0x70 0xf2
+# CHECK: vrshl.s64 d16, d17, d16
+0xa1 0x05 0x40 0xf3
+# CHECK: vrshl.u8 d16, d17, d16
+0xa1 0x05 0x50 0xf3
+# CHECK: vrshl.u16 d16, d17, d16
+0xa1 0x05 0x60 0xf3
+# CHECK: vrshl.u32 d16, d17, d16
+0xa1 0x05 0x70 0xf3
+# CHECK: vrshl.u64 d16, d17, d16
+0xe2 0x05 0x40 0xf2
+# CHECK: vrshl.s8 q8, q9, q8
+0xe2 0x05 0x50 0xf2
+# CHECK: vrshl.s16 q8, q9, q8
+0xe2 0x05 0x60 0xf2
+# CHECK: vrshl.s32 q8, q9, q8
+0xe2 0x05 0x70 0xf2
+# CHECK: vrshl.s64 q8, q9, q8
+0xe2 0x05 0x40 0xf3
+# CHECK: vrshl.u8 q8, q9, q8
+0xe2 0x05 0x50 0xf3
+# CHECK: vrshl.u16 q8, q9, q8
+0xe2 0x05 0x60 0xf3
+# CHECK: vrshl.u32 q8, q9, q8
+0xe2 0x05 0x70 0xf3
+# CHECK: vrshl.u64 q8, q9, q8
+0x30 0x02 0xc8 0xf2
+# CHECK: vrshr.s8 d16, d16, #8
+0x30 0x02 0xd0 0xf2
+# CHECK: vrshr.s16 d16, d16, #16
+0x30 0x02 0xe0 0xf2
+# CHECK: vrshr.s32 d16, d16, #32
+0xb0 0x02 0xc0 0xf2
+# CHECK: vrshr.s64 d16, d16, #64
+0x30 0x02 0xc8 0xf3
+# CHECK: vrshr.u8 d16, d16, #8
+0x30 0x02 0xd0 0xf3
+# CHECK: vrshr.u16 d16, d16, #16
+0x30 0x02 0xe0 0xf3
+# CHECK: vrshr.u32 d16, d16, #32
+0xb0 0x02 0xc0 0xf3
+# CHECK: vrshr.u64 d16, d16, #64
+0x70 0x02 0xc8 0xf2
+# CHECK: vrshr.s8 q8, q8, #8
+0x70 0x02 0xd0 0xf2
+# CHECK: vrshr.s16 q8, q8, #16
+0x70 0x02 0xe0 0xf2
+# CHECK: vrshr.s32 q8, q8, #32
+0xf0 0x02 0xc0 0xf2
+# CHECK: vrshr.s64 q8, q8, #64
+0x70 0x02 0xc8 0xf3
+# CHECK: vrshr.u8 q8, q8, #8
+0x70 0x02 0xd0 0xf3
+# CHECK: vrshr.u16 q8, q8, #16
+0x70 0x02 0xe0 0xf3
+# CHECK: vrshr.u32 q8, q8, #32
+0xf0 0x02 0xc0 0xf3
+# CHECK: vrshr.u64 q8, q8, #64
+0x70 0x08 0xc8 0xf2
+# CHECK: vrshrn.i16 d16, q8, #8
+0x70 0x08 0xd0 0xf2
+# CHECK: vrshrn.i32 d16, q8, #16
+0x70 0x08 0xe0 0xf2
+# CHECK: vrshrn.i64 d16, q8, #32
+0x70 0x09 0xcc 0xf2
+# CHECK: vqrshrn.s16 d16, q8, #4
+0x70 0x09 0xd3 0xf2
+# CHECK: vqrshrn.s32 d16, q8, #13
+0x70 0x09 0xf3 0xf2
+# CHECK: vqrshrn.s64 d16, q8, #13
+0x70 0x09 0xcc 0xf3
+# CHECK: vqrshrn.u16 d16, q8, #4
+0x70 0x09 0xd3 0xf3
+# CHECK: vqrshrn.u32 d16, q8, #13
+0x70 0x09 0xf3 0xf3
+# CHECK: vqrshrn.u64 d16, q8, #13
+
+
+0x30 0x11 0xc8 0xf2
+# CHECK: vsra.s8 d17, d16, #8
+0x30 0x11 0xd0 0xf2
+# CHECK: vsra.s16 d17, d16, #16
+0x30 0x11 0xe0 0xf2
+# CHECK: vsra.s32 d17, d16, #32
+0xb0 0x11 0xc0 0xf2
+# CHECK: vsra.s64 d17, d16, #64
+0x72 0x01 0xc8 0xf2
+# CHECK: vsra.s8 q8, q9, #8
+0x72 0x01 0xd0 0xf2
+# CHECK: vsra.s16 q8, q9, #16
+0x72 0x01 0xe0 0xf2
+# CHECK: vsra.s32 q8, q9, #32
+0xf2 0x01 0xc0 0xf2
+# CHECK: vsra.s64 q8, q9, #64
+0x30 0x11 0xc8 0xf3
+# CHECK: vsra.u8 d17, d16, #8
+0x30 0x11 0xd0 0xf3
+# CHECK: vsra.u16 d17, d16, #16
+0x30 0x11 0xe0 0xf3
+# CHECK: vsra.u32 d17, d16, #32
+0xb0 0x11 0xc0 0xf3
+# CHECK: vsra.u64 d17, d16, #64
+0x72 0x01 0xc8 0xf3
+# CHECK: vsra.u8 q8, q9, #8
+0x72 0x01 0xd0 0xf3
+# CHECK: vsra.u16 q8, q9, #16
+0x72 0x01 0xe0 0xf3
+# CHECK: vsra.u32 q8, q9, #32
+0xf2 0x01 0xc0 0xf3
+# CHECK: vsra.u64 q8, q9, #64
+0x30 0x13 0xc8 0xf2
+# CHECK: vrsra.s8 d17, d16, #8
+0x30 0x13 0xd0 0xf2
+# CHECK: vrsra.s16 d17, d16, #16
+0x30 0x13 0xe0 0xf2
+# CHECK: vrsra.s32 d17, d16, #32
+0xb0 0x13 0xc0 0xf2
+# CHECK: vrsra.s64 d17, d16, #64
+0x30 0x13 0xc8 0xf3
+# CHECK: vrsra.u8 d17, d16, #8
+0x30 0x13 0xd0 0xf3
+# CHECK: vrsra.u16 d17, d16, #16
+0x30 0x13 0xe0 0xf3
+# CHECK: vrsra.u32 d17, d16, #32
+0xb0 0x13 0xc0 0xf3
+# CHECK: vrsra.u64 d17, d16, #64
+0x72 0x03 0xc8 0xf2
+# CHECK: vrsra.s8 q8, q9, #8
+0x72 0x03 0xd0 0xf2
+# CHECK: vrsra.s16 q8, q9, #16
+0x72 0x03 0xe0 0xf2
+# CHECK: vrsra.s32 q8, q9, #32
+0xf2 0x03 0xc0 0xf2
+# CHECK: vrsra.s64 q8, q9, #64
+0x72 0x03 0xc8 0xf3
+# CHECK: vrsra.u8 q8, q9, #8
+0x72 0x03 0xd0 0xf3
+# CHECK: vrsra.u16 q8, q9, #16
+0x72 0x03 0xe0 0xf3
+# CHECK: vrsra.u32 q8, q9, #32
+0xf2 0x03 0xc0 0xf3
+# CHECK: vrsra.u64 q8, q9, #64
+0x30 0x15 0xcf 0xf3
+# CHECK: vsli.8 d17, d16, #7
+0x30 0x15 0xdf 0xf3
+# CHECK: vsli.16 d17, d16, #15
+0x30 0x15 0xff 0xf3
+# CHECK: vsli.32 d17, d16, #31
+0xb0 0x15 0xff 0xf3
+# CHECK: vsli.64 d17, d16, #63
+0x70 0x25 0xcf 0xf3
+# CHECK: vsli.8 q9, q8, #7
+0x70 0x25 0xdf 0xf3
+# CHECK: vsli.16 q9, q8, #15
+0x70 0x25 0xff 0xf3
+# CHECK: vsli.32 q9, q8, #31
+0xf0 0x25 0xff 0xf3
+# CHECK: vsli.64 q9, q8, #63
+0x30 0x14 0xc8 0xf3
+# CHECK: vsri.8 d17, d16, #8
+0x30 0x14 0xd0 0xf3
+# CHECK: vsri.16 d17, d16, #16
+0x30 0x14 0xe0 0xf3
+# CHECK: vsri.32 d17, d16, #32
+0xb0 0x14 0xc0 0xf3
+# CHECK: vsri.64 d17, d16, #64
+0x70 0x24 0xc8 0xf3
+# CHECK: vsri.8 q9, q8, #8
+0x70 0x24 0xd0 0xf3
+# CHECK: vsri.16 q9, q8, #16
+0x70 0x24 0xe0 0xf3
+# CHECK: vsri.32 q9, q8, #32
+0xf0 0x24 0xc0 0xf3
+# CHECK: vsri.64 q9, q8, #64
+
+
+0xa0 0x03 0xf1 0xf2
+# CHECK: vext.8 d16, d17, d16, #3
+0xa0 0x05 0xf1 0xf2
+# CHECK: vext.8 d16, d17, d16, #5
+0xe0 0x03 0xf2 0xf2
+# CHECK: vext.8 q8, q9, q8, #3
+0xe0 0x07 0xf2 0xf2
+# CHECK: vext.8 q8, q9, q8, #7
+0xa0 0x06 0xf1 0xf2
+# CHECK: vext.16 d16, d17, d16, #3
+0xe0 0x0c 0xf2 0xf2
+# CHECK: vext.32 q8, q9, q8, #3
+0xa0 0x10 0xf2 0xf3
+# CHECK: vtrn.8 d17, d16
+0xa0 0x10 0xf6 0xf3
+# CHECK: vtrn.16 d17, d16
+0xa0 0x10 0xfa 0xf3
+# CHECK: vtrn.32 d17, d16
+0xe0 0x20 0xf2 0xf3
+# CHECK: vtrn.8 q9, q8
+0xe0 0x20 0xf6 0xf3
+# CHECK: vtrn.16 q9, q8
+0xe0 0x20 0xfa 0xf3
+# CHECK: vtrn.32 q9, q8
+0x20 0x11 0xf2 0xf3
+# CHECK: vuzp.8 d17, d16
+0x20 0x11 0xf6 0xf3
+# CHECK: vuzp.16 d17, d16
+0x60 0x21 0xf2 0xf3
+# CHECK: vuzp.8 q9, q8
+0x60 0x21 0xf6 0xf3
+# CHECK: vuzp.16 q9, q8
+0x60 0x21 0xfa 0xf3
+# CHECK: vuzp.32 q9, q8
+0xa0 0x11 0xf2 0xf3
+# CHECK: vzip.8 d17, d16
+0xa0 0x11 0xf6 0xf3
+# CHECK: vzip.16 d17, d16
+0xe0 0x21 0xf2 0xf3
+# CHECK: vzip.8 q9, q8
+0xe0 0x21 0xf6 0xf3
+# CHECK: vzip.16 q9, q8
+0xe0 0x21 0xfa 0xf3
+# CHECK: vzip.32 q9, q8
+
+
+0xa0 0x08 0x41 0xf3
+# CHECK: vsub.i8 d16, d17, d16
+0xa0 0x08 0x51 0xf3
+# CHECK: vsub.i16 d16, d17, d16
+0xa0 0x08 0x61 0xf3
+# CHECK: vsub.i32 d16, d17, d16
+0xa0 0x08 0x71 0xf3
+# CHECK: vsub.i64 d16, d17, d16
+0xa1 0x0d 0x60 0xf2
+# CHECK: vsub.f32 d16, d16, d17
+0xe2 0x08 0x40 0xf3
+# CHECK: vsub.i8 q8, q8, q9
+0xe2 0x08 0x50 0xf3
+# CHECK: vsub.i16 q8, q8, q9
+0xe2 0x08 0x60 0xf3
+# CHECK: vsub.i32 q8, q8, q9
+0xe2 0x08 0x70 0xf3
+# CHECK: vsub.i64 q8, q8, q9
+0xe2 0x0d 0x60 0xf2
+# CHECK: vsub.f32 q8, q8, q9
+0xa0 0x02 0xc1 0xf2
+# CHECK: vsubl.s8 q8, d17, d16
+0xa0 0x02 0xd1 0xf2
+# CHECK: vsubl.s16 q8, d17, d16
+0xa0 0x02 0xe1 0xf2
+# CHECK: vsubl.s32 q8, d17, d16
+0xa0 0x02 0xc1 0xf3
+# CHECK: vsubl.u8 q8, d17, d16
+0xa0 0x02 0xd1 0xf3
+# CHECK: vsubl.u16 q8, d17, d16
+0xa0 0x02 0xe1 0xf3
+# CHECK: vsubl.u32 q8, d17, d16
+0xa2 0x03 0xc0 0xf2
+# CHECK: vsubw.s8 q8, q8, d18
+0xa2 0x03 0xd0 0xf2
+# CHECK: vsubw.s16 q8, q8, d18
+0xa2 0x03 0xe0 0xf2
+# CHECK: vsubw.s32 q8, q8, d18
+0xa2 0x03 0xc0 0xf3
+# CHECK: vsubw.u8 q8, q8, d18
+0xa2 0x03 0xd0 0xf3
+# CHECK: vsubw.u16 q8, q8, d18
+0xa2 0x03 0xe0 0xf3
+# CHECK: vsubw.u32 q8, q8, d18
+0xa1 0x02 0x40 0xf2
+# CHECK: vhsub.s8 d16, d16, d17
+0xa1 0x02 0x50 0xf2
+# CHECK: vhsub.s16 d16, d16, d17
+0xa1 0x02 0x60 0xf2
+# CHECK: vhsub.s32 d16, d16, d17
+0xa1 0x02 0x40 0xf3
+# CHECK: vhsub.u8 d16, d16, d17
+0xa1 0x02 0x50 0xf3
+# CHECK: vhsub.u16 d16, d16, d17
+0xa1 0x02 0x60 0xf3
+# CHECK: vhsub.u32 d16, d16, d17
+0xe2 0x02 0x40 0xf2
+# CHECK: vhsub.s8 q8, q8, q9
+0xe2 0x02 0x50 0xf2
+# CHECK: vhsub.s16 q8, q8, q9
+0xe2 0x02 0x60 0xf2
+# CHECK: vhsub.s32 q8, q8, q9
+0xb1 0x02 0x40 0xf2
+# CHECK: vqsub.s8 d16, d16, d17
+0xb1 0x02 0x50 0xf2
+# CHECK: vqsub.s16 d16, d16, d17
+0xb1 0x02 0x60 0xf2
+# CHECK: vqsub.s32 d16, d16, d17
+0xb1 0x02 0x70 0xf2
+# CHECK: vqsub.s64 d16, d16, d17
+0xb1 0x02 0x40 0xf3
+# CHECK: vqsub.u8 d16, d16, d17
+0xb1 0x02 0x50 0xf3
+# CHECK: vqsub.u16 d16, d16, d17
+0xb1 0x02 0x60 0xf3
+# CHECK: vqsub.u32 d16, d16, d17
+0xb1 0x02 0x70 0xf3
+# CHECK: vqsub.u64 d16, d16, d17
+0xf2 0x02 0x40 0xf2
+# CHECK: vqsub.s8 q8, q8, q9
+0xf2 0x02 0x50 0xf2
+# CHECK: vqsub.s16 q8, q8, q9
+0xf2 0x02 0x60 0xf2
+# CHECK: vqsub.s32 q8, q8, q9
+0xf2 0x02 0x70 0xf2
+# CHECK: vqsub.s64 q8, q8, q9
+0xf2 0x02 0x40 0xf3
+# CHECK: vqsub.u8 q8, q8, q9
+0xf2 0x02 0x50 0xf3
+# CHECK: vqsub.u16 q8, q8, q9
+0xf2 0x02 0x60 0xf3
+# CHECK: vqsub.u32 q8, q8, q9
+0xf2 0x02 0x70 0xf3
+# CHECK: vqsub.u64 q8, q8, q9
+0xa2 0x06 0xc0 0xf2
+# CHECK: vsubhn.i16 d16, q8, q9
+0xa2 0x06 0xd0 0xf2
+# CHECK: vsubhn.i32 d16, q8, q9
+0xa2 0x06 0xe0 0xf2
+# CHECK: vsubhn.i64 d16, q8, q9
+0xa2 0x06 0xc0 0xf3
+# CHECK: vrsubhn.i16 d16, q8, q9
+0xa2 0x06 0xd0 0xf3
+# CHECK: vrsubhn.i32 d16, q8, q9
+0xa2 0x06 0xe0 0xf3
+# CHECK: vrsubhn.i64 d16, q8, q9
+
+
+
+0xa0 0x08 0xf1 0xf3
+# CHECK: vtbl.8 d16, {d17}, d16
+0xa2 0x09 0xf0 0xf3
+# CHECK: vtbl.8 d16, {d16, d17}, d18
+0xa4 0x0a 0xf0 0xf3
+# CHECK: vtbl.8 d16, {d16, d17, d18}, d20
+0xa4 0x0b 0xf0 0xf3
+# CHECK: vtbl.8 d16, {d16, d17, d18, d19}, d20
+0xe1 0x28 0xf0 0xf3
+# CHECK: vtbx.8 d18, {d16}, d17
+0xe2 0x39 0xf0 0xf3
+# CHECK: vtbx.8 d19, {d16, d17}, d18
+0xe5 0x4a 0xf0 0xf3
+# CHECK: vtbx.8 d20, {d16, d17, d18}, d21
+0xe5 0x4b 0xf0 0xf3
+# CHECK: vtbx.8 d20, {d16, d17, d18, d19}, d21
+
+
+
+0x1f 0x07 0x60 0xf4
+# CHECK: vld1.8 {d16}, [r0, :64]
+0x4f 0x07 0x60 0xf4
+# CHECK: vld1.16 {d16}, [r0]
+0x8f 0x07 0x60 0xf4
+# CHECK: vld1.32 {d16}, [r0]
+0xcf 0x07 0x60 0xf4
+# CHECK: vld1.64 {d16}, [r0]
+0x1f 0x0a 0x60 0xf4
+# CHECK: vld1.8 {d16, d17}, [r0, :64]
+0x6f 0x0a 0x60 0xf4
+# CHECK: vld1.16 {d16, d17}, [r0, :128]
+0x8f 0x0a 0x60 0xf4
+# CHECK: vld1.32 {d16, d17}, [r0]
+0xcf 0x0a 0x60 0xf4
+# CHECK: vld1.64 {d16, d17}, [r0]
+
+0x1f 0x08 0x60 0xf4
+# CHECK: vld2.8 {d16, d17}, [r0, :64]
+0x6f 0x08 0x60 0xf4
+# CHECK: vld2.16 {d16, d17}, [r0, :128]
+0x8f 0x08 0x60 0xf4
+# CHECK: vld2.32 {d16, d17}, [r0]
+0x1f 0x03 0x60 0xf4
+# CHECK: vld2.8 {d16, d17, d18, d19}, [r0, :64]
+0x6f 0x03 0x60 0xf4
+# CHECK: vld2.16 {d16, d17, d18, d19}, [r0, :128]
+0xbf 0x03 0x60 0xf4
+# CHECK: vld2.32 {d16, d17, d18, d19}, [r0, :256]
+
+0x1f 0x04 0x60 0xf4
+# CHECK: vld3.8 {d16, d17, d18}, [r0, :64]
+0x4f 0x04 0x60 0xf4
+# CHECK: vld3.16 {d16, d17, d18}, [r0]
+0x8f 0x04 0x60 0xf4
+# CHECK: vld3.32 {d16, d17, d18}, [r0]
+0x1d 0x05 0x60 0xf4
+# CHECK: vld3.8 {d16, d18, d20}, [r0, :64]!
+0x1d 0x15 0x60 0xf4
+# CHECK: vld3.8 {d17, d19, d21}, [r0, :64]!
+0x4d 0x05 0x60 0xf4
+# CHECK: vld3.16 {d16, d18, d20}, [r0]!
+0x4d 0x15 0x60 0xf4
+# CHECK: vld3.16 {d17, d19, d21}, [r0]!
+0x8d 0x05 0x60 0xf4
+# CHECK: vld3.32 {d16, d18, d20}, [r0]!
+0x8d 0x15 0x60 0xf4
+# CHECK: vld3.32 {d17, d19, d21}, [r0]!
+
+0x1f 0x00 0x60 0xf4
+# CHECK: vld4.8 {d16, d17, d18, d19}, [r0, :64]
+0x6f 0x00 0x60 0xf4
+# CHECK: vld4.16 {d16, d17, d18, d19}, [r0, :128]
+0xbf 0x00 0x60 0xf4
+# CHECK: vld4.32 {d16, d17, d18, d19}, [r0, :256]
+0x3d 0x01 0x60 0xf4
+# CHECK: vld4.8 {d16, d18, d20, d22}, [r0, :256]!
+0x3d 0x11 0x60 0xf4
+# CHECK: vld4.8 {d17, d19, d21, d23}, [r0, :256]!
+0x4d 0x01 0x60 0xf4
+# CHECK: vld4.16 {d16, d18, d20, d22}, [r0]!
+0x4d 0x11 0x60 0xf4
+# CHECK: vld4.16 {d17, d19, d21, d23}, [r0]!
+0x8d 0x01 0x60 0xf4
+# CHECK: vld4.32 {d16, d18, d20, d22}, [r0]!
+0x8d 0x11 0x60 0xf4
+# CHECK: vld4.32 {d17, d19, d21, d23}, [r0]!
+
+0x6f 0x00 0xe0 0xf4
+# CHECK: vld1.8 {d16[3]}, [r0]
+0x9f 0x04 0xe0 0xf4
+# CHECK: vld1.16 {d16[2]}, [r0, :16]
+0xbf 0x08 0xe0 0xf4
+# CHECK: vld1.32 {d16[1]}, [r0, :32]
+
+0x3f 0x01 0xe0 0xf4
+# CHECK: vld2.8 {d16[1], d17[1]}, [r0, :16]
+0x5f 0x05 0xe0 0xf4
+# CHECK: vld2.16 {d16[1], d17[1]}, [r0, :32]
+0x8f 0x09 0xe0 0xf4
+# CHECK: vld2.32 {d16[1], d17[1]}, [r0]
+0x6f 0x15 0xe0 0xf4
+# CHECK: vld2.16 {d17[1], d19[1]}, [r0]
+0x5f 0x19 0xe0 0xf4
+# CHECK: vld2.32 {d17[0], d19[0]}, [r0, :64]
+
+0x2f 0x02 0xe0 0xf4
+# CHECK: vld3.8 {d16[1], d17[1], d18[1]}, [r0]
+0x4f 0x06 0xe0 0xf4
+# CHECK: vld3.16 {d16[1], d17[1], d18[1]}, [r0]
+0x8f 0x0a 0xe0 0xf4
+# CHECK: vld3.32 {d16[1], d17[1], d18[1]}, [r0]
+0x6f 0x06 0xe0 0xf4
+# CHECK: vld3.16 {d16[1], d18[1], d20[1]}, [r0]
+0xcf 0x1a 0xe0 0xf4
+# CHECK: vld3.32 {d17[1], d19[1], d21[1]}, [r0]
+
+0x3f 0x03 0xe0 0xf4
+# CHECK: vld4.8 {d16[1], d17[1], d18[1], d19[1]}, [r0, :32]
+0x4f 0x07 0xe0 0xf4
+# CHECK: vld4.16 {d16[1], d17[1], d18[1], d19[1]}, [r0]
+0xaf 0x0b 0xe0 0xf4
+# CHECK: vld4.32 {d16[1], d17[1], d18[1], d19[1]}, [r0, :128]
+0x7f 0x07 0xe0 0xf4
+# CHECK: vld4.16 {d16[1], d18[1], d20[1], d22[1]}, [r0, :64]
+0x4f 0x1b 0xe0 0xf4
+# CHECK: vld4.32 {d17[0], d19[0], d21[0], d23[0]}, [r0]
+
+
+
+0x1f 0x07 0x40 0xf4
+# CHECK: vst1.8 {d16}, [r0, :64]
+0x4f 0x07 0x40 0xf4
+# CHECK: vst1.16 {d16}, [r0]
+0x8f 0x07 0x40 0xf4
+# CHECK: vst1.32 {d16}, [r0]
+0xcf 0x07 0x40 0xf4
+# CHECK: vst1.64 {d16}, [r0]
+0x1f 0x0a 0x40 0xf4
+# CHECK: vst1.8 {d16, d17}, [r0, :64]
+0x6f 0x0a 0x40 0xf4
+# CHECK: vst1.16 {d16, d17}, [r0, :128]
+0x8f 0x0a 0x40 0xf4
+# CHECK: vst1.32 {d16, d17}, [r0]
+0xcf 0x0a 0x40 0xf4
+# CHECK: vst1.64 {d16, d17}, [r0]
+
+0x1f 0x08 0x40 0xf4
+# CHECK: vst2.8 {d16, d17}, [r0, :64]
+0x6f 0x08 0x40 0xf4
+# CHECK: vst2.16 {d16, d17}, [r0, :128]
+0x8f 0x08 0x40 0xf4
+# CHECK: vst2.32 {d16, d17}, [r0]
+0x1f 0x03 0x40 0xf4
+# CHECK: vst2.8 {d16, d17, d18, d19}, [r0, :64]
+0x6f 0x03 0x40 0xf4
+# CHECK: vst2.16 {d16, d17, d18, d19}, [r0, :128]
+0xbf 0x03 0x40 0xf4
+# CHECK: vst2.32 {d16, d17, d18, d19}, [r0, :256]
+
+0x1f 0x04 0x40 0xf4
+# CHECK: vst3.8 {d16, d17, d18}, [r0, :64]
+0x4f 0x04 0x40 0xf4
+# CHECK: vst3.16 {d16, d17, d18}, [r0]
+0x8f 0x04 0x40 0xf4
+# CHECK: vst3.32 {d16, d17, d18}, [r0]
+0x1d 0x05 0x40 0xf4
+# CHECK: vst3.8 {d16, d18, d20}, [r0, :64]!
+0x1d 0x15 0x40 0xf4
+# CHECK: vst3.8 {d17, d19, d21}, [r0, :64]!
+0x4d 0x05 0x40 0xf4
+# CHECK: vst3.16 {d16, d18, d20}, [r0]!
+0x4d 0x15 0x40 0xf4
+# CHECK: vst3.16 {d17, d19, d21}, [r0]!
+0x8d 0x05 0x40 0xf4
+# CHECK: vst3.32 {d16, d18, d20}, [r0]!
+0x8d 0x15 0x40 0xf4
+# CHECK: vst3.32 {d17, d19, d21}, [r0]!
+
+0x1f 0x00 0x40 0xf4
+# CHECK: vst4.8 {d16, d17, d18, d19}, [r0, :64]
+0x6f 0x00 0x40 0xf4
+# CHECK: vst4.16 {d16, d17, d18, d19}, [r0, :128]
+0x3d 0x01 0x40 0xf4
+# CHECK: vst4.8 {d16, d18, d20, d22}, [r0, :256]!
+0x3d 0x11 0x40 0xf4
+# CHECK: vst4.8 {d17, d19, d21, d23}, [r0, :256]!
+0x4d 0x01 0x40 0xf4
+# CHECK: vst4.16 {d16, d18, d20, d22}, [r0]!
+0x4d 0x11 0x40 0xf4
+# CHECK: vst4.16 {d17, d19, d21, d23}, [r0]!
+0x8d 0x01 0x40 0xf4
+# CHECK: vst4.32 {d16, d18, d20, d22}, [r0]!
+0x8d 0x11 0x40 0xf4
+# CHECK: vst4.32 {d17, d19, d21, d23}, [r0]!
+
+0x3f 0x01 0xc0 0xf4
+# CHECK: vst2.8 {d16[1], d17[1]}, [r0, :16]
+0x5f 0x05 0xc0 0xf4
+# CHECK: vst2.16 {d16[1], d17[1]}, [r0, :32]
+0x8f 0x09 0xc0 0xf4
+# CHECK: vst2.32 {d16[1], d17[1]}, [r0]
+0x6f 0x15 0xc0 0xf4
+# CHECK: vst2.16 {d17[1], d19[1]}, [r0]
+0x5f 0x19 0xc0 0xf4
+# CHECK: vst2.32 {d17[0], d19[0]}, [r0, :64]
+
+0x2f 0x02 0xc0 0xf4
+# CHECK: vst3.8 {d16[1], d17[1], d18[1]}, [r0]
+0x4f 0x06 0xc0 0xf4
+# CHECK: vst3.16 {d16[1], d17[1], d18[1]}, [r0]
+0x8f 0x0a 0xc0 0xf4
+# CHECK: vst3.32 {d16[1], d17[1], d18[1]}, [r0]
+0xaf 0x16 0xc0 0xf4
+# CHECK: vst3.16 {d17[2], d19[2], d21[2]}, [r0]
+0x4f 0x0a 0xc0 0xf4
+# CHECK: vst3.32 {d16[0], d18[0], d20[0]}, [r0]
+
+0x3f 0x03 0xc0 0xf4
+# CHECK: vst4.8 {d16[1], d17[1], d18[1], d19[1]}, [r0, :32]
+0x4f 0x07 0xc0 0xf4
+# CHECK: vst4.16 {d16[1], d17[1], d18[1], d19[1]}, [r0]
+0xaf 0x0b 0xc0 0xf4
+# CHECK: vst4.32 {d16[1], d17[1], d18[1], d19[1]}, [r0, :128]
+0xff 0x17 0xc0 0xf4
+# CHECK: vst4.16 {d17[3], d19[3], d21[3], d23[3]}, [r0, :64]
+0x4f 0x1b 0xc0 0xf4
+# CHECK: vst4.32 {d17[0], d19[0], d21[0], d23[0]}, [r0]
+
+0x0 0xc 0xa0 0xf4
+# CHECK: vld1.8 {d0[]}, [r0], r0
+0x0d 0x03 0x80 0xf4
+# CHECK: vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
+
+0x3d 0x2a 0x5e 0x6c
+# CHECK: vmovvs r2, lr, s29, s30
+
+0xe9 0x1a 0xb2 0x4e
+# CHECK: vcvttmi.f32.f16 s2, s19
diff --git a/test/MC/Disassembler/ARM/neont2.txt b/test/MC/Disassembler/ARM/neont2.txt
new file mode 100644
index 0000000..577703c
--- /dev/null
+++ b/test/MC/Disassembler/ARM/neont2.txt
@@ -0,0 +1,1586 @@
+# RUN: llvm-mc -triple thumbv7-unknown-unknown -disassemble -mattr +fp16 < %s | FileCheck %s
+
+0xf1 0xff 0x20 0x03
+# CHECK: vabs.s8 d16, d16
+0xf5 0xff 0x20 0x03
+# CHECK: vabs.s16 d16, d16
+0xf9 0xff 0x20 0x03
+# CHECK: vabs.s32 d16, d16
+0xf9 0xff 0x20 0x07
+# CHECK: vabs.f32 d16, d16
+0xf1 0xff 0x60 0x03
+# CHECK: vabs.s8 q8, q8
+0xf5 0xff 0x60 0x03
+# CHECK: vabs.s16 q8, q8
+0xf9 0xff 0x60 0x03
+# CHECK: vabs.s32 q8, q8
+0xf9 0xff 0x60 0x07
+# CHECK: vabs.f32 q8, q8
+
+0xf0 0xff 0x20 0x07
+# CHECK: vqabs.s8 d16, d16
+0xf4 0xff 0x20 0x07
+# CHECK: vqabs.s16 d16, d16
+0xf8 0xff 0x20 0x07
+# CHECK: vqabs.s32 d16, d16
+0xf0 0xff 0x60 0x07
+# CHECK: vqabs.s8 q8, q8
+0xf4 0xff 0x60 0x07
+# CHECK: vqabs.s16 q8, q8
+0xf8 0xff 0x60 0x07
+# CHECK: vqabs.s32 q8, q8
+
+0x40 0xef 0xa1 0x07
+# CHECK: vabd.s8 d16, d16, d17
+0x50 0xef 0xa1 0x07
+# CHECK: vabd.s16 d16, d16, d17
+0x60 0xef 0xa1 0x07
+# CHECK: vabd.s32 d16, d16, d17
+0x40 0xff 0xa1 0x07
+# CHECK: vabd.u8 d16, d16, d17
+0x50 0xff 0xa1 0x07
+# CHECK: vabd.u16 d16, d16, d17
+0x60 0xff 0xa1 0x07
+# CHECK: vabd.u32 d16, d16, d17
+0x60 0xff 0xa1 0x0d
+# CHECK: vabd.f32 d16, d16, d17
+0x40 0xef 0xe2 0x07
+# CHECK: vabd.s8 q8, q8, q9
+0x50 0xef 0xe2 0x07
+# CHECK: vabd.s16 q8, q8, q9
+0x60 0xef 0xe2 0x07
+# CHECK: vabd.s32 q8, q8, q9
+0x40 0xff 0xe2 0x07
+# CHECK: vabd.u8 q8, q8, q9
+0x50 0xff 0xe2 0x07
+# CHECK: vabd.u16 q8, q8, q9
+0x60 0xff 0xe2 0x07
+# CHECK: vabd.u32 q8, q8, q9
+0x60 0xff 0xe2 0x0d
+# CHECK: vabd.f32 q8, q8, q9
+
+0xc0 0xef 0xa1 0x07
+# CHECK: vabdl.s8 q8, d16, d17
+0xd0 0xef 0xa1 0x07
+# CHECK: vabdl.s16 q8, d16, d17
+0xe0 0xef 0xa1 0x07
+# CHECK: vabdl.s32 q8, d16, d17
+0xc0 0xff 0xa1 0x07
+# CHECK: vabdl.u8 q8, d16, d17
+0xd0 0xff 0xa1 0x07
+# CHECK: vabdl.u16 q8, d16, d17
+0xe0 0xff 0xa1 0x07
+# CHECK: vabdl.u32 q8, d16, d17
+
+0x42 0xef 0xb1 0x07
+# CHECK: vaba.s8 d16, d18, d17
+0x52 0xef 0xb1 0x07
+# CHECK: vaba.s16 d16, d18, d17
+0x62 0xef 0xb1 0x07
+# CHECK: vaba.s32 d16, d18, d17
+0x42 0xff 0xb1 0x07
+# CHECK: vaba.u8 d16, d18, d17
+0x52 0xff 0xb1 0x07
+# CHECK: vaba.u16 d16, d18, d17
+0x62 0xff 0xb1 0x07
+# CHECK: vaba.u32 d16, d18, d17
+0x40 0xef 0xf4 0x27
+# CHECK: vaba.s8 q9, q8, q10
+0x50 0xef 0xf4 0x27
+# CHECK: vaba.s16 q9, q8, q10
+0x60 0xef 0xf4 0x27
+# CHECK: vaba.s32 q9, q8, q10
+0x40 0xff 0xf4 0x27
+# CHECK: vaba.u8 q9, q8, q10
+0x50 0xff 0xf4 0x27
+# CHECK: vaba.u16 q9, q8, q10
+0x60 0xff 0xf4 0x27
+# CHECK: vaba.u32 q9, q8, q10
+
+0xc3 0xef 0xa2 0x05
+# CHECK: vabal.s8 q8, d19, d18
+0xd3 0xef 0xa2 0x05
+# CHECK: vabal.s16 q8, d19, d18
+0xe3 0xef 0xa2 0x05
+# CHECK: vabal.s32 q8, d19, d18
+0xc3 0xff 0xa2 0x05
+# CHECK: vabal.u8 q8, d19, d18
+0xd3 0xff 0xa2 0x05
+# CHECK: vabal.u16 q8, d19, d18
+0xe3 0xff 0xa2 0x05
+# CHECK: vabal.u32 q8, d19, d18
+
+0x41 0xef 0xa0 0x08
+# CHECK: vadd.i8 d16, d17, d16
+0x51 0xef 0xa0 0x08
+# CHECK: vadd.i16 d16, d17, d16
+0x71 0xef 0xa0 0x08
+# CHECK: vadd.i64 d16, d17, d16
+0x61 0xef 0xa0 0x08
+# CHECK: vadd.i32 d16, d17, d16
+0x40 0xef 0xa1 0x0d
+# CHECK: vadd.f32 d16, d16, d17
+0x40 0xef 0xe2 0x0d
+# CHECK: vadd.f32 q8, q8, q9
+
+0xc1 0xef 0xa0 0x00
+# CHECK: vaddl.s8 q8, d17, d16
+0xd1 0xef 0xa0 0x00
+# CHECK: vaddl.s16 q8, d17, d16
+0xe1 0xef 0xa0 0x00
+# CHECK: vaddl.s32 q8, d17, d16
+0xc1 0xff 0xa0 0x00
+# CHECK: vaddl.u8 q8, d17, d16
+0xd1 0xff 0xa0 0x00
+# CHECK: vaddl.u16 q8, d17, d16
+0xe1 0xff 0xa0 0x00
+# CHECK: vaddl.u32 q8, d17, d16
+
+0xc0 0xef 0xa2 0x01
+# CHECK: vaddw.s8 q8, q8, d18
+0xd0 0xef 0xa2 0x01
+# CHECK: vaddw.s16 q8, q8, d18
+0xe0 0xef 0xa2 0x01
+# CHECK: vaddw.s32 q8, q8, d18
+0xc0 0xff 0xa2 0x01
+# CHECK: vaddw.u8 q8, q8, d18
+0xd0 0xff 0xa2 0x01
+# CHECK: vaddw.u16 q8, q8, d18
+0xe0 0xff 0xa2 0x01
+# CHECK: vaddw.u32 q8, q8, d18
+
+0x40 0xef 0xa1 0x00
+# CHECK: vhadd.s8 d16, d16, d17
+0x50 0xef 0xa1 0x00
+# CHECK: vhadd.s16 d16, d16, d17
+0x60 0xef 0xa1 0x00
+# CHECK: vhadd.s32 d16, d16, d17
+0x40 0xff 0xa1 0x00
+# CHECK: vhadd.u8 d16, d16, d17
+0x50 0xff 0xa1 0x00
+# CHECK: vhadd.u16 d16, d16, d17
+0x60 0xff 0xa1 0x00
+# CHECK: vhadd.u32 d16, d16, d17
+0x40 0xef 0xe2 0x00
+# CHECK: vhadd.s8 q8, q8, q9
+0x50 0xef 0xe2 0x00
+# CHECK: vhadd.s16 q8, q8, q9
+0x60 0xef 0xe2 0x00
+# CHECK: vhadd.s32 q8, q8, q9
+0x40 0xff 0xe2 0x00
+# CHECK: vhadd.u8 q8, q8, q9
+0x50 0xff 0xe2 0x00
+# CHECK: vhadd.u16 q8, q8, q9
+0x60 0xff 0xe2 0x00
+# CHECK: vhadd.u32 q8, q8, q9
+
+0x40 0xef 0xa1 0x01
+# CHECK: vrhadd.s8 d16, d16, d17
+0x50 0xef 0xa1 0x01
+# CHECK: vrhadd.s16 d16, d16, d17
+0x60 0xef 0xa1 0x01
+# CHECK: vrhadd.s32 d16, d16, d17
+0x40 0xff 0xa1 0x01
+# CHECK: vrhadd.u8 d16, d16, d17
+0x50 0xff 0xa1 0x01
+# CHECK: vrhadd.u16 d16, d16, d17
+0x60 0xff 0xa1 0x01
+# CHECK: vrhadd.u32 d16, d16, d17
+0x40 0xef 0xe2 0x01
+# CHECK: vrhadd.s8 q8, q8, q9
+0x50 0xef 0xe2 0x01
+# CHECK: vrhadd.s16 q8, q8, q9
+0x60 0xef 0xe2 0x01
+# CHECK: vrhadd.s32 q8, q8, q9
+0x40 0xff 0xe2 0x01
+# CHECK: vrhadd.u8 q8, q8, q9
+0x50 0xff 0xe2 0x01
+# CHECK: vrhadd.u16 q8, q8, q9
+0x60 0xff 0xe2 0x01
+# CHECK: vrhadd.u32 q8, q8, q9
+
+0x40 0xef 0xb1 0x00
+# CHECK: vqadd.s8 d16, d16, d17
+0x50 0xef 0xb1 0x00
+# CHECK: vqadd.s16 d16, d16, d17
+0x60 0xef 0xb1 0x00
+# CHECK: vqadd.s32 d16, d16, d17
+0x70 0xef 0xb1 0x00
+# CHECK: vqadd.s64 d16, d16, d17
+0x40 0xff 0xb1 0x00
+# CHECK: vqadd.u8 d16, d16, d17
+0x50 0xff 0xb1 0x00
+# CHECK: vqadd.u16 d16, d16, d17
+0x60 0xff 0xb1 0x00
+# CHECK: vqadd.u32 d16, d16, d17
+0x70 0xff 0xb1 0x00
+# CHECK: vqadd.u64 d16, d16, d17
+0x40 0xef 0xf2 0x00
+# CHECK: vqadd.s8 q8, q8, q9
+0x50 0xef 0xf2 0x00
+# CHECK: vqadd.s16 q8, q8, q9
+0x60 0xef 0xf2 0x00
+# CHECK: vqadd.s32 q8, q8, q9
+0x70 0xef 0xf2 0x00
+# CHECK: vqadd.s64 q8, q8, q9
+0x40 0xff 0xf2 0x00
+# CHECK: vqadd.u8 q8, q8, q9
+0x50 0xff 0xf2 0x00
+# CHECK: vqadd.u16 q8, q8, q9
+0x60 0xff 0xf2 0x00
+# CHECK: vqadd.u32 q8, q8, q9
+0x70 0xff 0xf2 0x00
+# CHECK: vqadd.u64 q8, q8, q9
+
+0xc0 0xef 0xa2 0x04
+# CHECK: vaddhn.i16 d16, q8, q9
+0xd0 0xef 0xa2 0x04
+# CHECK: vaddhn.i32 d16, q8, q9
+0xe0 0xef 0xa2 0x04
+# CHECK: vaddhn.i64 d16, q8, q9
+0xc0 0xff 0xa2 0x04
+# CHECK: vraddhn.i16 d16, q8, q9
+0xd0 0xff 0xa2 0x04
+# CHECK: vraddhn.i32 d16, q8, q9
+0xe0 0xff 0xa2 0x04
+# CHECK: vraddhn.i64 d16, q8, q9
+
+0xf0 0xff 0x20 0x05
+# CHECK: vcnt.8 d16, d16
+0xf0 0xff 0x60 0x05
+# CHECK: vcnt.8 q8, q8
+0xf0 0xff 0xa0 0x04
+# CHECK: vclz.i8 d16, d16
+0xf4 0xff 0xa0 0x04
+# CHECK: vclz.i16 d16, d16
+0xf8 0xff 0xa0 0x04
+# CHECK: vclz.i32 d16, d16
+0xf0 0xff 0xe0 0x04
+# CHECK: vclz.i8 q8, q8
+0xf4 0xff 0xe0 0x04
+# CHECK: vclz.i16 q8, q8
+0xf8 0xff 0xe0 0x04
+# CHECK: vclz.i32 q8, q8
+0xf0 0xff 0x20 0x04
+# CHECK: vcls.s8 d16, d16
+0xf4 0xff 0x20 0x04
+# CHECK: vcls.s16 d16, d16
+0xf8 0xff 0x20 0x04
+# CHECK: vcls.s32 d16, d16
+0xf0 0xff 0x60 0x04
+# CHECK: vcls.s8 q8, q8
+0xf4 0xff 0x60 0x04
+# CHECK: vcls.s16 q8, q8
+0xf8 0xff 0x60 0x04
+# CHECK: vcls.s32 q8, q8
+
+
+0x41 0xef 0xb0 0x01
+# CHECK: vand d16, d17, d16
+0x40 0xef 0xf2 0x01
+# CHECK: vand q8, q8, q9
+
+0x41 0xff 0xb0 0x01
+# CHECK: veor d16, d17, d16
+0x40 0xff 0xf2 0x01
+# CHECK: veor q8, q8, q9
+
+0x61 0xef 0xb0 0x01
+# CHECK: vorr d16, d17, d16
+0x60 0xef 0xf2 0x01
+# CHECK: vorr q8, q8, q9
+0xc0 0xef 0x11 0x07
+# CHECK: vorr.i32 d16, #0x1000000
+0xc0 0xef 0x51 0x07
+# CHECK: vorr.i32 q8, #0x1000000
+0xc0 0xef 0x50 0x01
+# CHECK: vorr.i32 q8, #0x0
+
+0x51 0xef 0xb0 0x01
+# CHECK: vbic d16, d17, d16
+0x50 0xef 0xf2 0x01
+# CHECK: vbic q8, q8, q9
+0xc7 0xff 0x3f 0x07
+# CHECK: vbic.i32 d16, #0xFF000000
+0xc7 0xff 0x7f 0x07
+# CHECK: vbic.i32 q8, #0xFF000000
+
+0x71 0xef 0xb0 0x01
+# CHECK: vorn d16, d17, d16
+0x70 0xef 0xf2 0x01
+# CHECK: vorn q8, q8, q9
+
+0xf0 0xff 0xa0 0x05
+# CHECK: vmvn d16, d16
+0xf0 0xff 0xe0 0x05
+# CHECK: vmvn q8, q8
+
+0x51 0xff 0xb0 0x21
+# CHECK: vbsl d18, d17, d16
+0x54 0xff 0xf2 0x01
+# CHECK: vbsl q8, q10, q9
+
+0xfb 0xff 0x20 0x07
+# CHECK: vcvt.s32.f32 d16, d16
+0xfb 0xff 0xa0 0x07
+# CHECK: vcvt.u32.f32 d16, d16
+0xfb 0xff 0x20 0x06
+# CHECK: vcvt.f32.s32 d16, d16
+0xfb 0xff 0xa0 0x06
+# CHECK: vcvt.f32.u32 d16, d16
+0xfb 0xff 0x60 0x07
+# CHECK: vcvt.s32.f32 q8, q8
+0xfb 0xff 0xe0 0x07
+# CHECK: vcvt.u32.f32 q8, q8
+0xfb 0xff 0x60 0x06
+# CHECK: vcvt.f32.s32 q8, q8
+0xfb 0xff 0xe0 0x06
+# CHECK: vcvt.f32.u32 q8, q8
+0xff 0xef 0x30 0x0f
+# CHECK: vcvt.s32.f32 d16, d16, #1
+0xff 0xff 0x30 0x0f
+# CHECK: vcvt.u32.f32 d16, d16, #1
+0xff 0xef 0x30 0x0e
+# CHECK: vcvt.f32.s32 d16, d16, #1
+0xff 0xff 0x30 0x0e
+# CHECK: vcvt.f32.u32 d16, d16, #1
+0xff 0xef 0x70 0x0f
+# CHECK: vcvt.s32.f32 q8, q8, #1
+0xff 0xff 0x70 0x0f
+# CHECK: vcvt.u32.f32 q8, q8, #1
+0xff 0xef 0x70 0x0e
+# CHECK: vcvt.f32.s32 q8, q8, #1
+0xff 0xff 0x70 0x0e
+# CHECK: vcvt.f32.u32 q8, q8, #1
+0xfb 0xff 0x20 0x07
+# CHECK: vcvt.s32.f32 d16, d16
+0xfb 0xff 0xa0 0x07
+# CHECK: vcvt.u32.f32 d16, d16
+0xfb 0xff 0x20 0x06
+# CHECK: vcvt.f32.s32 d16, d16
+0xfb 0xff 0xa0 0x06
+# CHECK: vcvt.f32.u32 d16, d16
+0xfb 0xff 0x60 0x07
+# CHECK: vcvt.s32.f32 q8, q8
+0xfb 0xff 0xe0 0x07
+# CHECK: vcvt.u32.f32 q8, q8
+0xfb 0xff 0x60 0x06
+# CHECK: vcvt.f32.s32 q8, q8
+0xfb 0xff 0xe0 0x06
+# CHECK: vcvt.f32.u32 q8, q8
+0xff 0xef 0x30 0x0f
+# CHECK: vcvt.s32.f32 d16, d16, #1
+0xff 0xff 0x30 0x0f
+# CHECK: vcvt.u32.f32 d16, d16, #1
+0xff 0xef 0x30 0x0e
+# CHECK: vcvt.f32.s32 d16, d16, #1
+0xff 0xff 0x30 0x0e
+# CHECK: vcvt.f32.u32 d16, d16, #1
+0xff 0xef 0x70 0x0f
+# CHECK: vcvt.s32.f32 q8, q8, #1
+0xff 0xff 0x70 0x0f
+# CHECK: vcvt.u32.f32 q8, q8, #1
+0xff 0xef 0x70 0x0e
+# CHECK: vcvt.f32.s32 q8, q8, #1
+0xff 0xff 0x70 0x0e
+# CHECK: vcvt.f32.u32 q8, q8, #1
+0xf6 0xff 0x20 0x07
+# CHECK: vcvt.f32.f16 q8, d16
+0xf6 0xff 0x20 0x06
+# CHECK: vcvt.f16.f32 d16, q8
+
+0xc0 0xee 0x90 0x0b
+# CHECK: vdup.8 d16, r0
+0x80 0xee 0xb0 0x0b
+# CHECK: vdup.16 d16, r0
+0x80 0xee 0x90 0x0b
+# CHECK: vdup.32 d16, r0
+0xe0 0xee 0x90 0x0b
+# CHECK: vdup.8 q8, r0
+0xa0 0xee 0xb0 0x0b
+# CHECK: vdup.16 q8, r0
+0xa0 0xee 0x90 0x0b
+# CHECK: vdup.32 q8, r0
+0xf3 0xff 0x20 0x0c
+# CHECK: vdup.8 d16, d16[1]
+0xf6 0xff 0x20 0x0c
+# CHECK: vdup.16 d16, d16[1]
+0xfc 0xff 0x20 0x0c
+# CHECK: vdup.32 d16, d16[1]
+0xf3 0xff 0x60 0x0c
+# CHECK: vdup.8 q8, d16[1]
+0xf6 0xff 0x60 0x0c
+# CHECK: vdup.16 q8, d16[1]
+0xfc 0xff 0x60 0x0c
+# CHECK: vdup.32 q8, d16[1]
+
+0x40 0xef 0xb1 0x06
+# CHECK: vmin.s8 d16, d16, d17
+0x50 0xef 0xb1 0x06
+# CHECK: vmin.s16 d16, d16, d17
+0x60 0xef 0xb1 0x06
+# CHECK: vmin.s32 d16, d16, d17
+0x40 0xff 0xb1 0x06
+# CHECK: vmin.u8 d16, d16, d17
+0x50 0xff 0xb1 0x06
+# CHECK: vmin.u16 d16, d16, d17
+0x60 0xff 0xb1 0x06
+# CHECK: vmin.u32 d16, d16, d17
+0x60 0xef 0xa1 0x0f
+# CHECK: vmin.f32 d16, d16, d17
+0x40 0xef 0xf2 0x06
+# CHECK: vmin.s8 q8, q8, q9
+0x50 0xef 0xf2 0x06
+# CHECK: vmin.s16 q8, q8, q9
+0x60 0xef 0xf2 0x06
+# CHECK: vmin.s32 q8, q8, q9
+0x40 0xff 0xf2 0x06
+# CHECK: vmin.u8 q8, q8, q9
+0x50 0xff 0xf2 0x06
+# CHECK: vmin.u16 q8, q8, q9
+0x60 0xff 0xf2 0x06
+# CHECK: vmin.u32 q8, q8, q9
+0x60 0xef 0xe2 0x0f
+# CHECK: vmin.f32 q8, q8, q9
+0x40 0xef 0xa1 0x06
+# CHECK: vmax.s8 d16, d16, d17
+0x50 0xef 0xa1 0x06
+# CHECK: vmax.s16 d16, d16, d17
+0x60 0xef 0xa1 0x06
+# CHECK: vmax.s32 d16, d16, d17
+0x40 0xff 0xa1 0x06
+# CHECK: vmax.u8 d16, d16, d17
+0x50 0xff 0xa1 0x06
+# CHECK: vmax.u16 d16, d16, d17
+0x60 0xff 0xa1 0x06
+# CHECK: vmax.u32 d16, d16, d17
+0x40 0xef 0xa1 0x0f
+# CHECK: vmax.f32 d16, d16, d17
+0x40 0xef 0xe2 0x06
+# CHECK: vmax.s8 q8, q8, q9
+0x50 0xef 0xe2 0x06
+# CHECK: vmax.s16 q8, q8, q9
+0x60 0xef 0xe2 0x06
+# CHECK: vmax.s32 q8, q8, q9
+0x40 0xff 0xe2 0x06
+# CHECK: vmax.u8 q8, q8, q9
+0x50 0xff 0xe2 0x06
+# CHECK: vmax.u16 q8, q8, q9
+0x60 0xff 0xe2 0x06
+# CHECK: vmax.u32 q8, q8, q9
+0x40 0xef 0xe2 0x0f
+# CHECK: vmax.f32 q8, q8, q9
+
+0xc0 0xef 0x18 0x0e
+# CHECK: vmov.i8 d16, #0x8
+0xc1 0xef 0x10 0x08
+# CHECK: vmov.i16 d16, #0x10
+0xc1 0xef 0x10 0x0a
+# CHECK: vmov.i16 d16, #0x1000
+0xc2 0xef 0x10 0x00
+# CHECK: vmov.i32 d16, #0x20
+0xc2 0xef 0x10 0x02
+# CHECK: vmov.i32 d16, #0x2000
+0xc2 0xef 0x10 0x04
+# CHECK: vmov.i32 d16, #0x200000
+0xc2 0xef 0x10 0x06
+# CHECK: vmov.i32 d16, #0x20000000
+0xc2 0xef 0x10 0x0c
+# CHECK: vmov.i32 d16, #0x20FF
+0xc2 0xef 0x10 0x0d
+# CHECK: vmov.i32 d16, #0x20FFFF
+0xc1 0xff 0x33 0x0e
+# CHECK: vmov.i64 d16, #0xFF0000FF0000FFFF
+0xc0 0xef 0x58 0x0e
+# CHECK: vmov.i8 q8, #0x8
+0xc1 0xef 0x50 0x08
+# CHECK: vmov.i16 q8, #0x10
+0xc1 0xef 0x50 0x0a
+# CHECK: vmov.i16 q8, #0x1000
+0xc2 0xef 0x50 0x00
+# CHECK: vmov.i32 q8, #0x20
+0xc2 0xef 0x50 0x02
+# CHECK: vmov.i32 q8, #0x2000
+0xc2 0xef 0x50 0x04
+# CHECK: vmov.i32 q8, #0x200000
+0xc2 0xef 0x50 0x06
+# CHECK: vmov.i32 q8, #0x20000000
+0xc2 0xef 0x50 0x0c
+# CHECK: vmov.i32 q8, #0x20FF
+0xc2 0xef 0x50 0x0d
+# CHECK: vmov.i32 q8, #0x20FFFF
+0xc1 0xff 0x73 0x0e
+# CHECK: vmov.i64 q8, #0xFF0000FF0000FFFF
+0xc1 0xef 0x30 0x08
+# CHECK: vmvn.i16 d16, #0x10
+0xc1 0xef 0x30 0x0a
+# CHECK: vmvn.i16 d16, #0x1000
+0xc2 0xef 0x30 0x00
+# CHECK: vmvn.i32 d16, #0x20
+0xc2 0xef 0x30 0x02
+# CHECK: vmvn.i32 d16, #0x2000
+0xc2 0xef 0x30 0x04
+# CHECK: vmvn.i32 d16, #0x200000
+0xc2 0xef 0x30 0x06
+# CHECK: vmvn.i32 d16, #0x20000000
+0xc2 0xef 0x30 0x0c
+# CHECK: vmvn.i32 d16, #0x20FF
+0xc2 0xef 0x30 0x0d
+# CHECK: vmvn.i32 d16, #0x20FFFF
+0xc8 0xef 0x30 0x0a
+# CHECK: vmovl.s8 q8, d16
+0xd0 0xef 0x30 0x0a
+# CHECK: vmovl.s16 q8, d16
+0xe0 0xef 0x30 0x0a
+# CHECK: vmovl.s32 q8, d16
+0xc8 0xff 0x30 0x0a
+# CHECK: vmovl.u8 q8, d16
+0xd0 0xff 0x30 0x0a
+# CHECK: vmovl.u16 q8, d16
+0xe0 0xff 0x30 0x0a
+# CHECK: vmovl.u32 q8, d16
+0xf2 0xff 0x20 0x02
+# CHECK: vmovn.i16 d16, q8
+0xf6 0xff 0x20 0x02
+# CHECK: vmovn.i32 d16, q8
+0xfa 0xff 0x20 0x02
+# CHECK: vmovn.i64 d16, q8
+0xf2 0xff 0xa0 0x02
+# CHECK: vqmovn.s16 d16, q8
+0xf6 0xff 0xa0 0x02
+# CHECK: vqmovn.s32 d16, q8
+0xfa 0xff 0xa0 0x02
+# CHECK: vqmovn.s64 d16, q8
+0xf2 0xff 0xe0 0x02
+# CHECK: vqmovn.u16 d16, q8
+0xf6 0xff 0xe0 0x02
+# CHECK: vqmovn.u32 d16, q8
+0xfa 0xff 0xe0 0x02
+# CHECK: vqmovn.u64 d16, q8
+0xf2 0xff 0x60 0x02
+# CHECK: vqmovun.s16 d16, q8
+0xf6 0xff 0x60 0x02
+# CHECK: vqmovun.s32 d16, q8
+0xfa 0xff 0x60 0x02
+# CHECK: vqmovun.s64 d16, q8
+0x50 0xee 0xb0 0x0b
+# CHECK: vmov.s8 r0, d16[1]
+0x10 0xee 0xf0 0x0b
+# CHECK: vmov.s16 r0, d16[1]
+0xd0 0xee 0xb0 0x0b
+# CHECK: vmov.u8 r0, d16[1]
+0x90 0xee 0xf0 0x0b
+# CHECK: vmov.u16 r0, d16[1]
+0x30 0xee 0x90 0x0b
+# CHECK: vmov.32 r0, d16[1]
+0x40 0xee 0xb0 0x1b
+# CHECK: vmov.8 d16[1], r1
+0x00 0xee 0xf0 0x1b
+# CHECK: vmov.16 d16[1], r1
+0x20 0xee 0x90 0x1b
+# CHECK: vmov.32 d16[1], r1
+0x42 0xee 0xb0 0x1b
+# CHECK: vmov.8 d18[1], r1
+0x02 0xee 0xf0 0x1b
+# CHECK: vmov.16 d18[1], r1
+0x22 0xee 0x90 0x1b
+# CHECK: vmov.32 d18[1], r1
+
+0x42 0xef 0xa1 0x09
+# CHECK: vmla.i8 d16, d18, d17
+0x52 0xef 0xa1 0x09
+# CHECK: vmla.i16 d16, d18, d17
+0x62 0xef 0xa1 0x09
+# CHECK: vmla.i32 d16, d18, d17
+0x42 0xef 0xb1 0x0d
+# CHECK: vmla.f32 d16, d18, d17
+0x40 0xef 0xe4 0x29
+# CHECK: vmla.i8 q9, q8, q10
+0x50 0xef 0xe4 0x29
+# CHECK: vmla.i16 q9, q8, q10
+0x60 0xef 0xe4 0x29
+# CHECK: vmla.i32 q9, q8, q10
+0x40 0xef 0xf4 0x2d
+# CHECK: vmla.f32 q9, q8, q10
+0xc3 0xef 0xa2 0x08
+# CHECK: vmlal.s8 q8, d19, d18
+0xd3 0xef 0xa2 0x08
+# CHECK: vmlal.s16 q8, d19, d18
+0xe3 0xef 0xa2 0x08
+# CHECK: vmlal.s32 q8, d19, d18
+0xc3 0xff 0xa2 0x08
+# CHECK: vmlal.u8 q8, d19, d18
+0xd3 0xff 0xa2 0x08
+# CHECK: vmlal.u16 q8, d19, d18
+0xe3 0xff 0xa2 0x08
+# CHECK: vmlal.u32 q8, d19, d18
+0xd3 0xef 0xa2 0x09
+# CHECK: vqdmlal.s16 q8, d19, d18
+0xe3 0xef 0xa2 0x09
+# CHECK: vqdmlal.s32 q8, d19, d18
+0x42 0xff 0xa1 0x09
+# CHECK: vmls.i8 d16, d18, d17
+0x52 0xff 0xa1 0x09
+# CHECK: vmls.i16 d16, d18, d17
+0x62 0xff 0xa1 0x09
+# CHECK: vmls.i32 d16, d18, d17
+0x62 0xef 0xb1 0x0d
+# CHECK: vmls.f32 d16, d18, d17
+0x40 0xff 0xe4 0x29
+# CHECK: vmls.i8 q9, q8, q10
+0x50 0xff 0xe4 0x29
+# CHECK: vmls.i16 q9, q8, q10
+0x60 0xff 0xe4 0x29
+# CHECK: vmls.i32 q9, q8, q10
+0x60 0xef 0xf4 0x2d
+# CHECK: vmls.f32 q9, q8, q10
+0xc3 0xef 0xa2 0x0a
+# CHECK: vmlsl.s8 q8, d19, d18
+0xd3 0xef 0xa2 0x0a
+# CHECK: vmlsl.s16 q8, d19, d18
+0xe3 0xef 0xa2 0x0a
+# CHECK: vmlsl.s32 q8, d19, d18
+0xc3 0xff 0xa2 0x0a
+# CHECK: vmlsl.u8 q8, d19, d18
+0xd3 0xff 0xa2 0x0a
+# CHECK: vmlsl.u16 q8, d19, d18
+0xe3 0xff 0xa2 0x0a
+# CHECK: vmlsl.u32 q8, d19, d18
+0xd3 0xef 0xa2 0x0b
+# CHECK: vqdmlsl.s16 q8, d19, d18
+0xe3 0xef 0xa2 0x0b
+# CHECK: vqdmlsl.s32 q8, d19, d18
+
+0x40 0xef 0xb1 0x09
+# CHECK: vmul.i8 d16, d16, d17
+0x50 0xef 0xb1 0x09
+# CHECK: vmul.i16 d16, d16, d17
+0x60 0xef 0xb1 0x09
+# CHECK: vmul.i32 d16, d16, d17
+0x40 0xff 0xb1 0x0d
+# CHECK: vmul.f32 d16, d16, d17
+0x40 0xef 0xf2 0x09
+# CHECK: vmul.i8 q8, q8, q9
+0x50 0xef 0xf2 0x09
+# CHECK: vmul.i16 q8, q8, q9
+0x60 0xef 0xf2 0x09
+# CHECK: vmul.i32 q8, q8, q9
+0x40 0xff 0xf2 0x0d
+# CHECK: vmul.f32 q8, q8, q9
+0x40 0xff 0xb1 0x09
+# CHECK: vmul.p8 d16, d16, d17
+0x40 0xff 0xf2 0x09
+# CHECK: vmul.p8 q8, q8, q9
+0x50 0xef 0xa1 0x0b
+# CHECK: vqdmulh.s16 d16, d16, d17
+0x60 0xef 0xa1 0x0b
+# CHECK: vqdmulh.s32 d16, d16, d17
+0x50 0xef 0xe2 0x0b
+# CHECK: vqdmulh.s16 q8, q8, q9
+0x60 0xef 0xe2 0x0b
+# CHECK: vqdmulh.s32 q8, q8, q9
+0x50 0xff 0xa1 0x0b
+# CHECK: vqrdmulh.s16 d16, d16, d17
+0x60 0xff 0xa1 0x0b
+# CHECK: vqrdmulh.s32 d16, d16, d17
+0x50 0xff 0xe2 0x0b
+# CHECK: vqrdmulh.s16 q8, q8, q9
+0x60 0xff 0xe2 0x0b
+# CHECK: vqrdmulh.s32 q8, q8, q9
+0xc0 0xef 0xa1 0x0c
+# CHECK: vmull.s8 q8, d16, d17
+0xd0 0xef 0xa1 0x0c
+# CHECK: vmull.s16 q8, d16, d17
+0xe0 0xef 0xa1 0x0c
+# CHECK: vmull.s32 q8, d16, d17
+0xc0 0xff 0xa1 0x0c
+# CHECK: vmull.u8 q8, d16, d17
+0xd0 0xff 0xa1 0x0c
+# CHECK: vmull.u16 q8, d16, d17
+0xe0 0xff 0xa1 0x0c
+# CHECK: vmull.u32 q8, d16, d17
+0xc0 0xef 0xa1 0x0e
+# CHECK: vmull.p8 q8, d16, d17
+0xd0 0xef 0xa1 0x0d
+# CHECK: vqdmull.s16 q8, d16, d17
+0xe0 0xef 0xa1 0x0d
+# CHECK: vqdmull.s32 q8, d16, d17
+0xf1 0xff 0xa0 0x03
+# CHECK: vneg.s8 d16, d16
+0xf5 0xff 0xa0 0x03
+# CHECK: vneg.s16 d16, d16
+0xf9 0xff 0xa0 0x03
+# CHECK: vneg.s32 d16, d16
+0xf9 0xff 0xa0 0x07
+# CHECK: vneg.f32 d16, d16
+0xf1 0xff 0xe0 0x03
+# CHECK: vneg.s8 q8, q8
+0xf5 0xff 0xe0 0x03
+# CHECK: vneg.s16 q8, q8
+0xf9 0xff 0xe0 0x03
+# CHECK: vneg.s32 q8, q8
+0xf9 0xff 0xe0 0x07
+# CHECK: vneg.f32 q8, q8
+0xf0 0xff 0xa0 0x07
+# CHECK: vqneg.s8 d16, d16
+0xf4 0xff 0xa0 0x07
+# CHECK: vqneg.s16 d16, d16
+0xf8 0xff 0xa0 0x07
+# CHECK: vqneg.s32 d16, d16
+0xf0 0xff 0xe0 0x07
+# CHECK: vqneg.s8 q8, q8
+0xf4 0xff 0xe0 0x07
+# CHECK: vqneg.s16 q8, q8
+0xf8 0xff 0xe0 0x07
+# CHECK: vqneg.s32 q8, q8
+
+0x41 0xef 0xb0 0x0b
+# CHECK: vpadd.i8 d16, d17, d16
+0x51 0xef 0xb0 0x0b
+# CHECK: vpadd.i16 d16, d17, d16
+0x61 0xef 0xb0 0x0b
+# CHECK: vpadd.i32 d16, d17, d16
+0x40 0xff 0xa1 0x0d
+# CHECK: vpadd.f32 d16, d16, d17
+0xf0 0xff 0x20 0x02
+# CHECK: vpaddl.s8 d16, d16
+0xf4 0xff 0x20 0x02
+# CHECK: vpaddl.s16 d16, d16
+0xf8 0xff 0x20 0x02
+# CHECK: vpaddl.s32 d16, d16
+0xf0 0xff 0xa0 0x02
+# CHECK: vpaddl.u8 d16, d16
+0xf4 0xff 0xa0 0x02
+# CHECK: vpaddl.u16 d16, d16
+0xf8 0xff 0xa0 0x02
+# CHECK: vpaddl.u32 d16, d16
+0xf0 0xff 0x60 0x02
+# CHECK: vpaddl.s8 q8, q8
+0xf4 0xff 0x60 0x02
+# CHECK: vpaddl.s16 q8, q8
+0xf8 0xff 0x60 0x02
+# CHECK: vpaddl.s32 q8, q8
+0xf0 0xff 0xe0 0x02
+# CHECK: vpaddl.u8 q8, q8
+0xf4 0xff 0xe0 0x02
+# CHECK: vpaddl.u16 q8, q8
+0xf8 0xff 0xe0 0x02
+# CHECK: vpaddl.u32 q8, q8
+0xf0 0xff 0x21 0x06
+# CHECK: vpadal.s8 d16, d17
+0xf4 0xff 0x21 0x06
+# CHECK: vpadal.s16 d16, d17
+0xf8 0xff 0x21 0x06
+# CHECK: vpadal.s32 d16, d17
+0xf0 0xff 0xa1 0x06
+# CHECK: vpadal.u8 d16, d17
+0xf4 0xff 0xa1 0x06
+# CHECK: vpadal.u16 d16, d17
+0xf8 0xff 0xa1 0x06
+# CHECK: vpadal.u32 d16, d17
+0xf0 0xff 0x60 0x26
+# CHECK: vpadal.s8 q9, q8
+0xf4 0xff 0x60 0x26
+# CHECK: vpadal.s16 q9, q8
+0xf8 0xff 0x60 0x26
+# CHECK: vpadal.s32 q9, q8
+0xf0 0xff 0xe0 0x26
+# CHECK: vpadal.u8 q9, q8
+0xf4 0xff 0xe0 0x26
+# CHECK: vpadal.u16 q9, q8
+0xf8 0xff 0xe0 0x26
+# CHECK: vpadal.u32 q9, q8
+0x40 0xef 0xb1 0x0a
+# CHECK: vpmin.s8 d16, d16, d17
+0x50 0xef 0xb1 0x0a
+# CHECK: vpmin.s16 d16, d16, d17
+0x60 0xef 0xb1 0x0a
+# CHECK: vpmin.s32 d16, d16, d17
+0x40 0xff 0xb1 0x0a
+# CHECK: vpmin.u8 d16, d16, d17
+0x50 0xff 0xb1 0x0a
+# CHECK: vpmin.u16 d16, d16, d17
+0x60 0xff 0xb1 0x0a
+# CHECK: vpmin.u32 d16, d16, d17
+0x60 0xff 0xa1 0x0f
+# CHECK: vpmin.f32 d16, d16, d17
+0x40 0xef 0xa1 0x0a
+# CHECK: vpmax.s8 d16, d16, d17
+0x50 0xef 0xa1 0x0a
+# CHECK: vpmax.s16 d16, d16, d17
+0x60 0xef 0xa1 0x0a
+# CHECK: vpmax.s32 d16, d16, d17
+0x40 0xff 0xa1 0x0a
+# CHECK: vpmax.u8 d16, d16, d17
+0x50 0xff 0xa1 0x0a
+# CHECK: vpmax.u16 d16, d16, d17
+0x60 0xff 0xa1 0x0a
+# CHECK: vpmax.u32 d16, d16, d17
+0x40 0xff 0xa1 0x0f
+# CHECK: vpmax.f32 d16, d16, d17
+0xfb 0xff 0x20 0x04
+# CHECK: vrecpe.u32 d16, d16
+0xfb 0xff 0x60 0x04
+# CHECK: vrecpe.u32 q8, q8
+0xfb 0xff 0x20 0x05
+# CHECK: vrecpe.f32 d16, d16
+0xfb 0xff 0x60 0x05
+# CHECK: vrecpe.f32 q8, q8
+0x40 0xef 0xb1 0x0f
+# CHECK: vrecps.f32 d16, d16, d17
+0x40 0xef 0xf2 0x0f
+# CHECK: vrecps.f32 q8, q8, q9
+0xfb 0xff 0xa0 0x04
+# CHECK: vrsqrte.u32 d16, d16
+0xfb 0xff 0xe0 0x04
+# CHECK: vrsqrte.u32 q8, q8
+0xfb 0xff 0xa0 0x05
+# CHECK: vrsqrte.f32 d16, d16
+0xfb 0xff 0xe0 0x05
+# CHECK: vrsqrte.f32 q8, q8
+0x60 0xef 0xb1 0x0f
+# CHECK: vrsqrts.f32 d16, d16, d17
+0x60 0xef 0xf2 0x0f
+# CHECK: vrsqrts.f32 q8, q8, q9
+
+
+0xf0 0xff 0x20 0x00
+# CHECK: vrev64.8 d16, d16
+0xf4 0xff 0x20 0x00
+# CHECK: vrev64.16 d16, d16
+0xf8 0xff 0x20 0x00
+# CHECK: vrev64.32 d16, d16
+0xf0 0xff 0x60 0x00
+# CHECK: vrev64.8 q8, q8
+0xf4 0xff 0x60 0x00
+# CHECK: vrev64.16 q8, q8
+0xf8 0xff 0x60 0x00
+# CHECK: vrev64.32 q8, q8
+0xf0 0xff 0xa0 0x00
+# CHECK: vrev32.8 d16, d16
+0xf4 0xff 0xa0 0x00
+# CHECK: vrev32.16 d16, d16
+0xf0 0xff 0xe0 0x00
+# CHECK: vrev32.8 q8, q8
+0xf4 0xff 0xe0 0x00
+# CHECK: vrev32.16 q8, q8
+0xf0 0xff 0x20 0x01
+# CHECK: vrev16.8 d16, d16
+0xf0 0xff 0x60 0x01
+# CHECK: vrev16.8 q8, q8
+0x41 0xef 0xb0 0x04
+# CHECK: vqshl.s8 d16, d16, d17
+0x51 0xef 0xb0 0x04
+# CHECK: vqshl.s16 d16, d16, d17
+0x61 0xef 0xb0 0x04
+# CHECK: vqshl.s32 d16, d16, d17
+0x71 0xef 0xb0 0x04
+# CHECK: vqshl.s64 d16, d16, d17
+0x41 0xff 0xb0 0x04
+# CHECK: vqshl.u8 d16, d16, d17
+0x51 0xff 0xb0 0x04
+# CHECK: vqshl.u16 d16, d16, d17
+0x61 0xff 0xb0 0x04
+# CHECK: vqshl.u32 d16, d16, d17
+0x71 0xff 0xb0 0x04
+# CHECK: vqshl.u64 d16, d16, d17
+0x42 0xef 0xf0 0x04
+# CHECK: vqshl.s8 q8, q8, q9
+0x52 0xef 0xf0 0x04
+# CHECK: vqshl.s16 q8, q8, q9
+0x62 0xef 0xf0 0x04
+# CHECK: vqshl.s32 q8, q8, q9
+0x72 0xef 0xf0 0x04
+# CHECK: vqshl.s64 q8, q8, q9
+0x42 0xff 0xf0 0x04
+# CHECK: vqshl.u8 q8, q8, q9
+0x52 0xff 0xf0 0x04
+# CHECK: vqshl.u16 q8, q8, q9
+0x62 0xff 0xf0 0x04
+# CHECK: vqshl.u32 q8, q8, q9
+0x72 0xff 0xf0 0x04
+# CHECK: vqshl.u64 q8, q8, q9
+0xcf 0xef 0x30 0x07
+# CHECK: vqshl.s8 d16, d16, #7
+0xdf 0xef 0x30 0x07
+# CHECK: vqshl.s16 d16, d16, #15
+0xff 0xef 0x30 0x07
+# CHECK: vqshl.s32 d16, d16, #31
+0xff 0xef 0xb0 0x07
+# CHECK: vqshl.s64 d16, d16, #63
+0xcf 0xff 0x30 0x07
+# CHECK: vqshl.u8 d16, d16, #7
+0xdf 0xff 0x30 0x07
+# CHECK: vqshl.u16 d16, d16, #15
+0xff 0xff 0x30 0x07
+# CHECK: vqshl.u32 d16, d16, #31
+0xff 0xff 0xb0 0x07
+# CHECK: vqshl.u64 d16, d16, #63
+0xcf 0xff 0x30 0x06
+# CHECK: vqshlu.s8 d16, d16, #7
+0xdf 0xff 0x30 0x06
+# CHECK: vqshlu.s16 d16, d16, #15
+0xff 0xff 0x30 0x06
+# CHECK: vqshlu.s32 d16, d16, #31
+0xff 0xff 0xb0 0x06
+# CHECK: vqshlu.s64 d16, d16, #63
+0xcf 0xef 0x70 0x07
+# CHECK: vqshl.s8 q8, q8, #7
+0xdf 0xef 0x70 0x07
+# CHECK: vqshl.s16 q8, q8, #15
+0xff 0xef 0x70 0x07
+# CHECK: vqshl.s32 q8, q8, #31
+0xff 0xef 0xf0 0x07
+# CHECK: vqshl.s64 q8, q8, #63
+0xcf 0xff 0x70 0x07
+# CHECK: vqshl.u8 q8, q8, #7
+0xdf 0xff 0x70 0x07
+# CHECK: vqshl.u16 q8, q8, #15
+0xff 0xff 0x70 0x07
+# CHECK: vqshl.u32 q8, q8, #31
+0xff 0xff 0xf0 0x07
+# CHECK: vqshl.u64 q8, q8, #63
+0xcf 0xff 0x70 0x06
+# CHECK: vqshlu.s8 q8, q8, #7
+0xdf 0xff 0x70 0x06
+# CHECK: vqshlu.s16 q8, q8, #15
+0xff 0xff 0x70 0x06
+# CHECK: vqshlu.s32 q8, q8, #31
+0xff 0xff 0xf0 0x06
+# CHECK: vqshlu.s64 q8, q8, #63
+0x41 0xef 0xb0 0x05
+# CHECK: vqrshl.s8 d16, d16, d17
+0x51 0xef 0xb0 0x05
+# CHECK: vqrshl.s16 d16, d16, d17
+0x61 0xef 0xb0 0x05
+# CHECK: vqrshl.s32 d16, d16, d17
+0x71 0xef 0xb0 0x05
+# CHECK: vqrshl.s64 d16, d16, d17
+0x41 0xff 0xb0 0x05
+# CHECK: vqrshl.u8 d16, d16, d17
+0x51 0xff 0xb0 0x05
+# CHECK: vqrshl.u16 d16, d16, d17
+0x61 0xff 0xb0 0x05
+# CHECK: vqrshl.u32 d16, d16, d17
+0x71 0xff 0xb0 0x05
+# CHECK: vqrshl.u64 d16, d16, d17
+0x42 0xef 0xf0 0x05
+# CHECK: vqrshl.s8 q8, q8, q9
+0x52 0xef 0xf0 0x05
+# CHECK: vqrshl.s16 q8, q8, q9
+0x62 0xef 0xf0 0x05
+# CHECK: vqrshl.s32 q8, q8, q9
+0x72 0xef 0xf0 0x05
+# CHECK: vqrshl.s64 q8, q8, q9
+0x42 0xff 0xf0 0x05
+# CHECK: vqrshl.u8 q8, q8, q9
+0x52 0xff 0xf0 0x05
+# CHECK: vqrshl.u16 q8, q8, q9
+0x62 0xff 0xf0 0x05
+# CHECK: vqrshl.u32 q8, q8, q9
+0x72 0xff 0xf0 0x05
+# CHECK: vqrshl.u64 q8, q8, q9
+0xc8 0xef 0x30 0x09
+# CHECK: vqshrn.s16 d16, q8, #8
+0xd0 0xef 0x30 0x09
+# CHECK: vqshrn.s32 d16, q8, #16
+0xe0 0xef 0x30 0x09
+# CHECK: vqshrn.s64 d16, q8, #32
+0xc8 0xff 0x30 0x09
+# CHECK: vqshrn.u16 d16, q8, #8
+0xd0 0xff 0x30 0x09
+# CHECK: vqshrn.u32 d16, q8, #16
+0xe0 0xff 0x30 0x09
+# CHECK: vqshrn.u64 d16, q8, #32
+0xc8 0xff 0x30 0x08
+# CHECK: vqshrun.s16 d16, q8, #8
+0xd0 0xff 0x30 0x08
+# CHECK: vqshrun.s32 d16, q8, #16
+0xe0 0xff 0x30 0x08
+# CHECK: vqshrun.s64 d16, q8, #32
+0xc8 0xef 0x70 0x09
+# CHECK: vqrshrn.s16 d16, q8, #8
+0xd0 0xef 0x70 0x09
+# CHECK: vqrshrn.s32 d16, q8, #16
+0xe0 0xef 0x70 0x09
+# CHECK: vqrshrn.s64 d16, q8, #32
+0xc8 0xff 0x70 0x09
+# CHECK: vqrshrn.u16 d16, q8, #8
+0xd0 0xff 0x70 0x09
+# CHECK: vqrshrn.u32 d16, q8, #16
+0xe0 0xff 0x70 0x09
+# CHECK: vqrshrn.u64 d16, q8, #32
+0xc8 0xff 0x70 0x08
+# CHECK: vqrshrun.s16 d16, q8, #8
+0xd0 0xff 0x70 0x08
+# CHECK: vqrshrun.s32 d16, q8, #16
+0xe0 0xff 0x70 0x08
+# CHECK: vqrshrun.s64 d16, q8, #32
+0x40 0xff 0xa1 0x04
+# CHECK: vshl.u8 d16, d17, d16
+0x50 0xff 0xa1 0x04
+# CHECK: vshl.u16 d16, d17, d16
+0x60 0xff 0xa1 0x04
+# CHECK: vshl.u32 d16, d17, d16
+0x70 0xff 0xa1 0x04
+# CHECK: vshl.u64 d16, d17, d16
+0xcf 0xef 0x30 0x05
+# CHECK: vshl.i8 d16, d16, #7
+0xdf 0xef 0x30 0x05
+# CHECK: vshl.i16 d16, d16, #15
+0xff 0xef 0x30 0x05
+# CHECK: vshl.i32 d16, d16, #31
+0xff 0xef 0xb0 0x05
+# CHECK: vshl.i64 d16, d16, #63
+0x40 0xff 0xe2 0x04
+# CHECK: vshl.u8 q8, q9, q8
+0x50 0xff 0xe2 0x04
+# CHECK: vshl.u16 q8, q9, q8
+0x60 0xff 0xe2 0x04
+# CHECK: vshl.u32 q8, q9, q8
+0x70 0xff 0xe2 0x04
+# CHECK: vshl.u64 q8, q9, q8
+0xcf 0xef 0x70 0x05
+# CHECK: vshl.i8 q8, q8, #7
+0xdf 0xef 0x70 0x05
+# CHECK: vshl.i16 q8, q8, #15
+0xff 0xef 0x70 0x05
+# CHECK: vshl.i32 q8, q8, #31
+0xff 0xef 0xf0 0x05
+# CHECK: vshl.i64 q8, q8, #63
+0xc8 0xff 0x30 0x00
+# CHECK: vshr.u8 d16, d16, #8
+0xd0 0xff 0x30 0x00
+# CHECK: vshr.u16 d16, d16, #16
+0xe0 0xff 0x30 0x00
+# CHECK: vshr.u32 d16, d16, #32
+0xc0 0xff 0xb0 0x00
+# CHECK: vshr.u64 d16, d16, #64
+0xc8 0xff 0x70 0x00
+# CHECK: vshr.u8 q8, q8, #8
+0xd0 0xff 0x70 0x00
+# CHECK: vshr.u16 q8, q8, #16
+0xe0 0xff 0x70 0x00
+# CHECK: vshr.u32 q8, q8, #32
+0xc0 0xff 0xf0 0x00
+# CHECK: vshr.u64 q8, q8, #64
+0xc8 0xef 0x30 0x00
+# CHECK: vshr.s8 d16, d16, #8
+0xd0 0xef 0x30 0x00
+# CHECK: vshr.s16 d16, d16, #16
+0xe0 0xef 0x30 0x00
+# CHECK: vshr.s32 d16, d16, #32
+0xc0 0xef 0xb0 0x00
+# CHECK: vshr.s64 d16, d16, #64
+0xc8 0xef 0x70 0x00
+# CHECK: vshr.s8 q8, q8, #8
+0xd0 0xef 0x70 0x00
+# CHECK: vshr.s16 q8, q8, #16
+0xe0 0xef 0x70 0x00
+# CHECK: vshr.s32 q8, q8, #32
+0xc0 0xef 0xf0 0x00
+# CHECK: vshr.s64 q8, q8, #64
+0xcf 0xef 0x30 0x0a
+# CHECK: vshll.s8 q8, d16, #7
+0xdf 0xef 0x30 0x0a
+# CHECK: vshll.s16 q8, d16, #15
+0xff 0xef 0x30 0x0a
+# CHECK: vshll.s32 q8, d16, #31
+0xcf 0xff 0x30 0x0a
+# CHECK: vshll.u8 q8, d16, #7
+0xdf 0xff 0x30 0x0a
+# CHECK: vshll.u16 q8, d16, #15
+0xff 0xff 0x30 0x0a
+# CHECK: vshll.u32 q8, d16, #31
+0xf2 0xff 0x20 0x03
+# CHECK: vshll.i8 q8, d16, #8
+0xf6 0xff 0x20 0x03
+# CHECK: vshll.i16 q8, d16, #16
+0xfa 0xff 0x20 0x03
+# CHECK: vshll.i32 q8, d16, #32
+0xc8 0xef 0x30 0x08
+# CHECK: vshrn.i16 d16, q8, #8
+0xd0 0xef 0x30 0x08
+# CHECK: vshrn.i32 d16, q8, #16
+0xe0 0xef 0x30 0x08
+# CHECK: vshrn.i64 d16, q8, #32
+0x40 0xef 0xa1 0x05
+# CHECK: vrshl.s8 d16, d17, d16
+0x50 0xef 0xa1 0x05
+# CHECK: vrshl.s16 d16, d17, d16
+0x60 0xef 0xa1 0x05
+# CHECK: vrshl.s32 d16, d17, d16
+0x70 0xef 0xa1 0x05
+# CHECK: vrshl.s64 d16, d17, d16
+0x40 0xff 0xa1 0x05
+# CHECK: vrshl.u8 d16, d17, d16
+0x50 0xff 0xa1 0x05
+# CHECK: vrshl.u16 d16, d17, d16
+0x60 0xff 0xa1 0x05
+# CHECK: vrshl.u32 d16, d17, d16
+0x70 0xff 0xa1 0x05
+# CHECK: vrshl.u64 d16, d17, d16
+0x40 0xef 0xe2 0x05
+# CHECK: vrshl.s8 q8, q9, q8
+0x50 0xef 0xe2 0x05
+# CHECK: vrshl.s16 q8, q9, q8
+0x60 0xef 0xe2 0x05
+# CHECK: vrshl.s32 q8, q9, q8
+0x70 0xef 0xe2 0x05
+# CHECK: vrshl.s64 q8, q9, q8
+0x40 0xff 0xe2 0x05
+# CHECK: vrshl.u8 q8, q9, q8
+0x50 0xff 0xe2 0x05
+# CHECK: vrshl.u16 q8, q9, q8
+0x60 0xff 0xe2 0x05
+# CHECK: vrshl.u32 q8, q9, q8
+0x70 0xff 0xe2 0x05
+# CHECK: vrshl.u64 q8, q9, q8
+0xc8 0xef 0x30 0x02
+# CHECK: vrshr.s8 d16, d16, #8
+0xd0 0xef 0x30 0x02
+# CHECK: vrshr.s16 d16, d16, #16
+0xe0 0xef 0x30 0x02
+# CHECK: vrshr.s32 d16, d16, #32
+0xc0 0xef 0xb0 0x02
+# CHECK: vrshr.s64 d16, d16, #64
+0xc8 0xff 0x30 0x02
+# CHECK: vrshr.u8 d16, d16, #8
+0xd0 0xff 0x30 0x02
+# CHECK: vrshr.u16 d16, d16, #16
+0xe0 0xff 0x30 0x02
+# CHECK: vrshr.u32 d16, d16, #32
+0xc0 0xff 0xb0 0x02
+# CHECK: vrshr.u64 d16, d16, #64
+0xc8 0xef 0x70 0x02
+# CHECK: vrshr.s8 q8, q8, #8
+0xd0 0xef 0x70 0x02
+# CHECK: vrshr.s16 q8, q8, #16
+0xe0 0xef 0x70 0x02
+# CHECK: vrshr.s32 q8, q8, #32
+0xc0 0xef 0xf0 0x02
+# CHECK: vrshr.s64 q8, q8, #64
+0xc8 0xff 0x70 0x02
+# CHECK: vrshr.u8 q8, q8, #8
+0xd0 0xff 0x70 0x02
+# CHECK: vrshr.u16 q8, q8, #16
+0xe0 0xff 0x70 0x02
+# CHECK: vrshr.u32 q8, q8, #32
+0xc0 0xff 0xf0 0x02
+# CHECK: vrshr.u64 q8, q8, #64
+0xc8 0xef 0x70 0x08
+# CHECK: vrshrn.i16 d16, q8, #8
+0xd0 0xef 0x70 0x08
+# CHECK: vrshrn.i32 d16, q8, #16
+0xe0 0xef 0x70 0x08
+# CHECK: vrshrn.i64 d16, q8, #32
+0xc8 0xef 0x30 0x11
+# CHECK: vsra.s8 d17, d16, #8
+0xd0 0xef 0x30 0x11
+# CHECK: vsra.s16 d17, d16, #16
+0xe0 0xef 0x30 0x11
+# CHECK: vsra.s32 d17, d16, #32
+0xc0 0xef 0xb0 0x11
+# CHECK: vsra.s64 d17, d16, #64
+0xc8 0xef 0x72 0x01
+# CHECK: vsra.s8 q8, q9, #8
+0xd0 0xef 0x72 0x01
+# CHECK: vsra.s16 q8, q9, #16
+0xe0 0xef 0x72 0x01
+# CHECK: vsra.s32 q8, q9, #32
+0xc0 0xef 0xf2 0x01
+# CHECK: vsra.s64 q8, q9, #64
+0xc8 0xff 0x30 0x11
+# CHECK: vsra.u8 d17, d16, #8
+0xd0 0xff 0x30 0x11
+# CHECK: vsra.u16 d17, d16, #16
+0xe0 0xff 0x30 0x11
+# CHECK: vsra.u32 d17, d16, #32
+0xc0 0xff 0xb0 0x11
+# CHECK: vsra.u64 d17, d16, #64
+0xc8 0xff 0x72 0x01
+# CHECK: vsra.u8 q8, q9, #8
+0xd0 0xff 0x72 0x01
+# CHECK: vsra.u16 q8, q9, #16
+0xe0 0xff 0x72 0x01
+# CHECK: vsra.u32 q8, q9, #32
+0xc0 0xff 0xf2 0x01
+# CHECK: vsra.u64 q8, q9, #64
+0xc8 0xef 0x30 0x13
+# CHECK: vrsra.s8 d17, d16, #8
+0xd0 0xef 0x30 0x13
+# CHECK: vrsra.s16 d17, d16, #16
+0xe0 0xef 0x30 0x13
+# CHECK: vrsra.s32 d17, d16, #32
+0xc0 0xef 0xb0 0x13
+# CHECK: vrsra.s64 d17, d16, #64
+0xc8 0xff 0x30 0x13
+# CHECK: vrsra.u8 d17, d16, #8
+0xd0 0xff 0x30 0x13
+# CHECK: vrsra.u16 d17, d16, #16
+0xe0 0xff 0x30 0x13
+# CHECK: vrsra.u32 d17, d16, #32
+0xc0 0xff 0xb0 0x13
+# CHECK: vrsra.u64 d17, d16, #64
+0xc8 0xef 0x72 0x03
+# CHECK: vrsra.s8 q8, q9, #8
+0xd0 0xef 0x72 0x03
+# CHECK: vrsra.s16 q8, q9, #16
+0xe0 0xef 0x72 0x03
+# CHECK: vrsra.s32 q8, q9, #32
+0xc0 0xef 0xf2 0x03
+# CHECK: vrsra.s64 q8, q9, #64
+0xc8 0xff 0x72 0x03
+# CHECK: vrsra.u8 q8, q9, #8
+0xd0 0xff 0x72 0x03
+# CHECK: vrsra.u16 q8, q9, #16
+0xe0 0xff 0x72 0x03
+# CHECK: vrsra.u32 q8, q9, #32
+0xc0 0xff 0xf2 0x03
+# CHECK: vrsra.u64 q8, q9, #64
+0xcf 0xff 0x30 0x15
+# CHECK: vsli.8 d17, d16, #7
+0xdf 0xff 0x30 0x15
+# CHECK: vsli.16 d17, d16, #15
+0xff 0xff 0x30 0x15
+# CHECK: vsli.32 d17, d16, #31
+0xff 0xff 0xb0 0x15
+# CHECK: vsli.64 d17, d16, #63
+0xcf 0xff 0x70 0x25
+# CHECK: vsli.8 q9, q8, #7
+0xdf 0xff 0x70 0x25
+# CHECK: vsli.16 q9, q8, #15
+0xff 0xff 0x70 0x25
+# CHECK: vsli.32 q9, q8, #31
+0xff 0xff 0xf0 0x25
+# CHECK: vsli.64 q9, q8, #63
+0xc8 0xff 0x30 0x14
+# CHECK: vsri.8 d17, d16, #8
+0xd0 0xff 0x30 0x14
+# CHECK: vsri.16 d17, d16, #16
+0xe0 0xff 0x30 0x14
+# CHECK: vsri.32 d17, d16, #32
+0xc0 0xff 0xb0 0x14
+# CHECK: vsri.64 d17, d16, #64
+0xc8 0xff 0x70 0x24
+# CHECK: vsri.8 q9, q8, #8
+0xd0 0xff 0x70 0x24
+# CHECK: vsri.16 q9, q8, #16
+0xe0 0xff 0x70 0x24
+# CHECK: vsri.32 q9, q8, #32
+0xc0 0xff 0xf0 0x24
+# CHECK: vsri.64 q9, q8, #64
+0xf1 0xef 0xa0 0x03
+# CHECK: vext.8 d16, d17, d16, #3
+0xf1 0xef 0xa0 0x05
+# CHECK: vext.8 d16, d17, d16, #5
+0xf2 0xef 0xe0 0x03
+# CHECK: vext.8 q8, q9, q8, #3
+0xf2 0xef 0xe0 0x07
+# CHECK: vext.8 q8, q9, q8, #7
+0xf1 0xef 0xa0 0x06
+# CHECK: vext.16 d16, d17, d16, #3
+0xf2 0xef 0xe0 0x0c
+# CHECK: vext.32 q8, q9, q8, #3
+0xf2 0xff 0xa0 0x10
+# CHECK: vtrn.8 d17, d16
+0xf6 0xff 0xa0 0x10
+# CHECK: vtrn.16 d17, d16
+0xfa 0xff 0xa0 0x10
+# CHECK: vtrn.32 d17, d16
+0xf2 0xff 0xe0 0x20
+# CHECK: vtrn.8 q9, q8
+0xf6 0xff 0xe0 0x20
+# CHECK: vtrn.16 q9, q8
+0xfa 0xff 0xe0 0x20
+# CHECK: vtrn.32 q9, q8
+0xf2 0xff 0x20 0x11
+# CHECK: vuzp.8 d17, d16
+0xf6 0xff 0x20 0x11
+# CHECK: vuzp.16 d17, d16
+0xf2 0xff 0x60 0x21
+# CHECK: vuzp.8 q9, q8
+0xf6 0xff 0x60 0x21
+# CHECK: vuzp.16 q9, q8
+0xfa 0xff 0x60 0x21
+# CHECK: vuzp.32 q9, q8
+0xf2 0xff 0xa0 0x11
+# CHECK: vzip.8 d17, d16
+0xf6 0xff 0xa0 0x11
+# CHECK: vzip.16 d17, d16
+0xf2 0xff 0xe0 0x21
+# CHECK: vzip.8 q9, q8
+0xf6 0xff 0xe0 0x21
+# CHECK: vzip.16 q9, q8
+0xfa 0xff 0xe0 0x21
+# CHECK: vzip.32 q9, q8
+
+
+0xf1 0xef 0xa0 0x03
+# CHECK: vext.8 d16, d17, d16, #3
+0xf1 0xef 0xa0 0x05
+# CHECK: vext.8 d16, d17, d16, #5
+0xf2 0xef 0xe0 0x03
+# CHECK: vext.8 q8, q9, q8, #3
+0xf2 0xef 0xe0 0x07
+# CHECK: vext.8 q8, q9, q8, #7
+0xf1 0xef 0xa0 0x06
+# CHECK: vext.16 d16, d17, d16, #3
+0xf2 0xef 0xe0 0x0c
+# CHECK: vext.32 q8, q9, q8, #3
+0xf2 0xff 0xa0 0x10
+# CHECK: vtrn.8 d17, d16
+0xf6 0xff 0xa0 0x10
+# CHECK: vtrn.16 d17, d16
+0xfa 0xff 0xa0 0x10
+# CHECK: vtrn.32 d17, d16
+0xf2 0xff 0xe0 0x20
+# CHECK: vtrn.8 q9, q8
+0xf6 0xff 0xe0 0x20
+# CHECK: vtrn.16 q9, q8
+0xfa 0xff 0xe0 0x20
+# CHECK: vtrn.32 q9, q8
+0xf2 0xff 0x20 0x11
+# CHECK: vuzp.8 d17, d16
+0xf6 0xff 0x20 0x11
+# CHECK: vuzp.16 d17, d16
+0xf2 0xff 0x60 0x21
+# CHECK: vuzp.8 q9, q8
+0xf6 0xff 0x60 0x21
+# CHECK: vuzp.16 q9, q8
+0xfa 0xff 0x60 0x21
+# CHECK: vuzp.32 q9, q8
+0xf2 0xff 0xa0 0x11
+# CHECK: vzip.8 d17, d16
+0xf6 0xff 0xa0 0x11
+# CHECK: vzip.16 d17, d16
+0xf2 0xff 0xe0 0x21
+# CHECK: vzip.8 q9, q8
+0xf6 0xff 0xe0 0x21
+# CHECK: vzip.16 q9, q8
+0xfa 0xff 0xe0 0x21
+# CHECK: vzip.32 q9, q8
+
+0xf1 0xff 0xa0 0x08
+# CHECK: vtbl.8 d16, {d17}, d16
+0xf0 0xff 0xa2 0x09
+# CHECK: vtbl.8 d16, {d16, d17}, d18
+0xf0 0xff 0xa4 0x0a
+# CHECK: vtbl.8 d16, {d16, d17, d18}, d20
+0xf0 0xff 0xa4 0x0b
+# CHECK: vtbl.8 d16, {d16, d17, d18, d19}, d20
+0xf0 0xff 0xe1 0x28
+# CHECK: vtbx.8 d18, {d16}, d17
+0xf0 0xff 0xe2 0x39
+# CHECK: vtbx.8 d19, {d16, d17}, d18
+0xf0 0xff 0xe5 0x4a
+# CHECK: vtbx.8 d20, {d16, d17, d18}, d21
+0xf0 0xff 0xe5 0x4b
+# CHECK: vtbx.8 d20, {d16, d17, d18, d19}, d21
+
+0x60 0xf9 0x1f 0x07
+# CHECK: vld1.8 {d16}, [r0, :64]
+0x60 0xf9 0x4f 0x07
+# CHECK: vld1.16 {d16}, [r0]
+0x60 0xf9 0x8f 0x07
+# CHECK: vld1.32 {d16}, [r0]
+0x60 0xf9 0xcf 0x07
+# CHECK: vld1.64 {d16}, [r0]
+0x60 0xf9 0x1f 0x0a
+# CHECK: vld1.8 {d16, d17}, [r0, :64]
+0x60 0xf9 0x6f 0x0a
+# CHECK: vld1.16 {d16, d17}, [r0, :128]
+0x60 0xf9 0x8f 0x0a
+# CHECK: vld1.32 {d16, d17}, [r0]
+0x60 0xf9 0xcf 0x0a
+# CHECK: vld1.64 {d16, d17}, [r0]
+
+0x60 0xf9 0x1f 0x08
+# CHECK: vld2.8 {d16, d17}, [r0, :64]
+0x60 0xf9 0x6f 0x08
+# CHECK: vld2.16 {d16, d17}, [r0, :128]
+0x60 0xf9 0x8f 0x08
+# CHECK: vld2.32 {d16, d17}, [r0]
+0x60 0xf9 0x1f 0x03
+# CHECK: vld2.8 {d16, d17, d18, d19}, [r0, :64]
+0x60 0xf9 0x6f 0x03
+# CHECK: vld2.16 {d16, d17, d18, d19}, [r0, :128]
+0x60 0xf9 0xbf 0x03
+# CHECK: vld2.32 {d16, d17, d18, d19}, [r0, :256]
+
+0x60 0xf9 0x1f 0x04
+# CHECK: vld3.8 {d16, d17, d18}, [r0, :64]
+0x60 0xf9 0x4f 0x04
+# CHECK: vld3.16 {d16, d17, d18}, [r0]
+0x60 0xf9 0x8f 0x04
+# CHECK: vld3.32 {d16, d17, d18}, [r0]
+0x60 0xf9 0x1d 0x05
+# CHECK: vld3.8 {d16, d18, d20}, [r0, :64]!
+0x60 0xf9 0x1d 0x15
+# CHECK: vld3.8 {d17, d19, d21}, [r0, :64]!
+0x60 0xf9 0x4d 0x05
+# CHECK: vld3.16 {d16, d18, d20}, [r0]!
+0x60 0xf9 0x4d 0x15
+# CHECK: vld3.16 {d17, d19, d21}, [r0]!
+0x60 0xf9 0x8d 0x05
+# CHECK: vld3.32 {d16, d18, d20}, [r0]!
+0x60 0xf9 0x8d 0x15
+# CHECK: vld3.32 {d17, d19, d21}, [r0]!
+
+0x60 0xf9 0x1f 0x00
+# CHECK: vld4.8 {d16, d17, d18, d19}, [r0, :64]
+0x60 0xf9 0x6f 0x00
+# CHECK: vld4.16 {d16, d17, d18, d19}, [r0, :128]
+0x60 0xf9 0xbf 0x00
+# CHECK: vld4.32 {d16, d17, d18, d19}, [r0, :256]
+0x60 0xf9 0x3d 0x01
+# CHECK: vld4.8 {d16, d18, d20, d22}, [r0, :256]!
+0x60 0xf9 0x3d 0x11
+# CHECK: vld4.8 {d17, d19, d21, d23}, [r0, :256]!
+0x60 0xf9 0x4d 0x01
+# CHECK: vld4.16 {d16, d18, d20, d22}, [r0]!
+0x60 0xf9 0x4d 0x11
+# CHECK: vld4.16 {d17, d19, d21, d23}, [r0]!
+0x60 0xf9 0x8d 0x01
+# CHECK: vld4.32 {d16, d18, d20, d22}, [r0]!
+0x60 0xf9 0x8d 0x11
+# CHECK: vld4.32 {d17, d19, d21, d23}, [r0]!
+
+0xe0 0xf9 0x6f 0x00
+# CHECK: vld1.8 {d16[3]}, [r0]
+0xe0 0xf9 0x9f 0x04
+# CHECK: vld1.16 {d16[2]}, [r0, :16]
+0xe0 0xf9 0xbf 0x08
+# CHECK: vld1.32 {d16[1]}, [r0, :32]
+
+0xe0 0xf9 0x3f 0x01
+# CHECK: vld2.8 {d16[1], d17[1]}, [r0, :16]
+0xe0 0xf9 0x5f 0x05
+# CHECK: vld2.16 {d16[1], d17[1]}, [r0, :32]
+0xe0 0xf9 0x8f 0x09
+# CHECK: vld2.32 {d16[1], d17[1]}, [r0]
+0xe0 0xf9 0x6f 0x15
+# CHECK: vld2.16 {d17[1], d19[1]}, [r0]
+0xe0 0xf9 0x5f 0x19
+# CHECK: vld2.32 {d17[0], d19[0]}, [r0, :64]
+
+0xe0 0xf9 0x2f 0x02
+# CHECK: vld3.8 {d16[1], d17[1], d18[1]}, [r0]
+0xe0 0xf9 0x4f 0x06
+# CHECK: vld3.16 {d16[1], d17[1], d18[1]}, [r0]
+0xe0 0xf9 0x8f 0x0a
+# CHECK: vld3.32 {d16[1], d17[1], d18[1]}, [r0]
+0xe0 0xf9 0x6f 0x06
+# CHECK: vld3.16 {d16[1], d18[1], d20[1]}, [r0]
+0xe0 0xf9 0xcf 0x1a
+# CHECK: vld3.32 {d17[1], d19[1], d21[1]}, [r0]
+
+0xe0 0xf9 0x3f 0x03
+# CHECK: vld4.8 {d16[1], d17[1], d18[1], d19[1]}, [r0, :32]
+0xe0 0xf9 0x4f 0x07
+# CHECK: vld4.16 {d16[1], d17[1], d18[1], d19[1]}, [r0]
+0xe0 0xf9 0xaf 0x0b
+# CHECK: vld4.32 {d16[1], d17[1], d18[1], d19[1]}, [r0, :128]
+0xe0 0xf9 0x7f 0x07
+# CHECK: vld4.16 {d16[1], d18[1], d20[1], d22[1]}, [r0, :64]
+0xe0 0xf9 0x4f 0x1b
+# CHECK: vld4.32 {d17[0], d19[0], d21[0], d23[0]}, [r0]
+
+0x40 0xf9 0x1f 0x07
+# CHECK: vst1.8 {d16}, [r0, :64]
+0x40 0xf9 0x4f 0x07
+# CHECK: vst1.16 {d16}, [r0]
+0x40 0xf9 0x8f 0x07
+# CHECK: vst1.32 {d16}, [r0]
+0x40 0xf9 0xcf 0x07
+# CHECK: vst1.64 {d16}, [r0]
+0x40 0xf9 0x1f 0x0a
+# CHECK: vst1.8 {d16, d17}, [r0, :64]
+0x40 0xf9 0x6f 0x0a
+# CHECK: vst1.16 {d16, d17}, [r0, :128]
+0x40 0xf9 0x8f 0x0a
+# CHECK: vst1.32 {d16, d17}, [r0]
+0x40 0xf9 0xcf 0x0a
+# CHECK: vst1.64 {d16, d17}, [r0]
+
+0x40 0xf9 0x1f 0x08
+# CHECK: vst2.8 {d16, d17}, [r0, :64]
+0x40 0xf9 0x6f 0x08
+# CHECK: vst2.16 {d16, d17}, [r0, :128]
+0x40 0xf9 0x8f 0x08
+# CHECK: vst2.32 {d16, d17}, [r0]
+0x40 0xf9 0x1f 0x03
+# CHECK: vst2.8 {d16, d17, d18, d19}, [r0, :64]
+0x40 0xf9 0x6f 0x03
+# CHECK: vst2.16 {d16, d17, d18, d19}, [r0, :128]
+0x40 0xf9 0xbf 0x03
+# CHECK: vst2.32 {d16, d17, d18, d19}, [r0, :256]
+
+0x40 0xf9 0x1f 0x04
+# CHECK: vst3.8 {d16, d17, d18}, [r0, :64]
+0x40 0xf9 0x4f 0x04
+# CHECK: vst3.16 {d16, d17, d18}, [r0]
+0x40 0xf9 0x8f 0x04
+# CHECK: vst3.32 {d16, d17, d18}, [r0]
+0x40 0xf9 0x1d 0x05
+# CHECK: vst3.8 {d16, d18, d20}, [r0, :64]!
+0x40 0xf9 0x1d 0x15
+# CHECK: vst3.8 {d17, d19, d21}, [r0, :64]!
+0x40 0xf9 0x4d 0x05
+# CHECK: vst3.16 {d16, d18, d20}, [r0]!
+0x40 0xf9 0x4d 0x15
+# CHECK: vst3.16 {d17, d19, d21}, [r0]!
+0x40 0xf9 0x8d 0x05
+# CHECK: vst3.32 {d16, d18, d20}, [r0]!
+0x40 0xf9 0x8d 0x15
+# CHECK: vst3.32 {d17, d19, d21}, [r0]!
+
+0x40 0xf9 0x1f 0x00
+# CHECK: vst4.8 {d16, d17, d18, d19}, [r0, :64]
+0x40 0xf9 0x6f 0x00
+# CHECK: vst4.16 {d16, d17, d18, d19}, [r0, :128]
+0x40 0xf9 0x3d 0x01
+# CHECK: vst4.8 {d16, d18, d20, d22}, [r0, :256]!
+0x40 0xf9 0x3d 0x11
+# CHECK: vst4.8 {d17, d19, d21, d23}, [r0, :256]!
+0x40 0xf9 0x4d 0x01
+# CHECK: vst4.16 {d16, d18, d20, d22}, [r0]!
+0x40 0xf9 0x4d 0x11
+# CHECK: vst4.16 {d17, d19, d21, d23}, [r0]!
+0x40 0xf9 0x8d 0x01
+# CHECK: vst4.32 {d16, d18, d20, d22}, [r0]!
+0x40 0xf9 0x8d 0x11
+# CHECK: vst4.32 {d17, d19, d21, d23}, [r0]!
+
+0xc0 0xf9 0x3f 0x01
+# CHECK: vst2.8 {d16[1], d17[1]}, [r0, :16]
+0xc0 0xf9 0x5f 0x05
+# CHECK: vst2.16 {d16[1], d17[1]}, [r0, :32]
+0xc0 0xf9 0x8f 0x09
+# CHECK: vst2.32 {d16[1], d17[1]}, [r0]
+0xc0 0xf9 0x6f 0x15
+# CHECK: vst2.16 {d17[1], d19[1]}, [r0]
+0xc0 0xf9 0x5f 0x19
+# CHECK: vst2.32 {d17[0], d19[0]}, [r0, :64]
+
+0xc0 0xf9 0x2f 0x02
+# CHECK: vst3.8 {d16[1], d17[1], d18[1]}, [r0]
+0xc0 0xf9 0x4f 0x06
+# CHECK: vst3.16 {d16[1], d17[1], d18[1]}, [r0]
+0xc0 0xf9 0x8f 0x0a
+# CHECK: vst3.32 {d16[1], d17[1], d18[1]}, [r0]
+0xc0 0xf9 0xaf 0x16
+# CHECK: vst3.16 {d17[2], d19[2], d21[2]}, [r0]
+0xc0 0xf9 0x4f 0x0a
+# CHECK: vst3.32 {d16[0], d18[0], d20[0]}, [r0]
+
+0xc0 0xf9 0x3f 0x03
+# CHECK: vst4.8 {d16[1], d17[1], d18[1], d19[1]}, [r0, :32]
+0xc0 0xf9 0x4f 0x07
+# CHECK: vst4.16 {d16[1], d17[1], d18[1], d19[1]}, [r0]
+0xc0 0xf9 0xaf 0x0b
+# CHECK: vst4.32 {d16[1], d17[1], d18[1], d19[1]}, [r0, :128]
+0xc0 0xf9 0xff 0x17
+# CHECK: vst4.16 {d17[3], d19[3], d21[3], d23[3]}, [r0, :64]
+0xc0 0xf9 0x4f 0x1b
+# CHECK: vst4.32 {d17[0], d19[0], d21[0], d23[0]}, [r0]
diff --git a/test/MC/Disassembler/ARM/thumb-MSR-MClass.txt b/test/MC/Disassembler/ARM/thumb-MSR-MClass.txt
new file mode 100644
index 0000000..497cb9a
--- /dev/null
+++ b/test/MC/Disassembler/ARM/thumb-MSR-MClass.txt
@@ -0,0 +1,7 @@
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 -mcpu cortex-m3 | FileCheck %s
+
+# CHECK: msr primask, r0
+0x80 0xf3 0x10 0x80
+
+# CHECK: mrs r0, primask
+0xef 0xf3 0x10 0x80
diff --git a/test/MC/Disassembler/ARM/thumb-printf.txt b/test/MC/Disassembler/ARM/thumb-printf.txt
index 6c2c500..8158a73 100644
--- a/test/MC/Disassembler/ARM/thumb-printf.txt
+++ b/test/MC/Disassembler/ARM/thumb-printf.txt
@@ -1,4 +1,4 @@
-# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 | FileCheck %s
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 | FileCheck %s
# CHECK: push {r0, r1, r2, r3}
# CHECK-NEXT: push {r4, r5, r7, lr}
diff --git a/test/MC/Disassembler/ARM/thumb-tests.txt b/test/MC/Disassembler/ARM/thumb-tests.txt
index 895a5bb..18b8f47 100644
--- a/test/MC/Disassembler/ARM/thumb-tests.txt
+++ b/test/MC/Disassembler/ARM/thumb-tests.txt
@@ -1,4 +1,4 @@
-# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 | FileCheck %s
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 -mattr +t2xtpk,+mp | FileCheck %s
# CHECK: add r5, sp, #68
0x11 0xad
@@ -27,7 +27,7 @@
# CHECK: cmn.w r0, #31
0x10 0xf1 0x1f 0x0f
-# CHECK: ldmia r0!, {r1}
+# CHECK: ldm r0!, {r1}
0x02 0xc8
# CHECK: ldr r5, #432
@@ -42,7 +42,7 @@
# CHECK: str r2, [r5, r3]
0xea 0x50
-# CHECK: ldrb.w r8, #-24
+# CHECK: ldrb.w r8, [pc, #-24]
0x1f 0xf8 0x18 0x80
# CHECK: ldrd r0, r1, [r7, #64]!
@@ -112,7 +112,7 @@
# CHECK: lsleq r1, r0, #28
0x01 0x07
-# CHECK: stmiane r0!, {r1, r2, r3}
+# CHECK: stmne r0!, {r1, r2, r3}
0x0e 0xc0
# IT block end
@@ -131,7 +131,7 @@
# CHECK: cpsie aif
0x67 0xb6
-# CHECK: msr cpsr_fc, r0
+# CHECK: msr CPSR_fc, r0
0x80 0xf3 0x00 0x89
# CHECK: blx #-4
@@ -143,16 +143,16 @@
# CHECK: vcmpe.f64 d8, #0
0xb5 0xee 0xc0 0x8b
-# CHECK: stmdb.w sp, {r0, r2, r3, r8, r11, lr}
+# CHECK: stmdb sp, {r0, r2, r3, r8, r11, lr}
0x0d 0xe9 0x0d 0x49
-# CHECK: stmia r5!, {r0, r1, r2, r3, r4}
+# CHECK: stm r5!, {r0, r1, r2, r3, r4}
0x1f 0xc5
-# CHECK: ldmia r5, {r0, r1, r2, r3, r4, r5}
+# CHECK: ldm r5, {r0, r1, r2, r3, r4, r5}
0x3f 0xcd
-# CHECK: ldmia r5!, {r0, r1, r2, r3, r4}
+# CHECK: ldm r5!, {r0, r1, r2, r3, r4}
0x1f 0xcd
# CHECK: addw r0, pc, #1050
@@ -218,7 +218,7 @@
# CHECK: pld [r5, #30]
0x95 0xf8 0x1e 0xf0
-# CHECK: stc2 p12, cr15, [r9], {137}
+# CHECK: stc2 p12, c15, [r9], {137}
0x89 0xfc 0x89 0xfc
# CHECK: vmov r1, r0, d11
@@ -265,3 +265,39 @@
# CHECK: bne #24
0x0c 0xd1
+
+# CHECK: vadd.f32 q0, q1, q2
+0x02 0xef 0x44 0x0d
+
+# CHECK: ldrsb r1, [r0, r0]
+0x01 0x56
+
+# CHECK: ldrsh r1, [r0, r0]
+0x01 0x5E
+
+# CHECK: and.w r5, r1, r10, ror #7
+0x1 0xea 0xfa 0x95
+
+# CHECK: ldrsh r6, [sp], #81
+0x3d 0xf9 0x51 0x6b
+
+# CHECK: usat16 r4, #10, r1
+0xa1 0xf3 0x0a 0x04
+
+# CHECK: smlad r5, r12, r8, r11
+0x2c 0xfb 0x8 0xb5
+
+# CHECK: teq.w r0, r11
+0x90 0xea 0xb 0x8f
+
+# CHECK: uxtb16 r9, r12, ror #16
+0x3f 0xfa 0xec 0xf9
+
+# CHECK: pldw [r11, r12, lsl #2]
+0x3b 0xf8 0x2c 0xf0
+
+# CHECK: msr CPSR_fc, r0
+0x80 0xf3 0x00 0x89
+
+# CHECK: mrs r0, apsr
+0xef 0xf3 0x00 0x80
diff --git a/test/MC/Disassembler/ARM/thumb1.txt b/test/MC/Disassembler/ARM/thumb1.txt
new file mode 100644
index 0000000..17c4bad
--- /dev/null
+++ b/test/MC/Disassembler/ARM/thumb1.txt
@@ -0,0 +1,530 @@
+# RUN: llvm-mc -triple=thumbv6-apple-darwin -disassemble < %s | FileCheck %s
+
+#------------------------------------------------------------------------------
+# ADC (register)
+#------------------------------------------------------------------------------
+# CHECK: adcs r4, r6
+
+0x74 0x41
+
+
+#------------------------------------------------------------------------------
+# ADD (immediate)
+#------------------------------------------------------------------------------
+# CHECK: adds r1, r2, #3
+# CHECK: adds r2, r2, #3
+# CHECK: adds r2, #8
+
+0xd1 0x1c
+0xd2 0x1c
+0x08 0x32
+
+#------------------------------------------------------------------------------
+# ADD (register)
+#------------------------------------------------------------------------------
+# CHECK: adds r1, r2, r3
+# CHECK: add r2, r8
+
+0xd1 0x18
+0x42 0x44
+
+#------------------------------------------------------------------------------
+# ADD (SP plus immediate)
+#------------------------------------------------------------------------------
+# CHECK: add sp, #508
+# CHECK: add sp, #4
+# CHECK: add r2, sp, #8
+# CHECK: add r2, sp, #1020
+
+0x7f 0xb0
+0x01 0xb0
+0x02 0xaa
+0xff 0xaa
+
+
+#------------------------------------------------------------------------------
+# ADD (SP plus register)
+#------------------------------------------------------------------------------
+# CHECK: add sp, r3
+# CHECK: add r2, sp, r2
+
+0x9d 0x44
+0x6a 0x44
+
+#------------------------------------------------------------------------------
+# ADR
+#------------------------------------------------------------------------------
+# CHECK: adr r2, #3
+0x03 0xa2
+
+#------------------------------------------------------------------------------
+# ASR (immediate)
+#------------------------------------------------------------------------------
+# CHECK: asrs r2, r3, #32
+# CHECK: asrs r2, r3, #5
+# CHECK: asrs r2, r3, #1
+
+0x1a 0x10
+0x5a 0x11
+0x5a 0x10
+
+#------------------------------------------------------------------------------
+# ASR (register)
+#------------------------------------------------------------------------------
+# CHECK: asrs r5, r2
+
+0x15 0x41
+
+#------------------------------------------------------------------------------
+# BICS
+#------------------------------------------------------------------------------
+# CHECK: bics r1, r6
+
+0xb1 0x43
+
+#------------------------------------------------------------------------------
+# BKPT
+#------------------------------------------------------------------------------
+# CHECK: bkpt #0
+# CHECK: bkpt #255
+
+0x00 0xbe
+0xff 0xbe
+
+#------------------------------------------------------------------------------
+# BLX (register)
+#------------------------------------------------------------------------------
+# CHECK: blx r4
+
+0xa0 0x47
+
+#------------------------------------------------------------------------------
+# BX
+#------------------------------------------------------------------------------
+# CHECK: bx r2
+
+0x10 0x47
+
+#------------------------------------------------------------------------------
+# CMN
+#------------------------------------------------------------------------------
+# CHECK: cmn r5, r1
+
+0xcd 0x42
+
+#------------------------------------------------------------------------------
+# CMP
+#------------------------------------------------------------------------------
+# CHECK: cmp r6, #32
+# CHECK: cmp r3, r4
+# CHECK: cmp r8, r1
+
+0x20 0x2e
+0xa3 0x42
+0x88 0x45
+
+#------------------------------------------------------------------------------
+# EOR
+#------------------------------------------------------------------------------
+# CHECK: eors r4, r5
+
+0x6c 0x40
+
+#------------------------------------------------------------------------------
+# LDM
+#------------------------------------------------------------------------------
+# CHECK: ldm r3, {r0, r1, r2, r3, r4, r5, r6, r7}
+# CHECK: ldm r2!, {r1, r3, r4, r5, r7}
+# CHECK: ldm r1, {r1}
+
+0xff 0xcb
+0xba 0xca
+0x02 0xc9
+
+
+#------------------------------------------------------------------------------
+# LDR (immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldr r1, [r5]
+# CHECK: ldr r2, [r6, #32]
+# CHECK: ldr r3, [r7, #124]
+# CHECK: ldr r1, [sp]
+# CHECK: ldr r2, [sp, #24]
+# CHECK: ldr r3, [sp, #1020]
+
+
+0x29 0x68
+0x32 0x6a
+0xfb 0x6f
+0x00 0x99
+0x06 0x9a
+0xff 0x9b
+
+#------------------------------------------------------------------------------
+# LDR (register)
+#------------------------------------------------------------------------------
+# CHECK: ldr r1, [r2, r3]
+
+0xd1 0x58
+
+
+#------------------------------------------------------------------------------
+# LDRB (immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrb r4, [r3]
+# CHECK: ldrb r5, [r6]
+# CHECK: ldrb r6, [r7, #31]
+
+0x1c 0x78
+0x35 0x78
+0xfe 0x7f
+
+
+#------------------------------------------------------------------------------
+# LDRB (register)
+#------------------------------------------------------------------------------
+# CHECK: ldrb r6, [r4, r5]
+
+0x66 0x5d
+
+
+#------------------------------------------------------------------------------
+# LDRH (immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrh r3, [r3]
+# CHECK: ldrh r4, [r6, #2]
+# CHECK: ldrh r5, [r7, #62]
+
+0x1b 0x88
+0x74 0x88
+0xfd 0x8f
+
+#------------------------------------------------------------------------------
+# LDRH (register)
+#------------------------------------------------------------------------------
+# CHECK: ldrh r6, [r2, r6]
+
+0x96 0x5b
+
+
+#------------------------------------------------------------------------------
+# LDRSB/LDRSH
+#------------------------------------------------------------------------------
+# CHECK: ldrsb r6, [r2, r6]
+# CHECK: ldrsh r3, [r7, r1]
+
+0x96 0x57
+0x7b 0x5e
+
+#------------------------------------------------------------------------------
+# LSL (immediate)
+#------------------------------------------------------------------------------
+# CHECK: movs r4, r5
+# CHECK: lsls r4, r5, #4
+
+0x2c 0x00
+0x2c 0x01
+
+
+#------------------------------------------------------------------------------
+# LSL (register)
+#------------------------------------------------------------------------------
+# CHECK: lsls r2, r6
+
+0xb2 0x40
+
+
+#------------------------------------------------------------------------------
+# LSR (immediate)
+#------------------------------------------------------------------------------
+# CHECK: lsrs r1, r3, #1
+# CHECK: lsrs r1, r3, #32
+
+0x59 0x08
+0x19 0x08
+
+
+#------------------------------------------------------------------------------
+# LSR (register)
+#------------------------------------------------------------------------------
+# CHECK: lsrs r2, r6
+
+0xf2 0x40
+
+#------------------------------------------------------------------------------
+# MOV (immediate)
+#------------------------------------------------------------------------------
+# CHECK: movs r2, #0
+# CHECK: movs r2, #255
+# CHECK: movs r2, #23
+
+0x00 0x22
+0xff 0x22
+0x17 0x22
+
+
+#------------------------------------------------------------------------------
+# MOV (register)
+#------------------------------------------------------------------------------
+# CHECK: mov r3, r4
+# CHECK: movs r1, r3
+
+0x23 0x46
+0x19 0x00
+
+
+#------------------------------------------------------------------------------
+# MUL
+#------------------------------------------------------------------------------
+# CHECK: muls r1, r2, r1
+# CHECK: muls r3, r4
+
+0x51 0x43
+0x63 0x43
+
+
+#------------------------------------------------------------------------------
+# MVN
+#------------------------------------------------------------------------------
+# CHECK: mvns r6, r3
+
+0xde 0x43
+
+#------------------------------------------------------------------------------
+# NEG
+#------------------------------------------------------------------------------
+# CHECK: rsbs r3, r4, #0
+
+0x63 0x42
+
+
+#------------------------------------------------------------------------------
+# NOP
+#------------------------------------------------------------------------------
+# CHECK: nop
+
+0xc0 0x46
+
+
+#------------------------------------------------------------------------------
+# ORR
+#------------------------------------------------------------------------------
+# CHECK: orrs r3, r4
+
+0x23 0x43
+
+#------------------------------------------------------------------------------
+# POP
+#------------------------------------------------------------------------------
+# CHECK: pop {r2, r3, r6}
+
+0x4c 0xbc
+
+
+#------------------------------------------------------------------------------
+# PUSH
+#------------------------------------------------------------------------------
+# CHECK: push {r1, r2, r7}
+
+0x86 0xb4
+
+
+#------------------------------------------------------------------------------
+# REV/REV16/REVSH
+#------------------------------------------------------------------------------
+# CHECK: rev r6, r3
+# CHECK: rev16 r7, r2
+# CHECK: revsh r5, r1
+
+0x1e 0xba
+0x57 0xba
+0xcd 0xba
+
+
+#------------------------------------------------------------------------------
+# ROR
+#------------------------------------------------------------------------------
+# CHECK: rors r2, r7
+
+0xfa 0x41
+
+#------------------------------------------------------------------------------
+# RSB
+#------------------------------------------------------------------------------
+# CHECK: rsbs r1, r3, #0
+
+0x59 0x42
+
+
+#------------------------------------------------------------------------------
+# SBC
+#------------------------------------------------------------------------------
+# CHECK: sbcs r4, r3
+
+0x9c 0x41
+
+
+#------------------------------------------------------------------------------
+# SETEND
+#------------------------------------------------------------------------------
+# CHECK: setend be
+# CHECK: setend le
+
+0x58 0xb6
+0x50 0xb6
+
+#------------------------------------------------------------------------------
+# STM
+#------------------------------------------------------------------------------
+# CHECK: stm r1!, {r2, r6}
+# CHECK: stm r1!, {r1, r2, r3, r7}
+
+0x44 0xc1
+0x8e 0xc1
+
+
+#------------------------------------------------------------------------------
+# STR (immediate)
+#------------------------------------------------------------------------------
+# CHECK: str r2, [r7]
+# CHECK: str r2, [r7]
+# CHECK: str r5, [r1, #4]
+# CHECK: str r3, [r7, #124]
+# CHECK: str r2, [sp]
+# CHECK: str r3, [sp]
+# CHECK: str r4, [sp, #20]
+# CHECK: str r5, [sp, #1020]
+
+0x3a 0x60
+0x3a 0x60
+0x4d 0x60
+0xfb 0x67
+0x00 0x92
+0x00 0x93
+0x05 0x94
+0xff 0x95
+
+
+#------------------------------------------------------------------------------
+# STR (register)
+#------------------------------------------------------------------------------
+# CHECK: str r2, [r7, r3]
+
+0xfa 0x50
+
+
+#------------------------------------------------------------------------------
+# STRB (immediate)
+#------------------------------------------------------------------------------
+# CHECK: strb r4, [r3]
+# CHECK: strb r5, [r6]
+# CHECK: strb r6, [r7, #31]
+
+0x1c 0x70
+0x35 0x70
+0xfe 0x77
+
+
+#------------------------------------------------------------------------------
+# STRB (register)
+#------------------------------------------------------------------------------
+# CHECK: strb r6, [r4, r5]
+
+0x66 0x55
+
+
+#------------------------------------------------------------------------------
+# STRH (immediate)
+#------------------------------------------------------------------------------
+# CHECK: strh r3, [r3]
+# CHECK: strh r4, [r6, #2]
+# CHECK: strh r5, [r7, #62]
+
+0x1b 0x80
+0x74 0x80
+0xfd 0x87
+
+
+#------------------------------------------------------------------------------
+# STRH (register)
+#------------------------------------------------------------------------------
+# CHECK: strh r6, [r2, r6]
+
+0x96 0x53
+
+
+#------------------------------------------------------------------------------
+# SUB (immediate)
+#------------------------------------------------------------------------------
+# CHECK: subs r1, r2, #3
+# CHECK: subs r2, #3
+# CHECK: subs r2, #8
+
+0xd1 0x1e
+0x03 0x3a
+0x08 0x3a
+
+#------------------------------------------------------------------------------
+# SUB (register)
+#------------------------------------------------------------------------------
+# CHECK: subs r1, r2, r3
+
+0xd1 0x1a
+
+#------------------------------------------------------------------------------
+# SUB (SP minus immediate)
+#------------------------------------------------------------------------------
+# CHECK: sub sp, #12
+# CHECK: sub sp, #508
+
+0x83 0xb0
+0xff 0xb0
+
+#------------------------------------------------------------------------------
+# SVC
+#------------------------------------------------------------------------------
+# CHECK: svc #0
+# CHECK: svc #255
+
+0x00 0xdf
+0xff 0xdf
+
+
+#------------------------------------------------------------------------------
+# SXTB/SXTH
+#------------------------------------------------------------------------------
+# CHECK: sxtb r3, r5
+# CHECK: sxth r3, r5
+
+0x6b 0xb2
+0x2b 0xb2
+
+
+#------------------------------------------------------------------------------
+# TST
+#------------------------------------------------------------------------------
+# CHECK: tst r6, r1
+
+0x0e 0x42
+
+
+#------------------------------------------------------------------------------
+# UXTB/UXTH
+#------------------------------------------------------------------------------
+# CHECK: uxtb r7, r2
+# CHECK: uxth r1, r4
+
+0xd7 0xb2
+0xa1 0xb2
+
+
+#------------------------------------------------------------------------------
+# WFE/WFI/YIELD
+#------------------------------------------------------------------------------
+# CHECK: wfe
+# CHECK: wfi
+# CHECK: yield
+
+0x20 0xbf
+0x30 0xbf
+0x10 0xbf
diff --git a/test/MC/Disassembler/ARM/thumb2.txt b/test/MC/Disassembler/ARM/thumb2.txt
new file mode 100644
index 0000000..ed8d988
--- /dev/null
+++ b/test/MC/Disassembler/ARM/thumb2.txt
@@ -0,0 +1,2558 @@
+# RUN: llvm-mc -triple=thumbv7-apple-darwin -disassemble < %s | FileCheck %s
+
+#------------------------------------------------------------------------------
+# ADC (immediate)
+#------------------------------------------------------------------------------
+# CHECK: adc r0, r1, #4
+# CHECK: adcs r0, r1, #0
+# CHECK: adc r1, r2, #255
+# CHECK: adc r3, r7, #5570645
+# CHECK: adc r8, r12, #2852170240
+# CHECK: adc r9, r7, #2779096485
+# CHECK: adc r5, r3, #2264924160
+# CHECK: adc r4, r2, #2139095040
+# CHECK: adc r4, r2, #1664
+
+0x41 0xf1 0x04 0x00
+0x51 0xf1 0x00 0x00
+0x42 0xf1 0xff 0x01
+0x47 0xf1 0x55 0x13
+0x4c 0xf1 0xaa 0x28
+0x47 0xf1 0xa5 0x39
+0x43 0xf1 0x07 0x45
+0x42 0xf1 0xff 0x44
+0x42 0xf5 0xd0 0x64
+
+#------------------------------------------------------------------------------
+# ADC (register)
+#------------------------------------------------------------------------------
+# CHECK: adc.w r4, r5, r6
+# CHECK: adcs.w r4, r5, r6
+# CHECK: adc.w r9, r1, r3
+# CHECK: adcs.w r9, r1, r3
+# CHECK: adc.w r0, r1, r3, ror #4
+# CHECK: adcs.w r0, r1, r3, lsl #7
+# CHECK: adc.w r0, r1, r3, lsr #31
+# CHECK: adcs.w r0, r1, r3, asr #32
+
+0x45 0xeb 0x06 0x04
+0x55 0xeb 0x06 0x04
+0x41 0xeb 0x03 0x09
+0x51 0xeb 0x03 0x09
+0x41 0xeb 0x33 0x10
+0x51 0xeb 0xc3 0x10
+0x41 0xeb 0xd3 0x70
+0x51 0xeb 0x23 0x00
+
+
+#------------------------------------------------------------------------------
+# ADD (immediate)
+#------------------------------------------------------------------------------
+# CHECK: itet eq
+# CHECK: addeq r1, r2, #4
+# CHECK: addwne r5, r3, #1023
+# CHECK: addweq r4, r5, #293
+# CHECK: add.w r2, sp, #1024
+# CHECK: add.w r2, r8, #65280
+# CHECK: addw r2, r3, #257
+# CHECK: add.w r12, r6, #256
+# CHECK: addw r12, r6, #256
+# CHECK: adds.w r1, r2, #496
+
+0x0a 0xbf
+0x11 0x1d
+0x03 0xf2 0xff 0x35
+0x05 0xf2 0x25 0x14
+0x0d 0xf5 0x80 0x62
+0x08 0xf5 0x7f 0x42
+0x03 0xf2 0x01 0x12
+0x06 0xf5 0x80 0x7c
+0x06 0xf2 0x00 0x1c
+0x12 0xf5 0xf8 0x71
+
+
+#------------------------------------------------------------------------------
+# ADD (register)
+#------------------------------------------------------------------------------
+# CHECK: add.w r1, r2, r8
+# CHECK: add.w r5, r9, r2, asr #32
+# CHECK: adds.w r7, r3, r1, lsl #31
+# CHECK: adds.w r0, r3, r6, lsr #25
+# CHECK: add.w r4, r8, r1, ror #12
+
+0x02 0xeb 0x08 0x01
+0x09 0xeb 0x22 0x05
+0x13 0xeb 0xc1 0x77
+0x13 0xeb 0x56 0x60
+0x08 0xeb 0x31 0x34
+
+
+#------------------------------------------------------------------------------
+# ADR
+#------------------------------------------------------------------------------
+# CHECK: subw r11, pc, #3270
+# CHECK: subw r11, pc, #826
+
+0xaf 0xf6 0xc6 0x4b
+0xaf 0xf2 0x3a 0x3b
+
+#------------------------------------------------------------------------------
+# AND (immediate)
+#------------------------------------------------------------------------------
+# CHECK: and r2, r5, #1044480
+# CHECK: ands r3, r12, #15
+# CHECK: and r1, r1, #255
+
+0x05 0xf4 0x7f 0x22
+0x1c 0xf0 0x0f 0x03
+0x01 0xf0 0xff 0x01
+
+
+#------------------------------------------------------------------------------
+# AND (register)
+#------------------------------------------------------------------------------
+# CHECK: and.w r4, r9, r8
+# CHECK: and.w r1, r4, r8, asr #3
+# CHECK: ands.w r2, r1, r7, lsl #1
+# CHECK: ands.w r4, r5, r2, lsr #20
+# CHECK: and.w r9, r12, r1, ror #17
+
+0x09 0xea 0x08 0x04
+0x04 0xea 0xe8 0x01
+0x11 0xea 0x47 0x02
+0x15 0xea 0x12 0x54
+0x0c 0xea 0x71 0x49
+
+#------------------------------------------------------------------------------
+# ASR (immediate)
+#------------------------------------------------------------------------------
+# CHECK: asr.w r2, r3, #12
+# CHECK: asrs.w r8, r3, #32
+# CHECK: asrs.w r2, r3, #1
+# CHECK: asr.w r2, r3, #4
+# CHECK: asrs.w r2, r12, #15
+
+# CHECK: asr.w r3, r3, #19
+# CHECK: asrs.w r8, r8, #2
+# CHECK: asrs.w r7, r7, #5
+# CHECK: asr.w r12, r12, #21
+
+0x4f 0xea 0x23 0x32
+0x5f 0xea 0x23 0x08
+0x5f 0xea 0x63 0x02
+0x4f 0xea 0x23 0x12
+0x5f 0xea 0xec 0x32
+
+0x4f 0xea 0xe3 0x43
+0x5f 0xea 0xa8 0x08
+0x5f 0xea 0x67 0x17
+0x4f 0xea 0x6c 0x5c
+
+
+#------------------------------------------------------------------------------
+# ASR (register)
+#------------------------------------------------------------------------------
+# CHECK: asr.w r3, r4, r2
+# CHECK: asr.w r1, r1, r2
+# CHECK: asrs.w r3, r4, r8
+
+0x44 0xfa 0x02 0xf3
+0x41 0xfa 0x02 0xf1
+0x54 0xfa 0x08 0xf3
+
+#------------------------------------------------------------------------------
+# B
+#------------------------------------------------------------------------------
+# CHECK: bmi.w #-183396
+
+0x13 0xf5 0xce 0xa9
+
+
+#------------------------------------------------------------------------------
+# BFC
+#------------------------------------------------------------------------------
+# CHECK: bfc r5, #3, #17
+# CHECK: it lo
+# CHECK: bfclo r5, #3, #17
+
+0x6f 0xf3 0xd3 0x05
+0x38 0xbf
+0x6f 0xf3 0xd3 0x05
+
+
+#------------------------------------------------------------------------------
+# BFI
+#------------------------------------------------------------------------------
+# CHECK: bfi r5, r2, #3, #17
+# CHECK: it ne
+# CHECK: bfine r5, r2, #3, #17
+# CHECK: bfi r6, r0, #0, #32
+# CHECK: bfi r6, r0, #31, #1
+
+0x62 0xf3 0xd3 0x05
+0x18 0xbf
+0x62 0xf3 0xd3 0x05
+0x60 0xf3 0x1f 0x06
+0x60 0xf3 0xdf 0x76
+
+
+#------------------------------------------------------------------------------
+# BIC
+#------------------------------------------------------------------------------
+# CHECK: bic r10, r1, #15
+# CHECK: bic.w r12, r3, r6
+# CHECK: bic.w r11, r2, r6, lsl #12
+# CHECK: bic.w r8, r4, r1, lsr #11
+# CHECK: bic.w r7, r5, r7, lsr #15
+# CHECK: bic.w r6, r7, r9, asr #32
+# CHECK: bic.w r5, r6, r8, ror #1
+
+# CHECK: bic r1, r1, #15
+# CHECK: bic.w r1, r1, r1
+# CHECK: bic.w r4, r4, r2, lsl #31
+# CHECK: bic.w r6, r6, r3, lsr #12
+# CHECK: bic.w r7, r7, r4, lsr #7
+# CHECK: bic.w r8, r8, r5, asr #15
+# CHECK: bic.w r12, r12, r6, ror #29
+
+0x21 0xf0 0x0f 0x0a
+0x23 0xea 0x06 0x0c
+0x22 0xea 0x06 0x3b
+0x24 0xea 0xd1 0x28
+0x25 0xea 0xd7 0x37
+0x27 0xea 0x29 0x06
+0x26 0xea 0x78 0x05
+
+0x21 0xf0 0x0f 0x01
+0x21 0xea 0x01 0x01
+0x24 0xea 0xc2 0x74
+0x26 0xea 0x13 0x36
+0x27 0xea 0xd4 0x17
+0x28 0xea 0xe5 0x38
+0x2c 0xea 0x76 0x7c
+
+
+#------------------------------------------------------------------------------
+# BXJ
+#------------------------------------------------------------------------------
+# CHECK: bxj r5
+# CHECK: it ne
+# CHECK: bxjne r7
+
+0xc5 0xf3 0x00 0x8f
+0x18 0xbf
+0xc7 0xf3 0x00 0x8f
+
+
+#------------------------------------------------------------------------------
+# CBZ/CBNZ
+#------------------------------------------------------------------------------
+# CHECK: cbnz r7, #6
+# CHECK: cbnz r7, #12
+
+0x1f 0xb9
+0x37 0xb9
+
+#------------------------------------------------------------------------------
+# CDP/CDP2
+#------------------------------------------------------------------------------
+# CHECK: cdp p7, #1, c1, c1, c1, #4
+# CHECK: cdp2 p7, #1, c1, c1, c1, #4
+
+0x11 0xee 0x81 0x17
+0x11 0xfe 0x81 0x17
+
+
+#------------------------------------------------------------------------------
+# CLREX
+#------------------------------------------------------------------------------
+#CHECK: clrex
+#CHECK: it ne
+#CHECK: clrexne
+
+0xbf 0xf3 0x2f 0x8f
+0x18 0xbf
+0xbf 0xf3 0x2f 0x8f
+
+
+#------------------------------------------------------------------------------
+# CLZ
+#------------------------------------------------------------------------------
+#CHECK: clz r1, r2
+#CHECK: it eq
+#CHECK: clzeq r1, r2
+
+0xb2 0xfa 0x82 0xf1
+0x08 0xbf
+0xb2 0xfa 0x82 0xf1
+
+
+#------------------------------------------------------------------------------
+# CMN
+#------------------------------------------------------------------------------
+#CHECK: cmn.w r1, #15
+#CHECK: cmn.w r8, r6
+#CHECK: cmn.w r1, r6, lsl #10
+#CHECK: cmn.w r1, r6, lsr #10
+#CHECK: cmn.w sp, r6, lsr #10
+#CHECK: cmn.w r1, r6, asr #10
+#CHECK: cmn.w r1, r6, ror #10
+
+0x11 0xf1 0x0f 0x0f
+0x18 0xeb 0x06 0x0f
+0x11 0xeb 0x86 0x2f
+0x11 0xeb 0x96 0x2f
+0x1d 0xeb 0x96 0x2f
+0x11 0xeb 0xa6 0x2f
+0x11 0xeb 0xb6 0x2f
+
+
+#------------------------------------------------------------------------------
+# CMP
+#------------------------------------------------------------------------------
+#CHECK: cmp.w r5, #65280
+#CHECK: cmp.w r4, r12
+#CHECK: cmp.w r9, r6, lsl #12
+#CHECK: cmp.w r3, r7, lsr #31
+#CHECK: cmp.w sp, r6, lsr #1
+#CHECK: cmp.w r2, r5, asr #24
+#CHECK: cmp.w r1, r4, ror #15
+
+0xb5 0xf5 0x7f 0x4f
+0xb4 0xeb 0x0c 0x0f
+0xb9 0xeb 0x06 0x3f
+0xb3 0xeb 0xd7 0x7f
+0xbd 0xeb 0x56 0x0f
+0xb2 0xeb 0x25 0x6f
+0xb1 0xeb 0xf4 0x3f
+
+
+#------------------------------------------------------------------------------
+# DBG
+#------------------------------------------------------------------------------
+#CHECK: dbg #5
+#CHECK: dbg #0
+#CHECK: dbg #15
+
+0xaf 0xf3 0xf5 0x80
+0xaf 0xf3 0xf0 0x80
+0xaf 0xf3 0xff 0x80
+
+
+#------------------------------------------------------------------------------
+# DMB
+#------------------------------------------------------------------------------
+#CHECK: dmb sy
+#CHECK: dmb st
+#CHECK: dmb ish
+#CHECK: dmb ishst
+#CHECK: dmb nsh
+#CHECK: dmb nshst
+#CHECK: dmb osh
+#CHECK: dmb oshst
+#CHECK: dmb
+
+0xbf 0xf3 0x5f 0x8f
+0xbf 0xf3 0x5e 0x8f
+0xbf 0xf3 0x5b 0x8f
+0xbf 0xf3 0x5a 0x8f
+0xbf 0xf3 0x57 0x8f
+0xbf 0xf3 0x56 0x8f
+0xbf 0xf3 0x53 0x8f
+0xbf 0xf3 0x52 0x8f
+0xbf 0xf3 0x5f 0x8f
+
+
+#------------------------------------------------------------------------------
+# DSB
+#------------------------------------------------------------------------------
+#CHECK: dsb sy
+#CHECK: dsb st
+#CHECK: dsb ish
+#CHECK: dsb ishst
+#CHECK: dsb nsh
+#CHECK: dsb nshst
+#CHECK: dsb osh
+#CHECK: dsb oshst
+
+0xbf 0xf3 0x4f 0x8f
+0xbf 0xf3 0x4e 0x8f
+0xbf 0xf3 0x4b 0x8f
+0xbf 0xf3 0x4a 0x8f
+0xbf 0xf3 0x47 0x8f
+0xbf 0xf3 0x46 0x8f
+0xbf 0xf3 0x43 0x8f
+0xbf 0xf3 0x42 0x8f
+
+
+#------------------------------------------------------------------------------
+# EOR
+#------------------------------------------------------------------------------
+#CHECK: eor r4, r5, #61440
+#CHECK: eor.w r4, r5, r6
+#CHECK: eor.w r4, r5, r6, lsl #5
+#CHECK: eor.w r4, r5, r6, lsr #5
+#CHECK: eor.w r4, r5, r6, lsr #5
+#CHECK: eor.w r4, r5, r6, asr #5
+#CHECK: eor.w r4, r5, r6, ror #5
+
+0x85 0xf4 0x70 0x44
+0x85 0xea 0x06 0x04
+0x85 0xea 0x46 0x14
+0x85 0xea 0x56 0x14
+0x85 0xea 0x56 0x14
+0x85 0xea 0x66 0x14
+0x85 0xea 0x76 0x14
+
+
+#------------------------------------------------------------------------------
+# ISB
+#------------------------------------------------------------------------------
+#CHECK: isb sy
+
+0xbf 0xf3 0x6f 0x8f
+
+#------------------------------------------------------------------------------
+# IT
+#------------------------------------------------------------------------------
+# Test encodings of a few full IT blocks, not just the IT instruction
+
+# CHECK: iteet eq
+# CHECK: addeq r0, r1, r2
+# CHECK: nopne
+# CHECK: subne r5, r6, r7
+# CHECK: addeq r1, r2, #4
+
+0x0d 0xbf
+0x88 0x18
+0x00 0xbf
+0xf5 0x1b
+0x11 0x1d
+
+# CHECK: ittee ls
+# CHECK: addls r0, r1, r2
+# CHECK: nopls
+# CHECK: subhi r5, r6, r7
+# CHECK: addhi r1, r2, #4
+
+0x99 0xbf
+0x88 0x18
+0x00 0xbf
+0xf5 0x1b
+0x11 0x1d
+
+
+#------------------------------------------------------------------------------
+# LDMIA
+#------------------------------------------------------------------------------
+# CHECK: ldm.w r4, {r4, r5, r8, r9}
+# CHECK: ldm.w r4, {r5, r6}
+# CHECK: ldm.w r5!, {r3, r8}
+# CHECK: ldm.w r4, {r4, r5, r8, r9}
+# CHECK: ldm.w r4, {r5, r6}
+# CHECK: ldm.w r5!, {r3, r8}
+# CHECK: ldm.w r5!, {r1, r2}
+# CHECK: ldm.w r2, {r1, r2}
+
+# CHECK: ldm.w r4, {r4, r5, r8, r9}
+# CHECK: ldm.w r4, {r5, r6}
+# CHECK: ldm.w r5!, {r3, r8}
+# CHECK: ldm.w r4, {r4, r5, r8, r9}
+# CHECK: ldm.w r4, {r5, r6}
+# CHECK: ldm.w r5!, {r3, r8}
+# CHECK: ldm.w r5!, {r3, r8}
+
+0x94 0xe8 0x30 0x03
+0x94 0xe8 0x60 0x00
+0xb5 0xe8 0x08 0x01
+0x94 0xe8 0x30 0x03
+0x94 0xe8 0x60 0x00
+0xb5 0xe8 0x08 0x01
+0xb5 0xe8 0x06 0x00
+0x92 0xe8 0x06 0x00
+
+0x94 0xe8 0x30 0x03
+0x94 0xe8 0x60 0x00
+0xb5 0xe8 0x08 0x01
+0x94 0xe8 0x30 0x03
+0x94 0xe8 0x60 0x00
+0xb5 0xe8 0x08 0x01
+0xb5 0xe8 0x08 0x01
+
+
+#------------------------------------------------------------------------------
+# LDMDB
+#------------------------------------------------------------------------------
+# CHECK: ldmdb r4, {r4, r5, r8, r9}
+# CHECK: ldmdb r4, {r5, r6}
+# CHECK: ldmdb r5!, {r3, r8}
+# CHECK: ldmdb r5!, {r3, r8}
+
+0x14 0xe9 0x30 0x03
+0x14 0xe9 0x60 0x00
+0x35 0xe9 0x08 0x01
+0x35 0xe9 0x08 0x01
+
+
+#------------------------------------------------------------------------------
+# LDR(immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldr r5, [r5, #-4]
+# CHECK: ldr r5, [r6, #32]
+# CHECK: ldr.w r5, [r6, #33]
+# CHECK: ldr.w r5, [r6, #257]
+# CHECK: ldr.w pc, [r7, #257]
+
+0x55 0xf8 0x04 0x5c
+0x35 0x6a
+0xd6 0xf8 0x21 0x50
+0xd6 0xf8 0x01 0x51
+0xd7 0xf8 0x01 0xf1
+
+
+#------------------------------------------------------------------------------
+# LDR(register)
+#------------------------------------------------------------------------------
+# CHECK: ldr.w r1, [r8, r1]
+# CHECK: ldr.w r4, [r5, r2]
+# CHECK: ldr.w r6, [r0, r2, lsl #3]
+# CHECK: ldr.w r8, [r8, r2, lsl #2]
+# CHECK: ldr.w r7, [sp, r2, lsl #1]
+# CHECK: ldr.w r7, [sp, r2]
+# CHECK: ldr r2, [r4, #255]!
+# CHECK: ldr r8, [sp, #4]!
+# CHECK: ldr lr, [sp, #-4]!
+# CHECK: ldr r2, [r4], #255
+# CHECK: ldr r8, [sp], #4
+# CHECK: ldr lr, [sp], #-4
+
+0x58 0xf8 0x01 0x10
+0x55 0xf8 0x02 0x40
+0x50 0xf8 0x32 0x60
+0x58 0xf8 0x22 0x80
+0x5d 0xf8 0x12 0x70
+0x5d 0xf8 0x02 0x70
+0x54 0xf8 0xff 0x2f
+0x5d 0xf8 0x04 0x8f
+0x5d 0xf8 0x04 0xed
+0x54 0xf8 0xff 0x2b
+0x5d 0xf8 0x04 0x8b
+0x5d 0xf8 0x04 0xe9
+
+
+#------------------------------------------------------------------------------
+# LDRB(immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrb r5, [r5, #-4]
+# CHECK: ldrb.w r5, [r6, #32]
+# CHECK: ldrb.w r5, [r6, #33]
+# CHECK: ldrb.w r5, [r6, #257]
+# CHECK: ldrb.w lr, [r7, #257]
+
+0x15 0xf8 0x04 0x5c
+0x96 0xf8 0x20 0x50
+0x96 0xf8 0x21 0x50
+0x96 0xf8 0x01 0x51
+0x97 0xf8 0x01 0xe1
+
+
+#------------------------------------------------------------------------------
+# LDRB(register)
+#------------------------------------------------------------------------------
+# CHECK: ldrb.w r1, [r8, r1]
+# CHECK: ldrb.w r4, [r5, r2]
+# CHECK: ldrb.w r6, [r0, r2, lsl #3]
+# CHECK: ldrb.w r8, [r8, r2, lsl #2]
+# CHECK: ldrb.w r7, [sp, r2, lsl #1]
+# CHECK: ldrb.w r7, [sp, r2]
+# CHECK: ldrb r5, [r8, #255]!
+# CHECK: ldrb r2, [r5, #4]!
+# CHECK: ldrb r1, [r4, #-4]!
+# CHECK: ldrb lr, [r3], #255
+# CHECK: ldrb r9, [r2], #4
+# CHECK: ldrb r3, [sp], #-4
+
+0x18 0xf8 0x01 0x10
+0x15 0xf8 0x02 0x40
+0x10 0xf8 0x32 0x60
+0x18 0xf8 0x22 0x80
+0x1d 0xf8 0x12 0x70
+0x1d 0xf8 0x02 0x70
+0x18 0xf8 0xff 0x5f
+0x15 0xf8 0x04 0x2f
+0x14 0xf8 0x04 0x1d
+0x13 0xf8 0xff 0xeb
+0x12 0xf8 0x04 0x9b
+0x1d 0xf8 0x04 0x39
+
+
+#------------------------------------------------------------------------------
+# LDRBT
+#------------------------------------------------------------------------------
+# CHECK: ldrbt r1, [r2]
+# CHECK: ldrbt r1, [r8]
+# CHECK: ldrbt r1, [r8, #3]
+# CHECK: ldrbt r1, [r8, #255]
+
+0x12 0xf8 0x00 0x1e
+0x18 0xf8 0x00 0x1e
+0x18 0xf8 0x03 0x1e
+0x18 0xf8 0xff 0x1e
+
+
+#------------------------------------------------------------------------------
+# LDRD(immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrd r3, r5, [r6, #24]
+# CHECK: ldrd r3, r5, [r6, #24]!
+# CHECK: ldrd r3, r5, [r6], #4
+# CHECK: ldrd r3, r5, [r6], #-8
+# CHECK: ldrd r3, r5, [r6]
+# CHECK: ldrd r8, r1, [r3]
+
+0xd6 0xe9 0x06 0x35
+0xf6 0xe9 0x06 0x35
+0xf6 0xe8 0x01 0x35
+0x76 0xe8 0x02 0x35
+0xd6 0xe9 0x00 0x35
+0xd3 0xe9 0x00 0x81
+
+
+#------------------------------------------------------------------------------
+# FIXME: LDRD(literal)
+#------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------
+# LDREX/LDREXB/LDREXH/LDREXD
+#------------------------------------------------------------------------------
+# CHECK: ldrex r1, [r4]
+# CHECK: ldrex r8, [r4]
+# CHECK: ldrex r2, [sp, #128]
+# CHECK: ldrexb r5, [r7]
+# CHECK: ldrexh r9, [r12]
+# CHECK: ldrexd r9, r3, [r4]
+
+0x54 0xe8 0x00 0x1f
+0x54 0xe8 0x00 0x8f
+0x5d 0xe8 0x20 0x2f
+0xd7 0xe8 0x4f 0x5f
+0xdc 0xe8 0x5f 0x9f
+0xd4 0xe8 0x7f 0x93
+
+
+#------------------------------------------------------------------------------
+# LDRH(immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrh r5, [r5, #-4]
+# CHECK: ldrh r5, [r6, #32]
+# CHECK: ldrh.w r5, [r6, #33]
+# CHECK: ldrh.w r5, [r6, #257]
+# CHECK: ldrh.w lr, [r7, #257]
+# CHECK: ldrh.w r0, [pc, #-21]
+
+0x35 0xf8 0x04 0x5c
+0x35 0x8c
+0xb6 0xf8 0x21 0x50
+0xb6 0xf8 0x01 0x51
+0xb7 0xf8 0x01 0xe1
+0x3f 0xf8 0x15 0x00
+
+
+#------------------------------------------------------------------------------
+# LDRH(register)
+#------------------------------------------------------------------------------
+# CHECK: ldrh.w r1, [r8, r1]
+# CHECK: ldrh.w r4, [r5, r2]
+# CHECK: ldrh.w r6, [r0, r2, lsl #3]
+# CHECK: ldrh.w r8, [r8, r2, lsl #2]
+# CHECK: ldrh.w r7, [sp, r2, lsl #1]
+# CHECK: ldrh.w r7, [sp, r2]
+# CHECK: ldrh r5, [r8, #255]!
+# CHECK: ldrh r2, [r5, #4]!
+# CHECK: ldrh r1, [r4, #-4]!
+# CHECK: ldrh lr, [r3], #255
+# CHECK: ldrh r9, [r2], #4
+# CHECK: ldrh r3, [sp], #-4
+
+0x38 0xf8 0x01 0x10
+0x35 0xf8 0x02 0x40
+0x30 0xf8 0x32 0x60
+0x38 0xf8 0x22 0x80
+0x3d 0xf8 0x12 0x70
+0x3d 0xf8 0x02 0x70
+0x38 0xf8 0xff 0x5f
+0x35 0xf8 0x04 0x2f
+0x34 0xf8 0x04 0x1d
+0x33 0xf8 0xff 0xeb
+0x32 0xf8 0x04 0x9b
+0x3d 0xf8 0x04 0x39
+
+
+#------------------------------------------------------------------------------
+# LDRSB(immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrsb r5, [r5, #-4]
+# CHECK: ldrsb.w r5, [r6, #32]
+# CHECK: ldrsb.w r5, [r6, #33]
+# CHECK: ldrsb.w r5, [r6, #257]
+# CHECK: ldrsb.w lr, [r7, #257]
+
+0x15 0xf9 0x04 0x5c
+0x96 0xf9 0x20 0x50
+0x96 0xf9 0x21 0x50
+0x96 0xf9 0x01 0x51
+0x97 0xf9 0x01 0xe1
+
+
+#------------------------------------------------------------------------------
+# LDRSB(register)
+#------------------------------------------------------------------------------
+# CHECK: ldrsb.w r1, [r8, r1]
+# CHECK: ldrsb.w r4, [r5, r2]
+# CHECK: ldrsb.w r6, [r0, r2, lsl #3]
+# CHECK: ldrsb.w r8, [r8, r2, lsl #2]
+# CHECK: ldrsb.w r7, [sp, r2, lsl #1]
+# CHECK: ldrsb.w r7, [sp, r2]
+# CHECK: ldrsb r5, [r8, #255]!
+# CHECK: ldrsb r2, [r5, #4]!
+# CHECK: ldrsb r1, [r4, #-4]!
+# CHECK: ldrsb lr, [r3], #255
+# CHECK: ldrsb r9, [r2], #4
+# CHECK: ldrsb r3, [sp], #-4
+
+0x18 0xf9 0x01 0x10
+0x15 0xf9 0x02 0x40
+0x10 0xf9 0x32 0x60
+0x18 0xf9 0x22 0x80
+0x1d 0xf9 0x12 0x70
+0x1d 0xf9 0x02 0x70
+0x18 0xf9 0xff 0x5f
+0x15 0xf9 0x04 0x2f
+0x14 0xf9 0x04 0x1d
+0x13 0xf9 0xff 0xeb
+0x12 0xf9 0x04 0x9b
+0x1d 0xf9 0x04 0x39
+
+
+#------------------------------------------------------------------------------
+# LDRSBT
+#------------------------------------------------------------------------------
+# CHECK: ldrsbt r1, [r2]
+# CHECK: ldrsbt r1, [r8]
+# CHECK: ldrsbt r1, [r8, #3]
+# CHECK: ldrsbt r1, [r8, #255]
+
+0x12 0xf9 0x00 0x1e
+0x18 0xf9 0x00 0x1e
+0x18 0xf9 0x03 0x1e
+0x18 0xf9 0xff 0x1e
+
+
+#------------------------------------------------------------------------------
+# LDRSH(immediate)
+#------------------------------------------------------------------------------
+# CHECK: ldrsh r5, [r5, #-4]
+# CHECK: ldrsh.w r5, [r6, #32]
+# CHECK: ldrsh.w r5, [r6, #33]
+# CHECK: ldrsh.w r5, [r6, #257]
+# CHECK: ldrsh.w lr, [r7, #257]
+# CHECK: ldrsh r10, [r5, #-0]
+
+0x35 0xf9 0x04 0x5c
+0xb6 0xf9 0x20 0x50
+0xb6 0xf9 0x21 0x50
+0xb6 0xf9 0x01 0x51
+0xb7 0xf9 0x01 0xe1
+0x35 0xf9 0x00 0xac
+
+#------------------------------------------------------------------------------
+# LDRSH(register)
+#------------------------------------------------------------------------------
+# CHECK: ldrsh.w r1, [r8, r1]
+# CHECK: ldrsh.w r4, [r5, r2]
+# CHECK: ldrsh.w r6, [r0, r2, lsl #3]
+# CHECK: ldrsh.w r8, [r8, r2, lsl #2]
+# CHECK: ldrsh.w r7, [sp, r2, lsl #1]
+# CHECK: ldrsh.w r7, [sp, r2]
+# CHECK: ldrsh r5, [r8, #255]!
+# CHECK: ldrsh r2, [r5, #4]!
+# CHECK: ldrsh r1, [r4, #-4]!
+# CHECK: ldrsh lr, [r3], #255
+# CHECK: ldrsh r9, [r2], #4
+# CHECK: ldrsh r3, [sp], #-4
+
+0x38 0xf9 0x01 0x10
+0x35 0xf9 0x02 0x40
+0x30 0xf9 0x32 0x60
+0x38 0xf9 0x22 0x80
+0x3d 0xf9 0x12 0x70
+0x3d 0xf9 0x02 0x70
+0x38 0xf9 0xff 0x5f
+0x35 0xf9 0x04 0x2f
+0x34 0xf9 0x04 0x1d
+0x33 0xf9 0xff 0xeb
+0x32 0xf9 0x04 0x9b
+0x3d 0xf9 0x04 0x39
+
+
+#------------------------------------------------------------------------------
+# LDRSHT
+#------------------------------------------------------------------------------
+# CHECK: ldrsht r1, [r2]
+# CHECK: ldrsht r1, [r8]
+# CHECK: ldrsht r1, [r8, #3]
+# CHECK: ldrsht r1, [r8, #255]
+
+0x32 0xf9 0x00 0x1e
+0x38 0xf9 0x00 0x1e
+0x38 0xf9 0x03 0x1e
+0x38 0xf9 0xff 0x1e
+
+
+#------------------------------------------------------------------------------
+# LDRT
+#------------------------------------------------------------------------------
+# CHECK: ldrt r1, [r2]
+# CHECK: ldrt r2, [r6]
+# CHECK: ldrt r3, [r7, #3]
+# CHECK: ldrt r4, [r9, #255]
+
+0x52 0xf8 0x00 0x1e
+0x56 0xf8 0x00 0x2e
+0x57 0xf8 0x03 0x3e
+0x59 0xf8 0xff 0x4e
+
+
+#------------------------------------------------------------------------------
+# LSL (immediate)
+#------------------------------------------------------------------------------
+# CHECK: lsl.w r2, r3, #12
+# CHECK: lsls.w r8, r3, #31
+# CHECK: lsls.w r2, r3, #1
+# CHECK: lsl.w r2, r3, #4
+# CHECK: lsls.w r2, r12, #15
+
+# CHECK: lsl.w r3, r3, #19
+# CHECK: lsls.w r8, r8, #2
+# CHECK: lsls.w r7, r7, #5
+# CHECK: lsl.w r12, r12, #21
+
+0x4f 0xea 0x03 0x32
+0x5f 0xea 0xc3 0x78
+0x5f 0xea 0x43 0x02
+0x4f 0xea 0x03 0x12
+0x5f 0xea 0xcc 0x32
+
+0x4f 0xea 0xc3 0x43
+0x5f 0xea 0x88 0x08
+0x5f 0xea 0x47 0x17
+0x4f 0xea 0x4c 0x5c
+
+
+#------------------------------------------------------------------------------
+# LSL (register)
+#------------------------------------------------------------------------------
+# CHECK: lsl.w r3, r4, r2
+# CHECK: lsl.w r1, r1, r2
+# CHECK: lsls.w r3, r4, r8
+
+0x04 0xfa 0x02 0xf3
+0x01 0xfa 0x02 0xf1
+0x14 0xfa 0x08 0xf3
+
+
+#------------------------------------------------------------------------------
+# LSR (immediate)
+#------------------------------------------------------------------------------
+# CHECK: lsr.w r2, r3, #12
+# CHECK: lsrs.w r8, r3, #32
+# CHECK: lsrs.w r2, r3, #1
+# CHECK: lsr.w r2, r3, #4
+# CHECK: lsrs.w r2, r12, #15
+
+# CHECK: lsr.w r3, r3, #19
+# CHECK: lsrs.w r8, r8, #2
+# CHECK: lsrs.w r7, r7, #5
+# CHECK: lsr.w r12, r12, #21
+
+0x4f 0xea 0x13 0x32
+0x5f 0xea 0x13 0x08
+0x5f 0xea 0x53 0x02
+0x4f 0xea 0x13 0x12
+0x5f 0xea 0xdc 0x32
+
+0x4f 0xea 0xd3 0x43
+0x5f 0xea 0x98 0x08
+0x5f 0xea 0x57 0x17
+0x4f 0xea 0x5c 0x5c
+
+
+#------------------------------------------------------------------------------
+# LSR (register)
+#------------------------------------------------------------------------------
+# CHECK: lsr.w r3, r4, r2
+# CHECK: lsr.w r1, r1, r2
+# CHECK: lsrs.w r3, r4, r8
+
+0x24 0xfa 0x02 0xf3
+0x21 0xfa 0x02 0xf1
+0x34 0xfa 0x08 0xf3
+
+#------------------------------------------------------------------------------
+# MCR/MCR2
+#------------------------------------------------------------------------------
+# CHECK: mcr p7, #1, r5, c1, c1, #4
+# CHECK: mcr2 p7, #1, r5, c1, c1, #4
+
+0x21 0xee 0x91 0x57
+0x21 0xfe 0x91 0x57
+
+
+#------------------------------------------------------------------------------
+# MCRR/MCRR2
+#------------------------------------------------------------------------------
+# CHECK: mcrr p7, #15, r5, r4, c1
+# CHECK: mcrr2 p7, #15, r5, r4, c1
+
+0x44 0xec 0xf1 0x57
+0x44 0xfc 0xf1 0x57
+
+
+#------------------------------------------------------------------------------
+# MLA/MLS
+#------------------------------------------------------------------------------
+# CHECK: mla r1, r2, r3, r4
+# CHECK: mls r1, r2, r3, r4
+
+0x02 0xfb 0x03 0x41
+0x02 0xfb 0x13 0x41
+
+
+#------------------------------------------------------------------------------
+# MOV(immediate)
+#------------------------------------------------------------------------------
+# CHECK: movs r1, #21
+# CHECK: movs.w r1, #21
+# CHECK: movs.w r8, #21
+# CHECK: movw r0, #65535
+# CHECK: movw r1, #43777
+# CHECK: movw r1, #43792
+# CHECK: mov.w r0, #66846720
+# CHECK: mov.w r0, #66846720
+# CHECK: movs.w r0, #66846720
+
+0x15 0x21
+0x5f 0xf0 0x15 0x01
+0x5f 0xf0 0x15 0x08
+0x4f 0xf6 0xff 0x70
+0x4a 0xf6 0x01 0x31
+0x4a 0xf6 0x10 0x31
+0x4f 0xf0 0x7f 0x70
+0x4f 0xf0 0x7f 0x70
+0x5f 0xf0 0x7f 0x70
+
+#------------------------------------------------------------------------------
+# MOVT
+#------------------------------------------------------------------------------
+# CHECK: movt r3, #7
+# CHECK: movt r6, #65535
+# CHECK: it eq
+# CHECK: movteq r4, #4080
+
+0xc0 0xf2 0x07 0x03
+0xcf 0xf6 0xff 0x76
+0x08 0xbf
+0xc0 0xf6 0xf0 0x74
+
+#------------------------------------------------------------------------------
+# MRC/MRC2
+#------------------------------------------------------------------------------
+# CHECK: mrc p14, #0, r1, c1, c2, #4
+# CHECK: mrc2 p14, #0, r1, c1, c2, #4
+
+0x11 0xee 0x92 0x1e
+0x11 0xfe 0x92 0x1e
+
+
+#------------------------------------------------------------------------------
+# MRRC/MRRC2
+#------------------------------------------------------------------------------
+# CHECK: mrrc p7, #1, r5, r4, c1
+# CHECK: mrrc2 p7, #1, r5, r4, c1
+
+0x54 0xec 0x11 0x57
+0x54 0xfc 0x11 0x57
+
+
+#------------------------------------------------------------------------------
+# MRS
+#------------------------------------------------------------------------------
+# CHECK: mrs r8, apsr
+# CHECK: mrs r8, spsr
+
+0xef 0xf3 0x00 0x88
+0xff 0xf3 0x00 0x88
+
+
+#------------------------------------------------------------------------------
+# MSR
+#------------------------------------------------------------------------------
+# CHECK: msr APSR_nzcvq, r1
+# CHECK: msr APSR_g, r2
+# CHECK: msr APSR_nzcvq, r3
+# CHECK: msr APSR_nzcvq, r4
+# CHECK: msr APSR_nzcvqg, r5
+# CHECK: msr CPSR_fc, r6
+# CHECK: msr CPSR_c, r7
+# CHECK: msr CPSR_x, r8
+# CHECK: msr CPSR_fc, r9
+# CHECK: msr CPSR_fc, r11
+# CHECK: msr CPSR_fsx, r12
+# CHECK: msr SPSR_fc, r0
+# CHECK: msr SPSR_fsxc, r5
+# CHECK: msr CPSR_fsxc, r8
+
+0x81 0xf3 0x00 0x88
+0x82 0xf3 0x00 0x84
+0x83 0xf3 0x00 0x88
+0x84 0xf3 0x00 0x88
+0x85 0xf3 0x00 0x8c
+0x86 0xf3 0x00 0x89
+0x87 0xf3 0x00 0x81
+0x88 0xf3 0x00 0x82
+0x89 0xf3 0x00 0x89
+0x8b 0xf3 0x00 0x89
+0x8c 0xf3 0x00 0x8e
+0x90 0xf3 0x00 0x89
+0x95 0xf3 0x00 0x8f
+0x88 0xf3 0x00 0x8f
+
+
+#------------------------------------------------------------------------------
+# MUL
+#------------------------------------------------------------------------------
+# CHECK: muls r3, r4, r3
+# CHECK: mul r3, r4, r3
+# CHECK: mul r3, r4, r6
+# CHECK: it eq
+# CHECK: muleq r3, r4, r5
+
+0x63 0x43
+0x04 0xfb 0x03 0xf3
+0x04 0xfb 0x06 0xf3
+0x08 0xbf
+0x04 0xfb 0x05 0xf3
+
+
+#------------------------------------------------------------------------------
+# MVN(immediate)
+#------------------------------------------------------------------------------
+# CHECK: mvns r8, #21
+# CHECK: mvn r0, #66846720
+# CHECK: mvns r0, #66846720
+# CHECK: itte eq
+# CHECK: mvnseq r1, #12
+# CHECK: mvneq r1, #12
+# CHECK: mvnne r1, #12
+
+0x7f 0xf0 0x15 0x08
+0x6f 0xf0 0x7f 0x70
+0x7f 0xf0 0x7f 0x70
+0x06 0xbf
+0x7f 0xf0 0x0c 0x01
+0x6f 0xf0 0x0c 0x01
+0x6f 0xf0 0x0c 0x01
+
+
+#------------------------------------------------------------------------------
+# MVN(register)
+#------------------------------------------------------------------------------
+# CHECK: mvn.w r2, r3
+# CHECK: mvns r2, r3
+# CHECK: mvn.w r5, r6, lsl #19
+# CHECK: mvn.w r5, r6, lsr #9
+# CHECK: mvn.w r5, r6, asr #4
+# CHECK: mvn.w r5, r6, ror #6
+# CHECK: mvn.w r5, r6, rrx
+# CHECK: it eq
+# CHECK: mvneq r2, r3
+
+0x6f 0xea 0x03 0x02
+0xda 0x43
+0x6f 0xea 0xc6 0x45
+0x6f 0xea 0x56 0x25
+0x6f 0xea 0x26 0x15
+0x6f 0xea 0xb6 0x15
+0x6f 0xea 0x36 0x05
+0x08 0xbf
+0xda 0x43
+
+#------------------------------------------------------------------------------
+# NOP
+#------------------------------------------------------------------------------
+# CHECK: nop.w
+
+0xaf 0xf3 0x00 0x80
+
+
+#------------------------------------------------------------------------------
+# ORN
+#------------------------------------------------------------------------------
+# CHECK: orn r4, r5, #61440
+# CHECK: orn r4, r5, r6
+# CHECK: orns r4, r5, r6
+# CHECK: orn r4, r5, r6, lsl #5
+# CHECK: orns r4, r5, r6, lsr #5
+# CHECK: orn r4, r5, r6, lsr #5
+# CHECK: orns r4, r5, r6, asr #5
+# CHECK: orn r4, r5, r6, ror #5
+
+0x65 0xf4 0x70 0x44
+0x65 0xea 0x06 0x04
+0x75 0xea 0x06 0x04
+0x65 0xea 0x46 0x14
+0x75 0xea 0x56 0x14
+0x65 0xea 0x56 0x14
+0x75 0xea 0x66 0x14
+0x65 0xea 0x76 0x14
+
+
+#------------------------------------------------------------------------------
+# ORR
+#------------------------------------------------------------------------------
+# CHECK: orr r4, r5, #61440
+# CHECK: orr.w r4, r5, r6
+# CHECK: orr.w r4, r5, r6, lsl #5
+# CHECK: orrs.w r4, r5, r6, lsr #5
+# CHECK: orr.w r4, r5, r6, lsr #5
+# CHECK: orrs.w r4, r5, r6, asr #5
+# CHECK: orr.w r4, r5, r6, ror #5
+
+0x45 0xf4 0x70 0x44
+0x45 0xea 0x06 0x04
+0x45 0xea 0x46 0x14
+0x55 0xea 0x56 0x14
+0x45 0xea 0x56 0x14
+0x55 0xea 0x66 0x14
+0x45 0xea 0x76 0x14
+
+
+#------------------------------------------------------------------------------
+# PKH
+#------------------------------------------------------------------------------
+# CHECK: pkhbt r2, r2, r3
+# CHECK: pkhbt r2, r2, r3, lsl #31
+# CHECK: pkhbt r2, r2, r3, lsl #15
+
+# CHECK: pkhtb r2, r2, r3, asr #31
+# CHECK: pkhtb r2, r2, r3, asr #15
+
+0xc2 0xea 0x03 0x02
+0xc2 0xea 0xc3 0x72
+0xc2 0xea 0xc3 0x32
+
+0xc2 0xea 0xe3 0x72
+0xc2 0xea 0xe3 0x32
+
+
+#------------------------------------------------------------------------------
+# PLD(immediate)
+#------------------------------------------------------------------------------
+# CHECK: pld [r5, #-4]
+# CHECK: pld [r6, #32]
+# CHECK: pld [r6, #33]
+# CHECK: pld [r6, #257]
+# CHECK: pld [r7, #257]
+
+0x15 0xf8 0x04 0xfc
+0x96 0xf8 0x20 0xf0
+0x96 0xf8 0x21 0xf0
+0x96 0xf8 0x01 0xf1
+0x97 0xf8 0x01 0xf1
+
+#------------------------------------------------------------------------------
+# PLD(register)
+#------------------------------------------------------------------------------
+# CHECK: pld [r8, r1]
+# CHECK: pld [r5, r2]
+# CHECK: pld [r0, r2, lsl #3]
+# CHECK: pld [r8, r2, lsl #2]
+# CHECK: pld [sp, r2, lsl #1]
+# CHECK: pld [sp, r2]
+
+0x18 0xf8 0x01 0xf0
+0x15 0xf8 0x02 0xf0
+0x10 0xf8 0x32 0xf0
+0x18 0xf8 0x22 0xf0
+0x1d 0xf8 0x12 0xf0
+0x1d 0xf8 0x02 0xf0
+
+#------------------------------------------------------------------------------
+# PLI(immediate)
+#------------------------------------------------------------------------------
+# CHECK: pli [r5, #-4]
+# CHECK: pli [r6, #32]
+# CHECK: pli [r6, #33]
+# CHECK: pli [r6, #257]
+# CHECK: pli [r7, #257]
+
+0x15 0xf9 0x04 0xfc
+0x96 0xf9 0x20 0xf0
+0x96 0xf9 0x21 0xf0
+0x96 0xf9 0x01 0xf1
+0x97 0xf9 0x01 0xf1
+
+#------------------------------------------------------------------------------
+# PLI(register)
+#------------------------------------------------------------------------------
+# CHECK: pli [r8, r1]
+# CHECK: pli [r5, r2]
+# CHECK: pli [r0, r2, lsl #3]
+# CHECK: pli [r8, r2, lsl #2]
+# CHECK: pli [sp, r2, lsl #1]
+# CHECK: pli [sp, r2]
+
+0x18 0xf9 0x01 0xf0
+0x15 0xf9 0x02 0xf0
+0x10 0xf9 0x32 0xf0
+0x18 0xf9 0x22 0xf0
+0x1d 0xf9 0x12 0xf0
+0x1d 0xf9 0x02 0xf0
+
+
+#------------------------------------------------------------------------------
+# QADD/QADD16/QADD8
+#------------------------------------------------------------------------------
+# CHECK: qadd r1, r2, r3
+# CHECK: qadd16 r1, r2, r3
+# CHECK: qadd8 r1, r2, r3
+# CHECK: itte gt
+# CHECK: qaddgt r1, r2, r3
+# CHECK: qadd16gt r1, r2, r3
+# CHECK: qadd8le r1, r2, r3
+
+0x83 0xfa 0x82 0xf1
+0x92 0xfa 0x13 0xf1
+0x82 0xfa 0x13 0xf1
+0xc6 0xbf
+0x83 0xfa 0x82 0xf1
+0x92 0xfa 0x13 0xf1
+0x82 0xfa 0x13 0xf1
+
+
+#------------------------------------------------------------------------------
+# QDADD/QDSUB
+#------------------------------------------------------------------------------
+# CHECK: qdadd r6, r7, r8
+# CHECK: qdsub r6, r7, r8
+# CHECK: itt hi
+# CHECK: qdaddhi r6, r7, r8
+# CHECK: qdsubhi r6, r7, r8
+
+0x88 0xfa 0x97 0xf6
+0x88 0xfa 0xb7 0xf6
+0x84 0xbf
+0x88 0xfa 0x97 0xf6
+0x88 0xfa 0xb7 0xf6
+
+
+#------------------------------------------------------------------------------
+# QSAX
+#------------------------------------------------------------------------------
+# CHECK: qsax r9, r12, r0
+# CHECK: it eq
+# CHECK: qsaxeq r9, r12, r0
+
+0xec 0xfa 0x10 0xf9
+0x08 0xbf
+0xec 0xfa 0x10 0xf9
+
+
+#------------------------------------------------------------------------------
+# QSUB/QSUB16/QSUB8
+#------------------------------------------------------------------------------
+# CHECK: qsub r1, r2, r3
+# CHECK: qsub16 r1, r2, r3
+# CHECK: qsub8 r1, r2, r3
+# CHECK: itet le
+# CHECK: qsuble r1, r2, r3
+# CHECK: qsub16gt r1, r2, r3
+# CHECK: qsub8le r1, r2, r3
+
+0x83 0xfa 0xa2 0xf1
+0xd2 0xfa 0x13 0xf1
+0xc2 0xfa 0x13 0xf1
+0xd6 0xbf
+0x83 0xfa 0xa2 0xf1
+0xd2 0xfa 0x13 0xf1
+0xc2 0xfa 0x13 0xf1
+
+
+#------------------------------------------------------------------------------
+# RBIT
+#------------------------------------------------------------------------------
+# CHECK: rbit r1, r2
+# CHECK: it ne
+# CHECK: rbitne r1, r2
+
+0x92 0xfa 0xa2 0xf1
+0x18 0xbf
+0x92 0xfa 0xa2 0xf1
+
+
+#------------------------------------------------------------------------------
+# REV
+#------------------------------------------------------------------------------
+# CHECK: rev.w r1, r2
+# CHECK: rev.w r2, r8
+# CHECK: itt ne
+# CHECK: revne r1, r2
+# CHECK: revne.w r1, r8
+
+0x92 0xfa 0x82 0xf1
+0x98 0xfa 0x88 0xf2
+0x1c 0xbf
+0x11 0xba
+0x98 0xfa 0x88 0xf1
+
+
+#------------------------------------------------------------------------------
+# REV16
+#------------------------------------------------------------------------------
+# CHECK: rev16.w r1, r2
+# CHECK: rev16.w r2, r8
+# CHECK: itt ne
+# CHECK: rev16ne r1, r2
+# CHECK: rev16ne.w r1, r8
+
+0x92 0xfa 0x92 0xf1
+0x98 0xfa 0x98 0xf2
+0x1c 0xbf
+0x51 0xba
+0x98 0xfa 0x98 0xf1
+
+
+#------------------------------------------------------------------------------
+# REVSH
+#------------------------------------------------------------------------------
+# CHECK: revsh.w r1, r2
+# CHECK: revsh.w r2, r8
+# CHECK: itt ne
+# CHECK: revshne r1, r2
+# CHECK: revshne.w r1, r8
+
+0x92 0xfa 0xb2 0xf1
+0x98 0xfa 0xb8 0xf2
+0x1c 0xbf
+0xd1 0xba
+0x98 0xfa 0xb8 0xf1
+
+
+#------------------------------------------------------------------------------
+# ROR (immediate)
+#------------------------------------------------------------------------------
+# CHECK: ror.w r2, r3, #12
+# CHECK: rors.w r8, r3, #31
+# CHECK: rors.w r2, r3, #1
+# CHECK: ror.w r2, r3, #4
+# CHECK: rors.w r2, r12, #15
+
+# CHECK: ror.w r3, r3, #19
+# CHECK: rors.w r8, r8, #2
+# CHECK: rors.w r7, r7, #5
+# CHECK: ror.w r12, r12, #21
+
+0x4f 0xea 0x33 0x32
+0x5f 0xea 0xf3 0x78
+0x5f 0xea 0x73 0x02
+0x4f 0xea 0x33 0x12
+0x5f 0xea 0xfc 0x32
+
+0x4f 0xea 0xf3 0x43
+0x5f 0xea 0xb8 0x08
+0x5f 0xea 0x77 0x17
+0x4f 0xea 0x7c 0x5c
+
+
+#------------------------------------------------------------------------------
+# ROR (register)
+#------------------------------------------------------------------------------
+# CHECK: ror.w r3, r4, r2
+# CHECK: ror.w r1, r1, r2
+# CHECK: rors.w r3, r4, r8
+
+0x64 0xfa 0x02 0xf3
+0x61 0xfa 0x02 0xf1
+0x74 0xfa 0x08 0xf3
+
+
+#------------------------------------------------------------------------------
+# RRX
+#------------------------------------------------------------------------------
+# CHECK: rrx r1, r2
+# CHECK: rrxs r1, r2
+# CHECK: ite lt
+# CHECK: rrxlt r9, r12
+# CHECK: rrxsge r8, r3
+
+0x4f 0xea 0x32 0x01
+0x5f 0xea 0x32 0x01
+0xb4 0xbf
+0x4f 0xea 0x3c 0x09
+0x5f 0xea 0x33 0x08
+
+#------------------------------------------------------------------------------
+# RSB (immediate)
+#------------------------------------------------------------------------------
+# CHECK: rsb.w r2, r5, #1044480
+# CHECK: rsbs.w r3, r12, #15
+# CHECK: rsb.w r1, r1, #255
+
+0xc5 0xf5 0x7f 0x22
+0xdc 0xf1 0x0f 0x03
+0xc1 0xf1 0xff 0x01
+
+
+#------------------------------------------------------------------------------
+# RSB (register)
+#------------------------------------------------------------------------------
+# CHECK: rsb r4, r4, r8
+# CHECK: rsb r4, r9, r8
+# CHECK: rsb r1, r4, r8, asr #3
+# CHECK: rsbs r2, r1, r7, lsl #1
+
+0xc4 0xeb 0x08 0x04
+0xc9 0xeb 0x08 0x04
+0xc4 0xeb 0xe8 0x01
+0xd1 0xeb 0x47 0x02
+
+
+#------------------------------------------------------------------------------
+# SADD16
+#------------------------------------------------------------------------------
+# CHECK: sadd16 r3, r4, r8
+# CHECK: it ne
+# CHECK: sadd16ne r3, r4, r8
+
+0x94 0xfa 0x08 0xf3
+0x18 0xbf
+0x94 0xfa 0x08 0xf3
+
+
+#------------------------------------------------------------------------------
+# SADD8
+#------------------------------------------------------------------------------
+# CHECK: sadd8 r3, r4, r8
+# CHECK: it ne
+# CHECK: sadd8ne r3, r4, r8
+
+0x84 0xfa 0x08 0xf3
+0x18 0xbf
+0x84 0xfa 0x08 0xf3
+
+
+#------------------------------------------------------------------------------
+# SASX
+#------------------------------------------------------------------------------
+# CHECK: sasx r9, r2, r7
+# CHECK: it ne
+# CHECK: sasxne r2, r5, r6
+
+0xa2 0xfa 0x07 0xf9
+0x18 0xbf
+0xa5 0xfa 0x06 0xf2
+
+
+#------------------------------------------------------------------------------
+# SBC (immediate)
+#------------------------------------------------------------------------------
+# CHECK: sbc r0, r1, #4
+# CHECK: sbcs r0, r1, #0
+# CHECK: sbc r1, r2, #255
+# CHECK: sbc r3, r7, #5570645
+# CHECK: sbc r8, r12, #2852170240
+# CHECK: sbc r9, r7, #2779096485
+# CHECK: sbc r5, r3, #2264924160
+# CHECK: sbc r4, r2, #2139095040
+# CHECK: sbc r4, r2, #1664
+
+0x61 0xf1 0x04 0x00
+0x71 0xf1 0x00 0x00
+0x62 0xf1 0xff 0x01
+0x67 0xf1 0x55 0x13
+0x6c 0xf1 0xaa 0x28
+0x67 0xf1 0xa5 0x39
+0x63 0xf1 0x07 0x45
+0x62 0xf1 0xff 0x44
+0x62 0xf5 0xd0 0x64
+
+
+#------------------------------------------------------------------------------
+# SBC (register)
+#------------------------------------------------------------------------------
+# CHECK: sbc.w r4, r5, r6
+# CHECK: sbcs.w r4, r5, r6
+# CHECK: sbc.w r9, r1, r3
+# CHECK: sbcs.w r9, r1, r3
+# CHECK: sbc.w r0, r1, r3, ror #4
+# CHECK: sbcs.w r0, r1, r3, lsl #7
+# CHECK: sbc.w r0, r1, r3, lsr #31
+# CHECK: sbcs.w r0, r1, r3, asr #32
+
+0x65 0xeb 0x06 0x04
+0x75 0xeb 0x06 0x04
+0x61 0xeb 0x03 0x09
+0x71 0xeb 0x03 0x09
+0x61 0xeb 0x33 0x10
+0x71 0xeb 0xc3 0x10
+0x61 0xeb 0xd3 0x70
+0x71 0xeb 0x23 0x00
+
+
+#------------------------------------------------------------------------------
+# SBFX
+#------------------------------------------------------------------------------
+# CHECK: sbfx r4, r5, #16, #1
+# CHECK: it gt
+# CHECK: sbfxgt r4, r5, #16, #16
+
+0x45 0xf3 0x00 0x44
+0xc8 0xbf
+0x45 0xf3 0x0f 0x44
+
+
+#------------------------------------------------------------------------------
+# SEL
+#------------------------------------------------------------------------------
+# CHECK: sel r5, r9, r2
+# CHECK: it le
+# CHECK: selle r5, r9, r2
+
+0xa9 0xfa 0x82 0xf5
+0xd8 0xbf
+0xa9 0xfa 0x82 0xf5
+
+
+#------------------------------------------------------------------------------
+# SEV
+#------------------------------------------------------------------------------
+# CHECK: sev.w
+# CHECK: it eq
+# CHECK: seveq.w
+
+0xaf 0xf3 0x04 0x80
+0x08 0xbf
+0xaf 0xf3 0x04 0x80
+
+
+#------------------------------------------------------------------------------
+# SADD16/SADD8
+#------------------------------------------------------------------------------
+# CHECK: sadd16 r1, r2, r3
+# CHECK: sadd8 r1, r2, r3
+# CHECK: ite gt
+# CHECK: sadd16gt r1, r2, r3
+# CHECK: sadd8le r1, r2, r3
+
+0x92 0xfa 0x03 0xf1
+0x82 0xfa 0x03 0xf1
+0xcc 0xbf
+0x92 0xfa 0x03 0xf1
+0x82 0xfa 0x03 0xf1
+
+
+#------------------------------------------------------------------------------
+# SHASX
+#------------------------------------------------------------------------------
+# CHECK: shasx r4, r8, r2
+# CHECK: it gt
+# CHECK: shasxgt r4, r8, r2
+
+0xa8 0xfa 0x22 0xf4
+0xc8 0xbf
+0xa8 0xfa 0x22 0xf4
+
+
+#------------------------------------------------------------------------------
+# SHASX
+#------------------------------------------------------------------------------
+# CHECK: shsax r4, r8, r2
+# CHECK: it gt
+# CHECK: shsaxgt r4, r8, r2
+
+0xe8 0xfa 0x22 0xf4
+0xc8 0xbf
+0xe8 0xfa 0x22 0xf4
+
+
+#------------------------------------------------------------------------------
+# SHSUB16/SHSUB8
+#------------------------------------------------------------------------------
+# CHECK: shsub16 r4, r8, r2
+# CHECK: shsub8 r4, r8, r2
+# CHECK: itt gt
+# CHECK: shsub16gt r4, r8, r2
+# CHECK: shsub8gt r4, r8, r2
+
+0xd8 0xfa 0x22 0xf4
+0xc8 0xfa 0x22 0xf4
+0xc4 0xbf
+0xd8 0xfa 0x22 0xf4
+0xc8 0xfa 0x22 0xf4
+
+
+#------------------------------------------------------------------------------
+# SMLABB/SMLABT/SMLATB/SMLATT
+#------------------------------------------------------------------------------
+# CHECK: smlabb r3, r1, r9, r0
+# CHECK: smlabt r5, r6, r4, r1
+# CHECK: smlatb r4, r2, r3, r2
+# CHECK: smlatt r8, r3, r8, r4
+# CHECK: itete gt
+# CHECK: smlabbgt r3, r1, r9, r0
+# CHECK: smlabtle r5, r6, r4, r1
+# CHECK: smlatbgt r4, r2, r3, r2
+# CHECK: smlattle r8, r3, r8, r4
+
+0x11 0xfb 0x09 0x03
+0x16 0xfb 0x14 0x15
+0x12 0xfb 0x23 0x24
+0x13 0xfb 0x38 0x48
+0xcb 0xbf
+0x11 0xfb 0x09 0x03
+0x16 0xfb 0x14 0x15
+0x12 0xfb 0x23 0x24
+0x13 0xfb 0x38 0x48
+
+
+#------------------------------------------------------------------------------
+# SMLAD/SMLADX
+#------------------------------------------------------------------------------
+# CHECK: smlad r2, r3, r5, r8
+# CHECK: smladx r2, r3, r5, r8
+# CHECK: itt hi
+# CHECK: smladhi r2, r3, r5, r8
+# CHECK: smladxhi r2, r3, r5, r8
+
+0x23 0xfb 0x05 0x82
+0x23 0xfb 0x15 0x82
+0x84 0xbf
+0x23 0xfb 0x05 0x82
+0x23 0xfb 0x15 0x82
+
+
+#------------------------------------------------------------------------------
+# SMLAL
+#------------------------------------------------------------------------------
+# CHECK: smlal r2, r3, r5, r8
+# CHECK: it eq
+# CHECK: smlaleq r2, r3, r5, r8
+
+0xc5 0xfb 0x08 0x23
+0x08 0xbf
+0xc5 0xfb 0x08 0x23
+
+
+#------------------------------------------------------------------------------
+# SMLALBB/SMLALBT/SMLALTB/SMLALTT
+#------------------------------------------------------------------------------
+# CHECK: smlalbb r3, r1, r9, r0
+# CHECK: smlalbt r5, r6, r4, r1
+# CHECK: smlaltb r4, r2, r3, r2
+# CHECK: smlaltt r8, r3, r8, r4
+# CHECK: iteet ge
+# CHECK: smlalbbge r3, r1, r9, r0
+# CHECK: smlalbtlt r5, r6, r4, r1
+# CHECK: smlaltblt r4, r2, r3, r2
+# CHECK: smlalttge r8, r3, r8, r4
+
+0xc9 0xfb 0x80 0x31
+0xc4 0xfb 0x91 0x56
+0xc3 0xfb 0xa2 0x42
+0xc8 0xfb 0xb4 0x83
+0xad 0xbf
+0xc9 0xfb 0x80 0x31
+0xc4 0xfb 0x91 0x56
+0xc3 0xfb 0xa2 0x42
+0xc8 0xfb 0xb4 0x83
+
+#------------------------------------------------------------------------------
+# SMLALD/SMLALDX
+#------------------------------------------------------------------------------
+# CHECK: smlald r2, r3, r5, r8
+# CHECK: smlaldx r2, r3, r5, r8
+# CHECK: ite eq
+# CHECK: smlaldeq r2, r3, r5, r8
+# CHECK: smlaldxne r2, r3, r5, r8
+
+0xc5 0xfb 0xc8 0x23
+0xc5 0xfb 0xd8 0x23
+0x0c 0xbf
+0xc5 0xfb 0xc8 0x23
+0xc5 0xfb 0xd8 0x23
+
+
+#------------------------------------------------------------------------------
+# SMLAWB/SMLAWT
+#------------------------------------------------------------------------------
+# CHECK: smlawb r2, r3, r10, r8
+# CHECK: smlawt r8, r3, r5, r9
+# CHECK: ite eq
+# CHECK: smlawbeq r2, r7, r5, r8
+# CHECK: smlawtne r1, r3, r0, r8
+
+0x33 0xfb 0x0a 0x82
+0x33 0xfb 0x15 0x98
+0x0c 0xbf
+0x37 0xfb 0x05 0x82
+0x33 0xfb 0x10 0x81
+
+
+#------------------------------------------------------------------------------
+# SMLSD/SMLSDX
+#------------------------------------------------------------------------------
+# CHECK: smlsd r2, r3, r5, r8
+# CHECK: smlsdx r2, r3, r5, r8
+# CHECK: ite le
+# CHECK: smlsdle r2, r3, r5, r8
+# CHECK: smlsdxgt r2, r3, r5, r8
+
+0x43 0xfb 0x05 0x82
+0x43 0xfb 0x15 0x82
+0xd4 0xbf
+0x43 0xfb 0x05 0x82
+0x43 0xfb 0x15 0x82
+
+
+#------------------------------------------------------------------------------
+# SMLSLD/SMLSLDX
+#------------------------------------------------------------------------------
+# CHECK: smlsld r2, r9, r5, r1
+# CHECK: smlsldx r4, r11, r2, r8
+# CHECK: ite ge
+# CHECK: smlsldge r8, r2, r5, r6
+# CHECK: smlsldxlt r1, r0, r3, r8
+
+0xd5 0xfb 0xc1 0x29
+0xd2 0xfb 0xd8 0x4b
+0xac 0xbf
+0xd5 0xfb 0xc6 0x82
+0xd3 0xfb 0xd8 0x10
+
+
+#------------------------------------------------------------------------------
+# SMMLA/SMMLAR
+#------------------------------------------------------------------------------
+# CHECK: smmla r1, r2, r3, r4
+# CHECK: smmlar r4, r3, r2, r1
+# CHECK: ite lo
+# CHECK: smmlalo r1, r2, r3, r4
+# CHECK: smmlarhs r4, r3, r2, r1
+
+0x52 0xfb 0x03 0x41
+0x53 0xfb 0x12 0x14
+0x34 0xbf
+0x52 0xfb 0x03 0x41
+0x53 0xfb 0x12 0x14
+
+
+#------------------------------------------------------------------------------
+# SMMLS/SMMLSR
+#------------------------------------------------------------------------------
+# CHECK: smmls r1, r2, r3, r4
+# CHECK: smmlsr r4, r3, r2, r1
+# CHECK: ite lo
+# CHECK: smmlslo r1, r2, r3, r4
+# CHECK: smmlsrhs r4, r3, r2, r1
+
+0x62 0xfb 0x03 0x41
+0x63 0xfb 0x12 0x14
+0x34 0xbf
+0x62 0xfb 0x03 0x41
+0x63 0xfb 0x12 0x14
+
+#------------------------------------------------------------------------------
+# SSAT
+#------------------------------------------------------------------------------
+# CHECK: ssat r9, #30, r0, asr #2
+
+0x20 0xf3 0x9d 0x09
+
+#------------------------------------------------------------------------------
+# STR (immediate)
+#------------------------------------------------------------------------------
+# CHECK: str r10, [r11], #0
+
+0x4b 0xf8 0x00 0xab
+
+#------------------------------------------------------------------------------
+# STRD (immediate)
+#------------------------------------------------------------------------------
+# CHECK: strd r6, r3, [r5], #-8
+# CHECK: strd r8, r5, [r5]{{$}}
+# CHECK: strd r7, r4, [r5], #-4
+
+0x65 0xe8 0x02 0x63
+0x65 0xe8 0x00 0x85
+0x65 0xe8 0x01 0x74
+
+#------------------------------------------------------------------------------
+# STREX/STREXB/STREXH/STREXD
+#------------------------------------------------------------------------------
+# CHECK: strex r1, r8, [r4]
+# CHECK: strex r8, r2, [r4]
+# CHECK: strex r2, r12, [sp, #128]
+# CHECK: strexb r5, r1, [r7]
+# CHECK: strexh r9, r7, [r12]
+# CHECK: strexd r9, r3, r6, [r4]
+
+0x44 0xe8 0x00 0x81
+0x44 0xe8 0x00 0x28
+0x4d 0xe8 0x20 0xc2
+0xc7 0xe8 0x45 0x1f
+0xcc 0xe8 0x59 0x7f
+0xc4 0xe8 0x79 0x36
+
+
+#------------------------------------------------------------------------------
+# STRH(immediate)
+#------------------------------------------------------------------------------
+# CHECK: strh r5, [r5, #-4]
+# CHECK: strh r5, [r6, #32]
+# CHECK: strh.w r5, [r6, #33]
+# CHECK: strh.w r5, [r6, #257]
+# CHECK: strh.w lr, [r7, #257]
+# CHECK: strh r5, [r8, #255]!
+# CHECK: strh r2, [r5, #4]!
+# CHECK: strh r1, [r4, #-4]!
+# CHECK: strh lr, [r3], #255
+# CHECK: strh r9, [r2], #4
+# CHECK: strh r3, [sp], #-4
+
+0x25 0xf8 0x04 0x5c
+0x35 0x84
+0xa6 0xf8 0x21 0x50
+0xa6 0xf8 0x01 0x51
+0xa7 0xf8 0x01 0xe1
+0x28 0xf8 0xff 0x5f
+0x25 0xf8 0x04 0x2f
+0x24 0xf8 0x04 0x1d
+0x23 0xf8 0xff 0xeb
+0x22 0xf8 0x04 0x9b
+0x2d 0xf8 0x04 0x39
+
+
+#------------------------------------------------------------------------------
+# STRH(register)
+#------------------------------------------------------------------------------
+# CHECK: strh.w r1, [r8, r1]
+# CHECK: strh.w r4, [r5, r2]
+# CHECK: strh.w r6, [r0, r2, lsl #3]
+# CHECK: strh.w r8, [r8, r2, lsl #2]
+# CHECK: strh.w r7, [sp, r2, lsl #1]
+# CHECK: strh.w r7, [sp, r2]
+
+0x28 0xf8 0x01 0x10
+0x25 0xf8 0x02 0x40
+0x20 0xf8 0x32 0x60
+0x28 0xf8 0x22 0x80
+0x2d 0xf8 0x12 0x70
+0x2d 0xf8 0x02 0x70
+
+
+#------------------------------------------------------------------------------
+# STRHT
+#------------------------------------------------------------------------------
+# CHECK: strht r1, [r2]
+# CHECK: strht r1, [r8]
+# CHECK: strht r1, [r8, #3]
+# CHECK: strht r1, [r8, #255]
+
+0x22 0xf8 0x00 0x1e
+0x28 0xf8 0x00 0x1e
+0x28 0xf8 0x03 0x1e
+0x28 0xf8 0xff 0x1e
+
+
+#------------------------------------------------------------------------------
+# STRT
+#------------------------------------------------------------------------------
+# CHECK: strt r1, [r2]
+# CHECK: strt r1, [r8]
+# CHECK: strt r1, [r8, #3]
+# CHECK: strt r1, [r8, #255]
+
+0x42 0xf8 0x00 0x1e
+0x48 0xf8 0x00 0x1e
+0x48 0xf8 0x03 0x1e
+0x48 0xf8 0xff 0x1e
+
+
+#------------------------------------------------------------------------------
+# SUB (immediate)
+#------------------------------------------------------------------------------
+# CHECK: itet eq
+# CHECK: subeq r1, r2, #4
+# CHECK: subwne r5, r3, #1023
+# CHECK: subweq r4, r5, #293
+# CHECK: sub.w r2, sp, #1024
+# CHECK: sub.w r2, r8, #65280
+# CHECK: subw r2, r3, #257
+# CHECK: sub.w r12, r6, #256
+# CHECK: subw r12, r6, #256
+# CHECK: subs.w r1, r2, #496
+
+0x0a 0xbf
+0x11 0x1f
+0xa3 0xf2 0xff 0x35
+0xa5 0xf2 0x25 0x14
+0xad 0xf5 0x80 0x62
+0xa8 0xf5 0x7f 0x42
+0xa3 0xf2 0x01 0x12
+0xa6 0xf5 0x80 0x7c
+0xa6 0xf2 0x00 0x1c
+0xb2 0xf5 0xf8 0x71
+
+
+#------------------------------------------------------------------------------
+# SUB (register)
+#------------------------------------------------------------------------------
+# CHECK: sub.w r4, r5, r6
+# CHECK: sub.w r4, r5, r6, lsl #5
+# CHECK: sub.w r4, r5, r6, lsr #5
+# CHECK: sub.w r4, r5, r6, lsr #5
+# CHECK: sub.w r4, r5, r6, asr #5
+# CHECK: sub.w r4, r5, r6, ror #5
+# CHECK: sub.w r5, r2, r12, rrx
+
+0xa5 0xeb 0x06 0x04
+0xa5 0xeb 0x46 0x14
+0xa5 0xeb 0x56 0x14
+0xa5 0xeb 0x56 0x14
+0xa5 0xeb 0x66 0x14
+0xa5 0xeb 0x76 0x14
+0xa2 0xeb 0x3c 0x05
+
+
+#------------------------------------------------------------------------------
+# SVC
+#------------------------------------------------------------------------------
+# CHECK: svc #0
+# CHECK: ite eq
+# CHECK: svceq #255
+# CHECK: svcne #33
+
+0x00 0xdf
+0x0c 0xbf
+0xff 0xdf
+0x21 0xdf
+
+#------------------------------------------------------------------------------
+# SXTAB
+#------------------------------------------------------------------------------
+# CHECK: sxtab r2, r3, r4
+# CHECK: sxtab r4, r5, r6
+# CHECK: it lt
+# CHECK: sxtablt r6, r2, r9, ror #8
+# CHECK: sxtab r5, r1, r4, ror #16
+# CHECK: sxtab r7, r8, r3, ror #24
+
+0x43 0xfa 0x84 0xf2
+0x45 0xfa 0x86 0xf4
+0xb8 0xbf
+0x42 0xfa 0x99 0xf6
+0x41 0xfa 0xa4 0xf5
+0x48 0xfa 0xb3 0xf7
+
+
+#------------------------------------------------------------------------------
+# SXTAB16
+#------------------------------------------------------------------------------
+# CHECK: sxtab16 r6, r2, r7
+# CHECK: sxtab16 r3, r5, r8, ror #8
+# CHECK: sxtab16 r3, r2, r1, ror #16
+# CHECK: ite ne
+# CHECK: sxtab16ne r0, r1, r4
+# CHECK: sxtab16eq r1, r2, r3, ror #24
+
+0x22 0xfa 0x87 0xf6
+0x25 0xfa 0x98 0xf3
+0x22 0xfa 0xa1 0xf3
+0x14 0xbf
+0x21 0xfa 0x84 0xf0
+0x22 0xfa 0xb3 0xf1
+
+
+#------------------------------------------------------------------------------
+# SXTAH
+#------------------------------------------------------------------------------
+# CHECK: sxtah r1, r3, r9
+# CHECK: sxtah r3, r8, r3, ror #8
+# CHECK: sxtah r9, r3, r3, ror #24
+# CHECK: ite hi
+# CHECK: sxtahhi r6, r1, r6
+# CHECK: sxtahls r2, r2, r4, ror #16
+
+0x03 0xfa 0x89 0xf1
+0x08 0xfa 0x93 0xf3
+0x03 0xfa 0xb3 0xf9
+0x8c 0xbf
+0x01 0xfa 0x86 0xf6
+0x02 0xfa 0xa4 0xf2
+
+
+#------------------------------------------------------------------------------
+# SXTB
+#------------------------------------------------------------------------------
+# CHECK: sxtb r5, r6
+# CHECK: sxtb.w r6, r9, ror #8
+# CHECK: sxtb.w r8, r3, ror #24
+# CHECK: ite ge
+# CHECK: sxtbge r2, r4
+# CHECK: sxtblt.w r5, r1, ror #16
+
+0x75 0xb2
+0x4f 0xfa 0x99 0xf6
+0x4f 0xfa 0xb3 0xf8
+0xac 0xbf
+0x62 0xb2
+0x4f 0xfa 0xa1 0xf5
+
+
+#------------------------------------------------------------------------------
+# SXTB16
+#------------------------------------------------------------------------------
+# CHECK: sxtb16 r1, r4
+# CHECK: sxtb16 r6, r7
+# CHECK: sxtb16 r3, r1, ror #16
+# CHECK: ite hs
+# CHECK: sxtb16hs r3, r5, ror #8
+# CHECK: sxtb16lo r2, r3, ror #24
+
+0x2f 0xfa 0x84 0xf1
+0x2f 0xfa 0x87 0xf6
+0x2f 0xfa 0xa1 0xf3
+0x2c 0xbf
+0x2f 0xfa 0x95 0xf3
+0x2f 0xfa 0xb3 0xf2
+
+
+#------------------------------------------------------------------------------
+# SXTH
+#------------------------------------------------------------------------------
+# CHECK: sxth r1, r6
+# CHECK: sxth.w r3, r8, ror #8
+# CHECK: sxth.w r9, r3, ror #24
+# CHECK: itt ne
+# CHECK: sxthne.w r3, r9
+# CHECK: sxthne.w r2, r2, ror #16
+
+0x31 0xb2
+0x0f 0xfa 0x98 0xf3
+0x0f 0xfa 0xb3 0xf9
+0x1c 0xbf
+0x0f 0xfa 0x89 0xf3
+0x0f 0xfa 0xa2 0xf2
+
+
+#------------------------------------------------------------------------------
+# SXTB
+#------------------------------------------------------------------------------
+# CHECK: sxtb r5, r6
+# CHECK: sxtb.w r6, r9, ror #8
+# CHECK: sxtb.w r8, r3, ror #24
+# CHECK: ite ge
+# CHECK: sxtbge r2, r4
+# CHECK: sxtblt.w r5, r1, ror #16
+
+0x75 0xb2
+0x4f 0xfa 0x99 0xf6
+0x4f 0xfa 0xb3 0xf8
+0xac 0xbf
+0x62 0xb2
+0x4f 0xfa 0xa1 0xf5
+
+
+#------------------------------------------------------------------------------
+# SXTB16
+#------------------------------------------------------------------------------
+# CHECK: sxtb16 r1, r4
+# CHECK: sxtb16 r6, r7
+# CHECK: sxtb16 r3, r1, ror #16
+# CHECK: ite hs
+# CHECK: sxtb16hs r3, r5, ror #8
+# CHECK: sxtb16lo r2, r3, ror #24
+
+0x2f 0xfa 0x84 0xf1
+0x2f 0xfa 0x87 0xf6
+0x2f 0xfa 0xa1 0xf3
+0x2c 0xbf
+0x2f 0xfa 0x95 0xf3
+0x2f 0xfa 0xb3 0xf2
+
+
+#------------------------------------------------------------------------------
+# SXTH
+#------------------------------------------------------------------------------
+# CHECK: sxth r1, r6
+# CHECK: sxth.w r3, r8, ror #8
+# CHECK: sxth.w r9, r3, ror #24
+# CHECK: itt ne
+# CHECK: sxthne.w r3, r9
+# CHECK: sxthne.w r2, r2, ror #16
+
+0x31 0xb2
+0x0f 0xfa 0x98 0xf3
+0x0f 0xfa 0xb3 0xf9
+0x1c 0xbf
+0x0f 0xfa 0x89 0xf3
+0x0f 0xfa 0xa2 0xf2
+
+
+#------------------------------------------------------------------------------
+# TBB/TBH
+#------------------------------------------------------------------------------
+# CHECK: tbb [r3, r8]
+# CHECK: tbh [r3, r8, lsl #1]
+# CHECK: it eq
+# CHECK: tbbeq [r3, r8]
+# CHECK: it hs
+# CHECK: tbhhs [r3, r8, lsl #1]
+
+0xd3 0xe8 0x08 0xf0
+0xd3 0xe8 0x18 0xf0
+0x08 0xbf
+0xd3 0xe8 0x08 0xf0
+0x28 0xbf
+0xd3 0xe8 0x18 0xf0
+
+
+#------------------------------------------------------------------------------
+# TEQ
+#------------------------------------------------------------------------------
+# CHECK: teq.w r5, #61440
+# CHECK: teq.w r4, r5
+# CHECK: teq.w r4, r5, lsl #5
+# CHECK: teq.w r4, r5, lsr #5
+# CHECK: teq.w r4, r5, lsr #5
+# CHECK: teq.w r4, r5, asr #5
+# CHECK: teq.w r4, r5, ror #5
+
+0x95 0xf4 0x70 0x4f
+0x94 0xea 0x05 0x0f
+0x94 0xea 0x45 0x1f
+0x94 0xea 0x55 0x1f
+0x94 0xea 0x55 0x1f
+0x94 0xea 0x65 0x1f
+0x94 0xea 0x75 0x1f
+
+
+#------------------------------------------------------------------------------
+# TST
+#------------------------------------------------------------------------------
+# CHECK: tst.w r5, #61440
+# CHECK: tst r2, r5
+# CHECK: tst.w r3, r12, lsl #5
+# CHECK: tst.w r4, r11, lsr #4
+# CHECK: tst.w r5, r10, lsr #12
+# CHECK: tst.w r6, r9, asr #30
+# CHECK: tst.w r7, r8, ror #2
+
+0x15 0xf4 0x70 0x4f
+0x2a 0x42
+0x13 0xea 0x4c 0x1f
+0x14 0xea 0x1b 0x1f
+0x15 0xea 0x1a 0x3f
+0x16 0xea 0xa9 0x7f
+0x17 0xea 0xb8 0x0f
+
+
+#------------------------------------------------------------------------------
+# UADD16/UADD8
+#------------------------------------------------------------------------------
+# CHECK: uadd16 r1, r2, r3
+# CHECK: uadd8 r1, r2, r3
+# CHECK: ite gt
+# CHECK: uadd16gt r1, r2, r3
+# CHECK: uadd8le r1, r2, r3
+
+0x92 0xfa 0x43 0xf1
+0x82 0xfa 0x43 0xf1
+0xcc 0xbf
+0x92 0xfa 0x43 0xf1
+0x82 0xfa 0x43 0xf1
+
+
+#------------------------------------------------------------------------------
+# UASX
+#------------------------------------------------------------------------------
+# CHECK: uasx r9, r12, r0
+# CHECK: it eq
+# CHECK: uasxeq r9, r12, r0
+# CHECK: uasx r9, r12, r0
+# CHECK: it eq
+# CHECK: uasxeq r9, r12, r0
+
+0xac 0xfa 0x40 0xf9
+0x08 0xbf
+0xac 0xfa 0x40 0xf9
+0xac 0xfa 0x40 0xf9
+0x08 0xbf
+0xac 0xfa 0x40 0xf9
+
+
+#------------------------------------------------------------------------------
+# UBFX
+#------------------------------------------------------------------------------
+# CHECK: ubfx r4, r5, #16, #1
+# CHECK: it gt
+# CHECK: ubfxgt r4, r5, #16, #16
+
+0xc5 0xf3 0x00 0x44
+0xc8 0xbf
+0xc5 0xf3 0x0f 0x44
+
+
+#------------------------------------------------------------------------------
+# UHADD16/UHADD8
+#------------------------------------------------------------------------------
+# CHECK: uhadd16 r4, r8, r2
+# CHECK: uhadd8 r4, r8, r2
+# CHECK: itt gt
+# CHECK: uhadd16gt r4, r8, r2
+# CHECK: uhadd8gt r4, r8, r2
+
+0x98 0xfa 0x62 0xf4
+0x88 0xfa 0x62 0xf4
+0xc4 0xbf
+0x98 0xfa 0x62 0xf4
+0x88 0xfa 0x62 0xf4
+
+
+#------------------------------------------------------------------------------
+# UHASX/UHSAX
+#------------------------------------------------------------------------------
+# CHECK: uhasx r4, r1, r5
+# CHECK: uhsax r5, r6, r6
+# CHECK: itt gt
+# CHECK: uhasxgt r6, r9, r8
+# CHECK: uhsaxgt r7, r8, r12
+
+0xa1 0xfa 0x65 0xf4
+0xe6 0xfa 0x66 0xf5
+0xc4 0xbf
+0xa9 0xfa 0x68 0xf6
+0xe8 0xfa 0x6c 0xf7
+
+#------------------------------------------------------------------------------
+# UHSUB16/UHSUB8
+#------------------------------------------------------------------------------
+# CHECK: uhsub16 r5, r8, r3
+# CHECK: uhsub8 r1, r7, r6
+# CHECK: itt lt
+# CHECK: uhsub16lt r4, r9, r12
+# CHECK: uhsub8lt r3, r1, r5
+
+0xd8 0xfa 0x63 0xf5
+0xc7 0xfa 0x66 0xf1
+0xbc 0xbf
+0xd9 0xfa 0x6c 0xf4
+0xc1 0xfa 0x65 0xf3
+
+
+#------------------------------------------------------------------------------
+# UMAAL
+#------------------------------------------------------------------------------
+# CHECK: umaal r3, r4, r5, r6
+# CHECK: it lt
+# CHECK: umaallt r3, r4, r5, r6
+
+0xe5 0xfb 0x66 0x34
+0xb8 0xbf
+0xe5 0xfb 0x66 0x34
+
+
+#------------------------------------------------------------------------------
+# UMLAL
+#------------------------------------------------------------------------------
+# CHECK: umlal r2, r4, r6, r8
+# CHECK: it gt
+# CHECK: umlalgt r6, r1, r2, r6
+
+0xe6 0xfb 0x08 0x24
+0xc8 0xbf
+0xe2 0xfb 0x06 0x61
+
+
+#------------------------------------------------------------------------------
+# UMULL
+#------------------------------------------------------------------------------
+# CHECK: umull r2, r4, r6, r8
+# CHECK: it gt
+# CHECK: umullgt r6, r1, r2, r6
+
+0xa6 0xfb 0x08 0x24
+0xc8 0xbf
+0xa2 0xfb 0x06 0x61
+
+
+#------------------------------------------------------------------------------
+# UQADD16/UQADD8
+#------------------------------------------------------------------------------
+# CHECK: uqadd16 r1, r2, r3
+# CHECK: uqadd8 r3, r4, r8
+# CHECK: ite gt
+# CHECK: uqadd16gt r4, r7, r9
+# CHECK: uqadd8le r8, r1, r2
+
+0x92 0xfa 0x53 0xf1
+0x84 0xfa 0x58 0xf3
+0xcc 0xbf
+0x97 0xfa 0x59 0xf4
+0x81 0xfa 0x52 0xf8
+
+
+#------------------------------------------------------------------------------
+# UQASX/UQSAX
+#------------------------------------------------------------------------------
+# CHECK: uqasx r1, r2, r3
+# CHECK: uqsax r3, r4, r8
+# CHECK: ite gt
+# CHECK: uqasxgt r4, r7, r9
+# CHECK: uqsaxle r8, r1, r2
+
+0xa2 0xfa 0x53 0xf1
+0xe4 0xfa 0x58 0xf3
+0xcc 0xbf
+0xa7 0xfa 0x59 0xf4
+0xe1 0xfa 0x52 0xf8
+
+
+#------------------------------------------------------------------------------
+# UQSUB16/UQSUB8
+#------------------------------------------------------------------------------
+# CHECK: uqsub8 r8, r2, r9
+# CHECK: uqsub16 r1, r9, r7
+# CHECK: ite gt
+# CHECK: uqsub8gt r3, r1, r6
+# CHECK: uqsub16le r4, r6, r4
+
+0xc2 0xfa 0x59 0xf8
+0xd9 0xfa 0x57 0xf1
+0xcc 0xbf
+0xc1 0xfa 0x56 0xf3
+0xd6 0xfa 0x54 0xf4
+
+
+#------------------------------------------------------------------------------
+# UQSUB16/UQSUB8
+#------------------------------------------------------------------------------
+# CHECK: usad8 r1, r9, r7
+# CHECK: usada8 r8, r2, r9, r12
+# CHECK: ite gt
+# CHECK: usada8gt r3, r1, r6, r9
+# CHECK: usad8le r4, r6, r4
+
+0x79 0xfb 0x07 0xf1
+0x72 0xfb 0x09 0xc8
+0xcc 0xbf
+0x71 0xfb 0x06 0x93
+0x76 0xfb 0x04 0xf4
+
+
+#------------------------------------------------------------------------------
+# USAT
+#------------------------------------------------------------------------------
+# CHECK: usat r8, #1, r10
+# CHECK: usat r8, #4, r10
+# CHECK: usat r8, #5, r10, lsl #31
+# CHECK: usat r8, #16, r10, asr #1
+
+0x8a 0xf3 0x01 0x08
+0x8a 0xf3 0x04 0x08
+0x8a 0xf3 0xc5 0x78
+0xaa 0xf3 0x50 0x08
+
+
+#------------------------------------------------------------------------------
+# USAT16
+#------------------------------------------------------------------------------
+# CHECK: usat16 r2, #2, r7
+# CHECK: usat16 r3, #15, r5
+
+0xa7 0xf3 0x02 0x02
+0xa5 0xf3 0x0f 0x03
+
+
+#------------------------------------------------------------------------------
+# USAX
+#------------------------------------------------------------------------------
+# CHECK: usax r2, r3, r4
+# CHECK: it ne
+# CHECK: usaxne r6, r1, r9
+# CHECK: usax r2, r3, r4
+# CHECK: it ne
+# CHECK: usaxne r6, r1, r9
+
+0xe3 0xfa 0x44 0xf2
+0x18 0xbf
+0xe1 0xfa 0x49 0xf6
+0xe3 0xfa 0x44 0xf2
+0x18 0xbf
+0xe1 0xfa 0x49 0xf6
+
+
+#------------------------------------------------------------------------------
+# USUB16/USUB8
+#------------------------------------------------------------------------------
+# CHECK: usub16 r4, r2, r7
+# CHECK: usub8 r1, r8, r5
+# CHECK: ite hi
+# CHECK: usub16hi r1, r1, r3
+# CHECK: usub8ls r9, r2, r3
+
+0xd2 0xfa 0x47 0xf4
+0xc8 0xfa 0x45 0xf1
+0x8c 0xbf
+0xd1 0xfa 0x43 0xf1
+0xc2 0xfa 0x43 0xf9
+
+
+#------------------------------------------------------------------------------
+# UXTAB
+#------------------------------------------------------------------------------
+# CHECK: uxtab r2, r3, r4
+# CHECK: uxtab r4, r5, r6
+# CHECK: it lt
+# CHECK: uxtablt r6, r2, r9, ror #8
+# CHECK: uxtab r5, r1, r4, ror #16
+# CHECK: uxtab r7, r8, r3, ror #24
+
+0x53 0xfa 0x84 0xf2
+0x55 0xfa 0x86 0xf4
+0xb8 0xbf
+0x52 0xfa 0x99 0xf6
+0x51 0xfa 0xa4 0xf5
+0x58 0xfa 0xb3 0xf7
+
+
+#------------------------------------------------------------------------------
+# UXTAB16
+#------------------------------------------------------------------------------
+# CHECK: it ge
+# CHECK: uxtab16ge r0, r1, r4
+# CHECK: uxtab16 r6, r2, r7
+# CHECK: uxtab16 r3, r5, r8, ror #8
+# CHECK: uxtab16 r3, r2, r1, ror #16
+# CHECK: it eq
+# CHECK: uxtab16eq r1, r2, r3, ror #24
+
+0xa8 0xbf
+0x31 0xfa 0x84 0xf0
+0x32 0xfa 0x87 0xf6
+0x35 0xfa 0x98 0xf3
+0x32 0xfa 0xa1 0xf3
+0x08 0xbf
+0x32 0xfa 0xb3 0xf1
+
+
+#------------------------------------------------------------------------------
+# UXTAH
+#------------------------------------------------------------------------------
+# CHECK: uxtah r1, r3, r9
+# CHECK: it hi
+# CHECK: uxtahhi r6, r1, r6
+# CHECK: uxtah r3, r8, r3, ror #8
+# CHECK: it lo
+# CHECK: uxtahlo r2, r2, r4, ror #16
+# CHECK: uxtah r9, r3, r3, ror #24
+
+0x13 0xfa 0x89 0xf1
+0x88 0xbf
+0x11 0xfa 0x86 0xf6
+0x18 0xfa 0x93 0xf3
+0x38 0xbf
+0x12 0xfa 0xa4 0xf2
+0x13 0xfa 0xb3 0xf9
+
+
+#------------------------------------------------------------------------------
+# UXTB
+#------------------------------------------------------------------------------
+# CHECK: it ge
+# CHECK: uxtbge r2, r4
+# CHECK: uxtb r5, r6
+# CHECK: uxtb.w r6, r9, ror #8
+# CHECK: it lo
+# CHECK: uxtblo.w r5, r1, ror #16
+# CHECK: uxtb.w r8, r3, ror #24
+
+0xa8 0xbf
+0xe2 0xb2
+0xf5 0xb2
+0x5f 0xfa 0x99 0xf6
+0x38 0xbf
+0x5f 0xfa 0xa1 0xf5
+0x5f 0xfa 0xb3 0xf8
+
+
+#------------------------------------------------------------------------------
+# UXTB16
+#------------------------------------------------------------------------------
+# CHECK: uxtb16 r1, r4
+# CHECK: uxtb16 r6, r7
+# CHECK: it hs
+# CHECK: uxtb16hs r3, r5, ror #8
+# CHECK: uxtb16 r3, r1, ror #16
+# CHECK: it ge
+# CHECK: uxtb16ge r2, r3, ror #24
+
+0x3f 0xfa 0x84 0xf1
+0x3f 0xfa 0x87 0xf6
+0x28 0xbf
+0x3f 0xfa 0x95 0xf3
+0x3f 0xfa 0xa1 0xf3
+0xa8 0xbf
+0x3f 0xfa 0xb3 0xf2
+
+
+#------------------------------------------------------------------------------
+# UXTH
+#------------------------------------------------------------------------------
+# CHECK: it ne
+# CHECK: uxthne.w r3, r9
+# CHECK: uxth r1, r6
+# CHECK: uxth.w r3, r8, ror #8
+# CHECK: it le
+# CHECK: uxthle.w r2, r2, ror #16
+# CHECK: uxth.w r9, r3, ror #24
+
+0x18 0xbf
+0x1f 0xfa 0x89 0xf3
+0xb1 0xb2
+0x1f 0xfa 0x98 0xf3
+0xd8 0xbf
+0x1f 0xfa 0xa2 0xf2
+0x1f 0xfa 0xb3 0xf9
+
+
+#------------------------------------------------------------------------------
+# WFE/WFI/YIELD
+#------------------------------------------------------------------------------
+# CHECK: wfe
+# CHECK: wfi
+# CHECK: yield
+# CHECK: itet lt
+# CHECK: wfelt
+# CHECK: wfige
+# CHECK: yieldlt
+
+0x20 0xbf
+0x30 0xbf
+0x10 0xbf
+0xb6 0xbf
+0x20 0xbf
+0x30 0xbf
+0x10 0xbf
+
diff --git a/test/MC/Disassembler/X86/enhanced.txt b/test/MC/Disassembler/X86/enhanced.txt
index fc69499..752ab17 100644
--- a/test/MC/Disassembler/X86/enhanced.txt
+++ b/test/MC/Disassembler/X86/enhanced.txt
@@ -4,3 +4,7 @@
0x0f 0x85 0xf6 0xff 0xff 0xff
# CHECK: [o:movq][w: ][1-r:%gs=r63][1-p::][1-l:8=8][p:,][w: ][0-r:%rcx=r108] <mov> 0:[RCX/108]=0 1:[GS/63]=8
0x65 0x48 0x8b 0x0c 0x25 0x08 0x00 0x00 0x00
+# CHECK: [o:xorps][w: ][2-r:%xmm1=r129][p:,][w: ][0-r:%xmm2=r130] 0:[XMM2/130]=0 1:[XMM2/130]=0 2:[XMM1/129]=0
+0x0f 0x57 0xd1
+# CHECK: [o:andps][w: ][2-r:%xmm1=r129][p:,][w: ][0-r:%xmm2=r130] 0:[XMM2/130]=0 1:[XMM2/130]=0 2:[XMM1/129]=0
+0x0f 0x54 0xd1
diff --git a/test/MC/Disassembler/X86/intel-syntax.txt b/test/MC/Disassembler/X86/intel-syntax.txt
new file mode 100644
index 0000000..54b242d
--- /dev/null
+++ b/test/MC/Disassembler/X86/intel-syntax.txt
@@ -0,0 +1,79 @@
+# RUN: llvm-mc --disassemble %s -triple=x86_64-apple-darwin9 -x86-asm-syntax=intel | FileCheck %s
+
+# CHECK: movsb
+0xa4
+
+# CHECK: movsw
+0x66 0xa5
+
+# CHECK: movsd
+0xa5
+
+# CHECK: movsq
+0x48 0xa5
+
+# CHECK: pop FS
+0x0f 0xa1
+
+# CHECK: pop GS
+0x0f 0xa9
+
+# CHECK: in AL, DX
+0xec
+
+# CHECK: nop
+0x90
+
+# CHECK: xchg EAX, R8D
+0x41 0x90
+
+# CHECK: xchg RAX, R8
+0x49 0x90
+
+# CHECK: add AL, 0
+0x04 0x00
+
+# CHECK: add AX, 0
+0x66 0x05 0x00 0x00
+
+# CHECK: add EAX, 0
+0x05 0x00 0x00 0x00 0x00
+
+# CHECK: add RAX, 0
+0x48 0x05 0x00 0x00 0x00 0x00
+
+# CHECK: adc AL, 0
+0x14 0x00
+
+# CHECK: adc AX, 0
+0x66 0x15 0x00 0x00
+
+# CHECK: adc EAX, 0
+0x15 0x00 0x00 0x00 0x00
+
+# CHECK: adc RAX, 0
+0x48 0x15 0x00 0x00 0x00 0x00
+
+# CHECK: cmp AL, 0
+0x3c 0x00
+
+# CHECK: cmp AX, 0
+0x66 0x3d 0x00 0x00
+
+# CHECK: cmp EAX, 0
+0x3d 0x00 0x00 0x00 0x00
+
+# CHECK: cmp RAX, 0
+0x48 0x3d 0x00 0x00 0x00 0x00
+
+# CHECK: test AL, 0
+0xa8 0x00
+
+# CHECK: test AX, 0
+0x66 0xa9 0x00 0x00
+
+# CHECK: test EAX, 0
+0xa9 0x00 0x00 0x00 0x00
+
+# CHECK: test RAX, 0
+0x48 0xa9 0x00 0x00 0x00 0x00
diff --git a/test/MC/Disassembler/X86/invalid-VEX-vvvv.txt b/test/MC/Disassembler/X86/invalid-VEX-vvvv.txt
new file mode 100644
index 0000000..9feb54c
--- /dev/null
+++ b/test/MC/Disassembler/X86/invalid-VEX-vvvv.txt
@@ -0,0 +1,4 @@
+# RUN: llvm-mc --disassemble %s -triple=x86_64-apple-darwin9 |& grep {invalid instruction encoding}
+
+# This instruction would decode as movmskps if the vvvv field in the VEX prefix was all 1s.
+0xc5 0xf0 0x50 0xc0
diff --git a/test/MC/Disassembler/X86/simple-tests.txt b/test/MC/Disassembler/X86/simple-tests.txt
index 08fb4c5..2dc918c 100644
--- a/test/MC/Disassembler/X86/simple-tests.txt
+++ b/test/MC/Disassembler/X86/simple-tests.txt
@@ -72,3 +72,449 @@
# CHECK: vaddps %ymm3, %ymm1, %ymm0
0xc5 0xf4 0x58 0xc3
+
+# CHECK: vandpd %ymm13, %ymm1, %ymm0
+0xc4 0xc1 0x75 0x54 0xc5
+
+# CHECK: vandps %ymm3, %ymm1, %ymm0
+0xc5 0xf4 0x54 0xc3
+
+# CHECK: vzeroall
+0xc5 0xfc 0x77
+
+# CHECK: vcvtps2pd %xmm0, %ymm0
+0xc5 0xfc 0x5a 0xc0
+
+# CHECK: vandps (%rdx), %xmm1, %xmm7
+0xc5 0xf0 0x54 0x3a
+
+# CHECK: vcvtss2sil %xmm0, %eax
+0xc5 0xfa 0x2d 0xc0
+
+# CHECK: vcvtsd2si %xmm0, %eax
+0xc5 0xfb 0x2d 0xc0
+
+# CHECK: vcvtsd2si %xmm0, %rax
+0xc4 0xe1 0xfb 0x2d 0xc0
+
+# CHECK: vmaskmovpd %xmm0, %xmm1, (%rax)
+0xc4 0xe2 0x71 0x2f 0x00
+
+# CHECK: vmovapd %xmm0, %xmm2
+0xc5 0xf9 0x28 0xd0
+
+# Check X86 immediates print as signed values by default. radr://8795217
+# CHECK: andq $-16, %rsp
+0x48 0x83 0xe4 0xf0
+
+# Check these special case instructions that the immediate is not sign-extend.
+# CHECK: blendps $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x0c 0xca 0x81
+
+# CHECK: blendpd $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x0d 0xca 0x81
+
+# CHECK: pblendw $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x0e 0xca 0x81
+
+# CHECK: mpsadbw $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x42 0xca 0x81
+
+# CHECK: dpps $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x40 0xca 0x81
+
+# CHECK: dppd $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x41 0xca 0x81
+
+# CHECK: insertps $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x21 0xca 0x81
+
+# CHECK: vblendps $129, %ymm2, %ymm5, %ymm1
+0xc4 0xe3 0x55 0x0c 0xca 0x81
+
+# CHECK: vblendps $129, (%rax), %ymm5, %ymm1
+0xc4 0xe3 0x55 0x0c 0x08 0x81
+
+# CHECK: vblendpd $129, %ymm2, %ymm5, %ymm1
+0xc4 0xe3 0x55 0x0d 0xca 0x81
+
+# CHECK: vblendpd $129, (%rax), %ymm5, %ymm1
+0xc4 0xe3 0x55 0x0d 0x08 0x81
+
+# CHECK: vpblendw $129, %xmm2, %xmm5, %xmm1
+0xc4 0xe3 0x51 0x0e 0xca 0x81
+
+# CHECK: vmpsadbw $129, %xmm2, %xmm5, %xmm1
+0xc4 0xe3 0x51 0x42 0xca 0x81
+
+# CHECK: vdpps $129, %ymm2, %ymm5, %ymm1
+0xc4 0xe3 0x55 0x40 0xca 0x81
+
+# CHECK: vdpps $129, (%rax), %ymm5, %ymm1
+0xc4 0xe3 0x55 0x40 0x08 0x81
+
+# CHECK: vdppd $129, %xmm2, %xmm5, %xmm1
+0xc4 0xe3 0x51 0x41 0xca 0x81
+
+# CHECK: vinsertps $129, %xmm3, %xmm2, %xmm1
+0xc4 0xe3 0x69 0x21 0xcb 0x81
+
+# CHECK: pause
+0xf3 0x90
+
+# CHECK: addl %eax, %edi
+0x01 0xc7
+
+# CHECK: addl %edi, %eax
+0x03 0xc7
+
+# CHECK: movl %eax, %edi
+0x89 0xc7
+
+# CHECK: movl %edi, %eax
+0x8b 0xc7
+
+# CHECK: movups %xmm1, %xmm0
+0x0f 0x10 0xc1
+
+# CHECK: movups %xmm0, %xmm1
+0x0f 0x11 0xc1
+
+# CHECK: movaps %xmm1, %xmm0
+0x0f 0x28 0xc1
+
+# CHECK: movaps %xmm0, %xmm1
+0x0f 0x29 0xc1
+
+# CHECK: movupd %xmm1, %xmm0
+0x66 0x0f 0x10 0xc1
+
+# CHECK: movupd %xmm0, %xmm1
+0x66 0x0f 0x11 0xc1
+
+# CHECK: movapd %xmm1, %xmm0
+0x66 0x0f 0x28 0xc1
+
+# CHECK: movapd %xmm0, %xmm1
+0x66 0x0f 0x29 0xc1
+
+# CHECK: vmovups %xmm1, %xmm0
+0xc5 0xf8 0x10 0xc1
+
+# CHECK: vmovups %xmm0, %xmm1
+0xc5 0xf8 0x11 0xc1
+
+# CHECK: vmovaps %xmm1, %xmm0
+0xc5 0xf8 0x28 0xc1
+
+# CHECK: vmovaps %xmm0, %xmm1
+0xc5 0xf8 0x29 0xc1
+
+# CHECK: vmovupd %xmm1, %xmm0
+0xc5 0xf9 0x10 0xc1
+
+# CHECK: vmovupd %xmm0, %xmm1
+0xc5 0xf9 0x11 0xc1
+
+# CHECK: vmovapd %xmm1, %xmm0
+0xc5 0xf9 0x28 0xc1
+
+# CHECK: vmovapd %xmm0, %xmm1
+0xc5 0xf9 0x29 0xc1
+
+# CHECK: vmovups %ymm1, %ymm0
+0xc5 0xfc 0x10 0xc1
+
+# CHECK: vmovups %ymm0, %ymm1
+0xc5 0xfc 0x11 0xc1
+
+# CHECK: vmovaps %ymm1, %ymm0
+0xc5 0xfc 0x28 0xc1
+
+# CHECK: vmovaps %ymm0, %ymm1
+0xc5 0xfc 0x29 0xc1
+
+# CHECK: movdqa %xmm1, %xmm0
+0x66 0x0f 0x6f 0xc1
+
+# CHECK: movdqa %xmm0, %xmm1
+0x66 0x0f 0x7f 0xc1
+
+# CHECK: movdqu %xmm1, %xmm0
+0xf3 0x0f 0x6f 0xc1
+
+# CHECK: movdqu %xmm0, %xmm1
+0xf3 0x0f 0x7f 0xc1
+
+# CHECK: vmovdqa %xmm1, %xmm0
+0xc5 0xf9 0x6f 0xc1
+
+# CHECK: vmovdqa %xmm0, %xmm1
+0xc5 0xf9 0x7f 0xc1
+
+# CHECK: vmovdqa %ymm1, %ymm0
+0xc5 0xfd 0x6f 0xc1
+
+# CHECK: vmovdqa %ymm0, %ymm1
+0xc5 0xfd 0x7f 0xc1
+
+# CHECK: vmovdqu %xmm1, %xmm0
+0xc5 0xfa 0x6f 0xc1
+
+# CHECK: vmovdqu %xmm0, %xmm1
+0xc5 0xfa 0x7f 0xc1
+
+# CHECK: vmovdqu %ymm1, %ymm0
+0xc5 0xfe 0x6f 0xc1
+
+# CHECK: vmovdqu %ymm0, %ymm1
+0xc5 0xfe 0x7f 0xc1
+
+# CHECK: vblendvps %xmm4, %xmm1, %xmm2, %xmm3
+0xc4 0xe3 0x69 0x4a 0xd9 0x41
+
+# CHECK: vroundpd $0, %xmm0, %xmm0
+0xc4 0xe3 0x79 0x09 0xc0 0x00
+
+# CHECK: vroundps $0, %xmm0, %xmm0
+0xc4 0xe3 0x79 0x08 0xc0 0x00
+
+# CHECK: vroundpd $0, %ymm0, %ymm0
+0xc4 0xe3 0x7d 0x09 0xc0 0x00
+
+# CHECK: vroundps $0, %ymm0, %ymm0
+0xc4 0xe3 0x7d 0x08 0xc0 0x00
+
+# CHECK: vroundss $0, %xmm0, %xmm0, %xmm0
+0xc4 0xe3 0x79 0x0a 0xc0 0x00
+
+# CHECK: vroundsd $0, %xmm0, %xmm0, %xmm0
+0xc4 0xe3 0x79 0x0b 0xc0 0x00
+
+# CHECK: crc32b %al, %eax
+0xf2 0x0f 0x38 0xf0 0xc0
+
+# CHECK: crc32w %ax, %eax
+0x66 0xf2 0x0f 0x38 0xf1 0xc0
+
+# CHECK: crc32l %eax, %eax
+0xf2 0x0f 0x38 0xf1 0xc0
+
+# CHECK: crc32q %rax, %rax
+0xf2 0x48 0x0f 0x38 0xf1 0xc0
+
+# CHECK: invept (%rax), %rax
+0x66 0x0f 0x38 0x80 0x00
+
+# CHECK: invvpid (%rax), %rax
+0x66 0x0f 0x38 0x81 0x00
+
+# CHECK: nop
+0x90
+
+# CHECK: xchgl %r8d, %eax
+0x41 0x90
+
+# CHECK: xchgq %r8, %rax
+0x49 0x90
+
+# CHECK: addb $0, %al
+0x04 0x00
+
+# CHECK: addw $0, %ax
+0x66 0x05 0x00 0x00
+
+# CHECK: addl $0, %eax
+0x05 0x00 0x00 0x00 0x00
+
+# CHECK: addq $0, %rax
+0x48 0x05 0x00 0x00 0x00 0x00
+
+# CHECK: adcb $0, %al
+0x14 0x00
+
+# CHECK: adcw $0, %ax
+0x66 0x15 0x00 0x00
+
+# CHECK: adcl $0, %eax
+0x15 0x00 0x00 0x00 0x00
+
+# CHECK: adcq $0, %rax
+0x48 0x15 0x00 0x00 0x00 0x00
+
+# CHECK: cmpb $0, %al
+0x3c 0x00
+
+# CHECK: cmpw $0, %ax
+0x66 0x3d 0x00 0x00
+
+# CHECK: cmpl $0, %eax
+0x3d 0x00 0x00 0x00 0x00
+
+# CHECK: cmpq $0, %rax
+0x48 0x3d 0x00 0x00 0x00 0x00
+
+# CHECK: testb $0, %al
+0xa8 0x00
+
+# CHECK: testw $0, %ax
+0x66 0xa9 0x00 0x00
+
+# CHECK: testl $0, %eax
+0xa9 0x00 0x00 0x00 0x00
+
+# CHECK: testq $0, %rax
+0x48 0xa9 0x00 0x00 0x00 0x00
+
+# CHECK: vaddps %xmm3, %xmm15, %xmm0
+0xc4 0xe1 0x00 0x58 0xc3
+
+# CHECK: movbel (%rax), %eax
+0x0f 0x38 0xf0 0x00
+
+# CHECK: movbel %eax, (%rax)
+0x0f 0x38 0xf1 0x00
+
+# CHECK: movbew (%rax), %ax
+0x66 0x0f 0x38 0xf0 0x00
+
+# CHECK: movbew %ax, (%rax)
+0x66 0x0f 0x38 0xf1 0x00
+
+# CHECK: movbeq (%rax), %rax
+0x48 0x0f 0x38 0xf0 0x00
+
+# CHECK: movbeq %rax, (%rax)
+0x48 0x0f 0x38 0xf1 0x00
+
+# CHECK: rdrandw %ax
+0x66 0x0f 0xc7 0xf0
+
+# CHECK: rdrandl %eax
+0x0f 0xc7 0xf0
+
+# CHECK: rdrandq %rax
+0x48 0x0f 0xc7 0xf0
+
+# CHECK: vroundss $0, %xmm0, %xmm0, %xmm0
+0xc4 0xe3 0x7d 0x0a 0xc0 0x00
+
+# CHECK: vroundsd $0, %xmm0, %xmm0, %xmm0
+0xc4 0xe3 0x7d 0x0b 0xc0 0x00
+
+# CHECK: vcvtsd2si %xmm0, %eax
+0xc4 0xe1 0x7f 0x2d 0xc0
+
+# CHECK: vcvtsd2si %xmm0, %rax
+0xc4 0xe1 0xff 0x2d 0xc0
+
+# CHECK: vucomisd %xmm1, %xmm0
+0xc5 0xfd 0x2e 0xc1
+
+# CHECK: vucomiss %xmm1, %xmm0
+0xc5 0xfc 0x2e 0xc1
+
+# CHECK: vcomisd %xmm1, %xmm0
+0xc5 0xfd 0x2f 0xc1
+
+# CHECK: vcomiss %xmm1, %xmm0
+0xc5 0xfc 0x2f 0xc1
+
+# CHECK: vaddss %xmm1, %xmm0, %xmm0
+0xc5 0xfe 0x58 0xc1
+
+# CHECK: xsave (%rax)
+0x0f 0xae 0x20
+
+# CHECK: xrstor (%rax)
+0x0f 0xae 0x28
+
+# CHECK: xsaveopt (%rax)
+0x0f 0xae 0x30
+
+# CHECK: rdfsbasel %eax
+0xf3 0x0f 0xae 0xc0
+
+# CHECK: rdgsbasel %eax
+0xf3 0x0f 0xae 0xc8
+
+# CHECK: wrfsbasel %eax
+0xf3 0x0f 0xae 0xd0
+
+# CHECK: wrgsbasel %eax
+0xf3 0x0f 0xae 0xd8
+
+# CHECK: rdfsbaseq %rax
+0xf3 0x48 0x0f 0xae 0xc0
+
+# CHECK: rdgsbaseq %rax
+0xf3 0x48 0x0f 0xae 0xc8
+
+# CHECK: wrfsbaseq %rax
+0xf3 0x48 0x0f 0xae 0xd0
+
+# CHECK: wrgsbaseq %rax
+0xf3 0x48 0x0f 0xae 0xd8
+
+# CHECK: vcvtph2ps %xmm0, %xmm0
+0xc4 0xe2 0x79 0x13 0xc0
+
+# CHECK: vcvtph2ps (%rax), %xmm0
+0xc4 0xe2 0x79 0x13 0x00
+
+# CHECK: vcvtph2ps %xmm0, %ymm0
+0xc4 0xe2 0x7d 0x13 0xc0
+
+# CHECK: vcvtph2ps (%rax), %ymm0
+0xc4 0xe2 0x7d 0x13 0x00
+
+# CHECK: vcvtps2ph $0, %xmm0, %xmm0
+0xc4 0xe3 0x79 0x1d 0xc0 0x00
+
+# CHECK: vcvtps2ph $0, %xmm0, (%rax)
+0xc4 0xe3 0x79 0x1d 0x00 0x00
+
+# CHECK: vcvtps2ph $0, %ymm0, %xmm0
+0xc4 0xe3 0x7d 0x1d 0xc0 0x00
+
+# CHECK: vcvtps2ph $0, %ymm0, (%rax)
+0xc4 0xe3 0x7d 0x1d 0x00 0x00
+
+# CHECK: popcntl %eax, %eax
+0xf3 0x0f 0xb8 0xc0
+
+# CHECK: popcntw %ax, %ax
+0x66 0xf3 0x0f 0xb8 0xc0
+
+# CHECK: popcntq %rax, %rax
+0xf3 0x48 0x0f 0xb8 0xc0
+
+# CHECK: lzcntl %eax, %eax
+0xf3 0x0f 0xbd 0xc0
+
+# CHECK: lzcntw %ax, %ax
+0x66 0xf3 0x0f 0xbd 0xc0
+
+# CHECK: lzcntq %rax, %rax
+0xf3 0x48 0x0f 0xbd 0xc0
+
+# CHECK: tzcntl %eax, %eax
+0xf3 0x0f 0xbc 0xc0
+
+# CHECK: tzcntw %ax, %ax
+0x66 0xf3 0x0f 0xbc 0xc0
+
+# CHECK: tzcntq %rax, %rax
+0xf3 0x48 0x0f 0xbc 0xc0
+
+# CHECK: andnl %ecx, %r15d, %eax
+0xc4 0xe2 0x00 0xf2 0xc1
+
+# CHECK: andnq %rax, %r15, %rax
+0xc4 0xe2 0x80 0xf2 0xc0
+
+# CHECK: andnl (%rax), %r15d, %eax
+0xc4 0xe2 0x00 0xf2 0x00
+
+# CHECK: andnq (%rax), %r15, %rax
+0xc4 0xe2 0x80 0xf2 0x00
diff --git a/test/MC/Disassembler/X86/x86-32.txt b/test/MC/Disassembler/X86/x86-32.txt
index dd313f1..c4437ba 100644
--- a/test/MC/Disassembler/X86/x86-32.txt
+++ b/test/MC/Disassembler/X86/x86-32.txt
@@ -24,3 +24,474 @@
# CHECK: pshufb
0x0f 0x38 0x00 0xc0
+
+# CHECK: crc32b %al, %eax
+0xf2 0x0f 0x38 0xf0 0xc0
+
+# CHECK: crc32w %ax, %eax
+0x66 0xf2 0x0f 0x38 0xf1 0xc0
+
+# CHECK: crc32l %eax, %eax
+0xf2 0x0f 0x38 0xf1 0xc0
+
+
+# CHECK: int $33
+0xCD 0x21
+
+# CHECK: int $33
+0xCD 0x21
+
+
+# CHECK: addb %al, (%eax)
+0 0
+
+# CHECK: calll -1234
+0xe8 0x2e 0xfb 0xff 0xff
+
+# CHECK: lfence
+0x0f 0xae 0xe8
+
+# CHECK: mfence
+0x0f 0xae 0xf0
+
+# CHECK: monitor
+0x0f 0x01 0xc8
+
+# CHECK: mwait
+0x0f 0x01 0xc9
+
+# CHECK: vmcall
+0x0f 0x01 0xc1
+
+# CHECK: vmlaunch
+0x0f 0x01 0xc2
+
+# CHECK: vmresume
+0x0f 0x01 0xc3
+
+# CHECK: vmxoff
+0x0f 0x01 0xc4
+
+# CHECK: swapgs
+0x0f 0x01 0xf8
+
+# CHECK: rdtscp
+0x0f 0x01 0xf9
+
+# CHECK: vmxon
+0xf3 0x0f 0xc7 0x30
+
+# CHECK: vmptrld
+0x0f 0xc7 0x30
+
+# CHECK: vmptrst
+0x0f 0xc7 0x38
+
+# CHECK: movl $0, -4(%ebp)
+0xc7 0x45 0xfc 0x00 0x00 0x00 0x00
+
+# CHECK: movl %cr0, %ecx
+0x0f 0x20 0xc1
+
+# CHECK: leal 4(%esp), %ecx
+0x8d 0x4c 0x24 0x04
+
+# CHECK: enter $1, $2
+0xc8 0x01 0x00 0x02
+
+# CHECK: movw $47416, -66(%ebp)
+0x66 0xc7 0x45 0xbe 0x38 0xb9
+
+# CHECK: vaddpd %ymm5, %ymm1, %ymm0
+0xc4 0xc1 0x75 0x58 0xc5
+
+# CHECK: vaddps %ymm3, %ymm1, %ymm0
+0xc5 0xf4 0x58 0xc3
+
+# CHECK: vandpd %ymm5, %ymm1, %ymm0
+0xc4 0xc1 0x75 0x54 0xc5
+
+# CHECK: vandps %ymm3, %ymm1, %ymm0
+0xc5 0xf4 0x54 0xc3
+
+# CHECK: vzeroall
+0xc5 0xfc 0x77
+
+# CHECK: vcvtps2pd %xmm0, %ymm0
+0xc5 0xfc 0x5a 0xc0
+
+# CHECK: vandps (%edx), %xmm1, %xmm7
+0xc5 0xf0 0x54 0x3a
+
+# CHECK: vcvtss2sil %xmm0, %eax
+0xc5 0xfa 0x2d 0xc0
+
+# CHECK: vcvtsd2si %xmm0, %eax
+0xc5 0xfb 0x2d 0xc0
+
+# CHECK: vcvtsd2si %xmm0, %eax
+0xc4 0xe1 0x7b 0x2d 0xc0
+
+# CHECK: vmaskmovpd %xmm0, %xmm1, (%eax)
+0xc4 0xe2 0x71 0x2f 0x00
+
+# CHECK: vmovapd %xmm0, %xmm2
+0xc5 0xf9 0x28 0xd0
+
+# Check these special case instructions that the immediate is not sign-extend.
+# CHECK: blendps $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x0c 0xca 0x81
+
+# CHECK: blendpd $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x0d 0xca 0x81
+
+# CHECK: pblendw $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x0e 0xca 0x81
+
+# CHECK: mpsadbw $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x42 0xca 0x81
+
+# CHECK: dpps $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x40 0xca 0x81
+
+# CHECK: dppd $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x41 0xca 0x81
+
+# CHECK: insertps $129, %xmm2, %xmm1
+0x66 0x0f 0x3a 0x21 0xca 0x81
+
+# CHECK: vblendps $129, %ymm2, %ymm5, %ymm1
+0xc4 0xe3 0x55 0x0c 0xca 0x81
+
+# CHECK: vblendps $129, (%eax), %ymm5, %ymm1
+0xc4 0xe3 0x55 0x0c 0x08 0x81
+
+# CHECK: vblendpd $129, %ymm2, %ymm5, %ymm1
+0xc4 0xe3 0x55 0x0d 0xca 0x81
+
+# CHECK: vblendpd $129, (%eax), %ymm5, %ymm1
+0xc4 0xe3 0x55 0x0d 0x08 0x81
+
+# CHECK: vpblendw $129, %xmm2, %xmm5, %xmm1
+0xc4 0xe3 0x51 0x0e 0xca 0x81
+
+# CHECK: vmpsadbw $129, %xmm2, %xmm5, %xmm1
+0xc4 0xe3 0x51 0x42 0xca 0x81
+
+# CHECK: vdpps $129, %ymm2, %ymm5, %ymm1
+0xc4 0xe3 0x55 0x40 0xca 0x81
+
+# CHECK: vdpps $129, (%eax), %ymm5, %ymm1
+0xc4 0xe3 0x55 0x40 0x08 0x81
+
+# CHECK: vdppd $129, %xmm2, %xmm5, %xmm1
+0xc4 0xe3 0x51 0x41 0xca 0x81
+
+# CHECK: vinsertps $129, %xmm3, %xmm2, %xmm1
+0xc4 0xe3 0x69 0x21 0xcb 0x81
+
+# CHECK: pause
+0xf3 0x90
+
+# CHECK: addl %eax, %edi
+0x01 0xc7
+
+# CHECK: addl %edi, %eax
+0x03 0xc7
+
+# CHECK: movl %eax, %edi
+0x89 0xc7
+
+# CHECK: movl %edi, %eax
+0x8b 0xc7
+
+# CHECK: movups %xmm1, %xmm0
+0x0f 0x10 0xc1
+
+# CHECK: movups %xmm0, %xmm1
+0x0f 0x11 0xc1
+
+# CHECK: movaps %xmm1, %xmm0
+0x0f 0x28 0xc1
+
+# CHECK: movaps %xmm0, %xmm1
+0x0f 0x29 0xc1
+
+# CHECK: movupd %xmm1, %xmm0
+0x66 0x0f 0x10 0xc1
+
+# CHECK: movupd %xmm0, %xmm1
+0x66 0x0f 0x11 0xc1
+
+# CHECK: movapd %xmm1, %xmm0
+0x66 0x0f 0x28 0xc1
+
+# CHECK: movapd %xmm0, %xmm1
+0x66 0x0f 0x29 0xc1
+
+# CHECK: vmovups %xmm1, %xmm0
+0xc5 0xf8 0x10 0xc1
+
+# CHECK: vmovups %xmm0, %xmm1
+0xc5 0xf8 0x11 0xc1
+
+# CHECK: vmovaps %xmm1, %xmm0
+0xc5 0xf8 0x28 0xc1
+
+# CHECK: vmovaps %xmm0, %xmm1
+0xc5 0xf8 0x29 0xc1
+
+# CHECK: vmovupd %xmm1, %xmm0
+0xc5 0xf9 0x10 0xc1
+
+# CHECK: vmovupd %xmm0, %xmm1
+0xc5 0xf9 0x11 0xc1
+
+# CHECK: vmovapd %xmm1, %xmm0
+0xc5 0xf9 0x28 0xc1
+
+# CHECK: vmovapd %xmm0, %xmm1
+0xc5 0xf9 0x29 0xc1
+
+# CHECK: vmovups %ymm1, %ymm0
+0xc5 0xfc 0x10 0xc1
+
+# CHECK: vmovups %ymm0, %ymm1
+0xc5 0xfc 0x11 0xc1
+
+# CHECK: vmovaps %ymm1, %ymm0
+0xc5 0xfc 0x28 0xc1
+
+# CHECK: vmovaps %ymm0, %ymm1
+0xc5 0xfc 0x29 0xc1
+
+# CHECK: movdqa %xmm1, %xmm0
+0x66 0x0f 0x6f 0xc1
+
+# CHECK: movdqa %xmm0, %xmm1
+0x66 0x0f 0x7f 0xc1
+
+# CHECK: movdqu %xmm1, %xmm0
+0xf3 0x0f 0x6f 0xc1
+
+# CHECK: movdqu %xmm0, %xmm1
+0xf3 0x0f 0x7f 0xc1
+
+# CHECK: vmovdqa %xmm1, %xmm0
+0xc5 0xf9 0x6f 0xc1
+
+# CHECK: vmovdqa %xmm0, %xmm1
+0xc5 0xf9 0x7f 0xc1
+
+# CHECK: vmovdqa %ymm1, %ymm0
+0xc5 0xfd 0x6f 0xc1
+
+# CHECK: vmovdqa %ymm0, %ymm1
+0xc5 0xfd 0x7f 0xc1
+
+# CHECK: vmovdqu %xmm1, %xmm0
+0xc5 0xfa 0x6f 0xc1
+
+# CHECK: vmovdqu %xmm0, %xmm1
+0xc5 0xfa 0x7f 0xc1
+
+# CHECK: vmovdqu %ymm1, %ymm0
+0xc5 0xfe 0x6f 0xc1
+
+# CHECK: vmovdqu %ymm0, %ymm1
+0xc5 0xfe 0x7f 0xc1
+
+# CHECK: vblendvps %xmm4, %xmm1, %xmm2, %xmm3
+0xc4 0xe3 0x69 0x4a 0xd9 0x41
+
+# CHECK: vroundpd $0, %xmm0, %xmm0
+0xc4 0xe3 0x79 0x09 0xc0 0x00
+
+# CHECK: vroundps $0, %xmm0, %xmm0
+0xc4 0xe3 0x79 0x08 0xc0 0x00
+
+# CHECK: vroundpd $0, %ymm0, %ymm0
+0xc4 0xe3 0x7d 0x09 0xc0 0x00
+
+# CHECK: vroundps $0, %ymm0, %ymm0
+0xc4 0xe3 0x7d 0x08 0xc0 0x00
+
+# CHECK: vroundss $0, %xmm0, %xmm0, %xmm0
+0xc4 0xe3 0x79 0x0a 0xc0 0x00
+
+# CHECK: vroundsd $0, %xmm0, %xmm0, %xmm0
+0xc4 0xe3 0x79 0x0b 0xc0 0x00
+
+# CHECK: invept (%eax), %eax
+0x66 0x0f 0x38 0x80 0x00
+
+# CHECK: invvpid (%eax), %eax
+0x66 0x0f 0x38 0x81 0x00
+
+# CHECK: nop
+0x90
+
+# CHECK: addb $0, %al
+0x04 0x00
+
+# CHECK: addw $0, %ax
+0x66 0x05 0x00 0x00
+
+# CHECK: addl $0, %eax
+0x05 0x00 0x00 0x00 0x00
+
+# CHECK: adcb $0, %al
+0x14 0x00
+
+# CHECK: adcw $0, %ax
+0x66 0x15 0x00 0x00
+
+# CHECK: adcl $0, %eax
+0x15 0x00 0x00 0x00 0x00
+
+# CHECK: cmpb $0, %al
+0x3c 0x00
+
+# CHECK: cmpw $0, %ax
+0x66 0x3d 0x00 0x00
+
+# CHECK: cmpl $0, %eax
+0x3d 0x00 0x00 0x00 0x00
+
+# CHECK: testb $0, %al
+0xa8 0x00
+
+# CHECK: testw $0, %ax
+0x66 0xa9 0x00 0x00
+
+# CHECK: testl $0, %eax
+0xa9 0x00 0x00 0x00 0x00
+
+# CHECK: movb 0, %al
+0xa0 0x00 0x00 0x00 0x00
+
+# CHECK: movw 0, %ax
+0x66 0xa1 0x00 0x00 0x00 0x00
+
+# CHECK: movl 0, %eax
+0xa1 0x00 0x00 0x00 0x00
+
+# CHECK: movb %al, 0
+0xa2 0x00 0x00 0x00 0x00
+
+# CHECK: movw %ax, 0
+0x66 0xa3 0x00 0x00 0x00 0x00
+
+# CHECK: movl %eax, 0
+0xa3 0x00 0x00 0x00 0x00
+
+# CHECK: vaddps %xmm3, %xmm7, %xmm0
+0xc4 0xe1 0x00 0x58 0xc3
+
+# CHECK: movbel (%eax), %eax
+0x0f 0x38 0xf0 0x00
+
+# CHECK: movbel %eax, (%eax)
+0x0f 0x38 0xf1 0x00
+
+# CHECK: movbew (%eax), %ax
+0x66 0x0f 0x38 0xf0 0x00
+
+# CHECK: movbew %ax, (%eax)
+0x66 0x0f 0x38 0xf1 0x00
+
+# CHECK: rdrandw %ax
+0x66 0x0f 0xc7 0xf0
+
+# CHECK: rdrandl %eax
+0x0f 0xc7 0xf0
+
+# CHECK: vroundss $0, %xmm0, %xmm0, %xmm0
+0xc4 0xe3 0x7d 0x0a 0xc0 0x00
+
+# CHECK: vroundsd $0, %xmm0, %xmm0, %xmm0
+0xc4 0xe3 0x7d 0x0b 0xc0 0x00
+
+# CHECK: vcvtsd2si %xmm0, %eax
+0xc4 0xe1 0x7f 0x2d 0xc0
+
+# CHECK: vcvtsd2si %xmm0, %eax
+0xc4 0xe1 0xff 0x2d 0xc0
+
+# CHECK: vucomisd %xmm1, %xmm0
+0xc5 0xfd 0x2e 0xc1
+
+# CHECK: vucomiss %xmm1, %xmm0
+0xc5 0xfc 0x2e 0xc1
+
+# CHECK: vcomisd %xmm1, %xmm0
+0xc5 0xfd 0x2f 0xc1
+
+# CHECK: vcomiss %xmm1, %xmm0
+0xc5 0xfc 0x2f 0xc1
+
+# CHECK: vaddss %xmm1, %xmm0, %xmm0
+0xc5 0xfe 0x58 0xc1
+
+# CHECK: xsave (%eax)
+0x0f 0xae 0x20
+
+# CHECK: xrstor (%eax)
+0x0f 0xae 0x28
+
+# CHECK: xsaveopt (%eax)
+0x0f 0xae 0x30
+
+# CHECK: vcvtph2ps %xmm0, %xmm0
+0xc4 0xe2 0x79 0x13 0xc0
+
+# CHECK: vcvtph2ps (%eax), %xmm0
+0xc4 0xe2 0x79 0x13 0x00
+
+# CHECK: vcvtph2ps %xmm0, %ymm0
+0xc4 0xe2 0x7d 0x13 0xc0
+
+# CHECK: vcvtph2ps (%eax), %ymm0
+0xc4 0xe2 0x7d 0x13 0x00
+
+# CHECK: vcvtps2ph $0, %xmm0, %xmm0
+0xc4 0xe3 0x79 0x1d 0xc0 0x00
+
+# CHECK: vcvtps2ph $0, %xmm0, (%eax)
+0xc4 0xe3 0x79 0x1d 0x00 0x00
+
+# CHECK: vcvtps2ph $0, %ymm0, %xmm0
+0xc4 0xe3 0x7d 0x1d 0xc0 0x00
+
+# CHECK: vcvtps2ph $0, %ymm0, (%eax)
+0xc4 0xe3 0x7d 0x1d 0x00 0x00
+
+# CHECK: popcntl %eax, %eax
+0xf3 0x0f 0xb8 0xc0
+
+# CHECK: popcntw %ax, %ax
+0x66 0xf3 0x0f 0xb8 0xc0
+
+# CHECK: lzcntl %eax, %eax
+0xf3 0x0f 0xbd 0xc0
+
+# CHECK: lzcntw %ax, %ax
+0x66 0xf3 0x0f 0xbd 0xc0
+
+# CHECK: tzcntl %eax, %eax
+0xf3 0x0f 0xbc 0xc0
+
+# CHECK: tzcntw %ax, %ax
+0x66 0xf3 0x0f 0xbc 0xc0
+
+# CHECK: andnl %ecx, %edi, %eax
+0xc4 0xe2 0x00 0xf2 0xc1
+
+# CHECK: andnl (%eax), %edi, %eax
+0xc4 0xe2 0x00 0xf2 0x00
+
+# CHECK: andnl %ecx, %edi, %eax
+0xc4 0xe2 0x80 0xf2 0xc1
+
+# CHECK: andnl (%eax), %edi, %eax
+0xc4 0xe2 0x80 0xf2 0x00
diff --git a/test/MC/ELF/abs.s b/test/MC/ELF/abs.s
index c598b11..48dbe3d 100644
--- a/test/MC/ELF/abs.s
+++ b/test/MC/ELF/abs.s
@@ -6,11 +6,11 @@
.Lbar:
zed = .Lfoo - .Lbar
-// CHECK: # Symbol 0x00000001
+// CHECK: # Symbol 1
// CHECK-NEXT: (('st_name', 0x00000001) # 'zed'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x0000fff1)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0xfff1)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
diff --git a/test/MC/ELF/alias-reloc.s b/test/MC/ELF/alias-reloc.s
index 67266d6..f0db815 100644
--- a/test/MC/ELF/alias-reloc.s
+++ b/test/MC/ELF/alias-reloc.s
@@ -17,36 +17,36 @@ foo2:
.set bar2,foo2
.quad bar2
-// CHECK: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000001)
+// CHECK: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000001)
// CHECK-NEXT: ('r_sym', 0x00000001)
// CHECK-NEXT: ('r_type', 0x00000004)
-// CHECK-NEXT: ('r_addend', 0xfffffffc)
+// CHECK-NEXT: ('r_addend', 0xfffffffffffffffc)
// CHECK-NEXT: ),
-// CHECK: # Relocation 0x00000001
-// CHECK-NEXT: (('r_offset', 0x00000005)
+// CHECK: # Relocation 1
+// CHECK-NEXT: (('r_offset', 0x0000000000000005)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x00000001)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK: # Symbol 0x00000001
+// CHECK: # Symbol 1
// CHECK-NEXT: (('st_name', 0x00000005) # 'bar'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK: # Symbol 0x00000006
+// CHECK: # Symbol 6
// CHECK-NEXT: (('st_name', 0x0000000e) # 'bar2'
-// CHECK-NEXT: ('st_bind', 0x00000002)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000004)
+// CHECK-NEXT: ('st_bind', 0x2)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0004)
// CHECK-NEXT: ('st_value', 0x0000000000000005)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/alias.s b/test/MC/ELF/alias.s
index 42d54bc..f382628 100644
--- a/test/MC/ELF/alias.s
+++ b/test/MC/ELF/alias.s
@@ -16,70 +16,70 @@ foo4:
bar4 = foo4
.long foo2
-// CHECK: # Symbol 0x00000001
+// CHECK: # Symbol 1
// CHECK-NEXT: (('st_name', 0x00000005) # 'bar'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000002
+// CHECK-NEXT: # Symbol 2
// CHECK-NEXT: (('st_name', 0x0000001d) # 'bar4'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000002)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x2)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000003
+// CHECK-NEXT: # Symbol 3
// CHECK-NEXT: (('st_name', 0x00000001) # 'foo'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000004
+// CHECK-NEXT: # Symbol 4
// CHECK-NEXT: (('st_name', 0x0000000e) # 'foo3'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000005
+// CHECK-NEXT: # Symbol 5
// CHECK-NEXT: (('st_name', 0x00000018) # 'foo4'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000002)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x2)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000006
+// CHECK-NEXT: # Symbol 6
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK: # Symbol 0x00000007
+// CHECK: # Symbol 7
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK: # Symbol 0x00000008
+// CHECK: # Symbol 8
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK: # Symbol 0x00000009
+// CHECK: # Symbol 9
// CHECK-NEXT: (('st_name', 0x00000013) # 'bar3'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
-// CHECK: # Symbol 0x0000000a
+// CHECK: # Symbol 10
// CHECK-NEXT: (('st_name', 0x00000009) # 'bar2'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
diff --git a/test/MC/ELF/align-bss.s b/test/MC/ELF/align-bss.s
index ca6da91..a59232b 100644
--- a/test/MC/ELF/align-bss.s
+++ b/test/MC/ELF/align-bss.s
@@ -7,11 +7,11 @@
// CHECK: ('sh_name', 0x00000007) # '.bss'
// CHECK-NEXT: ('sh_type', 0x00000008)
-// CHECK-NEXT: ('sh_flags', 0x00000003)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000800)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000003)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000800)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000010)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000010)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
diff --git a/test/MC/ELF/align-nops.s b/test/MC/ELF/align-nops.s
index d29cb5b..3bf96e9 100644
--- a/test/MC/ELF/align-nops.s
+++ b/test/MC/ELF/align-nops.s
@@ -17,24 +17,24 @@ f0:
// CHECK: (('sh_name', 0x00000001) # '.text'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000006)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000006)
// CHECK-NEXT: ('sh_addr',
// CHECK-NEXT: ('sh_offset',
-// CHECK-NEXT: ('sh_size', 0x00000010)
+// CHECK-NEXT: ('sh_size', 0x0000000000000010)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '00000000 0f1f4000 00000000 0f1f4000')
// CHECK: (('sh_name', 0x00000026) # '.data'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000003)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000003)
// CHECK-NEXT: ('sh_addr',
// CHECK-NEXT: ('sh_offset',
-// CHECK-NEXT: ('sh_size', 0x00000010)
+// CHECK-NEXT: ('sh_size', 0x0000000000000010)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '00000000 90909090 00000000 00000000')
diff --git a/test/MC/ELF/align-size.s b/test/MC/ELF/align-size.s
index 85331d7..f628291 100644
--- a/test/MC/ELF/align-size.s
+++ b/test/MC/ELF/align-size.s
@@ -7,7 +7,7 @@
// CHECK: (('sh_name', 0x00000001) # '.text'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000006)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000008)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000006)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000008)
diff --git a/test/MC/ELF/align-text.s b/test/MC/ELF/align-text.s
index 1d2dacb..2fd3cba 100644
--- a/test/MC/ELF/align-text.s
+++ b/test/MC/ELF/align-text.s
@@ -8,12 +8,12 @@
// CHECK: (('sh_name', 0x00000001) # '.text'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000006)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000002)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000006)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000002)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/align.s b/test/MC/ELF/align.s
index c1e7086..3142ffb 100644
--- a/test/MC/ELF/align.s
+++ b/test/MC/ELF/align.s
@@ -7,26 +7,26 @@
.section .rodata,"a",@progbits
.align 8
-// CHECK: # Section 0x00000003
+// CHECK: # Section 3
// CHECK-NEXT: (('sh_name', 0x00000007) # '.bss'
// CHECK-NEXT: ('sh_type', 0x00000008)
-// CHECK-NEXT: ('sh_flags', 0x00000003)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000044)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000003)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000044)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Section 0x00000004
+// CHECK-NEXT: # Section 4
// CHECK-NEXT: (('sh_name', 0x00000026) # '.rodata'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000048)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000048)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
diff --git a/test/MC/ELF/basic-elf-32.s b/test/MC/ELF/basic-elf-32.s
index 7c2927a..2c6a984 100644
--- a/test/MC/ELF/basic-elf-32.s
+++ b/test/MC/ELF/basic-elf-32.s
@@ -30,9 +30,9 @@ main: # @main
.section .note.GNU-stack,"",@progbits
-// CHECK: ('e_indent[EI_CLASS]', 0x00000001)
-// CHECK: ('e_indent[EI_DATA]', 0x00000001)
-// CHECK: ('e_indent[EI_VERSION]', 0x00000001)
+// CHECK: ('e_indent[EI_CLASS]', 0x01)
+// CHECK: ('e_indent[EI_DATA]', 0x01)
+// CHECK: ('e_indent[EI_VERSION]', 0x01)
// CHECK: ('_sections', [
// CHECK: # Section 0
// CHECK: (('sh_name', 0x00000000) # ''
@@ -42,37 +42,37 @@ main: # @main
// CHECK: # '.rel.text'
// CHECK: ('_relocations', [
-// CHECK: # Relocation 0x00000000
+// CHECK: # Relocation 0
// CHECK: (('r_offset', 0x00000006)
-// CHECK: ('r_type', 0x00000001)
+// CHECK: ('r_type', 0x01)
// CHECK: ),
-// CHECK: # Relocation 0x00000001
+// CHECK: # Relocation 1
// CHECK: (('r_offset', 0x0000000b)
-// CHECK: ('r_type', 0x00000002)
+// CHECK: ('r_type', 0x02)
// CHECK: ),
-// CHECK: # Relocation 0x00000002
+// CHECK: # Relocation 2
// CHECK: (('r_offset', 0x00000012)
-// CHECK: ('r_type', 0x00000001)
+// CHECK: ('r_type', 0x01)
// CHECK: ),
-// CHECK: # Relocation 0x00000003
+// CHECK: # Relocation 3
// CHECK: (('r_offset', 0x00000017)
-// CHECK: ('r_type', 0x00000002)
+// CHECK: ('r_type', 0x02)
// CHECK: ),
// CHECK: ])
-// CHECK: ('st_bind', 0x00000000)
-// CHECK: ('st_type', 0x00000003)
+// CHECK: ('st_bind', 0x0)
+// CHECK: ('st_type', 0x3)
-// CHECK: ('st_bind', 0x00000000)
-// CHECK: ('st_type', 0x00000003)
+// CHECK: ('st_bind', 0x0)
+// CHECK: ('st_type', 0x3)
-// CHECK: ('st_bind', 0x00000000)
-// CHECK: ('st_type', 0x00000003)
+// CHECK: ('st_bind', 0x0)
+// CHECK: ('st_type', 0x3)
// CHECK: # 'main'
-// CHECK: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000002)
+// CHECK: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x2)
// CHECK: # 'puts'
-// CHECK: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
+// CHECK: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
diff --git a/test/MC/ELF/basic-elf-64.s b/test/MC/ELF/basic-elf-64.s
index 5ae1f45..38ffaa7 100644
--- a/test/MC/ELF/basic-elf-64.s
+++ b/test/MC/ELF/basic-elf-64.s
@@ -30,9 +30,9 @@ main: # @main
.section .note.GNU-stack,"",@progbits
-// CHECK: ('e_indent[EI_CLASS]', 0x00000002)
-// CHECK: ('e_indent[EI_DATA]', 0x00000001)
-// CHECK: ('e_indent[EI_VERSION]', 0x00000001)
+// CHECK: ('e_indent[EI_CLASS]', 0x02)
+// CHECK: ('e_indent[EI_DATA]', 0x01)
+// CHECK: ('e_indent[EI_VERSION]', 0x01)
// CHECK: ('_sections', [
// CHECK: # Section 0
// CHECK: (('sh_name', 0x00000000) # ''
@@ -42,41 +42,41 @@ main: # @main
// CHECK: # '.rela.text'
// CHECK: ('_relocations', [
-// CHECK: # Relocation 0x00000000
-// CHECK: (('r_offset', 0x00000005)
+// CHECK: # Relocation 0
+// CHECK: (('r_offset', 0x0000000000000005)
// CHECK: ('r_type', 0x0000000a)
-// CHECK: ('r_addend', 0x00000000)
+// CHECK: ('r_addend', 0x0000000000000000)
// CHECK: ),
-// CHECK: # Relocation 0x00000001
-// CHECK: (('r_offset', 0x0000000a)
+// CHECK: # Relocation 1
+// CHECK: (('r_offset', 0x000000000000000a)
// CHECK: ('r_type', 0x00000002)
-// CHECK: ('r_addend', 0xfffffffc)
+// CHECK: ('r_addend', 0xfffffffffffffffc)
// CHECK: ),
-// CHECK: # Relocation 0x00000002
-// CHECK: (('r_offset', 0x0000000f)
+// CHECK: # Relocation 2
+// CHECK: (('r_offset', 0x000000000000000f)
// CHECK: ('r_type', 0x0000000a)
-// CHECK: ('r_addend', 0x00000006)
+// CHECK: ('r_addend', 0x0000000000000006)
// CHECK: ),
-// CHECK: # Relocation 0x00000003
-// CHECK: (('r_offset', 0x00000014)
+// CHECK: # Relocation 3
+// CHECK: (('r_offset', 0x0000000000000014)
// CHECK: ('r_type', 0x00000002)
-// CHECK: ('r_addend', 0xfffffffc)
+// CHECK: ('r_addend', 0xfffffffffffffffc)
// CHECK: ),
// CHECK: ])
-// CHECK: ('st_bind', 0x00000000)
-// CHECK: ('st_type', 0x00000003)
+// CHECK: ('st_bind', 0x0)
+// CHECK: ('st_type', 0x3)
-// CHECK: ('st_bind', 0x00000000)
-// CHECK: ('st_type', 0x00000003)
+// CHECK: ('st_bind', 0x0)
+// CHECK: ('st_type', 0x3)
-// CHECK: ('st_bind', 0x00000000)
-// CHECK: ('st_type', 0x00000003)
+// CHECK: ('st_bind', 0x0)
+// CHECK: ('st_type', 0x3)
// CHECK: # 'main'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000002)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x2)
// CHECK: # 'puts'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
diff --git a/test/MC/ELF/call-abs.s b/test/MC/ELF/call-abs.s
index 885c2d1..795a659 100644
--- a/test/MC/ELF/call-abs.s
+++ b/test/MC/ELF/call-abs.s
@@ -16,9 +16,9 @@ f: # @f
.section .note.GNU-stack,"",@progbits
// CHECK: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
+// CHECK-NEXT: # Relocation 0
// CHECK-NEXT: (('r_offset', 0x00000004)
-// CHECK-NEXT: ('r_sym', 0x00000000)
-// CHECK-NEXT: ('r_type', 0x00000002)
+// CHECK-NEXT: ('r_sym', 0x000000)
+// CHECK-NEXT: ('r_type', 0x02)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
diff --git a/test/MC/ELF/cfi-adjust-cfa-offset.s b/test/MC/ELF/cfi-adjust-cfa-offset.s
index 5c1a9f9..f0d9c5f 100644
--- a/test/MC/ELF/cfi-adjust-cfa-offset.s
+++ b/test/MC/ELF/cfi-adjust-cfa-offset.s
@@ -11,36 +11,36 @@ f:
ret
.cfi_endproc
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000050)
-// CHECK-NEXT: ('sh_size', 0x00000038)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000050)
+// CHECK-NEXT: ('sh_size', 0x0000000000000038)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 1c000000 1c000000 00000000 0a000000 00440e10 410e1444 0e080000 00000000')
// CHECK-NEXT: ),
-// CHECK-NEXT: # Section 0x00000005
+// CHECK-NEXT: # Section 5
// CHECK-NEXT: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x000003a0)
-// CHECK-NEXT: ('sh_size', 0x00000018)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x00000000000003a0)
+// CHECK-NEXT: ('sh_size', 0x0000000000000018)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/cfi-advance-loc2.s b/test/MC/ELF/cfi-advance-loc2.s
index 163e810..b3c08e0 100644
--- a/test/MC/ELF/cfi-advance-loc2.s
+++ b/test/MC/ELF/cfi-advance-loc2.s
@@ -12,34 +12,34 @@ f:
// CHECK: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000148)
-// CHECK-NEXT: ('sh_size', 0x00000030)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000148)
+// CHECK-NEXT: ('sh_size', 0x0000000000000030)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 01010000 00030001 0e080000')
// CHECK-NEXT: ),
// CHECK: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000490)
-// CHECK-NEXT: ('sh_size', 0x00000018)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000490)
+// CHECK-NEXT: ('sh_size', 0x0000000000000018)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/cfi-def-cfa-offset.s b/test/MC/ELF/cfi-def-cfa-offset.s
index 124d02e..0ed2be0 100644
--- a/test/MC/ELF/cfi-def-cfa-offset.s
+++ b/test/MC/ELF/cfi-def-cfa-offset.s
@@ -10,37 +10,37 @@ f:
ret
.cfi_endproc
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000050)
-// CHECK-NEXT: ('sh_size', 0x00000030)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000050)
+// CHECK-NEXT: ('sh_size', 0x0000000000000030)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 0a000000 00440e10 450e0800')
// CHECK-NEXT: ),
-// CHECK: # Section 0x00000005
+// CHECK: # Section 5
// CHECK-NEXT: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000398)
-// CHECK-NEXT: ('sh_size', 0x00000018)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000398)
+// CHECK-NEXT: ('sh_size', 0x0000000000000018)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/cfi-def-cfa-register.s b/test/MC/ELF/cfi-def-cfa-register.s
index 75311e2..e87b4f6 100644
--- a/test/MC/ELF/cfi-def-cfa-register.s
+++ b/test/MC/ELF/cfi-def-cfa-register.s
@@ -9,33 +9,33 @@ f:
// CHECK: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000048)
-// CHECK-NEXT: ('sh_size', 0x00000030)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000048)
+// CHECK-NEXT: ('sh_size', 0x0000000000000030)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 02000000 00410d06 00000000')
// CHECK-NEXT: ),
// CHECK: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000390)
-// CHECK-NEXT: ('sh_size', 0x00000018)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000390)
+// CHECK-NEXT: ('sh_size', 0x0000000000000018)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/cfi-def-cfa.s b/test/MC/ELF/cfi-def-cfa.s
index 53a169c..e25bf5c 100644
--- a/test/MC/ELF/cfi-def-cfa.s
+++ b/test/MC/ELF/cfi-def-cfa.s
@@ -9,34 +9,34 @@ f:
// CHECK: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000048)
-// CHECK-NEXT: ('sh_size', 0x00000030)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000048)
+// CHECK-NEXT: ('sh_size', 0x0000000000000030)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 02000000 00410c07 08000000')
// CHECK-NEXT: ),
// CHECK: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000390)
-// CHECK-NEXT: ('sh_size', 0x00000018)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000390)
+// CHECK-NEXT: ('sh_size', 0x0000000000000018)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/cfi-offset.s b/test/MC/ELF/cfi-offset.s
index f54dec0..9acb76c 100644
--- a/test/MC/ELF/cfi-offset.s
+++ b/test/MC/ELF/cfi-offset.s
@@ -9,34 +9,34 @@ f:
// CHECK: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000048)
-// CHECK-NEXT: ('sh_size', 0x00000030)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000048)
+// CHECK-NEXT: ('sh_size', 0x0000000000000030)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 02000000 00418602 00000000')
// CHECK-NEXT: ),
// CHECK: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000390)
-// CHECK-NEXT: ('sh_size', 0x00000018)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000390)
+// CHECK-NEXT: ('sh_size', 0x0000000000000018)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/cfi-rel-offset.s b/test/MC/ELF/cfi-rel-offset.s
index 87c0cf3..82bbd8d 100644
--- a/test/MC/ELF/cfi-rel-offset.s
+++ b/test/MC/ELF/cfi-rel-offset.s
@@ -14,36 +14,36 @@ f:
.cfi_rel_offset 6,0
.cfi_endproc
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000048)
-// CHECK-NEXT: ('sh_size', 0x00000040)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000048)
+// CHECK-NEXT: ('sh_size', 0x0000000000000040)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 24000000 1c000000 00000000 05000000 00410e08 410d0641 11067f41 0e104186 02000000 00000000')
// CHECK-NEXT: ),
-// CHECK-NEXT: # Section 0x00000005
+// CHECK-NEXT: # Section 5
// CHECK-NEXT: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x000003a0)
-// CHECK-NEXT: ('sh_size', 0x00000018)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x00000000000003a0)
+// CHECK-NEXT: ('sh_size', 0x0000000000000018)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/cfi-rel-offset2.s b/test/MC/ELF/cfi-rel-offset2.s
index f14beaf..7726adb 100644
--- a/test/MC/ELF/cfi-rel-offset2.s
+++ b/test/MC/ELF/cfi-rel-offset2.s
@@ -6,36 +6,36 @@ f:
.cfi_rel_offset 6,16
.cfi_endproc
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000048)
-// CHECK-NEXT: ('sh_size', 0x00000030)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000048)
+// CHECK-NEXT: ('sh_size', 0x0000000000000030)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 01000000 00411106 7f000000')
// CHECK-NEXT: ),
-// CHECK-NEXT: # Section 0x00000005
+// CHECK-NEXT: # Section 5
// CHECK-NEXT: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000390)
-// CHECK-NEXT: ('sh_size', 0x00000018)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000390)
+// CHECK-NEXT: ('sh_size', 0x0000000000000018)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/cfi-remember.s b/test/MC/ELF/cfi-remember.s
index 814812e..1717662 100644
--- a/test/MC/ELF/cfi-remember.s
+++ b/test/MC/ELF/cfi-remember.s
@@ -9,37 +9,37 @@ f:
nop
.cfi_endproc
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000048)
-// CHECK-NEXT: ('sh_size', 0x00000030)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000048)
+// CHECK-NEXT: ('sh_size', 0x0000000000000030)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 03000000 00410a41 0b000000')
// CHECK-NEXT: ),
-// CHECK: # Section 0x00000005
+// CHECK: # Section 5
// CHECK-NEXT: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000390)
-// CHECK-NEXT: ('sh_size', 0x00000018)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000390)
+// CHECK-NEXT: ('sh_size', 0x0000000000000018)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/cfi-same-value.s b/test/MC/ELF/cfi-same-value.s
index eab1ae4..4c80a0a 100644
--- a/test/MC/ELF/cfi-same-value.s
+++ b/test/MC/ELF/cfi-same-value.s
@@ -7,36 +7,36 @@ f:
nop
.cfi_endproc
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000048)
-// CHECK-NEXT: ('sh_size', 0x00000030)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000048)
+// CHECK-NEXT: ('sh_size', 0x0000000000000030)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 02000000 00410806 00000000')
// CHECK-NEXT: ),
-// CHECK-NEXT: # Section 0x00000005
+// CHECK-NEXT: # Section 5
// CHECK-NEXT: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000390)
-// CHECK-NEXT: ('sh_size', 0x00000018)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000390)
+// CHECK-NEXT: ('sh_size', 0x0000000000000018)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/cfi-sections.s b/test/MC/ELF/cfi-sections.s
index a73f3a9..b256bbf 100644
--- a/test/MC/ELF/cfi-sections.s
+++ b/test/MC/ELF/cfi-sections.s
@@ -15,14 +15,14 @@ f2:
// ELF_64: (('sh_name', 0x00000011) # '.debug_frame'
// ELF_64-NEXT: ('sh_type', 0x00000001)
-// ELF_64-NEXT: ('sh_flags', 0x00000000)
-// ELF_64-NEXT: ('sh_addr', 0x00000000)
-// ELF_64-NEXT: ('sh_offset', 0x00000048)
-// ELF_64-NEXT: ('sh_size', 0x00000048)
+// ELF_64-NEXT: ('sh_flags', 0x0000000000000000)
+// ELF_64-NEXT: ('sh_addr', 0x0000000000000000)
+// ELF_64-NEXT: ('sh_offset', 0x0000000000000048)
+// ELF_64-NEXT: ('sh_size', 0x0000000000000048)
// ELF_64-NEXT: ('sh_link', 0x00000000)
// ELF_64-NEXT: ('sh_info', 0x00000000)
-// ELF_64-NEXT: ('sh_addralign', 0x00000008)
-// ELF_64-NEXT: ('sh_entsize', 0x00000000)
+// ELF_64-NEXT: ('sh_addralign', 0x0000000000000008)
+// ELF_64-NEXT: ('sh_entsize', 0x0000000000000000)
// ELF_64-NEXT: ('_section_data', '14000000 ffffffff 01000178 100c0708 90010000 00000000 14000000 00000000 00000000 00000000 01000000 00000000 14000000 00000000 00000000 00000000 01000000 00000000')
// ELF_32: (('sh_name', 0x00000010) # '.debug_frame'
diff --git a/test/MC/ELF/cfi-zero-addr-delta.s b/test/MC/ELF/cfi-zero-addr-delta.s
index 3ddf69e..9e818e6 100644
--- a/test/MC/ELF/cfi-zero-addr-delta.s
+++ b/test/MC/ELF/cfi-zero-addr-delta.s
@@ -16,33 +16,33 @@ f:
// CHECK: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000048)
-// CHECK-NEXT: ('sh_size', 0x00000038)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000048)
+// CHECK-NEXT: ('sh_size', 0x0000000000000038)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 1c000000 1c000000 00000000 04000000 00410e10 410a0e08 410b0000 00000000')
// CHECK-NEXT: ),
// CHECK: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000398)
-// CHECK-NEXT: ('sh_size', 0x00000018)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000398)
+// CHECK-NEXT: ('sh_size', 0x0000000000000018)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/cfi.s b/test/MC/ELF/cfi.s
index 133b858..9320894 100644
--- a/test/MC/ELF/cfi.s
+++ b/test/MC/ELF/cfi.s
@@ -212,463 +212,463 @@ f36:
nop
.cfi_endproc
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000068)
-// CHECK-NEXT: ('sh_size', 0x000006c8)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000068)
+// CHECK-NEXT: ('sh_size', 0x00000000000006c8)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a4c52 00017810 02031b0c 07089001 14000000 1c000000 00000000 01000000 04000000 00000000 20000000 00000000 017a504c 52000178 100b0000 00000000 00000003 1b0c0708 90010000 14000000 28000000 00000000 01000000 04000000 00000000 14000000 70000000 00000000 01000000 04000000 00000000 20000000 00000000 017a504c 52000178 100b0000 00000000 00000002 1b0c0708 90010000 10000000 28000000 00000000 01000000 02000000 18000000 00000000 017a5052 00017810 04020000 1b0c0708 90010000 10000000 20000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 06030000 00001b0c 07089001 10000000 20000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a040000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 040a0000 1b0c0708 90010000 10000000 20000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 060b0000 00001b0c 07089001 10000000 20000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a0c0000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a080000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a100000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 04120000 1b0c0708 90010000 10000000 20000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 06130000 00001b0c 07089001 10000000 20000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a140000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 041a0000 1b0c0708 90010000 10000000 20000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 061b0000 00001b0c 07089001 10000000 20000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a1c0000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a180000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a800000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 04820000 1b0c0708 90010000 10000000 20000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 06830000 00001b0c 07089001 10000000 20000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a840000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 048a0000 1b0c0708 90010000 10000000 20000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 068b0000 00001b0c 07089001 10000000 20000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a8c0000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a880000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a900000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 04920000 1b0c0708 90010000 10000000 20000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 06930000 00001b0c 07089001 10000000 20000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a940000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 049a0000 1b0c0708 90010000 10000000 20000000 00000000 01000000 00000000 18000000 00000000 017a5052 00017810 069b0000 00001b0c 07089001 10000000 20000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a9c0000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a980000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000')
// CHECK-NEXT: ),
-// CHECK: # Section 0x00000005
+// CHECK: # Section 5
// CHECK-NEXT: (('sh_name', 0x0000000c) # '.rela.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000e30)
-// CHECK-NEXT: ('sh_size', 0x000006c0)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000e30)
+// CHECK-NEXT: ('sh_size', 0x00000000000006c0)
// CHECK-NEXT: ('sh_link', 0x00000007)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000020)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000020)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000001
-// CHECK-NEXT: (('r_offset', 0x00000029)
+// CHECK-NEXT: # Relocation 1
+// CHECK-NEXT: (('r_offset', 0x0000000000000029)
// CHECK-NEXT: ('r_sym', 0x00000028)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000002
-// CHECK-NEXT: (('r_offset', 0x00000043)
+// CHECK-NEXT: # Relocation 2
+// CHECK-NEXT: (('r_offset', 0x0000000000000043)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000001)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000003
-// CHECK-NEXT: (('r_offset', 0x0000005c)
+// CHECK-NEXT: # Relocation 3
+// CHECK-NEXT: (('r_offset', 0x000000000000005c)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000001)
+// CHECK-NEXT: ('r_addend', 0x0000000000000001)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000004
-// CHECK-NEXT: (('r_offset', 0x00000065)
+// CHECK-NEXT: # Relocation 4
+// CHECK-NEXT: (('r_offset', 0x0000000000000065)
// CHECK-NEXT: ('r_sym', 0x00000028)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000005
-// CHECK-NEXT: (('r_offset', 0x00000074)
+// CHECK-NEXT: # Relocation 5
+// CHECK-NEXT: (('r_offset', 0x0000000000000074)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000002)
+// CHECK-NEXT: ('r_addend', 0x0000000000000002)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000006
-// CHECK-NEXT: (('r_offset', 0x0000007d)
+// CHECK-NEXT: # Relocation 6
+// CHECK-NEXT: (('r_offset', 0x000000000000007d)
// CHECK-NEXT: ('r_sym', 0x00000028)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000007
-// CHECK-NEXT: (('r_offset', 0x00000097)
+// CHECK-NEXT: # Relocation 7
+// CHECK-NEXT: (('r_offset', 0x0000000000000097)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000001)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000008
-// CHECK-NEXT: (('r_offset', 0x000000b0)
+// CHECK-NEXT: # Relocation 8
+// CHECK-NEXT: (('r_offset', 0x00000000000000b0)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000003)
+// CHECK-NEXT: ('r_addend', 0x0000000000000003)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000009
-// CHECK-NEXT: (('r_offset', 0x000000b9)
+// CHECK-NEXT: # Relocation 9
+// CHECK-NEXT: (('r_offset', 0x00000000000000b9)
// CHECK-NEXT: ('r_sym', 0x00000028)
// CHECK-NEXT: ('r_type', 0x0000000c)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000000a
-// CHECK-NEXT: (('r_offset', 0x000000ce)
+// CHECK-NEXT: # Relocation 10
+// CHECK-NEXT: (('r_offset', 0x00000000000000ce)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000c)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000000b
-// CHECK-NEXT: (('r_offset', 0x000000e0)
+// CHECK-NEXT: # Relocation 11
+// CHECK-NEXT: (('r_offset', 0x00000000000000e0)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000004)
+// CHECK-NEXT: ('r_addend', 0x0000000000000004)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000000c
-// CHECK-NEXT: (('r_offset', 0x000000fe)
+// CHECK-NEXT: # Relocation 12
+// CHECK-NEXT: (('r_offset', 0x00000000000000fe)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000000d
-// CHECK-NEXT: (('r_offset', 0x00000110)
+// CHECK-NEXT: # Relocation 13
+// CHECK-NEXT: (('r_offset', 0x0000000000000110)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000005)
+// CHECK-NEXT: ('r_addend', 0x0000000000000005)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000000e
-// CHECK-NEXT: (('r_offset', 0x0000012e)
+// CHECK-NEXT: # Relocation 14
+// CHECK-NEXT: (('r_offset', 0x000000000000012e)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000001)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000000f
-// CHECK-NEXT: (('r_offset', 0x00000144)
+// CHECK-NEXT: # Relocation 15
+// CHECK-NEXT: (('r_offset', 0x0000000000000144)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000006)
+// CHECK-NEXT: ('r_addend', 0x0000000000000006)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000010
-// CHECK-NEXT: (('r_offset', 0x00000162)
+// CHECK-NEXT: # Relocation 16
+// CHECK-NEXT: (('r_offset', 0x0000000000000162)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000c)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000011
-// CHECK-NEXT: (('r_offset', 0x00000174)
+// CHECK-NEXT: # Relocation 17
+// CHECK-NEXT: (('r_offset', 0x0000000000000174)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000007)
+// CHECK-NEXT: ('r_addend', 0x0000000000000007)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000012
-// CHECK-NEXT: (('r_offset', 0x00000192)
+// CHECK-NEXT: # Relocation 18
+// CHECK-NEXT: (('r_offset', 0x0000000000000192)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000013
-// CHECK-NEXT: (('r_offset', 0x000001a4)
+// CHECK-NEXT: # Relocation 19
+// CHECK-NEXT: (('r_offset', 0x00000000000001a4)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000008)
+// CHECK-NEXT: ('r_addend', 0x0000000000000008)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000014
-// CHECK-NEXT: (('r_offset', 0x000001c2)
+// CHECK-NEXT: # Relocation 20
+// CHECK-NEXT: (('r_offset', 0x00000000000001c2)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000001)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000015
-// CHECK-NEXT: (('r_offset', 0x000001d8)
+// CHECK-NEXT: # Relocation 21
+// CHECK-NEXT: (('r_offset', 0x00000000000001d8)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000009)
+// CHECK-NEXT: ('r_addend', 0x0000000000000009)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000016
-// CHECK-NEXT: (('r_offset', 0x000001f6)
+// CHECK-NEXT: # Relocation 22
+// CHECK-NEXT: (('r_offset', 0x00000000000001f6)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000001)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000017
-// CHECK-NEXT: (('r_offset', 0x0000020c)
+// CHECK-NEXT: # Relocation 23
+// CHECK-NEXT: (('r_offset', 0x000000000000020c)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000000a)
+// CHECK-NEXT: ('r_addend', 0x000000000000000a)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000018
-// CHECK-NEXT: (('r_offset', 0x0000022a)
+// CHECK-NEXT: # Relocation 24
+// CHECK-NEXT: (('r_offset', 0x000000000000022a)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000018)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000019
-// CHECK-NEXT: (('r_offset', 0x00000240)
+// CHECK-NEXT: # Relocation 25
+// CHECK-NEXT: (('r_offset', 0x0000000000000240)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000000b)
+// CHECK-NEXT: ('r_addend', 0x000000000000000b)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000001a
-// CHECK-NEXT: (('r_offset', 0x0000025e)
+// CHECK-NEXT: # Relocation 26
+// CHECK-NEXT: (('r_offset', 0x000000000000025e)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000d)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000001b
-// CHECK-NEXT: (('r_offset', 0x00000270)
+// CHECK-NEXT: # Relocation 27
+// CHECK-NEXT: (('r_offset', 0x0000000000000270)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000000c)
+// CHECK-NEXT: ('r_addend', 0x000000000000000c)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000001c
-// CHECK-NEXT: (('r_offset', 0x0000028e)
+// CHECK-NEXT: # Relocation 28
+// CHECK-NEXT: (('r_offset', 0x000000000000028e)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000001d
-// CHECK-NEXT: (('r_offset', 0x000002a0)
+// CHECK-NEXT: # Relocation 29
+// CHECK-NEXT: (('r_offset', 0x00000000000002a0)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000000d)
+// CHECK-NEXT: ('r_addend', 0x000000000000000d)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000001e
-// CHECK-NEXT: (('r_offset', 0x000002be)
+// CHECK-NEXT: # Relocation 30
+// CHECK-NEXT: (('r_offset', 0x00000000000002be)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000018)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000001f
-// CHECK-NEXT: (('r_offset', 0x000002d4)
+// CHECK-NEXT: # Relocation 31
+// CHECK-NEXT: (('r_offset', 0x00000000000002d4)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000000e)
+// CHECK-NEXT: ('r_addend', 0x000000000000000e)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000020
-// CHECK-NEXT: (('r_offset', 0x000002f2)
+// CHECK-NEXT: # Relocation 32
+// CHECK-NEXT: (('r_offset', 0x00000000000002f2)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000d)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000021
-// CHECK-NEXT: (('r_offset', 0x00000304)
+// CHECK-NEXT: # Relocation 33
+// CHECK-NEXT: (('r_offset', 0x0000000000000304)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000000f)
+// CHECK-NEXT: ('r_addend', 0x000000000000000f)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000022
-// CHECK-NEXT: (('r_offset', 0x00000322)
+// CHECK-NEXT: # Relocation 34
+// CHECK-NEXT: (('r_offset', 0x0000000000000322)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000023
-// CHECK-NEXT: (('r_offset', 0x00000334)
+// CHECK-NEXT: # Relocation 35
+// CHECK-NEXT: (('r_offset', 0x0000000000000334)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000010)
+// CHECK-NEXT: ('r_addend', 0x0000000000000010)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000024
-// CHECK-NEXT: (('r_offset', 0x00000352)
+// CHECK-NEXT: # Relocation 36
+// CHECK-NEXT: (('r_offset', 0x0000000000000352)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000018)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000025
-// CHECK-NEXT: (('r_offset', 0x00000368)
+// CHECK-NEXT: # Relocation 37
+// CHECK-NEXT: (('r_offset', 0x0000000000000368)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000011)
+// CHECK-NEXT: ('r_addend', 0x0000000000000011)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000026
-// CHECK-NEXT: (('r_offset', 0x00000386)
+// CHECK-NEXT: # Relocation 38
+// CHECK-NEXT: (('r_offset', 0x0000000000000386)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000018)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000027
-// CHECK-NEXT: (('r_offset', 0x0000039c)
+// CHECK-NEXT: # Relocation 39
+// CHECK-NEXT: (('r_offset', 0x000000000000039c)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000012)
+// CHECK-NEXT: ('r_addend', 0x0000000000000012)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000028
-// CHECK-NEXT: (('r_offset', 0x000003ba)
+// CHECK-NEXT: # Relocation 40
+// CHECK-NEXT: (('r_offset', 0x00000000000003ba)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000001)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000029
-// CHECK-NEXT: (('r_offset', 0x000003d0)
+// CHECK-NEXT: # Relocation 41
+// CHECK-NEXT: (('r_offset', 0x00000000000003d0)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000013)
+// CHECK-NEXT: ('r_addend', 0x0000000000000013)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000002a
-// CHECK-NEXT: (('r_offset', 0x000003ee)
+// CHECK-NEXT: # Relocation 42
+// CHECK-NEXT: (('r_offset', 0x00000000000003ee)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000c)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000002b
-// CHECK-NEXT: (('r_offset', 0x00000400)
+// CHECK-NEXT: # Relocation 43
+// CHECK-NEXT: (('r_offset', 0x0000000000000400)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000014)
+// CHECK-NEXT: ('r_addend', 0x0000000000000014)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000002c
-// CHECK-NEXT: (('r_offset', 0x0000041e)
+// CHECK-NEXT: # Relocation 44
+// CHECK-NEXT: (('r_offset', 0x000000000000041e)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000002d
-// CHECK-NEXT: (('r_offset', 0x00000430)
+// CHECK-NEXT: # Relocation 45
+// CHECK-NEXT: (('r_offset', 0x0000000000000430)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000015)
+// CHECK-NEXT: ('r_addend', 0x0000000000000015)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000002e
-// CHECK-NEXT: (('r_offset', 0x0000044e)
+// CHECK-NEXT: # Relocation 46
+// CHECK-NEXT: (('r_offset', 0x000000000000044e)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000001)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000002f
-// CHECK-NEXT: (('r_offset', 0x00000464)
+// CHECK-NEXT: # Relocation 47
+// CHECK-NEXT: (('r_offset', 0x0000000000000464)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000016)
+// CHECK-NEXT: ('r_addend', 0x0000000000000016)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000030
-// CHECK-NEXT: (('r_offset', 0x00000482)
+// CHECK-NEXT: # Relocation 48
+// CHECK-NEXT: (('r_offset', 0x0000000000000482)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000c)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000031
-// CHECK-NEXT: (('r_offset', 0x00000494)
+// CHECK-NEXT: # Relocation 49
+// CHECK-NEXT: (('r_offset', 0x0000000000000494)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000017)
+// CHECK-NEXT: ('r_addend', 0x0000000000000017)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000032
-// CHECK-NEXT: (('r_offset', 0x000004b2)
+// CHECK-NEXT: # Relocation 50
+// CHECK-NEXT: (('r_offset', 0x00000000000004b2)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000033
-// CHECK-NEXT: (('r_offset', 0x000004c4)
+// CHECK-NEXT: # Relocation 51
+// CHECK-NEXT: (('r_offset', 0x00000000000004c4)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000018)
+// CHECK-NEXT: ('r_addend', 0x0000000000000018)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000034
-// CHECK-NEXT: (('r_offset', 0x000004e2)
+// CHECK-NEXT: # Relocation 52
+// CHECK-NEXT: (('r_offset', 0x00000000000004e2)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000001)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000035
-// CHECK-NEXT: (('r_offset', 0x000004f8)
+// CHECK-NEXT: # Relocation 53
+// CHECK-NEXT: (('r_offset', 0x00000000000004f8)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000019)
+// CHECK-NEXT: ('r_addend', 0x0000000000000019)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000036
-// CHECK-NEXT: (('r_offset', 0x00000516)
+// CHECK-NEXT: # Relocation 54
+// CHECK-NEXT: (('r_offset', 0x0000000000000516)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000001)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000037
-// CHECK-NEXT: (('r_offset', 0x0000052c)
+// CHECK-NEXT: # Relocation 55
+// CHECK-NEXT: (('r_offset', 0x000000000000052c)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000001a)
+// CHECK-NEXT: ('r_addend', 0x000000000000001a)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000038
-// CHECK-NEXT: (('r_offset', 0x0000054a)
+// CHECK-NEXT: # Relocation 56
+// CHECK-NEXT: (('r_offset', 0x000000000000054a)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000018)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000039
-// CHECK-NEXT: (('r_offset', 0x00000560)
+// CHECK-NEXT: # Relocation 57
+// CHECK-NEXT: (('r_offset', 0x0000000000000560)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000001b)
+// CHECK-NEXT: ('r_addend', 0x000000000000001b)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000003a
-// CHECK-NEXT: (('r_offset', 0x0000057e)
+// CHECK-NEXT: # Relocation 58
+// CHECK-NEXT: (('r_offset', 0x000000000000057e)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000d)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000003b
-// CHECK-NEXT: (('r_offset', 0x00000590)
+// CHECK-NEXT: # Relocation 59
+// CHECK-NEXT: (('r_offset', 0x0000000000000590)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000001c)
+// CHECK-NEXT: ('r_addend', 0x000000000000001c)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000003c
-// CHECK-NEXT: (('r_offset', 0x000005ae)
+// CHECK-NEXT: # Relocation 60
+// CHECK-NEXT: (('r_offset', 0x00000000000005ae)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000003d
-// CHECK-NEXT: (('r_offset', 0x000005c0)
+// CHECK-NEXT: # Relocation 61
+// CHECK-NEXT: (('r_offset', 0x00000000000005c0)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000001d)
+// CHECK-NEXT: ('r_addend', 0x000000000000001d)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000003e
-// CHECK-NEXT: (('r_offset', 0x000005de)
+// CHECK-NEXT: # Relocation 62
+// CHECK-NEXT: (('r_offset', 0x00000000000005de)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000018)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x0000003f
-// CHECK-NEXT: (('r_offset', 0x000005f4)
+// CHECK-NEXT: # Relocation 63
+// CHECK-NEXT: (('r_offset', 0x00000000000005f4)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000001e)
+// CHECK-NEXT: ('r_addend', 0x000000000000001e)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000040
-// CHECK-NEXT: (('r_offset', 0x00000612)
+// CHECK-NEXT: # Relocation 64
+// CHECK-NEXT: (('r_offset', 0x0000000000000612)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x0000000d)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000041
-// CHECK-NEXT: (('r_offset', 0x00000624)
+// CHECK-NEXT: # Relocation 65
+// CHECK-NEXT: (('r_offset', 0x0000000000000624)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000001f)
+// CHECK-NEXT: ('r_addend', 0x000000000000001f)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000042
-// CHECK-NEXT: (('r_offset', 0x00000642)
+// CHECK-NEXT: # Relocation 66
+// CHECK-NEXT: (('r_offset', 0x0000000000000642)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000043
-// CHECK-NEXT: (('r_offset', 0x00000654)
+// CHECK-NEXT: # Relocation 67
+// CHECK-NEXT: (('r_offset', 0x0000000000000654)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000020)
+// CHECK-NEXT: ('r_addend', 0x0000000000000020)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000044
-// CHECK-NEXT: (('r_offset', 0x00000672)
+// CHECK-NEXT: # Relocation 68
+// CHECK-NEXT: (('r_offset', 0x0000000000000672)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000018)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000045
-// CHECK-NEXT: (('r_offset', 0x00000688)
+// CHECK-NEXT: # Relocation 69
+// CHECK-NEXT: (('r_offset', 0x0000000000000688)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000021)
+// CHECK-NEXT: ('r_addend', 0x0000000000000021)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000046
-// CHECK-NEXT: (('r_offset', 0x000006a6)
+// CHECK-NEXT: # Relocation 70
+// CHECK-NEXT: (('r_offset', 0x00000000000006a6)
// CHECK-NEXT: ('r_sym', 0x00000029)
// CHECK-NEXT: ('r_type', 0x00000018)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000047
-// CHECK-NEXT: (('r_offset', 0x000006bc)
+// CHECK-NEXT: # Relocation 71
+// CHECK-NEXT: (('r_offset', 0x00000000000006bc)
// CHECK-NEXT: ('r_sym', 0x00000024)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000022)
+// CHECK-NEXT: ('r_addend', 0x0000000000000022)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/comdat.s b/test/MC/ELF/comdat.s
index be7128b..d7acea6 100644
--- a/test/MC/ELF/comdat.s
+++ b/test/MC/ELF/comdat.s
@@ -3,70 +3,70 @@
// Test that we produce the group sections and that they are a the beginning
// of the file.
-// CHECK: # Section 0x00000001
+// CHECK: # Section 1
// CHECK-NEXT: (('sh_name', 0x0000001b) # '.group'
// CHECK-NEXT: ('sh_type', 0x00000011)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x0000000c)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x000000000000000c)
// CHECK-NEXT: ('sh_link', 0x0000000d)
// CHECK-NEXT: ('sh_info', 0x00000001)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000004)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000004)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Section 0x00000002
+// CHECK-NEXT: # Section 2
// CHECK-NEXT: (('sh_name', 0x0000001b) # '.group'
// CHECK-NEXT: ('sh_type', 0x00000011)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x0000004c)
-// CHECK-NEXT: ('sh_size', 0x00000008)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x000000000000004c)
+// CHECK-NEXT: ('sh_size', 0x0000000000000008)
// CHECK-NEXT: ('sh_link', 0x0000000d)
// CHECK-NEXT: ('sh_info', 0x00000002)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000004)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000004)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Section 0x00000003
+// CHECK-NEXT: # Section 3
// CHECK-NEXT: (('sh_name', 0x0000001b) # '.group'
// CHECK-NEXT: ('sh_type', 0x00000011)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000054)
-// CHECK-NEXT: ('sh_size', 0x00000008)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000054)
+// CHECK-NEXT: ('sh_size', 0x0000000000000008)
// CHECK-NEXT: ('sh_link', 0x0000000d)
// CHECK-NEXT: ('sh_info', 0x0000000d)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000004)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000004)
// CHECK-NEXT: ),
// Test that g1 and g2 are local, but g3 is an undefined global.
-// CHECK: # Symbol 0x00000001
+// CHECK: # Symbol 1
// CHECK-NEXT: (('st_name', 0x00000001) # 'g1'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000007)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0007)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000002
+// CHECK-NEXT: # Symbol 2
// CHECK-NEXT: (('st_name', 0x00000004) # 'g2'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000002)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0002)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK: # Symbol 0x0000000d
+// CHECK: # Symbol 13
// CHECK-NEXT: (('st_name', 0x00000007) # 'g3'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/common.s b/test/MC/ELF/common.s
index 70e2ed2..046306e 100644
--- a/test/MC/ELF/common.s
+++ b/test/MC/ELF/common.s
@@ -9,9 +9,9 @@
.comm common1,1,1
// CHECK: ('st_name', 0x00000001) # 'common1'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000001)
-// CHECK-NEXT: ('st_other', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x1)
+// CHECK-NEXT: ('st_other', 0x00)
// CHECK-NEXT: ('st_shndx',
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000001)
@@ -23,9 +23,9 @@
.comm common2,1,1
// CHECK: ('st_name', 0x00000009) # 'common2'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000001)
-// CHECK-NEXT: ('st_other', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x1)
+// CHECK-NEXT: ('st_other', 0x00)
// CHECK-NEXT: ('st_shndx',
// CHECK-NEXT: ('st_value', 0x0000000000000001)
// CHECK-NEXT: ('st_size', 0x0000000000000001)
@@ -33,12 +33,12 @@
.local common6
.comm common6,8,16
-// CHECK: # Symbol 0x00000003
+// CHECK: # Symbol 3
// CHECK-NEXT: (('st_name', 0x00000011) # 'common6'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000001)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000004)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x1)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0004)
// CHECK-NEXT: ('st_value', 0x0000000000000010)
// CHECK-NEXT: ('st_size', 0x0000000000000008)
// CHECK-NEXT: ),
@@ -48,10 +48,10 @@
.comm common3,4,4
// CHECK: ('st_name', 0x00000019) # 'common3'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000001)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x0000fff2)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x1)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0xfff2)
// CHECK-NEXT: ('st_value', 0x0000000000000004)
// CHECK-NEXT: ('st_size', 0x0000000000000004)
@@ -68,21 +68,21 @@ foo:
.comm common4,40,16
// CHECK: ('st_name', 0x00000025) # 'common4'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000001)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x0000fff2)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x1)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0xfff2)
// CHECK-NEXT: ('st_value', 0x0000000000000010)
// CHECK-NEXT: ('st_size', 0x0000000000000028)
.comm common5,4,4
-// CHECK: # Symbol 0x00000009
+// CHECK: # Symbol 9
// CHECK-NEXT: (('st_name', 0x0000002d) # 'common5'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000001)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x0000fff2)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x1)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0xfff2)
// CHECK-NEXT: ('st_value', 0x0000000000000004)
// CHECK-NEXT: ('st_size', 0x0000000000000004)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/common2.s b/test/MC/ELF/common2.s
index b48ca66..b13577d 100644
--- a/test/MC/ELF/common2.s
+++ b/test/MC/ELF/common2.s
@@ -14,7 +14,7 @@
// CHECK-NEXT: ('sh_flags'
// CHECK-NEXT: ('sh_addr',
// CHECK-NEXT: ('sh_offset',
-// CHECK-NEXT: ('sh_size', 0x00000009)
+// CHECK-NEXT: ('sh_size', 0x0000000000000009)
// CHECK-NEXT: ('sh_link',
// CHECK-NEXT: ('sh_info',
// CHECK-NEXT: ('sh_addralign',
diff --git a/test/MC/ELF/debug-line.s b/test/MC/ELF/debug-line.s
index aa0197d..fed816a 100644
--- a/test/MC/ELF/debug-line.s
+++ b/test/MC/ELF/debug-line.s
@@ -4,14 +4,14 @@
// CHECK: (('sh_name', 0x00000011) # '.debug_line'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000044)
-// CHECK-NEXT: ('sh_size', 0x00000037)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000044)
+// CHECK-NEXT: ('sh_size', 0x0000000000000037)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '33000000 02001c00 00000101 fb0e0d00 01010101 00000001 00000100 666f6f2e 63000000 00000009 02000000 00000000 00150204 000101')
.section .debug_line,"",@progbits
diff --git a/test/MC/ELF/debug-loc.s b/test/MC/ELF/debug-loc.s
index 68e36a5..3eb3797 100644
--- a/test/MC/ELF/debug-loc.s
+++ b/test/MC/ELF/debug-loc.s
@@ -7,17 +7,17 @@
// FIXME: This size is the same as gnu as, but we can probably do a bit better.
// FIXME2: We need a debug_line dumper so that we can test the actual contents.
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: (('sh_name', 0x00000011) # '.debug_line'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000044)
-// CHECK-NEXT: ('sh_size', 0x0000003d)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000044)
+// CHECK-NEXT: ('sh_size', 0x000000000000003d)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ),
.section .debug_line,"",@progbits
diff --git a/test/MC/ELF/diff.s b/test/MC/ELF/diff.s
index 1879a39..4214fc7 100644
--- a/test/MC/ELF/diff.s
+++ b/test/MC/ELF/diff.s
@@ -8,8 +8,8 @@ bar:
zed:
mov zed+(bar-foo), %eax
-// CHECK: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000005)
+// CHECK: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000005)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x0000000b)
-// CHECK-NEXT: ('r_addend', 0x00000001)
+// CHECK-NEXT: ('r_addend', 0x0000000000000001)
diff --git a/test/MC/ELF/empty-dwarf-lines.s b/test/MC/ELF/empty-dwarf-lines.s
index 1b135a6..7baedbc 100644
--- a/test/MC/ELF/empty-dwarf-lines.s
+++ b/test/MC/ELF/empty-dwarf-lines.s
@@ -7,15 +7,15 @@
c:
.asciz "hi\n"
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: (('sh_name', 0x0000000c) # '.debug_line'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000044)
-// CHECK-NEXT: ('sh_size', 0x00000027)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000044)
+// CHECK-NEXT: ('sh_size', 0x0000000000000027)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/empty.s b/test/MC/ELF/empty.s
index d98f0c6..b38a621 100644
--- a/test/MC/ELF/empty.s
+++ b/test/MC/ELF/empty.s
@@ -5,66 +5,66 @@
// CHECK: ('sh_name', 0x00000001) # '.text'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000006)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000006)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK: ('sh_name', 0x00000026) # '.data'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000003)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000003)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK: ('sh_name', 0x00000007) # '.bss'
// CHECK-NEXT: ('sh_type', 0x00000008)
-// CHECK-NEXT: ('sh_flags', 0x00000003)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000003)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK: ('sh_name', 0x0000000c) # '.shstrtab'
// CHECK-NEXT: ('sh_type', 0x00000003)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x0000002c)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x000000000000002c)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK: ('sh_name', 0x0000001e) # '.symtab'
// CHECK-NEXT: ('sh_type', 0x00000002)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
// CHECK-NEXT: ('sh_offset',
-// CHECK-NEXT: ('sh_size', 0x00000060)
+// CHECK-NEXT: ('sh_size', 0x0000000000000060)
// CHECK-NEXT: ('sh_link', 0x00000006)
// CHECK-NEXT: ('sh_info', 0x00000004)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK: ('sh_name', 0x00000016) # '.strtab'
// CHECK-NEXT: ('sh_type', 0x00000003)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
// CHECK-NEXT: ('sh_offset',
-// CHECK-NEXT: ('sh_size', 0x00000001)
+// CHECK-NEXT: ('sh_size', 0x0000000000000001)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
diff --git a/test/MC/ELF/entsize.ll b/test/MC/ELF/entsize.ll
index 74f0413..dce6dba 100644
--- a/test/MC/ELF/entsize.ll
+++ b/test/MC/ELF/entsize.ll
@@ -22,23 +22,23 @@ declare void @foo(i64* nocapture) nounwind
; 64: (('sh_name', 0x0000004e) # '.rodata.str1.1'
; 64-NEXT: ('sh_type', 0x00000001)
-; 64-NEXT: ('sh_flags', 0x00000032)
+; 64-NEXT: ('sh_flags', 0x0000000000000032)
; 64-NEXT: ('sh_addr',
; 64-NEXT: ('sh_offset',
-; 64-NEXT: ('sh_size', 0x0000000d)
+; 64-NEXT: ('sh_size', 0x000000000000000d)
; 64-NEXT: ('sh_link',
; 64-NEXT: ('sh_info',
-; 64-NEXT: ('sh_addralign', 0x00000001)
-; 64-NEXT: ('sh_entsize', 0x00000001)
+; 64-NEXT: ('sh_addralign', 0x0000000000000001)
+; 64-NEXT: ('sh_entsize', 0x0000000000000001)
; 64: (('sh_name', 0x00000041) # '.rodata.cst8'
; 64-NEXT: ('sh_type', 0x00000001)
-; 64-NEXT: ('sh_flags', 0x00000012)
+; 64-NEXT: ('sh_flags', 0x0000000000000012)
; 64-NEXT: ('sh_addr',
; 64-NEXT: ('sh_offset',
-; 64-NEXT: ('sh_size', 0x00000010)
+; 64-NEXT: ('sh_size', 0x0000000000000010)
; 64-NEXT: ('sh_link',
; 64-NEXT: ('sh_info',
-; 64-NEXT: ('sh_addralign', 0x00000008)
-; 64-NEXT: ('sh_entsize', 0x00000008)
+; 64-NEXT: ('sh_addralign', 0x0000000000000008)
+; 64-NEXT: ('sh_entsize', 0x0000000000000008)
diff --git a/test/MC/ELF/entsize.s b/test/MC/ELF/entsize.s
index 415eaef..4645686 100644
--- a/test/MC/ELF/entsize.s
+++ b/test/MC/ELF/entsize.s
@@ -32,38 +32,38 @@
.quad 42
.quad 42
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: ('sh_name', 0x00000048) # '.rodata.str1.1'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000032)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000032)
// CHECK-NEXT: ('sh_addr',
// CHECK-NEXT: ('sh_offset',
-// CHECK-NEXT: ('sh_size', 0x0000000d)
+// CHECK-NEXT: ('sh_size', 0x000000000000000d)
// CHECK-NEXT: ('sh_link',
// CHECK-NEXT: ('sh_info',
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000001)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000001)
-// CHECK: # Section 0x00000005
+// CHECK: # Section 5
// CHECK-NEXT: ('sh_name', 0x00000039) # '.rodata.str2.1'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000032)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000032)
// CHECK-NEXT: ('sh_addr',
// CHECK-NEXT: ('sh_offset',
-// CHECK-NEXT: ('sh_size', 0x00000010)
+// CHECK-NEXT: ('sh_size', 0x0000000000000010)
// CHECK-NEXT: ('sh_link',
// CHECK-NEXT: ('sh_info',
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000002)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000002)
-// CHECK: # Section 0x00000006
+// CHECK: # Section 6
// CHECK-NEXT: ('sh_name', 0x0000002c) # '.rodata.cst8
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000012)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000012)
// CHECK-NEXT: ('sh_addr',
// CHECK-NEXT: ('sh_offset',
-// CHECK-NEXT: ('sh_size', 0x00000010)
+// CHECK-NEXT: ('sh_size', 0x0000000000000010)
// CHECK-NEXT: ('sh_link',
// CHECK-NEXT: ('sh_info',
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000008)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000008)
diff --git a/test/MC/ELF/file.s b/test/MC/ELF/file.s
index d8ccbe6..434fb6e 100644
--- a/test/MC/ELF/file.s
+++ b/test/MC/ELF/file.s
@@ -4,20 +4,20 @@
.file "foo"
foa:
-// CHECK: # Symbol 0x00000001
+// CHECK: # Symbol 1
// CHECK-NEXT: (('st_name', 0x00000001) # 'foo'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000004)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x0000fff1)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x4)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0xfff1)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000002
+// CHECK-NEXT: # Symbol 2
// CHECK-NEXT: (('st_name', 0x00000005) # 'foa'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
diff --git a/test/MC/ELF/global-offset.s b/test/MC/ELF/global-offset.s
index 77f7267..8cc5dbb 100644
--- a/test/MC/ELF/global-offset.s
+++ b/test/MC/ELF/global-offset.s
@@ -1,9 +1,10 @@
// RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s
// We test that _GLOBAL_OFFSET_TABLE_ will account for the two bytes at the
-// start of the addl.
+// start of the addl/leal.
addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ leal _GLOBAL_OFFSET_TABLE_(%ebx), %ebx
// CHECK: ('sh_name', 0x00000005) # '.text'
// CHECK-NEXT: ('sh_type',
@@ -15,4 +16,4 @@
// CHECK-NEXT: ('sh_info',
// CHECK-NEXT: ('sh_addralign',
// CHECK-NEXT: ('sh_entsize',
-// CHECK-NEXT: ('_section_data', '81c30200 0000')
+// CHECK-NEXT: ('_section_data', '81c30200 00008d9b 02000000')
diff --git a/test/MC/ELF/got.s b/test/MC/ELF/got.s
index a3abef5..a849872 100644
--- a/test/MC/ELF/got.s
+++ b/test/MC/ELF/got.s
@@ -7,13 +7,13 @@
movl foo@GOTPCREL(%rip), %eax
// CHECK: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
+// CHECK-NEXT: # Relocation 0
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym',
// CHECK-NEXT: ('r_type', 0x00000003)
// CHECK-NEXT: ('r_addend',
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000001
+// CHECK-NEXT: # Relocation 1
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym',
// CHECK-NEXT: ('r_type', 0x00000009)
@@ -22,4 +22,4 @@
// CHECK-NEXT: ])
// CHECK: (('st_name', 0x00000005) # '_GLOBAL_OFFSET_TABLE_'
-// CHECK-NEXT: ('st_bind', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
diff --git a/test/MC/ELF/ident.s b/test/MC/ELF/ident.s
index b364d60..56af19a 100644
--- a/test/MC/ELF/ident.s
+++ b/test/MC/ELF/ident.s
@@ -2,14 +2,14 @@
// CHECK: (('sh_name', 0x00000007) # '.comment'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000030)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x0000000d)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000030)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x000000000000000d)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000001)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000001)
// CHECK-NEXT: ('_section_data', '00666f6f 00626172 007a6564 00')
.ident "foo"
diff --git a/test/MC/ELF/leb128.s b/test/MC/ELF/leb128.s
index e5f31f4..f6daac8 100644
--- a/test/MC/ELF/leb128.s
+++ b/test/MC/ELF/leb128.s
@@ -8,12 +8,12 @@
// CHECK: (('sh_name', 0x00000001) # '.text'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000006)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000081)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000006)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000081)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '817f7f90 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90')
diff --git a/test/MC/ELF/local-reloc.s b/test/MC/ELF/local-reloc.s
index 8384e0e..b32a9cc 100644
--- a/test/MC/ELF/local-reloc.s
+++ b/test/MC/ELF/local-reloc.s
@@ -7,12 +7,12 @@
foo:
// Section number 1 is .text
-// CHECK: # Section 0x00000001
+// CHECK: # Section 1
// CHECK-next: (('sh_name', 0x00000001) # '.text'
// Relocation refers to symbol number 2
// CHECK: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
+// CHECK-NEXT: # Relocation 0
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type',
@@ -21,11 +21,11 @@ foo:
// CHECK-NEXT: ])
// Symbol number 2 is section number 1
-// CHECK: # Symbol 0x00000002
+// CHECK: # Symbol 2
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000003)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x3)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
diff --git a/test/MC/ELF/many-section.s b/test/MC/ELF/many-section.s
new file mode 100644
index 0000000..e7e723a
--- /dev/null
+++ b/test/MC/ELF/many-section.s
@@ -0,0 +1,93319 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t
+// RUN: llvm-nm %t | FileCheck %s
+
+// CHECK: s000a
+// CHECK-NOT: U
+// CHECK: szzzb
+
+.section saaaa
+.section saaab
+.section saaba
+.section saabb
+.section saaca
+.section saacb
+.section saada
+.section saadb
+.section saaea
+.section saaeb
+.section saafa
+.section saafb
+.section saaga
+.section saagb
+.section saaha
+.section saahb
+.section saaia
+.section saaib
+.section saaja
+.section saajb
+.section saaka
+.section saakb
+.section saala
+.section saalb
+.section saama
+.section saamb
+.section saana
+.section saanb
+.section saaoa
+.section saaob
+.section saapa
+.section saapb
+.section saaqa
+.section saaqb
+.section saara
+.section saarb
+.section saasa
+.section saasb
+.section saata
+.section saatb
+.section saaua
+.section saaub
+.section saava
+.section saavb
+.section saawa
+.section saawb
+.section saaxa
+.section saaxb
+.section saaya
+.section saayb
+.section saaza
+.section saazb
+.section saa1a
+.section saa1b
+.section saa2a
+.section saa2b
+.section saa3a
+.section saa3b
+.section saa4a
+.section saa4b
+.section saa5a
+.section saa5b
+.section saa6a
+.section saa6b
+.section saa7a
+.section saa7b
+.section saa8a
+.section saa8b
+.section saa9a
+.section saa9b
+.section saa0a
+.section saa0b
+.section sabaa
+.section sabab
+.section sabba
+.section sabbb
+.section sabca
+.section sabcb
+.section sabda
+.section sabdb
+.section sabea
+.section sabeb
+.section sabfa
+.section sabfb
+.section sabga
+.section sabgb
+.section sabha
+.section sabhb
+.section sabia
+.section sabib
+.section sabja
+.section sabjb
+.section sabka
+.section sabkb
+.section sabla
+.section sablb
+.section sabma
+.section sabmb
+.section sabna
+.section sabnb
+.section saboa
+.section sabob
+.section sabpa
+.section sabpb
+.section sabqa
+.section sabqb
+.section sabra
+.section sabrb
+.section sabsa
+.section sabsb
+.section sabta
+.section sabtb
+.section sabua
+.section sabub
+.section sabva
+.section sabvb
+.section sabwa
+.section sabwb
+.section sabxa
+.section sabxb
+.section sabya
+.section sabyb
+.section sabza
+.section sabzb
+.section sab1a
+.section sab1b
+.section sab2a
+.section sab2b
+.section sab3a
+.section sab3b
+.section sab4a
+.section sab4b
+.section sab5a
+.section sab5b
+.section sab6a
+.section sab6b
+.section sab7a
+.section sab7b
+.section sab8a
+.section sab8b
+.section sab9a
+.section sab9b
+.section sab0a
+.section sab0b
+.section sacaa
+.section sacab
+.section sacba
+.section sacbb
+.section sacca
+.section saccb
+.section sacda
+.section sacdb
+.section sacea
+.section saceb
+.section sacfa
+.section sacfb
+.section sacga
+.section sacgb
+.section sacha
+.section sachb
+.section sacia
+.section sacib
+.section sacja
+.section sacjb
+.section sacka
+.section sackb
+.section sacla
+.section saclb
+.section sacma
+.section sacmb
+.section sacna
+.section sacnb
+.section sacoa
+.section sacob
+.section sacpa
+.section sacpb
+.section sacqa
+.section sacqb
+.section sacra
+.section sacrb
+.section sacsa
+.section sacsb
+.section sacta
+.section sactb
+.section sacua
+.section sacub
+.section sacva
+.section sacvb
+.section sacwa
+.section sacwb
+.section sacxa
+.section sacxb
+.section sacya
+.section sacyb
+.section sacza
+.section saczb
+.section sac1a
+.section sac1b
+.section sac2a
+.section sac2b
+.section sac3a
+.section sac3b
+.section sac4a
+.section sac4b
+.section sac5a
+.section sac5b
+.section sac6a
+.section sac6b
+.section sac7a
+.section sac7b
+.section sac8a
+.section sac8b
+.section sac9a
+.section sac9b
+.section sac0a
+.section sac0b
+.section sadaa
+.section sadab
+.section sadba
+.section sadbb
+.section sadca
+.section sadcb
+.section sadda
+.section saddb
+.section sadea
+.section sadeb
+.section sadfa
+.section sadfb
+.section sadga
+.section sadgb
+.section sadha
+.section sadhb
+.section sadia
+.section sadib
+.section sadja
+.section sadjb
+.section sadka
+.section sadkb
+.section sadla
+.section sadlb
+.section sadma
+.section sadmb
+.section sadna
+.section sadnb
+.section sadoa
+.section sadob
+.section sadpa
+.section sadpb
+.section sadqa
+.section sadqb
+.section sadra
+.section sadrb
+.section sadsa
+.section sadsb
+.section sadta
+.section sadtb
+.section sadua
+.section sadub
+.section sadva
+.section sadvb
+.section sadwa
+.section sadwb
+.section sadxa
+.section sadxb
+.section sadya
+.section sadyb
+.section sadza
+.section sadzb
+.section sad1a
+.section sad1b
+.section sad2a
+.section sad2b
+.section sad3a
+.section sad3b
+.section sad4a
+.section sad4b
+.section sad5a
+.section sad5b
+.section sad6a
+.section sad6b
+.section sad7a
+.section sad7b
+.section sad8a
+.section sad8b
+.section sad9a
+.section sad9b
+.section sad0a
+.section sad0b
+.section saeaa
+.section saeab
+.section saeba
+.section saebb
+.section saeca
+.section saecb
+.section saeda
+.section saedb
+.section saeea
+.section saeeb
+.section saefa
+.section saefb
+.section saega
+.section saegb
+.section saeha
+.section saehb
+.section saeia
+.section saeib
+.section saeja
+.section saejb
+.section saeka
+.section saekb
+.section saela
+.section saelb
+.section saema
+.section saemb
+.section saena
+.section saenb
+.section saeoa
+.section saeob
+.section saepa
+.section saepb
+.section saeqa
+.section saeqb
+.section saera
+.section saerb
+.section saesa
+.section saesb
+.section saeta
+.section saetb
+.section saeua
+.section saeub
+.section saeva
+.section saevb
+.section saewa
+.section saewb
+.section saexa
+.section saexb
+.section saeya
+.section saeyb
+.section saeza
+.section saezb
+.section sae1a
+.section sae1b
+.section sae2a
+.section sae2b
+.section sae3a
+.section sae3b
+.section sae4a
+.section sae4b
+.section sae5a
+.section sae5b
+.section sae6a
+.section sae6b
+.section sae7a
+.section sae7b
+.section sae8a
+.section sae8b
+.section sae9a
+.section sae9b
+.section sae0a
+.section sae0b
+.section safaa
+.section safab
+.section safba
+.section safbb
+.section safca
+.section safcb
+.section safda
+.section safdb
+.section safea
+.section safeb
+.section saffa
+.section saffb
+.section safga
+.section safgb
+.section safha
+.section safhb
+.section safia
+.section safib
+.section safja
+.section safjb
+.section safka
+.section safkb
+.section safla
+.section saflb
+.section safma
+.section safmb
+.section safna
+.section safnb
+.section safoa
+.section safob
+.section safpa
+.section safpb
+.section safqa
+.section safqb
+.section safra
+.section safrb
+.section safsa
+.section safsb
+.section safta
+.section saftb
+.section safua
+.section safub
+.section safva
+.section safvb
+.section safwa
+.section safwb
+.section safxa
+.section safxb
+.section safya
+.section safyb
+.section safza
+.section safzb
+.section saf1a
+.section saf1b
+.section saf2a
+.section saf2b
+.section saf3a
+.section saf3b
+.section saf4a
+.section saf4b
+.section saf5a
+.section saf5b
+.section saf6a
+.section saf6b
+.section saf7a
+.section saf7b
+.section saf8a
+.section saf8b
+.section saf9a
+.section saf9b
+.section saf0a
+.section saf0b
+.section sagaa
+.section sagab
+.section sagba
+.section sagbb
+.section sagca
+.section sagcb
+.section sagda
+.section sagdb
+.section sagea
+.section sageb
+.section sagfa
+.section sagfb
+.section sagga
+.section saggb
+.section sagha
+.section saghb
+.section sagia
+.section sagib
+.section sagja
+.section sagjb
+.section sagka
+.section sagkb
+.section sagla
+.section saglb
+.section sagma
+.section sagmb
+.section sagna
+.section sagnb
+.section sagoa
+.section sagob
+.section sagpa
+.section sagpb
+.section sagqa
+.section sagqb
+.section sagra
+.section sagrb
+.section sagsa
+.section sagsb
+.section sagta
+.section sagtb
+.section sagua
+.section sagub
+.section sagva
+.section sagvb
+.section sagwa
+.section sagwb
+.section sagxa
+.section sagxb
+.section sagya
+.section sagyb
+.section sagza
+.section sagzb
+.section sag1a
+.section sag1b
+.section sag2a
+.section sag2b
+.section sag3a
+.section sag3b
+.section sag4a
+.section sag4b
+.section sag5a
+.section sag5b
+.section sag6a
+.section sag6b
+.section sag7a
+.section sag7b
+.section sag8a
+.section sag8b
+.section sag9a
+.section sag9b
+.section sag0a
+.section sag0b
+.section sahaa
+.section sahab
+.section sahba
+.section sahbb
+.section sahca
+.section sahcb
+.section sahda
+.section sahdb
+.section sahea
+.section saheb
+.section sahfa
+.section sahfb
+.section sahga
+.section sahgb
+.section sahha
+.section sahhb
+.section sahia
+.section sahib
+.section sahja
+.section sahjb
+.section sahka
+.section sahkb
+.section sahla
+.section sahlb
+.section sahma
+.section sahmb
+.section sahna
+.section sahnb
+.section sahoa
+.section sahob
+.section sahpa
+.section sahpb
+.section sahqa
+.section sahqb
+.section sahra
+.section sahrb
+.section sahsa
+.section sahsb
+.section sahta
+.section sahtb
+.section sahua
+.section sahub
+.section sahva
+.section sahvb
+.section sahwa
+.section sahwb
+.section sahxa
+.section sahxb
+.section sahya
+.section sahyb
+.section sahza
+.section sahzb
+.section sah1a
+.section sah1b
+.section sah2a
+.section sah2b
+.section sah3a
+.section sah3b
+.section sah4a
+.section sah4b
+.section sah5a
+.section sah5b
+.section sah6a
+.section sah6b
+.section sah7a
+.section sah7b
+.section sah8a
+.section sah8b
+.section sah9a
+.section sah9b
+.section sah0a
+.section sah0b
+.section saiaa
+.section saiab
+.section saiba
+.section saibb
+.section saica
+.section saicb
+.section saida
+.section saidb
+.section saiea
+.section saieb
+.section saifa
+.section saifb
+.section saiga
+.section saigb
+.section saiha
+.section saihb
+.section saiia
+.section saiib
+.section saija
+.section saijb
+.section saika
+.section saikb
+.section saila
+.section sailb
+.section saima
+.section saimb
+.section saina
+.section sainb
+.section saioa
+.section saiob
+.section saipa
+.section saipb
+.section saiqa
+.section saiqb
+.section saira
+.section sairb
+.section saisa
+.section saisb
+.section saita
+.section saitb
+.section saiua
+.section saiub
+.section saiva
+.section saivb
+.section saiwa
+.section saiwb
+.section saixa
+.section saixb
+.section saiya
+.section saiyb
+.section saiza
+.section saizb
+.section sai1a
+.section sai1b
+.section sai2a
+.section sai2b
+.section sai3a
+.section sai3b
+.section sai4a
+.section sai4b
+.section sai5a
+.section sai5b
+.section sai6a
+.section sai6b
+.section sai7a
+.section sai7b
+.section sai8a
+.section sai8b
+.section sai9a
+.section sai9b
+.section sai0a
+.section sai0b
+.section sajaa
+.section sajab
+.section sajba
+.section sajbb
+.section sajca
+.section sajcb
+.section sajda
+.section sajdb
+.section sajea
+.section sajeb
+.section sajfa
+.section sajfb
+.section sajga
+.section sajgb
+.section sajha
+.section sajhb
+.section sajia
+.section sajib
+.section sajja
+.section sajjb
+.section sajka
+.section sajkb
+.section sajla
+.section sajlb
+.section sajma
+.section sajmb
+.section sajna
+.section sajnb
+.section sajoa
+.section sajob
+.section sajpa
+.section sajpb
+.section sajqa
+.section sajqb
+.section sajra
+.section sajrb
+.section sajsa
+.section sajsb
+.section sajta
+.section sajtb
+.section sajua
+.section sajub
+.section sajva
+.section sajvb
+.section sajwa
+.section sajwb
+.section sajxa
+.section sajxb
+.section sajya
+.section sajyb
+.section sajza
+.section sajzb
+.section saj1a
+.section saj1b
+.section saj2a
+.section saj2b
+.section saj3a
+.section saj3b
+.section saj4a
+.section saj4b
+.section saj5a
+.section saj5b
+.section saj6a
+.section saj6b
+.section saj7a
+.section saj7b
+.section saj8a
+.section saj8b
+.section saj9a
+.section saj9b
+.section saj0a
+.section saj0b
+.section sakaa
+.section sakab
+.section sakba
+.section sakbb
+.section sakca
+.section sakcb
+.section sakda
+.section sakdb
+.section sakea
+.section sakeb
+.section sakfa
+.section sakfb
+.section sakga
+.section sakgb
+.section sakha
+.section sakhb
+.section sakia
+.section sakib
+.section sakja
+.section sakjb
+.section sakka
+.section sakkb
+.section sakla
+.section saklb
+.section sakma
+.section sakmb
+.section sakna
+.section saknb
+.section sakoa
+.section sakob
+.section sakpa
+.section sakpb
+.section sakqa
+.section sakqb
+.section sakra
+.section sakrb
+.section saksa
+.section saksb
+.section sakta
+.section saktb
+.section sakua
+.section sakub
+.section sakva
+.section sakvb
+.section sakwa
+.section sakwb
+.section sakxa
+.section sakxb
+.section sakya
+.section sakyb
+.section sakza
+.section sakzb
+.section sak1a
+.section sak1b
+.section sak2a
+.section sak2b
+.section sak3a
+.section sak3b
+.section sak4a
+.section sak4b
+.section sak5a
+.section sak5b
+.section sak6a
+.section sak6b
+.section sak7a
+.section sak7b
+.section sak8a
+.section sak8b
+.section sak9a
+.section sak9b
+.section sak0a
+.section sak0b
+.section salaa
+.section salab
+.section salba
+.section salbb
+.section salca
+.section salcb
+.section salda
+.section saldb
+.section salea
+.section saleb
+.section salfa
+.section salfb
+.section salga
+.section salgb
+.section salha
+.section salhb
+.section salia
+.section salib
+.section salja
+.section saljb
+.section salka
+.section salkb
+.section salla
+.section sallb
+.section salma
+.section salmb
+.section salna
+.section salnb
+.section saloa
+.section salob
+.section salpa
+.section salpb
+.section salqa
+.section salqb
+.section salra
+.section salrb
+.section salsa
+.section salsb
+.section salta
+.section saltb
+.section salua
+.section salub
+.section salva
+.section salvb
+.section salwa
+.section salwb
+.section salxa
+.section salxb
+.section salya
+.section salyb
+.section salza
+.section salzb
+.section sal1a
+.section sal1b
+.section sal2a
+.section sal2b
+.section sal3a
+.section sal3b
+.section sal4a
+.section sal4b
+.section sal5a
+.section sal5b
+.section sal6a
+.section sal6b
+.section sal7a
+.section sal7b
+.section sal8a
+.section sal8b
+.section sal9a
+.section sal9b
+.section sal0a
+.section sal0b
+.section samaa
+.section samab
+.section samba
+.section sambb
+.section samca
+.section samcb
+.section samda
+.section samdb
+.section samea
+.section sameb
+.section samfa
+.section samfb
+.section samga
+.section samgb
+.section samha
+.section samhb
+.section samia
+.section samib
+.section samja
+.section samjb
+.section samka
+.section samkb
+.section samla
+.section samlb
+.section samma
+.section sammb
+.section samna
+.section samnb
+.section samoa
+.section samob
+.section sampa
+.section sampb
+.section samqa
+.section samqb
+.section samra
+.section samrb
+.section samsa
+.section samsb
+.section samta
+.section samtb
+.section samua
+.section samub
+.section samva
+.section samvb
+.section samwa
+.section samwb
+.section samxa
+.section samxb
+.section samya
+.section samyb
+.section samza
+.section samzb
+.section sam1a
+.section sam1b
+.section sam2a
+.section sam2b
+.section sam3a
+.section sam3b
+.section sam4a
+.section sam4b
+.section sam5a
+.section sam5b
+.section sam6a
+.section sam6b
+.section sam7a
+.section sam7b
+.section sam8a
+.section sam8b
+.section sam9a
+.section sam9b
+.section sam0a
+.section sam0b
+.section sanaa
+.section sanab
+.section sanba
+.section sanbb
+.section sanca
+.section sancb
+.section sanda
+.section sandb
+.section sanea
+.section saneb
+.section sanfa
+.section sanfb
+.section sanga
+.section sangb
+.section sanha
+.section sanhb
+.section sania
+.section sanib
+.section sanja
+.section sanjb
+.section sanka
+.section sankb
+.section sanla
+.section sanlb
+.section sanma
+.section sanmb
+.section sanna
+.section sannb
+.section sanoa
+.section sanob
+.section sanpa
+.section sanpb
+.section sanqa
+.section sanqb
+.section sanra
+.section sanrb
+.section sansa
+.section sansb
+.section santa
+.section santb
+.section sanua
+.section sanub
+.section sanva
+.section sanvb
+.section sanwa
+.section sanwb
+.section sanxa
+.section sanxb
+.section sanya
+.section sanyb
+.section sanza
+.section sanzb
+.section san1a
+.section san1b
+.section san2a
+.section san2b
+.section san3a
+.section san3b
+.section san4a
+.section san4b
+.section san5a
+.section san5b
+.section san6a
+.section san6b
+.section san7a
+.section san7b
+.section san8a
+.section san8b
+.section san9a
+.section san9b
+.section san0a
+.section san0b
+.section saoaa
+.section saoab
+.section saoba
+.section saobb
+.section saoca
+.section saocb
+.section saoda
+.section saodb
+.section saoea
+.section saoeb
+.section saofa
+.section saofb
+.section saoga
+.section saogb
+.section saoha
+.section saohb
+.section saoia
+.section saoib
+.section saoja
+.section saojb
+.section saoka
+.section saokb
+.section saola
+.section saolb
+.section saoma
+.section saomb
+.section saona
+.section saonb
+.section saooa
+.section saoob
+.section saopa
+.section saopb
+.section saoqa
+.section saoqb
+.section saora
+.section saorb
+.section saosa
+.section saosb
+.section saota
+.section saotb
+.section saoua
+.section saoub
+.section saova
+.section saovb
+.section saowa
+.section saowb
+.section saoxa
+.section saoxb
+.section saoya
+.section saoyb
+.section saoza
+.section saozb
+.section sao1a
+.section sao1b
+.section sao2a
+.section sao2b
+.section sao3a
+.section sao3b
+.section sao4a
+.section sao4b
+.section sao5a
+.section sao5b
+.section sao6a
+.section sao6b
+.section sao7a
+.section sao7b
+.section sao8a
+.section sao8b
+.section sao9a
+.section sao9b
+.section sao0a
+.section sao0b
+.section sapaa
+.section sapab
+.section sapba
+.section sapbb
+.section sapca
+.section sapcb
+.section sapda
+.section sapdb
+.section sapea
+.section sapeb
+.section sapfa
+.section sapfb
+.section sapga
+.section sapgb
+.section sapha
+.section saphb
+.section sapia
+.section sapib
+.section sapja
+.section sapjb
+.section sapka
+.section sapkb
+.section sapla
+.section saplb
+.section sapma
+.section sapmb
+.section sapna
+.section sapnb
+.section sapoa
+.section sapob
+.section sappa
+.section sappb
+.section sapqa
+.section sapqb
+.section sapra
+.section saprb
+.section sapsa
+.section sapsb
+.section sapta
+.section saptb
+.section sapua
+.section sapub
+.section sapva
+.section sapvb
+.section sapwa
+.section sapwb
+.section sapxa
+.section sapxb
+.section sapya
+.section sapyb
+.section sapza
+.section sapzb
+.section sap1a
+.section sap1b
+.section sap2a
+.section sap2b
+.section sap3a
+.section sap3b
+.section sap4a
+.section sap4b
+.section sap5a
+.section sap5b
+.section sap6a
+.section sap6b
+.section sap7a
+.section sap7b
+.section sap8a
+.section sap8b
+.section sap9a
+.section sap9b
+.section sap0a
+.section sap0b
+.section saqaa
+.section saqab
+.section saqba
+.section saqbb
+.section saqca
+.section saqcb
+.section saqda
+.section saqdb
+.section saqea
+.section saqeb
+.section saqfa
+.section saqfb
+.section saqga
+.section saqgb
+.section saqha
+.section saqhb
+.section saqia
+.section saqib
+.section saqja
+.section saqjb
+.section saqka
+.section saqkb
+.section saqla
+.section saqlb
+.section saqma
+.section saqmb
+.section saqna
+.section saqnb
+.section saqoa
+.section saqob
+.section saqpa
+.section saqpb
+.section saqqa
+.section saqqb
+.section saqra
+.section saqrb
+.section saqsa
+.section saqsb
+.section saqta
+.section saqtb
+.section saqua
+.section saqub
+.section saqva
+.section saqvb
+.section saqwa
+.section saqwb
+.section saqxa
+.section saqxb
+.section saqya
+.section saqyb
+.section saqza
+.section saqzb
+.section saq1a
+.section saq1b
+.section saq2a
+.section saq2b
+.section saq3a
+.section saq3b
+.section saq4a
+.section saq4b
+.section saq5a
+.section saq5b
+.section saq6a
+.section saq6b
+.section saq7a
+.section saq7b
+.section saq8a
+.section saq8b
+.section saq9a
+.section saq9b
+.section saq0a
+.section saq0b
+.section saraa
+.section sarab
+.section sarba
+.section sarbb
+.section sarca
+.section sarcb
+.section sarda
+.section sardb
+.section sarea
+.section sareb
+.section sarfa
+.section sarfb
+.section sarga
+.section sargb
+.section sarha
+.section sarhb
+.section saria
+.section sarib
+.section sarja
+.section sarjb
+.section sarka
+.section sarkb
+.section sarla
+.section sarlb
+.section sarma
+.section sarmb
+.section sarna
+.section sarnb
+.section saroa
+.section sarob
+.section sarpa
+.section sarpb
+.section sarqa
+.section sarqb
+.section sarra
+.section sarrb
+.section sarsa
+.section sarsb
+.section sarta
+.section sartb
+.section sarua
+.section sarub
+.section sarva
+.section sarvb
+.section sarwa
+.section sarwb
+.section sarxa
+.section sarxb
+.section sarya
+.section saryb
+.section sarza
+.section sarzb
+.section sar1a
+.section sar1b
+.section sar2a
+.section sar2b
+.section sar3a
+.section sar3b
+.section sar4a
+.section sar4b
+.section sar5a
+.section sar5b
+.section sar6a
+.section sar6b
+.section sar7a
+.section sar7b
+.section sar8a
+.section sar8b
+.section sar9a
+.section sar9b
+.section sar0a
+.section sar0b
+.section sasaa
+.section sasab
+.section sasba
+.section sasbb
+.section sasca
+.section sascb
+.section sasda
+.section sasdb
+.section sasea
+.section saseb
+.section sasfa
+.section sasfb
+.section sasga
+.section sasgb
+.section sasha
+.section sashb
+.section sasia
+.section sasib
+.section sasja
+.section sasjb
+.section saska
+.section saskb
+.section sasla
+.section saslb
+.section sasma
+.section sasmb
+.section sasna
+.section sasnb
+.section sasoa
+.section sasob
+.section saspa
+.section saspb
+.section sasqa
+.section sasqb
+.section sasra
+.section sasrb
+.section sassa
+.section sassb
+.section sasta
+.section sastb
+.section sasua
+.section sasub
+.section sasva
+.section sasvb
+.section saswa
+.section saswb
+.section sasxa
+.section sasxb
+.section sasya
+.section sasyb
+.section sasza
+.section saszb
+.section sas1a
+.section sas1b
+.section sas2a
+.section sas2b
+.section sas3a
+.section sas3b
+.section sas4a
+.section sas4b
+.section sas5a
+.section sas5b
+.section sas6a
+.section sas6b
+.section sas7a
+.section sas7b
+.section sas8a
+.section sas8b
+.section sas9a
+.section sas9b
+.section sas0a
+.section sas0b
+.section sataa
+.section satab
+.section satba
+.section satbb
+.section satca
+.section satcb
+.section satda
+.section satdb
+.section satea
+.section sateb
+.section satfa
+.section satfb
+.section satga
+.section satgb
+.section satha
+.section sathb
+.section satia
+.section satib
+.section satja
+.section satjb
+.section satka
+.section satkb
+.section satla
+.section satlb
+.section satma
+.section satmb
+.section satna
+.section satnb
+.section satoa
+.section satob
+.section satpa
+.section satpb
+.section satqa
+.section satqb
+.section satra
+.section satrb
+.section satsa
+.section satsb
+.section satta
+.section sattb
+.section satua
+.section satub
+.section satva
+.section satvb
+.section satwa
+.section satwb
+.section satxa
+.section satxb
+.section satya
+.section satyb
+.section satza
+.section satzb
+.section sat1a
+.section sat1b
+.section sat2a
+.section sat2b
+.section sat3a
+.section sat3b
+.section sat4a
+.section sat4b
+.section sat5a
+.section sat5b
+.section sat6a
+.section sat6b
+.section sat7a
+.section sat7b
+.section sat8a
+.section sat8b
+.section sat9a
+.section sat9b
+.section sat0a
+.section sat0b
+.section sauaa
+.section sauab
+.section sauba
+.section saubb
+.section sauca
+.section saucb
+.section sauda
+.section saudb
+.section sauea
+.section saueb
+.section saufa
+.section saufb
+.section sauga
+.section saugb
+.section sauha
+.section sauhb
+.section sauia
+.section sauib
+.section sauja
+.section saujb
+.section sauka
+.section saukb
+.section saula
+.section saulb
+.section sauma
+.section saumb
+.section sauna
+.section saunb
+.section sauoa
+.section sauob
+.section saupa
+.section saupb
+.section sauqa
+.section sauqb
+.section saura
+.section saurb
+.section sausa
+.section sausb
+.section sauta
+.section sautb
+.section sauua
+.section sauub
+.section sauva
+.section sauvb
+.section sauwa
+.section sauwb
+.section sauxa
+.section sauxb
+.section sauya
+.section sauyb
+.section sauza
+.section sauzb
+.section sau1a
+.section sau1b
+.section sau2a
+.section sau2b
+.section sau3a
+.section sau3b
+.section sau4a
+.section sau4b
+.section sau5a
+.section sau5b
+.section sau6a
+.section sau6b
+.section sau7a
+.section sau7b
+.section sau8a
+.section sau8b
+.section sau9a
+.section sau9b
+.section sau0a
+.section sau0b
+.section savaa
+.section savab
+.section savba
+.section savbb
+.section savca
+.section savcb
+.section savda
+.section savdb
+.section savea
+.section saveb
+.section savfa
+.section savfb
+.section savga
+.section savgb
+.section savha
+.section savhb
+.section savia
+.section savib
+.section savja
+.section savjb
+.section savka
+.section savkb
+.section savla
+.section savlb
+.section savma
+.section savmb
+.section savna
+.section savnb
+.section savoa
+.section savob
+.section savpa
+.section savpb
+.section savqa
+.section savqb
+.section savra
+.section savrb
+.section savsa
+.section savsb
+.section savta
+.section savtb
+.section savua
+.section savub
+.section savva
+.section savvb
+.section savwa
+.section savwb
+.section savxa
+.section savxb
+.section savya
+.section savyb
+.section savza
+.section savzb
+.section sav1a
+.section sav1b
+.section sav2a
+.section sav2b
+.section sav3a
+.section sav3b
+.section sav4a
+.section sav4b
+.section sav5a
+.section sav5b
+.section sav6a
+.section sav6b
+.section sav7a
+.section sav7b
+.section sav8a
+.section sav8b
+.section sav9a
+.section sav9b
+.section sav0a
+.section sav0b
+.section sawaa
+.section sawab
+.section sawba
+.section sawbb
+.section sawca
+.section sawcb
+.section sawda
+.section sawdb
+.section sawea
+.section saweb
+.section sawfa
+.section sawfb
+.section sawga
+.section sawgb
+.section sawha
+.section sawhb
+.section sawia
+.section sawib
+.section sawja
+.section sawjb
+.section sawka
+.section sawkb
+.section sawla
+.section sawlb
+.section sawma
+.section sawmb
+.section sawna
+.section sawnb
+.section sawoa
+.section sawob
+.section sawpa
+.section sawpb
+.section sawqa
+.section sawqb
+.section sawra
+.section sawrb
+.section sawsa
+.section sawsb
+.section sawta
+.section sawtb
+.section sawua
+.section sawub
+.section sawva
+.section sawvb
+.section sawwa
+.section sawwb
+.section sawxa
+.section sawxb
+.section sawya
+.section sawyb
+.section sawza
+.section sawzb
+.section saw1a
+.section saw1b
+.section saw2a
+.section saw2b
+.section saw3a
+.section saw3b
+.section saw4a
+.section saw4b
+.section saw5a
+.section saw5b
+.section saw6a
+.section saw6b
+.section saw7a
+.section saw7b
+.section saw8a
+.section saw8b
+.section saw9a
+.section saw9b
+.section saw0a
+.section saw0b
+.section saxaa
+.section saxab
+.section saxba
+.section saxbb
+.section saxca
+.section saxcb
+.section saxda
+.section saxdb
+.section saxea
+.section saxeb
+.section saxfa
+.section saxfb
+.section saxga
+.section saxgb
+.section saxha
+.section saxhb
+.section saxia
+.section saxib
+.section saxja
+.section saxjb
+.section saxka
+.section saxkb
+.section saxla
+.section saxlb
+.section saxma
+.section saxmb
+.section saxna
+.section saxnb
+.section saxoa
+.section saxob
+.section saxpa
+.section saxpb
+.section saxqa
+.section saxqb
+.section saxra
+.section saxrb
+.section saxsa
+.section saxsb
+.section saxta
+.section saxtb
+.section saxua
+.section saxub
+.section saxva
+.section saxvb
+.section saxwa
+.section saxwb
+.section saxxa
+.section saxxb
+.section saxya
+.section saxyb
+.section saxza
+.section saxzb
+.section sax1a
+.section sax1b
+.section sax2a
+.section sax2b
+.section sax3a
+.section sax3b
+.section sax4a
+.section sax4b
+.section sax5a
+.section sax5b
+.section sax6a
+.section sax6b
+.section sax7a
+.section sax7b
+.section sax8a
+.section sax8b
+.section sax9a
+.section sax9b
+.section sax0a
+.section sax0b
+.section sayaa
+.section sayab
+.section sayba
+.section saybb
+.section sayca
+.section saycb
+.section sayda
+.section saydb
+.section sayea
+.section sayeb
+.section sayfa
+.section sayfb
+.section sayga
+.section saygb
+.section sayha
+.section sayhb
+.section sayia
+.section sayib
+.section sayja
+.section sayjb
+.section sayka
+.section saykb
+.section sayla
+.section saylb
+.section sayma
+.section saymb
+.section sayna
+.section saynb
+.section sayoa
+.section sayob
+.section saypa
+.section saypb
+.section sayqa
+.section sayqb
+.section sayra
+.section sayrb
+.section saysa
+.section saysb
+.section sayta
+.section saytb
+.section sayua
+.section sayub
+.section sayva
+.section sayvb
+.section saywa
+.section saywb
+.section sayxa
+.section sayxb
+.section sayya
+.section sayyb
+.section sayza
+.section sayzb
+.section say1a
+.section say1b
+.section say2a
+.section say2b
+.section say3a
+.section say3b
+.section say4a
+.section say4b
+.section say5a
+.section say5b
+.section say6a
+.section say6b
+.section say7a
+.section say7b
+.section say8a
+.section say8b
+.section say9a
+.section say9b
+.section say0a
+.section say0b
+.section sazaa
+.section sazab
+.section sazba
+.section sazbb
+.section sazca
+.section sazcb
+.section sazda
+.section sazdb
+.section sazea
+.section sazeb
+.section sazfa
+.section sazfb
+.section sazga
+.section sazgb
+.section sazha
+.section sazhb
+.section sazia
+.section sazib
+.section sazja
+.section sazjb
+.section sazka
+.section sazkb
+.section sazla
+.section sazlb
+.section sazma
+.section sazmb
+.section sazna
+.section saznb
+.section sazoa
+.section sazob
+.section sazpa
+.section sazpb
+.section sazqa
+.section sazqb
+.section sazra
+.section sazrb
+.section sazsa
+.section sazsb
+.section sazta
+.section saztb
+.section sazua
+.section sazub
+.section sazva
+.section sazvb
+.section sazwa
+.section sazwb
+.section sazxa
+.section sazxb
+.section sazya
+.section sazyb
+.section sazza
+.section sazzb
+.section saz1a
+.section saz1b
+.section saz2a
+.section saz2b
+.section saz3a
+.section saz3b
+.section saz4a
+.section saz4b
+.section saz5a
+.section saz5b
+.section saz6a
+.section saz6b
+.section saz7a
+.section saz7b
+.section saz8a
+.section saz8b
+.section saz9a
+.section saz9b
+.section saz0a
+.section saz0b
+.section sa1aa
+.section sa1ab
+.section sa1ba
+.section sa1bb
+.section sa1ca
+.section sa1cb
+.section sa1da
+.section sa1db
+.section sa1ea
+.section sa1eb
+.section sa1fa
+.section sa1fb
+.section sa1ga
+.section sa1gb
+.section sa1ha
+.section sa1hb
+.section sa1ia
+.section sa1ib
+.section sa1ja
+.section sa1jb
+.section sa1ka
+.section sa1kb
+.section sa1la
+.section sa1lb
+.section sa1ma
+.section sa1mb
+.section sa1na
+.section sa1nb
+.section sa1oa
+.section sa1ob
+.section sa1pa
+.section sa1pb
+.section sa1qa
+.section sa1qb
+.section sa1ra
+.section sa1rb
+.section sa1sa
+.section sa1sb
+.section sa1ta
+.section sa1tb
+.section sa1ua
+.section sa1ub
+.section sa1va
+.section sa1vb
+.section sa1wa
+.section sa1wb
+.section sa1xa
+.section sa1xb
+.section sa1ya
+.section sa1yb
+.section sa1za
+.section sa1zb
+.section sa11a
+.section sa11b
+.section sa12a
+.section sa12b
+.section sa13a
+.section sa13b
+.section sa14a
+.section sa14b
+.section sa15a
+.section sa15b
+.section sa16a
+.section sa16b
+.section sa17a
+.section sa17b
+.section sa18a
+.section sa18b
+.section sa19a
+.section sa19b
+.section sa10a
+.section sa10b
+.section sa2aa
+.section sa2ab
+.section sa2ba
+.section sa2bb
+.section sa2ca
+.section sa2cb
+.section sa2da
+.section sa2db
+.section sa2ea
+.section sa2eb
+.section sa2fa
+.section sa2fb
+.section sa2ga
+.section sa2gb
+.section sa2ha
+.section sa2hb
+.section sa2ia
+.section sa2ib
+.section sa2ja
+.section sa2jb
+.section sa2ka
+.section sa2kb
+.section sa2la
+.section sa2lb
+.section sa2ma
+.section sa2mb
+.section sa2na
+.section sa2nb
+.section sa2oa
+.section sa2ob
+.section sa2pa
+.section sa2pb
+.section sa2qa
+.section sa2qb
+.section sa2ra
+.section sa2rb
+.section sa2sa
+.section sa2sb
+.section sa2ta
+.section sa2tb
+.section sa2ua
+.section sa2ub
+.section sa2va
+.section sa2vb
+.section sa2wa
+.section sa2wb
+.section sa2xa
+.section sa2xb
+.section sa2ya
+.section sa2yb
+.section sa2za
+.section sa2zb
+.section sa21a
+.section sa21b
+.section sa22a
+.section sa22b
+.section sa23a
+.section sa23b
+.section sa24a
+.section sa24b
+.section sa25a
+.section sa25b
+.section sa26a
+.section sa26b
+.section sa27a
+.section sa27b
+.section sa28a
+.section sa28b
+.section sa29a
+.section sa29b
+.section sa20a
+.section sa20b
+.section sa3aa
+.section sa3ab
+.section sa3ba
+.section sa3bb
+.section sa3ca
+.section sa3cb
+.section sa3da
+.section sa3db
+.section sa3ea
+.section sa3eb
+.section sa3fa
+.section sa3fb
+.section sa3ga
+.section sa3gb
+.section sa3ha
+.section sa3hb
+.section sa3ia
+.section sa3ib
+.section sa3ja
+.section sa3jb
+.section sa3ka
+.section sa3kb
+.section sa3la
+.section sa3lb
+.section sa3ma
+.section sa3mb
+.section sa3na
+.section sa3nb
+.section sa3oa
+.section sa3ob
+.section sa3pa
+.section sa3pb
+.section sa3qa
+.section sa3qb
+.section sa3ra
+.section sa3rb
+.section sa3sa
+.section sa3sb
+.section sa3ta
+.section sa3tb
+.section sa3ua
+.section sa3ub
+.section sa3va
+.section sa3vb
+.section sa3wa
+.section sa3wb
+.section sa3xa
+.section sa3xb
+.section sa3ya
+.section sa3yb
+.section sa3za
+.section sa3zb
+.section sa31a
+.section sa31b
+.section sa32a
+.section sa32b
+.section sa33a
+.section sa33b
+.section sa34a
+.section sa34b
+.section sa35a
+.section sa35b
+.section sa36a
+.section sa36b
+.section sa37a
+.section sa37b
+.section sa38a
+.section sa38b
+.section sa39a
+.section sa39b
+.section sa30a
+.section sa30b
+.section sa4aa
+.section sa4ab
+.section sa4ba
+.section sa4bb
+.section sa4ca
+.section sa4cb
+.section sa4da
+.section sa4db
+.section sa4ea
+.section sa4eb
+.section sa4fa
+.section sa4fb
+.section sa4ga
+.section sa4gb
+.section sa4ha
+.section sa4hb
+.section sa4ia
+.section sa4ib
+.section sa4ja
+.section sa4jb
+.section sa4ka
+.section sa4kb
+.section sa4la
+.section sa4lb
+.section sa4ma
+.section sa4mb
+.section sa4na
+.section sa4nb
+.section sa4oa
+.section sa4ob
+.section sa4pa
+.section sa4pb
+.section sa4qa
+.section sa4qb
+.section sa4ra
+.section sa4rb
+.section sa4sa
+.section sa4sb
+.section sa4ta
+.section sa4tb
+.section sa4ua
+.section sa4ub
+.section sa4va
+.section sa4vb
+.section sa4wa
+.section sa4wb
+.section sa4xa
+.section sa4xb
+.section sa4ya
+.section sa4yb
+.section sa4za
+.section sa4zb
+.section sa41a
+.section sa41b
+.section sa42a
+.section sa42b
+.section sa43a
+.section sa43b
+.section sa44a
+.section sa44b
+.section sa45a
+.section sa45b
+.section sa46a
+.section sa46b
+.section sa47a
+.section sa47b
+.section sa48a
+.section sa48b
+.section sa49a
+.section sa49b
+.section sa40a
+.section sa40b
+.section sa5aa
+.section sa5ab
+.section sa5ba
+.section sa5bb
+.section sa5ca
+.section sa5cb
+.section sa5da
+.section sa5db
+.section sa5ea
+.section sa5eb
+.section sa5fa
+.section sa5fb
+.section sa5ga
+.section sa5gb
+.section sa5ha
+.section sa5hb
+.section sa5ia
+.section sa5ib
+.section sa5ja
+.section sa5jb
+.section sa5ka
+.section sa5kb
+.section sa5la
+.section sa5lb
+.section sa5ma
+.section sa5mb
+.section sa5na
+.section sa5nb
+.section sa5oa
+.section sa5ob
+.section sa5pa
+.section sa5pb
+.section sa5qa
+.section sa5qb
+.section sa5ra
+.section sa5rb
+.section sa5sa
+.section sa5sb
+.section sa5ta
+.section sa5tb
+.section sa5ua
+.section sa5ub
+.section sa5va
+.section sa5vb
+.section sa5wa
+.section sa5wb
+.section sa5xa
+.section sa5xb
+.section sa5ya
+.section sa5yb
+.section sa5za
+.section sa5zb
+.section sa51a
+.section sa51b
+.section sa52a
+.section sa52b
+.section sa53a
+.section sa53b
+.section sa54a
+.section sa54b
+.section sa55a
+.section sa55b
+.section sa56a
+.section sa56b
+.section sa57a
+.section sa57b
+.section sa58a
+.section sa58b
+.section sa59a
+.section sa59b
+.section sa50a
+.section sa50b
+.section sa6aa
+.section sa6ab
+.section sa6ba
+.section sa6bb
+.section sa6ca
+.section sa6cb
+.section sa6da
+.section sa6db
+.section sa6ea
+.section sa6eb
+.section sa6fa
+.section sa6fb
+.section sa6ga
+.section sa6gb
+.section sa6ha
+.section sa6hb
+.section sa6ia
+.section sa6ib
+.section sa6ja
+.section sa6jb
+.section sa6ka
+.section sa6kb
+.section sa6la
+.section sa6lb
+.section sa6ma
+.section sa6mb
+.section sa6na
+.section sa6nb
+.section sa6oa
+.section sa6ob
+.section sa6pa
+.section sa6pb
+.section sa6qa
+.section sa6qb
+.section sa6ra
+.section sa6rb
+.section sa6sa
+.section sa6sb
+.section sa6ta
+.section sa6tb
+.section sa6ua
+.section sa6ub
+.section sa6va
+.section sa6vb
+.section sa6wa
+.section sa6wb
+.section sa6xa
+.section sa6xb
+.section sa6ya
+.section sa6yb
+.section sa6za
+.section sa6zb
+.section sa61a
+.section sa61b
+.section sa62a
+.section sa62b
+.section sa63a
+.section sa63b
+.section sa64a
+.section sa64b
+.section sa65a
+.section sa65b
+.section sa66a
+.section sa66b
+.section sa67a
+.section sa67b
+.section sa68a
+.section sa68b
+.section sa69a
+.section sa69b
+.section sa60a
+.section sa60b
+.section sa7aa
+.section sa7ab
+.section sa7ba
+.section sa7bb
+.section sa7ca
+.section sa7cb
+.section sa7da
+.section sa7db
+.section sa7ea
+.section sa7eb
+.section sa7fa
+.section sa7fb
+.section sa7ga
+.section sa7gb
+.section sa7ha
+.section sa7hb
+.section sa7ia
+.section sa7ib
+.section sa7ja
+.section sa7jb
+.section sa7ka
+.section sa7kb
+.section sa7la
+.section sa7lb
+.section sa7ma
+.section sa7mb
+.section sa7na
+.section sa7nb
+.section sa7oa
+.section sa7ob
+.section sa7pa
+.section sa7pb
+.section sa7qa
+.section sa7qb
+.section sa7ra
+.section sa7rb
+.section sa7sa
+.section sa7sb
+.section sa7ta
+.section sa7tb
+.section sa7ua
+.section sa7ub
+.section sa7va
+.section sa7vb
+.section sa7wa
+.section sa7wb
+.section sa7xa
+.section sa7xb
+.section sa7ya
+.section sa7yb
+.section sa7za
+.section sa7zb
+.section sa71a
+.section sa71b
+.section sa72a
+.section sa72b
+.section sa73a
+.section sa73b
+.section sa74a
+.section sa74b
+.section sa75a
+.section sa75b
+.section sa76a
+.section sa76b
+.section sa77a
+.section sa77b
+.section sa78a
+.section sa78b
+.section sa79a
+.section sa79b
+.section sa70a
+.section sa70b
+.section sa8aa
+.section sa8ab
+.section sa8ba
+.section sa8bb
+.section sa8ca
+.section sa8cb
+.section sa8da
+.section sa8db
+.section sa8ea
+.section sa8eb
+.section sa8fa
+.section sa8fb
+.section sa8ga
+.section sa8gb
+.section sa8ha
+.section sa8hb
+.section sa8ia
+.section sa8ib
+.section sa8ja
+.section sa8jb
+.section sa8ka
+.section sa8kb
+.section sa8la
+.section sa8lb
+.section sa8ma
+.section sa8mb
+.section sa8na
+.section sa8nb
+.section sa8oa
+.section sa8ob
+.section sa8pa
+.section sa8pb
+.section sa8qa
+.section sa8qb
+.section sa8ra
+.section sa8rb
+.section sa8sa
+.section sa8sb
+.section sa8ta
+.section sa8tb
+.section sa8ua
+.section sa8ub
+.section sa8va
+.section sa8vb
+.section sa8wa
+.section sa8wb
+.section sa8xa
+.section sa8xb
+.section sa8ya
+.section sa8yb
+.section sa8za
+.section sa8zb
+.section sa81a
+.section sa81b
+.section sa82a
+.section sa82b
+.section sa83a
+.section sa83b
+.section sa84a
+.section sa84b
+.section sa85a
+.section sa85b
+.section sa86a
+.section sa86b
+.section sa87a
+.section sa87b
+.section sa88a
+.section sa88b
+.section sa89a
+.section sa89b
+.section sa80a
+.section sa80b
+.section sa9aa
+.section sa9ab
+.section sa9ba
+.section sa9bb
+.section sa9ca
+.section sa9cb
+.section sa9da
+.section sa9db
+.section sa9ea
+.section sa9eb
+.section sa9fa
+.section sa9fb
+.section sa9ga
+.section sa9gb
+.section sa9ha
+.section sa9hb
+.section sa9ia
+.section sa9ib
+.section sa9ja
+.section sa9jb
+.section sa9ka
+.section sa9kb
+.section sa9la
+.section sa9lb
+.section sa9ma
+.section sa9mb
+.section sa9na
+.section sa9nb
+.section sa9oa
+.section sa9ob
+.section sa9pa
+.section sa9pb
+.section sa9qa
+.section sa9qb
+.section sa9ra
+.section sa9rb
+.section sa9sa
+.section sa9sb
+.section sa9ta
+.section sa9tb
+.section sa9ua
+.section sa9ub
+.section sa9va
+.section sa9vb
+.section sa9wa
+.section sa9wb
+.section sa9xa
+.section sa9xb
+.section sa9ya
+.section sa9yb
+.section sa9za
+.section sa9zb
+.section sa91a
+.section sa91b
+.section sa92a
+.section sa92b
+.section sa93a
+.section sa93b
+.section sa94a
+.section sa94b
+.section sa95a
+.section sa95b
+.section sa96a
+.section sa96b
+.section sa97a
+.section sa97b
+.section sa98a
+.section sa98b
+.section sa99a
+.section sa99b
+.section sa90a
+.section sa90b
+.section sa0aa
+.section sa0ab
+.section sa0ba
+.section sa0bb
+.section sa0ca
+.section sa0cb
+.section sa0da
+.section sa0db
+.section sa0ea
+.section sa0eb
+.section sa0fa
+.section sa0fb
+.section sa0ga
+.section sa0gb
+.section sa0ha
+.section sa0hb
+.section sa0ia
+.section sa0ib
+.section sa0ja
+.section sa0jb
+.section sa0ka
+.section sa0kb
+.section sa0la
+.section sa0lb
+.section sa0ma
+.section sa0mb
+.section sa0na
+.section sa0nb
+.section sa0oa
+.section sa0ob
+.section sa0pa
+.section sa0pb
+.section sa0qa
+.section sa0qb
+.section sa0ra
+.section sa0rb
+.section sa0sa
+.section sa0sb
+.section sa0ta
+.section sa0tb
+.section sa0ua
+.section sa0ub
+.section sa0va
+.section sa0vb
+.section sa0wa
+.section sa0wb
+.section sa0xa
+.section sa0xb
+.section sa0ya
+.section sa0yb
+.section sa0za
+.section sa0zb
+.section sa01a
+.section sa01b
+.section sa02a
+.section sa02b
+.section sa03a
+.section sa03b
+.section sa04a
+.section sa04b
+.section sa05a
+.section sa05b
+.section sa06a
+.section sa06b
+.section sa07a
+.section sa07b
+.section sa08a
+.section sa08b
+.section sa09a
+.section sa09b
+.section sa00a
+.section sa00b
+.section sbaaa
+.section sbaab
+.section sbaba
+.section sbabb
+.section sbaca
+.section sbacb
+.section sbada
+.section sbadb
+.section sbaea
+.section sbaeb
+.section sbafa
+.section sbafb
+.section sbaga
+.section sbagb
+.section sbaha
+.section sbahb
+.section sbaia
+.section sbaib
+.section sbaja
+.section sbajb
+.section sbaka
+.section sbakb
+.section sbala
+.section sbalb
+.section sbama
+.section sbamb
+.section sbana
+.section sbanb
+.section sbaoa
+.section sbaob
+.section sbapa
+.section sbapb
+.section sbaqa
+.section sbaqb
+.section sbara
+.section sbarb
+.section sbasa
+.section sbasb
+.section sbata
+.section sbatb
+.section sbaua
+.section sbaub
+.section sbava
+.section sbavb
+.section sbawa
+.section sbawb
+.section sbaxa
+.section sbaxb
+.section sbaya
+.section sbayb
+.section sbaza
+.section sbazb
+.section sba1a
+.section sba1b
+.section sba2a
+.section sba2b
+.section sba3a
+.section sba3b
+.section sba4a
+.section sba4b
+.section sba5a
+.section sba5b
+.section sba6a
+.section sba6b
+.section sba7a
+.section sba7b
+.section sba8a
+.section sba8b
+.section sba9a
+.section sba9b
+.section sba0a
+.section sba0b
+.section sbbaa
+.section sbbab
+.section sbbba
+.section sbbbb
+.section sbbca
+.section sbbcb
+.section sbbda
+.section sbbdb
+.section sbbea
+.section sbbeb
+.section sbbfa
+.section sbbfb
+.section sbbga
+.section sbbgb
+.section sbbha
+.section sbbhb
+.section sbbia
+.section sbbib
+.section sbbja
+.section sbbjb
+.section sbbka
+.section sbbkb
+.section sbbla
+.section sbblb
+.section sbbma
+.section sbbmb
+.section sbbna
+.section sbbnb
+.section sbboa
+.section sbbob
+.section sbbpa
+.section sbbpb
+.section sbbqa
+.section sbbqb
+.section sbbra
+.section sbbrb
+.section sbbsa
+.section sbbsb
+.section sbbta
+.section sbbtb
+.section sbbua
+.section sbbub
+.section sbbva
+.section sbbvb
+.section sbbwa
+.section sbbwb
+.section sbbxa
+.section sbbxb
+.section sbbya
+.section sbbyb
+.section sbbza
+.section sbbzb
+.section sbb1a
+.section sbb1b
+.section sbb2a
+.section sbb2b
+.section sbb3a
+.section sbb3b
+.section sbb4a
+.section sbb4b
+.section sbb5a
+.section sbb5b
+.section sbb6a
+.section sbb6b
+.section sbb7a
+.section sbb7b
+.section sbb8a
+.section sbb8b
+.section sbb9a
+.section sbb9b
+.section sbb0a
+.section sbb0b
+.section sbcaa
+.section sbcab
+.section sbcba
+.section sbcbb
+.section sbcca
+.section sbccb
+.section sbcda
+.section sbcdb
+.section sbcea
+.section sbceb
+.section sbcfa
+.section sbcfb
+.section sbcga
+.section sbcgb
+.section sbcha
+.section sbchb
+.section sbcia
+.section sbcib
+.section sbcja
+.section sbcjb
+.section sbcka
+.section sbckb
+.section sbcla
+.section sbclb
+.section sbcma
+.section sbcmb
+.section sbcna
+.section sbcnb
+.section sbcoa
+.section sbcob
+.section sbcpa
+.section sbcpb
+.section sbcqa
+.section sbcqb
+.section sbcra
+.section sbcrb
+.section sbcsa
+.section sbcsb
+.section sbcta
+.section sbctb
+.section sbcua
+.section sbcub
+.section sbcva
+.section sbcvb
+.section sbcwa
+.section sbcwb
+.section sbcxa
+.section sbcxb
+.section sbcya
+.section sbcyb
+.section sbcza
+.section sbczb
+.section sbc1a
+.section sbc1b
+.section sbc2a
+.section sbc2b
+.section sbc3a
+.section sbc3b
+.section sbc4a
+.section sbc4b
+.section sbc5a
+.section sbc5b
+.section sbc6a
+.section sbc6b
+.section sbc7a
+.section sbc7b
+.section sbc8a
+.section sbc8b
+.section sbc9a
+.section sbc9b
+.section sbc0a
+.section sbc0b
+.section sbdaa
+.section sbdab
+.section sbdba
+.section sbdbb
+.section sbdca
+.section sbdcb
+.section sbdda
+.section sbddb
+.section sbdea
+.section sbdeb
+.section sbdfa
+.section sbdfb
+.section sbdga
+.section sbdgb
+.section sbdha
+.section sbdhb
+.section sbdia
+.section sbdib
+.section sbdja
+.section sbdjb
+.section sbdka
+.section sbdkb
+.section sbdla
+.section sbdlb
+.section sbdma
+.section sbdmb
+.section sbdna
+.section sbdnb
+.section sbdoa
+.section sbdob
+.section sbdpa
+.section sbdpb
+.section sbdqa
+.section sbdqb
+.section sbdra
+.section sbdrb
+.section sbdsa
+.section sbdsb
+.section sbdta
+.section sbdtb
+.section sbdua
+.section sbdub
+.section sbdva
+.section sbdvb
+.section sbdwa
+.section sbdwb
+.section sbdxa
+.section sbdxb
+.section sbdya
+.section sbdyb
+.section sbdza
+.section sbdzb
+.section sbd1a
+.section sbd1b
+.section sbd2a
+.section sbd2b
+.section sbd3a
+.section sbd3b
+.section sbd4a
+.section sbd4b
+.section sbd5a
+.section sbd5b
+.section sbd6a
+.section sbd6b
+.section sbd7a
+.section sbd7b
+.section sbd8a
+.section sbd8b
+.section sbd9a
+.section sbd9b
+.section sbd0a
+.section sbd0b
+.section sbeaa
+.section sbeab
+.section sbeba
+.section sbebb
+.section sbeca
+.section sbecb
+.section sbeda
+.section sbedb
+.section sbeea
+.section sbeeb
+.section sbefa
+.section sbefb
+.section sbega
+.section sbegb
+.section sbeha
+.section sbehb
+.section sbeia
+.section sbeib
+.section sbeja
+.section sbejb
+.section sbeka
+.section sbekb
+.section sbela
+.section sbelb
+.section sbema
+.section sbemb
+.section sbena
+.section sbenb
+.section sbeoa
+.section sbeob
+.section sbepa
+.section sbepb
+.section sbeqa
+.section sbeqb
+.section sbera
+.section sberb
+.section sbesa
+.section sbesb
+.section sbeta
+.section sbetb
+.section sbeua
+.section sbeub
+.section sbeva
+.section sbevb
+.section sbewa
+.section sbewb
+.section sbexa
+.section sbexb
+.section sbeya
+.section sbeyb
+.section sbeza
+.section sbezb
+.section sbe1a
+.section sbe1b
+.section sbe2a
+.section sbe2b
+.section sbe3a
+.section sbe3b
+.section sbe4a
+.section sbe4b
+.section sbe5a
+.section sbe5b
+.section sbe6a
+.section sbe6b
+.section sbe7a
+.section sbe7b
+.section sbe8a
+.section sbe8b
+.section sbe9a
+.section sbe9b
+.section sbe0a
+.section sbe0b
+.section sbfaa
+.section sbfab
+.section sbfba
+.section sbfbb
+.section sbfca
+.section sbfcb
+.section sbfda
+.section sbfdb
+.section sbfea
+.section sbfeb
+.section sbffa
+.section sbffb
+.section sbfga
+.section sbfgb
+.section sbfha
+.section sbfhb
+.section sbfia
+.section sbfib
+.section sbfja
+.section sbfjb
+.section sbfka
+.section sbfkb
+.section sbfla
+.section sbflb
+.section sbfma
+.section sbfmb
+.section sbfna
+.section sbfnb
+.section sbfoa
+.section sbfob
+.section sbfpa
+.section sbfpb
+.section sbfqa
+.section sbfqb
+.section sbfra
+.section sbfrb
+.section sbfsa
+.section sbfsb
+.section sbfta
+.section sbftb
+.section sbfua
+.section sbfub
+.section sbfva
+.section sbfvb
+.section sbfwa
+.section sbfwb
+.section sbfxa
+.section sbfxb
+.section sbfya
+.section sbfyb
+.section sbfza
+.section sbfzb
+.section sbf1a
+.section sbf1b
+.section sbf2a
+.section sbf2b
+.section sbf3a
+.section sbf3b
+.section sbf4a
+.section sbf4b
+.section sbf5a
+.section sbf5b
+.section sbf6a
+.section sbf6b
+.section sbf7a
+.section sbf7b
+.section sbf8a
+.section sbf8b
+.section sbf9a
+.section sbf9b
+.section sbf0a
+.section sbf0b
+.section sbgaa
+.section sbgab
+.section sbgba
+.section sbgbb
+.section sbgca
+.section sbgcb
+.section sbgda
+.section sbgdb
+.section sbgea
+.section sbgeb
+.section sbgfa
+.section sbgfb
+.section sbgga
+.section sbggb
+.section sbgha
+.section sbghb
+.section sbgia
+.section sbgib
+.section sbgja
+.section sbgjb
+.section sbgka
+.section sbgkb
+.section sbgla
+.section sbglb
+.section sbgma
+.section sbgmb
+.section sbgna
+.section sbgnb
+.section sbgoa
+.section sbgob
+.section sbgpa
+.section sbgpb
+.section sbgqa
+.section sbgqb
+.section sbgra
+.section sbgrb
+.section sbgsa
+.section sbgsb
+.section sbgta
+.section sbgtb
+.section sbgua
+.section sbgub
+.section sbgva
+.section sbgvb
+.section sbgwa
+.section sbgwb
+.section sbgxa
+.section sbgxb
+.section sbgya
+.section sbgyb
+.section sbgza
+.section sbgzb
+.section sbg1a
+.section sbg1b
+.section sbg2a
+.section sbg2b
+.section sbg3a
+.section sbg3b
+.section sbg4a
+.section sbg4b
+.section sbg5a
+.section sbg5b
+.section sbg6a
+.section sbg6b
+.section sbg7a
+.section sbg7b
+.section sbg8a
+.section sbg8b
+.section sbg9a
+.section sbg9b
+.section sbg0a
+.section sbg0b
+.section sbhaa
+.section sbhab
+.section sbhba
+.section sbhbb
+.section sbhca
+.section sbhcb
+.section sbhda
+.section sbhdb
+.section sbhea
+.section sbheb
+.section sbhfa
+.section sbhfb
+.section sbhga
+.section sbhgb
+.section sbhha
+.section sbhhb
+.section sbhia
+.section sbhib
+.section sbhja
+.section sbhjb
+.section sbhka
+.section sbhkb
+.section sbhla
+.section sbhlb
+.section sbhma
+.section sbhmb
+.section sbhna
+.section sbhnb
+.section sbhoa
+.section sbhob
+.section sbhpa
+.section sbhpb
+.section sbhqa
+.section sbhqb
+.section sbhra
+.section sbhrb
+.section sbhsa
+.section sbhsb
+.section sbhta
+.section sbhtb
+.section sbhua
+.section sbhub
+.section sbhva
+.section sbhvb
+.section sbhwa
+.section sbhwb
+.section sbhxa
+.section sbhxb
+.section sbhya
+.section sbhyb
+.section sbhza
+.section sbhzb
+.section sbh1a
+.section sbh1b
+.section sbh2a
+.section sbh2b
+.section sbh3a
+.section sbh3b
+.section sbh4a
+.section sbh4b
+.section sbh5a
+.section sbh5b
+.section sbh6a
+.section sbh6b
+.section sbh7a
+.section sbh7b
+.section sbh8a
+.section sbh8b
+.section sbh9a
+.section sbh9b
+.section sbh0a
+.section sbh0b
+.section sbiaa
+.section sbiab
+.section sbiba
+.section sbibb
+.section sbica
+.section sbicb
+.section sbida
+.section sbidb
+.section sbiea
+.section sbieb
+.section sbifa
+.section sbifb
+.section sbiga
+.section sbigb
+.section sbiha
+.section sbihb
+.section sbiia
+.section sbiib
+.section sbija
+.section sbijb
+.section sbika
+.section sbikb
+.section sbila
+.section sbilb
+.section sbima
+.section sbimb
+.section sbina
+.section sbinb
+.section sbioa
+.section sbiob
+.section sbipa
+.section sbipb
+.section sbiqa
+.section sbiqb
+.section sbira
+.section sbirb
+.section sbisa
+.section sbisb
+.section sbita
+.section sbitb
+.section sbiua
+.section sbiub
+.section sbiva
+.section sbivb
+.section sbiwa
+.section sbiwb
+.section sbixa
+.section sbixb
+.section sbiya
+.section sbiyb
+.section sbiza
+.section sbizb
+.section sbi1a
+.section sbi1b
+.section sbi2a
+.section sbi2b
+.section sbi3a
+.section sbi3b
+.section sbi4a
+.section sbi4b
+.section sbi5a
+.section sbi5b
+.section sbi6a
+.section sbi6b
+.section sbi7a
+.section sbi7b
+.section sbi8a
+.section sbi8b
+.section sbi9a
+.section sbi9b
+.section sbi0a
+.section sbi0b
+.section sbjaa
+.section sbjab
+.section sbjba
+.section sbjbb
+.section sbjca
+.section sbjcb
+.section sbjda
+.section sbjdb
+.section sbjea
+.section sbjeb
+.section sbjfa
+.section sbjfb
+.section sbjga
+.section sbjgb
+.section sbjha
+.section sbjhb
+.section sbjia
+.section sbjib
+.section sbjja
+.section sbjjb
+.section sbjka
+.section sbjkb
+.section sbjla
+.section sbjlb
+.section sbjma
+.section sbjmb
+.section sbjna
+.section sbjnb
+.section sbjoa
+.section sbjob
+.section sbjpa
+.section sbjpb
+.section sbjqa
+.section sbjqb
+.section sbjra
+.section sbjrb
+.section sbjsa
+.section sbjsb
+.section sbjta
+.section sbjtb
+.section sbjua
+.section sbjub
+.section sbjva
+.section sbjvb
+.section sbjwa
+.section sbjwb
+.section sbjxa
+.section sbjxb
+.section sbjya
+.section sbjyb
+.section sbjza
+.section sbjzb
+.section sbj1a
+.section sbj1b
+.section sbj2a
+.section sbj2b
+.section sbj3a
+.section sbj3b
+.section sbj4a
+.section sbj4b
+.section sbj5a
+.section sbj5b
+.section sbj6a
+.section sbj6b
+.section sbj7a
+.section sbj7b
+.section sbj8a
+.section sbj8b
+.section sbj9a
+.section sbj9b
+.section sbj0a
+.section sbj0b
+.section sbkaa
+.section sbkab
+.section sbkba
+.section sbkbb
+.section sbkca
+.section sbkcb
+.section sbkda
+.section sbkdb
+.section sbkea
+.section sbkeb
+.section sbkfa
+.section sbkfb
+.section sbkga
+.section sbkgb
+.section sbkha
+.section sbkhb
+.section sbkia
+.section sbkib
+.section sbkja
+.section sbkjb
+.section sbkka
+.section sbkkb
+.section sbkla
+.section sbklb
+.section sbkma
+.section sbkmb
+.section sbkna
+.section sbknb
+.section sbkoa
+.section sbkob
+.section sbkpa
+.section sbkpb
+.section sbkqa
+.section sbkqb
+.section sbkra
+.section sbkrb
+.section sbksa
+.section sbksb
+.section sbkta
+.section sbktb
+.section sbkua
+.section sbkub
+.section sbkva
+.section sbkvb
+.section sbkwa
+.section sbkwb
+.section sbkxa
+.section sbkxb
+.section sbkya
+.section sbkyb
+.section sbkza
+.section sbkzb
+.section sbk1a
+.section sbk1b
+.section sbk2a
+.section sbk2b
+.section sbk3a
+.section sbk3b
+.section sbk4a
+.section sbk4b
+.section sbk5a
+.section sbk5b
+.section sbk6a
+.section sbk6b
+.section sbk7a
+.section sbk7b
+.section sbk8a
+.section sbk8b
+.section sbk9a
+.section sbk9b
+.section sbk0a
+.section sbk0b
+.section sblaa
+.section sblab
+.section sblba
+.section sblbb
+.section sblca
+.section sblcb
+.section sblda
+.section sbldb
+.section sblea
+.section sbleb
+.section sblfa
+.section sblfb
+.section sblga
+.section sblgb
+.section sblha
+.section sblhb
+.section sblia
+.section sblib
+.section sblja
+.section sbljb
+.section sblka
+.section sblkb
+.section sblla
+.section sbllb
+.section sblma
+.section sblmb
+.section sblna
+.section sblnb
+.section sbloa
+.section sblob
+.section sblpa
+.section sblpb
+.section sblqa
+.section sblqb
+.section sblra
+.section sblrb
+.section sblsa
+.section sblsb
+.section sblta
+.section sbltb
+.section sblua
+.section sblub
+.section sblva
+.section sblvb
+.section sblwa
+.section sblwb
+.section sblxa
+.section sblxb
+.section sblya
+.section sblyb
+.section sblza
+.section sblzb
+.section sbl1a
+.section sbl1b
+.section sbl2a
+.section sbl2b
+.section sbl3a
+.section sbl3b
+.section sbl4a
+.section sbl4b
+.section sbl5a
+.section sbl5b
+.section sbl6a
+.section sbl6b
+.section sbl7a
+.section sbl7b
+.section sbl8a
+.section sbl8b
+.section sbl9a
+.section sbl9b
+.section sbl0a
+.section sbl0b
+.section sbmaa
+.section sbmab
+.section sbmba
+.section sbmbb
+.section sbmca
+.section sbmcb
+.section sbmda
+.section sbmdb
+.section sbmea
+.section sbmeb
+.section sbmfa
+.section sbmfb
+.section sbmga
+.section sbmgb
+.section sbmha
+.section sbmhb
+.section sbmia
+.section sbmib
+.section sbmja
+.section sbmjb
+.section sbmka
+.section sbmkb
+.section sbmla
+.section sbmlb
+.section sbmma
+.section sbmmb
+.section sbmna
+.section sbmnb
+.section sbmoa
+.section sbmob
+.section sbmpa
+.section sbmpb
+.section sbmqa
+.section sbmqb
+.section sbmra
+.section sbmrb
+.section sbmsa
+.section sbmsb
+.section sbmta
+.section sbmtb
+.section sbmua
+.section sbmub
+.section sbmva
+.section sbmvb
+.section sbmwa
+.section sbmwb
+.section sbmxa
+.section sbmxb
+.section sbmya
+.section sbmyb
+.section sbmza
+.section sbmzb
+.section sbm1a
+.section sbm1b
+.section sbm2a
+.section sbm2b
+.section sbm3a
+.section sbm3b
+.section sbm4a
+.section sbm4b
+.section sbm5a
+.section sbm5b
+.section sbm6a
+.section sbm6b
+.section sbm7a
+.section sbm7b
+.section sbm8a
+.section sbm8b
+.section sbm9a
+.section sbm9b
+.section sbm0a
+.section sbm0b
+.section sbnaa
+.section sbnab
+.section sbnba
+.section sbnbb
+.section sbnca
+.section sbncb
+.section sbnda
+.section sbndb
+.section sbnea
+.section sbneb
+.section sbnfa
+.section sbnfb
+.section sbnga
+.section sbngb
+.section sbnha
+.section sbnhb
+.section sbnia
+.section sbnib
+.section sbnja
+.section sbnjb
+.section sbnka
+.section sbnkb
+.section sbnla
+.section sbnlb
+.section sbnma
+.section sbnmb
+.section sbnna
+.section sbnnb
+.section sbnoa
+.section sbnob
+.section sbnpa
+.section sbnpb
+.section sbnqa
+.section sbnqb
+.section sbnra
+.section sbnrb
+.section sbnsa
+.section sbnsb
+.section sbnta
+.section sbntb
+.section sbnua
+.section sbnub
+.section sbnva
+.section sbnvb
+.section sbnwa
+.section sbnwb
+.section sbnxa
+.section sbnxb
+.section sbnya
+.section sbnyb
+.section sbnza
+.section sbnzb
+.section sbn1a
+.section sbn1b
+.section sbn2a
+.section sbn2b
+.section sbn3a
+.section sbn3b
+.section sbn4a
+.section sbn4b
+.section sbn5a
+.section sbn5b
+.section sbn6a
+.section sbn6b
+.section sbn7a
+.section sbn7b
+.section sbn8a
+.section sbn8b
+.section sbn9a
+.section sbn9b
+.section sbn0a
+.section sbn0b
+.section sboaa
+.section sboab
+.section sboba
+.section sbobb
+.section sboca
+.section sbocb
+.section sboda
+.section sbodb
+.section sboea
+.section sboeb
+.section sbofa
+.section sbofb
+.section sboga
+.section sbogb
+.section sboha
+.section sbohb
+.section sboia
+.section sboib
+.section sboja
+.section sbojb
+.section sboka
+.section sbokb
+.section sbola
+.section sbolb
+.section sboma
+.section sbomb
+.section sbona
+.section sbonb
+.section sbooa
+.section sboob
+.section sbopa
+.section sbopb
+.section sboqa
+.section sboqb
+.section sbora
+.section sborb
+.section sbosa
+.section sbosb
+.section sbota
+.section sbotb
+.section sboua
+.section sboub
+.section sbova
+.section sbovb
+.section sbowa
+.section sbowb
+.section sboxa
+.section sboxb
+.section sboya
+.section sboyb
+.section sboza
+.section sbozb
+.section sbo1a
+.section sbo1b
+.section sbo2a
+.section sbo2b
+.section sbo3a
+.section sbo3b
+.section sbo4a
+.section sbo4b
+.section sbo5a
+.section sbo5b
+.section sbo6a
+.section sbo6b
+.section sbo7a
+.section sbo7b
+.section sbo8a
+.section sbo8b
+.section sbo9a
+.section sbo9b
+.section sbo0a
+.section sbo0b
+.section sbpaa
+.section sbpab
+.section sbpba
+.section sbpbb
+.section sbpca
+.section sbpcb
+.section sbpda
+.section sbpdb
+.section sbpea
+.section sbpeb
+.section sbpfa
+.section sbpfb
+.section sbpga
+.section sbpgb
+.section sbpha
+.section sbphb
+.section sbpia
+.section sbpib
+.section sbpja
+.section sbpjb
+.section sbpka
+.section sbpkb
+.section sbpla
+.section sbplb
+.section sbpma
+.section sbpmb
+.section sbpna
+.section sbpnb
+.section sbpoa
+.section sbpob
+.section sbppa
+.section sbppb
+.section sbpqa
+.section sbpqb
+.section sbpra
+.section sbprb
+.section sbpsa
+.section sbpsb
+.section sbpta
+.section sbptb
+.section sbpua
+.section sbpub
+.section sbpva
+.section sbpvb
+.section sbpwa
+.section sbpwb
+.section sbpxa
+.section sbpxb
+.section sbpya
+.section sbpyb
+.section sbpza
+.section sbpzb
+.section sbp1a
+.section sbp1b
+.section sbp2a
+.section sbp2b
+.section sbp3a
+.section sbp3b
+.section sbp4a
+.section sbp4b
+.section sbp5a
+.section sbp5b
+.section sbp6a
+.section sbp6b
+.section sbp7a
+.section sbp7b
+.section sbp8a
+.section sbp8b
+.section sbp9a
+.section sbp9b
+.section sbp0a
+.section sbp0b
+.section sbqaa
+.section sbqab
+.section sbqba
+.section sbqbb
+.section sbqca
+.section sbqcb
+.section sbqda
+.section sbqdb
+.section sbqea
+.section sbqeb
+.section sbqfa
+.section sbqfb
+.section sbqga
+.section sbqgb
+.section sbqha
+.section sbqhb
+.section sbqia
+.section sbqib
+.section sbqja
+.section sbqjb
+.section sbqka
+.section sbqkb
+.section sbqla
+.section sbqlb
+.section sbqma
+.section sbqmb
+.section sbqna
+.section sbqnb
+.section sbqoa
+.section sbqob
+.section sbqpa
+.section sbqpb
+.section sbqqa
+.section sbqqb
+.section sbqra
+.section sbqrb
+.section sbqsa
+.section sbqsb
+.section sbqta
+.section sbqtb
+.section sbqua
+.section sbqub
+.section sbqva
+.section sbqvb
+.section sbqwa
+.section sbqwb
+.section sbqxa
+.section sbqxb
+.section sbqya
+.section sbqyb
+.section sbqza
+.section sbqzb
+.section sbq1a
+.section sbq1b
+.section sbq2a
+.section sbq2b
+.section sbq3a
+.section sbq3b
+.section sbq4a
+.section sbq4b
+.section sbq5a
+.section sbq5b
+.section sbq6a
+.section sbq6b
+.section sbq7a
+.section sbq7b
+.section sbq8a
+.section sbq8b
+.section sbq9a
+.section sbq9b
+.section sbq0a
+.section sbq0b
+.section sbraa
+.section sbrab
+.section sbrba
+.section sbrbb
+.section sbrca
+.section sbrcb
+.section sbrda
+.section sbrdb
+.section sbrea
+.section sbreb
+.section sbrfa
+.section sbrfb
+.section sbrga
+.section sbrgb
+.section sbrha
+.section sbrhb
+.section sbria
+.section sbrib
+.section sbrja
+.section sbrjb
+.section sbrka
+.section sbrkb
+.section sbrla
+.section sbrlb
+.section sbrma
+.section sbrmb
+.section sbrna
+.section sbrnb
+.section sbroa
+.section sbrob
+.section sbrpa
+.section sbrpb
+.section sbrqa
+.section sbrqb
+.section sbrra
+.section sbrrb
+.section sbrsa
+.section sbrsb
+.section sbrta
+.section sbrtb
+.section sbrua
+.section sbrub
+.section sbrva
+.section sbrvb
+.section sbrwa
+.section sbrwb
+.section sbrxa
+.section sbrxb
+.section sbrya
+.section sbryb
+.section sbrza
+.section sbrzb
+.section sbr1a
+.section sbr1b
+.section sbr2a
+.section sbr2b
+.section sbr3a
+.section sbr3b
+.section sbr4a
+.section sbr4b
+.section sbr5a
+.section sbr5b
+.section sbr6a
+.section sbr6b
+.section sbr7a
+.section sbr7b
+.section sbr8a
+.section sbr8b
+.section sbr9a
+.section sbr9b
+.section sbr0a
+.section sbr0b
+.section sbsaa
+.section sbsab
+.section sbsba
+.section sbsbb
+.section sbsca
+.section sbscb
+.section sbsda
+.section sbsdb
+.section sbsea
+.section sbseb
+.section sbsfa
+.section sbsfb
+.section sbsga
+.section sbsgb
+.section sbsha
+.section sbshb
+.section sbsia
+.section sbsib
+.section sbsja
+.section sbsjb
+.section sbska
+.section sbskb
+.section sbsla
+.section sbslb
+.section sbsma
+.section sbsmb
+.section sbsna
+.section sbsnb
+.section sbsoa
+.section sbsob
+.section sbspa
+.section sbspb
+.section sbsqa
+.section sbsqb
+.section sbsra
+.section sbsrb
+.section sbssa
+.section sbssb
+.section sbsta
+.section sbstb
+.section sbsua
+.section sbsub
+.section sbsva
+.section sbsvb
+.section sbswa
+.section sbswb
+.section sbsxa
+.section sbsxb
+.section sbsya
+.section sbsyb
+.section sbsza
+.section sbszb
+.section sbs1a
+.section sbs1b
+.section sbs2a
+.section sbs2b
+.section sbs3a
+.section sbs3b
+.section sbs4a
+.section sbs4b
+.section sbs5a
+.section sbs5b
+.section sbs6a
+.section sbs6b
+.section sbs7a
+.section sbs7b
+.section sbs8a
+.section sbs8b
+.section sbs9a
+.section sbs9b
+.section sbs0a
+.section sbs0b
+.section sbtaa
+.section sbtab
+.section sbtba
+.section sbtbb
+.section sbtca
+.section sbtcb
+.section sbtda
+.section sbtdb
+.section sbtea
+.section sbteb
+.section sbtfa
+.section sbtfb
+.section sbtga
+.section sbtgb
+.section sbtha
+.section sbthb
+.section sbtia
+.section sbtib
+.section sbtja
+.section sbtjb
+.section sbtka
+.section sbtkb
+.section sbtla
+.section sbtlb
+.section sbtma
+.section sbtmb
+.section sbtna
+.section sbtnb
+.section sbtoa
+.section sbtob
+.section sbtpa
+.section sbtpb
+.section sbtqa
+.section sbtqb
+.section sbtra
+.section sbtrb
+.section sbtsa
+.section sbtsb
+.section sbtta
+.section sbttb
+.section sbtua
+.section sbtub
+.section sbtva
+.section sbtvb
+.section sbtwa
+.section sbtwb
+.section sbtxa
+.section sbtxb
+.section sbtya
+.section sbtyb
+.section sbtza
+.section sbtzb
+.section sbt1a
+.section sbt1b
+.section sbt2a
+.section sbt2b
+.section sbt3a
+.section sbt3b
+.section sbt4a
+.section sbt4b
+.section sbt5a
+.section sbt5b
+.section sbt6a
+.section sbt6b
+.section sbt7a
+.section sbt7b
+.section sbt8a
+.section sbt8b
+.section sbt9a
+.section sbt9b
+.section sbt0a
+.section sbt0b
+.section sbuaa
+.section sbuab
+.section sbuba
+.section sbubb
+.section sbuca
+.section sbucb
+.section sbuda
+.section sbudb
+.section sbuea
+.section sbueb
+.section sbufa
+.section sbufb
+.section sbuga
+.section sbugb
+.section sbuha
+.section sbuhb
+.section sbuia
+.section sbuib
+.section sbuja
+.section sbujb
+.section sbuka
+.section sbukb
+.section sbula
+.section sbulb
+.section sbuma
+.section sbumb
+.section sbuna
+.section sbunb
+.section sbuoa
+.section sbuob
+.section sbupa
+.section sbupb
+.section sbuqa
+.section sbuqb
+.section sbura
+.section sburb
+.section sbusa
+.section sbusb
+.section sbuta
+.section sbutb
+.section sbuua
+.section sbuub
+.section sbuva
+.section sbuvb
+.section sbuwa
+.section sbuwb
+.section sbuxa
+.section sbuxb
+.section sbuya
+.section sbuyb
+.section sbuza
+.section sbuzb
+.section sbu1a
+.section sbu1b
+.section sbu2a
+.section sbu2b
+.section sbu3a
+.section sbu3b
+.section sbu4a
+.section sbu4b
+.section sbu5a
+.section sbu5b
+.section sbu6a
+.section sbu6b
+.section sbu7a
+.section sbu7b
+.section sbu8a
+.section sbu8b
+.section sbu9a
+.section sbu9b
+.section sbu0a
+.section sbu0b
+.section sbvaa
+.section sbvab
+.section sbvba
+.section sbvbb
+.section sbvca
+.section sbvcb
+.section sbvda
+.section sbvdb
+.section sbvea
+.section sbveb
+.section sbvfa
+.section sbvfb
+.section sbvga
+.section sbvgb
+.section sbvha
+.section sbvhb
+.section sbvia
+.section sbvib
+.section sbvja
+.section sbvjb
+.section sbvka
+.section sbvkb
+.section sbvla
+.section sbvlb
+.section sbvma
+.section sbvmb
+.section sbvna
+.section sbvnb
+.section sbvoa
+.section sbvob
+.section sbvpa
+.section sbvpb
+.section sbvqa
+.section sbvqb
+.section sbvra
+.section sbvrb
+.section sbvsa
+.section sbvsb
+.section sbvta
+.section sbvtb
+.section sbvua
+.section sbvub
+.section sbvva
+.section sbvvb
+.section sbvwa
+.section sbvwb
+.section sbvxa
+.section sbvxb
+.section sbvya
+.section sbvyb
+.section sbvza
+.section sbvzb
+.section sbv1a
+.section sbv1b
+.section sbv2a
+.section sbv2b
+.section sbv3a
+.section sbv3b
+.section sbv4a
+.section sbv4b
+.section sbv5a
+.section sbv5b
+.section sbv6a
+.section sbv6b
+.section sbv7a
+.section sbv7b
+.section sbv8a
+.section sbv8b
+.section sbv9a
+.section sbv9b
+.section sbv0a
+.section sbv0b
+.section sbwaa
+.section sbwab
+.section sbwba
+.section sbwbb
+.section sbwca
+.section sbwcb
+.section sbwda
+.section sbwdb
+.section sbwea
+.section sbweb
+.section sbwfa
+.section sbwfb
+.section sbwga
+.section sbwgb
+.section sbwha
+.section sbwhb
+.section sbwia
+.section sbwib
+.section sbwja
+.section sbwjb
+.section sbwka
+.section sbwkb
+.section sbwla
+.section sbwlb
+.section sbwma
+.section sbwmb
+.section sbwna
+.section sbwnb
+.section sbwoa
+.section sbwob
+.section sbwpa
+.section sbwpb
+.section sbwqa
+.section sbwqb
+.section sbwra
+.section sbwrb
+.section sbwsa
+.section sbwsb
+.section sbwta
+.section sbwtb
+.section sbwua
+.section sbwub
+.section sbwva
+.section sbwvb
+.section sbwwa
+.section sbwwb
+.section sbwxa
+.section sbwxb
+.section sbwya
+.section sbwyb
+.section sbwza
+.section sbwzb
+.section sbw1a
+.section sbw1b
+.section sbw2a
+.section sbw2b
+.section sbw3a
+.section sbw3b
+.section sbw4a
+.section sbw4b
+.section sbw5a
+.section sbw5b
+.section sbw6a
+.section sbw6b
+.section sbw7a
+.section sbw7b
+.section sbw8a
+.section sbw8b
+.section sbw9a
+.section sbw9b
+.section sbw0a
+.section sbw0b
+.section sbxaa
+.section sbxab
+.section sbxba
+.section sbxbb
+.section sbxca
+.section sbxcb
+.section sbxda
+.section sbxdb
+.section sbxea
+.section sbxeb
+.section sbxfa
+.section sbxfb
+.section sbxga
+.section sbxgb
+.section sbxha
+.section sbxhb
+.section sbxia
+.section sbxib
+.section sbxja
+.section sbxjb
+.section sbxka
+.section sbxkb
+.section sbxla
+.section sbxlb
+.section sbxma
+.section sbxmb
+.section sbxna
+.section sbxnb
+.section sbxoa
+.section sbxob
+.section sbxpa
+.section sbxpb
+.section sbxqa
+.section sbxqb
+.section sbxra
+.section sbxrb
+.section sbxsa
+.section sbxsb
+.section sbxta
+.section sbxtb
+.section sbxua
+.section sbxub
+.section sbxva
+.section sbxvb
+.section sbxwa
+.section sbxwb
+.section sbxxa
+.section sbxxb
+.section sbxya
+.section sbxyb
+.section sbxza
+.section sbxzb
+.section sbx1a
+.section sbx1b
+.section sbx2a
+.section sbx2b
+.section sbx3a
+.section sbx3b
+.section sbx4a
+.section sbx4b
+.section sbx5a
+.section sbx5b
+.section sbx6a
+.section sbx6b
+.section sbx7a
+.section sbx7b
+.section sbx8a
+.section sbx8b
+.section sbx9a
+.section sbx9b
+.section sbx0a
+.section sbx0b
+.section sbyaa
+.section sbyab
+.section sbyba
+.section sbybb
+.section sbyca
+.section sbycb
+.section sbyda
+.section sbydb
+.section sbyea
+.section sbyeb
+.section sbyfa
+.section sbyfb
+.section sbyga
+.section sbygb
+.section sbyha
+.section sbyhb
+.section sbyia
+.section sbyib
+.section sbyja
+.section sbyjb
+.section sbyka
+.section sbykb
+.section sbyla
+.section sbylb
+.section sbyma
+.section sbymb
+.section sbyna
+.section sbynb
+.section sbyoa
+.section sbyob
+.section sbypa
+.section sbypb
+.section sbyqa
+.section sbyqb
+.section sbyra
+.section sbyrb
+.section sbysa
+.section sbysb
+.section sbyta
+.section sbytb
+.section sbyua
+.section sbyub
+.section sbyva
+.section sbyvb
+.section sbywa
+.section sbywb
+.section sbyxa
+.section sbyxb
+.section sbyya
+.section sbyyb
+.section sbyza
+.section sbyzb
+.section sby1a
+.section sby1b
+.section sby2a
+.section sby2b
+.section sby3a
+.section sby3b
+.section sby4a
+.section sby4b
+.section sby5a
+.section sby5b
+.section sby6a
+.section sby6b
+.section sby7a
+.section sby7b
+.section sby8a
+.section sby8b
+.section sby9a
+.section sby9b
+.section sby0a
+.section sby0b
+.section sbzaa
+.section sbzab
+.section sbzba
+.section sbzbb
+.section sbzca
+.section sbzcb
+.section sbzda
+.section sbzdb
+.section sbzea
+.section sbzeb
+.section sbzfa
+.section sbzfb
+.section sbzga
+.section sbzgb
+.section sbzha
+.section sbzhb
+.section sbzia
+.section sbzib
+.section sbzja
+.section sbzjb
+.section sbzka
+.section sbzkb
+.section sbzla
+.section sbzlb
+.section sbzma
+.section sbzmb
+.section sbzna
+.section sbznb
+.section sbzoa
+.section sbzob
+.section sbzpa
+.section sbzpb
+.section sbzqa
+.section sbzqb
+.section sbzra
+.section sbzrb
+.section sbzsa
+.section sbzsb
+.section sbzta
+.section sbztb
+.section sbzua
+.section sbzub
+.section sbzva
+.section sbzvb
+.section sbzwa
+.section sbzwb
+.section sbzxa
+.section sbzxb
+.section sbzya
+.section sbzyb
+.section sbzza
+.section sbzzb
+.section sbz1a
+.section sbz1b
+.section sbz2a
+.section sbz2b
+.section sbz3a
+.section sbz3b
+.section sbz4a
+.section sbz4b
+.section sbz5a
+.section sbz5b
+.section sbz6a
+.section sbz6b
+.section sbz7a
+.section sbz7b
+.section sbz8a
+.section sbz8b
+.section sbz9a
+.section sbz9b
+.section sbz0a
+.section sbz0b
+.section sb1aa
+.section sb1ab
+.section sb1ba
+.section sb1bb
+.section sb1ca
+.section sb1cb
+.section sb1da
+.section sb1db
+.section sb1ea
+.section sb1eb
+.section sb1fa
+.section sb1fb
+.section sb1ga
+.section sb1gb
+.section sb1ha
+.section sb1hb
+.section sb1ia
+.section sb1ib
+.section sb1ja
+.section sb1jb
+.section sb1ka
+.section sb1kb
+.section sb1la
+.section sb1lb
+.section sb1ma
+.section sb1mb
+.section sb1na
+.section sb1nb
+.section sb1oa
+.section sb1ob
+.section sb1pa
+.section sb1pb
+.section sb1qa
+.section sb1qb
+.section sb1ra
+.section sb1rb
+.section sb1sa
+.section sb1sb
+.section sb1ta
+.section sb1tb
+.section sb1ua
+.section sb1ub
+.section sb1va
+.section sb1vb
+.section sb1wa
+.section sb1wb
+.section sb1xa
+.section sb1xb
+.section sb1ya
+.section sb1yb
+.section sb1za
+.section sb1zb
+.section sb11a
+.section sb11b
+.section sb12a
+.section sb12b
+.section sb13a
+.section sb13b
+.section sb14a
+.section sb14b
+.section sb15a
+.section sb15b
+.section sb16a
+.section sb16b
+.section sb17a
+.section sb17b
+.section sb18a
+.section sb18b
+.section sb19a
+.section sb19b
+.section sb10a
+.section sb10b
+.section sb2aa
+.section sb2ab
+.section sb2ba
+.section sb2bb
+.section sb2ca
+.section sb2cb
+.section sb2da
+.section sb2db
+.section sb2ea
+.section sb2eb
+.section sb2fa
+.section sb2fb
+.section sb2ga
+.section sb2gb
+.section sb2ha
+.section sb2hb
+.section sb2ia
+.section sb2ib
+.section sb2ja
+.section sb2jb
+.section sb2ka
+.section sb2kb
+.section sb2la
+.section sb2lb
+.section sb2ma
+.section sb2mb
+.section sb2na
+.section sb2nb
+.section sb2oa
+.section sb2ob
+.section sb2pa
+.section sb2pb
+.section sb2qa
+.section sb2qb
+.section sb2ra
+.section sb2rb
+.section sb2sa
+.section sb2sb
+.section sb2ta
+.section sb2tb
+.section sb2ua
+.section sb2ub
+.section sb2va
+.section sb2vb
+.section sb2wa
+.section sb2wb
+.section sb2xa
+.section sb2xb
+.section sb2ya
+.section sb2yb
+.section sb2za
+.section sb2zb
+.section sb21a
+.section sb21b
+.section sb22a
+.section sb22b
+.section sb23a
+.section sb23b
+.section sb24a
+.section sb24b
+.section sb25a
+.section sb25b
+.section sb26a
+.section sb26b
+.section sb27a
+.section sb27b
+.section sb28a
+.section sb28b
+.section sb29a
+.section sb29b
+.section sb20a
+.section sb20b
+.section sb3aa
+.section sb3ab
+.section sb3ba
+.section sb3bb
+.section sb3ca
+.section sb3cb
+.section sb3da
+.section sb3db
+.section sb3ea
+.section sb3eb
+.section sb3fa
+.section sb3fb
+.section sb3ga
+.section sb3gb
+.section sb3ha
+.section sb3hb
+.section sb3ia
+.section sb3ib
+.section sb3ja
+.section sb3jb
+.section sb3ka
+.section sb3kb
+.section sb3la
+.section sb3lb
+.section sb3ma
+.section sb3mb
+.section sb3na
+.section sb3nb
+.section sb3oa
+.section sb3ob
+.section sb3pa
+.section sb3pb
+.section sb3qa
+.section sb3qb
+.section sb3ra
+.section sb3rb
+.section sb3sa
+.section sb3sb
+.section sb3ta
+.section sb3tb
+.section sb3ua
+.section sb3ub
+.section sb3va
+.section sb3vb
+.section sb3wa
+.section sb3wb
+.section sb3xa
+.section sb3xb
+.section sb3ya
+.section sb3yb
+.section sb3za
+.section sb3zb
+.section sb31a
+.section sb31b
+.section sb32a
+.section sb32b
+.section sb33a
+.section sb33b
+.section sb34a
+.section sb34b
+.section sb35a
+.section sb35b
+.section sb36a
+.section sb36b
+.section sb37a
+.section sb37b
+.section sb38a
+.section sb38b
+.section sb39a
+.section sb39b
+.section sb30a
+.section sb30b
+.section sb4aa
+.section sb4ab
+.section sb4ba
+.section sb4bb
+.section sb4ca
+.section sb4cb
+.section sb4da
+.section sb4db
+.section sb4ea
+.section sb4eb
+.section sb4fa
+.section sb4fb
+.section sb4ga
+.section sb4gb
+.section sb4ha
+.section sb4hb
+.section sb4ia
+.section sb4ib
+.section sb4ja
+.section sb4jb
+.section sb4ka
+.section sb4kb
+.section sb4la
+.section sb4lb
+.section sb4ma
+.section sb4mb
+.section sb4na
+.section sb4nb
+.section sb4oa
+.section sb4ob
+.section sb4pa
+.section sb4pb
+.section sb4qa
+.section sb4qb
+.section sb4ra
+.section sb4rb
+.section sb4sa
+.section sb4sb
+.section sb4ta
+.section sb4tb
+.section sb4ua
+.section sb4ub
+.section sb4va
+.section sb4vb
+.section sb4wa
+.section sb4wb
+.section sb4xa
+.section sb4xb
+.section sb4ya
+.section sb4yb
+.section sb4za
+.section sb4zb
+.section sb41a
+.section sb41b
+.section sb42a
+.section sb42b
+.section sb43a
+.section sb43b
+.section sb44a
+.section sb44b
+.section sb45a
+.section sb45b
+.section sb46a
+.section sb46b
+.section sb47a
+.section sb47b
+.section sb48a
+.section sb48b
+.section sb49a
+.section sb49b
+.section sb40a
+.section sb40b
+.section sb5aa
+.section sb5ab
+.section sb5ba
+.section sb5bb
+.section sb5ca
+.section sb5cb
+.section sb5da
+.section sb5db
+.section sb5ea
+.section sb5eb
+.section sb5fa
+.section sb5fb
+.section sb5ga
+.section sb5gb
+.section sb5ha
+.section sb5hb
+.section sb5ia
+.section sb5ib
+.section sb5ja
+.section sb5jb
+.section sb5ka
+.section sb5kb
+.section sb5la
+.section sb5lb
+.section sb5ma
+.section sb5mb
+.section sb5na
+.section sb5nb
+.section sb5oa
+.section sb5ob
+.section sb5pa
+.section sb5pb
+.section sb5qa
+.section sb5qb
+.section sb5ra
+.section sb5rb
+.section sb5sa
+.section sb5sb
+.section sb5ta
+.section sb5tb
+.section sb5ua
+.section sb5ub
+.section sb5va
+.section sb5vb
+.section sb5wa
+.section sb5wb
+.section sb5xa
+.section sb5xb
+.section sb5ya
+.section sb5yb
+.section sb5za
+.section sb5zb
+.section sb51a
+.section sb51b
+.section sb52a
+.section sb52b
+.section sb53a
+.section sb53b
+.section sb54a
+.section sb54b
+.section sb55a
+.section sb55b
+.section sb56a
+.section sb56b
+.section sb57a
+.section sb57b
+.section sb58a
+.section sb58b
+.section sb59a
+.section sb59b
+.section sb50a
+.section sb50b
+.section sb6aa
+.section sb6ab
+.section sb6ba
+.section sb6bb
+.section sb6ca
+.section sb6cb
+.section sb6da
+.section sb6db
+.section sb6ea
+.section sb6eb
+.section sb6fa
+.section sb6fb
+.section sb6ga
+.section sb6gb
+.section sb6ha
+.section sb6hb
+.section sb6ia
+.section sb6ib
+.section sb6ja
+.section sb6jb
+.section sb6ka
+.section sb6kb
+.section sb6la
+.section sb6lb
+.section sb6ma
+.section sb6mb
+.section sb6na
+.section sb6nb
+.section sb6oa
+.section sb6ob
+.section sb6pa
+.section sb6pb
+.section sb6qa
+.section sb6qb
+.section sb6ra
+.section sb6rb
+.section sb6sa
+.section sb6sb
+.section sb6ta
+.section sb6tb
+.section sb6ua
+.section sb6ub
+.section sb6va
+.section sb6vb
+.section sb6wa
+.section sb6wb
+.section sb6xa
+.section sb6xb
+.section sb6ya
+.section sb6yb
+.section sb6za
+.section sb6zb
+.section sb61a
+.section sb61b
+.section sb62a
+.section sb62b
+.section sb63a
+.section sb63b
+.section sb64a
+.section sb64b
+.section sb65a
+.section sb65b
+.section sb66a
+.section sb66b
+.section sb67a
+.section sb67b
+.section sb68a
+.section sb68b
+.section sb69a
+.section sb69b
+.section sb60a
+.section sb60b
+.section sb7aa
+.section sb7ab
+.section sb7ba
+.section sb7bb
+.section sb7ca
+.section sb7cb
+.section sb7da
+.section sb7db
+.section sb7ea
+.section sb7eb
+.section sb7fa
+.section sb7fb
+.section sb7ga
+.section sb7gb
+.section sb7ha
+.section sb7hb
+.section sb7ia
+.section sb7ib
+.section sb7ja
+.section sb7jb
+.section sb7ka
+.section sb7kb
+.section sb7la
+.section sb7lb
+.section sb7ma
+.section sb7mb
+.section sb7na
+.section sb7nb
+.section sb7oa
+.section sb7ob
+.section sb7pa
+.section sb7pb
+.section sb7qa
+.section sb7qb
+.section sb7ra
+.section sb7rb
+.section sb7sa
+.section sb7sb
+.section sb7ta
+.section sb7tb
+.section sb7ua
+.section sb7ub
+.section sb7va
+.section sb7vb
+.section sb7wa
+.section sb7wb
+.section sb7xa
+.section sb7xb
+.section sb7ya
+.section sb7yb
+.section sb7za
+.section sb7zb
+.section sb71a
+.section sb71b
+.section sb72a
+.section sb72b
+.section sb73a
+.section sb73b
+.section sb74a
+.section sb74b
+.section sb75a
+.section sb75b
+.section sb76a
+.section sb76b
+.section sb77a
+.section sb77b
+.section sb78a
+.section sb78b
+.section sb79a
+.section sb79b
+.section sb70a
+.section sb70b
+.section sb8aa
+.section sb8ab
+.section sb8ba
+.section sb8bb
+.section sb8ca
+.section sb8cb
+.section sb8da
+.section sb8db
+.section sb8ea
+.section sb8eb
+.section sb8fa
+.section sb8fb
+.section sb8ga
+.section sb8gb
+.section sb8ha
+.section sb8hb
+.section sb8ia
+.section sb8ib
+.section sb8ja
+.section sb8jb
+.section sb8ka
+.section sb8kb
+.section sb8la
+.section sb8lb
+.section sb8ma
+.section sb8mb
+.section sb8na
+.section sb8nb
+.section sb8oa
+.section sb8ob
+.section sb8pa
+.section sb8pb
+.section sb8qa
+.section sb8qb
+.section sb8ra
+.section sb8rb
+.section sb8sa
+.section sb8sb
+.section sb8ta
+.section sb8tb
+.section sb8ua
+.section sb8ub
+.section sb8va
+.section sb8vb
+.section sb8wa
+.section sb8wb
+.section sb8xa
+.section sb8xb
+.section sb8ya
+.section sb8yb
+.section sb8za
+.section sb8zb
+.section sb81a
+.section sb81b
+.section sb82a
+.section sb82b
+.section sb83a
+.section sb83b
+.section sb84a
+.section sb84b
+.section sb85a
+.section sb85b
+.section sb86a
+.section sb86b
+.section sb87a
+.section sb87b
+.section sb88a
+.section sb88b
+.section sb89a
+.section sb89b
+.section sb80a
+.section sb80b
+.section sb9aa
+.section sb9ab
+.section sb9ba
+.section sb9bb
+.section sb9ca
+.section sb9cb
+.section sb9da
+.section sb9db
+.section sb9ea
+.section sb9eb
+.section sb9fa
+.section sb9fb
+.section sb9ga
+.section sb9gb
+.section sb9ha
+.section sb9hb
+.section sb9ia
+.section sb9ib
+.section sb9ja
+.section sb9jb
+.section sb9ka
+.section sb9kb
+.section sb9la
+.section sb9lb
+.section sb9ma
+.section sb9mb
+.section sb9na
+.section sb9nb
+.section sb9oa
+.section sb9ob
+.section sb9pa
+.section sb9pb
+.section sb9qa
+.section sb9qb
+.section sb9ra
+.section sb9rb
+.section sb9sa
+.section sb9sb
+.section sb9ta
+.section sb9tb
+.section sb9ua
+.section sb9ub
+.section sb9va
+.section sb9vb
+.section sb9wa
+.section sb9wb
+.section sb9xa
+.section sb9xb
+.section sb9ya
+.section sb9yb
+.section sb9za
+.section sb9zb
+.section sb91a
+.section sb91b
+.section sb92a
+.section sb92b
+.section sb93a
+.section sb93b
+.section sb94a
+.section sb94b
+.section sb95a
+.section sb95b
+.section sb96a
+.section sb96b
+.section sb97a
+.section sb97b
+.section sb98a
+.section sb98b
+.section sb99a
+.section sb99b
+.section sb90a
+.section sb90b
+.section sb0aa
+.section sb0ab
+.section sb0ba
+.section sb0bb
+.section sb0ca
+.section sb0cb
+.section sb0da
+.section sb0db
+.section sb0ea
+.section sb0eb
+.section sb0fa
+.section sb0fb
+.section sb0ga
+.section sb0gb
+.section sb0ha
+.section sb0hb
+.section sb0ia
+.section sb0ib
+.section sb0ja
+.section sb0jb
+.section sb0ka
+.section sb0kb
+.section sb0la
+.section sb0lb
+.section sb0ma
+.section sb0mb
+.section sb0na
+.section sb0nb
+.section sb0oa
+.section sb0ob
+.section sb0pa
+.section sb0pb
+.section sb0qa
+.section sb0qb
+.section sb0ra
+.section sb0rb
+.section sb0sa
+.section sb0sb
+.section sb0ta
+.section sb0tb
+.section sb0ua
+.section sb0ub
+.section sb0va
+.section sb0vb
+.section sb0wa
+.section sb0wb
+.section sb0xa
+.section sb0xb
+.section sb0ya
+.section sb0yb
+.section sb0za
+.section sb0zb
+.section sb01a
+.section sb01b
+.section sb02a
+.section sb02b
+.section sb03a
+.section sb03b
+.section sb04a
+.section sb04b
+.section sb05a
+.section sb05b
+.section sb06a
+.section sb06b
+.section sb07a
+.section sb07b
+.section sb08a
+.section sb08b
+.section sb09a
+.section sb09b
+.section sb00a
+.section sb00b
+.section scaaa
+.section scaab
+.section scaba
+.section scabb
+.section scaca
+.section scacb
+.section scada
+.section scadb
+.section scaea
+.section scaeb
+.section scafa
+.section scafb
+.section scaga
+.section scagb
+.section scaha
+.section scahb
+.section scaia
+.section scaib
+.section scaja
+.section scajb
+.section scaka
+.section scakb
+.section scala
+.section scalb
+.section scama
+.section scamb
+.section scana
+.section scanb
+.section scaoa
+.section scaob
+.section scapa
+.section scapb
+.section scaqa
+.section scaqb
+.section scara
+.section scarb
+.section scasa
+.section scasb
+.section scata
+.section scatb
+.section scaua
+.section scaub
+.section scava
+.section scavb
+.section scawa
+.section scawb
+.section scaxa
+.section scaxb
+.section scaya
+.section scayb
+.section scaza
+.section scazb
+.section sca1a
+.section sca1b
+.section sca2a
+.section sca2b
+.section sca3a
+.section sca3b
+.section sca4a
+.section sca4b
+.section sca5a
+.section sca5b
+.section sca6a
+.section sca6b
+.section sca7a
+.section sca7b
+.section sca8a
+.section sca8b
+.section sca9a
+.section sca9b
+.section sca0a
+.section sca0b
+.section scbaa
+.section scbab
+.section scbba
+.section scbbb
+.section scbca
+.section scbcb
+.section scbda
+.section scbdb
+.section scbea
+.section scbeb
+.section scbfa
+.section scbfb
+.section scbga
+.section scbgb
+.section scbha
+.section scbhb
+.section scbia
+.section scbib
+.section scbja
+.section scbjb
+.section scbka
+.section scbkb
+.section scbla
+.section scblb
+.section scbma
+.section scbmb
+.section scbna
+.section scbnb
+.section scboa
+.section scbob
+.section scbpa
+.section scbpb
+.section scbqa
+.section scbqb
+.section scbra
+.section scbrb
+.section scbsa
+.section scbsb
+.section scbta
+.section scbtb
+.section scbua
+.section scbub
+.section scbva
+.section scbvb
+.section scbwa
+.section scbwb
+.section scbxa
+.section scbxb
+.section scbya
+.section scbyb
+.section scbza
+.section scbzb
+.section scb1a
+.section scb1b
+.section scb2a
+.section scb2b
+.section scb3a
+.section scb3b
+.section scb4a
+.section scb4b
+.section scb5a
+.section scb5b
+.section scb6a
+.section scb6b
+.section scb7a
+.section scb7b
+.section scb8a
+.section scb8b
+.section scb9a
+.section scb9b
+.section scb0a
+.section scb0b
+.section sccaa
+.section sccab
+.section sccba
+.section sccbb
+.section sccca
+.section scccb
+.section sccda
+.section sccdb
+.section sccea
+.section scceb
+.section sccfa
+.section sccfb
+.section sccga
+.section sccgb
+.section sccha
+.section scchb
+.section sccia
+.section sccib
+.section sccja
+.section sccjb
+.section sccka
+.section scckb
+.section sccla
+.section scclb
+.section sccma
+.section sccmb
+.section sccna
+.section sccnb
+.section sccoa
+.section sccob
+.section sccpa
+.section sccpb
+.section sccqa
+.section sccqb
+.section sccra
+.section sccrb
+.section sccsa
+.section sccsb
+.section sccta
+.section scctb
+.section sccua
+.section sccub
+.section sccva
+.section sccvb
+.section sccwa
+.section sccwb
+.section sccxa
+.section sccxb
+.section sccya
+.section sccyb
+.section sccza
+.section scczb
+.section scc1a
+.section scc1b
+.section scc2a
+.section scc2b
+.section scc3a
+.section scc3b
+.section scc4a
+.section scc4b
+.section scc5a
+.section scc5b
+.section scc6a
+.section scc6b
+.section scc7a
+.section scc7b
+.section scc8a
+.section scc8b
+.section scc9a
+.section scc9b
+.section scc0a
+.section scc0b
+.section scdaa
+.section scdab
+.section scdba
+.section scdbb
+.section scdca
+.section scdcb
+.section scdda
+.section scddb
+.section scdea
+.section scdeb
+.section scdfa
+.section scdfb
+.section scdga
+.section scdgb
+.section scdha
+.section scdhb
+.section scdia
+.section scdib
+.section scdja
+.section scdjb
+.section scdka
+.section scdkb
+.section scdla
+.section scdlb
+.section scdma
+.section scdmb
+.section scdna
+.section scdnb
+.section scdoa
+.section scdob
+.section scdpa
+.section scdpb
+.section scdqa
+.section scdqb
+.section scdra
+.section scdrb
+.section scdsa
+.section scdsb
+.section scdta
+.section scdtb
+.section scdua
+.section scdub
+.section scdva
+.section scdvb
+.section scdwa
+.section scdwb
+.section scdxa
+.section scdxb
+.section scdya
+.section scdyb
+.section scdza
+.section scdzb
+.section scd1a
+.section scd1b
+.section scd2a
+.section scd2b
+.section scd3a
+.section scd3b
+.section scd4a
+.section scd4b
+.section scd5a
+.section scd5b
+.section scd6a
+.section scd6b
+.section scd7a
+.section scd7b
+.section scd8a
+.section scd8b
+.section scd9a
+.section scd9b
+.section scd0a
+.section scd0b
+.section sceaa
+.section sceab
+.section sceba
+.section scebb
+.section sceca
+.section scecb
+.section sceda
+.section scedb
+.section sceea
+.section sceeb
+.section scefa
+.section scefb
+.section scega
+.section scegb
+.section sceha
+.section scehb
+.section sceia
+.section sceib
+.section sceja
+.section scejb
+.section sceka
+.section scekb
+.section scela
+.section scelb
+.section scema
+.section scemb
+.section scena
+.section scenb
+.section sceoa
+.section sceob
+.section scepa
+.section scepb
+.section sceqa
+.section sceqb
+.section scera
+.section scerb
+.section scesa
+.section scesb
+.section sceta
+.section scetb
+.section sceua
+.section sceub
+.section sceva
+.section scevb
+.section scewa
+.section scewb
+.section scexa
+.section scexb
+.section sceya
+.section sceyb
+.section sceza
+.section scezb
+.section sce1a
+.section sce1b
+.section sce2a
+.section sce2b
+.section sce3a
+.section sce3b
+.section sce4a
+.section sce4b
+.section sce5a
+.section sce5b
+.section sce6a
+.section sce6b
+.section sce7a
+.section sce7b
+.section sce8a
+.section sce8b
+.section sce9a
+.section sce9b
+.section sce0a
+.section sce0b
+.section scfaa
+.section scfab
+.section scfba
+.section scfbb
+.section scfca
+.section scfcb
+.section scfda
+.section scfdb
+.section scfea
+.section scfeb
+.section scffa
+.section scffb
+.section scfga
+.section scfgb
+.section scfha
+.section scfhb
+.section scfia
+.section scfib
+.section scfja
+.section scfjb
+.section scfka
+.section scfkb
+.section scfla
+.section scflb
+.section scfma
+.section scfmb
+.section scfna
+.section scfnb
+.section scfoa
+.section scfob
+.section scfpa
+.section scfpb
+.section scfqa
+.section scfqb
+.section scfra
+.section scfrb
+.section scfsa
+.section scfsb
+.section scfta
+.section scftb
+.section scfua
+.section scfub
+.section scfva
+.section scfvb
+.section scfwa
+.section scfwb
+.section scfxa
+.section scfxb
+.section scfya
+.section scfyb
+.section scfza
+.section scfzb
+.section scf1a
+.section scf1b
+.section scf2a
+.section scf2b
+.section scf3a
+.section scf3b
+.section scf4a
+.section scf4b
+.section scf5a
+.section scf5b
+.section scf6a
+.section scf6b
+.section scf7a
+.section scf7b
+.section scf8a
+.section scf8b
+.section scf9a
+.section scf9b
+.section scf0a
+.section scf0b
+.section scgaa
+.section scgab
+.section scgba
+.section scgbb
+.section scgca
+.section scgcb
+.section scgda
+.section scgdb
+.section scgea
+.section scgeb
+.section scgfa
+.section scgfb
+.section scgga
+.section scggb
+.section scgha
+.section scghb
+.section scgia
+.section scgib
+.section scgja
+.section scgjb
+.section scgka
+.section scgkb
+.section scgla
+.section scglb
+.section scgma
+.section scgmb
+.section scgna
+.section scgnb
+.section scgoa
+.section scgob
+.section scgpa
+.section scgpb
+.section scgqa
+.section scgqb
+.section scgra
+.section scgrb
+.section scgsa
+.section scgsb
+.section scgta
+.section scgtb
+.section scgua
+.section scgub
+.section scgva
+.section scgvb
+.section scgwa
+.section scgwb
+.section scgxa
+.section scgxb
+.section scgya
+.section scgyb
+.section scgza
+.section scgzb
+.section scg1a
+.section scg1b
+.section scg2a
+.section scg2b
+.section scg3a
+.section scg3b
+.section scg4a
+.section scg4b
+.section scg5a
+.section scg5b
+.section scg6a
+.section scg6b
+.section scg7a
+.section scg7b
+.section scg8a
+.section scg8b
+.section scg9a
+.section scg9b
+.section scg0a
+.section scg0b
+.section schaa
+.section schab
+.section schba
+.section schbb
+.section schca
+.section schcb
+.section schda
+.section schdb
+.section schea
+.section scheb
+.section schfa
+.section schfb
+.section schga
+.section schgb
+.section schha
+.section schhb
+.section schia
+.section schib
+.section schja
+.section schjb
+.section schka
+.section schkb
+.section schla
+.section schlb
+.section schma
+.section schmb
+.section schna
+.section schnb
+.section schoa
+.section schob
+.section schpa
+.section schpb
+.section schqa
+.section schqb
+.section schra
+.section schrb
+.section schsa
+.section schsb
+.section schta
+.section schtb
+.section schua
+.section schub
+.section schva
+.section schvb
+.section schwa
+.section schwb
+.section schxa
+.section schxb
+.section schya
+.section schyb
+.section schza
+.section schzb
+.section sch1a
+.section sch1b
+.section sch2a
+.section sch2b
+.section sch3a
+.section sch3b
+.section sch4a
+.section sch4b
+.section sch5a
+.section sch5b
+.section sch6a
+.section sch6b
+.section sch7a
+.section sch7b
+.section sch8a
+.section sch8b
+.section sch9a
+.section sch9b
+.section sch0a
+.section sch0b
+.section sciaa
+.section sciab
+.section sciba
+.section scibb
+.section scica
+.section scicb
+.section scida
+.section scidb
+.section sciea
+.section scieb
+.section scifa
+.section scifb
+.section sciga
+.section scigb
+.section sciha
+.section scihb
+.section sciia
+.section sciib
+.section scija
+.section scijb
+.section scika
+.section scikb
+.section scila
+.section scilb
+.section scima
+.section scimb
+.section scina
+.section scinb
+.section scioa
+.section sciob
+.section scipa
+.section scipb
+.section sciqa
+.section sciqb
+.section scira
+.section scirb
+.section scisa
+.section scisb
+.section scita
+.section scitb
+.section sciua
+.section sciub
+.section sciva
+.section scivb
+.section sciwa
+.section sciwb
+.section scixa
+.section scixb
+.section sciya
+.section sciyb
+.section sciza
+.section scizb
+.section sci1a
+.section sci1b
+.section sci2a
+.section sci2b
+.section sci3a
+.section sci3b
+.section sci4a
+.section sci4b
+.section sci5a
+.section sci5b
+.section sci6a
+.section sci6b
+.section sci7a
+.section sci7b
+.section sci8a
+.section sci8b
+.section sci9a
+.section sci9b
+.section sci0a
+.section sci0b
+.section scjaa
+.section scjab
+.section scjba
+.section scjbb
+.section scjca
+.section scjcb
+.section scjda
+.section scjdb
+.section scjea
+.section scjeb
+.section scjfa
+.section scjfb
+.section scjga
+.section scjgb
+.section scjha
+.section scjhb
+.section scjia
+.section scjib
+.section scjja
+.section scjjb
+.section scjka
+.section scjkb
+.section scjla
+.section scjlb
+.section scjma
+.section scjmb
+.section scjna
+.section scjnb
+.section scjoa
+.section scjob
+.section scjpa
+.section scjpb
+.section scjqa
+.section scjqb
+.section scjra
+.section scjrb
+.section scjsa
+.section scjsb
+.section scjta
+.section scjtb
+.section scjua
+.section scjub
+.section scjva
+.section scjvb
+.section scjwa
+.section scjwb
+.section scjxa
+.section scjxb
+.section scjya
+.section scjyb
+.section scjza
+.section scjzb
+.section scj1a
+.section scj1b
+.section scj2a
+.section scj2b
+.section scj3a
+.section scj3b
+.section scj4a
+.section scj4b
+.section scj5a
+.section scj5b
+.section scj6a
+.section scj6b
+.section scj7a
+.section scj7b
+.section scj8a
+.section scj8b
+.section scj9a
+.section scj9b
+.section scj0a
+.section scj0b
+.section sckaa
+.section sckab
+.section sckba
+.section sckbb
+.section sckca
+.section sckcb
+.section sckda
+.section sckdb
+.section sckea
+.section sckeb
+.section sckfa
+.section sckfb
+.section sckga
+.section sckgb
+.section sckha
+.section sckhb
+.section sckia
+.section sckib
+.section sckja
+.section sckjb
+.section sckka
+.section sckkb
+.section sckla
+.section scklb
+.section sckma
+.section sckmb
+.section sckna
+.section scknb
+.section sckoa
+.section sckob
+.section sckpa
+.section sckpb
+.section sckqa
+.section sckqb
+.section sckra
+.section sckrb
+.section scksa
+.section scksb
+.section sckta
+.section scktb
+.section sckua
+.section sckub
+.section sckva
+.section sckvb
+.section sckwa
+.section sckwb
+.section sckxa
+.section sckxb
+.section sckya
+.section sckyb
+.section sckza
+.section sckzb
+.section sck1a
+.section sck1b
+.section sck2a
+.section sck2b
+.section sck3a
+.section sck3b
+.section sck4a
+.section sck4b
+.section sck5a
+.section sck5b
+.section sck6a
+.section sck6b
+.section sck7a
+.section sck7b
+.section sck8a
+.section sck8b
+.section sck9a
+.section sck9b
+.section sck0a
+.section sck0b
+.section sclaa
+.section sclab
+.section sclba
+.section sclbb
+.section sclca
+.section sclcb
+.section sclda
+.section scldb
+.section sclea
+.section scleb
+.section sclfa
+.section sclfb
+.section sclga
+.section sclgb
+.section sclha
+.section sclhb
+.section sclia
+.section sclib
+.section sclja
+.section scljb
+.section sclka
+.section sclkb
+.section sclla
+.section scllb
+.section sclma
+.section sclmb
+.section sclna
+.section sclnb
+.section scloa
+.section sclob
+.section sclpa
+.section sclpb
+.section sclqa
+.section sclqb
+.section sclra
+.section sclrb
+.section sclsa
+.section sclsb
+.section sclta
+.section scltb
+.section sclua
+.section sclub
+.section sclva
+.section sclvb
+.section sclwa
+.section sclwb
+.section sclxa
+.section sclxb
+.section sclya
+.section sclyb
+.section sclza
+.section sclzb
+.section scl1a
+.section scl1b
+.section scl2a
+.section scl2b
+.section scl3a
+.section scl3b
+.section scl4a
+.section scl4b
+.section scl5a
+.section scl5b
+.section scl6a
+.section scl6b
+.section scl7a
+.section scl7b
+.section scl8a
+.section scl8b
+.section scl9a
+.section scl9b
+.section scl0a
+.section scl0b
+.section scmaa
+.section scmab
+.section scmba
+.section scmbb
+.section scmca
+.section scmcb
+.section scmda
+.section scmdb
+.section scmea
+.section scmeb
+.section scmfa
+.section scmfb
+.section scmga
+.section scmgb
+.section scmha
+.section scmhb
+.section scmia
+.section scmib
+.section scmja
+.section scmjb
+.section scmka
+.section scmkb
+.section scmla
+.section scmlb
+.section scmma
+.section scmmb
+.section scmna
+.section scmnb
+.section scmoa
+.section scmob
+.section scmpa
+.section scmpb
+.section scmqa
+.section scmqb
+.section scmra
+.section scmrb
+.section scmsa
+.section scmsb
+.section scmta
+.section scmtb
+.section scmua
+.section scmub
+.section scmva
+.section scmvb
+.section scmwa
+.section scmwb
+.section scmxa
+.section scmxb
+.section scmya
+.section scmyb
+.section scmza
+.section scmzb
+.section scm1a
+.section scm1b
+.section scm2a
+.section scm2b
+.section scm3a
+.section scm3b
+.section scm4a
+.section scm4b
+.section scm5a
+.section scm5b
+.section scm6a
+.section scm6b
+.section scm7a
+.section scm7b
+.section scm8a
+.section scm8b
+.section scm9a
+.section scm9b
+.section scm0a
+.section scm0b
+.section scnaa
+.section scnab
+.section scnba
+.section scnbb
+.section scnca
+.section scncb
+.section scnda
+.section scndb
+.section scnea
+.section scneb
+.section scnfa
+.section scnfb
+.section scnga
+.section scngb
+.section scnha
+.section scnhb
+.section scnia
+.section scnib
+.section scnja
+.section scnjb
+.section scnka
+.section scnkb
+.section scnla
+.section scnlb
+.section scnma
+.section scnmb
+.section scnna
+.section scnnb
+.section scnoa
+.section scnob
+.section scnpa
+.section scnpb
+.section scnqa
+.section scnqb
+.section scnra
+.section scnrb
+.section scnsa
+.section scnsb
+.section scnta
+.section scntb
+.section scnua
+.section scnub
+.section scnva
+.section scnvb
+.section scnwa
+.section scnwb
+.section scnxa
+.section scnxb
+.section scnya
+.section scnyb
+.section scnza
+.section scnzb
+.section scn1a
+.section scn1b
+.section scn2a
+.section scn2b
+.section scn3a
+.section scn3b
+.section scn4a
+.section scn4b
+.section scn5a
+.section scn5b
+.section scn6a
+.section scn6b
+.section scn7a
+.section scn7b
+.section scn8a
+.section scn8b
+.section scn9a
+.section scn9b
+.section scn0a
+.section scn0b
+.section scoaa
+.section scoab
+.section scoba
+.section scobb
+.section scoca
+.section scocb
+.section scoda
+.section scodb
+.section scoea
+.section scoeb
+.section scofa
+.section scofb
+.section scoga
+.section scogb
+.section scoha
+.section scohb
+.section scoia
+.section scoib
+.section scoja
+.section scojb
+.section scoka
+.section scokb
+.section scola
+.section scolb
+.section scoma
+.section scomb
+.section scona
+.section sconb
+.section scooa
+.section scoob
+.section scopa
+.section scopb
+.section scoqa
+.section scoqb
+.section scora
+.section scorb
+.section scosa
+.section scosb
+.section scota
+.section scotb
+.section scoua
+.section scoub
+.section scova
+.section scovb
+.section scowa
+.section scowb
+.section scoxa
+.section scoxb
+.section scoya
+.section scoyb
+.section scoza
+.section scozb
+.section sco1a
+.section sco1b
+.section sco2a
+.section sco2b
+.section sco3a
+.section sco3b
+.section sco4a
+.section sco4b
+.section sco5a
+.section sco5b
+.section sco6a
+.section sco6b
+.section sco7a
+.section sco7b
+.section sco8a
+.section sco8b
+.section sco9a
+.section sco9b
+.section sco0a
+.section sco0b
+.section scpaa
+.section scpab
+.section scpba
+.section scpbb
+.section scpca
+.section scpcb
+.section scpda
+.section scpdb
+.section scpea
+.section scpeb
+.section scpfa
+.section scpfb
+.section scpga
+.section scpgb
+.section scpha
+.section scphb
+.section scpia
+.section scpib
+.section scpja
+.section scpjb
+.section scpka
+.section scpkb
+.section scpla
+.section scplb
+.section scpma
+.section scpmb
+.section scpna
+.section scpnb
+.section scpoa
+.section scpob
+.section scppa
+.section scppb
+.section scpqa
+.section scpqb
+.section scpra
+.section scprb
+.section scpsa
+.section scpsb
+.section scpta
+.section scptb
+.section scpua
+.section scpub
+.section scpva
+.section scpvb
+.section scpwa
+.section scpwb
+.section scpxa
+.section scpxb
+.section scpya
+.section scpyb
+.section scpza
+.section scpzb
+.section scp1a
+.section scp1b
+.section scp2a
+.section scp2b
+.section scp3a
+.section scp3b
+.section scp4a
+.section scp4b
+.section scp5a
+.section scp5b
+.section scp6a
+.section scp6b
+.section scp7a
+.section scp7b
+.section scp8a
+.section scp8b
+.section scp9a
+.section scp9b
+.section scp0a
+.section scp0b
+.section scqaa
+.section scqab
+.section scqba
+.section scqbb
+.section scqca
+.section scqcb
+.section scqda
+.section scqdb
+.section scqea
+.section scqeb
+.section scqfa
+.section scqfb
+.section scqga
+.section scqgb
+.section scqha
+.section scqhb
+.section scqia
+.section scqib
+.section scqja
+.section scqjb
+.section scqka
+.section scqkb
+.section scqla
+.section scqlb
+.section scqma
+.section scqmb
+.section scqna
+.section scqnb
+.section scqoa
+.section scqob
+.section scqpa
+.section scqpb
+.section scqqa
+.section scqqb
+.section scqra
+.section scqrb
+.section scqsa
+.section scqsb
+.section scqta
+.section scqtb
+.section scqua
+.section scqub
+.section scqva
+.section scqvb
+.section scqwa
+.section scqwb
+.section scqxa
+.section scqxb
+.section scqya
+.section scqyb
+.section scqza
+.section scqzb
+.section scq1a
+.section scq1b
+.section scq2a
+.section scq2b
+.section scq3a
+.section scq3b
+.section scq4a
+.section scq4b
+.section scq5a
+.section scq5b
+.section scq6a
+.section scq6b
+.section scq7a
+.section scq7b
+.section scq8a
+.section scq8b
+.section scq9a
+.section scq9b
+.section scq0a
+.section scq0b
+.section scraa
+.section scrab
+.section scrba
+.section scrbb
+.section scrca
+.section scrcb
+.section scrda
+.section scrdb
+.section screa
+.section screb
+.section scrfa
+.section scrfb
+.section scrga
+.section scrgb
+.section scrha
+.section scrhb
+.section scria
+.section scrib
+.section scrja
+.section scrjb
+.section scrka
+.section scrkb
+.section scrla
+.section scrlb
+.section scrma
+.section scrmb
+.section scrna
+.section scrnb
+.section scroa
+.section scrob
+.section scrpa
+.section scrpb
+.section scrqa
+.section scrqb
+.section scrra
+.section scrrb
+.section scrsa
+.section scrsb
+.section scrta
+.section scrtb
+.section scrua
+.section scrub
+.section scrva
+.section scrvb
+.section scrwa
+.section scrwb
+.section scrxa
+.section scrxb
+.section scrya
+.section scryb
+.section scrza
+.section scrzb
+.section scr1a
+.section scr1b
+.section scr2a
+.section scr2b
+.section scr3a
+.section scr3b
+.section scr4a
+.section scr4b
+.section scr5a
+.section scr5b
+.section scr6a
+.section scr6b
+.section scr7a
+.section scr7b
+.section scr8a
+.section scr8b
+.section scr9a
+.section scr9b
+.section scr0a
+.section scr0b
+.section scsaa
+.section scsab
+.section scsba
+.section scsbb
+.section scsca
+.section scscb
+.section scsda
+.section scsdb
+.section scsea
+.section scseb
+.section scsfa
+.section scsfb
+.section scsga
+.section scsgb
+.section scsha
+.section scshb
+.section scsia
+.section scsib
+.section scsja
+.section scsjb
+.section scska
+.section scskb
+.section scsla
+.section scslb
+.section scsma
+.section scsmb
+.section scsna
+.section scsnb
+.section scsoa
+.section scsob
+.section scspa
+.section scspb
+.section scsqa
+.section scsqb
+.section scsra
+.section scsrb
+.section scssa
+.section scssb
+.section scsta
+.section scstb
+.section scsua
+.section scsub
+.section scsva
+.section scsvb
+.section scswa
+.section scswb
+.section scsxa
+.section scsxb
+.section scsya
+.section scsyb
+.section scsza
+.section scszb
+.section scs1a
+.section scs1b
+.section scs2a
+.section scs2b
+.section scs3a
+.section scs3b
+.section scs4a
+.section scs4b
+.section scs5a
+.section scs5b
+.section scs6a
+.section scs6b
+.section scs7a
+.section scs7b
+.section scs8a
+.section scs8b
+.section scs9a
+.section scs9b
+.section scs0a
+.section scs0b
+.section sctaa
+.section sctab
+.section sctba
+.section sctbb
+.section sctca
+.section sctcb
+.section sctda
+.section sctdb
+.section sctea
+.section scteb
+.section sctfa
+.section sctfb
+.section sctga
+.section sctgb
+.section sctha
+.section scthb
+.section sctia
+.section sctib
+.section sctja
+.section sctjb
+.section sctka
+.section sctkb
+.section sctla
+.section sctlb
+.section sctma
+.section sctmb
+.section sctna
+.section sctnb
+.section sctoa
+.section sctob
+.section sctpa
+.section sctpb
+.section sctqa
+.section sctqb
+.section sctra
+.section sctrb
+.section sctsa
+.section sctsb
+.section sctta
+.section scttb
+.section sctua
+.section sctub
+.section sctva
+.section sctvb
+.section sctwa
+.section sctwb
+.section sctxa
+.section sctxb
+.section sctya
+.section sctyb
+.section sctza
+.section sctzb
+.section sct1a
+.section sct1b
+.section sct2a
+.section sct2b
+.section sct3a
+.section sct3b
+.section sct4a
+.section sct4b
+.section sct5a
+.section sct5b
+.section sct6a
+.section sct6b
+.section sct7a
+.section sct7b
+.section sct8a
+.section sct8b
+.section sct9a
+.section sct9b
+.section sct0a
+.section sct0b
+.section scuaa
+.section scuab
+.section scuba
+.section scubb
+.section scuca
+.section scucb
+.section scuda
+.section scudb
+.section scuea
+.section scueb
+.section scufa
+.section scufb
+.section scuga
+.section scugb
+.section scuha
+.section scuhb
+.section scuia
+.section scuib
+.section scuja
+.section scujb
+.section scuka
+.section scukb
+.section scula
+.section sculb
+.section scuma
+.section scumb
+.section scuna
+.section scunb
+.section scuoa
+.section scuob
+.section scupa
+.section scupb
+.section scuqa
+.section scuqb
+.section scura
+.section scurb
+.section scusa
+.section scusb
+.section scuta
+.section scutb
+.section scuua
+.section scuub
+.section scuva
+.section scuvb
+.section scuwa
+.section scuwb
+.section scuxa
+.section scuxb
+.section scuya
+.section scuyb
+.section scuza
+.section scuzb
+.section scu1a
+.section scu1b
+.section scu2a
+.section scu2b
+.section scu3a
+.section scu3b
+.section scu4a
+.section scu4b
+.section scu5a
+.section scu5b
+.section scu6a
+.section scu6b
+.section scu7a
+.section scu7b
+.section scu8a
+.section scu8b
+.section scu9a
+.section scu9b
+.section scu0a
+.section scu0b
+.section scvaa
+.section scvab
+.section scvba
+.section scvbb
+.section scvca
+.section scvcb
+.section scvda
+.section scvdb
+.section scvea
+.section scveb
+.section scvfa
+.section scvfb
+.section scvga
+.section scvgb
+.section scvha
+.section scvhb
+.section scvia
+.section scvib
+.section scvja
+.section scvjb
+.section scvka
+.section scvkb
+.section scvla
+.section scvlb
+.section scvma
+.section scvmb
+.section scvna
+.section scvnb
+.section scvoa
+.section scvob
+.section scvpa
+.section scvpb
+.section scvqa
+.section scvqb
+.section scvra
+.section scvrb
+.section scvsa
+.section scvsb
+.section scvta
+.section scvtb
+.section scvua
+.section scvub
+.section scvva
+.section scvvb
+.section scvwa
+.section scvwb
+.section scvxa
+.section scvxb
+.section scvya
+.section scvyb
+.section scvza
+.section scvzb
+.section scv1a
+.section scv1b
+.section scv2a
+.section scv2b
+.section scv3a
+.section scv3b
+.section scv4a
+.section scv4b
+.section scv5a
+.section scv5b
+.section scv6a
+.section scv6b
+.section scv7a
+.section scv7b
+.section scv8a
+.section scv8b
+.section scv9a
+.section scv9b
+.section scv0a
+.section scv0b
+.section scwaa
+.section scwab
+.section scwba
+.section scwbb
+.section scwca
+.section scwcb
+.section scwda
+.section scwdb
+.section scwea
+.section scweb
+.section scwfa
+.section scwfb
+.section scwga
+.section scwgb
+.section scwha
+.section scwhb
+.section scwia
+.section scwib
+.section scwja
+.section scwjb
+.section scwka
+.section scwkb
+.section scwla
+.section scwlb
+.section scwma
+.section scwmb
+.section scwna
+.section scwnb
+.section scwoa
+.section scwob
+.section scwpa
+.section scwpb
+.section scwqa
+.section scwqb
+.section scwra
+.section scwrb
+.section scwsa
+.section scwsb
+.section scwta
+.section scwtb
+.section scwua
+.section scwub
+.section scwva
+.section scwvb
+.section scwwa
+.section scwwb
+.section scwxa
+.section scwxb
+.section scwya
+.section scwyb
+.section scwza
+.section scwzb
+.section scw1a
+.section scw1b
+.section scw2a
+.section scw2b
+.section scw3a
+.section scw3b
+.section scw4a
+.section scw4b
+.section scw5a
+.section scw5b
+.section scw6a
+.section scw6b
+.section scw7a
+.section scw7b
+.section scw8a
+.section scw8b
+.section scw9a
+.section scw9b
+.section scw0a
+.section scw0b
+.section scxaa
+.section scxab
+.section scxba
+.section scxbb
+.section scxca
+.section scxcb
+.section scxda
+.section scxdb
+.section scxea
+.section scxeb
+.section scxfa
+.section scxfb
+.section scxga
+.section scxgb
+.section scxha
+.section scxhb
+.section scxia
+.section scxib
+.section scxja
+.section scxjb
+.section scxka
+.section scxkb
+.section scxla
+.section scxlb
+.section scxma
+.section scxmb
+.section scxna
+.section scxnb
+.section scxoa
+.section scxob
+.section scxpa
+.section scxpb
+.section scxqa
+.section scxqb
+.section scxra
+.section scxrb
+.section scxsa
+.section scxsb
+.section scxta
+.section scxtb
+.section scxua
+.section scxub
+.section scxva
+.section scxvb
+.section scxwa
+.section scxwb
+.section scxxa
+.section scxxb
+.section scxya
+.section scxyb
+.section scxza
+.section scxzb
+.section scx1a
+.section scx1b
+.section scx2a
+.section scx2b
+.section scx3a
+.section scx3b
+.section scx4a
+.section scx4b
+.section scx5a
+.section scx5b
+.section scx6a
+.section scx6b
+.section scx7a
+.section scx7b
+.section scx8a
+.section scx8b
+.section scx9a
+.section scx9b
+.section scx0a
+.section scx0b
+.section scyaa
+.section scyab
+.section scyba
+.section scybb
+.section scyca
+.section scycb
+.section scyda
+.section scydb
+.section scyea
+.section scyeb
+.section scyfa
+.section scyfb
+.section scyga
+.section scygb
+.section scyha
+.section scyhb
+.section scyia
+.section scyib
+.section scyja
+.section scyjb
+.section scyka
+.section scykb
+.section scyla
+.section scylb
+.section scyma
+.section scymb
+.section scyna
+.section scynb
+.section scyoa
+.section scyob
+.section scypa
+.section scypb
+.section scyqa
+.section scyqb
+.section scyra
+.section scyrb
+.section scysa
+.section scysb
+.section scyta
+.section scytb
+.section scyua
+.section scyub
+.section scyva
+.section scyvb
+.section scywa
+.section scywb
+.section scyxa
+.section scyxb
+.section scyya
+.section scyyb
+.section scyza
+.section scyzb
+.section scy1a
+.section scy1b
+.section scy2a
+.section scy2b
+.section scy3a
+.section scy3b
+.section scy4a
+.section scy4b
+.section scy5a
+.section scy5b
+.section scy6a
+.section scy6b
+.section scy7a
+.section scy7b
+.section scy8a
+.section scy8b
+.section scy9a
+.section scy9b
+.section scy0a
+.section scy0b
+.section sczaa
+.section sczab
+.section sczba
+.section sczbb
+.section sczca
+.section sczcb
+.section sczda
+.section sczdb
+.section sczea
+.section sczeb
+.section sczfa
+.section sczfb
+.section sczga
+.section sczgb
+.section sczha
+.section sczhb
+.section sczia
+.section sczib
+.section sczja
+.section sczjb
+.section sczka
+.section sczkb
+.section sczla
+.section sczlb
+.section sczma
+.section sczmb
+.section sczna
+.section scznb
+.section sczoa
+.section sczob
+.section sczpa
+.section sczpb
+.section sczqa
+.section sczqb
+.section sczra
+.section sczrb
+.section sczsa
+.section sczsb
+.section sczta
+.section scztb
+.section sczua
+.section sczub
+.section sczva
+.section sczvb
+.section sczwa
+.section sczwb
+.section sczxa
+.section sczxb
+.section sczya
+.section sczyb
+.section sczza
+.section sczzb
+.section scz1a
+.section scz1b
+.section scz2a
+.section scz2b
+.section scz3a
+.section scz3b
+.section scz4a
+.section scz4b
+.section scz5a
+.section scz5b
+.section scz6a
+.section scz6b
+.section scz7a
+.section scz7b
+.section scz8a
+.section scz8b
+.section scz9a
+.section scz9b
+.section scz0a
+.section scz0b
+.section sc1aa
+.section sc1ab
+.section sc1ba
+.section sc1bb
+.section sc1ca
+.section sc1cb
+.section sc1da
+.section sc1db
+.section sc1ea
+.section sc1eb
+.section sc1fa
+.section sc1fb
+.section sc1ga
+.section sc1gb
+.section sc1ha
+.section sc1hb
+.section sc1ia
+.section sc1ib
+.section sc1ja
+.section sc1jb
+.section sc1ka
+.section sc1kb
+.section sc1la
+.section sc1lb
+.section sc1ma
+.section sc1mb
+.section sc1na
+.section sc1nb
+.section sc1oa
+.section sc1ob
+.section sc1pa
+.section sc1pb
+.section sc1qa
+.section sc1qb
+.section sc1ra
+.section sc1rb
+.section sc1sa
+.section sc1sb
+.section sc1ta
+.section sc1tb
+.section sc1ua
+.section sc1ub
+.section sc1va
+.section sc1vb
+.section sc1wa
+.section sc1wb
+.section sc1xa
+.section sc1xb
+.section sc1ya
+.section sc1yb
+.section sc1za
+.section sc1zb
+.section sc11a
+.section sc11b
+.section sc12a
+.section sc12b
+.section sc13a
+.section sc13b
+.section sc14a
+.section sc14b
+.section sc15a
+.section sc15b
+.section sc16a
+.section sc16b
+.section sc17a
+.section sc17b
+.section sc18a
+.section sc18b
+.section sc19a
+.section sc19b
+.section sc10a
+.section sc10b
+.section sc2aa
+.section sc2ab
+.section sc2ba
+.section sc2bb
+.section sc2ca
+.section sc2cb
+.section sc2da
+.section sc2db
+.section sc2ea
+.section sc2eb
+.section sc2fa
+.section sc2fb
+.section sc2ga
+.section sc2gb
+.section sc2ha
+.section sc2hb
+.section sc2ia
+.section sc2ib
+.section sc2ja
+.section sc2jb
+.section sc2ka
+.section sc2kb
+.section sc2la
+.section sc2lb
+.section sc2ma
+.section sc2mb
+.section sc2na
+.section sc2nb
+.section sc2oa
+.section sc2ob
+.section sc2pa
+.section sc2pb
+.section sc2qa
+.section sc2qb
+.section sc2ra
+.section sc2rb
+.section sc2sa
+.section sc2sb
+.section sc2ta
+.section sc2tb
+.section sc2ua
+.section sc2ub
+.section sc2va
+.section sc2vb
+.section sc2wa
+.section sc2wb
+.section sc2xa
+.section sc2xb
+.section sc2ya
+.section sc2yb
+.section sc2za
+.section sc2zb
+.section sc21a
+.section sc21b
+.section sc22a
+.section sc22b
+.section sc23a
+.section sc23b
+.section sc24a
+.section sc24b
+.section sc25a
+.section sc25b
+.section sc26a
+.section sc26b
+.section sc27a
+.section sc27b
+.section sc28a
+.section sc28b
+.section sc29a
+.section sc29b
+.section sc20a
+.section sc20b
+.section sc3aa
+.section sc3ab
+.section sc3ba
+.section sc3bb
+.section sc3ca
+.section sc3cb
+.section sc3da
+.section sc3db
+.section sc3ea
+.section sc3eb
+.section sc3fa
+.section sc3fb
+.section sc3ga
+.section sc3gb
+.section sc3ha
+.section sc3hb
+.section sc3ia
+.section sc3ib
+.section sc3ja
+.section sc3jb
+.section sc3ka
+.section sc3kb
+.section sc3la
+.section sc3lb
+.section sc3ma
+.section sc3mb
+.section sc3na
+.section sc3nb
+.section sc3oa
+.section sc3ob
+.section sc3pa
+.section sc3pb
+.section sc3qa
+.section sc3qb
+.section sc3ra
+.section sc3rb
+.section sc3sa
+.section sc3sb
+.section sc3ta
+.section sc3tb
+.section sc3ua
+.section sc3ub
+.section sc3va
+.section sc3vb
+.section sc3wa
+.section sc3wb
+.section sc3xa
+.section sc3xb
+.section sc3ya
+.section sc3yb
+.section sc3za
+.section sc3zb
+.section sc31a
+.section sc31b
+.section sc32a
+.section sc32b
+.section sc33a
+.section sc33b
+.section sc34a
+.section sc34b
+.section sc35a
+.section sc35b
+.section sc36a
+.section sc36b
+.section sc37a
+.section sc37b
+.section sc38a
+.section sc38b
+.section sc39a
+.section sc39b
+.section sc30a
+.section sc30b
+.section sc4aa
+.section sc4ab
+.section sc4ba
+.section sc4bb
+.section sc4ca
+.section sc4cb
+.section sc4da
+.section sc4db
+.section sc4ea
+.section sc4eb
+.section sc4fa
+.section sc4fb
+.section sc4ga
+.section sc4gb
+.section sc4ha
+.section sc4hb
+.section sc4ia
+.section sc4ib
+.section sc4ja
+.section sc4jb
+.section sc4ka
+.section sc4kb
+.section sc4la
+.section sc4lb
+.section sc4ma
+.section sc4mb
+.section sc4na
+.section sc4nb
+.section sc4oa
+.section sc4ob
+.section sc4pa
+.section sc4pb
+.section sc4qa
+.section sc4qb
+.section sc4ra
+.section sc4rb
+.section sc4sa
+.section sc4sb
+.section sc4ta
+.section sc4tb
+.section sc4ua
+.section sc4ub
+.section sc4va
+.section sc4vb
+.section sc4wa
+.section sc4wb
+.section sc4xa
+.section sc4xb
+.section sc4ya
+.section sc4yb
+.section sc4za
+.section sc4zb
+.section sc41a
+.section sc41b
+.section sc42a
+.section sc42b
+.section sc43a
+.section sc43b
+.section sc44a
+.section sc44b
+.section sc45a
+.section sc45b
+.section sc46a
+.section sc46b
+.section sc47a
+.section sc47b
+.section sc48a
+.section sc48b
+.section sc49a
+.section sc49b
+.section sc40a
+.section sc40b
+.section sc5aa
+.section sc5ab
+.section sc5ba
+.section sc5bb
+.section sc5ca
+.section sc5cb
+.section sc5da
+.section sc5db
+.section sc5ea
+.section sc5eb
+.section sc5fa
+.section sc5fb
+.section sc5ga
+.section sc5gb
+.section sc5ha
+.section sc5hb
+.section sc5ia
+.section sc5ib
+.section sc5ja
+.section sc5jb
+.section sc5ka
+.section sc5kb
+.section sc5la
+.section sc5lb
+.section sc5ma
+.section sc5mb
+.section sc5na
+.section sc5nb
+.section sc5oa
+.section sc5ob
+.section sc5pa
+.section sc5pb
+.section sc5qa
+.section sc5qb
+.section sc5ra
+.section sc5rb
+.section sc5sa
+.section sc5sb
+.section sc5ta
+.section sc5tb
+.section sc5ua
+.section sc5ub
+.section sc5va
+.section sc5vb
+.section sc5wa
+.section sc5wb
+.section sc5xa
+.section sc5xb
+.section sc5ya
+.section sc5yb
+.section sc5za
+.section sc5zb
+.section sc51a
+.section sc51b
+.section sc52a
+.section sc52b
+.section sc53a
+.section sc53b
+.section sc54a
+.section sc54b
+.section sc55a
+.section sc55b
+.section sc56a
+.section sc56b
+.section sc57a
+.section sc57b
+.section sc58a
+.section sc58b
+.section sc59a
+.section sc59b
+.section sc50a
+.section sc50b
+.section sc6aa
+.section sc6ab
+.section sc6ba
+.section sc6bb
+.section sc6ca
+.section sc6cb
+.section sc6da
+.section sc6db
+.section sc6ea
+.section sc6eb
+.section sc6fa
+.section sc6fb
+.section sc6ga
+.section sc6gb
+.section sc6ha
+.section sc6hb
+.section sc6ia
+.section sc6ib
+.section sc6ja
+.section sc6jb
+.section sc6ka
+.section sc6kb
+.section sc6la
+.section sc6lb
+.section sc6ma
+.section sc6mb
+.section sc6na
+.section sc6nb
+.section sc6oa
+.section sc6ob
+.section sc6pa
+.section sc6pb
+.section sc6qa
+.section sc6qb
+.section sc6ra
+.section sc6rb
+.section sc6sa
+.section sc6sb
+.section sc6ta
+.section sc6tb
+.section sc6ua
+.section sc6ub
+.section sc6va
+.section sc6vb
+.section sc6wa
+.section sc6wb
+.section sc6xa
+.section sc6xb
+.section sc6ya
+.section sc6yb
+.section sc6za
+.section sc6zb
+.section sc61a
+.section sc61b
+.section sc62a
+.section sc62b
+.section sc63a
+.section sc63b
+.section sc64a
+.section sc64b
+.section sc65a
+.section sc65b
+.section sc66a
+.section sc66b
+.section sc67a
+.section sc67b
+.section sc68a
+.section sc68b
+.section sc69a
+.section sc69b
+.section sc60a
+.section sc60b
+.section sc7aa
+.section sc7ab
+.section sc7ba
+.section sc7bb
+.section sc7ca
+.section sc7cb
+.section sc7da
+.section sc7db
+.section sc7ea
+.section sc7eb
+.section sc7fa
+.section sc7fb
+.section sc7ga
+.section sc7gb
+.section sc7ha
+.section sc7hb
+.section sc7ia
+.section sc7ib
+.section sc7ja
+.section sc7jb
+.section sc7ka
+.section sc7kb
+.section sc7la
+.section sc7lb
+.section sc7ma
+.section sc7mb
+.section sc7na
+.section sc7nb
+.section sc7oa
+.section sc7ob
+.section sc7pa
+.section sc7pb
+.section sc7qa
+.section sc7qb
+.section sc7ra
+.section sc7rb
+.section sc7sa
+.section sc7sb
+.section sc7ta
+.section sc7tb
+.section sc7ua
+.section sc7ub
+.section sc7va
+.section sc7vb
+.section sc7wa
+.section sc7wb
+.section sc7xa
+.section sc7xb
+.section sc7ya
+.section sc7yb
+.section sc7za
+.section sc7zb
+.section sc71a
+.section sc71b
+.section sc72a
+.section sc72b
+.section sc73a
+.section sc73b
+.section sc74a
+.section sc74b
+.section sc75a
+.section sc75b
+.section sc76a
+.section sc76b
+.section sc77a
+.section sc77b
+.section sc78a
+.section sc78b
+.section sc79a
+.section sc79b
+.section sc70a
+.section sc70b
+.section sc8aa
+.section sc8ab
+.section sc8ba
+.section sc8bb
+.section sc8ca
+.section sc8cb
+.section sc8da
+.section sc8db
+.section sc8ea
+.section sc8eb
+.section sc8fa
+.section sc8fb
+.section sc8ga
+.section sc8gb
+.section sc8ha
+.section sc8hb
+.section sc8ia
+.section sc8ib
+.section sc8ja
+.section sc8jb
+.section sc8ka
+.section sc8kb
+.section sc8la
+.section sc8lb
+.section sc8ma
+.section sc8mb
+.section sc8na
+.section sc8nb
+.section sc8oa
+.section sc8ob
+.section sc8pa
+.section sc8pb
+.section sc8qa
+.section sc8qb
+.section sc8ra
+.section sc8rb
+.section sc8sa
+.section sc8sb
+.section sc8ta
+.section sc8tb
+.section sc8ua
+.section sc8ub
+.section sc8va
+.section sc8vb
+.section sc8wa
+.section sc8wb
+.section sc8xa
+.section sc8xb
+.section sc8ya
+.section sc8yb
+.section sc8za
+.section sc8zb
+.section sc81a
+.section sc81b
+.section sc82a
+.section sc82b
+.section sc83a
+.section sc83b
+.section sc84a
+.section sc84b
+.section sc85a
+.section sc85b
+.section sc86a
+.section sc86b
+.section sc87a
+.section sc87b
+.section sc88a
+.section sc88b
+.section sc89a
+.section sc89b
+.section sc80a
+.section sc80b
+.section sc9aa
+.section sc9ab
+.section sc9ba
+.section sc9bb
+.section sc9ca
+.section sc9cb
+.section sc9da
+.section sc9db
+.section sc9ea
+.section sc9eb
+.section sc9fa
+.section sc9fb
+.section sc9ga
+.section sc9gb
+.section sc9ha
+.section sc9hb
+.section sc9ia
+.section sc9ib
+.section sc9ja
+.section sc9jb
+.section sc9ka
+.section sc9kb
+.section sc9la
+.section sc9lb
+.section sc9ma
+.section sc9mb
+.section sc9na
+.section sc9nb
+.section sc9oa
+.section sc9ob
+.section sc9pa
+.section sc9pb
+.section sc9qa
+.section sc9qb
+.section sc9ra
+.section sc9rb
+.section sc9sa
+.section sc9sb
+.section sc9ta
+.section sc9tb
+.section sc9ua
+.section sc9ub
+.section sc9va
+.section sc9vb
+.section sc9wa
+.section sc9wb
+.section sc9xa
+.section sc9xb
+.section sc9ya
+.section sc9yb
+.section sc9za
+.section sc9zb
+.section sc91a
+.section sc91b
+.section sc92a
+.section sc92b
+.section sc93a
+.section sc93b
+.section sc94a
+.section sc94b
+.section sc95a
+.section sc95b
+.section sc96a
+.section sc96b
+.section sc97a
+.section sc97b
+.section sc98a
+.section sc98b
+.section sc99a
+.section sc99b
+.section sc90a
+.section sc90b
+.section sc0aa
+.section sc0ab
+.section sc0ba
+.section sc0bb
+.section sc0ca
+.section sc0cb
+.section sc0da
+.section sc0db
+.section sc0ea
+.section sc0eb
+.section sc0fa
+.section sc0fb
+.section sc0ga
+.section sc0gb
+.section sc0ha
+.section sc0hb
+.section sc0ia
+.section sc0ib
+.section sc0ja
+.section sc0jb
+.section sc0ka
+.section sc0kb
+.section sc0la
+.section sc0lb
+.section sc0ma
+.section sc0mb
+.section sc0na
+.section sc0nb
+.section sc0oa
+.section sc0ob
+.section sc0pa
+.section sc0pb
+.section sc0qa
+.section sc0qb
+.section sc0ra
+.section sc0rb
+.section sc0sa
+.section sc0sb
+.section sc0ta
+.section sc0tb
+.section sc0ua
+.section sc0ub
+.section sc0va
+.section sc0vb
+.section sc0wa
+.section sc0wb
+.section sc0xa
+.section sc0xb
+.section sc0ya
+.section sc0yb
+.section sc0za
+.section sc0zb
+.section sc01a
+.section sc01b
+.section sc02a
+.section sc02b
+.section sc03a
+.section sc03b
+.section sc04a
+.section sc04b
+.section sc05a
+.section sc05b
+.section sc06a
+.section sc06b
+.section sc07a
+.section sc07b
+.section sc08a
+.section sc08b
+.section sc09a
+.section sc09b
+.section sc00a
+.section sc00b
+.section sdaaa
+.section sdaab
+.section sdaba
+.section sdabb
+.section sdaca
+.section sdacb
+.section sdada
+.section sdadb
+.section sdaea
+.section sdaeb
+.section sdafa
+.section sdafb
+.section sdaga
+.section sdagb
+.section sdaha
+.section sdahb
+.section sdaia
+.section sdaib
+.section sdaja
+.section sdajb
+.section sdaka
+.section sdakb
+.section sdala
+.section sdalb
+.section sdama
+.section sdamb
+.section sdana
+.section sdanb
+.section sdaoa
+.section sdaob
+.section sdapa
+.section sdapb
+.section sdaqa
+.section sdaqb
+.section sdara
+.section sdarb
+.section sdasa
+.section sdasb
+.section sdata
+.section sdatb
+.section sdaua
+.section sdaub
+.section sdava
+.section sdavb
+.section sdawa
+.section sdawb
+.section sdaxa
+.section sdaxb
+.section sdaya
+.section sdayb
+.section sdaza
+.section sdazb
+.section sda1a
+.section sda1b
+.section sda2a
+.section sda2b
+.section sda3a
+.section sda3b
+.section sda4a
+.section sda4b
+.section sda5a
+.section sda5b
+.section sda6a
+.section sda6b
+.section sda7a
+.section sda7b
+.section sda8a
+.section sda8b
+.section sda9a
+.section sda9b
+.section sda0a
+.section sda0b
+.section sdbaa
+.section sdbab
+.section sdbba
+.section sdbbb
+.section sdbca
+.section sdbcb
+.section sdbda
+.section sdbdb
+.section sdbea
+.section sdbeb
+.section sdbfa
+.section sdbfb
+.section sdbga
+.section sdbgb
+.section sdbha
+.section sdbhb
+.section sdbia
+.section sdbib
+.section sdbja
+.section sdbjb
+.section sdbka
+.section sdbkb
+.section sdbla
+.section sdblb
+.section sdbma
+.section sdbmb
+.section sdbna
+.section sdbnb
+.section sdboa
+.section sdbob
+.section sdbpa
+.section sdbpb
+.section sdbqa
+.section sdbqb
+.section sdbra
+.section sdbrb
+.section sdbsa
+.section sdbsb
+.section sdbta
+.section sdbtb
+.section sdbua
+.section sdbub
+.section sdbva
+.section sdbvb
+.section sdbwa
+.section sdbwb
+.section sdbxa
+.section sdbxb
+.section sdbya
+.section sdbyb
+.section sdbza
+.section sdbzb
+.section sdb1a
+.section sdb1b
+.section sdb2a
+.section sdb2b
+.section sdb3a
+.section sdb3b
+.section sdb4a
+.section sdb4b
+.section sdb5a
+.section sdb5b
+.section sdb6a
+.section sdb6b
+.section sdb7a
+.section sdb7b
+.section sdb8a
+.section sdb8b
+.section sdb9a
+.section sdb9b
+.section sdb0a
+.section sdb0b
+.section sdcaa
+.section sdcab
+.section sdcba
+.section sdcbb
+.section sdcca
+.section sdccb
+.section sdcda
+.section sdcdb
+.section sdcea
+.section sdceb
+.section sdcfa
+.section sdcfb
+.section sdcga
+.section sdcgb
+.section sdcha
+.section sdchb
+.section sdcia
+.section sdcib
+.section sdcja
+.section sdcjb
+.section sdcka
+.section sdckb
+.section sdcla
+.section sdclb
+.section sdcma
+.section sdcmb
+.section sdcna
+.section sdcnb
+.section sdcoa
+.section sdcob
+.section sdcpa
+.section sdcpb
+.section sdcqa
+.section sdcqb
+.section sdcra
+.section sdcrb
+.section sdcsa
+.section sdcsb
+.section sdcta
+.section sdctb
+.section sdcua
+.section sdcub
+.section sdcva
+.section sdcvb
+.section sdcwa
+.section sdcwb
+.section sdcxa
+.section sdcxb
+.section sdcya
+.section sdcyb
+.section sdcza
+.section sdczb
+.section sdc1a
+.section sdc1b
+.section sdc2a
+.section sdc2b
+.section sdc3a
+.section sdc3b
+.section sdc4a
+.section sdc4b
+.section sdc5a
+.section sdc5b
+.section sdc6a
+.section sdc6b
+.section sdc7a
+.section sdc7b
+.section sdc8a
+.section sdc8b
+.section sdc9a
+.section sdc9b
+.section sdc0a
+.section sdc0b
+.section sddaa
+.section sddab
+.section sddba
+.section sddbb
+.section sddca
+.section sddcb
+.section sddda
+.section sdddb
+.section sddea
+.section sddeb
+.section sddfa
+.section sddfb
+.section sddga
+.section sddgb
+.section sddha
+.section sddhb
+.section sddia
+.section sddib
+.section sddja
+.section sddjb
+.section sddka
+.section sddkb
+.section sddla
+.section sddlb
+.section sddma
+.section sddmb
+.section sddna
+.section sddnb
+.section sddoa
+.section sddob
+.section sddpa
+.section sddpb
+.section sddqa
+.section sddqb
+.section sddra
+.section sddrb
+.section sddsa
+.section sddsb
+.section sddta
+.section sddtb
+.section sddua
+.section sddub
+.section sddva
+.section sddvb
+.section sddwa
+.section sddwb
+.section sddxa
+.section sddxb
+.section sddya
+.section sddyb
+.section sddza
+.section sddzb
+.section sdd1a
+.section sdd1b
+.section sdd2a
+.section sdd2b
+.section sdd3a
+.section sdd3b
+.section sdd4a
+.section sdd4b
+.section sdd5a
+.section sdd5b
+.section sdd6a
+.section sdd6b
+.section sdd7a
+.section sdd7b
+.section sdd8a
+.section sdd8b
+.section sdd9a
+.section sdd9b
+.section sdd0a
+.section sdd0b
+.section sdeaa
+.section sdeab
+.section sdeba
+.section sdebb
+.section sdeca
+.section sdecb
+.section sdeda
+.section sdedb
+.section sdeea
+.section sdeeb
+.section sdefa
+.section sdefb
+.section sdega
+.section sdegb
+.section sdeha
+.section sdehb
+.section sdeia
+.section sdeib
+.section sdeja
+.section sdejb
+.section sdeka
+.section sdekb
+.section sdela
+.section sdelb
+.section sdema
+.section sdemb
+.section sdena
+.section sdenb
+.section sdeoa
+.section sdeob
+.section sdepa
+.section sdepb
+.section sdeqa
+.section sdeqb
+.section sdera
+.section sderb
+.section sdesa
+.section sdesb
+.section sdeta
+.section sdetb
+.section sdeua
+.section sdeub
+.section sdeva
+.section sdevb
+.section sdewa
+.section sdewb
+.section sdexa
+.section sdexb
+.section sdeya
+.section sdeyb
+.section sdeza
+.section sdezb
+.section sde1a
+.section sde1b
+.section sde2a
+.section sde2b
+.section sde3a
+.section sde3b
+.section sde4a
+.section sde4b
+.section sde5a
+.section sde5b
+.section sde6a
+.section sde6b
+.section sde7a
+.section sde7b
+.section sde8a
+.section sde8b
+.section sde9a
+.section sde9b
+.section sde0a
+.section sde0b
+.section sdfaa
+.section sdfab
+.section sdfba
+.section sdfbb
+.section sdfca
+.section sdfcb
+.section sdfda
+.section sdfdb
+.section sdfea
+.section sdfeb
+.section sdffa
+.section sdffb
+.section sdfga
+.section sdfgb
+.section sdfha
+.section sdfhb
+.section sdfia
+.section sdfib
+.section sdfja
+.section sdfjb
+.section sdfka
+.section sdfkb
+.section sdfla
+.section sdflb
+.section sdfma
+.section sdfmb
+.section sdfna
+.section sdfnb
+.section sdfoa
+.section sdfob
+.section sdfpa
+.section sdfpb
+.section sdfqa
+.section sdfqb
+.section sdfra
+.section sdfrb
+.section sdfsa
+.section sdfsb
+.section sdfta
+.section sdftb
+.section sdfua
+.section sdfub
+.section sdfva
+.section sdfvb
+.section sdfwa
+.section sdfwb
+.section sdfxa
+.section sdfxb
+.section sdfya
+.section sdfyb
+.section sdfza
+.section sdfzb
+.section sdf1a
+.section sdf1b
+.section sdf2a
+.section sdf2b
+.section sdf3a
+.section sdf3b
+.section sdf4a
+.section sdf4b
+.section sdf5a
+.section sdf5b
+.section sdf6a
+.section sdf6b
+.section sdf7a
+.section sdf7b
+.section sdf8a
+.section sdf8b
+.section sdf9a
+.section sdf9b
+.section sdf0a
+.section sdf0b
+.section sdgaa
+.section sdgab
+.section sdgba
+.section sdgbb
+.section sdgca
+.section sdgcb
+.section sdgda
+.section sdgdb
+.section sdgea
+.section sdgeb
+.section sdgfa
+.section sdgfb
+.section sdgga
+.section sdggb
+.section sdgha
+.section sdghb
+.section sdgia
+.section sdgib
+.section sdgja
+.section sdgjb
+.section sdgka
+.section sdgkb
+.section sdgla
+.section sdglb
+.section sdgma
+.section sdgmb
+.section sdgna
+.section sdgnb
+.section sdgoa
+.section sdgob
+.section sdgpa
+.section sdgpb
+.section sdgqa
+.section sdgqb
+.section sdgra
+.section sdgrb
+.section sdgsa
+.section sdgsb
+.section sdgta
+.section sdgtb
+.section sdgua
+.section sdgub
+.section sdgva
+.section sdgvb
+.section sdgwa
+.section sdgwb
+.section sdgxa
+.section sdgxb
+.section sdgya
+.section sdgyb
+.section sdgza
+.section sdgzb
+.section sdg1a
+.section sdg1b
+.section sdg2a
+.section sdg2b
+.section sdg3a
+.section sdg3b
+.section sdg4a
+.section sdg4b
+.section sdg5a
+.section sdg5b
+.section sdg6a
+.section sdg6b
+.section sdg7a
+.section sdg7b
+.section sdg8a
+.section sdg8b
+.section sdg9a
+.section sdg9b
+.section sdg0a
+.section sdg0b
+.section sdhaa
+.section sdhab
+.section sdhba
+.section sdhbb
+.section sdhca
+.section sdhcb
+.section sdhda
+.section sdhdb
+.section sdhea
+.section sdheb
+.section sdhfa
+.section sdhfb
+.section sdhga
+.section sdhgb
+.section sdhha
+.section sdhhb
+.section sdhia
+.section sdhib
+.section sdhja
+.section sdhjb
+.section sdhka
+.section sdhkb
+.section sdhla
+.section sdhlb
+.section sdhma
+.section sdhmb
+.section sdhna
+.section sdhnb
+.section sdhoa
+.section sdhob
+.section sdhpa
+.section sdhpb
+.section sdhqa
+.section sdhqb
+.section sdhra
+.section sdhrb
+.section sdhsa
+.section sdhsb
+.section sdhta
+.section sdhtb
+.section sdhua
+.section sdhub
+.section sdhva
+.section sdhvb
+.section sdhwa
+.section sdhwb
+.section sdhxa
+.section sdhxb
+.section sdhya
+.section sdhyb
+.section sdhza
+.section sdhzb
+.section sdh1a
+.section sdh1b
+.section sdh2a
+.section sdh2b
+.section sdh3a
+.section sdh3b
+.section sdh4a
+.section sdh4b
+.section sdh5a
+.section sdh5b
+.section sdh6a
+.section sdh6b
+.section sdh7a
+.section sdh7b
+.section sdh8a
+.section sdh8b
+.section sdh9a
+.section sdh9b
+.section sdh0a
+.section sdh0b
+.section sdiaa
+.section sdiab
+.section sdiba
+.section sdibb
+.section sdica
+.section sdicb
+.section sdida
+.section sdidb
+.section sdiea
+.section sdieb
+.section sdifa
+.section sdifb
+.section sdiga
+.section sdigb
+.section sdiha
+.section sdihb
+.section sdiia
+.section sdiib
+.section sdija
+.section sdijb
+.section sdika
+.section sdikb
+.section sdila
+.section sdilb
+.section sdima
+.section sdimb
+.section sdina
+.section sdinb
+.section sdioa
+.section sdiob
+.section sdipa
+.section sdipb
+.section sdiqa
+.section sdiqb
+.section sdira
+.section sdirb
+.section sdisa
+.section sdisb
+.section sdita
+.section sditb
+.section sdiua
+.section sdiub
+.section sdiva
+.section sdivb
+.section sdiwa
+.section sdiwb
+.section sdixa
+.section sdixb
+.section sdiya
+.section sdiyb
+.section sdiza
+.section sdizb
+.section sdi1a
+.section sdi1b
+.section sdi2a
+.section sdi2b
+.section sdi3a
+.section sdi3b
+.section sdi4a
+.section sdi4b
+.section sdi5a
+.section sdi5b
+.section sdi6a
+.section sdi6b
+.section sdi7a
+.section sdi7b
+.section sdi8a
+.section sdi8b
+.section sdi9a
+.section sdi9b
+.section sdi0a
+.section sdi0b
+.section sdjaa
+.section sdjab
+.section sdjba
+.section sdjbb
+.section sdjca
+.section sdjcb
+.section sdjda
+.section sdjdb
+.section sdjea
+.section sdjeb
+.section sdjfa
+.section sdjfb
+.section sdjga
+.section sdjgb
+.section sdjha
+.section sdjhb
+.section sdjia
+.section sdjib
+.section sdjja
+.section sdjjb
+.section sdjka
+.section sdjkb
+.section sdjla
+.section sdjlb
+.section sdjma
+.section sdjmb
+.section sdjna
+.section sdjnb
+.section sdjoa
+.section sdjob
+.section sdjpa
+.section sdjpb
+.section sdjqa
+.section sdjqb
+.section sdjra
+.section sdjrb
+.section sdjsa
+.section sdjsb
+.section sdjta
+.section sdjtb
+.section sdjua
+.section sdjub
+.section sdjva
+.section sdjvb
+.section sdjwa
+.section sdjwb
+.section sdjxa
+.section sdjxb
+.section sdjya
+.section sdjyb
+.section sdjza
+.section sdjzb
+.section sdj1a
+.section sdj1b
+.section sdj2a
+.section sdj2b
+.section sdj3a
+.section sdj3b
+.section sdj4a
+.section sdj4b
+.section sdj5a
+.section sdj5b
+.section sdj6a
+.section sdj6b
+.section sdj7a
+.section sdj7b
+.section sdj8a
+.section sdj8b
+.section sdj9a
+.section sdj9b
+.section sdj0a
+.section sdj0b
+.section sdkaa
+.section sdkab
+.section sdkba
+.section sdkbb
+.section sdkca
+.section sdkcb
+.section sdkda
+.section sdkdb
+.section sdkea
+.section sdkeb
+.section sdkfa
+.section sdkfb
+.section sdkga
+.section sdkgb
+.section sdkha
+.section sdkhb
+.section sdkia
+.section sdkib
+.section sdkja
+.section sdkjb
+.section sdkka
+.section sdkkb
+.section sdkla
+.section sdklb
+.section sdkma
+.section sdkmb
+.section sdkna
+.section sdknb
+.section sdkoa
+.section sdkob
+.section sdkpa
+.section sdkpb
+.section sdkqa
+.section sdkqb
+.section sdkra
+.section sdkrb
+.section sdksa
+.section sdksb
+.section sdkta
+.section sdktb
+.section sdkua
+.section sdkub
+.section sdkva
+.section sdkvb
+.section sdkwa
+.section sdkwb
+.section sdkxa
+.section sdkxb
+.section sdkya
+.section sdkyb
+.section sdkza
+.section sdkzb
+.section sdk1a
+.section sdk1b
+.section sdk2a
+.section sdk2b
+.section sdk3a
+.section sdk3b
+.section sdk4a
+.section sdk4b
+.section sdk5a
+.section sdk5b
+.section sdk6a
+.section sdk6b
+.section sdk7a
+.section sdk7b
+.section sdk8a
+.section sdk8b
+.section sdk9a
+.section sdk9b
+.section sdk0a
+.section sdk0b
+.section sdlaa
+.section sdlab
+.section sdlba
+.section sdlbb
+.section sdlca
+.section sdlcb
+.section sdlda
+.section sdldb
+.section sdlea
+.section sdleb
+.section sdlfa
+.section sdlfb
+.section sdlga
+.section sdlgb
+.section sdlha
+.section sdlhb
+.section sdlia
+.section sdlib
+.section sdlja
+.section sdljb
+.section sdlka
+.section sdlkb
+.section sdlla
+.section sdllb
+.section sdlma
+.section sdlmb
+.section sdlna
+.section sdlnb
+.section sdloa
+.section sdlob
+.section sdlpa
+.section sdlpb
+.section sdlqa
+.section sdlqb
+.section sdlra
+.section sdlrb
+.section sdlsa
+.section sdlsb
+.section sdlta
+.section sdltb
+.section sdlua
+.section sdlub
+.section sdlva
+.section sdlvb
+.section sdlwa
+.section sdlwb
+.section sdlxa
+.section sdlxb
+.section sdlya
+.section sdlyb
+.section sdlza
+.section sdlzb
+.section sdl1a
+.section sdl1b
+.section sdl2a
+.section sdl2b
+.section sdl3a
+.section sdl3b
+.section sdl4a
+.section sdl4b
+.section sdl5a
+.section sdl5b
+.section sdl6a
+.section sdl6b
+.section sdl7a
+.section sdl7b
+.section sdl8a
+.section sdl8b
+.section sdl9a
+.section sdl9b
+.section sdl0a
+.section sdl0b
+.section sdmaa
+.section sdmab
+.section sdmba
+.section sdmbb
+.section sdmca
+.section sdmcb
+.section sdmda
+.section sdmdb
+.section sdmea
+.section sdmeb
+.section sdmfa
+.section sdmfb
+.section sdmga
+.section sdmgb
+.section sdmha
+.section sdmhb
+.section sdmia
+.section sdmib
+.section sdmja
+.section sdmjb
+.section sdmka
+.section sdmkb
+.section sdmla
+.section sdmlb
+.section sdmma
+.section sdmmb
+.section sdmna
+.section sdmnb
+.section sdmoa
+.section sdmob
+.section sdmpa
+.section sdmpb
+.section sdmqa
+.section sdmqb
+.section sdmra
+.section sdmrb
+.section sdmsa
+.section sdmsb
+.section sdmta
+.section sdmtb
+.section sdmua
+.section sdmub
+.section sdmva
+.section sdmvb
+.section sdmwa
+.section sdmwb
+.section sdmxa
+.section sdmxb
+.section sdmya
+.section sdmyb
+.section sdmza
+.section sdmzb
+.section sdm1a
+.section sdm1b
+.section sdm2a
+.section sdm2b
+.section sdm3a
+.section sdm3b
+.section sdm4a
+.section sdm4b
+.section sdm5a
+.section sdm5b
+.section sdm6a
+.section sdm6b
+.section sdm7a
+.section sdm7b
+.section sdm8a
+.section sdm8b
+.section sdm9a
+.section sdm9b
+.section sdm0a
+.section sdm0b
+.section sdnaa
+.section sdnab
+.section sdnba
+.section sdnbb
+.section sdnca
+.section sdncb
+.section sdnda
+.section sdndb
+.section sdnea
+.section sdneb
+.section sdnfa
+.section sdnfb
+.section sdnga
+.section sdngb
+.section sdnha
+.section sdnhb
+.section sdnia
+.section sdnib
+.section sdnja
+.section sdnjb
+.section sdnka
+.section sdnkb
+.section sdnla
+.section sdnlb
+.section sdnma
+.section sdnmb
+.section sdnna
+.section sdnnb
+.section sdnoa
+.section sdnob
+.section sdnpa
+.section sdnpb
+.section sdnqa
+.section sdnqb
+.section sdnra
+.section sdnrb
+.section sdnsa
+.section sdnsb
+.section sdnta
+.section sdntb
+.section sdnua
+.section sdnub
+.section sdnva
+.section sdnvb
+.section sdnwa
+.section sdnwb
+.section sdnxa
+.section sdnxb
+.section sdnya
+.section sdnyb
+.section sdnza
+.section sdnzb
+.section sdn1a
+.section sdn1b
+.section sdn2a
+.section sdn2b
+.section sdn3a
+.section sdn3b
+.section sdn4a
+.section sdn4b
+.section sdn5a
+.section sdn5b
+.section sdn6a
+.section sdn6b
+.section sdn7a
+.section sdn7b
+.section sdn8a
+.section sdn8b
+.section sdn9a
+.section sdn9b
+.section sdn0a
+.section sdn0b
+.section sdoaa
+.section sdoab
+.section sdoba
+.section sdobb
+.section sdoca
+.section sdocb
+.section sdoda
+.section sdodb
+.section sdoea
+.section sdoeb
+.section sdofa
+.section sdofb
+.section sdoga
+.section sdogb
+.section sdoha
+.section sdohb
+.section sdoia
+.section sdoib
+.section sdoja
+.section sdojb
+.section sdoka
+.section sdokb
+.section sdola
+.section sdolb
+.section sdoma
+.section sdomb
+.section sdona
+.section sdonb
+.section sdooa
+.section sdoob
+.section sdopa
+.section sdopb
+.section sdoqa
+.section sdoqb
+.section sdora
+.section sdorb
+.section sdosa
+.section sdosb
+.section sdota
+.section sdotb
+.section sdoua
+.section sdoub
+.section sdova
+.section sdovb
+.section sdowa
+.section sdowb
+.section sdoxa
+.section sdoxb
+.section sdoya
+.section sdoyb
+.section sdoza
+.section sdozb
+.section sdo1a
+.section sdo1b
+.section sdo2a
+.section sdo2b
+.section sdo3a
+.section sdo3b
+.section sdo4a
+.section sdo4b
+.section sdo5a
+.section sdo5b
+.section sdo6a
+.section sdo6b
+.section sdo7a
+.section sdo7b
+.section sdo8a
+.section sdo8b
+.section sdo9a
+.section sdo9b
+.section sdo0a
+.section sdo0b
+.section sdpaa
+.section sdpab
+.section sdpba
+.section sdpbb
+.section sdpca
+.section sdpcb
+.section sdpda
+.section sdpdb
+.section sdpea
+.section sdpeb
+.section sdpfa
+.section sdpfb
+.section sdpga
+.section sdpgb
+.section sdpha
+.section sdphb
+.section sdpia
+.section sdpib
+.section sdpja
+.section sdpjb
+.section sdpka
+.section sdpkb
+.section sdpla
+.section sdplb
+.section sdpma
+.section sdpmb
+.section sdpna
+.section sdpnb
+.section sdpoa
+.section sdpob
+.section sdppa
+.section sdppb
+.section sdpqa
+.section sdpqb
+.section sdpra
+.section sdprb
+.section sdpsa
+.section sdpsb
+.section sdpta
+.section sdptb
+.section sdpua
+.section sdpub
+.section sdpva
+.section sdpvb
+.section sdpwa
+.section sdpwb
+.section sdpxa
+.section sdpxb
+.section sdpya
+.section sdpyb
+.section sdpza
+.section sdpzb
+.section sdp1a
+.section sdp1b
+.section sdp2a
+.section sdp2b
+.section sdp3a
+.section sdp3b
+.section sdp4a
+.section sdp4b
+.section sdp5a
+.section sdp5b
+.section sdp6a
+.section sdp6b
+.section sdp7a
+.section sdp7b
+.section sdp8a
+.section sdp8b
+.section sdp9a
+.section sdp9b
+.section sdp0a
+.section sdp0b
+.section sdqaa
+.section sdqab
+.section sdqba
+.section sdqbb
+.section sdqca
+.section sdqcb
+.section sdqda
+.section sdqdb
+.section sdqea
+.section sdqeb
+.section sdqfa
+.section sdqfb
+.section sdqga
+.section sdqgb
+.section sdqha
+.section sdqhb
+.section sdqia
+.section sdqib
+.section sdqja
+.section sdqjb
+.section sdqka
+.section sdqkb
+.section sdqla
+.section sdqlb
+.section sdqma
+.section sdqmb
+.section sdqna
+.section sdqnb
+.section sdqoa
+.section sdqob
+.section sdqpa
+.section sdqpb
+.section sdqqa
+.section sdqqb
+.section sdqra
+.section sdqrb
+.section sdqsa
+.section sdqsb
+.section sdqta
+.section sdqtb
+.section sdqua
+.section sdqub
+.section sdqva
+.section sdqvb
+.section sdqwa
+.section sdqwb
+.section sdqxa
+.section sdqxb
+.section sdqya
+.section sdqyb
+.section sdqza
+.section sdqzb
+.section sdq1a
+.section sdq1b
+.section sdq2a
+.section sdq2b
+.section sdq3a
+.section sdq3b
+.section sdq4a
+.section sdq4b
+.section sdq5a
+.section sdq5b
+.section sdq6a
+.section sdq6b
+.section sdq7a
+.section sdq7b
+.section sdq8a
+.section sdq8b
+.section sdq9a
+.section sdq9b
+.section sdq0a
+.section sdq0b
+.section sdraa
+.section sdrab
+.section sdrba
+.section sdrbb
+.section sdrca
+.section sdrcb
+.section sdrda
+.section sdrdb
+.section sdrea
+.section sdreb
+.section sdrfa
+.section sdrfb
+.section sdrga
+.section sdrgb
+.section sdrha
+.section sdrhb
+.section sdria
+.section sdrib
+.section sdrja
+.section sdrjb
+.section sdrka
+.section sdrkb
+.section sdrla
+.section sdrlb
+.section sdrma
+.section sdrmb
+.section sdrna
+.section sdrnb
+.section sdroa
+.section sdrob
+.section sdrpa
+.section sdrpb
+.section sdrqa
+.section sdrqb
+.section sdrra
+.section sdrrb
+.section sdrsa
+.section sdrsb
+.section sdrta
+.section sdrtb
+.section sdrua
+.section sdrub
+.section sdrva
+.section sdrvb
+.section sdrwa
+.section sdrwb
+.section sdrxa
+.section sdrxb
+.section sdrya
+.section sdryb
+.section sdrza
+.section sdrzb
+.section sdr1a
+.section sdr1b
+.section sdr2a
+.section sdr2b
+.section sdr3a
+.section sdr3b
+.section sdr4a
+.section sdr4b
+.section sdr5a
+.section sdr5b
+.section sdr6a
+.section sdr6b
+.section sdr7a
+.section sdr7b
+.section sdr8a
+.section sdr8b
+.section sdr9a
+.section sdr9b
+.section sdr0a
+.section sdr0b
+.section sdsaa
+.section sdsab
+.section sdsba
+.section sdsbb
+.section sdsca
+.section sdscb
+.section sdsda
+.section sdsdb
+.section sdsea
+.section sdseb
+.section sdsfa
+.section sdsfb
+.section sdsga
+.section sdsgb
+.section sdsha
+.section sdshb
+.section sdsia
+.section sdsib
+.section sdsja
+.section sdsjb
+.section sdska
+.section sdskb
+.section sdsla
+.section sdslb
+.section sdsma
+.section sdsmb
+.section sdsna
+.section sdsnb
+.section sdsoa
+.section sdsob
+.section sdspa
+.section sdspb
+.section sdsqa
+.section sdsqb
+.section sdsra
+.section sdsrb
+.section sdssa
+.section sdssb
+.section sdsta
+.section sdstb
+.section sdsua
+.section sdsub
+.section sdsva
+.section sdsvb
+.section sdswa
+.section sdswb
+.section sdsxa
+.section sdsxb
+.section sdsya
+.section sdsyb
+.section sdsza
+.section sdszb
+.section sds1a
+.section sds1b
+.section sds2a
+.section sds2b
+.section sds3a
+.section sds3b
+.section sds4a
+.section sds4b
+.section sds5a
+.section sds5b
+.section sds6a
+.section sds6b
+.section sds7a
+.section sds7b
+.section sds8a
+.section sds8b
+.section sds9a
+.section sds9b
+.section sds0a
+.section sds0b
+.section sdtaa
+.section sdtab
+.section sdtba
+.section sdtbb
+.section sdtca
+.section sdtcb
+.section sdtda
+.section sdtdb
+.section sdtea
+.section sdteb
+.section sdtfa
+.section sdtfb
+.section sdtga
+.section sdtgb
+.section sdtha
+.section sdthb
+.section sdtia
+.section sdtib
+.section sdtja
+.section sdtjb
+.section sdtka
+.section sdtkb
+.section sdtla
+.section sdtlb
+.section sdtma
+.section sdtmb
+.section sdtna
+.section sdtnb
+.section sdtoa
+.section sdtob
+.section sdtpa
+.section sdtpb
+.section sdtqa
+.section sdtqb
+.section sdtra
+.section sdtrb
+.section sdtsa
+.section sdtsb
+.section sdtta
+.section sdttb
+.section sdtua
+.section sdtub
+.section sdtva
+.section sdtvb
+.section sdtwa
+.section sdtwb
+.section sdtxa
+.section sdtxb
+.section sdtya
+.section sdtyb
+.section sdtza
+.section sdtzb
+.section sdt1a
+.section sdt1b
+.section sdt2a
+.section sdt2b
+.section sdt3a
+.section sdt3b
+.section sdt4a
+.section sdt4b
+.section sdt5a
+.section sdt5b
+.section sdt6a
+.section sdt6b
+.section sdt7a
+.section sdt7b
+.section sdt8a
+.section sdt8b
+.section sdt9a
+.section sdt9b
+.section sdt0a
+.section sdt0b
+.section sduaa
+.section sduab
+.section sduba
+.section sdubb
+.section sduca
+.section sducb
+.section sduda
+.section sdudb
+.section sduea
+.section sdueb
+.section sdufa
+.section sdufb
+.section sduga
+.section sdugb
+.section sduha
+.section sduhb
+.section sduia
+.section sduib
+.section sduja
+.section sdujb
+.section sduka
+.section sdukb
+.section sdula
+.section sdulb
+.section sduma
+.section sdumb
+.section sduna
+.section sdunb
+.section sduoa
+.section sduob
+.section sdupa
+.section sdupb
+.section sduqa
+.section sduqb
+.section sdura
+.section sdurb
+.section sdusa
+.section sdusb
+.section sduta
+.section sdutb
+.section sduua
+.section sduub
+.section sduva
+.section sduvb
+.section sduwa
+.section sduwb
+.section sduxa
+.section sduxb
+.section sduya
+.section sduyb
+.section sduza
+.section sduzb
+.section sdu1a
+.section sdu1b
+.section sdu2a
+.section sdu2b
+.section sdu3a
+.section sdu3b
+.section sdu4a
+.section sdu4b
+.section sdu5a
+.section sdu5b
+.section sdu6a
+.section sdu6b
+.section sdu7a
+.section sdu7b
+.section sdu8a
+.section sdu8b
+.section sdu9a
+.section sdu9b
+.section sdu0a
+.section sdu0b
+.section sdvaa
+.section sdvab
+.section sdvba
+.section sdvbb
+.section sdvca
+.section sdvcb
+.section sdvda
+.section sdvdb
+.section sdvea
+.section sdveb
+.section sdvfa
+.section sdvfb
+.section sdvga
+.section sdvgb
+.section sdvha
+.section sdvhb
+.section sdvia
+.section sdvib
+.section sdvja
+.section sdvjb
+.section sdvka
+.section sdvkb
+.section sdvla
+.section sdvlb
+.section sdvma
+.section sdvmb
+.section sdvna
+.section sdvnb
+.section sdvoa
+.section sdvob
+.section sdvpa
+.section sdvpb
+.section sdvqa
+.section sdvqb
+.section sdvra
+.section sdvrb
+.section sdvsa
+.section sdvsb
+.section sdvta
+.section sdvtb
+.section sdvua
+.section sdvub
+.section sdvva
+.section sdvvb
+.section sdvwa
+.section sdvwb
+.section sdvxa
+.section sdvxb
+.section sdvya
+.section sdvyb
+.section sdvza
+.section sdvzb
+.section sdv1a
+.section sdv1b
+.section sdv2a
+.section sdv2b
+.section sdv3a
+.section sdv3b
+.section sdv4a
+.section sdv4b
+.section sdv5a
+.section sdv5b
+.section sdv6a
+.section sdv6b
+.section sdv7a
+.section sdv7b
+.section sdv8a
+.section sdv8b
+.section sdv9a
+.section sdv9b
+.section sdv0a
+.section sdv0b
+.section sdwaa
+.section sdwab
+.section sdwba
+.section sdwbb
+.section sdwca
+.section sdwcb
+.section sdwda
+.section sdwdb
+.section sdwea
+.section sdweb
+.section sdwfa
+.section sdwfb
+.section sdwga
+.section sdwgb
+.section sdwha
+.section sdwhb
+.section sdwia
+.section sdwib
+.section sdwja
+.section sdwjb
+.section sdwka
+.section sdwkb
+.section sdwla
+.section sdwlb
+.section sdwma
+.section sdwmb
+.section sdwna
+.section sdwnb
+.section sdwoa
+.section sdwob
+.section sdwpa
+.section sdwpb
+.section sdwqa
+.section sdwqb
+.section sdwra
+.section sdwrb
+.section sdwsa
+.section sdwsb
+.section sdwta
+.section sdwtb
+.section sdwua
+.section sdwub
+.section sdwva
+.section sdwvb
+.section sdwwa
+.section sdwwb
+.section sdwxa
+.section sdwxb
+.section sdwya
+.section sdwyb
+.section sdwza
+.section sdwzb
+.section sdw1a
+.section sdw1b
+.section sdw2a
+.section sdw2b
+.section sdw3a
+.section sdw3b
+.section sdw4a
+.section sdw4b
+.section sdw5a
+.section sdw5b
+.section sdw6a
+.section sdw6b
+.section sdw7a
+.section sdw7b
+.section sdw8a
+.section sdw8b
+.section sdw9a
+.section sdw9b
+.section sdw0a
+.section sdw0b
+.section sdxaa
+.section sdxab
+.section sdxba
+.section sdxbb
+.section sdxca
+.section sdxcb
+.section sdxda
+.section sdxdb
+.section sdxea
+.section sdxeb
+.section sdxfa
+.section sdxfb
+.section sdxga
+.section sdxgb
+.section sdxha
+.section sdxhb
+.section sdxia
+.section sdxib
+.section sdxja
+.section sdxjb
+.section sdxka
+.section sdxkb
+.section sdxla
+.section sdxlb
+.section sdxma
+.section sdxmb
+.section sdxna
+.section sdxnb
+.section sdxoa
+.section sdxob
+.section sdxpa
+.section sdxpb
+.section sdxqa
+.section sdxqb
+.section sdxra
+.section sdxrb
+.section sdxsa
+.section sdxsb
+.section sdxta
+.section sdxtb
+.section sdxua
+.section sdxub
+.section sdxva
+.section sdxvb
+.section sdxwa
+.section sdxwb
+.section sdxxa
+.section sdxxb
+.section sdxya
+.section sdxyb
+.section sdxza
+.section sdxzb
+.section sdx1a
+.section sdx1b
+.section sdx2a
+.section sdx2b
+.section sdx3a
+.section sdx3b
+.section sdx4a
+.section sdx4b
+.section sdx5a
+.section sdx5b
+.section sdx6a
+.section sdx6b
+.section sdx7a
+.section sdx7b
+.section sdx8a
+.section sdx8b
+.section sdx9a
+.section sdx9b
+.section sdx0a
+.section sdx0b
+.section sdyaa
+.section sdyab
+.section sdyba
+.section sdybb
+.section sdyca
+.section sdycb
+.section sdyda
+.section sdydb
+.section sdyea
+.section sdyeb
+.section sdyfa
+.section sdyfb
+.section sdyga
+.section sdygb
+.section sdyha
+.section sdyhb
+.section sdyia
+.section sdyib
+.section sdyja
+.section sdyjb
+.section sdyka
+.section sdykb
+.section sdyla
+.section sdylb
+.section sdyma
+.section sdymb
+.section sdyna
+.section sdynb
+.section sdyoa
+.section sdyob
+.section sdypa
+.section sdypb
+.section sdyqa
+.section sdyqb
+.section sdyra
+.section sdyrb
+.section sdysa
+.section sdysb
+.section sdyta
+.section sdytb
+.section sdyua
+.section sdyub
+.section sdyva
+.section sdyvb
+.section sdywa
+.section sdywb
+.section sdyxa
+.section sdyxb
+.section sdyya
+.section sdyyb
+.section sdyza
+.section sdyzb
+.section sdy1a
+.section sdy1b
+.section sdy2a
+.section sdy2b
+.section sdy3a
+.section sdy3b
+.section sdy4a
+.section sdy4b
+.section sdy5a
+.section sdy5b
+.section sdy6a
+.section sdy6b
+.section sdy7a
+.section sdy7b
+.section sdy8a
+.section sdy8b
+.section sdy9a
+.section sdy9b
+.section sdy0a
+.section sdy0b
+.section sdzaa
+.section sdzab
+.section sdzba
+.section sdzbb
+.section sdzca
+.section sdzcb
+.section sdzda
+.section sdzdb
+.section sdzea
+.section sdzeb
+.section sdzfa
+.section sdzfb
+.section sdzga
+.section sdzgb
+.section sdzha
+.section sdzhb
+.section sdzia
+.section sdzib
+.section sdzja
+.section sdzjb
+.section sdzka
+.section sdzkb
+.section sdzla
+.section sdzlb
+.section sdzma
+.section sdzmb
+.section sdzna
+.section sdznb
+.section sdzoa
+.section sdzob
+.section sdzpa
+.section sdzpb
+.section sdzqa
+.section sdzqb
+.section sdzra
+.section sdzrb
+.section sdzsa
+.section sdzsb
+.section sdzta
+.section sdztb
+.section sdzua
+.section sdzub
+.section sdzva
+.section sdzvb
+.section sdzwa
+.section sdzwb
+.section sdzxa
+.section sdzxb
+.section sdzya
+.section sdzyb
+.section sdzza
+.section sdzzb
+.section sdz1a
+.section sdz1b
+.section sdz2a
+.section sdz2b
+.section sdz3a
+.section sdz3b
+.section sdz4a
+.section sdz4b
+.section sdz5a
+.section sdz5b
+.section sdz6a
+.section sdz6b
+.section sdz7a
+.section sdz7b
+.section sdz8a
+.section sdz8b
+.section sdz9a
+.section sdz9b
+.section sdz0a
+.section sdz0b
+.section sd1aa
+.section sd1ab
+.section sd1ba
+.section sd1bb
+.section sd1ca
+.section sd1cb
+.section sd1da
+.section sd1db
+.section sd1ea
+.section sd1eb
+.section sd1fa
+.section sd1fb
+.section sd1ga
+.section sd1gb
+.section sd1ha
+.section sd1hb
+.section sd1ia
+.section sd1ib
+.section sd1ja
+.section sd1jb
+.section sd1ka
+.section sd1kb
+.section sd1la
+.section sd1lb
+.section sd1ma
+.section sd1mb
+.section sd1na
+.section sd1nb
+.section sd1oa
+.section sd1ob
+.section sd1pa
+.section sd1pb
+.section sd1qa
+.section sd1qb
+.section sd1ra
+.section sd1rb
+.section sd1sa
+.section sd1sb
+.section sd1ta
+.section sd1tb
+.section sd1ua
+.section sd1ub
+.section sd1va
+.section sd1vb
+.section sd1wa
+.section sd1wb
+.section sd1xa
+.section sd1xb
+.section sd1ya
+.section sd1yb
+.section sd1za
+.section sd1zb
+.section sd11a
+.section sd11b
+.section sd12a
+.section sd12b
+.section sd13a
+.section sd13b
+.section sd14a
+.section sd14b
+.section sd15a
+.section sd15b
+.section sd16a
+.section sd16b
+.section sd17a
+.section sd17b
+.section sd18a
+.section sd18b
+.section sd19a
+.section sd19b
+.section sd10a
+.section sd10b
+.section sd2aa
+.section sd2ab
+.section sd2ba
+.section sd2bb
+.section sd2ca
+.section sd2cb
+.section sd2da
+.section sd2db
+.section sd2ea
+.section sd2eb
+.section sd2fa
+.section sd2fb
+.section sd2ga
+.section sd2gb
+.section sd2ha
+.section sd2hb
+.section sd2ia
+.section sd2ib
+.section sd2ja
+.section sd2jb
+.section sd2ka
+.section sd2kb
+.section sd2la
+.section sd2lb
+.section sd2ma
+.section sd2mb
+.section sd2na
+.section sd2nb
+.section sd2oa
+.section sd2ob
+.section sd2pa
+.section sd2pb
+.section sd2qa
+.section sd2qb
+.section sd2ra
+.section sd2rb
+.section sd2sa
+.section sd2sb
+.section sd2ta
+.section sd2tb
+.section sd2ua
+.section sd2ub
+.section sd2va
+.section sd2vb
+.section sd2wa
+.section sd2wb
+.section sd2xa
+.section sd2xb
+.section sd2ya
+.section sd2yb
+.section sd2za
+.section sd2zb
+.section sd21a
+.section sd21b
+.section sd22a
+.section sd22b
+.section sd23a
+.section sd23b
+.section sd24a
+.section sd24b
+.section sd25a
+.section sd25b
+.section sd26a
+.section sd26b
+.section sd27a
+.section sd27b
+.section sd28a
+.section sd28b
+.section sd29a
+.section sd29b
+.section sd20a
+.section sd20b
+.section sd3aa
+.section sd3ab
+.section sd3ba
+.section sd3bb
+.section sd3ca
+.section sd3cb
+.section sd3da
+.section sd3db
+.section sd3ea
+.section sd3eb
+.section sd3fa
+.section sd3fb
+.section sd3ga
+.section sd3gb
+.section sd3ha
+.section sd3hb
+.section sd3ia
+.section sd3ib
+.section sd3ja
+.section sd3jb
+.section sd3ka
+.section sd3kb
+.section sd3la
+.section sd3lb
+.section sd3ma
+.section sd3mb
+.section sd3na
+.section sd3nb
+.section sd3oa
+.section sd3ob
+.section sd3pa
+.section sd3pb
+.section sd3qa
+.section sd3qb
+.section sd3ra
+.section sd3rb
+.section sd3sa
+.section sd3sb
+.section sd3ta
+.section sd3tb
+.section sd3ua
+.section sd3ub
+.section sd3va
+.section sd3vb
+.section sd3wa
+.section sd3wb
+.section sd3xa
+.section sd3xb
+.section sd3ya
+.section sd3yb
+.section sd3za
+.section sd3zb
+.section sd31a
+.section sd31b
+.section sd32a
+.section sd32b
+.section sd33a
+.section sd33b
+.section sd34a
+.section sd34b
+.section sd35a
+.section sd35b
+.section sd36a
+.section sd36b
+.section sd37a
+.section sd37b
+.section sd38a
+.section sd38b
+.section sd39a
+.section sd39b
+.section sd30a
+.section sd30b
+.section sd4aa
+.section sd4ab
+.section sd4ba
+.section sd4bb
+.section sd4ca
+.section sd4cb
+.section sd4da
+.section sd4db
+.section sd4ea
+.section sd4eb
+.section sd4fa
+.section sd4fb
+.section sd4ga
+.section sd4gb
+.section sd4ha
+.section sd4hb
+.section sd4ia
+.section sd4ib
+.section sd4ja
+.section sd4jb
+.section sd4ka
+.section sd4kb
+.section sd4la
+.section sd4lb
+.section sd4ma
+.section sd4mb
+.section sd4na
+.section sd4nb
+.section sd4oa
+.section sd4ob
+.section sd4pa
+.section sd4pb
+.section sd4qa
+.section sd4qb
+.section sd4ra
+.section sd4rb
+.section sd4sa
+.section sd4sb
+.section sd4ta
+.section sd4tb
+.section sd4ua
+.section sd4ub
+.section sd4va
+.section sd4vb
+.section sd4wa
+.section sd4wb
+.section sd4xa
+.section sd4xb
+.section sd4ya
+.section sd4yb
+.section sd4za
+.section sd4zb
+.section sd41a
+.section sd41b
+.section sd42a
+.section sd42b
+.section sd43a
+.section sd43b
+.section sd44a
+.section sd44b
+.section sd45a
+.section sd45b
+.section sd46a
+.section sd46b
+.section sd47a
+.section sd47b
+.section sd48a
+.section sd48b
+.section sd49a
+.section sd49b
+.section sd40a
+.section sd40b
+.section sd5aa
+.section sd5ab
+.section sd5ba
+.section sd5bb
+.section sd5ca
+.section sd5cb
+.section sd5da
+.section sd5db
+.section sd5ea
+.section sd5eb
+.section sd5fa
+.section sd5fb
+.section sd5ga
+.section sd5gb
+.section sd5ha
+.section sd5hb
+.section sd5ia
+.section sd5ib
+.section sd5ja
+.section sd5jb
+.section sd5ka
+.section sd5kb
+.section sd5la
+.section sd5lb
+.section sd5ma
+.section sd5mb
+.section sd5na
+.section sd5nb
+.section sd5oa
+.section sd5ob
+.section sd5pa
+.section sd5pb
+.section sd5qa
+.section sd5qb
+.section sd5ra
+.section sd5rb
+.section sd5sa
+.section sd5sb
+.section sd5ta
+.section sd5tb
+.section sd5ua
+.section sd5ub
+.section sd5va
+.section sd5vb
+.section sd5wa
+.section sd5wb
+.section sd5xa
+.section sd5xb
+.section sd5ya
+.section sd5yb
+.section sd5za
+.section sd5zb
+.section sd51a
+.section sd51b
+.section sd52a
+.section sd52b
+.section sd53a
+.section sd53b
+.section sd54a
+.section sd54b
+.section sd55a
+.section sd55b
+.section sd56a
+.section sd56b
+.section sd57a
+.section sd57b
+.section sd58a
+.section sd58b
+.section sd59a
+.section sd59b
+.section sd50a
+.section sd50b
+.section sd6aa
+.section sd6ab
+.section sd6ba
+.section sd6bb
+.section sd6ca
+.section sd6cb
+.section sd6da
+.section sd6db
+.section sd6ea
+.section sd6eb
+.section sd6fa
+.section sd6fb
+.section sd6ga
+.section sd6gb
+.section sd6ha
+.section sd6hb
+.section sd6ia
+.section sd6ib
+.section sd6ja
+.section sd6jb
+.section sd6ka
+.section sd6kb
+.section sd6la
+.section sd6lb
+.section sd6ma
+.section sd6mb
+.section sd6na
+.section sd6nb
+.section sd6oa
+.section sd6ob
+.section sd6pa
+.section sd6pb
+.section sd6qa
+.section sd6qb
+.section sd6ra
+.section sd6rb
+.section sd6sa
+.section sd6sb
+.section sd6ta
+.section sd6tb
+.section sd6ua
+.section sd6ub
+.section sd6va
+.section sd6vb
+.section sd6wa
+.section sd6wb
+.section sd6xa
+.section sd6xb
+.section sd6ya
+.section sd6yb
+.section sd6za
+.section sd6zb
+.section sd61a
+.section sd61b
+.section sd62a
+.section sd62b
+.section sd63a
+.section sd63b
+.section sd64a
+.section sd64b
+.section sd65a
+.section sd65b
+.section sd66a
+.section sd66b
+.section sd67a
+.section sd67b
+.section sd68a
+.section sd68b
+.section sd69a
+.section sd69b
+.section sd60a
+.section sd60b
+.section sd7aa
+.section sd7ab
+.section sd7ba
+.section sd7bb
+.section sd7ca
+.section sd7cb
+.section sd7da
+.section sd7db
+.section sd7ea
+.section sd7eb
+.section sd7fa
+.section sd7fb
+.section sd7ga
+.section sd7gb
+.section sd7ha
+.section sd7hb
+.section sd7ia
+.section sd7ib
+.section sd7ja
+.section sd7jb
+.section sd7ka
+.section sd7kb
+.section sd7la
+.section sd7lb
+.section sd7ma
+.section sd7mb
+.section sd7na
+.section sd7nb
+.section sd7oa
+.section sd7ob
+.section sd7pa
+.section sd7pb
+.section sd7qa
+.section sd7qb
+.section sd7ra
+.section sd7rb
+.section sd7sa
+.section sd7sb
+.section sd7ta
+.section sd7tb
+.section sd7ua
+.section sd7ub
+.section sd7va
+.section sd7vb
+.section sd7wa
+.section sd7wb
+.section sd7xa
+.section sd7xb
+.section sd7ya
+.section sd7yb
+.section sd7za
+.section sd7zb
+.section sd71a
+.section sd71b
+.section sd72a
+.section sd72b
+.section sd73a
+.section sd73b
+.section sd74a
+.section sd74b
+.section sd75a
+.section sd75b
+.section sd76a
+.section sd76b
+.section sd77a
+.section sd77b
+.section sd78a
+.section sd78b
+.section sd79a
+.section sd79b
+.section sd70a
+.section sd70b
+.section sd8aa
+.section sd8ab
+.section sd8ba
+.section sd8bb
+.section sd8ca
+.section sd8cb
+.section sd8da
+.section sd8db
+.section sd8ea
+.section sd8eb
+.section sd8fa
+.section sd8fb
+.section sd8ga
+.section sd8gb
+.section sd8ha
+.section sd8hb
+.section sd8ia
+.section sd8ib
+.section sd8ja
+.section sd8jb
+.section sd8ka
+.section sd8kb
+.section sd8la
+.section sd8lb
+.section sd8ma
+.section sd8mb
+.section sd8na
+.section sd8nb
+.section sd8oa
+.section sd8ob
+.section sd8pa
+.section sd8pb
+.section sd8qa
+.section sd8qb
+.section sd8ra
+.section sd8rb
+.section sd8sa
+.section sd8sb
+.section sd8ta
+.section sd8tb
+.section sd8ua
+.section sd8ub
+.section sd8va
+.section sd8vb
+.section sd8wa
+.section sd8wb
+.section sd8xa
+.section sd8xb
+.section sd8ya
+.section sd8yb
+.section sd8za
+.section sd8zb
+.section sd81a
+.section sd81b
+.section sd82a
+.section sd82b
+.section sd83a
+.section sd83b
+.section sd84a
+.section sd84b
+.section sd85a
+.section sd85b
+.section sd86a
+.section sd86b
+.section sd87a
+.section sd87b
+.section sd88a
+.section sd88b
+.section sd89a
+.section sd89b
+.section sd80a
+.section sd80b
+.section sd9aa
+.section sd9ab
+.section sd9ba
+.section sd9bb
+.section sd9ca
+.section sd9cb
+.section sd9da
+.section sd9db
+.section sd9ea
+.section sd9eb
+.section sd9fa
+.section sd9fb
+.section sd9ga
+.section sd9gb
+.section sd9ha
+.section sd9hb
+.section sd9ia
+.section sd9ib
+.section sd9ja
+.section sd9jb
+.section sd9ka
+.section sd9kb
+.section sd9la
+.section sd9lb
+.section sd9ma
+.section sd9mb
+.section sd9na
+.section sd9nb
+.section sd9oa
+.section sd9ob
+.section sd9pa
+.section sd9pb
+.section sd9qa
+.section sd9qb
+.section sd9ra
+.section sd9rb
+.section sd9sa
+.section sd9sb
+.section sd9ta
+.section sd9tb
+.section sd9ua
+.section sd9ub
+.section sd9va
+.section sd9vb
+.section sd9wa
+.section sd9wb
+.section sd9xa
+.section sd9xb
+.section sd9ya
+.section sd9yb
+.section sd9za
+.section sd9zb
+.section sd91a
+.section sd91b
+.section sd92a
+.section sd92b
+.section sd93a
+.section sd93b
+.section sd94a
+.section sd94b
+.section sd95a
+.section sd95b
+.section sd96a
+.section sd96b
+.section sd97a
+.section sd97b
+.section sd98a
+.section sd98b
+.section sd99a
+.section sd99b
+.section sd90a
+.section sd90b
+.section sd0aa
+.section sd0ab
+.section sd0ba
+.section sd0bb
+.section sd0ca
+.section sd0cb
+.section sd0da
+.section sd0db
+.section sd0ea
+.section sd0eb
+.section sd0fa
+.section sd0fb
+.section sd0ga
+.section sd0gb
+.section sd0ha
+.section sd0hb
+.section sd0ia
+.section sd0ib
+.section sd0ja
+.section sd0jb
+.section sd0ka
+.section sd0kb
+.section sd0la
+.section sd0lb
+.section sd0ma
+.section sd0mb
+.section sd0na
+.section sd0nb
+.section sd0oa
+.section sd0ob
+.section sd0pa
+.section sd0pb
+.section sd0qa
+.section sd0qb
+.section sd0ra
+.section sd0rb
+.section sd0sa
+.section sd0sb
+.section sd0ta
+.section sd0tb
+.section sd0ua
+.section sd0ub
+.section sd0va
+.section sd0vb
+.section sd0wa
+.section sd0wb
+.section sd0xa
+.section sd0xb
+.section sd0ya
+.section sd0yb
+.section sd0za
+.section sd0zb
+.section sd01a
+.section sd01b
+.section sd02a
+.section sd02b
+.section sd03a
+.section sd03b
+.section sd04a
+.section sd04b
+.section sd05a
+.section sd05b
+.section sd06a
+.section sd06b
+.section sd07a
+.section sd07b
+.section sd08a
+.section sd08b
+.section sd09a
+.section sd09b
+.section sd00a
+.section sd00b
+.section seaaa
+.section seaab
+.section seaba
+.section seabb
+.section seaca
+.section seacb
+.section seada
+.section seadb
+.section seaea
+.section seaeb
+.section seafa
+.section seafb
+.section seaga
+.section seagb
+.section seaha
+.section seahb
+.section seaia
+.section seaib
+.section seaja
+.section seajb
+.section seaka
+.section seakb
+.section seala
+.section sealb
+.section seama
+.section seamb
+.section seana
+.section seanb
+.section seaoa
+.section seaob
+.section seapa
+.section seapb
+.section seaqa
+.section seaqb
+.section seara
+.section searb
+.section seasa
+.section seasb
+.section seata
+.section seatb
+.section seaua
+.section seaub
+.section seava
+.section seavb
+.section seawa
+.section seawb
+.section seaxa
+.section seaxb
+.section seaya
+.section seayb
+.section seaza
+.section seazb
+.section sea1a
+.section sea1b
+.section sea2a
+.section sea2b
+.section sea3a
+.section sea3b
+.section sea4a
+.section sea4b
+.section sea5a
+.section sea5b
+.section sea6a
+.section sea6b
+.section sea7a
+.section sea7b
+.section sea8a
+.section sea8b
+.section sea9a
+.section sea9b
+.section sea0a
+.section sea0b
+.section sebaa
+.section sebab
+.section sebba
+.section sebbb
+.section sebca
+.section sebcb
+.section sebda
+.section sebdb
+.section sebea
+.section sebeb
+.section sebfa
+.section sebfb
+.section sebga
+.section sebgb
+.section sebha
+.section sebhb
+.section sebia
+.section sebib
+.section sebja
+.section sebjb
+.section sebka
+.section sebkb
+.section sebla
+.section seblb
+.section sebma
+.section sebmb
+.section sebna
+.section sebnb
+.section seboa
+.section sebob
+.section sebpa
+.section sebpb
+.section sebqa
+.section sebqb
+.section sebra
+.section sebrb
+.section sebsa
+.section sebsb
+.section sebta
+.section sebtb
+.section sebua
+.section sebub
+.section sebva
+.section sebvb
+.section sebwa
+.section sebwb
+.section sebxa
+.section sebxb
+.section sebya
+.section sebyb
+.section sebza
+.section sebzb
+.section seb1a
+.section seb1b
+.section seb2a
+.section seb2b
+.section seb3a
+.section seb3b
+.section seb4a
+.section seb4b
+.section seb5a
+.section seb5b
+.section seb6a
+.section seb6b
+.section seb7a
+.section seb7b
+.section seb8a
+.section seb8b
+.section seb9a
+.section seb9b
+.section seb0a
+.section seb0b
+.section secaa
+.section secab
+.section secba
+.section secbb
+.section secca
+.section seccb
+.section secda
+.section secdb
+.section secea
+.section seceb
+.section secfa
+.section secfb
+.section secga
+.section secgb
+.section secha
+.section sechb
+.section secia
+.section secib
+.section secja
+.section secjb
+.section secka
+.section seckb
+.section secla
+.section seclb
+.section secma
+.section secmb
+.section secna
+.section secnb
+.section secoa
+.section secob
+.section secpa
+.section secpb
+.section secqa
+.section secqb
+.section secra
+.section secrb
+.section secsa
+.section secsb
+.section secta
+.section sectb
+.section secua
+.section secub
+.section secva
+.section secvb
+.section secwa
+.section secwb
+.section secxa
+.section secxb
+.section secya
+.section secyb
+.section secza
+.section seczb
+.section sec1a
+.section sec1b
+.section sec2a
+.section sec2b
+.section sec3a
+.section sec3b
+.section sec4a
+.section sec4b
+.section sec5a
+.section sec5b
+.section sec6a
+.section sec6b
+.section sec7a
+.section sec7b
+.section sec8a
+.section sec8b
+.section sec9a
+.section sec9b
+.section sec0a
+.section sec0b
+.section sedaa
+.section sedab
+.section sedba
+.section sedbb
+.section sedca
+.section sedcb
+.section sedda
+.section seddb
+.section sedea
+.section sedeb
+.section sedfa
+.section sedfb
+.section sedga
+.section sedgb
+.section sedha
+.section sedhb
+.section sedia
+.section sedib
+.section sedja
+.section sedjb
+.section sedka
+.section sedkb
+.section sedla
+.section sedlb
+.section sedma
+.section sedmb
+.section sedna
+.section sednb
+.section sedoa
+.section sedob
+.section sedpa
+.section sedpb
+.section sedqa
+.section sedqb
+.section sedra
+.section sedrb
+.section sedsa
+.section sedsb
+.section sedta
+.section sedtb
+.section sedua
+.section sedub
+.section sedva
+.section sedvb
+.section sedwa
+.section sedwb
+.section sedxa
+.section sedxb
+.section sedya
+.section sedyb
+.section sedza
+.section sedzb
+.section sed1a
+.section sed1b
+.section sed2a
+.section sed2b
+.section sed3a
+.section sed3b
+.section sed4a
+.section sed4b
+.section sed5a
+.section sed5b
+.section sed6a
+.section sed6b
+.section sed7a
+.section sed7b
+.section sed8a
+.section sed8b
+.section sed9a
+.section sed9b
+.section sed0a
+.section sed0b
+.section seeaa
+.section seeab
+.section seeba
+.section seebb
+.section seeca
+.section seecb
+.section seeda
+.section seedb
+.section seeea
+.section seeeb
+.section seefa
+.section seefb
+.section seega
+.section seegb
+.section seeha
+.section seehb
+.section seeia
+.section seeib
+.section seeja
+.section seejb
+.section seeka
+.section seekb
+.section seela
+.section seelb
+.section seema
+.section seemb
+.section seena
+.section seenb
+.section seeoa
+.section seeob
+.section seepa
+.section seepb
+.section seeqa
+.section seeqb
+.section seera
+.section seerb
+.section seesa
+.section seesb
+.section seeta
+.section seetb
+.section seeua
+.section seeub
+.section seeva
+.section seevb
+.section seewa
+.section seewb
+.section seexa
+.section seexb
+.section seeya
+.section seeyb
+.section seeza
+.section seezb
+.section see1a
+.section see1b
+.section see2a
+.section see2b
+.section see3a
+.section see3b
+.section see4a
+.section see4b
+.section see5a
+.section see5b
+.section see6a
+.section see6b
+.section see7a
+.section see7b
+.section see8a
+.section see8b
+.section see9a
+.section see9b
+.section see0a
+.section see0b
+.section sefaa
+.section sefab
+.section sefba
+.section sefbb
+.section sefca
+.section sefcb
+.section sefda
+.section sefdb
+.section sefea
+.section sefeb
+.section seffa
+.section seffb
+.section sefga
+.section sefgb
+.section sefha
+.section sefhb
+.section sefia
+.section sefib
+.section sefja
+.section sefjb
+.section sefka
+.section sefkb
+.section sefla
+.section seflb
+.section sefma
+.section sefmb
+.section sefna
+.section sefnb
+.section sefoa
+.section sefob
+.section sefpa
+.section sefpb
+.section sefqa
+.section sefqb
+.section sefra
+.section sefrb
+.section sefsa
+.section sefsb
+.section sefta
+.section seftb
+.section sefua
+.section sefub
+.section sefva
+.section sefvb
+.section sefwa
+.section sefwb
+.section sefxa
+.section sefxb
+.section sefya
+.section sefyb
+.section sefza
+.section sefzb
+.section sef1a
+.section sef1b
+.section sef2a
+.section sef2b
+.section sef3a
+.section sef3b
+.section sef4a
+.section sef4b
+.section sef5a
+.section sef5b
+.section sef6a
+.section sef6b
+.section sef7a
+.section sef7b
+.section sef8a
+.section sef8b
+.section sef9a
+.section sef9b
+.section sef0a
+.section sef0b
+.section segaa
+.section segab
+.section segba
+.section segbb
+.section segca
+.section segcb
+.section segda
+.section segdb
+.section segea
+.section segeb
+.section segfa
+.section segfb
+.section segga
+.section seggb
+.section segha
+.section seghb
+.section segia
+.section segib
+.section segja
+.section segjb
+.section segka
+.section segkb
+.section segla
+.section seglb
+.section segma
+.section segmb
+.section segna
+.section segnb
+.section segoa
+.section segob
+.section segpa
+.section segpb
+.section segqa
+.section segqb
+.section segra
+.section segrb
+.section segsa
+.section segsb
+.section segta
+.section segtb
+.section segua
+.section segub
+.section segva
+.section segvb
+.section segwa
+.section segwb
+.section segxa
+.section segxb
+.section segya
+.section segyb
+.section segza
+.section segzb
+.section seg1a
+.section seg1b
+.section seg2a
+.section seg2b
+.section seg3a
+.section seg3b
+.section seg4a
+.section seg4b
+.section seg5a
+.section seg5b
+.section seg6a
+.section seg6b
+.section seg7a
+.section seg7b
+.section seg8a
+.section seg8b
+.section seg9a
+.section seg9b
+.section seg0a
+.section seg0b
+.section sehaa
+.section sehab
+.section sehba
+.section sehbb
+.section sehca
+.section sehcb
+.section sehda
+.section sehdb
+.section sehea
+.section seheb
+.section sehfa
+.section sehfb
+.section sehga
+.section sehgb
+.section sehha
+.section sehhb
+.section sehia
+.section sehib
+.section sehja
+.section sehjb
+.section sehka
+.section sehkb
+.section sehla
+.section sehlb
+.section sehma
+.section sehmb
+.section sehna
+.section sehnb
+.section sehoa
+.section sehob
+.section sehpa
+.section sehpb
+.section sehqa
+.section sehqb
+.section sehra
+.section sehrb
+.section sehsa
+.section sehsb
+.section sehta
+.section sehtb
+.section sehua
+.section sehub
+.section sehva
+.section sehvb
+.section sehwa
+.section sehwb
+.section sehxa
+.section sehxb
+.section sehya
+.section sehyb
+.section sehza
+.section sehzb
+.section seh1a
+.section seh1b
+.section seh2a
+.section seh2b
+.section seh3a
+.section seh3b
+.section seh4a
+.section seh4b
+.section seh5a
+.section seh5b
+.section seh6a
+.section seh6b
+.section seh7a
+.section seh7b
+.section seh8a
+.section seh8b
+.section seh9a
+.section seh9b
+.section seh0a
+.section seh0b
+.section seiaa
+.section seiab
+.section seiba
+.section seibb
+.section seica
+.section seicb
+.section seida
+.section seidb
+.section seiea
+.section seieb
+.section seifa
+.section seifb
+.section seiga
+.section seigb
+.section seiha
+.section seihb
+.section seiia
+.section seiib
+.section seija
+.section seijb
+.section seika
+.section seikb
+.section seila
+.section seilb
+.section seima
+.section seimb
+.section seina
+.section seinb
+.section seioa
+.section seiob
+.section seipa
+.section seipb
+.section seiqa
+.section seiqb
+.section seira
+.section seirb
+.section seisa
+.section seisb
+.section seita
+.section seitb
+.section seiua
+.section seiub
+.section seiva
+.section seivb
+.section seiwa
+.section seiwb
+.section seixa
+.section seixb
+.section seiya
+.section seiyb
+.section seiza
+.section seizb
+.section sei1a
+.section sei1b
+.section sei2a
+.section sei2b
+.section sei3a
+.section sei3b
+.section sei4a
+.section sei4b
+.section sei5a
+.section sei5b
+.section sei6a
+.section sei6b
+.section sei7a
+.section sei7b
+.section sei8a
+.section sei8b
+.section sei9a
+.section sei9b
+.section sei0a
+.section sei0b
+.section sejaa
+.section sejab
+.section sejba
+.section sejbb
+.section sejca
+.section sejcb
+.section sejda
+.section sejdb
+.section sejea
+.section sejeb
+.section sejfa
+.section sejfb
+.section sejga
+.section sejgb
+.section sejha
+.section sejhb
+.section sejia
+.section sejib
+.section sejja
+.section sejjb
+.section sejka
+.section sejkb
+.section sejla
+.section sejlb
+.section sejma
+.section sejmb
+.section sejna
+.section sejnb
+.section sejoa
+.section sejob
+.section sejpa
+.section sejpb
+.section sejqa
+.section sejqb
+.section sejra
+.section sejrb
+.section sejsa
+.section sejsb
+.section sejta
+.section sejtb
+.section sejua
+.section sejub
+.section sejva
+.section sejvb
+.section sejwa
+.section sejwb
+.section sejxa
+.section sejxb
+.section sejya
+.section sejyb
+.section sejza
+.section sejzb
+.section sej1a
+.section sej1b
+.section sej2a
+.section sej2b
+.section sej3a
+.section sej3b
+.section sej4a
+.section sej4b
+.section sej5a
+.section sej5b
+.section sej6a
+.section sej6b
+.section sej7a
+.section sej7b
+.section sej8a
+.section sej8b
+.section sej9a
+.section sej9b
+.section sej0a
+.section sej0b
+.section sekaa
+.section sekab
+.section sekba
+.section sekbb
+.section sekca
+.section sekcb
+.section sekda
+.section sekdb
+.section sekea
+.section sekeb
+.section sekfa
+.section sekfb
+.section sekga
+.section sekgb
+.section sekha
+.section sekhb
+.section sekia
+.section sekib
+.section sekja
+.section sekjb
+.section sekka
+.section sekkb
+.section sekla
+.section seklb
+.section sekma
+.section sekmb
+.section sekna
+.section seknb
+.section sekoa
+.section sekob
+.section sekpa
+.section sekpb
+.section sekqa
+.section sekqb
+.section sekra
+.section sekrb
+.section seksa
+.section seksb
+.section sekta
+.section sektb
+.section sekua
+.section sekub
+.section sekva
+.section sekvb
+.section sekwa
+.section sekwb
+.section sekxa
+.section sekxb
+.section sekya
+.section sekyb
+.section sekza
+.section sekzb
+.section sek1a
+.section sek1b
+.section sek2a
+.section sek2b
+.section sek3a
+.section sek3b
+.section sek4a
+.section sek4b
+.section sek5a
+.section sek5b
+.section sek6a
+.section sek6b
+.section sek7a
+.section sek7b
+.section sek8a
+.section sek8b
+.section sek9a
+.section sek9b
+.section sek0a
+.section sek0b
+.section selaa
+.section selab
+.section selba
+.section selbb
+.section selca
+.section selcb
+.section selda
+.section seldb
+.section selea
+.section seleb
+.section selfa
+.section selfb
+.section selga
+.section selgb
+.section selha
+.section selhb
+.section selia
+.section selib
+.section selja
+.section seljb
+.section selka
+.section selkb
+.section sella
+.section sellb
+.section selma
+.section selmb
+.section selna
+.section selnb
+.section seloa
+.section selob
+.section selpa
+.section selpb
+.section selqa
+.section selqb
+.section selra
+.section selrb
+.section selsa
+.section selsb
+.section selta
+.section seltb
+.section selua
+.section selub
+.section selva
+.section selvb
+.section selwa
+.section selwb
+.section selxa
+.section selxb
+.section selya
+.section selyb
+.section selza
+.section selzb
+.section sel1a
+.section sel1b
+.section sel2a
+.section sel2b
+.section sel3a
+.section sel3b
+.section sel4a
+.section sel4b
+.section sel5a
+.section sel5b
+.section sel6a
+.section sel6b
+.section sel7a
+.section sel7b
+.section sel8a
+.section sel8b
+.section sel9a
+.section sel9b
+.section sel0a
+.section sel0b
+.section semaa
+.section semab
+.section semba
+.section sembb
+.section semca
+.section semcb
+.section semda
+.section semdb
+.section semea
+.section semeb
+.section semfa
+.section semfb
+.section semga
+.section semgb
+.section semha
+.section semhb
+.section semia
+.section semib
+.section semja
+.section semjb
+.section semka
+.section semkb
+.section semla
+.section semlb
+.section semma
+.section semmb
+.section semna
+.section semnb
+.section semoa
+.section semob
+.section sempa
+.section sempb
+.section semqa
+.section semqb
+.section semra
+.section semrb
+.section semsa
+.section semsb
+.section semta
+.section semtb
+.section semua
+.section semub
+.section semva
+.section semvb
+.section semwa
+.section semwb
+.section semxa
+.section semxb
+.section semya
+.section semyb
+.section semza
+.section semzb
+.section sem1a
+.section sem1b
+.section sem2a
+.section sem2b
+.section sem3a
+.section sem3b
+.section sem4a
+.section sem4b
+.section sem5a
+.section sem5b
+.section sem6a
+.section sem6b
+.section sem7a
+.section sem7b
+.section sem8a
+.section sem8b
+.section sem9a
+.section sem9b
+.section sem0a
+.section sem0b
+.section senaa
+.section senab
+.section senba
+.section senbb
+.section senca
+.section sencb
+.section senda
+.section sendb
+.section senea
+.section seneb
+.section senfa
+.section senfb
+.section senga
+.section sengb
+.section senha
+.section senhb
+.section senia
+.section senib
+.section senja
+.section senjb
+.section senka
+.section senkb
+.section senla
+.section senlb
+.section senma
+.section senmb
+.section senna
+.section sennb
+.section senoa
+.section senob
+.section senpa
+.section senpb
+.section senqa
+.section senqb
+.section senra
+.section senrb
+.section sensa
+.section sensb
+.section senta
+.section sentb
+.section senua
+.section senub
+.section senva
+.section senvb
+.section senwa
+.section senwb
+.section senxa
+.section senxb
+.section senya
+.section senyb
+.section senza
+.section senzb
+.section sen1a
+.section sen1b
+.section sen2a
+.section sen2b
+.section sen3a
+.section sen3b
+.section sen4a
+.section sen4b
+.section sen5a
+.section sen5b
+.section sen6a
+.section sen6b
+.section sen7a
+.section sen7b
+.section sen8a
+.section sen8b
+.section sen9a
+.section sen9b
+.section sen0a
+.section sen0b
+.section seoaa
+.section seoab
+.section seoba
+.section seobb
+.section seoca
+.section seocb
+.section seoda
+.section seodb
+.section seoea
+.section seoeb
+.section seofa
+.section seofb
+.section seoga
+.section seogb
+.section seoha
+.section seohb
+.section seoia
+.section seoib
+.section seoja
+.section seojb
+.section seoka
+.section seokb
+.section seola
+.section seolb
+.section seoma
+.section seomb
+.section seona
+.section seonb
+.section seooa
+.section seoob
+.section seopa
+.section seopb
+.section seoqa
+.section seoqb
+.section seora
+.section seorb
+.section seosa
+.section seosb
+.section seota
+.section seotb
+.section seoua
+.section seoub
+.section seova
+.section seovb
+.section seowa
+.section seowb
+.section seoxa
+.section seoxb
+.section seoya
+.section seoyb
+.section seoza
+.section seozb
+.section seo1a
+.section seo1b
+.section seo2a
+.section seo2b
+.section seo3a
+.section seo3b
+.section seo4a
+.section seo4b
+.section seo5a
+.section seo5b
+.section seo6a
+.section seo6b
+.section seo7a
+.section seo7b
+.section seo8a
+.section seo8b
+.section seo9a
+.section seo9b
+.section seo0a
+.section seo0b
+.section sepaa
+.section sepab
+.section sepba
+.section sepbb
+.section sepca
+.section sepcb
+.section sepda
+.section sepdb
+.section sepea
+.section sepeb
+.section sepfa
+.section sepfb
+.section sepga
+.section sepgb
+.section sepha
+.section sephb
+.section sepia
+.section sepib
+.section sepja
+.section sepjb
+.section sepka
+.section sepkb
+.section sepla
+.section seplb
+.section sepma
+.section sepmb
+.section sepna
+.section sepnb
+.section sepoa
+.section sepob
+.section seppa
+.section seppb
+.section sepqa
+.section sepqb
+.section sepra
+.section seprb
+.section sepsa
+.section sepsb
+.section septa
+.section septb
+.section sepua
+.section sepub
+.section sepva
+.section sepvb
+.section sepwa
+.section sepwb
+.section sepxa
+.section sepxb
+.section sepya
+.section sepyb
+.section sepza
+.section sepzb
+.section sep1a
+.section sep1b
+.section sep2a
+.section sep2b
+.section sep3a
+.section sep3b
+.section sep4a
+.section sep4b
+.section sep5a
+.section sep5b
+.section sep6a
+.section sep6b
+.section sep7a
+.section sep7b
+.section sep8a
+.section sep8b
+.section sep9a
+.section sep9b
+.section sep0a
+.section sep0b
+.section seqaa
+.section seqab
+.section seqba
+.section seqbb
+.section seqca
+.section seqcb
+.section seqda
+.section seqdb
+.section seqea
+.section seqeb
+.section seqfa
+.section seqfb
+.section seqga
+.section seqgb
+.section seqha
+.section seqhb
+.section seqia
+.section seqib
+.section seqja
+.section seqjb
+.section seqka
+.section seqkb
+.section seqla
+.section seqlb
+.section seqma
+.section seqmb
+.section seqna
+.section seqnb
+.section seqoa
+.section seqob
+.section seqpa
+.section seqpb
+.section seqqa
+.section seqqb
+.section seqra
+.section seqrb
+.section seqsa
+.section seqsb
+.section seqta
+.section seqtb
+.section sequa
+.section sequb
+.section seqva
+.section seqvb
+.section seqwa
+.section seqwb
+.section seqxa
+.section seqxb
+.section seqya
+.section seqyb
+.section seqza
+.section seqzb
+.section seq1a
+.section seq1b
+.section seq2a
+.section seq2b
+.section seq3a
+.section seq3b
+.section seq4a
+.section seq4b
+.section seq5a
+.section seq5b
+.section seq6a
+.section seq6b
+.section seq7a
+.section seq7b
+.section seq8a
+.section seq8b
+.section seq9a
+.section seq9b
+.section seq0a
+.section seq0b
+.section seraa
+.section serab
+.section serba
+.section serbb
+.section serca
+.section sercb
+.section serda
+.section serdb
+.section serea
+.section sereb
+.section serfa
+.section serfb
+.section serga
+.section sergb
+.section serha
+.section serhb
+.section seria
+.section serib
+.section serja
+.section serjb
+.section serka
+.section serkb
+.section serla
+.section serlb
+.section serma
+.section sermb
+.section serna
+.section sernb
+.section seroa
+.section serob
+.section serpa
+.section serpb
+.section serqa
+.section serqb
+.section serra
+.section serrb
+.section sersa
+.section sersb
+.section serta
+.section sertb
+.section serua
+.section serub
+.section serva
+.section servb
+.section serwa
+.section serwb
+.section serxa
+.section serxb
+.section serya
+.section seryb
+.section serza
+.section serzb
+.section ser1a
+.section ser1b
+.section ser2a
+.section ser2b
+.section ser3a
+.section ser3b
+.section ser4a
+.section ser4b
+.section ser5a
+.section ser5b
+.section ser6a
+.section ser6b
+.section ser7a
+.section ser7b
+.section ser8a
+.section ser8b
+.section ser9a
+.section ser9b
+.section ser0a
+.section ser0b
+.section sesaa
+.section sesab
+.section sesba
+.section sesbb
+.section sesca
+.section sescb
+.section sesda
+.section sesdb
+.section sesea
+.section seseb
+.section sesfa
+.section sesfb
+.section sesga
+.section sesgb
+.section sesha
+.section seshb
+.section sesia
+.section sesib
+.section sesja
+.section sesjb
+.section seska
+.section seskb
+.section sesla
+.section seslb
+.section sesma
+.section sesmb
+.section sesna
+.section sesnb
+.section sesoa
+.section sesob
+.section sespa
+.section sespb
+.section sesqa
+.section sesqb
+.section sesra
+.section sesrb
+.section sessa
+.section sessb
+.section sesta
+.section sestb
+.section sesua
+.section sesub
+.section sesva
+.section sesvb
+.section seswa
+.section seswb
+.section sesxa
+.section sesxb
+.section sesya
+.section sesyb
+.section sesza
+.section seszb
+.section ses1a
+.section ses1b
+.section ses2a
+.section ses2b
+.section ses3a
+.section ses3b
+.section ses4a
+.section ses4b
+.section ses5a
+.section ses5b
+.section ses6a
+.section ses6b
+.section ses7a
+.section ses7b
+.section ses8a
+.section ses8b
+.section ses9a
+.section ses9b
+.section ses0a
+.section ses0b
+.section setaa
+.section setab
+.section setba
+.section setbb
+.section setca
+.section setcb
+.section setda
+.section setdb
+.section setea
+.section seteb
+.section setfa
+.section setfb
+.section setga
+.section setgb
+.section setha
+.section sethb
+.section setia
+.section setib
+.section setja
+.section setjb
+.section setka
+.section setkb
+.section setla
+.section setlb
+.section setma
+.section setmb
+.section setna
+.section setnb
+.section setoa
+.section setob
+.section setpa
+.section setpb
+.section setqa
+.section setqb
+.section setra
+.section setrb
+.section setsa
+.section setsb
+.section setta
+.section settb
+.section setua
+.section setub
+.section setva
+.section setvb
+.section setwa
+.section setwb
+.section setxa
+.section setxb
+.section setya
+.section setyb
+.section setza
+.section setzb
+.section set1a
+.section set1b
+.section set2a
+.section set2b
+.section set3a
+.section set3b
+.section set4a
+.section set4b
+.section set5a
+.section set5b
+.section set6a
+.section set6b
+.section set7a
+.section set7b
+.section set8a
+.section set8b
+.section set9a
+.section set9b
+.section set0a
+.section set0b
+.section seuaa
+.section seuab
+.section seuba
+.section seubb
+.section seuca
+.section seucb
+.section seuda
+.section seudb
+.section seuea
+.section seueb
+.section seufa
+.section seufb
+.section seuga
+.section seugb
+.section seuha
+.section seuhb
+.section seuia
+.section seuib
+.section seuja
+.section seujb
+.section seuka
+.section seukb
+.section seula
+.section seulb
+.section seuma
+.section seumb
+.section seuna
+.section seunb
+.section seuoa
+.section seuob
+.section seupa
+.section seupb
+.section seuqa
+.section seuqb
+.section seura
+.section seurb
+.section seusa
+.section seusb
+.section seuta
+.section seutb
+.section seuua
+.section seuub
+.section seuva
+.section seuvb
+.section seuwa
+.section seuwb
+.section seuxa
+.section seuxb
+.section seuya
+.section seuyb
+.section seuza
+.section seuzb
+.section seu1a
+.section seu1b
+.section seu2a
+.section seu2b
+.section seu3a
+.section seu3b
+.section seu4a
+.section seu4b
+.section seu5a
+.section seu5b
+.section seu6a
+.section seu6b
+.section seu7a
+.section seu7b
+.section seu8a
+.section seu8b
+.section seu9a
+.section seu9b
+.section seu0a
+.section seu0b
+.section sevaa
+.section sevab
+.section sevba
+.section sevbb
+.section sevca
+.section sevcb
+.section sevda
+.section sevdb
+.section sevea
+.section seveb
+.section sevfa
+.section sevfb
+.section sevga
+.section sevgb
+.section sevha
+.section sevhb
+.section sevia
+.section sevib
+.section sevja
+.section sevjb
+.section sevka
+.section sevkb
+.section sevla
+.section sevlb
+.section sevma
+.section sevmb
+.section sevna
+.section sevnb
+.section sevoa
+.section sevob
+.section sevpa
+.section sevpb
+.section sevqa
+.section sevqb
+.section sevra
+.section sevrb
+.section sevsa
+.section sevsb
+.section sevta
+.section sevtb
+.section sevua
+.section sevub
+.section sevva
+.section sevvb
+.section sevwa
+.section sevwb
+.section sevxa
+.section sevxb
+.section sevya
+.section sevyb
+.section sevza
+.section sevzb
+.section sev1a
+.section sev1b
+.section sev2a
+.section sev2b
+.section sev3a
+.section sev3b
+.section sev4a
+.section sev4b
+.section sev5a
+.section sev5b
+.section sev6a
+.section sev6b
+.section sev7a
+.section sev7b
+.section sev8a
+.section sev8b
+.section sev9a
+.section sev9b
+.section sev0a
+.section sev0b
+.section sewaa
+.section sewab
+.section sewba
+.section sewbb
+.section sewca
+.section sewcb
+.section sewda
+.section sewdb
+.section sewea
+.section seweb
+.section sewfa
+.section sewfb
+.section sewga
+.section sewgb
+.section sewha
+.section sewhb
+.section sewia
+.section sewib
+.section sewja
+.section sewjb
+.section sewka
+.section sewkb
+.section sewla
+.section sewlb
+.section sewma
+.section sewmb
+.section sewna
+.section sewnb
+.section sewoa
+.section sewob
+.section sewpa
+.section sewpb
+.section sewqa
+.section sewqb
+.section sewra
+.section sewrb
+.section sewsa
+.section sewsb
+.section sewta
+.section sewtb
+.section sewua
+.section sewub
+.section sewva
+.section sewvb
+.section sewwa
+.section sewwb
+.section sewxa
+.section sewxb
+.section sewya
+.section sewyb
+.section sewza
+.section sewzb
+.section sew1a
+.section sew1b
+.section sew2a
+.section sew2b
+.section sew3a
+.section sew3b
+.section sew4a
+.section sew4b
+.section sew5a
+.section sew5b
+.section sew6a
+.section sew6b
+.section sew7a
+.section sew7b
+.section sew8a
+.section sew8b
+.section sew9a
+.section sew9b
+.section sew0a
+.section sew0b
+.section sexaa
+.section sexab
+.section sexba
+.section sexbb
+.section sexca
+.section sexcb
+.section sexda
+.section sexdb
+.section sexea
+.section sexeb
+.section sexfa
+.section sexfb
+.section sexga
+.section sexgb
+.section sexha
+.section sexhb
+.section sexia
+.section sexib
+.section sexja
+.section sexjb
+.section sexka
+.section sexkb
+.section sexla
+.section sexlb
+.section sexma
+.section sexmb
+.section sexna
+.section sexnb
+.section sexoa
+.section sexob
+.section sexpa
+.section sexpb
+.section sexqa
+.section sexqb
+.section sexra
+.section sexrb
+.section sexsa
+.section sexsb
+.section sexta
+.section sextb
+.section sexua
+.section sexub
+.section sexva
+.section sexvb
+.section sexwa
+.section sexwb
+.section sexxa
+.section sexxb
+.section sexya
+.section sexyb
+.section sexza
+.section sexzb
+.section sex1a
+.section sex1b
+.section sex2a
+.section sex2b
+.section sex3a
+.section sex3b
+.section sex4a
+.section sex4b
+.section sex5a
+.section sex5b
+.section sex6a
+.section sex6b
+.section sex7a
+.section sex7b
+.section sex8a
+.section sex8b
+.section sex9a
+.section sex9b
+.section sex0a
+.section sex0b
+.section seyaa
+.section seyab
+.section seyba
+.section seybb
+.section seyca
+.section seycb
+.section seyda
+.section seydb
+.section seyea
+.section seyeb
+.section seyfa
+.section seyfb
+.section seyga
+.section seygb
+.section seyha
+.section seyhb
+.section seyia
+.section seyib
+.section seyja
+.section seyjb
+.section seyka
+.section seykb
+.section seyla
+.section seylb
+.section seyma
+.section seymb
+.section seyna
+.section seynb
+.section seyoa
+.section seyob
+.section seypa
+.section seypb
+.section seyqa
+.section seyqb
+.section seyra
+.section seyrb
+.section seysa
+.section seysb
+.section seyta
+.section seytb
+.section seyua
+.section seyub
+.section seyva
+.section seyvb
+.section seywa
+.section seywb
+.section seyxa
+.section seyxb
+.section seyya
+.section seyyb
+.section seyza
+.section seyzb
+.section sey1a
+.section sey1b
+.section sey2a
+.section sey2b
+.section sey3a
+.section sey3b
+.section sey4a
+.section sey4b
+.section sey5a
+.section sey5b
+.section sey6a
+.section sey6b
+.section sey7a
+.section sey7b
+.section sey8a
+.section sey8b
+.section sey9a
+.section sey9b
+.section sey0a
+.section sey0b
+.section sezaa
+.section sezab
+.section sezba
+.section sezbb
+.section sezca
+.section sezcb
+.section sezda
+.section sezdb
+.section sezea
+.section sezeb
+.section sezfa
+.section sezfb
+.section sezga
+.section sezgb
+.section sezha
+.section sezhb
+.section sezia
+.section sezib
+.section sezja
+.section sezjb
+.section sezka
+.section sezkb
+.section sezla
+.section sezlb
+.section sezma
+.section sezmb
+.section sezna
+.section seznb
+.section sezoa
+.section sezob
+.section sezpa
+.section sezpb
+.section sezqa
+.section sezqb
+.section sezra
+.section sezrb
+.section sezsa
+.section sezsb
+.section sezta
+.section seztb
+.section sezua
+.section sezub
+.section sezva
+.section sezvb
+.section sezwa
+.section sezwb
+.section sezxa
+.section sezxb
+.section sezya
+.section sezyb
+.section sezza
+.section sezzb
+.section sez1a
+.section sez1b
+.section sez2a
+.section sez2b
+.section sez3a
+.section sez3b
+.section sez4a
+.section sez4b
+.section sez5a
+.section sez5b
+.section sez6a
+.section sez6b
+.section sez7a
+.section sez7b
+.section sez8a
+.section sez8b
+.section sez9a
+.section sez9b
+.section sez0a
+.section sez0b
+.section se1aa
+.section se1ab
+.section se1ba
+.section se1bb
+.section se1ca
+.section se1cb
+.section se1da
+.section se1db
+.section se1ea
+.section se1eb
+.section se1fa
+.section se1fb
+.section se1ga
+.section se1gb
+.section se1ha
+.section se1hb
+.section se1ia
+.section se1ib
+.section se1ja
+.section se1jb
+.section se1ka
+.section se1kb
+.section se1la
+.section se1lb
+.section se1ma
+.section se1mb
+.section se1na
+.section se1nb
+.section se1oa
+.section se1ob
+.section se1pa
+.section se1pb
+.section se1qa
+.section se1qb
+.section se1ra
+.section se1rb
+.section se1sa
+.section se1sb
+.section se1ta
+.section se1tb
+.section se1ua
+.section se1ub
+.section se1va
+.section se1vb
+.section se1wa
+.section se1wb
+.section se1xa
+.section se1xb
+.section se1ya
+.section se1yb
+.section se1za
+.section se1zb
+.section se11a
+.section se11b
+.section se12a
+.section se12b
+.section se13a
+.section se13b
+.section se14a
+.section se14b
+.section se15a
+.section se15b
+.section se16a
+.section se16b
+.section se17a
+.section se17b
+.section se18a
+.section se18b
+.section se19a
+.section se19b
+.section se10a
+.section se10b
+.section se2aa
+.section se2ab
+.section se2ba
+.section se2bb
+.section se2ca
+.section se2cb
+.section se2da
+.section se2db
+.section se2ea
+.section se2eb
+.section se2fa
+.section se2fb
+.section se2ga
+.section se2gb
+.section se2ha
+.section se2hb
+.section se2ia
+.section se2ib
+.section se2ja
+.section se2jb
+.section se2ka
+.section se2kb
+.section se2la
+.section se2lb
+.section se2ma
+.section se2mb
+.section se2na
+.section se2nb
+.section se2oa
+.section se2ob
+.section se2pa
+.section se2pb
+.section se2qa
+.section se2qb
+.section se2ra
+.section se2rb
+.section se2sa
+.section se2sb
+.section se2ta
+.section se2tb
+.section se2ua
+.section se2ub
+.section se2va
+.section se2vb
+.section se2wa
+.section se2wb
+.section se2xa
+.section se2xb
+.section se2ya
+.section se2yb
+.section se2za
+.section se2zb
+.section se21a
+.section se21b
+.section se22a
+.section se22b
+.section se23a
+.section se23b
+.section se24a
+.section se24b
+.section se25a
+.section se25b
+.section se26a
+.section se26b
+.section se27a
+.section se27b
+.section se28a
+.section se28b
+.section se29a
+.section se29b
+.section se20a
+.section se20b
+.section se3aa
+.section se3ab
+.section se3ba
+.section se3bb
+.section se3ca
+.section se3cb
+.section se3da
+.section se3db
+.section se3ea
+.section se3eb
+.section se3fa
+.section se3fb
+.section se3ga
+.section se3gb
+.section se3ha
+.section se3hb
+.section se3ia
+.section se3ib
+.section se3ja
+.section se3jb
+.section se3ka
+.section se3kb
+.section se3la
+.section se3lb
+.section se3ma
+.section se3mb
+.section se3na
+.section se3nb
+.section se3oa
+.section se3ob
+.section se3pa
+.section se3pb
+.section se3qa
+.section se3qb
+.section se3ra
+.section se3rb
+.section se3sa
+.section se3sb
+.section se3ta
+.section se3tb
+.section se3ua
+.section se3ub
+.section se3va
+.section se3vb
+.section se3wa
+.section se3wb
+.section se3xa
+.section se3xb
+.section se3ya
+.section se3yb
+.section se3za
+.section se3zb
+.section se31a
+.section se31b
+.section se32a
+.section se32b
+.section se33a
+.section se33b
+.section se34a
+.section se34b
+.section se35a
+.section se35b
+.section se36a
+.section se36b
+.section se37a
+.section se37b
+.section se38a
+.section se38b
+.section se39a
+.section se39b
+.section se30a
+.section se30b
+.section se4aa
+.section se4ab
+.section se4ba
+.section se4bb
+.section se4ca
+.section se4cb
+.section se4da
+.section se4db
+.section se4ea
+.section se4eb
+.section se4fa
+.section se4fb
+.section se4ga
+.section se4gb
+.section se4ha
+.section se4hb
+.section se4ia
+.section se4ib
+.section se4ja
+.section se4jb
+.section se4ka
+.section se4kb
+.section se4la
+.section se4lb
+.section se4ma
+.section se4mb
+.section se4na
+.section se4nb
+.section se4oa
+.section se4ob
+.section se4pa
+.section se4pb
+.section se4qa
+.section se4qb
+.section se4ra
+.section se4rb
+.section se4sa
+.section se4sb
+.section se4ta
+.section se4tb
+.section se4ua
+.section se4ub
+.section se4va
+.section se4vb
+.section se4wa
+.section se4wb
+.section se4xa
+.section se4xb
+.section se4ya
+.section se4yb
+.section se4za
+.section se4zb
+.section se41a
+.section se41b
+.section se42a
+.section se42b
+.section se43a
+.section se43b
+.section se44a
+.section se44b
+.section se45a
+.section se45b
+.section se46a
+.section se46b
+.section se47a
+.section se47b
+.section se48a
+.section se48b
+.section se49a
+.section se49b
+.section se40a
+.section se40b
+.section se5aa
+.section se5ab
+.section se5ba
+.section se5bb
+.section se5ca
+.section se5cb
+.section se5da
+.section se5db
+.section se5ea
+.section se5eb
+.section se5fa
+.section se5fb
+.section se5ga
+.section se5gb
+.section se5ha
+.section se5hb
+.section se5ia
+.section se5ib
+.section se5ja
+.section se5jb
+.section se5ka
+.section se5kb
+.section se5la
+.section se5lb
+.section se5ma
+.section se5mb
+.section se5na
+.section se5nb
+.section se5oa
+.section se5ob
+.section se5pa
+.section se5pb
+.section se5qa
+.section se5qb
+.section se5ra
+.section se5rb
+.section se5sa
+.section se5sb
+.section se5ta
+.section se5tb
+.section se5ua
+.section se5ub
+.section se5va
+.section se5vb
+.section se5wa
+.section se5wb
+.section se5xa
+.section se5xb
+.section se5ya
+.section se5yb
+.section se5za
+.section se5zb
+.section se51a
+.section se51b
+.section se52a
+.section se52b
+.section se53a
+.section se53b
+.section se54a
+.section se54b
+.section se55a
+.section se55b
+.section se56a
+.section se56b
+.section se57a
+.section se57b
+.section se58a
+.section se58b
+.section se59a
+.section se59b
+.section se50a
+.section se50b
+.section se6aa
+.section se6ab
+.section se6ba
+.section se6bb
+.section se6ca
+.section se6cb
+.section se6da
+.section se6db
+.section se6ea
+.section se6eb
+.section se6fa
+.section se6fb
+.section se6ga
+.section se6gb
+.section se6ha
+.section se6hb
+.section se6ia
+.section se6ib
+.section se6ja
+.section se6jb
+.section se6ka
+.section se6kb
+.section se6la
+.section se6lb
+.section se6ma
+.section se6mb
+.section se6na
+.section se6nb
+.section se6oa
+.section se6ob
+.section se6pa
+.section se6pb
+.section se6qa
+.section se6qb
+.section se6ra
+.section se6rb
+.section se6sa
+.section se6sb
+.section se6ta
+.section se6tb
+.section se6ua
+.section se6ub
+.section se6va
+.section se6vb
+.section se6wa
+.section se6wb
+.section se6xa
+.section se6xb
+.section se6ya
+.section se6yb
+.section se6za
+.section se6zb
+.section se61a
+.section se61b
+.section se62a
+.section se62b
+.section se63a
+.section se63b
+.section se64a
+.section se64b
+.section se65a
+.section se65b
+.section se66a
+.section se66b
+.section se67a
+.section se67b
+.section se68a
+.section se68b
+.section se69a
+.section se69b
+.section se60a
+.section se60b
+.section se7aa
+.section se7ab
+.section se7ba
+.section se7bb
+.section se7ca
+.section se7cb
+.section se7da
+.section se7db
+.section se7ea
+.section se7eb
+.section se7fa
+.section se7fb
+.section se7ga
+.section se7gb
+.section se7ha
+.section se7hb
+.section se7ia
+.section se7ib
+.section se7ja
+.section se7jb
+.section se7ka
+.section se7kb
+.section se7la
+.section se7lb
+.section se7ma
+.section se7mb
+.section se7na
+.section se7nb
+.section se7oa
+.section se7ob
+.section se7pa
+.section se7pb
+.section se7qa
+.section se7qb
+.section se7ra
+.section se7rb
+.section se7sa
+.section se7sb
+.section se7ta
+.section se7tb
+.section se7ua
+.section se7ub
+.section se7va
+.section se7vb
+.section se7wa
+.section se7wb
+.section se7xa
+.section se7xb
+.section se7ya
+.section se7yb
+.section se7za
+.section se7zb
+.section se71a
+.section se71b
+.section se72a
+.section se72b
+.section se73a
+.section se73b
+.section se74a
+.section se74b
+.section se75a
+.section se75b
+.section se76a
+.section se76b
+.section se77a
+.section se77b
+.section se78a
+.section se78b
+.section se79a
+.section se79b
+.section se70a
+.section se70b
+.section se8aa
+.section se8ab
+.section se8ba
+.section se8bb
+.section se8ca
+.section se8cb
+.section se8da
+.section se8db
+.section se8ea
+.section se8eb
+.section se8fa
+.section se8fb
+.section se8ga
+.section se8gb
+.section se8ha
+.section se8hb
+.section se8ia
+.section se8ib
+.section se8ja
+.section se8jb
+.section se8ka
+.section se8kb
+.section se8la
+.section se8lb
+.section se8ma
+.section se8mb
+.section se8na
+.section se8nb
+.section se8oa
+.section se8ob
+.section se8pa
+.section se8pb
+.section se8qa
+.section se8qb
+.section se8ra
+.section se8rb
+.section se8sa
+.section se8sb
+.section se8ta
+.section se8tb
+.section se8ua
+.section se8ub
+.section se8va
+.section se8vb
+.section se8wa
+.section se8wb
+.section se8xa
+.section se8xb
+.section se8ya
+.section se8yb
+.section se8za
+.section se8zb
+.section se81a
+.section se81b
+.section se82a
+.section se82b
+.section se83a
+.section se83b
+.section se84a
+.section se84b
+.section se85a
+.section se85b
+.section se86a
+.section se86b
+.section se87a
+.section se87b
+.section se88a
+.section se88b
+.section se89a
+.section se89b
+.section se80a
+.section se80b
+.section se9aa
+.section se9ab
+.section se9ba
+.section se9bb
+.section se9ca
+.section se9cb
+.section se9da
+.section se9db
+.section se9ea
+.section se9eb
+.section se9fa
+.section se9fb
+.section se9ga
+.section se9gb
+.section se9ha
+.section se9hb
+.section se9ia
+.section se9ib
+.section se9ja
+.section se9jb
+.section se9ka
+.section se9kb
+.section se9la
+.section se9lb
+.section se9ma
+.section se9mb
+.section se9na
+.section se9nb
+.section se9oa
+.section se9ob
+.section se9pa
+.section se9pb
+.section se9qa
+.section se9qb
+.section se9ra
+.section se9rb
+.section se9sa
+.section se9sb
+.section se9ta
+.section se9tb
+.section se9ua
+.section se9ub
+.section se9va
+.section se9vb
+.section se9wa
+.section se9wb
+.section se9xa
+.section se9xb
+.section se9ya
+.section se9yb
+.section se9za
+.section se9zb
+.section se91a
+.section se91b
+.section se92a
+.section se92b
+.section se93a
+.section se93b
+.section se94a
+.section se94b
+.section se95a
+.section se95b
+.section se96a
+.section se96b
+.section se97a
+.section se97b
+.section se98a
+.section se98b
+.section se99a
+.section se99b
+.section se90a
+.section se90b
+.section se0aa
+.section se0ab
+.section se0ba
+.section se0bb
+.section se0ca
+.section se0cb
+.section se0da
+.section se0db
+.section se0ea
+.section se0eb
+.section se0fa
+.section se0fb
+.section se0ga
+.section se0gb
+.section se0ha
+.section se0hb
+.section se0ia
+.section se0ib
+.section se0ja
+.section se0jb
+.section se0ka
+.section se0kb
+.section se0la
+.section se0lb
+.section se0ma
+.section se0mb
+.section se0na
+.section se0nb
+.section se0oa
+.section se0ob
+.section se0pa
+.section se0pb
+.section se0qa
+.section se0qb
+.section se0ra
+.section se0rb
+.section se0sa
+.section se0sb
+.section se0ta
+.section se0tb
+.section se0ua
+.section se0ub
+.section se0va
+.section se0vb
+.section se0wa
+.section se0wb
+.section se0xa
+.section se0xb
+.section se0ya
+.section se0yb
+.section se0za
+.section se0zb
+.section se01a
+.section se01b
+.section se02a
+.section se02b
+.section se03a
+.section se03b
+.section se04a
+.section se04b
+.section se05a
+.section se05b
+.section se06a
+.section se06b
+.section se07a
+.section se07b
+.section se08a
+.section se08b
+.section se09a
+.section se09b
+.section se00a
+.section se00b
+.section sfaaa
+.section sfaab
+.section sfaba
+.section sfabb
+.section sfaca
+.section sfacb
+.section sfada
+.section sfadb
+.section sfaea
+.section sfaeb
+.section sfafa
+.section sfafb
+.section sfaga
+.section sfagb
+.section sfaha
+.section sfahb
+.section sfaia
+.section sfaib
+.section sfaja
+.section sfajb
+.section sfaka
+.section sfakb
+.section sfala
+.section sfalb
+.section sfama
+.section sfamb
+.section sfana
+.section sfanb
+.section sfaoa
+.section sfaob
+.section sfapa
+.section sfapb
+.section sfaqa
+.section sfaqb
+.section sfara
+.section sfarb
+.section sfasa
+.section sfasb
+.section sfata
+.section sfatb
+.section sfaua
+.section sfaub
+.section sfava
+.section sfavb
+.section sfawa
+.section sfawb
+.section sfaxa
+.section sfaxb
+.section sfaya
+.section sfayb
+.section sfaza
+.section sfazb
+.section sfa1a
+.section sfa1b
+.section sfa2a
+.section sfa2b
+.section sfa3a
+.section sfa3b
+.section sfa4a
+.section sfa4b
+.section sfa5a
+.section sfa5b
+.section sfa6a
+.section sfa6b
+.section sfa7a
+.section sfa7b
+.section sfa8a
+.section sfa8b
+.section sfa9a
+.section sfa9b
+.section sfa0a
+.section sfa0b
+.section sfbaa
+.section sfbab
+.section sfbba
+.section sfbbb
+.section sfbca
+.section sfbcb
+.section sfbda
+.section sfbdb
+.section sfbea
+.section sfbeb
+.section sfbfa
+.section sfbfb
+.section sfbga
+.section sfbgb
+.section sfbha
+.section sfbhb
+.section sfbia
+.section sfbib
+.section sfbja
+.section sfbjb
+.section sfbka
+.section sfbkb
+.section sfbla
+.section sfblb
+.section sfbma
+.section sfbmb
+.section sfbna
+.section sfbnb
+.section sfboa
+.section sfbob
+.section sfbpa
+.section sfbpb
+.section sfbqa
+.section sfbqb
+.section sfbra
+.section sfbrb
+.section sfbsa
+.section sfbsb
+.section sfbta
+.section sfbtb
+.section sfbua
+.section sfbub
+.section sfbva
+.section sfbvb
+.section sfbwa
+.section sfbwb
+.section sfbxa
+.section sfbxb
+.section sfbya
+.section sfbyb
+.section sfbza
+.section sfbzb
+.section sfb1a
+.section sfb1b
+.section sfb2a
+.section sfb2b
+.section sfb3a
+.section sfb3b
+.section sfb4a
+.section sfb4b
+.section sfb5a
+.section sfb5b
+.section sfb6a
+.section sfb6b
+.section sfb7a
+.section sfb7b
+.section sfb8a
+.section sfb8b
+.section sfb9a
+.section sfb9b
+.section sfb0a
+.section sfb0b
+.section sfcaa
+.section sfcab
+.section sfcba
+.section sfcbb
+.section sfcca
+.section sfccb
+.section sfcda
+.section sfcdb
+.section sfcea
+.section sfceb
+.section sfcfa
+.section sfcfb
+.section sfcga
+.section sfcgb
+.section sfcha
+.section sfchb
+.section sfcia
+.section sfcib
+.section sfcja
+.section sfcjb
+.section sfcka
+.section sfckb
+.section sfcla
+.section sfclb
+.section sfcma
+.section sfcmb
+.section sfcna
+.section sfcnb
+.section sfcoa
+.section sfcob
+.section sfcpa
+.section sfcpb
+.section sfcqa
+.section sfcqb
+.section sfcra
+.section sfcrb
+.section sfcsa
+.section sfcsb
+.section sfcta
+.section sfctb
+.section sfcua
+.section sfcub
+.section sfcva
+.section sfcvb
+.section sfcwa
+.section sfcwb
+.section sfcxa
+.section sfcxb
+.section sfcya
+.section sfcyb
+.section sfcza
+.section sfczb
+.section sfc1a
+.section sfc1b
+.section sfc2a
+.section sfc2b
+.section sfc3a
+.section sfc3b
+.section sfc4a
+.section sfc4b
+.section sfc5a
+.section sfc5b
+.section sfc6a
+.section sfc6b
+.section sfc7a
+.section sfc7b
+.section sfc8a
+.section sfc8b
+.section sfc9a
+.section sfc9b
+.section sfc0a
+.section sfc0b
+.section sfdaa
+.section sfdab
+.section sfdba
+.section sfdbb
+.section sfdca
+.section sfdcb
+.section sfdda
+.section sfddb
+.section sfdea
+.section sfdeb
+.section sfdfa
+.section sfdfb
+.section sfdga
+.section sfdgb
+.section sfdha
+.section sfdhb
+.section sfdia
+.section sfdib
+.section sfdja
+.section sfdjb
+.section sfdka
+.section sfdkb
+.section sfdla
+.section sfdlb
+.section sfdma
+.section sfdmb
+.section sfdna
+.section sfdnb
+.section sfdoa
+.section sfdob
+.section sfdpa
+.section sfdpb
+.section sfdqa
+.section sfdqb
+.section sfdra
+.section sfdrb
+.section sfdsa
+.section sfdsb
+.section sfdta
+.section sfdtb
+.section sfdua
+.section sfdub
+.section sfdva
+.section sfdvb
+.section sfdwa
+.section sfdwb
+.section sfdxa
+.section sfdxb
+.section sfdya
+.section sfdyb
+.section sfdza
+.section sfdzb
+.section sfd1a
+.section sfd1b
+.section sfd2a
+.section sfd2b
+.section sfd3a
+.section sfd3b
+.section sfd4a
+.section sfd4b
+.section sfd5a
+.section sfd5b
+.section sfd6a
+.section sfd6b
+.section sfd7a
+.section sfd7b
+.section sfd8a
+.section sfd8b
+.section sfd9a
+.section sfd9b
+.section sfd0a
+.section sfd0b
+.section sfeaa
+.section sfeab
+.section sfeba
+.section sfebb
+.section sfeca
+.section sfecb
+.section sfeda
+.section sfedb
+.section sfeea
+.section sfeeb
+.section sfefa
+.section sfefb
+.section sfega
+.section sfegb
+.section sfeha
+.section sfehb
+.section sfeia
+.section sfeib
+.section sfeja
+.section sfejb
+.section sfeka
+.section sfekb
+.section sfela
+.section sfelb
+.section sfema
+.section sfemb
+.section sfena
+.section sfenb
+.section sfeoa
+.section sfeob
+.section sfepa
+.section sfepb
+.section sfeqa
+.section sfeqb
+.section sfera
+.section sferb
+.section sfesa
+.section sfesb
+.section sfeta
+.section sfetb
+.section sfeua
+.section sfeub
+.section sfeva
+.section sfevb
+.section sfewa
+.section sfewb
+.section sfexa
+.section sfexb
+.section sfeya
+.section sfeyb
+.section sfeza
+.section sfezb
+.section sfe1a
+.section sfe1b
+.section sfe2a
+.section sfe2b
+.section sfe3a
+.section sfe3b
+.section sfe4a
+.section sfe4b
+.section sfe5a
+.section sfe5b
+.section sfe6a
+.section sfe6b
+.section sfe7a
+.section sfe7b
+.section sfe8a
+.section sfe8b
+.section sfe9a
+.section sfe9b
+.section sfe0a
+.section sfe0b
+.section sffaa
+.section sffab
+.section sffba
+.section sffbb
+.section sffca
+.section sffcb
+.section sffda
+.section sffdb
+.section sffea
+.section sffeb
+.section sfffa
+.section sfffb
+.section sffga
+.section sffgb
+.section sffha
+.section sffhb
+.section sffia
+.section sffib
+.section sffja
+.section sffjb
+.section sffka
+.section sffkb
+.section sffla
+.section sfflb
+.section sffma
+.section sffmb
+.section sffna
+.section sffnb
+.section sffoa
+.section sffob
+.section sffpa
+.section sffpb
+.section sffqa
+.section sffqb
+.section sffra
+.section sffrb
+.section sffsa
+.section sffsb
+.section sffta
+.section sfftb
+.section sffua
+.section sffub
+.section sffva
+.section sffvb
+.section sffwa
+.section sffwb
+.section sffxa
+.section sffxb
+.section sffya
+.section sffyb
+.section sffza
+.section sffzb
+.section sff1a
+.section sff1b
+.section sff2a
+.section sff2b
+.section sff3a
+.section sff3b
+.section sff4a
+.section sff4b
+.section sff5a
+.section sff5b
+.section sff6a
+.section sff6b
+.section sff7a
+.section sff7b
+.section sff8a
+.section sff8b
+.section sff9a
+.section sff9b
+.section sff0a
+.section sff0b
+.section sfgaa
+.section sfgab
+.section sfgba
+.section sfgbb
+.section sfgca
+.section sfgcb
+.section sfgda
+.section sfgdb
+.section sfgea
+.section sfgeb
+.section sfgfa
+.section sfgfb
+.section sfgga
+.section sfggb
+.section sfgha
+.section sfghb
+.section sfgia
+.section sfgib
+.section sfgja
+.section sfgjb
+.section sfgka
+.section sfgkb
+.section sfgla
+.section sfglb
+.section sfgma
+.section sfgmb
+.section sfgna
+.section sfgnb
+.section sfgoa
+.section sfgob
+.section sfgpa
+.section sfgpb
+.section sfgqa
+.section sfgqb
+.section sfgra
+.section sfgrb
+.section sfgsa
+.section sfgsb
+.section sfgta
+.section sfgtb
+.section sfgua
+.section sfgub
+.section sfgva
+.section sfgvb
+.section sfgwa
+.section sfgwb
+.section sfgxa
+.section sfgxb
+.section sfgya
+.section sfgyb
+.section sfgza
+.section sfgzb
+.section sfg1a
+.section sfg1b
+.section sfg2a
+.section sfg2b
+.section sfg3a
+.section sfg3b
+.section sfg4a
+.section sfg4b
+.section sfg5a
+.section sfg5b
+.section sfg6a
+.section sfg6b
+.section sfg7a
+.section sfg7b
+.section sfg8a
+.section sfg8b
+.section sfg9a
+.section sfg9b
+.section sfg0a
+.section sfg0b
+.section sfhaa
+.section sfhab
+.section sfhba
+.section sfhbb
+.section sfhca
+.section sfhcb
+.section sfhda
+.section sfhdb
+.section sfhea
+.section sfheb
+.section sfhfa
+.section sfhfb
+.section sfhga
+.section sfhgb
+.section sfhha
+.section sfhhb
+.section sfhia
+.section sfhib
+.section sfhja
+.section sfhjb
+.section sfhka
+.section sfhkb
+.section sfhla
+.section sfhlb
+.section sfhma
+.section sfhmb
+.section sfhna
+.section sfhnb
+.section sfhoa
+.section sfhob
+.section sfhpa
+.section sfhpb
+.section sfhqa
+.section sfhqb
+.section sfhra
+.section sfhrb
+.section sfhsa
+.section sfhsb
+.section sfhta
+.section sfhtb
+.section sfhua
+.section sfhub
+.section sfhva
+.section sfhvb
+.section sfhwa
+.section sfhwb
+.section sfhxa
+.section sfhxb
+.section sfhya
+.section sfhyb
+.section sfhza
+.section sfhzb
+.section sfh1a
+.section sfh1b
+.section sfh2a
+.section sfh2b
+.section sfh3a
+.section sfh3b
+.section sfh4a
+.section sfh4b
+.section sfh5a
+.section sfh5b
+.section sfh6a
+.section sfh6b
+.section sfh7a
+.section sfh7b
+.section sfh8a
+.section sfh8b
+.section sfh9a
+.section sfh9b
+.section sfh0a
+.section sfh0b
+.section sfiaa
+.section sfiab
+.section sfiba
+.section sfibb
+.section sfica
+.section sficb
+.section sfida
+.section sfidb
+.section sfiea
+.section sfieb
+.section sfifa
+.section sfifb
+.section sfiga
+.section sfigb
+.section sfiha
+.section sfihb
+.section sfiia
+.section sfiib
+.section sfija
+.section sfijb
+.section sfika
+.section sfikb
+.section sfila
+.section sfilb
+.section sfima
+.section sfimb
+.section sfina
+.section sfinb
+.section sfioa
+.section sfiob
+.section sfipa
+.section sfipb
+.section sfiqa
+.section sfiqb
+.section sfira
+.section sfirb
+.section sfisa
+.section sfisb
+.section sfita
+.section sfitb
+.section sfiua
+.section sfiub
+.section sfiva
+.section sfivb
+.section sfiwa
+.section sfiwb
+.section sfixa
+.section sfixb
+.section sfiya
+.section sfiyb
+.section sfiza
+.section sfizb
+.section sfi1a
+.section sfi1b
+.section sfi2a
+.section sfi2b
+.section sfi3a
+.section sfi3b
+.section sfi4a
+.section sfi4b
+.section sfi5a
+.section sfi5b
+.section sfi6a
+.section sfi6b
+.section sfi7a
+.section sfi7b
+.section sfi8a
+.section sfi8b
+.section sfi9a
+.section sfi9b
+.section sfi0a
+.section sfi0b
+.section sfjaa
+.section sfjab
+.section sfjba
+.section sfjbb
+.section sfjca
+.section sfjcb
+.section sfjda
+.section sfjdb
+.section sfjea
+.section sfjeb
+.section sfjfa
+.section sfjfb
+.section sfjga
+.section sfjgb
+.section sfjha
+.section sfjhb
+.section sfjia
+.section sfjib
+.section sfjja
+.section sfjjb
+.section sfjka
+.section sfjkb
+.section sfjla
+.section sfjlb
+.section sfjma
+.section sfjmb
+.section sfjna
+.section sfjnb
+.section sfjoa
+.section sfjob
+.section sfjpa
+.section sfjpb
+.section sfjqa
+.section sfjqb
+.section sfjra
+.section sfjrb
+.section sfjsa
+.section sfjsb
+.section sfjta
+.section sfjtb
+.section sfjua
+.section sfjub
+.section sfjva
+.section sfjvb
+.section sfjwa
+.section sfjwb
+.section sfjxa
+.section sfjxb
+.section sfjya
+.section sfjyb
+.section sfjza
+.section sfjzb
+.section sfj1a
+.section sfj1b
+.section sfj2a
+.section sfj2b
+.section sfj3a
+.section sfj3b
+.section sfj4a
+.section sfj4b
+.section sfj5a
+.section sfj5b
+.section sfj6a
+.section sfj6b
+.section sfj7a
+.section sfj7b
+.section sfj8a
+.section sfj8b
+.section sfj9a
+.section sfj9b
+.section sfj0a
+.section sfj0b
+.section sfkaa
+.section sfkab
+.section sfkba
+.section sfkbb
+.section sfkca
+.section sfkcb
+.section sfkda
+.section sfkdb
+.section sfkea
+.section sfkeb
+.section sfkfa
+.section sfkfb
+.section sfkga
+.section sfkgb
+.section sfkha
+.section sfkhb
+.section sfkia
+.section sfkib
+.section sfkja
+.section sfkjb
+.section sfkka
+.section sfkkb
+.section sfkla
+.section sfklb
+.section sfkma
+.section sfkmb
+.section sfkna
+.section sfknb
+.section sfkoa
+.section sfkob
+.section sfkpa
+.section sfkpb
+.section sfkqa
+.section sfkqb
+.section sfkra
+.section sfkrb
+.section sfksa
+.section sfksb
+.section sfkta
+.section sfktb
+.section sfkua
+.section sfkub
+.section sfkva
+.section sfkvb
+.section sfkwa
+.section sfkwb
+.section sfkxa
+.section sfkxb
+.section sfkya
+.section sfkyb
+.section sfkza
+.section sfkzb
+.section sfk1a
+.section sfk1b
+.section sfk2a
+.section sfk2b
+.section sfk3a
+.section sfk3b
+.section sfk4a
+.section sfk4b
+.section sfk5a
+.section sfk5b
+.section sfk6a
+.section sfk6b
+.section sfk7a
+.section sfk7b
+.section sfk8a
+.section sfk8b
+.section sfk9a
+.section sfk9b
+.section sfk0a
+.section sfk0b
+.section sflaa
+.section sflab
+.section sflba
+.section sflbb
+.section sflca
+.section sflcb
+.section sflda
+.section sfldb
+.section sflea
+.section sfleb
+.section sflfa
+.section sflfb
+.section sflga
+.section sflgb
+.section sflha
+.section sflhb
+.section sflia
+.section sflib
+.section sflja
+.section sfljb
+.section sflka
+.section sflkb
+.section sflla
+.section sfllb
+.section sflma
+.section sflmb
+.section sflna
+.section sflnb
+.section sfloa
+.section sflob
+.section sflpa
+.section sflpb
+.section sflqa
+.section sflqb
+.section sflra
+.section sflrb
+.section sflsa
+.section sflsb
+.section sflta
+.section sfltb
+.section sflua
+.section sflub
+.section sflva
+.section sflvb
+.section sflwa
+.section sflwb
+.section sflxa
+.section sflxb
+.section sflya
+.section sflyb
+.section sflza
+.section sflzb
+.section sfl1a
+.section sfl1b
+.section sfl2a
+.section sfl2b
+.section sfl3a
+.section sfl3b
+.section sfl4a
+.section sfl4b
+.section sfl5a
+.section sfl5b
+.section sfl6a
+.section sfl6b
+.section sfl7a
+.section sfl7b
+.section sfl8a
+.section sfl8b
+.section sfl9a
+.section sfl9b
+.section sfl0a
+.section sfl0b
+.section sfmaa
+.section sfmab
+.section sfmba
+.section sfmbb
+.section sfmca
+.section sfmcb
+.section sfmda
+.section sfmdb
+.section sfmea
+.section sfmeb
+.section sfmfa
+.section sfmfb
+.section sfmga
+.section sfmgb
+.section sfmha
+.section sfmhb
+.section sfmia
+.section sfmib
+.section sfmja
+.section sfmjb
+.section sfmka
+.section sfmkb
+.section sfmla
+.section sfmlb
+.section sfmma
+.section sfmmb
+.section sfmna
+.section sfmnb
+.section sfmoa
+.section sfmob
+.section sfmpa
+.section sfmpb
+.section sfmqa
+.section sfmqb
+.section sfmra
+.section sfmrb
+.section sfmsa
+.section sfmsb
+.section sfmta
+.section sfmtb
+.section sfmua
+.section sfmub
+.section sfmva
+.section sfmvb
+.section sfmwa
+.section sfmwb
+.section sfmxa
+.section sfmxb
+.section sfmya
+.section sfmyb
+.section sfmza
+.section sfmzb
+.section sfm1a
+.section sfm1b
+.section sfm2a
+.section sfm2b
+.section sfm3a
+.section sfm3b
+.section sfm4a
+.section sfm4b
+.section sfm5a
+.section sfm5b
+.section sfm6a
+.section sfm6b
+.section sfm7a
+.section sfm7b
+.section sfm8a
+.section sfm8b
+.section sfm9a
+.section sfm9b
+.section sfm0a
+.section sfm0b
+.section sfnaa
+.section sfnab
+.section sfnba
+.section sfnbb
+.section sfnca
+.section sfncb
+.section sfnda
+.section sfndb
+.section sfnea
+.section sfneb
+.section sfnfa
+.section sfnfb
+.section sfnga
+.section sfngb
+.section sfnha
+.section sfnhb
+.section sfnia
+.section sfnib
+.section sfnja
+.section sfnjb
+.section sfnka
+.section sfnkb
+.section sfnla
+.section sfnlb
+.section sfnma
+.section sfnmb
+.section sfnna
+.section sfnnb
+.section sfnoa
+.section sfnob
+.section sfnpa
+.section sfnpb
+.section sfnqa
+.section sfnqb
+.section sfnra
+.section sfnrb
+.section sfnsa
+.section sfnsb
+.section sfnta
+.section sfntb
+.section sfnua
+.section sfnub
+.section sfnva
+.section sfnvb
+.section sfnwa
+.section sfnwb
+.section sfnxa
+.section sfnxb
+.section sfnya
+.section sfnyb
+.section sfnza
+.section sfnzb
+.section sfn1a
+.section sfn1b
+.section sfn2a
+.section sfn2b
+.section sfn3a
+.section sfn3b
+.section sfn4a
+.section sfn4b
+.section sfn5a
+.section sfn5b
+.section sfn6a
+.section sfn6b
+.section sfn7a
+.section sfn7b
+.section sfn8a
+.section sfn8b
+.section sfn9a
+.section sfn9b
+.section sfn0a
+.section sfn0b
+.section sfoaa
+.section sfoab
+.section sfoba
+.section sfobb
+.section sfoca
+.section sfocb
+.section sfoda
+.section sfodb
+.section sfoea
+.section sfoeb
+.section sfofa
+.section sfofb
+.section sfoga
+.section sfogb
+.section sfoha
+.section sfohb
+.section sfoia
+.section sfoib
+.section sfoja
+.section sfojb
+.section sfoka
+.section sfokb
+.section sfola
+.section sfolb
+.section sfoma
+.section sfomb
+.section sfona
+.section sfonb
+.section sfooa
+.section sfoob
+.section sfopa
+.section sfopb
+.section sfoqa
+.section sfoqb
+.section sfora
+.section sforb
+.section sfosa
+.section sfosb
+.section sfota
+.section sfotb
+.section sfoua
+.section sfoub
+.section sfova
+.section sfovb
+.section sfowa
+.section sfowb
+.section sfoxa
+.section sfoxb
+.section sfoya
+.section sfoyb
+.section sfoza
+.section sfozb
+.section sfo1a
+.section sfo1b
+.section sfo2a
+.section sfo2b
+.section sfo3a
+.section sfo3b
+.section sfo4a
+.section sfo4b
+.section sfo5a
+.section sfo5b
+.section sfo6a
+.section sfo6b
+.section sfo7a
+.section sfo7b
+.section sfo8a
+.section sfo8b
+.section sfo9a
+.section sfo9b
+.section sfo0a
+.section sfo0b
+.section sfpaa
+.section sfpab
+.section sfpba
+.section sfpbb
+.section sfpca
+.section sfpcb
+.section sfpda
+.section sfpdb
+.section sfpea
+.section sfpeb
+.section sfpfa
+.section sfpfb
+.section sfpga
+.section sfpgb
+.section sfpha
+.section sfphb
+.section sfpia
+.section sfpib
+.section sfpja
+.section sfpjb
+.section sfpka
+.section sfpkb
+.section sfpla
+.section sfplb
+.section sfpma
+.section sfpmb
+.section sfpna
+.section sfpnb
+.section sfpoa
+.section sfpob
+.section sfppa
+.section sfppb
+.section sfpqa
+.section sfpqb
+.section sfpra
+.section sfprb
+.section sfpsa
+.section sfpsb
+.section sfpta
+.section sfptb
+.section sfpua
+.section sfpub
+.section sfpva
+.section sfpvb
+.section sfpwa
+.section sfpwb
+.section sfpxa
+.section sfpxb
+.section sfpya
+.section sfpyb
+.section sfpza
+.section sfpzb
+.section sfp1a
+.section sfp1b
+.section sfp2a
+.section sfp2b
+.section sfp3a
+.section sfp3b
+.section sfp4a
+.section sfp4b
+.section sfp5a
+.section sfp5b
+.section sfp6a
+.section sfp6b
+.section sfp7a
+.section sfp7b
+.section sfp8a
+.section sfp8b
+.section sfp9a
+.section sfp9b
+.section sfp0a
+.section sfp0b
+.section sfqaa
+.section sfqab
+.section sfqba
+.section sfqbb
+.section sfqca
+.section sfqcb
+.section sfqda
+.section sfqdb
+.section sfqea
+.section sfqeb
+.section sfqfa
+.section sfqfb
+.section sfqga
+.section sfqgb
+.section sfqha
+.section sfqhb
+.section sfqia
+.section sfqib
+.section sfqja
+.section sfqjb
+.section sfqka
+.section sfqkb
+.section sfqla
+.section sfqlb
+.section sfqma
+.section sfqmb
+.section sfqna
+.section sfqnb
+.section sfqoa
+.section sfqob
+.section sfqpa
+.section sfqpb
+.section sfqqa
+.section sfqqb
+.section sfqra
+.section sfqrb
+.section sfqsa
+.section sfqsb
+.section sfqta
+.section sfqtb
+.section sfqua
+.section sfqub
+.section sfqva
+.section sfqvb
+.section sfqwa
+.section sfqwb
+.section sfqxa
+.section sfqxb
+.section sfqya
+.section sfqyb
+.section sfqza
+.section sfqzb
+.section sfq1a
+.section sfq1b
+.section sfq2a
+.section sfq2b
+.section sfq3a
+.section sfq3b
+.section sfq4a
+.section sfq4b
+.section sfq5a
+.section sfq5b
+.section sfq6a
+.section sfq6b
+.section sfq7a
+.section sfq7b
+.section sfq8a
+.section sfq8b
+.section sfq9a
+.section sfq9b
+.section sfq0a
+.section sfq0b
+.section sfraa
+.section sfrab
+.section sfrba
+.section sfrbb
+.section sfrca
+.section sfrcb
+.section sfrda
+.section sfrdb
+.section sfrea
+.section sfreb
+.section sfrfa
+.section sfrfb
+.section sfrga
+.section sfrgb
+.section sfrha
+.section sfrhb
+.section sfria
+.section sfrib
+.section sfrja
+.section sfrjb
+.section sfrka
+.section sfrkb
+.section sfrla
+.section sfrlb
+.section sfrma
+.section sfrmb
+.section sfrna
+.section sfrnb
+.section sfroa
+.section sfrob
+.section sfrpa
+.section sfrpb
+.section sfrqa
+.section sfrqb
+.section sfrra
+.section sfrrb
+.section sfrsa
+.section sfrsb
+.section sfrta
+.section sfrtb
+.section sfrua
+.section sfrub
+.section sfrva
+.section sfrvb
+.section sfrwa
+.section sfrwb
+.section sfrxa
+.section sfrxb
+.section sfrya
+.section sfryb
+.section sfrza
+.section sfrzb
+.section sfr1a
+.section sfr1b
+.section sfr2a
+.section sfr2b
+.section sfr3a
+.section sfr3b
+.section sfr4a
+.section sfr4b
+.section sfr5a
+.section sfr5b
+.section sfr6a
+.section sfr6b
+.section sfr7a
+.section sfr7b
+.section sfr8a
+.section sfr8b
+.section sfr9a
+.section sfr9b
+.section sfr0a
+.section sfr0b
+.section sfsaa
+.section sfsab
+.section sfsba
+.section sfsbb
+.section sfsca
+.section sfscb
+.section sfsda
+.section sfsdb
+.section sfsea
+.section sfseb
+.section sfsfa
+.section sfsfb
+.section sfsga
+.section sfsgb
+.section sfsha
+.section sfshb
+.section sfsia
+.section sfsib
+.section sfsja
+.section sfsjb
+.section sfska
+.section sfskb
+.section sfsla
+.section sfslb
+.section sfsma
+.section sfsmb
+.section sfsna
+.section sfsnb
+.section sfsoa
+.section sfsob
+.section sfspa
+.section sfspb
+.section sfsqa
+.section sfsqb
+.section sfsra
+.section sfsrb
+.section sfssa
+.section sfssb
+.section sfsta
+.section sfstb
+.section sfsua
+.section sfsub
+.section sfsva
+.section sfsvb
+.section sfswa
+.section sfswb
+.section sfsxa
+.section sfsxb
+.section sfsya
+.section sfsyb
+.section sfsza
+.section sfszb
+.section sfs1a
+.section sfs1b
+.section sfs2a
+.section sfs2b
+.section sfs3a
+.section sfs3b
+.section sfs4a
+.section sfs4b
+.section sfs5a
+.section sfs5b
+.section sfs6a
+.section sfs6b
+.section sfs7a
+.section sfs7b
+.section sfs8a
+.section sfs8b
+.section sfs9a
+.section sfs9b
+.section sfs0a
+.section sfs0b
+.section sftaa
+.section sftab
+.section sftba
+.section sftbb
+.section sftca
+.section sftcb
+.section sftda
+.section sftdb
+.section sftea
+.section sfteb
+.section sftfa
+.section sftfb
+.section sftga
+.section sftgb
+.section sftha
+.section sfthb
+.section sftia
+.section sftib
+.section sftja
+.section sftjb
+.section sftka
+.section sftkb
+.section sftla
+.section sftlb
+.section sftma
+.section sftmb
+.section sftna
+.section sftnb
+.section sftoa
+.section sftob
+.section sftpa
+.section sftpb
+.section sftqa
+.section sftqb
+.section sftra
+.section sftrb
+.section sftsa
+.section sftsb
+.section sftta
+.section sfttb
+.section sftua
+.section sftub
+.section sftva
+.section sftvb
+.section sftwa
+.section sftwb
+.section sftxa
+.section sftxb
+.section sftya
+.section sftyb
+.section sftza
+.section sftzb
+.section sft1a
+.section sft1b
+.section sft2a
+.section sft2b
+.section sft3a
+.section sft3b
+.section sft4a
+.section sft4b
+.section sft5a
+.section sft5b
+.section sft6a
+.section sft6b
+.section sft7a
+.section sft7b
+.section sft8a
+.section sft8b
+.section sft9a
+.section sft9b
+.section sft0a
+.section sft0b
+.section sfuaa
+.section sfuab
+.section sfuba
+.section sfubb
+.section sfuca
+.section sfucb
+.section sfuda
+.section sfudb
+.section sfuea
+.section sfueb
+.section sfufa
+.section sfufb
+.section sfuga
+.section sfugb
+.section sfuha
+.section sfuhb
+.section sfuia
+.section sfuib
+.section sfuja
+.section sfujb
+.section sfuka
+.section sfukb
+.section sfula
+.section sfulb
+.section sfuma
+.section sfumb
+.section sfuna
+.section sfunb
+.section sfuoa
+.section sfuob
+.section sfupa
+.section sfupb
+.section sfuqa
+.section sfuqb
+.section sfura
+.section sfurb
+.section sfusa
+.section sfusb
+.section sfuta
+.section sfutb
+.section sfuua
+.section sfuub
+.section sfuva
+.section sfuvb
+.section sfuwa
+.section sfuwb
+.section sfuxa
+.section sfuxb
+.section sfuya
+.section sfuyb
+.section sfuza
+.section sfuzb
+.section sfu1a
+.section sfu1b
+.section sfu2a
+.section sfu2b
+.section sfu3a
+.section sfu3b
+.section sfu4a
+.section sfu4b
+.section sfu5a
+.section sfu5b
+.section sfu6a
+.section sfu6b
+.section sfu7a
+.section sfu7b
+.section sfu8a
+.section sfu8b
+.section sfu9a
+.section sfu9b
+.section sfu0a
+.section sfu0b
+.section sfvaa
+.section sfvab
+.section sfvba
+.section sfvbb
+.section sfvca
+.section sfvcb
+.section sfvda
+.section sfvdb
+.section sfvea
+.section sfveb
+.section sfvfa
+.section sfvfb
+.section sfvga
+.section sfvgb
+.section sfvha
+.section sfvhb
+.section sfvia
+.section sfvib
+.section sfvja
+.section sfvjb
+.section sfvka
+.section sfvkb
+.section sfvla
+.section sfvlb
+.section sfvma
+.section sfvmb
+.section sfvna
+.section sfvnb
+.section sfvoa
+.section sfvob
+.section sfvpa
+.section sfvpb
+.section sfvqa
+.section sfvqb
+.section sfvra
+.section sfvrb
+.section sfvsa
+.section sfvsb
+.section sfvta
+.section sfvtb
+.section sfvua
+.section sfvub
+.section sfvva
+.section sfvvb
+.section sfvwa
+.section sfvwb
+.section sfvxa
+.section sfvxb
+.section sfvya
+.section sfvyb
+.section sfvza
+.section sfvzb
+.section sfv1a
+.section sfv1b
+.section sfv2a
+.section sfv2b
+.section sfv3a
+.section sfv3b
+.section sfv4a
+.section sfv4b
+.section sfv5a
+.section sfv5b
+.section sfv6a
+.section sfv6b
+.section sfv7a
+.section sfv7b
+.section sfv8a
+.section sfv8b
+.section sfv9a
+.section sfv9b
+.section sfv0a
+.section sfv0b
+.section sfwaa
+.section sfwab
+.section sfwba
+.section sfwbb
+.section sfwca
+.section sfwcb
+.section sfwda
+.section sfwdb
+.section sfwea
+.section sfweb
+.section sfwfa
+.section sfwfb
+.section sfwga
+.section sfwgb
+.section sfwha
+.section sfwhb
+.section sfwia
+.section sfwib
+.section sfwja
+.section sfwjb
+.section sfwka
+.section sfwkb
+.section sfwla
+.section sfwlb
+.section sfwma
+.section sfwmb
+.section sfwna
+.section sfwnb
+.section sfwoa
+.section sfwob
+.section sfwpa
+.section sfwpb
+.section sfwqa
+.section sfwqb
+.section sfwra
+.section sfwrb
+.section sfwsa
+.section sfwsb
+.section sfwta
+.section sfwtb
+.section sfwua
+.section sfwub
+.section sfwva
+.section sfwvb
+.section sfwwa
+.section sfwwb
+.section sfwxa
+.section sfwxb
+.section sfwya
+.section sfwyb
+.section sfwza
+.section sfwzb
+.section sfw1a
+.section sfw1b
+.section sfw2a
+.section sfw2b
+.section sfw3a
+.section sfw3b
+.section sfw4a
+.section sfw4b
+.section sfw5a
+.section sfw5b
+.section sfw6a
+.section sfw6b
+.section sfw7a
+.section sfw7b
+.section sfw8a
+.section sfw8b
+.section sfw9a
+.section sfw9b
+.section sfw0a
+.section sfw0b
+.section sfxaa
+.section sfxab
+.section sfxba
+.section sfxbb
+.section sfxca
+.section sfxcb
+.section sfxda
+.section sfxdb
+.section sfxea
+.section sfxeb
+.section sfxfa
+.section sfxfb
+.section sfxga
+.section sfxgb
+.section sfxha
+.section sfxhb
+.section sfxia
+.section sfxib
+.section sfxja
+.section sfxjb
+.section sfxka
+.section sfxkb
+.section sfxla
+.section sfxlb
+.section sfxma
+.section sfxmb
+.section sfxna
+.section sfxnb
+.section sfxoa
+.section sfxob
+.section sfxpa
+.section sfxpb
+.section sfxqa
+.section sfxqb
+.section sfxra
+.section sfxrb
+.section sfxsa
+.section sfxsb
+.section sfxta
+.section sfxtb
+.section sfxua
+.section sfxub
+.section sfxva
+.section sfxvb
+.section sfxwa
+.section sfxwb
+.section sfxxa
+.section sfxxb
+.section sfxya
+.section sfxyb
+.section sfxza
+.section sfxzb
+.section sfx1a
+.section sfx1b
+.section sfx2a
+.section sfx2b
+.section sfx3a
+.section sfx3b
+.section sfx4a
+.section sfx4b
+.section sfx5a
+.section sfx5b
+.section sfx6a
+.section sfx6b
+.section sfx7a
+.section sfx7b
+.section sfx8a
+.section sfx8b
+.section sfx9a
+.section sfx9b
+.section sfx0a
+.section sfx0b
+.section sfyaa
+.section sfyab
+.section sfyba
+.section sfybb
+.section sfyca
+.section sfycb
+.section sfyda
+.section sfydb
+.section sfyea
+.section sfyeb
+.section sfyfa
+.section sfyfb
+.section sfyga
+.section sfygb
+.section sfyha
+.section sfyhb
+.section sfyia
+.section sfyib
+.section sfyja
+.section sfyjb
+.section sfyka
+.section sfykb
+.section sfyla
+.section sfylb
+.section sfyma
+.section sfymb
+.section sfyna
+.section sfynb
+.section sfyoa
+.section sfyob
+.section sfypa
+.section sfypb
+.section sfyqa
+.section sfyqb
+.section sfyra
+.section sfyrb
+.section sfysa
+.section sfysb
+.section sfyta
+.section sfytb
+.section sfyua
+.section sfyub
+.section sfyva
+.section sfyvb
+.section sfywa
+.section sfywb
+.section sfyxa
+.section sfyxb
+.section sfyya
+.section sfyyb
+.section sfyza
+.section sfyzb
+.section sfy1a
+.section sfy1b
+.section sfy2a
+.section sfy2b
+.section sfy3a
+.section sfy3b
+.section sfy4a
+.section sfy4b
+.section sfy5a
+.section sfy5b
+.section sfy6a
+.section sfy6b
+.section sfy7a
+.section sfy7b
+.section sfy8a
+.section sfy8b
+.section sfy9a
+.section sfy9b
+.section sfy0a
+.section sfy0b
+.section sfzaa
+.section sfzab
+.section sfzba
+.section sfzbb
+.section sfzca
+.section sfzcb
+.section sfzda
+.section sfzdb
+.section sfzea
+.section sfzeb
+.section sfzfa
+.section sfzfb
+.section sfzga
+.section sfzgb
+.section sfzha
+.section sfzhb
+.section sfzia
+.section sfzib
+.section sfzja
+.section sfzjb
+.section sfzka
+.section sfzkb
+.section sfzla
+.section sfzlb
+.section sfzma
+.section sfzmb
+.section sfzna
+.section sfznb
+.section sfzoa
+.section sfzob
+.section sfzpa
+.section sfzpb
+.section sfzqa
+.section sfzqb
+.section sfzra
+.section sfzrb
+.section sfzsa
+.section sfzsb
+.section sfzta
+.section sfztb
+.section sfzua
+.section sfzub
+.section sfzva
+.section sfzvb
+.section sfzwa
+.section sfzwb
+.section sfzxa
+.section sfzxb
+.section sfzya
+.section sfzyb
+.section sfzza
+.section sfzzb
+.section sfz1a
+.section sfz1b
+.section sfz2a
+.section sfz2b
+.section sfz3a
+.section sfz3b
+.section sfz4a
+.section sfz4b
+.section sfz5a
+.section sfz5b
+.section sfz6a
+.section sfz6b
+.section sfz7a
+.section sfz7b
+.section sfz8a
+.section sfz8b
+.section sfz9a
+.section sfz9b
+.section sfz0a
+.section sfz0b
+.section sf1aa
+.section sf1ab
+.section sf1ba
+.section sf1bb
+.section sf1ca
+.section sf1cb
+.section sf1da
+.section sf1db
+.section sf1ea
+.section sf1eb
+.section sf1fa
+.section sf1fb
+.section sf1ga
+.section sf1gb
+.section sf1ha
+.section sf1hb
+.section sf1ia
+.section sf1ib
+.section sf1ja
+.section sf1jb
+.section sf1ka
+.section sf1kb
+.section sf1la
+.section sf1lb
+.section sf1ma
+.section sf1mb
+.section sf1na
+.section sf1nb
+.section sf1oa
+.section sf1ob
+.section sf1pa
+.section sf1pb
+.section sf1qa
+.section sf1qb
+.section sf1ra
+.section sf1rb
+.section sf1sa
+.section sf1sb
+.section sf1ta
+.section sf1tb
+.section sf1ua
+.section sf1ub
+.section sf1va
+.section sf1vb
+.section sf1wa
+.section sf1wb
+.section sf1xa
+.section sf1xb
+.section sf1ya
+.section sf1yb
+.section sf1za
+.section sf1zb
+.section sf11a
+.section sf11b
+.section sf12a
+.section sf12b
+.section sf13a
+.section sf13b
+.section sf14a
+.section sf14b
+.section sf15a
+.section sf15b
+.section sf16a
+.section sf16b
+.section sf17a
+.section sf17b
+.section sf18a
+.section sf18b
+.section sf19a
+.section sf19b
+.section sf10a
+.section sf10b
+.section sf2aa
+.section sf2ab
+.section sf2ba
+.section sf2bb
+.section sf2ca
+.section sf2cb
+.section sf2da
+.section sf2db
+.section sf2ea
+.section sf2eb
+.section sf2fa
+.section sf2fb
+.section sf2ga
+.section sf2gb
+.section sf2ha
+.section sf2hb
+.section sf2ia
+.section sf2ib
+.section sf2ja
+.section sf2jb
+.section sf2ka
+.section sf2kb
+.section sf2la
+.section sf2lb
+.section sf2ma
+.section sf2mb
+.section sf2na
+.section sf2nb
+.section sf2oa
+.section sf2ob
+.section sf2pa
+.section sf2pb
+.section sf2qa
+.section sf2qb
+.section sf2ra
+.section sf2rb
+.section sf2sa
+.section sf2sb
+.section sf2ta
+.section sf2tb
+.section sf2ua
+.section sf2ub
+.section sf2va
+.section sf2vb
+.section sf2wa
+.section sf2wb
+.section sf2xa
+.section sf2xb
+.section sf2ya
+.section sf2yb
+.section sf2za
+.section sf2zb
+.section sf21a
+.section sf21b
+.section sf22a
+.section sf22b
+.section sf23a
+.section sf23b
+.section sf24a
+.section sf24b
+.section sf25a
+.section sf25b
+.section sf26a
+.section sf26b
+.section sf27a
+.section sf27b
+.section sf28a
+.section sf28b
+.section sf29a
+.section sf29b
+.section sf20a
+.section sf20b
+.section sf3aa
+.section sf3ab
+.section sf3ba
+.section sf3bb
+.section sf3ca
+.section sf3cb
+.section sf3da
+.section sf3db
+.section sf3ea
+.section sf3eb
+.section sf3fa
+.section sf3fb
+.section sf3ga
+.section sf3gb
+.section sf3ha
+.section sf3hb
+.section sf3ia
+.section sf3ib
+.section sf3ja
+.section sf3jb
+.section sf3ka
+.section sf3kb
+.section sf3la
+.section sf3lb
+.section sf3ma
+.section sf3mb
+.section sf3na
+.section sf3nb
+.section sf3oa
+.section sf3ob
+.section sf3pa
+.section sf3pb
+.section sf3qa
+.section sf3qb
+.section sf3ra
+.section sf3rb
+.section sf3sa
+.section sf3sb
+.section sf3ta
+.section sf3tb
+.section sf3ua
+.section sf3ub
+.section sf3va
+.section sf3vb
+.section sf3wa
+.section sf3wb
+.section sf3xa
+.section sf3xb
+.section sf3ya
+.section sf3yb
+.section sf3za
+.section sf3zb
+.section sf31a
+.section sf31b
+.section sf32a
+.section sf32b
+.section sf33a
+.section sf33b
+.section sf34a
+.section sf34b
+.section sf35a
+.section sf35b
+.section sf36a
+.section sf36b
+.section sf37a
+.section sf37b
+.section sf38a
+.section sf38b
+.section sf39a
+.section sf39b
+.section sf30a
+.section sf30b
+.section sf4aa
+.section sf4ab
+.section sf4ba
+.section sf4bb
+.section sf4ca
+.section sf4cb
+.section sf4da
+.section sf4db
+.section sf4ea
+.section sf4eb
+.section sf4fa
+.section sf4fb
+.section sf4ga
+.section sf4gb
+.section sf4ha
+.section sf4hb
+.section sf4ia
+.section sf4ib
+.section sf4ja
+.section sf4jb
+.section sf4ka
+.section sf4kb
+.section sf4la
+.section sf4lb
+.section sf4ma
+.section sf4mb
+.section sf4na
+.section sf4nb
+.section sf4oa
+.section sf4ob
+.section sf4pa
+.section sf4pb
+.section sf4qa
+.section sf4qb
+.section sf4ra
+.section sf4rb
+.section sf4sa
+.section sf4sb
+.section sf4ta
+.section sf4tb
+.section sf4ua
+.section sf4ub
+.section sf4va
+.section sf4vb
+.section sf4wa
+.section sf4wb
+.section sf4xa
+.section sf4xb
+.section sf4ya
+.section sf4yb
+.section sf4za
+.section sf4zb
+.section sf41a
+.section sf41b
+.section sf42a
+.section sf42b
+.section sf43a
+.section sf43b
+.section sf44a
+.section sf44b
+.section sf45a
+.section sf45b
+.section sf46a
+.section sf46b
+.section sf47a
+.section sf47b
+.section sf48a
+.section sf48b
+.section sf49a
+.section sf49b
+.section sf40a
+.section sf40b
+.section sf5aa
+.section sf5ab
+.section sf5ba
+.section sf5bb
+.section sf5ca
+.section sf5cb
+.section sf5da
+.section sf5db
+.section sf5ea
+.section sf5eb
+.section sf5fa
+.section sf5fb
+.section sf5ga
+.section sf5gb
+.section sf5ha
+.section sf5hb
+.section sf5ia
+.section sf5ib
+.section sf5ja
+.section sf5jb
+.section sf5ka
+.section sf5kb
+.section sf5la
+.section sf5lb
+.section sf5ma
+.section sf5mb
+.section sf5na
+.section sf5nb
+.section sf5oa
+.section sf5ob
+.section sf5pa
+.section sf5pb
+.section sf5qa
+.section sf5qb
+.section sf5ra
+.section sf5rb
+.section sf5sa
+.section sf5sb
+.section sf5ta
+.section sf5tb
+.section sf5ua
+.section sf5ub
+.section sf5va
+.section sf5vb
+.section sf5wa
+.section sf5wb
+.section sf5xa
+.section sf5xb
+.section sf5ya
+.section sf5yb
+.section sf5za
+.section sf5zb
+.section sf51a
+.section sf51b
+.section sf52a
+.section sf52b
+.section sf53a
+.section sf53b
+.section sf54a
+.section sf54b
+.section sf55a
+.section sf55b
+.section sf56a
+.section sf56b
+.section sf57a
+.section sf57b
+.section sf58a
+.section sf58b
+.section sf59a
+.section sf59b
+.section sf50a
+.section sf50b
+.section sf6aa
+.section sf6ab
+.section sf6ba
+.section sf6bb
+.section sf6ca
+.section sf6cb
+.section sf6da
+.section sf6db
+.section sf6ea
+.section sf6eb
+.section sf6fa
+.section sf6fb
+.section sf6ga
+.section sf6gb
+.section sf6ha
+.section sf6hb
+.section sf6ia
+.section sf6ib
+.section sf6ja
+.section sf6jb
+.section sf6ka
+.section sf6kb
+.section sf6la
+.section sf6lb
+.section sf6ma
+.section sf6mb
+.section sf6na
+.section sf6nb
+.section sf6oa
+.section sf6ob
+.section sf6pa
+.section sf6pb
+.section sf6qa
+.section sf6qb
+.section sf6ra
+.section sf6rb
+.section sf6sa
+.section sf6sb
+.section sf6ta
+.section sf6tb
+.section sf6ua
+.section sf6ub
+.section sf6va
+.section sf6vb
+.section sf6wa
+.section sf6wb
+.section sf6xa
+.section sf6xb
+.section sf6ya
+.section sf6yb
+.section sf6za
+.section sf6zb
+.section sf61a
+.section sf61b
+.section sf62a
+.section sf62b
+.section sf63a
+.section sf63b
+.section sf64a
+.section sf64b
+.section sf65a
+.section sf65b
+.section sf66a
+.section sf66b
+.section sf67a
+.section sf67b
+.section sf68a
+.section sf68b
+.section sf69a
+.section sf69b
+.section sf60a
+.section sf60b
+.section sf7aa
+.section sf7ab
+.section sf7ba
+.section sf7bb
+.section sf7ca
+.section sf7cb
+.section sf7da
+.section sf7db
+.section sf7ea
+.section sf7eb
+.section sf7fa
+.section sf7fb
+.section sf7ga
+.section sf7gb
+.section sf7ha
+.section sf7hb
+.section sf7ia
+.section sf7ib
+.section sf7ja
+.section sf7jb
+.section sf7ka
+.section sf7kb
+.section sf7la
+.section sf7lb
+.section sf7ma
+.section sf7mb
+.section sf7na
+.section sf7nb
+.section sf7oa
+.section sf7ob
+.section sf7pa
+.section sf7pb
+.section sf7qa
+.section sf7qb
+.section sf7ra
+.section sf7rb
+.section sf7sa
+.section sf7sb
+.section sf7ta
+.section sf7tb
+.section sf7ua
+.section sf7ub
+.section sf7va
+.section sf7vb
+.section sf7wa
+.section sf7wb
+.section sf7xa
+.section sf7xb
+.section sf7ya
+.section sf7yb
+.section sf7za
+.section sf7zb
+.section sf71a
+.section sf71b
+.section sf72a
+.section sf72b
+.section sf73a
+.section sf73b
+.section sf74a
+.section sf74b
+.section sf75a
+.section sf75b
+.section sf76a
+.section sf76b
+.section sf77a
+.section sf77b
+.section sf78a
+.section sf78b
+.section sf79a
+.section sf79b
+.section sf70a
+.section sf70b
+.section sf8aa
+.section sf8ab
+.section sf8ba
+.section sf8bb
+.section sf8ca
+.section sf8cb
+.section sf8da
+.section sf8db
+.section sf8ea
+.section sf8eb
+.section sf8fa
+.section sf8fb
+.section sf8ga
+.section sf8gb
+.section sf8ha
+.section sf8hb
+.section sf8ia
+.section sf8ib
+.section sf8ja
+.section sf8jb
+.section sf8ka
+.section sf8kb
+.section sf8la
+.section sf8lb
+.section sf8ma
+.section sf8mb
+.section sf8na
+.section sf8nb
+.section sf8oa
+.section sf8ob
+.section sf8pa
+.section sf8pb
+.section sf8qa
+.section sf8qb
+.section sf8ra
+.section sf8rb
+.section sf8sa
+.section sf8sb
+.section sf8ta
+.section sf8tb
+.section sf8ua
+.section sf8ub
+.section sf8va
+.section sf8vb
+.section sf8wa
+.section sf8wb
+.section sf8xa
+.section sf8xb
+.section sf8ya
+.section sf8yb
+.section sf8za
+.section sf8zb
+.section sf81a
+.section sf81b
+.section sf82a
+.section sf82b
+.section sf83a
+.section sf83b
+.section sf84a
+.section sf84b
+.section sf85a
+.section sf85b
+.section sf86a
+.section sf86b
+.section sf87a
+.section sf87b
+.section sf88a
+.section sf88b
+.section sf89a
+.section sf89b
+.section sf80a
+.section sf80b
+.section sf9aa
+.section sf9ab
+.section sf9ba
+.section sf9bb
+.section sf9ca
+.section sf9cb
+.section sf9da
+.section sf9db
+.section sf9ea
+.section sf9eb
+.section sf9fa
+.section sf9fb
+.section sf9ga
+.section sf9gb
+.section sf9ha
+.section sf9hb
+.section sf9ia
+.section sf9ib
+.section sf9ja
+.section sf9jb
+.section sf9ka
+.section sf9kb
+.section sf9la
+.section sf9lb
+.section sf9ma
+.section sf9mb
+.section sf9na
+.section sf9nb
+.section sf9oa
+.section sf9ob
+.section sf9pa
+.section sf9pb
+.section sf9qa
+.section sf9qb
+.section sf9ra
+.section sf9rb
+.section sf9sa
+.section sf9sb
+.section sf9ta
+.section sf9tb
+.section sf9ua
+.section sf9ub
+.section sf9va
+.section sf9vb
+.section sf9wa
+.section sf9wb
+.section sf9xa
+.section sf9xb
+.section sf9ya
+.section sf9yb
+.section sf9za
+.section sf9zb
+.section sf91a
+.section sf91b
+.section sf92a
+.section sf92b
+.section sf93a
+.section sf93b
+.section sf94a
+.section sf94b
+.section sf95a
+.section sf95b
+.section sf96a
+.section sf96b
+.section sf97a
+.section sf97b
+.section sf98a
+.section sf98b
+.section sf99a
+.section sf99b
+.section sf90a
+.section sf90b
+.section sf0aa
+.section sf0ab
+.section sf0ba
+.section sf0bb
+.section sf0ca
+.section sf0cb
+.section sf0da
+.section sf0db
+.section sf0ea
+.section sf0eb
+.section sf0fa
+.section sf0fb
+.section sf0ga
+.section sf0gb
+.section sf0ha
+.section sf0hb
+.section sf0ia
+.section sf0ib
+.section sf0ja
+.section sf0jb
+.section sf0ka
+.section sf0kb
+.section sf0la
+.section sf0lb
+.section sf0ma
+.section sf0mb
+.section sf0na
+.section sf0nb
+.section sf0oa
+.section sf0ob
+.section sf0pa
+.section sf0pb
+.section sf0qa
+.section sf0qb
+.section sf0ra
+.section sf0rb
+.section sf0sa
+.section sf0sb
+.section sf0ta
+.section sf0tb
+.section sf0ua
+.section sf0ub
+.section sf0va
+.section sf0vb
+.section sf0wa
+.section sf0wb
+.section sf0xa
+.section sf0xb
+.section sf0ya
+.section sf0yb
+.section sf0za
+.section sf0zb
+.section sf01a
+.section sf01b
+.section sf02a
+.section sf02b
+.section sf03a
+.section sf03b
+.section sf04a
+.section sf04b
+.section sf05a
+.section sf05b
+.section sf06a
+.section sf06b
+.section sf07a
+.section sf07b
+.section sf08a
+.section sf08b
+.section sf09a
+.section sf09b
+.section sf00a
+.section sf00b
+.section sgaaa
+.section sgaab
+.section sgaba
+.section sgabb
+.section sgaca
+.section sgacb
+.section sgada
+.section sgadb
+.section sgaea
+.section sgaeb
+.section sgafa
+.section sgafb
+.section sgaga
+.section sgagb
+.section sgaha
+.section sgahb
+.section sgaia
+.section sgaib
+.section sgaja
+.section sgajb
+.section sgaka
+.section sgakb
+.section sgala
+.section sgalb
+.section sgama
+.section sgamb
+.section sgana
+.section sganb
+.section sgaoa
+.section sgaob
+.section sgapa
+.section sgapb
+.section sgaqa
+.section sgaqb
+.section sgara
+.section sgarb
+.section sgasa
+.section sgasb
+.section sgata
+.section sgatb
+.section sgaua
+.section sgaub
+.section sgava
+.section sgavb
+.section sgawa
+.section sgawb
+.section sgaxa
+.section sgaxb
+.section sgaya
+.section sgayb
+.section sgaza
+.section sgazb
+.section sga1a
+.section sga1b
+.section sga2a
+.section sga2b
+.section sga3a
+.section sga3b
+.section sga4a
+.section sga4b
+.section sga5a
+.section sga5b
+.section sga6a
+.section sga6b
+.section sga7a
+.section sga7b
+.section sga8a
+.section sga8b
+.section sga9a
+.section sga9b
+.section sga0a
+.section sga0b
+.section sgbaa
+.section sgbab
+.section sgbba
+.section sgbbb
+.section sgbca
+.section sgbcb
+.section sgbda
+.section sgbdb
+.section sgbea
+.section sgbeb
+.section sgbfa
+.section sgbfb
+.section sgbga
+.section sgbgb
+.section sgbha
+.section sgbhb
+.section sgbia
+.section sgbib
+.section sgbja
+.section sgbjb
+.section sgbka
+.section sgbkb
+.section sgbla
+.section sgblb
+.section sgbma
+.section sgbmb
+.section sgbna
+.section sgbnb
+.section sgboa
+.section sgbob
+.section sgbpa
+.section sgbpb
+.section sgbqa
+.section sgbqb
+.section sgbra
+.section sgbrb
+.section sgbsa
+.section sgbsb
+.section sgbta
+.section sgbtb
+.section sgbua
+.section sgbub
+.section sgbva
+.section sgbvb
+.section sgbwa
+.section sgbwb
+.section sgbxa
+.section sgbxb
+.section sgbya
+.section sgbyb
+.section sgbza
+.section sgbzb
+.section sgb1a
+.section sgb1b
+.section sgb2a
+.section sgb2b
+.section sgb3a
+.section sgb3b
+.section sgb4a
+.section sgb4b
+.section sgb5a
+.section sgb5b
+.section sgb6a
+.section sgb6b
+.section sgb7a
+.section sgb7b
+.section sgb8a
+.section sgb8b
+.section sgb9a
+.section sgb9b
+.section sgb0a
+.section sgb0b
+.section sgcaa
+.section sgcab
+.section sgcba
+.section sgcbb
+.section sgcca
+.section sgccb
+.section sgcda
+.section sgcdb
+.section sgcea
+.section sgceb
+.section sgcfa
+.section sgcfb
+.section sgcga
+.section sgcgb
+.section sgcha
+.section sgchb
+.section sgcia
+.section sgcib
+.section sgcja
+.section sgcjb
+.section sgcka
+.section sgckb
+.section sgcla
+.section sgclb
+.section sgcma
+.section sgcmb
+.section sgcna
+.section sgcnb
+.section sgcoa
+.section sgcob
+.section sgcpa
+.section sgcpb
+.section sgcqa
+.section sgcqb
+.section sgcra
+.section sgcrb
+.section sgcsa
+.section sgcsb
+.section sgcta
+.section sgctb
+.section sgcua
+.section sgcub
+.section sgcva
+.section sgcvb
+.section sgcwa
+.section sgcwb
+.section sgcxa
+.section sgcxb
+.section sgcya
+.section sgcyb
+.section sgcza
+.section sgczb
+.section sgc1a
+.section sgc1b
+.section sgc2a
+.section sgc2b
+.section sgc3a
+.section sgc3b
+.section sgc4a
+.section sgc4b
+.section sgc5a
+.section sgc5b
+.section sgc6a
+.section sgc6b
+.section sgc7a
+.section sgc7b
+.section sgc8a
+.section sgc8b
+.section sgc9a
+.section sgc9b
+.section sgc0a
+.section sgc0b
+.section sgdaa
+.section sgdab
+.section sgdba
+.section sgdbb
+.section sgdca
+.section sgdcb
+.section sgdda
+.section sgddb
+.section sgdea
+.section sgdeb
+.section sgdfa
+.section sgdfb
+.section sgdga
+.section sgdgb
+.section sgdha
+.section sgdhb
+.section sgdia
+.section sgdib
+.section sgdja
+.section sgdjb
+.section sgdka
+.section sgdkb
+.section sgdla
+.section sgdlb
+.section sgdma
+.section sgdmb
+.section sgdna
+.section sgdnb
+.section sgdoa
+.section sgdob
+.section sgdpa
+.section sgdpb
+.section sgdqa
+.section sgdqb
+.section sgdra
+.section sgdrb
+.section sgdsa
+.section sgdsb
+.section sgdta
+.section sgdtb
+.section sgdua
+.section sgdub
+.section sgdva
+.section sgdvb
+.section sgdwa
+.section sgdwb
+.section sgdxa
+.section sgdxb
+.section sgdya
+.section sgdyb
+.section sgdza
+.section sgdzb
+.section sgd1a
+.section sgd1b
+.section sgd2a
+.section sgd2b
+.section sgd3a
+.section sgd3b
+.section sgd4a
+.section sgd4b
+.section sgd5a
+.section sgd5b
+.section sgd6a
+.section sgd6b
+.section sgd7a
+.section sgd7b
+.section sgd8a
+.section sgd8b
+.section sgd9a
+.section sgd9b
+.section sgd0a
+.section sgd0b
+.section sgeaa
+.section sgeab
+.section sgeba
+.section sgebb
+.section sgeca
+.section sgecb
+.section sgeda
+.section sgedb
+.section sgeea
+.section sgeeb
+.section sgefa
+.section sgefb
+.section sgega
+.section sgegb
+.section sgeha
+.section sgehb
+.section sgeia
+.section sgeib
+.section sgeja
+.section sgejb
+.section sgeka
+.section sgekb
+.section sgela
+.section sgelb
+.section sgema
+.section sgemb
+.section sgena
+.section sgenb
+.section sgeoa
+.section sgeob
+.section sgepa
+.section sgepb
+.section sgeqa
+.section sgeqb
+.section sgera
+.section sgerb
+.section sgesa
+.section sgesb
+.section sgeta
+.section sgetb
+.section sgeua
+.section sgeub
+.section sgeva
+.section sgevb
+.section sgewa
+.section sgewb
+.section sgexa
+.section sgexb
+.section sgeya
+.section sgeyb
+.section sgeza
+.section sgezb
+.section sge1a
+.section sge1b
+.section sge2a
+.section sge2b
+.section sge3a
+.section sge3b
+.section sge4a
+.section sge4b
+.section sge5a
+.section sge5b
+.section sge6a
+.section sge6b
+.section sge7a
+.section sge7b
+.section sge8a
+.section sge8b
+.section sge9a
+.section sge9b
+.section sge0a
+.section sge0b
+.section sgfaa
+.section sgfab
+.section sgfba
+.section sgfbb
+.section sgfca
+.section sgfcb
+.section sgfda
+.section sgfdb
+.section sgfea
+.section sgfeb
+.section sgffa
+.section sgffb
+.section sgfga
+.section sgfgb
+.section sgfha
+.section sgfhb
+.section sgfia
+.section sgfib
+.section sgfja
+.section sgfjb
+.section sgfka
+.section sgfkb
+.section sgfla
+.section sgflb
+.section sgfma
+.section sgfmb
+.section sgfna
+.section sgfnb
+.section sgfoa
+.section sgfob
+.section sgfpa
+.section sgfpb
+.section sgfqa
+.section sgfqb
+.section sgfra
+.section sgfrb
+.section sgfsa
+.section sgfsb
+.section sgfta
+.section sgftb
+.section sgfua
+.section sgfub
+.section sgfva
+.section sgfvb
+.section sgfwa
+.section sgfwb
+.section sgfxa
+.section sgfxb
+.section sgfya
+.section sgfyb
+.section sgfza
+.section sgfzb
+.section sgf1a
+.section sgf1b
+.section sgf2a
+.section sgf2b
+.section sgf3a
+.section sgf3b
+.section sgf4a
+.section sgf4b
+.section sgf5a
+.section sgf5b
+.section sgf6a
+.section sgf6b
+.section sgf7a
+.section sgf7b
+.section sgf8a
+.section sgf8b
+.section sgf9a
+.section sgf9b
+.section sgf0a
+.section sgf0b
+.section sggaa
+.section sggab
+.section sggba
+.section sggbb
+.section sggca
+.section sggcb
+.section sggda
+.section sggdb
+.section sggea
+.section sggeb
+.section sggfa
+.section sggfb
+.section sggga
+.section sgggb
+.section sggha
+.section sgghb
+.section sggia
+.section sggib
+.section sggja
+.section sggjb
+.section sggka
+.section sggkb
+.section sggla
+.section sgglb
+.section sggma
+.section sggmb
+.section sggna
+.section sggnb
+.section sggoa
+.section sggob
+.section sggpa
+.section sggpb
+.section sggqa
+.section sggqb
+.section sggra
+.section sggrb
+.section sggsa
+.section sggsb
+.section sggta
+.section sggtb
+.section sggua
+.section sggub
+.section sggva
+.section sggvb
+.section sggwa
+.section sggwb
+.section sggxa
+.section sggxb
+.section sggya
+.section sggyb
+.section sggza
+.section sggzb
+.section sgg1a
+.section sgg1b
+.section sgg2a
+.section sgg2b
+.section sgg3a
+.section sgg3b
+.section sgg4a
+.section sgg4b
+.section sgg5a
+.section sgg5b
+.section sgg6a
+.section sgg6b
+.section sgg7a
+.section sgg7b
+.section sgg8a
+.section sgg8b
+.section sgg9a
+.section sgg9b
+.section sgg0a
+.section sgg0b
+.section sghaa
+.section sghab
+.section sghba
+.section sghbb
+.section sghca
+.section sghcb
+.section sghda
+.section sghdb
+.section sghea
+.section sgheb
+.section sghfa
+.section sghfb
+.section sghga
+.section sghgb
+.section sghha
+.section sghhb
+.section sghia
+.section sghib
+.section sghja
+.section sghjb
+.section sghka
+.section sghkb
+.section sghla
+.section sghlb
+.section sghma
+.section sghmb
+.section sghna
+.section sghnb
+.section sghoa
+.section sghob
+.section sghpa
+.section sghpb
+.section sghqa
+.section sghqb
+.section sghra
+.section sghrb
+.section sghsa
+.section sghsb
+.section sghta
+.section sghtb
+.section sghua
+.section sghub
+.section sghva
+.section sghvb
+.section sghwa
+.section sghwb
+.section sghxa
+.section sghxb
+.section sghya
+.section sghyb
+.section sghza
+.section sghzb
+.section sgh1a
+.section sgh1b
+.section sgh2a
+.section sgh2b
+.section sgh3a
+.section sgh3b
+.section sgh4a
+.section sgh4b
+.section sgh5a
+.section sgh5b
+.section sgh6a
+.section sgh6b
+.section sgh7a
+.section sgh7b
+.section sgh8a
+.section sgh8b
+.section sgh9a
+.section sgh9b
+.section sgh0a
+.section sgh0b
+.section sgiaa
+.section sgiab
+.section sgiba
+.section sgibb
+.section sgica
+.section sgicb
+.section sgida
+.section sgidb
+.section sgiea
+.section sgieb
+.section sgifa
+.section sgifb
+.section sgiga
+.section sgigb
+.section sgiha
+.section sgihb
+.section sgiia
+.section sgiib
+.section sgija
+.section sgijb
+.section sgika
+.section sgikb
+.section sgila
+.section sgilb
+.section sgima
+.section sgimb
+.section sgina
+.section sginb
+.section sgioa
+.section sgiob
+.section sgipa
+.section sgipb
+.section sgiqa
+.section sgiqb
+.section sgira
+.section sgirb
+.section sgisa
+.section sgisb
+.section sgita
+.section sgitb
+.section sgiua
+.section sgiub
+.section sgiva
+.section sgivb
+.section sgiwa
+.section sgiwb
+.section sgixa
+.section sgixb
+.section sgiya
+.section sgiyb
+.section sgiza
+.section sgizb
+.section sgi1a
+.section sgi1b
+.section sgi2a
+.section sgi2b
+.section sgi3a
+.section sgi3b
+.section sgi4a
+.section sgi4b
+.section sgi5a
+.section sgi5b
+.section sgi6a
+.section sgi6b
+.section sgi7a
+.section sgi7b
+.section sgi8a
+.section sgi8b
+.section sgi9a
+.section sgi9b
+.section sgi0a
+.section sgi0b
+.section sgjaa
+.section sgjab
+.section sgjba
+.section sgjbb
+.section sgjca
+.section sgjcb
+.section sgjda
+.section sgjdb
+.section sgjea
+.section sgjeb
+.section sgjfa
+.section sgjfb
+.section sgjga
+.section sgjgb
+.section sgjha
+.section sgjhb
+.section sgjia
+.section sgjib
+.section sgjja
+.section sgjjb
+.section sgjka
+.section sgjkb
+.section sgjla
+.section sgjlb
+.section sgjma
+.section sgjmb
+.section sgjna
+.section sgjnb
+.section sgjoa
+.section sgjob
+.section sgjpa
+.section sgjpb
+.section sgjqa
+.section sgjqb
+.section sgjra
+.section sgjrb
+.section sgjsa
+.section sgjsb
+.section sgjta
+.section sgjtb
+.section sgjua
+.section sgjub
+.section sgjva
+.section sgjvb
+.section sgjwa
+.section sgjwb
+.section sgjxa
+.section sgjxb
+.section sgjya
+.section sgjyb
+.section sgjza
+.section sgjzb
+.section sgj1a
+.section sgj1b
+.section sgj2a
+.section sgj2b
+.section sgj3a
+.section sgj3b
+.section sgj4a
+.section sgj4b
+.section sgj5a
+.section sgj5b
+.section sgj6a
+.section sgj6b
+.section sgj7a
+.section sgj7b
+.section sgj8a
+.section sgj8b
+.section sgj9a
+.section sgj9b
+.section sgj0a
+.section sgj0b
+.section sgkaa
+.section sgkab
+.section sgkba
+.section sgkbb
+.section sgkca
+.section sgkcb
+.section sgkda
+.section sgkdb
+.section sgkea
+.section sgkeb
+.section sgkfa
+.section sgkfb
+.section sgkga
+.section sgkgb
+.section sgkha
+.section sgkhb
+.section sgkia
+.section sgkib
+.section sgkja
+.section sgkjb
+.section sgkka
+.section sgkkb
+.section sgkla
+.section sgklb
+.section sgkma
+.section sgkmb
+.section sgkna
+.section sgknb
+.section sgkoa
+.section sgkob
+.section sgkpa
+.section sgkpb
+.section sgkqa
+.section sgkqb
+.section sgkra
+.section sgkrb
+.section sgksa
+.section sgksb
+.section sgkta
+.section sgktb
+.section sgkua
+.section sgkub
+.section sgkva
+.section sgkvb
+.section sgkwa
+.section sgkwb
+.section sgkxa
+.section sgkxb
+.section sgkya
+.section sgkyb
+.section sgkza
+.section sgkzb
+.section sgk1a
+.section sgk1b
+.section sgk2a
+.section sgk2b
+.section sgk3a
+.section sgk3b
+.section sgk4a
+.section sgk4b
+.section sgk5a
+.section sgk5b
+.section sgk6a
+.section sgk6b
+.section sgk7a
+.section sgk7b
+.section sgk8a
+.section sgk8b
+.section sgk9a
+.section sgk9b
+.section sgk0a
+.section sgk0b
+.section sglaa
+.section sglab
+.section sglba
+.section sglbb
+.section sglca
+.section sglcb
+.section sglda
+.section sgldb
+.section sglea
+.section sgleb
+.section sglfa
+.section sglfb
+.section sglga
+.section sglgb
+.section sglha
+.section sglhb
+.section sglia
+.section sglib
+.section sglja
+.section sgljb
+.section sglka
+.section sglkb
+.section sglla
+.section sgllb
+.section sglma
+.section sglmb
+.section sglna
+.section sglnb
+.section sgloa
+.section sglob
+.section sglpa
+.section sglpb
+.section sglqa
+.section sglqb
+.section sglra
+.section sglrb
+.section sglsa
+.section sglsb
+.section sglta
+.section sgltb
+.section sglua
+.section sglub
+.section sglva
+.section sglvb
+.section sglwa
+.section sglwb
+.section sglxa
+.section sglxb
+.section sglya
+.section sglyb
+.section sglza
+.section sglzb
+.section sgl1a
+.section sgl1b
+.section sgl2a
+.section sgl2b
+.section sgl3a
+.section sgl3b
+.section sgl4a
+.section sgl4b
+.section sgl5a
+.section sgl5b
+.section sgl6a
+.section sgl6b
+.section sgl7a
+.section sgl7b
+.section sgl8a
+.section sgl8b
+.section sgl9a
+.section sgl9b
+.section sgl0a
+.section sgl0b
+.section sgmaa
+.section sgmab
+.section sgmba
+.section sgmbb
+.section sgmca
+.section sgmcb
+.section sgmda
+.section sgmdb
+.section sgmea
+.section sgmeb
+.section sgmfa
+.section sgmfb
+.section sgmga
+.section sgmgb
+.section sgmha
+.section sgmhb
+.section sgmia
+.section sgmib
+.section sgmja
+.section sgmjb
+.section sgmka
+.section sgmkb
+.section sgmla
+.section sgmlb
+.section sgmma
+.section sgmmb
+.section sgmna
+.section sgmnb
+.section sgmoa
+.section sgmob
+.section sgmpa
+.section sgmpb
+.section sgmqa
+.section sgmqb
+.section sgmra
+.section sgmrb
+.section sgmsa
+.section sgmsb
+.section sgmta
+.section sgmtb
+.section sgmua
+.section sgmub
+.section sgmva
+.section sgmvb
+.section sgmwa
+.section sgmwb
+.section sgmxa
+.section sgmxb
+.section sgmya
+.section sgmyb
+.section sgmza
+.section sgmzb
+.section sgm1a
+.section sgm1b
+.section sgm2a
+.section sgm2b
+.section sgm3a
+.section sgm3b
+.section sgm4a
+.section sgm4b
+.section sgm5a
+.section sgm5b
+.section sgm6a
+.section sgm6b
+.section sgm7a
+.section sgm7b
+.section sgm8a
+.section sgm8b
+.section sgm9a
+.section sgm9b
+.section sgm0a
+.section sgm0b
+.section sgnaa
+.section sgnab
+.section sgnba
+.section sgnbb
+.section sgnca
+.section sgncb
+.section sgnda
+.section sgndb
+.section sgnea
+.section sgneb
+.section sgnfa
+.section sgnfb
+.section sgnga
+.section sgngb
+.section sgnha
+.section sgnhb
+.section sgnia
+.section sgnib
+.section sgnja
+.section sgnjb
+.section sgnka
+.section sgnkb
+.section sgnla
+.section sgnlb
+.section sgnma
+.section sgnmb
+.section sgnna
+.section sgnnb
+.section sgnoa
+.section sgnob
+.section sgnpa
+.section sgnpb
+.section sgnqa
+.section sgnqb
+.section sgnra
+.section sgnrb
+.section sgnsa
+.section sgnsb
+.section sgnta
+.section sgntb
+.section sgnua
+.section sgnub
+.section sgnva
+.section sgnvb
+.section sgnwa
+.section sgnwb
+.section sgnxa
+.section sgnxb
+.section sgnya
+.section sgnyb
+.section sgnza
+.section sgnzb
+.section sgn1a
+.section sgn1b
+.section sgn2a
+.section sgn2b
+.section sgn3a
+.section sgn3b
+.section sgn4a
+.section sgn4b
+.section sgn5a
+.section sgn5b
+.section sgn6a
+.section sgn6b
+.section sgn7a
+.section sgn7b
+.section sgn8a
+.section sgn8b
+.section sgn9a
+.section sgn9b
+.section sgn0a
+.section sgn0b
+.section sgoaa
+.section sgoab
+.section sgoba
+.section sgobb
+.section sgoca
+.section sgocb
+.section sgoda
+.section sgodb
+.section sgoea
+.section sgoeb
+.section sgofa
+.section sgofb
+.section sgoga
+.section sgogb
+.section sgoha
+.section sgohb
+.section sgoia
+.section sgoib
+.section sgoja
+.section sgojb
+.section sgoka
+.section sgokb
+.section sgola
+.section sgolb
+.section sgoma
+.section sgomb
+.section sgona
+.section sgonb
+.section sgooa
+.section sgoob
+.section sgopa
+.section sgopb
+.section sgoqa
+.section sgoqb
+.section sgora
+.section sgorb
+.section sgosa
+.section sgosb
+.section sgota
+.section sgotb
+.section sgoua
+.section sgoub
+.section sgova
+.section sgovb
+.section sgowa
+.section sgowb
+.section sgoxa
+.section sgoxb
+.section sgoya
+.section sgoyb
+.section sgoza
+.section sgozb
+.section sgo1a
+.section sgo1b
+.section sgo2a
+.section sgo2b
+.section sgo3a
+.section sgo3b
+.section sgo4a
+.section sgo4b
+.section sgo5a
+.section sgo5b
+.section sgo6a
+.section sgo6b
+.section sgo7a
+.section sgo7b
+.section sgo8a
+.section sgo8b
+.section sgo9a
+.section sgo9b
+.section sgo0a
+.section sgo0b
+.section sgpaa
+.section sgpab
+.section sgpba
+.section sgpbb
+.section sgpca
+.section sgpcb
+.section sgpda
+.section sgpdb
+.section sgpea
+.section sgpeb
+.section sgpfa
+.section sgpfb
+.section sgpga
+.section sgpgb
+.section sgpha
+.section sgphb
+.section sgpia
+.section sgpib
+.section sgpja
+.section sgpjb
+.section sgpka
+.section sgpkb
+.section sgpla
+.section sgplb
+.section sgpma
+.section sgpmb
+.section sgpna
+.section sgpnb
+.section sgpoa
+.section sgpob
+.section sgppa
+.section sgppb
+.section sgpqa
+.section sgpqb
+.section sgpra
+.section sgprb
+.section sgpsa
+.section sgpsb
+.section sgpta
+.section sgptb
+.section sgpua
+.section sgpub
+.section sgpva
+.section sgpvb
+.section sgpwa
+.section sgpwb
+.section sgpxa
+.section sgpxb
+.section sgpya
+.section sgpyb
+.section sgpza
+.section sgpzb
+.section sgp1a
+.section sgp1b
+.section sgp2a
+.section sgp2b
+.section sgp3a
+.section sgp3b
+.section sgp4a
+.section sgp4b
+.section sgp5a
+.section sgp5b
+.section sgp6a
+.section sgp6b
+.section sgp7a
+.section sgp7b
+.section sgp8a
+.section sgp8b
+.section sgp9a
+.section sgp9b
+.section sgp0a
+.section sgp0b
+.section sgqaa
+.section sgqab
+.section sgqba
+.section sgqbb
+.section sgqca
+.section sgqcb
+.section sgqda
+.section sgqdb
+.section sgqea
+.section sgqeb
+.section sgqfa
+.section sgqfb
+.section sgqga
+.section sgqgb
+.section sgqha
+.section sgqhb
+.section sgqia
+.section sgqib
+.section sgqja
+.section sgqjb
+.section sgqka
+.section sgqkb
+.section sgqla
+.section sgqlb
+.section sgqma
+.section sgqmb
+.section sgqna
+.section sgqnb
+.section sgqoa
+.section sgqob
+.section sgqpa
+.section sgqpb
+.section sgqqa
+.section sgqqb
+.section sgqra
+.section sgqrb
+.section sgqsa
+.section sgqsb
+.section sgqta
+.section sgqtb
+.section sgqua
+.section sgqub
+.section sgqva
+.section sgqvb
+.section sgqwa
+.section sgqwb
+.section sgqxa
+.section sgqxb
+.section sgqya
+.section sgqyb
+.section sgqza
+.section sgqzb
+.section sgq1a
+.section sgq1b
+.section sgq2a
+.section sgq2b
+.section sgq3a
+.section sgq3b
+.section sgq4a
+.section sgq4b
+.section sgq5a
+.section sgq5b
+.section sgq6a
+.section sgq6b
+.section sgq7a
+.section sgq7b
+.section sgq8a
+.section sgq8b
+.section sgq9a
+.section sgq9b
+.section sgq0a
+.section sgq0b
+.section sgraa
+.section sgrab
+.section sgrba
+.section sgrbb
+.section sgrca
+.section sgrcb
+.section sgrda
+.section sgrdb
+.section sgrea
+.section sgreb
+.section sgrfa
+.section sgrfb
+.section sgrga
+.section sgrgb
+.section sgrha
+.section sgrhb
+.section sgria
+.section sgrib
+.section sgrja
+.section sgrjb
+.section sgrka
+.section sgrkb
+.section sgrla
+.section sgrlb
+.section sgrma
+.section sgrmb
+.section sgrna
+.section sgrnb
+.section sgroa
+.section sgrob
+.section sgrpa
+.section sgrpb
+.section sgrqa
+.section sgrqb
+.section sgrra
+.section sgrrb
+.section sgrsa
+.section sgrsb
+.section sgrta
+.section sgrtb
+.section sgrua
+.section sgrub
+.section sgrva
+.section sgrvb
+.section sgrwa
+.section sgrwb
+.section sgrxa
+.section sgrxb
+.section sgrya
+.section sgryb
+.section sgrza
+.section sgrzb
+.section sgr1a
+.section sgr1b
+.section sgr2a
+.section sgr2b
+.section sgr3a
+.section sgr3b
+.section sgr4a
+.section sgr4b
+.section sgr5a
+.section sgr5b
+.section sgr6a
+.section sgr6b
+.section sgr7a
+.section sgr7b
+.section sgr8a
+.section sgr8b
+.section sgr9a
+.section sgr9b
+.section sgr0a
+.section sgr0b
+.section sgsaa
+.section sgsab
+.section sgsba
+.section sgsbb
+.section sgsca
+.section sgscb
+.section sgsda
+.section sgsdb
+.section sgsea
+.section sgseb
+.section sgsfa
+.section sgsfb
+.section sgsga
+.section sgsgb
+.section sgsha
+.section sgshb
+.section sgsia
+.section sgsib
+.section sgsja
+.section sgsjb
+.section sgska
+.section sgskb
+.section sgsla
+.section sgslb
+.section sgsma
+.section sgsmb
+.section sgsna
+.section sgsnb
+.section sgsoa
+.section sgsob
+.section sgspa
+.section sgspb
+.section sgsqa
+.section sgsqb
+.section sgsra
+.section sgsrb
+.section sgssa
+.section sgssb
+.section sgsta
+.section sgstb
+.section sgsua
+.section sgsub
+.section sgsva
+.section sgsvb
+.section sgswa
+.section sgswb
+.section sgsxa
+.section sgsxb
+.section sgsya
+.section sgsyb
+.section sgsza
+.section sgszb
+.section sgs1a
+.section sgs1b
+.section sgs2a
+.section sgs2b
+.section sgs3a
+.section sgs3b
+.section sgs4a
+.section sgs4b
+.section sgs5a
+.section sgs5b
+.section sgs6a
+.section sgs6b
+.section sgs7a
+.section sgs7b
+.section sgs8a
+.section sgs8b
+.section sgs9a
+.section sgs9b
+.section sgs0a
+.section sgs0b
+.section sgtaa
+.section sgtab
+.section sgtba
+.section sgtbb
+.section sgtca
+.section sgtcb
+.section sgtda
+.section sgtdb
+.section sgtea
+.section sgteb
+.section sgtfa
+.section sgtfb
+.section sgtga
+.section sgtgb
+.section sgtha
+.section sgthb
+.section sgtia
+.section sgtib
+.section sgtja
+.section sgtjb
+.section sgtka
+.section sgtkb
+.section sgtla
+.section sgtlb
+.section sgtma
+.section sgtmb
+.section sgtna
+.section sgtnb
+.section sgtoa
+.section sgtob
+.section sgtpa
+.section sgtpb
+.section sgtqa
+.section sgtqb
+.section sgtra
+.section sgtrb
+.section sgtsa
+.section sgtsb
+.section sgtta
+.section sgttb
+.section sgtua
+.section sgtub
+.section sgtva
+.section sgtvb
+.section sgtwa
+.section sgtwb
+.section sgtxa
+.section sgtxb
+.section sgtya
+.section sgtyb
+.section sgtza
+.section sgtzb
+.section sgt1a
+.section sgt1b
+.section sgt2a
+.section sgt2b
+.section sgt3a
+.section sgt3b
+.section sgt4a
+.section sgt4b
+.section sgt5a
+.section sgt5b
+.section sgt6a
+.section sgt6b
+.section sgt7a
+.section sgt7b
+.section sgt8a
+.section sgt8b
+.section sgt9a
+.section sgt9b
+.section sgt0a
+.section sgt0b
+.section sguaa
+.section sguab
+.section sguba
+.section sgubb
+.section sguca
+.section sgucb
+.section sguda
+.section sgudb
+.section sguea
+.section sgueb
+.section sgufa
+.section sgufb
+.section sguga
+.section sgugb
+.section sguha
+.section sguhb
+.section sguia
+.section sguib
+.section sguja
+.section sgujb
+.section sguka
+.section sgukb
+.section sgula
+.section sgulb
+.section sguma
+.section sgumb
+.section sguna
+.section sgunb
+.section sguoa
+.section sguob
+.section sgupa
+.section sgupb
+.section sguqa
+.section sguqb
+.section sgura
+.section sgurb
+.section sgusa
+.section sgusb
+.section sguta
+.section sgutb
+.section sguua
+.section sguub
+.section sguva
+.section sguvb
+.section sguwa
+.section sguwb
+.section sguxa
+.section sguxb
+.section sguya
+.section sguyb
+.section sguza
+.section sguzb
+.section sgu1a
+.section sgu1b
+.section sgu2a
+.section sgu2b
+.section sgu3a
+.section sgu3b
+.section sgu4a
+.section sgu4b
+.section sgu5a
+.section sgu5b
+.section sgu6a
+.section sgu6b
+.section sgu7a
+.section sgu7b
+.section sgu8a
+.section sgu8b
+.section sgu9a
+.section sgu9b
+.section sgu0a
+.section sgu0b
+.section sgvaa
+.section sgvab
+.section sgvba
+.section sgvbb
+.section sgvca
+.section sgvcb
+.section sgvda
+.section sgvdb
+.section sgvea
+.section sgveb
+.section sgvfa
+.section sgvfb
+.section sgvga
+.section sgvgb
+.section sgvha
+.section sgvhb
+.section sgvia
+.section sgvib
+.section sgvja
+.section sgvjb
+.section sgvka
+.section sgvkb
+.section sgvla
+.section sgvlb
+.section sgvma
+.section sgvmb
+.section sgvna
+.section sgvnb
+.section sgvoa
+.section sgvob
+.section sgvpa
+.section sgvpb
+.section sgvqa
+.section sgvqb
+.section sgvra
+.section sgvrb
+.section sgvsa
+.section sgvsb
+.section sgvta
+.section sgvtb
+.section sgvua
+.section sgvub
+.section sgvva
+.section sgvvb
+.section sgvwa
+.section sgvwb
+.section sgvxa
+.section sgvxb
+.section sgvya
+.section sgvyb
+.section sgvza
+.section sgvzb
+.section sgv1a
+.section sgv1b
+.section sgv2a
+.section sgv2b
+.section sgv3a
+.section sgv3b
+.section sgv4a
+.section sgv4b
+.section sgv5a
+.section sgv5b
+.section sgv6a
+.section sgv6b
+.section sgv7a
+.section sgv7b
+.section sgv8a
+.section sgv8b
+.section sgv9a
+.section sgv9b
+.section sgv0a
+.section sgv0b
+.section sgwaa
+.section sgwab
+.section sgwba
+.section sgwbb
+.section sgwca
+.section sgwcb
+.section sgwda
+.section sgwdb
+.section sgwea
+.section sgweb
+.section sgwfa
+.section sgwfb
+.section sgwga
+.section sgwgb
+.section sgwha
+.section sgwhb
+.section sgwia
+.section sgwib
+.section sgwja
+.section sgwjb
+.section sgwka
+.section sgwkb
+.section sgwla
+.section sgwlb
+.section sgwma
+.section sgwmb
+.section sgwna
+.section sgwnb
+.section sgwoa
+.section sgwob
+.section sgwpa
+.section sgwpb
+.section sgwqa
+.section sgwqb
+.section sgwra
+.section sgwrb
+.section sgwsa
+.section sgwsb
+.section sgwta
+.section sgwtb
+.section sgwua
+.section sgwub
+.section sgwva
+.section sgwvb
+.section sgwwa
+.section sgwwb
+.section sgwxa
+.section sgwxb
+.section sgwya
+.section sgwyb
+.section sgwza
+.section sgwzb
+.section sgw1a
+.section sgw1b
+.section sgw2a
+.section sgw2b
+.section sgw3a
+.section sgw3b
+.section sgw4a
+.section sgw4b
+.section sgw5a
+.section sgw5b
+.section sgw6a
+.section sgw6b
+.section sgw7a
+.section sgw7b
+.section sgw8a
+.section sgw8b
+.section sgw9a
+.section sgw9b
+.section sgw0a
+.section sgw0b
+.section sgxaa
+.section sgxab
+.section sgxba
+.section sgxbb
+.section sgxca
+.section sgxcb
+.section sgxda
+.section sgxdb
+.section sgxea
+.section sgxeb
+.section sgxfa
+.section sgxfb
+.section sgxga
+.section sgxgb
+.section sgxha
+.section sgxhb
+.section sgxia
+.section sgxib
+.section sgxja
+.section sgxjb
+.section sgxka
+.section sgxkb
+.section sgxla
+.section sgxlb
+.section sgxma
+.section sgxmb
+.section sgxna
+.section sgxnb
+.section sgxoa
+.section sgxob
+.section sgxpa
+.section sgxpb
+.section sgxqa
+.section sgxqb
+.section sgxra
+.section sgxrb
+.section sgxsa
+.section sgxsb
+.section sgxta
+.section sgxtb
+.section sgxua
+.section sgxub
+.section sgxva
+.section sgxvb
+.section sgxwa
+.section sgxwb
+.section sgxxa
+.section sgxxb
+.section sgxya
+.section sgxyb
+.section sgxza
+.section sgxzb
+.section sgx1a
+.section sgx1b
+.section sgx2a
+.section sgx2b
+.section sgx3a
+.section sgx3b
+.section sgx4a
+.section sgx4b
+.section sgx5a
+.section sgx5b
+.section sgx6a
+.section sgx6b
+.section sgx7a
+.section sgx7b
+.section sgx8a
+.section sgx8b
+.section sgx9a
+.section sgx9b
+.section sgx0a
+.section sgx0b
+.section sgyaa
+.section sgyab
+.section sgyba
+.section sgybb
+.section sgyca
+.section sgycb
+.section sgyda
+.section sgydb
+.section sgyea
+.section sgyeb
+.section sgyfa
+.section sgyfb
+.section sgyga
+.section sgygb
+.section sgyha
+.section sgyhb
+.section sgyia
+.section sgyib
+.section sgyja
+.section sgyjb
+.section sgyka
+.section sgykb
+.section sgyla
+.section sgylb
+.section sgyma
+.section sgymb
+.section sgyna
+.section sgynb
+.section sgyoa
+.section sgyob
+.section sgypa
+.section sgypb
+.section sgyqa
+.section sgyqb
+.section sgyra
+.section sgyrb
+.section sgysa
+.section sgysb
+.section sgyta
+.section sgytb
+.section sgyua
+.section sgyub
+.section sgyva
+.section sgyvb
+.section sgywa
+.section sgywb
+.section sgyxa
+.section sgyxb
+.section sgyya
+.section sgyyb
+.section sgyza
+.section sgyzb
+.section sgy1a
+.section sgy1b
+.section sgy2a
+.section sgy2b
+.section sgy3a
+.section sgy3b
+.section sgy4a
+.section sgy4b
+.section sgy5a
+.section sgy5b
+.section sgy6a
+.section sgy6b
+.section sgy7a
+.section sgy7b
+.section sgy8a
+.section sgy8b
+.section sgy9a
+.section sgy9b
+.section sgy0a
+.section sgy0b
+.section sgzaa
+.section sgzab
+.section sgzba
+.section sgzbb
+.section sgzca
+.section sgzcb
+.section sgzda
+.section sgzdb
+.section sgzea
+.section sgzeb
+.section sgzfa
+.section sgzfb
+.section sgzga
+.section sgzgb
+.section sgzha
+.section sgzhb
+.section sgzia
+.section sgzib
+.section sgzja
+.section sgzjb
+.section sgzka
+.section sgzkb
+.section sgzla
+.section sgzlb
+.section sgzma
+.section sgzmb
+.section sgzna
+.section sgznb
+.section sgzoa
+.section sgzob
+.section sgzpa
+.section sgzpb
+.section sgzqa
+.section sgzqb
+.section sgzra
+.section sgzrb
+.section sgzsa
+.section sgzsb
+.section sgzta
+.section sgztb
+.section sgzua
+.section sgzub
+.section sgzva
+.section sgzvb
+.section sgzwa
+.section sgzwb
+.section sgzxa
+.section sgzxb
+.section sgzya
+.section sgzyb
+.section sgzza
+.section sgzzb
+.section sgz1a
+.section sgz1b
+.section sgz2a
+.section sgz2b
+.section sgz3a
+.section sgz3b
+.section sgz4a
+.section sgz4b
+.section sgz5a
+.section sgz5b
+.section sgz6a
+.section sgz6b
+.section sgz7a
+.section sgz7b
+.section sgz8a
+.section sgz8b
+.section sgz9a
+.section sgz9b
+.section sgz0a
+.section sgz0b
+.section sg1aa
+.section sg1ab
+.section sg1ba
+.section sg1bb
+.section sg1ca
+.section sg1cb
+.section sg1da
+.section sg1db
+.section sg1ea
+.section sg1eb
+.section sg1fa
+.section sg1fb
+.section sg1ga
+.section sg1gb
+.section sg1ha
+.section sg1hb
+.section sg1ia
+.section sg1ib
+.section sg1ja
+.section sg1jb
+.section sg1ka
+.section sg1kb
+.section sg1la
+.section sg1lb
+.section sg1ma
+.section sg1mb
+.section sg1na
+.section sg1nb
+.section sg1oa
+.section sg1ob
+.section sg1pa
+.section sg1pb
+.section sg1qa
+.section sg1qb
+.section sg1ra
+.section sg1rb
+.section sg1sa
+.section sg1sb
+.section sg1ta
+.section sg1tb
+.section sg1ua
+.section sg1ub
+.section sg1va
+.section sg1vb
+.section sg1wa
+.section sg1wb
+.section sg1xa
+.section sg1xb
+.section sg1ya
+.section sg1yb
+.section sg1za
+.section sg1zb
+.section sg11a
+.section sg11b
+.section sg12a
+.section sg12b
+.section sg13a
+.section sg13b
+.section sg14a
+.section sg14b
+.section sg15a
+.section sg15b
+.section sg16a
+.section sg16b
+.section sg17a
+.section sg17b
+.section sg18a
+.section sg18b
+.section sg19a
+.section sg19b
+.section sg10a
+.section sg10b
+.section sg2aa
+.section sg2ab
+.section sg2ba
+.section sg2bb
+.section sg2ca
+.section sg2cb
+.section sg2da
+.section sg2db
+.section sg2ea
+.section sg2eb
+.section sg2fa
+.section sg2fb
+.section sg2ga
+.section sg2gb
+.section sg2ha
+.section sg2hb
+.section sg2ia
+.section sg2ib
+.section sg2ja
+.section sg2jb
+.section sg2ka
+.section sg2kb
+.section sg2la
+.section sg2lb
+.section sg2ma
+.section sg2mb
+.section sg2na
+.section sg2nb
+.section sg2oa
+.section sg2ob
+.section sg2pa
+.section sg2pb
+.section sg2qa
+.section sg2qb
+.section sg2ra
+.section sg2rb
+.section sg2sa
+.section sg2sb
+.section sg2ta
+.section sg2tb
+.section sg2ua
+.section sg2ub
+.section sg2va
+.section sg2vb
+.section sg2wa
+.section sg2wb
+.section sg2xa
+.section sg2xb
+.section sg2ya
+.section sg2yb
+.section sg2za
+.section sg2zb
+.section sg21a
+.section sg21b
+.section sg22a
+.section sg22b
+.section sg23a
+.section sg23b
+.section sg24a
+.section sg24b
+.section sg25a
+.section sg25b
+.section sg26a
+.section sg26b
+.section sg27a
+.section sg27b
+.section sg28a
+.section sg28b
+.section sg29a
+.section sg29b
+.section sg20a
+.section sg20b
+.section sg3aa
+.section sg3ab
+.section sg3ba
+.section sg3bb
+.section sg3ca
+.section sg3cb
+.section sg3da
+.section sg3db
+.section sg3ea
+.section sg3eb
+.section sg3fa
+.section sg3fb
+.section sg3ga
+.section sg3gb
+.section sg3ha
+.section sg3hb
+.section sg3ia
+.section sg3ib
+.section sg3ja
+.section sg3jb
+.section sg3ka
+.section sg3kb
+.section sg3la
+.section sg3lb
+.section sg3ma
+.section sg3mb
+.section sg3na
+.section sg3nb
+.section sg3oa
+.section sg3ob
+.section sg3pa
+.section sg3pb
+.section sg3qa
+.section sg3qb
+.section sg3ra
+.section sg3rb
+.section sg3sa
+.section sg3sb
+.section sg3ta
+.section sg3tb
+.section sg3ua
+.section sg3ub
+.section sg3va
+.section sg3vb
+.section sg3wa
+.section sg3wb
+.section sg3xa
+.section sg3xb
+.section sg3ya
+.section sg3yb
+.section sg3za
+.section sg3zb
+.section sg31a
+.section sg31b
+.section sg32a
+.section sg32b
+.section sg33a
+.section sg33b
+.section sg34a
+.section sg34b
+.section sg35a
+.section sg35b
+.section sg36a
+.section sg36b
+.section sg37a
+.section sg37b
+.section sg38a
+.section sg38b
+.section sg39a
+.section sg39b
+.section sg30a
+.section sg30b
+.section sg4aa
+.section sg4ab
+.section sg4ba
+.section sg4bb
+.section sg4ca
+.section sg4cb
+.section sg4da
+.section sg4db
+.section sg4ea
+.section sg4eb
+.section sg4fa
+.section sg4fb
+.section sg4ga
+.section sg4gb
+.section sg4ha
+.section sg4hb
+.section sg4ia
+.section sg4ib
+.section sg4ja
+.section sg4jb
+.section sg4ka
+.section sg4kb
+.section sg4la
+.section sg4lb
+.section sg4ma
+.section sg4mb
+.section sg4na
+.section sg4nb
+.section sg4oa
+.section sg4ob
+.section sg4pa
+.section sg4pb
+.section sg4qa
+.section sg4qb
+.section sg4ra
+.section sg4rb
+.section sg4sa
+.section sg4sb
+.section sg4ta
+.section sg4tb
+.section sg4ua
+.section sg4ub
+.section sg4va
+.section sg4vb
+.section sg4wa
+.section sg4wb
+.section sg4xa
+.section sg4xb
+.section sg4ya
+.section sg4yb
+.section sg4za
+.section sg4zb
+.section sg41a
+.section sg41b
+.section sg42a
+.section sg42b
+.section sg43a
+.section sg43b
+.section sg44a
+.section sg44b
+.section sg45a
+.section sg45b
+.section sg46a
+.section sg46b
+.section sg47a
+.section sg47b
+.section sg48a
+.section sg48b
+.section sg49a
+.section sg49b
+.section sg40a
+.section sg40b
+.section sg5aa
+.section sg5ab
+.section sg5ba
+.section sg5bb
+.section sg5ca
+.section sg5cb
+.section sg5da
+.section sg5db
+.section sg5ea
+.section sg5eb
+.section sg5fa
+.section sg5fb
+.section sg5ga
+.section sg5gb
+.section sg5ha
+.section sg5hb
+.section sg5ia
+.section sg5ib
+.section sg5ja
+.section sg5jb
+.section sg5ka
+.section sg5kb
+.section sg5la
+.section sg5lb
+.section sg5ma
+.section sg5mb
+.section sg5na
+.section sg5nb
+.section sg5oa
+.section sg5ob
+.section sg5pa
+.section sg5pb
+.section sg5qa
+.section sg5qb
+.section sg5ra
+.section sg5rb
+.section sg5sa
+.section sg5sb
+.section sg5ta
+.section sg5tb
+.section sg5ua
+.section sg5ub
+.section sg5va
+.section sg5vb
+.section sg5wa
+.section sg5wb
+.section sg5xa
+.section sg5xb
+.section sg5ya
+.section sg5yb
+.section sg5za
+.section sg5zb
+.section sg51a
+.section sg51b
+.section sg52a
+.section sg52b
+.section sg53a
+.section sg53b
+.section sg54a
+.section sg54b
+.section sg55a
+.section sg55b
+.section sg56a
+.section sg56b
+.section sg57a
+.section sg57b
+.section sg58a
+.section sg58b
+.section sg59a
+.section sg59b
+.section sg50a
+.section sg50b
+.section sg6aa
+.section sg6ab
+.section sg6ba
+.section sg6bb
+.section sg6ca
+.section sg6cb
+.section sg6da
+.section sg6db
+.section sg6ea
+.section sg6eb
+.section sg6fa
+.section sg6fb
+.section sg6ga
+.section sg6gb
+.section sg6ha
+.section sg6hb
+.section sg6ia
+.section sg6ib
+.section sg6ja
+.section sg6jb
+.section sg6ka
+.section sg6kb
+.section sg6la
+.section sg6lb
+.section sg6ma
+.section sg6mb
+.section sg6na
+.section sg6nb
+.section sg6oa
+.section sg6ob
+.section sg6pa
+.section sg6pb
+.section sg6qa
+.section sg6qb
+.section sg6ra
+.section sg6rb
+.section sg6sa
+.section sg6sb
+.section sg6ta
+.section sg6tb
+.section sg6ua
+.section sg6ub
+.section sg6va
+.section sg6vb
+.section sg6wa
+.section sg6wb
+.section sg6xa
+.section sg6xb
+.section sg6ya
+.section sg6yb
+.section sg6za
+.section sg6zb
+.section sg61a
+.section sg61b
+.section sg62a
+.section sg62b
+.section sg63a
+.section sg63b
+.section sg64a
+.section sg64b
+.section sg65a
+.section sg65b
+.section sg66a
+.section sg66b
+.section sg67a
+.section sg67b
+.section sg68a
+.section sg68b
+.section sg69a
+.section sg69b
+.section sg60a
+.section sg60b
+.section sg7aa
+.section sg7ab
+.section sg7ba
+.section sg7bb
+.section sg7ca
+.section sg7cb
+.section sg7da
+.section sg7db
+.section sg7ea
+.section sg7eb
+.section sg7fa
+.section sg7fb
+.section sg7ga
+.section sg7gb
+.section sg7ha
+.section sg7hb
+.section sg7ia
+.section sg7ib
+.section sg7ja
+.section sg7jb
+.section sg7ka
+.section sg7kb
+.section sg7la
+.section sg7lb
+.section sg7ma
+.section sg7mb
+.section sg7na
+.section sg7nb
+.section sg7oa
+.section sg7ob
+.section sg7pa
+.section sg7pb
+.section sg7qa
+.section sg7qb
+.section sg7ra
+.section sg7rb
+.section sg7sa
+.section sg7sb
+.section sg7ta
+.section sg7tb
+.section sg7ua
+.section sg7ub
+.section sg7va
+.section sg7vb
+.section sg7wa
+.section sg7wb
+.section sg7xa
+.section sg7xb
+.section sg7ya
+.section sg7yb
+.section sg7za
+.section sg7zb
+.section sg71a
+.section sg71b
+.section sg72a
+.section sg72b
+.section sg73a
+.section sg73b
+.section sg74a
+.section sg74b
+.section sg75a
+.section sg75b
+.section sg76a
+.section sg76b
+.section sg77a
+.section sg77b
+.section sg78a
+.section sg78b
+.section sg79a
+.section sg79b
+.section sg70a
+.section sg70b
+.section sg8aa
+.section sg8ab
+.section sg8ba
+.section sg8bb
+.section sg8ca
+.section sg8cb
+.section sg8da
+.section sg8db
+.section sg8ea
+.section sg8eb
+.section sg8fa
+.section sg8fb
+.section sg8ga
+.section sg8gb
+.section sg8ha
+.section sg8hb
+.section sg8ia
+.section sg8ib
+.section sg8ja
+.section sg8jb
+.section sg8ka
+.section sg8kb
+.section sg8la
+.section sg8lb
+.section sg8ma
+.section sg8mb
+.section sg8na
+.section sg8nb
+.section sg8oa
+.section sg8ob
+.section sg8pa
+.section sg8pb
+.section sg8qa
+.section sg8qb
+.section sg8ra
+.section sg8rb
+.section sg8sa
+.section sg8sb
+.section sg8ta
+.section sg8tb
+.section sg8ua
+.section sg8ub
+.section sg8va
+.section sg8vb
+.section sg8wa
+.section sg8wb
+.section sg8xa
+.section sg8xb
+.section sg8ya
+.section sg8yb
+.section sg8za
+.section sg8zb
+.section sg81a
+.section sg81b
+.section sg82a
+.section sg82b
+.section sg83a
+.section sg83b
+.section sg84a
+.section sg84b
+.section sg85a
+.section sg85b
+.section sg86a
+.section sg86b
+.section sg87a
+.section sg87b
+.section sg88a
+.section sg88b
+.section sg89a
+.section sg89b
+.section sg80a
+.section sg80b
+.section sg9aa
+.section sg9ab
+.section sg9ba
+.section sg9bb
+.section sg9ca
+.section sg9cb
+.section sg9da
+.section sg9db
+.section sg9ea
+.section sg9eb
+.section sg9fa
+.section sg9fb
+.section sg9ga
+.section sg9gb
+.section sg9ha
+.section sg9hb
+.section sg9ia
+.section sg9ib
+.section sg9ja
+.section sg9jb
+.section sg9ka
+.section sg9kb
+.section sg9la
+.section sg9lb
+.section sg9ma
+.section sg9mb
+.section sg9na
+.section sg9nb
+.section sg9oa
+.section sg9ob
+.section sg9pa
+.section sg9pb
+.section sg9qa
+.section sg9qb
+.section sg9ra
+.section sg9rb
+.section sg9sa
+.section sg9sb
+.section sg9ta
+.section sg9tb
+.section sg9ua
+.section sg9ub
+.section sg9va
+.section sg9vb
+.section sg9wa
+.section sg9wb
+.section sg9xa
+.section sg9xb
+.section sg9ya
+.section sg9yb
+.section sg9za
+.section sg9zb
+.section sg91a
+.section sg91b
+.section sg92a
+.section sg92b
+.section sg93a
+.section sg93b
+.section sg94a
+.section sg94b
+.section sg95a
+.section sg95b
+.section sg96a
+.section sg96b
+.section sg97a
+.section sg97b
+.section sg98a
+.section sg98b
+.section sg99a
+.section sg99b
+.section sg90a
+.section sg90b
+.section sg0aa
+.section sg0ab
+.section sg0ba
+.section sg0bb
+.section sg0ca
+.section sg0cb
+.section sg0da
+.section sg0db
+.section sg0ea
+.section sg0eb
+.section sg0fa
+.section sg0fb
+.section sg0ga
+.section sg0gb
+.section sg0ha
+.section sg0hb
+.section sg0ia
+.section sg0ib
+.section sg0ja
+.section sg0jb
+.section sg0ka
+.section sg0kb
+.section sg0la
+.section sg0lb
+.section sg0ma
+.section sg0mb
+.section sg0na
+.section sg0nb
+.section sg0oa
+.section sg0ob
+.section sg0pa
+.section sg0pb
+.section sg0qa
+.section sg0qb
+.section sg0ra
+.section sg0rb
+.section sg0sa
+.section sg0sb
+.section sg0ta
+.section sg0tb
+.section sg0ua
+.section sg0ub
+.section sg0va
+.section sg0vb
+.section sg0wa
+.section sg0wb
+.section sg0xa
+.section sg0xb
+.section sg0ya
+.section sg0yb
+.section sg0za
+.section sg0zb
+.section sg01a
+.section sg01b
+.section sg02a
+.section sg02b
+.section sg03a
+.section sg03b
+.section sg04a
+.section sg04b
+.section sg05a
+.section sg05b
+.section sg06a
+.section sg06b
+.section sg07a
+.section sg07b
+.section sg08a
+.section sg08b
+.section sg09a
+.section sg09b
+.section sg00a
+.section sg00b
+.section shaaa
+.section shaab
+.section shaba
+.section shabb
+.section shaca
+.section shacb
+.section shada
+.section shadb
+.section shaea
+.section shaeb
+.section shafa
+.section shafb
+.section shaga
+.section shagb
+.section shaha
+.section shahb
+.section shaia
+.section shaib
+.section shaja
+.section shajb
+.section shaka
+.section shakb
+.section shala
+.section shalb
+.section shama
+.section shamb
+.section shana
+.section shanb
+.section shaoa
+.section shaob
+.section shapa
+.section shapb
+.section shaqa
+.section shaqb
+.section shara
+.section sharb
+.section shasa
+.section shasb
+.section shata
+.section shatb
+.section shaua
+.section shaub
+.section shava
+.section shavb
+.section shawa
+.section shawb
+.section shaxa
+.section shaxb
+.section shaya
+.section shayb
+.section shaza
+.section shazb
+.section sha1a
+.section sha1b
+.section sha2a
+.section sha2b
+.section sha3a
+.section sha3b
+.section sha4a
+.section sha4b
+.section sha5a
+.section sha5b
+.section sha6a
+.section sha6b
+.section sha7a
+.section sha7b
+.section sha8a
+.section sha8b
+.section sha9a
+.section sha9b
+.section sha0a
+.section sha0b
+.section shbaa
+.section shbab
+.section shbba
+.section shbbb
+.section shbca
+.section shbcb
+.section shbda
+.section shbdb
+.section shbea
+.section shbeb
+.section shbfa
+.section shbfb
+.section shbga
+.section shbgb
+.section shbha
+.section shbhb
+.section shbia
+.section shbib
+.section shbja
+.section shbjb
+.section shbka
+.section shbkb
+.section shbla
+.section shblb
+.section shbma
+.section shbmb
+.section shbna
+.section shbnb
+.section shboa
+.section shbob
+.section shbpa
+.section shbpb
+.section shbqa
+.section shbqb
+.section shbra
+.section shbrb
+.section shbsa
+.section shbsb
+.section shbta
+.section shbtb
+.section shbua
+.section shbub
+.section shbva
+.section shbvb
+.section shbwa
+.section shbwb
+.section shbxa
+.section shbxb
+.section shbya
+.section shbyb
+.section shbza
+.section shbzb
+.section shb1a
+.section shb1b
+.section shb2a
+.section shb2b
+.section shb3a
+.section shb3b
+.section shb4a
+.section shb4b
+.section shb5a
+.section shb5b
+.section shb6a
+.section shb6b
+.section shb7a
+.section shb7b
+.section shb8a
+.section shb8b
+.section shb9a
+.section shb9b
+.section shb0a
+.section shb0b
+.section shcaa
+.section shcab
+.section shcba
+.section shcbb
+.section shcca
+.section shccb
+.section shcda
+.section shcdb
+.section shcea
+.section shceb
+.section shcfa
+.section shcfb
+.section shcga
+.section shcgb
+.section shcha
+.section shchb
+.section shcia
+.section shcib
+.section shcja
+.section shcjb
+.section shcka
+.section shckb
+.section shcla
+.section shclb
+.section shcma
+.section shcmb
+.section shcna
+.section shcnb
+.section shcoa
+.section shcob
+.section shcpa
+.section shcpb
+.section shcqa
+.section shcqb
+.section shcra
+.section shcrb
+.section shcsa
+.section shcsb
+.section shcta
+.section shctb
+.section shcua
+.section shcub
+.section shcva
+.section shcvb
+.section shcwa
+.section shcwb
+.section shcxa
+.section shcxb
+.section shcya
+.section shcyb
+.section shcza
+.section shczb
+.section shc1a
+.section shc1b
+.section shc2a
+.section shc2b
+.section shc3a
+.section shc3b
+.section shc4a
+.section shc4b
+.section shc5a
+.section shc5b
+.section shc6a
+.section shc6b
+.section shc7a
+.section shc7b
+.section shc8a
+.section shc8b
+.section shc9a
+.section shc9b
+.section shc0a
+.section shc0b
+.section shdaa
+.section shdab
+.section shdba
+.section shdbb
+.section shdca
+.section shdcb
+.section shdda
+.section shddb
+.section shdea
+.section shdeb
+.section shdfa
+.section shdfb
+.section shdga
+.section shdgb
+.section shdha
+.section shdhb
+.section shdia
+.section shdib
+.section shdja
+.section shdjb
+.section shdka
+.section shdkb
+.section shdla
+.section shdlb
+.section shdma
+.section shdmb
+.section shdna
+.section shdnb
+.section shdoa
+.section shdob
+.section shdpa
+.section shdpb
+.section shdqa
+.section shdqb
+.section shdra
+.section shdrb
+.section shdsa
+.section shdsb
+.section shdta
+.section shdtb
+.section shdua
+.section shdub
+.section shdva
+.section shdvb
+.section shdwa
+.section shdwb
+.section shdxa
+.section shdxb
+.section shdya
+.section shdyb
+.section shdza
+.section shdzb
+.section shd1a
+.section shd1b
+.section shd2a
+.section shd2b
+.section shd3a
+.section shd3b
+.section shd4a
+.section shd4b
+.section shd5a
+.section shd5b
+.section shd6a
+.section shd6b
+.section shd7a
+.section shd7b
+.section shd8a
+.section shd8b
+.section shd9a
+.section shd9b
+.section shd0a
+.section shd0b
+.section sheaa
+.section sheab
+.section sheba
+.section shebb
+.section sheca
+.section shecb
+.section sheda
+.section shedb
+.section sheea
+.section sheeb
+.section shefa
+.section shefb
+.section shega
+.section shegb
+.section sheha
+.section shehb
+.section sheia
+.section sheib
+.section sheja
+.section shejb
+.section sheka
+.section shekb
+.section shela
+.section shelb
+.section shema
+.section shemb
+.section shena
+.section shenb
+.section sheoa
+.section sheob
+.section shepa
+.section shepb
+.section sheqa
+.section sheqb
+.section shera
+.section sherb
+.section shesa
+.section shesb
+.section sheta
+.section shetb
+.section sheua
+.section sheub
+.section sheva
+.section shevb
+.section shewa
+.section shewb
+.section shexa
+.section shexb
+.section sheya
+.section sheyb
+.section sheza
+.section shezb
+.section she1a
+.section she1b
+.section she2a
+.section she2b
+.section she3a
+.section she3b
+.section she4a
+.section she4b
+.section she5a
+.section she5b
+.section she6a
+.section she6b
+.section she7a
+.section she7b
+.section she8a
+.section she8b
+.section she9a
+.section she9b
+.section she0a
+.section she0b
+.section shfaa
+.section shfab
+.section shfba
+.section shfbb
+.section shfca
+.section shfcb
+.section shfda
+.section shfdb
+.section shfea
+.section shfeb
+.section shffa
+.section shffb
+.section shfga
+.section shfgb
+.section shfha
+.section shfhb
+.section shfia
+.section shfib
+.section shfja
+.section shfjb
+.section shfka
+.section shfkb
+.section shfla
+.section shflb
+.section shfma
+.section shfmb
+.section shfna
+.section shfnb
+.section shfoa
+.section shfob
+.section shfpa
+.section shfpb
+.section shfqa
+.section shfqb
+.section shfra
+.section shfrb
+.section shfsa
+.section shfsb
+.section shfta
+.section shftb
+.section shfua
+.section shfub
+.section shfva
+.section shfvb
+.section shfwa
+.section shfwb
+.section shfxa
+.section shfxb
+.section shfya
+.section shfyb
+.section shfza
+.section shfzb
+.section shf1a
+.section shf1b
+.section shf2a
+.section shf2b
+.section shf3a
+.section shf3b
+.section shf4a
+.section shf4b
+.section shf5a
+.section shf5b
+.section shf6a
+.section shf6b
+.section shf7a
+.section shf7b
+.section shf8a
+.section shf8b
+.section shf9a
+.section shf9b
+.section shf0a
+.section shf0b
+.section shgaa
+.section shgab
+.section shgba
+.section shgbb
+.section shgca
+.section shgcb
+.section shgda
+.section shgdb
+.section shgea
+.section shgeb
+.section shgfa
+.section shgfb
+.section shgga
+.section shggb
+.section shgha
+.section shghb
+.section shgia
+.section shgib
+.section shgja
+.section shgjb
+.section shgka
+.section shgkb
+.section shgla
+.section shglb
+.section shgma
+.section shgmb
+.section shgna
+.section shgnb
+.section shgoa
+.section shgob
+.section shgpa
+.section shgpb
+.section shgqa
+.section shgqb
+.section shgra
+.section shgrb
+.section shgsa
+.section shgsb
+.section shgta
+.section shgtb
+.section shgua
+.section shgub
+.section shgva
+.section shgvb
+.section shgwa
+.section shgwb
+.section shgxa
+.section shgxb
+.section shgya
+.section shgyb
+.section shgza
+.section shgzb
+.section shg1a
+.section shg1b
+.section shg2a
+.section shg2b
+.section shg3a
+.section shg3b
+.section shg4a
+.section shg4b
+.section shg5a
+.section shg5b
+.section shg6a
+.section shg6b
+.section shg7a
+.section shg7b
+.section shg8a
+.section shg8b
+.section shg9a
+.section shg9b
+.section shg0a
+.section shg0b
+.section shhaa
+.section shhab
+.section shhba
+.section shhbb
+.section shhca
+.section shhcb
+.section shhda
+.section shhdb
+.section shhea
+.section shheb
+.section shhfa
+.section shhfb
+.section shhga
+.section shhgb
+.section shhha
+.section shhhb
+.section shhia
+.section shhib
+.section shhja
+.section shhjb
+.section shhka
+.section shhkb
+.section shhla
+.section shhlb
+.section shhma
+.section shhmb
+.section shhna
+.section shhnb
+.section shhoa
+.section shhob
+.section shhpa
+.section shhpb
+.section shhqa
+.section shhqb
+.section shhra
+.section shhrb
+.section shhsa
+.section shhsb
+.section shhta
+.section shhtb
+.section shhua
+.section shhub
+.section shhva
+.section shhvb
+.section shhwa
+.section shhwb
+.section shhxa
+.section shhxb
+.section shhya
+.section shhyb
+.section shhza
+.section shhzb
+.section shh1a
+.section shh1b
+.section shh2a
+.section shh2b
+.section shh3a
+.section shh3b
+.section shh4a
+.section shh4b
+.section shh5a
+.section shh5b
+.section shh6a
+.section shh6b
+.section shh7a
+.section shh7b
+.section shh8a
+.section shh8b
+.section shh9a
+.section shh9b
+.section shh0a
+.section shh0b
+.section shiaa
+.section shiab
+.section shiba
+.section shibb
+.section shica
+.section shicb
+.section shida
+.section shidb
+.section shiea
+.section shieb
+.section shifa
+.section shifb
+.section shiga
+.section shigb
+.section shiha
+.section shihb
+.section shiia
+.section shiib
+.section shija
+.section shijb
+.section shika
+.section shikb
+.section shila
+.section shilb
+.section shima
+.section shimb
+.section shina
+.section shinb
+.section shioa
+.section shiob
+.section shipa
+.section shipb
+.section shiqa
+.section shiqb
+.section shira
+.section shirb
+.section shisa
+.section shisb
+.section shita
+.section shitb
+.section shiua
+.section shiub
+.section shiva
+.section shivb
+.section shiwa
+.section shiwb
+.section shixa
+.section shixb
+.section shiya
+.section shiyb
+.section shiza
+.section shizb
+.section shi1a
+.section shi1b
+.section shi2a
+.section shi2b
+.section shi3a
+.section shi3b
+.section shi4a
+.section shi4b
+.section shi5a
+.section shi5b
+.section shi6a
+.section shi6b
+.section shi7a
+.section shi7b
+.section shi8a
+.section shi8b
+.section shi9a
+.section shi9b
+.section shi0a
+.section shi0b
+.section shjaa
+.section shjab
+.section shjba
+.section shjbb
+.section shjca
+.section shjcb
+.section shjda
+.section shjdb
+.section shjea
+.section shjeb
+.section shjfa
+.section shjfb
+.section shjga
+.section shjgb
+.section shjha
+.section shjhb
+.section shjia
+.section shjib
+.section shjja
+.section shjjb
+.section shjka
+.section shjkb
+.section shjla
+.section shjlb
+.section shjma
+.section shjmb
+.section shjna
+.section shjnb
+.section shjoa
+.section shjob
+.section shjpa
+.section shjpb
+.section shjqa
+.section shjqb
+.section shjra
+.section shjrb
+.section shjsa
+.section shjsb
+.section shjta
+.section shjtb
+.section shjua
+.section shjub
+.section shjva
+.section shjvb
+.section shjwa
+.section shjwb
+.section shjxa
+.section shjxb
+.section shjya
+.section shjyb
+.section shjza
+.section shjzb
+.section shj1a
+.section shj1b
+.section shj2a
+.section shj2b
+.section shj3a
+.section shj3b
+.section shj4a
+.section shj4b
+.section shj5a
+.section shj5b
+.section shj6a
+.section shj6b
+.section shj7a
+.section shj7b
+.section shj8a
+.section shj8b
+.section shj9a
+.section shj9b
+.section shj0a
+.section shj0b
+.section shkaa
+.section shkab
+.section shkba
+.section shkbb
+.section shkca
+.section shkcb
+.section shkda
+.section shkdb
+.section shkea
+.section shkeb
+.section shkfa
+.section shkfb
+.section shkga
+.section shkgb
+.section shkha
+.section shkhb
+.section shkia
+.section shkib
+.section shkja
+.section shkjb
+.section shkka
+.section shkkb
+.section shkla
+.section shklb
+.section shkma
+.section shkmb
+.section shkna
+.section shknb
+.section shkoa
+.section shkob
+.section shkpa
+.section shkpb
+.section shkqa
+.section shkqb
+.section shkra
+.section shkrb
+.section shksa
+.section shksb
+.section shkta
+.section shktb
+.section shkua
+.section shkub
+.section shkva
+.section shkvb
+.section shkwa
+.section shkwb
+.section shkxa
+.section shkxb
+.section shkya
+.section shkyb
+.section shkza
+.section shkzb
+.section shk1a
+.section shk1b
+.section shk2a
+.section shk2b
+.section shk3a
+.section shk3b
+.section shk4a
+.section shk4b
+.section shk5a
+.section shk5b
+.section shk6a
+.section shk6b
+.section shk7a
+.section shk7b
+.section shk8a
+.section shk8b
+.section shk9a
+.section shk9b
+.section shk0a
+.section shk0b
+.section shlaa
+.section shlab
+.section shlba
+.section shlbb
+.section shlca
+.section shlcb
+.section shlda
+.section shldb
+.section shlea
+.section shleb
+.section shlfa
+.section shlfb
+.section shlga
+.section shlgb
+.section shlha
+.section shlhb
+.section shlia
+.section shlib
+.section shlja
+.section shljb
+.section shlka
+.section shlkb
+.section shlla
+.section shllb
+.section shlma
+.section shlmb
+.section shlna
+.section shlnb
+.section shloa
+.section shlob
+.section shlpa
+.section shlpb
+.section shlqa
+.section shlqb
+.section shlra
+.section shlrb
+.section shlsa
+.section shlsb
+.section shlta
+.section shltb
+.section shlua
+.section shlub
+.section shlva
+.section shlvb
+.section shlwa
+.section shlwb
+.section shlxa
+.section shlxb
+.section shlya
+.section shlyb
+.section shlza
+.section shlzb
+.section shl1a
+.section shl1b
+.section shl2a
+.section shl2b
+.section shl3a
+.section shl3b
+.section shl4a
+.section shl4b
+.section shl5a
+.section shl5b
+.section shl6a
+.section shl6b
+.section shl7a
+.section shl7b
+.section shl8a
+.section shl8b
+.section shl9a
+.section shl9b
+.section shl0a
+.section shl0b
+.section shmaa
+.section shmab
+.section shmba
+.section shmbb
+.section shmca
+.section shmcb
+.section shmda
+.section shmdb
+.section shmea
+.section shmeb
+.section shmfa
+.section shmfb
+.section shmga
+.section shmgb
+.section shmha
+.section shmhb
+.section shmia
+.section shmib
+.section shmja
+.section shmjb
+.section shmka
+.section shmkb
+.section shmla
+.section shmlb
+.section shmma
+.section shmmb
+.section shmna
+.section shmnb
+.section shmoa
+.section shmob
+.section shmpa
+.section shmpb
+.section shmqa
+.section shmqb
+.section shmra
+.section shmrb
+.section shmsa
+.section shmsb
+.section shmta
+.section shmtb
+.section shmua
+.section shmub
+.section shmva
+.section shmvb
+.section shmwa
+.section shmwb
+.section shmxa
+.section shmxb
+.section shmya
+.section shmyb
+.section shmza
+.section shmzb
+.section shm1a
+.section shm1b
+.section shm2a
+.section shm2b
+.section shm3a
+.section shm3b
+.section shm4a
+.section shm4b
+.section shm5a
+.section shm5b
+.section shm6a
+.section shm6b
+.section shm7a
+.section shm7b
+.section shm8a
+.section shm8b
+.section shm9a
+.section shm9b
+.section shm0a
+.section shm0b
+.section shnaa
+.section shnab
+.section shnba
+.section shnbb
+.section shnca
+.section shncb
+.section shnda
+.section shndb
+.section shnea
+.section shneb
+.section shnfa
+.section shnfb
+.section shnga
+.section shngb
+.section shnha
+.section shnhb
+.section shnia
+.section shnib
+.section shnja
+.section shnjb
+.section shnka
+.section shnkb
+.section shnla
+.section shnlb
+.section shnma
+.section shnmb
+.section shnna
+.section shnnb
+.section shnoa
+.section shnob
+.section shnpa
+.section shnpb
+.section shnqa
+.section shnqb
+.section shnra
+.section shnrb
+.section shnsa
+.section shnsb
+.section shnta
+.section shntb
+.section shnua
+.section shnub
+.section shnva
+.section shnvb
+.section shnwa
+.section shnwb
+.section shnxa
+.section shnxb
+.section shnya
+.section shnyb
+.section shnza
+.section shnzb
+.section shn1a
+.section shn1b
+.section shn2a
+.section shn2b
+.section shn3a
+.section shn3b
+.section shn4a
+.section shn4b
+.section shn5a
+.section shn5b
+.section shn6a
+.section shn6b
+.section shn7a
+.section shn7b
+.section shn8a
+.section shn8b
+.section shn9a
+.section shn9b
+.section shn0a
+.section shn0b
+.section shoaa
+.section shoab
+.section shoba
+.section shobb
+.section shoca
+.section shocb
+.section shoda
+.section shodb
+.section shoea
+.section shoeb
+.section shofa
+.section shofb
+.section shoga
+.section shogb
+.section shoha
+.section shohb
+.section shoia
+.section shoib
+.section shoja
+.section shojb
+.section shoka
+.section shokb
+.section shola
+.section sholb
+.section shoma
+.section shomb
+.section shona
+.section shonb
+.section shooa
+.section shoob
+.section shopa
+.section shopb
+.section shoqa
+.section shoqb
+.section shora
+.section shorb
+.section shosa
+.section shosb
+.section shota
+.section shotb
+.section shoua
+.section shoub
+.section shova
+.section shovb
+.section showa
+.section showb
+.section shoxa
+.section shoxb
+.section shoya
+.section shoyb
+.section shoza
+.section shozb
+.section sho1a
+.section sho1b
+.section sho2a
+.section sho2b
+.section sho3a
+.section sho3b
+.section sho4a
+.section sho4b
+.section sho5a
+.section sho5b
+.section sho6a
+.section sho6b
+.section sho7a
+.section sho7b
+.section sho8a
+.section sho8b
+.section sho9a
+.section sho9b
+.section sho0a
+.section sho0b
+.section shpaa
+.section shpab
+.section shpba
+.section shpbb
+.section shpca
+.section shpcb
+.section shpda
+.section shpdb
+.section shpea
+.section shpeb
+.section shpfa
+.section shpfb
+.section shpga
+.section shpgb
+.section shpha
+.section shphb
+.section shpia
+.section shpib
+.section shpja
+.section shpjb
+.section shpka
+.section shpkb
+.section shpla
+.section shplb
+.section shpma
+.section shpmb
+.section shpna
+.section shpnb
+.section shpoa
+.section shpob
+.section shppa
+.section shppb
+.section shpqa
+.section shpqb
+.section shpra
+.section shprb
+.section shpsa
+.section shpsb
+.section shpta
+.section shptb
+.section shpua
+.section shpub
+.section shpva
+.section shpvb
+.section shpwa
+.section shpwb
+.section shpxa
+.section shpxb
+.section shpya
+.section shpyb
+.section shpza
+.section shpzb
+.section shp1a
+.section shp1b
+.section shp2a
+.section shp2b
+.section shp3a
+.section shp3b
+.section shp4a
+.section shp4b
+.section shp5a
+.section shp5b
+.section shp6a
+.section shp6b
+.section shp7a
+.section shp7b
+.section shp8a
+.section shp8b
+.section shp9a
+.section shp9b
+.section shp0a
+.section shp0b
+.section shqaa
+.section shqab
+.section shqba
+.section shqbb
+.section shqca
+.section shqcb
+.section shqda
+.section shqdb
+.section shqea
+.section shqeb
+.section shqfa
+.section shqfb
+.section shqga
+.section shqgb
+.section shqha
+.section shqhb
+.section shqia
+.section shqib
+.section shqja
+.section shqjb
+.section shqka
+.section shqkb
+.section shqla
+.section shqlb
+.section shqma
+.section shqmb
+.section shqna
+.section shqnb
+.section shqoa
+.section shqob
+.section shqpa
+.section shqpb
+.section shqqa
+.section shqqb
+.section shqra
+.section shqrb
+.section shqsa
+.section shqsb
+.section shqta
+.section shqtb
+.section shqua
+.section shqub
+.section shqva
+.section shqvb
+.section shqwa
+.section shqwb
+.section shqxa
+.section shqxb
+.section shqya
+.section shqyb
+.section shqza
+.section shqzb
+.section shq1a
+.section shq1b
+.section shq2a
+.section shq2b
+.section shq3a
+.section shq3b
+.section shq4a
+.section shq4b
+.section shq5a
+.section shq5b
+.section shq6a
+.section shq6b
+.section shq7a
+.section shq7b
+.section shq8a
+.section shq8b
+.section shq9a
+.section shq9b
+.section shq0a
+.section shq0b
+.section shraa
+.section shrab
+.section shrba
+.section shrbb
+.section shrca
+.section shrcb
+.section shrda
+.section shrdb
+.section shrea
+.section shreb
+.section shrfa
+.section shrfb
+.section shrga
+.section shrgb
+.section shrha
+.section shrhb
+.section shria
+.section shrib
+.section shrja
+.section shrjb
+.section shrka
+.section shrkb
+.section shrla
+.section shrlb
+.section shrma
+.section shrmb
+.section shrna
+.section shrnb
+.section shroa
+.section shrob
+.section shrpa
+.section shrpb
+.section shrqa
+.section shrqb
+.section shrra
+.section shrrb
+.section shrsa
+.section shrsb
+.section shrta
+.section shrtb
+.section shrua
+.section shrub
+.section shrva
+.section shrvb
+.section shrwa
+.section shrwb
+.section shrxa
+.section shrxb
+.section shrya
+.section shryb
+.section shrza
+.section shrzb
+.section shr1a
+.section shr1b
+.section shr2a
+.section shr2b
+.section shr3a
+.section shr3b
+.section shr4a
+.section shr4b
+.section shr5a
+.section shr5b
+.section shr6a
+.section shr6b
+.section shr7a
+.section shr7b
+.section shr8a
+.section shr8b
+.section shr9a
+.section shr9b
+.section shr0a
+.section shr0b
+.section shsaa
+.section shsab
+.section shsba
+.section shsbb
+.section shsca
+.section shscb
+.section shsda
+.section shsdb
+.section shsea
+.section shseb
+.section shsfa
+.section shsfb
+.section shsga
+.section shsgb
+.section shsha
+.section shshb
+.section shsia
+.section shsib
+.section shsja
+.section shsjb
+.section shska
+.section shskb
+.section shsla
+.section shslb
+.section shsma
+.section shsmb
+.section shsna
+.section shsnb
+.section shsoa
+.section shsob
+.section shspa
+.section shspb
+.section shsqa
+.section shsqb
+.section shsra
+.section shsrb
+.section shssa
+.section shssb
+.section shsta
+.section shstb
+.section shsua
+.section shsub
+.section shsva
+.section shsvb
+.section shswa
+.section shswb
+.section shsxa
+.section shsxb
+.section shsya
+.section shsyb
+.section shsza
+.section shszb
+.section shs1a
+.section shs1b
+.section shs2a
+.section shs2b
+.section shs3a
+.section shs3b
+.section shs4a
+.section shs4b
+.section shs5a
+.section shs5b
+.section shs6a
+.section shs6b
+.section shs7a
+.section shs7b
+.section shs8a
+.section shs8b
+.section shs9a
+.section shs9b
+.section shs0a
+.section shs0b
+.section shtaa
+.section shtab
+.section shtba
+.section shtbb
+.section shtca
+.section shtcb
+.section shtda
+.section shtdb
+.section shtea
+.section shteb
+.section shtfa
+.section shtfb
+.section shtga
+.section shtgb
+.section shtha
+.section shthb
+.section shtia
+.section shtib
+.section shtja
+.section shtjb
+.section shtka
+.section shtkb
+.section shtla
+.section shtlb
+.section shtma
+.section shtmb
+.section shtna
+.section shtnb
+.section shtoa
+.section shtob
+.section shtpa
+.section shtpb
+.section shtqa
+.section shtqb
+.section shtra
+.section shtrb
+.section shtsa
+.section shtsb
+.section shtta
+.section shttb
+.section shtua
+.section shtub
+.section shtva
+.section shtvb
+.section shtwa
+.section shtwb
+.section shtxa
+.section shtxb
+.section shtya
+.section shtyb
+.section shtza
+.section shtzb
+.section sht1a
+.section sht1b
+.section sht2a
+.section sht2b
+.section sht3a
+.section sht3b
+.section sht4a
+.section sht4b
+.section sht5a
+.section sht5b
+.section sht6a
+.section sht6b
+.section sht7a
+.section sht7b
+.section sht8a
+.section sht8b
+.section sht9a
+.section sht9b
+.section sht0a
+.section sht0b
+.section shuaa
+.section shuab
+.section shuba
+.section shubb
+.section shuca
+.section shucb
+.section shuda
+.section shudb
+.section shuea
+.section shueb
+.section shufa
+.section shufb
+.section shuga
+.section shugb
+.section shuha
+.section shuhb
+.section shuia
+.section shuib
+.section shuja
+.section shujb
+.section shuka
+.section shukb
+.section shula
+.section shulb
+.section shuma
+.section shumb
+.section shuna
+.section shunb
+.section shuoa
+.section shuob
+.section shupa
+.section shupb
+.section shuqa
+.section shuqb
+.section shura
+.section shurb
+.section shusa
+.section shusb
+.section shuta
+.section shutb
+.section shuua
+.section shuub
+.section shuva
+.section shuvb
+.section shuwa
+.section shuwb
+.section shuxa
+.section shuxb
+.section shuya
+.section shuyb
+.section shuza
+.section shuzb
+.section shu1a
+.section shu1b
+.section shu2a
+.section shu2b
+.section shu3a
+.section shu3b
+.section shu4a
+.section shu4b
+.section shu5a
+.section shu5b
+.section shu6a
+.section shu6b
+.section shu7a
+.section shu7b
+.section shu8a
+.section shu8b
+.section shu9a
+.section shu9b
+.section shu0a
+.section shu0b
+.section shvaa
+.section shvab
+.section shvba
+.section shvbb
+.section shvca
+.section shvcb
+.section shvda
+.section shvdb
+.section shvea
+.section shveb
+.section shvfa
+.section shvfb
+.section shvga
+.section shvgb
+.section shvha
+.section shvhb
+.section shvia
+.section shvib
+.section shvja
+.section shvjb
+.section shvka
+.section shvkb
+.section shvla
+.section shvlb
+.section shvma
+.section shvmb
+.section shvna
+.section shvnb
+.section shvoa
+.section shvob
+.section shvpa
+.section shvpb
+.section shvqa
+.section shvqb
+.section shvra
+.section shvrb
+.section shvsa
+.section shvsb
+.section shvta
+.section shvtb
+.section shvua
+.section shvub
+.section shvva
+.section shvvb
+.section shvwa
+.section shvwb
+.section shvxa
+.section shvxb
+.section shvya
+.section shvyb
+.section shvza
+.section shvzb
+.section shv1a
+.section shv1b
+.section shv2a
+.section shv2b
+.section shv3a
+.section shv3b
+.section shv4a
+.section shv4b
+.section shv5a
+.section shv5b
+.section shv6a
+.section shv6b
+.section shv7a
+.section shv7b
+.section shv8a
+.section shv8b
+.section shv9a
+.section shv9b
+.section shv0a
+.section shv0b
+.section shwaa
+.section shwab
+.section shwba
+.section shwbb
+.section shwca
+.section shwcb
+.section shwda
+.section shwdb
+.section shwea
+.section shweb
+.section shwfa
+.section shwfb
+.section shwga
+.section shwgb
+.section shwha
+.section shwhb
+.section shwia
+.section shwib
+.section shwja
+.section shwjb
+.section shwka
+.section shwkb
+.section shwla
+.section shwlb
+.section shwma
+.section shwmb
+.section shwna
+.section shwnb
+.section shwoa
+.section shwob
+.section shwpa
+.section shwpb
+.section shwqa
+.section shwqb
+.section shwra
+.section shwrb
+.section shwsa
+.section shwsb
+.section shwta
+.section shwtb
+.section shwua
+.section shwub
+.section shwva
+.section shwvb
+.section shwwa
+.section shwwb
+.section shwxa
+.section shwxb
+.section shwya
+.section shwyb
+.section shwza
+.section shwzb
+.section shw1a
+.section shw1b
+.section shw2a
+.section shw2b
+.section shw3a
+.section shw3b
+.section shw4a
+.section shw4b
+.section shw5a
+.section shw5b
+.section shw6a
+.section shw6b
+.section shw7a
+.section shw7b
+.section shw8a
+.section shw8b
+.section shw9a
+.section shw9b
+.section shw0a
+.section shw0b
+.section shxaa
+.section shxab
+.section shxba
+.section shxbb
+.section shxca
+.section shxcb
+.section shxda
+.section shxdb
+.section shxea
+.section shxeb
+.section shxfa
+.section shxfb
+.section shxga
+.section shxgb
+.section shxha
+.section shxhb
+.section shxia
+.section shxib
+.section shxja
+.section shxjb
+.section shxka
+.section shxkb
+.section shxla
+.section shxlb
+.section shxma
+.section shxmb
+.section shxna
+.section shxnb
+.section shxoa
+.section shxob
+.section shxpa
+.section shxpb
+.section shxqa
+.section shxqb
+.section shxra
+.section shxrb
+.section shxsa
+.section shxsb
+.section shxta
+.section shxtb
+.section shxua
+.section shxub
+.section shxva
+.section shxvb
+.section shxwa
+.section shxwb
+.section shxxa
+.section shxxb
+.section shxya
+.section shxyb
+.section shxza
+.section shxzb
+.section shx1a
+.section shx1b
+.section shx2a
+.section shx2b
+.section shx3a
+.section shx3b
+.section shx4a
+.section shx4b
+.section shx5a
+.section shx5b
+.section shx6a
+.section shx6b
+.section shx7a
+.section shx7b
+.section shx8a
+.section shx8b
+.section shx9a
+.section shx9b
+.section shx0a
+.section shx0b
+.section shyaa
+.section shyab
+.section shyba
+.section shybb
+.section shyca
+.section shycb
+.section shyda
+.section shydb
+.section shyea
+.section shyeb
+.section shyfa
+.section shyfb
+.section shyga
+.section shygb
+.section shyha
+.section shyhb
+.section shyia
+.section shyib
+.section shyja
+.section shyjb
+.section shyka
+.section shykb
+.section shyla
+.section shylb
+.section shyma
+.section shymb
+.section shyna
+.section shynb
+.section shyoa
+.section shyob
+.section shypa
+.section shypb
+.section shyqa
+.section shyqb
+.section shyra
+.section shyrb
+.section shysa
+.section shysb
+.section shyta
+.section shytb
+.section shyua
+.section shyub
+.section shyva
+.section shyvb
+.section shywa
+.section shywb
+.section shyxa
+.section shyxb
+.section shyya
+.section shyyb
+.section shyza
+.section shyzb
+.section shy1a
+.section shy1b
+.section shy2a
+.section shy2b
+.section shy3a
+.section shy3b
+.section shy4a
+.section shy4b
+.section shy5a
+.section shy5b
+.section shy6a
+.section shy6b
+.section shy7a
+.section shy7b
+.section shy8a
+.section shy8b
+.section shy9a
+.section shy9b
+.section shy0a
+.section shy0b
+.section shzaa
+.section shzab
+.section shzba
+.section shzbb
+.section shzca
+.section shzcb
+.section shzda
+.section shzdb
+.section shzea
+.section shzeb
+.section shzfa
+.section shzfb
+.section shzga
+.section shzgb
+.section shzha
+.section shzhb
+.section shzia
+.section shzib
+.section shzja
+.section shzjb
+.section shzka
+.section shzkb
+.section shzla
+.section shzlb
+.section shzma
+.section shzmb
+.section shzna
+.section shznb
+.section shzoa
+.section shzob
+.section shzpa
+.section shzpb
+.section shzqa
+.section shzqb
+.section shzra
+.section shzrb
+.section shzsa
+.section shzsb
+.section shzta
+.section shztb
+.section shzua
+.section shzub
+.section shzva
+.section shzvb
+.section shzwa
+.section shzwb
+.section shzxa
+.section shzxb
+.section shzya
+.section shzyb
+.section shzza
+.section shzzb
+.section shz1a
+.section shz1b
+.section shz2a
+.section shz2b
+.section shz3a
+.section shz3b
+.section shz4a
+.section shz4b
+.section shz5a
+.section shz5b
+.section shz6a
+.section shz6b
+.section shz7a
+.section shz7b
+.section shz8a
+.section shz8b
+.section shz9a
+.section shz9b
+.section shz0a
+.section shz0b
+.section sh1aa
+.section sh1ab
+.section sh1ba
+.section sh1bb
+.section sh1ca
+.section sh1cb
+.section sh1da
+.section sh1db
+.section sh1ea
+.section sh1eb
+.section sh1fa
+.section sh1fb
+.section sh1ga
+.section sh1gb
+.section sh1ha
+.section sh1hb
+.section sh1ia
+.section sh1ib
+.section sh1ja
+.section sh1jb
+.section sh1ka
+.section sh1kb
+.section sh1la
+.section sh1lb
+.section sh1ma
+.section sh1mb
+.section sh1na
+.section sh1nb
+.section sh1oa
+.section sh1ob
+.section sh1pa
+.section sh1pb
+.section sh1qa
+.section sh1qb
+.section sh1ra
+.section sh1rb
+.section sh1sa
+.section sh1sb
+.section sh1ta
+.section sh1tb
+.section sh1ua
+.section sh1ub
+.section sh1va
+.section sh1vb
+.section sh1wa
+.section sh1wb
+.section sh1xa
+.section sh1xb
+.section sh1ya
+.section sh1yb
+.section sh1za
+.section sh1zb
+.section sh11a
+.section sh11b
+.section sh12a
+.section sh12b
+.section sh13a
+.section sh13b
+.section sh14a
+.section sh14b
+.section sh15a
+.section sh15b
+.section sh16a
+.section sh16b
+.section sh17a
+.section sh17b
+.section sh18a
+.section sh18b
+.section sh19a
+.section sh19b
+.section sh10a
+.section sh10b
+.section sh2aa
+.section sh2ab
+.section sh2ba
+.section sh2bb
+.section sh2ca
+.section sh2cb
+.section sh2da
+.section sh2db
+.section sh2ea
+.section sh2eb
+.section sh2fa
+.section sh2fb
+.section sh2ga
+.section sh2gb
+.section sh2ha
+.section sh2hb
+.section sh2ia
+.section sh2ib
+.section sh2ja
+.section sh2jb
+.section sh2ka
+.section sh2kb
+.section sh2la
+.section sh2lb
+.section sh2ma
+.section sh2mb
+.section sh2na
+.section sh2nb
+.section sh2oa
+.section sh2ob
+.section sh2pa
+.section sh2pb
+.section sh2qa
+.section sh2qb
+.section sh2ra
+.section sh2rb
+.section sh2sa
+.section sh2sb
+.section sh2ta
+.section sh2tb
+.section sh2ua
+.section sh2ub
+.section sh2va
+.section sh2vb
+.section sh2wa
+.section sh2wb
+.section sh2xa
+.section sh2xb
+.section sh2ya
+.section sh2yb
+.section sh2za
+.section sh2zb
+.section sh21a
+.section sh21b
+.section sh22a
+.section sh22b
+.section sh23a
+.section sh23b
+.section sh24a
+.section sh24b
+.section sh25a
+.section sh25b
+.section sh26a
+.section sh26b
+.section sh27a
+.section sh27b
+.section sh28a
+.section sh28b
+.section sh29a
+.section sh29b
+.section sh20a
+.section sh20b
+.section sh3aa
+.section sh3ab
+.section sh3ba
+.section sh3bb
+.section sh3ca
+.section sh3cb
+.section sh3da
+.section sh3db
+.section sh3ea
+.section sh3eb
+.section sh3fa
+.section sh3fb
+.section sh3ga
+.section sh3gb
+.section sh3ha
+.section sh3hb
+.section sh3ia
+.section sh3ib
+.section sh3ja
+.section sh3jb
+.section sh3ka
+.section sh3kb
+.section sh3la
+.section sh3lb
+.section sh3ma
+.section sh3mb
+.section sh3na
+.section sh3nb
+.section sh3oa
+.section sh3ob
+.section sh3pa
+.section sh3pb
+.section sh3qa
+.section sh3qb
+.section sh3ra
+.section sh3rb
+.section sh3sa
+.section sh3sb
+.section sh3ta
+.section sh3tb
+.section sh3ua
+.section sh3ub
+.section sh3va
+.section sh3vb
+.section sh3wa
+.section sh3wb
+.section sh3xa
+.section sh3xb
+.section sh3ya
+.section sh3yb
+.section sh3za
+.section sh3zb
+.section sh31a
+.section sh31b
+.section sh32a
+.section sh32b
+.section sh33a
+.section sh33b
+.section sh34a
+.section sh34b
+.section sh35a
+.section sh35b
+.section sh36a
+.section sh36b
+.section sh37a
+.section sh37b
+.section sh38a
+.section sh38b
+.section sh39a
+.section sh39b
+.section sh30a
+.section sh30b
+.section sh4aa
+.section sh4ab
+.section sh4ba
+.section sh4bb
+.section sh4ca
+.section sh4cb
+.section sh4da
+.section sh4db
+.section sh4ea
+.section sh4eb
+.section sh4fa
+.section sh4fb
+.section sh4ga
+.section sh4gb
+.section sh4ha
+.section sh4hb
+.section sh4ia
+.section sh4ib
+.section sh4ja
+.section sh4jb
+.section sh4ka
+.section sh4kb
+.section sh4la
+.section sh4lb
+.section sh4ma
+.section sh4mb
+.section sh4na
+.section sh4nb
+.section sh4oa
+.section sh4ob
+.section sh4pa
+.section sh4pb
+.section sh4qa
+.section sh4qb
+.section sh4ra
+.section sh4rb
+.section sh4sa
+.section sh4sb
+.section sh4ta
+.section sh4tb
+.section sh4ua
+.section sh4ub
+.section sh4va
+.section sh4vb
+.section sh4wa
+.section sh4wb
+.section sh4xa
+.section sh4xb
+.section sh4ya
+.section sh4yb
+.section sh4za
+.section sh4zb
+.section sh41a
+.section sh41b
+.section sh42a
+.section sh42b
+.section sh43a
+.section sh43b
+.section sh44a
+.section sh44b
+.section sh45a
+.section sh45b
+.section sh46a
+.section sh46b
+.section sh47a
+.section sh47b
+.section sh48a
+.section sh48b
+.section sh49a
+.section sh49b
+.section sh40a
+.section sh40b
+.section sh5aa
+.section sh5ab
+.section sh5ba
+.section sh5bb
+.section sh5ca
+.section sh5cb
+.section sh5da
+.section sh5db
+.section sh5ea
+.section sh5eb
+.section sh5fa
+.section sh5fb
+.section sh5ga
+.section sh5gb
+.section sh5ha
+.section sh5hb
+.section sh5ia
+.section sh5ib
+.section sh5ja
+.section sh5jb
+.section sh5ka
+.section sh5kb
+.section sh5la
+.section sh5lb
+.section sh5ma
+.section sh5mb
+.section sh5na
+.section sh5nb
+.section sh5oa
+.section sh5ob
+.section sh5pa
+.section sh5pb
+.section sh5qa
+.section sh5qb
+.section sh5ra
+.section sh5rb
+.section sh5sa
+.section sh5sb
+.section sh5ta
+.section sh5tb
+.section sh5ua
+.section sh5ub
+.section sh5va
+.section sh5vb
+.section sh5wa
+.section sh5wb
+.section sh5xa
+.section sh5xb
+.section sh5ya
+.section sh5yb
+.section sh5za
+.section sh5zb
+.section sh51a
+.section sh51b
+.section sh52a
+.section sh52b
+.section sh53a
+.section sh53b
+.section sh54a
+.section sh54b
+.section sh55a
+.section sh55b
+.section sh56a
+.section sh56b
+.section sh57a
+.section sh57b
+.section sh58a
+.section sh58b
+.section sh59a
+.section sh59b
+.section sh50a
+.section sh50b
+.section sh6aa
+.section sh6ab
+.section sh6ba
+.section sh6bb
+.section sh6ca
+.section sh6cb
+.section sh6da
+.section sh6db
+.section sh6ea
+.section sh6eb
+.section sh6fa
+.section sh6fb
+.section sh6ga
+.section sh6gb
+.section sh6ha
+.section sh6hb
+.section sh6ia
+.section sh6ib
+.section sh6ja
+.section sh6jb
+.section sh6ka
+.section sh6kb
+.section sh6la
+.section sh6lb
+.section sh6ma
+.section sh6mb
+.section sh6na
+.section sh6nb
+.section sh6oa
+.section sh6ob
+.section sh6pa
+.section sh6pb
+.section sh6qa
+.section sh6qb
+.section sh6ra
+.section sh6rb
+.section sh6sa
+.section sh6sb
+.section sh6ta
+.section sh6tb
+.section sh6ua
+.section sh6ub
+.section sh6va
+.section sh6vb
+.section sh6wa
+.section sh6wb
+.section sh6xa
+.section sh6xb
+.section sh6ya
+.section sh6yb
+.section sh6za
+.section sh6zb
+.section sh61a
+.section sh61b
+.section sh62a
+.section sh62b
+.section sh63a
+.section sh63b
+.section sh64a
+.section sh64b
+.section sh65a
+.section sh65b
+.section sh66a
+.section sh66b
+.section sh67a
+.section sh67b
+.section sh68a
+.section sh68b
+.section sh69a
+.section sh69b
+.section sh60a
+.section sh60b
+.section sh7aa
+.section sh7ab
+.section sh7ba
+.section sh7bb
+.section sh7ca
+.section sh7cb
+.section sh7da
+.section sh7db
+.section sh7ea
+.section sh7eb
+.section sh7fa
+.section sh7fb
+.section sh7ga
+.section sh7gb
+.section sh7ha
+.section sh7hb
+.section sh7ia
+.section sh7ib
+.section sh7ja
+.section sh7jb
+.section sh7ka
+.section sh7kb
+.section sh7la
+.section sh7lb
+.section sh7ma
+.section sh7mb
+.section sh7na
+.section sh7nb
+.section sh7oa
+.section sh7ob
+.section sh7pa
+.section sh7pb
+.section sh7qa
+.section sh7qb
+.section sh7ra
+.section sh7rb
+.section sh7sa
+.section sh7sb
+.section sh7ta
+.section sh7tb
+.section sh7ua
+.section sh7ub
+.section sh7va
+.section sh7vb
+.section sh7wa
+.section sh7wb
+.section sh7xa
+.section sh7xb
+.section sh7ya
+.section sh7yb
+.section sh7za
+.section sh7zb
+.section sh71a
+.section sh71b
+.section sh72a
+.section sh72b
+.section sh73a
+.section sh73b
+.section sh74a
+.section sh74b
+.section sh75a
+.section sh75b
+.section sh76a
+.section sh76b
+.section sh77a
+.section sh77b
+.section sh78a
+.section sh78b
+.section sh79a
+.section sh79b
+.section sh70a
+.section sh70b
+.section sh8aa
+.section sh8ab
+.section sh8ba
+.section sh8bb
+.section sh8ca
+.section sh8cb
+.section sh8da
+.section sh8db
+.section sh8ea
+.section sh8eb
+.section sh8fa
+.section sh8fb
+.section sh8ga
+.section sh8gb
+.section sh8ha
+.section sh8hb
+.section sh8ia
+.section sh8ib
+.section sh8ja
+.section sh8jb
+.section sh8ka
+.section sh8kb
+.section sh8la
+.section sh8lb
+.section sh8ma
+.section sh8mb
+.section sh8na
+.section sh8nb
+.section sh8oa
+.section sh8ob
+.section sh8pa
+.section sh8pb
+.section sh8qa
+.section sh8qb
+.section sh8ra
+.section sh8rb
+.section sh8sa
+.section sh8sb
+.section sh8ta
+.section sh8tb
+.section sh8ua
+.section sh8ub
+.section sh8va
+.section sh8vb
+.section sh8wa
+.section sh8wb
+.section sh8xa
+.section sh8xb
+.section sh8ya
+.section sh8yb
+.section sh8za
+.section sh8zb
+.section sh81a
+.section sh81b
+.section sh82a
+.section sh82b
+.section sh83a
+.section sh83b
+.section sh84a
+.section sh84b
+.section sh85a
+.section sh85b
+.section sh86a
+.section sh86b
+.section sh87a
+.section sh87b
+.section sh88a
+.section sh88b
+.section sh89a
+.section sh89b
+.section sh80a
+.section sh80b
+.section sh9aa
+.section sh9ab
+.section sh9ba
+.section sh9bb
+.section sh9ca
+.section sh9cb
+.section sh9da
+.section sh9db
+.section sh9ea
+.section sh9eb
+.section sh9fa
+.section sh9fb
+.section sh9ga
+.section sh9gb
+.section sh9ha
+.section sh9hb
+.section sh9ia
+.section sh9ib
+.section sh9ja
+.section sh9jb
+.section sh9ka
+.section sh9kb
+.section sh9la
+.section sh9lb
+.section sh9ma
+.section sh9mb
+.section sh9na
+.section sh9nb
+.section sh9oa
+.section sh9ob
+.section sh9pa
+.section sh9pb
+.section sh9qa
+.section sh9qb
+.section sh9ra
+.section sh9rb
+.section sh9sa
+.section sh9sb
+.section sh9ta
+.section sh9tb
+.section sh9ua
+.section sh9ub
+.section sh9va
+.section sh9vb
+.section sh9wa
+.section sh9wb
+.section sh9xa
+.section sh9xb
+.section sh9ya
+.section sh9yb
+.section sh9za
+.section sh9zb
+.section sh91a
+.section sh91b
+.section sh92a
+.section sh92b
+.section sh93a
+.section sh93b
+.section sh94a
+.section sh94b
+.section sh95a
+.section sh95b
+.section sh96a
+.section sh96b
+.section sh97a
+.section sh97b
+.section sh98a
+.section sh98b
+.section sh99a
+.section sh99b
+.section sh90a
+.section sh90b
+.section sh0aa
+.section sh0ab
+.section sh0ba
+.section sh0bb
+.section sh0ca
+.section sh0cb
+.section sh0da
+.section sh0db
+.section sh0ea
+.section sh0eb
+.section sh0fa
+.section sh0fb
+.section sh0ga
+.section sh0gb
+.section sh0ha
+.section sh0hb
+.section sh0ia
+.section sh0ib
+.section sh0ja
+.section sh0jb
+.section sh0ka
+.section sh0kb
+.section sh0la
+.section sh0lb
+.section sh0ma
+.section sh0mb
+.section sh0na
+.section sh0nb
+.section sh0oa
+.section sh0ob
+.section sh0pa
+.section sh0pb
+.section sh0qa
+.section sh0qb
+.section sh0ra
+.section sh0rb
+.section sh0sa
+.section sh0sb
+.section sh0ta
+.section sh0tb
+.section sh0ua
+.section sh0ub
+.section sh0va
+.section sh0vb
+.section sh0wa
+.section sh0wb
+.section sh0xa
+.section sh0xb
+.section sh0ya
+.section sh0yb
+.section sh0za
+.section sh0zb
+.section sh01a
+.section sh01b
+.section sh02a
+.section sh02b
+.section sh03a
+.section sh03b
+.section sh04a
+.section sh04b
+.section sh05a
+.section sh05b
+.section sh06a
+.section sh06b
+.section sh07a
+.section sh07b
+.section sh08a
+.section sh08b
+.section sh09a
+.section sh09b
+.section sh00a
+.section sh00b
+.section siaaa
+.section siaab
+.section siaba
+.section siabb
+.section siaca
+.section siacb
+.section siada
+.section siadb
+.section siaea
+.section siaeb
+.section siafa
+.section siafb
+.section siaga
+.section siagb
+.section siaha
+.section siahb
+.section siaia
+.section siaib
+.section siaja
+.section siajb
+.section siaka
+.section siakb
+.section siala
+.section sialb
+.section siama
+.section siamb
+.section siana
+.section sianb
+.section siaoa
+.section siaob
+.section siapa
+.section siapb
+.section siaqa
+.section siaqb
+.section siara
+.section siarb
+.section siasa
+.section siasb
+.section siata
+.section siatb
+.section siaua
+.section siaub
+.section siava
+.section siavb
+.section siawa
+.section siawb
+.section siaxa
+.section siaxb
+.section siaya
+.section siayb
+.section siaza
+.section siazb
+.section sia1a
+.section sia1b
+.section sia2a
+.section sia2b
+.section sia3a
+.section sia3b
+.section sia4a
+.section sia4b
+.section sia5a
+.section sia5b
+.section sia6a
+.section sia6b
+.section sia7a
+.section sia7b
+.section sia8a
+.section sia8b
+.section sia9a
+.section sia9b
+.section sia0a
+.section sia0b
+.section sibaa
+.section sibab
+.section sibba
+.section sibbb
+.section sibca
+.section sibcb
+.section sibda
+.section sibdb
+.section sibea
+.section sibeb
+.section sibfa
+.section sibfb
+.section sibga
+.section sibgb
+.section sibha
+.section sibhb
+.section sibia
+.section sibib
+.section sibja
+.section sibjb
+.section sibka
+.section sibkb
+.section sibla
+.section siblb
+.section sibma
+.section sibmb
+.section sibna
+.section sibnb
+.section siboa
+.section sibob
+.section sibpa
+.section sibpb
+.section sibqa
+.section sibqb
+.section sibra
+.section sibrb
+.section sibsa
+.section sibsb
+.section sibta
+.section sibtb
+.section sibua
+.section sibub
+.section sibva
+.section sibvb
+.section sibwa
+.section sibwb
+.section sibxa
+.section sibxb
+.section sibya
+.section sibyb
+.section sibza
+.section sibzb
+.section sib1a
+.section sib1b
+.section sib2a
+.section sib2b
+.section sib3a
+.section sib3b
+.section sib4a
+.section sib4b
+.section sib5a
+.section sib5b
+.section sib6a
+.section sib6b
+.section sib7a
+.section sib7b
+.section sib8a
+.section sib8b
+.section sib9a
+.section sib9b
+.section sib0a
+.section sib0b
+.section sicaa
+.section sicab
+.section sicba
+.section sicbb
+.section sicca
+.section siccb
+.section sicda
+.section sicdb
+.section sicea
+.section siceb
+.section sicfa
+.section sicfb
+.section sicga
+.section sicgb
+.section sicha
+.section sichb
+.section sicia
+.section sicib
+.section sicja
+.section sicjb
+.section sicka
+.section sickb
+.section sicla
+.section siclb
+.section sicma
+.section sicmb
+.section sicna
+.section sicnb
+.section sicoa
+.section sicob
+.section sicpa
+.section sicpb
+.section sicqa
+.section sicqb
+.section sicra
+.section sicrb
+.section sicsa
+.section sicsb
+.section sicta
+.section sictb
+.section sicua
+.section sicub
+.section sicva
+.section sicvb
+.section sicwa
+.section sicwb
+.section sicxa
+.section sicxb
+.section sicya
+.section sicyb
+.section sicza
+.section siczb
+.section sic1a
+.section sic1b
+.section sic2a
+.section sic2b
+.section sic3a
+.section sic3b
+.section sic4a
+.section sic4b
+.section sic5a
+.section sic5b
+.section sic6a
+.section sic6b
+.section sic7a
+.section sic7b
+.section sic8a
+.section sic8b
+.section sic9a
+.section sic9b
+.section sic0a
+.section sic0b
+.section sidaa
+.section sidab
+.section sidba
+.section sidbb
+.section sidca
+.section sidcb
+.section sidda
+.section siddb
+.section sidea
+.section sideb
+.section sidfa
+.section sidfb
+.section sidga
+.section sidgb
+.section sidha
+.section sidhb
+.section sidia
+.section sidib
+.section sidja
+.section sidjb
+.section sidka
+.section sidkb
+.section sidla
+.section sidlb
+.section sidma
+.section sidmb
+.section sidna
+.section sidnb
+.section sidoa
+.section sidob
+.section sidpa
+.section sidpb
+.section sidqa
+.section sidqb
+.section sidra
+.section sidrb
+.section sidsa
+.section sidsb
+.section sidta
+.section sidtb
+.section sidua
+.section sidub
+.section sidva
+.section sidvb
+.section sidwa
+.section sidwb
+.section sidxa
+.section sidxb
+.section sidya
+.section sidyb
+.section sidza
+.section sidzb
+.section sid1a
+.section sid1b
+.section sid2a
+.section sid2b
+.section sid3a
+.section sid3b
+.section sid4a
+.section sid4b
+.section sid5a
+.section sid5b
+.section sid6a
+.section sid6b
+.section sid7a
+.section sid7b
+.section sid8a
+.section sid8b
+.section sid9a
+.section sid9b
+.section sid0a
+.section sid0b
+.section sieaa
+.section sieab
+.section sieba
+.section siebb
+.section sieca
+.section siecb
+.section sieda
+.section siedb
+.section sieea
+.section sieeb
+.section siefa
+.section siefb
+.section siega
+.section siegb
+.section sieha
+.section siehb
+.section sieia
+.section sieib
+.section sieja
+.section siejb
+.section sieka
+.section siekb
+.section siela
+.section sielb
+.section siema
+.section siemb
+.section siena
+.section sienb
+.section sieoa
+.section sieob
+.section siepa
+.section siepb
+.section sieqa
+.section sieqb
+.section siera
+.section sierb
+.section siesa
+.section siesb
+.section sieta
+.section sietb
+.section sieua
+.section sieub
+.section sieva
+.section sievb
+.section siewa
+.section siewb
+.section siexa
+.section siexb
+.section sieya
+.section sieyb
+.section sieza
+.section siezb
+.section sie1a
+.section sie1b
+.section sie2a
+.section sie2b
+.section sie3a
+.section sie3b
+.section sie4a
+.section sie4b
+.section sie5a
+.section sie5b
+.section sie6a
+.section sie6b
+.section sie7a
+.section sie7b
+.section sie8a
+.section sie8b
+.section sie9a
+.section sie9b
+.section sie0a
+.section sie0b
+.section sifaa
+.section sifab
+.section sifba
+.section sifbb
+.section sifca
+.section sifcb
+.section sifda
+.section sifdb
+.section sifea
+.section sifeb
+.section siffa
+.section siffb
+.section sifga
+.section sifgb
+.section sifha
+.section sifhb
+.section sifia
+.section sifib
+.section sifja
+.section sifjb
+.section sifka
+.section sifkb
+.section sifla
+.section siflb
+.section sifma
+.section sifmb
+.section sifna
+.section sifnb
+.section sifoa
+.section sifob
+.section sifpa
+.section sifpb
+.section sifqa
+.section sifqb
+.section sifra
+.section sifrb
+.section sifsa
+.section sifsb
+.section sifta
+.section siftb
+.section sifua
+.section sifub
+.section sifva
+.section sifvb
+.section sifwa
+.section sifwb
+.section sifxa
+.section sifxb
+.section sifya
+.section sifyb
+.section sifza
+.section sifzb
+.section sif1a
+.section sif1b
+.section sif2a
+.section sif2b
+.section sif3a
+.section sif3b
+.section sif4a
+.section sif4b
+.section sif5a
+.section sif5b
+.section sif6a
+.section sif6b
+.section sif7a
+.section sif7b
+.section sif8a
+.section sif8b
+.section sif9a
+.section sif9b
+.section sif0a
+.section sif0b
+.section sigaa
+.section sigab
+.section sigba
+.section sigbb
+.section sigca
+.section sigcb
+.section sigda
+.section sigdb
+.section sigea
+.section sigeb
+.section sigfa
+.section sigfb
+.section sigga
+.section siggb
+.section sigha
+.section sighb
+.section sigia
+.section sigib
+.section sigja
+.section sigjb
+.section sigka
+.section sigkb
+.section sigla
+.section siglb
+.section sigma
+.section sigmb
+.section signa
+.section signb
+.section sigoa
+.section sigob
+.section sigpa
+.section sigpb
+.section sigqa
+.section sigqb
+.section sigra
+.section sigrb
+.section sigsa
+.section sigsb
+.section sigta
+.section sigtb
+.section sigua
+.section sigub
+.section sigva
+.section sigvb
+.section sigwa
+.section sigwb
+.section sigxa
+.section sigxb
+.section sigya
+.section sigyb
+.section sigza
+.section sigzb
+.section sig1a
+.section sig1b
+.section sig2a
+.section sig2b
+.section sig3a
+.section sig3b
+.section sig4a
+.section sig4b
+.section sig5a
+.section sig5b
+.section sig6a
+.section sig6b
+.section sig7a
+.section sig7b
+.section sig8a
+.section sig8b
+.section sig9a
+.section sig9b
+.section sig0a
+.section sig0b
+.section sihaa
+.section sihab
+.section sihba
+.section sihbb
+.section sihca
+.section sihcb
+.section sihda
+.section sihdb
+.section sihea
+.section siheb
+.section sihfa
+.section sihfb
+.section sihga
+.section sihgb
+.section sihha
+.section sihhb
+.section sihia
+.section sihib
+.section sihja
+.section sihjb
+.section sihka
+.section sihkb
+.section sihla
+.section sihlb
+.section sihma
+.section sihmb
+.section sihna
+.section sihnb
+.section sihoa
+.section sihob
+.section sihpa
+.section sihpb
+.section sihqa
+.section sihqb
+.section sihra
+.section sihrb
+.section sihsa
+.section sihsb
+.section sihta
+.section sihtb
+.section sihua
+.section sihub
+.section sihva
+.section sihvb
+.section sihwa
+.section sihwb
+.section sihxa
+.section sihxb
+.section sihya
+.section sihyb
+.section sihza
+.section sihzb
+.section sih1a
+.section sih1b
+.section sih2a
+.section sih2b
+.section sih3a
+.section sih3b
+.section sih4a
+.section sih4b
+.section sih5a
+.section sih5b
+.section sih6a
+.section sih6b
+.section sih7a
+.section sih7b
+.section sih8a
+.section sih8b
+.section sih9a
+.section sih9b
+.section sih0a
+.section sih0b
+.section siiaa
+.section siiab
+.section siiba
+.section siibb
+.section siica
+.section siicb
+.section siida
+.section siidb
+.section siiea
+.section siieb
+.section siifa
+.section siifb
+.section siiga
+.section siigb
+.section siiha
+.section siihb
+.section siiia
+.section siiib
+.section siija
+.section siijb
+.section siika
+.section siikb
+.section siila
+.section siilb
+.section siima
+.section siimb
+.section siina
+.section siinb
+.section siioa
+.section siiob
+.section siipa
+.section siipb
+.section siiqa
+.section siiqb
+.section siira
+.section siirb
+.section siisa
+.section siisb
+.section siita
+.section siitb
+.section siiua
+.section siiub
+.section siiva
+.section siivb
+.section siiwa
+.section siiwb
+.section siixa
+.section siixb
+.section siiya
+.section siiyb
+.section siiza
+.section siizb
+.section sii1a
+.section sii1b
+.section sii2a
+.section sii2b
+.section sii3a
+.section sii3b
+.section sii4a
+.section sii4b
+.section sii5a
+.section sii5b
+.section sii6a
+.section sii6b
+.section sii7a
+.section sii7b
+.section sii8a
+.section sii8b
+.section sii9a
+.section sii9b
+.section sii0a
+.section sii0b
+.section sijaa
+.section sijab
+.section sijba
+.section sijbb
+.section sijca
+.section sijcb
+.section sijda
+.section sijdb
+.section sijea
+.section sijeb
+.section sijfa
+.section sijfb
+.section sijga
+.section sijgb
+.section sijha
+.section sijhb
+.section sijia
+.section sijib
+.section sijja
+.section sijjb
+.section sijka
+.section sijkb
+.section sijla
+.section sijlb
+.section sijma
+.section sijmb
+.section sijna
+.section sijnb
+.section sijoa
+.section sijob
+.section sijpa
+.section sijpb
+.section sijqa
+.section sijqb
+.section sijra
+.section sijrb
+.section sijsa
+.section sijsb
+.section sijta
+.section sijtb
+.section sijua
+.section sijub
+.section sijva
+.section sijvb
+.section sijwa
+.section sijwb
+.section sijxa
+.section sijxb
+.section sijya
+.section sijyb
+.section sijza
+.section sijzb
+.section sij1a
+.section sij1b
+.section sij2a
+.section sij2b
+.section sij3a
+.section sij3b
+.section sij4a
+.section sij4b
+.section sij5a
+.section sij5b
+.section sij6a
+.section sij6b
+.section sij7a
+.section sij7b
+.section sij8a
+.section sij8b
+.section sij9a
+.section sij9b
+.section sij0a
+.section sij0b
+.section sikaa
+.section sikab
+.section sikba
+.section sikbb
+.section sikca
+.section sikcb
+.section sikda
+.section sikdb
+.section sikea
+.section sikeb
+.section sikfa
+.section sikfb
+.section sikga
+.section sikgb
+.section sikha
+.section sikhb
+.section sikia
+.section sikib
+.section sikja
+.section sikjb
+.section sikka
+.section sikkb
+.section sikla
+.section siklb
+.section sikma
+.section sikmb
+.section sikna
+.section siknb
+.section sikoa
+.section sikob
+.section sikpa
+.section sikpb
+.section sikqa
+.section sikqb
+.section sikra
+.section sikrb
+.section siksa
+.section siksb
+.section sikta
+.section siktb
+.section sikua
+.section sikub
+.section sikva
+.section sikvb
+.section sikwa
+.section sikwb
+.section sikxa
+.section sikxb
+.section sikya
+.section sikyb
+.section sikza
+.section sikzb
+.section sik1a
+.section sik1b
+.section sik2a
+.section sik2b
+.section sik3a
+.section sik3b
+.section sik4a
+.section sik4b
+.section sik5a
+.section sik5b
+.section sik6a
+.section sik6b
+.section sik7a
+.section sik7b
+.section sik8a
+.section sik8b
+.section sik9a
+.section sik9b
+.section sik0a
+.section sik0b
+.section silaa
+.section silab
+.section silba
+.section silbb
+.section silca
+.section silcb
+.section silda
+.section sildb
+.section silea
+.section sileb
+.section silfa
+.section silfb
+.section silga
+.section silgb
+.section silha
+.section silhb
+.section silia
+.section silib
+.section silja
+.section siljb
+.section silka
+.section silkb
+.section silla
+.section sillb
+.section silma
+.section silmb
+.section silna
+.section silnb
+.section siloa
+.section silob
+.section silpa
+.section silpb
+.section silqa
+.section silqb
+.section silra
+.section silrb
+.section silsa
+.section silsb
+.section silta
+.section siltb
+.section silua
+.section silub
+.section silva
+.section silvb
+.section silwa
+.section silwb
+.section silxa
+.section silxb
+.section silya
+.section silyb
+.section silza
+.section silzb
+.section sil1a
+.section sil1b
+.section sil2a
+.section sil2b
+.section sil3a
+.section sil3b
+.section sil4a
+.section sil4b
+.section sil5a
+.section sil5b
+.section sil6a
+.section sil6b
+.section sil7a
+.section sil7b
+.section sil8a
+.section sil8b
+.section sil9a
+.section sil9b
+.section sil0a
+.section sil0b
+.section simaa
+.section simab
+.section simba
+.section simbb
+.section simca
+.section simcb
+.section simda
+.section simdb
+.section simea
+.section simeb
+.section simfa
+.section simfb
+.section simga
+.section simgb
+.section simha
+.section simhb
+.section simia
+.section simib
+.section simja
+.section simjb
+.section simka
+.section simkb
+.section simla
+.section simlb
+.section simma
+.section simmb
+.section simna
+.section simnb
+.section simoa
+.section simob
+.section simpa
+.section simpb
+.section simqa
+.section simqb
+.section simra
+.section simrb
+.section simsa
+.section simsb
+.section simta
+.section simtb
+.section simua
+.section simub
+.section simva
+.section simvb
+.section simwa
+.section simwb
+.section simxa
+.section simxb
+.section simya
+.section simyb
+.section simza
+.section simzb
+.section sim1a
+.section sim1b
+.section sim2a
+.section sim2b
+.section sim3a
+.section sim3b
+.section sim4a
+.section sim4b
+.section sim5a
+.section sim5b
+.section sim6a
+.section sim6b
+.section sim7a
+.section sim7b
+.section sim8a
+.section sim8b
+.section sim9a
+.section sim9b
+.section sim0a
+.section sim0b
+.section sinaa
+.section sinab
+.section sinba
+.section sinbb
+.section sinca
+.section sincb
+.section sinda
+.section sindb
+.section sinea
+.section sineb
+.section sinfa
+.section sinfb
+.section singa
+.section singb
+.section sinha
+.section sinhb
+.section sinia
+.section sinib
+.section sinja
+.section sinjb
+.section sinka
+.section sinkb
+.section sinla
+.section sinlb
+.section sinma
+.section sinmb
+.section sinna
+.section sinnb
+.section sinoa
+.section sinob
+.section sinpa
+.section sinpb
+.section sinqa
+.section sinqb
+.section sinra
+.section sinrb
+.section sinsa
+.section sinsb
+.section sinta
+.section sintb
+.section sinua
+.section sinub
+.section sinva
+.section sinvb
+.section sinwa
+.section sinwb
+.section sinxa
+.section sinxb
+.section sinya
+.section sinyb
+.section sinza
+.section sinzb
+.section sin1a
+.section sin1b
+.section sin2a
+.section sin2b
+.section sin3a
+.section sin3b
+.section sin4a
+.section sin4b
+.section sin5a
+.section sin5b
+.section sin6a
+.section sin6b
+.section sin7a
+.section sin7b
+.section sin8a
+.section sin8b
+.section sin9a
+.section sin9b
+.section sin0a
+.section sin0b
+.section sioaa
+.section sioab
+.section sioba
+.section siobb
+.section sioca
+.section siocb
+.section sioda
+.section siodb
+.section sioea
+.section sioeb
+.section siofa
+.section siofb
+.section sioga
+.section siogb
+.section sioha
+.section siohb
+.section sioia
+.section sioib
+.section sioja
+.section siojb
+.section sioka
+.section siokb
+.section siola
+.section siolb
+.section sioma
+.section siomb
+.section siona
+.section sionb
+.section siooa
+.section sioob
+.section siopa
+.section siopb
+.section sioqa
+.section sioqb
+.section siora
+.section siorb
+.section siosa
+.section siosb
+.section siota
+.section siotb
+.section sioua
+.section sioub
+.section siova
+.section siovb
+.section siowa
+.section siowb
+.section sioxa
+.section sioxb
+.section sioya
+.section sioyb
+.section sioza
+.section siozb
+.section sio1a
+.section sio1b
+.section sio2a
+.section sio2b
+.section sio3a
+.section sio3b
+.section sio4a
+.section sio4b
+.section sio5a
+.section sio5b
+.section sio6a
+.section sio6b
+.section sio7a
+.section sio7b
+.section sio8a
+.section sio8b
+.section sio9a
+.section sio9b
+.section sio0a
+.section sio0b
+.section sipaa
+.section sipab
+.section sipba
+.section sipbb
+.section sipca
+.section sipcb
+.section sipda
+.section sipdb
+.section sipea
+.section sipeb
+.section sipfa
+.section sipfb
+.section sipga
+.section sipgb
+.section sipha
+.section siphb
+.section sipia
+.section sipib
+.section sipja
+.section sipjb
+.section sipka
+.section sipkb
+.section sipla
+.section siplb
+.section sipma
+.section sipmb
+.section sipna
+.section sipnb
+.section sipoa
+.section sipob
+.section sippa
+.section sippb
+.section sipqa
+.section sipqb
+.section sipra
+.section siprb
+.section sipsa
+.section sipsb
+.section sipta
+.section siptb
+.section sipua
+.section sipub
+.section sipva
+.section sipvb
+.section sipwa
+.section sipwb
+.section sipxa
+.section sipxb
+.section sipya
+.section sipyb
+.section sipza
+.section sipzb
+.section sip1a
+.section sip1b
+.section sip2a
+.section sip2b
+.section sip3a
+.section sip3b
+.section sip4a
+.section sip4b
+.section sip5a
+.section sip5b
+.section sip6a
+.section sip6b
+.section sip7a
+.section sip7b
+.section sip8a
+.section sip8b
+.section sip9a
+.section sip9b
+.section sip0a
+.section sip0b
+.section siqaa
+.section siqab
+.section siqba
+.section siqbb
+.section siqca
+.section siqcb
+.section siqda
+.section siqdb
+.section siqea
+.section siqeb
+.section siqfa
+.section siqfb
+.section siqga
+.section siqgb
+.section siqha
+.section siqhb
+.section siqia
+.section siqib
+.section siqja
+.section siqjb
+.section siqka
+.section siqkb
+.section siqla
+.section siqlb
+.section siqma
+.section siqmb
+.section siqna
+.section siqnb
+.section siqoa
+.section siqob
+.section siqpa
+.section siqpb
+.section siqqa
+.section siqqb
+.section siqra
+.section siqrb
+.section siqsa
+.section siqsb
+.section siqta
+.section siqtb
+.section siqua
+.section siqub
+.section siqva
+.section siqvb
+.section siqwa
+.section siqwb
+.section siqxa
+.section siqxb
+.section siqya
+.section siqyb
+.section siqza
+.section siqzb
+.section siq1a
+.section siq1b
+.section siq2a
+.section siq2b
+.section siq3a
+.section siq3b
+.section siq4a
+.section siq4b
+.section siq5a
+.section siq5b
+.section siq6a
+.section siq6b
+.section siq7a
+.section siq7b
+.section siq8a
+.section siq8b
+.section siq9a
+.section siq9b
+.section siq0a
+.section siq0b
+.section siraa
+.section sirab
+.section sirba
+.section sirbb
+.section sirca
+.section sircb
+.section sirda
+.section sirdb
+.section sirea
+.section sireb
+.section sirfa
+.section sirfb
+.section sirga
+.section sirgb
+.section sirha
+.section sirhb
+.section siria
+.section sirib
+.section sirja
+.section sirjb
+.section sirka
+.section sirkb
+.section sirla
+.section sirlb
+.section sirma
+.section sirmb
+.section sirna
+.section sirnb
+.section siroa
+.section sirob
+.section sirpa
+.section sirpb
+.section sirqa
+.section sirqb
+.section sirra
+.section sirrb
+.section sirsa
+.section sirsb
+.section sirta
+.section sirtb
+.section sirua
+.section sirub
+.section sirva
+.section sirvb
+.section sirwa
+.section sirwb
+.section sirxa
+.section sirxb
+.section sirya
+.section siryb
+.section sirza
+.section sirzb
+.section sir1a
+.section sir1b
+.section sir2a
+.section sir2b
+.section sir3a
+.section sir3b
+.section sir4a
+.section sir4b
+.section sir5a
+.section sir5b
+.section sir6a
+.section sir6b
+.section sir7a
+.section sir7b
+.section sir8a
+.section sir8b
+.section sir9a
+.section sir9b
+.section sir0a
+.section sir0b
+.section sisaa
+.section sisab
+.section sisba
+.section sisbb
+.section sisca
+.section siscb
+.section sisda
+.section sisdb
+.section sisea
+.section siseb
+.section sisfa
+.section sisfb
+.section sisga
+.section sisgb
+.section sisha
+.section sishb
+.section sisia
+.section sisib
+.section sisja
+.section sisjb
+.section siska
+.section siskb
+.section sisla
+.section sislb
+.section sisma
+.section sismb
+.section sisna
+.section sisnb
+.section sisoa
+.section sisob
+.section sispa
+.section sispb
+.section sisqa
+.section sisqb
+.section sisra
+.section sisrb
+.section sissa
+.section sissb
+.section sista
+.section sistb
+.section sisua
+.section sisub
+.section sisva
+.section sisvb
+.section siswa
+.section siswb
+.section sisxa
+.section sisxb
+.section sisya
+.section sisyb
+.section sisza
+.section siszb
+.section sis1a
+.section sis1b
+.section sis2a
+.section sis2b
+.section sis3a
+.section sis3b
+.section sis4a
+.section sis4b
+.section sis5a
+.section sis5b
+.section sis6a
+.section sis6b
+.section sis7a
+.section sis7b
+.section sis8a
+.section sis8b
+.section sis9a
+.section sis9b
+.section sis0a
+.section sis0b
+.section sitaa
+.section sitab
+.section sitba
+.section sitbb
+.section sitca
+.section sitcb
+.section sitda
+.section sitdb
+.section sitea
+.section siteb
+.section sitfa
+.section sitfb
+.section sitga
+.section sitgb
+.section sitha
+.section sithb
+.section sitia
+.section sitib
+.section sitja
+.section sitjb
+.section sitka
+.section sitkb
+.section sitla
+.section sitlb
+.section sitma
+.section sitmb
+.section sitna
+.section sitnb
+.section sitoa
+.section sitob
+.section sitpa
+.section sitpb
+.section sitqa
+.section sitqb
+.section sitra
+.section sitrb
+.section sitsa
+.section sitsb
+.section sitta
+.section sittb
+.section situa
+.section situb
+.section sitva
+.section sitvb
+.section sitwa
+.section sitwb
+.section sitxa
+.section sitxb
+.section sitya
+.section sityb
+.section sitza
+.section sitzb
+.section sit1a
+.section sit1b
+.section sit2a
+.section sit2b
+.section sit3a
+.section sit3b
+.section sit4a
+.section sit4b
+.section sit5a
+.section sit5b
+.section sit6a
+.section sit6b
+.section sit7a
+.section sit7b
+.section sit8a
+.section sit8b
+.section sit9a
+.section sit9b
+.section sit0a
+.section sit0b
+.section siuaa
+.section siuab
+.section siuba
+.section siubb
+.section siuca
+.section siucb
+.section siuda
+.section siudb
+.section siuea
+.section siueb
+.section siufa
+.section siufb
+.section siuga
+.section siugb
+.section siuha
+.section siuhb
+.section siuia
+.section siuib
+.section siuja
+.section siujb
+.section siuka
+.section siukb
+.section siula
+.section siulb
+.section siuma
+.section siumb
+.section siuna
+.section siunb
+.section siuoa
+.section siuob
+.section siupa
+.section siupb
+.section siuqa
+.section siuqb
+.section siura
+.section siurb
+.section siusa
+.section siusb
+.section siuta
+.section siutb
+.section siuua
+.section siuub
+.section siuva
+.section siuvb
+.section siuwa
+.section siuwb
+.section siuxa
+.section siuxb
+.section siuya
+.section siuyb
+.section siuza
+.section siuzb
+.section siu1a
+.section siu1b
+.section siu2a
+.section siu2b
+.section siu3a
+.section siu3b
+.section siu4a
+.section siu4b
+.section siu5a
+.section siu5b
+.section siu6a
+.section siu6b
+.section siu7a
+.section siu7b
+.section siu8a
+.section siu8b
+.section siu9a
+.section siu9b
+.section siu0a
+.section siu0b
+.section sivaa
+.section sivab
+.section sivba
+.section sivbb
+.section sivca
+.section sivcb
+.section sivda
+.section sivdb
+.section sivea
+.section siveb
+.section sivfa
+.section sivfb
+.section sivga
+.section sivgb
+.section sivha
+.section sivhb
+.section sivia
+.section sivib
+.section sivja
+.section sivjb
+.section sivka
+.section sivkb
+.section sivla
+.section sivlb
+.section sivma
+.section sivmb
+.section sivna
+.section sivnb
+.section sivoa
+.section sivob
+.section sivpa
+.section sivpb
+.section sivqa
+.section sivqb
+.section sivra
+.section sivrb
+.section sivsa
+.section sivsb
+.section sivta
+.section sivtb
+.section sivua
+.section sivub
+.section sivva
+.section sivvb
+.section sivwa
+.section sivwb
+.section sivxa
+.section sivxb
+.section sivya
+.section sivyb
+.section sivza
+.section sivzb
+.section siv1a
+.section siv1b
+.section siv2a
+.section siv2b
+.section siv3a
+.section siv3b
+.section siv4a
+.section siv4b
+.section siv5a
+.section siv5b
+.section siv6a
+.section siv6b
+.section siv7a
+.section siv7b
+.section siv8a
+.section siv8b
+.section siv9a
+.section siv9b
+.section siv0a
+.section siv0b
+.section siwaa
+.section siwab
+.section siwba
+.section siwbb
+.section siwca
+.section siwcb
+.section siwda
+.section siwdb
+.section siwea
+.section siweb
+.section siwfa
+.section siwfb
+.section siwga
+.section siwgb
+.section siwha
+.section siwhb
+.section siwia
+.section siwib
+.section siwja
+.section siwjb
+.section siwka
+.section siwkb
+.section siwla
+.section siwlb
+.section siwma
+.section siwmb
+.section siwna
+.section siwnb
+.section siwoa
+.section siwob
+.section siwpa
+.section siwpb
+.section siwqa
+.section siwqb
+.section siwra
+.section siwrb
+.section siwsa
+.section siwsb
+.section siwta
+.section siwtb
+.section siwua
+.section siwub
+.section siwva
+.section siwvb
+.section siwwa
+.section siwwb
+.section siwxa
+.section siwxb
+.section siwya
+.section siwyb
+.section siwza
+.section siwzb
+.section siw1a
+.section siw1b
+.section siw2a
+.section siw2b
+.section siw3a
+.section siw3b
+.section siw4a
+.section siw4b
+.section siw5a
+.section siw5b
+.section siw6a
+.section siw6b
+.section siw7a
+.section siw7b
+.section siw8a
+.section siw8b
+.section siw9a
+.section siw9b
+.section siw0a
+.section siw0b
+.section sixaa
+.section sixab
+.section sixba
+.section sixbb
+.section sixca
+.section sixcb
+.section sixda
+.section sixdb
+.section sixea
+.section sixeb
+.section sixfa
+.section sixfb
+.section sixga
+.section sixgb
+.section sixha
+.section sixhb
+.section sixia
+.section sixib
+.section sixja
+.section sixjb
+.section sixka
+.section sixkb
+.section sixla
+.section sixlb
+.section sixma
+.section sixmb
+.section sixna
+.section sixnb
+.section sixoa
+.section sixob
+.section sixpa
+.section sixpb
+.section sixqa
+.section sixqb
+.section sixra
+.section sixrb
+.section sixsa
+.section sixsb
+.section sixta
+.section sixtb
+.section sixua
+.section sixub
+.section sixva
+.section sixvb
+.section sixwa
+.section sixwb
+.section sixxa
+.section sixxb
+.section sixya
+.section sixyb
+.section sixza
+.section sixzb
+.section six1a
+.section six1b
+.section six2a
+.section six2b
+.section six3a
+.section six3b
+.section six4a
+.section six4b
+.section six5a
+.section six5b
+.section six6a
+.section six6b
+.section six7a
+.section six7b
+.section six8a
+.section six8b
+.section six9a
+.section six9b
+.section six0a
+.section six0b
+.section siyaa
+.section siyab
+.section siyba
+.section siybb
+.section siyca
+.section siycb
+.section siyda
+.section siydb
+.section siyea
+.section siyeb
+.section siyfa
+.section siyfb
+.section siyga
+.section siygb
+.section siyha
+.section siyhb
+.section siyia
+.section siyib
+.section siyja
+.section siyjb
+.section siyka
+.section siykb
+.section siyla
+.section siylb
+.section siyma
+.section siymb
+.section siyna
+.section siynb
+.section siyoa
+.section siyob
+.section siypa
+.section siypb
+.section siyqa
+.section siyqb
+.section siyra
+.section siyrb
+.section siysa
+.section siysb
+.section siyta
+.section siytb
+.section siyua
+.section siyub
+.section siyva
+.section siyvb
+.section siywa
+.section siywb
+.section siyxa
+.section siyxb
+.section siyya
+.section siyyb
+.section siyza
+.section siyzb
+.section siy1a
+.section siy1b
+.section siy2a
+.section siy2b
+.section siy3a
+.section siy3b
+.section siy4a
+.section siy4b
+.section siy5a
+.section siy5b
+.section siy6a
+.section siy6b
+.section siy7a
+.section siy7b
+.section siy8a
+.section siy8b
+.section siy9a
+.section siy9b
+.section siy0a
+.section siy0b
+.section sizaa
+.section sizab
+.section sizba
+.section sizbb
+.section sizca
+.section sizcb
+.section sizda
+.section sizdb
+.section sizea
+.section sizeb
+.section sizfa
+.section sizfb
+.section sizga
+.section sizgb
+.section sizha
+.section sizhb
+.section sizia
+.section sizib
+.section sizja
+.section sizjb
+.section sizka
+.section sizkb
+.section sizla
+.section sizlb
+.section sizma
+.section sizmb
+.section sizna
+.section siznb
+.section sizoa
+.section sizob
+.section sizpa
+.section sizpb
+.section sizqa
+.section sizqb
+.section sizra
+.section sizrb
+.section sizsa
+.section sizsb
+.section sizta
+.section siztb
+.section sizua
+.section sizub
+.section sizva
+.section sizvb
+.section sizwa
+.section sizwb
+.section sizxa
+.section sizxb
+.section sizya
+.section sizyb
+.section sizza
+.section sizzb
+.section siz1a
+.section siz1b
+.section siz2a
+.section siz2b
+.section siz3a
+.section siz3b
+.section siz4a
+.section siz4b
+.section siz5a
+.section siz5b
+.section siz6a
+.section siz6b
+.section siz7a
+.section siz7b
+.section siz8a
+.section siz8b
+.section siz9a
+.section siz9b
+.section siz0a
+.section siz0b
+.section si1aa
+.section si1ab
+.section si1ba
+.section si1bb
+.section si1ca
+.section si1cb
+.section si1da
+.section si1db
+.section si1ea
+.section si1eb
+.section si1fa
+.section si1fb
+.section si1ga
+.section si1gb
+.section si1ha
+.section si1hb
+.section si1ia
+.section si1ib
+.section si1ja
+.section si1jb
+.section si1ka
+.section si1kb
+.section si1la
+.section si1lb
+.section si1ma
+.section si1mb
+.section si1na
+.section si1nb
+.section si1oa
+.section si1ob
+.section si1pa
+.section si1pb
+.section si1qa
+.section si1qb
+.section si1ra
+.section si1rb
+.section si1sa
+.section si1sb
+.section si1ta
+.section si1tb
+.section si1ua
+.section si1ub
+.section si1va
+.section si1vb
+.section si1wa
+.section si1wb
+.section si1xa
+.section si1xb
+.section si1ya
+.section si1yb
+.section si1za
+.section si1zb
+.section si11a
+.section si11b
+.section si12a
+.section si12b
+.section si13a
+.section si13b
+.section si14a
+.section si14b
+.section si15a
+.section si15b
+.section si16a
+.section si16b
+.section si17a
+.section si17b
+.section si18a
+.section si18b
+.section si19a
+.section si19b
+.section si10a
+.section si10b
+.section si2aa
+.section si2ab
+.section si2ba
+.section si2bb
+.section si2ca
+.section si2cb
+.section si2da
+.section si2db
+.section si2ea
+.section si2eb
+.section si2fa
+.section si2fb
+.section si2ga
+.section si2gb
+.section si2ha
+.section si2hb
+.section si2ia
+.section si2ib
+.section si2ja
+.section si2jb
+.section si2ka
+.section si2kb
+.section si2la
+.section si2lb
+.section si2ma
+.section si2mb
+.section si2na
+.section si2nb
+.section si2oa
+.section si2ob
+.section si2pa
+.section si2pb
+.section si2qa
+.section si2qb
+.section si2ra
+.section si2rb
+.section si2sa
+.section si2sb
+.section si2ta
+.section si2tb
+.section si2ua
+.section si2ub
+.section si2va
+.section si2vb
+.section si2wa
+.section si2wb
+.section si2xa
+.section si2xb
+.section si2ya
+.section si2yb
+.section si2za
+.section si2zb
+.section si21a
+.section si21b
+.section si22a
+.section si22b
+.section si23a
+.section si23b
+.section si24a
+.section si24b
+.section si25a
+.section si25b
+.section si26a
+.section si26b
+.section si27a
+.section si27b
+.section si28a
+.section si28b
+.section si29a
+.section si29b
+.section si20a
+.section si20b
+.section si3aa
+.section si3ab
+.section si3ba
+.section si3bb
+.section si3ca
+.section si3cb
+.section si3da
+.section si3db
+.section si3ea
+.section si3eb
+.section si3fa
+.section si3fb
+.section si3ga
+.section si3gb
+.section si3ha
+.section si3hb
+.section si3ia
+.section si3ib
+.section si3ja
+.section si3jb
+.section si3ka
+.section si3kb
+.section si3la
+.section si3lb
+.section si3ma
+.section si3mb
+.section si3na
+.section si3nb
+.section si3oa
+.section si3ob
+.section si3pa
+.section si3pb
+.section si3qa
+.section si3qb
+.section si3ra
+.section si3rb
+.section si3sa
+.section si3sb
+.section si3ta
+.section si3tb
+.section si3ua
+.section si3ub
+.section si3va
+.section si3vb
+.section si3wa
+.section si3wb
+.section si3xa
+.section si3xb
+.section si3ya
+.section si3yb
+.section si3za
+.section si3zb
+.section si31a
+.section si31b
+.section si32a
+.section si32b
+.section si33a
+.section si33b
+.section si34a
+.section si34b
+.section si35a
+.section si35b
+.section si36a
+.section si36b
+.section si37a
+.section si37b
+.section si38a
+.section si38b
+.section si39a
+.section si39b
+.section si30a
+.section si30b
+.section si4aa
+.section si4ab
+.section si4ba
+.section si4bb
+.section si4ca
+.section si4cb
+.section si4da
+.section si4db
+.section si4ea
+.section si4eb
+.section si4fa
+.section si4fb
+.section si4ga
+.section si4gb
+.section si4ha
+.section si4hb
+.section si4ia
+.section si4ib
+.section si4ja
+.section si4jb
+.section si4ka
+.section si4kb
+.section si4la
+.section si4lb
+.section si4ma
+.section si4mb
+.section si4na
+.section si4nb
+.section si4oa
+.section si4ob
+.section si4pa
+.section si4pb
+.section si4qa
+.section si4qb
+.section si4ra
+.section si4rb
+.section si4sa
+.section si4sb
+.section si4ta
+.section si4tb
+.section si4ua
+.section si4ub
+.section si4va
+.section si4vb
+.section si4wa
+.section si4wb
+.section si4xa
+.section si4xb
+.section si4ya
+.section si4yb
+.section si4za
+.section si4zb
+.section si41a
+.section si41b
+.section si42a
+.section si42b
+.section si43a
+.section si43b
+.section si44a
+.section si44b
+.section si45a
+.section si45b
+.section si46a
+.section si46b
+.section si47a
+.section si47b
+.section si48a
+.section si48b
+.section si49a
+.section si49b
+.section si40a
+.section si40b
+.section si5aa
+.section si5ab
+.section si5ba
+.section si5bb
+.section si5ca
+.section si5cb
+.section si5da
+.section si5db
+.section si5ea
+.section si5eb
+.section si5fa
+.section si5fb
+.section si5ga
+.section si5gb
+.section si5ha
+.section si5hb
+.section si5ia
+.section si5ib
+.section si5ja
+.section si5jb
+.section si5ka
+.section si5kb
+.section si5la
+.section si5lb
+.section si5ma
+.section si5mb
+.section si5na
+.section si5nb
+.section si5oa
+.section si5ob
+.section si5pa
+.section si5pb
+.section si5qa
+.section si5qb
+.section si5ra
+.section si5rb
+.section si5sa
+.section si5sb
+.section si5ta
+.section si5tb
+.section si5ua
+.section si5ub
+.section si5va
+.section si5vb
+.section si5wa
+.section si5wb
+.section si5xa
+.section si5xb
+.section si5ya
+.section si5yb
+.section si5za
+.section si5zb
+.section si51a
+.section si51b
+.section si52a
+.section si52b
+.section si53a
+.section si53b
+.section si54a
+.section si54b
+.section si55a
+.section si55b
+.section si56a
+.section si56b
+.section si57a
+.section si57b
+.section si58a
+.section si58b
+.section si59a
+.section si59b
+.section si50a
+.section si50b
+.section si6aa
+.section si6ab
+.section si6ba
+.section si6bb
+.section si6ca
+.section si6cb
+.section si6da
+.section si6db
+.section si6ea
+.section si6eb
+.section si6fa
+.section si6fb
+.section si6ga
+.section si6gb
+.section si6ha
+.section si6hb
+.section si6ia
+.section si6ib
+.section si6ja
+.section si6jb
+.section si6ka
+.section si6kb
+.section si6la
+.section si6lb
+.section si6ma
+.section si6mb
+.section si6na
+.section si6nb
+.section si6oa
+.section si6ob
+.section si6pa
+.section si6pb
+.section si6qa
+.section si6qb
+.section si6ra
+.section si6rb
+.section si6sa
+.section si6sb
+.section si6ta
+.section si6tb
+.section si6ua
+.section si6ub
+.section si6va
+.section si6vb
+.section si6wa
+.section si6wb
+.section si6xa
+.section si6xb
+.section si6ya
+.section si6yb
+.section si6za
+.section si6zb
+.section si61a
+.section si61b
+.section si62a
+.section si62b
+.section si63a
+.section si63b
+.section si64a
+.section si64b
+.section si65a
+.section si65b
+.section si66a
+.section si66b
+.section si67a
+.section si67b
+.section si68a
+.section si68b
+.section si69a
+.section si69b
+.section si60a
+.section si60b
+.section si7aa
+.section si7ab
+.section si7ba
+.section si7bb
+.section si7ca
+.section si7cb
+.section si7da
+.section si7db
+.section si7ea
+.section si7eb
+.section si7fa
+.section si7fb
+.section si7ga
+.section si7gb
+.section si7ha
+.section si7hb
+.section si7ia
+.section si7ib
+.section si7ja
+.section si7jb
+.section si7ka
+.section si7kb
+.section si7la
+.section si7lb
+.section si7ma
+.section si7mb
+.section si7na
+.section si7nb
+.section si7oa
+.section si7ob
+.section si7pa
+.section si7pb
+.section si7qa
+.section si7qb
+.section si7ra
+.section si7rb
+.section si7sa
+.section si7sb
+.section si7ta
+.section si7tb
+.section si7ua
+.section si7ub
+.section si7va
+.section si7vb
+.section si7wa
+.section si7wb
+.section si7xa
+.section si7xb
+.section si7ya
+.section si7yb
+.section si7za
+.section si7zb
+.section si71a
+.section si71b
+.section si72a
+.section si72b
+.section si73a
+.section si73b
+.section si74a
+.section si74b
+.section si75a
+.section si75b
+.section si76a
+.section si76b
+.section si77a
+.section si77b
+.section si78a
+.section si78b
+.section si79a
+.section si79b
+.section si70a
+.section si70b
+.section si8aa
+.section si8ab
+.section si8ba
+.section si8bb
+.section si8ca
+.section si8cb
+.section si8da
+.section si8db
+.section si8ea
+.section si8eb
+.section si8fa
+.section si8fb
+.section si8ga
+.section si8gb
+.section si8ha
+.section si8hb
+.section si8ia
+.section si8ib
+.section si8ja
+.section si8jb
+.section si8ka
+.section si8kb
+.section si8la
+.section si8lb
+.section si8ma
+.section si8mb
+.section si8na
+.section si8nb
+.section si8oa
+.section si8ob
+.section si8pa
+.section si8pb
+.section si8qa
+.section si8qb
+.section si8ra
+.section si8rb
+.section si8sa
+.section si8sb
+.section si8ta
+.section si8tb
+.section si8ua
+.section si8ub
+.section si8va
+.section si8vb
+.section si8wa
+.section si8wb
+.section si8xa
+.section si8xb
+.section si8ya
+.section si8yb
+.section si8za
+.section si8zb
+.section si81a
+.section si81b
+.section si82a
+.section si82b
+.section si83a
+.section si83b
+.section si84a
+.section si84b
+.section si85a
+.section si85b
+.section si86a
+.section si86b
+.section si87a
+.section si87b
+.section si88a
+.section si88b
+.section si89a
+.section si89b
+.section si80a
+.section si80b
+.section si9aa
+.section si9ab
+.section si9ba
+.section si9bb
+.section si9ca
+.section si9cb
+.section si9da
+.section si9db
+.section si9ea
+.section si9eb
+.section si9fa
+.section si9fb
+.section si9ga
+.section si9gb
+.section si9ha
+.section si9hb
+.section si9ia
+.section si9ib
+.section si9ja
+.section si9jb
+.section si9ka
+.section si9kb
+.section si9la
+.section si9lb
+.section si9ma
+.section si9mb
+.section si9na
+.section si9nb
+.section si9oa
+.section si9ob
+.section si9pa
+.section si9pb
+.section si9qa
+.section si9qb
+.section si9ra
+.section si9rb
+.section si9sa
+.section si9sb
+.section si9ta
+.section si9tb
+.section si9ua
+.section si9ub
+.section si9va
+.section si9vb
+.section si9wa
+.section si9wb
+.section si9xa
+.section si9xb
+.section si9ya
+.section si9yb
+.section si9za
+.section si9zb
+.section si91a
+.section si91b
+.section si92a
+.section si92b
+.section si93a
+.section si93b
+.section si94a
+.section si94b
+.section si95a
+.section si95b
+.section si96a
+.section si96b
+.section si97a
+.section si97b
+.section si98a
+.section si98b
+.section si99a
+.section si99b
+.section si90a
+.section si90b
+.section si0aa
+.section si0ab
+.section si0ba
+.section si0bb
+.section si0ca
+.section si0cb
+.section si0da
+.section si0db
+.section si0ea
+.section si0eb
+.section si0fa
+.section si0fb
+.section si0ga
+.section si0gb
+.section si0ha
+.section si0hb
+.section si0ia
+.section si0ib
+.section si0ja
+.section si0jb
+.section si0ka
+.section si0kb
+.section si0la
+.section si0lb
+.section si0ma
+.section si0mb
+.section si0na
+.section si0nb
+.section si0oa
+.section si0ob
+.section si0pa
+.section si0pb
+.section si0qa
+.section si0qb
+.section si0ra
+.section si0rb
+.section si0sa
+.section si0sb
+.section si0ta
+.section si0tb
+.section si0ua
+.section si0ub
+.section si0va
+.section si0vb
+.section si0wa
+.section si0wb
+.section si0xa
+.section si0xb
+.section si0ya
+.section si0yb
+.section si0za
+.section si0zb
+.section si01a
+.section si01b
+.section si02a
+.section si02b
+.section si03a
+.section si03b
+.section si04a
+.section si04b
+.section si05a
+.section si05b
+.section si06a
+.section si06b
+.section si07a
+.section si07b
+.section si08a
+.section si08b
+.section si09a
+.section si09b
+.section si00a
+.section si00b
+.section sjaaa
+.section sjaab
+.section sjaba
+.section sjabb
+.section sjaca
+.section sjacb
+.section sjada
+.section sjadb
+.section sjaea
+.section sjaeb
+.section sjafa
+.section sjafb
+.section sjaga
+.section sjagb
+.section sjaha
+.section sjahb
+.section sjaia
+.section sjaib
+.section sjaja
+.section sjajb
+.section sjaka
+.section sjakb
+.section sjala
+.section sjalb
+.section sjama
+.section sjamb
+.section sjana
+.section sjanb
+.section sjaoa
+.section sjaob
+.section sjapa
+.section sjapb
+.section sjaqa
+.section sjaqb
+.section sjara
+.section sjarb
+.section sjasa
+.section sjasb
+.section sjata
+.section sjatb
+.section sjaua
+.section sjaub
+.section sjava
+.section sjavb
+.section sjawa
+.section sjawb
+.section sjaxa
+.section sjaxb
+.section sjaya
+.section sjayb
+.section sjaza
+.section sjazb
+.section sja1a
+.section sja1b
+.section sja2a
+.section sja2b
+.section sja3a
+.section sja3b
+.section sja4a
+.section sja4b
+.section sja5a
+.section sja5b
+.section sja6a
+.section sja6b
+.section sja7a
+.section sja7b
+.section sja8a
+.section sja8b
+.section sja9a
+.section sja9b
+.section sja0a
+.section sja0b
+.section sjbaa
+.section sjbab
+.section sjbba
+.section sjbbb
+.section sjbca
+.section sjbcb
+.section sjbda
+.section sjbdb
+.section sjbea
+.section sjbeb
+.section sjbfa
+.section sjbfb
+.section sjbga
+.section sjbgb
+.section sjbha
+.section sjbhb
+.section sjbia
+.section sjbib
+.section sjbja
+.section sjbjb
+.section sjbka
+.section sjbkb
+.section sjbla
+.section sjblb
+.section sjbma
+.section sjbmb
+.section sjbna
+.section sjbnb
+.section sjboa
+.section sjbob
+.section sjbpa
+.section sjbpb
+.section sjbqa
+.section sjbqb
+.section sjbra
+.section sjbrb
+.section sjbsa
+.section sjbsb
+.section sjbta
+.section sjbtb
+.section sjbua
+.section sjbub
+.section sjbva
+.section sjbvb
+.section sjbwa
+.section sjbwb
+.section sjbxa
+.section sjbxb
+.section sjbya
+.section sjbyb
+.section sjbza
+.section sjbzb
+.section sjb1a
+.section sjb1b
+.section sjb2a
+.section sjb2b
+.section sjb3a
+.section sjb3b
+.section sjb4a
+.section sjb4b
+.section sjb5a
+.section sjb5b
+.section sjb6a
+.section sjb6b
+.section sjb7a
+.section sjb7b
+.section sjb8a
+.section sjb8b
+.section sjb9a
+.section sjb9b
+.section sjb0a
+.section sjb0b
+.section sjcaa
+.section sjcab
+.section sjcba
+.section sjcbb
+.section sjcca
+.section sjccb
+.section sjcda
+.section sjcdb
+.section sjcea
+.section sjceb
+.section sjcfa
+.section sjcfb
+.section sjcga
+.section sjcgb
+.section sjcha
+.section sjchb
+.section sjcia
+.section sjcib
+.section sjcja
+.section sjcjb
+.section sjcka
+.section sjckb
+.section sjcla
+.section sjclb
+.section sjcma
+.section sjcmb
+.section sjcna
+.section sjcnb
+.section sjcoa
+.section sjcob
+.section sjcpa
+.section sjcpb
+.section sjcqa
+.section sjcqb
+.section sjcra
+.section sjcrb
+.section sjcsa
+.section sjcsb
+.section sjcta
+.section sjctb
+.section sjcua
+.section sjcub
+.section sjcva
+.section sjcvb
+.section sjcwa
+.section sjcwb
+.section sjcxa
+.section sjcxb
+.section sjcya
+.section sjcyb
+.section sjcza
+.section sjczb
+.section sjc1a
+.section sjc1b
+.section sjc2a
+.section sjc2b
+.section sjc3a
+.section sjc3b
+.section sjc4a
+.section sjc4b
+.section sjc5a
+.section sjc5b
+.section sjc6a
+.section sjc6b
+.section sjc7a
+.section sjc7b
+.section sjc8a
+.section sjc8b
+.section sjc9a
+.section sjc9b
+.section sjc0a
+.section sjc0b
+.section sjdaa
+.section sjdab
+.section sjdba
+.section sjdbb
+.section sjdca
+.section sjdcb
+.section sjdda
+.section sjddb
+.section sjdea
+.section sjdeb
+.section sjdfa
+.section sjdfb
+.section sjdga
+.section sjdgb
+.section sjdha
+.section sjdhb
+.section sjdia
+.section sjdib
+.section sjdja
+.section sjdjb
+.section sjdka
+.section sjdkb
+.section sjdla
+.section sjdlb
+.section sjdma
+.section sjdmb
+.section sjdna
+.section sjdnb
+.section sjdoa
+.section sjdob
+.section sjdpa
+.section sjdpb
+.section sjdqa
+.section sjdqb
+.section sjdra
+.section sjdrb
+.section sjdsa
+.section sjdsb
+.section sjdta
+.section sjdtb
+.section sjdua
+.section sjdub
+.section sjdva
+.section sjdvb
+.section sjdwa
+.section sjdwb
+.section sjdxa
+.section sjdxb
+.section sjdya
+.section sjdyb
+.section sjdza
+.section sjdzb
+.section sjd1a
+.section sjd1b
+.section sjd2a
+.section sjd2b
+.section sjd3a
+.section sjd3b
+.section sjd4a
+.section sjd4b
+.section sjd5a
+.section sjd5b
+.section sjd6a
+.section sjd6b
+.section sjd7a
+.section sjd7b
+.section sjd8a
+.section sjd8b
+.section sjd9a
+.section sjd9b
+.section sjd0a
+.section sjd0b
+.section sjeaa
+.section sjeab
+.section sjeba
+.section sjebb
+.section sjeca
+.section sjecb
+.section sjeda
+.section sjedb
+.section sjeea
+.section sjeeb
+.section sjefa
+.section sjefb
+.section sjega
+.section sjegb
+.section sjeha
+.section sjehb
+.section sjeia
+.section sjeib
+.section sjeja
+.section sjejb
+.section sjeka
+.section sjekb
+.section sjela
+.section sjelb
+.section sjema
+.section sjemb
+.section sjena
+.section sjenb
+.section sjeoa
+.section sjeob
+.section sjepa
+.section sjepb
+.section sjeqa
+.section sjeqb
+.section sjera
+.section sjerb
+.section sjesa
+.section sjesb
+.section sjeta
+.section sjetb
+.section sjeua
+.section sjeub
+.section sjeva
+.section sjevb
+.section sjewa
+.section sjewb
+.section sjexa
+.section sjexb
+.section sjeya
+.section sjeyb
+.section sjeza
+.section sjezb
+.section sje1a
+.section sje1b
+.section sje2a
+.section sje2b
+.section sje3a
+.section sje3b
+.section sje4a
+.section sje4b
+.section sje5a
+.section sje5b
+.section sje6a
+.section sje6b
+.section sje7a
+.section sje7b
+.section sje8a
+.section sje8b
+.section sje9a
+.section sje9b
+.section sje0a
+.section sje0b
+.section sjfaa
+.section sjfab
+.section sjfba
+.section sjfbb
+.section sjfca
+.section sjfcb
+.section sjfda
+.section sjfdb
+.section sjfea
+.section sjfeb
+.section sjffa
+.section sjffb
+.section sjfga
+.section sjfgb
+.section sjfha
+.section sjfhb
+.section sjfia
+.section sjfib
+.section sjfja
+.section sjfjb
+.section sjfka
+.section sjfkb
+.section sjfla
+.section sjflb
+.section sjfma
+.section sjfmb
+.section sjfna
+.section sjfnb
+.section sjfoa
+.section sjfob
+.section sjfpa
+.section sjfpb
+.section sjfqa
+.section sjfqb
+.section sjfra
+.section sjfrb
+.section sjfsa
+.section sjfsb
+.section sjfta
+.section sjftb
+.section sjfua
+.section sjfub
+.section sjfva
+.section sjfvb
+.section sjfwa
+.section sjfwb
+.section sjfxa
+.section sjfxb
+.section sjfya
+.section sjfyb
+.section sjfza
+.section sjfzb
+.section sjf1a
+.section sjf1b
+.section sjf2a
+.section sjf2b
+.section sjf3a
+.section sjf3b
+.section sjf4a
+.section sjf4b
+.section sjf5a
+.section sjf5b
+.section sjf6a
+.section sjf6b
+.section sjf7a
+.section sjf7b
+.section sjf8a
+.section sjf8b
+.section sjf9a
+.section sjf9b
+.section sjf0a
+.section sjf0b
+.section sjgaa
+.section sjgab
+.section sjgba
+.section sjgbb
+.section sjgca
+.section sjgcb
+.section sjgda
+.section sjgdb
+.section sjgea
+.section sjgeb
+.section sjgfa
+.section sjgfb
+.section sjgga
+.section sjggb
+.section sjgha
+.section sjghb
+.section sjgia
+.section sjgib
+.section sjgja
+.section sjgjb
+.section sjgka
+.section sjgkb
+.section sjgla
+.section sjglb
+.section sjgma
+.section sjgmb
+.section sjgna
+.section sjgnb
+.section sjgoa
+.section sjgob
+.section sjgpa
+.section sjgpb
+.section sjgqa
+.section sjgqb
+.section sjgra
+.section sjgrb
+.section sjgsa
+.section sjgsb
+.section sjgta
+.section sjgtb
+.section sjgua
+.section sjgub
+.section sjgva
+.section sjgvb
+.section sjgwa
+.section sjgwb
+.section sjgxa
+.section sjgxb
+.section sjgya
+.section sjgyb
+.section sjgza
+.section sjgzb
+.section sjg1a
+.section sjg1b
+.section sjg2a
+.section sjg2b
+.section sjg3a
+.section sjg3b
+.section sjg4a
+.section sjg4b
+.section sjg5a
+.section sjg5b
+.section sjg6a
+.section sjg6b
+.section sjg7a
+.section sjg7b
+.section sjg8a
+.section sjg8b
+.section sjg9a
+.section sjg9b
+.section sjg0a
+.section sjg0b
+.section sjhaa
+.section sjhab
+.section sjhba
+.section sjhbb
+.section sjhca
+.section sjhcb
+.section sjhda
+.section sjhdb
+.section sjhea
+.section sjheb
+.section sjhfa
+.section sjhfb
+.section sjhga
+.section sjhgb
+.section sjhha
+.section sjhhb
+.section sjhia
+.section sjhib
+.section sjhja
+.section sjhjb
+.section sjhka
+.section sjhkb
+.section sjhla
+.section sjhlb
+.section sjhma
+.section sjhmb
+.section sjhna
+.section sjhnb
+.section sjhoa
+.section sjhob
+.section sjhpa
+.section sjhpb
+.section sjhqa
+.section sjhqb
+.section sjhra
+.section sjhrb
+.section sjhsa
+.section sjhsb
+.section sjhta
+.section sjhtb
+.section sjhua
+.section sjhub
+.section sjhva
+.section sjhvb
+.section sjhwa
+.section sjhwb
+.section sjhxa
+.section sjhxb
+.section sjhya
+.section sjhyb
+.section sjhza
+.section sjhzb
+.section sjh1a
+.section sjh1b
+.section sjh2a
+.section sjh2b
+.section sjh3a
+.section sjh3b
+.section sjh4a
+.section sjh4b
+.section sjh5a
+.section sjh5b
+.section sjh6a
+.section sjh6b
+.section sjh7a
+.section sjh7b
+.section sjh8a
+.section sjh8b
+.section sjh9a
+.section sjh9b
+.section sjh0a
+.section sjh0b
+.section sjiaa
+.section sjiab
+.section sjiba
+.section sjibb
+.section sjica
+.section sjicb
+.section sjida
+.section sjidb
+.section sjiea
+.section sjieb
+.section sjifa
+.section sjifb
+.section sjiga
+.section sjigb
+.section sjiha
+.section sjihb
+.section sjiia
+.section sjiib
+.section sjija
+.section sjijb
+.section sjika
+.section sjikb
+.section sjila
+.section sjilb
+.section sjima
+.section sjimb
+.section sjina
+.section sjinb
+.section sjioa
+.section sjiob
+.section sjipa
+.section sjipb
+.section sjiqa
+.section sjiqb
+.section sjira
+.section sjirb
+.section sjisa
+.section sjisb
+.section sjita
+.section sjitb
+.section sjiua
+.section sjiub
+.section sjiva
+.section sjivb
+.section sjiwa
+.section sjiwb
+.section sjixa
+.section sjixb
+.section sjiya
+.section sjiyb
+.section sjiza
+.section sjizb
+.section sji1a
+.section sji1b
+.section sji2a
+.section sji2b
+.section sji3a
+.section sji3b
+.section sji4a
+.section sji4b
+.section sji5a
+.section sji5b
+.section sji6a
+.section sji6b
+.section sji7a
+.section sji7b
+.section sji8a
+.section sji8b
+.section sji9a
+.section sji9b
+.section sji0a
+.section sji0b
+.section sjjaa
+.section sjjab
+.section sjjba
+.section sjjbb
+.section sjjca
+.section sjjcb
+.section sjjda
+.section sjjdb
+.section sjjea
+.section sjjeb
+.section sjjfa
+.section sjjfb
+.section sjjga
+.section sjjgb
+.section sjjha
+.section sjjhb
+.section sjjia
+.section sjjib
+.section sjjja
+.section sjjjb
+.section sjjka
+.section sjjkb
+.section sjjla
+.section sjjlb
+.section sjjma
+.section sjjmb
+.section sjjna
+.section sjjnb
+.section sjjoa
+.section sjjob
+.section sjjpa
+.section sjjpb
+.section sjjqa
+.section sjjqb
+.section sjjra
+.section sjjrb
+.section sjjsa
+.section sjjsb
+.section sjjta
+.section sjjtb
+.section sjjua
+.section sjjub
+.section sjjva
+.section sjjvb
+.section sjjwa
+.section sjjwb
+.section sjjxa
+.section sjjxb
+.section sjjya
+.section sjjyb
+.section sjjza
+.section sjjzb
+.section sjj1a
+.section sjj1b
+.section sjj2a
+.section sjj2b
+.section sjj3a
+.section sjj3b
+.section sjj4a
+.section sjj4b
+.section sjj5a
+.section sjj5b
+.section sjj6a
+.section sjj6b
+.section sjj7a
+.section sjj7b
+.section sjj8a
+.section sjj8b
+.section sjj9a
+.section sjj9b
+.section sjj0a
+.section sjj0b
+.section sjkaa
+.section sjkab
+.section sjkba
+.section sjkbb
+.section sjkca
+.section sjkcb
+.section sjkda
+.section sjkdb
+.section sjkea
+.section sjkeb
+.section sjkfa
+.section sjkfb
+.section sjkga
+.section sjkgb
+.section sjkha
+.section sjkhb
+.section sjkia
+.section sjkib
+.section sjkja
+.section sjkjb
+.section sjkka
+.section sjkkb
+.section sjkla
+.section sjklb
+.section sjkma
+.section sjkmb
+.section sjkna
+.section sjknb
+.section sjkoa
+.section sjkob
+.section sjkpa
+.section sjkpb
+.section sjkqa
+.section sjkqb
+.section sjkra
+.section sjkrb
+.section sjksa
+.section sjksb
+.section sjkta
+.section sjktb
+.section sjkua
+.section sjkub
+.section sjkva
+.section sjkvb
+.section sjkwa
+.section sjkwb
+.section sjkxa
+.section sjkxb
+.section sjkya
+.section sjkyb
+.section sjkza
+.section sjkzb
+.section sjk1a
+.section sjk1b
+.section sjk2a
+.section sjk2b
+.section sjk3a
+.section sjk3b
+.section sjk4a
+.section sjk4b
+.section sjk5a
+.section sjk5b
+.section sjk6a
+.section sjk6b
+.section sjk7a
+.section sjk7b
+.section sjk8a
+.section sjk8b
+.section sjk9a
+.section sjk9b
+.section sjk0a
+.section sjk0b
+.section sjlaa
+.section sjlab
+.section sjlba
+.section sjlbb
+.section sjlca
+.section sjlcb
+.section sjlda
+.section sjldb
+.section sjlea
+.section sjleb
+.section sjlfa
+.section sjlfb
+.section sjlga
+.section sjlgb
+.section sjlha
+.section sjlhb
+.section sjlia
+.section sjlib
+.section sjlja
+.section sjljb
+.section sjlka
+.section sjlkb
+.section sjlla
+.section sjllb
+.section sjlma
+.section sjlmb
+.section sjlna
+.section sjlnb
+.section sjloa
+.section sjlob
+.section sjlpa
+.section sjlpb
+.section sjlqa
+.section sjlqb
+.section sjlra
+.section sjlrb
+.section sjlsa
+.section sjlsb
+.section sjlta
+.section sjltb
+.section sjlua
+.section sjlub
+.section sjlva
+.section sjlvb
+.section sjlwa
+.section sjlwb
+.section sjlxa
+.section sjlxb
+.section sjlya
+.section sjlyb
+.section sjlza
+.section sjlzb
+.section sjl1a
+.section sjl1b
+.section sjl2a
+.section sjl2b
+.section sjl3a
+.section sjl3b
+.section sjl4a
+.section sjl4b
+.section sjl5a
+.section sjl5b
+.section sjl6a
+.section sjl6b
+.section sjl7a
+.section sjl7b
+.section sjl8a
+.section sjl8b
+.section sjl9a
+.section sjl9b
+.section sjl0a
+.section sjl0b
+.section sjmaa
+.section sjmab
+.section sjmba
+.section sjmbb
+.section sjmca
+.section sjmcb
+.section sjmda
+.section sjmdb
+.section sjmea
+.section sjmeb
+.section sjmfa
+.section sjmfb
+.section sjmga
+.section sjmgb
+.section sjmha
+.section sjmhb
+.section sjmia
+.section sjmib
+.section sjmja
+.section sjmjb
+.section sjmka
+.section sjmkb
+.section sjmla
+.section sjmlb
+.section sjmma
+.section sjmmb
+.section sjmna
+.section sjmnb
+.section sjmoa
+.section sjmob
+.section sjmpa
+.section sjmpb
+.section sjmqa
+.section sjmqb
+.section sjmra
+.section sjmrb
+.section sjmsa
+.section sjmsb
+.section sjmta
+.section sjmtb
+.section sjmua
+.section sjmub
+.section sjmva
+.section sjmvb
+.section sjmwa
+.section sjmwb
+.section sjmxa
+.section sjmxb
+.section sjmya
+.section sjmyb
+.section sjmza
+.section sjmzb
+.section sjm1a
+.section sjm1b
+.section sjm2a
+.section sjm2b
+.section sjm3a
+.section sjm3b
+.section sjm4a
+.section sjm4b
+.section sjm5a
+.section sjm5b
+.section sjm6a
+.section sjm6b
+.section sjm7a
+.section sjm7b
+.section sjm8a
+.section sjm8b
+.section sjm9a
+.section sjm9b
+.section sjm0a
+.section sjm0b
+.section sjnaa
+.section sjnab
+.section sjnba
+.section sjnbb
+.section sjnca
+.section sjncb
+.section sjnda
+.section sjndb
+.section sjnea
+.section sjneb
+.section sjnfa
+.section sjnfb
+.section sjnga
+.section sjngb
+.section sjnha
+.section sjnhb
+.section sjnia
+.section sjnib
+.section sjnja
+.section sjnjb
+.section sjnka
+.section sjnkb
+.section sjnla
+.section sjnlb
+.section sjnma
+.section sjnmb
+.section sjnna
+.section sjnnb
+.section sjnoa
+.section sjnob
+.section sjnpa
+.section sjnpb
+.section sjnqa
+.section sjnqb
+.section sjnra
+.section sjnrb
+.section sjnsa
+.section sjnsb
+.section sjnta
+.section sjntb
+.section sjnua
+.section sjnub
+.section sjnva
+.section sjnvb
+.section sjnwa
+.section sjnwb
+.section sjnxa
+.section sjnxb
+.section sjnya
+.section sjnyb
+.section sjnza
+.section sjnzb
+.section sjn1a
+.section sjn1b
+.section sjn2a
+.section sjn2b
+.section sjn3a
+.section sjn3b
+.section sjn4a
+.section sjn4b
+.section sjn5a
+.section sjn5b
+.section sjn6a
+.section sjn6b
+.section sjn7a
+.section sjn7b
+.section sjn8a
+.section sjn8b
+.section sjn9a
+.section sjn9b
+.section sjn0a
+.section sjn0b
+.section sjoaa
+.section sjoab
+.section sjoba
+.section sjobb
+.section sjoca
+.section sjocb
+.section sjoda
+.section sjodb
+.section sjoea
+.section sjoeb
+.section sjofa
+.section sjofb
+.section sjoga
+.section sjogb
+.section sjoha
+.section sjohb
+.section sjoia
+.section sjoib
+.section sjoja
+.section sjojb
+.section sjoka
+.section sjokb
+.section sjola
+.section sjolb
+.section sjoma
+.section sjomb
+.section sjona
+.section sjonb
+.section sjooa
+.section sjoob
+.section sjopa
+.section sjopb
+.section sjoqa
+.section sjoqb
+.section sjora
+.section sjorb
+.section sjosa
+.section sjosb
+.section sjota
+.section sjotb
+.section sjoua
+.section sjoub
+.section sjova
+.section sjovb
+.section sjowa
+.section sjowb
+.section sjoxa
+.section sjoxb
+.section sjoya
+.section sjoyb
+.section sjoza
+.section sjozb
+.section sjo1a
+.section sjo1b
+.section sjo2a
+.section sjo2b
+.section sjo3a
+.section sjo3b
+.section sjo4a
+.section sjo4b
+.section sjo5a
+.section sjo5b
+.section sjo6a
+.section sjo6b
+.section sjo7a
+.section sjo7b
+.section sjo8a
+.section sjo8b
+.section sjo9a
+.section sjo9b
+.section sjo0a
+.section sjo0b
+.section sjpaa
+.section sjpab
+.section sjpba
+.section sjpbb
+.section sjpca
+.section sjpcb
+.section sjpda
+.section sjpdb
+.section sjpea
+.section sjpeb
+.section sjpfa
+.section sjpfb
+.section sjpga
+.section sjpgb
+.section sjpha
+.section sjphb
+.section sjpia
+.section sjpib
+.section sjpja
+.section sjpjb
+.section sjpka
+.section sjpkb
+.section sjpla
+.section sjplb
+.section sjpma
+.section sjpmb
+.section sjpna
+.section sjpnb
+.section sjpoa
+.section sjpob
+.section sjppa
+.section sjppb
+.section sjpqa
+.section sjpqb
+.section sjpra
+.section sjprb
+.section sjpsa
+.section sjpsb
+.section sjpta
+.section sjptb
+.section sjpua
+.section sjpub
+.section sjpva
+.section sjpvb
+.section sjpwa
+.section sjpwb
+.section sjpxa
+.section sjpxb
+.section sjpya
+.section sjpyb
+.section sjpza
+.section sjpzb
+.section sjp1a
+.section sjp1b
+.section sjp2a
+.section sjp2b
+.section sjp3a
+.section sjp3b
+.section sjp4a
+.section sjp4b
+.section sjp5a
+.section sjp5b
+.section sjp6a
+.section sjp6b
+.section sjp7a
+.section sjp7b
+.section sjp8a
+.section sjp8b
+.section sjp9a
+.section sjp9b
+.section sjp0a
+.section sjp0b
+.section sjqaa
+.section sjqab
+.section sjqba
+.section sjqbb
+.section sjqca
+.section sjqcb
+.section sjqda
+.section sjqdb
+.section sjqea
+.section sjqeb
+.section sjqfa
+.section sjqfb
+.section sjqga
+.section sjqgb
+.section sjqha
+.section sjqhb
+.section sjqia
+.section sjqib
+.section sjqja
+.section sjqjb
+.section sjqka
+.section sjqkb
+.section sjqla
+.section sjqlb
+.section sjqma
+.section sjqmb
+.section sjqna
+.section sjqnb
+.section sjqoa
+.section sjqob
+.section sjqpa
+.section sjqpb
+.section sjqqa
+.section sjqqb
+.section sjqra
+.section sjqrb
+.section sjqsa
+.section sjqsb
+.section sjqta
+.section sjqtb
+.section sjqua
+.section sjqub
+.section sjqva
+.section sjqvb
+.section sjqwa
+.section sjqwb
+.section sjqxa
+.section sjqxb
+.section sjqya
+.section sjqyb
+.section sjqza
+.section sjqzb
+.section sjq1a
+.section sjq1b
+.section sjq2a
+.section sjq2b
+.section sjq3a
+.section sjq3b
+.section sjq4a
+.section sjq4b
+.section sjq5a
+.section sjq5b
+.section sjq6a
+.section sjq6b
+.section sjq7a
+.section sjq7b
+.section sjq8a
+.section sjq8b
+.section sjq9a
+.section sjq9b
+.section sjq0a
+.section sjq0b
+.section sjraa
+.section sjrab
+.section sjrba
+.section sjrbb
+.section sjrca
+.section sjrcb
+.section sjrda
+.section sjrdb
+.section sjrea
+.section sjreb
+.section sjrfa
+.section sjrfb
+.section sjrga
+.section sjrgb
+.section sjrha
+.section sjrhb
+.section sjria
+.section sjrib
+.section sjrja
+.section sjrjb
+.section sjrka
+.section sjrkb
+.section sjrla
+.section sjrlb
+.section sjrma
+.section sjrmb
+.section sjrna
+.section sjrnb
+.section sjroa
+.section sjrob
+.section sjrpa
+.section sjrpb
+.section sjrqa
+.section sjrqb
+.section sjrra
+.section sjrrb
+.section sjrsa
+.section sjrsb
+.section sjrta
+.section sjrtb
+.section sjrua
+.section sjrub
+.section sjrva
+.section sjrvb
+.section sjrwa
+.section sjrwb
+.section sjrxa
+.section sjrxb
+.section sjrya
+.section sjryb
+.section sjrza
+.section sjrzb
+.section sjr1a
+.section sjr1b
+.section sjr2a
+.section sjr2b
+.section sjr3a
+.section sjr3b
+.section sjr4a
+.section sjr4b
+.section sjr5a
+.section sjr5b
+.section sjr6a
+.section sjr6b
+.section sjr7a
+.section sjr7b
+.section sjr8a
+.section sjr8b
+.section sjr9a
+.section sjr9b
+.section sjr0a
+.section sjr0b
+.section sjsaa
+.section sjsab
+.section sjsba
+.section sjsbb
+.section sjsca
+.section sjscb
+.section sjsda
+.section sjsdb
+.section sjsea
+.section sjseb
+.section sjsfa
+.section sjsfb
+.section sjsga
+.section sjsgb
+.section sjsha
+.section sjshb
+.section sjsia
+.section sjsib
+.section sjsja
+.section sjsjb
+.section sjska
+.section sjskb
+.section sjsla
+.section sjslb
+.section sjsma
+.section sjsmb
+.section sjsna
+.section sjsnb
+.section sjsoa
+.section sjsob
+.section sjspa
+.section sjspb
+.section sjsqa
+.section sjsqb
+.section sjsra
+.section sjsrb
+.section sjssa
+.section sjssb
+.section sjsta
+.section sjstb
+.section sjsua
+.section sjsub
+.section sjsva
+.section sjsvb
+.section sjswa
+.section sjswb
+.section sjsxa
+.section sjsxb
+.section sjsya
+.section sjsyb
+.section sjsza
+.section sjszb
+.section sjs1a
+.section sjs1b
+.section sjs2a
+.section sjs2b
+.section sjs3a
+.section sjs3b
+.section sjs4a
+.section sjs4b
+.section sjs5a
+.section sjs5b
+.section sjs6a
+.section sjs6b
+.section sjs7a
+.section sjs7b
+.section sjs8a
+.section sjs8b
+.section sjs9a
+.section sjs9b
+.section sjs0a
+.section sjs0b
+.section sjtaa
+.section sjtab
+.section sjtba
+.section sjtbb
+.section sjtca
+.section sjtcb
+.section sjtda
+.section sjtdb
+.section sjtea
+.section sjteb
+.section sjtfa
+.section sjtfb
+.section sjtga
+.section sjtgb
+.section sjtha
+.section sjthb
+.section sjtia
+.section sjtib
+.section sjtja
+.section sjtjb
+.section sjtka
+.section sjtkb
+.section sjtla
+.section sjtlb
+.section sjtma
+.section sjtmb
+.section sjtna
+.section sjtnb
+.section sjtoa
+.section sjtob
+.section sjtpa
+.section sjtpb
+.section sjtqa
+.section sjtqb
+.section sjtra
+.section sjtrb
+.section sjtsa
+.section sjtsb
+.section sjtta
+.section sjttb
+.section sjtua
+.section sjtub
+.section sjtva
+.section sjtvb
+.section sjtwa
+.section sjtwb
+.section sjtxa
+.section sjtxb
+.section sjtya
+.section sjtyb
+.section sjtza
+.section sjtzb
+.section sjt1a
+.section sjt1b
+.section sjt2a
+.section sjt2b
+.section sjt3a
+.section sjt3b
+.section sjt4a
+.section sjt4b
+.section sjt5a
+.section sjt5b
+.section sjt6a
+.section sjt6b
+.section sjt7a
+.section sjt7b
+.section sjt8a
+.section sjt8b
+.section sjt9a
+.section sjt9b
+.section sjt0a
+.section sjt0b
+.section sjuaa
+.section sjuab
+.section sjuba
+.section sjubb
+.section sjuca
+.section sjucb
+.section sjuda
+.section sjudb
+.section sjuea
+.section sjueb
+.section sjufa
+.section sjufb
+.section sjuga
+.section sjugb
+.section sjuha
+.section sjuhb
+.section sjuia
+.section sjuib
+.section sjuja
+.section sjujb
+.section sjuka
+.section sjukb
+.section sjula
+.section sjulb
+.section sjuma
+.section sjumb
+.section sjuna
+.section sjunb
+.section sjuoa
+.section sjuob
+.section sjupa
+.section sjupb
+.section sjuqa
+.section sjuqb
+.section sjura
+.section sjurb
+.section sjusa
+.section sjusb
+.section sjuta
+.section sjutb
+.section sjuua
+.section sjuub
+.section sjuva
+.section sjuvb
+.section sjuwa
+.section sjuwb
+.section sjuxa
+.section sjuxb
+.section sjuya
+.section sjuyb
+.section sjuza
+.section sjuzb
+.section sju1a
+.section sju1b
+.section sju2a
+.section sju2b
+.section sju3a
+.section sju3b
+.section sju4a
+.section sju4b
+.section sju5a
+.section sju5b
+.section sju6a
+.section sju6b
+.section sju7a
+.section sju7b
+.section sju8a
+.section sju8b
+.section sju9a
+.section sju9b
+.section sju0a
+.section sju0b
+.section sjvaa
+.section sjvab
+.section sjvba
+.section sjvbb
+.section sjvca
+.section sjvcb
+.section sjvda
+.section sjvdb
+.section sjvea
+.section sjveb
+.section sjvfa
+.section sjvfb
+.section sjvga
+.section sjvgb
+.section sjvha
+.section sjvhb
+.section sjvia
+.section sjvib
+.section sjvja
+.section sjvjb
+.section sjvka
+.section sjvkb
+.section sjvla
+.section sjvlb
+.section sjvma
+.section sjvmb
+.section sjvna
+.section sjvnb
+.section sjvoa
+.section sjvob
+.section sjvpa
+.section sjvpb
+.section sjvqa
+.section sjvqb
+.section sjvra
+.section sjvrb
+.section sjvsa
+.section sjvsb
+.section sjvta
+.section sjvtb
+.section sjvua
+.section sjvub
+.section sjvva
+.section sjvvb
+.section sjvwa
+.section sjvwb
+.section sjvxa
+.section sjvxb
+.section sjvya
+.section sjvyb
+.section sjvza
+.section sjvzb
+.section sjv1a
+.section sjv1b
+.section sjv2a
+.section sjv2b
+.section sjv3a
+.section sjv3b
+.section sjv4a
+.section sjv4b
+.section sjv5a
+.section sjv5b
+.section sjv6a
+.section sjv6b
+.section sjv7a
+.section sjv7b
+.section sjv8a
+.section sjv8b
+.section sjv9a
+.section sjv9b
+.section sjv0a
+.section sjv0b
+.section sjwaa
+.section sjwab
+.section sjwba
+.section sjwbb
+.section sjwca
+.section sjwcb
+.section sjwda
+.section sjwdb
+.section sjwea
+.section sjweb
+.section sjwfa
+.section sjwfb
+.section sjwga
+.section sjwgb
+.section sjwha
+.section sjwhb
+.section sjwia
+.section sjwib
+.section sjwja
+.section sjwjb
+.section sjwka
+.section sjwkb
+.section sjwla
+.section sjwlb
+.section sjwma
+.section sjwmb
+.section sjwna
+.section sjwnb
+.section sjwoa
+.section sjwob
+.section sjwpa
+.section sjwpb
+.section sjwqa
+.section sjwqb
+.section sjwra
+.section sjwrb
+.section sjwsa
+.section sjwsb
+.section sjwta
+.section sjwtb
+.section sjwua
+.section sjwub
+.section sjwva
+.section sjwvb
+.section sjwwa
+.section sjwwb
+.section sjwxa
+.section sjwxb
+.section sjwya
+.section sjwyb
+.section sjwza
+.section sjwzb
+.section sjw1a
+.section sjw1b
+.section sjw2a
+.section sjw2b
+.section sjw3a
+.section sjw3b
+.section sjw4a
+.section sjw4b
+.section sjw5a
+.section sjw5b
+.section sjw6a
+.section sjw6b
+.section sjw7a
+.section sjw7b
+.section sjw8a
+.section sjw8b
+.section sjw9a
+.section sjw9b
+.section sjw0a
+.section sjw0b
+.section sjxaa
+.section sjxab
+.section sjxba
+.section sjxbb
+.section sjxca
+.section sjxcb
+.section sjxda
+.section sjxdb
+.section sjxea
+.section sjxeb
+.section sjxfa
+.section sjxfb
+.section sjxga
+.section sjxgb
+.section sjxha
+.section sjxhb
+.section sjxia
+.section sjxib
+.section sjxja
+.section sjxjb
+.section sjxka
+.section sjxkb
+.section sjxla
+.section sjxlb
+.section sjxma
+.section sjxmb
+.section sjxna
+.section sjxnb
+.section sjxoa
+.section sjxob
+.section sjxpa
+.section sjxpb
+.section sjxqa
+.section sjxqb
+.section sjxra
+.section sjxrb
+.section sjxsa
+.section sjxsb
+.section sjxta
+.section sjxtb
+.section sjxua
+.section sjxub
+.section sjxva
+.section sjxvb
+.section sjxwa
+.section sjxwb
+.section sjxxa
+.section sjxxb
+.section sjxya
+.section sjxyb
+.section sjxza
+.section sjxzb
+.section sjx1a
+.section sjx1b
+.section sjx2a
+.section sjx2b
+.section sjx3a
+.section sjx3b
+.section sjx4a
+.section sjx4b
+.section sjx5a
+.section sjx5b
+.section sjx6a
+.section sjx6b
+.section sjx7a
+.section sjx7b
+.section sjx8a
+.section sjx8b
+.section sjx9a
+.section sjx9b
+.section sjx0a
+.section sjx0b
+.section sjyaa
+.section sjyab
+.section sjyba
+.section sjybb
+.section sjyca
+.section sjycb
+.section sjyda
+.section sjydb
+.section sjyea
+.section sjyeb
+.section sjyfa
+.section sjyfb
+.section sjyga
+.section sjygb
+.section sjyha
+.section sjyhb
+.section sjyia
+.section sjyib
+.section sjyja
+.section sjyjb
+.section sjyka
+.section sjykb
+.section sjyla
+.section sjylb
+.section sjyma
+.section sjymb
+.section sjyna
+.section sjynb
+.section sjyoa
+.section sjyob
+.section sjypa
+.section sjypb
+.section sjyqa
+.section sjyqb
+.section sjyra
+.section sjyrb
+.section sjysa
+.section sjysb
+.section sjyta
+.section sjytb
+.section sjyua
+.section sjyub
+.section sjyva
+.section sjyvb
+.section sjywa
+.section sjywb
+.section sjyxa
+.section sjyxb
+.section sjyya
+.section sjyyb
+.section sjyza
+.section sjyzb
+.section sjy1a
+.section sjy1b
+.section sjy2a
+.section sjy2b
+.section sjy3a
+.section sjy3b
+.section sjy4a
+.section sjy4b
+.section sjy5a
+.section sjy5b
+.section sjy6a
+.section sjy6b
+.section sjy7a
+.section sjy7b
+.section sjy8a
+.section sjy8b
+.section sjy9a
+.section sjy9b
+.section sjy0a
+.section sjy0b
+.section sjzaa
+.section sjzab
+.section sjzba
+.section sjzbb
+.section sjzca
+.section sjzcb
+.section sjzda
+.section sjzdb
+.section sjzea
+.section sjzeb
+.section sjzfa
+.section sjzfb
+.section sjzga
+.section sjzgb
+.section sjzha
+.section sjzhb
+.section sjzia
+.section sjzib
+.section sjzja
+.section sjzjb
+.section sjzka
+.section sjzkb
+.section sjzla
+.section sjzlb
+.section sjzma
+.section sjzmb
+.section sjzna
+.section sjznb
+.section sjzoa
+.section sjzob
+.section sjzpa
+.section sjzpb
+.section sjzqa
+.section sjzqb
+.section sjzra
+.section sjzrb
+.section sjzsa
+.section sjzsb
+.section sjzta
+.section sjztb
+.section sjzua
+.section sjzub
+.section sjzva
+.section sjzvb
+.section sjzwa
+.section sjzwb
+.section sjzxa
+.section sjzxb
+.section sjzya
+.section sjzyb
+.section sjzza
+.section sjzzb
+.section sjz1a
+.section sjz1b
+.section sjz2a
+.section sjz2b
+.section sjz3a
+.section sjz3b
+.section sjz4a
+.section sjz4b
+.section sjz5a
+.section sjz5b
+.section sjz6a
+.section sjz6b
+.section sjz7a
+.section sjz7b
+.section sjz8a
+.section sjz8b
+.section sjz9a
+.section sjz9b
+.section sjz0a
+.section sjz0b
+.section sj1aa
+.section sj1ab
+.section sj1ba
+.section sj1bb
+.section sj1ca
+.section sj1cb
+.section sj1da
+.section sj1db
+.section sj1ea
+.section sj1eb
+.section sj1fa
+.section sj1fb
+.section sj1ga
+.section sj1gb
+.section sj1ha
+.section sj1hb
+.section sj1ia
+.section sj1ib
+.section sj1ja
+.section sj1jb
+.section sj1ka
+.section sj1kb
+.section sj1la
+.section sj1lb
+.section sj1ma
+.section sj1mb
+.section sj1na
+.section sj1nb
+.section sj1oa
+.section sj1ob
+.section sj1pa
+.section sj1pb
+.section sj1qa
+.section sj1qb
+.section sj1ra
+.section sj1rb
+.section sj1sa
+.section sj1sb
+.section sj1ta
+.section sj1tb
+.section sj1ua
+.section sj1ub
+.section sj1va
+.section sj1vb
+.section sj1wa
+.section sj1wb
+.section sj1xa
+.section sj1xb
+.section sj1ya
+.section sj1yb
+.section sj1za
+.section sj1zb
+.section sj11a
+.section sj11b
+.section sj12a
+.section sj12b
+.section sj13a
+.section sj13b
+.section sj14a
+.section sj14b
+.section sj15a
+.section sj15b
+.section sj16a
+.section sj16b
+.section sj17a
+.section sj17b
+.section sj18a
+.section sj18b
+.section sj19a
+.section sj19b
+.section sj10a
+.section sj10b
+.section sj2aa
+.section sj2ab
+.section sj2ba
+.section sj2bb
+.section sj2ca
+.section sj2cb
+.section sj2da
+.section sj2db
+.section sj2ea
+.section sj2eb
+.section sj2fa
+.section sj2fb
+.section sj2ga
+.section sj2gb
+.section sj2ha
+.section sj2hb
+.section sj2ia
+.section sj2ib
+.section sj2ja
+.section sj2jb
+.section sj2ka
+.section sj2kb
+.section sj2la
+.section sj2lb
+.section sj2ma
+.section sj2mb
+.section sj2na
+.section sj2nb
+.section sj2oa
+.section sj2ob
+.section sj2pa
+.section sj2pb
+.section sj2qa
+.section sj2qb
+.section sj2ra
+.section sj2rb
+.section sj2sa
+.section sj2sb
+.section sj2ta
+.section sj2tb
+.section sj2ua
+.section sj2ub
+.section sj2va
+.section sj2vb
+.section sj2wa
+.section sj2wb
+.section sj2xa
+.section sj2xb
+.section sj2ya
+.section sj2yb
+.section sj2za
+.section sj2zb
+.section sj21a
+.section sj21b
+.section sj22a
+.section sj22b
+.section sj23a
+.section sj23b
+.section sj24a
+.section sj24b
+.section sj25a
+.section sj25b
+.section sj26a
+.section sj26b
+.section sj27a
+.section sj27b
+.section sj28a
+.section sj28b
+.section sj29a
+.section sj29b
+.section sj20a
+.section sj20b
+.section sj3aa
+.section sj3ab
+.section sj3ba
+.section sj3bb
+.section sj3ca
+.section sj3cb
+.section sj3da
+.section sj3db
+.section sj3ea
+.section sj3eb
+.section sj3fa
+.section sj3fb
+.section sj3ga
+.section sj3gb
+.section sj3ha
+.section sj3hb
+.section sj3ia
+.section sj3ib
+.section sj3ja
+.section sj3jb
+.section sj3ka
+.section sj3kb
+.section sj3la
+.section sj3lb
+.section sj3ma
+.section sj3mb
+.section sj3na
+.section sj3nb
+.section sj3oa
+.section sj3ob
+.section sj3pa
+.section sj3pb
+.section sj3qa
+.section sj3qb
+.section sj3ra
+.section sj3rb
+.section sj3sa
+.section sj3sb
+.section sj3ta
+.section sj3tb
+.section sj3ua
+.section sj3ub
+.section sj3va
+.section sj3vb
+.section sj3wa
+.section sj3wb
+.section sj3xa
+.section sj3xb
+.section sj3ya
+.section sj3yb
+.section sj3za
+.section sj3zb
+.section sj31a
+.section sj31b
+.section sj32a
+.section sj32b
+.section sj33a
+.section sj33b
+.section sj34a
+.section sj34b
+.section sj35a
+.section sj35b
+.section sj36a
+.section sj36b
+.section sj37a
+.section sj37b
+.section sj38a
+.section sj38b
+.section sj39a
+.section sj39b
+.section sj30a
+.section sj30b
+.section sj4aa
+.section sj4ab
+.section sj4ba
+.section sj4bb
+.section sj4ca
+.section sj4cb
+.section sj4da
+.section sj4db
+.section sj4ea
+.section sj4eb
+.section sj4fa
+.section sj4fb
+.section sj4ga
+.section sj4gb
+.section sj4ha
+.section sj4hb
+.section sj4ia
+.section sj4ib
+.section sj4ja
+.section sj4jb
+.section sj4ka
+.section sj4kb
+.section sj4la
+.section sj4lb
+.section sj4ma
+.section sj4mb
+.section sj4na
+.section sj4nb
+.section sj4oa
+.section sj4ob
+.section sj4pa
+.section sj4pb
+.section sj4qa
+.section sj4qb
+.section sj4ra
+.section sj4rb
+.section sj4sa
+.section sj4sb
+.section sj4ta
+.section sj4tb
+.section sj4ua
+.section sj4ub
+.section sj4va
+.section sj4vb
+.section sj4wa
+.section sj4wb
+.section sj4xa
+.section sj4xb
+.section sj4ya
+.section sj4yb
+.section sj4za
+.section sj4zb
+.section sj41a
+.section sj41b
+.section sj42a
+.section sj42b
+.section sj43a
+.section sj43b
+.section sj44a
+.section sj44b
+.section sj45a
+.section sj45b
+.section sj46a
+.section sj46b
+.section sj47a
+.section sj47b
+.section sj48a
+.section sj48b
+.section sj49a
+.section sj49b
+.section sj40a
+.section sj40b
+.section sj5aa
+.section sj5ab
+.section sj5ba
+.section sj5bb
+.section sj5ca
+.section sj5cb
+.section sj5da
+.section sj5db
+.section sj5ea
+.section sj5eb
+.section sj5fa
+.section sj5fb
+.section sj5ga
+.section sj5gb
+.section sj5ha
+.section sj5hb
+.section sj5ia
+.section sj5ib
+.section sj5ja
+.section sj5jb
+.section sj5ka
+.section sj5kb
+.section sj5la
+.section sj5lb
+.section sj5ma
+.section sj5mb
+.section sj5na
+.section sj5nb
+.section sj5oa
+.section sj5ob
+.section sj5pa
+.section sj5pb
+.section sj5qa
+.section sj5qb
+.section sj5ra
+.section sj5rb
+.section sj5sa
+.section sj5sb
+.section sj5ta
+.section sj5tb
+.section sj5ua
+.section sj5ub
+.section sj5va
+.section sj5vb
+.section sj5wa
+.section sj5wb
+.section sj5xa
+.section sj5xb
+.section sj5ya
+.section sj5yb
+.section sj5za
+.section sj5zb
+.section sj51a
+.section sj51b
+.section sj52a
+.section sj52b
+.section sj53a
+.section sj53b
+.section sj54a
+.section sj54b
+.section sj55a
+.section sj55b
+.section sj56a
+.section sj56b
+.section sj57a
+.section sj57b
+.section sj58a
+.section sj58b
+.section sj59a
+.section sj59b
+.section sj50a
+.section sj50b
+.section sj6aa
+.section sj6ab
+.section sj6ba
+.section sj6bb
+.section sj6ca
+.section sj6cb
+.section sj6da
+.section sj6db
+.section sj6ea
+.section sj6eb
+.section sj6fa
+.section sj6fb
+.section sj6ga
+.section sj6gb
+.section sj6ha
+.section sj6hb
+.section sj6ia
+.section sj6ib
+.section sj6ja
+.section sj6jb
+.section sj6ka
+.section sj6kb
+.section sj6la
+.section sj6lb
+.section sj6ma
+.section sj6mb
+.section sj6na
+.section sj6nb
+.section sj6oa
+.section sj6ob
+.section sj6pa
+.section sj6pb
+.section sj6qa
+.section sj6qb
+.section sj6ra
+.section sj6rb
+.section sj6sa
+.section sj6sb
+.section sj6ta
+.section sj6tb
+.section sj6ua
+.section sj6ub
+.section sj6va
+.section sj6vb
+.section sj6wa
+.section sj6wb
+.section sj6xa
+.section sj6xb
+.section sj6ya
+.section sj6yb
+.section sj6za
+.section sj6zb
+.section sj61a
+.section sj61b
+.section sj62a
+.section sj62b
+.section sj63a
+.section sj63b
+.section sj64a
+.section sj64b
+.section sj65a
+.section sj65b
+.section sj66a
+.section sj66b
+.section sj67a
+.section sj67b
+.section sj68a
+.section sj68b
+.section sj69a
+.section sj69b
+.section sj60a
+.section sj60b
+.section sj7aa
+.section sj7ab
+.section sj7ba
+.section sj7bb
+.section sj7ca
+.section sj7cb
+.section sj7da
+.section sj7db
+.section sj7ea
+.section sj7eb
+.section sj7fa
+.section sj7fb
+.section sj7ga
+.section sj7gb
+.section sj7ha
+.section sj7hb
+.section sj7ia
+.section sj7ib
+.section sj7ja
+.section sj7jb
+.section sj7ka
+.section sj7kb
+.section sj7la
+.section sj7lb
+.section sj7ma
+.section sj7mb
+.section sj7na
+.section sj7nb
+.section sj7oa
+.section sj7ob
+.section sj7pa
+.section sj7pb
+.section sj7qa
+.section sj7qb
+.section sj7ra
+.section sj7rb
+.section sj7sa
+.section sj7sb
+.section sj7ta
+.section sj7tb
+.section sj7ua
+.section sj7ub
+.section sj7va
+.section sj7vb
+.section sj7wa
+.section sj7wb
+.section sj7xa
+.section sj7xb
+.section sj7ya
+.section sj7yb
+.section sj7za
+.section sj7zb
+.section sj71a
+.section sj71b
+.section sj72a
+.section sj72b
+.section sj73a
+.section sj73b
+.section sj74a
+.section sj74b
+.section sj75a
+.section sj75b
+.section sj76a
+.section sj76b
+.section sj77a
+.section sj77b
+.section sj78a
+.section sj78b
+.section sj79a
+.section sj79b
+.section sj70a
+.section sj70b
+.section sj8aa
+.section sj8ab
+.section sj8ba
+.section sj8bb
+.section sj8ca
+.section sj8cb
+.section sj8da
+.section sj8db
+.section sj8ea
+.section sj8eb
+.section sj8fa
+.section sj8fb
+.section sj8ga
+.section sj8gb
+.section sj8ha
+.section sj8hb
+.section sj8ia
+.section sj8ib
+.section sj8ja
+.section sj8jb
+.section sj8ka
+.section sj8kb
+.section sj8la
+.section sj8lb
+.section sj8ma
+.section sj8mb
+.section sj8na
+.section sj8nb
+.section sj8oa
+.section sj8ob
+.section sj8pa
+.section sj8pb
+.section sj8qa
+.section sj8qb
+.section sj8ra
+.section sj8rb
+.section sj8sa
+.section sj8sb
+.section sj8ta
+.section sj8tb
+.section sj8ua
+.section sj8ub
+.section sj8va
+.section sj8vb
+.section sj8wa
+.section sj8wb
+.section sj8xa
+.section sj8xb
+.section sj8ya
+.section sj8yb
+.section sj8za
+.section sj8zb
+.section sj81a
+.section sj81b
+.section sj82a
+.section sj82b
+.section sj83a
+.section sj83b
+.section sj84a
+.section sj84b
+.section sj85a
+.section sj85b
+.section sj86a
+.section sj86b
+.section sj87a
+.section sj87b
+.section sj88a
+.section sj88b
+.section sj89a
+.section sj89b
+.section sj80a
+.section sj80b
+.section sj9aa
+.section sj9ab
+.section sj9ba
+.section sj9bb
+.section sj9ca
+.section sj9cb
+.section sj9da
+.section sj9db
+.section sj9ea
+.section sj9eb
+.section sj9fa
+.section sj9fb
+.section sj9ga
+.section sj9gb
+.section sj9ha
+.section sj9hb
+.section sj9ia
+.section sj9ib
+.section sj9ja
+.section sj9jb
+.section sj9ka
+.section sj9kb
+.section sj9la
+.section sj9lb
+.section sj9ma
+.section sj9mb
+.section sj9na
+.section sj9nb
+.section sj9oa
+.section sj9ob
+.section sj9pa
+.section sj9pb
+.section sj9qa
+.section sj9qb
+.section sj9ra
+.section sj9rb
+.section sj9sa
+.section sj9sb
+.section sj9ta
+.section sj9tb
+.section sj9ua
+.section sj9ub
+.section sj9va
+.section sj9vb
+.section sj9wa
+.section sj9wb
+.section sj9xa
+.section sj9xb
+.section sj9ya
+.section sj9yb
+.section sj9za
+.section sj9zb
+.section sj91a
+.section sj91b
+.section sj92a
+.section sj92b
+.section sj93a
+.section sj93b
+.section sj94a
+.section sj94b
+.section sj95a
+.section sj95b
+.section sj96a
+.section sj96b
+.section sj97a
+.section sj97b
+.section sj98a
+.section sj98b
+.section sj99a
+.section sj99b
+.section sj90a
+.section sj90b
+.section sj0aa
+.section sj0ab
+.section sj0ba
+.section sj0bb
+.section sj0ca
+.section sj0cb
+.section sj0da
+.section sj0db
+.section sj0ea
+.section sj0eb
+.section sj0fa
+.section sj0fb
+.section sj0ga
+.section sj0gb
+.section sj0ha
+.section sj0hb
+.section sj0ia
+.section sj0ib
+.section sj0ja
+.section sj0jb
+.section sj0ka
+.section sj0kb
+.section sj0la
+.section sj0lb
+.section sj0ma
+.section sj0mb
+.section sj0na
+.section sj0nb
+.section sj0oa
+.section sj0ob
+.section sj0pa
+.section sj0pb
+.section sj0qa
+.section sj0qb
+.section sj0ra
+.section sj0rb
+.section sj0sa
+.section sj0sb
+.section sj0ta
+.section sj0tb
+.section sj0ua
+.section sj0ub
+.section sj0va
+.section sj0vb
+.section sj0wa
+.section sj0wb
+.section sj0xa
+.section sj0xb
+.section sj0ya
+.section sj0yb
+.section sj0za
+.section sj0zb
+.section sj01a
+.section sj01b
+.section sj02a
+.section sj02b
+.section sj03a
+.section sj03b
+.section sj04a
+.section sj04b
+.section sj05a
+.section sj05b
+.section sj06a
+.section sj06b
+.section sj07a
+.section sj07b
+.section sj08a
+.section sj08b
+.section sj09a
+.section sj09b
+.section sj00a
+.section sj00b
+.section skaaa
+.section skaab
+.section skaba
+.section skabb
+.section skaca
+.section skacb
+.section skada
+.section skadb
+.section skaea
+.section skaeb
+.section skafa
+.section skafb
+.section skaga
+.section skagb
+.section skaha
+.section skahb
+.section skaia
+.section skaib
+.section skaja
+.section skajb
+.section skaka
+.section skakb
+.section skala
+.section skalb
+.section skama
+.section skamb
+.section skana
+.section skanb
+.section skaoa
+.section skaob
+.section skapa
+.section skapb
+.section skaqa
+.section skaqb
+.section skara
+.section skarb
+.section skasa
+.section skasb
+.section skata
+.section skatb
+.section skaua
+.section skaub
+.section skava
+.section skavb
+.section skawa
+.section skawb
+.section skaxa
+.section skaxb
+.section skaya
+.section skayb
+.section skaza
+.section skazb
+.section ska1a
+.section ska1b
+.section ska2a
+.section ska2b
+.section ska3a
+.section ska3b
+.section ska4a
+.section ska4b
+.section ska5a
+.section ska5b
+.section ska6a
+.section ska6b
+.section ska7a
+.section ska7b
+.section ska8a
+.section ska8b
+.section ska9a
+.section ska9b
+.section ska0a
+.section ska0b
+.section skbaa
+.section skbab
+.section skbba
+.section skbbb
+.section skbca
+.section skbcb
+.section skbda
+.section skbdb
+.section skbea
+.section skbeb
+.section skbfa
+.section skbfb
+.section skbga
+.section skbgb
+.section skbha
+.section skbhb
+.section skbia
+.section skbib
+.section skbja
+.section skbjb
+.section skbka
+.section skbkb
+.section skbla
+.section skblb
+.section skbma
+.section skbmb
+.section skbna
+.section skbnb
+.section skboa
+.section skbob
+.section skbpa
+.section skbpb
+.section skbqa
+.section skbqb
+.section skbra
+.section skbrb
+.section skbsa
+.section skbsb
+.section skbta
+.section skbtb
+.section skbua
+.section skbub
+.section skbva
+.section skbvb
+.section skbwa
+.section skbwb
+.section skbxa
+.section skbxb
+.section skbya
+.section skbyb
+.section skbza
+.section skbzb
+.section skb1a
+.section skb1b
+.section skb2a
+.section skb2b
+.section skb3a
+.section skb3b
+.section skb4a
+.section skb4b
+.section skb5a
+.section skb5b
+.section skb6a
+.section skb6b
+.section skb7a
+.section skb7b
+.section skb8a
+.section skb8b
+.section skb9a
+.section skb9b
+.section skb0a
+.section skb0b
+.section skcaa
+.section skcab
+.section skcba
+.section skcbb
+.section skcca
+.section skccb
+.section skcda
+.section skcdb
+.section skcea
+.section skceb
+.section skcfa
+.section skcfb
+.section skcga
+.section skcgb
+.section skcha
+.section skchb
+.section skcia
+.section skcib
+.section skcja
+.section skcjb
+.section skcka
+.section skckb
+.section skcla
+.section skclb
+.section skcma
+.section skcmb
+.section skcna
+.section skcnb
+.section skcoa
+.section skcob
+.section skcpa
+.section skcpb
+.section skcqa
+.section skcqb
+.section skcra
+.section skcrb
+.section skcsa
+.section skcsb
+.section skcta
+.section skctb
+.section skcua
+.section skcub
+.section skcva
+.section skcvb
+.section skcwa
+.section skcwb
+.section skcxa
+.section skcxb
+.section skcya
+.section skcyb
+.section skcza
+.section skczb
+.section skc1a
+.section skc1b
+.section skc2a
+.section skc2b
+.section skc3a
+.section skc3b
+.section skc4a
+.section skc4b
+.section skc5a
+.section skc5b
+.section skc6a
+.section skc6b
+.section skc7a
+.section skc7b
+.section skc8a
+.section skc8b
+.section skc9a
+.section skc9b
+.section skc0a
+.section skc0b
+.section skdaa
+.section skdab
+.section skdba
+.section skdbb
+.section skdca
+.section skdcb
+.section skdda
+.section skddb
+.section skdea
+.section skdeb
+.section skdfa
+.section skdfb
+.section skdga
+.section skdgb
+.section skdha
+.section skdhb
+.section skdia
+.section skdib
+.section skdja
+.section skdjb
+.section skdka
+.section skdkb
+.section skdla
+.section skdlb
+.section skdma
+.section skdmb
+.section skdna
+.section skdnb
+.section skdoa
+.section skdob
+.section skdpa
+.section skdpb
+.section skdqa
+.section skdqb
+.section skdra
+.section skdrb
+.section skdsa
+.section skdsb
+.section skdta
+.section skdtb
+.section skdua
+.section skdub
+.section skdva
+.section skdvb
+.section skdwa
+.section skdwb
+.section skdxa
+.section skdxb
+.section skdya
+.section skdyb
+.section skdza
+.section skdzb
+.section skd1a
+.section skd1b
+.section skd2a
+.section skd2b
+.section skd3a
+.section skd3b
+.section skd4a
+.section skd4b
+.section skd5a
+.section skd5b
+.section skd6a
+.section skd6b
+.section skd7a
+.section skd7b
+.section skd8a
+.section skd8b
+.section skd9a
+.section skd9b
+.section skd0a
+.section skd0b
+.section skeaa
+.section skeab
+.section skeba
+.section skebb
+.section skeca
+.section skecb
+.section skeda
+.section skedb
+.section skeea
+.section skeeb
+.section skefa
+.section skefb
+.section skega
+.section skegb
+.section skeha
+.section skehb
+.section skeia
+.section skeib
+.section skeja
+.section skejb
+.section skeka
+.section skekb
+.section skela
+.section skelb
+.section skema
+.section skemb
+.section skena
+.section skenb
+.section skeoa
+.section skeob
+.section skepa
+.section skepb
+.section skeqa
+.section skeqb
+.section skera
+.section skerb
+.section skesa
+.section skesb
+.section sketa
+.section sketb
+.section skeua
+.section skeub
+.section skeva
+.section skevb
+.section skewa
+.section skewb
+.section skexa
+.section skexb
+.section skeya
+.section skeyb
+.section skeza
+.section skezb
+.section ske1a
+.section ske1b
+.section ske2a
+.section ske2b
+.section ske3a
+.section ske3b
+.section ske4a
+.section ske4b
+.section ske5a
+.section ske5b
+.section ske6a
+.section ske6b
+.section ske7a
+.section ske7b
+.section ske8a
+.section ske8b
+.section ske9a
+.section ske9b
+.section ske0a
+.section ske0b
+.section skfaa
+.section skfab
+.section skfba
+.section skfbb
+.section skfca
+.section skfcb
+.section skfda
+.section skfdb
+.section skfea
+.section skfeb
+.section skffa
+.section skffb
+.section skfga
+.section skfgb
+.section skfha
+.section skfhb
+.section skfia
+.section skfib
+.section skfja
+.section skfjb
+.section skfka
+.section skfkb
+.section skfla
+.section skflb
+.section skfma
+.section skfmb
+.section skfna
+.section skfnb
+.section skfoa
+.section skfob
+.section skfpa
+.section skfpb
+.section skfqa
+.section skfqb
+.section skfra
+.section skfrb
+.section skfsa
+.section skfsb
+.section skfta
+.section skftb
+.section skfua
+.section skfub
+.section skfva
+.section skfvb
+.section skfwa
+.section skfwb
+.section skfxa
+.section skfxb
+.section skfya
+.section skfyb
+.section skfza
+.section skfzb
+.section skf1a
+.section skf1b
+.section skf2a
+.section skf2b
+.section skf3a
+.section skf3b
+.section skf4a
+.section skf4b
+.section skf5a
+.section skf5b
+.section skf6a
+.section skf6b
+.section skf7a
+.section skf7b
+.section skf8a
+.section skf8b
+.section skf9a
+.section skf9b
+.section skf0a
+.section skf0b
+.section skgaa
+.section skgab
+.section skgba
+.section skgbb
+.section skgca
+.section skgcb
+.section skgda
+.section skgdb
+.section skgea
+.section skgeb
+.section skgfa
+.section skgfb
+.section skgga
+.section skggb
+.section skgha
+.section skghb
+.section skgia
+.section skgib
+.section skgja
+.section skgjb
+.section skgka
+.section skgkb
+.section skgla
+.section skglb
+.section skgma
+.section skgmb
+.section skgna
+.section skgnb
+.section skgoa
+.section skgob
+.section skgpa
+.section skgpb
+.section skgqa
+.section skgqb
+.section skgra
+.section skgrb
+.section skgsa
+.section skgsb
+.section skgta
+.section skgtb
+.section skgua
+.section skgub
+.section skgva
+.section skgvb
+.section skgwa
+.section skgwb
+.section skgxa
+.section skgxb
+.section skgya
+.section skgyb
+.section skgza
+.section skgzb
+.section skg1a
+.section skg1b
+.section skg2a
+.section skg2b
+.section skg3a
+.section skg3b
+.section skg4a
+.section skg4b
+.section skg5a
+.section skg5b
+.section skg6a
+.section skg6b
+.section skg7a
+.section skg7b
+.section skg8a
+.section skg8b
+.section skg9a
+.section skg9b
+.section skg0a
+.section skg0b
+.section skhaa
+.section skhab
+.section skhba
+.section skhbb
+.section skhca
+.section skhcb
+.section skhda
+.section skhdb
+.section skhea
+.section skheb
+.section skhfa
+.section skhfb
+.section skhga
+.section skhgb
+.section skhha
+.section skhhb
+.section skhia
+.section skhib
+.section skhja
+.section skhjb
+.section skhka
+.section skhkb
+.section skhla
+.section skhlb
+.section skhma
+.section skhmb
+.section skhna
+.section skhnb
+.section skhoa
+.section skhob
+.section skhpa
+.section skhpb
+.section skhqa
+.section skhqb
+.section skhra
+.section skhrb
+.section skhsa
+.section skhsb
+.section skhta
+.section skhtb
+.section skhua
+.section skhub
+.section skhva
+.section skhvb
+.section skhwa
+.section skhwb
+.section skhxa
+.section skhxb
+.section skhya
+.section skhyb
+.section skhza
+.section skhzb
+.section skh1a
+.section skh1b
+.section skh2a
+.section skh2b
+.section skh3a
+.section skh3b
+.section skh4a
+.section skh4b
+.section skh5a
+.section skh5b
+.section skh6a
+.section skh6b
+.section skh7a
+.section skh7b
+.section skh8a
+.section skh8b
+.section skh9a
+.section skh9b
+.section skh0a
+.section skh0b
+.section skiaa
+.section skiab
+.section skiba
+.section skibb
+.section skica
+.section skicb
+.section skida
+.section skidb
+.section skiea
+.section skieb
+.section skifa
+.section skifb
+.section skiga
+.section skigb
+.section skiha
+.section skihb
+.section skiia
+.section skiib
+.section skija
+.section skijb
+.section skika
+.section skikb
+.section skila
+.section skilb
+.section skima
+.section skimb
+.section skina
+.section skinb
+.section skioa
+.section skiob
+.section skipa
+.section skipb
+.section skiqa
+.section skiqb
+.section skira
+.section skirb
+.section skisa
+.section skisb
+.section skita
+.section skitb
+.section skiua
+.section skiub
+.section skiva
+.section skivb
+.section skiwa
+.section skiwb
+.section skixa
+.section skixb
+.section skiya
+.section skiyb
+.section skiza
+.section skizb
+.section ski1a
+.section ski1b
+.section ski2a
+.section ski2b
+.section ski3a
+.section ski3b
+.section ski4a
+.section ski4b
+.section ski5a
+.section ski5b
+.section ski6a
+.section ski6b
+.section ski7a
+.section ski7b
+.section ski8a
+.section ski8b
+.section ski9a
+.section ski9b
+.section ski0a
+.section ski0b
+.section skjaa
+.section skjab
+.section skjba
+.section skjbb
+.section skjca
+.section skjcb
+.section skjda
+.section skjdb
+.section skjea
+.section skjeb
+.section skjfa
+.section skjfb
+.section skjga
+.section skjgb
+.section skjha
+.section skjhb
+.section skjia
+.section skjib
+.section skjja
+.section skjjb
+.section skjka
+.section skjkb
+.section skjla
+.section skjlb
+.section skjma
+.section skjmb
+.section skjna
+.section skjnb
+.section skjoa
+.section skjob
+.section skjpa
+.section skjpb
+.section skjqa
+.section skjqb
+.section skjra
+.section skjrb
+.section skjsa
+.section skjsb
+.section skjta
+.section skjtb
+.section skjua
+.section skjub
+.section skjva
+.section skjvb
+.section skjwa
+.section skjwb
+.section skjxa
+.section skjxb
+.section skjya
+.section skjyb
+.section skjza
+.section skjzb
+.section skj1a
+.section skj1b
+.section skj2a
+.section skj2b
+.section skj3a
+.section skj3b
+.section skj4a
+.section skj4b
+.section skj5a
+.section skj5b
+.section skj6a
+.section skj6b
+.section skj7a
+.section skj7b
+.section skj8a
+.section skj8b
+.section skj9a
+.section skj9b
+.section skj0a
+.section skj0b
+.section skkaa
+.section skkab
+.section skkba
+.section skkbb
+.section skkca
+.section skkcb
+.section skkda
+.section skkdb
+.section skkea
+.section skkeb
+.section skkfa
+.section skkfb
+.section skkga
+.section skkgb
+.section skkha
+.section skkhb
+.section skkia
+.section skkib
+.section skkja
+.section skkjb
+.section skkka
+.section skkkb
+.section skkla
+.section skklb
+.section skkma
+.section skkmb
+.section skkna
+.section skknb
+.section skkoa
+.section skkob
+.section skkpa
+.section skkpb
+.section skkqa
+.section skkqb
+.section skkra
+.section skkrb
+.section skksa
+.section skksb
+.section skkta
+.section skktb
+.section skkua
+.section skkub
+.section skkva
+.section skkvb
+.section skkwa
+.section skkwb
+.section skkxa
+.section skkxb
+.section skkya
+.section skkyb
+.section skkza
+.section skkzb
+.section skk1a
+.section skk1b
+.section skk2a
+.section skk2b
+.section skk3a
+.section skk3b
+.section skk4a
+.section skk4b
+.section skk5a
+.section skk5b
+.section skk6a
+.section skk6b
+.section skk7a
+.section skk7b
+.section skk8a
+.section skk8b
+.section skk9a
+.section skk9b
+.section skk0a
+.section skk0b
+.section sklaa
+.section sklab
+.section sklba
+.section sklbb
+.section sklca
+.section sklcb
+.section sklda
+.section skldb
+.section sklea
+.section skleb
+.section sklfa
+.section sklfb
+.section sklga
+.section sklgb
+.section sklha
+.section sklhb
+.section sklia
+.section sklib
+.section sklja
+.section skljb
+.section sklka
+.section sklkb
+.section sklla
+.section skllb
+.section sklma
+.section sklmb
+.section sklna
+.section sklnb
+.section skloa
+.section sklob
+.section sklpa
+.section sklpb
+.section sklqa
+.section sklqb
+.section sklra
+.section sklrb
+.section sklsa
+.section sklsb
+.section sklta
+.section skltb
+.section sklua
+.section sklub
+.section sklva
+.section sklvb
+.section sklwa
+.section sklwb
+.section sklxa
+.section sklxb
+.section sklya
+.section sklyb
+.section sklza
+.section sklzb
+.section skl1a
+.section skl1b
+.section skl2a
+.section skl2b
+.section skl3a
+.section skl3b
+.section skl4a
+.section skl4b
+.section skl5a
+.section skl5b
+.section skl6a
+.section skl6b
+.section skl7a
+.section skl7b
+.section skl8a
+.section skl8b
+.section skl9a
+.section skl9b
+.section skl0a
+.section skl0b
+.section skmaa
+.section skmab
+.section skmba
+.section skmbb
+.section skmca
+.section skmcb
+.section skmda
+.section skmdb
+.section skmea
+.section skmeb
+.section skmfa
+.section skmfb
+.section skmga
+.section skmgb
+.section skmha
+.section skmhb
+.section skmia
+.section skmib
+.section skmja
+.section skmjb
+.section skmka
+.section skmkb
+.section skmla
+.section skmlb
+.section skmma
+.section skmmb
+.section skmna
+.section skmnb
+.section skmoa
+.section skmob
+.section skmpa
+.section skmpb
+.section skmqa
+.section skmqb
+.section skmra
+.section skmrb
+.section skmsa
+.section skmsb
+.section skmta
+.section skmtb
+.section skmua
+.section skmub
+.section skmva
+.section skmvb
+.section skmwa
+.section skmwb
+.section skmxa
+.section skmxb
+.section skmya
+.section skmyb
+.section skmza
+.section skmzb
+.section skm1a
+.section skm1b
+.section skm2a
+.section skm2b
+.section skm3a
+.section skm3b
+.section skm4a
+.section skm4b
+.section skm5a
+.section skm5b
+.section skm6a
+.section skm6b
+.section skm7a
+.section skm7b
+.section skm8a
+.section skm8b
+.section skm9a
+.section skm9b
+.section skm0a
+.section skm0b
+.section sknaa
+.section sknab
+.section sknba
+.section sknbb
+.section sknca
+.section skncb
+.section sknda
+.section skndb
+.section sknea
+.section skneb
+.section sknfa
+.section sknfb
+.section sknga
+.section skngb
+.section sknha
+.section sknhb
+.section sknia
+.section sknib
+.section sknja
+.section sknjb
+.section sknka
+.section sknkb
+.section sknla
+.section sknlb
+.section sknma
+.section sknmb
+.section sknna
+.section sknnb
+.section sknoa
+.section sknob
+.section sknpa
+.section sknpb
+.section sknqa
+.section sknqb
+.section sknra
+.section sknrb
+.section sknsa
+.section sknsb
+.section sknta
+.section skntb
+.section sknua
+.section sknub
+.section sknva
+.section sknvb
+.section sknwa
+.section sknwb
+.section sknxa
+.section sknxb
+.section sknya
+.section sknyb
+.section sknza
+.section sknzb
+.section skn1a
+.section skn1b
+.section skn2a
+.section skn2b
+.section skn3a
+.section skn3b
+.section skn4a
+.section skn4b
+.section skn5a
+.section skn5b
+.section skn6a
+.section skn6b
+.section skn7a
+.section skn7b
+.section skn8a
+.section skn8b
+.section skn9a
+.section skn9b
+.section skn0a
+.section skn0b
+.section skoaa
+.section skoab
+.section skoba
+.section skobb
+.section skoca
+.section skocb
+.section skoda
+.section skodb
+.section skoea
+.section skoeb
+.section skofa
+.section skofb
+.section skoga
+.section skogb
+.section skoha
+.section skohb
+.section skoia
+.section skoib
+.section skoja
+.section skojb
+.section skoka
+.section skokb
+.section skola
+.section skolb
+.section skoma
+.section skomb
+.section skona
+.section skonb
+.section skooa
+.section skoob
+.section skopa
+.section skopb
+.section skoqa
+.section skoqb
+.section skora
+.section skorb
+.section skosa
+.section skosb
+.section skota
+.section skotb
+.section skoua
+.section skoub
+.section skova
+.section skovb
+.section skowa
+.section skowb
+.section skoxa
+.section skoxb
+.section skoya
+.section skoyb
+.section skoza
+.section skozb
+.section sko1a
+.section sko1b
+.section sko2a
+.section sko2b
+.section sko3a
+.section sko3b
+.section sko4a
+.section sko4b
+.section sko5a
+.section sko5b
+.section sko6a
+.section sko6b
+.section sko7a
+.section sko7b
+.section sko8a
+.section sko8b
+.section sko9a
+.section sko9b
+.section sko0a
+.section sko0b
+.section skpaa
+.section skpab
+.section skpba
+.section skpbb
+.section skpca
+.section skpcb
+.section skpda
+.section skpdb
+.section skpea
+.section skpeb
+.section skpfa
+.section skpfb
+.section skpga
+.section skpgb
+.section skpha
+.section skphb
+.section skpia
+.section skpib
+.section skpja
+.section skpjb
+.section skpka
+.section skpkb
+.section skpla
+.section skplb
+.section skpma
+.section skpmb
+.section skpna
+.section skpnb
+.section skpoa
+.section skpob
+.section skppa
+.section skppb
+.section skpqa
+.section skpqb
+.section skpra
+.section skprb
+.section skpsa
+.section skpsb
+.section skpta
+.section skptb
+.section skpua
+.section skpub
+.section skpva
+.section skpvb
+.section skpwa
+.section skpwb
+.section skpxa
+.section skpxb
+.section skpya
+.section skpyb
+.section skpza
+.section skpzb
+.section skp1a
+.section skp1b
+.section skp2a
+.section skp2b
+.section skp3a
+.section skp3b
+.section skp4a
+.section skp4b
+.section skp5a
+.section skp5b
+.section skp6a
+.section skp6b
+.section skp7a
+.section skp7b
+.section skp8a
+.section skp8b
+.section skp9a
+.section skp9b
+.section skp0a
+.section skp0b
+.section skqaa
+.section skqab
+.section skqba
+.section skqbb
+.section skqca
+.section skqcb
+.section skqda
+.section skqdb
+.section skqea
+.section skqeb
+.section skqfa
+.section skqfb
+.section skqga
+.section skqgb
+.section skqha
+.section skqhb
+.section skqia
+.section skqib
+.section skqja
+.section skqjb
+.section skqka
+.section skqkb
+.section skqla
+.section skqlb
+.section skqma
+.section skqmb
+.section skqna
+.section skqnb
+.section skqoa
+.section skqob
+.section skqpa
+.section skqpb
+.section skqqa
+.section skqqb
+.section skqra
+.section skqrb
+.section skqsa
+.section skqsb
+.section skqta
+.section skqtb
+.section skqua
+.section skqub
+.section skqva
+.section skqvb
+.section skqwa
+.section skqwb
+.section skqxa
+.section skqxb
+.section skqya
+.section skqyb
+.section skqza
+.section skqzb
+.section skq1a
+.section skq1b
+.section skq2a
+.section skq2b
+.section skq3a
+.section skq3b
+.section skq4a
+.section skq4b
+.section skq5a
+.section skq5b
+.section skq6a
+.section skq6b
+.section skq7a
+.section skq7b
+.section skq8a
+.section skq8b
+.section skq9a
+.section skq9b
+.section skq0a
+.section skq0b
+.section skraa
+.section skrab
+.section skrba
+.section skrbb
+.section skrca
+.section skrcb
+.section skrda
+.section skrdb
+.section skrea
+.section skreb
+.section skrfa
+.section skrfb
+.section skrga
+.section skrgb
+.section skrha
+.section skrhb
+.section skria
+.section skrib
+.section skrja
+.section skrjb
+.section skrka
+.section skrkb
+.section skrla
+.section skrlb
+.section skrma
+.section skrmb
+.section skrna
+.section skrnb
+.section skroa
+.section skrob
+.section skrpa
+.section skrpb
+.section skrqa
+.section skrqb
+.section skrra
+.section skrrb
+.section skrsa
+.section skrsb
+.section skrta
+.section skrtb
+.section skrua
+.section skrub
+.section skrva
+.section skrvb
+.section skrwa
+.section skrwb
+.section skrxa
+.section skrxb
+.section skrya
+.section skryb
+.section skrza
+.section skrzb
+.section skr1a
+.section skr1b
+.section skr2a
+.section skr2b
+.section skr3a
+.section skr3b
+.section skr4a
+.section skr4b
+.section skr5a
+.section skr5b
+.section skr6a
+.section skr6b
+.section skr7a
+.section skr7b
+.section skr8a
+.section skr8b
+.section skr9a
+.section skr9b
+.section skr0a
+.section skr0b
+.section sksaa
+.section sksab
+.section sksba
+.section sksbb
+.section sksca
+.section skscb
+.section sksda
+.section sksdb
+.section sksea
+.section skseb
+.section sksfa
+.section sksfb
+.section sksga
+.section sksgb
+.section sksha
+.section skshb
+.section sksia
+.section sksib
+.section sksja
+.section sksjb
+.section skska
+.section skskb
+.section sksla
+.section skslb
+.section sksma
+.section sksmb
+.section sksna
+.section sksnb
+.section sksoa
+.section sksob
+.section skspa
+.section skspb
+.section sksqa
+.section sksqb
+.section sksra
+.section sksrb
+.section skssa
+.section skssb
+.section sksta
+.section skstb
+.section sksua
+.section sksub
+.section sksva
+.section sksvb
+.section skswa
+.section skswb
+.section sksxa
+.section sksxb
+.section sksya
+.section sksyb
+.section sksza
+.section skszb
+.section sks1a
+.section sks1b
+.section sks2a
+.section sks2b
+.section sks3a
+.section sks3b
+.section sks4a
+.section sks4b
+.section sks5a
+.section sks5b
+.section sks6a
+.section sks6b
+.section sks7a
+.section sks7b
+.section sks8a
+.section sks8b
+.section sks9a
+.section sks9b
+.section sks0a
+.section sks0b
+.section sktaa
+.section sktab
+.section sktba
+.section sktbb
+.section sktca
+.section sktcb
+.section sktda
+.section sktdb
+.section sktea
+.section skteb
+.section sktfa
+.section sktfb
+.section sktga
+.section sktgb
+.section sktha
+.section skthb
+.section sktia
+.section sktib
+.section sktja
+.section sktjb
+.section sktka
+.section sktkb
+.section sktla
+.section sktlb
+.section sktma
+.section sktmb
+.section sktna
+.section sktnb
+.section sktoa
+.section sktob
+.section sktpa
+.section sktpb
+.section sktqa
+.section sktqb
+.section sktra
+.section sktrb
+.section sktsa
+.section sktsb
+.section sktta
+.section skttb
+.section sktua
+.section sktub
+.section sktva
+.section sktvb
+.section sktwa
+.section sktwb
+.section sktxa
+.section sktxb
+.section sktya
+.section sktyb
+.section sktza
+.section sktzb
+.section skt1a
+.section skt1b
+.section skt2a
+.section skt2b
+.section skt3a
+.section skt3b
+.section skt4a
+.section skt4b
+.section skt5a
+.section skt5b
+.section skt6a
+.section skt6b
+.section skt7a
+.section skt7b
+.section skt8a
+.section skt8b
+.section skt9a
+.section skt9b
+.section skt0a
+.section skt0b
+.section skuaa
+.section skuab
+.section skuba
+.section skubb
+.section skuca
+.section skucb
+.section skuda
+.section skudb
+.section skuea
+.section skueb
+.section skufa
+.section skufb
+.section skuga
+.section skugb
+.section skuha
+.section skuhb
+.section skuia
+.section skuib
+.section skuja
+.section skujb
+.section skuka
+.section skukb
+.section skula
+.section skulb
+.section skuma
+.section skumb
+.section skuna
+.section skunb
+.section skuoa
+.section skuob
+.section skupa
+.section skupb
+.section skuqa
+.section skuqb
+.section skura
+.section skurb
+.section skusa
+.section skusb
+.section skuta
+.section skutb
+.section skuua
+.section skuub
+.section skuva
+.section skuvb
+.section skuwa
+.section skuwb
+.section skuxa
+.section skuxb
+.section skuya
+.section skuyb
+.section skuza
+.section skuzb
+.section sku1a
+.section sku1b
+.section sku2a
+.section sku2b
+.section sku3a
+.section sku3b
+.section sku4a
+.section sku4b
+.section sku5a
+.section sku5b
+.section sku6a
+.section sku6b
+.section sku7a
+.section sku7b
+.section sku8a
+.section sku8b
+.section sku9a
+.section sku9b
+.section sku0a
+.section sku0b
+.section skvaa
+.section skvab
+.section skvba
+.section skvbb
+.section skvca
+.section skvcb
+.section skvda
+.section skvdb
+.section skvea
+.section skveb
+.section skvfa
+.section skvfb
+.section skvga
+.section skvgb
+.section skvha
+.section skvhb
+.section skvia
+.section skvib
+.section skvja
+.section skvjb
+.section skvka
+.section skvkb
+.section skvla
+.section skvlb
+.section skvma
+.section skvmb
+.section skvna
+.section skvnb
+.section skvoa
+.section skvob
+.section skvpa
+.section skvpb
+.section skvqa
+.section skvqb
+.section skvra
+.section skvrb
+.section skvsa
+.section skvsb
+.section skvta
+.section skvtb
+.section skvua
+.section skvub
+.section skvva
+.section skvvb
+.section skvwa
+.section skvwb
+.section skvxa
+.section skvxb
+.section skvya
+.section skvyb
+.section skvza
+.section skvzb
+.section skv1a
+.section skv1b
+.section skv2a
+.section skv2b
+.section skv3a
+.section skv3b
+.section skv4a
+.section skv4b
+.section skv5a
+.section skv5b
+.section skv6a
+.section skv6b
+.section skv7a
+.section skv7b
+.section skv8a
+.section skv8b
+.section skv9a
+.section skv9b
+.section skv0a
+.section skv0b
+.section skwaa
+.section skwab
+.section skwba
+.section skwbb
+.section skwca
+.section skwcb
+.section skwda
+.section skwdb
+.section skwea
+.section skweb
+.section skwfa
+.section skwfb
+.section skwga
+.section skwgb
+.section skwha
+.section skwhb
+.section skwia
+.section skwib
+.section skwja
+.section skwjb
+.section skwka
+.section skwkb
+.section skwla
+.section skwlb
+.section skwma
+.section skwmb
+.section skwna
+.section skwnb
+.section skwoa
+.section skwob
+.section skwpa
+.section skwpb
+.section skwqa
+.section skwqb
+.section skwra
+.section skwrb
+.section skwsa
+.section skwsb
+.section skwta
+.section skwtb
+.section skwua
+.section skwub
+.section skwva
+.section skwvb
+.section skwwa
+.section skwwb
+.section skwxa
+.section skwxb
+.section skwya
+.section skwyb
+.section skwza
+.section skwzb
+.section skw1a
+.section skw1b
+.section skw2a
+.section skw2b
+.section skw3a
+.section skw3b
+.section skw4a
+.section skw4b
+.section skw5a
+.section skw5b
+.section skw6a
+.section skw6b
+.section skw7a
+.section skw7b
+.section skw8a
+.section skw8b
+.section skw9a
+.section skw9b
+.section skw0a
+.section skw0b
+.section skxaa
+.section skxab
+.section skxba
+.section skxbb
+.section skxca
+.section skxcb
+.section skxda
+.section skxdb
+.section skxea
+.section skxeb
+.section skxfa
+.section skxfb
+.section skxga
+.section skxgb
+.section skxha
+.section skxhb
+.section skxia
+.section skxib
+.section skxja
+.section skxjb
+.section skxka
+.section skxkb
+.section skxla
+.section skxlb
+.section skxma
+.section skxmb
+.section skxna
+.section skxnb
+.section skxoa
+.section skxob
+.section skxpa
+.section skxpb
+.section skxqa
+.section skxqb
+.section skxra
+.section skxrb
+.section skxsa
+.section skxsb
+.section skxta
+.section skxtb
+.section skxua
+.section skxub
+.section skxva
+.section skxvb
+.section skxwa
+.section skxwb
+.section skxxa
+.section skxxb
+.section skxya
+.section skxyb
+.section skxza
+.section skxzb
+.section skx1a
+.section skx1b
+.section skx2a
+.section skx2b
+.section skx3a
+.section skx3b
+.section skx4a
+.section skx4b
+.section skx5a
+.section skx5b
+.section skx6a
+.section skx6b
+.section skx7a
+.section skx7b
+.section skx8a
+.section skx8b
+.section skx9a
+.section skx9b
+.section skx0a
+.section skx0b
+.section skyaa
+.section skyab
+.section skyba
+.section skybb
+.section skyca
+.section skycb
+.section skyda
+.section skydb
+.section skyea
+.section skyeb
+.section skyfa
+.section skyfb
+.section skyga
+.section skygb
+.section skyha
+.section skyhb
+.section skyia
+.section skyib
+.section skyja
+.section skyjb
+.section skyka
+.section skykb
+.section skyla
+.section skylb
+.section skyma
+.section skymb
+.section skyna
+.section skynb
+.section skyoa
+.section skyob
+.section skypa
+.section skypb
+.section skyqa
+.section skyqb
+.section skyra
+.section skyrb
+.section skysa
+.section skysb
+.section skyta
+.section skytb
+.section skyua
+.section skyub
+.section skyva
+.section skyvb
+.section skywa
+.section skywb
+.section skyxa
+.section skyxb
+.section skyya
+.section skyyb
+.section skyza
+.section skyzb
+.section sky1a
+.section sky1b
+.section sky2a
+.section sky2b
+.section sky3a
+.section sky3b
+.section sky4a
+.section sky4b
+.section sky5a
+.section sky5b
+.section sky6a
+.section sky6b
+.section sky7a
+.section sky7b
+.section sky8a
+.section sky8b
+.section sky9a
+.section sky9b
+.section sky0a
+.section sky0b
+.section skzaa
+.section skzab
+.section skzba
+.section skzbb
+.section skzca
+.section skzcb
+.section skzda
+.section skzdb
+.section skzea
+.section skzeb
+.section skzfa
+.section skzfb
+.section skzga
+.section skzgb
+.section skzha
+.section skzhb
+.section skzia
+.section skzib
+.section skzja
+.section skzjb
+.section skzka
+.section skzkb
+.section skzla
+.section skzlb
+.section skzma
+.section skzmb
+.section skzna
+.section skznb
+.section skzoa
+.section skzob
+.section skzpa
+.section skzpb
+.section skzqa
+.section skzqb
+.section skzra
+.section skzrb
+.section skzsa
+.section skzsb
+.section skzta
+.section skztb
+.section skzua
+.section skzub
+.section skzva
+.section skzvb
+.section skzwa
+.section skzwb
+.section skzxa
+.section skzxb
+.section skzya
+.section skzyb
+.section skzza
+.section skzzb
+.section skz1a
+.section skz1b
+.section skz2a
+.section skz2b
+.section skz3a
+.section skz3b
+.section skz4a
+.section skz4b
+.section skz5a
+.section skz5b
+.section skz6a
+.section skz6b
+.section skz7a
+.section skz7b
+.section skz8a
+.section skz8b
+.section skz9a
+.section skz9b
+.section skz0a
+.section skz0b
+.section sk1aa
+.section sk1ab
+.section sk1ba
+.section sk1bb
+.section sk1ca
+.section sk1cb
+.section sk1da
+.section sk1db
+.section sk1ea
+.section sk1eb
+.section sk1fa
+.section sk1fb
+.section sk1ga
+.section sk1gb
+.section sk1ha
+.section sk1hb
+.section sk1ia
+.section sk1ib
+.section sk1ja
+.section sk1jb
+.section sk1ka
+.section sk1kb
+.section sk1la
+.section sk1lb
+.section sk1ma
+.section sk1mb
+.section sk1na
+.section sk1nb
+.section sk1oa
+.section sk1ob
+.section sk1pa
+.section sk1pb
+.section sk1qa
+.section sk1qb
+.section sk1ra
+.section sk1rb
+.section sk1sa
+.section sk1sb
+.section sk1ta
+.section sk1tb
+.section sk1ua
+.section sk1ub
+.section sk1va
+.section sk1vb
+.section sk1wa
+.section sk1wb
+.section sk1xa
+.section sk1xb
+.section sk1ya
+.section sk1yb
+.section sk1za
+.section sk1zb
+.section sk11a
+.section sk11b
+.section sk12a
+.section sk12b
+.section sk13a
+.section sk13b
+.section sk14a
+.section sk14b
+.section sk15a
+.section sk15b
+.section sk16a
+.section sk16b
+.section sk17a
+.section sk17b
+.section sk18a
+.section sk18b
+.section sk19a
+.section sk19b
+.section sk10a
+.section sk10b
+.section sk2aa
+.section sk2ab
+.section sk2ba
+.section sk2bb
+.section sk2ca
+.section sk2cb
+.section sk2da
+.section sk2db
+.section sk2ea
+.section sk2eb
+.section sk2fa
+.section sk2fb
+.section sk2ga
+.section sk2gb
+.section sk2ha
+.section sk2hb
+.section sk2ia
+.section sk2ib
+.section sk2ja
+.section sk2jb
+.section sk2ka
+.section sk2kb
+.section sk2la
+.section sk2lb
+.section sk2ma
+.section sk2mb
+.section sk2na
+.section sk2nb
+.section sk2oa
+.section sk2ob
+.section sk2pa
+.section sk2pb
+.section sk2qa
+.section sk2qb
+.section sk2ra
+.section sk2rb
+.section sk2sa
+.section sk2sb
+.section sk2ta
+.section sk2tb
+.section sk2ua
+.section sk2ub
+.section sk2va
+.section sk2vb
+.section sk2wa
+.section sk2wb
+.section sk2xa
+.section sk2xb
+.section sk2ya
+.section sk2yb
+.section sk2za
+.section sk2zb
+.section sk21a
+.section sk21b
+.section sk22a
+.section sk22b
+.section sk23a
+.section sk23b
+.section sk24a
+.section sk24b
+.section sk25a
+.section sk25b
+.section sk26a
+.section sk26b
+.section sk27a
+.section sk27b
+.section sk28a
+.section sk28b
+.section sk29a
+.section sk29b
+.section sk20a
+.section sk20b
+.section sk3aa
+.section sk3ab
+.section sk3ba
+.section sk3bb
+.section sk3ca
+.section sk3cb
+.section sk3da
+.section sk3db
+.section sk3ea
+.section sk3eb
+.section sk3fa
+.section sk3fb
+.section sk3ga
+.section sk3gb
+.section sk3ha
+.section sk3hb
+.section sk3ia
+.section sk3ib
+.section sk3ja
+.section sk3jb
+.section sk3ka
+.section sk3kb
+.section sk3la
+.section sk3lb
+.section sk3ma
+.section sk3mb
+.section sk3na
+.section sk3nb
+.section sk3oa
+.section sk3ob
+.section sk3pa
+.section sk3pb
+.section sk3qa
+.section sk3qb
+.section sk3ra
+.section sk3rb
+.section sk3sa
+.section sk3sb
+.section sk3ta
+.section sk3tb
+.section sk3ua
+.section sk3ub
+.section sk3va
+.section sk3vb
+.section sk3wa
+.section sk3wb
+.section sk3xa
+.section sk3xb
+.section sk3ya
+.section sk3yb
+.section sk3za
+.section sk3zb
+.section sk31a
+.section sk31b
+.section sk32a
+.section sk32b
+.section sk33a
+.section sk33b
+.section sk34a
+.section sk34b
+.section sk35a
+.section sk35b
+.section sk36a
+.section sk36b
+.section sk37a
+.section sk37b
+.section sk38a
+.section sk38b
+.section sk39a
+.section sk39b
+.section sk30a
+.section sk30b
+.section sk4aa
+.section sk4ab
+.section sk4ba
+.section sk4bb
+.section sk4ca
+.section sk4cb
+.section sk4da
+.section sk4db
+.section sk4ea
+.section sk4eb
+.section sk4fa
+.section sk4fb
+.section sk4ga
+.section sk4gb
+.section sk4ha
+.section sk4hb
+.section sk4ia
+.section sk4ib
+.section sk4ja
+.section sk4jb
+.section sk4ka
+.section sk4kb
+.section sk4la
+.section sk4lb
+.section sk4ma
+.section sk4mb
+.section sk4na
+.section sk4nb
+.section sk4oa
+.section sk4ob
+.section sk4pa
+.section sk4pb
+.section sk4qa
+.section sk4qb
+.section sk4ra
+.section sk4rb
+.section sk4sa
+.section sk4sb
+.section sk4ta
+.section sk4tb
+.section sk4ua
+.section sk4ub
+.section sk4va
+.section sk4vb
+.section sk4wa
+.section sk4wb
+.section sk4xa
+.section sk4xb
+.section sk4ya
+.section sk4yb
+.section sk4za
+.section sk4zb
+.section sk41a
+.section sk41b
+.section sk42a
+.section sk42b
+.section sk43a
+.section sk43b
+.section sk44a
+.section sk44b
+.section sk45a
+.section sk45b
+.section sk46a
+.section sk46b
+.section sk47a
+.section sk47b
+.section sk48a
+.section sk48b
+.section sk49a
+.section sk49b
+.section sk40a
+.section sk40b
+.section sk5aa
+.section sk5ab
+.section sk5ba
+.section sk5bb
+.section sk5ca
+.section sk5cb
+.section sk5da
+.section sk5db
+.section sk5ea
+.section sk5eb
+.section sk5fa
+.section sk5fb
+.section sk5ga
+.section sk5gb
+.section sk5ha
+.section sk5hb
+.section sk5ia
+.section sk5ib
+.section sk5ja
+.section sk5jb
+.section sk5ka
+.section sk5kb
+.section sk5la
+.section sk5lb
+.section sk5ma
+.section sk5mb
+.section sk5na
+.section sk5nb
+.section sk5oa
+.section sk5ob
+.section sk5pa
+.section sk5pb
+.section sk5qa
+.section sk5qb
+.section sk5ra
+.section sk5rb
+.section sk5sa
+.section sk5sb
+.section sk5ta
+.section sk5tb
+.section sk5ua
+.section sk5ub
+.section sk5va
+.section sk5vb
+.section sk5wa
+.section sk5wb
+.section sk5xa
+.section sk5xb
+.section sk5ya
+.section sk5yb
+.section sk5za
+.section sk5zb
+.section sk51a
+.section sk51b
+.section sk52a
+.section sk52b
+.section sk53a
+.section sk53b
+.section sk54a
+.section sk54b
+.section sk55a
+.section sk55b
+.section sk56a
+.section sk56b
+.section sk57a
+.section sk57b
+.section sk58a
+.section sk58b
+.section sk59a
+.section sk59b
+.section sk50a
+.section sk50b
+.section sk6aa
+.section sk6ab
+.section sk6ba
+.section sk6bb
+.section sk6ca
+.section sk6cb
+.section sk6da
+.section sk6db
+.section sk6ea
+.section sk6eb
+.section sk6fa
+.section sk6fb
+.section sk6ga
+.section sk6gb
+.section sk6ha
+.section sk6hb
+.section sk6ia
+.section sk6ib
+.section sk6ja
+.section sk6jb
+.section sk6ka
+.section sk6kb
+.section sk6la
+.section sk6lb
+.section sk6ma
+.section sk6mb
+.section sk6na
+.section sk6nb
+.section sk6oa
+.section sk6ob
+.section sk6pa
+.section sk6pb
+.section sk6qa
+.section sk6qb
+.section sk6ra
+.section sk6rb
+.section sk6sa
+.section sk6sb
+.section sk6ta
+.section sk6tb
+.section sk6ua
+.section sk6ub
+.section sk6va
+.section sk6vb
+.section sk6wa
+.section sk6wb
+.section sk6xa
+.section sk6xb
+.section sk6ya
+.section sk6yb
+.section sk6za
+.section sk6zb
+.section sk61a
+.section sk61b
+.section sk62a
+.section sk62b
+.section sk63a
+.section sk63b
+.section sk64a
+.section sk64b
+.section sk65a
+.section sk65b
+.section sk66a
+.section sk66b
+.section sk67a
+.section sk67b
+.section sk68a
+.section sk68b
+.section sk69a
+.section sk69b
+.section sk60a
+.section sk60b
+.section sk7aa
+.section sk7ab
+.section sk7ba
+.section sk7bb
+.section sk7ca
+.section sk7cb
+.section sk7da
+.section sk7db
+.section sk7ea
+.section sk7eb
+.section sk7fa
+.section sk7fb
+.section sk7ga
+.section sk7gb
+.section sk7ha
+.section sk7hb
+.section sk7ia
+.section sk7ib
+.section sk7ja
+.section sk7jb
+.section sk7ka
+.section sk7kb
+.section sk7la
+.section sk7lb
+.section sk7ma
+.section sk7mb
+.section sk7na
+.section sk7nb
+.section sk7oa
+.section sk7ob
+.section sk7pa
+.section sk7pb
+.section sk7qa
+.section sk7qb
+.section sk7ra
+.section sk7rb
+.section sk7sa
+.section sk7sb
+.section sk7ta
+.section sk7tb
+.section sk7ua
+.section sk7ub
+.section sk7va
+.section sk7vb
+.section sk7wa
+.section sk7wb
+.section sk7xa
+.section sk7xb
+.section sk7ya
+.section sk7yb
+.section sk7za
+.section sk7zb
+.section sk71a
+.section sk71b
+.section sk72a
+.section sk72b
+.section sk73a
+.section sk73b
+.section sk74a
+.section sk74b
+.section sk75a
+.section sk75b
+.section sk76a
+.section sk76b
+.section sk77a
+.section sk77b
+.section sk78a
+.section sk78b
+.section sk79a
+.section sk79b
+.section sk70a
+.section sk70b
+.section sk8aa
+.section sk8ab
+.section sk8ba
+.section sk8bb
+.section sk8ca
+.section sk8cb
+.section sk8da
+.section sk8db
+.section sk8ea
+.section sk8eb
+.section sk8fa
+.section sk8fb
+.section sk8ga
+.section sk8gb
+.section sk8ha
+.section sk8hb
+.section sk8ia
+.section sk8ib
+.section sk8ja
+.section sk8jb
+.section sk8ka
+.section sk8kb
+.section sk8la
+.section sk8lb
+.section sk8ma
+.section sk8mb
+.section sk8na
+.section sk8nb
+.section sk8oa
+.section sk8ob
+.section sk8pa
+.section sk8pb
+.section sk8qa
+.section sk8qb
+.section sk8ra
+.section sk8rb
+.section sk8sa
+.section sk8sb
+.section sk8ta
+.section sk8tb
+.section sk8ua
+.section sk8ub
+.section sk8va
+.section sk8vb
+.section sk8wa
+.section sk8wb
+.section sk8xa
+.section sk8xb
+.section sk8ya
+.section sk8yb
+.section sk8za
+.section sk8zb
+.section sk81a
+.section sk81b
+.section sk82a
+.section sk82b
+.section sk83a
+.section sk83b
+.section sk84a
+.section sk84b
+.section sk85a
+.section sk85b
+.section sk86a
+.section sk86b
+.section sk87a
+.section sk87b
+.section sk88a
+.section sk88b
+.section sk89a
+.section sk89b
+.section sk80a
+.section sk80b
+.section sk9aa
+.section sk9ab
+.section sk9ba
+.section sk9bb
+.section sk9ca
+.section sk9cb
+.section sk9da
+.section sk9db
+.section sk9ea
+.section sk9eb
+.section sk9fa
+.section sk9fb
+.section sk9ga
+.section sk9gb
+.section sk9ha
+.section sk9hb
+.section sk9ia
+.section sk9ib
+.section sk9ja
+.section sk9jb
+.section sk9ka
+.section sk9kb
+.section sk9la
+.section sk9lb
+.section sk9ma
+.section sk9mb
+.section sk9na
+.section sk9nb
+.section sk9oa
+.section sk9ob
+.section sk9pa
+.section sk9pb
+.section sk9qa
+.section sk9qb
+.section sk9ra
+.section sk9rb
+.section sk9sa
+.section sk9sb
+.section sk9ta
+.section sk9tb
+.section sk9ua
+.section sk9ub
+.section sk9va
+.section sk9vb
+.section sk9wa
+.section sk9wb
+.section sk9xa
+.section sk9xb
+.section sk9ya
+.section sk9yb
+.section sk9za
+.section sk9zb
+.section sk91a
+.section sk91b
+.section sk92a
+.section sk92b
+.section sk93a
+.section sk93b
+.section sk94a
+.section sk94b
+.section sk95a
+.section sk95b
+.section sk96a
+.section sk96b
+.section sk97a
+.section sk97b
+.section sk98a
+.section sk98b
+.section sk99a
+.section sk99b
+.section sk90a
+.section sk90b
+.section sk0aa
+.section sk0ab
+.section sk0ba
+.section sk0bb
+.section sk0ca
+.section sk0cb
+.section sk0da
+.section sk0db
+.section sk0ea
+.section sk0eb
+.section sk0fa
+.section sk0fb
+.section sk0ga
+.section sk0gb
+.section sk0ha
+.section sk0hb
+.section sk0ia
+.section sk0ib
+.section sk0ja
+.section sk0jb
+.section sk0ka
+.section sk0kb
+.section sk0la
+.section sk0lb
+.section sk0ma
+.section sk0mb
+.section sk0na
+.section sk0nb
+.section sk0oa
+.section sk0ob
+.section sk0pa
+.section sk0pb
+.section sk0qa
+.section sk0qb
+.section sk0ra
+.section sk0rb
+.section sk0sa
+.section sk0sb
+.section sk0ta
+.section sk0tb
+.section sk0ua
+.section sk0ub
+.section sk0va
+.section sk0vb
+.section sk0wa
+.section sk0wb
+.section sk0xa
+.section sk0xb
+.section sk0ya
+.section sk0yb
+.section sk0za
+.section sk0zb
+.section sk01a
+.section sk01b
+.section sk02a
+.section sk02b
+.section sk03a
+.section sk03b
+.section sk04a
+.section sk04b
+.section sk05a
+.section sk05b
+.section sk06a
+.section sk06b
+.section sk07a
+.section sk07b
+.section sk08a
+.section sk08b
+.section sk09a
+.section sk09b
+.section sk00a
+.section sk00b
+.section slaaa
+.section slaab
+.section slaba
+.section slabb
+.section slaca
+.section slacb
+.section slada
+.section sladb
+.section slaea
+.section slaeb
+.section slafa
+.section slafb
+.section slaga
+.section slagb
+.section slaha
+.section slahb
+.section slaia
+.section slaib
+.section slaja
+.section slajb
+.section slaka
+.section slakb
+.section slala
+.section slalb
+.section slama
+.section slamb
+.section slana
+.section slanb
+.section slaoa
+.section slaob
+.section slapa
+.section slapb
+.section slaqa
+.section slaqb
+.section slara
+.section slarb
+.section slasa
+.section slasb
+.section slata
+.section slatb
+.section slaua
+.section slaub
+.section slava
+.section slavb
+.section slawa
+.section slawb
+.section slaxa
+.section slaxb
+.section slaya
+.section slayb
+.section slaza
+.section slazb
+.section sla1a
+.section sla1b
+.section sla2a
+.section sla2b
+.section sla3a
+.section sla3b
+.section sla4a
+.section sla4b
+.section sla5a
+.section sla5b
+.section sla6a
+.section sla6b
+.section sla7a
+.section sla7b
+.section sla8a
+.section sla8b
+.section sla9a
+.section sla9b
+.section sla0a
+.section sla0b
+.section slbaa
+.section slbab
+.section slbba
+.section slbbb
+.section slbca
+.section slbcb
+.section slbda
+.section slbdb
+.section slbea
+.section slbeb
+.section slbfa
+.section slbfb
+.section slbga
+.section slbgb
+.section slbha
+.section slbhb
+.section slbia
+.section slbib
+.section slbja
+.section slbjb
+.section slbka
+.section slbkb
+.section slbla
+.section slblb
+.section slbma
+.section slbmb
+.section slbna
+.section slbnb
+.section slboa
+.section slbob
+.section slbpa
+.section slbpb
+.section slbqa
+.section slbqb
+.section slbra
+.section slbrb
+.section slbsa
+.section slbsb
+.section slbta
+.section slbtb
+.section slbua
+.section slbub
+.section slbva
+.section slbvb
+.section slbwa
+.section slbwb
+.section slbxa
+.section slbxb
+.section slbya
+.section slbyb
+.section slbza
+.section slbzb
+.section slb1a
+.section slb1b
+.section slb2a
+.section slb2b
+.section slb3a
+.section slb3b
+.section slb4a
+.section slb4b
+.section slb5a
+.section slb5b
+.section slb6a
+.section slb6b
+.section slb7a
+.section slb7b
+.section slb8a
+.section slb8b
+.section slb9a
+.section slb9b
+.section slb0a
+.section slb0b
+.section slcaa
+.section slcab
+.section slcba
+.section slcbb
+.section slcca
+.section slccb
+.section slcda
+.section slcdb
+.section slcea
+.section slceb
+.section slcfa
+.section slcfb
+.section slcga
+.section slcgb
+.section slcha
+.section slchb
+.section slcia
+.section slcib
+.section slcja
+.section slcjb
+.section slcka
+.section slckb
+.section slcla
+.section slclb
+.section slcma
+.section slcmb
+.section slcna
+.section slcnb
+.section slcoa
+.section slcob
+.section slcpa
+.section slcpb
+.section slcqa
+.section slcqb
+.section slcra
+.section slcrb
+.section slcsa
+.section slcsb
+.section slcta
+.section slctb
+.section slcua
+.section slcub
+.section slcva
+.section slcvb
+.section slcwa
+.section slcwb
+.section slcxa
+.section slcxb
+.section slcya
+.section slcyb
+.section slcza
+.section slczb
+.section slc1a
+.section slc1b
+.section slc2a
+.section slc2b
+.section slc3a
+.section slc3b
+.section slc4a
+.section slc4b
+.section slc5a
+.section slc5b
+.section slc6a
+.section slc6b
+.section slc7a
+.section slc7b
+.section slc8a
+.section slc8b
+.section slc9a
+.section slc9b
+.section slc0a
+.section slc0b
+.section sldaa
+.section sldab
+.section sldba
+.section sldbb
+.section sldca
+.section sldcb
+.section sldda
+.section slddb
+.section sldea
+.section sldeb
+.section sldfa
+.section sldfb
+.section sldga
+.section sldgb
+.section sldha
+.section sldhb
+.section sldia
+.section sldib
+.section sldja
+.section sldjb
+.section sldka
+.section sldkb
+.section sldla
+.section sldlb
+.section sldma
+.section sldmb
+.section sldna
+.section sldnb
+.section sldoa
+.section sldob
+.section sldpa
+.section sldpb
+.section sldqa
+.section sldqb
+.section sldra
+.section sldrb
+.section sldsa
+.section sldsb
+.section sldta
+.section sldtb
+.section sldua
+.section sldub
+.section sldva
+.section sldvb
+.section sldwa
+.section sldwb
+.section sldxa
+.section sldxb
+.section sldya
+.section sldyb
+.section sldza
+.section sldzb
+.section sld1a
+.section sld1b
+.section sld2a
+.section sld2b
+.section sld3a
+.section sld3b
+.section sld4a
+.section sld4b
+.section sld5a
+.section sld5b
+.section sld6a
+.section sld6b
+.section sld7a
+.section sld7b
+.section sld8a
+.section sld8b
+.section sld9a
+.section sld9b
+.section sld0a
+.section sld0b
+.section sleaa
+.section sleab
+.section sleba
+.section slebb
+.section sleca
+.section slecb
+.section sleda
+.section sledb
+.section sleea
+.section sleeb
+.section slefa
+.section slefb
+.section slega
+.section slegb
+.section sleha
+.section slehb
+.section sleia
+.section sleib
+.section sleja
+.section slejb
+.section sleka
+.section slekb
+.section slela
+.section slelb
+.section slema
+.section slemb
+.section slena
+.section slenb
+.section sleoa
+.section sleob
+.section slepa
+.section slepb
+.section sleqa
+.section sleqb
+.section slera
+.section slerb
+.section slesa
+.section slesb
+.section sleta
+.section sletb
+.section sleua
+.section sleub
+.section sleva
+.section slevb
+.section slewa
+.section slewb
+.section slexa
+.section slexb
+.section sleya
+.section sleyb
+.section sleza
+.section slezb
+.section sle1a
+.section sle1b
+.section sle2a
+.section sle2b
+.section sle3a
+.section sle3b
+.section sle4a
+.section sle4b
+.section sle5a
+.section sle5b
+.section sle6a
+.section sle6b
+.section sle7a
+.section sle7b
+.section sle8a
+.section sle8b
+.section sle9a
+.section sle9b
+.section sle0a
+.section sle0b
+.section slfaa
+.section slfab
+.section slfba
+.section slfbb
+.section slfca
+.section slfcb
+.section slfda
+.section slfdb
+.section slfea
+.section slfeb
+.section slffa
+.section slffb
+.section slfga
+.section slfgb
+.section slfha
+.section slfhb
+.section slfia
+.section slfib
+.section slfja
+.section slfjb
+.section slfka
+.section slfkb
+.section slfla
+.section slflb
+.section slfma
+.section slfmb
+.section slfna
+.section slfnb
+.section slfoa
+.section slfob
+.section slfpa
+.section slfpb
+.section slfqa
+.section slfqb
+.section slfra
+.section slfrb
+.section slfsa
+.section slfsb
+.section slfta
+.section slftb
+.section slfua
+.section slfub
+.section slfva
+.section slfvb
+.section slfwa
+.section slfwb
+.section slfxa
+.section slfxb
+.section slfya
+.section slfyb
+.section slfza
+.section slfzb
+.section slf1a
+.section slf1b
+.section slf2a
+.section slf2b
+.section slf3a
+.section slf3b
+.section slf4a
+.section slf4b
+.section slf5a
+.section slf5b
+.section slf6a
+.section slf6b
+.section slf7a
+.section slf7b
+.section slf8a
+.section slf8b
+.section slf9a
+.section slf9b
+.section slf0a
+.section slf0b
+.section slgaa
+.section slgab
+.section slgba
+.section slgbb
+.section slgca
+.section slgcb
+.section slgda
+.section slgdb
+.section slgea
+.section slgeb
+.section slgfa
+.section slgfb
+.section slgga
+.section slggb
+.section slgha
+.section slghb
+.section slgia
+.section slgib
+.section slgja
+.section slgjb
+.section slgka
+.section slgkb
+.section slgla
+.section slglb
+.section slgma
+.section slgmb
+.section slgna
+.section slgnb
+.section slgoa
+.section slgob
+.section slgpa
+.section slgpb
+.section slgqa
+.section slgqb
+.section slgra
+.section slgrb
+.section slgsa
+.section slgsb
+.section slgta
+.section slgtb
+.section slgua
+.section slgub
+.section slgva
+.section slgvb
+.section slgwa
+.section slgwb
+.section slgxa
+.section slgxb
+.section slgya
+.section slgyb
+.section slgza
+.section slgzb
+.section slg1a
+.section slg1b
+.section slg2a
+.section slg2b
+.section slg3a
+.section slg3b
+.section slg4a
+.section slg4b
+.section slg5a
+.section slg5b
+.section slg6a
+.section slg6b
+.section slg7a
+.section slg7b
+.section slg8a
+.section slg8b
+.section slg9a
+.section slg9b
+.section slg0a
+.section slg0b
+.section slhaa
+.section slhab
+.section slhba
+.section slhbb
+.section slhca
+.section slhcb
+.section slhda
+.section slhdb
+.section slhea
+.section slheb
+.section slhfa
+.section slhfb
+.section slhga
+.section slhgb
+.section slhha
+.section slhhb
+.section slhia
+.section slhib
+.section slhja
+.section slhjb
+.section slhka
+.section slhkb
+.section slhla
+.section slhlb
+.section slhma
+.section slhmb
+.section slhna
+.section slhnb
+.section slhoa
+.section slhob
+.section slhpa
+.section slhpb
+.section slhqa
+.section slhqb
+.section slhra
+.section slhrb
+.section slhsa
+.section slhsb
+.section slhta
+.section slhtb
+.section slhua
+.section slhub
+.section slhva
+.section slhvb
+.section slhwa
+.section slhwb
+.section slhxa
+.section slhxb
+.section slhya
+.section slhyb
+.section slhza
+.section slhzb
+.section slh1a
+.section slh1b
+.section slh2a
+.section slh2b
+.section slh3a
+.section slh3b
+.section slh4a
+.section slh4b
+.section slh5a
+.section slh5b
+.section slh6a
+.section slh6b
+.section slh7a
+.section slh7b
+.section slh8a
+.section slh8b
+.section slh9a
+.section slh9b
+.section slh0a
+.section slh0b
+.section sliaa
+.section sliab
+.section sliba
+.section slibb
+.section slica
+.section slicb
+.section slida
+.section slidb
+.section sliea
+.section slieb
+.section slifa
+.section slifb
+.section sliga
+.section sligb
+.section sliha
+.section slihb
+.section sliia
+.section sliib
+.section slija
+.section slijb
+.section slika
+.section slikb
+.section slila
+.section slilb
+.section slima
+.section slimb
+.section slina
+.section slinb
+.section slioa
+.section sliob
+.section slipa
+.section slipb
+.section sliqa
+.section sliqb
+.section slira
+.section slirb
+.section slisa
+.section slisb
+.section slita
+.section slitb
+.section sliua
+.section sliub
+.section sliva
+.section slivb
+.section sliwa
+.section sliwb
+.section slixa
+.section slixb
+.section sliya
+.section sliyb
+.section sliza
+.section slizb
+.section sli1a
+.section sli1b
+.section sli2a
+.section sli2b
+.section sli3a
+.section sli3b
+.section sli4a
+.section sli4b
+.section sli5a
+.section sli5b
+.section sli6a
+.section sli6b
+.section sli7a
+.section sli7b
+.section sli8a
+.section sli8b
+.section sli9a
+.section sli9b
+.section sli0a
+.section sli0b
+.section sljaa
+.section sljab
+.section sljba
+.section sljbb
+.section sljca
+.section sljcb
+.section sljda
+.section sljdb
+.section sljea
+.section sljeb
+.section sljfa
+.section sljfb
+.section sljga
+.section sljgb
+.section sljha
+.section sljhb
+.section sljia
+.section sljib
+.section sljja
+.section sljjb
+.section sljka
+.section sljkb
+.section sljla
+.section sljlb
+.section sljma
+.section sljmb
+.section sljna
+.section sljnb
+.section sljoa
+.section sljob
+.section sljpa
+.section sljpb
+.section sljqa
+.section sljqb
+.section sljra
+.section sljrb
+.section sljsa
+.section sljsb
+.section sljta
+.section sljtb
+.section sljua
+.section sljub
+.section sljva
+.section sljvb
+.section sljwa
+.section sljwb
+.section sljxa
+.section sljxb
+.section sljya
+.section sljyb
+.section sljza
+.section sljzb
+.section slj1a
+.section slj1b
+.section slj2a
+.section slj2b
+.section slj3a
+.section slj3b
+.section slj4a
+.section slj4b
+.section slj5a
+.section slj5b
+.section slj6a
+.section slj6b
+.section slj7a
+.section slj7b
+.section slj8a
+.section slj8b
+.section slj9a
+.section slj9b
+.section slj0a
+.section slj0b
+.section slkaa
+.section slkab
+.section slkba
+.section slkbb
+.section slkca
+.section slkcb
+.section slkda
+.section slkdb
+.section slkea
+.section slkeb
+.section slkfa
+.section slkfb
+.section slkga
+.section slkgb
+.section slkha
+.section slkhb
+.section slkia
+.section slkib
+.section slkja
+.section slkjb
+.section slkka
+.section slkkb
+.section slkla
+.section slklb
+.section slkma
+.section slkmb
+.section slkna
+.section slknb
+.section slkoa
+.section slkob
+.section slkpa
+.section slkpb
+.section slkqa
+.section slkqb
+.section slkra
+.section slkrb
+.section slksa
+.section slksb
+.section slkta
+.section slktb
+.section slkua
+.section slkub
+.section slkva
+.section slkvb
+.section slkwa
+.section slkwb
+.section slkxa
+.section slkxb
+.section slkya
+.section slkyb
+.section slkza
+.section slkzb
+.section slk1a
+.section slk1b
+.section slk2a
+.section slk2b
+.section slk3a
+.section slk3b
+.section slk4a
+.section slk4b
+.section slk5a
+.section slk5b
+.section slk6a
+.section slk6b
+.section slk7a
+.section slk7b
+.section slk8a
+.section slk8b
+.section slk9a
+.section slk9b
+.section slk0a
+.section slk0b
+.section sllaa
+.section sllab
+.section sllba
+.section sllbb
+.section sllca
+.section sllcb
+.section sllda
+.section slldb
+.section sllea
+.section slleb
+.section sllfa
+.section sllfb
+.section sllga
+.section sllgb
+.section sllha
+.section sllhb
+.section sllia
+.section sllib
+.section sllja
+.section slljb
+.section sllka
+.section sllkb
+.section sllla
+.section slllb
+.section sllma
+.section sllmb
+.section sllna
+.section sllnb
+.section slloa
+.section sllob
+.section sllpa
+.section sllpb
+.section sllqa
+.section sllqb
+.section sllra
+.section sllrb
+.section sllsa
+.section sllsb
+.section sllta
+.section slltb
+.section sllua
+.section sllub
+.section sllva
+.section sllvb
+.section sllwa
+.section sllwb
+.section sllxa
+.section sllxb
+.section sllya
+.section sllyb
+.section sllza
+.section sllzb
+.section sll1a
+.section sll1b
+.section sll2a
+.section sll2b
+.section sll3a
+.section sll3b
+.section sll4a
+.section sll4b
+.section sll5a
+.section sll5b
+.section sll6a
+.section sll6b
+.section sll7a
+.section sll7b
+.section sll8a
+.section sll8b
+.section sll9a
+.section sll9b
+.section sll0a
+.section sll0b
+.section slmaa
+.section slmab
+.section slmba
+.section slmbb
+.section slmca
+.section slmcb
+.section slmda
+.section slmdb
+.section slmea
+.section slmeb
+.section slmfa
+.section slmfb
+.section slmga
+.section slmgb
+.section slmha
+.section slmhb
+.section slmia
+.section slmib
+.section slmja
+.section slmjb
+.section slmka
+.section slmkb
+.section slmla
+.section slmlb
+.section slmma
+.section slmmb
+.section slmna
+.section slmnb
+.section slmoa
+.section slmob
+.section slmpa
+.section slmpb
+.section slmqa
+.section slmqb
+.section slmra
+.section slmrb
+.section slmsa
+.section slmsb
+.section slmta
+.section slmtb
+.section slmua
+.section slmub
+.section slmva
+.section slmvb
+.section slmwa
+.section slmwb
+.section slmxa
+.section slmxb
+.section slmya
+.section slmyb
+.section slmza
+.section slmzb
+.section slm1a
+.section slm1b
+.section slm2a
+.section slm2b
+.section slm3a
+.section slm3b
+.section slm4a
+.section slm4b
+.section slm5a
+.section slm5b
+.section slm6a
+.section slm6b
+.section slm7a
+.section slm7b
+.section slm8a
+.section slm8b
+.section slm9a
+.section slm9b
+.section slm0a
+.section slm0b
+.section slnaa
+.section slnab
+.section slnba
+.section slnbb
+.section slnca
+.section slncb
+.section slnda
+.section slndb
+.section slnea
+.section slneb
+.section slnfa
+.section slnfb
+.section slnga
+.section slngb
+.section slnha
+.section slnhb
+.section slnia
+.section slnib
+.section slnja
+.section slnjb
+.section slnka
+.section slnkb
+.section slnla
+.section slnlb
+.section slnma
+.section slnmb
+.section slnna
+.section slnnb
+.section slnoa
+.section slnob
+.section slnpa
+.section slnpb
+.section slnqa
+.section slnqb
+.section slnra
+.section slnrb
+.section slnsa
+.section slnsb
+.section slnta
+.section slntb
+.section slnua
+.section slnub
+.section slnva
+.section slnvb
+.section slnwa
+.section slnwb
+.section slnxa
+.section slnxb
+.section slnya
+.section slnyb
+.section slnza
+.section slnzb
+.section sln1a
+.section sln1b
+.section sln2a
+.section sln2b
+.section sln3a
+.section sln3b
+.section sln4a
+.section sln4b
+.section sln5a
+.section sln5b
+.section sln6a
+.section sln6b
+.section sln7a
+.section sln7b
+.section sln8a
+.section sln8b
+.section sln9a
+.section sln9b
+.section sln0a
+.section sln0b
+.section sloaa
+.section sloab
+.section sloba
+.section slobb
+.section sloca
+.section slocb
+.section sloda
+.section slodb
+.section sloea
+.section sloeb
+.section slofa
+.section slofb
+.section sloga
+.section slogb
+.section sloha
+.section slohb
+.section sloia
+.section sloib
+.section sloja
+.section slojb
+.section sloka
+.section slokb
+.section slola
+.section slolb
+.section sloma
+.section slomb
+.section slona
+.section slonb
+.section slooa
+.section sloob
+.section slopa
+.section slopb
+.section sloqa
+.section sloqb
+.section slora
+.section slorb
+.section slosa
+.section slosb
+.section slota
+.section slotb
+.section sloua
+.section sloub
+.section slova
+.section slovb
+.section slowa
+.section slowb
+.section sloxa
+.section sloxb
+.section sloya
+.section sloyb
+.section sloza
+.section slozb
+.section slo1a
+.section slo1b
+.section slo2a
+.section slo2b
+.section slo3a
+.section slo3b
+.section slo4a
+.section slo4b
+.section slo5a
+.section slo5b
+.section slo6a
+.section slo6b
+.section slo7a
+.section slo7b
+.section slo8a
+.section slo8b
+.section slo9a
+.section slo9b
+.section slo0a
+.section slo0b
+.section slpaa
+.section slpab
+.section slpba
+.section slpbb
+.section slpca
+.section slpcb
+.section slpda
+.section slpdb
+.section slpea
+.section slpeb
+.section slpfa
+.section slpfb
+.section slpga
+.section slpgb
+.section slpha
+.section slphb
+.section slpia
+.section slpib
+.section slpja
+.section slpjb
+.section slpka
+.section slpkb
+.section slpla
+.section slplb
+.section slpma
+.section slpmb
+.section slpna
+.section slpnb
+.section slpoa
+.section slpob
+.section slppa
+.section slppb
+.section slpqa
+.section slpqb
+.section slpra
+.section slprb
+.section slpsa
+.section slpsb
+.section slpta
+.section slptb
+.section slpua
+.section slpub
+.section slpva
+.section slpvb
+.section slpwa
+.section slpwb
+.section slpxa
+.section slpxb
+.section slpya
+.section slpyb
+.section slpza
+.section slpzb
+.section slp1a
+.section slp1b
+.section slp2a
+.section slp2b
+.section slp3a
+.section slp3b
+.section slp4a
+.section slp4b
+.section slp5a
+.section slp5b
+.section slp6a
+.section slp6b
+.section slp7a
+.section slp7b
+.section slp8a
+.section slp8b
+.section slp9a
+.section slp9b
+.section slp0a
+.section slp0b
+.section slqaa
+.section slqab
+.section slqba
+.section slqbb
+.section slqca
+.section slqcb
+.section slqda
+.section slqdb
+.section slqea
+.section slqeb
+.section slqfa
+.section slqfb
+.section slqga
+.section slqgb
+.section slqha
+.section slqhb
+.section slqia
+.section slqib
+.section slqja
+.section slqjb
+.section slqka
+.section slqkb
+.section slqla
+.section slqlb
+.section slqma
+.section slqmb
+.section slqna
+.section slqnb
+.section slqoa
+.section slqob
+.section slqpa
+.section slqpb
+.section slqqa
+.section slqqb
+.section slqra
+.section slqrb
+.section slqsa
+.section slqsb
+.section slqta
+.section slqtb
+.section slqua
+.section slqub
+.section slqva
+.section slqvb
+.section slqwa
+.section slqwb
+.section slqxa
+.section slqxb
+.section slqya
+.section slqyb
+.section slqza
+.section slqzb
+.section slq1a
+.section slq1b
+.section slq2a
+.section slq2b
+.section slq3a
+.section slq3b
+.section slq4a
+.section slq4b
+.section slq5a
+.section slq5b
+.section slq6a
+.section slq6b
+.section slq7a
+.section slq7b
+.section slq8a
+.section slq8b
+.section slq9a
+.section slq9b
+.section slq0a
+.section slq0b
+.section slraa
+.section slrab
+.section slrba
+.section slrbb
+.section slrca
+.section slrcb
+.section slrda
+.section slrdb
+.section slrea
+.section slreb
+.section slrfa
+.section slrfb
+.section slrga
+.section slrgb
+.section slrha
+.section slrhb
+.section slria
+.section slrib
+.section slrja
+.section slrjb
+.section slrka
+.section slrkb
+.section slrla
+.section slrlb
+.section slrma
+.section slrmb
+.section slrna
+.section slrnb
+.section slroa
+.section slrob
+.section slrpa
+.section slrpb
+.section slrqa
+.section slrqb
+.section slrra
+.section slrrb
+.section slrsa
+.section slrsb
+.section slrta
+.section slrtb
+.section slrua
+.section slrub
+.section slrva
+.section slrvb
+.section slrwa
+.section slrwb
+.section slrxa
+.section slrxb
+.section slrya
+.section slryb
+.section slrza
+.section slrzb
+.section slr1a
+.section slr1b
+.section slr2a
+.section slr2b
+.section slr3a
+.section slr3b
+.section slr4a
+.section slr4b
+.section slr5a
+.section slr5b
+.section slr6a
+.section slr6b
+.section slr7a
+.section slr7b
+.section slr8a
+.section slr8b
+.section slr9a
+.section slr9b
+.section slr0a
+.section slr0b
+.section slsaa
+.section slsab
+.section slsba
+.section slsbb
+.section slsca
+.section slscb
+.section slsda
+.section slsdb
+.section slsea
+.section slseb
+.section slsfa
+.section slsfb
+.section slsga
+.section slsgb
+.section slsha
+.section slshb
+.section slsia
+.section slsib
+.section slsja
+.section slsjb
+.section slska
+.section slskb
+.section slsla
+.section slslb
+.section slsma
+.section slsmb
+.section slsna
+.section slsnb
+.section slsoa
+.section slsob
+.section slspa
+.section slspb
+.section slsqa
+.section slsqb
+.section slsra
+.section slsrb
+.section slssa
+.section slssb
+.section slsta
+.section slstb
+.section slsua
+.section slsub
+.section slsva
+.section slsvb
+.section slswa
+.section slswb
+.section slsxa
+.section slsxb
+.section slsya
+.section slsyb
+.section slsza
+.section slszb
+.section sls1a
+.section sls1b
+.section sls2a
+.section sls2b
+.section sls3a
+.section sls3b
+.section sls4a
+.section sls4b
+.section sls5a
+.section sls5b
+.section sls6a
+.section sls6b
+.section sls7a
+.section sls7b
+.section sls8a
+.section sls8b
+.section sls9a
+.section sls9b
+.section sls0a
+.section sls0b
+.section sltaa
+.section sltab
+.section sltba
+.section sltbb
+.section sltca
+.section sltcb
+.section sltda
+.section sltdb
+.section sltea
+.section slteb
+.section sltfa
+.section sltfb
+.section sltga
+.section sltgb
+.section sltha
+.section slthb
+.section sltia
+.section sltib
+.section sltja
+.section sltjb
+.section sltka
+.section sltkb
+.section sltla
+.section sltlb
+.section sltma
+.section sltmb
+.section sltna
+.section sltnb
+.section sltoa
+.section sltob
+.section sltpa
+.section sltpb
+.section sltqa
+.section sltqb
+.section sltra
+.section sltrb
+.section sltsa
+.section sltsb
+.section sltta
+.section slttb
+.section sltua
+.section sltub
+.section sltva
+.section sltvb
+.section sltwa
+.section sltwb
+.section sltxa
+.section sltxb
+.section sltya
+.section sltyb
+.section sltza
+.section sltzb
+.section slt1a
+.section slt1b
+.section slt2a
+.section slt2b
+.section slt3a
+.section slt3b
+.section slt4a
+.section slt4b
+.section slt5a
+.section slt5b
+.section slt6a
+.section slt6b
+.section slt7a
+.section slt7b
+.section slt8a
+.section slt8b
+.section slt9a
+.section slt9b
+.section slt0a
+.section slt0b
+.section sluaa
+.section sluab
+.section sluba
+.section slubb
+.section sluca
+.section slucb
+.section sluda
+.section sludb
+.section sluea
+.section slueb
+.section slufa
+.section slufb
+.section sluga
+.section slugb
+.section sluha
+.section sluhb
+.section sluia
+.section sluib
+.section sluja
+.section slujb
+.section sluka
+.section slukb
+.section slula
+.section slulb
+.section sluma
+.section slumb
+.section sluna
+.section slunb
+.section sluoa
+.section sluob
+.section slupa
+.section slupb
+.section sluqa
+.section sluqb
+.section slura
+.section slurb
+.section slusa
+.section slusb
+.section sluta
+.section slutb
+.section sluua
+.section sluub
+.section sluva
+.section sluvb
+.section sluwa
+.section sluwb
+.section sluxa
+.section sluxb
+.section sluya
+.section sluyb
+.section sluza
+.section sluzb
+.section slu1a
+.section slu1b
+.section slu2a
+.section slu2b
+.section slu3a
+.section slu3b
+.section slu4a
+.section slu4b
+.section slu5a
+.section slu5b
+.section slu6a
+.section slu6b
+.section slu7a
+.section slu7b
+.section slu8a
+.section slu8b
+.section slu9a
+.section slu9b
+.section slu0a
+.section slu0b
+.section slvaa
+.section slvab
+.section slvba
+.section slvbb
+.section slvca
+.section slvcb
+.section slvda
+.section slvdb
+.section slvea
+.section slveb
+.section slvfa
+.section slvfb
+.section slvga
+.section slvgb
+.section slvha
+.section slvhb
+.section slvia
+.section slvib
+.section slvja
+.section slvjb
+.section slvka
+.section slvkb
+.section slvla
+.section slvlb
+.section slvma
+.section slvmb
+.section slvna
+.section slvnb
+.section slvoa
+.section slvob
+.section slvpa
+.section slvpb
+.section slvqa
+.section slvqb
+.section slvra
+.section slvrb
+.section slvsa
+.section slvsb
+.section slvta
+.section slvtb
+.section slvua
+.section slvub
+.section slvva
+.section slvvb
+.section slvwa
+.section slvwb
+.section slvxa
+.section slvxb
+.section slvya
+.section slvyb
+.section slvza
+.section slvzb
+.section slv1a
+.section slv1b
+.section slv2a
+.section slv2b
+.section slv3a
+.section slv3b
+.section slv4a
+.section slv4b
+.section slv5a
+.section slv5b
+.section slv6a
+.section slv6b
+.section slv7a
+.section slv7b
+.section slv8a
+.section slv8b
+.section slv9a
+.section slv9b
+.section slv0a
+.section slv0b
+.section slwaa
+.section slwab
+.section slwba
+.section slwbb
+.section slwca
+.section slwcb
+.section slwda
+.section slwdb
+.section slwea
+.section slweb
+.section slwfa
+.section slwfb
+.section slwga
+.section slwgb
+.section slwha
+.section slwhb
+.section slwia
+.section slwib
+.section slwja
+.section slwjb
+.section slwka
+.section slwkb
+.section slwla
+.section slwlb
+.section slwma
+.section slwmb
+.section slwna
+.section slwnb
+.section slwoa
+.section slwob
+.section slwpa
+.section slwpb
+.section slwqa
+.section slwqb
+.section slwra
+.section slwrb
+.section slwsa
+.section slwsb
+.section slwta
+.section slwtb
+.section slwua
+.section slwub
+.section slwva
+.section slwvb
+.section slwwa
+.section slwwb
+.section slwxa
+.section slwxb
+.section slwya
+.section slwyb
+.section slwza
+.section slwzb
+.section slw1a
+.section slw1b
+.section slw2a
+.section slw2b
+.section slw3a
+.section slw3b
+.section slw4a
+.section slw4b
+.section slw5a
+.section slw5b
+.section slw6a
+.section slw6b
+.section slw7a
+.section slw7b
+.section slw8a
+.section slw8b
+.section slw9a
+.section slw9b
+.section slw0a
+.section slw0b
+.section slxaa
+.section slxab
+.section slxba
+.section slxbb
+.section slxca
+.section slxcb
+.section slxda
+.section slxdb
+.section slxea
+.section slxeb
+.section slxfa
+.section slxfb
+.section slxga
+.section slxgb
+.section slxha
+.section slxhb
+.section slxia
+.section slxib
+.section slxja
+.section slxjb
+.section slxka
+.section slxkb
+.section slxla
+.section slxlb
+.section slxma
+.section slxmb
+.section slxna
+.section slxnb
+.section slxoa
+.section slxob
+.section slxpa
+.section slxpb
+.section slxqa
+.section slxqb
+.section slxra
+.section slxrb
+.section slxsa
+.section slxsb
+.section slxta
+.section slxtb
+.section slxua
+.section slxub
+.section slxva
+.section slxvb
+.section slxwa
+.section slxwb
+.section slxxa
+.section slxxb
+.section slxya
+.section slxyb
+.section slxza
+.section slxzb
+.section slx1a
+.section slx1b
+.section slx2a
+.section slx2b
+.section slx3a
+.section slx3b
+.section slx4a
+.section slx4b
+.section slx5a
+.section slx5b
+.section slx6a
+.section slx6b
+.section slx7a
+.section slx7b
+.section slx8a
+.section slx8b
+.section slx9a
+.section slx9b
+.section slx0a
+.section slx0b
+.section slyaa
+.section slyab
+.section slyba
+.section slybb
+.section slyca
+.section slycb
+.section slyda
+.section slydb
+.section slyea
+.section slyeb
+.section slyfa
+.section slyfb
+.section slyga
+.section slygb
+.section slyha
+.section slyhb
+.section slyia
+.section slyib
+.section slyja
+.section slyjb
+.section slyka
+.section slykb
+.section slyla
+.section slylb
+.section slyma
+.section slymb
+.section slyna
+.section slynb
+.section slyoa
+.section slyob
+.section slypa
+.section slypb
+.section slyqa
+.section slyqb
+.section slyra
+.section slyrb
+.section slysa
+.section slysb
+.section slyta
+.section slytb
+.section slyua
+.section slyub
+.section slyva
+.section slyvb
+.section slywa
+.section slywb
+.section slyxa
+.section slyxb
+.section slyya
+.section slyyb
+.section slyza
+.section slyzb
+.section sly1a
+.section sly1b
+.section sly2a
+.section sly2b
+.section sly3a
+.section sly3b
+.section sly4a
+.section sly4b
+.section sly5a
+.section sly5b
+.section sly6a
+.section sly6b
+.section sly7a
+.section sly7b
+.section sly8a
+.section sly8b
+.section sly9a
+.section sly9b
+.section sly0a
+.section sly0b
+.section slzaa
+.section slzab
+.section slzba
+.section slzbb
+.section slzca
+.section slzcb
+.section slzda
+.section slzdb
+.section slzea
+.section slzeb
+.section slzfa
+.section slzfb
+.section slzga
+.section slzgb
+.section slzha
+.section slzhb
+.section slzia
+.section slzib
+.section slzja
+.section slzjb
+.section slzka
+.section slzkb
+.section slzla
+.section slzlb
+.section slzma
+.section slzmb
+.section slzna
+.section slznb
+.section slzoa
+.section slzob
+.section slzpa
+.section slzpb
+.section slzqa
+.section slzqb
+.section slzra
+.section slzrb
+.section slzsa
+.section slzsb
+.section slzta
+.section slztb
+.section slzua
+.section slzub
+.section slzva
+.section slzvb
+.section slzwa
+.section slzwb
+.section slzxa
+.section slzxb
+.section slzya
+.section slzyb
+.section slzza
+.section slzzb
+.section slz1a
+.section slz1b
+.section slz2a
+.section slz2b
+.section slz3a
+.section slz3b
+.section slz4a
+.section slz4b
+.section slz5a
+.section slz5b
+.section slz6a
+.section slz6b
+.section slz7a
+.section slz7b
+.section slz8a
+.section slz8b
+.section slz9a
+.section slz9b
+.section slz0a
+.section slz0b
+.section sl1aa
+.section sl1ab
+.section sl1ba
+.section sl1bb
+.section sl1ca
+.section sl1cb
+.section sl1da
+.section sl1db
+.section sl1ea
+.section sl1eb
+.section sl1fa
+.section sl1fb
+.section sl1ga
+.section sl1gb
+.section sl1ha
+.section sl1hb
+.section sl1ia
+.section sl1ib
+.section sl1ja
+.section sl1jb
+.section sl1ka
+.section sl1kb
+.section sl1la
+.section sl1lb
+.section sl1ma
+.section sl1mb
+.section sl1na
+.section sl1nb
+.section sl1oa
+.section sl1ob
+.section sl1pa
+.section sl1pb
+.section sl1qa
+.section sl1qb
+.section sl1ra
+.section sl1rb
+.section sl1sa
+.section sl1sb
+.section sl1ta
+.section sl1tb
+.section sl1ua
+.section sl1ub
+.section sl1va
+.section sl1vb
+.section sl1wa
+.section sl1wb
+.section sl1xa
+.section sl1xb
+.section sl1ya
+.section sl1yb
+.section sl1za
+.section sl1zb
+.section sl11a
+.section sl11b
+.section sl12a
+.section sl12b
+.section sl13a
+.section sl13b
+.section sl14a
+.section sl14b
+.section sl15a
+.section sl15b
+.section sl16a
+.section sl16b
+.section sl17a
+.section sl17b
+.section sl18a
+.section sl18b
+.section sl19a
+.section sl19b
+.section sl10a
+.section sl10b
+.section sl2aa
+.section sl2ab
+.section sl2ba
+.section sl2bb
+.section sl2ca
+.section sl2cb
+.section sl2da
+.section sl2db
+.section sl2ea
+.section sl2eb
+.section sl2fa
+.section sl2fb
+.section sl2ga
+.section sl2gb
+.section sl2ha
+.section sl2hb
+.section sl2ia
+.section sl2ib
+.section sl2ja
+.section sl2jb
+.section sl2ka
+.section sl2kb
+.section sl2la
+.section sl2lb
+.section sl2ma
+.section sl2mb
+.section sl2na
+.section sl2nb
+.section sl2oa
+.section sl2ob
+.section sl2pa
+.section sl2pb
+.section sl2qa
+.section sl2qb
+.section sl2ra
+.section sl2rb
+.section sl2sa
+.section sl2sb
+.section sl2ta
+.section sl2tb
+.section sl2ua
+.section sl2ub
+.section sl2va
+.section sl2vb
+.section sl2wa
+.section sl2wb
+.section sl2xa
+.section sl2xb
+.section sl2ya
+.section sl2yb
+.section sl2za
+.section sl2zb
+.section sl21a
+.section sl21b
+.section sl22a
+.section sl22b
+.section sl23a
+.section sl23b
+.section sl24a
+.section sl24b
+.section sl25a
+.section sl25b
+.section sl26a
+.section sl26b
+.section sl27a
+.section sl27b
+.section sl28a
+.section sl28b
+.section sl29a
+.section sl29b
+.section sl20a
+.section sl20b
+.section sl3aa
+.section sl3ab
+.section sl3ba
+.section sl3bb
+.section sl3ca
+.section sl3cb
+.section sl3da
+.section sl3db
+.section sl3ea
+.section sl3eb
+.section sl3fa
+.section sl3fb
+.section sl3ga
+.section sl3gb
+.section sl3ha
+.section sl3hb
+.section sl3ia
+.section sl3ib
+.section sl3ja
+.section sl3jb
+.section sl3ka
+.section sl3kb
+.section sl3la
+.section sl3lb
+.section sl3ma
+.section sl3mb
+.section sl3na
+.section sl3nb
+.section sl3oa
+.section sl3ob
+.section sl3pa
+.section sl3pb
+.section sl3qa
+.section sl3qb
+.section sl3ra
+.section sl3rb
+.section sl3sa
+.section sl3sb
+.section sl3ta
+.section sl3tb
+.section sl3ua
+.section sl3ub
+.section sl3va
+.section sl3vb
+.section sl3wa
+.section sl3wb
+.section sl3xa
+.section sl3xb
+.section sl3ya
+.section sl3yb
+.section sl3za
+.section sl3zb
+.section sl31a
+.section sl31b
+.section sl32a
+.section sl32b
+.section sl33a
+.section sl33b
+.section sl34a
+.section sl34b
+.section sl35a
+.section sl35b
+.section sl36a
+.section sl36b
+.section sl37a
+.section sl37b
+.section sl38a
+.section sl38b
+.section sl39a
+.section sl39b
+.section sl30a
+.section sl30b
+.section sl4aa
+.section sl4ab
+.section sl4ba
+.section sl4bb
+.section sl4ca
+.section sl4cb
+.section sl4da
+.section sl4db
+.section sl4ea
+.section sl4eb
+.section sl4fa
+.section sl4fb
+.section sl4ga
+.section sl4gb
+.section sl4ha
+.section sl4hb
+.section sl4ia
+.section sl4ib
+.section sl4ja
+.section sl4jb
+.section sl4ka
+.section sl4kb
+.section sl4la
+.section sl4lb
+.section sl4ma
+.section sl4mb
+.section sl4na
+.section sl4nb
+.section sl4oa
+.section sl4ob
+.section sl4pa
+.section sl4pb
+.section sl4qa
+.section sl4qb
+.section sl4ra
+.section sl4rb
+.section sl4sa
+.section sl4sb
+.section sl4ta
+.section sl4tb
+.section sl4ua
+.section sl4ub
+.section sl4va
+.section sl4vb
+.section sl4wa
+.section sl4wb
+.section sl4xa
+.section sl4xb
+.section sl4ya
+.section sl4yb
+.section sl4za
+.section sl4zb
+.section sl41a
+.section sl41b
+.section sl42a
+.section sl42b
+.section sl43a
+.section sl43b
+.section sl44a
+.section sl44b
+.section sl45a
+.section sl45b
+.section sl46a
+.section sl46b
+.section sl47a
+.section sl47b
+.section sl48a
+.section sl48b
+.section sl49a
+.section sl49b
+.section sl40a
+.section sl40b
+.section sl5aa
+.section sl5ab
+.section sl5ba
+.section sl5bb
+.section sl5ca
+.section sl5cb
+.section sl5da
+.section sl5db
+.section sl5ea
+.section sl5eb
+.section sl5fa
+.section sl5fb
+.section sl5ga
+.section sl5gb
+.section sl5ha
+.section sl5hb
+.section sl5ia
+.section sl5ib
+.section sl5ja
+.section sl5jb
+.section sl5ka
+.section sl5kb
+.section sl5la
+.section sl5lb
+.section sl5ma
+.section sl5mb
+.section sl5na
+.section sl5nb
+.section sl5oa
+.section sl5ob
+.section sl5pa
+.section sl5pb
+.section sl5qa
+.section sl5qb
+.section sl5ra
+.section sl5rb
+.section sl5sa
+.section sl5sb
+.section sl5ta
+.section sl5tb
+.section sl5ua
+.section sl5ub
+.section sl5va
+.section sl5vb
+.section sl5wa
+.section sl5wb
+.section sl5xa
+.section sl5xb
+.section sl5ya
+.section sl5yb
+.section sl5za
+.section sl5zb
+.section sl51a
+.section sl51b
+.section sl52a
+.section sl52b
+.section sl53a
+.section sl53b
+.section sl54a
+.section sl54b
+.section sl55a
+.section sl55b
+.section sl56a
+.section sl56b
+.section sl57a
+.section sl57b
+.section sl58a
+.section sl58b
+.section sl59a
+.section sl59b
+.section sl50a
+.section sl50b
+.section sl6aa
+.section sl6ab
+.section sl6ba
+.section sl6bb
+.section sl6ca
+.section sl6cb
+.section sl6da
+.section sl6db
+.section sl6ea
+.section sl6eb
+.section sl6fa
+.section sl6fb
+.section sl6ga
+.section sl6gb
+.section sl6ha
+.section sl6hb
+.section sl6ia
+.section sl6ib
+.section sl6ja
+.section sl6jb
+.section sl6ka
+.section sl6kb
+.section sl6la
+.section sl6lb
+.section sl6ma
+.section sl6mb
+.section sl6na
+.section sl6nb
+.section sl6oa
+.section sl6ob
+.section sl6pa
+.section sl6pb
+.section sl6qa
+.section sl6qb
+.section sl6ra
+.section sl6rb
+.section sl6sa
+.section sl6sb
+.section sl6ta
+.section sl6tb
+.section sl6ua
+.section sl6ub
+.section sl6va
+.section sl6vb
+.section sl6wa
+.section sl6wb
+.section sl6xa
+.section sl6xb
+.section sl6ya
+.section sl6yb
+.section sl6za
+.section sl6zb
+.section sl61a
+.section sl61b
+.section sl62a
+.section sl62b
+.section sl63a
+.section sl63b
+.section sl64a
+.section sl64b
+.section sl65a
+.section sl65b
+.section sl66a
+.section sl66b
+.section sl67a
+.section sl67b
+.section sl68a
+.section sl68b
+.section sl69a
+.section sl69b
+.section sl60a
+.section sl60b
+.section sl7aa
+.section sl7ab
+.section sl7ba
+.section sl7bb
+.section sl7ca
+.section sl7cb
+.section sl7da
+.section sl7db
+.section sl7ea
+.section sl7eb
+.section sl7fa
+.section sl7fb
+.section sl7ga
+.section sl7gb
+.section sl7ha
+.section sl7hb
+.section sl7ia
+.section sl7ib
+.section sl7ja
+.section sl7jb
+.section sl7ka
+.section sl7kb
+.section sl7la
+.section sl7lb
+.section sl7ma
+.section sl7mb
+.section sl7na
+.section sl7nb
+.section sl7oa
+.section sl7ob
+.section sl7pa
+.section sl7pb
+.section sl7qa
+.section sl7qb
+.section sl7ra
+.section sl7rb
+.section sl7sa
+.section sl7sb
+.section sl7ta
+.section sl7tb
+.section sl7ua
+.section sl7ub
+.section sl7va
+.section sl7vb
+.section sl7wa
+.section sl7wb
+.section sl7xa
+.section sl7xb
+.section sl7ya
+.section sl7yb
+.section sl7za
+.section sl7zb
+.section sl71a
+.section sl71b
+.section sl72a
+.section sl72b
+.section sl73a
+.section sl73b
+.section sl74a
+.section sl74b
+.section sl75a
+.section sl75b
+.section sl76a
+.section sl76b
+.section sl77a
+.section sl77b
+.section sl78a
+.section sl78b
+.section sl79a
+.section sl79b
+.section sl70a
+.section sl70b
+.section sl8aa
+.section sl8ab
+.section sl8ba
+.section sl8bb
+.section sl8ca
+.section sl8cb
+.section sl8da
+.section sl8db
+.section sl8ea
+.section sl8eb
+.section sl8fa
+.section sl8fb
+.section sl8ga
+.section sl8gb
+.section sl8ha
+.section sl8hb
+.section sl8ia
+.section sl8ib
+.section sl8ja
+.section sl8jb
+.section sl8ka
+.section sl8kb
+.section sl8la
+.section sl8lb
+.section sl8ma
+.section sl8mb
+.section sl8na
+.section sl8nb
+.section sl8oa
+.section sl8ob
+.section sl8pa
+.section sl8pb
+.section sl8qa
+.section sl8qb
+.section sl8ra
+.section sl8rb
+.section sl8sa
+.section sl8sb
+.section sl8ta
+.section sl8tb
+.section sl8ua
+.section sl8ub
+.section sl8va
+.section sl8vb
+.section sl8wa
+.section sl8wb
+.section sl8xa
+.section sl8xb
+.section sl8ya
+.section sl8yb
+.section sl8za
+.section sl8zb
+.section sl81a
+.section sl81b
+.section sl82a
+.section sl82b
+.section sl83a
+.section sl83b
+.section sl84a
+.section sl84b
+.section sl85a
+.section sl85b
+.section sl86a
+.section sl86b
+.section sl87a
+.section sl87b
+.section sl88a
+.section sl88b
+.section sl89a
+.section sl89b
+.section sl80a
+.section sl80b
+.section sl9aa
+.section sl9ab
+.section sl9ba
+.section sl9bb
+.section sl9ca
+.section sl9cb
+.section sl9da
+.section sl9db
+.section sl9ea
+.section sl9eb
+.section sl9fa
+.section sl9fb
+.section sl9ga
+.section sl9gb
+.section sl9ha
+.section sl9hb
+.section sl9ia
+.section sl9ib
+.section sl9ja
+.section sl9jb
+.section sl9ka
+.section sl9kb
+.section sl9la
+.section sl9lb
+.section sl9ma
+.section sl9mb
+.section sl9na
+.section sl9nb
+.section sl9oa
+.section sl9ob
+.section sl9pa
+.section sl9pb
+.section sl9qa
+.section sl9qb
+.section sl9ra
+.section sl9rb
+.section sl9sa
+.section sl9sb
+.section sl9ta
+.section sl9tb
+.section sl9ua
+.section sl9ub
+.section sl9va
+.section sl9vb
+.section sl9wa
+.section sl9wb
+.section sl9xa
+.section sl9xb
+.section sl9ya
+.section sl9yb
+.section sl9za
+.section sl9zb
+.section sl91a
+.section sl91b
+.section sl92a
+.section sl92b
+.section sl93a
+.section sl93b
+.section sl94a
+.section sl94b
+.section sl95a
+.section sl95b
+.section sl96a
+.section sl96b
+.section sl97a
+.section sl97b
+.section sl98a
+.section sl98b
+.section sl99a
+.section sl99b
+.section sl90a
+.section sl90b
+.section sl0aa
+.section sl0ab
+.section sl0ba
+.section sl0bb
+.section sl0ca
+.section sl0cb
+.section sl0da
+.section sl0db
+.section sl0ea
+.section sl0eb
+.section sl0fa
+.section sl0fb
+.section sl0ga
+.section sl0gb
+.section sl0ha
+.section sl0hb
+.section sl0ia
+.section sl0ib
+.section sl0ja
+.section sl0jb
+.section sl0ka
+.section sl0kb
+.section sl0la
+.section sl0lb
+.section sl0ma
+.section sl0mb
+.section sl0na
+.section sl0nb
+.section sl0oa
+.section sl0ob
+.section sl0pa
+.section sl0pb
+.section sl0qa
+.section sl0qb
+.section sl0ra
+.section sl0rb
+.section sl0sa
+.section sl0sb
+.section sl0ta
+.section sl0tb
+.section sl0ua
+.section sl0ub
+.section sl0va
+.section sl0vb
+.section sl0wa
+.section sl0wb
+.section sl0xa
+.section sl0xb
+.section sl0ya
+.section sl0yb
+.section sl0za
+.section sl0zb
+.section sl01a
+.section sl01b
+.section sl02a
+.section sl02b
+.section sl03a
+.section sl03b
+.section sl04a
+.section sl04b
+.section sl05a
+.section sl05b
+.section sl06a
+.section sl06b
+.section sl07a
+.section sl07b
+.section sl08a
+.section sl08b
+.section sl09a
+.section sl09b
+.section sl00a
+.section sl00b
+.section smaaa
+.section smaab
+.section smaba
+.section smabb
+.section smaca
+.section smacb
+.section smada
+.section smadb
+.section smaea
+.section smaeb
+.section smafa
+.section smafb
+.section smaga
+.section smagb
+.section smaha
+.section smahb
+.section smaia
+.section smaib
+.section smaja
+.section smajb
+.section smaka
+.section smakb
+.section smala
+.section smalb
+.section smama
+.section smamb
+.section smana
+.section smanb
+.section smaoa
+.section smaob
+.section smapa
+.section smapb
+.section smaqa
+.section smaqb
+.section smara
+.section smarb
+.section smasa
+.section smasb
+.section smata
+.section smatb
+.section smaua
+.section smaub
+.section smava
+.section smavb
+.section smawa
+.section smawb
+.section smaxa
+.section smaxb
+.section smaya
+.section smayb
+.section smaza
+.section smazb
+.section sma1a
+.section sma1b
+.section sma2a
+.section sma2b
+.section sma3a
+.section sma3b
+.section sma4a
+.section sma4b
+.section sma5a
+.section sma5b
+.section sma6a
+.section sma6b
+.section sma7a
+.section sma7b
+.section sma8a
+.section sma8b
+.section sma9a
+.section sma9b
+.section sma0a
+.section sma0b
+.section smbaa
+.section smbab
+.section smbba
+.section smbbb
+.section smbca
+.section smbcb
+.section smbda
+.section smbdb
+.section smbea
+.section smbeb
+.section smbfa
+.section smbfb
+.section smbga
+.section smbgb
+.section smbha
+.section smbhb
+.section smbia
+.section smbib
+.section smbja
+.section smbjb
+.section smbka
+.section smbkb
+.section smbla
+.section smblb
+.section smbma
+.section smbmb
+.section smbna
+.section smbnb
+.section smboa
+.section smbob
+.section smbpa
+.section smbpb
+.section smbqa
+.section smbqb
+.section smbra
+.section smbrb
+.section smbsa
+.section smbsb
+.section smbta
+.section smbtb
+.section smbua
+.section smbub
+.section smbva
+.section smbvb
+.section smbwa
+.section smbwb
+.section smbxa
+.section smbxb
+.section smbya
+.section smbyb
+.section smbza
+.section smbzb
+.section smb1a
+.section smb1b
+.section smb2a
+.section smb2b
+.section smb3a
+.section smb3b
+.section smb4a
+.section smb4b
+.section smb5a
+.section smb5b
+.section smb6a
+.section smb6b
+.section smb7a
+.section smb7b
+.section smb8a
+.section smb8b
+.section smb9a
+.section smb9b
+.section smb0a
+.section smb0b
+.section smcaa
+.section smcab
+.section smcba
+.section smcbb
+.section smcca
+.section smccb
+.section smcda
+.section smcdb
+.section smcea
+.section smceb
+.section smcfa
+.section smcfb
+.section smcga
+.section smcgb
+.section smcha
+.section smchb
+.section smcia
+.section smcib
+.section smcja
+.section smcjb
+.section smcka
+.section smckb
+.section smcla
+.section smclb
+.section smcma
+.section smcmb
+.section smcna
+.section smcnb
+.section smcoa
+.section smcob
+.section smcpa
+.section smcpb
+.section smcqa
+.section smcqb
+.section smcra
+.section smcrb
+.section smcsa
+.section smcsb
+.section smcta
+.section smctb
+.section smcua
+.section smcub
+.section smcva
+.section smcvb
+.section smcwa
+.section smcwb
+.section smcxa
+.section smcxb
+.section smcya
+.section smcyb
+.section smcza
+.section smczb
+.section smc1a
+.section smc1b
+.section smc2a
+.section smc2b
+.section smc3a
+.section smc3b
+.section smc4a
+.section smc4b
+.section smc5a
+.section smc5b
+.section smc6a
+.section smc6b
+.section smc7a
+.section smc7b
+.section smc8a
+.section smc8b
+.section smc9a
+.section smc9b
+.section smc0a
+.section smc0b
+.section smdaa
+.section smdab
+.section smdba
+.section smdbb
+.section smdca
+.section smdcb
+.section smdda
+.section smddb
+.section smdea
+.section smdeb
+.section smdfa
+.section smdfb
+.section smdga
+.section smdgb
+.section smdha
+.section smdhb
+.section smdia
+.section smdib
+.section smdja
+.section smdjb
+.section smdka
+.section smdkb
+.section smdla
+.section smdlb
+.section smdma
+.section smdmb
+.section smdna
+.section smdnb
+.section smdoa
+.section smdob
+.section smdpa
+.section smdpb
+.section smdqa
+.section smdqb
+.section smdra
+.section smdrb
+.section smdsa
+.section smdsb
+.section smdta
+.section smdtb
+.section smdua
+.section smdub
+.section smdva
+.section smdvb
+.section smdwa
+.section smdwb
+.section smdxa
+.section smdxb
+.section smdya
+.section smdyb
+.section smdza
+.section smdzb
+.section smd1a
+.section smd1b
+.section smd2a
+.section smd2b
+.section smd3a
+.section smd3b
+.section smd4a
+.section smd4b
+.section smd5a
+.section smd5b
+.section smd6a
+.section smd6b
+.section smd7a
+.section smd7b
+.section smd8a
+.section smd8b
+.section smd9a
+.section smd9b
+.section smd0a
+.section smd0b
+.section smeaa
+.section smeab
+.section smeba
+.section smebb
+.section smeca
+.section smecb
+.section smeda
+.section smedb
+.section smeea
+.section smeeb
+.section smefa
+.section smefb
+.section smega
+.section smegb
+.section smeha
+.section smehb
+.section smeia
+.section smeib
+.section smeja
+.section smejb
+.section smeka
+.section smekb
+.section smela
+.section smelb
+.section smema
+.section smemb
+.section smena
+.section smenb
+.section smeoa
+.section smeob
+.section smepa
+.section smepb
+.section smeqa
+.section smeqb
+.section smera
+.section smerb
+.section smesa
+.section smesb
+.section smeta
+.section smetb
+.section smeua
+.section smeub
+.section smeva
+.section smevb
+.section smewa
+.section smewb
+.section smexa
+.section smexb
+.section smeya
+.section smeyb
+.section smeza
+.section smezb
+.section sme1a
+.section sme1b
+.section sme2a
+.section sme2b
+.section sme3a
+.section sme3b
+.section sme4a
+.section sme4b
+.section sme5a
+.section sme5b
+.section sme6a
+.section sme6b
+.section sme7a
+.section sme7b
+.section sme8a
+.section sme8b
+.section sme9a
+.section sme9b
+.section sme0a
+.section sme0b
+.section smfaa
+.section smfab
+.section smfba
+.section smfbb
+.section smfca
+.section smfcb
+.section smfda
+.section smfdb
+.section smfea
+.section smfeb
+.section smffa
+.section smffb
+.section smfga
+.section smfgb
+.section smfha
+.section smfhb
+.section smfia
+.section smfib
+.section smfja
+.section smfjb
+.section smfka
+.section smfkb
+.section smfla
+.section smflb
+.section smfma
+.section smfmb
+.section smfna
+.section smfnb
+.section smfoa
+.section smfob
+.section smfpa
+.section smfpb
+.section smfqa
+.section smfqb
+.section smfra
+.section smfrb
+.section smfsa
+.section smfsb
+.section smfta
+.section smftb
+.section smfua
+.section smfub
+.section smfva
+.section smfvb
+.section smfwa
+.section smfwb
+.section smfxa
+.section smfxb
+.section smfya
+.section smfyb
+.section smfza
+.section smfzb
+.section smf1a
+.section smf1b
+.section smf2a
+.section smf2b
+.section smf3a
+.section smf3b
+.section smf4a
+.section smf4b
+.section smf5a
+.section smf5b
+.section smf6a
+.section smf6b
+.section smf7a
+.section smf7b
+.section smf8a
+.section smf8b
+.section smf9a
+.section smf9b
+.section smf0a
+.section smf0b
+.section smgaa
+.section smgab
+.section smgba
+.section smgbb
+.section smgca
+.section smgcb
+.section smgda
+.section smgdb
+.section smgea
+.section smgeb
+.section smgfa
+.section smgfb
+.section smgga
+.section smggb
+.section smgha
+.section smghb
+.section smgia
+.section smgib
+.section smgja
+.section smgjb
+.section smgka
+.section smgkb
+.section smgla
+.section smglb
+.section smgma
+.section smgmb
+.section smgna
+.section smgnb
+.section smgoa
+.section smgob
+.section smgpa
+.section smgpb
+.section smgqa
+.section smgqb
+.section smgra
+.section smgrb
+.section smgsa
+.section smgsb
+.section smgta
+.section smgtb
+.section smgua
+.section smgub
+.section smgva
+.section smgvb
+.section smgwa
+.section smgwb
+.section smgxa
+.section smgxb
+.section smgya
+.section smgyb
+.section smgza
+.section smgzb
+.section smg1a
+.section smg1b
+.section smg2a
+.section smg2b
+.section smg3a
+.section smg3b
+.section smg4a
+.section smg4b
+.section smg5a
+.section smg5b
+.section smg6a
+.section smg6b
+.section smg7a
+.section smg7b
+.section smg8a
+.section smg8b
+.section smg9a
+.section smg9b
+.section smg0a
+.section smg0b
+.section smhaa
+.section smhab
+.section smhba
+.section smhbb
+.section smhca
+.section smhcb
+.section smhda
+.section smhdb
+.section smhea
+.section smheb
+.section smhfa
+.section smhfb
+.section smhga
+.section smhgb
+.section smhha
+.section smhhb
+.section smhia
+.section smhib
+.section smhja
+.section smhjb
+.section smhka
+.section smhkb
+.section smhla
+.section smhlb
+.section smhma
+.section smhmb
+.section smhna
+.section smhnb
+.section smhoa
+.section smhob
+.section smhpa
+.section smhpb
+.section smhqa
+.section smhqb
+.section smhra
+.section smhrb
+.section smhsa
+.section smhsb
+.section smhta
+.section smhtb
+.section smhua
+.section smhub
+.section smhva
+.section smhvb
+.section smhwa
+.section smhwb
+.section smhxa
+.section smhxb
+.section smhya
+.section smhyb
+.section smhza
+.section smhzb
+.section smh1a
+.section smh1b
+.section smh2a
+.section smh2b
+.section smh3a
+.section smh3b
+.section smh4a
+.section smh4b
+.section smh5a
+.section smh5b
+.section smh6a
+.section smh6b
+.section smh7a
+.section smh7b
+.section smh8a
+.section smh8b
+.section smh9a
+.section smh9b
+.section smh0a
+.section smh0b
+.section smiaa
+.section smiab
+.section smiba
+.section smibb
+.section smica
+.section smicb
+.section smida
+.section smidb
+.section smiea
+.section smieb
+.section smifa
+.section smifb
+.section smiga
+.section smigb
+.section smiha
+.section smihb
+.section smiia
+.section smiib
+.section smija
+.section smijb
+.section smika
+.section smikb
+.section smila
+.section smilb
+.section smima
+.section smimb
+.section smina
+.section sminb
+.section smioa
+.section smiob
+.section smipa
+.section smipb
+.section smiqa
+.section smiqb
+.section smira
+.section smirb
+.section smisa
+.section smisb
+.section smita
+.section smitb
+.section smiua
+.section smiub
+.section smiva
+.section smivb
+.section smiwa
+.section smiwb
+.section smixa
+.section smixb
+.section smiya
+.section smiyb
+.section smiza
+.section smizb
+.section smi1a
+.section smi1b
+.section smi2a
+.section smi2b
+.section smi3a
+.section smi3b
+.section smi4a
+.section smi4b
+.section smi5a
+.section smi5b
+.section smi6a
+.section smi6b
+.section smi7a
+.section smi7b
+.section smi8a
+.section smi8b
+.section smi9a
+.section smi9b
+.section smi0a
+.section smi0b
+.section smjaa
+.section smjab
+.section smjba
+.section smjbb
+.section smjca
+.section smjcb
+.section smjda
+.section smjdb
+.section smjea
+.section smjeb
+.section smjfa
+.section smjfb
+.section smjga
+.section smjgb
+.section smjha
+.section smjhb
+.section smjia
+.section smjib
+.section smjja
+.section smjjb
+.section smjka
+.section smjkb
+.section smjla
+.section smjlb
+.section smjma
+.section smjmb
+.section smjna
+.section smjnb
+.section smjoa
+.section smjob
+.section smjpa
+.section smjpb
+.section smjqa
+.section smjqb
+.section smjra
+.section smjrb
+.section smjsa
+.section smjsb
+.section smjta
+.section smjtb
+.section smjua
+.section smjub
+.section smjva
+.section smjvb
+.section smjwa
+.section smjwb
+.section smjxa
+.section smjxb
+.section smjya
+.section smjyb
+.section smjza
+.section smjzb
+.section smj1a
+.section smj1b
+.section smj2a
+.section smj2b
+.section smj3a
+.section smj3b
+.section smj4a
+.section smj4b
+.section smj5a
+.section smj5b
+.section smj6a
+.section smj6b
+.section smj7a
+.section smj7b
+.section smj8a
+.section smj8b
+.section smj9a
+.section smj9b
+.section smj0a
+.section smj0b
+.section smkaa
+.section smkab
+.section smkba
+.section smkbb
+.section smkca
+.section smkcb
+.section smkda
+.section smkdb
+.section smkea
+.section smkeb
+.section smkfa
+.section smkfb
+.section smkga
+.section smkgb
+.section smkha
+.section smkhb
+.section smkia
+.section smkib
+.section smkja
+.section smkjb
+.section smkka
+.section smkkb
+.section smkla
+.section smklb
+.section smkma
+.section smkmb
+.section smkna
+.section smknb
+.section smkoa
+.section smkob
+.section smkpa
+.section smkpb
+.section smkqa
+.section smkqb
+.section smkra
+.section smkrb
+.section smksa
+.section smksb
+.section smkta
+.section smktb
+.section smkua
+.section smkub
+.section smkva
+.section smkvb
+.section smkwa
+.section smkwb
+.section smkxa
+.section smkxb
+.section smkya
+.section smkyb
+.section smkza
+.section smkzb
+.section smk1a
+.section smk1b
+.section smk2a
+.section smk2b
+.section smk3a
+.section smk3b
+.section smk4a
+.section smk4b
+.section smk5a
+.section smk5b
+.section smk6a
+.section smk6b
+.section smk7a
+.section smk7b
+.section smk8a
+.section smk8b
+.section smk9a
+.section smk9b
+.section smk0a
+.section smk0b
+.section smlaa
+.section smlab
+.section smlba
+.section smlbb
+.section smlca
+.section smlcb
+.section smlda
+.section smldb
+.section smlea
+.section smleb
+.section smlfa
+.section smlfb
+.section smlga
+.section smlgb
+.section smlha
+.section smlhb
+.section smlia
+.section smlib
+.section smlja
+.section smljb
+.section smlka
+.section smlkb
+.section smlla
+.section smllb
+.section smlma
+.section smlmb
+.section smlna
+.section smlnb
+.section smloa
+.section smlob
+.section smlpa
+.section smlpb
+.section smlqa
+.section smlqb
+.section smlra
+.section smlrb
+.section smlsa
+.section smlsb
+.section smlta
+.section smltb
+.section smlua
+.section smlub
+.section smlva
+.section smlvb
+.section smlwa
+.section smlwb
+.section smlxa
+.section smlxb
+.section smlya
+.section smlyb
+.section smlza
+.section smlzb
+.section sml1a
+.section sml1b
+.section sml2a
+.section sml2b
+.section sml3a
+.section sml3b
+.section sml4a
+.section sml4b
+.section sml5a
+.section sml5b
+.section sml6a
+.section sml6b
+.section sml7a
+.section sml7b
+.section sml8a
+.section sml8b
+.section sml9a
+.section sml9b
+.section sml0a
+.section sml0b
+.section smmaa
+.section smmab
+.section smmba
+.section smmbb
+.section smmca
+.section smmcb
+.section smmda
+.section smmdb
+.section smmea
+.section smmeb
+.section smmfa
+.section smmfb
+.section smmga
+.section smmgb
+.section smmha
+.section smmhb
+.section smmia
+.section smmib
+.section smmja
+.section smmjb
+.section smmka
+.section smmkb
+.section smmla
+.section smmlb
+.section smmma
+.section smmmb
+.section smmna
+.section smmnb
+.section smmoa
+.section smmob
+.section smmpa
+.section smmpb
+.section smmqa
+.section smmqb
+.section smmra
+.section smmrb
+.section smmsa
+.section smmsb
+.section smmta
+.section smmtb
+.section smmua
+.section smmub
+.section smmva
+.section smmvb
+.section smmwa
+.section smmwb
+.section smmxa
+.section smmxb
+.section smmya
+.section smmyb
+.section smmza
+.section smmzb
+.section smm1a
+.section smm1b
+.section smm2a
+.section smm2b
+.section smm3a
+.section smm3b
+.section smm4a
+.section smm4b
+.section smm5a
+.section smm5b
+.section smm6a
+.section smm6b
+.section smm7a
+.section smm7b
+.section smm8a
+.section smm8b
+.section smm9a
+.section smm9b
+.section smm0a
+.section smm0b
+.section smnaa
+.section smnab
+.section smnba
+.section smnbb
+.section smnca
+.section smncb
+.section smnda
+.section smndb
+.section smnea
+.section smneb
+.section smnfa
+.section smnfb
+.section smnga
+.section smngb
+.section smnha
+.section smnhb
+.section smnia
+.section smnib
+.section smnja
+.section smnjb
+.section smnka
+.section smnkb
+.section smnla
+.section smnlb
+.section smnma
+.section smnmb
+.section smnna
+.section smnnb
+.section smnoa
+.section smnob
+.section smnpa
+.section smnpb
+.section smnqa
+.section smnqb
+.section smnra
+.section smnrb
+.section smnsa
+.section smnsb
+.section smnta
+.section smntb
+.section smnua
+.section smnub
+.section smnva
+.section smnvb
+.section smnwa
+.section smnwb
+.section smnxa
+.section smnxb
+.section smnya
+.section smnyb
+.section smnza
+.section smnzb
+.section smn1a
+.section smn1b
+.section smn2a
+.section smn2b
+.section smn3a
+.section smn3b
+.section smn4a
+.section smn4b
+.section smn5a
+.section smn5b
+.section smn6a
+.section smn6b
+.section smn7a
+.section smn7b
+.section smn8a
+.section smn8b
+.section smn9a
+.section smn9b
+.section smn0a
+.section smn0b
+.section smoaa
+.section smoab
+.section smoba
+.section smobb
+.section smoca
+.section smocb
+.section smoda
+.section smodb
+.section smoea
+.section smoeb
+.section smofa
+.section smofb
+.section smoga
+.section smogb
+.section smoha
+.section smohb
+.section smoia
+.section smoib
+.section smoja
+.section smojb
+.section smoka
+.section smokb
+.section smola
+.section smolb
+.section smoma
+.section smomb
+.section smona
+.section smonb
+.section smooa
+.section smoob
+.section smopa
+.section smopb
+.section smoqa
+.section smoqb
+.section smora
+.section smorb
+.section smosa
+.section smosb
+.section smota
+.section smotb
+.section smoua
+.section smoub
+.section smova
+.section smovb
+.section smowa
+.section smowb
+.section smoxa
+.section smoxb
+.section smoya
+.section smoyb
+.section smoza
+.section smozb
+.section smo1a
+.section smo1b
+.section smo2a
+.section smo2b
+.section smo3a
+.section smo3b
+.section smo4a
+.section smo4b
+.section smo5a
+.section smo5b
+.section smo6a
+.section smo6b
+.section smo7a
+.section smo7b
+.section smo8a
+.section smo8b
+.section smo9a
+.section smo9b
+.section smo0a
+.section smo0b
+.section smpaa
+.section smpab
+.section smpba
+.section smpbb
+.section smpca
+.section smpcb
+.section smpda
+.section smpdb
+.section smpea
+.section smpeb
+.section smpfa
+.section smpfb
+.section smpga
+.section smpgb
+.section smpha
+.section smphb
+.section smpia
+.section smpib
+.section smpja
+.section smpjb
+.section smpka
+.section smpkb
+.section smpla
+.section smplb
+.section smpma
+.section smpmb
+.section smpna
+.section smpnb
+.section smpoa
+.section smpob
+.section smppa
+.section smppb
+.section smpqa
+.section smpqb
+.section smpra
+.section smprb
+.section smpsa
+.section smpsb
+.section smpta
+.section smptb
+.section smpua
+.section smpub
+.section smpva
+.section smpvb
+.section smpwa
+.section smpwb
+.section smpxa
+.section smpxb
+.section smpya
+.section smpyb
+.section smpza
+.section smpzb
+.section smp1a
+.section smp1b
+.section smp2a
+.section smp2b
+.section smp3a
+.section smp3b
+.section smp4a
+.section smp4b
+.section smp5a
+.section smp5b
+.section smp6a
+.section smp6b
+.section smp7a
+.section smp7b
+.section smp8a
+.section smp8b
+.section smp9a
+.section smp9b
+.section smp0a
+.section smp0b
+.section smqaa
+.section smqab
+.section smqba
+.section smqbb
+.section smqca
+.section smqcb
+.section smqda
+.section smqdb
+.section smqea
+.section smqeb
+.section smqfa
+.section smqfb
+.section smqga
+.section smqgb
+.section smqha
+.section smqhb
+.section smqia
+.section smqib
+.section smqja
+.section smqjb
+.section smqka
+.section smqkb
+.section smqla
+.section smqlb
+.section smqma
+.section smqmb
+.section smqna
+.section smqnb
+.section smqoa
+.section smqob
+.section smqpa
+.section smqpb
+.section smqqa
+.section smqqb
+.section smqra
+.section smqrb
+.section smqsa
+.section smqsb
+.section smqta
+.section smqtb
+.section smqua
+.section smqub
+.section smqva
+.section smqvb
+.section smqwa
+.section smqwb
+.section smqxa
+.section smqxb
+.section smqya
+.section smqyb
+.section smqza
+.section smqzb
+.section smq1a
+.section smq1b
+.section smq2a
+.section smq2b
+.section smq3a
+.section smq3b
+.section smq4a
+.section smq4b
+.section smq5a
+.section smq5b
+.section smq6a
+.section smq6b
+.section smq7a
+.section smq7b
+.section smq8a
+.section smq8b
+.section smq9a
+.section smq9b
+.section smq0a
+.section smq0b
+.section smraa
+.section smrab
+.section smrba
+.section smrbb
+.section smrca
+.section smrcb
+.section smrda
+.section smrdb
+.section smrea
+.section smreb
+.section smrfa
+.section smrfb
+.section smrga
+.section smrgb
+.section smrha
+.section smrhb
+.section smria
+.section smrib
+.section smrja
+.section smrjb
+.section smrka
+.section smrkb
+.section smrla
+.section smrlb
+.section smrma
+.section smrmb
+.section smrna
+.section smrnb
+.section smroa
+.section smrob
+.section smrpa
+.section smrpb
+.section smrqa
+.section smrqb
+.section smrra
+.section smrrb
+.section smrsa
+.section smrsb
+.section smrta
+.section smrtb
+.section smrua
+.section smrub
+.section smrva
+.section smrvb
+.section smrwa
+.section smrwb
+.section smrxa
+.section smrxb
+.section smrya
+.section smryb
+.section smrza
+.section smrzb
+.section smr1a
+.section smr1b
+.section smr2a
+.section smr2b
+.section smr3a
+.section smr3b
+.section smr4a
+.section smr4b
+.section smr5a
+.section smr5b
+.section smr6a
+.section smr6b
+.section smr7a
+.section smr7b
+.section smr8a
+.section smr8b
+.section smr9a
+.section smr9b
+.section smr0a
+.section smr0b
+.section smsaa
+.section smsab
+.section smsba
+.section smsbb
+.section smsca
+.section smscb
+.section smsda
+.section smsdb
+.section smsea
+.section smseb
+.section smsfa
+.section smsfb
+.section smsga
+.section smsgb
+.section smsha
+.section smshb
+.section smsia
+.section smsib
+.section smsja
+.section smsjb
+.section smska
+.section smskb
+.section smsla
+.section smslb
+.section smsma
+.section smsmb
+.section smsna
+.section smsnb
+.section smsoa
+.section smsob
+.section smspa
+.section smspb
+.section smsqa
+.section smsqb
+.section smsra
+.section smsrb
+.section smssa
+.section smssb
+.section smsta
+.section smstb
+.section smsua
+.section smsub
+.section smsva
+.section smsvb
+.section smswa
+.section smswb
+.section smsxa
+.section smsxb
+.section smsya
+.section smsyb
+.section smsza
+.section smszb
+.section sms1a
+.section sms1b
+.section sms2a
+.section sms2b
+.section sms3a
+.section sms3b
+.section sms4a
+.section sms4b
+.section sms5a
+.section sms5b
+.section sms6a
+.section sms6b
+.section sms7a
+.section sms7b
+.section sms8a
+.section sms8b
+.section sms9a
+.section sms9b
+.section sms0a
+.section sms0b
+.section smtaa
+.section smtab
+.section smtba
+.section smtbb
+.section smtca
+.section smtcb
+.section smtda
+.section smtdb
+.section smtea
+.section smteb
+.section smtfa
+.section smtfb
+.section smtga
+.section smtgb
+.section smtha
+.section smthb
+.section smtia
+.section smtib
+.section smtja
+.section smtjb
+.section smtka
+.section smtkb
+.section smtla
+.section smtlb
+.section smtma
+.section smtmb
+.section smtna
+.section smtnb
+.section smtoa
+.section smtob
+.section smtpa
+.section smtpb
+.section smtqa
+.section smtqb
+.section smtra
+.section smtrb
+.section smtsa
+.section smtsb
+.section smtta
+.section smttb
+.section smtua
+.section smtub
+.section smtva
+.section smtvb
+.section smtwa
+.section smtwb
+.section smtxa
+.section smtxb
+.section smtya
+.section smtyb
+.section smtza
+.section smtzb
+.section smt1a
+.section smt1b
+.section smt2a
+.section smt2b
+.section smt3a
+.section smt3b
+.section smt4a
+.section smt4b
+.section smt5a
+.section smt5b
+.section smt6a
+.section smt6b
+.section smt7a
+.section smt7b
+.section smt8a
+.section smt8b
+.section smt9a
+.section smt9b
+.section smt0a
+.section smt0b
+.section smuaa
+.section smuab
+.section smuba
+.section smubb
+.section smuca
+.section smucb
+.section smuda
+.section smudb
+.section smuea
+.section smueb
+.section smufa
+.section smufb
+.section smuga
+.section smugb
+.section smuha
+.section smuhb
+.section smuia
+.section smuib
+.section smuja
+.section smujb
+.section smuka
+.section smukb
+.section smula
+.section smulb
+.section smuma
+.section smumb
+.section smuna
+.section smunb
+.section smuoa
+.section smuob
+.section smupa
+.section smupb
+.section smuqa
+.section smuqb
+.section smura
+.section smurb
+.section smusa
+.section smusb
+.section smuta
+.section smutb
+.section smuua
+.section smuub
+.section smuva
+.section smuvb
+.section smuwa
+.section smuwb
+.section smuxa
+.section smuxb
+.section smuya
+.section smuyb
+.section smuza
+.section smuzb
+.section smu1a
+.section smu1b
+.section smu2a
+.section smu2b
+.section smu3a
+.section smu3b
+.section smu4a
+.section smu4b
+.section smu5a
+.section smu5b
+.section smu6a
+.section smu6b
+.section smu7a
+.section smu7b
+.section smu8a
+.section smu8b
+.section smu9a
+.section smu9b
+.section smu0a
+.section smu0b
+.section smvaa
+.section smvab
+.section smvba
+.section smvbb
+.section smvca
+.section smvcb
+.section smvda
+.section smvdb
+.section smvea
+.section smveb
+.section smvfa
+.section smvfb
+.section smvga
+.section smvgb
+.section smvha
+.section smvhb
+.section smvia
+.section smvib
+.section smvja
+.section smvjb
+.section smvka
+.section smvkb
+.section smvla
+.section smvlb
+.section smvma
+.section smvmb
+.section smvna
+.section smvnb
+.section smvoa
+.section smvob
+.section smvpa
+.section smvpb
+.section smvqa
+.section smvqb
+.section smvra
+.section smvrb
+.section smvsa
+.section smvsb
+.section smvta
+.section smvtb
+.section smvua
+.section smvub
+.section smvva
+.section smvvb
+.section smvwa
+.section smvwb
+.section smvxa
+.section smvxb
+.section smvya
+.section smvyb
+.section smvza
+.section smvzb
+.section smv1a
+.section smv1b
+.section smv2a
+.section smv2b
+.section smv3a
+.section smv3b
+.section smv4a
+.section smv4b
+.section smv5a
+.section smv5b
+.section smv6a
+.section smv6b
+.section smv7a
+.section smv7b
+.section smv8a
+.section smv8b
+.section smv9a
+.section smv9b
+.section smv0a
+.section smv0b
+.section smwaa
+.section smwab
+.section smwba
+.section smwbb
+.section smwca
+.section smwcb
+.section smwda
+.section smwdb
+.section smwea
+.section smweb
+.section smwfa
+.section smwfb
+.section smwga
+.section smwgb
+.section smwha
+.section smwhb
+.section smwia
+.section smwib
+.section smwja
+.section smwjb
+.section smwka
+.section smwkb
+.section smwla
+.section smwlb
+.section smwma
+.section smwmb
+.section smwna
+.section smwnb
+.section smwoa
+.section smwob
+.section smwpa
+.section smwpb
+.section smwqa
+.section smwqb
+.section smwra
+.section smwrb
+.section smwsa
+.section smwsb
+.section smwta
+.section smwtb
+.section smwua
+.section smwub
+.section smwva
+.section smwvb
+.section smwwa
+.section smwwb
+.section smwxa
+.section smwxb
+.section smwya
+.section smwyb
+.section smwza
+.section smwzb
+.section smw1a
+.section smw1b
+.section smw2a
+.section smw2b
+.section smw3a
+.section smw3b
+.section smw4a
+.section smw4b
+.section smw5a
+.section smw5b
+.section smw6a
+.section smw6b
+.section smw7a
+.section smw7b
+.section smw8a
+.section smw8b
+.section smw9a
+.section smw9b
+.section smw0a
+.section smw0b
+.section smxaa
+.section smxab
+.section smxba
+.section smxbb
+.section smxca
+.section smxcb
+.section smxda
+.section smxdb
+.section smxea
+.section smxeb
+.section smxfa
+.section smxfb
+.section smxga
+.section smxgb
+.section smxha
+.section smxhb
+.section smxia
+.section smxib
+.section smxja
+.section smxjb
+.section smxka
+.section smxkb
+.section smxla
+.section smxlb
+.section smxma
+.section smxmb
+.section smxna
+.section smxnb
+.section smxoa
+.section smxob
+.section smxpa
+.section smxpb
+.section smxqa
+.section smxqb
+.section smxra
+.section smxrb
+.section smxsa
+.section smxsb
+.section smxta
+.section smxtb
+.section smxua
+.section smxub
+.section smxva
+.section smxvb
+.section smxwa
+.section smxwb
+.section smxxa
+.section smxxb
+.section smxya
+.section smxyb
+.section smxza
+.section smxzb
+.section smx1a
+.section smx1b
+.section smx2a
+.section smx2b
+.section smx3a
+.section smx3b
+.section smx4a
+.section smx4b
+.section smx5a
+.section smx5b
+.section smx6a
+.section smx6b
+.section smx7a
+.section smx7b
+.section smx8a
+.section smx8b
+.section smx9a
+.section smx9b
+.section smx0a
+.section smx0b
+.section smyaa
+.section smyab
+.section smyba
+.section smybb
+.section smyca
+.section smycb
+.section smyda
+.section smydb
+.section smyea
+.section smyeb
+.section smyfa
+.section smyfb
+.section smyga
+.section smygb
+.section smyha
+.section smyhb
+.section smyia
+.section smyib
+.section smyja
+.section smyjb
+.section smyka
+.section smykb
+.section smyla
+.section smylb
+.section smyma
+.section smymb
+.section smyna
+.section smynb
+.section smyoa
+.section smyob
+.section smypa
+.section smypb
+.section smyqa
+.section smyqb
+.section smyra
+.section smyrb
+.section smysa
+.section smysb
+.section smyta
+.section smytb
+.section smyua
+.section smyub
+.section smyva
+.section smyvb
+.section smywa
+.section smywb
+.section smyxa
+.section smyxb
+.section smyya
+.section smyyb
+.section smyza
+.section smyzb
+.section smy1a
+.section smy1b
+.section smy2a
+.section smy2b
+.section smy3a
+.section smy3b
+.section smy4a
+.section smy4b
+.section smy5a
+.section smy5b
+.section smy6a
+.section smy6b
+.section smy7a
+.section smy7b
+.section smy8a
+.section smy8b
+.section smy9a
+.section smy9b
+.section smy0a
+.section smy0b
+.section smzaa
+.section smzab
+.section smzba
+.section smzbb
+.section smzca
+.section smzcb
+.section smzda
+.section smzdb
+.section smzea
+.section smzeb
+.section smzfa
+.section smzfb
+.section smzga
+.section smzgb
+.section smzha
+.section smzhb
+.section smzia
+.section smzib
+.section smzja
+.section smzjb
+.section smzka
+.section smzkb
+.section smzla
+.section smzlb
+.section smzma
+.section smzmb
+.section smzna
+.section smznb
+.section smzoa
+.section smzob
+.section smzpa
+.section smzpb
+.section smzqa
+.section smzqb
+.section smzra
+.section smzrb
+.section smzsa
+.section smzsb
+.section smzta
+.section smztb
+.section smzua
+.section smzub
+.section smzva
+.section smzvb
+.section smzwa
+.section smzwb
+.section smzxa
+.section smzxb
+.section smzya
+.section smzyb
+.section smzza
+.section smzzb
+.section smz1a
+.section smz1b
+.section smz2a
+.section smz2b
+.section smz3a
+.section smz3b
+.section smz4a
+.section smz4b
+.section smz5a
+.section smz5b
+.section smz6a
+.section smz6b
+.section smz7a
+.section smz7b
+.section smz8a
+.section smz8b
+.section smz9a
+.section smz9b
+.section smz0a
+.section smz0b
+.section sm1aa
+.section sm1ab
+.section sm1ba
+.section sm1bb
+.section sm1ca
+.section sm1cb
+.section sm1da
+.section sm1db
+.section sm1ea
+.section sm1eb
+.section sm1fa
+.section sm1fb
+.section sm1ga
+.section sm1gb
+.section sm1ha
+.section sm1hb
+.section sm1ia
+.section sm1ib
+.section sm1ja
+.section sm1jb
+.section sm1ka
+.section sm1kb
+.section sm1la
+.section sm1lb
+.section sm1ma
+.section sm1mb
+.section sm1na
+.section sm1nb
+.section sm1oa
+.section sm1ob
+.section sm1pa
+.section sm1pb
+.section sm1qa
+.section sm1qb
+.section sm1ra
+.section sm1rb
+.section sm1sa
+.section sm1sb
+.section sm1ta
+.section sm1tb
+.section sm1ua
+.section sm1ub
+.section sm1va
+.section sm1vb
+.section sm1wa
+.section sm1wb
+.section sm1xa
+.section sm1xb
+.section sm1ya
+.section sm1yb
+.section sm1za
+.section sm1zb
+.section sm11a
+.section sm11b
+.section sm12a
+.section sm12b
+.section sm13a
+.section sm13b
+.section sm14a
+.section sm14b
+.section sm15a
+.section sm15b
+.section sm16a
+.section sm16b
+.section sm17a
+.section sm17b
+.section sm18a
+.section sm18b
+.section sm19a
+.section sm19b
+.section sm10a
+.section sm10b
+.section sm2aa
+.section sm2ab
+.section sm2ba
+.section sm2bb
+.section sm2ca
+.section sm2cb
+.section sm2da
+.section sm2db
+.section sm2ea
+.section sm2eb
+.section sm2fa
+.section sm2fb
+.section sm2ga
+.section sm2gb
+.section sm2ha
+.section sm2hb
+.section sm2ia
+.section sm2ib
+.section sm2ja
+.section sm2jb
+.section sm2ka
+.section sm2kb
+.section sm2la
+.section sm2lb
+.section sm2ma
+.section sm2mb
+.section sm2na
+.section sm2nb
+.section sm2oa
+.section sm2ob
+.section sm2pa
+.section sm2pb
+.section sm2qa
+.section sm2qb
+.section sm2ra
+.section sm2rb
+.section sm2sa
+.section sm2sb
+.section sm2ta
+.section sm2tb
+.section sm2ua
+.section sm2ub
+.section sm2va
+.section sm2vb
+.section sm2wa
+.section sm2wb
+.section sm2xa
+.section sm2xb
+.section sm2ya
+.section sm2yb
+.section sm2za
+.section sm2zb
+.section sm21a
+.section sm21b
+.section sm22a
+.section sm22b
+.section sm23a
+.section sm23b
+.section sm24a
+.section sm24b
+.section sm25a
+.section sm25b
+.section sm26a
+.section sm26b
+.section sm27a
+.section sm27b
+.section sm28a
+.section sm28b
+.section sm29a
+.section sm29b
+.section sm20a
+.section sm20b
+.section sm3aa
+.section sm3ab
+.section sm3ba
+.section sm3bb
+.section sm3ca
+.section sm3cb
+.section sm3da
+.section sm3db
+.section sm3ea
+.section sm3eb
+.section sm3fa
+.section sm3fb
+.section sm3ga
+.section sm3gb
+.section sm3ha
+.section sm3hb
+.section sm3ia
+.section sm3ib
+.section sm3ja
+.section sm3jb
+.section sm3ka
+.section sm3kb
+.section sm3la
+.section sm3lb
+.section sm3ma
+.section sm3mb
+.section sm3na
+.section sm3nb
+.section sm3oa
+.section sm3ob
+.section sm3pa
+.section sm3pb
+.section sm3qa
+.section sm3qb
+.section sm3ra
+.section sm3rb
+.section sm3sa
+.section sm3sb
+.section sm3ta
+.section sm3tb
+.section sm3ua
+.section sm3ub
+.section sm3va
+.section sm3vb
+.section sm3wa
+.section sm3wb
+.section sm3xa
+.section sm3xb
+.section sm3ya
+.section sm3yb
+.section sm3za
+.section sm3zb
+.section sm31a
+.section sm31b
+.section sm32a
+.section sm32b
+.section sm33a
+.section sm33b
+.section sm34a
+.section sm34b
+.section sm35a
+.section sm35b
+.section sm36a
+.section sm36b
+.section sm37a
+.section sm37b
+.section sm38a
+.section sm38b
+.section sm39a
+.section sm39b
+.section sm30a
+.section sm30b
+.section sm4aa
+.section sm4ab
+.section sm4ba
+.section sm4bb
+.section sm4ca
+.section sm4cb
+.section sm4da
+.section sm4db
+.section sm4ea
+.section sm4eb
+.section sm4fa
+.section sm4fb
+.section sm4ga
+.section sm4gb
+.section sm4ha
+.section sm4hb
+.section sm4ia
+.section sm4ib
+.section sm4ja
+.section sm4jb
+.section sm4ka
+.section sm4kb
+.section sm4la
+.section sm4lb
+.section sm4ma
+.section sm4mb
+.section sm4na
+.section sm4nb
+.section sm4oa
+.section sm4ob
+.section sm4pa
+.section sm4pb
+.section sm4qa
+.section sm4qb
+.section sm4ra
+.section sm4rb
+.section sm4sa
+.section sm4sb
+.section sm4ta
+.section sm4tb
+.section sm4ua
+.section sm4ub
+.section sm4va
+.section sm4vb
+.section sm4wa
+.section sm4wb
+.section sm4xa
+.section sm4xb
+.section sm4ya
+.section sm4yb
+.section sm4za
+.section sm4zb
+.section sm41a
+.section sm41b
+.section sm42a
+.section sm42b
+.section sm43a
+.section sm43b
+.section sm44a
+.section sm44b
+.section sm45a
+.section sm45b
+.section sm46a
+.section sm46b
+.section sm47a
+.section sm47b
+.section sm48a
+.section sm48b
+.section sm49a
+.section sm49b
+.section sm40a
+.section sm40b
+.section sm5aa
+.section sm5ab
+.section sm5ba
+.section sm5bb
+.section sm5ca
+.section sm5cb
+.section sm5da
+.section sm5db
+.section sm5ea
+.section sm5eb
+.section sm5fa
+.section sm5fb
+.section sm5ga
+.section sm5gb
+.section sm5ha
+.section sm5hb
+.section sm5ia
+.section sm5ib
+.section sm5ja
+.section sm5jb
+.section sm5ka
+.section sm5kb
+.section sm5la
+.section sm5lb
+.section sm5ma
+.section sm5mb
+.section sm5na
+.section sm5nb
+.section sm5oa
+.section sm5ob
+.section sm5pa
+.section sm5pb
+.section sm5qa
+.section sm5qb
+.section sm5ra
+.section sm5rb
+.section sm5sa
+.section sm5sb
+.section sm5ta
+.section sm5tb
+.section sm5ua
+.section sm5ub
+.section sm5va
+.section sm5vb
+.section sm5wa
+.section sm5wb
+.section sm5xa
+.section sm5xb
+.section sm5ya
+.section sm5yb
+.section sm5za
+.section sm5zb
+.section sm51a
+.section sm51b
+.section sm52a
+.section sm52b
+.section sm53a
+.section sm53b
+.section sm54a
+.section sm54b
+.section sm55a
+.section sm55b
+.section sm56a
+.section sm56b
+.section sm57a
+.section sm57b
+.section sm58a
+.section sm58b
+.section sm59a
+.section sm59b
+.section sm50a
+.section sm50b
+.section sm6aa
+.section sm6ab
+.section sm6ba
+.section sm6bb
+.section sm6ca
+.section sm6cb
+.section sm6da
+.section sm6db
+.section sm6ea
+.section sm6eb
+.section sm6fa
+.section sm6fb
+.section sm6ga
+.section sm6gb
+.section sm6ha
+.section sm6hb
+.section sm6ia
+.section sm6ib
+.section sm6ja
+.section sm6jb
+.section sm6ka
+.section sm6kb
+.section sm6la
+.section sm6lb
+.section sm6ma
+.section sm6mb
+.section sm6na
+.section sm6nb
+.section sm6oa
+.section sm6ob
+.section sm6pa
+.section sm6pb
+.section sm6qa
+.section sm6qb
+.section sm6ra
+.section sm6rb
+.section sm6sa
+.section sm6sb
+.section sm6ta
+.section sm6tb
+.section sm6ua
+.section sm6ub
+.section sm6va
+.section sm6vb
+.section sm6wa
+.section sm6wb
+.section sm6xa
+.section sm6xb
+.section sm6ya
+.section sm6yb
+.section sm6za
+.section sm6zb
+.section sm61a
+.section sm61b
+.section sm62a
+.section sm62b
+.section sm63a
+.section sm63b
+.section sm64a
+.section sm64b
+.section sm65a
+.section sm65b
+.section sm66a
+.section sm66b
+.section sm67a
+.section sm67b
+.section sm68a
+.section sm68b
+.section sm69a
+.section sm69b
+.section sm60a
+.section sm60b
+.section sm7aa
+.section sm7ab
+.section sm7ba
+.section sm7bb
+.section sm7ca
+.section sm7cb
+.section sm7da
+.section sm7db
+.section sm7ea
+.section sm7eb
+.section sm7fa
+.section sm7fb
+.section sm7ga
+.section sm7gb
+.section sm7ha
+.section sm7hb
+.section sm7ia
+.section sm7ib
+.section sm7ja
+.section sm7jb
+.section sm7ka
+.section sm7kb
+.section sm7la
+.section sm7lb
+.section sm7ma
+.section sm7mb
+.section sm7na
+.section sm7nb
+.section sm7oa
+.section sm7ob
+.section sm7pa
+.section sm7pb
+.section sm7qa
+.section sm7qb
+.section sm7ra
+.section sm7rb
+.section sm7sa
+.section sm7sb
+.section sm7ta
+.section sm7tb
+.section sm7ua
+.section sm7ub
+.section sm7va
+.section sm7vb
+.section sm7wa
+.section sm7wb
+.section sm7xa
+.section sm7xb
+.section sm7ya
+.section sm7yb
+.section sm7za
+.section sm7zb
+.section sm71a
+.section sm71b
+.section sm72a
+.section sm72b
+.section sm73a
+.section sm73b
+.section sm74a
+.section sm74b
+.section sm75a
+.section sm75b
+.section sm76a
+.section sm76b
+.section sm77a
+.section sm77b
+.section sm78a
+.section sm78b
+.section sm79a
+.section sm79b
+.section sm70a
+.section sm70b
+.section sm8aa
+.section sm8ab
+.section sm8ba
+.section sm8bb
+.section sm8ca
+.section sm8cb
+.section sm8da
+.section sm8db
+.section sm8ea
+.section sm8eb
+.section sm8fa
+.section sm8fb
+.section sm8ga
+.section sm8gb
+.section sm8ha
+.section sm8hb
+.section sm8ia
+.section sm8ib
+.section sm8ja
+.section sm8jb
+.section sm8ka
+.section sm8kb
+.section sm8la
+.section sm8lb
+.section sm8ma
+.section sm8mb
+.section sm8na
+.section sm8nb
+.section sm8oa
+.section sm8ob
+.section sm8pa
+.section sm8pb
+.section sm8qa
+.section sm8qb
+.section sm8ra
+.section sm8rb
+.section sm8sa
+.section sm8sb
+.section sm8ta
+.section sm8tb
+.section sm8ua
+.section sm8ub
+.section sm8va
+.section sm8vb
+.section sm8wa
+.section sm8wb
+.section sm8xa
+.section sm8xb
+.section sm8ya
+.section sm8yb
+.section sm8za
+.section sm8zb
+.section sm81a
+.section sm81b
+.section sm82a
+.section sm82b
+.section sm83a
+.section sm83b
+.section sm84a
+.section sm84b
+.section sm85a
+.section sm85b
+.section sm86a
+.section sm86b
+.section sm87a
+.section sm87b
+.section sm88a
+.section sm88b
+.section sm89a
+.section sm89b
+.section sm80a
+.section sm80b
+.section sm9aa
+.section sm9ab
+.section sm9ba
+.section sm9bb
+.section sm9ca
+.section sm9cb
+.section sm9da
+.section sm9db
+.section sm9ea
+.section sm9eb
+.section sm9fa
+.section sm9fb
+.section sm9ga
+.section sm9gb
+.section sm9ha
+.section sm9hb
+.section sm9ia
+.section sm9ib
+.section sm9ja
+.section sm9jb
+.section sm9ka
+.section sm9kb
+.section sm9la
+.section sm9lb
+.section sm9ma
+.section sm9mb
+.section sm9na
+.section sm9nb
+.section sm9oa
+.section sm9ob
+.section sm9pa
+.section sm9pb
+.section sm9qa
+.section sm9qb
+.section sm9ra
+.section sm9rb
+.section sm9sa
+.section sm9sb
+.section sm9ta
+.section sm9tb
+.section sm9ua
+.section sm9ub
+.section sm9va
+.section sm9vb
+.section sm9wa
+.section sm9wb
+.section sm9xa
+.section sm9xb
+.section sm9ya
+.section sm9yb
+.section sm9za
+.section sm9zb
+.section sm91a
+.section sm91b
+.section sm92a
+.section sm92b
+.section sm93a
+.section sm93b
+.section sm94a
+.section sm94b
+.section sm95a
+.section sm95b
+.section sm96a
+.section sm96b
+.section sm97a
+.section sm97b
+.section sm98a
+.section sm98b
+.section sm99a
+.section sm99b
+.section sm90a
+.section sm90b
+.section sm0aa
+.section sm0ab
+.section sm0ba
+.section sm0bb
+.section sm0ca
+.section sm0cb
+.section sm0da
+.section sm0db
+.section sm0ea
+.section sm0eb
+.section sm0fa
+.section sm0fb
+.section sm0ga
+.section sm0gb
+.section sm0ha
+.section sm0hb
+.section sm0ia
+.section sm0ib
+.section sm0ja
+.section sm0jb
+.section sm0ka
+.section sm0kb
+.section sm0la
+.section sm0lb
+.section sm0ma
+.section sm0mb
+.section sm0na
+.section sm0nb
+.section sm0oa
+.section sm0ob
+.section sm0pa
+.section sm0pb
+.section sm0qa
+.section sm0qb
+.section sm0ra
+.section sm0rb
+.section sm0sa
+.section sm0sb
+.section sm0ta
+.section sm0tb
+.section sm0ua
+.section sm0ub
+.section sm0va
+.section sm0vb
+.section sm0wa
+.section sm0wb
+.section sm0xa
+.section sm0xb
+.section sm0ya
+.section sm0yb
+.section sm0za
+.section sm0zb
+.section sm01a
+.section sm01b
+.section sm02a
+.section sm02b
+.section sm03a
+.section sm03b
+.section sm04a
+.section sm04b
+.section sm05a
+.section sm05b
+.section sm06a
+.section sm06b
+.section sm07a
+.section sm07b
+.section sm08a
+.section sm08b
+.section sm09a
+.section sm09b
+.section sm00a
+.section sm00b
+.section snaaa
+.section snaab
+.section snaba
+.section snabb
+.section snaca
+.section snacb
+.section snada
+.section snadb
+.section snaea
+.section snaeb
+.section snafa
+.section snafb
+.section snaga
+.section snagb
+.section snaha
+.section snahb
+.section snaia
+.section snaib
+.section snaja
+.section snajb
+.section snaka
+.section snakb
+.section snala
+.section snalb
+.section snama
+.section snamb
+.section snana
+.section snanb
+.section snaoa
+.section snaob
+.section snapa
+.section snapb
+.section snaqa
+.section snaqb
+.section snara
+.section snarb
+.section snasa
+.section snasb
+.section snata
+.section snatb
+.section snaua
+.section snaub
+.section snava
+.section snavb
+.section snawa
+.section snawb
+.section snaxa
+.section snaxb
+.section snaya
+.section snayb
+.section snaza
+.section snazb
+.section sna1a
+.section sna1b
+.section sna2a
+.section sna2b
+.section sna3a
+.section sna3b
+.section sna4a
+.section sna4b
+.section sna5a
+.section sna5b
+.section sna6a
+.section sna6b
+.section sna7a
+.section sna7b
+.section sna8a
+.section sna8b
+.section sna9a
+.section sna9b
+.section sna0a
+.section sna0b
+.section snbaa
+.section snbab
+.section snbba
+.section snbbb
+.section snbca
+.section snbcb
+.section snbda
+.section snbdb
+.section snbea
+.section snbeb
+.section snbfa
+.section snbfb
+.section snbga
+.section snbgb
+.section snbha
+.section snbhb
+.section snbia
+.section snbib
+.section snbja
+.section snbjb
+.section snbka
+.section snbkb
+.section snbla
+.section snblb
+.section snbma
+.section snbmb
+.section snbna
+.section snbnb
+.section snboa
+.section snbob
+.section snbpa
+.section snbpb
+.section snbqa
+.section snbqb
+.section snbra
+.section snbrb
+.section snbsa
+.section snbsb
+.section snbta
+.section snbtb
+.section snbua
+.section snbub
+.section snbva
+.section snbvb
+.section snbwa
+.section snbwb
+.section snbxa
+.section snbxb
+.section snbya
+.section snbyb
+.section snbza
+.section snbzb
+.section snb1a
+.section snb1b
+.section snb2a
+.section snb2b
+.section snb3a
+.section snb3b
+.section snb4a
+.section snb4b
+.section snb5a
+.section snb5b
+.section snb6a
+.section snb6b
+.section snb7a
+.section snb7b
+.section snb8a
+.section snb8b
+.section snb9a
+.section snb9b
+.section snb0a
+.section snb0b
+.section sncaa
+.section sncab
+.section sncba
+.section sncbb
+.section sncca
+.section snccb
+.section sncda
+.section sncdb
+.section sncea
+.section snceb
+.section sncfa
+.section sncfb
+.section sncga
+.section sncgb
+.section sncha
+.section snchb
+.section sncia
+.section sncib
+.section sncja
+.section sncjb
+.section sncka
+.section snckb
+.section sncla
+.section snclb
+.section sncma
+.section sncmb
+.section sncna
+.section sncnb
+.section sncoa
+.section sncob
+.section sncpa
+.section sncpb
+.section sncqa
+.section sncqb
+.section sncra
+.section sncrb
+.section sncsa
+.section sncsb
+.section sncta
+.section snctb
+.section sncua
+.section sncub
+.section sncva
+.section sncvb
+.section sncwa
+.section sncwb
+.section sncxa
+.section sncxb
+.section sncya
+.section sncyb
+.section sncza
+.section snczb
+.section snc1a
+.section snc1b
+.section snc2a
+.section snc2b
+.section snc3a
+.section snc3b
+.section snc4a
+.section snc4b
+.section snc5a
+.section snc5b
+.section snc6a
+.section snc6b
+.section snc7a
+.section snc7b
+.section snc8a
+.section snc8b
+.section snc9a
+.section snc9b
+.section snc0a
+.section snc0b
+.section sndaa
+.section sndab
+.section sndba
+.section sndbb
+.section sndca
+.section sndcb
+.section sndda
+.section snddb
+.section sndea
+.section sndeb
+.section sndfa
+.section sndfb
+.section sndga
+.section sndgb
+.section sndha
+.section sndhb
+.section sndia
+.section sndib
+.section sndja
+.section sndjb
+.section sndka
+.section sndkb
+.section sndla
+.section sndlb
+.section sndma
+.section sndmb
+.section sndna
+.section sndnb
+.section sndoa
+.section sndob
+.section sndpa
+.section sndpb
+.section sndqa
+.section sndqb
+.section sndra
+.section sndrb
+.section sndsa
+.section sndsb
+.section sndta
+.section sndtb
+.section sndua
+.section sndub
+.section sndva
+.section sndvb
+.section sndwa
+.section sndwb
+.section sndxa
+.section sndxb
+.section sndya
+.section sndyb
+.section sndza
+.section sndzb
+.section snd1a
+.section snd1b
+.section snd2a
+.section snd2b
+.section snd3a
+.section snd3b
+.section snd4a
+.section snd4b
+.section snd5a
+.section snd5b
+.section snd6a
+.section snd6b
+.section snd7a
+.section snd7b
+.section snd8a
+.section snd8b
+.section snd9a
+.section snd9b
+.section snd0a
+.section snd0b
+.section sneaa
+.section sneab
+.section sneba
+.section snebb
+.section sneca
+.section snecb
+.section sneda
+.section snedb
+.section sneea
+.section sneeb
+.section snefa
+.section snefb
+.section snega
+.section snegb
+.section sneha
+.section snehb
+.section sneia
+.section sneib
+.section sneja
+.section snejb
+.section sneka
+.section snekb
+.section snela
+.section snelb
+.section snema
+.section snemb
+.section snena
+.section snenb
+.section sneoa
+.section sneob
+.section snepa
+.section snepb
+.section sneqa
+.section sneqb
+.section snera
+.section snerb
+.section snesa
+.section snesb
+.section sneta
+.section snetb
+.section sneua
+.section sneub
+.section sneva
+.section snevb
+.section snewa
+.section snewb
+.section snexa
+.section snexb
+.section sneya
+.section sneyb
+.section sneza
+.section snezb
+.section sne1a
+.section sne1b
+.section sne2a
+.section sne2b
+.section sne3a
+.section sne3b
+.section sne4a
+.section sne4b
+.section sne5a
+.section sne5b
+.section sne6a
+.section sne6b
+.section sne7a
+.section sne7b
+.section sne8a
+.section sne8b
+.section sne9a
+.section sne9b
+.section sne0a
+.section sne0b
+.section snfaa
+.section snfab
+.section snfba
+.section snfbb
+.section snfca
+.section snfcb
+.section snfda
+.section snfdb
+.section snfea
+.section snfeb
+.section snffa
+.section snffb
+.section snfga
+.section snfgb
+.section snfha
+.section snfhb
+.section snfia
+.section snfib
+.section snfja
+.section snfjb
+.section snfka
+.section snfkb
+.section snfla
+.section snflb
+.section snfma
+.section snfmb
+.section snfna
+.section snfnb
+.section snfoa
+.section snfob
+.section snfpa
+.section snfpb
+.section snfqa
+.section snfqb
+.section snfra
+.section snfrb
+.section snfsa
+.section snfsb
+.section snfta
+.section snftb
+.section snfua
+.section snfub
+.section snfva
+.section snfvb
+.section snfwa
+.section snfwb
+.section snfxa
+.section snfxb
+.section snfya
+.section snfyb
+.section snfza
+.section snfzb
+.section snf1a
+.section snf1b
+.section snf2a
+.section snf2b
+.section snf3a
+.section snf3b
+.section snf4a
+.section snf4b
+.section snf5a
+.section snf5b
+.section snf6a
+.section snf6b
+.section snf7a
+.section snf7b
+.section snf8a
+.section snf8b
+.section snf9a
+.section snf9b
+.section snf0a
+.section snf0b
+.section sngaa
+.section sngab
+.section sngba
+.section sngbb
+.section sngca
+.section sngcb
+.section sngda
+.section sngdb
+.section sngea
+.section sngeb
+.section sngfa
+.section sngfb
+.section sngga
+.section snggb
+.section sngha
+.section snghb
+.section sngia
+.section sngib
+.section sngja
+.section sngjb
+.section sngka
+.section sngkb
+.section sngla
+.section snglb
+.section sngma
+.section sngmb
+.section sngna
+.section sngnb
+.section sngoa
+.section sngob
+.section sngpa
+.section sngpb
+.section sngqa
+.section sngqb
+.section sngra
+.section sngrb
+.section sngsa
+.section sngsb
+.section sngta
+.section sngtb
+.section sngua
+.section sngub
+.section sngva
+.section sngvb
+.section sngwa
+.section sngwb
+.section sngxa
+.section sngxb
+.section sngya
+.section sngyb
+.section sngza
+.section sngzb
+.section sng1a
+.section sng1b
+.section sng2a
+.section sng2b
+.section sng3a
+.section sng3b
+.section sng4a
+.section sng4b
+.section sng5a
+.section sng5b
+.section sng6a
+.section sng6b
+.section sng7a
+.section sng7b
+.section sng8a
+.section sng8b
+.section sng9a
+.section sng9b
+.section sng0a
+.section sng0b
+.section snhaa
+.section snhab
+.section snhba
+.section snhbb
+.section snhca
+.section snhcb
+.section snhda
+.section snhdb
+.section snhea
+.section snheb
+.section snhfa
+.section snhfb
+.section snhga
+.section snhgb
+.section snhha
+.section snhhb
+.section snhia
+.section snhib
+.section snhja
+.section snhjb
+.section snhka
+.section snhkb
+.section snhla
+.section snhlb
+.section snhma
+.section snhmb
+.section snhna
+.section snhnb
+.section snhoa
+.section snhob
+.section snhpa
+.section snhpb
+.section snhqa
+.section snhqb
+.section snhra
+.section snhrb
+.section snhsa
+.section snhsb
+.section snhta
+.section snhtb
+.section snhua
+.section snhub
+.section snhva
+.section snhvb
+.section snhwa
+.section snhwb
+.section snhxa
+.section snhxb
+.section snhya
+.section snhyb
+.section snhza
+.section snhzb
+.section snh1a
+.section snh1b
+.section snh2a
+.section snh2b
+.section snh3a
+.section snh3b
+.section snh4a
+.section snh4b
+.section snh5a
+.section snh5b
+.section snh6a
+.section snh6b
+.section snh7a
+.section snh7b
+.section snh8a
+.section snh8b
+.section snh9a
+.section snh9b
+.section snh0a
+.section snh0b
+.section sniaa
+.section sniab
+.section sniba
+.section snibb
+.section snica
+.section snicb
+.section snida
+.section snidb
+.section sniea
+.section snieb
+.section snifa
+.section snifb
+.section sniga
+.section snigb
+.section sniha
+.section snihb
+.section sniia
+.section sniib
+.section snija
+.section snijb
+.section snika
+.section snikb
+.section snila
+.section snilb
+.section snima
+.section snimb
+.section snina
+.section sninb
+.section snioa
+.section sniob
+.section snipa
+.section snipb
+.section sniqa
+.section sniqb
+.section snira
+.section snirb
+.section snisa
+.section snisb
+.section snita
+.section snitb
+.section sniua
+.section sniub
+.section sniva
+.section snivb
+.section sniwa
+.section sniwb
+.section snixa
+.section snixb
+.section sniya
+.section sniyb
+.section sniza
+.section snizb
+.section sni1a
+.section sni1b
+.section sni2a
+.section sni2b
+.section sni3a
+.section sni3b
+.section sni4a
+.section sni4b
+.section sni5a
+.section sni5b
+.section sni6a
+.section sni6b
+.section sni7a
+.section sni7b
+.section sni8a
+.section sni8b
+.section sni9a
+.section sni9b
+.section sni0a
+.section sni0b
+.section snjaa
+.section snjab
+.section snjba
+.section snjbb
+.section snjca
+.section snjcb
+.section snjda
+.section snjdb
+.section snjea
+.section snjeb
+.section snjfa
+.section snjfb
+.section snjga
+.section snjgb
+.section snjha
+.section snjhb
+.section snjia
+.section snjib
+.section snjja
+.section snjjb
+.section snjka
+.section snjkb
+.section snjla
+.section snjlb
+.section snjma
+.section snjmb
+.section snjna
+.section snjnb
+.section snjoa
+.section snjob
+.section snjpa
+.section snjpb
+.section snjqa
+.section snjqb
+.section snjra
+.section snjrb
+.section snjsa
+.section snjsb
+.section snjta
+.section snjtb
+.section snjua
+.section snjub
+.section snjva
+.section snjvb
+.section snjwa
+.section snjwb
+.section snjxa
+.section snjxb
+.section snjya
+.section snjyb
+.section snjza
+.section snjzb
+.section snj1a
+.section snj1b
+.section snj2a
+.section snj2b
+.section snj3a
+.section snj3b
+.section snj4a
+.section snj4b
+.section snj5a
+.section snj5b
+.section snj6a
+.section snj6b
+.section snj7a
+.section snj7b
+.section snj8a
+.section snj8b
+.section snj9a
+.section snj9b
+.section snj0a
+.section snj0b
+.section snkaa
+.section snkab
+.section snkba
+.section snkbb
+.section snkca
+.section snkcb
+.section snkda
+.section snkdb
+.section snkea
+.section snkeb
+.section snkfa
+.section snkfb
+.section snkga
+.section snkgb
+.section snkha
+.section snkhb
+.section snkia
+.section snkib
+.section snkja
+.section snkjb
+.section snkka
+.section snkkb
+.section snkla
+.section snklb
+.section snkma
+.section snkmb
+.section snkna
+.section snknb
+.section snkoa
+.section snkob
+.section snkpa
+.section snkpb
+.section snkqa
+.section snkqb
+.section snkra
+.section snkrb
+.section snksa
+.section snksb
+.section snkta
+.section snktb
+.section snkua
+.section snkub
+.section snkva
+.section snkvb
+.section snkwa
+.section snkwb
+.section snkxa
+.section snkxb
+.section snkya
+.section snkyb
+.section snkza
+.section snkzb
+.section snk1a
+.section snk1b
+.section snk2a
+.section snk2b
+.section snk3a
+.section snk3b
+.section snk4a
+.section snk4b
+.section snk5a
+.section snk5b
+.section snk6a
+.section snk6b
+.section snk7a
+.section snk7b
+.section snk8a
+.section snk8b
+.section snk9a
+.section snk9b
+.section snk0a
+.section snk0b
+.section snlaa
+.section snlab
+.section snlba
+.section snlbb
+.section snlca
+.section snlcb
+.section snlda
+.section snldb
+.section snlea
+.section snleb
+.section snlfa
+.section snlfb
+.section snlga
+.section snlgb
+.section snlha
+.section snlhb
+.section snlia
+.section snlib
+.section snlja
+.section snljb
+.section snlka
+.section snlkb
+.section snlla
+.section snllb
+.section snlma
+.section snlmb
+.section snlna
+.section snlnb
+.section snloa
+.section snlob
+.section snlpa
+.section snlpb
+.section snlqa
+.section snlqb
+.section snlra
+.section snlrb
+.section snlsa
+.section snlsb
+.section snlta
+.section snltb
+.section snlua
+.section snlub
+.section snlva
+.section snlvb
+.section snlwa
+.section snlwb
+.section snlxa
+.section snlxb
+.section snlya
+.section snlyb
+.section snlza
+.section snlzb
+.section snl1a
+.section snl1b
+.section snl2a
+.section snl2b
+.section snl3a
+.section snl3b
+.section snl4a
+.section snl4b
+.section snl5a
+.section snl5b
+.section snl6a
+.section snl6b
+.section snl7a
+.section snl7b
+.section snl8a
+.section snl8b
+.section snl9a
+.section snl9b
+.section snl0a
+.section snl0b
+.section snmaa
+.section snmab
+.section snmba
+.section snmbb
+.section snmca
+.section snmcb
+.section snmda
+.section snmdb
+.section snmea
+.section snmeb
+.section snmfa
+.section snmfb
+.section snmga
+.section snmgb
+.section snmha
+.section snmhb
+.section snmia
+.section snmib
+.section snmja
+.section snmjb
+.section snmka
+.section snmkb
+.section snmla
+.section snmlb
+.section snmma
+.section snmmb
+.section snmna
+.section snmnb
+.section snmoa
+.section snmob
+.section snmpa
+.section snmpb
+.section snmqa
+.section snmqb
+.section snmra
+.section snmrb
+.section snmsa
+.section snmsb
+.section snmta
+.section snmtb
+.section snmua
+.section snmub
+.section snmva
+.section snmvb
+.section snmwa
+.section snmwb
+.section snmxa
+.section snmxb
+.section snmya
+.section snmyb
+.section snmza
+.section snmzb
+.section snm1a
+.section snm1b
+.section snm2a
+.section snm2b
+.section snm3a
+.section snm3b
+.section snm4a
+.section snm4b
+.section snm5a
+.section snm5b
+.section snm6a
+.section snm6b
+.section snm7a
+.section snm7b
+.section snm8a
+.section snm8b
+.section snm9a
+.section snm9b
+.section snm0a
+.section snm0b
+.section snnaa
+.section snnab
+.section snnba
+.section snnbb
+.section snnca
+.section snncb
+.section snnda
+.section snndb
+.section snnea
+.section snneb
+.section snnfa
+.section snnfb
+.section snnga
+.section snngb
+.section snnha
+.section snnhb
+.section snnia
+.section snnib
+.section snnja
+.section snnjb
+.section snnka
+.section snnkb
+.section snnla
+.section snnlb
+.section snnma
+.section snnmb
+.section snnna
+.section snnnb
+.section snnoa
+.section snnob
+.section snnpa
+.section snnpb
+.section snnqa
+.section snnqb
+.section snnra
+.section snnrb
+.section snnsa
+.section snnsb
+.section snnta
+.section snntb
+.section snnua
+.section snnub
+.section snnva
+.section snnvb
+.section snnwa
+.section snnwb
+.section snnxa
+.section snnxb
+.section snnya
+.section snnyb
+.section snnza
+.section snnzb
+.section snn1a
+.section snn1b
+.section snn2a
+.section snn2b
+.section snn3a
+.section snn3b
+.section snn4a
+.section snn4b
+.section snn5a
+.section snn5b
+.section snn6a
+.section snn6b
+.section snn7a
+.section snn7b
+.section snn8a
+.section snn8b
+.section snn9a
+.section snn9b
+.section snn0a
+.section snn0b
+.section snoaa
+.section snoab
+.section snoba
+.section snobb
+.section snoca
+.section snocb
+.section snoda
+.section snodb
+.section snoea
+.section snoeb
+.section snofa
+.section snofb
+.section snoga
+.section snogb
+.section snoha
+.section snohb
+.section snoia
+.section snoib
+.section snoja
+.section snojb
+.section snoka
+.section snokb
+.section snola
+.section snolb
+.section snoma
+.section snomb
+.section snona
+.section snonb
+.section snooa
+.section snoob
+.section snopa
+.section snopb
+.section snoqa
+.section snoqb
+.section snora
+.section snorb
+.section snosa
+.section snosb
+.section snota
+.section snotb
+.section snoua
+.section snoub
+.section snova
+.section snovb
+.section snowa
+.section snowb
+.section snoxa
+.section snoxb
+.section snoya
+.section snoyb
+.section snoza
+.section snozb
+.section sno1a
+.section sno1b
+.section sno2a
+.section sno2b
+.section sno3a
+.section sno3b
+.section sno4a
+.section sno4b
+.section sno5a
+.section sno5b
+.section sno6a
+.section sno6b
+.section sno7a
+.section sno7b
+.section sno8a
+.section sno8b
+.section sno9a
+.section sno9b
+.section sno0a
+.section sno0b
+.section snpaa
+.section snpab
+.section snpba
+.section snpbb
+.section snpca
+.section snpcb
+.section snpda
+.section snpdb
+.section snpea
+.section snpeb
+.section snpfa
+.section snpfb
+.section snpga
+.section snpgb
+.section snpha
+.section snphb
+.section snpia
+.section snpib
+.section snpja
+.section snpjb
+.section snpka
+.section snpkb
+.section snpla
+.section snplb
+.section snpma
+.section snpmb
+.section snpna
+.section snpnb
+.section snpoa
+.section snpob
+.section snppa
+.section snppb
+.section snpqa
+.section snpqb
+.section snpra
+.section snprb
+.section snpsa
+.section snpsb
+.section snpta
+.section snptb
+.section snpua
+.section snpub
+.section snpva
+.section snpvb
+.section snpwa
+.section snpwb
+.section snpxa
+.section snpxb
+.section snpya
+.section snpyb
+.section snpza
+.section snpzb
+.section snp1a
+.section snp1b
+.section snp2a
+.section snp2b
+.section snp3a
+.section snp3b
+.section snp4a
+.section snp4b
+.section snp5a
+.section snp5b
+.section snp6a
+.section snp6b
+.section snp7a
+.section snp7b
+.section snp8a
+.section snp8b
+.section snp9a
+.section snp9b
+.section snp0a
+.section snp0b
+.section snqaa
+.section snqab
+.section snqba
+.section snqbb
+.section snqca
+.section snqcb
+.section snqda
+.section snqdb
+.section snqea
+.section snqeb
+.section snqfa
+.section snqfb
+.section snqga
+.section snqgb
+.section snqha
+.section snqhb
+.section snqia
+.section snqib
+.section snqja
+.section snqjb
+.section snqka
+.section snqkb
+.section snqla
+.section snqlb
+.section snqma
+.section snqmb
+.section snqna
+.section snqnb
+.section snqoa
+.section snqob
+.section snqpa
+.section snqpb
+.section snqqa
+.section snqqb
+.section snqra
+.section snqrb
+.section snqsa
+.section snqsb
+.section snqta
+.section snqtb
+.section snqua
+.section snqub
+.section snqva
+.section snqvb
+.section snqwa
+.section snqwb
+.section snqxa
+.section snqxb
+.section snqya
+.section snqyb
+.section snqza
+.section snqzb
+.section snq1a
+.section snq1b
+.section snq2a
+.section snq2b
+.section snq3a
+.section snq3b
+.section snq4a
+.section snq4b
+.section snq5a
+.section snq5b
+.section snq6a
+.section snq6b
+.section snq7a
+.section snq7b
+.section snq8a
+.section snq8b
+.section snq9a
+.section snq9b
+.section snq0a
+.section snq0b
+.section snraa
+.section snrab
+.section snrba
+.section snrbb
+.section snrca
+.section snrcb
+.section snrda
+.section snrdb
+.section snrea
+.section snreb
+.section snrfa
+.section snrfb
+.section snrga
+.section snrgb
+.section snrha
+.section snrhb
+.section snria
+.section snrib
+.section snrja
+.section snrjb
+.section snrka
+.section snrkb
+.section snrla
+.section snrlb
+.section snrma
+.section snrmb
+.section snrna
+.section snrnb
+.section snroa
+.section snrob
+.section snrpa
+.section snrpb
+.section snrqa
+.section snrqb
+.section snrra
+.section snrrb
+.section snrsa
+.section snrsb
+.section snrta
+.section snrtb
+.section snrua
+.section snrub
+.section snrva
+.section snrvb
+.section snrwa
+.section snrwb
+.section snrxa
+.section snrxb
+.section snrya
+.section snryb
+.section snrza
+.section snrzb
+.section snr1a
+.section snr1b
+.section snr2a
+.section snr2b
+.section snr3a
+.section snr3b
+.section snr4a
+.section snr4b
+.section snr5a
+.section snr5b
+.section snr6a
+.section snr6b
+.section snr7a
+.section snr7b
+.section snr8a
+.section snr8b
+.section snr9a
+.section snr9b
+.section snr0a
+.section snr0b
+.section snsaa
+.section snsab
+.section snsba
+.section snsbb
+.section snsca
+.section snscb
+.section snsda
+.section snsdb
+.section snsea
+.section snseb
+.section snsfa
+.section snsfb
+.section snsga
+.section snsgb
+.section snsha
+.section snshb
+.section snsia
+.section snsib
+.section snsja
+.section snsjb
+.section snska
+.section snskb
+.section snsla
+.section snslb
+.section snsma
+.section snsmb
+.section snsna
+.section snsnb
+.section snsoa
+.section snsob
+.section snspa
+.section snspb
+.section snsqa
+.section snsqb
+.section snsra
+.section snsrb
+.section snssa
+.section snssb
+.section snsta
+.section snstb
+.section snsua
+.section snsub
+.section snsva
+.section snsvb
+.section snswa
+.section snswb
+.section snsxa
+.section snsxb
+.section snsya
+.section snsyb
+.section snsza
+.section snszb
+.section sns1a
+.section sns1b
+.section sns2a
+.section sns2b
+.section sns3a
+.section sns3b
+.section sns4a
+.section sns4b
+.section sns5a
+.section sns5b
+.section sns6a
+.section sns6b
+.section sns7a
+.section sns7b
+.section sns8a
+.section sns8b
+.section sns9a
+.section sns9b
+.section sns0a
+.section sns0b
+.section sntaa
+.section sntab
+.section sntba
+.section sntbb
+.section sntca
+.section sntcb
+.section sntda
+.section sntdb
+.section sntea
+.section snteb
+.section sntfa
+.section sntfb
+.section sntga
+.section sntgb
+.section sntha
+.section snthb
+.section sntia
+.section sntib
+.section sntja
+.section sntjb
+.section sntka
+.section sntkb
+.section sntla
+.section sntlb
+.section sntma
+.section sntmb
+.section sntna
+.section sntnb
+.section sntoa
+.section sntob
+.section sntpa
+.section sntpb
+.section sntqa
+.section sntqb
+.section sntra
+.section sntrb
+.section sntsa
+.section sntsb
+.section sntta
+.section snttb
+.section sntua
+.section sntub
+.section sntva
+.section sntvb
+.section sntwa
+.section sntwb
+.section sntxa
+.section sntxb
+.section sntya
+.section sntyb
+.section sntza
+.section sntzb
+.section snt1a
+.section snt1b
+.section snt2a
+.section snt2b
+.section snt3a
+.section snt3b
+.section snt4a
+.section snt4b
+.section snt5a
+.section snt5b
+.section snt6a
+.section snt6b
+.section snt7a
+.section snt7b
+.section snt8a
+.section snt8b
+.section snt9a
+.section snt9b
+.section snt0a
+.section snt0b
+.section snuaa
+.section snuab
+.section snuba
+.section snubb
+.section snuca
+.section snucb
+.section snuda
+.section snudb
+.section snuea
+.section snueb
+.section snufa
+.section snufb
+.section snuga
+.section snugb
+.section snuha
+.section snuhb
+.section snuia
+.section snuib
+.section snuja
+.section snujb
+.section snuka
+.section snukb
+.section snula
+.section snulb
+.section snuma
+.section snumb
+.section snuna
+.section snunb
+.section snuoa
+.section snuob
+.section snupa
+.section snupb
+.section snuqa
+.section snuqb
+.section snura
+.section snurb
+.section snusa
+.section snusb
+.section snuta
+.section snutb
+.section snuua
+.section snuub
+.section snuva
+.section snuvb
+.section snuwa
+.section snuwb
+.section snuxa
+.section snuxb
+.section snuya
+.section snuyb
+.section snuza
+.section snuzb
+.section snu1a
+.section snu1b
+.section snu2a
+.section snu2b
+.section snu3a
+.section snu3b
+.section snu4a
+.section snu4b
+.section snu5a
+.section snu5b
+.section snu6a
+.section snu6b
+.section snu7a
+.section snu7b
+.section snu8a
+.section snu8b
+.section snu9a
+.section snu9b
+.section snu0a
+.section snu0b
+.section snvaa
+.section snvab
+.section snvba
+.section snvbb
+.section snvca
+.section snvcb
+.section snvda
+.section snvdb
+.section snvea
+.section snveb
+.section snvfa
+.section snvfb
+.section snvga
+.section snvgb
+.section snvha
+.section snvhb
+.section snvia
+.section snvib
+.section snvja
+.section snvjb
+.section snvka
+.section snvkb
+.section snvla
+.section snvlb
+.section snvma
+.section snvmb
+.section snvna
+.section snvnb
+.section snvoa
+.section snvob
+.section snvpa
+.section snvpb
+.section snvqa
+.section snvqb
+.section snvra
+.section snvrb
+.section snvsa
+.section snvsb
+.section snvta
+.section snvtb
+.section snvua
+.section snvub
+.section snvva
+.section snvvb
+.section snvwa
+.section snvwb
+.section snvxa
+.section snvxb
+.section snvya
+.section snvyb
+.section snvza
+.section snvzb
+.section snv1a
+.section snv1b
+.section snv2a
+.section snv2b
+.section snv3a
+.section snv3b
+.section snv4a
+.section snv4b
+.section snv5a
+.section snv5b
+.section snv6a
+.section snv6b
+.section snv7a
+.section snv7b
+.section snv8a
+.section snv8b
+.section snv9a
+.section snv9b
+.section snv0a
+.section snv0b
+.section snwaa
+.section snwab
+.section snwba
+.section snwbb
+.section snwca
+.section snwcb
+.section snwda
+.section snwdb
+.section snwea
+.section snweb
+.section snwfa
+.section snwfb
+.section snwga
+.section snwgb
+.section snwha
+.section snwhb
+.section snwia
+.section snwib
+.section snwja
+.section snwjb
+.section snwka
+.section snwkb
+.section snwla
+.section snwlb
+.section snwma
+.section snwmb
+.section snwna
+.section snwnb
+.section snwoa
+.section snwob
+.section snwpa
+.section snwpb
+.section snwqa
+.section snwqb
+.section snwra
+.section snwrb
+.section snwsa
+.section snwsb
+.section snwta
+.section snwtb
+.section snwua
+.section snwub
+.section snwva
+.section snwvb
+.section snwwa
+.section snwwb
+.section snwxa
+.section snwxb
+.section snwya
+.section snwyb
+.section snwza
+.section snwzb
+.section snw1a
+.section snw1b
+.section snw2a
+.section snw2b
+.section snw3a
+.section snw3b
+.section snw4a
+.section snw4b
+.section snw5a
+.section snw5b
+.section snw6a
+.section snw6b
+.section snw7a
+.section snw7b
+.section snw8a
+.section snw8b
+.section snw9a
+.section snw9b
+.section snw0a
+.section snw0b
+.section snxaa
+.section snxab
+.section snxba
+.section snxbb
+.section snxca
+.section snxcb
+.section snxda
+.section snxdb
+.section snxea
+.section snxeb
+.section snxfa
+.section snxfb
+.section snxga
+.section snxgb
+.section snxha
+.section snxhb
+.section snxia
+.section snxib
+.section snxja
+.section snxjb
+.section snxka
+.section snxkb
+.section snxla
+.section snxlb
+.section snxma
+.section snxmb
+.section snxna
+.section snxnb
+.section snxoa
+.section snxob
+.section snxpa
+.section snxpb
+.section snxqa
+.section snxqb
+.section snxra
+.section snxrb
+.section snxsa
+.section snxsb
+.section snxta
+.section snxtb
+.section snxua
+.section snxub
+.section snxva
+.section snxvb
+.section snxwa
+.section snxwb
+.section snxxa
+.section snxxb
+.section snxya
+.section snxyb
+.section snxza
+.section snxzb
+.section snx1a
+.section snx1b
+.section snx2a
+.section snx2b
+.section snx3a
+.section snx3b
+.section snx4a
+.section snx4b
+.section snx5a
+.section snx5b
+.section snx6a
+.section snx6b
+.section snx7a
+.section snx7b
+.section snx8a
+.section snx8b
+.section snx9a
+.section snx9b
+.section snx0a
+.section snx0b
+.section snyaa
+.section snyab
+.section snyba
+.section snybb
+.section snyca
+.section snycb
+.section snyda
+.section snydb
+.section snyea
+.section snyeb
+.section snyfa
+.section snyfb
+.section snyga
+.section snygb
+.section snyha
+.section snyhb
+.section snyia
+.section snyib
+.section snyja
+.section snyjb
+.section snyka
+.section snykb
+.section snyla
+.section snylb
+.section snyma
+.section snymb
+.section snyna
+.section snynb
+.section snyoa
+.section snyob
+.section snypa
+.section snypb
+.section snyqa
+.section snyqb
+.section snyra
+.section snyrb
+.section snysa
+.section snysb
+.section snyta
+.section snytb
+.section snyua
+.section snyub
+.section snyva
+.section snyvb
+.section snywa
+.section snywb
+.section snyxa
+.section snyxb
+.section snyya
+.section snyyb
+.section snyza
+.section snyzb
+.section sny1a
+.section sny1b
+.section sny2a
+.section sny2b
+.section sny3a
+.section sny3b
+.section sny4a
+.section sny4b
+.section sny5a
+.section sny5b
+.section sny6a
+.section sny6b
+.section sny7a
+.section sny7b
+.section sny8a
+.section sny8b
+.section sny9a
+.section sny9b
+.section sny0a
+.section sny0b
+.section snzaa
+.section snzab
+.section snzba
+.section snzbb
+.section snzca
+.section snzcb
+.section snzda
+.section snzdb
+.section snzea
+.section snzeb
+.section snzfa
+.section snzfb
+.section snzga
+.section snzgb
+.section snzha
+.section snzhb
+.section snzia
+.section snzib
+.section snzja
+.section snzjb
+.section snzka
+.section snzkb
+.section snzla
+.section snzlb
+.section snzma
+.section snzmb
+.section snzna
+.section snznb
+.section snzoa
+.section snzob
+.section snzpa
+.section snzpb
+.section snzqa
+.section snzqb
+.section snzra
+.section snzrb
+.section snzsa
+.section snzsb
+.section snzta
+.section snztb
+.section snzua
+.section snzub
+.section snzva
+.section snzvb
+.section snzwa
+.section snzwb
+.section snzxa
+.section snzxb
+.section snzya
+.section snzyb
+.section snzza
+.section snzzb
+.section snz1a
+.section snz1b
+.section snz2a
+.section snz2b
+.section snz3a
+.section snz3b
+.section snz4a
+.section snz4b
+.section snz5a
+.section snz5b
+.section snz6a
+.section snz6b
+.section snz7a
+.section snz7b
+.section snz8a
+.section snz8b
+.section snz9a
+.section snz9b
+.section snz0a
+.section snz0b
+.section sn1aa
+.section sn1ab
+.section sn1ba
+.section sn1bb
+.section sn1ca
+.section sn1cb
+.section sn1da
+.section sn1db
+.section sn1ea
+.section sn1eb
+.section sn1fa
+.section sn1fb
+.section sn1ga
+.section sn1gb
+.section sn1ha
+.section sn1hb
+.section sn1ia
+.section sn1ib
+.section sn1ja
+.section sn1jb
+.section sn1ka
+.section sn1kb
+.section sn1la
+.section sn1lb
+.section sn1ma
+.section sn1mb
+.section sn1na
+.section sn1nb
+.section sn1oa
+.section sn1ob
+.section sn1pa
+.section sn1pb
+.section sn1qa
+.section sn1qb
+.section sn1ra
+.section sn1rb
+.section sn1sa
+.section sn1sb
+.section sn1ta
+.section sn1tb
+.section sn1ua
+.section sn1ub
+.section sn1va
+.section sn1vb
+.section sn1wa
+.section sn1wb
+.section sn1xa
+.section sn1xb
+.section sn1ya
+.section sn1yb
+.section sn1za
+.section sn1zb
+.section sn11a
+.section sn11b
+.section sn12a
+.section sn12b
+.section sn13a
+.section sn13b
+.section sn14a
+.section sn14b
+.section sn15a
+.section sn15b
+.section sn16a
+.section sn16b
+.section sn17a
+.section sn17b
+.section sn18a
+.section sn18b
+.section sn19a
+.section sn19b
+.section sn10a
+.section sn10b
+.section sn2aa
+.section sn2ab
+.section sn2ba
+.section sn2bb
+.section sn2ca
+.section sn2cb
+.section sn2da
+.section sn2db
+.section sn2ea
+.section sn2eb
+.section sn2fa
+.section sn2fb
+.section sn2ga
+.section sn2gb
+.section sn2ha
+.section sn2hb
+.section sn2ia
+.section sn2ib
+.section sn2ja
+.section sn2jb
+.section sn2ka
+.section sn2kb
+.section sn2la
+.section sn2lb
+.section sn2ma
+.section sn2mb
+.section sn2na
+.section sn2nb
+.section sn2oa
+.section sn2ob
+.section sn2pa
+.section sn2pb
+.section sn2qa
+.section sn2qb
+.section sn2ra
+.section sn2rb
+.section sn2sa
+.section sn2sb
+.section sn2ta
+.section sn2tb
+.section sn2ua
+.section sn2ub
+.section sn2va
+.section sn2vb
+.section sn2wa
+.section sn2wb
+.section sn2xa
+.section sn2xb
+.section sn2ya
+.section sn2yb
+.section sn2za
+.section sn2zb
+.section sn21a
+.section sn21b
+.section sn22a
+.section sn22b
+.section sn23a
+.section sn23b
+.section sn24a
+.section sn24b
+.section sn25a
+.section sn25b
+.section sn26a
+.section sn26b
+.section sn27a
+.section sn27b
+.section sn28a
+.section sn28b
+.section sn29a
+.section sn29b
+.section sn20a
+.section sn20b
+.section sn3aa
+.section sn3ab
+.section sn3ba
+.section sn3bb
+.section sn3ca
+.section sn3cb
+.section sn3da
+.section sn3db
+.section sn3ea
+.section sn3eb
+.section sn3fa
+.section sn3fb
+.section sn3ga
+.section sn3gb
+.section sn3ha
+.section sn3hb
+.section sn3ia
+.section sn3ib
+.section sn3ja
+.section sn3jb
+.section sn3ka
+.section sn3kb
+.section sn3la
+.section sn3lb
+.section sn3ma
+.section sn3mb
+.section sn3na
+.section sn3nb
+.section sn3oa
+.section sn3ob
+.section sn3pa
+.section sn3pb
+.section sn3qa
+.section sn3qb
+.section sn3ra
+.section sn3rb
+.section sn3sa
+.section sn3sb
+.section sn3ta
+.section sn3tb
+.section sn3ua
+.section sn3ub
+.section sn3va
+.section sn3vb
+.section sn3wa
+.section sn3wb
+.section sn3xa
+.section sn3xb
+.section sn3ya
+.section sn3yb
+.section sn3za
+.section sn3zb
+.section sn31a
+.section sn31b
+.section sn32a
+.section sn32b
+.section sn33a
+.section sn33b
+.section sn34a
+.section sn34b
+.section sn35a
+.section sn35b
+.section sn36a
+.section sn36b
+.section sn37a
+.section sn37b
+.section sn38a
+.section sn38b
+.section sn39a
+.section sn39b
+.section sn30a
+.section sn30b
+.section sn4aa
+.section sn4ab
+.section sn4ba
+.section sn4bb
+.section sn4ca
+.section sn4cb
+.section sn4da
+.section sn4db
+.section sn4ea
+.section sn4eb
+.section sn4fa
+.section sn4fb
+.section sn4ga
+.section sn4gb
+.section sn4ha
+.section sn4hb
+.section sn4ia
+.section sn4ib
+.section sn4ja
+.section sn4jb
+.section sn4ka
+.section sn4kb
+.section sn4la
+.section sn4lb
+.section sn4ma
+.section sn4mb
+.section sn4na
+.section sn4nb
+.section sn4oa
+.section sn4ob
+.section sn4pa
+.section sn4pb
+.section sn4qa
+.section sn4qb
+.section sn4ra
+.section sn4rb
+.section sn4sa
+.section sn4sb
+.section sn4ta
+.section sn4tb
+.section sn4ua
+.section sn4ub
+.section sn4va
+.section sn4vb
+.section sn4wa
+.section sn4wb
+.section sn4xa
+.section sn4xb
+.section sn4ya
+.section sn4yb
+.section sn4za
+.section sn4zb
+.section sn41a
+.section sn41b
+.section sn42a
+.section sn42b
+.section sn43a
+.section sn43b
+.section sn44a
+.section sn44b
+.section sn45a
+.section sn45b
+.section sn46a
+.section sn46b
+.section sn47a
+.section sn47b
+.section sn48a
+.section sn48b
+.section sn49a
+.section sn49b
+.section sn40a
+.section sn40b
+.section sn5aa
+.section sn5ab
+.section sn5ba
+.section sn5bb
+.section sn5ca
+.section sn5cb
+.section sn5da
+.section sn5db
+.section sn5ea
+.section sn5eb
+.section sn5fa
+.section sn5fb
+.section sn5ga
+.section sn5gb
+.section sn5ha
+.section sn5hb
+.section sn5ia
+.section sn5ib
+.section sn5ja
+.section sn5jb
+.section sn5ka
+.section sn5kb
+.section sn5la
+.section sn5lb
+.section sn5ma
+.section sn5mb
+.section sn5na
+.section sn5nb
+.section sn5oa
+.section sn5ob
+.section sn5pa
+.section sn5pb
+.section sn5qa
+.section sn5qb
+.section sn5ra
+.section sn5rb
+.section sn5sa
+.section sn5sb
+.section sn5ta
+.section sn5tb
+.section sn5ua
+.section sn5ub
+.section sn5va
+.section sn5vb
+.section sn5wa
+.section sn5wb
+.section sn5xa
+.section sn5xb
+.section sn5ya
+.section sn5yb
+.section sn5za
+.section sn5zb
+.section sn51a
+.section sn51b
+.section sn52a
+.section sn52b
+.section sn53a
+.section sn53b
+.section sn54a
+.section sn54b
+.section sn55a
+.section sn55b
+.section sn56a
+.section sn56b
+.section sn57a
+.section sn57b
+.section sn58a
+.section sn58b
+.section sn59a
+.section sn59b
+.section sn50a
+.section sn50b
+.section sn6aa
+.section sn6ab
+.section sn6ba
+.section sn6bb
+.section sn6ca
+.section sn6cb
+.section sn6da
+.section sn6db
+.section sn6ea
+.section sn6eb
+.section sn6fa
+.section sn6fb
+.section sn6ga
+.section sn6gb
+.section sn6ha
+.section sn6hb
+.section sn6ia
+.section sn6ib
+.section sn6ja
+.section sn6jb
+.section sn6ka
+.section sn6kb
+.section sn6la
+.section sn6lb
+.section sn6ma
+.section sn6mb
+.section sn6na
+.section sn6nb
+.section sn6oa
+.section sn6ob
+.section sn6pa
+.section sn6pb
+.section sn6qa
+.section sn6qb
+.section sn6ra
+.section sn6rb
+.section sn6sa
+.section sn6sb
+.section sn6ta
+.section sn6tb
+.section sn6ua
+.section sn6ub
+.section sn6va
+.section sn6vb
+.section sn6wa
+.section sn6wb
+.section sn6xa
+.section sn6xb
+.section sn6ya
+.section sn6yb
+.section sn6za
+.section sn6zb
+.section sn61a
+.section sn61b
+.section sn62a
+.section sn62b
+.section sn63a
+.section sn63b
+.section sn64a
+.section sn64b
+.section sn65a
+.section sn65b
+.section sn66a
+.section sn66b
+.section sn67a
+.section sn67b
+.section sn68a
+.section sn68b
+.section sn69a
+.section sn69b
+.section sn60a
+.section sn60b
+.section sn7aa
+.section sn7ab
+.section sn7ba
+.section sn7bb
+.section sn7ca
+.section sn7cb
+.section sn7da
+.section sn7db
+.section sn7ea
+.section sn7eb
+.section sn7fa
+.section sn7fb
+.section sn7ga
+.section sn7gb
+.section sn7ha
+.section sn7hb
+.section sn7ia
+.section sn7ib
+.section sn7ja
+.section sn7jb
+.section sn7ka
+.section sn7kb
+.section sn7la
+.section sn7lb
+.section sn7ma
+.section sn7mb
+.section sn7na
+.section sn7nb
+.section sn7oa
+.section sn7ob
+.section sn7pa
+.section sn7pb
+.section sn7qa
+.section sn7qb
+.section sn7ra
+.section sn7rb
+.section sn7sa
+.section sn7sb
+.section sn7ta
+.section sn7tb
+.section sn7ua
+.section sn7ub
+.section sn7va
+.section sn7vb
+.section sn7wa
+.section sn7wb
+.section sn7xa
+.section sn7xb
+.section sn7ya
+.section sn7yb
+.section sn7za
+.section sn7zb
+.section sn71a
+.section sn71b
+.section sn72a
+.section sn72b
+.section sn73a
+.section sn73b
+.section sn74a
+.section sn74b
+.section sn75a
+.section sn75b
+.section sn76a
+.section sn76b
+.section sn77a
+.section sn77b
+.section sn78a
+.section sn78b
+.section sn79a
+.section sn79b
+.section sn70a
+.section sn70b
+.section sn8aa
+.section sn8ab
+.section sn8ba
+.section sn8bb
+.section sn8ca
+.section sn8cb
+.section sn8da
+.section sn8db
+.section sn8ea
+.section sn8eb
+.section sn8fa
+.section sn8fb
+.section sn8ga
+.section sn8gb
+.section sn8ha
+.section sn8hb
+.section sn8ia
+.section sn8ib
+.section sn8ja
+.section sn8jb
+.section sn8ka
+.section sn8kb
+.section sn8la
+.section sn8lb
+.section sn8ma
+.section sn8mb
+.section sn8na
+.section sn8nb
+.section sn8oa
+.section sn8ob
+.section sn8pa
+.section sn8pb
+.section sn8qa
+.section sn8qb
+.section sn8ra
+.section sn8rb
+.section sn8sa
+.section sn8sb
+.section sn8ta
+.section sn8tb
+.section sn8ua
+.section sn8ub
+.section sn8va
+.section sn8vb
+.section sn8wa
+.section sn8wb
+.section sn8xa
+.section sn8xb
+.section sn8ya
+.section sn8yb
+.section sn8za
+.section sn8zb
+.section sn81a
+.section sn81b
+.section sn82a
+.section sn82b
+.section sn83a
+.section sn83b
+.section sn84a
+.section sn84b
+.section sn85a
+.section sn85b
+.section sn86a
+.section sn86b
+.section sn87a
+.section sn87b
+.section sn88a
+.section sn88b
+.section sn89a
+.section sn89b
+.section sn80a
+.section sn80b
+.section sn9aa
+.section sn9ab
+.section sn9ba
+.section sn9bb
+.section sn9ca
+.section sn9cb
+.section sn9da
+.section sn9db
+.section sn9ea
+.section sn9eb
+.section sn9fa
+.section sn9fb
+.section sn9ga
+.section sn9gb
+.section sn9ha
+.section sn9hb
+.section sn9ia
+.section sn9ib
+.section sn9ja
+.section sn9jb
+.section sn9ka
+.section sn9kb
+.section sn9la
+.section sn9lb
+.section sn9ma
+.section sn9mb
+.section sn9na
+.section sn9nb
+.section sn9oa
+.section sn9ob
+.section sn9pa
+.section sn9pb
+.section sn9qa
+.section sn9qb
+.section sn9ra
+.section sn9rb
+.section sn9sa
+.section sn9sb
+.section sn9ta
+.section sn9tb
+.section sn9ua
+.section sn9ub
+.section sn9va
+.section sn9vb
+.section sn9wa
+.section sn9wb
+.section sn9xa
+.section sn9xb
+.section sn9ya
+.section sn9yb
+.section sn9za
+.section sn9zb
+.section sn91a
+.section sn91b
+.section sn92a
+.section sn92b
+.section sn93a
+.section sn93b
+.section sn94a
+.section sn94b
+.section sn95a
+.section sn95b
+.section sn96a
+.section sn96b
+.section sn97a
+.section sn97b
+.section sn98a
+.section sn98b
+.section sn99a
+.section sn99b
+.section sn90a
+.section sn90b
+.section sn0aa
+.section sn0ab
+.section sn0ba
+.section sn0bb
+.section sn0ca
+.section sn0cb
+.section sn0da
+.section sn0db
+.section sn0ea
+.section sn0eb
+.section sn0fa
+.section sn0fb
+.section sn0ga
+.section sn0gb
+.section sn0ha
+.section sn0hb
+.section sn0ia
+.section sn0ib
+.section sn0ja
+.section sn0jb
+.section sn0ka
+.section sn0kb
+.section sn0la
+.section sn0lb
+.section sn0ma
+.section sn0mb
+.section sn0na
+.section sn0nb
+.section sn0oa
+.section sn0ob
+.section sn0pa
+.section sn0pb
+.section sn0qa
+.section sn0qb
+.section sn0ra
+.section sn0rb
+.section sn0sa
+.section sn0sb
+.section sn0ta
+.section sn0tb
+.section sn0ua
+.section sn0ub
+.section sn0va
+.section sn0vb
+.section sn0wa
+.section sn0wb
+.section sn0xa
+.section sn0xb
+.section sn0ya
+.section sn0yb
+.section sn0za
+.section sn0zb
+.section sn01a
+.section sn01b
+.section sn02a
+.section sn02b
+.section sn03a
+.section sn03b
+.section sn04a
+.section sn04b
+.section sn05a
+.section sn05b
+.section sn06a
+.section sn06b
+.section sn07a
+.section sn07b
+.section sn08a
+.section sn08b
+.section sn09a
+.section sn09b
+.section sn00a
+.section sn00b
+.section soaaa
+.section soaab
+.section soaba
+.section soabb
+.section soaca
+.section soacb
+.section soada
+.section soadb
+.section soaea
+.section soaeb
+.section soafa
+.section soafb
+.section soaga
+.section soagb
+.section soaha
+.section soahb
+.section soaia
+.section soaib
+.section soaja
+.section soajb
+.section soaka
+.section soakb
+.section soala
+.section soalb
+.section soama
+.section soamb
+.section soana
+.section soanb
+.section soaoa
+.section soaob
+.section soapa
+.section soapb
+.section soaqa
+.section soaqb
+.section soara
+.section soarb
+.section soasa
+.section soasb
+.section soata
+.section soatb
+.section soaua
+.section soaub
+.section soava
+.section soavb
+.section soawa
+.section soawb
+.section soaxa
+.section soaxb
+.section soaya
+.section soayb
+.section soaza
+.section soazb
+.section soa1a
+.section soa1b
+.section soa2a
+.section soa2b
+.section soa3a
+.section soa3b
+.section soa4a
+.section soa4b
+.section soa5a
+.section soa5b
+.section soa6a
+.section soa6b
+.section soa7a
+.section soa7b
+.section soa8a
+.section soa8b
+.section soa9a
+.section soa9b
+.section soa0a
+.section soa0b
+.section sobaa
+.section sobab
+.section sobba
+.section sobbb
+.section sobca
+.section sobcb
+.section sobda
+.section sobdb
+.section sobea
+.section sobeb
+.section sobfa
+.section sobfb
+.section sobga
+.section sobgb
+.section sobha
+.section sobhb
+.section sobia
+.section sobib
+.section sobja
+.section sobjb
+.section sobka
+.section sobkb
+.section sobla
+.section soblb
+.section sobma
+.section sobmb
+.section sobna
+.section sobnb
+.section soboa
+.section sobob
+.section sobpa
+.section sobpb
+.section sobqa
+.section sobqb
+.section sobra
+.section sobrb
+.section sobsa
+.section sobsb
+.section sobta
+.section sobtb
+.section sobua
+.section sobub
+.section sobva
+.section sobvb
+.section sobwa
+.section sobwb
+.section sobxa
+.section sobxb
+.section sobya
+.section sobyb
+.section sobza
+.section sobzb
+.section sob1a
+.section sob1b
+.section sob2a
+.section sob2b
+.section sob3a
+.section sob3b
+.section sob4a
+.section sob4b
+.section sob5a
+.section sob5b
+.section sob6a
+.section sob6b
+.section sob7a
+.section sob7b
+.section sob8a
+.section sob8b
+.section sob9a
+.section sob9b
+.section sob0a
+.section sob0b
+.section socaa
+.section socab
+.section socba
+.section socbb
+.section socca
+.section soccb
+.section socda
+.section socdb
+.section socea
+.section soceb
+.section socfa
+.section socfb
+.section socga
+.section socgb
+.section socha
+.section sochb
+.section socia
+.section socib
+.section socja
+.section socjb
+.section socka
+.section sockb
+.section socla
+.section soclb
+.section socma
+.section socmb
+.section socna
+.section socnb
+.section socoa
+.section socob
+.section socpa
+.section socpb
+.section socqa
+.section socqb
+.section socra
+.section socrb
+.section socsa
+.section socsb
+.section socta
+.section soctb
+.section socua
+.section socub
+.section socva
+.section socvb
+.section socwa
+.section socwb
+.section socxa
+.section socxb
+.section socya
+.section socyb
+.section socza
+.section soczb
+.section soc1a
+.section soc1b
+.section soc2a
+.section soc2b
+.section soc3a
+.section soc3b
+.section soc4a
+.section soc4b
+.section soc5a
+.section soc5b
+.section soc6a
+.section soc6b
+.section soc7a
+.section soc7b
+.section soc8a
+.section soc8b
+.section soc9a
+.section soc9b
+.section soc0a
+.section soc0b
+.section sodaa
+.section sodab
+.section sodba
+.section sodbb
+.section sodca
+.section sodcb
+.section sodda
+.section soddb
+.section sodea
+.section sodeb
+.section sodfa
+.section sodfb
+.section sodga
+.section sodgb
+.section sodha
+.section sodhb
+.section sodia
+.section sodib
+.section sodja
+.section sodjb
+.section sodka
+.section sodkb
+.section sodla
+.section sodlb
+.section sodma
+.section sodmb
+.section sodna
+.section sodnb
+.section sodoa
+.section sodob
+.section sodpa
+.section sodpb
+.section sodqa
+.section sodqb
+.section sodra
+.section sodrb
+.section sodsa
+.section sodsb
+.section sodta
+.section sodtb
+.section sodua
+.section sodub
+.section sodva
+.section sodvb
+.section sodwa
+.section sodwb
+.section sodxa
+.section sodxb
+.section sodya
+.section sodyb
+.section sodza
+.section sodzb
+.section sod1a
+.section sod1b
+.section sod2a
+.section sod2b
+.section sod3a
+.section sod3b
+.section sod4a
+.section sod4b
+.section sod5a
+.section sod5b
+.section sod6a
+.section sod6b
+.section sod7a
+.section sod7b
+.section sod8a
+.section sod8b
+.section sod9a
+.section sod9b
+.section sod0a
+.section sod0b
+.section soeaa
+.section soeab
+.section soeba
+.section soebb
+.section soeca
+.section soecb
+.section soeda
+.section soedb
+.section soeea
+.section soeeb
+.section soefa
+.section soefb
+.section soega
+.section soegb
+.section soeha
+.section soehb
+.section soeia
+.section soeib
+.section soeja
+.section soejb
+.section soeka
+.section soekb
+.section soela
+.section soelb
+.section soema
+.section soemb
+.section soena
+.section soenb
+.section soeoa
+.section soeob
+.section soepa
+.section soepb
+.section soeqa
+.section soeqb
+.section soera
+.section soerb
+.section soesa
+.section soesb
+.section soeta
+.section soetb
+.section soeua
+.section soeub
+.section soeva
+.section soevb
+.section soewa
+.section soewb
+.section soexa
+.section soexb
+.section soeya
+.section soeyb
+.section soeza
+.section soezb
+.section soe1a
+.section soe1b
+.section soe2a
+.section soe2b
+.section soe3a
+.section soe3b
+.section soe4a
+.section soe4b
+.section soe5a
+.section soe5b
+.section soe6a
+.section soe6b
+.section soe7a
+.section soe7b
+.section soe8a
+.section soe8b
+.section soe9a
+.section soe9b
+.section soe0a
+.section soe0b
+.section sofaa
+.section sofab
+.section sofba
+.section sofbb
+.section sofca
+.section sofcb
+.section sofda
+.section sofdb
+.section sofea
+.section sofeb
+.section soffa
+.section soffb
+.section sofga
+.section sofgb
+.section sofha
+.section sofhb
+.section sofia
+.section sofib
+.section sofja
+.section sofjb
+.section sofka
+.section sofkb
+.section sofla
+.section soflb
+.section sofma
+.section sofmb
+.section sofna
+.section sofnb
+.section sofoa
+.section sofob
+.section sofpa
+.section sofpb
+.section sofqa
+.section sofqb
+.section sofra
+.section sofrb
+.section sofsa
+.section sofsb
+.section softa
+.section softb
+.section sofua
+.section sofub
+.section sofva
+.section sofvb
+.section sofwa
+.section sofwb
+.section sofxa
+.section sofxb
+.section sofya
+.section sofyb
+.section sofza
+.section sofzb
+.section sof1a
+.section sof1b
+.section sof2a
+.section sof2b
+.section sof3a
+.section sof3b
+.section sof4a
+.section sof4b
+.section sof5a
+.section sof5b
+.section sof6a
+.section sof6b
+.section sof7a
+.section sof7b
+.section sof8a
+.section sof8b
+.section sof9a
+.section sof9b
+.section sof0a
+.section sof0b
+.section sogaa
+.section sogab
+.section sogba
+.section sogbb
+.section sogca
+.section sogcb
+.section sogda
+.section sogdb
+.section sogea
+.section sogeb
+.section sogfa
+.section sogfb
+.section sogga
+.section soggb
+.section sogha
+.section soghb
+.section sogia
+.section sogib
+.section sogja
+.section sogjb
+.section sogka
+.section sogkb
+.section sogla
+.section soglb
+.section sogma
+.section sogmb
+.section sogna
+.section sognb
+.section sogoa
+.section sogob
+.section sogpa
+.section sogpb
+.section sogqa
+.section sogqb
+.section sogra
+.section sogrb
+.section sogsa
+.section sogsb
+.section sogta
+.section sogtb
+.section sogua
+.section sogub
+.section sogva
+.section sogvb
+.section sogwa
+.section sogwb
+.section sogxa
+.section sogxb
+.section sogya
+.section sogyb
+.section sogza
+.section sogzb
+.section sog1a
+.section sog1b
+.section sog2a
+.section sog2b
+.section sog3a
+.section sog3b
+.section sog4a
+.section sog4b
+.section sog5a
+.section sog5b
+.section sog6a
+.section sog6b
+.section sog7a
+.section sog7b
+.section sog8a
+.section sog8b
+.section sog9a
+.section sog9b
+.section sog0a
+.section sog0b
+.section sohaa
+.section sohab
+.section sohba
+.section sohbb
+.section sohca
+.section sohcb
+.section sohda
+.section sohdb
+.section sohea
+.section soheb
+.section sohfa
+.section sohfb
+.section sohga
+.section sohgb
+.section sohha
+.section sohhb
+.section sohia
+.section sohib
+.section sohja
+.section sohjb
+.section sohka
+.section sohkb
+.section sohla
+.section sohlb
+.section sohma
+.section sohmb
+.section sohna
+.section sohnb
+.section sohoa
+.section sohob
+.section sohpa
+.section sohpb
+.section sohqa
+.section sohqb
+.section sohra
+.section sohrb
+.section sohsa
+.section sohsb
+.section sohta
+.section sohtb
+.section sohua
+.section sohub
+.section sohva
+.section sohvb
+.section sohwa
+.section sohwb
+.section sohxa
+.section sohxb
+.section sohya
+.section sohyb
+.section sohza
+.section sohzb
+.section soh1a
+.section soh1b
+.section soh2a
+.section soh2b
+.section soh3a
+.section soh3b
+.section soh4a
+.section soh4b
+.section soh5a
+.section soh5b
+.section soh6a
+.section soh6b
+.section soh7a
+.section soh7b
+.section soh8a
+.section soh8b
+.section soh9a
+.section soh9b
+.section soh0a
+.section soh0b
+.section soiaa
+.section soiab
+.section soiba
+.section soibb
+.section soica
+.section soicb
+.section soida
+.section soidb
+.section soiea
+.section soieb
+.section soifa
+.section soifb
+.section soiga
+.section soigb
+.section soiha
+.section soihb
+.section soiia
+.section soiib
+.section soija
+.section soijb
+.section soika
+.section soikb
+.section soila
+.section soilb
+.section soima
+.section soimb
+.section soina
+.section soinb
+.section soioa
+.section soiob
+.section soipa
+.section soipb
+.section soiqa
+.section soiqb
+.section soira
+.section soirb
+.section soisa
+.section soisb
+.section soita
+.section soitb
+.section soiua
+.section soiub
+.section soiva
+.section soivb
+.section soiwa
+.section soiwb
+.section soixa
+.section soixb
+.section soiya
+.section soiyb
+.section soiza
+.section soizb
+.section soi1a
+.section soi1b
+.section soi2a
+.section soi2b
+.section soi3a
+.section soi3b
+.section soi4a
+.section soi4b
+.section soi5a
+.section soi5b
+.section soi6a
+.section soi6b
+.section soi7a
+.section soi7b
+.section soi8a
+.section soi8b
+.section soi9a
+.section soi9b
+.section soi0a
+.section soi0b
+.section sojaa
+.section sojab
+.section sojba
+.section sojbb
+.section sojca
+.section sojcb
+.section sojda
+.section sojdb
+.section sojea
+.section sojeb
+.section sojfa
+.section sojfb
+.section sojga
+.section sojgb
+.section sojha
+.section sojhb
+.section sojia
+.section sojib
+.section sojja
+.section sojjb
+.section sojka
+.section sojkb
+.section sojla
+.section sojlb
+.section sojma
+.section sojmb
+.section sojna
+.section sojnb
+.section sojoa
+.section sojob
+.section sojpa
+.section sojpb
+.section sojqa
+.section sojqb
+.section sojra
+.section sojrb
+.section sojsa
+.section sojsb
+.section sojta
+.section sojtb
+.section sojua
+.section sojub
+.section sojva
+.section sojvb
+.section sojwa
+.section sojwb
+.section sojxa
+.section sojxb
+.section sojya
+.section sojyb
+.section sojza
+.section sojzb
+.section soj1a
+.section soj1b
+.section soj2a
+.section soj2b
+.section soj3a
+.section soj3b
+.section soj4a
+.section soj4b
+.section soj5a
+.section soj5b
+.section soj6a
+.section soj6b
+.section soj7a
+.section soj7b
+.section soj8a
+.section soj8b
+.section soj9a
+.section soj9b
+.section soj0a
+.section soj0b
+.section sokaa
+.section sokab
+.section sokba
+.section sokbb
+.section sokca
+.section sokcb
+.section sokda
+.section sokdb
+.section sokea
+.section sokeb
+.section sokfa
+.section sokfb
+.section sokga
+.section sokgb
+.section sokha
+.section sokhb
+.section sokia
+.section sokib
+.section sokja
+.section sokjb
+.section sokka
+.section sokkb
+.section sokla
+.section soklb
+.section sokma
+.section sokmb
+.section sokna
+.section soknb
+.section sokoa
+.section sokob
+.section sokpa
+.section sokpb
+.section sokqa
+.section sokqb
+.section sokra
+.section sokrb
+.section soksa
+.section soksb
+.section sokta
+.section soktb
+.section sokua
+.section sokub
+.section sokva
+.section sokvb
+.section sokwa
+.section sokwb
+.section sokxa
+.section sokxb
+.section sokya
+.section sokyb
+.section sokza
+.section sokzb
+.section sok1a
+.section sok1b
+.section sok2a
+.section sok2b
+.section sok3a
+.section sok3b
+.section sok4a
+.section sok4b
+.section sok5a
+.section sok5b
+.section sok6a
+.section sok6b
+.section sok7a
+.section sok7b
+.section sok8a
+.section sok8b
+.section sok9a
+.section sok9b
+.section sok0a
+.section sok0b
+.section solaa
+.section solab
+.section solba
+.section solbb
+.section solca
+.section solcb
+.section solda
+.section soldb
+.section solea
+.section soleb
+.section solfa
+.section solfb
+.section solga
+.section solgb
+.section solha
+.section solhb
+.section solia
+.section solib
+.section solja
+.section soljb
+.section solka
+.section solkb
+.section solla
+.section sollb
+.section solma
+.section solmb
+.section solna
+.section solnb
+.section soloa
+.section solob
+.section solpa
+.section solpb
+.section solqa
+.section solqb
+.section solra
+.section solrb
+.section solsa
+.section solsb
+.section solta
+.section soltb
+.section solua
+.section solub
+.section solva
+.section solvb
+.section solwa
+.section solwb
+.section solxa
+.section solxb
+.section solya
+.section solyb
+.section solza
+.section solzb
+.section sol1a
+.section sol1b
+.section sol2a
+.section sol2b
+.section sol3a
+.section sol3b
+.section sol4a
+.section sol4b
+.section sol5a
+.section sol5b
+.section sol6a
+.section sol6b
+.section sol7a
+.section sol7b
+.section sol8a
+.section sol8b
+.section sol9a
+.section sol9b
+.section sol0a
+.section sol0b
+.section somaa
+.section somab
+.section somba
+.section sombb
+.section somca
+.section somcb
+.section somda
+.section somdb
+.section somea
+.section someb
+.section somfa
+.section somfb
+.section somga
+.section somgb
+.section somha
+.section somhb
+.section somia
+.section somib
+.section somja
+.section somjb
+.section somka
+.section somkb
+.section somla
+.section somlb
+.section somma
+.section sommb
+.section somna
+.section somnb
+.section somoa
+.section somob
+.section sompa
+.section sompb
+.section somqa
+.section somqb
+.section somra
+.section somrb
+.section somsa
+.section somsb
+.section somta
+.section somtb
+.section somua
+.section somub
+.section somva
+.section somvb
+.section somwa
+.section somwb
+.section somxa
+.section somxb
+.section somya
+.section somyb
+.section somza
+.section somzb
+.section som1a
+.section som1b
+.section som2a
+.section som2b
+.section som3a
+.section som3b
+.section som4a
+.section som4b
+.section som5a
+.section som5b
+.section som6a
+.section som6b
+.section som7a
+.section som7b
+.section som8a
+.section som8b
+.section som9a
+.section som9b
+.section som0a
+.section som0b
+.section sonaa
+.section sonab
+.section sonba
+.section sonbb
+.section sonca
+.section soncb
+.section sonda
+.section sondb
+.section sonea
+.section soneb
+.section sonfa
+.section sonfb
+.section songa
+.section songb
+.section sonha
+.section sonhb
+.section sonia
+.section sonib
+.section sonja
+.section sonjb
+.section sonka
+.section sonkb
+.section sonla
+.section sonlb
+.section sonma
+.section sonmb
+.section sonna
+.section sonnb
+.section sonoa
+.section sonob
+.section sonpa
+.section sonpb
+.section sonqa
+.section sonqb
+.section sonra
+.section sonrb
+.section sonsa
+.section sonsb
+.section sonta
+.section sontb
+.section sonua
+.section sonub
+.section sonva
+.section sonvb
+.section sonwa
+.section sonwb
+.section sonxa
+.section sonxb
+.section sonya
+.section sonyb
+.section sonza
+.section sonzb
+.section son1a
+.section son1b
+.section son2a
+.section son2b
+.section son3a
+.section son3b
+.section son4a
+.section son4b
+.section son5a
+.section son5b
+.section son6a
+.section son6b
+.section son7a
+.section son7b
+.section son8a
+.section son8b
+.section son9a
+.section son9b
+.section son0a
+.section son0b
+.section sooaa
+.section sooab
+.section sooba
+.section soobb
+.section sooca
+.section soocb
+.section sooda
+.section soodb
+.section sooea
+.section sooeb
+.section soofa
+.section soofb
+.section sooga
+.section soogb
+.section sooha
+.section soohb
+.section sooia
+.section sooib
+.section sooja
+.section soojb
+.section sooka
+.section sookb
+.section soola
+.section soolb
+.section sooma
+.section soomb
+.section soona
+.section soonb
+.section soooa
+.section sooob
+.section soopa
+.section soopb
+.section sooqa
+.section sooqb
+.section soora
+.section soorb
+.section soosa
+.section soosb
+.section soota
+.section sootb
+.section sooua
+.section sooub
+.section soova
+.section soovb
+.section soowa
+.section soowb
+.section sooxa
+.section sooxb
+.section sooya
+.section sooyb
+.section sooza
+.section soozb
+.section soo1a
+.section soo1b
+.section soo2a
+.section soo2b
+.section soo3a
+.section soo3b
+.section soo4a
+.section soo4b
+.section soo5a
+.section soo5b
+.section soo6a
+.section soo6b
+.section soo7a
+.section soo7b
+.section soo8a
+.section soo8b
+.section soo9a
+.section soo9b
+.section soo0a
+.section soo0b
+.section sopaa
+.section sopab
+.section sopba
+.section sopbb
+.section sopca
+.section sopcb
+.section sopda
+.section sopdb
+.section sopea
+.section sopeb
+.section sopfa
+.section sopfb
+.section sopga
+.section sopgb
+.section sopha
+.section sophb
+.section sopia
+.section sopib
+.section sopja
+.section sopjb
+.section sopka
+.section sopkb
+.section sopla
+.section soplb
+.section sopma
+.section sopmb
+.section sopna
+.section sopnb
+.section sopoa
+.section sopob
+.section soppa
+.section soppb
+.section sopqa
+.section sopqb
+.section sopra
+.section soprb
+.section sopsa
+.section sopsb
+.section sopta
+.section soptb
+.section sopua
+.section sopub
+.section sopva
+.section sopvb
+.section sopwa
+.section sopwb
+.section sopxa
+.section sopxb
+.section sopya
+.section sopyb
+.section sopza
+.section sopzb
+.section sop1a
+.section sop1b
+.section sop2a
+.section sop2b
+.section sop3a
+.section sop3b
+.section sop4a
+.section sop4b
+.section sop5a
+.section sop5b
+.section sop6a
+.section sop6b
+.section sop7a
+.section sop7b
+.section sop8a
+.section sop8b
+.section sop9a
+.section sop9b
+.section sop0a
+.section sop0b
+.section soqaa
+.section soqab
+.section soqba
+.section soqbb
+.section soqca
+.section soqcb
+.section soqda
+.section soqdb
+.section soqea
+.section soqeb
+.section soqfa
+.section soqfb
+.section soqga
+.section soqgb
+.section soqha
+.section soqhb
+.section soqia
+.section soqib
+.section soqja
+.section soqjb
+.section soqka
+.section soqkb
+.section soqla
+.section soqlb
+.section soqma
+.section soqmb
+.section soqna
+.section soqnb
+.section soqoa
+.section soqob
+.section soqpa
+.section soqpb
+.section soqqa
+.section soqqb
+.section soqra
+.section soqrb
+.section soqsa
+.section soqsb
+.section soqta
+.section soqtb
+.section soqua
+.section soqub
+.section soqva
+.section soqvb
+.section soqwa
+.section soqwb
+.section soqxa
+.section soqxb
+.section soqya
+.section soqyb
+.section soqza
+.section soqzb
+.section soq1a
+.section soq1b
+.section soq2a
+.section soq2b
+.section soq3a
+.section soq3b
+.section soq4a
+.section soq4b
+.section soq5a
+.section soq5b
+.section soq6a
+.section soq6b
+.section soq7a
+.section soq7b
+.section soq8a
+.section soq8b
+.section soq9a
+.section soq9b
+.section soq0a
+.section soq0b
+.section soraa
+.section sorab
+.section sorba
+.section sorbb
+.section sorca
+.section sorcb
+.section sorda
+.section sordb
+.section sorea
+.section soreb
+.section sorfa
+.section sorfb
+.section sorga
+.section sorgb
+.section sorha
+.section sorhb
+.section soria
+.section sorib
+.section sorja
+.section sorjb
+.section sorka
+.section sorkb
+.section sorla
+.section sorlb
+.section sorma
+.section sormb
+.section sorna
+.section sornb
+.section soroa
+.section sorob
+.section sorpa
+.section sorpb
+.section sorqa
+.section sorqb
+.section sorra
+.section sorrb
+.section sorsa
+.section sorsb
+.section sorta
+.section sortb
+.section sorua
+.section sorub
+.section sorva
+.section sorvb
+.section sorwa
+.section sorwb
+.section sorxa
+.section sorxb
+.section sorya
+.section soryb
+.section sorza
+.section sorzb
+.section sor1a
+.section sor1b
+.section sor2a
+.section sor2b
+.section sor3a
+.section sor3b
+.section sor4a
+.section sor4b
+.section sor5a
+.section sor5b
+.section sor6a
+.section sor6b
+.section sor7a
+.section sor7b
+.section sor8a
+.section sor8b
+.section sor9a
+.section sor9b
+.section sor0a
+.section sor0b
+.section sosaa
+.section sosab
+.section sosba
+.section sosbb
+.section sosca
+.section soscb
+.section sosda
+.section sosdb
+.section sosea
+.section soseb
+.section sosfa
+.section sosfb
+.section sosga
+.section sosgb
+.section sosha
+.section soshb
+.section sosia
+.section sosib
+.section sosja
+.section sosjb
+.section soska
+.section soskb
+.section sosla
+.section soslb
+.section sosma
+.section sosmb
+.section sosna
+.section sosnb
+.section sosoa
+.section sosob
+.section sospa
+.section sospb
+.section sosqa
+.section sosqb
+.section sosra
+.section sosrb
+.section sossa
+.section sossb
+.section sosta
+.section sostb
+.section sosua
+.section sosub
+.section sosva
+.section sosvb
+.section soswa
+.section soswb
+.section sosxa
+.section sosxb
+.section sosya
+.section sosyb
+.section sosza
+.section soszb
+.section sos1a
+.section sos1b
+.section sos2a
+.section sos2b
+.section sos3a
+.section sos3b
+.section sos4a
+.section sos4b
+.section sos5a
+.section sos5b
+.section sos6a
+.section sos6b
+.section sos7a
+.section sos7b
+.section sos8a
+.section sos8b
+.section sos9a
+.section sos9b
+.section sos0a
+.section sos0b
+.section sotaa
+.section sotab
+.section sotba
+.section sotbb
+.section sotca
+.section sotcb
+.section sotda
+.section sotdb
+.section sotea
+.section soteb
+.section sotfa
+.section sotfb
+.section sotga
+.section sotgb
+.section sotha
+.section sothb
+.section sotia
+.section sotib
+.section sotja
+.section sotjb
+.section sotka
+.section sotkb
+.section sotla
+.section sotlb
+.section sotma
+.section sotmb
+.section sotna
+.section sotnb
+.section sotoa
+.section sotob
+.section sotpa
+.section sotpb
+.section sotqa
+.section sotqb
+.section sotra
+.section sotrb
+.section sotsa
+.section sotsb
+.section sotta
+.section sottb
+.section sotua
+.section sotub
+.section sotva
+.section sotvb
+.section sotwa
+.section sotwb
+.section sotxa
+.section sotxb
+.section sotya
+.section sotyb
+.section sotza
+.section sotzb
+.section sot1a
+.section sot1b
+.section sot2a
+.section sot2b
+.section sot3a
+.section sot3b
+.section sot4a
+.section sot4b
+.section sot5a
+.section sot5b
+.section sot6a
+.section sot6b
+.section sot7a
+.section sot7b
+.section sot8a
+.section sot8b
+.section sot9a
+.section sot9b
+.section sot0a
+.section sot0b
+.section souaa
+.section souab
+.section souba
+.section soubb
+.section souca
+.section soucb
+.section souda
+.section soudb
+.section souea
+.section soueb
+.section soufa
+.section soufb
+.section souga
+.section sougb
+.section souha
+.section souhb
+.section souia
+.section souib
+.section souja
+.section soujb
+.section souka
+.section soukb
+.section soula
+.section soulb
+.section souma
+.section soumb
+.section souna
+.section sounb
+.section souoa
+.section souob
+.section soupa
+.section soupb
+.section souqa
+.section souqb
+.section soura
+.section sourb
+.section sousa
+.section sousb
+.section souta
+.section soutb
+.section souua
+.section souub
+.section souva
+.section souvb
+.section souwa
+.section souwb
+.section souxa
+.section souxb
+.section souya
+.section souyb
+.section souza
+.section souzb
+.section sou1a
+.section sou1b
+.section sou2a
+.section sou2b
+.section sou3a
+.section sou3b
+.section sou4a
+.section sou4b
+.section sou5a
+.section sou5b
+.section sou6a
+.section sou6b
+.section sou7a
+.section sou7b
+.section sou8a
+.section sou8b
+.section sou9a
+.section sou9b
+.section sou0a
+.section sou0b
+.section sovaa
+.section sovab
+.section sovba
+.section sovbb
+.section sovca
+.section sovcb
+.section sovda
+.section sovdb
+.section sovea
+.section soveb
+.section sovfa
+.section sovfb
+.section sovga
+.section sovgb
+.section sovha
+.section sovhb
+.section sovia
+.section sovib
+.section sovja
+.section sovjb
+.section sovka
+.section sovkb
+.section sovla
+.section sovlb
+.section sovma
+.section sovmb
+.section sovna
+.section sovnb
+.section sovoa
+.section sovob
+.section sovpa
+.section sovpb
+.section sovqa
+.section sovqb
+.section sovra
+.section sovrb
+.section sovsa
+.section sovsb
+.section sovta
+.section sovtb
+.section sovua
+.section sovub
+.section sovva
+.section sovvb
+.section sovwa
+.section sovwb
+.section sovxa
+.section sovxb
+.section sovya
+.section sovyb
+.section sovza
+.section sovzb
+.section sov1a
+.section sov1b
+.section sov2a
+.section sov2b
+.section sov3a
+.section sov3b
+.section sov4a
+.section sov4b
+.section sov5a
+.section sov5b
+.section sov6a
+.section sov6b
+.section sov7a
+.section sov7b
+.section sov8a
+.section sov8b
+.section sov9a
+.section sov9b
+.section sov0a
+.section sov0b
+.section sowaa
+.section sowab
+.section sowba
+.section sowbb
+.section sowca
+.section sowcb
+.section sowda
+.section sowdb
+.section sowea
+.section soweb
+.section sowfa
+.section sowfb
+.section sowga
+.section sowgb
+.section sowha
+.section sowhb
+.section sowia
+.section sowib
+.section sowja
+.section sowjb
+.section sowka
+.section sowkb
+.section sowla
+.section sowlb
+.section sowma
+.section sowmb
+.section sowna
+.section sownb
+.section sowoa
+.section sowob
+.section sowpa
+.section sowpb
+.section sowqa
+.section sowqb
+.section sowra
+.section sowrb
+.section sowsa
+.section sowsb
+.section sowta
+.section sowtb
+.section sowua
+.section sowub
+.section sowva
+.section sowvb
+.section sowwa
+.section sowwb
+.section sowxa
+.section sowxb
+.section sowya
+.section sowyb
+.section sowza
+.section sowzb
+.section sow1a
+.section sow1b
+.section sow2a
+.section sow2b
+.section sow3a
+.section sow3b
+.section sow4a
+.section sow4b
+.section sow5a
+.section sow5b
+.section sow6a
+.section sow6b
+.section sow7a
+.section sow7b
+.section sow8a
+.section sow8b
+.section sow9a
+.section sow9b
+.section sow0a
+.section sow0b
+.section soxaa
+.section soxab
+.section soxba
+.section soxbb
+.section soxca
+.section soxcb
+.section soxda
+.section soxdb
+.section soxea
+.section soxeb
+.section soxfa
+.section soxfb
+.section soxga
+.section soxgb
+.section soxha
+.section soxhb
+.section soxia
+.section soxib
+.section soxja
+.section soxjb
+.section soxka
+.section soxkb
+.section soxla
+.section soxlb
+.section soxma
+.section soxmb
+.section soxna
+.section soxnb
+.section soxoa
+.section soxob
+.section soxpa
+.section soxpb
+.section soxqa
+.section soxqb
+.section soxra
+.section soxrb
+.section soxsa
+.section soxsb
+.section soxta
+.section soxtb
+.section soxua
+.section soxub
+.section soxva
+.section soxvb
+.section soxwa
+.section soxwb
+.section soxxa
+.section soxxb
+.section soxya
+.section soxyb
+.section soxza
+.section soxzb
+.section sox1a
+.section sox1b
+.section sox2a
+.section sox2b
+.section sox3a
+.section sox3b
+.section sox4a
+.section sox4b
+.section sox5a
+.section sox5b
+.section sox6a
+.section sox6b
+.section sox7a
+.section sox7b
+.section sox8a
+.section sox8b
+.section sox9a
+.section sox9b
+.section sox0a
+.section sox0b
+.section soyaa
+.section soyab
+.section soyba
+.section soybb
+.section soyca
+.section soycb
+.section soyda
+.section soydb
+.section soyea
+.section soyeb
+.section soyfa
+.section soyfb
+.section soyga
+.section soygb
+.section soyha
+.section soyhb
+.section soyia
+.section soyib
+.section soyja
+.section soyjb
+.section soyka
+.section soykb
+.section soyla
+.section soylb
+.section soyma
+.section soymb
+.section soyna
+.section soynb
+.section soyoa
+.section soyob
+.section soypa
+.section soypb
+.section soyqa
+.section soyqb
+.section soyra
+.section soyrb
+.section soysa
+.section soysb
+.section soyta
+.section soytb
+.section soyua
+.section soyub
+.section soyva
+.section soyvb
+.section soywa
+.section soywb
+.section soyxa
+.section soyxb
+.section soyya
+.section soyyb
+.section soyza
+.section soyzb
+.section soy1a
+.section soy1b
+.section soy2a
+.section soy2b
+.section soy3a
+.section soy3b
+.section soy4a
+.section soy4b
+.section soy5a
+.section soy5b
+.section soy6a
+.section soy6b
+.section soy7a
+.section soy7b
+.section soy8a
+.section soy8b
+.section soy9a
+.section soy9b
+.section soy0a
+.section soy0b
+.section sozaa
+.section sozab
+.section sozba
+.section sozbb
+.section sozca
+.section sozcb
+.section sozda
+.section sozdb
+.section sozea
+.section sozeb
+.section sozfa
+.section sozfb
+.section sozga
+.section sozgb
+.section sozha
+.section sozhb
+.section sozia
+.section sozib
+.section sozja
+.section sozjb
+.section sozka
+.section sozkb
+.section sozla
+.section sozlb
+.section sozma
+.section sozmb
+.section sozna
+.section soznb
+.section sozoa
+.section sozob
+.section sozpa
+.section sozpb
+.section sozqa
+.section sozqb
+.section sozra
+.section sozrb
+.section sozsa
+.section sozsb
+.section sozta
+.section soztb
+.section sozua
+.section sozub
+.section sozva
+.section sozvb
+.section sozwa
+.section sozwb
+.section sozxa
+.section sozxb
+.section sozya
+.section sozyb
+.section sozza
+.section sozzb
+.section soz1a
+.section soz1b
+.section soz2a
+.section soz2b
+.section soz3a
+.section soz3b
+.section soz4a
+.section soz4b
+.section soz5a
+.section soz5b
+.section soz6a
+.section soz6b
+.section soz7a
+.section soz7b
+.section soz8a
+.section soz8b
+.section soz9a
+.section soz9b
+.section soz0a
+.section soz0b
+.section so1aa
+.section so1ab
+.section so1ba
+.section so1bb
+.section so1ca
+.section so1cb
+.section so1da
+.section so1db
+.section so1ea
+.section so1eb
+.section so1fa
+.section so1fb
+.section so1ga
+.section so1gb
+.section so1ha
+.section so1hb
+.section so1ia
+.section so1ib
+.section so1ja
+.section so1jb
+.section so1ka
+.section so1kb
+.section so1la
+.section so1lb
+.section so1ma
+.section so1mb
+.section so1na
+.section so1nb
+.section so1oa
+.section so1ob
+.section so1pa
+.section so1pb
+.section so1qa
+.section so1qb
+.section so1ra
+.section so1rb
+.section so1sa
+.section so1sb
+.section so1ta
+.section so1tb
+.section so1ua
+.section so1ub
+.section so1va
+.section so1vb
+.section so1wa
+.section so1wb
+.section so1xa
+.section so1xb
+.section so1ya
+.section so1yb
+.section so1za
+.section so1zb
+.section so11a
+.section so11b
+.section so12a
+.section so12b
+.section so13a
+.section so13b
+.section so14a
+.section so14b
+.section so15a
+.section so15b
+.section so16a
+.section so16b
+.section so17a
+.section so17b
+.section so18a
+.section so18b
+.section so19a
+.section so19b
+.section so10a
+.section so10b
+.section so2aa
+.section so2ab
+.section so2ba
+.section so2bb
+.section so2ca
+.section so2cb
+.section so2da
+.section so2db
+.section so2ea
+.section so2eb
+.section so2fa
+.section so2fb
+.section so2ga
+.section so2gb
+.section so2ha
+.section so2hb
+.section so2ia
+.section so2ib
+.section so2ja
+.section so2jb
+.section so2ka
+.section so2kb
+.section so2la
+.section so2lb
+.section so2ma
+.section so2mb
+.section so2na
+.section so2nb
+.section so2oa
+.section so2ob
+.section so2pa
+.section so2pb
+.section so2qa
+.section so2qb
+.section so2ra
+.section so2rb
+.section so2sa
+.section so2sb
+.section so2ta
+.section so2tb
+.section so2ua
+.section so2ub
+.section so2va
+.section so2vb
+.section so2wa
+.section so2wb
+.section so2xa
+.section so2xb
+.section so2ya
+.section so2yb
+.section so2za
+.section so2zb
+.section so21a
+.section so21b
+.section so22a
+.section so22b
+.section so23a
+.section so23b
+.section so24a
+.section so24b
+.section so25a
+.section so25b
+.section so26a
+.section so26b
+.section so27a
+.section so27b
+.section so28a
+.section so28b
+.section so29a
+.section so29b
+.section so20a
+.section so20b
+.section so3aa
+.section so3ab
+.section so3ba
+.section so3bb
+.section so3ca
+.section so3cb
+.section so3da
+.section so3db
+.section so3ea
+.section so3eb
+.section so3fa
+.section so3fb
+.section so3ga
+.section so3gb
+.section so3ha
+.section so3hb
+.section so3ia
+.section so3ib
+.section so3ja
+.section so3jb
+.section so3ka
+.section so3kb
+.section so3la
+.section so3lb
+.section so3ma
+.section so3mb
+.section so3na
+.section so3nb
+.section so3oa
+.section so3ob
+.section so3pa
+.section so3pb
+.section so3qa
+.section so3qb
+.section so3ra
+.section so3rb
+.section so3sa
+.section so3sb
+.section so3ta
+.section so3tb
+.section so3ua
+.section so3ub
+.section so3va
+.section so3vb
+.section so3wa
+.section so3wb
+.section so3xa
+.section so3xb
+.section so3ya
+.section so3yb
+.section so3za
+.section so3zb
+.section so31a
+.section so31b
+.section so32a
+.section so32b
+.section so33a
+.section so33b
+.section so34a
+.section so34b
+.section so35a
+.section so35b
+.section so36a
+.section so36b
+.section so37a
+.section so37b
+.section so38a
+.section so38b
+.section so39a
+.section so39b
+.section so30a
+.section so30b
+.section so4aa
+.section so4ab
+.section so4ba
+.section so4bb
+.section so4ca
+.section so4cb
+.section so4da
+.section so4db
+.section so4ea
+.section so4eb
+.section so4fa
+.section so4fb
+.section so4ga
+.section so4gb
+.section so4ha
+.section so4hb
+.section so4ia
+.section so4ib
+.section so4ja
+.section so4jb
+.section so4ka
+.section so4kb
+.section so4la
+.section so4lb
+.section so4ma
+.section so4mb
+.section so4na
+.section so4nb
+.section so4oa
+.section so4ob
+.section so4pa
+.section so4pb
+.section so4qa
+.section so4qb
+.section so4ra
+.section so4rb
+.section so4sa
+.section so4sb
+.section so4ta
+.section so4tb
+.section so4ua
+.section so4ub
+.section so4va
+.section so4vb
+.section so4wa
+.section so4wb
+.section so4xa
+.section so4xb
+.section so4ya
+.section so4yb
+.section so4za
+.section so4zb
+.section so41a
+.section so41b
+.section so42a
+.section so42b
+.section so43a
+.section so43b
+.section so44a
+.section so44b
+.section so45a
+.section so45b
+.section so46a
+.section so46b
+.section so47a
+.section so47b
+.section so48a
+.section so48b
+.section so49a
+.section so49b
+.section so40a
+.section so40b
+.section so5aa
+.section so5ab
+.section so5ba
+.section so5bb
+.section so5ca
+.section so5cb
+.section so5da
+.section so5db
+.section so5ea
+.section so5eb
+.section so5fa
+.section so5fb
+.section so5ga
+.section so5gb
+.section so5ha
+.section so5hb
+.section so5ia
+.section so5ib
+.section so5ja
+.section so5jb
+.section so5ka
+.section so5kb
+.section so5la
+.section so5lb
+.section so5ma
+.section so5mb
+.section so5na
+.section so5nb
+.section so5oa
+.section so5ob
+.section so5pa
+.section so5pb
+.section so5qa
+.section so5qb
+.section so5ra
+.section so5rb
+.section so5sa
+.section so5sb
+.section so5ta
+.section so5tb
+.section so5ua
+.section so5ub
+.section so5va
+.section so5vb
+.section so5wa
+.section so5wb
+.section so5xa
+.section so5xb
+.section so5ya
+.section so5yb
+.section so5za
+.section so5zb
+.section so51a
+.section so51b
+.section so52a
+.section so52b
+.section so53a
+.section so53b
+.section so54a
+.section so54b
+.section so55a
+.section so55b
+.section so56a
+.section so56b
+.section so57a
+.section so57b
+.section so58a
+.section so58b
+.section so59a
+.section so59b
+.section so50a
+.section so50b
+.section so6aa
+.section so6ab
+.section so6ba
+.section so6bb
+.section so6ca
+.section so6cb
+.section so6da
+.section so6db
+.section so6ea
+.section so6eb
+.section so6fa
+.section so6fb
+.section so6ga
+.section so6gb
+.section so6ha
+.section so6hb
+.section so6ia
+.section so6ib
+.section so6ja
+.section so6jb
+.section so6ka
+.section so6kb
+.section so6la
+.section so6lb
+.section so6ma
+.section so6mb
+.section so6na
+.section so6nb
+.section so6oa
+.section so6ob
+.section so6pa
+.section so6pb
+.section so6qa
+.section so6qb
+.section so6ra
+.section so6rb
+.section so6sa
+.section so6sb
+.section so6ta
+.section so6tb
+.section so6ua
+.section so6ub
+.section so6va
+.section so6vb
+.section so6wa
+.section so6wb
+.section so6xa
+.section so6xb
+.section so6ya
+.section so6yb
+.section so6za
+.section so6zb
+.section so61a
+.section so61b
+.section so62a
+.section so62b
+.section so63a
+.section so63b
+.section so64a
+.section so64b
+.section so65a
+.section so65b
+.section so66a
+.section so66b
+.section so67a
+.section so67b
+.section so68a
+.section so68b
+.section so69a
+.section so69b
+.section so60a
+.section so60b
+.section so7aa
+.section so7ab
+.section so7ba
+.section so7bb
+.section so7ca
+.section so7cb
+.section so7da
+.section so7db
+.section so7ea
+.section so7eb
+.section so7fa
+.section so7fb
+.section so7ga
+.section so7gb
+.section so7ha
+.section so7hb
+.section so7ia
+.section so7ib
+.section so7ja
+.section so7jb
+.section so7ka
+.section so7kb
+.section so7la
+.section so7lb
+.section so7ma
+.section so7mb
+.section so7na
+.section so7nb
+.section so7oa
+.section so7ob
+.section so7pa
+.section so7pb
+.section so7qa
+.section so7qb
+.section so7ra
+.section so7rb
+.section so7sa
+.section so7sb
+.section so7ta
+.section so7tb
+.section so7ua
+.section so7ub
+.section so7va
+.section so7vb
+.section so7wa
+.section so7wb
+.section so7xa
+.section so7xb
+.section so7ya
+.section so7yb
+.section so7za
+.section so7zb
+.section so71a
+.section so71b
+.section so72a
+.section so72b
+.section so73a
+.section so73b
+.section so74a
+.section so74b
+.section so75a
+.section so75b
+.section so76a
+.section so76b
+.section so77a
+.section so77b
+.section so78a
+.section so78b
+.section so79a
+.section so79b
+.section so70a
+.section so70b
+.section so8aa
+.section so8ab
+.section so8ba
+.section so8bb
+.section so8ca
+.section so8cb
+.section so8da
+.section so8db
+.section so8ea
+.section so8eb
+.section so8fa
+.section so8fb
+.section so8ga
+.section so8gb
+.section so8ha
+.section so8hb
+.section so8ia
+.section so8ib
+.section so8ja
+.section so8jb
+.section so8ka
+.section so8kb
+.section so8la
+.section so8lb
+.section so8ma
+.section so8mb
+.section so8na
+.section so8nb
+.section so8oa
+.section so8ob
+.section so8pa
+.section so8pb
+.section so8qa
+.section so8qb
+.section so8ra
+.section so8rb
+.section so8sa
+.section so8sb
+.section so8ta
+.section so8tb
+.section so8ua
+.section so8ub
+.section so8va
+.section so8vb
+.section so8wa
+.section so8wb
+.section so8xa
+.section so8xb
+.section so8ya
+.section so8yb
+.section so8za
+.section so8zb
+.section so81a
+.section so81b
+.section so82a
+.section so82b
+.section so83a
+.section so83b
+.section so84a
+.section so84b
+.section so85a
+.section so85b
+.section so86a
+.section so86b
+.section so87a
+.section so87b
+.section so88a
+.section so88b
+.section so89a
+.section so89b
+.section so80a
+.section so80b
+.section so9aa
+.section so9ab
+.section so9ba
+.section so9bb
+.section so9ca
+.section so9cb
+.section so9da
+.section so9db
+.section so9ea
+.section so9eb
+.section so9fa
+.section so9fb
+.section so9ga
+.section so9gb
+.section so9ha
+.section so9hb
+.section so9ia
+.section so9ib
+.section so9ja
+.section so9jb
+.section so9ka
+.section so9kb
+.section so9la
+.section so9lb
+.section so9ma
+.section so9mb
+.section so9na
+.section so9nb
+.section so9oa
+.section so9ob
+.section so9pa
+.section so9pb
+.section so9qa
+.section so9qb
+.section so9ra
+.section so9rb
+.section so9sa
+.section so9sb
+.section so9ta
+.section so9tb
+.section so9ua
+.section so9ub
+.section so9va
+.section so9vb
+.section so9wa
+.section so9wb
+.section so9xa
+.section so9xb
+.section so9ya
+.section so9yb
+.section so9za
+.section so9zb
+.section so91a
+.section so91b
+.section so92a
+.section so92b
+.section so93a
+.section so93b
+.section so94a
+.section so94b
+.section so95a
+.section so95b
+.section so96a
+.section so96b
+.section so97a
+.section so97b
+.section so98a
+.section so98b
+.section so99a
+.section so99b
+.section so90a
+.section so90b
+.section so0aa
+.section so0ab
+.section so0ba
+.section so0bb
+.section so0ca
+.section so0cb
+.section so0da
+.section so0db
+.section so0ea
+.section so0eb
+.section so0fa
+.section so0fb
+.section so0ga
+.section so0gb
+.section so0ha
+.section so0hb
+.section so0ia
+.section so0ib
+.section so0ja
+.section so0jb
+.section so0ka
+.section so0kb
+.section so0la
+.section so0lb
+.section so0ma
+.section so0mb
+.section so0na
+.section so0nb
+.section so0oa
+.section so0ob
+.section so0pa
+.section so0pb
+.section so0qa
+.section so0qb
+.section so0ra
+.section so0rb
+.section so0sa
+.section so0sb
+.section so0ta
+.section so0tb
+.section so0ua
+.section so0ub
+.section so0va
+.section so0vb
+.section so0wa
+.section so0wb
+.section so0xa
+.section so0xb
+.section so0ya
+.section so0yb
+.section so0za
+.section so0zb
+.section so01a
+.section so01b
+.section so02a
+.section so02b
+.section so03a
+.section so03b
+.section so04a
+.section so04b
+.section so05a
+.section so05b
+.section so06a
+.section so06b
+.section so07a
+.section so07b
+.section so08a
+.section so08b
+.section so09a
+.section so09b
+.section so00a
+.section so00b
+.section spaaa
+.section spaab
+.section spaba
+.section spabb
+.section spaca
+.section spacb
+.section spada
+.section spadb
+.section spaea
+.section spaeb
+.section spafa
+.section spafb
+.section spaga
+.section spagb
+.section spaha
+.section spahb
+.section spaia
+.section spaib
+.section spaja
+.section spajb
+.section spaka
+.section spakb
+.section spala
+.section spalb
+.section spama
+.section spamb
+.section spana
+.section spanb
+.section spaoa
+.section spaob
+.section spapa
+.section spapb
+.section spaqa
+.section spaqb
+.section spara
+.section sparb
+.section spasa
+.section spasb
+.section spata
+.section spatb
+.section spaua
+.section spaub
+.section spava
+.section spavb
+.section spawa
+.section spawb
+.section spaxa
+.section spaxb
+.section spaya
+.section spayb
+.section spaza
+.section spazb
+.section spa1a
+.section spa1b
+.section spa2a
+.section spa2b
+.section spa3a
+.section spa3b
+.section spa4a
+.section spa4b
+.section spa5a
+.section spa5b
+.section spa6a
+.section spa6b
+.section spa7a
+.section spa7b
+.section spa8a
+.section spa8b
+.section spa9a
+.section spa9b
+.section spa0a
+.section spa0b
+.section spbaa
+.section spbab
+.section spbba
+.section spbbb
+.section spbca
+.section spbcb
+.section spbda
+.section spbdb
+.section spbea
+.section spbeb
+.section spbfa
+.section spbfb
+.section spbga
+.section spbgb
+.section spbha
+.section spbhb
+.section spbia
+.section spbib
+.section spbja
+.section spbjb
+.section spbka
+.section spbkb
+.section spbla
+.section spblb
+.section spbma
+.section spbmb
+.section spbna
+.section spbnb
+.section spboa
+.section spbob
+.section spbpa
+.section spbpb
+.section spbqa
+.section spbqb
+.section spbra
+.section spbrb
+.section spbsa
+.section spbsb
+.section spbta
+.section spbtb
+.section spbua
+.section spbub
+.section spbva
+.section spbvb
+.section spbwa
+.section spbwb
+.section spbxa
+.section spbxb
+.section spbya
+.section spbyb
+.section spbza
+.section spbzb
+.section spb1a
+.section spb1b
+.section spb2a
+.section spb2b
+.section spb3a
+.section spb3b
+.section spb4a
+.section spb4b
+.section spb5a
+.section spb5b
+.section spb6a
+.section spb6b
+.section spb7a
+.section spb7b
+.section spb8a
+.section spb8b
+.section spb9a
+.section spb9b
+.section spb0a
+.section spb0b
+.section spcaa
+.section spcab
+.section spcba
+.section spcbb
+.section spcca
+.section spccb
+.section spcda
+.section spcdb
+.section spcea
+.section spceb
+.section spcfa
+.section spcfb
+.section spcga
+.section spcgb
+.section spcha
+.section spchb
+.section spcia
+.section spcib
+.section spcja
+.section spcjb
+.section spcka
+.section spckb
+.section spcla
+.section spclb
+.section spcma
+.section spcmb
+.section spcna
+.section spcnb
+.section spcoa
+.section spcob
+.section spcpa
+.section spcpb
+.section spcqa
+.section spcqb
+.section spcra
+.section spcrb
+.section spcsa
+.section spcsb
+.section spcta
+.section spctb
+.section spcua
+.section spcub
+.section spcva
+.section spcvb
+.section spcwa
+.section spcwb
+.section spcxa
+.section spcxb
+.section spcya
+.section spcyb
+.section spcza
+.section spczb
+.section spc1a
+.section spc1b
+.section spc2a
+.section spc2b
+.section spc3a
+.section spc3b
+.section spc4a
+.section spc4b
+.section spc5a
+.section spc5b
+.section spc6a
+.section spc6b
+.section spc7a
+.section spc7b
+.section spc8a
+.section spc8b
+.section spc9a
+.section spc9b
+.section spc0a
+.section spc0b
+.section spdaa
+.section spdab
+.section spdba
+.section spdbb
+.section spdca
+.section spdcb
+.section spdda
+.section spddb
+.section spdea
+.section spdeb
+.section spdfa
+.section spdfb
+.section spdga
+.section spdgb
+.section spdha
+.section spdhb
+.section spdia
+.section spdib
+.section spdja
+.section spdjb
+.section spdka
+.section spdkb
+.section spdla
+.section spdlb
+.section spdma
+.section spdmb
+.section spdna
+.section spdnb
+.section spdoa
+.section spdob
+.section spdpa
+.section spdpb
+.section spdqa
+.section spdqb
+.section spdra
+.section spdrb
+.section spdsa
+.section spdsb
+.section spdta
+.section spdtb
+.section spdua
+.section spdub
+.section spdva
+.section spdvb
+.section spdwa
+.section spdwb
+.section spdxa
+.section spdxb
+.section spdya
+.section spdyb
+.section spdza
+.section spdzb
+.section spd1a
+.section spd1b
+.section spd2a
+.section spd2b
+.section spd3a
+.section spd3b
+.section spd4a
+.section spd4b
+.section spd5a
+.section spd5b
+.section spd6a
+.section spd6b
+.section spd7a
+.section spd7b
+.section spd8a
+.section spd8b
+.section spd9a
+.section spd9b
+.section spd0a
+.section spd0b
+.section speaa
+.section speab
+.section speba
+.section spebb
+.section speca
+.section specb
+.section speda
+.section spedb
+.section speea
+.section speeb
+.section spefa
+.section spefb
+.section spega
+.section spegb
+.section speha
+.section spehb
+.section speia
+.section speib
+.section speja
+.section spejb
+.section speka
+.section spekb
+.section spela
+.section spelb
+.section spema
+.section spemb
+.section spena
+.section spenb
+.section speoa
+.section speob
+.section spepa
+.section spepb
+.section speqa
+.section speqb
+.section spera
+.section sperb
+.section spesa
+.section spesb
+.section speta
+.section spetb
+.section speua
+.section speub
+.section speva
+.section spevb
+.section spewa
+.section spewb
+.section spexa
+.section spexb
+.section speya
+.section speyb
+.section speza
+.section spezb
+.section spe1a
+.section spe1b
+.section spe2a
+.section spe2b
+.section spe3a
+.section spe3b
+.section spe4a
+.section spe4b
+.section spe5a
+.section spe5b
+.section spe6a
+.section spe6b
+.section spe7a
+.section spe7b
+.section spe8a
+.section spe8b
+.section spe9a
+.section spe9b
+.section spe0a
+.section spe0b
+.section spfaa
+.section spfab
+.section spfba
+.section spfbb
+.section spfca
+.section spfcb
+.section spfda
+.section spfdb
+.section spfea
+.section spfeb
+.section spffa
+.section spffb
+.section spfga
+.section spfgb
+.section spfha
+.section spfhb
+.section spfia
+.section spfib
+.section spfja
+.section spfjb
+.section spfka
+.section spfkb
+.section spfla
+.section spflb
+.section spfma
+.section spfmb
+.section spfna
+.section spfnb
+.section spfoa
+.section spfob
+.section spfpa
+.section spfpb
+.section spfqa
+.section spfqb
+.section spfra
+.section spfrb
+.section spfsa
+.section spfsb
+.section spfta
+.section spftb
+.section spfua
+.section spfub
+.section spfva
+.section spfvb
+.section spfwa
+.section spfwb
+.section spfxa
+.section spfxb
+.section spfya
+.section spfyb
+.section spfza
+.section spfzb
+.section spf1a
+.section spf1b
+.section spf2a
+.section spf2b
+.section spf3a
+.section spf3b
+.section spf4a
+.section spf4b
+.section spf5a
+.section spf5b
+.section spf6a
+.section spf6b
+.section spf7a
+.section spf7b
+.section spf8a
+.section spf8b
+.section spf9a
+.section spf9b
+.section spf0a
+.section spf0b
+.section spgaa
+.section spgab
+.section spgba
+.section spgbb
+.section spgca
+.section spgcb
+.section spgda
+.section spgdb
+.section spgea
+.section spgeb
+.section spgfa
+.section spgfb
+.section spgga
+.section spggb
+.section spgha
+.section spghb
+.section spgia
+.section spgib
+.section spgja
+.section spgjb
+.section spgka
+.section spgkb
+.section spgla
+.section spglb
+.section spgma
+.section spgmb
+.section spgna
+.section spgnb
+.section spgoa
+.section spgob
+.section spgpa
+.section spgpb
+.section spgqa
+.section spgqb
+.section spgra
+.section spgrb
+.section spgsa
+.section spgsb
+.section spgta
+.section spgtb
+.section spgua
+.section spgub
+.section spgva
+.section spgvb
+.section spgwa
+.section spgwb
+.section spgxa
+.section spgxb
+.section spgya
+.section spgyb
+.section spgza
+.section spgzb
+.section spg1a
+.section spg1b
+.section spg2a
+.section spg2b
+.section spg3a
+.section spg3b
+.section spg4a
+.section spg4b
+.section spg5a
+.section spg5b
+.section spg6a
+.section spg6b
+.section spg7a
+.section spg7b
+.section spg8a
+.section spg8b
+.section spg9a
+.section spg9b
+.section spg0a
+.section spg0b
+.section sphaa
+.section sphab
+.section sphba
+.section sphbb
+.section sphca
+.section sphcb
+.section sphda
+.section sphdb
+.section sphea
+.section spheb
+.section sphfa
+.section sphfb
+.section sphga
+.section sphgb
+.section sphha
+.section sphhb
+.section sphia
+.section sphib
+.section sphja
+.section sphjb
+.section sphka
+.section sphkb
+.section sphla
+.section sphlb
+.section sphma
+.section sphmb
+.section sphna
+.section sphnb
+.section sphoa
+.section sphob
+.section sphpa
+.section sphpb
+.section sphqa
+.section sphqb
+.section sphra
+.section sphrb
+.section sphsa
+.section sphsb
+.section sphta
+.section sphtb
+.section sphua
+.section sphub
+.section sphva
+.section sphvb
+.section sphwa
+.section sphwb
+.section sphxa
+.section sphxb
+.section sphya
+.section sphyb
+.section sphza
+.section sphzb
+.section sph1a
+.section sph1b
+.section sph2a
+.section sph2b
+.section sph3a
+.section sph3b
+.section sph4a
+.section sph4b
+.section sph5a
+.section sph5b
+.section sph6a
+.section sph6b
+.section sph7a
+.section sph7b
+.section sph8a
+.section sph8b
+.section sph9a
+.section sph9b
+.section sph0a
+.section sph0b
+.section spiaa
+.section spiab
+.section spiba
+.section spibb
+.section spica
+.section spicb
+.section spida
+.section spidb
+.section spiea
+.section spieb
+.section spifa
+.section spifb
+.section spiga
+.section spigb
+.section spiha
+.section spihb
+.section spiia
+.section spiib
+.section spija
+.section spijb
+.section spika
+.section spikb
+.section spila
+.section spilb
+.section spima
+.section spimb
+.section spina
+.section spinb
+.section spioa
+.section spiob
+.section spipa
+.section spipb
+.section spiqa
+.section spiqb
+.section spira
+.section spirb
+.section spisa
+.section spisb
+.section spita
+.section spitb
+.section spiua
+.section spiub
+.section spiva
+.section spivb
+.section spiwa
+.section spiwb
+.section spixa
+.section spixb
+.section spiya
+.section spiyb
+.section spiza
+.section spizb
+.section spi1a
+.section spi1b
+.section spi2a
+.section spi2b
+.section spi3a
+.section spi3b
+.section spi4a
+.section spi4b
+.section spi5a
+.section spi5b
+.section spi6a
+.section spi6b
+.section spi7a
+.section spi7b
+.section spi8a
+.section spi8b
+.section spi9a
+.section spi9b
+.section spi0a
+.section spi0b
+.section spjaa
+.section spjab
+.section spjba
+.section spjbb
+.section spjca
+.section spjcb
+.section spjda
+.section spjdb
+.section spjea
+.section spjeb
+.section spjfa
+.section spjfb
+.section spjga
+.section spjgb
+.section spjha
+.section spjhb
+.section spjia
+.section spjib
+.section spjja
+.section spjjb
+.section spjka
+.section spjkb
+.section spjla
+.section spjlb
+.section spjma
+.section spjmb
+.section spjna
+.section spjnb
+.section spjoa
+.section spjob
+.section spjpa
+.section spjpb
+.section spjqa
+.section spjqb
+.section spjra
+.section spjrb
+.section spjsa
+.section spjsb
+.section spjta
+.section spjtb
+.section spjua
+.section spjub
+.section spjva
+.section spjvb
+.section spjwa
+.section spjwb
+.section spjxa
+.section spjxb
+.section spjya
+.section spjyb
+.section spjza
+.section spjzb
+.section spj1a
+.section spj1b
+.section spj2a
+.section spj2b
+.section spj3a
+.section spj3b
+.section spj4a
+.section spj4b
+.section spj5a
+.section spj5b
+.section spj6a
+.section spj6b
+.section spj7a
+.section spj7b
+.section spj8a
+.section spj8b
+.section spj9a
+.section spj9b
+.section spj0a
+.section spj0b
+.section spkaa
+.section spkab
+.section spkba
+.section spkbb
+.section spkca
+.section spkcb
+.section spkda
+.section spkdb
+.section spkea
+.section spkeb
+.section spkfa
+.section spkfb
+.section spkga
+.section spkgb
+.section spkha
+.section spkhb
+.section spkia
+.section spkib
+.section spkja
+.section spkjb
+.section spkka
+.section spkkb
+.section spkla
+.section spklb
+.section spkma
+.section spkmb
+.section spkna
+.section spknb
+.section spkoa
+.section spkob
+.section spkpa
+.section spkpb
+.section spkqa
+.section spkqb
+.section spkra
+.section spkrb
+.section spksa
+.section spksb
+.section spkta
+.section spktb
+.section spkua
+.section spkub
+.section spkva
+.section spkvb
+.section spkwa
+.section spkwb
+.section spkxa
+.section spkxb
+.section spkya
+.section spkyb
+.section spkza
+.section spkzb
+.section spk1a
+.section spk1b
+.section spk2a
+.section spk2b
+.section spk3a
+.section spk3b
+.section spk4a
+.section spk4b
+.section spk5a
+.section spk5b
+.section spk6a
+.section spk6b
+.section spk7a
+.section spk7b
+.section spk8a
+.section spk8b
+.section spk9a
+.section spk9b
+.section spk0a
+.section spk0b
+.section splaa
+.section splab
+.section splba
+.section splbb
+.section splca
+.section splcb
+.section splda
+.section spldb
+.section splea
+.section spleb
+.section splfa
+.section splfb
+.section splga
+.section splgb
+.section splha
+.section splhb
+.section splia
+.section splib
+.section splja
+.section spljb
+.section splka
+.section splkb
+.section splla
+.section spllb
+.section splma
+.section splmb
+.section splna
+.section splnb
+.section sploa
+.section splob
+.section splpa
+.section splpb
+.section splqa
+.section splqb
+.section splra
+.section splrb
+.section splsa
+.section splsb
+.section splta
+.section spltb
+.section splua
+.section splub
+.section splva
+.section splvb
+.section splwa
+.section splwb
+.section splxa
+.section splxb
+.section splya
+.section splyb
+.section splza
+.section splzb
+.section spl1a
+.section spl1b
+.section spl2a
+.section spl2b
+.section spl3a
+.section spl3b
+.section spl4a
+.section spl4b
+.section spl5a
+.section spl5b
+.section spl6a
+.section spl6b
+.section spl7a
+.section spl7b
+.section spl8a
+.section spl8b
+.section spl9a
+.section spl9b
+.section spl0a
+.section spl0b
+.section spmaa
+.section spmab
+.section spmba
+.section spmbb
+.section spmca
+.section spmcb
+.section spmda
+.section spmdb
+.section spmea
+.section spmeb
+.section spmfa
+.section spmfb
+.section spmga
+.section spmgb
+.section spmha
+.section spmhb
+.section spmia
+.section spmib
+.section spmja
+.section spmjb
+.section spmka
+.section spmkb
+.section spmla
+.section spmlb
+.section spmma
+.section spmmb
+.section spmna
+.section spmnb
+.section spmoa
+.section spmob
+.section spmpa
+.section spmpb
+.section spmqa
+.section spmqb
+.section spmra
+.section spmrb
+.section spmsa
+.section spmsb
+.section spmta
+.section spmtb
+.section spmua
+.section spmub
+.section spmva
+.section spmvb
+.section spmwa
+.section spmwb
+.section spmxa
+.section spmxb
+.section spmya
+.section spmyb
+.section spmza
+.section spmzb
+.section spm1a
+.section spm1b
+.section spm2a
+.section spm2b
+.section spm3a
+.section spm3b
+.section spm4a
+.section spm4b
+.section spm5a
+.section spm5b
+.section spm6a
+.section spm6b
+.section spm7a
+.section spm7b
+.section spm8a
+.section spm8b
+.section spm9a
+.section spm9b
+.section spm0a
+.section spm0b
+.section spnaa
+.section spnab
+.section spnba
+.section spnbb
+.section spnca
+.section spncb
+.section spnda
+.section spndb
+.section spnea
+.section spneb
+.section spnfa
+.section spnfb
+.section spnga
+.section spngb
+.section spnha
+.section spnhb
+.section spnia
+.section spnib
+.section spnja
+.section spnjb
+.section spnka
+.section spnkb
+.section spnla
+.section spnlb
+.section spnma
+.section spnmb
+.section spnna
+.section spnnb
+.section spnoa
+.section spnob
+.section spnpa
+.section spnpb
+.section spnqa
+.section spnqb
+.section spnra
+.section spnrb
+.section spnsa
+.section spnsb
+.section spnta
+.section spntb
+.section spnua
+.section spnub
+.section spnva
+.section spnvb
+.section spnwa
+.section spnwb
+.section spnxa
+.section spnxb
+.section spnya
+.section spnyb
+.section spnza
+.section spnzb
+.section spn1a
+.section spn1b
+.section spn2a
+.section spn2b
+.section spn3a
+.section spn3b
+.section spn4a
+.section spn4b
+.section spn5a
+.section spn5b
+.section spn6a
+.section spn6b
+.section spn7a
+.section spn7b
+.section spn8a
+.section spn8b
+.section spn9a
+.section spn9b
+.section spn0a
+.section spn0b
+.section spoaa
+.section spoab
+.section spoba
+.section spobb
+.section spoca
+.section spocb
+.section spoda
+.section spodb
+.section spoea
+.section spoeb
+.section spofa
+.section spofb
+.section spoga
+.section spogb
+.section spoha
+.section spohb
+.section spoia
+.section spoib
+.section spoja
+.section spojb
+.section spoka
+.section spokb
+.section spola
+.section spolb
+.section spoma
+.section spomb
+.section spona
+.section sponb
+.section spooa
+.section spoob
+.section spopa
+.section spopb
+.section spoqa
+.section spoqb
+.section spora
+.section sporb
+.section sposa
+.section sposb
+.section spota
+.section spotb
+.section spoua
+.section spoub
+.section spova
+.section spovb
+.section spowa
+.section spowb
+.section spoxa
+.section spoxb
+.section spoya
+.section spoyb
+.section spoza
+.section spozb
+.section spo1a
+.section spo1b
+.section spo2a
+.section spo2b
+.section spo3a
+.section spo3b
+.section spo4a
+.section spo4b
+.section spo5a
+.section spo5b
+.section spo6a
+.section spo6b
+.section spo7a
+.section spo7b
+.section spo8a
+.section spo8b
+.section spo9a
+.section spo9b
+.section spo0a
+.section spo0b
+.section sppaa
+.section sppab
+.section sppba
+.section sppbb
+.section sppca
+.section sppcb
+.section sppda
+.section sppdb
+.section sppea
+.section sppeb
+.section sppfa
+.section sppfb
+.section sppga
+.section sppgb
+.section sppha
+.section spphb
+.section sppia
+.section sppib
+.section sppja
+.section sppjb
+.section sppka
+.section sppkb
+.section sppla
+.section spplb
+.section sppma
+.section sppmb
+.section sppna
+.section sppnb
+.section sppoa
+.section sppob
+.section spppa
+.section spppb
+.section sppqa
+.section sppqb
+.section sppra
+.section spprb
+.section sppsa
+.section sppsb
+.section sppta
+.section spptb
+.section sppua
+.section sppub
+.section sppva
+.section sppvb
+.section sppwa
+.section sppwb
+.section sppxa
+.section sppxb
+.section sppya
+.section sppyb
+.section sppza
+.section sppzb
+.section spp1a
+.section spp1b
+.section spp2a
+.section spp2b
+.section spp3a
+.section spp3b
+.section spp4a
+.section spp4b
+.section spp5a
+.section spp5b
+.section spp6a
+.section spp6b
+.section spp7a
+.section spp7b
+.section spp8a
+.section spp8b
+.section spp9a
+.section spp9b
+.section spp0a
+.section spp0b
+.section spqaa
+.section spqab
+.section spqba
+.section spqbb
+.section spqca
+.section spqcb
+.section spqda
+.section spqdb
+.section spqea
+.section spqeb
+.section spqfa
+.section spqfb
+.section spqga
+.section spqgb
+.section spqha
+.section spqhb
+.section spqia
+.section spqib
+.section spqja
+.section spqjb
+.section spqka
+.section spqkb
+.section spqla
+.section spqlb
+.section spqma
+.section spqmb
+.section spqna
+.section spqnb
+.section spqoa
+.section spqob
+.section spqpa
+.section spqpb
+.section spqqa
+.section spqqb
+.section spqra
+.section spqrb
+.section spqsa
+.section spqsb
+.section spqta
+.section spqtb
+.section spqua
+.section spqub
+.section spqva
+.section spqvb
+.section spqwa
+.section spqwb
+.section spqxa
+.section spqxb
+.section spqya
+.section spqyb
+.section spqza
+.section spqzb
+.section spq1a
+.section spq1b
+.section spq2a
+.section spq2b
+.section spq3a
+.section spq3b
+.section spq4a
+.section spq4b
+.section spq5a
+.section spq5b
+.section spq6a
+.section spq6b
+.section spq7a
+.section spq7b
+.section spq8a
+.section spq8b
+.section spq9a
+.section spq9b
+.section spq0a
+.section spq0b
+.section spraa
+.section sprab
+.section sprba
+.section sprbb
+.section sprca
+.section sprcb
+.section sprda
+.section sprdb
+.section sprea
+.section spreb
+.section sprfa
+.section sprfb
+.section sprga
+.section sprgb
+.section sprha
+.section sprhb
+.section spria
+.section sprib
+.section sprja
+.section sprjb
+.section sprka
+.section sprkb
+.section sprla
+.section sprlb
+.section sprma
+.section sprmb
+.section sprna
+.section sprnb
+.section sproa
+.section sprob
+.section sprpa
+.section sprpb
+.section sprqa
+.section sprqb
+.section sprra
+.section sprrb
+.section sprsa
+.section sprsb
+.section sprta
+.section sprtb
+.section sprua
+.section sprub
+.section sprva
+.section sprvb
+.section sprwa
+.section sprwb
+.section sprxa
+.section sprxb
+.section sprya
+.section spryb
+.section sprza
+.section sprzb
+.section spr1a
+.section spr1b
+.section spr2a
+.section spr2b
+.section spr3a
+.section spr3b
+.section spr4a
+.section spr4b
+.section spr5a
+.section spr5b
+.section spr6a
+.section spr6b
+.section spr7a
+.section spr7b
+.section spr8a
+.section spr8b
+.section spr9a
+.section spr9b
+.section spr0a
+.section spr0b
+.section spsaa
+.section spsab
+.section spsba
+.section spsbb
+.section spsca
+.section spscb
+.section spsda
+.section spsdb
+.section spsea
+.section spseb
+.section spsfa
+.section spsfb
+.section spsga
+.section spsgb
+.section spsha
+.section spshb
+.section spsia
+.section spsib
+.section spsja
+.section spsjb
+.section spska
+.section spskb
+.section spsla
+.section spslb
+.section spsma
+.section spsmb
+.section spsna
+.section spsnb
+.section spsoa
+.section spsob
+.section spspa
+.section spspb
+.section spsqa
+.section spsqb
+.section spsra
+.section spsrb
+.section spssa
+.section spssb
+.section spsta
+.section spstb
+.section spsua
+.section spsub
+.section spsva
+.section spsvb
+.section spswa
+.section spswb
+.section spsxa
+.section spsxb
+.section spsya
+.section spsyb
+.section spsza
+.section spszb
+.section sps1a
+.section sps1b
+.section sps2a
+.section sps2b
+.section sps3a
+.section sps3b
+.section sps4a
+.section sps4b
+.section sps5a
+.section sps5b
+.section sps6a
+.section sps6b
+.section sps7a
+.section sps7b
+.section sps8a
+.section sps8b
+.section sps9a
+.section sps9b
+.section sps0a
+.section sps0b
+.section sptaa
+.section sptab
+.section sptba
+.section sptbb
+.section sptca
+.section sptcb
+.section sptda
+.section sptdb
+.section sptea
+.section spteb
+.section sptfa
+.section sptfb
+.section sptga
+.section sptgb
+.section sptha
+.section spthb
+.section sptia
+.section sptib
+.section sptja
+.section sptjb
+.section sptka
+.section sptkb
+.section sptla
+.section sptlb
+.section sptma
+.section sptmb
+.section sptna
+.section sptnb
+.section sptoa
+.section sptob
+.section sptpa
+.section sptpb
+.section sptqa
+.section sptqb
+.section sptra
+.section sptrb
+.section sptsa
+.section sptsb
+.section sptta
+.section spttb
+.section sptua
+.section sptub
+.section sptva
+.section sptvb
+.section sptwa
+.section sptwb
+.section sptxa
+.section sptxb
+.section sptya
+.section sptyb
+.section sptza
+.section sptzb
+.section spt1a
+.section spt1b
+.section spt2a
+.section spt2b
+.section spt3a
+.section spt3b
+.section spt4a
+.section spt4b
+.section spt5a
+.section spt5b
+.section spt6a
+.section spt6b
+.section spt7a
+.section spt7b
+.section spt8a
+.section spt8b
+.section spt9a
+.section spt9b
+.section spt0a
+.section spt0b
+.section spuaa
+.section spuab
+.section spuba
+.section spubb
+.section spuca
+.section spucb
+.section spuda
+.section spudb
+.section spuea
+.section spueb
+.section spufa
+.section spufb
+.section spuga
+.section spugb
+.section spuha
+.section spuhb
+.section spuia
+.section spuib
+.section spuja
+.section spujb
+.section spuka
+.section spukb
+.section spula
+.section spulb
+.section spuma
+.section spumb
+.section spuna
+.section spunb
+.section spuoa
+.section spuob
+.section spupa
+.section spupb
+.section spuqa
+.section spuqb
+.section spura
+.section spurb
+.section spusa
+.section spusb
+.section sputa
+.section sputb
+.section spuua
+.section spuub
+.section spuva
+.section spuvb
+.section spuwa
+.section spuwb
+.section spuxa
+.section spuxb
+.section spuya
+.section spuyb
+.section spuza
+.section spuzb
+.section spu1a
+.section spu1b
+.section spu2a
+.section spu2b
+.section spu3a
+.section spu3b
+.section spu4a
+.section spu4b
+.section spu5a
+.section spu5b
+.section spu6a
+.section spu6b
+.section spu7a
+.section spu7b
+.section spu8a
+.section spu8b
+.section spu9a
+.section spu9b
+.section spu0a
+.section spu0b
+.section spvaa
+.section spvab
+.section spvba
+.section spvbb
+.section spvca
+.section spvcb
+.section spvda
+.section spvdb
+.section spvea
+.section spveb
+.section spvfa
+.section spvfb
+.section spvga
+.section spvgb
+.section spvha
+.section spvhb
+.section spvia
+.section spvib
+.section spvja
+.section spvjb
+.section spvka
+.section spvkb
+.section spvla
+.section spvlb
+.section spvma
+.section spvmb
+.section spvna
+.section spvnb
+.section spvoa
+.section spvob
+.section spvpa
+.section spvpb
+.section spvqa
+.section spvqb
+.section spvra
+.section spvrb
+.section spvsa
+.section spvsb
+.section spvta
+.section spvtb
+.section spvua
+.section spvub
+.section spvva
+.section spvvb
+.section spvwa
+.section spvwb
+.section spvxa
+.section spvxb
+.section spvya
+.section spvyb
+.section spvza
+.section spvzb
+.section spv1a
+.section spv1b
+.section spv2a
+.section spv2b
+.section spv3a
+.section spv3b
+.section spv4a
+.section spv4b
+.section spv5a
+.section spv5b
+.section spv6a
+.section spv6b
+.section spv7a
+.section spv7b
+.section spv8a
+.section spv8b
+.section spv9a
+.section spv9b
+.section spv0a
+.section spv0b
+.section spwaa
+.section spwab
+.section spwba
+.section spwbb
+.section spwca
+.section spwcb
+.section spwda
+.section spwdb
+.section spwea
+.section spweb
+.section spwfa
+.section spwfb
+.section spwga
+.section spwgb
+.section spwha
+.section spwhb
+.section spwia
+.section spwib
+.section spwja
+.section spwjb
+.section spwka
+.section spwkb
+.section spwla
+.section spwlb
+.section spwma
+.section spwmb
+.section spwna
+.section spwnb
+.section spwoa
+.section spwob
+.section spwpa
+.section spwpb
+.section spwqa
+.section spwqb
+.section spwra
+.section spwrb
+.section spwsa
+.section spwsb
+.section spwta
+.section spwtb
+.section spwua
+.section spwub
+.section spwva
+.section spwvb
+.section spwwa
+.section spwwb
+.section spwxa
+.section spwxb
+.section spwya
+.section spwyb
+.section spwza
+.section spwzb
+.section spw1a
+.section spw1b
+.section spw2a
+.section spw2b
+.section spw3a
+.section spw3b
+.section spw4a
+.section spw4b
+.section spw5a
+.section spw5b
+.section spw6a
+.section spw6b
+.section spw7a
+.section spw7b
+.section spw8a
+.section spw8b
+.section spw9a
+.section spw9b
+.section spw0a
+.section spw0b
+.section spxaa
+.section spxab
+.section spxba
+.section spxbb
+.section spxca
+.section spxcb
+.section spxda
+.section spxdb
+.section spxea
+.section spxeb
+.section spxfa
+.section spxfb
+.section spxga
+.section spxgb
+.section spxha
+.section spxhb
+.section spxia
+.section spxib
+.section spxja
+.section spxjb
+.section spxka
+.section spxkb
+.section spxla
+.section spxlb
+.section spxma
+.section spxmb
+.section spxna
+.section spxnb
+.section spxoa
+.section spxob
+.section spxpa
+.section spxpb
+.section spxqa
+.section spxqb
+.section spxra
+.section spxrb
+.section spxsa
+.section spxsb
+.section spxta
+.section spxtb
+.section spxua
+.section spxub
+.section spxva
+.section spxvb
+.section spxwa
+.section spxwb
+.section spxxa
+.section spxxb
+.section spxya
+.section spxyb
+.section spxza
+.section spxzb
+.section spx1a
+.section spx1b
+.section spx2a
+.section spx2b
+.section spx3a
+.section spx3b
+.section spx4a
+.section spx4b
+.section spx5a
+.section spx5b
+.section spx6a
+.section spx6b
+.section spx7a
+.section spx7b
+.section spx8a
+.section spx8b
+.section spx9a
+.section spx9b
+.section spx0a
+.section spx0b
+.section spyaa
+.section spyab
+.section spyba
+.section spybb
+.section spyca
+.section spycb
+.section spyda
+.section spydb
+.section spyea
+.section spyeb
+.section spyfa
+.section spyfb
+.section spyga
+.section spygb
+.section spyha
+.section spyhb
+.section spyia
+.section spyib
+.section spyja
+.section spyjb
+.section spyka
+.section spykb
+.section spyla
+.section spylb
+.section spyma
+.section spymb
+.section spyna
+.section spynb
+.section spyoa
+.section spyob
+.section spypa
+.section spypb
+.section spyqa
+.section spyqb
+.section spyra
+.section spyrb
+.section spysa
+.section spysb
+.section spyta
+.section spytb
+.section spyua
+.section spyub
+.section spyva
+.section spyvb
+.section spywa
+.section spywb
+.section spyxa
+.section spyxb
+.section spyya
+.section spyyb
+.section spyza
+.section spyzb
+.section spy1a
+.section spy1b
+.section spy2a
+.section spy2b
+.section spy3a
+.section spy3b
+.section spy4a
+.section spy4b
+.section spy5a
+.section spy5b
+.section spy6a
+.section spy6b
+.section spy7a
+.section spy7b
+.section spy8a
+.section spy8b
+.section spy9a
+.section spy9b
+.section spy0a
+.section spy0b
+.section spzaa
+.section spzab
+.section spzba
+.section spzbb
+.section spzca
+.section spzcb
+.section spzda
+.section spzdb
+.section spzea
+.section spzeb
+.section spzfa
+.section spzfb
+.section spzga
+.section spzgb
+.section spzha
+.section spzhb
+.section spzia
+.section spzib
+.section spzja
+.section spzjb
+.section spzka
+.section spzkb
+.section spzla
+.section spzlb
+.section spzma
+.section spzmb
+.section spzna
+.section spznb
+.section spzoa
+.section spzob
+.section spzpa
+.section spzpb
+.section spzqa
+.section spzqb
+.section spzra
+.section spzrb
+.section spzsa
+.section spzsb
+.section spzta
+.section spztb
+.section spzua
+.section spzub
+.section spzva
+.section spzvb
+.section spzwa
+.section spzwb
+.section spzxa
+.section spzxb
+.section spzya
+.section spzyb
+.section spzza
+.section spzzb
+.section spz1a
+.section spz1b
+.section spz2a
+.section spz2b
+.section spz3a
+.section spz3b
+.section spz4a
+.section spz4b
+.section spz5a
+.section spz5b
+.section spz6a
+.section spz6b
+.section spz7a
+.section spz7b
+.section spz8a
+.section spz8b
+.section spz9a
+.section spz9b
+.section spz0a
+.section spz0b
+.section sp1aa
+.section sp1ab
+.section sp1ba
+.section sp1bb
+.section sp1ca
+.section sp1cb
+.section sp1da
+.section sp1db
+.section sp1ea
+.section sp1eb
+.section sp1fa
+.section sp1fb
+.section sp1ga
+.section sp1gb
+.section sp1ha
+.section sp1hb
+.section sp1ia
+.section sp1ib
+.section sp1ja
+.section sp1jb
+.section sp1ka
+.section sp1kb
+.section sp1la
+.section sp1lb
+.section sp1ma
+.section sp1mb
+.section sp1na
+.section sp1nb
+.section sp1oa
+.section sp1ob
+.section sp1pa
+.section sp1pb
+.section sp1qa
+.section sp1qb
+.section sp1ra
+.section sp1rb
+.section sp1sa
+.section sp1sb
+.section sp1ta
+.section sp1tb
+.section sp1ua
+.section sp1ub
+.section sp1va
+.section sp1vb
+.section sp1wa
+.section sp1wb
+.section sp1xa
+.section sp1xb
+.section sp1ya
+.section sp1yb
+.section sp1za
+.section sp1zb
+.section sp11a
+.section sp11b
+.section sp12a
+.section sp12b
+.section sp13a
+.section sp13b
+.section sp14a
+.section sp14b
+.section sp15a
+.section sp15b
+.section sp16a
+.section sp16b
+.section sp17a
+.section sp17b
+.section sp18a
+.section sp18b
+.section sp19a
+.section sp19b
+.section sp10a
+.section sp10b
+.section sp2aa
+.section sp2ab
+.section sp2ba
+.section sp2bb
+.section sp2ca
+.section sp2cb
+.section sp2da
+.section sp2db
+.section sp2ea
+.section sp2eb
+.section sp2fa
+.section sp2fb
+.section sp2ga
+.section sp2gb
+.section sp2ha
+.section sp2hb
+.section sp2ia
+.section sp2ib
+.section sp2ja
+.section sp2jb
+.section sp2ka
+.section sp2kb
+.section sp2la
+.section sp2lb
+.section sp2ma
+.section sp2mb
+.section sp2na
+.section sp2nb
+.section sp2oa
+.section sp2ob
+.section sp2pa
+.section sp2pb
+.section sp2qa
+.section sp2qb
+.section sp2ra
+.section sp2rb
+.section sp2sa
+.section sp2sb
+.section sp2ta
+.section sp2tb
+.section sp2ua
+.section sp2ub
+.section sp2va
+.section sp2vb
+.section sp2wa
+.section sp2wb
+.section sp2xa
+.section sp2xb
+.section sp2ya
+.section sp2yb
+.section sp2za
+.section sp2zb
+.section sp21a
+.section sp21b
+.section sp22a
+.section sp22b
+.section sp23a
+.section sp23b
+.section sp24a
+.section sp24b
+.section sp25a
+.section sp25b
+.section sp26a
+.section sp26b
+.section sp27a
+.section sp27b
+.section sp28a
+.section sp28b
+.section sp29a
+.section sp29b
+.section sp20a
+.section sp20b
+.section sp3aa
+.section sp3ab
+.section sp3ba
+.section sp3bb
+.section sp3ca
+.section sp3cb
+.section sp3da
+.section sp3db
+.section sp3ea
+.section sp3eb
+.section sp3fa
+.section sp3fb
+.section sp3ga
+.section sp3gb
+.section sp3ha
+.section sp3hb
+.section sp3ia
+.section sp3ib
+.section sp3ja
+.section sp3jb
+.section sp3ka
+.section sp3kb
+.section sp3la
+.section sp3lb
+.section sp3ma
+.section sp3mb
+.section sp3na
+.section sp3nb
+.section sp3oa
+.section sp3ob
+.section sp3pa
+.section sp3pb
+.section sp3qa
+.section sp3qb
+.section sp3ra
+.section sp3rb
+.section sp3sa
+.section sp3sb
+.section sp3ta
+.section sp3tb
+.section sp3ua
+.section sp3ub
+.section sp3va
+.section sp3vb
+.section sp3wa
+.section sp3wb
+.section sp3xa
+.section sp3xb
+.section sp3ya
+.section sp3yb
+.section sp3za
+.section sp3zb
+.section sp31a
+.section sp31b
+.section sp32a
+.section sp32b
+.section sp33a
+.section sp33b
+.section sp34a
+.section sp34b
+.section sp35a
+.section sp35b
+.section sp36a
+.section sp36b
+.section sp37a
+.section sp37b
+.section sp38a
+.section sp38b
+.section sp39a
+.section sp39b
+.section sp30a
+.section sp30b
+.section sp4aa
+.section sp4ab
+.section sp4ba
+.section sp4bb
+.section sp4ca
+.section sp4cb
+.section sp4da
+.section sp4db
+.section sp4ea
+.section sp4eb
+.section sp4fa
+.section sp4fb
+.section sp4ga
+.section sp4gb
+.section sp4ha
+.section sp4hb
+.section sp4ia
+.section sp4ib
+.section sp4ja
+.section sp4jb
+.section sp4ka
+.section sp4kb
+.section sp4la
+.section sp4lb
+.section sp4ma
+.section sp4mb
+.section sp4na
+.section sp4nb
+.section sp4oa
+.section sp4ob
+.section sp4pa
+.section sp4pb
+.section sp4qa
+.section sp4qb
+.section sp4ra
+.section sp4rb
+.section sp4sa
+.section sp4sb
+.section sp4ta
+.section sp4tb
+.section sp4ua
+.section sp4ub
+.section sp4va
+.section sp4vb
+.section sp4wa
+.section sp4wb
+.section sp4xa
+.section sp4xb
+.section sp4ya
+.section sp4yb
+.section sp4za
+.section sp4zb
+.section sp41a
+.section sp41b
+.section sp42a
+.section sp42b
+.section sp43a
+.section sp43b
+.section sp44a
+.section sp44b
+.section sp45a
+.section sp45b
+.section sp46a
+.section sp46b
+.section sp47a
+.section sp47b
+.section sp48a
+.section sp48b
+.section sp49a
+.section sp49b
+.section sp40a
+.section sp40b
+.section sp5aa
+.section sp5ab
+.section sp5ba
+.section sp5bb
+.section sp5ca
+.section sp5cb
+.section sp5da
+.section sp5db
+.section sp5ea
+.section sp5eb
+.section sp5fa
+.section sp5fb
+.section sp5ga
+.section sp5gb
+.section sp5ha
+.section sp5hb
+.section sp5ia
+.section sp5ib
+.section sp5ja
+.section sp5jb
+.section sp5ka
+.section sp5kb
+.section sp5la
+.section sp5lb
+.section sp5ma
+.section sp5mb
+.section sp5na
+.section sp5nb
+.section sp5oa
+.section sp5ob
+.section sp5pa
+.section sp5pb
+.section sp5qa
+.section sp5qb
+.section sp5ra
+.section sp5rb
+.section sp5sa
+.section sp5sb
+.section sp5ta
+.section sp5tb
+.section sp5ua
+.section sp5ub
+.section sp5va
+.section sp5vb
+.section sp5wa
+.section sp5wb
+.section sp5xa
+.section sp5xb
+.section sp5ya
+.section sp5yb
+.section sp5za
+.section sp5zb
+.section sp51a
+.section sp51b
+.section sp52a
+.section sp52b
+.section sp53a
+.section sp53b
+.section sp54a
+.section sp54b
+.section sp55a
+.section sp55b
+.section sp56a
+.section sp56b
+.section sp57a
+.section sp57b
+.section sp58a
+.section sp58b
+.section sp59a
+.section sp59b
+.section sp50a
+.section sp50b
+.section sp6aa
+.section sp6ab
+.section sp6ba
+.section sp6bb
+.section sp6ca
+.section sp6cb
+.section sp6da
+.section sp6db
+.section sp6ea
+.section sp6eb
+.section sp6fa
+.section sp6fb
+.section sp6ga
+.section sp6gb
+.section sp6ha
+.section sp6hb
+.section sp6ia
+.section sp6ib
+.section sp6ja
+.section sp6jb
+.section sp6ka
+.section sp6kb
+.section sp6la
+.section sp6lb
+.section sp6ma
+.section sp6mb
+.section sp6na
+.section sp6nb
+.section sp6oa
+.section sp6ob
+.section sp6pa
+.section sp6pb
+.section sp6qa
+.section sp6qb
+.section sp6ra
+.section sp6rb
+.section sp6sa
+.section sp6sb
+.section sp6ta
+.section sp6tb
+.section sp6ua
+.section sp6ub
+.section sp6va
+.section sp6vb
+.section sp6wa
+.section sp6wb
+.section sp6xa
+.section sp6xb
+.section sp6ya
+.section sp6yb
+.section sp6za
+.section sp6zb
+.section sp61a
+.section sp61b
+.section sp62a
+.section sp62b
+.section sp63a
+.section sp63b
+.section sp64a
+.section sp64b
+.section sp65a
+.section sp65b
+.section sp66a
+.section sp66b
+.section sp67a
+.section sp67b
+.section sp68a
+.section sp68b
+.section sp69a
+.section sp69b
+.section sp60a
+.section sp60b
+.section sp7aa
+.section sp7ab
+.section sp7ba
+.section sp7bb
+.section sp7ca
+.section sp7cb
+.section sp7da
+.section sp7db
+.section sp7ea
+.section sp7eb
+.section sp7fa
+.section sp7fb
+.section sp7ga
+.section sp7gb
+.section sp7ha
+.section sp7hb
+.section sp7ia
+.section sp7ib
+.section sp7ja
+.section sp7jb
+.section sp7ka
+.section sp7kb
+.section sp7la
+.section sp7lb
+.section sp7ma
+.section sp7mb
+.section sp7na
+.section sp7nb
+.section sp7oa
+.section sp7ob
+.section sp7pa
+.section sp7pb
+.section sp7qa
+.section sp7qb
+.section sp7ra
+.section sp7rb
+.section sp7sa
+.section sp7sb
+.section sp7ta
+.section sp7tb
+.section sp7ua
+.section sp7ub
+.section sp7va
+.section sp7vb
+.section sp7wa
+.section sp7wb
+.section sp7xa
+.section sp7xb
+.section sp7ya
+.section sp7yb
+.section sp7za
+.section sp7zb
+.section sp71a
+.section sp71b
+.section sp72a
+.section sp72b
+.section sp73a
+.section sp73b
+.section sp74a
+.section sp74b
+.section sp75a
+.section sp75b
+.section sp76a
+.section sp76b
+.section sp77a
+.section sp77b
+.section sp78a
+.section sp78b
+.section sp79a
+.section sp79b
+.section sp70a
+.section sp70b
+.section sp8aa
+.section sp8ab
+.section sp8ba
+.section sp8bb
+.section sp8ca
+.section sp8cb
+.section sp8da
+.section sp8db
+.section sp8ea
+.section sp8eb
+.section sp8fa
+.section sp8fb
+.section sp8ga
+.section sp8gb
+.section sp8ha
+.section sp8hb
+.section sp8ia
+.section sp8ib
+.section sp8ja
+.section sp8jb
+.section sp8ka
+.section sp8kb
+.section sp8la
+.section sp8lb
+.section sp8ma
+.section sp8mb
+.section sp8na
+.section sp8nb
+.section sp8oa
+.section sp8ob
+.section sp8pa
+.section sp8pb
+.section sp8qa
+.section sp8qb
+.section sp8ra
+.section sp8rb
+.section sp8sa
+.section sp8sb
+.section sp8ta
+.section sp8tb
+.section sp8ua
+.section sp8ub
+.section sp8va
+.section sp8vb
+.section sp8wa
+.section sp8wb
+.section sp8xa
+.section sp8xb
+.section sp8ya
+.section sp8yb
+.section sp8za
+.section sp8zb
+.section sp81a
+.section sp81b
+.section sp82a
+.section sp82b
+.section sp83a
+.section sp83b
+.section sp84a
+.section sp84b
+.section sp85a
+.section sp85b
+.section sp86a
+.section sp86b
+.section sp87a
+.section sp87b
+.section sp88a
+.section sp88b
+.section sp89a
+.section sp89b
+.section sp80a
+.section sp80b
+.section sp9aa
+.section sp9ab
+.section sp9ba
+.section sp9bb
+.section sp9ca
+.section sp9cb
+.section sp9da
+.section sp9db
+.section sp9ea
+.section sp9eb
+.section sp9fa
+.section sp9fb
+.section sp9ga
+.section sp9gb
+.section sp9ha
+.section sp9hb
+.section sp9ia
+.section sp9ib
+.section sp9ja
+.section sp9jb
+.section sp9ka
+.section sp9kb
+.section sp9la
+.section sp9lb
+.section sp9ma
+.section sp9mb
+.section sp9na
+.section sp9nb
+.section sp9oa
+.section sp9ob
+.section sp9pa
+.section sp9pb
+.section sp9qa
+.section sp9qb
+.section sp9ra
+.section sp9rb
+.section sp9sa
+.section sp9sb
+.section sp9ta
+.section sp9tb
+.section sp9ua
+.section sp9ub
+.section sp9va
+.section sp9vb
+.section sp9wa
+.section sp9wb
+.section sp9xa
+.section sp9xb
+.section sp9ya
+.section sp9yb
+.section sp9za
+.section sp9zb
+.section sp91a
+.section sp91b
+.section sp92a
+.section sp92b
+.section sp93a
+.section sp93b
+.section sp94a
+.section sp94b
+.section sp95a
+.section sp95b
+.section sp96a
+.section sp96b
+.section sp97a
+.section sp97b
+.section sp98a
+.section sp98b
+.section sp99a
+.section sp99b
+.section sp90a
+.section sp90b
+.section sp0aa
+.section sp0ab
+.section sp0ba
+.section sp0bb
+.section sp0ca
+.section sp0cb
+.section sp0da
+.section sp0db
+.section sp0ea
+.section sp0eb
+.section sp0fa
+.section sp0fb
+.section sp0ga
+.section sp0gb
+.section sp0ha
+.section sp0hb
+.section sp0ia
+.section sp0ib
+.section sp0ja
+.section sp0jb
+.section sp0ka
+.section sp0kb
+.section sp0la
+.section sp0lb
+.section sp0ma
+.section sp0mb
+.section sp0na
+.section sp0nb
+.section sp0oa
+.section sp0ob
+.section sp0pa
+.section sp0pb
+.section sp0qa
+.section sp0qb
+.section sp0ra
+.section sp0rb
+.section sp0sa
+.section sp0sb
+.section sp0ta
+.section sp0tb
+.section sp0ua
+.section sp0ub
+.section sp0va
+.section sp0vb
+.section sp0wa
+.section sp0wb
+.section sp0xa
+.section sp0xb
+.section sp0ya
+.section sp0yb
+.section sp0za
+.section sp0zb
+.section sp01a
+.section sp01b
+.section sp02a
+.section sp02b
+.section sp03a
+.section sp03b
+.section sp04a
+.section sp04b
+.section sp05a
+.section sp05b
+.section sp06a
+.section sp06b
+.section sp07a
+.section sp07b
+.section sp08a
+.section sp08b
+.section sp09a
+.section sp09b
+.section sp00a
+.section sp00b
+.section sqaaa
+.section sqaab
+.section sqaba
+.section sqabb
+.section sqaca
+.section sqacb
+.section sqada
+.section sqadb
+.section sqaea
+.section sqaeb
+.section sqafa
+.section sqafb
+.section sqaga
+.section sqagb
+.section sqaha
+.section sqahb
+.section sqaia
+.section sqaib
+.section sqaja
+.section sqajb
+.section sqaka
+.section sqakb
+.section sqala
+.section sqalb
+.section sqama
+.section sqamb
+.section sqana
+.section sqanb
+.section sqaoa
+.section sqaob
+.section sqapa
+.section sqapb
+.section sqaqa
+.section sqaqb
+.section sqara
+.section sqarb
+.section sqasa
+.section sqasb
+.section sqata
+.section sqatb
+.section sqaua
+.section sqaub
+.section sqava
+.section sqavb
+.section sqawa
+.section sqawb
+.section sqaxa
+.section sqaxb
+.section sqaya
+.section sqayb
+.section sqaza
+.section sqazb
+.section sqa1a
+.section sqa1b
+.section sqa2a
+.section sqa2b
+.section sqa3a
+.section sqa3b
+.section sqa4a
+.section sqa4b
+.section sqa5a
+.section sqa5b
+.section sqa6a
+.section sqa6b
+.section sqa7a
+.section sqa7b
+.section sqa8a
+.section sqa8b
+.section sqa9a
+.section sqa9b
+.section sqa0a
+.section sqa0b
+.section sqbaa
+.section sqbab
+.section sqbba
+.section sqbbb
+.section sqbca
+.section sqbcb
+.section sqbda
+.section sqbdb
+.section sqbea
+.section sqbeb
+.section sqbfa
+.section sqbfb
+.section sqbga
+.section sqbgb
+.section sqbha
+.section sqbhb
+.section sqbia
+.section sqbib
+.section sqbja
+.section sqbjb
+.section sqbka
+.section sqbkb
+.section sqbla
+.section sqblb
+.section sqbma
+.section sqbmb
+.section sqbna
+.section sqbnb
+.section sqboa
+.section sqbob
+.section sqbpa
+.section sqbpb
+.section sqbqa
+.section sqbqb
+.section sqbra
+.section sqbrb
+.section sqbsa
+.section sqbsb
+.section sqbta
+.section sqbtb
+.section sqbua
+.section sqbub
+.section sqbva
+.section sqbvb
+.section sqbwa
+.section sqbwb
+.section sqbxa
+.section sqbxb
+.section sqbya
+.section sqbyb
+.section sqbza
+.section sqbzb
+.section sqb1a
+.section sqb1b
+.section sqb2a
+.section sqb2b
+.section sqb3a
+.section sqb3b
+.section sqb4a
+.section sqb4b
+.section sqb5a
+.section sqb5b
+.section sqb6a
+.section sqb6b
+.section sqb7a
+.section sqb7b
+.section sqb8a
+.section sqb8b
+.section sqb9a
+.section sqb9b
+.section sqb0a
+.section sqb0b
+.section sqcaa
+.section sqcab
+.section sqcba
+.section sqcbb
+.section sqcca
+.section sqccb
+.section sqcda
+.section sqcdb
+.section sqcea
+.section sqceb
+.section sqcfa
+.section sqcfb
+.section sqcga
+.section sqcgb
+.section sqcha
+.section sqchb
+.section sqcia
+.section sqcib
+.section sqcja
+.section sqcjb
+.section sqcka
+.section sqckb
+.section sqcla
+.section sqclb
+.section sqcma
+.section sqcmb
+.section sqcna
+.section sqcnb
+.section sqcoa
+.section sqcob
+.section sqcpa
+.section sqcpb
+.section sqcqa
+.section sqcqb
+.section sqcra
+.section sqcrb
+.section sqcsa
+.section sqcsb
+.section sqcta
+.section sqctb
+.section sqcua
+.section sqcub
+.section sqcva
+.section sqcvb
+.section sqcwa
+.section sqcwb
+.section sqcxa
+.section sqcxb
+.section sqcya
+.section sqcyb
+.section sqcza
+.section sqczb
+.section sqc1a
+.section sqc1b
+.section sqc2a
+.section sqc2b
+.section sqc3a
+.section sqc3b
+.section sqc4a
+.section sqc4b
+.section sqc5a
+.section sqc5b
+.section sqc6a
+.section sqc6b
+.section sqc7a
+.section sqc7b
+.section sqc8a
+.section sqc8b
+.section sqc9a
+.section sqc9b
+.section sqc0a
+.section sqc0b
+.section sqdaa
+.section sqdab
+.section sqdba
+.section sqdbb
+.section sqdca
+.section sqdcb
+.section sqdda
+.section sqddb
+.section sqdea
+.section sqdeb
+.section sqdfa
+.section sqdfb
+.section sqdga
+.section sqdgb
+.section sqdha
+.section sqdhb
+.section sqdia
+.section sqdib
+.section sqdja
+.section sqdjb
+.section sqdka
+.section sqdkb
+.section sqdla
+.section sqdlb
+.section sqdma
+.section sqdmb
+.section sqdna
+.section sqdnb
+.section sqdoa
+.section sqdob
+.section sqdpa
+.section sqdpb
+.section sqdqa
+.section sqdqb
+.section sqdra
+.section sqdrb
+.section sqdsa
+.section sqdsb
+.section sqdta
+.section sqdtb
+.section sqdua
+.section sqdub
+.section sqdva
+.section sqdvb
+.section sqdwa
+.section sqdwb
+.section sqdxa
+.section sqdxb
+.section sqdya
+.section sqdyb
+.section sqdza
+.section sqdzb
+.section sqd1a
+.section sqd1b
+.section sqd2a
+.section sqd2b
+.section sqd3a
+.section sqd3b
+.section sqd4a
+.section sqd4b
+.section sqd5a
+.section sqd5b
+.section sqd6a
+.section sqd6b
+.section sqd7a
+.section sqd7b
+.section sqd8a
+.section sqd8b
+.section sqd9a
+.section sqd9b
+.section sqd0a
+.section sqd0b
+.section sqeaa
+.section sqeab
+.section sqeba
+.section sqebb
+.section sqeca
+.section sqecb
+.section sqeda
+.section sqedb
+.section sqeea
+.section sqeeb
+.section sqefa
+.section sqefb
+.section sqega
+.section sqegb
+.section sqeha
+.section sqehb
+.section sqeia
+.section sqeib
+.section sqeja
+.section sqejb
+.section sqeka
+.section sqekb
+.section sqela
+.section sqelb
+.section sqema
+.section sqemb
+.section sqena
+.section sqenb
+.section sqeoa
+.section sqeob
+.section sqepa
+.section sqepb
+.section sqeqa
+.section sqeqb
+.section sqera
+.section sqerb
+.section sqesa
+.section sqesb
+.section sqeta
+.section sqetb
+.section sqeua
+.section sqeub
+.section sqeva
+.section sqevb
+.section sqewa
+.section sqewb
+.section sqexa
+.section sqexb
+.section sqeya
+.section sqeyb
+.section sqeza
+.section sqezb
+.section sqe1a
+.section sqe1b
+.section sqe2a
+.section sqe2b
+.section sqe3a
+.section sqe3b
+.section sqe4a
+.section sqe4b
+.section sqe5a
+.section sqe5b
+.section sqe6a
+.section sqe6b
+.section sqe7a
+.section sqe7b
+.section sqe8a
+.section sqe8b
+.section sqe9a
+.section sqe9b
+.section sqe0a
+.section sqe0b
+.section sqfaa
+.section sqfab
+.section sqfba
+.section sqfbb
+.section sqfca
+.section sqfcb
+.section sqfda
+.section sqfdb
+.section sqfea
+.section sqfeb
+.section sqffa
+.section sqffb
+.section sqfga
+.section sqfgb
+.section sqfha
+.section sqfhb
+.section sqfia
+.section sqfib
+.section sqfja
+.section sqfjb
+.section sqfka
+.section sqfkb
+.section sqfla
+.section sqflb
+.section sqfma
+.section sqfmb
+.section sqfna
+.section sqfnb
+.section sqfoa
+.section sqfob
+.section sqfpa
+.section sqfpb
+.section sqfqa
+.section sqfqb
+.section sqfra
+.section sqfrb
+.section sqfsa
+.section sqfsb
+.section sqfta
+.section sqftb
+.section sqfua
+.section sqfub
+.section sqfva
+.section sqfvb
+.section sqfwa
+.section sqfwb
+.section sqfxa
+.section sqfxb
+.section sqfya
+.section sqfyb
+.section sqfza
+.section sqfzb
+.section sqf1a
+.section sqf1b
+.section sqf2a
+.section sqf2b
+.section sqf3a
+.section sqf3b
+.section sqf4a
+.section sqf4b
+.section sqf5a
+.section sqf5b
+.section sqf6a
+.section sqf6b
+.section sqf7a
+.section sqf7b
+.section sqf8a
+.section sqf8b
+.section sqf9a
+.section sqf9b
+.section sqf0a
+.section sqf0b
+.section sqgaa
+.section sqgab
+.section sqgba
+.section sqgbb
+.section sqgca
+.section sqgcb
+.section sqgda
+.section sqgdb
+.section sqgea
+.section sqgeb
+.section sqgfa
+.section sqgfb
+.section sqgga
+.section sqggb
+.section sqgha
+.section sqghb
+.section sqgia
+.section sqgib
+.section sqgja
+.section sqgjb
+.section sqgka
+.section sqgkb
+.section sqgla
+.section sqglb
+.section sqgma
+.section sqgmb
+.section sqgna
+.section sqgnb
+.section sqgoa
+.section sqgob
+.section sqgpa
+.section sqgpb
+.section sqgqa
+.section sqgqb
+.section sqgra
+.section sqgrb
+.section sqgsa
+.section sqgsb
+.section sqgta
+.section sqgtb
+.section sqgua
+.section sqgub
+.section sqgva
+.section sqgvb
+.section sqgwa
+.section sqgwb
+.section sqgxa
+.section sqgxb
+.section sqgya
+.section sqgyb
+.section sqgza
+.section sqgzb
+.section sqg1a
+.section sqg1b
+.section sqg2a
+.section sqg2b
+.section sqg3a
+.section sqg3b
+.section sqg4a
+.section sqg4b
+.section sqg5a
+.section sqg5b
+.section sqg6a
+.section sqg6b
+.section sqg7a
+.section sqg7b
+.section sqg8a
+.section sqg8b
+.section sqg9a
+.section sqg9b
+.section sqg0a
+.section sqg0b
+.section sqhaa
+.section sqhab
+.section sqhba
+.section sqhbb
+.section sqhca
+.section sqhcb
+.section sqhda
+.section sqhdb
+.section sqhea
+.section sqheb
+.section sqhfa
+.section sqhfb
+.section sqhga
+.section sqhgb
+.section sqhha
+.section sqhhb
+.section sqhia
+.section sqhib
+.section sqhja
+.section sqhjb
+.section sqhka
+.section sqhkb
+.section sqhla
+.section sqhlb
+.section sqhma
+.section sqhmb
+.section sqhna
+.section sqhnb
+.section sqhoa
+.section sqhob
+.section sqhpa
+.section sqhpb
+.section sqhqa
+.section sqhqb
+.section sqhra
+.section sqhrb
+.section sqhsa
+.section sqhsb
+.section sqhta
+.section sqhtb
+.section sqhua
+.section sqhub
+.section sqhva
+.section sqhvb
+.section sqhwa
+.section sqhwb
+.section sqhxa
+.section sqhxb
+.section sqhya
+.section sqhyb
+.section sqhza
+.section sqhzb
+.section sqh1a
+.section sqh1b
+.section sqh2a
+.section sqh2b
+.section sqh3a
+.section sqh3b
+.section sqh4a
+.section sqh4b
+.section sqh5a
+.section sqh5b
+.section sqh6a
+.section sqh6b
+.section sqh7a
+.section sqh7b
+.section sqh8a
+.section sqh8b
+.section sqh9a
+.section sqh9b
+.section sqh0a
+.section sqh0b
+.section sqiaa
+.section sqiab
+.section sqiba
+.section sqibb
+.section sqica
+.section sqicb
+.section sqida
+.section sqidb
+.section sqiea
+.section sqieb
+.section sqifa
+.section sqifb
+.section sqiga
+.section sqigb
+.section sqiha
+.section sqihb
+.section sqiia
+.section sqiib
+.section sqija
+.section sqijb
+.section sqika
+.section sqikb
+.section sqila
+.section sqilb
+.section sqima
+.section sqimb
+.section sqina
+.section sqinb
+.section sqioa
+.section sqiob
+.section sqipa
+.section sqipb
+.section sqiqa
+.section sqiqb
+.section sqira
+.section sqirb
+.section sqisa
+.section sqisb
+.section sqita
+.section sqitb
+.section sqiua
+.section sqiub
+.section sqiva
+.section sqivb
+.section sqiwa
+.section sqiwb
+.section sqixa
+.section sqixb
+.section sqiya
+.section sqiyb
+.section sqiza
+.section sqizb
+.section sqi1a
+.section sqi1b
+.section sqi2a
+.section sqi2b
+.section sqi3a
+.section sqi3b
+.section sqi4a
+.section sqi4b
+.section sqi5a
+.section sqi5b
+.section sqi6a
+.section sqi6b
+.section sqi7a
+.section sqi7b
+.section sqi8a
+.section sqi8b
+.section sqi9a
+.section sqi9b
+.section sqi0a
+.section sqi0b
+.section sqjaa
+.section sqjab
+.section sqjba
+.section sqjbb
+.section sqjca
+.section sqjcb
+.section sqjda
+.section sqjdb
+.section sqjea
+.section sqjeb
+.section sqjfa
+.section sqjfb
+.section sqjga
+.section sqjgb
+.section sqjha
+.section sqjhb
+.section sqjia
+.section sqjib
+.section sqjja
+.section sqjjb
+.section sqjka
+.section sqjkb
+.section sqjla
+.section sqjlb
+.section sqjma
+.section sqjmb
+.section sqjna
+.section sqjnb
+.section sqjoa
+.section sqjob
+.section sqjpa
+.section sqjpb
+.section sqjqa
+.section sqjqb
+.section sqjra
+.section sqjrb
+.section sqjsa
+.section sqjsb
+.section sqjta
+.section sqjtb
+.section sqjua
+.section sqjub
+.section sqjva
+.section sqjvb
+.section sqjwa
+.section sqjwb
+.section sqjxa
+.section sqjxb
+.section sqjya
+.section sqjyb
+.section sqjza
+.section sqjzb
+.section sqj1a
+.section sqj1b
+.section sqj2a
+.section sqj2b
+.section sqj3a
+.section sqj3b
+.section sqj4a
+.section sqj4b
+.section sqj5a
+.section sqj5b
+.section sqj6a
+.section sqj6b
+.section sqj7a
+.section sqj7b
+.section sqj8a
+.section sqj8b
+.section sqj9a
+.section sqj9b
+.section sqj0a
+.section sqj0b
+.section sqkaa
+.section sqkab
+.section sqkba
+.section sqkbb
+.section sqkca
+.section sqkcb
+.section sqkda
+.section sqkdb
+.section sqkea
+.section sqkeb
+.section sqkfa
+.section sqkfb
+.section sqkga
+.section sqkgb
+.section sqkha
+.section sqkhb
+.section sqkia
+.section sqkib
+.section sqkja
+.section sqkjb
+.section sqkka
+.section sqkkb
+.section sqkla
+.section sqklb
+.section sqkma
+.section sqkmb
+.section sqkna
+.section sqknb
+.section sqkoa
+.section sqkob
+.section sqkpa
+.section sqkpb
+.section sqkqa
+.section sqkqb
+.section sqkra
+.section sqkrb
+.section sqksa
+.section sqksb
+.section sqkta
+.section sqktb
+.section sqkua
+.section sqkub
+.section sqkva
+.section sqkvb
+.section sqkwa
+.section sqkwb
+.section sqkxa
+.section sqkxb
+.section sqkya
+.section sqkyb
+.section sqkza
+.section sqkzb
+.section sqk1a
+.section sqk1b
+.section sqk2a
+.section sqk2b
+.section sqk3a
+.section sqk3b
+.section sqk4a
+.section sqk4b
+.section sqk5a
+.section sqk5b
+.section sqk6a
+.section sqk6b
+.section sqk7a
+.section sqk7b
+.section sqk8a
+.section sqk8b
+.section sqk9a
+.section sqk9b
+.section sqk0a
+.section sqk0b
+.section sqlaa
+.section sqlab
+.section sqlba
+.section sqlbb
+.section sqlca
+.section sqlcb
+.section sqlda
+.section sqldb
+.section sqlea
+.section sqleb
+.section sqlfa
+.section sqlfb
+.section sqlga
+.section sqlgb
+.section sqlha
+.section sqlhb
+.section sqlia
+.section sqlib
+.section sqlja
+.section sqljb
+.section sqlka
+.section sqlkb
+.section sqlla
+.section sqllb
+.section sqlma
+.section sqlmb
+.section sqlna
+.section sqlnb
+.section sqloa
+.section sqlob
+.section sqlpa
+.section sqlpb
+.section sqlqa
+.section sqlqb
+.section sqlra
+.section sqlrb
+.section sqlsa
+.section sqlsb
+.section sqlta
+.section sqltb
+.section sqlua
+.section sqlub
+.section sqlva
+.section sqlvb
+.section sqlwa
+.section sqlwb
+.section sqlxa
+.section sqlxb
+.section sqlya
+.section sqlyb
+.section sqlza
+.section sqlzb
+.section sql1a
+.section sql1b
+.section sql2a
+.section sql2b
+.section sql3a
+.section sql3b
+.section sql4a
+.section sql4b
+.section sql5a
+.section sql5b
+.section sql6a
+.section sql6b
+.section sql7a
+.section sql7b
+.section sql8a
+.section sql8b
+.section sql9a
+.section sql9b
+.section sql0a
+.section sql0b
+.section sqmaa
+.section sqmab
+.section sqmba
+.section sqmbb
+.section sqmca
+.section sqmcb
+.section sqmda
+.section sqmdb
+.section sqmea
+.section sqmeb
+.section sqmfa
+.section sqmfb
+.section sqmga
+.section sqmgb
+.section sqmha
+.section sqmhb
+.section sqmia
+.section sqmib
+.section sqmja
+.section sqmjb
+.section sqmka
+.section sqmkb
+.section sqmla
+.section sqmlb
+.section sqmma
+.section sqmmb
+.section sqmna
+.section sqmnb
+.section sqmoa
+.section sqmob
+.section sqmpa
+.section sqmpb
+.section sqmqa
+.section sqmqb
+.section sqmra
+.section sqmrb
+.section sqmsa
+.section sqmsb
+.section sqmta
+.section sqmtb
+.section sqmua
+.section sqmub
+.section sqmva
+.section sqmvb
+.section sqmwa
+.section sqmwb
+.section sqmxa
+.section sqmxb
+.section sqmya
+.section sqmyb
+.section sqmza
+.section sqmzb
+.section sqm1a
+.section sqm1b
+.section sqm2a
+.section sqm2b
+.section sqm3a
+.section sqm3b
+.section sqm4a
+.section sqm4b
+.section sqm5a
+.section sqm5b
+.section sqm6a
+.section sqm6b
+.section sqm7a
+.section sqm7b
+.section sqm8a
+.section sqm8b
+.section sqm9a
+.section sqm9b
+.section sqm0a
+.section sqm0b
+.section sqnaa
+.section sqnab
+.section sqnba
+.section sqnbb
+.section sqnca
+.section sqncb
+.section sqnda
+.section sqndb
+.section sqnea
+.section sqneb
+.section sqnfa
+.section sqnfb
+.section sqnga
+.section sqngb
+.section sqnha
+.section sqnhb
+.section sqnia
+.section sqnib
+.section sqnja
+.section sqnjb
+.section sqnka
+.section sqnkb
+.section sqnla
+.section sqnlb
+.section sqnma
+.section sqnmb
+.section sqnna
+.section sqnnb
+.section sqnoa
+.section sqnob
+.section sqnpa
+.section sqnpb
+.section sqnqa
+.section sqnqb
+.section sqnra
+.section sqnrb
+.section sqnsa
+.section sqnsb
+.section sqnta
+.section sqntb
+.section sqnua
+.section sqnub
+.section sqnva
+.section sqnvb
+.section sqnwa
+.section sqnwb
+.section sqnxa
+.section sqnxb
+.section sqnya
+.section sqnyb
+.section sqnza
+.section sqnzb
+.section sqn1a
+.section sqn1b
+.section sqn2a
+.section sqn2b
+.section sqn3a
+.section sqn3b
+.section sqn4a
+.section sqn4b
+.section sqn5a
+.section sqn5b
+.section sqn6a
+.section sqn6b
+.section sqn7a
+.section sqn7b
+.section sqn8a
+.section sqn8b
+.section sqn9a
+.section sqn9b
+.section sqn0a
+.section sqn0b
+.section sqoaa
+.section sqoab
+.section sqoba
+.section sqobb
+.section sqoca
+.section sqocb
+.section sqoda
+.section sqodb
+.section sqoea
+.section sqoeb
+.section sqofa
+.section sqofb
+.section sqoga
+.section sqogb
+.section sqoha
+.section sqohb
+.section sqoia
+.section sqoib
+.section sqoja
+.section sqojb
+.section sqoka
+.section sqokb
+.section sqola
+.section sqolb
+.section sqoma
+.section sqomb
+.section sqona
+.section sqonb
+.section sqooa
+.section sqoob
+.section sqopa
+.section sqopb
+.section sqoqa
+.section sqoqb
+.section sqora
+.section sqorb
+.section sqosa
+.section sqosb
+.section sqota
+.section sqotb
+.section sqoua
+.section sqoub
+.section sqova
+.section sqovb
+.section sqowa
+.section sqowb
+.section sqoxa
+.section sqoxb
+.section sqoya
+.section sqoyb
+.section sqoza
+.section sqozb
+.section sqo1a
+.section sqo1b
+.section sqo2a
+.section sqo2b
+.section sqo3a
+.section sqo3b
+.section sqo4a
+.section sqo4b
+.section sqo5a
+.section sqo5b
+.section sqo6a
+.section sqo6b
+.section sqo7a
+.section sqo7b
+.section sqo8a
+.section sqo8b
+.section sqo9a
+.section sqo9b
+.section sqo0a
+.section sqo0b
+.section sqpaa
+.section sqpab
+.section sqpba
+.section sqpbb
+.section sqpca
+.section sqpcb
+.section sqpda
+.section sqpdb
+.section sqpea
+.section sqpeb
+.section sqpfa
+.section sqpfb
+.section sqpga
+.section sqpgb
+.section sqpha
+.section sqphb
+.section sqpia
+.section sqpib
+.section sqpja
+.section sqpjb
+.section sqpka
+.section sqpkb
+.section sqpla
+.section sqplb
+.section sqpma
+.section sqpmb
+.section sqpna
+.section sqpnb
+.section sqpoa
+.section sqpob
+.section sqppa
+.section sqppb
+.section sqpqa
+.section sqpqb
+.section sqpra
+.section sqprb
+.section sqpsa
+.section sqpsb
+.section sqpta
+.section sqptb
+.section sqpua
+.section sqpub
+.section sqpva
+.section sqpvb
+.section sqpwa
+.section sqpwb
+.section sqpxa
+.section sqpxb
+.section sqpya
+.section sqpyb
+.section sqpza
+.section sqpzb
+.section sqp1a
+.section sqp1b
+.section sqp2a
+.section sqp2b
+.section sqp3a
+.section sqp3b
+.section sqp4a
+.section sqp4b
+.section sqp5a
+.section sqp5b
+.section sqp6a
+.section sqp6b
+.section sqp7a
+.section sqp7b
+.section sqp8a
+.section sqp8b
+.section sqp9a
+.section sqp9b
+.section sqp0a
+.section sqp0b
+.section sqqaa
+.section sqqab
+.section sqqba
+.section sqqbb
+.section sqqca
+.section sqqcb
+.section sqqda
+.section sqqdb
+.section sqqea
+.section sqqeb
+.section sqqfa
+.section sqqfb
+.section sqqga
+.section sqqgb
+.section sqqha
+.section sqqhb
+.section sqqia
+.section sqqib
+.section sqqja
+.section sqqjb
+.section sqqka
+.section sqqkb
+.section sqqla
+.section sqqlb
+.section sqqma
+.section sqqmb
+.section sqqna
+.section sqqnb
+.section sqqoa
+.section sqqob
+.section sqqpa
+.section sqqpb
+.section sqqqa
+.section sqqqb
+.section sqqra
+.section sqqrb
+.section sqqsa
+.section sqqsb
+.section sqqta
+.section sqqtb
+.section sqqua
+.section sqqub
+.section sqqva
+.section sqqvb
+.section sqqwa
+.section sqqwb
+.section sqqxa
+.section sqqxb
+.section sqqya
+.section sqqyb
+.section sqqza
+.section sqqzb
+.section sqq1a
+.section sqq1b
+.section sqq2a
+.section sqq2b
+.section sqq3a
+.section sqq3b
+.section sqq4a
+.section sqq4b
+.section sqq5a
+.section sqq5b
+.section sqq6a
+.section sqq6b
+.section sqq7a
+.section sqq7b
+.section sqq8a
+.section sqq8b
+.section sqq9a
+.section sqq9b
+.section sqq0a
+.section sqq0b
+.section sqraa
+.section sqrab
+.section sqrba
+.section sqrbb
+.section sqrca
+.section sqrcb
+.section sqrda
+.section sqrdb
+.section sqrea
+.section sqreb
+.section sqrfa
+.section sqrfb
+.section sqrga
+.section sqrgb
+.section sqrha
+.section sqrhb
+.section sqria
+.section sqrib
+.section sqrja
+.section sqrjb
+.section sqrka
+.section sqrkb
+.section sqrla
+.section sqrlb
+.section sqrma
+.section sqrmb
+.section sqrna
+.section sqrnb
+.section sqroa
+.section sqrob
+.section sqrpa
+.section sqrpb
+.section sqrqa
+.section sqrqb
+.section sqrra
+.section sqrrb
+.section sqrsa
+.section sqrsb
+.section sqrta
+.section sqrtb
+.section sqrua
+.section sqrub
+.section sqrva
+.section sqrvb
+.section sqrwa
+.section sqrwb
+.section sqrxa
+.section sqrxb
+.section sqrya
+.section sqryb
+.section sqrza
+.section sqrzb
+.section sqr1a
+.section sqr1b
+.section sqr2a
+.section sqr2b
+.section sqr3a
+.section sqr3b
+.section sqr4a
+.section sqr4b
+.section sqr5a
+.section sqr5b
+.section sqr6a
+.section sqr6b
+.section sqr7a
+.section sqr7b
+.section sqr8a
+.section sqr8b
+.section sqr9a
+.section sqr9b
+.section sqr0a
+.section sqr0b
+.section sqsaa
+.section sqsab
+.section sqsba
+.section sqsbb
+.section sqsca
+.section sqscb
+.section sqsda
+.section sqsdb
+.section sqsea
+.section sqseb
+.section sqsfa
+.section sqsfb
+.section sqsga
+.section sqsgb
+.section sqsha
+.section sqshb
+.section sqsia
+.section sqsib
+.section sqsja
+.section sqsjb
+.section sqska
+.section sqskb
+.section sqsla
+.section sqslb
+.section sqsma
+.section sqsmb
+.section sqsna
+.section sqsnb
+.section sqsoa
+.section sqsob
+.section sqspa
+.section sqspb
+.section sqsqa
+.section sqsqb
+.section sqsra
+.section sqsrb
+.section sqssa
+.section sqssb
+.section sqsta
+.section sqstb
+.section sqsua
+.section sqsub
+.section sqsva
+.section sqsvb
+.section sqswa
+.section sqswb
+.section sqsxa
+.section sqsxb
+.section sqsya
+.section sqsyb
+.section sqsza
+.section sqszb
+.section sqs1a
+.section sqs1b
+.section sqs2a
+.section sqs2b
+.section sqs3a
+.section sqs3b
+.section sqs4a
+.section sqs4b
+.section sqs5a
+.section sqs5b
+.section sqs6a
+.section sqs6b
+.section sqs7a
+.section sqs7b
+.section sqs8a
+.section sqs8b
+.section sqs9a
+.section sqs9b
+.section sqs0a
+.section sqs0b
+.section sqtaa
+.section sqtab
+.section sqtba
+.section sqtbb
+.section sqtca
+.section sqtcb
+.section sqtda
+.section sqtdb
+.section sqtea
+.section sqteb
+.section sqtfa
+.section sqtfb
+.section sqtga
+.section sqtgb
+.section sqtha
+.section sqthb
+.section sqtia
+.section sqtib
+.section sqtja
+.section sqtjb
+.section sqtka
+.section sqtkb
+.section sqtla
+.section sqtlb
+.section sqtma
+.section sqtmb
+.section sqtna
+.section sqtnb
+.section sqtoa
+.section sqtob
+.section sqtpa
+.section sqtpb
+.section sqtqa
+.section sqtqb
+.section sqtra
+.section sqtrb
+.section sqtsa
+.section sqtsb
+.section sqtta
+.section sqttb
+.section sqtua
+.section sqtub
+.section sqtva
+.section sqtvb
+.section sqtwa
+.section sqtwb
+.section sqtxa
+.section sqtxb
+.section sqtya
+.section sqtyb
+.section sqtza
+.section sqtzb
+.section sqt1a
+.section sqt1b
+.section sqt2a
+.section sqt2b
+.section sqt3a
+.section sqt3b
+.section sqt4a
+.section sqt4b
+.section sqt5a
+.section sqt5b
+.section sqt6a
+.section sqt6b
+.section sqt7a
+.section sqt7b
+.section sqt8a
+.section sqt8b
+.section sqt9a
+.section sqt9b
+.section sqt0a
+.section sqt0b
+.section squaa
+.section squab
+.section squba
+.section squbb
+.section squca
+.section squcb
+.section squda
+.section squdb
+.section squea
+.section squeb
+.section squfa
+.section squfb
+.section squga
+.section squgb
+.section squha
+.section squhb
+.section squia
+.section squib
+.section squja
+.section squjb
+.section squka
+.section squkb
+.section squla
+.section squlb
+.section squma
+.section squmb
+.section squna
+.section squnb
+.section squoa
+.section squob
+.section squpa
+.section squpb
+.section squqa
+.section squqb
+.section squra
+.section squrb
+.section squsa
+.section squsb
+.section squta
+.section squtb
+.section squua
+.section squub
+.section squva
+.section squvb
+.section squwa
+.section squwb
+.section squxa
+.section squxb
+.section squya
+.section squyb
+.section squza
+.section squzb
+.section squ1a
+.section squ1b
+.section squ2a
+.section squ2b
+.section squ3a
+.section squ3b
+.section squ4a
+.section squ4b
+.section squ5a
+.section squ5b
+.section squ6a
+.section squ6b
+.section squ7a
+.section squ7b
+.section squ8a
+.section squ8b
+.section squ9a
+.section squ9b
+.section squ0a
+.section squ0b
+.section sqvaa
+.section sqvab
+.section sqvba
+.section sqvbb
+.section sqvca
+.section sqvcb
+.section sqvda
+.section sqvdb
+.section sqvea
+.section sqveb
+.section sqvfa
+.section sqvfb
+.section sqvga
+.section sqvgb
+.section sqvha
+.section sqvhb
+.section sqvia
+.section sqvib
+.section sqvja
+.section sqvjb
+.section sqvka
+.section sqvkb
+.section sqvla
+.section sqvlb
+.section sqvma
+.section sqvmb
+.section sqvna
+.section sqvnb
+.section sqvoa
+.section sqvob
+.section sqvpa
+.section sqvpb
+.section sqvqa
+.section sqvqb
+.section sqvra
+.section sqvrb
+.section sqvsa
+.section sqvsb
+.section sqvta
+.section sqvtb
+.section sqvua
+.section sqvub
+.section sqvva
+.section sqvvb
+.section sqvwa
+.section sqvwb
+.section sqvxa
+.section sqvxb
+.section sqvya
+.section sqvyb
+.section sqvza
+.section sqvzb
+.section sqv1a
+.section sqv1b
+.section sqv2a
+.section sqv2b
+.section sqv3a
+.section sqv3b
+.section sqv4a
+.section sqv4b
+.section sqv5a
+.section sqv5b
+.section sqv6a
+.section sqv6b
+.section sqv7a
+.section sqv7b
+.section sqv8a
+.section sqv8b
+.section sqv9a
+.section sqv9b
+.section sqv0a
+.section sqv0b
+.section sqwaa
+.section sqwab
+.section sqwba
+.section sqwbb
+.section sqwca
+.section sqwcb
+.section sqwda
+.section sqwdb
+.section sqwea
+.section sqweb
+.section sqwfa
+.section sqwfb
+.section sqwga
+.section sqwgb
+.section sqwha
+.section sqwhb
+.section sqwia
+.section sqwib
+.section sqwja
+.section sqwjb
+.section sqwka
+.section sqwkb
+.section sqwla
+.section sqwlb
+.section sqwma
+.section sqwmb
+.section sqwna
+.section sqwnb
+.section sqwoa
+.section sqwob
+.section sqwpa
+.section sqwpb
+.section sqwqa
+.section sqwqb
+.section sqwra
+.section sqwrb
+.section sqwsa
+.section sqwsb
+.section sqwta
+.section sqwtb
+.section sqwua
+.section sqwub
+.section sqwva
+.section sqwvb
+.section sqwwa
+.section sqwwb
+.section sqwxa
+.section sqwxb
+.section sqwya
+.section sqwyb
+.section sqwza
+.section sqwzb
+.section sqw1a
+.section sqw1b
+.section sqw2a
+.section sqw2b
+.section sqw3a
+.section sqw3b
+.section sqw4a
+.section sqw4b
+.section sqw5a
+.section sqw5b
+.section sqw6a
+.section sqw6b
+.section sqw7a
+.section sqw7b
+.section sqw8a
+.section sqw8b
+.section sqw9a
+.section sqw9b
+.section sqw0a
+.section sqw0b
+.section sqxaa
+.section sqxab
+.section sqxba
+.section sqxbb
+.section sqxca
+.section sqxcb
+.section sqxda
+.section sqxdb
+.section sqxea
+.section sqxeb
+.section sqxfa
+.section sqxfb
+.section sqxga
+.section sqxgb
+.section sqxha
+.section sqxhb
+.section sqxia
+.section sqxib
+.section sqxja
+.section sqxjb
+.section sqxka
+.section sqxkb
+.section sqxla
+.section sqxlb
+.section sqxma
+.section sqxmb
+.section sqxna
+.section sqxnb
+.section sqxoa
+.section sqxob
+.section sqxpa
+.section sqxpb
+.section sqxqa
+.section sqxqb
+.section sqxra
+.section sqxrb
+.section sqxsa
+.section sqxsb
+.section sqxta
+.section sqxtb
+.section sqxua
+.section sqxub
+.section sqxva
+.section sqxvb
+.section sqxwa
+.section sqxwb
+.section sqxxa
+.section sqxxb
+.section sqxya
+.section sqxyb
+.section sqxza
+.section sqxzb
+.section sqx1a
+.section sqx1b
+.section sqx2a
+.section sqx2b
+.section sqx3a
+.section sqx3b
+.section sqx4a
+.section sqx4b
+.section sqx5a
+.section sqx5b
+.section sqx6a
+.section sqx6b
+.section sqx7a
+.section sqx7b
+.section sqx8a
+.section sqx8b
+.section sqx9a
+.section sqx9b
+.section sqx0a
+.section sqx0b
+.section sqyaa
+.section sqyab
+.section sqyba
+.section sqybb
+.section sqyca
+.section sqycb
+.section sqyda
+.section sqydb
+.section sqyea
+.section sqyeb
+.section sqyfa
+.section sqyfb
+.section sqyga
+.section sqygb
+.section sqyha
+.section sqyhb
+.section sqyia
+.section sqyib
+.section sqyja
+.section sqyjb
+.section sqyka
+.section sqykb
+.section sqyla
+.section sqylb
+.section sqyma
+.section sqymb
+.section sqyna
+.section sqynb
+.section sqyoa
+.section sqyob
+.section sqypa
+.section sqypb
+.section sqyqa
+.section sqyqb
+.section sqyra
+.section sqyrb
+.section sqysa
+.section sqysb
+.section sqyta
+.section sqytb
+.section sqyua
+.section sqyub
+.section sqyva
+.section sqyvb
+.section sqywa
+.section sqywb
+.section sqyxa
+.section sqyxb
+.section sqyya
+.section sqyyb
+.section sqyza
+.section sqyzb
+.section sqy1a
+.section sqy1b
+.section sqy2a
+.section sqy2b
+.section sqy3a
+.section sqy3b
+.section sqy4a
+.section sqy4b
+.section sqy5a
+.section sqy5b
+.section sqy6a
+.section sqy6b
+.section sqy7a
+.section sqy7b
+.section sqy8a
+.section sqy8b
+.section sqy9a
+.section sqy9b
+.section sqy0a
+.section sqy0b
+.section sqzaa
+.section sqzab
+.section sqzba
+.section sqzbb
+.section sqzca
+.section sqzcb
+.section sqzda
+.section sqzdb
+.section sqzea
+.section sqzeb
+.section sqzfa
+.section sqzfb
+.section sqzga
+.section sqzgb
+.section sqzha
+.section sqzhb
+.section sqzia
+.section sqzib
+.section sqzja
+.section sqzjb
+.section sqzka
+.section sqzkb
+.section sqzla
+.section sqzlb
+.section sqzma
+.section sqzmb
+.section sqzna
+.section sqznb
+.section sqzoa
+.section sqzob
+.section sqzpa
+.section sqzpb
+.section sqzqa
+.section sqzqb
+.section sqzra
+.section sqzrb
+.section sqzsa
+.section sqzsb
+.section sqzta
+.section sqztb
+.section sqzua
+.section sqzub
+.section sqzva
+.section sqzvb
+.section sqzwa
+.section sqzwb
+.section sqzxa
+.section sqzxb
+.section sqzya
+.section sqzyb
+.section sqzza
+.section sqzzb
+.section sqz1a
+.section sqz1b
+.section sqz2a
+.section sqz2b
+.section sqz3a
+.section sqz3b
+.section sqz4a
+.section sqz4b
+.section sqz5a
+.section sqz5b
+.section sqz6a
+.section sqz6b
+.section sqz7a
+.section sqz7b
+.section sqz8a
+.section sqz8b
+.section sqz9a
+.section sqz9b
+.section sqz0a
+.section sqz0b
+.section sq1aa
+.section sq1ab
+.section sq1ba
+.section sq1bb
+.section sq1ca
+.section sq1cb
+.section sq1da
+.section sq1db
+.section sq1ea
+.section sq1eb
+.section sq1fa
+.section sq1fb
+.section sq1ga
+.section sq1gb
+.section sq1ha
+.section sq1hb
+.section sq1ia
+.section sq1ib
+.section sq1ja
+.section sq1jb
+.section sq1ka
+.section sq1kb
+.section sq1la
+.section sq1lb
+.section sq1ma
+.section sq1mb
+.section sq1na
+.section sq1nb
+.section sq1oa
+.section sq1ob
+.section sq1pa
+.section sq1pb
+.section sq1qa
+.section sq1qb
+.section sq1ra
+.section sq1rb
+.section sq1sa
+.section sq1sb
+.section sq1ta
+.section sq1tb
+.section sq1ua
+.section sq1ub
+.section sq1va
+.section sq1vb
+.section sq1wa
+.section sq1wb
+.section sq1xa
+.section sq1xb
+.section sq1ya
+.section sq1yb
+.section sq1za
+.section sq1zb
+.section sq11a
+.section sq11b
+.section sq12a
+.section sq12b
+.section sq13a
+.section sq13b
+.section sq14a
+.section sq14b
+.section sq15a
+.section sq15b
+.section sq16a
+.section sq16b
+.section sq17a
+.section sq17b
+.section sq18a
+.section sq18b
+.section sq19a
+.section sq19b
+.section sq10a
+.section sq10b
+.section sq2aa
+.section sq2ab
+.section sq2ba
+.section sq2bb
+.section sq2ca
+.section sq2cb
+.section sq2da
+.section sq2db
+.section sq2ea
+.section sq2eb
+.section sq2fa
+.section sq2fb
+.section sq2ga
+.section sq2gb
+.section sq2ha
+.section sq2hb
+.section sq2ia
+.section sq2ib
+.section sq2ja
+.section sq2jb
+.section sq2ka
+.section sq2kb
+.section sq2la
+.section sq2lb
+.section sq2ma
+.section sq2mb
+.section sq2na
+.section sq2nb
+.section sq2oa
+.section sq2ob
+.section sq2pa
+.section sq2pb
+.section sq2qa
+.section sq2qb
+.section sq2ra
+.section sq2rb
+.section sq2sa
+.section sq2sb
+.section sq2ta
+.section sq2tb
+.section sq2ua
+.section sq2ub
+.section sq2va
+.section sq2vb
+.section sq2wa
+.section sq2wb
+.section sq2xa
+.section sq2xb
+.section sq2ya
+.section sq2yb
+.section sq2za
+.section sq2zb
+.section sq21a
+.section sq21b
+.section sq22a
+.section sq22b
+.section sq23a
+.section sq23b
+.section sq24a
+.section sq24b
+.section sq25a
+.section sq25b
+.section sq26a
+.section sq26b
+.section sq27a
+.section sq27b
+.section sq28a
+.section sq28b
+.section sq29a
+.section sq29b
+.section sq20a
+.section sq20b
+.section sq3aa
+.section sq3ab
+.section sq3ba
+.section sq3bb
+.section sq3ca
+.section sq3cb
+.section sq3da
+.section sq3db
+.section sq3ea
+.section sq3eb
+.section sq3fa
+.section sq3fb
+.section sq3ga
+.section sq3gb
+.section sq3ha
+.section sq3hb
+.section sq3ia
+.section sq3ib
+.section sq3ja
+.section sq3jb
+.section sq3ka
+.section sq3kb
+.section sq3la
+.section sq3lb
+.section sq3ma
+.section sq3mb
+.section sq3na
+.section sq3nb
+.section sq3oa
+.section sq3ob
+.section sq3pa
+.section sq3pb
+.section sq3qa
+.section sq3qb
+.section sq3ra
+.section sq3rb
+.section sq3sa
+.section sq3sb
+.section sq3ta
+.section sq3tb
+.section sq3ua
+.section sq3ub
+.section sq3va
+.section sq3vb
+.section sq3wa
+.section sq3wb
+.section sq3xa
+.section sq3xb
+.section sq3ya
+.section sq3yb
+.section sq3za
+.section sq3zb
+.section sq31a
+.section sq31b
+.section sq32a
+.section sq32b
+.section sq33a
+.section sq33b
+.section sq34a
+.section sq34b
+.section sq35a
+.section sq35b
+.section sq36a
+.section sq36b
+.section sq37a
+.section sq37b
+.section sq38a
+.section sq38b
+.section sq39a
+.section sq39b
+.section sq30a
+.section sq30b
+.section sq4aa
+.section sq4ab
+.section sq4ba
+.section sq4bb
+.section sq4ca
+.section sq4cb
+.section sq4da
+.section sq4db
+.section sq4ea
+.section sq4eb
+.section sq4fa
+.section sq4fb
+.section sq4ga
+.section sq4gb
+.section sq4ha
+.section sq4hb
+.section sq4ia
+.section sq4ib
+.section sq4ja
+.section sq4jb
+.section sq4ka
+.section sq4kb
+.section sq4la
+.section sq4lb
+.section sq4ma
+.section sq4mb
+.section sq4na
+.section sq4nb
+.section sq4oa
+.section sq4ob
+.section sq4pa
+.section sq4pb
+.section sq4qa
+.section sq4qb
+.section sq4ra
+.section sq4rb
+.section sq4sa
+.section sq4sb
+.section sq4ta
+.section sq4tb
+.section sq4ua
+.section sq4ub
+.section sq4va
+.section sq4vb
+.section sq4wa
+.section sq4wb
+.section sq4xa
+.section sq4xb
+.section sq4ya
+.section sq4yb
+.section sq4za
+.section sq4zb
+.section sq41a
+.section sq41b
+.section sq42a
+.section sq42b
+.section sq43a
+.section sq43b
+.section sq44a
+.section sq44b
+.section sq45a
+.section sq45b
+.section sq46a
+.section sq46b
+.section sq47a
+.section sq47b
+.section sq48a
+.section sq48b
+.section sq49a
+.section sq49b
+.section sq40a
+.section sq40b
+.section sq5aa
+.section sq5ab
+.section sq5ba
+.section sq5bb
+.section sq5ca
+.section sq5cb
+.section sq5da
+.section sq5db
+.section sq5ea
+.section sq5eb
+.section sq5fa
+.section sq5fb
+.section sq5ga
+.section sq5gb
+.section sq5ha
+.section sq5hb
+.section sq5ia
+.section sq5ib
+.section sq5ja
+.section sq5jb
+.section sq5ka
+.section sq5kb
+.section sq5la
+.section sq5lb
+.section sq5ma
+.section sq5mb
+.section sq5na
+.section sq5nb
+.section sq5oa
+.section sq5ob
+.section sq5pa
+.section sq5pb
+.section sq5qa
+.section sq5qb
+.section sq5ra
+.section sq5rb
+.section sq5sa
+.section sq5sb
+.section sq5ta
+.section sq5tb
+.section sq5ua
+.section sq5ub
+.section sq5va
+.section sq5vb
+.section sq5wa
+.section sq5wb
+.section sq5xa
+.section sq5xb
+.section sq5ya
+.section sq5yb
+.section sq5za
+.section sq5zb
+.section sq51a
+.section sq51b
+.section sq52a
+.section sq52b
+.section sq53a
+.section sq53b
+.section sq54a
+.section sq54b
+.section sq55a
+.section sq55b
+.section sq56a
+.section sq56b
+.section sq57a
+.section sq57b
+.section sq58a
+.section sq58b
+.section sq59a
+.section sq59b
+.section sq50a
+.section sq50b
+.section sq6aa
+.section sq6ab
+.section sq6ba
+.section sq6bb
+.section sq6ca
+.section sq6cb
+.section sq6da
+.section sq6db
+.section sq6ea
+.section sq6eb
+.section sq6fa
+.section sq6fb
+.section sq6ga
+.section sq6gb
+.section sq6ha
+.section sq6hb
+.section sq6ia
+.section sq6ib
+.section sq6ja
+.section sq6jb
+.section sq6ka
+.section sq6kb
+.section sq6la
+.section sq6lb
+.section sq6ma
+.section sq6mb
+.section sq6na
+.section sq6nb
+.section sq6oa
+.section sq6ob
+.section sq6pa
+.section sq6pb
+.section sq6qa
+.section sq6qb
+.section sq6ra
+.section sq6rb
+.section sq6sa
+.section sq6sb
+.section sq6ta
+.section sq6tb
+.section sq6ua
+.section sq6ub
+.section sq6va
+.section sq6vb
+.section sq6wa
+.section sq6wb
+.section sq6xa
+.section sq6xb
+.section sq6ya
+.section sq6yb
+.section sq6za
+.section sq6zb
+.section sq61a
+.section sq61b
+.section sq62a
+.section sq62b
+.section sq63a
+.section sq63b
+.section sq64a
+.section sq64b
+.section sq65a
+.section sq65b
+.section sq66a
+.section sq66b
+.section sq67a
+.section sq67b
+.section sq68a
+.section sq68b
+.section sq69a
+.section sq69b
+.section sq60a
+.section sq60b
+.section sq7aa
+.section sq7ab
+.section sq7ba
+.section sq7bb
+.section sq7ca
+.section sq7cb
+.section sq7da
+.section sq7db
+.section sq7ea
+.section sq7eb
+.section sq7fa
+.section sq7fb
+.section sq7ga
+.section sq7gb
+.section sq7ha
+.section sq7hb
+.section sq7ia
+.section sq7ib
+.section sq7ja
+.section sq7jb
+.section sq7ka
+.section sq7kb
+.section sq7la
+.section sq7lb
+.section sq7ma
+.section sq7mb
+.section sq7na
+.section sq7nb
+.section sq7oa
+.section sq7ob
+.section sq7pa
+.section sq7pb
+.section sq7qa
+.section sq7qb
+.section sq7ra
+.section sq7rb
+.section sq7sa
+.section sq7sb
+.section sq7ta
+.section sq7tb
+.section sq7ua
+.section sq7ub
+.section sq7va
+.section sq7vb
+.section sq7wa
+.section sq7wb
+.section sq7xa
+.section sq7xb
+.section sq7ya
+.section sq7yb
+.section sq7za
+.section sq7zb
+.section sq71a
+.section sq71b
+.section sq72a
+.section sq72b
+.section sq73a
+.section sq73b
+.section sq74a
+.section sq74b
+.section sq75a
+.section sq75b
+.section sq76a
+.section sq76b
+.section sq77a
+.section sq77b
+.section sq78a
+.section sq78b
+.section sq79a
+.section sq79b
+.section sq70a
+.section sq70b
+.section sq8aa
+.section sq8ab
+.section sq8ba
+.section sq8bb
+.section sq8ca
+.section sq8cb
+.section sq8da
+.section sq8db
+.section sq8ea
+.section sq8eb
+.section sq8fa
+.section sq8fb
+.section sq8ga
+.section sq8gb
+.section sq8ha
+.section sq8hb
+.section sq8ia
+.section sq8ib
+.section sq8ja
+.section sq8jb
+.section sq8ka
+.section sq8kb
+.section sq8la
+.section sq8lb
+.section sq8ma
+.section sq8mb
+.section sq8na
+.section sq8nb
+.section sq8oa
+.section sq8ob
+.section sq8pa
+.section sq8pb
+.section sq8qa
+.section sq8qb
+.section sq8ra
+.section sq8rb
+.section sq8sa
+.section sq8sb
+.section sq8ta
+.section sq8tb
+.section sq8ua
+.section sq8ub
+.section sq8va
+.section sq8vb
+.section sq8wa
+.section sq8wb
+.section sq8xa
+.section sq8xb
+.section sq8ya
+.section sq8yb
+.section sq8za
+.section sq8zb
+.section sq81a
+.section sq81b
+.section sq82a
+.section sq82b
+.section sq83a
+.section sq83b
+.section sq84a
+.section sq84b
+.section sq85a
+.section sq85b
+.section sq86a
+.section sq86b
+.section sq87a
+.section sq87b
+.section sq88a
+.section sq88b
+.section sq89a
+.section sq89b
+.section sq80a
+.section sq80b
+.section sq9aa
+.section sq9ab
+.section sq9ba
+.section sq9bb
+.section sq9ca
+.section sq9cb
+.section sq9da
+.section sq9db
+.section sq9ea
+.section sq9eb
+.section sq9fa
+.section sq9fb
+.section sq9ga
+.section sq9gb
+.section sq9ha
+.section sq9hb
+.section sq9ia
+.section sq9ib
+.section sq9ja
+.section sq9jb
+.section sq9ka
+.section sq9kb
+.section sq9la
+.section sq9lb
+.section sq9ma
+.section sq9mb
+.section sq9na
+.section sq9nb
+.section sq9oa
+.section sq9ob
+.section sq9pa
+.section sq9pb
+.section sq9qa
+.section sq9qb
+.section sq9ra
+.section sq9rb
+.section sq9sa
+.section sq9sb
+.section sq9ta
+.section sq9tb
+.section sq9ua
+.section sq9ub
+.section sq9va
+.section sq9vb
+.section sq9wa
+.section sq9wb
+.section sq9xa
+.section sq9xb
+.section sq9ya
+.section sq9yb
+.section sq9za
+.section sq9zb
+.section sq91a
+.section sq91b
+.section sq92a
+.section sq92b
+.section sq93a
+.section sq93b
+.section sq94a
+.section sq94b
+.section sq95a
+.section sq95b
+.section sq96a
+.section sq96b
+.section sq97a
+.section sq97b
+.section sq98a
+.section sq98b
+.section sq99a
+.section sq99b
+.section sq90a
+.section sq90b
+.section sq0aa
+.section sq0ab
+.section sq0ba
+.section sq0bb
+.section sq0ca
+.section sq0cb
+.section sq0da
+.section sq0db
+.section sq0ea
+.section sq0eb
+.section sq0fa
+.section sq0fb
+.section sq0ga
+.section sq0gb
+.section sq0ha
+.section sq0hb
+.section sq0ia
+.section sq0ib
+.section sq0ja
+.section sq0jb
+.section sq0ka
+.section sq0kb
+.section sq0la
+.section sq0lb
+.section sq0ma
+.section sq0mb
+.section sq0na
+.section sq0nb
+.section sq0oa
+.section sq0ob
+.section sq0pa
+.section sq0pb
+.section sq0qa
+.section sq0qb
+.section sq0ra
+.section sq0rb
+.section sq0sa
+.section sq0sb
+.section sq0ta
+.section sq0tb
+.section sq0ua
+.section sq0ub
+.section sq0va
+.section sq0vb
+.section sq0wa
+.section sq0wb
+.section sq0xa
+.section sq0xb
+.section sq0ya
+.section sq0yb
+.section sq0za
+.section sq0zb
+.section sq01a
+.section sq01b
+.section sq02a
+.section sq02b
+.section sq03a
+.section sq03b
+.section sq04a
+.section sq04b
+.section sq05a
+.section sq05b
+.section sq06a
+.section sq06b
+.section sq07a
+.section sq07b
+.section sq08a
+.section sq08b
+.section sq09a
+.section sq09b
+.section sq00a
+.section sq00b
+.section sraaa
+.section sraab
+.section sraba
+.section srabb
+.section sraca
+.section sracb
+.section srada
+.section sradb
+.section sraea
+.section sraeb
+.section srafa
+.section srafb
+.section sraga
+.section sragb
+.section sraha
+.section srahb
+.section sraia
+.section sraib
+.section sraja
+.section srajb
+.section sraka
+.section srakb
+.section srala
+.section sralb
+.section srama
+.section sramb
+.section srana
+.section sranb
+.section sraoa
+.section sraob
+.section srapa
+.section srapb
+.section sraqa
+.section sraqb
+.section srara
+.section srarb
+.section srasa
+.section srasb
+.section srata
+.section sratb
+.section sraua
+.section sraub
+.section srava
+.section sravb
+.section srawa
+.section srawb
+.section sraxa
+.section sraxb
+.section sraya
+.section srayb
+.section sraza
+.section srazb
+.section sra1a
+.section sra1b
+.section sra2a
+.section sra2b
+.section sra3a
+.section sra3b
+.section sra4a
+.section sra4b
+.section sra5a
+.section sra5b
+.section sra6a
+.section sra6b
+.section sra7a
+.section sra7b
+.section sra8a
+.section sra8b
+.section sra9a
+.section sra9b
+.section sra0a
+.section sra0b
+.section srbaa
+.section srbab
+.section srbba
+.section srbbb
+.section srbca
+.section srbcb
+.section srbda
+.section srbdb
+.section srbea
+.section srbeb
+.section srbfa
+.section srbfb
+.section srbga
+.section srbgb
+.section srbha
+.section srbhb
+.section srbia
+.section srbib
+.section srbja
+.section srbjb
+.section srbka
+.section srbkb
+.section srbla
+.section srblb
+.section srbma
+.section srbmb
+.section srbna
+.section srbnb
+.section srboa
+.section srbob
+.section srbpa
+.section srbpb
+.section srbqa
+.section srbqb
+.section srbra
+.section srbrb
+.section srbsa
+.section srbsb
+.section srbta
+.section srbtb
+.section srbua
+.section srbub
+.section srbva
+.section srbvb
+.section srbwa
+.section srbwb
+.section srbxa
+.section srbxb
+.section srbya
+.section srbyb
+.section srbza
+.section srbzb
+.section srb1a
+.section srb1b
+.section srb2a
+.section srb2b
+.section srb3a
+.section srb3b
+.section srb4a
+.section srb4b
+.section srb5a
+.section srb5b
+.section srb6a
+.section srb6b
+.section srb7a
+.section srb7b
+.section srb8a
+.section srb8b
+.section srb9a
+.section srb9b
+.section srb0a
+.section srb0b
+.section srcaa
+.section srcab
+.section srcba
+.section srcbb
+.section srcca
+.section srccb
+.section srcda
+.section srcdb
+.section srcea
+.section srceb
+.section srcfa
+.section srcfb
+.section srcga
+.section srcgb
+.section srcha
+.section srchb
+.section srcia
+.section srcib
+.section srcja
+.section srcjb
+.section srcka
+.section srckb
+.section srcla
+.section srclb
+.section srcma
+.section srcmb
+.section srcna
+.section srcnb
+.section srcoa
+.section srcob
+.section srcpa
+.section srcpb
+.section srcqa
+.section srcqb
+.section srcra
+.section srcrb
+.section srcsa
+.section srcsb
+.section srcta
+.section srctb
+.section srcua
+.section srcub
+.section srcva
+.section srcvb
+.section srcwa
+.section srcwb
+.section srcxa
+.section srcxb
+.section srcya
+.section srcyb
+.section srcza
+.section srczb
+.section src1a
+.section src1b
+.section src2a
+.section src2b
+.section src3a
+.section src3b
+.section src4a
+.section src4b
+.section src5a
+.section src5b
+.section src6a
+.section src6b
+.section src7a
+.section src7b
+.section src8a
+.section src8b
+.section src9a
+.section src9b
+.section src0a
+.section src0b
+.section srdaa
+.section srdab
+.section srdba
+.section srdbb
+.section srdca
+.section srdcb
+.section srdda
+.section srddb
+.section srdea
+.section srdeb
+.section srdfa
+.section srdfb
+.section srdga
+.section srdgb
+.section srdha
+.section srdhb
+.section srdia
+.section srdib
+.section srdja
+.section srdjb
+.section srdka
+.section srdkb
+.section srdla
+.section srdlb
+.section srdma
+.section srdmb
+.section srdna
+.section srdnb
+.section srdoa
+.section srdob
+.section srdpa
+.section srdpb
+.section srdqa
+.section srdqb
+.section srdra
+.section srdrb
+.section srdsa
+.section srdsb
+.section srdta
+.section srdtb
+.section srdua
+.section srdub
+.section srdva
+.section srdvb
+.section srdwa
+.section srdwb
+.section srdxa
+.section srdxb
+.section srdya
+.section srdyb
+.section srdza
+.section srdzb
+.section srd1a
+.section srd1b
+.section srd2a
+.section srd2b
+.section srd3a
+.section srd3b
+.section srd4a
+.section srd4b
+.section srd5a
+.section srd5b
+.section srd6a
+.section srd6b
+.section srd7a
+.section srd7b
+.section srd8a
+.section srd8b
+.section srd9a
+.section srd9b
+.section srd0a
+.section srd0b
+.section sreaa
+.section sreab
+.section sreba
+.section srebb
+.section sreca
+.section srecb
+.section sreda
+.section sredb
+.section sreea
+.section sreeb
+.section srefa
+.section srefb
+.section srega
+.section sregb
+.section sreha
+.section srehb
+.section sreia
+.section sreib
+.section sreja
+.section srejb
+.section sreka
+.section srekb
+.section srela
+.section srelb
+.section srema
+.section sremb
+.section srena
+.section srenb
+.section sreoa
+.section sreob
+.section srepa
+.section srepb
+.section sreqa
+.section sreqb
+.section srera
+.section srerb
+.section sresa
+.section sresb
+.section sreta
+.section sretb
+.section sreua
+.section sreub
+.section sreva
+.section srevb
+.section srewa
+.section srewb
+.section srexa
+.section srexb
+.section sreya
+.section sreyb
+.section sreza
+.section srezb
+.section sre1a
+.section sre1b
+.section sre2a
+.section sre2b
+.section sre3a
+.section sre3b
+.section sre4a
+.section sre4b
+.section sre5a
+.section sre5b
+.section sre6a
+.section sre6b
+.section sre7a
+.section sre7b
+.section sre8a
+.section sre8b
+.section sre9a
+.section sre9b
+.section sre0a
+.section sre0b
+.section srfaa
+.section srfab
+.section srfba
+.section srfbb
+.section srfca
+.section srfcb
+.section srfda
+.section srfdb
+.section srfea
+.section srfeb
+.section srffa
+.section srffb
+.section srfga
+.section srfgb
+.section srfha
+.section srfhb
+.section srfia
+.section srfib
+.section srfja
+.section srfjb
+.section srfka
+.section srfkb
+.section srfla
+.section srflb
+.section srfma
+.section srfmb
+.section srfna
+.section srfnb
+.section srfoa
+.section srfob
+.section srfpa
+.section srfpb
+.section srfqa
+.section srfqb
+.section srfra
+.section srfrb
+.section srfsa
+.section srfsb
+.section srfta
+.section srftb
+.section srfua
+.section srfub
+.section srfva
+.section srfvb
+.section srfwa
+.section srfwb
+.section srfxa
+.section srfxb
+.section srfya
+.section srfyb
+.section srfza
+.section srfzb
+.section srf1a
+.section srf1b
+.section srf2a
+.section srf2b
+.section srf3a
+.section srf3b
+.section srf4a
+.section srf4b
+.section srf5a
+.section srf5b
+.section srf6a
+.section srf6b
+.section srf7a
+.section srf7b
+.section srf8a
+.section srf8b
+.section srf9a
+.section srf9b
+.section srf0a
+.section srf0b
+.section srgaa
+.section srgab
+.section srgba
+.section srgbb
+.section srgca
+.section srgcb
+.section srgda
+.section srgdb
+.section srgea
+.section srgeb
+.section srgfa
+.section srgfb
+.section srgga
+.section srggb
+.section srgha
+.section srghb
+.section srgia
+.section srgib
+.section srgja
+.section srgjb
+.section srgka
+.section srgkb
+.section srgla
+.section srglb
+.section srgma
+.section srgmb
+.section srgna
+.section srgnb
+.section srgoa
+.section srgob
+.section srgpa
+.section srgpb
+.section srgqa
+.section srgqb
+.section srgra
+.section srgrb
+.section srgsa
+.section srgsb
+.section srgta
+.section srgtb
+.section srgua
+.section srgub
+.section srgva
+.section srgvb
+.section srgwa
+.section srgwb
+.section srgxa
+.section srgxb
+.section srgya
+.section srgyb
+.section srgza
+.section srgzb
+.section srg1a
+.section srg1b
+.section srg2a
+.section srg2b
+.section srg3a
+.section srg3b
+.section srg4a
+.section srg4b
+.section srg5a
+.section srg5b
+.section srg6a
+.section srg6b
+.section srg7a
+.section srg7b
+.section srg8a
+.section srg8b
+.section srg9a
+.section srg9b
+.section srg0a
+.section srg0b
+.section srhaa
+.section srhab
+.section srhba
+.section srhbb
+.section srhca
+.section srhcb
+.section srhda
+.section srhdb
+.section srhea
+.section srheb
+.section srhfa
+.section srhfb
+.section srhga
+.section srhgb
+.section srhha
+.section srhhb
+.section srhia
+.section srhib
+.section srhja
+.section srhjb
+.section srhka
+.section srhkb
+.section srhla
+.section srhlb
+.section srhma
+.section srhmb
+.section srhna
+.section srhnb
+.section srhoa
+.section srhob
+.section srhpa
+.section srhpb
+.section srhqa
+.section srhqb
+.section srhra
+.section srhrb
+.section srhsa
+.section srhsb
+.section srhta
+.section srhtb
+.section srhua
+.section srhub
+.section srhva
+.section srhvb
+.section srhwa
+.section srhwb
+.section srhxa
+.section srhxb
+.section srhya
+.section srhyb
+.section srhza
+.section srhzb
+.section srh1a
+.section srh1b
+.section srh2a
+.section srh2b
+.section srh3a
+.section srh3b
+.section srh4a
+.section srh4b
+.section srh5a
+.section srh5b
+.section srh6a
+.section srh6b
+.section srh7a
+.section srh7b
+.section srh8a
+.section srh8b
+.section srh9a
+.section srh9b
+.section srh0a
+.section srh0b
+.section sriaa
+.section sriab
+.section sriba
+.section sribb
+.section srica
+.section sricb
+.section srida
+.section sridb
+.section sriea
+.section srieb
+.section srifa
+.section srifb
+.section sriga
+.section srigb
+.section sriha
+.section srihb
+.section sriia
+.section sriib
+.section srija
+.section srijb
+.section srika
+.section srikb
+.section srila
+.section srilb
+.section srima
+.section srimb
+.section srina
+.section srinb
+.section srioa
+.section sriob
+.section sripa
+.section sripb
+.section sriqa
+.section sriqb
+.section srira
+.section srirb
+.section srisa
+.section srisb
+.section srita
+.section sritb
+.section sriua
+.section sriub
+.section sriva
+.section srivb
+.section sriwa
+.section sriwb
+.section srixa
+.section srixb
+.section sriya
+.section sriyb
+.section sriza
+.section srizb
+.section sri1a
+.section sri1b
+.section sri2a
+.section sri2b
+.section sri3a
+.section sri3b
+.section sri4a
+.section sri4b
+.section sri5a
+.section sri5b
+.section sri6a
+.section sri6b
+.section sri7a
+.section sri7b
+.section sri8a
+.section sri8b
+.section sri9a
+.section sri9b
+.section sri0a
+.section sri0b
+.section srjaa
+.section srjab
+.section srjba
+.section srjbb
+.section srjca
+.section srjcb
+.section srjda
+.section srjdb
+.section srjea
+.section srjeb
+.section srjfa
+.section srjfb
+.section srjga
+.section srjgb
+.section srjha
+.section srjhb
+.section srjia
+.section srjib
+.section srjja
+.section srjjb
+.section srjka
+.section srjkb
+.section srjla
+.section srjlb
+.section srjma
+.section srjmb
+.section srjna
+.section srjnb
+.section srjoa
+.section srjob
+.section srjpa
+.section srjpb
+.section srjqa
+.section srjqb
+.section srjra
+.section srjrb
+.section srjsa
+.section srjsb
+.section srjta
+.section srjtb
+.section srjua
+.section srjub
+.section srjva
+.section srjvb
+.section srjwa
+.section srjwb
+.section srjxa
+.section srjxb
+.section srjya
+.section srjyb
+.section srjza
+.section srjzb
+.section srj1a
+.section srj1b
+.section srj2a
+.section srj2b
+.section srj3a
+.section srj3b
+.section srj4a
+.section srj4b
+.section srj5a
+.section srj5b
+.section srj6a
+.section srj6b
+.section srj7a
+.section srj7b
+.section srj8a
+.section srj8b
+.section srj9a
+.section srj9b
+.section srj0a
+.section srj0b
+.section srkaa
+.section srkab
+.section srkba
+.section srkbb
+.section srkca
+.section srkcb
+.section srkda
+.section srkdb
+.section srkea
+.section srkeb
+.section srkfa
+.section srkfb
+.section srkga
+.section srkgb
+.section srkha
+.section srkhb
+.section srkia
+.section srkib
+.section srkja
+.section srkjb
+.section srkka
+.section srkkb
+.section srkla
+.section srklb
+.section srkma
+.section srkmb
+.section srkna
+.section srknb
+.section srkoa
+.section srkob
+.section srkpa
+.section srkpb
+.section srkqa
+.section srkqb
+.section srkra
+.section srkrb
+.section srksa
+.section srksb
+.section srkta
+.section srktb
+.section srkua
+.section srkub
+.section srkva
+.section srkvb
+.section srkwa
+.section srkwb
+.section srkxa
+.section srkxb
+.section srkya
+.section srkyb
+.section srkza
+.section srkzb
+.section srk1a
+.section srk1b
+.section srk2a
+.section srk2b
+.section srk3a
+.section srk3b
+.section srk4a
+.section srk4b
+.section srk5a
+.section srk5b
+.section srk6a
+.section srk6b
+.section srk7a
+.section srk7b
+.section srk8a
+.section srk8b
+.section srk9a
+.section srk9b
+.section srk0a
+.section srk0b
+.section srlaa
+.section srlab
+.section srlba
+.section srlbb
+.section srlca
+.section srlcb
+.section srlda
+.section srldb
+.section srlea
+.section srleb
+.section srlfa
+.section srlfb
+.section srlga
+.section srlgb
+.section srlha
+.section srlhb
+.section srlia
+.section srlib
+.section srlja
+.section srljb
+.section srlka
+.section srlkb
+.section srlla
+.section srllb
+.section srlma
+.section srlmb
+.section srlna
+.section srlnb
+.section srloa
+.section srlob
+.section srlpa
+.section srlpb
+.section srlqa
+.section srlqb
+.section srlra
+.section srlrb
+.section srlsa
+.section srlsb
+.section srlta
+.section srltb
+.section srlua
+.section srlub
+.section srlva
+.section srlvb
+.section srlwa
+.section srlwb
+.section srlxa
+.section srlxb
+.section srlya
+.section srlyb
+.section srlza
+.section srlzb
+.section srl1a
+.section srl1b
+.section srl2a
+.section srl2b
+.section srl3a
+.section srl3b
+.section srl4a
+.section srl4b
+.section srl5a
+.section srl5b
+.section srl6a
+.section srl6b
+.section srl7a
+.section srl7b
+.section srl8a
+.section srl8b
+.section srl9a
+.section srl9b
+.section srl0a
+.section srl0b
+.section srmaa
+.section srmab
+.section srmba
+.section srmbb
+.section srmca
+.section srmcb
+.section srmda
+.section srmdb
+.section srmea
+.section srmeb
+.section srmfa
+.section srmfb
+.section srmga
+.section srmgb
+.section srmha
+.section srmhb
+.section srmia
+.section srmib
+.section srmja
+.section srmjb
+.section srmka
+.section srmkb
+.section srmla
+.section srmlb
+.section srmma
+.section srmmb
+.section srmna
+.section srmnb
+.section srmoa
+.section srmob
+.section srmpa
+.section srmpb
+.section srmqa
+.section srmqb
+.section srmra
+.section srmrb
+.section srmsa
+.section srmsb
+.section srmta
+.section srmtb
+.section srmua
+.section srmub
+.section srmva
+.section srmvb
+.section srmwa
+.section srmwb
+.section srmxa
+.section srmxb
+.section srmya
+.section srmyb
+.section srmza
+.section srmzb
+.section srm1a
+.section srm1b
+.section srm2a
+.section srm2b
+.section srm3a
+.section srm3b
+.section srm4a
+.section srm4b
+.section srm5a
+.section srm5b
+.section srm6a
+.section srm6b
+.section srm7a
+.section srm7b
+.section srm8a
+.section srm8b
+.section srm9a
+.section srm9b
+.section srm0a
+.section srm0b
+.section srnaa
+.section srnab
+.section srnba
+.section srnbb
+.section srnca
+.section srncb
+.section srnda
+.section srndb
+.section srnea
+.section srneb
+.section srnfa
+.section srnfb
+.section srnga
+.section srngb
+.section srnha
+.section srnhb
+.section srnia
+.section srnib
+.section srnja
+.section srnjb
+.section srnka
+.section srnkb
+.section srnla
+.section srnlb
+.section srnma
+.section srnmb
+.section srnna
+.section srnnb
+.section srnoa
+.section srnob
+.section srnpa
+.section srnpb
+.section srnqa
+.section srnqb
+.section srnra
+.section srnrb
+.section srnsa
+.section srnsb
+.section srnta
+.section srntb
+.section srnua
+.section srnub
+.section srnva
+.section srnvb
+.section srnwa
+.section srnwb
+.section srnxa
+.section srnxb
+.section srnya
+.section srnyb
+.section srnza
+.section srnzb
+.section srn1a
+.section srn1b
+.section srn2a
+.section srn2b
+.section srn3a
+.section srn3b
+.section srn4a
+.section srn4b
+.section srn5a
+.section srn5b
+.section srn6a
+.section srn6b
+.section srn7a
+.section srn7b
+.section srn8a
+.section srn8b
+.section srn9a
+.section srn9b
+.section srn0a
+.section srn0b
+.section sroaa
+.section sroab
+.section sroba
+.section srobb
+.section sroca
+.section srocb
+.section sroda
+.section srodb
+.section sroea
+.section sroeb
+.section srofa
+.section srofb
+.section sroga
+.section srogb
+.section sroha
+.section srohb
+.section sroia
+.section sroib
+.section sroja
+.section srojb
+.section sroka
+.section srokb
+.section srola
+.section srolb
+.section sroma
+.section sromb
+.section srona
+.section sronb
+.section srooa
+.section sroob
+.section sropa
+.section sropb
+.section sroqa
+.section sroqb
+.section srora
+.section srorb
+.section srosa
+.section srosb
+.section srota
+.section srotb
+.section sroua
+.section sroub
+.section srova
+.section srovb
+.section srowa
+.section srowb
+.section sroxa
+.section sroxb
+.section sroya
+.section sroyb
+.section sroza
+.section srozb
+.section sro1a
+.section sro1b
+.section sro2a
+.section sro2b
+.section sro3a
+.section sro3b
+.section sro4a
+.section sro4b
+.section sro5a
+.section sro5b
+.section sro6a
+.section sro6b
+.section sro7a
+.section sro7b
+.section sro8a
+.section sro8b
+.section sro9a
+.section sro9b
+.section sro0a
+.section sro0b
+.section srpaa
+.section srpab
+.section srpba
+.section srpbb
+.section srpca
+.section srpcb
+.section srpda
+.section srpdb
+.section srpea
+.section srpeb
+.section srpfa
+.section srpfb
+.section srpga
+.section srpgb
+.section srpha
+.section srphb
+.section srpia
+.section srpib
+.section srpja
+.section srpjb
+.section srpka
+.section srpkb
+.section srpla
+.section srplb
+.section srpma
+.section srpmb
+.section srpna
+.section srpnb
+.section srpoa
+.section srpob
+.section srppa
+.section srppb
+.section srpqa
+.section srpqb
+.section srpra
+.section srprb
+.section srpsa
+.section srpsb
+.section srpta
+.section srptb
+.section srpua
+.section srpub
+.section srpva
+.section srpvb
+.section srpwa
+.section srpwb
+.section srpxa
+.section srpxb
+.section srpya
+.section srpyb
+.section srpza
+.section srpzb
+.section srp1a
+.section srp1b
+.section srp2a
+.section srp2b
+.section srp3a
+.section srp3b
+.section srp4a
+.section srp4b
+.section srp5a
+.section srp5b
+.section srp6a
+.section srp6b
+.section srp7a
+.section srp7b
+.section srp8a
+.section srp8b
+.section srp9a
+.section srp9b
+.section srp0a
+.section srp0b
+.section srqaa
+.section srqab
+.section srqba
+.section srqbb
+.section srqca
+.section srqcb
+.section srqda
+.section srqdb
+.section srqea
+.section srqeb
+.section srqfa
+.section srqfb
+.section srqga
+.section srqgb
+.section srqha
+.section srqhb
+.section srqia
+.section srqib
+.section srqja
+.section srqjb
+.section srqka
+.section srqkb
+.section srqla
+.section srqlb
+.section srqma
+.section srqmb
+.section srqna
+.section srqnb
+.section srqoa
+.section srqob
+.section srqpa
+.section srqpb
+.section srqqa
+.section srqqb
+.section srqra
+.section srqrb
+.section srqsa
+.section srqsb
+.section srqta
+.section srqtb
+.section srqua
+.section srqub
+.section srqva
+.section srqvb
+.section srqwa
+.section srqwb
+.section srqxa
+.section srqxb
+.section srqya
+.section srqyb
+.section srqza
+.section srqzb
+.section srq1a
+.section srq1b
+.section srq2a
+.section srq2b
+.section srq3a
+.section srq3b
+.section srq4a
+.section srq4b
+.section srq5a
+.section srq5b
+.section srq6a
+.section srq6b
+.section srq7a
+.section srq7b
+.section srq8a
+.section srq8b
+.section srq9a
+.section srq9b
+.section srq0a
+.section srq0b
+.section srraa
+.section srrab
+.section srrba
+.section srrbb
+.section srrca
+.section srrcb
+.section srrda
+.section srrdb
+.section srrea
+.section srreb
+.section srrfa
+.section srrfb
+.section srrga
+.section srrgb
+.section srrha
+.section srrhb
+.section srria
+.section srrib
+.section srrja
+.section srrjb
+.section srrka
+.section srrkb
+.section srrla
+.section srrlb
+.section srrma
+.section srrmb
+.section srrna
+.section srrnb
+.section srroa
+.section srrob
+.section srrpa
+.section srrpb
+.section srrqa
+.section srrqb
+.section srrra
+.section srrrb
+.section srrsa
+.section srrsb
+.section srrta
+.section srrtb
+.section srrua
+.section srrub
+.section srrva
+.section srrvb
+.section srrwa
+.section srrwb
+.section srrxa
+.section srrxb
+.section srrya
+.section srryb
+.section srrza
+.section srrzb
+.section srr1a
+.section srr1b
+.section srr2a
+.section srr2b
+.section srr3a
+.section srr3b
+.section srr4a
+.section srr4b
+.section srr5a
+.section srr5b
+.section srr6a
+.section srr6b
+.section srr7a
+.section srr7b
+.section srr8a
+.section srr8b
+.section srr9a
+.section srr9b
+.section srr0a
+.section srr0b
+.section srsaa
+.section srsab
+.section srsba
+.section srsbb
+.section srsca
+.section srscb
+.section srsda
+.section srsdb
+.section srsea
+.section srseb
+.section srsfa
+.section srsfb
+.section srsga
+.section srsgb
+.section srsha
+.section srshb
+.section srsia
+.section srsib
+.section srsja
+.section srsjb
+.section srska
+.section srskb
+.section srsla
+.section srslb
+.section srsma
+.section srsmb
+.section srsna
+.section srsnb
+.section srsoa
+.section srsob
+.section srspa
+.section srspb
+.section srsqa
+.section srsqb
+.section srsra
+.section srsrb
+.section srssa
+.section srssb
+.section srsta
+.section srstb
+.section srsua
+.section srsub
+.section srsva
+.section srsvb
+.section srswa
+.section srswb
+.section srsxa
+.section srsxb
+.section srsya
+.section srsyb
+.section srsza
+.section srszb
+.section srs1a
+.section srs1b
+.section srs2a
+.section srs2b
+.section srs3a
+.section srs3b
+.section srs4a
+.section srs4b
+.section srs5a
+.section srs5b
+.section srs6a
+.section srs6b
+.section srs7a
+.section srs7b
+.section srs8a
+.section srs8b
+.section srs9a
+.section srs9b
+.section srs0a
+.section srs0b
+.section srtaa
+.section srtab
+.section srtba
+.section srtbb
+.section srtca
+.section srtcb
+.section srtda
+.section srtdb
+.section srtea
+.section srteb
+.section srtfa
+.section srtfb
+.section srtga
+.section srtgb
+.section srtha
+.section srthb
+.section srtia
+.section srtib
+.section srtja
+.section srtjb
+.section srtka
+.section srtkb
+.section srtla
+.section srtlb
+.section srtma
+.section srtmb
+.section srtna
+.section srtnb
+.section srtoa
+.section srtob
+.section srtpa
+.section srtpb
+.section srtqa
+.section srtqb
+.section srtra
+.section srtrb
+.section srtsa
+.section srtsb
+.section srtta
+.section srttb
+.section srtua
+.section srtub
+.section srtva
+.section srtvb
+.section srtwa
+.section srtwb
+.section srtxa
+.section srtxb
+.section srtya
+.section srtyb
+.section srtza
+.section srtzb
+.section srt1a
+.section srt1b
+.section srt2a
+.section srt2b
+.section srt3a
+.section srt3b
+.section srt4a
+.section srt4b
+.section srt5a
+.section srt5b
+.section srt6a
+.section srt6b
+.section srt7a
+.section srt7b
+.section srt8a
+.section srt8b
+.section srt9a
+.section srt9b
+.section srt0a
+.section srt0b
+.section sruaa
+.section sruab
+.section sruba
+.section srubb
+.section sruca
+.section srucb
+.section sruda
+.section srudb
+.section sruea
+.section srueb
+.section srufa
+.section srufb
+.section sruga
+.section srugb
+.section sruha
+.section sruhb
+.section sruia
+.section sruib
+.section sruja
+.section srujb
+.section sruka
+.section srukb
+.section srula
+.section srulb
+.section sruma
+.section srumb
+.section sruna
+.section srunb
+.section sruoa
+.section sruob
+.section srupa
+.section srupb
+.section sruqa
+.section sruqb
+.section srura
+.section srurb
+.section srusa
+.section srusb
+.section sruta
+.section srutb
+.section sruua
+.section sruub
+.section sruva
+.section sruvb
+.section sruwa
+.section sruwb
+.section sruxa
+.section sruxb
+.section sruya
+.section sruyb
+.section sruza
+.section sruzb
+.section sru1a
+.section sru1b
+.section sru2a
+.section sru2b
+.section sru3a
+.section sru3b
+.section sru4a
+.section sru4b
+.section sru5a
+.section sru5b
+.section sru6a
+.section sru6b
+.section sru7a
+.section sru7b
+.section sru8a
+.section sru8b
+.section sru9a
+.section sru9b
+.section sru0a
+.section sru0b
+.section srvaa
+.section srvab
+.section srvba
+.section srvbb
+.section srvca
+.section srvcb
+.section srvda
+.section srvdb
+.section srvea
+.section srveb
+.section srvfa
+.section srvfb
+.section srvga
+.section srvgb
+.section srvha
+.section srvhb
+.section srvia
+.section srvib
+.section srvja
+.section srvjb
+.section srvka
+.section srvkb
+.section srvla
+.section srvlb
+.section srvma
+.section srvmb
+.section srvna
+.section srvnb
+.section srvoa
+.section srvob
+.section srvpa
+.section srvpb
+.section srvqa
+.section srvqb
+.section srvra
+.section srvrb
+.section srvsa
+.section srvsb
+.section srvta
+.section srvtb
+.section srvua
+.section srvub
+.section srvva
+.section srvvb
+.section srvwa
+.section srvwb
+.section srvxa
+.section srvxb
+.section srvya
+.section srvyb
+.section srvza
+.section srvzb
+.section srv1a
+.section srv1b
+.section srv2a
+.section srv2b
+.section srv3a
+.section srv3b
+.section srv4a
+.section srv4b
+.section srv5a
+.section srv5b
+.section srv6a
+.section srv6b
+.section srv7a
+.section srv7b
+.section srv8a
+.section srv8b
+.section srv9a
+.section srv9b
+.section srv0a
+.section srv0b
+.section srwaa
+.section srwab
+.section srwba
+.section srwbb
+.section srwca
+.section srwcb
+.section srwda
+.section srwdb
+.section srwea
+.section srweb
+.section srwfa
+.section srwfb
+.section srwga
+.section srwgb
+.section srwha
+.section srwhb
+.section srwia
+.section srwib
+.section srwja
+.section srwjb
+.section srwka
+.section srwkb
+.section srwla
+.section srwlb
+.section srwma
+.section srwmb
+.section srwna
+.section srwnb
+.section srwoa
+.section srwob
+.section srwpa
+.section srwpb
+.section srwqa
+.section srwqb
+.section srwra
+.section srwrb
+.section srwsa
+.section srwsb
+.section srwta
+.section srwtb
+.section srwua
+.section srwub
+.section srwva
+.section srwvb
+.section srwwa
+.section srwwb
+.section srwxa
+.section srwxb
+.section srwya
+.section srwyb
+.section srwza
+.section srwzb
+.section srw1a
+.section srw1b
+.section srw2a
+.section srw2b
+.section srw3a
+.section srw3b
+.section srw4a
+.section srw4b
+.section srw5a
+.section srw5b
+.section srw6a
+.section srw6b
+.section srw7a
+.section srw7b
+.section srw8a
+.section srw8b
+.section srw9a
+.section srw9b
+.section srw0a
+.section srw0b
+.section srxaa
+.section srxab
+.section srxba
+.section srxbb
+.section srxca
+.section srxcb
+.section srxda
+.section srxdb
+.section srxea
+.section srxeb
+.section srxfa
+.section srxfb
+.section srxga
+.section srxgb
+.section srxha
+.section srxhb
+.section srxia
+.section srxib
+.section srxja
+.section srxjb
+.section srxka
+.section srxkb
+.section srxla
+.section srxlb
+.section srxma
+.section srxmb
+.section srxna
+.section srxnb
+.section srxoa
+.section srxob
+.section srxpa
+.section srxpb
+.section srxqa
+.section srxqb
+.section srxra
+.section srxrb
+.section srxsa
+.section srxsb
+.section srxta
+.section srxtb
+.section srxua
+.section srxub
+.section srxva
+.section srxvb
+.section srxwa
+.section srxwb
+.section srxxa
+.section srxxb
+.section srxya
+.section srxyb
+.section srxza
+.section srxzb
+.section srx1a
+.section srx1b
+.section srx2a
+.section srx2b
+.section srx3a
+.section srx3b
+.section srx4a
+.section srx4b
+.section srx5a
+.section srx5b
+.section srx6a
+.section srx6b
+.section srx7a
+.section srx7b
+.section srx8a
+.section srx8b
+.section srx9a
+.section srx9b
+.section srx0a
+.section srx0b
+.section sryaa
+.section sryab
+.section sryba
+.section srybb
+.section sryca
+.section srycb
+.section sryda
+.section srydb
+.section sryea
+.section sryeb
+.section sryfa
+.section sryfb
+.section sryga
+.section srygb
+.section sryha
+.section sryhb
+.section sryia
+.section sryib
+.section sryja
+.section sryjb
+.section sryka
+.section srykb
+.section sryla
+.section srylb
+.section sryma
+.section srymb
+.section sryna
+.section srynb
+.section sryoa
+.section sryob
+.section srypa
+.section srypb
+.section sryqa
+.section sryqb
+.section sryra
+.section sryrb
+.section srysa
+.section srysb
+.section sryta
+.section srytb
+.section sryua
+.section sryub
+.section sryva
+.section sryvb
+.section srywa
+.section srywb
+.section sryxa
+.section sryxb
+.section sryya
+.section sryyb
+.section sryza
+.section sryzb
+.section sry1a
+.section sry1b
+.section sry2a
+.section sry2b
+.section sry3a
+.section sry3b
+.section sry4a
+.section sry4b
+.section sry5a
+.section sry5b
+.section sry6a
+.section sry6b
+.section sry7a
+.section sry7b
+.section sry8a
+.section sry8b
+.section sry9a
+.section sry9b
+.section sry0a
+.section sry0b
+.section srzaa
+.section srzab
+.section srzba
+.section srzbb
+.section srzca
+.section srzcb
+.section srzda
+.section srzdb
+.section srzea
+.section srzeb
+.section srzfa
+.section srzfb
+.section srzga
+.section srzgb
+.section srzha
+.section srzhb
+.section srzia
+.section srzib
+.section srzja
+.section srzjb
+.section srzka
+.section srzkb
+.section srzla
+.section srzlb
+.section srzma
+.section srzmb
+.section srzna
+.section srznb
+.section srzoa
+.section srzob
+.section srzpa
+.section srzpb
+.section srzqa
+.section srzqb
+.section srzra
+.section srzrb
+.section srzsa
+.section srzsb
+.section srzta
+.section srztb
+.section srzua
+.section srzub
+.section srzva
+.section srzvb
+.section srzwa
+.section srzwb
+.section srzxa
+.section srzxb
+.section srzya
+.section srzyb
+.section srzza
+.section srzzb
+.section srz1a
+.section srz1b
+.section srz2a
+.section srz2b
+.section srz3a
+.section srz3b
+.section srz4a
+.section srz4b
+.section srz5a
+.section srz5b
+.section srz6a
+.section srz6b
+.section srz7a
+.section srz7b
+.section srz8a
+.section srz8b
+.section srz9a
+.section srz9b
+.section srz0a
+.section srz0b
+.section sr1aa
+.section sr1ab
+.section sr1ba
+.section sr1bb
+.section sr1ca
+.section sr1cb
+.section sr1da
+.section sr1db
+.section sr1ea
+.section sr1eb
+.section sr1fa
+.section sr1fb
+.section sr1ga
+.section sr1gb
+.section sr1ha
+.section sr1hb
+.section sr1ia
+.section sr1ib
+.section sr1ja
+.section sr1jb
+.section sr1ka
+.section sr1kb
+.section sr1la
+.section sr1lb
+.section sr1ma
+.section sr1mb
+.section sr1na
+.section sr1nb
+.section sr1oa
+.section sr1ob
+.section sr1pa
+.section sr1pb
+.section sr1qa
+.section sr1qb
+.section sr1ra
+.section sr1rb
+.section sr1sa
+.section sr1sb
+.section sr1ta
+.section sr1tb
+.section sr1ua
+.section sr1ub
+.section sr1va
+.section sr1vb
+.section sr1wa
+.section sr1wb
+.section sr1xa
+.section sr1xb
+.section sr1ya
+.section sr1yb
+.section sr1za
+.section sr1zb
+.section sr11a
+.section sr11b
+.section sr12a
+.section sr12b
+.section sr13a
+.section sr13b
+.section sr14a
+.section sr14b
+.section sr15a
+.section sr15b
+.section sr16a
+.section sr16b
+.section sr17a
+.section sr17b
+.section sr18a
+.section sr18b
+.section sr19a
+.section sr19b
+.section sr10a
+.section sr10b
+.section sr2aa
+.section sr2ab
+.section sr2ba
+.section sr2bb
+.section sr2ca
+.section sr2cb
+.section sr2da
+.section sr2db
+.section sr2ea
+.section sr2eb
+.section sr2fa
+.section sr2fb
+.section sr2ga
+.section sr2gb
+.section sr2ha
+.section sr2hb
+.section sr2ia
+.section sr2ib
+.section sr2ja
+.section sr2jb
+.section sr2ka
+.section sr2kb
+.section sr2la
+.section sr2lb
+.section sr2ma
+.section sr2mb
+.section sr2na
+.section sr2nb
+.section sr2oa
+.section sr2ob
+.section sr2pa
+.section sr2pb
+.section sr2qa
+.section sr2qb
+.section sr2ra
+.section sr2rb
+.section sr2sa
+.section sr2sb
+.section sr2ta
+.section sr2tb
+.section sr2ua
+.section sr2ub
+.section sr2va
+.section sr2vb
+.section sr2wa
+.section sr2wb
+.section sr2xa
+.section sr2xb
+.section sr2ya
+.section sr2yb
+.section sr2za
+.section sr2zb
+.section sr21a
+.section sr21b
+.section sr22a
+.section sr22b
+.section sr23a
+.section sr23b
+.section sr24a
+.section sr24b
+.section sr25a
+.section sr25b
+.section sr26a
+.section sr26b
+.section sr27a
+.section sr27b
+.section sr28a
+.section sr28b
+.section sr29a
+.section sr29b
+.section sr20a
+.section sr20b
+.section sr3aa
+.section sr3ab
+.section sr3ba
+.section sr3bb
+.section sr3ca
+.section sr3cb
+.section sr3da
+.section sr3db
+.section sr3ea
+.section sr3eb
+.section sr3fa
+.section sr3fb
+.section sr3ga
+.section sr3gb
+.section sr3ha
+.section sr3hb
+.section sr3ia
+.section sr3ib
+.section sr3ja
+.section sr3jb
+.section sr3ka
+.section sr3kb
+.section sr3la
+.section sr3lb
+.section sr3ma
+.section sr3mb
+.section sr3na
+.section sr3nb
+.section sr3oa
+.section sr3ob
+.section sr3pa
+.section sr3pb
+.section sr3qa
+.section sr3qb
+.section sr3ra
+.section sr3rb
+.section sr3sa
+.section sr3sb
+.section sr3ta
+.section sr3tb
+.section sr3ua
+.section sr3ub
+.section sr3va
+.section sr3vb
+.section sr3wa
+.section sr3wb
+.section sr3xa
+.section sr3xb
+.section sr3ya
+.section sr3yb
+.section sr3za
+.section sr3zb
+.section sr31a
+.section sr31b
+.section sr32a
+.section sr32b
+.section sr33a
+.section sr33b
+.section sr34a
+.section sr34b
+.section sr35a
+.section sr35b
+.section sr36a
+.section sr36b
+.section sr37a
+.section sr37b
+.section sr38a
+.section sr38b
+.section sr39a
+.section sr39b
+.section sr30a
+.section sr30b
+.section sr4aa
+.section sr4ab
+.section sr4ba
+.section sr4bb
+.section sr4ca
+.section sr4cb
+.section sr4da
+.section sr4db
+.section sr4ea
+.section sr4eb
+.section sr4fa
+.section sr4fb
+.section sr4ga
+.section sr4gb
+.section sr4ha
+.section sr4hb
+.section sr4ia
+.section sr4ib
+.section sr4ja
+.section sr4jb
+.section sr4ka
+.section sr4kb
+.section sr4la
+.section sr4lb
+.section sr4ma
+.section sr4mb
+.section sr4na
+.section sr4nb
+.section sr4oa
+.section sr4ob
+.section sr4pa
+.section sr4pb
+.section sr4qa
+.section sr4qb
+.section sr4ra
+.section sr4rb
+.section sr4sa
+.section sr4sb
+.section sr4ta
+.section sr4tb
+.section sr4ua
+.section sr4ub
+.section sr4va
+.section sr4vb
+.section sr4wa
+.section sr4wb
+.section sr4xa
+.section sr4xb
+.section sr4ya
+.section sr4yb
+.section sr4za
+.section sr4zb
+.section sr41a
+.section sr41b
+.section sr42a
+.section sr42b
+.section sr43a
+.section sr43b
+.section sr44a
+.section sr44b
+.section sr45a
+.section sr45b
+.section sr46a
+.section sr46b
+.section sr47a
+.section sr47b
+.section sr48a
+.section sr48b
+.section sr49a
+.section sr49b
+.section sr40a
+.section sr40b
+.section sr5aa
+.section sr5ab
+.section sr5ba
+.section sr5bb
+.section sr5ca
+.section sr5cb
+.section sr5da
+.section sr5db
+.section sr5ea
+.section sr5eb
+.section sr5fa
+.section sr5fb
+.section sr5ga
+.section sr5gb
+.section sr5ha
+.section sr5hb
+.section sr5ia
+.section sr5ib
+.section sr5ja
+.section sr5jb
+.section sr5ka
+.section sr5kb
+.section sr5la
+.section sr5lb
+.section sr5ma
+.section sr5mb
+.section sr5na
+.section sr5nb
+.section sr5oa
+.section sr5ob
+.section sr5pa
+.section sr5pb
+.section sr5qa
+.section sr5qb
+.section sr5ra
+.section sr5rb
+.section sr5sa
+.section sr5sb
+.section sr5ta
+.section sr5tb
+.section sr5ua
+.section sr5ub
+.section sr5va
+.section sr5vb
+.section sr5wa
+.section sr5wb
+.section sr5xa
+.section sr5xb
+.section sr5ya
+.section sr5yb
+.section sr5za
+.section sr5zb
+.section sr51a
+.section sr51b
+.section sr52a
+.section sr52b
+.section sr53a
+.section sr53b
+.section sr54a
+.section sr54b
+.section sr55a
+.section sr55b
+.section sr56a
+.section sr56b
+.section sr57a
+.section sr57b
+.section sr58a
+.section sr58b
+.section sr59a
+.section sr59b
+.section sr50a
+.section sr50b
+.section sr6aa
+.section sr6ab
+.section sr6ba
+.section sr6bb
+.section sr6ca
+.section sr6cb
+.section sr6da
+.section sr6db
+.section sr6ea
+.section sr6eb
+.section sr6fa
+.section sr6fb
+.section sr6ga
+.section sr6gb
+.section sr6ha
+.section sr6hb
+.section sr6ia
+.section sr6ib
+.section sr6ja
+.section sr6jb
+.section sr6ka
+.section sr6kb
+.section sr6la
+.section sr6lb
+.section sr6ma
+.section sr6mb
+.section sr6na
+.section sr6nb
+.section sr6oa
+.section sr6ob
+.section sr6pa
+.section sr6pb
+.section sr6qa
+.section sr6qb
+.section sr6ra
+.section sr6rb
+.section sr6sa
+.section sr6sb
+.section sr6ta
+.section sr6tb
+.section sr6ua
+.section sr6ub
+.section sr6va
+.section sr6vb
+.section sr6wa
+.section sr6wb
+.section sr6xa
+.section sr6xb
+.section sr6ya
+.section sr6yb
+.section sr6za
+.section sr6zb
+.section sr61a
+.section sr61b
+.section sr62a
+.section sr62b
+.section sr63a
+.section sr63b
+.section sr64a
+.section sr64b
+.section sr65a
+.section sr65b
+.section sr66a
+.section sr66b
+.section sr67a
+.section sr67b
+.section sr68a
+.section sr68b
+.section sr69a
+.section sr69b
+.section sr60a
+.section sr60b
+.section sr7aa
+.section sr7ab
+.section sr7ba
+.section sr7bb
+.section sr7ca
+.section sr7cb
+.section sr7da
+.section sr7db
+.section sr7ea
+.section sr7eb
+.section sr7fa
+.section sr7fb
+.section sr7ga
+.section sr7gb
+.section sr7ha
+.section sr7hb
+.section sr7ia
+.section sr7ib
+.section sr7ja
+.section sr7jb
+.section sr7ka
+.section sr7kb
+.section sr7la
+.section sr7lb
+.section sr7ma
+.section sr7mb
+.section sr7na
+.section sr7nb
+.section sr7oa
+.section sr7ob
+.section sr7pa
+.section sr7pb
+.section sr7qa
+.section sr7qb
+.section sr7ra
+.section sr7rb
+.section sr7sa
+.section sr7sb
+.section sr7ta
+.section sr7tb
+.section sr7ua
+.section sr7ub
+.section sr7va
+.section sr7vb
+.section sr7wa
+.section sr7wb
+.section sr7xa
+.section sr7xb
+.section sr7ya
+.section sr7yb
+.section sr7za
+.section sr7zb
+.section sr71a
+.section sr71b
+.section sr72a
+.section sr72b
+.section sr73a
+.section sr73b
+.section sr74a
+.section sr74b
+.section sr75a
+.section sr75b
+.section sr76a
+.section sr76b
+.section sr77a
+.section sr77b
+.section sr78a
+.section sr78b
+.section sr79a
+.section sr79b
+.section sr70a
+.section sr70b
+.section sr8aa
+.section sr8ab
+.section sr8ba
+.section sr8bb
+.section sr8ca
+.section sr8cb
+.section sr8da
+.section sr8db
+.section sr8ea
+.section sr8eb
+.section sr8fa
+.section sr8fb
+.section sr8ga
+.section sr8gb
+.section sr8ha
+.section sr8hb
+.section sr8ia
+.section sr8ib
+.section sr8ja
+.section sr8jb
+.section sr8ka
+.section sr8kb
+.section sr8la
+.section sr8lb
+.section sr8ma
+.section sr8mb
+.section sr8na
+.section sr8nb
+.section sr8oa
+.section sr8ob
+.section sr8pa
+.section sr8pb
+.section sr8qa
+.section sr8qb
+.section sr8ra
+.section sr8rb
+.section sr8sa
+.section sr8sb
+.section sr8ta
+.section sr8tb
+.section sr8ua
+.section sr8ub
+.section sr8va
+.section sr8vb
+.section sr8wa
+.section sr8wb
+.section sr8xa
+.section sr8xb
+.section sr8ya
+.section sr8yb
+.section sr8za
+.section sr8zb
+.section sr81a
+.section sr81b
+.section sr82a
+.section sr82b
+.section sr83a
+.section sr83b
+.section sr84a
+.section sr84b
+.section sr85a
+.section sr85b
+.section sr86a
+.section sr86b
+.section sr87a
+.section sr87b
+.section sr88a
+.section sr88b
+.section sr89a
+.section sr89b
+.section sr80a
+.section sr80b
+.section sr9aa
+.section sr9ab
+.section sr9ba
+.section sr9bb
+.section sr9ca
+.section sr9cb
+.section sr9da
+.section sr9db
+.section sr9ea
+.section sr9eb
+.section sr9fa
+.section sr9fb
+.section sr9ga
+.section sr9gb
+.section sr9ha
+.section sr9hb
+.section sr9ia
+.section sr9ib
+.section sr9ja
+.section sr9jb
+.section sr9ka
+.section sr9kb
+.section sr9la
+.section sr9lb
+.section sr9ma
+.section sr9mb
+.section sr9na
+.section sr9nb
+.section sr9oa
+.section sr9ob
+.section sr9pa
+.section sr9pb
+.section sr9qa
+.section sr9qb
+.section sr9ra
+.section sr9rb
+.section sr9sa
+.section sr9sb
+.section sr9ta
+.section sr9tb
+.section sr9ua
+.section sr9ub
+.section sr9va
+.section sr9vb
+.section sr9wa
+.section sr9wb
+.section sr9xa
+.section sr9xb
+.section sr9ya
+.section sr9yb
+.section sr9za
+.section sr9zb
+.section sr91a
+.section sr91b
+.section sr92a
+.section sr92b
+.section sr93a
+.section sr93b
+.section sr94a
+.section sr94b
+.section sr95a
+.section sr95b
+.section sr96a
+.section sr96b
+.section sr97a
+.section sr97b
+.section sr98a
+.section sr98b
+.section sr99a
+.section sr99b
+.section sr90a
+.section sr90b
+.section sr0aa
+.section sr0ab
+.section sr0ba
+.section sr0bb
+.section sr0ca
+.section sr0cb
+.section sr0da
+.section sr0db
+.section sr0ea
+.section sr0eb
+.section sr0fa
+.section sr0fb
+.section sr0ga
+.section sr0gb
+.section sr0ha
+.section sr0hb
+.section sr0ia
+.section sr0ib
+.section sr0ja
+.section sr0jb
+.section sr0ka
+.section sr0kb
+.section sr0la
+.section sr0lb
+.section sr0ma
+.section sr0mb
+.section sr0na
+.section sr0nb
+.section sr0oa
+.section sr0ob
+.section sr0pa
+.section sr0pb
+.section sr0qa
+.section sr0qb
+.section sr0ra
+.section sr0rb
+.section sr0sa
+.section sr0sb
+.section sr0ta
+.section sr0tb
+.section sr0ua
+.section sr0ub
+.section sr0va
+.section sr0vb
+.section sr0wa
+.section sr0wb
+.section sr0xa
+.section sr0xb
+.section sr0ya
+.section sr0yb
+.section sr0za
+.section sr0zb
+.section sr01a
+.section sr01b
+.section sr02a
+.section sr02b
+.section sr03a
+.section sr03b
+.section sr04a
+.section sr04b
+.section sr05a
+.section sr05b
+.section sr06a
+.section sr06b
+.section sr07a
+.section sr07b
+.section sr08a
+.section sr08b
+.section sr09a
+.section sr09b
+.section sr00a
+.section sr00b
+.section ssaaa
+.section ssaab
+.section ssaba
+.section ssabb
+.section ssaca
+.section ssacb
+.section ssada
+.section ssadb
+.section ssaea
+.section ssaeb
+.section ssafa
+.section ssafb
+.section ssaga
+.section ssagb
+.section ssaha
+.section ssahb
+.section ssaia
+.section ssaib
+.section ssaja
+.section ssajb
+.section ssaka
+.section ssakb
+.section ssala
+.section ssalb
+.section ssama
+.section ssamb
+.section ssana
+.section ssanb
+.section ssaoa
+.section ssaob
+.section ssapa
+.section ssapb
+.section ssaqa
+.section ssaqb
+.section ssara
+.section ssarb
+.section ssasa
+.section ssasb
+.section ssata
+.section ssatb
+.section ssaua
+.section ssaub
+.section ssava
+.section ssavb
+.section ssawa
+.section ssawb
+.section ssaxa
+.section ssaxb
+.section ssaya
+.section ssayb
+.section ssaza
+.section ssazb
+.section ssa1a
+.section ssa1b
+.section ssa2a
+.section ssa2b
+.section ssa3a
+.section ssa3b
+.section ssa4a
+.section ssa4b
+.section ssa5a
+.section ssa5b
+.section ssa6a
+.section ssa6b
+.section ssa7a
+.section ssa7b
+.section ssa8a
+.section ssa8b
+.section ssa9a
+.section ssa9b
+.section ssa0a
+.section ssa0b
+.section ssbaa
+.section ssbab
+.section ssbba
+.section ssbbb
+.section ssbca
+.section ssbcb
+.section ssbda
+.section ssbdb
+.section ssbea
+.section ssbeb
+.section ssbfa
+.section ssbfb
+.section ssbga
+.section ssbgb
+.section ssbha
+.section ssbhb
+.section ssbia
+.section ssbib
+.section ssbja
+.section ssbjb
+.section ssbka
+.section ssbkb
+.section ssbla
+.section ssblb
+.section ssbma
+.section ssbmb
+.section ssbna
+.section ssbnb
+.section ssboa
+.section ssbob
+.section ssbpa
+.section ssbpb
+.section ssbqa
+.section ssbqb
+.section ssbra
+.section ssbrb
+.section ssbsa
+.section ssbsb
+.section ssbta
+.section ssbtb
+.section ssbua
+.section ssbub
+.section ssbva
+.section ssbvb
+.section ssbwa
+.section ssbwb
+.section ssbxa
+.section ssbxb
+.section ssbya
+.section ssbyb
+.section ssbza
+.section ssbzb
+.section ssb1a
+.section ssb1b
+.section ssb2a
+.section ssb2b
+.section ssb3a
+.section ssb3b
+.section ssb4a
+.section ssb4b
+.section ssb5a
+.section ssb5b
+.section ssb6a
+.section ssb6b
+.section ssb7a
+.section ssb7b
+.section ssb8a
+.section ssb8b
+.section ssb9a
+.section ssb9b
+.section ssb0a
+.section ssb0b
+.section sscaa
+.section sscab
+.section sscba
+.section sscbb
+.section sscca
+.section ssccb
+.section sscda
+.section sscdb
+.section sscea
+.section ssceb
+.section sscfa
+.section sscfb
+.section sscga
+.section sscgb
+.section sscha
+.section sschb
+.section sscia
+.section sscib
+.section sscja
+.section sscjb
+.section sscka
+.section ssckb
+.section sscla
+.section ssclb
+.section sscma
+.section sscmb
+.section sscna
+.section sscnb
+.section sscoa
+.section sscob
+.section sscpa
+.section sscpb
+.section sscqa
+.section sscqb
+.section sscra
+.section sscrb
+.section sscsa
+.section sscsb
+.section sscta
+.section ssctb
+.section sscua
+.section sscub
+.section sscva
+.section sscvb
+.section sscwa
+.section sscwb
+.section sscxa
+.section sscxb
+.section sscya
+.section sscyb
+.section sscza
+.section ssczb
+.section ssc1a
+.section ssc1b
+.section ssc2a
+.section ssc2b
+.section ssc3a
+.section ssc3b
+.section ssc4a
+.section ssc4b
+.section ssc5a
+.section ssc5b
+.section ssc6a
+.section ssc6b
+.section ssc7a
+.section ssc7b
+.section ssc8a
+.section ssc8b
+.section ssc9a
+.section ssc9b
+.section ssc0a
+.section ssc0b
+.section ssdaa
+.section ssdab
+.section ssdba
+.section ssdbb
+.section ssdca
+.section ssdcb
+.section ssdda
+.section ssddb
+.section ssdea
+.section ssdeb
+.section ssdfa
+.section ssdfb
+.section ssdga
+.section ssdgb
+.section ssdha
+.section ssdhb
+.section ssdia
+.section ssdib
+.section ssdja
+.section ssdjb
+.section ssdka
+.section ssdkb
+.section ssdla
+.section ssdlb
+.section ssdma
+.section ssdmb
+.section ssdna
+.section ssdnb
+.section ssdoa
+.section ssdob
+.section ssdpa
+.section ssdpb
+.section ssdqa
+.section ssdqb
+.section ssdra
+.section ssdrb
+.section ssdsa
+.section ssdsb
+.section ssdta
+.section ssdtb
+.section ssdua
+.section ssdub
+.section ssdva
+.section ssdvb
+.section ssdwa
+.section ssdwb
+.section ssdxa
+.section ssdxb
+.section ssdya
+.section ssdyb
+.section ssdza
+.section ssdzb
+.section ssd1a
+.section ssd1b
+.section ssd2a
+.section ssd2b
+.section ssd3a
+.section ssd3b
+.section ssd4a
+.section ssd4b
+.section ssd5a
+.section ssd5b
+.section ssd6a
+.section ssd6b
+.section ssd7a
+.section ssd7b
+.section ssd8a
+.section ssd8b
+.section ssd9a
+.section ssd9b
+.section ssd0a
+.section ssd0b
+.section sseaa
+.section sseab
+.section sseba
+.section ssebb
+.section sseca
+.section ssecb
+.section sseda
+.section ssedb
+.section sseea
+.section sseeb
+.section ssefa
+.section ssefb
+.section ssega
+.section ssegb
+.section sseha
+.section ssehb
+.section sseia
+.section sseib
+.section sseja
+.section ssejb
+.section sseka
+.section ssekb
+.section ssela
+.section sselb
+.section ssema
+.section ssemb
+.section ssena
+.section ssenb
+.section sseoa
+.section sseob
+.section ssepa
+.section ssepb
+.section sseqa
+.section sseqb
+.section ssera
+.section sserb
+.section ssesa
+.section ssesb
+.section sseta
+.section ssetb
+.section sseua
+.section sseub
+.section sseva
+.section ssevb
+.section ssewa
+.section ssewb
+.section ssexa
+.section ssexb
+.section sseya
+.section sseyb
+.section sseza
+.section ssezb
+.section sse1a
+.section sse1b
+.section sse2a
+.section sse2b
+.section sse3a
+.section sse3b
+.section sse4a
+.section sse4b
+.section sse5a
+.section sse5b
+.section sse6a
+.section sse6b
+.section sse7a
+.section sse7b
+.section sse8a
+.section sse8b
+.section sse9a
+.section sse9b
+.section sse0a
+.section sse0b
+.section ssfaa
+.section ssfab
+.section ssfba
+.section ssfbb
+.section ssfca
+.section ssfcb
+.section ssfda
+.section ssfdb
+.section ssfea
+.section ssfeb
+.section ssffa
+.section ssffb
+.section ssfga
+.section ssfgb
+.section ssfha
+.section ssfhb
+.section ssfia
+.section ssfib
+.section ssfja
+.section ssfjb
+.section ssfka
+.section ssfkb
+.section ssfla
+.section ssflb
+.section ssfma
+.section ssfmb
+.section ssfna
+.section ssfnb
+.section ssfoa
+.section ssfob
+.section ssfpa
+.section ssfpb
+.section ssfqa
+.section ssfqb
+.section ssfra
+.section ssfrb
+.section ssfsa
+.section ssfsb
+.section ssfta
+.section ssftb
+.section ssfua
+.section ssfub
+.section ssfva
+.section ssfvb
+.section ssfwa
+.section ssfwb
+.section ssfxa
+.section ssfxb
+.section ssfya
+.section ssfyb
+.section ssfza
+.section ssfzb
+.section ssf1a
+.section ssf1b
+.section ssf2a
+.section ssf2b
+.section ssf3a
+.section ssf3b
+.section ssf4a
+.section ssf4b
+.section ssf5a
+.section ssf5b
+.section ssf6a
+.section ssf6b
+.section ssf7a
+.section ssf7b
+.section ssf8a
+.section ssf8b
+.section ssf9a
+.section ssf9b
+.section ssf0a
+.section ssf0b
+.section ssgaa
+.section ssgab
+.section ssgba
+.section ssgbb
+.section ssgca
+.section ssgcb
+.section ssgda
+.section ssgdb
+.section ssgea
+.section ssgeb
+.section ssgfa
+.section ssgfb
+.section ssgga
+.section ssggb
+.section ssgha
+.section ssghb
+.section ssgia
+.section ssgib
+.section ssgja
+.section ssgjb
+.section ssgka
+.section ssgkb
+.section ssgla
+.section ssglb
+.section ssgma
+.section ssgmb
+.section ssgna
+.section ssgnb
+.section ssgoa
+.section ssgob
+.section ssgpa
+.section ssgpb
+.section ssgqa
+.section ssgqb
+.section ssgra
+.section ssgrb
+.section ssgsa
+.section ssgsb
+.section ssgta
+.section ssgtb
+.section ssgua
+.section ssgub
+.section ssgva
+.section ssgvb
+.section ssgwa
+.section ssgwb
+.section ssgxa
+.section ssgxb
+.section ssgya
+.section ssgyb
+.section ssgza
+.section ssgzb
+.section ssg1a
+.section ssg1b
+.section ssg2a
+.section ssg2b
+.section ssg3a
+.section ssg3b
+.section ssg4a
+.section ssg4b
+.section ssg5a
+.section ssg5b
+.section ssg6a
+.section ssg6b
+.section ssg7a
+.section ssg7b
+.section ssg8a
+.section ssg8b
+.section ssg9a
+.section ssg9b
+.section ssg0a
+.section ssg0b
+.section sshaa
+.section sshab
+.section sshba
+.section sshbb
+.section sshca
+.section sshcb
+.section sshda
+.section sshdb
+.section sshea
+.section ssheb
+.section sshfa
+.section sshfb
+.section sshga
+.section sshgb
+.section sshha
+.section sshhb
+.section sshia
+.section sshib
+.section sshja
+.section sshjb
+.section sshka
+.section sshkb
+.section sshla
+.section sshlb
+.section sshma
+.section sshmb
+.section sshna
+.section sshnb
+.section sshoa
+.section sshob
+.section sshpa
+.section sshpb
+.section sshqa
+.section sshqb
+.section sshra
+.section sshrb
+.section sshsa
+.section sshsb
+.section sshta
+.section sshtb
+.section sshua
+.section sshub
+.section sshva
+.section sshvb
+.section sshwa
+.section sshwb
+.section sshxa
+.section sshxb
+.section sshya
+.section sshyb
+.section sshza
+.section sshzb
+.section ssh1a
+.section ssh1b
+.section ssh2a
+.section ssh2b
+.section ssh3a
+.section ssh3b
+.section ssh4a
+.section ssh4b
+.section ssh5a
+.section ssh5b
+.section ssh6a
+.section ssh6b
+.section ssh7a
+.section ssh7b
+.section ssh8a
+.section ssh8b
+.section ssh9a
+.section ssh9b
+.section ssh0a
+.section ssh0b
+.section ssiaa
+.section ssiab
+.section ssiba
+.section ssibb
+.section ssica
+.section ssicb
+.section ssida
+.section ssidb
+.section ssiea
+.section ssieb
+.section ssifa
+.section ssifb
+.section ssiga
+.section ssigb
+.section ssiha
+.section ssihb
+.section ssiia
+.section ssiib
+.section ssija
+.section ssijb
+.section ssika
+.section ssikb
+.section ssila
+.section ssilb
+.section ssima
+.section ssimb
+.section ssina
+.section ssinb
+.section ssioa
+.section ssiob
+.section ssipa
+.section ssipb
+.section ssiqa
+.section ssiqb
+.section ssira
+.section ssirb
+.section ssisa
+.section ssisb
+.section ssita
+.section ssitb
+.section ssiua
+.section ssiub
+.section ssiva
+.section ssivb
+.section ssiwa
+.section ssiwb
+.section ssixa
+.section ssixb
+.section ssiya
+.section ssiyb
+.section ssiza
+.section ssizb
+.section ssi1a
+.section ssi1b
+.section ssi2a
+.section ssi2b
+.section ssi3a
+.section ssi3b
+.section ssi4a
+.section ssi4b
+.section ssi5a
+.section ssi5b
+.section ssi6a
+.section ssi6b
+.section ssi7a
+.section ssi7b
+.section ssi8a
+.section ssi8b
+.section ssi9a
+.section ssi9b
+.section ssi0a
+.section ssi0b
+.section ssjaa
+.section ssjab
+.section ssjba
+.section ssjbb
+.section ssjca
+.section ssjcb
+.section ssjda
+.section ssjdb
+.section ssjea
+.section ssjeb
+.section ssjfa
+.section ssjfb
+.section ssjga
+.section ssjgb
+.section ssjha
+.section ssjhb
+.section ssjia
+.section ssjib
+.section ssjja
+.section ssjjb
+.section ssjka
+.section ssjkb
+.section ssjla
+.section ssjlb
+.section ssjma
+.section ssjmb
+.section ssjna
+.section ssjnb
+.section ssjoa
+.section ssjob
+.section ssjpa
+.section ssjpb
+.section ssjqa
+.section ssjqb
+.section ssjra
+.section ssjrb
+.section ssjsa
+.section ssjsb
+.section ssjta
+.section ssjtb
+.section ssjua
+.section ssjub
+.section ssjva
+.section ssjvb
+.section ssjwa
+.section ssjwb
+.section ssjxa
+.section ssjxb
+.section ssjya
+.section ssjyb
+.section ssjza
+.section ssjzb
+.section ssj1a
+.section ssj1b
+.section ssj2a
+.section ssj2b
+.section ssj3a
+.section ssj3b
+.section ssj4a
+.section ssj4b
+.section ssj5a
+.section ssj5b
+.section ssj6a
+.section ssj6b
+.section ssj7a
+.section ssj7b
+.section ssj8a
+.section ssj8b
+.section ssj9a
+.section ssj9b
+.section ssj0a
+.section ssj0b
+.section sskaa
+.section sskab
+.section sskba
+.section sskbb
+.section sskca
+.section sskcb
+.section sskda
+.section sskdb
+.section sskea
+.section sskeb
+.section sskfa
+.section sskfb
+.section sskga
+.section sskgb
+.section sskha
+.section sskhb
+.section sskia
+.section sskib
+.section sskja
+.section sskjb
+.section sskka
+.section sskkb
+.section sskla
+.section ssklb
+.section sskma
+.section sskmb
+.section sskna
+.section ssknb
+.section sskoa
+.section sskob
+.section sskpa
+.section sskpb
+.section sskqa
+.section sskqb
+.section sskra
+.section sskrb
+.section ssksa
+.section ssksb
+.section sskta
+.section ssktb
+.section sskua
+.section sskub
+.section sskva
+.section sskvb
+.section sskwa
+.section sskwb
+.section sskxa
+.section sskxb
+.section sskya
+.section sskyb
+.section sskza
+.section sskzb
+.section ssk1a
+.section ssk1b
+.section ssk2a
+.section ssk2b
+.section ssk3a
+.section ssk3b
+.section ssk4a
+.section ssk4b
+.section ssk5a
+.section ssk5b
+.section ssk6a
+.section ssk6b
+.section ssk7a
+.section ssk7b
+.section ssk8a
+.section ssk8b
+.section ssk9a
+.section ssk9b
+.section ssk0a
+.section ssk0b
+.section sslaa
+.section sslab
+.section sslba
+.section sslbb
+.section sslca
+.section sslcb
+.section sslda
+.section ssldb
+.section sslea
+.section ssleb
+.section sslfa
+.section sslfb
+.section sslga
+.section sslgb
+.section sslha
+.section sslhb
+.section sslia
+.section sslib
+.section sslja
+.section ssljb
+.section sslka
+.section sslkb
+.section sslla
+.section ssllb
+.section sslma
+.section sslmb
+.section sslna
+.section sslnb
+.section ssloa
+.section sslob
+.section sslpa
+.section sslpb
+.section sslqa
+.section sslqb
+.section sslra
+.section sslrb
+.section sslsa
+.section sslsb
+.section sslta
+.section ssltb
+.section sslua
+.section sslub
+.section sslva
+.section sslvb
+.section sslwa
+.section sslwb
+.section sslxa
+.section sslxb
+.section sslya
+.section sslyb
+.section sslza
+.section sslzb
+.section ssl1a
+.section ssl1b
+.section ssl2a
+.section ssl2b
+.section ssl3a
+.section ssl3b
+.section ssl4a
+.section ssl4b
+.section ssl5a
+.section ssl5b
+.section ssl6a
+.section ssl6b
+.section ssl7a
+.section ssl7b
+.section ssl8a
+.section ssl8b
+.section ssl9a
+.section ssl9b
+.section ssl0a
+.section ssl0b
+.section ssmaa
+.section ssmab
+.section ssmba
+.section ssmbb
+.section ssmca
+.section ssmcb
+.section ssmda
+.section ssmdb
+.section ssmea
+.section ssmeb
+.section ssmfa
+.section ssmfb
+.section ssmga
+.section ssmgb
+.section ssmha
+.section ssmhb
+.section ssmia
+.section ssmib
+.section ssmja
+.section ssmjb
+.section ssmka
+.section ssmkb
+.section ssmla
+.section ssmlb
+.section ssmma
+.section ssmmb
+.section ssmna
+.section ssmnb
+.section ssmoa
+.section ssmob
+.section ssmpa
+.section ssmpb
+.section ssmqa
+.section ssmqb
+.section ssmra
+.section ssmrb
+.section ssmsa
+.section ssmsb
+.section ssmta
+.section ssmtb
+.section ssmua
+.section ssmub
+.section ssmva
+.section ssmvb
+.section ssmwa
+.section ssmwb
+.section ssmxa
+.section ssmxb
+.section ssmya
+.section ssmyb
+.section ssmza
+.section ssmzb
+.section ssm1a
+.section ssm1b
+.section ssm2a
+.section ssm2b
+.section ssm3a
+.section ssm3b
+.section ssm4a
+.section ssm4b
+.section ssm5a
+.section ssm5b
+.section ssm6a
+.section ssm6b
+.section ssm7a
+.section ssm7b
+.section ssm8a
+.section ssm8b
+.section ssm9a
+.section ssm9b
+.section ssm0a
+.section ssm0b
+.section ssnaa
+.section ssnab
+.section ssnba
+.section ssnbb
+.section ssnca
+.section ssncb
+.section ssnda
+.section ssndb
+.section ssnea
+.section ssneb
+.section ssnfa
+.section ssnfb
+.section ssnga
+.section ssngb
+.section ssnha
+.section ssnhb
+.section ssnia
+.section ssnib
+.section ssnja
+.section ssnjb
+.section ssnka
+.section ssnkb
+.section ssnla
+.section ssnlb
+.section ssnma
+.section ssnmb
+.section ssnna
+.section ssnnb
+.section ssnoa
+.section ssnob
+.section ssnpa
+.section ssnpb
+.section ssnqa
+.section ssnqb
+.section ssnra
+.section ssnrb
+.section ssnsa
+.section ssnsb
+.section ssnta
+.section ssntb
+.section ssnua
+.section ssnub
+.section ssnva
+.section ssnvb
+.section ssnwa
+.section ssnwb
+.section ssnxa
+.section ssnxb
+.section ssnya
+.section ssnyb
+.section ssnza
+.section ssnzb
+.section ssn1a
+.section ssn1b
+.section ssn2a
+.section ssn2b
+.section ssn3a
+.section ssn3b
+.section ssn4a
+.section ssn4b
+.section ssn5a
+.section ssn5b
+.section ssn6a
+.section ssn6b
+.section ssn7a
+.section ssn7b
+.section ssn8a
+.section ssn8b
+.section ssn9a
+.section ssn9b
+.section ssn0a
+.section ssn0b
+.section ssoaa
+.section ssoab
+.section ssoba
+.section ssobb
+.section ssoca
+.section ssocb
+.section ssoda
+.section ssodb
+.section ssoea
+.section ssoeb
+.section ssofa
+.section ssofb
+.section ssoga
+.section ssogb
+.section ssoha
+.section ssohb
+.section ssoia
+.section ssoib
+.section ssoja
+.section ssojb
+.section ssoka
+.section ssokb
+.section ssola
+.section ssolb
+.section ssoma
+.section ssomb
+.section ssona
+.section ssonb
+.section ssooa
+.section ssoob
+.section ssopa
+.section ssopb
+.section ssoqa
+.section ssoqb
+.section ssora
+.section ssorb
+.section ssosa
+.section ssosb
+.section ssota
+.section ssotb
+.section ssoua
+.section ssoub
+.section ssova
+.section ssovb
+.section ssowa
+.section ssowb
+.section ssoxa
+.section ssoxb
+.section ssoya
+.section ssoyb
+.section ssoza
+.section ssozb
+.section sso1a
+.section sso1b
+.section sso2a
+.section sso2b
+.section sso3a
+.section sso3b
+.section sso4a
+.section sso4b
+.section sso5a
+.section sso5b
+.section sso6a
+.section sso6b
+.section sso7a
+.section sso7b
+.section sso8a
+.section sso8b
+.section sso9a
+.section sso9b
+.section sso0a
+.section sso0b
+.section sspaa
+.section sspab
+.section sspba
+.section sspbb
+.section sspca
+.section sspcb
+.section sspda
+.section sspdb
+.section sspea
+.section sspeb
+.section sspfa
+.section sspfb
+.section sspga
+.section sspgb
+.section sspha
+.section ssphb
+.section sspia
+.section sspib
+.section sspja
+.section sspjb
+.section sspka
+.section sspkb
+.section sspla
+.section ssplb
+.section sspma
+.section sspmb
+.section sspna
+.section sspnb
+.section sspoa
+.section sspob
+.section ssppa
+.section ssppb
+.section sspqa
+.section sspqb
+.section sspra
+.section ssprb
+.section sspsa
+.section sspsb
+.section sspta
+.section ssptb
+.section sspua
+.section sspub
+.section sspva
+.section sspvb
+.section sspwa
+.section sspwb
+.section sspxa
+.section sspxb
+.section sspya
+.section sspyb
+.section sspza
+.section sspzb
+.section ssp1a
+.section ssp1b
+.section ssp2a
+.section ssp2b
+.section ssp3a
+.section ssp3b
+.section ssp4a
+.section ssp4b
+.section ssp5a
+.section ssp5b
+.section ssp6a
+.section ssp6b
+.section ssp7a
+.section ssp7b
+.section ssp8a
+.section ssp8b
+.section ssp9a
+.section ssp9b
+.section ssp0a
+.section ssp0b
+.section ssqaa
+.section ssqab
+.section ssqba
+.section ssqbb
+.section ssqca
+.section ssqcb
+.section ssqda
+.section ssqdb
+.section ssqea
+.section ssqeb
+.section ssqfa
+.section ssqfb
+.section ssqga
+.section ssqgb
+.section ssqha
+.section ssqhb
+.section ssqia
+.section ssqib
+.section ssqja
+.section ssqjb
+.section ssqka
+.section ssqkb
+.section ssqla
+.section ssqlb
+.section ssqma
+.section ssqmb
+.section ssqna
+.section ssqnb
+.section ssqoa
+.section ssqob
+.section ssqpa
+.section ssqpb
+.section ssqqa
+.section ssqqb
+.section ssqra
+.section ssqrb
+.section ssqsa
+.section ssqsb
+.section ssqta
+.section ssqtb
+.section ssqua
+.section ssqub
+.section ssqva
+.section ssqvb
+.section ssqwa
+.section ssqwb
+.section ssqxa
+.section ssqxb
+.section ssqya
+.section ssqyb
+.section ssqza
+.section ssqzb
+.section ssq1a
+.section ssq1b
+.section ssq2a
+.section ssq2b
+.section ssq3a
+.section ssq3b
+.section ssq4a
+.section ssq4b
+.section ssq5a
+.section ssq5b
+.section ssq6a
+.section ssq6b
+.section ssq7a
+.section ssq7b
+.section ssq8a
+.section ssq8b
+.section ssq9a
+.section ssq9b
+.section ssq0a
+.section ssq0b
+.section ssraa
+.section ssrab
+.section ssrba
+.section ssrbb
+.section ssrca
+.section ssrcb
+.section ssrda
+.section ssrdb
+.section ssrea
+.section ssreb
+.section ssrfa
+.section ssrfb
+.section ssrga
+.section ssrgb
+.section ssrha
+.section ssrhb
+.section ssria
+.section ssrib
+.section ssrja
+.section ssrjb
+.section ssrka
+.section ssrkb
+.section ssrla
+.section ssrlb
+.section ssrma
+.section ssrmb
+.section ssrna
+.section ssrnb
+.section ssroa
+.section ssrob
+.section ssrpa
+.section ssrpb
+.section ssrqa
+.section ssrqb
+.section ssrra
+.section ssrrb
+.section ssrsa
+.section ssrsb
+.section ssrta
+.section ssrtb
+.section ssrua
+.section ssrub
+.section ssrva
+.section ssrvb
+.section ssrwa
+.section ssrwb
+.section ssrxa
+.section ssrxb
+.section ssrya
+.section ssryb
+.section ssrza
+.section ssrzb
+.section ssr1a
+.section ssr1b
+.section ssr2a
+.section ssr2b
+.section ssr3a
+.section ssr3b
+.section ssr4a
+.section ssr4b
+.section ssr5a
+.section ssr5b
+.section ssr6a
+.section ssr6b
+.section ssr7a
+.section ssr7b
+.section ssr8a
+.section ssr8b
+.section ssr9a
+.section ssr9b
+.section ssr0a
+.section ssr0b
+.section sssaa
+.section sssab
+.section sssba
+.section sssbb
+.section sssca
+.section ssscb
+.section sssda
+.section sssdb
+.section sssea
+.section ssseb
+.section sssfa
+.section sssfb
+.section sssga
+.section sssgb
+.section sssha
+.section ssshb
+.section sssia
+.section sssib
+.section sssja
+.section sssjb
+.section ssska
+.section ssskb
+.section sssla
+.section ssslb
+.section sssma
+.section sssmb
+.section sssna
+.section sssnb
+.section sssoa
+.section sssob
+.section ssspa
+.section ssspb
+.section sssqa
+.section sssqb
+.section sssra
+.section sssrb
+.section ssssa
+.section ssssb
+.section sssta
+.section ssstb
+.section sssua
+.section sssub
+.section sssva
+.section sssvb
+.section ssswa
+.section ssswb
+.section sssxa
+.section sssxb
+.section sssya
+.section sssyb
+.section sssza
+.section ssszb
+.section sss1a
+.section sss1b
+.section sss2a
+.section sss2b
+.section sss3a
+.section sss3b
+.section sss4a
+.section sss4b
+.section sss5a
+.section sss5b
+.section sss6a
+.section sss6b
+.section sss7a
+.section sss7b
+.section sss8a
+.section sss8b
+.section sss9a
+.section sss9b
+.section sss0a
+.section sss0b
+.section sstaa
+.section sstab
+.section sstba
+.section sstbb
+.section sstca
+.section sstcb
+.section sstda
+.section sstdb
+.section sstea
+.section ssteb
+.section sstfa
+.section sstfb
+.section sstga
+.section sstgb
+.section sstha
+.section ssthb
+.section sstia
+.section sstib
+.section sstja
+.section sstjb
+.section sstka
+.section sstkb
+.section sstla
+.section sstlb
+.section sstma
+.section sstmb
+.section sstna
+.section sstnb
+.section sstoa
+.section sstob
+.section sstpa
+.section sstpb
+.section sstqa
+.section sstqb
+.section sstra
+.section sstrb
+.section sstsa
+.section sstsb
+.section sstta
+.section ssttb
+.section sstua
+.section sstub
+.section sstva
+.section sstvb
+.section sstwa
+.section sstwb
+.section sstxa
+.section sstxb
+.section sstya
+.section sstyb
+.section sstza
+.section sstzb
+.section sst1a
+.section sst1b
+.section sst2a
+.section sst2b
+.section sst3a
+.section sst3b
+.section sst4a
+.section sst4b
+.section sst5a
+.section sst5b
+.section sst6a
+.section sst6b
+.section sst7a
+.section sst7b
+.section sst8a
+.section sst8b
+.section sst9a
+.section sst9b
+.section sst0a
+.section sst0b
+.section ssuaa
+.section ssuab
+.section ssuba
+.section ssubb
+.section ssuca
+.section ssucb
+.section ssuda
+.section ssudb
+.section ssuea
+.section ssueb
+.section ssufa
+.section ssufb
+.section ssuga
+.section ssugb
+.section ssuha
+.section ssuhb
+.section ssuia
+.section ssuib
+.section ssuja
+.section ssujb
+.section ssuka
+.section ssukb
+.section ssula
+.section ssulb
+.section ssuma
+.section ssumb
+.section ssuna
+.section ssunb
+.section ssuoa
+.section ssuob
+.section ssupa
+.section ssupb
+.section ssuqa
+.section ssuqb
+.section ssura
+.section ssurb
+.section ssusa
+.section ssusb
+.section ssuta
+.section ssutb
+.section ssuua
+.section ssuub
+.section ssuva
+.section ssuvb
+.section ssuwa
+.section ssuwb
+.section ssuxa
+.section ssuxb
+.section ssuya
+.section ssuyb
+.section ssuza
+.section ssuzb
+.section ssu1a
+.section ssu1b
+.section ssu2a
+.section ssu2b
+.section ssu3a
+.section ssu3b
+.section ssu4a
+.section ssu4b
+.section ssu5a
+.section ssu5b
+.section ssu6a
+.section ssu6b
+.section ssu7a
+.section ssu7b
+.section ssu8a
+.section ssu8b
+.section ssu9a
+.section ssu9b
+.section ssu0a
+.section ssu0b
+.section ssvaa
+.section ssvab
+.section ssvba
+.section ssvbb
+.section ssvca
+.section ssvcb
+.section ssvda
+.section ssvdb
+.section ssvea
+.section ssveb
+.section ssvfa
+.section ssvfb
+.section ssvga
+.section ssvgb
+.section ssvha
+.section ssvhb
+.section ssvia
+.section ssvib
+.section ssvja
+.section ssvjb
+.section ssvka
+.section ssvkb
+.section ssvla
+.section ssvlb
+.section ssvma
+.section ssvmb
+.section ssvna
+.section ssvnb
+.section ssvoa
+.section ssvob
+.section ssvpa
+.section ssvpb
+.section ssvqa
+.section ssvqb
+.section ssvra
+.section ssvrb
+.section ssvsa
+.section ssvsb
+.section ssvta
+.section ssvtb
+.section ssvua
+.section ssvub
+.section ssvva
+.section ssvvb
+.section ssvwa
+.section ssvwb
+.section ssvxa
+.section ssvxb
+.section ssvya
+.section ssvyb
+.section ssvza
+.section ssvzb
+.section ssv1a
+.section ssv1b
+.section ssv2a
+.section ssv2b
+.section ssv3a
+.section ssv3b
+.section ssv4a
+.section ssv4b
+.section ssv5a
+.section ssv5b
+.section ssv6a
+.section ssv6b
+.section ssv7a
+.section ssv7b
+.section ssv8a
+.section ssv8b
+.section ssv9a
+.section ssv9b
+.section ssv0a
+.section ssv0b
+.section sswaa
+.section sswab
+.section sswba
+.section sswbb
+.section sswca
+.section sswcb
+.section sswda
+.section sswdb
+.section sswea
+.section ssweb
+.section sswfa
+.section sswfb
+.section sswga
+.section sswgb
+.section sswha
+.section sswhb
+.section sswia
+.section sswib
+.section sswja
+.section sswjb
+.section sswka
+.section sswkb
+.section sswla
+.section sswlb
+.section sswma
+.section sswmb
+.section sswna
+.section sswnb
+.section sswoa
+.section sswob
+.section sswpa
+.section sswpb
+.section sswqa
+.section sswqb
+.section sswra
+.section sswrb
+.section sswsa
+.section sswsb
+.section sswta
+.section sswtb
+.section sswua
+.section sswub
+.section sswva
+.section sswvb
+.section sswwa
+.section sswwb
+.section sswxa
+.section sswxb
+.section sswya
+.section sswyb
+.section sswza
+.section sswzb
+.section ssw1a
+.section ssw1b
+.section ssw2a
+.section ssw2b
+.section ssw3a
+.section ssw3b
+.section ssw4a
+.section ssw4b
+.section ssw5a
+.section ssw5b
+.section ssw6a
+.section ssw6b
+.section ssw7a
+.section ssw7b
+.section ssw8a
+.section ssw8b
+.section ssw9a
+.section ssw9b
+.section ssw0a
+.section ssw0b
+.section ssxaa
+.section ssxab
+.section ssxba
+.section ssxbb
+.section ssxca
+.section ssxcb
+.section ssxda
+.section ssxdb
+.section ssxea
+.section ssxeb
+.section ssxfa
+.section ssxfb
+.section ssxga
+.section ssxgb
+.section ssxha
+.section ssxhb
+.section ssxia
+.section ssxib
+.section ssxja
+.section ssxjb
+.section ssxka
+.section ssxkb
+.section ssxla
+.section ssxlb
+.section ssxma
+.section ssxmb
+.section ssxna
+.section ssxnb
+.section ssxoa
+.section ssxob
+.section ssxpa
+.section ssxpb
+.section ssxqa
+.section ssxqb
+.section ssxra
+.section ssxrb
+.section ssxsa
+.section ssxsb
+.section ssxta
+.section ssxtb
+.section ssxua
+.section ssxub
+.section ssxva
+.section ssxvb
+.section ssxwa
+.section ssxwb
+.section ssxxa
+.section ssxxb
+.section ssxya
+.section ssxyb
+.section ssxza
+.section ssxzb
+.section ssx1a
+.section ssx1b
+.section ssx2a
+.section ssx2b
+.section ssx3a
+.section ssx3b
+.section ssx4a
+.section ssx4b
+.section ssx5a
+.section ssx5b
+.section ssx6a
+.section ssx6b
+.section ssx7a
+.section ssx7b
+.section ssx8a
+.section ssx8b
+.section ssx9a
+.section ssx9b
+.section ssx0a
+.section ssx0b
+.section ssyaa
+.section ssyab
+.section ssyba
+.section ssybb
+.section ssyca
+.section ssycb
+.section ssyda
+.section ssydb
+.section ssyea
+.section ssyeb
+.section ssyfa
+.section ssyfb
+.section ssyga
+.section ssygb
+.section ssyha
+.section ssyhb
+.section ssyia
+.section ssyib
+.section ssyja
+.section ssyjb
+.section ssyka
+.section ssykb
+.section ssyla
+.section ssylb
+.section ssyma
+.section ssymb
+.section ssyna
+.section ssynb
+.section ssyoa
+.section ssyob
+.section ssypa
+.section ssypb
+.section ssyqa
+.section ssyqb
+.section ssyra
+.section ssyrb
+.section ssysa
+.section ssysb
+.section ssyta
+.section ssytb
+.section ssyua
+.section ssyub
+.section ssyva
+.section ssyvb
+.section ssywa
+.section ssywb
+.section ssyxa
+.section ssyxb
+.section ssyya
+.section ssyyb
+.section ssyza
+.section ssyzb
+.section ssy1a
+.section ssy1b
+.section ssy2a
+.section ssy2b
+.section ssy3a
+.section ssy3b
+.section ssy4a
+.section ssy4b
+.section ssy5a
+.section ssy5b
+.section ssy6a
+.section ssy6b
+.section ssy7a
+.section ssy7b
+.section ssy8a
+.section ssy8b
+.section ssy9a
+.section ssy9b
+.section ssy0a
+.section ssy0b
+.section sszaa
+.section sszab
+.section sszba
+.section sszbb
+.section sszca
+.section sszcb
+.section sszda
+.section sszdb
+.section sszea
+.section sszeb
+.section sszfa
+.section sszfb
+.section sszga
+.section sszgb
+.section sszha
+.section sszhb
+.section sszia
+.section sszib
+.section sszja
+.section sszjb
+.section sszka
+.section sszkb
+.section sszla
+.section sszlb
+.section sszma
+.section sszmb
+.section sszna
+.section ssznb
+.section sszoa
+.section sszob
+.section sszpa
+.section sszpb
+.section sszqa
+.section sszqb
+.section sszra
+.section sszrb
+.section sszsa
+.section sszsb
+.section sszta
+.section ssztb
+.section sszua
+.section sszub
+.section sszva
+.section sszvb
+.section sszwa
+.section sszwb
+.section sszxa
+.section sszxb
+.section sszya
+.section sszyb
+.section sszza
+.section sszzb
+.section ssz1a
+.section ssz1b
+.section ssz2a
+.section ssz2b
+.section ssz3a
+.section ssz3b
+.section ssz4a
+.section ssz4b
+.section ssz5a
+.section ssz5b
+.section ssz6a
+.section ssz6b
+.section ssz7a
+.section ssz7b
+.section ssz8a
+.section ssz8b
+.section ssz9a
+.section ssz9b
+.section ssz0a
+.section ssz0b
+.section ss1aa
+.section ss1ab
+.section ss1ba
+.section ss1bb
+.section ss1ca
+.section ss1cb
+.section ss1da
+.section ss1db
+.section ss1ea
+.section ss1eb
+.section ss1fa
+.section ss1fb
+.section ss1ga
+.section ss1gb
+.section ss1ha
+.section ss1hb
+.section ss1ia
+.section ss1ib
+.section ss1ja
+.section ss1jb
+.section ss1ka
+.section ss1kb
+.section ss1la
+.section ss1lb
+.section ss1ma
+.section ss1mb
+.section ss1na
+.section ss1nb
+.section ss1oa
+.section ss1ob
+.section ss1pa
+.section ss1pb
+.section ss1qa
+.section ss1qb
+.section ss1ra
+.section ss1rb
+.section ss1sa
+.section ss1sb
+.section ss1ta
+.section ss1tb
+.section ss1ua
+.section ss1ub
+.section ss1va
+.section ss1vb
+.section ss1wa
+.section ss1wb
+.section ss1xa
+.section ss1xb
+.section ss1ya
+.section ss1yb
+.section ss1za
+.section ss1zb
+.section ss11a
+.section ss11b
+.section ss12a
+.section ss12b
+.section ss13a
+.section ss13b
+.section ss14a
+.section ss14b
+.section ss15a
+.section ss15b
+.section ss16a
+.section ss16b
+.section ss17a
+.section ss17b
+.section ss18a
+.section ss18b
+.section ss19a
+.section ss19b
+.section ss10a
+.section ss10b
+.section ss2aa
+.section ss2ab
+.section ss2ba
+.section ss2bb
+.section ss2ca
+.section ss2cb
+.section ss2da
+.section ss2db
+.section ss2ea
+.section ss2eb
+.section ss2fa
+.section ss2fb
+.section ss2ga
+.section ss2gb
+.section ss2ha
+.section ss2hb
+.section ss2ia
+.section ss2ib
+.section ss2ja
+.section ss2jb
+.section ss2ka
+.section ss2kb
+.section ss2la
+.section ss2lb
+.section ss2ma
+.section ss2mb
+.section ss2na
+.section ss2nb
+.section ss2oa
+.section ss2ob
+.section ss2pa
+.section ss2pb
+.section ss2qa
+.section ss2qb
+.section ss2ra
+.section ss2rb
+.section ss2sa
+.section ss2sb
+.section ss2ta
+.section ss2tb
+.section ss2ua
+.section ss2ub
+.section ss2va
+.section ss2vb
+.section ss2wa
+.section ss2wb
+.section ss2xa
+.section ss2xb
+.section ss2ya
+.section ss2yb
+.section ss2za
+.section ss2zb
+.section ss21a
+.section ss21b
+.section ss22a
+.section ss22b
+.section ss23a
+.section ss23b
+.section ss24a
+.section ss24b
+.section ss25a
+.section ss25b
+.section ss26a
+.section ss26b
+.section ss27a
+.section ss27b
+.section ss28a
+.section ss28b
+.section ss29a
+.section ss29b
+.section ss20a
+.section ss20b
+.section ss3aa
+.section ss3ab
+.section ss3ba
+.section ss3bb
+.section ss3ca
+.section ss3cb
+.section ss3da
+.section ss3db
+.section ss3ea
+.section ss3eb
+.section ss3fa
+.section ss3fb
+.section ss3ga
+.section ss3gb
+.section ss3ha
+.section ss3hb
+.section ss3ia
+.section ss3ib
+.section ss3ja
+.section ss3jb
+.section ss3ka
+.section ss3kb
+.section ss3la
+.section ss3lb
+.section ss3ma
+.section ss3mb
+.section ss3na
+.section ss3nb
+.section ss3oa
+.section ss3ob
+.section ss3pa
+.section ss3pb
+.section ss3qa
+.section ss3qb
+.section ss3ra
+.section ss3rb
+.section ss3sa
+.section ss3sb
+.section ss3ta
+.section ss3tb
+.section ss3ua
+.section ss3ub
+.section ss3va
+.section ss3vb
+.section ss3wa
+.section ss3wb
+.section ss3xa
+.section ss3xb
+.section ss3ya
+.section ss3yb
+.section ss3za
+.section ss3zb
+.section ss31a
+.section ss31b
+.section ss32a
+.section ss32b
+.section ss33a
+.section ss33b
+.section ss34a
+.section ss34b
+.section ss35a
+.section ss35b
+.section ss36a
+.section ss36b
+.section ss37a
+.section ss37b
+.section ss38a
+.section ss38b
+.section ss39a
+.section ss39b
+.section ss30a
+.section ss30b
+.section ss4aa
+.section ss4ab
+.section ss4ba
+.section ss4bb
+.section ss4ca
+.section ss4cb
+.section ss4da
+.section ss4db
+.section ss4ea
+.section ss4eb
+.section ss4fa
+.section ss4fb
+.section ss4ga
+.section ss4gb
+.section ss4ha
+.section ss4hb
+.section ss4ia
+.section ss4ib
+.section ss4ja
+.section ss4jb
+.section ss4ka
+.section ss4kb
+.section ss4la
+.section ss4lb
+.section ss4ma
+.section ss4mb
+.section ss4na
+.section ss4nb
+.section ss4oa
+.section ss4ob
+.section ss4pa
+.section ss4pb
+.section ss4qa
+.section ss4qb
+.section ss4ra
+.section ss4rb
+.section ss4sa
+.section ss4sb
+.section ss4ta
+.section ss4tb
+.section ss4ua
+.section ss4ub
+.section ss4va
+.section ss4vb
+.section ss4wa
+.section ss4wb
+.section ss4xa
+.section ss4xb
+.section ss4ya
+.section ss4yb
+.section ss4za
+.section ss4zb
+.section ss41a
+.section ss41b
+.section ss42a
+.section ss42b
+.section ss43a
+.section ss43b
+.section ss44a
+.section ss44b
+.section ss45a
+.section ss45b
+.section ss46a
+.section ss46b
+.section ss47a
+.section ss47b
+.section ss48a
+.section ss48b
+.section ss49a
+.section ss49b
+.section ss40a
+.section ss40b
+.section ss5aa
+.section ss5ab
+.section ss5ba
+.section ss5bb
+.section ss5ca
+.section ss5cb
+.section ss5da
+.section ss5db
+.section ss5ea
+.section ss5eb
+.section ss5fa
+.section ss5fb
+.section ss5ga
+.section ss5gb
+.section ss5ha
+.section ss5hb
+.section ss5ia
+.section ss5ib
+.section ss5ja
+.section ss5jb
+.section ss5ka
+.section ss5kb
+.section ss5la
+.section ss5lb
+.section ss5ma
+.section ss5mb
+.section ss5na
+.section ss5nb
+.section ss5oa
+.section ss5ob
+.section ss5pa
+.section ss5pb
+.section ss5qa
+.section ss5qb
+.section ss5ra
+.section ss5rb
+.section ss5sa
+.section ss5sb
+.section ss5ta
+.section ss5tb
+.section ss5ua
+.section ss5ub
+.section ss5va
+.section ss5vb
+.section ss5wa
+.section ss5wb
+.section ss5xa
+.section ss5xb
+.section ss5ya
+.section ss5yb
+.section ss5za
+.section ss5zb
+.section ss51a
+.section ss51b
+.section ss52a
+.section ss52b
+.section ss53a
+.section ss53b
+.section ss54a
+.section ss54b
+.section ss55a
+.section ss55b
+.section ss56a
+.section ss56b
+.section ss57a
+.section ss57b
+.section ss58a
+.section ss58b
+.section ss59a
+.section ss59b
+.section ss50a
+.section ss50b
+.section ss6aa
+.section ss6ab
+.section ss6ba
+.section ss6bb
+.section ss6ca
+.section ss6cb
+.section ss6da
+.section ss6db
+.section ss6ea
+.section ss6eb
+.section ss6fa
+.section ss6fb
+.section ss6ga
+.section ss6gb
+.section ss6ha
+.section ss6hb
+.section ss6ia
+.section ss6ib
+.section ss6ja
+.section ss6jb
+.section ss6ka
+.section ss6kb
+.section ss6la
+.section ss6lb
+.section ss6ma
+.section ss6mb
+.section ss6na
+.section ss6nb
+.section ss6oa
+.section ss6ob
+.section ss6pa
+.section ss6pb
+.section ss6qa
+.section ss6qb
+.section ss6ra
+.section ss6rb
+.section ss6sa
+.section ss6sb
+.section ss6ta
+.section ss6tb
+.section ss6ua
+.section ss6ub
+.section ss6va
+.section ss6vb
+.section ss6wa
+.section ss6wb
+.section ss6xa
+.section ss6xb
+.section ss6ya
+.section ss6yb
+.section ss6za
+.section ss6zb
+.section ss61a
+.section ss61b
+.section ss62a
+.section ss62b
+.section ss63a
+.section ss63b
+.section ss64a
+.section ss64b
+.section ss65a
+.section ss65b
+.section ss66a
+.section ss66b
+.section ss67a
+.section ss67b
+.section ss68a
+.section ss68b
+.section ss69a
+.section ss69b
+.section ss60a
+.section ss60b
+.section ss7aa
+.section ss7ab
+.section ss7ba
+.section ss7bb
+.section ss7ca
+.section ss7cb
+.section ss7da
+.section ss7db
+.section ss7ea
+.section ss7eb
+.section ss7fa
+.section ss7fb
+.section ss7ga
+.section ss7gb
+.section ss7ha
+.section ss7hb
+.section ss7ia
+.section ss7ib
+.section ss7ja
+.section ss7jb
+.section ss7ka
+.section ss7kb
+.section ss7la
+.section ss7lb
+.section ss7ma
+.section ss7mb
+.section ss7na
+.section ss7nb
+.section ss7oa
+.section ss7ob
+.section ss7pa
+.section ss7pb
+.section ss7qa
+.section ss7qb
+.section ss7ra
+.section ss7rb
+.section ss7sa
+.section ss7sb
+.section ss7ta
+.section ss7tb
+.section ss7ua
+.section ss7ub
+.section ss7va
+.section ss7vb
+.section ss7wa
+.section ss7wb
+.section ss7xa
+.section ss7xb
+.section ss7ya
+.section ss7yb
+.section ss7za
+.section ss7zb
+.section ss71a
+.section ss71b
+.section ss72a
+.section ss72b
+.section ss73a
+.section ss73b
+.section ss74a
+.section ss74b
+.section ss75a
+.section ss75b
+.section ss76a
+.section ss76b
+.section ss77a
+.section ss77b
+.section ss78a
+.section ss78b
+.section ss79a
+.section ss79b
+.section ss70a
+.section ss70b
+.section ss8aa
+.section ss8ab
+.section ss8ba
+.section ss8bb
+.section ss8ca
+.section ss8cb
+.section ss8da
+.section ss8db
+.section ss8ea
+.section ss8eb
+.section ss8fa
+.section ss8fb
+.section ss8ga
+.section ss8gb
+.section ss8ha
+.section ss8hb
+.section ss8ia
+.section ss8ib
+.section ss8ja
+.section ss8jb
+.section ss8ka
+.section ss8kb
+.section ss8la
+.section ss8lb
+.section ss8ma
+.section ss8mb
+.section ss8na
+.section ss8nb
+.section ss8oa
+.section ss8ob
+.section ss8pa
+.section ss8pb
+.section ss8qa
+.section ss8qb
+.section ss8ra
+.section ss8rb
+.section ss8sa
+.section ss8sb
+.section ss8ta
+.section ss8tb
+.section ss8ua
+.section ss8ub
+.section ss8va
+.section ss8vb
+.section ss8wa
+.section ss8wb
+.section ss8xa
+.section ss8xb
+.section ss8ya
+.section ss8yb
+.section ss8za
+.section ss8zb
+.section ss81a
+.section ss81b
+.section ss82a
+.section ss82b
+.section ss83a
+.section ss83b
+.section ss84a
+.section ss84b
+.section ss85a
+.section ss85b
+.section ss86a
+.section ss86b
+.section ss87a
+.section ss87b
+.section ss88a
+.section ss88b
+.section ss89a
+.section ss89b
+.section ss80a
+.section ss80b
+.section ss9aa
+.section ss9ab
+.section ss9ba
+.section ss9bb
+.section ss9ca
+.section ss9cb
+.section ss9da
+.section ss9db
+.section ss9ea
+.section ss9eb
+.section ss9fa
+.section ss9fb
+.section ss9ga
+.section ss9gb
+.section ss9ha
+.section ss9hb
+.section ss9ia
+.section ss9ib
+.section ss9ja
+.section ss9jb
+.section ss9ka
+.section ss9kb
+.section ss9la
+.section ss9lb
+.section ss9ma
+.section ss9mb
+.section ss9na
+.section ss9nb
+.section ss9oa
+.section ss9ob
+.section ss9pa
+.section ss9pb
+.section ss9qa
+.section ss9qb
+.section ss9ra
+.section ss9rb
+.section ss9sa
+.section ss9sb
+.section ss9ta
+.section ss9tb
+.section ss9ua
+.section ss9ub
+.section ss9va
+.section ss9vb
+.section ss9wa
+.section ss9wb
+.section ss9xa
+.section ss9xb
+.section ss9ya
+.section ss9yb
+.section ss9za
+.section ss9zb
+.section ss91a
+.section ss91b
+.section ss92a
+.section ss92b
+.section ss93a
+.section ss93b
+.section ss94a
+.section ss94b
+.section ss95a
+.section ss95b
+.section ss96a
+.section ss96b
+.section ss97a
+.section ss97b
+.section ss98a
+.section ss98b
+.section ss99a
+.section ss99b
+.section ss90a
+.section ss90b
+.section ss0aa
+.section ss0ab
+.section ss0ba
+.section ss0bb
+.section ss0ca
+.section ss0cb
+.section ss0da
+.section ss0db
+.section ss0ea
+.section ss0eb
+.section ss0fa
+.section ss0fb
+.section ss0ga
+.section ss0gb
+.section ss0ha
+.section ss0hb
+.section ss0ia
+.section ss0ib
+.section ss0ja
+.section ss0jb
+.section ss0ka
+.section ss0kb
+.section ss0la
+.section ss0lb
+.section ss0ma
+.section ss0mb
+.section ss0na
+.section ss0nb
+.section ss0oa
+.section ss0ob
+.section ss0pa
+.section ss0pb
+.section ss0qa
+.section ss0qb
+.section ss0ra
+.section ss0rb
+.section ss0sa
+.section ss0sb
+.section ss0ta
+.section ss0tb
+.section ss0ua
+.section ss0ub
+.section ss0va
+.section ss0vb
+.section ss0wa
+.section ss0wb
+.section ss0xa
+.section ss0xb
+.section ss0ya
+.section ss0yb
+.section ss0za
+.section ss0zb
+.section ss01a
+.section ss01b
+.section ss02a
+.section ss02b
+.section ss03a
+.section ss03b
+.section ss04a
+.section ss04b
+.section ss05a
+.section ss05b
+.section ss06a
+.section ss06b
+.section ss07a
+.section ss07b
+.section ss08a
+.section ss08b
+.section ss09a
+.section ss09b
+.section ss00a
+.section ss00b
+.section staaa
+.section staab
+.section staba
+.section stabb
+.section staca
+.section stacb
+.section stada
+.section stadb
+.section staea
+.section staeb
+.section stafa
+.section stafb
+.section staga
+.section stagb
+.section staha
+.section stahb
+.section staia
+.section staib
+.section staja
+.section stajb
+.section staka
+.section stakb
+.section stala
+.section stalb
+.section stama
+.section stamb
+.section stana
+.section stanb
+.section staoa
+.section staob
+.section stapa
+.section stapb
+.section staqa
+.section staqb
+.section stara
+.section starb
+.section stasa
+.section stasb
+.section stata
+.section statb
+.section staua
+.section staub
+.section stava
+.section stavb
+.section stawa
+.section stawb
+.section staxa
+.section staxb
+.section staya
+.section stayb
+.section staza
+.section stazb
+.section sta1a
+.section sta1b
+.section sta2a
+.section sta2b
+.section sta3a
+.section sta3b
+.section sta4a
+.section sta4b
+.section sta5a
+.section sta5b
+.section sta6a
+.section sta6b
+.section sta7a
+.section sta7b
+.section sta8a
+.section sta8b
+.section sta9a
+.section sta9b
+.section sta0a
+.section sta0b
+.section stbaa
+.section stbab
+.section stbba
+.section stbbb
+.section stbca
+.section stbcb
+.section stbda
+.section stbdb
+.section stbea
+.section stbeb
+.section stbfa
+.section stbfb
+.section stbga
+.section stbgb
+.section stbha
+.section stbhb
+.section stbia
+.section stbib
+.section stbja
+.section stbjb
+.section stbka
+.section stbkb
+.section stbla
+.section stblb
+.section stbma
+.section stbmb
+.section stbna
+.section stbnb
+.section stboa
+.section stbob
+.section stbpa
+.section stbpb
+.section stbqa
+.section stbqb
+.section stbra
+.section stbrb
+.section stbsa
+.section stbsb
+.section stbta
+.section stbtb
+.section stbua
+.section stbub
+.section stbva
+.section stbvb
+.section stbwa
+.section stbwb
+.section stbxa
+.section stbxb
+.section stbya
+.section stbyb
+.section stbza
+.section stbzb
+.section stb1a
+.section stb1b
+.section stb2a
+.section stb2b
+.section stb3a
+.section stb3b
+.section stb4a
+.section stb4b
+.section stb5a
+.section stb5b
+.section stb6a
+.section stb6b
+.section stb7a
+.section stb7b
+.section stb8a
+.section stb8b
+.section stb9a
+.section stb9b
+.section stb0a
+.section stb0b
+.section stcaa
+.section stcab
+.section stcba
+.section stcbb
+.section stcca
+.section stccb
+.section stcda
+.section stcdb
+.section stcea
+.section stceb
+.section stcfa
+.section stcfb
+.section stcga
+.section stcgb
+.section stcha
+.section stchb
+.section stcia
+.section stcib
+.section stcja
+.section stcjb
+.section stcka
+.section stckb
+.section stcla
+.section stclb
+.section stcma
+.section stcmb
+.section stcna
+.section stcnb
+.section stcoa
+.section stcob
+.section stcpa
+.section stcpb
+.section stcqa
+.section stcqb
+.section stcra
+.section stcrb
+.section stcsa
+.section stcsb
+.section stcta
+.section stctb
+.section stcua
+.section stcub
+.section stcva
+.section stcvb
+.section stcwa
+.section stcwb
+.section stcxa
+.section stcxb
+.section stcya
+.section stcyb
+.section stcza
+.section stczb
+.section stc1a
+.section stc1b
+.section stc2a
+.section stc2b
+.section stc3a
+.section stc3b
+.section stc4a
+.section stc4b
+.section stc5a
+.section stc5b
+.section stc6a
+.section stc6b
+.section stc7a
+.section stc7b
+.section stc8a
+.section stc8b
+.section stc9a
+.section stc9b
+.section stc0a
+.section stc0b
+.section stdaa
+.section stdab
+.section stdba
+.section stdbb
+.section stdca
+.section stdcb
+.section stdda
+.section stddb
+.section stdea
+.section stdeb
+.section stdfa
+.section stdfb
+.section stdga
+.section stdgb
+.section stdha
+.section stdhb
+.section stdia
+.section stdib
+.section stdja
+.section stdjb
+.section stdka
+.section stdkb
+.section stdla
+.section stdlb
+.section stdma
+.section stdmb
+.section stdna
+.section stdnb
+.section stdoa
+.section stdob
+.section stdpa
+.section stdpb
+.section stdqa
+.section stdqb
+.section stdra
+.section stdrb
+.section stdsa
+.section stdsb
+.section stdta
+.section stdtb
+.section stdua
+.section stdub
+.section stdva
+.section stdvb
+.section stdwa
+.section stdwb
+.section stdxa
+.section stdxb
+.section stdya
+.section stdyb
+.section stdza
+.section stdzb
+.section std1a
+.section std1b
+.section std2a
+.section std2b
+.section std3a
+.section std3b
+.section std4a
+.section std4b
+.section std5a
+.section std5b
+.section std6a
+.section std6b
+.section std7a
+.section std7b
+.section std8a
+.section std8b
+.section std9a
+.section std9b
+.section std0a
+.section std0b
+.section steaa
+.section steab
+.section steba
+.section stebb
+.section steca
+.section stecb
+.section steda
+.section stedb
+.section steea
+.section steeb
+.section stefa
+.section stefb
+.section stega
+.section stegb
+.section steha
+.section stehb
+.section steia
+.section steib
+.section steja
+.section stejb
+.section steka
+.section stekb
+.section stela
+.section stelb
+.section stema
+.section stemb
+.section stena
+.section stenb
+.section steoa
+.section steob
+.section stepa
+.section stepb
+.section steqa
+.section steqb
+.section stera
+.section sterb
+.section stesa
+.section stesb
+.section steta
+.section stetb
+.section steua
+.section steub
+.section steva
+.section stevb
+.section stewa
+.section stewb
+.section stexa
+.section stexb
+.section steya
+.section steyb
+.section steza
+.section stezb
+.section ste1a
+.section ste1b
+.section ste2a
+.section ste2b
+.section ste3a
+.section ste3b
+.section ste4a
+.section ste4b
+.section ste5a
+.section ste5b
+.section ste6a
+.section ste6b
+.section ste7a
+.section ste7b
+.section ste8a
+.section ste8b
+.section ste9a
+.section ste9b
+.section ste0a
+.section ste0b
+.section stfaa
+.section stfab
+.section stfba
+.section stfbb
+.section stfca
+.section stfcb
+.section stfda
+.section stfdb
+.section stfea
+.section stfeb
+.section stffa
+.section stffb
+.section stfga
+.section stfgb
+.section stfha
+.section stfhb
+.section stfia
+.section stfib
+.section stfja
+.section stfjb
+.section stfka
+.section stfkb
+.section stfla
+.section stflb
+.section stfma
+.section stfmb
+.section stfna
+.section stfnb
+.section stfoa
+.section stfob
+.section stfpa
+.section stfpb
+.section stfqa
+.section stfqb
+.section stfra
+.section stfrb
+.section stfsa
+.section stfsb
+.section stfta
+.section stftb
+.section stfua
+.section stfub
+.section stfva
+.section stfvb
+.section stfwa
+.section stfwb
+.section stfxa
+.section stfxb
+.section stfya
+.section stfyb
+.section stfza
+.section stfzb
+.section stf1a
+.section stf1b
+.section stf2a
+.section stf2b
+.section stf3a
+.section stf3b
+.section stf4a
+.section stf4b
+.section stf5a
+.section stf5b
+.section stf6a
+.section stf6b
+.section stf7a
+.section stf7b
+.section stf8a
+.section stf8b
+.section stf9a
+.section stf9b
+.section stf0a
+.section stf0b
+.section stgaa
+.section stgab
+.section stgba
+.section stgbb
+.section stgca
+.section stgcb
+.section stgda
+.section stgdb
+.section stgea
+.section stgeb
+.section stgfa
+.section stgfb
+.section stgga
+.section stggb
+.section stgha
+.section stghb
+.section stgia
+.section stgib
+.section stgja
+.section stgjb
+.section stgka
+.section stgkb
+.section stgla
+.section stglb
+.section stgma
+.section stgmb
+.section stgna
+.section stgnb
+.section stgoa
+.section stgob
+.section stgpa
+.section stgpb
+.section stgqa
+.section stgqb
+.section stgra
+.section stgrb
+.section stgsa
+.section stgsb
+.section stgta
+.section stgtb
+.section stgua
+.section stgub
+.section stgva
+.section stgvb
+.section stgwa
+.section stgwb
+.section stgxa
+.section stgxb
+.section stgya
+.section stgyb
+.section stgza
+.section stgzb
+.section stg1a
+.section stg1b
+.section stg2a
+.section stg2b
+.section stg3a
+.section stg3b
+.section stg4a
+.section stg4b
+.section stg5a
+.section stg5b
+.section stg6a
+.section stg6b
+.section stg7a
+.section stg7b
+.section stg8a
+.section stg8b
+.section stg9a
+.section stg9b
+.section stg0a
+.section stg0b
+.section sthaa
+.section sthab
+.section sthba
+.section sthbb
+.section sthca
+.section sthcb
+.section sthda
+.section sthdb
+.section sthea
+.section stheb
+.section sthfa
+.section sthfb
+.section sthga
+.section sthgb
+.section sthha
+.section sthhb
+.section sthia
+.section sthib
+.section sthja
+.section sthjb
+.section sthka
+.section sthkb
+.section sthla
+.section sthlb
+.section sthma
+.section sthmb
+.section sthna
+.section sthnb
+.section sthoa
+.section sthob
+.section sthpa
+.section sthpb
+.section sthqa
+.section sthqb
+.section sthra
+.section sthrb
+.section sthsa
+.section sthsb
+.section sthta
+.section sthtb
+.section sthua
+.section sthub
+.section sthva
+.section sthvb
+.section sthwa
+.section sthwb
+.section sthxa
+.section sthxb
+.section sthya
+.section sthyb
+.section sthza
+.section sthzb
+.section sth1a
+.section sth1b
+.section sth2a
+.section sth2b
+.section sth3a
+.section sth3b
+.section sth4a
+.section sth4b
+.section sth5a
+.section sth5b
+.section sth6a
+.section sth6b
+.section sth7a
+.section sth7b
+.section sth8a
+.section sth8b
+.section sth9a
+.section sth9b
+.section sth0a
+.section sth0b
+.section stiaa
+.section stiab
+.section stiba
+.section stibb
+.section stica
+.section sticb
+.section stida
+.section stidb
+.section stiea
+.section stieb
+.section stifa
+.section stifb
+.section stiga
+.section stigb
+.section stiha
+.section stihb
+.section stiia
+.section stiib
+.section stija
+.section stijb
+.section stika
+.section stikb
+.section stila
+.section stilb
+.section stima
+.section stimb
+.section stina
+.section stinb
+.section stioa
+.section stiob
+.section stipa
+.section stipb
+.section stiqa
+.section stiqb
+.section stira
+.section stirb
+.section stisa
+.section stisb
+.section stita
+.section stitb
+.section stiua
+.section stiub
+.section stiva
+.section stivb
+.section stiwa
+.section stiwb
+.section stixa
+.section stixb
+.section stiya
+.section stiyb
+.section stiza
+.section stizb
+.section sti1a
+.section sti1b
+.section sti2a
+.section sti2b
+.section sti3a
+.section sti3b
+.section sti4a
+.section sti4b
+.section sti5a
+.section sti5b
+.section sti6a
+.section sti6b
+.section sti7a
+.section sti7b
+.section sti8a
+.section sti8b
+.section sti9a
+.section sti9b
+.section sti0a
+.section sti0b
+.section stjaa
+.section stjab
+.section stjba
+.section stjbb
+.section stjca
+.section stjcb
+.section stjda
+.section stjdb
+.section stjea
+.section stjeb
+.section stjfa
+.section stjfb
+.section stjga
+.section stjgb
+.section stjha
+.section stjhb
+.section stjia
+.section stjib
+.section stjja
+.section stjjb
+.section stjka
+.section stjkb
+.section stjla
+.section stjlb
+.section stjma
+.section stjmb
+.section stjna
+.section stjnb
+.section stjoa
+.section stjob
+.section stjpa
+.section stjpb
+.section stjqa
+.section stjqb
+.section stjra
+.section stjrb
+.section stjsa
+.section stjsb
+.section stjta
+.section stjtb
+.section stjua
+.section stjub
+.section stjva
+.section stjvb
+.section stjwa
+.section stjwb
+.section stjxa
+.section stjxb
+.section stjya
+.section stjyb
+.section stjza
+.section stjzb
+.section stj1a
+.section stj1b
+.section stj2a
+.section stj2b
+.section stj3a
+.section stj3b
+.section stj4a
+.section stj4b
+.section stj5a
+.section stj5b
+.section stj6a
+.section stj6b
+.section stj7a
+.section stj7b
+.section stj8a
+.section stj8b
+.section stj9a
+.section stj9b
+.section stj0a
+.section stj0b
+.section stkaa
+.section stkab
+.section stkba
+.section stkbb
+.section stkca
+.section stkcb
+.section stkda
+.section stkdb
+.section stkea
+.section stkeb
+.section stkfa
+.section stkfb
+.section stkga
+.section stkgb
+.section stkha
+.section stkhb
+.section stkia
+.section stkib
+.section stkja
+.section stkjb
+.section stkka
+.section stkkb
+.section stkla
+.section stklb
+.section stkma
+.section stkmb
+.section stkna
+.section stknb
+.section stkoa
+.section stkob
+.section stkpa
+.section stkpb
+.section stkqa
+.section stkqb
+.section stkra
+.section stkrb
+.section stksa
+.section stksb
+.section stkta
+.section stktb
+.section stkua
+.section stkub
+.section stkva
+.section stkvb
+.section stkwa
+.section stkwb
+.section stkxa
+.section stkxb
+.section stkya
+.section stkyb
+.section stkza
+.section stkzb
+.section stk1a
+.section stk1b
+.section stk2a
+.section stk2b
+.section stk3a
+.section stk3b
+.section stk4a
+.section stk4b
+.section stk5a
+.section stk5b
+.section stk6a
+.section stk6b
+.section stk7a
+.section stk7b
+.section stk8a
+.section stk8b
+.section stk9a
+.section stk9b
+.section stk0a
+.section stk0b
+.section stlaa
+.section stlab
+.section stlba
+.section stlbb
+.section stlca
+.section stlcb
+.section stlda
+.section stldb
+.section stlea
+.section stleb
+.section stlfa
+.section stlfb
+.section stlga
+.section stlgb
+.section stlha
+.section stlhb
+.section stlia
+.section stlib
+.section stlja
+.section stljb
+.section stlka
+.section stlkb
+.section stlla
+.section stllb
+.section stlma
+.section stlmb
+.section stlna
+.section stlnb
+.section stloa
+.section stlob
+.section stlpa
+.section stlpb
+.section stlqa
+.section stlqb
+.section stlra
+.section stlrb
+.section stlsa
+.section stlsb
+.section stlta
+.section stltb
+.section stlua
+.section stlub
+.section stlva
+.section stlvb
+.section stlwa
+.section stlwb
+.section stlxa
+.section stlxb
+.section stlya
+.section stlyb
+.section stlza
+.section stlzb
+.section stl1a
+.section stl1b
+.section stl2a
+.section stl2b
+.section stl3a
+.section stl3b
+.section stl4a
+.section stl4b
+.section stl5a
+.section stl5b
+.section stl6a
+.section stl6b
+.section stl7a
+.section stl7b
+.section stl8a
+.section stl8b
+.section stl9a
+.section stl9b
+.section stl0a
+.section stl0b
+.section stmaa
+.section stmab
+.section stmba
+.section stmbb
+.section stmca
+.section stmcb
+.section stmda
+.section stmdb
+.section stmea
+.section stmeb
+.section stmfa
+.section stmfb
+.section stmga
+.section stmgb
+.section stmha
+.section stmhb
+.section stmia
+.section stmib
+.section stmja
+.section stmjb
+.section stmka
+.section stmkb
+.section stmla
+.section stmlb
+.section stmma
+.section stmmb
+.section stmna
+.section stmnb
+.section stmoa
+.section stmob
+.section stmpa
+.section stmpb
+.section stmqa
+.section stmqb
+.section stmra
+.section stmrb
+.section stmsa
+.section stmsb
+.section stmta
+.section stmtb
+.section stmua
+.section stmub
+.section stmva
+.section stmvb
+.section stmwa
+.section stmwb
+.section stmxa
+.section stmxb
+.section stmya
+.section stmyb
+.section stmza
+.section stmzb
+.section stm1a
+.section stm1b
+.section stm2a
+.section stm2b
+.section stm3a
+.section stm3b
+.section stm4a
+.section stm4b
+.section stm5a
+.section stm5b
+.section stm6a
+.section stm6b
+.section stm7a
+.section stm7b
+.section stm8a
+.section stm8b
+.section stm9a
+.section stm9b
+.section stm0a
+.section stm0b
+.section stnaa
+.section stnab
+.section stnba
+.section stnbb
+.section stnca
+.section stncb
+.section stnda
+.section stndb
+.section stnea
+.section stneb
+.section stnfa
+.section stnfb
+.section stnga
+.section stngb
+.section stnha
+.section stnhb
+.section stnia
+.section stnib
+.section stnja
+.section stnjb
+.section stnka
+.section stnkb
+.section stnla
+.section stnlb
+.section stnma
+.section stnmb
+.section stnna
+.section stnnb
+.section stnoa
+.section stnob
+.section stnpa
+.section stnpb
+.section stnqa
+.section stnqb
+.section stnra
+.section stnrb
+.section stnsa
+.section stnsb
+.section stnta
+.section stntb
+.section stnua
+.section stnub
+.section stnva
+.section stnvb
+.section stnwa
+.section stnwb
+.section stnxa
+.section stnxb
+.section stnya
+.section stnyb
+.section stnza
+.section stnzb
+.section stn1a
+.section stn1b
+.section stn2a
+.section stn2b
+.section stn3a
+.section stn3b
+.section stn4a
+.section stn4b
+.section stn5a
+.section stn5b
+.section stn6a
+.section stn6b
+.section stn7a
+.section stn7b
+.section stn8a
+.section stn8b
+.section stn9a
+.section stn9b
+.section stn0a
+.section stn0b
+.section stoaa
+.section stoab
+.section stoba
+.section stobb
+.section stoca
+.section stocb
+.section stoda
+.section stodb
+.section stoea
+.section stoeb
+.section stofa
+.section stofb
+.section stoga
+.section stogb
+.section stoha
+.section stohb
+.section stoia
+.section stoib
+.section stoja
+.section stojb
+.section stoka
+.section stokb
+.section stola
+.section stolb
+.section stoma
+.section stomb
+.section stona
+.section stonb
+.section stooa
+.section stoob
+.section stopa
+.section stopb
+.section stoqa
+.section stoqb
+.section stora
+.section storb
+.section stosa
+.section stosb
+.section stota
+.section stotb
+.section stoua
+.section stoub
+.section stova
+.section stovb
+.section stowa
+.section stowb
+.section stoxa
+.section stoxb
+.section stoya
+.section stoyb
+.section stoza
+.section stozb
+.section sto1a
+.section sto1b
+.section sto2a
+.section sto2b
+.section sto3a
+.section sto3b
+.section sto4a
+.section sto4b
+.section sto5a
+.section sto5b
+.section sto6a
+.section sto6b
+.section sto7a
+.section sto7b
+.section sto8a
+.section sto8b
+.section sto9a
+.section sto9b
+.section sto0a
+.section sto0b
+.section stpaa
+.section stpab
+.section stpba
+.section stpbb
+.section stpca
+.section stpcb
+.section stpda
+.section stpdb
+.section stpea
+.section stpeb
+.section stpfa
+.section stpfb
+.section stpga
+.section stpgb
+.section stpha
+.section stphb
+.section stpia
+.section stpib
+.section stpja
+.section stpjb
+.section stpka
+.section stpkb
+.section stpla
+.section stplb
+.section stpma
+.section stpmb
+.section stpna
+.section stpnb
+.section stpoa
+.section stpob
+.section stppa
+.section stppb
+.section stpqa
+.section stpqb
+.section stpra
+.section stprb
+.section stpsa
+.section stpsb
+.section stpta
+.section stptb
+.section stpua
+.section stpub
+.section stpva
+.section stpvb
+.section stpwa
+.section stpwb
+.section stpxa
+.section stpxb
+.section stpya
+.section stpyb
+.section stpza
+.section stpzb
+.section stp1a
+.section stp1b
+.section stp2a
+.section stp2b
+.section stp3a
+.section stp3b
+.section stp4a
+.section stp4b
+.section stp5a
+.section stp5b
+.section stp6a
+.section stp6b
+.section stp7a
+.section stp7b
+.section stp8a
+.section stp8b
+.section stp9a
+.section stp9b
+.section stp0a
+.section stp0b
+.section stqaa
+.section stqab
+.section stqba
+.section stqbb
+.section stqca
+.section stqcb
+.section stqda
+.section stqdb
+.section stqea
+.section stqeb
+.section stqfa
+.section stqfb
+.section stqga
+.section stqgb
+.section stqha
+.section stqhb
+.section stqia
+.section stqib
+.section stqja
+.section stqjb
+.section stqka
+.section stqkb
+.section stqla
+.section stqlb
+.section stqma
+.section stqmb
+.section stqna
+.section stqnb
+.section stqoa
+.section stqob
+.section stqpa
+.section stqpb
+.section stqqa
+.section stqqb
+.section stqra
+.section stqrb
+.section stqsa
+.section stqsb
+.section stqta
+.section stqtb
+.section stqua
+.section stqub
+.section stqva
+.section stqvb
+.section stqwa
+.section stqwb
+.section stqxa
+.section stqxb
+.section stqya
+.section stqyb
+.section stqza
+.section stqzb
+.section stq1a
+.section stq1b
+.section stq2a
+.section stq2b
+.section stq3a
+.section stq3b
+.section stq4a
+.section stq4b
+.section stq5a
+.section stq5b
+.section stq6a
+.section stq6b
+.section stq7a
+.section stq7b
+.section stq8a
+.section stq8b
+.section stq9a
+.section stq9b
+.section stq0a
+.section stq0b
+.section straa
+.section strab
+.section strba
+.section strbb
+.section strca
+.section strcb
+.section strda
+.section strdb
+.section strea
+.section streb
+.section strfa
+.section strfb
+.section strga
+.section strgb
+.section strha
+.section strhb
+.section stria
+.section strib
+.section strja
+.section strjb
+.section strka
+.section strkb
+.section strla
+.section strlb
+.section strma
+.section strmb
+.section strna
+.section strnb
+.section stroa
+.section strob
+.section strpa
+.section strpb
+.section strqa
+.section strqb
+.section strra
+.section strrb
+.section strsa
+.section strsb
+.section strta
+.section strtb
+.section strua
+.section strub
+.section strva
+.section strvb
+.section strwa
+.section strwb
+.section strxa
+.section strxb
+.section strya
+.section stryb
+.section strza
+.section strzb
+.section str1a
+.section str1b
+.section str2a
+.section str2b
+.section str3a
+.section str3b
+.section str4a
+.section str4b
+.section str5a
+.section str5b
+.section str6a
+.section str6b
+.section str7a
+.section str7b
+.section str8a
+.section str8b
+.section str9a
+.section str9b
+.section str0a
+.section str0b
+.section stsaa
+.section stsab
+.section stsba
+.section stsbb
+.section stsca
+.section stscb
+.section stsda
+.section stsdb
+.section stsea
+.section stseb
+.section stsfa
+.section stsfb
+.section stsga
+.section stsgb
+.section stsha
+.section stshb
+.section stsia
+.section stsib
+.section stsja
+.section stsjb
+.section stska
+.section stskb
+.section stsla
+.section stslb
+.section stsma
+.section stsmb
+.section stsna
+.section stsnb
+.section stsoa
+.section stsob
+.section stspa
+.section stspb
+.section stsqa
+.section stsqb
+.section stsra
+.section stsrb
+.section stssa
+.section stssb
+.section ststa
+.section ststb
+.section stsua
+.section stsub
+.section stsva
+.section stsvb
+.section stswa
+.section stswb
+.section stsxa
+.section stsxb
+.section stsya
+.section stsyb
+.section stsza
+.section stszb
+.section sts1a
+.section sts1b
+.section sts2a
+.section sts2b
+.section sts3a
+.section sts3b
+.section sts4a
+.section sts4b
+.section sts5a
+.section sts5b
+.section sts6a
+.section sts6b
+.section sts7a
+.section sts7b
+.section sts8a
+.section sts8b
+.section sts9a
+.section sts9b
+.section sts0a
+.section sts0b
+.section sttaa
+.section sttab
+.section sttba
+.section sttbb
+.section sttca
+.section sttcb
+.section sttda
+.section sttdb
+.section sttea
+.section stteb
+.section sttfa
+.section sttfb
+.section sttga
+.section sttgb
+.section sttha
+.section stthb
+.section sttia
+.section sttib
+.section sttja
+.section sttjb
+.section sttka
+.section sttkb
+.section sttla
+.section sttlb
+.section sttma
+.section sttmb
+.section sttna
+.section sttnb
+.section sttoa
+.section sttob
+.section sttpa
+.section sttpb
+.section sttqa
+.section sttqb
+.section sttra
+.section sttrb
+.section sttsa
+.section sttsb
+.section sttta
+.section stttb
+.section sttua
+.section sttub
+.section sttva
+.section sttvb
+.section sttwa
+.section sttwb
+.section sttxa
+.section sttxb
+.section sttya
+.section sttyb
+.section sttza
+.section sttzb
+.section stt1a
+.section stt1b
+.section stt2a
+.section stt2b
+.section stt3a
+.section stt3b
+.section stt4a
+.section stt4b
+.section stt5a
+.section stt5b
+.section stt6a
+.section stt6b
+.section stt7a
+.section stt7b
+.section stt8a
+.section stt8b
+.section stt9a
+.section stt9b
+.section stt0a
+.section stt0b
+.section stuaa
+.section stuab
+.section stuba
+.section stubb
+.section stuca
+.section stucb
+.section studa
+.section studb
+.section stuea
+.section stueb
+.section stufa
+.section stufb
+.section stuga
+.section stugb
+.section stuha
+.section stuhb
+.section stuia
+.section stuib
+.section stuja
+.section stujb
+.section stuka
+.section stukb
+.section stula
+.section stulb
+.section stuma
+.section stumb
+.section stuna
+.section stunb
+.section stuoa
+.section stuob
+.section stupa
+.section stupb
+.section stuqa
+.section stuqb
+.section stura
+.section sturb
+.section stusa
+.section stusb
+.section stuta
+.section stutb
+.section stuua
+.section stuub
+.section stuva
+.section stuvb
+.section stuwa
+.section stuwb
+.section stuxa
+.section stuxb
+.section stuya
+.section stuyb
+.section stuza
+.section stuzb
+.section stu1a
+.section stu1b
+.section stu2a
+.section stu2b
+.section stu3a
+.section stu3b
+.section stu4a
+.section stu4b
+.section stu5a
+.section stu5b
+.section stu6a
+.section stu6b
+.section stu7a
+.section stu7b
+.section stu8a
+.section stu8b
+.section stu9a
+.section stu9b
+.section stu0a
+.section stu0b
+.section stvaa
+.section stvab
+.section stvba
+.section stvbb
+.section stvca
+.section stvcb
+.section stvda
+.section stvdb
+.section stvea
+.section stveb
+.section stvfa
+.section stvfb
+.section stvga
+.section stvgb
+.section stvha
+.section stvhb
+.section stvia
+.section stvib
+.section stvja
+.section stvjb
+.section stvka
+.section stvkb
+.section stvla
+.section stvlb
+.section stvma
+.section stvmb
+.section stvna
+.section stvnb
+.section stvoa
+.section stvob
+.section stvpa
+.section stvpb
+.section stvqa
+.section stvqb
+.section stvra
+.section stvrb
+.section stvsa
+.section stvsb
+.section stvta
+.section stvtb
+.section stvua
+.section stvub
+.section stvva
+.section stvvb
+.section stvwa
+.section stvwb
+.section stvxa
+.section stvxb
+.section stvya
+.section stvyb
+.section stvza
+.section stvzb
+.section stv1a
+.section stv1b
+.section stv2a
+.section stv2b
+.section stv3a
+.section stv3b
+.section stv4a
+.section stv4b
+.section stv5a
+.section stv5b
+.section stv6a
+.section stv6b
+.section stv7a
+.section stv7b
+.section stv8a
+.section stv8b
+.section stv9a
+.section stv9b
+.section stv0a
+.section stv0b
+.section stwaa
+.section stwab
+.section stwba
+.section stwbb
+.section stwca
+.section stwcb
+.section stwda
+.section stwdb
+.section stwea
+.section stweb
+.section stwfa
+.section stwfb
+.section stwga
+.section stwgb
+.section stwha
+.section stwhb
+.section stwia
+.section stwib
+.section stwja
+.section stwjb
+.section stwka
+.section stwkb
+.section stwla
+.section stwlb
+.section stwma
+.section stwmb
+.section stwna
+.section stwnb
+.section stwoa
+.section stwob
+.section stwpa
+.section stwpb
+.section stwqa
+.section stwqb
+.section stwra
+.section stwrb
+.section stwsa
+.section stwsb
+.section stwta
+.section stwtb
+.section stwua
+.section stwub
+.section stwva
+.section stwvb
+.section stwwa
+.section stwwb
+.section stwxa
+.section stwxb
+.section stwya
+.section stwyb
+.section stwza
+.section stwzb
+.section stw1a
+.section stw1b
+.section stw2a
+.section stw2b
+.section stw3a
+.section stw3b
+.section stw4a
+.section stw4b
+.section stw5a
+.section stw5b
+.section stw6a
+.section stw6b
+.section stw7a
+.section stw7b
+.section stw8a
+.section stw8b
+.section stw9a
+.section stw9b
+.section stw0a
+.section stw0b
+.section stxaa
+.section stxab
+.section stxba
+.section stxbb
+.section stxca
+.section stxcb
+.section stxda
+.section stxdb
+.section stxea
+.section stxeb
+.section stxfa
+.section stxfb
+.section stxga
+.section stxgb
+.section stxha
+.section stxhb
+.section stxia
+.section stxib
+.section stxja
+.section stxjb
+.section stxka
+.section stxkb
+.section stxla
+.section stxlb
+.section stxma
+.section stxmb
+.section stxna
+.section stxnb
+.section stxoa
+.section stxob
+.section stxpa
+.section stxpb
+.section stxqa
+.section stxqb
+.section stxra
+.section stxrb
+.section stxsa
+.section stxsb
+.section stxta
+.section stxtb
+.section stxua
+.section stxub
+.section stxva
+.section stxvb
+.section stxwa
+.section stxwb
+.section stxxa
+.section stxxb
+.section stxya
+.section stxyb
+.section stxza
+.section stxzb
+.section stx1a
+.section stx1b
+.section stx2a
+.section stx2b
+.section stx3a
+.section stx3b
+.section stx4a
+.section stx4b
+.section stx5a
+.section stx5b
+.section stx6a
+.section stx6b
+.section stx7a
+.section stx7b
+.section stx8a
+.section stx8b
+.section stx9a
+.section stx9b
+.section stx0a
+.section stx0b
+.section styaa
+.section styab
+.section styba
+.section stybb
+.section styca
+.section stycb
+.section styda
+.section stydb
+.section styea
+.section styeb
+.section styfa
+.section styfb
+.section styga
+.section stygb
+.section styha
+.section styhb
+.section styia
+.section styib
+.section styja
+.section styjb
+.section styka
+.section stykb
+.section styla
+.section stylb
+.section styma
+.section stymb
+.section styna
+.section stynb
+.section styoa
+.section styob
+.section stypa
+.section stypb
+.section styqa
+.section styqb
+.section styra
+.section styrb
+.section stysa
+.section stysb
+.section styta
+.section stytb
+.section styua
+.section styub
+.section styva
+.section styvb
+.section stywa
+.section stywb
+.section styxa
+.section styxb
+.section styya
+.section styyb
+.section styza
+.section styzb
+.section sty1a
+.section sty1b
+.section sty2a
+.section sty2b
+.section sty3a
+.section sty3b
+.section sty4a
+.section sty4b
+.section sty5a
+.section sty5b
+.section sty6a
+.section sty6b
+.section sty7a
+.section sty7b
+.section sty8a
+.section sty8b
+.section sty9a
+.section sty9b
+.section sty0a
+.section sty0b
+.section stzaa
+.section stzab
+.section stzba
+.section stzbb
+.section stzca
+.section stzcb
+.section stzda
+.section stzdb
+.section stzea
+.section stzeb
+.section stzfa
+.section stzfb
+.section stzga
+.section stzgb
+.section stzha
+.section stzhb
+.section stzia
+.section stzib
+.section stzja
+.section stzjb
+.section stzka
+.section stzkb
+.section stzla
+.section stzlb
+.section stzma
+.section stzmb
+.section stzna
+.section stznb
+.section stzoa
+.section stzob
+.section stzpa
+.section stzpb
+.section stzqa
+.section stzqb
+.section stzra
+.section stzrb
+.section stzsa
+.section stzsb
+.section stzta
+.section stztb
+.section stzua
+.section stzub
+.section stzva
+.section stzvb
+.section stzwa
+.section stzwb
+.section stzxa
+.section stzxb
+.section stzya
+.section stzyb
+.section stzza
+.section stzzb
+.section stz1a
+.section stz1b
+.section stz2a
+.section stz2b
+.section stz3a
+.section stz3b
+.section stz4a
+.section stz4b
+.section stz5a
+.section stz5b
+.section stz6a
+.section stz6b
+.section stz7a
+.section stz7b
+.section stz8a
+.section stz8b
+.section stz9a
+.section stz9b
+.section stz0a
+.section stz0b
+.section st1aa
+.section st1ab
+.section st1ba
+.section st1bb
+.section st1ca
+.section st1cb
+.section st1da
+.section st1db
+.section st1ea
+.section st1eb
+.section st1fa
+.section st1fb
+.section st1ga
+.section st1gb
+.section st1ha
+.section st1hb
+.section st1ia
+.section st1ib
+.section st1ja
+.section st1jb
+.section st1ka
+.section st1kb
+.section st1la
+.section st1lb
+.section st1ma
+.section st1mb
+.section st1na
+.section st1nb
+.section st1oa
+.section st1ob
+.section st1pa
+.section st1pb
+.section st1qa
+.section st1qb
+.section st1ra
+.section st1rb
+.section st1sa
+.section st1sb
+.section st1ta
+.section st1tb
+.section st1ua
+.section st1ub
+.section st1va
+.section st1vb
+.section st1wa
+.section st1wb
+.section st1xa
+.section st1xb
+.section st1ya
+.section st1yb
+.section st1za
+.section st1zb
+.section st11a
+.section st11b
+.section st12a
+.section st12b
+.section st13a
+.section st13b
+.section st14a
+.section st14b
+.section st15a
+.section st15b
+.section st16a
+.section st16b
+.section st17a
+.section st17b
+.section st18a
+.section st18b
+.section st19a
+.section st19b
+.section st10a
+.section st10b
+.section st2aa
+.section st2ab
+.section st2ba
+.section st2bb
+.section st2ca
+.section st2cb
+.section st2da
+.section st2db
+.section st2ea
+.section st2eb
+.section st2fa
+.section st2fb
+.section st2ga
+.section st2gb
+.section st2ha
+.section st2hb
+.section st2ia
+.section st2ib
+.section st2ja
+.section st2jb
+.section st2ka
+.section st2kb
+.section st2la
+.section st2lb
+.section st2ma
+.section st2mb
+.section st2na
+.section st2nb
+.section st2oa
+.section st2ob
+.section st2pa
+.section st2pb
+.section st2qa
+.section st2qb
+.section st2ra
+.section st2rb
+.section st2sa
+.section st2sb
+.section st2ta
+.section st2tb
+.section st2ua
+.section st2ub
+.section st2va
+.section st2vb
+.section st2wa
+.section st2wb
+.section st2xa
+.section st2xb
+.section st2ya
+.section st2yb
+.section st2za
+.section st2zb
+.section st21a
+.section st21b
+.section st22a
+.section st22b
+.section st23a
+.section st23b
+.section st24a
+.section st24b
+.section st25a
+.section st25b
+.section st26a
+.section st26b
+.section st27a
+.section st27b
+.section st28a
+.section st28b
+.section st29a
+.section st29b
+.section st20a
+.section st20b
+.section st3aa
+.section st3ab
+.section st3ba
+.section st3bb
+.section st3ca
+.section st3cb
+.section st3da
+.section st3db
+.section st3ea
+.section st3eb
+.section st3fa
+.section st3fb
+.section st3ga
+.section st3gb
+.section st3ha
+.section st3hb
+.section st3ia
+.section st3ib
+.section st3ja
+.section st3jb
+.section st3ka
+.section st3kb
+.section st3la
+.section st3lb
+.section st3ma
+.section st3mb
+.section st3na
+.section st3nb
+.section st3oa
+.section st3ob
+.section st3pa
+.section st3pb
+.section st3qa
+.section st3qb
+.section st3ra
+.section st3rb
+.section st3sa
+.section st3sb
+.section st3ta
+.section st3tb
+.section st3ua
+.section st3ub
+.section st3va
+.section st3vb
+.section st3wa
+.section st3wb
+.section st3xa
+.section st3xb
+.section st3ya
+.section st3yb
+.section st3za
+.section st3zb
+.section st31a
+.section st31b
+.section st32a
+.section st32b
+.section st33a
+.section st33b
+.section st34a
+.section st34b
+.section st35a
+.section st35b
+.section st36a
+.section st36b
+.section st37a
+.section st37b
+.section st38a
+.section st38b
+.section st39a
+.section st39b
+.section st30a
+.section st30b
+.section st4aa
+.section st4ab
+.section st4ba
+.section st4bb
+.section st4ca
+.section st4cb
+.section st4da
+.section st4db
+.section st4ea
+.section st4eb
+.section st4fa
+.section st4fb
+.section st4ga
+.section st4gb
+.section st4ha
+.section st4hb
+.section st4ia
+.section st4ib
+.section st4ja
+.section st4jb
+.section st4ka
+.section st4kb
+.section st4la
+.section st4lb
+.section st4ma
+.section st4mb
+.section st4na
+.section st4nb
+.section st4oa
+.section st4ob
+.section st4pa
+.section st4pb
+.section st4qa
+.section st4qb
+.section st4ra
+.section st4rb
+.section st4sa
+.section st4sb
+.section st4ta
+.section st4tb
+.section st4ua
+.section st4ub
+.section st4va
+.section st4vb
+.section st4wa
+.section st4wb
+.section st4xa
+.section st4xb
+.section st4ya
+.section st4yb
+.section st4za
+.section st4zb
+.section st41a
+.section st41b
+.section st42a
+.section st42b
+.section st43a
+.section st43b
+.section st44a
+.section st44b
+.section st45a
+.section st45b
+.section st46a
+.section st46b
+.section st47a
+.section st47b
+.section st48a
+.section st48b
+.section st49a
+.section st49b
+.section st40a
+.section st40b
+.section st5aa
+.section st5ab
+.section st5ba
+.section st5bb
+.section st5ca
+.section st5cb
+.section st5da
+.section st5db
+.section st5ea
+.section st5eb
+.section st5fa
+.section st5fb
+.section st5ga
+.section st5gb
+.section st5ha
+.section st5hb
+.section st5ia
+.section st5ib
+.section st5ja
+.section st5jb
+.section st5ka
+.section st5kb
+.section st5la
+.section st5lb
+.section st5ma
+.section st5mb
+.section st5na
+.section st5nb
+.section st5oa
+.section st5ob
+.section st5pa
+.section st5pb
+.section st5qa
+.section st5qb
+.section st5ra
+.section st5rb
+.section st5sa
+.section st5sb
+.section st5ta
+.section st5tb
+.section st5ua
+.section st5ub
+.section st5va
+.section st5vb
+.section st5wa
+.section st5wb
+.section st5xa
+.section st5xb
+.section st5ya
+.section st5yb
+.section st5za
+.section st5zb
+.section st51a
+.section st51b
+.section st52a
+.section st52b
+.section st53a
+.section st53b
+.section st54a
+.section st54b
+.section st55a
+.section st55b
+.section st56a
+.section st56b
+.section st57a
+.section st57b
+.section st58a
+.section st58b
+.section st59a
+.section st59b
+.section st50a
+.section st50b
+.section st6aa
+.section st6ab
+.section st6ba
+.section st6bb
+.section st6ca
+.section st6cb
+.section st6da
+.section st6db
+.section st6ea
+.section st6eb
+.section st6fa
+.section st6fb
+.section st6ga
+.section st6gb
+.section st6ha
+.section st6hb
+.section st6ia
+.section st6ib
+.section st6ja
+.section st6jb
+.section st6ka
+.section st6kb
+.section st6la
+.section st6lb
+.section st6ma
+.section st6mb
+.section st6na
+.section st6nb
+.section st6oa
+.section st6ob
+.section st6pa
+.section st6pb
+.section st6qa
+.section st6qb
+.section st6ra
+.section st6rb
+.section st6sa
+.section st6sb
+.section st6ta
+.section st6tb
+.section st6ua
+.section st6ub
+.section st6va
+.section st6vb
+.section st6wa
+.section st6wb
+.section st6xa
+.section st6xb
+.section st6ya
+.section st6yb
+.section st6za
+.section st6zb
+.section st61a
+.section st61b
+.section st62a
+.section st62b
+.section st63a
+.section st63b
+.section st64a
+.section st64b
+.section st65a
+.section st65b
+.section st66a
+.section st66b
+.section st67a
+.section st67b
+.section st68a
+.section st68b
+.section st69a
+.section st69b
+.section st60a
+.section st60b
+.section st7aa
+.section st7ab
+.section st7ba
+.section st7bb
+.section st7ca
+.section st7cb
+.section st7da
+.section st7db
+.section st7ea
+.section st7eb
+.section st7fa
+.section st7fb
+.section st7ga
+.section st7gb
+.section st7ha
+.section st7hb
+.section st7ia
+.section st7ib
+.section st7ja
+.section st7jb
+.section st7ka
+.section st7kb
+.section st7la
+.section st7lb
+.section st7ma
+.section st7mb
+.section st7na
+.section st7nb
+.section st7oa
+.section st7ob
+.section st7pa
+.section st7pb
+.section st7qa
+.section st7qb
+.section st7ra
+.section st7rb
+.section st7sa
+.section st7sb
+.section st7ta
+.section st7tb
+.section st7ua
+.section st7ub
+.section st7va
+.section st7vb
+.section st7wa
+.section st7wb
+.section st7xa
+.section st7xb
+.section st7ya
+.section st7yb
+.section st7za
+.section st7zb
+.section st71a
+.section st71b
+.section st72a
+.section st72b
+.section st73a
+.section st73b
+.section st74a
+.section st74b
+.section st75a
+.section st75b
+.section st76a
+.section st76b
+.section st77a
+.section st77b
+.section st78a
+.section st78b
+.section st79a
+.section st79b
+.section st70a
+.section st70b
+.section st8aa
+.section st8ab
+.section st8ba
+.section st8bb
+.section st8ca
+.section st8cb
+.section st8da
+.section st8db
+.section st8ea
+.section st8eb
+.section st8fa
+.section st8fb
+.section st8ga
+.section st8gb
+.section st8ha
+.section st8hb
+.section st8ia
+.section st8ib
+.section st8ja
+.section st8jb
+.section st8ka
+.section st8kb
+.section st8la
+.section st8lb
+.section st8ma
+.section st8mb
+.section st8na
+.section st8nb
+.section st8oa
+.section st8ob
+.section st8pa
+.section st8pb
+.section st8qa
+.section st8qb
+.section st8ra
+.section st8rb
+.section st8sa
+.section st8sb
+.section st8ta
+.section st8tb
+.section st8ua
+.section st8ub
+.section st8va
+.section st8vb
+.section st8wa
+.section st8wb
+.section st8xa
+.section st8xb
+.section st8ya
+.section st8yb
+.section st8za
+.section st8zb
+.section st81a
+.section st81b
+.section st82a
+.section st82b
+.section st83a
+.section st83b
+.section st84a
+.section st84b
+.section st85a
+.section st85b
+.section st86a
+.section st86b
+.section st87a
+.section st87b
+.section st88a
+.section st88b
+.section st89a
+.section st89b
+.section st80a
+.section st80b
+.section st9aa
+.section st9ab
+.section st9ba
+.section st9bb
+.section st9ca
+.section st9cb
+.section st9da
+.section st9db
+.section st9ea
+.section st9eb
+.section st9fa
+.section st9fb
+.section st9ga
+.section st9gb
+.section st9ha
+.section st9hb
+.section st9ia
+.section st9ib
+.section st9ja
+.section st9jb
+.section st9ka
+.section st9kb
+.section st9la
+.section st9lb
+.section st9ma
+.section st9mb
+.section st9na
+.section st9nb
+.section st9oa
+.section st9ob
+.section st9pa
+.section st9pb
+.section st9qa
+.section st9qb
+.section st9ra
+.section st9rb
+.section st9sa
+.section st9sb
+.section st9ta
+.section st9tb
+.section st9ua
+.section st9ub
+.section st9va
+.section st9vb
+.section st9wa
+.section st9wb
+.section st9xa
+.section st9xb
+.section st9ya
+.section st9yb
+.section st9za
+.section st9zb
+.section st91a
+.section st91b
+.section st92a
+.section st92b
+.section st93a
+.section st93b
+.section st94a
+.section st94b
+.section st95a
+.section st95b
+.section st96a
+.section st96b
+.section st97a
+.section st97b
+.section st98a
+.section st98b
+.section st99a
+.section st99b
+.section st90a
+.section st90b
+.section st0aa
+.section st0ab
+.section st0ba
+.section st0bb
+.section st0ca
+.section st0cb
+.section st0da
+.section st0db
+.section st0ea
+.section st0eb
+.section st0fa
+.section st0fb
+.section st0ga
+.section st0gb
+.section st0ha
+.section st0hb
+.section st0ia
+.section st0ib
+.section st0ja
+.section st0jb
+.section st0ka
+.section st0kb
+.section st0la
+.section st0lb
+.section st0ma
+.section st0mb
+.section st0na
+.section st0nb
+.section st0oa
+.section st0ob
+.section st0pa
+.section st0pb
+.section st0qa
+.section st0qb
+.section st0ra
+.section st0rb
+.section st0sa
+.section st0sb
+.section st0ta
+.section st0tb
+.section st0ua
+.section st0ub
+.section st0va
+.section st0vb
+.section st0wa
+.section st0wb
+.section st0xa
+.section st0xb
+.section st0ya
+.section st0yb
+.section st0za
+.section st0zb
+.section st01a
+.section st01b
+.section st02a
+.section st02b
+.section st03a
+.section st03b
+.section st04a
+.section st04b
+.section st05a
+.section st05b
+.section st06a
+.section st06b
+.section st07a
+.section st07b
+.section st08a
+.section st08b
+.section st09a
+.section st09b
+.section st00a
+.section st00b
+.section suaaa
+.section suaab
+.section suaba
+.section suabb
+.section suaca
+.section suacb
+.section suada
+.section suadb
+.section suaea
+.section suaeb
+.section suafa
+.section suafb
+.section suaga
+.section suagb
+.section suaha
+.section suahb
+.section suaia
+.section suaib
+.section suaja
+.section suajb
+.section suaka
+.section suakb
+.section suala
+.section sualb
+.section suama
+.section suamb
+.section suana
+.section suanb
+.section suaoa
+.section suaob
+.section suapa
+.section suapb
+.section suaqa
+.section suaqb
+.section suara
+.section suarb
+.section suasa
+.section suasb
+.section suata
+.section suatb
+.section suaua
+.section suaub
+.section suava
+.section suavb
+.section suawa
+.section suawb
+.section suaxa
+.section suaxb
+.section suaya
+.section suayb
+.section suaza
+.section suazb
+.section sua1a
+.section sua1b
+.section sua2a
+.section sua2b
+.section sua3a
+.section sua3b
+.section sua4a
+.section sua4b
+.section sua5a
+.section sua5b
+.section sua6a
+.section sua6b
+.section sua7a
+.section sua7b
+.section sua8a
+.section sua8b
+.section sua9a
+.section sua9b
+.section sua0a
+.section sua0b
+.section subaa
+.section subab
+.section subba
+.section subbb
+.section subca
+.section subcb
+.section subda
+.section subdb
+.section subea
+.section subeb
+.section subfa
+.section subfb
+.section subga
+.section subgb
+.section subha
+.section subhb
+.section subia
+.section subib
+.section subja
+.section subjb
+.section subka
+.section subkb
+.section subla
+.section sublb
+.section subma
+.section submb
+.section subna
+.section subnb
+.section suboa
+.section subob
+.section subpa
+.section subpb
+.section subqa
+.section subqb
+.section subra
+.section subrb
+.section subsa
+.section subsb
+.section subta
+.section subtb
+.section subua
+.section subub
+.section subva
+.section subvb
+.section subwa
+.section subwb
+.section subxa
+.section subxb
+.section subya
+.section subyb
+.section subza
+.section subzb
+.section sub1a
+.section sub1b
+.section sub2a
+.section sub2b
+.section sub3a
+.section sub3b
+.section sub4a
+.section sub4b
+.section sub5a
+.section sub5b
+.section sub6a
+.section sub6b
+.section sub7a
+.section sub7b
+.section sub8a
+.section sub8b
+.section sub9a
+.section sub9b
+.section sub0a
+.section sub0b
+.section sucaa
+.section sucab
+.section sucba
+.section sucbb
+.section succa
+.section succb
+.section sucda
+.section sucdb
+.section sucea
+.section suceb
+.section sucfa
+.section sucfb
+.section sucga
+.section sucgb
+.section sucha
+.section suchb
+.section sucia
+.section sucib
+.section sucja
+.section sucjb
+.section sucka
+.section suckb
+.section sucla
+.section suclb
+.section sucma
+.section sucmb
+.section sucna
+.section sucnb
+.section sucoa
+.section sucob
+.section sucpa
+.section sucpb
+.section sucqa
+.section sucqb
+.section sucra
+.section sucrb
+.section sucsa
+.section sucsb
+.section sucta
+.section suctb
+.section sucua
+.section sucub
+.section sucva
+.section sucvb
+.section sucwa
+.section sucwb
+.section sucxa
+.section sucxb
+.section sucya
+.section sucyb
+.section sucza
+.section suczb
+.section suc1a
+.section suc1b
+.section suc2a
+.section suc2b
+.section suc3a
+.section suc3b
+.section suc4a
+.section suc4b
+.section suc5a
+.section suc5b
+.section suc6a
+.section suc6b
+.section suc7a
+.section suc7b
+.section suc8a
+.section suc8b
+.section suc9a
+.section suc9b
+.section suc0a
+.section suc0b
+.section sudaa
+.section sudab
+.section sudba
+.section sudbb
+.section sudca
+.section sudcb
+.section sudda
+.section suddb
+.section sudea
+.section sudeb
+.section sudfa
+.section sudfb
+.section sudga
+.section sudgb
+.section sudha
+.section sudhb
+.section sudia
+.section sudib
+.section sudja
+.section sudjb
+.section sudka
+.section sudkb
+.section sudla
+.section sudlb
+.section sudma
+.section sudmb
+.section sudna
+.section sudnb
+.section sudoa
+.section sudob
+.section sudpa
+.section sudpb
+.section sudqa
+.section sudqb
+.section sudra
+.section sudrb
+.section sudsa
+.section sudsb
+.section sudta
+.section sudtb
+.section sudua
+.section sudub
+.section sudva
+.section sudvb
+.section sudwa
+.section sudwb
+.section sudxa
+.section sudxb
+.section sudya
+.section sudyb
+.section sudza
+.section sudzb
+.section sud1a
+.section sud1b
+.section sud2a
+.section sud2b
+.section sud3a
+.section sud3b
+.section sud4a
+.section sud4b
+.section sud5a
+.section sud5b
+.section sud6a
+.section sud6b
+.section sud7a
+.section sud7b
+.section sud8a
+.section sud8b
+.section sud9a
+.section sud9b
+.section sud0a
+.section sud0b
+.section sueaa
+.section sueab
+.section sueba
+.section suebb
+.section sueca
+.section suecb
+.section sueda
+.section suedb
+.section sueea
+.section sueeb
+.section suefa
+.section suefb
+.section suega
+.section suegb
+.section sueha
+.section suehb
+.section sueia
+.section sueib
+.section sueja
+.section suejb
+.section sueka
+.section suekb
+.section suela
+.section suelb
+.section suema
+.section suemb
+.section suena
+.section suenb
+.section sueoa
+.section sueob
+.section suepa
+.section suepb
+.section sueqa
+.section sueqb
+.section suera
+.section suerb
+.section suesa
+.section suesb
+.section sueta
+.section suetb
+.section sueua
+.section sueub
+.section sueva
+.section suevb
+.section suewa
+.section suewb
+.section suexa
+.section suexb
+.section sueya
+.section sueyb
+.section sueza
+.section suezb
+.section sue1a
+.section sue1b
+.section sue2a
+.section sue2b
+.section sue3a
+.section sue3b
+.section sue4a
+.section sue4b
+.section sue5a
+.section sue5b
+.section sue6a
+.section sue6b
+.section sue7a
+.section sue7b
+.section sue8a
+.section sue8b
+.section sue9a
+.section sue9b
+.section sue0a
+.section sue0b
+.section sufaa
+.section sufab
+.section sufba
+.section sufbb
+.section sufca
+.section sufcb
+.section sufda
+.section sufdb
+.section sufea
+.section sufeb
+.section suffa
+.section suffb
+.section sufga
+.section sufgb
+.section sufha
+.section sufhb
+.section sufia
+.section sufib
+.section sufja
+.section sufjb
+.section sufka
+.section sufkb
+.section sufla
+.section suflb
+.section sufma
+.section sufmb
+.section sufna
+.section sufnb
+.section sufoa
+.section sufob
+.section sufpa
+.section sufpb
+.section sufqa
+.section sufqb
+.section sufra
+.section sufrb
+.section sufsa
+.section sufsb
+.section sufta
+.section suftb
+.section sufua
+.section sufub
+.section sufva
+.section sufvb
+.section sufwa
+.section sufwb
+.section sufxa
+.section sufxb
+.section sufya
+.section sufyb
+.section sufza
+.section sufzb
+.section suf1a
+.section suf1b
+.section suf2a
+.section suf2b
+.section suf3a
+.section suf3b
+.section suf4a
+.section suf4b
+.section suf5a
+.section suf5b
+.section suf6a
+.section suf6b
+.section suf7a
+.section suf7b
+.section suf8a
+.section suf8b
+.section suf9a
+.section suf9b
+.section suf0a
+.section suf0b
+.section sugaa
+.section sugab
+.section sugba
+.section sugbb
+.section sugca
+.section sugcb
+.section sugda
+.section sugdb
+.section sugea
+.section sugeb
+.section sugfa
+.section sugfb
+.section sugga
+.section suggb
+.section sugha
+.section sughb
+.section sugia
+.section sugib
+.section sugja
+.section sugjb
+.section sugka
+.section sugkb
+.section sugla
+.section suglb
+.section sugma
+.section sugmb
+.section sugna
+.section sugnb
+.section sugoa
+.section sugob
+.section sugpa
+.section sugpb
+.section sugqa
+.section sugqb
+.section sugra
+.section sugrb
+.section sugsa
+.section sugsb
+.section sugta
+.section sugtb
+.section sugua
+.section sugub
+.section sugva
+.section sugvb
+.section sugwa
+.section sugwb
+.section sugxa
+.section sugxb
+.section sugya
+.section sugyb
+.section sugza
+.section sugzb
+.section sug1a
+.section sug1b
+.section sug2a
+.section sug2b
+.section sug3a
+.section sug3b
+.section sug4a
+.section sug4b
+.section sug5a
+.section sug5b
+.section sug6a
+.section sug6b
+.section sug7a
+.section sug7b
+.section sug8a
+.section sug8b
+.section sug9a
+.section sug9b
+.section sug0a
+.section sug0b
+.section suhaa
+.section suhab
+.section suhba
+.section suhbb
+.section suhca
+.section suhcb
+.section suhda
+.section suhdb
+.section suhea
+.section suheb
+.section suhfa
+.section suhfb
+.section suhga
+.section suhgb
+.section suhha
+.section suhhb
+.section suhia
+.section suhib
+.section suhja
+.section suhjb
+.section suhka
+.section suhkb
+.section suhla
+.section suhlb
+.section suhma
+.section suhmb
+.section suhna
+.section suhnb
+.section suhoa
+.section suhob
+.section suhpa
+.section suhpb
+.section suhqa
+.section suhqb
+.section suhra
+.section suhrb
+.section suhsa
+.section suhsb
+.section suhta
+.section suhtb
+.section suhua
+.section suhub
+.section suhva
+.section suhvb
+.section suhwa
+.section suhwb
+.section suhxa
+.section suhxb
+.section suhya
+.section suhyb
+.section suhza
+.section suhzb
+.section suh1a
+.section suh1b
+.section suh2a
+.section suh2b
+.section suh3a
+.section suh3b
+.section suh4a
+.section suh4b
+.section suh5a
+.section suh5b
+.section suh6a
+.section suh6b
+.section suh7a
+.section suh7b
+.section suh8a
+.section suh8b
+.section suh9a
+.section suh9b
+.section suh0a
+.section suh0b
+.section suiaa
+.section suiab
+.section suiba
+.section suibb
+.section suica
+.section suicb
+.section suida
+.section suidb
+.section suiea
+.section suieb
+.section suifa
+.section suifb
+.section suiga
+.section suigb
+.section suiha
+.section suihb
+.section suiia
+.section suiib
+.section suija
+.section suijb
+.section suika
+.section suikb
+.section suila
+.section suilb
+.section suima
+.section suimb
+.section suina
+.section suinb
+.section suioa
+.section suiob
+.section suipa
+.section suipb
+.section suiqa
+.section suiqb
+.section suira
+.section suirb
+.section suisa
+.section suisb
+.section suita
+.section suitb
+.section suiua
+.section suiub
+.section suiva
+.section suivb
+.section suiwa
+.section suiwb
+.section suixa
+.section suixb
+.section suiya
+.section suiyb
+.section suiza
+.section suizb
+.section sui1a
+.section sui1b
+.section sui2a
+.section sui2b
+.section sui3a
+.section sui3b
+.section sui4a
+.section sui4b
+.section sui5a
+.section sui5b
+.section sui6a
+.section sui6b
+.section sui7a
+.section sui7b
+.section sui8a
+.section sui8b
+.section sui9a
+.section sui9b
+.section sui0a
+.section sui0b
+.section sujaa
+.section sujab
+.section sujba
+.section sujbb
+.section sujca
+.section sujcb
+.section sujda
+.section sujdb
+.section sujea
+.section sujeb
+.section sujfa
+.section sujfb
+.section sujga
+.section sujgb
+.section sujha
+.section sujhb
+.section sujia
+.section sujib
+.section sujja
+.section sujjb
+.section sujka
+.section sujkb
+.section sujla
+.section sujlb
+.section sujma
+.section sujmb
+.section sujna
+.section sujnb
+.section sujoa
+.section sujob
+.section sujpa
+.section sujpb
+.section sujqa
+.section sujqb
+.section sujra
+.section sujrb
+.section sujsa
+.section sujsb
+.section sujta
+.section sujtb
+.section sujua
+.section sujub
+.section sujva
+.section sujvb
+.section sujwa
+.section sujwb
+.section sujxa
+.section sujxb
+.section sujya
+.section sujyb
+.section sujza
+.section sujzb
+.section suj1a
+.section suj1b
+.section suj2a
+.section suj2b
+.section suj3a
+.section suj3b
+.section suj4a
+.section suj4b
+.section suj5a
+.section suj5b
+.section suj6a
+.section suj6b
+.section suj7a
+.section suj7b
+.section suj8a
+.section suj8b
+.section suj9a
+.section suj9b
+.section suj0a
+.section suj0b
+.section sukaa
+.section sukab
+.section sukba
+.section sukbb
+.section sukca
+.section sukcb
+.section sukda
+.section sukdb
+.section sukea
+.section sukeb
+.section sukfa
+.section sukfb
+.section sukga
+.section sukgb
+.section sukha
+.section sukhb
+.section sukia
+.section sukib
+.section sukja
+.section sukjb
+.section sukka
+.section sukkb
+.section sukla
+.section suklb
+.section sukma
+.section sukmb
+.section sukna
+.section suknb
+.section sukoa
+.section sukob
+.section sukpa
+.section sukpb
+.section sukqa
+.section sukqb
+.section sukra
+.section sukrb
+.section suksa
+.section suksb
+.section sukta
+.section suktb
+.section sukua
+.section sukub
+.section sukva
+.section sukvb
+.section sukwa
+.section sukwb
+.section sukxa
+.section sukxb
+.section sukya
+.section sukyb
+.section sukza
+.section sukzb
+.section suk1a
+.section suk1b
+.section suk2a
+.section suk2b
+.section suk3a
+.section suk3b
+.section suk4a
+.section suk4b
+.section suk5a
+.section suk5b
+.section suk6a
+.section suk6b
+.section suk7a
+.section suk7b
+.section suk8a
+.section suk8b
+.section suk9a
+.section suk9b
+.section suk0a
+.section suk0b
+.section sulaa
+.section sulab
+.section sulba
+.section sulbb
+.section sulca
+.section sulcb
+.section sulda
+.section suldb
+.section sulea
+.section suleb
+.section sulfa
+.section sulfb
+.section sulga
+.section sulgb
+.section sulha
+.section sulhb
+.section sulia
+.section sulib
+.section sulja
+.section suljb
+.section sulka
+.section sulkb
+.section sulla
+.section sullb
+.section sulma
+.section sulmb
+.section sulna
+.section sulnb
+.section suloa
+.section sulob
+.section sulpa
+.section sulpb
+.section sulqa
+.section sulqb
+.section sulra
+.section sulrb
+.section sulsa
+.section sulsb
+.section sulta
+.section sultb
+.section sulua
+.section sulub
+.section sulva
+.section sulvb
+.section sulwa
+.section sulwb
+.section sulxa
+.section sulxb
+.section sulya
+.section sulyb
+.section sulza
+.section sulzb
+.section sul1a
+.section sul1b
+.section sul2a
+.section sul2b
+.section sul3a
+.section sul3b
+.section sul4a
+.section sul4b
+.section sul5a
+.section sul5b
+.section sul6a
+.section sul6b
+.section sul7a
+.section sul7b
+.section sul8a
+.section sul8b
+.section sul9a
+.section sul9b
+.section sul0a
+.section sul0b
+.section sumaa
+.section sumab
+.section sumba
+.section sumbb
+.section sumca
+.section sumcb
+.section sumda
+.section sumdb
+.section sumea
+.section sumeb
+.section sumfa
+.section sumfb
+.section sumga
+.section sumgb
+.section sumha
+.section sumhb
+.section sumia
+.section sumib
+.section sumja
+.section sumjb
+.section sumka
+.section sumkb
+.section sumla
+.section sumlb
+.section summa
+.section summb
+.section sumna
+.section sumnb
+.section sumoa
+.section sumob
+.section sumpa
+.section sumpb
+.section sumqa
+.section sumqb
+.section sumra
+.section sumrb
+.section sumsa
+.section sumsb
+.section sumta
+.section sumtb
+.section sumua
+.section sumub
+.section sumva
+.section sumvb
+.section sumwa
+.section sumwb
+.section sumxa
+.section sumxb
+.section sumya
+.section sumyb
+.section sumza
+.section sumzb
+.section sum1a
+.section sum1b
+.section sum2a
+.section sum2b
+.section sum3a
+.section sum3b
+.section sum4a
+.section sum4b
+.section sum5a
+.section sum5b
+.section sum6a
+.section sum6b
+.section sum7a
+.section sum7b
+.section sum8a
+.section sum8b
+.section sum9a
+.section sum9b
+.section sum0a
+.section sum0b
+.section sunaa
+.section sunab
+.section sunba
+.section sunbb
+.section sunca
+.section suncb
+.section sunda
+.section sundb
+.section sunea
+.section suneb
+.section sunfa
+.section sunfb
+.section sunga
+.section sungb
+.section sunha
+.section sunhb
+.section sunia
+.section sunib
+.section sunja
+.section sunjb
+.section sunka
+.section sunkb
+.section sunla
+.section sunlb
+.section sunma
+.section sunmb
+.section sunna
+.section sunnb
+.section sunoa
+.section sunob
+.section sunpa
+.section sunpb
+.section sunqa
+.section sunqb
+.section sunra
+.section sunrb
+.section sunsa
+.section sunsb
+.section sunta
+.section suntb
+.section sunua
+.section sunub
+.section sunva
+.section sunvb
+.section sunwa
+.section sunwb
+.section sunxa
+.section sunxb
+.section sunya
+.section sunyb
+.section sunza
+.section sunzb
+.section sun1a
+.section sun1b
+.section sun2a
+.section sun2b
+.section sun3a
+.section sun3b
+.section sun4a
+.section sun4b
+.section sun5a
+.section sun5b
+.section sun6a
+.section sun6b
+.section sun7a
+.section sun7b
+.section sun8a
+.section sun8b
+.section sun9a
+.section sun9b
+.section sun0a
+.section sun0b
+.section suoaa
+.section suoab
+.section suoba
+.section suobb
+.section suoca
+.section suocb
+.section suoda
+.section suodb
+.section suoea
+.section suoeb
+.section suofa
+.section suofb
+.section suoga
+.section suogb
+.section suoha
+.section suohb
+.section suoia
+.section suoib
+.section suoja
+.section suojb
+.section suoka
+.section suokb
+.section suola
+.section suolb
+.section suoma
+.section suomb
+.section suona
+.section suonb
+.section suooa
+.section suoob
+.section suopa
+.section suopb
+.section suoqa
+.section suoqb
+.section suora
+.section suorb
+.section suosa
+.section suosb
+.section suota
+.section suotb
+.section suoua
+.section suoub
+.section suova
+.section suovb
+.section suowa
+.section suowb
+.section suoxa
+.section suoxb
+.section suoya
+.section suoyb
+.section suoza
+.section suozb
+.section suo1a
+.section suo1b
+.section suo2a
+.section suo2b
+.section suo3a
+.section suo3b
+.section suo4a
+.section suo4b
+.section suo5a
+.section suo5b
+.section suo6a
+.section suo6b
+.section suo7a
+.section suo7b
+.section suo8a
+.section suo8b
+.section suo9a
+.section suo9b
+.section suo0a
+.section suo0b
+.section supaa
+.section supab
+.section supba
+.section supbb
+.section supca
+.section supcb
+.section supda
+.section supdb
+.section supea
+.section supeb
+.section supfa
+.section supfb
+.section supga
+.section supgb
+.section supha
+.section suphb
+.section supia
+.section supib
+.section supja
+.section supjb
+.section supka
+.section supkb
+.section supla
+.section suplb
+.section supma
+.section supmb
+.section supna
+.section supnb
+.section supoa
+.section supob
+.section suppa
+.section suppb
+.section supqa
+.section supqb
+.section supra
+.section suprb
+.section supsa
+.section supsb
+.section supta
+.section suptb
+.section supua
+.section supub
+.section supva
+.section supvb
+.section supwa
+.section supwb
+.section supxa
+.section supxb
+.section supya
+.section supyb
+.section supza
+.section supzb
+.section sup1a
+.section sup1b
+.section sup2a
+.section sup2b
+.section sup3a
+.section sup3b
+.section sup4a
+.section sup4b
+.section sup5a
+.section sup5b
+.section sup6a
+.section sup6b
+.section sup7a
+.section sup7b
+.section sup8a
+.section sup8b
+.section sup9a
+.section sup9b
+.section sup0a
+.section sup0b
+.section suqaa
+.section suqab
+.section suqba
+.section suqbb
+.section suqca
+.section suqcb
+.section suqda
+.section suqdb
+.section suqea
+.section suqeb
+.section suqfa
+.section suqfb
+.section suqga
+.section suqgb
+.section suqha
+.section suqhb
+.section suqia
+.section suqib
+.section suqja
+.section suqjb
+.section suqka
+.section suqkb
+.section suqla
+.section suqlb
+.section suqma
+.section suqmb
+.section suqna
+.section suqnb
+.section suqoa
+.section suqob
+.section suqpa
+.section suqpb
+.section suqqa
+.section suqqb
+.section suqra
+.section suqrb
+.section suqsa
+.section suqsb
+.section suqta
+.section suqtb
+.section suqua
+.section suqub
+.section suqva
+.section suqvb
+.section suqwa
+.section suqwb
+.section suqxa
+.section suqxb
+.section suqya
+.section suqyb
+.section suqza
+.section suqzb
+.section suq1a
+.section suq1b
+.section suq2a
+.section suq2b
+.section suq3a
+.section suq3b
+.section suq4a
+.section suq4b
+.section suq5a
+.section suq5b
+.section suq6a
+.section suq6b
+.section suq7a
+.section suq7b
+.section suq8a
+.section suq8b
+.section suq9a
+.section suq9b
+.section suq0a
+.section suq0b
+.section suraa
+.section surab
+.section surba
+.section surbb
+.section surca
+.section surcb
+.section surda
+.section surdb
+.section surea
+.section sureb
+.section surfa
+.section surfb
+.section surga
+.section surgb
+.section surha
+.section surhb
+.section suria
+.section surib
+.section surja
+.section surjb
+.section surka
+.section surkb
+.section surla
+.section surlb
+.section surma
+.section surmb
+.section surna
+.section surnb
+.section suroa
+.section surob
+.section surpa
+.section surpb
+.section surqa
+.section surqb
+.section surra
+.section surrb
+.section sursa
+.section sursb
+.section surta
+.section surtb
+.section surua
+.section surub
+.section surva
+.section survb
+.section surwa
+.section surwb
+.section surxa
+.section surxb
+.section surya
+.section suryb
+.section surza
+.section surzb
+.section sur1a
+.section sur1b
+.section sur2a
+.section sur2b
+.section sur3a
+.section sur3b
+.section sur4a
+.section sur4b
+.section sur5a
+.section sur5b
+.section sur6a
+.section sur6b
+.section sur7a
+.section sur7b
+.section sur8a
+.section sur8b
+.section sur9a
+.section sur9b
+.section sur0a
+.section sur0b
+.section susaa
+.section susab
+.section susba
+.section susbb
+.section susca
+.section suscb
+.section susda
+.section susdb
+.section susea
+.section suseb
+.section susfa
+.section susfb
+.section susga
+.section susgb
+.section susha
+.section sushb
+.section susia
+.section susib
+.section susja
+.section susjb
+.section suska
+.section suskb
+.section susla
+.section suslb
+.section susma
+.section susmb
+.section susna
+.section susnb
+.section susoa
+.section susob
+.section suspa
+.section suspb
+.section susqa
+.section susqb
+.section susra
+.section susrb
+.section sussa
+.section sussb
+.section susta
+.section sustb
+.section susua
+.section susub
+.section susva
+.section susvb
+.section suswa
+.section suswb
+.section susxa
+.section susxb
+.section susya
+.section susyb
+.section susza
+.section suszb
+.section sus1a
+.section sus1b
+.section sus2a
+.section sus2b
+.section sus3a
+.section sus3b
+.section sus4a
+.section sus4b
+.section sus5a
+.section sus5b
+.section sus6a
+.section sus6b
+.section sus7a
+.section sus7b
+.section sus8a
+.section sus8b
+.section sus9a
+.section sus9b
+.section sus0a
+.section sus0b
+.section sutaa
+.section sutab
+.section sutba
+.section sutbb
+.section sutca
+.section sutcb
+.section sutda
+.section sutdb
+.section sutea
+.section suteb
+.section sutfa
+.section sutfb
+.section sutga
+.section sutgb
+.section sutha
+.section suthb
+.section sutia
+.section sutib
+.section sutja
+.section sutjb
+.section sutka
+.section sutkb
+.section sutla
+.section sutlb
+.section sutma
+.section sutmb
+.section sutna
+.section sutnb
+.section sutoa
+.section sutob
+.section sutpa
+.section sutpb
+.section sutqa
+.section sutqb
+.section sutra
+.section sutrb
+.section sutsa
+.section sutsb
+.section sutta
+.section suttb
+.section sutua
+.section sutub
+.section sutva
+.section sutvb
+.section sutwa
+.section sutwb
+.section sutxa
+.section sutxb
+.section sutya
+.section sutyb
+.section sutza
+.section sutzb
+.section sut1a
+.section sut1b
+.section sut2a
+.section sut2b
+.section sut3a
+.section sut3b
+.section sut4a
+.section sut4b
+.section sut5a
+.section sut5b
+.section sut6a
+.section sut6b
+.section sut7a
+.section sut7b
+.section sut8a
+.section sut8b
+.section sut9a
+.section sut9b
+.section sut0a
+.section sut0b
+.section suuaa
+.section suuab
+.section suuba
+.section suubb
+.section suuca
+.section suucb
+.section suuda
+.section suudb
+.section suuea
+.section suueb
+.section suufa
+.section suufb
+.section suuga
+.section suugb
+.section suuha
+.section suuhb
+.section suuia
+.section suuib
+.section suuja
+.section suujb
+.section suuka
+.section suukb
+.section suula
+.section suulb
+.section suuma
+.section suumb
+.section suuna
+.section suunb
+.section suuoa
+.section suuob
+.section suupa
+.section suupb
+.section suuqa
+.section suuqb
+.section suura
+.section suurb
+.section suusa
+.section suusb
+.section suuta
+.section suutb
+.section suuua
+.section suuub
+.section suuva
+.section suuvb
+.section suuwa
+.section suuwb
+.section suuxa
+.section suuxb
+.section suuya
+.section suuyb
+.section suuza
+.section suuzb
+.section suu1a
+.section suu1b
+.section suu2a
+.section suu2b
+.section suu3a
+.section suu3b
+.section suu4a
+.section suu4b
+.section suu5a
+.section suu5b
+.section suu6a
+.section suu6b
+.section suu7a
+.section suu7b
+.section suu8a
+.section suu8b
+.section suu9a
+.section suu9b
+.section suu0a
+.section suu0b
+.section suvaa
+.section suvab
+.section suvba
+.section suvbb
+.section suvca
+.section suvcb
+.section suvda
+.section suvdb
+.section suvea
+.section suveb
+.section suvfa
+.section suvfb
+.section suvga
+.section suvgb
+.section suvha
+.section suvhb
+.section suvia
+.section suvib
+.section suvja
+.section suvjb
+.section suvka
+.section suvkb
+.section suvla
+.section suvlb
+.section suvma
+.section suvmb
+.section suvna
+.section suvnb
+.section suvoa
+.section suvob
+.section suvpa
+.section suvpb
+.section suvqa
+.section suvqb
+.section suvra
+.section suvrb
+.section suvsa
+.section suvsb
+.section suvta
+.section suvtb
+.section suvua
+.section suvub
+.section suvva
+.section suvvb
+.section suvwa
+.section suvwb
+.section suvxa
+.section suvxb
+.section suvya
+.section suvyb
+.section suvza
+.section suvzb
+.section suv1a
+.section suv1b
+.section suv2a
+.section suv2b
+.section suv3a
+.section suv3b
+.section suv4a
+.section suv4b
+.section suv5a
+.section suv5b
+.section suv6a
+.section suv6b
+.section suv7a
+.section suv7b
+.section suv8a
+.section suv8b
+.section suv9a
+.section suv9b
+.section suv0a
+.section suv0b
+.section suwaa
+.section suwab
+.section suwba
+.section suwbb
+.section suwca
+.section suwcb
+.section suwda
+.section suwdb
+.section suwea
+.section suweb
+.section suwfa
+.section suwfb
+.section suwga
+.section suwgb
+.section suwha
+.section suwhb
+.section suwia
+.section suwib
+.section suwja
+.section suwjb
+.section suwka
+.section suwkb
+.section suwla
+.section suwlb
+.section suwma
+.section suwmb
+.section suwna
+.section suwnb
+.section suwoa
+.section suwob
+.section suwpa
+.section suwpb
+.section suwqa
+.section suwqb
+.section suwra
+.section suwrb
+.section suwsa
+.section suwsb
+.section suwta
+.section suwtb
+.section suwua
+.section suwub
+.section suwva
+.section suwvb
+.section suwwa
+.section suwwb
+.section suwxa
+.section suwxb
+.section suwya
+.section suwyb
+.section suwza
+.section suwzb
+.section suw1a
+.section suw1b
+.section suw2a
+.section suw2b
+.section suw3a
+.section suw3b
+.section suw4a
+.section suw4b
+.section suw5a
+.section suw5b
+.section suw6a
+.section suw6b
+.section suw7a
+.section suw7b
+.section suw8a
+.section suw8b
+.section suw9a
+.section suw9b
+.section suw0a
+.section suw0b
+.section suxaa
+.section suxab
+.section suxba
+.section suxbb
+.section suxca
+.section suxcb
+.section suxda
+.section suxdb
+.section suxea
+.section suxeb
+.section suxfa
+.section suxfb
+.section suxga
+.section suxgb
+.section suxha
+.section suxhb
+.section suxia
+.section suxib
+.section suxja
+.section suxjb
+.section suxka
+.section suxkb
+.section suxla
+.section suxlb
+.section suxma
+.section suxmb
+.section suxna
+.section suxnb
+.section suxoa
+.section suxob
+.section suxpa
+.section suxpb
+.section suxqa
+.section suxqb
+.section suxra
+.section suxrb
+.section suxsa
+.section suxsb
+.section suxta
+.section suxtb
+.section suxua
+.section suxub
+.section suxva
+.section suxvb
+.section suxwa
+.section suxwb
+.section suxxa
+.section suxxb
+.section suxya
+.section suxyb
+.section suxza
+.section suxzb
+.section sux1a
+.section sux1b
+.section sux2a
+.section sux2b
+.section sux3a
+.section sux3b
+.section sux4a
+.section sux4b
+.section sux5a
+.section sux5b
+.section sux6a
+.section sux6b
+.section sux7a
+.section sux7b
+.section sux8a
+.section sux8b
+.section sux9a
+.section sux9b
+.section sux0a
+.section sux0b
+.section suyaa
+.section suyab
+.section suyba
+.section suybb
+.section suyca
+.section suycb
+.section suyda
+.section suydb
+.section suyea
+.section suyeb
+.section suyfa
+.section suyfb
+.section suyga
+.section suygb
+.section suyha
+.section suyhb
+.section suyia
+.section suyib
+.section suyja
+.section suyjb
+.section suyka
+.section suykb
+.section suyla
+.section suylb
+.section suyma
+.section suymb
+.section suyna
+.section suynb
+.section suyoa
+.section suyob
+.section suypa
+.section suypb
+.section suyqa
+.section suyqb
+.section suyra
+.section suyrb
+.section suysa
+.section suysb
+.section suyta
+.section suytb
+.section suyua
+.section suyub
+.section suyva
+.section suyvb
+.section suywa
+.section suywb
+.section suyxa
+.section suyxb
+.section suyya
+.section suyyb
+.section suyza
+.section suyzb
+.section suy1a
+.section suy1b
+.section suy2a
+.section suy2b
+.section suy3a
+.section suy3b
+.section suy4a
+.section suy4b
+.section suy5a
+.section suy5b
+.section suy6a
+.section suy6b
+.section suy7a
+.section suy7b
+.section suy8a
+.section suy8b
+.section suy9a
+.section suy9b
+.section suy0a
+.section suy0b
+.section suzaa
+.section suzab
+.section suzba
+.section suzbb
+.section suzca
+.section suzcb
+.section suzda
+.section suzdb
+.section suzea
+.section suzeb
+.section suzfa
+.section suzfb
+.section suzga
+.section suzgb
+.section suzha
+.section suzhb
+.section suzia
+.section suzib
+.section suzja
+.section suzjb
+.section suzka
+.section suzkb
+.section suzla
+.section suzlb
+.section suzma
+.section suzmb
+.section suzna
+.section suznb
+.section suzoa
+.section suzob
+.section suzpa
+.section suzpb
+.section suzqa
+.section suzqb
+.section suzra
+.section suzrb
+.section suzsa
+.section suzsb
+.section suzta
+.section suztb
+.section suzua
+.section suzub
+.section suzva
+.section suzvb
+.section suzwa
+.section suzwb
+.section suzxa
+.section suzxb
+.section suzya
+.section suzyb
+.section suzza
+.section suzzb
+.section suz1a
+.section suz1b
+.section suz2a
+.section suz2b
+.section suz3a
+.section suz3b
+.section suz4a
+.section suz4b
+.section suz5a
+.section suz5b
+.section suz6a
+.section suz6b
+.section suz7a
+.section suz7b
+.section suz8a
+.section suz8b
+.section suz9a
+.section suz9b
+.section suz0a
+.section suz0b
+.section su1aa
+.section su1ab
+.section su1ba
+.section su1bb
+.section su1ca
+.section su1cb
+.section su1da
+.section su1db
+.section su1ea
+.section su1eb
+.section su1fa
+.section su1fb
+.section su1ga
+.section su1gb
+.section su1ha
+.section su1hb
+.section su1ia
+.section su1ib
+.section su1ja
+.section su1jb
+.section su1ka
+.section su1kb
+.section su1la
+.section su1lb
+.section su1ma
+.section su1mb
+.section su1na
+.section su1nb
+.section su1oa
+.section su1ob
+.section su1pa
+.section su1pb
+.section su1qa
+.section su1qb
+.section su1ra
+.section su1rb
+.section su1sa
+.section su1sb
+.section su1ta
+.section su1tb
+.section su1ua
+.section su1ub
+.section su1va
+.section su1vb
+.section su1wa
+.section su1wb
+.section su1xa
+.section su1xb
+.section su1ya
+.section su1yb
+.section su1za
+.section su1zb
+.section su11a
+.section su11b
+.section su12a
+.section su12b
+.section su13a
+.section su13b
+.section su14a
+.section su14b
+.section su15a
+.section su15b
+.section su16a
+.section su16b
+.section su17a
+.section su17b
+.section su18a
+.section su18b
+.section su19a
+.section su19b
+.section su10a
+.section su10b
+.section su2aa
+.section su2ab
+.section su2ba
+.section su2bb
+.section su2ca
+.section su2cb
+.section su2da
+.section su2db
+.section su2ea
+.section su2eb
+.section su2fa
+.section su2fb
+.section su2ga
+.section su2gb
+.section su2ha
+.section su2hb
+.section su2ia
+.section su2ib
+.section su2ja
+.section su2jb
+.section su2ka
+.section su2kb
+.section su2la
+.section su2lb
+.section su2ma
+.section su2mb
+.section su2na
+.section su2nb
+.section su2oa
+.section su2ob
+.section su2pa
+.section su2pb
+.section su2qa
+.section su2qb
+.section su2ra
+.section su2rb
+.section su2sa
+.section su2sb
+.section su2ta
+.section su2tb
+.section su2ua
+.section su2ub
+.section su2va
+.section su2vb
+.section su2wa
+.section su2wb
+.section su2xa
+.section su2xb
+.section su2ya
+.section su2yb
+.section su2za
+.section su2zb
+.section su21a
+.section su21b
+.section su22a
+.section su22b
+.section su23a
+.section su23b
+.section su24a
+.section su24b
+.section su25a
+.section su25b
+.section su26a
+.section su26b
+.section su27a
+.section su27b
+.section su28a
+.section su28b
+.section su29a
+.section su29b
+.section su20a
+.section su20b
+.section su3aa
+.section su3ab
+.section su3ba
+.section su3bb
+.section su3ca
+.section su3cb
+.section su3da
+.section su3db
+.section su3ea
+.section su3eb
+.section su3fa
+.section su3fb
+.section su3ga
+.section su3gb
+.section su3ha
+.section su3hb
+.section su3ia
+.section su3ib
+.section su3ja
+.section su3jb
+.section su3ka
+.section su3kb
+.section su3la
+.section su3lb
+.section su3ma
+.section su3mb
+.section su3na
+.section su3nb
+.section su3oa
+.section su3ob
+.section su3pa
+.section su3pb
+.section su3qa
+.section su3qb
+.section su3ra
+.section su3rb
+.section su3sa
+.section su3sb
+.section su3ta
+.section su3tb
+.section su3ua
+.section su3ub
+.section su3va
+.section su3vb
+.section su3wa
+.section su3wb
+.section su3xa
+.section su3xb
+.section su3ya
+.section su3yb
+.section su3za
+.section su3zb
+.section su31a
+.section su31b
+.section su32a
+.section su32b
+.section su33a
+.section su33b
+.section su34a
+.section su34b
+.section su35a
+.section su35b
+.section su36a
+.section su36b
+.section su37a
+.section su37b
+.section su38a
+.section su38b
+.section su39a
+.section su39b
+.section su30a
+.section su30b
+.section su4aa
+.section su4ab
+.section su4ba
+.section su4bb
+.section su4ca
+.section su4cb
+.section su4da
+.section su4db
+.section su4ea
+.section su4eb
+.section su4fa
+.section su4fb
+.section su4ga
+.section su4gb
+.section su4ha
+.section su4hb
+.section su4ia
+.section su4ib
+.section su4ja
+.section su4jb
+.section su4ka
+.section su4kb
+.section su4la
+.section su4lb
+.section su4ma
+.section su4mb
+.section su4na
+.section su4nb
+.section su4oa
+.section su4ob
+.section su4pa
+.section su4pb
+.section su4qa
+.section su4qb
+.section su4ra
+.section su4rb
+.section su4sa
+.section su4sb
+.section su4ta
+.section su4tb
+.section su4ua
+.section su4ub
+.section su4va
+.section su4vb
+.section su4wa
+.section su4wb
+.section su4xa
+.section su4xb
+.section su4ya
+.section su4yb
+.section su4za
+.section su4zb
+.section su41a
+.section su41b
+.section su42a
+.section su42b
+.section su43a
+.section su43b
+.section su44a
+.section su44b
+.section su45a
+.section su45b
+.section su46a
+.section su46b
+.section su47a
+.section su47b
+.section su48a
+.section su48b
+.section su49a
+.section su49b
+.section su40a
+.section su40b
+.section su5aa
+.section su5ab
+.section su5ba
+.section su5bb
+.section su5ca
+.section su5cb
+.section su5da
+.section su5db
+.section su5ea
+.section su5eb
+.section su5fa
+.section su5fb
+.section su5ga
+.section su5gb
+.section su5ha
+.section su5hb
+.section su5ia
+.section su5ib
+.section su5ja
+.section su5jb
+.section su5ka
+.section su5kb
+.section su5la
+.section su5lb
+.section su5ma
+.section su5mb
+.section su5na
+.section su5nb
+.section su5oa
+.section su5ob
+.section su5pa
+.section su5pb
+.section su5qa
+.section su5qb
+.section su5ra
+.section su5rb
+.section su5sa
+.section su5sb
+.section su5ta
+.section su5tb
+.section su5ua
+.section su5ub
+.section su5va
+.section su5vb
+.section su5wa
+.section su5wb
+.section su5xa
+.section su5xb
+.section su5ya
+.section su5yb
+.section su5za
+.section su5zb
+.section su51a
+.section su51b
+.section su52a
+.section su52b
+.section su53a
+.section su53b
+.section su54a
+.section su54b
+.section su55a
+.section su55b
+.section su56a
+.section su56b
+.section su57a
+.section su57b
+.section su58a
+.section su58b
+.section su59a
+.section su59b
+.section su50a
+.section su50b
+.section su6aa
+.section su6ab
+.section su6ba
+.section su6bb
+.section su6ca
+.section su6cb
+.section su6da
+.section su6db
+.section su6ea
+.section su6eb
+.section su6fa
+.section su6fb
+.section su6ga
+.section su6gb
+.section su6ha
+.section su6hb
+.section su6ia
+.section su6ib
+.section su6ja
+.section su6jb
+.section su6ka
+.section su6kb
+.section su6la
+.section su6lb
+.section su6ma
+.section su6mb
+.section su6na
+.section su6nb
+.section su6oa
+.section su6ob
+.section su6pa
+.section su6pb
+.section su6qa
+.section su6qb
+.section su6ra
+.section su6rb
+.section su6sa
+.section su6sb
+.section su6ta
+.section su6tb
+.section su6ua
+.section su6ub
+.section su6va
+.section su6vb
+.section su6wa
+.section su6wb
+.section su6xa
+.section su6xb
+.section su6ya
+.section su6yb
+.section su6za
+.section su6zb
+.section su61a
+.section su61b
+.section su62a
+.section su62b
+.section su63a
+.section su63b
+.section su64a
+.section su64b
+.section su65a
+.section su65b
+.section su66a
+.section su66b
+.section su67a
+.section su67b
+.section su68a
+.section su68b
+.section su69a
+.section su69b
+.section su60a
+.section su60b
+.section su7aa
+.section su7ab
+.section su7ba
+.section su7bb
+.section su7ca
+.section su7cb
+.section su7da
+.section su7db
+.section su7ea
+.section su7eb
+.section su7fa
+.section su7fb
+.section su7ga
+.section su7gb
+.section su7ha
+.section su7hb
+.section su7ia
+.section su7ib
+.section su7ja
+.section su7jb
+.section su7ka
+.section su7kb
+.section su7la
+.section su7lb
+.section su7ma
+.section su7mb
+.section su7na
+.section su7nb
+.section su7oa
+.section su7ob
+.section su7pa
+.section su7pb
+.section su7qa
+.section su7qb
+.section su7ra
+.section su7rb
+.section su7sa
+.section su7sb
+.section su7ta
+.section su7tb
+.section su7ua
+.section su7ub
+.section su7va
+.section su7vb
+.section su7wa
+.section su7wb
+.section su7xa
+.section su7xb
+.section su7ya
+.section su7yb
+.section su7za
+.section su7zb
+.section su71a
+.section su71b
+.section su72a
+.section su72b
+.section su73a
+.section su73b
+.section su74a
+.section su74b
+.section su75a
+.section su75b
+.section su76a
+.section su76b
+.section su77a
+.section su77b
+.section su78a
+.section su78b
+.section su79a
+.section su79b
+.section su70a
+.section su70b
+.section su8aa
+.section su8ab
+.section su8ba
+.section su8bb
+.section su8ca
+.section su8cb
+.section su8da
+.section su8db
+.section su8ea
+.section su8eb
+.section su8fa
+.section su8fb
+.section su8ga
+.section su8gb
+.section su8ha
+.section su8hb
+.section su8ia
+.section su8ib
+.section su8ja
+.section su8jb
+.section su8ka
+.section su8kb
+.section su8la
+.section su8lb
+.section su8ma
+.section su8mb
+.section su8na
+.section su8nb
+.section su8oa
+.section su8ob
+.section su8pa
+.section su8pb
+.section su8qa
+.section su8qb
+.section su8ra
+.section su8rb
+.section su8sa
+.section su8sb
+.section su8ta
+.section su8tb
+.section su8ua
+.section su8ub
+.section su8va
+.section su8vb
+.section su8wa
+.section su8wb
+.section su8xa
+.section su8xb
+.section su8ya
+.section su8yb
+.section su8za
+.section su8zb
+.section su81a
+.section su81b
+.section su82a
+.section su82b
+.section su83a
+.section su83b
+.section su84a
+.section su84b
+.section su85a
+.section su85b
+.section su86a
+.section su86b
+.section su87a
+.section su87b
+.section su88a
+.section su88b
+.section su89a
+.section su89b
+.section su80a
+.section su80b
+.section su9aa
+.section su9ab
+.section su9ba
+.section su9bb
+.section su9ca
+.section su9cb
+.section su9da
+.section su9db
+.section su9ea
+.section su9eb
+.section su9fa
+.section su9fb
+.section su9ga
+.section su9gb
+.section su9ha
+.section su9hb
+.section su9ia
+.section su9ib
+.section su9ja
+.section su9jb
+.section su9ka
+.section su9kb
+.section su9la
+.section su9lb
+.section su9ma
+.section su9mb
+.section su9na
+.section su9nb
+.section su9oa
+.section su9ob
+.section su9pa
+.section su9pb
+.section su9qa
+.section su9qb
+.section su9ra
+.section su9rb
+.section su9sa
+.section su9sb
+.section su9ta
+.section su9tb
+.section su9ua
+.section su9ub
+.section su9va
+.section su9vb
+.section su9wa
+.section su9wb
+.section su9xa
+.section su9xb
+.section su9ya
+.section su9yb
+.section su9za
+.section su9zb
+.section su91a
+.section su91b
+.section su92a
+.section su92b
+.section su93a
+.section su93b
+.section su94a
+.section su94b
+.section su95a
+.section su95b
+.section su96a
+.section su96b
+.section su97a
+.section su97b
+.section su98a
+.section su98b
+.section su99a
+.section su99b
+.section su90a
+.section su90b
+.section su0aa
+.section su0ab
+.section su0ba
+.section su0bb
+.section su0ca
+.section su0cb
+.section su0da
+.section su0db
+.section su0ea
+.section su0eb
+.section su0fa
+.section su0fb
+.section su0ga
+.section su0gb
+.section su0ha
+.section su0hb
+.section su0ia
+.section su0ib
+.section su0ja
+.section su0jb
+.section su0ka
+.section su0kb
+.section su0la
+.section su0lb
+.section su0ma
+.section su0mb
+.section su0na
+.section su0nb
+.section su0oa
+.section su0ob
+.section su0pa
+.section su0pb
+.section su0qa
+.section su0qb
+.section su0ra
+.section su0rb
+.section su0sa
+.section su0sb
+.section su0ta
+.section su0tb
+.section su0ua
+.section su0ub
+.section su0va
+.section su0vb
+.section su0wa
+.section su0wb
+.section su0xa
+.section su0xb
+.section su0ya
+.section su0yb
+.section su0za
+.section su0zb
+.section su01a
+.section su01b
+.section su02a
+.section su02b
+.section su03a
+.section su03b
+.section su04a
+.section su04b
+.section su05a
+.section su05b
+.section su06a
+.section su06b
+.section su07a
+.section su07b
+.section su08a
+.section su08b
+.section su09a
+.section su09b
+.section su00a
+.section su00b
+.section svaaa
+.section svaab
+.section svaba
+.section svabb
+.section svaca
+.section svacb
+.section svada
+.section svadb
+.section svaea
+.section svaeb
+.section svafa
+.section svafb
+.section svaga
+.section svagb
+.section svaha
+.section svahb
+.section svaia
+.section svaib
+.section svaja
+.section svajb
+.section svaka
+.section svakb
+.section svala
+.section svalb
+.section svama
+.section svamb
+.section svana
+.section svanb
+.section svaoa
+.section svaob
+.section svapa
+.section svapb
+.section svaqa
+.section svaqb
+.section svara
+.section svarb
+.section svasa
+.section svasb
+.section svata
+.section svatb
+.section svaua
+.section svaub
+.section svava
+.section svavb
+.section svawa
+.section svawb
+.section svaxa
+.section svaxb
+.section svaya
+.section svayb
+.section svaza
+.section svazb
+.section sva1a
+.section sva1b
+.section sva2a
+.section sva2b
+.section sva3a
+.section sva3b
+.section sva4a
+.section sva4b
+.section sva5a
+.section sva5b
+.section sva6a
+.section sva6b
+.section sva7a
+.section sva7b
+.section sva8a
+.section sva8b
+.section sva9a
+.section sva9b
+.section sva0a
+.section sva0b
+.section svbaa
+.section svbab
+.section svbba
+.section svbbb
+.section svbca
+.section svbcb
+.section svbda
+.section svbdb
+.section svbea
+.section svbeb
+.section svbfa
+.section svbfb
+.section svbga
+.section svbgb
+.section svbha
+.section svbhb
+.section svbia
+.section svbib
+.section svbja
+.section svbjb
+.section svbka
+.section svbkb
+.section svbla
+.section svblb
+.section svbma
+.section svbmb
+.section svbna
+.section svbnb
+.section svboa
+.section svbob
+.section svbpa
+.section svbpb
+.section svbqa
+.section svbqb
+.section svbra
+.section svbrb
+.section svbsa
+.section svbsb
+.section svbta
+.section svbtb
+.section svbua
+.section svbub
+.section svbva
+.section svbvb
+.section svbwa
+.section svbwb
+.section svbxa
+.section svbxb
+.section svbya
+.section svbyb
+.section svbza
+.section svbzb
+.section svb1a
+.section svb1b
+.section svb2a
+.section svb2b
+.section svb3a
+.section svb3b
+.section svb4a
+.section svb4b
+.section svb5a
+.section svb5b
+.section svb6a
+.section svb6b
+.section svb7a
+.section svb7b
+.section svb8a
+.section svb8b
+.section svb9a
+.section svb9b
+.section svb0a
+.section svb0b
+.section svcaa
+.section svcab
+.section svcba
+.section svcbb
+.section svcca
+.section svccb
+.section svcda
+.section svcdb
+.section svcea
+.section svceb
+.section svcfa
+.section svcfb
+.section svcga
+.section svcgb
+.section svcha
+.section svchb
+.section svcia
+.section svcib
+.section svcja
+.section svcjb
+.section svcka
+.section svckb
+.section svcla
+.section svclb
+.section svcma
+.section svcmb
+.section svcna
+.section svcnb
+.section svcoa
+.section svcob
+.section svcpa
+.section svcpb
+.section svcqa
+.section svcqb
+.section svcra
+.section svcrb
+.section svcsa
+.section svcsb
+.section svcta
+.section svctb
+.section svcua
+.section svcub
+.section svcva
+.section svcvb
+.section svcwa
+.section svcwb
+.section svcxa
+.section svcxb
+.section svcya
+.section svcyb
+.section svcza
+.section svczb
+.section svc1a
+.section svc1b
+.section svc2a
+.section svc2b
+.section svc3a
+.section svc3b
+.section svc4a
+.section svc4b
+.section svc5a
+.section svc5b
+.section svc6a
+.section svc6b
+.section svc7a
+.section svc7b
+.section svc8a
+.section svc8b
+.section svc9a
+.section svc9b
+.section svc0a
+.section svc0b
+.section svdaa
+.section svdab
+.section svdba
+.section svdbb
+.section svdca
+.section svdcb
+.section svdda
+.section svddb
+.section svdea
+.section svdeb
+.section svdfa
+.section svdfb
+.section svdga
+.section svdgb
+.section svdha
+.section svdhb
+.section svdia
+.section svdib
+.section svdja
+.section svdjb
+.section svdka
+.section svdkb
+.section svdla
+.section svdlb
+.section svdma
+.section svdmb
+.section svdna
+.section svdnb
+.section svdoa
+.section svdob
+.section svdpa
+.section svdpb
+.section svdqa
+.section svdqb
+.section svdra
+.section svdrb
+.section svdsa
+.section svdsb
+.section svdta
+.section svdtb
+.section svdua
+.section svdub
+.section svdva
+.section svdvb
+.section svdwa
+.section svdwb
+.section svdxa
+.section svdxb
+.section svdya
+.section svdyb
+.section svdza
+.section svdzb
+.section svd1a
+.section svd1b
+.section svd2a
+.section svd2b
+.section svd3a
+.section svd3b
+.section svd4a
+.section svd4b
+.section svd5a
+.section svd5b
+.section svd6a
+.section svd6b
+.section svd7a
+.section svd7b
+.section svd8a
+.section svd8b
+.section svd9a
+.section svd9b
+.section svd0a
+.section svd0b
+.section sveaa
+.section sveab
+.section sveba
+.section svebb
+.section sveca
+.section svecb
+.section sveda
+.section svedb
+.section sveea
+.section sveeb
+.section svefa
+.section svefb
+.section svega
+.section svegb
+.section sveha
+.section svehb
+.section sveia
+.section sveib
+.section sveja
+.section svejb
+.section sveka
+.section svekb
+.section svela
+.section svelb
+.section svema
+.section svemb
+.section svena
+.section svenb
+.section sveoa
+.section sveob
+.section svepa
+.section svepb
+.section sveqa
+.section sveqb
+.section svera
+.section sverb
+.section svesa
+.section svesb
+.section sveta
+.section svetb
+.section sveua
+.section sveub
+.section sveva
+.section svevb
+.section svewa
+.section svewb
+.section svexa
+.section svexb
+.section sveya
+.section sveyb
+.section sveza
+.section svezb
+.section sve1a
+.section sve1b
+.section sve2a
+.section sve2b
+.section sve3a
+.section sve3b
+.section sve4a
+.section sve4b
+.section sve5a
+.section sve5b
+.section sve6a
+.section sve6b
+.section sve7a
+.section sve7b
+.section sve8a
+.section sve8b
+.section sve9a
+.section sve9b
+.section sve0a
+.section sve0b
+.section svfaa
+.section svfab
+.section svfba
+.section svfbb
+.section svfca
+.section svfcb
+.section svfda
+.section svfdb
+.section svfea
+.section svfeb
+.section svffa
+.section svffb
+.section svfga
+.section svfgb
+.section svfha
+.section svfhb
+.section svfia
+.section svfib
+.section svfja
+.section svfjb
+.section svfka
+.section svfkb
+.section svfla
+.section svflb
+.section svfma
+.section svfmb
+.section svfna
+.section svfnb
+.section svfoa
+.section svfob
+.section svfpa
+.section svfpb
+.section svfqa
+.section svfqb
+.section svfra
+.section svfrb
+.section svfsa
+.section svfsb
+.section svfta
+.section svftb
+.section svfua
+.section svfub
+.section svfva
+.section svfvb
+.section svfwa
+.section svfwb
+.section svfxa
+.section svfxb
+.section svfya
+.section svfyb
+.section svfza
+.section svfzb
+.section svf1a
+.section svf1b
+.section svf2a
+.section svf2b
+.section svf3a
+.section svf3b
+.section svf4a
+.section svf4b
+.section svf5a
+.section svf5b
+.section svf6a
+.section svf6b
+.section svf7a
+.section svf7b
+.section svf8a
+.section svf8b
+.section svf9a
+.section svf9b
+.section svf0a
+.section svf0b
+.section svgaa
+.section svgab
+.section svgba
+.section svgbb
+.section svgca
+.section svgcb
+.section svgda
+.section svgdb
+.section svgea
+.section svgeb
+.section svgfa
+.section svgfb
+.section svgga
+.section svggb
+.section svgha
+.section svghb
+.section svgia
+.section svgib
+.section svgja
+.section svgjb
+.section svgka
+.section svgkb
+.section svgla
+.section svglb
+.section svgma
+.section svgmb
+.section svgna
+.section svgnb
+.section svgoa
+.section svgob
+.section svgpa
+.section svgpb
+.section svgqa
+.section svgqb
+.section svgra
+.section svgrb
+.section svgsa
+.section svgsb
+.section svgta
+.section svgtb
+.section svgua
+.section svgub
+.section svgva
+.section svgvb
+.section svgwa
+.section svgwb
+.section svgxa
+.section svgxb
+.section svgya
+.section svgyb
+.section svgza
+.section svgzb
+.section svg1a
+.section svg1b
+.section svg2a
+.section svg2b
+.section svg3a
+.section svg3b
+.section svg4a
+.section svg4b
+.section svg5a
+.section svg5b
+.section svg6a
+.section svg6b
+.section svg7a
+.section svg7b
+.section svg8a
+.section svg8b
+.section svg9a
+.section svg9b
+.section svg0a
+.section svg0b
+.section svhaa
+.section svhab
+.section svhba
+.section svhbb
+.section svhca
+.section svhcb
+.section svhda
+.section svhdb
+.section svhea
+.section svheb
+.section svhfa
+.section svhfb
+.section svhga
+.section svhgb
+.section svhha
+.section svhhb
+.section svhia
+.section svhib
+.section svhja
+.section svhjb
+.section svhka
+.section svhkb
+.section svhla
+.section svhlb
+.section svhma
+.section svhmb
+.section svhna
+.section svhnb
+.section svhoa
+.section svhob
+.section svhpa
+.section svhpb
+.section svhqa
+.section svhqb
+.section svhra
+.section svhrb
+.section svhsa
+.section svhsb
+.section svhta
+.section svhtb
+.section svhua
+.section svhub
+.section svhva
+.section svhvb
+.section svhwa
+.section svhwb
+.section svhxa
+.section svhxb
+.section svhya
+.section svhyb
+.section svhza
+.section svhzb
+.section svh1a
+.section svh1b
+.section svh2a
+.section svh2b
+.section svh3a
+.section svh3b
+.section svh4a
+.section svh4b
+.section svh5a
+.section svh5b
+.section svh6a
+.section svh6b
+.section svh7a
+.section svh7b
+.section svh8a
+.section svh8b
+.section svh9a
+.section svh9b
+.section svh0a
+.section svh0b
+.section sviaa
+.section sviab
+.section sviba
+.section svibb
+.section svica
+.section svicb
+.section svida
+.section svidb
+.section sviea
+.section svieb
+.section svifa
+.section svifb
+.section sviga
+.section svigb
+.section sviha
+.section svihb
+.section sviia
+.section sviib
+.section svija
+.section svijb
+.section svika
+.section svikb
+.section svila
+.section svilb
+.section svima
+.section svimb
+.section svina
+.section svinb
+.section svioa
+.section sviob
+.section svipa
+.section svipb
+.section sviqa
+.section sviqb
+.section svira
+.section svirb
+.section svisa
+.section svisb
+.section svita
+.section svitb
+.section sviua
+.section sviub
+.section sviva
+.section svivb
+.section sviwa
+.section sviwb
+.section svixa
+.section svixb
+.section sviya
+.section sviyb
+.section sviza
+.section svizb
+.section svi1a
+.section svi1b
+.section svi2a
+.section svi2b
+.section svi3a
+.section svi3b
+.section svi4a
+.section svi4b
+.section svi5a
+.section svi5b
+.section svi6a
+.section svi6b
+.section svi7a
+.section svi7b
+.section svi8a
+.section svi8b
+.section svi9a
+.section svi9b
+.section svi0a
+.section svi0b
+.section svjaa
+.section svjab
+.section svjba
+.section svjbb
+.section svjca
+.section svjcb
+.section svjda
+.section svjdb
+.section svjea
+.section svjeb
+.section svjfa
+.section svjfb
+.section svjga
+.section svjgb
+.section svjha
+.section svjhb
+.section svjia
+.section svjib
+.section svjja
+.section svjjb
+.section svjka
+.section svjkb
+.section svjla
+.section svjlb
+.section svjma
+.section svjmb
+.section svjna
+.section svjnb
+.section svjoa
+.section svjob
+.section svjpa
+.section svjpb
+.section svjqa
+.section svjqb
+.section svjra
+.section svjrb
+.section svjsa
+.section svjsb
+.section svjta
+.section svjtb
+.section svjua
+.section svjub
+.section svjva
+.section svjvb
+.section svjwa
+.section svjwb
+.section svjxa
+.section svjxb
+.section svjya
+.section svjyb
+.section svjza
+.section svjzb
+.section svj1a
+.section svj1b
+.section svj2a
+.section svj2b
+.section svj3a
+.section svj3b
+.section svj4a
+.section svj4b
+.section svj5a
+.section svj5b
+.section svj6a
+.section svj6b
+.section svj7a
+.section svj7b
+.section svj8a
+.section svj8b
+.section svj9a
+.section svj9b
+.section svj0a
+.section svj0b
+.section svkaa
+.section svkab
+.section svkba
+.section svkbb
+.section svkca
+.section svkcb
+.section svkda
+.section svkdb
+.section svkea
+.section svkeb
+.section svkfa
+.section svkfb
+.section svkga
+.section svkgb
+.section svkha
+.section svkhb
+.section svkia
+.section svkib
+.section svkja
+.section svkjb
+.section svkka
+.section svkkb
+.section svkla
+.section svklb
+.section svkma
+.section svkmb
+.section svkna
+.section svknb
+.section svkoa
+.section svkob
+.section svkpa
+.section svkpb
+.section svkqa
+.section svkqb
+.section svkra
+.section svkrb
+.section svksa
+.section svksb
+.section svkta
+.section svktb
+.section svkua
+.section svkub
+.section svkva
+.section svkvb
+.section svkwa
+.section svkwb
+.section svkxa
+.section svkxb
+.section svkya
+.section svkyb
+.section svkza
+.section svkzb
+.section svk1a
+.section svk1b
+.section svk2a
+.section svk2b
+.section svk3a
+.section svk3b
+.section svk4a
+.section svk4b
+.section svk5a
+.section svk5b
+.section svk6a
+.section svk6b
+.section svk7a
+.section svk7b
+.section svk8a
+.section svk8b
+.section svk9a
+.section svk9b
+.section svk0a
+.section svk0b
+.section svlaa
+.section svlab
+.section svlba
+.section svlbb
+.section svlca
+.section svlcb
+.section svlda
+.section svldb
+.section svlea
+.section svleb
+.section svlfa
+.section svlfb
+.section svlga
+.section svlgb
+.section svlha
+.section svlhb
+.section svlia
+.section svlib
+.section svlja
+.section svljb
+.section svlka
+.section svlkb
+.section svlla
+.section svllb
+.section svlma
+.section svlmb
+.section svlna
+.section svlnb
+.section svloa
+.section svlob
+.section svlpa
+.section svlpb
+.section svlqa
+.section svlqb
+.section svlra
+.section svlrb
+.section svlsa
+.section svlsb
+.section svlta
+.section svltb
+.section svlua
+.section svlub
+.section svlva
+.section svlvb
+.section svlwa
+.section svlwb
+.section svlxa
+.section svlxb
+.section svlya
+.section svlyb
+.section svlza
+.section svlzb
+.section svl1a
+.section svl1b
+.section svl2a
+.section svl2b
+.section svl3a
+.section svl3b
+.section svl4a
+.section svl4b
+.section svl5a
+.section svl5b
+.section svl6a
+.section svl6b
+.section svl7a
+.section svl7b
+.section svl8a
+.section svl8b
+.section svl9a
+.section svl9b
+.section svl0a
+.section svl0b
+.section svmaa
+.section svmab
+.section svmba
+.section svmbb
+.section svmca
+.section svmcb
+.section svmda
+.section svmdb
+.section svmea
+.section svmeb
+.section svmfa
+.section svmfb
+.section svmga
+.section svmgb
+.section svmha
+.section svmhb
+.section svmia
+.section svmib
+.section svmja
+.section svmjb
+.section svmka
+.section svmkb
+.section svmla
+.section svmlb
+.section svmma
+.section svmmb
+.section svmna
+.section svmnb
+.section svmoa
+.section svmob
+.section svmpa
+.section svmpb
+.section svmqa
+.section svmqb
+.section svmra
+.section svmrb
+.section svmsa
+.section svmsb
+.section svmta
+.section svmtb
+.section svmua
+.section svmub
+.section svmva
+.section svmvb
+.section svmwa
+.section svmwb
+.section svmxa
+.section svmxb
+.section svmya
+.section svmyb
+.section svmza
+.section svmzb
+.section svm1a
+.section svm1b
+.section svm2a
+.section svm2b
+.section svm3a
+.section svm3b
+.section svm4a
+.section svm4b
+.section svm5a
+.section svm5b
+.section svm6a
+.section svm6b
+.section svm7a
+.section svm7b
+.section svm8a
+.section svm8b
+.section svm9a
+.section svm9b
+.section svm0a
+.section svm0b
+.section svnaa
+.section svnab
+.section svnba
+.section svnbb
+.section svnca
+.section svncb
+.section svnda
+.section svndb
+.section svnea
+.section svneb
+.section svnfa
+.section svnfb
+.section svnga
+.section svngb
+.section svnha
+.section svnhb
+.section svnia
+.section svnib
+.section svnja
+.section svnjb
+.section svnka
+.section svnkb
+.section svnla
+.section svnlb
+.section svnma
+.section svnmb
+.section svnna
+.section svnnb
+.section svnoa
+.section svnob
+.section svnpa
+.section svnpb
+.section svnqa
+.section svnqb
+.section svnra
+.section svnrb
+.section svnsa
+.section svnsb
+.section svnta
+.section svntb
+.section svnua
+.section svnub
+.section svnva
+.section svnvb
+.section svnwa
+.section svnwb
+.section svnxa
+.section svnxb
+.section svnya
+.section svnyb
+.section svnza
+.section svnzb
+.section svn1a
+.section svn1b
+.section svn2a
+.section svn2b
+.section svn3a
+.section svn3b
+.section svn4a
+.section svn4b
+.section svn5a
+.section svn5b
+.section svn6a
+.section svn6b
+.section svn7a
+.section svn7b
+.section svn8a
+.section svn8b
+.section svn9a
+.section svn9b
+.section svn0a
+.section svn0b
+.section svoaa
+.section svoab
+.section svoba
+.section svobb
+.section svoca
+.section svocb
+.section svoda
+.section svodb
+.section svoea
+.section svoeb
+.section svofa
+.section svofb
+.section svoga
+.section svogb
+.section svoha
+.section svohb
+.section svoia
+.section svoib
+.section svoja
+.section svojb
+.section svoka
+.section svokb
+.section svola
+.section svolb
+.section svoma
+.section svomb
+.section svona
+.section svonb
+.section svooa
+.section svoob
+.section svopa
+.section svopb
+.section svoqa
+.section svoqb
+.section svora
+.section svorb
+.section svosa
+.section svosb
+.section svota
+.section svotb
+.section svoua
+.section svoub
+.section svova
+.section svovb
+.section svowa
+.section svowb
+.section svoxa
+.section svoxb
+.section svoya
+.section svoyb
+.section svoza
+.section svozb
+.section svo1a
+.section svo1b
+.section svo2a
+.section svo2b
+.section svo3a
+.section svo3b
+.section svo4a
+.section svo4b
+.section svo5a
+.section svo5b
+.section svo6a
+.section svo6b
+.section svo7a
+.section svo7b
+.section svo8a
+.section svo8b
+.section svo9a
+.section svo9b
+.section svo0a
+.section svo0b
+.section svpaa
+.section svpab
+.section svpba
+.section svpbb
+.section svpca
+.section svpcb
+.section svpda
+.section svpdb
+.section svpea
+.section svpeb
+.section svpfa
+.section svpfb
+.section svpga
+.section svpgb
+.section svpha
+.section svphb
+.section svpia
+.section svpib
+.section svpja
+.section svpjb
+.section svpka
+.section svpkb
+.section svpla
+.section svplb
+.section svpma
+.section svpmb
+.section svpna
+.section svpnb
+.section svpoa
+.section svpob
+.section svppa
+.section svppb
+.section svpqa
+.section svpqb
+.section svpra
+.section svprb
+.section svpsa
+.section svpsb
+.section svpta
+.section svptb
+.section svpua
+.section svpub
+.section svpva
+.section svpvb
+.section svpwa
+.section svpwb
+.section svpxa
+.section svpxb
+.section svpya
+.section svpyb
+.section svpza
+.section svpzb
+.section svp1a
+.section svp1b
+.section svp2a
+.section svp2b
+.section svp3a
+.section svp3b
+.section svp4a
+.section svp4b
+.section svp5a
+.section svp5b
+.section svp6a
+.section svp6b
+.section svp7a
+.section svp7b
+.section svp8a
+.section svp8b
+.section svp9a
+.section svp9b
+.section svp0a
+.section svp0b
+.section svqaa
+.section svqab
+.section svqba
+.section svqbb
+.section svqca
+.section svqcb
+.section svqda
+.section svqdb
+.section svqea
+.section svqeb
+.section svqfa
+.section svqfb
+.section svqga
+.section svqgb
+.section svqha
+.section svqhb
+.section svqia
+.section svqib
+.section svqja
+.section svqjb
+.section svqka
+.section svqkb
+.section svqla
+.section svqlb
+.section svqma
+.section svqmb
+.section svqna
+.section svqnb
+.section svqoa
+.section svqob
+.section svqpa
+.section svqpb
+.section svqqa
+.section svqqb
+.section svqra
+.section svqrb
+.section svqsa
+.section svqsb
+.section svqta
+.section svqtb
+.section svqua
+.section svqub
+.section svqva
+.section svqvb
+.section svqwa
+.section svqwb
+.section svqxa
+.section svqxb
+.section svqya
+.section svqyb
+.section svqza
+.section svqzb
+.section svq1a
+.section svq1b
+.section svq2a
+.section svq2b
+.section svq3a
+.section svq3b
+.section svq4a
+.section svq4b
+.section svq5a
+.section svq5b
+.section svq6a
+.section svq6b
+.section svq7a
+.section svq7b
+.section svq8a
+.section svq8b
+.section svq9a
+.section svq9b
+.section svq0a
+.section svq0b
+.section svraa
+.section svrab
+.section svrba
+.section svrbb
+.section svrca
+.section svrcb
+.section svrda
+.section svrdb
+.section svrea
+.section svreb
+.section svrfa
+.section svrfb
+.section svrga
+.section svrgb
+.section svrha
+.section svrhb
+.section svria
+.section svrib
+.section svrja
+.section svrjb
+.section svrka
+.section svrkb
+.section svrla
+.section svrlb
+.section svrma
+.section svrmb
+.section svrna
+.section svrnb
+.section svroa
+.section svrob
+.section svrpa
+.section svrpb
+.section svrqa
+.section svrqb
+.section svrra
+.section svrrb
+.section svrsa
+.section svrsb
+.section svrta
+.section svrtb
+.section svrua
+.section svrub
+.section svrva
+.section svrvb
+.section svrwa
+.section svrwb
+.section svrxa
+.section svrxb
+.section svrya
+.section svryb
+.section svrza
+.section svrzb
+.section svr1a
+.section svr1b
+.section svr2a
+.section svr2b
+.section svr3a
+.section svr3b
+.section svr4a
+.section svr4b
+.section svr5a
+.section svr5b
+.section svr6a
+.section svr6b
+.section svr7a
+.section svr7b
+.section svr8a
+.section svr8b
+.section svr9a
+.section svr9b
+.section svr0a
+.section svr0b
+.section svsaa
+.section svsab
+.section svsba
+.section svsbb
+.section svsca
+.section svscb
+.section svsda
+.section svsdb
+.section svsea
+.section svseb
+.section svsfa
+.section svsfb
+.section svsga
+.section svsgb
+.section svsha
+.section svshb
+.section svsia
+.section svsib
+.section svsja
+.section svsjb
+.section svska
+.section svskb
+.section svsla
+.section svslb
+.section svsma
+.section svsmb
+.section svsna
+.section svsnb
+.section svsoa
+.section svsob
+.section svspa
+.section svspb
+.section svsqa
+.section svsqb
+.section svsra
+.section svsrb
+.section svssa
+.section svssb
+.section svsta
+.section svstb
+.section svsua
+.section svsub
+.section svsva
+.section svsvb
+.section svswa
+.section svswb
+.section svsxa
+.section svsxb
+.section svsya
+.section svsyb
+.section svsza
+.section svszb
+.section svs1a
+.section svs1b
+.section svs2a
+.section svs2b
+.section svs3a
+.section svs3b
+.section svs4a
+.section svs4b
+.section svs5a
+.section svs5b
+.section svs6a
+.section svs6b
+.section svs7a
+.section svs7b
+.section svs8a
+.section svs8b
+.section svs9a
+.section svs9b
+.section svs0a
+.section svs0b
+.section svtaa
+.section svtab
+.section svtba
+.section svtbb
+.section svtca
+.section svtcb
+.section svtda
+.section svtdb
+.section svtea
+.section svteb
+.section svtfa
+.section svtfb
+.section svtga
+.section svtgb
+.section svtha
+.section svthb
+.section svtia
+.section svtib
+.section svtja
+.section svtjb
+.section svtka
+.section svtkb
+.section svtla
+.section svtlb
+.section svtma
+.section svtmb
+.section svtna
+.section svtnb
+.section svtoa
+.section svtob
+.section svtpa
+.section svtpb
+.section svtqa
+.section svtqb
+.section svtra
+.section svtrb
+.section svtsa
+.section svtsb
+.section svtta
+.section svttb
+.section svtua
+.section svtub
+.section svtva
+.section svtvb
+.section svtwa
+.section svtwb
+.section svtxa
+.section svtxb
+.section svtya
+.section svtyb
+.section svtza
+.section svtzb
+.section svt1a
+.section svt1b
+.section svt2a
+.section svt2b
+.section svt3a
+.section svt3b
+.section svt4a
+.section svt4b
+.section svt5a
+.section svt5b
+.section svt6a
+.section svt6b
+.section svt7a
+.section svt7b
+.section svt8a
+.section svt8b
+.section svt9a
+.section svt9b
+.section svt0a
+.section svt0b
+.section svuaa
+.section svuab
+.section svuba
+.section svubb
+.section svuca
+.section svucb
+.section svuda
+.section svudb
+.section svuea
+.section svueb
+.section svufa
+.section svufb
+.section svuga
+.section svugb
+.section svuha
+.section svuhb
+.section svuia
+.section svuib
+.section svuja
+.section svujb
+.section svuka
+.section svukb
+.section svula
+.section svulb
+.section svuma
+.section svumb
+.section svuna
+.section svunb
+.section svuoa
+.section svuob
+.section svupa
+.section svupb
+.section svuqa
+.section svuqb
+.section svura
+.section svurb
+.section svusa
+.section svusb
+.section svuta
+.section svutb
+.section svuua
+.section svuub
+.section svuva
+.section svuvb
+.section svuwa
+.section svuwb
+.section svuxa
+.section svuxb
+.section svuya
+.section svuyb
+.section svuza
+.section svuzb
+.section svu1a
+.section svu1b
+.section svu2a
+.section svu2b
+.section svu3a
+.section svu3b
+.section svu4a
+.section svu4b
+.section svu5a
+.section svu5b
+.section svu6a
+.section svu6b
+.section svu7a
+.section svu7b
+.section svu8a
+.section svu8b
+.section svu9a
+.section svu9b
+.section svu0a
+.section svu0b
+.section svvaa
+.section svvab
+.section svvba
+.section svvbb
+.section svvca
+.section svvcb
+.section svvda
+.section svvdb
+.section svvea
+.section svveb
+.section svvfa
+.section svvfb
+.section svvga
+.section svvgb
+.section svvha
+.section svvhb
+.section svvia
+.section svvib
+.section svvja
+.section svvjb
+.section svvka
+.section svvkb
+.section svvla
+.section svvlb
+.section svvma
+.section svvmb
+.section svvna
+.section svvnb
+.section svvoa
+.section svvob
+.section svvpa
+.section svvpb
+.section svvqa
+.section svvqb
+.section svvra
+.section svvrb
+.section svvsa
+.section svvsb
+.section svvta
+.section svvtb
+.section svvua
+.section svvub
+.section svvva
+.section svvvb
+.section svvwa
+.section svvwb
+.section svvxa
+.section svvxb
+.section svvya
+.section svvyb
+.section svvza
+.section svvzb
+.section svv1a
+.section svv1b
+.section svv2a
+.section svv2b
+.section svv3a
+.section svv3b
+.section svv4a
+.section svv4b
+.section svv5a
+.section svv5b
+.section svv6a
+.section svv6b
+.section svv7a
+.section svv7b
+.section svv8a
+.section svv8b
+.section svv9a
+.section svv9b
+.section svv0a
+.section svv0b
+.section svwaa
+.section svwab
+.section svwba
+.section svwbb
+.section svwca
+.section svwcb
+.section svwda
+.section svwdb
+.section svwea
+.section svweb
+.section svwfa
+.section svwfb
+.section svwga
+.section svwgb
+.section svwha
+.section svwhb
+.section svwia
+.section svwib
+.section svwja
+.section svwjb
+.section svwka
+.section svwkb
+.section svwla
+.section svwlb
+.section svwma
+.section svwmb
+.section svwna
+.section svwnb
+.section svwoa
+.section svwob
+.section svwpa
+.section svwpb
+.section svwqa
+.section svwqb
+.section svwra
+.section svwrb
+.section svwsa
+.section svwsb
+.section svwta
+.section svwtb
+.section svwua
+.section svwub
+.section svwva
+.section svwvb
+.section svwwa
+.section svwwb
+.section svwxa
+.section svwxb
+.section svwya
+.section svwyb
+.section svwza
+.section svwzb
+.section svw1a
+.section svw1b
+.section svw2a
+.section svw2b
+.section svw3a
+.section svw3b
+.section svw4a
+.section svw4b
+.section svw5a
+.section svw5b
+.section svw6a
+.section svw6b
+.section svw7a
+.section svw7b
+.section svw8a
+.section svw8b
+.section svw9a
+.section svw9b
+.section svw0a
+.section svw0b
+.section svxaa
+.section svxab
+.section svxba
+.section svxbb
+.section svxca
+.section svxcb
+.section svxda
+.section svxdb
+.section svxea
+.section svxeb
+.section svxfa
+.section svxfb
+.section svxga
+.section svxgb
+.section svxha
+.section svxhb
+.section svxia
+.section svxib
+.section svxja
+.section svxjb
+.section svxka
+.section svxkb
+.section svxla
+.section svxlb
+.section svxma
+.section svxmb
+.section svxna
+.section svxnb
+.section svxoa
+.section svxob
+.section svxpa
+.section svxpb
+.section svxqa
+.section svxqb
+.section svxra
+.section svxrb
+.section svxsa
+.section svxsb
+.section svxta
+.section svxtb
+.section svxua
+.section svxub
+.section svxva
+.section svxvb
+.section svxwa
+.section svxwb
+.section svxxa
+.section svxxb
+.section svxya
+.section svxyb
+.section svxza
+.section svxzb
+.section svx1a
+.section svx1b
+.section svx2a
+.section svx2b
+.section svx3a
+.section svx3b
+.section svx4a
+.section svx4b
+.section svx5a
+.section svx5b
+.section svx6a
+.section svx6b
+.section svx7a
+.section svx7b
+.section svx8a
+.section svx8b
+.section svx9a
+.section svx9b
+.section svx0a
+.section svx0b
+.section svyaa
+.section svyab
+.section svyba
+.section svybb
+.section svyca
+.section svycb
+.section svyda
+.section svydb
+.section svyea
+.section svyeb
+.section svyfa
+.section svyfb
+.section svyga
+.section svygb
+.section svyha
+.section svyhb
+.section svyia
+.section svyib
+.section svyja
+.section svyjb
+.section svyka
+.section svykb
+.section svyla
+.section svylb
+.section svyma
+.section svymb
+.section svyna
+.section svynb
+.section svyoa
+.section svyob
+.section svypa
+.section svypb
+.section svyqa
+.section svyqb
+.section svyra
+.section svyrb
+.section svysa
+.section svysb
+.section svyta
+.section svytb
+.section svyua
+.section svyub
+.section svyva
+.section svyvb
+.section svywa
+.section svywb
+.section svyxa
+.section svyxb
+.section svyya
+.section svyyb
+.section svyza
+.section svyzb
+.section svy1a
+.section svy1b
+.section svy2a
+.section svy2b
+.section svy3a
+.section svy3b
+.section svy4a
+.section svy4b
+.section svy5a
+.section svy5b
+.section svy6a
+.section svy6b
+.section svy7a
+.section svy7b
+.section svy8a
+.section svy8b
+.section svy9a
+.section svy9b
+.section svy0a
+.section svy0b
+.section svzaa
+.section svzab
+.section svzba
+.section svzbb
+.section svzca
+.section svzcb
+.section svzda
+.section svzdb
+.section svzea
+.section svzeb
+.section svzfa
+.section svzfb
+.section svzga
+.section svzgb
+.section svzha
+.section svzhb
+.section svzia
+.section svzib
+.section svzja
+.section svzjb
+.section svzka
+.section svzkb
+.section svzla
+.section svzlb
+.section svzma
+.section svzmb
+.section svzna
+.section svznb
+.section svzoa
+.section svzob
+.section svzpa
+.section svzpb
+.section svzqa
+.section svzqb
+.section svzra
+.section svzrb
+.section svzsa
+.section svzsb
+.section svzta
+.section svztb
+.section svzua
+.section svzub
+.section svzva
+.section svzvb
+.section svzwa
+.section svzwb
+.section svzxa
+.section svzxb
+.section svzya
+.section svzyb
+.section svzza
+.section svzzb
+.section svz1a
+.section svz1b
+.section svz2a
+.section svz2b
+.section svz3a
+.section svz3b
+.section svz4a
+.section svz4b
+.section svz5a
+.section svz5b
+.section svz6a
+.section svz6b
+.section svz7a
+.section svz7b
+.section svz8a
+.section svz8b
+.section svz9a
+.section svz9b
+.section svz0a
+.section svz0b
+.section sv1aa
+.section sv1ab
+.section sv1ba
+.section sv1bb
+.section sv1ca
+.section sv1cb
+.section sv1da
+.section sv1db
+.section sv1ea
+.section sv1eb
+.section sv1fa
+.section sv1fb
+.section sv1ga
+.section sv1gb
+.section sv1ha
+.section sv1hb
+.section sv1ia
+.section sv1ib
+.section sv1ja
+.section sv1jb
+.section sv1ka
+.section sv1kb
+.section sv1la
+.section sv1lb
+.section sv1ma
+.section sv1mb
+.section sv1na
+.section sv1nb
+.section sv1oa
+.section sv1ob
+.section sv1pa
+.section sv1pb
+.section sv1qa
+.section sv1qb
+.section sv1ra
+.section sv1rb
+.section sv1sa
+.section sv1sb
+.section sv1ta
+.section sv1tb
+.section sv1ua
+.section sv1ub
+.section sv1va
+.section sv1vb
+.section sv1wa
+.section sv1wb
+.section sv1xa
+.section sv1xb
+.section sv1ya
+.section sv1yb
+.section sv1za
+.section sv1zb
+.section sv11a
+.section sv11b
+.section sv12a
+.section sv12b
+.section sv13a
+.section sv13b
+.section sv14a
+.section sv14b
+.section sv15a
+.section sv15b
+.section sv16a
+.section sv16b
+.section sv17a
+.section sv17b
+.section sv18a
+.section sv18b
+.section sv19a
+.section sv19b
+.section sv10a
+.section sv10b
+.section sv2aa
+.section sv2ab
+.section sv2ba
+.section sv2bb
+.section sv2ca
+.section sv2cb
+.section sv2da
+.section sv2db
+.section sv2ea
+.section sv2eb
+.section sv2fa
+.section sv2fb
+.section sv2ga
+.section sv2gb
+.section sv2ha
+.section sv2hb
+.section sv2ia
+.section sv2ib
+.section sv2ja
+.section sv2jb
+.section sv2ka
+.section sv2kb
+.section sv2la
+.section sv2lb
+.section sv2ma
+.section sv2mb
+.section sv2na
+.section sv2nb
+.section sv2oa
+.section sv2ob
+.section sv2pa
+.section sv2pb
+.section sv2qa
+.section sv2qb
+.section sv2ra
+.section sv2rb
+.section sv2sa
+.section sv2sb
+.section sv2ta
+.section sv2tb
+.section sv2ua
+.section sv2ub
+.section sv2va
+.section sv2vb
+.section sv2wa
+.section sv2wb
+.section sv2xa
+.section sv2xb
+.section sv2ya
+.section sv2yb
+.section sv2za
+.section sv2zb
+.section sv21a
+.section sv21b
+.section sv22a
+.section sv22b
+.section sv23a
+.section sv23b
+.section sv24a
+.section sv24b
+.section sv25a
+.section sv25b
+.section sv26a
+.section sv26b
+.section sv27a
+.section sv27b
+.section sv28a
+.section sv28b
+.section sv29a
+.section sv29b
+.section sv20a
+.section sv20b
+.section sv3aa
+.section sv3ab
+.section sv3ba
+.section sv3bb
+.section sv3ca
+.section sv3cb
+.section sv3da
+.section sv3db
+.section sv3ea
+.section sv3eb
+.section sv3fa
+.section sv3fb
+.section sv3ga
+.section sv3gb
+.section sv3ha
+.section sv3hb
+.section sv3ia
+.section sv3ib
+.section sv3ja
+.section sv3jb
+.section sv3ka
+.section sv3kb
+.section sv3la
+.section sv3lb
+.section sv3ma
+.section sv3mb
+.section sv3na
+.section sv3nb
+.section sv3oa
+.section sv3ob
+.section sv3pa
+.section sv3pb
+.section sv3qa
+.section sv3qb
+.section sv3ra
+.section sv3rb
+.section sv3sa
+.section sv3sb
+.section sv3ta
+.section sv3tb
+.section sv3ua
+.section sv3ub
+.section sv3va
+.section sv3vb
+.section sv3wa
+.section sv3wb
+.section sv3xa
+.section sv3xb
+.section sv3ya
+.section sv3yb
+.section sv3za
+.section sv3zb
+.section sv31a
+.section sv31b
+.section sv32a
+.section sv32b
+.section sv33a
+.section sv33b
+.section sv34a
+.section sv34b
+.section sv35a
+.section sv35b
+.section sv36a
+.section sv36b
+.section sv37a
+.section sv37b
+.section sv38a
+.section sv38b
+.section sv39a
+.section sv39b
+.section sv30a
+.section sv30b
+.section sv4aa
+.section sv4ab
+.section sv4ba
+.section sv4bb
+.section sv4ca
+.section sv4cb
+.section sv4da
+.section sv4db
+.section sv4ea
+.section sv4eb
+.section sv4fa
+.section sv4fb
+.section sv4ga
+.section sv4gb
+.section sv4ha
+.section sv4hb
+.section sv4ia
+.section sv4ib
+.section sv4ja
+.section sv4jb
+.section sv4ka
+.section sv4kb
+.section sv4la
+.section sv4lb
+.section sv4ma
+.section sv4mb
+.section sv4na
+.section sv4nb
+.section sv4oa
+.section sv4ob
+.section sv4pa
+.section sv4pb
+.section sv4qa
+.section sv4qb
+.section sv4ra
+.section sv4rb
+.section sv4sa
+.section sv4sb
+.section sv4ta
+.section sv4tb
+.section sv4ua
+.section sv4ub
+.section sv4va
+.section sv4vb
+.section sv4wa
+.section sv4wb
+.section sv4xa
+.section sv4xb
+.section sv4ya
+.section sv4yb
+.section sv4za
+.section sv4zb
+.section sv41a
+.section sv41b
+.section sv42a
+.section sv42b
+.section sv43a
+.section sv43b
+.section sv44a
+.section sv44b
+.section sv45a
+.section sv45b
+.section sv46a
+.section sv46b
+.section sv47a
+.section sv47b
+.section sv48a
+.section sv48b
+.section sv49a
+.section sv49b
+.section sv40a
+.section sv40b
+.section sv5aa
+.section sv5ab
+.section sv5ba
+.section sv5bb
+.section sv5ca
+.section sv5cb
+.section sv5da
+.section sv5db
+.section sv5ea
+.section sv5eb
+.section sv5fa
+.section sv5fb
+.section sv5ga
+.section sv5gb
+.section sv5ha
+.section sv5hb
+.section sv5ia
+.section sv5ib
+.section sv5ja
+.section sv5jb
+.section sv5ka
+.section sv5kb
+.section sv5la
+.section sv5lb
+.section sv5ma
+.section sv5mb
+.section sv5na
+.section sv5nb
+.section sv5oa
+.section sv5ob
+.section sv5pa
+.section sv5pb
+.section sv5qa
+.section sv5qb
+.section sv5ra
+.section sv5rb
+.section sv5sa
+.section sv5sb
+.section sv5ta
+.section sv5tb
+.section sv5ua
+.section sv5ub
+.section sv5va
+.section sv5vb
+.section sv5wa
+.section sv5wb
+.section sv5xa
+.section sv5xb
+.section sv5ya
+.section sv5yb
+.section sv5za
+.section sv5zb
+.section sv51a
+.section sv51b
+.section sv52a
+.section sv52b
+.section sv53a
+.section sv53b
+.section sv54a
+.section sv54b
+.section sv55a
+.section sv55b
+.section sv56a
+.section sv56b
+.section sv57a
+.section sv57b
+.section sv58a
+.section sv58b
+.section sv59a
+.section sv59b
+.section sv50a
+.section sv50b
+.section sv6aa
+.section sv6ab
+.section sv6ba
+.section sv6bb
+.section sv6ca
+.section sv6cb
+.section sv6da
+.section sv6db
+.section sv6ea
+.section sv6eb
+.section sv6fa
+.section sv6fb
+.section sv6ga
+.section sv6gb
+.section sv6ha
+.section sv6hb
+.section sv6ia
+.section sv6ib
+.section sv6ja
+.section sv6jb
+.section sv6ka
+.section sv6kb
+.section sv6la
+.section sv6lb
+.section sv6ma
+.section sv6mb
+.section sv6na
+.section sv6nb
+.section sv6oa
+.section sv6ob
+.section sv6pa
+.section sv6pb
+.section sv6qa
+.section sv6qb
+.section sv6ra
+.section sv6rb
+.section sv6sa
+.section sv6sb
+.section sv6ta
+.section sv6tb
+.section sv6ua
+.section sv6ub
+.section sv6va
+.section sv6vb
+.section sv6wa
+.section sv6wb
+.section sv6xa
+.section sv6xb
+.section sv6ya
+.section sv6yb
+.section sv6za
+.section sv6zb
+.section sv61a
+.section sv61b
+.section sv62a
+.section sv62b
+.section sv63a
+.section sv63b
+.section sv64a
+.section sv64b
+.section sv65a
+.section sv65b
+.section sv66a
+.section sv66b
+.section sv67a
+.section sv67b
+.section sv68a
+.section sv68b
+.section sv69a
+.section sv69b
+.section sv60a
+.section sv60b
+.section sv7aa
+.section sv7ab
+.section sv7ba
+.section sv7bb
+.section sv7ca
+.section sv7cb
+.section sv7da
+.section sv7db
+.section sv7ea
+.section sv7eb
+.section sv7fa
+.section sv7fb
+.section sv7ga
+.section sv7gb
+.section sv7ha
+.section sv7hb
+.section sv7ia
+.section sv7ib
+.section sv7ja
+.section sv7jb
+.section sv7ka
+.section sv7kb
+.section sv7la
+.section sv7lb
+.section sv7ma
+.section sv7mb
+.section sv7na
+.section sv7nb
+.section sv7oa
+.section sv7ob
+.section sv7pa
+.section sv7pb
+.section sv7qa
+.section sv7qb
+.section sv7ra
+.section sv7rb
+.section sv7sa
+.section sv7sb
+.section sv7ta
+.section sv7tb
+.section sv7ua
+.section sv7ub
+.section sv7va
+.section sv7vb
+.section sv7wa
+.section sv7wb
+.section sv7xa
+.section sv7xb
+.section sv7ya
+.section sv7yb
+.section sv7za
+.section sv7zb
+.section sv71a
+.section sv71b
+.section sv72a
+.section sv72b
+.section sv73a
+.section sv73b
+.section sv74a
+.section sv74b
+.section sv75a
+.section sv75b
+.section sv76a
+.section sv76b
+.section sv77a
+.section sv77b
+.section sv78a
+.section sv78b
+.section sv79a
+.section sv79b
+.section sv70a
+.section sv70b
+.section sv8aa
+.section sv8ab
+.section sv8ba
+.section sv8bb
+.section sv8ca
+.section sv8cb
+.section sv8da
+.section sv8db
+.section sv8ea
+.section sv8eb
+.section sv8fa
+.section sv8fb
+.section sv8ga
+.section sv8gb
+.section sv8ha
+.section sv8hb
+.section sv8ia
+.section sv8ib
+.section sv8ja
+.section sv8jb
+.section sv8ka
+.section sv8kb
+.section sv8la
+.section sv8lb
+.section sv8ma
+.section sv8mb
+.section sv8na
+.section sv8nb
+.section sv8oa
+.section sv8ob
+.section sv8pa
+.section sv8pb
+.section sv8qa
+.section sv8qb
+.section sv8ra
+.section sv8rb
+.section sv8sa
+.section sv8sb
+.section sv8ta
+.section sv8tb
+.section sv8ua
+.section sv8ub
+.section sv8va
+.section sv8vb
+.section sv8wa
+.section sv8wb
+.section sv8xa
+.section sv8xb
+.section sv8ya
+.section sv8yb
+.section sv8za
+.section sv8zb
+.section sv81a
+.section sv81b
+.section sv82a
+.section sv82b
+.section sv83a
+.section sv83b
+.section sv84a
+.section sv84b
+.section sv85a
+.section sv85b
+.section sv86a
+.section sv86b
+.section sv87a
+.section sv87b
+.section sv88a
+.section sv88b
+.section sv89a
+.section sv89b
+.section sv80a
+.section sv80b
+.section sv9aa
+.section sv9ab
+.section sv9ba
+.section sv9bb
+.section sv9ca
+.section sv9cb
+.section sv9da
+.section sv9db
+.section sv9ea
+.section sv9eb
+.section sv9fa
+.section sv9fb
+.section sv9ga
+.section sv9gb
+.section sv9ha
+.section sv9hb
+.section sv9ia
+.section sv9ib
+.section sv9ja
+.section sv9jb
+.section sv9ka
+.section sv9kb
+.section sv9la
+.section sv9lb
+.section sv9ma
+.section sv9mb
+.section sv9na
+.section sv9nb
+.section sv9oa
+.section sv9ob
+.section sv9pa
+.section sv9pb
+.section sv9qa
+.section sv9qb
+.section sv9ra
+.section sv9rb
+.section sv9sa
+.section sv9sb
+.section sv9ta
+.section sv9tb
+.section sv9ua
+.section sv9ub
+.section sv9va
+.section sv9vb
+.section sv9wa
+.section sv9wb
+.section sv9xa
+.section sv9xb
+.section sv9ya
+.section sv9yb
+.section sv9za
+.section sv9zb
+.section sv91a
+.section sv91b
+.section sv92a
+.section sv92b
+.section sv93a
+.section sv93b
+.section sv94a
+.section sv94b
+.section sv95a
+.section sv95b
+.section sv96a
+.section sv96b
+.section sv97a
+.section sv97b
+.section sv98a
+.section sv98b
+.section sv99a
+.section sv99b
+.section sv90a
+.section sv90b
+.section sv0aa
+.section sv0ab
+.section sv0ba
+.section sv0bb
+.section sv0ca
+.section sv0cb
+.section sv0da
+.section sv0db
+.section sv0ea
+.section sv0eb
+.section sv0fa
+.section sv0fb
+.section sv0ga
+.section sv0gb
+.section sv0ha
+.section sv0hb
+.section sv0ia
+.section sv0ib
+.section sv0ja
+.section sv0jb
+.section sv0ka
+.section sv0kb
+.section sv0la
+.section sv0lb
+.section sv0ma
+.section sv0mb
+.section sv0na
+.section sv0nb
+.section sv0oa
+.section sv0ob
+.section sv0pa
+.section sv0pb
+.section sv0qa
+.section sv0qb
+.section sv0ra
+.section sv0rb
+.section sv0sa
+.section sv0sb
+.section sv0ta
+.section sv0tb
+.section sv0ua
+.section sv0ub
+.section sv0va
+.section sv0vb
+.section sv0wa
+.section sv0wb
+.section sv0xa
+.section sv0xb
+.section sv0ya
+.section sv0yb
+.section sv0za
+.section sv0zb
+.section sv01a
+.section sv01b
+.section sv02a
+.section sv02b
+.section sv03a
+.section sv03b
+.section sv04a
+.section sv04b
+.section sv05a
+.section sv05b
+.section sv06a
+.section sv06b
+.section sv07a
+.section sv07b
+.section sv08a
+.section sv08b
+.section sv09a
+.section sv09b
+.section sv00a
+.section sv00b
+.section swaaa
+.section swaab
+.section swaba
+.section swabb
+.section swaca
+.section swacb
+.section swada
+.section swadb
+.section swaea
+.section swaeb
+.section swafa
+.section swafb
+.section swaga
+.section swagb
+.section swaha
+.section swahb
+.section swaia
+.section swaib
+.section swaja
+.section swajb
+.section swaka
+.section swakb
+.section swala
+.section swalb
+.section swama
+.section swamb
+.section swana
+.section swanb
+.section swaoa
+.section swaob
+.section swapa
+.section swapb
+.section swaqa
+.section swaqb
+.section swara
+.section swarb
+.section swasa
+.section swasb
+.section swata
+.section swatb
+.section swaua
+.section swaub
+.section swava
+.section swavb
+.section swawa
+.section swawb
+.section swaxa
+.section swaxb
+.section swaya
+.section swayb
+.section swaza
+.section swazb
+.section swa1a
+.section swa1b
+.section swa2a
+.section swa2b
+.section swa3a
+.section swa3b
+.section swa4a
+.section swa4b
+.section swa5a
+.section swa5b
+.section swa6a
+.section swa6b
+.section swa7a
+.section swa7b
+.section swa8a
+.section swa8b
+.section swa9a
+.section swa9b
+.section swa0a
+.section swa0b
+.section swbaa
+.section swbab
+.section swbba
+.section swbbb
+.section swbca
+.section swbcb
+.section swbda
+.section swbdb
+.section swbea
+.section swbeb
+.section swbfa
+.section swbfb
+.section swbga
+.section swbgb
+.section swbha
+.section swbhb
+.section swbia
+.section swbib
+.section swbja
+.section swbjb
+.section swbka
+.section swbkb
+.section swbla
+.section swblb
+.section swbma
+.section swbmb
+.section swbna
+.section swbnb
+.section swboa
+.section swbob
+.section swbpa
+.section swbpb
+.section swbqa
+.section swbqb
+.section swbra
+.section swbrb
+.section swbsa
+.section swbsb
+.section swbta
+.section swbtb
+.section swbua
+.section swbub
+.section swbva
+.section swbvb
+.section swbwa
+.section swbwb
+.section swbxa
+.section swbxb
+.section swbya
+.section swbyb
+.section swbza
+.section swbzb
+.section swb1a
+.section swb1b
+.section swb2a
+.section swb2b
+.section swb3a
+.section swb3b
+.section swb4a
+.section swb4b
+.section swb5a
+.section swb5b
+.section swb6a
+.section swb6b
+.section swb7a
+.section swb7b
+.section swb8a
+.section swb8b
+.section swb9a
+.section swb9b
+.section swb0a
+.section swb0b
+.section swcaa
+.section swcab
+.section swcba
+.section swcbb
+.section swcca
+.section swccb
+.section swcda
+.section swcdb
+.section swcea
+.section swceb
+.section swcfa
+.section swcfb
+.section swcga
+.section swcgb
+.section swcha
+.section swchb
+.section swcia
+.section swcib
+.section swcja
+.section swcjb
+.section swcka
+.section swckb
+.section swcla
+.section swclb
+.section swcma
+.section swcmb
+.section swcna
+.section swcnb
+.section swcoa
+.section swcob
+.section swcpa
+.section swcpb
+.section swcqa
+.section swcqb
+.section swcra
+.section swcrb
+.section swcsa
+.section swcsb
+.section swcta
+.section swctb
+.section swcua
+.section swcub
+.section swcva
+.section swcvb
+.section swcwa
+.section swcwb
+.section swcxa
+.section swcxb
+.section swcya
+.section swcyb
+.section swcza
+.section swczb
+.section swc1a
+.section swc1b
+.section swc2a
+.section swc2b
+.section swc3a
+.section swc3b
+.section swc4a
+.section swc4b
+.section swc5a
+.section swc5b
+.section swc6a
+.section swc6b
+.section swc7a
+.section swc7b
+.section swc8a
+.section swc8b
+.section swc9a
+.section swc9b
+.section swc0a
+.section swc0b
+.section swdaa
+.section swdab
+.section swdba
+.section swdbb
+.section swdca
+.section swdcb
+.section swdda
+.section swddb
+.section swdea
+.section swdeb
+.section swdfa
+.section swdfb
+.section swdga
+.section swdgb
+.section swdha
+.section swdhb
+.section swdia
+.section swdib
+.section swdja
+.section swdjb
+.section swdka
+.section swdkb
+.section swdla
+.section swdlb
+.section swdma
+.section swdmb
+.section swdna
+.section swdnb
+.section swdoa
+.section swdob
+.section swdpa
+.section swdpb
+.section swdqa
+.section swdqb
+.section swdra
+.section swdrb
+.section swdsa
+.section swdsb
+.section swdta
+.section swdtb
+.section swdua
+.section swdub
+.section swdva
+.section swdvb
+.section swdwa
+.section swdwb
+.section swdxa
+.section swdxb
+.section swdya
+.section swdyb
+.section swdza
+.section swdzb
+.section swd1a
+.section swd1b
+.section swd2a
+.section swd2b
+.section swd3a
+.section swd3b
+.section swd4a
+.section swd4b
+.section swd5a
+.section swd5b
+.section swd6a
+.section swd6b
+.section swd7a
+.section swd7b
+.section swd8a
+.section swd8b
+.section swd9a
+.section swd9b
+.section swd0a
+.section swd0b
+.section sweaa
+.section sweab
+.section sweba
+.section swebb
+.section sweca
+.section swecb
+.section sweda
+.section swedb
+.section sweea
+.section sweeb
+.section swefa
+.section swefb
+.section swega
+.section swegb
+.section sweha
+.section swehb
+.section sweia
+.section sweib
+.section sweja
+.section swejb
+.section sweka
+.section swekb
+.section swela
+.section swelb
+.section swema
+.section swemb
+.section swena
+.section swenb
+.section sweoa
+.section sweob
+.section swepa
+.section swepb
+.section sweqa
+.section sweqb
+.section swera
+.section swerb
+.section swesa
+.section swesb
+.section sweta
+.section swetb
+.section sweua
+.section sweub
+.section sweva
+.section swevb
+.section swewa
+.section swewb
+.section swexa
+.section swexb
+.section sweya
+.section sweyb
+.section sweza
+.section swezb
+.section swe1a
+.section swe1b
+.section swe2a
+.section swe2b
+.section swe3a
+.section swe3b
+.section swe4a
+.section swe4b
+.section swe5a
+.section swe5b
+.section swe6a
+.section swe6b
+.section swe7a
+.section swe7b
+.section swe8a
+.section swe8b
+.section swe9a
+.section swe9b
+.section swe0a
+.section swe0b
+.section swfaa
+.section swfab
+.section swfba
+.section swfbb
+.section swfca
+.section swfcb
+.section swfda
+.section swfdb
+.section swfea
+.section swfeb
+.section swffa
+.section swffb
+.section swfga
+.section swfgb
+.section swfha
+.section swfhb
+.section swfia
+.section swfib
+.section swfja
+.section swfjb
+.section swfka
+.section swfkb
+.section swfla
+.section swflb
+.section swfma
+.section swfmb
+.section swfna
+.section swfnb
+.section swfoa
+.section swfob
+.section swfpa
+.section swfpb
+.section swfqa
+.section swfqb
+.section swfra
+.section swfrb
+.section swfsa
+.section swfsb
+.section swfta
+.section swftb
+.section swfua
+.section swfub
+.section swfva
+.section swfvb
+.section swfwa
+.section swfwb
+.section swfxa
+.section swfxb
+.section swfya
+.section swfyb
+.section swfza
+.section swfzb
+.section swf1a
+.section swf1b
+.section swf2a
+.section swf2b
+.section swf3a
+.section swf3b
+.section swf4a
+.section swf4b
+.section swf5a
+.section swf5b
+.section swf6a
+.section swf6b
+.section swf7a
+.section swf7b
+.section swf8a
+.section swf8b
+.section swf9a
+.section swf9b
+.section swf0a
+.section swf0b
+.section swgaa
+.section swgab
+.section swgba
+.section swgbb
+.section swgca
+.section swgcb
+.section swgda
+.section swgdb
+.section swgea
+.section swgeb
+.section swgfa
+.section swgfb
+.section swgga
+.section swggb
+.section swgha
+.section swghb
+.section swgia
+.section swgib
+.section swgja
+.section swgjb
+.section swgka
+.section swgkb
+.section swgla
+.section swglb
+.section swgma
+.section swgmb
+.section swgna
+.section swgnb
+.section swgoa
+.section swgob
+.section swgpa
+.section swgpb
+.section swgqa
+.section swgqb
+.section swgra
+.section swgrb
+.section swgsa
+.section swgsb
+.section swgta
+.section swgtb
+.section swgua
+.section swgub
+.section swgva
+.section swgvb
+.section swgwa
+.section swgwb
+.section swgxa
+.section swgxb
+.section swgya
+.section swgyb
+.section swgza
+.section swgzb
+.section swg1a
+.section swg1b
+.section swg2a
+.section swg2b
+.section swg3a
+.section swg3b
+.section swg4a
+.section swg4b
+.section swg5a
+.section swg5b
+.section swg6a
+.section swg6b
+.section swg7a
+.section swg7b
+.section swg8a
+.section swg8b
+.section swg9a
+.section swg9b
+.section swg0a
+.section swg0b
+.section swhaa
+.section swhab
+.section swhba
+.section swhbb
+.section swhca
+.section swhcb
+.section swhda
+.section swhdb
+.section swhea
+.section swheb
+.section swhfa
+.section swhfb
+.section swhga
+.section swhgb
+.section swhha
+.section swhhb
+.section swhia
+.section swhib
+.section swhja
+.section swhjb
+.section swhka
+.section swhkb
+.section swhla
+.section swhlb
+.section swhma
+.section swhmb
+.section swhna
+.section swhnb
+.section swhoa
+.section swhob
+.section swhpa
+.section swhpb
+.section swhqa
+.section swhqb
+.section swhra
+.section swhrb
+.section swhsa
+.section swhsb
+.section swhta
+.section swhtb
+.section swhua
+.section swhub
+.section swhva
+.section swhvb
+.section swhwa
+.section swhwb
+.section swhxa
+.section swhxb
+.section swhya
+.section swhyb
+.section swhza
+.section swhzb
+.section swh1a
+.section swh1b
+.section swh2a
+.section swh2b
+.section swh3a
+.section swh3b
+.section swh4a
+.section swh4b
+.section swh5a
+.section swh5b
+.section swh6a
+.section swh6b
+.section swh7a
+.section swh7b
+.section swh8a
+.section swh8b
+.section swh9a
+.section swh9b
+.section swh0a
+.section swh0b
+.section swiaa
+.section swiab
+.section swiba
+.section swibb
+.section swica
+.section swicb
+.section swida
+.section swidb
+.section swiea
+.section swieb
+.section swifa
+.section swifb
+.section swiga
+.section swigb
+.section swiha
+.section swihb
+.section swiia
+.section swiib
+.section swija
+.section swijb
+.section swika
+.section swikb
+.section swila
+.section swilb
+.section swima
+.section swimb
+.section swina
+.section swinb
+.section swioa
+.section swiob
+.section swipa
+.section swipb
+.section swiqa
+.section swiqb
+.section swira
+.section swirb
+.section swisa
+.section swisb
+.section swita
+.section switb
+.section swiua
+.section swiub
+.section swiva
+.section swivb
+.section swiwa
+.section swiwb
+.section swixa
+.section swixb
+.section swiya
+.section swiyb
+.section swiza
+.section swizb
+.section swi1a
+.section swi1b
+.section swi2a
+.section swi2b
+.section swi3a
+.section swi3b
+.section swi4a
+.section swi4b
+.section swi5a
+.section swi5b
+.section swi6a
+.section swi6b
+.section swi7a
+.section swi7b
+.section swi8a
+.section swi8b
+.section swi9a
+.section swi9b
+.section swi0a
+.section swi0b
+.section swjaa
+.section swjab
+.section swjba
+.section swjbb
+.section swjca
+.section swjcb
+.section swjda
+.section swjdb
+.section swjea
+.section swjeb
+.section swjfa
+.section swjfb
+.section swjga
+.section swjgb
+.section swjha
+.section swjhb
+.section swjia
+.section swjib
+.section swjja
+.section swjjb
+.section swjka
+.section swjkb
+.section swjla
+.section swjlb
+.section swjma
+.section swjmb
+.section swjna
+.section swjnb
+.section swjoa
+.section swjob
+.section swjpa
+.section swjpb
+.section swjqa
+.section swjqb
+.section swjra
+.section swjrb
+.section swjsa
+.section swjsb
+.section swjta
+.section swjtb
+.section swjua
+.section swjub
+.section swjva
+.section swjvb
+.section swjwa
+.section swjwb
+.section swjxa
+.section swjxb
+.section swjya
+.section swjyb
+.section swjza
+.section swjzb
+.section swj1a
+.section swj1b
+.section swj2a
+.section swj2b
+.section swj3a
+.section swj3b
+.section swj4a
+.section swj4b
+.section swj5a
+.section swj5b
+.section swj6a
+.section swj6b
+.section swj7a
+.section swj7b
+.section swj8a
+.section swj8b
+.section swj9a
+.section swj9b
+.section swj0a
+.section swj0b
+.section swkaa
+.section swkab
+.section swkba
+.section swkbb
+.section swkca
+.section swkcb
+.section swkda
+.section swkdb
+.section swkea
+.section swkeb
+.section swkfa
+.section swkfb
+.section swkga
+.section swkgb
+.section swkha
+.section swkhb
+.section swkia
+.section swkib
+.section swkja
+.section swkjb
+.section swkka
+.section swkkb
+.section swkla
+.section swklb
+.section swkma
+.section swkmb
+.section swkna
+.section swknb
+.section swkoa
+.section swkob
+.section swkpa
+.section swkpb
+.section swkqa
+.section swkqb
+.section swkra
+.section swkrb
+.section swksa
+.section swksb
+.section swkta
+.section swktb
+.section swkua
+.section swkub
+.section swkva
+.section swkvb
+.section swkwa
+.section swkwb
+.section swkxa
+.section swkxb
+.section swkya
+.section swkyb
+.section swkza
+.section swkzb
+.section swk1a
+.section swk1b
+.section swk2a
+.section swk2b
+.section swk3a
+.section swk3b
+.section swk4a
+.section swk4b
+.section swk5a
+.section swk5b
+.section swk6a
+.section swk6b
+.section swk7a
+.section swk7b
+.section swk8a
+.section swk8b
+.section swk9a
+.section swk9b
+.section swk0a
+.section swk0b
+.section swlaa
+.section swlab
+.section swlba
+.section swlbb
+.section swlca
+.section swlcb
+.section swlda
+.section swldb
+.section swlea
+.section swleb
+.section swlfa
+.section swlfb
+.section swlga
+.section swlgb
+.section swlha
+.section swlhb
+.section swlia
+.section swlib
+.section swlja
+.section swljb
+.section swlka
+.section swlkb
+.section swlla
+.section swllb
+.section swlma
+.section swlmb
+.section swlna
+.section swlnb
+.section swloa
+.section swlob
+.section swlpa
+.section swlpb
+.section swlqa
+.section swlqb
+.section swlra
+.section swlrb
+.section swlsa
+.section swlsb
+.section swlta
+.section swltb
+.section swlua
+.section swlub
+.section swlva
+.section swlvb
+.section swlwa
+.section swlwb
+.section swlxa
+.section swlxb
+.section swlya
+.section swlyb
+.section swlza
+.section swlzb
+.section swl1a
+.section swl1b
+.section swl2a
+.section swl2b
+.section swl3a
+.section swl3b
+.section swl4a
+.section swl4b
+.section swl5a
+.section swl5b
+.section swl6a
+.section swl6b
+.section swl7a
+.section swl7b
+.section swl8a
+.section swl8b
+.section swl9a
+.section swl9b
+.section swl0a
+.section swl0b
+.section swmaa
+.section swmab
+.section swmba
+.section swmbb
+.section swmca
+.section swmcb
+.section swmda
+.section swmdb
+.section swmea
+.section swmeb
+.section swmfa
+.section swmfb
+.section swmga
+.section swmgb
+.section swmha
+.section swmhb
+.section swmia
+.section swmib
+.section swmja
+.section swmjb
+.section swmka
+.section swmkb
+.section swmla
+.section swmlb
+.section swmma
+.section swmmb
+.section swmna
+.section swmnb
+.section swmoa
+.section swmob
+.section swmpa
+.section swmpb
+.section swmqa
+.section swmqb
+.section swmra
+.section swmrb
+.section swmsa
+.section swmsb
+.section swmta
+.section swmtb
+.section swmua
+.section swmub
+.section swmva
+.section swmvb
+.section swmwa
+.section swmwb
+.section swmxa
+.section swmxb
+.section swmya
+.section swmyb
+.section swmza
+.section swmzb
+.section swm1a
+.section swm1b
+.section swm2a
+.section swm2b
+.section swm3a
+.section swm3b
+.section swm4a
+.section swm4b
+.section swm5a
+.section swm5b
+.section swm6a
+.section swm6b
+.section swm7a
+.section swm7b
+.section swm8a
+.section swm8b
+.section swm9a
+.section swm9b
+.section swm0a
+.section swm0b
+.section swnaa
+.section swnab
+.section swnba
+.section swnbb
+.section swnca
+.section swncb
+.section swnda
+.section swndb
+.section swnea
+.section swneb
+.section swnfa
+.section swnfb
+.section swnga
+.section swngb
+.section swnha
+.section swnhb
+.section swnia
+.section swnib
+.section swnja
+.section swnjb
+.section swnka
+.section swnkb
+.section swnla
+.section swnlb
+.section swnma
+.section swnmb
+.section swnna
+.section swnnb
+.section swnoa
+.section swnob
+.section swnpa
+.section swnpb
+.section swnqa
+.section swnqb
+.section swnra
+.section swnrb
+.section swnsa
+.section swnsb
+.section swnta
+.section swntb
+.section swnua
+.section swnub
+.section swnva
+.section swnvb
+.section swnwa
+.section swnwb
+.section swnxa
+.section swnxb
+.section swnya
+.section swnyb
+.section swnza
+.section swnzb
+.section swn1a
+.section swn1b
+.section swn2a
+.section swn2b
+.section swn3a
+.section swn3b
+.section swn4a
+.section swn4b
+.section swn5a
+.section swn5b
+.section swn6a
+.section swn6b
+.section swn7a
+.section swn7b
+.section swn8a
+.section swn8b
+.section swn9a
+.section swn9b
+.section swn0a
+.section swn0b
+.section swoaa
+.section swoab
+.section swoba
+.section swobb
+.section swoca
+.section swocb
+.section swoda
+.section swodb
+.section swoea
+.section swoeb
+.section swofa
+.section swofb
+.section swoga
+.section swogb
+.section swoha
+.section swohb
+.section swoia
+.section swoib
+.section swoja
+.section swojb
+.section swoka
+.section swokb
+.section swola
+.section swolb
+.section swoma
+.section swomb
+.section swona
+.section swonb
+.section swooa
+.section swoob
+.section swopa
+.section swopb
+.section swoqa
+.section swoqb
+.section swora
+.section sworb
+.section swosa
+.section swosb
+.section swota
+.section swotb
+.section swoua
+.section swoub
+.section swova
+.section swovb
+.section swowa
+.section swowb
+.section swoxa
+.section swoxb
+.section swoya
+.section swoyb
+.section swoza
+.section swozb
+.section swo1a
+.section swo1b
+.section swo2a
+.section swo2b
+.section swo3a
+.section swo3b
+.section swo4a
+.section swo4b
+.section swo5a
+.section swo5b
+.section swo6a
+.section swo6b
+.section swo7a
+.section swo7b
+.section swo8a
+.section swo8b
+.section swo9a
+.section swo9b
+.section swo0a
+.section swo0b
+.section swpaa
+.section swpab
+.section swpba
+.section swpbb
+.section swpca
+.section swpcb
+.section swpda
+.section swpdb
+.section swpea
+.section swpeb
+.section swpfa
+.section swpfb
+.section swpga
+.section swpgb
+.section swpha
+.section swphb
+.section swpia
+.section swpib
+.section swpja
+.section swpjb
+.section swpka
+.section swpkb
+.section swpla
+.section swplb
+.section swpma
+.section swpmb
+.section swpna
+.section swpnb
+.section swpoa
+.section swpob
+.section swppa
+.section swppb
+.section swpqa
+.section swpqb
+.section swpra
+.section swprb
+.section swpsa
+.section swpsb
+.section swpta
+.section swptb
+.section swpua
+.section swpub
+.section swpva
+.section swpvb
+.section swpwa
+.section swpwb
+.section swpxa
+.section swpxb
+.section swpya
+.section swpyb
+.section swpza
+.section swpzb
+.section swp1a
+.section swp1b
+.section swp2a
+.section swp2b
+.section swp3a
+.section swp3b
+.section swp4a
+.section swp4b
+.section swp5a
+.section swp5b
+.section swp6a
+.section swp6b
+.section swp7a
+.section swp7b
+.section swp8a
+.section swp8b
+.section swp9a
+.section swp9b
+.section swp0a
+.section swp0b
+.section swqaa
+.section swqab
+.section swqba
+.section swqbb
+.section swqca
+.section swqcb
+.section swqda
+.section swqdb
+.section swqea
+.section swqeb
+.section swqfa
+.section swqfb
+.section swqga
+.section swqgb
+.section swqha
+.section swqhb
+.section swqia
+.section swqib
+.section swqja
+.section swqjb
+.section swqka
+.section swqkb
+.section swqla
+.section swqlb
+.section swqma
+.section swqmb
+.section swqna
+.section swqnb
+.section swqoa
+.section swqob
+.section swqpa
+.section swqpb
+.section swqqa
+.section swqqb
+.section swqra
+.section swqrb
+.section swqsa
+.section swqsb
+.section swqta
+.section swqtb
+.section swqua
+.section swqub
+.section swqva
+.section swqvb
+.section swqwa
+.section swqwb
+.section swqxa
+.section swqxb
+.section swqya
+.section swqyb
+.section swqza
+.section swqzb
+.section swq1a
+.section swq1b
+.section swq2a
+.section swq2b
+.section swq3a
+.section swq3b
+.section swq4a
+.section swq4b
+.section swq5a
+.section swq5b
+.section swq6a
+.section swq6b
+.section swq7a
+.section swq7b
+.section swq8a
+.section swq8b
+.section swq9a
+.section swq9b
+.section swq0a
+.section swq0b
+.section swraa
+.section swrab
+.section swrba
+.section swrbb
+.section swrca
+.section swrcb
+.section swrda
+.section swrdb
+.section swrea
+.section swreb
+.section swrfa
+.section swrfb
+.section swrga
+.section swrgb
+.section swrha
+.section swrhb
+.section swria
+.section swrib
+.section swrja
+.section swrjb
+.section swrka
+.section swrkb
+.section swrla
+.section swrlb
+.section swrma
+.section swrmb
+.section swrna
+.section swrnb
+.section swroa
+.section swrob
+.section swrpa
+.section swrpb
+.section swrqa
+.section swrqb
+.section swrra
+.section swrrb
+.section swrsa
+.section swrsb
+.section swrta
+.section swrtb
+.section swrua
+.section swrub
+.section swrva
+.section swrvb
+.section swrwa
+.section swrwb
+.section swrxa
+.section swrxb
+.section swrya
+.section swryb
+.section swrza
+.section swrzb
+.section swr1a
+.section swr1b
+.section swr2a
+.section swr2b
+.section swr3a
+.section swr3b
+.section swr4a
+.section swr4b
+.section swr5a
+.section swr5b
+.section swr6a
+.section swr6b
+.section swr7a
+.section swr7b
+.section swr8a
+.section swr8b
+.section swr9a
+.section swr9b
+.section swr0a
+.section swr0b
+.section swsaa
+.section swsab
+.section swsba
+.section swsbb
+.section swsca
+.section swscb
+.section swsda
+.section swsdb
+.section swsea
+.section swseb
+.section swsfa
+.section swsfb
+.section swsga
+.section swsgb
+.section swsha
+.section swshb
+.section swsia
+.section swsib
+.section swsja
+.section swsjb
+.section swska
+.section swskb
+.section swsla
+.section swslb
+.section swsma
+.section swsmb
+.section swsna
+.section swsnb
+.section swsoa
+.section swsob
+.section swspa
+.section swspb
+.section swsqa
+.section swsqb
+.section swsra
+.section swsrb
+.section swssa
+.section swssb
+.section swsta
+.section swstb
+.section swsua
+.section swsub
+.section swsva
+.section swsvb
+.section swswa
+.section swswb
+.section swsxa
+.section swsxb
+.section swsya
+.section swsyb
+.section swsza
+.section swszb
+.section sws1a
+.section sws1b
+.section sws2a
+.section sws2b
+.section sws3a
+.section sws3b
+.section sws4a
+.section sws4b
+.section sws5a
+.section sws5b
+.section sws6a
+.section sws6b
+.section sws7a
+.section sws7b
+.section sws8a
+.section sws8b
+.section sws9a
+.section sws9b
+.section sws0a
+.section sws0b
+.section swtaa
+.section swtab
+.section swtba
+.section swtbb
+.section swtca
+.section swtcb
+.section swtda
+.section swtdb
+.section swtea
+.section swteb
+.section swtfa
+.section swtfb
+.section swtga
+.section swtgb
+.section swtha
+.section swthb
+.section swtia
+.section swtib
+.section swtja
+.section swtjb
+.section swtka
+.section swtkb
+.section swtla
+.section swtlb
+.section swtma
+.section swtmb
+.section swtna
+.section swtnb
+.section swtoa
+.section swtob
+.section swtpa
+.section swtpb
+.section swtqa
+.section swtqb
+.section swtra
+.section swtrb
+.section swtsa
+.section swtsb
+.section swtta
+.section swttb
+.section swtua
+.section swtub
+.section swtva
+.section swtvb
+.section swtwa
+.section swtwb
+.section swtxa
+.section swtxb
+.section swtya
+.section swtyb
+.section swtza
+.section swtzb
+.section swt1a
+.section swt1b
+.section swt2a
+.section swt2b
+.section swt3a
+.section swt3b
+.section swt4a
+.section swt4b
+.section swt5a
+.section swt5b
+.section swt6a
+.section swt6b
+.section swt7a
+.section swt7b
+.section swt8a
+.section swt8b
+.section swt9a
+.section swt9b
+.section swt0a
+.section swt0b
+.section swuaa
+.section swuab
+.section swuba
+.section swubb
+.section swuca
+.section swucb
+.section swuda
+.section swudb
+.section swuea
+.section swueb
+.section swufa
+.section swufb
+.section swuga
+.section swugb
+.section swuha
+.section swuhb
+.section swuia
+.section swuib
+.section swuja
+.section swujb
+.section swuka
+.section swukb
+.section swula
+.section swulb
+.section swuma
+.section swumb
+.section swuna
+.section swunb
+.section swuoa
+.section swuob
+.section swupa
+.section swupb
+.section swuqa
+.section swuqb
+.section swura
+.section swurb
+.section swusa
+.section swusb
+.section swuta
+.section swutb
+.section swuua
+.section swuub
+.section swuva
+.section swuvb
+.section swuwa
+.section swuwb
+.section swuxa
+.section swuxb
+.section swuya
+.section swuyb
+.section swuza
+.section swuzb
+.section swu1a
+.section swu1b
+.section swu2a
+.section swu2b
+.section swu3a
+.section swu3b
+.section swu4a
+.section swu4b
+.section swu5a
+.section swu5b
+.section swu6a
+.section swu6b
+.section swu7a
+.section swu7b
+.section swu8a
+.section swu8b
+.section swu9a
+.section swu9b
+.section swu0a
+.section swu0b
+.section swvaa
+.section swvab
+.section swvba
+.section swvbb
+.section swvca
+.section swvcb
+.section swvda
+.section swvdb
+.section swvea
+.section swveb
+.section swvfa
+.section swvfb
+.section swvga
+.section swvgb
+.section swvha
+.section swvhb
+.section swvia
+.section swvib
+.section swvja
+.section swvjb
+.section swvka
+.section swvkb
+.section swvla
+.section swvlb
+.section swvma
+.section swvmb
+.section swvna
+.section swvnb
+.section swvoa
+.section swvob
+.section swvpa
+.section swvpb
+.section swvqa
+.section swvqb
+.section swvra
+.section swvrb
+.section swvsa
+.section swvsb
+.section swvta
+.section swvtb
+.section swvua
+.section swvub
+.section swvva
+.section swvvb
+.section swvwa
+.section swvwb
+.section swvxa
+.section swvxb
+.section swvya
+.section swvyb
+.section swvza
+.section swvzb
+.section swv1a
+.section swv1b
+.section swv2a
+.section swv2b
+.section swv3a
+.section swv3b
+.section swv4a
+.section swv4b
+.section swv5a
+.section swv5b
+.section swv6a
+.section swv6b
+.section swv7a
+.section swv7b
+.section swv8a
+.section swv8b
+.section swv9a
+.section swv9b
+.section swv0a
+.section swv0b
+.section swwaa
+.section swwab
+.section swwba
+.section swwbb
+.section swwca
+.section swwcb
+.section swwda
+.section swwdb
+.section swwea
+.section swweb
+.section swwfa
+.section swwfb
+.section swwga
+.section swwgb
+.section swwha
+.section swwhb
+.section swwia
+.section swwib
+.section swwja
+.section swwjb
+.section swwka
+.section swwkb
+.section swwla
+.section swwlb
+.section swwma
+.section swwmb
+.section swwna
+.section swwnb
+.section swwoa
+.section swwob
+.section swwpa
+.section swwpb
+.section swwqa
+.section swwqb
+.section swwra
+.section swwrb
+.section swwsa
+.section swwsb
+.section swwta
+.section swwtb
+.section swwua
+.section swwub
+.section swwva
+.section swwvb
+.section swwwa
+.section swwwb
+.section swwxa
+.section swwxb
+.section swwya
+.section swwyb
+.section swwza
+.section swwzb
+.section sww1a
+.section sww1b
+.section sww2a
+.section sww2b
+.section sww3a
+.section sww3b
+.section sww4a
+.section sww4b
+.section sww5a
+.section sww5b
+.section sww6a
+.section sww6b
+.section sww7a
+.section sww7b
+.section sww8a
+.section sww8b
+.section sww9a
+.section sww9b
+.section sww0a
+.section sww0b
+.section swxaa
+.section swxab
+.section swxba
+.section swxbb
+.section swxca
+.section swxcb
+.section swxda
+.section swxdb
+.section swxea
+.section swxeb
+.section swxfa
+.section swxfb
+.section swxga
+.section swxgb
+.section swxha
+.section swxhb
+.section swxia
+.section swxib
+.section swxja
+.section swxjb
+.section swxka
+.section swxkb
+.section swxla
+.section swxlb
+.section swxma
+.section swxmb
+.section swxna
+.section swxnb
+.section swxoa
+.section swxob
+.section swxpa
+.section swxpb
+.section swxqa
+.section swxqb
+.section swxra
+.section swxrb
+.section swxsa
+.section swxsb
+.section swxta
+.section swxtb
+.section swxua
+.section swxub
+.section swxva
+.section swxvb
+.section swxwa
+.section swxwb
+.section swxxa
+.section swxxb
+.section swxya
+.section swxyb
+.section swxza
+.section swxzb
+.section swx1a
+.section swx1b
+.section swx2a
+.section swx2b
+.section swx3a
+.section swx3b
+.section swx4a
+.section swx4b
+.section swx5a
+.section swx5b
+.section swx6a
+.section swx6b
+.section swx7a
+.section swx7b
+.section swx8a
+.section swx8b
+.section swx9a
+.section swx9b
+.section swx0a
+.section swx0b
+.section swyaa
+.section swyab
+.section swyba
+.section swybb
+.section swyca
+.section swycb
+.section swyda
+.section swydb
+.section swyea
+.section swyeb
+.section swyfa
+.section swyfb
+.section swyga
+.section swygb
+.section swyha
+.section swyhb
+.section swyia
+.section swyib
+.section swyja
+.section swyjb
+.section swyka
+.section swykb
+.section swyla
+.section swylb
+.section swyma
+.section swymb
+.section swyna
+.section swynb
+.section swyoa
+.section swyob
+.section swypa
+.section swypb
+.section swyqa
+.section swyqb
+.section swyra
+.section swyrb
+.section swysa
+.section swysb
+.section swyta
+.section swytb
+.section swyua
+.section swyub
+.section swyva
+.section swyvb
+.section swywa
+.section swywb
+.section swyxa
+.section swyxb
+.section swyya
+.section swyyb
+.section swyza
+.section swyzb
+.section swy1a
+.section swy1b
+.section swy2a
+.section swy2b
+.section swy3a
+.section swy3b
+.section swy4a
+.section swy4b
+.section swy5a
+.section swy5b
+.section swy6a
+.section swy6b
+.section swy7a
+.section swy7b
+.section swy8a
+.section swy8b
+.section swy9a
+.section swy9b
+.section swy0a
+.section swy0b
+.section swzaa
+.section swzab
+.section swzba
+.section swzbb
+.section swzca
+.section swzcb
+.section swzda
+.section swzdb
+.section swzea
+.section swzeb
+.section swzfa
+.section swzfb
+.section swzga
+.section swzgb
+.section swzha
+.section swzhb
+.section swzia
+.section swzib
+.section swzja
+.section swzjb
+.section swzka
+.section swzkb
+.section swzla
+.section swzlb
+.section swzma
+.section swzmb
+.section swzna
+.section swznb
+.section swzoa
+.section swzob
+.section swzpa
+.section swzpb
+.section swzqa
+.section swzqb
+.section swzra
+.section swzrb
+.section swzsa
+.section swzsb
+.section swzta
+.section swztb
+.section swzua
+.section swzub
+.section swzva
+.section swzvb
+.section swzwa
+.section swzwb
+.section swzxa
+.section swzxb
+.section swzya
+.section swzyb
+.section swzza
+.section swzzb
+.section swz1a
+.section swz1b
+.section swz2a
+.section swz2b
+.section swz3a
+.section swz3b
+.section swz4a
+.section swz4b
+.section swz5a
+.section swz5b
+.section swz6a
+.section swz6b
+.section swz7a
+.section swz7b
+.section swz8a
+.section swz8b
+.section swz9a
+.section swz9b
+.section swz0a
+.section swz0b
+.section sw1aa
+.section sw1ab
+.section sw1ba
+.section sw1bb
+.section sw1ca
+.section sw1cb
+.section sw1da
+.section sw1db
+.section sw1ea
+.section sw1eb
+.section sw1fa
+.section sw1fb
+.section sw1ga
+.section sw1gb
+.section sw1ha
+.section sw1hb
+.section sw1ia
+.section sw1ib
+.section sw1ja
+.section sw1jb
+.section sw1ka
+.section sw1kb
+.section sw1la
+.section sw1lb
+.section sw1ma
+.section sw1mb
+.section sw1na
+.section sw1nb
+.section sw1oa
+.section sw1ob
+.section sw1pa
+.section sw1pb
+.section sw1qa
+.section sw1qb
+.section sw1ra
+.section sw1rb
+.section sw1sa
+.section sw1sb
+.section sw1ta
+.section sw1tb
+.section sw1ua
+.section sw1ub
+.section sw1va
+.section sw1vb
+.section sw1wa
+.section sw1wb
+.section sw1xa
+.section sw1xb
+.section sw1ya
+.section sw1yb
+.section sw1za
+.section sw1zb
+.section sw11a
+.section sw11b
+.section sw12a
+.section sw12b
+.section sw13a
+.section sw13b
+.section sw14a
+.section sw14b
+.section sw15a
+.section sw15b
+.section sw16a
+.section sw16b
+.section sw17a
+.section sw17b
+.section sw18a
+.section sw18b
+.section sw19a
+.section sw19b
+.section sw10a
+.section sw10b
+.section sw2aa
+.section sw2ab
+.section sw2ba
+.section sw2bb
+.section sw2ca
+.section sw2cb
+.section sw2da
+.section sw2db
+.section sw2ea
+.section sw2eb
+.section sw2fa
+.section sw2fb
+.section sw2ga
+.section sw2gb
+.section sw2ha
+.section sw2hb
+.section sw2ia
+.section sw2ib
+.section sw2ja
+.section sw2jb
+.section sw2ka
+.section sw2kb
+.section sw2la
+.section sw2lb
+.section sw2ma
+.section sw2mb
+.section sw2na
+.section sw2nb
+.section sw2oa
+.section sw2ob
+.section sw2pa
+.section sw2pb
+.section sw2qa
+.section sw2qb
+.section sw2ra
+.section sw2rb
+.section sw2sa
+.section sw2sb
+.section sw2ta
+.section sw2tb
+.section sw2ua
+.section sw2ub
+.section sw2va
+.section sw2vb
+.section sw2wa
+.section sw2wb
+.section sw2xa
+.section sw2xb
+.section sw2ya
+.section sw2yb
+.section sw2za
+.section sw2zb
+.section sw21a
+.section sw21b
+.section sw22a
+.section sw22b
+.section sw23a
+.section sw23b
+.section sw24a
+.section sw24b
+.section sw25a
+.section sw25b
+.section sw26a
+.section sw26b
+.section sw27a
+.section sw27b
+.section sw28a
+.section sw28b
+.section sw29a
+.section sw29b
+.section sw20a
+.section sw20b
+.section sw3aa
+.section sw3ab
+.section sw3ba
+.section sw3bb
+.section sw3ca
+.section sw3cb
+.section sw3da
+.section sw3db
+.section sw3ea
+.section sw3eb
+.section sw3fa
+.section sw3fb
+.section sw3ga
+.section sw3gb
+.section sw3ha
+.section sw3hb
+.section sw3ia
+.section sw3ib
+.section sw3ja
+.section sw3jb
+.section sw3ka
+.section sw3kb
+.section sw3la
+.section sw3lb
+.section sw3ma
+.section sw3mb
+.section sw3na
+.section sw3nb
+.section sw3oa
+.section sw3ob
+.section sw3pa
+.section sw3pb
+.section sw3qa
+.section sw3qb
+.section sw3ra
+.section sw3rb
+.section sw3sa
+.section sw3sb
+.section sw3ta
+.section sw3tb
+.section sw3ua
+.section sw3ub
+.section sw3va
+.section sw3vb
+.section sw3wa
+.section sw3wb
+.section sw3xa
+.section sw3xb
+.section sw3ya
+.section sw3yb
+.section sw3za
+.section sw3zb
+.section sw31a
+.section sw31b
+.section sw32a
+.section sw32b
+.section sw33a
+.section sw33b
+.section sw34a
+.section sw34b
+.section sw35a
+.section sw35b
+.section sw36a
+.section sw36b
+.section sw37a
+.section sw37b
+.section sw38a
+.section sw38b
+.section sw39a
+.section sw39b
+.section sw30a
+.section sw30b
+.section sw4aa
+.section sw4ab
+.section sw4ba
+.section sw4bb
+.section sw4ca
+.section sw4cb
+.section sw4da
+.section sw4db
+.section sw4ea
+.section sw4eb
+.section sw4fa
+.section sw4fb
+.section sw4ga
+.section sw4gb
+.section sw4ha
+.section sw4hb
+.section sw4ia
+.section sw4ib
+.section sw4ja
+.section sw4jb
+.section sw4ka
+.section sw4kb
+.section sw4la
+.section sw4lb
+.section sw4ma
+.section sw4mb
+.section sw4na
+.section sw4nb
+.section sw4oa
+.section sw4ob
+.section sw4pa
+.section sw4pb
+.section sw4qa
+.section sw4qb
+.section sw4ra
+.section sw4rb
+.section sw4sa
+.section sw4sb
+.section sw4ta
+.section sw4tb
+.section sw4ua
+.section sw4ub
+.section sw4va
+.section sw4vb
+.section sw4wa
+.section sw4wb
+.section sw4xa
+.section sw4xb
+.section sw4ya
+.section sw4yb
+.section sw4za
+.section sw4zb
+.section sw41a
+.section sw41b
+.section sw42a
+.section sw42b
+.section sw43a
+.section sw43b
+.section sw44a
+.section sw44b
+.section sw45a
+.section sw45b
+.section sw46a
+.section sw46b
+.section sw47a
+.section sw47b
+.section sw48a
+.section sw48b
+.section sw49a
+.section sw49b
+.section sw40a
+.section sw40b
+.section sw5aa
+.section sw5ab
+.section sw5ba
+.section sw5bb
+.section sw5ca
+.section sw5cb
+.section sw5da
+.section sw5db
+.section sw5ea
+.section sw5eb
+.section sw5fa
+.section sw5fb
+.section sw5ga
+.section sw5gb
+.section sw5ha
+.section sw5hb
+.section sw5ia
+.section sw5ib
+.section sw5ja
+.section sw5jb
+.section sw5ka
+.section sw5kb
+.section sw5la
+.section sw5lb
+.section sw5ma
+.section sw5mb
+.section sw5na
+.section sw5nb
+.section sw5oa
+.section sw5ob
+.section sw5pa
+.section sw5pb
+.section sw5qa
+.section sw5qb
+.section sw5ra
+.section sw5rb
+.section sw5sa
+.section sw5sb
+.section sw5ta
+.section sw5tb
+.section sw5ua
+.section sw5ub
+.section sw5va
+.section sw5vb
+.section sw5wa
+.section sw5wb
+.section sw5xa
+.section sw5xb
+.section sw5ya
+.section sw5yb
+.section sw5za
+.section sw5zb
+.section sw51a
+.section sw51b
+.section sw52a
+.section sw52b
+.section sw53a
+.section sw53b
+.section sw54a
+.section sw54b
+.section sw55a
+.section sw55b
+.section sw56a
+.section sw56b
+.section sw57a
+.section sw57b
+.section sw58a
+.section sw58b
+.section sw59a
+.section sw59b
+.section sw50a
+.section sw50b
+.section sw6aa
+.section sw6ab
+.section sw6ba
+.section sw6bb
+.section sw6ca
+.section sw6cb
+.section sw6da
+.section sw6db
+.section sw6ea
+.section sw6eb
+.section sw6fa
+.section sw6fb
+.section sw6ga
+.section sw6gb
+.section sw6ha
+.section sw6hb
+.section sw6ia
+.section sw6ib
+.section sw6ja
+.section sw6jb
+.section sw6ka
+.section sw6kb
+.section sw6la
+.section sw6lb
+.section sw6ma
+.section sw6mb
+.section sw6na
+.section sw6nb
+.section sw6oa
+.section sw6ob
+.section sw6pa
+.section sw6pb
+.section sw6qa
+.section sw6qb
+.section sw6ra
+.section sw6rb
+.section sw6sa
+.section sw6sb
+.section sw6ta
+.section sw6tb
+.section sw6ua
+.section sw6ub
+.section sw6va
+.section sw6vb
+.section sw6wa
+.section sw6wb
+.section sw6xa
+.section sw6xb
+.section sw6ya
+.section sw6yb
+.section sw6za
+.section sw6zb
+.section sw61a
+.section sw61b
+.section sw62a
+.section sw62b
+.section sw63a
+.section sw63b
+.section sw64a
+.section sw64b
+.section sw65a
+.section sw65b
+.section sw66a
+.section sw66b
+.section sw67a
+.section sw67b
+.section sw68a
+.section sw68b
+.section sw69a
+.section sw69b
+.section sw60a
+.section sw60b
+.section sw7aa
+.section sw7ab
+.section sw7ba
+.section sw7bb
+.section sw7ca
+.section sw7cb
+.section sw7da
+.section sw7db
+.section sw7ea
+.section sw7eb
+.section sw7fa
+.section sw7fb
+.section sw7ga
+.section sw7gb
+.section sw7ha
+.section sw7hb
+.section sw7ia
+.section sw7ib
+.section sw7ja
+.section sw7jb
+.section sw7ka
+.section sw7kb
+.section sw7la
+.section sw7lb
+.section sw7ma
+.section sw7mb
+.section sw7na
+.section sw7nb
+.section sw7oa
+.section sw7ob
+.section sw7pa
+.section sw7pb
+.section sw7qa
+.section sw7qb
+.section sw7ra
+.section sw7rb
+.section sw7sa
+.section sw7sb
+.section sw7ta
+.section sw7tb
+.section sw7ua
+.section sw7ub
+.section sw7va
+.section sw7vb
+.section sw7wa
+.section sw7wb
+.section sw7xa
+.section sw7xb
+.section sw7ya
+.section sw7yb
+.section sw7za
+.section sw7zb
+.section sw71a
+.section sw71b
+.section sw72a
+.section sw72b
+.section sw73a
+.section sw73b
+.section sw74a
+.section sw74b
+.section sw75a
+.section sw75b
+.section sw76a
+.section sw76b
+.section sw77a
+.section sw77b
+.section sw78a
+.section sw78b
+.section sw79a
+.section sw79b
+.section sw70a
+.section sw70b
+.section sw8aa
+.section sw8ab
+.section sw8ba
+.section sw8bb
+.section sw8ca
+.section sw8cb
+.section sw8da
+.section sw8db
+.section sw8ea
+.section sw8eb
+.section sw8fa
+.section sw8fb
+.section sw8ga
+.section sw8gb
+.section sw8ha
+.section sw8hb
+.section sw8ia
+.section sw8ib
+.section sw8ja
+.section sw8jb
+.section sw8ka
+.section sw8kb
+.section sw8la
+.section sw8lb
+.section sw8ma
+.section sw8mb
+.section sw8na
+.section sw8nb
+.section sw8oa
+.section sw8ob
+.section sw8pa
+.section sw8pb
+.section sw8qa
+.section sw8qb
+.section sw8ra
+.section sw8rb
+.section sw8sa
+.section sw8sb
+.section sw8ta
+.section sw8tb
+.section sw8ua
+.section sw8ub
+.section sw8va
+.section sw8vb
+.section sw8wa
+.section sw8wb
+.section sw8xa
+.section sw8xb
+.section sw8ya
+.section sw8yb
+.section sw8za
+.section sw8zb
+.section sw81a
+.section sw81b
+.section sw82a
+.section sw82b
+.section sw83a
+.section sw83b
+.section sw84a
+.section sw84b
+.section sw85a
+.section sw85b
+.section sw86a
+.section sw86b
+.section sw87a
+.section sw87b
+.section sw88a
+.section sw88b
+.section sw89a
+.section sw89b
+.section sw80a
+.section sw80b
+.section sw9aa
+.section sw9ab
+.section sw9ba
+.section sw9bb
+.section sw9ca
+.section sw9cb
+.section sw9da
+.section sw9db
+.section sw9ea
+.section sw9eb
+.section sw9fa
+.section sw9fb
+.section sw9ga
+.section sw9gb
+.section sw9ha
+.section sw9hb
+.section sw9ia
+.section sw9ib
+.section sw9ja
+.section sw9jb
+.section sw9ka
+.section sw9kb
+.section sw9la
+.section sw9lb
+.section sw9ma
+.section sw9mb
+.section sw9na
+.section sw9nb
+.section sw9oa
+.section sw9ob
+.section sw9pa
+.section sw9pb
+.section sw9qa
+.section sw9qb
+.section sw9ra
+.section sw9rb
+.section sw9sa
+.section sw9sb
+.section sw9ta
+.section sw9tb
+.section sw9ua
+.section sw9ub
+.section sw9va
+.section sw9vb
+.section sw9wa
+.section sw9wb
+.section sw9xa
+.section sw9xb
+.section sw9ya
+.section sw9yb
+.section sw9za
+.section sw9zb
+.section sw91a
+.section sw91b
+.section sw92a
+.section sw92b
+.section sw93a
+.section sw93b
+.section sw94a
+.section sw94b
+.section sw95a
+.section sw95b
+.section sw96a
+.section sw96b
+.section sw97a
+.section sw97b
+.section sw98a
+.section sw98b
+.section sw99a
+.section sw99b
+.section sw90a
+.section sw90b
+.section sw0aa
+.section sw0ab
+.section sw0ba
+.section sw0bb
+.section sw0ca
+.section sw0cb
+.section sw0da
+.section sw0db
+.section sw0ea
+.section sw0eb
+.section sw0fa
+.section sw0fb
+.section sw0ga
+.section sw0gb
+.section sw0ha
+.section sw0hb
+.section sw0ia
+.section sw0ib
+.section sw0ja
+.section sw0jb
+.section sw0ka
+.section sw0kb
+.section sw0la
+.section sw0lb
+.section sw0ma
+.section sw0mb
+.section sw0na
+.section sw0nb
+.section sw0oa
+.section sw0ob
+.section sw0pa
+.section sw0pb
+.section sw0qa
+.section sw0qb
+.section sw0ra
+.section sw0rb
+.section sw0sa
+.section sw0sb
+.section sw0ta
+.section sw0tb
+.section sw0ua
+.section sw0ub
+.section sw0va
+.section sw0vb
+.section sw0wa
+.section sw0wb
+.section sw0xa
+.section sw0xb
+.section sw0ya
+.section sw0yb
+.section sw0za
+.section sw0zb
+.section sw01a
+.section sw01b
+.section sw02a
+.section sw02b
+.section sw03a
+.section sw03b
+.section sw04a
+.section sw04b
+.section sw05a
+.section sw05b
+.section sw06a
+.section sw06b
+.section sw07a
+.section sw07b
+.section sw08a
+.section sw08b
+.section sw09a
+.section sw09b
+.section sw00a
+.section sw00b
+.section sxaaa
+.section sxaab
+.section sxaba
+.section sxabb
+.section sxaca
+.section sxacb
+.section sxada
+.section sxadb
+.section sxaea
+.section sxaeb
+.section sxafa
+.section sxafb
+.section sxaga
+.section sxagb
+.section sxaha
+.section sxahb
+.section sxaia
+.section sxaib
+.section sxaja
+.section sxajb
+.section sxaka
+.section sxakb
+.section sxala
+.section sxalb
+.section sxama
+.section sxamb
+.section sxana
+.section sxanb
+.section sxaoa
+.section sxaob
+.section sxapa
+.section sxapb
+.section sxaqa
+.section sxaqb
+.section sxara
+.section sxarb
+.section sxasa
+.section sxasb
+.section sxata
+.section sxatb
+.section sxaua
+.section sxaub
+.section sxava
+.section sxavb
+.section sxawa
+.section sxawb
+.section sxaxa
+.section sxaxb
+.section sxaya
+.section sxayb
+.section sxaza
+.section sxazb
+.section sxa1a
+.section sxa1b
+.section sxa2a
+.section sxa2b
+.section sxa3a
+.section sxa3b
+.section sxa4a
+.section sxa4b
+.section sxa5a
+.section sxa5b
+.section sxa6a
+.section sxa6b
+.section sxa7a
+.section sxa7b
+.section sxa8a
+.section sxa8b
+.section sxa9a
+.section sxa9b
+.section sxa0a
+.section sxa0b
+.section sxbaa
+.section sxbab
+.section sxbba
+.section sxbbb
+.section sxbca
+.section sxbcb
+.section sxbda
+.section sxbdb
+.section sxbea
+.section sxbeb
+.section sxbfa
+.section sxbfb
+.section sxbga
+.section sxbgb
+.section sxbha
+.section sxbhb
+.section sxbia
+.section sxbib
+.section sxbja
+.section sxbjb
+.section sxbka
+.section sxbkb
+.section sxbla
+.section sxblb
+.section sxbma
+.section sxbmb
+.section sxbna
+.section sxbnb
+.section sxboa
+.section sxbob
+.section sxbpa
+.section sxbpb
+.section sxbqa
+.section sxbqb
+.section sxbra
+.section sxbrb
+.section sxbsa
+.section sxbsb
+.section sxbta
+.section sxbtb
+.section sxbua
+.section sxbub
+.section sxbva
+.section sxbvb
+.section sxbwa
+.section sxbwb
+.section sxbxa
+.section sxbxb
+.section sxbya
+.section sxbyb
+.section sxbza
+.section sxbzb
+.section sxb1a
+.section sxb1b
+.section sxb2a
+.section sxb2b
+.section sxb3a
+.section sxb3b
+.section sxb4a
+.section sxb4b
+.section sxb5a
+.section sxb5b
+.section sxb6a
+.section sxb6b
+.section sxb7a
+.section sxb7b
+.section sxb8a
+.section sxb8b
+.section sxb9a
+.section sxb9b
+.section sxb0a
+.section sxb0b
+.section sxcaa
+.section sxcab
+.section sxcba
+.section sxcbb
+.section sxcca
+.section sxccb
+.section sxcda
+.section sxcdb
+.section sxcea
+.section sxceb
+.section sxcfa
+.section sxcfb
+.section sxcga
+.section sxcgb
+.section sxcha
+.section sxchb
+.section sxcia
+.section sxcib
+.section sxcja
+.section sxcjb
+.section sxcka
+.section sxckb
+.section sxcla
+.section sxclb
+.section sxcma
+.section sxcmb
+.section sxcna
+.section sxcnb
+.section sxcoa
+.section sxcob
+.section sxcpa
+.section sxcpb
+.section sxcqa
+.section sxcqb
+.section sxcra
+.section sxcrb
+.section sxcsa
+.section sxcsb
+.section sxcta
+.section sxctb
+.section sxcua
+.section sxcub
+.section sxcva
+.section sxcvb
+.section sxcwa
+.section sxcwb
+.section sxcxa
+.section sxcxb
+.section sxcya
+.section sxcyb
+.section sxcza
+.section sxczb
+.section sxc1a
+.section sxc1b
+.section sxc2a
+.section sxc2b
+.section sxc3a
+.section sxc3b
+.section sxc4a
+.section sxc4b
+.section sxc5a
+.section sxc5b
+.section sxc6a
+.section sxc6b
+.section sxc7a
+.section sxc7b
+.section sxc8a
+.section sxc8b
+.section sxc9a
+.section sxc9b
+.section sxc0a
+.section sxc0b
+.section sxdaa
+.section sxdab
+.section sxdba
+.section sxdbb
+.section sxdca
+.section sxdcb
+.section sxdda
+.section sxddb
+.section sxdea
+.section sxdeb
+.section sxdfa
+.section sxdfb
+.section sxdga
+.section sxdgb
+.section sxdha
+.section sxdhb
+.section sxdia
+.section sxdib
+.section sxdja
+.section sxdjb
+.section sxdka
+.section sxdkb
+.section sxdla
+.section sxdlb
+.section sxdma
+.section sxdmb
+.section sxdna
+.section sxdnb
+.section sxdoa
+.section sxdob
+.section sxdpa
+.section sxdpb
+.section sxdqa
+.section sxdqb
+.section sxdra
+.section sxdrb
+.section sxdsa
+.section sxdsb
+.section sxdta
+.section sxdtb
+.section sxdua
+.section sxdub
+.section sxdva
+.section sxdvb
+.section sxdwa
+.section sxdwb
+.section sxdxa
+.section sxdxb
+.section sxdya
+.section sxdyb
+.section sxdza
+.section sxdzb
+.section sxd1a
+.section sxd1b
+.section sxd2a
+.section sxd2b
+.section sxd3a
+.section sxd3b
+.section sxd4a
+.section sxd4b
+.section sxd5a
+.section sxd5b
+.section sxd6a
+.section sxd6b
+.section sxd7a
+.section sxd7b
+.section sxd8a
+.section sxd8b
+.section sxd9a
+.section sxd9b
+.section sxd0a
+.section sxd0b
+.section sxeaa
+.section sxeab
+.section sxeba
+.section sxebb
+.section sxeca
+.section sxecb
+.section sxeda
+.section sxedb
+.section sxeea
+.section sxeeb
+.section sxefa
+.section sxefb
+.section sxega
+.section sxegb
+.section sxeha
+.section sxehb
+.section sxeia
+.section sxeib
+.section sxeja
+.section sxejb
+.section sxeka
+.section sxekb
+.section sxela
+.section sxelb
+.section sxema
+.section sxemb
+.section sxena
+.section sxenb
+.section sxeoa
+.section sxeob
+.section sxepa
+.section sxepb
+.section sxeqa
+.section sxeqb
+.section sxera
+.section sxerb
+.section sxesa
+.section sxesb
+.section sxeta
+.section sxetb
+.section sxeua
+.section sxeub
+.section sxeva
+.section sxevb
+.section sxewa
+.section sxewb
+.section sxexa
+.section sxexb
+.section sxeya
+.section sxeyb
+.section sxeza
+.section sxezb
+.section sxe1a
+.section sxe1b
+.section sxe2a
+.section sxe2b
+.section sxe3a
+.section sxe3b
+.section sxe4a
+.section sxe4b
+.section sxe5a
+.section sxe5b
+.section sxe6a
+.section sxe6b
+.section sxe7a
+.section sxe7b
+.section sxe8a
+.section sxe8b
+.section sxe9a
+.section sxe9b
+.section sxe0a
+.section sxe0b
+.section sxfaa
+.section sxfab
+.section sxfba
+.section sxfbb
+.section sxfca
+.section sxfcb
+.section sxfda
+.section sxfdb
+.section sxfea
+.section sxfeb
+.section sxffa
+.section sxffb
+.section sxfga
+.section sxfgb
+.section sxfha
+.section sxfhb
+.section sxfia
+.section sxfib
+.section sxfja
+.section sxfjb
+.section sxfka
+.section sxfkb
+.section sxfla
+.section sxflb
+.section sxfma
+.section sxfmb
+.section sxfna
+.section sxfnb
+.section sxfoa
+.section sxfob
+.section sxfpa
+.section sxfpb
+.section sxfqa
+.section sxfqb
+.section sxfra
+.section sxfrb
+.section sxfsa
+.section sxfsb
+.section sxfta
+.section sxftb
+.section sxfua
+.section sxfub
+.section sxfva
+.section sxfvb
+.section sxfwa
+.section sxfwb
+.section sxfxa
+.section sxfxb
+.section sxfya
+.section sxfyb
+.section sxfza
+.section sxfzb
+.section sxf1a
+.section sxf1b
+.section sxf2a
+.section sxf2b
+.section sxf3a
+.section sxf3b
+.section sxf4a
+.section sxf4b
+.section sxf5a
+.section sxf5b
+.section sxf6a
+.section sxf6b
+.section sxf7a
+.section sxf7b
+.section sxf8a
+.section sxf8b
+.section sxf9a
+.section sxf9b
+.section sxf0a
+.section sxf0b
+.section sxgaa
+.section sxgab
+.section sxgba
+.section sxgbb
+.section sxgca
+.section sxgcb
+.section sxgda
+.section sxgdb
+.section sxgea
+.section sxgeb
+.section sxgfa
+.section sxgfb
+.section sxgga
+.section sxggb
+.section sxgha
+.section sxghb
+.section sxgia
+.section sxgib
+.section sxgja
+.section sxgjb
+.section sxgka
+.section sxgkb
+.section sxgla
+.section sxglb
+.section sxgma
+.section sxgmb
+.section sxgna
+.section sxgnb
+.section sxgoa
+.section sxgob
+.section sxgpa
+.section sxgpb
+.section sxgqa
+.section sxgqb
+.section sxgra
+.section sxgrb
+.section sxgsa
+.section sxgsb
+.section sxgta
+.section sxgtb
+.section sxgua
+.section sxgub
+.section sxgva
+.section sxgvb
+.section sxgwa
+.section sxgwb
+.section sxgxa
+.section sxgxb
+.section sxgya
+.section sxgyb
+.section sxgza
+.section sxgzb
+.section sxg1a
+.section sxg1b
+.section sxg2a
+.section sxg2b
+.section sxg3a
+.section sxg3b
+.section sxg4a
+.section sxg4b
+.section sxg5a
+.section sxg5b
+.section sxg6a
+.section sxg6b
+.section sxg7a
+.section sxg7b
+.section sxg8a
+.section sxg8b
+.section sxg9a
+.section sxg9b
+.section sxg0a
+.section sxg0b
+.section sxhaa
+.section sxhab
+.section sxhba
+.section sxhbb
+.section sxhca
+.section sxhcb
+.section sxhda
+.section sxhdb
+.section sxhea
+.section sxheb
+.section sxhfa
+.section sxhfb
+.section sxhga
+.section sxhgb
+.section sxhha
+.section sxhhb
+.section sxhia
+.section sxhib
+.section sxhja
+.section sxhjb
+.section sxhka
+.section sxhkb
+.section sxhla
+.section sxhlb
+.section sxhma
+.section sxhmb
+.section sxhna
+.section sxhnb
+.section sxhoa
+.section sxhob
+.section sxhpa
+.section sxhpb
+.section sxhqa
+.section sxhqb
+.section sxhra
+.section sxhrb
+.section sxhsa
+.section sxhsb
+.section sxhta
+.section sxhtb
+.section sxhua
+.section sxhub
+.section sxhva
+.section sxhvb
+.section sxhwa
+.section sxhwb
+.section sxhxa
+.section sxhxb
+.section sxhya
+.section sxhyb
+.section sxhza
+.section sxhzb
+.section sxh1a
+.section sxh1b
+.section sxh2a
+.section sxh2b
+.section sxh3a
+.section sxh3b
+.section sxh4a
+.section sxh4b
+.section sxh5a
+.section sxh5b
+.section sxh6a
+.section sxh6b
+.section sxh7a
+.section sxh7b
+.section sxh8a
+.section sxh8b
+.section sxh9a
+.section sxh9b
+.section sxh0a
+.section sxh0b
+.section sxiaa
+.section sxiab
+.section sxiba
+.section sxibb
+.section sxica
+.section sxicb
+.section sxida
+.section sxidb
+.section sxiea
+.section sxieb
+.section sxifa
+.section sxifb
+.section sxiga
+.section sxigb
+.section sxiha
+.section sxihb
+.section sxiia
+.section sxiib
+.section sxija
+.section sxijb
+.section sxika
+.section sxikb
+.section sxila
+.section sxilb
+.section sxima
+.section sximb
+.section sxina
+.section sxinb
+.section sxioa
+.section sxiob
+.section sxipa
+.section sxipb
+.section sxiqa
+.section sxiqb
+.section sxira
+.section sxirb
+.section sxisa
+.section sxisb
+.section sxita
+.section sxitb
+.section sxiua
+.section sxiub
+.section sxiva
+.section sxivb
+.section sxiwa
+.section sxiwb
+.section sxixa
+.section sxixb
+.section sxiya
+.section sxiyb
+.section sxiza
+.section sxizb
+.section sxi1a
+.section sxi1b
+.section sxi2a
+.section sxi2b
+.section sxi3a
+.section sxi3b
+.section sxi4a
+.section sxi4b
+.section sxi5a
+.section sxi5b
+.section sxi6a
+.section sxi6b
+.section sxi7a
+.section sxi7b
+.section sxi8a
+.section sxi8b
+.section sxi9a
+.section sxi9b
+.section sxi0a
+.section sxi0b
+.section sxjaa
+.section sxjab
+.section sxjba
+.section sxjbb
+.section sxjca
+.section sxjcb
+.section sxjda
+.section sxjdb
+.section sxjea
+.section sxjeb
+.section sxjfa
+.section sxjfb
+.section sxjga
+.section sxjgb
+.section sxjha
+.section sxjhb
+.section sxjia
+.section sxjib
+.section sxjja
+.section sxjjb
+.section sxjka
+.section sxjkb
+.section sxjla
+.section sxjlb
+.section sxjma
+.section sxjmb
+.section sxjna
+.section sxjnb
+.section sxjoa
+.section sxjob
+.section sxjpa
+.section sxjpb
+.section sxjqa
+.section sxjqb
+.section sxjra
+.section sxjrb
+.section sxjsa
+.section sxjsb
+.section sxjta
+.section sxjtb
+.section sxjua
+.section sxjub
+.section sxjva
+.section sxjvb
+.section sxjwa
+.section sxjwb
+.section sxjxa
+.section sxjxb
+.section sxjya
+.section sxjyb
+.section sxjza
+.section sxjzb
+.section sxj1a
+.section sxj1b
+.section sxj2a
+.section sxj2b
+.section sxj3a
+.section sxj3b
+.section sxj4a
+.section sxj4b
+.section sxj5a
+.section sxj5b
+.section sxj6a
+.section sxj6b
+.section sxj7a
+.section sxj7b
+.section sxj8a
+.section sxj8b
+.section sxj9a
+.section sxj9b
+.section sxj0a
+.section sxj0b
+.section sxkaa
+.section sxkab
+.section sxkba
+.section sxkbb
+.section sxkca
+.section sxkcb
+.section sxkda
+.section sxkdb
+.section sxkea
+.section sxkeb
+.section sxkfa
+.section sxkfb
+.section sxkga
+.section sxkgb
+.section sxkha
+.section sxkhb
+.section sxkia
+.section sxkib
+.section sxkja
+.section sxkjb
+.section sxkka
+.section sxkkb
+.section sxkla
+.section sxklb
+.section sxkma
+.section sxkmb
+.section sxkna
+.section sxknb
+.section sxkoa
+.section sxkob
+.section sxkpa
+.section sxkpb
+.section sxkqa
+.section sxkqb
+.section sxkra
+.section sxkrb
+.section sxksa
+.section sxksb
+.section sxkta
+.section sxktb
+.section sxkua
+.section sxkub
+.section sxkva
+.section sxkvb
+.section sxkwa
+.section sxkwb
+.section sxkxa
+.section sxkxb
+.section sxkya
+.section sxkyb
+.section sxkza
+.section sxkzb
+.section sxk1a
+.section sxk1b
+.section sxk2a
+.section sxk2b
+.section sxk3a
+.section sxk3b
+.section sxk4a
+.section sxk4b
+.section sxk5a
+.section sxk5b
+.section sxk6a
+.section sxk6b
+.section sxk7a
+.section sxk7b
+.section sxk8a
+.section sxk8b
+.section sxk9a
+.section sxk9b
+.section sxk0a
+.section sxk0b
+.section sxlaa
+.section sxlab
+.section sxlba
+.section sxlbb
+.section sxlca
+.section sxlcb
+.section sxlda
+.section sxldb
+.section sxlea
+.section sxleb
+.section sxlfa
+.section sxlfb
+.section sxlga
+.section sxlgb
+.section sxlha
+.section sxlhb
+.section sxlia
+.section sxlib
+.section sxlja
+.section sxljb
+.section sxlka
+.section sxlkb
+.section sxlla
+.section sxllb
+.section sxlma
+.section sxlmb
+.section sxlna
+.section sxlnb
+.section sxloa
+.section sxlob
+.section sxlpa
+.section sxlpb
+.section sxlqa
+.section sxlqb
+.section sxlra
+.section sxlrb
+.section sxlsa
+.section sxlsb
+.section sxlta
+.section sxltb
+.section sxlua
+.section sxlub
+.section sxlva
+.section sxlvb
+.section sxlwa
+.section sxlwb
+.section sxlxa
+.section sxlxb
+.section sxlya
+.section sxlyb
+.section sxlza
+.section sxlzb
+.section sxl1a
+.section sxl1b
+.section sxl2a
+.section sxl2b
+.section sxl3a
+.section sxl3b
+.section sxl4a
+.section sxl4b
+.section sxl5a
+.section sxl5b
+.section sxl6a
+.section sxl6b
+.section sxl7a
+.section sxl7b
+.section sxl8a
+.section sxl8b
+.section sxl9a
+.section sxl9b
+.section sxl0a
+.section sxl0b
+.section sxmaa
+.section sxmab
+.section sxmba
+.section sxmbb
+.section sxmca
+.section sxmcb
+.section sxmda
+.section sxmdb
+.section sxmea
+.section sxmeb
+.section sxmfa
+.section sxmfb
+.section sxmga
+.section sxmgb
+.section sxmha
+.section sxmhb
+.section sxmia
+.section sxmib
+.section sxmja
+.section sxmjb
+.section sxmka
+.section sxmkb
+.section sxmla
+.section sxmlb
+.section sxmma
+.section sxmmb
+.section sxmna
+.section sxmnb
+.section sxmoa
+.section sxmob
+.section sxmpa
+.section sxmpb
+.section sxmqa
+.section sxmqb
+.section sxmra
+.section sxmrb
+.section sxmsa
+.section sxmsb
+.section sxmta
+.section sxmtb
+.section sxmua
+.section sxmub
+.section sxmva
+.section sxmvb
+.section sxmwa
+.section sxmwb
+.section sxmxa
+.section sxmxb
+.section sxmya
+.section sxmyb
+.section sxmza
+.section sxmzb
+.section sxm1a
+.section sxm1b
+.section sxm2a
+.section sxm2b
+.section sxm3a
+.section sxm3b
+.section sxm4a
+.section sxm4b
+.section sxm5a
+.section sxm5b
+.section sxm6a
+.section sxm6b
+.section sxm7a
+.section sxm7b
+.section sxm8a
+.section sxm8b
+.section sxm9a
+.section sxm9b
+.section sxm0a
+.section sxm0b
+.section sxnaa
+.section sxnab
+.section sxnba
+.section sxnbb
+.section sxnca
+.section sxncb
+.section sxnda
+.section sxndb
+.section sxnea
+.section sxneb
+.section sxnfa
+.section sxnfb
+.section sxnga
+.section sxngb
+.section sxnha
+.section sxnhb
+.section sxnia
+.section sxnib
+.section sxnja
+.section sxnjb
+.section sxnka
+.section sxnkb
+.section sxnla
+.section sxnlb
+.section sxnma
+.section sxnmb
+.section sxnna
+.section sxnnb
+.section sxnoa
+.section sxnob
+.section sxnpa
+.section sxnpb
+.section sxnqa
+.section sxnqb
+.section sxnra
+.section sxnrb
+.section sxnsa
+.section sxnsb
+.section sxnta
+.section sxntb
+.section sxnua
+.section sxnub
+.section sxnva
+.section sxnvb
+.section sxnwa
+.section sxnwb
+.section sxnxa
+.section sxnxb
+.section sxnya
+.section sxnyb
+.section sxnza
+.section sxnzb
+.section sxn1a
+.section sxn1b
+.section sxn2a
+.section sxn2b
+.section sxn3a
+.section sxn3b
+.section sxn4a
+.section sxn4b
+.section sxn5a
+.section sxn5b
+.section sxn6a
+.section sxn6b
+.section sxn7a
+.section sxn7b
+.section sxn8a
+.section sxn8b
+.section sxn9a
+.section sxn9b
+.section sxn0a
+.section sxn0b
+.section sxoaa
+.section sxoab
+.section sxoba
+.section sxobb
+.section sxoca
+.section sxocb
+.section sxoda
+.section sxodb
+.section sxoea
+.section sxoeb
+.section sxofa
+.section sxofb
+.section sxoga
+.section sxogb
+.section sxoha
+.section sxohb
+.section sxoia
+.section sxoib
+.section sxoja
+.section sxojb
+.section sxoka
+.section sxokb
+.section sxola
+.section sxolb
+.section sxoma
+.section sxomb
+.section sxona
+.section sxonb
+.section sxooa
+.section sxoob
+.section sxopa
+.section sxopb
+.section sxoqa
+.section sxoqb
+.section sxora
+.section sxorb
+.section sxosa
+.section sxosb
+.section sxota
+.section sxotb
+.section sxoua
+.section sxoub
+.section sxova
+.section sxovb
+.section sxowa
+.section sxowb
+.section sxoxa
+.section sxoxb
+.section sxoya
+.section sxoyb
+.section sxoza
+.section sxozb
+.section sxo1a
+.section sxo1b
+.section sxo2a
+.section sxo2b
+.section sxo3a
+.section sxo3b
+.section sxo4a
+.section sxo4b
+.section sxo5a
+.section sxo5b
+.section sxo6a
+.section sxo6b
+.section sxo7a
+.section sxo7b
+.section sxo8a
+.section sxo8b
+.section sxo9a
+.section sxo9b
+.section sxo0a
+.section sxo0b
+.section sxpaa
+.section sxpab
+.section sxpba
+.section sxpbb
+.section sxpca
+.section sxpcb
+.section sxpda
+.section sxpdb
+.section sxpea
+.section sxpeb
+.section sxpfa
+.section sxpfb
+.section sxpga
+.section sxpgb
+.section sxpha
+.section sxphb
+.section sxpia
+.section sxpib
+.section sxpja
+.section sxpjb
+.section sxpka
+.section sxpkb
+.section sxpla
+.section sxplb
+.section sxpma
+.section sxpmb
+.section sxpna
+.section sxpnb
+.section sxpoa
+.section sxpob
+.section sxppa
+.section sxppb
+.section sxpqa
+.section sxpqb
+.section sxpra
+.section sxprb
+.section sxpsa
+.section sxpsb
+.section sxpta
+.section sxptb
+.section sxpua
+.section sxpub
+.section sxpva
+.section sxpvb
+.section sxpwa
+.section sxpwb
+.section sxpxa
+.section sxpxb
+.section sxpya
+.section sxpyb
+.section sxpza
+.section sxpzb
+.section sxp1a
+.section sxp1b
+.section sxp2a
+.section sxp2b
+.section sxp3a
+.section sxp3b
+.section sxp4a
+.section sxp4b
+.section sxp5a
+.section sxp5b
+.section sxp6a
+.section sxp6b
+.section sxp7a
+.section sxp7b
+.section sxp8a
+.section sxp8b
+.section sxp9a
+.section sxp9b
+.section sxp0a
+.section sxp0b
+.section sxqaa
+.section sxqab
+.section sxqba
+.section sxqbb
+.section sxqca
+.section sxqcb
+.section sxqda
+.section sxqdb
+.section sxqea
+.section sxqeb
+.section sxqfa
+.section sxqfb
+.section sxqga
+.section sxqgb
+.section sxqha
+.section sxqhb
+.section sxqia
+.section sxqib
+.section sxqja
+.section sxqjb
+.section sxqka
+.section sxqkb
+.section sxqla
+.section sxqlb
+.section sxqma
+.section sxqmb
+.section sxqna
+.section sxqnb
+.section sxqoa
+.section sxqob
+.section sxqpa
+.section sxqpb
+.section sxqqa
+.section sxqqb
+.section sxqra
+.section sxqrb
+.section sxqsa
+.section sxqsb
+.section sxqta
+.section sxqtb
+.section sxqua
+.section sxqub
+.section sxqva
+.section sxqvb
+.section sxqwa
+.section sxqwb
+.section sxqxa
+.section sxqxb
+.section sxqya
+.section sxqyb
+.section sxqza
+.section sxqzb
+.section sxq1a
+.section sxq1b
+.section sxq2a
+.section sxq2b
+.section sxq3a
+.section sxq3b
+.section sxq4a
+.section sxq4b
+.section sxq5a
+.section sxq5b
+.section sxq6a
+.section sxq6b
+.section sxq7a
+.section sxq7b
+.section sxq8a
+.section sxq8b
+.section sxq9a
+.section sxq9b
+.section sxq0a
+.section sxq0b
+.section sxraa
+.section sxrab
+.section sxrba
+.section sxrbb
+.section sxrca
+.section sxrcb
+.section sxrda
+.section sxrdb
+.section sxrea
+.section sxreb
+.section sxrfa
+.section sxrfb
+.section sxrga
+.section sxrgb
+.section sxrha
+.section sxrhb
+.section sxria
+.section sxrib
+.section sxrja
+.section sxrjb
+.section sxrka
+.section sxrkb
+.section sxrla
+.section sxrlb
+.section sxrma
+.section sxrmb
+.section sxrna
+.section sxrnb
+.section sxroa
+.section sxrob
+.section sxrpa
+.section sxrpb
+.section sxrqa
+.section sxrqb
+.section sxrra
+.section sxrrb
+.section sxrsa
+.section sxrsb
+.section sxrta
+.section sxrtb
+.section sxrua
+.section sxrub
+.section sxrva
+.section sxrvb
+.section sxrwa
+.section sxrwb
+.section sxrxa
+.section sxrxb
+.section sxrya
+.section sxryb
+.section sxrza
+.section sxrzb
+.section sxr1a
+.section sxr1b
+.section sxr2a
+.section sxr2b
+.section sxr3a
+.section sxr3b
+.section sxr4a
+.section sxr4b
+.section sxr5a
+.section sxr5b
+.section sxr6a
+.section sxr6b
+.section sxr7a
+.section sxr7b
+.section sxr8a
+.section sxr8b
+.section sxr9a
+.section sxr9b
+.section sxr0a
+.section sxr0b
+.section sxsaa
+.section sxsab
+.section sxsba
+.section sxsbb
+.section sxsca
+.section sxscb
+.section sxsda
+.section sxsdb
+.section sxsea
+.section sxseb
+.section sxsfa
+.section sxsfb
+.section sxsga
+.section sxsgb
+.section sxsha
+.section sxshb
+.section sxsia
+.section sxsib
+.section sxsja
+.section sxsjb
+.section sxska
+.section sxskb
+.section sxsla
+.section sxslb
+.section sxsma
+.section sxsmb
+.section sxsna
+.section sxsnb
+.section sxsoa
+.section sxsob
+.section sxspa
+.section sxspb
+.section sxsqa
+.section sxsqb
+.section sxsra
+.section sxsrb
+.section sxssa
+.section sxssb
+.section sxsta
+.section sxstb
+.section sxsua
+.section sxsub
+.section sxsva
+.section sxsvb
+.section sxswa
+.section sxswb
+.section sxsxa
+.section sxsxb
+.section sxsya
+.section sxsyb
+.section sxsza
+.section sxszb
+.section sxs1a
+.section sxs1b
+.section sxs2a
+.section sxs2b
+.section sxs3a
+.section sxs3b
+.section sxs4a
+.section sxs4b
+.section sxs5a
+.section sxs5b
+.section sxs6a
+.section sxs6b
+.section sxs7a
+.section sxs7b
+.section sxs8a
+.section sxs8b
+.section sxs9a
+.section sxs9b
+.section sxs0a
+.section sxs0b
+.section sxtaa
+.section sxtab
+.section sxtba
+.section sxtbb
+.section sxtca
+.section sxtcb
+.section sxtda
+.section sxtdb
+.section sxtea
+.section sxteb
+.section sxtfa
+.section sxtfb
+.section sxtga
+.section sxtgb
+.section sxtha
+.section sxthb
+.section sxtia
+.section sxtib
+.section sxtja
+.section sxtjb
+.section sxtka
+.section sxtkb
+.section sxtla
+.section sxtlb
+.section sxtma
+.section sxtmb
+.section sxtna
+.section sxtnb
+.section sxtoa
+.section sxtob
+.section sxtpa
+.section sxtpb
+.section sxtqa
+.section sxtqb
+.section sxtra
+.section sxtrb
+.section sxtsa
+.section sxtsb
+.section sxtta
+.section sxttb
+.section sxtua
+.section sxtub
+.section sxtva
+.section sxtvb
+.section sxtwa
+.section sxtwb
+.section sxtxa
+.section sxtxb
+.section sxtya
+.section sxtyb
+.section sxtza
+.section sxtzb
+.section sxt1a
+.section sxt1b
+.section sxt2a
+.section sxt2b
+.section sxt3a
+.section sxt3b
+.section sxt4a
+.section sxt4b
+.section sxt5a
+.section sxt5b
+.section sxt6a
+.section sxt6b
+.section sxt7a
+.section sxt7b
+.section sxt8a
+.section sxt8b
+.section sxt9a
+.section sxt9b
+.section sxt0a
+.section sxt0b
+.section sxuaa
+.section sxuab
+.section sxuba
+.section sxubb
+.section sxuca
+.section sxucb
+.section sxuda
+.section sxudb
+.section sxuea
+.section sxueb
+.section sxufa
+.section sxufb
+.section sxuga
+.section sxugb
+.section sxuha
+.section sxuhb
+.section sxuia
+.section sxuib
+.section sxuja
+.section sxujb
+.section sxuka
+.section sxukb
+.section sxula
+.section sxulb
+.section sxuma
+.section sxumb
+.section sxuna
+.section sxunb
+.section sxuoa
+.section sxuob
+.section sxupa
+.section sxupb
+.section sxuqa
+.section sxuqb
+.section sxura
+.section sxurb
+.section sxusa
+.section sxusb
+.section sxuta
+.section sxutb
+.section sxuua
+.section sxuub
+.section sxuva
+.section sxuvb
+.section sxuwa
+.section sxuwb
+.section sxuxa
+.section sxuxb
+.section sxuya
+.section sxuyb
+.section sxuza
+.section sxuzb
+.section sxu1a
+.section sxu1b
+.section sxu2a
+.section sxu2b
+.section sxu3a
+.section sxu3b
+.section sxu4a
+.section sxu4b
+.section sxu5a
+.section sxu5b
+.section sxu6a
+.section sxu6b
+.section sxu7a
+.section sxu7b
+.section sxu8a
+.section sxu8b
+.section sxu9a
+.section sxu9b
+.section sxu0a
+.section sxu0b
+.section sxvaa
+.section sxvab
+.section sxvba
+.section sxvbb
+.section sxvca
+.section sxvcb
+.section sxvda
+.section sxvdb
+.section sxvea
+.section sxveb
+.section sxvfa
+.section sxvfb
+.section sxvga
+.section sxvgb
+.section sxvha
+.section sxvhb
+.section sxvia
+.section sxvib
+.section sxvja
+.section sxvjb
+.section sxvka
+.section sxvkb
+.section sxvla
+.section sxvlb
+.section sxvma
+.section sxvmb
+.section sxvna
+.section sxvnb
+.section sxvoa
+.section sxvob
+.section sxvpa
+.section sxvpb
+.section sxvqa
+.section sxvqb
+.section sxvra
+.section sxvrb
+.section sxvsa
+.section sxvsb
+.section sxvta
+.section sxvtb
+.section sxvua
+.section sxvub
+.section sxvva
+.section sxvvb
+.section sxvwa
+.section sxvwb
+.section sxvxa
+.section sxvxb
+.section sxvya
+.section sxvyb
+.section sxvza
+.section sxvzb
+.section sxv1a
+.section sxv1b
+.section sxv2a
+.section sxv2b
+.section sxv3a
+.section sxv3b
+.section sxv4a
+.section sxv4b
+.section sxv5a
+.section sxv5b
+.section sxv6a
+.section sxv6b
+.section sxv7a
+.section sxv7b
+.section sxv8a
+.section sxv8b
+.section sxv9a
+.section sxv9b
+.section sxv0a
+.section sxv0b
+.section sxwaa
+.section sxwab
+.section sxwba
+.section sxwbb
+.section sxwca
+.section sxwcb
+.section sxwda
+.section sxwdb
+.section sxwea
+.section sxweb
+.section sxwfa
+.section sxwfb
+.section sxwga
+.section sxwgb
+.section sxwha
+.section sxwhb
+.section sxwia
+.section sxwib
+.section sxwja
+.section sxwjb
+.section sxwka
+.section sxwkb
+.section sxwla
+.section sxwlb
+.section sxwma
+.section sxwmb
+.section sxwna
+.section sxwnb
+.section sxwoa
+.section sxwob
+.section sxwpa
+.section sxwpb
+.section sxwqa
+.section sxwqb
+.section sxwra
+.section sxwrb
+.section sxwsa
+.section sxwsb
+.section sxwta
+.section sxwtb
+.section sxwua
+.section sxwub
+.section sxwva
+.section sxwvb
+.section sxwwa
+.section sxwwb
+.section sxwxa
+.section sxwxb
+.section sxwya
+.section sxwyb
+.section sxwza
+.section sxwzb
+.section sxw1a
+.section sxw1b
+.section sxw2a
+.section sxw2b
+.section sxw3a
+.section sxw3b
+.section sxw4a
+.section sxw4b
+.section sxw5a
+.section sxw5b
+.section sxw6a
+.section sxw6b
+.section sxw7a
+.section sxw7b
+.section sxw8a
+.section sxw8b
+.section sxw9a
+.section sxw9b
+.section sxw0a
+.section sxw0b
+.section sxxaa
+.section sxxab
+.section sxxba
+.section sxxbb
+.section sxxca
+.section sxxcb
+.section sxxda
+.section sxxdb
+.section sxxea
+.section sxxeb
+.section sxxfa
+.section sxxfb
+.section sxxga
+.section sxxgb
+.section sxxha
+.section sxxhb
+.section sxxia
+.section sxxib
+.section sxxja
+.section sxxjb
+.section sxxka
+.section sxxkb
+.section sxxla
+.section sxxlb
+.section sxxma
+.section sxxmb
+.section sxxna
+.section sxxnb
+.section sxxoa
+.section sxxob
+.section sxxpa
+.section sxxpb
+.section sxxqa
+.section sxxqb
+.section sxxra
+.section sxxrb
+.section sxxsa
+.section sxxsb
+.section sxxta
+.section sxxtb
+.section sxxua
+.section sxxub
+.section sxxva
+.section sxxvb
+.section sxxwa
+.section sxxwb
+.section sxxxa
+.section sxxxb
+.section sxxya
+.section sxxyb
+.section sxxza
+.section sxxzb
+.section sxx1a
+.section sxx1b
+.section sxx2a
+.section sxx2b
+.section sxx3a
+.section sxx3b
+.section sxx4a
+.section sxx4b
+.section sxx5a
+.section sxx5b
+.section sxx6a
+.section sxx6b
+.section sxx7a
+.section sxx7b
+.section sxx8a
+.section sxx8b
+.section sxx9a
+.section sxx9b
+.section sxx0a
+.section sxx0b
+.section sxyaa
+.section sxyab
+.section sxyba
+.section sxybb
+.section sxyca
+.section sxycb
+.section sxyda
+.section sxydb
+.section sxyea
+.section sxyeb
+.section sxyfa
+.section sxyfb
+.section sxyga
+.section sxygb
+.section sxyha
+.section sxyhb
+.section sxyia
+.section sxyib
+.section sxyja
+.section sxyjb
+.section sxyka
+.section sxykb
+.section sxyla
+.section sxylb
+.section sxyma
+.section sxymb
+.section sxyna
+.section sxynb
+.section sxyoa
+.section sxyob
+.section sxypa
+.section sxypb
+.section sxyqa
+.section sxyqb
+.section sxyra
+.section sxyrb
+.section sxysa
+.section sxysb
+.section sxyta
+.section sxytb
+.section sxyua
+.section sxyub
+.section sxyva
+.section sxyvb
+.section sxywa
+.section sxywb
+.section sxyxa
+.section sxyxb
+.section sxyya
+.section sxyyb
+.section sxyza
+.section sxyzb
+.section sxy1a
+.section sxy1b
+.section sxy2a
+.section sxy2b
+.section sxy3a
+.section sxy3b
+.section sxy4a
+.section sxy4b
+.section sxy5a
+.section sxy5b
+.section sxy6a
+.section sxy6b
+.section sxy7a
+.section sxy7b
+.section sxy8a
+.section sxy8b
+.section sxy9a
+.section sxy9b
+.section sxy0a
+.section sxy0b
+.section sxzaa
+.section sxzab
+.section sxzba
+.section sxzbb
+.section sxzca
+.section sxzcb
+.section sxzda
+.section sxzdb
+.section sxzea
+.section sxzeb
+.section sxzfa
+.section sxzfb
+.section sxzga
+.section sxzgb
+.section sxzha
+.section sxzhb
+.section sxzia
+.section sxzib
+.section sxzja
+.section sxzjb
+.section sxzka
+.section sxzkb
+.section sxzla
+.section sxzlb
+.section sxzma
+.section sxzmb
+.section sxzna
+.section sxznb
+.section sxzoa
+.section sxzob
+.section sxzpa
+.section sxzpb
+.section sxzqa
+.section sxzqb
+.section sxzra
+.section sxzrb
+.section sxzsa
+.section sxzsb
+.section sxzta
+.section sxztb
+.section sxzua
+.section sxzub
+.section sxzva
+.section sxzvb
+.section sxzwa
+.section sxzwb
+.section sxzxa
+.section sxzxb
+.section sxzya
+.section sxzyb
+.section sxzza
+.section sxzzb
+.section sxz1a
+.section sxz1b
+.section sxz2a
+.section sxz2b
+.section sxz3a
+.section sxz3b
+.section sxz4a
+.section sxz4b
+.section sxz5a
+.section sxz5b
+.section sxz6a
+.section sxz6b
+.section sxz7a
+.section sxz7b
+.section sxz8a
+.section sxz8b
+.section sxz9a
+.section sxz9b
+.section sxz0a
+.section sxz0b
+.section sx1aa
+.section sx1ab
+.section sx1ba
+.section sx1bb
+.section sx1ca
+.section sx1cb
+.section sx1da
+.section sx1db
+.section sx1ea
+.section sx1eb
+.section sx1fa
+.section sx1fb
+.section sx1ga
+.section sx1gb
+.section sx1ha
+.section sx1hb
+.section sx1ia
+.section sx1ib
+.section sx1ja
+.section sx1jb
+.section sx1ka
+.section sx1kb
+.section sx1la
+.section sx1lb
+.section sx1ma
+.section sx1mb
+.section sx1na
+.section sx1nb
+.section sx1oa
+.section sx1ob
+.section sx1pa
+.section sx1pb
+.section sx1qa
+.section sx1qb
+.section sx1ra
+.section sx1rb
+.section sx1sa
+.section sx1sb
+.section sx1ta
+.section sx1tb
+.section sx1ua
+.section sx1ub
+.section sx1va
+.section sx1vb
+.section sx1wa
+.section sx1wb
+.section sx1xa
+.section sx1xb
+.section sx1ya
+.section sx1yb
+.section sx1za
+.section sx1zb
+.section sx11a
+.section sx11b
+.section sx12a
+.section sx12b
+.section sx13a
+.section sx13b
+.section sx14a
+.section sx14b
+.section sx15a
+.section sx15b
+.section sx16a
+.section sx16b
+.section sx17a
+.section sx17b
+.section sx18a
+.section sx18b
+.section sx19a
+.section sx19b
+.section sx10a
+.section sx10b
+.section sx2aa
+.section sx2ab
+.section sx2ba
+.section sx2bb
+.section sx2ca
+.section sx2cb
+.section sx2da
+.section sx2db
+.section sx2ea
+.section sx2eb
+.section sx2fa
+.section sx2fb
+.section sx2ga
+.section sx2gb
+.section sx2ha
+.section sx2hb
+.section sx2ia
+.section sx2ib
+.section sx2ja
+.section sx2jb
+.section sx2ka
+.section sx2kb
+.section sx2la
+.section sx2lb
+.section sx2ma
+.section sx2mb
+.section sx2na
+.section sx2nb
+.section sx2oa
+.section sx2ob
+.section sx2pa
+.section sx2pb
+.section sx2qa
+.section sx2qb
+.section sx2ra
+.section sx2rb
+.section sx2sa
+.section sx2sb
+.section sx2ta
+.section sx2tb
+.section sx2ua
+.section sx2ub
+.section sx2va
+.section sx2vb
+.section sx2wa
+.section sx2wb
+.section sx2xa
+.section sx2xb
+.section sx2ya
+.section sx2yb
+.section sx2za
+.section sx2zb
+.section sx21a
+.section sx21b
+.section sx22a
+.section sx22b
+.section sx23a
+.section sx23b
+.section sx24a
+.section sx24b
+.section sx25a
+.section sx25b
+.section sx26a
+.section sx26b
+.section sx27a
+.section sx27b
+.section sx28a
+.section sx28b
+.section sx29a
+.section sx29b
+.section sx20a
+.section sx20b
+.section sx3aa
+.section sx3ab
+.section sx3ba
+.section sx3bb
+.section sx3ca
+.section sx3cb
+.section sx3da
+.section sx3db
+.section sx3ea
+.section sx3eb
+.section sx3fa
+.section sx3fb
+.section sx3ga
+.section sx3gb
+.section sx3ha
+.section sx3hb
+.section sx3ia
+.section sx3ib
+.section sx3ja
+.section sx3jb
+.section sx3ka
+.section sx3kb
+.section sx3la
+.section sx3lb
+.section sx3ma
+.section sx3mb
+.section sx3na
+.section sx3nb
+.section sx3oa
+.section sx3ob
+.section sx3pa
+.section sx3pb
+.section sx3qa
+.section sx3qb
+.section sx3ra
+.section sx3rb
+.section sx3sa
+.section sx3sb
+.section sx3ta
+.section sx3tb
+.section sx3ua
+.section sx3ub
+.section sx3va
+.section sx3vb
+.section sx3wa
+.section sx3wb
+.section sx3xa
+.section sx3xb
+.section sx3ya
+.section sx3yb
+.section sx3za
+.section sx3zb
+.section sx31a
+.section sx31b
+.section sx32a
+.section sx32b
+.section sx33a
+.section sx33b
+.section sx34a
+.section sx34b
+.section sx35a
+.section sx35b
+.section sx36a
+.section sx36b
+.section sx37a
+.section sx37b
+.section sx38a
+.section sx38b
+.section sx39a
+.section sx39b
+.section sx30a
+.section sx30b
+.section sx4aa
+.section sx4ab
+.section sx4ba
+.section sx4bb
+.section sx4ca
+.section sx4cb
+.section sx4da
+.section sx4db
+.section sx4ea
+.section sx4eb
+.section sx4fa
+.section sx4fb
+.section sx4ga
+.section sx4gb
+.section sx4ha
+.section sx4hb
+.section sx4ia
+.section sx4ib
+.section sx4ja
+.section sx4jb
+.section sx4ka
+.section sx4kb
+.section sx4la
+.section sx4lb
+.section sx4ma
+.section sx4mb
+.section sx4na
+.section sx4nb
+.section sx4oa
+.section sx4ob
+.section sx4pa
+.section sx4pb
+.section sx4qa
+.section sx4qb
+.section sx4ra
+.section sx4rb
+.section sx4sa
+.section sx4sb
+.section sx4ta
+.section sx4tb
+.section sx4ua
+.section sx4ub
+.section sx4va
+.section sx4vb
+.section sx4wa
+.section sx4wb
+.section sx4xa
+.section sx4xb
+.section sx4ya
+.section sx4yb
+.section sx4za
+.section sx4zb
+.section sx41a
+.section sx41b
+.section sx42a
+.section sx42b
+.section sx43a
+.section sx43b
+.section sx44a
+.section sx44b
+.section sx45a
+.section sx45b
+.section sx46a
+.section sx46b
+.section sx47a
+.section sx47b
+.section sx48a
+.section sx48b
+.section sx49a
+.section sx49b
+.section sx40a
+.section sx40b
+.section sx5aa
+.section sx5ab
+.section sx5ba
+.section sx5bb
+.section sx5ca
+.section sx5cb
+.section sx5da
+.section sx5db
+.section sx5ea
+.section sx5eb
+.section sx5fa
+.section sx5fb
+.section sx5ga
+.section sx5gb
+.section sx5ha
+.section sx5hb
+.section sx5ia
+.section sx5ib
+.section sx5ja
+.section sx5jb
+.section sx5ka
+.section sx5kb
+.section sx5la
+.section sx5lb
+.section sx5ma
+.section sx5mb
+.section sx5na
+.section sx5nb
+.section sx5oa
+.section sx5ob
+.section sx5pa
+.section sx5pb
+.section sx5qa
+.section sx5qb
+.section sx5ra
+.section sx5rb
+.section sx5sa
+.section sx5sb
+.section sx5ta
+.section sx5tb
+.section sx5ua
+.section sx5ub
+.section sx5va
+.section sx5vb
+.section sx5wa
+.section sx5wb
+.section sx5xa
+.section sx5xb
+.section sx5ya
+.section sx5yb
+.section sx5za
+.section sx5zb
+.section sx51a
+.section sx51b
+.section sx52a
+.section sx52b
+.section sx53a
+.section sx53b
+.section sx54a
+.section sx54b
+.section sx55a
+.section sx55b
+.section sx56a
+.section sx56b
+.section sx57a
+.section sx57b
+.section sx58a
+.section sx58b
+.section sx59a
+.section sx59b
+.section sx50a
+.section sx50b
+.section sx6aa
+.section sx6ab
+.section sx6ba
+.section sx6bb
+.section sx6ca
+.section sx6cb
+.section sx6da
+.section sx6db
+.section sx6ea
+.section sx6eb
+.section sx6fa
+.section sx6fb
+.section sx6ga
+.section sx6gb
+.section sx6ha
+.section sx6hb
+.section sx6ia
+.section sx6ib
+.section sx6ja
+.section sx6jb
+.section sx6ka
+.section sx6kb
+.section sx6la
+.section sx6lb
+.section sx6ma
+.section sx6mb
+.section sx6na
+.section sx6nb
+.section sx6oa
+.section sx6ob
+.section sx6pa
+.section sx6pb
+.section sx6qa
+.section sx6qb
+.section sx6ra
+.section sx6rb
+.section sx6sa
+.section sx6sb
+.section sx6ta
+.section sx6tb
+.section sx6ua
+.section sx6ub
+.section sx6va
+.section sx6vb
+.section sx6wa
+.section sx6wb
+.section sx6xa
+.section sx6xb
+.section sx6ya
+.section sx6yb
+.section sx6za
+.section sx6zb
+.section sx61a
+.section sx61b
+.section sx62a
+.section sx62b
+.section sx63a
+.section sx63b
+.section sx64a
+.section sx64b
+.section sx65a
+.section sx65b
+.section sx66a
+.section sx66b
+.section sx67a
+.section sx67b
+.section sx68a
+.section sx68b
+.section sx69a
+.section sx69b
+.section sx60a
+.section sx60b
+.section sx7aa
+.section sx7ab
+.section sx7ba
+.section sx7bb
+.section sx7ca
+.section sx7cb
+.section sx7da
+.section sx7db
+.section sx7ea
+.section sx7eb
+.section sx7fa
+.section sx7fb
+.section sx7ga
+.section sx7gb
+.section sx7ha
+.section sx7hb
+.section sx7ia
+.section sx7ib
+.section sx7ja
+.section sx7jb
+.section sx7ka
+.section sx7kb
+.section sx7la
+.section sx7lb
+.section sx7ma
+.section sx7mb
+.section sx7na
+.section sx7nb
+.section sx7oa
+.section sx7ob
+.section sx7pa
+.section sx7pb
+.section sx7qa
+.section sx7qb
+.section sx7ra
+.section sx7rb
+.section sx7sa
+.section sx7sb
+.section sx7ta
+.section sx7tb
+.section sx7ua
+.section sx7ub
+.section sx7va
+.section sx7vb
+.section sx7wa
+.section sx7wb
+.section sx7xa
+.section sx7xb
+.section sx7ya
+.section sx7yb
+.section sx7za
+.section sx7zb
+.section sx71a
+.section sx71b
+.section sx72a
+.section sx72b
+.section sx73a
+.section sx73b
+.section sx74a
+.section sx74b
+.section sx75a
+.section sx75b
+.section sx76a
+.section sx76b
+.section sx77a
+.section sx77b
+.section sx78a
+.section sx78b
+.section sx79a
+.section sx79b
+.section sx70a
+.section sx70b
+.section sx8aa
+.section sx8ab
+.section sx8ba
+.section sx8bb
+.section sx8ca
+.section sx8cb
+.section sx8da
+.section sx8db
+.section sx8ea
+.section sx8eb
+.section sx8fa
+.section sx8fb
+.section sx8ga
+.section sx8gb
+.section sx8ha
+.section sx8hb
+.section sx8ia
+.section sx8ib
+.section sx8ja
+.section sx8jb
+.section sx8ka
+.section sx8kb
+.section sx8la
+.section sx8lb
+.section sx8ma
+.section sx8mb
+.section sx8na
+.section sx8nb
+.section sx8oa
+.section sx8ob
+.section sx8pa
+.section sx8pb
+.section sx8qa
+.section sx8qb
+.section sx8ra
+.section sx8rb
+.section sx8sa
+.section sx8sb
+.section sx8ta
+.section sx8tb
+.section sx8ua
+.section sx8ub
+.section sx8va
+.section sx8vb
+.section sx8wa
+.section sx8wb
+.section sx8xa
+.section sx8xb
+.section sx8ya
+.section sx8yb
+.section sx8za
+.section sx8zb
+.section sx81a
+.section sx81b
+.section sx82a
+.section sx82b
+.section sx83a
+.section sx83b
+.section sx84a
+.section sx84b
+.section sx85a
+.section sx85b
+.section sx86a
+.section sx86b
+.section sx87a
+.section sx87b
+.section sx88a
+.section sx88b
+.section sx89a
+.section sx89b
+.section sx80a
+.section sx80b
+.section sx9aa
+.section sx9ab
+.section sx9ba
+.section sx9bb
+.section sx9ca
+.section sx9cb
+.section sx9da
+.section sx9db
+.section sx9ea
+.section sx9eb
+.section sx9fa
+.section sx9fb
+.section sx9ga
+.section sx9gb
+.section sx9ha
+.section sx9hb
+.section sx9ia
+.section sx9ib
+.section sx9ja
+.section sx9jb
+.section sx9ka
+.section sx9kb
+.section sx9la
+.section sx9lb
+.section sx9ma
+.section sx9mb
+.section sx9na
+.section sx9nb
+.section sx9oa
+.section sx9ob
+.section sx9pa
+.section sx9pb
+.section sx9qa
+.section sx9qb
+.section sx9ra
+.section sx9rb
+.section sx9sa
+.section sx9sb
+.section sx9ta
+.section sx9tb
+.section sx9ua
+.section sx9ub
+.section sx9va
+.section sx9vb
+.section sx9wa
+.section sx9wb
+.section sx9xa
+.section sx9xb
+.section sx9ya
+.section sx9yb
+.section sx9za
+.section sx9zb
+.section sx91a
+.section sx91b
+.section sx92a
+.section sx92b
+.section sx93a
+.section sx93b
+.section sx94a
+.section sx94b
+.section sx95a
+.section sx95b
+.section sx96a
+.section sx96b
+.section sx97a
+.section sx97b
+.section sx98a
+.section sx98b
+.section sx99a
+.section sx99b
+.section sx90a
+.section sx90b
+.section sx0aa
+.section sx0ab
+.section sx0ba
+.section sx0bb
+.section sx0ca
+.section sx0cb
+.section sx0da
+.section sx0db
+.section sx0ea
+.section sx0eb
+.section sx0fa
+.section sx0fb
+.section sx0ga
+.section sx0gb
+.section sx0ha
+.section sx0hb
+.section sx0ia
+.section sx0ib
+.section sx0ja
+.section sx0jb
+.section sx0ka
+.section sx0kb
+.section sx0la
+.section sx0lb
+.section sx0ma
+.section sx0mb
+.section sx0na
+.section sx0nb
+.section sx0oa
+.section sx0ob
+.section sx0pa
+.section sx0pb
+.section sx0qa
+.section sx0qb
+.section sx0ra
+.section sx0rb
+.section sx0sa
+.section sx0sb
+.section sx0ta
+.section sx0tb
+.section sx0ua
+.section sx0ub
+.section sx0va
+.section sx0vb
+.section sx0wa
+.section sx0wb
+.section sx0xa
+.section sx0xb
+.section sx0ya
+.section sx0yb
+.section sx0za
+.section sx0zb
+.section sx01a
+.section sx01b
+.section sx02a
+.section sx02b
+.section sx03a
+.section sx03b
+.section sx04a
+.section sx04b
+.section sx05a
+.section sx05b
+.section sx06a
+.section sx06b
+.section sx07a
+.section sx07b
+.section sx08a
+.section sx08b
+.section sx09a
+.section sx09b
+.section sx00a
+.section sx00b
+.section syaaa
+.section syaab
+.section syaba
+.section syabb
+.section syaca
+.section syacb
+.section syada
+.section syadb
+.section syaea
+.section syaeb
+.section syafa
+.section syafb
+.section syaga
+.section syagb
+.section syaha
+.section syahb
+.section syaia
+.section syaib
+.section syaja
+.section syajb
+.section syaka
+.section syakb
+.section syala
+.section syalb
+.section syama
+.section syamb
+.section syana
+.section syanb
+.section syaoa
+.section syaob
+.section syapa
+.section syapb
+.section syaqa
+.section syaqb
+.section syara
+.section syarb
+.section syasa
+.section syasb
+.section syata
+.section syatb
+.section syaua
+.section syaub
+.section syava
+.section syavb
+.section syawa
+.section syawb
+.section syaxa
+.section syaxb
+.section syaya
+.section syayb
+.section syaza
+.section syazb
+.section sya1a
+.section sya1b
+.section sya2a
+.section sya2b
+.section sya3a
+.section sya3b
+.section sya4a
+.section sya4b
+.section sya5a
+.section sya5b
+.section sya6a
+.section sya6b
+.section sya7a
+.section sya7b
+.section sya8a
+.section sya8b
+.section sya9a
+.section sya9b
+.section sya0a
+.section sya0b
+.section sybaa
+.section sybab
+.section sybba
+.section sybbb
+.section sybca
+.section sybcb
+.section sybda
+.section sybdb
+.section sybea
+.section sybeb
+.section sybfa
+.section sybfb
+.section sybga
+.section sybgb
+.section sybha
+.section sybhb
+.section sybia
+.section sybib
+.section sybja
+.section sybjb
+.section sybka
+.section sybkb
+.section sybla
+.section syblb
+.section sybma
+.section sybmb
+.section sybna
+.section sybnb
+.section syboa
+.section sybob
+.section sybpa
+.section sybpb
+.section sybqa
+.section sybqb
+.section sybra
+.section sybrb
+.section sybsa
+.section sybsb
+.section sybta
+.section sybtb
+.section sybua
+.section sybub
+.section sybva
+.section sybvb
+.section sybwa
+.section sybwb
+.section sybxa
+.section sybxb
+.section sybya
+.section sybyb
+.section sybza
+.section sybzb
+.section syb1a
+.section syb1b
+.section syb2a
+.section syb2b
+.section syb3a
+.section syb3b
+.section syb4a
+.section syb4b
+.section syb5a
+.section syb5b
+.section syb6a
+.section syb6b
+.section syb7a
+.section syb7b
+.section syb8a
+.section syb8b
+.section syb9a
+.section syb9b
+.section syb0a
+.section syb0b
+.section sycaa
+.section sycab
+.section sycba
+.section sycbb
+.section sycca
+.section syccb
+.section sycda
+.section sycdb
+.section sycea
+.section syceb
+.section sycfa
+.section sycfb
+.section sycga
+.section sycgb
+.section sycha
+.section sychb
+.section sycia
+.section sycib
+.section sycja
+.section sycjb
+.section sycka
+.section syckb
+.section sycla
+.section syclb
+.section sycma
+.section sycmb
+.section sycna
+.section sycnb
+.section sycoa
+.section sycob
+.section sycpa
+.section sycpb
+.section sycqa
+.section sycqb
+.section sycra
+.section sycrb
+.section sycsa
+.section sycsb
+.section sycta
+.section syctb
+.section sycua
+.section sycub
+.section sycva
+.section sycvb
+.section sycwa
+.section sycwb
+.section sycxa
+.section sycxb
+.section sycya
+.section sycyb
+.section sycza
+.section syczb
+.section syc1a
+.section syc1b
+.section syc2a
+.section syc2b
+.section syc3a
+.section syc3b
+.section syc4a
+.section syc4b
+.section syc5a
+.section syc5b
+.section syc6a
+.section syc6b
+.section syc7a
+.section syc7b
+.section syc8a
+.section syc8b
+.section syc9a
+.section syc9b
+.section syc0a
+.section syc0b
+.section sydaa
+.section sydab
+.section sydba
+.section sydbb
+.section sydca
+.section sydcb
+.section sydda
+.section syddb
+.section sydea
+.section sydeb
+.section sydfa
+.section sydfb
+.section sydga
+.section sydgb
+.section sydha
+.section sydhb
+.section sydia
+.section sydib
+.section sydja
+.section sydjb
+.section sydka
+.section sydkb
+.section sydla
+.section sydlb
+.section sydma
+.section sydmb
+.section sydna
+.section sydnb
+.section sydoa
+.section sydob
+.section sydpa
+.section sydpb
+.section sydqa
+.section sydqb
+.section sydra
+.section sydrb
+.section sydsa
+.section sydsb
+.section sydta
+.section sydtb
+.section sydua
+.section sydub
+.section sydva
+.section sydvb
+.section sydwa
+.section sydwb
+.section sydxa
+.section sydxb
+.section sydya
+.section sydyb
+.section sydza
+.section sydzb
+.section syd1a
+.section syd1b
+.section syd2a
+.section syd2b
+.section syd3a
+.section syd3b
+.section syd4a
+.section syd4b
+.section syd5a
+.section syd5b
+.section syd6a
+.section syd6b
+.section syd7a
+.section syd7b
+.section syd8a
+.section syd8b
+.section syd9a
+.section syd9b
+.section syd0a
+.section syd0b
+.section syeaa
+.section syeab
+.section syeba
+.section syebb
+.section syeca
+.section syecb
+.section syeda
+.section syedb
+.section syeea
+.section syeeb
+.section syefa
+.section syefb
+.section syega
+.section syegb
+.section syeha
+.section syehb
+.section syeia
+.section syeib
+.section syeja
+.section syejb
+.section syeka
+.section syekb
+.section syela
+.section syelb
+.section syema
+.section syemb
+.section syena
+.section syenb
+.section syeoa
+.section syeob
+.section syepa
+.section syepb
+.section syeqa
+.section syeqb
+.section syera
+.section syerb
+.section syesa
+.section syesb
+.section syeta
+.section syetb
+.section syeua
+.section syeub
+.section syeva
+.section syevb
+.section syewa
+.section syewb
+.section syexa
+.section syexb
+.section syeya
+.section syeyb
+.section syeza
+.section syezb
+.section sye1a
+.section sye1b
+.section sye2a
+.section sye2b
+.section sye3a
+.section sye3b
+.section sye4a
+.section sye4b
+.section sye5a
+.section sye5b
+.section sye6a
+.section sye6b
+.section sye7a
+.section sye7b
+.section sye8a
+.section sye8b
+.section sye9a
+.section sye9b
+.section sye0a
+.section sye0b
+.section syfaa
+.section syfab
+.section syfba
+.section syfbb
+.section syfca
+.section syfcb
+.section syfda
+.section syfdb
+.section syfea
+.section syfeb
+.section syffa
+.section syffb
+.section syfga
+.section syfgb
+.section syfha
+.section syfhb
+.section syfia
+.section syfib
+.section syfja
+.section syfjb
+.section syfka
+.section syfkb
+.section syfla
+.section syflb
+.section syfma
+.section syfmb
+.section syfna
+.section syfnb
+.section syfoa
+.section syfob
+.section syfpa
+.section syfpb
+.section syfqa
+.section syfqb
+.section syfra
+.section syfrb
+.section syfsa
+.section syfsb
+.section syfta
+.section syftb
+.section syfua
+.section syfub
+.section syfva
+.section syfvb
+.section syfwa
+.section syfwb
+.section syfxa
+.section syfxb
+.section syfya
+.section syfyb
+.section syfza
+.section syfzb
+.section syf1a
+.section syf1b
+.section syf2a
+.section syf2b
+.section syf3a
+.section syf3b
+.section syf4a
+.section syf4b
+.section syf5a
+.section syf5b
+.section syf6a
+.section syf6b
+.section syf7a
+.section syf7b
+.section syf8a
+.section syf8b
+.section syf9a
+.section syf9b
+.section syf0a
+.section syf0b
+.section sygaa
+.section sygab
+.section sygba
+.section sygbb
+.section sygca
+.section sygcb
+.section sygda
+.section sygdb
+.section sygea
+.section sygeb
+.section sygfa
+.section sygfb
+.section sygga
+.section syggb
+.section sygha
+.section syghb
+.section sygia
+.section sygib
+.section sygja
+.section sygjb
+.section sygka
+.section sygkb
+.section sygla
+.section syglb
+.section sygma
+.section sygmb
+.section sygna
+.section sygnb
+.section sygoa
+.section sygob
+.section sygpa
+.section sygpb
+.section sygqa
+.section sygqb
+.section sygra
+.section sygrb
+.section sygsa
+.section sygsb
+.section sygta
+.section sygtb
+.section sygua
+.section sygub
+.section sygva
+.section sygvb
+.section sygwa
+.section sygwb
+.section sygxa
+.section sygxb
+.section sygya
+.section sygyb
+.section sygza
+.section sygzb
+.section syg1a
+.section syg1b
+.section syg2a
+.section syg2b
+.section syg3a
+.section syg3b
+.section syg4a
+.section syg4b
+.section syg5a
+.section syg5b
+.section syg6a
+.section syg6b
+.section syg7a
+.section syg7b
+.section syg8a
+.section syg8b
+.section syg9a
+.section syg9b
+.section syg0a
+.section syg0b
+.section syhaa
+.section syhab
+.section syhba
+.section syhbb
+.section syhca
+.section syhcb
+.section syhda
+.section syhdb
+.section syhea
+.section syheb
+.section syhfa
+.section syhfb
+.section syhga
+.section syhgb
+.section syhha
+.section syhhb
+.section syhia
+.section syhib
+.section syhja
+.section syhjb
+.section syhka
+.section syhkb
+.section syhla
+.section syhlb
+.section syhma
+.section syhmb
+.section syhna
+.section syhnb
+.section syhoa
+.section syhob
+.section syhpa
+.section syhpb
+.section syhqa
+.section syhqb
+.section syhra
+.section syhrb
+.section syhsa
+.section syhsb
+.section syhta
+.section syhtb
+.section syhua
+.section syhub
+.section syhva
+.section syhvb
+.section syhwa
+.section syhwb
+.section syhxa
+.section syhxb
+.section syhya
+.section syhyb
+.section syhza
+.section syhzb
+.section syh1a
+.section syh1b
+.section syh2a
+.section syh2b
+.section syh3a
+.section syh3b
+.section syh4a
+.section syh4b
+.section syh5a
+.section syh5b
+.section syh6a
+.section syh6b
+.section syh7a
+.section syh7b
+.section syh8a
+.section syh8b
+.section syh9a
+.section syh9b
+.section syh0a
+.section syh0b
+.section syiaa
+.section syiab
+.section syiba
+.section syibb
+.section syica
+.section syicb
+.section syida
+.section syidb
+.section syiea
+.section syieb
+.section syifa
+.section syifb
+.section syiga
+.section syigb
+.section syiha
+.section syihb
+.section syiia
+.section syiib
+.section syija
+.section syijb
+.section syika
+.section syikb
+.section syila
+.section syilb
+.section syima
+.section syimb
+.section syina
+.section syinb
+.section syioa
+.section syiob
+.section syipa
+.section syipb
+.section syiqa
+.section syiqb
+.section syira
+.section syirb
+.section syisa
+.section syisb
+.section syita
+.section syitb
+.section syiua
+.section syiub
+.section syiva
+.section syivb
+.section syiwa
+.section syiwb
+.section syixa
+.section syixb
+.section syiya
+.section syiyb
+.section syiza
+.section syizb
+.section syi1a
+.section syi1b
+.section syi2a
+.section syi2b
+.section syi3a
+.section syi3b
+.section syi4a
+.section syi4b
+.section syi5a
+.section syi5b
+.section syi6a
+.section syi6b
+.section syi7a
+.section syi7b
+.section syi8a
+.section syi8b
+.section syi9a
+.section syi9b
+.section syi0a
+.section syi0b
+.section syjaa
+.section syjab
+.section syjba
+.section syjbb
+.section syjca
+.section syjcb
+.section syjda
+.section syjdb
+.section syjea
+.section syjeb
+.section syjfa
+.section syjfb
+.section syjga
+.section syjgb
+.section syjha
+.section syjhb
+.section syjia
+.section syjib
+.section syjja
+.section syjjb
+.section syjka
+.section syjkb
+.section syjla
+.section syjlb
+.section syjma
+.section syjmb
+.section syjna
+.section syjnb
+.section syjoa
+.section syjob
+.section syjpa
+.section syjpb
+.section syjqa
+.section syjqb
+.section syjra
+.section syjrb
+.section syjsa
+.section syjsb
+.section syjta
+.section syjtb
+.section syjua
+.section syjub
+.section syjva
+.section syjvb
+.section syjwa
+.section syjwb
+.section syjxa
+.section syjxb
+.section syjya
+.section syjyb
+.section syjza
+.section syjzb
+.section syj1a
+.section syj1b
+.section syj2a
+.section syj2b
+.section syj3a
+.section syj3b
+.section syj4a
+.section syj4b
+.section syj5a
+.section syj5b
+.section syj6a
+.section syj6b
+.section syj7a
+.section syj7b
+.section syj8a
+.section syj8b
+.section syj9a
+.section syj9b
+.section syj0a
+.section syj0b
+.section sykaa
+.section sykab
+.section sykba
+.section sykbb
+.section sykca
+.section sykcb
+.section sykda
+.section sykdb
+.section sykea
+.section sykeb
+.section sykfa
+.section sykfb
+.section sykga
+.section sykgb
+.section sykha
+.section sykhb
+.section sykia
+.section sykib
+.section sykja
+.section sykjb
+.section sykka
+.section sykkb
+.section sykla
+.section syklb
+.section sykma
+.section sykmb
+.section sykna
+.section syknb
+.section sykoa
+.section sykob
+.section sykpa
+.section sykpb
+.section sykqa
+.section sykqb
+.section sykra
+.section sykrb
+.section syksa
+.section syksb
+.section sykta
+.section syktb
+.section sykua
+.section sykub
+.section sykva
+.section sykvb
+.section sykwa
+.section sykwb
+.section sykxa
+.section sykxb
+.section sykya
+.section sykyb
+.section sykza
+.section sykzb
+.section syk1a
+.section syk1b
+.section syk2a
+.section syk2b
+.section syk3a
+.section syk3b
+.section syk4a
+.section syk4b
+.section syk5a
+.section syk5b
+.section syk6a
+.section syk6b
+.section syk7a
+.section syk7b
+.section syk8a
+.section syk8b
+.section syk9a
+.section syk9b
+.section syk0a
+.section syk0b
+.section sylaa
+.section sylab
+.section sylba
+.section sylbb
+.section sylca
+.section sylcb
+.section sylda
+.section syldb
+.section sylea
+.section syleb
+.section sylfa
+.section sylfb
+.section sylga
+.section sylgb
+.section sylha
+.section sylhb
+.section sylia
+.section sylib
+.section sylja
+.section syljb
+.section sylka
+.section sylkb
+.section sylla
+.section syllb
+.section sylma
+.section sylmb
+.section sylna
+.section sylnb
+.section syloa
+.section sylob
+.section sylpa
+.section sylpb
+.section sylqa
+.section sylqb
+.section sylra
+.section sylrb
+.section sylsa
+.section sylsb
+.section sylta
+.section syltb
+.section sylua
+.section sylub
+.section sylva
+.section sylvb
+.section sylwa
+.section sylwb
+.section sylxa
+.section sylxb
+.section sylya
+.section sylyb
+.section sylza
+.section sylzb
+.section syl1a
+.section syl1b
+.section syl2a
+.section syl2b
+.section syl3a
+.section syl3b
+.section syl4a
+.section syl4b
+.section syl5a
+.section syl5b
+.section syl6a
+.section syl6b
+.section syl7a
+.section syl7b
+.section syl8a
+.section syl8b
+.section syl9a
+.section syl9b
+.section syl0a
+.section syl0b
+.section symaa
+.section symab
+.section symba
+.section symbb
+.section symca
+.section symcb
+.section symda
+.section symdb
+.section symea
+.section symeb
+.section symfa
+.section symfb
+.section symga
+.section symgb
+.section symha
+.section symhb
+.section symia
+.section symib
+.section symja
+.section symjb
+.section symka
+.section symkb
+.section symla
+.section symlb
+.section symma
+.section symmb
+.section symna
+.section symnb
+.section symoa
+.section symob
+.section sympa
+.section sympb
+.section symqa
+.section symqb
+.section symra
+.section symrb
+.section symsa
+.section symsb
+.section symta
+.section symtb
+.section symua
+.section symub
+.section symva
+.section symvb
+.section symwa
+.section symwb
+.section symxa
+.section symxb
+.section symya
+.section symyb
+.section symza
+.section symzb
+.section sym1a
+.section sym1b
+.section sym2a
+.section sym2b
+.section sym3a
+.section sym3b
+.section sym4a
+.section sym4b
+.section sym5a
+.section sym5b
+.section sym6a
+.section sym6b
+.section sym7a
+.section sym7b
+.section sym8a
+.section sym8b
+.section sym9a
+.section sym9b
+.section sym0a
+.section sym0b
+.section synaa
+.section synab
+.section synba
+.section synbb
+.section synca
+.section syncb
+.section synda
+.section syndb
+.section synea
+.section syneb
+.section synfa
+.section synfb
+.section synga
+.section syngb
+.section synha
+.section synhb
+.section synia
+.section synib
+.section synja
+.section synjb
+.section synka
+.section synkb
+.section synla
+.section synlb
+.section synma
+.section synmb
+.section synna
+.section synnb
+.section synoa
+.section synob
+.section synpa
+.section synpb
+.section synqa
+.section synqb
+.section synra
+.section synrb
+.section synsa
+.section synsb
+.section synta
+.section syntb
+.section synua
+.section synub
+.section synva
+.section synvb
+.section synwa
+.section synwb
+.section synxa
+.section synxb
+.section synya
+.section synyb
+.section synza
+.section synzb
+.section syn1a
+.section syn1b
+.section syn2a
+.section syn2b
+.section syn3a
+.section syn3b
+.section syn4a
+.section syn4b
+.section syn5a
+.section syn5b
+.section syn6a
+.section syn6b
+.section syn7a
+.section syn7b
+.section syn8a
+.section syn8b
+.section syn9a
+.section syn9b
+.section syn0a
+.section syn0b
+.section syoaa
+.section syoab
+.section syoba
+.section syobb
+.section syoca
+.section syocb
+.section syoda
+.section syodb
+.section syoea
+.section syoeb
+.section syofa
+.section syofb
+.section syoga
+.section syogb
+.section syoha
+.section syohb
+.section syoia
+.section syoib
+.section syoja
+.section syojb
+.section syoka
+.section syokb
+.section syola
+.section syolb
+.section syoma
+.section syomb
+.section syona
+.section syonb
+.section syooa
+.section syoob
+.section syopa
+.section syopb
+.section syoqa
+.section syoqb
+.section syora
+.section syorb
+.section syosa
+.section syosb
+.section syota
+.section syotb
+.section syoua
+.section syoub
+.section syova
+.section syovb
+.section syowa
+.section syowb
+.section syoxa
+.section syoxb
+.section syoya
+.section syoyb
+.section syoza
+.section syozb
+.section syo1a
+.section syo1b
+.section syo2a
+.section syo2b
+.section syo3a
+.section syo3b
+.section syo4a
+.section syo4b
+.section syo5a
+.section syo5b
+.section syo6a
+.section syo6b
+.section syo7a
+.section syo7b
+.section syo8a
+.section syo8b
+.section syo9a
+.section syo9b
+.section syo0a
+.section syo0b
+.section sypaa
+.section sypab
+.section sypba
+.section sypbb
+.section sypca
+.section sypcb
+.section sypda
+.section sypdb
+.section sypea
+.section sypeb
+.section sypfa
+.section sypfb
+.section sypga
+.section sypgb
+.section sypha
+.section syphb
+.section sypia
+.section sypib
+.section sypja
+.section sypjb
+.section sypka
+.section sypkb
+.section sypla
+.section syplb
+.section sypma
+.section sypmb
+.section sypna
+.section sypnb
+.section sypoa
+.section sypob
+.section syppa
+.section syppb
+.section sypqa
+.section sypqb
+.section sypra
+.section syprb
+.section sypsa
+.section sypsb
+.section sypta
+.section syptb
+.section sypua
+.section sypub
+.section sypva
+.section sypvb
+.section sypwa
+.section sypwb
+.section sypxa
+.section sypxb
+.section sypya
+.section sypyb
+.section sypza
+.section sypzb
+.section syp1a
+.section syp1b
+.section syp2a
+.section syp2b
+.section syp3a
+.section syp3b
+.section syp4a
+.section syp4b
+.section syp5a
+.section syp5b
+.section syp6a
+.section syp6b
+.section syp7a
+.section syp7b
+.section syp8a
+.section syp8b
+.section syp9a
+.section syp9b
+.section syp0a
+.section syp0b
+.section syqaa
+.section syqab
+.section syqba
+.section syqbb
+.section syqca
+.section syqcb
+.section syqda
+.section syqdb
+.section syqea
+.section syqeb
+.section syqfa
+.section syqfb
+.section syqga
+.section syqgb
+.section syqha
+.section syqhb
+.section syqia
+.section syqib
+.section syqja
+.section syqjb
+.section syqka
+.section syqkb
+.section syqla
+.section syqlb
+.section syqma
+.section syqmb
+.section syqna
+.section syqnb
+.section syqoa
+.section syqob
+.section syqpa
+.section syqpb
+.section syqqa
+.section syqqb
+.section syqra
+.section syqrb
+.section syqsa
+.section syqsb
+.section syqta
+.section syqtb
+.section syqua
+.section syqub
+.section syqva
+.section syqvb
+.section syqwa
+.section syqwb
+.section syqxa
+.section syqxb
+.section syqya
+.section syqyb
+.section syqza
+.section syqzb
+.section syq1a
+.section syq1b
+.section syq2a
+.section syq2b
+.section syq3a
+.section syq3b
+.section syq4a
+.section syq4b
+.section syq5a
+.section syq5b
+.section syq6a
+.section syq6b
+.section syq7a
+.section syq7b
+.section syq8a
+.section syq8b
+.section syq9a
+.section syq9b
+.section syq0a
+.section syq0b
+.section syraa
+.section syrab
+.section syrba
+.section syrbb
+.section syrca
+.section syrcb
+.section syrda
+.section syrdb
+.section syrea
+.section syreb
+.section syrfa
+.section syrfb
+.section syrga
+.section syrgb
+.section syrha
+.section syrhb
+.section syria
+.section syrib
+.section syrja
+.section syrjb
+.section syrka
+.section syrkb
+.section syrla
+.section syrlb
+.section syrma
+.section syrmb
+.section syrna
+.section syrnb
+.section syroa
+.section syrob
+.section syrpa
+.section syrpb
+.section syrqa
+.section syrqb
+.section syrra
+.section syrrb
+.section syrsa
+.section syrsb
+.section syrta
+.section syrtb
+.section syrua
+.section syrub
+.section syrva
+.section syrvb
+.section syrwa
+.section syrwb
+.section syrxa
+.section syrxb
+.section syrya
+.section syryb
+.section syrza
+.section syrzb
+.section syr1a
+.section syr1b
+.section syr2a
+.section syr2b
+.section syr3a
+.section syr3b
+.section syr4a
+.section syr4b
+.section syr5a
+.section syr5b
+.section syr6a
+.section syr6b
+.section syr7a
+.section syr7b
+.section syr8a
+.section syr8b
+.section syr9a
+.section syr9b
+.section syr0a
+.section syr0b
+.section sysaa
+.section sysab
+.section sysba
+.section sysbb
+.section sysca
+.section syscb
+.section sysda
+.section sysdb
+.section sysea
+.section syseb
+.section sysfa
+.section sysfb
+.section sysga
+.section sysgb
+.section sysha
+.section syshb
+.section sysia
+.section sysib
+.section sysja
+.section sysjb
+.section syska
+.section syskb
+.section sysla
+.section syslb
+.section sysma
+.section sysmb
+.section sysna
+.section sysnb
+.section sysoa
+.section sysob
+.section syspa
+.section syspb
+.section sysqa
+.section sysqb
+.section sysra
+.section sysrb
+.section syssa
+.section syssb
+.section systa
+.section systb
+.section sysua
+.section sysub
+.section sysva
+.section sysvb
+.section syswa
+.section syswb
+.section sysxa
+.section sysxb
+.section sysya
+.section sysyb
+.section sysza
+.section syszb
+.section sys1a
+.section sys1b
+.section sys2a
+.section sys2b
+.section sys3a
+.section sys3b
+.section sys4a
+.section sys4b
+.section sys5a
+.section sys5b
+.section sys6a
+.section sys6b
+.section sys7a
+.section sys7b
+.section sys8a
+.section sys8b
+.section sys9a
+.section sys9b
+.section sys0a
+.section sys0b
+.section sytaa
+.section sytab
+.section sytba
+.section sytbb
+.section sytca
+.section sytcb
+.section sytda
+.section sytdb
+.section sytea
+.section syteb
+.section sytfa
+.section sytfb
+.section sytga
+.section sytgb
+.section sytha
+.section sythb
+.section sytia
+.section sytib
+.section sytja
+.section sytjb
+.section sytka
+.section sytkb
+.section sytla
+.section sytlb
+.section sytma
+.section sytmb
+.section sytna
+.section sytnb
+.section sytoa
+.section sytob
+.section sytpa
+.section sytpb
+.section sytqa
+.section sytqb
+.section sytra
+.section sytrb
+.section sytsa
+.section sytsb
+.section sytta
+.section syttb
+.section sytua
+.section sytub
+.section sytva
+.section sytvb
+.section sytwa
+.section sytwb
+.section sytxa
+.section sytxb
+.section sytya
+.section sytyb
+.section sytza
+.section sytzb
+.section syt1a
+.section syt1b
+.section syt2a
+.section syt2b
+.section syt3a
+.section syt3b
+.section syt4a
+.section syt4b
+.section syt5a
+.section syt5b
+.section syt6a
+.section syt6b
+.section syt7a
+.section syt7b
+.section syt8a
+.section syt8b
+.section syt9a
+.section syt9b
+.section syt0a
+.section syt0b
+.section syuaa
+.section syuab
+.section syuba
+.section syubb
+.section syuca
+.section syucb
+.section syuda
+.section syudb
+.section syuea
+.section syueb
+.section syufa
+.section syufb
+.section syuga
+.section syugb
+.section syuha
+.section syuhb
+.section syuia
+.section syuib
+.section syuja
+.section syujb
+.section syuka
+.section syukb
+.section syula
+.section syulb
+.section syuma
+.section syumb
+.section syuna
+.section syunb
+.section syuoa
+.section syuob
+.section syupa
+.section syupb
+.section syuqa
+.section syuqb
+.section syura
+.section syurb
+.section syusa
+.section syusb
+.section syuta
+.section syutb
+.section syuua
+.section syuub
+.section syuva
+.section syuvb
+.section syuwa
+.section syuwb
+.section syuxa
+.section syuxb
+.section syuya
+.section syuyb
+.section syuza
+.section syuzb
+.section syu1a
+.section syu1b
+.section syu2a
+.section syu2b
+.section syu3a
+.section syu3b
+.section syu4a
+.section syu4b
+.section syu5a
+.section syu5b
+.section syu6a
+.section syu6b
+.section syu7a
+.section syu7b
+.section syu8a
+.section syu8b
+.section syu9a
+.section syu9b
+.section syu0a
+.section syu0b
+.section syvaa
+.section syvab
+.section syvba
+.section syvbb
+.section syvca
+.section syvcb
+.section syvda
+.section syvdb
+.section syvea
+.section syveb
+.section syvfa
+.section syvfb
+.section syvga
+.section syvgb
+.section syvha
+.section syvhb
+.section syvia
+.section syvib
+.section syvja
+.section syvjb
+.section syvka
+.section syvkb
+.section syvla
+.section syvlb
+.section syvma
+.section syvmb
+.section syvna
+.section syvnb
+.section syvoa
+.section syvob
+.section syvpa
+.section syvpb
+.section syvqa
+.section syvqb
+.section syvra
+.section syvrb
+.section syvsa
+.section syvsb
+.section syvta
+.section syvtb
+.section syvua
+.section syvub
+.section syvva
+.section syvvb
+.section syvwa
+.section syvwb
+.section syvxa
+.section syvxb
+.section syvya
+.section syvyb
+.section syvza
+.section syvzb
+.section syv1a
+.section syv1b
+.section syv2a
+.section syv2b
+.section syv3a
+.section syv3b
+.section syv4a
+.section syv4b
+.section syv5a
+.section syv5b
+.section syv6a
+.section syv6b
+.section syv7a
+.section syv7b
+.section syv8a
+.section syv8b
+.section syv9a
+.section syv9b
+.section syv0a
+.section syv0b
+.section sywaa
+.section sywab
+.section sywba
+.section sywbb
+.section sywca
+.section sywcb
+.section sywda
+.section sywdb
+.section sywea
+.section syweb
+.section sywfa
+.section sywfb
+.section sywga
+.section sywgb
+.section sywha
+.section sywhb
+.section sywia
+.section sywib
+.section sywja
+.section sywjb
+.section sywka
+.section sywkb
+.section sywla
+.section sywlb
+.section sywma
+.section sywmb
+.section sywna
+.section sywnb
+.section sywoa
+.section sywob
+.section sywpa
+.section sywpb
+.section sywqa
+.section sywqb
+.section sywra
+.section sywrb
+.section sywsa
+.section sywsb
+.section sywta
+.section sywtb
+.section sywua
+.section sywub
+.section sywva
+.section sywvb
+.section sywwa
+.section sywwb
+.section sywxa
+.section sywxb
+.section sywya
+.section sywyb
+.section sywza
+.section sywzb
+.section syw1a
+.section syw1b
+.section syw2a
+.section syw2b
+.section syw3a
+.section syw3b
+.section syw4a
+.section syw4b
+.section syw5a
+.section syw5b
+.section syw6a
+.section syw6b
+.section syw7a
+.section syw7b
+.section syw8a
+.section syw8b
+.section syw9a
+.section syw9b
+.section syw0a
+.section syw0b
+.section syxaa
+.section syxab
+.section syxba
+.section syxbb
+.section syxca
+.section syxcb
+.section syxda
+.section syxdb
+.section syxea
+.section syxeb
+.section syxfa
+.section syxfb
+.section syxga
+.section syxgb
+.section syxha
+.section syxhb
+.section syxia
+.section syxib
+.section syxja
+.section syxjb
+.section syxka
+.section syxkb
+.section syxla
+.section syxlb
+.section syxma
+.section syxmb
+.section syxna
+.section syxnb
+.section syxoa
+.section syxob
+.section syxpa
+.section syxpb
+.section syxqa
+.section syxqb
+.section syxra
+.section syxrb
+.section syxsa
+.section syxsb
+.section syxta
+.section syxtb
+.section syxua
+.section syxub
+.section syxva
+.section syxvb
+.section syxwa
+.section syxwb
+.section syxxa
+.section syxxb
+.section syxya
+.section syxyb
+.section syxza
+.section syxzb
+.section syx1a
+.section syx1b
+.section syx2a
+.section syx2b
+.section syx3a
+.section syx3b
+.section syx4a
+.section syx4b
+.section syx5a
+.section syx5b
+.section syx6a
+.section syx6b
+.section syx7a
+.section syx7b
+.section syx8a
+.section syx8b
+.section syx9a
+.section syx9b
+.section syx0a
+.section syx0b
+.section syyaa
+.section syyab
+.section syyba
+.section syybb
+.section syyca
+.section syycb
+.section syyda
+.section syydb
+.section syyea
+.section syyeb
+.section syyfa
+.section syyfb
+.section syyga
+.section syygb
+.section syyha
+.section syyhb
+.section syyia
+.section syyib
+.section syyja
+.section syyjb
+.section syyka
+.section syykb
+.section syyla
+.section syylb
+.section syyma
+.section syymb
+.section syyna
+.section syynb
+.section syyoa
+.section syyob
+.section syypa
+.section syypb
+.section syyqa
+.section syyqb
+.section syyra
+.section syyrb
+.section syysa
+.section syysb
+.section syyta
+.section syytb
+.section syyua
+.section syyub
+.section syyva
+.section syyvb
+.section syywa
+.section syywb
+.section syyxa
+.section syyxb
+.section syyya
+.section syyyb
+.section syyza
+.section syyzb
+.section syy1a
+.section syy1b
+.section syy2a
+.section syy2b
+.section syy3a
+.section syy3b
+.section syy4a
+.section syy4b
+.section syy5a
+.section syy5b
+.section syy6a
+.section syy6b
+.section syy7a
+.section syy7b
+.section syy8a
+.section syy8b
+.section syy9a
+.section syy9b
+.section syy0a
+.section syy0b
+.section syzaa
+.section syzab
+.section syzba
+.section syzbb
+.section syzca
+.section syzcb
+.section syzda
+.section syzdb
+.section syzea
+.section syzeb
+.section syzfa
+.section syzfb
+.section syzga
+.section syzgb
+.section syzha
+.section syzhb
+.section syzia
+.section syzib
+.section syzja
+.section syzjb
+.section syzka
+.section syzkb
+.section syzla
+.section syzlb
+.section syzma
+.section syzmb
+.section syzna
+.section syznb
+.section syzoa
+.section syzob
+.section syzpa
+.section syzpb
+.section syzqa
+.section syzqb
+.section syzra
+.section syzrb
+.section syzsa
+.section syzsb
+.section syzta
+.section syztb
+.section syzua
+.section syzub
+.section syzva
+.section syzvb
+.section syzwa
+.section syzwb
+.section syzxa
+.section syzxb
+.section syzya
+.section syzyb
+.section syzza
+.section syzzb
+.section syz1a
+.section syz1b
+.section syz2a
+.section syz2b
+.section syz3a
+.section syz3b
+.section syz4a
+.section syz4b
+.section syz5a
+.section syz5b
+.section syz6a
+.section syz6b
+.section syz7a
+.section syz7b
+.section syz8a
+.section syz8b
+.section syz9a
+.section syz9b
+.section syz0a
+.section syz0b
+.section sy1aa
+.section sy1ab
+.section sy1ba
+.section sy1bb
+.section sy1ca
+.section sy1cb
+.section sy1da
+.section sy1db
+.section sy1ea
+.section sy1eb
+.section sy1fa
+.section sy1fb
+.section sy1ga
+.section sy1gb
+.section sy1ha
+.section sy1hb
+.section sy1ia
+.section sy1ib
+.section sy1ja
+.section sy1jb
+.section sy1ka
+.section sy1kb
+.section sy1la
+.section sy1lb
+.section sy1ma
+.section sy1mb
+.section sy1na
+.section sy1nb
+.section sy1oa
+.section sy1ob
+.section sy1pa
+.section sy1pb
+.section sy1qa
+.section sy1qb
+.section sy1ra
+.section sy1rb
+.section sy1sa
+.section sy1sb
+.section sy1ta
+.section sy1tb
+.section sy1ua
+.section sy1ub
+.section sy1va
+.section sy1vb
+.section sy1wa
+.section sy1wb
+.section sy1xa
+.section sy1xb
+.section sy1ya
+.section sy1yb
+.section sy1za
+.section sy1zb
+.section sy11a
+.section sy11b
+.section sy12a
+.section sy12b
+.section sy13a
+.section sy13b
+.section sy14a
+.section sy14b
+.section sy15a
+.section sy15b
+.section sy16a
+.section sy16b
+.section sy17a
+.section sy17b
+.section sy18a
+.section sy18b
+.section sy19a
+.section sy19b
+.section sy10a
+.section sy10b
+.section sy2aa
+.section sy2ab
+.section sy2ba
+.section sy2bb
+.section sy2ca
+.section sy2cb
+.section sy2da
+.section sy2db
+.section sy2ea
+.section sy2eb
+.section sy2fa
+.section sy2fb
+.section sy2ga
+.section sy2gb
+.section sy2ha
+.section sy2hb
+.section sy2ia
+.section sy2ib
+.section sy2ja
+.section sy2jb
+.section sy2ka
+.section sy2kb
+.section sy2la
+.section sy2lb
+.section sy2ma
+.section sy2mb
+.section sy2na
+.section sy2nb
+.section sy2oa
+.section sy2ob
+.section sy2pa
+.section sy2pb
+.section sy2qa
+.section sy2qb
+.section sy2ra
+.section sy2rb
+.section sy2sa
+.section sy2sb
+.section sy2ta
+.section sy2tb
+.section sy2ua
+.section sy2ub
+.section sy2va
+.section sy2vb
+.section sy2wa
+.section sy2wb
+.section sy2xa
+.section sy2xb
+.section sy2ya
+.section sy2yb
+.section sy2za
+.section sy2zb
+.section sy21a
+.section sy21b
+.section sy22a
+.section sy22b
+.section sy23a
+.section sy23b
+.section sy24a
+.section sy24b
+.section sy25a
+.section sy25b
+.section sy26a
+.section sy26b
+.section sy27a
+.section sy27b
+.section sy28a
+.section sy28b
+.section sy29a
+.section sy29b
+.section sy20a
+.section sy20b
+.section sy3aa
+.section sy3ab
+.section sy3ba
+.section sy3bb
+.section sy3ca
+.section sy3cb
+.section sy3da
+.section sy3db
+.section sy3ea
+.section sy3eb
+.section sy3fa
+.section sy3fb
+.section sy3ga
+.section sy3gb
+.section sy3ha
+.section sy3hb
+.section sy3ia
+.section sy3ib
+.section sy3ja
+.section sy3jb
+.section sy3ka
+.section sy3kb
+.section sy3la
+.section sy3lb
+.section sy3ma
+.section sy3mb
+.section sy3na
+.section sy3nb
+.section sy3oa
+.section sy3ob
+.section sy3pa
+.section sy3pb
+.section sy3qa
+.section sy3qb
+.section sy3ra
+.section sy3rb
+.section sy3sa
+.section sy3sb
+.section sy3ta
+.section sy3tb
+.section sy3ua
+.section sy3ub
+.section sy3va
+.section sy3vb
+.section sy3wa
+.section sy3wb
+.section sy3xa
+.section sy3xb
+.section sy3ya
+.section sy3yb
+.section sy3za
+.section sy3zb
+.section sy31a
+.section sy31b
+.section sy32a
+.section sy32b
+.section sy33a
+.section sy33b
+.section sy34a
+.section sy34b
+.section sy35a
+.section sy35b
+.section sy36a
+.section sy36b
+.section sy37a
+.section sy37b
+.section sy38a
+.section sy38b
+.section sy39a
+.section sy39b
+.section sy30a
+.section sy30b
+.section sy4aa
+.section sy4ab
+.section sy4ba
+.section sy4bb
+.section sy4ca
+.section sy4cb
+.section sy4da
+.section sy4db
+.section sy4ea
+.section sy4eb
+.section sy4fa
+.section sy4fb
+.section sy4ga
+.section sy4gb
+.section sy4ha
+.section sy4hb
+.section sy4ia
+.section sy4ib
+.section sy4ja
+.section sy4jb
+.section sy4ka
+.section sy4kb
+.section sy4la
+.section sy4lb
+.section sy4ma
+.section sy4mb
+.section sy4na
+.section sy4nb
+.section sy4oa
+.section sy4ob
+.section sy4pa
+.section sy4pb
+.section sy4qa
+.section sy4qb
+.section sy4ra
+.section sy4rb
+.section sy4sa
+.section sy4sb
+.section sy4ta
+.section sy4tb
+.section sy4ua
+.section sy4ub
+.section sy4va
+.section sy4vb
+.section sy4wa
+.section sy4wb
+.section sy4xa
+.section sy4xb
+.section sy4ya
+.section sy4yb
+.section sy4za
+.section sy4zb
+.section sy41a
+.section sy41b
+.section sy42a
+.section sy42b
+.section sy43a
+.section sy43b
+.section sy44a
+.section sy44b
+.section sy45a
+.section sy45b
+.section sy46a
+.section sy46b
+.section sy47a
+.section sy47b
+.section sy48a
+.section sy48b
+.section sy49a
+.section sy49b
+.section sy40a
+.section sy40b
+.section sy5aa
+.section sy5ab
+.section sy5ba
+.section sy5bb
+.section sy5ca
+.section sy5cb
+.section sy5da
+.section sy5db
+.section sy5ea
+.section sy5eb
+.section sy5fa
+.section sy5fb
+.section sy5ga
+.section sy5gb
+.section sy5ha
+.section sy5hb
+.section sy5ia
+.section sy5ib
+.section sy5ja
+.section sy5jb
+.section sy5ka
+.section sy5kb
+.section sy5la
+.section sy5lb
+.section sy5ma
+.section sy5mb
+.section sy5na
+.section sy5nb
+.section sy5oa
+.section sy5ob
+.section sy5pa
+.section sy5pb
+.section sy5qa
+.section sy5qb
+.section sy5ra
+.section sy5rb
+.section sy5sa
+.section sy5sb
+.section sy5ta
+.section sy5tb
+.section sy5ua
+.section sy5ub
+.section sy5va
+.section sy5vb
+.section sy5wa
+.section sy5wb
+.section sy5xa
+.section sy5xb
+.section sy5ya
+.section sy5yb
+.section sy5za
+.section sy5zb
+.section sy51a
+.section sy51b
+.section sy52a
+.section sy52b
+.section sy53a
+.section sy53b
+.section sy54a
+.section sy54b
+.section sy55a
+.section sy55b
+.section sy56a
+.section sy56b
+.section sy57a
+.section sy57b
+.section sy58a
+.section sy58b
+.section sy59a
+.section sy59b
+.section sy50a
+.section sy50b
+.section sy6aa
+.section sy6ab
+.section sy6ba
+.section sy6bb
+.section sy6ca
+.section sy6cb
+.section sy6da
+.section sy6db
+.section sy6ea
+.section sy6eb
+.section sy6fa
+.section sy6fb
+.section sy6ga
+.section sy6gb
+.section sy6ha
+.section sy6hb
+.section sy6ia
+.section sy6ib
+.section sy6ja
+.section sy6jb
+.section sy6ka
+.section sy6kb
+.section sy6la
+.section sy6lb
+.section sy6ma
+.section sy6mb
+.section sy6na
+.section sy6nb
+.section sy6oa
+.section sy6ob
+.section sy6pa
+.section sy6pb
+.section sy6qa
+.section sy6qb
+.section sy6ra
+.section sy6rb
+.section sy6sa
+.section sy6sb
+.section sy6ta
+.section sy6tb
+.section sy6ua
+.section sy6ub
+.section sy6va
+.section sy6vb
+.section sy6wa
+.section sy6wb
+.section sy6xa
+.section sy6xb
+.section sy6ya
+.section sy6yb
+.section sy6za
+.section sy6zb
+.section sy61a
+.section sy61b
+.section sy62a
+.section sy62b
+.section sy63a
+.section sy63b
+.section sy64a
+.section sy64b
+.section sy65a
+.section sy65b
+.section sy66a
+.section sy66b
+.section sy67a
+.section sy67b
+.section sy68a
+.section sy68b
+.section sy69a
+.section sy69b
+.section sy60a
+.section sy60b
+.section sy7aa
+.section sy7ab
+.section sy7ba
+.section sy7bb
+.section sy7ca
+.section sy7cb
+.section sy7da
+.section sy7db
+.section sy7ea
+.section sy7eb
+.section sy7fa
+.section sy7fb
+.section sy7ga
+.section sy7gb
+.section sy7ha
+.section sy7hb
+.section sy7ia
+.section sy7ib
+.section sy7ja
+.section sy7jb
+.section sy7ka
+.section sy7kb
+.section sy7la
+.section sy7lb
+.section sy7ma
+.section sy7mb
+.section sy7na
+.section sy7nb
+.section sy7oa
+.section sy7ob
+.section sy7pa
+.section sy7pb
+.section sy7qa
+.section sy7qb
+.section sy7ra
+.section sy7rb
+.section sy7sa
+.section sy7sb
+.section sy7ta
+.section sy7tb
+.section sy7ua
+.section sy7ub
+.section sy7va
+.section sy7vb
+.section sy7wa
+.section sy7wb
+.section sy7xa
+.section sy7xb
+.section sy7ya
+.section sy7yb
+.section sy7za
+.section sy7zb
+.section sy71a
+.section sy71b
+.section sy72a
+.section sy72b
+.section sy73a
+.section sy73b
+.section sy74a
+.section sy74b
+.section sy75a
+.section sy75b
+.section sy76a
+.section sy76b
+.section sy77a
+.section sy77b
+.section sy78a
+.section sy78b
+.section sy79a
+.section sy79b
+.section sy70a
+.section sy70b
+.section sy8aa
+.section sy8ab
+.section sy8ba
+.section sy8bb
+.section sy8ca
+.section sy8cb
+.section sy8da
+.section sy8db
+.section sy8ea
+.section sy8eb
+.section sy8fa
+.section sy8fb
+.section sy8ga
+.section sy8gb
+.section sy8ha
+.section sy8hb
+.section sy8ia
+.section sy8ib
+.section sy8ja
+.section sy8jb
+.section sy8ka
+.section sy8kb
+.section sy8la
+.section sy8lb
+.section sy8ma
+.section sy8mb
+.section sy8na
+.section sy8nb
+.section sy8oa
+.section sy8ob
+.section sy8pa
+.section sy8pb
+.section sy8qa
+.section sy8qb
+.section sy8ra
+.section sy8rb
+.section sy8sa
+.section sy8sb
+.section sy8ta
+.section sy8tb
+.section sy8ua
+.section sy8ub
+.section sy8va
+.section sy8vb
+.section sy8wa
+.section sy8wb
+.section sy8xa
+.section sy8xb
+.section sy8ya
+.section sy8yb
+.section sy8za
+.section sy8zb
+.section sy81a
+.section sy81b
+.section sy82a
+.section sy82b
+.section sy83a
+.section sy83b
+.section sy84a
+.section sy84b
+.section sy85a
+.section sy85b
+.section sy86a
+.section sy86b
+.section sy87a
+.section sy87b
+.section sy88a
+.section sy88b
+.section sy89a
+.section sy89b
+.section sy80a
+.section sy80b
+.section sy9aa
+.section sy9ab
+.section sy9ba
+.section sy9bb
+.section sy9ca
+.section sy9cb
+.section sy9da
+.section sy9db
+.section sy9ea
+.section sy9eb
+.section sy9fa
+.section sy9fb
+.section sy9ga
+.section sy9gb
+.section sy9ha
+.section sy9hb
+.section sy9ia
+.section sy9ib
+.section sy9ja
+.section sy9jb
+.section sy9ka
+.section sy9kb
+.section sy9la
+.section sy9lb
+.section sy9ma
+.section sy9mb
+.section sy9na
+.section sy9nb
+.section sy9oa
+.section sy9ob
+.section sy9pa
+.section sy9pb
+.section sy9qa
+.section sy9qb
+.section sy9ra
+.section sy9rb
+.section sy9sa
+.section sy9sb
+.section sy9ta
+.section sy9tb
+.section sy9ua
+.section sy9ub
+.section sy9va
+.section sy9vb
+.section sy9wa
+.section sy9wb
+.section sy9xa
+.section sy9xb
+.section sy9ya
+.section sy9yb
+.section sy9za
+.section sy9zb
+.section sy91a
+.section sy91b
+.section sy92a
+.section sy92b
+.section sy93a
+.section sy93b
+.section sy94a
+.section sy94b
+.section sy95a
+.section sy95b
+.section sy96a
+.section sy96b
+.section sy97a
+.section sy97b
+.section sy98a
+.section sy98b
+.section sy99a
+.section sy99b
+.section sy90a
+.section sy90b
+.section sy0aa
+.section sy0ab
+.section sy0ba
+.section sy0bb
+.section sy0ca
+.section sy0cb
+.section sy0da
+.section sy0db
+.section sy0ea
+.section sy0eb
+.section sy0fa
+.section sy0fb
+.section sy0ga
+.section sy0gb
+.section sy0ha
+.section sy0hb
+.section sy0ia
+.section sy0ib
+.section sy0ja
+.section sy0jb
+.section sy0ka
+.section sy0kb
+.section sy0la
+.section sy0lb
+.section sy0ma
+.section sy0mb
+.section sy0na
+.section sy0nb
+.section sy0oa
+.section sy0ob
+.section sy0pa
+.section sy0pb
+.section sy0qa
+.section sy0qb
+.section sy0ra
+.section sy0rb
+.section sy0sa
+.section sy0sb
+.section sy0ta
+.section sy0tb
+.section sy0ua
+.section sy0ub
+.section sy0va
+.section sy0vb
+.section sy0wa
+.section sy0wb
+.section sy0xa
+.section sy0xb
+.section sy0ya
+.section sy0yb
+.section sy0za
+.section sy0zb
+.section sy01a
+.section sy01b
+.section sy02a
+.section sy02b
+.section sy03a
+.section sy03b
+.section sy04a
+.section sy04b
+.section sy05a
+.section sy05b
+.section sy06a
+.section sy06b
+.section sy07a
+.section sy07b
+.section sy08a
+.section sy08b
+.section sy09a
+.section sy09b
+.section sy00a
+.section sy00b
+.section szaaa
+.section szaab
+.section szaba
+.section szabb
+.section szaca
+.section szacb
+.section szada
+.section szadb
+.section szaea
+.section szaeb
+.section szafa
+.section szafb
+.section szaga
+.section szagb
+.section szaha
+.section szahb
+.section szaia
+.section szaib
+.section szaja
+.section szajb
+.section szaka
+.section szakb
+.section szala
+.section szalb
+.section szama
+.section szamb
+.section szana
+.section szanb
+.section szaoa
+.section szaob
+.section szapa
+.section szapb
+.section szaqa
+.section szaqb
+.section szara
+.section szarb
+.section szasa
+.section szasb
+.section szata
+.section szatb
+.section szaua
+.section szaub
+.section szava
+.section szavb
+.section szawa
+.section szawb
+.section szaxa
+.section szaxb
+.section szaya
+.section szayb
+.section szaza
+.section szazb
+.section sza1a
+.section sza1b
+.section sza2a
+.section sza2b
+.section sza3a
+.section sza3b
+.section sza4a
+.section sza4b
+.section sza5a
+.section sza5b
+.section sza6a
+.section sza6b
+.section sza7a
+.section sza7b
+.section sza8a
+.section sza8b
+.section sza9a
+.section sza9b
+.section sza0a
+.section sza0b
+.section szbaa
+.section szbab
+.section szbba
+.section szbbb
+.section szbca
+.section szbcb
+.section szbda
+.section szbdb
+.section szbea
+.section szbeb
+.section szbfa
+.section szbfb
+.section szbga
+.section szbgb
+.section szbha
+.section szbhb
+.section szbia
+.section szbib
+.section szbja
+.section szbjb
+.section szbka
+.section szbkb
+.section szbla
+.section szblb
+.section szbma
+.section szbmb
+.section szbna
+.section szbnb
+.section szboa
+.section szbob
+.section szbpa
+.section szbpb
+.section szbqa
+.section szbqb
+.section szbra
+.section szbrb
+.section szbsa
+.section szbsb
+.section szbta
+.section szbtb
+.section szbua
+.section szbub
+.section szbva
+.section szbvb
+.section szbwa
+.section szbwb
+.section szbxa
+.section szbxb
+.section szbya
+.section szbyb
+.section szbza
+.section szbzb
+.section szb1a
+.section szb1b
+.section szb2a
+.section szb2b
+.section szb3a
+.section szb3b
+.section szb4a
+.section szb4b
+.section szb5a
+.section szb5b
+.section szb6a
+.section szb6b
+.section szb7a
+.section szb7b
+.section szb8a
+.section szb8b
+.section szb9a
+.section szb9b
+.section szb0a
+.section szb0b
+.section szcaa
+.section szcab
+.section szcba
+.section szcbb
+.section szcca
+.section szccb
+.section szcda
+.section szcdb
+.section szcea
+.section szceb
+.section szcfa
+.section szcfb
+.section szcga
+.section szcgb
+.section szcha
+.section szchb
+.section szcia
+.section szcib
+.section szcja
+.section szcjb
+.section szcka
+.section szckb
+.section szcla
+.section szclb
+.section szcma
+.section szcmb
+.section szcna
+.section szcnb
+.section szcoa
+.section szcob
+.section szcpa
+.section szcpb
+.section szcqa
+.section szcqb
+.section szcra
+.section szcrb
+.section szcsa
+.section szcsb
+.section szcta
+.section szctb
+.section szcua
+.section szcub
+.section szcva
+.section szcvb
+.section szcwa
+.section szcwb
+.section szcxa
+.section szcxb
+.section szcya
+.section szcyb
+.section szcza
+.section szczb
+.section szc1a
+.section szc1b
+.section szc2a
+.section szc2b
+.section szc3a
+.section szc3b
+.section szc4a
+.section szc4b
+.section szc5a
+.section szc5b
+.section szc6a
+.section szc6b
+.section szc7a
+.section szc7b
+.section szc8a
+.section szc8b
+.section szc9a
+.section szc9b
+.section szc0a
+.section szc0b
+.section szdaa
+.section szdab
+.section szdba
+.section szdbb
+.section szdca
+.section szdcb
+.section szdda
+.section szddb
+.section szdea
+.section szdeb
+.section szdfa
+.section szdfb
+.section szdga
+.section szdgb
+.section szdha
+.section szdhb
+.section szdia
+.section szdib
+.section szdja
+.section szdjb
+.section szdka
+.section szdkb
+.section szdla
+.section szdlb
+.section szdma
+.section szdmb
+.section szdna
+.section szdnb
+.section szdoa
+.section szdob
+.section szdpa
+.section szdpb
+.section szdqa
+.section szdqb
+.section szdra
+.section szdrb
+.section szdsa
+.section szdsb
+.section szdta
+.section szdtb
+.section szdua
+.section szdub
+.section szdva
+.section szdvb
+.section szdwa
+.section szdwb
+.section szdxa
+.section szdxb
+.section szdya
+.section szdyb
+.section szdza
+.section szdzb
+.section szd1a
+.section szd1b
+.section szd2a
+.section szd2b
+.section szd3a
+.section szd3b
+.section szd4a
+.section szd4b
+.section szd5a
+.section szd5b
+.section szd6a
+.section szd6b
+.section szd7a
+.section szd7b
+.section szd8a
+.section szd8b
+.section szd9a
+.section szd9b
+.section szd0a
+.section szd0b
+.section szeaa
+.section szeab
+.section szeba
+.section szebb
+.section szeca
+.section szecb
+.section szeda
+.section szedb
+.section szeea
+.section szeeb
+.section szefa
+.section szefb
+.section szega
+.section szegb
+.section szeha
+.section szehb
+.section szeia
+.section szeib
+.section szeja
+.section szejb
+.section szeka
+.section szekb
+.section szela
+.section szelb
+.section szema
+.section szemb
+.section szena
+.section szenb
+.section szeoa
+.section szeob
+.section szepa
+.section szepb
+.section szeqa
+.section szeqb
+.section szera
+.section szerb
+.section szesa
+.section szesb
+.section szeta
+.section szetb
+.section szeua
+.section szeub
+.section szeva
+.section szevb
+.section szewa
+.section szewb
+.section szexa
+.section szexb
+.section szeya
+.section szeyb
+.section szeza
+.section szezb
+.section sze1a
+.section sze1b
+.section sze2a
+.section sze2b
+.section sze3a
+.section sze3b
+.section sze4a
+.section sze4b
+.section sze5a
+.section sze5b
+.section sze6a
+.section sze6b
+.section sze7a
+.section sze7b
+.section sze8a
+.section sze8b
+.section sze9a
+.section sze9b
+.section sze0a
+.section sze0b
+.section szfaa
+.section szfab
+.section szfba
+.section szfbb
+.section szfca
+.section szfcb
+.section szfda
+.section szfdb
+.section szfea
+.section szfeb
+.section szffa
+.section szffb
+.section szfga
+.section szfgb
+.section szfha
+.section szfhb
+.section szfia
+.section szfib
+.section szfja
+.section szfjb
+.section szfka
+.section szfkb
+.section szfla
+.section szflb
+.section szfma
+.section szfmb
+.section szfna
+.section szfnb
+.section szfoa
+.section szfob
+.section szfpa
+.section szfpb
+.section szfqa
+.section szfqb
+.section szfra
+.section szfrb
+.section szfsa
+.section szfsb
+.section szfta
+.section szftb
+.section szfua
+.section szfub
+.section szfva
+.section szfvb
+.section szfwa
+.section szfwb
+.section szfxa
+.section szfxb
+.section szfya
+.section szfyb
+.section szfza
+.section szfzb
+.section szf1a
+.section szf1b
+.section szf2a
+.section szf2b
+.section szf3a
+.section szf3b
+.section szf4a
+.section szf4b
+.section szf5a
+.section szf5b
+.section szf6a
+.section szf6b
+.section szf7a
+.section szf7b
+.section szf8a
+.section szf8b
+.section szf9a
+.section szf9b
+.section szf0a
+.section szf0b
+.section szgaa
+.section szgab
+.section szgba
+.section szgbb
+.section szgca
+.section szgcb
+.section szgda
+.section szgdb
+.section szgea
+.section szgeb
+.section szgfa
+.section szgfb
+.section szgga
+.section szggb
+.section szgha
+.section szghb
+.section szgia
+.section szgib
+.section szgja
+.section szgjb
+.section szgka
+.section szgkb
+.section szgla
+.section szglb
+.section szgma
+.section szgmb
+.section szgna
+.section szgnb
+.section szgoa
+.section szgob
+.section szgpa
+.section szgpb
+.section szgqa
+.section szgqb
+.section szgra
+.section szgrb
+.section szgsa
+.section szgsb
+.section szgta
+.section szgtb
+.section szgua
+.section szgub
+.section szgva
+.section szgvb
+.section szgwa
+.section szgwb
+.section szgxa
+.section szgxb
+.section szgya
+.section szgyb
+.section szgza
+.section szgzb
+.section szg1a
+.section szg1b
+.section szg2a
+.section szg2b
+.section szg3a
+.section szg3b
+.section szg4a
+.section szg4b
+.section szg5a
+.section szg5b
+.section szg6a
+.section szg6b
+.section szg7a
+.section szg7b
+.section szg8a
+.section szg8b
+.section szg9a
+.section szg9b
+.section szg0a
+.section szg0b
+.section szhaa
+.section szhab
+.section szhba
+.section szhbb
+.section szhca
+.section szhcb
+.section szhda
+.section szhdb
+.section szhea
+.section szheb
+.section szhfa
+.section szhfb
+.section szhga
+.section szhgb
+.section szhha
+.section szhhb
+.section szhia
+.section szhib
+.section szhja
+.section szhjb
+.section szhka
+.section szhkb
+.section szhla
+.section szhlb
+.section szhma
+.section szhmb
+.section szhna
+.section szhnb
+.section szhoa
+.section szhob
+.section szhpa
+.section szhpb
+.section szhqa
+.section szhqb
+.section szhra
+.section szhrb
+.section szhsa
+.section szhsb
+.section szhta
+.section szhtb
+.section szhua
+.section szhub
+.section szhva
+.section szhvb
+.section szhwa
+.section szhwb
+.section szhxa
+.section szhxb
+.section szhya
+.section szhyb
+.section szhza
+.section szhzb
+.section szh1a
+.section szh1b
+.section szh2a
+.section szh2b
+.section szh3a
+.section szh3b
+.section szh4a
+.section szh4b
+.section szh5a
+.section szh5b
+.section szh6a
+.section szh6b
+.section szh7a
+.section szh7b
+.section szh8a
+.section szh8b
+.section szh9a
+.section szh9b
+.section szh0a
+.section szh0b
+.section sziaa
+.section sziab
+.section sziba
+.section szibb
+.section szica
+.section szicb
+.section szida
+.section szidb
+.section sziea
+.section szieb
+.section szifa
+.section szifb
+.section sziga
+.section szigb
+.section sziha
+.section szihb
+.section sziia
+.section sziib
+.section szija
+.section szijb
+.section szika
+.section szikb
+.section szila
+.section szilb
+.section szima
+.section szimb
+.section szina
+.section szinb
+.section szioa
+.section sziob
+.section szipa
+.section szipb
+.section sziqa
+.section sziqb
+.section szira
+.section szirb
+.section szisa
+.section szisb
+.section szita
+.section szitb
+.section sziua
+.section sziub
+.section sziva
+.section szivb
+.section sziwa
+.section sziwb
+.section szixa
+.section szixb
+.section sziya
+.section sziyb
+.section sziza
+.section szizb
+.section szi1a
+.section szi1b
+.section szi2a
+.section szi2b
+.section szi3a
+.section szi3b
+.section szi4a
+.section szi4b
+.section szi5a
+.section szi5b
+.section szi6a
+.section szi6b
+.section szi7a
+.section szi7b
+.section szi8a
+.section szi8b
+.section szi9a
+.section szi9b
+.section szi0a
+.section szi0b
+.section szjaa
+.section szjab
+.section szjba
+.section szjbb
+.section szjca
+.section szjcb
+.section szjda
+.section szjdb
+.section szjea
+.section szjeb
+.section szjfa
+.section szjfb
+.section szjga
+.section szjgb
+.section szjha
+.section szjhb
+.section szjia
+.section szjib
+.section szjja
+.section szjjb
+.section szjka
+.section szjkb
+.section szjla
+.section szjlb
+.section szjma
+.section szjmb
+.section szjna
+.section szjnb
+.section szjoa
+.section szjob
+.section szjpa
+.section szjpb
+.section szjqa
+.section szjqb
+.section szjra
+.section szjrb
+.section szjsa
+.section szjsb
+.section szjta
+.section szjtb
+.section szjua
+.section szjub
+.section szjva
+.section szjvb
+.section szjwa
+.section szjwb
+.section szjxa
+.section szjxb
+.section szjya
+.section szjyb
+.section szjza
+.section szjzb
+.section szj1a
+.section szj1b
+.section szj2a
+.section szj2b
+.section szj3a
+.section szj3b
+.section szj4a
+.section szj4b
+.section szj5a
+.section szj5b
+.section szj6a
+.section szj6b
+.section szj7a
+.section szj7b
+.section szj8a
+.section szj8b
+.section szj9a
+.section szj9b
+.section szj0a
+.section szj0b
+.section szkaa
+.section szkab
+.section szkba
+.section szkbb
+.section szkca
+.section szkcb
+.section szkda
+.section szkdb
+.section szkea
+.section szkeb
+.section szkfa
+.section szkfb
+.section szkga
+.section szkgb
+.section szkha
+.section szkhb
+.section szkia
+.section szkib
+.section szkja
+.section szkjb
+.section szkka
+.section szkkb
+.section szkla
+.section szklb
+.section szkma
+.section szkmb
+.section szkna
+.section szknb
+.section szkoa
+.section szkob
+.section szkpa
+.section szkpb
+.section szkqa
+.section szkqb
+.section szkra
+.section szkrb
+.section szksa
+.section szksb
+.section szkta
+.section szktb
+.section szkua
+.section szkub
+.section szkva
+.section szkvb
+.section szkwa
+.section szkwb
+.section szkxa
+.section szkxb
+.section szkya
+.section szkyb
+.section szkza
+.section szkzb
+.section szk1a
+.section szk1b
+.section szk2a
+.section szk2b
+.section szk3a
+.section szk3b
+.section szk4a
+.section szk4b
+.section szk5a
+.section szk5b
+.section szk6a
+.section szk6b
+.section szk7a
+.section szk7b
+.section szk8a
+.section szk8b
+.section szk9a
+.section szk9b
+.section szk0a
+.section szk0b
+.section szlaa
+.section szlab
+.section szlba
+.section szlbb
+.section szlca
+.section szlcb
+.section szlda
+.section szldb
+.section szlea
+.section szleb
+.section szlfa
+.section szlfb
+.section szlga
+.section szlgb
+.section szlha
+.section szlhb
+.section szlia
+.section szlib
+.section szlja
+.section szljb
+.section szlka
+.section szlkb
+.section szlla
+.section szllb
+.section szlma
+.section szlmb
+.section szlna
+.section szlnb
+.section szloa
+.section szlob
+.section szlpa
+.section szlpb
+.section szlqa
+.section szlqb
+.section szlra
+.section szlrb
+.section szlsa
+.section szlsb
+.section szlta
+.section szltb
+.section szlua
+.section szlub
+.section szlva
+.section szlvb
+.section szlwa
+.section szlwb
+.section szlxa
+.section szlxb
+.section szlya
+.section szlyb
+.section szlza
+.section szlzb
+.section szl1a
+.section szl1b
+.section szl2a
+.section szl2b
+.section szl3a
+.section szl3b
+.section szl4a
+.section szl4b
+.section szl5a
+.section szl5b
+.section szl6a
+.section szl6b
+.section szl7a
+.section szl7b
+.section szl8a
+.section szl8b
+.section szl9a
+.section szl9b
+.section szl0a
+.section szl0b
+.section szmaa
+.section szmab
+.section szmba
+.section szmbb
+.section szmca
+.section szmcb
+.section szmda
+.section szmdb
+.section szmea
+.section szmeb
+.section szmfa
+.section szmfb
+.section szmga
+.section szmgb
+.section szmha
+.section szmhb
+.section szmia
+.section szmib
+.section szmja
+.section szmjb
+.section szmka
+.section szmkb
+.section szmla
+.section szmlb
+.section szmma
+.section szmmb
+.section szmna
+.section szmnb
+.section szmoa
+.section szmob
+.section szmpa
+.section szmpb
+.section szmqa
+.section szmqb
+.section szmra
+.section szmrb
+.section szmsa
+.section szmsb
+.section szmta
+.section szmtb
+.section szmua
+.section szmub
+.section szmva
+.section szmvb
+.section szmwa
+.section szmwb
+.section szmxa
+.section szmxb
+.section szmya
+.section szmyb
+.section szmza
+.section szmzb
+.section szm1a
+.section szm1b
+.section szm2a
+.section szm2b
+.section szm3a
+.section szm3b
+.section szm4a
+.section szm4b
+.section szm5a
+.section szm5b
+.section szm6a
+.section szm6b
+.section szm7a
+.section szm7b
+.section szm8a
+.section szm8b
+.section szm9a
+.section szm9b
+.section szm0a
+.section szm0b
+.section sznaa
+.section sznab
+.section sznba
+.section sznbb
+.section sznca
+.section szncb
+.section sznda
+.section szndb
+.section sznea
+.section szneb
+.section sznfa
+.section sznfb
+.section sznga
+.section szngb
+.section sznha
+.section sznhb
+.section sznia
+.section sznib
+.section sznja
+.section sznjb
+.section sznka
+.section sznkb
+.section sznla
+.section sznlb
+.section sznma
+.section sznmb
+.section sznna
+.section sznnb
+.section sznoa
+.section sznob
+.section sznpa
+.section sznpb
+.section sznqa
+.section sznqb
+.section sznra
+.section sznrb
+.section sznsa
+.section sznsb
+.section sznta
+.section szntb
+.section sznua
+.section sznub
+.section sznva
+.section sznvb
+.section sznwa
+.section sznwb
+.section sznxa
+.section sznxb
+.section sznya
+.section sznyb
+.section sznza
+.section sznzb
+.section szn1a
+.section szn1b
+.section szn2a
+.section szn2b
+.section szn3a
+.section szn3b
+.section szn4a
+.section szn4b
+.section szn5a
+.section szn5b
+.section szn6a
+.section szn6b
+.section szn7a
+.section szn7b
+.section szn8a
+.section szn8b
+.section szn9a
+.section szn9b
+.section szn0a
+.section szn0b
+.section szoaa
+.section szoab
+.section szoba
+.section szobb
+.section szoca
+.section szocb
+.section szoda
+.section szodb
+.section szoea
+.section szoeb
+.section szofa
+.section szofb
+.section szoga
+.section szogb
+.section szoha
+.section szohb
+.section szoia
+.section szoib
+.section szoja
+.section szojb
+.section szoka
+.section szokb
+.section szola
+.section szolb
+.section szoma
+.section szomb
+.section szona
+.section szonb
+.section szooa
+.section szoob
+.section szopa
+.section szopb
+.section szoqa
+.section szoqb
+.section szora
+.section szorb
+.section szosa
+.section szosb
+.section szota
+.section szotb
+.section szoua
+.section szoub
+.section szova
+.section szovb
+.section szowa
+.section szowb
+.section szoxa
+.section szoxb
+.section szoya
+.section szoyb
+.section szoza
+.section szozb
+.section szo1a
+.section szo1b
+.section szo2a
+.section szo2b
+.section szo3a
+.section szo3b
+.section szo4a
+.section szo4b
+.section szo5a
+.section szo5b
+.section szo6a
+.section szo6b
+.section szo7a
+.section szo7b
+.section szo8a
+.section szo8b
+.section szo9a
+.section szo9b
+.section szo0a
+.section szo0b
+.section szpaa
+.section szpab
+.section szpba
+.section szpbb
+.section szpca
+.section szpcb
+.section szpda
+.section szpdb
+.section szpea
+.section szpeb
+.section szpfa
+.section szpfb
+.section szpga
+.section szpgb
+.section szpha
+.section szphb
+.section szpia
+.section szpib
+.section szpja
+.section szpjb
+.section szpka
+.section szpkb
+.section szpla
+.section szplb
+.section szpma
+.section szpmb
+.section szpna
+.section szpnb
+.section szpoa
+.section szpob
+.section szppa
+.section szppb
+.section szpqa
+.section szpqb
+.section szpra
+.section szprb
+.section szpsa
+.section szpsb
+.section szpta
+.section szptb
+.section szpua
+.section szpub
+.section szpva
+.section szpvb
+.section szpwa
+.section szpwb
+.section szpxa
+.section szpxb
+.section szpya
+.section szpyb
+.section szpza
+.section szpzb
+.section szp1a
+.section szp1b
+.section szp2a
+.section szp2b
+.section szp3a
+.section szp3b
+.section szp4a
+.section szp4b
+.section szp5a
+.section szp5b
+.section szp6a
+.section szp6b
+.section szp7a
+.section szp7b
+.section szp8a
+.section szp8b
+.section szp9a
+.section szp9b
+.section szp0a
+.section szp0b
+.section szqaa
+.section szqab
+.section szqba
+.section szqbb
+.section szqca
+.section szqcb
+.section szqda
+.section szqdb
+.section szqea
+.section szqeb
+.section szqfa
+.section szqfb
+.section szqga
+.section szqgb
+.section szqha
+.section szqhb
+.section szqia
+.section szqib
+.section szqja
+.section szqjb
+.section szqka
+.section szqkb
+.section szqla
+.section szqlb
+.section szqma
+.section szqmb
+.section szqna
+.section szqnb
+.section szqoa
+.section szqob
+.section szqpa
+.section szqpb
+.section szqqa
+.section szqqb
+.section szqra
+.section szqrb
+.section szqsa
+.section szqsb
+.section szqta
+.section szqtb
+.section szqua
+.section szqub
+.section szqva
+.section szqvb
+.section szqwa
+.section szqwb
+.section szqxa
+.section szqxb
+.section szqya
+.section szqyb
+.section szqza
+.section szqzb
+.section szq1a
+.section szq1b
+.section szq2a
+.section szq2b
+.section szq3a
+.section szq3b
+.section szq4a
+.section szq4b
+.section szq5a
+.section szq5b
+.section szq6a
+.section szq6b
+.section szq7a
+.section szq7b
+.section szq8a
+.section szq8b
+.section szq9a
+.section szq9b
+.section szq0a
+.section szq0b
+.section szraa
+.section szrab
+.section szrba
+.section szrbb
+.section szrca
+.section szrcb
+.section szrda
+.section szrdb
+.section szrea
+.section szreb
+.section szrfa
+.section szrfb
+.section szrga
+.section szrgb
+.section szrha
+.section szrhb
+.section szria
+.section szrib
+.section szrja
+.section szrjb
+.section szrka
+.section szrkb
+.section szrla
+.section szrlb
+.section szrma
+.section szrmb
+.section szrna
+.section szrnb
+.section szroa
+.section szrob
+.section szrpa
+.section szrpb
+.section szrqa
+.section szrqb
+.section szrra
+.section szrrb
+.section szrsa
+.section szrsb
+.section szrta
+.section szrtb
+.section szrua
+.section szrub
+.section szrva
+.section szrvb
+.section szrwa
+.section szrwb
+.section szrxa
+.section szrxb
+.section szrya
+.section szryb
+.section szrza
+.section szrzb
+.section szr1a
+.section szr1b
+.section szr2a
+.section szr2b
+.section szr3a
+.section szr3b
+.section szr4a
+.section szr4b
+.section szr5a
+.section szr5b
+.section szr6a
+.section szr6b
+.section szr7a
+.section szr7b
+.section szr8a
+.section szr8b
+.section szr9a
+.section szr9b
+.section szr0a
+.section szr0b
+.section szsaa
+.section szsab
+.section szsba
+.section szsbb
+.section szsca
+.section szscb
+.section szsda
+.section szsdb
+.section szsea
+.section szseb
+.section szsfa
+.section szsfb
+.section szsga
+.section szsgb
+.section szsha
+.section szshb
+.section szsia
+.section szsib
+.section szsja
+.section szsjb
+.section szska
+.section szskb
+.section szsla
+.section szslb
+.section szsma
+.section szsmb
+.section szsna
+.section szsnb
+.section szsoa
+.section szsob
+.section szspa
+.section szspb
+.section szsqa
+.section szsqb
+.section szsra
+.section szsrb
+.section szssa
+.section szssb
+.section szsta
+.section szstb
+.section szsua
+.section szsub
+.section szsva
+.section szsvb
+.section szswa
+.section szswb
+.section szsxa
+.section szsxb
+.section szsya
+.section szsyb
+.section szsza
+.section szszb
+.section szs1a
+.section szs1b
+.section szs2a
+.section szs2b
+.section szs3a
+.section szs3b
+.section szs4a
+.section szs4b
+.section szs5a
+.section szs5b
+.section szs6a
+.section szs6b
+.section szs7a
+.section szs7b
+.section szs8a
+.section szs8b
+.section szs9a
+.section szs9b
+.section szs0a
+.section szs0b
+.section sztaa
+.section sztab
+.section sztba
+.section sztbb
+.section sztca
+.section sztcb
+.section sztda
+.section sztdb
+.section sztea
+.section szteb
+.section sztfa
+.section sztfb
+.section sztga
+.section sztgb
+.section sztha
+.section szthb
+.section sztia
+.section sztib
+.section sztja
+.section sztjb
+.section sztka
+.section sztkb
+.section sztla
+.section sztlb
+.section sztma
+.section sztmb
+.section sztna
+.section sztnb
+.section sztoa
+.section sztob
+.section sztpa
+.section sztpb
+.section sztqa
+.section sztqb
+.section sztra
+.section sztrb
+.section sztsa
+.section sztsb
+.section sztta
+.section szttb
+.section sztua
+.section sztub
+.section sztva
+.section sztvb
+.section sztwa
+.section sztwb
+.section sztxa
+.section sztxb
+.section sztya
+.section sztyb
+.section sztza
+.section sztzb
+.section szt1a
+.section szt1b
+.section szt2a
+.section szt2b
+.section szt3a
+.section szt3b
+.section szt4a
+.section szt4b
+.section szt5a
+.section szt5b
+.section szt6a
+.section szt6b
+.section szt7a
+.section szt7b
+.section szt8a
+.section szt8b
+.section szt9a
+.section szt9b
+.section szt0a
+.section szt0b
+.section szuaa
+.section szuab
+.section szuba
+.section szubb
+.section szuca
+.section szucb
+.section szuda
+.section szudb
+.section szuea
+.section szueb
+.section szufa
+.section szufb
+.section szuga
+.section szugb
+.section szuha
+.section szuhb
+.section szuia
+.section szuib
+.section szuja
+.section szujb
+.section szuka
+.section szukb
+.section szula
+.section szulb
+.section szuma
+.section szumb
+.section szuna
+.section szunb
+.section szuoa
+.section szuob
+.section szupa
+.section szupb
+.section szuqa
+.section szuqb
+.section szura
+.section szurb
+.section szusa
+.section szusb
+.section szuta
+.section szutb
+.section szuua
+.section szuub
+.section szuva
+.section szuvb
+.section szuwa
+.section szuwb
+.section szuxa
+.section szuxb
+.section szuya
+.section szuyb
+.section szuza
+.section szuzb
+.section szu1a
+.section szu1b
+.section szu2a
+.section szu2b
+.section szu3a
+.section szu3b
+.section szu4a
+.section szu4b
+.section szu5a
+.section szu5b
+.section szu6a
+.section szu6b
+.section szu7a
+.section szu7b
+.section szu8a
+.section szu8b
+.section szu9a
+.section szu9b
+.section szu0a
+.section szu0b
+.section szvaa
+.section szvab
+.section szvba
+.section szvbb
+.section szvca
+.section szvcb
+.section szvda
+.section szvdb
+.section szvea
+.section szveb
+.section szvfa
+.section szvfb
+.section szvga
+.section szvgb
+.section szvha
+.section szvhb
+.section szvia
+.section szvib
+.section szvja
+.section szvjb
+.section szvka
+.section szvkb
+.section szvla
+.section szvlb
+.section szvma
+.section szvmb
+.section szvna
+.section szvnb
+.section szvoa
+.section szvob
+.section szvpa
+.section szvpb
+.section szvqa
+.section szvqb
+.section szvra
+.section szvrb
+.section szvsa
+.section szvsb
+.section szvta
+.section szvtb
+.section szvua
+.section szvub
+.section szvva
+.section szvvb
+.section szvwa
+.section szvwb
+.section szvxa
+.section szvxb
+.section szvya
+.section szvyb
+.section szvza
+.section szvzb
+.section szv1a
+.section szv1b
+.section szv2a
+.section szv2b
+.section szv3a
+.section szv3b
+.section szv4a
+.section szv4b
+.section szv5a
+.section szv5b
+.section szv6a
+.section szv6b
+.section szv7a
+.section szv7b
+.section szv8a
+.section szv8b
+.section szv9a
+.section szv9b
+.section szv0a
+.section szv0b
+.section szwaa
+.section szwab
+.section szwba
+.section szwbb
+.section szwca
+.section szwcb
+.section szwda
+.section szwdb
+.section szwea
+.section szweb
+.section szwfa
+.section szwfb
+.section szwga
+.section szwgb
+.section szwha
+.section szwhb
+.section szwia
+.section szwib
+.section szwja
+.section szwjb
+.section szwka
+.section szwkb
+.section szwla
+.section szwlb
+.section szwma
+.section szwmb
+.section szwna
+.section szwnb
+.section szwoa
+.section szwob
+.section szwpa
+.section szwpb
+.section szwqa
+.section szwqb
+.section szwra
+.section szwrb
+.section szwsa
+.section szwsb
+.section szwta
+.section szwtb
+.section szwua
+.section szwub
+.section szwva
+.section szwvb
+.section szwwa
+.section szwwb
+.section szwxa
+.section szwxb
+.section szwya
+.section szwyb
+.section szwza
+.section szwzb
+.section szw1a
+.section szw1b
+.section szw2a
+.section szw2b
+.section szw3a
+.section szw3b
+.section szw4a
+.section szw4b
+.section szw5a
+.section szw5b
+.section szw6a
+.section szw6b
+.section szw7a
+.section szw7b
+.section szw8a
+.section szw8b
+.section szw9a
+.section szw9b
+.section szw0a
+.section szw0b
+.section szxaa
+.section szxab
+.section szxba
+.section szxbb
+.section szxca
+.section szxcb
+.section szxda
+.section szxdb
+.section szxea
+.section szxeb
+.section szxfa
+.section szxfb
+.section szxga
+.section szxgb
+.section szxha
+.section szxhb
+.section szxia
+.section szxib
+.section szxja
+.section szxjb
+.section szxka
+.section szxkb
+.section szxla
+.section szxlb
+.section szxma
+.section szxmb
+.section szxna
+.section szxnb
+.section szxoa
+.section szxob
+.section szxpa
+.section szxpb
+.section szxqa
+.section szxqb
+.section szxra
+.section szxrb
+.section szxsa
+.section szxsb
+.section szxta
+.section szxtb
+.section szxua
+.section szxub
+.section szxva
+.section szxvb
+.section szxwa
+.section szxwb
+.section szxxa
+.section szxxb
+.section szxya
+.section szxyb
+.section szxza
+.section szxzb
+.section szx1a
+.section szx1b
+.section szx2a
+.section szx2b
+.section szx3a
+.section szx3b
+.section szx4a
+.section szx4b
+.section szx5a
+.section szx5b
+.section szx6a
+.section szx6b
+.section szx7a
+.section szx7b
+.section szx8a
+.section szx8b
+.section szx9a
+.section szx9b
+.section szx0a
+.section szx0b
+.section szyaa
+.section szyab
+.section szyba
+.section szybb
+.section szyca
+.section szycb
+.section szyda
+.section szydb
+.section szyea
+.section szyeb
+.section szyfa
+.section szyfb
+.section szyga
+.section szygb
+.section szyha
+.section szyhb
+.section szyia
+.section szyib
+.section szyja
+.section szyjb
+.section szyka
+.section szykb
+.section szyla
+.section szylb
+.section szyma
+.section szymb
+.section szyna
+.section szynb
+.section szyoa
+.section szyob
+.section szypa
+.section szypb
+.section szyqa
+.section szyqb
+.section szyra
+.section szyrb
+.section szysa
+.section szysb
+.section szyta
+.section szytb
+.section szyua
+.section szyub
+.section szyva
+.section szyvb
+.section szywa
+.section szywb
+.section szyxa
+.section szyxb
+.section szyya
+.section szyyb
+.section szyza
+.section szyzb
+.section szy1a
+.section szy1b
+.section szy2a
+.section szy2b
+.section szy3a
+.section szy3b
+.section szy4a
+.section szy4b
+.section szy5a
+.section szy5b
+.section szy6a
+.section szy6b
+.section szy7a
+.section szy7b
+.section szy8a
+.section szy8b
+.section szy9a
+.section szy9b
+.section szy0a
+.section szy0b
+.section szzaa
+.section szzab
+.section szzba
+.section szzbb
+.section szzca
+.section szzcb
+.section szzda
+.section szzdb
+.section szzea
+.section szzeb
+.section szzfa
+.section szzfb
+.section szzga
+.section szzgb
+.section szzha
+.section szzhb
+.section szzia
+.section szzib
+.section szzja
+.section szzjb
+.section szzka
+.section szzkb
+.section szzla
+.section szzlb
+.section szzma
+.section szzmb
+.section szzna
+.section szznb
+.section szzoa
+.section szzob
+.section szzpa
+.section szzpb
+.section szzqa
+.section szzqb
+.section szzra
+.section szzrb
+.section szzsa
+.section szzsb
+.section szzta
+.section szztb
+.section szzua
+.section szzub
+.section szzva
+.section szzvb
+.section szzwa
+.section szzwb
+.section szzxa
+.section szzxb
+.section szzya
+.section szzyb
+.section szzza
+.section szzzb
+.section szz1a
+.section szz1b
+.section szz2a
+.section szz2b
+.section szz3a
+.section szz3b
+.section szz4a
+.section szz4b
+.section szz5a
+.section szz5b
+.section szz6a
+.section szz6b
+.section szz7a
+.section szz7b
+.section szz8a
+.section szz8b
+.section szz9a
+.section szz9b
+.section szz0a
+.section szz0b
+.section sz1aa
+.section sz1ab
+.section sz1ba
+.section sz1bb
+.section sz1ca
+.section sz1cb
+.section sz1da
+.section sz1db
+.section sz1ea
+.section sz1eb
+.section sz1fa
+.section sz1fb
+.section sz1ga
+.section sz1gb
+.section sz1ha
+.section sz1hb
+.section sz1ia
+.section sz1ib
+.section sz1ja
+.section sz1jb
+.section sz1ka
+.section sz1kb
+.section sz1la
+.section sz1lb
+.section sz1ma
+.section sz1mb
+.section sz1na
+.section sz1nb
+.section sz1oa
+.section sz1ob
+.section sz1pa
+.section sz1pb
+.section sz1qa
+.section sz1qb
+.section sz1ra
+.section sz1rb
+.section sz1sa
+.section sz1sb
+.section sz1ta
+.section sz1tb
+.section sz1ua
+.section sz1ub
+.section sz1va
+.section sz1vb
+.section sz1wa
+.section sz1wb
+.section sz1xa
+.section sz1xb
+.section sz1ya
+.section sz1yb
+.section sz1za
+.section sz1zb
+.section sz11a
+.section sz11b
+.section sz12a
+.section sz12b
+.section sz13a
+.section sz13b
+.section sz14a
+.section sz14b
+.section sz15a
+.section sz15b
+.section sz16a
+.section sz16b
+.section sz17a
+.section sz17b
+.section sz18a
+.section sz18b
+.section sz19a
+.section sz19b
+.section sz10a
+.section sz10b
+.section sz2aa
+.section sz2ab
+.section sz2ba
+.section sz2bb
+.section sz2ca
+.section sz2cb
+.section sz2da
+.section sz2db
+.section sz2ea
+.section sz2eb
+.section sz2fa
+.section sz2fb
+.section sz2ga
+.section sz2gb
+.section sz2ha
+.section sz2hb
+.section sz2ia
+.section sz2ib
+.section sz2ja
+.section sz2jb
+.section sz2ka
+.section sz2kb
+.section sz2la
+.section sz2lb
+.section sz2ma
+.section sz2mb
+.section sz2na
+.section sz2nb
+.section sz2oa
+.section sz2ob
+.section sz2pa
+.section sz2pb
+.section sz2qa
+.section sz2qb
+.section sz2ra
+.section sz2rb
+.section sz2sa
+.section sz2sb
+.section sz2ta
+.section sz2tb
+.section sz2ua
+.section sz2ub
+.section sz2va
+.section sz2vb
+.section sz2wa
+.section sz2wb
+.section sz2xa
+.section sz2xb
+.section sz2ya
+.section sz2yb
+.section sz2za
+.section sz2zb
+.section sz21a
+.section sz21b
+.section sz22a
+.section sz22b
+.section sz23a
+.section sz23b
+.section sz24a
+.section sz24b
+.section sz25a
+.section sz25b
+.section sz26a
+.section sz26b
+.section sz27a
+.section sz27b
+.section sz28a
+.section sz28b
+.section sz29a
+.section sz29b
+.section sz20a
+.section sz20b
+.section sz3aa
+.section sz3ab
+.section sz3ba
+.section sz3bb
+.section sz3ca
+.section sz3cb
+.section sz3da
+.section sz3db
+.section sz3ea
+.section sz3eb
+.section sz3fa
+.section sz3fb
+.section sz3ga
+.section sz3gb
+.section sz3ha
+.section sz3hb
+.section sz3ia
+.section sz3ib
+.section sz3ja
+.section sz3jb
+.section sz3ka
+.section sz3kb
+.section sz3la
+.section sz3lb
+.section sz3ma
+.section sz3mb
+.section sz3na
+.section sz3nb
+.section sz3oa
+.section sz3ob
+.section sz3pa
+.section sz3pb
+.section sz3qa
+.section sz3qb
+.section sz3ra
+.section sz3rb
+.section sz3sa
+.section sz3sb
+.section sz3ta
+.section sz3tb
+.section sz3ua
+.section sz3ub
+.section sz3va
+.section sz3vb
+.section sz3wa
+.section sz3wb
+.section sz3xa
+.section sz3xb
+.section sz3ya
+.section sz3yb
+.section sz3za
+.section sz3zb
+.section sz31a
+.section sz31b
+.section sz32a
+.section sz32b
+.section sz33a
+.section sz33b
+.section sz34a
+.section sz34b
+.section sz35a
+.section sz35b
+.section sz36a
+.section sz36b
+.section sz37a
+.section sz37b
+.section sz38a
+.section sz38b
+.section sz39a
+.section sz39b
+.section sz30a
+.section sz30b
+.section sz4aa
+.section sz4ab
+.section sz4ba
+.section sz4bb
+.section sz4ca
+.section sz4cb
+.section sz4da
+.section sz4db
+.section sz4ea
+.section sz4eb
+.section sz4fa
+.section sz4fb
+.section sz4ga
+.section sz4gb
+.section sz4ha
+.section sz4hb
+.section sz4ia
+.section sz4ib
+.section sz4ja
+.section sz4jb
+.section sz4ka
+.section sz4kb
+.section sz4la
+.section sz4lb
+.section sz4ma
+.section sz4mb
+.section sz4na
+.section sz4nb
+.section sz4oa
+.section sz4ob
+.section sz4pa
+.section sz4pb
+.section sz4qa
+.section sz4qb
+.section sz4ra
+.section sz4rb
+.section sz4sa
+.section sz4sb
+.section sz4ta
+.section sz4tb
+.section sz4ua
+.section sz4ub
+.section sz4va
+.section sz4vb
+.section sz4wa
+.section sz4wb
+.section sz4xa
+.section sz4xb
+.section sz4ya
+.section sz4yb
+.section sz4za
+.section sz4zb
+.section sz41a
+.section sz41b
+.section sz42a
+.section sz42b
+.section sz43a
+.section sz43b
+.section sz44a
+.section sz44b
+.section sz45a
+.section sz45b
+.section sz46a
+.section sz46b
+.section sz47a
+.section sz47b
+.section sz48a
+.section sz48b
+.section sz49a
+.section sz49b
+.section sz40a
+.section sz40b
+.section sz5aa
+.section sz5ab
+.section sz5ba
+.section sz5bb
+.section sz5ca
+.section sz5cb
+.section sz5da
+.section sz5db
+.section sz5ea
+.section sz5eb
+.section sz5fa
+.section sz5fb
+.section sz5ga
+.section sz5gb
+.section sz5ha
+.section sz5hb
+.section sz5ia
+.section sz5ib
+.section sz5ja
+.section sz5jb
+.section sz5ka
+.section sz5kb
+.section sz5la
+.section sz5lb
+.section sz5ma
+.section sz5mb
+.section sz5na
+.section sz5nb
+.section sz5oa
+.section sz5ob
+.section sz5pa
+.section sz5pb
+.section sz5qa
+.section sz5qb
+.section sz5ra
+.section sz5rb
+.section sz5sa
+.section sz5sb
+.section sz5ta
+.section sz5tb
+.section sz5ua
+.section sz5ub
+.section sz5va
+.section sz5vb
+.section sz5wa
+.section sz5wb
+.section sz5xa
+.section sz5xb
+.section sz5ya
+.section sz5yb
+.section sz5za
+.section sz5zb
+.section sz51a
+.section sz51b
+.section sz52a
+.section sz52b
+.section sz53a
+.section sz53b
+.section sz54a
+.section sz54b
+.section sz55a
+.section sz55b
+.section sz56a
+.section sz56b
+.section sz57a
+.section sz57b
+.section sz58a
+.section sz58b
+.section sz59a
+.section sz59b
+.section sz50a
+.section sz50b
+.section sz6aa
+.section sz6ab
+.section sz6ba
+.section sz6bb
+.section sz6ca
+.section sz6cb
+.section sz6da
+.section sz6db
+.section sz6ea
+.section sz6eb
+.section sz6fa
+.section sz6fb
+.section sz6ga
+.section sz6gb
+.section sz6ha
+.section sz6hb
+.section sz6ia
+.section sz6ib
+.section sz6ja
+.section sz6jb
+.section sz6ka
+.section sz6kb
+.section sz6la
+.section sz6lb
+.section sz6ma
+.section sz6mb
+.section sz6na
+.section sz6nb
+.section sz6oa
+.section sz6ob
+.section sz6pa
+.section sz6pb
+.section sz6qa
+.section sz6qb
+.section sz6ra
+.section sz6rb
+.section sz6sa
+.section sz6sb
+.section sz6ta
+.section sz6tb
+.section sz6ua
+.section sz6ub
+.section sz6va
+.section sz6vb
+.section sz6wa
+.section sz6wb
+.section sz6xa
+.section sz6xb
+.section sz6ya
+.section sz6yb
+.section sz6za
+.section sz6zb
+.section sz61a
+.section sz61b
+.section sz62a
+.section sz62b
+.section sz63a
+.section sz63b
+.section sz64a
+.section sz64b
+.section sz65a
+.section sz65b
+.section sz66a
+.section sz66b
+.section sz67a
+.section sz67b
+.section sz68a
+.section sz68b
+.section sz69a
+.section sz69b
+.section sz60a
+.section sz60b
+.section sz7aa
+.section sz7ab
+.section sz7ba
+.section sz7bb
+.section sz7ca
+.section sz7cb
+.section sz7da
+.section sz7db
+.section sz7ea
+.section sz7eb
+.section sz7fa
+.section sz7fb
+.section sz7ga
+.section sz7gb
+.section sz7ha
+.section sz7hb
+.section sz7ia
+.section sz7ib
+.section sz7ja
+.section sz7jb
+.section sz7ka
+.section sz7kb
+.section sz7la
+.section sz7lb
+.section sz7ma
+.section sz7mb
+.section sz7na
+.section sz7nb
+.section sz7oa
+.section sz7ob
+.section sz7pa
+.section sz7pb
+.section sz7qa
+.section sz7qb
+.section sz7ra
+.section sz7rb
+.section sz7sa
+.section sz7sb
+.section sz7ta
+.section sz7tb
+.section sz7ua
+.section sz7ub
+.section sz7va
+.section sz7vb
+.section sz7wa
+.section sz7wb
+.section sz7xa
+.section sz7xb
+.section sz7ya
+.section sz7yb
+.section sz7za
+.section sz7zb
+.section sz71a
+.section sz71b
+.section sz72a
+.section sz72b
+.section sz73a
+.section sz73b
+.section sz74a
+.section sz74b
+.section sz75a
+.section sz75b
+.section sz76a
+.section sz76b
+.section sz77a
+.section sz77b
+.section sz78a
+.section sz78b
+.section sz79a
+.section sz79b
+.section sz70a
+.section sz70b
+.section sz8aa
+.section sz8ab
+.section sz8ba
+.section sz8bb
+.section sz8ca
+.section sz8cb
+.section sz8da
+.section sz8db
+.section sz8ea
+.section sz8eb
+.section sz8fa
+.section sz8fb
+.section sz8ga
+.section sz8gb
+.section sz8ha
+.section sz8hb
+.section sz8ia
+.section sz8ib
+.section sz8ja
+.section sz8jb
+.section sz8ka
+.section sz8kb
+.section sz8la
+.section sz8lb
+.section sz8ma
+.section sz8mb
+.section sz8na
+.section sz8nb
+.section sz8oa
+.section sz8ob
+.section sz8pa
+.section sz8pb
+.section sz8qa
+.section sz8qb
+.section sz8ra
+.section sz8rb
+.section sz8sa
+.section sz8sb
+.section sz8ta
+.section sz8tb
+.section sz8ua
+.section sz8ub
+.section sz8va
+.section sz8vb
+.section sz8wa
+.section sz8wb
+.section sz8xa
+.section sz8xb
+.section sz8ya
+.section sz8yb
+.section sz8za
+.section sz8zb
+.section sz81a
+.section sz81b
+.section sz82a
+.section sz82b
+.section sz83a
+.section sz83b
+.section sz84a
+.section sz84b
+.section sz85a
+.section sz85b
+.section sz86a
+.section sz86b
+.section sz87a
+.section sz87b
+.section sz88a
+.section sz88b
+.section sz89a
+.section sz89b
+.section sz80a
+.section sz80b
+.section sz9aa
+.section sz9ab
+.section sz9ba
+.section sz9bb
+.section sz9ca
+.section sz9cb
+.section sz9da
+.section sz9db
+.section sz9ea
+.section sz9eb
+.section sz9fa
+.section sz9fb
+.section sz9ga
+.section sz9gb
+.section sz9ha
+.section sz9hb
+.section sz9ia
+.section sz9ib
+.section sz9ja
+.section sz9jb
+.section sz9ka
+.section sz9kb
+.section sz9la
+.section sz9lb
+.section sz9ma
+.section sz9mb
+.section sz9na
+.section sz9nb
+.section sz9oa
+.section sz9ob
+.section sz9pa
+.section sz9pb
+.section sz9qa
+.section sz9qb
+.section sz9ra
+.section sz9rb
+.section sz9sa
+.section sz9sb
+.section sz9ta
+.section sz9tb
+.section sz9ua
+.section sz9ub
+.section sz9va
+.section sz9vb
+.section sz9wa
+.section sz9wb
+.section sz9xa
+.section sz9xb
+.section sz9ya
+.section sz9yb
+.section sz9za
+.section sz9zb
+.section sz91a
+.section sz91b
+.section sz92a
+.section sz92b
+.section sz93a
+.section sz93b
+.section sz94a
+.section sz94b
+.section sz95a
+.section sz95b
+.section sz96a
+.section sz96b
+.section sz97a
+.section sz97b
+.section sz98a
+.section sz98b
+.section sz99a
+.section sz99b
+.section sz90a
+.section sz90b
+.section sz0aa
+.section sz0ab
+.section sz0ba
+.section sz0bb
+.section sz0ca
+.section sz0cb
+.section sz0da
+.section sz0db
+.section sz0ea
+.section sz0eb
+.section sz0fa
+.section sz0fb
+.section sz0ga
+.section sz0gb
+.section sz0ha
+.section sz0hb
+.section sz0ia
+.section sz0ib
+.section sz0ja
+.section sz0jb
+.section sz0ka
+.section sz0kb
+.section sz0la
+.section sz0lb
+.section sz0ma
+.section sz0mb
+.section sz0na
+.section sz0nb
+.section sz0oa
+.section sz0ob
+.section sz0pa
+.section sz0pb
+.section sz0qa
+.section sz0qb
+.section sz0ra
+.section sz0rb
+.section sz0sa
+.section sz0sb
+.section sz0ta
+.section sz0tb
+.section sz0ua
+.section sz0ub
+.section sz0va
+.section sz0vb
+.section sz0wa
+.section sz0wb
+.section sz0xa
+.section sz0xb
+.section sz0ya
+.section sz0yb
+.section sz0za
+.section sz0zb
+.section sz01a
+.section sz01b
+.section sz02a
+.section sz02b
+.section sz03a
+.section sz03b
+.section sz04a
+.section sz04b
+.section sz05a
+.section sz05b
+.section sz06a
+.section sz06b
+.section sz07a
+.section sz07b
+.section sz08a
+.section sz08b
+.section sz09a
+.section sz09b
+.section sz00a
+.section sz00b
+.section s1aaa
+.section s1aab
+.section s1aba
+.section s1abb
+.section s1aca
+.section s1acb
+.section s1ada
+.section s1adb
+.section s1aea
+.section s1aeb
+.section s1afa
+.section s1afb
+.section s1aga
+.section s1agb
+.section s1aha
+.section s1ahb
+.section s1aia
+.section s1aib
+.section s1aja
+.section s1ajb
+.section s1aka
+.section s1akb
+.section s1ala
+.section s1alb
+.section s1ama
+.section s1amb
+.section s1ana
+.section s1anb
+.section s1aoa
+.section s1aob
+.section s1apa
+.section s1apb
+.section s1aqa
+.section s1aqb
+.section s1ara
+.section s1arb
+.section s1asa
+.section s1asb
+.section s1ata
+.section s1atb
+.section s1aua
+.section s1aub
+.section s1ava
+.section s1avb
+.section s1awa
+.section s1awb
+.section s1axa
+.section s1axb
+.section s1aya
+.section s1ayb
+.section s1aza
+.section s1azb
+.section s1a1a
+.section s1a1b
+.section s1a2a
+.section s1a2b
+.section s1a3a
+.section s1a3b
+.section s1a4a
+.section s1a4b
+.section s1a5a
+.section s1a5b
+.section s1a6a
+.section s1a6b
+.section s1a7a
+.section s1a7b
+.section s1a8a
+.section s1a8b
+.section s1a9a
+.section s1a9b
+.section s1a0a
+.section s1a0b
+.section s1baa
+.section s1bab
+.section s1bba
+.section s1bbb
+.section s1bca
+.section s1bcb
+.section s1bda
+.section s1bdb
+.section s1bea
+.section s1beb
+.section s1bfa
+.section s1bfb
+.section s1bga
+.section s1bgb
+.section s1bha
+.section s1bhb
+.section s1bia
+.section s1bib
+.section s1bja
+.section s1bjb
+.section s1bka
+.section s1bkb
+.section s1bla
+.section s1blb
+.section s1bma
+.section s1bmb
+.section s1bna
+.section s1bnb
+.section s1boa
+.section s1bob
+.section s1bpa
+.section s1bpb
+.section s1bqa
+.section s1bqb
+.section s1bra
+.section s1brb
+.section s1bsa
+.section s1bsb
+.section s1bta
+.section s1btb
+.section s1bua
+.section s1bub
+.section s1bva
+.section s1bvb
+.section s1bwa
+.section s1bwb
+.section s1bxa
+.section s1bxb
+.section s1bya
+.section s1byb
+.section s1bza
+.section s1bzb
+.section s1b1a
+.section s1b1b
+.section s1b2a
+.section s1b2b
+.section s1b3a
+.section s1b3b
+.section s1b4a
+.section s1b4b
+.section s1b5a
+.section s1b5b
+.section s1b6a
+.section s1b6b
+.section s1b7a
+.section s1b7b
+.section s1b8a
+.section s1b8b
+.section s1b9a
+.section s1b9b
+.section s1b0a
+.section s1b0b
+.section s1caa
+.section s1cab
+.section s1cba
+.section s1cbb
+.section s1cca
+.section s1ccb
+.section s1cda
+.section s1cdb
+.section s1cea
+.section s1ceb
+.section s1cfa
+.section s1cfb
+.section s1cga
+.section s1cgb
+.section s1cha
+.section s1chb
+.section s1cia
+.section s1cib
+.section s1cja
+.section s1cjb
+.section s1cka
+.section s1ckb
+.section s1cla
+.section s1clb
+.section s1cma
+.section s1cmb
+.section s1cna
+.section s1cnb
+.section s1coa
+.section s1cob
+.section s1cpa
+.section s1cpb
+.section s1cqa
+.section s1cqb
+.section s1cra
+.section s1crb
+.section s1csa
+.section s1csb
+.section s1cta
+.section s1ctb
+.section s1cua
+.section s1cub
+.section s1cva
+.section s1cvb
+.section s1cwa
+.section s1cwb
+.section s1cxa
+.section s1cxb
+.section s1cya
+.section s1cyb
+.section s1cza
+.section s1czb
+.section s1c1a
+.section s1c1b
+.section s1c2a
+.section s1c2b
+.section s1c3a
+.section s1c3b
+.section s1c4a
+.section s1c4b
+.section s1c5a
+.section s1c5b
+.section s1c6a
+.section s1c6b
+.section s1c7a
+.section s1c7b
+.section s1c8a
+.section s1c8b
+.section s1c9a
+.section s1c9b
+.section s1c0a
+.section s1c0b
+.section s1daa
+.section s1dab
+.section s1dba
+.section s1dbb
+.section s1dca
+.section s1dcb
+.section s1dda
+.section s1ddb
+.section s1dea
+.section s1deb
+.section s1dfa
+.section s1dfb
+.section s1dga
+.section s1dgb
+.section s1dha
+.section s1dhb
+.section s1dia
+.section s1dib
+.section s1dja
+.section s1djb
+.section s1dka
+.section s1dkb
+.section s1dla
+.section s1dlb
+.section s1dma
+.section s1dmb
+.section s1dna
+.section s1dnb
+.section s1doa
+.section s1dob
+.section s1dpa
+.section s1dpb
+.section s1dqa
+.section s1dqb
+.section s1dra
+.section s1drb
+.section s1dsa
+.section s1dsb
+.section s1dta
+.section s1dtb
+.section s1dua
+.section s1dub
+.section s1dva
+.section s1dvb
+.section s1dwa
+.section s1dwb
+.section s1dxa
+.section s1dxb
+.section s1dya
+.section s1dyb
+.section s1dza
+.section s1dzb
+.section s1d1a
+.section s1d1b
+.section s1d2a
+.section s1d2b
+.section s1d3a
+.section s1d3b
+.section s1d4a
+.section s1d4b
+.section s1d5a
+.section s1d5b
+.section s1d6a
+.section s1d6b
+.section s1d7a
+.section s1d7b
+.section s1d8a
+.section s1d8b
+.section s1d9a
+.section s1d9b
+.section s1d0a
+.section s1d0b
+.section s1eaa
+.section s1eab
+.section s1eba
+.section s1ebb
+.section s1eca
+.section s1ecb
+.section s1eda
+.section s1edb
+.section s1eea
+.section s1eeb
+.section s1efa
+.section s1efb
+.section s1ega
+.section s1egb
+.section s1eha
+.section s1ehb
+.section s1eia
+.section s1eib
+.section s1eja
+.section s1ejb
+.section s1eka
+.section s1ekb
+.section s1ela
+.section s1elb
+.section s1ema
+.section s1emb
+.section s1ena
+.section s1enb
+.section s1eoa
+.section s1eob
+.section s1epa
+.section s1epb
+.section s1eqa
+.section s1eqb
+.section s1era
+.section s1erb
+.section s1esa
+.section s1esb
+.section s1eta
+.section s1etb
+.section s1eua
+.section s1eub
+.section s1eva
+.section s1evb
+.section s1ewa
+.section s1ewb
+.section s1exa
+.section s1exb
+.section s1eya
+.section s1eyb
+.section s1eza
+.section s1ezb
+.section s1e1a
+.section s1e1b
+.section s1e2a
+.section s1e2b
+.section s1e3a
+.section s1e3b
+.section s1e4a
+.section s1e4b
+.section s1e5a
+.section s1e5b
+.section s1e6a
+.section s1e6b
+.section s1e7a
+.section s1e7b
+.section s1e8a
+.section s1e8b
+.section s1e9a
+.section s1e9b
+.section s1e0a
+.section s1e0b
+.section s1faa
+.section s1fab
+.section s1fba
+.section s1fbb
+.section s1fca
+.section s1fcb
+.section s1fda
+.section s1fdb
+.section s1fea
+.section s1feb
+.section s1ffa
+.section s1ffb
+.section s1fga
+.section s1fgb
+.section s1fha
+.section s1fhb
+.section s1fia
+.section s1fib
+.section s1fja
+.section s1fjb
+.section s1fka
+.section s1fkb
+.section s1fla
+.section s1flb
+.section s1fma
+.section s1fmb
+.section s1fna
+.section s1fnb
+.section s1foa
+.section s1fob
+.section s1fpa
+.section s1fpb
+.section s1fqa
+.section s1fqb
+.section s1fra
+.section s1frb
+.section s1fsa
+.section s1fsb
+.section s1fta
+.section s1ftb
+.section s1fua
+.section s1fub
+.section s1fva
+.section s1fvb
+.section s1fwa
+.section s1fwb
+.section s1fxa
+.section s1fxb
+.section s1fya
+.section s1fyb
+.section s1fza
+.section s1fzb
+.section s1f1a
+.section s1f1b
+.section s1f2a
+.section s1f2b
+.section s1f3a
+.section s1f3b
+.section s1f4a
+.section s1f4b
+.section s1f5a
+.section s1f5b
+.section s1f6a
+.section s1f6b
+.section s1f7a
+.section s1f7b
+.section s1f8a
+.section s1f8b
+.section s1f9a
+.section s1f9b
+.section s1f0a
+.section s1f0b
+.section s1gaa
+.section s1gab
+.section s1gba
+.section s1gbb
+.section s1gca
+.section s1gcb
+.section s1gda
+.section s1gdb
+.section s1gea
+.section s1geb
+.section s1gfa
+.section s1gfb
+.section s1gga
+.section s1ggb
+.section s1gha
+.section s1ghb
+.section s1gia
+.section s1gib
+.section s1gja
+.section s1gjb
+.section s1gka
+.section s1gkb
+.section s1gla
+.section s1glb
+.section s1gma
+.section s1gmb
+.section s1gna
+.section s1gnb
+.section s1goa
+.section s1gob
+.section s1gpa
+.section s1gpb
+.section s1gqa
+.section s1gqb
+.section s1gra
+.section s1grb
+.section s1gsa
+.section s1gsb
+.section s1gta
+.section s1gtb
+.section s1gua
+.section s1gub
+.section s1gva
+.section s1gvb
+.section s1gwa
+.section s1gwb
+.section s1gxa
+.section s1gxb
+.section s1gya
+.section s1gyb
+.section s1gza
+.section s1gzb
+.section s1g1a
+.section s1g1b
+.section s1g2a
+.section s1g2b
+.section s1g3a
+.section s1g3b
+.section s1g4a
+.section s1g4b
+.section s1g5a
+.section s1g5b
+.section s1g6a
+.section s1g6b
+.section s1g7a
+.section s1g7b
+.section s1g8a
+.section s1g8b
+.section s1g9a
+.section s1g9b
+.section s1g0a
+.section s1g0b
+.section s1haa
+.section s1hab
+.section s1hba
+.section s1hbb
+.section s1hca
+.section s1hcb
+.section s1hda
+.section s1hdb
+.section s1hea
+.section s1heb
+.section s1hfa
+.section s1hfb
+.section s1hga
+.section s1hgb
+.section s1hha
+.section s1hhb
+.section s1hia
+.section s1hib
+.section s1hja
+.section s1hjb
+.section s1hka
+.section s1hkb
+.section s1hla
+.section s1hlb
+.section s1hma
+.section s1hmb
+.section s1hna
+.section s1hnb
+.section s1hoa
+.section s1hob
+.section s1hpa
+.section s1hpb
+.section s1hqa
+.section s1hqb
+.section s1hra
+.section s1hrb
+.section s1hsa
+.section s1hsb
+.section s1hta
+.section s1htb
+.section s1hua
+.section s1hub
+.section s1hva
+.section s1hvb
+.section s1hwa
+.section s1hwb
+.section s1hxa
+.section s1hxb
+.section s1hya
+.section s1hyb
+.section s1hza
+.section s1hzb
+.section s1h1a
+.section s1h1b
+.section s1h2a
+.section s1h2b
+.section s1h3a
+.section s1h3b
+.section s1h4a
+.section s1h4b
+.section s1h5a
+.section s1h5b
+.section s1h6a
+.section s1h6b
+.section s1h7a
+.section s1h7b
+.section s1h8a
+.section s1h8b
+.section s1h9a
+.section s1h9b
+.section s1h0a
+.section s1h0b
+.section s1iaa
+.section s1iab
+.section s1iba
+.section s1ibb
+.section s1ica
+.section s1icb
+.section s1ida
+.section s1idb
+.section s1iea
+.section s1ieb
+.section s1ifa
+.section s1ifb
+.section s1iga
+.section s1igb
+.section s1iha
+.section s1ihb
+.section s1iia
+.section s1iib
+.section s1ija
+.section s1ijb
+.section s1ika
+.section s1ikb
+.section s1ila
+.section s1ilb
+.section s1ima
+.section s1imb
+.section s1ina
+.section s1inb
+.section s1ioa
+.section s1iob
+.section s1ipa
+.section s1ipb
+.section s1iqa
+.section s1iqb
+.section s1ira
+.section s1irb
+.section s1isa
+.section s1isb
+.section s1ita
+.section s1itb
+.section s1iua
+.section s1iub
+.section s1iva
+.section s1ivb
+.section s1iwa
+.section s1iwb
+.section s1ixa
+.section s1ixb
+.section s1iya
+.section s1iyb
+.section s1iza
+.section s1izb
+.section s1i1a
+.section s1i1b
+.section s1i2a
+.section s1i2b
+.section s1i3a
+.section s1i3b
+.section s1i4a
+.section s1i4b
+.section s1i5a
+.section s1i5b
+.section s1i6a
+.section s1i6b
+.section s1i7a
+.section s1i7b
+.section s1i8a
+.section s1i8b
+.section s1i9a
+.section s1i9b
+.section s1i0a
+.section s1i0b
+.section s1jaa
+.section s1jab
+.section s1jba
+.section s1jbb
+.section s1jca
+.section s1jcb
+.section s1jda
+.section s1jdb
+.section s1jea
+.section s1jeb
+.section s1jfa
+.section s1jfb
+.section s1jga
+.section s1jgb
+.section s1jha
+.section s1jhb
+.section s1jia
+.section s1jib
+.section s1jja
+.section s1jjb
+.section s1jka
+.section s1jkb
+.section s1jla
+.section s1jlb
+.section s1jma
+.section s1jmb
+.section s1jna
+.section s1jnb
+.section s1joa
+.section s1job
+.section s1jpa
+.section s1jpb
+.section s1jqa
+.section s1jqb
+.section s1jra
+.section s1jrb
+.section s1jsa
+.section s1jsb
+.section s1jta
+.section s1jtb
+.section s1jua
+.section s1jub
+.section s1jva
+.section s1jvb
+.section s1jwa
+.section s1jwb
+.section s1jxa
+.section s1jxb
+.section s1jya
+.section s1jyb
+.section s1jza
+.section s1jzb
+.section s1j1a
+.section s1j1b
+.section s1j2a
+.section s1j2b
+.section s1j3a
+.section s1j3b
+.section s1j4a
+.section s1j4b
+.section s1j5a
+.section s1j5b
+.section s1j6a
+.section s1j6b
+.section s1j7a
+.section s1j7b
+.section s1j8a
+.section s1j8b
+.section s1j9a
+.section s1j9b
+.section s1j0a
+.section s1j0b
+.section s1kaa
+.section s1kab
+.section s1kba
+.section s1kbb
+.section s1kca
+.section s1kcb
+.section s1kda
+.section s1kdb
+.section s1kea
+.section s1keb
+.section s1kfa
+.section s1kfb
+.section s1kga
+.section s1kgb
+.section s1kha
+.section s1khb
+.section s1kia
+.section s1kib
+.section s1kja
+.section s1kjb
+.section s1kka
+.section s1kkb
+.section s1kla
+.section s1klb
+.section s1kma
+.section s1kmb
+.section s1kna
+.section s1knb
+.section s1koa
+.section s1kob
+.section s1kpa
+.section s1kpb
+.section s1kqa
+.section s1kqb
+.section s1kra
+.section s1krb
+.section s1ksa
+.section s1ksb
+.section s1kta
+.section s1ktb
+.section s1kua
+.section s1kub
+.section s1kva
+.section s1kvb
+.section s1kwa
+.section s1kwb
+.section s1kxa
+.section s1kxb
+.section s1kya
+.section s1kyb
+.section s1kza
+.section s1kzb
+.section s1k1a
+.section s1k1b
+.section s1k2a
+.section s1k2b
+.section s1k3a
+.section s1k3b
+.section s1k4a
+.section s1k4b
+.section s1k5a
+.section s1k5b
+.section s1k6a
+.section s1k6b
+.section s1k7a
+.section s1k7b
+.section s1k8a
+.section s1k8b
+.section s1k9a
+.section s1k9b
+.section s1k0a
+.section s1k0b
+.section s1laa
+.section s1lab
+.section s1lba
+.section s1lbb
+.section s1lca
+.section s1lcb
+.section s1lda
+.section s1ldb
+.section s1lea
+.section s1leb
+.section s1lfa
+.section s1lfb
+.section s1lga
+.section s1lgb
+.section s1lha
+.section s1lhb
+.section s1lia
+.section s1lib
+.section s1lja
+.section s1ljb
+.section s1lka
+.section s1lkb
+.section s1lla
+.section s1llb
+.section s1lma
+.section s1lmb
+.section s1lna
+.section s1lnb
+.section s1loa
+.section s1lob
+.section s1lpa
+.section s1lpb
+.section s1lqa
+.section s1lqb
+.section s1lra
+.section s1lrb
+.section s1lsa
+.section s1lsb
+.section s1lta
+.section s1ltb
+.section s1lua
+.section s1lub
+.section s1lva
+.section s1lvb
+.section s1lwa
+.section s1lwb
+.section s1lxa
+.section s1lxb
+.section s1lya
+.section s1lyb
+.section s1lza
+.section s1lzb
+.section s1l1a
+.section s1l1b
+.section s1l2a
+.section s1l2b
+.section s1l3a
+.section s1l3b
+.section s1l4a
+.section s1l4b
+.section s1l5a
+.section s1l5b
+.section s1l6a
+.section s1l6b
+.section s1l7a
+.section s1l7b
+.section s1l8a
+.section s1l8b
+.section s1l9a
+.section s1l9b
+.section s1l0a
+.section s1l0b
+.section s1maa
+.section s1mab
+.section s1mba
+.section s1mbb
+.section s1mca
+.section s1mcb
+.section s1mda
+.section s1mdb
+.section s1mea
+.section s1meb
+.section s1mfa
+.section s1mfb
+.section s1mga
+.section s1mgb
+.section s1mha
+.section s1mhb
+.section s1mia
+.section s1mib
+.section s1mja
+.section s1mjb
+.section s1mka
+.section s1mkb
+.section s1mla
+.section s1mlb
+.section s1mma
+.section s1mmb
+.section s1mna
+.section s1mnb
+.section s1moa
+.section s1mob
+.section s1mpa
+.section s1mpb
+.section s1mqa
+.section s1mqb
+.section s1mra
+.section s1mrb
+.section s1msa
+.section s1msb
+.section s1mta
+.section s1mtb
+.section s1mua
+.section s1mub
+.section s1mva
+.section s1mvb
+.section s1mwa
+.section s1mwb
+.section s1mxa
+.section s1mxb
+.section s1mya
+.section s1myb
+.section s1mza
+.section s1mzb
+.section s1m1a
+.section s1m1b
+.section s1m2a
+.section s1m2b
+.section s1m3a
+.section s1m3b
+.section s1m4a
+.section s1m4b
+.section s1m5a
+.section s1m5b
+.section s1m6a
+.section s1m6b
+.section s1m7a
+.section s1m7b
+.section s1m8a
+.section s1m8b
+.section s1m9a
+.section s1m9b
+.section s1m0a
+.section s1m0b
+.section s1naa
+.section s1nab
+.section s1nba
+.section s1nbb
+.section s1nca
+.section s1ncb
+.section s1nda
+.section s1ndb
+.section s1nea
+.section s1neb
+.section s1nfa
+.section s1nfb
+.section s1nga
+.section s1ngb
+.section s1nha
+.section s1nhb
+.section s1nia
+.section s1nib
+.section s1nja
+.section s1njb
+.section s1nka
+.section s1nkb
+.section s1nla
+.section s1nlb
+.section s1nma
+.section s1nmb
+.section s1nna
+.section s1nnb
+.section s1noa
+.section s1nob
+.section s1npa
+.section s1npb
+.section s1nqa
+.section s1nqb
+.section s1nra
+.section s1nrb
+.section s1nsa
+.section s1nsb
+.section s1nta
+.section s1ntb
+.section s1nua
+.section s1nub
+.section s1nva
+.section s1nvb
+.section s1nwa
+.section s1nwb
+.section s1nxa
+.section s1nxb
+.section s1nya
+.section s1nyb
+.section s1nza
+.section s1nzb
+.section s1n1a
+.section s1n1b
+.section s1n2a
+.section s1n2b
+.section s1n3a
+.section s1n3b
+.section s1n4a
+.section s1n4b
+.section s1n5a
+.section s1n5b
+.section s1n6a
+.section s1n6b
+.section s1n7a
+.section s1n7b
+.section s1n8a
+.section s1n8b
+.section s1n9a
+.section s1n9b
+.section s1n0a
+.section s1n0b
+.section s1oaa
+.section s1oab
+.section s1oba
+.section s1obb
+.section s1oca
+.section s1ocb
+.section s1oda
+.section s1odb
+.section s1oea
+.section s1oeb
+.section s1ofa
+.section s1ofb
+.section s1oga
+.section s1ogb
+.section s1oha
+.section s1ohb
+.section s1oia
+.section s1oib
+.section s1oja
+.section s1ojb
+.section s1oka
+.section s1okb
+.section s1ola
+.section s1olb
+.section s1oma
+.section s1omb
+.section s1ona
+.section s1onb
+.section s1ooa
+.section s1oob
+.section s1opa
+.section s1opb
+.section s1oqa
+.section s1oqb
+.section s1ora
+.section s1orb
+.section s1osa
+.section s1osb
+.section s1ota
+.section s1otb
+.section s1oua
+.section s1oub
+.section s1ova
+.section s1ovb
+.section s1owa
+.section s1owb
+.section s1oxa
+.section s1oxb
+.section s1oya
+.section s1oyb
+.section s1oza
+.section s1ozb
+.section s1o1a
+.section s1o1b
+.section s1o2a
+.section s1o2b
+.section s1o3a
+.section s1o3b
+.section s1o4a
+.section s1o4b
+.section s1o5a
+.section s1o5b
+.section s1o6a
+.section s1o6b
+.section s1o7a
+.section s1o7b
+.section s1o8a
+.section s1o8b
+.section s1o9a
+.section s1o9b
+.section s1o0a
+.section s1o0b
+.section s1paa
+.section s1pab
+.section s1pba
+.section s1pbb
+.section s1pca
+.section s1pcb
+.section s1pda
+.section s1pdb
+.section s1pea
+.section s1peb
+.section s1pfa
+.section s1pfb
+.section s1pga
+.section s1pgb
+.section s1pha
+.section s1phb
+.section s1pia
+.section s1pib
+.section s1pja
+.section s1pjb
+.section s1pka
+.section s1pkb
+.section s1pla
+.section s1plb
+.section s1pma
+.section s1pmb
+.section s1pna
+.section s1pnb
+.section s1poa
+.section s1pob
+.section s1ppa
+.section s1ppb
+.section s1pqa
+.section s1pqb
+.section s1pra
+.section s1prb
+.section s1psa
+.section s1psb
+.section s1pta
+.section s1ptb
+.section s1pua
+.section s1pub
+.section s1pva
+.section s1pvb
+.section s1pwa
+.section s1pwb
+.section s1pxa
+.section s1pxb
+.section s1pya
+.section s1pyb
+.section s1pza
+.section s1pzb
+.section s1p1a
+.section s1p1b
+.section s1p2a
+.section s1p2b
+.section s1p3a
+.section s1p3b
+.section s1p4a
+.section s1p4b
+.section s1p5a
+.section s1p5b
+.section s1p6a
+.section s1p6b
+.section s1p7a
+.section s1p7b
+.section s1p8a
+.section s1p8b
+.section s1p9a
+.section s1p9b
+.section s1p0a
+.section s1p0b
+.section s1qaa
+.section s1qab
+.section s1qba
+.section s1qbb
+.section s1qca
+.section s1qcb
+.section s1qda
+.section s1qdb
+.section s1qea
+.section s1qeb
+.section s1qfa
+.section s1qfb
+.section s1qga
+.section s1qgb
+.section s1qha
+.section s1qhb
+.section s1qia
+.section s1qib
+.section s1qja
+.section s1qjb
+.section s1qka
+.section s1qkb
+.section s1qla
+.section s1qlb
+.section s1qma
+.section s1qmb
+.section s1qna
+.section s1qnb
+.section s1qoa
+.section s1qob
+.section s1qpa
+.section s1qpb
+.section s1qqa
+.section s1qqb
+.section s1qra
+.section s1qrb
+.section s1qsa
+.section s1qsb
+.section s1qta
+.section s1qtb
+.section s1qua
+.section s1qub
+.section s1qva
+.section s1qvb
+.section s1qwa
+.section s1qwb
+.section s1qxa
+.section s1qxb
+.section s1qya
+.section s1qyb
+.section s1qza
+.section s1qzb
+.section s1q1a
+.section s1q1b
+.section s1q2a
+.section s1q2b
+.section s1q3a
+.section s1q3b
+.section s1q4a
+.section s1q4b
+.section s1q5a
+.section s1q5b
+.section s1q6a
+.section s1q6b
+.section s1q7a
+.section s1q7b
+.section s1q8a
+.section s1q8b
+.section s1q9a
+.section s1q9b
+.section s1q0a
+.section s1q0b
+.section s1raa
+.section s1rab
+.section s1rba
+.section s1rbb
+.section s1rca
+.section s1rcb
+.section s1rda
+.section s1rdb
+.section s1rea
+.section s1reb
+.section s1rfa
+.section s1rfb
+.section s1rga
+.section s1rgb
+.section s1rha
+.section s1rhb
+.section s1ria
+.section s1rib
+.section s1rja
+.section s1rjb
+.section s1rka
+.section s1rkb
+.section s1rla
+.section s1rlb
+.section s1rma
+.section s1rmb
+.section s1rna
+.section s1rnb
+.section s1roa
+.section s1rob
+.section s1rpa
+.section s1rpb
+.section s1rqa
+.section s1rqb
+.section s1rra
+.section s1rrb
+.section s1rsa
+.section s1rsb
+.section s1rta
+.section s1rtb
+.section s1rua
+.section s1rub
+.section s1rva
+.section s1rvb
+.section s1rwa
+.section s1rwb
+.section s1rxa
+.section s1rxb
+.section s1rya
+.section s1ryb
+.section s1rza
+.section s1rzb
+.section s1r1a
+.section s1r1b
+.section s1r2a
+.section s1r2b
+.section s1r3a
+.section s1r3b
+.section s1r4a
+.section s1r4b
+.section s1r5a
+.section s1r5b
+.section s1r6a
+.section s1r6b
+.section s1r7a
+.section s1r7b
+.section s1r8a
+.section s1r8b
+.section s1r9a
+.section s1r9b
+.section s1r0a
+.section s1r0b
+.section s1saa
+.section s1sab
+.section s1sba
+.section s1sbb
+.section s1sca
+.section s1scb
+.section s1sda
+.section s1sdb
+.section s1sea
+.section s1seb
+.section s1sfa
+.section s1sfb
+.section s1sga
+.section s1sgb
+.section s1sha
+.section s1shb
+.section s1sia
+.section s1sib
+.section s1sja
+.section s1sjb
+.section s1ska
+.section s1skb
+.section s1sla
+.section s1slb
+.section s1sma
+.section s1smb
+.section s1sna
+.section s1snb
+.section s1soa
+.section s1sob
+.section s1spa
+.section s1spb
+.section s1sqa
+.section s1sqb
+.section s1sra
+.section s1srb
+.section s1ssa
+.section s1ssb
+.section s1sta
+.section s1stb
+.section s1sua
+.section s1sub
+.section s1sva
+.section s1svb
+.section s1swa
+.section s1swb
+.section s1sxa
+.section s1sxb
+.section s1sya
+.section s1syb
+.section s1sza
+.section s1szb
+.section s1s1a
+.section s1s1b
+.section s1s2a
+.section s1s2b
+.section s1s3a
+.section s1s3b
+.section s1s4a
+.section s1s4b
+.section s1s5a
+.section s1s5b
+.section s1s6a
+.section s1s6b
+.section s1s7a
+.section s1s7b
+.section s1s8a
+.section s1s8b
+.section s1s9a
+.section s1s9b
+.section s1s0a
+.section s1s0b
+.section s1taa
+.section s1tab
+.section s1tba
+.section s1tbb
+.section s1tca
+.section s1tcb
+.section s1tda
+.section s1tdb
+.section s1tea
+.section s1teb
+.section s1tfa
+.section s1tfb
+.section s1tga
+.section s1tgb
+.section s1tha
+.section s1thb
+.section s1tia
+.section s1tib
+.section s1tja
+.section s1tjb
+.section s1tka
+.section s1tkb
+.section s1tla
+.section s1tlb
+.section s1tma
+.section s1tmb
+.section s1tna
+.section s1tnb
+.section s1toa
+.section s1tob
+.section s1tpa
+.section s1tpb
+.section s1tqa
+.section s1tqb
+.section s1tra
+.section s1trb
+.section s1tsa
+.section s1tsb
+.section s1tta
+.section s1ttb
+.section s1tua
+.section s1tub
+.section s1tva
+.section s1tvb
+.section s1twa
+.section s1twb
+.section s1txa
+.section s1txb
+.section s1tya
+.section s1tyb
+.section s1tza
+.section s1tzb
+.section s1t1a
+.section s1t1b
+.section s1t2a
+.section s1t2b
+.section s1t3a
+.section s1t3b
+.section s1t4a
+.section s1t4b
+.section s1t5a
+.section s1t5b
+.section s1t6a
+.section s1t6b
+.section s1t7a
+.section s1t7b
+.section s1t8a
+.section s1t8b
+.section s1t9a
+.section s1t9b
+.section s1t0a
+.section s1t0b
+.section s1uaa
+.section s1uab
+.section s1uba
+.section s1ubb
+.section s1uca
+.section s1ucb
+.section s1uda
+.section s1udb
+.section s1uea
+.section s1ueb
+.section s1ufa
+.section s1ufb
+.section s1uga
+.section s1ugb
+.section s1uha
+.section s1uhb
+.section s1uia
+.section s1uib
+.section s1uja
+.section s1ujb
+.section s1uka
+.section s1ukb
+.section s1ula
+.section s1ulb
+.section s1uma
+.section s1umb
+.section s1una
+.section s1unb
+.section s1uoa
+.section s1uob
+.section s1upa
+.section s1upb
+.section s1uqa
+.section s1uqb
+.section s1ura
+.section s1urb
+.section s1usa
+.section s1usb
+.section s1uta
+.section s1utb
+.section s1uua
+.section s1uub
+.section s1uva
+.section s1uvb
+.section s1uwa
+.section s1uwb
+.section s1uxa
+.section s1uxb
+.section s1uya
+.section s1uyb
+.section s1uza
+.section s1uzb
+.section s1u1a
+.section s1u1b
+.section s1u2a
+.section s1u2b
+.section s1u3a
+.section s1u3b
+.section s1u4a
+.section s1u4b
+.section s1u5a
+.section s1u5b
+.section s1u6a
+.section s1u6b
+.section s1u7a
+.section s1u7b
+.section s1u8a
+.section s1u8b
+.section s1u9a
+.section s1u9b
+.section s1u0a
+.section s1u0b
+.section s1vaa
+.section s1vab
+.section s1vba
+.section s1vbb
+.section s1vca
+.section s1vcb
+.section s1vda
+.section s1vdb
+.section s1vea
+.section s1veb
+.section s1vfa
+.section s1vfb
+.section s1vga
+.section s1vgb
+.section s1vha
+.section s1vhb
+.section s1via
+.section s1vib
+.section s1vja
+.section s1vjb
+.section s1vka
+.section s1vkb
+.section s1vla
+.section s1vlb
+.section s1vma
+.section s1vmb
+.section s1vna
+.section s1vnb
+.section s1voa
+.section s1vob
+.section s1vpa
+.section s1vpb
+.section s1vqa
+.section s1vqb
+.section s1vra
+.section s1vrb
+.section s1vsa
+.section s1vsb
+.section s1vta
+.section s1vtb
+.section s1vua
+.section s1vub
+.section s1vva
+.section s1vvb
+.section s1vwa
+.section s1vwb
+.section s1vxa
+.section s1vxb
+.section s1vya
+.section s1vyb
+.section s1vza
+.section s1vzb
+.section s1v1a
+.section s1v1b
+.section s1v2a
+.section s1v2b
+.section s1v3a
+.section s1v3b
+.section s1v4a
+.section s1v4b
+.section s1v5a
+.section s1v5b
+.section s1v6a
+.section s1v6b
+.section s1v7a
+.section s1v7b
+.section s1v8a
+.section s1v8b
+.section s1v9a
+.section s1v9b
+.section s1v0a
+.section s1v0b
+.section s1waa
+.section s1wab
+.section s1wba
+.section s1wbb
+.section s1wca
+.section s1wcb
+.section s1wda
+.section s1wdb
+.section s1wea
+.section s1web
+.section s1wfa
+.section s1wfb
+.section s1wga
+.section s1wgb
+.section s1wha
+.section s1whb
+.section s1wia
+.section s1wib
+.section s1wja
+.section s1wjb
+.section s1wka
+.section s1wkb
+.section s1wla
+.section s1wlb
+.section s1wma
+.section s1wmb
+.section s1wna
+.section s1wnb
+.section s1woa
+.section s1wob
+.section s1wpa
+.section s1wpb
+.section s1wqa
+.section s1wqb
+.section s1wra
+.section s1wrb
+.section s1wsa
+.section s1wsb
+.section s1wta
+.section s1wtb
+.section s1wua
+.section s1wub
+.section s1wva
+.section s1wvb
+.section s1wwa
+.section s1wwb
+.section s1wxa
+.section s1wxb
+.section s1wya
+.section s1wyb
+.section s1wza
+.section s1wzb
+.section s1w1a
+.section s1w1b
+.section s1w2a
+.section s1w2b
+.section s1w3a
+.section s1w3b
+.section s1w4a
+.section s1w4b
+.section s1w5a
+.section s1w5b
+.section s1w6a
+.section s1w6b
+.section s1w7a
+.section s1w7b
+.section s1w8a
+.section s1w8b
+.section s1w9a
+.section s1w9b
+.section s1w0a
+.section s1w0b
+.section s1xaa
+.section s1xab
+.section s1xba
+.section s1xbb
+.section s1xca
+.section s1xcb
+.section s1xda
+.section s1xdb
+.section s1xea
+.section s1xeb
+.section s1xfa
+.section s1xfb
+.section s1xga
+.section s1xgb
+.section s1xha
+.section s1xhb
+.section s1xia
+.section s1xib
+.section s1xja
+.section s1xjb
+.section s1xka
+.section s1xkb
+.section s1xla
+.section s1xlb
+.section s1xma
+.section s1xmb
+.section s1xna
+.section s1xnb
+.section s1xoa
+.section s1xob
+.section s1xpa
+.section s1xpb
+.section s1xqa
+.section s1xqb
+.section s1xra
+.section s1xrb
+.section s1xsa
+.section s1xsb
+.section s1xta
+.section s1xtb
+.section s1xua
+.section s1xub
+.section s1xva
+.section s1xvb
+.section s1xwa
+.section s1xwb
+.section s1xxa
+.section s1xxb
+.section s1xya
+.section s1xyb
+.section s1xza
+.section s1xzb
+.section s1x1a
+.section s1x1b
+.section s1x2a
+.section s1x2b
+.section s1x3a
+.section s1x3b
+.section s1x4a
+.section s1x4b
+.section s1x5a
+.section s1x5b
+.section s1x6a
+.section s1x6b
+.section s1x7a
+.section s1x7b
+.section s1x8a
+.section s1x8b
+.section s1x9a
+.section s1x9b
+.section s1x0a
+.section s1x0b
+.section s1yaa
+.section s1yab
+.section s1yba
+.section s1ybb
+.section s1yca
+.section s1ycb
+.section s1yda
+.section s1ydb
+.section s1yea
+.section s1yeb
+.section s1yfa
+.section s1yfb
+.section s1yga
+.section s1ygb
+.section s1yha
+.section s1yhb
+.section s1yia
+.section s1yib
+.section s1yja
+.section s1yjb
+.section s1yka
+.section s1ykb
+.section s1yla
+.section s1ylb
+.section s1yma
+.section s1ymb
+.section s1yna
+.section s1ynb
+.section s1yoa
+.section s1yob
+.section s1ypa
+.section s1ypb
+.section s1yqa
+.section s1yqb
+.section s1yra
+.section s1yrb
+.section s1ysa
+.section s1ysb
+.section s1yta
+.section s1ytb
+.section s1yua
+.section s1yub
+.section s1yva
+.section s1yvb
+.section s1ywa
+.section s1ywb
+.section s1yxa
+.section s1yxb
+.section s1yya
+.section s1yyb
+.section s1yza
+.section s1yzb
+.section s1y1a
+.section s1y1b
+.section s1y2a
+.section s1y2b
+.section s1y3a
+.section s1y3b
+.section s1y4a
+.section s1y4b
+.section s1y5a
+.section s1y5b
+.section s1y6a
+.section s1y6b
+.section s1y7a
+.section s1y7b
+.section s1y8a
+.section s1y8b
+.section s1y9a
+.section s1y9b
+.section s1y0a
+.section s1y0b
+.section s1zaa
+.section s1zab
+.section s1zba
+.section s1zbb
+.section s1zca
+.section s1zcb
+.section s1zda
+.section s1zdb
+.section s1zea
+.section s1zeb
+.section s1zfa
+.section s1zfb
+.section s1zga
+.section s1zgb
+.section s1zha
+.section s1zhb
+.section s1zia
+.section s1zib
+.section s1zja
+.section s1zjb
+.section s1zka
+.section s1zkb
+.section s1zla
+.section s1zlb
+.section s1zma
+.section s1zmb
+.section s1zna
+.section s1znb
+.section s1zoa
+.section s1zob
+.section s1zpa
+.section s1zpb
+.section s1zqa
+.section s1zqb
+.section s1zra
+.section s1zrb
+.section s1zsa
+.section s1zsb
+.section s1zta
+.section s1ztb
+.section s1zua
+.section s1zub
+.section s1zva
+.section s1zvb
+.section s1zwa
+.section s1zwb
+.section s1zxa
+.section s1zxb
+.section s1zya
+.section s1zyb
+.section s1zza
+.section s1zzb
+.section s1z1a
+.section s1z1b
+.section s1z2a
+.section s1z2b
+.section s1z3a
+.section s1z3b
+.section s1z4a
+.section s1z4b
+.section s1z5a
+.section s1z5b
+.section s1z6a
+.section s1z6b
+.section s1z7a
+.section s1z7b
+.section s1z8a
+.section s1z8b
+.section s1z9a
+.section s1z9b
+.section s1z0a
+.section s1z0b
+.section s11aa
+.section s11ab
+.section s11ba
+.section s11bb
+.section s11ca
+.section s11cb
+.section s11da
+.section s11db
+.section s11ea
+.section s11eb
+.section s11fa
+.section s11fb
+.section s11ga
+.section s11gb
+.section s11ha
+.section s11hb
+.section s11ia
+.section s11ib
+.section s11ja
+.section s11jb
+.section s11ka
+.section s11kb
+.section s11la
+.section s11lb
+.section s11ma
+.section s11mb
+.section s11na
+.section s11nb
+.section s11oa
+.section s11ob
+.section s11pa
+.section s11pb
+.section s11qa
+.section s11qb
+.section s11ra
+.section s11rb
+.section s11sa
+.section s11sb
+.section s11ta
+.section s11tb
+.section s11ua
+.section s11ub
+.section s11va
+.section s11vb
+.section s11wa
+.section s11wb
+.section s11xa
+.section s11xb
+.section s11ya
+.section s11yb
+.section s11za
+.section s11zb
+.section s111a
+.section s111b
+.section s112a
+.section s112b
+.section s113a
+.section s113b
+.section s114a
+.section s114b
+.section s115a
+.section s115b
+.section s116a
+.section s116b
+.section s117a
+.section s117b
+.section s118a
+.section s118b
+.section s119a
+.section s119b
+.section s110a
+.section s110b
+.section s12aa
+.section s12ab
+.section s12ba
+.section s12bb
+.section s12ca
+.section s12cb
+.section s12da
+.section s12db
+.section s12ea
+.section s12eb
+.section s12fa
+.section s12fb
+.section s12ga
+.section s12gb
+.section s12ha
+.section s12hb
+.section s12ia
+.section s12ib
+.section s12ja
+.section s12jb
+.section s12ka
+.section s12kb
+.section s12la
+.section s12lb
+.section s12ma
+.section s12mb
+.section s12na
+.section s12nb
+.section s12oa
+.section s12ob
+.section s12pa
+.section s12pb
+.section s12qa
+.section s12qb
+.section s12ra
+.section s12rb
+.section s12sa
+.section s12sb
+.section s12ta
+.section s12tb
+.section s12ua
+.section s12ub
+.section s12va
+.section s12vb
+.section s12wa
+.section s12wb
+.section s12xa
+.section s12xb
+.section s12ya
+.section s12yb
+.section s12za
+.section s12zb
+.section s121a
+.section s121b
+.section s122a
+.section s122b
+.section s123a
+.section s123b
+.section s124a
+.section s124b
+.section s125a
+.section s125b
+.section s126a
+.section s126b
+.section s127a
+.section s127b
+.section s128a
+.section s128b
+.section s129a
+.section s129b
+.section s120a
+.section s120b
+.section s13aa
+.section s13ab
+.section s13ba
+.section s13bb
+.section s13ca
+.section s13cb
+.section s13da
+.section s13db
+.section s13ea
+.section s13eb
+.section s13fa
+.section s13fb
+.section s13ga
+.section s13gb
+.section s13ha
+.section s13hb
+.section s13ia
+.section s13ib
+.section s13ja
+.section s13jb
+.section s13ka
+.section s13kb
+.section s13la
+.section s13lb
+.section s13ma
+.section s13mb
+.section s13na
+.section s13nb
+.section s13oa
+.section s13ob
+.section s13pa
+.section s13pb
+.section s13qa
+.section s13qb
+.section s13ra
+.section s13rb
+.section s13sa
+.section s13sb
+.section s13ta
+.section s13tb
+.section s13ua
+.section s13ub
+.section s13va
+.section s13vb
+.section s13wa
+.section s13wb
+.section s13xa
+.section s13xb
+.section s13ya
+.section s13yb
+.section s13za
+.section s13zb
+.section s131a
+.section s131b
+.section s132a
+.section s132b
+.section s133a
+.section s133b
+.section s134a
+.section s134b
+.section s135a
+.section s135b
+.section s136a
+.section s136b
+.section s137a
+.section s137b
+.section s138a
+.section s138b
+.section s139a
+.section s139b
+.section s130a
+.section s130b
+.section s14aa
+.section s14ab
+.section s14ba
+.section s14bb
+.section s14ca
+.section s14cb
+.section s14da
+.section s14db
+.section s14ea
+.section s14eb
+.section s14fa
+.section s14fb
+.section s14ga
+.section s14gb
+.section s14ha
+.section s14hb
+.section s14ia
+.section s14ib
+.section s14ja
+.section s14jb
+.section s14ka
+.section s14kb
+.section s14la
+.section s14lb
+.section s14ma
+.section s14mb
+.section s14na
+.section s14nb
+.section s14oa
+.section s14ob
+.section s14pa
+.section s14pb
+.section s14qa
+.section s14qb
+.section s14ra
+.section s14rb
+.section s14sa
+.section s14sb
+.section s14ta
+.section s14tb
+.section s14ua
+.section s14ub
+.section s14va
+.section s14vb
+.section s14wa
+.section s14wb
+.section s14xa
+.section s14xb
+.section s14ya
+.section s14yb
+.section s14za
+.section s14zb
+.section s141a
+.section s141b
+.section s142a
+.section s142b
+.section s143a
+.section s143b
+.section s144a
+.section s144b
+.section s145a
+.section s145b
+.section s146a
+.section s146b
+.section s147a
+.section s147b
+.section s148a
+.section s148b
+.section s149a
+.section s149b
+.section s140a
+.section s140b
+.section s15aa
+.section s15ab
+.section s15ba
+.section s15bb
+.section s15ca
+.section s15cb
+.section s15da
+.section s15db
+.section s15ea
+.section s15eb
+.section s15fa
+.section s15fb
+.section s15ga
+.section s15gb
+.section s15ha
+.section s15hb
+.section s15ia
+.section s15ib
+.section s15ja
+.section s15jb
+.section s15ka
+.section s15kb
+.section s15la
+.section s15lb
+.section s15ma
+.section s15mb
+.section s15na
+.section s15nb
+.section s15oa
+.section s15ob
+.section s15pa
+.section s15pb
+.section s15qa
+.section s15qb
+.section s15ra
+.section s15rb
+.section s15sa
+.section s15sb
+.section s15ta
+.section s15tb
+.section s15ua
+.section s15ub
+.section s15va
+.section s15vb
+.section s15wa
+.section s15wb
+.section s15xa
+.section s15xb
+.section s15ya
+.section s15yb
+.section s15za
+.section s15zb
+.section s151a
+.section s151b
+.section s152a
+.section s152b
+.section s153a
+.section s153b
+.section s154a
+.section s154b
+.section s155a
+.section s155b
+.section s156a
+.section s156b
+.section s157a
+.section s157b
+.section s158a
+.section s158b
+.section s159a
+.section s159b
+.section s150a
+.section s150b
+.section s16aa
+.section s16ab
+.section s16ba
+.section s16bb
+.section s16ca
+.section s16cb
+.section s16da
+.section s16db
+.section s16ea
+.section s16eb
+.section s16fa
+.section s16fb
+.section s16ga
+.section s16gb
+.section s16ha
+.section s16hb
+.section s16ia
+.section s16ib
+.section s16ja
+.section s16jb
+.section s16ka
+.section s16kb
+.section s16la
+.section s16lb
+.section s16ma
+.section s16mb
+.section s16na
+.section s16nb
+.section s16oa
+.section s16ob
+.section s16pa
+.section s16pb
+.section s16qa
+.section s16qb
+.section s16ra
+.section s16rb
+.section s16sa
+.section s16sb
+.section s16ta
+.section s16tb
+.section s16ua
+.section s16ub
+.section s16va
+.section s16vb
+.section s16wa
+.section s16wb
+.section s16xa
+.section s16xb
+.section s16ya
+.section s16yb
+.section s16za
+.section s16zb
+.section s161a
+.section s161b
+.section s162a
+.section s162b
+.section s163a
+.section s163b
+.section s164a
+.section s164b
+.section s165a
+.section s165b
+.section s166a
+.section s166b
+.section s167a
+.section s167b
+.section s168a
+.section s168b
+.section s169a
+.section s169b
+.section s160a
+.section s160b
+.section s17aa
+.section s17ab
+.section s17ba
+.section s17bb
+.section s17ca
+.section s17cb
+.section s17da
+.section s17db
+.section s17ea
+.section s17eb
+.section s17fa
+.section s17fb
+.section s17ga
+.section s17gb
+.section s17ha
+.section s17hb
+.section s17ia
+.section s17ib
+.section s17ja
+.section s17jb
+.section s17ka
+.section s17kb
+.section s17la
+.section s17lb
+.section s17ma
+.section s17mb
+.section s17na
+.section s17nb
+.section s17oa
+.section s17ob
+.section s17pa
+.section s17pb
+.section s17qa
+.section s17qb
+.section s17ra
+.section s17rb
+.section s17sa
+.section s17sb
+.section s17ta
+.section s17tb
+.section s17ua
+.section s17ub
+.section s17va
+.section s17vb
+.section s17wa
+.section s17wb
+.section s17xa
+.section s17xb
+.section s17ya
+.section s17yb
+.section s17za
+.section s17zb
+.section s171a
+.section s171b
+.section s172a
+.section s172b
+.section s173a
+.section s173b
+.section s174a
+.section s174b
+.section s175a
+.section s175b
+.section s176a
+.section s176b
+.section s177a
+.section s177b
+.section s178a
+.section s178b
+.section s179a
+.section s179b
+.section s170a
+.section s170b
+.section s18aa
+.section s18ab
+.section s18ba
+.section s18bb
+.section s18ca
+.section s18cb
+.section s18da
+.section s18db
+.section s18ea
+.section s18eb
+.section s18fa
+.section s18fb
+.section s18ga
+.section s18gb
+.section s18ha
+.section s18hb
+.section s18ia
+.section s18ib
+.section s18ja
+.section s18jb
+.section s18ka
+.section s18kb
+.section s18la
+.section s18lb
+.section s18ma
+.section s18mb
+.section s18na
+.section s18nb
+.section s18oa
+.section s18ob
+.section s18pa
+.section s18pb
+.section s18qa
+.section s18qb
+.section s18ra
+.section s18rb
+.section s18sa
+.section s18sb
+.section s18ta
+.section s18tb
+.section s18ua
+.section s18ub
+.section s18va
+.section s18vb
+.section s18wa
+.section s18wb
+.section s18xa
+.section s18xb
+.section s18ya
+.section s18yb
+.section s18za
+.section s18zb
+.section s181a
+.section s181b
+.section s182a
+.section s182b
+.section s183a
+.section s183b
+.section s184a
+.section s184b
+.section s185a
+.section s185b
+.section s186a
+.section s186b
+.section s187a
+.section s187b
+.section s188a
+.section s188b
+.section s189a
+.section s189b
+.section s180a
+.section s180b
+.section s19aa
+.section s19ab
+.section s19ba
+.section s19bb
+.section s19ca
+.section s19cb
+.section s19da
+.section s19db
+.section s19ea
+.section s19eb
+.section s19fa
+.section s19fb
+.section s19ga
+.section s19gb
+.section s19ha
+.section s19hb
+.section s19ia
+.section s19ib
+.section s19ja
+.section s19jb
+.section s19ka
+.section s19kb
+.section s19la
+.section s19lb
+.section s19ma
+.section s19mb
+.section s19na
+.section s19nb
+.section s19oa
+.section s19ob
+.section s19pa
+.section s19pb
+.section s19qa
+.section s19qb
+.section s19ra
+.section s19rb
+.section s19sa
+.section s19sb
+.section s19ta
+.section s19tb
+.section s19ua
+.section s19ub
+.section s19va
+.section s19vb
+.section s19wa
+.section s19wb
+.section s19xa
+.section s19xb
+.section s19ya
+.section s19yb
+.section s19za
+.section s19zb
+.section s191a
+.section s191b
+.section s192a
+.section s192b
+.section s193a
+.section s193b
+.section s194a
+.section s194b
+.section s195a
+.section s195b
+.section s196a
+.section s196b
+.section s197a
+.section s197b
+.section s198a
+.section s198b
+.section s199a
+.section s199b
+.section s190a
+.section s190b
+.section s10aa
+.section s10ab
+.section s10ba
+.section s10bb
+.section s10ca
+.section s10cb
+.section s10da
+.section s10db
+.section s10ea
+.section s10eb
+.section s10fa
+.section s10fb
+.section s10ga
+.section s10gb
+.section s10ha
+.section s10hb
+.section s10ia
+.section s10ib
+.section s10ja
+.section s10jb
+.section s10ka
+.section s10kb
+.section s10la
+.section s10lb
+.section s10ma
+.section s10mb
+.section s10na
+.section s10nb
+.section s10oa
+.section s10ob
+.section s10pa
+.section s10pb
+.section s10qa
+.section s10qb
+.section s10ra
+.section s10rb
+.section s10sa
+.section s10sb
+.section s10ta
+.section s10tb
+.section s10ua
+.section s10ub
+.section s10va
+.section s10vb
+.section s10wa
+.section s10wb
+.section s10xa
+.section s10xb
+.section s10ya
+.section s10yb
+.section s10za
+.section s10zb
+.section s101a
+.section s101b
+.section s102a
+.section s102b
+.section s103a
+.section s103b
+.section s104a
+.section s104b
+.section s105a
+.section s105b
+.section s106a
+.section s106b
+.section s107a
+.section s107b
+.section s108a
+.section s108b
+.section s109a
+.section s109b
+.section s100a
+.section s100b
+.section s2aaa
+.section s2aab
+.section s2aba
+.section s2abb
+.section s2aca
+.section s2acb
+.section s2ada
+.section s2adb
+.section s2aea
+.section s2aeb
+.section s2afa
+.section s2afb
+.section s2aga
+.section s2agb
+.section s2aha
+.section s2ahb
+.section s2aia
+.section s2aib
+.section s2aja
+.section s2ajb
+.section s2aka
+.section s2akb
+.section s2ala
+.section s2alb
+.section s2ama
+.section s2amb
+.section s2ana
+.section s2anb
+.section s2aoa
+.section s2aob
+.section s2apa
+.section s2apb
+.section s2aqa
+.section s2aqb
+.section s2ara
+.section s2arb
+.section s2asa
+.section s2asb
+.section s2ata
+.section s2atb
+.section s2aua
+.section s2aub
+.section s2ava
+.section s2avb
+.section s2awa
+.section s2awb
+.section s2axa
+.section s2axb
+.section s2aya
+.section s2ayb
+.section s2aza
+.section s2azb
+.section s2a1a
+.section s2a1b
+.section s2a2a
+.section s2a2b
+.section s2a3a
+.section s2a3b
+.section s2a4a
+.section s2a4b
+.section s2a5a
+.section s2a5b
+.section s2a6a
+.section s2a6b
+.section s2a7a
+.section s2a7b
+.section s2a8a
+.section s2a8b
+.section s2a9a
+.section s2a9b
+.section s2a0a
+.section s2a0b
+.section s2baa
+.section s2bab
+.section s2bba
+.section s2bbb
+.section s2bca
+.section s2bcb
+.section s2bda
+.section s2bdb
+.section s2bea
+.section s2beb
+.section s2bfa
+.section s2bfb
+.section s2bga
+.section s2bgb
+.section s2bha
+.section s2bhb
+.section s2bia
+.section s2bib
+.section s2bja
+.section s2bjb
+.section s2bka
+.section s2bkb
+.section s2bla
+.section s2blb
+.section s2bma
+.section s2bmb
+.section s2bna
+.section s2bnb
+.section s2boa
+.section s2bob
+.section s2bpa
+.section s2bpb
+.section s2bqa
+.section s2bqb
+.section s2bra
+.section s2brb
+.section s2bsa
+.section s2bsb
+.section s2bta
+.section s2btb
+.section s2bua
+.section s2bub
+.section s2bva
+.section s2bvb
+.section s2bwa
+.section s2bwb
+.section s2bxa
+.section s2bxb
+.section s2bya
+.section s2byb
+.section s2bza
+.section s2bzb
+.section s2b1a
+.section s2b1b
+.section s2b2a
+.section s2b2b
+.section s2b3a
+.section s2b3b
+.section s2b4a
+.section s2b4b
+.section s2b5a
+.section s2b5b
+.section s2b6a
+.section s2b6b
+.section s2b7a
+.section s2b7b
+.section s2b8a
+.section s2b8b
+.section s2b9a
+.section s2b9b
+.section s2b0a
+.section s2b0b
+.section s2caa
+.section s2cab
+.section s2cba
+.section s2cbb
+.section s2cca
+.section s2ccb
+.section s2cda
+.section s2cdb
+.section s2cea
+.section s2ceb
+.section s2cfa
+.section s2cfb
+.section s2cga
+.section s2cgb
+.section s2cha
+.section s2chb
+.section s2cia
+.section s2cib
+.section s2cja
+.section s2cjb
+.section s2cka
+.section s2ckb
+.section s2cla
+.section s2clb
+.section s2cma
+.section s2cmb
+.section s2cna
+.section s2cnb
+.section s2coa
+.section s2cob
+.section s2cpa
+.section s2cpb
+.section s2cqa
+.section s2cqb
+.section s2cra
+.section s2crb
+.section s2csa
+.section s2csb
+.section s2cta
+.section s2ctb
+.section s2cua
+.section s2cub
+.section s2cva
+.section s2cvb
+.section s2cwa
+.section s2cwb
+.section s2cxa
+.section s2cxb
+.section s2cya
+.section s2cyb
+.section s2cza
+.section s2czb
+.section s2c1a
+.section s2c1b
+.section s2c2a
+.section s2c2b
+.section s2c3a
+.section s2c3b
+.section s2c4a
+.section s2c4b
+.section s2c5a
+.section s2c5b
+.section s2c6a
+.section s2c6b
+.section s2c7a
+.section s2c7b
+.section s2c8a
+.section s2c8b
+.section s2c9a
+.section s2c9b
+.section s2c0a
+.section s2c0b
+.section s2daa
+.section s2dab
+.section s2dba
+.section s2dbb
+.section s2dca
+.section s2dcb
+.section s2dda
+.section s2ddb
+.section s2dea
+.section s2deb
+.section s2dfa
+.section s2dfb
+.section s2dga
+.section s2dgb
+.section s2dha
+.section s2dhb
+.section s2dia
+.section s2dib
+.section s2dja
+.section s2djb
+.section s2dka
+.section s2dkb
+.section s2dla
+.section s2dlb
+.section s2dma
+.section s2dmb
+.section s2dna
+.section s2dnb
+.section s2doa
+.section s2dob
+.section s2dpa
+.section s2dpb
+.section s2dqa
+.section s2dqb
+.section s2dra
+.section s2drb
+.section s2dsa
+.section s2dsb
+.section s2dta
+.section s2dtb
+.section s2dua
+.section s2dub
+.section s2dva
+.section s2dvb
+.section s2dwa
+.section s2dwb
+.section s2dxa
+.section s2dxb
+.section s2dya
+.section s2dyb
+.section s2dza
+.section s2dzb
+.section s2d1a
+.section s2d1b
+.section s2d2a
+.section s2d2b
+.section s2d3a
+.section s2d3b
+.section s2d4a
+.section s2d4b
+.section s2d5a
+.section s2d5b
+.section s2d6a
+.section s2d6b
+.section s2d7a
+.section s2d7b
+.section s2d8a
+.section s2d8b
+.section s2d9a
+.section s2d9b
+.section s2d0a
+.section s2d0b
+.section s2eaa
+.section s2eab
+.section s2eba
+.section s2ebb
+.section s2eca
+.section s2ecb
+.section s2eda
+.section s2edb
+.section s2eea
+.section s2eeb
+.section s2efa
+.section s2efb
+.section s2ega
+.section s2egb
+.section s2eha
+.section s2ehb
+.section s2eia
+.section s2eib
+.section s2eja
+.section s2ejb
+.section s2eka
+.section s2ekb
+.section s2ela
+.section s2elb
+.section s2ema
+.section s2emb
+.section s2ena
+.section s2enb
+.section s2eoa
+.section s2eob
+.section s2epa
+.section s2epb
+.section s2eqa
+.section s2eqb
+.section s2era
+.section s2erb
+.section s2esa
+.section s2esb
+.section s2eta
+.section s2etb
+.section s2eua
+.section s2eub
+.section s2eva
+.section s2evb
+.section s2ewa
+.section s2ewb
+.section s2exa
+.section s2exb
+.section s2eya
+.section s2eyb
+.section s2eza
+.section s2ezb
+.section s2e1a
+.section s2e1b
+.section s2e2a
+.section s2e2b
+.section s2e3a
+.section s2e3b
+.section s2e4a
+.section s2e4b
+.section s2e5a
+.section s2e5b
+.section s2e6a
+.section s2e6b
+.section s2e7a
+.section s2e7b
+.section s2e8a
+.section s2e8b
+.section s2e9a
+.section s2e9b
+.section s2e0a
+.section s2e0b
+.section s2faa
+.section s2fab
+.section s2fba
+.section s2fbb
+.section s2fca
+.section s2fcb
+.section s2fda
+.section s2fdb
+.section s2fea
+.section s2feb
+.section s2ffa
+.section s2ffb
+.section s2fga
+.section s2fgb
+.section s2fha
+.section s2fhb
+.section s2fia
+.section s2fib
+.section s2fja
+.section s2fjb
+.section s2fka
+.section s2fkb
+.section s2fla
+.section s2flb
+.section s2fma
+.section s2fmb
+.section s2fna
+.section s2fnb
+.section s2foa
+.section s2fob
+.section s2fpa
+.section s2fpb
+.section s2fqa
+.section s2fqb
+.section s2fra
+.section s2frb
+.section s2fsa
+.section s2fsb
+.section s2fta
+.section s2ftb
+.section s2fua
+.section s2fub
+.section s2fva
+.section s2fvb
+.section s2fwa
+.section s2fwb
+.section s2fxa
+.section s2fxb
+.section s2fya
+.section s2fyb
+.section s2fza
+.section s2fzb
+.section s2f1a
+.section s2f1b
+.section s2f2a
+.section s2f2b
+.section s2f3a
+.section s2f3b
+.section s2f4a
+.section s2f4b
+.section s2f5a
+.section s2f5b
+.section s2f6a
+.section s2f6b
+.section s2f7a
+.section s2f7b
+.section s2f8a
+.section s2f8b
+.section s2f9a
+.section s2f9b
+.section s2f0a
+.section s2f0b
+.section s2gaa
+.section s2gab
+.section s2gba
+.section s2gbb
+.section s2gca
+.section s2gcb
+.section s2gda
+.section s2gdb
+.section s2gea
+.section s2geb
+.section s2gfa
+.section s2gfb
+.section s2gga
+.section s2ggb
+.section s2gha
+.section s2ghb
+.section s2gia
+.section s2gib
+.section s2gja
+.section s2gjb
+.section s2gka
+.section s2gkb
+.section s2gla
+.section s2glb
+.section s2gma
+.section s2gmb
+.section s2gna
+.section s2gnb
+.section s2goa
+.section s2gob
+.section s2gpa
+.section s2gpb
+.section s2gqa
+.section s2gqb
+.section s2gra
+.section s2grb
+.section s2gsa
+.section s2gsb
+.section s2gta
+.section s2gtb
+.section s2gua
+.section s2gub
+.section s2gva
+.section s2gvb
+.section s2gwa
+.section s2gwb
+.section s2gxa
+.section s2gxb
+.section s2gya
+.section s2gyb
+.section s2gza
+.section s2gzb
+.section s2g1a
+.section s2g1b
+.section s2g2a
+.section s2g2b
+.section s2g3a
+.section s2g3b
+.section s2g4a
+.section s2g4b
+.section s2g5a
+.section s2g5b
+.section s2g6a
+.section s2g6b
+.section s2g7a
+.section s2g7b
+.section s2g8a
+.section s2g8b
+.section s2g9a
+.section s2g9b
+.section s2g0a
+.section s2g0b
+.section s2haa
+.section s2hab
+.section s2hba
+.section s2hbb
+.section s2hca
+.section s2hcb
+.section s2hda
+.section s2hdb
+.section s2hea
+.section s2heb
+.section s2hfa
+.section s2hfb
+.section s2hga
+.section s2hgb
+.section s2hha
+.section s2hhb
+.section s2hia
+.section s2hib
+.section s2hja
+.section s2hjb
+.section s2hka
+.section s2hkb
+.section s2hla
+.section s2hlb
+.section s2hma
+.section s2hmb
+.section s2hna
+.section s2hnb
+.section s2hoa
+.section s2hob
+.section s2hpa
+.section s2hpb
+.section s2hqa
+.section s2hqb
+.section s2hra
+.section s2hrb
+.section s2hsa
+.section s2hsb
+.section s2hta
+.section s2htb
+.section s2hua
+.section s2hub
+.section s2hva
+.section s2hvb
+.section s2hwa
+.section s2hwb
+.section s2hxa
+.section s2hxb
+.section s2hya
+.section s2hyb
+.section s2hza
+.section s2hzb
+.section s2h1a
+.section s2h1b
+.section s2h2a
+.section s2h2b
+.section s2h3a
+.section s2h3b
+.section s2h4a
+.section s2h4b
+.section s2h5a
+.section s2h5b
+.section s2h6a
+.section s2h6b
+.section s2h7a
+.section s2h7b
+.section s2h8a
+.section s2h8b
+.section s2h9a
+.section s2h9b
+.section s2h0a
+.section s2h0b
+.section s2iaa
+.section s2iab
+.section s2iba
+.section s2ibb
+.section s2ica
+.section s2icb
+.section s2ida
+.section s2idb
+.section s2iea
+.section s2ieb
+.section s2ifa
+.section s2ifb
+.section s2iga
+.section s2igb
+.section s2iha
+.section s2ihb
+.section s2iia
+.section s2iib
+.section s2ija
+.section s2ijb
+.section s2ika
+.section s2ikb
+.section s2ila
+.section s2ilb
+.section s2ima
+.section s2imb
+.section s2ina
+.section s2inb
+.section s2ioa
+.section s2iob
+.section s2ipa
+.section s2ipb
+.section s2iqa
+.section s2iqb
+.section s2ira
+.section s2irb
+.section s2isa
+.section s2isb
+.section s2ita
+.section s2itb
+.section s2iua
+.section s2iub
+.section s2iva
+.section s2ivb
+.section s2iwa
+.section s2iwb
+.section s2ixa
+.section s2ixb
+.section s2iya
+.section s2iyb
+.section s2iza
+.section s2izb
+.section s2i1a
+.section s2i1b
+.section s2i2a
+.section s2i2b
+.section s2i3a
+.section s2i3b
+.section s2i4a
+.section s2i4b
+.section s2i5a
+.section s2i5b
+.section s2i6a
+.section s2i6b
+.section s2i7a
+.section s2i7b
+.section s2i8a
+.section s2i8b
+.section s2i9a
+.section s2i9b
+.section s2i0a
+.section s2i0b
+.section s2jaa
+.section s2jab
+.section s2jba
+.section s2jbb
+.section s2jca
+.section s2jcb
+.section s2jda
+.section s2jdb
+.section s2jea
+.section s2jeb
+.section s2jfa
+.section s2jfb
+.section s2jga
+.section s2jgb
+.section s2jha
+.section s2jhb
+.section s2jia
+.section s2jib
+.section s2jja
+.section s2jjb
+.section s2jka
+.section s2jkb
+.section s2jla
+.section s2jlb
+.section s2jma
+.section s2jmb
+.section s2jna
+.section s2jnb
+.section s2joa
+.section s2job
+.section s2jpa
+.section s2jpb
+.section s2jqa
+.section s2jqb
+.section s2jra
+.section s2jrb
+.section s2jsa
+.section s2jsb
+.section s2jta
+.section s2jtb
+.section s2jua
+.section s2jub
+.section s2jva
+.section s2jvb
+.section s2jwa
+.section s2jwb
+.section s2jxa
+.section s2jxb
+.section s2jya
+.section s2jyb
+.section s2jza
+.section s2jzb
+.section s2j1a
+.section s2j1b
+.section s2j2a
+.section s2j2b
+.section s2j3a
+.section s2j3b
+.section s2j4a
+.section s2j4b
+.section s2j5a
+.section s2j5b
+.section s2j6a
+.section s2j6b
+.section s2j7a
+.section s2j7b
+.section s2j8a
+.section s2j8b
+.section s2j9a
+.section s2j9b
+.section s2j0a
+.section s2j0b
+.section s2kaa
+.section s2kab
+.section s2kba
+.section s2kbb
+.section s2kca
+.section s2kcb
+.section s2kda
+.section s2kdb
+.section s2kea
+.section s2keb
+.section s2kfa
+.section s2kfb
+.section s2kga
+.section s2kgb
+.section s2kha
+.section s2khb
+.section s2kia
+.section s2kib
+.section s2kja
+.section s2kjb
+.section s2kka
+.section s2kkb
+.section s2kla
+.section s2klb
+.section s2kma
+.section s2kmb
+.section s2kna
+.section s2knb
+.section s2koa
+.section s2kob
+.section s2kpa
+.section s2kpb
+.section s2kqa
+.section s2kqb
+.section s2kra
+.section s2krb
+.section s2ksa
+.section s2ksb
+.section s2kta
+.section s2ktb
+.section s2kua
+.section s2kub
+.section s2kva
+.section s2kvb
+.section s2kwa
+.section s2kwb
+.section s2kxa
+.section s2kxb
+.section s2kya
+.section s2kyb
+.section s2kza
+.section s2kzb
+.section s2k1a
+.section s2k1b
+.section s2k2a
+.section s2k2b
+.section s2k3a
+.section s2k3b
+.section s2k4a
+.section s2k4b
+.section s2k5a
+.section s2k5b
+.section s2k6a
+.section s2k6b
+.section s2k7a
+.section s2k7b
+.section s2k8a
+.section s2k8b
+.section s2k9a
+.section s2k9b
+.section s2k0a
+.section s2k0b
+.section s2laa
+.section s2lab
+.section s2lba
+.section s2lbb
+.section s2lca
+.section s2lcb
+.section s2lda
+.section s2ldb
+.section s2lea
+.section s2leb
+.section s2lfa
+.section s2lfb
+.section s2lga
+.section s2lgb
+.section s2lha
+.section s2lhb
+.section s2lia
+.section s2lib
+.section s2lja
+.section s2ljb
+.section s2lka
+.section s2lkb
+.section s2lla
+.section s2llb
+.section s2lma
+.section s2lmb
+.section s2lna
+.section s2lnb
+.section s2loa
+.section s2lob
+.section s2lpa
+.section s2lpb
+.section s2lqa
+.section s2lqb
+.section s2lra
+.section s2lrb
+.section s2lsa
+.section s2lsb
+.section s2lta
+.section s2ltb
+.section s2lua
+.section s2lub
+.section s2lva
+.section s2lvb
+.section s2lwa
+.section s2lwb
+.section s2lxa
+.section s2lxb
+.section s2lya
+.section s2lyb
+.section s2lza
+.section s2lzb
+.section s2l1a
+.section s2l1b
+.section s2l2a
+.section s2l2b
+.section s2l3a
+.section s2l3b
+.section s2l4a
+.section s2l4b
+.section s2l5a
+.section s2l5b
+.section s2l6a
+.section s2l6b
+.section s2l7a
+.section s2l7b
+.section s2l8a
+.section s2l8b
+.section s2l9a
+.section s2l9b
+.section s2l0a
+.section s2l0b
+.section s2maa
+.section s2mab
+.section s2mba
+.section s2mbb
+.section s2mca
+.section s2mcb
+.section s2mda
+.section s2mdb
+.section s2mea
+.section s2meb
+.section s2mfa
+.section s2mfb
+.section s2mga
+.section s2mgb
+.section s2mha
+.section s2mhb
+.section s2mia
+.section s2mib
+.section s2mja
+.section s2mjb
+.section s2mka
+.section s2mkb
+.section s2mla
+.section s2mlb
+.section s2mma
+.section s2mmb
+.section s2mna
+.section s2mnb
+.section s2moa
+.section s2mob
+.section s2mpa
+.section s2mpb
+.section s2mqa
+.section s2mqb
+.section s2mra
+.section s2mrb
+.section s2msa
+.section s2msb
+.section s2mta
+.section s2mtb
+.section s2mua
+.section s2mub
+.section s2mva
+.section s2mvb
+.section s2mwa
+.section s2mwb
+.section s2mxa
+.section s2mxb
+.section s2mya
+.section s2myb
+.section s2mza
+.section s2mzb
+.section s2m1a
+.section s2m1b
+.section s2m2a
+.section s2m2b
+.section s2m3a
+.section s2m3b
+.section s2m4a
+.section s2m4b
+.section s2m5a
+.section s2m5b
+.section s2m6a
+.section s2m6b
+.section s2m7a
+.section s2m7b
+.section s2m8a
+.section s2m8b
+.section s2m9a
+.section s2m9b
+.section s2m0a
+.section s2m0b
+.section s2naa
+.section s2nab
+.section s2nba
+.section s2nbb
+.section s2nca
+.section s2ncb
+.section s2nda
+.section s2ndb
+.section s2nea
+.section s2neb
+.section s2nfa
+.section s2nfb
+.section s2nga
+.section s2ngb
+.section s2nha
+.section s2nhb
+.section s2nia
+.section s2nib
+.section s2nja
+.section s2njb
+.section s2nka
+.section s2nkb
+.section s2nla
+.section s2nlb
+.section s2nma
+.section s2nmb
+.section s2nna
+.section s2nnb
+.section s2noa
+.section s2nob
+.section s2npa
+.section s2npb
+.section s2nqa
+.section s2nqb
+.section s2nra
+.section s2nrb
+.section s2nsa
+.section s2nsb
+.section s2nta
+.section s2ntb
+.section s2nua
+.section s2nub
+.section s2nva
+.section s2nvb
+.section s2nwa
+.section s2nwb
+.section s2nxa
+.section s2nxb
+.section s2nya
+.section s2nyb
+.section s2nza
+.section s2nzb
+.section s2n1a
+.section s2n1b
+.section s2n2a
+.section s2n2b
+.section s2n3a
+.section s2n3b
+.section s2n4a
+.section s2n4b
+.section s2n5a
+.section s2n5b
+.section s2n6a
+.section s2n6b
+.section s2n7a
+.section s2n7b
+.section s2n8a
+.section s2n8b
+.section s2n9a
+.section s2n9b
+.section s2n0a
+.section s2n0b
+.section s2oaa
+.section s2oab
+.section s2oba
+.section s2obb
+.section s2oca
+.section s2ocb
+.section s2oda
+.section s2odb
+.section s2oea
+.section s2oeb
+.section s2ofa
+.section s2ofb
+.section s2oga
+.section s2ogb
+.section s2oha
+.section s2ohb
+.section s2oia
+.section s2oib
+.section s2oja
+.section s2ojb
+.section s2oka
+.section s2okb
+.section s2ola
+.section s2olb
+.section s2oma
+.section s2omb
+.section s2ona
+.section s2onb
+.section s2ooa
+.section s2oob
+.section s2opa
+.section s2opb
+.section s2oqa
+.section s2oqb
+.section s2ora
+.section s2orb
+.section s2osa
+.section s2osb
+.section s2ota
+.section s2otb
+.section s2oua
+.section s2oub
+.section s2ova
+.section s2ovb
+.section s2owa
+.section s2owb
+.section s2oxa
+.section s2oxb
+.section s2oya
+.section s2oyb
+.section s2oza
+.section s2ozb
+.section s2o1a
+.section s2o1b
+.section s2o2a
+.section s2o2b
+.section s2o3a
+.section s2o3b
+.section s2o4a
+.section s2o4b
+.section s2o5a
+.section s2o5b
+.section s2o6a
+.section s2o6b
+.section s2o7a
+.section s2o7b
+.section s2o8a
+.section s2o8b
+.section s2o9a
+.section s2o9b
+.section s2o0a
+.section s2o0b
+.section s2paa
+.section s2pab
+.section s2pba
+.section s2pbb
+.section s2pca
+.section s2pcb
+.section s2pda
+.section s2pdb
+.section s2pea
+.section s2peb
+.section s2pfa
+.section s2pfb
+.section s2pga
+.section s2pgb
+.section s2pha
+.section s2phb
+.section s2pia
+.section s2pib
+.section s2pja
+.section s2pjb
+.section s2pka
+.section s2pkb
+.section s2pla
+.section s2plb
+.section s2pma
+.section s2pmb
+.section s2pna
+.section s2pnb
+.section s2poa
+.section s2pob
+.section s2ppa
+.section s2ppb
+.section s2pqa
+.section s2pqb
+.section s2pra
+.section s2prb
+.section s2psa
+.section s2psb
+.section s2pta
+.section s2ptb
+.section s2pua
+.section s2pub
+.section s2pva
+.section s2pvb
+.section s2pwa
+.section s2pwb
+.section s2pxa
+.section s2pxb
+.section s2pya
+.section s2pyb
+.section s2pza
+.section s2pzb
+.section s2p1a
+.section s2p1b
+.section s2p2a
+.section s2p2b
+.section s2p3a
+.section s2p3b
+.section s2p4a
+.section s2p4b
+.section s2p5a
+.section s2p5b
+.section s2p6a
+.section s2p6b
+.section s2p7a
+.section s2p7b
+.section s2p8a
+.section s2p8b
+.section s2p9a
+.section s2p9b
+.section s2p0a
+.section s2p0b
+.section s2qaa
+.section s2qab
+.section s2qba
+.section s2qbb
+.section s2qca
+.section s2qcb
+.section s2qda
+.section s2qdb
+.section s2qea
+.section s2qeb
+.section s2qfa
+.section s2qfb
+.section s2qga
+.section s2qgb
+.section s2qha
+.section s2qhb
+.section s2qia
+.section s2qib
+.section s2qja
+.section s2qjb
+.section s2qka
+.section s2qkb
+.section s2qla
+.section s2qlb
+.section s2qma
+.section s2qmb
+.section s2qna
+.section s2qnb
+.section s2qoa
+.section s2qob
+.section s2qpa
+.section s2qpb
+.section s2qqa
+.section s2qqb
+.section s2qra
+.section s2qrb
+.section s2qsa
+.section s2qsb
+.section s2qta
+.section s2qtb
+.section s2qua
+.section s2qub
+.section s2qva
+.section s2qvb
+.section s2qwa
+.section s2qwb
+.section s2qxa
+.section s2qxb
+.section s2qya
+.section s2qyb
+.section s2qza
+.section s2qzb
+.section s2q1a
+.section s2q1b
+.section s2q2a
+.section s2q2b
+.section s2q3a
+.section s2q3b
+.section s2q4a
+.section s2q4b
+.section s2q5a
+.section s2q5b
+.section s2q6a
+.section s2q6b
+.section s2q7a
+.section s2q7b
+.section s2q8a
+.section s2q8b
+.section s2q9a
+.section s2q9b
+.section s2q0a
+.section s2q0b
+.section s2raa
+.section s2rab
+.section s2rba
+.section s2rbb
+.section s2rca
+.section s2rcb
+.section s2rda
+.section s2rdb
+.section s2rea
+.section s2reb
+.section s2rfa
+.section s2rfb
+.section s2rga
+.section s2rgb
+.section s2rha
+.section s2rhb
+.section s2ria
+.section s2rib
+.section s2rja
+.section s2rjb
+.section s2rka
+.section s2rkb
+.section s2rla
+.section s2rlb
+.section s2rma
+.section s2rmb
+.section s2rna
+.section s2rnb
+.section s2roa
+.section s2rob
+.section s2rpa
+.section s2rpb
+.section s2rqa
+.section s2rqb
+.section s2rra
+.section s2rrb
+.section s2rsa
+.section s2rsb
+.section s2rta
+.section s2rtb
+.section s2rua
+.section s2rub
+.section s2rva
+.section s2rvb
+.section s2rwa
+.section s2rwb
+.section s2rxa
+.section s2rxb
+.section s2rya
+.section s2ryb
+.section s2rza
+.section s2rzb
+.section s2r1a
+.section s2r1b
+.section s2r2a
+.section s2r2b
+.section s2r3a
+.section s2r3b
+.section s2r4a
+.section s2r4b
+.section s2r5a
+.section s2r5b
+.section s2r6a
+.section s2r6b
+.section s2r7a
+.section s2r7b
+.section s2r8a
+.section s2r8b
+.section s2r9a
+.section s2r9b
+.section s2r0a
+.section s2r0b
+.section s2saa
+.section s2sab
+.section s2sba
+.section s2sbb
+.section s2sca
+.section s2scb
+.section s2sda
+.section s2sdb
+.section s2sea
+.section s2seb
+.section s2sfa
+.section s2sfb
+.section s2sga
+.section s2sgb
+.section s2sha
+.section s2shb
+.section s2sia
+.section s2sib
+.section s2sja
+.section s2sjb
+.section s2ska
+.section s2skb
+.section s2sla
+.section s2slb
+.section s2sma
+.section s2smb
+.section s2sna
+.section s2snb
+.section s2soa
+.section s2sob
+.section s2spa
+.section s2spb
+.section s2sqa
+.section s2sqb
+.section s2sra
+.section s2srb
+.section s2ssa
+.section s2ssb
+.section s2sta
+.section s2stb
+.section s2sua
+.section s2sub
+.section s2sva
+.section s2svb
+.section s2swa
+.section s2swb
+.section s2sxa
+.section s2sxb
+.section s2sya
+.section s2syb
+.section s2sza
+.section s2szb
+.section s2s1a
+.section s2s1b
+.section s2s2a
+.section s2s2b
+.section s2s3a
+.section s2s3b
+.section s2s4a
+.section s2s4b
+.section s2s5a
+.section s2s5b
+.section s2s6a
+.section s2s6b
+.section s2s7a
+.section s2s7b
+.section s2s8a
+.section s2s8b
+.section s2s9a
+.section s2s9b
+.section s2s0a
+.section s2s0b
+.section s2taa
+.section s2tab
+.section s2tba
+.section s2tbb
+.section s2tca
+.section s2tcb
+.section s2tda
+.section s2tdb
+.section s2tea
+.section s2teb
+.section s2tfa
+.section s2tfb
+.section s2tga
+.section s2tgb
+.section s2tha
+.section s2thb
+.section s2tia
+.section s2tib
+.section s2tja
+.section s2tjb
+.section s2tka
+.section s2tkb
+.section s2tla
+.section s2tlb
+.section s2tma
+.section s2tmb
+.section s2tna
+.section s2tnb
+.section s2toa
+.section s2tob
+.section s2tpa
+.section s2tpb
+.section s2tqa
+.section s2tqb
+.section s2tra
+.section s2trb
+.section s2tsa
+.section s2tsb
+.section s2tta
+.section s2ttb
+.section s2tua
+.section s2tub
+.section s2tva
+.section s2tvb
+.section s2twa
+.section s2twb
+.section s2txa
+.section s2txb
+.section s2tya
+.section s2tyb
+.section s2tza
+.section s2tzb
+.section s2t1a
+.section s2t1b
+.section s2t2a
+.section s2t2b
+.section s2t3a
+.section s2t3b
+.section s2t4a
+.section s2t4b
+.section s2t5a
+.section s2t5b
+.section s2t6a
+.section s2t6b
+.section s2t7a
+.section s2t7b
+.section s2t8a
+.section s2t8b
+.section s2t9a
+.section s2t9b
+.section s2t0a
+.section s2t0b
+.section s2uaa
+.section s2uab
+.section s2uba
+.section s2ubb
+.section s2uca
+.section s2ucb
+.section s2uda
+.section s2udb
+.section s2uea
+.section s2ueb
+.section s2ufa
+.section s2ufb
+.section s2uga
+.section s2ugb
+.section s2uha
+.section s2uhb
+.section s2uia
+.section s2uib
+.section s2uja
+.section s2ujb
+.section s2uka
+.section s2ukb
+.section s2ula
+.section s2ulb
+.section s2uma
+.section s2umb
+.section s2una
+.section s2unb
+.section s2uoa
+.section s2uob
+.section s2upa
+.section s2upb
+.section s2uqa
+.section s2uqb
+.section s2ura
+.section s2urb
+.section s2usa
+.section s2usb
+.section s2uta
+.section s2utb
+.section s2uua
+.section s2uub
+.section s2uva
+.section s2uvb
+.section s2uwa
+.section s2uwb
+.section s2uxa
+.section s2uxb
+.section s2uya
+.section s2uyb
+.section s2uza
+.section s2uzb
+.section s2u1a
+.section s2u1b
+.section s2u2a
+.section s2u2b
+.section s2u3a
+.section s2u3b
+.section s2u4a
+.section s2u4b
+.section s2u5a
+.section s2u5b
+.section s2u6a
+.section s2u6b
+.section s2u7a
+.section s2u7b
+.section s2u8a
+.section s2u8b
+.section s2u9a
+.section s2u9b
+.section s2u0a
+.section s2u0b
+.section s2vaa
+.section s2vab
+.section s2vba
+.section s2vbb
+.section s2vca
+.section s2vcb
+.section s2vda
+.section s2vdb
+.section s2vea
+.section s2veb
+.section s2vfa
+.section s2vfb
+.section s2vga
+.section s2vgb
+.section s2vha
+.section s2vhb
+.section s2via
+.section s2vib
+.section s2vja
+.section s2vjb
+.section s2vka
+.section s2vkb
+.section s2vla
+.section s2vlb
+.section s2vma
+.section s2vmb
+.section s2vna
+.section s2vnb
+.section s2voa
+.section s2vob
+.section s2vpa
+.section s2vpb
+.section s2vqa
+.section s2vqb
+.section s2vra
+.section s2vrb
+.section s2vsa
+.section s2vsb
+.section s2vta
+.section s2vtb
+.section s2vua
+.section s2vub
+.section s2vva
+.section s2vvb
+.section s2vwa
+.section s2vwb
+.section s2vxa
+.section s2vxb
+.section s2vya
+.section s2vyb
+.section s2vza
+.section s2vzb
+.section s2v1a
+.section s2v1b
+.section s2v2a
+.section s2v2b
+.section s2v3a
+.section s2v3b
+.section s2v4a
+.section s2v4b
+.section s2v5a
+.section s2v5b
+.section s2v6a
+.section s2v6b
+.section s2v7a
+.section s2v7b
+.section s2v8a
+.section s2v8b
+.section s2v9a
+.section s2v9b
+.section s2v0a
+.section s2v0b
+.section s2waa
+.section s2wab
+.section s2wba
+.section s2wbb
+.section s2wca
+.section s2wcb
+.section s2wda
+.section s2wdb
+.section s2wea
+.section s2web
+.section s2wfa
+.section s2wfb
+.section s2wga
+.section s2wgb
+.section s2wha
+.section s2whb
+.section s2wia
+.section s2wib
+.section s2wja
+.section s2wjb
+.section s2wka
+.section s2wkb
+.section s2wla
+.section s2wlb
+.section s2wma
+.section s2wmb
+.section s2wna
+.section s2wnb
+.section s2woa
+.section s2wob
+.section s2wpa
+.section s2wpb
+.section s2wqa
+.section s2wqb
+.section s2wra
+.section s2wrb
+.section s2wsa
+.section s2wsb
+.section s2wta
+.section s2wtb
+.section s2wua
+.section s2wub
+.section s2wva
+.section s2wvb
+.section s2wwa
+.section s2wwb
+.section s2wxa
+.section s2wxb
+.section s2wya
+.section s2wyb
+.section s2wza
+.section s2wzb
+.section s2w1a
+.section s2w1b
+.section s2w2a
+.section s2w2b
+.section s2w3a
+.section s2w3b
+.section s2w4a
+.section s2w4b
+.section s2w5a
+.section s2w5b
+.section s2w6a
+.section s2w6b
+.section s2w7a
+.section s2w7b
+.section s2w8a
+.section s2w8b
+.section s2w9a
+.section s2w9b
+.section s2w0a
+.section s2w0b
+.section s2xaa
+.section s2xab
+.section s2xba
+.section s2xbb
+.section s2xca
+.section s2xcb
+.section s2xda
+.section s2xdb
+.section s2xea
+.section s2xeb
+.section s2xfa
+.section s2xfb
+.section s2xga
+.section s2xgb
+.section s2xha
+.section s2xhb
+.section s2xia
+.section s2xib
+.section s2xja
+.section s2xjb
+.section s2xka
+.section s2xkb
+.section s2xla
+.section s2xlb
+.section s2xma
+.section s2xmb
+.section s2xna
+.section s2xnb
+.section s2xoa
+.section s2xob
+.section s2xpa
+.section s2xpb
+.section s2xqa
+.section s2xqb
+.section s2xra
+.section s2xrb
+.section s2xsa
+.section s2xsb
+.section s2xta
+.section s2xtb
+.section s2xua
+.section s2xub
+.section s2xva
+.section s2xvb
+.section s2xwa
+.section s2xwb
+.section s2xxa
+.section s2xxb
+.section s2xya
+.section s2xyb
+.section s2xza
+.section s2xzb
+.section s2x1a
+.section s2x1b
+.section s2x2a
+.section s2x2b
+.section s2x3a
+.section s2x3b
+.section s2x4a
+.section s2x4b
+.section s2x5a
+.section s2x5b
+.section s2x6a
+.section s2x6b
+.section s2x7a
+.section s2x7b
+.section s2x8a
+.section s2x8b
+.section s2x9a
+.section s2x9b
+.section s2x0a
+.section s2x0b
+.section s2yaa
+.section s2yab
+.section s2yba
+.section s2ybb
+.section s2yca
+.section s2ycb
+.section s2yda
+.section s2ydb
+.section s2yea
+.section s2yeb
+.section s2yfa
+.section s2yfb
+.section s2yga
+.section s2ygb
+.section s2yha
+.section s2yhb
+.section s2yia
+.section s2yib
+.section s2yja
+.section s2yjb
+.section s2yka
+.section s2ykb
+.section s2yla
+.section s2ylb
+.section s2yma
+.section s2ymb
+.section s2yna
+.section s2ynb
+.section s2yoa
+.section s2yob
+.section s2ypa
+.section s2ypb
+.section s2yqa
+.section s2yqb
+.section s2yra
+.section s2yrb
+.section s2ysa
+.section s2ysb
+.section s2yta
+.section s2ytb
+.section s2yua
+.section s2yub
+.section s2yva
+.section s2yvb
+.section s2ywa
+.section s2ywb
+.section s2yxa
+.section s2yxb
+.section s2yya
+.section s2yyb
+.section s2yza
+.section s2yzb
+.section s2y1a
+.section s2y1b
+.section s2y2a
+.section s2y2b
+.section s2y3a
+.section s2y3b
+.section s2y4a
+.section s2y4b
+.section s2y5a
+.section s2y5b
+.section s2y6a
+.section s2y6b
+.section s2y7a
+.section s2y7b
+.section s2y8a
+.section s2y8b
+.section s2y9a
+.section s2y9b
+.section s2y0a
+.section s2y0b
+.section s2zaa
+.section s2zab
+.section s2zba
+.section s2zbb
+.section s2zca
+.section s2zcb
+.section s2zda
+.section s2zdb
+.section s2zea
+.section s2zeb
+.section s2zfa
+.section s2zfb
+.section s2zga
+.section s2zgb
+.section s2zha
+.section s2zhb
+.section s2zia
+.section s2zib
+.section s2zja
+.section s2zjb
+.section s2zka
+.section s2zkb
+.section s2zla
+.section s2zlb
+.section s2zma
+.section s2zmb
+.section s2zna
+.section s2znb
+.section s2zoa
+.section s2zob
+.section s2zpa
+.section s2zpb
+.section s2zqa
+.section s2zqb
+.section s2zra
+.section s2zrb
+.section s2zsa
+.section s2zsb
+.section s2zta
+.section s2ztb
+.section s2zua
+.section s2zub
+.section s2zva
+.section s2zvb
+.section s2zwa
+.section s2zwb
+.section s2zxa
+.section s2zxb
+.section s2zya
+.section s2zyb
+.section s2zza
+.section s2zzb
+.section s2z1a
+.section s2z1b
+.section s2z2a
+.section s2z2b
+.section s2z3a
+.section s2z3b
+.section s2z4a
+.section s2z4b
+.section s2z5a
+.section s2z5b
+.section s2z6a
+.section s2z6b
+.section s2z7a
+.section s2z7b
+.section s2z8a
+.section s2z8b
+.section s2z9a
+.section s2z9b
+.section s2z0a
+.section s2z0b
+.section s21aa
+.section s21ab
+.section s21ba
+.section s21bb
+.section s21ca
+.section s21cb
+.section s21da
+.section s21db
+.section s21ea
+.section s21eb
+.section s21fa
+.section s21fb
+.section s21ga
+.section s21gb
+.section s21ha
+.section s21hb
+.section s21ia
+.section s21ib
+.section s21ja
+.section s21jb
+.section s21ka
+.section s21kb
+.section s21la
+.section s21lb
+.section s21ma
+.section s21mb
+.section s21na
+.section s21nb
+.section s21oa
+.section s21ob
+.section s21pa
+.section s21pb
+.section s21qa
+.section s21qb
+.section s21ra
+.section s21rb
+.section s21sa
+.section s21sb
+.section s21ta
+.section s21tb
+.section s21ua
+.section s21ub
+.section s21va
+.section s21vb
+.section s21wa
+.section s21wb
+.section s21xa
+.section s21xb
+.section s21ya
+.section s21yb
+.section s21za
+.section s21zb
+.section s211a
+.section s211b
+.section s212a
+.section s212b
+.section s213a
+.section s213b
+.section s214a
+.section s214b
+.section s215a
+.section s215b
+.section s216a
+.section s216b
+.section s217a
+.section s217b
+.section s218a
+.section s218b
+.section s219a
+.section s219b
+.section s210a
+.section s210b
+.section s22aa
+.section s22ab
+.section s22ba
+.section s22bb
+.section s22ca
+.section s22cb
+.section s22da
+.section s22db
+.section s22ea
+.section s22eb
+.section s22fa
+.section s22fb
+.section s22ga
+.section s22gb
+.section s22ha
+.section s22hb
+.section s22ia
+.section s22ib
+.section s22ja
+.section s22jb
+.section s22ka
+.section s22kb
+.section s22la
+.section s22lb
+.section s22ma
+.section s22mb
+.section s22na
+.section s22nb
+.section s22oa
+.section s22ob
+.section s22pa
+.section s22pb
+.section s22qa
+.section s22qb
+.section s22ra
+.section s22rb
+.section s22sa
+.section s22sb
+.section s22ta
+.section s22tb
+.section s22ua
+.section s22ub
+.section s22va
+.section s22vb
+.section s22wa
+.section s22wb
+.section s22xa
+.section s22xb
+.section s22ya
+.section s22yb
+.section s22za
+.section s22zb
+.section s221a
+.section s221b
+.section s222a
+.section s222b
+.section s223a
+.section s223b
+.section s224a
+.section s224b
+.section s225a
+.section s225b
+.section s226a
+.section s226b
+.section s227a
+.section s227b
+.section s228a
+.section s228b
+.section s229a
+.section s229b
+.section s220a
+.section s220b
+.section s23aa
+.section s23ab
+.section s23ba
+.section s23bb
+.section s23ca
+.section s23cb
+.section s23da
+.section s23db
+.section s23ea
+.section s23eb
+.section s23fa
+.section s23fb
+.section s23ga
+.section s23gb
+.section s23ha
+.section s23hb
+.section s23ia
+.section s23ib
+.section s23ja
+.section s23jb
+.section s23ka
+.section s23kb
+.section s23la
+.section s23lb
+.section s23ma
+.section s23mb
+.section s23na
+.section s23nb
+.section s23oa
+.section s23ob
+.section s23pa
+.section s23pb
+.section s23qa
+.section s23qb
+.section s23ra
+.section s23rb
+.section s23sa
+.section s23sb
+.section s23ta
+.section s23tb
+.section s23ua
+.section s23ub
+.section s23va
+.section s23vb
+.section s23wa
+.section s23wb
+.section s23xa
+.section s23xb
+.section s23ya
+.section s23yb
+.section s23za
+.section s23zb
+.section s231a
+.section s231b
+.section s232a
+.section s232b
+.section s233a
+.section s233b
+.section s234a
+.section s234b
+.section s235a
+.section s235b
+.section s236a
+.section s236b
+.section s237a
+.section s237b
+.section s238a
+.section s238b
+.section s239a
+.section s239b
+.section s230a
+.section s230b
+.section s24aa
+.section s24ab
+.section s24ba
+.section s24bb
+.section s24ca
+.section s24cb
+.section s24da
+.section s24db
+.section s24ea
+.section s24eb
+.section s24fa
+.section s24fb
+.section s24ga
+.section s24gb
+.section s24ha
+.section s24hb
+.section s24ia
+.section s24ib
+.section s24ja
+.section s24jb
+.section s24ka
+.section s24kb
+.section s24la
+.section s24lb
+.section s24ma
+.section s24mb
+.section s24na
+.section s24nb
+.section s24oa
+.section s24ob
+.section s24pa
+.section s24pb
+.section s24qa
+.section s24qb
+.section s24ra
+.section s24rb
+.section s24sa
+.section s24sb
+.section s24ta
+.section s24tb
+.section s24ua
+.section s24ub
+.section s24va
+.section s24vb
+.section s24wa
+.section s24wb
+.section s24xa
+.section s24xb
+.section s24ya
+.section s24yb
+.section s24za
+.section s24zb
+.section s241a
+.section s241b
+.section s242a
+.section s242b
+.section s243a
+.section s243b
+.section s244a
+.section s244b
+.section s245a
+.section s245b
+.section s246a
+.section s246b
+.section s247a
+.section s247b
+.section s248a
+.section s248b
+.section s249a
+.section s249b
+.section s240a
+.section s240b
+.section s25aa
+.section s25ab
+.section s25ba
+.section s25bb
+.section s25ca
+.section s25cb
+.section s25da
+.section s25db
+.section s25ea
+.section s25eb
+.section s25fa
+.section s25fb
+.section s25ga
+.section s25gb
+.section s25ha
+.section s25hb
+.section s25ia
+.section s25ib
+.section s25ja
+.section s25jb
+.section s25ka
+.section s25kb
+.section s25la
+.section s25lb
+.section s25ma
+.section s25mb
+.section s25na
+.section s25nb
+.section s25oa
+.section s25ob
+.section s25pa
+.section s25pb
+.section s25qa
+.section s25qb
+.section s25ra
+.section s25rb
+.section s25sa
+.section s25sb
+.section s25ta
+.section s25tb
+.section s25ua
+.section s25ub
+.section s25va
+.section s25vb
+.section s25wa
+.section s25wb
+.section s25xa
+.section s25xb
+.section s25ya
+.section s25yb
+.section s25za
+.section s25zb
+.section s251a
+.section s251b
+.section s252a
+.section s252b
+.section s253a
+.section s253b
+.section s254a
+.section s254b
+.section s255a
+.section s255b
+.section s256a
+.section s256b
+.section s257a
+.section s257b
+.section s258a
+.section s258b
+.section s259a
+.section s259b
+.section s250a
+.section s250b
+.section s26aa
+.section s26ab
+.section s26ba
+.section s26bb
+.section s26ca
+.section s26cb
+.section s26da
+.section s26db
+.section s26ea
+.section s26eb
+.section s26fa
+.section s26fb
+.section s26ga
+.section s26gb
+.section s26ha
+.section s26hb
+.section s26ia
+.section s26ib
+.section s26ja
+.section s26jb
+.section s26ka
+.section s26kb
+.section s26la
+.section s26lb
+.section s26ma
+.section s26mb
+.section s26na
+.section s26nb
+.section s26oa
+.section s26ob
+.section s26pa
+.section s26pb
+.section s26qa
+.section s26qb
+.section s26ra
+.section s26rb
+.section s26sa
+.section s26sb
+.section s26ta
+.section s26tb
+.section s26ua
+.section s26ub
+.section s26va
+.section s26vb
+.section s26wa
+.section s26wb
+.section s26xa
+.section s26xb
+.section s26ya
+.section s26yb
+.section s26za
+.section s26zb
+.section s261a
+.section s261b
+.section s262a
+.section s262b
+.section s263a
+.section s263b
+.section s264a
+.section s264b
+.section s265a
+.section s265b
+.section s266a
+.section s266b
+.section s267a
+.section s267b
+.section s268a
+.section s268b
+.section s269a
+.section s269b
+.section s260a
+.section s260b
+.section s27aa
+.section s27ab
+.section s27ba
+.section s27bb
+.section s27ca
+.section s27cb
+.section s27da
+.section s27db
+.section s27ea
+.section s27eb
+.section s27fa
+.section s27fb
+.section s27ga
+.section s27gb
+.section s27ha
+.section s27hb
+.section s27ia
+.section s27ib
+.section s27ja
+.section s27jb
+.section s27ka
+.section s27kb
+.section s27la
+.section s27lb
+.section s27ma
+.section s27mb
+.section s27na
+.section s27nb
+.section s27oa
+.section s27ob
+.section s27pa
+.section s27pb
+.section s27qa
+.section s27qb
+.section s27ra
+.section s27rb
+.section s27sa
+.section s27sb
+.section s27ta
+.section s27tb
+.section s27ua
+.section s27ub
+.section s27va
+.section s27vb
+.section s27wa
+.section s27wb
+.section s27xa
+.section s27xb
+.section s27ya
+.section s27yb
+.section s27za
+.section s27zb
+.section s271a
+.section s271b
+.section s272a
+.section s272b
+.section s273a
+.section s273b
+.section s274a
+.section s274b
+.section s275a
+.section s275b
+.section s276a
+.section s276b
+.section s277a
+.section s277b
+.section s278a
+.section s278b
+.section s279a
+.section s279b
+.section s270a
+.section s270b
+.section s28aa
+.section s28ab
+.section s28ba
+.section s28bb
+.section s28ca
+.section s28cb
+.section s28da
+.section s28db
+.section s28ea
+.section s28eb
+.section s28fa
+.section s28fb
+.section s28ga
+.section s28gb
+.section s28ha
+.section s28hb
+.section s28ia
+.section s28ib
+.section s28ja
+.section s28jb
+.section s28ka
+.section s28kb
+.section s28la
+.section s28lb
+.section s28ma
+.section s28mb
+.section s28na
+.section s28nb
+.section s28oa
+.section s28ob
+.section s28pa
+.section s28pb
+.section s28qa
+.section s28qb
+.section s28ra
+.section s28rb
+.section s28sa
+.section s28sb
+.section s28ta
+.section s28tb
+.section s28ua
+.section s28ub
+.section s28va
+.section s28vb
+.section s28wa
+.section s28wb
+.section s28xa
+.section s28xb
+.section s28ya
+.section s28yb
+.section s28za
+.section s28zb
+.section s281a
+.section s281b
+.section s282a
+.section s282b
+.section s283a
+.section s283b
+.section s284a
+.section s284b
+.section s285a
+.section s285b
+.section s286a
+.section s286b
+.section s287a
+.section s287b
+.section s288a
+.section s288b
+.section s289a
+.section s289b
+.section s280a
+.section s280b
+.section s29aa
+.section s29ab
+.section s29ba
+.section s29bb
+.section s29ca
+.section s29cb
+.section s29da
+.section s29db
+.section s29ea
+.section s29eb
+.section s29fa
+.section s29fb
+.section s29ga
+.section s29gb
+.section s29ha
+.section s29hb
+.section s29ia
+.section s29ib
+.section s29ja
+.section s29jb
+.section s29ka
+.section s29kb
+.section s29la
+.section s29lb
+.section s29ma
+.section s29mb
+.section s29na
+.section s29nb
+.section s29oa
+.section s29ob
+.section s29pa
+.section s29pb
+.section s29qa
+.section s29qb
+.section s29ra
+.section s29rb
+.section s29sa
+.section s29sb
+.section s29ta
+.section s29tb
+.section s29ua
+.section s29ub
+.section s29va
+.section s29vb
+.section s29wa
+.section s29wb
+.section s29xa
+.section s29xb
+.section s29ya
+.section s29yb
+.section s29za
+.section s29zb
+.section s291a
+.section s291b
+.section s292a
+.section s292b
+.section s293a
+.section s293b
+.section s294a
+.section s294b
+.section s295a
+.section s295b
+.section s296a
+.section s296b
+.section s297a
+.section s297b
+.section s298a
+.section s298b
+.section s299a
+.section s299b
+.section s290a
+.section s290b
+.section s20aa
+.section s20ab
+.section s20ba
+.section s20bb
+.section s20ca
+.section s20cb
+.section s20da
+.section s20db
+.section s20ea
+.section s20eb
+.section s20fa
+.section s20fb
+.section s20ga
+.section s20gb
+.section s20ha
+.section s20hb
+.section s20ia
+.section s20ib
+.section s20ja
+.section s20jb
+.section s20ka
+.section s20kb
+.section s20la
+.section s20lb
+.section s20ma
+.section s20mb
+.section s20na
+.section s20nb
+.section s20oa
+.section s20ob
+.section s20pa
+.section s20pb
+.section s20qa
+.section s20qb
+.section s20ra
+.section s20rb
+.section s20sa
+.section s20sb
+.section s20ta
+.section s20tb
+.section s20ua
+.section s20ub
+.section s20va
+.section s20vb
+.section s20wa
+.section s20wb
+.section s20xa
+.section s20xb
+.section s20ya
+.section s20yb
+.section s20za
+.section s20zb
+.section s201a
+.section s201b
+.section s202a
+.section s202b
+.section s203a
+.section s203b
+.section s204a
+.section s204b
+.section s205a
+.section s205b
+.section s206a
+.section s206b
+.section s207a
+.section s207b
+.section s208a
+.section s208b
+.section s209a
+.section s209b
+.section s200a
+.section s200b
+.section s3aaa
+.section s3aab
+.section s3aba
+.section s3abb
+.section s3aca
+.section s3acb
+.section s3ada
+.section s3adb
+.section s3aea
+.section s3aeb
+.section s3afa
+.section s3afb
+.section s3aga
+.section s3agb
+.section s3aha
+.section s3ahb
+.section s3aia
+.section s3aib
+.section s3aja
+.section s3ajb
+.section s3aka
+.section s3akb
+.section s3ala
+.section s3alb
+.section s3ama
+.section s3amb
+.section s3ana
+.section s3anb
+.section s3aoa
+.section s3aob
+.section s3apa
+.section s3apb
+.section s3aqa
+.section s3aqb
+.section s3ara
+.section s3arb
+.section s3asa
+.section s3asb
+.section s3ata
+.section s3atb
+.section s3aua
+.section s3aub
+.section s3ava
+.section s3avb
+.section s3awa
+.section s3awb
+.section s3axa
+.section s3axb
+.section s3aya
+.section s3ayb
+.section s3aza
+.section s3azb
+.section s3a1a
+.section s3a1b
+.section s3a2a
+.section s3a2b
+.section s3a3a
+.section s3a3b
+.section s3a4a
+.section s3a4b
+.section s3a5a
+.section s3a5b
+.section s3a6a
+.section s3a6b
+.section s3a7a
+.section s3a7b
+.section s3a8a
+.section s3a8b
+.section s3a9a
+.section s3a9b
+.section s3a0a
+.section s3a0b
+.section s3baa
+.section s3bab
+.section s3bba
+.section s3bbb
+.section s3bca
+.section s3bcb
+.section s3bda
+.section s3bdb
+.section s3bea
+.section s3beb
+.section s3bfa
+.section s3bfb
+.section s3bga
+.section s3bgb
+.section s3bha
+.section s3bhb
+.section s3bia
+.section s3bib
+.section s3bja
+.section s3bjb
+.section s3bka
+.section s3bkb
+.section s3bla
+.section s3blb
+.section s3bma
+.section s3bmb
+.section s3bna
+.section s3bnb
+.section s3boa
+.section s3bob
+.section s3bpa
+.section s3bpb
+.section s3bqa
+.section s3bqb
+.section s3bra
+.section s3brb
+.section s3bsa
+.section s3bsb
+.section s3bta
+.section s3btb
+.section s3bua
+.section s3bub
+.section s3bva
+.section s3bvb
+.section s3bwa
+.section s3bwb
+.section s3bxa
+.section s3bxb
+.section s3bya
+.section s3byb
+.section s3bza
+.section s3bzb
+.section s3b1a
+.section s3b1b
+.section s3b2a
+.section s3b2b
+.section s3b3a
+.section s3b3b
+.section s3b4a
+.section s3b4b
+.section s3b5a
+.section s3b5b
+.section s3b6a
+.section s3b6b
+.section s3b7a
+.section s3b7b
+.section s3b8a
+.section s3b8b
+.section s3b9a
+.section s3b9b
+.section s3b0a
+.section s3b0b
+.section s3caa
+.section s3cab
+.section s3cba
+.section s3cbb
+.section s3cca
+.section s3ccb
+.section s3cda
+.section s3cdb
+.section s3cea
+.section s3ceb
+.section s3cfa
+.section s3cfb
+.section s3cga
+.section s3cgb
+.section s3cha
+.section s3chb
+.section s3cia
+.section s3cib
+.section s3cja
+.section s3cjb
+.section s3cka
+.section s3ckb
+.section s3cla
+.section s3clb
+.section s3cma
+.section s3cmb
+.section s3cna
+.section s3cnb
+.section s3coa
+.section s3cob
+.section s3cpa
+.section s3cpb
+.section s3cqa
+.section s3cqb
+.section s3cra
+.section s3crb
+.section s3csa
+.section s3csb
+.section s3cta
+.section s3ctb
+.section s3cua
+.section s3cub
+.section s3cva
+.section s3cvb
+.section s3cwa
+.section s3cwb
+.section s3cxa
+.section s3cxb
+.section s3cya
+.section s3cyb
+.section s3cza
+.section s3czb
+.section s3c1a
+.section s3c1b
+.section s3c2a
+.section s3c2b
+.section s3c3a
+.section s3c3b
+.section s3c4a
+.section s3c4b
+.section s3c5a
+.section s3c5b
+.section s3c6a
+.section s3c6b
+.section s3c7a
+.section s3c7b
+.section s3c8a
+.section s3c8b
+.section s3c9a
+.section s3c9b
+.section s3c0a
+.section s3c0b
+.section s3daa
+.section s3dab
+.section s3dba
+.section s3dbb
+.section s3dca
+.section s3dcb
+.section s3dda
+.section s3ddb
+.section s3dea
+.section s3deb
+.section s3dfa
+.section s3dfb
+.section s3dga
+.section s3dgb
+.section s3dha
+.section s3dhb
+.section s3dia
+.section s3dib
+.section s3dja
+.section s3djb
+.section s3dka
+.section s3dkb
+.section s3dla
+.section s3dlb
+.section s3dma
+.section s3dmb
+.section s3dna
+.section s3dnb
+.section s3doa
+.section s3dob
+.section s3dpa
+.section s3dpb
+.section s3dqa
+.section s3dqb
+.section s3dra
+.section s3drb
+.section s3dsa
+.section s3dsb
+.section s3dta
+.section s3dtb
+.section s3dua
+.section s3dub
+.section s3dva
+.section s3dvb
+.section s3dwa
+.section s3dwb
+.section s3dxa
+.section s3dxb
+.section s3dya
+.section s3dyb
+.section s3dza
+.section s3dzb
+.section s3d1a
+.section s3d1b
+.section s3d2a
+.section s3d2b
+.section s3d3a
+.section s3d3b
+.section s3d4a
+.section s3d4b
+.section s3d5a
+.section s3d5b
+.section s3d6a
+.section s3d6b
+.section s3d7a
+.section s3d7b
+.section s3d8a
+.section s3d8b
+.section s3d9a
+.section s3d9b
+.section s3d0a
+.section s3d0b
+.section s3eaa
+.section s3eab
+.section s3eba
+.section s3ebb
+.section s3eca
+.section s3ecb
+.section s3eda
+.section s3edb
+.section s3eea
+.section s3eeb
+.section s3efa
+.section s3efb
+.section s3ega
+.section s3egb
+.section s3eha
+.section s3ehb
+.section s3eia
+.section s3eib
+.section s3eja
+.section s3ejb
+.section s3eka
+.section s3ekb
+.section s3ela
+.section s3elb
+.section s3ema
+.section s3emb
+.section s3ena
+.section s3enb
+.section s3eoa
+.section s3eob
+.section s3epa
+.section s3epb
+.section s3eqa
+.section s3eqb
+.section s3era
+.section s3erb
+.section s3esa
+.section s3esb
+.section s3eta
+.section s3etb
+.section s3eua
+.section s3eub
+.section s3eva
+.section s3evb
+.section s3ewa
+.section s3ewb
+.section s3exa
+.section s3exb
+.section s3eya
+.section s3eyb
+.section s3eza
+.section s3ezb
+.section s3e1a
+.section s3e1b
+.section s3e2a
+.section s3e2b
+.section s3e3a
+.section s3e3b
+.section s3e4a
+.section s3e4b
+.section s3e5a
+.section s3e5b
+.section s3e6a
+.section s3e6b
+.section s3e7a
+.section s3e7b
+.section s3e8a
+.section s3e8b
+.section s3e9a
+.section s3e9b
+.section s3e0a
+.section s3e0b
+.section s3faa
+.section s3fab
+.section s3fba
+.section s3fbb
+.section s3fca
+.section s3fcb
+.section s3fda
+.section s3fdb
+.section s3fea
+.section s3feb
+.section s3ffa
+.section s3ffb
+.section s3fga
+.section s3fgb
+.section s3fha
+.section s3fhb
+.section s3fia
+.section s3fib
+.section s3fja
+.section s3fjb
+.section s3fka
+.section s3fkb
+.section s3fla
+.section s3flb
+.section s3fma
+.section s3fmb
+.section s3fna
+.section s3fnb
+.section s3foa
+.section s3fob
+.section s3fpa
+.section s3fpb
+.section s3fqa
+.section s3fqb
+.section s3fra
+.section s3frb
+.section s3fsa
+.section s3fsb
+.section s3fta
+.section s3ftb
+.section s3fua
+.section s3fub
+.section s3fva
+.section s3fvb
+.section s3fwa
+.section s3fwb
+.section s3fxa
+.section s3fxb
+.section s3fya
+.section s3fyb
+.section s3fza
+.section s3fzb
+.section s3f1a
+.section s3f1b
+.section s3f2a
+.section s3f2b
+.section s3f3a
+.section s3f3b
+.section s3f4a
+.section s3f4b
+.section s3f5a
+.section s3f5b
+.section s3f6a
+.section s3f6b
+.section s3f7a
+.section s3f7b
+.section s3f8a
+.section s3f8b
+.section s3f9a
+.section s3f9b
+.section s3f0a
+.section s3f0b
+.section s3gaa
+.section s3gab
+.section s3gba
+.section s3gbb
+.section s3gca
+.section s3gcb
+.section s3gda
+.section s3gdb
+.section s3gea
+.section s3geb
+.section s3gfa
+.section s3gfb
+.section s3gga
+.section s3ggb
+.section s3gha
+.section s3ghb
+.section s3gia
+.section s3gib
+.section s3gja
+.section s3gjb
+.section s3gka
+.section s3gkb
+.section s3gla
+.section s3glb
+.section s3gma
+.section s3gmb
+.section s3gna
+.section s3gnb
+.section s3goa
+.section s3gob
+.section s3gpa
+.section s3gpb
+.section s3gqa
+.section s3gqb
+.section s3gra
+.section s3grb
+.section s3gsa
+.section s3gsb
+.section s3gta
+.section s3gtb
+.section s3gua
+.section s3gub
+.section s3gva
+.section s3gvb
+.section s3gwa
+.section s3gwb
+.section s3gxa
+.section s3gxb
+.section s3gya
+.section s3gyb
+.section s3gza
+.section s3gzb
+.section s3g1a
+.section s3g1b
+.section s3g2a
+.section s3g2b
+.section s3g3a
+.section s3g3b
+.section s3g4a
+.section s3g4b
+.section s3g5a
+.section s3g5b
+.section s3g6a
+.section s3g6b
+.section s3g7a
+.section s3g7b
+.section s3g8a
+.section s3g8b
+.section s3g9a
+.section s3g9b
+.section s3g0a
+.section s3g0b
+.section s3haa
+.section s3hab
+.section s3hba
+.section s3hbb
+.section s3hca
+.section s3hcb
+.section s3hda
+.section s3hdb
+.section s3hea
+.section s3heb
+.section s3hfa
+.section s3hfb
+.section s3hga
+.section s3hgb
+.section s3hha
+.section s3hhb
+.section s3hia
+.section s3hib
+.section s3hja
+.section s3hjb
+.section s3hka
+.section s3hkb
+.section s3hla
+.section s3hlb
+.section s3hma
+.section s3hmb
+.section s3hna
+.section s3hnb
+.section s3hoa
+.section s3hob
+.section s3hpa
+.section s3hpb
+.section s3hqa
+.section s3hqb
+.section s3hra
+.section s3hrb
+.section s3hsa
+.section s3hsb
+.section s3hta
+.section s3htb
+.section s3hua
+.section s3hub
+.section s3hva
+.section s3hvb
+.section s3hwa
+.section s3hwb
+.section s3hxa
+.section s3hxb
+.section s3hya
+.section s3hyb
+.section s3hza
+.section s3hzb
+.section s3h1a
+.section s3h1b
+.section s3h2a
+.section s3h2b
+.section s3h3a
+.section s3h3b
+.section s3h4a
+.section s3h4b
+.section s3h5a
+.section s3h5b
+.section s3h6a
+.section s3h6b
+.section s3h7a
+.section s3h7b
+.section s3h8a
+.section s3h8b
+.section s3h9a
+.section s3h9b
+.section s3h0a
+.section s3h0b
+.section s3iaa
+.section s3iab
+.section s3iba
+.section s3ibb
+.section s3ica
+.section s3icb
+.section s3ida
+.section s3idb
+.section s3iea
+.section s3ieb
+.section s3ifa
+.section s3ifb
+.section s3iga
+.section s3igb
+.section s3iha
+.section s3ihb
+.section s3iia
+.section s3iib
+.section s3ija
+.section s3ijb
+.section s3ika
+.section s3ikb
+.section s3ila
+.section s3ilb
+.section s3ima
+.section s3imb
+.section s3ina
+.section s3inb
+.section s3ioa
+.section s3iob
+.section s3ipa
+.section s3ipb
+.section s3iqa
+.section s3iqb
+.section s3ira
+.section s3irb
+.section s3isa
+.section s3isb
+.section s3ita
+.section s3itb
+.section s3iua
+.section s3iub
+.section s3iva
+.section s3ivb
+.section s3iwa
+.section s3iwb
+.section s3ixa
+.section s3ixb
+.section s3iya
+.section s3iyb
+.section s3iza
+.section s3izb
+.section s3i1a
+.section s3i1b
+.section s3i2a
+.section s3i2b
+.section s3i3a
+.section s3i3b
+.section s3i4a
+.section s3i4b
+.section s3i5a
+.section s3i5b
+.section s3i6a
+.section s3i6b
+.section s3i7a
+.section s3i7b
+.section s3i8a
+.section s3i8b
+.section s3i9a
+.section s3i9b
+.section s3i0a
+.section s3i0b
+.section s3jaa
+.section s3jab
+.section s3jba
+.section s3jbb
+.section s3jca
+.section s3jcb
+.section s3jda
+.section s3jdb
+.section s3jea
+.section s3jeb
+.section s3jfa
+.section s3jfb
+.section s3jga
+.section s3jgb
+.section s3jha
+.section s3jhb
+.section s3jia
+.section s3jib
+.section s3jja
+.section s3jjb
+.section s3jka
+.section s3jkb
+.section s3jla
+.section s3jlb
+.section s3jma
+.section s3jmb
+.section s3jna
+.section s3jnb
+.section s3joa
+.section s3job
+.section s3jpa
+.section s3jpb
+.section s3jqa
+.section s3jqb
+.section s3jra
+.section s3jrb
+.section s3jsa
+.section s3jsb
+.section s3jta
+.section s3jtb
+.section s3jua
+.section s3jub
+.section s3jva
+.section s3jvb
+.section s3jwa
+.section s3jwb
+.section s3jxa
+.section s3jxb
+.section s3jya
+.section s3jyb
+.section s3jza
+.section s3jzb
+.section s3j1a
+.section s3j1b
+.section s3j2a
+.section s3j2b
+.section s3j3a
+.section s3j3b
+.section s3j4a
+.section s3j4b
+.section s3j5a
+.section s3j5b
+.section s3j6a
+.section s3j6b
+.section s3j7a
+.section s3j7b
+.section s3j8a
+.section s3j8b
+.section s3j9a
+.section s3j9b
+.section s3j0a
+.section s3j0b
+.section s3kaa
+.section s3kab
+.section s3kba
+.section s3kbb
+.section s3kca
+.section s3kcb
+.section s3kda
+.section s3kdb
+.section s3kea
+.section s3keb
+.section s3kfa
+.section s3kfb
+.section s3kga
+.section s3kgb
+.section s3kha
+.section s3khb
+.section s3kia
+.section s3kib
+.section s3kja
+.section s3kjb
+.section s3kka
+.section s3kkb
+.section s3kla
+.section s3klb
+.section s3kma
+.section s3kmb
+.section s3kna
+.section s3knb
+.section s3koa
+.section s3kob
+.section s3kpa
+.section s3kpb
+.section s3kqa
+.section s3kqb
+.section s3kra
+.section s3krb
+.section s3ksa
+.section s3ksb
+.section s3kta
+.section s3ktb
+.section s3kua
+.section s3kub
+.section s3kva
+.section s3kvb
+.section s3kwa
+.section s3kwb
+.section s3kxa
+.section s3kxb
+.section s3kya
+.section s3kyb
+.section s3kza
+.section s3kzb
+.section s3k1a
+.section s3k1b
+.section s3k2a
+.section s3k2b
+.section s3k3a
+.section s3k3b
+.section s3k4a
+.section s3k4b
+.section s3k5a
+.section s3k5b
+.section s3k6a
+.section s3k6b
+.section s3k7a
+.section s3k7b
+.section s3k8a
+.section s3k8b
+.section s3k9a
+.section s3k9b
+.section s3k0a
+.section s3k0b
+.section s3laa
+.section s3lab
+.section s3lba
+.section s3lbb
+.section s3lca
+.section s3lcb
+.section s3lda
+.section s3ldb
+.section s3lea
+.section s3leb
+.section s3lfa
+.section s3lfb
+.section s3lga
+.section s3lgb
+.section s3lha
+.section s3lhb
+.section s3lia
+.section s3lib
+.section s3lja
+.section s3ljb
+.section s3lka
+.section s3lkb
+.section s3lla
+.section s3llb
+.section s3lma
+.section s3lmb
+.section s3lna
+.section s3lnb
+.section s3loa
+.section s3lob
+.section s3lpa
+.section s3lpb
+.section s3lqa
+.section s3lqb
+.section s3lra
+.section s3lrb
+.section s3lsa
+.section s3lsb
+.section s3lta
+.section s3ltb
+.section s3lua
+.section s3lub
+.section s3lva
+.section s3lvb
+.section s3lwa
+.section s3lwb
+.section s3lxa
+.section s3lxb
+.section s3lya
+.section s3lyb
+.section s3lza
+.section s3lzb
+.section s3l1a
+.section s3l1b
+.section s3l2a
+.section s3l2b
+.section s3l3a
+.section s3l3b
+.section s3l4a
+.section s3l4b
+.section s3l5a
+.section s3l5b
+.section s3l6a
+.section s3l6b
+.section s3l7a
+.section s3l7b
+.section s3l8a
+.section s3l8b
+.section s3l9a
+.section s3l9b
+.section s3l0a
+.section s3l0b
+.section s3maa
+.section s3mab
+.section s3mba
+.section s3mbb
+.section s3mca
+.section s3mcb
+.section s3mda
+.section s3mdb
+.section s3mea
+.section s3meb
+.section s3mfa
+.section s3mfb
+.section s3mga
+.section s3mgb
+.section s3mha
+.section s3mhb
+.section s3mia
+.section s3mib
+.section s3mja
+.section s3mjb
+.section s3mka
+.section s3mkb
+.section s3mla
+.section s3mlb
+.section s3mma
+.section s3mmb
+.section s3mna
+.section s3mnb
+.section s3moa
+.section s3mob
+.section s3mpa
+.section s3mpb
+.section s3mqa
+.section s3mqb
+.section s3mra
+.section s3mrb
+.section s3msa
+.section s3msb
+.section s3mta
+.section s3mtb
+.section s3mua
+.section s3mub
+.section s3mva
+.section s3mvb
+.section s3mwa
+.section s3mwb
+.section s3mxa
+.section s3mxb
+.section s3mya
+.section s3myb
+.section s3mza
+.section s3mzb
+.section s3m1a
+.section s3m1b
+.section s3m2a
+.section s3m2b
+.section s3m3a
+.section s3m3b
+.section s3m4a
+.section s3m4b
+.section s3m5a
+.section s3m5b
+.section s3m6a
+.section s3m6b
+.section s3m7a
+.section s3m7b
+.section s3m8a
+.section s3m8b
+.section s3m9a
+.section s3m9b
+.section s3m0a
+.section s3m0b
+.section s3naa
+.section s3nab
+.section s3nba
+.section s3nbb
+.section s3nca
+.section s3ncb
+.section s3nda
+.section s3ndb
+.section s3nea
+.section s3neb
+.section s3nfa
+.section s3nfb
+.section s3nga
+.section s3ngb
+.section s3nha
+.section s3nhb
+.section s3nia
+.section s3nib
+.section s3nja
+.section s3njb
+.section s3nka
+.section s3nkb
+.section s3nla
+.section s3nlb
+.section s3nma
+.section s3nmb
+.section s3nna
+.section s3nnb
+.section s3noa
+.section s3nob
+.section s3npa
+.section s3npb
+.section s3nqa
+.section s3nqb
+.section s3nra
+.section s3nrb
+.section s3nsa
+.section s3nsb
+.section s3nta
+.section s3ntb
+.section s3nua
+.section s3nub
+.section s3nva
+.section s3nvb
+.section s3nwa
+.section s3nwb
+.section s3nxa
+.section s3nxb
+.section s3nya
+.section s3nyb
+.section s3nza
+.section s3nzb
+.section s3n1a
+.section s3n1b
+.section s3n2a
+.section s3n2b
+.section s3n3a
+.section s3n3b
+.section s3n4a
+.section s3n4b
+.section s3n5a
+.section s3n5b
+.section s3n6a
+.section s3n6b
+.section s3n7a
+.section s3n7b
+.section s3n8a
+.section s3n8b
+.section s3n9a
+.section s3n9b
+.section s3n0a
+.section s3n0b
+.section s3oaa
+.section s3oab
+.section s3oba
+.section s3obb
+.section s3oca
+.section s3ocb
+.section s3oda
+.section s3odb
+.section s3oea
+.section s3oeb
+.section s3ofa
+.section s3ofb
+.section s3oga
+.section s3ogb
+.section s3oha
+.section s3ohb
+.section s3oia
+.section s3oib
+.section s3oja
+.section s3ojb
+.section s3oka
+.section s3okb
+.section s3ola
+.section s3olb
+.section s3oma
+.section s3omb
+.section s3ona
+.section s3onb
+.section s3ooa
+.section s3oob
+.section s3opa
+.section s3opb
+.section s3oqa
+.section s3oqb
+.section s3ora
+.section s3orb
+.section s3osa
+.section s3osb
+.section s3ota
+.section s3otb
+.section s3oua
+.section s3oub
+.section s3ova
+.section s3ovb
+.section s3owa
+.section s3owb
+.section s3oxa
+.section s3oxb
+.section s3oya
+.section s3oyb
+.section s3oza
+.section s3ozb
+.section s3o1a
+.section s3o1b
+.section s3o2a
+.section s3o2b
+.section s3o3a
+.section s3o3b
+.section s3o4a
+.section s3o4b
+.section s3o5a
+.section s3o5b
+.section s3o6a
+.section s3o6b
+.section s3o7a
+.section s3o7b
+.section s3o8a
+.section s3o8b
+.section s3o9a
+.section s3o9b
+.section s3o0a
+.section s3o0b
+.section s3paa
+.section s3pab
+.section s3pba
+.section s3pbb
+.section s3pca
+.section s3pcb
+.section s3pda
+.section s3pdb
+.section s3pea
+.section s3peb
+.section s3pfa
+.section s3pfb
+.section s3pga
+.section s3pgb
+.section s3pha
+.section s3phb
+.section s3pia
+.section s3pib
+.section s3pja
+.section s3pjb
+.section s3pka
+.section s3pkb
+.section s3pla
+.section s3plb
+.section s3pma
+.section s3pmb
+.section s3pna
+.section s3pnb
+.section s3poa
+.section s3pob
+.section s3ppa
+.section s3ppb
+.section s3pqa
+.section s3pqb
+.section s3pra
+.section s3prb
+.section s3psa
+.section s3psb
+.section s3pta
+.section s3ptb
+.section s3pua
+.section s3pub
+.section s3pva
+.section s3pvb
+.section s3pwa
+.section s3pwb
+.section s3pxa
+.section s3pxb
+.section s3pya
+.section s3pyb
+.section s3pza
+.section s3pzb
+.section s3p1a
+.section s3p1b
+.section s3p2a
+.section s3p2b
+.section s3p3a
+.section s3p3b
+.section s3p4a
+.section s3p4b
+.section s3p5a
+.section s3p5b
+.section s3p6a
+.section s3p6b
+.section s3p7a
+.section s3p7b
+.section s3p8a
+.section s3p8b
+.section s3p9a
+.section s3p9b
+.section s3p0a
+.section s3p0b
+.section s3qaa
+.section s3qab
+.section s3qba
+.section s3qbb
+.section s3qca
+.section s3qcb
+.section s3qda
+.section s3qdb
+.section s3qea
+.section s3qeb
+.section s3qfa
+.section s3qfb
+.section s3qga
+.section s3qgb
+.section s3qha
+.section s3qhb
+.section s3qia
+.section s3qib
+.section s3qja
+.section s3qjb
+.section s3qka
+.section s3qkb
+.section s3qla
+.section s3qlb
+.section s3qma
+.section s3qmb
+.section s3qna
+.section s3qnb
+.section s3qoa
+.section s3qob
+.section s3qpa
+.section s3qpb
+.section s3qqa
+.section s3qqb
+.section s3qra
+.section s3qrb
+.section s3qsa
+.section s3qsb
+.section s3qta
+.section s3qtb
+.section s3qua
+.section s3qub
+.section s3qva
+.section s3qvb
+.section s3qwa
+.section s3qwb
+.section s3qxa
+.section s3qxb
+.section s3qya
+.section s3qyb
+.section s3qza
+.section s3qzb
+.section s3q1a
+.section s3q1b
+.section s3q2a
+.section s3q2b
+.section s3q3a
+.section s3q3b
+.section s3q4a
+.section s3q4b
+.section s3q5a
+.section s3q5b
+.section s3q6a
+.section s3q6b
+.section s3q7a
+.section s3q7b
+.section s3q8a
+.section s3q8b
+.section s3q9a
+.section s3q9b
+.section s3q0a
+.section s3q0b
+.section s3raa
+.section s3rab
+.section s3rba
+.section s3rbb
+.section s3rca
+.section s3rcb
+.section s3rda
+.section s3rdb
+.section s3rea
+.section s3reb
+.section s3rfa
+.section s3rfb
+.section s3rga
+.section s3rgb
+.section s3rha
+.section s3rhb
+.section s3ria
+.section s3rib
+.section s3rja
+.section s3rjb
+.section s3rka
+.section s3rkb
+.section s3rla
+.section s3rlb
+.section s3rma
+.section s3rmb
+.section s3rna
+.section s3rnb
+.section s3roa
+.section s3rob
+.section s3rpa
+.section s3rpb
+.section s3rqa
+.section s3rqb
+.section s3rra
+.section s3rrb
+.section s3rsa
+.section s3rsb
+.section s3rta
+.section s3rtb
+.section s3rua
+.section s3rub
+.section s3rva
+.section s3rvb
+.section s3rwa
+.section s3rwb
+.section s3rxa
+.section s3rxb
+.section s3rya
+.section s3ryb
+.section s3rza
+.section s3rzb
+.section s3r1a
+.section s3r1b
+.section s3r2a
+.section s3r2b
+.section s3r3a
+.section s3r3b
+.section s3r4a
+.section s3r4b
+.section s3r5a
+.section s3r5b
+.section s3r6a
+.section s3r6b
+.section s3r7a
+.section s3r7b
+.section s3r8a
+.section s3r8b
+.section s3r9a
+.section s3r9b
+.section s3r0a
+.section s3r0b
+.section s3saa
+.section s3sab
+.section s3sba
+.section s3sbb
+.section s3sca
+.section s3scb
+.section s3sda
+.section s3sdb
+.section s3sea
+.section s3seb
+.section s3sfa
+.section s3sfb
+.section s3sga
+.section s3sgb
+.section s3sha
+.section s3shb
+.section s3sia
+.section s3sib
+.section s3sja
+.section s3sjb
+.section s3ska
+.section s3skb
+.section s3sla
+.section s3slb
+.section s3sma
+.section s3smb
+.section s3sna
+.section s3snb
+.section s3soa
+.section s3sob
+.section s3spa
+.section s3spb
+.section s3sqa
+.section s3sqb
+.section s3sra
+.section s3srb
+.section s3ssa
+.section s3ssb
+.section s3sta
+.section s3stb
+.section s3sua
+.section s3sub
+.section s3sva
+.section s3svb
+.section s3swa
+.section s3swb
+.section s3sxa
+.section s3sxb
+.section s3sya
+.section s3syb
+.section s3sza
+.section s3szb
+.section s3s1a
+.section s3s1b
+.section s3s2a
+.section s3s2b
+.section s3s3a
+.section s3s3b
+.section s3s4a
+.section s3s4b
+.section s3s5a
+.section s3s5b
+.section s3s6a
+.section s3s6b
+.section s3s7a
+.section s3s7b
+.section s3s8a
+.section s3s8b
+.section s3s9a
+.section s3s9b
+.section s3s0a
+.section s3s0b
+.section s3taa
+.section s3tab
+.section s3tba
+.section s3tbb
+.section s3tca
+.section s3tcb
+.section s3tda
+.section s3tdb
+.section s3tea
+.section s3teb
+.section s3tfa
+.section s3tfb
+.section s3tga
+.section s3tgb
+.section s3tha
+.section s3thb
+.section s3tia
+.section s3tib
+.section s3tja
+.section s3tjb
+.section s3tka
+.section s3tkb
+.section s3tla
+.section s3tlb
+.section s3tma
+.section s3tmb
+.section s3tna
+.section s3tnb
+.section s3toa
+.section s3tob
+.section s3tpa
+.section s3tpb
+.section s3tqa
+.section s3tqb
+.section s3tra
+.section s3trb
+.section s3tsa
+.section s3tsb
+.section s3tta
+.section s3ttb
+.section s3tua
+.section s3tub
+.section s3tva
+.section s3tvb
+.section s3twa
+.section s3twb
+.section s3txa
+.section s3txb
+.section s3tya
+.section s3tyb
+.section s3tza
+.section s3tzb
+.section s3t1a
+.section s3t1b
+.section s3t2a
+.section s3t2b
+.section s3t3a
+.section s3t3b
+.section s3t4a
+.section s3t4b
+.section s3t5a
+.section s3t5b
+.section s3t6a
+.section s3t6b
+.section s3t7a
+.section s3t7b
+.section s3t8a
+.section s3t8b
+.section s3t9a
+.section s3t9b
+.section s3t0a
+.section s3t0b
+.section s3uaa
+.section s3uab
+.section s3uba
+.section s3ubb
+.section s3uca
+.section s3ucb
+.section s3uda
+.section s3udb
+.section s3uea
+.section s3ueb
+.section s3ufa
+.section s3ufb
+.section s3uga
+.section s3ugb
+.section s3uha
+.section s3uhb
+.section s3uia
+.section s3uib
+.section s3uja
+.section s3ujb
+.section s3uka
+.section s3ukb
+.section s3ula
+.section s3ulb
+.section s3uma
+.section s3umb
+.section s3una
+.section s3unb
+.section s3uoa
+.section s3uob
+.section s3upa
+.section s3upb
+.section s3uqa
+.section s3uqb
+.section s3ura
+.section s3urb
+.section s3usa
+.section s3usb
+.section s3uta
+.section s3utb
+.section s3uua
+.section s3uub
+.section s3uva
+.section s3uvb
+.section s3uwa
+.section s3uwb
+.section s3uxa
+.section s3uxb
+.section s3uya
+.section s3uyb
+.section s3uza
+.section s3uzb
+.section s3u1a
+.section s3u1b
+.section s3u2a
+.section s3u2b
+.section s3u3a
+.section s3u3b
+.section s3u4a
+.section s3u4b
+.section s3u5a
+.section s3u5b
+.section s3u6a
+.section s3u6b
+.section s3u7a
+.section s3u7b
+.section s3u8a
+.section s3u8b
+.section s3u9a
+.section s3u9b
+.section s3u0a
+.section s3u0b
+.section s3vaa
+.section s3vab
+.section s3vba
+.section s3vbb
+.section s3vca
+.section s3vcb
+.section s3vda
+.section s3vdb
+.section s3vea
+.section s3veb
+.section s3vfa
+.section s3vfb
+.section s3vga
+.section s3vgb
+.section s3vha
+.section s3vhb
+.section s3via
+.section s3vib
+.section s3vja
+.section s3vjb
+.section s3vka
+.section s3vkb
+.section s3vla
+.section s3vlb
+.section s3vma
+.section s3vmb
+.section s3vna
+.section s3vnb
+.section s3voa
+.section s3vob
+.section s3vpa
+.section s3vpb
+.section s3vqa
+.section s3vqb
+.section s3vra
+.section s3vrb
+.section s3vsa
+.section s3vsb
+.section s3vta
+.section s3vtb
+.section s3vua
+.section s3vub
+.section s3vva
+.section s3vvb
+.section s3vwa
+.section s3vwb
+.section s3vxa
+.section s3vxb
+.section s3vya
+.section s3vyb
+.section s3vza
+.section s3vzb
+.section s3v1a
+.section s3v1b
+.section s3v2a
+.section s3v2b
+.section s3v3a
+.section s3v3b
+.section s3v4a
+.section s3v4b
+.section s3v5a
+.section s3v5b
+.section s3v6a
+.section s3v6b
+.section s3v7a
+.section s3v7b
+.section s3v8a
+.section s3v8b
+.section s3v9a
+.section s3v9b
+.section s3v0a
+.section s3v0b
+.section s3waa
+.section s3wab
+.section s3wba
+.section s3wbb
+.section s3wca
+.section s3wcb
+.section s3wda
+.section s3wdb
+.section s3wea
+.section s3web
+.section s3wfa
+.section s3wfb
+.section s3wga
+.section s3wgb
+.section s3wha
+.section s3whb
+.section s3wia
+.section s3wib
+.section s3wja
+.section s3wjb
+.section s3wka
+.section s3wkb
+.section s3wla
+.section s3wlb
+.section s3wma
+.section s3wmb
+.section s3wna
+.section s3wnb
+.section s3woa
+.section s3wob
+.section s3wpa
+.section s3wpb
+.section s3wqa
+.section s3wqb
+.section s3wra
+.section s3wrb
+.section s3wsa
+.section s3wsb
+.section s3wta
+.section s3wtb
+.section s3wua
+.section s3wub
+.section s3wva
+.section s3wvb
+.section s3wwa
+.section s3wwb
+.section s3wxa
+.section s3wxb
+.section s3wya
+.section s3wyb
+.section s3wza
+.section s3wzb
+.section s3w1a
+.section s3w1b
+.section s3w2a
+.section s3w2b
+.section s3w3a
+.section s3w3b
+.section s3w4a
+.section s3w4b
+.section s3w5a
+.section s3w5b
+.section s3w6a
+.section s3w6b
+.section s3w7a
+.section s3w7b
+.section s3w8a
+.section s3w8b
+.section s3w9a
+.section s3w9b
+.section s3w0a
+.section s3w0b
+.section s3xaa
+.section s3xab
+.section s3xba
+.section s3xbb
+.section s3xca
+.section s3xcb
+.section s3xda
+.section s3xdb
+.section s3xea
+.section s3xeb
+.section s3xfa
+.section s3xfb
+.section s3xga
+.section s3xgb
+.section s3xha
+.section s3xhb
+.section s3xia
+.section s3xib
+.section s3xja
+.section s3xjb
+.section s3xka
+.section s3xkb
+.section s3xla
+.section s3xlb
+.section s3xma
+.section s3xmb
+.section s3xna
+.section s3xnb
+.section s3xoa
+.section s3xob
+.section s3xpa
+.section s3xpb
+.section s3xqa
+.section s3xqb
+.section s3xra
+.section s3xrb
+.section s3xsa
+.section s3xsb
+.section s3xta
+.section s3xtb
+.section s3xua
+.section s3xub
+.section s3xva
+.section s3xvb
+.section s3xwa
+.section s3xwb
+.section s3xxa
+.section s3xxb
+.section s3xya
+.section s3xyb
+.section s3xza
+.section s3xzb
+.section s3x1a
+.section s3x1b
+.section s3x2a
+.section s3x2b
+.section s3x3a
+.section s3x3b
+.section s3x4a
+.section s3x4b
+.section s3x5a
+.section s3x5b
+.section s3x6a
+.section s3x6b
+.section s3x7a
+.section s3x7b
+.section s3x8a
+.section s3x8b
+.section s3x9a
+.section s3x9b
+.section s3x0a
+.section s3x0b
+.section s3yaa
+.section s3yab
+.section s3yba
+.section s3ybb
+.section s3yca
+.section s3ycb
+.section s3yda
+.section s3ydb
+.section s3yea
+.section s3yeb
+.section s3yfa
+.section s3yfb
+.section s3yga
+.section s3ygb
+.section s3yha
+.section s3yhb
+.section s3yia
+.section s3yib
+.section s3yja
+.section s3yjb
+.section s3yka
+.section s3ykb
+.section s3yla
+.section s3ylb
+.section s3yma
+.section s3ymb
+.section s3yna
+.section s3ynb
+.section s3yoa
+.section s3yob
+.section s3ypa
+.section s3ypb
+.section s3yqa
+.section s3yqb
+.section s3yra
+.section s3yrb
+.section s3ysa
+.section s3ysb
+.section s3yta
+.section s3ytb
+.section s3yua
+.section s3yub
+.section s3yva
+.section s3yvb
+.section s3ywa
+.section s3ywb
+.section s3yxa
+.section s3yxb
+.section s3yya
+.section s3yyb
+.section s3yza
+.section s3yzb
+.section s3y1a
+.section s3y1b
+.section s3y2a
+.section s3y2b
+.section s3y3a
+.section s3y3b
+.section s3y4a
+.section s3y4b
+.section s3y5a
+.section s3y5b
+.section s3y6a
+.section s3y6b
+.section s3y7a
+.section s3y7b
+.section s3y8a
+.section s3y8b
+.section s3y9a
+.section s3y9b
+.section s3y0a
+.section s3y0b
+.section s3zaa
+.section s3zab
+.section s3zba
+.section s3zbb
+.section s3zca
+.section s3zcb
+.section s3zda
+.section s3zdb
+.section s3zea
+.section s3zeb
+.section s3zfa
+.section s3zfb
+.section s3zga
+.section s3zgb
+.section s3zha
+.section s3zhb
+.section s3zia
+.section s3zib
+.section s3zja
+.section s3zjb
+.section s3zka
+.section s3zkb
+.section s3zla
+.section s3zlb
+.section s3zma
+.section s3zmb
+.section s3zna
+.section s3znb
+.section s3zoa
+.section s3zob
+.section s3zpa
+.section s3zpb
+.section s3zqa
+.section s3zqb
+.section s3zra
+.section s3zrb
+.section s3zsa
+.section s3zsb
+.section s3zta
+.section s3ztb
+.section s3zua
+.section s3zub
+.section s3zva
+.section s3zvb
+.section s3zwa
+.section s3zwb
+.section s3zxa
+.section s3zxb
+.section s3zya
+.section s3zyb
+.section s3zza
+.section s3zzb
+.section s3z1a
+.section s3z1b
+.section s3z2a
+.section s3z2b
+.section s3z3a
+.section s3z3b
+.section s3z4a
+.section s3z4b
+.section s3z5a
+.section s3z5b
+.section s3z6a
+.section s3z6b
+.section s3z7a
+.section s3z7b
+.section s3z8a
+.section s3z8b
+.section s3z9a
+.section s3z9b
+.section s3z0a
+.section s3z0b
+.section s31aa
+.section s31ab
+.section s31ba
+.section s31bb
+.section s31ca
+.section s31cb
+.section s31da
+.section s31db
+.section s31ea
+.section s31eb
+.section s31fa
+.section s31fb
+.section s31ga
+.section s31gb
+.section s31ha
+.section s31hb
+.section s31ia
+.section s31ib
+.section s31ja
+.section s31jb
+.section s31ka
+.section s31kb
+.section s31la
+.section s31lb
+.section s31ma
+.section s31mb
+.section s31na
+.section s31nb
+.section s31oa
+.section s31ob
+.section s31pa
+.section s31pb
+.section s31qa
+.section s31qb
+.section s31ra
+.section s31rb
+.section s31sa
+.section s31sb
+.section s31ta
+.section s31tb
+.section s31ua
+.section s31ub
+.section s31va
+.section s31vb
+.section s31wa
+.section s31wb
+.section s31xa
+.section s31xb
+.section s31ya
+.section s31yb
+.section s31za
+.section s31zb
+.section s311a
+.section s311b
+.section s312a
+.section s312b
+.section s313a
+.section s313b
+.section s314a
+.section s314b
+.section s315a
+.section s315b
+.section s316a
+.section s316b
+.section s317a
+.section s317b
+.section s318a
+.section s318b
+.section s319a
+.section s319b
+.section s310a
+.section s310b
+.section s32aa
+.section s32ab
+.section s32ba
+.section s32bb
+.section s32ca
+.section s32cb
+.section s32da
+.section s32db
+.section s32ea
+.section s32eb
+.section s32fa
+.section s32fb
+.section s32ga
+.section s32gb
+.section s32ha
+.section s32hb
+.section s32ia
+.section s32ib
+.section s32ja
+.section s32jb
+.section s32ka
+.section s32kb
+.section s32la
+.section s32lb
+.section s32ma
+.section s32mb
+.section s32na
+.section s32nb
+.section s32oa
+.section s32ob
+.section s32pa
+.section s32pb
+.section s32qa
+.section s32qb
+.section s32ra
+.section s32rb
+.section s32sa
+.section s32sb
+.section s32ta
+.section s32tb
+.section s32ua
+.section s32ub
+.section s32va
+.section s32vb
+.section s32wa
+.section s32wb
+.section s32xa
+.section s32xb
+.section s32ya
+.section s32yb
+.section s32za
+.section s32zb
+.section s321a
+.section s321b
+.section s322a
+.section s322b
+.section s323a
+.section s323b
+.section s324a
+.section s324b
+.section s325a
+.section s325b
+.section s326a
+.section s326b
+.section s327a
+.section s327b
+.section s328a
+.section s328b
+.section s329a
+.section s329b
+.section s320a
+.section s320b
+.section s33aa
+.section s33ab
+.section s33ba
+.section s33bb
+.section s33ca
+.section s33cb
+.section s33da
+.section s33db
+.section s33ea
+.section s33eb
+.section s33fa
+.section s33fb
+.section s33ga
+.section s33gb
+.section s33ha
+.section s33hb
+.section s33ia
+.section s33ib
+.section s33ja
+.section s33jb
+.section s33ka
+.section s33kb
+.section s33la
+.section s33lb
+.section s33ma
+.section s33mb
+.section s33na
+.section s33nb
+.section s33oa
+.section s33ob
+.section s33pa
+.section s33pb
+.section s33qa
+.section s33qb
+.section s33ra
+.section s33rb
+.section s33sa
+.section s33sb
+.section s33ta
+.section s33tb
+.section s33ua
+.section s33ub
+.section s33va
+.section s33vb
+.section s33wa
+.section s33wb
+.section s33xa
+.section s33xb
+.section s33ya
+.section s33yb
+.section s33za
+.section s33zb
+.section s331a
+.section s331b
+.section s332a
+.section s332b
+.section s333a
+.section s333b
+.section s334a
+.section s334b
+.section s335a
+.section s335b
+.section s336a
+.section s336b
+.section s337a
+.section s337b
+.section s338a
+.section s338b
+.section s339a
+.section s339b
+.section s330a
+.section s330b
+.section s34aa
+.section s34ab
+.section s34ba
+.section s34bb
+.section s34ca
+.section s34cb
+.section s34da
+.section s34db
+.section s34ea
+.section s34eb
+.section s34fa
+.section s34fb
+.section s34ga
+.section s34gb
+.section s34ha
+.section s34hb
+.section s34ia
+.section s34ib
+.section s34ja
+.section s34jb
+.section s34ka
+.section s34kb
+.section s34la
+.section s34lb
+.section s34ma
+.section s34mb
+.section s34na
+.section s34nb
+.section s34oa
+.section s34ob
+.section s34pa
+.section s34pb
+.section s34qa
+.section s34qb
+.section s34ra
+.section s34rb
+.section s34sa
+.section s34sb
+.section s34ta
+.section s34tb
+.section s34ua
+.section s34ub
+.section s34va
+.section s34vb
+.section s34wa
+.section s34wb
+.section s34xa
+.section s34xb
+.section s34ya
+.section s34yb
+.section s34za
+.section s34zb
+.section s341a
+.section s341b
+.section s342a
+.section s342b
+.section s343a
+.section s343b
+.section s344a
+.section s344b
+.section s345a
+.section s345b
+.section s346a
+.section s346b
+.section s347a
+.section s347b
+.section s348a
+.section s348b
+.section s349a
+.section s349b
+.section s340a
+.section s340b
+.section s35aa
+.section s35ab
+.section s35ba
+.section s35bb
+.section s35ca
+.section s35cb
+.section s35da
+.section s35db
+.section s35ea
+.section s35eb
+.section s35fa
+.section s35fb
+.section s35ga
+.section s35gb
+.section s35ha
+.section s35hb
+.section s35ia
+.section s35ib
+.section s35ja
+.section s35jb
+.section s35ka
+.section s35kb
+.section s35la
+.section s35lb
+.section s35ma
+.section s35mb
+.section s35na
+.section s35nb
+.section s35oa
+.section s35ob
+.section s35pa
+.section s35pb
+.section s35qa
+.section s35qb
+.section s35ra
+.section s35rb
+.section s35sa
+.section s35sb
+.section s35ta
+.section s35tb
+.section s35ua
+.section s35ub
+.section s35va
+.section s35vb
+.section s35wa
+.section s35wb
+.section s35xa
+.section s35xb
+.section s35ya
+.section s35yb
+.section s35za
+.section s35zb
+.section s351a
+.section s351b
+.section s352a
+.section s352b
+.section s353a
+.section s353b
+.section s354a
+.section s354b
+.section s355a
+.section s355b
+.section s356a
+.section s356b
+.section s357a
+.section s357b
+.section s358a
+.section s358b
+.section s359a
+.section s359b
+.section s350a
+.section s350b
+.section s36aa
+.section s36ab
+.section s36ba
+.section s36bb
+.section s36ca
+.section s36cb
+.section s36da
+.section s36db
+.section s36ea
+.section s36eb
+.section s36fa
+.section s36fb
+.section s36ga
+.section s36gb
+.section s36ha
+.section s36hb
+.section s36ia
+.section s36ib
+.section s36ja
+.section s36jb
+.section s36ka
+.section s36kb
+.section s36la
+.section s36lb
+.section s36ma
+.section s36mb
+.section s36na
+.section s36nb
+.section s36oa
+.section s36ob
+.section s36pa
+.section s36pb
+.section s36qa
+.section s36qb
+.section s36ra
+.section s36rb
+.section s36sa
+.section s36sb
+.section s36ta
+.section s36tb
+.section s36ua
+.section s36ub
+.section s36va
+.section s36vb
+.section s36wa
+.section s36wb
+.section s36xa
+.section s36xb
+.section s36ya
+.section s36yb
+.section s36za
+.section s36zb
+.section s361a
+.section s361b
+.section s362a
+.section s362b
+.section s363a
+.section s363b
+.section s364a
+.section s364b
+.section s365a
+.section s365b
+.section s366a
+.section s366b
+.section s367a
+.section s367b
+.section s368a
+.section s368b
+.section s369a
+.section s369b
+.section s360a
+.section s360b
+.section s37aa
+.section s37ab
+.section s37ba
+.section s37bb
+.section s37ca
+.section s37cb
+.section s37da
+.section s37db
+.section s37ea
+.section s37eb
+.section s37fa
+.section s37fb
+.section s37ga
+.section s37gb
+.section s37ha
+.section s37hb
+.section s37ia
+.section s37ib
+.section s37ja
+.section s37jb
+.section s37ka
+.section s37kb
+.section s37la
+.section s37lb
+.section s37ma
+.section s37mb
+.section s37na
+.section s37nb
+.section s37oa
+.section s37ob
+.section s37pa
+.section s37pb
+.section s37qa
+.section s37qb
+.section s37ra
+.section s37rb
+.section s37sa
+.section s37sb
+.section s37ta
+.section s37tb
+.section s37ua
+.section s37ub
+.section s37va
+.section s37vb
+.section s37wa
+.section s37wb
+.section s37xa
+.section s37xb
+.section s37ya
+.section s37yb
+.section s37za
+.section s37zb
+.section s371a
+.section s371b
+.section s372a
+.section s372b
+.section s373a
+.section s373b
+.section s374a
+.section s374b
+.section s375a
+.section s375b
+.section s376a
+.section s376b
+.section s377a
+.section s377b
+.section s378a
+.section s378b
+.section s379a
+.section s379b
+.section s370a
+.section s370b
+.section s38aa
+.section s38ab
+.section s38ba
+.section s38bb
+.section s38ca
+.section s38cb
+.section s38da
+.section s38db
+.section s38ea
+.section s38eb
+.section s38fa
+.section s38fb
+.section s38ga
+.section s38gb
+.section s38ha
+.section s38hb
+.section s38ia
+.section s38ib
+.section s38ja
+.section s38jb
+.section s38ka
+.section s38kb
+.section s38la
+.section s38lb
+.section s38ma
+.section s38mb
+.section s38na
+.section s38nb
+.section s38oa
+.section s38ob
+.section s38pa
+.section s38pb
+.section s38qa
+.section s38qb
+.section s38ra
+.section s38rb
+.section s38sa
+.section s38sb
+.section s38ta
+.section s38tb
+.section s38ua
+.section s38ub
+.section s38va
+.section s38vb
+.section s38wa
+.section s38wb
+.section s38xa
+.section s38xb
+.section s38ya
+.section s38yb
+.section s38za
+.section s38zb
+.section s381a
+.section s381b
+.section s382a
+.section s382b
+.section s383a
+.section s383b
+.section s384a
+.section s384b
+.section s385a
+.section s385b
+.section s386a
+.section s386b
+.section s387a
+.section s387b
+.section s388a
+.section s388b
+.section s389a
+.section s389b
+.section s380a
+.section s380b
+.section s39aa
+.section s39ab
+.section s39ba
+.section s39bb
+.section s39ca
+.section s39cb
+.section s39da
+.section s39db
+.section s39ea
+.section s39eb
+.section s39fa
+.section s39fb
+.section s39ga
+.section s39gb
+.section s39ha
+.section s39hb
+.section s39ia
+.section s39ib
+.section s39ja
+.section s39jb
+.section s39ka
+.section s39kb
+.section s39la
+.section s39lb
+.section s39ma
+.section s39mb
+.section s39na
+.section s39nb
+.section s39oa
+.section s39ob
+.section s39pa
+.section s39pb
+.section s39qa
+.section s39qb
+.section s39ra
+.section s39rb
+.section s39sa
+.section s39sb
+.section s39ta
+.section s39tb
+.section s39ua
+.section s39ub
+.section s39va
+.section s39vb
+.section s39wa
+.section s39wb
+.section s39xa
+.section s39xb
+.section s39ya
+.section s39yb
+.section s39za
+.section s39zb
+.section s391a
+.section s391b
+.section s392a
+.section s392b
+.section s393a
+.section s393b
+.section s394a
+.section s394b
+.section s395a
+.section s395b
+.section s396a
+.section s396b
+.section s397a
+.section s397b
+.section s398a
+.section s398b
+.section s399a
+.section s399b
+.section s390a
+.section s390b
+.section s30aa
+.section s30ab
+.section s30ba
+.section s30bb
+.section s30ca
+.section s30cb
+.section s30da
+.section s30db
+.section s30ea
+.section s30eb
+.section s30fa
+.section s30fb
+.section s30ga
+.section s30gb
+.section s30ha
+.section s30hb
+.section s30ia
+.section s30ib
+.section s30ja
+.section s30jb
+.section s30ka
+.section s30kb
+.section s30la
+.section s30lb
+.section s30ma
+.section s30mb
+.section s30na
+.section s30nb
+.section s30oa
+.section s30ob
+.section s30pa
+.section s30pb
+.section s30qa
+.section s30qb
+.section s30ra
+.section s30rb
+.section s30sa
+.section s30sb
+.section s30ta
+.section s30tb
+.section s30ua
+.section s30ub
+.section s30va
+.section s30vb
+.section s30wa
+.section s30wb
+.section s30xa
+.section s30xb
+.section s30ya
+.section s30yb
+.section s30za
+.section s30zb
+.section s301a
+.section s301b
+.section s302a
+.section s302b
+.section s303a
+.section s303b
+.section s304a
+.section s304b
+.section s305a
+.section s305b
+.section s306a
+.section s306b
+.section s307a
+.section s307b
+.section s308a
+.section s308b
+.section s309a
+.section s309b
+.section s300a
+.section s300b
+.section s4aaa
+.section s4aab
+.section s4aba
+.section s4abb
+.section s4aca
+.section s4acb
+.section s4ada
+.section s4adb
+.section s4aea
+.section s4aeb
+.section s4afa
+.section s4afb
+.section s4aga
+.section s4agb
+.section s4aha
+.section s4ahb
+.section s4aia
+.section s4aib
+.section s4aja
+.section s4ajb
+.section s4aka
+.section s4akb
+.section s4ala
+.section s4alb
+.section s4ama
+.section s4amb
+.section s4ana
+.section s4anb
+.section s4aoa
+.section s4aob
+.section s4apa
+.section s4apb
+.section s4aqa
+.section s4aqb
+.section s4ara
+.section s4arb
+.section s4asa
+.section s4asb
+.section s4ata
+.section s4atb
+.section s4aua
+.section s4aub
+.section s4ava
+.section s4avb
+.section s4awa
+.section s4awb
+.section s4axa
+.section s4axb
+.section s4aya
+.section s4ayb
+.section s4aza
+.section s4azb
+.section s4a1a
+.section s4a1b
+.section s4a2a
+.section s4a2b
+.section s4a3a
+.section s4a3b
+.section s4a4a
+.section s4a4b
+.section s4a5a
+.section s4a5b
+.section s4a6a
+.section s4a6b
+.section s4a7a
+.section s4a7b
+.section s4a8a
+.section s4a8b
+.section s4a9a
+.section s4a9b
+.section s4a0a
+.section s4a0b
+.section s4baa
+.section s4bab
+.section s4bba
+.section s4bbb
+.section s4bca
+.section s4bcb
+.section s4bda
+.section s4bdb
+.section s4bea
+.section s4beb
+.section s4bfa
+.section s4bfb
+.section s4bga
+.section s4bgb
+.section s4bha
+.section s4bhb
+.section s4bia
+.section s4bib
+.section s4bja
+.section s4bjb
+.section s4bka
+.section s4bkb
+.section s4bla
+.section s4blb
+.section s4bma
+.section s4bmb
+.section s4bna
+.section s4bnb
+.section s4boa
+.section s4bob
+.section s4bpa
+.section s4bpb
+.section s4bqa
+.section s4bqb
+.section s4bra
+.section s4brb
+.section s4bsa
+.section s4bsb
+.section s4bta
+.section s4btb
+.section s4bua
+.section s4bub
+.section s4bva
+.section s4bvb
+.section s4bwa
+.section s4bwb
+.section s4bxa
+.section s4bxb
+.section s4bya
+.section s4byb
+.section s4bza
+.section s4bzb
+.section s4b1a
+.section s4b1b
+.section s4b2a
+.section s4b2b
+.section s4b3a
+.section s4b3b
+.section s4b4a
+.section s4b4b
+.section s4b5a
+.section s4b5b
+.section s4b6a
+.section s4b6b
+.section s4b7a
+.section s4b7b
+.section s4b8a
+.section s4b8b
+.section s4b9a
+.section s4b9b
+.section s4b0a
+.section s4b0b
+.section s4caa
+.section s4cab
+.section s4cba
+.section s4cbb
+.section s4cca
+.section s4ccb
+.section s4cda
+.section s4cdb
+.section s4cea
+.section s4ceb
+.section s4cfa
+.section s4cfb
+.section s4cga
+.section s4cgb
+.section s4cha
+.section s4chb
+.section s4cia
+.section s4cib
+.section s4cja
+.section s4cjb
+.section s4cka
+.section s4ckb
+.section s4cla
+.section s4clb
+.section s4cma
+.section s4cmb
+.section s4cna
+.section s4cnb
+.section s4coa
+.section s4cob
+.section s4cpa
+.section s4cpb
+.section s4cqa
+.section s4cqb
+.section s4cra
+.section s4crb
+.section s4csa
+.section s4csb
+.section s4cta
+.section s4ctb
+.section s4cua
+.section s4cub
+.section s4cva
+.section s4cvb
+.section s4cwa
+.section s4cwb
+.section s4cxa
+.section s4cxb
+.section s4cya
+.section s4cyb
+.section s4cza
+.section s4czb
+.section s4c1a
+.section s4c1b
+.section s4c2a
+.section s4c2b
+.section s4c3a
+.section s4c3b
+.section s4c4a
+.section s4c4b
+.section s4c5a
+.section s4c5b
+.section s4c6a
+.section s4c6b
+.section s4c7a
+.section s4c7b
+.section s4c8a
+.section s4c8b
+.section s4c9a
+.section s4c9b
+.section s4c0a
+.section s4c0b
+.section s4daa
+.section s4dab
+.section s4dba
+.section s4dbb
+.section s4dca
+.section s4dcb
+.section s4dda
+.section s4ddb
+.section s4dea
+.section s4deb
+.section s4dfa
+.section s4dfb
+.section s4dga
+.section s4dgb
+.section s4dha
+.section s4dhb
+.section s4dia
+.section s4dib
+.section s4dja
+.section s4djb
+.section s4dka
+.section s4dkb
+.section s4dla
+.section s4dlb
+.section s4dma
+.section s4dmb
+.section s4dna
+.section s4dnb
+.section s4doa
+.section s4dob
+.section s4dpa
+.section s4dpb
+.section s4dqa
+.section s4dqb
+.section s4dra
+.section s4drb
+.section s4dsa
+.section s4dsb
+.section s4dta
+.section s4dtb
+.section s4dua
+.section s4dub
+.section s4dva
+.section s4dvb
+.section s4dwa
+.section s4dwb
+.section s4dxa
+.section s4dxb
+.section s4dya
+.section s4dyb
+.section s4dza
+.section s4dzb
+.section s4d1a
+.section s4d1b
+.section s4d2a
+.section s4d2b
+.section s4d3a
+.section s4d3b
+.section s4d4a
+.section s4d4b
+.section s4d5a
+.section s4d5b
+.section s4d6a
+.section s4d6b
+.section s4d7a
+.section s4d7b
+.section s4d8a
+.section s4d8b
+.section s4d9a
+.section s4d9b
+.section s4d0a
+.section s4d0b
+.section s4eaa
+.section s4eab
+.section s4eba
+.section s4ebb
+.section s4eca
+.section s4ecb
+.section s4eda
+.section s4edb
+.section s4eea
+.section s4eeb
+.section s4efa
+.section s4efb
+.section s4ega
+.section s4egb
+.section s4eha
+.section s4ehb
+.section s4eia
+.section s4eib
+.section s4eja
+.section s4ejb
+.section s4eka
+.section s4ekb
+.section s4ela
+.section s4elb
+.section s4ema
+.section s4emb
+.section s4ena
+.section s4enb
+.section s4eoa
+.section s4eob
+.section s4epa
+.section s4epb
+.section s4eqa
+.section s4eqb
+.section s4era
+.section s4erb
+.section s4esa
+.section s4esb
+.section s4eta
+.section s4etb
+.section s4eua
+.section s4eub
+.section s4eva
+.section s4evb
+.section s4ewa
+.section s4ewb
+.section s4exa
+.section s4exb
+.section s4eya
+.section s4eyb
+.section s4eza
+.section s4ezb
+.section s4e1a
+.section s4e1b
+.section s4e2a
+.section s4e2b
+.section s4e3a
+.section s4e3b
+.section s4e4a
+.section s4e4b
+.section s4e5a
+.section s4e5b
+.section s4e6a
+.section s4e6b
+.section s4e7a
+.section s4e7b
+.section s4e8a
+.section s4e8b
+.section s4e9a
+.section s4e9b
+.section s4e0a
+.section s4e0b
+.section s4faa
+.section s4fab
+.section s4fba
+.section s4fbb
+.section s4fca
+.section s4fcb
+.section s4fda
+.section s4fdb
+.section s4fea
+.section s4feb
+.section s4ffa
+.section s4ffb
+.section s4fga
+.section s4fgb
+.section s4fha
+.section s4fhb
+.section s4fia
+.section s4fib
+.section s4fja
+.section s4fjb
+.section s4fka
+.section s4fkb
+.section s4fla
+.section s4flb
+.section s4fma
+.section s4fmb
+.section s4fna
+.section s4fnb
+.section s4foa
+.section s4fob
+.section s4fpa
+.section s4fpb
+.section s4fqa
+.section s4fqb
+.section s4fra
+.section s4frb
+.section s4fsa
+.section s4fsb
+.section s4fta
+.section s4ftb
+.section s4fua
+.section s4fub
+.section s4fva
+.section s4fvb
+.section s4fwa
+.section s4fwb
+.section s4fxa
+.section s4fxb
+.section s4fya
+.section s4fyb
+.section s4fza
+.section s4fzb
+.section s4f1a
+.section s4f1b
+.section s4f2a
+.section s4f2b
+.section s4f3a
+.section s4f3b
+.section s4f4a
+.section s4f4b
+.section s4f5a
+.section s4f5b
+.section s4f6a
+.section s4f6b
+.section s4f7a
+.section s4f7b
+.section s4f8a
+.section s4f8b
+.section s4f9a
+.section s4f9b
+.section s4f0a
+.section s4f0b
+.section s4gaa
+.section s4gab
+.section s4gba
+.section s4gbb
+.section s4gca
+.section s4gcb
+.section s4gda
+.section s4gdb
+.section s4gea
+.section s4geb
+.section s4gfa
+.section s4gfb
+.section s4gga
+.section s4ggb
+.section s4gha
+.section s4ghb
+.section s4gia
+.section s4gib
+.section s4gja
+.section s4gjb
+.section s4gka
+.section s4gkb
+.section s4gla
+.section s4glb
+.section s4gma
+.section s4gmb
+.section s4gna
+.section s4gnb
+.section s4goa
+.section s4gob
+.section s4gpa
+.section s4gpb
+.section s4gqa
+.section s4gqb
+.section s4gra
+.section s4grb
+.section s4gsa
+.section s4gsb
+.section s4gta
+.section s4gtb
+.section s4gua
+.section s4gub
+.section s4gva
+.section s4gvb
+.section s4gwa
+.section s4gwb
+.section s4gxa
+.section s4gxb
+.section s4gya
+.section s4gyb
+.section s4gza
+.section s4gzb
+.section s4g1a
+.section s4g1b
+.section s4g2a
+.section s4g2b
+.section s4g3a
+.section s4g3b
+.section s4g4a
+.section s4g4b
+.section s4g5a
+.section s4g5b
+.section s4g6a
+.section s4g6b
+.section s4g7a
+.section s4g7b
+.section s4g8a
+.section s4g8b
+.section s4g9a
+.section s4g9b
+.section s4g0a
+.section s4g0b
+.section s4haa
+.section s4hab
+.section s4hba
+.section s4hbb
+.section s4hca
+.section s4hcb
+.section s4hda
+.section s4hdb
+.section s4hea
+.section s4heb
+.section s4hfa
+.section s4hfb
+.section s4hga
+.section s4hgb
+.section s4hha
+.section s4hhb
+.section s4hia
+.section s4hib
+.section s4hja
+.section s4hjb
+.section s4hka
+.section s4hkb
+.section s4hla
+.section s4hlb
+.section s4hma
+.section s4hmb
+.section s4hna
+.section s4hnb
+.section s4hoa
+.section s4hob
+.section s4hpa
+.section s4hpb
+.section s4hqa
+.section s4hqb
+.section s4hra
+.section s4hrb
+.section s4hsa
+.section s4hsb
+.section s4hta
+.section s4htb
+.section s4hua
+.section s4hub
+.section s4hva
+.section s4hvb
+.section s4hwa
+.section s4hwb
+.section s4hxa
+.section s4hxb
+.section s4hya
+.section s4hyb
+.section s4hza
+.section s4hzb
+.section s4h1a
+.section s4h1b
+.section s4h2a
+.section s4h2b
+.section s4h3a
+.section s4h3b
+.section s4h4a
+.section s4h4b
+.section s4h5a
+.section s4h5b
+.section s4h6a
+.section s4h6b
+.section s4h7a
+.section s4h7b
+.section s4h8a
+.section s4h8b
+.section s4h9a
+.section s4h9b
+.section s4h0a
+.section s4h0b
+.section s4iaa
+.section s4iab
+.section s4iba
+.section s4ibb
+.section s4ica
+.section s4icb
+.section s4ida
+.section s4idb
+.section s4iea
+.section s4ieb
+.section s4ifa
+.section s4ifb
+.section s4iga
+.section s4igb
+.section s4iha
+.section s4ihb
+.section s4iia
+.section s4iib
+.section s4ija
+.section s4ijb
+.section s4ika
+.section s4ikb
+.section s4ila
+.section s4ilb
+.section s4ima
+.section s4imb
+.section s4ina
+.section s4inb
+.section s4ioa
+.section s4iob
+.section s4ipa
+.section s4ipb
+.section s4iqa
+.section s4iqb
+.section s4ira
+.section s4irb
+.section s4isa
+.section s4isb
+.section s4ita
+.section s4itb
+.section s4iua
+.section s4iub
+.section s4iva
+.section s4ivb
+.section s4iwa
+.section s4iwb
+.section s4ixa
+.section s4ixb
+.section s4iya
+.section s4iyb
+.section s4iza
+.section s4izb
+.section s4i1a
+.section s4i1b
+.section s4i2a
+.section s4i2b
+.section s4i3a
+.section s4i3b
+.section s4i4a
+.section s4i4b
+.section s4i5a
+.section s4i5b
+.section s4i6a
+.section s4i6b
+.section s4i7a
+.section s4i7b
+.section s4i8a
+.section s4i8b
+.section s4i9a
+.section s4i9b
+.section s4i0a
+.section s4i0b
+.section s4jaa
+.section s4jab
+.section s4jba
+.section s4jbb
+.section s4jca
+.section s4jcb
+.section s4jda
+.section s4jdb
+.section s4jea
+.section s4jeb
+.section s4jfa
+.section s4jfb
+.section s4jga
+.section s4jgb
+.section s4jha
+.section s4jhb
+.section s4jia
+.section s4jib
+.section s4jja
+.section s4jjb
+.section s4jka
+.section s4jkb
+.section s4jla
+.section s4jlb
+.section s4jma
+.section s4jmb
+.section s4jna
+.section s4jnb
+.section s4joa
+.section s4job
+.section s4jpa
+.section s4jpb
+.section s4jqa
+.section s4jqb
+.section s4jra
+.section s4jrb
+.section s4jsa
+.section s4jsb
+.section s4jta
+.section s4jtb
+.section s4jua
+.section s4jub
+.section s4jva
+.section s4jvb
+.section s4jwa
+.section s4jwb
+.section s4jxa
+.section s4jxb
+.section s4jya
+.section s4jyb
+.section s4jza
+.section s4jzb
+.section s4j1a
+.section s4j1b
+.section s4j2a
+.section s4j2b
+.section s4j3a
+.section s4j3b
+.section s4j4a
+.section s4j4b
+.section s4j5a
+.section s4j5b
+.section s4j6a
+.section s4j6b
+.section s4j7a
+.section s4j7b
+.section s4j8a
+.section s4j8b
+.section s4j9a
+.section s4j9b
+.section s4j0a
+.section s4j0b
+.section s4kaa
+.section s4kab
+.section s4kba
+.section s4kbb
+.section s4kca
+.section s4kcb
+.section s4kda
+.section s4kdb
+.section s4kea
+.section s4keb
+.section s4kfa
+.section s4kfb
+.section s4kga
+.section s4kgb
+.section s4kha
+.section s4khb
+.section s4kia
+.section s4kib
+.section s4kja
+.section s4kjb
+.section s4kka
+.section s4kkb
+.section s4kla
+.section s4klb
+.section s4kma
+.section s4kmb
+.section s4kna
+.section s4knb
+.section s4koa
+.section s4kob
+.section s4kpa
+.section s4kpb
+.section s4kqa
+.section s4kqb
+.section s4kra
+.section s4krb
+.section s4ksa
+.section s4ksb
+.section s4kta
+.section s4ktb
+.section s4kua
+.section s4kub
+.section s4kva
+.section s4kvb
+.section s4kwa
+.section s4kwb
+.section s4kxa
+.section s4kxb
+.section s4kya
+.section s4kyb
+.section s4kza
+.section s4kzb
+.section s4k1a
+.section s4k1b
+.section s4k2a
+.section s4k2b
+.section s4k3a
+.section s4k3b
+.section s4k4a
+.section s4k4b
+.section s4k5a
+.section s4k5b
+.section s4k6a
+.section s4k6b
+.section s4k7a
+.section s4k7b
+.section s4k8a
+.section s4k8b
+.section s4k9a
+.section s4k9b
+.section s4k0a
+.section s4k0b
+.section s4laa
+.section s4lab
+.section s4lba
+.section s4lbb
+.section s4lca
+.section s4lcb
+.section s4lda
+.section s4ldb
+.section s4lea
+.section s4leb
+.section s4lfa
+.section s4lfb
+.section s4lga
+.section s4lgb
+.section s4lha
+.section s4lhb
+.section s4lia
+.section s4lib
+.section s4lja
+.section s4ljb
+.section s4lka
+.section s4lkb
+.section s4lla
+.section s4llb
+.section s4lma
+.section s4lmb
+.section s4lna
+.section s4lnb
+.section s4loa
+.section s4lob
+.section s4lpa
+.section s4lpb
+.section s4lqa
+.section s4lqb
+.section s4lra
+.section s4lrb
+.section s4lsa
+.section s4lsb
+.section s4lta
+.section s4ltb
+.section s4lua
+.section s4lub
+.section s4lva
+.section s4lvb
+.section s4lwa
+.section s4lwb
+.section s4lxa
+.section s4lxb
+.section s4lya
+.section s4lyb
+.section s4lza
+.section s4lzb
+.section s4l1a
+.section s4l1b
+.section s4l2a
+.section s4l2b
+.section s4l3a
+.section s4l3b
+.section s4l4a
+.section s4l4b
+.section s4l5a
+.section s4l5b
+.section s4l6a
+.section s4l6b
+.section s4l7a
+.section s4l7b
+.section s4l8a
+.section s4l8b
+.section s4l9a
+.section s4l9b
+.section s4l0a
+.section s4l0b
+.section s4maa
+.section s4mab
+.section s4mba
+.section s4mbb
+.section s4mca
+.section s4mcb
+.section s4mda
+.section s4mdb
+.section s4mea
+.section s4meb
+.section s4mfa
+.section s4mfb
+.section s4mga
+.section s4mgb
+.section s4mha
+.section s4mhb
+.section s4mia
+.section s4mib
+.section s4mja
+.section s4mjb
+.section s4mka
+.section s4mkb
+.section s4mla
+.section s4mlb
+.section s4mma
+.section s4mmb
+.section s4mna
+.section s4mnb
+.section s4moa
+.section s4mob
+.section s4mpa
+.section s4mpb
+.section s4mqa
+.section s4mqb
+.section s4mra
+.section s4mrb
+.section s4msa
+.section s4msb
+.section s4mta
+.section s4mtb
+.section s4mua
+.section s4mub
+.section s4mva
+.section s4mvb
+.section s4mwa
+.section s4mwb
+.section s4mxa
+.section s4mxb
+.section s4mya
+.section s4myb
+.section s4mza
+.section s4mzb
+.section s4m1a
+.section s4m1b
+.section s4m2a
+.section s4m2b
+.section s4m3a
+.section s4m3b
+.section s4m4a
+.section s4m4b
+.section s4m5a
+.section s4m5b
+.section s4m6a
+.section s4m6b
+.section s4m7a
+.section s4m7b
+.section s4m8a
+.section s4m8b
+.section s4m9a
+.section s4m9b
+.section s4m0a
+.section s4m0b
+.section s4naa
+.section s4nab
+.section s4nba
+.section s4nbb
+.section s4nca
+.section s4ncb
+.section s4nda
+.section s4ndb
+.section s4nea
+.section s4neb
+.section s4nfa
+.section s4nfb
+.section s4nga
+.section s4ngb
+.section s4nha
+.section s4nhb
+.section s4nia
+.section s4nib
+.section s4nja
+.section s4njb
+.section s4nka
+.section s4nkb
+.section s4nla
+.section s4nlb
+.section s4nma
+.section s4nmb
+.section s4nna
+.section s4nnb
+.section s4noa
+.section s4nob
+.section s4npa
+.section s4npb
+.section s4nqa
+.section s4nqb
+.section s4nra
+.section s4nrb
+.section s4nsa
+.section s4nsb
+.section s4nta
+.section s4ntb
+.section s4nua
+.section s4nub
+.section s4nva
+.section s4nvb
+.section s4nwa
+.section s4nwb
+.section s4nxa
+.section s4nxb
+.section s4nya
+.section s4nyb
+.section s4nza
+.section s4nzb
+.section s4n1a
+.section s4n1b
+.section s4n2a
+.section s4n2b
+.section s4n3a
+.section s4n3b
+.section s4n4a
+.section s4n4b
+.section s4n5a
+.section s4n5b
+.section s4n6a
+.section s4n6b
+.section s4n7a
+.section s4n7b
+.section s4n8a
+.section s4n8b
+.section s4n9a
+.section s4n9b
+.section s4n0a
+.section s4n0b
+.section s4oaa
+.section s4oab
+.section s4oba
+.section s4obb
+.section s4oca
+.section s4ocb
+.section s4oda
+.section s4odb
+.section s4oea
+.section s4oeb
+.section s4ofa
+.section s4ofb
+.section s4oga
+.section s4ogb
+.section s4oha
+.section s4ohb
+.section s4oia
+.section s4oib
+.section s4oja
+.section s4ojb
+.section s4oka
+.section s4okb
+.section s4ola
+.section s4olb
+.section s4oma
+.section s4omb
+.section s4ona
+.section s4onb
+.section s4ooa
+.section s4oob
+.section s4opa
+.section s4opb
+.section s4oqa
+.section s4oqb
+.section s4ora
+.section s4orb
+.section s4osa
+.section s4osb
+.section s4ota
+.section s4otb
+.section s4oua
+.section s4oub
+.section s4ova
+.section s4ovb
+.section s4owa
+.section s4owb
+.section s4oxa
+.section s4oxb
+.section s4oya
+.section s4oyb
+.section s4oza
+.section s4ozb
+.section s4o1a
+.section s4o1b
+.section s4o2a
+.section s4o2b
+.section s4o3a
+.section s4o3b
+.section s4o4a
+.section s4o4b
+.section s4o5a
+.section s4o5b
+.section s4o6a
+.section s4o6b
+.section s4o7a
+.section s4o7b
+.section s4o8a
+.section s4o8b
+.section s4o9a
+.section s4o9b
+.section s4o0a
+.section s4o0b
+.section s4paa
+.section s4pab
+.section s4pba
+.section s4pbb
+.section s4pca
+.section s4pcb
+.section s4pda
+.section s4pdb
+.section s4pea
+.section s4peb
+.section s4pfa
+.section s4pfb
+.section s4pga
+.section s4pgb
+.section s4pha
+.section s4phb
+.section s4pia
+.section s4pib
+.section s4pja
+.section s4pjb
+.section s4pka
+.section s4pkb
+.section s4pla
+.section s4plb
+.section s4pma
+.section s4pmb
+.section s4pna
+.section s4pnb
+.section s4poa
+.section s4pob
+.section s4ppa
+.section s4ppb
+.section s4pqa
+.section s4pqb
+.section s4pra
+.section s4prb
+.section s4psa
+.section s4psb
+.section s4pta
+.section s4ptb
+.section s4pua
+.section s4pub
+.section s4pva
+.section s4pvb
+.section s4pwa
+.section s4pwb
+.section s4pxa
+.section s4pxb
+.section s4pya
+.section s4pyb
+.section s4pza
+.section s4pzb
+.section s4p1a
+.section s4p1b
+.section s4p2a
+.section s4p2b
+.section s4p3a
+.section s4p3b
+.section s4p4a
+.section s4p4b
+.section s4p5a
+.section s4p5b
+.section s4p6a
+.section s4p6b
+.section s4p7a
+.section s4p7b
+.section s4p8a
+.section s4p8b
+.section s4p9a
+.section s4p9b
+.section s4p0a
+.section s4p0b
+.section s4qaa
+.section s4qab
+.section s4qba
+.section s4qbb
+.section s4qca
+.section s4qcb
+.section s4qda
+.section s4qdb
+.section s4qea
+.section s4qeb
+.section s4qfa
+.section s4qfb
+.section s4qga
+.section s4qgb
+.section s4qha
+.section s4qhb
+.section s4qia
+.section s4qib
+.section s4qja
+.section s4qjb
+.section s4qka
+.section s4qkb
+.section s4qla
+.section s4qlb
+.section s4qma
+.section s4qmb
+.section s4qna
+.section s4qnb
+.section s4qoa
+.section s4qob
+.section s4qpa
+.section s4qpb
+.section s4qqa
+.section s4qqb
+.section s4qra
+.section s4qrb
+.section s4qsa
+.section s4qsb
+.section s4qta
+.section s4qtb
+.section s4qua
+.section s4qub
+.section s4qva
+.section s4qvb
+.section s4qwa
+.section s4qwb
+.section s4qxa
+.section s4qxb
+.section s4qya
+.section s4qyb
+.section s4qza
+.section s4qzb
+.section s4q1a
+.section s4q1b
+.section s4q2a
+.section s4q2b
+.section s4q3a
+.section s4q3b
+.section s4q4a
+.section s4q4b
+.section s4q5a
+.section s4q5b
+.section s4q6a
+.section s4q6b
+.section s4q7a
+.section s4q7b
+.section s4q8a
+.section s4q8b
+.section s4q9a
+.section s4q9b
+.section s4q0a
+.section s4q0b
+.section s4raa
+.section s4rab
+.section s4rba
+.section s4rbb
+.section s4rca
+.section s4rcb
+.section s4rda
+.section s4rdb
+.section s4rea
+.section s4reb
+.section s4rfa
+.section s4rfb
+.section s4rga
+.section s4rgb
+.section s4rha
+.section s4rhb
+.section s4ria
+.section s4rib
+.section s4rja
+.section s4rjb
+.section s4rka
+.section s4rkb
+.section s4rla
+.section s4rlb
+.section s4rma
+.section s4rmb
+.section s4rna
+.section s4rnb
+.section s4roa
+.section s4rob
+.section s4rpa
+.section s4rpb
+.section s4rqa
+.section s4rqb
+.section s4rra
+.section s4rrb
+.section s4rsa
+.section s4rsb
+.section s4rta
+.section s4rtb
+.section s4rua
+.section s4rub
+.section s4rva
+.section s4rvb
+.section s4rwa
+.section s4rwb
+.section s4rxa
+.section s4rxb
+.section s4rya
+.section s4ryb
+.section s4rza
+.section s4rzb
+.section s4r1a
+.section s4r1b
+.section s4r2a
+.section s4r2b
+.section s4r3a
+.section s4r3b
+.section s4r4a
+.section s4r4b
+.section s4r5a
+.section s4r5b
+.section s4r6a
+.section s4r6b
+.section s4r7a
+.section s4r7b
+.section s4r8a
+.section s4r8b
+.section s4r9a
+.section s4r9b
+.section s4r0a
+.section s4r0b
+.section s4saa
+.section s4sab
+.section s4sba
+.section s4sbb
+.section s4sca
+.section s4scb
+.section s4sda
+.section s4sdb
+.section s4sea
+.section s4seb
+.section s4sfa
+.section s4sfb
+.section s4sga
+.section s4sgb
+.section s4sha
+.section s4shb
+.section s4sia
+.section s4sib
+.section s4sja
+.section s4sjb
+.section s4ska
+.section s4skb
+.section s4sla
+.section s4slb
+.section s4sma
+.section s4smb
+.section s4sna
+.section s4snb
+.section s4soa
+.section s4sob
+.section s4spa
+.section s4spb
+.section s4sqa
+.section s4sqb
+.section s4sra
+.section s4srb
+.section s4ssa
+.section s4ssb
+.section s4sta
+.section s4stb
+.section s4sua
+.section s4sub
+.section s4sva
+.section s4svb
+.section s4swa
+.section s4swb
+.section s4sxa
+.section s4sxb
+.section s4sya
+.section s4syb
+.section s4sza
+.section s4szb
+.section s4s1a
+.section s4s1b
+.section s4s2a
+.section s4s2b
+.section s4s3a
+.section s4s3b
+.section s4s4a
+.section s4s4b
+.section s4s5a
+.section s4s5b
+.section s4s6a
+.section s4s6b
+.section s4s7a
+.section s4s7b
+.section s4s8a
+.section s4s8b
+.section s4s9a
+.section s4s9b
+.section s4s0a
+.section s4s0b
+.section s4taa
+.section s4tab
+.section s4tba
+.section s4tbb
+.section s4tca
+.section s4tcb
+.section s4tda
+.section s4tdb
+.section s4tea
+.section s4teb
+.section s4tfa
+.section s4tfb
+.section s4tga
+.section s4tgb
+.section s4tha
+.section s4thb
+.section s4tia
+.section s4tib
+.section s4tja
+.section s4tjb
+.section s4tka
+.section s4tkb
+.section s4tla
+.section s4tlb
+.section s4tma
+.section s4tmb
+.section s4tna
+.section s4tnb
+.section s4toa
+.section s4tob
+.section s4tpa
+.section s4tpb
+.section s4tqa
+.section s4tqb
+.section s4tra
+.section s4trb
+.section s4tsa
+.section s4tsb
+.section s4tta
+.section s4ttb
+.section s4tua
+.section s4tub
+.section s4tva
+.section s4tvb
+.section s4twa
+.section s4twb
+.section s4txa
+.section s4txb
+.section s4tya
+.section s4tyb
+.section s4tza
+.section s4tzb
+.section s4t1a
+.section s4t1b
+.section s4t2a
+.section s4t2b
+.section s4t3a
+.section s4t3b
+.section s4t4a
+.section s4t4b
+.section s4t5a
+.section s4t5b
+.section s4t6a
+.section s4t6b
+.section s4t7a
+.section s4t7b
+.section s4t8a
+.section s4t8b
+.section s4t9a
+.section s4t9b
+.section s4t0a
+.section s4t0b
+.section s4uaa
+.section s4uab
+.section s4uba
+.section s4ubb
+.section s4uca
+.section s4ucb
+.section s4uda
+.section s4udb
+.section s4uea
+.section s4ueb
+.section s4ufa
+.section s4ufb
+.section s4uga
+.section s4ugb
+.section s4uha
+.section s4uhb
+.section s4uia
+.section s4uib
+.section s4uja
+.section s4ujb
+.section s4uka
+.section s4ukb
+.section s4ula
+.section s4ulb
+.section s4uma
+.section s4umb
+.section s4una
+.section s4unb
+.section s4uoa
+.section s4uob
+.section s4upa
+.section s4upb
+.section s4uqa
+.section s4uqb
+.section s4ura
+.section s4urb
+.section s4usa
+.section s4usb
+.section s4uta
+.section s4utb
+.section s4uua
+.section s4uub
+.section s4uva
+.section s4uvb
+.section s4uwa
+.section s4uwb
+.section s4uxa
+.section s4uxb
+.section s4uya
+.section s4uyb
+.section s4uza
+.section s4uzb
+.section s4u1a
+.section s4u1b
+.section s4u2a
+.section s4u2b
+.section s4u3a
+.section s4u3b
+.section s4u4a
+.section s4u4b
+.section s4u5a
+.section s4u5b
+.section s4u6a
+.section s4u6b
+.section s4u7a
+.section s4u7b
+.section s4u8a
+.section s4u8b
+.section s4u9a
+.section s4u9b
+.section s4u0a
+.section s4u0b
+.section s4vaa
+.section s4vab
+.section s4vba
+.section s4vbb
+.section s4vca
+.section s4vcb
+.section s4vda
+.section s4vdb
+.section s4vea
+.section s4veb
+.section s4vfa
+.section s4vfb
+.section s4vga
+.section s4vgb
+.section s4vha
+.section s4vhb
+.section s4via
+.section s4vib
+.section s4vja
+.section s4vjb
+.section s4vka
+.section s4vkb
+.section s4vla
+.section s4vlb
+.section s4vma
+.section s4vmb
+.section s4vna
+.section s4vnb
+.section s4voa
+.section s4vob
+.section s4vpa
+.section s4vpb
+.section s4vqa
+.section s4vqb
+.section s4vra
+.section s4vrb
+.section s4vsa
+.section s4vsb
+.section s4vta
+.section s4vtb
+.section s4vua
+.section s4vub
+.section s4vva
+.section s4vvb
+.section s4vwa
+.section s4vwb
+.section s4vxa
+.section s4vxb
+.section s4vya
+.section s4vyb
+.section s4vza
+.section s4vzb
+.section s4v1a
+.section s4v1b
+.section s4v2a
+.section s4v2b
+.section s4v3a
+.section s4v3b
+.section s4v4a
+.section s4v4b
+.section s4v5a
+.section s4v5b
+.section s4v6a
+.section s4v6b
+.section s4v7a
+.section s4v7b
+.section s4v8a
+.section s4v8b
+.section s4v9a
+.section s4v9b
+.section s4v0a
+.section s4v0b
+.section s4waa
+.section s4wab
+.section s4wba
+.section s4wbb
+.section s4wca
+.section s4wcb
+.section s4wda
+.section s4wdb
+.section s4wea
+.section s4web
+.section s4wfa
+.section s4wfb
+.section s4wga
+.section s4wgb
+.section s4wha
+.section s4whb
+.section s4wia
+.section s4wib
+.section s4wja
+.section s4wjb
+.section s4wka
+.section s4wkb
+.section s4wla
+.section s4wlb
+.section s4wma
+.section s4wmb
+.section s4wna
+.section s4wnb
+.section s4woa
+.section s4wob
+.section s4wpa
+.section s4wpb
+.section s4wqa
+.section s4wqb
+.section s4wra
+.section s4wrb
+.section s4wsa
+.section s4wsb
+.section s4wta
+.section s4wtb
+.section s4wua
+.section s4wub
+.section s4wva
+.section s4wvb
+.section s4wwa
+.section s4wwb
+.section s4wxa
+.section s4wxb
+.section s4wya
+.section s4wyb
+.section s4wza
+.section s4wzb
+.section s4w1a
+.section s4w1b
+.section s4w2a
+.section s4w2b
+.section s4w3a
+.section s4w3b
+.section s4w4a
+.section s4w4b
+.section s4w5a
+.section s4w5b
+.section s4w6a
+.section s4w6b
+.section s4w7a
+.section s4w7b
+.section s4w8a
+.section s4w8b
+.section s4w9a
+.section s4w9b
+.section s4w0a
+.section s4w0b
+.section s4xaa
+.section s4xab
+.section s4xba
+.section s4xbb
+.section s4xca
+.section s4xcb
+.section s4xda
+.section s4xdb
+.section s4xea
+.section s4xeb
+.section s4xfa
+.section s4xfb
+.section s4xga
+.section s4xgb
+.section s4xha
+.section s4xhb
+.section s4xia
+.section s4xib
+.section s4xja
+.section s4xjb
+.section s4xka
+.section s4xkb
+.section s4xla
+.section s4xlb
+.section s4xma
+.section s4xmb
+.section s4xna
+.section s4xnb
+.section s4xoa
+.section s4xob
+.section s4xpa
+.section s4xpb
+.section s4xqa
+.section s4xqb
+.section s4xra
+.section s4xrb
+.section s4xsa
+.section s4xsb
+.section s4xta
+.section s4xtb
+.section s4xua
+.section s4xub
+.section s4xva
+.section s4xvb
+.section s4xwa
+.section s4xwb
+.section s4xxa
+.section s4xxb
+.section s4xya
+.section s4xyb
+.section s4xza
+.section s4xzb
+.section s4x1a
+.section s4x1b
+.section s4x2a
+.section s4x2b
+.section s4x3a
+.section s4x3b
+.section s4x4a
+.section s4x4b
+.section s4x5a
+.section s4x5b
+.section s4x6a
+.section s4x6b
+.section s4x7a
+.section s4x7b
+.section s4x8a
+.section s4x8b
+.section s4x9a
+.section s4x9b
+.section s4x0a
+.section s4x0b
+.section s4yaa
+.section s4yab
+.section s4yba
+.section s4ybb
+.section s4yca
+.section s4ycb
+.section s4yda
+.section s4ydb
+.section s4yea
+.section s4yeb
+.section s4yfa
+.section s4yfb
+.section s4yga
+.section s4ygb
+.section s4yha
+.section s4yhb
+.section s4yia
+.section s4yib
+.section s4yja
+.section s4yjb
+.section s4yka
+.section s4ykb
+.section s4yla
+.section s4ylb
+.section s4yma
+.section s4ymb
+.section s4yna
+.section s4ynb
+.section s4yoa
+.section s4yob
+.section s4ypa
+.section s4ypb
+.section s4yqa
+.section s4yqb
+.section s4yra
+.section s4yrb
+.section s4ysa
+.section s4ysb
+.section s4yta
+.section s4ytb
+.section s4yua
+.section s4yub
+.section s4yva
+.section s4yvb
+.section s4ywa
+.section s4ywb
+.section s4yxa
+.section s4yxb
+.section s4yya
+.section s4yyb
+.section s4yza
+.section s4yzb
+.section s4y1a
+.section s4y1b
+.section s4y2a
+.section s4y2b
+.section s4y3a
+.section s4y3b
+.section s4y4a
+.section s4y4b
+.section s4y5a
+.section s4y5b
+.section s4y6a
+.section s4y6b
+.section s4y7a
+.section s4y7b
+.section s4y8a
+.section s4y8b
+.section s4y9a
+.section s4y9b
+.section s4y0a
+.section s4y0b
+.section s4zaa
+.section s4zab
+.section s4zba
+.section s4zbb
+.section s4zca
+.section s4zcb
+.section s4zda
+.section s4zdb
+.section s4zea
+.section s4zeb
+.section s4zfa
+.section s4zfb
+.section s4zga
+.section s4zgb
+.section s4zha
+.section s4zhb
+.section s4zia
+.section s4zib
+.section s4zja
+.section s4zjb
+.section s4zka
+.section s4zkb
+.section s4zla
+.section s4zlb
+.section s4zma
+.section s4zmb
+.section s4zna
+.section s4znb
+.section s4zoa
+.section s4zob
+.section s4zpa
+.section s4zpb
+.section s4zqa
+.section s4zqb
+.section s4zra
+.section s4zrb
+.section s4zsa
+.section s4zsb
+.section s4zta
+.section s4ztb
+.section s4zua
+.section s4zub
+.section s4zva
+.section s4zvb
+.section s4zwa
+.section s4zwb
+.section s4zxa
+.section s4zxb
+.section s4zya
+.section s4zyb
+.section s4zza
+.section s4zzb
+.section s4z1a
+.section s4z1b
+.section s4z2a
+.section s4z2b
+.section s4z3a
+.section s4z3b
+.section s4z4a
+.section s4z4b
+.section s4z5a
+.section s4z5b
+.section s4z6a
+.section s4z6b
+.section s4z7a
+.section s4z7b
+.section s4z8a
+.section s4z8b
+.section s4z9a
+.section s4z9b
+.section s4z0a
+.section s4z0b
+.section s41aa
+.section s41ab
+.section s41ba
+.section s41bb
+.section s41ca
+.section s41cb
+.section s41da
+.section s41db
+.section s41ea
+.section s41eb
+.section s41fa
+.section s41fb
+.section s41ga
+.section s41gb
+.section s41ha
+.section s41hb
+.section s41ia
+.section s41ib
+.section s41ja
+.section s41jb
+.section s41ka
+.section s41kb
+.section s41la
+.section s41lb
+.section s41ma
+.section s41mb
+.section s41na
+.section s41nb
+.section s41oa
+.section s41ob
+.section s41pa
+.section s41pb
+.section s41qa
+.section s41qb
+.section s41ra
+.section s41rb
+.section s41sa
+.section s41sb
+.section s41ta
+.section s41tb
+.section s41ua
+.section s41ub
+.section s41va
+.section s41vb
+.section s41wa
+.section s41wb
+.section s41xa
+.section s41xb
+.section s41ya
+.section s41yb
+.section s41za
+.section s41zb
+.section s411a
+.section s411b
+.section s412a
+.section s412b
+.section s413a
+.section s413b
+.section s414a
+.section s414b
+.section s415a
+.section s415b
+.section s416a
+.section s416b
+.section s417a
+.section s417b
+.section s418a
+.section s418b
+.section s419a
+.section s419b
+.section s410a
+.section s410b
+.section s42aa
+.section s42ab
+.section s42ba
+.section s42bb
+.section s42ca
+.section s42cb
+.section s42da
+.section s42db
+.section s42ea
+.section s42eb
+.section s42fa
+.section s42fb
+.section s42ga
+.section s42gb
+.section s42ha
+.section s42hb
+.section s42ia
+.section s42ib
+.section s42ja
+.section s42jb
+.section s42ka
+.section s42kb
+.section s42la
+.section s42lb
+.section s42ma
+.section s42mb
+.section s42na
+.section s42nb
+.section s42oa
+.section s42ob
+.section s42pa
+.section s42pb
+.section s42qa
+.section s42qb
+.section s42ra
+.section s42rb
+.section s42sa
+.section s42sb
+.section s42ta
+.section s42tb
+.section s42ua
+.section s42ub
+.section s42va
+.section s42vb
+.section s42wa
+.section s42wb
+.section s42xa
+.section s42xb
+.section s42ya
+.section s42yb
+.section s42za
+.section s42zb
+.section s421a
+.section s421b
+.section s422a
+.section s422b
+.section s423a
+.section s423b
+.section s424a
+.section s424b
+.section s425a
+.section s425b
+.section s426a
+.section s426b
+.section s427a
+.section s427b
+.section s428a
+.section s428b
+.section s429a
+.section s429b
+.section s420a
+.section s420b
+.section s43aa
+.section s43ab
+.section s43ba
+.section s43bb
+.section s43ca
+.section s43cb
+.section s43da
+.section s43db
+.section s43ea
+.section s43eb
+.section s43fa
+.section s43fb
+.section s43ga
+.section s43gb
+.section s43ha
+.section s43hb
+.section s43ia
+.section s43ib
+.section s43ja
+.section s43jb
+.section s43ka
+.section s43kb
+.section s43la
+.section s43lb
+.section s43ma
+.section s43mb
+.section s43na
+.section s43nb
+.section s43oa
+.section s43ob
+.section s43pa
+.section s43pb
+.section s43qa
+.section s43qb
+.section s43ra
+.section s43rb
+.section s43sa
+.section s43sb
+.section s43ta
+.section s43tb
+.section s43ua
+.section s43ub
+.section s43va
+.section s43vb
+.section s43wa
+.section s43wb
+.section s43xa
+.section s43xb
+.section s43ya
+.section s43yb
+.section s43za
+.section s43zb
+.section s431a
+.section s431b
+.section s432a
+.section s432b
+.section s433a
+.section s433b
+.section s434a
+.section s434b
+.section s435a
+.section s435b
+.section s436a
+.section s436b
+.section s437a
+.section s437b
+.section s438a
+.section s438b
+.section s439a
+.section s439b
+.section s430a
+.section s430b
+.section s44aa
+.section s44ab
+.section s44ba
+.section s44bb
+.section s44ca
+.section s44cb
+.section s44da
+.section s44db
+.section s44ea
+.section s44eb
+.section s44fa
+.section s44fb
+.section s44ga
+.section s44gb
+.section s44ha
+.section s44hb
+.section s44ia
+.section s44ib
+.section s44ja
+.section s44jb
+.section s44ka
+.section s44kb
+.section s44la
+.section s44lb
+.section s44ma
+.section s44mb
+.section s44na
+.section s44nb
+.section s44oa
+.section s44ob
+.section s44pa
+.section s44pb
+.section s44qa
+.section s44qb
+.section s44ra
+.section s44rb
+.section s44sa
+.section s44sb
+.section s44ta
+.section s44tb
+.section s44ua
+.section s44ub
+.section s44va
+.section s44vb
+.section s44wa
+.section s44wb
+.section s44xa
+.section s44xb
+.section s44ya
+.section s44yb
+.section s44za
+.section s44zb
+.section s441a
+.section s441b
+.section s442a
+.section s442b
+.section s443a
+.section s443b
+.section s444a
+.section s444b
+.section s445a
+.section s445b
+.section s446a
+.section s446b
+.section s447a
+.section s447b
+.section s448a
+.section s448b
+.section s449a
+.section s449b
+.section s440a
+.section s440b
+.section s45aa
+.section s45ab
+.section s45ba
+.section s45bb
+.section s45ca
+.section s45cb
+.section s45da
+.section s45db
+.section s45ea
+.section s45eb
+.section s45fa
+.section s45fb
+.section s45ga
+.section s45gb
+.section s45ha
+.section s45hb
+.section s45ia
+.section s45ib
+.section s45ja
+.section s45jb
+.section s45ka
+.section s45kb
+.section s45la
+.section s45lb
+.section s45ma
+.section s45mb
+.section s45na
+.section s45nb
+.section s45oa
+.section s45ob
+.section s45pa
+.section s45pb
+.section s45qa
+.section s45qb
+.section s45ra
+.section s45rb
+.section s45sa
+.section s45sb
+.section s45ta
+.section s45tb
+.section s45ua
+.section s45ub
+.section s45va
+.section s45vb
+.section s45wa
+.section s45wb
+.section s45xa
+.section s45xb
+.section s45ya
+.section s45yb
+.section s45za
+.section s45zb
+.section s451a
+.section s451b
+.section s452a
+.section s452b
+.section s453a
+.section s453b
+.section s454a
+.section s454b
+.section s455a
+.section s455b
+.section s456a
+.section s456b
+.section s457a
+.section s457b
+.section s458a
+.section s458b
+.section s459a
+.section s459b
+.section s450a
+.section s450b
+.section s46aa
+.section s46ab
+.section s46ba
+.section s46bb
+.section s46ca
+.section s46cb
+.section s46da
+.section s46db
+.section s46ea
+.section s46eb
+.section s46fa
+.section s46fb
+.section s46ga
+.section s46gb
+.section s46ha
+.section s46hb
+.section s46ia
+.section s46ib
+.section s46ja
+.section s46jb
+.section s46ka
+.section s46kb
+.section s46la
+.section s46lb
+.section s46ma
+.section s46mb
+.section s46na
+.section s46nb
+.section s46oa
+.section s46ob
+.section s46pa
+.section s46pb
+.section s46qa
+.section s46qb
+.section s46ra
+.section s46rb
+.section s46sa
+.section s46sb
+.section s46ta
+.section s46tb
+.section s46ua
+.section s46ub
+.section s46va
+.section s46vb
+.section s46wa
+.section s46wb
+.section s46xa
+.section s46xb
+.section s46ya
+.section s46yb
+.section s46za
+.section s46zb
+.section s461a
+.section s461b
+.section s462a
+.section s462b
+.section s463a
+.section s463b
+.section s464a
+.section s464b
+.section s465a
+.section s465b
+.section s466a
+.section s466b
+.section s467a
+.section s467b
+.section s468a
+.section s468b
+.section s469a
+.section s469b
+.section s460a
+.section s460b
+.section s47aa
+.section s47ab
+.section s47ba
+.section s47bb
+.section s47ca
+.section s47cb
+.section s47da
+.section s47db
+.section s47ea
+.section s47eb
+.section s47fa
+.section s47fb
+.section s47ga
+.section s47gb
+.section s47ha
+.section s47hb
+.section s47ia
+.section s47ib
+.section s47ja
+.section s47jb
+.section s47ka
+.section s47kb
+.section s47la
+.section s47lb
+.section s47ma
+.section s47mb
+.section s47na
+.section s47nb
+.section s47oa
+.section s47ob
+.section s47pa
+.section s47pb
+.section s47qa
+.section s47qb
+.section s47ra
+.section s47rb
+.section s47sa
+.section s47sb
+.section s47ta
+.section s47tb
+.section s47ua
+.section s47ub
+.section s47va
+.section s47vb
+.section s47wa
+.section s47wb
+.section s47xa
+.section s47xb
+.section s47ya
+.section s47yb
+.section s47za
+.section s47zb
+.section s471a
+.section s471b
+.section s472a
+.section s472b
+.section s473a
+.section s473b
+.section s474a
+.section s474b
+.section s475a
+.section s475b
+.section s476a
+.section s476b
+.section s477a
+.section s477b
+.section s478a
+.section s478b
+.section s479a
+.section s479b
+.section s470a
+.section s470b
+.section s48aa
+.section s48ab
+.section s48ba
+.section s48bb
+.section s48ca
+.section s48cb
+.section s48da
+.section s48db
+.section s48ea
+.section s48eb
+.section s48fa
+.section s48fb
+.section s48ga
+.section s48gb
+.section s48ha
+.section s48hb
+.section s48ia
+.section s48ib
+.section s48ja
+.section s48jb
+.section s48ka
+.section s48kb
+.section s48la
+.section s48lb
+.section s48ma
+.section s48mb
+.section s48na
+.section s48nb
+.section s48oa
+.section s48ob
+.section s48pa
+.section s48pb
+.section s48qa
+.section s48qb
+.section s48ra
+.section s48rb
+.section s48sa
+.section s48sb
+.section s48ta
+.section s48tb
+.section s48ua
+.section s48ub
+.section s48va
+.section s48vb
+.section s48wa
+.section s48wb
+.section s48xa
+.section s48xb
+.section s48ya
+.section s48yb
+.section s48za
+.section s48zb
+.section s481a
+.section s481b
+.section s482a
+.section s482b
+.section s483a
+.section s483b
+.section s484a
+.section s484b
+.section s485a
+.section s485b
+.section s486a
+.section s486b
+.section s487a
+.section s487b
+.section s488a
+.section s488b
+.section s489a
+.section s489b
+.section s480a
+.section s480b
+.section s49aa
+.section s49ab
+.section s49ba
+.section s49bb
+.section s49ca
+.section s49cb
+.section s49da
+.section s49db
+.section s49ea
+.section s49eb
+.section s49fa
+.section s49fb
+.section s49ga
+.section s49gb
+.section s49ha
+.section s49hb
+.section s49ia
+.section s49ib
+.section s49ja
+.section s49jb
+.section s49ka
+.section s49kb
+.section s49la
+.section s49lb
+.section s49ma
+.section s49mb
+.section s49na
+.section s49nb
+.section s49oa
+.section s49ob
+.section s49pa
+.section s49pb
+.section s49qa
+.section s49qb
+.section s49ra
+.section s49rb
+.section s49sa
+.section s49sb
+.section s49ta
+.section s49tb
+.section s49ua
+.section s49ub
+.section s49va
+.section s49vb
+.section s49wa
+.section s49wb
+.section s49xa
+.section s49xb
+.section s49ya
+.section s49yb
+.section s49za
+.section s49zb
+.section s491a
+.section s491b
+.section s492a
+.section s492b
+.section s493a
+.section s493b
+.section s494a
+.section s494b
+.section s495a
+.section s495b
+.section s496a
+.section s496b
+.section s497a
+.section s497b
+.section s498a
+.section s498b
+.section s499a
+.section s499b
+.section s490a
+.section s490b
+.section s40aa
+.section s40ab
+.section s40ba
+.section s40bb
+.section s40ca
+.section s40cb
+.section s40da
+.section s40db
+.section s40ea
+.section s40eb
+.section s40fa
+.section s40fb
+.section s40ga
+.section s40gb
+.section s40ha
+.section s40hb
+.section s40ia
+.section s40ib
+.section s40ja
+.section s40jb
+.section s40ka
+.section s40kb
+.section s40la
+.section s40lb
+.section s40ma
+.section s40mb
+.section s40na
+.section s40nb
+.section s40oa
+.section s40ob
+.section s40pa
+.section s40pb
+.section s40qa
+.section s40qb
+.section s40ra
+.section s40rb
+.section s40sa
+.section s40sb
+.section s40ta
+.section s40tb
+.section s40ua
+.section s40ub
+.section s40va
+.section s40vb
+.section s40wa
+.section s40wb
+.section s40xa
+.section s40xb
+.section s40ya
+.section s40yb
+.section s40za
+.section s40zb
+.section s401a
+.section s401b
+.section s402a
+.section s402b
+.section s403a
+.section s403b
+.section s404a
+.section s404b
+.section s405a
+.section s405b
+.section s406a
+.section s406b
+.section s407a
+.section s407b
+.section s408a
+.section s408b
+.section s409a
+.section s409b
+.section s400a
+.section s400b
+.section s5aaa
+.section s5aab
+.section s5aba
+.section s5abb
+.section s5aca
+.section s5acb
+.section s5ada
+.section s5adb
+.section s5aea
+.section s5aeb
+.section s5afa
+.section s5afb
+.section s5aga
+.section s5agb
+.section s5aha
+.section s5ahb
+.section s5aia
+.section s5aib
+.section s5aja
+.section s5ajb
+.section s5aka
+.section s5akb
+.section s5ala
+.section s5alb
+.section s5ama
+.section s5amb
+.section s5ana
+.section s5anb
+.section s5aoa
+.section s5aob
+.section s5apa
+.section s5apb
+.section s5aqa
+.section s5aqb
+.section s5ara
+.section s5arb
+.section s5asa
+.section s5asb
+.section s5ata
+.section s5atb
+.section s5aua
+.section s5aub
+.section s5ava
+.section s5avb
+.section s5awa
+.section s5awb
+.section s5axa
+.section s5axb
+.section s5aya
+.section s5ayb
+.section s5aza
+.section s5azb
+.section s5a1a
+.section s5a1b
+.section s5a2a
+.section s5a2b
+.section s5a3a
+.section s5a3b
+.section s5a4a
+.section s5a4b
+.section s5a5a
+.section s5a5b
+.section s5a6a
+.section s5a6b
+.section s5a7a
+.section s5a7b
+.section s5a8a
+.section s5a8b
+.section s5a9a
+.section s5a9b
+.section s5a0a
+.section s5a0b
+.section s5baa
+.section s5bab
+.section s5bba
+.section s5bbb
+.section s5bca
+.section s5bcb
+.section s5bda
+.section s5bdb
+.section s5bea
+.section s5beb
+.section s5bfa
+.section s5bfb
+.section s5bga
+.section s5bgb
+.section s5bha
+.section s5bhb
+.section s5bia
+.section s5bib
+.section s5bja
+.section s5bjb
+.section s5bka
+.section s5bkb
+.section s5bla
+.section s5blb
+.section s5bma
+.section s5bmb
+.section s5bna
+.section s5bnb
+.section s5boa
+.section s5bob
+.section s5bpa
+.section s5bpb
+.section s5bqa
+.section s5bqb
+.section s5bra
+.section s5brb
+.section s5bsa
+.section s5bsb
+.section s5bta
+.section s5btb
+.section s5bua
+.section s5bub
+.section s5bva
+.section s5bvb
+.section s5bwa
+.section s5bwb
+.section s5bxa
+.section s5bxb
+.section s5bya
+.section s5byb
+.section s5bza
+.section s5bzb
+.section s5b1a
+.section s5b1b
+.section s5b2a
+.section s5b2b
+.section s5b3a
+.section s5b3b
+.section s5b4a
+.section s5b4b
+.section s5b5a
+.section s5b5b
+.section s5b6a
+.section s5b6b
+.section s5b7a
+.section s5b7b
+.section s5b8a
+.section s5b8b
+.section s5b9a
+.section s5b9b
+.section s5b0a
+.section s5b0b
+.section s5caa
+.section s5cab
+.section s5cba
+.section s5cbb
+.section s5cca
+.section s5ccb
+.section s5cda
+.section s5cdb
+.section s5cea
+.section s5ceb
+.section s5cfa
+.section s5cfb
+.section s5cga
+.section s5cgb
+.section s5cha
+.section s5chb
+.section s5cia
+.section s5cib
+.section s5cja
+.section s5cjb
+.section s5cka
+.section s5ckb
+.section s5cla
+.section s5clb
+.section s5cma
+.section s5cmb
+.section s5cna
+.section s5cnb
+.section s5coa
+.section s5cob
+.section s5cpa
+.section s5cpb
+.section s5cqa
+.section s5cqb
+.section s5cra
+.section s5crb
+.section s5csa
+.section s5csb
+.section s5cta
+.section s5ctb
+.section s5cua
+.section s5cub
+.section s5cva
+.section s5cvb
+.section s5cwa
+.section s5cwb
+.section s5cxa
+.section s5cxb
+.section s5cya
+.section s5cyb
+.section s5cza
+.section s5czb
+.section s5c1a
+.section s5c1b
+.section s5c2a
+.section s5c2b
+.section s5c3a
+.section s5c3b
+.section s5c4a
+.section s5c4b
+.section s5c5a
+.section s5c5b
+.section s5c6a
+.section s5c6b
+.section s5c7a
+.section s5c7b
+.section s5c8a
+.section s5c8b
+.section s5c9a
+.section s5c9b
+.section s5c0a
+.section s5c0b
+.section s5daa
+.section s5dab
+.section s5dba
+.section s5dbb
+.section s5dca
+.section s5dcb
+.section s5dda
+.section s5ddb
+.section s5dea
+.section s5deb
+.section s5dfa
+.section s5dfb
+.section s5dga
+.section s5dgb
+.section s5dha
+.section s5dhb
+.section s5dia
+.section s5dib
+.section s5dja
+.section s5djb
+.section s5dka
+.section s5dkb
+.section s5dla
+.section s5dlb
+.section s5dma
+.section s5dmb
+.section s5dna
+.section s5dnb
+.section s5doa
+.section s5dob
+.section s5dpa
+.section s5dpb
+.section s5dqa
+.section s5dqb
+.section s5dra
+.section s5drb
+.section s5dsa
+.section s5dsb
+.section s5dta
+.section s5dtb
+.section s5dua
+.section s5dub
+.section s5dva
+.section s5dvb
+.section s5dwa
+.section s5dwb
+.section s5dxa
+.section s5dxb
+.section s5dya
+.section s5dyb
+.section s5dza
+.section s5dzb
+.section s5d1a
+.section s5d1b
+.section s5d2a
+.section s5d2b
+.section s5d3a
+.section s5d3b
+.section s5d4a
+.section s5d4b
+.section s5d5a
+.section s5d5b
+.section s5d6a
+.section s5d6b
+.section s5d7a
+.section s5d7b
+.section s5d8a
+.section s5d8b
+.section s5d9a
+.section s5d9b
+.section s5d0a
+.section s5d0b
+.section s5eaa
+.section s5eab
+.section s5eba
+.section s5ebb
+.section s5eca
+.section s5ecb
+.section s5eda
+.section s5edb
+.section s5eea
+.section s5eeb
+.section s5efa
+.section s5efb
+.section s5ega
+.section s5egb
+.section s5eha
+.section s5ehb
+.section s5eia
+.section s5eib
+.section s5eja
+.section s5ejb
+.section s5eka
+.section s5ekb
+.section s5ela
+.section s5elb
+.section s5ema
+.section s5emb
+.section s5ena
+.section s5enb
+.section s5eoa
+.section s5eob
+.section s5epa
+.section s5epb
+.section s5eqa
+.section s5eqb
+.section s5era
+.section s5erb
+.section s5esa
+.section s5esb
+.section s5eta
+.section s5etb
+.section s5eua
+.section s5eub
+.section s5eva
+.section s5evb
+.section s5ewa
+.section s5ewb
+.section s5exa
+.section s5exb
+.section s5eya
+.section s5eyb
+.section s5eza
+.section s5ezb
+.section s5e1a
+.section s5e1b
+.section s5e2a
+.section s5e2b
+.section s5e3a
+.section s5e3b
+.section s5e4a
+.section s5e4b
+.section s5e5a
+.section s5e5b
+.section s5e6a
+.section s5e6b
+.section s5e7a
+.section s5e7b
+.section s5e8a
+.section s5e8b
+.section s5e9a
+.section s5e9b
+.section s5e0a
+.section s5e0b
+.section s5faa
+.section s5fab
+.section s5fba
+.section s5fbb
+.section s5fca
+.section s5fcb
+.section s5fda
+.section s5fdb
+.section s5fea
+.section s5feb
+.section s5ffa
+.section s5ffb
+.section s5fga
+.section s5fgb
+.section s5fha
+.section s5fhb
+.section s5fia
+.section s5fib
+.section s5fja
+.section s5fjb
+.section s5fka
+.section s5fkb
+.section s5fla
+.section s5flb
+.section s5fma
+.section s5fmb
+.section s5fna
+.section s5fnb
+.section s5foa
+.section s5fob
+.section s5fpa
+.section s5fpb
+.section s5fqa
+.section s5fqb
+.section s5fra
+.section s5frb
+.section s5fsa
+.section s5fsb
+.section s5fta
+.section s5ftb
+.section s5fua
+.section s5fub
+.section s5fva
+.section s5fvb
+.section s5fwa
+.section s5fwb
+.section s5fxa
+.section s5fxb
+.section s5fya
+.section s5fyb
+.section s5fza
+.section s5fzb
+.section s5f1a
+.section s5f1b
+.section s5f2a
+.section s5f2b
+.section s5f3a
+.section s5f3b
+.section s5f4a
+.section s5f4b
+.section s5f5a
+.section s5f5b
+.section s5f6a
+.section s5f6b
+.section s5f7a
+.section s5f7b
+.section s5f8a
+.section s5f8b
+.section s5f9a
+.section s5f9b
+.section s5f0a
+.section s5f0b
+.section s5gaa
+.section s5gab
+.section s5gba
+.section s5gbb
+.section s5gca
+.section s5gcb
+.section s5gda
+.section s5gdb
+.section s5gea
+.section s5geb
+.section s5gfa
+.section s5gfb
+.section s5gga
+.section s5ggb
+.section s5gha
+.section s5ghb
+.section s5gia
+.section s5gib
+.section s5gja
+.section s5gjb
+.section s5gka
+.section s5gkb
+.section s5gla
+.section s5glb
+.section s5gma
+.section s5gmb
+.section s5gna
+.section s5gnb
+.section s5goa
+.section s5gob
+.section s5gpa
+.section s5gpb
+.section s5gqa
+.section s5gqb
+.section s5gra
+.section s5grb
+.section s5gsa
+.section s5gsb
+.section s5gta
+.section s5gtb
+.section s5gua
+.section s5gub
+.section s5gva
+.section s5gvb
+.section s5gwa
+.section s5gwb
+.section s5gxa
+.section s5gxb
+.section s5gya
+.section s5gyb
+.section s5gza
+.section s5gzb
+.section s5g1a
+.section s5g1b
+.section s5g2a
+.section s5g2b
+.section s5g3a
+.section s5g3b
+.section s5g4a
+.section s5g4b
+.section s5g5a
+.section s5g5b
+.section s5g6a
+.section s5g6b
+.section s5g7a
+.section s5g7b
+.section s5g8a
+.section s5g8b
+.section s5g9a
+.section s5g9b
+.section s5g0a
+.section s5g0b
+.section s5haa
+.section s5hab
+.section s5hba
+.section s5hbb
+.section s5hca
+.section s5hcb
+.section s5hda
+.section s5hdb
+.section s5hea
+.section s5heb
+.section s5hfa
+.section s5hfb
+.section s5hga
+.section s5hgb
+.section s5hha
+.section s5hhb
+.section s5hia
+.section s5hib
+.section s5hja
+.section s5hjb
+.section s5hka
+.section s5hkb
+.section s5hla
+.section s5hlb
+.section s5hma
+.section s5hmb
+.section s5hna
+.section s5hnb
+.section s5hoa
+.section s5hob
+.section s5hpa
+.section s5hpb
+.section s5hqa
+.section s5hqb
+.section s5hra
+.section s5hrb
+.section s5hsa
+.section s5hsb
+.section s5hta
+.section s5htb
+.section s5hua
+.section s5hub
+.section s5hva
+.section s5hvb
+.section s5hwa
+.section s5hwb
+.section s5hxa
+.section s5hxb
+.section s5hya
+.section s5hyb
+.section s5hza
+.section s5hzb
+.section s5h1a
+.section s5h1b
+.section s5h2a
+.section s5h2b
+.section s5h3a
+.section s5h3b
+.section s5h4a
+.section s5h4b
+.section s5h5a
+.section s5h5b
+.section s5h6a
+.section s5h6b
+.section s5h7a
+.section s5h7b
+.section s5h8a
+.section s5h8b
+.section s5h9a
+.section s5h9b
+.section s5h0a
+.section s5h0b
+.section s5iaa
+.section s5iab
+.section s5iba
+.section s5ibb
+.section s5ica
+.section s5icb
+.section s5ida
+.section s5idb
+.section s5iea
+.section s5ieb
+.section s5ifa
+.section s5ifb
+.section s5iga
+.section s5igb
+.section s5iha
+.section s5ihb
+.section s5iia
+.section s5iib
+.section s5ija
+.section s5ijb
+.section s5ika
+.section s5ikb
+.section s5ila
+.section s5ilb
+.section s5ima
+.section s5imb
+.section s5ina
+.section s5inb
+.section s5ioa
+.section s5iob
+.section s5ipa
+.section s5ipb
+.section s5iqa
+.section s5iqb
+.section s5ira
+.section s5irb
+.section s5isa
+.section s5isb
+.section s5ita
+.section s5itb
+.section s5iua
+.section s5iub
+.section s5iva
+.section s5ivb
+.section s5iwa
+.section s5iwb
+.section s5ixa
+.section s5ixb
+.section s5iya
+.section s5iyb
+.section s5iza
+.section s5izb
+.section s5i1a
+.section s5i1b
+.section s5i2a
+.section s5i2b
+.section s5i3a
+.section s5i3b
+.section s5i4a
+.section s5i4b
+.section s5i5a
+.section s5i5b
+.section s5i6a
+.section s5i6b
+.section s5i7a
+.section s5i7b
+.section s5i8a
+.section s5i8b
+.section s5i9a
+.section s5i9b
+.section s5i0a
+.section s5i0b
+.section s5jaa
+.section s5jab
+.section s5jba
+.section s5jbb
+.section s5jca
+.section s5jcb
+.section s5jda
+.section s5jdb
+.section s5jea
+.section s5jeb
+.section s5jfa
+.section s5jfb
+.section s5jga
+.section s5jgb
+.section s5jha
+.section s5jhb
+.section s5jia
+.section s5jib
+.section s5jja
+.section s5jjb
+.section s5jka
+.section s5jkb
+.section s5jla
+.section s5jlb
+.section s5jma
+.section s5jmb
+.section s5jna
+.section s5jnb
+.section s5joa
+.section s5job
+.section s5jpa
+.section s5jpb
+.section s5jqa
+.section s5jqb
+.section s5jra
+.section s5jrb
+.section s5jsa
+.section s5jsb
+.section s5jta
+.section s5jtb
+.section s5jua
+.section s5jub
+.section s5jva
+.section s5jvb
+.section s5jwa
+.section s5jwb
+.section s5jxa
+.section s5jxb
+.section s5jya
+.section s5jyb
+.section s5jza
+.section s5jzb
+.section s5j1a
+.section s5j1b
+.section s5j2a
+.section s5j2b
+.section s5j3a
+.section s5j3b
+.section s5j4a
+.section s5j4b
+.section s5j5a
+.section s5j5b
+.section s5j6a
+.section s5j6b
+.section s5j7a
+.section s5j7b
+.section s5j8a
+.section s5j8b
+.section s5j9a
+.section s5j9b
+.section s5j0a
+.section s5j0b
+.section s5kaa
+.section s5kab
+.section s5kba
+.section s5kbb
+.section s5kca
+.section s5kcb
+.section s5kda
+.section s5kdb
+.section s5kea
+.section s5keb
+.section s5kfa
+.section s5kfb
+.section s5kga
+.section s5kgb
+.section s5kha
+.section s5khb
+.section s5kia
+.section s5kib
+.section s5kja
+.section s5kjb
+.section s5kka
+.section s5kkb
+.section s5kla
+.section s5klb
+.section s5kma
+.section s5kmb
+.section s5kna
+.section s5knb
+.section s5koa
+.section s5kob
+.section s5kpa
+.section s5kpb
+.section s5kqa
+.section s5kqb
+.section s5kra
+.section s5krb
+.section s5ksa
+.section s5ksb
+.section s5kta
+.section s5ktb
+.section s5kua
+.section s5kub
+.section s5kva
+.section s5kvb
+.section s5kwa
+.section s5kwb
+.section s5kxa
+.section s5kxb
+.section s5kya
+.section s5kyb
+.section s5kza
+.section s5kzb
+.section s5k1a
+.section s5k1b
+.section s5k2a
+.section s5k2b
+.section s5k3a
+.section s5k3b
+.section s5k4a
+.section s5k4b
+.section s5k5a
+.section s5k5b
+.section s5k6a
+.section s5k6b
+.section s5k7a
+.section s5k7b
+.section s5k8a
+.section s5k8b
+.section s5k9a
+.section s5k9b
+.section s5k0a
+.section s5k0b
+.section s5laa
+.section s5lab
+.section s5lba
+.section s5lbb
+.section s5lca
+.section s5lcb
+.section s5lda
+.section s5ldb
+.section s5lea
+.section s5leb
+.section s5lfa
+.section s5lfb
+.section s5lga
+.section s5lgb
+.section s5lha
+.section s5lhb
+.section s5lia
+.section s5lib
+.section s5lja
+.section s5ljb
+.section s5lka
+.section s5lkb
+.section s5lla
+.section s5llb
+.section s5lma
+.section s5lmb
+.section s5lna
+.section s5lnb
+.section s5loa
+.section s5lob
+.section s5lpa
+.section s5lpb
+.section s5lqa
+.section s5lqb
+.section s5lra
+.section s5lrb
+.section s5lsa
+.section s5lsb
+.section s5lta
+.section s5ltb
+.section s5lua
+.section s5lub
+.section s5lva
+.section s5lvb
+.section s5lwa
+.section s5lwb
+.section s5lxa
+.section s5lxb
+.section s5lya
+.section s5lyb
+.section s5lza
+.section s5lzb
+.section s5l1a
+.section s5l1b
+.section s5l2a
+.section s5l2b
+.section s5l3a
+.section s5l3b
+.section s5l4a
+.section s5l4b
+.section s5l5a
+.section s5l5b
+.section s5l6a
+.section s5l6b
+.section s5l7a
+.section s5l7b
+.section s5l8a
+.section s5l8b
+.section s5l9a
+.section s5l9b
+.section s5l0a
+.section s5l0b
+.section s5maa
+.section s5mab
+.section s5mba
+.section s5mbb
+.section s5mca
+.section s5mcb
+.section s5mda
+.section s5mdb
+.section s5mea
+.section s5meb
+.section s5mfa
+.section s5mfb
+.section s5mga
+.section s5mgb
+.section s5mha
+.section s5mhb
+.section s5mia
+.section s5mib
+.section s5mja
+.section s5mjb
+.section s5mka
+.section s5mkb
+.section s5mla
+.section s5mlb
+.section s5mma
+.section s5mmb
+.section s5mna
+.section s5mnb
+.section s5moa
+.section s5mob
+.section s5mpa
+.section s5mpb
+.section s5mqa
+.section s5mqb
+.section s5mra
+.section s5mrb
+.section s5msa
+.section s5msb
+.section s5mta
+.section s5mtb
+.section s5mua
+.section s5mub
+.section s5mva
+.section s5mvb
+.section s5mwa
+.section s5mwb
+.section s5mxa
+.section s5mxb
+.section s5mya
+.section s5myb
+.section s5mza
+.section s5mzb
+.section s5m1a
+.section s5m1b
+.section s5m2a
+.section s5m2b
+.section s5m3a
+.section s5m3b
+.section s5m4a
+.section s5m4b
+.section s5m5a
+.section s5m5b
+.section s5m6a
+.section s5m6b
+.section s5m7a
+.section s5m7b
+.section s5m8a
+.section s5m8b
+.section s5m9a
+.section s5m9b
+.section s5m0a
+.section s5m0b
+.section s5naa
+.section s5nab
+.section s5nba
+.section s5nbb
+.section s5nca
+.section s5ncb
+.section s5nda
+.section s5ndb
+.section s5nea
+.section s5neb
+.section s5nfa
+.section s5nfb
+.section s5nga
+.section s5ngb
+.section s5nha
+.section s5nhb
+.section s5nia
+.section s5nib
+.section s5nja
+.section s5njb
+.section s5nka
+.section s5nkb
+.section s5nla
+.section s5nlb
+.section s5nma
+.section s5nmb
+.section s5nna
+.section s5nnb
+.section s5noa
+.section s5nob
+.section s5npa
+.section s5npb
+.section s5nqa
+.section s5nqb
+.section s5nra
+.section s5nrb
+.section s5nsa
+.section s5nsb
+.section s5nta
+.section s5ntb
+.section s5nua
+.section s5nub
+.section s5nva
+.section s5nvb
+.section s5nwa
+.section s5nwb
+.section s5nxa
+.section s5nxb
+.section s5nya
+.section s5nyb
+.section s5nza
+.section s5nzb
+.section s5n1a
+.section s5n1b
+.section s5n2a
+.section s5n2b
+.section s5n3a
+.section s5n3b
+.section s5n4a
+.section s5n4b
+.section s5n5a
+.section s5n5b
+.section s5n6a
+.section s5n6b
+.section s5n7a
+.section s5n7b
+.section s5n8a
+.section s5n8b
+.section s5n9a
+.section s5n9b
+.section s5n0a
+.section s5n0b
+.section s5oaa
+.section s5oab
+.section s5oba
+.section s5obb
+.section s5oca
+.section s5ocb
+.section s5oda
+.section s5odb
+.section s5oea
+.section s5oeb
+.section s5ofa
+.section s5ofb
+.section s5oga
+.section s5ogb
+.section s5oha
+.section s5ohb
+.section s5oia
+.section s5oib
+.section s5oja
+.section s5ojb
+.section s5oka
+.section s5okb
+.section s5ola
+.section s5olb
+.section s5oma
+.section s5omb
+.section s5ona
+.section s5onb
+.section s5ooa
+.section s5oob
+.section s5opa
+.section s5opb
+.section s5oqa
+.section s5oqb
+.section s5ora
+.section s5orb
+.section s5osa
+.section s5osb
+.section s5ota
+.section s5otb
+.section s5oua
+.section s5oub
+.section s5ova
+.section s5ovb
+.section s5owa
+.section s5owb
+.section s5oxa
+.section s5oxb
+.section s5oya
+.section s5oyb
+.section s5oza
+.section s5ozb
+.section s5o1a
+.section s5o1b
+.section s5o2a
+.section s5o2b
+.section s5o3a
+.section s5o3b
+.section s5o4a
+.section s5o4b
+.section s5o5a
+.section s5o5b
+.section s5o6a
+.section s5o6b
+.section s5o7a
+.section s5o7b
+.section s5o8a
+.section s5o8b
+.section s5o9a
+.section s5o9b
+.section s5o0a
+.section s5o0b
+.section s5paa
+.section s5pab
+.section s5pba
+.section s5pbb
+.section s5pca
+.section s5pcb
+.section s5pda
+.section s5pdb
+.section s5pea
+.section s5peb
+.section s5pfa
+.section s5pfb
+.section s5pga
+.section s5pgb
+.section s5pha
+.section s5phb
+.section s5pia
+.section s5pib
+.section s5pja
+.section s5pjb
+.section s5pka
+.section s5pkb
+.section s5pla
+.section s5plb
+.section s5pma
+.section s5pmb
+.section s5pna
+.section s5pnb
+.section s5poa
+.section s5pob
+.section s5ppa
+.section s5ppb
+.section s5pqa
+.section s5pqb
+.section s5pra
+.section s5prb
+.section s5psa
+.section s5psb
+.section s5pta
+.section s5ptb
+.section s5pua
+.section s5pub
+.section s5pva
+.section s5pvb
+.section s5pwa
+.section s5pwb
+.section s5pxa
+.section s5pxb
+.section s5pya
+.section s5pyb
+.section s5pza
+.section s5pzb
+.section s5p1a
+.section s5p1b
+.section s5p2a
+.section s5p2b
+.section s5p3a
+.section s5p3b
+.section s5p4a
+.section s5p4b
+.section s5p5a
+.section s5p5b
+.section s5p6a
+.section s5p6b
+.section s5p7a
+.section s5p7b
+.section s5p8a
+.section s5p8b
+.section s5p9a
+.section s5p9b
+.section s5p0a
+.section s5p0b
+.section s5qaa
+.section s5qab
+.section s5qba
+.section s5qbb
+.section s5qca
+.section s5qcb
+.section s5qda
+.section s5qdb
+.section s5qea
+.section s5qeb
+.section s5qfa
+.section s5qfb
+.section s5qga
+.section s5qgb
+.section s5qha
+.section s5qhb
+.section s5qia
+.section s5qib
+.section s5qja
+.section s5qjb
+.section s5qka
+.section s5qkb
+.section s5qla
+.section s5qlb
+.section s5qma
+.section s5qmb
+.section s5qna
+.section s5qnb
+.section s5qoa
+.section s5qob
+.section s5qpa
+.section s5qpb
+.section s5qqa
+.section s5qqb
+.section s5qra
+.section s5qrb
+.section s5qsa
+.section s5qsb
+.section s5qta
+.section s5qtb
+.section s5qua
+.section s5qub
+.section s5qva
+.section s5qvb
+.section s5qwa
+.section s5qwb
+.section s5qxa
+.section s5qxb
+.section s5qya
+.section s5qyb
+.section s5qza
+.section s5qzb
+.section s5q1a
+.section s5q1b
+.section s5q2a
+.section s5q2b
+.section s5q3a
+.section s5q3b
+.section s5q4a
+.section s5q4b
+.section s5q5a
+.section s5q5b
+.section s5q6a
+.section s5q6b
+.section s5q7a
+.section s5q7b
+.section s5q8a
+.section s5q8b
+.section s5q9a
+.section s5q9b
+.section s5q0a
+.section s5q0b
+.section s5raa
+.section s5rab
+.section s5rba
+.section s5rbb
+.section s5rca
+.section s5rcb
+.section s5rda
+.section s5rdb
+.section s5rea
+.section s5reb
+.section s5rfa
+.section s5rfb
+.section s5rga
+.section s5rgb
+.section s5rha
+.section s5rhb
+.section s5ria
+.section s5rib
+.section s5rja
+.section s5rjb
+.section s5rka
+.section s5rkb
+.section s5rla
+.section s5rlb
+.section s5rma
+.section s5rmb
+.section s5rna
+.section s5rnb
+.section s5roa
+.section s5rob
+.section s5rpa
+.section s5rpb
+.section s5rqa
+.section s5rqb
+.section s5rra
+.section s5rrb
+.section s5rsa
+.section s5rsb
+.section s5rta
+.section s5rtb
+.section s5rua
+.section s5rub
+.section s5rva
+.section s5rvb
+.section s5rwa
+.section s5rwb
+.section s5rxa
+.section s5rxb
+.section s5rya
+.section s5ryb
+.section s5rza
+.section s5rzb
+.section s5r1a
+.section s5r1b
+.section s5r2a
+.section s5r2b
+.section s5r3a
+.section s5r3b
+.section s5r4a
+.section s5r4b
+.section s5r5a
+.section s5r5b
+.section s5r6a
+.section s5r6b
+.section s5r7a
+.section s5r7b
+.section s5r8a
+.section s5r8b
+.section s5r9a
+.section s5r9b
+.section s5r0a
+.section s5r0b
+.section s5saa
+.section s5sab
+.section s5sba
+.section s5sbb
+.section s5sca
+.section s5scb
+.section s5sda
+.section s5sdb
+.section s5sea
+.section s5seb
+.section s5sfa
+.section s5sfb
+.section s5sga
+.section s5sgb
+.section s5sha
+.section s5shb
+.section s5sia
+.section s5sib
+.section s5sja
+.section s5sjb
+.section s5ska
+.section s5skb
+.section s5sla
+.section s5slb
+.section s5sma
+.section s5smb
+.section s5sna
+.section s5snb
+.section s5soa
+.section s5sob
+.section s5spa
+.section s5spb
+.section s5sqa
+.section s5sqb
+.section s5sra
+.section s5srb
+.section s5ssa
+.section s5ssb
+.section s5sta
+.section s5stb
+.section s5sua
+.section s5sub
+.section s5sva
+.section s5svb
+.section s5swa
+.section s5swb
+.section s5sxa
+.section s5sxb
+.section s5sya
+.section s5syb
+.section s5sza
+.section s5szb
+.section s5s1a
+.section s5s1b
+.section s5s2a
+.section s5s2b
+.section s5s3a
+.section s5s3b
+.section s5s4a
+.section s5s4b
+.section s5s5a
+.section s5s5b
+.section s5s6a
+.section s5s6b
+.section s5s7a
+.section s5s7b
+.section s5s8a
+.section s5s8b
+.section s5s9a
+.section s5s9b
+.section s5s0a
+.section s5s0b
+.section s5taa
+.section s5tab
+.section s5tba
+.section s5tbb
+.section s5tca
+.section s5tcb
+.section s5tda
+.section s5tdb
+.section s5tea
+.section s5teb
+.section s5tfa
+.section s5tfb
+.section s5tga
+.section s5tgb
+.section s5tha
+.section s5thb
+.section s5tia
+.section s5tib
+.section s5tja
+.section s5tjb
+.section s5tka
+.section s5tkb
+.section s5tla
+.section s5tlb
+.section s5tma
+.section s5tmb
+.section s5tna
+.section s5tnb
+.section s5toa
+.section s5tob
+.section s5tpa
+.section s5tpb
+.section s5tqa
+.section s5tqb
+.section s5tra
+.section s5trb
+.section s5tsa
+.section s5tsb
+.section s5tta
+.section s5ttb
+.section s5tua
+.section s5tub
+.section s5tva
+.section s5tvb
+.section s5twa
+.section s5twb
+.section s5txa
+.section s5txb
+.section s5tya
+.section s5tyb
+.section s5tza
+.section s5tzb
+.section s5t1a
+.section s5t1b
+.section s5t2a
+.section s5t2b
+.section s5t3a
+.section s5t3b
+.section s5t4a
+.section s5t4b
+.section s5t5a
+.section s5t5b
+.section s5t6a
+.section s5t6b
+.section s5t7a
+.section s5t7b
+.section s5t8a
+.section s5t8b
+.section s5t9a
+.section s5t9b
+.section s5t0a
+.section s5t0b
+.section s5uaa
+.section s5uab
+.section s5uba
+.section s5ubb
+.section s5uca
+.section s5ucb
+.section s5uda
+.section s5udb
+.section s5uea
+.section s5ueb
+.section s5ufa
+.section s5ufb
+.section s5uga
+.section s5ugb
+.section s5uha
+.section s5uhb
+.section s5uia
+.section s5uib
+.section s5uja
+.section s5ujb
+.section s5uka
+.section s5ukb
+.section s5ula
+.section s5ulb
+.section s5uma
+.section s5umb
+.section s5una
+.section s5unb
+.section s5uoa
+.section s5uob
+.section s5upa
+.section s5upb
+.section s5uqa
+.section s5uqb
+.section s5ura
+.section s5urb
+.section s5usa
+.section s5usb
+.section s5uta
+.section s5utb
+.section s5uua
+.section s5uub
+.section s5uva
+.section s5uvb
+.section s5uwa
+.section s5uwb
+.section s5uxa
+.section s5uxb
+.section s5uya
+.section s5uyb
+.section s5uza
+.section s5uzb
+.section s5u1a
+.section s5u1b
+.section s5u2a
+.section s5u2b
+.section s5u3a
+.section s5u3b
+.section s5u4a
+.section s5u4b
+.section s5u5a
+.section s5u5b
+.section s5u6a
+.section s5u6b
+.section s5u7a
+.section s5u7b
+.section s5u8a
+.section s5u8b
+.section s5u9a
+.section s5u9b
+.section s5u0a
+.section s5u0b
+.section s5vaa
+.section s5vab
+.section s5vba
+.section s5vbb
+.section s5vca
+.section s5vcb
+.section s5vda
+.section s5vdb
+.section s5vea
+.section s5veb
+.section s5vfa
+.section s5vfb
+.section s5vga
+.section s5vgb
+.section s5vha
+.section s5vhb
+.section s5via
+.section s5vib
+.section s5vja
+.section s5vjb
+.section s5vka
+.section s5vkb
+.section s5vla
+.section s5vlb
+.section s5vma
+.section s5vmb
+.section s5vna
+.section s5vnb
+.section s5voa
+.section s5vob
+.section s5vpa
+.section s5vpb
+.section s5vqa
+.section s5vqb
+.section s5vra
+.section s5vrb
+.section s5vsa
+.section s5vsb
+.section s5vta
+.section s5vtb
+.section s5vua
+.section s5vub
+.section s5vva
+.section s5vvb
+.section s5vwa
+.section s5vwb
+.section s5vxa
+.section s5vxb
+.section s5vya
+.section s5vyb
+.section s5vza
+.section s5vzb
+.section s5v1a
+.section s5v1b
+.section s5v2a
+.section s5v2b
+.section s5v3a
+.section s5v3b
+.section s5v4a
+.section s5v4b
+.section s5v5a
+.section s5v5b
+.section s5v6a
+.section s5v6b
+.section s5v7a
+.section s5v7b
+.section s5v8a
+.section s5v8b
+.section s5v9a
+.section s5v9b
+.section s5v0a
+.section s5v0b
+.section s5waa
+.section s5wab
+.section s5wba
+.section s5wbb
+.section s5wca
+.section s5wcb
+.section s5wda
+.section s5wdb
+.section s5wea
+.section s5web
+.section s5wfa
+.section s5wfb
+.section s5wga
+.section s5wgb
+.section s5wha
+.section s5whb
+.section s5wia
+.section s5wib
+.section s5wja
+.section s5wjb
+.section s5wka
+.section s5wkb
+.section s5wla
+.section s5wlb
+.section s5wma
+.section s5wmb
+.section s5wna
+.section s5wnb
+.section s5woa
+.section s5wob
+.section s5wpa
+.section s5wpb
+.section s5wqa
+.section s5wqb
+.section s5wra
+.section s5wrb
+.section s5wsa
+.section s5wsb
+.section s5wta
+.section s5wtb
+.section s5wua
+.section s5wub
+.section s5wva
+.section s5wvb
+.section s5wwa
+.section s5wwb
+.section s5wxa
+.section s5wxb
+.section s5wya
+.section s5wyb
+.section s5wza
+.section s5wzb
+.section s5w1a
+.section s5w1b
+.section s5w2a
+.section s5w2b
+.section s5w3a
+.section s5w3b
+.section s5w4a
+.section s5w4b
+.section s5w5a
+.section s5w5b
+.section s5w6a
+.section s5w6b
+.section s5w7a
+.section s5w7b
+.section s5w8a
+.section s5w8b
+.section s5w9a
+.section s5w9b
+.section s5w0a
+.section s5w0b
+.section s5xaa
+.section s5xab
+.section s5xba
+.section s5xbb
+.section s5xca
+.section s5xcb
+.section s5xda
+.section s5xdb
+.section s5xea
+.section s5xeb
+.section s5xfa
+.section s5xfb
+.section s5xga
+.section s5xgb
+.section s5xha
+.section s5xhb
+.section s5xia
+.section s5xib
+.section s5xja
+.section s5xjb
+.section s5xka
+.section s5xkb
+.section s5xla
+.section s5xlb
+.section s5xma
+.section s5xmb
+.section s5xna
+.section s5xnb
+.section s5xoa
+.section s5xob
+.section s5xpa
+.section s5xpb
+.section s5xqa
+.section s5xqb
+.section s5xra
+.section s5xrb
+.section s5xsa
+.section s5xsb
+.section s5xta
+.section s5xtb
+.section s5xua
+.section s5xub
+.section s5xva
+.section s5xvb
+.section s5xwa
+.section s5xwb
+.section s5xxa
+.section s5xxb
+.section s5xya
+.section s5xyb
+.section s5xza
+.section s5xzb
+.section s5x1a
+.section s5x1b
+.section s5x2a
+.section s5x2b
+.section s5x3a
+.section s5x3b
+.section s5x4a
+.section s5x4b
+.section s5x5a
+.section s5x5b
+.section s5x6a
+.section s5x6b
+.section s5x7a
+.section s5x7b
+.section s5x8a
+.section s5x8b
+.section s5x9a
+.section s5x9b
+.section s5x0a
+.section s5x0b
+.section s5yaa
+.section s5yab
+.section s5yba
+.section s5ybb
+.section s5yca
+.section s5ycb
+.section s5yda
+.section s5ydb
+.section s5yea
+.section s5yeb
+.section s5yfa
+.section s5yfb
+.section s5yga
+.section s5ygb
+.section s5yha
+.section s5yhb
+.section s5yia
+.section s5yib
+.section s5yja
+.section s5yjb
+.section s5yka
+.section s5ykb
+.section s5yla
+.section s5ylb
+.section s5yma
+.section s5ymb
+.section s5yna
+.section s5ynb
+.section s5yoa
+.section s5yob
+.section s5ypa
+.section s5ypb
+.section s5yqa
+.section s5yqb
+.section s5yra
+.section s5yrb
+.section s5ysa
+.section s5ysb
+.section s5yta
+.section s5ytb
+.section s5yua
+.section s5yub
+.section s5yva
+.section s5yvb
+.section s5ywa
+.section s5ywb
+.section s5yxa
+.section s5yxb
+.section s5yya
+.section s5yyb
+.section s5yza
+.section s5yzb
+.section s5y1a
+.section s5y1b
+.section s5y2a
+.section s5y2b
+.section s5y3a
+.section s5y3b
+.section s5y4a
+.section s5y4b
+.section s5y5a
+.section s5y5b
+.section s5y6a
+.section s5y6b
+.section s5y7a
+.section s5y7b
+.section s5y8a
+.section s5y8b
+.section s5y9a
+.section s5y9b
+.section s5y0a
+.section s5y0b
+.section s5zaa
+.section s5zab
+.section s5zba
+.section s5zbb
+.section s5zca
+.section s5zcb
+.section s5zda
+.section s5zdb
+.section s5zea
+.section s5zeb
+.section s5zfa
+.section s5zfb
+.section s5zga
+.section s5zgb
+.section s5zha
+.section s5zhb
+.section s5zia
+.section s5zib
+.section s5zja
+.section s5zjb
+.section s5zka
+.section s5zkb
+.section s5zla
+.section s5zlb
+.section s5zma
+.section s5zmb
+.section s5zna
+.section s5znb
+.section s5zoa
+.section s5zob
+.section s5zpa
+.section s5zpb
+.section s5zqa
+.section s5zqb
+.section s5zra
+.section s5zrb
+.section s5zsa
+.section s5zsb
+.section s5zta
+.section s5ztb
+.section s5zua
+.section s5zub
+.section s5zva
+.section s5zvb
+.section s5zwa
+.section s5zwb
+.section s5zxa
+.section s5zxb
+.section s5zya
+.section s5zyb
+.section s5zza
+.section s5zzb
+.section s5z1a
+.section s5z1b
+.section s5z2a
+.section s5z2b
+.section s5z3a
+.section s5z3b
+.section s5z4a
+.section s5z4b
+.section s5z5a
+.section s5z5b
+.section s5z6a
+.section s5z6b
+.section s5z7a
+.section s5z7b
+.section s5z8a
+.section s5z8b
+.section s5z9a
+.section s5z9b
+.section s5z0a
+.section s5z0b
+.section s51aa
+.section s51ab
+.section s51ba
+.section s51bb
+.section s51ca
+.section s51cb
+.section s51da
+.section s51db
+.section s51ea
+.section s51eb
+.section s51fa
+.section s51fb
+.section s51ga
+.section s51gb
+.section s51ha
+.section s51hb
+.section s51ia
+.section s51ib
+.section s51ja
+.section s51jb
+.section s51ka
+.section s51kb
+.section s51la
+.section s51lb
+.section s51ma
+.section s51mb
+.section s51na
+.section s51nb
+.section s51oa
+.section s51ob
+.section s51pa
+.section s51pb
+.section s51qa
+.section s51qb
+.section s51ra
+.section s51rb
+.section s51sa
+.section s51sb
+.section s51ta
+.section s51tb
+.section s51ua
+.section s51ub
+.section s51va
+.section s51vb
+.section s51wa
+.section s51wb
+.section s51xa
+.section s51xb
+.section s51ya
+.section s51yb
+.section s51za
+.section s51zb
+.section s511a
+.section s511b
+.section s512a
+.section s512b
+.section s513a
+.section s513b
+.section s514a
+.section s514b
+.section s515a
+.section s515b
+.section s516a
+.section s516b
+.section s517a
+.section s517b
+.section s518a
+.section s518b
+.section s519a
+.section s519b
+.section s510a
+.section s510b
+.section s52aa
+.section s52ab
+.section s52ba
+.section s52bb
+.section s52ca
+.section s52cb
+.section s52da
+.section s52db
+.section s52ea
+.section s52eb
+.section s52fa
+.section s52fb
+.section s52ga
+.section s52gb
+.section s52ha
+.section s52hb
+.section s52ia
+.section s52ib
+.section s52ja
+.section s52jb
+.section s52ka
+.section s52kb
+.section s52la
+.section s52lb
+.section s52ma
+.section s52mb
+.section s52na
+.section s52nb
+.section s52oa
+.section s52ob
+.section s52pa
+.section s52pb
+.section s52qa
+.section s52qb
+.section s52ra
+.section s52rb
+.section s52sa
+.section s52sb
+.section s52ta
+.section s52tb
+.section s52ua
+.section s52ub
+.section s52va
+.section s52vb
+.section s52wa
+.section s52wb
+.section s52xa
+.section s52xb
+.section s52ya
+.section s52yb
+.section s52za
+.section s52zb
+.section s521a
+.section s521b
+.section s522a
+.section s522b
+.section s523a
+.section s523b
+.section s524a
+.section s524b
+.section s525a
+.section s525b
+.section s526a
+.section s526b
+.section s527a
+.section s527b
+.section s528a
+.section s528b
+.section s529a
+.section s529b
+.section s520a
+.section s520b
+.section s53aa
+.section s53ab
+.section s53ba
+.section s53bb
+.section s53ca
+.section s53cb
+.section s53da
+.section s53db
+.section s53ea
+.section s53eb
+.section s53fa
+.section s53fb
+.section s53ga
+.section s53gb
+.section s53ha
+.section s53hb
+.section s53ia
+.section s53ib
+.section s53ja
+.section s53jb
+.section s53ka
+.section s53kb
+.section s53la
+.section s53lb
+.section s53ma
+.section s53mb
+.section s53na
+.section s53nb
+.section s53oa
+.section s53ob
+.section s53pa
+.section s53pb
+.section s53qa
+.section s53qb
+.section s53ra
+.section s53rb
+.section s53sa
+.section s53sb
+.section s53ta
+.section s53tb
+.section s53ua
+.section s53ub
+.section s53va
+.section s53vb
+.section s53wa
+.section s53wb
+.section s53xa
+.section s53xb
+.section s53ya
+.section s53yb
+.section s53za
+.section s53zb
+.section s531a
+.section s531b
+.section s532a
+.section s532b
+.section s533a
+.section s533b
+.section s534a
+.section s534b
+.section s535a
+.section s535b
+.section s536a
+.section s536b
+.section s537a
+.section s537b
+.section s538a
+.section s538b
+.section s539a
+.section s539b
+.section s530a
+.section s530b
+.section s54aa
+.section s54ab
+.section s54ba
+.section s54bb
+.section s54ca
+.section s54cb
+.section s54da
+.section s54db
+.section s54ea
+.section s54eb
+.section s54fa
+.section s54fb
+.section s54ga
+.section s54gb
+.section s54ha
+.section s54hb
+.section s54ia
+.section s54ib
+.section s54ja
+.section s54jb
+.section s54ka
+.section s54kb
+.section s54la
+.section s54lb
+.section s54ma
+.section s54mb
+.section s54na
+.section s54nb
+.section s54oa
+.section s54ob
+.section s54pa
+.section s54pb
+.section s54qa
+.section s54qb
+.section s54ra
+.section s54rb
+.section s54sa
+.section s54sb
+.section s54ta
+.section s54tb
+.section s54ua
+.section s54ub
+.section s54va
+.section s54vb
+.section s54wa
+.section s54wb
+.section s54xa
+.section s54xb
+.section s54ya
+.section s54yb
+.section s54za
+.section s54zb
+.section s541a
+.section s541b
+.section s542a
+.section s542b
+.section s543a
+.section s543b
+.section s544a
+.section s544b
+.section s545a
+.section s545b
+.section s546a
+.section s546b
+.section s547a
+.section s547b
+.section s548a
+.section s548b
+.section s549a
+.section s549b
+.section s540a
+.section s540b
+.section s55aa
+.section s55ab
+.section s55ba
+.section s55bb
+.section s55ca
+.section s55cb
+.section s55da
+.section s55db
+.section s55ea
+.section s55eb
+.section s55fa
+.section s55fb
+.section s55ga
+.section s55gb
+.section s55ha
+.section s55hb
+.section s55ia
+.section s55ib
+.section s55ja
+.section s55jb
+.section s55ka
+.section s55kb
+.section s55la
+.section s55lb
+.section s55ma
+.section s55mb
+.section s55na
+.section s55nb
+.section s55oa
+.section s55ob
+.section s55pa
+.section s55pb
+.section s55qa
+.section s55qb
+.section s55ra
+.section s55rb
+.section s55sa
+.section s55sb
+.section s55ta
+.section s55tb
+.section s55ua
+.section s55ub
+.section s55va
+.section s55vb
+.section s55wa
+.section s55wb
+.section s55xa
+.section s55xb
+.section s55ya
+.section s55yb
+.section s55za
+.section s55zb
+.section s551a
+.section s551b
+.section s552a
+.section s552b
+.section s553a
+.section s553b
+.section s554a
+.section s554b
+.section s555a
+.section s555b
+.section s556a
+.section s556b
+.section s557a
+.section s557b
+.section s558a
+.section s558b
+.section s559a
+.section s559b
+.section s550a
+.section s550b
+.section s56aa
+.section s56ab
+.section s56ba
+.section s56bb
+.section s56ca
+.section s56cb
+.section s56da
+.section s56db
+.section s56ea
+.section s56eb
+.section s56fa
+.section s56fb
+.section s56ga
+.section s56gb
+.section s56ha
+.section s56hb
+.section s56ia
+.section s56ib
+.section s56ja
+.section s56jb
+.section s56ka
+.section s56kb
+.section s56la
+.section s56lb
+.section s56ma
+.section s56mb
+.section s56na
+.section s56nb
+.section s56oa
+.section s56ob
+.section s56pa
+.section s56pb
+.section s56qa
+.section s56qb
+.section s56ra
+.section s56rb
+.section s56sa
+.section s56sb
+.section s56ta
+.section s56tb
+.section s56ua
+.section s56ub
+.section s56va
+.section s56vb
+.section s56wa
+.section s56wb
+.section s56xa
+.section s56xb
+.section s56ya
+.section s56yb
+.section s56za
+.section s56zb
+.section s561a
+.section s561b
+.section s562a
+.section s562b
+.section s563a
+.section s563b
+.section s564a
+.section s564b
+.section s565a
+.section s565b
+.section s566a
+.section s566b
+.section s567a
+.section s567b
+.section s568a
+.section s568b
+.section s569a
+.section s569b
+.section s560a
+.section s560b
+.section s57aa
+.section s57ab
+.section s57ba
+.section s57bb
+.section s57ca
+.section s57cb
+.section s57da
+.section s57db
+.section s57ea
+.section s57eb
+.section s57fa
+.section s57fb
+.section s57ga
+.section s57gb
+.section s57ha
+.section s57hb
+.section s57ia
+.section s57ib
+.section s57ja
+.section s57jb
+.section s57ka
+.section s57kb
+.section s57la
+.section s57lb
+.section s57ma
+.section s57mb
+.section s57na
+.section s57nb
+.section s57oa
+.section s57ob
+.section s57pa
+.section s57pb
+.section s57qa
+.section s57qb
+.section s57ra
+.section s57rb
+.section s57sa
+.section s57sb
+.section s57ta
+.section s57tb
+.section s57ua
+.section s57ub
+.section s57va
+.section s57vb
+.section s57wa
+.section s57wb
+.section s57xa
+.section s57xb
+.section s57ya
+.section s57yb
+.section s57za
+.section s57zb
+.section s571a
+.section s571b
+.section s572a
+.section s572b
+.section s573a
+.section s573b
+.section s574a
+.section s574b
+.section s575a
+.section s575b
+.section s576a
+.section s576b
+.section s577a
+.section s577b
+.section s578a
+.section s578b
+.section s579a
+.section s579b
+.section s570a
+.section s570b
+.section s58aa
+.section s58ab
+.section s58ba
+.section s58bb
+.section s58ca
+.section s58cb
+.section s58da
+.section s58db
+.section s58ea
+.section s58eb
+.section s58fa
+.section s58fb
+.section s58ga
+.section s58gb
+.section s58ha
+.section s58hb
+.section s58ia
+.section s58ib
+.section s58ja
+.section s58jb
+.section s58ka
+.section s58kb
+.section s58la
+.section s58lb
+.section s58ma
+.section s58mb
+.section s58na
+.section s58nb
+.section s58oa
+.section s58ob
+.section s58pa
+.section s58pb
+.section s58qa
+.section s58qb
+.section s58ra
+.section s58rb
+.section s58sa
+.section s58sb
+.section s58ta
+.section s58tb
+.section s58ua
+.section s58ub
+.section s58va
+.section s58vb
+.section s58wa
+.section s58wb
+.section s58xa
+.section s58xb
+.section s58ya
+.section s58yb
+.section s58za
+.section s58zb
+.section s581a
+.section s581b
+.section s582a
+.section s582b
+.section s583a
+.section s583b
+.section s584a
+.section s584b
+.section s585a
+.section s585b
+.section s586a
+.section s586b
+.section s587a
+.section s587b
+.section s588a
+.section s588b
+.section s589a
+.section s589b
+.section s580a
+.section s580b
+.section s59aa
+.section s59ab
+.section s59ba
+.section s59bb
+.section s59ca
+.section s59cb
+.section s59da
+.section s59db
+.section s59ea
+.section s59eb
+.section s59fa
+.section s59fb
+.section s59ga
+.section s59gb
+.section s59ha
+.section s59hb
+.section s59ia
+.section s59ib
+.section s59ja
+.section s59jb
+.section s59ka
+.section s59kb
+.section s59la
+.section s59lb
+.section s59ma
+.section s59mb
+.section s59na
+.section s59nb
+.section s59oa
+.section s59ob
+.section s59pa
+.section s59pb
+.section s59qa
+.section s59qb
+.section s59ra
+.section s59rb
+.section s59sa
+.section s59sb
+.section s59ta
+.section s59tb
+.section s59ua
+.section s59ub
+.section s59va
+.section s59vb
+.section s59wa
+.section s59wb
+.section s59xa
+.section s59xb
+.section s59ya
+.section s59yb
+.section s59za
+.section s59zb
+.section s591a
+.section s591b
+.section s592a
+.section s592b
+.section s593a
+.section s593b
+.section s594a
+.section s594b
+.section s595a
+.section s595b
+.section s596a
+.section s596b
+.section s597a
+.section s597b
+.section s598a
+.section s598b
+.section s599a
+.section s599b
+.section s590a
+.section s590b
+.section s50aa
+.section s50ab
+.section s50ba
+.section s50bb
+.section s50ca
+.section s50cb
+.section s50da
+.section s50db
+.section s50ea
+.section s50eb
+.section s50fa
+.section s50fb
+.section s50ga
+.section s50gb
+.section s50ha
+.section s50hb
+.section s50ia
+.section s50ib
+.section s50ja
+.section s50jb
+.section s50ka
+.section s50kb
+.section s50la
+.section s50lb
+.section s50ma
+.section s50mb
+.section s50na
+.section s50nb
+.section s50oa
+.section s50ob
+.section s50pa
+.section s50pb
+.section s50qa
+.section s50qb
+.section s50ra
+.section s50rb
+.section s50sa
+.section s50sb
+.section s50ta
+.section s50tb
+.section s50ua
+.section s50ub
+.section s50va
+.section s50vb
+.section s50wa
+.section s50wb
+.section s50xa
+.section s50xb
+.section s50ya
+.section s50yb
+.section s50za
+.section s50zb
+.section s501a
+.section s501b
+.section s502a
+.section s502b
+.section s503a
+.section s503b
+.section s504a
+.section s504b
+.section s505a
+.section s505b
+.section s506a
+.section s506b
+.section s507a
+.section s507b
+.section s508a
+.section s508b
+.section s509a
+.section s509b
+.section s500a
+.section s500b
+.section s6aaa
+.section s6aab
+.section s6aba
+.section s6abb
+.section s6aca
+.section s6acb
+.section s6ada
+.section s6adb
+.section s6aea
+.section s6aeb
+.section s6afa
+.section s6afb
+.section s6aga
+.section s6agb
+.section s6aha
+.section s6ahb
+.section s6aia
+.section s6aib
+.section s6aja
+.section s6ajb
+.section s6aka
+.section s6akb
+.section s6ala
+.section s6alb
+.section s6ama
+.section s6amb
+.section s6ana
+.section s6anb
+.section s6aoa
+.section s6aob
+.section s6apa
+.section s6apb
+.section s6aqa
+.section s6aqb
+.section s6ara
+.section s6arb
+.section s6asa
+.section s6asb
+.section s6ata
+.section s6atb
+.section s6aua
+.section s6aub
+.section s6ava
+.section s6avb
+.section s6awa
+.section s6awb
+.section s6axa
+.section s6axb
+.section s6aya
+.section s6ayb
+.section s6aza
+.section s6azb
+.section s6a1a
+.section s6a1b
+.section s6a2a
+.section s6a2b
+.section s6a3a
+.section s6a3b
+.section s6a4a
+.section s6a4b
+.section s6a5a
+.section s6a5b
+.section s6a6a
+.section s6a6b
+.section s6a7a
+.section s6a7b
+.section s6a8a
+.section s6a8b
+.section s6a9a
+.section s6a9b
+.section s6a0a
+.section s6a0b
+.section s6baa
+.section s6bab
+.section s6bba
+.section s6bbb
+.section s6bca
+.section s6bcb
+.section s6bda
+.section s6bdb
+.section s6bea
+.section s6beb
+.section s6bfa
+.section s6bfb
+.section s6bga
+.section s6bgb
+.section s6bha
+.section s6bhb
+.section s6bia
+.section s6bib
+.section s6bja
+.section s6bjb
+.section s6bka
+.section s6bkb
+.section s6bla
+.section s6blb
+.section s6bma
+.section s6bmb
+.section s6bna
+.section s6bnb
+.section s6boa
+.section s6bob
+.section s6bpa
+.section s6bpb
+.section s6bqa
+.section s6bqb
+.section s6bra
+.section s6brb
+.section s6bsa
+.section s6bsb
+.section s6bta
+.section s6btb
+.section s6bua
+.section s6bub
+.section s6bva
+.section s6bvb
+.section s6bwa
+.section s6bwb
+.section s6bxa
+.section s6bxb
+.section s6bya
+.section s6byb
+.section s6bza
+.section s6bzb
+.section s6b1a
+.section s6b1b
+.section s6b2a
+.section s6b2b
+.section s6b3a
+.section s6b3b
+.section s6b4a
+.section s6b4b
+.section s6b5a
+.section s6b5b
+.section s6b6a
+.section s6b6b
+.section s6b7a
+.section s6b7b
+.section s6b8a
+.section s6b8b
+.section s6b9a
+.section s6b9b
+.section s6b0a
+.section s6b0b
+.section s6caa
+.section s6cab
+.section s6cba
+.section s6cbb
+.section s6cca
+.section s6ccb
+.section s6cda
+.section s6cdb
+.section s6cea
+.section s6ceb
+.section s6cfa
+.section s6cfb
+.section s6cga
+.section s6cgb
+.section s6cha
+.section s6chb
+.section s6cia
+.section s6cib
+.section s6cja
+.section s6cjb
+.section s6cka
+.section s6ckb
+.section s6cla
+.section s6clb
+.section s6cma
+.section s6cmb
+.section s6cna
+.section s6cnb
+.section s6coa
+.section s6cob
+.section s6cpa
+.section s6cpb
+.section s6cqa
+.section s6cqb
+.section s6cra
+.section s6crb
+.section s6csa
+.section s6csb
+.section s6cta
+.section s6ctb
+.section s6cua
+.section s6cub
+.section s6cva
+.section s6cvb
+.section s6cwa
+.section s6cwb
+.section s6cxa
+.section s6cxb
+.section s6cya
+.section s6cyb
+.section s6cza
+.section s6czb
+.section s6c1a
+.section s6c1b
+.section s6c2a
+.section s6c2b
+.section s6c3a
+.section s6c3b
+.section s6c4a
+.section s6c4b
+.section s6c5a
+.section s6c5b
+.section s6c6a
+.section s6c6b
+.section s6c7a
+.section s6c7b
+.section s6c8a
+.section s6c8b
+.section s6c9a
+.section s6c9b
+.section s6c0a
+.section s6c0b
+.section s6daa
+.section s6dab
+.section s6dba
+.section s6dbb
+.section s6dca
+.section s6dcb
+.section s6dda
+.section s6ddb
+.section s6dea
+.section s6deb
+.section s6dfa
+.section s6dfb
+.section s6dga
+.section s6dgb
+.section s6dha
+.section s6dhb
+.section s6dia
+.section s6dib
+.section s6dja
+.section s6djb
+.section s6dka
+.section s6dkb
+.section s6dla
+.section s6dlb
+.section s6dma
+.section s6dmb
+.section s6dna
+.section s6dnb
+.section s6doa
+.section s6dob
+.section s6dpa
+.section s6dpb
+.section s6dqa
+.section s6dqb
+.section s6dra
+.section s6drb
+.section s6dsa
+.section s6dsb
+.section s6dta
+.section s6dtb
+.section s6dua
+.section s6dub
+.section s6dva
+.section s6dvb
+.section s6dwa
+.section s6dwb
+.section s6dxa
+.section s6dxb
+.section s6dya
+.section s6dyb
+.section s6dza
+.section s6dzb
+.section s6d1a
+.section s6d1b
+.section s6d2a
+.section s6d2b
+.section s6d3a
+.section s6d3b
+.section s6d4a
+.section s6d4b
+.section s6d5a
+.section s6d5b
+.section s6d6a
+.section s6d6b
+.section s6d7a
+.section s6d7b
+.section s6d8a
+.section s6d8b
+.section s6d9a
+.section s6d9b
+.section s6d0a
+.section s6d0b
+.section s6eaa
+.section s6eab
+.section s6eba
+.section s6ebb
+.section s6eca
+.section s6ecb
+.section s6eda
+.section s6edb
+.section s6eea
+.section s6eeb
+.section s6efa
+.section s6efb
+.section s6ega
+.section s6egb
+.section s6eha
+.section s6ehb
+.section s6eia
+.section s6eib
+.section s6eja
+.section s6ejb
+.section s6eka
+.section s6ekb
+.section s6ela
+.section s6elb
+.section s6ema
+.section s6emb
+.section s6ena
+.section s6enb
+.section s6eoa
+.section s6eob
+.section s6epa
+.section s6epb
+.section s6eqa
+.section s6eqb
+.section s6era
+.section s6erb
+.section s6esa
+.section s6esb
+.section s6eta
+.section s6etb
+.section s6eua
+.section s6eub
+.section s6eva
+.section s6evb
+.section s6ewa
+.section s6ewb
+.section s6exa
+.section s6exb
+.section s6eya
+.section s6eyb
+.section s6eza
+.section s6ezb
+.section s6e1a
+.section s6e1b
+.section s6e2a
+.section s6e2b
+.section s6e3a
+.section s6e3b
+.section s6e4a
+.section s6e4b
+.section s6e5a
+.section s6e5b
+.section s6e6a
+.section s6e6b
+.section s6e7a
+.section s6e7b
+.section s6e8a
+.section s6e8b
+.section s6e9a
+.section s6e9b
+.section s6e0a
+.section s6e0b
+.section s6faa
+.section s6fab
+.section s6fba
+.section s6fbb
+.section s6fca
+.section s6fcb
+.section s6fda
+.section s6fdb
+.section s6fea
+.section s6feb
+.section s6ffa
+.section s6ffb
+.section s6fga
+.section s6fgb
+.section s6fha
+.section s6fhb
+.section s6fia
+.section s6fib
+.section s6fja
+.section s6fjb
+.section s6fka
+.section s6fkb
+.section s6fla
+.section s6flb
+.section s6fma
+.section s6fmb
+.section s6fna
+.section s6fnb
+.section s6foa
+.section s6fob
+.section s6fpa
+.section s6fpb
+.section s6fqa
+.section s6fqb
+.section s6fra
+.section s6frb
+.section s6fsa
+.section s6fsb
+.section s6fta
+.section s6ftb
+.section s6fua
+.section s6fub
+.section s6fva
+.section s6fvb
+.section s6fwa
+.section s6fwb
+.section s6fxa
+.section s6fxb
+.section s6fya
+.section s6fyb
+.section s6fza
+.section s6fzb
+.section s6f1a
+.section s6f1b
+.section s6f2a
+.section s6f2b
+.section s6f3a
+.section s6f3b
+.section s6f4a
+.section s6f4b
+.section s6f5a
+.section s6f5b
+.section s6f6a
+.section s6f6b
+.section s6f7a
+.section s6f7b
+.section s6f8a
+.section s6f8b
+.section s6f9a
+.section s6f9b
+.section s6f0a
+.section s6f0b
+.section s6gaa
+.section s6gab
+.section s6gba
+.section s6gbb
+.section s6gca
+.section s6gcb
+.section s6gda
+.section s6gdb
+.section s6gea
+.section s6geb
+.section s6gfa
+.section s6gfb
+.section s6gga
+.section s6ggb
+.section s6gha
+.section s6ghb
+.section s6gia
+.section s6gib
+.section s6gja
+.section s6gjb
+.section s6gka
+.section s6gkb
+.section s6gla
+.section s6glb
+.section s6gma
+.section s6gmb
+.section s6gna
+.section s6gnb
+.section s6goa
+.section s6gob
+.section s6gpa
+.section s6gpb
+.section s6gqa
+.section s6gqb
+.section s6gra
+.section s6grb
+.section s6gsa
+.section s6gsb
+.section s6gta
+.section s6gtb
+.section s6gua
+.section s6gub
+.section s6gva
+.section s6gvb
+.section s6gwa
+.section s6gwb
+.section s6gxa
+.section s6gxb
+.section s6gya
+.section s6gyb
+.section s6gza
+.section s6gzb
+.section s6g1a
+.section s6g1b
+.section s6g2a
+.section s6g2b
+.section s6g3a
+.section s6g3b
+.section s6g4a
+.section s6g4b
+.section s6g5a
+.section s6g5b
+.section s6g6a
+.section s6g6b
+.section s6g7a
+.section s6g7b
+.section s6g8a
+.section s6g8b
+.section s6g9a
+.section s6g9b
+.section s6g0a
+.section s6g0b
+.section s6haa
+.section s6hab
+.section s6hba
+.section s6hbb
+.section s6hca
+.section s6hcb
+.section s6hda
+.section s6hdb
+.section s6hea
+.section s6heb
+.section s6hfa
+.section s6hfb
+.section s6hga
+.section s6hgb
+.section s6hha
+.section s6hhb
+.section s6hia
+.section s6hib
+.section s6hja
+.section s6hjb
+.section s6hka
+.section s6hkb
+.section s6hla
+.section s6hlb
+.section s6hma
+.section s6hmb
+.section s6hna
+.section s6hnb
+.section s6hoa
+.section s6hob
+.section s6hpa
+.section s6hpb
+.section s6hqa
+.section s6hqb
+.section s6hra
+.section s6hrb
+.section s6hsa
+.section s6hsb
+.section s6hta
+.section s6htb
+.section s6hua
+.section s6hub
+.section s6hva
+.section s6hvb
+.section s6hwa
+.section s6hwb
+.section s6hxa
+.section s6hxb
+.section s6hya
+.section s6hyb
+.section s6hza
+.section s6hzb
+.section s6h1a
+.section s6h1b
+.section s6h2a
+.section s6h2b
+.section s6h3a
+.section s6h3b
+.section s6h4a
+.section s6h4b
+.section s6h5a
+.section s6h5b
+.section s6h6a
+.section s6h6b
+.section s6h7a
+.section s6h7b
+.section s6h8a
+.section s6h8b
+.section s6h9a
+.section s6h9b
+.section s6h0a
+.section s6h0b
+.section s6iaa
+.section s6iab
+.section s6iba
+.section s6ibb
+.section s6ica
+.section s6icb
+.section s6ida
+.section s6idb
+.section s6iea
+.section s6ieb
+.section s6ifa
+.section s6ifb
+.section s6iga
+.section s6igb
+.section s6iha
+.section s6ihb
+.section s6iia
+.section s6iib
+.section s6ija
+.section s6ijb
+.section s6ika
+.section s6ikb
+.section s6ila
+.section s6ilb
+.section s6ima
+.section s6imb
+.section s6ina
+.section s6inb
+.section s6ioa
+.section s6iob
+.section s6ipa
+.section s6ipb
+.section s6iqa
+.section s6iqb
+.section s6ira
+.section s6irb
+.section s6isa
+.section s6isb
+.section s6ita
+.section s6itb
+.section s6iua
+.section s6iub
+.section s6iva
+.section s6ivb
+.section s6iwa
+.section s6iwb
+.section s6ixa
+.section s6ixb
+.section s6iya
+.section s6iyb
+.section s6iza
+.section s6izb
+.section s6i1a
+.section s6i1b
+.section s6i2a
+.section s6i2b
+.section s6i3a
+.section s6i3b
+.section s6i4a
+.section s6i4b
+.section s6i5a
+.section s6i5b
+.section s6i6a
+.section s6i6b
+.section s6i7a
+.section s6i7b
+.section s6i8a
+.section s6i8b
+.section s6i9a
+.section s6i9b
+.section s6i0a
+.section s6i0b
+.section s6jaa
+.section s6jab
+.section s6jba
+.section s6jbb
+.section s6jca
+.section s6jcb
+.section s6jda
+.section s6jdb
+.section s6jea
+.section s6jeb
+.section s6jfa
+.section s6jfb
+.section s6jga
+.section s6jgb
+.section s6jha
+.section s6jhb
+.section s6jia
+.section s6jib
+.section s6jja
+.section s6jjb
+.section s6jka
+.section s6jkb
+.section s6jla
+.section s6jlb
+.section s6jma
+.section s6jmb
+.section s6jna
+.section s6jnb
+.section s6joa
+.section s6job
+.section s6jpa
+.section s6jpb
+.section s6jqa
+.section s6jqb
+.section s6jra
+.section s6jrb
+.section s6jsa
+.section s6jsb
+.section s6jta
+.section s6jtb
+.section s6jua
+.section s6jub
+.section s6jva
+.section s6jvb
+.section s6jwa
+.section s6jwb
+.section s6jxa
+.section s6jxb
+.section s6jya
+.section s6jyb
+.section s6jza
+.section s6jzb
+.section s6j1a
+.section s6j1b
+.section s6j2a
+.section s6j2b
+.section s6j3a
+.section s6j3b
+.section s6j4a
+.section s6j4b
+.section s6j5a
+.section s6j5b
+.section s6j6a
+.section s6j6b
+.section s6j7a
+.section s6j7b
+.section s6j8a
+.section s6j8b
+.section s6j9a
+.section s6j9b
+.section s6j0a
+.section s6j0b
+.section s6kaa
+.section s6kab
+.section s6kba
+.section s6kbb
+.section s6kca
+.section s6kcb
+.section s6kda
+.section s6kdb
+.section s6kea
+.section s6keb
+.section s6kfa
+.section s6kfb
+.section s6kga
+.section s6kgb
+.section s6kha
+.section s6khb
+.section s6kia
+.section s6kib
+.section s6kja
+.section s6kjb
+.section s6kka
+.section s6kkb
+.section s6kla
+.section s6klb
+.section s6kma
+.section s6kmb
+.section s6kna
+.section s6knb
+.section s6koa
+.section s6kob
+.section s6kpa
+.section s6kpb
+.section s6kqa
+.section s6kqb
+.section s6kra
+.section s6krb
+.section s6ksa
+.section s6ksb
+.section s6kta
+.section s6ktb
+.section s6kua
+.section s6kub
+.section s6kva
+.section s6kvb
+.section s6kwa
+.section s6kwb
+.section s6kxa
+.section s6kxb
+.section s6kya
+.section s6kyb
+.section s6kza
+.section s6kzb
+.section s6k1a
+.section s6k1b
+.section s6k2a
+.section s6k2b
+.section s6k3a
+.section s6k3b
+.section s6k4a
+.section s6k4b
+.section s6k5a
+.section s6k5b
+.section s6k6a
+.section s6k6b
+.section s6k7a
+.section s6k7b
+.section s6k8a
+.section s6k8b
+.section s6k9a
+.section s6k9b
+.section s6k0a
+.section s6k0b
+.section s6laa
+.section s6lab
+.section s6lba
+.section s6lbb
+.section s6lca
+.section s6lcb
+.section s6lda
+.section s6ldb
+.section s6lea
+.section s6leb
+.section s6lfa
+.section s6lfb
+.section s6lga
+.section s6lgb
+.section s6lha
+.section s6lhb
+.section s6lia
+.section s6lib
+.section s6lja
+.section s6ljb
+.section s6lka
+.section s6lkb
+.section s6lla
+.section s6llb
+.section s6lma
+.section s6lmb
+.section s6lna
+.section s6lnb
+.section s6loa
+.section s6lob
+.section s6lpa
+.section s6lpb
+.section s6lqa
+.section s6lqb
+.section s6lra
+.section s6lrb
+.section s6lsa
+.section s6lsb
+.section s6lta
+.section s6ltb
+.section s6lua
+.section s6lub
+.section s6lva
+.section s6lvb
+.section s6lwa
+.section s6lwb
+.section s6lxa
+.section s6lxb
+.section s6lya
+.section s6lyb
+.section s6lza
+.section s6lzb
+.section s6l1a
+.section s6l1b
+.section s6l2a
+.section s6l2b
+.section s6l3a
+.section s6l3b
+.section s6l4a
+.section s6l4b
+.section s6l5a
+.section s6l5b
+.section s6l6a
+.section s6l6b
+.section s6l7a
+.section s6l7b
+.section s6l8a
+.section s6l8b
+.section s6l9a
+.section s6l9b
+.section s6l0a
+.section s6l0b
+.section s6maa
+.section s6mab
+.section s6mba
+.section s6mbb
+.section s6mca
+.section s6mcb
+.section s6mda
+.section s6mdb
+.section s6mea
+.section s6meb
+.section s6mfa
+.section s6mfb
+.section s6mga
+.section s6mgb
+.section s6mha
+.section s6mhb
+.section s6mia
+.section s6mib
+.section s6mja
+.section s6mjb
+.section s6mka
+.section s6mkb
+.section s6mla
+.section s6mlb
+.section s6mma
+.section s6mmb
+.section s6mna
+.section s6mnb
+.section s6moa
+.section s6mob
+.section s6mpa
+.section s6mpb
+.section s6mqa
+.section s6mqb
+.section s6mra
+.section s6mrb
+.section s6msa
+.section s6msb
+.section s6mta
+.section s6mtb
+.section s6mua
+.section s6mub
+.section s6mva
+.section s6mvb
+.section s6mwa
+.section s6mwb
+.section s6mxa
+.section s6mxb
+.section s6mya
+.section s6myb
+.section s6mza
+.section s6mzb
+.section s6m1a
+.section s6m1b
+.section s6m2a
+.section s6m2b
+.section s6m3a
+.section s6m3b
+.section s6m4a
+.section s6m4b
+.section s6m5a
+.section s6m5b
+.section s6m6a
+.section s6m6b
+.section s6m7a
+.section s6m7b
+.section s6m8a
+.section s6m8b
+.section s6m9a
+.section s6m9b
+.section s6m0a
+.section s6m0b
+.section s6naa
+.section s6nab
+.section s6nba
+.section s6nbb
+.section s6nca
+.section s6ncb
+.section s6nda
+.section s6ndb
+.section s6nea
+.section s6neb
+.section s6nfa
+.section s6nfb
+.section s6nga
+.section s6ngb
+.section s6nha
+.section s6nhb
+.section s6nia
+.section s6nib
+.section s6nja
+.section s6njb
+.section s6nka
+.section s6nkb
+.section s6nla
+.section s6nlb
+.section s6nma
+.section s6nmb
+.section s6nna
+.section s6nnb
+.section s6noa
+.section s6nob
+.section s6npa
+.section s6npb
+.section s6nqa
+.section s6nqb
+.section s6nra
+.section s6nrb
+.section s6nsa
+.section s6nsb
+.section s6nta
+.section s6ntb
+.section s6nua
+.section s6nub
+.section s6nva
+.section s6nvb
+.section s6nwa
+.section s6nwb
+.section s6nxa
+.section s6nxb
+.section s6nya
+.section s6nyb
+.section s6nza
+.section s6nzb
+.section s6n1a
+.section s6n1b
+.section s6n2a
+.section s6n2b
+.section s6n3a
+.section s6n3b
+.section s6n4a
+.section s6n4b
+.section s6n5a
+.section s6n5b
+.section s6n6a
+.section s6n6b
+.section s6n7a
+.section s6n7b
+.section s6n8a
+.section s6n8b
+.section s6n9a
+.section s6n9b
+.section s6n0a
+.section s6n0b
+.section s6oaa
+.section s6oab
+.section s6oba
+.section s6obb
+.section s6oca
+.section s6ocb
+.section s6oda
+.section s6odb
+.section s6oea
+.section s6oeb
+.section s6ofa
+.section s6ofb
+.section s6oga
+.section s6ogb
+.section s6oha
+.section s6ohb
+.section s6oia
+.section s6oib
+.section s6oja
+.section s6ojb
+.section s6oka
+.section s6okb
+.section s6ola
+.section s6olb
+.section s6oma
+.section s6omb
+.section s6ona
+.section s6onb
+.section s6ooa
+.section s6oob
+.section s6opa
+.section s6opb
+.section s6oqa
+.section s6oqb
+.section s6ora
+.section s6orb
+.section s6osa
+.section s6osb
+.section s6ota
+.section s6otb
+.section s6oua
+.section s6oub
+.section s6ova
+.section s6ovb
+.section s6owa
+.section s6owb
+.section s6oxa
+.section s6oxb
+.section s6oya
+.section s6oyb
+.section s6oza
+.section s6ozb
+.section s6o1a
+.section s6o1b
+.section s6o2a
+.section s6o2b
+.section s6o3a
+.section s6o3b
+.section s6o4a
+.section s6o4b
+.section s6o5a
+.section s6o5b
+.section s6o6a
+.section s6o6b
+.section s6o7a
+.section s6o7b
+.section s6o8a
+.section s6o8b
+.section s6o9a
+.section s6o9b
+.section s6o0a
+.section s6o0b
+.section s6paa
+.section s6pab
+.section s6pba
+.section s6pbb
+.section s6pca
+.section s6pcb
+.section s6pda
+.section s6pdb
+.section s6pea
+.section s6peb
+.section s6pfa
+.section s6pfb
+.section s6pga
+.section s6pgb
+.section s6pha
+.section s6phb
+.section s6pia
+.section s6pib
+.section s6pja
+.section s6pjb
+.section s6pka
+.section s6pkb
+.section s6pla
+.section s6plb
+.section s6pma
+.section s6pmb
+.section s6pna
+.section s6pnb
+.section s6poa
+.section s6pob
+.section s6ppa
+.section s6ppb
+.section s6pqa
+.section s6pqb
+.section s6pra
+.section s6prb
+.section s6psa
+.section s6psb
+.section s6pta
+.section s6ptb
+.section s6pua
+.section s6pub
+.section s6pva
+.section s6pvb
+.section s6pwa
+.section s6pwb
+.section s6pxa
+.section s6pxb
+.section s6pya
+.section s6pyb
+.section s6pza
+.section s6pzb
+.section s6p1a
+.section s6p1b
+.section s6p2a
+.section s6p2b
+.section s6p3a
+.section s6p3b
+.section s6p4a
+.section s6p4b
+.section s6p5a
+.section s6p5b
+.section s6p6a
+.section s6p6b
+.section s6p7a
+.section s6p7b
+.section s6p8a
+.section s6p8b
+.section s6p9a
+.section s6p9b
+.section s6p0a
+.section s6p0b
+.section s6qaa
+.section s6qab
+.section s6qba
+.section s6qbb
+.section s6qca
+.section s6qcb
+.section s6qda
+.section s6qdb
+.section s6qea
+.section s6qeb
+.section s6qfa
+.section s6qfb
+.section s6qga
+.section s6qgb
+.section s6qha
+.section s6qhb
+.section s6qia
+.section s6qib
+.section s6qja
+.section s6qjb
+.section s6qka
+.section s6qkb
+.section s6qla
+.section s6qlb
+.section s6qma
+.section s6qmb
+.section s6qna
+.section s6qnb
+.section s6qoa
+.section s6qob
+.section s6qpa
+.section s6qpb
+.section s6qqa
+.section s6qqb
+.section s6qra
+.section s6qrb
+.section s6qsa
+.section s6qsb
+.section s6qta
+.section s6qtb
+.section s6qua
+.section s6qub
+.section s6qva
+.section s6qvb
+.section s6qwa
+.section s6qwb
+.section s6qxa
+.section s6qxb
+.section s6qya
+.section s6qyb
+.section s6qza
+.section s6qzb
+.section s6q1a
+.section s6q1b
+.section s6q2a
+.section s6q2b
+.section s6q3a
+.section s6q3b
+.section s6q4a
+.section s6q4b
+.section s6q5a
+.section s6q5b
+.section s6q6a
+.section s6q6b
+.section s6q7a
+.section s6q7b
+.section s6q8a
+.section s6q8b
+.section s6q9a
+.section s6q9b
+.section s6q0a
+.section s6q0b
+.section s6raa
+.section s6rab
+.section s6rba
+.section s6rbb
+.section s6rca
+.section s6rcb
+.section s6rda
+.section s6rdb
+.section s6rea
+.section s6reb
+.section s6rfa
+.section s6rfb
+.section s6rga
+.section s6rgb
+.section s6rha
+.section s6rhb
+.section s6ria
+.section s6rib
+.section s6rja
+.section s6rjb
+.section s6rka
+.section s6rkb
+.section s6rla
+.section s6rlb
+.section s6rma
+.section s6rmb
+.section s6rna
+.section s6rnb
+.section s6roa
+.section s6rob
+.section s6rpa
+.section s6rpb
+.section s6rqa
+.section s6rqb
+.section s6rra
+.section s6rrb
+.section s6rsa
+.section s6rsb
+.section s6rta
+.section s6rtb
+.section s6rua
+.section s6rub
+.section s6rva
+.section s6rvb
+.section s6rwa
+.section s6rwb
+.section s6rxa
+.section s6rxb
+.section s6rya
+.section s6ryb
+.section s6rza
+.section s6rzb
+.section s6r1a
+.section s6r1b
+.section s6r2a
+.section s6r2b
+.section s6r3a
+.section s6r3b
+.section s6r4a
+.section s6r4b
+.section s6r5a
+.section s6r5b
+.section s6r6a
+.section s6r6b
+.section s6r7a
+.section s6r7b
+.section s6r8a
+.section s6r8b
+.section s6r9a
+.section s6r9b
+.section s6r0a
+.section s6r0b
+.section s6saa
+.section s6sab
+.section s6sba
+.section s6sbb
+.section s6sca
+.section s6scb
+.section s6sda
+.section s6sdb
+.section s6sea
+.section s6seb
+.section s6sfa
+.section s6sfb
+.section s6sga
+.section s6sgb
+.section s6sha
+.section s6shb
+.section s6sia
+.section s6sib
+.section s6sja
+.section s6sjb
+.section s6ska
+.section s6skb
+.section s6sla
+.section s6slb
+.section s6sma
+.section s6smb
+.section s6sna
+.section s6snb
+.section s6soa
+.section s6sob
+.section s6spa
+.section s6spb
+.section s6sqa
+.section s6sqb
+.section s6sra
+.section s6srb
+.section s6ssa
+.section s6ssb
+.section s6sta
+.section s6stb
+.section s6sua
+.section s6sub
+.section s6sva
+.section s6svb
+.section s6swa
+.section s6swb
+.section s6sxa
+.section s6sxb
+.section s6sya
+.section s6syb
+.section s6sza
+.section s6szb
+.section s6s1a
+.section s6s1b
+.section s6s2a
+.section s6s2b
+.section s6s3a
+.section s6s3b
+.section s6s4a
+.section s6s4b
+.section s6s5a
+.section s6s5b
+.section s6s6a
+.section s6s6b
+.section s6s7a
+.section s6s7b
+.section s6s8a
+.section s6s8b
+.section s6s9a
+.section s6s9b
+.section s6s0a
+.section s6s0b
+.section s6taa
+.section s6tab
+.section s6tba
+.section s6tbb
+.section s6tca
+.section s6tcb
+.section s6tda
+.section s6tdb
+.section s6tea
+.section s6teb
+.section s6tfa
+.section s6tfb
+.section s6tga
+.section s6tgb
+.section s6tha
+.section s6thb
+.section s6tia
+.section s6tib
+.section s6tja
+.section s6tjb
+.section s6tka
+.section s6tkb
+.section s6tla
+.section s6tlb
+.section s6tma
+.section s6tmb
+.section s6tna
+.section s6tnb
+.section s6toa
+.section s6tob
+.section s6tpa
+.section s6tpb
+.section s6tqa
+.section s6tqb
+.section s6tra
+.section s6trb
+.section s6tsa
+.section s6tsb
+.section s6tta
+.section s6ttb
+.section s6tua
+.section s6tub
+.section s6tva
+.section s6tvb
+.section s6twa
+.section s6twb
+.section s6txa
+.section s6txb
+.section s6tya
+.section s6tyb
+.section s6tza
+.section s6tzb
+.section s6t1a
+.section s6t1b
+.section s6t2a
+.section s6t2b
+.section s6t3a
+.section s6t3b
+.section s6t4a
+.section s6t4b
+.section s6t5a
+.section s6t5b
+.section s6t6a
+.section s6t6b
+.section s6t7a
+.section s6t7b
+.section s6t8a
+.section s6t8b
+.section s6t9a
+.section s6t9b
+.section s6t0a
+.section s6t0b
+.section s6uaa
+.section s6uab
+.section s6uba
+.section s6ubb
+.section s6uca
+.section s6ucb
+.section s6uda
+.section s6udb
+.section s6uea
+.section s6ueb
+.section s6ufa
+.section s6ufb
+.section s6uga
+.section s6ugb
+.section s6uha
+.section s6uhb
+.section s6uia
+.section s6uib
+.section s6uja
+.section s6ujb
+.section s6uka
+.section s6ukb
+.section s6ula
+.section s6ulb
+.section s6uma
+.section s6umb
+.section s6una
+.section s6unb
+.section s6uoa
+.section s6uob
+.section s6upa
+.section s6upb
+.section s6uqa
+.section s6uqb
+.section s6ura
+.section s6urb
+.section s6usa
+.section s6usb
+.section s6uta
+.section s6utb
+.section s6uua
+.section s6uub
+.section s6uva
+.section s6uvb
+.section s6uwa
+.section s6uwb
+.section s6uxa
+.section s6uxb
+.section s6uya
+.section s6uyb
+.section s6uza
+.section s6uzb
+.section s6u1a
+.section s6u1b
+.section s6u2a
+.section s6u2b
+.section s6u3a
+.section s6u3b
+.section s6u4a
+.section s6u4b
+.section s6u5a
+.section s6u5b
+.section s6u6a
+.section s6u6b
+.section s6u7a
+.section s6u7b
+.section s6u8a
+.section s6u8b
+.section s6u9a
+.section s6u9b
+.section s6u0a
+.section s6u0b
+.section s6vaa
+.section s6vab
+.section s6vba
+.section s6vbb
+.section s6vca
+.section s6vcb
+.section s6vda
+.section s6vdb
+.section s6vea
+.section s6veb
+.section s6vfa
+.section s6vfb
+.section s6vga
+.section s6vgb
+.section s6vha
+.section s6vhb
+.section s6via
+.section s6vib
+.section s6vja
+.section s6vjb
+.section s6vka
+.section s6vkb
+.section s6vla
+.section s6vlb
+.section s6vma
+.section s6vmb
+.section s6vna
+.section s6vnb
+.section s6voa
+.section s6vob
+.section s6vpa
+.section s6vpb
+.section s6vqa
+.section s6vqb
+.section s6vra
+.section s6vrb
+.section s6vsa
+.section s6vsb
+.section s6vta
+.section s6vtb
+.section s6vua
+.section s6vub
+.section s6vva
+.section s6vvb
+.section s6vwa
+.section s6vwb
+.section s6vxa
+.section s6vxb
+.section s6vya
+.section s6vyb
+.section s6vza
+.section s6vzb
+.section s6v1a
+.section s6v1b
+.section s6v2a
+.section s6v2b
+.section s6v3a
+.section s6v3b
+.section s6v4a
+.section s6v4b
+.section s6v5a
+.section s6v5b
+.section s6v6a
+.section s6v6b
+.section s6v7a
+.section s6v7b
+.section s6v8a
+.section s6v8b
+.section s6v9a
+.section s6v9b
+.section s6v0a
+.section s6v0b
+.section s6waa
+.section s6wab
+.section s6wba
+.section s6wbb
+.section s6wca
+.section s6wcb
+.section s6wda
+.section s6wdb
+.section s6wea
+.section s6web
+.section s6wfa
+.section s6wfb
+.section s6wga
+.section s6wgb
+.section s6wha
+.section s6whb
+.section s6wia
+.section s6wib
+.section s6wja
+.section s6wjb
+.section s6wka
+.section s6wkb
+.section s6wla
+.section s6wlb
+.section s6wma
+.section s6wmb
+.section s6wna
+.section s6wnb
+.section s6woa
+.section s6wob
+.section s6wpa
+.section s6wpb
+.section s6wqa
+.section s6wqb
+.section s6wra
+.section s6wrb
+.section s6wsa
+.section s6wsb
+.section s6wta
+.section s6wtb
+.section s6wua
+.section s6wub
+.section s6wva
+.section s6wvb
+.section s6wwa
+.section s6wwb
+.section s6wxa
+.section s6wxb
+.section s6wya
+.section s6wyb
+.section s6wza
+.section s6wzb
+.section s6w1a
+.section s6w1b
+.section s6w2a
+.section s6w2b
+.section s6w3a
+.section s6w3b
+.section s6w4a
+.section s6w4b
+.section s6w5a
+.section s6w5b
+.section s6w6a
+.section s6w6b
+.section s6w7a
+.section s6w7b
+.section s6w8a
+.section s6w8b
+.section s6w9a
+.section s6w9b
+.section s6w0a
+.section s6w0b
+.section s6xaa
+.section s6xab
+.section s6xba
+.section s6xbb
+.section s6xca
+.section s6xcb
+.section s6xda
+.section s6xdb
+.section s6xea
+.section s6xeb
+.section s6xfa
+.section s6xfb
+.section s6xga
+.section s6xgb
+.section s6xha
+.section s6xhb
+.section s6xia
+.section s6xib
+.section s6xja
+.section s6xjb
+.section s6xka
+.section s6xkb
+.section s6xla
+.section s6xlb
+.section s6xma
+.section s6xmb
+.section s6xna
+.section s6xnb
+.section s6xoa
+.section s6xob
+.section s6xpa
+.section s6xpb
+.section s6xqa
+.section s6xqb
+.section s6xra
+.section s6xrb
+.section s6xsa
+.section s6xsb
+.section s6xta
+.section s6xtb
+.section s6xua
+.section s6xub
+.section s6xva
+.section s6xvb
+.section s6xwa
+.section s6xwb
+.section s6xxa
+.section s6xxb
+.section s6xya
+.section s6xyb
+.section s6xza
+.section s6xzb
+.section s6x1a
+.section s6x1b
+.section s6x2a
+.section s6x2b
+.section s6x3a
+.section s6x3b
+.section s6x4a
+.section s6x4b
+.section s6x5a
+.section s6x5b
+.section s6x6a
+.section s6x6b
+.section s6x7a
+.section s6x7b
+.section s6x8a
+.section s6x8b
+.section s6x9a
+.section s6x9b
+.section s6x0a
+.section s6x0b
+.section s6yaa
+.section s6yab
+.section s6yba
+.section s6ybb
+.section s6yca
+.section s6ycb
+.section s6yda
+.section s6ydb
+.section s6yea
+.section s6yeb
+.section s6yfa
+.section s6yfb
+.section s6yga
+.section s6ygb
+.section s6yha
+.section s6yhb
+.section s6yia
+.section s6yib
+.section s6yja
+.section s6yjb
+.section s6yka
+.section s6ykb
+.section s6yla
+.section s6ylb
+.section s6yma
+.section s6ymb
+.section s6yna
+.section s6ynb
+.section s6yoa
+.section s6yob
+.section s6ypa
+.section s6ypb
+.section s6yqa
+.section s6yqb
+.section s6yra
+.section s6yrb
+.section s6ysa
+.section s6ysb
+.section s6yta
+.section s6ytb
+.section s6yua
+.section s6yub
+.section s6yva
+.section s6yvb
+.section s6ywa
+.section s6ywb
+.section s6yxa
+.section s6yxb
+.section s6yya
+.section s6yyb
+.section s6yza
+.section s6yzb
+.section s6y1a
+.section s6y1b
+.section s6y2a
+.section s6y2b
+.section s6y3a
+.section s6y3b
+.section s6y4a
+.section s6y4b
+.section s6y5a
+.section s6y5b
+.section s6y6a
+.section s6y6b
+.section s6y7a
+.section s6y7b
+.section s6y8a
+.section s6y8b
+.section s6y9a
+.section s6y9b
+.section s6y0a
+.section s6y0b
+.section s6zaa
+.section s6zab
+.section s6zba
+.section s6zbb
+.section s6zca
+.section s6zcb
+.section s6zda
+.section s6zdb
+.section s6zea
+.section s6zeb
+.section s6zfa
+.section s6zfb
+.section s6zga
+.section s6zgb
+.section s6zha
+.section s6zhb
+.section s6zia
+.section s6zib
+.section s6zja
+.section s6zjb
+.section s6zka
+.section s6zkb
+.section s6zla
+.section s6zlb
+.section s6zma
+.section s6zmb
+.section s6zna
+.section s6znb
+.section s6zoa
+.section s6zob
+.section s6zpa
+.section s6zpb
+.section s6zqa
+.section s6zqb
+.section s6zra
+.section s6zrb
+.section s6zsa
+.section s6zsb
+.section s6zta
+.section s6ztb
+.section s6zua
+.section s6zub
+.section s6zva
+.section s6zvb
+.section s6zwa
+.section s6zwb
+.section s6zxa
+.section s6zxb
+.section s6zya
+.section s6zyb
+.section s6zza
+.section s6zzb
+.section s6z1a
+.section s6z1b
+.section s6z2a
+.section s6z2b
+.section s6z3a
+.section s6z3b
+.section s6z4a
+.section s6z4b
+.section s6z5a
+.section s6z5b
+.section s6z6a
+.section s6z6b
+.section s6z7a
+.section s6z7b
+.section s6z8a
+.section s6z8b
+.section s6z9a
+.section s6z9b
+.section s6z0a
+.section s6z0b
+.section s61aa
+.section s61ab
+.section s61ba
+.section s61bb
+.section s61ca
+.section s61cb
+.section s61da
+.section s61db
+.section s61ea
+.section s61eb
+.section s61fa
+.section s61fb
+.section s61ga
+.section s61gb
+.section s61ha
+.section s61hb
+.section s61ia
+.section s61ib
+.section s61ja
+.section s61jb
+.section s61ka
+.section s61kb
+.section s61la
+.section s61lb
+.section s61ma
+.section s61mb
+.section s61na
+.section s61nb
+.section s61oa
+.section s61ob
+.section s61pa
+.section s61pb
+.section s61qa
+.section s61qb
+.section s61ra
+.section s61rb
+.section s61sa
+.section s61sb
+.section s61ta
+.section s61tb
+.section s61ua
+.section s61ub
+.section s61va
+.section s61vb
+.section s61wa
+.section s61wb
+.section s61xa
+.section s61xb
+.section s61ya
+.section s61yb
+.section s61za
+.section s61zb
+.section s611a
+.section s611b
+.section s612a
+.section s612b
+.section s613a
+.section s613b
+.section s614a
+.section s614b
+.section s615a
+.section s615b
+.section s616a
+.section s616b
+.section s617a
+.section s617b
+.section s618a
+.section s618b
+.section s619a
+.section s619b
+.section s610a
+.section s610b
+.section s62aa
+.section s62ab
+.section s62ba
+.section s62bb
+.section s62ca
+.section s62cb
+.section s62da
+.section s62db
+.section s62ea
+.section s62eb
+.section s62fa
+.section s62fb
+.section s62ga
+.section s62gb
+.section s62ha
+.section s62hb
+.section s62ia
+.section s62ib
+.section s62ja
+.section s62jb
+.section s62ka
+.section s62kb
+.section s62la
+.section s62lb
+.section s62ma
+.section s62mb
+.section s62na
+.section s62nb
+.section s62oa
+.section s62ob
+.section s62pa
+.section s62pb
+.section s62qa
+.section s62qb
+.section s62ra
+.section s62rb
+.section s62sa
+.section s62sb
+.section s62ta
+.section s62tb
+.section s62ua
+.section s62ub
+.section s62va
+.section s62vb
+.section s62wa
+.section s62wb
+.section s62xa
+.section s62xb
+.section s62ya
+.section s62yb
+.section s62za
+.section s62zb
+.section s621a
+.section s621b
+.section s622a
+.section s622b
+.section s623a
+.section s623b
+.section s624a
+.section s624b
+.section s625a
+.section s625b
+.section s626a
+.section s626b
+.section s627a
+.section s627b
+.section s628a
+.section s628b
+.section s629a
+.section s629b
+.section s620a
+.section s620b
+.section s63aa
+.section s63ab
+.section s63ba
+.section s63bb
+.section s63ca
+.section s63cb
+.section s63da
+.section s63db
+.section s63ea
+.section s63eb
+.section s63fa
+.section s63fb
+.section s63ga
+.section s63gb
+.section s63ha
+.section s63hb
+.section s63ia
+.section s63ib
+.section s63ja
+.section s63jb
+.section s63ka
+.section s63kb
+.section s63la
+.section s63lb
+.section s63ma
+.section s63mb
+.section s63na
+.section s63nb
+.section s63oa
+.section s63ob
+.section s63pa
+.section s63pb
+.section s63qa
+.section s63qb
+.section s63ra
+.section s63rb
+.section s63sa
+.section s63sb
+.section s63ta
+.section s63tb
+.section s63ua
+.section s63ub
+.section s63va
+.section s63vb
+.section s63wa
+.section s63wb
+.section s63xa
+.section s63xb
+.section s63ya
+.section s63yb
+.section s63za
+.section s63zb
+.section s631a
+.section s631b
+.section s632a
+.section s632b
+.section s633a
+.section s633b
+.section s634a
+.section s634b
+.section s635a
+.section s635b
+.section s636a
+.section s636b
+.section s637a
+.section s637b
+.section s638a
+.section s638b
+.section s639a
+.section s639b
+.section s630a
+.section s630b
+.section s64aa
+.section s64ab
+.section s64ba
+.section s64bb
+.section s64ca
+.section s64cb
+.section s64da
+.section s64db
+.section s64ea
+.section s64eb
+.section s64fa
+.section s64fb
+.section s64ga
+.section s64gb
+.section s64ha
+.section s64hb
+.section s64ia
+.section s64ib
+.section s64ja
+.section s64jb
+.section s64ka
+.section s64kb
+.section s64la
+.section s64lb
+.section s64ma
+.section s64mb
+.section s64na
+.section s64nb
+.section s64oa
+.section s64ob
+.section s64pa
+.section s64pb
+.section s64qa
+.section s64qb
+.section s64ra
+.section s64rb
+.section s64sa
+.section s64sb
+.section s64ta
+.section s64tb
+.section s64ua
+.section s64ub
+.section s64va
+.section s64vb
+.section s64wa
+.section s64wb
+.section s64xa
+.section s64xb
+.section s64ya
+.section s64yb
+.section s64za
+.section s64zb
+.section s641a
+.section s641b
+.section s642a
+.section s642b
+.section s643a
+.section s643b
+.section s644a
+.section s644b
+.section s645a
+.section s645b
+.section s646a
+.section s646b
+.section s647a
+.section s647b
+.section s648a
+.section s648b
+.section s649a
+.section s649b
+.section s640a
+.section s640b
+.section s65aa
+.section s65ab
+.section s65ba
+.section s65bb
+.section s65ca
+.section s65cb
+.section s65da
+.section s65db
+.section s65ea
+.section s65eb
+.section s65fa
+.section s65fb
+.section s65ga
+.section s65gb
+.section s65ha
+.section s65hb
+.section s65ia
+.section s65ib
+.section s65ja
+.section s65jb
+.section s65ka
+.section s65kb
+.section s65la
+.section s65lb
+.section s65ma
+.section s65mb
+.section s65na
+.section s65nb
+.section s65oa
+.section s65ob
+.section s65pa
+.section s65pb
+.section s65qa
+.section s65qb
+.section s65ra
+.section s65rb
+.section s65sa
+.section s65sb
+.section s65ta
+.section s65tb
+.section s65ua
+.section s65ub
+.section s65va
+.section s65vb
+.section s65wa
+.section s65wb
+.section s65xa
+.section s65xb
+.section s65ya
+.section s65yb
+.section s65za
+.section s65zb
+.section s651a
+.section s651b
+.section s652a
+.section s652b
+.section s653a
+.section s653b
+.section s654a
+.section s654b
+.section s655a
+.section s655b
+.section s656a
+.section s656b
+.section s657a
+.section s657b
+.section s658a
+.section s658b
+.section s659a
+.section s659b
+.section s650a
+.section s650b
+.section s66aa
+.section s66ab
+.section s66ba
+.section s66bb
+.section s66ca
+.section s66cb
+.section s66da
+.section s66db
+.section s66ea
+.section s66eb
+.section s66fa
+.section s66fb
+.section s66ga
+.section s66gb
+.section s66ha
+.section s66hb
+.section s66ia
+.section s66ib
+.section s66ja
+.section s66jb
+.section s66ka
+.section s66kb
+.section s66la
+.section s66lb
+.section s66ma
+.section s66mb
+.section s66na
+.section s66nb
+.section s66oa
+.section s66ob
+.section s66pa
+.section s66pb
+.section s66qa
+.section s66qb
+.section s66ra
+.section s66rb
+.section s66sa
+.section s66sb
+.section s66ta
+.section s66tb
+.section s66ua
+.section s66ub
+.section s66va
+.section s66vb
+.section s66wa
+.section s66wb
+.section s66xa
+.section s66xb
+.section s66ya
+.section s66yb
+.section s66za
+.section s66zb
+.section s661a
+.section s661b
+.section s662a
+.section s662b
+.section s663a
+.section s663b
+.section s664a
+.section s664b
+.section s665a
+.section s665b
+.section s666a
+.section s666b
+.section s667a
+.section s667b
+.section s668a
+.section s668b
+.section s669a
+.section s669b
+.section s660a
+.section s660b
+.section s67aa
+.section s67ab
+.section s67ba
+.section s67bb
+.section s67ca
+.section s67cb
+.section s67da
+.section s67db
+.section s67ea
+.section s67eb
+.section s67fa
+.section s67fb
+.section s67ga
+.section s67gb
+.section s67ha
+.section s67hb
+.section s67ia
+.section s67ib
+.section s67ja
+.section s67jb
+.section s67ka
+.section s67kb
+.section s67la
+.section s67lb
+.section s67ma
+.section s67mb
+.section s67na
+.section s67nb
+.section s67oa
+.section s67ob
+.section s67pa
+.section s67pb
+.section s67qa
+.section s67qb
+.section s67ra
+.section s67rb
+.section s67sa
+.section s67sb
+.section s67ta
+.section s67tb
+.section s67ua
+.section s67ub
+.section s67va
+.section s67vb
+.section s67wa
+.section s67wb
+.section s67xa
+.section s67xb
+.section s67ya
+.section s67yb
+.section s67za
+.section s67zb
+.section s671a
+.section s671b
+.section s672a
+.section s672b
+.section s673a
+.section s673b
+.section s674a
+.section s674b
+.section s675a
+.section s675b
+.section s676a
+.section s676b
+.section s677a
+.section s677b
+.section s678a
+.section s678b
+.section s679a
+.section s679b
+.section s670a
+.section s670b
+.section s68aa
+.section s68ab
+.section s68ba
+.section s68bb
+.section s68ca
+.section s68cb
+.section s68da
+.section s68db
+.section s68ea
+.section s68eb
+.section s68fa
+.section s68fb
+.section s68ga
+.section s68gb
+.section s68ha
+.section s68hb
+.section s68ia
+.section s68ib
+.section s68ja
+.section s68jb
+.section s68ka
+.section s68kb
+.section s68la
+.section s68lb
+.section s68ma
+.section s68mb
+.section s68na
+.section s68nb
+.section s68oa
+.section s68ob
+.section s68pa
+.section s68pb
+.section s68qa
+.section s68qb
+.section s68ra
+.section s68rb
+.section s68sa
+.section s68sb
+.section s68ta
+.section s68tb
+.section s68ua
+.section s68ub
+.section s68va
+.section s68vb
+.section s68wa
+.section s68wb
+.section s68xa
+.section s68xb
+.section s68ya
+.section s68yb
+.section s68za
+.section s68zb
+.section s681a
+.section s681b
+.section s682a
+.section s682b
+.section s683a
+.section s683b
+.section s684a
+.section s684b
+.section s685a
+.section s685b
+.section s686a
+.section s686b
+.section s687a
+.section s687b
+.section s688a
+.section s688b
+.section s689a
+.section s689b
+.section s680a
+.section s680b
+.section s69aa
+.section s69ab
+.section s69ba
+.section s69bb
+.section s69ca
+.section s69cb
+.section s69da
+.section s69db
+.section s69ea
+.section s69eb
+.section s69fa
+.section s69fb
+.section s69ga
+.section s69gb
+.section s69ha
+.section s69hb
+.section s69ia
+.section s69ib
+.section s69ja
+.section s69jb
+.section s69ka
+.section s69kb
+.section s69la
+.section s69lb
+.section s69ma
+.section s69mb
+.section s69na
+.section s69nb
+.section s69oa
+.section s69ob
+.section s69pa
+.section s69pb
+.section s69qa
+.section s69qb
+.section s69ra
+.section s69rb
+.section s69sa
+.section s69sb
+.section s69ta
+.section s69tb
+.section s69ua
+.section s69ub
+.section s69va
+.section s69vb
+.section s69wa
+.section s69wb
+.section s69xa
+.section s69xb
+.section s69ya
+.section s69yb
+.section s69za
+.section s69zb
+.section s691a
+.section s691b
+.section s692a
+.section s692b
+.section s693a
+.section s693b
+.section s694a
+.section s694b
+.section s695a
+.section s695b
+.section s696a
+.section s696b
+.section s697a
+.section s697b
+.section s698a
+.section s698b
+.section s699a
+.section s699b
+.section s690a
+.section s690b
+.section s60aa
+.section s60ab
+.section s60ba
+.section s60bb
+.section s60ca
+.section s60cb
+.section s60da
+.section s60db
+.section s60ea
+.section s60eb
+.section s60fa
+.section s60fb
+.section s60ga
+.section s60gb
+.section s60ha
+.section s60hb
+.section s60ia
+.section s60ib
+.section s60ja
+.section s60jb
+.section s60ka
+.section s60kb
+.section s60la
+.section s60lb
+.section s60ma
+.section s60mb
+.section s60na
+.section s60nb
+.section s60oa
+.section s60ob
+.section s60pa
+.section s60pb
+.section s60qa
+.section s60qb
+.section s60ra
+.section s60rb
+.section s60sa
+.section s60sb
+.section s60ta
+.section s60tb
+.section s60ua
+.section s60ub
+.section s60va
+.section s60vb
+.section s60wa
+.section s60wb
+.section s60xa
+.section s60xb
+.section s60ya
+.section s60yb
+.section s60za
+.section s60zb
+.section s601a
+.section s601b
+.section s602a
+.section s602b
+.section s603a
+.section s603b
+.section s604a
+.section s604b
+.section s605a
+.section s605b
+.section s606a
+.section s606b
+.section s607a
+.section s607b
+.section s608a
+.section s608b
+.section s609a
+.section s609b
+.section s600a
+.section s600b
+.section s7aaa
+.section s7aab
+.section s7aba
+.section s7abb
+.section s7aca
+.section s7acb
+.section s7ada
+.section s7adb
+.section s7aea
+.section s7aeb
+.section s7afa
+.section s7afb
+.section s7aga
+.section s7agb
+.section s7aha
+.section s7ahb
+.section s7aia
+.section s7aib
+.section s7aja
+.section s7ajb
+.section s7aka
+.section s7akb
+.section s7ala
+.section s7alb
+.section s7ama
+.section s7amb
+.section s7ana
+.section s7anb
+.section s7aoa
+.section s7aob
+.section s7apa
+.section s7apb
+.section s7aqa
+.section s7aqb
+.section s7ara
+.section s7arb
+.section s7asa
+.section s7asb
+.section s7ata
+.section s7atb
+.section s7aua
+.section s7aub
+.section s7ava
+.section s7avb
+.section s7awa
+.section s7awb
+.section s7axa
+.section s7axb
+.section s7aya
+.section s7ayb
+.section s7aza
+.section s7azb
+.section s7a1a
+.section s7a1b
+.section s7a2a
+.section s7a2b
+.section s7a3a
+.section s7a3b
+.section s7a4a
+.section s7a4b
+.section s7a5a
+.section s7a5b
+.section s7a6a
+.section s7a6b
+.section s7a7a
+.section s7a7b
+.section s7a8a
+.section s7a8b
+.section s7a9a
+.section s7a9b
+.section s7a0a
+.section s7a0b
+.section s7baa
+.section s7bab
+.section s7bba
+.section s7bbb
+.section s7bca
+.section s7bcb
+.section s7bda
+.section s7bdb
+.section s7bea
+.section s7beb
+.section s7bfa
+.section s7bfb
+.section s7bga
+.section s7bgb
+.section s7bha
+.section s7bhb
+.section s7bia
+.section s7bib
+.section s7bja
+.section s7bjb
+.section s7bka
+.section s7bkb
+.section s7bla
+.section s7blb
+.section s7bma
+.section s7bmb
+.section s7bna
+.section s7bnb
+.section s7boa
+.section s7bob
+.section s7bpa
+.section s7bpb
+.section s7bqa
+.section s7bqb
+.section s7bra
+.section s7brb
+.section s7bsa
+.section s7bsb
+.section s7bta
+.section s7btb
+.section s7bua
+.section s7bub
+.section s7bva
+.section s7bvb
+.section s7bwa
+.section s7bwb
+.section s7bxa
+.section s7bxb
+.section s7bya
+.section s7byb
+.section s7bza
+.section s7bzb
+.section s7b1a
+.section s7b1b
+.section s7b2a
+.section s7b2b
+.section s7b3a
+.section s7b3b
+.section s7b4a
+.section s7b4b
+.section s7b5a
+.section s7b5b
+.section s7b6a
+.section s7b6b
+.section s7b7a
+.section s7b7b
+.section s7b8a
+.section s7b8b
+.section s7b9a
+.section s7b9b
+.section s7b0a
+.section s7b0b
+.section s7caa
+.section s7cab
+.section s7cba
+.section s7cbb
+.section s7cca
+.section s7ccb
+.section s7cda
+.section s7cdb
+.section s7cea
+.section s7ceb
+.section s7cfa
+.section s7cfb
+.section s7cga
+.section s7cgb
+.section s7cha
+.section s7chb
+.section s7cia
+.section s7cib
+.section s7cja
+.section s7cjb
+.section s7cka
+.section s7ckb
+.section s7cla
+.section s7clb
+.section s7cma
+.section s7cmb
+.section s7cna
+.section s7cnb
+.section s7coa
+.section s7cob
+.section s7cpa
+.section s7cpb
+.section s7cqa
+.section s7cqb
+.section s7cra
+.section s7crb
+.section s7csa
+.section s7csb
+.section s7cta
+.section s7ctb
+.section s7cua
+.section s7cub
+.section s7cva
+.section s7cvb
+.section s7cwa
+.section s7cwb
+.section s7cxa
+.section s7cxb
+.section s7cya
+.section s7cyb
+.section s7cza
+.section s7czb
+.section s7c1a
+.section s7c1b
+.section s7c2a
+.section s7c2b
+.section s7c3a
+.section s7c3b
+.section s7c4a
+.section s7c4b
+.section s7c5a
+.section s7c5b
+.section s7c6a
+.section s7c6b
+.section s7c7a
+.section s7c7b
+.section s7c8a
+.section s7c8b
+.section s7c9a
+.section s7c9b
+.section s7c0a
+.section s7c0b
+.section s7daa
+.section s7dab
+.section s7dba
+.section s7dbb
+.section s7dca
+.section s7dcb
+.section s7dda
+.section s7ddb
+.section s7dea
+.section s7deb
+.section s7dfa
+.section s7dfb
+.section s7dga
+.section s7dgb
+.section s7dha
+.section s7dhb
+.section s7dia
+.section s7dib
+.section s7dja
+.section s7djb
+.section s7dka
+.section s7dkb
+.section s7dla
+.section s7dlb
+.section s7dma
+.section s7dmb
+.section s7dna
+.section s7dnb
+.section s7doa
+.section s7dob
+.section s7dpa
+.section s7dpb
+.section s7dqa
+.section s7dqb
+.section s7dra
+.section s7drb
+.section s7dsa
+.section s7dsb
+.section s7dta
+.section s7dtb
+.section s7dua
+.section s7dub
+.section s7dva
+.section s7dvb
+.section s7dwa
+.section s7dwb
+.section s7dxa
+.section s7dxb
+.section s7dya
+.section s7dyb
+.section s7dza
+.section s7dzb
+.section s7d1a
+.section s7d1b
+.section s7d2a
+.section s7d2b
+.section s7d3a
+.section s7d3b
+.section s7d4a
+.section s7d4b
+.section s7d5a
+.section s7d5b
+.section s7d6a
+.section s7d6b
+.section s7d7a
+.section s7d7b
+.section s7d8a
+.section s7d8b
+.section s7d9a
+.section s7d9b
+.section s7d0a
+.section s7d0b
+.section s7eaa
+.section s7eab
+.section s7eba
+.section s7ebb
+.section s7eca
+.section s7ecb
+.section s7eda
+.section s7edb
+.section s7eea
+.section s7eeb
+.section s7efa
+.section s7efb
+.section s7ega
+.section s7egb
+.section s7eha
+.section s7ehb
+.section s7eia
+.section s7eib
+.section s7eja
+.section s7ejb
+.section s7eka
+.section s7ekb
+.section s7ela
+.section s7elb
+.section s7ema
+.section s7emb
+.section s7ena
+.section s7enb
+.section s7eoa
+.section s7eob
+.section s7epa
+.section s7epb
+.section s7eqa
+.section s7eqb
+.section s7era
+.section s7erb
+.section s7esa
+.section s7esb
+.section s7eta
+.section s7etb
+.section s7eua
+.section s7eub
+.section s7eva
+.section s7evb
+.section s7ewa
+.section s7ewb
+.section s7exa
+.section s7exb
+.section s7eya
+.section s7eyb
+.section s7eza
+.section s7ezb
+.section s7e1a
+.section s7e1b
+.section s7e2a
+.section s7e2b
+.section s7e3a
+.section s7e3b
+.section s7e4a
+.section s7e4b
+.section s7e5a
+.section s7e5b
+.section s7e6a
+.section s7e6b
+.section s7e7a
+.section s7e7b
+.section s7e8a
+.section s7e8b
+.section s7e9a
+.section s7e9b
+.section s7e0a
+.section s7e0b
+.section s7faa
+.section s7fab
+.section s7fba
+.section s7fbb
+.section s7fca
+.section s7fcb
+.section s7fda
+.section s7fdb
+.section s7fea
+.section s7feb
+.section s7ffa
+.section s7ffb
+.section s7fga
+.section s7fgb
+.section s7fha
+.section s7fhb
+.section s7fia
+.section s7fib
+.section s7fja
+.section s7fjb
+.section s7fka
+.section s7fkb
+.section s7fla
+.section s7flb
+.section s7fma
+.section s7fmb
+.section s7fna
+.section s7fnb
+.section s7foa
+.section s7fob
+.section s7fpa
+.section s7fpb
+.section s7fqa
+.section s7fqb
+.section s7fra
+.section s7frb
+.section s7fsa
+.section s7fsb
+.section s7fta
+.section s7ftb
+.section s7fua
+.section s7fub
+.section s7fva
+.section s7fvb
+.section s7fwa
+.section s7fwb
+.section s7fxa
+.section s7fxb
+.section s7fya
+.section s7fyb
+.section s7fza
+.section s7fzb
+.section s7f1a
+.section s7f1b
+.section s7f2a
+.section s7f2b
+.section s7f3a
+.section s7f3b
+.section s7f4a
+.section s7f4b
+.section s7f5a
+.section s7f5b
+.section s7f6a
+.section s7f6b
+.section s7f7a
+.section s7f7b
+.section s7f8a
+.section s7f8b
+.section s7f9a
+.section s7f9b
+.section s7f0a
+.section s7f0b
+.section s7gaa
+.section s7gab
+.section s7gba
+.section s7gbb
+.section s7gca
+.section s7gcb
+.section s7gda
+.section s7gdb
+.section s7gea
+.section s7geb
+.section s7gfa
+.section s7gfb
+.section s7gga
+.section s7ggb
+.section s7gha
+.section s7ghb
+.section s7gia
+.section s7gib
+.section s7gja
+.section s7gjb
+.section s7gka
+.section s7gkb
+.section s7gla
+.section s7glb
+.section s7gma
+.section s7gmb
+.section s7gna
+.section s7gnb
+.section s7goa
+.section s7gob
+.section s7gpa
+.section s7gpb
+.section s7gqa
+.section s7gqb
+.section s7gra
+.section s7grb
+.section s7gsa
+.section s7gsb
+.section s7gta
+.section s7gtb
+.section s7gua
+.section s7gub
+.section s7gva
+.section s7gvb
+.section s7gwa
+.section s7gwb
+.section s7gxa
+.section s7gxb
+.section s7gya
+.section s7gyb
+.section s7gza
+.section s7gzb
+.section s7g1a
+.section s7g1b
+.section s7g2a
+.section s7g2b
+.section s7g3a
+.section s7g3b
+.section s7g4a
+.section s7g4b
+.section s7g5a
+.section s7g5b
+.section s7g6a
+.section s7g6b
+.section s7g7a
+.section s7g7b
+.section s7g8a
+.section s7g8b
+.section s7g9a
+.section s7g9b
+.section s7g0a
+.section s7g0b
+.section s7haa
+.section s7hab
+.section s7hba
+.section s7hbb
+.section s7hca
+.section s7hcb
+.section s7hda
+.section s7hdb
+.section s7hea
+.section s7heb
+.section s7hfa
+.section s7hfb
+.section s7hga
+.section s7hgb
+.section s7hha
+.section s7hhb
+.section s7hia
+.section s7hib
+.section s7hja
+.section s7hjb
+.section s7hka
+.section s7hkb
+.section s7hla
+.section s7hlb
+.section s7hma
+.section s7hmb
+.section s7hna
+.section s7hnb
+.section s7hoa
+.section s7hob
+.section s7hpa
+.section s7hpb
+.section s7hqa
+.section s7hqb
+.section s7hra
+.section s7hrb
+.section s7hsa
+.section s7hsb
+.section s7hta
+.section s7htb
+.section s7hua
+.section s7hub
+.section s7hva
+.section s7hvb
+.section s7hwa
+.section s7hwb
+.section s7hxa
+.section s7hxb
+.section s7hya
+.section s7hyb
+.section s7hza
+.section s7hzb
+.section s7h1a
+.section s7h1b
+.section s7h2a
+.section s7h2b
+.section s7h3a
+.section s7h3b
+.section s7h4a
+.section s7h4b
+.section s7h5a
+.section s7h5b
+.section s7h6a
+.section s7h6b
+.section s7h7a
+.section s7h7b
+.section s7h8a
+.section s7h8b
+.section s7h9a
+.section s7h9b
+.section s7h0a
+.section s7h0b
+.section s7iaa
+.section s7iab
+.section s7iba
+.section s7ibb
+.section s7ica
+.section s7icb
+.section s7ida
+.section s7idb
+.section s7iea
+.section s7ieb
+.section s7ifa
+.section s7ifb
+.section s7iga
+.section s7igb
+.section s7iha
+.section s7ihb
+.section s7iia
+.section s7iib
+.section s7ija
+.section s7ijb
+.section s7ika
+.section s7ikb
+.section s7ila
+.section s7ilb
+.section s7ima
+.section s7imb
+.section s7ina
+.section s7inb
+.section s7ioa
+.section s7iob
+.section s7ipa
+.section s7ipb
+.section s7iqa
+.section s7iqb
+.section s7ira
+.section s7irb
+.section s7isa
+.section s7isb
+.section s7ita
+.section s7itb
+.section s7iua
+.section s7iub
+.section s7iva
+.section s7ivb
+.section s7iwa
+.section s7iwb
+.section s7ixa
+.section s7ixb
+.section s7iya
+.section s7iyb
+.section s7iza
+.section s7izb
+.section s7i1a
+.section s7i1b
+.section s7i2a
+.section s7i2b
+.section s7i3a
+.section s7i3b
+.section s7i4a
+.section s7i4b
+.section s7i5a
+.section s7i5b
+.section s7i6a
+.section s7i6b
+.section s7i7a
+.section s7i7b
+.section s7i8a
+.section s7i8b
+.section s7i9a
+.section s7i9b
+.section s7i0a
+.section s7i0b
+.section s7jaa
+.section s7jab
+.section s7jba
+.section s7jbb
+.section s7jca
+.section s7jcb
+.section s7jda
+.section s7jdb
+.section s7jea
+.section s7jeb
+.section s7jfa
+.section s7jfb
+.section s7jga
+.section s7jgb
+.section s7jha
+.section s7jhb
+.section s7jia
+.section s7jib
+.section s7jja
+.section s7jjb
+.section s7jka
+.section s7jkb
+.section s7jla
+.section s7jlb
+.section s7jma
+.section s7jmb
+.section s7jna
+.section s7jnb
+.section s7joa
+.section s7job
+.section s7jpa
+.section s7jpb
+.section s7jqa
+.section s7jqb
+.section s7jra
+.section s7jrb
+.section s7jsa
+.section s7jsb
+.section s7jta
+.section s7jtb
+.section s7jua
+.section s7jub
+.section s7jva
+.section s7jvb
+.section s7jwa
+.section s7jwb
+.section s7jxa
+.section s7jxb
+.section s7jya
+.section s7jyb
+.section s7jza
+.section s7jzb
+.section s7j1a
+.section s7j1b
+.section s7j2a
+.section s7j2b
+.section s7j3a
+.section s7j3b
+.section s7j4a
+.section s7j4b
+.section s7j5a
+.section s7j5b
+.section s7j6a
+.section s7j6b
+.section s7j7a
+.section s7j7b
+.section s7j8a
+.section s7j8b
+.section s7j9a
+.section s7j9b
+.section s7j0a
+.section s7j0b
+.section s7kaa
+.section s7kab
+.section s7kba
+.section s7kbb
+.section s7kca
+.section s7kcb
+.section s7kda
+.section s7kdb
+.section s7kea
+.section s7keb
+.section s7kfa
+.section s7kfb
+.section s7kga
+.section s7kgb
+.section s7kha
+.section s7khb
+.section s7kia
+.section s7kib
+.section s7kja
+.section s7kjb
+.section s7kka
+.section s7kkb
+.section s7kla
+.section s7klb
+.section s7kma
+.section s7kmb
+.section s7kna
+.section s7knb
+.section s7koa
+.section s7kob
+.section s7kpa
+.section s7kpb
+.section s7kqa
+.section s7kqb
+.section s7kra
+.section s7krb
+.section s7ksa
+.section s7ksb
+.section s7kta
+.section s7ktb
+.section s7kua
+.section s7kub
+.section s7kva
+.section s7kvb
+.section s7kwa
+.section s7kwb
+.section s7kxa
+.section s7kxb
+.section s7kya
+.section s7kyb
+.section s7kza
+.section s7kzb
+.section s7k1a
+.section s7k1b
+.section s7k2a
+.section s7k2b
+.section s7k3a
+.section s7k3b
+.section s7k4a
+.section s7k4b
+.section s7k5a
+.section s7k5b
+.section s7k6a
+.section s7k6b
+.section s7k7a
+.section s7k7b
+.section s7k8a
+.section s7k8b
+.section s7k9a
+.section s7k9b
+.section s7k0a
+.section s7k0b
+.section s7laa
+.section s7lab
+.section s7lba
+.section s7lbb
+.section s7lca
+.section s7lcb
+.section s7lda
+.section s7ldb
+.section s7lea
+.section s7leb
+.section s7lfa
+.section s7lfb
+.section s7lga
+.section s7lgb
+.section s7lha
+.section s7lhb
+.section s7lia
+.section s7lib
+.section s7lja
+.section s7ljb
+.section s7lka
+.section s7lkb
+.section s7lla
+.section s7llb
+.section s7lma
+.section s7lmb
+.section s7lna
+.section s7lnb
+.section s7loa
+.section s7lob
+.section s7lpa
+.section s7lpb
+.section s7lqa
+.section s7lqb
+.section s7lra
+.section s7lrb
+.section s7lsa
+.section s7lsb
+.section s7lta
+.section s7ltb
+.section s7lua
+.section s7lub
+.section s7lva
+.section s7lvb
+.section s7lwa
+.section s7lwb
+.section s7lxa
+.section s7lxb
+.section s7lya
+.section s7lyb
+.section s7lza
+.section s7lzb
+.section s7l1a
+.section s7l1b
+.section s7l2a
+.section s7l2b
+.section s7l3a
+.section s7l3b
+.section s7l4a
+.section s7l4b
+.section s7l5a
+.section s7l5b
+.section s7l6a
+.section s7l6b
+.section s7l7a
+.section s7l7b
+.section s7l8a
+.section s7l8b
+.section s7l9a
+.section s7l9b
+.section s7l0a
+.section s7l0b
+.section s7maa
+.section s7mab
+.section s7mba
+.section s7mbb
+.section s7mca
+.section s7mcb
+.section s7mda
+.section s7mdb
+.section s7mea
+.section s7meb
+.section s7mfa
+.section s7mfb
+.section s7mga
+.section s7mgb
+.section s7mha
+.section s7mhb
+.section s7mia
+.section s7mib
+.section s7mja
+.section s7mjb
+.section s7mka
+.section s7mkb
+.section s7mla
+.section s7mlb
+.section s7mma
+.section s7mmb
+.section s7mna
+.section s7mnb
+.section s7moa
+.section s7mob
+.section s7mpa
+.section s7mpb
+.section s7mqa
+.section s7mqb
+.section s7mra
+.section s7mrb
+.section s7msa
+.section s7msb
+.section s7mta
+.section s7mtb
+.section s7mua
+.section s7mub
+.section s7mva
+.section s7mvb
+.section s7mwa
+.section s7mwb
+.section s7mxa
+.section s7mxb
+.section s7mya
+.section s7myb
+.section s7mza
+.section s7mzb
+.section s7m1a
+.section s7m1b
+.section s7m2a
+.section s7m2b
+.section s7m3a
+.section s7m3b
+.section s7m4a
+.section s7m4b
+.section s7m5a
+.section s7m5b
+.section s7m6a
+.section s7m6b
+.section s7m7a
+.section s7m7b
+.section s7m8a
+.section s7m8b
+.section s7m9a
+.section s7m9b
+.section s7m0a
+.section s7m0b
+.section s7naa
+.section s7nab
+.section s7nba
+.section s7nbb
+.section s7nca
+.section s7ncb
+.section s7nda
+.section s7ndb
+.section s7nea
+.section s7neb
+.section s7nfa
+.section s7nfb
+.section s7nga
+.section s7ngb
+.section s7nha
+.section s7nhb
+.section s7nia
+.section s7nib
+.section s7nja
+.section s7njb
+.section s7nka
+.section s7nkb
+.section s7nla
+.section s7nlb
+.section s7nma
+.section s7nmb
+.section s7nna
+.section s7nnb
+.section s7noa
+.section s7nob
+.section s7npa
+.section s7npb
+.section s7nqa
+.section s7nqb
+.section s7nra
+.section s7nrb
+.section s7nsa
+.section s7nsb
+.section s7nta
+.section s7ntb
+.section s7nua
+.section s7nub
+.section s7nva
+.section s7nvb
+.section s7nwa
+.section s7nwb
+.section s7nxa
+.section s7nxb
+.section s7nya
+.section s7nyb
+.section s7nza
+.section s7nzb
+.section s7n1a
+.section s7n1b
+.section s7n2a
+.section s7n2b
+.section s7n3a
+.section s7n3b
+.section s7n4a
+.section s7n4b
+.section s7n5a
+.section s7n5b
+.section s7n6a
+.section s7n6b
+.section s7n7a
+.section s7n7b
+.section s7n8a
+.section s7n8b
+.section s7n9a
+.section s7n9b
+.section s7n0a
+.section s7n0b
+.section s7oaa
+.section s7oab
+.section s7oba
+.section s7obb
+.section s7oca
+.section s7ocb
+.section s7oda
+.section s7odb
+.section s7oea
+.section s7oeb
+.section s7ofa
+.section s7ofb
+.section s7oga
+.section s7ogb
+.section s7oha
+.section s7ohb
+.section s7oia
+.section s7oib
+.section s7oja
+.section s7ojb
+.section s7oka
+.section s7okb
+.section s7ola
+.section s7olb
+.section s7oma
+.section s7omb
+.section s7ona
+.section s7onb
+.section s7ooa
+.section s7oob
+.section s7opa
+.section s7opb
+.section s7oqa
+.section s7oqb
+.section s7ora
+.section s7orb
+.section s7osa
+.section s7osb
+.section s7ota
+.section s7otb
+.section s7oua
+.section s7oub
+.section s7ova
+.section s7ovb
+.section s7owa
+.section s7owb
+.section s7oxa
+.section s7oxb
+.section s7oya
+.section s7oyb
+.section s7oza
+.section s7ozb
+.section s7o1a
+.section s7o1b
+.section s7o2a
+.section s7o2b
+.section s7o3a
+.section s7o3b
+.section s7o4a
+.section s7o4b
+.section s7o5a
+.section s7o5b
+.section s7o6a
+.section s7o6b
+.section s7o7a
+.section s7o7b
+.section s7o8a
+.section s7o8b
+.section s7o9a
+.section s7o9b
+.section s7o0a
+.section s7o0b
+.section s7paa
+.section s7pab
+.section s7pba
+.section s7pbb
+.section s7pca
+.section s7pcb
+.section s7pda
+.section s7pdb
+.section s7pea
+.section s7peb
+.section s7pfa
+.section s7pfb
+.section s7pga
+.section s7pgb
+.section s7pha
+.section s7phb
+.section s7pia
+.section s7pib
+.section s7pja
+.section s7pjb
+.section s7pka
+.section s7pkb
+.section s7pla
+.section s7plb
+.section s7pma
+.section s7pmb
+.section s7pna
+.section s7pnb
+.section s7poa
+.section s7pob
+.section s7ppa
+.section s7ppb
+.section s7pqa
+.section s7pqb
+.section s7pra
+.section s7prb
+.section s7psa
+.section s7psb
+.section s7pta
+.section s7ptb
+.section s7pua
+.section s7pub
+.section s7pva
+.section s7pvb
+.section s7pwa
+.section s7pwb
+.section s7pxa
+.section s7pxb
+.section s7pya
+.section s7pyb
+.section s7pza
+.section s7pzb
+.section s7p1a
+.section s7p1b
+.section s7p2a
+.section s7p2b
+.section s7p3a
+.section s7p3b
+.section s7p4a
+.section s7p4b
+.section s7p5a
+.section s7p5b
+.section s7p6a
+.section s7p6b
+.section s7p7a
+.section s7p7b
+.section s7p8a
+.section s7p8b
+.section s7p9a
+.section s7p9b
+.section s7p0a
+.section s7p0b
+.section s7qaa
+.section s7qab
+.section s7qba
+.section s7qbb
+.section s7qca
+.section s7qcb
+.section s7qda
+.section s7qdb
+.section s7qea
+.section s7qeb
+.section s7qfa
+.section s7qfb
+.section s7qga
+.section s7qgb
+.section s7qha
+.section s7qhb
+.section s7qia
+.section s7qib
+.section s7qja
+.section s7qjb
+.section s7qka
+.section s7qkb
+.section s7qla
+.section s7qlb
+.section s7qma
+.section s7qmb
+.section s7qna
+.section s7qnb
+.section s7qoa
+.section s7qob
+.section s7qpa
+.section s7qpb
+.section s7qqa
+.section s7qqb
+.section s7qra
+.section s7qrb
+.section s7qsa
+.section s7qsb
+.section s7qta
+.section s7qtb
+.section s7qua
+.section s7qub
+.section s7qva
+.section s7qvb
+.section s7qwa
+.section s7qwb
+.section s7qxa
+.section s7qxb
+.section s7qya
+.section s7qyb
+.section s7qza
+.section s7qzb
+.section s7q1a
+.section s7q1b
+.section s7q2a
+.section s7q2b
+.section s7q3a
+.section s7q3b
+.section s7q4a
+.section s7q4b
+.section s7q5a
+.section s7q5b
+.section s7q6a
+.section s7q6b
+.section s7q7a
+.section s7q7b
+.section s7q8a
+.section s7q8b
+.section s7q9a
+.section s7q9b
+.section s7q0a
+.section s7q0b
+.section s7raa
+.section s7rab
+.section s7rba
+.section s7rbb
+.section s7rca
+.section s7rcb
+.section s7rda
+.section s7rdb
+.section s7rea
+.section s7reb
+.section s7rfa
+.section s7rfb
+.section s7rga
+.section s7rgb
+.section s7rha
+.section s7rhb
+.section s7ria
+.section s7rib
+.section s7rja
+.section s7rjb
+.section s7rka
+.section s7rkb
+.section s7rla
+.section s7rlb
+.section s7rma
+.section s7rmb
+.section s7rna
+.section s7rnb
+.section s7roa
+.section s7rob
+.section s7rpa
+.section s7rpb
+.section s7rqa
+.section s7rqb
+.section s7rra
+.section s7rrb
+.section s7rsa
+.section s7rsb
+.section s7rta
+.section s7rtb
+.section s7rua
+.section s7rub
+.section s7rva
+.section s7rvb
+.section s7rwa
+.section s7rwb
+.section s7rxa
+.section s7rxb
+.section s7rya
+.section s7ryb
+.section s7rza
+.section s7rzb
+.section s7r1a
+.section s7r1b
+.section s7r2a
+.section s7r2b
+.section s7r3a
+.section s7r3b
+.section s7r4a
+.section s7r4b
+.section s7r5a
+.section s7r5b
+.section s7r6a
+.section s7r6b
+.section s7r7a
+.section s7r7b
+.section s7r8a
+.section s7r8b
+.section s7r9a
+.section s7r9b
+.section s7r0a
+.section s7r0b
+.section s7saa
+.section s7sab
+.section s7sba
+.section s7sbb
+.section s7sca
+.section s7scb
+.section s7sda
+.section s7sdb
+.section s7sea
+.section s7seb
+.section s7sfa
+.section s7sfb
+.section s7sga
+.section s7sgb
+.section s7sha
+.section s7shb
+.section s7sia
+.section s7sib
+.section s7sja
+.section s7sjb
+.section s7ska
+.section s7skb
+.section s7sla
+.section s7slb
+.section s7sma
+.section s7smb
+.section s7sna
+.section s7snb
+.section s7soa
+.section s7sob
+.section s7spa
+.section s7spb
+.section s7sqa
+.section s7sqb
+.section s7sra
+.section s7srb
+.section s7ssa
+.section s7ssb
+.section s7sta
+.section s7stb
+.section s7sua
+.section s7sub
+.section s7sva
+.section s7svb
+.section s7swa
+.section s7swb
+.section s7sxa
+.section s7sxb
+.section s7sya
+.section s7syb
+.section s7sza
+.section s7szb
+.section s7s1a
+.section s7s1b
+.section s7s2a
+.section s7s2b
+.section s7s3a
+.section s7s3b
+.section s7s4a
+.section s7s4b
+.section s7s5a
+.section s7s5b
+.section s7s6a
+.section s7s6b
+.section s7s7a
+.section s7s7b
+.section s7s8a
+.section s7s8b
+.section s7s9a
+.section s7s9b
+.section s7s0a
+.section s7s0b
+.section s7taa
+.section s7tab
+.section s7tba
+.section s7tbb
+.section s7tca
+.section s7tcb
+.section s7tda
+.section s7tdb
+.section s7tea
+.section s7teb
+.section s7tfa
+.section s7tfb
+.section s7tga
+.section s7tgb
+.section s7tha
+.section s7thb
+.section s7tia
+.section s7tib
+.section s7tja
+.section s7tjb
+.section s7tka
+.section s7tkb
+.section s7tla
+.section s7tlb
+.section s7tma
+.section s7tmb
+.section s7tna
+.section s7tnb
+.section s7toa
+.section s7tob
+.section s7tpa
+.section s7tpb
+.section s7tqa
+.section s7tqb
+.section s7tra
+.section s7trb
+.section s7tsa
+.section s7tsb
+.section s7tta
+.section s7ttb
+.section s7tua
+.section s7tub
+.section s7tva
+.section s7tvb
+.section s7twa
+.section s7twb
+.section s7txa
+.section s7txb
+.section s7tya
+.section s7tyb
+.section s7tza
+.section s7tzb
+.section s7t1a
+.section s7t1b
+.section s7t2a
+.section s7t2b
+.section s7t3a
+.section s7t3b
+.section s7t4a
+.section s7t4b
+.section s7t5a
+.section s7t5b
+.section s7t6a
+.section s7t6b
+.section s7t7a
+.section s7t7b
+.section s7t8a
+.section s7t8b
+.section s7t9a
+.section s7t9b
+.section s7t0a
+.section s7t0b
+.section s7uaa
+.section s7uab
+.section s7uba
+.section s7ubb
+.section s7uca
+.section s7ucb
+.section s7uda
+.section s7udb
+.section s7uea
+.section s7ueb
+.section s7ufa
+.section s7ufb
+.section s7uga
+.section s7ugb
+.section s7uha
+.section s7uhb
+.section s7uia
+.section s7uib
+.section s7uja
+.section s7ujb
+.section s7uka
+.section s7ukb
+.section s7ula
+.section s7ulb
+.section s7uma
+.section s7umb
+.section s7una
+.section s7unb
+.section s7uoa
+.section s7uob
+.section s7upa
+.section s7upb
+.section s7uqa
+.section s7uqb
+.section s7ura
+.section s7urb
+.section s7usa
+.section s7usb
+.section s7uta
+.section s7utb
+.section s7uua
+.section s7uub
+.section s7uva
+.section s7uvb
+.section s7uwa
+.section s7uwb
+.section s7uxa
+.section s7uxb
+.section s7uya
+.section s7uyb
+.section s7uza
+.section s7uzb
+.section s7u1a
+.section s7u1b
+.section s7u2a
+.section s7u2b
+.section s7u3a
+.section s7u3b
+.section s7u4a
+.section s7u4b
+.section s7u5a
+.section s7u5b
+.section s7u6a
+.section s7u6b
+.section s7u7a
+.section s7u7b
+.section s7u8a
+.section s7u8b
+.section s7u9a
+.section s7u9b
+.section s7u0a
+.section s7u0b
+.section s7vaa
+.section s7vab
+.section s7vba
+.section s7vbb
+.section s7vca
+.section s7vcb
+.section s7vda
+.section s7vdb
+.section s7vea
+.section s7veb
+.section s7vfa
+.section s7vfb
+.section s7vga
+.section s7vgb
+.section s7vha
+.section s7vhb
+.section s7via
+.section s7vib
+.section s7vja
+.section s7vjb
+.section s7vka
+.section s7vkb
+.section s7vla
+.section s7vlb
+.section s7vma
+.section s7vmb
+.section s7vna
+.section s7vnb
+.section s7voa
+.section s7vob
+.section s7vpa
+.section s7vpb
+.section s7vqa
+.section s7vqb
+.section s7vra
+.section s7vrb
+.section s7vsa
+.section s7vsb
+.section s7vta
+.section s7vtb
+.section s7vua
+.section s7vub
+.section s7vva
+.section s7vvb
+.section s7vwa
+.section s7vwb
+.section s7vxa
+.section s7vxb
+.section s7vya
+.section s7vyb
+.section s7vza
+.section s7vzb
+.section s7v1a
+.section s7v1b
+.section s7v2a
+.section s7v2b
+.section s7v3a
+.section s7v3b
+.section s7v4a
+.section s7v4b
+.section s7v5a
+.section s7v5b
+.section s7v6a
+.section s7v6b
+.section s7v7a
+.section s7v7b
+.section s7v8a
+.section s7v8b
+.section s7v9a
+.section s7v9b
+.section s7v0a
+.section s7v0b
+.section s7waa
+.section s7wab
+.section s7wba
+.section s7wbb
+.section s7wca
+.section s7wcb
+.section s7wda
+.section s7wdb
+.section s7wea
+.section s7web
+.section s7wfa
+.section s7wfb
+.section s7wga
+.section s7wgb
+.section s7wha
+.section s7whb
+.section s7wia
+.section s7wib
+.section s7wja
+.section s7wjb
+.section s7wka
+.section s7wkb
+.section s7wla
+.section s7wlb
+.section s7wma
+.section s7wmb
+.section s7wna
+.section s7wnb
+.section s7woa
+.section s7wob
+.section s7wpa
+.section s7wpb
+.section s7wqa
+.section s7wqb
+.section s7wra
+.section s7wrb
+.section s7wsa
+.section s7wsb
+.section s7wta
+.section s7wtb
+.section s7wua
+.section s7wub
+.section s7wva
+.section s7wvb
+.section s7wwa
+.section s7wwb
+.section s7wxa
+.section s7wxb
+.section s7wya
+.section s7wyb
+.section s7wza
+.section s7wzb
+.section s7w1a
+.section s7w1b
+.section s7w2a
+.section s7w2b
+.section s7w3a
+.section s7w3b
+.section s7w4a
+.section s7w4b
+.section s7w5a
+.section s7w5b
+.section s7w6a
+.section s7w6b
+.section s7w7a
+.section s7w7b
+.section s7w8a
+.section s7w8b
+.section s7w9a
+.section s7w9b
+.section s7w0a
+.section s7w0b
+.section s7xaa
+.section s7xab
+.section s7xba
+.section s7xbb
+.section s7xca
+.section s7xcb
+.section s7xda
+.section s7xdb
+.section s7xea
+.section s7xeb
+.section s7xfa
+.section s7xfb
+.section s7xga
+.section s7xgb
+.section s7xha
+.section s7xhb
+.section s7xia
+.section s7xib
+.section s7xja
+.section s7xjb
+.section s7xka
+.section s7xkb
+.section s7xla
+.section s7xlb
+.section s7xma
+.section s7xmb
+.section s7xna
+.section s7xnb
+.section s7xoa
+.section s7xob
+.section s7xpa
+.section s7xpb
+.section s7xqa
+.section s7xqb
+.section s7xra
+.section s7xrb
+.section s7xsa
+.section s7xsb
+.section s7xta
+.section s7xtb
+.section s7xua
+.section s7xub
+.section s7xva
+.section s7xvb
+.section s7xwa
+.section s7xwb
+.section s7xxa
+.section s7xxb
+.section s7xya
+.section s7xyb
+.section s7xza
+.section s7xzb
+.section s7x1a
+.section s7x1b
+.section s7x2a
+.section s7x2b
+.section s7x3a
+.section s7x3b
+.section s7x4a
+.section s7x4b
+.section s7x5a
+.section s7x5b
+.section s7x6a
+.section s7x6b
+.section s7x7a
+.section s7x7b
+.section s7x8a
+.section s7x8b
+.section s7x9a
+.section s7x9b
+.section s7x0a
+.section s7x0b
+.section s7yaa
+.section s7yab
+.section s7yba
+.section s7ybb
+.section s7yca
+.section s7ycb
+.section s7yda
+.section s7ydb
+.section s7yea
+.section s7yeb
+.section s7yfa
+.section s7yfb
+.section s7yga
+.section s7ygb
+.section s7yha
+.section s7yhb
+.section s7yia
+.section s7yib
+.section s7yja
+.section s7yjb
+.section s7yka
+.section s7ykb
+.section s7yla
+.section s7ylb
+.section s7yma
+.section s7ymb
+.section s7yna
+.section s7ynb
+.section s7yoa
+.section s7yob
+.section s7ypa
+.section s7ypb
+.section s7yqa
+.section s7yqb
+.section s7yra
+.section s7yrb
+.section s7ysa
+.section s7ysb
+.section s7yta
+.section s7ytb
+.section s7yua
+.section s7yub
+.section s7yva
+.section s7yvb
+.section s7ywa
+.section s7ywb
+.section s7yxa
+.section s7yxb
+.section s7yya
+.section s7yyb
+.section s7yza
+.section s7yzb
+.section s7y1a
+.section s7y1b
+.section s7y2a
+.section s7y2b
+.section s7y3a
+.section s7y3b
+.section s7y4a
+.section s7y4b
+.section s7y5a
+.section s7y5b
+.section s7y6a
+.section s7y6b
+.section s7y7a
+.section s7y7b
+.section s7y8a
+.section s7y8b
+.section s7y9a
+.section s7y9b
+.section s7y0a
+.section s7y0b
+.section s7zaa
+.section s7zab
+.section s7zba
+.section s7zbb
+.section s7zca
+.section s7zcb
+.section s7zda
+.section s7zdb
+.section s7zea
+.section s7zeb
+.section s7zfa
+.section s7zfb
+.section s7zga
+.section s7zgb
+.section s7zha
+.section s7zhb
+.section s7zia
+.section s7zib
+.section s7zja
+.section s7zjb
+.section s7zka
+.section s7zkb
+.section s7zla
+.section s7zlb
+.section s7zma
+.section s7zmb
+.section s7zna
+.section s7znb
+.section s7zoa
+.section s7zob
+.section s7zpa
+.section s7zpb
+.section s7zqa
+.section s7zqb
+.section s7zra
+.section s7zrb
+.section s7zsa
+.section s7zsb
+.section s7zta
+.section s7ztb
+.section s7zua
+.section s7zub
+.section s7zva
+.section s7zvb
+.section s7zwa
+.section s7zwb
+.section s7zxa
+.section s7zxb
+.section s7zya
+.section s7zyb
+.section s7zza
+.section s7zzb
+.section s7z1a
+.section s7z1b
+.section s7z2a
+.section s7z2b
+.section s7z3a
+.section s7z3b
+.section s7z4a
+.section s7z4b
+.section s7z5a
+.section s7z5b
+.section s7z6a
+.section s7z6b
+.section s7z7a
+.section s7z7b
+.section s7z8a
+.section s7z8b
+.section s7z9a
+.section s7z9b
+.section s7z0a
+.section s7z0b
+.section s71aa
+.section s71ab
+.section s71ba
+.section s71bb
+.section s71ca
+.section s71cb
+.section s71da
+.section s71db
+.section s71ea
+.section s71eb
+.section s71fa
+.section s71fb
+.section s71ga
+.section s71gb
+.section s71ha
+.section s71hb
+.section s71ia
+.section s71ib
+.section s71ja
+.section s71jb
+.section s71ka
+.section s71kb
+.section s71la
+.section s71lb
+.section s71ma
+.section s71mb
+.section s71na
+.section s71nb
+.section s71oa
+.section s71ob
+.section s71pa
+.section s71pb
+.section s71qa
+.section s71qb
+.section s71ra
+.section s71rb
+.section s71sa
+.section s71sb
+.section s71ta
+.section s71tb
+.section s71ua
+.section s71ub
+.section s71va
+.section s71vb
+.section s71wa
+.section s71wb
+.section s71xa
+.section s71xb
+.section s71ya
+.section s71yb
+.section s71za
+.section s71zb
+.section s711a
+.section s711b
+.section s712a
+.section s712b
+.section s713a
+.section s713b
+.section s714a
+.section s714b
+.section s715a
+.section s715b
+.section s716a
+.section s716b
+.section s717a
+.section s717b
+.section s718a
+.section s718b
+.section s719a
+.section s719b
+.section s710a
+.section s710b
+.section s72aa
+.section s72ab
+.section s72ba
+.section s72bb
+.section s72ca
+.section s72cb
+.section s72da
+.section s72db
+.section s72ea
+.section s72eb
+.section s72fa
+.section s72fb
+.section s72ga
+.section s72gb
+.section s72ha
+.section s72hb
+.section s72ia
+.section s72ib
+.section s72ja
+.section s72jb
+.section s72ka
+.section s72kb
+.section s72la
+.section s72lb
+.section s72ma
+.section s72mb
+.section s72na
+.section s72nb
+.section s72oa
+.section s72ob
+.section s72pa
+.section s72pb
+.section s72qa
+.section s72qb
+.section s72ra
+.section s72rb
+.section s72sa
+.section s72sb
+.section s72ta
+.section s72tb
+.section s72ua
+.section s72ub
+.section s72va
+.section s72vb
+.section s72wa
+.section s72wb
+.section s72xa
+.section s72xb
+.section s72ya
+.section s72yb
+.section s72za
+.section s72zb
+.section s721a
+.section s721b
+.section s722a
+.section s722b
+.section s723a
+.section s723b
+.section s724a
+.section s724b
+.section s725a
+.section s725b
+.section s726a
+.section s726b
+.section s727a
+.section s727b
+.section s728a
+.section s728b
+.section s729a
+.section s729b
+.section s720a
+.section s720b
+.section s73aa
+.section s73ab
+.section s73ba
+.section s73bb
+.section s73ca
+.section s73cb
+.section s73da
+.section s73db
+.section s73ea
+.section s73eb
+.section s73fa
+.section s73fb
+.section s73ga
+.section s73gb
+.section s73ha
+.section s73hb
+.section s73ia
+.section s73ib
+.section s73ja
+.section s73jb
+.section s73ka
+.section s73kb
+.section s73la
+.section s73lb
+.section s73ma
+.section s73mb
+.section s73na
+.section s73nb
+.section s73oa
+.section s73ob
+.section s73pa
+.section s73pb
+.section s73qa
+.section s73qb
+.section s73ra
+.section s73rb
+.section s73sa
+.section s73sb
+.section s73ta
+.section s73tb
+.section s73ua
+.section s73ub
+.section s73va
+.section s73vb
+.section s73wa
+.section s73wb
+.section s73xa
+.section s73xb
+.section s73ya
+.section s73yb
+.section s73za
+.section s73zb
+.section s731a
+.section s731b
+.section s732a
+.section s732b
+.section s733a
+.section s733b
+.section s734a
+.section s734b
+.section s735a
+.section s735b
+.section s736a
+.section s736b
+.section s737a
+.section s737b
+.section s738a
+.section s738b
+.section s739a
+.section s739b
+.section s730a
+.section s730b
+.section s74aa
+.section s74ab
+.section s74ba
+.section s74bb
+.section s74ca
+.section s74cb
+.section s74da
+.section s74db
+.section s74ea
+.section s74eb
+.section s74fa
+.section s74fb
+.section s74ga
+.section s74gb
+.section s74ha
+.section s74hb
+.section s74ia
+.section s74ib
+.section s74ja
+.section s74jb
+.section s74ka
+.section s74kb
+.section s74la
+.section s74lb
+.section s74ma
+.section s74mb
+.section s74na
+.section s74nb
+.section s74oa
+.section s74ob
+.section s74pa
+.section s74pb
+.section s74qa
+.section s74qb
+.section s74ra
+.section s74rb
+.section s74sa
+.section s74sb
+.section s74ta
+.section s74tb
+.section s74ua
+.section s74ub
+.section s74va
+.section s74vb
+.section s74wa
+.section s74wb
+.section s74xa
+.section s74xb
+.section s74ya
+.section s74yb
+.section s74za
+.section s74zb
+.section s741a
+.section s741b
+.section s742a
+.section s742b
+.section s743a
+.section s743b
+.section s744a
+.section s744b
+.section s745a
+.section s745b
+.section s746a
+.section s746b
+.section s747a
+.section s747b
+.section s748a
+.section s748b
+.section s749a
+.section s749b
+.section s740a
+.section s740b
+.section s75aa
+.section s75ab
+.section s75ba
+.section s75bb
+.section s75ca
+.section s75cb
+.section s75da
+.section s75db
+.section s75ea
+.section s75eb
+.section s75fa
+.section s75fb
+.section s75ga
+.section s75gb
+.section s75ha
+.section s75hb
+.section s75ia
+.section s75ib
+.section s75ja
+.section s75jb
+.section s75ka
+.section s75kb
+.section s75la
+.section s75lb
+.section s75ma
+.section s75mb
+.section s75na
+.section s75nb
+.section s75oa
+.section s75ob
+.section s75pa
+.section s75pb
+.section s75qa
+.section s75qb
+.section s75ra
+.section s75rb
+.section s75sa
+.section s75sb
+.section s75ta
+.section s75tb
+.section s75ua
+.section s75ub
+.section s75va
+.section s75vb
+.section s75wa
+.section s75wb
+.section s75xa
+.section s75xb
+.section s75ya
+.section s75yb
+.section s75za
+.section s75zb
+.section s751a
+.section s751b
+.section s752a
+.section s752b
+.section s753a
+.section s753b
+.section s754a
+.section s754b
+.section s755a
+.section s755b
+.section s756a
+.section s756b
+.section s757a
+.section s757b
+.section s758a
+.section s758b
+.section s759a
+.section s759b
+.section s750a
+.section s750b
+.section s76aa
+.section s76ab
+.section s76ba
+.section s76bb
+.section s76ca
+.section s76cb
+.section s76da
+.section s76db
+.section s76ea
+.section s76eb
+.section s76fa
+.section s76fb
+.section s76ga
+.section s76gb
+.section s76ha
+.section s76hb
+.section s76ia
+.section s76ib
+.section s76ja
+.section s76jb
+.section s76ka
+.section s76kb
+.section s76la
+.section s76lb
+.section s76ma
+.section s76mb
+.section s76na
+.section s76nb
+.section s76oa
+.section s76ob
+.section s76pa
+.section s76pb
+.section s76qa
+.section s76qb
+.section s76ra
+.section s76rb
+.section s76sa
+.section s76sb
+.section s76ta
+.section s76tb
+.section s76ua
+.section s76ub
+.section s76va
+.section s76vb
+.section s76wa
+.section s76wb
+.section s76xa
+.section s76xb
+.section s76ya
+.section s76yb
+.section s76za
+.section s76zb
+.section s761a
+.section s761b
+.section s762a
+.section s762b
+.section s763a
+.section s763b
+.section s764a
+.section s764b
+.section s765a
+.section s765b
+.section s766a
+.section s766b
+.section s767a
+.section s767b
+.section s768a
+.section s768b
+.section s769a
+.section s769b
+.section s760a
+.section s760b
+.section s77aa
+.section s77ab
+.section s77ba
+.section s77bb
+.section s77ca
+.section s77cb
+.section s77da
+.section s77db
+.section s77ea
+.section s77eb
+.section s77fa
+.section s77fb
+.section s77ga
+.section s77gb
+.section s77ha
+.section s77hb
+.section s77ia
+.section s77ib
+.section s77ja
+.section s77jb
+.section s77ka
+.section s77kb
+.section s77la
+.section s77lb
+.section s77ma
+.section s77mb
+.section s77na
+.section s77nb
+.section s77oa
+.section s77ob
+.section s77pa
+.section s77pb
+.section s77qa
+.section s77qb
+.section s77ra
+.section s77rb
+.section s77sa
+.section s77sb
+.section s77ta
+.section s77tb
+.section s77ua
+.section s77ub
+.section s77va
+.section s77vb
+.section s77wa
+.section s77wb
+.section s77xa
+.section s77xb
+.section s77ya
+.section s77yb
+.section s77za
+.section s77zb
+.section s771a
+.section s771b
+.section s772a
+.section s772b
+.section s773a
+.section s773b
+.section s774a
+.section s774b
+.section s775a
+.section s775b
+.section s776a
+.section s776b
+.section s777a
+.section s777b
+.section s778a
+.section s778b
+.section s779a
+.section s779b
+.section s770a
+.section s770b
+.section s78aa
+.section s78ab
+.section s78ba
+.section s78bb
+.section s78ca
+.section s78cb
+.section s78da
+.section s78db
+.section s78ea
+.section s78eb
+.section s78fa
+.section s78fb
+.section s78ga
+.section s78gb
+.section s78ha
+.section s78hb
+.section s78ia
+.section s78ib
+.section s78ja
+.section s78jb
+.section s78ka
+.section s78kb
+.section s78la
+.section s78lb
+.section s78ma
+.section s78mb
+.section s78na
+.section s78nb
+.section s78oa
+.section s78ob
+.section s78pa
+.section s78pb
+.section s78qa
+.section s78qb
+.section s78ra
+.section s78rb
+.section s78sa
+.section s78sb
+.section s78ta
+.section s78tb
+.section s78ua
+.section s78ub
+.section s78va
+.section s78vb
+.section s78wa
+.section s78wb
+.section s78xa
+.section s78xb
+.section s78ya
+.section s78yb
+.section s78za
+.section s78zb
+.section s781a
+.section s781b
+.section s782a
+.section s782b
+.section s783a
+.section s783b
+.section s784a
+.section s784b
+.section s785a
+.section s785b
+.section s786a
+.section s786b
+.section s787a
+.section s787b
+.section s788a
+.section s788b
+.section s789a
+.section s789b
+.section s780a
+.section s780b
+.section s79aa
+.section s79ab
+.section s79ba
+.section s79bb
+.section s79ca
+.section s79cb
+.section s79da
+.section s79db
+.section s79ea
+.section s79eb
+.section s79fa
+.section s79fb
+.section s79ga
+.section s79gb
+.section s79ha
+.section s79hb
+.section s79ia
+.section s79ib
+.section s79ja
+.section s79jb
+.section s79ka
+.section s79kb
+.section s79la
+.section s79lb
+.section s79ma
+.section s79mb
+.section s79na
+.section s79nb
+.section s79oa
+.section s79ob
+.section s79pa
+.section s79pb
+.section s79qa
+.section s79qb
+.section s79ra
+.section s79rb
+.section s79sa
+.section s79sb
+.section s79ta
+.section s79tb
+.section s79ua
+.section s79ub
+.section s79va
+.section s79vb
+.section s79wa
+.section s79wb
+.section s79xa
+.section s79xb
+.section s79ya
+.section s79yb
+.section s79za
+.section s79zb
+.section s791a
+.section s791b
+.section s792a
+.section s792b
+.section s793a
+.section s793b
+.section s794a
+.section s794b
+.section s795a
+.section s795b
+.section s796a
+.section s796b
+.section s797a
+.section s797b
+.section s798a
+.section s798b
+.section s799a
+.section s799b
+.section s790a
+.section s790b
+.section s70aa
+.section s70ab
+.section s70ba
+.section s70bb
+.section s70ca
+.section s70cb
+.section s70da
+.section s70db
+.section s70ea
+.section s70eb
+.section s70fa
+.section s70fb
+.section s70ga
+.section s70gb
+.section s70ha
+.section s70hb
+.section s70ia
+.section s70ib
+.section s70ja
+.section s70jb
+.section s70ka
+.section s70kb
+.section s70la
+.section s70lb
+.section s70ma
+.section s70mb
+.section s70na
+.section s70nb
+.section s70oa
+.section s70ob
+.section s70pa
+.section s70pb
+.section s70qa
+.section s70qb
+.section s70ra
+.section s70rb
+.section s70sa
+.section s70sb
+.section s70ta
+.section s70tb
+.section s70ua
+.section s70ub
+.section s70va
+.section s70vb
+.section s70wa
+.section s70wb
+.section s70xa
+.section s70xb
+.section s70ya
+.section s70yb
+.section s70za
+.section s70zb
+.section s701a
+.section s701b
+.section s702a
+.section s702b
+.section s703a
+.section s703b
+.section s704a
+.section s704b
+.section s705a
+.section s705b
+.section s706a
+.section s706b
+.section s707a
+.section s707b
+.section s708a
+.section s708b
+.section s709a
+.section s709b
+.section s700a
+.section s700b
+.section s8aaa
+.section s8aab
+.section s8aba
+.section s8abb
+.section s8aca
+.section s8acb
+.section s8ada
+.section s8adb
+.section s8aea
+.section s8aeb
+.section s8afa
+.section s8afb
+.section s8aga
+.section s8agb
+.section s8aha
+.section s8ahb
+.section s8aia
+.section s8aib
+.section s8aja
+.section s8ajb
+.section s8aka
+.section s8akb
+.section s8ala
+.section s8alb
+.section s8ama
+.section s8amb
+.section s8ana
+.section s8anb
+.section s8aoa
+.section s8aob
+.section s8apa
+.section s8apb
+.section s8aqa
+.section s8aqb
+.section s8ara
+.section s8arb
+.section s8asa
+.section s8asb
+.section s8ata
+.section s8atb
+.section s8aua
+.section s8aub
+.section s8ava
+.section s8avb
+.section s8awa
+.section s8awb
+.section s8axa
+.section s8axb
+.section s8aya
+.section s8ayb
+.section s8aza
+.section s8azb
+.section s8a1a
+.section s8a1b
+.section s8a2a
+.section s8a2b
+.section s8a3a
+.section s8a3b
+.section s8a4a
+.section s8a4b
+.section s8a5a
+.section s8a5b
+.section s8a6a
+.section s8a6b
+.section s8a7a
+.section s8a7b
+.section s8a8a
+.section s8a8b
+.section s8a9a
+.section s8a9b
+.section s8a0a
+.section s8a0b
+.section s8baa
+.section s8bab
+.section s8bba
+.section s8bbb
+.section s8bca
+.section s8bcb
+.section s8bda
+.section s8bdb
+.section s8bea
+.section s8beb
+.section s8bfa
+.section s8bfb
+.section s8bga
+.section s8bgb
+.section s8bha
+.section s8bhb
+.section s8bia
+.section s8bib
+.section s8bja
+.section s8bjb
+.section s8bka
+.section s8bkb
+.section s8bla
+.section s8blb
+.section s8bma
+.section s8bmb
+.section s8bna
+.section s8bnb
+.section s8boa
+.section s8bob
+.section s8bpa
+.section s8bpb
+.section s8bqa
+.section s8bqb
+.section s8bra
+.section s8brb
+.section s8bsa
+.section s8bsb
+.section s8bta
+.section s8btb
+.section s8bua
+.section s8bub
+.section s8bva
+.section s8bvb
+.section s8bwa
+.section s8bwb
+.section s8bxa
+.section s8bxb
+.section s8bya
+.section s8byb
+.section s8bza
+.section s8bzb
+.section s8b1a
+.section s8b1b
+.section s8b2a
+.section s8b2b
+.section s8b3a
+.section s8b3b
+.section s8b4a
+.section s8b4b
+.section s8b5a
+.section s8b5b
+.section s8b6a
+.section s8b6b
+.section s8b7a
+.section s8b7b
+.section s8b8a
+.section s8b8b
+.section s8b9a
+.section s8b9b
+.section s8b0a
+.section s8b0b
+.section s8caa
+.section s8cab
+.section s8cba
+.section s8cbb
+.section s8cca
+.section s8ccb
+.section s8cda
+.section s8cdb
+.section s8cea
+.section s8ceb
+.section s8cfa
+.section s8cfb
+.section s8cga
+.section s8cgb
+.section s8cha
+.section s8chb
+.section s8cia
+.section s8cib
+.section s8cja
+.section s8cjb
+.section s8cka
+.section s8ckb
+.section s8cla
+.section s8clb
+.section s8cma
+.section s8cmb
+.section s8cna
+.section s8cnb
+.section s8coa
+.section s8cob
+.section s8cpa
+.section s8cpb
+.section s8cqa
+.section s8cqb
+.section s8cra
+.section s8crb
+.section s8csa
+.section s8csb
+.section s8cta
+.section s8ctb
+.section s8cua
+.section s8cub
+.section s8cva
+.section s8cvb
+.section s8cwa
+.section s8cwb
+.section s8cxa
+.section s8cxb
+.section s8cya
+.section s8cyb
+.section s8cza
+.section s8czb
+.section s8c1a
+.section s8c1b
+.section s8c2a
+.section s8c2b
+.section s8c3a
+.section s8c3b
+.section s8c4a
+.section s8c4b
+.section s8c5a
+.section s8c5b
+.section s8c6a
+.section s8c6b
+.section s8c7a
+.section s8c7b
+.section s8c8a
+.section s8c8b
+.section s8c9a
+.section s8c9b
+.section s8c0a
+.section s8c0b
+.section s8daa
+.section s8dab
+.section s8dba
+.section s8dbb
+.section s8dca
+.section s8dcb
+.section s8dda
+.section s8ddb
+.section s8dea
+.section s8deb
+.section s8dfa
+.section s8dfb
+.section s8dga
+.section s8dgb
+.section s8dha
+.section s8dhb
+.section s8dia
+.section s8dib
+.section s8dja
+.section s8djb
+.section s8dka
+.section s8dkb
+.section s8dla
+.section s8dlb
+.section s8dma
+.section s8dmb
+.section s8dna
+.section s8dnb
+.section s8doa
+.section s8dob
+.section s8dpa
+.section s8dpb
+.section s8dqa
+.section s8dqb
+.section s8dra
+.section s8drb
+.section s8dsa
+.section s8dsb
+.section s8dta
+.section s8dtb
+.section s8dua
+.section s8dub
+.section s8dva
+.section s8dvb
+.section s8dwa
+.section s8dwb
+.section s8dxa
+.section s8dxb
+.section s8dya
+.section s8dyb
+.section s8dza
+.section s8dzb
+.section s8d1a
+.section s8d1b
+.section s8d2a
+.section s8d2b
+.section s8d3a
+.section s8d3b
+.section s8d4a
+.section s8d4b
+.section s8d5a
+.section s8d5b
+.section s8d6a
+.section s8d6b
+.section s8d7a
+.section s8d7b
+.section s8d8a
+.section s8d8b
+.section s8d9a
+.section s8d9b
+.section s8d0a
+.section s8d0b
+.section s8eaa
+.section s8eab
+.section s8eba
+.section s8ebb
+.section s8eca
+.section s8ecb
+.section s8eda
+.section s8edb
+.section s8eea
+.section s8eeb
+.section s8efa
+.section s8efb
+.section s8ega
+.section s8egb
+.section s8eha
+.section s8ehb
+.section s8eia
+.section s8eib
+.section s8eja
+.section s8ejb
+.section s8eka
+.section s8ekb
+.section s8ela
+.section s8elb
+.section s8ema
+.section s8emb
+.section s8ena
+.section s8enb
+.section s8eoa
+.section s8eob
+.section s8epa
+.section s8epb
+.section s8eqa
+.section s8eqb
+.section s8era
+.section s8erb
+.section s8esa
+.section s8esb
+.section s8eta
+.section s8etb
+.section s8eua
+.section s8eub
+.section s8eva
+.section s8evb
+.section s8ewa
+.section s8ewb
+.section s8exa
+.section s8exb
+.section s8eya
+.section s8eyb
+.section s8eza
+.section s8ezb
+.section s8e1a
+.section s8e1b
+.section s8e2a
+.section s8e2b
+.section s8e3a
+.section s8e3b
+.section s8e4a
+.section s8e4b
+.section s8e5a
+.section s8e5b
+.section s8e6a
+.section s8e6b
+.section s8e7a
+.section s8e7b
+.section s8e8a
+.section s8e8b
+.section s8e9a
+.section s8e9b
+.section s8e0a
+.section s8e0b
+.section s8faa
+.section s8fab
+.section s8fba
+.section s8fbb
+.section s8fca
+.section s8fcb
+.section s8fda
+.section s8fdb
+.section s8fea
+.section s8feb
+.section s8ffa
+.section s8ffb
+.section s8fga
+.section s8fgb
+.section s8fha
+.section s8fhb
+.section s8fia
+.section s8fib
+.section s8fja
+.section s8fjb
+.section s8fka
+.section s8fkb
+.section s8fla
+.section s8flb
+.section s8fma
+.section s8fmb
+.section s8fna
+.section s8fnb
+.section s8foa
+.section s8fob
+.section s8fpa
+.section s8fpb
+.section s8fqa
+.section s8fqb
+.section s8fra
+.section s8frb
+.section s8fsa
+.section s8fsb
+.section s8fta
+.section s8ftb
+.section s8fua
+.section s8fub
+.section s8fva
+.section s8fvb
+.section s8fwa
+.section s8fwb
+.section s8fxa
+.section s8fxb
+.section s8fya
+.section s8fyb
+.section s8fza
+.section s8fzb
+.section s8f1a
+.section s8f1b
+.section s8f2a
+.section s8f2b
+.section s8f3a
+.section s8f3b
+.section s8f4a
+.section s8f4b
+.section s8f5a
+.section s8f5b
+.section s8f6a
+.section s8f6b
+.section s8f7a
+.section s8f7b
+.section s8f8a
+.section s8f8b
+.section s8f9a
+.section s8f9b
+.section s8f0a
+.section s8f0b
+.section s8gaa
+.section s8gab
+.section s8gba
+.section s8gbb
+.section s8gca
+.section s8gcb
+.section s8gda
+.section s8gdb
+.section s8gea
+.section s8geb
+.section s8gfa
+.section s8gfb
+.section s8gga
+.section s8ggb
+.section s8gha
+.section s8ghb
+.section s8gia
+.section s8gib
+.section s8gja
+.section s8gjb
+.section s8gka
+.section s8gkb
+.section s8gla
+.section s8glb
+.section s8gma
+.section s8gmb
+.section s8gna
+.section s8gnb
+.section s8goa
+.section s8gob
+.section s8gpa
+.section s8gpb
+.section s8gqa
+.section s8gqb
+.section s8gra
+.section s8grb
+.section s8gsa
+.section s8gsb
+.section s8gta
+.section s8gtb
+.section s8gua
+.section s8gub
+.section s8gva
+.section s8gvb
+.section s8gwa
+.section s8gwb
+.section s8gxa
+.section s8gxb
+.section s8gya
+.section s8gyb
+.section s8gza
+.section s8gzb
+.section s8g1a
+.section s8g1b
+.section s8g2a
+.section s8g2b
+.section s8g3a
+.section s8g3b
+.section s8g4a
+.section s8g4b
+.section s8g5a
+.section s8g5b
+.section s8g6a
+.section s8g6b
+.section s8g7a
+.section s8g7b
+.section s8g8a
+.section s8g8b
+.section s8g9a
+.section s8g9b
+.section s8g0a
+.section s8g0b
+.section s8haa
+.section s8hab
+.section s8hba
+.section s8hbb
+.section s8hca
+.section s8hcb
+.section s8hda
+.section s8hdb
+.section s8hea
+.section s8heb
+.section s8hfa
+.section s8hfb
+.section s8hga
+.section s8hgb
+.section s8hha
+.section s8hhb
+.section s8hia
+.section s8hib
+.section s8hja
+.section s8hjb
+.section s8hka
+.section s8hkb
+.section s8hla
+.section s8hlb
+.section s8hma
+.section s8hmb
+.section s8hna
+.section s8hnb
+.section s8hoa
+.section s8hob
+.section s8hpa
+.section s8hpb
+.section s8hqa
+.section s8hqb
+.section s8hra
+.section s8hrb
+.section s8hsa
+.section s8hsb
+.section s8hta
+.section s8htb
+.section s8hua
+.section s8hub
+.section s8hva
+.section s8hvb
+.section s8hwa
+.section s8hwb
+.section s8hxa
+.section s8hxb
+.section s8hya
+.section s8hyb
+.section s8hza
+.section s8hzb
+.section s8h1a
+.section s8h1b
+.section s8h2a
+.section s8h2b
+.section s8h3a
+.section s8h3b
+.section s8h4a
+.section s8h4b
+.section s8h5a
+.section s8h5b
+.section s8h6a
+.section s8h6b
+.section s8h7a
+.section s8h7b
+.section s8h8a
+.section s8h8b
+.section s8h9a
+.section s8h9b
+.section s8h0a
+.section s8h0b
+.section s8iaa
+.section s8iab
+.section s8iba
+.section s8ibb
+.section s8ica
+.section s8icb
+.section s8ida
+.section s8idb
+.section s8iea
+.section s8ieb
+.section s8ifa
+.section s8ifb
+.section s8iga
+.section s8igb
+.section s8iha
+.section s8ihb
+.section s8iia
+.section s8iib
+.section s8ija
+.section s8ijb
+.section s8ika
+.section s8ikb
+.section s8ila
+.section s8ilb
+.section s8ima
+.section s8imb
+.section s8ina
+.section s8inb
+.section s8ioa
+.section s8iob
+.section s8ipa
+.section s8ipb
+.section s8iqa
+.section s8iqb
+.section s8ira
+.section s8irb
+.section s8isa
+.section s8isb
+.section s8ita
+.section s8itb
+.section s8iua
+.section s8iub
+.section s8iva
+.section s8ivb
+.section s8iwa
+.section s8iwb
+.section s8ixa
+.section s8ixb
+.section s8iya
+.section s8iyb
+.section s8iza
+.section s8izb
+.section s8i1a
+.section s8i1b
+.section s8i2a
+.section s8i2b
+.section s8i3a
+.section s8i3b
+.section s8i4a
+.section s8i4b
+.section s8i5a
+.section s8i5b
+.section s8i6a
+.section s8i6b
+.section s8i7a
+.section s8i7b
+.section s8i8a
+.section s8i8b
+.section s8i9a
+.section s8i9b
+.section s8i0a
+.section s8i0b
+.section s8jaa
+.section s8jab
+.section s8jba
+.section s8jbb
+.section s8jca
+.section s8jcb
+.section s8jda
+.section s8jdb
+.section s8jea
+.section s8jeb
+.section s8jfa
+.section s8jfb
+.section s8jga
+.section s8jgb
+.section s8jha
+.section s8jhb
+.section s8jia
+.section s8jib
+.section s8jja
+.section s8jjb
+.section s8jka
+.section s8jkb
+.section s8jla
+.section s8jlb
+.section s8jma
+.section s8jmb
+.section s8jna
+.section s8jnb
+.section s8joa
+.section s8job
+.section s8jpa
+.section s8jpb
+.section s8jqa
+.section s8jqb
+.section s8jra
+.section s8jrb
+.section s8jsa
+.section s8jsb
+.section s8jta
+.section s8jtb
+.section s8jua
+.section s8jub
+.section s8jva
+.section s8jvb
+.section s8jwa
+.section s8jwb
+.section s8jxa
+.section s8jxb
+.section s8jya
+.section s8jyb
+.section s8jza
+.section s8jzb
+.section s8j1a
+.section s8j1b
+.section s8j2a
+.section s8j2b
+.section s8j3a
+.section s8j3b
+.section s8j4a
+.section s8j4b
+.section s8j5a
+.section s8j5b
+.section s8j6a
+.section s8j6b
+.section s8j7a
+.section s8j7b
+.section s8j8a
+.section s8j8b
+.section s8j9a
+.section s8j9b
+.section s8j0a
+.section s8j0b
+.section s8kaa
+.section s8kab
+.section s8kba
+.section s8kbb
+.section s8kca
+.section s8kcb
+.section s8kda
+.section s8kdb
+.section s8kea
+.section s8keb
+.section s8kfa
+.section s8kfb
+.section s8kga
+.section s8kgb
+.section s8kha
+.section s8khb
+.section s8kia
+.section s8kib
+.section s8kja
+.section s8kjb
+.section s8kka
+.section s8kkb
+.section s8kla
+.section s8klb
+.section s8kma
+.section s8kmb
+.section s8kna
+.section s8knb
+.section s8koa
+.section s8kob
+.section s8kpa
+.section s8kpb
+.section s8kqa
+.section s8kqb
+.section s8kra
+.section s8krb
+.section s8ksa
+.section s8ksb
+.section s8kta
+.section s8ktb
+.section s8kua
+.section s8kub
+.section s8kva
+.section s8kvb
+.section s8kwa
+.section s8kwb
+.section s8kxa
+.section s8kxb
+.section s8kya
+.section s8kyb
+.section s8kza
+.section s8kzb
+.section s8k1a
+.section s8k1b
+.section s8k2a
+.section s8k2b
+.section s8k3a
+.section s8k3b
+.section s8k4a
+.section s8k4b
+.section s8k5a
+.section s8k5b
+.section s8k6a
+.section s8k6b
+.section s8k7a
+.section s8k7b
+.section s8k8a
+.section s8k8b
+.section s8k9a
+.section s8k9b
+.section s8k0a
+.section s8k0b
+.section s8laa
+.section s8lab
+.section s8lba
+.section s8lbb
+.section s8lca
+.section s8lcb
+.section s8lda
+.section s8ldb
+.section s8lea
+.section s8leb
+.section s8lfa
+.section s8lfb
+.section s8lga
+.section s8lgb
+.section s8lha
+.section s8lhb
+.section s8lia
+.section s8lib
+.section s8lja
+.section s8ljb
+.section s8lka
+.section s8lkb
+.section s8lla
+.section s8llb
+.section s8lma
+.section s8lmb
+.section s8lna
+.section s8lnb
+.section s8loa
+.section s8lob
+.section s8lpa
+.section s8lpb
+.section s8lqa
+.section s8lqb
+.section s8lra
+.section s8lrb
+.section s8lsa
+.section s8lsb
+.section s8lta
+.section s8ltb
+.section s8lua
+.section s8lub
+.section s8lva
+.section s8lvb
+.section s8lwa
+.section s8lwb
+.section s8lxa
+.section s8lxb
+.section s8lya
+.section s8lyb
+.section s8lza
+.section s8lzb
+.section s8l1a
+.section s8l1b
+.section s8l2a
+.section s8l2b
+.section s8l3a
+.section s8l3b
+.section s8l4a
+.section s8l4b
+.section s8l5a
+.section s8l5b
+.section s8l6a
+.section s8l6b
+.section s8l7a
+.section s8l7b
+.section s8l8a
+.section s8l8b
+.section s8l9a
+.section s8l9b
+.section s8l0a
+.section s8l0b
+.section s8maa
+.section s8mab
+.section s8mba
+.section s8mbb
+.section s8mca
+.section s8mcb
+.section s8mda
+.section s8mdb
+.section s8mea
+.section s8meb
+.section s8mfa
+.section s8mfb
+.section s8mga
+.section s8mgb
+.section s8mha
+.section s8mhb
+.section s8mia
+.section s8mib
+.section s8mja
+.section s8mjb
+.section s8mka
+.section s8mkb
+.section s8mla
+.section s8mlb
+.section s8mma
+.section s8mmb
+.section s8mna
+.section s8mnb
+.section s8moa
+.section s8mob
+.section s8mpa
+.section s8mpb
+.section s8mqa
+.section s8mqb
+.section s8mra
+.section s8mrb
+.section s8msa
+.section s8msb
+.section s8mta
+.section s8mtb
+.section s8mua
+.section s8mub
+.section s8mva
+.section s8mvb
+.section s8mwa
+.section s8mwb
+.section s8mxa
+.section s8mxb
+.section s8mya
+.section s8myb
+.section s8mza
+.section s8mzb
+.section s8m1a
+.section s8m1b
+.section s8m2a
+.section s8m2b
+.section s8m3a
+.section s8m3b
+.section s8m4a
+.section s8m4b
+.section s8m5a
+.section s8m5b
+.section s8m6a
+.section s8m6b
+.section s8m7a
+.section s8m7b
+.section s8m8a
+.section s8m8b
+.section s8m9a
+.section s8m9b
+.section s8m0a
+.section s8m0b
+.section s8naa
+.section s8nab
+.section s8nba
+.section s8nbb
+.section s8nca
+.section s8ncb
+.section s8nda
+.section s8ndb
+.section s8nea
+.section s8neb
+.section s8nfa
+.section s8nfb
+.section s8nga
+.section s8ngb
+.section s8nha
+.section s8nhb
+.section s8nia
+.section s8nib
+.section s8nja
+.section s8njb
+.section s8nka
+.section s8nkb
+.section s8nla
+.section s8nlb
+.section s8nma
+.section s8nmb
+.section s8nna
+.section s8nnb
+.section s8noa
+.section s8nob
+.section s8npa
+.section s8npb
+.section s8nqa
+.section s8nqb
+.section s8nra
+.section s8nrb
+.section s8nsa
+.section s8nsb
+.section s8nta
+.section s8ntb
+.section s8nua
+.section s8nub
+.section s8nva
+.section s8nvb
+.section s8nwa
+.section s8nwb
+.section s8nxa
+.section s8nxb
+.section s8nya
+.section s8nyb
+.section s8nza
+.section s8nzb
+.section s8n1a
+.section s8n1b
+.section s8n2a
+.section s8n2b
+.section s8n3a
+.section s8n3b
+.section s8n4a
+.section s8n4b
+.section s8n5a
+.section s8n5b
+.section s8n6a
+.section s8n6b
+.section s8n7a
+.section s8n7b
+.section s8n8a
+.section s8n8b
+.section s8n9a
+.section s8n9b
+.section s8n0a
+.section s8n0b
+.section s8oaa
+.section s8oab
+.section s8oba
+.section s8obb
+.section s8oca
+.section s8ocb
+.section s8oda
+.section s8odb
+.section s8oea
+.section s8oeb
+.section s8ofa
+.section s8ofb
+.section s8oga
+.section s8ogb
+.section s8oha
+.section s8ohb
+.section s8oia
+.section s8oib
+.section s8oja
+.section s8ojb
+.section s8oka
+.section s8okb
+.section s8ola
+.section s8olb
+.section s8oma
+.section s8omb
+.section s8ona
+.section s8onb
+.section s8ooa
+.section s8oob
+.section s8opa
+.section s8opb
+.section s8oqa
+.section s8oqb
+.section s8ora
+.section s8orb
+.section s8osa
+.section s8osb
+.section s8ota
+.section s8otb
+.section s8oua
+.section s8oub
+.section s8ova
+.section s8ovb
+.section s8owa
+.section s8owb
+.section s8oxa
+.section s8oxb
+.section s8oya
+.section s8oyb
+.section s8oza
+.section s8ozb
+.section s8o1a
+.section s8o1b
+.section s8o2a
+.section s8o2b
+.section s8o3a
+.section s8o3b
+.section s8o4a
+.section s8o4b
+.section s8o5a
+.section s8o5b
+.section s8o6a
+.section s8o6b
+.section s8o7a
+.section s8o7b
+.section s8o8a
+.section s8o8b
+.section s8o9a
+.section s8o9b
+.section s8o0a
+.section s8o0b
+.section s8paa
+.section s8pab
+.section s8pba
+.section s8pbb
+.section s8pca
+.section s8pcb
+.section s8pda
+.section s8pdb
+.section s8pea
+.section s8peb
+.section s8pfa
+.section s8pfb
+.section s8pga
+.section s8pgb
+.section s8pha
+.section s8phb
+.section s8pia
+.section s8pib
+.section s8pja
+.section s8pjb
+.section s8pka
+.section s8pkb
+.section s8pla
+.section s8plb
+.section s8pma
+.section s8pmb
+.section s8pna
+.section s8pnb
+.section s8poa
+.section s8pob
+.section s8ppa
+.section s8ppb
+.section s8pqa
+.section s8pqb
+.section s8pra
+.section s8prb
+.section s8psa
+.section s8psb
+.section s8pta
+.section s8ptb
+.section s8pua
+.section s8pub
+.section s8pva
+.section s8pvb
+.section s8pwa
+.section s8pwb
+.section s8pxa
+.section s8pxb
+.section s8pya
+.section s8pyb
+.section s8pza
+.section s8pzb
+.section s8p1a
+.section s8p1b
+.section s8p2a
+.section s8p2b
+.section s8p3a
+.section s8p3b
+.section s8p4a
+.section s8p4b
+.section s8p5a
+.section s8p5b
+.section s8p6a
+.section s8p6b
+.section s8p7a
+.section s8p7b
+.section s8p8a
+.section s8p8b
+.section s8p9a
+.section s8p9b
+.section s8p0a
+.section s8p0b
+.section s8qaa
+.section s8qab
+.section s8qba
+.section s8qbb
+.section s8qca
+.section s8qcb
+.section s8qda
+.section s8qdb
+.section s8qea
+.section s8qeb
+.section s8qfa
+.section s8qfb
+.section s8qga
+.section s8qgb
+.section s8qha
+.section s8qhb
+.section s8qia
+.section s8qib
+.section s8qja
+.section s8qjb
+.section s8qka
+.section s8qkb
+.section s8qla
+.section s8qlb
+.section s8qma
+.section s8qmb
+.section s8qna
+.section s8qnb
+.section s8qoa
+.section s8qob
+.section s8qpa
+.section s8qpb
+.section s8qqa
+.section s8qqb
+.section s8qra
+.section s8qrb
+.section s8qsa
+.section s8qsb
+.section s8qta
+.section s8qtb
+.section s8qua
+.section s8qub
+.section s8qva
+.section s8qvb
+.section s8qwa
+.section s8qwb
+.section s8qxa
+.section s8qxb
+.section s8qya
+.section s8qyb
+.section s8qza
+.section s8qzb
+.section s8q1a
+.section s8q1b
+.section s8q2a
+.section s8q2b
+.section s8q3a
+.section s8q3b
+.section s8q4a
+.section s8q4b
+.section s8q5a
+.section s8q5b
+.section s8q6a
+.section s8q6b
+.section s8q7a
+.section s8q7b
+.section s8q8a
+.section s8q8b
+.section s8q9a
+.section s8q9b
+.section s8q0a
+.section s8q0b
+.section s8raa
+.section s8rab
+.section s8rba
+.section s8rbb
+.section s8rca
+.section s8rcb
+.section s8rda
+.section s8rdb
+.section s8rea
+.section s8reb
+.section s8rfa
+.section s8rfb
+.section s8rga
+.section s8rgb
+.section s8rha
+.section s8rhb
+.section s8ria
+.section s8rib
+.section s8rja
+.section s8rjb
+.section s8rka
+.section s8rkb
+.section s8rla
+.section s8rlb
+.section s8rma
+.section s8rmb
+.section s8rna
+.section s8rnb
+.section s8roa
+.section s8rob
+.section s8rpa
+.section s8rpb
+.section s8rqa
+.section s8rqb
+.section s8rra
+.section s8rrb
+.section s8rsa
+.section s8rsb
+.section s8rta
+.section s8rtb
+.section s8rua
+.section s8rub
+.section s8rva
+.section s8rvb
+.section s8rwa
+.section s8rwb
+.section s8rxa
+.section s8rxb
+.section s8rya
+.section s8ryb
+.section s8rza
+.section s8rzb
+.section s8r1a
+.section s8r1b
+.section s8r2a
+.section s8r2b
+.section s8r3a
+.section s8r3b
+.section s8r4a
+.section s8r4b
+.section s8r5a
+.section s8r5b
+.section s8r6a
+.section s8r6b
+.section s8r7a
+.section s8r7b
+.section s8r8a
+.section s8r8b
+.section s8r9a
+.section s8r9b
+.section s8r0a
+.section s8r0b
+.section s8saa
+.section s8sab
+.section s8sba
+.section s8sbb
+.section s8sca
+.section s8scb
+.section s8sda
+.section s8sdb
+.section s8sea
+.section s8seb
+.section s8sfa
+.section s8sfb
+.section s8sga
+.section s8sgb
+.section s8sha
+.section s8shb
+.section s8sia
+.section s8sib
+.section s8sja
+.section s8sjb
+.section s8ska
+.section s8skb
+.section s8sla
+.section s8slb
+.section s8sma
+.section s8smb
+.section s8sna
+.section s8snb
+.section s8soa
+.section s8sob
+.section s8spa
+.section s8spb
+.section s8sqa
+.section s8sqb
+.section s8sra
+.section s8srb
+.section s8ssa
+.section s8ssb
+.section s8sta
+.section s8stb
+.section s8sua
+.section s8sub
+.section s8sva
+.section s8svb
+.section s8swa
+.section s8swb
+.section s8sxa
+.section s8sxb
+.section s8sya
+.section s8syb
+.section s8sza
+.section s8szb
+.section s8s1a
+.section s8s1b
+.section s8s2a
+.section s8s2b
+.section s8s3a
+.section s8s3b
+.section s8s4a
+.section s8s4b
+.section s8s5a
+.section s8s5b
+.section s8s6a
+.section s8s6b
+.section s8s7a
+.section s8s7b
+.section s8s8a
+.section s8s8b
+.section s8s9a
+.section s8s9b
+.section s8s0a
+.section s8s0b
+.section s8taa
+.section s8tab
+.section s8tba
+.section s8tbb
+.section s8tca
+.section s8tcb
+.section s8tda
+.section s8tdb
+.section s8tea
+.section s8teb
+.section s8tfa
+.section s8tfb
+.section s8tga
+.section s8tgb
+.section s8tha
+.section s8thb
+.section s8tia
+.section s8tib
+.section s8tja
+.section s8tjb
+.section s8tka
+.section s8tkb
+.section s8tla
+.section s8tlb
+.section s8tma
+.section s8tmb
+.section s8tna
+.section s8tnb
+.section s8toa
+.section s8tob
+.section s8tpa
+.section s8tpb
+.section s8tqa
+.section s8tqb
+.section s8tra
+.section s8trb
+.section s8tsa
+.section s8tsb
+.section s8tta
+.section s8ttb
+.section s8tua
+.section s8tub
+.section s8tva
+.section s8tvb
+.section s8twa
+.section s8twb
+.section s8txa
+.section s8txb
+.section s8tya
+.section s8tyb
+.section s8tza
+.section s8tzb
+.section s8t1a
+.section s8t1b
+.section s8t2a
+.section s8t2b
+.section s8t3a
+.section s8t3b
+.section s8t4a
+.section s8t4b
+.section s8t5a
+.section s8t5b
+.section s8t6a
+.section s8t6b
+.section s8t7a
+.section s8t7b
+.section s8t8a
+.section s8t8b
+.section s8t9a
+.section s8t9b
+.section s8t0a
+.section s8t0b
+.section s8uaa
+.section s8uab
+.section s8uba
+.section s8ubb
+.section s8uca
+.section s8ucb
+.section s8uda
+.section s8udb
+.section s8uea
+.section s8ueb
+.section s8ufa
+.section s8ufb
+.section s8uga
+.section s8ugb
+.section s8uha
+.section s8uhb
+.section s8uia
+.section s8uib
+.section s8uja
+.section s8ujb
+.section s8uka
+.section s8ukb
+.section s8ula
+.section s8ulb
+.section s8uma
+.section s8umb
+.section s8una
+.section s8unb
+.section s8uoa
+.section s8uob
+.section s8upa
+.section s8upb
+.section s8uqa
+.section s8uqb
+.section s8ura
+.section s8urb
+.section s8usa
+.section s8usb
+.section s8uta
+.section s8utb
+.section s8uua
+.section s8uub
+.section s8uva
+.section s8uvb
+.section s8uwa
+.section s8uwb
+.section s8uxa
+.section s8uxb
+.section s8uya
+.section s8uyb
+.section s8uza
+.section s8uzb
+.section s8u1a
+.section s8u1b
+.section s8u2a
+.section s8u2b
+.section s8u3a
+.section s8u3b
+.section s8u4a
+.section s8u4b
+.section s8u5a
+.section s8u5b
+.section s8u6a
+.section s8u6b
+.section s8u7a
+.section s8u7b
+.section s8u8a
+.section s8u8b
+.section s8u9a
+.section s8u9b
+.section s8u0a
+.section s8u0b
+.section s8vaa
+.section s8vab
+.section s8vba
+.section s8vbb
+.section s8vca
+.section s8vcb
+.section s8vda
+.section s8vdb
+.section s8vea
+.section s8veb
+.section s8vfa
+.section s8vfb
+.section s8vga
+.section s8vgb
+.section s8vha
+.section s8vhb
+.section s8via
+.section s8vib
+.section s8vja
+.section s8vjb
+.section s8vka
+.section s8vkb
+.section s8vla
+.section s8vlb
+.section s8vma
+.section s8vmb
+.section s8vna
+.section s8vnb
+.section s8voa
+.section s8vob
+.section s8vpa
+.section s8vpb
+.section s8vqa
+.section s8vqb
+.section s8vra
+.section s8vrb
+.section s8vsa
+.section s8vsb
+.section s8vta
+.section s8vtb
+.section s8vua
+.section s8vub
+.section s8vva
+.section s8vvb
+.section s8vwa
+.section s8vwb
+.section s8vxa
+.section s8vxb
+.section s8vya
+.section s8vyb
+.section s8vza
+.section s8vzb
+.section s8v1a
+.section s8v1b
+.section s8v2a
+.section s8v2b
+.section s8v3a
+.section s8v3b
+.section s8v4a
+.section s8v4b
+.section s8v5a
+.section s8v5b
+.section s8v6a
+.section s8v6b
+.section s8v7a
+.section s8v7b
+.section s8v8a
+.section s8v8b
+.section s8v9a
+.section s8v9b
+.section s8v0a
+.section s8v0b
+.section s8waa
+.section s8wab
+.section s8wba
+.section s8wbb
+.section s8wca
+.section s8wcb
+.section s8wda
+.section s8wdb
+.section s8wea
+.section s8web
+.section s8wfa
+.section s8wfb
+.section s8wga
+.section s8wgb
+.section s8wha
+.section s8whb
+.section s8wia
+.section s8wib
+.section s8wja
+.section s8wjb
+.section s8wka
+.section s8wkb
+.section s8wla
+.section s8wlb
+.section s8wma
+.section s8wmb
+.section s8wna
+.section s8wnb
+.section s8woa
+.section s8wob
+.section s8wpa
+.section s8wpb
+.section s8wqa
+.section s8wqb
+.section s8wra
+.section s8wrb
+.section s8wsa
+.section s8wsb
+.section s8wta
+.section s8wtb
+.section s8wua
+.section s8wub
+.section s8wva
+.section s8wvb
+.section s8wwa
+.section s8wwb
+.section s8wxa
+.section s8wxb
+.section s8wya
+.section s8wyb
+.section s8wza
+.section s8wzb
+.section s8w1a
+.section s8w1b
+.section s8w2a
+.section s8w2b
+.section s8w3a
+.section s8w3b
+.section s8w4a
+.section s8w4b
+.section s8w5a
+.section s8w5b
+.section s8w6a
+.section s8w6b
+.section s8w7a
+.section s8w7b
+.section s8w8a
+.section s8w8b
+.section s8w9a
+.section s8w9b
+.section s8w0a
+.section s8w0b
+.section s8xaa
+.section s8xab
+.section s8xba
+.section s8xbb
+.section s8xca
+.section s8xcb
+.section s8xda
+.section s8xdb
+.section s8xea
+.section s8xeb
+.section s8xfa
+.section s8xfb
+.section s8xga
+.section s8xgb
+.section s8xha
+.section s8xhb
+.section s8xia
+.section s8xib
+.section s8xja
+.section s8xjb
+.section s8xka
+.section s8xkb
+.section s8xla
+.section s8xlb
+.section s8xma
+.section s8xmb
+.section s8xna
+.section s8xnb
+.section s8xoa
+.section s8xob
+.section s8xpa
+.section s8xpb
+.section s8xqa
+.section s8xqb
+.section s8xra
+.section s8xrb
+.section s8xsa
+.section s8xsb
+.section s8xta
+.section s8xtb
+.section s8xua
+.section s8xub
+.section s8xva
+.section s8xvb
+.section s8xwa
+.section s8xwb
+.section s8xxa
+.section s8xxb
+.section s8xya
+.section s8xyb
+.section s8xza
+.section s8xzb
+.section s8x1a
+.section s8x1b
+.section s8x2a
+.section s8x2b
+.section s8x3a
+.section s8x3b
+.section s8x4a
+.section s8x4b
+.section s8x5a
+.section s8x5b
+.section s8x6a
+.section s8x6b
+.section s8x7a
+.section s8x7b
+.section s8x8a
+.section s8x8b
+.section s8x9a
+.section s8x9b
+.section s8x0a
+.section s8x0b
+.section s8yaa
+.section s8yab
+.section s8yba
+.section s8ybb
+.section s8yca
+.section s8ycb
+.section s8yda
+.section s8ydb
+.section s8yea
+.section s8yeb
+.section s8yfa
+.section s8yfb
+.section s8yga
+.section s8ygb
+.section s8yha
+.section s8yhb
+.section s8yia
+.section s8yib
+.section s8yja
+.section s8yjb
+.section s8yka
+.section s8ykb
+.section s8yla
+.section s8ylb
+.section s8yma
+.section s8ymb
+.section s8yna
+.section s8ynb
+.section s8yoa
+.section s8yob
+.section s8ypa
+.section s8ypb
+.section s8yqa
+.section s8yqb
+.section s8yra
+.section s8yrb
+.section s8ysa
+.section s8ysb
+.section s8yta
+.section s8ytb
+.section s8yua
+.section s8yub
+.section s8yva
+.section s8yvb
+.section s8ywa
+.section s8ywb
+.section s8yxa
+.section s8yxb
+.section s8yya
+.section s8yyb
+.section s8yza
+.section s8yzb
+.section s8y1a
+.section s8y1b
+.section s8y2a
+.section s8y2b
+.section s8y3a
+.section s8y3b
+.section s8y4a
+.section s8y4b
+.section s8y5a
+.section s8y5b
+.section s8y6a
+.section s8y6b
+.section s8y7a
+.section s8y7b
+.section s8y8a
+.section s8y8b
+.section s8y9a
+.section s8y9b
+.section s8y0a
+.section s8y0b
+.section s8zaa
+.section s8zab
+.section s8zba
+.section s8zbb
+.section s8zca
+.section s8zcb
+.section s8zda
+.section s8zdb
+.section s8zea
+.section s8zeb
+.section s8zfa
+.section s8zfb
+.section s8zga
+.section s8zgb
+.section s8zha
+.section s8zhb
+.section s8zia
+.section s8zib
+.section s8zja
+.section s8zjb
+.section s8zka
+.section s8zkb
+.section s8zla
+.section s8zlb
+.section s8zma
+.section s8zmb
+.section s8zna
+.section s8znb
+.section s8zoa
+.section s8zob
+.section s8zpa
+.section s8zpb
+.section s8zqa
+.section s8zqb
+.section s8zra
+.section s8zrb
+.section s8zsa
+.section s8zsb
+.section s8zta
+.section s8ztb
+.section s8zua
+.section s8zub
+.section s8zva
+.section s8zvb
+.section s8zwa
+.section s8zwb
+.section s8zxa
+.section s8zxb
+.section s8zya
+.section s8zyb
+.section s8zza
+.section s8zzb
+.section s8z1a
+.section s8z1b
+.section s8z2a
+.section s8z2b
+.section s8z3a
+.section s8z3b
+.section s8z4a
+.section s8z4b
+.section s8z5a
+.section s8z5b
+.section s8z6a
+.section s8z6b
+.section s8z7a
+.section s8z7b
+.section s8z8a
+.section s8z8b
+.section s8z9a
+.section s8z9b
+.section s8z0a
+.section s8z0b
+.section s81aa
+.section s81ab
+.section s81ba
+.section s81bb
+.section s81ca
+.section s81cb
+.section s81da
+.section s81db
+.section s81ea
+.section s81eb
+.section s81fa
+.section s81fb
+.section s81ga
+.section s81gb
+.section s81ha
+.section s81hb
+.section s81ia
+.section s81ib
+.section s81ja
+.section s81jb
+.section s81ka
+.section s81kb
+.section s81la
+.section s81lb
+.section s81ma
+.section s81mb
+.section s81na
+.section s81nb
+.section s81oa
+.section s81ob
+.section s81pa
+.section s81pb
+.section s81qa
+.section s81qb
+.section s81ra
+.section s81rb
+.section s81sa
+.section s81sb
+.section s81ta
+.section s81tb
+.section s81ua
+.section s81ub
+.section s81va
+.section s81vb
+.section s81wa
+.section s81wb
+.section s81xa
+.section s81xb
+.section s81ya
+.section s81yb
+.section s81za
+.section s81zb
+.section s811a
+.section s811b
+.section s812a
+.section s812b
+.section s813a
+.section s813b
+.section s814a
+.section s814b
+.section s815a
+.section s815b
+.section s816a
+.section s816b
+.section s817a
+.section s817b
+.section s818a
+.section s818b
+.section s819a
+.section s819b
+.section s810a
+.section s810b
+.section s82aa
+.section s82ab
+.section s82ba
+.section s82bb
+.section s82ca
+.section s82cb
+.section s82da
+.section s82db
+.section s82ea
+.section s82eb
+.section s82fa
+.section s82fb
+.section s82ga
+.section s82gb
+.section s82ha
+.section s82hb
+.section s82ia
+.section s82ib
+.section s82ja
+.section s82jb
+.section s82ka
+.section s82kb
+.section s82la
+.section s82lb
+.section s82ma
+.section s82mb
+.section s82na
+.section s82nb
+.section s82oa
+.section s82ob
+.section s82pa
+.section s82pb
+.section s82qa
+.section s82qb
+.section s82ra
+.section s82rb
+.section s82sa
+.section s82sb
+.section s82ta
+.section s82tb
+.section s82ua
+.section s82ub
+.section s82va
+.section s82vb
+.section s82wa
+.section s82wb
+.section s82xa
+.section s82xb
+.section s82ya
+.section s82yb
+.section s82za
+.section s82zb
+.section s821a
+.section s821b
+.section s822a
+.section s822b
+.section s823a
+.section s823b
+.section s824a
+.section s824b
+.section s825a
+.section s825b
+.section s826a
+.section s826b
+.section s827a
+.section s827b
+.section s828a
+.section s828b
+.section s829a
+.section s829b
+.section s820a
+.section s820b
+.section s83aa
+.section s83ab
+.section s83ba
+.section s83bb
+.section s83ca
+.section s83cb
+.section s83da
+.section s83db
+.section s83ea
+.section s83eb
+.section s83fa
+.section s83fb
+.section s83ga
+.section s83gb
+.section s83ha
+.section s83hb
+.section s83ia
+.section s83ib
+.section s83ja
+.section s83jb
+.section s83ka
+.section s83kb
+.section s83la
+.section s83lb
+.section s83ma
+.section s83mb
+.section s83na
+.section s83nb
+.section s83oa
+.section s83ob
+.section s83pa
+.section s83pb
+.section s83qa
+.section s83qb
+.section s83ra
+.section s83rb
+.section s83sa
+.section s83sb
+.section s83ta
+.section s83tb
+.section s83ua
+.section s83ub
+.section s83va
+.section s83vb
+.section s83wa
+.section s83wb
+.section s83xa
+.section s83xb
+.section s83ya
+.section s83yb
+.section s83za
+.section s83zb
+.section s831a
+.section s831b
+.section s832a
+.section s832b
+.section s833a
+.section s833b
+.section s834a
+.section s834b
+.section s835a
+.section s835b
+.section s836a
+.section s836b
+.section s837a
+.section s837b
+.section s838a
+.section s838b
+.section s839a
+.section s839b
+.section s830a
+.section s830b
+.section s84aa
+.section s84ab
+.section s84ba
+.section s84bb
+.section s84ca
+.section s84cb
+.section s84da
+.section s84db
+.section s84ea
+.section s84eb
+.section s84fa
+.section s84fb
+.section s84ga
+.section s84gb
+.section s84ha
+.section s84hb
+.section s84ia
+.section s84ib
+.section s84ja
+.section s84jb
+.section s84ka
+.section s84kb
+.section s84la
+.section s84lb
+.section s84ma
+.section s84mb
+.section s84na
+.section s84nb
+.section s84oa
+.section s84ob
+.section s84pa
+.section s84pb
+.section s84qa
+.section s84qb
+.section s84ra
+.section s84rb
+.section s84sa
+.section s84sb
+.section s84ta
+.section s84tb
+.section s84ua
+.section s84ub
+.section s84va
+.section s84vb
+.section s84wa
+.section s84wb
+.section s84xa
+.section s84xb
+.section s84ya
+.section s84yb
+.section s84za
+.section s84zb
+.section s841a
+.section s841b
+.section s842a
+.section s842b
+.section s843a
+.section s843b
+.section s844a
+.section s844b
+.section s845a
+.section s845b
+.section s846a
+.section s846b
+.section s847a
+.section s847b
+.section s848a
+.section s848b
+.section s849a
+.section s849b
+.section s840a
+.section s840b
+.section s85aa
+.section s85ab
+.section s85ba
+.section s85bb
+.section s85ca
+.section s85cb
+.section s85da
+.section s85db
+.section s85ea
+.section s85eb
+.section s85fa
+.section s85fb
+.section s85ga
+.section s85gb
+.section s85ha
+.section s85hb
+.section s85ia
+.section s85ib
+.section s85ja
+.section s85jb
+.section s85ka
+.section s85kb
+.section s85la
+.section s85lb
+.section s85ma
+.section s85mb
+.section s85na
+.section s85nb
+.section s85oa
+.section s85ob
+.section s85pa
+.section s85pb
+.section s85qa
+.section s85qb
+.section s85ra
+.section s85rb
+.section s85sa
+.section s85sb
+.section s85ta
+.section s85tb
+.section s85ua
+.section s85ub
+.section s85va
+.section s85vb
+.section s85wa
+.section s85wb
+.section s85xa
+.section s85xb
+.section s85ya
+.section s85yb
+.section s85za
+.section s85zb
+.section s851a
+.section s851b
+.section s852a
+.section s852b
+.section s853a
+.section s853b
+.section s854a
+.section s854b
+.section s855a
+.section s855b
+.section s856a
+.section s856b
+.section s857a
+.section s857b
+.section s858a
+.section s858b
+.section s859a
+.section s859b
+.section s850a
+.section s850b
+.section s86aa
+.section s86ab
+.section s86ba
+.section s86bb
+.section s86ca
+.section s86cb
+.section s86da
+.section s86db
+.section s86ea
+.section s86eb
+.section s86fa
+.section s86fb
+.section s86ga
+.section s86gb
+.section s86ha
+.section s86hb
+.section s86ia
+.section s86ib
+.section s86ja
+.section s86jb
+.section s86ka
+.section s86kb
+.section s86la
+.section s86lb
+.section s86ma
+.section s86mb
+.section s86na
+.section s86nb
+.section s86oa
+.section s86ob
+.section s86pa
+.section s86pb
+.section s86qa
+.section s86qb
+.section s86ra
+.section s86rb
+.section s86sa
+.section s86sb
+.section s86ta
+.section s86tb
+.section s86ua
+.section s86ub
+.section s86va
+.section s86vb
+.section s86wa
+.section s86wb
+.section s86xa
+.section s86xb
+.section s86ya
+.section s86yb
+.section s86za
+.section s86zb
+.section s861a
+.section s861b
+.section s862a
+.section s862b
+.section s863a
+.section s863b
+.section s864a
+.section s864b
+.section s865a
+.section s865b
+.section s866a
+.section s866b
+.section s867a
+.section s867b
+.section s868a
+.section s868b
+.section s869a
+.section s869b
+.section s860a
+.section s860b
+.section s87aa
+.section s87ab
+.section s87ba
+.section s87bb
+.section s87ca
+.section s87cb
+.section s87da
+.section s87db
+.section s87ea
+.section s87eb
+.section s87fa
+.section s87fb
+.section s87ga
+.section s87gb
+.section s87ha
+.section s87hb
+.section s87ia
+.section s87ib
+.section s87ja
+.section s87jb
+.section s87ka
+.section s87kb
+.section s87la
+.section s87lb
+.section s87ma
+.section s87mb
+.section s87na
+.section s87nb
+.section s87oa
+.section s87ob
+.section s87pa
+.section s87pb
+.section s87qa
+.section s87qb
+.section s87ra
+.section s87rb
+.section s87sa
+.section s87sb
+.section s87ta
+.section s87tb
+.section s87ua
+.section s87ub
+.section s87va
+.section s87vb
+.section s87wa
+.section s87wb
+.section s87xa
+.section s87xb
+.section s87ya
+.section s87yb
+.section s87za
+.section s87zb
+.section s871a
+.section s871b
+.section s872a
+.section s872b
+.section s873a
+.section s873b
+.section s874a
+.section s874b
+.section s875a
+.section s875b
+.section s876a
+.section s876b
+.section s877a
+.section s877b
+.section s878a
+.section s878b
+.section s879a
+.section s879b
+.section s870a
+.section s870b
+.section s88aa
+.section s88ab
+.section s88ba
+.section s88bb
+.section s88ca
+.section s88cb
+.section s88da
+.section s88db
+.section s88ea
+.section s88eb
+.section s88fa
+.section s88fb
+.section s88ga
+.section s88gb
+.section s88ha
+.section s88hb
+.section s88ia
+.section s88ib
+.section s88ja
+.section s88jb
+.section s88ka
+.section s88kb
+.section s88la
+.section s88lb
+.section s88ma
+.section s88mb
+.section s88na
+.section s88nb
+.section s88oa
+.section s88ob
+.section s88pa
+.section s88pb
+.section s88qa
+.section s88qb
+.section s88ra
+.section s88rb
+.section s88sa
+.section s88sb
+.section s88ta
+.section s88tb
+.section s88ua
+.section s88ub
+.section s88va
+.section s88vb
+.section s88wa
+.section s88wb
+.section s88xa
+.section s88xb
+.section s88ya
+.section s88yb
+.section s88za
+.section s88zb
+.section s881a
+.section s881b
+.section s882a
+.section s882b
+.section s883a
+.section s883b
+.section s884a
+.section s884b
+.section s885a
+.section s885b
+.section s886a
+.section s886b
+.section s887a
+.section s887b
+.section s888a
+.section s888b
+.section s889a
+.section s889b
+.section s880a
+.section s880b
+.section s89aa
+.section s89ab
+.section s89ba
+.section s89bb
+.section s89ca
+.section s89cb
+.section s89da
+.section s89db
+.section s89ea
+.section s89eb
+.section s89fa
+.section s89fb
+.section s89ga
+.section s89gb
+.section s89ha
+.section s89hb
+.section s89ia
+.section s89ib
+.section s89ja
+.section s89jb
+.section s89ka
+.section s89kb
+.section s89la
+.section s89lb
+.section s89ma
+.section s89mb
+.section s89na
+.section s89nb
+.section s89oa
+.section s89ob
+.section s89pa
+.section s89pb
+.section s89qa
+.section s89qb
+.section s89ra
+.section s89rb
+.section s89sa
+.section s89sb
+.section s89ta
+.section s89tb
+.section s89ua
+.section s89ub
+.section s89va
+.section s89vb
+.section s89wa
+.section s89wb
+.section s89xa
+.section s89xb
+.section s89ya
+.section s89yb
+.section s89za
+.section s89zb
+.section s891a
+.section s891b
+.section s892a
+.section s892b
+.section s893a
+.section s893b
+.section s894a
+.section s894b
+.section s895a
+.section s895b
+.section s896a
+.section s896b
+.section s897a
+.section s897b
+.section s898a
+.section s898b
+.section s899a
+.section s899b
+.section s890a
+.section s890b
+.section s80aa
+.section s80ab
+.section s80ba
+.section s80bb
+.section s80ca
+.section s80cb
+.section s80da
+.section s80db
+.section s80ea
+.section s80eb
+.section s80fa
+.section s80fb
+.section s80ga
+.section s80gb
+.section s80ha
+.section s80hb
+.section s80ia
+.section s80ib
+.section s80ja
+.section s80jb
+.section s80ka
+.section s80kb
+.section s80la
+.section s80lb
+.section s80ma
+.section s80mb
+.section s80na
+.section s80nb
+.section s80oa
+.section s80ob
+.section s80pa
+.section s80pb
+.section s80qa
+.section s80qb
+.section s80ra
+.section s80rb
+.section s80sa
+.section s80sb
+.section s80ta
+.section s80tb
+.section s80ua
+.section s80ub
+.section s80va
+.section s80vb
+.section s80wa
+.section s80wb
+.section s80xa
+.section s80xb
+.section s80ya
+.section s80yb
+.section s80za
+.section s80zb
+.section s801a
+.section s801b
+.section s802a
+.section s802b
+.section s803a
+.section s803b
+.section s804a
+.section s804b
+.section s805a
+.section s805b
+.section s806a
+.section s806b
+.section s807a
+.section s807b
+.section s808a
+.section s808b
+.section s809a
+.section s809b
+.section s800a
+.section s800b
+.section s9aaa
+.section s9aab
+.section s9aba
+.section s9abb
+.section s9aca
+.section s9acb
+.section s9ada
+.section s9adb
+.section s9aea
+.section s9aeb
+.section s9afa
+.section s9afb
+.section s9aga
+.section s9agb
+.section s9aha
+.section s9ahb
+.section s9aia
+.section s9aib
+.section s9aja
+.section s9ajb
+.section s9aka
+.section s9akb
+.section s9ala
+.section s9alb
+.section s9ama
+.section s9amb
+.section s9ana
+.section s9anb
+.section s9aoa
+.section s9aob
+.section s9apa
+.section s9apb
+.section s9aqa
+.section s9aqb
+.section s9ara
+.section s9arb
+.section s9asa
+.section s9asb
+.section s9ata
+.section s9atb
+.section s9aua
+.section s9aub
+.section s9ava
+.section s9avb
+.section s9awa
+.section s9awb
+.section s9axa
+.section s9axb
+.section s9aya
+.section s9ayb
+.section s9aza
+.section s9azb
+.section s9a1a
+.section s9a1b
+.section s9a2a
+.section s9a2b
+.section s9a3a
+.section s9a3b
+.section s9a4a
+.section s9a4b
+.section s9a5a
+.section s9a5b
+.section s9a6a
+.section s9a6b
+.section s9a7a
+.section s9a7b
+.section s9a8a
+.section s9a8b
+.section s9a9a
+.section s9a9b
+.section s9a0a
+.section s9a0b
+.section s9baa
+.section s9bab
+.section s9bba
+.section s9bbb
+.section s9bca
+.section s9bcb
+.section s9bda
+.section s9bdb
+.section s9bea
+.section s9beb
+.section s9bfa
+.section s9bfb
+.section s9bga
+.section s9bgb
+.section s9bha
+.section s9bhb
+.section s9bia
+.section s9bib
+.section s9bja
+.section s9bjb
+.section s9bka
+.section s9bkb
+.section s9bla
+.section s9blb
+.section s9bma
+.section s9bmb
+.section s9bna
+.section s9bnb
+.section s9boa
+.section s9bob
+.section s9bpa
+.section s9bpb
+.section s9bqa
+.section s9bqb
+.section s9bra
+.section s9brb
+.section s9bsa
+.section s9bsb
+.section s9bta
+.section s9btb
+.section s9bua
+.section s9bub
+.section s9bva
+.section s9bvb
+.section s9bwa
+.section s9bwb
+.section s9bxa
+.section s9bxb
+.section s9bya
+.section s9byb
+.section s9bza
+.section s9bzb
+.section s9b1a
+.section s9b1b
+.section s9b2a
+.section s9b2b
+.section s9b3a
+.section s9b3b
+.section s9b4a
+.section s9b4b
+.section s9b5a
+.section s9b5b
+.section s9b6a
+.section s9b6b
+.section s9b7a
+.section s9b7b
+.section s9b8a
+.section s9b8b
+.section s9b9a
+.section s9b9b
+.section s9b0a
+.section s9b0b
+.section s9caa
+.section s9cab
+.section s9cba
+.section s9cbb
+.section s9cca
+.section s9ccb
+.section s9cda
+.section s9cdb
+.section s9cea
+.section s9ceb
+.section s9cfa
+.section s9cfb
+.section s9cga
+.section s9cgb
+.section s9cha
+.section s9chb
+.section s9cia
+.section s9cib
+.section s9cja
+.section s9cjb
+.section s9cka
+.section s9ckb
+.section s9cla
+.section s9clb
+.section s9cma
+.section s9cmb
+.section s9cna
+.section s9cnb
+.section s9coa
+.section s9cob
+.section s9cpa
+.section s9cpb
+.section s9cqa
+.section s9cqb
+.section s9cra
+.section s9crb
+.section s9csa
+.section s9csb
+.section s9cta
+.section s9ctb
+.section s9cua
+.section s9cub
+.section s9cva
+.section s9cvb
+.section s9cwa
+.section s9cwb
+.section s9cxa
+.section s9cxb
+.section s9cya
+.section s9cyb
+.section s9cza
+.section s9czb
+.section s9c1a
+.section s9c1b
+.section s9c2a
+.section s9c2b
+.section s9c3a
+.section s9c3b
+.section s9c4a
+.section s9c4b
+.section s9c5a
+.section s9c5b
+.section s9c6a
+.section s9c6b
+.section s9c7a
+.section s9c7b
+.section s9c8a
+.section s9c8b
+.section s9c9a
+.section s9c9b
+.section s9c0a
+.section s9c0b
+.section s9daa
+.section s9dab
+.section s9dba
+.section s9dbb
+.section s9dca
+.section s9dcb
+.section s9dda
+.section s9ddb
+.section s9dea
+.section s9deb
+.section s9dfa
+.section s9dfb
+.section s9dga
+.section s9dgb
+.section s9dha
+.section s9dhb
+.section s9dia
+.section s9dib
+.section s9dja
+.section s9djb
+.section s9dka
+.section s9dkb
+.section s9dla
+.section s9dlb
+.section s9dma
+.section s9dmb
+.section s9dna
+.section s9dnb
+.section s9doa
+.section s9dob
+.section s9dpa
+.section s9dpb
+.section s9dqa
+.section s9dqb
+.section s9dra
+.section s9drb
+.section s9dsa
+.section s9dsb
+.section s9dta
+.section s9dtb
+.section s9dua
+.section s9dub
+.section s9dva
+.section s9dvb
+.section s9dwa
+.section s9dwb
+.section s9dxa
+.section s9dxb
+.section s9dya
+.section s9dyb
+.section s9dza
+.section s9dzb
+.section s9d1a
+.section s9d1b
+.section s9d2a
+.section s9d2b
+.section s9d3a
+.section s9d3b
+.section s9d4a
+.section s9d4b
+.section s9d5a
+.section s9d5b
+.section s9d6a
+.section s9d6b
+.section s9d7a
+.section s9d7b
+.section s9d8a
+.section s9d8b
+.section s9d9a
+.section s9d9b
+.section s9d0a
+.section s9d0b
+.section s9eaa
+.section s9eab
+.section s9eba
+.section s9ebb
+.section s9eca
+.section s9ecb
+.section s9eda
+.section s9edb
+.section s9eea
+.section s9eeb
+.section s9efa
+.section s9efb
+.section s9ega
+.section s9egb
+.section s9eha
+.section s9ehb
+.section s9eia
+.section s9eib
+.section s9eja
+.section s9ejb
+.section s9eka
+.section s9ekb
+.section s9ela
+.section s9elb
+.section s9ema
+.section s9emb
+.section s9ena
+.section s9enb
+.section s9eoa
+.section s9eob
+.section s9epa
+.section s9epb
+.section s9eqa
+.section s9eqb
+.section s9era
+.section s9erb
+.section s9esa
+.section s9esb
+.section s9eta
+.section s9etb
+.section s9eua
+.section s9eub
+.section s9eva
+.section s9evb
+.section s9ewa
+.section s9ewb
+.section s9exa
+.section s9exb
+.section s9eya
+.section s9eyb
+.section s9eza
+.section s9ezb
+.section s9e1a
+.section s9e1b
+.section s9e2a
+.section s9e2b
+.section s9e3a
+.section s9e3b
+.section s9e4a
+.section s9e4b
+.section s9e5a
+.section s9e5b
+.section s9e6a
+.section s9e6b
+.section s9e7a
+.section s9e7b
+.section s9e8a
+.section s9e8b
+.section s9e9a
+.section s9e9b
+.section s9e0a
+.section s9e0b
+.section s9faa
+.section s9fab
+.section s9fba
+.section s9fbb
+.section s9fca
+.section s9fcb
+.section s9fda
+.section s9fdb
+.section s9fea
+.section s9feb
+.section s9ffa
+.section s9ffb
+.section s9fga
+.section s9fgb
+.section s9fha
+.section s9fhb
+.section s9fia
+.section s9fib
+.section s9fja
+.section s9fjb
+.section s9fka
+.section s9fkb
+.section s9fla
+.section s9flb
+.section s9fma
+.section s9fmb
+.section s9fna
+.section s9fnb
+.section s9foa
+.section s9fob
+.section s9fpa
+.section s9fpb
+.section s9fqa
+.section s9fqb
+.section s9fra
+.section s9frb
+.section s9fsa
+.section s9fsb
+.section s9fta
+.section s9ftb
+.section s9fua
+.section s9fub
+.section s9fva
+.section s9fvb
+.section s9fwa
+.section s9fwb
+.section s9fxa
+.section s9fxb
+.section s9fya
+.section s9fyb
+.section s9fza
+.section s9fzb
+.section s9f1a
+.section s9f1b
+.section s9f2a
+.section s9f2b
+.section s9f3a
+.section s9f3b
+.section s9f4a
+.section s9f4b
+.section s9f5a
+.section s9f5b
+.section s9f6a
+.section s9f6b
+.section s9f7a
+.section s9f7b
+.section s9f8a
+.section s9f8b
+.section s9f9a
+.section s9f9b
+.section s9f0a
+.section s9f0b
+.section s9gaa
+.section s9gab
+.section s9gba
+.section s9gbb
+.section s9gca
+.section s9gcb
+.section s9gda
+.section s9gdb
+.section s9gea
+.section s9geb
+.section s9gfa
+.section s9gfb
+.section s9gga
+.section s9ggb
+.section s9gha
+.section s9ghb
+.section s9gia
+.section s9gib
+.section s9gja
+.section s9gjb
+.section s9gka
+.section s9gkb
+.section s9gla
+.section s9glb
+.section s9gma
+.section s9gmb
+.section s9gna
+.section s9gnb
+.section s9goa
+.section s9gob
+.section s9gpa
+.section s9gpb
+.section s9gqa
+.section s9gqb
+.section s9gra
+.section s9grb
+.section s9gsa
+.section s9gsb
+.section s9gta
+.section s9gtb
+.section s9gua
+.section s9gub
+.section s9gva
+.section s9gvb
+.section s9gwa
+.section s9gwb
+.section s9gxa
+.section s9gxb
+.section s9gya
+.section s9gyb
+.section s9gza
+.section s9gzb
+.section s9g1a
+.section s9g1b
+.section s9g2a
+.section s9g2b
+.section s9g3a
+.section s9g3b
+.section s9g4a
+.section s9g4b
+.section s9g5a
+.section s9g5b
+.section s9g6a
+.section s9g6b
+.section s9g7a
+.section s9g7b
+.section s9g8a
+.section s9g8b
+.section s9g9a
+.section s9g9b
+.section s9g0a
+.section s9g0b
+.section s9haa
+.section s9hab
+.section s9hba
+.section s9hbb
+.section s9hca
+.section s9hcb
+.section s9hda
+.section s9hdb
+.section s9hea
+.section s9heb
+.section s9hfa
+.section s9hfb
+.section s9hga
+.section s9hgb
+.section s9hha
+.section s9hhb
+.section s9hia
+.section s9hib
+.section s9hja
+.section s9hjb
+.section s9hka
+.section s9hkb
+.section s9hla
+.section s9hlb
+.section s9hma
+.section s9hmb
+.section s9hna
+.section s9hnb
+.section s9hoa
+.section s9hob
+.section s9hpa
+.section s9hpb
+.section s9hqa
+.section s9hqb
+.section s9hra
+.section s9hrb
+.section s9hsa
+.section s9hsb
+.section s9hta
+.section s9htb
+.section s9hua
+.section s9hub
+.section s9hva
+.section s9hvb
+.section s9hwa
+.section s9hwb
+.section s9hxa
+.section s9hxb
+.section s9hya
+.section s9hyb
+.section s9hza
+.section s9hzb
+.section s9h1a
+.section s9h1b
+.section s9h2a
+.section s9h2b
+.section s9h3a
+.section s9h3b
+.section s9h4a
+.section s9h4b
+.section s9h5a
+.section s9h5b
+.section s9h6a
+.section s9h6b
+.section s9h7a
+.section s9h7b
+.section s9h8a
+.section s9h8b
+.section s9h9a
+.section s9h9b
+.section s9h0a
+.section s9h0b
+.section s9iaa
+.section s9iab
+.section s9iba
+.section s9ibb
+.section s9ica
+.section s9icb
+.section s9ida
+.section s9idb
+.section s9iea
+.section s9ieb
+.section s9ifa
+.section s9ifb
+.section s9iga
+.section s9igb
+.section s9iha
+.section s9ihb
+.section s9iia
+.section s9iib
+.section s9ija
+.section s9ijb
+.section s9ika
+.section s9ikb
+.section s9ila
+.section s9ilb
+.section s9ima
+.section s9imb
+.section s9ina
+.section s9inb
+.section s9ioa
+.section s9iob
+.section s9ipa
+.section s9ipb
+.section s9iqa
+.section s9iqb
+.section s9ira
+.section s9irb
+.section s9isa
+.section s9isb
+.section s9ita
+.section s9itb
+.section s9iua
+.section s9iub
+.section s9iva
+.section s9ivb
+.section s9iwa
+.section s9iwb
+.section s9ixa
+.section s9ixb
+.section s9iya
+.section s9iyb
+.section s9iza
+.section s9izb
+.section s9i1a
+.section s9i1b
+.section s9i2a
+.section s9i2b
+.section s9i3a
+.section s9i3b
+.section s9i4a
+.section s9i4b
+.section s9i5a
+.section s9i5b
+.section s9i6a
+.section s9i6b
+.section s9i7a
+.section s9i7b
+.section s9i8a
+.section s9i8b
+.section s9i9a
+.section s9i9b
+.section s9i0a
+.section s9i0b
+.section s9jaa
+.section s9jab
+.section s9jba
+.section s9jbb
+.section s9jca
+.section s9jcb
+.section s9jda
+.section s9jdb
+.section s9jea
+.section s9jeb
+.section s9jfa
+.section s9jfb
+.section s9jga
+.section s9jgb
+.section s9jha
+.section s9jhb
+.section s9jia
+.section s9jib
+.section s9jja
+.section s9jjb
+.section s9jka
+.section s9jkb
+.section s9jla
+.section s9jlb
+.section s9jma
+.section s9jmb
+.section s9jna
+.section s9jnb
+.section s9joa
+.section s9job
+.section s9jpa
+.section s9jpb
+.section s9jqa
+.section s9jqb
+.section s9jra
+.section s9jrb
+.section s9jsa
+.section s9jsb
+.section s9jta
+.section s9jtb
+.section s9jua
+.section s9jub
+.section s9jva
+.section s9jvb
+.section s9jwa
+.section s9jwb
+.section s9jxa
+.section s9jxb
+.section s9jya
+.section s9jyb
+.section s9jza
+.section s9jzb
+.section s9j1a
+.section s9j1b
+.section s9j2a
+.section s9j2b
+.section s9j3a
+.section s9j3b
+.section s9j4a
+.section s9j4b
+.section s9j5a
+.section s9j5b
+.section s9j6a
+.section s9j6b
+.section s9j7a
+.section s9j7b
+.section s9j8a
+.section s9j8b
+.section s9j9a
+.section s9j9b
+.section s9j0a
+.section s9j0b
+.section s9kaa
+.section s9kab
+.section s9kba
+.section s9kbb
+.section s9kca
+.section s9kcb
+.section s9kda
+.section s9kdb
+.section s9kea
+.section s9keb
+.section s9kfa
+.section s9kfb
+.section s9kga
+.section s9kgb
+.section s9kha
+.section s9khb
+.section s9kia
+.section s9kib
+.section s9kja
+.section s9kjb
+.section s9kka
+.section s9kkb
+.section s9kla
+.section s9klb
+.section s9kma
+.section s9kmb
+.section s9kna
+.section s9knb
+.section s9koa
+.section s9kob
+.section s9kpa
+.section s9kpb
+.section s9kqa
+.section s9kqb
+.section s9kra
+.section s9krb
+.section s9ksa
+.section s9ksb
+.section s9kta
+.section s9ktb
+.section s9kua
+.section s9kub
+.section s9kva
+.section s9kvb
+.section s9kwa
+.section s9kwb
+.section s9kxa
+.section s9kxb
+.section s9kya
+.section s9kyb
+.section s9kza
+.section s9kzb
+.section s9k1a
+.section s9k1b
+.section s9k2a
+.section s9k2b
+.section s9k3a
+.section s9k3b
+.section s9k4a
+.section s9k4b
+.section s9k5a
+.section s9k5b
+.section s9k6a
+.section s9k6b
+.section s9k7a
+.section s9k7b
+.section s9k8a
+.section s9k8b
+.section s9k9a
+.section s9k9b
+.section s9k0a
+.section s9k0b
+.section s9laa
+.section s9lab
+.section s9lba
+.section s9lbb
+.section s9lca
+.section s9lcb
+.section s9lda
+.section s9ldb
+.section s9lea
+.section s9leb
+.section s9lfa
+.section s9lfb
+.section s9lga
+.section s9lgb
+.section s9lha
+.section s9lhb
+.section s9lia
+.section s9lib
+.section s9lja
+.section s9ljb
+.section s9lka
+.section s9lkb
+.section s9lla
+.section s9llb
+.section s9lma
+.section s9lmb
+.section s9lna
+.section s9lnb
+.section s9loa
+.section s9lob
+.section s9lpa
+.section s9lpb
+.section s9lqa
+.section s9lqb
+.section s9lra
+.section s9lrb
+.section s9lsa
+.section s9lsb
+.section s9lta
+.section s9ltb
+.section s9lua
+.section s9lub
+.section s9lva
+.section s9lvb
+.section s9lwa
+.section s9lwb
+.section s9lxa
+.section s9lxb
+.section s9lya
+.section s9lyb
+.section s9lza
+.section s9lzb
+.section s9l1a
+.section s9l1b
+.section s9l2a
+.section s9l2b
+.section s9l3a
+.section s9l3b
+.section s9l4a
+.section s9l4b
+.section s9l5a
+.section s9l5b
+.section s9l6a
+.section s9l6b
+.section s9l7a
+.section s9l7b
+.section s9l8a
+.section s9l8b
+.section s9l9a
+.section s9l9b
+.section s9l0a
+.section s9l0b
+.section s9maa
+.section s9mab
+.section s9mba
+.section s9mbb
+.section s9mca
+.section s9mcb
+.section s9mda
+.section s9mdb
+.section s9mea
+.section s9meb
+.section s9mfa
+.section s9mfb
+.section s9mga
+.section s9mgb
+.section s9mha
+.section s9mhb
+.section s9mia
+.section s9mib
+.section s9mja
+.section s9mjb
+.section s9mka
+.section s9mkb
+.section s9mla
+.section s9mlb
+.section s9mma
+.section s9mmb
+.section s9mna
+.section s9mnb
+.section s9moa
+.section s9mob
+.section s9mpa
+.section s9mpb
+.section s9mqa
+.section s9mqb
+.section s9mra
+.section s9mrb
+.section s9msa
+.section s9msb
+.section s9mta
+.section s9mtb
+.section s9mua
+.section s9mub
+.section s9mva
+.section s9mvb
+.section s9mwa
+.section s9mwb
+.section s9mxa
+.section s9mxb
+.section s9mya
+.section s9myb
+.section s9mza
+.section s9mzb
+.section s9m1a
+.section s9m1b
+.section s9m2a
+.section s9m2b
+.section s9m3a
+.section s9m3b
+.section s9m4a
+.section s9m4b
+.section s9m5a
+.section s9m5b
+.section s9m6a
+.section s9m6b
+.section s9m7a
+.section s9m7b
+.section s9m8a
+.section s9m8b
+.section s9m9a
+.section s9m9b
+.section s9m0a
+.section s9m0b
+.section s9naa
+.section s9nab
+.section s9nba
+.section s9nbb
+.section s9nca
+.section s9ncb
+.section s9nda
+.section s9ndb
+.section s9nea
+.section s9neb
+.section s9nfa
+.section s9nfb
+.section s9nga
+.section s9ngb
+.section s9nha
+.section s9nhb
+.section s9nia
+.section s9nib
+.section s9nja
+.section s9njb
+.section s9nka
+.section s9nkb
+.section s9nla
+.section s9nlb
+.section s9nma
+.section s9nmb
+.section s9nna
+.section s9nnb
+.section s9noa
+.section s9nob
+.section s9npa
+.section s9npb
+.section s9nqa
+.section s9nqb
+.section s9nra
+.section s9nrb
+.section s9nsa
+.section s9nsb
+.section s9nta
+.section s9ntb
+.section s9nua
+.section s9nub
+.section s9nva
+.section s9nvb
+.section s9nwa
+.section s9nwb
+.section s9nxa
+.section s9nxb
+.section s9nya
+.section s9nyb
+.section s9nza
+.section s9nzb
+.section s9n1a
+.section s9n1b
+.section s9n2a
+.section s9n2b
+.section s9n3a
+.section s9n3b
+.section s9n4a
+.section s9n4b
+.section s9n5a
+.section s9n5b
+.section s9n6a
+.section s9n6b
+.section s9n7a
+.section s9n7b
+.section s9n8a
+.section s9n8b
+.section s9n9a
+.section s9n9b
+.section s9n0a
+.section s9n0b
+.section s9oaa
+.section s9oab
+.section s9oba
+.section s9obb
+.section s9oca
+.section s9ocb
+.section s9oda
+.section s9odb
+.section s9oea
+.section s9oeb
+.section s9ofa
+.section s9ofb
+.section s9oga
+.section s9ogb
+.section s9oha
+.section s9ohb
+.section s9oia
+.section s9oib
+.section s9oja
+.section s9ojb
+.section s9oka
+.section s9okb
+.section s9ola
+.section s9olb
+.section s9oma
+.section s9omb
+.section s9ona
+.section s9onb
+.section s9ooa
+.section s9oob
+.section s9opa
+.section s9opb
+.section s9oqa
+.section s9oqb
+.section s9ora
+.section s9orb
+.section s9osa
+.section s9osb
+.section s9ota
+.section s9otb
+.section s9oua
+.section s9oub
+.section s9ova
+.section s9ovb
+.section s9owa
+.section s9owb
+.section s9oxa
+.section s9oxb
+.section s9oya
+.section s9oyb
+.section s9oza
+.section s9ozb
+.section s9o1a
+.section s9o1b
+.section s9o2a
+.section s9o2b
+.section s9o3a
+.section s9o3b
+.section s9o4a
+.section s9o4b
+.section s9o5a
+.section s9o5b
+.section s9o6a
+.section s9o6b
+.section s9o7a
+.section s9o7b
+.section s9o8a
+.section s9o8b
+.section s9o9a
+.section s9o9b
+.section s9o0a
+.section s9o0b
+.section s9paa
+.section s9pab
+.section s9pba
+.section s9pbb
+.section s9pca
+.section s9pcb
+.section s9pda
+.section s9pdb
+.section s9pea
+.section s9peb
+.section s9pfa
+.section s9pfb
+.section s9pga
+.section s9pgb
+.section s9pha
+.section s9phb
+.section s9pia
+.section s9pib
+.section s9pja
+.section s9pjb
+.section s9pka
+.section s9pkb
+.section s9pla
+.section s9plb
+.section s9pma
+.section s9pmb
+.section s9pna
+.section s9pnb
+.section s9poa
+.section s9pob
+.section s9ppa
+.section s9ppb
+.section s9pqa
+.section s9pqb
+.section s9pra
+.section s9prb
+.section s9psa
+.section s9psb
+.section s9pta
+.section s9ptb
+.section s9pua
+.section s9pub
+.section s9pva
+.section s9pvb
+.section s9pwa
+.section s9pwb
+.section s9pxa
+.section s9pxb
+.section s9pya
+.section s9pyb
+.section s9pza
+.section s9pzb
+.section s9p1a
+.section s9p1b
+.section s9p2a
+.section s9p2b
+.section s9p3a
+.section s9p3b
+.section s9p4a
+.section s9p4b
+.section s9p5a
+.section s9p5b
+.section s9p6a
+.section s9p6b
+.section s9p7a
+.section s9p7b
+.section s9p8a
+.section s9p8b
+.section s9p9a
+.section s9p9b
+.section s9p0a
+.section s9p0b
+.section s9qaa
+.section s9qab
+.section s9qba
+.section s9qbb
+.section s9qca
+.section s9qcb
+.section s9qda
+.section s9qdb
+.section s9qea
+.section s9qeb
+.section s9qfa
+.section s9qfb
+.section s9qga
+.section s9qgb
+.section s9qha
+.section s9qhb
+.section s9qia
+.section s9qib
+.section s9qja
+.section s9qjb
+.section s9qka
+.section s9qkb
+.section s9qla
+.section s9qlb
+.section s9qma
+.section s9qmb
+.section s9qna
+.section s9qnb
+.section s9qoa
+.section s9qob
+.section s9qpa
+.section s9qpb
+.section s9qqa
+.section s9qqb
+.section s9qra
+.section s9qrb
+.section s9qsa
+.section s9qsb
+.section s9qta
+.section s9qtb
+.section s9qua
+.section s9qub
+.section s9qva
+.section s9qvb
+.section s9qwa
+.section s9qwb
+.section s9qxa
+.section s9qxb
+.section s9qya
+.section s9qyb
+.section s9qza
+.section s9qzb
+.section s9q1a
+.section s9q1b
+.section s9q2a
+.section s9q2b
+.section s9q3a
+.section s9q3b
+.section s9q4a
+.section s9q4b
+.section s9q5a
+.section s9q5b
+.section s9q6a
+.section s9q6b
+.section s9q7a
+.section s9q7b
+.section s9q8a
+.section s9q8b
+.section s9q9a
+.section s9q9b
+.section s9q0a
+.section s9q0b
+.section s9raa
+.section s9rab
+.section s9rba
+.section s9rbb
+.section s9rca
+.section s9rcb
+.section s9rda
+.section s9rdb
+.section s9rea
+.section s9reb
+.section s9rfa
+.section s9rfb
+.section s9rga
+.section s9rgb
+.section s9rha
+.section s9rhb
+.section s9ria
+.section s9rib
+.section s9rja
+.section s9rjb
+.section s9rka
+.section s9rkb
+.section s9rla
+.section s9rlb
+.section s9rma
+.section s9rmb
+.section s9rna
+.section s9rnb
+.section s9roa
+.section s9rob
+.section s9rpa
+.section s9rpb
+.section s9rqa
+.section s9rqb
+.section s9rra
+.section s9rrb
+.section s9rsa
+.section s9rsb
+.section s9rta
+.section s9rtb
+.section s9rua
+.section s9rub
+.section s9rva
+.section s9rvb
+.section s9rwa
+.section s9rwb
+.section s9rxa
+.section s9rxb
+.section s9rya
+.section s9ryb
+.section s9rza
+.section s9rzb
+.section s9r1a
+.section s9r1b
+.section s9r2a
+.section s9r2b
+.section s9r3a
+.section s9r3b
+.section s9r4a
+.section s9r4b
+.section s9r5a
+.section s9r5b
+.section s9r6a
+.section s9r6b
+.section s9r7a
+.section s9r7b
+.section s9r8a
+.section s9r8b
+.section s9r9a
+.section s9r9b
+.section s9r0a
+.section s9r0b
+.section s9saa
+.section s9sab
+.section s9sba
+.section s9sbb
+.section s9sca
+.section s9scb
+.section s9sda
+.section s9sdb
+.section s9sea
+.section s9seb
+.section s9sfa
+.section s9sfb
+.section s9sga
+.section s9sgb
+.section s9sha
+.section s9shb
+.section s9sia
+.section s9sib
+.section s9sja
+.section s9sjb
+.section s9ska
+.section s9skb
+.section s9sla
+.section s9slb
+.section s9sma
+.section s9smb
+.section s9sna
+.section s9snb
+.section s9soa
+.section s9sob
+.section s9spa
+.section s9spb
+.section s9sqa
+.section s9sqb
+.section s9sra
+.section s9srb
+.section s9ssa
+.section s9ssb
+.section s9sta
+.section s9stb
+.section s9sua
+.section s9sub
+.section s9sva
+.section s9svb
+.section s9swa
+.section s9swb
+.section s9sxa
+.section s9sxb
+.section s9sya
+.section s9syb
+.section s9sza
+.section s9szb
+.section s9s1a
+.section s9s1b
+.section s9s2a
+.section s9s2b
+.section s9s3a
+.section s9s3b
+.section s9s4a
+.section s9s4b
+.section s9s5a
+.section s9s5b
+.section s9s6a
+.section s9s6b
+.section s9s7a
+.section s9s7b
+.section s9s8a
+.section s9s8b
+.section s9s9a
+.section s9s9b
+.section s9s0a
+.section s9s0b
+.section s9taa
+.section s9tab
+.section s9tba
+.section s9tbb
+.section s9tca
+.section s9tcb
+.section s9tda
+.section s9tdb
+.section s9tea
+.section s9teb
+.section s9tfa
+.section s9tfb
+.section s9tga
+.section s9tgb
+.section s9tha
+.section s9thb
+.section s9tia
+.section s9tib
+.section s9tja
+.section s9tjb
+.section s9tka
+.section s9tkb
+.section s9tla
+.section s9tlb
+.section s9tma
+.section s9tmb
+.section s9tna
+.section s9tnb
+.section s9toa
+.section s9tob
+.section s9tpa
+.section s9tpb
+.section s9tqa
+.section s9tqb
+.section s9tra
+.section s9trb
+.section s9tsa
+.section s9tsb
+.section s9tta
+.section s9ttb
+.section s9tua
+.section s9tub
+.section s9tva
+.section s9tvb
+.section s9twa
+.section s9twb
+.section s9txa
+.section s9txb
+.section s9tya
+.section s9tyb
+.section s9tza
+.section s9tzb
+.section s9t1a
+.section s9t1b
+.section s9t2a
+.section s9t2b
+.section s9t3a
+.section s9t3b
+.section s9t4a
+.section s9t4b
+.section s9t5a
+.section s9t5b
+.section s9t6a
+.section s9t6b
+.section s9t7a
+.section s9t7b
+.section s9t8a
+.section s9t8b
+.section s9t9a
+.section s9t9b
+.section s9t0a
+.section s9t0b
+.section s9uaa
+.section s9uab
+.section s9uba
+.section s9ubb
+.section s9uca
+.section s9ucb
+.section s9uda
+.section s9udb
+.section s9uea
+.section s9ueb
+.section s9ufa
+.section s9ufb
+.section s9uga
+.section s9ugb
+.section s9uha
+.section s9uhb
+.section s9uia
+.section s9uib
+.section s9uja
+.section s9ujb
+.section s9uka
+.section s9ukb
+.section s9ula
+.section s9ulb
+.section s9uma
+.section s9umb
+.section s9una
+.section s9unb
+.section s9uoa
+.section s9uob
+.section s9upa
+.section s9upb
+.section s9uqa
+.section s9uqb
+.section s9ura
+.section s9urb
+.section s9usa
+.section s9usb
+.section s9uta
+.section s9utb
+.section s9uua
+.section s9uub
+.section s9uva
+.section s9uvb
+.section s9uwa
+.section s9uwb
+.section s9uxa
+.section s9uxb
+.section s9uya
+.section s9uyb
+.section s9uza
+.section s9uzb
+.section s9u1a
+.section s9u1b
+.section s9u2a
+.section s9u2b
+.section s9u3a
+.section s9u3b
+.section s9u4a
+.section s9u4b
+.section s9u5a
+.section s9u5b
+.section s9u6a
+.section s9u6b
+.section s9u7a
+.section s9u7b
+.section s9u8a
+.section s9u8b
+.section s9u9a
+.section s9u9b
+.section s9u0a
+.section s9u0b
+.section s9vaa
+.section s9vab
+.section s9vba
+.section s9vbb
+.section s9vca
+.section s9vcb
+.section s9vda
+.section s9vdb
+.section s9vea
+.section s9veb
+.section s9vfa
+.section s9vfb
+.section s9vga
+.section s9vgb
+.section s9vha
+.section s9vhb
+.section s9via
+.section s9vib
+.section s9vja
+.section s9vjb
+.section s9vka
+.section s9vkb
+.section s9vla
+.section s9vlb
+.section s9vma
+.section s9vmb
+.section s9vna
+.section s9vnb
+.section s9voa
+.section s9vob
+.section s9vpa
+.section s9vpb
+.section s9vqa
+.section s9vqb
+.section s9vra
+.section s9vrb
+.section s9vsa
+.section s9vsb
+.section s9vta
+.section s9vtb
+.section s9vua
+.section s9vub
+.section s9vva
+.section s9vvb
+.section s9vwa
+.section s9vwb
+.section s9vxa
+.section s9vxb
+.section s9vya
+.section s9vyb
+.section s9vza
+.section s9vzb
+.section s9v1a
+.section s9v1b
+.section s9v2a
+.section s9v2b
+.section s9v3a
+.section s9v3b
+.section s9v4a
+.section s9v4b
+.section s9v5a
+.section s9v5b
+.section s9v6a
+.section s9v6b
+.section s9v7a
+.section s9v7b
+.section s9v8a
+.section s9v8b
+.section s9v9a
+.section s9v9b
+.section s9v0a
+.section s9v0b
+.section s9waa
+.section s9wab
+.section s9wba
+.section s9wbb
+.section s9wca
+.section s9wcb
+.section s9wda
+.section s9wdb
+.section s9wea
+.section s9web
+.section s9wfa
+.section s9wfb
+.section s9wga
+.section s9wgb
+.section s9wha
+.section s9whb
+.section s9wia
+.section s9wib
+.section s9wja
+.section s9wjb
+.section s9wka
+.section s9wkb
+.section s9wla
+.section s9wlb
+.section s9wma
+.section s9wmb
+.section s9wna
+.section s9wnb
+.section s9woa
+.section s9wob
+.section s9wpa
+.section s9wpb
+.section s9wqa
+.section s9wqb
+.section s9wra
+.section s9wrb
+.section s9wsa
+.section s9wsb
+.section s9wta
+.section s9wtb
+.section s9wua
+.section s9wub
+.section s9wva
+.section s9wvb
+.section s9wwa
+.section s9wwb
+.section s9wxa
+.section s9wxb
+.section s9wya
+.section s9wyb
+.section s9wza
+.section s9wzb
+.section s9w1a
+.section s9w1b
+.section s9w2a
+.section s9w2b
+.section s9w3a
+.section s9w3b
+.section s9w4a
+.section s9w4b
+.section s9w5a
+.section s9w5b
+.section s9w6a
+.section s9w6b
+.section s9w7a
+.section s9w7b
+.section s9w8a
+.section s9w8b
+.section s9w9a
+.section s9w9b
+.section s9w0a
+.section s9w0b
+.section s9xaa
+.section s9xab
+.section s9xba
+.section s9xbb
+.section s9xca
+.section s9xcb
+.section s9xda
+.section s9xdb
+.section s9xea
+.section s9xeb
+.section s9xfa
+.section s9xfb
+.section s9xga
+.section s9xgb
+.section s9xha
+.section s9xhb
+.section s9xia
+.section s9xib
+.section s9xja
+.section s9xjb
+.section s9xka
+.section s9xkb
+.section s9xla
+.section s9xlb
+.section s9xma
+.section s9xmb
+.section s9xna
+.section s9xnb
+.section s9xoa
+.section s9xob
+.section s9xpa
+.section s9xpb
+.section s9xqa
+.section s9xqb
+.section s9xra
+.section s9xrb
+.section s9xsa
+.section s9xsb
+.section s9xta
+.section s9xtb
+.section s9xua
+.section s9xub
+.section s9xva
+.section s9xvb
+.section s9xwa
+.section s9xwb
+.section s9xxa
+.section s9xxb
+.section s9xya
+.section s9xyb
+.section s9xza
+.section s9xzb
+.section s9x1a
+.section s9x1b
+.section s9x2a
+.section s9x2b
+.section s9x3a
+.section s9x3b
+.section s9x4a
+.section s9x4b
+.section s9x5a
+.section s9x5b
+.section s9x6a
+.section s9x6b
+.section s9x7a
+.section s9x7b
+.section s9x8a
+.section s9x8b
+.section s9x9a
+.section s9x9b
+.section s9x0a
+.section s9x0b
+.section s9yaa
+.section s9yab
+.section s9yba
+.section s9ybb
+.section s9yca
+.section s9ycb
+.section s9yda
+.section s9ydb
+.section s9yea
+.section s9yeb
+.section s9yfa
+.section s9yfb
+.section s9yga
+.section s9ygb
+.section s9yha
+.section s9yhb
+.section s9yia
+.section s9yib
+.section s9yja
+.section s9yjb
+.section s9yka
+.section s9ykb
+.section s9yla
+.section s9ylb
+.section s9yma
+.section s9ymb
+.section s9yna
+.section s9ynb
+.section s9yoa
+.section s9yob
+.section s9ypa
+.section s9ypb
+.section s9yqa
+.section s9yqb
+.section s9yra
+.section s9yrb
+.section s9ysa
+.section s9ysb
+.section s9yta
+.section s9ytb
+.section s9yua
+.section s9yub
+.section s9yva
+.section s9yvb
+.section s9ywa
+.section s9ywb
+.section s9yxa
+.section s9yxb
+.section s9yya
+.section s9yyb
+.section s9yza
+.section s9yzb
+.section s9y1a
+.section s9y1b
+.section s9y2a
+.section s9y2b
+.section s9y3a
+.section s9y3b
+.section s9y4a
+.section s9y4b
+.section s9y5a
+.section s9y5b
+.section s9y6a
+.section s9y6b
+.section s9y7a
+.section s9y7b
+.section s9y8a
+.section s9y8b
+.section s9y9a
+.section s9y9b
+.section s9y0a
+.section s9y0b
+.section s9zaa
+.section s9zab
+.section s9zba
+.section s9zbb
+.section s9zca
+.section s9zcb
+.section s9zda
+.section s9zdb
+.section s9zea
+.section s9zeb
+.section s9zfa
+.section s9zfb
+.section s9zga
+.section s9zgb
+.section s9zha
+.section s9zhb
+.section s9zia
+.section s9zib
+.section s9zja
+.section s9zjb
+.section s9zka
+.section s9zkb
+.section s9zla
+.section s9zlb
+.section s9zma
+.section s9zmb
+.section s9zna
+.section s9znb
+.section s9zoa
+.section s9zob
+.section s9zpa
+.section s9zpb
+.section s9zqa
+.section s9zqb
+.section s9zra
+.section s9zrb
+.section s9zsa
+.section s9zsb
+.section s9zta
+.section s9ztb
+.section s9zua
+.section s9zub
+.section s9zva
+.section s9zvb
+.section s9zwa
+.section s9zwb
+.section s9zxa
+.section s9zxb
+.section s9zya
+.section s9zyb
+.section s9zza
+.section s9zzb
+.section s9z1a
+.section s9z1b
+.section s9z2a
+.section s9z2b
+.section s9z3a
+.section s9z3b
+.section s9z4a
+.section s9z4b
+.section s9z5a
+.section s9z5b
+.section s9z6a
+.section s9z6b
+.section s9z7a
+.section s9z7b
+.section s9z8a
+.section s9z8b
+.section s9z9a
+.section s9z9b
+.section s9z0a
+.section s9z0b
+.section s91aa
+.section s91ab
+.section s91ba
+.section s91bb
+.section s91ca
+.section s91cb
+.section s91da
+.section s91db
+.section s91ea
+.section s91eb
+.section s91fa
+.section s91fb
+.section s91ga
+.section s91gb
+.section s91ha
+.section s91hb
+.section s91ia
+.section s91ib
+.section s91ja
+.section s91jb
+.section s91ka
+.section s91kb
+.section s91la
+.section s91lb
+.section s91ma
+.section s91mb
+.section s91na
+.section s91nb
+.section s91oa
+.section s91ob
+.section s91pa
+.section s91pb
+.section s91qa
+.section s91qb
+.section s91ra
+.section s91rb
+.section s91sa
+.section s91sb
+.section s91ta
+.section s91tb
+.section s91ua
+.section s91ub
+.section s91va
+.section s91vb
+.section s91wa
+.section s91wb
+.section s91xa
+.section s91xb
+.section s91ya
+.section s91yb
+.section s91za
+.section s91zb
+.section s911a
+.section s911b
+.section s912a
+.section s912b
+.section s913a
+.section s913b
+.section s914a
+.section s914b
+.section s915a
+.section s915b
+.section s916a
+.section s916b
+.section s917a
+.section s917b
+.section s918a
+.section s918b
+.section s919a
+.section s919b
+.section s910a
+.section s910b
+.section s92aa
+.section s92ab
+.section s92ba
+.section s92bb
+.section s92ca
+.section s92cb
+.section s92da
+.section s92db
+.section s92ea
+.section s92eb
+.section s92fa
+.section s92fb
+.section s92ga
+.section s92gb
+.section s92ha
+.section s92hb
+.section s92ia
+.section s92ib
+.section s92ja
+.section s92jb
+.section s92ka
+.section s92kb
+.section s92la
+.section s92lb
+.section s92ma
+.section s92mb
+.section s92na
+.section s92nb
+.section s92oa
+.section s92ob
+.section s92pa
+.section s92pb
+.section s92qa
+.section s92qb
+.section s92ra
+.section s92rb
+.section s92sa
+.section s92sb
+.section s92ta
+.section s92tb
+.section s92ua
+.section s92ub
+.section s92va
+.section s92vb
+.section s92wa
+.section s92wb
+.section s92xa
+.section s92xb
+.section s92ya
+.section s92yb
+.section s92za
+.section s92zb
+.section s921a
+.section s921b
+.section s922a
+.section s922b
+.section s923a
+.section s923b
+.section s924a
+.section s924b
+.section s925a
+.section s925b
+.section s926a
+.section s926b
+.section s927a
+.section s927b
+.section s928a
+.section s928b
+.section s929a
+.section s929b
+.section s920a
+.section s920b
+.section s93aa
+.section s93ab
+.section s93ba
+.section s93bb
+.section s93ca
+.section s93cb
+.section s93da
+.section s93db
+.section s93ea
+.section s93eb
+.section s93fa
+.section s93fb
+.section s93ga
+.section s93gb
+.section s93ha
+.section s93hb
+.section s93ia
+.section s93ib
+.section s93ja
+.section s93jb
+.section s93ka
+.section s93kb
+.section s93la
+.section s93lb
+.section s93ma
+.section s93mb
+.section s93na
+.section s93nb
+.section s93oa
+.section s93ob
+.section s93pa
+.section s93pb
+.section s93qa
+.section s93qb
+.section s93ra
+.section s93rb
+.section s93sa
+.section s93sb
+.section s93ta
+.section s93tb
+.section s93ua
+.section s93ub
+.section s93va
+.section s93vb
+.section s93wa
+.section s93wb
+.section s93xa
+.section s93xb
+.section s93ya
+.section s93yb
+.section s93za
+.section s93zb
+.section s931a
+.section s931b
+.section s932a
+.section s932b
+.section s933a
+.section s933b
+.section s934a
+.section s934b
+.section s935a
+.section s935b
+.section s936a
+.section s936b
+.section s937a
+.section s937b
+.section s938a
+.section s938b
+.section s939a
+.section s939b
+.section s930a
+.section s930b
+.section s94aa
+.section s94ab
+.section s94ba
+.section s94bb
+.section s94ca
+.section s94cb
+.section s94da
+.section s94db
+.section s94ea
+.section s94eb
+.section s94fa
+.section s94fb
+.section s94ga
+.section s94gb
+.section s94ha
+.section s94hb
+.section s94ia
+.section s94ib
+.section s94ja
+.section s94jb
+.section s94ka
+.section s94kb
+.section s94la
+.section s94lb
+.section s94ma
+.section s94mb
+.section s94na
+.section s94nb
+.section s94oa
+.section s94ob
+.section s94pa
+.section s94pb
+.section s94qa
+.section s94qb
+.section s94ra
+.section s94rb
+.section s94sa
+.section s94sb
+.section s94ta
+.section s94tb
+.section s94ua
+.section s94ub
+.section s94va
+.section s94vb
+.section s94wa
+.section s94wb
+.section s94xa
+.section s94xb
+.section s94ya
+.section s94yb
+.section s94za
+.section s94zb
+.section s941a
+.section s941b
+.section s942a
+.section s942b
+.section s943a
+.section s943b
+.section s944a
+.section s944b
+.section s945a
+.section s945b
+.section s946a
+.section s946b
+.section s947a
+.section s947b
+.section s948a
+.section s948b
+.section s949a
+.section s949b
+.section s940a
+.section s940b
+.section s95aa
+.section s95ab
+.section s95ba
+.section s95bb
+.section s95ca
+.section s95cb
+.section s95da
+.section s95db
+.section s95ea
+.section s95eb
+.section s95fa
+.section s95fb
+.section s95ga
+.section s95gb
+.section s95ha
+.section s95hb
+.section s95ia
+.section s95ib
+.section s95ja
+.section s95jb
+.section s95ka
+.section s95kb
+.section s95la
+.section s95lb
+.section s95ma
+.section s95mb
+.section s95na
+.section s95nb
+.section s95oa
+.section s95ob
+.section s95pa
+.section s95pb
+.section s95qa
+.section s95qb
+.section s95ra
+.section s95rb
+.section s95sa
+.section s95sb
+.section s95ta
+.section s95tb
+.section s95ua
+.section s95ub
+.section s95va
+.section s95vb
+.section s95wa
+.section s95wb
+.section s95xa
+.section s95xb
+.section s95ya
+.section s95yb
+.section s95za
+.section s95zb
+.section s951a
+.section s951b
+.section s952a
+.section s952b
+.section s953a
+.section s953b
+.section s954a
+.section s954b
+.section s955a
+.section s955b
+.section s956a
+.section s956b
+.section s957a
+.section s957b
+.section s958a
+.section s958b
+.section s959a
+.section s959b
+.section s950a
+.section s950b
+.section s96aa
+.section s96ab
+.section s96ba
+.section s96bb
+.section s96ca
+.section s96cb
+.section s96da
+.section s96db
+.section s96ea
+.section s96eb
+.section s96fa
+.section s96fb
+.section s96ga
+.section s96gb
+.section s96ha
+.section s96hb
+.section s96ia
+.section s96ib
+.section s96ja
+.section s96jb
+.section s96ka
+.section s96kb
+.section s96la
+.section s96lb
+.section s96ma
+.section s96mb
+.section s96na
+.section s96nb
+.section s96oa
+.section s96ob
+.section s96pa
+.section s96pb
+.section s96qa
+.section s96qb
+.section s96ra
+.section s96rb
+.section s96sa
+.section s96sb
+.section s96ta
+.section s96tb
+.section s96ua
+.section s96ub
+.section s96va
+.section s96vb
+.section s96wa
+.section s96wb
+.section s96xa
+.section s96xb
+.section s96ya
+.section s96yb
+.section s96za
+.section s96zb
+.section s961a
+.section s961b
+.section s962a
+.section s962b
+.section s963a
+.section s963b
+.section s964a
+.section s964b
+.section s965a
+.section s965b
+.section s966a
+.section s966b
+.section s967a
+.section s967b
+.section s968a
+.section s968b
+.section s969a
+.section s969b
+.section s960a
+.section s960b
+.section s97aa
+.section s97ab
+.section s97ba
+.section s97bb
+.section s97ca
+.section s97cb
+.section s97da
+.section s97db
+.section s97ea
+.section s97eb
+.section s97fa
+.section s97fb
+.section s97ga
+.section s97gb
+.section s97ha
+.section s97hb
+.section s97ia
+.section s97ib
+.section s97ja
+.section s97jb
+.section s97ka
+.section s97kb
+.section s97la
+.section s97lb
+.section s97ma
+.section s97mb
+.section s97na
+.section s97nb
+.section s97oa
+.section s97ob
+.section s97pa
+.section s97pb
+.section s97qa
+.section s97qb
+.section s97ra
+.section s97rb
+.section s97sa
+.section s97sb
+.section s97ta
+.section s97tb
+.section s97ua
+.section s97ub
+.section s97va
+.section s97vb
+.section s97wa
+.section s97wb
+.section s97xa
+.section s97xb
+.section s97ya
+.section s97yb
+.section s97za
+.section s97zb
+.section s971a
+.section s971b
+.section s972a
+.section s972b
+.section s973a
+.section s973b
+.section s974a
+.section s974b
+.section s975a
+.section s975b
+.section s976a
+.section s976b
+.section s977a
+.section s977b
+.section s978a
+.section s978b
+.section s979a
+.section s979b
+.section s970a
+.section s970b
+.section s98aa
+.section s98ab
+.section s98ba
+.section s98bb
+.section s98ca
+.section s98cb
+.section s98da
+.section s98db
+.section s98ea
+.section s98eb
+.section s98fa
+.section s98fb
+.section s98ga
+.section s98gb
+.section s98ha
+.section s98hb
+.section s98ia
+.section s98ib
+.section s98ja
+.section s98jb
+.section s98ka
+.section s98kb
+.section s98la
+.section s98lb
+.section s98ma
+.section s98mb
+.section s98na
+.section s98nb
+.section s98oa
+.section s98ob
+.section s98pa
+.section s98pb
+.section s98qa
+.section s98qb
+.section s98ra
+.section s98rb
+.section s98sa
+.section s98sb
+.section s98ta
+.section s98tb
+.section s98ua
+.section s98ub
+.section s98va
+.section s98vb
+.section s98wa
+.section s98wb
+.section s98xa
+.section s98xb
+.section s98ya
+.section s98yb
+.section s98za
+.section s98zb
+.section s981a
+.section s981b
+.section s982a
+.section s982b
+.section s983a
+.section s983b
+.section s984a
+.section s984b
+.section s985a
+.section s985b
+.section s986a
+.section s986b
+.section s987a
+.section s987b
+.section s988a
+.section s988b
+.section s989a
+.section s989b
+.section s980a
+.section s980b
+.section s99aa
+.section s99ab
+.section s99ba
+.section s99bb
+.section s99ca
+.section s99cb
+.section s99da
+.section s99db
+.section s99ea
+.section s99eb
+.section s99fa
+.section s99fb
+.section s99ga
+.section s99gb
+.section s99ha
+.section s99hb
+.section s99ia
+.section s99ib
+.section s99ja
+.section s99jb
+.section s99ka
+.section s99kb
+.section s99la
+.section s99lb
+.section s99ma
+.section s99mb
+.section s99na
+.section s99nb
+.section s99oa
+.section s99ob
+.section s99pa
+.section s99pb
+.section s99qa
+.section s99qb
+.section s99ra
+.section s99rb
+.section s99sa
+.section s99sb
+.section s99ta
+.section s99tb
+.section s99ua
+.section s99ub
+.section s99va
+.section s99vb
+.section s99wa
+.section s99wb
+.section s99xa
+.section s99xb
+.section s99ya
+.section s99yb
+.section s99za
+.section s99zb
+.section s991a
+.section s991b
+.section s992a
+.section s992b
+.section s993a
+.section s993b
+.section s994a
+.section s994b
+.section s995a
+.section s995b
+.section s996a
+.section s996b
+.section s997a
+.section s997b
+.section s998a
+.section s998b
+.section s999a
+.section s999b
+.section s990a
+.section s990b
+.section s90aa
+.section s90ab
+.section s90ba
+.section s90bb
+.section s90ca
+.section s90cb
+.section s90da
+.section s90db
+.section s90ea
+.section s90eb
+.section s90fa
+.section s90fb
+.section s90ga
+.section s90gb
+.section s90ha
+.section s90hb
+.section s90ia
+.section s90ib
+.section s90ja
+.section s90jb
+.section s90ka
+.section s90kb
+.section s90la
+.section s90lb
+.section s90ma
+.section s90mb
+.section s90na
+.section s90nb
+.section s90oa
+.section s90ob
+.section s90pa
+.section s90pb
+.section s90qa
+.section s90qb
+.section s90ra
+.section s90rb
+.section s90sa
+.section s90sb
+.section s90ta
+.section s90tb
+.section s90ua
+.section s90ub
+.section s90va
+.section s90vb
+.section s90wa
+.section s90wb
+.section s90xa
+.section s90xb
+.section s90ya
+.section s90yb
+.section s90za
+.section s90zb
+.section s901a
+.section s901b
+.section s902a
+.section s902b
+.section s903a
+.section s903b
+.section s904a
+.section s904b
+.section s905a
+.section s905b
+.section s906a
+.section s906b
+.section s907a
+.section s907b
+.section s908a
+.section s908b
+.section s909a
+.section s909b
+.section s900a
+.section s900b
+.section s0aaa
+.section s0aab
+.section s0aba
+.section s0abb
+.section s0aca
+.section s0acb
+.section s0ada
+.section s0adb
+.section s0aea
+.section s0aeb
+.section s0afa
+.section s0afb
+.section s0aga
+.section s0agb
+.section s0aha
+.section s0ahb
+.section s0aia
+.section s0aib
+.section s0aja
+.section s0ajb
+.section s0aka
+.section s0akb
+.section s0ala
+.section s0alb
+.section s0ama
+.section s0amb
+.section s0ana
+.section s0anb
+.section s0aoa
+.section s0aob
+.section s0apa
+.section s0apb
+.section s0aqa
+.section s0aqb
+.section s0ara
+.section s0arb
+.section s0asa
+.section s0asb
+.section s0ata
+.section s0atb
+.section s0aua
+.section s0aub
+.section s0ava
+.section s0avb
+.section s0awa
+.section s0awb
+.section s0axa
+.section s0axb
+.section s0aya
+.section s0ayb
+.section s0aza
+.section s0azb
+.section s0a1a
+.section s0a1b
+.section s0a2a
+.section s0a2b
+.section s0a3a
+.section s0a3b
+.section s0a4a
+.section s0a4b
+.section s0a5a
+.section s0a5b
+.section s0a6a
+.section s0a6b
+.section s0a7a
+.section s0a7b
+.section s0a8a
+.section s0a8b
+.section s0a9a
+.section s0a9b
+.section s0a0a
+.section s0a0b
+.section s0baa
+.section s0bab
+.section s0bba
+.section s0bbb
+.section s0bca
+.section s0bcb
+.section s0bda
+.section s0bdb
+.section s0bea
+.section s0beb
+.section s0bfa
+.section s0bfb
+.section s0bga
+.section s0bgb
+.section s0bha
+.section s0bhb
+.section s0bia
+.section s0bib
+.section s0bja
+.section s0bjb
+.section s0bka
+.section s0bkb
+.section s0bla
+.section s0blb
+.section s0bma
+.section s0bmb
+.section s0bna
+.section s0bnb
+.section s0boa
+.section s0bob
+.section s0bpa
+.section s0bpb
+.section s0bqa
+.section s0bqb
+.section s0bra
+.section s0brb
+.section s0bsa
+.section s0bsb
+.section s0bta
+.section s0btb
+.section s0bua
+.section s0bub
+.section s0bva
+.section s0bvb
+.section s0bwa
+.section s0bwb
+.section s0bxa
+.section s0bxb
+.section s0bya
+.section s0byb
+.section s0bza
+.section s0bzb
+.section s0b1a
+.section s0b1b
+.section s0b2a
+.section s0b2b
+.section s0b3a
+.section s0b3b
+.section s0b4a
+.section s0b4b
+.section s0b5a
+.section s0b5b
+.section s0b6a
+.section s0b6b
+.section s0b7a
+.section s0b7b
+.section s0b8a
+.section s0b8b
+.section s0b9a
+.section s0b9b
+.section s0b0a
+.section s0b0b
+.section s0caa
+.section s0cab
+.section s0cba
+.section s0cbb
+.section s0cca
+.section s0ccb
+.section s0cda
+.section s0cdb
+.section s0cea
+.section s0ceb
+.section s0cfa
+.section s0cfb
+.section s0cga
+.section s0cgb
+.section s0cha
+.section s0chb
+.section s0cia
+.section s0cib
+.section s0cja
+.section s0cjb
+.section s0cka
+.section s0ckb
+.section s0cla
+.section s0clb
+.section s0cma
+.section s0cmb
+.section s0cna
+.section s0cnb
+.section s0coa
+.section s0cob
+.section s0cpa
+.section s0cpb
+.section s0cqa
+.section s0cqb
+.section s0cra
+.section s0crb
+.section s0csa
+.section s0csb
+.section s0cta
+.section s0ctb
+.section s0cua
+.section s0cub
+.section s0cva
+.section s0cvb
+.section s0cwa
+.section s0cwb
+.section s0cxa
+.section s0cxb
+.section s0cya
+.section s0cyb
+.section s0cza
+.section s0czb
+.section s0c1a
+.section s0c1b
+.section s0c2a
+.section s0c2b
+.section s0c3a
+.section s0c3b
+.section s0c4a
+.section s0c4b
+.section s0c5a
+.section s0c5b
+.section s0c6a
+.section s0c6b
+.section s0c7a
+.section s0c7b
+.section s0c8a
+.section s0c8b
+.section s0c9a
+.section s0c9b
+.section s0c0a
+.section s0c0b
+.section s0daa
+.section s0dab
+.section s0dba
+.section s0dbb
+.section s0dca
+.section s0dcb
+.section s0dda
+.section s0ddb
+.section s0dea
+.section s0deb
+.section s0dfa
+.section s0dfb
+.section s0dga
+.section s0dgb
+.section s0dha
+.section s0dhb
+.section s0dia
+.section s0dib
+.section s0dja
+.section s0djb
+.section s0dka
+.section s0dkb
+.section s0dla
+.section s0dlb
+.section s0dma
+.section s0dmb
+.section s0dna
+.section s0dnb
+.section s0doa
+.section s0dob
+.section s0dpa
+.section s0dpb
+.section s0dqa
+.section s0dqb
+.section s0dra
+.section s0drb
+.section s0dsa
+.section s0dsb
+.section s0dta
+.section s0dtb
+.section s0dua
+.section s0dub
+.section s0dva
+.section s0dvb
+.section s0dwa
+.section s0dwb
+.section s0dxa
+.section s0dxb
+.section s0dya
+.section s0dyb
+.section s0dza
+.section s0dzb
+.section s0d1a
+.section s0d1b
+.section s0d2a
+.section s0d2b
+.section s0d3a
+.section s0d3b
+.section s0d4a
+.section s0d4b
+.section s0d5a
+.section s0d5b
+.section s0d6a
+.section s0d6b
+.section s0d7a
+.section s0d7b
+.section s0d8a
+.section s0d8b
+.section s0d9a
+.section s0d9b
+.section s0d0a
+.section s0d0b
+.section s0eaa
+.section s0eab
+.section s0eba
+.section s0ebb
+.section s0eca
+.section s0ecb
+.section s0eda
+.section s0edb
+.section s0eea
+.section s0eeb
+.section s0efa
+.section s0efb
+.section s0ega
+.section s0egb
+.section s0eha
+.section s0ehb
+.section s0eia
+.section s0eib
+.section s0eja
+.section s0ejb
+.section s0eka
+.section s0ekb
+.section s0ela
+.section s0elb
+.section s0ema
+.section s0emb
+.section s0ena
+.section s0enb
+.section s0eoa
+.section s0eob
+.section s0epa
+.section s0epb
+.section s0eqa
+.section s0eqb
+.section s0era
+.section s0erb
+.section s0esa
+.section s0esb
+.section s0eta
+.section s0etb
+.section s0eua
+.section s0eub
+.section s0eva
+.section s0evb
+.section s0ewa
+.section s0ewb
+.section s0exa
+.section s0exb
+.section s0eya
+.section s0eyb
+.section s0eza
+.section s0ezb
+.section s0e1a
+.section s0e1b
+.section s0e2a
+.section s0e2b
+.section s0e3a
+.section s0e3b
+.section s0e4a
+.section s0e4b
+.section s0e5a
+.section s0e5b
+.section s0e6a
+.section s0e6b
+.section s0e7a
+.section s0e7b
+.section s0e8a
+.section s0e8b
+.section s0e9a
+.section s0e9b
+.section s0e0a
+.section s0e0b
+.section s0faa
+.section s0fab
+.section s0fba
+.section s0fbb
+.section s0fca
+.section s0fcb
+.section s0fda
+.section s0fdb
+.section s0fea
+.section s0feb
+.section s0ffa
+.section s0ffb
+.section s0fga
+.section s0fgb
+.section s0fha
+.section s0fhb
+.section s0fia
+.section s0fib
+.section s0fja
+.section s0fjb
+.section s0fka
+.section s0fkb
+.section s0fla
+.section s0flb
+.section s0fma
+.section s0fmb
+.section s0fna
+.section s0fnb
+.section s0foa
+.section s0fob
+.section s0fpa
+.section s0fpb
+.section s0fqa
+.section s0fqb
+.section s0fra
+.section s0frb
+.section s0fsa
+.section s0fsb
+.section s0fta
+.section s0ftb
+.section s0fua
+.section s0fub
+.section s0fva
+.section s0fvb
+.section s0fwa
+.section s0fwb
+.section s0fxa
+.section s0fxb
+.section s0fya
+.section s0fyb
+.section s0fza
+.section s0fzb
+.section s0f1a
+.section s0f1b
+.section s0f2a
+.section s0f2b
+.section s0f3a
+.section s0f3b
+.section s0f4a
+.section s0f4b
+.section s0f5a
+.section s0f5b
+.section s0f6a
+.section s0f6b
+.section s0f7a
+.section s0f7b
+.section s0f8a
+.section s0f8b
+.section s0f9a
+.section s0f9b
+.section s0f0a
+.section s0f0b
+.section s0gaa
+.section s0gab
+.section s0gba
+.section s0gbb
+.section s0gca
+.section s0gcb
+.section s0gda
+.section s0gdb
+.section s0gea
+.section s0geb
+.section s0gfa
+.section s0gfb
+.section s0gga
+.section s0ggb
+.section s0gha
+.section s0ghb
+.section s0gia
+.section s0gib
+.section s0gja
+.section s0gjb
+.section s0gka
+.section s0gkb
+.section s0gla
+.section s0glb
+.section s0gma
+.section s0gmb
+.section s0gna
+.section s0gnb
+.section s0goa
+.section s0gob
+.section s0gpa
+.section s0gpb
+.section s0gqa
+.section s0gqb
+.section s0gra
+.section s0grb
+.section s0gsa
+.section s0gsb
+.section s0gta
+.section s0gtb
+.section s0gua
+.section s0gub
+.section s0gva
+.section s0gvb
+.section s0gwa
+.section s0gwb
+.section s0gxa
+.section s0gxb
+.section s0gya
+.section s0gyb
+.section s0gza
+.section s0gzb
+.section s0g1a
+.section s0g1b
+.section s0g2a
+.section s0g2b
+.section s0g3a
+.section s0g3b
+.section s0g4a
+.section s0g4b
+.section s0g5a
+.section s0g5b
+.section s0g6a
+.section s0g6b
+.section s0g7a
+.section s0g7b
+.section s0g8a
+.section s0g8b
+.section s0g9a
+.section s0g9b
+.section s0g0a
+.section s0g0b
+.section s0haa
+.section s0hab
+.section s0hba
+.section s0hbb
+.section s0hca
+.section s0hcb
+.section s0hda
+.section s0hdb
+.section s0hea
+.section s0heb
+.section s0hfa
+.section s0hfb
+.section s0hga
+.section s0hgb
+.section s0hha
+.section s0hhb
+.section s0hia
+.section s0hib
+.section s0hja
+.section s0hjb
+.section s0hka
+.section s0hkb
+.section s0hla
+.section s0hlb
+.section s0hma
+.section s0hmb
+.section s0hna
+.section s0hnb
+.section s0hoa
+.section s0hob
+.section s0hpa
+.section s0hpb
+.section s0hqa
+.section s0hqb
+.section s0hra
+.section s0hrb
+.section s0hsa
+.section s0hsb
+.section s0hta
+.section s0htb
+.section s0hua
+.section s0hub
+.section s0hva
+.section s0hvb
+.section s0hwa
+.section s0hwb
+.section s0hxa
+.section s0hxb
+.section s0hya
+.section s0hyb
+.section s0hza
+.section s0hzb
+.section s0h1a
+.section s0h1b
+.section s0h2a
+.section s0h2b
+.section s0h3a
+.section s0h3b
+.section s0h4a
+.section s0h4b
+.section s0h5a
+.section s0h5b
+.section s0h6a
+.section s0h6b
+.section s0h7a
+.section s0h7b
+.section s0h8a
+.section s0h8b
+.section s0h9a
+.section s0h9b
+.section s0h0a
+.section s0h0b
+.section s0iaa
+.section s0iab
+.section s0iba
+.section s0ibb
+.section s0ica
+.section s0icb
+.section s0ida
+.section s0idb
+.section s0iea
+.section s0ieb
+.section s0ifa
+.section s0ifb
+.section s0iga
+.section s0igb
+.section s0iha
+.section s0ihb
+.section s0iia
+.section s0iib
+.section s0ija
+.section s0ijb
+.section s0ika
+.section s0ikb
+.section s0ila
+.section s0ilb
+.section s0ima
+.section s0imb
+.section s0ina
+.section s0inb
+.section s0ioa
+.section s0iob
+.section s0ipa
+.section s0ipb
+.section s0iqa
+.section s0iqb
+.section s0ira
+.section s0irb
+.section s0isa
+.section s0isb
+.section s0ita
+.section s0itb
+.section s0iua
+.section s0iub
+.section s0iva
+.section s0ivb
+.section s0iwa
+.section s0iwb
+.section s0ixa
+.section s0ixb
+.section s0iya
+.section s0iyb
+.section s0iza
+.section s0izb
+.section s0i1a
+.section s0i1b
+.section s0i2a
+.section s0i2b
+.section s0i3a
+.section s0i3b
+.section s0i4a
+.section s0i4b
+.section s0i5a
+.section s0i5b
+.section s0i6a
+.section s0i6b
+.section s0i7a
+.section s0i7b
+.section s0i8a
+.section s0i8b
+.section s0i9a
+.section s0i9b
+.section s0i0a
+.section s0i0b
+.section s0jaa
+.section s0jab
+.section s0jba
+.section s0jbb
+.section s0jca
+.section s0jcb
+.section s0jda
+.section s0jdb
+.section s0jea
+.section s0jeb
+.section s0jfa
+.section s0jfb
+.section s0jga
+.section s0jgb
+.section s0jha
+.section s0jhb
+.section s0jia
+.section s0jib
+.section s0jja
+.section s0jjb
+.section s0jka
+.section s0jkb
+.section s0jla
+.section s0jlb
+.section s0jma
+.section s0jmb
+.section s0jna
+.section s0jnb
+.section s0joa
+.section s0job
+.section s0jpa
+.section s0jpb
+.section s0jqa
+.section s0jqb
+.section s0jra
+.section s0jrb
+.section s0jsa
+.section s0jsb
+.section s0jta
+.section s0jtb
+.section s0jua
+.section s0jub
+.section s0jva
+.section s0jvb
+.section s0jwa
+.section s0jwb
+.section s0jxa
+.section s0jxb
+.section s0jya
+.section s0jyb
+.section s0jza
+.section s0jzb
+.section s0j1a
+.section s0j1b
+.section s0j2a
+.section s0j2b
+.section s0j3a
+.section s0j3b
+.section s0j4a
+.section s0j4b
+.section s0j5a
+.section s0j5b
+.section s0j6a
+.section s0j6b
+.section s0j7a
+.section s0j7b
+.section s0j8a
+.section s0j8b
+.section s0j9a
+.section s0j9b
+.section s0j0a
+.section s0j0b
+.section s0kaa
+.section s0kab
+.section s0kba
+.section s0kbb
+.section s0kca
+.section s0kcb
+.section s0kda
+.section s0kdb
+.section s0kea
+.section s0keb
+.section s0kfa
+.section s0kfb
+.section s0kga
+.section s0kgb
+.section s0kha
+.section s0khb
+.section s0kia
+.section s0kib
+.section s0kja
+.section s0kjb
+.section s0kka
+.section s0kkb
+.section s0kla
+.section s0klb
+.section s0kma
+.section s0kmb
+.section s0kna
+.section s0knb
+.section s0koa
+.section s0kob
+.section s0kpa
+.section s0kpb
+.section s0kqa
+.section s0kqb
+.section s0kra
+.section s0krb
+.section s0ksa
+.section s0ksb
+.section s0kta
+.section s0ktb
+.section s0kua
+.section s0kub
+.section s0kva
+.section s0kvb
+.section s0kwa
+.section s0kwb
+.section s0kxa
+.section s0kxb
+.section s0kya
+.section s0kyb
+.section s0kza
+.section s0kzb
+.section s0k1a
+.section s0k1b
+.section s0k2a
+.section s0k2b
+.section s0k3a
+.section s0k3b
+.section s0k4a
+.section s0k4b
+.section s0k5a
+.section s0k5b
+.section s0k6a
+.section s0k6b
+.section s0k7a
+.section s0k7b
+.section s0k8a
+.section s0k8b
+.section s0k9a
+.section s0k9b
+.section s0k0a
+.section s0k0b
+.section s0laa
+.section s0lab
+.section s0lba
+.section s0lbb
+.section s0lca
+.section s0lcb
+.section s0lda
+.section s0ldb
+.section s0lea
+.section s0leb
+.section s0lfa
+.section s0lfb
+.section s0lga
+.section s0lgb
+.section s0lha
+.section s0lhb
+.section s0lia
+.section s0lib
+.section s0lja
+.section s0ljb
+.section s0lka
+.section s0lkb
+.section s0lla
+.section s0llb
+.section s0lma
+.section s0lmb
+.section s0lna
+.section s0lnb
+.section s0loa
+.section s0lob
+.section s0lpa
+.section s0lpb
+.section s0lqa
+.section s0lqb
+.section s0lra
+.section s0lrb
+.section s0lsa
+.section s0lsb
+.section s0lta
+.section s0ltb
+.section s0lua
+.section s0lub
+.section s0lva
+.section s0lvb
+.section s0lwa
+.section s0lwb
+.section s0lxa
+.section s0lxb
+.section s0lya
+.section s0lyb
+.section s0lza
+.section s0lzb
+.section s0l1a
+.section s0l1b
+.section s0l2a
+.section s0l2b
+.section s0l3a
+.section s0l3b
+.section s0l4a
+.section s0l4b
+.section s0l5a
+.section s0l5b
+.section s0l6a
+.section s0l6b
+.section s0l7a
+.section s0l7b
+.section s0l8a
+.section s0l8b
+.section s0l9a
+.section s0l9b
+.section s0l0a
+.section s0l0b
+.section s0maa
+.section s0mab
+.section s0mba
+.section s0mbb
+.section s0mca
+.section s0mcb
+.section s0mda
+.section s0mdb
+.section s0mea
+.section s0meb
+.section s0mfa
+.section s0mfb
+.section s0mga
+.section s0mgb
+.section s0mha
+.section s0mhb
+.section s0mia
+.section s0mib
+.section s0mja
+.section s0mjb
+.section s0mka
+.section s0mkb
+.section s0mla
+.section s0mlb
+.section s0mma
+.section s0mmb
+.section s0mna
+.section s0mnb
+.section s0moa
+.section s0mob
+.section s0mpa
+.section s0mpb
+.section s0mqa
+.section s0mqb
+.section s0mra
+.section s0mrb
+.section s0msa
+.section s0msb
+.section s0mta
+.section s0mtb
+.section s0mua
+.section s0mub
+.section s0mva
+.section s0mvb
+.section s0mwa
+.section s0mwb
+.section s0mxa
+.section s0mxb
+.section s0mya
+.section s0myb
+.section s0mza
+.section s0mzb
+.section s0m1a
+.section s0m1b
+.section s0m2a
+.section s0m2b
+.section s0m3a
+.section s0m3b
+.section s0m4a
+.section s0m4b
+.section s0m5a
+.section s0m5b
+.section s0m6a
+.section s0m6b
+.section s0m7a
+.section s0m7b
+.section s0m8a
+.section s0m8b
+.section s0m9a
+.section s0m9b
+.section s0m0a
+.section s0m0b
+.section s0naa
+.section s0nab
+.section s0nba
+.section s0nbb
+.section s0nca
+.section s0ncb
+.section s0nda
+.section s0ndb
+.section s0nea
+.section s0neb
+.section s0nfa
+.section s0nfb
+.section s0nga
+.section s0ngb
+.section s0nha
+.section s0nhb
+.section s0nia
+.section s0nib
+.section s0nja
+.section s0njb
+.section s0nka
+.section s0nkb
+.section s0nla
+.section s0nlb
+.section s0nma
+.section s0nmb
+.section s0nna
+.section s0nnb
+.section s0noa
+.section s0nob
+.section s0npa
+.section s0npb
+.section s0nqa
+.section s0nqb
+.section s0nra
+.section s0nrb
+.section s0nsa
+.section s0nsb
+.section s0nta
+.section s0ntb
+.section s0nua
+.section s0nub
+.section s0nva
+.section s0nvb
+.section s0nwa
+.section s0nwb
+.section s0nxa
+.section s0nxb
+.section s0nya
+.section s0nyb
+.section s0nza
+.section s0nzb
+.section s0n1a
+.section s0n1b
+.section s0n2a
+.section s0n2b
+.section s0n3a
+.section s0n3b
+.section s0n4a
+.section s0n4b
+.section s0n5a
+.section s0n5b
+.section s0n6a
+.section s0n6b
+.section s0n7a
+.section s0n7b
+.section s0n8a
+.section s0n8b
+.section s0n9a
+.section s0n9b
+.section s0n0a
+.section s0n0b
+.section s0oaa
+.section s0oab
+.section s0oba
+.section s0obb
+.section s0oca
+.section s0ocb
+.section s0oda
+.section s0odb
+.section s0oea
+.section s0oeb
+.section s0ofa
+.section s0ofb
+.section s0oga
+.section s0ogb
+.section s0oha
+.section s0ohb
+.section s0oia
+.section s0oib
+.section s0oja
+.section s0ojb
+.section s0oka
+.section s0okb
+.section s0ola
+.section s0olb
+.section s0oma
+.section s0omb
+.section s0ona
+.section s0onb
+.section s0ooa
+.section s0oob
+.section s0opa
+.section s0opb
+.section s0oqa
+.section s0oqb
+.section s0ora
+.section s0orb
+.section s0osa
+.section s0osb
+.section s0ota
+.section s0otb
+.section s0oua
+.section s0oub
+.section s0ova
+.section s0ovb
+.section s0owa
+.section s0owb
+.section s0oxa
+.section s0oxb
+.section s0oya
+.section s0oyb
+.section s0oza
+.section s0ozb
+.section s0o1a
+.section s0o1b
+.section s0o2a
+.section s0o2b
+.section s0o3a
+.section s0o3b
+.section s0o4a
+.section s0o4b
+.section s0o5a
+.section s0o5b
+.section s0o6a
+.section s0o6b
+.section s0o7a
+.section s0o7b
+.section s0o8a
+.section s0o8b
+.section s0o9a
+.section s0o9b
+.section s0o0a
+.section s0o0b
+.section s0paa
+.section s0pab
+.section s0pba
+.section s0pbb
+.section s0pca
+.section s0pcb
+.section s0pda
+.section s0pdb
+.section s0pea
+.section s0peb
+.section s0pfa
+.section s0pfb
+.section s0pga
+.section s0pgb
+.section s0pha
+.section s0phb
+.section s0pia
+.section s0pib
+.section s0pja
+.section s0pjb
+.section s0pka
+.section s0pkb
+.section s0pla
+.section s0plb
+.section s0pma
+.section s0pmb
+.section s0pna
+.section s0pnb
+.section s0poa
+.section s0pob
+.section s0ppa
+.section s0ppb
+.section s0pqa
+.section s0pqb
+.section s0pra
+.section s0prb
+.section s0psa
+.section s0psb
+.section s0pta
+.section s0ptb
+.section s0pua
+.section s0pub
+.section s0pva
+.section s0pvb
+.section s0pwa
+.section s0pwb
+.section s0pxa
+.section s0pxb
+.section s0pya
+.section s0pyb
+.section s0pza
+.section s0pzb
+.section s0p1a
+.section s0p1b
+.section s0p2a
+.section s0p2b
+.section s0p3a
+.section s0p3b
+.section s0p4a
+.section s0p4b
+.section s0p5a
+.section s0p5b
+.section s0p6a
+.section s0p6b
+.section s0p7a
+.section s0p7b
+.section s0p8a
+.section s0p8b
+.section s0p9a
+.section s0p9b
+.section s0p0a
+.section s0p0b
+.section s0qaa
+.section s0qab
+.section s0qba
+.section s0qbb
+.section s0qca
+.section s0qcb
+.section s0qda
+.section s0qdb
+.section s0qea
+.section s0qeb
+.section s0qfa
+.section s0qfb
+.section s0qga
+.section s0qgb
+.section s0qha
+.section s0qhb
+.section s0qia
+.section s0qib
+.section s0qja
+.section s0qjb
+.section s0qka
+.section s0qkb
+.section s0qla
+.section s0qlb
+.section s0qma
+.section s0qmb
+.section s0qna
+.section s0qnb
+.section s0qoa
+.section s0qob
+.section s0qpa
+.section s0qpb
+.section s0qqa
+.section s0qqb
+.section s0qra
+.section s0qrb
+.section s0qsa
+.section s0qsb
+.section s0qta
+.section s0qtb
+.section s0qua
+.section s0qub
+.section s0qva
+.section s0qvb
+.section s0qwa
+.section s0qwb
+.section s0qxa
+.section s0qxb
+.section s0qya
+.section s0qyb
+.section s0qza
+.section s0qzb
+.section s0q1a
+.section s0q1b
+.section s0q2a
+.section s0q2b
+.section s0q3a
+.section s0q3b
+.section s0q4a
+.section s0q4b
+.section s0q5a
+.section s0q5b
+.section s0q6a
+.section s0q6b
+.section s0q7a
+.section s0q7b
+.section s0q8a
+.section s0q8b
+.section s0q9a
+.section s0q9b
+.section s0q0a
+.section s0q0b
+.section s0raa
+.section s0rab
+.section s0rba
+.section s0rbb
+.section s0rca
+.section s0rcb
+.section s0rda
+.section s0rdb
+.section s0rea
+.section s0reb
+.section s0rfa
+.section s0rfb
+.section s0rga
+.section s0rgb
+.section s0rha
+.section s0rhb
+.section s0ria
+.section s0rib
+.section s0rja
+.section s0rjb
+.section s0rka
+.section s0rkb
+.section s0rla
+.section s0rlb
+.section s0rma
+.section s0rmb
+.section s0rna
+.section s0rnb
+.section s0roa
+.section s0rob
+.section s0rpa
+.section s0rpb
+.section s0rqa
+.section s0rqb
+.section s0rra
+.section s0rrb
+.section s0rsa
+.section s0rsb
+.section s0rta
+.section s0rtb
+.section s0rua
+.section s0rub
+.section s0rva
+.section s0rvb
+.section s0rwa
+.section s0rwb
+.section s0rxa
+.section s0rxb
+.section s0rya
+.section s0ryb
+.section s0rza
+.section s0rzb
+.section s0r1a
+.section s0r1b
+.section s0r2a
+.section s0r2b
+.section s0r3a
+.section s0r3b
+.section s0r4a
+.section s0r4b
+.section s0r5a
+.section s0r5b
+.section s0r6a
+.section s0r6b
+.section s0r7a
+.section s0r7b
+.section s0r8a
+.section s0r8b
+.section s0r9a
+.section s0r9b
+.section s0r0a
+.section s0r0b
+.section s0saa
+.section s0sab
+.section s0sba
+.section s0sbb
+.section s0sca
+.section s0scb
+.section s0sda
+.section s0sdb
+.section s0sea
+.section s0seb
+.section s0sfa
+.section s0sfb
+.section s0sga
+.section s0sgb
+.section s0sha
+.section s0shb
+.section s0sia
+.section s0sib
+.section s0sja
+.section s0sjb
+.section s0ska
+.section s0skb
+.section s0sla
+.section s0slb
+.section s0sma
+.section s0smb
+.section s0sna
+.section s0snb
+.section s0soa
+.section s0sob
+.section s0spa
+.section s0spb
+.section s0sqa
+.section s0sqb
+.section s0sra
+.section s0srb
+.section s0ssa
+.section s0ssb
+.section s0sta
+.section s0stb
+.section s0sua
+.section s0sub
+.section s0sva
+.section s0svb
+.section s0swa
+.section s0swb
+.section s0sxa
+.section s0sxb
+.section s0sya
+.section s0syb
+.section s0sza
+.section s0szb
+.section s0s1a
+.section s0s1b
+.section s0s2a
+.section s0s2b
+.section s0s3a
+.section s0s3b
+.section s0s4a
+.section s0s4b
+.section s0s5a
+.section s0s5b
+.section s0s6a
+.section s0s6b
+.section s0s7a
+.section s0s7b
+.section s0s8a
+.section s0s8b
+.section s0s9a
+.section s0s9b
+.section s0s0a
+.section s0s0b
+.section s0taa
+.section s0tab
+.section s0tba
+.section s0tbb
+.section s0tca
+.section s0tcb
+.section s0tda
+.section s0tdb
+.section s0tea
+.section s0teb
+.section s0tfa
+.section s0tfb
+.section s0tga
+.section s0tgb
+.section s0tha
+.section s0thb
+.section s0tia
+.section s0tib
+.section s0tja
+.section s0tjb
+.section s0tka
+.section s0tkb
+.section s0tla
+.section s0tlb
+.section s0tma
+.section s0tmb
+.section s0tna
+.section s0tnb
+.section s0toa
+.section s0tob
+.section s0tpa
+.section s0tpb
+.section s0tqa
+.section s0tqb
+.section s0tra
+.section s0trb
+.section s0tsa
+.section s0tsb
+.section s0tta
+.section s0ttb
+.section s0tua
+.section s0tub
+.section s0tva
+.section s0tvb
+.section s0twa
+.section s0twb
+.section s0txa
+.section s0txb
+.section s0tya
+.section s0tyb
+.section s0tza
+.section s0tzb
+.section s0t1a
+.section s0t1b
+.section s0t2a
+.section s0t2b
+.section s0t3a
+.section s0t3b
+.section s0t4a
+.section s0t4b
+.section s0t5a
+.section s0t5b
+.section s0t6a
+.section s0t6b
+.section s0t7a
+.section s0t7b
+.section s0t8a
+.section s0t8b
+.section s0t9a
+.section s0t9b
+.section s0t0a
+.section s0t0b
+.section s0uaa
+.section s0uab
+.section s0uba
+.section s0ubb
+.section s0uca
+.section s0ucb
+.section s0uda
+.section s0udb
+.section s0uea
+.section s0ueb
+.section s0ufa
+.section s0ufb
+.section s0uga
+.section s0ugb
+.section s0uha
+.section s0uhb
+.section s0uia
+.section s0uib
+.section s0uja
+.section s0ujb
+.section s0uka
+.section s0ukb
+.section s0ula
+.section s0ulb
+.section s0uma
+.section s0umb
+.section s0una
+.section s0unb
+.section s0uoa
+.section s0uob
+.section s0upa
+.section s0upb
+.section s0uqa
+.section s0uqb
+.section s0ura
+.section s0urb
+.section s0usa
+.section s0usb
+.section s0uta
+.section s0utb
+.section s0uua
+.section s0uub
+.section s0uva
+.section s0uvb
+.section s0uwa
+.section s0uwb
+.section s0uxa
+.section s0uxb
+.section s0uya
+.section s0uyb
+.section s0uza
+.section s0uzb
+.section s0u1a
+.section s0u1b
+.section s0u2a
+.section s0u2b
+.section s0u3a
+.section s0u3b
+.section s0u4a
+.section s0u4b
+.section s0u5a
+.section s0u5b
+.section s0u6a
+.section s0u6b
+.section s0u7a
+.section s0u7b
+.section s0u8a
+.section s0u8b
+.section s0u9a
+.section s0u9b
+.section s0u0a
+.section s0u0b
+.section s0vaa
+.section s0vab
+.section s0vba
+.section s0vbb
+.section s0vca
+.section s0vcb
+.section s0vda
+.section s0vdb
+.section s0vea
+.section s0veb
+.section s0vfa
+.section s0vfb
+.section s0vga
+.section s0vgb
+.section s0vha
+.section s0vhb
+.section s0via
+.section s0vib
+.section s0vja
+.section s0vjb
+.section s0vka
+.section s0vkb
+.section s0vla
+.section s0vlb
+.section s0vma
+.section s0vmb
+.section s0vna
+.section s0vnb
+.section s0voa
+.section s0vob
+.section s0vpa
+.section s0vpb
+.section s0vqa
+.section s0vqb
+.section s0vra
+.section s0vrb
+.section s0vsa
+.section s0vsb
+.section s0vta
+.section s0vtb
+.section s0vua
+.section s0vub
+.section s0vva
+.section s0vvb
+.section s0vwa
+.section s0vwb
+.section s0vxa
+.section s0vxb
+.section s0vya
+.section s0vyb
+.section s0vza
+.section s0vzb
+.section s0v1a
+.section s0v1b
+.section s0v2a
+.section s0v2b
+.section s0v3a
+.section s0v3b
+.section s0v4a
+.section s0v4b
+.section s0v5a
+.section s0v5b
+.section s0v6a
+.section s0v6b
+.section s0v7a
+.section s0v7b
+.section s0v8a
+.section s0v8b
+.section s0v9a
+.section s0v9b
+.section s0v0a
+.section s0v0b
+.section s0waa
+.section s0wab
+.section s0wba
+.section s0wbb
+.section s0wca
+.section s0wcb
+.section s0wda
+.section s0wdb
+.section s0wea
+.section s0web
+.section s0wfa
+.section s0wfb
+.section s0wga
+.section s0wgb
+.section s0wha
+.section s0whb
+.section s0wia
+.section s0wib
+.section s0wja
+.section s0wjb
+.section s0wka
+.section s0wkb
+.section s0wla
+.section s0wlb
+.section s0wma
+.section s0wmb
+.section s0wna
+.section s0wnb
+.section s0woa
+.section s0wob
+.section s0wpa
+.section s0wpb
+.section s0wqa
+.section s0wqb
+.section s0wra
+.section s0wrb
+.section s0wsa
+.section s0wsb
+.section s0wta
+.section s0wtb
+.section s0wua
+.section s0wub
+.section s0wva
+.section s0wvb
+.section s0wwa
+.section s0wwb
+.section s0wxa
+.section s0wxb
+.section s0wya
+.section s0wyb
+.section s0wza
+.section s0wzb
+.section s0w1a
+.section s0w1b
+.section s0w2a
+.section s0w2b
+.section s0w3a
+.section s0w3b
+.section s0w4a
+.section s0w4b
+.section s0w5a
+.section s0w5b
+.section s0w6a
+.section s0w6b
+.section s0w7a
+.section s0w7b
+.section s0w8a
+.section s0w8b
+.section s0w9a
+.section s0w9b
+.section s0w0a
+.section s0w0b
+.section s0xaa
+.section s0xab
+.section s0xba
+.section s0xbb
+.section s0xca
+.section s0xcb
+.section s0xda
+.section s0xdb
+.section s0xea
+.section s0xeb
+.section s0xfa
+.section s0xfb
+.section s0xga
+.section s0xgb
+.section s0xha
+.section s0xhb
+.section s0xia
+.section s0xib
+.section s0xja
+.section s0xjb
+.section s0xka
+.section s0xkb
+.section s0xla
+.section s0xlb
+.section s0xma
+.section s0xmb
+.section s0xna
+.section s0xnb
+.section s0xoa
+.section s0xob
+.section s0xpa
+.section s0xpb
+.section s0xqa
+.section s0xqb
+.section s0xra
+.section s0xrb
+.section s0xsa
+.section s0xsb
+.section s0xta
+.section s0xtb
+.section s0xua
+.section s0xub
+.section s0xva
+.section s0xvb
+.section s0xwa
+.section s0xwb
+.section s0xxa
+.section s0xxb
+.section s0xya
+.section s0xyb
+.section s0xza
+.section s0xzb
+.section s0x1a
+.section s0x1b
+.section s0x2a
+.section s0x2b
+.section s0x3a
+.section s0x3b
+.section s0x4a
+.section s0x4b
+.section s0x5a
+.section s0x5b
+.section s0x6a
+.section s0x6b
+.section s0x7a
+.section s0x7b
+.section s0x8a
+.section s0x8b
+.section s0x9a
+.section s0x9b
+.section s0x0a
+.section s0x0b
+.section s0yaa
+.section s0yab
+.section s0yba
+.section s0ybb
+.section s0yca
+.section s0ycb
+.section s0yda
+.section s0ydb
+.section s0yea
+.section s0yeb
+.section s0yfa
+.section s0yfb
+.section s0yga
+.section s0ygb
+.section s0yha
+.section s0yhb
+.section s0yia
+.section s0yib
+.section s0yja
+.section s0yjb
+.section s0yka
+.section s0ykb
+.section s0yla
+.section s0ylb
+.section s0yma
+.section s0ymb
+.section s0yna
+.section s0ynb
+.section s0yoa
+.section s0yob
+.section s0ypa
+.section s0ypb
+.section s0yqa
+.section s0yqb
+.section s0yra
+.section s0yrb
+.section s0ysa
+.section s0ysb
+.section s0yta
+.section s0ytb
+.section s0yua
+.section s0yub
+.section s0yva
+.section s0yvb
+.section s0ywa
+.section s0ywb
+.section s0yxa
+.section s0yxb
+.section s0yya
+.section s0yyb
+.section s0yza
+.section s0yzb
+.section s0y1a
+.section s0y1b
+.section s0y2a
+.section s0y2b
+.section s0y3a
+.section s0y3b
+.section s0y4a
+.section s0y4b
+.section s0y5a
+.section s0y5b
+.section s0y6a
+.section s0y6b
+.section s0y7a
+.section s0y7b
+.section s0y8a
+.section s0y8b
+.section s0y9a
+.section s0y9b
+.section s0y0a
+.section s0y0b
+.section s0zaa
+.section s0zab
+.section s0zba
+.section s0zbb
+.section s0zca
+.section s0zcb
+.section s0zda
+.section s0zdb
+.section s0zea
+.section s0zeb
+.section s0zfa
+.section s0zfb
+.section s0zga
+.section s0zgb
+.section s0zha
+.section s0zhb
+.section s0zia
+.section s0zib
+.section s0zja
+.section s0zjb
+.section s0zka
+.section s0zkb
+.section s0zla
+.section s0zlb
+.section s0zma
+.section s0zmb
+.section s0zna
+.section s0znb
+.section s0zoa
+.section s0zob
+.section s0zpa
+.section s0zpb
+.section s0zqa
+.section s0zqb
+.section s0zra
+.section s0zrb
+.section s0zsa
+.section s0zsb
+.section s0zta
+.section s0ztb
+.section s0zua
+.section s0zub
+.section s0zva
+.section s0zvb
+.section s0zwa
+.section s0zwb
+.section s0zxa
+.section s0zxb
+.section s0zya
+.section s0zyb
+.section s0zza
+.section s0zzb
+.section s0z1a
+.section s0z1b
+.section s0z2a
+.section s0z2b
+.section s0z3a
+.section s0z3b
+.section s0z4a
+.section s0z4b
+.section s0z5a
+.section s0z5b
+.section s0z6a
+.section s0z6b
+.section s0z7a
+.section s0z7b
+.section s0z8a
+.section s0z8b
+.section s0z9a
+.section s0z9b
+.section s0z0a
+.section s0z0b
+.section s01aa
+.section s01ab
+.section s01ba
+.section s01bb
+.section s01ca
+.section s01cb
+.section s01da
+.section s01db
+.section s01ea
+.section s01eb
+.section s01fa
+.section s01fb
+.section s01ga
+.section s01gb
+.section s01ha
+.section s01hb
+.section s01ia
+.section s01ib
+.section s01ja
+.section s01jb
+.section s01ka
+.section s01kb
+.section s01la
+.section s01lb
+.section s01ma
+.section s01mb
+.section s01na
+.section s01nb
+.section s01oa
+.section s01ob
+.section s01pa
+.section s01pb
+.section s01qa
+.section s01qb
+.section s01ra
+.section s01rb
+.section s01sa
+.section s01sb
+.section s01ta
+.section s01tb
+.section s01ua
+.section s01ub
+.section s01va
+.section s01vb
+.section s01wa
+.section s01wb
+.section s01xa
+.section s01xb
+.section s01ya
+.section s01yb
+.section s01za
+.section s01zb
+.section s011a
+.section s011b
+.section s012a
+.section s012b
+.section s013a
+.section s013b
+.section s014a
+.section s014b
+.section s015a
+.section s015b
+.section s016a
+.section s016b
+.section s017a
+.section s017b
+.section s018a
+.section s018b
+.section s019a
+.section s019b
+.section s010a
+.section s010b
+.section s02aa
+.section s02ab
+.section s02ba
+.section s02bb
+.section s02ca
+.section s02cb
+.section s02da
+.section s02db
+.section s02ea
+.section s02eb
+.section s02fa
+.section s02fb
+.section s02ga
+.section s02gb
+.section s02ha
+.section s02hb
+.section s02ia
+.section s02ib
+.section s02ja
+.section s02jb
+.section s02ka
+.section s02kb
+.section s02la
+.section s02lb
+.section s02ma
+.section s02mb
+.section s02na
+.section s02nb
+.section s02oa
+.section s02ob
+.section s02pa
+.section s02pb
+.section s02qa
+.section s02qb
+.section s02ra
+.section s02rb
+.section s02sa
+.section s02sb
+.section s02ta
+.section s02tb
+.section s02ua
+.section s02ub
+.section s02va
+.section s02vb
+.section s02wa
+.section s02wb
+.section s02xa
+.section s02xb
+.section s02ya
+.section s02yb
+.section s02za
+.section s02zb
+.section s021a
+.section s021b
+.section s022a
+.section s022b
+.section s023a
+.section s023b
+.section s024a
+.section s024b
+.section s025a
+.section s025b
+.section s026a
+.section s026b
+.section s027a
+.section s027b
+.section s028a
+.section s028b
+.section s029a
+.section s029b
+.section s020a
+.section s020b
+.section s03aa
+.section s03ab
+.section s03ba
+.section s03bb
+.section s03ca
+.section s03cb
+.section s03da
+.section s03db
+.section s03ea
+.section s03eb
+.section s03fa
+.section s03fb
+.section s03ga
+.section s03gb
+.section s03ha
+.section s03hb
+.section s03ia
+.section s03ib
+.section s03ja
+.section s03jb
+.section s03ka
+.section s03kb
+.section s03la
+.section s03lb
+.section s03ma
+.section s03mb
+.section s03na
+.section s03nb
+.section s03oa
+.section s03ob
+.section s03pa
+.section s03pb
+.section s03qa
+.section s03qb
+.section s03ra
+.section s03rb
+.section s03sa
+.section s03sb
+.section s03ta
+.section s03tb
+.section s03ua
+.section s03ub
+.section s03va
+.section s03vb
+.section s03wa
+.section s03wb
+.section s03xa
+.section s03xb
+.section s03ya
+.section s03yb
+.section s03za
+.section s03zb
+.section s031a
+.section s031b
+.section s032a
+.section s032b
+.section s033a
+.section s033b
+.section s034a
+.section s034b
+.section s035a
+.section s035b
+.section s036a
+.section s036b
+.section s037a
+.section s037b
+.section s038a
+.section s038b
+.section s039a
+.section s039b
+.section s030a
+.section s030b
+.section s04aa
+.section s04ab
+.section s04ba
+.section s04bb
+.section s04ca
+.section s04cb
+.section s04da
+.section s04db
+.section s04ea
+.section s04eb
+.section s04fa
+.section s04fb
+.section s04ga
+.section s04gb
+.section s04ha
+.section s04hb
+.section s04ia
+.section s04ib
+.section s04ja
+.section s04jb
+.section s04ka
+.section s04kb
+.section s04la
+.section s04lb
+.section s04ma
+.section s04mb
+.section s04na
+.section s04nb
+.section s04oa
+.section s04ob
+.section s04pa
+.section s04pb
+.section s04qa
+.section s04qb
+.section s04ra
+.section s04rb
+.section s04sa
+.section s04sb
+.section s04ta
+.section s04tb
+.section s04ua
+.section s04ub
+.section s04va
+.section s04vb
+.section s04wa
+.section s04wb
+.section s04xa
+.section s04xb
+.section s04ya
+.section s04yb
+.section s04za
+.section s04zb
+.section s041a
+.section s041b
+.section s042a
+.section s042b
+.section s043a
+.section s043b
+.section s044a
+.section s044b
+.section s045a
+.section s045b
+.section s046a
+.section s046b
+.section s047a
+.section s047b
+.section s048a
+.section s048b
+.section s049a
+.section s049b
+.section s040a
+.section s040b
+.section s05aa
+.section s05ab
+.section s05ba
+.section s05bb
+.section s05ca
+.section s05cb
+.section s05da
+.section s05db
+.section s05ea
+.section s05eb
+.section s05fa
+.section s05fb
+.section s05ga
+.section s05gb
+.section s05ha
+.section s05hb
+.section s05ia
+.section s05ib
+.section s05ja
+.section s05jb
+.section s05ka
+.section s05kb
+.section s05la
+.section s05lb
+.section s05ma
+.section s05mb
+.section s05na
+.section s05nb
+.section s05oa
+.section s05ob
+.section s05pa
+.section s05pb
+.section s05qa
+.section s05qb
+.section s05ra
+.section s05rb
+.section s05sa
+.section s05sb
+.section s05ta
+.section s05tb
+.section s05ua
+.section s05ub
+.section s05va
+.section s05vb
+.section s05wa
+.section s05wb
+.section s05xa
+.section s05xb
+.section s05ya
+.section s05yb
+.section s05za
+.section s05zb
+.section s051a
+.section s051b
+.section s052a
+.section s052b
+.section s053a
+.section s053b
+.section s054a
+.section s054b
+.section s055a
+.section s055b
+.section s056a
+.section s056b
+.section s057a
+.section s057b
+.section s058a
+.section s058b
+.section s059a
+.section s059b
+.section s050a
+.section s050b
+.section s06aa
+.section s06ab
+.section s06ba
+.section s06bb
+.section s06ca
+.section s06cb
+.section s06da
+.section s06db
+.section s06ea
+.section s06eb
+.section s06fa
+.section s06fb
+.section s06ga
+.section s06gb
+.section s06ha
+.section s06hb
+.section s06ia
+.section s06ib
+.section s06ja
+.section s06jb
+.section s06ka
+.section s06kb
+.section s06la
+.section s06lb
+.section s06ma
+.section s06mb
+.section s06na
+.section s06nb
+.section s06oa
+.section s06ob
+.section s06pa
+.section s06pb
+.section s06qa
+.section s06qb
+.section s06ra
+.section s06rb
+.section s06sa
+.section s06sb
+.section s06ta
+.section s06tb
+.section s06ua
+.section s06ub
+.section s06va
+.section s06vb
+.section s06wa
+.section s06wb
+.section s06xa
+.section s06xb
+.section s06ya
+.section s06yb
+.section s06za
+.section s06zb
+.section s061a
+.section s061b
+.section s062a
+.section s062b
+.section s063a
+.section s063b
+.section s064a
+.section s064b
+.section s065a
+.section s065b
+.section s066a
+.section s066b
+.section s067a
+.section s067b
+.section s068a
+.section s068b
+.section s069a
+.section s069b
+.section s060a
+.section s060b
+.section s07aa
+.section s07ab
+.section s07ba
+.section s07bb
+.section s07ca
+.section s07cb
+.section s07da
+.section s07db
+.section s07ea
+.section s07eb
+.section s07fa
+.section s07fb
+.section s07ga
+.section s07gb
+.section s07ha
+.section s07hb
+.section s07ia
+.section s07ib
+.section s07ja
+.section s07jb
+.section s07ka
+.section s07kb
+.section s07la
+.section s07lb
+.section s07ma
+.section s07mb
+.section s07na
+.section s07nb
+.section s07oa
+.section s07ob
+.section s07pa
+.section s07pb
+.section s07qa
+.section s07qb
+.section s07ra
+.section s07rb
+.section s07sa
+.section s07sb
+.section s07ta
+.section s07tb
+.section s07ua
+.section s07ub
+.section s07va
+.section s07vb
+.section s07wa
+.section s07wb
+.section s07xa
+.section s07xb
+.section s07ya
+.section s07yb
+.section s07za
+.section s07zb
+.section s071a
+.section s071b
+.section s072a
+.section s072b
+.section s073a
+.section s073b
+.section s074a
+.section s074b
+.section s075a
+.section s075b
+.section s076a
+.section s076b
+.section s077a
+.section s077b
+.section s078a
+.section s078b
+.section s079a
+.section s079b
+.section s070a
+.section s070b
+.section s08aa
+.section s08ab
+.section s08ba
+.section s08bb
+.section s08ca
+.section s08cb
+.section s08da
+.section s08db
+.section s08ea
+.section s08eb
+.section s08fa
+.section s08fb
+.section s08ga
+.section s08gb
+.section s08ha
+.section s08hb
+.section s08ia
+.section s08ib
+.section s08ja
+.section s08jb
+.section s08ka
+.section s08kb
+.section s08la
+.section s08lb
+.section s08ma
+.section s08mb
+.section s08na
+.section s08nb
+.section s08oa
+.section s08ob
+.section s08pa
+.section s08pb
+.section s08qa
+.section s08qb
+.section s08ra
+.section s08rb
+.section s08sa
+.section s08sb
+.section s08ta
+.section s08tb
+.section s08ua
+.section s08ub
+.section s08va
+.section s08vb
+.section s08wa
+.section s08wb
+.section s08xa
+.section s08xb
+.section s08ya
+.section s08yb
+.section s08za
+.section s08zb
+.section s081a
+.section s081b
+.section s082a
+.section s082b
+.section s083a
+.section s083b
+.section s084a
+.section s084b
+.section s085a
+.section s085b
+.section s086a
+.section s086b
+.section s087a
+.section s087b
+.section s088a
+.section s088b
+.section s089a
+.section s089b
+.section s080a
+.section s080b
+.section s09aa
+.section s09ab
+.section s09ba
+.section s09bb
+.section s09ca
+.section s09cb
+.section s09da
+.section s09db
+.section s09ea
+.section s09eb
+.section s09fa
+.section s09fb
+.section s09ga
+.section s09gb
+.section s09ha
+.section s09hb
+.section s09ia
+.section s09ib
+.section s09ja
+.section s09jb
+.section s09ka
+.section s09kb
+.section s09la
+.section s09lb
+.section s09ma
+.section s09mb
+.section s09na
+.section s09nb
+.section s09oa
+.section s09ob
+.section s09pa
+.section s09pb
+.section s09qa
+.section s09qb
+.section s09ra
+.section s09rb
+.section s09sa
+.section s09sb
+.section s09ta
+.section s09tb
+.section s09ua
+.section s09ub
+.section s09va
+.section s09vb
+.section s09wa
+.section s09wb
+.section s09xa
+.section s09xb
+.section s09ya
+.section s09yb
+.section s09za
+.section s09zb
+.section s091a
+.section s091b
+.section s092a
+.section s092b
+.section s093a
+.section s093b
+.section s094a
+.section s094b
+.section s095a
+.section s095b
+.section s096a
+.section s096b
+.section s097a
+.section s097b
+.section s098a
+.section s098b
+.section s099a
+.section s099b
+.section s090a
+.section s090b
+.section s00aa
+.section s00ab
+.section s00ba
+.section s00bb
+.section s00ca
+.section s00cb
+.section s00da
+.section s00db
+.section s00ea
+.section s00eb
+.section s00fa
+.section s00fb
+.section s00ga
+.section s00gb
+.section s00ha
+.section s00hb
+.section s00ia
+.section s00ib
+.section s00ja
+.section s00jb
+.section s00ka
+.section s00kb
+.section s00la
+.section s00lb
+.section s00ma
+.section s00mb
+.section s00na
+.section s00nb
+.section s00oa
+.section s00ob
+.section s00pa
+.section s00pb
+.section s00qa
+.section s00qb
+.section s00ra
+.section s00rb
+.section s00sa
+.section s00sb
+.section s00ta
+.section s00tb
+.section s00ua
+.section s00ub
+.section s00va
+.section s00vb
+.section s00wa
+.section s00wb
+.section s00xa
+.section s00xb
+.section s00ya
+.section s00yb
+.section s00za
+.section s00zb
+.section s001a
+.section s001b
+.section s002a
+.section s002b
+.section s003a
+.section s003b
+.section s004a
+.section s004b
+.section s005a
+.section s005b
+.section s006a
+.section s006b
+.section s007a
+.section s007b
+.section s008a
+.section s008b
+.section s009a
+.section s009b
+.section s000a
+.section s000b
diff --git a/test/MC/ELF/merge.s b/test/MC/ELF/merge.s
index befc2bf..11a80ad 100644
--- a/test/MC/ELF/merge.s
+++ b/test/MC/ELF/merge.s
@@ -32,7 +32,7 @@ foo:
// CHECK-NEXT: ),
// Relocation 1 refers to symbol 6
-// CHECK-NEXT: # Relocation 0x00000001
+// CHECK-NEXT: # Relocation 1
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x0000000a)
@@ -40,7 +40,7 @@ foo:
// CHECK-NEXT: ),
// Relocation 2 refers to symbol 1
-// CHECK-NEXT: # Relocation 0x00000002
+// CHECK-NEXT: # Relocation 2
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym', 0x00000001)
// CHECK-NEXT: ('r_type', 0x0000000a
@@ -48,7 +48,7 @@ foo:
// CHECK-NEXT: ),
// Relocation 3 refers to symbol 2
-// CHECK-NEXT: # Relocation 0x00000003
+// CHECK-NEXT: # Relocation 3
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000004
@@ -56,7 +56,7 @@ foo:
// CHECK-NEXT: ),
// Relocation 4 refers to symbol 2
-// CHECK-NEXT: # Relocation 0x00000004
+// CHECK-NEXT: # Relocation 4
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x00000009
@@ -64,34 +64,34 @@ foo:
// CHECK-NEXT: ),
// Relocation 5 refers to symbol 8
-// CHECK-NEXT: # Relocation 0x00000005
-// CHECK-NEXT: (('r_offset', 0x00000023)
+// CHECK-NEXT: # Relocation 5
+// CHECK-NEXT: (('r_offset', 0x0000000000000023)
// CHECK-NEXT: ('r_sym', 0x00000008)
// CHECK-NEXT: ('r_type', 0x0000000b)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// Section 5 is "sec1"
-// CHECK: # Section 0x00000005
+// CHECK: # Section 5
// CHECK-NEXT: (('sh_name', 0x00000035) # '.sec1'
// Symbol number 1 is .Lfoo
-// CHECK: # Symbol 0x00000001
+// CHECK: # Symbol 1
// CHECK-NEXT: (('st_name', 0x00000001) # '.Lfoo'
// Symbol number 2 is foo
-// CHECK: # Symbol 0x00000002
+// CHECK: # Symbol 2
// CHECK-NEXT: (('st_name', 0x00000007) # 'foo'
// Symbol number 6 is section 5
-// CHECK: # Symbol 0x00000006
+// CHECK: # Symbol 6
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000003)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000005)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x3)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0005)
// Symbol number 8 is zed
-// CHECK: # Symbol 0x00000008
+// CHECK: # Symbol 8
// CHECK-NEXT: (('st_name', 0x0000000b) # 'zed'
diff --git a/test/MC/ELF/n_bytes.s b/test/MC/ELF/n_bytes.s
index 59d67bf..de66322 100644
--- a/test/MC/ELF/n_bytes.s
+++ b/test/MC/ELF/n_bytes.s
@@ -5,16 +5,16 @@
.8byte 42, 1, 2, 3
.int 42, 1, 2, 3
-// CHECK: # Section 0x00000001
+// CHECK: # Section 1
// CHECK-NEXT: (('sh_name', 0x00000001) # '.text'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000006)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000048)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000006)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000048)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '2a000100 02000300 2a000000 01000000 02000000 03000000 2a000000 00000000 01000000 00000000 02000000 00000000 03000000 00000000 2a000000 01000000 02000000 03000000')
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/noexec.s b/test/MC/ELF/noexec.s
index c4b7d98..d8b7b32 100644
--- a/test/MC/ELF/noexec.s
+++ b/test/MC/ELF/noexec.s
@@ -1,24 +1,24 @@
// RUN: llvm-mc -mc-no-exec-stack -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump | FileCheck %s
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: (('sh_name', 0x0000000c) # '.note.GNU-stack'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK: # Symbol 0x00000004
+// CHECK: # Symbol 4
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000003)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000004)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x3)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0004)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/norelocation.s b/test/MC/ELF/norelocation.s
index 0a0efe1..c639479 100644
--- a/test/MC/ELF/norelocation.s
+++ b/test/MC/ELF/norelocation.s
@@ -5,14 +5,14 @@ bar:
// CHECK: ('sh_name', 0x00000001) # '.text'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000006)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000005)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000006)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000005)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', 'e8000000 00')
// CHECK-NOT: .rela.text
// CHECK: shstrtab
diff --git a/test/MC/ELF/org.s b/test/MC/ELF/org.s
index c073fa5..3afc364 100644
--- a/test/MC/ELF/org.s
+++ b/test/MC/ELF/org.s
@@ -10,4 +10,4 @@ foo:
// CHECK-NEXT: ('sh_flags',
// CHECK-NEXT: ('sh_addr',
// CHECK-NEXT: ('sh_offset'
-// CHECK-NEXT: ('sh_size', 0x00000014)
+// CHECK-NEXT: ('sh_size', 0x0000000000000014)
diff --git a/test/MC/ELF/pic-diff.s b/test/MC/ELF/pic-diff.s
index c2f96c2..2c68f6c 100644
--- a/test/MC/ELF/pic-diff.s
+++ b/test/MC/ELF/pic-diff.s
@@ -1,20 +1,20 @@
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump | FileCheck %s
// CHECK: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x0000000c)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x000000000000000c)
// CHECK-NEXT: ('r_sym', 0x00000005)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000008)
+// CHECK-NEXT: ('r_addend', 0x0000000000000008)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
-// CHECK: # Symbol 0x00000005
+// CHECK: # Symbol 5
// CHECK-NEXT: (('st_name', 0x00000005) # 'baz'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/plt.s b/test/MC/ELF/plt.s
index 7d0073c..7d78e23 100644
--- a/test/MC/ELF/plt.s
+++ b/test/MC/ELF/plt.s
@@ -5,7 +5,7 @@
jmp foo@PLT
// CHECK: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
+// CHECK-NEXT: # Relocation 0
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym',
// CHECK-NEXT: ('r_type', 0x00000004)
diff --git a/test/MC/ELF/pr9292.s b/test/MC/ELF/pr9292.s
index a198fed..05f377f 100644
--- a/test/MC/ELF/pr9292.s
+++ b/test/MC/ELF/pr9292.s
@@ -8,19 +8,19 @@ mov %eax,bar
// CHECK: (('st_name', 0x00000005) # 'bar'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000005
+// CHECK-NEXT: # Symbol 5
// CHECK-NEXT: (('st_name', 0x00000001) # 'foo'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/relax.s b/test/MC/ELF/relax.s
index 2c0e285..0b5d24f 100644
--- a/test/MC/ELF/relax.s
+++ b/test/MC/ELF/relax.s
@@ -13,15 +13,15 @@ foo:
// CHECK: ('sh_name', 0x00000001) # '.text'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000006)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000006)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000006)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000006)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', 'ebfeebfc ebfa')
-// CHECK: # Symbol 0x00000006
+// CHECK: # Symbol 6
// CHECK-NEXT: (('st_name', 0x00000005) # 'foo'
diff --git a/test/MC/ELF/relocation-386.s b/test/MC/ELF/relocation-386.s
index 25f3450..4421763 100644
--- a/test/MC/ELF/relocation-386.s
+++ b/test/MC/ELF/relocation-386.s
@@ -3,190 +3,190 @@
// Test that we produce the correct relocation types and that the relocations
// correctly point to the section or the symbol.
-// CHECK: # Relocation 0x00000000
+// CHECK: # Relocation 0
// CHECK-NEXT: (('r_offset', 0x00000002)
-// CHECK-NEXT: ('r_sym', 0x00000001)
-// CHECK-NEXT: ('r_type', 0x00000009)
+// CHECK-NEXT: ('r_sym', 0x000001)
+// CHECK-NEXT: ('r_type', 0x09)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000001
+// CHECK-NEXT: # Relocation 1
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym',
-// CHECK-NEXT: ('r_type', 0x00000004)
+// CHECK-NEXT: ('r_type', 0x04)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000002
+// CHECK-NEXT: # Relocation 2
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym',
-// CHECK-NEXT: ('r_type', 0x0000000a)
+// CHECK-NEXT: ('r_type', 0x0a)
// CHECK-NEXT: ),
// Relocation 3 (bar3@GOTOFF) is done with symbol 7 (bss)
-// CHECK-NEXT: # Relocation 0x00000003
+// CHECK-NEXT: # Relocation 3
// CHECK-NEXT: (('r_offset',
-// CHECK-NEXT: ('r_sym', 0x00000007
+// CHECK-NEXT: ('r_sym', 0x000007
// CHECK-NEXT: ('r_type',
// CHECK-NEXT: ),
// Relocation 4 (bar2@GOT) is of type R_386_GOT32
-// CHECK-NEXT: # Relocation 0x00000004
+// CHECK-NEXT: # Relocation 4
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym',
-// CHECK-NEXT: ('r_type', 0x00000003
+// CHECK-NEXT: ('r_type', 0x03
// CHECK-NEXT: ),
// Relocation 5 (foo@TLSGD) is of type R_386_TLS_GD
-// CHECK-NEXT: # Relocation 0x00000005
+// CHECK-NEXT: # Relocation 5
// CHECK-NEXT: (('r_offset', 0x00000020)
-// CHECK-NEXT: ('r_sym', 0x0000000d)
-// CHECK-NEXT: ('r_type', 0x00000012)
+// CHECK-NEXT: ('r_sym', 0x00000d)
+// CHECK-NEXT: ('r_type', 0x12)
// CHECK-NEXT: ),
// Relocation 6 ($foo@TPOFF) is of type R_386_TLS_LE_32
-// CHECK-NEXT: # Relocation 0x00000006
+// CHECK-NEXT: # Relocation 6
// CHECK-NEXT: (('r_offset', 0x00000025)
-// CHECK-NEXT: ('r_sym', 0x0000000d)
-// CHECK-NEXT: ('r_type', 0x00000022)
+// CHECK-NEXT: ('r_sym', 0x00000d)
+// CHECK-NEXT: ('r_type', 0x22)
// CHECK-NEXT: ),
// Relocation 7 (foo@INDNTPOFF) is of type R_386_TLS_IE
-// CHECK-NEXT: # Relocation 0x00000007
+// CHECK-NEXT: # Relocation 7
// CHECK-NEXT: (('r_offset', 0x0000002b)
-// CHECK-NEXT: ('r_sym', 0x0000000d)
-// CHECK-NEXT: ('r_type', 0x0000000f)
+// CHECK-NEXT: ('r_sym', 0x00000d)
+// CHECK-NEXT: ('r_type', 0x0f)
// CHECK-NEXT: ),
// Relocation 8 (foo@NTPOFF) is of type R_386_TLS_LE
-// CHECK-NEXT: # Relocation 0x00000008
+// CHECK-NEXT: # Relocation 8
// CHECK-NEXT: (('r_offset', 0x00000031)
-// CHECK-NEXT: ('r_sym', 0x0000000d)
-// CHECK-NEXT: ('r_type', 0x00000011)
+// CHECK-NEXT: ('r_sym', 0x00000d)
+// CHECK-NEXT: ('r_type', 0x11)
// CHECK-NEXT: ),
// Relocation 9 (foo@GOTNTPOFF) is of type R_386_TLS_GOTIE
-// CHECK-NEXT: # Relocation 0x00000009
+// CHECK-NEXT: # Relocation 9
// CHECK-NEXT: (('r_offset', 0x00000037)
-// CHECK-NEXT: ('r_sym', 0x0000000d)
-// CHECK-NEXT: ('r_type', 0x00000010)
+// CHECK-NEXT: ('r_sym', 0x00000d)
+// CHECK-NEXT: ('r_type', 0x10)
// CHECK-NEXT: ),
// Relocation 10 (foo@TLSLDM) is of type R_386_TLS_LDM
-// CHECK-NEXT: # Relocation 0x0000000a
+// CHECK-NEXT: # Relocation 10
// CHECK-NEXT: (('r_offset', 0x0000003d)
-// CHECK-NEXT: ('r_sym', 0x0000000d)
-// CHECK-NEXT: ('r_type', 0x00000013)
+// CHECK-NEXT: ('r_sym', 0x00000d)
+// CHECK-NEXT: ('r_type', 0x13)
// CHECK-NEXT: ),
// Relocation 11 (foo@DTPOFF) is of type R_386_TLS_LDO_32
-// CHECK-NEXT: # Relocation 0x0000000b
+// CHECK-NEXT: # Relocation 11
// CHECK-NEXT: (('r_offset', 0x00000043)
-// CHECK-NEXT: ('r_sym', 0x0000000d)
-// CHECK-NEXT: ('r_type', 0x00000020)
+// CHECK-NEXT: ('r_sym', 0x00000d)
+// CHECK-NEXT: ('r_type', 0x20)
// CHECK-NEXT: ),
// Relocation 12 (calll 4096) is of type R_386_PC32
-// CHECK-NEXT: # Relocation 0x0000000c
+// CHECK-NEXT: # Relocation 12
// CHECK-NEXT: (('r_offset', 0x00000048)
-// CHECK-NEXT: ('r_sym', 0x00000000)
-// CHECK-NEXT: ('r_type', 0x00000002)
+// CHECK-NEXT: ('r_sym', 0x000000)
+// CHECK-NEXT: ('r_type', 0x02)
// CHECK-NEXT: ),
// Relocation 13 (zed@GOT) is of type R_386_GOT32 and uses the symbol
-// CHECK-NEXT: # Relocation 0x0000000d
+// CHECK-NEXT: # Relocation 13
// CHECK-NEXT: (('r_offset', 0x0000004e)
-// CHECK-NEXT: ('r_sym', 0x00000004)
-// CHECK-NEXT: ('r_type', 0x00000003)
+// CHECK-NEXT: ('r_sym', 0x000004)
+// CHECK-NEXT: ('r_type', 0x03)
// CHECK-NEXT: ),
// Relocation 14 (zed@GOTOFF) is of type R_386_GOTOFF and uses the symbol
-// CHECK-NEXT: # Relocation 0x0000000e
+// CHECK-NEXT: # Relocation 14
// CHECK-NEXT: (('r_offset', 0x00000054)
-// CHECK-NEXT: ('r_sym', 0x00000004)
-// CHECK-NEXT: ('r_type', 0x00000009)
+// CHECK-NEXT: ('r_sym', 0x000004)
+// CHECK-NEXT: ('r_type', 0x09)
// CHECK-NEXT: ),
// Relocation 15 (zed@INDNTPOFF) is of type R_386_TLS_IE and uses the symbol
-// CHECK-NEXT: # Relocation 0x0000000f
+// CHECK-NEXT: # Relocation 15
// CHECK-NEXT: (('r_offset', 0x0000005a)
-// CHECK-NEXT: ('r_sym', 0x00000004)
-// CHECK-NEXT: ('r_type', 0x0000000f)
+// CHECK-NEXT: ('r_sym', 0x000004)
+// CHECK-NEXT: ('r_type', 0x0f)
// CHECK-NEXT: ),
// Relocation 16 (zed@NTPOFF) is of type R_386_TLS_LE and uses the symbol
-// CHECK-NEXT: # Relocation 0x00000010
+// CHECK-NEXT: # Relocation 16
// CHECK-NEXT: (('r_offset', 0x00000060)
-// CHECK-NEXT: ('r_sym', 0x00000004)
-// CHECK-NEXT: ('r_type', 0x00000011)
+// CHECK-NEXT: ('r_sym', 0x000004)
+// CHECK-NEXT: ('r_type', 0x11)
// CHECK-NEXT: ),
// Relocation 17 (zed@GOTNTPOFF) is of type R_386_TLS_GOTIE and uses the symbol
-// CHECK-NEXT: # Relocation 0x00000011
+// CHECK-NEXT: # Relocation 17
// CHECK-NEXT: (('r_offset', 0x00000066)
-// CHECK-NEXT: ('r_sym', 0x00000004)
-// CHECK-NEXT: ('r_type', 0x00000010)
+// CHECK-NEXT: ('r_sym', 0x000004)
+// CHECK-NEXT: ('r_type', 0x10)
// CHECK-NEXT: ),
// Relocation 18 (zed@PLT) is of type R_386_PLT32 and uses the symbol
-// CHECK-NEXT: # Relocation 0x00000012
+// CHECK-NEXT: # Relocation 18
// CHECK-NEXT: (('r_offset', 0x0000006b)
-// CHECK-NEXT: ('r_sym', 0x00000004)
-// CHECK-NEXT: ('r_type', 0x00000004)
+// CHECK-NEXT: ('r_sym', 0x000004)
+// CHECK-NEXT: ('r_type', 0x04)
// CHECK-NEXT: ),
// Relocation 19 (zed@TLSGD) is of type R_386_TLS_GD and uses the symbol
-// CHECK-NEXT: # Relocation 0x00000013
+// CHECK-NEXT: # Relocation 19
// CHECK-NEXT: (('r_offset', 0x00000071)
-// CHECK-NEXT: ('r_sym', 0x00000004)
-// CHECK-NEXT: ('r_type', 0x00000012)
+// CHECK-NEXT: ('r_sym', 0x000004)
+// CHECK-NEXT: ('r_type', 0x12)
// CHECK-NEXT: ),
// Relocation 20 (zed@TLSLDM) is of type R_386_TLS_LDM and uses the symbol
-// CHECK-NEXT: # Relocation 0x00000014
+// CHECK-NEXT: # Relocation 20
// CHECK-NEXT: (('r_offset', 0x00000077)
-// CHECK-NEXT: ('r_sym', 0x00000004)
-// CHECK-NEXT: ('r_type', 0x00000013)
+// CHECK-NEXT: ('r_sym', 0x000004)
+// CHECK-NEXT: ('r_type', 0x13)
// CHECK-NEXT: ),
// Relocation 21 (zed@TPOFF) is of type R_386_TLS_LE_32 and uses the symbol
-// CHECK-NEXT:# Relocation 0x00000015
+// CHECK-NEXT:# Relocation 21
// CHECK-NEXT: (('r_offset', 0x0000007d)
-// CHECK-NEXT: ('r_sym', 0x00000004)
-// CHECK-NEXT: ('r_type', 0x00000022)
+// CHECK-NEXT: ('r_sym', 0x000004)
+// CHECK-NEXT: ('r_type', 0x22)
// CHECK-NEXT: ),
// Relocation 22 (zed@DTPOFF) is of type R_386_TLS_LDO_32 and uses the symbol
-// CHECK-NEXT: Relocation 0x00000016
+// CHECK-NEXT: Relocation 22
// CHECK-NEXT: (('r_offset', 0x00000083)
-// CHECK-NEXT: ('r_sym', 0x00000004)
-// CHECK-NEXT: ('r_type', 0x00000020)
+// CHECK-NEXT: ('r_sym', 0x000004)
+// CHECK-NEXT: ('r_type', 0x20)
// CHECK-NEXT: ),
// Relocation 23 ($bar) is of type R_386_32 and uses the section
-// CHECK-NEXT: Relocation 0x00000017
+// CHECK-NEXT: Relocation 23
// CHECK-NEXT: (('r_offset',
// CHECK-NEXT: ('r_sym',
-// CHECK-NEXT: ('r_type', 0x00000001)
+// CHECK-NEXT: ('r_type', 0x01)
// CHECK-NEXT: ),
// Relocation 24 (foo@GOTTPOFF(%edx)) is of type R_386_TLS_IE_32 and uses the
// symbol
-// CHECK-NEXT: Relocation 0x00000018
+// CHECK-NEXT: Relocation 24
// CHECK-NEXT: (('r_offset', 0x0000008e)
-// CHECK-NEXT: ('r_sym', 0x0000000d)
-// CHECK-NEXT: ('r_type', 0x00000021)
+// CHECK-NEXT: ('r_sym', 0x00000d)
+// CHECK-NEXT: ('r_type', 0x21)
// CHECK-NEXT: ),
// Section 4 is bss
-// CHECK: # Section 0x00000004
+// CHECK: # Section 4
// CHECK-NEXT: (('sh_name', 0x0000000b) # '.bss'
-// CHECK: # Symbol 0x00000001
+// CHECK: # Symbol 1
// CHECK-NEXT: (('st_name', 0x00000005) # '.Lfoo'
// Symbol 4 is zed
-// CHECK: # Symbol 0x00000004
+// CHECK: # Symbol 4
// CHECK-NEXT: (('st_name', 0x00000035) # 'zed'
// CHECK-NEXT: ('st_value', 0x00000000)
// CHECK-NEXT: ('st_size', 0x00000000)
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000005)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0005)
// Symbol 7 is section 4
-// CHECK: # Symbol 0x00000007
+// CHECK: # Symbol 7
// CHECK-NEXT: (('st_name', 0x00000000) # ''
// CHECK-NEXT: ('st_value', 0x00000000)
// CHECK-NEXT: ('st_size', 0x00000000)
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000003)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000004)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x3)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0004)
.text
diff --git a/test/MC/ELF/relocation-pc.s b/test/MC/ELF/relocation-pc.s
index 36212cb..b6279c3 100644
--- a/test/MC/ELF/relocation-pc.s
+++ b/test/MC/ELF/relocation-pc.s
@@ -5,29 +5,29 @@
loope 0 # R_X86_64_PC8
jmp -256 # R_X86_64_PC32
-// CHECK: # Section 0x00000002
+// CHECK: # Section 2
// CHECK-NEXT: (('sh_name', 0x00000001) # '.rela.text'
// CHECK-NEXT: ('sh_type', 0x00000004)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x000002e8)
-// CHECK-NEXT: ('sh_size', 0x00000030)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x00000000000002e8)
+// CHECK-NEXT: ('sh_size', 0x0000000000000030)
// CHECK-NEXT: ('sh_link', 0x00000006)
// CHECK-NEXT: ('sh_info', 0x00000001)
-// CHECK-NEXT: ('sh_addralign', 0x00000008)
-// CHECK-NEXT: ('sh_entsize', 0x00000018)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000018)
// CHECK-NEXT: ('_relocations', [
-// CHECK-NEXT: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000001)
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000001)
// CHECK-NEXT: ('r_sym', 0x00000000)
// CHECK-NEXT: ('r_type', 0x0000000f)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000001
-// CHECK-NEXT: (('r_offset', 0x00000003)
+// CHECK-NEXT: # Relocation 1
+// CHECK-NEXT: (('r_offset', 0x0000000000000003)
// CHECK-NEXT: ('r_sym', 0x00000000)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT: ])
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/relocation.s b/test/MC/ELF/relocation.s
index 2760232..5db213b 100644
--- a/test/MC/ELF/relocation.s
+++ b/test/MC/ELF/relocation.s
@@ -20,102 +20,102 @@ bar:
addq $bar,%rax # R_X86_64_32S
-// CHECK: # Section 0x00000001
+// CHECK: # Section 1
// CHECK: (('sh_name', 0x00000006) # '.text'
-// CHECK: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000001)
+// CHECK: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000001)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x0000000a)
// CHECK-NEXT: ('r_addend',
-// CHECK: # Relocation 0x00000001
-// CHECK-NEXT: (('r_offset', 0x00000008)
+// CHECK: # Relocation 1
+// CHECK-NEXT: (('r_offset', 0x0000000000000008)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x0000000b)
// CHECK-NEXT: ('r_addend',
-// CHECK: # Relocation 0x00000002
-// CHECK-NEXT: (('r_offset', 0x00000013)
+// CHECK: # Relocation 2
+// CHECK-NEXT: (('r_offset', 0x0000000000000013)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x0000000b)
// CHECK-NEXT: ('r_addend',
-// CHECK: # Relocation 0x00000003
-// CHECK-NEXT: (('r_offset', 0x0000001a)
+// CHECK: # Relocation 3
+// CHECK-NEXT: (('r_offset', 0x000000000000001a)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x0000000b)
// CHECK-NEXT: ('r_addend',
-// CHECK: # Relocation 0x00000004
-// CHECK-NEXT: (('r_offset', 0x00000022)
+// CHECK: # Relocation 4
+// CHECK-NEXT: (('r_offset', 0x0000000000000022)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x0000000b)
// CHECK-NEXT: ('r_addend',
-// CHECK: # Relocation 0x00000005
-// CHECK-NEXT: (('r_offset', 0x00000026)
+// CHECK: # Relocation 5
+// CHECK-NEXT: (('r_offset', 0x0000000000000026)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x0000000a)
// CHECK-NEXT: ('r_addend',
-// CHECK: # Relocation 0x00000006
-// CHECK-NEXT: (('r_offset', 0x0000002d)
+// CHECK: # Relocation 6
+// CHECK-NEXT: (('r_offset', 0x000000000000002d)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x00000016)
-// CHECK-NEXT: ('r_addend', 0xfffffffc)
+// CHECK-NEXT: ('r_addend', 0xfffffffffffffffc)
-// CHECK: # Relocation 0x00000007
-// CHECK-NEXT: (('r_offset', 0x00000034)
+// CHECK: # Relocation 7
+// CHECK-NEXT: (('r_offset', 0x0000000000000034)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x00000013)
-// CHECK-NEXT: ('r_addend', 0xfffffffc)
+// CHECK-NEXT: ('r_addend', 0xfffffffffffffffc)
-// CHECK: # Relocation 0x00000008
-// CHECK-NEXT: (('r_offset', 0x0000003b)
+// CHECK: # Relocation 8
+// CHECK-NEXT: (('r_offset', 0x000000000000003b)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x00000017)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
-// CHECK: # Relocation 0x00000009
-// CHECK-NEXT: (('r_offset', 0x00000042)
+// CHECK: # Relocation 9
+// CHECK-NEXT: (('r_offset', 0x0000000000000042)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x00000014)
-// CHECK-NEXT: ('r_addend', 0xfffffffc)
+// CHECK-NEXT: ('r_addend', 0xfffffffffffffffc)
-// CHECK: # Relocation 0x0000000a
-// CHECK-NEXT: (('r_offset', 0x00000049)
+// CHECK: # Relocation 10
+// CHECK-NEXT: (('r_offset', 0x0000000000000049)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x00000015)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
-// CHECK: # Relocation 0x0000000b
-// CHECK-NEXT: (('r_offset', 0x0000004e)
+// CHECK: # Relocation 11
+// CHECK-NEXT: (('r_offset', 0x000000000000004e)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x0000000b)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
-// CHECK: # Relocation 0x0000000c
-// CHECK-NEXT: (('r_offset', 0x00000055)
+// CHECK: # Relocation 12
+// CHECK-NEXT: (('r_offset', 0x0000000000000055)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0xfffffffc)
+// CHECK-NEXT: ('r_addend', 0xfffffffffffffffc)
-// CHECK: # Relocation 0x0000000d
-// CHECK-NEXT: (('r_offset', 0x0000005c)
+// CHECK: # Relocation 13
+// CHECK-NEXT: (('r_offset', 0x000000000000005c)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0x0000005c)
+// CHECK-NEXT: ('r_addend', 0x000000000000005c)
-// CHECK: # Relocation 0x0000000e
-// CHECK-NEXT: (('r_offset', 0x00000063)
+// CHECK: # Relocation 14
+// CHECK-NEXT: (('r_offset', 0x0000000000000063)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x0000000b)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
-// CHECK: # Symbol 0x00000002
+// CHECK: # Symbol 2
// CHECK: (('st_name', 0x00000000) # ''
-// CHECK: ('st_bind', 0x00000000)
-// CHECK: ('st_type', 0x00000003)
-// CHECK: ('st_other', 0x00000000)
-// CHECK: ('st_shndx', 0x00000001)
+// CHECK: ('st_bind', 0x0)
+// CHECK: ('st_type', 0x3)
+// CHECK: ('st_other', 0x00)
+// CHECK: ('st_shndx', 0x0001)
diff --git a/test/MC/ELF/rename.s b/test/MC/ELF/rename.s
index e7cedd0..241aa05 100644
--- a/test/MC/ELF/rename.s
+++ b/test/MC/ELF/rename.s
@@ -16,31 +16,31 @@ defined3:
.global defined1
// Section 1 is .text
-// CHECK: # Section 0x00000001
+// CHECK: # Section 1
// CHECK-NEXT: (('sh_name', 0x00000006) # '.text'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000006)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000040)
-// CHECK-NEXT: ('sh_size', 0x00000004)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000006)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
+// CHECK-NEXT: ('sh_size', 0x0000000000000004)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000004)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000004)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// The relocation uses symbol 2
-// CHECK: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000000)
+// CHECK: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000000)
// CHECK-NEXT: ('r_sym', 0x00000002)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// Symbol 2 is section 1
-// CHECK: # Symbol 0x00000002
+// CHECK: # Symbol 2
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000003)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x3)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
diff --git a/test/MC/ELF/section.s b/test/MC/ELF/section.s
index 5fb5525..c71e1a7 100644
--- a/test/MC/ELF/section.s
+++ b/test/MC/ELF/section.s
@@ -21,63 +21,63 @@
// CHECK: (('sh_name', 0x00000012) # '.init'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000006)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000050)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000006)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000050)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Section 0x0000000b
+// CHECK-NEXT: # Section 11
// CHECK-NEXT: (('sh_name', 0x00000048) # '.fini'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000006)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000050)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000006)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000050)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Section 0x0000000c
+// CHECK-NEXT: # Section 12
// CHECK-NEXT: (('sh_name', 0x00000076) # '.rodata'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000050)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000050)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Section 0x0000000d
+// CHECK-NEXT: # Section 13
// CHECK-NEXT: (('sh_name', 0x00000058) # 'zed'
// CHECK-NEXT: ('sh_type', 0x00000001)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000050)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000050)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ),
.section .note.test,"",@note
// CHECK: (('sh_name', 0x00000007) # '.note.test'
// CHECK-NEXT: ('sh_type', 0x00000007)
-// CHECK-NEXT: ('sh_flags', 0x00000000)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000050)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000000)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000050)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ),
// Test that we can parse these
@@ -92,14 +92,14 @@ bar:
// CHECK: (('sh_name', 0x0000004e) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x70000001)
-// CHECK-NEXT: ('sh_flags', 0x00000002)
-// CHECK-NEXT: ('sh_addr', 0x00000000)
-// CHECK-NEXT: ('sh_offset', 0x00000050)
-// CHECK-NEXT: ('sh_size', 0x00000000)
+// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
+// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
+// CHECK-NEXT: ('sh_offset', 0x0000000000000050)
+// CHECK-NEXT: ('sh_size', 0x0000000000000000)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
-// CHECK-NEXT: ('sh_addralign', 0x00000001)
-// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x0000000000000001)
+// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ),
// Test that we handle the strings like gas
diff --git a/test/MC/ELF/set.s b/test/MC/ELF/set.s
index 69d6c91..2258b19 100644
--- a/test/MC/ELF/set.s
+++ b/test/MC/ELF/set.s
@@ -5,10 +5,10 @@
.set kernbase,0xffffffff80000000
// CHECK: (('st_name', 0x00000001) # 'kernbase'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x0000fff1)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0xfff1)
// CHECK-NEXT: ('st_value', 0xffffffff80000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
@@ -25,10 +25,10 @@
// Test that there is an undefined reference to bar
// CHECK: (('st_name', 0x0000000a) # 'bar'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/symref.s b/test/MC/ELF/symref.s
index d945c82..2dfa058 100644
--- a/test/MC/ELF/symref.s
+++ b/test/MC/ELF/symref.s
@@ -22,143 +22,143 @@ defined3:
global1:
-// CHECK: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000000)
+// CHECK: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000000)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000001
-// CHECK-NEXT: (('r_offset', 0x00000004)
+// CHECK-NEXT: # Relocation 1
+// CHECK-NEXT: (('r_offset', 0x0000000000000004)
// CHECK-NEXT: ('r_sym', 0x0000000b)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000002
-// CHECK-NEXT: (('r_offset', 0x00000008)
+// CHECK-NEXT: # Relocation 2
+// CHECK-NEXT: (('r_offset', 0x0000000000000008)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000003
-// CHECK-NEXT: (('r_offset', 0x0000000c)
+// CHECK-NEXT: # Relocation 3
+// CHECK-NEXT: (('r_offset', 0x000000000000000c)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000004
-// CHECK-NEXT: (('r_offset', 0x00000010)
+// CHECK-NEXT: # Relocation 4
+// CHECK-NEXT: (('r_offset', 0x0000000000000010)
// CHECK-NEXT: ('r_sym', 0x0000000c)
// CHECK-NEXT: ('r_type', 0x0000000a)
-// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ('r_addend', 0x0000000000000000)
// CHECK-NEXT: ),
// CHECK-NEXT:])
-// CHECK: # Symbol 0x00000001
+// CHECK: # Symbol 1
// CHECK-NEXT: (('st_name', 0x00000013) # 'bar1@zed'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000002
+// CHECK-NEXT: # Symbol 2
// CHECK-NEXT: (('st_name', 0x00000025) # 'bar3@@zed'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000003
+// CHECK-NEXT: # Symbol 3
// CHECK-NEXT: (('st_name', 0x0000002f) # 'bar5@@zed'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000004
+// CHECK-NEXT: # Symbol 4
// CHECK-NEXT: (('st_name', 0x00000001) # 'defined1'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000005
+// CHECK-NEXT: # Symbol 5
// CHECK-NEXT: (('st_name', 0x0000000a) # 'defined2'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000006
+// CHECK-NEXT: # Symbol 6
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000003)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x3)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000007
+// CHECK-NEXT: # Symbol 7
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000003)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000003)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x3)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0003)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000008
+// CHECK-NEXT: # Symbol 8
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000003)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000004)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x3)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0004)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000009
+// CHECK-NEXT: # Symbol 9
// CHECK-NEXT: (('st_name', 0x0000004a) # 'g1@@zed'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000014)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x0000000a
+// CHECK-NEXT: # Symbol 10
// CHECK-NEXT: (('st_name', 0x00000042) # 'global1'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000014)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x0000000b
+// CHECK-NEXT: # Symbol 11
// CHECK-NEXT: (('st_name', 0x0000001c) # 'bar2@zed'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x0000000c
+// CHECK-NEXT: # Symbol 12
// CHECK-NEXT: (('st_name', 0x00000039) # 'bar6@zed'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/tls-i386.s b/test/MC/ELF/tls-i386.s
index c754121..197418d 100644
--- a/test/MC/ELF/tls-i386.s
+++ b/test/MC/ELF/tls-i386.s
@@ -13,62 +13,62 @@
// CHECK: (('st_name', 0x00000001) # 'foo1'
// CHECK-NEXT: ('st_value', 0x00000000)
// CHECK-NEXT: ('st_size', 0x00000000)
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000006
+// CHECK-NEXT: # Symbol 6
// CHECK-NEXT: (('st_name', 0x00000006) # 'foo2'
// CHECK-NEXT: ('st_value', 0x00000000)
// CHECK-NEXT: ('st_size', 0x00000000)
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000007
+// CHECK-NEXT: # Symbol 7
// CHECK-NEXT: (('st_name', 0x0000000b) # 'foo3'
// CHECK-NEXT: ('st_value', 0x00000000)
// CHECK-NEXT: ('st_size', 0x00000000)
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000008
+// CHECK-NEXT: # Symbol 8
// CHECK-NEXT: (('st_name', 0x00000010) # 'foo4'
// CHECK-NEXT: ('st_value', 0x00000000)
// CHECK-NEXT: ('st_size', 0x00000000)
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000009
+// CHECK-NEXT: # Symbol 9
// CHECK-NEXT: (('st_name', 0x00000015) # 'foo5'
// CHECK-NEXT: ('st_value', 0x00000000)
// CHECK-NEXT: ('st_size', 0x00000000)
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x0000000a
+// CHECK-NEXT: # Symbol 10
// CHECK-NEXT: (('st_name', 0x0000001a) # 'foo6'
// CHECK-NEXT: ('st_value', 0x00000000)
// CHECK-NEXT: ('st_size', 0x00000000)
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x0000000b
+// CHECK-NEXT: # Symbol 11
// CHECK-NEXT: (('st_name', 0x0000001f) # 'foo7'
// CHECK-NEXT: ('st_value', 0x00000000)
// CHECK-NEXT: ('st_size', 0x00000000)
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/tls.s b/test/MC/ELF/tls.s
index f9d6425..d6d7de6 100644
--- a/test/MC/ELF/tls.s
+++ b/test/MC/ELF/tls.s
@@ -11,38 +11,38 @@ foobar:
.long 43
// CHECK: (('st_name', 0x00000010) # 'foobar'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000005)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0005)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK: # Symbol 0x00000007
+// CHECK: # Symbol 7
// CHECK-NEXT: (('st_name', 0x00000001) # 'foo1'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000008
+// CHECK-NEXT: # Symbol 8
// CHECK-NEXT: (('st_name', 0x00000006) # 'foo2'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000009
+// CHECK-NEXT: # Symbol 9
// CHECK-NEXT: (('st_name', 0x0000000b) # 'foo3'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000006)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x6)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/type.s b/test/MC/ELF/type.s
index 4b98c02..2b25a6b 100644
--- a/test/MC/ELF/type.s
+++ b/test/MC/ELF/type.s
@@ -12,21 +12,21 @@ bar:
// Test that gnu_unique_object is accepted.
.type zed,@gnu_unique_object
-// CHECK: # Symbol 0x00000004
+// CHECK: # Symbol 4
// CHECK-NEXT: (('st_name', 0x00000005) # 'bar'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000001)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x1)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000005
+// CHECK-NEXT: # Symbol 5
// CHECK-NEXT: (('st_name', 0x00000001) # 'foo'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000002)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x2)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/undef.s b/test/MC/ELF/undef.s
index fc3a2d2..e377c63 100644
--- a/test/MC/ELF/undef.s
+++ b/test/MC/ELF/undef.s
@@ -20,26 +20,26 @@
movsd .Lsym8(%rip), %xmm1
// CHECK: ('_symbols', [
-// CHECK-NEXT: # Symbol 0x00000000
+// CHECK-NEXT: # Symbol 0
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK: # Symbol 0x00000001
+// CHECK: # Symbol 1
// CHECK-NEXT: (('st_name', 0x0000000d) # '.Lsym8'
-// CHECK: # Symbol 0x00000002
+// CHECK: # Symbol 2
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK: # Symbol 0x00000003
+// CHECK: # Symbol 3
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK: # Symbol 0x00000004
+// CHECK: # Symbol 4
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK: # Symbol 0x00000005
+// CHECK: # Symbol 5
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK: # Symbol 0x00000006
+// CHECK: # Symbol 6
// CHECK-NEXT: (('st_name', 0x00000001) # '.Lsym1'
-// CHECK: # Symbol 0x00000007
+// CHECK: # Symbol 7
// CHECK-NEXT: (('st_name', 0x00000008) # 'sym6'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000001)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x1)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/undef2.s b/test/MC/ELF/undef2.s
index 6ce269b..6f971c5 100644
--- a/test/MC/ELF/undef2.s
+++ b/test/MC/ELF/undef2.s
@@ -6,5 +6,5 @@
// CHECK: ('_symbols', [
// CHECK: (('st_name', 0x00000001) # '.Lfoo'
-// CHECK-NEXT: ('st_bind', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
// CHECK: (('sh_name', 0x0000001b) # '.strtab'
diff --git a/test/MC/ELF/weak-relocation.s b/test/MC/ELF/weak-relocation.s
index ef331d7..88e841e 100644
--- a/test/MC/ELF/weak-relocation.s
+++ b/test/MC/ELF/weak-relocation.s
@@ -7,9 +7,9 @@ foo:
bar:
call foo
-//CHECK: # Relocation 0x00000000
-//CHECK-NEXT: (('r_offset', 0x00000001)
+//CHECK: # Relocation 0
+//CHECK-NEXT: (('r_offset', 0x0000000000000001)
//CHECK-NEXT: ('r_sym', 0x00000005)
//CHECK-NEXT: ('r_type', 0x00000002)
-//CHECK-NEXT: ('r_addend', 0xfffffffc)
+//CHECK-NEXT: ('r_addend', 0xfffffffffffffffc)
//CHECK-NEXT: ),
diff --git a/test/MC/ELF/weak.s b/test/MC/ELF/weak.s
index 67e9b18..07a83913 100644
--- a/test/MC/ELF/weak.s
+++ b/test/MC/ELF/weak.s
@@ -9,21 +9,21 @@
.weak bar
bar:
-//CHECK: # Symbol 0x00000004
+//CHECK: # Symbol 4
//CHECK-NEXT: (('st_name', 0x00000005) # 'bar'
-//CHECK-NEXT: ('st_bind', 0x00000002)
-//CHECK-NEXT: ('st_type', 0x00000000)
-//CHECK-NEXT: ('st_other', 0x00000000)
-//CHECK-NEXT: ('st_shndx', 0x00000001)
+//CHECK-NEXT: ('st_bind', 0x2)
+//CHECK-NEXT: ('st_type', 0x0)
+//CHECK-NEXT: ('st_other', 0x00)
+//CHECK-NEXT: ('st_shndx', 0x0001)
//CHECK-NEXT: ('st_value', 0x0000000000000004)
//CHECK-NEXT: ('st_size', 0x0000000000000000)
//CHECK-NEXT: ),
-//CHECK-NEXT: # Symbol 0x00000005
+//CHECK-NEXT: # Symbol 5
//CHECK: (('st_name', 0x00000001) # 'foo'
-//CHECK-NEXT: ('st_bind', 0x00000002)
-//CHECK-NEXT: ('st_type', 0x00000000)
-//CHECK-NEXT: ('st_other', 0x00000000)
-//CHECK-NEXT: ('st_shndx', 0x00000000)
+//CHECK-NEXT: ('st_bind', 0x2)
+//CHECK-NEXT: ('st_type', 0x0)
+//CHECK-NEXT: ('st_other', 0x00)
+//CHECK-NEXT: ('st_shndx', 0x0000)
//CHECK-NEXT: ('st_value', 0x0000000000000000)
//CHECK-NEXT: ('st_size', 0x0000000000000000)
//CHECK-NEXT: ),
diff --git a/test/MC/ELF/weakref-plt.s b/test/MC/ELF/weakref-plt.s
index 26ba3f6..2e50093 100644
--- a/test/MC/ELF/weakref-plt.s
+++ b/test/MC/ELF/weakref-plt.s
@@ -3,6 +3,6 @@
.weakref bar,foo
call bar@PLT
-// CHECK: # Symbol 0x00000005
+// CHECK: # Symbol 5
// CHECK-NEXT: (('st_name', 0x00000001) # 'foo'
-// CHECK-NEXT: ('st_bind', 0x00000002)
+// CHECK-NEXT: ('st_bind', 0x2)
diff --git a/test/MC/ELF/weakref-reloc.s b/test/MC/ELF/weakref-reloc.s
index 63c1f5e..4bbf264 100644
--- a/test/MC/ELF/weakref-reloc.s
+++ b/test/MC/ELF/weakref-reloc.s
@@ -7,43 +7,43 @@
call zed@PLT
call bar
-// CHECK: # Relocation 0x00000000
-// CHECK-NEXT: (('r_offset', 0x00000001)
+// CHECK: # Relocation 0
+// CHECK-NEXT: (('r_offset', 0x0000000000000001)
// CHECK-NEXT: ('r_sym', 0x00000006)
// CHECK-NEXT: ('r_type', 0x00000004)
-// CHECK-NEXT: ('r_addend', 0xfffffffc)
+// CHECK-NEXT: ('r_addend', 0xfffffffffffffffc)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Relocation 0x00000001
-// CHECK-NEXT: (('r_offset', 0x00000006)
+// CHECK-NEXT: # Relocation 1
+// CHECK-NEXT: (('r_offset', 0x0000000000000006)
// CHECK-NEXT: ('r_sym', 0x00000005)
// CHECK-NEXT: ('r_type', 0x00000002)
-// CHECK-NEXT: ('r_addend', 0xfffffffc)
+// CHECK-NEXT: ('r_addend', 0xfffffffffffffffc)
// CHECK-NEXT: ),
-// CHECK: # Symbol 0x00000004
+// CHECK: # Symbol 4
// CHECK-NEXT: (('st_name', 0x00000009) # '_GLOBAL_OFFSET_TABLE_'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000005
+// CHECK-NEXT: # Symbol 5
// CHECK-NEXT: (('st_name', 0x00000001) # 'foo'
-// CHECK-NEXT: ('st_bind', 0x00000002)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x2)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000006
+// CHECK-NEXT: # Symbol 6
// CHECK-NEXT: (('st_name', 0x00000005) # 'zed'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/weakref.s b/test/MC/ELF/weakref.s
index 9100073..e12d2c7 100644
--- a/test/MC/ELF/weakref.s
+++ b/test/MC/ELF/weakref.s
@@ -69,165 +69,165 @@ bar15:
.long bar15
.long foo15
-// CHECK: # Symbol 0x00000000
+// CHECK: # Symbol 0
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000001
+// CHECK-NEXT: # Symbol 1
// CHECK-NEXT: (('st_name', 0x00000015) # 'bar6'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000018)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000002
+// CHECK-NEXT: # Symbol 2
// CHECK-NEXT: (('st_name', 0x0000001a) # 'bar7'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000018)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000003
+// CHECK-NEXT: # Symbol 3
// CHECK-NEXT: (('st_name', 0x0000001f) # 'bar8'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x000000000000001c)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000004
+// CHECK-NEXT: # Symbol 4
// CHECK-NEXT: (('st_name', 0x00000024) # 'bar9'
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000020)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000005
+// CHECK-NEXT: # Symbol 5
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000003)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x3)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000006
+// CHECK-NEXT: # Symbol 6
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000003)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000003)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x3)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0003)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000007
+// CHECK-NEXT: # Symbol 7
// CHECK-NEXT: (('st_name', 0x00000000) # ''
-// CHECK-NEXT: ('st_bind', 0x00000000)
-// CHECK-NEXT: ('st_type', 0x00000003)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000004)
+// CHECK-NEXT: ('st_bind', 0x0)
+// CHECK-NEXT: ('st_type', 0x3)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0004)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000008
+// CHECK-NEXT: # Symbol 8
// CHECK-NEXT: (('st_name', 0x00000029) # 'bar10'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000028)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000009
+// CHECK-NEXT: # Symbol 9
// CHECK-NEXT: (('st_name', 0x0000002f) # 'bar11'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000030)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x0000000a
+// CHECK-NEXT: # Symbol 10
// CHECK-NEXT: (('st_name', 0x00000035) # 'bar12'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000030)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x0000000b
+// CHECK-NEXT: # Symbol 11
// CHECK-NEXT: (('st_name', 0x0000003b) # 'bar13'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000034)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x0000000c
+// CHECK-NEXT: # Symbol 12
// CHECK-NEXT: (('st_name', 0x00000041) # 'bar14'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000038)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x0000000d
+// CHECK-NEXT: # Symbol 13
// CHECK-NEXT: (('st_name', 0x00000047) # 'bar15'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000001)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0001)
// CHECK-NEXT: ('st_value', 0x0000000000000040)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x0000000e
+// CHECK-NEXT: # Symbol 14
// CHECK-NEXT: (('st_name', 0x00000001) # 'bar2'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x0000000f
+// CHECK-NEXT: # Symbol 15
// CHECK-NEXT: (('st_name', 0x00000006) # 'bar3'
-// CHECK-NEXT: ('st_bind', 0x00000002)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x2)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000010
+// CHECK-NEXT: # Symbol 16
// CHECK-NEXT: (('st_name', 0x0000000b) # 'bar4'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
-// CHECK-NEXT: # Symbol 0x00000011
+// CHECK-NEXT: # Symbol 17
// CHECK-NEXT: (('st_name', 0x00000010) # 'bar5'
-// CHECK-NEXT: ('st_bind', 0x00000001)
-// CHECK-NEXT: ('st_type', 0x00000000)
-// CHECK-NEXT: ('st_other', 0x00000000)
-// CHECK-NEXT: ('st_shndx', 0x00000000)
+// CHECK-NEXT: ('st_bind', 0x1)
+// CHECK-NEXT: ('st_type', 0x0)
+// CHECK-NEXT: ('st_other', 0x00)
+// CHECK-NEXT: ('st_shndx', 0x0000)
// CHECK-NEXT: ('st_value', 0x0000000000000000)
// CHECK-NEXT: ('st_size', 0x0000000000000000)
// CHECK-NEXT: ),
diff --git a/test/MC/ELF/x86_64-reloc-sizetest.s b/test/MC/ELF/x86_64-reloc-sizetest.s
new file mode 100644
index 0000000..acca2f5
--- /dev/null
+++ b/test/MC/ELF/x86_64-reloc-sizetest.s
@@ -0,0 +1,13 @@
+// RUN: llvm-mc -triple x86_64-linux-gnu -filetype=obj %s | elf-dump | FileCheck %s
+
+// Tests that relocation value fits in the provided size
+// Original bug http://llvm.org/bugs/show_bug.cgi?id=10568
+
+L: movq $(L + 2147483648),%rax
+
+
+// CHECK: Relocation 0
+// CHECK-NEXT: ('r_offset', 0x0000000000000003)
+// CHECK-NEXT: ('r_sym'
+// CHECK-NEXT: ('r_type', 0x0000000b)
+// CHECK-NEXT: ('r_addend', 0x0000000080000000
diff --git a/test/MC/ELF/zero.s b/test/MC/ELF/zero.s
index adf21f8..46ffe17 100644
--- a/test/MC/ELF/zero.s
+++ b/test/MC/ELF/zero.s
@@ -5,12 +5,12 @@
// CHECK: ('sh_name', 0x00000001) # '.text'
// CHECK: ('sh_type', 0x00000001)
-// CHECK: ('sh_flags', 0x00000006)
-// CHECK: ('sh_addr', 0x00000000)
-// CHECK: ('sh_offset', 0x00000040)
-// CHECK: ('sh_size', 0x00000005)
+// CHECK: ('sh_flags', 0x0000000000000006)
+// CHECK: ('sh_addr', 0x0000000000000000)
+// CHECK: ('sh_offset', 0x0000000000000040)
+// CHECK: ('sh_size', 0x0000000000000005)
// CHECK: ('sh_link', 0x00000000)
// CHECK: ('sh_info', 0x00000000)
-// CHECK: ('sh_addralign', 0x00000004)
-// CHECK: ('sh_entsize', 0x00000000)
+// CHECK: ('sh_addralign', 0x0000000000000004)
+// CHECK: ('sh_entsize', 0x0000000000000000)
// CHECK: ('_section_data', '00000000 2a')
diff --git a/test/MC/MachO/darwin-x86_64-nobase-relocs.s b/test/MC/MachO/darwin-x86_64-nobase-relocs.s
new file mode 100644
index 0000000..a90b3e4
--- /dev/null
+++ b/test/MC/MachO/darwin-x86_64-nobase-relocs.s
@@ -0,0 +1,58 @@
+// RUN: llvm-mc -n -triple x86_64-apple-darwin9 %s -filetype=obj -o - | macho-dump --dump-section-data | FileCheck %s
+
+// Test case for rdar://10062261
+
+// Must be no base, non-temporary, symbol before the reference to Lbar at the
+// start of the section. What we are testing for is that the reference does not
+// create a relocation entry.
+.text
+Ladd:
+ nop
+ jmp Lbar
+ .byte 0x0f,0x1f,0x40,0x00
+ .byte 0x0f,0x1f,0x40,0x00
+Lbar:
+ mov $1, %eax
+ ret
+
+// CHECK: ('cputype', 16777223)
+// CHECK: ('cpusubtype', 3)
+// CHECK: ('filetype', 1)
+// CHECK: ('num_load_commands', 1)
+// CHECK: ('load_commands_size', 152)
+// CHECK: ('flag', 0)
+// CHECK: ('reserved', 0)
+// CHECK: ('load_commands', [
+// CHECK: # Load Command 0
+// CHECK: (('command', 25)
+// CHECK: ('size', 152)
+// CHECK: ('segment_name', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('vm_addr', 0)
+// CHECK: ('vm_size', 17)
+// CHECK: ('file_offset', 184)
+// CHECK: ('file_size', 17)
+// CHECK: ('maxprot', 7)
+// CHECK: ('initprot', 7)
+// CHECK: ('num_sections', 1)
+// CHECK: ('flags', 0)
+// CHECK: ('sections', [
+// CHECK: # Section 0
+// CHECK: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 17)
+// CHECK: ('offset', 184)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x80000400)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ('reserved3', 0)
+// CHECK: ),
+// CHECK: ('_relocations', [
+// CHECK: ])
+// CHECK: ('_section_data', '90eb080f 1f40000f 1f4000b8 01000000 c3')
+// CHECK: ])
+// CHECK: ),
+// CHECK: ])
diff --git a/test/MC/MachO/debug_frame.s b/test/MC/MachO/debug_frame.s
index 47264ef..20bfd8d 100644
--- a/test/MC/MachO/debug_frame.s
+++ b/test/MC/MachO/debug_frame.s
@@ -1,5 +1,11 @@
// RUN: llvm-mc -triple i386-apple-darwin %s -filetype=obj -o - | macho-dump | FileCheck %s
+// Make sure MC can handle file level .cfi_startproc and .cfi_endproc that creates
+// an empty frame.
+// rdar://10017184
+.cfi_startproc
+.cfi_endproc
+
// Check that we don't produce a relocation for the CIE pointer and therefore
// we have only one relocation in __debug_frame.
@@ -22,17 +28,20 @@ Ltext_end:
// CHECK: (('section_name', '__debug_frame\x00\x00\x00')
// CHECK-NEXT: ('segment_name', '__DWARF\x00\x00\x00\x00\x00\x00\x00\x00\x00')
// CHECK-NEXT: ('address', 8)
-// CHECK-NEXT: ('size', 36)
+// CHECK-NEXT: ('size', 52)
// CHECK-NEXT: ('offset', 332)
// CHECK-NEXT: ('alignment', 2)
-// CHECK-NEXT: ('reloc_offset', 368)
-// CHECK-NEXT: ('num_reloc', 1)
+// CHECK-NEXT: ('reloc_offset', 384)
+// CHECK-NEXT: ('num_reloc', 2)
// CHECK-NEXT: ('flags', 0x2000000)
// CHECK-NEXT: ('reserved1', 0)
// CHECK-NEXT: ('reserved2', 0)
// CHECK-NEXT: ),
// CHECK-NEXT: ('_relocations', [
// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('word-0', 0x2c),
+// CHECK-NEXT: ('word-1', 0x4000001)),
+// CHECK-NEXT: # Relocation 1
// CHECK-NEXT: (('word-0', 0x1c),
// CHECK-NEXT: ('word-1', 0x4000001)),
// CHECK-NEXT: ])
diff --git a/test/MC/MachO/x86_64-reloc-arithmetic.s b/test/MC/MachO/x86_64-reloc-arithmetic.s
new file mode 100644
index 0000000..e82f69b
--- /dev/null
+++ b/test/MC/MachO/x86_64-reloc-arithmetic.s
@@ -0,0 +1,21 @@
+// RUN: llvm-mc -triple x86_64-apple-darwin10 %s -filetype=obj -o - | macho-dump | FileCheck %s
+
+// rdar://9906375
+.org 0x100
+_foo:
+_bar = _foo + 2
+_baz:
+ leaq _bar(%rip), %rcx
+
+// CHECK: ('_relocations', [
+// CHECK-NEXT: # Relocation 0
+// CHECK-NEXT: (('word-0', 0x103),
+// CHECK-NEXT: ('word-1', 0x1d000001))
+
+// CHECK: # Symbol 1
+// CHECK-NEXT: (('n_strx', 6)
+// CHECK-NEXT: ('n_type', 0xe)
+// CHECK-NEXT: ('n_sect', 1)
+// CHECK-NEXT: ('n_desc', 0)
+// CHECK-NEXT: ('n_value', 258)
+// CHECK-NEXT: ('_string', '_bar')
diff --git a/test/MC/X86/3DNow.s b/test/MC/X86/3DNow.s
index 4dc68ae..871857b 100644
--- a/test/MC/X86/3DNow.s
+++ b/test/MC/X86/3DNow.s
@@ -1,18 +1,18 @@
-// RUN: llvm-mc -triple i386-unknown-unknown --show-encoding %s | FileCheck %s
+// RUN: llvm-mc -triple x86_64-unknown-unknown --show-encoding %s | FileCheck %s
// PR8283
// CHECK: pavgusb %mm2, %mm1 # encoding: [0x0f,0x0f,0xca,0xbf]
pavgusb %mm2, %mm1
-// CHECK: pavgusb 9(%esi,%edx), %mm3 # encoding: [0x0f,0x0f,0x5c,0x16,0x09,0xbf]
+// CHECK: pavgusb 9(%esi,%edx), %mm3 # encoding: [0x67,0x0f,0x0f,0x5c,0x16,0x09,0xbf]
pavgusb 9(%esi,%edx), %mm3
// CHECK: pf2id %mm2, %mm1 # encoding: [0x0f,0x0f,0xca,0x1d]
pf2id %mm2, %mm1
-// CHECK: pf2id 9(%esi,%edx), %mm3 # encoding: [0x0f,0x0f,0x5c,0x16,0x09,0x1d]
+// CHECK: pf2id 9(%esi,%edx), %mm3 # encoding: [0x67,0x0f,0x0f,0x5c,0x16,0x09,0x1d]
pf2id 9(%esi,%edx), %mm3
// CHECK: pfacc %mm2, %mm1 # encoding: [0x0f,0x0f,0xca,0xae]
diff --git a/test/MC/X86/x86-32-avx.s b/test/MC/X86/x86-32-avx.s
index 1927e4e..e13a871 100644
--- a/test/MC/X86/x86-32-avx.s
+++ b/test/MC/X86/x86-32-avx.s
@@ -479,6 +479,14 @@
// CHECK: encoding: [0xc5,0xf9,0x50,0xc2]
vmovmskpd %xmm2, %eax
+// CHECK: vmovmskps %ymm2, %eax
+// CHECK: encoding: [0xc5,0xfc,0x50,0xc2]
+ vmovmskps %ymm2, %eax
+
+// CHECK: vmovmskpd %ymm2, %eax
+// CHECK: encoding: [0xc5,0xfd,0x50,0xc2]
+ vmovmskpd %ymm2, %eax
+
// CHECK: vcmpss $0, %xmm1, %xmm2, %xmm3
// CHECK: encoding: [0xc5,0xea,0xc2,0xd9,0x00]
vcmpeqss %xmm1, %xmm2, %xmm3
@@ -3281,3 +3289,25 @@
// CHECK: encoding: [0xc4,0xe3,0x51,0x44,0x18,0x11]
vpclmulqdq $17, (%eax), %xmm5, %xmm3
+// rdar://9795008
+// These instructions take a mask not an 8-bit sign extended value.
+// CHECK: vblendps $129, %ymm2, %ymm5, %ymm1
+ vblendps $0x81, %ymm2, %ymm5, %ymm1
+// CHECK: vblendps $129, (%eax), %ymm5, %ymm1
+ vblendps $0x81, (%eax), %ymm5, %ymm1
+// CHECK: vblendpd $129, %ymm2, %ymm5, %ymm1
+ vblendpd $0x81, %ymm2, %ymm5, %ymm1
+// CHECK: vblendpd $129, (%eax), %ymm5, %ymm1
+ vblendpd $0x81, (%eax), %ymm5, %ymm1
+// CHECK: vpblendw $129, %xmm2, %xmm5, %xmm1
+ vpblendw $0x81, %xmm2, %xmm5, %xmm1
+// CHECK: vmpsadbw $129, %xmm2, %xmm5, %xmm1
+ vmpsadbw $0x81, %xmm2, %xmm5, %xmm1
+// CHECK: vdpps $129, %ymm2, %ymm5, %ymm1
+ vdpps $0x81, %ymm2, %ymm5, %ymm1
+// CHECK: vdpps $129, (%eax), %ymm5, %ymm1
+ vdpps $0x81, (%eax), %ymm5, %ymm1
+// CHECK: vdppd $129, %xmm2, %xmm5, %xmm1
+ vdppd $0x81, %xmm2, %xmm5, %xmm1
+// CHECK: vinsertps $129, %xmm3, %xmm2, %xmm1
+ vinsertps $0x81, %xmm3, %xmm2, %xmm1
diff --git a/test/MC/X86/x86-32-coverage.s b/test/MC/X86/x86-32-coverage.s
index bdc54a6..0954ce2 100644
--- a/test/MC/X86/x86-32-coverage.s
+++ b/test/MC/X86/x86-32-coverage.s
@@ -19571,7 +19571,24 @@
// CHECK: aeskeygenassist $125, (%edx,%eax,4), %xmm2
aeskeygenassist $125, (%edx,%eax,4), %xmm2
-// CHECK: blendvps (%rax), %xmm1 # encoding: [0x66,0x0f,0x38,0x14,0x08]
- blendvps (%rax), %xmm1
+// CHECK: blendvps (%eax), %xmm1 # encoding: [0x66,0x0f,0x38,0x14,0x08]
+ blendvps (%eax), %xmm1
// CHECK: blendvps %xmm2, %xmm1 # encoding: [0x66,0x0f,0x38,0x14,0xca]
blendvps %xmm2, %xmm1
+
+// rdar://9795008
+// These instructions take a mask not an 8-bit sign extended value.
+// CHECK: blendps $129, %xmm2, %xmm1
+ blendps $0x81, %xmm2, %xmm1
+// CHECK: blendpd $129, %xmm2, %xmm1
+ blendpd $0x81, %xmm2, %xmm1
+// CHECK: pblendw $129, %xmm2, %xmm1
+ pblendw $0x81, %xmm2, %xmm1
+// CHECK: mpsadbw $129, %xmm2, %xmm1
+ mpsadbw $0x81, %xmm2, %xmm1
+// CHECK: dpps $129, %xmm2, %xmm1
+ dpps $0x81, %xmm2, %xmm1
+// CHECK: dppd $129, %xmm2, %xmm1
+ dppd $0x81, %xmm2, %xmm1
+// CHECK: insertps $129, %xmm2, %xmm1
+ insertps $0x81, %xmm2, %xmm1
diff --git a/test/MC/X86/x86-32.s b/test/MC/X86/x86-32.s
index 6017880..19f1445 100644
--- a/test/MC/X86/x86-32.s
+++ b/test/MC/X86/x86-32.s
@@ -946,3 +946,19 @@ fsubp %st,%st(1)
// CHECK: encoding: [0xde,0xe2]
fsubp %st, %st(2)
+// PR10345
+// CHECK: xchgl %eax, %eax
+// CHECK: encoding: [0x90]
+xchgl %eax, %eax
+
+// CHECK: xchgw %ax, %ax
+// CHECK: encoding: [0x66,0x90]
+xchgw %ax, %ax
+
+// CHECK: xchgl %ecx, %eax
+// CHECK: encoding: [0x91]
+xchgl %ecx, %eax
+
+// CHECK: xchgl %ecx, %eax
+// CHECK: encoding: [0x91]
+xchgl %eax, %ecx
diff --git a/test/MC/X86/x86-64.s b/test/MC/X86/x86-64.s
index 6f828e8..a9cdaa4 100644
--- a/test/MC/X86/x86-64.s
+++ b/test/MC/X86/x86-64.s
@@ -1170,3 +1170,24 @@ pclmullqhqdq (%rdi), %xmm1
// CHECK: pclmulqdq $0, (%rdi), %xmm1
// CHECK: encoding: [0x66,0x0f,0x3a,0x44,0x0f,0x00]
pclmulqdq $0, (%rdi), %xmm1
+
+// PR10345
+// CHECK: xchgq %rax, %rax
+// CHECK: encoding: [0x48,0x90]
+xchgq %rax, %rax
+
+// CHECK: xchgl %eax, %eax
+// CHECK: encoding: [0x87,0xc0]
+xchgl %eax, %eax
+
+// CHECK: xchgw %ax, %ax
+// CHECK: encoding: [0x66,0x90]
+xchgw %ax, %ax
+
+// CHECK: xchgl %ecx, %eax
+// CHECK: encoding: [0x91]
+xchgl %ecx, %eax
+
+// CHECK: xchgl %ecx, %eax
+// CHECK: encoding: [0x91]
+xchgl %eax, %ecx
diff --git a/test/MC/X86/x86_64-avx-encoding.s b/test/MC/X86/x86_64-avx-encoding.s
index 7a96bb5..d3b226f 100644
--- a/test/MC/X86/x86_64-avx-encoding.s
+++ b/test/MC/X86/x86_64-avx-encoding.s
@@ -1448,6 +1448,10 @@ vdivpd -4(%rcx,%rbx,8), %xmm10, %xmm11
// CHECK: encoding: [0xc4,0x61,0xf9,0x6e,0xf0]
vmovd %rax, %xmm14
+// CHECK: vmovd %xmm0, %rax
+// CHECK: encoding: [0xc4,0xe1,0xf9,0x7e,0xc0]
+ vmovd %xmm0, %rax
+
// CHECK: vmovq %xmm14, (%rax)
// CHECK: encoding: [0xc5,0x79,0xd6,0x30]
vmovq %xmm14, (%rax)
@@ -3316,3 +3320,29 @@ vdivpd -4(%rcx,%rbx,8), %xmm10, %xmm11
// CHECK: encoding: [0xc4,0x63,0x1d,0x4b,0xac,0x20,0xad,0xde,0x00,0x00,0xb0]
vblendvpd %ymm11, 0xdead(%rax,%riz), %ymm12, %ymm13
+// CHECK: vmovaps %xmm3, (%r14,%r11)
+// CHECK: encoding: [0xc4,0x81,0x78,0x29,0x1c,0x1e]
+ vmovaps %xmm3, (%r14,%r11)
+
+// CHECK: vmovaps (%r14,%r11), %xmm3
+// CHECK: encoding: [0xc4,0x81,0x78,0x28,0x1c,0x1e]
+ vmovaps (%r14,%r11), %xmm3
+
+// CHECK: vmovaps %xmm3, (%r14,%rbx)
+// CHECK: encoding: [0xc4,0xc1,0x78,0x29,0x1c,0x1e]
+ vmovaps %xmm3, (%r14,%rbx)
+
+// CHECK: vmovaps (%r14,%rbx), %xmm3
+// CHECK: encoding: [0xc4,0xc1,0x78,0x28,0x1c,0x1e]
+ vmovaps (%r14,%rbx), %xmm3
+
+// CHECK: vmovaps %xmm3, (%rax,%r11)
+// CHECK: encoding: [0xc4,0xa1,0x78,0x29,0x1c,0x18]
+ vmovaps %xmm3, (%rax,%r11)
+
+// CHECK: vpshufb _foo(%rip), %xmm0, %xmm0
+// CHECK: encoding: [0xc4,0xe2,0x79,0x00,0x05,A,A,A,A]
+// CHECK: kind: reloc_riprel_4byte
+_foo:
+ nop
+ vpshufb _foo(%rip), %xmm0, %xmm0
diff --git a/test/MC/X86/x86_errors.s b/test/MC/X86/x86_errors.s
index 183306b..e0a2c676 100644
--- a/test/MC/X86/x86_errors.s
+++ b/test/MC/X86/x86_errors.s
@@ -1,5 +1,17 @@
// RUN: not llvm-mc -triple x86_64-unknown-unknown %s 2> %t.err
-// RUN: FileCheck < %t.err %s
+// RUN: FileCheck --check-prefix=64 < %t.err %s
-// CHECK: error: ambiguous instructions require an explicit suffix (could be 'cmpb', 'cmpw', 'cmpl', or 'cmpq')
+// RUN: not llvm-mc -triple i386-unknown-unknown %s 2> %t.err
+// RUN: FileCheck --check-prefix=32 < %t.err %s
+// rdar://8204588
+
+// 64: error: ambiguous instructions require an explicit suffix (could be 'cmpb', 'cmpw', 'cmpl', or 'cmpq')
cmp $0, 0(%eax)
+
+// 32: error: register %rax is only available in 64-bit mode
+addl $0, 0(%rax)
+
+// 32: test.s:8:2: error: invalid instruction mnemonic 'movi'
+
+# 8 "test.s"
+ movi $8,%eax
diff --git a/test/Object/TestObjectFiles/archive-test.a-bitcode b/test/Object/TestObjectFiles/archive-test.a-bitcode
new file mode 100644
index 0000000..3aeb34f
--- /dev/null
+++ b/test/Object/TestObjectFiles/archive-test.a-bitcode
Binary files differ
diff --git a/test/Object/TestObjectFiles/archive-test.a-coff-i386 b/test/Object/TestObjectFiles/archive-test.a-coff-i386
new file mode 100644
index 0000000..846cd63
--- /dev/null
+++ b/test/Object/TestObjectFiles/archive-test.a-coff-i386
Binary files differ
diff --git a/test/Object/nm-archive.test b/test/Object/nm-archive.test
new file mode 100644
index 0000000..da6144e
--- /dev/null
+++ b/test/Object/nm-archive.test
@@ -0,0 +1,17 @@
+RUN: llvm-nm %p/TestObjectFiles/archive-test.a-coff-i386 \
+RUN: | FileCheck %s -check-prefix COFF
+RUN: llvm-nm %p/TestObjectFiles/archive-test.a-bitcode \
+RUN: | FileCheck %s -check-prefix BITCODE
+
+
+COFF: trivial-object-test.coff-i386:
+COFF-NEXT: 00000000 d .data
+COFF-NEXT: 00000000 t .text
+COFF-NEXT: 00000000 d L_.str
+COFF-NEXT: U _SomeOtherFunction
+COFF-NEXT: 00000000 T _main
+COFF-NEXT: U _puts
+
+BITCODE: U SomeOtherFunction
+BITCODE-NEXT: T main
+BITCODE-NEXT: U puts
diff --git a/test/Object/nm-trivial-object.test-broken b/test/Object/nm-trivial-object.test
index 6de1780..6de1780 100644
--- a/test/Object/nm-trivial-object.test-broken
+++ b/test/Object/nm-trivial-object.test
diff --git a/test/Object/objdump-disassembly-inline-relocations.test b/test/Object/objdump-disassembly-inline-relocations.test
new file mode 100644
index 0000000..91f2e48
--- /dev/null
+++ b/test/Object/objdump-disassembly-inline-relocations.test
@@ -0,0 +1,32 @@
+RUN: llvm-objdump -d -r %p/TestObjectFiles/trivial-object-test.coff-i386 \
+RUN: | FileCheck %s -check-prefix COFF-i386
+RUN: llvm-objdump -d -r %p/TestObjectFiles/trivial-object-test.coff-x86-64 \
+RUN: | FileCheck %s -check-prefix COFF-x86-64
+
+COFF-i386: file format COFF-i386
+COFF-i386: Disassembly of section .text:
+COFF-i386: 0: 83 ec 0c subl $12, %esp
+COFF-i386: 3: c7 44 24 08 00 00 00 00 movl $0, 8(%esp)
+COFF-i386: b: c7 04 24 00 00 00 00 movl $0, (%esp)
+COFF-i386: e: IMAGE_REL_I386_DIR32 L_.str
+COFF-i386: 12: e8 00 00 00 00 calll 0
+COFF-i386: 13: IMAGE_REL_I386_REL32 _puts
+COFF-i386: 17: e8 00 00 00 00 calll 0
+COFF-i386: 18: IMAGE_REL_I386_REL32 _SomeOtherFunction
+COFF-i386: 1c: 8b 44 24 08 movl 8(%esp), %eax
+COFF-i386: 20: 83 c4 0c addl $12, %esp
+COFF-i386: 23: c3 ret
+
+COFF-x86-64: file format COFF-x86-64
+COFF-x86-64: Disassembly of section .text:
+COFF-x86-64: 0: 48 83 ec 28 subq $40, %rsp
+COFF-x86-64: 4: c7 44 24 24 00 00 00 00 movl $0, 36(%rsp)
+COFF-x86-64: c: 48 8d 0d 00 00 00 00 leaq (%rip), %rcx
+COFF-x86-64: f: IMAGE_REL_AMD64_REL32 L.str
+COFF-x86-64: 13: e8 00 00 00 00 callq 0
+COFF-x86-64: 14: IMAGE_REL_AMD64_REL32 puts
+COFF-x86-64: 18: e8 00 00 00 00 callq 0
+COFF-x86-64: 19: IMAGE_REL_AMD64_REL32 SomeOtherFunction
+COFF-x86-64: 1d: 8b 44 24 24 movl 36(%rsp), %eax
+COFF-x86-64: 21: 48 83 c4 28 addq $40, %rsp
+COFF-x86-64: 25: c3 ret
diff --git a/test/Object/objdump-relocations.test b/test/Object/objdump-relocations.test
new file mode 100644
index 0000000..2dcdb43
--- /dev/null
+++ b/test/Object/objdump-relocations.test
@@ -0,0 +1,28 @@
+RUN: llvm-objdump -r %p/TestObjectFiles/trivial-object-test.coff-i386 \
+RUN: | FileCheck %s -check-prefix COFF-i386
+RUN: llvm-objdump -r %p/TestObjectFiles/trivial-object-test.coff-x86-64 \
+RUN: | FileCheck %s -check-prefix COFF-x86-64
+RUN: llvm-objdump -r %p/TestObjectFiles/trivial-object-test.elf-i386 \
+RUN: | FileCheck %s -check-prefix ELF-i386
+RUN: llvm-objdump -r %p/TestObjectFiles/trivial-object-test.elf-x86-64 \
+RUN: | FileCheck %s -check-prefix ELF-x86-64
+
+COFF-i386: .text
+COFF-i386: IMAGE_REL_I386_DIR32 L_.str
+COFF-i386: IMAGE_REL_I386_REL32 _puts
+COFF-i386: IMAGE_REL_I386_REL32 _SomeOtherFunction
+
+COFF-x86-64: .text
+COFF-x86-64: IMAGE_REL_AMD64_REL32 L.str
+COFF-x86-64: IMAGE_REL_AMD64_REL32 puts
+COFF-x86-64: IMAGE_REL_AMD64_REL32 SomeOtherFunction
+
+ELF-i386: .text
+ELF-i386: R_386_32
+ELF-i386: R_386_PC32
+ELF-i386: R_386_PC32
+
+ELF-x86-64: .text
+ELF-x86-64: R_X86_64_32S .rodata.str1.1
+ELF-x86-64: R_X86_64_PC32 puts
+ELF-x86-64: R_X86_64_PC32 SomeOtherFunction
diff --git a/test/Object/objdump-sectionheaders.test b/test/Object/objdump-sectionheaders.test
new file mode 100644
index 0000000..4515d00
--- /dev/null
+++ b/test/Object/objdump-sectionheaders.test
@@ -0,0 +1,16 @@
+; RUN: llvm-objdump -h %p/TestObjectFiles/trivial-object-test.elf-x86-64 \
+; RUN: | FileCheck %s
+
+; To verify this, use readelf -S, not objdump -h. Binutils objdump filters the
+; results in a way that we don't emulate.
+
+; CHECK: Sections:
+; CHECK: Idx Name Size Address Type
+; CHECK: 0 000000000 00000000000000000
+; CHECK: 1 .text 000000026 00000000000000000 TEXT DATA
+; CHECK: 2 .rodata.str1.1 00000000d 00000000000000026 DATA
+; CHECK: 3 .note.GNU-stack 000000000 00000000000000033
+; CHECK: 4 .rela.text 000000048 00000000000000038
+; CHECK: 5 .symtab 0000000c0 00000000000000080
+; CHECK: 6 .strtab 000000033 00000000000000140
+; CHECK: 7 .shstrtab 00000004b 00000000000000173
diff --git a/test/Object/objdump-trivial-object.test-broken b/test/Object/objdump-trivial-object.test
index c4855fd..c4855fd 100644
--- a/test/Object/objdump-trivial-object.test-broken
+++ b/test/Object/objdump-trivial-object.test
diff --git a/test/Other/2008-10-15-MissingSpace.ll b/test/Other/2008-10-15-MissingSpace.ll
index a61fa61..d16ea72 100644
--- a/test/Other/2008-10-15-MissingSpace.ll
+++ b/test/Other/2008-10-15-MissingSpace.ll
@@ -3,5 +3,10 @@
declare void @g()
define void @f() {
invoke void @g() to label %c unwind label %c
- c: ret void
+c:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ ret void
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Scripts/common_dump.py b/test/Scripts/common_dump.py
index 3d69c3f..fd58993 100644
--- a/test/Scripts/common_dump.py
+++ b/test/Scripts/common_dump.py
@@ -31,7 +31,7 @@ def dataToHexUnified(d):
return ''.join(bytes).strip()
-def HexDump(val, numBits=32):
+def HexDump(valPair):
"""
1. do not print 'L'
2. Handle negatives and large numbers by mod (2^numBits)
@@ -40,7 +40,9 @@ def HexDump(val, numBits=32):
4. Do print 0x Why?
so that they can be easily distinguished using sed/rx
"""
+ val, numBits = valPair
+ assert 0 <= val < (1 << numBits)
+
val = val & (( 1 << numBits) - 1)
newFmt = "0x%0" + "%d" % (numBits / 4) + "x"
return newFmt % val
-
diff --git a/test/Scripts/elf-dump b/test/Scripts/elf-dump
index 76cdbf9..58ca177 100755
--- a/test/Scripts/elf-dump
+++ b/test/Scripts/elf-dump
@@ -26,22 +26,16 @@ class Reader:
return data
def read8(self):
- return ord(self.read(1))
+ return (ord(self.read(1)), 8)
def read16(self):
- return struct.unpack('><'[self.isLSB] + 'H', self.read(2))[0]
+ return (struct.unpack('><'[self.isLSB] + 'H', self.read(2))[0], 16)
def read32(self):
- return struct.unpack('><'[self.isLSB] + 'I', self.read(4))[0]
-
- def read32S(self):
- return struct.unpack('><'[self.isLSB] + 'i', self.read(4))[0]
+ return (struct.unpack('><'[self.isLSB] + 'I', self.read(4))[0], 32)
def read64(self):
- return struct.unpack('><'[self.isLSB] + 'Q', self.read(8))[0]
-
- def read64S(self):
- return struct.unpack('><'[self.isLSB] + 'q', self.read(8))[0]
+ return (struct.unpack('><'[self.isLSB] + 'Q', self.read(8))[0], 64)
def readWord(self):
if self.is64Bit:
@@ -49,12 +43,6 @@ class Reader:
else:
return self.read32()
- def readWordS(self):
- if self.is64Bit:
- return self.read64S()
- else:
- return self.read32S()
-
class StringTable:
def __init__(self, strings):
self.string_table = strings
@@ -77,7 +65,7 @@ class Section:
self.sh_entsize = f.readWord()
def dump(self, shstrtab, f, strtab, dumpdata):
- print " (('sh_name', %s)" % common_dump.HexDump(self.sh_name), "# %r" % shstrtab[self.sh_name]
+ print " (('sh_name', %s)" % common_dump.HexDump(self.sh_name), "# %r" % shstrtab[self.sh_name[0]]
print " ('sh_type', %s)" % common_dump.HexDump(self.sh_type)
print " ('sh_flags', %s)" % common_dump.HexDump(self.sh_flags)
print " ('sh_addr', %s)" % common_dump.HexDump(self.sh_addr)
@@ -87,60 +75,64 @@ class Section:
print " ('sh_info', %s)" % common_dump.HexDump(self.sh_info)
print " ('sh_addralign', %s)" % common_dump.HexDump(self.sh_addralign)
print " ('sh_entsize', %s)" % common_dump.HexDump(self.sh_entsize)
- if self.sh_type == 2: # SHT_SYMTAB
+ if self.sh_type[0] == 2: # SHT_SYMTAB
print " ('_symbols', ["
dumpSymtab(f, self, strtab)
print " ])"
- elif self.sh_type == 4 or self.sh_type == 9: # SHT_RELA / SHT_REL
+ elif self.sh_type[0] == 4 or self.sh_type[0] == 9: # SHT_RELA / SHT_REL
print " ('_relocations', ["
- dumpRel(f, self, self.sh_type == 4)
+ dumpRel(f, self, self.sh_type[0] == 4)
print " ])"
elif dumpdata:
- f.seek(self.sh_offset)
+ f.seek(self.sh_offset[0])
if self.sh_type != 8: # != SHT_NOBITS
- data = f.read(self.sh_size)
+ data = f.read(self.sh_size[0])
print " ('_section_data', '%s')" % common_dump.dataToHex(data)
else:
print " ('_section_data', '')"
print " ),"
def dumpSymtab(f, section, strtab):
- entries = section.sh_size // section.sh_entsize
+ entries = section.sh_size[0] // section.sh_entsize[0]
for index in range(entries):
- f.seek(section.sh_offset + index * section.sh_entsize)
- print " # Symbol %s" % common_dump.HexDump(index)
+ f.seek(section.sh_offset[0] + index * section.sh_entsize[0])
+ print " # Symbol %s" % index
name = f.read32()
- print " (('st_name', %s)" % common_dump.HexDump(name), "# %r" % strtab[name]
+ print " (('st_name', %s)" % common_dump.HexDump(name), "# %r" % strtab[name[0]]
if not f.is64Bit:
print " ('st_value', %s)" % common_dump.HexDump(f.read32())
print " ('st_size', %s)" % common_dump.HexDump(f.read32())
- st_info = f.read8()
- print " ('st_bind', %s)" % common_dump.HexDump((st_info >> 4))
- print " ('st_type', %s)" % common_dump.HexDump((st_info & 0xf))
+ st_info = f.read8()[0]
+ st_bind = (st_info >> 4, 4)
+ st_type = (st_info & 0xf, 4)
+ print " ('st_bind', %s)" % common_dump.HexDump(st_bind)
+ print " ('st_type', %s)" % common_dump.HexDump(st_type)
print " ('st_other', %s)" % common_dump.HexDump(f.read8())
print " ('st_shndx', %s)" % common_dump.HexDump(f.read16())
if f.is64Bit:
- print " ('st_value', %s)" % common_dump.HexDump(f.read64(), 64)
- print " ('st_size', %s)" % common_dump.HexDump(f.read64(), 64)
+ print " ('st_value', %s)" % common_dump.HexDump(f.read64())
+ print " ('st_size', %s)" % common_dump.HexDump(f.read64())
print " ),"
def dumpRel(f, section, dumprela = False):
- entries = section.sh_size // section.sh_entsize
+ entries = section.sh_size[0] // section.sh_entsize[0]
for index in range(entries):
- f.seek(section.sh_offset + index * section.sh_entsize)
- print " # Relocation %s" % common_dump.HexDump(index)
+ f.seek(section.sh_offset[0] + index * section.sh_entsize[0])
+ print " # Relocation %s" % index
print " (('r_offset', %s)" % common_dump.HexDump(f.readWord())
- r_info = f.readWord()
+ r_info = f.readWord()[0]
if f.is64Bit:
- print " ('r_sym', %s)" % common_dump.HexDump((r_info >> 32))
- print " ('r_type', %s)" % common_dump.HexDump((r_info & 0xffffffff))
+ r_sym = (r_info >> 32, 32)
+ r_type = (r_info & 0xffffffff, 32)
else:
- print " ('r_sym', %s)" % common_dump.HexDump((r_info >> 8))
- print " ('r_type', %s)" % common_dump.HexDump((r_info & 0xff))
+ r_sym = (r_info >> 8, 24)
+ r_type = (r_info & 0xff, 8)
+ print " ('r_sym', %s)" % common_dump.HexDump(r_sym)
+ print " ('r_type', %s)" % common_dump.HexDump(r_type)
if dumprela:
- print " ('r_addend', %s)" % common_dump.HexDump(f.readWordS())
+ print " ('r_addend', %s)" % common_dump.HexDump(f.readWord())
print " ),"
def dumpELF(path, opts):
@@ -150,18 +142,18 @@ def dumpELF(path, opts):
assert magic == '\x7FELF'
fileclass = f.read8()
- if fileclass == 1: # ELFCLASS32
+ if fileclass[0] == 1: # ELFCLASS32
f.is64Bit = False
- elif fileclass == 2: # ELFCLASS64
+ elif fileclass[0] == 2: # ELFCLASS64
f.is64Bit = True
else:
raise ValueError, "Unknown file class %s" % common_dump.HexDump(fileclass)
print "('e_indent[EI_CLASS]', %s)" % common_dump.HexDump(fileclass)
byteordering = f.read8()
- if byteordering == 1: # ELFDATA2LSB
+ if byteordering[0] == 1: # ELFDATA2LSB
f.isLSB = True
- elif byteordering == 2: # ELFDATA2MSB
+ elif byteordering[0] == 2: # ELFDATA2MSB
f.isLSB = False
else:
raise ValueError, "Unknown byte ordering %s" % common_dump.HexDump(byteordering)
@@ -193,26 +185,26 @@ def dumpELF(path, opts):
# Read all section headers
sections = []
- for index in range(e_shnum):
- f.seek(e_shoff + index * e_shentsize)
+ for index in range(e_shnum[0]):
+ f.seek(e_shoff[0] + index * e_shentsize[0])
s = Section(f)
sections.append(s)
# Read .shstrtab so we can resolve section names
- f.seek(sections[e_shstrndx].sh_offset)
- shstrtab = StringTable(f.read(sections[e_shstrndx].sh_size))
+ f.seek(sections[e_shstrndx[0]].sh_offset[0])
+ shstrtab = StringTable(f.read(sections[e_shstrndx[0]].sh_size[0]))
# Get the symbol string table
strtab = None
for section in sections:
- if shstrtab[section.sh_name] == ".strtab":
- f.seek(section.sh_offset)
- strtab = StringTable(f.read(section.sh_size))
+ if shstrtab[section.sh_name[0]] == ".strtab":
+ f.seek(section.sh_offset[0])
+ strtab = StringTable(f.read(section.sh_size[0]))
break
print "('_sections', ["
- for index in range(e_shnum):
- print " # Section %s" % common_dump.HexDump(index)
+ for index in range(e_shnum[0]):
+ print " # Section %s" % index
sections[index].dump(shstrtab, f, strtab, opts.dumpSectionData)
print "])"
diff --git a/test/TableGen/2003-08-03-PassCode.td b/test/TableGen/2003-08-03-PassCode.td
index c02f499..de7d626 100644
--- a/test/TableGen/2003-08-03-PassCode.td
+++ b/test/TableGen/2003-08-03-PassCode.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
class test<code C> {
diff --git a/test/TableGen/2006-09-18-LargeInt.td b/test/TableGen/2006-09-18-LargeInt.td
index 194699a..f7ae4ee 100644
--- a/test/TableGen/2006-09-18-LargeInt.td
+++ b/test/TableGen/2006-09-18-LargeInt.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep -- 4294901760
+// RUN: llvm-tblgen %s | grep -- 4294901760
// XFAIL: vg_leak
def X {
diff --git a/test/TableGen/2010-03-24-PrematureDefaults.td b/test/TableGen/2010-03-24-PrematureDefaults.td
index 2ff2d42..24f6c93 100644
--- a/test/TableGen/2010-03-24-PrematureDefaults.td
+++ b/test/TableGen/2010-03-24-PrematureDefaults.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | FileCheck %s
+// RUN: llvm-tblgen %s | FileCheck %s
// XFAIL: vg_leak
class A<int k, bits<2> x = 1> {
diff --git a/test/TableGen/AnonDefinitionOnDemand.td b/test/TableGen/AnonDefinitionOnDemand.td
index b10ad58..b6e0fc7 100644
--- a/test/TableGen/AnonDefinitionOnDemand.td
+++ b/test/TableGen/AnonDefinitionOnDemand.td
@@ -1,4 +1,4 @@
-// RUN: tblgen < %s
+// RUN: llvm-tblgen < %s
// XFAIL: vg_leak
class foo<int X> { int THEVAL = X; }
diff --git a/test/TableGen/BitsInitOverflow.td b/test/TableGen/BitsInitOverflow.td
index 076b3f6..c3f9720 100644
--- a/test/TableGen/BitsInitOverflow.td
+++ b/test/TableGen/BitsInitOverflow.td
@@ -1,4 +1,4 @@
-// RUN: not tblgen %s 2> /dev/null
+// RUN: not llvm-tblgen %s 2> /dev/null
def {
bits<2> X = 5; // bitfield is too small, reject
diff --git a/test/TableGen/CStyleComment.td b/test/TableGen/CStyleComment.td
index 703ae68..55fb0e7 100644
--- a/test/TableGen/CStyleComment.td
+++ b/test/TableGen/CStyleComment.td
@@ -1,6 +1,7 @@
// Test that multiline, nested, comments work correctly.
//
-// RUN: tblgen < %s
+// RUN: llvm-tblgen < %s
+// XFAIL: vg_leak
/* Foo
bar
diff --git a/test/TableGen/Dag.td b/test/TableGen/Dag.td
index d3481a5..9ed2301 100644
--- a/test/TableGen/Dag.td
+++ b/test/TableGen/Dag.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | FileCheck %s
+// RUN: llvm-tblgen %s | FileCheck %s
// XFAIL: vg_leak
//===----------------------------------------------------------------------===//
diff --git a/test/TableGen/DefmInherit.td b/test/TableGen/DefmInherit.td
index 9e16670..47fd81d 100644
--- a/test/TableGen/DefmInherit.td
+++ b/test/TableGen/DefmInherit.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep {zing = 4} | count 4
+// RUN: llvm-tblgen %s | grep {zing = 4} | count 4
// XFAIL: vg_leak
class C1<int A, string B> {
diff --git a/test/TableGen/DefmInsideMultiClass.td b/test/TableGen/DefmInsideMultiClass.td
index 68cc12d..e6fc019 100644
--- a/test/TableGen/DefmInsideMultiClass.td
+++ b/test/TableGen/DefmInsideMultiClass.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep ADDPSrr | count 1
+// RUN: llvm-tblgen %s | grep ADDPSrr | count 1
// XFAIL: vg_leak
class Instruction<bits<4> opc, string Name> {
diff --git a/test/TableGen/FieldAccess.td b/test/TableGen/FieldAccess.td
index 8b4dc83..d69caae 100644
--- a/test/TableGen/FieldAccess.td
+++ b/test/TableGen/FieldAccess.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
class Bla<string t>
diff --git a/test/TableGen/ForwardRef.td b/test/TableGen/ForwardRef.td
index 955cc14..7388445 100644
--- a/test/TableGen/ForwardRef.td
+++ b/test/TableGen/ForwardRef.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s -o -
+// RUN: llvm-tblgen %s -o -
// XFAIL: vg_leak
class bar {
diff --git a/test/TableGen/GeneralList.td b/test/TableGen/GeneralList.td
index ca92a21..9e0c7df 100644
--- a/test/TableGen/GeneralList.td
+++ b/test/TableGen/GeneralList.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
//
// Test to make sure that lists work with any data-type
diff --git a/test/TableGen/Include.td b/test/TableGen/Include.td
index 29ed515..8783638 100644
--- a/test/TableGen/Include.td
+++ b/test/TableGen/Include.td
@@ -1,4 +1,5 @@
-// RUN: tblgen -I %p %s
+// RUN: llvm-tblgen -I %p %s
+// XFAIL: vg_leak
def BeforeInclude;
include "Include.inc"
diff --git a/test/TableGen/IntBitInit.td b/test/TableGen/IntBitInit.td
index 16ac9c8..83713a3 100644
--- a/test/TableGen/IntBitInit.td
+++ b/test/TableGen/IntBitInit.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
def {
bit A = 1;
diff --git a/test/TableGen/LazyChange.td b/test/TableGen/LazyChange.td
index fa53562..8145a3f 100644
--- a/test/TableGen/LazyChange.td
+++ b/test/TableGen/LazyChange.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep {int Y = 3}
+// RUN: llvm-tblgen %s | grep {int Y = 3}
// XFAIL: vg_leak
class C {
diff --git a/test/TableGen/LetInsideMultiClasses.td b/test/TableGen/LetInsideMultiClasses.td
index 9238bf4..cb13508 100644
--- a/test/TableGen/LetInsideMultiClasses.td
+++ b/test/TableGen/LetInsideMultiClasses.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep "bit IsDouble = 1;" | count 3
+// RUN: llvm-tblgen %s | grep "bit IsDouble = 1;" | count 3
// XFAIL: vg_leak
class Instruction<bits<4> opc, string Name> {
diff --git a/test/TableGen/ListArgs.td b/test/TableGen/ListArgs.td
index a513db6..8714112 100644
--- a/test/TableGen/ListArgs.td
+++ b/test/TableGen/ListArgs.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
class B<list<int> v> {
diff --git a/test/TableGen/ListArgsSimple.td b/test/TableGen/ListArgsSimple.td
index f7caed6..b8ec6e0 100644
--- a/test/TableGen/ListArgsSimple.td
+++ b/test/TableGen/ListArgsSimple.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
class B<int v> {
diff --git a/test/TableGen/ListConversion.td b/test/TableGen/ListConversion.td
index 222b614..29b8779 100644
--- a/test/TableGen/ListConversion.td
+++ b/test/TableGen/ListConversion.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
class A;
class B : A;
diff --git a/test/TableGen/ListManip.td b/test/TableGen/ListManip.td
index 6b1e491..bece266 100644
--- a/test/TableGen/ListManip.td
+++ b/test/TableGen/ListManip.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
class Bli<string _t>
diff --git a/test/TableGen/ListOfList.td b/test/TableGen/ListOfList.td
new file mode 100644
index 0000000..565a99c
--- /dev/null
+++ b/test/TableGen/ListOfList.td
@@ -0,0 +1,14 @@
+// RUN llvm-tblgen %s | FileCheck %s
+
+// RUN: llvm-tblgen %s | grep {foo} | count 1
+// XFAIL: vg_leak
+
+class Base<string t> {
+ string text = t;
+}
+
+class Derived<list<list<string>> thetext> : Base<thetext[0][0]>;
+
+def FOO : Derived<[["foo"]]>;
+
+// CHECK: text = "foo"
diff --git a/test/TableGen/ListSlices.td b/test/TableGen/ListSlices.td
index 5848a4e..cbb2326 100644
--- a/test/TableGen/ListSlices.td
+++ b/test/TableGen/ListSlices.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
def A {
diff --git a/test/TableGen/LoLoL.td b/test/TableGen/LoLoL.td
new file mode 100644
index 0000000..778c960
--- /dev/null
+++ b/test/TableGen/LoLoL.td
@@ -0,0 +1,18 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+class Base<list<int> v> {
+ list<int> values = v;
+}
+
+class Derived<list<int> v> : Base<!if(!empty(v),[0],v)>;
+
+multiclass Multi<list<list<list<int>>> v> {
+ def ONE : Derived<!if(!empty(v),[]<int>,!if(!empty(!head(v)),[]<int>,v[0][0]))>;
+ def TWO : Derived<!if(!empty(v),[]<int>,!if(!empty(!tail(v)),!if(!empty(!head(v)),[]<int>,v[0][0]),v[1][0]))>;
+}
+
+defm Def : Multi<[[[]],[[1, 2, 3]]]>;
+
+// CHECK: values = [0]
+// CHECK: values = [1, 2, 3]
diff --git a/test/TableGen/MultiClass.td b/test/TableGen/MultiClass.td
index 9f92b73..04f3a56 100644
--- a/test/TableGen/MultiClass.td
+++ b/test/TableGen/MultiClass.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep {zing = 4} | count 2
+// RUN: llvm-tblgen %s | grep {zing = 4} | count 2
// XFAIL: vg_leak
class C1<int A, string B> {
diff --git a/test/TableGen/MultiClassDefName.td b/test/TableGen/MultiClassDefName.td
index 138c93d..296e30c 100644
--- a/test/TableGen/MultiClassDefName.td
+++ b/test/TableGen/MultiClassDefName.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep WorldHelloCC | count 1
+// RUN: llvm-tblgen %s | grep WorldHelloCC | count 1
// XFAIL: vg_leak
class C<string n> {
diff --git a/test/TableGen/MultiClassInherit.td b/test/TableGen/MultiClassInherit.td
index 9da80ba..8b78bc7 100644
--- a/test/TableGen/MultiClassInherit.td
+++ b/test/TableGen/MultiClassInherit.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep {zing = 4} | count 28
+// RUN: llvm-tblgen %s | grep {zing = 4} | count 28
// XFAIL: vg_leak
class C1<int A, string B> {
diff --git a/test/TableGen/MultiPat.td b/test/TableGen/MultiPat.td
new file mode 100644
index 0000000..b379277
--- /dev/null
+++ b/test/TableGen/MultiPat.td
@@ -0,0 +1,121 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+class ValueType<int size, int value> {
+ int Size = size;
+ int Value = value;
+}
+
+def v2i64 : ValueType<128, 22>; // 2 x i64 vector value
+def v2f64 : ValueType<128, 28>; // 2 x f64 vector value
+
+class Intrinsic<string name> {
+ string Name = name;
+}
+
+class Pattern<dag patternToMatch, list<dag> resultInstrs> {
+ dag PatternToMatch = patternToMatch;
+ list<dag> ResultInstrs = resultInstrs;
+}
+
+// Pat - A simple (but common) form of a pattern, which produces a simple result
+// not needing a full list.
+class Pat<dag pattern, dag result> : Pattern<pattern, [result]>;
+
+class Inst<bits<8> opcode, dag oopnds, dag iopnds, string asmstr,
+ list<dag> pattern> {
+ bits<8> Opcode = opcode;
+ dag OutOperands = oopnds;
+ dag InOperands = iopnds;
+ string AssemblyString = asmstr;
+ list<dag> Pattern = pattern;
+}
+
+def ops;
+def outs;
+def ins;
+
+def set;
+
+// Define registers
+class Register<string n> {
+ string Name = n;
+}
+
+class RegisterClass<list<ValueType> regTypes, list<Register> regList> {
+ list<ValueType> RegTypes = regTypes;
+ list<Register> MemberList = regList;
+}
+
+def XMM0: Register<"xmm0">;
+def XMM1: Register<"xmm1">;
+def XMM2: Register<"xmm2">;
+def XMM3: Register<"xmm3">;
+def XMM4: Register<"xmm4">;
+def XMM5: Register<"xmm5">;
+def XMM6: Register<"xmm6">;
+def XMM7: Register<"xmm7">;
+def XMM8: Register<"xmm8">;
+def XMM9: Register<"xmm9">;
+def XMM10: Register<"xmm10">;
+def XMM11: Register<"xmm11">;
+def XMM12: Register<"xmm12">;
+def XMM13: Register<"xmm13">;
+def XMM14: Register<"xmm14">;
+def XMM15: Register<"xmm15">;
+
+def VR128 : RegisterClass<[v2i64, v2f64],
+ [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
+ XMM8, XMM9, XMM10, XMM11,
+ XMM12, XMM13, XMM14, XMM15]>;
+
+// Dummy for subst
+def REGCLASS : RegisterClass<[], []>;
+def MNEMONIC;
+
+class decls {
+ // Dummy for foreach
+ dag pattern;
+ int operand;
+}
+
+def Decls : decls;
+
+// Define intrinsics
+def int_x86_sse2_add_ps : Intrinsic<"addps">;
+def int_x86_sse2_add_pd : Intrinsic<"addpd">;
+def INTRINSIC : Intrinsic<"Dummy">;
+def bitconvert;
+
+class MakePat<list<dag> patterns> : Pat<patterns[0], patterns[1]>;
+
+class Base<bits<8> opcode, dag opnds, dag iopnds, string asmstr, Intrinsic intr,
+ list<list<dag>> patterns>
+ : Inst<opcode, opnds, iopnds, asmstr,
+ !foreach(Decls.pattern, patterns[0],
+ !foreach(Decls.operand, Decls.pattern,
+ !subst(INTRINSIC, intr,
+ !subst(REGCLASS, VR128,
+ !subst(MNEMONIC, set, Decls.operand)))))>,
+ MakePat<!foreach(Decls.pattern, patterns[1],
+ !foreach(Decls.operand, Decls.pattern,
+ !subst(INTRINSIC, intr,
+ !subst(REGCLASS, VR128,
+ !subst(MNEMONIC, set, Decls.operand)))))>;
+
+multiclass arith<bits<8> opcode, string asmstr, string intr, list<list<dag>> patterns> {
+ def PS : Base<opcode, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
+ !strconcat(asmstr, "\t$dst, $src1, $src2"), !cast<Intrinsic>(!subst("SUFFIX", "_ps", intr)), patterns>;
+
+ def PD : Base<opcode, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
+ !strconcat(asmstr, "\t$dst, $src1, $src2"), !cast<Intrinsic>(!subst("SUFFIX", "_pd", intr)), patterns>;
+}
+
+defm ADD : arith<0x58, "add", "int_x86_sse2_addSUFFIX",
+ // rr Patterns
+ [[(set REGCLASS:$dst, (INTRINSIC REGCLASS:$src1, REGCLASS:$src2))],
+ [(set REGCLASS:$dst, (bitconvert (INTRINSIC REGCLASS:$src1, REGCLASS:$src2))),
+ (MNEMONIC REGCLASS:$dst, REGCLASS:$src)]]>;
+
+// CHECK: [(set VR128:$dst, (int_x86_sse2_add_pd VR128:$src1, VR128:$src2))]
+// CHECK: [(set VR128:$dst, (int_x86_sse2_add_ps VR128:$src1, VR128:$src2))]
diff --git a/test/TableGen/SetTheory.td b/test/TableGen/SetTheory.td
index e0abc63..a4acea9 100644
--- a/test/TableGen/SetTheory.td
+++ b/test/TableGen/SetTheory.td
@@ -1,5 +1,5 @@
// Test evaluation of set operations in dags.
-// RUN: tblgen -print-sets %s | FileCheck %s
+// RUN: llvm-tblgen -print-sets %s | FileCheck %s
// XFAIL: vg_leak
//
// The -print-sets driver configures a primitive SetTheory instance that
diff --git a/test/TableGen/Slice.td b/test/TableGen/Slice.td
index 13d9da2..2d2822c 100644
--- a/test/TableGen/Slice.td
+++ b/test/TableGen/Slice.td
@@ -1,5 +1,5 @@
-// RUN: tblgen %s | grep {\\\[(set} | count 2
-// RUN: tblgen %s | grep {\\\[\\\]} | count 2
+// RUN: llvm-tblgen %s | grep {\\\[(set} | count 2
+// RUN: llvm-tblgen %s | grep {\\\[\\\]} | count 2
// XFAIL: vg_leak
class ValueType<int size, int value> {
diff --git a/test/TableGen/String.td b/test/TableGen/String.td
index fc0f5b8..c71ed50 100644
--- a/test/TableGen/String.td
+++ b/test/TableGen/String.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
class x {
string y = "missing terminating '\"' character";
diff --git a/test/TableGen/SuperSubclassSameName.td b/test/TableGen/SuperSubclassSameName.td
index 304c883..643b380 100644
--- a/test/TableGen/SuperSubclassSameName.td
+++ b/test/TableGen/SuperSubclassSameName.td
@@ -1,4 +1,4 @@
-// RUN: tblgen < %s
+// RUN: llvm-tblgen < %s
// XFAIL: vg_leak
// Test for template arguments that have the same name as superclass template
// arguments.
diff --git a/test/TableGen/TargetInstrInfo.td b/test/TableGen/TargetInstrInfo.td
index 6c39d5c..e6c563b 100644
--- a/test/TableGen/TargetInstrInfo.td
+++ b/test/TableGen/TargetInstrInfo.td
@@ -1,6 +1,6 @@
// This test describes how we eventually want to describe instructions in
// the target independent code generators.
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
// Target indep stuff.
diff --git a/test/TableGen/TargetInstrSpec.td b/test/TableGen/TargetInstrSpec.td
index a7ca902..7b611e7 100644
--- a/test/TableGen/TargetInstrSpec.td
+++ b/test/TableGen/TargetInstrSpec.td
@@ -1,5 +1,5 @@
-// RUN: tblgen %s | grep {\\\[(set VR128:\$dst, (int_x86_sse2_add_pd VR128:\$src1, VR128:\$src2))\\\]} | count 1
-// RUN: tblgen %s | grep {\\\[(set VR128:\$dst, (int_x86_sse2_add_ps VR128:\$src1, VR128:\$src2))\\\]} | count 1
+// RUN: llvm-tblgen %s | grep {\\\[(set VR128:\$dst, (int_x86_sse2_add_pd VR128:\$src1, VR128:\$src2))\\\]} | count 1
+// RUN: llvm-tblgen %s | grep {\\\[(set VR128:\$dst, (int_x86_sse2_add_ps VR128:\$src1, VR128:\$src2))\\\]} | count 1
// XFAIL: vg_leak
class ValueType<int size, int value> {
diff --git a/test/TableGen/TemplateArgRename.td b/test/TableGen/TemplateArgRename.td
index ee5d2cf..654b86d 100644
--- a/test/TableGen/TemplateArgRename.td
+++ b/test/TableGen/TemplateArgRename.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
// Make sure there is no collision between XX and XX.
diff --git a/test/TableGen/Tree.td b/test/TableGen/Tree.td
index 2796cfd..5190b96 100644
--- a/test/TableGen/Tree.td
+++ b/test/TableGen/Tree.td
@@ -1,5 +1,5 @@
// This tests to make sure we can parse tree patterns.
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
class TreeNode;
diff --git a/test/TableGen/TreeNames.td b/test/TableGen/TreeNames.td
index ccdeb88..b224e90 100644
--- a/test/TableGen/TreeNames.td
+++ b/test/TableGen/TreeNames.td
@@ -1,5 +1,5 @@
// This tests to make sure we can parse tree patterns with names.
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
class TreeNode;
diff --git a/test/TableGen/UnsetBitInit.td b/test/TableGen/UnsetBitInit.td
index ff70108..d232293 100644
--- a/test/TableGen/UnsetBitInit.td
+++ b/test/TableGen/UnsetBitInit.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s
+// RUN: llvm-tblgen %s
// XFAIL: vg_leak
class x {
field bits<32> A;
diff --git a/test/TableGen/UnterminatedComment.td b/test/TableGen/UnterminatedComment.td
index 158cede..f92525a 100644
--- a/test/TableGen/UnterminatedComment.td
+++ b/test/TableGen/UnterminatedComment.td
@@ -1,4 +1,4 @@
-// RUN: not tblgen < %s >& /dev/null
+// RUN: not llvm-tblgen < %s >& /dev/null
def x;
diff --git a/test/TableGen/cast.td b/test/TableGen/cast.td
index 8164e74..8a23eb4 100644
--- a/test/TableGen/cast.td
+++ b/test/TableGen/cast.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep {add_ps} | count 3
+// RUN: llvm-tblgen %s | grep {add_ps} | count 3
// XFAIL: vg_leak
class ValueType<int size, int value> {
diff --git a/test/TableGen/defmclass.td b/test/TableGen/defmclass.td
index 57972b6..80f03b3 100644
--- a/test/TableGen/defmclass.td
+++ b/test/TableGen/defmclass.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | FileCheck %s
+// RUN: llvm-tblgen %s | FileCheck %s
// XFAIL: vg_leak
class XD { bits<4> Prefix = 11; }
diff --git a/test/TableGen/eq.td b/test/TableGen/eq.td
index 518a80a..f8daf88 100644
--- a/test/TableGen/eq.td
+++ b/test/TableGen/eq.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | FileCheck %s
+// RUN: llvm-tblgen %s | FileCheck %s
// XFAIL: vg_leak
// CHECK: Value = 0
// CHECK: Value = 1
diff --git a/test/TableGen/eqbit.td b/test/TableGen/eqbit.td
index 3953252c..1d58fa0 100644
--- a/test/TableGen/eqbit.td
+++ b/test/TableGen/eqbit.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | FileCheck %s
+// RUN: llvm-tblgen %s | FileCheck %s
// XFAIL: vg_leak
// CHECK: a = 6
// CHECK: a = 5
diff --git a/test/TableGen/foreach.td b/test/TableGen/foreach.td
index d4d81f8..cbcade9 100644
--- a/test/TableGen/foreach.td
+++ b/test/TableGen/foreach.td
@@ -1,6 +1,6 @@
-// RUN: tblgen %s | grep {Jr} | count 2
-// RUN: tblgen %s | grep {Sr} | count 2
-// RUN: tblgen %s | grep {NAME} | count 1
+// RUN: llvm-tblgen %s | grep {Jr} | count 2
+// RUN: llvm-tblgen %s | grep {Sr} | count 2
+// RUN: llvm-tblgen %s | grep {NAME} | count 1
// XFAIL: vg_leak
// Variables for foreach
diff --git a/test/TableGen/if.td b/test/TableGen/if.td
index c4d953e..18de368 100644
--- a/test/TableGen/if.td
+++ b/test/TableGen/if.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | FileCheck %s
+// RUN: llvm-tblgen %s | FileCheck %s
// XFAIL: vg_leak
// Support for an `!if' operator as part of a `let' statement.
diff --git a/test/TableGen/ifbit.td b/test/TableGen/ifbit.td
index 3b0349e..88f575e 100644
--- a/test/TableGen/ifbit.td
+++ b/test/TableGen/ifbit.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | FileCheck %s
+// RUN: llvm-tblgen %s | FileCheck %s
// XFAIL: vg_leak
// CHECK: a = 6
// CHECK: a = 5
diff --git a/test/TableGen/lisp.td b/test/TableGen/lisp.td
index bbed869..025aca9 100644
--- a/test/TableGen/lisp.td
+++ b/test/TableGen/lisp.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep {}
+// RUN: llvm-tblgen %s | grep {}
// XFAIL: vg_leak
class List<list<string> n> {
diff --git a/test/TableGen/nested-comment.td b/test/TableGen/nested-comment.td
index 68e2958..bf030e7 100644
--- a/test/TableGen/nested-comment.td
+++ b/test/TableGen/nested-comment.td
@@ -1,4 +1,5 @@
-// RUN: tblgen < %s
+// RUN: llvm-tblgen < %s
+// XFAIL: vg_leak
/* foo
diff --git a/test/TableGen/strconcat.td b/test/TableGen/strconcat.td
index 38409a9..85ee831 100644
--- a/test/TableGen/strconcat.td
+++ b/test/TableGen/strconcat.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep fufoo
+// RUN: llvm-tblgen %s | grep fufoo
// XFAIL: vg_leak
class Y<string S> {
diff --git a/test/TableGen/subst.td b/test/TableGen/subst.td
index 05d424f..5a73ec4 100644
--- a/test/TableGen/subst.td
+++ b/test/TableGen/subst.td
@@ -1,9 +1,9 @@
-// RUN: tblgen %s | grep {Smith} | count 7
-// RUN: tblgen %s | grep {Johnson} | count 2
-// RUN: tblgen %s | grep {FIRST} | count 1
-// RUN: tblgen %s | grep {LAST} | count 1
-// RUN: tblgen %s | grep {TVAR} | count 2
-// RUN: tblgen %s | grep {Bogus} | count 1
+// RUN: llvm-tblgen %s | grep {Smith} | count 7
+// RUN: llvm-tblgen %s | grep {Johnson} | count 2
+// RUN: llvm-tblgen %s | grep {FIRST} | count 1
+// RUN: llvm-tblgen %s | grep {LAST} | count 1
+// RUN: llvm-tblgen %s | grep {TVAR} | count 2
+// RUN: llvm-tblgen %s | grep {Bogus} | count 1
// XFAIL: vg_leak
class Honorific<string t> {
diff --git a/test/TableGen/subst2.td b/test/TableGen/subst2.td
index 584266e..7c007f7 100644
--- a/test/TableGen/subst2.td
+++ b/test/TableGen/subst2.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | FileCheck %s
+// RUN: llvm-tblgen %s | FileCheck %s
// XFAIL: vg_leak
// CHECK: No subst
// CHECK: No foo
diff --git a/test/TableGen/usevalname.td b/test/TableGen/usevalname.td
index 1b31c8f..d85b98a 100644
--- a/test/TableGen/usevalname.td
+++ b/test/TableGen/usevalname.td
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | FileCheck %s
+// RUN: llvm-tblgen %s | FileCheck %s
// XFAIL: vg_leak
class Instr<list<dag> pat> {
diff --git a/test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll b/test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll
index 444ca8e..6bbcfdb 100644
--- a/test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll
+++ b/test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll
@@ -8,7 +8,9 @@ then: ; preds = %0
to label %invoke_cont unwind label %invoke_catch
invoke_catch: ; preds = %then
- unwind
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ resume { i8*, i32 } %exn
invoke_cont: ; preds = %then
ret void
@@ -17,3 +19,4 @@ endif: ; preds = %0
ret void
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll b/test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll
index a6a41fd..7ee0f46 100644
--- a/test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll
+++ b/test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll
@@ -11,6 +11,6 @@ invoke_catch.0: ; No predecessors!
br i1 false, label %UnifiedUnwindBlock, label %UnifiedReturnBlock
UnifiedUnwindBlock: ; preds = %invoke_catch.0
- unwind
+ unreachable
}
diff --git a/test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll b/test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll
index 991e876..4ddc2f1 100644
--- a/test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll
+++ b/test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll
@@ -15,17 +15,21 @@ tmp.3.i.noexc: ; preds = %entry
br i1 false, label %then.0, label %else.0
invoke_catch.0: ; preds = %entry
+ %exn.0 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
invoke void @q_atomic_decrement( )
to label %tmp.1.i.i183.noexc unwind label %terminate
tmp.1.i.i183.noexc: ; preds = %invoke_catch.0
- unwind
+ ret void
then.0: ; preds = %tmp.3.i.noexc
invoke void @_ZN10QByteArray6resizeEi( )
to label %invoke_cont.1 unwind label %invoke_catch.1
invoke_catch.1: ; preds = %then.0
+ %exn.1 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
invoke void @q_atomic_decrement( )
to label %tmp.1.i.i162.noexc unwind label %terminate
@@ -40,6 +44,9 @@ else.0: ; preds = %tmp.3.i.noexc
terminate: ; preds = %invoke_catch.1, %invoke_catch.0
%dbg.0.1 = phi { }* [ null, %invoke_catch.1 ], [ null, %invoke_catch.0 ] ; <{ }*> [#uses=0]
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/ADCE/dce_pure_invoke.ll b/test/Transforms/ADCE/dce_pure_invoke.ll
index c16d45c..8e78518 100644
--- a/test/Transforms/ADCE/dce_pure_invoke.ll
+++ b/test/Transforms/ADCE/dce_pure_invoke.ll
@@ -11,5 +11,9 @@ Cont: ; preds = %0
ret i32 0
Other: ; preds = %0
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i32 1
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll b/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll
index 91e9799..ff5de6b 100644
--- a/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll
+++ b/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll
@@ -190,5 +190,9 @@ return: ; preds = %entry
ret void
LongJmpBlkPre: ; preds = %endif.52, %then.40
+ %exn = landingpad { i8*, i32 } personality i32 (...)* @__gcc_personality_v0
+ catch i8* null
ret void
}
+
+declare i32 @__gcc_personality_v0(...)
diff --git a/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll b/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll
index fc58577..92603d9 100644
--- a/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll
+++ b/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll
@@ -10,6 +10,9 @@ Cont: ; preds = %EB
ret i32 %V
Unw: ; preds = %EB
- unwind
+ %exn = landingpad { i8*, i32 } personality i32 (...)* @__gcc_personality_v0
+ catch i8* null
+ resume { i8*, i32 } %exn
}
+declare i32 @__gcc_personality_v0(...)
diff --git a/test/Transforms/ConstantMerge/merge-both.ll b/test/Transforms/ConstantMerge/merge-both.ll
index 0282f46..b71eb43 100644
--- a/test/Transforms/ConstantMerge/merge-both.ll
+++ b/test/Transforms/ConstantMerge/merge-both.ll
@@ -1,5 +1,7 @@
; RUN: opt -constmerge %s -S -o - | FileCheck %s
; Test that in one run var3 is merged into var2 and var1 into var4.
+; Test that we merge @var5 and @var6 into one with the higher alignment, and
+; don't merge var7/var8 into var5/var6.
declare void @zed(%struct.foobar*, %struct.foobar*)
@@ -14,13 +16,24 @@ declare void @zed(%struct.foobar*, %struct.foobar*)
; CHECK-NOT: @
; CHECK: @var2 = constant %struct.foobar { i32 2 }
; CHECK-NEXT: @var4 = constant %struct.foobar { i32 2 }
-; CHECK-NOT: @
-; CHECK: declare void @zed(%struct.foobar*, %struct.foobar*)
+
+declare void @helper([16 x i8]*)
+@var5 = internal constant [16 x i8] c"foo1bar2foo3bar\00", align 16
+@var6 = private unnamed_addr constant [16 x i8] c"foo1bar2foo3bar\00", align 1
+@var7 = internal constant [16 x i8] c"foo1bar2foo3bar\00"
+@var8 = private unnamed_addr constant [16 x i8] c"foo1bar2foo3bar\00"
+
+; CHECK-NEXT: @var6 = private constant [16 x i8] c"foo1bar2foo3bar\00", align 16
+; CHECK-NEXT: @var8 = private constant [16 x i8] c"foo1bar2foo3bar\00"
define i32 @main() {
entry:
call void @zed(%struct.foobar* @var1, %struct.foobar* @var2)
call void @zed(%struct.foobar* @var3, %struct.foobar* @var4)
+ call void @helper([16 x i8]* @var5)
+ call void @helper([16 x i8]* @var6)
+ call void @helper([16 x i8]* @var7)
+ call void @helper([16 x i8]* @var8)
ret i32 0
}
diff --git a/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll b/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll
index 161821f..fc25dac 100644
--- a/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll
+++ b/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll
@@ -11,6 +11,8 @@ T:
%y = extractvalue {i32,i32} %x, 1
ret i32 %y
T2:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
@@ -22,5 +24,9 @@ T:
%y = extractvalue {i32,i32} %x, 1
ret i32 %y
T2:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/DeadArgElim/deadexternal.ll b/test/Transforms/DeadArgElim/deadexternal.ll
index 8409261..b2d63ec 100644
--- a/test/Transforms/DeadArgElim/deadexternal.ll
+++ b/test/Transforms/DeadArgElim/deadexternal.ll
@@ -31,7 +31,7 @@ define void @h() {
entry:
%i = alloca i32, align 4
volatile store i32 10, i32* %i, align 4
-; CHECK: %tmp = volatile load i32* %i, align 4
+; CHECK: %tmp = load volatile i32* %i, align 4
; CHECK-next: call void @f(i32 undef)
%tmp = volatile load i32* %i, align 4
call void @f(i32 %tmp)
diff --git a/test/Transforms/DeadStoreElimination/2011-09-06-EndOfFunction.ll b/test/Transforms/DeadStoreElimination/2011-09-06-EndOfFunction.ll
new file mode 100644
index 0000000..c5cc101
--- /dev/null
+++ b/test/Transforms/DeadStoreElimination/2011-09-06-EndOfFunction.ll
@@ -0,0 +1,27 @@
+; RUN: opt -dse -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin"
+
+%"class.std::auto_ptr" = type { i32* }
+
+; CHECK: @_Z3foov
+define void @_Z3foov(%"class.std::auto_ptr"* noalias nocapture sret %agg.result) uwtable ssp {
+_ZNSt8auto_ptrIiED1Ev.exit:
+ %temp.lvalue = alloca %"class.std::auto_ptr", align 8
+ call void @_Z3barv(%"class.std::auto_ptr"* sret %temp.lvalue)
+ %_M_ptr.i.i = getelementptr inbounds %"class.std::auto_ptr"* %temp.lvalue, i64 0, i32 0
+ %tmp.i.i = load i32** %_M_ptr.i.i, align 8, !tbaa !0
+; CHECK-NOT: store i32* null
+ store i32* null, i32** %_M_ptr.i.i, align 8, !tbaa !0
+ %_M_ptr.i.i4 = getelementptr inbounds %"class.std::auto_ptr"* %agg.result, i64 0, i32 0
+ store i32* %tmp.i.i, i32** %_M_ptr.i.i4, align 8, !tbaa !0
+; CHECK: ret void
+ ret void
+}
+
+declare void @_Z3barv(%"class.std::auto_ptr"* sret)
+
+!0 = metadata !{metadata !"any pointer", metadata !1}
+!1 = metadata !{metadata !"omnipotent char", metadata !2}
+!2 = metadata !{metadata !"Simple C/C++ TBAA", null}
diff --git a/test/Transforms/DeadStoreElimination/2011-09-06-MemCpy.ll b/test/Transforms/DeadStoreElimination/2011-09-06-MemCpy.ll
new file mode 100644
index 0000000..22b8786
--- /dev/null
+++ b/test/Transforms/DeadStoreElimination/2011-09-06-MemCpy.ll
@@ -0,0 +1,85 @@
+; RUN: opt -dse -S < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.pair.162 = type { %struct.BasicBlock*, i32, [4 x i8] }
+%struct.BasicBlock = type { %struct.Value, %struct.ilist_node.24, %struct.iplist.22, %struct.Function* }
+%struct.Value = type { i32 (...)**, i8, i8, i16, %struct.Type*, %struct.Use*, %struct.StringMapEntry* }
+%struct.Type = type { %struct.LLVMContext*, i8, [3 x i8], i32, {}* }
+%struct.LLVMContext = type { %struct.LLVMContextImpl* }
+%struct.LLVMContextImpl = type opaque
+%struct.Use = type { %struct.Value*, %struct.Use*, %struct.PointerIntPair }
+%struct.PointerIntPair = type { i64 }
+%struct.StringMapEntry = type opaque
+%struct.ilist_node.24 = type { %struct.ilist_half_node.23, %struct.BasicBlock* }
+%struct.ilist_half_node.23 = type { %struct.BasicBlock* }
+%struct.iplist.22 = type { %struct.ilist_traits.21, %struct.Instruction* }
+%struct.ilist_traits.21 = type { %struct.ilist_half_node.25 }
+%struct.ilist_half_node.25 = type { %struct.Instruction* }
+%struct.Instruction = type { [52 x i8], %struct.ilist_node.26, %struct.BasicBlock*, %struct.DebugLoc }
+%struct.ilist_node.26 = type { %struct.ilist_half_node.25, %struct.Instruction* }
+%struct.DebugLoc = type { i32, i32 }
+%struct.Function = type { %struct.GlobalValue, %struct.ilist_node.14, %struct.iplist.4, %struct.iplist, %struct.ValueSymbolTable*, %struct.AttrListPtr }
+%struct.GlobalValue = type <{ [52 x i8], [4 x i8], %struct.Module*, i8, i16, [5 x i8], %struct.basic_string }>
+%struct.Module = type { %struct.LLVMContext*, %struct.iplist.20, %struct.iplist.16, %struct.iplist.12, %struct.vector.2, %struct.ilist, %struct.basic_string, %struct.ValueSymbolTable*, %struct.OwningPtr, %struct.basic_string, %struct.basic_string, %struct.basic_string, i8* }
+%struct.iplist.20 = type { %struct.ilist_traits.19, %struct.GlobalVariable* }
+%struct.ilist_traits.19 = type { %struct.ilist_node.18 }
+%struct.ilist_node.18 = type { %struct.ilist_half_node.17, %struct.GlobalVariable* }
+%struct.ilist_half_node.17 = type { %struct.GlobalVariable* }
+%struct.GlobalVariable = type { %struct.GlobalValue, %struct.ilist_node.18, i8, [7 x i8] }
+%struct.iplist.16 = type { %struct.ilist_traits.15, %struct.Function* }
+%struct.ilist_traits.15 = type { %struct.ilist_node.14 }
+%struct.ilist_node.14 = type { %struct.ilist_half_node.13, %struct.Function* }
+%struct.ilist_half_node.13 = type { %struct.Function* }
+%struct.iplist.12 = type { %struct.ilist_traits.11, %struct.GlobalAlias* }
+%struct.ilist_traits.11 = type { %struct.ilist_node.10 }
+%struct.ilist_node.10 = type { %struct.ilist_half_node.9, %struct.GlobalAlias* }
+%struct.ilist_half_node.9 = type { %struct.GlobalAlias* }
+%struct.GlobalAlias = type { %struct.GlobalValue, %struct.ilist_node.10 }
+%struct.vector.2 = type { %struct._Vector_base.1 }
+%struct._Vector_base.1 = type { %struct._Vector_impl.0 }
+%struct._Vector_impl.0 = type { %struct.basic_string*, %struct.basic_string*, %struct.basic_string* }
+%struct.basic_string = type { %struct._Alloc_hider }
+%struct._Alloc_hider = type { i8* }
+%struct.ilist = type { %struct.iplist.8 }
+%struct.iplist.8 = type { %struct.ilist_traits.7, %struct.NamedMDNode* }
+%struct.ilist_traits.7 = type { %struct.ilist_node.6 }
+%struct.ilist_node.6 = type { %struct.ilist_half_node.5, %struct.NamedMDNode* }
+%struct.ilist_half_node.5 = type { %struct.NamedMDNode* }
+%struct.NamedMDNode = type { %struct.ilist_node.6, %struct.basic_string, %struct.Module*, i8* }
+%struct.ValueSymbolTable = type opaque
+%struct.OwningPtr = type { %struct.GVMaterializer* }
+%struct.GVMaterializer = type opaque
+%struct.iplist.4 = type { %struct.ilist_traits.3, %struct.BasicBlock* }
+%struct.ilist_traits.3 = type { %struct.ilist_half_node.23 }
+%struct.iplist = type { %struct.ilist_traits, %struct.Argument* }
+%struct.ilist_traits = type { %struct.ilist_half_node }
+%struct.ilist_half_node = type { %struct.Argument* }
+%struct.Argument = type { %struct.Value, %struct.ilist_node, %struct.Function* }
+%struct.ilist_node = type { %struct.ilist_half_node, %struct.Argument* }
+%struct.AttrListPtr = type { %struct.AttributeListImpl* }
+%struct.AttributeListImpl = type opaque
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
+
+; CHECK: _ZSt9iter_swapIPSt4pairIPN4llvm10BasicBlockEjES5_EvT_T0_
+; CHECK: store
+; CHECK: ret void
+define void @_ZSt9iter_swapIPSt4pairIPN4llvm10BasicBlockEjES5_EvT_T0_(%struct.pair.162* %__a, %struct.pair.162* %__b) nounwind uwtable inlinehint {
+entry:
+ %memtmp = alloca %struct.pair.162, align 8
+ %0 = getelementptr inbounds %struct.pair.162* %memtmp, i64 0, i32 0
+ %1 = getelementptr inbounds %struct.pair.162* %__a, i64 0, i32 0
+ %2 = load %struct.BasicBlock** %1, align 8
+ store %struct.BasicBlock* %2, %struct.BasicBlock** %0, align 8
+ %3 = getelementptr inbounds %struct.pair.162* %memtmp, i64 0, i32 1
+ %4 = getelementptr inbounds %struct.pair.162* %__a, i64 0, i32 1
+ %5 = load i32* %4, align 4
+ store i32 %5, i32* %3, align 8
+ %6 = bitcast %struct.pair.162* %__a to i8*
+ %7 = bitcast %struct.pair.162* %__b to i8*
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* %6, i8* %7, i64 12, i32 1, i1 false)
+ %8 = bitcast %struct.pair.162* %memtmp to i8*
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* %7, i8* %8, i64 12, i32 1, i1 false)
+ ret void
+}
diff --git a/test/Transforms/DeadStoreElimination/atomic.ll b/test/Transforms/DeadStoreElimination/atomic.ll
new file mode 100644
index 0000000..2e84298
--- /dev/null
+++ b/test/Transforms/DeadStoreElimination/atomic.ll
@@ -0,0 +1,107 @@
+; RUN: opt -basicaa -dse -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+; Sanity tests for atomic stores.
+; Note that it turns out essentially every transformation DSE does is legal on
+; atomic ops, just some transformations are not allowed across them.
+
+@x = common global i32 0, align 4
+@y = common global i32 0, align 4
+
+declare void @randomop(i32*)
+
+; DSE across unordered store (allowed)
+define void @test1() nounwind uwtable ssp {
+; CHECK: test1
+; CHECK-NOT: store i32 0
+; CHECK: store i32 1
+entry:
+ store i32 0, i32* @x
+ store atomic i32 0, i32* @y unordered, align 4
+ store i32 1, i32* @x
+ ret void
+}
+
+; DSE across seq_cst load (allowed in theory; not implemented ATM)
+define i32 @test2() nounwind uwtable ssp {
+; CHECK: test2
+; CHECK: store i32 0
+; CHECK: store i32 1
+entry:
+ store i32 0, i32* @x
+ %x = load atomic i32* @y seq_cst, align 4
+ store i32 1, i32* @x
+ ret i32 %x
+}
+
+; DSE across seq_cst store (store before atomic store must not be removed)
+define void @test3() nounwind uwtable ssp {
+; CHECK: test3
+; CHECK: store i32
+; CHECK: store atomic i32 2
+entry:
+ store i32 0, i32* @x
+ store atomic i32 2, i32* @y seq_cst, align 4
+ store i32 1, i32* @x
+ ret void
+}
+
+; DSE remove unordered store (allowed)
+define void @test4() nounwind uwtable ssp {
+; CHECK: test4
+; CHECK-NOT: store atomic
+; CHECK: store i32 1
+entry:
+ store atomic i32 0, i32* @x unordered, align 4
+ store i32 1, i32* @x
+ ret void
+}
+
+; DSE unordered store overwriting non-atomic store (allowed)
+define void @test5() nounwind uwtable ssp {
+; CHECK: test5
+; CHECK: store atomic i32 1
+entry:
+ store i32 0, i32* @x
+ store atomic i32 1, i32* @x unordered, align 4
+ ret void
+}
+
+; DSE no-op unordered atomic store (allowed)
+define void @test6() nounwind uwtable ssp {
+; CHECK: test6
+; CHECK-NOT: store
+; CHECK: ret void
+entry:
+ %x = load atomic i32* @x unordered, align 4
+ store atomic i32 %x, i32* @x unordered, align 4
+ ret void
+}
+
+; DSE seq_cst store (be conservative; DSE doesn't have infrastructure
+; to reason about atomic operations).
+define void @test7() nounwind uwtable ssp {
+; CHECK: test7
+; CHECK: store atomic
+entry:
+ %a = alloca i32
+ store atomic i32 0, i32* %a seq_cst, align 4
+ ret void
+}
+
+; DSE and seq_cst load (be conservative; DSE doesn't have infrastructure
+; to reason about atomic operations).
+define i32 @test8() nounwind uwtable ssp {
+; CHECK: test8
+; CHECK: store
+; CHECK: load atomic
+entry:
+ %a = alloca i32
+ call void @randomop(i32* %a)
+ store i32 0, i32* %a, align 4
+ %x = load atomic i32* @x seq_cst, align 4
+ ret i32 %x
+}
+
diff --git a/test/Transforms/DeadStoreElimination/simple.ll b/test/Transforms/DeadStoreElimination/simple.ll
index 5f143fc..ec2f157 100644
--- a/test/Transforms/DeadStoreElimination/simple.ll
+++ b/test/Transforms/DeadStoreElimination/simple.ll
@@ -42,20 +42,20 @@ define i32 @test3(i32* %g_addr) nounwind {
define void @test4(i32* %Q) {
%a = load i32* %Q
- volatile store i32 %a, i32* %Q
+ store volatile i32 %a, i32* %Q
ret void
; CHECK: @test4
; CHECK-NEXT: load i32
-; CHECK-NEXT: volatile store
+; CHECK-NEXT: store volatile
; CHECK-NEXT: ret void
}
define void @test5(i32* %Q) {
- %a = volatile load i32* %Q
+ %a = load volatile i32* %Q
store i32 %a, i32* %Q
ret void
; CHECK: @test5
-; CHECK-NEXT: volatile load
+; CHECK-NEXT: load volatile
; CHECK-NEXT: ret void
}
diff --git a/test/Transforms/EarlyCSE/basic.ll b/test/Transforms/EarlyCSE/basic.ll
index e3c75f9..57b1697 100644
--- a/test/Transforms/EarlyCSE/basic.ll
+++ b/test/Transforms/EarlyCSE/basic.ll
@@ -13,21 +13,21 @@ define void @test1(i8 %V, i32 *%P) {
volatile store i32 %C, i32* %P
volatile store i32 %D, i32* %P
; CHECK-NEXT: %C = zext i8 %V to i32
- ; CHECK-NEXT: volatile store i32 %C
- ; CHECK-NEXT: volatile store i32 %C
+ ; CHECK-NEXT: store volatile i32 %C
+ ; CHECK-NEXT: store volatile i32 %C
%E = add i32 %C, %C
%F = add i32 %C, %C
volatile store i32 %E, i32* %P
volatile store i32 %F, i32* %P
; CHECK-NEXT: %E = add i32 %C, %C
- ; CHECK-NEXT: volatile store i32 %E
- ; CHECK-NEXT: volatile store i32 %E
+ ; CHECK-NEXT: store volatile i32 %E
+ ; CHECK-NEXT: store volatile i32 %E
%G = add nuw i32 %C, %C ;; not a CSE with E
volatile store i32 %G, i32* %P
; CHECK-NEXT: %G = add nuw i32 %C, %C
- ; CHECK-NEXT: volatile store i32 %G
+ ; CHECK-NEXT: store volatile i32 %G
ret void
}
diff --git a/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll b/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll
index 53857f6..e2bab19 100644
--- a/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll
+++ b/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll
@@ -46,9 +46,13 @@ define i1 @c6(i8* %q, i8 %bit) {
ret0:
ret i1 0
ret1:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i1 1
}
+declare i32 @__gxx_personality_v0(...)
+
define i1* @lookup_bit(i32* %q, i32 %bitno) readnone nounwind {
%tmp = ptrtoint i32* %q to i32
%tmp2 = lshr i32 %tmp, %bitno
diff --git a/test/Transforms/FunctionAttrs/atomic.ll b/test/Transforms/FunctionAttrs/atomic.ll
new file mode 100644
index 0000000..7c2bff7
--- /dev/null
+++ b/test/Transforms/FunctionAttrs/atomic.ll
@@ -0,0 +1,21 @@
+; RUN: opt -basicaa -functionattrs -S < %s | FileCheck %s
+
+; Atomic load/store to local doesn't affect whether a function is
+; readnone/readonly.
+define i32 @test1(i32 %x) uwtable ssp {
+; CHECK: define i32 @test1(i32 %x) uwtable readnone ssp {
+entry:
+ %x.addr = alloca i32, align 4
+ store atomic i32 %x, i32* %x.addr seq_cst, align 4
+ %r = load atomic i32* %x.addr seq_cst, align 4
+ ret i32 %r
+}
+
+; A function with an Acquire load is not readonly.
+define i32 @test2(i32* %x) uwtable ssp {
+; CHECK: define i32 @test2(i32* nocapture %x) uwtable ssp {
+entry:
+ %r = load atomic i32* %x seq_cst, align 4
+ ret i32 %r
+}
+
diff --git a/test/Transforms/GVN/2010-05-08-OneBit.ll b/test/Transforms/GVN/2010-05-08-OneBit.ll
index 1809cf0..480ce8b 100644
--- a/test/Transforms/GVN/2010-05-08-OneBit.ll
+++ b/test/Transforms/GVN/2010-05-08-OneBit.ll
@@ -45,6 +45,8 @@ k151.i.i: ; preds = %k133.i.i
ret i32 0
landing_pad: ; preds = %l147.i.i, %l129.i.i, %l117.i.i
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
switch i32 undef, label %fin [
i32 1, label %catch1
i32 2, label %catch
@@ -61,3 +63,5 @@ catch1: ; preds = %landing_pad
}
declare fastcc void @foo()
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/GVN/2011-09-07-TypeIdFor.ll b/test/Transforms/GVN/2011-09-07-TypeIdFor.ll
new file mode 100644
index 0000000..314b5bb
--- /dev/null
+++ b/test/Transforms/GVN/2011-09-07-TypeIdFor.ll
@@ -0,0 +1,81 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+%struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo }
+%struct.__type_info_pseudo = type { i8*, i8* }
+
+@_ZTIi = external constant %struct.__fundamental_type_info_pseudo
+@_ZTIb = external constant %struct.__fundamental_type_info_pseudo
+
+declare void @_Z4barv()
+
+declare void @_Z7cleanupv()
+
+declare i32 @llvm.eh.typeid.for(i8*) nounwind readonly
+
+declare i8* @__cxa_begin_catch(i8*) nounwind
+
+declare void @__cxa_end_catch()
+
+declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)
+
+define void @_Z3foov() uwtable {
+entry:
+ invoke void @_Z4barv()
+ to label %return unwind label %lpad
+
+lpad: ; preds = %entry
+ %0 = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0
+ catch %struct.__fundamental_type_info_pseudo* @_ZTIi
+ catch %struct.__fundamental_type_info_pseudo* @_ZTIb
+ catch %struct.__fundamental_type_info_pseudo* @_ZTIi
+ catch %struct.__fundamental_type_info_pseudo* @_ZTIb
+ %exc_ptr2.i = extractvalue { i8*, i32 } %0, 0
+ %filter3.i = extractvalue { i8*, i32 } %0, 1
+ %typeid.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*))
+; CHECK: call i32 @llvm.eh.typeid.for
+ %1 = icmp eq i32 %filter3.i, %typeid.i
+ br i1 %1, label %ppad, label %next
+
+next: ; preds = %lpad
+ %typeid1.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*))
+; CHECK: call i32 @llvm.eh.typeid.for
+ %2 = icmp eq i32 %filter3.i, %typeid1.i
+ br i1 %2, label %ppad2, label %next2
+
+ppad: ; preds = %lpad
+ %3 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
+ tail call void @__cxa_end_catch() nounwind
+ br label %return
+
+ppad2: ; preds = %next
+ %D.2073_5.i = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
+ tail call void @__cxa_end_catch() nounwind
+ br label %return
+
+next2: ; preds = %next
+ call void @_Z7cleanupv()
+ %typeid = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*))
+; CHECK-NOT: call i32 @llvm.eh.typeid.for
+ %4 = icmp eq i32 %filter3.i, %typeid
+ br i1 %4, label %ppad3, label %next3
+
+next3: ; preds = %next2
+ %typeid1 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*))
+ %5 = icmp eq i32 %filter3.i, %typeid1
+ br i1 %5, label %ppad4, label %unwind
+
+unwind: ; preds = %next3
+ resume { i8*, i32 } %0
+
+ppad3: ; preds = %next2
+ %6 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
+ tail call void @__cxa_end_catch() nounwind
+ br label %return
+
+ppad4: ; preds = %next3
+ %D.2080_5 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
+ tail call void @__cxa_end_catch() nounwind
+ br label %return
+
+return: ; preds = %ppad4, %ppad3, %ppad2, %ppad, %entry
+ ret void
+}
diff --git a/test/Transforms/GVN/atomic.ll b/test/Transforms/GVN/atomic.ll
new file mode 100644
index 0000000..094e22b
--- /dev/null
+++ b/test/Transforms/GVN/atomic.ll
@@ -0,0 +1,80 @@
+; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+@x = common global i32 0, align 4
+@y = common global i32 0, align 4
+
+; GVN across unordered store (allowed)
+define i32 @test1() nounwind uwtable ssp {
+; CHECK: test1
+; CHECK: add i32 %x, %x
+entry:
+ %x = load i32* @y
+ store atomic i32 %x, i32* @x unordered, align 4
+ %y = load i32* @y
+ %z = add i32 %x, %y
+ ret i32 %z
+}
+
+; GVN across seq_cst store (allowed in theory; not implemented ATM)
+define i32 @test2() nounwind uwtable ssp {
+; CHECK: test2
+; CHECK: add i32 %x, %y
+entry:
+ %x = load i32* @y
+ store atomic i32 %x, i32* @x seq_cst, align 4
+ %y = load i32* @y
+ %z = add i32 %x, %y
+ ret i32 %z
+}
+
+; GVN across unordered load (allowed)
+define i32 @test3() nounwind uwtable ssp {
+; CHECK: test3
+; CHECK: add i32 %x, %x
+entry:
+ %x = load i32* @y
+ %y = load atomic i32* @x unordered, align 4
+ %z = load i32* @y
+ %a = add i32 %x, %z
+ %b = add i32 %y, %a
+ ret i32 %b
+}
+
+; GVN across acquire load (load after atomic load must not be removed)
+define i32 @test4() nounwind uwtable ssp {
+; CHECK: test4
+; CHECK: load atomic i32* @x
+; CHECK: load i32* @y
+entry:
+ %x = load i32* @y
+ %y = load atomic i32* @x seq_cst, align 4
+ %x2 = load i32* @y
+ %x3 = add i32 %x, %x2
+ %y2 = add i32 %y, %x3
+ ret i32 %y2
+}
+
+; GVN load to unordered load (allowed)
+define i32 @test5() nounwind uwtable ssp {
+; CHECK: test5
+; CHECK: add i32 %x, %x
+entry:
+ %x = load atomic i32* @x unordered, align 4
+ %y = load i32* @x
+ %z = add i32 %x, %y
+ ret i32 %z
+}
+
+; GVN unordered load to load (unordered load must not be removed)
+define i32 @test6() nounwind uwtable ssp {
+; CHECK: test6
+; CHECK: load atomic i32* @x unordered
+entry:
+ %x = load i32* @x
+ %x2 = load atomic i32* @x unordered, align 4
+ %x3 = add i32 %x, %x2
+ ret i32 %x3
+}
diff --git a/test/Transforms/GVN/condprop.ll b/test/Transforms/GVN/condprop.ll
index be6c349..0b31b01 100644
--- a/test/Transforms/GVN/condprop.ll
+++ b/test/Transforms/GVN/condprop.ll
@@ -2,8 +2,8 @@
@a = external global i32 ; <i32*> [#uses=7]
-; CHECK: @foo
-define i32 @foo() nounwind {
+; CHECK: @test1
+define i32 @test1() nounwind {
entry:
%0 = load i32* @a, align 4
%1 = icmp eq i32 %0, 4
@@ -52,4 +52,81 @@ bb8: ; preds = %bb7, %bb6, %bb4, %bb2, %bb
return: ; preds = %bb8
ret i32 %.0
-} \ No newline at end of file
+}
+
+declare void @foo(i1)
+
+; CHECK: @test2
+define void @test2(i1 %x, i1 %y) {
+ %z = or i1 %x, %y
+ br i1 %z, label %true, label %false
+true:
+; CHECK: true:
+ %z2 = or i1 %x, %y
+ call void @foo(i1 %z2)
+; CHECK: call void @foo(i1 true)
+ br label %true
+false:
+; CHECK: false:
+ %z3 = or i1 %x, %y
+ call void @foo(i1 %z3)
+; CHECK: call void @foo(i1 false)
+ br label %false
+}
+
+declare void @bar(i32)
+
+; CHECK: @test3
+define void @test3(i32 %x, i32 %y) {
+ %xz = icmp eq i32 %x, 0
+ %yz = icmp eq i32 %y, 0
+ %z = and i1 %xz, %yz
+ br i1 %z, label %both_zero, label %nope
+both_zero:
+ call void @foo(i1 %xz)
+; CHECK: call void @foo(i1 true)
+ call void @foo(i1 %yz)
+; CHECK: call void @foo(i1 true)
+ call void @bar(i32 %x)
+; CHECK: call void @bar(i32 0)
+ call void @bar(i32 %y)
+; CHECK: call void @bar(i32 0)
+ ret void
+nope:
+ call void @foo(i1 %z)
+; CHECK: call void @foo(i1 false)
+ ret void
+}
+
+; CHECK: @test4
+define void @test4(i1 %b, i32 %x) {
+ br i1 %b, label %sw, label %case3
+sw:
+ switch i32 %x, label %default [
+ i32 0, label %case0
+ i32 1, label %case1
+ i32 2, label %case0
+ i32 3, label %case3
+ i32 4, label %default
+ ]
+default:
+; CHECK: default:
+ call void @bar(i32 %x)
+; CHECK: call void @bar(i32 %x)
+ ret void
+case0:
+; CHECK: case0:
+ call void @bar(i32 %x)
+; CHECK: call void @bar(i32 %x)
+ ret void
+case1:
+; CHECK: case1:
+ call void @bar(i32 %x)
+; CHECK: call void @bar(i32 1)
+ ret void
+case3:
+; CHECK: case3:
+ call void @bar(i32 %x)
+; CHECK: call void @bar(i32 %x)
+ ret void
+}
diff --git a/test/Transforms/GVN/phi-translate.ll b/test/Transforms/GVN/phi-translate.ll
index f10537e..fa91d29 100644
--- a/test/Transforms/GVN/phi-translate.ll
+++ b/test/Transforms/GVN/phi-translate.ll
@@ -14,7 +14,7 @@ target datalayout = "e-p:64:64:64"
@G = external global [100 x i32]
define i32 @foo(i32 %x, i32 %z) {
entry:
- %tobool = icmp eq i32 %x, 0
+ %tobool = icmp eq i32 %z, 0
br i1 %tobool, label %end, label %then
then:
diff --git a/test/Transforms/GVN/pr10820.ll b/test/Transforms/GVN/pr10820.ll
new file mode 100644
index 0000000..12c1e70
--- /dev/null
+++ b/test/Transforms/GVN/pr10820.ll
@@ -0,0 +1,18 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+target datalayout =
+"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+@g = external global i31
+
+define void @main() nounwind uwtable {
+entry:
+; CHECK: store i32
+ store i32 402662078, i32* bitcast (i31* @g to i32*), align 8
+; CHECK-NOT: load i31
+ %0 = load i31* @g, align 8
+; CHECK: store i31
+ store i31 %0, i31* undef, align 1
+ unreachable
+}
diff --git a/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll b/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll
index 0c81700..a6803ab 100644
--- a/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll
+++ b/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -globalopt -S | grep {volatile load}
+; RUN: opt < %s -globalopt -S | grep {load volatile}
@t0.1441 = internal global double 0x3FD5555555555555, align 8 ; <double*> [#uses=1]
define double @foo() nounwind {
diff --git a/test/Transforms/IPConstantProp/global.ll b/test/Transforms/IPConstantProp/global.ll
new file mode 100644
index 0000000..6715293
--- /dev/null
+++ b/test/Transforms/IPConstantProp/global.ll
@@ -0,0 +1,26 @@
+; RUN: opt < %s -S -ipsccp | FileCheck %s
+
+@_ZL6test1g = internal global i32 42, align 4
+
+define void @_Z7test1f1v() nounwind {
+entry:
+ %tmp = load i32* @_ZL6test1g, align 4
+ %cmp = icmp eq i32 %tmp, 0
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ store i32 0, i32* @_ZL6test1g, align 4
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; CHECK: @_Z7test1f2v()
+; CHECK: entry:
+; CHECK-NEXT: ret i32 42
+define i32 @_Z7test1f2v() nounwind {
+entry:
+ %tmp = load i32* @_ZL6test1g, align 4
+ ret i32 %tmp
+}
diff --git a/test/Transforms/IPConstantProp/return-argument.ll b/test/Transforms/IPConstantProp/return-argument.ll
index 6d6eb24..f4b7018 100644
--- a/test/Transforms/IPConstantProp/return-argument.ll
+++ b/test/Transforms/IPConstantProp/return-argument.ll
@@ -36,14 +36,22 @@ define void @caller(i1 %C) {
;; propagated per-caller).
%S1 = call { i32, i32 } @foo(i32 1, i32 2)
%X1 = extractvalue { i32, i32 } %S1, 0
- %S2 = invoke { i32, i32 } @foo(i32 3, i32 4) to label %OK unwind label %RET
+ %S2 = invoke { i32, i32 } @foo(i32 3, i32 4) to label %OK unwind label %LPAD
+
OK:
%X2 = extractvalue { i32, i32 } %S2, 0
;; Do some stuff with the returned values which we can grep for
%Z = add i32 %X1, %X2
store i32 %Z, i32* %W
br label %RET
+
+LPAD:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ br label %RET
+
RET:
ret void
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/IPConstantProp/return-constant.ll b/test/Transforms/IPConstantProp/return-constant.ll
index b255859..ff15df7 100644
--- a/test/Transforms/IPConstantProp/return-constant.ll
+++ b/test/Transforms/IPConstantProp/return-constant.ll
@@ -22,5 +22,9 @@ OK:
%Y = icmp ne i32 %X, 0 ; <i1> [#uses=1]
ret i1 %Y
FAIL:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i1 false
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll b/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll
deleted file mode 100644
index ecd5086..0000000
--- a/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; RUN: opt < %s -indvars -S | grep indvar
-
-define i32 @test() {
-; <label>:0
- br i1 true, label %LoopHead, label %LoopHead
-
-LoopHead: ; preds = %LoopHead, %0, %0
- %A = phi i32 [ 7, %0 ], [ 7, %0 ], [ %B, %LoopHead ] ; <i32> [#uses=1]
- %B = add i32 %A, 1 ; <i32> [#uses=2]
- br i1 true, label %LoopHead, label %Out
-
-Out: ; preds = %LoopHead
- ret i32 %B
-}
-
diff --git a/test/Transforms/IndVarSimplify/2003-12-21-IndVarSize.ll b/test/Transforms/IndVarSimplify/2003-12-21-IndVarSize.ll
deleted file mode 100644
index 0fc9c85..0000000
--- a/test/Transforms/IndVarSimplify/2003-12-21-IndVarSize.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; RUN: opt < %s -indvars -S | grep indvar | not grep i32
-
-@G = global i64 0 ; <i64*> [#uses=1]
-
-define void @test() {
-; <label>:0
- br label %Loop
-
-Loop: ; preds = %Loop, %0
- %X = phi i64 [ 1, %0 ], [ %X.next, %Loop ] ; <i64> [#uses=2]
- %X.next = add i64 %X, 1 ; <i64> [#uses=1]
- store i64 %X, i64* @G
- br label %Loop
-}
-
diff --git a/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll b/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll
index 1ed4c44..708a961 100644
--- a/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll
+++ b/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll
@@ -110,12 +110,16 @@ declare void @_ZNK4llvm19MachineInstrBuilder7addMRegEiNS_14MachineOperand7UseTyp
declare void @_ZNK4llvm19MachineInstrBuilder7addSImmEi()
+declare i32 @__gxx_personality_v0(...)
+
define void @_ZN4llvm11_GLOBAL__N_22InsertPrologEpilogCode20runOnMachineFunctionERNS_15MachineFunctionE(%"struct.llvm::MachineFunction"* %F) {
entry:
%tmp.8.i = invoke %"struct.llvm::TargetFrameInfo"* null( %"struct.llvm::TargetMachine"* null )
to label %invoke_cont.0.i unwind label %invoke_catch.0.i ; <%"struct.llvm::TargetFrameInfo"*> [#uses=0]
invoke_catch.0.i: ; preds = %invoke_cont.49.i, %invoke_cont.48.i, %invoke_cont.47.i, %invoke_cont.i53.i, %no_exit.i, %invoke_cont.44.i, %invoke_cont.43.i, %invoke_cont.42.i, %invoke_cont.41.i, %invoke_cont.40.i, %invoke_cont.39.i, %invoke_cont.38.i, %invoke_cont.37.i, %then.2.i, %invoke_cont.35.i, %invoke_cont.34.i, %then.1.i, %endif.0.i, %invoke_cont.9.i, %invoke_cont.8.i, %invoke_cont.7.i, %invoke_cont.i.i, %then.0.i, %invoke_cont.4.i, %invoke_cont.3.i, %invoke_cont.2.i, %invoke_cont.1.i, %endif.0.i.i, %tmp.7.i.noexc.i, %invoke_cont.0.i, %entry
+ %exn0.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret void
invoke_cont.0.i: ; preds = %entry
@@ -164,6 +168,8 @@ tmp.0.i.noexc.i: ; preds = %then.0.i
to label %invoke_cont.i.i unwind label %cond_true.i.i
cond_true.i.i: ; preds = %tmp.0.i.noexc.i
+ %exn.i.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret void
invoke_cont.i.i: ; preds = %tmp.0.i.noexc.i
@@ -256,6 +262,8 @@ tmp.0.i.noexc55.i: ; preds = %no_exit.i
to label %invoke_cont.i53.i unwind label %cond_true.i52.i
cond_true.i52.i: ; preds = %tmp.0.i.noexc55.i
+ %exn.i52.i = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret void
invoke_cont.i53.i: ; preds = %tmp.0.i.noexc55.i
diff --git a/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll b/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll
index aee67cc..a5706ca 100644
--- a/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll
+++ b/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll
@@ -5,9 +5,6 @@ entry:
%tmp.7 = invoke i32 @_ZN5ArrayISt7complexIdEE8get_sizeERK10dim_vector( )
to label %invoke_cont.0 unwind label %cond_true.1 ; <i32> [#uses=2]
-cond_true.1: ; preds = %entry
- unwind
-
invoke_cont.0: ; preds = %entry
%tmp.4.i = bitcast i32 %tmp.7 to i32 ; <i32> [#uses=0]
%tmp.14.0.i5 = add i32 %tmp.7, -1 ; <i32> [#uses=1]
@@ -17,7 +14,14 @@ no_exit.i: ; preds = %no_exit.i, %invoke_cont.0
%tmp.14.0.i.0 = phi i32 [ %tmp.14.0.i, %no_exit.i ], [ %tmp.14.0.i5, %invoke_cont.0 ] ; <i32> [#uses=1]
%tmp.14.0.i = add i32 %tmp.14.0.i.0, -1 ; <i32> [#uses=1]
br label %no_exit.i
+
+cond_true.1: ; preds = %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ resume { i8*, i32 } %exn
}
+declare i32 @__gxx_personality_v0(...)
+
declare i32 @_ZN5ArrayISt7complexIdEE8get_sizeERK10dim_vector()
diff --git a/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll b/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll
index 70a7a9d..ce043be 100644
--- a/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll
+++ b/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll
@@ -10,6 +10,8 @@ entry:
to label %endif.1 unwind label %then.i.i551
then.i.i551: ; preds = %entry
+ %exn551 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret void
endif.1: ; preds = %entry
@@ -20,6 +22,8 @@ then.2: ; preds = %endif.1
to label %loopentry.0 unwind label %invoke_catch.6
invoke_catch.6: ; preds = %then.2
+ %exn6 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret void
loopentry.0: ; preds = %then.2
@@ -59,3 +63,5 @@ loopexit.1: ; preds = %no_exit.0, %endif.4
then.i.i: ; preds = %endif.1
ret void
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll b/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll
index 0f6267b..dd400be 100644
--- a/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll
+++ b/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll
@@ -1,6 +1,6 @@
; RUN: opt < %s -indvars -S | not grep {sext}
; ModuleID = '<stdin>'
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n:32:64"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
target triple = "x86_64-apple-darwin9.6"
@a = external global i32* ; <i32**> [#uses=3]
@b = external global i32* ; <i32**> [#uses=3]
diff --git a/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll b/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll
index 46d6b38..55e8a50 100644
--- a/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll
+++ b/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll
@@ -13,7 +13,7 @@
; d[(i+2)&15] = e[(i+2)&15]+f[(i+2)&15]+K[i+2];
; }
;}
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n:32:64"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
target triple = "x86_64-apple-darwin9.6"
@a = external global i32* ; <i32**> [#uses=3]
@b = external global i32* ; <i32**> [#uses=3]
diff --git a/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll b/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll
new file mode 100644
index 0000000..77354f7
--- /dev/null
+++ b/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll
@@ -0,0 +1,30 @@
+; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s
+; Test WidenIV::GetExtendedOperandRecurrence.
+; add219 should be extended to i64 because it is nsw, even though its
+; sext cannot be hoisted outside the loop.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+define void @test() nounwind {
+entry:
+ br i1 undef, label %for.body11, label %for.end285
+
+for.body11: ; preds = %entry
+ %shl = shl i32 1, 1
+ %shl132 = shl i32 %shl, 1
+ br label %for.body153
+
+for.body153: ; preds = %for.body153, %for.body11
+ br i1 undef, label %for.body170, label %for.body153
+
+; CHECK: add nsw i64 %indvars.iv, 1
+for.body170: ; preds = %for.body170, %for.body153
+ %i2.19 = phi i32 [ %add249, %for.body170 ], [ undef, %for.body153 ]
+ %add219 = add nsw i32 %i2.19, 1
+ %idxprom220 = sext i32 %add219 to i64
+ %add249 = add nsw i32 %i2.19, %shl132
+ br label %for.body170
+
+for.end285: ; preds = %entry
+ ret void
+}
diff --git a/test/Transforms/IndVarSimplify/2011-09-19-vectoriv.ll b/test/Transforms/IndVarSimplify/2011-09-19-vectoriv.ll
new file mode 100644
index 0000000..6a01012
--- /dev/null
+++ b/test/Transforms/IndVarSimplify/2011-09-19-vectoriv.ll
@@ -0,0 +1,16 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; PR10946: Vector IVs are not SCEVable.
+; CHECK-NOT: phi
+define void @test() nounwind {
+allocas:
+ br i1 undef, label %cif_done, label %for_loop398
+
+cif_done: ; preds = %allocas
+ ret void
+
+for_loop398: ; preds = %for_loop398, %allocas
+ %storemerge35 = phi <4 x i32> [ %storemerge, %for_loop398 ], [ undef, %allocas ]
+ %bincmp431 = icmp sge <4 x i32> %storemerge35, <i32 5, i32 5, i32 5, i32 5>
+ %storemerge = bitcast <4 x float> undef to <4 x i32>
+ br label %for_loop398
+}
diff --git a/test/Transforms/IndVarSimplify/2011-09-27-hoistsext.ll b/test/Transforms/IndVarSimplify/2011-09-27-hoistsext.ll
new file mode 100644
index 0000000..0737489
--- /dev/null
+++ b/test/Transforms/IndVarSimplify/2011-09-27-hoistsext.ll
@@ -0,0 +1,28 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; Test indvars' ability to hoist new sext created by WidenIV.
+; From ffbench.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+define internal double @fourn(double* %data, i32 %x, i32 %y, i32 %n) nounwind {
+; CHECK: entry:
+; CHECK: sext
+; CHECK: sext
+entry:
+ br label %for.body
+
+; CHECK: for.body:
+; CHECK-NOT: sext
+; CHECK: br
+for.body:
+ %i2.115 = phi i32 [ 0, %entry ], [ %add249, %for.body ]
+ %add174 = add nsw i32 %i2.115, %x
+ %idxprom177 = sext i32 %add174 to i64
+ %arrayidx179 = getelementptr inbounds double* %data, i64 %idxprom177
+ %tmp180 = load double* %arrayidx179, align 8
+ %add249 = add nsw i32 %i2.115, %y
+ %cmp168 = icmp sgt i32 %add249, %n
+ br i1 %cmp168, label %exit, label %for.body
+
+exit:
+ ret double %tmp180
+}
diff --git a/test/Transforms/IndVarSimplify/ada-loops.ll b/test/Transforms/IndVarSimplify/ada-loops.ll
index 9e635fd..154de6f 100644
--- a/test/Transforms/IndVarSimplify/ada-loops.ll
+++ b/test/Transforms/IndVarSimplify/ada-loops.ll
@@ -1,5 +1,5 @@
; RUN: opt < %s -indvars -S | FileCheck %s
-; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s
+; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s
;
; PR1301
@@ -9,13 +9,12 @@
; Note that all four functions should actually be converted to
; memset. However, this test case validates indvars behavior. We
; don't check that phis are "folded together" because that is a job
-; for loop strength reduction. But indvars must remove sext, zext,
-; trunc, and add i8.
+; for loop strength reduction. But indvars must remove sext, zext, and add i8.
;
-; CHECK-NOT: {{sext|zext|trunc|add i8}}
+; CHECK-NOT: {{sext|zext|add i8}}
; ModuleID = 'ada.bc'
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-n:8:16:32"
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32"
target triple = "i686-pc-linux-gnu"
define void @kinds__sbytezero([256 x i32]* nocapture %a) nounwind {
diff --git a/test/Transforms/IndVarSimplify/addrec-gep.ll b/test/Transforms/IndVarSimplify/addrec-gep.ll
index 58cba60..b62d093 100644
--- a/test/Transforms/IndVarSimplify/addrec-gep.ll
+++ b/test/Transforms/IndVarSimplify/addrec-gep.ll
@@ -1,15 +1,15 @@
-; RUN: opt < %s -indvars -S > %t
-; RUN: grep getelementptr %t | count 1
-; RUN: grep {mul .*, 37} %t | count 1
-; RUN: grep {add .*, 5203} %t | count 1
-; RUN: not grep cast %t
+; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s
+; CHECK: getelementptr
+; CHECK: mul {{.*}}, 37
+; CHECK: add {{.*}}, 5203
+; CHECK-NOT: cast
; This test tests several things. The load and store should use the
; same address instead of having it computed twice, and SCEVExpander should
; be able to reconstruct the full getelementptr, despite it having a few
; obstacles set in its way.
-target datalayout = "e-p:64:64:64-n:32:64"
+target datalayout = "e-p:64:64:64-n32:64"
define void @foo(i64 %n, i64 %m, i64 %o, i64 %q, double* nocapture %p) nounwind {
entry:
diff --git a/test/Transforms/IndVarSimplify/ashr-tripcount.ll b/test/Transforms/IndVarSimplify/ashr-tripcount.ll
index 09d559f..b47c8ad 100644
--- a/test/Transforms/IndVarSimplify/ashr-tripcount.ll
+++ b/test/Transforms/IndVarSimplify/ashr-tripcount.ll
@@ -4,7 +4,7 @@
; Indvars should be able to eliminate all of the sign extensions
; inside the loop.
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n:32:64"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
@pow_2_tab = external constant [0 x float] ; <[0 x float]*> [#uses=1]
@pow_2_025_tab = external constant [0 x float] ; <[0 x float]*> [#uses=1]
@i_pow_2_tab = external constant [0 x float] ; <[0 x float]*> [#uses=1]
diff --git a/test/Transforms/IndVarSimplify/complex-scev.ll b/test/Transforms/IndVarSimplify/complex-scev.ll
index 434c4ec..395377e 100644
--- a/test/Transforms/IndVarSimplify/complex-scev.ll
+++ b/test/Transforms/IndVarSimplify/complex-scev.ll
@@ -1,7 +1,9 @@
; The i induction variable looks like a wrap-around, but it really is just
; a simple affine IV. Make sure that indvars eliminates it.
-; RUN: opt < %s -indvars -S | grep phi | count 1
+; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s
+; CHECK: phi
+; CHECK-NOT: phi
define void @foo() {
entry:
diff --git a/test/Transforms/IndVarSimplify/crash.ll b/test/Transforms/IndVarSimplify/crash.ll
index 516fd80..3335be7 100644
--- a/test/Transforms/IndVarSimplify/crash.ll
+++ b/test/Transforms/IndVarSimplify/crash.ll
@@ -53,3 +53,37 @@ bb30: ; preds = %bb29
%2 = add nsw i32 %r.0, 1 ; <i32> [#uses=1]
br label %bb24
}
+
+; PR10770
+
+declare void @__go_panic() noreturn
+
+declare void @__go_undefer()
+
+declare i32 @__gccgo_personality_v0(i32, i64, i8*, i8*)
+
+define void @main.main() uwtable {
+entry:
+ invoke void @__go_panic() noreturn
+ to label %0 unwind label %"5.i"
+
+; <label>:0 ; preds = %entry
+ unreachable
+
+"3.i": ; preds = %"7.i", %"5.i"
+ invoke void @__go_undefer()
+ to label %main.f.exit unwind label %"7.i"
+
+"5.i": ; preds = %entry
+ %1 = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gccgo_personality_v0
+ catch i8* null
+ br label %"3.i"
+
+"7.i": ; preds = %"3.i"
+ %2 = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gccgo_personality_v0
+ catch i8* null
+ br label %"3.i"
+
+main.f.exit: ; preds = %"3.i"
+ unreachable
+}
diff --git a/test/Transforms/IndVarSimplify/elim-extend.ll b/test/Transforms/IndVarSimplify/elim-extend.ll
index 0367e11..43c162f 100644
--- a/test/Transforms/IndVarSimplify/elim-extend.ll
+++ b/test/Transforms/IndVarSimplify/elim-extend.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s
+; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
diff --git a/test/Transforms/IndVarSimplify/floating-point-iv.ll b/test/Transforms/IndVarSimplify/floating-point-iv.ll
index 8f4b870..266eebd 100644
--- a/test/Transforms/IndVarSimplify/floating-point-iv.ll
+++ b/test/Transforms/IndVarSimplify/floating-point-iv.ll
@@ -67,7 +67,8 @@ bb: ; preds = %bb, %entry
return:
ret void
; CHECK: @test4
-; CHECK: fcmp
+; CHECK-NOT: cmp
+; CHECK: br i1 false
}
; PR6761
@@ -84,9 +85,8 @@ define void @test5() nounwind {
exit:
ret void
-
+
; CHECK: @test5
-; CHECK: icmp eq i32 {{.*}}, 10
+; CHECK: icmp slt i32 {{.*}}, 0
; CHECK-NEXT: br i1
}
-
diff --git a/test/Transforms/IndVarSimplify/gep-with-mul-base.ll b/test/Transforms/IndVarSimplify/gep-with-mul-base.ll
index 19d54ff..7e1e2a3 100644
--- a/test/Transforms/IndVarSimplify/gep-with-mul-base.ll
+++ b/test/Transforms/IndVarSimplify/gep-with-mul-base.ll
@@ -1,7 +1,16 @@
-; RUN: opt < %s -indvars -S > %t
-; RUN: grep add %t | count 6
-; RUN: grep sub %t | count 2
-; RUN: grep mul %t | count 6
+; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s
+; CHECK: define void @foo
+; CHECK: mul
+; CHECK: mul
+; CHECK: mul
+; CHECK: add
+; CHECK: sub
+; CHECK: define void @bar
+; CHECK: mul
+; CHECK: mul
+; CHECK: mul
+; CHECK: add
+; CHECK: sub
define void @foo(i64 %n, i64 %m, i64 %o, double* nocapture %p) nounwind {
entry:
diff --git a/test/Transforms/IndVarSimplify/interesting-invoke-use.ll b/test/Transforms/IndVarSimplify/interesting-invoke-use.ll
index 8adc0e5..69bea6e 100644
--- a/test/Transforms/IndVarSimplify/interesting-invoke-use.ll
+++ b/test/Transforms/IndVarSimplify/interesting-invoke-use.ll
@@ -47,9 +47,13 @@ bb178: ; preds = %invcont127
br label %bb123
lpad266: ; preds = %invcont129, %bb128, %bb123
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
+declare i32 @__gxx_personality_v0(...)
+
declare void @system__img_int__image_integer(%struct.string___XUP* noalias sret, i32)
declare void @system__string_ops__str_concat(%struct.string___XUP* noalias sret, [0 x i8]*, %struct.string___XUB*, [0 x i8]*, %struct.string___XUB*)
diff --git a/test/Transforms/IndVarSimplify/iv-fold.ll b/test/Transforms/IndVarSimplify/iv-fold.ll
new file mode 100644
index 0000000..2e19118
--- /dev/null
+++ b/test/Transforms/IndVarSimplify/iv-fold.ll
@@ -0,0 +1,56 @@
+; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
+
+; Indvars should be able to fold IV increments into shr when low bits are zero.
+;
+; CHECK: @foldIncShr
+; CHECK: shr.1 = lshr i32 %0, 5
+define i32 @foldIncShr(i32* %bitmap, i32 %bit_addr, i32 %nbits) nounwind {
+entry:
+ br label %while.body
+
+while.body:
+ %0 = phi i32 [ 0, %entry ], [ %inc.2, %while.body ]
+ %shr = lshr i32 %0, 5
+ %arrayidx = getelementptr inbounds i32* %bitmap, i32 %shr
+ %tmp6 = load i32* %arrayidx, align 4
+ %inc.1 = add i32 %0, 1
+ %shr.1 = lshr i32 %inc.1, 5
+ %arrayidx.1 = getelementptr inbounds i32* %bitmap, i32 %shr.1
+ %tmp6.1 = load i32* %arrayidx.1, align 4
+ %inc.2 = add i32 %inc.1, 1
+ %exitcond.3 = icmp eq i32 %inc.2, 128
+ br i1 %exitcond.3, label %while.end, label %while.body
+
+while.end:
+ %r = add i32 %tmp6, %tmp6.1
+ ret i32 %r
+}
+
+; Invdars should not fold an increment into shr unless 2^shiftBits is
+; a multiple of the recurrence step.
+;
+; CHECK: @noFoldIncShr
+; CHECK: shr.1 = lshr i32 %inc.1, 5
+define i32 @noFoldIncShr(i32* %bitmap, i32 %bit_addr, i32 %nbits) nounwind {
+entry:
+ br label %while.body
+
+while.body:
+ %0 = phi i32 [ 0, %entry ], [ %inc.3, %while.body ]
+ %shr = lshr i32 %0, 5
+ %arrayidx = getelementptr inbounds i32* %bitmap, i32 %shr
+ %tmp6 = load i32* %arrayidx, align 4
+ %inc.1 = add i32 %0, 1
+ %shr.1 = lshr i32 %inc.1, 5
+ %arrayidx.1 = getelementptr inbounds i32* %bitmap, i32 %shr.1
+ %tmp6.1 = load i32* %arrayidx.1, align 4
+ %inc.3 = add i32 %inc.1, 2
+ %exitcond.3 = icmp eq i32 %inc.3, 96
+ br i1 %exitcond.3, label %while.end, label %while.body
+
+while.end:
+ %r = add i32 %tmp6, %tmp6.1
+ ret i32 %r
+}
diff --git a/test/Transforms/IndVarSimplify/iv-sext.ll b/test/Transforms/IndVarSimplify/iv-sext.ll
index 6c7a627..04df0f9 100644
--- a/test/Transforms/IndVarSimplify/iv-sext.ll
+++ b/test/Transforms/IndVarSimplify/iv-sext.ll
@@ -4,7 +4,7 @@
; inner loop to i64.
; TODO: it should promote hiPart to i64 in the outer loop too.
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n:32:64"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
define void @t(float* %pTmp1, float* %peakWeight, float* %nrgReducePeakrate, i32 %bandEdgeIndex, float %tmp1) nounwind {
entry:
diff --git a/test/Transforms/IndVarSimplify/iv-zext.ll b/test/Transforms/IndVarSimplify/iv-zext.ll
index 3a05c89..646e6c0 100644
--- a/test/Transforms/IndVarSimplify/iv-zext.ll
+++ b/test/Transforms/IndVarSimplify/iv-zext.ll
@@ -1,9 +1,9 @@
; RUN: opt < %s -indvars -S | FileCheck %s
-; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s
+; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s
; CHECK-NOT: and
; CHECK-NOT: zext
-target datalayout = "-p:64:64:64-n:32:64"
+target datalayout = "-p:64:64:64-n32:64"
define void @foo(double* %d, i64 %n) nounwind {
entry:
diff --git a/test/Transforms/IndVarSimplify/lftr-reuse.ll b/test/Transforms/IndVarSimplify/lftr-reuse.ll
new file mode 100644
index 0000000..490eee9
--- /dev/null
+++ b/test/Transforms/IndVarSimplify/lftr-reuse.ll
@@ -0,0 +1,230 @@
+; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s
+;
+; Make sure that indvars can perform LFTR without a canonical IV.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+; Perform LFTR using the original pointer-type IV.
+
+; for(char* p = base; p < base + n; ++p) {
+; *p = p-base;
+; }
+define void @ptriv(i8* %base, i32 %n) nounwind {
+entry:
+ %idx.ext = sext i32 %n to i64
+ %add.ptr = getelementptr inbounds i8* %base, i64 %idx.ext
+ %cmp1 = icmp ult i8* %base, %add.ptr
+ br i1 %cmp1, label %for.body, label %for.end
+
+; CHECK: for.body:
+; CHECK: phi i8*
+; CHECK-NOT: phi
+; CHECK-NOT: add
+; CHECK: icmp ne i8*
+; CHECK: br i1
+for.body:
+ %p.02 = phi i8* [ %base, %entry ], [ %incdec.ptr, %for.body ]
+ ; cruft to make the IV useful
+ %sub.ptr.lhs.cast = ptrtoint i8* %p.02 to i64
+ %sub.ptr.rhs.cast = ptrtoint i8* %base to i64
+ %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+ %conv = trunc i64 %sub.ptr.sub to i8
+ store i8 %conv, i8* %p.02
+ %incdec.ptr = getelementptr inbounds i8* %p.02, i32 1
+ %cmp = icmp ult i8* %incdec.ptr, %add.ptr
+ br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+ ret void
+}
+
+; It would be nice if SCEV and any loop analysis could assume that
+; preheaders exist. Unfortunately it is not always the case. This test
+; checks that SCEVExpander can handle an outer loop that has not yet
+; been simplified. As a result, the inner loop's exit test will not be
+; rewritten.
+define void @expandOuterRecurrence(i32 %arg) nounwind {
+entry:
+ %sub1 = sub nsw i32 %arg, 1
+ %cmp1 = icmp slt i32 0, %sub1
+ br i1 %cmp1, label %outer, label %exit
+
+outer:
+ %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
+ %sub2 = sub nsw i32 %arg, %i
+ %sub3 = sub nsw i32 %sub2, 1
+ %cmp2 = icmp slt i32 0, %sub3
+ br i1 %cmp2, label %inner.ph, label %outer.inc
+
+inner.ph:
+ br label %inner
+
+; CHECK: inner:
+; CHECK: icmp slt
+; CHECK: br i1
+inner:
+ %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
+ %j.inc = add nsw i32 %j, 1
+ %cmp3 = icmp slt i32 %j.inc, %sub3
+ br i1 %cmp3, label %inner, label %outer.inc
+
+; CHECK: outer.inc:
+; CHECK: icmp ne
+; CHECK: br i1
+outer.inc:
+ %i.inc = add nsw i32 %i, 1
+ %cmp4 = icmp slt i32 %i.inc, %sub1
+ br i1 %cmp4, label %outer, label %exit
+
+exit:
+ ret void
+}
+
+; Force SCEVExpander to look for an existing well-formed phi.
+; Perform LFTR without generating extra preheader code.
+define void @guardedloop([0 x double]* %matrix, [0 x double]* %vector,
+ i32 %irow, i32 %ilead) nounwind {
+; CHECK: entry:
+; CHECK-NOT: zext
+; CHECK-NOT: add
+; CHECK: loop:
+; CHECK: phi i64
+; CHECK: phi i64
+; CHECK-NOT: phi
+; CHECK: icmp ne
+; CHECK: br i1
+entry:
+ %cmp = icmp slt i32 1, %irow
+ br i1 %cmp, label %loop, label %return
+
+loop:
+ %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ]
+ %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
+ %diagidx = add nsw i32 %rowidx, %i
+ %diagidxw = sext i32 %diagidx to i64
+ %matrixp = getelementptr inbounds [0 x double]* %matrix, i32 0, i64 %diagidxw
+ %v1 = load double* %matrixp
+ %iw = sext i32 %i to i64
+ %vectorp = getelementptr inbounds [0 x double]* %vector, i32 0, i64 %iw
+ %v2 = load double* %vectorp
+ %row.inc = add nsw i32 %rowidx, %ilead
+ %i.inc = add nsw i32 %i, 1
+ %cmp196 = icmp slt i32 %i.inc, %irow
+ br i1 %cmp196, label %loop, label %return
+
+return:
+ ret void
+}
+
+; Avoid generating extra code to materialize a trip count. Skip LFTR.
+define void @unguardedloop([0 x double]* %matrix, [0 x double]* %vector,
+ i32 %irow, i32 %ilead) nounwind {
+entry:
+ br label %loop
+
+; CHECK: entry:
+; CHECK-NOT: zext
+; CHECK-NOT: add
+; CHECK: loop:
+; CHECK: phi i64
+; CHECK: phi i64
+; CHECK-NOT: phi
+; CHECK: icmp slt
+; CHECK: br i1
+loop:
+ %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ]
+ %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
+ %diagidx = add nsw i32 %rowidx, %i
+ %diagidxw = sext i32 %diagidx to i64
+ %matrixp = getelementptr inbounds [0 x double]* %matrix, i32 0, i64 %diagidxw
+ %v1 = load double* %matrixp
+ %iw = sext i32 %i to i64
+ %vectorp = getelementptr inbounds [0 x double]* %vector, i32 0, i64 %iw
+ %v2 = load double* %vectorp
+ %row.inc = add nsw i32 %rowidx, %ilead
+ %i.inc = add nsw i32 %i, 1
+ %cmp196 = icmp slt i32 %i.inc, %irow
+ br i1 %cmp196, label %loop, label %return
+
+return:
+ ret void
+}
+
+; Remove %i which is only used by the exit test.
+; Verify that SCEV can still compute a backedge count from the sign
+; extended %n, used for pointer comparison by LFTR.
+define void @geplftr(i8* %base, i32 %x, i32 %y, i32 %n) nounwind {
+entry:
+ %x.ext = sext i32 %x to i64
+ %add.ptr = getelementptr inbounds i8* %base, i64 %x.ext
+ %y.ext = sext i32 %y to i64
+ %add.ptr10 = getelementptr inbounds i8* %add.ptr, i64 %y.ext
+ %lim = add i32 %x, %n
+ %cmp.ph = icmp ult i32 %x, %lim
+ br i1 %cmp.ph, label %loop, label %exit
+
+; CHECK: loop:
+; CHECK: phi i8*
+; CHECK-NOT: phi
+; CHECK: getelementptr
+; CHECK: store
+; CHECK: icmp ne i8*
+; CHECK: br i1
+loop:
+ %i = phi i32 [ %x, %entry ], [ %inc, %loop ]
+ %aptr = phi i8* [ %add.ptr10, %entry ], [ %incdec.ptr, %loop ]
+ %incdec.ptr = getelementptr inbounds i8* %aptr, i32 1
+ store i8 3, i8* %aptr
+ %inc = add i32 %i, 1
+ %cmp = icmp ult i32 %inc, %lim
+ br i1 %cmp, label %loop, label %exit
+
+exit:
+ ret void
+}
+
+; Exercise backedge taken count verification with a never-taken loop.
+define void @nevertaken() nounwind uwtable ssp {
+entry:
+ br label %loop
+
+; CHECK: loop:
+; CHECK-NOT: phi
+; CHECK-NOT: add
+; CHECK-NOT: icmp
+; CHECK: exit:
+loop:
+ %i = phi i32 [ 0, %entry ], [ %inc, %loop ]
+ %inc = add nsw i32 %i, 1
+ %cmp = icmp sle i32 %inc, 0
+ br i1 %cmp, label %loop, label %exit
+
+exit:
+ ret void
+}
+
+; Test LFTR on an IV whose recurrence start is a non-unit pointer type.
+define void @aryptriv([256 x i8]* %base, i32 %n) nounwind {
+entry:
+ %ivstart = getelementptr inbounds [256 x i8]* %base, i32 0, i32 0
+ %ivend = getelementptr inbounds [256 x i8]* %base, i32 0, i32 %n
+ %cmp.ph = icmp ult i8* %ivstart, %ivend
+ br i1 %cmp.ph, label %loop, label %exit
+
+; CHECK: loop:
+; CHECK: phi i8*
+; CHECK-NOT: phi
+; CHECK: getelementptr
+; CHECK: store
+; CHECK: icmp ne i8*
+; CHECK: br i1
+loop:
+ %aptr = phi i8* [ %ivstart, %entry ], [ %incdec.ptr, %loop ]
+ %incdec.ptr = getelementptr inbounds i8* %aptr, i32 1
+ store i8 3, i8* %aptr
+ %cmp = icmp ult i8* %incdec.ptr, %ivend
+ br i1 %cmp, label %loop, label %exit
+
+exit:
+ ret void
+}
diff --git a/test/Transforms/IndVarSimplify/max-pointer.ll b/test/Transforms/IndVarSimplify/max-pointer.ll
deleted file mode 100644
index 46ac2d8..0000000
--- a/test/Transforms/IndVarSimplify/max-pointer.ll
+++ /dev/null
@@ -1,39 +0,0 @@
-; RUN: opt < %s -indvars -S > %t
-; RUN: grep {icmp ugt i8\\\*} %t | count 1
-; RUN: grep {icmp sgt i8\\\*} %t | count 1
-
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n:32:64"
-
- %struct.CKenCodeCodec = type <{ i8 }>
-
-define void @foo(i8* %str1Ptr, i8* %str2Ptr, i8* %inLastBytePtr) nounwind {
-entry:
- %0 = icmp ult i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1]
- %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1]
- br label %bb2
-
-bb2: ; preds = %bb2, %entry
- %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1]
- %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2]
- %2 = icmp ult i8* %1, %inLastBytePtr ; <i1> [#uses=0]
- br i1 undef, label %bb2, label %return
-
-return: ; preds = %bb2
- ret void
-}
-
-define void @sfoo(i8* %str1Ptr, i8* %str2Ptr, i8* %inLastBytePtr) nounwind {
-entry:
- %0 = icmp slt i8* %str2Ptr, %str1Ptr ; <i1> [#uses=1]
- %str2Ptr_addr.0 = select i1 %0, i8* %str1Ptr, i8* %str2Ptr ; <i8*> [#uses=1]
- br label %bb2
-
-bb2: ; preds = %bb2, %entry
- %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; <i8*> [#uses=1]
- %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; <i8*> [#uses=2]
- %2 = icmp slt i8* %1, %inLastBytePtr ; <i1> [#uses=0]
- br i1 undef, label %bb2, label %return
-
-return: ; preds = %bb2
- ret void
-}
diff --git a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll
index 9605670..9c2abd0 100644
--- a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll
+++ b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s
+; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s
;
; Make sure that indvars isn't inserting canonical IVs.
; This is kinda hard to do until linear function test replacement is removed.
@@ -125,9 +125,9 @@ return:
ret void
}
-%struct = type { i32 }
+%structI = type { i32 }
-define void @bitcastiv(i32 %start, i32 %limit, i32 %step, %struct* %base)
+define void @bitcastiv(i32 %start, i32 %limit, i32 %step, %structI* %base)
nounwind
{
entry:
@@ -142,12 +142,12 @@ entry:
; CHECK: exit:
loop:
%iv = phi i32 [%start, %entry], [%next, %loop]
- %p = phi %struct* [%base, %entry], [%pinc, %loop]
- %adr = getelementptr %struct* %p, i32 0, i32 0
+ %p = phi %structI* [%base, %entry], [%pinc, %loop]
+ %adr = getelementptr %structI* %p, i32 0, i32 0
store i32 3, i32* %adr
- %pp = bitcast %struct* %p to i32*
+ %pp = bitcast %structI* %p to i32*
store i32 4, i32* %pp
- %pinc = getelementptr %struct* %p, i32 1
+ %pinc = getelementptr %structI* %p, i32 1
%next = add i32 %iv, 1
%cond = icmp ne i32 %next, %limit
br i1 %cond, label %loop, label %exit
@@ -281,6 +281,7 @@ return:
; CHECK-NOT: phi
; CHECK: add i32
; CHECK: add i32
+; CHECK: add i32
; CHECK-NOT: add
; CHECK: return:
;
@@ -320,3 +321,72 @@ return:
%sum4 = add i32 %sum1, %l.next
ret i32 %sum4
}
+
+; Test a GEP IV that is derived from another GEP IV by a nop gep that
+; lowers the type without changing the expression.
+%structIF = type { i32, float }
+
+define void @congruentgepiv(%structIF* %base) nounwind uwtable ssp {
+entry:
+ %first = getelementptr inbounds %structIF* %base, i64 0, i32 0
+ br label %loop
+
+; CHECK: loop:
+; CHECK: phi %structIF*
+; CHECK: phi i32*
+; CHECK: getelementptr inbounds
+; CHECK: getelementptr inbounds
+; CHECK: exit:
+loop:
+ %ptr.iv = phi %structIF* [ %ptr.inc, %latch ], [ %base, %entry ]
+ %next = phi i32* [ %next.inc, %latch ], [ %first, %entry ]
+ store i32 4, i32* %next
+ br i1 undef, label %latch, label %exit
+
+latch: ; preds = %for.inc50.i
+ %ptr.inc = getelementptr inbounds %structIF* %ptr.iv, i64 1
+ %next.inc = getelementptr inbounds %structIF* %ptr.inc, i64 0, i32 0
+ br label %loop
+
+exit:
+ ret void
+}
+
+; Test a widened IV that is used by a phi on different paths within the loop.
+;
+; CHECK: for.body:
+; CHECK: phi i64
+; CHECK: trunc i64
+; CHECK: if.then:
+; CHECK: for.inc:
+; CHECK: phi i32
+; CHECK: for.end:
+define void @phiUsesTrunc() nounwind {
+entry:
+ br i1 undef, label %for.body, label %for.end
+
+for.body:
+ %iv = phi i32 [ %inc, %for.inc ], [ 1, %entry ]
+ br i1 undef, label %if.then, label %if.else
+
+if.then:
+ br i1 undef, label %if.then33, label %for.inc
+
+if.then33:
+ br label %for.inc
+
+if.else:
+ br i1 undef, label %if.then97, label %for.inc
+
+if.then97:
+ %idxprom100 = sext i32 %iv to i64
+ br label %for.inc
+
+for.inc:
+ %kmin.1 = phi i32 [ %iv, %if.then33 ], [ 0, %if.then ], [ %iv, %if.then97 ], [ 0, %if.else ]
+ %inc = add nsw i32 %iv, 1
+ br i1 undef, label %for.body, label %for.end
+
+for.end:
+ ret void
+}
diff --git a/test/Transforms/IndVarSimplify/pointer-indvars.ll b/test/Transforms/IndVarSimplify/pointer-indvars.ll
deleted file mode 100644
index 6d25f90..0000000
--- a/test/Transforms/IndVarSimplify/pointer-indvars.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; RUN: opt < %s -indvars -S | grep indvar
-@G = global i32* null ; <i32**> [#uses=1]
-@Array = external global [40 x i32] ; <[40 x i32]*> [#uses=1]
-
-define void @test() {
-; <label>:0
- br label %Loop
-
-Loop: ; preds = %Loop, %0
- %X = phi i32* [ getelementptr ([40 x i32]* @Array, i64 0, i64 0), %0 ], [ %X.next, %Loop ] ; <i32*> [#uses=2]
- %X.next = getelementptr i32* %X, i64 1 ; <i32*> [#uses=1]
- store i32* %X, i32** @G
- br label %Loop
-}
-
diff --git a/test/Transforms/IndVarSimplify/pointer.ll b/test/Transforms/IndVarSimplify/pointer.ll
deleted file mode 100644
index d55bf98..0000000
--- a/test/Transforms/IndVarSimplify/pointer.ll
+++ /dev/null
@@ -1,38 +0,0 @@
-; RUN: opt < %s -indvars -S > %t
-; RUN: grep {%exitcond = icmp eq i64 %indvar.next, %n} %t
-; RUN: grep {getelementptr i8\\* %A, i64 %indvar} %t
-; RUN: grep getelementptr %t | count 1
-; RUN: grep add %t | count 1
-; RUN: not grep scevgep %t
-; RUN: not grep ptrtoint %t
-
-; Indvars should be able to expand the pointer-arithmetic
-; IV into an integer IV indexing into a simple getelementptr.
-
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-n:32:64"
-
-define void @foo(i8* %A, i64 %n) nounwind {
-entry:
- %0 = icmp eq i64 %n, 0 ; <i1> [#uses=1]
- br i1 %0, label %return, label %bb.nph
-
-bb.nph: ; preds = %entry
- %1 = getelementptr i8* %A, i64 %n ; <i8*> [#uses=1]
- br label %bb
-
-bb: ; preds = %bb1, %bb.nph
- %q.01 = phi i8* [ %2, %bb1 ], [ %A, %bb.nph ] ; <i8*> [#uses=2]
- store i8 0, i8* %q.01, align 1
- %2 = getelementptr i8* %q.01, i64 1 ; <i8*> [#uses=2]
- br label %bb1
-
-bb1: ; preds = %bb
- %3 = icmp eq i8* %1, %2 ; <i1> [#uses=1]
- br i1 %3, label %bb1.return_crit_edge, label %bb
-
-bb1.return_crit_edge: ; preds = %bb1
- br label %return
-
-return: ; preds = %bb1.return_crit_edge, %entry
- ret void
-}
diff --git a/test/Transforms/IndVarSimplify/preserve-gep-loop-variant.ll b/test/Transforms/IndVarSimplify/preserve-gep-loop-variant.ll
index 26f05c4..251d34e 100644
--- a/test/Transforms/IndVarSimplify/preserve-gep-loop-variant.ll
+++ b/test/Transforms/IndVarSimplify/preserve-gep-loop-variant.ll
@@ -1,8 +1,8 @@
-; RUN: opt < %s -indvars -S > %t
-; RUN: not grep inttoptr %t
-; RUN: not grep ptrtoint %t
-; RUN: grep scevgep %t
-target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128-n:32:64"
+; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s
+; CHECK-NOT: {{inttoptr|ptrtoint}}
+; CHECK: scevgep
+; CHECK-NOT: {{inttoptr|ptrtoint}}
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128-n32:64"
; Indvars shouldn't need inttoptr/ptrtoint to expand an address here.
diff --git a/test/Transforms/IndVarSimplify/preserve-gep-nested.ll b/test/Transforms/IndVarSimplify/preserve-gep-nested.ll
index b41de58..cdcaaa0 100644
--- a/test/Transforms/IndVarSimplify/preserve-gep-nested.ll
+++ b/test/Transforms/IndVarSimplify/preserve-gep-nested.ll
@@ -1,19 +1,20 @@
-; RUN: opt < %s -indvars -S > %t
-; Exactly one getelementptr for each load+store.
-; RUN: grep getelementptr %t | count 6
-; Each getelementptr using %struct.Q* %s as a base and not i8*.
-; RUN: grep {getelementptr \[%\]struct\\.Q\\* \[%\]s,} %t | count 6
+; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s
; No explicit integer multiplications!
-; RUN: not grep {= mul} %t
; No i8* arithmetic or pointer casting anywhere!
-; RUN: not grep {i8\\*} %t
-; RUN: not grep bitcast %t
-; RUN: not grep inttoptr %t
-; RUN: not grep ptrtoint %t
+; CHECK-NOT: = {{= mul|i8\*|bitcast|inttoptr|ptrtoint}}
+; Exactly one getelementptr for each load+store.
+; Each getelementptr using %struct.Q* %s as a base and not i8*.
+; CHECK: getelementptr %struct.Q* %s,
+; CHECK: getelementptr %struct.Q* %s,
+; CHECK: getelementptr %struct.Q* %s,
+; CHECK: getelementptr %struct.Q* %s,
+; CHECK: getelementptr %struct.Q* %s,
+; CHECK: getelementptr %struct.Q* %s,
+; CHECK-NOT: = {{= mul|i8\*|bitcast|inttoptr|ptrtoint}}
; FIXME: This test should pass with or without TargetData. Until opt
; supports running tests without targetdata, just hardware this in.
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n:32:64"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
%struct.Q = type { [10 x %struct.N] }
%struct.N = type { %struct.S }
diff --git a/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll b/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll
index ca0c399..2f3100f 100644
--- a/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll
+++ b/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll
@@ -1,6 +1,6 @@
-; RUN: opt < %s -indvars -S \
-; RUN: | grep {\[%\]p.2.ip.1 = getelementptr \\\[3 x \\\[3 x double\\\]\\\]\\* \[%\]p, i64 2, i64 \[%\]tmp, i64 1}
-target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128-n:32:64"
+; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s
+; CHECK: %p.2.ip.1 = getelementptr [3 x [3 x double]]* %p, i64 2, i64 %0, i64 1
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128-n32:64"
; Indvars shouldn't expand this to
; %p.2.ip.1 = getelementptr [3 x [3 x double]]* %p, i64 0, i64 %tmp, i64 19
diff --git a/test/Transforms/IndVarSimplify/preserve-gep.ll b/test/Transforms/IndVarSimplify/preserve-gep.ll
index 82eda03..fec8a28 100644
--- a/test/Transforms/IndVarSimplify/preserve-gep.ll
+++ b/test/Transforms/IndVarSimplify/preserve-gep.ll
@@ -1,12 +1,12 @@
-; RUN: opt < %s -indvars -S > %t
-; RUN: not grep ptrtoint %t
-; RUN: not grep inttoptr %t
-; RUN: grep getelementptr %t | count 1
+; RUN: opt < %s -indvars -S -enable-iv-rewrite | FileCheck %s
+; CHECK-NOT: {{ptrtoint|inttoptr}}
+; CHECK: getelementptr
+; CHECK-NOT: {{ptrtoint|inttoptr|getelementptr}}
; Indvars shouldn't leave getelementptrs expanded out as
; inttoptr+ptrtoint in its output in common cases.
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n:32:64"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
target triple = "x86_64-unknown-linux-gnu"
%struct.Foo = type { i32, i32, [10 x i32], i32 }
diff --git a/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll b/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll
index 5063b17..22e2092 100644
--- a/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll
+++ b/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll
@@ -1,5 +1,5 @@
; RUN: opt < %s -indvars -S | FileCheck %s
-; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s
+; RUN: opt < %s -indvars -enable-iv-rewrite=false -S | FileCheck %s
; Indvars should insert a 64-bit induction variable to eliminate the
; sext for the addressing, however it shouldn't eliminate the sext
diff --git a/test/Transforms/IndVarSimplify/subtract.ll b/test/Transforms/IndVarSimplify/subtract.ll
deleted file mode 100644
index f45bdab..0000000
--- a/test/Transforms/IndVarSimplify/subtract.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; RUN: opt < %s -indvars -S | grep indvar
-
-@G = global i64 0 ; <i64*> [#uses=1]
-
-define void @test(i64 %V) {
-; <label>:0
- br label %Loop
-
-Loop: ; preds = %Loop, %0
- %X = phi i64 [ 1, %0 ], [ %X.next, %Loop ] ; <i64> [#uses=2]
- %X.next = sub i64 %X, %V ; <i64> [#uses=1]
- store i64 %X, i64* @G
- br label %Loop
-}
-
diff --git a/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll b/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll
index ace74ff..fc906cd 100644
--- a/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll
+++ b/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll
@@ -1,5 +1,5 @@
; RUN: opt < %s -indvars -instcombine -S | FileCheck %s
-; RUN: opt < %s -indvars -disable-iv-rewrite -instcombine -S | FileCheck %s
+; RUN: opt < %s -indvars -enable-iv-rewrite=false -instcombine -S | FileCheck %s
;
; Test that -indvars can reduce variable stride IVs. If it can reduce variable
; stride iv's, it will make %iv. and %m.0.0 isomorphic to each other without
diff --git a/test/Transforms/Inline/2003-09-14-InlineValue.ll b/test/Transforms/Inline/2003-09-14-InlineValue.ll
index 49a27e1..98bc08b 100644
--- a/test/Transforms/Inline/2003-09-14-InlineValue.ll
+++ b/test/Transforms/Inline/2003-09-14-InlineValue.ll
@@ -16,6 +16,10 @@ Ok: ; preds = %0
ret i32 %V
Bad: ; preds = %0
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i32 0
}
+declare i32 @__gxx_personality_v0(...)
+
diff --git a/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll b/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll
index 4418f77..9af9332 100644
--- a/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll
+++ b/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll
@@ -6,10 +6,15 @@ entry:
to label %Call2Invoke unwind label %LongJmpBlkPre
Call2Invoke: ; preds = %entry
- br label %LongJmpBlkPre
+ br label %exit
LongJmpBlkPre: ; preds = %Call2Invoke, %entry
%i.3 = phi i32 [ 0, %entry ], [ 0, %Call2Invoke ] ; <i32> [#uses=0]
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ br label %exit
+
+exit:
ret i32 0
}
@@ -19,6 +24,8 @@ define void @__main() {
ret void
}
+declare i32 @__gxx_personality_v0(...)
+
declare void @__llvm_getGlobalCtors()
declare void @__llvm_getGlobalDtors()
diff --git a/test/Transforms/Inline/2003-10-26-InlineInvokeExceptionDestPhi.ll b/test/Transforms/Inline/2003-10-26-InlineInvokeExceptionDestPhi.ll
deleted file mode 100644
index 9afd450..0000000
--- a/test/Transforms/Inline/2003-10-26-InlineInvokeExceptionDestPhi.ll
+++ /dev/null
@@ -1,20 +0,0 @@
-; The inliner is breaking inlining invoke instructions where there is a PHI
-; node in the exception destination, and the inlined function contains an
-; unwind instruction.
-
-; RUN: opt < %s -inline -disable-output
-
-define linkonce void @foo() {
- unwind
-}
-
-define i32 @test() {
-BB1:
- invoke void @foo( )
- to label %Cont unwind label %Cont
-
-Cont: ; preds = %BB1, %BB1
- %A = phi i32 [ 0, %BB1 ], [ 0, %BB1 ] ; <i32> [#uses=1]
- ret i32 %A
-}
-
diff --git a/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll b/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll
index 3899451..62a7594 100644
--- a/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll
+++ b/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll
@@ -5,7 +5,7 @@
; exists.
define internal void @Callee1() {
- unwind
+ unreachable
}
define void @Callee2() {
diff --git a/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll b/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll
index 733cbb9..866327f 100644
--- a/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll
+++ b/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll
@@ -1,7 +1,7 @@
; RUN: opt < %s -inline -disable-output
define i32 @test() {
- unwind
+ unreachable
}
define i32 @caller() {
diff --git a/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll b/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll
index 37cba98..b4380d0 100644
--- a/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll
+++ b/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll
@@ -114,7 +114,7 @@ entry:
define fastcc void @_ZSt19__throw_ios_failurePKc() {
entry:
call fastcc void @_ZNSsC1EPKcRKSaIcE( )
- unwind
+ unreachable
}
define void @_GLOBAL__D__ZSt23lexicographical_compareIPKaS1_EbT_S2_T0_S3_() {
@@ -133,10 +133,12 @@ entry:
to label %try_exit.0 unwind label %try_catch.0
try_catch.0: ; preds = %entry
- unreachable
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
+ resume { i8*, i32 } %exn
try_exit.0: ; preds = %entry
- unwind
+ unreachable
}
define fastcc void @_ZNSt11logic_errorC1ERKSs() {
@@ -153,7 +155,7 @@ entry:
define fastcc void @_ZSt20__throw_length_errorPKc() {
entry:
call fastcc void @_ZNSt12length_errorC1ERKSs( )
- unwind
+ unreachable
}
define fastcc void @_ZNSt12length_errorC1ERKSs() {
@@ -162,7 +164,9 @@ entry:
to label %_ZNSt11logic_errorC2ERKSs.exit unwind label %invoke_catch.i
invoke_catch.i: ; preds = %entry
- unwind
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
+ resume { i8*, i32 } %exn
_ZNSt11logic_errorC2ERKSs.exit: ; preds = %entry
ret void
@@ -199,8 +203,10 @@ entry:
to label %invoke_cont.1 unwind label %invoke_catch.1
invoke_catch.1: ; preds = %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
call fastcc void @_ZNSaIcED1Ev( )
- unwind
+ resume { i8*, i32 } %exn
invoke_cont.1: ; preds = %entry
call fastcc void @_ZNSaIcEC2ERKS_( )
@@ -243,3 +249,5 @@ define fastcc void @_ZN9__gnu_cxx12__pool_allocILb1ELi0EE9_S_refillEj() {
entry:
unreachable
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll b/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll
index 279823a..b754d9f 100644
--- a/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll
+++ b/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll
@@ -155,7 +155,7 @@ endif.0: ; preds = %entry
define fastcc void @_ZSt20__throw_length_errorPKc() {
entry:
call fastcc void @_ZNSt12length_errorC1ERKSs( )
- unwind
+ ret void
}
define fastcc void @_ZNSs16_S_construct_auxIPKcEEPcT_S3_RKSaIcE12__false_type() {
@@ -178,8 +178,10 @@ entry:
to label %invoke_cont.1 unwind label %invoke_catch.1
invoke_catch.1: ; preds = %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
call fastcc void @_ZNSaIcED1Ev( )
- unwind
+ resume { i8*, i32 } %exn
invoke_cont.1: ; preds = %entry
call fastcc void @_ZNSaIcEC2ERKS_( )
@@ -306,7 +308,9 @@ entry:
to label %_ZNSt11logic_errorC2ERKSs.exit unwind label %invoke_catch.i
invoke_catch.i: ; preds = %entry
- unwind
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
+ resume { i8*, i32 } %exn
_ZNSt11logic_errorC2ERKSs.exit: ; preds = %entry
ret void
@@ -336,3 +340,5 @@ define fastcc void @_ZNSt5ctypeIcEC1EPKtbj() {
entry:
ret void
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/Inline/2007-04-15-InlineEH.ll b/test/Transforms/Inline/2007-04-15-InlineEH.ll
index 635f93e..8fbcf92 100644
--- a/test/Transforms/Inline/2007-04-15-InlineEH.ll
+++ b/test/Transforms/Inline/2007-04-15-InlineEH.ll
@@ -33,9 +33,13 @@ invcont67: ; preds = %invcont65
ret void
cleanup144: ; preds = %invcont65, %invcont64, %invcont, %entry
- unwind
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ resume { i8*, i32 } %exn
}
+declare i32 @__gxx_personality_v0(...)
+
declare void @gnat__os_lib__getenv(%struct.gnat__strings__string_access*)
declare void @ada__calendar__delays__delay_for()
diff --git a/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll b/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll
index 979157e..a5cfc3b 100644
--- a/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll
+++ b/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll
@@ -10,7 +10,7 @@ entry:
r:
ret i32 0
u:
- unwind
+ unreachable
}
define i32 @caller() {
diff --git a/test/Transforms/Inline/callgraph-update.ll b/test/Transforms/Inline/callgraph-update.ll
index ff0120b..b96fbc3 100644
--- a/test/Transforms/Inline/callgraph-update.ll
+++ b/test/Transforms/Inline/callgraph-update.ll
@@ -29,5 +29,8 @@ invcont:
unreachable
lpad:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/Inline/crash.ll b/test/Transforms/Inline/crash.ll
index 1df4d60..e2cd49c 100644
--- a/test/Transforms/Inline/crash.ll
+++ b/test/Transforms/Inline/crash.ll
@@ -69,9 +69,13 @@ invcont98:
unreachable
lpad156:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
+declare i32 @__gxx_personality_v0(...)
+
declare fastcc void @YYY()
define internal fastcc void @XXX() {
@@ -84,7 +88,9 @@ bb260:
ret void
lpad:
- unwind
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ resume { i8*, i32 } %exn
}
@@ -105,6 +111,8 @@ invcont3: ; preds = %bb1
ret void
lpad18: ; preds = %invcont3, %bb1
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
diff --git a/test/Transforms/Inline/inline_invoke.ll b/test/Transforms/Inline/inline_invoke.ll
index 2a1b883..9f5f670 100644
--- a/test/Transforms/Inline/inline_invoke.ll
+++ b/test/Transforms/Inline/inline_invoke.ll
@@ -18,14 +18,8 @@ declare void @use(i32) nounwind
declare void @opaque()
-declare i8* @llvm.eh.exception() nounwind readonly
-
-declare i32 @llvm.eh.selector(i8*, i8*, ...) nounwind
-
declare i32 @llvm.eh.typeid.for(i8*) nounwind
-declare void @llvm.eh.resume(i8*, i32)
-
declare i32 @__gxx_personality_v0(...)
declare i8* @__cxa_begin_catch(i8*)
@@ -51,18 +45,17 @@ invoke.cont1:
ret void
lpad:
- %exn = call i8* @llvm.eh.exception() nounwind
- %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0) nounwind
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
invoke void @_ZN1AD1Ev(%struct.A* %a)
to label %invoke.cont2 unwind label %terminate.lpad
invoke.cont2:
- call void @llvm.eh.resume(i8* %exn, i32 %eh.selector) noreturn
- unreachable
+ resume { i8*, i32 } %exn
terminate.lpad:
- %exn3 = call i8* @llvm.eh.exception() nounwind
- %eh.selector4 = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn3, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null) nounwind
+ %exn1 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
call void @_ZSt9terminatev() noreturn nounwind
unreachable
}
@@ -76,20 +69,21 @@ ret:
ret void
lpad: ; preds = %entry
- %exn = call i8* @llvm.eh.exception() nounwind
- %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* bitcast (i8** @_ZTIi to i8*)
+ %eh.exc = extractvalue { i8*, i32 } %exn, 0
+ %eh.selector = extractvalue { i8*, i32 } %exn, 1
%0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) nounwind
%1 = icmp eq i32 %eh.selector, %0
br i1 %1, label %catch, label %eh.resume
catch:
- %ignored = call i8* @__cxa_begin_catch(i8* %exn) nounwind
+ %ignored = call i8* @__cxa_begin_catch(i8* %eh.exc) nounwind
call void @__cxa_end_catch() nounwind
br label %ret
eh.resume:
- call void @llvm.eh.resume(i8* %exn, i32 %eh.selector) noreturn
- unreachable
+ resume { i8*, i32 } %exn
}
; CHECK: define void @test0_out()
@@ -99,18 +93,21 @@ eh.resume:
; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[B]])
; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[B]])
; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[A]])
-; CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*))
+; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A]])
; CHECK-NEXT: to label %[[LBL:[^\s]+]] unwind
; CHECK: [[LBL]]:
; CHECK-NEXT: br label %[[LPAD:[^\s]+]]
; CHECK: ret void
-; CHECK: call i8* @llvm.eh.exception()
-; CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*))
+; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
; CHECK-NEXT: br label %[[LPAD]]
; CHECK: [[LPAD]]:
-; CHECK-NEXT: phi i8* [
-; CHECK-NEXT: phi i32 [
+; CHECK-NEXT: phi { i8*, i32 } [
+; CHECK-NEXT: extractvalue { i8*, i32 }
+; CHECK-NEXT: extractvalue { i8*, i32 }
; CHECK-NEXT: call i32 @llvm.eh.typeid.for(
@@ -131,22 +128,23 @@ ret:
lpad:
%x = phi i32 [ 0, %entry ], [ 1, %cont ]
%y = phi i32 [ 1, %entry ], [ 4, %cont ]
- %exn = call i8* @llvm.eh.exception() nounwind
- %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* bitcast (i8** @_ZTIi to i8*)
+ %eh.exc = extractvalue { i8*, i32 } %exn, 0
+ %eh.selector = extractvalue { i8*, i32 } %exn, 1
%0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) nounwind
%1 = icmp eq i32 %eh.selector, %0
br i1 %1, label %catch, label %eh.resume
catch:
- %ignored = call i8* @__cxa_begin_catch(i8* %exn) nounwind
+ %ignored = call i8* @__cxa_begin_catch(i8* %eh.exc) nounwind
call void @use(i32 %x)
call void @use(i32 %y)
call void @__cxa_end_catch() nounwind
br label %ret
eh.resume:
- call void @llvm.eh.resume(i8* %exn, i32 %eh.selector) noreturn
- unreachable
+ resume { i8*, i32 } %exn
}
; CHECK: define void @test1_out()
@@ -165,8 +163,9 @@ eh.resume:
; Inner landing pad from first inlining.
; CHECK: [[LPAD1]]:
-; CHECK-NEXT: [[EXN1:%.*]] = call i8* @llvm.eh.exception()
-; CHECK-NEXT: [[SEL1:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[EXN1]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*))
+; CHECK-NEXT: [[LPADVAL1:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A1]])
; CHECK-NEXT: to label %[[RESUME1:[^\s]+]] unwind
; CHECK: [[RESUME1]]:
@@ -183,8 +182,9 @@ eh.resume:
; Inner landing pad from second inlining.
; CHECK: [[LPAD2]]:
-; CHECK-NEXT: [[EXN2:%.*]] = call i8* @llvm.eh.exception()
-; CHECK-NEXT: [[SEL2:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[EXN2]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*))
+; CHECK-NEXT: [[LPADVAL2:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A2]])
; CHECK-NEXT: to label %[[RESUME2:[^\s]+]] unwind
; CHECK: [[RESUME2]]:
@@ -195,29 +195,29 @@ eh.resume:
; CHECK: [[LPAD]]:
; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, %entry ], [ 0, {{%.*}} ], [ 1, %cont ], [ 1, {{%.*}} ]
; CHECK-NEXT: [[Y:%.*]] = phi i32 [ 1, %entry ], [ 1, {{%.*}} ], [ 4, %cont ], [ 4, {{%.*}} ]
-; CHECK-NEXT: [[EXN:%.*]] = call i8* @llvm.eh.exception()
-; CHECK-NEXT: [[SEL:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[EXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*))
+; CHECK-NEXT: [[LPADVAL:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
; CHECK-NEXT: br label %[[LPAD_JOIN2]]
; CHECK: [[LPAD_JOIN2]]:
; CHECK-NEXT: [[XJ2:%.*]] = phi i32 [ [[X]], %[[LPAD]] ], [ 1, %[[RESUME2]] ]
; CHECK-NEXT: [[YJ2:%.*]] = phi i32 [ [[Y]], %[[LPAD]] ], [ 4, %[[RESUME2]] ]
-; CHECK-NEXT: [[EXNJ2:%.*]] = phi i8* [ [[EXN]], %[[LPAD]] ], [ [[EXN2]], %[[RESUME2]] ]
-; CHECK-NEXT: [[SELJ2:%.*]] = phi i32 [ [[SEL]], %[[LPAD]] ], [ [[SEL2]], %[[RESUME2]] ]
+; CHECK-NEXT: [[EXNJ2:%.*]] = phi { i8*, i32 } [ [[LPADVAL]], %[[LPAD]] ], [ [[LPADVAL2]], %[[RESUME2]] ]
; CHECK-NEXT: br label %[[LPAD_JOIN1]]
; CHECK: [[LPAD_JOIN1]]:
; CHECK-NEXT: [[XJ1:%.*]] = phi i32 [ [[XJ2]], %[[LPAD_JOIN2]] ], [ 0, %[[RESUME1]] ]
; CHECK-NEXT: [[YJ1:%.*]] = phi i32 [ [[YJ2]], %[[LPAD_JOIN2]] ], [ 1, %[[RESUME1]] ]
-; CHECK-NEXT: [[EXNJ1:%.*]] = phi i8* [ [[EXNJ2]], %[[LPAD_JOIN2]] ], [ [[EXN1]], %[[RESUME1]] ]
-; CHECK-NEXT: [[SELJ1:%.*]] = phi i32 [ [[SELJ2]], %[[LPAD_JOIN2]] ], [ [[SEL1]], %[[RESUME1]] ]
+; CHECK-NEXT: [[EXNJ1:%.*]] = phi { i8*, i32 } [ [[EXNJ2]], %[[LPAD_JOIN2]] ], [ [[LPADVAL1]], %[[RESUME1]] ]
+; CHECK-NEXT: extractvalue { i8*, i32 } [[EXNJ1]], 0
+; CHECK-NEXT: [[SELJ1:%.*]] = extractvalue { i8*, i32 } [[EXNJ1]], 1
; CHECK-NEXT: [[T:%.*]] = call i32 @llvm.eh.typeid.for(
; CHECK-NEXT: icmp eq i32 [[SELJ1]], [[T]]
; CHECK: call void @use(i32 [[XJ1]])
; CHECK: call void @use(i32 [[YJ1]])
-; CHECK: call void @llvm.eh.resume(i8* [[EXNJ1]], i32 [[SELJ1]])
+; CHECK: resume { i8*, i32 }
;; Test 2 - Don't make invalid IR for inlines into landing pads without eh.exception calls
@@ -230,6 +230,8 @@ ret:
ret void
lpad:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
call void @_ZSt9terminatev()
unreachable
}
@@ -257,24 +259,25 @@ ret:
ret void
lpad:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* bitcast (i8** @_ZTIi to i8*)
br label %lpad.cont
lpad.cont:
- %exn = call i8* @llvm.eh.exception() nounwind
- %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind
call void @_ZSt9terminatev()
unreachable
}
; CHECK: define void @test3_out()
-; CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*))
+; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
; CHECK-NEXT: invoke void @_ZN1AD1Ev(
; CHECK-NEXT: to label %[[L:[^\s]+]] unwind
; CHECK: [[L]]:
; CHECK-NEXT: br label %[[JOIN:[^\s]+]]
; CHECK: [[JOIN]]:
-; CHECK-NEXT: phi
-; CHECK-NEXT: phi
+; CHECK-NEXT: phi { i8*, i32 }
; CHECK-NEXT: br label %lpad.cont
; CHECK: lpad.cont:
; CHECK-NEXT: call void @_ZSt9terminatev()
@@ -294,20 +297,27 @@ ret:
ret void
lpad.crit:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* bitcast (i8** @_ZTIi to i8*)
call void @opaque() nounwind
- br label %lpad
+ br label %terminate
lpad:
- %phi = phi i32 [ 0, %lpad.crit ], [ 1, %cont ]
- %exn = call i8* @llvm.eh.exception() nounwind
- %eh.selector = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) nounwind
+ %exn2 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* bitcast (i8** @_ZTIi to i8*)
+ br label %terminate
+
+terminate:
+ %phi = phi i32 [ 0, %lpad.crit ], [ 1, %lpad ]
call void @use(i32 %phi)
call void @_ZSt9terminatev()
unreachable
}
; CHECK: define void @test4_out()
-; CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{%.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 0, i8* bitcast (i8** @_ZTIi to i8*))
+; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
; CHECK-NEXT: invoke void @_ZN1AD1Ev(
; CHECK-NEXT: to label %[[L:[^\s]+]] unwind
; CHECK: [[L]]:
@@ -315,22 +325,18 @@ lpad:
; CHECK: invoke void @opaque()
; CHECK-NEXT: unwind label %lpad
; CHECK: lpad.crit:
-; CHECK-NEXT: call i8* @llvm.eh.exception()
-; CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %4, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*))
+; CHECK-NEXT: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
; CHECK-NEXT: br label %[[JOIN]]
; CHECK: [[JOIN]]:
-; CHECK-NEXT: phi i8*
-; CHECK-NEXT: phi i32
+; CHECK-NEXT: phi { i8*, i32 }
; CHECK-NEXT: call void @opaque() nounwind
; CHECK-NEXT: br label %[[FIX:[^\s]+]]
; CHECK: lpad:
-; CHECK-NEXT: [[T0:%.*]] = phi i32 [ 1, %cont ]
-; CHECK-NEXT: call i8* @llvm.eh.exception() nounwind
-; CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*))
+; CHECK-NEXT: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
; CHECK-NEXT: br label %[[FIX]]
; CHECK: [[FIX]]:
-; CHECK-NEXT: [[T1:%.*]] = phi i32 [ [[T0]], %lpad ], [ 0, %[[JOIN]] ]
-; CHECK-NEXT: phi i8*
-; CHECK-NEXT: phi i32
+; CHECK-NEXT: [[T1:%.*]] = phi i32 [ 0, %[[JOIN]] ], [ 1, %lpad ]
; CHECK-NEXT: call void @use(i32 [[T1]])
; CHECK-NEXT: call void @_ZSt9terminatev()
diff --git a/test/Transforms/Inline/invoke_test-1.ll b/test/Transforms/Inline/invoke_test-1.ll
index 0d27e2a..e0e6d60 100644
--- a/test/Transforms/Inline/invoke_test-1.ll
+++ b/test/Transforms/Inline/invoke_test-1.ll
@@ -20,5 +20,9 @@ cont: ; preds = %0
ret i32 0
exc: ; preds = %0
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i32 1
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/Inline/invoke_test-2.ll b/test/Transforms/Inline/invoke_test-2.ll
index bbb9ab0..680a5ca 100644
--- a/test/Transforms/Inline/invoke_test-2.ll
+++ b/test/Transforms/Inline/invoke_test-2.ll
@@ -14,6 +14,8 @@ cont: ; preds = %0
ret i32 0
exc: ; preds = %0
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i32 1
}
@@ -26,5 +28,9 @@ cont: ; preds = %0
ret i32 %X
UnreachableExceptionHandler: ; preds = %0
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i32 -1
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/Inline/invoke_test-3.ll b/test/Transforms/Inline/invoke_test-3.ll
index b360526..f5ce95a 100644
--- a/test/Transforms/Inline/invoke_test-3.ll
+++ b/test/Transforms/Inline/invoke_test-3.ll
@@ -14,7 +14,9 @@ cont: ; preds = %0
exc: ; preds = %0a
; This just rethrows the exception!
- unwind
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ resume { i8*, i32 } %exn
}
; caller returns true if might_throw throws an exception... which gets
@@ -28,5 +30,9 @@ cont: ; preds = %0
Handler: ; preds = %0
; This consumes an exception thrown by might_throw
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i32 1
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll b/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll
index cfe5df6..56493e2 100644
--- a/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll
+++ b/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll
@@ -10,6 +10,9 @@ invoke_cont: ; preds = %0
ret float* %tmp.11
X: ; preds = %0
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret float* null
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll b/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll
index bec0b9e..6df30c7 100644
--- a/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll
+++ b/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll
@@ -23,6 +23,9 @@ cont: ; preds = %call, %entry
ret i32 %V
N: ; preds = %call
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i32 0
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll b/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll
index 9bb9408..aacea9d 100644
--- a/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll
+++ b/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll
@@ -3,7 +3,8 @@
%struct.FRAME.nest = type { i32, i32 (...)* }
%struct.__builtin_trampoline = type { [10 x i8] }
-declare i8* @llvm.init.trampoline(i8*, i8*, i8*) nounwind
+declare void @llvm.init.trampoline(i8*, i8*, i8*) nounwind
+declare i8* @llvm.adjust.trampoline(i8*) nounwind
declare i32 @f(%struct.FRAME.nest* nest , ...)
@@ -15,7 +16,8 @@ entry:
%tmp3 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 0 ; <i32*> [#uses=1]
store i32 %n, i32* %tmp3, align 8
%FRAME.06 = bitcast %struct.FRAME.nest* %FRAME.0 to i8* ; <i8*> [#uses=1]
- %tramp = call i8* @llvm.init.trampoline( i8* %TRAMP.216.sub, i8* bitcast (i32 (%struct.FRAME.nest*, ...)* @f to i8*), i8* %FRAME.06 ) ; <i8*> [#uses=1]
+ call void @llvm.init.trampoline( i8* %TRAMP.216.sub, i8* bitcast (i32 (%struct.FRAME.nest*, ...)* @f to i8*), i8* %FRAME.06 ) ; <i8*> [#uses=1]
+ %tramp = call i8* @llvm.adjust.trampoline( i8* %TRAMP.216.sub)
%tmp7 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 1 ; <i32 (...)**> [#uses=1]
%tmp89 = bitcast i8* %tramp to i32 (...)* ; <i32 (...)*> [#uses=2]
store i32 (...)* %tmp89, i32 (...)** %tmp7, align 8
diff --git a/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll b/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll
index 626564da..6847f5e 100644
--- a/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll
+++ b/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -instcombine -S | grep {volatile store}
+; RUN: opt < %s -instcombine -S | grep {store volatile}
define void @test() {
%votf = alloca <4 x float> ; <<4 x float>*> [#uses=1]
diff --git a/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll b/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll
index f2cc725..a24f307 100644
--- a/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll
+++ b/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -instcombine -S | grep {volatile load} | count 2
+; RUN: opt < %s -instcombine -S | grep {load volatile} | count 2
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin8"
@g_1 = internal global i32 0 ; <i32*> [#uses=3]
diff --git a/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll b/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll
index 176162d..5fb11ff 100644
--- a/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll
+++ b/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -instcombine -S | grep {volatile load} | count 2
+; RUN: opt < %s -instcombine -S | grep {load volatile} | count 2
; PR2262
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin8"
diff --git a/test/Transforms/InstCombine/2008-05-09-SinkOfInvoke.ll b/test/Transforms/InstCombine/2008-05-09-SinkOfInvoke.ll
index d56a1a0..f6eb248 100644
--- a/test/Transforms/InstCombine/2008-05-09-SinkOfInvoke.ll
+++ b/test/Transforms/InstCombine/2008-05-09-SinkOfInvoke.ll
@@ -29,5 +29,9 @@ invcont37: ; preds = %invcont31
ret void
lpad: ; preds = %invcont31, %invcont, %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll b/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll
index ccfb118..8104408 100644
--- a/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll
+++ b/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -instcombine -S | grep {volatile load} | count 2
+; RUN: opt < %s -instcombine -S | grep {load volatile} | count 2
; PR2496
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin8"
diff --git a/test/Transforms/InstCombine/2011-09-03-Trampoline.ll b/test/Transforms/InstCombine/2011-09-03-Trampoline.ll
new file mode 100644
index 0000000..5456e03
--- /dev/null
+++ b/test/Transforms/InstCombine/2011-09-03-Trampoline.ll
@@ -0,0 +1,87 @@
+; RUN: opt -instcombine -S < %s | FileCheck %s
+
+declare void @llvm.init.trampoline(i8*, i8*, i8*)
+declare i8* @llvm.adjust.trampoline(i8*)
+declare i32 @f(i8 * nest, i32)
+
+; Most common case
+define i32 @test0(i32 %n) {
+ %alloca = alloca [10 x i8], align 16
+ %gep = getelementptr [10 x i8]* %alloca, i32 0, i32 0
+ call void @llvm.init.trampoline(i8* %gep, i8* bitcast (i32 (i8*, i32)* @f to i8*),
+ i8* null)
+ %tramp = call i8* @llvm.adjust.trampoline(i8* %gep)
+ %function = bitcast i8* %tramp to i32(i32)*
+ %ret = call i32 %function(i32 %n)
+ ret i32 %ret
+
+; CHECK: define i32 @test0(i32 %n) {
+; CHECK: %ret = call i32 @f(i8* nest null, i32 %n)
+}
+
+define i32 @test1(i32 %n, i8* %trampmem) {
+ call void @llvm.init.trampoline(i8* %trampmem,
+ i8* bitcast (i32 (i8*, i32)* @f to i8*),
+ i8* null)
+ %tramp = call i8* @llvm.adjust.trampoline(i8* %trampmem)
+ %function = bitcast i8* %tramp to i32(i32)*
+ %ret = call i32 %function(i32 %n)
+ ret i32 %ret
+; CHECK: define i32 @test1(i32 %n, i8* %trampmem) {
+; CHECK: %ret = call i32 @f(i8* nest null, i32 %n)
+}
+
+define i32 @test2(i32 %n, i8* %trampmem) {
+ %tramp = call i8* @llvm.adjust.trampoline(i8* %trampmem)
+ %functiona = bitcast i8* %tramp to i32(i32)*
+ %ret = call i32 %functiona(i32 %n)
+ ret i32 %ret
+; CHECK: define i32 @test2(i32 %n, i8* %trampmem) {
+; CHECK: %ret = call i32 %functiona(i32 %n)
+}
+
+define i32 @test3(i32 %n, i8* %trampmem) {
+ call void @llvm.init.trampoline(i8* %trampmem,
+ i8* bitcast (i32 (i8*, i32)* @f to i8*),
+ i8* null)
+
+; CHECK: define i32 @test3(i32 %n, i8* %trampmem) {
+; CHECK: %ret0 = call i32 @f(i8* nest null, i32 %n)
+ %tramp0 = call i8* @llvm.adjust.trampoline(i8* %trampmem)
+ %function0 = bitcast i8* %tramp0 to i32(i32)*
+ %ret0 = call i32 %function0(i32 %n)
+
+ ;; Not optimized since previous call could be writing.
+ %tramp1 = call i8* @llvm.adjust.trampoline(i8* %trampmem)
+ %function1 = bitcast i8* %tramp1 to i32(i32)*
+ %ret1 = call i32 %function1(i32 %n)
+; CHECK: %ret1 = call i32 %function1(i32 %n)
+
+ ret i32 %ret1
+}
+
+define i32 @test4(i32 %n) {
+ %alloca = alloca [10 x i8], align 16
+ %gep = getelementptr [10 x i8]* %alloca, i32 0, i32 0
+ call void @llvm.init.trampoline(i8* %gep, i8* bitcast (i32 (i8*, i32)* @f to i8*),
+ i8* null)
+
+ %tramp0 = call i8* @llvm.adjust.trampoline(i8* %gep)
+ %function0 = bitcast i8* %tramp0 to i32(i32)*
+ %ret0 = call i32 %function0(i32 %n)
+
+ %tramp1 = call i8* @llvm.adjust.trampoline(i8* %gep)
+ %function1 = bitcast i8* %tramp0 to i32(i32)*
+ %ret1 = call i32 %function1(i32 %n)
+
+ %tramp2 = call i8* @llvm.adjust.trampoline(i8* %gep)
+ %function2 = bitcast i8* %tramp2 to i32(i32)*
+ %ret2 = call i32 %function2(i32 %n)
+
+ ret i32 %ret2
+
+; CHECK: define i32 @test4(i32 %n) {
+; CHECK: %ret0 = call i32 @f(i8* nest null, i32 %n)
+; CHECK: %ret1 = call i32 @f(i8* nest null, i32 %n)
+; CHECK: %ret2 = call i32 @f(i8* nest null, i32 %n)
+}
diff --git a/test/Transforms/InstCombine/2011-10-07-AlignPromotion.ll b/test/Transforms/InstCombine/2011-10-07-AlignPromotion.ll
new file mode 100644
index 0000000..22061b2
--- /dev/null
+++ b/test/Transforms/InstCombine/2011-10-07-AlignPromotion.ll
@@ -0,0 +1,20 @@
+; RUN: opt -S -instcombine < %s | FileCheck %s
+; rdar://problem/10063307
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32"
+target triple = "thumbv7-apple-ios5.0.0"
+
+%0 = type { [2 x i32] }
+%struct.CGPoint = type { float, float }
+
+define void @t(%struct.CGPoint* %a) nounwind {
+ %Point = alloca %struct.CGPoint, align 4
+ %1 = bitcast %struct.CGPoint* %a to i64*
+ %2 = bitcast %struct.CGPoint* %Point to i64*
+ %3 = load i64* %1, align 4
+ store i64 %3, i64* %2, align 4
+ call void @foo(i64* %2) nounwind
+ ret void
+; CHECK: %Point = alloca i64, align 4
+}
+
+declare void @foo(i64*)
diff --git a/test/Transforms/InstCombine/LandingPadClauses.ll b/test/Transforms/InstCombine/LandingPadClauses.ll
new file mode 100644
index 0000000..055bdcc
--- /dev/null
+++ b/test/Transforms/InstCombine/LandingPadClauses.ll
@@ -0,0 +1,181 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+@T1 = external constant i32
+@T2 = external constant i32
+@T3 = external constant i32
+
+declare i32 @generic_personality(i32, i64, i8*, i8*)
+declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)
+
+declare void @bar()
+
+define void @foo_generic() {
+; CHECK: @foo_generic
+ invoke void @bar()
+ to label %cont.a unwind label %lpad.a
+cont.a:
+ invoke void @bar()
+ to label %cont.b unwind label %lpad.b
+cont.b:
+ invoke void @bar()
+ to label %cont.c unwind label %lpad.c
+cont.c:
+ invoke void @bar()
+ to label %cont.d unwind label %lpad.d
+cont.d:
+ invoke void @bar()
+ to label %cont.e unwind label %lpad.e
+cont.e:
+ invoke void @bar()
+ to label %cont.f unwind label %lpad.f
+cont.f:
+ invoke void @bar()
+ to label %cont.g unwind label %lpad.g
+cont.g:
+ invoke void @bar()
+ to label %cont.h unwind label %lpad.h
+cont.h:
+ invoke void @bar()
+ to label %cont.i unwind label %lpad.i
+cont.i:
+ ret void
+
+lpad.a:
+ %a = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality
+ catch i32* @T1
+ catch i32* @T2
+ catch i32* @T1
+ catch i32* @T2
+ unreachable
+; CHECK: %a = landingpad
+; CHECK-NEXT: @T1
+; CHECK-NEXT: @T2
+; CHECK-NEXT: unreachable
+
+lpad.b:
+ %b = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality
+ filter [0 x i32*] zeroinitializer
+ catch i32* @T1
+ unreachable
+; CHECK: %b = landingpad
+; CHECK-NEXT: filter
+; CHECK-NEXT: unreachable
+
+lpad.c:
+ %c = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality
+ catch i32* @T1
+ filter [1 x i32*] [i32* @T1]
+ catch i32* @T2
+ unreachable
+; CHECK: %c = landingpad
+; CHECK-NEXT: @T1
+; CHECK-NEXT: filter [0 x i32*]
+; CHECK-NEXT: unreachable
+
+lpad.d:
+ %d = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality
+ filter [3 x i32*] zeroinitializer
+ unreachable
+; CHECK: %d = landingpad
+; CHECK-NEXT: filter [1 x i32*] zeroinitializer
+; CHECK-NEXT: unreachable
+
+lpad.e:
+ %e = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality
+ catch i32* @T1
+ filter [3 x i32*] [i32* @T1, i32* @T2, i32* @T2]
+ unreachable
+; CHECK: %e = landingpad
+; CHECK-NEXT: @T1
+; CHECK-NEXT: filter [1 x i32*] [i32* @T2]
+; CHECK-NEXT: unreachable
+
+lpad.f:
+ %f = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality
+ filter [2 x i32*] [i32* @T2, i32* @T1]
+ filter [1 x i32*] [i32* @T1]
+ unreachable
+; CHECK: %f = landingpad
+; CHECK-NEXT: filter [1 x i32*] [i32* @T1]
+; CHECK-NEXT: unreachable
+
+lpad.g:
+ %g = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality
+ filter [1 x i32*] [i32* @T1]
+ catch i32* @T3
+ filter [2 x i32*] [i32* @T2, i32* @T1]
+ unreachable
+; CHECK: %g = landingpad
+; CHECK-NEXT: filter [1 x i32*] [i32* @T1]
+; CHECK-NEXT: catch i32* @T3
+; CHECK-NEXT: unreachable
+
+lpad.h:
+ %h = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality
+ filter [2 x i32*] [i32* @T1, i32* null]
+ filter [1 x i32*] zeroinitializer
+ unreachable
+; CHECK: %h = landingpad
+; CHECK-NEXT: filter [1 x i32*] zeroinitializer
+; CHECK-NEXT: unreachable
+
+lpad.i:
+ %i = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @generic_personality
+ cleanup
+ filter [0 x i32*] zeroinitializer
+ unreachable
+; CHECK: %i = landingpad
+; CHECK-NEXT: filter
+; CHECK-NEXT: unreachable
+}
+
+define void @foo_cxx() {
+; CHECK: @foo_cxx
+ invoke void @bar()
+ to label %cont.a unwind label %lpad.a
+cont.a:
+ invoke void @bar()
+ to label %cont.b unwind label %lpad.b
+cont.b:
+ invoke void @bar()
+ to label %cont.c unwind label %lpad.c
+cont.c:
+ invoke void @bar()
+ to label %cont.d unwind label %lpad.d
+cont.d:
+ ret void
+
+lpad.a:
+ %a = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0
+ catch i32* null
+ catch i32* @T1
+ unreachable
+; CHECK: %a = landingpad
+; CHECK-NEXT: null
+; CHECK-NEXT: unreachable
+
+lpad.b:
+ %b = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0
+ filter [1 x i32*] zeroinitializer
+ unreachable
+; CHECK: %b = landingpad
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: unreachable
+
+lpad.c:
+ %c = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0
+ filter [2 x i32*] [i32* @T1, i32* null]
+ unreachable
+; CHECK: %c = landingpad
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: unreachable
+
+lpad.d:
+ %d = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0
+ cleanup
+ catch i32* null
+ unreachable
+; CHECK: %d = landingpad
+; CHECK-NEXT: null
+; CHECK-NEXT: unreachable
+}
diff --git a/test/Transforms/InstCombine/and2.ll b/test/Transforms/InstCombine/and2.ll
index a888152..531aedb 100644
--- a/test/Transforms/InstCombine/and2.ll
+++ b/test/Transforms/InstCombine/and2.ll
@@ -35,3 +35,10 @@ define i1 @test4(i32 %X) {
; CHECK: @test4
; CHECK-NEXT: ret i1 false
}
+
+; Make sure we don't go into an infinite loop with this test
+define <4 x i32> @test5(<4 x i32> %A) {
+ %1 = xor <4 x i32> %A, <i32 1, i32 2, i32 3, i32 4>
+ %2 = and <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %1
+ ret <4 x i32> %2
+}
diff --git a/test/Transforms/InstCombine/atomic.ll b/test/Transforms/InstCombine/atomic.ll
new file mode 100644
index 0000000..097cf5e
--- /dev/null
+++ b/test/Transforms/InstCombine/atomic.ll
@@ -0,0 +1,24 @@
+; RUN: opt -S < %s -instcombine | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+; Check transforms involving atomic operations
+
+define i32* @test1(i8** %p) {
+; CHECK: define i32* @test1
+; CHECK: load atomic i8** %p monotonic, align 8
+ %c = bitcast i8** %p to i32**
+ %r = load atomic i32** %c monotonic, align 8
+ ret i32* %r
+}
+
+define i32 @test2(i32* %p) {
+; CHECK: define i32 @test2
+; CHECK: %x = load atomic i32* %p seq_cst, align 4
+; CHECK: shl i32 %x, 1
+ %x = load atomic i32* %p seq_cst, align 4
+ %y = load i32* %p, align 4
+ %z = add i32 %x, %y
+ ret i32 %z
+}
diff --git a/test/Transforms/InstCombine/bitcast.ll b/test/Transforms/InstCombine/bitcast.ll
index 0718b8a..8f6ae7d 100644
--- a/test/Transforms/InstCombine/bitcast.ll
+++ b/test/Transforms/InstCombine/bitcast.ll
@@ -1,5 +1,8 @@
; RUN: opt < %s -instcombine -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin10.0.0"
+
; Bitcasts between vectors and scalars are valid.
; PR4487
define i32 @test1(i64 %a) {
@@ -103,3 +106,34 @@ define <2 x float> @test6(float %A){
; CHECK-NEXT: insertelement <2 x float> <float 4.200000e+01, float undef>, float %A, i32 1
; CHECK: ret
}
+
+define i64 @ISPC0(i64 %in) {
+ %out = and i64 %in, xor (i64 bitcast (<4 x i16> <i16 -1, i16 -1, i16 -1, i16 -1> to i64), i64 -1)
+ ret i64 %out
+; CHECK: @ISPC0
+; CHECK: ret i64 0
+}
+
+
+define i64 @Vec2(i64 %in) {
+ %out = and i64 %in, xor (i64 bitcast (<4 x i16> <i16 0, i16 0, i16 0, i16 0> to i64), i64 0)
+ ret i64 %out
+; CHECK: @Vec2
+; CHECK: ret i64 0
+}
+
+define i64 @All11(i64 %in) {
+ %out = and i64 %in, xor (i64 bitcast (<2 x float> bitcast (i64 -1 to <2 x float>) to i64), i64 -1)
+ ret i64 %out
+; CHECK: @All11
+; CHECK: ret i64 0
+}
+
+
+define i32 @All111(i32 %in) {
+ %out = and i32 %in, xor (i32 bitcast (<1 x float> bitcast (i32 -1 to <1 x float>) to i32), i32 -1)
+ ret i32 %out
+; CHECK: @All111
+; CHECK: ret i32 0
+}
+
diff --git a/test/Transforms/InstCombine/call.ll b/test/Transforms/InstCombine/call.ll
index d084873..96ec420 100644
--- a/test/Transforms/InstCombine/call.ll
+++ b/test/Transforms/InstCombine/call.ll
@@ -9,8 +9,8 @@ declare void @test1a(i8*)
define void @test1(i32* %A) {
call void bitcast (void (i8*)* @test1a to void (i32*)*)( i32* %A )
ret void
-; CHECK: %tmp = bitcast i32* %A to i8*
-; CHECK: call void @test1a(i8* %tmp)
+; CHECK: %1 = bitcast i32* %A to i8*
+; CHECK: call void @test1a(i8* %1)
; CHECK: ret void
}
@@ -24,8 +24,8 @@ define void @test2a(i8 %A) {
define i32 @test2(i32 %A) {
call void bitcast (void (i8)* @test2a to void (i32)*)( i32 %A )
ret i32 %A
-; CHECK: %tmp = trunc i32 %A to i8
-; CHECK: call void @test2a(i8 %tmp)
+; CHECK: %1 = trunc i32 %A to i8
+; CHECK: call void @test2a(i8 %1)
; CHECK: ret i32 %A
}
@@ -38,8 +38,8 @@ define void @test3(i8 %A, i8 %B) {
call void bitcast (void (i8, ...)* @test3a to void (i8, i8)*)( i8 %A, i8 %B
)
ret void
-; CHECK: %tmp = zext i8 %B to i32
-; CHECK: call void (i8, ...)* @test3a(i8 %A, i32 %tmp)
+; CHECK: %1 = zext i8 %B to i32
+; CHECK: call void (i8, ...)* @test3a(i8 %A, i32 %1)
; CHECK: ret void
}
@@ -54,8 +54,8 @@ define i32 @test4() {
%X = call i32 bitcast (i8 ()* @test4a to i32 ()*)( ) ; <i32> [#uses=1]
ret i32 %X
; CHECK: %X = call i8 @test4a()
-; CHECK: %tmp = zext i8 %X to i32
-; CHECK: ret i32 %tmp
+; CHECK: %1 = zext i8 %X to i32
+; CHECK: ret i32 %1
}
@@ -107,9 +107,13 @@ invoke.cont: ; preds = %entry
unreachable
try.handler: ; preds = %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret i8* null
}
+declare i32 @__gxx_personality_v0(...)
+
; Don't turn this into "unreachable": the callee and caller don't agree in
; calling conv, but the implementation of test8a may actually end up using the
; right calling conv.
diff --git a/test/Transforms/InstCombine/canonicalize_branch.ll b/test/Transforms/InstCombine/canonicalize_branch.ll
index 24090ab..869546d 100644
--- a/test/Transforms/InstCombine/canonicalize_branch.ll
+++ b/test/Transforms/InstCombine/canonicalize_branch.ll
@@ -1,8 +1,23 @@
; RUN: opt < %s -instcombine -S | FileCheck %s
+; Test an already canonical branch to make sure we don't flip those.
+define i32 @test0(i32 %X, i32 %Y) {
+ %C = icmp eq i32 %X, %Y
+ br i1 %C, label %T, label %F, !prof !0
+
+; CHECK: @test0
+; CHECK: %C = icmp eq i32 %X, %Y
+; CHECK: br i1 %C, label %T, label %F
+
+T:
+ ret i32 12
+F:
+ ret i32 123
+}
+
define i32 @test1(i32 %X, i32 %Y) {
%C = icmp ne i32 %X, %Y
- br i1 %C, label %T, label %F
+ br i1 %C, label %T, label %F, !prof !1
; CHECK: @test1
; CHECK: %C = icmp eq i32 %X, %Y
@@ -16,7 +31,7 @@ F:
define i32 @test2(i32 %X, i32 %Y) {
%C = icmp ule i32 %X, %Y
- br i1 %C, label %T, label %F
+ br i1 %C, label %T, label %F, !prof !2
; CHECK: @test2
; CHECK: %C = icmp ugt i32 %X, %Y
@@ -30,7 +45,7 @@ F:
define i32 @test3(i32 %X, i32 %Y) {
%C = icmp uge i32 %X, %Y
- br i1 %C, label %T, label %F
+ br i1 %C, label %T, label %F, !prof !3
; CHECK: @test3
; CHECK: %C = icmp ult i32 %X, %Y
@@ -42,3 +57,13 @@ F:
ret i32 123
}
+!0 = metadata !{metadata !"branch_weights", i32 1, i32 2}
+!1 = metadata !{metadata !"branch_weights", i32 3, i32 4}
+!2 = metadata !{metadata !"branch_weights", i32 5, i32 6}
+!3 = metadata !{metadata !"branch_weights", i32 7, i32 8}
+; Base case shouldn't change.
+; CHECK: !0 = {{.*}} i32 1, i32 2}
+; Ensure that the branch metadata is reversed to match the reversals above.
+; CHECK: !1 = {{.*}} i32 4, i32 3}
+; CHECK: !2 = {{.*}} i32 6, i32 5}
+; CHECK: !3 = {{.*}} i32 8, i32 7}
diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll
index f85636f..19d5a0a 100644
--- a/test/Transforms/InstCombine/cast.ll
+++ b/test/Transforms/InstCombine/cast.ll
@@ -630,3 +630,50 @@ entry:
; CHECK: uitofp
}
+define <4 x float> @test64(<4 x float> %c) nounwind {
+ %t0 = bitcast <4 x float> %c to <4 x i32>
+ %t1 = bitcast <4 x i32> %t0 to <4 x float>
+ ret <4 x float> %t1
+; CHECK: @test64
+; CHECK-NEXT: ret <4 x float> %c
+}
+
+define <4 x float> @test65(<4 x float> %c) nounwind {
+ %t0 = bitcast <4 x float> %c to <2 x double>
+ %t1 = bitcast <2 x double> %t0 to <4 x float>
+ ret <4 x float> %t1
+; CHECK: @test65
+; CHECK-NEXT: ret <4 x float> %c
+}
+
+define <2 x float> @test66(<2 x float> %c) nounwind {
+ %t0 = bitcast <2 x float> %c to double
+ %t1 = bitcast double %t0 to <2 x float>
+ ret <2 x float> %t1
+; CHECK: @test66
+; CHECK-NEXT: ret <2 x float> %c
+}
+
+define float @test2c() {
+ ret float extractelement (<2 x float> bitcast (double bitcast (<2 x float> <float -1.000000e+00, float -1.000000e+00> to double) to <2 x float>), i32 0)
+; CHECK: @test2c
+; CHECK-NOT: extractelement
+}
+
+define i64 @test_mmx(<2 x i32> %c) nounwind {
+ %A = bitcast <2 x i32> %c to x86_mmx
+ %B = bitcast x86_mmx %A to <2 x i32>
+ %C = bitcast <2 x i32> %B to i64
+ ret i64 %C
+; CHECK: @test_mmx
+; CHECK-NOT: x86_mmx
+}
+
+define i64 @test_mmx_const(<2 x i32> %c) nounwind {
+ %A = bitcast <2 x i32> zeroinitializer to x86_mmx
+ %B = bitcast x86_mmx %A to <2 x i32>
+ %C = bitcast <2 x i32> %B to i64
+ ret i64 %C
+; CHECK: @test_mmx_const
+; CHECK-NOT: x86_mmx
+}
diff --git a/test/Transforms/InstCombine/crash.ll b/test/Transforms/InstCombine/crash.ll
index e17774d..1a657f5 100644
--- a/test/Transforms/InstCombine/crash.ll
+++ b/test/Transforms/InstCombine/crash.ll
@@ -135,6 +135,8 @@ define void @test5() {
store i1 true, i1* undef
%1 = invoke i32 @test5a() to label %exit unwind label %exit
exit:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret void
}
@@ -219,6 +221,8 @@ invoke.cont: ; preds = %entry
unreachable
try.handler: ; preds = %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
ret i8* %self
}
diff --git a/test/Transforms/InstCombine/deadcode.ll b/test/Transforms/InstCombine/deadcode.ll
index 52af0ef..7c7f1ab 100644
--- a/test/Transforms/InstCombine/deadcode.ll
+++ b/test/Transforms/InstCombine/deadcode.ll
@@ -1,5 +1,5 @@
; RUN: opt < %s -instcombine -S | grep {ret i32 %A}
-; RUN: opt < %s -die -S | not grep call.*llvm.stacksave
+; RUN: opt < %s -die -S | not grep call.*llvm
define i32 @test(i32 %A) {
%X = or i1 false, false
@@ -22,3 +22,12 @@ define i32* @test2(i32 %width) {
declare i8* @llvm.stacksave()
+declare void @llvm.lifetime.start(i64, i8*)
+declare void @llvm.lifetime.end(i64, i8*)
+
+define void @test3() {
+ call void @llvm.lifetime.start(i64 -1, i8* undef)
+ call void @llvm.lifetime.end(i64 -1, i8* undef)
+ ret void
+}
+
diff --git a/test/Transforms/InstCombine/devirt.ll b/test/Transforms/InstCombine/devirt.ll
new file mode 100644
index 0000000..6189dc2
--- /dev/null
+++ b/test/Transforms/InstCombine/devirt.ll
@@ -0,0 +1,39 @@
+; RUN: opt -instcombine -S -o - %s | FileCheck %s
+
+; CHECK-NOT: getelementptr
+; CHECK-NOT: ptrtoint
+; CHECK: bitcast i8*
+%struct.S = type { i32 (...)** }
+
+@_ZL1p = internal constant { i64, i64 } { i64 1, i64 0 }, align 8
+
+define void @_Z1g1S(%struct.S* %s) nounwind {
+entry:
+ %tmp = load { i64, i64 }* @_ZL1p, align 8
+ %memptr.adj = extractvalue { i64, i64 } %tmp, 1
+ %0 = bitcast %struct.S* %s to i8*
+ %1 = getelementptr inbounds i8* %0, i64 %memptr.adj
+ %this.adjusted = bitcast i8* %1 to %struct.S*
+ %memptr.ptr = extractvalue { i64, i64 } %tmp, 0
+ %2 = and i64 %memptr.ptr, 1
+ %memptr.isvirtual = icmp ne i64 %2, 0
+ br i1 %memptr.isvirtual, label %memptr.virtual, label %memptr.nonvirtual
+
+memptr.virtual: ; preds = %entry
+ %3 = bitcast %struct.S* %this.adjusted to i8**
+ %memptr.vtable = load i8** %3
+ %4 = sub i64 %memptr.ptr, 1
+ %5 = getelementptr i8* %memptr.vtable, i64 %4
+ %6 = bitcast i8* %5 to void (%struct.S*)**
+ %memptr.virtualfn = load void (%struct.S*)** %6
+ br label %memptr.end
+
+memptr.nonvirtual: ; preds = %entry
+ %memptr.nonvirtualfn = inttoptr i64 %memptr.ptr to void (%struct.S*)*
+ br label %memptr.end
+
+memptr.end: ; preds = %memptr.nonvirtual, %memptr.virtual
+ %7 = phi void (%struct.S*)* [ %memptr.virtualfn, %memptr.virtual ], [ %memptr.nonvirtualfn, %memptr.nonvirtual ]
+ call void %7(%struct.S* %this.adjusted)
+ ret void
+}
diff --git a/test/Transforms/InstCombine/extractvalue.ll b/test/Transforms/InstCombine/extractvalue.ll
index 64edc18..cf36b8f 100644
--- a/test/Transforms/InstCombine/extractvalue.ll
+++ b/test/Transforms/InstCombine/extractvalue.ll
@@ -96,7 +96,7 @@ define i32 @nogep-multiuse({i32, i32}* %pair) {
}
; CHECK: define i32 @nogep-volatile
-; CHECK-NEXT: volatile load {{.*}} %pair
+; CHECK-NEXT: load volatile {{.*}} %pair
; CHECK-NEXT: extractvalue
; CHECK-NEXT: ret
define i32 @nogep-volatile({i32, i32}* %pair) {
diff --git a/test/Transforms/InstCombine/fcmp.ll b/test/Transforms/InstCombine/fcmp.ll
index 2eb4f05..d08cbf5 100644
--- a/test/Transforms/InstCombine/fcmp.ll
+++ b/test/Transforms/InstCombine/fcmp.ll
@@ -58,3 +58,14 @@ define i1 @test7(float %x) nounwind readnone ssp noredzone {
; CHECK: @test7
; CHECK-NEXT: fpext float %x to ppc_fp128
}
+
+define float @test8(float %x) nounwind readnone optsize ssp {
+ %conv = fpext float %x to double
+ %cmp = fcmp olt double %conv, 0.000000e+00
+ %conv1 = zext i1 %cmp to i32
+ %conv2 = sitofp i32 %conv1 to float
+ ret float %conv2
+; Float comparison to zero shouldn't cast to double.
+; CHECK: @test8
+; CHECK-NEXT: fcmp olt float %x, 0.000000e+00
+}
diff --git a/test/Transforms/InstCombine/getelementptr.ll b/test/Transforms/InstCombine/getelementptr.ll
index 26c0e47..1c120ec 100644
--- a/test/Transforms/InstCombine/getelementptr.ll
+++ b/test/Transforms/InstCombine/getelementptr.ll
@@ -472,3 +472,23 @@ entry:
; CHECK: @pr10322_f1
; CHECK: %tmp2 = getelementptr inbounds %pr10322_t* %arrayidx8, i64 0, i32 0
}
+
+; Test that we combine the last two geps in this sequence, before we
+; would wait for gep1 and gep2 to be combined and never combine 2 and 3.
+%three_gep_t = type {i32}
+%three_gep_t2 = type {%three_gep_t}
+
+define void @three_gep_f(%three_gep_t2* %x) {
+ %gep1 = getelementptr %three_gep_t2* %x, i64 2
+ call void @three_gep_h(%three_gep_t2* %gep1)
+ %gep2 = getelementptr %three_gep_t2* %gep1, i64 0, i32 0
+ %gep3 = getelementptr %three_gep_t* %gep2, i64 0, i32 0
+ call void @three_gep_g(i32* %gep3)
+
+; CHECK: @three_gep_f
+; CHECK: %gep3 = getelementptr %three_gep_t2* %gep1, i64 0, i32 0, i32 0
+ ret void
+}
+
+declare void @three_gep_g(i32*)
+declare void @three_gep_h(%three_gep_t2*)
diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll
index 0d84ae4..f033e51 100644
--- a/test/Transforms/InstCombine/intrinsics.ll
+++ b/test/Transforms/InstCombine/intrinsics.ll
@@ -152,9 +152,9 @@ entry:
ret void
; CHECK: @powi
; CHECK: %A = fdiv double 1.0{{.*}}, %V
-; CHECK: volatile store double %A,
-; CHECK: volatile store double 1.0
-; CHECK: volatile store double %V
+; CHECK: store volatile double %A,
+; CHECK: store volatile double 1.0
+; CHECK: store volatile double %V
}
define i32 @cttz(i32 %a) {
@@ -194,11 +194,11 @@ entry:
; CHECK: @cmp.simplify
; CHECK-NEXT: entry:
; CHECK-NEXT: %lz.cmp = icmp eq i32 %a, 0
-; CHECK-NEXT: volatile store i1 %lz.cmp, i1* %c
+; CHECK-NEXT: store volatile i1 %lz.cmp, i1* %c
; CHECK-NEXT: %tz.cmp = icmp ne i32 %a, 0
-; CHECK-NEXT: volatile store i1 %tz.cmp, i1* %c
+; CHECK-NEXT: store volatile i1 %tz.cmp, i1* %c
; CHECK-NEXT: %pop.cmp = icmp eq i32 %b, 0
-; CHECK-NEXT: volatile store i1 %pop.cmp, i1* %c
+; CHECK-NEXT: store volatile i1 %pop.cmp, i1* %c
}
diff --git a/test/Transforms/InstCombine/malloc-free-delete.ll b/test/Transforms/InstCombine/malloc-free-delete.ll
index 8455300..eae973d 100644
--- a/test/Transforms/InstCombine/malloc-free-delete.ll
+++ b/test/Transforms/InstCombine/malloc-free-delete.ll
@@ -12,7 +12,7 @@ define i32 @main(i32 %argc, i8** %argv) {
; CHECK: ret i32 0
}
-declare i8* @malloc(i32)
+declare noalias i8* @malloc(i32)
declare void @free(i8*)
define i1 @foo() {
@@ -23,3 +23,26 @@ define i1 @foo() {
call void @free(i8* %m)
ret i1 %z
}
+
+declare void @llvm.lifetime.start(i64, i8*)
+declare void @llvm.lifetime.end(i64, i8*)
+
+define void @test3() {
+; CHECK: @test3
+; CHECK-NEXT: ret void
+ %a = call noalias i8* @malloc(i32 10)
+ call void @llvm.lifetime.start(i64 10, i8* %a)
+ call void @llvm.lifetime.end(i64 10, i8* %a)
+ ret void
+}
+
+;; This used to crash.
+define void @test4() {
+; CHECK: @test4
+; CHECK-NEXT: ret void
+ %A = call i8* @malloc(i32 16000)
+ %B = bitcast i8* %A to double*
+ %C = bitcast double* %B to i8*
+ call void @free(i8* %C)
+ ret void
+}
diff --git a/test/Transforms/InstCombine/nsw.ll b/test/Transforms/InstCombine/nsw.ll
index 681bdc2..0140c2f 100644
--- a/test/Transforms/InstCombine/nsw.ll
+++ b/test/Transforms/InstCombine/nsw.ll
@@ -37,3 +37,47 @@ define i64 @shl1(i64 %X, i64* %P) nounwind {
%B = shl i64 %A, 8
ret i64 %B
}
+
+; CHECK: @preserve1
+; CHECK: add nsw i32 %x, 5
+define i32 @preserve1(i32 %x) nounwind {
+ %add = add nsw i32 %x, 2
+ %add3 = add nsw i32 %add, 3
+ ret i32 %add3
+}
+
+; CHECK: @nopreserve1
+; CHECK: add i8 %x, -126
+define i8 @nopreserve1(i8 %x) nounwind {
+ %add = add nsw i8 %x, 127
+ %add3 = add nsw i8 %add, 3
+ ret i8 %add3
+}
+
+; CHECK: @nopreserve2
+; CHECK: add i8 %x, 3
+define i8 @nopreserve2(i8 %x) nounwind {
+ %add = add i8 %x, 1
+ %add3 = add nsw i8 %add, 2
+ ret i8 %add3
+}
+
+; CHECK: @nopreserve3
+; CHECK: add i8 %A, %B
+; CHECK: add i8
+define i8 @nopreserve3(i8 %A, i8 %B) nounwind {
+ %x = add i8 %A, 10
+ %y = add i8 %B, 10
+ %add = add nsw i8 %x, %y
+ ret i8 %add
+}
+
+; CHECK: @nopreserve4
+; CHECK: add i8 %A, %B
+; CHECK: add i8
+define i8 @nopreserve4(i8 %A, i8 %B) nounwind {
+ %x = add nsw i8 %A, 10
+ %y = add nsw i8 %B, 10
+ %add = add nsw i8 %x, %y
+ ret i8 %add
+}
diff --git a/test/Transforms/InstCombine/ptr-int-cast.ll b/test/Transforms/InstCombine/ptr-int-cast.ll
index ad11e43..9524d44 100644
--- a/test/Transforms/InstCombine/ptr-int-cast.ll
+++ b/test/Transforms/InstCombine/ptr-int-cast.ll
@@ -5,22 +5,22 @@ define i1 @test1(i32 *%x) nounwind {
entry:
; CHECK: test1
; CHECK: ptrtoint i32* %x to i64
- %tmp = ptrtoint i32* %x to i1
- ret i1 %tmp
+ %0 = ptrtoint i32* %x to i1
+ ret i1 %0
}
define i32* @test2(i128 %x) nounwind {
entry:
; CHECK: test2
-; CHECK: inttoptr i64 %tmp1 to i32*
- %tmp = inttoptr i128 %x to i32*
- ret i32* %tmp
+; CHECK: inttoptr i64 %0 to i32*
+ %0 = inttoptr i128 %x to i32*
+ ret i32* %0
}
; PR3574
; CHECK: f0
-; CHECK: %tmp = zext i32 %a0 to i64
-; CHECK: ret i64 %tmp
+; CHECK: %1 = zext i32 %a0 to i64
+; CHECK: ret i64 %1
define i64 @f0(i32 %a0) nounwind {
%t0 = inttoptr i32 %a0 to i8*
%t1 = ptrtoint i8* %t0 to i64
diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll
index 4ca9bd2..4661561 100644
--- a/test/Transforms/InstCombine/select.ll
+++ b/test/Transforms/InstCombine/select.ll
@@ -799,3 +799,13 @@ define i1 @test60(i32 %x, i1* %y) nounwind {
; CHECK: @test60
; CHECK: select
}
+
+@glbl = constant i32 10
+define i32 @test61(i32* %ptr) {
+ %A = load i32* %ptr
+ %B = icmp eq i32* %ptr, @glbl
+ %C = select i1 %B, i32 %A, i32 10
+ ret i32 %C
+; CHECK: @test61
+; CHECK: ret i32 10
+}
diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll
index d9ac9cb..132d51a 100644
--- a/test/Transforms/InstCombine/shift.ll
+++ b/test/Transforms/InstCombine/shift.ll
@@ -525,5 +525,20 @@ define i32 @test43(i32 %a, i32 %b) nounwind {
; CHECK-NEXT: ret
}
-
-
+define i32 @test44(i32 %a) nounwind {
+ %y = shl nuw i32 %a, 1
+ %z = shl i32 %y, 4
+ ret i32 %z
+; CHECK: @test44
+; CHECK-NEXT: %y = shl i32 %a, 5
+; CHECK-NEXT: ret i32 %y
+}
+
+define i32 @test45(i32 %a) nounwind {
+ %y = lshr exact i32 %a, 1
+ %z = lshr i32 %y, 4
+ ret i32 %z
+; CHECK: @test45
+; CHECK-NEXT: %y = lshr i32 %a, 5
+; CHECK-NEXT: ret i32 %y
+}
diff --git a/test/Transforms/InstCombine/vec_demanded_elts.ll b/test/Transforms/InstCombine/vec_demanded_elts.ll
index e0188fe..cc63371 100644
--- a/test/Transforms/InstCombine/vec_demanded_elts.ll
+++ b/test/Transforms/InstCombine/vec_demanded_elts.ll
@@ -152,3 +152,14 @@ entry:
ret <4 x i32> %0
}
declare <4 x i32> @llvm.x86.sse41.pmovzxwd(<8 x i16>) nounwind readnone
+
+define <4 x float> @dead_shuffle_elt(<4 x float> %x, <2 x float> %y) nounwind {
+entry:
+; CHECK: define <4 x float> @dead_shuffle_elt
+; CHECK: shufflevector <2 x float> %y, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
+ %shuffle.i = shufflevector <2 x float> %y, <2 x float> %y, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
+ %shuffle9.i = shufflevector <4 x float> %x, <4 x float> %shuffle.i, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
+ ret <4 x float> %shuffle9.i
+}
+
+
diff --git a/test/Transforms/InstCombine/vector-casts.ll b/test/Transforms/InstCombine/vector-casts.ll
index e931dc7..7bbf53c 100644
--- a/test/Transforms/InstCombine/vector-casts.ll
+++ b/test/Transforms/InstCombine/vector-casts.ll
@@ -7,7 +7,7 @@ define <2 x i1> @test1(<2 x i64> %a) {
; CHECK: @test1
; CHECK: and <2 x i64> %a, <i64 1, i64 1>
-; CHECK: icmp ne <2 x i64> %tmp, zeroinitializer
+; CHECK: icmp ne <2 x i64> %1, zeroinitializer
}
; The ashr turns into an lshr.
diff --git a/test/Transforms/InstCombine/volatile_store.ll b/test/Transforms/InstCombine/volatile_store.ll
index 5316bd7..0518e5a 100644
--- a/test/Transforms/InstCombine/volatile_store.ll
+++ b/test/Transforms/InstCombine/volatile_store.ll
@@ -1,5 +1,5 @@
-; RUN: opt < %s -instcombine -S | grep {volatile store}
-; RUN: opt < %s -instcombine -S | grep {volatile load}
+; RUN: opt < %s -instcombine -S | grep {store volatile}
+; RUN: opt < %s -instcombine -S | grep {load volatile}
@x = weak global i32 0 ; <i32*> [#uses=2]
diff --git a/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll b/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll
new file mode 100644
index 0000000..d10c61fe
--- /dev/null
+++ b/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll
@@ -0,0 +1,29 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+declare void @bar()
+
+define void @test1() {
+entry:
+ invoke void @bar() to label %cont unwind label %lpad
+cont:
+ ret void
+lpad:
+ %ex = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 cleanup
+ %exc_ptr = extractvalue { i8*, i32 } %ex, 0
+ %filter = extractvalue { i8*, i32 } %ex, 1
+ %exc_ptr2 = insertvalue { i8*, i32 } undef, i8* %exc_ptr, 0
+ %filter2 = insertvalue { i8*, i32 } %exc_ptr2, i32 %filter, 1
+ resume { i8*, i32 } %filter2
+; CHECK: @test1
+; CHECK-NOT: extractvalue
+; CHECK-NOT: insertvalue
+}
+
+declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)
+
+define { i8, i32 } @test2({ i8*, i32 } %x) {
+ %ex = extractvalue { i8*, i32 } %x, 1
+ %ins = insertvalue { i8, i32 } undef, i32 %ex, 1
+ ret { i8, i32 } %ins
+; CHECK: @test2
+}
diff --git a/test/Transforms/InstSimplify/compare.ll b/test/Transforms/InstSimplify/compare.ll
index d2c564f..2cbd641 100644
--- a/test/Transforms/InstSimplify/compare.ll
+++ b/test/Transforms/InstSimplify/compare.ll
@@ -283,17 +283,6 @@ define i1 @srem3(i16 %X, i32 %Y) {
ret i1 %E
}
-; CHECK: @srem4
-; CHECK-NEXT: ret i1 false
-define i1 @srem4(i16 %X, i32 %Y) {
- %A = zext i16 %X to i32
- %B = or i32 2147483648, %A
- %C = sub nsw i32 %A, %B
- %D = srem i32 %C, %Y
- %E = icmp slt i32 %D, 0
- ret i1 %E
-}
-
define i1 @udiv1(i32 %X) {
; CHECK: @udiv1
%A = udiv i32 %X, 1000000
diff --git a/test/Transforms/JumpThreading/no-irreducible-loops.ll b/test/Transforms/JumpThreading/no-irreducible-loops.ll
index 97276b0..7c7fe39 100644
--- a/test/Transforms/JumpThreading/no-irreducible-loops.ll
+++ b/test/Transforms/JumpThreading/no-irreducible-loops.ll
@@ -1,5 +1,5 @@
; RUN: opt < %s -jump-threading -loop-rotate -instcombine -indvars -loop-unroll -simplifycfg -S -verify-dom-info -verify-loop-info > %t
-; RUN: grep {volatile store} %t | count 3
+; RUN: grep {store volatile} %t | count 3
; RUN: not grep {br label} %t
; Jump threading should not prevent this loop from being unrolled.
diff --git a/test/Transforms/LCSSA/invoke-dest.ll b/test/Transforms/LCSSA/invoke-dest.ll
index 4547150..22b3202 100644
--- a/test/Transforms/LCSSA/invoke-dest.ll
+++ b/test/Transforms/LCSSA/invoke-dest.ll
@@ -110,12 +110,18 @@ bb106: ; preds = %invcont105, %bb61
to label %.noexc unwind label %lpad119 ; <i8*> [#uses=1]
lpad: ; preds = %_ZN7cObjectnwEj.exit
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
br label %Unwind
lpad119: ; preds = %bb106, %invcont104, %invcont103, %bb102, %bb49, %bb34, %bb12, %invcont10, %invcont9, %bb8
+ %exn119 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
lpad123: ; preds = %.noexc
+ %exn123 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
%tmp5 = icmp eq i8* %tmp4, null ; <i1> [#uses=1]
br i1 %tmp5, label %Unwind, label %bb.i2
@@ -126,6 +132,8 @@ Unwind: ; preds = %bb.i2, %lpad123, %lpad
unreachable
}
+declare i32 @__gxx_personality_v0(...)
+
declare void @_ZN8EtherBus8tokenizeEPKcRSt6vectorIdSaIdEE(i8* nocapture, i8*, i8*)
declare i8* @_Znaj(i32)
diff --git a/test/Transforms/LICM/2007-05-22-VolatileSink.ll b/test/Transforms/LICM/2007-05-22-VolatileSink.ll
index c12e13b..17383c2 100644
--- a/test/Transforms/LICM/2007-05-22-VolatileSink.ll
+++ b/test/Transforms/LICM/2007-05-22-VolatileSink.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -licm -S | grep {volatile store}
+; RUN: opt < %s -licm -S | grep {store volatile}
; PR1435
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
target triple = "i686-apple-darwin8"
diff --git a/test/Transforms/LICM/2011-04-06-HoistMissedASTUpdate.ll b/test/Transforms/LICM/2011-04-06-HoistMissedASTUpdate.ll
index 5774f58..fd114f4 100644
--- a/test/Transforms/LICM/2011-04-06-HoistMissedASTUpdate.ll
+++ b/test/Transforms/LICM/2011-04-06-HoistMissedASTUpdate.ll
@@ -15,7 +15,7 @@ for.body4.lr.ph:
br label %for.body4
; CHECK: for.body4:
-; CHECK: volatile load i16* @g_39
+; CHECK: load volatile i16* @g_39
for.body4:
%l_612.11 = phi i32* [ undef, %for.body4.lr.ph ], [ %call19, %for.body4 ]
diff --git a/test/Transforms/LICM/atomics.ll b/test/Transforms/LICM/atomics.ll
new file mode 100644
index 0000000..3902152
--- /dev/null
+++ b/test/Transforms/LICM/atomics.ll
@@ -0,0 +1,79 @@
+; RUN: opt < %s -S -basicaa -licm | FileCheck %s
+
+; Check that we can hoist unordered loads
+define i32 @test1(i32* nocapture %y) nounwind uwtable ssp {
+entry:
+ br label %loop
+
+loop:
+ %i = phi i32 [ %inc, %loop ], [ 0, %entry ]
+ %val = load atomic i32* %y unordered, align 4
+ %inc = add nsw i32 %i, 1
+ %exitcond = icmp eq i32 %inc, %val
+ br i1 %exitcond, label %end, label %loop
+
+end:
+ ret i32 %val
+; CHECK: define i32 @test1(
+; CHECK: load atomic
+; CHECK-NEXT: br label %loop
+}
+
+; Check that we don't sink/hoist monotonic loads
+; (Strictly speaking, it's not forbidden, but it's supposed to be possible to
+; use monotonic for spinlock-like constructs.)
+define i32 @test2(i32* nocapture %y) nounwind uwtable ssp {
+entry:
+ br label %loop
+
+loop:
+ %val = load atomic i32* %y monotonic, align 4
+ %exitcond = icmp ne i32 %val, 0
+ br i1 %exitcond, label %end, label %loop
+
+end:
+ ret i32 %val
+; CHECK: define i32 @test2(
+; CHECK: load atomic
+; CHECK-NEXT: %exitcond = icmp ne
+; CHECK-NEXT: br i1 %exitcond, label %end, label %loop
+}
+
+; Check that we hoist unordered around monotonic.
+; (The noalias shouldn't be necessary in theory, but LICM isn't quite that
+; smart yet.)
+define i32 @test3(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp {
+entry:
+ br label %loop
+
+loop:
+ %vala = load atomic i32* %y monotonic, align 4
+ %valb = load atomic i32* %x unordered, align 4
+ %exitcond = icmp ne i32 %vala, %valb
+ br i1 %exitcond, label %end, label %loop
+
+end:
+ ret i32 %vala
+; CHECK: define i32 @test3(
+; CHECK: load atomic i32* %x unordered
+; CHECK-NEXT: br label %loop
+}
+
+; Don't try to "sink" unordered stores yet; it is legal, but the machinery
+; isn't there.
+define i32 @test4(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp {
+entry:
+ br label %loop
+
+loop:
+ %vala = load atomic i32* %y monotonic, align 4
+ store atomic i32 %vala, i32* %x unordered, align 4
+ %exitcond = icmp ne i32 %vala, 0
+ br i1 %exitcond, label %end, label %loop
+
+end:
+ ret i32 %vala
+; CHECK: define i32 @test4(
+; CHECK: load atomic i32* %y monotonic
+; CHECK-NEXT: store atomic
+}
diff --git a/test/Transforms/LICM/scalar-promote-memmodel.ll b/test/Transforms/LICM/scalar-promote-memmodel.ll
new file mode 100644
index 0000000..23d70f5
--- /dev/null
+++ b/test/Transforms/LICM/scalar-promote-memmodel.ll
@@ -0,0 +1,37 @@
+; RUN: opt < %s -basicaa -licm -S | FileCheck %s
+
+; Make sure we don't hoist a conditionally-executed store out of the loop;
+; it would violate the concurrency memory model
+
+@g = common global i32 0, align 4
+
+define void @bar(i32 %n, i32 %b) nounwind uwtable ssp {
+entry:
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc ]
+ %cmp = icmp slt i32 %i.0, %n
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %tobool = icmp eq i32 %b, 0
+ br i1 %tobool, label %for.inc, label %if.then
+
+if.then: ; preds = %for.body
+ %tmp3 = load i32* @g, align 4
+ %inc = add nsw i32 %tmp3, 1
+ store i32 %inc, i32* @g, align 4
+ br label %for.inc
+
+; CHECK: load i32*
+; CHECK-NEXT: add
+; CHECK-NEXT: store i32
+
+for.inc: ; preds = %for.body, %if.then
+ %inc5 = add nsw i32 %i.0, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
diff --git a/test/Transforms/LICM/scalar_promote.ll b/test/Transforms/LICM/scalar_promote.ll
index d8acdc1..9aefc4f8 100644
--- a/test/Transforms/LICM/scalar_promote.ll
+++ b/test/Transforms/LICM/scalar_promote.ll
@@ -65,7 +65,7 @@ Loop:
br i1 true, label %Out, label %Loop
; CHECK: Loop:
-; CHECK-NEXT: volatile load
+; CHECK-NEXT: load volatile
Out: ; preds = %Loop
ret void
diff --git a/test/Transforms/LoopDeletion/2008-05-06-Phi.ll b/test/Transforms/LoopDeletion/2008-05-06-Phi.ll
index 4fc6378..ff6a30d 100644
--- a/test/Transforms/LoopDeletion/2008-05-06-Phi.ll
+++ b/test/Transforms/LoopDeletion/2008-05-06-Phi.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -inline -tailduplicate -instcombine -jump-threading -licm -loop-unswitch -instcombine -indvars -loop-deletion -gvn -simplifycfg -verify -disable-output
+; RUN: opt < %s -inline -instcombine -jump-threading -licm -loop-unswitch -instcombine -indvars -loop-deletion -gvn -simplifycfg -verify -disable-output
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin9"
diff --git a/test/Transforms/LoopIdiom/basic.ll b/test/Transforms/LoopIdiom/basic.ll
index 9695418..46ab7e5 100644
--- a/test/Transforms/LoopIdiom/basic.ll
+++ b/test/Transforms/LoopIdiom/basic.ll
@@ -62,8 +62,8 @@ for.end: ; preds = %for.body, %entry
ret void
; CHECK: @test2
; CHECK: br i1 %cmp10,
-; CHECK: %tmp = mul i64 %Size, 4
-; CHECK: call void @llvm.memset.p0i8.i64(i8* %Base1, i8 1, i64 %tmp, i32 4, i1 false)
+; CHECK: %0 = mul i64 %Size, 4
+; CHECK: call void @llvm.memset.p0i8.i64(i8* %Base1, i8 1, i64 %0, i32 4, i1 false)
; CHECK-NOT: store
}
diff --git a/test/Transforms/LoopSimplify/2003-08-15-PreheadersFail.ll b/test/Transforms/LoopSimplify/2003-08-15-PreheadersFail.ll
index 11be694..73f0813 100644
--- a/test/Transforms/LoopSimplify/2003-08-15-PreheadersFail.ll
+++ b/test/Transforms/LoopSimplify/2003-08-15-PreheadersFail.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -tailduplicate -instcombine -simplifycfg -licm -disable-output
+; RUN: opt < %s -instcombine -simplifycfg -licm -disable-output
target datalayout = "e-p:32:32"
@yy_base = external global [787 x i16] ; <[787 x i16]*> [#uses=1]
@yy_state_ptr = external global i32* ; <i32**> [#uses=3]
diff --git a/test/Transforms/LoopSimplify/2007-10-28-InvokeCrash.ll b/test/Transforms/LoopSimplify/2007-10-28-InvokeCrash.ll
index e7d0f84..e91d141 100644
--- a/test/Transforms/LoopSimplify/2007-10-28-InvokeCrash.ll
+++ b/test/Transforms/LoopSimplify/2007-10-28-InvokeCrash.ll
@@ -1,892 +1,29 @@
-; RUN: opt < %s -loop-simplify -disable-output
+; RUN: llvm-as < %s | opt -loop-simplify -disable-output
; PR1752
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-s0:0:64-f80:32:32"
target triple = "i686-pc-mingw32"
- %struct.BigInt = type { %"struct.std::vector<ulong,std::allocator<ulong> >" }
- %struct.Fibonacci = type { %"struct.std::vector<BigInt,std::allocator<BigInt> >" }
- %struct.__false_type = type <{ i8 }>
- %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >" = type { %struct.BigInt* }
- %"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >" = type { %"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >::_Vector_impl" }
- %"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >::_Vector_impl" = type { %struct.BigInt*, %struct.BigInt*, %struct.BigInt* }
- %"struct.std::_Vector_base<ulong,std::allocator<ulong> >" = type { %"struct.std::_Vector_base<ulong,std::allocator<ulong> >::_Vector_impl" }
- %"struct.std::_Vector_base<ulong,std::allocator<ulong> >::_Vector_impl" = type { i32*, i32*, i32* }
- %"struct.std::basic_ios<char,std::char_traits<char> >" = type { %"struct.std::ios_base", %"struct.std::basic_ostream<char,std::char_traits<char> >"*, i8, i8, %"struct.std::basic_streambuf<char,std::char_traits<char> >"*, %"struct.std::ctype<char>"*, %"struct.std::num_get<char,std::istreambuf_iterator<char, std::char_traits<char> > >"*, %"struct.std::num_get<char,std::istreambuf_iterator<char, std::char_traits<char> > >"* }
- %"struct.std::basic_ostream<char,std::char_traits<char> >" = type { i32 (...)**, %"struct.std::basic_ios<char,std::char_traits<char> >" }
- %"struct.std::basic_streambuf<char,std::char_traits<char> >" = type { i32 (...)**, i8*, i8*, i8*, i8*, i8*, i8*, %"struct.std::locale" }
- %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >" = type { %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider" }
- %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider" = type { i8* }
- %"struct.std::basic_stringbuf<char,std::char_traits<char>,std::allocator<char> >" = type { %"struct.std::basic_streambuf<char,std::char_traits<char> >", i32, %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >" }
- %"struct.std::ctype<char>" = type { %"struct.std::locale::facet", i32*, i8, i32*, i32*, i16*, i8, [256 x i8], [256 x i8], i8 }
- %"struct.std::ios_base" = type { i32 (...)**, i32, i32, i32, i32, i32, %"struct.std::ios_base::_Callback_list"*, %"struct.std::ios_base::_Words", [8 x %"struct.std::ios_base::_Words"], i32, %"struct.std::ios_base::_Words"*, %"struct.std::locale" }
- %"struct.std::ios_base::_Callback_list" = type { %"struct.std::ios_base::_Callback_list"*, void (i32, %"struct.std::ios_base"*, i32)*, i32, i32 }
- %"struct.std::ios_base::_Words" = type { i8*, i32 }
- %"struct.std::locale" = type { %"struct.std::locale::_Impl"* }
- %"struct.std::locale::_Impl" = type { i32, %"struct.std::locale::facet"**, i32, %"struct.std::locale::facet"**, i8** }
- %"struct.std::locale::facet" = type { i32 (...)**, i32 }
- %"struct.std::num_get<char,std::istreambuf_iterator<char, std::char_traits<char> > >" = type { %"struct.std::locale::facet" }
- %"struct.std::ostringstream" = type { [4 x i8], %"struct.std::basic_stringbuf<char,std::char_traits<char>,std::allocator<char> >", %"struct.std::basic_ios<char,std::char_traits<char> >" }
- %"struct.std::vector<BigInt,std::allocator<BigInt> >" = type { %"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >" }
- %"struct.std::vector<ulong,std::allocator<ulong> >" = type { %"struct.std::_Vector_base<ulong,std::allocator<ulong> >" }
-@.str13 = external constant [6 x i8] ; <[6 x i8]*> [#uses=1]
-@.str14 = external constant [5 x i8] ; <[5 x i8]*> [#uses=1]
-@.str15 = external constant [2 x i8] ; <[2 x i8]*> [#uses=1]
-@_ZSt4cout = external global %"struct.std::basic_ostream<char,std::char_traits<char> >" ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=1]
-declare void @_ZN9Fibonacci10get_numberEj(%struct.BigInt* sret , %struct.Fibonacci*, i32)
-
-declare %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"struct.std::basic_ostream<char,std::char_traits<char> >"*, i8*)
-
-declare void @_ZNSsD1Ev(%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"*)
-
-declare %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZNSolsEm(%"struct.std::basic_ostream<char,std::char_traits<char> >"*, i32)
-
-declare void @_ZNKSt19basic_ostringstreamIcSt11char_traitsIcESaIcEE3strEv(%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* sret , %"struct.std::ostringstream"*)
-
-declare %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKSbIS4_S5_T1_E(%"struct.std::basic_ostream<char,std::char_traits<char> >"*, %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"*)
-
-declare void @_ZNSt19basic_ostringstreamIcSt11char_traitsIcESaIcEED1Ev(%"struct.std::ostringstream"*)
-
-declare %"struct.std::basic_ostream<char,std::char_traits<char> >"* @___ZlsRSoRK6BigInt___ZN9__gnu_cxx13new_allocatorI6BigIntE10deallocateEPS1_j(i32, %"struct.std::basic_ostream<char,std::char_traits<char> >"*, %struct.BigInt*, %struct.__false_type*, i32)
-
-declare void @___ZNSt12_Vector_baseI6BigIntSaIS0_EE13_M_deallocateEPS0_j___ZNSt12_Vector_baseI6BigIntSaIS0_EED2Ev___ZNSt6vectorI6BigIntSaIS0_EEC1ERKS1_(%"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >"*, i32, %struct.BigInt*, i32, %"struct.std::vector<BigInt,std::allocator<BigInt> >"*, %struct.__false_type*)
-
-declare i32 @___ZN9__gnu_cxxmiIPK6BigIntS3_St6vectorIS1_SaIS1_EEEENS_17__normal_iteratorIT_T1_E15difference_typeERKSA_RKNS7_IT0_S9_EE___ZNKSt6vectorI6BigIntSaIS0_EE4sizeEv___ZNK9Fibonacci16show_all_numbersEv___ZNKSt6vectorI6BigIntSaIS0_EE8capacityEv(%"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"*, %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"*, %"struct.std::vector<BigInt,std::allocator<BigInt> >"*, i32, %struct.Fibonacci*)
-
-declare %struct.BigInt* @___ZNSt6vectorI6BigIntSaIS0_EEixEj___ZNSt6vectorI6BigIntSaIS0_EE3endEv(%"struct.std::vector<BigInt,std::allocator<BigInt> >"*, i32, i32)
-
-declare %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* @___ZN9__gnu_cxx17__normal_iteratorIP6BigIntSt6vectorIS1_SaIS1_EEEppEv___ZNSt6vectorImSaImEED1Ev___ZN6BigIntD1Ev___ZN9__gnu_cxx13new_allocatorI6BigIntE7destroyEPS1____ZSt8_DestroyIP6BigIntSaIS0_EEvT_S3_T0_(i32, %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"*, %"struct.std::vector<ulong,std::allocator<ulong> >"*, %struct.BigInt*, %struct.__false_type*, %struct.BigInt*, %struct.__false_type* noalias )
-
-declare void @___ZNSt6vectorI6BigIntSaIS0_EED1Ev___ZN9FibonacciD1Ev___ZNSt6vectorImSaImEEC1ERKS0_(i32, %"struct.std::vector<BigInt,std::allocator<BigInt> >"*, %struct.Fibonacci*, %"struct.std::vector<ulong,std::allocator<ulong> >"*, %struct.__false_type*)
-
-define void @___ZN9FibonacciC1Ej___ZN9Fibonacci11show_numberEm(%struct.Fibonacci* %this_this, i32 %functionID, i32 %n_i_n_i) {
+define void @func() {
bb_init:
br label %bb_main
-bb_main: ; preds = %meshBB349, %meshBB348, %meshBB347, %meshBB346, %meshBB345.unwinddest, %meshBB345, %meshBB344, %meshBB343, %meshBB342, %meshBB341, %meshBB340.normaldest, %meshBB340, %meshBB339, %invcont17.normaldest.normaldest, %invcont17.normaldest, %meshBB338.unwinddest, %meshBB338, %meshBB337.unwinddest, %meshBB337, %meshBB336.unwinddest, %meshBB336, %meshBB335, %meshBB334, %meshBB333, %meshBB332, %meshBB331, %meshBB330.normaldest, %meshBB330, %meshBB329.normaldest, %meshBB329, %meshBB328, %meshBB327, %meshBB326, %meshBB325.unwinddest, %meshBB325, %meshBB324, %meshBB323.normaldest, %meshBB323, %meshBB322.unwinddest, %meshBB322, %meshBB321, %meshBB320.unwinddest, %meshBB320, %meshBB319.unwinddest, %meshBB319, %meshBB318.unwinddest, %meshBB318, %meshBB317, %meshBB37.fragment, %meshBB37.unwinddest, %meshBB37, %meshBB36.fragment, %meshBB36, %meshBB35.fragment, %meshBB35, %meshBB34.fragment, %meshBB34, %meshBB33.fragment, %meshBB33, %meshBB32.fragment, %meshBB32, %meshBB31.fragment, %meshBB31, %meshBB30.fragment, %meshBB30.normaldest, %meshBB30, %meshBB29.fragment, %meshBB29.unwinddest, %meshBB29, %meshBB28.fragment, %meshBB28.unwinddest, %meshBB28, %meshBB27.fragment, %meshBB27, %meshBB26.fragment, %meshBB26.normaldest, %meshBB26, %meshBB25.fragment, %meshBB25, %meshBB24.fragment, %meshBB24.unwinddest, %meshBB24, %meshBB23.fragment, %meshBB23.normaldest, %meshBB23, %entry1.fragment.normaldest.normaldest, %entry1.fragment.normaldest, %meshBB22.fragment, %meshBB22.unwinddest, %meshBB22, %meshBB.fragment, %meshBB.unwinddest, %meshBB, %Unwind20, %unwind78.Unwind_crit_edge, %unwind78.fragment.fragment, %unwind78.fragment, %unwind78.fragment316, %unwind78, %invcont70, %unwind66.Unwind_crit_edge, %unwind66.fragment.fragment, %unwind66.fragment, %unwind66.fragment315, %unwind66, %unwind53.nofilter_crit_edge, %unwind53.fragment.fragment, %unwind53.fragment, %unwind53.fragment314, %unwind53, %nofilter.Unwind_crit_edge.normaldest, %nofilter.Unwind_crit_edge, %nofilter, %unwind43.nofilter_crit_edge, %unwind43.fragment.fragment, %unwind43.fragment, %unwind43.fragment313, %unwind43, %invcont41.normaldest, %invcont41, %unwind37.nofilter_crit_edge, %unwind37, %invcont36, %invcont33.unwind_crit_edge.unwinddest, %invcont33.unwind_crit_edge, %invcont30.unwind_crit_edge.unwinddest, %invcont30.unwind_crit_edge, %invcont30.normaldest, %invcont30, %invcont28.unwind_crit_edge, %invcont28.normaldest, %invcont28, %invcont25.unwind_crit_edge.unwinddest, %invcont25.unwind_crit_edge, %invcont25, %invcont22.unwind_crit_edge, %invcont22, %invcont17.unwind_crit_edge, %invcont17, %cond_next.unwind_crit_edge, %cond_next, %invcont12.cond_next_crit_edge, %invcont12.unwind_crit_edge, %invcont12, %cond_true.unwind_crit_edge.unwinddest, %cond_true.unwind_crit_edge, %invcont.cond_next_crit_edge, %invcont16.fragment, %invcont16, %unwind11.fragment, %unwind11, %entry.unwind_crit_edge, %entry1.fragment, %entry1.fragment312, %entry1, %Unwind, %unwind20.Unwind_crit_edge, %unwind20.fragment.fragment, %unwind20.fragment, %unwind20.fragment311, %unwind20, %invcont15, %invcont14.unwind10_crit_edge, %invcont14, %unwind10.Unwind_crit_edge, %unwind10.fragment, %unwind10.fragment310, %unwind10, %invcont.unwind10_crit_edge, %invcont, %unwind.fragment, %unwind, %entry.fragment, %entry.fragment309, %entry, %NewDefault, %LeafBlock, %LeafBlock914, %NodeBlock, %comb_entry.fragment, %old_entry, %bb_init
- switch i32 0, label %old_entry [
- i32 2739, label %invcont28.fragment
- i32 2688, label %meshBB28.fragment
- i32 1318, label %meshBB32.fragment
- i32 2964, label %unwind53.fragment.fragment
- i32 824, label %unwind78.fragment.fragment
- i32 1983, label %meshBB33.fragment
- i32 2582, label %invcont30.fragment
- i32 2235, label %meshBB36.fragment
- i32 1275, label %meshBB343
- i32 2719, label %invcont.fragment
- i32 1500, label %entry1.fragment.fragment
- i32 815, label %unwind11.fragment
- i32 1051, label %entry
- i32 2342, label %unwind
- i32 1814, label %invcont
- i32 315, label %invcont.unwind10_crit_edge
- i32 2422, label %unwind10
- i32 2663, label %unwind10.Unwind_crit_edge
- i32 266, label %invcont14
- i32 367, label %invcont14.unwind10_crit_edge
- i32 2242, label %invcont15
- i32 452, label %unwind20
- i32 419, label %invcont.cond_next_crit_edge
- i32 181, label %cond_true
- i32 2089, label %unwind20.Unwind_crit_edge
- i32 633, label %filter
- i32 455, label %Unwind
- i32 2016, label %entry1
- i32 263, label %invcont33.unwind_crit_edge
- i32 2498, label %invcont36
- i32 2992, label %unwind37
- i32 616, label %entry.unwind_crit_edge
- i32 622, label %unwind11
- i32 875, label %invcont16
- i32 766, label %unwind53.nofilter_crit_edge
- i32 668, label %filter62
- i32 2138, label %unwind66
- i32 713, label %unwind66.Unwind_crit_edge
- i32 1422, label %invcont70
- i32 1976, label %cond_true.unwind_crit_edge
- i32 1263, label %invcont12
- i32 2453, label %invcont12.unwind_crit_edge
- i32 2876, label %invcont12.cond_next_crit_edge
- i32 2271, label %cond_next
- i32 2938, label %cond_next.unwind_crit_edge
- i32 1082, label %invcont17
- i32 531, label %invcont17.unwind_crit_edge
- i32 111, label %invcont22
- i32 1935, label %invcont22.unwind_crit_edge
- i32 2004, label %invcont25
- i32 1725, label %invcont25.unwind_crit_edge
- i32 1701, label %invcont28
- i32 957, label %invcont28.unwind_crit_edge
- i32 165, label %invcont30
- i32 899, label %invcont30.unwind_crit_edge
- i32 1092, label %invcont33
- i32 2869, label %unwind37.nofilter_crit_edge
- i32 203, label %invcont41
- i32 693, label %unwind43
- i32 2895, label %unwind43.nofilter_crit_edge
- i32 1174, label %invcont47
- i32 1153, label %filter19
- i32 2304, label %nofilter
- i32 848, label %nofilter.Unwind_crit_edge
- i32 1207, label %unwind53
- i32 2848, label %filter75
- i32 59, label %unwind78
- i32 1213, label %unwind78.Unwind_crit_edge
- i32 2199, label %filter87
- i32 1268, label %Unwind20
- i32 743, label %old_entry
- i32 1276, label %meshBB319
- i32 1619, label %meshBB320
- i32 2047, label %meshBB331
- i32 2828, label %meshBB23.fragment
- i32 2530, label %meshBB332
- i32 1389, label %meshBB318
- i32 1450, label %meshBB317
- i32 1416, label %meshBB31.fragment
- i32 82, label %meshBB322
- i32 853, label %unwind78.fragment316
- i32 107, label %meshBB24.fragment
- i32 1200, label %meshBB37.fragment
- i32 605, label %unwind53.fragment314
- i32 209, label %meshBB29.fragment
- i32 1513, label %meshBB27.fragment
- i32 1542, label %meshBB35.fragment
- i32 1873, label %meshBB348
- i32 472, label %meshBB325
- i32 2615, label %meshBB22.fragment
- i32 359, label %meshBB.fragment
- i32 2467, label %Unwind20.fragment
- i32 1671, label %unwind66.fragment.fragment
- i32 1006, label %meshBB25.fragment
- i32 1243, label %meshBB333
- i32 2795, label %unwind43.fragment313
- i32 1591, label %meshBB335
- i32 773, label %meshBB341
- i32 2440, label %cond_next.fragment
- i32 487, label %meshBB326
- i32 394, label %meshBB324
- i32 14, label %invcont16.fragment
- i32 574, label %entry1.fragment312
- i32 1453, label %meshBB35
- i32 345, label %entry1.fragment
- i32 2951, label %unwind20.fragment
- i32 1960, label %meshBB31
- i32 2163, label %meshBB32
- i32 1978, label %Unwind.fragment
- i32 1559, label %unwind20.fragment.fragment
- i32 950, label %unwind10.fragment
- i32 1724, label %unwind53.fragment
- i32 514, label %meshBB36
- i32 1928, label %unwind10.fragment.fragment
- i32 1266, label %meshBB26
- i32 3148, label %unwind20.fragment311
- i32 1581, label %unwind43.fragment
- i32 1829, label %meshBB34
- i32 1472, label %meshBB28
- i32 2657, label %unwind66.fragment
- i32 2169, label %meshBB22
- i32 2619, label %meshBB
- i32 1397, label %entry.fragment
- i32 231, label %invcont41.fragment
- i32 2557, label %meshBB338
- i32 2387, label %meshBB30.fragment
- i32 2927, label %meshBB340
- i32 2331, label %meshBB321
- i32 47, label %meshBB328
- i32 1753, label %meshBB342
- i32 2074, label %meshBB323
- i32 2128, label %meshBB334
- i32 2396, label %meshBB337
- i32 1811, label %meshBB29
- i32 1113, label %meshBB27
- i32 2232, label %unwind10.fragment310
- i32 804, label %meshBB24
- i32 3099, label %meshBB30
- i32 564, label %meshBB33
- i32 1359, label %unwind.fragment
- i32 1906, label %entry.fragment309
- i32 2644, label %entry.fragment.fragment
- i32 134, label %entry1.fragment.normaldest
- i32 2767, label %comb_entry.fragment
- i32 2577, label %meshBB25
- i32 3128, label %meshBB37
- i32 2360, label %meshBB23
- i32 286, label %unwind78.fragment
- i32 976, label %meshBB346
- i32 2412, label %meshBB339
- i32 876, label %meshBB345
- i32 3078, label %meshBB329
- i32 1297, label %meshBB347
- i32 3051, label %meshBB336
- i32 1342, label %meshBB344
- i32 728, label %meshBB330
- i32 1778, label %meshBB349
- i32 2784, label %meshBB327
- i32 1854, label %meshBB26.fragment
- i32 1025, label %meshBB34.fragment
- i32 2139, label %unwind43.fragment.fragment
- i32 2217, label %nofilter.fragment
- i32 665, label %invcont12.fragment
- i32 316, label %invcont22.fragment
- i32 1467, label %unwind66.fragment315
- i32 3018, label %unwind37.fragment
- i32 1123, label %invcont17.normaldest
- i32 2104, label %NewDefault
- i32 1639, label %LeafBlock
- i32 925, label %LeafBlock914
- i32 2880, label %NodeBlock
- ]
-
-old_entry: ; preds = %bb_main, %bb_main
- br label %bb_main
-
-comb_entry.fragment: ; preds = %bb_main
- br label %bb_main
-
-NodeBlock: ; preds = %bb_main
- br label %bb_main
-
-LeafBlock914: ; preds = %bb_main
- br label %bb_main
-
-LeafBlock: ; preds = %bb_main
- br label %bb_main
-
-NewDefault: ; preds = %bb_main
- br label %bb_main
-
-entry: ; preds = %bb_main
- br label %bb_main
-
-entry.fragment309: ; preds = %bb_main
- br label %bb_main
-
-entry.fragment: ; preds = %bb_main
- br label %bb_main
-
-entry.fragment.fragment: ; preds = %bb_main
- invoke void @___ZNSt12_Vector_baseI6BigIntSaIS0_EE13_M_deallocateEPS0_j___ZNSt12_Vector_baseI6BigIntSaIS0_EED2Ev___ZNSt6vectorI6BigIntSaIS0_EEC1ERKS1_( %"struct.std::_Vector_base<BigInt,std::allocator<BigInt> >"* null, i32 28, %struct.BigInt* null, i32 0, %"struct.std::vector<BigInt,std::allocator<BigInt> >"* null, %struct.__false_type* null )
- to label %meshBB340 unwind label %meshBB325
-
-unwind: ; preds = %bb_main
- br label %bb_main
-
-unwind.fragment: ; preds = %bb_main
- br label %bb_main
-
-invcont: ; preds = %bb_main
- br label %bb_main
-
-invcont.fragment: ; preds = %bb_main
- invoke void @_ZN9Fibonacci10get_numberEj( %struct.BigInt* sret null , %struct.Fibonacci* %this_this, i32 %n_i_n_i )
- to label %invcont14 unwind label %meshBB37
-
-invcont.unwind10_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-unwind10: ; preds = %bb_main
- br label %bb_main
-
-unwind10.fragment310: ; preds = %bb_main
- br label %bb_main
-
-unwind10.fragment: ; preds = %bb_main
- br label %bb_main
-
-unwind10.fragment.fragment: ; preds = %bb_main
- invoke void @___ZNSt6vectorI6BigIntSaIS0_EED1Ev___ZN9FibonacciD1Ev___ZNSt6vectorImSaImEEC1ERKS0_( i32 57, %"struct.std::vector<BigInt,std::allocator<BigInt> >"* null, %struct.Fibonacci* null, %"struct.std::vector<ulong,std::allocator<ulong> >"* null, %struct.__false_type* null )
- to label %meshBB329 unwind label %meshBB24
-
-unwind10.Unwind_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-invcont14: ; preds = %invcont.fragment, %bb_main
- br label %bb_main
-
-invcont14.normaldest: ; No predecessors!
- invoke %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* @___ZN9__gnu_cxx17__normal_iteratorIP6BigIntSt6vectorIS1_SaIS1_EEEppEv___ZNSt6vectorImSaImEED1Ev___ZN6BigIntD1Ev___ZN9__gnu_cxx13new_allocatorI6BigIntE7destroyEPS1____ZSt8_DestroyIP6BigIntSaIS0_EEvT_S3_T0_( i32 14, %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* null, %"struct.std::vector<ulong,std::allocator<ulong> >"* null, %struct.BigInt* null, %struct.__false_type* null, %struct.BigInt* null, %struct.__false_type* noalias null )
- to label %invcont15 unwind label %meshBB345 ; <%"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"*>:0 [#uses=0]
-
-invcont14.unwind10_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-invcont15: ; preds = %invcont14.normaldest, %bb_main
- br label %bb_main
-
-invcont15.normaldest: ; No predecessors!
- br label %UnifiedReturnBlock
-
-unwind20: ; preds = %bb_main
- br label %bb_main
-
-unwind20.fragment311: ; preds = %bb_main
- br label %bb_main
-
-unwind20.fragment: ; preds = %bb_main
- br label %bb_main
-
-unwind20.fragment.fragment: ; preds = %bb_main
- br label %bb_main
-
-unwind20.Unwind_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-filter: ; preds = %bb_main
- br label %UnifiedUnreachableBlock
-
-Unwind: ; preds = %bb_main
- br label %bb_main
-
-Unwind.fragment: ; preds = %bb_main
- br label %UnifiedUnreachableBlock
-
-entry1: ; preds = %bb_main
- br label %bb_main
-
-entry1.fragment312: ; preds = %bb_main
- br label %bb_main
-
-entry1.fragment: ; preds = %bb_main
- br label %bb_main
-
-entry1.fragment.fragment: ; preds = %bb_main
- %tmp52 = invoke i32 @___ZN9__gnu_cxxmiIPK6BigIntS3_St6vectorIS1_SaIS1_EEEENS_17__normal_iteratorIT_T1_E15difference_typeERKSA_RKNS7_IT0_S9_EE___ZNKSt6vectorI6BigIntSaIS0_EE4sizeEv___ZNK9Fibonacci16show_all_numbersEv___ZNKSt6vectorI6BigIntSaIS0_EE8capacityEv( %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* null, %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* null, %"struct.std::vector<BigInt,std::allocator<BigInt> >"* null, i32 16, %struct.Fibonacci* null )
- to label %entry1.fragment.normaldest unwind label %meshBB320 ; <i32> [#uses=0]
-
-entry.unwind_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-unwind11: ; preds = %bb_main
- br label %bb_main
-
-unwind11.fragment: ; preds = %bb_main
- br label %bb_main
-
-invcont16: ; preds = %bb_main
- br label %bb_main
-
-invcont16.fragment: ; preds = %bb_main
- br label %bb_main
-
-invcont.cond_next_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-cond_true: ; preds = %bb_main
- invoke void @_ZN9Fibonacci10get_numberEj( %struct.BigInt* sret null , %struct.Fibonacci* %this_this, i32 %n_i_n_i )
- to label %meshBB323 unwind label %cond_true.unwind_crit_edge
-
-cond_true.unwind_crit_edge: ; preds = %cond_true, %bb_main
- br label %bb_main
-
-cond_true.unwind_crit_edge.unwinddest: ; No predecessors!
- br label %bb_main
-
-invcont12: ; preds = %bb_main
- br label %bb_main
-
-invcont12.fragment: ; preds = %bb_main
- invoke %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* @___ZN9__gnu_cxx17__normal_iteratorIP6BigIntSt6vectorIS1_SaIS1_EEEppEv___ZNSt6vectorImSaImEED1Ev___ZN6BigIntD1Ev___ZN9__gnu_cxx13new_allocatorI6BigIntE7destroyEPS1____ZSt8_DestroyIP6BigIntSaIS0_EEvT_S3_T0_( i32 14, %"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"* null, %"struct.std::vector<ulong,std::allocator<ulong> >"* null, %struct.BigInt* null, %struct.__false_type* null, %struct.BigInt* null, %struct.__false_type* noalias null )
- to label %meshBB30 unwind label %meshBB337 ; <%"struct.__gnu_cxx::__normal_iterator<BigInt*,std::vector<BigInt, std::allocator<BigInt> > >"*>:1 [#uses=0]
-
-invcont12.unwind_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-invcont12.cond_next_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-cond_next: ; preds = %bb_main
- br label %bb_main
-
-cond_next.fragment: ; preds = %bb_main
- %tmp183 = invoke %struct.BigInt* @___ZNSt6vectorI6BigIntSaIS0_EEixEj___ZNSt6vectorI6BigIntSaIS0_EE3endEv( %"struct.std::vector<BigInt,std::allocator<BigInt> >"* null, i32 %n_i_n_i, i32 29 )
- to label %invcont17 unwind label %meshBB336 ; <%struct.BigInt*> [#uses=0]
-
-cond_next.unwind_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-invcont17: ; preds = %cond_next.fragment, %bb_main
- br label %bb_main
+bb_main:
+ br label %invcont17.normaldest
invcont17.normaldest917: ; No predecessors!
- %tmp23 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc( %"struct.std::basic_ostream<char,std::char_traits<char> >"* null, i8* getelementptr ([6 x i8]* @.str13, i32 0, i32 0) )
- to label %invcont17.normaldest unwind label %meshBB318 ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=1]
-
-invcont17.unwind_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-invcont22: ; preds = %bb_main
- br label %bb_main
-
-invcont22.fragment: ; preds = %bb_main
- %tmp26 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZNSolsEm( %"struct.std::basic_ostream<char,std::char_traits<char> >"* undef, i32 %n_i_n_i )
- to label %invcont25 unwind label %meshBB319 ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=1]
-
-invcont22.unwind_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-invcont25: ; preds = %invcont22.fragment, %bb_main
- br label %bb_main
-
-invcont25.normaldest: ; No predecessors!
- %tmp2918 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc( %"struct.std::basic_ostream<char,std::char_traits<char> >"* %tmp26, i8* getelementptr ([5 x i8]* @.str14, i32 0, i32 0) )
- to label %invcont28 unwind label %invcont25.unwind_crit_edge ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=0]
-
-invcont25.unwind_crit_edge: ; preds = %invcont25.normaldest, %bb_main
- br label %bb_main
-
-invcont25.unwind_crit_edge.unwinddest: ; No predecessors!
- br label %bb_main
-
-invcont28: ; preds = %invcont25.normaldest, %bb_main
- br label %bb_main
-
-invcont28.normaldest: ; No predecessors!
- br label %bb_main
-
-invcont28.fragment: ; preds = %bb_main
- %tmp311 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @___ZlsRSoRK6BigInt___ZN9__gnu_cxx13new_allocatorI6BigIntE10deallocateEPS1_j( i32 32, %"struct.std::basic_ostream<char,std::char_traits<char> >"* undef, %struct.BigInt* undef, %struct.__false_type* null, i32 0 )
- to label %invcont30 unwind label %meshBB322 ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=0]
-
-invcont28.unwind_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-invcont30: ; preds = %invcont28.fragment, %bb_main
- br label %bb_main
-
-invcont30.normaldest: ; No predecessors!
- br label %bb_main
-
-invcont30.fragment: ; preds = %bb_main
- %tmp34 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc( %"struct.std::basic_ostream<char,std::char_traits<char> >"* undef, i8* getelementptr ([2 x i8]* @.str15, i32 0, i32 0) )
- to label %meshBB26 unwind label %invcont30.unwind_crit_edge ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=0]
-
-invcont30.unwind_crit_edge: ; preds = %invcont30.fragment, %bb_main
- br label %bb_main
-
-invcont30.unwind_crit_edge.unwinddest: ; No predecessors!
- br label %bb_main
-
-invcont33: ; preds = %bb_main
- invoke void @_ZNKSt19basic_ostringstreamIcSt11char_traitsIcESaIcEE3strEv( %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* sret null , %"struct.std::ostringstream"* null )
- to label %invcont36 unwind label %invcont33.unwind_crit_edge
-
-invcont33.unwind_crit_edge: ; preds = %invcont33, %bb_main
- br label %bb_main
-
-invcont33.unwind_crit_edge.unwinddest: ; No predecessors!
- br label %bb_main
-
-invcont36: ; preds = %invcont33, %bb_main
- br label %bb_main
-
-invcont36.normaldest: ; No predecessors!
- %tmp42 = invoke %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKSbIS4_S5_T1_E( %"struct.std::basic_ostream<char,std::char_traits<char> >"* @_ZSt4cout, %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* null )
- to label %invcont41 unwind label %meshBB338 ; <%"struct.std::basic_ostream<char,std::char_traits<char> >"*> [#uses=0]
-
-unwind37: ; preds = %bb_main
- br label %bb_main
-
-unwind37.fragment: ; preds = %bb_main
- invoke void @_ZNSsD1Ev( %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* null )
- to label %meshBB330 unwind label %meshBB22
-
-unwind37.nofilter_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-invcont41: ; preds = %invcont36.normaldest, %bb_main
- br label %bb_main
-
-invcont41.normaldest: ; No predecessors!
- br label %bb_main
-
-invcont41.fragment: ; preds = %bb_main
- invoke void @_ZNSsD1Ev( %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* null )
- to label %meshBB23 unwind label %meshBB29
-
-unwind43: ; preds = %bb_main
- br label %bb_main
-
-unwind43.fragment313: ; preds = %bb_main
- br label %bb_main
-
-unwind43.fragment: ; preds = %bb_main
- br label %bb_main
-
-unwind43.fragment.fragment: ; preds = %bb_main
- br label %bb_main
-
-unwind43.nofilter_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-invcont47: ; preds = %bb_main
- invoke void @_ZNSt19basic_ostringstreamIcSt11char_traitsIcESaIcEED1Ev( %"struct.std::ostringstream"* null )
- to label %invcont70 unwind label %meshBB28
-
-filter19: ; preds = %bb_main
- br label %UnifiedUnreachableBlock
-
-nofilter: ; preds = %bb_main
- br label %bb_main
-
-nofilter.fragment: ; preds = %bb_main
- invoke void @_ZNSt19basic_ostringstreamIcSt11char_traitsIcESaIcEED1Ev( %"struct.std::ostringstream"* null )
- to label %nofilter.Unwind_crit_edge unwind label %meshBB
-
-nofilter.Unwind_crit_edge: ; preds = %nofilter.fragment, %bb_main
- br label %bb_main
-
-nofilter.Unwind_crit_edge.normaldest: ; No predecessors!
- br label %bb_main
-
-unwind53: ; preds = %bb_main
- br label %bb_main
-
-unwind53.fragment314: ; preds = %bb_main
- br label %bb_main
-
-unwind53.fragment: ; preds = %bb_main
- br label %bb_main
-
-unwind53.fragment.fragment: ; preds = %bb_main
- br label %bb_main
-
-unwind53.nofilter_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-filter62: ; preds = %bb_main
- br label %UnifiedUnreachableBlock
-
-unwind66: ; preds = %bb_main
- br label %bb_main
-
-unwind66.fragment315: ; preds = %bb_main
- br label %bb_main
-
-unwind66.fragment: ; preds = %bb_main
- br label %bb_main
-
-unwind66.fragment.fragment: ; preds = %bb_main
- br label %bb_main
-
-unwind66.Unwind_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-invcont70: ; preds = %invcont47, %bb_main
- br label %bb_main
-
-invcont70.normaldest: ; No predecessors!
- br label %UnifiedReturnBlock
-
-filter75: ; preds = %bb_main
- br label %UnifiedUnreachableBlock
-
-unwind78: ; preds = %bb_main
- br label %bb_main
-
-unwind78.fragment316: ; preds = %bb_main
- br label %bb_main
-
-unwind78.fragment: ; preds = %bb_main
- br label %bb_main
-
-unwind78.fragment.fragment: ; preds = %bb_main
- br label %bb_main
-
-unwind78.Unwind_crit_edge: ; preds = %bb_main
- br label %bb_main
-
-filter87: ; preds = %bb_main
- br label %UnifiedUnreachableBlock
-
-Unwind20: ; preds = %bb_main
- br label %bb_main
-
-Unwind20.fragment: ; preds = %bb_main
- br label %UnifiedUnreachableBlock
-
-meshBB: ; preds = %nofilter.fragment, %bb_main
- br label %bb_main
-
-meshBB.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB22: ; preds = %unwind37.fragment, %bb_main
- br label %bb_main
-
-meshBB22.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB22.fragment: ; preds = %bb_main
- br label %bb_main
-
-entry1.fragment.normaldest: ; preds = %entry1.fragment.fragment, %bb_main
- br label %bb_main
-
-entry1.fragment.normaldest.normaldest: ; No predecessors!
- br label %bb_main
-
-meshBB23: ; preds = %invcont41.fragment, %bb_main
- br label %bb_main
-
-meshBB23.normaldest: ; No predecessors!
- br label %bb_main
-
-meshBB23.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB24: ; preds = %unwind10.fragment.fragment, %bb_main
- br label %bb_main
-
-meshBB24.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB24.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB25: ; preds = %bb_main
- br label %bb_main
-
-meshBB25.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB26: ; preds = %invcont30.fragment, %bb_main
- br label %bb_main
-
-meshBB26.normaldest: ; No predecessors!
- br label %bb_main
-
-meshBB26.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB27: ; preds = %bb_main
- br label %bb_main
-
-meshBB27.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB28: ; preds = %invcont47, %bb_main
- br label %bb_main
-
-meshBB28.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB28.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB29: ; preds = %invcont41.fragment, %bb_main
- br label %bb_main
-
-meshBB29.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB29.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB30: ; preds = %invcont12.fragment, %bb_main
- br label %bb_main
-
-meshBB30.normaldest: ; No predecessors!
- br label %bb_main
-
-meshBB30.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB31: ; preds = %bb_main
- br label %bb_main
-
-meshBB31.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB32: ; preds = %bb_main
- br label %bb_main
-
-meshBB32.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB33: ; preds = %bb_main
- br label %bb_main
-
-meshBB33.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB34: ; preds = %bb_main
- br label %bb_main
-
-meshBB34.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB35: ; preds = %bb_main
- br label %bb_main
-
-meshBB35.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB36: ; preds = %bb_main
- br label %bb_main
-
-meshBB36.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB37: ; preds = %invcont.fragment, %bb_main
- br label %bb_main
-
-meshBB37.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB37.fragment: ; preds = %bb_main
- br label %bb_main
-
-meshBB317: ; preds = %bb_main
- br label %bb_main
-
-meshBB318: ; preds = %invcont17.normaldest917, %bb_main
- br label %bb_main
-
-meshBB318.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB319: ; preds = %invcont22.fragment, %bb_main
- br label %bb_main
-
-meshBB319.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB320: ; preds = %entry1.fragment.fragment, %bb_main
- br label %bb_main
-
-meshBB320.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB321: ; preds = %bb_main
- br label %bb_main
-
-meshBB322: ; preds = %invcont28.fragment, %bb_main
- br label %bb_main
-
-meshBB322.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB323: ; preds = %cond_true, %bb_main
- br label %bb_main
-
-meshBB323.normaldest: ; No predecessors!
- br label %bb_main
-
-meshBB324: ; preds = %bb_main
- br label %bb_main
-
-meshBB325: ; preds = %entry.fragment.fragment, %bb_main
- br label %bb_main
-
-meshBB325.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB326: ; preds = %bb_main
- br label %bb_main
-
-meshBB327: ; preds = %bb_main
- br label %bb_main
-
-meshBB328: ; preds = %bb_main
- br label %bb_main
-
-meshBB329: ; preds = %unwind10.fragment.fragment, %bb_main
- br label %bb_main
-
-meshBB329.normaldest: ; No predecessors!
- br label %bb_main
-
-meshBB330: ; preds = %unwind37.fragment, %bb_main
- br label %bb_main
-
-meshBB330.normaldest: ; No predecessors!
- br label %bb_main
-
-meshBB331: ; preds = %bb_main
- br label %bb_main
-
-meshBB332: ; preds = %bb_main
- br label %bb_main
-
-meshBB333: ; preds = %bb_main
- br label %bb_main
-
-meshBB334: ; preds = %bb_main
- br label %bb_main
-
-meshBB335: ; preds = %bb_main
- br label %bb_main
-
-meshBB336: ; preds = %cond_next.fragment, %bb_main
- br label %bb_main
-
-meshBB336.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB337: ; preds = %invcont12.fragment, %bb_main
- br label %bb_main
-
-meshBB337.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB338: ; preds = %invcont36.normaldest, %bb_main
- br label %bb_main
-
-meshBB338.unwinddest: ; No predecessors!
- br label %bb_main
+ %tmp23 = invoke i32 @foo()
+ to label %invcont17.normaldest unwind label %invcont17.normaldest.normaldest
invcont17.normaldest: ; preds = %invcont17.normaldest917, %bb_main
br label %bb_main
invcont17.normaldest.normaldest: ; No predecessors!
- store %"struct.std::basic_ostream<char,std::char_traits<char> >"* %tmp23, %"struct.std::basic_ostream<char,std::char_traits<char> >"** undef
- br label %bb_main
-
-meshBB339: ; preds = %bb_main
- br label %bb_main
-
-meshBB340: ; preds = %entry.fragment.fragment, %bb_main
- br label %bb_main
-
-meshBB340.normaldest: ; No predecessors!
- br label %bb_main
-
-meshBB341: ; preds = %bb_main
- br label %bb_main
-
-meshBB342: ; preds = %bb_main
- br label %bb_main
-
-meshBB343: ; preds = %bb_main
- br label %bb_main
-
-meshBB344: ; preds = %bb_main
- br label %bb_main
-
-meshBB345: ; preds = %invcont14.normaldest, %bb_main
- br label %bb_main
-
-meshBB345.unwinddest: ; No predecessors!
- br label %bb_main
-
-meshBB346: ; preds = %bb_main
- br label %bb_main
-
-meshBB347: ; preds = %bb_main
- br label %bb_main
-
-meshBB348: ; preds = %bb_main
- br label %bb_main
-
-meshBB349: ; preds = %bb_main
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
+ store i32 %tmp23, i32* undef
br label %bb_main
+}
-UnifiedUnreachableBlock: ; preds = %Unwind20.fragment, %filter87, %filter75, %filter62, %filter19, %Unwind.fragment, %filter
- unreachable
+declare i32 @foo()
-UnifiedReturnBlock: ; preds = %invcont70.normaldest, %invcont15.normaldest
- ret void
-}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/LoopSimplify/merge-exits.ll b/test/Transforms/LoopSimplify/merge-exits.ll
index e5e4717..40ad2f4 100644
--- a/test/Transforms/LoopSimplify/merge-exits.ll
+++ b/test/Transforms/LoopSimplify/merge-exits.ll
@@ -7,7 +7,7 @@
; that indvars can promote the induction variable to i64
; without needing casts.
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n:32:64"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
define float @t(float* %pTmp1, float* %peakWeight, i32 %bandEdgeIndex) nounwind {
entry:
diff --git a/test/Transforms/LoopSimplify/preserve-scev.ll b/test/Transforms/LoopSimplify/preserve-scev.ll
index 017a0d2..23ac7f2 100644
--- a/test/Transforms/LoopSimplify/preserve-scev.ll
+++ b/test/Transforms/LoopSimplify/preserve-scev.ll
@@ -48,3 +48,91 @@ return: ; preds = %for.body18, %for.bo
}
declare void @foo() nounwind
+
+; Notify SCEV when removing an ExitingBlock.
+; CHECK: @mergeExit
+; CHECK: while.cond191:
+; CHECK: br i1 %or.cond, label %while.body197
+; CHECK-NOT: land.rhs:
+; CHECK: ret
+define void @mergeExit(i32 %MapAttrCount) nounwind uwtable ssp {
+entry:
+ br i1 undef, label %if.then124, label %if.end126
+
+if.then124: ; preds = %entry
+ unreachable
+
+if.end126: ; preds = %entry
+ br i1 undef, label %while.body.lr.ph, label %if.end591
+
+while.body.lr.ph: ; preds = %if.end126
+ br i1 undef, label %if.end140, label %if.then137
+
+if.then137: ; preds = %while.body.lr.ph
+ unreachable
+
+if.end140: ; preds = %while.body.lr.ph
+ br i1 undef, label %while.cond191.outer, label %if.then148
+
+if.then148: ; preds = %if.end140
+ unreachable
+
+while.cond191.outer: ; preds = %if.then205, %if.end140
+ br label %while.cond191
+
+while.cond191: ; preds = %while.body197, %while.cond191.outer
+ %CppIndex.0 = phi i32 [ %inc, %while.body197 ], [ undef, %while.cond191.outer ]
+ br i1 undef, label %land.rhs, label %if.then216
+
+land.rhs: ; preds = %while.cond191
+ %inc = add i32 %CppIndex.0, 1
+ %cmp196 = icmp ult i32 %inc, %MapAttrCount
+ br i1 %cmp196, label %while.body197, label %if.then216
+
+while.body197: ; preds = %land.rhs
+ br i1 undef, label %if.then205, label %while.cond191
+
+if.then205: ; preds = %while.body197
+ br label %while.cond191.outer
+
+if.then216: ; preds = %land.rhs, %while.cond191
+ br i1 undef, label %if.else, label %if.then221
+
+if.then221: ; preds = %if.then216
+ unreachable
+
+if.else: ; preds = %if.then216
+ br i1 undef, label %if.then266, label %if.end340
+
+if.then266: ; preds = %if.else
+ switch i32 undef, label %if.else329 [
+ i32 17, label %if.then285
+ i32 19, label %if.then285
+ i32 18, label %if.then285
+ i32 15, label %if.then285
+ ]
+
+if.then285: ; preds = %if.then266, %if.then266, %if.then266, %if.then266
+ br i1 undef, label %if.then317, label %if.else324
+
+if.then317: ; preds = %if.then285
+ br label %if.end340
+
+if.else324: ; preds = %if.then285
+ unreachable
+
+if.else329: ; preds = %if.then266
+ unreachable
+
+if.end340: ; preds = %if.then317, %if.else
+ unreachable
+
+if.end591: ; preds = %if.end126
+ br i1 undef, label %cond.end, label %cond.false
+
+cond.false: ; preds = %if.end591
+ unreachable
+
+cond.end: ; preds = %if.end591
+ ret void
+}
diff --git a/test/Transforms/LoopSimplify/single-backedge.ll b/test/Transforms/LoopSimplify/single-backedge.ll
index f9567f1..aedd6f2 100644
--- a/test/Transforms/LoopSimplify/single-backedge.ll
+++ b/test/Transforms/LoopSimplify/single-backedge.ll
@@ -1,8 +1,11 @@
-; The loop canonicalization pass should guarantee that there is one backedge
-; for all loops. This allows the -indvars pass to recognize the %IV
+; The loop canonicalization pass should guarantee that there is one backedge
+; for all loops. This allows the -indvars pass to recognize the %IV
; induction variable in this testcase.
-; RUN: opt < %s -indvars -S | grep indvar
+; RUN: opt < %s -indvars -S | FileCheck %s
+; CHECK: Loop.backedge:
+; CHECK-NOT: br
+; CHECK: br label %Loop
define i32 @test(i1 %C) {
; <label>:0
diff --git a/test/Transforms/LoopStrengthReduce/2011-07-19-CritEdgeBreakCrash.ll b/test/Transforms/LoopStrengthReduce/2011-07-19-CritEdgeBreakCrash.ll
new file mode 100644
index 0000000..b9bd7c9
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2011-07-19-CritEdgeBreakCrash.ll
@@ -0,0 +1,52 @@
+; ModuleID = '<stdin>'
+; RUN: opt < %s -loop-reduce -S | FileCheck %s
+; PR10386
+
+declare i1 @foo()
+declare i8* @bar(i8*,i8*,i8*,i8*)
+
+define void @f(i64* %a,i64* %b,i64* %c,i64* %d,i64* %e,i64* %f,i64* %g) nounwind uwtable {
+entry:
+ br label %b_throw.preheader
+
+D_BREAK_LBL: ; preds = %indirectgoto
+ call i1 @foo()
+ br label %indirectgoto
+
+H_CONST_LBL: ; preds = %indirectgoto
+ call i1 @foo()
+ br label %body_failed
+
+H_MPZ_LBL: ; preds = %indirectgoto
+ %boo3 = call i1 @foo()
+ br i1 %boo3, label %body_failed, label %while.cond.i
+
+while.cond.i: ; preds = %while.body.i15795, %if.then.i15791
+ %phi = phi i64 [ %tmp20916, %while.body.i15795 ], [ 0, %H_MPZ_LBL ]
+ %tmp20916 = add i64 %phi, 1
+ %incdec.ptr.i15793 = getelementptr i64* %pc.0.lcssa.i1610719352, i64 %tmp20916
+ %boo2 = call i1 @foo()
+ br i1 %boo2, label %indirectgoto, label %while.body.i15795
+
+while.body.i15795: ; preds = %while.cond.i
+ %tmp20.i = load i64* %incdec.ptr.i15793, align 8
+ %boo1 = call i1 @foo()
+ br i1 %boo1, label %while.cond.i, label %body_failed
+
+b_throw.preheader: ; preds = %body_failed, %entry
+ call i1 @foo()
+ br label %indirectgoto
+
+body_failed:
+ %pc.0.lcssa.i1610719364 = phi i64* [ %pc.0.lcssa.i1610719352, %indirectgoto ], [ %pc.0.lcssa.i1610719352, %H_MPZ_LBL ], [ %b, %H_CONST_LBL ], [ %pc.0.lcssa.i1610719352, %while.body.i15795 ]
+ call i1 @foo()
+ br label %b_throw.preheader
+
+indirectgoto:
+ %pc.0.lcssa.i1610719352 = phi i64* [ %pc.0.lcssa.i1610719352, %D_BREAK_LBL ], [ %a, %b_throw.preheader ], [ %d, %while.cond.i ]
+ %p = call i8* @bar(i8* blockaddress(@f, %D_BREAK_LBL), i8* blockaddress(@f, %H_CONST_LBL), i8* blockaddress(@f, %H_MPZ_LBL), i8* blockaddress(@f, %body_failed) )
+ indirectbr i8* %p, [label %D_BREAK_LBL, label %H_CONST_LBL, label %H_MPZ_LBL, label %body_failed]
+}
+
+; CHECK: %p = call i8* @bar(i8* blockaddress(@f, %D_BREAK_LBL), i8* blockaddress(@f, %H_CONST_LBL), i8* blockaddress(@f, %H_MPZ_LBL), i8* blockaddress(@f, %body_failed))
+; CHECK: indirectbr i8* %p, [label %D_BREAK_LBL, label %H_CONST_LBL, label %H_MPZ_LBL, label %body_failed]
diff --git a/test/Transforms/LoopStrengthReduce/2011-07-20-DoubleIV.ll b/test/Transforms/LoopStrengthReduce/2011-07-20-DoubleIV.ll
new file mode 100644
index 0000000..5d9ed64
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2011-07-20-DoubleIV.ll
@@ -0,0 +1,43 @@
+; RUN: opt < %s -loop-reduce -S | FileCheck %s
+;
+; Test LSR's OptimizeShadowIV. Handle a floating-point IV with a
+; nonzero initial value.
+; rdar://9786536
+
+; First, make sure LSR doesn't crash on an empty IVUsers list.
+; CHECK: @dummyIV
+; CHECK-NOT: phi
+; CHECK-NOT: sitofp
+; CHECK: br
+define void @dummyIV() nounwind {
+entry:
+ br label %loop
+
+loop:
+ %i.01 = phi i32 [ -39, %entry ], [ %inc, %loop ]
+ %conv = sitofp i32 %i.01 to double
+ %inc = add nsw i32 %i.01, 1
+ br i1 undef, label %loop, label %for.end
+
+for.end:
+ unreachable
+}
+
+; Now check that the computed double constant is correct.
+; CHECK: @doubleIV
+; CHECK: phi double [ -3.900000e+01, %entry ]
+; CHECK: br
+define void @doubleIV() nounwind {
+entry:
+ br label %loop
+
+loop:
+ %i.01 = phi i32 [ -39, %entry ], [ %inc, %loop ]
+ %conv = sitofp i32 %i.01 to double
+ %div = fdiv double %conv, 4.000000e+01
+ %inc = add nsw i32 %i.01, 1
+ br i1 undef, label %loop, label %for.end
+
+for.end:
+ unreachable
+}
diff --git a/test/Transforms/LoopStrengthReduce/2011-10-03-CritEdgeMerge.ll b/test/Transforms/LoopStrengthReduce/2011-10-03-CritEdgeMerge.ll
new file mode 100644
index 0000000..a6996a8
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2011-10-03-CritEdgeMerge.ll
@@ -0,0 +1,43 @@
+; RUN: opt -loop-reduce -S < %s | FileCheck %s
+;
+; Test LSR's use of SplitCriticalEdge during phi rewriting.
+; Verify that identical edges are merged. rdar://problem/6453893
+
+target triple = "x86-apple-darwin"
+
+; CHECK: @test
+; CHECK: bb89:
+; CHECK: phi i8* [ %lsr.iv.next1, %bbA.bb89_crit_edge ], [ %lsr.iv.next1, %bbB.bb89_crit_edge ]{{$}}
+
+define i8* @test() {
+entry:
+ br label %loop
+
+loop:
+ %rec = phi i32 [ %next, %loop ], [ 0, %entry ]
+ %next = add i32 %rec, 1
+ %tmp75 = getelementptr i8* null, i32 %next
+ br i1 false, label %loop, label %loopexit
+
+loopexit:
+ br i1 false, label %bbA, label %bbB
+
+bbA:
+ switch i32 0, label %bb89 [
+ i32 47, label %bb89
+ i32 58, label %bb89
+ ]
+
+bbB:
+ switch i8 0, label %bb89 [
+ i8 47, label %bb89
+ i8 58, label %bb89
+ ]
+
+bb89:
+ %tmp75phi = phi i8* [ %tmp75, %bbA ], [ %tmp75, %bbA ], [ %tmp75, %bbA ], [ %tmp75, %bbB ], [ %tmp75, %bbB ], [ %tmp75, %bbB ]
+ br label %exit
+
+exit:
+ ret i8* %tmp75phi
+}
diff --git a/test/Transforms/LoopStrengthReduce/2011-10-06-ReusePhi.ll b/test/Transforms/LoopStrengthReduce/2011-10-06-ReusePhi.ll
new file mode 100644
index 0000000..1ee9bb4
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2011-10-06-ReusePhi.ll
@@ -0,0 +1,53 @@
+; RUN: opt -loop-reduce -S < %s | FileCheck %s
+;
+; Test LSR's intelligence regarding phi reuse.
+; Verify that scaled GEPs are not reused. rdar://5064068
+
+target triple = "x86-apple-darwin"
+
+; CHECK: @test
+; multiplies are hoisted out of the loop
+; CHECK: while.body.lr.ph:
+; CHECK: mul i64
+; CHECK: mul i64
+; GEPs are ugly
+; CHECK: while.body:
+; CHECK: phi
+; CHECK: phi
+; CHECK: phi
+; CHECK: phi
+; CHECK-NOT: phi
+; CHECK: bitcast float* {{.*}} to i8*
+; CHECK: bitcast float* {{.*}} to i8*
+; CHECK: getelementptr i8*
+; CHECK: getelementptr i8*
+
+define float @test(float* nocapture %A, float* nocapture %B, i32 %N, i32 %IA, i32 %IB) nounwind uwtable readonly ssp {
+entry:
+ %cmp1 = icmp sgt i32 %N, 0
+ br i1 %cmp1, label %while.body.lr.ph, label %while.end
+
+while.body.lr.ph: ; preds = %entry
+ %idx.ext = sext i32 %IA to i64
+ %idx.ext2 = sext i32 %IB to i64
+ br label %while.body
+
+while.body: ; preds = %while.body.lr.ph, %while.body
+ %A.addr.05 = phi float* [ %A, %while.body.lr.ph ], [ %add.ptr, %while.body ]
+ %B.addr.04 = phi float* [ %B, %while.body.lr.ph ], [ %add.ptr3, %while.body ]
+ %N.addr.03 = phi i32 [ %N, %while.body.lr.ph ], [ %sub, %while.body ]
+ %Sum0.02 = phi float [ 0.000000e+00, %while.body.lr.ph ], [ %add, %while.body ]
+ %0 = load float* %A.addr.05, align 4
+ %1 = load float* %B.addr.04, align 4
+ %mul = fmul float %0, %1
+ %add = fadd float %Sum0.02, %mul
+ %add.ptr = getelementptr inbounds float* %A.addr.05, i64 %idx.ext
+ %add.ptr3 = getelementptr inbounds float* %B.addr.04, i64 %idx.ext2
+ %sub = add nsw i32 %N.addr.03, -1
+ %cmp = icmp sgt i32 %sub, 0
+ br i1 %cmp, label %while.body, label %while.end
+
+while.end: ; preds = %while.body, %entry
+ %Sum0.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %add, %while.body ]
+ ret float %Sum0.0.lcssa
+}
diff --git a/test/Transforms/LoopStrengthReduce/2011-10-13-SCEVChain.ll b/test/Transforms/LoopStrengthReduce/2011-10-13-SCEVChain.ll
new file mode 100644
index 0000000..4718529
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2011-10-13-SCEVChain.ll
@@ -0,0 +1,111 @@
+; RUN: opt -loop-reduce -S < %s | FileCheck %s
+;
+; Test TransformForPostIncUse and LSR's expansion of expressions in
+; post-inc form to ensure the implementation can handle expressions
+; DAGs, not just trees.
+
+target triple = "x86_64-apple-darwin"
+
+; Verify that -loop-reduce runs without "hanging" and reuses post-inc
+; expansions.
+; CHECK: @test
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK: icmp
+; CHECK-NOT: icmp
+define void @test(i8* %base, i32 %a0) nounwind {
+entry:
+ br label %bb1
+bb1:
+ %n0 = sub i32 0, %a0
+ %t0 = icmp ugt i32 %n0, -4
+ %m0 = select i1 %t0, i32 %n0, i32 -4
+ %a1 = add i32 %m0, %a0
+ %n1 = sub i32 0, %a1
+ %t1 = icmp ugt i32 %n1, -4
+ %m1 = select i1 %t1, i32 %n1, i32 -4
+ %a2 = add i32 %m1, %a1
+ %n2 = sub i32 0, %a2
+ %t2 = icmp ugt i32 %n2, -4
+ %m2 = select i1 %t2, i32 %n2, i32 -4
+ %a3 = add i32 %m2, %a2
+ %n3 = sub i32 0, %a3
+ %t3 = icmp ugt i32 %n3, -4
+ %m3 = select i1 %t3, i32 %n3, i32 -4
+ %a4 = add i32 %m3, %a3
+ %n4 = sub i32 0, %a4
+ %t4 = icmp ugt i32 %n4, -4
+ %m4 = select i1 %t4, i32 %n4, i32 -4
+ %a5 = add i32 %m4, %a4
+ %n5 = sub i32 0, %a5
+ %t5 = icmp ugt i32 %n5, -4
+ %m5 = select i1 %t5, i32 %n5, i32 -4
+ %a6 = add i32 %m5, %a5
+ %n6 = sub i32 0, %a6
+ %t6 = icmp ugt i32 %n6, -4
+ %m6 = select i1 %t6, i32 %n6, i32 -4
+ %a7 = add i32 %m6, %a6
+ %n7 = sub i32 0, %a7
+ %t7 = icmp ugt i32 %n7, -4
+ %m7 = select i1 %t7, i32 %n7, i32 -4
+ %a8 = add i32 %m7, %a7
+ %n8 = sub i32 0, %a8
+ %t8 = icmp ugt i32 %n8, -4
+ %m8 = select i1 %t8, i32 %n8, i32 -4
+ %a9 = add i32 %m8, %a8
+ %n9 = sub i32 0, %a9
+ %t9 = icmp ugt i32 %n9, -4
+ %m9 = select i1 %t9, i32 %n9, i32 -4
+ %a10 = add i32 %m9, %a9
+ %n10 = sub i32 0, %a10
+ %t10 = icmp ugt i32 %n10, -4
+ %m10 = select i1 %t10, i32 %n10, i32 -4
+ %a11 = add i32 %m10, %a10
+ %n11 = sub i32 0, %a11
+ %t11 = icmp ugt i32 %n11, -4
+ %m11 = select i1 %t11, i32 %n11, i32 -4
+ %a12 = add i32 %m11, %a11
+ %n12 = sub i32 0, %a12
+ %t12 = icmp ugt i32 %n12, -4
+ %m12 = select i1 %t12, i32 %n12, i32 -4
+ %a13 = add i32 %m12, %a12
+ %n13 = sub i32 0, %a13
+ %t13 = icmp ugt i32 %n13, -4
+ %m13 = select i1 %t13, i32 %n13, i32 -4
+ %a14 = add i32 %m13, %a13
+ %n14 = sub i32 0, %a14
+ %t14 = icmp ugt i32 %n14, -4
+ %m14 = select i1 %t14, i32 %n14, i32 -4
+ %a15 = add i32 %m14, %a14
+ %n15 = sub i32 0, %a15
+ %t15 = icmp ugt i32 %n15, -4
+ %m15 = select i1 %t15, i32 %n15, i32 -4
+ %a16 = add i32 %m15, %a15
+ %gep = getelementptr i8* %base, i32 %a16
+ %ofs = add i32 %a16, 4
+ %limit = getelementptr i8* %base, i32 %ofs
+ br label %loop
+
+loop:
+ %iv = phi i8* [ %gep, %bb1 ], [ %inc, %loop ]
+ %inc = getelementptr inbounds i8* %iv, i64 1
+ %exitcond = icmp eq i8* %inc, %limit
+ br i1 %exitcond, label %loop, label %exit
+
+exit:
+ ret void
+}
diff --git a/test/Transforms/LoopStrengthReduce/2011-10-14-IntPtr.ll b/test/Transforms/LoopStrengthReduce/2011-10-14-IntPtr.ll
new file mode 100644
index 0000000..60cc7a5
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2011-10-14-IntPtr.ll
@@ -0,0 +1,27 @@
+; RUN: opt -loop-reduce -S < %s | FileCheck %s
+;
+; Test SCEVExpander reusing a phi->gep->phi IV when SCEV "wrongly"
+; reports the expression as an IntegerTy.
+
+target triple = "x86_64-apple-darwin"
+
+; CHECK: @test
+; CHECK: phi
+; CHECK-NOT: phi
+define void @test(i32 %rowStride) ssp align 2 {
+entry:
+ %cond = select i1 undef, i32 %rowStride, i32 4
+ br label %for.end
+
+for.end.critedge: ; preds = %for.end
+ br label %for.end
+
+for.end: ; preds = %for.end.critedge, %entry
+ br i1 undef, label %for.body83, label %for.end.critedge
+
+for.body83: ; preds = %for.body83, %for.end
+ %ptr.0157 = phi i8* [ %add.ptr96, %for.body83 ], [ null, %for.end ]
+ store i8 undef, i8* %ptr.0157, align 1
+ %add.ptr96 = getelementptr inbounds i8* %ptr.0157, i32 %cond
+ br label %for.body83
+}
diff --git a/test/Transforms/LoopStrengthReduce/invariant_value_first.ll b/test/Transforms/LoopStrengthReduce/invariant_value_first.ll
index 986a55a..2ca6787 100644
--- a/test/Transforms/LoopStrengthReduce/invariant_value_first.ll
+++ b/test/Transforms/LoopStrengthReduce/invariant_value_first.ll
@@ -2,7 +2,7 @@
; RUN: opt < %s -loop-reduce -S | \
; RUN: not grep {getelementptr.*%outer.*%INDVAR}
-target datalayout = "e-p:32:32:32-n:8:16:32"
+target datalayout = "e-p:32:32:32-n8:16:32"
declare i1 @pred()
declare i32 @foo()
diff --git a/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll b/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll
index 1d43961..86c4d91 100644
--- a/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll
+++ b/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll
@@ -2,7 +2,7 @@
; RUN: opt < %s -loop-reduce -S | \
; RUN: not grep {getelementptr.*%outer.*%INDVAR}
-target datalayout = "e-p:32:32:32-n:32"
+target datalayout = "e-p:32:32:32-n32"
declare i1 @pred()
define void @test([10000 x i32]* %P, i32 %outer) {
diff --git a/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll b/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll
index 00bd068..ec55179 100644
--- a/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll
+++ b/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll
@@ -3,7 +3,7 @@
; RUN: opt < %s -loop-reduce -S | not grep INDVAR
-target datalayout = "e-p:32:32:32-n:32"
+target datalayout = "e-p:32:32:32-n32"
declare i1 @pred()
diff --git a/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll b/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
index 294c090..2760915 100644
--- a/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
+++ b/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
@@ -4,15 +4,15 @@
; LSR should property handle the post-inc offset when folding the
; non-IV operand of an icmp into the IV.
-; CHECK: %tmp2 = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
-; CHECK: %tmp3 = lshr i64 %tmp2, 1
-; CHECK: %tmp4 = mul i64 %tmp3, 2
+; CHECK: %5 = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+; CHECK: %6 = lshr i64 %5, 1
+; CHECK: %7 = mul i64 %6, 2
; CHECK: br label %for.body
; CHECK: for.body:
-; CHECK: %lsr.iv5 = phi i64 [ %lsr.iv.next, %for.body ], [ %tmp4, %for.body.lr.ph ]
-; CHECK: %lsr.iv.next = add i64 %lsr.iv5, -2
-; CHECK: %lsr.iv.next6 = inttoptr i64 %lsr.iv.next to i16*
-; CHECK: %cmp27 = icmp eq i16* %lsr.iv.next6, null
+; CHECK: %lsr.iv2 = phi i64 [ %lsr.iv.next, %for.body ], [ %7, %for.body.lr.ph ]
+; CHECK: %lsr.iv.next = add i64 %lsr.iv2, -2
+; CHECK: %lsr.iv.next3 = inttoptr i64 %lsr.iv.next to i16*
+; CHECK: %cmp27 = icmp eq i16* %lsr.iv.next3, null
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
diff --git a/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll b/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll
index 7547d83..64ef4f9 100644
--- a/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll
+++ b/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll
@@ -9,7 +9,7 @@
; mul uint %i, 3
-target datalayout = "e-p:32:32-n:32"
+target datalayout = "e-p:32:32-n32"
target triple = "i686-apple-darwin8"
@flags2 = external global [8193 x i8], align 32 ; <[8193 x i8]*> [#uses=1]
diff --git a/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll b/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll
new file mode 100644
index 0000000..cd954c8
--- /dev/null
+++ b/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll
@@ -0,0 +1,103 @@
+; RUN: opt < %s -loop-unroll -S -unroll-count=4 | FileCheck %s
+; Test phi update after partial unroll.
+
+declare i1 @check() nounwind
+
+; CHECK: @test
+; CHECK: if.else:
+; CHECK: if.then.loopexit
+; CHECK: %sub5.lcssa = phi i32 [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ]
+; CHECK: if.else.3
+define void @test1(i32 %i, i32 %j) nounwind uwtable ssp {
+entry:
+ %cond1 = call zeroext i1 @check()
+ br i1 %cond1, label %if.then, label %if.else.lr.ph
+
+if.else.lr.ph: ; preds = %entry
+ br label %if.else
+
+if.else: ; preds = %if.else, %if.else.lr.ph
+ %sub = phi i32 [ %i, %if.else.lr.ph ], [ %sub5, %if.else ]
+ %sub5 = sub i32 %sub, %j
+ %cond2 = call zeroext i1 @check()
+ br i1 %cond2, label %if.then, label %if.else
+
+if.then: ; preds = %if.else, %entry
+ %i.tr = phi i32 [ %i, %entry ], [ %sub5, %if.else ]
+ ret void
+
+}
+
+; PR7318: assertion failure after doing a simple loop unroll
+;
+; CHECK: @test2
+; CHECK: bb1.bb2_crit_edge:
+; CHECK: %.lcssa = phi i32 [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ]
+; CHECK: bb1.3:
+define i32 @test2(i32* nocapture %p, i32 %n) nounwind readonly {
+entry:
+ %0 = icmp sgt i32 %n, 0 ; <i1> [#uses=1]
+ br i1 %0, label %bb.nph, label %bb2
+
+bb.nph: ; preds = %entry
+ %tmp = zext i32 %n to i64 ; <i64> [#uses=1]
+ br label %bb
+
+bb: ; preds = %bb.nph, %bb1
+ %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; <i64> [#uses=2]
+ %s.01 = phi i32 [ 0, %bb.nph ], [ %2, %bb1 ] ; <i32> [#uses=1]
+ %scevgep = getelementptr i32* %p, i64 %indvar ; <i32*> [#uses=1]
+ %1 = load i32* %scevgep, align 1 ; <i32> [#uses=1]
+ %2 = add nsw i32 %1, %s.01 ; <i32> [#uses=2]
+ br label %bb1
+
+bb1: ; preds = %bb
+ %indvar.next = add i64 %indvar, 1 ; <i64> [#uses=2]
+ %exitcond = icmp ne i64 %indvar.next, %tmp ; <i1> [#uses=1]
+ br i1 %exitcond, label %bb, label %bb1.bb2_crit_edge
+
+bb1.bb2_crit_edge: ; preds = %bb1
+ %.lcssa = phi i32 [ %2, %bb1 ] ; <i32> [#uses=1]
+ br label %bb2
+
+bb2: ; preds = %bb1.bb2_crit_edge, %entry
+ %s.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ 0, %entry ] ; <i32> [#uses=1]
+ ret i32 %s.0.lcssa
+}
+
+; Check phi update for loop with an early-exit.
+;
+; CHECK: @test3
+; CHECK: return.loopexit:
+; CHECK: %tmp7.i.lcssa = phi i32 [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ]
+; CHECK: exit.3:
+define i32 @test3() nounwind uwtable ssp align 2 {
+entry:
+ %cond1 = call zeroext i1 @check()
+ br i1 %cond1, label %return, label %if.end
+
+if.end: ; preds = %entry
+ br label %do.body
+
+do.body: ; preds = %do.cond, %if.end
+ %cond2 = call zeroext i1 @check()
+ br i1 %cond2, label %exit, label %do.cond
+
+exit: ; preds = %do.body
+ %tmp7.i = load i32* undef, align 8
+ br i1 undef, label %do.cond, label %land.lhs.true
+
+land.lhs.true: ; preds = %exit
+ br i1 undef, label %return, label %do.cond
+
+do.cond: ; preds = %land.lhs.true, %exit, %do.body
+ %cond3 = call zeroext i1 @check()
+ br i1 %cond3, label %do.end, label %do.body
+
+do.end: ; preds = %do.cond
+ br label %return
+
+return: ; preds = %do.end, %land.lhs.true, %entry
+ %retval.0 = phi i32 [ 0, %do.end ], [ 0, %entry ], [ %tmp7.i, %land.lhs.true ]
+ ret i32 %retval.0
+}
diff --git a/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll b/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll
new file mode 100644
index 0000000..59551d5
--- /dev/null
+++ b/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll
@@ -0,0 +1,41 @@
+; RUN: opt -S < %s -loop-unroll -unroll-count=4 -enable-iv-rewrite=false | FileCheck %s
+;
+; Test induction variable simplify after loop unrolling. It should
+; expose nice opportunities for GVN.
+;
+; CHECK-NOT: while.body also ensures that loop unrolling (with SCEV)
+; removes unrolled loop exits given that 128 is a multiple of 4.
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+
+; PR10534: LoopUnroll not keeping canonical induction variable...
+; CHECK: while.body:
+; CHECK-NOT: while.body.1:
+; CHECK: %shr.1 = lshr i32 %bit_addr.addr.01, 5
+; CHECK: %arrayidx.1 = getelementptr inbounds i32* %bitmap, i32 %shr.1
+; CHECK: %shr.2 = lshr i32 %bit_addr.addr.01, 5
+; CHECK: %arrayidx.2 = getelementptr inbounds i32* %bitmap, i32 %shr.2
+; CHECK: %shr.3 = lshr i32 %bit_addr.addr.01, 5
+; CHECK: %arrayidx.3 = getelementptr inbounds i32* %bitmap, i32 %shr.3
+define void @FlipBit(i32* nocapture %bitmap, i32 %bit_addr, i32 %nbits) nounwind {
+entry:
+ br label %while.body
+
+while.body:
+ %nbits.addr.02 = phi i32 [ 128, %entry ], [ %dec, %while.body ]
+ %bit_addr.addr.01 = phi i32 [ 0, %entry ], [ %inc, %while.body ]
+ %dec = add i32 %nbits.addr.02, -1
+ %shr = lshr i32 %bit_addr.addr.01, 5
+ %rem = and i32 %bit_addr.addr.01, 31
+ %shl = shl i32 1, %rem
+ %arrayidx = getelementptr inbounds i32* %bitmap, i32 %shr
+ %tmp6 = load i32* %arrayidx, align 4
+ %xor = xor i32 %tmp6, %shl
+ store i32 %xor, i32* %arrayidx, align 4
+ %inc = add i32 %bit_addr.addr.01, 1
+ %tobool = icmp eq i32 %dec, 0
+ br i1 %tobool, label %while.end, label %while.body
+
+while.end:
+ ret void
+}
diff --git a/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll b/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll
new file mode 100644
index 0000000..c1221f5
--- /dev/null
+++ b/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll
@@ -0,0 +1,62 @@
+; RUN: opt -S < %s -instcombine -inline -jump-threading -loop-unroll -unroll-count=4 | FileCheck %s
+;
+; This is a test case that required a number of setup passes because
+; it depends on block order.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.6.8"
+
+declare i1 @check() nounwind
+declare i32 @getval() nounwind
+
+; Check that the loop exit merges values from all the iterations. This
+; could be a tad fragile, but it's a good test.
+;
+; CHECK: @foo
+; CHECK: return:
+; CHECK: %retval.0 = phi i32 [ %tmp7.i, %land.lhs.true ], [ 0, %do.cond ], [ %tmp7.i.1, %land.lhs.true.1 ], [ 0, %do.cond.1 ], [ %tmp7.i.2, %land.lhs.true.2 ], [ 0, %do.cond.2 ], [ %tmp7.i.3, %land.lhs.true.3 ], [ 0, %do.cond.3 ]
+; CHECK-NOT: @bar
+; CHECK: bar.exit.3
+define i32 @foo() uwtable ssp align 2 {
+entry:
+ br i1 undef, label %return, label %if.end
+
+if.end: ; preds = %entry
+ %call2 = call i32 @getval()
+ br label %do.body
+
+do.body: ; preds = %do.cond, %if.end
+ %call6 = call i32 @bar()
+ %cmp = icmp ne i32 %call6, 0
+ br i1 %cmp, label %land.lhs.true, label %do.cond
+
+land.lhs.true: ; preds = %do.body
+ %call10 = call i32 @getval()
+ %cmp11 = icmp eq i32 0, %call10
+ br i1 %cmp11, label %return, label %do.cond
+
+do.cond: ; preds = %land.lhs.true, %do.body
+ %cmp18 = icmp sle i32 0, %call2
+ br i1 %cmp18, label %do.body, label %return
+
+return: ; preds = %do.cond, %land.lhs.true, %entry
+ %retval.0 = phi i32 [ 0, %entry ], [ %call6, %land.lhs.true ], [ 0, %do.cond ]
+ ret i32 %retval.0
+}
+
+define linkonce_odr i32 @bar() nounwind uwtable ssp align 2 {
+entry:
+ br i1 undef, label %land.lhs.true, label %cond.end
+
+land.lhs.true: ; preds = %entry
+ %cmp4 = call zeroext i1 @check()
+ br i1 %cmp4, label %cond.true, label %cond.end
+
+cond.true: ; preds = %land.lhs.true
+ %tmp7 = call i32 @getval()
+ br label %cond.end
+
+cond.end: ; preds = %cond.true, %land.lhs.true, %entry
+ %cond = phi i32 [ %tmp7, %cond.true ], [ 0, %land.lhs.true ], [ 0, %entry ]
+ ret i32 %cond
+}
diff --git a/test/Transforms/LoopUnroll/2011-10-01-NoopTrunc.ll b/test/Transforms/LoopUnroll/2011-10-01-NoopTrunc.ll
new file mode 100644
index 0000000..7fb471e
--- /dev/null
+++ b/test/Transforms/LoopUnroll/2011-10-01-NoopTrunc.ll
@@ -0,0 +1,36 @@
+; RUN: opt < %s -S -loop-unroll -unroll-threshold=150 | FileCheck %s
+;
+; Verify that trunc i64 to i32 is considered free by loop unrolling
+; heuristics when i32 is a native type.
+; This should result in full unrolling this loop with size=7, TC=19.
+; If the trunc were not free we would have 8*19=152 > 150.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+; Check that for.body was unrolled 19 times.
+; CHECK: @test
+; CHECK: %0 = load
+; CHECK: %conv = sext i8 %0 to i32
+; CHECK: %add.1 = add nsw i32 %conv.1, %conv
+; CHECK: %add.18 = add nsw i32 %conv.18, %add.17
+; CHECK: ret i32 %add.18
+define i32 @test(i8* %arr) nounwind uwtable readnone {
+entry:
+ br label %for.body
+
+for.body: ; preds = %for.body, %entry
+ %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+ %sum.02 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+ %arrayidx = getelementptr inbounds i8* %arr, i64 %indvars.iv
+ %0 = load i8* %arrayidx, align 1
+ %conv = sext i8 %0 to i32
+ %add = add nsw i32 %conv, %sum.02
+ %indvars.iv.next = add i64 %indvars.iv, 1
+ %lftr.wideiv1 = trunc i64 %indvars.iv.next to i32
+ %exitcond2 = icmp eq i32 %lftr.wideiv1, 19
+ br i1 %exitcond2, label %for.end, label %for.body
+
+for.end: ; preds = %for.body
+ %add.lcssa = phi i32 [ %add, %for.body ]
+ ret i32 %add.lcssa
+}
diff --git a/test/Transforms/LoopUnroll/pr10813.ll b/test/Transforms/LoopUnroll/pr10813.ll
new file mode 100644
index 0000000..7daefc2
--- /dev/null
+++ b/test/Transforms/LoopUnroll/pr10813.ll
@@ -0,0 +1,29 @@
+; RUN: opt < %s -loop-unroll -disable-output
+
+define void @"f_fu___REFUf[]REFUf[]Uf"() nounwind {
+allocas:
+ br i1 undef, label %cif_mask_all, label %cif_mixed_test_all
+
+cif_mask_all: ; preds = %allocas
+ unreachable
+
+cif_mixed_test_all: ; preds = %allocas
+ br label %pl_loop.i964
+
+pl_loop.i964: ; preds = %pl_loopend.i973, %cif_mixed_test_all
+ %0 = phi i32 [ %pl_nextlane.i971, %pl_loopend.i973 ], [ 0, %cif_mixed_test_all ]
+ br i1 undef, label %pl_dolane.i970, label %pl_loopend.i973
+
+pl_dolane.i970: ; preds = %pl_loop.i964
+ %storeval.i.i969 = extractelement <4 x i8> <i8 0, i8 1, i8 2, i8 3>, i32 %0
+ store i8 %storeval.i.i969, i8* undef, align 1
+ br label %pl_loopend.i973
+
+pl_loopend.i973: ; preds = %pl_dolane.i970, %pl_loop.i964
+ %pl_nextlane.i971 = add i32 %0, 1
+ %exitcond5 = icmp ne i32 %pl_nextlane.i971, 5
+ br i1 %exitcond5, label %pl_loop.i964, label %__scatter_base_offsets_i8.exit974
+
+__scatter_base_offsets_i8.exit974: ; preds = %pl_loopend.i973
+ unreachable
+}
diff --git a/test/Transforms/LoopUnroll/scevunroll.ll b/test/Transforms/LoopUnroll/scevunroll.ll
new file mode 100644
index 0000000..99b3a7d
--- /dev/null
+++ b/test/Transforms/LoopUnroll/scevunroll.ll
@@ -0,0 +1,172 @@
+; RUN: opt < %s -S -indvars -loop-unroll -verify-loop-info | FileCheck %s
+;
+; Unit tests for loop unrolling using ScalarEvolution to compute trip counts.
+;
+; Indvars is run first to generate an "old" SCEV result. Some unit
+; tests may check that SCEV is properly invalidated between passes.
+
+; Completely unroll loops without a canonical IV.
+;
+; CHECK: @sansCanonical
+; CHECK-NOT: phi
+; CHECK-NOT: icmp
+; CHECK: ret
+define i32 @sansCanonical(i32* %base) nounwind {
+entry:
+ br label %while.body
+
+while.body:
+ %iv = phi i64 [ 10, %entry ], [ %iv.next, %while.body ]
+ %sum = phi i32 [ 0, %entry ], [ %sum.next, %while.body ]
+ %iv.next = add i64 %iv, -1
+ %adr = getelementptr inbounds i32* %base, i64 %iv.next
+ %tmp = load i32* %adr, align 8
+ %sum.next = add i32 %sum, %tmp
+ %iv.narrow = trunc i64 %iv.next to i32
+ %cmp.i65 = icmp sgt i32 %iv.narrow, 0
+ br i1 %cmp.i65, label %while.body, label %exit
+
+exit:
+ ret i32 %sum
+}
+
+; SCEV unrolling properly handles loops with multiple exits. In this
+; case, the computed trip count based on a canonical IV is *not* for a
+; latch block. Canonical unrolling incorrectly unrolls it, but SCEV
+; unrolling does not.
+;
+; CHECK: @earlyLoopTest
+; CHECK: tail:
+; CHECK-NOT: br
+; CHECK: br i1 %cmp2, label %loop, label %exit2
+define i64 @earlyLoopTest(i64* %base) nounwind {
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %inc, %tail ]
+ %s = phi i64 [ 0, %entry ], [ %s.next, %tail ]
+ %adr = getelementptr i64* %base, i64 %iv
+ %val = load i64* %adr
+ %s.next = add i64 %s, %val
+ %inc = add i64 %iv, 1
+ %cmp = icmp ne i64 %inc, 4
+ br i1 %cmp, label %tail, label %exit1
+
+tail:
+ %cmp2 = icmp ne i64 %val, 0
+ br i1 %cmp2, label %loop, label %exit2
+
+exit1:
+ ret i64 %s
+
+exit2:
+ ret i64 %s.next
+}
+
+; SCEV properly unrolls multi-exit loops.
+;
+; CHECK: @multiExit
+; CHECK: getelementptr i32* %base, i32 10
+; CHECK-NEXT: load i32*
+; CHECK: br i1 false, label %l2.10, label %exit1
+; CHECK: l2.10:
+; CHECK-NOT: br
+; CHECK: ret i32
+define i32 @multiExit(i32* %base) nounwind {
+entry:
+ br label %l1
+l1:
+ %iv1 = phi i32 [ 0, %entry ], [ %inc1, %l2 ]
+ %iv2 = phi i32 [ 0, %entry ], [ %inc2, %l2 ]
+ %inc1 = add i32 %iv1, 1
+ %inc2 = add i32 %iv2, 1
+ %adr = getelementptr i32* %base, i32 %iv1
+ %val = load i32* %adr
+ %cmp1 = icmp slt i32 %iv1, 5
+ br i1 %cmp1, label %l2, label %exit1
+l2:
+ %cmp2 = icmp slt i32 %iv2, 10
+ br i1 %cmp2, label %l1, label %exit2
+exit1:
+ ret i32 1
+exit2:
+ ret i32 %val
+}
+
+
+; SCEV should not unroll a multi-exit loops unless the latch block has
+; a known trip count, regardless of the early exit trip counts. The
+; LoopUnroll utility uses this assumption to optimize the latch
+; block's branch.
+;
+; CHECK: @multiExit
+; CHECK: l3:
+; CHECK-NOT: br
+; CHECK: br i1 %cmp3, label %l1, label %exit3
+define i32 @multiExitIncomplete(i32* %base) nounwind {
+entry:
+ br label %l1
+l1:
+ %iv1 = phi i32 [ 0, %entry ], [ %inc1, %l3 ]
+ %iv2 = phi i32 [ 0, %entry ], [ %inc2, %l3 ]
+ %inc1 = add i32 %iv1, 1
+ %inc2 = add i32 %iv2, 1
+ %adr = getelementptr i32* %base, i32 %iv1
+ %val = load i32* %adr
+ %cmp1 = icmp slt i32 %iv1, 5
+ br i1 %cmp1, label %l2, label %exit1
+l2:
+ %cmp2 = icmp slt i32 %iv2, 10
+ br i1 %cmp2, label %l3, label %exit2
+l3:
+ %cmp3 = icmp ne i32 %val, 0
+ br i1 %cmp3, label %l1, label %exit3
+
+exit1:
+ ret i32 1
+exit2:
+ ret i32 2
+exit3:
+ ret i32 3
+}
+
+; When loop unroll merges a loop exit with one of its parent loop's
+; exits, SCEV must forget its ExitNotTaken info.
+;
+; CHECK: @nestedUnroll
+; CHECK-NOT: br i1
+; CHECK: for.body87:
+define void @nestedUnroll() nounwind {
+entry:
+ br label %for.inc
+
+for.inc:
+ br i1 false, label %for.inc, label %for.body38.preheader
+
+for.body38.preheader:
+ br label %for.body38
+
+for.body38:
+ %i.113 = phi i32 [ %inc76, %for.inc74 ], [ 0, %for.body38.preheader ]
+ %mul48 = mul nsw i32 %i.113, 6
+ br label %for.body43
+
+for.body43:
+ %j.011 = phi i32 [ 0, %for.body38 ], [ %inc72, %for.body43 ]
+ %add49 = add nsw i32 %j.011, %mul48
+ %sh_prom50 = zext i32 %add49 to i64
+ %inc72 = add nsw i32 %j.011, 1
+ br i1 false, label %for.body43, label %for.inc74
+
+for.inc74:
+ %inc76 = add nsw i32 %i.113, 1
+ br i1 false, label %for.body38, label %for.body87.preheader
+
+for.body87.preheader:
+ br label %for.body87
+
+for.body87:
+ br label %for.body87
+}
+
diff --git a/test/Transforms/LoopUnroll/unloop.ll b/test/Transforms/LoopUnroll/unloop.ll
new file mode 100644
index 0000000..217c8ce
--- /dev/null
+++ b/test/Transforms/LoopUnroll/unloop.ll
@@ -0,0 +1,429 @@
+; RUN: opt < %s -S -loop-unroll -verify-loop-info | FileCheck %s
+;
+; Unit tests for LoopInfo::updateUnloop.
+
+declare i1 @check() nounwind
+
+; Ensure that tail->inner is removed and rely on verify-loopinfo to
+; check soundness.
+;
+; CHECK: @skiplevelexit
+; CHECK: tail:
+; CHECK-NOT: br
+; CHECK: ret void
+define void @skiplevelexit() nounwind {
+entry:
+ br label %outer
+
+outer:
+ br label %inner
+
+inner:
+ %iv = phi i32 [ 0, %outer ], [ %inc, %tail ]
+ %inc = add i32 %iv, 1
+ %wbucond = call zeroext i1 @check()
+ br i1 %wbucond, label %outer.backedge, label %tail
+
+tail:
+ br i1 false, label %inner, label %exit
+
+outer.backedge:
+ br label %outer
+
+exit:
+ ret void
+}
+
+; Remove the middle loop of a triply nested loop tree.
+; Ensure that only the middle loop is removed and rely on verify-loopinfo to
+; check soundness.
+;
+; CHECK: @unloopNested
+; Outer loop control.
+; CHECK: while.body:
+; CHECK: br i1 %cmp3, label %if.then, label %if.end
+; Inner loop control.
+; CHECK: while.end14.i:
+; CHECK: br i1 %call15.i, label %if.end.i, label %exit
+; Middle loop control should no longer reach %while.cond.
+; Now it is the outer loop backedge.
+; CHECK: exit:
+; CHECK: br label %while.cond.outer
+define void @unloopNested() {
+entry:
+ br label %while.cond.outer
+
+while.cond.outer:
+ br label %while.cond
+
+while.cond:
+ %cmp = call zeroext i1 @check()
+ br i1 %cmp, label %while.body, label %while.end
+
+while.body:
+ %cmp3 = call zeroext i1 @check()
+ br i1 %cmp3, label %if.then, label %if.end
+
+if.then:
+ br label %return
+
+if.end:
+ %cmp.i48 = call zeroext i1 @check()
+ br i1 %cmp.i48, label %if.then.i, label %if.else20.i
+
+if.then.i:
+ %cmp8.i = call zeroext i1 @check()
+ br i1 %cmp8.i, label %merge, label %if.else.i
+
+if.else.i:
+ br label %merge
+
+if.else20.i:
+ %cmp25.i = call zeroext i1 @check()
+ br i1 %cmp25.i, label %merge, label %if.else28.i
+
+if.else28.i:
+ br label %merge
+
+merge:
+ br label %while.cond2.i
+
+while.cond2.i:
+ %cmp.i = call zeroext i1 @check()
+ br i1 %cmp.i, label %while.cond2.backedge.i, label %while.end.i
+
+while.cond2.backedge.i:
+ br label %while.cond2.i
+
+while.end.i:
+ %cmp1114.i = call zeroext i1 @check()
+ br i1 %cmp1114.i, label %while.body12.lr.ph.i, label %while.end14.i
+
+while.body12.lr.ph.i:
+ br label %while.end14.i
+
+while.end14.i:
+ %call15.i = call zeroext i1 @check()
+ br i1 %call15.i, label %if.end.i, label %exit
+
+if.end.i:
+ br label %while.cond2.backedge.i
+
+exit:
+ br i1 false, label %while.cond, label %if.else
+
+if.else:
+ br label %while.cond.outer
+
+while.end:
+ br label %return
+
+return:
+ ret void
+}
+
+; Remove the middle loop of a deeply nested loop tree.
+; Ensure that only the middle loop is removed and rely on verify-loopinfo to
+; check soundness.
+;
+; CHECK: @unloopDeepNested
+; Inner-inner loop control.
+; CHECK: while.cond.us.i:
+; CHECK: br i1 %cmp.us.i, label %next_data.exit, label %while.body.us.i
+; CHECK: if.then.us.i:
+; CHECK: br label %while.cond.us.i
+; Inner loop tail.
+; CHECK: if.else.i:
+; CHECK: br label %while.cond.outer.i
+; Middle loop control (removed).
+; CHECK: valid_data.exit:
+; CHECK-NOT: br
+; CHECK: %cmp = call zeroext i1 @check()
+; Outer loop control.
+; CHECK: copy_data.exit:
+; CHECK: br i1 %cmp38, label %if.then39, label %while.cond.outer
+; Outer-outer loop tail.
+; CHECK: while.cond.outer.outer.backedge:
+; CHECK: br label %while.cond.outer.outer
+define void @unloopDeepNested() nounwind {
+for.cond8.preheader.i:
+ %cmp113.i = call zeroext i1 @check()
+ br i1 %cmp113.i, label %make_data.exit, label %for.body13.lr.ph.i
+
+for.body13.lr.ph.i:
+ br label %make_data.exit
+
+make_data.exit:
+ br label %while.cond.outer.outer
+
+while.cond.outer.outer:
+ br label %while.cond.outer
+
+while.cond.outer:
+ br label %while.cond
+
+while.cond:
+ br label %while.cond.outer.i
+
+while.cond.outer.i:
+ %tmp192.ph.i = call zeroext i1 @check()
+ br i1 %tmp192.ph.i, label %while.cond.outer.split.us.i, label %while.body.loopexit
+
+while.cond.outer.split.us.i:
+ br label %while.cond.us.i
+
+while.cond.us.i:
+ %cmp.us.i = call zeroext i1 @check()
+ br i1 %cmp.us.i, label %next_data.exit, label %while.body.us.i
+
+while.body.us.i:
+ %cmp7.us.i = call zeroext i1 @check()
+ br i1 %cmp7.us.i, label %if.then.us.i, label %if.else.i
+
+if.then.us.i:
+ br label %while.cond.us.i
+
+if.else.i:
+ br label %while.cond.outer.i
+
+next_data.exit:
+ %tmp192.ph.i.lcssa28 = call zeroext i1 @check()
+ br i1 %tmp192.ph.i.lcssa28, label %while.end, label %while.body
+
+while.body.loopexit:
+ br label %while.body
+
+while.body:
+ br label %while.cond.i
+
+while.cond.i:
+ %cmp.i = call zeroext i1 @check()
+ br i1 %cmp.i, label %valid_data.exit, label %while.body.i
+
+while.body.i:
+ %cmp7.i = call zeroext i1 @check()
+ br i1 %cmp7.i, label %valid_data.exit, label %if.end.i
+
+if.end.i:
+ br label %while.cond.i
+
+valid_data.exit:
+ br i1 true, label %if.then, label %while.cond
+
+if.then:
+ %cmp = call zeroext i1 @check()
+ br i1 %cmp, label %if.then12, label %if.end
+
+if.then12:
+ br label %if.end
+
+if.end:
+ %tobool3.i = call zeroext i1 @check()
+ br i1 %tobool3.i, label %copy_data.exit, label %while.body.lr.ph.i
+
+while.body.lr.ph.i:
+ br label %copy_data.exit
+
+copy_data.exit:
+ %cmp38 = call zeroext i1 @check()
+ br i1 %cmp38, label %if.then39, label %while.cond.outer
+
+if.then39:
+ %cmp5.i = call zeroext i1 @check()
+ br i1 %cmp5.i, label %while.cond.outer.outer.backedge, label %for.cond8.preheader.i8.thread
+
+for.cond8.preheader.i8.thread:
+ br label %while.cond.outer.outer.backedge
+
+while.cond.outer.outer.backedge:
+ br label %while.cond.outer.outer
+
+while.end:
+ ret void
+}
+
+; Remove a nested loop with irreducible control flow.
+; Ensure that only the middle loop is removed and rely on verify-loopinfo to
+; check soundness.
+;
+; CHECK: @unloopIrreducible
+; Irreducible loop.
+; CHECK: for.inc117:
+; CHECK: br label %for.cond103t
+; Nested loop (removed).
+; CHECK: for.inc159:
+; CHECK: br label %for.inc163
+define void @unloopIrreducible() nounwind {
+
+entry:
+ br label %for.body
+
+for.body:
+ %cmp2113 = call zeroext i1 @check()
+ br i1 %cmp2113, label %for.body22.lr.ph, label %for.inc163
+
+for.body22.lr.ph:
+ br label %for.body22
+
+for.body22:
+ br label %for.body33
+
+for.body33:
+ br label %for.end
+
+for.end:
+ %cmp424 = call zeroext i1 @check()
+ br i1 %cmp424, label %for.body43.lr.ph, label %for.end93
+
+for.body43.lr.ph:
+ br label %for.end93
+
+for.end93:
+ %cmp96 = call zeroext i1 @check()
+ br i1 %cmp96, label %if.then97, label %for.cond103
+
+if.then97:
+ br label %for.cond103t
+
+for.cond103t:
+ br label %for.cond103
+
+for.cond103:
+ %cmp105 = call zeroext i1 @check()
+ br i1 %cmp105, label %for.body106, label %for.end120
+
+for.body106:
+ %cmp108 = call zeroext i1 @check()
+ br i1 %cmp108, label %if.then109, label %for.inc117
+
+if.then109:
+ br label %for.inc117
+
+for.inc117:
+ br label %for.cond103t
+
+for.end120:
+ br label %for.inc159
+
+for.inc159:
+ br i1 false, label %for.body22, label %for.cond15.for.inc163_crit_edge
+
+for.cond15.for.inc163_crit_edge:
+ br label %for.inc163
+
+for.inc163:
+ %cmp12 = call zeroext i1 @check()
+ br i1 %cmp12, label %for.body, label %for.end166
+
+for.end166:
+ ret void
+
+}
+
+; Remove a loop whose exit branches into a sibling loop.
+; Ensure that only the loop is removed and rely on verify-loopinfo to
+; check soundness.
+;
+; CHECK: @unloopCriticalEdge
+; CHECK: while.cond.outer.i.loopexit.split:
+; CHECK: br label %while.body
+; CHECK: while.body:
+; CHECK: br label %for.end78
+define void @unloopCriticalEdge() nounwind {
+entry:
+ br label %for.cond31
+
+for.cond31:
+ br i1 undef, label %for.body35, label %for.end94
+
+for.body35:
+ br label %while.cond.i.preheader
+
+while.cond.i.preheader:
+ br i1 undef, label %while.cond.i.preheader.split, label %while.cond.outer.i.loopexit.split
+
+while.cond.i.preheader.split:
+ br label %while.cond.i
+
+while.cond.i:
+ br i1 true, label %while.cond.i, label %while.cond.outer.i.loopexit
+
+while.cond.outer.i.loopexit:
+ br label %while.cond.outer.i.loopexit.split
+
+while.cond.outer.i.loopexit.split:
+ br i1 false, label %while.cond.i.preheader, label %Func2.exit
+
+Func2.exit:
+ br label %while.body
+
+while.body:
+ br i1 false, label %while.body, label %while.end
+
+while.end:
+ br label %for.end78
+
+for.end78:
+ br i1 undef, label %Proc2.exit, label %for.cond.i.preheader
+
+for.cond.i.preheader:
+ br label %for.cond.i
+
+for.cond.i:
+ br label %for.cond.i
+
+Proc2.exit:
+ br label %for.cond31
+
+for.end94:
+ ret void
+}
+
+; Test UnloopUpdater::removeBlocksFromAncestors.
+;
+; Check that the loop backedge is removed from the middle loop 1699,
+; but not the inner loop 1676.
+; CHECK: while.body1694:
+; CHECK: br label %while.cond1676
+; CHECK: while.end1699:
+; CHECK: br label %sw.default1711
+define void @removeSubloopBlocks() nounwind {
+entry:
+ br label %tryagain.outer
+
+tryagain.outer: ; preds = %sw.bb304, %entry
+ br label %tryagain
+
+tryagain: ; preds = %while.end1699, %tryagain.outer
+ br i1 undef, label %sw.bb1669, label %sw.bb304
+
+sw.bb304: ; preds = %tryagain
+ br i1 undef, label %return, label %tryagain.outer
+
+sw.bb1669: ; preds = %tryagain
+ br i1 undef, label %sw.default1711, label %while.cond1676
+
+while.cond1676: ; preds = %while.body1694, %sw.bb1669
+ br i1 undef, label %while.end1699, label %while.body1694
+
+while.body1694: ; preds = %while.cond1676
+ br label %while.cond1676
+
+while.end1699: ; preds = %while.cond1676
+ br i1 false, label %tryagain, label %sw.default1711
+
+sw.default1711: ; preds = %while.end1699, %sw.bb1669, %tryagain
+ br label %defchar
+
+defchar: ; preds = %sw.default1711, %sw.bb376
+ br i1 undef, label %if.end2413, label %if.then2368
+
+if.then2368: ; preds = %defchar
+ unreachable
+
+if.end2413: ; preds = %defchar
+ unreachable
+
+return: ; preds = %sw.bb304
+ ret void
+}
diff --git a/test/Transforms/LoopUnswitch/2011-09-26-EHCrash.ll b/test/Transforms/LoopUnswitch/2011-09-26-EHCrash.ll
new file mode 100644
index 0000000..0e3103d
--- /dev/null
+++ b/test/Transforms/LoopUnswitch/2011-09-26-EHCrash.ll
@@ -0,0 +1,67 @@
+; RUN: opt < %s -scalarrepl-ssa -loop-unswitch -disable-output
+; PR11016
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.2"
+
+%class.MyContainer.1.3.19.29 = type { [6 x %class.MyMemVarClass.0.2.18.28*] }
+%class.MyMemVarClass.0.2.18.28 = type { i32 }
+
+define void @_ZN11MyContainer1fEi(%class.MyContainer.1.3.19.29* %this, i32 %doit) uwtable ssp align 2 {
+entry:
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %inc1 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
+ %conv = sext i32 %inc1 to i64
+ %cmp = icmp ult i64 %conv, 6
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %tobool = icmp ne i32 %doit, 0
+ br i1 %tobool, label %for.inc, label %if.then
+
+if.then: ; preds = %for.body
+ %idxprom = sext i32 %inc1 to i64
+ %array_ = getelementptr inbounds %class.MyContainer.1.3.19.29* %this, i32 0, i32 0
+ %arrayidx = getelementptr inbounds [6 x %class.MyMemVarClass.0.2.18.28*]* %array_, i32 0, i64 %idxprom
+ %tmp4 = load %class.MyMemVarClass.0.2.18.28** %arrayidx, align 8, !tbaa !0
+ %isnull = icmp eq %class.MyMemVarClass.0.2.18.28* %tmp4, null
+ br i1 %isnull, label %for.inc, label %delete.notnull
+
+delete.notnull: ; preds = %if.then
+ invoke void @_ZN13MyMemVarClassD1Ev(%class.MyMemVarClass.0.2.18.28* %tmp4)
+ to label %invoke.cont unwind label %lpad
+
+invoke.cont: ; preds = %delete.notnull
+ %0 = bitcast %class.MyMemVarClass.0.2.18.28* %tmp4 to i8*
+ call void @_ZdlPv(i8* %0) nounwind
+ br label %for.inc
+
+lpad: ; preds = %delete.notnull
+ %1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
+ %2 = extractvalue { i8*, i32 } %1, 0
+ %3 = extractvalue { i8*, i32 } %1, 1
+ %4 = bitcast %class.MyMemVarClass.0.2.18.28* %tmp4 to i8*
+ call void @_ZdlPv(i8* %4) nounwind
+ %lpad.val = insertvalue { i8*, i32 } undef, i8* %2, 0
+ %lpad.val7 = insertvalue { i8*, i32 } %lpad.val, i32 %3, 1
+ resume { i8*, i32 } %lpad.val7
+
+for.inc: ; preds = %invoke.cont, %if.then, %for.body
+ %inc = add nsw i32 %inc1, 1
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ ret void
+}
+
+declare void @_ZN13MyMemVarClassD1Ev(%class.MyMemVarClass.0.2.18.28*)
+
+declare i32 @__gxx_personality_v0(...)
+
+declare void @_ZdlPv(i8*) nounwind
+
+!0 = metadata !{metadata !"any pointer", metadata !1}
+!1 = metadata !{metadata !"omnipotent char", metadata !2}
+!2 = metadata !{metadata !"Simple C/C++ TBAA", null}
diff --git a/test/Transforms/LowerAtomic/atomic-load.ll b/test/Transforms/LowerAtomic/atomic-load.ll
index 5b110d6..bc04e88 100644
--- a/test/Transforms/LowerAtomic/atomic-load.ll
+++ b/test/Transforms/LowerAtomic/atomic-load.ll
@@ -1,13 +1,9 @@
; RUN: opt < %s -loweratomic -S | FileCheck %s
-declare i8 @llvm.atomic.load.add.i8.p0i8(i8* %ptr, i8 %delta)
-declare i8 @llvm.atomic.load.nand.i8.p0i8(i8* %ptr, i8 %delta)
-declare i8 @llvm.atomic.load.min.i8.p0i8(i8* %ptr, i8 %delta)
-
define i8 @add() {
; CHECK: @add
%i = alloca i8
- %j = call i8 @llvm.atomic.load.add.i8.p0i8(i8* %i, i8 42)
+ %j = atomicrmw add i8* %i, i8 42 monotonic
; CHECK: [[INST:%[a-z0-9]+]] = load
; CHECK-NEXT: add
; CHECK-NEXT: store
@@ -18,7 +14,7 @@ define i8 @add() {
define i8 @nand() {
; CHECK: @nand
%i = alloca i8
- %j = call i8 @llvm.atomic.load.nand.i8.p0i8(i8* %i, i8 42)
+ %j = atomicrmw nand i8* %i, i8 42 monotonic
; CHECK: [[INST:%[a-z0-9]+]] = load
; CHECK-NEXT: and
; CHECK-NEXT: xor
@@ -30,7 +26,7 @@ define i8 @nand() {
define i8 @min() {
; CHECK: @min
%i = alloca i8
- %j = call i8 @llvm.atomic.load.min.i8.p0i8(i8* %i, i8 42)
+ %j = atomicrmw min i8* %i, i8 42 monotonic
; CHECK: [[INST:%[a-z0-9]+]] = load
; CHECK-NEXT: icmp
; CHECK-NEXT: select
diff --git a/test/Transforms/LowerAtomic/atomic-swap.ll b/test/Transforms/LowerAtomic/atomic-swap.ll
index 0a59c85..5e2f034 100644
--- a/test/Transforms/LowerAtomic/atomic-swap.ll
+++ b/test/Transforms/LowerAtomic/atomic-swap.ll
@@ -1,12 +1,9 @@
; RUN: opt < %s -loweratomic -S | FileCheck %s
-declare i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* %ptr, i8 %cmp, i8 %val)
-declare i8 @llvm.atomic.swap.i8.p0i8(i8* %ptr, i8 %val)
-
define i8 @cmpswap() {
; CHECK: @cmpswap
%i = alloca i8
- %j = call i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* %i, i8 0, i8 42)
+ %j = cmpxchg i8* %i, i8 0, i8 42 monotonic
; CHECK: [[INST:%[a-z0-9]+]] = load
; CHECK-NEXT: icmp
; CHECK-NEXT: select
@@ -18,7 +15,7 @@ define i8 @cmpswap() {
define i8 @swap() {
; CHECK: @swap
%i = alloca i8
- %j = call i8 @llvm.atomic.swap.i8.p0i8(i8* %i, i8 42)
+ %j = atomicrmw xchg i8* %i, i8 42 monotonic
; CHECK: [[INST:%[a-z0-9]+]] = load
; CHECK-NEXT: store
ret i8 %j
diff --git a/test/Transforms/LowerAtomic/barrier.ll b/test/Transforms/LowerAtomic/barrier.ll
index 218c5ba..814d7af 100644
--- a/test/Transforms/LowerAtomic/barrier.ll
+++ b/test/Transforms/LowerAtomic/barrier.ll
@@ -1,10 +1,8 @@
; RUN: opt < %s -loweratomic -S | FileCheck %s
-declare void @llvm.memory.barrier(i1 %ll, i1 %ls, i1 %sl, i1 %ss, i1 %device)
-
define void @barrier() {
; CHECK: @barrier
- call void @llvm.memory.barrier(i1 0, i1 0, i1 0, i1 0, i1 0)
+ fence seq_cst
; CHECK-NEXT: ret
ret void
}
diff --git a/test/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll b/test/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll
deleted file mode 100644
index 9180c15..0000000
--- a/test/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll
+++ /dev/null
@@ -1,16 +0,0 @@
-; RUN: opt < %s -lowersetjmp -disable-output
-
- %struct.jmpenv = type { i32, i8 }
-
-declare void @Perl_sv_setpv()
-
-declare i32 @llvm.setjmp(i32*)
-
-define void @perl_call_sv() {
- call void @Perl_sv_setpv( )
- %tmp.335 = getelementptr %struct.jmpenv* null, i64 0, i32 0 ; <i32*> [#uses=1]
- %tmp.336 = call i32 @llvm.setjmp( i32* null ) ; <i32> [#uses=1]
- store i32 %tmp.336, i32* %tmp.335
- ret void
-}
-
diff --git a/test/Transforms/LowerSetJmp/simpletest.ll b/test/Transforms/LowerSetJmp/simpletest.ll
deleted file mode 100644
index dece840..0000000
--- a/test/Transforms/LowerSetJmp/simpletest.ll
+++ /dev/null
@@ -1,31 +0,0 @@
-; RUN: opt < %s -lowersetjmp -S | grep invoke
-
-@.str_1 = internal constant [13 x i8] c"returned %d\0A\00" ; <[13 x i8]*> [#uses=1]
-
-declare void @llvm.longjmp(i32*, i32)
-
-declare i32 @llvm.setjmp(i32*)
-
-declare void @foo()
-
-define i32 @simpletest() {
- %B = alloca i32 ; <i32*> [#uses=2]
- %Val = call i32 @llvm.setjmp( i32* %B ) ; <i32> [#uses=2]
- %V = icmp ne i32 %Val, 0 ; <i1> [#uses=1]
- br i1 %V, label %LongJumped, label %Normal
-Normal: ; preds = %0
- call void @foo( )
- call void @llvm.longjmp( i32* %B, i32 42 )
- ret i32 0
-LongJumped: ; preds = %0
- ret i32 %Val
-}
-
-declare i32 @printf(i8*, ...)
-
-define i32 @main() {
- %V = call i32 @simpletest( ) ; <i32> [#uses=1]
- call i32 (i8*, ...)* @printf( i8* getelementptr ([13 x i8]* @.str_1, i64 0, i64 0), i32 %V ) ; <i32>:1 [#uses=0]
- ret i32 0
-}
-
diff --git a/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll b/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll
index 50683cf..52a8375 100644
--- a/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll
+++ b/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll
@@ -42,6 +42,6 @@ return: ; preds = %bb6
ret i32 %retval8
}
-declare i32 @_setjmp(%struct.__jmp_buf_tag*)
+declare i32 @_setjmp(%struct.__jmp_buf_tag*) returns_twice
declare void @g()
diff --git a/test/Transforms/Mem2Reg/atomic.ll b/test/Transforms/Mem2Reg/atomic.ll
new file mode 100644
index 0000000..982c413
--- /dev/null
+++ b/test/Transforms/Mem2Reg/atomic.ll
@@ -0,0 +1,12 @@
+; RUN: opt -mem2reg < %s -S | FileCheck %s
+
+; mem2reg is allowed with arbitrary atomic operations (although we only support
+; it for atomic load and store at the moment).
+define i32 @test1(i32 %x) {
+; CHECK: @test1
+; CHECK: ret i32 %x
+ %a = alloca i32
+ store atomic i32 %x, i32* %a seq_cst, align 4
+ %r = load atomic i32* %a seq_cst, align 4
+ ret i32 %r
+}
diff --git a/test/Transforms/Mem2Reg/crash.ll b/test/Transforms/Mem2Reg/crash.ll
index 655549f..59e2c0b 100644
--- a/test/Transforms/Mem2Reg/crash.ll
+++ b/test/Transforms/Mem2Reg/crash.ll
@@ -18,10 +18,13 @@ bb15:
ret i32 %B
lpad86:
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
br label %bb15
}
+declare i32 @__gxx_personality_v0(...)
define i32 @test2() {
diff --git a/test/Transforms/MemCpyOpt/atomic.ll b/test/Transforms/MemCpyOpt/atomic.ll
new file mode 100644
index 0000000..f351e67
--- /dev/null
+++ b/test/Transforms/MemCpyOpt/atomic.ll
@@ -0,0 +1,41 @@
+; RUN: opt -basicaa -memcpyopt -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+@x = global i32 0
+
+declare void @otherf(i32*)
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
+
+; memcpyopt should not touch atomic ops
+define void @test1() nounwind uwtable ssp {
+; CHECK: test1
+; CHECK: store atomic
+ %x = alloca [101 x i32], align 16
+ %bc = bitcast [101 x i32]* %x to i8*
+ call void @llvm.memset.p0i8.i64(i8* %bc, i8 0, i64 400, i32 16, i1 false)
+ %gep1 = getelementptr inbounds [101 x i32]* %x, i32 0, i32 100
+ store atomic i32 0, i32* %gep1 unordered, align 4
+ %gep2 = getelementptr inbounds [101 x i32]* %x, i32 0, i32 0
+ call void @otherf(i32* %gep2)
+ ret void
+}
+
+; memcpyopt across unordered store
+define void @test2() nounwind uwtable ssp {
+; CHECK: test2
+; CHECK: call
+; CHECK-NEXT: store atomic
+; CHECK-NEXT: call
+ %old = alloca i32
+ %new = alloca i32
+ call void @otherf(i32* nocapture %old)
+ store atomic i32 0, i32* @x unordered, align 4
+ %v = load i32* %old
+ store i32 %v, i32* %new
+ call void @otherf(i32* nocapture %new)
+ ret void
+}
+
diff --git a/test/Transforms/ObjCARC/basic.ll b/test/Transforms/ObjCARC/basic.ll
index a6bbf86..575cf42 100644
--- a/test/Transforms/ObjCARC/basic.ll
+++ b/test/Transforms/ObjCARC/basic.ll
@@ -353,13 +353,14 @@ entry:
; CHECK: define void @test10(
; CHECK: @objc_retain(i8* %x)
+; CHECK: @callee
; CHECK: @use_pointer
; CHECK: @objc_release
; CHECK: }
define void @test10(i8* %x) nounwind {
entry:
%0 = call i8* @objc_retain(i8* %x) nounwind
- call void @use_pointer(i8* %x)
+ call void @callee()
call void @use_pointer(i8* %x)
call void @objc_release(i8* %0) nounwind
ret void
@@ -697,6 +698,8 @@ invoke.cont23: ; preds = %if.then12
lpad20: ; preds = %invoke.cont23, %if.then12
%tmp502 = phi double* [ undef, %invoke.cont23 ], [ %self, %if.then12 ]
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
unreachable
if.end: ; preds = %invoke.cont23
@@ -768,7 +771,7 @@ entry:
define void @test23b(i8* %p) {
entry:
%0 = call i8* @objc_retainBlock(i8* %p) nounwind
- call void @use_pointer(i8* %p)
+ call void @callee()
call void @use_pointer(i8* %p)
call void @objc_release(i8* %p) nounwind
ret void
@@ -1569,6 +1572,107 @@ if.end: ; preds = %entry, %if.then
ret void
}
+; When there are adjacent retain+release pairs, the first one is
+; known unnecessary because the presence of the second one means that
+; the first one won't be deleting the object.
+
+; CHECK: define void @test57(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @use_pointer(i8* %x)
+; CHECK-NEXT: call void @use_pointer(i8* %x)
+; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind
+; CHECK-NEXT: call void @use_pointer(i8* %x)
+; CHECK-NEXT: call void @use_pointer(i8* %x)
+; CHECK-NEXT: call void @objc_release(i8* %x) nounwind
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test57(i8* %x) nounwind {
+entry:
+ call i8* @objc_retain(i8* %x) nounwind
+ call void @use_pointer(i8* %x)
+ call void @use_pointer(i8* %x)
+ call void @objc_release(i8* %x) nounwind
+ call i8* @objc_retain(i8* %x) nounwind
+ call void @use_pointer(i8* %x)
+ call void @use_pointer(i8* %x)
+ call void @objc_release(i8* %x) nounwind
+ ret void
+}
+
+; An adjacent retain+release pair is sufficient even if it will be
+; removed itself.
+
+; CHECK: define void @test58(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @use_pointer(i8* %x)
+; CHECK-NEXT: call void @use_pointer(i8* %x)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test58(i8* %x) nounwind {
+entry:
+ call i8* @objc_retain(i8* %x) nounwind
+ call void @use_pointer(i8* %x)
+ call void @use_pointer(i8* %x)
+ call void @objc_release(i8* %x) nounwind
+ call i8* @objc_retain(i8* %x) nounwind
+ call void @objc_release(i8* %x) nounwind
+ ret void
+}
+
+; Don't delete the second retain+release pair in an adjacent set.
+
+; CHECK: define void @test59(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind
+; CHECK-NEXT: call void @use_pointer(i8* %x)
+; CHECK-NEXT: call void @use_pointer(i8* %x)
+; CHECK-NEXT: call void @objc_release(i8* %x) nounwind
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test59(i8* %x) nounwind {
+entry:
+ %a = call i8* @objc_retain(i8* %x) nounwind
+ call void @objc_release(i8* %x) nounwind
+ %b = call i8* @objc_retain(i8* %x) nounwind
+ call void @use_pointer(i8* %x)
+ call void @use_pointer(i8* %x)
+ call void @objc_release(i8* %x) nounwind
+ ret void
+}
+
+; Constant pointers to objects don't need reference counting.
+
+@constptr = external constant i8*
+@something = external global i8*
+
+; CHECK: define void @test60(
+; CHECK-NOT: @objc_
+; CHECK: }
+define void @test60() {
+ %t = load i8** @constptr
+ %s = load i8** @something
+ call i8* @objc_retain(i8* %s)
+ call void @callee()
+ call void @use_pointer(i8* %t)
+ call void @objc_release(i8* %s)
+ ret void
+}
+
+; Constant pointers to objects don't need to be considered related to other
+; pointers.
+
+; CHECK: define void @test61(
+; CHECK-NOT: @objc_
+; CHECK: }
+define void @test61() {
+ %t = load i8** @constptr
+ call i8* @objc_retain(i8* %t)
+ call void @callee()
+ call void @use_pointer(i8* %t)
+ call void @objc_release(i8* %t)
+ ret void
+}
+
declare void @bar(i32 ()*)
; A few real-world testcases.
@@ -1896,3 +2000,5 @@ end: ; preds = %if.end125, %if.end1
}
!0 = metadata !{}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/ObjCARC/cfg-hazards.ll b/test/Transforms/ObjCARC/cfg-hazards.ll
index e3624df..1519423 100644
--- a/test/Transforms/ObjCARC/cfg-hazards.ll
+++ b/test/Transforms/ObjCARC/cfg-hazards.ll
@@ -7,6 +7,7 @@
declare void @use_pointer(i8*)
declare i8* @objc_retain(i8*)
declare void @objc_release(i8*)
+declare void @callee()
; CHECK: define void @test0(
; CHECK: call i8* @objc_retain(
@@ -18,18 +19,18 @@ declare void @objc_release(i8*)
define void @test0(i8* %digits) {
entry:
%tmp1 = call i8* @objc_retain(i8* %digits) nounwind
- call void @use_pointer(i8* %tmp1)
+ call void @use_pointer(i8* %digits)
br label %for.body
for.body: ; preds = %for.body, %entry
%upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
- call void @use_pointer(i8* %tmp1)
+ call void @use_pointer(i8* %digits)
%inc = add i64 %upcDigitIndex.01, 1
%cmp = icmp ult i64 %inc, 12
br i1 %cmp, label %for.body, label %for.end
for.end: ; preds = %for.body
- call void @objc_release(i8* %tmp1) nounwind, !clang.imprecise_release !0
+ call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0
ret void
}
@@ -47,14 +48,14 @@ entry:
for.body: ; preds = %for.body, %entry
%upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
- call void @use_pointer(i8* %tmp1)
- call void @use_pointer(i8* %tmp1)
+ call void @use_pointer(i8* %digits)
+ call void @use_pointer(i8* %digits)
%inc = add i64 %upcDigitIndex.01, 1
%cmp = icmp ult i64 %inc, 12
br i1 %cmp, label %for.body, label %for.end
for.end: ; preds = %for.body
- call void @objc_release(i8* %tmp1) nounwind, !clang.imprecise_release !0
+ call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0
ret void
}
@@ -72,14 +73,324 @@ entry:
for.body: ; preds = %for.body, %entry
%upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
- call void @use_pointer(i8* %tmp1)
+ call void @use_pointer(i8* %digits)
%inc = add i64 %upcDigitIndex.01, 1
%cmp = icmp ult i64 %inc, 12
br i1 %cmp, label %for.body, label %for.end
for.end: ; preds = %for.body
- call void @use_pointer(i8* %tmp1)
- call void @objc_release(i8* %tmp1) nounwind, !clang.imprecise_release !0
+ call void @use_pointer(i8* %digits)
+ call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; Delete nested retain+release pairs around loops.
+
+; CHECK: define void @test3(i8* %a) nounwind {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: br label %loop
+; CHECK-NOT: @objc_
+; CHECK: exit:
+; CHECK-NEXT: call void @objc_release(i8* %a)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test3(i8* %a) nounwind {
+entry:
+ %outer = call i8* @objc_retain(i8* %a) nounwind
+ %inner = call i8* @objc_retain(i8* %a) nounwind
+ br label %loop
+
+loop:
+ call void @callee()
+ store i8 0, i8* %a
+ br i1 undef, label %loop, label %exit
+
+exit:
+ call void @objc_release(i8* %a) nounwind
+ call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; CHECK: define void @test4(i8* %a) nounwind {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: br label %loop
+; CHECK-NOT: @objc_
+; CHECK: exit:
+; CHECK-NEXT: call void @objc_release(i8* %a)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test4(i8* %a) nounwind {
+entry:
+ %outer = call i8* @objc_retain(i8* %a) nounwind
+ %inner = call i8* @objc_retain(i8* %a) nounwind
+ br label %loop
+
+loop:
+ br label %more
+
+more:
+ call void @callee()
+ call void @callee()
+ store i8 0, i8* %a
+ br i1 undef, label %loop, label %exit
+
+exit:
+ call void @objc_release(i8* %a) nounwind
+ call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; CHECK: define void @test5(i8* %a) nounwind {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: call void @callee()
+; CHECK-NEXT: br label %loop
+; CHECK-NOT: @objc_
+; CHECK: exit:
+; CHECK-NEXT: call void @use_pointer(i8* %a)
+; CHECK-NEXT: call void @objc_release(i8* %a)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test5(i8* %a) nounwind {
+entry:
+ %outer = tail call i8* @objc_retain(i8* %a) nounwind
+ %inner = tail call i8* @objc_retain(i8* %a) nounwind
+ call void @callee()
+ br label %loop
+
+loop:
+ br i1 undef, label %true, label %more
+
+true:
+ br label %more
+
+more:
+ br i1 undef, label %exit, label %loop
+
+exit:
+ call void @use_pointer(i8* %a)
+ call void @objc_release(i8* %a) nounwind
+ call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; CHECK: define void @test6(i8* %a) nounwind {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: br label %loop
+; CHECK-NOT: @objc_
+; CHECK: exit:
+; CHECK-NEXT: call void @use_pointer(i8* %a)
+; CHECK-NEXT: call void @objc_release(i8* %a)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test6(i8* %a) nounwind {
+entry:
+ %outer = tail call i8* @objc_retain(i8* %a) nounwind
+ %inner = tail call i8* @objc_retain(i8* %a) nounwind
+ br label %loop
+
+loop:
+ br i1 undef, label %true, label %more
+
+true:
+ call void @callee()
+ br label %more
+
+more:
+ br i1 undef, label %exit, label %loop
+
+exit:
+ call void @use_pointer(i8* %a)
+ call void @objc_release(i8* %a) nounwind
+ call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; CHECK: define void @test7(i8* %a) nounwind {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: call void @callee()
+; CHECK-NEXT: br label %loop
+; CHECK-NOT: @objc_
+; CHECK: exit:
+; CHECK-NEXT: call void @objc_release(i8* %a)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test7(i8* %a) nounwind {
+entry:
+ %outer = tail call i8* @objc_retain(i8* %a) nounwind
+ %inner = tail call i8* @objc_retain(i8* %a) nounwind
+ call void @callee()
+ br label %loop
+
+loop:
+ br i1 undef, label %true, label %more
+
+true:
+ call void @use_pointer(i8* %a)
+ br label %more
+
+more:
+ br i1 undef, label %exit, label %loop
+
+exit:
+ call void @objc_release(i8* %a) nounwind
+ call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; CHECK: define void @test8(i8* %a) nounwind {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: br label %loop
+; CHECK-NOT: @objc_
+; CHECK: exit:
+; CHECK-NEXT: call void @objc_release(i8* %a)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test8(i8* %a) nounwind {
+entry:
+ %outer = tail call i8* @objc_retain(i8* %a) nounwind
+ %inner = tail call i8* @objc_retain(i8* %a) nounwind
+ br label %loop
+
+loop:
+ br i1 undef, label %true, label %more
+
+true:
+ call void @callee()
+ call void @use_pointer(i8* %a)
+ br label %more
+
+more:
+ br i1 undef, label %exit, label %loop
+
+exit:
+ call void @objc_release(i8* %a) nounwind
+ call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; CHECK: define void @test9(i8* %a) nounwind {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label %loop
+; CHECK-NOT: @objc_
+; CHECK: exit:
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test9(i8* %a) nounwind {
+entry:
+ %outer = tail call i8* @objc_retain(i8* %a) nounwind
+ %inner = tail call i8* @objc_retain(i8* %a) nounwind
+ br label %loop
+
+loop:
+ br i1 undef, label %true, label %more
+
+true:
+ call void @use_pointer(i8* %a)
+ br label %more
+
+more:
+ br i1 undef, label %exit, label %loop
+
+exit:
+ call void @objc_release(i8* %a) nounwind
+ call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; CHECK: define void @test10(i8* %a) nounwind {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label %loop
+; CHECK-NOT: @objc_
+; CHECK: exit:
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test10(i8* %a) nounwind {
+entry:
+ %outer = tail call i8* @objc_retain(i8* %a) nounwind
+ %inner = tail call i8* @objc_retain(i8* %a) nounwind
+ br label %loop
+
+loop:
+ br i1 undef, label %true, label %more
+
+true:
+ call void @callee()
+ br label %more
+
+more:
+ br i1 undef, label %exit, label %loop
+
+exit:
+ call void @objc_release(i8* %a) nounwind
+ call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; CHECK: define void @test11(i8* %a) nounwind {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label %loop
+; CHECK-NOT: @objc_
+; CHECK: exit:
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test11(i8* %a) nounwind {
+entry:
+ %outer = tail call i8* @objc_retain(i8* %a) nounwind
+ %inner = tail call i8* @objc_retain(i8* %a) nounwind
+ br label %loop
+
+loop:
+ br i1 undef, label %true, label %more
+
+true:
+ br label %more
+
+more:
+ br i1 undef, label %exit, label %loop
+
+exit:
+ call void @objc_release(i8* %a) nounwind
+ call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; Don't delete anything if they're not balanced.
+
+; CHECK: define void @test12(i8* %a) nounwind {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %outer = tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: %inner = tail call i8* @objc_retain(i8* %a) nounwind
+; CHECK-NEXT: br label %loop
+; CHECK-NOT: @objc_
+; CHECK: exit:
+; CHECK-NEXT: call void @objc_release(i8* %a) nounwind
+; CHECK-NEXT: call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test12(i8* %a) nounwind {
+entry:
+ %outer = tail call i8* @objc_retain(i8* %a) nounwind
+ %inner = tail call i8* @objc_retain(i8* %a) nounwind
+ br label %loop
+
+loop:
+ br i1 undef, label %true, label %more
+
+true:
+ ret void
+
+more:
+ br i1 undef, label %exit, label %loop
+
+exit:
+ call void @objc_release(i8* %a) nounwind
+ call void @objc_release(i8* %a) nounwind, !clang.imprecise_release !0
ret void
}
diff --git a/test/Transforms/ObjCARC/contract-storestrong.ll b/test/Transforms/ObjCARC/contract-storestrong.ll
index 50ed260..25c93f4 100644
--- a/test/Transforms/ObjCARC/contract-storestrong.ll
+++ b/test/Transforms/ObjCARC/contract-storestrong.ll
@@ -25,7 +25,7 @@ entry:
; CHECK: define void @test1(i8* %p) {
; CHECK-NEXT: entry:
; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) nounwind
-; CHECK-NEXT: %tmp = volatile load i8** @x, align 8
+; CHECK-NEXT: %tmp = load volatile i8** @x, align 8
; CHECK-NEXT: store i8* %0, i8** @x, align 8
; CHECK-NEXT: tail call void @objc_release(i8* %tmp) nounwind
; CHECK-NEXT: ret void
@@ -45,7 +45,7 @@ entry:
; CHECK-NEXT: entry:
; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %p) nounwind
; CHECK-NEXT: %tmp = load i8** @x, align 8
-; CHECK-NEXT: volatile store i8* %0, i8** @x, align 8
+; CHECK-NEXT: store volatile i8* %0, i8** @x, align 8
; CHECK-NEXT: tail call void @objc_release(i8* %tmp) nounwind
; CHECK-NEXT: ret void
; CHECK-NEXT: }
diff --git a/test/Transforms/ObjCARC/empty-block.ll b/test/Transforms/ObjCARC/empty-block.ll
new file mode 100644
index 0000000..ca55413
--- /dev/null
+++ b/test/Transforms/ObjCARC/empty-block.ll
@@ -0,0 +1,59 @@
+; RUN: opt -S -objc-arc < %s | FileCheck %s
+; rdar://10210274
+
+%0 = type opaque
+
+declare i8* @objc_retain(i8*)
+
+declare void @objc_release(i8*)
+
+declare i8* @objc_autoreleaseReturnValue(i8*)
+
+; Don't delete the autorelease.
+
+; CHECK: define %0* @test0(
+; CHECK: @objc_retain
+; CHECK: .lr.ph:
+; CHECK-NOT: @objc_r
+; CHECK: @objc_autoreleaseReturnValue
+; CHECK-NOT: @objc_
+; CHECK: }
+define %0* @test0(%0* %buffer) nounwind {
+ %1 = bitcast %0* %buffer to i8*
+ %2 = tail call i8* @objc_retain(i8* %1) nounwind
+ br i1 undef, label %.lr.ph, label %._crit_edge
+
+.lr.ph: ; preds = %.lr.ph, %0
+ br i1 false, label %.lr.ph, label %._crit_edge
+
+._crit_edge: ; preds = %.lr.ph, %0
+ %3 = tail call i8* @objc_retain(i8* %1) nounwind
+ tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0
+ %4 = tail call i8* @objc_autoreleaseReturnValue(i8* %1) nounwind
+ ret %0* %buffer
+}
+
+; Do delete the autorelease, even with the retain in a different block.
+
+; CHECK: define %0* @test1(
+; CHECK-NOT: @objc
+; CHECK: }
+define %0* @test1() nounwind {
+ %buffer = call %0* @foo()
+ %1 = bitcast %0* %buffer to i8*
+ %2 = tail call i8* @objc_retain(i8* %1) nounwind
+ br i1 undef, label %.lr.ph, label %._crit_edge
+
+.lr.ph: ; preds = %.lr.ph, %0
+ br i1 false, label %.lr.ph, label %._crit_edge
+
+._crit_edge: ; preds = %.lr.ph, %0
+ %3 = tail call i8* @objc_retain(i8* %1) nounwind
+ tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0
+ %4 = tail call i8* @objc_autoreleaseReturnValue(i8* %1) nounwind
+ ret %0* %buffer
+}
+
+declare %0* @foo()
+
+!0 = metadata !{}
diff --git a/test/Transforms/ObjCARC/invoke.ll b/test/Transforms/ObjCARC/invoke.ll
index a1b87d2..cf971e4 100644
--- a/test/Transforms/ObjCARC/invoke.ll
+++ b/test/Transforms/ObjCARC/invoke.ll
@@ -27,6 +27,8 @@ invoke.cont: ; preds = %entry
ret void
lpad: ; preds = %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
ret void
}
@@ -56,6 +58,8 @@ invoke.cont: ; preds = %entry
br label %done
lpad: ; preds = %entry
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
call void @callee()
br label %done
@@ -64,4 +68,6 @@ done:
ret void
}
+declare i32 @__gxx_personality_v0(...)
+
!0 = metadata !{}
diff --git a/test/Transforms/ObjCARC/nested.ll b/test/Transforms/ObjCARC/nested.ll
new file mode 100644
index 0000000..9eada8a
--- /dev/null
+++ b/test/Transforms/ObjCARC/nested.ll
@@ -0,0 +1,620 @@
+; RUN: opt -objc-arc -S < %s | FileCheck %s
+
+%struct.__objcFastEnumerationState = type { i64, i8**, i64*, [5 x i64] }
+
+@"\01L_OBJC_METH_VAR_NAME_" = internal global [43 x i8] c"countByEnumeratingWithState:objects:count:\00", section "__TEXT,__objc_methname,cstring_literals", align 1
+@"\01L_OBJC_SELECTOR_REFERENCES_" = internal global i8* getelementptr inbounds ([43 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@g = common global i8* null, align 8
+@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip"
+
+declare void @callee()
+declare i8* @returner()
+declare i8* @objc_retainAutoreleasedReturnValue(i8*)
+declare i8* @objc_retain(i8*)
+declare void @objc_enumerationMutation(i8*)
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
+declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind
+declare void @use(i8*)
+declare void @objc_release(i8*)
+
+!0 = metadata !{}
+
+; Delete a nested retain+release pair.
+
+; CHECK: define void @test0(
+; CHECK: call i8* @objc_retain
+; CHECK-NOT: @objc_retain
+; CHECK: }
+define void @test0(i8* %a) nounwind {
+entry:
+ %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+ %items.ptr = alloca [16 x i8*], align 8
+ %0 = call i8* @objc_retain(i8* %a) nounwind
+ %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+ call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
+ %1 = call i8* @objc_retain(i8* %0) nounwind
+ %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %iszero = icmp eq i64 %call, 0
+ br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+ %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+ %mutationsptr = load i64** %mutationsptr.ptr, align 8
+ %forcoll.initial-mutations = load i64* %mutationsptr, align 8
+ %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+ br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+ %forcoll.count.ph = phi i64 [ %call, %forcoll.loopinit ], [ %call6, %forcoll.refetch ]
+ %tmp7 = icmp ugt i64 %forcoll.count.ph, 1
+ %umax = select i1 %tmp7, i64 %forcoll.count.ph, i64 1
+ br label %forcoll.loopbody
+
+forcoll.loopbody:
+ %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+ %mutationsptr3 = load i64** %mutationsptr.ptr, align 8
+ %statemutations = load i64* %mutationsptr3, align 8
+ %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+ br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+ call void @objc_enumerationMutation(i8* %1)
+ br label %forcoll.notmutated
+
+forcoll.notmutated:
+ %stateitems = load i8*** %stateitems.ptr, align 8
+ %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
+ %3 = load i8** %currentitem.ptr, align 8
+ call void @use(i8* %3)
+ %4 = add i64 %forcoll.index, 1
+ %exitcond = icmp eq i64 %4, %umax
+ br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+ %tmp5 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call6 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp5, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %5 = icmp eq i64 %call6, 0
+ br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+ call void @objc_release(i8* %1) nounwind
+ call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK: define void @test2(
+; CHECK: call i8* @objc_retain
+; CHECK-NOT: @objc_retain
+; CHECK: }
+define void @test2() nounwind {
+entry:
+ %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+ %items.ptr = alloca [16 x i8*], align 8
+ %call = call i8* @returner()
+ %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
+ %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+ call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
+ %1 = call i8* @objc_retain(i8* %0) nounwind
+ %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %iszero = icmp eq i64 %call3, 0
+ br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+ %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+ %mutationsptr = load i64** %mutationsptr.ptr, align 8
+ %forcoll.initial-mutations = load i64* %mutationsptr, align 8
+ %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+ br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+ %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+ %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
+ %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
+ br label %forcoll.loopbody
+
+forcoll.loopbody:
+ %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+ %mutationsptr4 = load i64** %mutationsptr.ptr, align 8
+ %statemutations = load i64* %mutationsptr4, align 8
+ %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+ br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+ call void @objc_enumerationMutation(i8* %1)
+ br label %forcoll.notmutated
+
+forcoll.notmutated:
+ %stateitems = load i8*** %stateitems.ptr, align 8
+ %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
+ %3 = load i8** %currentitem.ptr, align 8
+ call void @use(i8* %3)
+ %4 = add i64 %forcoll.index, 1
+ %exitcond = icmp eq i64 %4, %umax
+ br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+ %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %5 = icmp eq i64 %call7, 0
+ br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+ call void @objc_release(i8* %1) nounwind
+ call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK: define void @test4(
+; CHECK: call i8* @objc_retain
+; CHECK-NOT: @objc_retain
+; CHECK: }
+define void @test4() nounwind {
+entry:
+ %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+ %items.ptr = alloca [16 x i8*], align 8
+ %tmp = load i8** @g, align 8
+ %0 = call i8* @objc_retain(i8* %tmp) nounwind
+ %tmp2 = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+ call void @llvm.memset.p0i8.i64(i8* %tmp2, i8 0, i64 64, i32 8, i1 false)
+ %1 = call i8* @objc_retain(i8* %0) nounwind
+ %tmp4 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp4, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %iszero = icmp eq i64 %call, 0
+ br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+ %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+ %mutationsptr = load i64** %mutationsptr.ptr, align 8
+ %forcoll.initial-mutations = load i64* %mutationsptr, align 8
+ %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+ br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+ %forcoll.count.ph = phi i64 [ %call, %forcoll.loopinit ], [ %call8, %forcoll.refetch ]
+ %tmp9 = icmp ugt i64 %forcoll.count.ph, 1
+ %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1
+ br label %forcoll.loopbody
+
+forcoll.loopbody:
+ %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+ %mutationsptr5 = load i64** %mutationsptr.ptr, align 8
+ %statemutations = load i64* %mutationsptr5, align 8
+ %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+ br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+ call void @objc_enumerationMutation(i8* %1)
+ br label %forcoll.notmutated
+
+forcoll.notmutated:
+ %stateitems = load i8*** %stateitems.ptr, align 8
+ %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
+ %3 = load i8** %currentitem.ptr, align 8
+ call void @use(i8* %3)
+ %4 = add i64 %forcoll.index, 1
+ %exitcond = icmp eq i64 %4, %umax
+ br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+ %tmp7 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call8 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp7, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %5 = icmp eq i64 %call8, 0
+ br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+ call void @objc_release(i8* %1) nounwind
+ call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK: define void @test5(
+; CHECK: call i8* @objc_retain
+; CHECK-NOT: @objc_retain
+; CHECK: }
+define void @test5() nounwind {
+entry:
+ %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+ %items.ptr = alloca [16 x i8*], align 8
+ %call = call i8* @returner()
+ %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
+ call void @callee()
+ %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+ call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
+ %1 = call i8* @objc_retain(i8* %0) nounwind
+ %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %iszero = icmp eq i64 %call3, 0
+ br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+ %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+ %mutationsptr = load i64** %mutationsptr.ptr, align 8
+ %forcoll.initial-mutations = load i64* %mutationsptr, align 8
+ %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+ br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+ %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+ %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
+ %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
+ br label %forcoll.loopbody
+
+forcoll.loopbody:
+ %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+ %mutationsptr4 = load i64** %mutationsptr.ptr, align 8
+ %statemutations = load i64* %mutationsptr4, align 8
+ %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+ br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+ call void @objc_enumerationMutation(i8* %1)
+ br label %forcoll.notmutated
+
+forcoll.notmutated:
+ %stateitems = load i8*** %stateitems.ptr, align 8
+ %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
+ %3 = load i8** %currentitem.ptr, align 8
+ call void @use(i8* %3)
+ %4 = add i64 %forcoll.index, 1
+ %exitcond = icmp eq i64 %4, %umax
+ br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+ %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %5 = icmp eq i64 %call7, 0
+ br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+ call void @objc_release(i8* %1) nounwind
+ call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK: define void @test6(
+; CHECK: call i8* @objc_retain
+; CHECK-NOT: @objc_retain
+; CHECK: }
+define void @test6() nounwind {
+entry:
+ %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+ %items.ptr = alloca [16 x i8*], align 8
+ %call = call i8* @returner()
+ %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
+ %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+ call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
+ %1 = call i8* @objc_retain(i8* %0) nounwind
+ %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %iszero = icmp eq i64 %call3, 0
+ br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+ %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+ %mutationsptr = load i64** %mutationsptr.ptr, align 8
+ %forcoll.initial-mutations = load i64* %mutationsptr, align 8
+ %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+ br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+ %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+ %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
+ %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
+ br label %forcoll.loopbody
+
+forcoll.loopbody:
+ %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+ %mutationsptr4 = load i64** %mutationsptr.ptr, align 8
+ %statemutations = load i64* %mutationsptr4, align 8
+ %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+ br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+ call void @objc_enumerationMutation(i8* %1)
+ br label %forcoll.notmutated
+
+forcoll.notmutated:
+ %stateitems = load i8*** %stateitems.ptr, align 8
+ %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
+ %3 = load i8** %currentitem.ptr, align 8
+ call void @use(i8* %3)
+ %4 = add i64 %forcoll.index, 1
+ %exitcond = icmp eq i64 %4, %umax
+ br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+ %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %5 = icmp eq i64 %call7, 0
+ br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+ call void @objc_release(i8* %1) nounwind
+ call void @callee()
+ call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK: define void @test7(
+; CHECK: call i8* @objc_retain
+; CHECK-NOT: @objc_retain
+; CHECK: }
+define void @test7() nounwind {
+entry:
+ %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+ %items.ptr = alloca [16 x i8*], align 8
+ %call = call i8* @returner()
+ %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
+ call void @callee()
+ %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+ call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
+ %1 = call i8* @objc_retain(i8* %0) nounwind
+ %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %iszero = icmp eq i64 %call3, 0
+ br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+ %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+ %mutationsptr = load i64** %mutationsptr.ptr, align 8
+ %forcoll.initial-mutations = load i64* %mutationsptr, align 8
+ %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+ br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+ %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+ %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
+ %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
+ br label %forcoll.loopbody
+
+forcoll.loopbody:
+ %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+ %mutationsptr4 = load i64** %mutationsptr.ptr, align 8
+ %statemutations = load i64* %mutationsptr4, align 8
+ %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+ br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+ call void @objc_enumerationMutation(i8* %1)
+ br label %forcoll.notmutated
+
+forcoll.notmutated:
+ %stateitems = load i8*** %stateitems.ptr, align 8
+ %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
+ %3 = load i8** %currentitem.ptr, align 8
+ call void @use(i8* %3)
+ %4 = add i64 %forcoll.index, 1
+ %exitcond = icmp eq i64 %4, %umax
+ br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+ %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %5 = icmp eq i64 %call7, 0
+ br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+ call void @objc_release(i8* %1) nounwind
+ call void @callee()
+ call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK: define void @test8(
+; CHECK: call i8* @objc_retain
+; CHECK-NOT: @objc_retain
+; CHECK: }
+define void @test8() nounwind {
+entry:
+ %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+ %items.ptr = alloca [16 x i8*], align 8
+ %call = call i8* @returner()
+ %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
+ %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+ call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
+ %1 = call i8* @objc_retain(i8* %0) nounwind
+ %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %iszero = icmp eq i64 %call3, 0
+ br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+ %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+ %mutationsptr = load i64** %mutationsptr.ptr, align 8
+ %forcoll.initial-mutations = load i64* %mutationsptr, align 8
+ %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+ br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+ %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+ %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
+ %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
+ br label %forcoll.loopbody
+
+forcoll.loopbody:
+ %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.next ]
+ %mutationsptr4 = load i64** %mutationsptr.ptr, align 8
+ %statemutations = load i64* %mutationsptr4, align 8
+ %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+ br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+ call void @objc_enumerationMutation(i8* %1)
+ br label %forcoll.notmutated
+
+forcoll.notmutated:
+ %stateitems = load i8*** %stateitems.ptr, align 8
+ %currentitem.ptr = getelementptr i8** %stateitems, i64 %forcoll.index
+ %3 = load i8** %currentitem.ptr, align 8
+ %tobool = icmp eq i8* %3, null
+ br i1 %tobool, label %forcoll.next, label %if.then
+
+if.then:
+ call void @callee()
+ br label %forcoll.next
+
+forcoll.next:
+ %4 = add i64 %forcoll.index, 1
+ %exitcond = icmp eq i64 %4, %umax
+ br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+ %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %5 = icmp eq i64 %call7, 0
+ br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+ call void @objc_release(i8* %1) nounwind
+ call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK: define void @test9(
+; CHECK: call i8* @objc_retain
+; CHECK: call i8* @objc_retain
+; CHECK-NOT: @objc_retain
+; CHECK: }
+define void @test9() nounwind {
+entry:
+ %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+ %items.ptr = alloca [16 x i8*], align 8
+ %call = call i8* @returner()
+ %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
+ %call1 = call i8* @returner()
+ %1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call1) nounwind
+ %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+ call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
+ %2 = call i8* @objc_retain(i8* %0) nounwind
+ %tmp3 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call4 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp3, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %iszero = icmp eq i64 %call4, 0
+ br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+ %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+ %mutationsptr = load i64** %mutationsptr.ptr, align 8
+ %forcoll.initial-mutations = load i64* %mutationsptr, align 8
+ br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+ %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+ %tmp9 = icmp ugt i64 %forcoll.count.ph, 1
+ %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1
+ br label %forcoll.loopbody
+
+forcoll.loopbody:
+ %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated.forcoll.loopbody_crit_edge ], [ 1, %forcoll.loopbody.outer ]
+ %mutationsptr5 = load i64** %mutationsptr.ptr, align 8
+ %statemutations = load i64* %mutationsptr5, align 8
+ %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+ br i1 %3, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+ call void @objc_enumerationMutation(i8* %2)
+ br label %forcoll.notmutated
+
+forcoll.notmutated:
+ %exitcond = icmp eq i64 %forcoll.index, %umax
+ br i1 %exitcond, label %forcoll.refetch, label %forcoll.notmutated.forcoll.loopbody_crit_edge
+
+forcoll.notmutated.forcoll.loopbody_crit_edge:
+ %phitmp = add i64 %forcoll.index, 1
+ br label %forcoll.loopbody
+
+forcoll.refetch:
+ %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %4 = icmp eq i64 %call7, 0
+ br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+ call void @objc_release(i8* %2) nounwind
+ call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0
+ call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK: define void @test10(
+; CHECK: call i8* @objc_retain
+; CHECK: call i8* @objc_retain
+; CHECK-NOT: @objc_retain
+; CHECK: }
+define void @test10() nounwind {
+entry:
+ %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+ %items.ptr = alloca [16 x i8*], align 8
+ %call = call i8* @returner()
+ %0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
+ %call1 = call i8* @returner()
+ %1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call1) nounwind
+ call void @callee()
+ %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+ call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 8, i1 false)
+ %2 = call i8* @objc_retain(i8* %0) nounwind
+ %tmp3 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call4 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp3, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %iszero = icmp eq i64 %call4, 0
+ br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+ %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+ %mutationsptr = load i64** %mutationsptr.ptr, align 8
+ %forcoll.initial-mutations = load i64* %mutationsptr, align 8
+ br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+ %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+ %tmp9 = icmp ugt i64 %forcoll.count.ph, 1
+ %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1
+ br label %forcoll.loopbody
+
+forcoll.loopbody:
+ %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated.forcoll.loopbody_crit_edge ], [ 1, %forcoll.loopbody.outer ]
+ %mutationsptr5 = load i64** %mutationsptr.ptr, align 8
+ %statemutations = load i64* %mutationsptr5, align 8
+ %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+ br i1 %3, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+ call void @objc_enumerationMutation(i8* %2)
+ br label %forcoll.notmutated
+
+forcoll.notmutated:
+ %exitcond = icmp eq i64 %forcoll.index, %umax
+ br i1 %exitcond, label %forcoll.refetch, label %forcoll.notmutated.forcoll.loopbody_crit_edge
+
+forcoll.notmutated.forcoll.loopbody_crit_edge:
+ %phitmp = add i64 %forcoll.index, 1
+ br label %forcoll.loopbody
+
+forcoll.refetch:
+ %tmp6 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+ %4 = icmp eq i64 %call7, 0
+ br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+ call void @objc_release(i8* %2) nounwind
+ call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0
+ call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0
+ ret void
+}
diff --git a/test/Transforms/ObjCARC/retain-block-alloca.ll b/test/Transforms/ObjCARC/retain-block-alloca.ll
new file mode 100644
index 0000000..468da91
--- /dev/null
+++ b/test/Transforms/ObjCARC/retain-block-alloca.ll
@@ -0,0 +1,54 @@
+; RUN: opt -S -objc-arc < %s | FileCheck %s
+; rdar://10209613
+
+; CHECK: define void @test
+; CHECK: %3 = call i8* @objc_retainBlock(i8* %2) nounwind
+; CHECK: @objc_msgSend
+; CHECK-NEXT: @objc_release(i8* %3)
+
+%0 = type opaque
+%struct.__block_descriptor = type { i64, i64 }
+
+@_NSConcreteStackBlock = external global i8*
+@__block_descriptor_tmp = external hidden constant { i64, i64, i8*, i8*, i8*, i8* }
+@"\01L_OBJC_SELECTOR_REFERENCES_" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+
+define void @test(%0* %array) uwtable {
+entry:
+ %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>, align 8
+ %0 = bitcast %0* %array to i8*
+ %1 = tail call i8* @objc_retain(i8* %0) nounwind
+ %block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 0
+ store i8* bitcast (i8** @_NSConcreteStackBlock to i8*), i8** %block.isa, align 8
+ %block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 1
+ store i32 1107296256, i32* %block.flags, align 8
+ %block.reserved = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 2
+ store i32 0, i32* %block.reserved, align 4
+ %block.invoke = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 3
+ store i8* bitcast (void (i8*)* @__test_block_invoke_0 to i8*), i8** %block.invoke, align 8
+ %block.descriptor = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 4
+ store %struct.__block_descriptor* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @__block_descriptor_tmp to %struct.__block_descriptor*), %struct.__block_descriptor** %block.descriptor, align 8
+ %block.captured = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block, i64 0, i32 5
+ store %0* %array, %0** %block.captured, align 8
+ %2 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %block to i8*
+ %3 = call i8* @objc_retainBlock(i8* %2) nounwind
+ %tmp2 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+ call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* %0, i8* %tmp2, i8* %3)
+ call void @objc_release(i8* %3) nounwind
+ %strongdestroy = load %0** %block.captured, align 8
+ %4 = bitcast %0* %strongdestroy to i8*
+ call void @objc_release(i8* %4) nounwind, !clang.imprecise_release !0
+ ret void
+}
+
+declare i8* @objc_retain(i8*)
+
+declare void @__test_block_invoke_0(i8* nocapture) uwtable
+
+declare i8* @objc_retainBlock(i8*)
+
+declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind
+
+declare void @objc_release(i8*)
+
+!0 = metadata !{}
diff --git a/test/Transforms/ObjCARC/retain-block-side-effects.ll b/test/Transforms/ObjCARC/retain-block-side-effects.ll
new file mode 100644
index 0000000..e84d48f
--- /dev/null
+++ b/test/Transforms/ObjCARC/retain-block-side-effects.ll
@@ -0,0 +1,39 @@
+; RUN: opt -S -objc-arc-aa -basicaa -gvn < %s | FileCheck %s
+; rdar://10050579
+
+; objc_retainBlock stores into %repeater so the load from after the
+; call isn't forwardable from the store before the call.
+
+; CHECK: %tmp16 = call i8* @objc_retainBlock(i8* %tmp15) nounwind
+; CHECK: %tmp17 = bitcast i8* %tmp16 to void ()*
+; CHECK: %tmp18 = load %struct.__block_byref_repeater** %byref.forwarding, align 8
+; CHECK: %repeater12 = getelementptr inbounds %struct.__block_byref_repeater* %tmp18, i64 0, i32 6
+; CHECK: store void ()* %tmp17, void ()** %repeater12, align 8
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+%0 = type opaque
+%struct.__block_byref_repeater = type { i8*, %struct.__block_byref_repeater*, i32, i32, i8*, i8*, void ()* }
+%struct.__block_descriptor = type { i64, i64 }
+
+define void @foo() noreturn {
+entry:
+ %repeater = alloca %struct.__block_byref_repeater, align 8
+ %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i8* }>, align 8
+ %byref.forwarding = getelementptr inbounds %struct.__block_byref_repeater* %repeater, i64 0, i32 1
+ %tmp10 = getelementptr inbounds %struct.__block_byref_repeater* %repeater, i64 0, i32 6
+ store void ()* null, void ()** %tmp10, align 8
+ %block.captured11 = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i8* }>* %block, i64 0, i32 6
+ %tmp14 = bitcast %struct.__block_byref_repeater* %repeater to i8*
+ store i8* %tmp14, i8** %block.captured11, align 8
+ %tmp15 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i8* }>* %block to i8*
+ %tmp16 = call i8* @objc_retainBlock(i8* %tmp15) nounwind
+ %tmp17 = bitcast i8* %tmp16 to void ()*
+ %tmp18 = load %struct.__block_byref_repeater** %byref.forwarding, align 8
+ %repeater12 = getelementptr inbounds %struct.__block_byref_repeater* %tmp18, i64 0, i32 6
+ %tmp13 = load void ()** %repeater12, align 8
+ store void ()* %tmp17, void ()** %repeater12, align 8
+ ret void
+}
+
+declare i8* @objc_retainBlock(i8*)
diff --git a/test/Transforms/ObjCARC/retain-not-declared.ll b/test/Transforms/ObjCARC/retain-not-declared.ll
index e1fe117..41bde01 100644
--- a/test/Transforms/ObjCARC/retain-not-declared.ll
+++ b/test/Transforms/ObjCARC/retain-not-declared.ll
@@ -1,21 +1,23 @@
; RUN: opt -S -objc-arc -objc-arc-contract < %s | FileCheck %s
-; Test that the optimizer can create an objc_retainAutoreleaseReturnValue
-; declaration even if no objc_retain declaration exists.
-; rdar://9401303
-
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
declare i8* @objc_unretainedObject(i8*)
declare i8* @objc_retainAutoreleasedReturnValue(i8*)
declare i8* @objc_autoreleaseReturnValue(i8*)
+declare i8* @objc_msgSend(i8*, i8*, ...)
+declare void @objc_release(i8*)
-; CHECK: define i8* @foo(i8* %p) {
+; Test that the optimizer can create an objc_retainAutoreleaseReturnValue
+; declaration even if no objc_retain declaration exists.
+; rdar://9401303
+
+; CHECK: define i8* @test0(i8* %p) {
; CHECK-NEXT: entry:
; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleaseReturnValue(i8* %p) nounwind
; CHECK-NEXT: ret i8* %0
; CHECK-NEXT: }
-define i8* @foo(i8* %p) {
+define i8* @test0(i8* %p) {
entry:
%call = tail call i8* @objc_unretainedObject(i8* %p)
%0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
@@ -23,3 +25,43 @@ entry:
ret i8* %1
}
+; Properly create the @objc_retain declaration when it doesn't already exist.
+; rdar://9825114
+
+; CHECK: @test1(
+; CHECK: @objc_retain(
+; CHECK: @objc_retain(
+; CHECK: @objc_release(
+; CHECK: @objc_release(
+; CHECK: }
+define void @test1(i8* %call88) nounwind {
+entry:
+ %tmp1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call88) nounwind
+ %call94 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*)*)(i8* %tmp1)
+ to label %invoke.cont93 unwind label %lpad91
+
+invoke.cont93: ; preds = %entry
+ %tmp2 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call94) nounwind
+ call void @objc_release(i8* %tmp1) nounwind
+ invoke void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*)*)(i8* %tmp2)
+ to label %invoke.cont102 unwind label %lpad100
+
+invoke.cont102: ; preds = %invoke.cont93
+ call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0
+ unreachable
+
+lpad91: ; preds = %entry
+ %exn91 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ unreachable
+
+lpad100: ; preds = %invoke.cont93
+ %exn100 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0
+ unreachable
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+!0 = metadata !{}
diff --git a/test/Transforms/ObjCARC/rv.ll b/test/Transforms/ObjCARC/rv.ll
index da53a86..9353a19 100644
--- a/test/Transforms/ObjCARC/rv.ll
+++ b/test/Transforms/ObjCARC/rv.ll
@@ -329,3 +329,14 @@ define void @test23(i8* %p) {
call i8* @objc_autoreleaseReturnValue(i8* %p)
ret void
}
+
+; Don't convert autoreleaseRV to autorelease if the result is returned,
+; even through a bitcast.
+
+; CHECK: define {}* @test24(
+; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %p)
+define {}* @test24(i8* %p) {
+ %t = call i8* @objc_autoreleaseReturnValue(i8* %p)
+ %s = bitcast i8* %p to {}*
+ ret {}* %s
+}
diff --git a/test/Transforms/PhaseOrdering/2010-03-22-empty-baseclass.ll b/test/Transforms/PhaseOrdering/2010-03-22-empty-baseclass.ll
new file mode 100644
index 0000000..8859da8
--- /dev/null
+++ b/test/Transforms/PhaseOrdering/2010-03-22-empty-baseclass.ll
@@ -0,0 +1,162 @@
+; RUN: opt -O2 %s -S -o - | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin11.1"
+
+%"struct.boost::compressed_pair<empty_t,int>" = type { %"struct.boost::details::compressed_pair_imp<empty_t,int,1>" }
+%"struct.boost::details::compressed_pair_imp<empty_t,int,1>" = type { i32 }
+%struct.empty_base_t = type <{ i8 }>
+%struct.empty_t = type <{ i8 }>
+
+@.str = private constant [25 x i8] c"x.second() was clobbered\00", align 1 ; <[25 x i8]*> [#uses=1]
+
+define i32 @main(i32 %argc, i8** %argv) ssp {
+entry:
+ %argc_addr = alloca i32, align 4 ; <i32*> [#uses=1]
+ %argv_addr = alloca i8**, align 8 ; <i8***> [#uses=1]
+ %retval = alloca i32 ; <i32*> [#uses=2]
+ %0 = alloca i32 ; <i32*> [#uses=2]
+ %retval.1 = alloca i8 ; <i8*> [#uses=2]
+ %1 = alloca %struct.empty_base_t ; <%struct.empty_base_t*> [#uses=1]
+ %2 = alloca %struct.empty_base_t* ; <%struct.empty_base_t**> [#uses=1]
+ %x = alloca %"struct.boost::compressed_pair<empty_t,int>" ; <%"struct.boost::compressed_pair<empty_t,int>"*> [#uses=3]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ store i32 %argc, i32* %argc_addr
+ store i8** %argv, i8*** %argv_addr
+ %3 = call i32* @_ZN5boost15compressed_pairI7empty_tiE6secondEv(%"struct.boost::compressed_pair<empty_t,int>"* %x) ssp ; <i32*> [#uses=1]
+ store i32 -3, i32* %3, align 4
+ %4 = call %struct.empty_base_t* @_ZN5boost15compressed_pairI7empty_tiE5firstEv(%"struct.boost::compressed_pair<empty_t,int>"* %x) ssp ; <%struct.empty_base_t*> [#uses=1]
+ store %struct.empty_base_t* %4, %struct.empty_base_t** %2, align 8
+ call void @_ZN7empty_tC1Ev(%struct.empty_base_t* %1) nounwind
+ %5 = call i32* @_ZN5boost15compressed_pairI7empty_tiE6secondEv(%"struct.boost::compressed_pair<empty_t,int>"* %x) ssp ; <i32*> [#uses=1]
+ %6 = load i32* %5, align 4 ; <i32> [#uses=1]
+ %7 = icmp ne i32 %6, -3 ; <i1> [#uses=1]
+ %8 = zext i1 %7 to i8 ; <i8> [#uses=1]
+ store i8 %8, i8* %retval.1, align 1
+ %9 = load i8* %retval.1, align 1 ; <i8> [#uses=1]
+ %toBool = icmp ne i8 %9, 0 ; <i1> [#uses=1]
+ br i1 %toBool, label %bb, label %bb1
+
+bb: ; preds = %entry
+ %10 = call i32 @puts(i8* getelementptr inbounds ([25 x i8]* @.str, i64 0, i64 0)) ; <i32> [#uses=0]
+ call void @abort() noreturn
+ unreachable
+
+bb1: ; preds = %entry
+ store i32 0, i32* %0, align 4
+ %11 = load i32* %0, align 4 ; <i32> [#uses=1]
+ store i32 %11, i32* %retval, align 4
+ br label %return
+
+; CHECK-NOT: x.second() was clobbered
+; CHECK: ret i32
+return: ; preds = %bb1
+ %retval2 = load i32* %retval ; <i32> [#uses=1]
+ ret i32 %retval2
+}
+
+define linkonce_odr void @_ZN12empty_base_tC2Ev(%struct.empty_base_t* %this) nounwind ssp align 2 {
+entry:
+ %this_addr = alloca %struct.empty_base_t*, align 8 ; <%struct.empty_base_t**> [#uses=1]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ store %struct.empty_base_t* %this, %struct.empty_base_t** %this_addr
+ br label %return
+
+return: ; preds = %entry
+ ret void
+}
+
+define linkonce_odr void @_ZN7empty_tC1Ev(%struct.empty_base_t* %this) nounwind ssp align 2 {
+entry:
+ %this_addr = alloca %struct.empty_base_t*, align 8 ; <%struct.empty_base_t**> [#uses=2]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ store %struct.empty_base_t* %this, %struct.empty_base_t** %this_addr
+ %0 = load %struct.empty_base_t** %this_addr, align 8 ; <%struct.empty_base_t*> [#uses=1]
+ call void @_ZN12empty_base_tC2Ev(%struct.empty_base_t* %0) nounwind
+ br label %return
+
+return: ; preds = %entry
+ ret void
+}
+
+define linkonce_odr i32* @_ZN5boost7details19compressed_pair_impI7empty_tiLi1EE6secondEv(%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %this) nounwind ssp align 2 {
+entry:
+ %this_addr = alloca %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*, align 8 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"**> [#uses=2]
+ %retval = alloca i32* ; <i32**> [#uses=2]
+ %0 = alloca i32* ; <i32**> [#uses=2]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ store %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %this, %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"** %this_addr
+ %1 = load %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"** %this_addr, align 8 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*> [#uses=1]
+ %2 = getelementptr inbounds %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %1, i32 0, i32 0 ; <i32*> [#uses=1]
+ store i32* %2, i32** %0, align 8
+ %3 = load i32** %0, align 8 ; <i32*> [#uses=1]
+ store i32* %3, i32** %retval, align 8
+ br label %return
+
+return: ; preds = %entry
+ %retval1 = load i32** %retval ; <i32*> [#uses=1]
+ ret i32* %retval1
+}
+
+define linkonce_odr i32* @_ZN5boost15compressed_pairI7empty_tiE6secondEv(%"struct.boost::compressed_pair<empty_t,int>"* %this) ssp align 2 {
+entry:
+ %this_addr = alloca %"struct.boost::compressed_pair<empty_t,int>"*, align 8 ; <%"struct.boost::compressed_pair<empty_t,int>"**> [#uses=2]
+ %retval = alloca i32* ; <i32**> [#uses=2]
+ %0 = alloca i32* ; <i32**> [#uses=2]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ store %"struct.boost::compressed_pair<empty_t,int>"* %this, %"struct.boost::compressed_pair<empty_t,int>"** %this_addr
+ %1 = load %"struct.boost::compressed_pair<empty_t,int>"** %this_addr, align 8 ; <%"struct.boost::compressed_pair<empty_t,int>"*> [#uses=1]
+ %2 = getelementptr inbounds %"struct.boost::compressed_pair<empty_t,int>"* %1, i32 0, i32 0 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*> [#uses=1]
+ %3 = call i32* @_ZN5boost7details19compressed_pair_impI7empty_tiLi1EE6secondEv(%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %2) nounwind ; <i32*> [#uses=1]
+ store i32* %3, i32** %0, align 8
+ %4 = load i32** %0, align 8 ; <i32*> [#uses=1]
+ store i32* %4, i32** %retval, align 8
+ br label %return
+
+return: ; preds = %entry
+ %retval1 = load i32** %retval ; <i32*> [#uses=1]
+ ret i32* %retval1
+}
+
+define linkonce_odr %struct.empty_base_t* @_ZN5boost7details19compressed_pair_impI7empty_tiLi1EE5firstEv(%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %this) nounwind ssp align 2 {
+entry:
+ %this_addr = alloca %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*, align 8 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"**> [#uses=2]
+ %retval = alloca %struct.empty_base_t* ; <%struct.empty_base_t**> [#uses=2]
+ %0 = alloca %struct.empty_base_t* ; <%struct.empty_base_t**> [#uses=2]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ store %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %this, %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"** %this_addr
+ %1 = load %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"** %this_addr, align 8 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*> [#uses=1]
+ %2 = bitcast %"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %1 to %struct.empty_base_t* ; <%struct.empty_base_t*> [#uses=1]
+ store %struct.empty_base_t* %2, %struct.empty_base_t** %0, align 8
+ %3 = load %struct.empty_base_t** %0, align 8 ; <%struct.empty_base_t*> [#uses=1]
+ store %struct.empty_base_t* %3, %struct.empty_base_t** %retval, align 8
+ br label %return
+
+return: ; preds = %entry
+ %retval1 = load %struct.empty_base_t** %retval ; <%struct.empty_base_t*> [#uses=1]
+ ret %struct.empty_base_t* %retval1
+}
+
+define linkonce_odr %struct.empty_base_t* @_ZN5boost15compressed_pairI7empty_tiE5firstEv(%"struct.boost::compressed_pair<empty_t,int>"* %this) ssp align 2 {
+entry:
+ %this_addr = alloca %"struct.boost::compressed_pair<empty_t,int>"*, align 8 ; <%"struct.boost::compressed_pair<empty_t,int>"**> [#uses=2]
+ %retval = alloca %struct.empty_base_t* ; <%struct.empty_base_t**> [#uses=2]
+ %0 = alloca %struct.empty_base_t* ; <%struct.empty_base_t**> [#uses=2]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ store %"struct.boost::compressed_pair<empty_t,int>"* %this, %"struct.boost::compressed_pair<empty_t,int>"** %this_addr
+ %1 = load %"struct.boost::compressed_pair<empty_t,int>"** %this_addr, align 8 ; <%"struct.boost::compressed_pair<empty_t,int>"*> [#uses=1]
+ %2 = getelementptr inbounds %"struct.boost::compressed_pair<empty_t,int>"* %1, i32 0, i32 0 ; <%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"*> [#uses=1]
+ %3 = call %struct.empty_base_t* @_ZN5boost7details19compressed_pair_impI7empty_tiLi1EE5firstEv(%"struct.boost::details::compressed_pair_imp<empty_t,int,1>"* %2) nounwind ; <%struct.empty_base_t*> [#uses=1]
+ store %struct.empty_base_t* %3, %struct.empty_base_t** %0, align 8
+ %4 = load %struct.empty_base_t** %0, align 8 ; <%struct.empty_base_t*> [#uses=1]
+ store %struct.empty_base_t* %4, %struct.empty_base_t** %retval, align 8
+ br label %return
+
+return: ; preds = %entry
+ %retval1 = load %struct.empty_base_t** %retval ; <%struct.empty_base_t*> [#uses=1]
+ ret %struct.empty_base_t* %retval1
+}
+
+declare i32 @puts(i8*)
+
+declare void @abort() noreturn
diff --git a/test/Transforms/PruneEH/2003-09-14-ExternalCall.ll b/test/Transforms/PruneEH/2003-09-14-ExternalCall.ll
index 679eafd..64aba46 100644
--- a/test/Transforms/PruneEH/2003-09-14-ExternalCall.ll
+++ b/test/Transforms/PruneEH/2003-09-14-ExternalCall.ll
@@ -6,6 +6,9 @@ define void @foo() {
invoke void @External( )
to label %Cont unwind label %Cont
Cont: ; preds = %0, %0
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ cleanup
ret void
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/SCCP/2003-08-26-InvokeHandling.ll b/test/Transforms/SCCP/2003-08-26-InvokeHandling.ll
index 9876375..fb1926e 100644
--- a/test/Transforms/SCCP/2003-08-26-InvokeHandling.ll
+++ b/test/Transforms/SCCP/2003-08-26-InvokeHandling.ll
@@ -8,11 +8,16 @@ Entry:
br i1 %cond, label %Inv, label %Cont
Inv: ; preds = %Entry
invoke void @foo( )
- to label %Ok unwind label %Cont
+ to label %Ok unwind label %LPad
Ok: ; preds = %Inv
br label %Cont
+LPad:
+ %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ catch i8* null
+ br label %Cont
Cont: ; preds = %Ok, %Inv, %Entry
- %X = phi i32 [ 0, %Entry ], [ 1, %Ok ], [ 0, %Inv ] ; <i32> [#uses=1]
+ %X = phi i32 [ 0, %Entry ], [ 1, %Ok ], [ 0, %LPad ] ; <i32> [#uses=1]
ret i32 %X
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/SCCP/2004-11-16-DeadInvoke.ll b/test/Transforms/SCCP/2004-11-16-DeadInvoke.ll
index 5d2c78e..e7eb101 100644
--- a/test/Transforms/SCCP/2004-11-16-DeadInvoke.ll
+++ b/test/Transforms/SCCP/2004-11-16-DeadInvoke.ll
@@ -6,8 +6,13 @@ define void @caller() {
br i1 true, label %T, label %F
F: ; preds = %0
%X = invoke i32 @foo( )
- to label %T unwind label %T ; <i32> [#uses=0]
-T: ; preds = %F, %F, %0
+ to label %T unwind label %LP ; <i32> [#uses=0]
+LP:
+ %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ catch i8* null
+ br label %T
+T:
ret void
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/SCCP/2007-05-16-InvokeCrash.ll b/test/Transforms/SCCP/2007-05-16-InvokeCrash.ll
index b84fe6d..a5a42f1 100644
--- a/test/Transforms/SCCP/2007-05-16-InvokeCrash.ll
+++ b/test/Transforms/SCCP/2007-05-16-InvokeCrash.ll
@@ -31,7 +31,9 @@ bb149: ; preds = %bb114
bb177: ; preds = %bb149
unreachable
cleanup: ; preds = %bb149, %bb114, %bb67
- unwind
+ %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
+ resume { i8*, i32 } %val
}
declare double @sin(double)
@@ -39,3 +41,5 @@ declare double @sin(double)
declare double @log(double)
declare double @sqrt(double)
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/SCCP/2009-01-14-IPSCCP-Invoke.ll b/test/Transforms/SCCP/2009-01-14-IPSCCP-Invoke.ll
index d23ee2b..7546bf5 100644
--- a/test/Transforms/SCCP/2009-01-14-IPSCCP-Invoke.ll
+++ b/test/Transforms/SCCP/2009-01-14-IPSCCP-Invoke.ll
@@ -7,6 +7,8 @@ define i32 @main() {
to label %UnifiedReturnBlock unwind label %lpad
lpad:
+ %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
unreachable
UnifiedReturnBlock:
diff --git a/test/Transforms/SCCP/atomic-load-store.ll b/test/Transforms/SCCP/atomic-load-store.ll
new file mode 100644
index 0000000..09061f0
--- /dev/null
+++ b/test/Transforms/SCCP/atomic-load-store.ll
@@ -0,0 +1,30 @@
+; RUN: opt < %s -ipsccp -S | FileCheck %s
+
+; This transformation is safe for atomic loads and stores; check that it works.
+
+@G = internal global i32 17
+@C = internal constant i32 222
+
+define i32 @test1() {
+ %V = load atomic i32* @G seq_cst, align 4
+ %C = icmp eq i32 %V, 17
+ br i1 %C, label %T, label %F
+T:
+ store atomic i32 17, i32* @G seq_cst, align 4
+ ret i32 %V
+F:
+ store atomic i32 123, i32* @G seq_cst, align 4
+ ret i32 0
+}
+; CHECK: define i32 @test1
+; CHECK-NOT: store
+; CHECK: ret i32 17
+
+define i32 @test2() {
+ %V = load atomic i32* @C seq_cst, align 4
+ ret i32 %V
+}
+
+; CHECK: define i32 @test2
+; CHECK-NOT: load
+; CHECK: ret i32 222
diff --git a/test/Transforms/SCCP/ipsccp-basic.ll b/test/Transforms/SCCP/ipsccp-basic.ll
index b9e3f42..8340f0c 100644
--- a/test/Transforms/SCCP/ipsccp-basic.ll
+++ b/test/Transforms/SCCP/ipsccp-basic.ll
@@ -90,6 +90,8 @@ A:
%c = call i64 @test4c(i64 %b)
ret i64 %c
B:
+ %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ catch i8* null
ret i64 0
}
; CHECK: define i64 @test4b()
@@ -121,6 +123,8 @@ A:
%c = call i64 @test5c({i64,i64} %a)
ret i64 %c
B:
+ %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ catch i8* null
ret i64 0
}
@@ -204,3 +208,22 @@ entry:
ret void
}
+declare i32 @__gxx_personality_v0(...)
+
+;;======================== test10
+
+define i32 @test10a() nounwind {
+entry:
+ %call = call i32 @test10b(i32 undef)
+ ret i32 %call
+; CHECK: define i32 @test10a
+; CHECK: ret i32 0
+}
+
+define internal i32 @test10b(i32 %x) nounwind {
+entry:
+ %r = and i32 %x, 1
+ ret i32 %r
+; CHECK: define internal i32 @test10b
+; CHECK: ret i32 undef
+}
diff --git a/test/Transforms/SCCP/switch.ll b/test/Transforms/SCCP/switch.ll
new file mode 100644
index 0000000..9f93423
--- /dev/null
+++ b/test/Transforms/SCCP/switch.ll
@@ -0,0 +1,13 @@
+; RUN: opt -S -sccp < %s | FileCheck %s
+
+; Make sure we always consider the default edge executable for a switch
+; with no cases.
+declare void @foo()
+define void @test1() {
+; CHECK: define void @test1
+; CHECK: call void @foo()
+ switch i32 undef, label %d []
+d:
+ call void @foo()
+ ret void
+}
diff --git a/test/Transforms/SCCP/undef-resolve.ll b/test/Transforms/SCCP/undef-resolve.ll
index bed561c..a3dddb7 100644
--- a/test/Transforms/SCCP/undef-resolve.ll
+++ b/test/Transforms/SCCP/undef-resolve.ll
@@ -104,3 +104,69 @@ bb1.us-lcssa: ; preds = %control
bb1: ; preds = %bb1.us-lcssa, %bb1.us-lcssa.us
ret i32 0
}
+
+; Make sure SCCP honors the xor "idiom"
+; rdar://9956541
+define i32 @test3() {
+ %t = xor i32 undef, undef
+ ret i32 %t
+; CHECK: @test3
+; CHECK: ret i32 0
+}
+
+; Be conservative with FP ops
+define double @test4(double %x) {
+ %t = fadd double %x, undef
+ ret double %t
+; CHECK: @test4
+; CHECK: fadd double %x, undef
+}
+
+; Make sure casts produce a possible value
+define i32 @test5() {
+ %t = sext i8 undef to i32
+ ret i32 %t
+; CHECK: @test5
+; CHECK: ret i32 0
+}
+
+; Make sure ashr produces a possible value
+define i32 @test6() {
+ %t = ashr i32 undef, 31
+ ret i32 %t
+; CHECK: @test6
+; CHECK: ret i32 -1
+}
+
+; Make sure lshr produces a possible value
+define i32 @test7() {
+ %t = lshr i32 undef, 31
+ ret i32 %t
+; CHECK: @test7
+; CHECK: ret i32 0
+}
+
+; icmp eq with undef simplifies to undef
+define i1 @test8() {
+ %t = icmp eq i32 undef, -1
+ ret i1 %t
+; CHECK: @test8
+; CHECK: ret i1 undef
+}
+
+; Make sure we don't conclude that relational comparisons simplify to undef
+define i1 @test9() {
+ %t = icmp ugt i32 undef, -1
+ ret i1 %t
+; CHECK: @test9
+; CHECK: icmp ugt
+}
+
+; Make sure we handle extractvalue
+define i64 @test10() {
+entry:
+ %e = extractvalue { i64, i64 } undef, 1
+ ret i64 %e
+; CHECK: @test10
+; CHECK: ret i64 undef
+}
diff --git a/test/Transforms/ScalarRepl/2003-10-29-ArrayProblem.ll b/test/Transforms/ScalarRepl/2003-10-29-ArrayProblem.ll
index d754987..00e43a7 100644
--- a/test/Transforms/ScalarRepl/2003-10-29-ArrayProblem.ll
+++ b/test/Transforms/ScalarRepl/2003-10-29-ArrayProblem.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -scalarrepl -S | grep {alloca %T}
+; RUN: opt < %s -scalarrepl -S | grep {alloca %%T}
%T = type { [80 x i8], i32, i32 }
declare i32 @.callback_1(i8*)
diff --git a/test/Transforms/ScalarRepl/2011-09-22-PHISpeculateInvoke.ll b/test/Transforms/ScalarRepl/2011-09-22-PHISpeculateInvoke.ll
new file mode 100644
index 0000000..f98f3e8
--- /dev/null
+++ b/test/Transforms/ScalarRepl/2011-09-22-PHISpeculateInvoke.ll
@@ -0,0 +1,40 @@
+; RUN: opt < %s -scalarrepl -S | FileCheck %s
+; PR10987
+
+; Make sure scalarrepl doesn't move a load across an invoke which could
+; modify the loaded value.
+; (The PHI could theoretically be transformed by splitting the critical
+; edge, but scalarrepl doesn't modify the CFG, at least at the moment.)
+
+declare void @extern_fn(i32*)
+declare i32 @extern_fn2(i32)
+declare i32 @__gcc_personality_v0(i32, i64, i8*, i8*)
+
+define void @odd_fn(i1) noinline {
+ %retptr1 = alloca i32
+ %retptr2 = alloca i32
+ br i1 %0, label %then, label %else
+
+then: ; preds = %2
+ invoke void @extern_fn(i32* %retptr1)
+ to label %join unwind label %unwind
+
+else: ; preds = %2
+ store i32 3, i32* %retptr2
+ br label %join
+
+join: ; preds = %then, %else
+ %storemerge.in = phi i32* [ %retptr2, %else ], [ %retptr1, %then ]
+ %storemerge = load i32* %storemerge.in
+ %x3 = call i32 @extern_fn2(i32 %storemerge)
+ ret void
+
+unwind: ; preds = %then
+ %info = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gcc_personality_v0
+ cleanup
+ call void @extern_fn(i32* null)
+ unreachable
+}
+
+; CHECK: define void @odd_fn
+; CHECK: %storemerge.in = phi i32* [ %retptr2, %else ], [ %retptr1, %then ]
diff --git a/test/Transforms/ScalarRepl/2011-10-11-VectorMemset.ll b/test/Transforms/ScalarRepl/2011-10-11-VectorMemset.ll
new file mode 100644
index 0000000..9e31231
--- /dev/null
+++ b/test/Transforms/ScalarRepl/2011-10-11-VectorMemset.ll
@@ -0,0 +1,22 @@
+; RUN: opt < %s -S -scalarrepl | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin11.0.1"
+
+; CHECK: test
+; CHECK-NOT: alloca
+
+define void @test() nounwind {
+entry:
+ %a156286 = alloca [4 x <4 x float>], align 16
+ br i1 undef, label %cif_done, label %for_test158.preheader
+
+for_test158.preheader: ; preds = %entry
+ %a156286305 = bitcast [4 x <4 x float>]* %a156286 to i8*
+ call void @llvm.memset.p0i8.i64(i8* %a156286305, i8 -1, i64 64, i32 16, i1 false)
+ unreachable
+
+cif_done: ; preds = %entry
+ ret void
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
diff --git a/test/Transforms/ScalarRepl/lifetime.ll b/test/Transforms/ScalarRepl/lifetime.ll
new file mode 100644
index 0000000..3f558a1
--- /dev/null
+++ b/test/Transforms/ScalarRepl/lifetime.ll
@@ -0,0 +1,139 @@
+; RUN: opt -scalarrepl -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @llvm.lifetime.start(i64, i8*)
+declare void @llvm.lifetime.end(i64, i8*)
+
+%t1 = type {i32, i32, i32}
+
+define void @test1() {
+; CHECK: @test1
+ %A = alloca %t1
+ %A1 = getelementptr %t1* %A, i32 0, i32 0
+ %A2 = getelementptr %t1* %A, i32 0, i32 1
+ %A3 = getelementptr %t1* %A, i32 0, i32 2
+ %B = bitcast i32* %A1 to i8*
+ store i32 0, i32* %A1
+ call void @llvm.lifetime.start(i64 -1, i8* %B)
+ ret void
+; CHECK-NEXT: ret void
+}
+
+define void @test2() {
+; CHECK: @test2
+ %A = alloca %t1
+ %A1 = getelementptr %t1* %A, i32 0, i32 0
+ %A2 = getelementptr %t1* %A, i32 0, i32 1
+ %A3 = getelementptr %t1* %A, i32 0, i32 2
+ %B = bitcast i32* %A2 to i8*
+ store i32 0, i32* %A2
+ call void @llvm.lifetime.start(i64 -1, i8* %B)
+ %C = load i32* %A2
+ ret void
+; CHECK: ret void
+}
+
+define void @test3() {
+; CHECK: @test3
+ %A = alloca %t1
+ %A1 = getelementptr %t1* %A, i32 0, i32 0
+ %A2 = getelementptr %t1* %A, i32 0, i32 1
+ %A3 = getelementptr %t1* %A, i32 0, i32 2
+ %B = bitcast i32* %A2 to i8*
+ store i32 0, i32* %A2
+ call void @llvm.lifetime.start(i64 6, i8* %B)
+ %C = load i32* %A2
+ ret void
+; CHECK-NEXT: ret void
+}
+
+define void @test4() {
+; CHECK: @test4
+ %A = alloca %t1
+ %A1 = getelementptr %t1* %A, i32 0, i32 0
+ %A2 = getelementptr %t1* %A, i32 0, i32 1
+ %A3 = getelementptr %t1* %A, i32 0, i32 2
+ %B = bitcast i32* %A2 to i8*
+ store i32 0, i32* %A2
+ call void @llvm.lifetime.start(i64 1, i8* %B)
+ %C = load i32* %A2
+ ret void
+; CHECK-NEXT: ret void
+}
+
+%t2 = type {i32, [4 x i8], i32}
+
+define void @test5() {
+; CHECK: @test5
+ %A = alloca %t2
+; CHECK: alloca{{.*}}i8
+; CHECK: alloca{{.*}}i8
+; CHECK: alloca{{.*}}i8
+
+ %A21 = getelementptr %t2* %A, i32 0, i32 1, i32 0
+ %A22 = getelementptr %t2* %A, i32 0, i32 1, i32 1
+ %A23 = getelementptr %t2* %A, i32 0, i32 1, i32 2
+ %A24 = getelementptr %t2* %A, i32 0, i32 1, i32 3
+; CHECK-NOT: store i8 1
+ store i8 1, i8* %A21
+ store i8 2, i8* %A22
+ store i8 3, i8* %A23
+ store i8 4, i8* %A24
+
+ %A1 = getelementptr %t2* %A, i32 0, i32 0
+ %A2 = getelementptr %t2* %A, i32 0, i32 1, i32 1
+ %A3 = getelementptr %t2* %A, i32 0, i32 2
+ store i8 0, i8* %A2
+ call void @llvm.lifetime.start(i64 5, i8* %A2)
+; CHECK: llvm.lifetime{{.*}}i64 1
+; CHECK: llvm.lifetime{{.*}}i64 1
+; CHECK: llvm.lifetime{{.*}}i64 1
+ %C = load i8* %A2
+ ret void
+}
+
+%t3 = type {[4 x i16], [4 x i8]}
+
+define void @test6() {
+; CHECK: @test6
+ %A = alloca %t3
+; CHECK: alloca i8
+; CHECK: alloca i8
+; CHECK: alloca i8
+
+ %A11 = getelementptr %t3* %A, i32 0, i32 0, i32 0
+ %A12 = getelementptr %t3* %A, i32 0, i32 0, i32 1
+ %A13 = getelementptr %t3* %A, i32 0, i32 0, i32 2
+ %A14 = getelementptr %t3* %A, i32 0, i32 0, i32 3
+ store i16 11, i16* %A11
+ store i16 12, i16* %A12
+ store i16 13, i16* %A13
+ store i16 14, i16* %A14
+; CHECK-NOT: store i16 11
+; CHECK-NOT: store i16 12
+; CHECK-NOT: store i16 13
+; CHECK-NOT: store i16 14
+
+ %A21 = getelementptr %t3* %A, i32 0, i32 1, i32 0
+ %A22 = getelementptr %t3* %A, i32 0, i32 1, i32 1
+ %A23 = getelementptr %t3* %A, i32 0, i32 1, i32 2
+ %A24 = getelementptr %t3* %A, i32 0, i32 1, i32 3
+ store i8 21, i8* %A21
+ store i8 22, i8* %A22
+ store i8 23, i8* %A23
+ store i8 24, i8* %A24
+; CHECK: store i8 21
+; CHECK: store i8 22
+; CHECK: store i8 23
+; CHECK-NOT: store i8 24
+
+ %B = bitcast i16* %A13 to i8*
+ call void @llvm.lifetime.start(i64 7, i8* %B)
+; CHECK: lifetime.start{{.*}}i64 1
+; CHECK: lifetime.start{{.*}}i64 1
+; CHECK: lifetime.start{{.*}}i64 1
+
+ ret void
+}
diff --git a/test/Transforms/ScalarRepl/vector_promote.ll b/test/Transforms/ScalarRepl/vector_promote.ll
index c51ef10..5c82ae4 100644
--- a/test/Transforms/ScalarRepl/vector_promote.ll
+++ b/test/Transforms/ScalarRepl/vector_promote.ll
@@ -86,7 +86,6 @@ define i32 @test5(float %X) { ;; should turn into bitcast.
; CHECK-NEXT: ret i32
}
-
define i64 @test6(<2 x float> %X) {
%X_addr = alloca <2 x float>
store <2 x float> %X, <2 x float>* %X_addr
@@ -98,168 +97,17 @@ define i64 @test6(<2 x float> %X) {
; CHECK: ret i64
}
-define float @test7(<4 x float> %x) {
- %a = alloca <4 x float>
- store <4 x float> %x, <4 x float>* %a
- %p = bitcast <4 x float>* %a to <2 x float>*
- %b = load <2 x float>* %p
- %q = getelementptr <4 x float>* %a, i32 0, i32 2
- %c = load float* %q
- ret float %c
-; CHECK: @test7
-; CHECK-NOT: alloca
-; CHECK: bitcast <4 x float> %x to <2 x double>
-; CHECK-NEXT: extractelement <2 x double>
-; CHECK-NEXT: bitcast double %tmp4 to <2 x float>
-; CHECK-NEXT: extractelement <4 x float>
-}
-
-define void @test8(<4 x float> %x, <2 x float> %y) {
- %a = alloca <4 x float>
- store <4 x float> %x, <4 x float>* %a
- %p = bitcast <4 x float>* %a to <2 x float>*
- store <2 x float> %y, <2 x float>* %p
- ret void
-; CHECK: @test8
-; CHECK-NOT: alloca
-; CHECK: bitcast <4 x float> %x to <2 x double>
-; CHECK-NEXT: bitcast <2 x float> %y to double
-; CHECK-NEXT: insertelement <2 x double>
-; CHECK-NEXT: bitcast <2 x double> %tmp2 to <4 x float>
-}
+%struct.test7 = type { [6 x i32] }
-define i256 @test9(<4 x i256> %x) {
- %a = alloca <4 x i256>
- store <4 x i256> %x, <4 x i256>* %a
- %p = bitcast <4 x i256>* %a to <2 x i256>*
- %b = load <2 x i256>* %p
- %q = getelementptr <4 x i256>* %a, i32 0, i32 2
- %c = load i256* %q
- ret i256 %c
-; CHECK: @test9
-; CHECK-NOT: alloca
-; CHECK: bitcast <4 x i256> %x to <2 x i512>
-; CHECK-NEXT: extractelement <2 x i512>
-; CHECK-NEXT: bitcast i512 %tmp4 to <2 x i256>
-; CHECK-NEXT: extractelement <4 x i256>
-}
-
-define void @test10(<4 x i256> %x, <2 x i256> %y) {
- %a = alloca <4 x i256>
- store <4 x i256> %x, <4 x i256>* %a
- %p = bitcast <4 x i256>* %a to <2 x i256>*
- store <2 x i256> %y, <2 x i256>* %p
- ret void
-; CHECK: @test10
-; CHECK-NOT: alloca
-; CHECK: bitcast <4 x i256> %x to <2 x i512>
-; CHECK-NEXT: bitcast <2 x i256> %y to i512
-; CHECK-NEXT: insertelement <2 x i512>
-; CHECK-NEXT: bitcast <2 x i512> %tmp2 to <4 x i256>
-}
-
-%union.v = type { <2 x i64> }
-
-define void @test11(<2 x i64> %x) {
- %a = alloca %union.v
- %p = getelementptr inbounds %union.v* %a, i32 0, i32 0
- store <2 x i64> %x, <2 x i64>* %p, align 16
- %q = getelementptr inbounds %union.v* %a, i32 0, i32 0
- %r = bitcast <2 x i64>* %q to <4 x float>*
- %b = load <4 x float>* %r, align 16
- ret void
-; CHECK: @test11
-; CHECK-NOT: alloca
-}
-
-define void @test12() {
-entry:
- %a = alloca <64 x i8>, align 64
- store <64 x i8> undef, <64 x i8>* %a, align 64
- %p = bitcast <64 x i8>* %a to <16 x i8>*
- %0 = load <16 x i8>* %p, align 64
- store <16 x i8> undef, <16 x i8>* %p, align 64
- %q = bitcast <16 x i8>* %p to <64 x i8>*
- %1 = load <64 x i8>* %q, align 64
- ret void
-; CHECK: @test12
-; CHECK-NOT: alloca
-; CHECK: extractelement <4 x i128>
-; CHECK: insertelement <4 x i128>
-}
-
-define float @test13(<4 x float> %x, <2 x i32> %y) {
- %a = alloca <4 x float>
- store <4 x float> %x, <4 x float>* %a
- %p = bitcast <4 x float>* %a to <2 x float>*
- %b = load <2 x float>* %p
- %q = getelementptr <4 x float>* %a, i32 0, i32 2
- %c = load float* %q
- %r = bitcast <4 x float>* %a to <2 x i32>*
- store <2 x i32> %y, <2 x i32>* %r
- ret float %c
-; CHECK: @test13
-; CHECK-NOT: alloca
-; CHECK: bitcast <4 x float> %x to i128
-}
-
-define <3 x float> @test14(<3 x float> %x) {
+define void @test7() {
entry:
- %x.addr = alloca <3 x float>, align 16
- %r = alloca <3 x i32>, align 16
- %extractVec = shufflevector <3 x float> %x, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
- %storetmp = bitcast <3 x float>* %x.addr to <4 x float>*
- store <4 x float> %extractVec, <4 x float>* %storetmp, align 16
- %tmp = load <3 x float>* %x.addr, align 16
- %cmp = fcmp une <3 x float> %tmp, zeroinitializer
- %sext = sext <3 x i1> %cmp to <3 x i32>
- %and = and <3 x i32> <i32 1065353216, i32 1065353216, i32 1065353216>, %sext
- %extractVec1 = shufflevector <3 x i32> %and, <3 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
- %storetmp2 = bitcast <3 x i32>* %r to <4 x i32>*
- store <4 x i32> %extractVec1, <4 x i32>* %storetmp2, align 16
- %tmp3 = load <3 x i32>* %r, align 16
- %0 = bitcast <3 x i32> %tmp3 to <3 x float>
- %tmp4 = load <3 x float>* %x.addr, align 16
- ret <3 x float> %tmp4
-; CHECK: @test14
-; CHECK-NOT: alloca
-; CHECK: shufflevector <4 x i32> %extractVec1, <4 x i32> undef, <3 x i32> <i32 0, i32 1, i32 2>
-}
-
-define void @test15(<3 x i64>* sret %agg.result, <3 x i64> %x, <3 x i64> %min) {
-entry:
- %x.addr = alloca <3 x i64>, align 32
- %min.addr = alloca <3 x i64>, align 32
- %extractVec = shufflevector <3 x i64> %x, <3 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
- %storetmp = bitcast <3 x i64>* %x.addr to <4 x i64>*
- store <4 x i64> %extractVec, <4 x i64>* %storetmp, align 32
- %extractVec1 = shufflevector <3 x i64> %min, <3 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
- %storetmp2 = bitcast <3 x i64>* %min.addr to <4 x i64>*
- store <4 x i64> %extractVec1, <4 x i64>* %storetmp2, align 32
- %tmp = load <3 x i64>* %x.addr
- %tmp5 = extractelement <3 x i64> %tmp, i32 0
- %tmp11 = insertelement <3 x i64> %tmp, i64 %tmp5, i32 0
- store <3 x i64> %tmp11, <3 x i64>* %x.addr
- %tmp30 = load <3 x i64>* %x.addr, align 32
- store <3 x i64> %tmp30, <3 x i64>* %agg.result
+ %memtmp = alloca %struct.test7, align 16
+ %0 = bitcast %struct.test7* %memtmp to <4 x i32>*
+ store <4 x i32> zeroinitializer, <4 x i32>* %0, align 16
+ %1 = getelementptr inbounds %struct.test7* %memtmp, i64 0, i32 0, i64 5
+ store i32 0, i32* %1, align 4
ret void
-; CHECK: @test15
-; CHECK-NOT: alloca
-; CHECK: shufflevector <4 x i64> %tmpV2, <4 x i64> undef, <3 x i32> <i32 0, i32 1, i32 2>
-}
-
-define <4 x float> @test16(<4 x float> %x, i64 %y0, i64 %y1) {
-entry:
- %tmp8 = bitcast <4 x float> undef to <2 x double>
- %tmp9 = bitcast i64 %y0 to double
- %tmp10 = insertelement <2 x double> %tmp8, double %tmp9, i32 0
- %tmp11 = bitcast <2 x double> %tmp10 to <4 x float>
- %tmp3 = bitcast <4 x float> %tmp11 to <2 x double>
- %tmp4 = bitcast i64 %y1 to double
- %tmp5 = insertelement <2 x double> %tmp3, double %tmp4, i32 1
- %tmp6 = bitcast <2 x double> %tmp5 to <4 x float>
- ret <4 x float> %tmp6
-; CHECK: @test16
+; CHECK: @test7
; CHECK-NOT: alloca
-; CHECK: bitcast <4 x float> %tmp11 to <2 x double>
+; CHECK: and i192
}
diff --git a/test/Transforms/ScalarRepl/vectors-with-mismatched-elements.ll b/test/Transforms/ScalarRepl/vectors-with-mismatched-elements.ll
new file mode 100644
index 0000000..c3fbdf5
--- /dev/null
+++ b/test/Transforms/ScalarRepl/vectors-with-mismatched-elements.ll
@@ -0,0 +1,27 @@
+; RUN: opt -scalarrepl -S < %s | FileCheck %s
+; rdar://9786827
+
+; SROA should be able to handle the mixed types and eliminate the allocas here.
+
+; TODO: Currently it does this by falling back to integer "bags of bits".
+; With enough cleverness, it should be possible to convert between <3 x i32>
+; and <2 x i64> by using a combination of a bitcast and a shuffle.
+
+; CHECK: {
+; CHECK-NOT: alloca
+; CHECK: }
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
+target triple = "i386-apple-darwin11.0.0"
+
+define <2 x i64> @foo() nounwind {
+entry:
+ %retval = alloca <3 x i32>, align 16
+ %z = alloca <4 x i32>, align 16
+ %tmp = load <4 x i32>* %z
+ %tmp1 = shufflevector <4 x i32> %tmp, <4 x i32> undef, <3 x i32> <i32 0, i32 1, i32 2>
+ store <3 x i32> %tmp1, <3 x i32>* %retval
+ %0 = bitcast <3 x i32>* %retval to <2 x i64>*
+ %1 = load <2 x i64>* %0, align 1
+ ret <2 x i64> %1
+}
diff --git a/test/Transforms/ScalarRepl/volatile.ll b/test/Transforms/ScalarRepl/volatile.ll
index 3ff322e..ab276b0 100644
--- a/test/Transforms/ScalarRepl/volatile.ll
+++ b/test/Transforms/ScalarRepl/volatile.ll
@@ -1,5 +1,5 @@
-; RUN: opt < %s -scalarrepl -S | grep {volatile load}
-; RUN: opt < %s -scalarrepl -S | grep {volatile store}
+; RUN: opt < %s -scalarrepl -S | grep {load volatile}
+; RUN: opt < %s -scalarrepl -S | grep {store volatile}
define i32 @voltest(i32 %T) {
%A = alloca {i32, i32}
diff --git a/test/Transforms/SimplifyCFG/2003-08-05-InvokeCrash.ll b/test/Transforms/SimplifyCFG/2003-08-05-InvokeCrash.ll
index c019931..7551e8f 100644
--- a/test/Transforms/SimplifyCFG/2003-08-05-InvokeCrash.ll
+++ b/test/Transforms/SimplifyCFG/2003-08-05-InvokeCrash.ll
@@ -8,6 +8,9 @@ define i32 @test() {
Ret: ; preds = %0
ret i32 %A
Ret2: ; preds = %0
+ %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ catch i8* null
ret i32 undef
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/SimplifyCFG/2003-08-05-MishandleInvoke.ll b/test/Transforms/SimplifyCFG/2003-08-05-MishandleInvoke.ll
index 15cd773..bc61a75 100644
--- a/test/Transforms/SimplifyCFG/2003-08-05-MishandleInvoke.ll
+++ b/test/Transforms/SimplifyCFG/2003-08-05-MishandleInvoke.ll
@@ -6,7 +6,10 @@ define i32 @test() {
invoke i32 @test( )
to label %Ret unwind label %Ret ; <i32>:1 [#uses=0]
Ret: ; preds = %0, %0
+ %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ catch i8* null
%A = add i32 0, 1 ; <i32> [#uses=1]
ret i32 %A
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll b/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll
index 778aa3b..2ecdc95 100644
--- a/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll
+++ b/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll
@@ -4,6 +4,8 @@ define i1 @foo() {
%X = invoke i1 @foo( )
to label %N unwind label %F ; <i1> [#uses=1]
F: ; preds = %0
+ %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ catch i8* null
ret i1 false
N: ; preds = %0
br i1 %X, label %A, label %B
@@ -13,3 +15,4 @@ B: ; preds = %N
ret i1 true
}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/SimplifyCFG/2006-10-29-InvokeCrash.ll b/test/Transforms/SimplifyCFG/2006-10-29-InvokeCrash.ll
index dba41c9..27d9d8f 100644
--- a/test/Transforms/SimplifyCFG/2006-10-29-InvokeCrash.ll
+++ b/test/Transforms/SimplifyCFG/2006-10-29-InvokeCrash.ll
@@ -275,12 +275,16 @@ invcont153: ; preds = %invcont151
invoke void @_ZN12QFontMetricsD1Ev( %struct.QFontMetrics* %tmp.upgrd.2 )
to label %cleanup171 unwind label %cleanup173
cleanup168: ; preds = %invcont151, %invcont148, %invcont146
+ %val168 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
invoke void @_ZN12QFontMetricsD1Ev( %struct.QFontMetrics* %tmp.upgrd.2 )
to label %cleanup173 unwind label %cleanup173
cleanup171: ; preds = %invcont153
invoke void @_ZN5QFontD1Ev( %struct.QFont* %tmp.upgrd.3 )
to label %finally170 unwind label %cleanup192
cleanup173: ; preds = %cleanup168, %cleanup168, %invcont153, %invcont144
+ %val173 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
invoke void @_ZN5QFontD1Ev( %struct.QFont* %tmp.upgrd.3 )
to label %cleanup192 unwind label %cleanup192
finally170: ; preds = %cleanup171
@@ -300,12 +304,16 @@ cleanup185: ; preds = %invcont181
invoke void @_ZN5QFontD1Ev( %struct.QFont* %font )
to label %cleanup190 unwind label %cleanup192
cleanup187: ; preds = %invcont181, %invcont179, %invcont177
+ %val187 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
invoke void @_ZN5QFontD1Ev( %struct.QFont* %font )
to label %cleanup192 unwind label %cleanup192
cleanup190: ; preds = %cleanup185
invoke void @_ZN16QTextFrameFormatD1Ev( %struct.QTextBlockFormat* %fmt )
to label %cond_next194 unwind label %cleanup329
cleanup192: ; preds = %cleanup187, %cleanup187, %cleanup185, %finally170, %cleanup173, %cleanup173, %cleanup171, %invcont141, %invcont124, %invcont122, %invcont120, %invcont118, %invcont117, %invcont114, %invcont111
+ %val192 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
invoke void @_ZN16QTextFrameFormatD1Ev( %struct.QTextBlockFormat* %fmt )
to label %cleanup329 unwind label %cleanup329
cond_next194: ; preds = %cleanup190, %invcont83
@@ -450,8 +458,10 @@ cleanup328: ; preds = %invcont
call void @_ZN8QPainterD1Ev( %struct.QPainter* %p )
ret void
cleanup329: ; preds = %cond_true319, %cond_true302, %cond_next293, %cond_true277, %cond_true266, %cond_next258, %cond_next244, %cond_next225, %cond_true220, %invcont210, %cond_next208, %cond_false204, %cond_true200, %cond_next194, %cleanup192, %cleanup192, %cleanup190, %invcont106, %invcont104, %invcont103, %invcont100, %invcont98, %invcont94, %cond_false, %invcont83, %invcont79, %invcont57, %invcont51, %invcont45, %cond_next42, %invcont37, %cond_true35, %invcont29, %invcont25, %cond_true24, %cond_next, %entry
+ %val = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
call void @_ZN8QPainterD1Ev( %struct.QPainter* %p )
- unwind
+ resume { i8*, i32 } %val
}
declare void @_ZN6QSizeFC1Edd(%struct.QPointF*, double, double)
@@ -553,3 +563,5 @@ declare i32 @_ZNK8QPrinter12printerStateEv(%struct.QPrinter*)
declare i1 @_ZN8QPrinter7newPageEv(%struct.QPrinter*)
declare void @_ZN8QPainterD1Ev(%struct.QPainter*)
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/SimplifyCFG/2009-01-19-UnconditionalTrappingConstantExpr.ll b/test/Transforms/SimplifyCFG/2009-01-19-UnconditionalTrappingConstantExpr.ll
index 33167bd..568e61c 100644
--- a/test/Transforms/SimplifyCFG/2009-01-19-UnconditionalTrappingConstantExpr.ll
+++ b/test/Transforms/SimplifyCFG/2009-01-19-UnconditionalTrappingConstantExpr.ll
@@ -15,7 +15,7 @@ bb2:
ret i32 42
bb6:
- unwind
+ ret i32 927
}
define i32 @test2(i32 %tmp21, i32 %tmp24, i1 %tmp34) {
@@ -26,6 +26,6 @@ bb5: ; preds = %bb4
bb6:
ret i32 42
bb7:
- unwind
+ ret i32 927
}
diff --git a/test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll b/test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll
index f99cbe1..abf4455 100644
--- a/test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll
+++ b/test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll
@@ -277,12 +277,16 @@ invcont153: ; preds = %invcont151
invoke void @_ZN12QFontMetricsD1Ev( %struct.QFontMetrics* %tmp.upgrd.2 )
to label %cleanup171 unwind label %cleanup173
cleanup168: ; preds = %invcont151, %invcont148, %invcont146
+ %val168 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
invoke void @_ZN12QFontMetricsD1Ev( %struct.QFontMetrics* %tmp.upgrd.2 )
to label %cleanup173 unwind label %cleanup173
cleanup171: ; preds = %invcont153
invoke void @_ZN5QFontD1Ev( %struct.QFont* %tmp.upgrd.3 )
to label %finally170 unwind label %cleanup192
cleanup173: ; preds = %cleanup168, %cleanup168, %invcont153, %invcont144
+ %val173 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
invoke void @_ZN5QFontD1Ev( %struct.QFont* %tmp.upgrd.3 )
to label %cleanup192 unwind label %cleanup192
finally170: ; preds = %cleanup171
@@ -302,12 +306,16 @@ cleanup185: ; preds = %invcont181
invoke void @_ZN5QFontD1Ev( %struct.QFont* %font )
to label %cleanup190 unwind label %cleanup192
cleanup187: ; preds = %invcont181, %invcont179, %invcont177
+ %val187 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
invoke void @_ZN5QFontD1Ev( %struct.QFont* %font )
to label %cleanup192 unwind label %cleanup192
cleanup190: ; preds = %cleanup185
invoke void @_ZN16QTextFrameFormatD1Ev( %struct.QTextBlockFormat* %fmt )
to label %cond_next194 unwind label %cleanup329
cleanup192: ; preds = %cleanup187, %cleanup187, %cleanup185, %finally170, %cleanup173, %cleanup173, %cleanup171, %invcont141, %invcont124, %invcont122, %invcont120, %invcont118, %invcont117, %invcont114, %invcont111
+ %val192 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
invoke void @_ZN16QTextFrameFormatD1Ev( %struct.QTextBlockFormat* %fmt )
to label %cleanup329 unwind label %cleanup329
cond_next194: ; preds = %cleanup190, %invcont83
@@ -452,8 +460,10 @@ cleanup328: ; preds = %invcont
call void @_ZN8QPainterD1Ev( %struct.QPainter* %p )
ret void
cleanup329: ; preds = %cond_true319, %cond_true302, %cond_next293, %cond_true277, %cond_true266, %cond_next258, %cond_next244, %cond_next225, %cond_true220, %invcont210, %cond_next208, %cond_false204, %cond_true200, %cond_next194, %cleanup192, %cleanup192, %cleanup190, %invcont106, %invcont104, %invcont103, %invcont100, %invcont98, %invcont94, %cond_false, %invcont83, %invcont79, %invcont57, %invcont51, %invcont45, %cond_next42, %invcont37, %cond_true35, %invcont29, %invcont25, %cond_true24, %cond_next, %entry
+ %val329 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
call void @_ZN8QPainterD1Ev( %struct.QPainter* %p )
- unwind
+ resume { i8*, i32 } %val329
}
declare void @_ZN6QSizeFC1Edd(%struct.QPointF*, double, double)
@@ -555,3 +565,5 @@ declare i32 @_ZNK8QPrinter12printerStateEv(%struct.QPrinter*)
declare i1 @_ZN8QPrinter7newPageEv(%struct.QPrinter*)
declare void @_ZN8QPainterD1Ev(%struct.QPainter*)
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/SimplifyCFG/2010-03-30-InvokeCrash.ll b/test/Transforms/SimplifyCFG/2010-03-30-InvokeCrash.ll
index ced89cf..7bffa1a 100644
--- a/test/Transforms/SimplifyCFG/2010-03-30-InvokeCrash.ll
+++ b/test/Transforms/SimplifyCFG/2010-03-30-InvokeCrash.ll
@@ -14,5 +14,9 @@ r: ; preds = %entry
ret void
u: ; preds = %entry
- unwind
+ %val = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+ cleanup
+ resume { i8*, i32 } %val
}
+
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/SimplifyCFG/2011-09-05-TrivialLPad.ll b/test/Transforms/SimplifyCFG/2011-09-05-TrivialLPad.ll
new file mode 100644
index 0000000..7558419
--- /dev/null
+++ b/test/Transforms/SimplifyCFG/2011-09-05-TrivialLPad.ll
@@ -0,0 +1,22 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; CHECK-NOT: invoke
+; CHECK-NOT: landingpad
+
+declare void @bar()
+
+define i32 @foo() {
+entry:
+ invoke void @bar()
+ to label %return unwind label %lpad
+
+return:
+ ret i32 0
+
+lpad:
+ %lp = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0
+ cleanup
+ resume { i8*, i32 } %lp
+}
+
+declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)
diff --git a/test/Transforms/SimplifyCFG/BrUnwind.ll b/test/Transforms/SimplifyCFG/BrUnwind.ll
index b19a27d..7ab8faa 100644
--- a/test/Transforms/SimplifyCFG/BrUnwind.ll
+++ b/test/Transforms/SimplifyCFG/BrUnwind.ll
@@ -10,6 +10,6 @@ B: ; preds = %0
call void @test( i1 %C )
br label %X
X: ; preds = %B, %A
- unwind
+ ret void
}
diff --git a/test/Transforms/SimplifyCFG/invoke_unwind.ll b/test/Transforms/SimplifyCFG/invoke_unwind.ll
index 73faa95..ed7ff82 100644
--- a/test/Transforms/SimplifyCFG/invoke_unwind.ll
+++ b/test/Transforms/SimplifyCFG/invoke_unwind.ll
@@ -12,21 +12,9 @@ define i32 @test1() {
to label %1 unwind label %Rethrow
ret i32 0
Rethrow:
- unwind
+ %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
+ catch i8* null
+ resume { i8*, i32 } %exn
}
-
-; Verify that simplifycfg isn't duplicating 'unwind' instructions. Doing this
-; is bad because it discourages commoning.
-define i32 @test2(i1 %c) {
-; CHECK: @test2
-; CHECK: T:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label %F
- br i1 %c, label %T, label %F
-T:
- call void @bar()
- br label %F
-F:
- unwind
-}
+declare i32 @__gxx_personality_v0(...)
diff --git a/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll b/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll
new file mode 100644
index 0000000..65d888e
--- /dev/null
+++ b/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll
@@ -0,0 +1,87 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+
+declare void @bar() nounwind
+
+define i32 @test1(i32* %a, i32 %b, i32* %c, i32 %d) nounwind {
+entry:
+ %tobool = icmp eq i32 %b, 0
+ br i1 %tobool, label %if.else, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.else: ; preds = %entry
+ %tobool3 = icmp eq i32 %d, 0
+ br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4: ; preds = %if.else
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.end7: ; preds = %if.else, %if.then4, %if.then
+ %x.0 = phi i32* [ %a, %if.then ], [ %c, %if.then4 ], [ null, %if.else ]
+ %tmp9 = load i32* %x.0
+ ret i32 %tmp9
+
+; CHECK: @test1
+; CHECK: if.else:
+; CHECK: br label %if.end7
+
+; CHECK: phi i32* [ %a, %if.then ], [ %c, %if.else ]
+}
+
+define i32 @test2(i32* %a, i32 %b, i32* %c, i32 %d) nounwind {
+entry:
+ %tobool = icmp eq i32 %b, 0
+ br i1 %tobool, label %if.else, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.else: ; preds = %entry
+ %tobool3 = icmp eq i32 %d, 0
+ br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4: ; preds = %if.else
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.end7: ; preds = %if.else, %if.then4, %if.then
+ %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+ %tmp9 = load i32* %x.0
+ ret i32 %tmp9
+; CHECK: @test2
+; CHECK: if.else:
+; CHECK: unreachable
+
+; CHECK-NOT: phi
+}
+
+define i32 @test3(i32* %a, i32 %b, i32* %c, i32 %d) nounwind {
+entry:
+ %tobool = icmp eq i32 %b, 0
+ br i1 %tobool, label %if.else, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.else: ; preds = %entry
+ %tobool3 = icmp eq i32 %d, 0
+ br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4: ; preds = %if.else
+ tail call void @bar() nounwind
+ br label %if.end7
+
+if.end7: ; preds = %if.else, %if.then4, %if.then
+ %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+ tail call void @bar() nounwind
+ %tmp9 = load i32* %x.0
+ ret i32 %tmp9
+; CHECK: @test3
+; CHECK: if.end7:
+; CHECK: phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+}
diff --git a/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll b/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll
index 7bca5f5..10d6981 100644
--- a/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll
+++ b/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll
@@ -11,14 +11,14 @@ entry:
br i1 %0, label %bb, label %return
bb: ; preds = %entry
- %1 = volatile load i32* null
+ %1 = load volatile i32* null
unreachable
br label %return
return: ; preds = %entry
ret void
; CHECK: @test1
-; CHECK: volatile load
+; CHECK: load volatile
}
; rdar://7958343
@@ -35,10 +35,53 @@ entry:
; PR7369
define void @test3() nounwind {
entry:
- volatile store i32 4, i32* null
+ store volatile i32 4, i32* null
ret void
; CHECK: @test3
-; CHECK: volatile store i32 4, i32* null
+; CHECK: store volatile i32 4, i32* null
; CHECK: ret
}
+
+; Check store before unreachable.
+define void @test4(i1 %C, i32* %P) {
+; CHECK: @test4
+; CHECK: entry:
+; CHECK-NEXT: br i1 %C
+entry:
+ br i1 %C, label %T, label %F
+T:
+ store volatile i32 0, i32* %P
+ unreachable
+F:
+ ret void
+}
+
+; Check cmpxchg before unreachable.
+define void @test5(i1 %C, i32* %P) {
+; CHECK: @test5
+; CHECK: entry:
+; CHECK-NEXT: br i1 %C
+entry:
+ br i1 %C, label %T, label %F
+T:
+ cmpxchg volatile i32* %P, i32 0, i32 1 seq_cst
+ unreachable
+F:
+ ret void
+}
+
+; Check atomicrmw before unreachable.
+define void @test6(i1 %C, i32* %P) {
+; CHECK: @test6
+; CHECK: entry:
+; CHECK-NEXT: br i1 %C
+entry:
+ br i1 %C, label %T, label %F
+T:
+ atomicrmw volatile xchg i32* %P, i32 0 seq_cst
+ unreachable
+F:
+ ret void
+}
+
diff --git a/test/Transforms/SimplifyLibCalls/StrCmp.ll b/test/Transforms/SimplifyLibCalls/StrCmp.ll
index 7359635..60854d7 100644
--- a/test/Transforms/SimplifyLibCalls/StrCmp.ll
+++ b/test/Transforms/SimplifyLibCalls/StrCmp.ll
@@ -1,28 +1,65 @@
; Test that the StrCmpOptimizer works correctly
-; RUN: opt < %s -simplify-libcalls -S | \
-; RUN: not grep {call.*strcmp}
+; RUN: opt < %s -simplify-libcalls -S | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
@hello = constant [6 x i8] c"hello\00" ; <[6 x i8]*> [#uses=1]
@hell = constant [5 x i8] c"hell\00" ; <[5 x i8]*> [#uses=1]
+@bell = constant [5 x i8] c"bell\00" ; <[5 x i8]*> [#uses=1]
@null = constant [1 x i8] zeroinitializer ; <[1 x i8]*> [#uses=1]
declare i32 @strcmp(i8*, i8*)
-declare i32 @puts(i8*)
-
-define i32 @main() {
- %hello_p = getelementptr [6 x i8]* @hello, i32 0, i32 0 ; <i8*> [#uses=5]
- %hell_p = getelementptr [5 x i8]* @hell, i32 0, i32 0 ; <i8*> [#uses=1]
- %null_p = getelementptr [1 x i8]* @null, i32 0, i32 0 ; <i8*> [#uses=4]
- %temp1 = call i32 @strcmp( i8* %hello_p, i8* %hello_p ) ; <i32> [#uses=1]
- %temp2 = call i32 @strcmp( i8* %null_p, i8* %null_p ) ; <i32> [#uses=1]
- %temp3 = call i32 @strcmp( i8* %hello_p, i8* %null_p ) ; <i32> [#uses=1]
- %temp4 = call i32 @strcmp( i8* %null_p, i8* %hello_p ) ; <i32> [#uses=1]
- %temp5 = call i32 @strcmp( i8* %hell_p, i8* %hello_p ) ; <i32> [#uses=1]
- %rslt1 = add i32 %temp1, %temp2 ; <i32> [#uses=1]
- %rslt2 = add i32 %rslt1, %temp3 ; <i32> [#uses=1]
- %rslt3 = add i32 %rslt2, %temp4 ; <i32> [#uses=1]
- %rslt4 = add i32 %rslt3, %temp5 ; <i32> [#uses=1]
- ret i32 %rslt4
+; strcmp("", x) -> -*x
+define i32 @test1(i8* %str) {
+ %temp1 = call i32 @strcmp(i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0), i8* %str)
+ ret i32 %temp1
+ ; CHECK: @test1
+ ; CHECK: %strcmpload = load i8* %str
+ ; CHECK: %1 = zext i8 %strcmpload to i32
+ ; CHECK: %temp1 = sub i32 0, %1
+ ; CHECK: ret i32 %temp1
+}
+
+; strcmp(x, "") -> *x
+define i32 @test2(i8* %str) {
+ %temp1 = call i32 @strcmp(i8* %str, i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0))
+ ret i32 %temp1
+ ; CHECK: @test2
+ ; CHECK: %strcmpload = load i8* %str
+ ; CHECK: %temp1 = zext i8 %strcmpload to i32
+ ; CHECK: ret i32 %temp1
}
+; strcmp(x, y) -> cnst
+define i32 @test3() {
+ %temp1 = call i32 @strcmp(i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8]* @hello, i32 0, i32 0))
+ ret i32 %temp1
+ ; CHECK: @test3
+ ; CHECK: ret i32 -1
+}
+define i32 @test4() {
+ %temp1 = call i32 @strcmp(i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0))
+ ret i32 %temp1
+ ; CHECK: @test4
+ ; CHECK: ret i32 1
+}
+
+; strcmp(x, y) -> memcmp(x, y, <known length>)
+; (This transform is rather difficult to trigger in a useful manner)
+define i32 @test5(i1 %b) {
+ %sel = select i1 %b, i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8]* @bell, i32 0, i32 0)
+ %temp1 = call i32 @strcmp(i8* getelementptr inbounds ([6 x i8]* @hello, i32 0, i32 0), i8* %sel)
+ ret i32 %temp1
+ ; CHECK: @test5
+ ; CHECK: %memcmp = call i32 @memcmp(i8* getelementptr inbounds ([6 x i8]* @hello, i32 0, i32 0), i8* %sel, i32 5)
+ ; CHECK: ret i32 %memcmp
+}
+
+; strcmp(x,x) -> 0
+define i32 @test6(i8* %str) {
+ %temp1 = call i32 @strcmp(i8* %str, i8* %str)
+ ret i32 %temp1
+ ; CHECK: @test6
+ ; CHECK: ret i32 0
+}
diff --git a/test/Transforms/SimplifyLibCalls/StrNCmp.ll b/test/Transforms/SimplifyLibCalls/StrNCmp.ll
index 8b536a5..0b2a501 100644
--- a/test/Transforms/SimplifyLibCalls/StrNCmp.ll
+++ b/test/Transforms/SimplifyLibCalls/StrNCmp.ll
@@ -1,35 +1,78 @@
-; Test that the StrNCmpOptimizer works correctly
-; RUN: opt < %s -simplify-libcalls -S | \
-; RUN: not grep {call.*strncmp}
+; Test that the StrCmpOptimizer works correctly
+; RUN: opt < %s -simplify-libcalls -S | FileCheck %s
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
-target triple = "i386-apple-darwin9.0"
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
@hello = constant [6 x i8] c"hello\00" ; <[6 x i8]*> [#uses=1]
@hell = constant [5 x i8] c"hell\00" ; <[5 x i8]*> [#uses=1]
+@bell = constant [5 x i8] c"bell\00" ; <[5 x i8]*> [#uses=1]
@null = constant [1 x i8] zeroinitializer ; <[1 x i8]*> [#uses=1]
declare i32 @strncmp(i8*, i8*, i32)
-declare i32 @puts(i8*)
-
-define i32 @main() {
- %hello_p = getelementptr [6 x i8]* @hello, i32 0, i32 0 ; <i8*> [#uses=5]
- %hell_p = getelementptr [5 x i8]* @hell, i32 0, i32 0 ; <i8*> [#uses=1]
- %null_p = getelementptr [1 x i8]* @null, i32 0, i32 0 ; <i8*> [#uses=4]
- %temp1 = call i32 @strncmp( i8* %hello_p, i8* %hello_p, i32 5 ) ; <i32> [#uses=1]
- %temp2 = call i32 @strncmp( i8* %null_p, i8* %null_p, i32 0 ) ; <i32> [#uses=1]
- %temp3 = call i32 @strncmp( i8* %hello_p, i8* %null_p, i32 0 ) ; <i32> [#uses=1]
- %temp4 = call i32 @strncmp( i8* %null_p, i8* %hello_p, i32 0 ) ; <i32> [#uses=1]
- %temp5 = call i32 @strncmp( i8* %hell_p, i8* %hello_p, i32 4 ) ; <i32> [#uses=1]
- %rslt1 = add i32 %temp1, %temp2 ; <i32> [#uses=1]
- %rslt2 = add i32 %rslt1, %temp3 ; <i32> [#uses=1]
- %rslt3 = add i32 %rslt2, %temp4 ; <i32> [#uses=1]
- %rslt4 = add i32 %rslt3, %temp5 ; <i32> [#uses=1]
- ret i32 %rslt4
-}
-
-define i32 @test1(i8* %P, i8* %Q) {
- %cmp = call i32 @strncmp(i8* %P, i8* %Q, i32 1)
- ret i32 %cmp
+; strcmp("", x) -> -*x
+define i32 @test1(i8* %str) {
+ %temp1 = call i32 @strncmp(i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0), i8* %str, i32 10)
+ ret i32 %temp1
+ ; CHECK: @test1
+ ; CHECK: %strcmpload = load i8* %str
+ ; CHECK: %1 = zext i8 %strcmpload to i32
+ ; CHECK: %temp1 = sub i32 0, %1
+ ; CHECK: ret i32 %temp1
+}
+
+; strcmp(x, "") -> *x
+define i32 @test2(i8* %str) {
+ %temp1 = call i32 @strncmp(i8* %str, i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0), i32 10)
+ ret i32 %temp1
+ ; CHECK: @test2
+ ; CHECK: %strcmpload = load i8* %str
+ ; CHECK: %temp1 = zext i8 %strcmpload to i32
+ ; CHECK: ret i32 %temp1
+}
+
+; strncmp(x, y, n) -> cnst
+define i32 @test3() {
+ %temp1 = call i32 @strncmp(i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8]* @hello, i32 0, i32 0), i32 10)
+ ret i32 %temp1
+ ; CHECK: @test3
+ ; CHECK: ret i32 -1
+}
+define i32 @test4() {
+ %temp1 = call i32 @strncmp(i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([1 x i8]* @null, i32 0, i32 0), i32 10)
+ ret i32 %temp1
+ ; CHECK: @test4
+ ; CHECK: ret i32 1
+}
+define i32 @test5() {
+ %temp1 = call i32 @strncmp(i8* getelementptr inbounds ([5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8]* @hello, i32 0, i32 0), i32 4)
+ ret i32 %temp1
+ ; CHECK: @test5
+ ; CHECK: ret i32 0
+}
+
+; strncmp(x,y,1) -> memcmp(x,y,1)
+define i32 @test6(i8* %str1, i8* %str2) {
+ %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 1)
+ ret i32 %temp1
+ ; CHECK: @test6
+ ; CHECK: load i8*
+ ; CHECK: load i8*
+ ; CHECK: sub i32
+}
+
+; strncmp(x,y,0) -> 0
+define i32 @test7(i8* %str1, i8* %str2) {
+ %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 0)
+ ret i32 %temp1
+ ; CHECK: @test7
+ ; CHECK: ret i32 0
+}
+
+; strncmp(x,x,n) -> 0
+define i32 @test8(i8* %str, i32 %n) {
+ %temp1 = call i32 @strncmp(i8* %str, i8* %str, i32 %n)
+ ret i32 %temp1
+ ; CHECK: @test8
+ ; CHECK: ret i32 0
}
diff --git a/test/Transforms/SimplifyLibCalls/memcmp.ll b/test/Transforms/SimplifyLibCalls/memcmp.ll
index ee99501..6ca4dc9 100644
--- a/test/Transforms/SimplifyLibCalls/memcmp.ll
+++ b/test/Transforms/SimplifyLibCalls/memcmp.ll
@@ -10,26 +10,26 @@ declare i32 @memcmp(i8*, i8*, i32)
define void @test(i8* %P, i8* %Q, i32 %N, i32* %IP, i1* %BP) {
%A = call i32 @memcmp( i8* %P, i8* %P, i32 %N ) ; <i32> [#uses=1]
; CHECK-NOT: call {{.*}} memcmp
-; CHECK: volatile store
- volatile store i32 %A, i32* %IP
+; CHECK: store volatile
+ store volatile i32 %A, i32* %IP
%B = call i32 @memcmp( i8* %P, i8* %Q, i32 0 ) ; <i32> [#uses=1]
; CHECK-NOT: call {{.*}} memcmp
-; CHECK: volatile store
- volatile store i32 %B, i32* %IP
+; CHECK: store volatile
+ store volatile i32 %B, i32* %IP
%C = call i32 @memcmp( i8* %P, i8* %Q, i32 1 ) ; <i32> [#uses=1]
; CHECK: load
; CHECK: zext
; CHECK: load
; CHECK: zext
; CHECK: sub
-; CHECK: volatile store
- volatile store i32 %C, i32* %IP
- %F = call i32 @memcmp(i8* getelementptr ([4 x i8]* @hel, i32 0, i32 0),
- i8* getelementptr ([8 x i8]* @hello_u, i32 0, i32 0),
- i32 3)
+; CHECK: store volatile
+ store volatile i32 %C, i32* %IP
+ %F = call i32 @memcmp(i8* getelementptr ([4 x i8]* @hel, i32 0, i32 0),
+ i8* getelementptr ([8 x i8]* @hello_u, i32 0, i32 0),
+ i32 3)
; CHECK-NOT: call {{.*}} memcmp
-; CHECK: volatile store
- volatile store i32 %F, i32* %IP
+; CHECK: store volatile
+ store volatile i32 %F, i32* %IP
ret void
}
diff --git a/test/Transforms/SimplifyLibCalls/pow-to-sqrt.ll b/test/Transforms/SimplifyLibCalls/pow-to-sqrt.ll
index 669b414..0480fdd 100644
--- a/test/Transforms/SimplifyLibCalls/pow-to-sqrt.ll
+++ b/test/Transforms/SimplifyLibCalls/pow-to-sqrt.ll
@@ -7,9 +7,9 @@
; CHECK: define float @foo(float %x) nounwind {
; CHECK: %sqrtf = call float @sqrtf(float %x) nounwind readonly
; CHECK: %fabsf = call float @fabsf(float %sqrtf) nounwind readonly
-; CHECK: %tmp = fcmp oeq float %x, 0xFFF0000000000000
-; CHECK: %tmp1 = select i1 %tmp, float 0x7FF0000000000000, float %fabsf
-; CHECK: ret float %tmp1
+; CHECK: %1 = fcmp oeq float %x, 0xFFF0000000000000
+; CHECK: %retval = select i1 %1, float 0x7FF0000000000000, float %fabsf
+; CHECK: ret float %retval
define float @foo(float %x) nounwind {
%retval = call float @powf(float %x, float 0.5)
@@ -19,9 +19,9 @@ define float @foo(float %x) nounwind {
; CHECK: define double @doo(double %x) nounwind {
; CHECK: %sqrt = call double @sqrt(double %x) nounwind readonly
; CHECK: %fabs = call double @fabs(double %sqrt) nounwind readonly
-; CHECK: %tmp = fcmp oeq double %x, 0xFFF0000000000000
-; CHECK: %tmp1 = select i1 %tmp, double 0x7FF0000000000000, double %fabs
-; CHECK: ret double %tmp1
+; CHECK: %1 = fcmp oeq double %x, 0xFFF0000000000000
+; CHECK: %retval = select i1 %1, double 0x7FF0000000000000, double %fabs
+; CHECK: ret double %retval
; CHECK: }
define double @doo(double %x) nounwind {
diff --git a/test/Transforms/Sink/basic.ll b/test/Transforms/Sink/basic.ll
index 54b7f13..2343372 100644
--- a/test/Transforms/Sink/basic.ll
+++ b/test/Transforms/Sink/basic.ll
@@ -20,3 +20,19 @@ true:
false:
ret i32 0
}
+
+; But don't sink volatile loads...
+
+; CHECK: @foo2
+; CHECK: load volatile
+; CHECK-NEXT: store i32
+
+define i32 @foo2(i1 %z) {
+ %l = load volatile i32* @A
+ store i32 0, i32* @B
+ br i1 %z, label %true, label %false
+true:
+ ret i32 %l
+false:
+ ret i32 0
+}
diff --git a/test/Transforms/StripSymbols/block-address.ll b/test/Transforms/StripSymbols/block-address.ll
new file mode 100644
index 0000000..d22c6b1
--- /dev/null
+++ b/test/Transforms/StripSymbols/block-address.ll
@@ -0,0 +1,23 @@
+; RUN: opt %s -strip -S | FileCheck %s
+; PR10286
+
+@main_addrs = constant [2 x i8*] [i8* blockaddress(@f, %FOO), i8* blockaddress(@f, %BAR)]
+; CHECK: @main_addrs = constant [2 x i8*] [i8* blockaddress(@f, %2), i8* blockaddress(@f, %3)]
+
+declare void @foo() nounwind
+declare void @bar() nounwind
+
+define void @f(i8* %indirect.goto.dest) nounwind uwtable ssp {
+entry:
+ indirectbr i8* %indirect.goto.dest, [label %FOO, label %BAR]
+
+ ; CHECK: indirectbr i8* %0, [label %2, label %3]
+
+FOO:
+ call void @foo()
+ ret void
+
+BAR:
+ call void @bar()
+ ret void
+}
diff --git a/test/Transforms/TailCallElim/dont_reorder_load.ll b/test/Transforms/TailCallElim/dont_reorder_load.ll
index cc273c3..899e115 100644
--- a/test/Transforms/TailCallElim/dont_reorder_load.ll
+++ b/test/Transforms/TailCallElim/dont_reorder_load.ll
@@ -16,7 +16,7 @@ entry:
br i1 %tmp2, label %if, label %else
if: ; preds = %entry
- unwind
+ ret i32 37
else: ; preds = %entry
%tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1]
diff --git a/test/Transforms/TailCallElim/reorder_load.ll b/test/Transforms/TailCallElim/reorder_load.ll
index 7f8af7e..7f5c36e 100644
--- a/test/Transforms/TailCallElim/reorder_load.ll
+++ b/test/Transforms/TailCallElim/reorder_load.ll
@@ -43,7 +43,7 @@ else: ; preds = %entry
br i1 %nullcheck, label %unwind, label %recurse
unwind: ; preds = %else
- unwind
+ unreachable
recurse: ; preds = %else
%tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1]
@@ -89,7 +89,7 @@ else: ; preds = %entry
br i1 %nullcheck, label %unwind, label %recurse
unwind: ; preds = %else
- unwind
+ unreachable
recurse: ; preds = %else
%tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1]
diff --git a/test/Transforms/TailCallElim/setjmp.ll b/test/Transforms/TailCallElim/setjmp.ll
index 7b7fe56..7ef9cb3 100644
--- a/test/Transforms/TailCallElim/setjmp.ll
+++ b/test/Transforms/TailCallElim/setjmp.ll
@@ -1,10 +1,14 @@
; RUN: opt < %s -tailcallelim -S | FileCheck %s
-; Test that we don't tail call in a functions that calls setjmp.
+; Test that we don't tail call in a functions that calls returns_twice
+; functions.
+declare void @bar()
+
+; CHECK: foo1
; CHECK-NOT: tail call void @bar()
-define void @foo(i32* %x) {
+define void @foo1(i32* %x) {
bb:
%tmp75 = tail call i32 @setjmp(i32* %x)
call void @bar()
@@ -13,4 +17,13 @@ bb:
declare i32 @setjmp(i32*)
-declare void @bar()
+; CHECK: foo2
+; CHECK-NOT: tail call void @bar()
+
+define void @foo2(i32* %x) {
+bb:
+ %tmp75 = tail call i32 @zed2(i32* %x)
+ call void @bar()
+ ret void
+}
+declare i32 @zed2(i32*) returns_twice
diff --git a/test/Transforms/TailDup/2003-06-24-Simpleloop.ll b/test/Transforms/TailDup/2003-06-24-Simpleloop.ll
deleted file mode 100644
index d7e45af..0000000
--- a/test/Transforms/TailDup/2003-06-24-Simpleloop.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; RUN: opt < %s -tailduplicate -disable-output
-
-define void @motion_result7() {
-entry:
- br label %endif
-endif: ; preds = %no_exit, %entry
- %i.1 = phi i32 [ %inc, %no_exit ], [ 0, %entry ] ; <i32> [#uses=1]
- %inc = add i32 %i.1, 1 ; <i32> [#uses=1]
- br i1 false, label %no_exit, label %UnifiedExitNode
-no_exit: ; preds = %endif
- br i1 false, label %UnifiedExitNode, label %endif
-UnifiedExitNode: ; preds = %no_exit, %endif
- ret void
-}
-
diff --git a/test/Transforms/TailDup/2003-07-22-InfiniteLoop.ll b/test/Transforms/TailDup/2003-07-22-InfiniteLoop.ll
deleted file mode 100644
index 90f4990..0000000
--- a/test/Transforms/TailDup/2003-07-22-InfiniteLoop.ll
+++ /dev/null
@@ -1,11 +0,0 @@
-; RUN: opt < %s -tailduplicate -disable-output
-
-define i32 @sum() {
-entry:
- br label %loopentry
-loopentry: ; preds = %loopentry, %entry
- %i.0 = phi i32 [ 1, %entry ], [ %tmp.3, %loopentry ] ; <i32> [#uses=1]
- %tmp.3 = add i32 %i.0, 1 ; <i32> [#uses=1]
- br label %loopentry
-}
-
diff --git a/test/Transforms/TailDup/2003-08-23-InvalidatedPointers.ll b/test/Transforms/TailDup/2003-08-23-InvalidatedPointers.ll
deleted file mode 100644
index efe9eae..0000000
--- a/test/Transforms/TailDup/2003-08-23-InvalidatedPointers.ll
+++ /dev/null
@@ -1,29 +0,0 @@
-; RUN: opt < %s -tailduplicate -disable-output
-
-define i32 @sell_haggle() {
-entry:
- br i1 false, label %then.5, label %UnifiedExitNode
-then.5: ; preds = %entry
- br i1 false, label %loopentry.1.preheader, label %else.1
-else.1: ; preds = %then.5
- br label %loopentry.1.preheader
-loopentry.1.preheader: ; preds = %else.1, %then.5
- %final_ask.0 = phi i32 [ 0, %else.1 ], [ 0, %then.5 ] ; <i32> [#uses=2]
- br label %loopentry.1
-loopentry.1: ; preds = %endif.17, %loopentry.1.preheader
- switch i32 0, label %UnifiedExitNode [
- i32 2, label %UnifiedExitNode
- i32 1, label %endif.16
- ]
-endif.16: ; preds = %loopentry.1
- br i1 false, label %then.17, label %UnifiedExitNode
-then.17: ; preds = %endif.16
- br i1 false, label %then.18, label %endif.17
-then.18: ; preds = %then.17
- br i1 false, label %endif.17, label %UnifiedExitNode
-endif.17: ; preds = %then.18, %then.17
- %cur_ask.3 = phi i32 [ %final_ask.0, %then.17 ], [ %final_ask.0, %then.18 ] ; <i32> [#uses=0]
- br i1 false, label %loopentry.1, label %UnifiedExitNode
-UnifiedExitNode: ; preds = %endif.17, %then.18, %endif.16, %loopentry.1, %loopentry.1, %entry
- ret i32 0
-}
diff --git a/test/Transforms/TailDup/2003-08-31-UnreachableBlocks.ll b/test/Transforms/TailDup/2003-08-31-UnreachableBlocks.ll
deleted file mode 100644
index dc64923..0000000
--- a/test/Transforms/TailDup/2003-08-31-UnreachableBlocks.ll
+++ /dev/null
@@ -1,17 +0,0 @@
-; RUN: opt < %s -tailduplicate -disable-output
-
-define i32 @foo() {
-entry:
- br label %return.i
-after_ret.i: ; No predecessors!
- br label %return.i
-return.i: ; preds = %after_ret.i, %entry
- %tmp.3 = ptrtoint i32* null to i32 ; <i32> [#uses=1]
- br label %return.i1
-after_ret.i1: ; No predecessors!
- br label %return.i1
-return.i1: ; preds = %after_ret.i1, %return.i
- %tmp.8 = sub i32 %tmp.3, 0 ; <i32> [#uses=0]
- ret i32 0
-}
-
diff --git a/test/Transforms/TailDup/2004-04-01-DemoteRegToStack.ll b/test/Transforms/TailDup/2004-04-01-DemoteRegToStack.ll
deleted file mode 100644
index c1e5f73..0000000
--- a/test/Transforms/TailDup/2004-04-01-DemoteRegToStack.ll
+++ /dev/null
@@ -1,20 +0,0 @@
-; RUN: opt < %s -tailduplicate -disable-output
-
-define void @interpret() {
-entry:
- br label %retry
-retry: ; preds = %endif.4, %entry
- %tmp.8 = call i32 @interp( ) ; <i32> [#uses=3]
- switch i32 0, label %endif.4 [
- i32 -25, label %return
- i32 -16, label %return
- ]
-endif.4: ; preds = %retry
- br i1 false, label %return, label %retry
-return: ; preds = %endif.4, %retry, %retry
- %result.0 = phi i32 [ %tmp.8, %retry ], [ %tmp.8, %retry ], [ %tmp.8, %endif.4 ] ; <i32> [#uses=0]
- ret void
-}
-
-declare i32 @interp()
-
diff --git a/test/Transforms/TailDup/2008-05-13-InfiniteLoop.ll b/test/Transforms/TailDup/2008-05-13-InfiniteLoop.ll
deleted file mode 100644
index 3e4f0b7..0000000
--- a/test/Transforms/TailDup/2008-05-13-InfiniteLoop.ll
+++ /dev/null
@@ -1,26 +0,0 @@
-; RUN: opt < %s -tailduplicate | llc
-; PR2323
-
-define i32 @func_27(i32 %p_28) nounwind {
-entry:
- %tmp125 = trunc i32 %p_28 to i8 ; <i8> [#uses=1]
- %tmp5.i = icmp eq i8 %tmp125, 0 ; <i1> [#uses=1]
- br i1 %tmp5.i, label %bb8.i, label %bb.i
-
-bb.i: ; preds = %entry
- br label %bb39.i
-
-bb8.i: ; preds = %entry
- br label %bb11.i
-
-bb11.i: ; preds = %bb39.i, %bb8.i
- %tmp126 = trunc i32 %p_28 to i8 ; <i8> [#uses=1]
- br label %bb39.i
-
-bb39.i: ; preds = %bb11.i, %bb.i
- %tmp127 = trunc i32 %p_28 to i8 ; <i8> [#uses=1]
- br label %bb11.i
-
-func_29.exit: ; No predecessors!
- ret i32 undef
-}
diff --git a/test/Transforms/TailDup/2009-07-31-phicrash.ll b/test/Transforms/TailDup/2009-07-31-phicrash.ll
deleted file mode 100644
index ad1a040..0000000
--- a/test/Transforms/TailDup/2009-07-31-phicrash.ll
+++ /dev/null
@@ -1,14 +0,0 @@
-; RUN: opt < %s -tailduplicate -disable-output
-; PR4662
-
-define void @a() {
-BB:
- br label %BB6
-
-BB6:
- %tmp9 = phi i64 [ 0, %BB ], [ 5, %BB34 ]
- br label %BB34
-
-BB34:
- br label %BB6
-}
diff --git a/test/Transforms/TailDup/MergeTest.ll b/test/Transforms/TailDup/MergeTest.ll
deleted file mode 100644
index 2224283..0000000
--- a/test/Transforms/TailDup/MergeTest.ll
+++ /dev/null
@@ -1,27 +0,0 @@
-; RUN: opt < %s -tailduplicate -taildup-threshold=2 -S | grep add | not grep uses=1
-
-define i32 @test1(i1 %C, i32 %A, i32* %P) {
-entry:
- br i1 %C, label %L1, label %L2
-L1: ; preds = %entry
- store i32 1, i32* %P
- br label %L2
-L2: ; preds = %L1, %entry
- %X = add i32 %A, 17 ; <i32> [#uses=1]
- ret i32 %X
-}
-
-define i32 @test2(i1 %C, i32 %A, i32* %P) {
-entry:
- br i1 %C, label %L1, label %L2
-L1: ; preds = %entry
- store i32 1, i32* %P
- br label %L3
-L2: ; preds = %entry
- store i32 7, i32* %P
- br label %L3
-L3: ; preds = %L2, %L1
- %X = add i32 %A, 17 ; <i32> [#uses=1]
- ret i32 %X
-}
-
diff --git a/test/Transforms/TailDup/PHIUpdateTest.ll b/test/Transforms/TailDup/PHIUpdateTest.ll
deleted file mode 100644
index 38d8ebf..0000000
--- a/test/Transforms/TailDup/PHIUpdateTest.ll
+++ /dev/null
@@ -1,16 +0,0 @@
-; This test checks to make sure phi nodes are updated properly
-;
-; RUN: opt < %s -tailduplicate -disable-output
-
-define i32 @test(i1 %c, i32 %X, i32 %Y) {
- br label %L
-L: ; preds = %F, %0
- %A = add i32 %X, %Y ; <i32> [#uses=1]
- br i1 %c, label %T, label %F
-F: ; preds = %L
- br i1 %c, label %L, label %T
-T: ; preds = %F, %L
- %V = phi i32 [ %A, %L ], [ 0, %F ] ; <i32> [#uses=1]
- ret i32 %V
-}
-
diff --git a/test/Transforms/TailDup/X86/if-tail-dup.ll b/test/Transforms/TailDup/X86/if-tail-dup.ll
deleted file mode 100644
index 2e4f5be..0000000
--- a/test/Transforms/TailDup/X86/if-tail-dup.ll
+++ /dev/null
@@ -1,49 +0,0 @@
-; RUN: opt < %s -tailduplicate | \
-; RUN: llc -march=x86 -o %t
-; RUN: grep {\\\<je\\\>} %t
-; RUN: not grep jmp %t
-; END.
-; This should have no unconditional jumps in it. The C source is:
-
-;void foo(int c, int* P) {
-; if (c & 1) P[0] = 1;
-; if (c & 2) P[1] = 1;
-; if (c & 4) P[2] = 1;
-; if (c & 8) P[3] = 1;
-;}
-
-define void @foo(i32 %c, i32* %P) {
-entry:
- %tmp1 = and i32 %c, 1 ; <i32> [#uses=1]
- %tmp1.upgrd.1 = icmp eq i32 %tmp1, 0 ; <i1> [#uses=1]
- br i1 %tmp1.upgrd.1, label %cond_next, label %cond_true
-cond_true: ; preds = %entry
- store i32 1, i32* %P
- br label %cond_next
-cond_next: ; preds = %cond_true, %entry
- %tmp5 = and i32 %c, 2 ; <i32> [#uses=1]
- %tmp5.upgrd.2 = icmp eq i32 %tmp5, 0 ; <i1> [#uses=1]
- br i1 %tmp5.upgrd.2, label %cond_next10, label %cond_true6
-cond_true6: ; preds = %cond_next
- %tmp8 = getelementptr i32* %P, i32 1 ; <i32*> [#uses=1]
- store i32 1, i32* %tmp8
- br label %cond_next10
-cond_next10: ; preds = %cond_true6, %cond_next
- %tmp13 = and i32 %c, 4 ; <i32> [#uses=1]
- %tmp13.upgrd.3 = icmp eq i32 %tmp13, 0 ; <i1> [#uses=1]
- br i1 %tmp13.upgrd.3, label %cond_next18, label %cond_true14
-cond_true14: ; preds = %cond_next10
- %tmp16 = getelementptr i32* %P, i32 2 ; <i32*> [#uses=1]
- store i32 1, i32* %tmp16
- br label %cond_next18
-cond_next18: ; preds = %cond_true14, %cond_next10
- %tmp21 = and i32 %c, 8 ; <i32> [#uses=1]
- %tmp21.upgrd.4 = icmp eq i32 %tmp21, 0 ; <i1> [#uses=1]
- br i1 %tmp21.upgrd.4, label %return, label %cond_true22
-cond_true22: ; preds = %cond_next18
- %tmp24 = getelementptr i32* %P, i32 3 ; <i32*> [#uses=1]
- store i32 1, i32* %tmp24
- ret void
-return: ; preds = %cond_next18
- ret void
-}
diff --git a/test/Transforms/TailDup/basictest.ll b/test/Transforms/TailDup/basictest.ll
deleted file mode 100644
index 94f5d87..0000000
--- a/test/Transforms/TailDup/basictest.ll
+++ /dev/null
@@ -1,20 +0,0 @@
-; RUN: opt < %s -tailduplicate -disable-output
-
-declare void @__main()
-
-define i32 @main() {
-entry:
- call void @__main( )
- br label %loopentry
-loopentry: ; preds = %no_exit, %entry
- %i.0 = phi i32 [ %inc, %no_exit ], [ 0, %entry ] ; <i32> [#uses=3]
- %tmp.1 = icmp sle i32 %i.0, 99 ; <i1> [#uses=1]
- br i1 %tmp.1, label %no_exit, label %return
-no_exit: ; preds = %loopentry
- %tmp.51 = call i32 @main( ) ; <i32> [#uses=0]
- %inc = add i32 %i.0, 1 ; <i32> [#uses=1]
- br label %loopentry
-return: ; preds = %loopentry
- ret i32 %i.0
-}
-
diff --git a/test/Transforms/TailDup/basictest2.ll b/test/Transforms/TailDup/basictest2.ll
deleted file mode 100644
index 81a996a..0000000
--- a/test/Transforms/TailDup/basictest2.ll
+++ /dev/null
@@ -1,15 +0,0 @@
-; RUN: opt < %s -tailduplicate -disable-output
-
-define void @ab() {
-entry:
- br label %loopentry.5
-loopentry.5: ; preds = %no_exit.5, %entry
- %poscnt.1 = phi i64 [ 0, %entry ], [ %tmp.289, %no_exit.5 ] ; <i64> [#uses=1]
- %tmp.289 = ashr i64 %poscnt.1, 1 ; <i64> [#uses=1]
- br i1 false, label %no_exit.5, label %loopexit.5
-no_exit.5: ; preds = %loopentry.5
- br label %loopentry.5
-loopexit.5: ; preds = %loopentry.5
- ret void
-}
-
diff --git a/test/lib/llvm.exp b/test/lib/llvm.exp
index d92503a..89be85c 100644
--- a/test/lib/llvm.exp
+++ b/test/lib/llvm.exp
@@ -111,7 +111,7 @@ proc substitute { line test tmpFile } {
regsub -all {llvm-ranlib } $new_line "$valgrind llvm-ranlib " new_line
regsub -all {([^a-zA-Z_-])opt } $new_line "\\1$valgrind opt " new_line
regsub -all {^opt } $new_line "$valgrind opt " new_line
- regsub -all {tblgen } $new_line "$valgrind tblgen " new_line
+ regsub -all {llvm-tblgen } $new_line "$valgrind llvm-tblgen " new_line
regsub -all "not $valgrind " $new_line "$valgrind not " new_line
return $new_line
@@ -249,34 +249,6 @@ proc RunLLVMTests { test_source_files } {
}
}
-# This procedure provides an interface to check the LLVMGCC_LANGS makefile
-# variable to see if llvm-gcc supports compilation of a particular language.
-proc llvm_gcc_supports { lang } {
- global llvmgcc llvmgcc_langs
- # validate the language choices and determine the name of the compiler
- # component responsible for determining if the compiler has been built.
- switch "$lang" {
- ada { set file gnat1 }
- c { set file cc1 }
- c++ { set file cc1plus }
- objc { set file cc1obj }
- obj-c++ { set file cc1objplus }
- fortran { set file f951 }
- default { return 0 }
- }
- foreach supported_lang [split "$llvmgcc_langs" ,] {
- if { "$lang" == "$supported_lang" } {
- # FIXME: Knowing it is configured is not enough. We should do two more
- # checks here. First, we need to run llvm-gcc -print-prog-name=$file to
- # get the path to the compiler. If we don't get a path, the language isn't
- # properly configured or built. If we do get a path, we should check to
- # make sure that it is executable and perhaps even try executing it.
- return 1;
- }
- }
- return 0;
-}
-
# This procedure provides an interface to check the TARGETS_TO_BUILD makefile
# variable to see if a particular target has been configured to build. This
# helps avoid running tests for targets that aren't available.
diff --git a/test/lit.cfg b/test/lit.cfg
index ef56473..91abb63 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -12,6 +12,9 @@ config.name = 'LLVM'
# testFormat: The test format to use to interpret tests.
config.test_format = lit.formats.TclTest()
+# To ignore test output on stderr so it doesn't trigger failures uncomment this:
+#config.test_format = lit.formats.TclTest(ignoreStdErr=True)
+
# suffixes: A list of file extensions to treat as test files, this is actually
# set by on_clone().
config.suffixes = []
@@ -174,12 +177,12 @@ for sub in ['llvmgcc', 'llvmgxx', 'emitir', 'compile_cxx', 'compile_c',
# includes every tool placed in $(LLVM_OBJ_ROOT)/$(BuildMode)/bin
# (llvm_tools_dir in lit parlance).
# Don't match 'bugpoint-' or 'clang-'.
- # Don't match '/clang'.
+ # Don't match '/clang' or '-clang'.
if os.pathsep == ';':
pathext = os.environ.get('PATHEXT', '').split(';')
else:
pathext = ['']
-for pattern in [r"\bbugpoint\b(?!-)", r"(?<!/)\bclang\b(?!-)",
+for pattern in [r"\bbugpoint\b(?!-)", r"(?<!/|-)\bclang\b(?!-)",
r"\bgold\b",
r"\bllc\b", r"\blli\b",
r"\bllvm-ar\b", r"\bllvm-as\b",
@@ -195,7 +198,7 @@ for pattern in [r"\bbugpoint\b(?!-)", r"(?<!/)\bclang\b(?!-)",
# Don't match '.opt', '-opt',
# '^opt' or '/opt'.
r"\bmacho-dump\b", r"(?<!\.|-|\^|/)\bopt\b",
- r"\btblgen\b", r"\bFileCheck\b",
+ r"\bllvm-tblgen\b", r"\bFileCheck\b",
r"\bFileUpdate\b", r"\bc-index-test\b",
r"\bfpcmp\b", r"\bllvm-PerfectShuffle\b",
# Handle these specially as they are strings searched
@@ -232,10 +235,6 @@ def llvm_supports_target(name):
def llvm_supports_darwin_and_target(name):
return 'darwin' in config.target_triple and llvm_supports_target(name)
-langs = set([s.strip() for s in site_exp['llvmgcc_langs'].split(',')])
-def llvm_gcc_supports(name):
- return name.strip() in langs
-
bindings = set([s.strip() for s in site_exp['llvm_bindings'].split(',')])
def llvm_supports_binding(name):
return name.strip() in bindings
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 8851a0b..e66648b 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -28,6 +28,7 @@ add_subdirectory(llc)
add_subdirectory(llvm-ranlib)
add_subdirectory(llvm-ar)
add_subdirectory(llvm-nm)
+add_subdirectory(llvm-size)
add_subdirectory(llvm-ld)
add_subdirectory(llvm-prof)
@@ -39,13 +40,13 @@ add_subdirectory(llvm-diff)
add_subdirectory(macho-dump)
add_subdirectory(llvm-objdump)
add_subdirectory(llvm-rtdyld)
+add_subdirectory(llvm-dwarfdump)
add_subdirectory(bugpoint)
add_subdirectory(bugpoint-passes)
add_subdirectory(llvm-bcanalyzer)
add_subdirectory(llvm-stub)
add_subdirectory(edis)
-add_subdirectory(llvmc)
if( NOT WIN32 )
add_subdirectory(lto)
diff --git a/tools/Makefile b/tools/Makefile
index 5960433..68ce314 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -25,8 +25,9 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \
llvm-ld llvm-prof llvm-link \
lli llvm-extract llvm-mc \
bugpoint llvm-bcanalyzer llvm-stub \
- llvmc llvm-diff macho-dump llvm-objdump \
- llvm-rtdyld
+ llvm-diff macho-dump llvm-objdump \
+ llvm-rtdyld llvm-dwarfdump llvm-cov \
+ llvm-size
# Let users override the set of tools to build from the command line.
ifdef ONLY_TOOLS
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp
index aa3e290..677d178 100644
--- a/tools/bugpoint/BugDriver.cpp
+++ b/tools/bugpoint/BugDriver.cpp
@@ -127,7 +127,8 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
outs() << "Linking in input file: '" << Filenames[i] << "'\n";
std::string ErrorMessage;
- if (Linker::LinkModules(Program, M.get(), &ErrorMessage)) {
+ if (Linker::LinkModules(Program, M.get(), Linker::DestroySource,
+ &ErrorMessage)) {
errs() << ToolName << ": error linking in '" << Filenames[i] << "': "
<< ErrorMessage << '\n';
return true;
diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp
index 9941add..73b65ca 100644
--- a/tools/bugpoint/ExtractFunction.cpp
+++ b/tools/bugpoint/ExtractFunction.cpp
@@ -175,7 +175,7 @@ static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) {
std::vector<Constant*> ArrayElts;
Type *Int32Ty = Type::getInt32Ty(TorList[0].first->getContext());
- const StructType *STy =
+ StructType *STy =
StructType::get(Int32Ty, TorList[0].first->getType(), NULL);
for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
Constant *Elts[] = {
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp
index d645dfb..7ff16db 100644
--- a/tools/bugpoint/Miscompilation.cpp
+++ b/tools/bugpoint/Miscompilation.cpp
@@ -222,7 +222,7 @@ static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2,
M1 = CloneModule(M1);
M2 = CloneModule(M2);
}
- if (Linker::LinkModules(M1, M2, &ErrorMsg)) {
+ if (Linker::LinkModules(M1, M2, Linker::DestroySource, &ErrorMsg)) {
errs() << BD.getToolName() << ": Error linking modules together:"
<< ErrorMsg << '\n';
exit(1);
@@ -384,7 +384,7 @@ static bool ExtractLoops(BugDriver &BD,
outs() << "*** Loop extraction successful!\n";
- std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions;
+ std::vector<std::pair<std::string, FunctionType*> > MisCompFunctions;
for (Module::iterator I = ToOptimizeLoopExtracted->begin(),
E = ToOptimizeLoopExtracted->end(); I != E; ++I)
if (!I->isDeclaration())
@@ -396,7 +396,8 @@ static bool ExtractLoops(BugDriver &BD,
// Replace the current program with the loop extracted version, and try to
// extract another loop.
std::string ErrorMsg;
- if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, &ErrorMsg)){
+ if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted,
+ Linker::DestroySource, &ErrorMsg)){
errs() << BD.getToolName() << ": Error linking modules together:"
<< ErrorMsg << '\n';
exit(1);
@@ -411,8 +412,6 @@ static bool ExtractLoops(BugDriver &BD,
Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first);
assert(NewF && "Function not found??");
- assert(NewF->getFunctionType() == MisCompFunctions[i].second &&
- "found wrong function type?");
MiscompiledFunctions.push_back(NewF);
}
@@ -569,7 +568,7 @@ static bool ExtractBlocks(BugDriver &BD,
// together.
delete ToExtract;
- std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions;
+ std::vector<std::pair<std::string, FunctionType*> > MisCompFunctions;
for (Module::iterator I = Extracted->begin(), E = Extracted->end();
I != E; ++I)
if (!I->isDeclaration())
@@ -577,7 +576,8 @@ static bool ExtractBlocks(BugDriver &BD,
I->getFunctionType()));
std::string ErrorMsg;
- if (Linker::LinkModules(ProgClone, Extracted, &ErrorMsg)) {
+ if (Linker::LinkModules(ProgClone, Extracted, Linker::DestroySource,
+ &ErrorMsg)) {
errs() << BD.getToolName() << ": Error linking modules together:"
<< ErrorMsg << '\n';
exit(1);
@@ -593,8 +593,6 @@ static bool ExtractBlocks(BugDriver &BD,
for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first);
assert(NewF && "Function not found??");
- assert(NewF->getFunctionType() == MisCompFunctions[i].second &&
- "Function has wrong type??");
MiscompiledFunctions.push_back(NewF);
}
@@ -834,8 +832,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
// GetElementPtr *funcName, ulong 0, ulong 0
std::vector<Constant*> GEPargs(2,
Constant::getNullValue(Type::getInt32Ty(F->getContext())));
- Value *GEP =
- ConstantExpr::getGetElementPtr(funcName, &GEPargs[0], 2);
+ Value *GEP = ConstantExpr::getGetElementPtr(funcName, GEPargs);
std::vector<Value*> ResolverArgs;
ResolverArgs.push_back(GEP);
@@ -850,7 +847,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
NullPtr,F->getName()+".fpcache");
// Construct a new stub function that will re-route calls to F
- const FunctionType *FuncTy = F->getFunctionType();
+ FunctionType *FuncTy = F->getFunctionType();
Function *FuncWrapper = Function::Create(FuncTy,
GlobalValue::InternalLinkage,
F->getName() + "_wrapper",
diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp
index e25414f..6a87521 100644
--- a/tools/bugpoint/bugpoint.cpp
+++ b/tools/bugpoint/bugpoint.cpp
@@ -17,16 +17,17 @@
#include "ToolRunner.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/LLVMContext.h"
+#include "llvm/PassManager.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/PassManagerBuilder.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Valgrind.h"
#include "llvm/LinkAllVMCore.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
//Enable this macro to debug bugpoint itself.
//#define DEBUG_BUGPOINT 1
diff --git a/tools/edis/CMakeLists.txt b/tools/edis/CMakeLists.txt
index 9406c2a..1e162f9 100644
--- a/tools/edis/CMakeLists.txt
+++ b/tools/edis/CMakeLists.txt
@@ -5,30 +5,17 @@ set(SOURCES
EDMain.cpp
)
-set(LLVM_LINK_COMPONENTS mcdisassembler)
+set(EDIS_DEPENDS LLVMMCDisassembler LLVMMCParser)
if( LLVM_TARGETS_TO_BUILD MATCHES X86 )
- list(APPEND LLVM_LINK_COMPONENTS x86asmprinter x86disassembler)
+ list(APPEND EDIS_DEPENDS LLVMX86AsmPrinter LLVMX86AsmParser LLVMX86Disassembler LLVMX86Desc)
endif()
if( LLVM_TARGETS_TO_BUILD MATCHES ARM )
- list(APPEND LLVM_LINK_COMPONENTS armasmprinter armdisassembler)
+ list(APPEND EDIS_DEPENDS LLVMARMAsmPrinter LLVMARMAsmParser LLVMARMDisassembler LLVMARMDesc)
endif()
-# TODO: Process EnhancedDisassembly.exports
+add_llvm_library(EnhancedDisassembly ${SOURCES})
+set_property(TARGET EnhancedDisassembly PROPERTY
+ OUTPUT_NAME "EnhancedDisassembly")
-if( NOT WIN32 AND LLVM_ENABLE_PIC )
- set(bsl ${BUILD_SHARED_LIBS})
- set(BUILD_SHARED_LIBS ON)
- add_llvm_library(EnhancedDisassembly ${SOURCES})
- set_property(TARGET EnhancedDisassembly PROPERTY
- OUTPUT_NAME "EnhancedDisassembly")
- set(BUILD_SHARED_LIBS ${bsl})
- set(EnhancedDisassembly_STATIC_TARGET_NAME EnhancedDisassembly_static)
-else()
- set(EnhancedDisassembly_STATIC_TARGET_NAME EnhancedDisassembly)
-endif()
-
-if( NOT BUILD_SHARED_LIBS )
- add_llvm_library(${EnhancedDisassembly_STATIC_TARGET_NAME} ${SOURCES})
- set_property(TARGET ${EnhancedDisassembly_STATIC_TARGET_NAME} PROPERTY
- OUTPUT_NAME "EnhancedDisassembly")
-endif()
+add_llvm_library_dependencies(EnhancedDisassembly
+ ${EDIS_DEPENDS})
diff --git a/tools/edis/EnhancedDisassembly.exports b/tools/edis/EnhancedDisassembly.exports
deleted file mode 100644
index 7050f7f..0000000
--- a/tools/edis/EnhancedDisassembly.exports
+++ /dev/null
@@ -1,36 +0,0 @@
-EDGetDisassembler
-EDGetRegisterName
-EDRegisterIsStackPointer
-EDRegisterIsProgramCounter
-EDCreateInsts
-EDReleaseInst
-EDInstByteSize
-EDGetInstString
-EDInstIsBranch
-EDInstIsMove
-EDBranchTargetID
-EDMoveSourceID
-EDMoveTargetID
-EDNumTokens
-EDGetToken
-EDGetTokenString
-EDOperandIndexForToken
-EDTokenIsWhitespace
-EDTokenIsPunctuation
-EDTokenIsOpcode
-EDTokenIsLiteral
-EDTokenIsRegister
-EDTokenIsNegativeLiteral
-EDLiteralTokenAbsoluteValue
-EDRegisterTokenValue
-EDNumOperands
-EDGetOperand
-EDOperandIsRegister
-EDOperandIsImmediate
-EDOperandIsMemory
-EDRegisterOperandValue
-EDImmediateOperandValue
-EDEvaluateOperand
-EDBlockCreateInsts
-EDBlockEvaluateOperand
-EDBlockVisitTokens
diff --git a/tools/edis/Makefile b/tools/edis/Makefile
index b5557fc..3fcb408 100644
--- a/tools/edis/Makefile
+++ b/tools/edis/Makefile
@@ -10,7 +10,6 @@
LEVEL = ../..
LIBRARYNAME = EnhancedDisassembly
LINK_LIBS_IN_SHARED = 1
-SHARED_LIBRARY = 1
EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/EnhancedDisassembly.exports
diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp
index 9e43bef..6f547b3 100644
--- a/tools/gold/gold-plugin.cpp
+++ b/tools/gold/gold-plugin.cpp
@@ -17,6 +17,9 @@
#include "llvm-c/lto.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/system_error.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/Path.h"
@@ -235,25 +238,43 @@ ld_plugin_status onload(ld_plugin_tv *tv) {
static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
int *claimed) {
lto_module_t M;
-
+ const void *view;
+ OwningPtr<MemoryBuffer> buffer;
if (get_view) {
- const void *view;
if (get_view(file->handle, &view) != LDPS_OK) {
(*message)(LDPL_ERROR, "Failed to get a view of %s", file->name);
return LDPS_ERR;
}
- M = lto_module_create_from_memory(view, file->filesize);
- } else if (file->offset) {
+ } else {
+ int64_t offset = 0;
// Gold has found what might be IR part-way inside of a file, such as
// an .a archive.
- M = lto_module_create_from_fd_at_offset(file->fd, file->name, -1,
- file->filesize, file->offset);
- } else {
- M = lto_module_create_from_fd(file->fd, file->name, file->filesize);
+ if (file->offset) {
+ offset = file->offset;
+ }
+ if (error_code ec =
+ MemoryBuffer::getOpenFile(file->fd, file->name, buffer, file->filesize,
+ -1, offset, false)) {
+ (*message)(LDPL_ERROR, ec.message().c_str());
+ return LDPS_ERR;
+ }
+ view = buffer->getBufferStart();
}
- if (!M)
+
+ if (!lto_module_is_object_file_in_memory(view, file->filesize))
return LDPS_OK;
+ M = lto_module_create_from_memory(view, file->filesize);
+ if (!M) {
+ if (const char* msg = lto_get_error_message()) {
+ (*message)(LDPL_ERROR,
+ "LLVM gold plugin has failed to create LTO module: %s",
+ msg);
+ return LDPS_ERR;
+ }
+ return LDPS_OK;
+ }
+
*claimed = 1;
Modules.resize(Modules.size() + 1);
claimed_file &cf = Modules.back();
@@ -360,6 +381,8 @@ static ld_plugin_status all_symbols_read_hook(void) {
bool anySymbolsPreserved = false;
for (std::list<claimed_file>::iterator I = Modules.begin(),
E = Modules.end(); I != E; ++I) {
+ if (I->syms.empty())
+ continue;
(*get_symbols)(I->handle, I->syms.size(), &I->syms[0]);
for (unsigned i = 0, e = I->syms.size(); i != e; i++) {
if (I->syms[i].resolution == LDPR_PREVAILING_DEF) {
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp
index b36e941..d29bd9b 100644
--- a/tools/llc/llc.cpp
+++ b/tools/llc/llc.cpp
@@ -32,10 +32,10 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetSelect.h"
#include <memory>
using namespace llvm;
@@ -76,6 +76,37 @@ MAttrs("mattr",
cl::desc("Target specific attributes (-mattr=help for details)"),
cl::value_desc("a1,+a2,-a3,..."));
+static cl::opt<Reloc::Model>
+RelocModel("relocation-model",
+ cl::desc("Choose relocation model"),
+ cl::init(Reloc::Default),
+ cl::values(
+ clEnumValN(Reloc::Default, "default",
+ "Target default relocation model"),
+ clEnumValN(Reloc::Static, "static",
+ "Non-relocatable code"),
+ clEnumValN(Reloc::PIC_, "pic",
+ "Fully relocatable, position independent code"),
+ clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+ "Relocatable external references, non-relocatable code"),
+ clEnumValEnd));
+
+static cl::opt<llvm::CodeModel::Model>
+CMModel("code-model",
+ cl::desc("Choose code model"),
+ cl::init(CodeModel::Default),
+ cl::values(clEnumValN(CodeModel::Default, "default",
+ "Target default code model"),
+ clEnumValN(CodeModel::Small, "small",
+ "Small code model"),
+ clEnumValN(CodeModel::Kernel, "kernel",
+ "Kernel code model"),
+ clEnumValN(CodeModel::Medium, "medium",
+ "Medium code model"),
+ clEnumValN(CodeModel::Large, "large",
+ "Large code model"),
+ clEnumValEnd));
+
static cl::opt<bool>
RelaxAll("mc-relax-all",
cl::desc("When used with filetype=obj, "
@@ -201,12 +232,13 @@ int main(int argc, char **argv) {
// Initialize targets first, so that --version shows registered targets.
InitializeAllTargets();
- InitializeAllMCAsmInfos();
- InitializeAllMCInstrInfos();
- InitializeAllMCSubtargetInfos();
+ InitializeAllTargetMCs();
InitializeAllAsmPrinters();
InitializeAllAsmParsers();
+ // Register the target printer for --version.
+ cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
+
cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
// Load the module to be compiled...
@@ -272,8 +304,9 @@ int main(int argc, char **argv) {
}
std::auto_ptr<TargetMachine>
- target(TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU,
- FeaturesStr));
+ target(TheTarget->createTargetMachine(TheTriple.getTriple(),
+ MCPU, FeaturesStr,
+ RelocModel, CMModel));
assert(target.get() && "Could not allocate target machine!");
TargetMachine &Target = *target.get();
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
index 014925c..50c7a49 100644
--- a/tools/lli/lli.cpp
+++ b/tools/lli/lli.cpp
@@ -33,7 +33,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
-#include "llvm/Target/TargetSelect.h"
+#include "llvm/Support/TargetSelect.h"
#include <cerrno>
#ifdef __CYGWIN__
@@ -108,6 +108,38 @@ namespace {
NoLazyCompilation("disable-lazy-compilation",
cl::desc("Disable JIT lazy compilation"),
cl::init(false));
+
+ cl::opt<Reloc::Model>
+ RelocModel("relocation-model",
+ cl::desc("Choose relocation model"),
+ cl::init(Reloc::Default),
+ cl::values(
+ clEnumValN(Reloc::Default, "default",
+ "Target default relocation model"),
+ clEnumValN(Reloc::Static, "static",
+ "Non-relocatable code"),
+ clEnumValN(Reloc::PIC_, "pic",
+ "Fully relocatable, position independent code"),
+ clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+ "Relocatable external references, non-relocatable code"),
+ clEnumValEnd));
+
+ cl::opt<llvm::CodeModel::Model>
+ CMModel("code-model",
+ cl::desc("Choose code model"),
+ cl::init(CodeModel::JITDefault),
+ cl::values(clEnumValN(CodeModel::JITDefault, "default",
+ "Target default JIT code model"),
+ clEnumValN(CodeModel::Small, "small",
+ "Small code model"),
+ clEnumValN(CodeModel::Kernel, "kernel",
+ "Kernel code model"),
+ clEnumValN(CodeModel::Medium, "medium",
+ "Medium code model"),
+ clEnumValN(CodeModel::Large, "large",
+ "Large code model"),
+ clEnumValEnd));
+
}
static ExecutionEngine *EE = 0;
@@ -164,6 +196,8 @@ int main(int argc, char **argv, char * const *envp) {
builder.setMArch(MArch);
builder.setMCPU(MCPU);
builder.setMAttrs(MAttrs);
+ builder.setRelocationModel(RelocModel);
+ builder.setCodeModel(CMModel);
builder.setErrorStr(&ErrorMsg);
builder.setEngineKind(ForceInterpreter
? EngineKind::Interpreter
diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt
index bc23a64..6016862 100644
--- a/tools/llvm-config/CMakeLists.txt
+++ b/tools/llvm-config/CMakeLists.txt
@@ -138,27 +138,3 @@ install(FILES ${LLVM_CONFIG}
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
DESTINATION bin)
-
-
-# Regeneration of library dependencies.
-
-# See the comments at the end of cmake/modules/LLVM-Config.cmake for
-# notes and guidelines.
-
-set(LLVMLibDeps ${LLVM_MAIN_SRC_DIR}/cmake/modules/LLVMLibDeps.cmake)
-set(LLVMLibDeps_TMP ${CMAKE_CURRENT_BINARY_DIR}/LLVMLibDeps.cmake.tmp)
-
-add_custom_command(OUTPUT ${LLVMLibDeps_TMP}
- COMMAND sed -e s'@\\.a@@g' -e s'@\\.so@@g' -e 's@libLLVM@LLVM@g' -e 's@: @ @' -e 's@\\\(.*\\\)@set\(MSVC_LIB_DEPS_\\1\)@' ${FINAL_LIBDEPS} > ${LLVMLibDeps_TMP}
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LLVMLibDeps_TMP} ${LLVMLibDeps}
- DEPENDS ${FINAL_LIBDEPS}
- COMMENT "Updating cmake library dependencies file ${LLVMLibDeps}"
- )
-
-if( LLVM_TARGETS_TO_BUILD STREQUAL LLVM_ALL_TARGETS )
- add_custom_target(llvmlibdeps.target ALL DEPENDS ${LLVMLibDeps_TMP})
- add_dependencies(llvmlibdeps.target llvm-config.target)
- set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} llvmlibdeps.target)
-endif()
-
-set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} PARENT_SCOPE)
diff --git a/tools/llvm-cov/CMakeLists.txt b/tools/llvm-cov/CMakeLists.txt
new file mode 100644
index 0000000..7184b9e
--- /dev/null
+++ b/tools/llvm-cov/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_LINK_COMPONENTS instrumentation )
+
+add_llvm_tool(llvm-cov
+ llvm-cov.cpp
+ )
diff --git a/tools/llvm-cov/Makefile b/tools/llvm-cov/Makefile
new file mode 100644
index 0000000..bd9fa2a
--- /dev/null
+++ b/tools/llvm-cov/Makefile
@@ -0,0 +1,18 @@
+##===- tools/llvm-cov/Makefile -----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+
+TOOLNAME = llvm-cov
+LINK_COMPONENTS := instrumentation
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-cov/llvm-cov.cpp b/tools/llvm-cov/llvm-cov.cpp
new file mode 100644
index 0000000..7b21c5b
--- /dev/null
+++ b/tools/llvm-cov/llvm-cov.cpp
@@ -0,0 +1,78 @@
+//===- tools/llvm-cov/llvm-cov.cpp - LLVM coverage tool -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// llvm-cov is a command line tools to analyze and report coverage information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/GCOV.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
+using namespace llvm;
+
+static cl::opt<bool>
+DumpGCOV("dump", cl::init(false), cl::desc("dump gcov file"));
+
+static cl::opt<std::string>
+InputGCNO("gcno", cl::desc("<input gcno file>"), cl::init(""));
+
+static cl::opt<std::string>
+InputGCDA("gcda", cl::desc("<input gcda file>"), cl::init(""));
+
+
+//===----------------------------------------------------------------------===//
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ cl::ParseCommandLineOptions(argc, argv, "llvm cov\n");
+
+ GCOVFile GF;
+ if (InputGCNO.empty())
+ errs() << " " << argv[0] << ": No gcov input file!\n";
+
+ OwningPtr<MemoryBuffer> GCNO_Buff;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputGCNO, GCNO_Buff)) {
+ errs() << InputGCNO << ": " << ec.message() << "\n";
+ return 1;
+ }
+ GCOVBuffer GCNO_GB(GCNO_Buff.take());
+ if (!GF.read(GCNO_GB)) {
+ errs() << "Invalid .gcno File!\n";
+ return 1;
+ }
+
+ if (!InputGCDA.empty()) {
+ OwningPtr<MemoryBuffer> GCDA_Buff;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputGCDA, GCDA_Buff)) {
+ errs() << InputGCDA << ": " << ec.message() << "\n";
+ return 1;
+ }
+ GCOVBuffer GCDA_GB(GCDA_Buff.take());
+ if (!GF.read(GCDA_GB)) {
+ errs() << "Invalid .gcda File!\n";
+ return 1;
+ }
+ }
+
+
+ if (DumpGCOV)
+ GF.dump();
+
+ FileInfo FI;
+ GF.collectLineCounts(FI);
+ return 0;
+}
diff --git a/tools/llvm-diff/DifferenceEngine.cpp b/tools/llvm-diff/DifferenceEngine.cpp
index ba2cec2..b240d8c 100644
--- a/tools/llvm-diff/DifferenceEngine.cpp
+++ b/tools/llvm-diff/DifferenceEngine.cpp
@@ -195,12 +195,12 @@ class FunctionDifferenceEngine {
DifferenceEngine::Context C(Engine, L, R);
BasicBlock::iterator LI = L->begin(), LE = L->end();
- BasicBlock::iterator RI = R->begin(), RE = R->end();
+ BasicBlock::iterator RI = R->begin();
llvm::SmallVector<std::pair<Instruction*,Instruction*>, 20> TentativePairs;
do {
- assert(LI != LE && RI != RE);
+ assert(LI != LE && RI != R->end());
Instruction *LeftI = &*LI, *RightI = &*RI;
// If the instructions differ, start the more sophisticated diff
diff --git a/tools/llvm-dwarfdump/CMakeLists.txt b/tools/llvm-dwarfdump/CMakeLists.txt
new file mode 100644
index 0000000..05aad3f
--- /dev/null
+++ b/tools/llvm-dwarfdump/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(LLVM_LINK_COMPONENTS
+ DebugInfo
+ Object
+ )
+
+add_llvm_tool(llvm-dwarfdump
+ llvm-dwarfdump.cpp
+ )
diff --git a/tools/llvm-dwarfdump/Makefile b/tools/llvm-dwarfdump/Makefile
new file mode 100644
index 0000000..e61f27d
--- /dev/null
+++ b/tools/llvm-dwarfdump/Makefile
@@ -0,0 +1,17 @@
+##===- tools/llvm-dwarfdump/Makefile -----------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+LEVEL = ../..
+
+TOOLNAME = llvm-dwarfdump
+LINK_COMPONENTS = DebugInfo Object
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
new file mode 100644
index 0000000..ca0493d
--- /dev/null
+++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -0,0 +1,116 @@
+//===-- llvm-dwarfdump.cpp - Debug info dumping utility for llvm -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This program is a utility that works like "dwarfdump".
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+#include <algorithm>
+#include <cstring>
+using namespace llvm;
+using namespace object;
+
+static cl::list<std::string>
+InputFilenames(cl::Positional, cl::desc("<input object files>"),
+ cl::ZeroOrMore);
+
+static cl::opt<unsigned long long>
+Address("address", cl::init(-1ULL),
+ cl::desc("Print line information for a given address"));
+
+static void DumpInput(const StringRef &Filename) {
+ OwningPtr<MemoryBuffer> Buff;
+
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
+ errs() << Filename << ": " << ec.message() << "\n";
+ return;
+ }
+
+ OwningPtr<ObjectFile> Obj(ObjectFile::createObjectFile(Buff.take()));
+
+ StringRef DebugInfoSection;
+ StringRef DebugAbbrevSection;
+ StringRef DebugLineSection;
+ StringRef DebugArangesSection;
+ StringRef DebugStringSection;
+
+ error_code ec;
+ for (section_iterator i = Obj->begin_sections(),
+ e = Obj->end_sections();
+ i != e; i.increment(ec)) {
+ StringRef name;
+ i->getName(name);
+ StringRef data;
+ i->getContents(data);
+
+ if (name.startswith("__DWARF,"))
+ name = name.substr(8); // Skip "__DWARF," prefix.
+ name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
+ if (name == "debug_info")
+ DebugInfoSection = data;
+ else if (name == "debug_abbrev")
+ DebugAbbrevSection = data;
+ else if (name == "debug_line")
+ DebugLineSection = data;
+ else if (name == "debug_aranges")
+ DebugArangesSection = data;
+ else if (name == "debug_str")
+ DebugStringSection = data;
+ }
+
+ OwningPtr<DIContext> dictx(DIContext::getDWARFContext(/*FIXME*/true,
+ DebugInfoSection,
+ DebugAbbrevSection,
+ DebugArangesSection,
+ DebugLineSection,
+ DebugStringSection));
+ if (Address == -1ULL) {
+ outs() << Filename
+ << ":\tfile format " << Obj->getFileFormatName() << "\n\n";
+ // Dump the complete DWARF structure.
+ dictx->dump(outs());
+ } else {
+ // Print line info for the specified address.
+ DILineInfo dli = dictx->getLineInfoForAddress(Address);
+ outs() << (dli.getFileName() ? dli.getFileName() : "<unknown>") << ':'
+ << dli.getLine() << ':' << dli.getColumn() << '\n';
+ }
+}
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ cl::ParseCommandLineOptions(argc, argv, "llvm dwarf dumper\n");
+
+ // Defaults to a.out if no filenames specified.
+ if (InputFilenames.size() == 0)
+ InputFilenames.push_back("a.out");
+
+ std::for_each(InputFilenames.begin(), InputFilenames.end(), DumpInput);
+
+ return 0;
+}
diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp
index a6c229f..f6227ee 100644
--- a/tools/llvm-extract/llvm-extract.cpp
+++ b/tools/llvm-extract/llvm-extract.cpp
@@ -26,7 +26,9 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/Regex.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SetVector.h"
#include <memory>
using namespace llvm;
@@ -45,16 +47,30 @@ Force("f", cl::desc("Enable binary output on terminals"));
static cl::opt<bool>
DeleteFn("delete", cl::desc("Delete specified Globals from Module"));
-// ExtractFuncs - The functions to extract from the module...
+// ExtractFuncs - The functions to extract from the module.
static cl::list<std::string>
ExtractFuncs("func", cl::desc("Specify function to extract"),
cl::ZeroOrMore, cl::value_desc("function"));
-// ExtractGlobals - The globals to extract from the module...
+// ExtractRegExpFuncs - The functions, matched via regular expression, to
+// extract from the module.
+static cl::list<std::string>
+ExtractRegExpFuncs("rfunc", cl::desc("Specify function(s) to extract using a "
+ "regular expression"),
+ cl::ZeroOrMore, cl::value_desc("rfunction"));
+
+// ExtractGlobals - The globals to extract from the module.
static cl::list<std::string>
ExtractGlobals("glob", cl::desc("Specify global to extract"),
cl::ZeroOrMore, cl::value_desc("global"));
+// ExtractRegExpGlobals - The globals, matched via regular expression, to
+// extract from the module...
+static cl::list<std::string>
+ExtractRegExpGlobals("rglob", cl::desc("Specify global(s) to extract using a "
+ "regular expression"),
+ cl::ZeroOrMore, cl::value_desc("rglobal"));
+
static cl::opt<bool>
OutputAssembly("S",
cl::desc("Write output as LLVM assembly"), cl::Hidden);
@@ -78,7 +94,8 @@ int main(int argc, char **argv) {
return 1;
}
- std::vector<GlobalValue *> GVs;
+ // Use SetVector to avoid duplicates.
+ SetVector<GlobalValue *> GVs;
// Figure out which globals we should extract.
for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) {
@@ -88,7 +105,30 @@ int main(int argc, char **argv) {
<< ExtractGlobals[i] << "'!\n";
return 1;
}
- GVs.push_back(GV);
+ GVs.insert(GV);
+ }
+
+ // Extract globals via regular expression matching.
+ for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) {
+ std::string Error;
+ Regex RegEx(ExtractRegExpGlobals[i]);
+ if (!RegEx.isValid(Error)) {
+ errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' "
+ "invalid regex: " << Error;
+ }
+ bool match = false;
+ for (Module::global_iterator GV = M.get()->global_begin(),
+ E = M.get()->global_end(); GV != E; GV++) {
+ if (RegEx.match(GV->getName())) {
+ GVs.insert(&*GV);
+ match = true;
+ }
+ }
+ if (!match) {
+ errs() << argv[0] << ": program doesn't contain global named '"
+ << ExtractRegExpGlobals[i] << "'!\n";
+ return 1;
+ }
}
// Figure out which functions we should extract.
@@ -99,7 +139,30 @@ int main(int argc, char **argv) {
<< ExtractFuncs[i] << "'!\n";
return 1;
}
- GVs.push_back(GV);
+ GVs.insert(GV);
+ }
+ // Extract functions via regular expression matching.
+ for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) {
+ std::string Error;
+ StringRef RegExStr = ExtractRegExpFuncs[i];
+ Regex RegEx(RegExStr);
+ if (!RegEx.isValid(Error)) {
+ errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' "
+ "invalid regex: " << Error;
+ }
+ bool match = false;
+ for (Module::iterator F = M.get()->begin(), E = M.get()->end(); F != E;
+ F++) {
+ if (RegEx.match(F->getName())) {
+ GVs.insert(&*F);
+ match = true;
+ }
+ }
+ if (!match) {
+ errs() << argv[0] << ": program doesn't contain global named '"
+ << ExtractRegExpFuncs[i] << "'!\n";
+ return 1;
+ }
}
// Materialize requisite global values.
@@ -145,7 +208,9 @@ int main(int argc, char **argv) {
PassManager Passes;
Passes.add(new TargetData(M.get())); // Use correct TargetData
- Passes.add(createGVExtractionPass(GVs, DeleteFn));
+ std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end());
+
+ Passes.add(createGVExtractionPass(Gvs, DeleteFn));
if (!DeleteFn)
Passes.add(createGlobalDCEPass()); // Delete unreachable globals
Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info
diff --git a/tools/llvm-ld/Optimize.cpp b/tools/llvm-ld/Optimize.cpp
index ca6a477..7f3f900 100644
--- a/tools/llvm-ld/Optimize.cpp
+++ b/tools/llvm-ld/Optimize.cpp
@@ -12,14 +12,18 @@
//===----------------------------------------------------------------------===//
#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/PassManagerBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/PluginLoader.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/Scalar.h"
using namespace llvm;
// Pass Name Options as generated by the PassNameParser
diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp
index 3fb7ba4..95ad1ca 100644
--- a/tools/llvm-link/llvm-link.cpp
+++ b/tools/llvm-link/llvm-link.cpp
@@ -103,7 +103,8 @@ int main(int argc, char **argv) {
if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n";
- if (Linker::LinkModules(Composite.get(), M.get(), &ErrorMessage)) {
+ if (Linker::LinkModules(Composite.get(), M.get(), Linker::DestroySource,
+ &ErrorMessage)) {
errs() << argv[0] << ": link error in '" << InputFilenames[i]
<< "': " << ErrorMessage << "\n";
return 1;
diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp
index c389f6a..a9381b5 100644
--- a/tools/llvm-mc/Disassembler.cpp
+++ b/tools/llvm-mc/Disassembler.cpp
@@ -21,14 +21,15 @@
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MemoryObject.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy;
@@ -65,15 +66,26 @@ static bool PrintInsts(const MCDisassembler &DisAsm,
for (Index = 0; Index < Bytes.size(); Index += Size) {
MCInst Inst;
- if (DisAsm.getInstruction(Inst, Size, memoryObject, Index,
- /*REMOVE*/ nulls())) {
- Printer.printInst(&Inst, Out);
- Out << "\n";
- } else {
+ MCDisassembler::DecodeStatus S;
+ S = DisAsm.getInstruction(Inst, Size, memoryObject, Index,
+ /*REMOVE*/ nulls(), nulls());
+ switch (S) {
+ case MCDisassembler::Fail:
SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
"invalid instruction encoding", "warning");
if (Size == 0)
Size = 1; // skip illegible bytes
+ break;
+
+ case MCDisassembler::SoftFail:
+ SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
+ "potentially undefined instruction encoding", "warning");
+ // Fall through
+
+ case MCDisassembler::Success:
+ Printer.printInst(&Inst, Out, "");
+ Out << "\n";
+ break;
}
}
@@ -129,6 +141,8 @@ static bool ByteArrayFromString(ByteArrayTy &ByteArray,
int Disassembler::disassemble(const Target &T,
const std::string &Triple,
+ const std::string &Cpu,
+ const std::string &FeaturesStr,
MemoryBuffer &Buffer,
raw_ostream &Out) {
// Set up disassembler.
@@ -139,7 +153,13 @@ int Disassembler::disassemble(const Target &T,
return -1;
}
- OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler());
+ OwningPtr<const MCSubtargetInfo> STI(T.createMCSubtargetInfo(Triple, Cpu, FeaturesStr));
+ if (!STI) {
+ errs() << "error: no subtarget info for target " << Triple << "\n";
+ return -1;
+ }
+
+ OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(*STI));
if (!DisAsm) {
errs() << "error: no disassembler for target " << Triple << "\n";
return -1;
@@ -147,7 +167,7 @@ int Disassembler::disassemble(const Target &T,
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(AsmPrinterVariant,
- *AsmInfo));
+ *AsmInfo, *STI));
if (!IP) {
errs() << "error: no instruction printer for target " << Triple << '\n';
return -1;
diff --git a/tools/llvm-mc/Disassembler.h b/tools/llvm-mc/Disassembler.h
index 433e71b..e8cd92d 100644
--- a/tools/llvm-mc/Disassembler.h
+++ b/tools/llvm-mc/Disassembler.h
@@ -27,6 +27,8 @@ class Disassembler {
public:
static int disassemble(const Target &target,
const std::string &tripleString,
+ const std::string &Cpu,
+ const std::string &FeaturesStr,
MemoryBuffer &buffer,
raw_ostream &Out);
diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp
index 334bf32..5fb3fdf 100644
--- a/tools/llvm-mc/llvm-mc.cpp
+++ b/tools/llvm-mc/llvm-mc.cpp
@@ -14,23 +14,18 @@
#include "llvm/MC/MCParser/AsmLexer.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/Target/TargetAsmBackend.h"
-#include "llvm/Target/TargetAsmParser.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetAsmInfo.h" // FIXME.
-#include "llvm/Target/TargetLowering.h" // FIXME.
-#include "llvm/Target/TargetLoweringObjectFile.h" // FIXME.
-#include "llvm/Target/TargetMachine.h" // FIXME.
-#include "llvm/Target/TargetSelect.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
@@ -42,6 +37,8 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/system_error.h"
#include "Disassembler.h"
using namespace llvm;
@@ -111,6 +108,43 @@ MCPU("mcpu",
cl::value_desc("cpu-name"),
cl::init(""));
+static cl::list<std::string>
+MAttrs("mattr",
+ cl::CommaSeparated,
+ cl::desc("Target specific attributes (-mattr=help for details)"),
+ cl::value_desc("a1,+a2,-a3,..."));
+
+static cl::opt<Reloc::Model>
+RelocModel("relocation-model",
+ cl::desc("Choose relocation model"),
+ cl::init(Reloc::Default),
+ cl::values(
+ clEnumValN(Reloc::Default, "default",
+ "Target default relocation model"),
+ clEnumValN(Reloc::Static, "static",
+ "Non-relocatable code"),
+ clEnumValN(Reloc::PIC_, "pic",
+ "Fully relocatable, position independent code"),
+ clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+ "Relocatable external references, non-relocatable code"),
+ clEnumValEnd));
+
+static cl::opt<llvm::CodeModel::Model>
+CMModel("code-model",
+ cl::desc("Choose code model"),
+ cl::init(CodeModel::Default),
+ cl::values(clEnumValN(CodeModel::Default, "default",
+ "Target default code model"),
+ clEnumValN(CodeModel::Small, "small",
+ "Small code model"),
+ clEnumValN(CodeModel::Kernel, "kernel",
+ "Kernel code model"),
+ clEnumValN(CodeModel::Medium, "medium",
+ "Medium code model"),
+ clEnumValN(CodeModel::Large, "large",
+ "Large code model"),
+ clEnumValEnd));
+
static cl::opt<bool>
NoInitialTextSection("n", cl::desc("Don't assume assembly file starts "
"in the text section"));
@@ -142,21 +176,42 @@ static const Target *GetTarget(const char *ProgName) {
// Figure out the target triple.
if (TripleName.empty())
TripleName = sys::getHostTriple();
+ Triple TheTriple(Triple::normalize(TripleName));
+
+ const Target *TheTarget = 0;
if (!ArchName.empty()) {
- llvm::Triple TT(TripleName);
- TT.setArchName(ArchName);
- TripleName = TT.str();
- }
+ for (TargetRegistry::iterator it = TargetRegistry::begin(),
+ ie = TargetRegistry::end(); it != ie; ++it) {
+ if (ArchName == it->getName()) {
+ TheTarget = &*it;
+ break;
+ }
+ }
- // Get the target specific parser.
- std::string Error;
- const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
- if (TheTarget)
- return TheTarget;
+ if (!TheTarget) {
+ errs() << ProgName << ": error: invalid target '" << ArchName << "'.\n";
+ return 0;
+ }
- errs() << ProgName << ": error: unable to get target for '" << TripleName
- << "', see --version and --triple.\n";
- return 0;
+ // Adjust the triple to match (if known), otherwise stick with the
+ // module/host triple.
+ Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
+ if (Type != Triple::UnknownArch)
+ TheTriple.setArch(Type);
+ } else {
+ // Get the target specific parser.
+ std::string Error;
+ TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error);
+ if (TheTarget == 0) {
+ errs() << ProgName << ": error: unable to get target for '"
+ << TheTriple.getTriple()
+ << "', see --version and --triple.\n";
+ return 0;
+ }
+ }
+
+ TripleName = TheTriple.getTriple();
+ return TheTarget;
}
static tool_output_file *GetOutputStream() {
@@ -309,28 +364,27 @@ static int AssembleInput(const char *ProgName) {
llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName));
assert(MAI && "Unable to create target asm info!");
- // Package up features to be passed to target/subtarget
- std::string FeaturesStr;
+ llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
+ assert(MRI && "Unable to create target register info!");
- // 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 (.e.g,
- // the .cpu and .code16 directives).
- OwningPtr<TargetMachine> TM(TheTarget->createTargetMachine(TripleName,
- MCPU,
- FeaturesStr));
-
- if (!TM) {
- errs() << ProgName << ": error: could not create target for triple '"
- << TripleName << "'.\n";
- return 1;
- }
+ // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
+ // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
+ OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
+ MCContext Ctx(*MAI, *MRI, MOFI.get());
+ MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx);
- const TargetAsmInfo *tai = new TargetAsmInfo(*TM);
- MCContext Ctx(*MAI, tai);
if (SaveTempLabels)
Ctx.setAllowTemporaryLabels(false);
+ // Package up features to be passed to target/subtarget
+ std::string FeaturesStr;
+ if (MAttrs.size()) {
+ SubtargetFeatures Features;
+ for (unsigned i = 0; i != MAttrs.size(); ++i)
+ Features.AddFeature(MAttrs[i]);
+ FeaturesStr = Features.getString();
+ }
+
OwningPtr<tool_output_file> Out(GetOutputStream());
if (!Out)
return 1;
@@ -338,10 +392,6 @@ static int AssembleInput(const char *ProgName) {
formatted_raw_ostream FOS(Out->os());
OwningPtr<MCStreamer> Str;
- const TargetLoweringObjectFile &TLOF =
- TM->getTargetLowering()->getObjFileLowering();
- const_cast<TargetLoweringObjectFile&>(TLOF).Initialize(Ctx, *TM);
-
OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
OwningPtr<MCSubtargetInfo>
STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
@@ -349,35 +399,35 @@ static int AssembleInput(const char *ProgName) {
// FIXME: There is a bit of code duplication with addPassesToEmitFile.
if (FileType == OFT_AssemblyFile) {
MCInstPrinter *IP =
- TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI);
+ TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *STI);
MCCodeEmitter *CE = 0;
- TargetAsmBackend *TAB = 0;
+ MCAsmBackend *MAB = 0;
if (ShowEncoding) {
- CE = TheTarget->createCodeEmitter(*MCII, *STI, Ctx);
- TAB = TheTarget->createAsmBackend(TripleName);
+ CE = TheTarget->createMCCodeEmitter(*MCII, *STI, Ctx);
+ MAB = TheTarget->createMCAsmBackend(TripleName);
}
Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/true,
/*useLoc*/ true,
- /*useCFI*/ true, IP, CE, TAB,
+ /*useCFI*/ true, IP, CE, MAB,
ShowInst));
} else if (FileType == OFT_Null) {
Str.reset(createNullStreamer(Ctx));
} else {
assert(FileType == OFT_ObjectFile && "Invalid file type!");
- MCCodeEmitter *CE = TheTarget->createCodeEmitter(*MCII, *STI, Ctx);
- TargetAsmBackend *TAB = TheTarget->createAsmBackend(TripleName);
- Str.reset(TheTarget->createObjectStreamer(TripleName, Ctx, *TAB,
- FOS, CE, RelaxAll,
- NoExecStack));
+ MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *STI, Ctx);
+ MCAsmBackend *MAB = TheTarget->createMCAsmBackend(TripleName);
+ Str.reset(TheTarget->createMCObjectStreamer(TripleName, Ctx, *MAB,
+ FOS, CE, RelaxAll,
+ NoExecStack));
}
if (EnableLogging) {
Str.reset(createLoggingStreamer(Str.take(), errs()));
}
- OwningPtr<MCAsmParser> Parser(createMCAsmParser(*TheTarget, SrcMgr, Ctx,
- *Str.get(), *MAI));
- OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(*STI, *Parser));
+ OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx,
+ *Str.get(), *MAI));
+ OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(*STI, *Parser));
if (!TAP) {
errs() << ProgName
<< ": error: this target does not support assembly parsing.\n";
@@ -415,7 +465,16 @@ static int DisassembleInput(const char *ProgName, bool Enhanced) {
Res =
Disassembler::disassembleEnhanced(TripleName, *Buffer.take(), Out->os());
} else {
- Res = Disassembler::disassemble(*TheTarget, TripleName,
+ // Package up features to be passed to target/subtarget
+ std::string FeaturesStr;
+ if (MAttrs.size()) {
+ SubtargetFeatures Features;
+ for (unsigned i = 0; i != MAttrs.size(); ++i)
+ Features.AddFeature(MAttrs[i]);
+ FeaturesStr = Features.getString();
+ }
+
+ Res = Disassembler::disassemble(*TheTarget, TripleName, MCPU, FeaturesStr,
*Buffer.take(), Out->os());
}
@@ -434,12 +493,7 @@ int main(int argc, char **argv) {
// Initialize targets and assembly printers/parsers.
llvm::InitializeAllTargetInfos();
- // FIXME: We shouldn't need to initialize the Target(Machine)s.
- llvm::InitializeAllTargets();
- llvm::InitializeAllMCAsmInfos();
- llvm::InitializeAllMCInstrInfos();
- llvm::InitializeAllMCSubtargetInfos();
- llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
llvm::InitializeAllDisassemblers();
diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp
index 014cb29..550ca4f 100644
--- a/tools/llvm-nm/llvm-nm.cpp
+++ b/tools/llvm-nm/llvm-nm.cpp
@@ -20,6 +20,7 @@
#include "llvm/Module.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Bitcode/Archive.h"
+#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
@@ -270,9 +271,9 @@ static void DumpSymbolNamesFromModule(Module *M) {
static void DumpSymbolNamesFromObject(ObjectFile *obj) {
error_code ec;
- for (ObjectFile::symbol_iterator i = obj->begin_symbols(),
- e = obj->end_symbols();
- i != e; i.increment(ec)) {
+ for (symbol_iterator i = obj->begin_symbols(),
+ e = obj->end_symbols();
+ i != e; i.increment(ec)) {
if (error(ec)) break;
bool internal;
if (error(i->isInternal(internal))) break;
@@ -285,7 +286,7 @@ static void DumpSymbolNamesFromObject(ObjectFile *obj) {
if (error(i->getSize(s.Size))) break;
}
if (PrintAddress)
- if (error(i->getAddress(s.Address))) break;
+ if (error(i->getOffset(s.Address))) break;
if (error(i->getNMTypeChar(s.TypeChar))) break;
if (error(i->getName(s.Name))) break;
SymbolList.push_back(s);
@@ -318,18 +319,34 @@ static void DumpSymbolNamesFromFile(std::string &Filename) {
errs() << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
} else if (aPath.isArchive()) {
- std::string ErrMsg;
- Archive* archive = Archive::OpenAndLoad(sys::Path(Filename), Context,
- &ErrorMessage);
- if (!archive)
- errs() << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
- std::vector<Module *> Modules;
- if (archive->getAllModules(Modules, &ErrorMessage)) {
- errs() << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
+ OwningPtr<Binary> arch;
+ if (error_code ec = object::createBinary(aPath.str(), arch)) {
+ errs() << ToolName << ": " << Filename << ": " << ec.message() << ".\n";
return;
}
- MultipleFiles = true;
- std::for_each (Modules.begin(), Modules.end(), DumpSymbolNamesFromModule);
+ if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) {
+ for (object::Archive::child_iterator i = a->begin_children(),
+ e = a->end_children(); i != e; ++i) {
+ OwningPtr<Binary> child;
+ if (error_code ec = i->getAsBinary(child)) {
+ // Try opening it as a bitcode file.
+ OwningPtr<MemoryBuffer> buff(i->getBuffer());
+ Module *Result = 0;
+ if (buff)
+ Result = ParseBitcodeFile(buff.get(), Context, &ErrorMessage);
+
+ if (Result) {
+ DumpSymbolNamesFromModule(Result);
+ delete Result;
+ }
+ continue;
+ }
+ if (object::ObjectFile *o = dyn_cast<ObjectFile>(child.get())) {
+ outs() << o->getFileName() << ":\n";
+ DumpSymbolNamesFromObject(o);
+ }
+ }
+ }
} else if (aPath.isObjectFile()) {
OwningPtr<Binary> obj;
if (error_code ec = object::createBinary(aPath.str(), obj)) {
diff --git a/tools/llvm-objdump/CMakeLists.txt b/tools/llvm-objdump/CMakeLists.txt
index 4181b32..f3b2e1f 100644
--- a/tools/llvm-objdump/CMakeLists.txt
+++ b/tools/llvm-objdump/CMakeLists.txt
@@ -1,5 +1,6 @@
set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
+ DebugInfo
MC
MCParser
MCDisassembler
@@ -8,4 +9,6 @@ set(LLVM_LINK_COMPONENTS
add_llvm_tool(llvm-objdump
llvm-objdump.cpp
+ MachODump.cpp
+ MCFunction.cpp
)
diff --git a/tools/llvm-objdump/MCFunction.cpp b/tools/llvm-objdump/MCFunction.cpp
new file mode 100644
index 0000000..5c67f1b
--- /dev/null
+++ b/tools/llvm-objdump/MCFunction.cpp
@@ -0,0 +1,138 @@
+//===-- MCFunction.cpp ----------------------------------------------------===//
+//
+// 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 algorithm to break down a region of machine code
+// into basic blocks and try to reconstruct a CFG from it.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCFunction.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrAnalysis.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+#include <set>
+using namespace llvm;
+
+MCFunction
+MCFunction::createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm,
+ const MemoryObject &Region, uint64_t Start,
+ uint64_t End, const MCInstrAnalysis *Ana,
+ raw_ostream &DebugOut,
+ SmallVectorImpl<uint64_t> &Calls) {
+ std::vector<MCDecodedInst> Instructions;
+ std::set<uint64_t> Splits;
+ Splits.insert(Start);
+ uint64_t Size;
+
+ MCFunction f(Name);
+
+ {
+ DenseSet<uint64_t> VisitedInsts;
+ SmallVector<uint64_t, 16> WorkList;
+ WorkList.push_back(Start);
+ // Disassemble code and gather basic block split points.
+ while (!WorkList.empty()) {
+ uint64_t Index = WorkList.pop_back_val();
+ if (VisitedInsts.find(Index) != VisitedInsts.end())
+ continue; // Already visited this location.
+
+ for (;Index < End; Index += Size) {
+ VisitedInsts.insert(Index);
+
+ MCInst Inst;
+ if (DisAsm->getInstruction(Inst, Size, Region, Index, DebugOut, nulls())){
+ Instructions.push_back(MCDecodedInst(Index, Size, Inst));
+ if (Ana->isBranch(Inst)) {
+ uint64_t targ = Ana->evaluateBranch(Inst, Index, Size);
+ if (targ != -1ULL && targ == Index+Size)
+ continue; // Skip nop jumps.
+
+ // If we could determine the branch target, make a note to start a
+ // new basic block there and add the target to the worklist.
+ if (targ != -1ULL) {
+ Splits.insert(targ);
+ WorkList.push_back(targ);
+ WorkList.push_back(Index+Size);
+ }
+ Splits.insert(Index+Size);
+ break;
+ } else if (Ana->isReturn(Inst)) {
+ // Return instruction. This basic block ends here.
+ Splits.insert(Index+Size);
+ break;
+ } else if (Ana->isCall(Inst)) {
+ uint64_t targ = Ana->evaluateBranch(Inst, Index, Size);
+ // Add the call to the call list if the destination is known.
+ if (targ != -1ULL && targ != Index+Size)
+ Calls.push_back(targ);
+ }
+ } else {
+ errs().write_hex(Index) << ": warning: invalid instruction encoding\n";
+ if (Size == 0)
+ Size = 1; // skip illegible bytes
+ }
+ }
+ }
+ }
+
+ // Make sure the instruction list is sorted.
+ std::sort(Instructions.begin(), Instructions.end());
+
+ // Create basic blocks.
+ unsigned ii = 0, ie = Instructions.size();
+ for (std::set<uint64_t>::iterator spi = Splits.begin(),
+ spe = llvm::prior(Splits.end()); spi != spe; ++spi) {
+ MCBasicBlock BB;
+ uint64_t BlockEnd = *llvm::next(spi);
+ // Add instructions to the BB.
+ for (; ii != ie; ++ii) {
+ if (Instructions[ii].Address < *spi ||
+ Instructions[ii].Address >= BlockEnd)
+ break;
+ BB.addInst(Instructions[ii]);
+ }
+ f.addBlock(*spi, BB);
+ }
+
+ std::sort(f.Blocks.begin(), f.Blocks.end());
+
+ // Calculate successors of each block.
+ for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i) {
+ MCBasicBlock &BB = const_cast<MCBasicBlock&>(i->second);
+ if (BB.getInsts().empty()) continue;
+ const MCDecodedInst &Inst = BB.getInsts().back();
+
+ if (Ana->isBranch(Inst.Inst)) {
+ uint64_t targ = Ana->evaluateBranch(Inst.Inst, Inst.Address, Inst.Size);
+ if (targ == -1ULL) {
+ // Indirect branch. Bail and add all blocks of the function as a
+ // successor.
+ for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i)
+ BB.addSucc(i->first);
+ } else if (targ != Inst.Address+Inst.Size)
+ BB.addSucc(targ);
+ // Conditional branches can also fall through to the next block.
+ if (Ana->isConditionalBranch(Inst.Inst) && llvm::next(i) != e)
+ BB.addSucc(llvm::next(i)->first);
+ } else {
+ // No branch. Fall through to the next block.
+ if (!Ana->isReturn(Inst.Inst) && llvm::next(i) != e)
+ BB.addSucc(llvm::next(i)->first);
+ }
+ }
+
+ return f;
+}
diff --git a/tools/llvm-objdump/MCFunction.h b/tools/llvm-objdump/MCFunction.h
new file mode 100644
index 0000000..6d3a548
--- /dev/null
+++ b/tools/llvm-objdump/MCFunction.h
@@ -0,0 +1,100 @@
+//===-- MCFunction.h ------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the data structures to hold a CFG reconstructed from
+// machine code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTDUMP_MCFUNCTION_H
+#define LLVM_OBJECTDUMP_MCFUNCTION_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/MC/MCInst.h"
+#include <map>
+
+namespace llvm {
+
+class MCDisassembler;
+class MCInstrAnalysis;
+class MemoryObject;
+class raw_ostream;
+
+/// MCDecodedInst - Small container to hold an MCInst and associated info like
+/// address and size.
+struct MCDecodedInst {
+ uint64_t Address;
+ uint64_t Size;
+ MCInst Inst;
+
+ MCDecodedInst() {}
+ MCDecodedInst(uint64_t Address, uint64_t Size, MCInst Inst)
+ : Address(Address), Size(Size), Inst(Inst) {}
+
+ bool operator<(const MCDecodedInst &RHS) const {
+ return Address < RHS.Address;
+ }
+};
+
+/// MCBasicBlock - Consists of multiple MCDecodedInsts and a list of successing
+/// MCBasicBlocks.
+class MCBasicBlock {
+ std::vector<MCDecodedInst> Insts;
+ typedef DenseSet<uint64_t> SetTy;
+ SetTy Succs;
+public:
+ ArrayRef<MCDecodedInst> getInsts() const { return Insts; }
+
+ typedef SetTy::const_iterator succ_iterator;
+ succ_iterator succ_begin() const { return Succs.begin(); }
+ succ_iterator succ_end() const { return Succs.end(); }
+
+ bool contains(uint64_t Addr) const { return Succs.count(Addr); }
+
+ void addInst(const MCDecodedInst &Inst) { Insts.push_back(Inst); }
+ void addSucc(uint64_t Addr) { Succs.insert(Addr); }
+
+ bool operator<(const MCBasicBlock &RHS) const {
+ return Insts.size() < RHS.Insts.size();
+ }
+};
+
+/// MCFunction - Represents a named function in machine code, containing
+/// multiple MCBasicBlocks.
+class MCFunction {
+ const StringRef Name;
+ // Keep BBs sorted by address.
+ typedef std::vector<std::pair<uint64_t, MCBasicBlock> > MapTy;
+ MapTy Blocks;
+public:
+ MCFunction(StringRef Name) : Name(Name) {}
+
+ // Create an MCFunction from a region of binary machine code.
+ static MCFunction
+ createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm,
+ const MemoryObject &Region, uint64_t Start, uint64_t End,
+ const MCInstrAnalysis *Ana, raw_ostream &DebugOut,
+ SmallVectorImpl<uint64_t> &Calls);
+
+ typedef MapTy::const_iterator iterator;
+ iterator begin() const { return Blocks.begin(); }
+ iterator end() const { return Blocks.end(); }
+
+ StringRef getName() const { return Name; }
+
+ MCBasicBlock &addBlock(uint64_t Address, const MCBasicBlock &BB) {
+ Blocks.push_back(std::make_pair(Address, BB));
+ return Blocks.back().second;
+ }
+};
+
+}
+
+#endif
diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp
new file mode 100644
index 0000000..3f44b29
--- /dev/null
+++ b/tools/llvm-objdump/MachODump.cpp
@@ -0,0 +1,617 @@
+//===-- MachODump.cpp - Object file dumping utility for llvm --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the MachO-specific dumper for llvm-objdump.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-objdump.h"
+#include "MCFunction.h"
+#include "llvm/Support/MachO.h"
+#include "llvm/Object/MachOObject.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrAnalysis.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/GraphWriter.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+#include <algorithm>
+#include <cstring>
+using namespace llvm;
+using namespace object;
+
+static cl::opt<bool>
+ CFG("cfg", cl::desc("Create a CFG for every symbol in the object file and"
+ "write it to a graphviz file (MachO-only)"));
+
+static cl::opt<bool>
+ UseDbg("g", cl::desc("Print line information from debug info if available"));
+
+static cl::opt<std::string>
+ DSYMFile("dsym", cl::desc("Use .dSYM file for debug info"));
+
+static const Target *GetTarget(const MachOObject *MachOObj) {
+ // Figure out the target triple.
+ llvm::Triple TT("unknown-unknown-unknown");
+ switch (MachOObj->getHeader().CPUType) {
+ case llvm::MachO::CPUTypeI386:
+ TT.setArch(Triple::ArchType(Triple::x86));
+ break;
+ case llvm::MachO::CPUTypeX86_64:
+ TT.setArch(Triple::ArchType(Triple::x86_64));
+ break;
+ case llvm::MachO::CPUTypeARM:
+ TT.setArch(Triple::ArchType(Triple::arm));
+ break;
+ case llvm::MachO::CPUTypePowerPC:
+ TT.setArch(Triple::ArchType(Triple::ppc));
+ break;
+ case llvm::MachO::CPUTypePowerPC64:
+ TT.setArch(Triple::ArchType(Triple::ppc64));
+ break;
+ }
+
+ TripleName = TT.str();
+
+ // Get the target specific parser.
+ std::string Error;
+ const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
+ if (TheTarget)
+ return TheTarget;
+
+ errs() << "llvm-objdump: error: unable to get target for '" << TripleName
+ << "', see --version and --triple.\n";
+ return 0;
+}
+
+struct Section {
+ char Name[16];
+ uint64_t Address;
+ uint64_t Size;
+ uint32_t Offset;
+ uint32_t NumRelocs;
+ uint64_t RelocTableOffset;
+};
+
+struct Symbol {
+ uint64_t Value;
+ uint32_t StringIndex;
+ uint8_t SectionIndex;
+ bool operator<(const Symbol &RHS) const { return Value < RHS.Value; }
+};
+
+template <typename T>
+static Section copySection(const T &Sect) {
+ Section S;
+ memcpy(S.Name, Sect->Name, 16);
+ S.Address = Sect->Address;
+ S.Size = Sect->Size;
+ S.Offset = Sect->Offset;
+ S.NumRelocs = Sect->NumRelocationTableEntries;
+ S.RelocTableOffset = Sect->RelocationTableOffset;
+ return S;
+}
+
+template <typename T>
+static Symbol copySymbol(const T &STE) {
+ Symbol S;
+ S.StringIndex = STE->StringIndex;
+ S.SectionIndex = STE->SectionIndex;
+ S.Value = STE->Value;
+ return S;
+}
+
+// Print additional information about an address, if available.
+static void DumpAddress(uint64_t Address, ArrayRef<Section> Sections,
+ MachOObject *MachOObj, raw_ostream &OS) {
+ for (unsigned i = 0; i != Sections.size(); ++i) {
+ uint64_t addr = Address-Sections[i].Address;
+ if (Sections[i].Address <= Address &&
+ Sections[i].Address + Sections[i].Size > Address) {
+ StringRef bytes = MachOObj->getData(Sections[i].Offset,
+ Sections[i].Size);
+ // Print constant strings.
+ if (!strcmp(Sections[i].Name, "__cstring"))
+ OS << '"' << bytes.substr(addr, bytes.find('\0', addr)) << '"';
+ // Print constant CFStrings.
+ if (!strcmp(Sections[i].Name, "__cfstring"))
+ OS << "@\"" << bytes.substr(addr, bytes.find('\0', addr)) << '"';
+ }
+ }
+}
+
+typedef std::map<uint64_t, MCFunction*> FunctionMapTy;
+typedef SmallVector<MCFunction, 16> FunctionListTy;
+static void createMCFunctionAndSaveCalls(StringRef Name,
+ const MCDisassembler *DisAsm,
+ MemoryObject &Object, uint64_t Start,
+ uint64_t End,
+ MCInstrAnalysis *InstrAnalysis,
+ uint64_t Address,
+ raw_ostream &DebugOut,
+ FunctionMapTy &FunctionMap,
+ FunctionListTy &Functions) {
+ SmallVector<uint64_t, 16> Calls;
+ MCFunction f =
+ MCFunction::createFunctionFromMC(Name, DisAsm, Object, Start, End,
+ InstrAnalysis, DebugOut, Calls);
+ Functions.push_back(f);
+ FunctionMap[Address] = &Functions.back();
+
+ // Add the gathered callees to the map.
+ for (unsigned i = 0, e = Calls.size(); i != e; ++i)
+ FunctionMap.insert(std::make_pair(Calls[i], (MCFunction*)0));
+}
+
+// Write a graphviz file for the CFG inside an MCFunction.
+static void emitDOTFile(const char *FileName, const MCFunction &f,
+ MCInstPrinter *IP) {
+ // Start a new dot file.
+ std::string Error;
+ raw_fd_ostream Out(FileName, Error);
+ if (!Error.empty()) {
+ errs() << "llvm-objdump: warning: " << Error << '\n';
+ return;
+ }
+
+ Out << "digraph " << f.getName() << " {\n";
+ Out << "graph [ rankdir = \"LR\" ];\n";
+ for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i) {
+ bool hasPreds = false;
+ // Only print blocks that have predecessors.
+ // FIXME: Slow.
+ for (MCFunction::iterator pi = f.begin(), pe = f.end(); pi != pe;
+ ++pi)
+ if (pi->second.contains(i->first)) {
+ hasPreds = true;
+ break;
+ }
+
+ if (!hasPreds && i != f.begin())
+ continue;
+
+ Out << '"' << i->first << "\" [ label=\"<a>";
+ // Print instructions.
+ for (unsigned ii = 0, ie = i->second.getInsts().size(); ii != ie;
+ ++ii) {
+ // Escape special chars and print the instruction in mnemonic form.
+ std::string Str;
+ raw_string_ostream OS(Str);
+ IP->printInst(&i->second.getInsts()[ii].Inst, OS, "");
+ Out << DOT::EscapeString(OS.str()) << '|';
+ }
+ Out << "<o>\" shape=\"record\" ];\n";
+
+ // Add edges.
+ for (MCBasicBlock::succ_iterator si = i->second.succ_begin(),
+ se = i->second.succ_end(); si != se; ++si)
+ Out << i->first << ":o -> " << *si <<":a\n";
+ }
+ Out << "}\n";
+}
+
+static void getSectionsAndSymbols(const macho::Header &Header,
+ MachOObject *MachOObj,
+ InMemoryStruct<macho::SymtabLoadCommand> *SymtabLC,
+ std::vector<Section> &Sections,
+ std::vector<Symbol> &Symbols,
+ SmallVectorImpl<uint64_t> &FoundFns) {
+ // Make a list of all symbols in the object file.
+ for (unsigned i = 0; i != Header.NumLoadCommands; ++i) {
+ const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i);
+ if (LCI.Command.Type == macho::LCT_Segment) {
+ InMemoryStruct<macho::SegmentLoadCommand> SegmentLC;
+ MachOObj->ReadSegmentLoadCommand(LCI, SegmentLC);
+
+ // Store the sections in this segment.
+ for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) {
+ InMemoryStruct<macho::Section> Sect;
+ MachOObj->ReadSection(LCI, SectNum, Sect);
+ Sections.push_back(copySection(Sect));
+
+ }
+ } else if (LCI.Command.Type == macho::LCT_Segment64) {
+ InMemoryStruct<macho::Segment64LoadCommand> Segment64LC;
+ MachOObj->ReadSegment64LoadCommand(LCI, Segment64LC);
+
+ // Store the sections in this segment.
+ for (unsigned SectNum = 0; SectNum != Segment64LC->NumSections;
+ ++SectNum) {
+ InMemoryStruct<macho::Section64> Sect64;
+ MachOObj->ReadSection64(LCI, SectNum, Sect64);
+ Sections.push_back(copySection(Sect64));
+ }
+ } else if (LCI.Command.Type == macho::LCT_FunctionStarts) {
+ // We found a function starts segment, parse the addresses for later
+ // consumption.
+ InMemoryStruct<macho::LinkeditDataLoadCommand> LLC;
+ MachOObj->ReadLinkeditDataLoadCommand(LCI, LLC);
+
+ MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns);
+ }
+ }
+ // Store the symbols.
+ if (SymtabLC) {
+ for (unsigned i = 0; i != (*SymtabLC)->NumSymbolTableEntries; ++i) {
+ if (MachOObj->is64Bit()) {
+ InMemoryStruct<macho::Symbol64TableEntry> STE;
+ MachOObj->ReadSymbol64TableEntry((*SymtabLC)->SymbolTableOffset, i,
+ STE);
+ Symbols.push_back(copySymbol(STE));
+ } else {
+ InMemoryStruct<macho::SymbolTableEntry> STE;
+ MachOObj->ReadSymbolTableEntry((*SymtabLC)->SymbolTableOffset, i,
+ STE);
+ Symbols.push_back(copySymbol(STE));
+ }
+ }
+ }
+}
+
+void llvm::DisassembleInputMachO(StringRef Filename) {
+ OwningPtr<MemoryBuffer> Buff;
+
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
+ errs() << "llvm-objdump: " << Filename << ": " << ec.message() << "\n";
+ return;
+ }
+
+ OwningPtr<MachOObject> MachOObj(MachOObject::LoadFromBuffer(Buff.take()));
+
+ const Target *TheTarget = GetTarget(MachOObj.get());
+ if (!TheTarget) {
+ // GetTarget prints out stuff.
+ return;
+ }
+ OwningPtr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
+ OwningPtr<MCInstrAnalysis>
+ InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo.get()));
+
+ // Set up disassembler.
+ OwningPtr<const MCAsmInfo> AsmInfo(TheTarget->createMCAsmInfo(TripleName));
+ OwningPtr<const MCSubtargetInfo>
+ STI(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
+ OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI));
+ int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
+ OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
+ AsmPrinterVariant, *AsmInfo, *STI));
+
+ if (!InstrAnalysis || !AsmInfo || !STI || !DisAsm || !IP) {
+ errs() << "error: couldn't initialize disassembler for target "
+ << TripleName << '\n';
+ return;
+ }
+
+ outs() << '\n' << Filename << ":\n\n";
+
+ const macho::Header &Header = MachOObj->getHeader();
+
+ const MachOObject::LoadCommandInfo *SymtabLCI = 0;
+ // First, find the symbol table segment.
+ for (unsigned i = 0; i != Header.NumLoadCommands; ++i) {
+ const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i);
+ if (LCI.Command.Type == macho::LCT_Symtab) {
+ SymtabLCI = &LCI;
+ break;
+ }
+ }
+
+ // Read and register the symbol table data.
+ InMemoryStruct<macho::SymtabLoadCommand> SymtabLC;
+ MachOObj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC);
+ MachOObj->RegisterStringTable(*SymtabLC);
+
+ std::vector<Section> Sections;
+ std::vector<Symbol> Symbols;
+ SmallVector<uint64_t, 8> FoundFns;
+
+ getSectionsAndSymbols(Header, MachOObj.get(), &SymtabLC, Sections, Symbols,
+ FoundFns);
+
+ // Make a copy of the unsorted symbol list. FIXME: duplication
+ std::vector<Symbol> UnsortedSymbols(Symbols);
+ // Sort the symbols by address, just in case they didn't come in that way.
+ array_pod_sort(Symbols.begin(), Symbols.end());
+
+#ifndef NDEBUG
+ raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
+#else
+ raw_ostream &DebugOut = nulls();
+#endif
+
+ StringRef DebugAbbrevSection, DebugInfoSection, DebugArangesSection,
+ DebugLineSection, DebugStrSection;
+ OwningPtr<DIContext> diContext;
+ OwningPtr<MachOObject> DSYMObj;
+ MachOObject *DbgInfoObj = MachOObj.get();
+ // Try to find debug info and set up the DIContext for it.
+ if (UseDbg) {
+ ArrayRef<Section> DebugSections = Sections;
+ std::vector<Section> DSYMSections;
+
+ // A separate DSym file path was specified, parse it as a macho file,
+ // get the sections and supply it to the section name parsing machinery.
+ if (!DSYMFile.empty()) {
+ OwningPtr<MemoryBuffer> Buf;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(DSYMFile.c_str(), Buf)) {
+ errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n';
+ return;
+ }
+ DSYMObj.reset(MachOObject::LoadFromBuffer(Buf.take()));
+ const macho::Header &Header = DSYMObj->getHeader();
+
+ std::vector<Symbol> Symbols;
+ SmallVector<uint64_t, 8> FoundFns;
+ getSectionsAndSymbols(Header, DSYMObj.get(), 0, DSYMSections, Symbols,
+ FoundFns);
+ DebugSections = DSYMSections;
+ DbgInfoObj = DSYMObj.get();
+ }
+
+ // Find the named debug info sections.
+ for (unsigned SectIdx = 0; SectIdx != DebugSections.size(); SectIdx++) {
+ if (!strcmp(DebugSections[SectIdx].Name, "__debug_abbrev"))
+ DebugAbbrevSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset,
+ DebugSections[SectIdx].Size);
+ else if (!strcmp(DebugSections[SectIdx].Name, "__debug_info"))
+ DebugInfoSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset,
+ DebugSections[SectIdx].Size);
+ else if (!strcmp(DebugSections[SectIdx].Name, "__debug_aranges"))
+ DebugArangesSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset,
+ DebugSections[SectIdx].Size);
+ else if (!strcmp(DebugSections[SectIdx].Name, "__debug_line"))
+ DebugLineSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset,
+ DebugSections[SectIdx].Size);
+ else if (!strcmp(DebugSections[SectIdx].Name, "__debug_str"))
+ DebugStrSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset,
+ DebugSections[SectIdx].Size);
+ }
+
+ // Setup the DIContext.
+ diContext.reset(DIContext::getDWARFContext(DbgInfoObj->isLittleEndian(),
+ DebugInfoSection,
+ DebugAbbrevSection,
+ DebugArangesSection,
+ DebugLineSection,
+ DebugStrSection));
+ }
+
+ FunctionMapTy FunctionMap;
+ FunctionListTy Functions;
+
+ for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
+ if (strcmp(Sections[SectIdx].Name, "__text"))
+ continue; // Skip non-text sections
+
+ // Insert the functions from the function starts segment into our map.
+ uint64_t VMAddr = Sections[SectIdx].Address - Sections[SectIdx].Offset;
+ for (unsigned i = 0, e = FoundFns.size(); i != e; ++i)
+ FunctionMap.insert(std::make_pair(FoundFns[i]+VMAddr, (MCFunction*)0));
+
+ StringRef Bytes = MachOObj->getData(Sections[SectIdx].Offset,
+ Sections[SectIdx].Size);
+ StringRefMemoryObject memoryObject(Bytes);
+ bool symbolTableWorked = false;
+
+ // Parse relocations.
+ std::vector<std::pair<uint64_t, uint32_t> > Relocs;
+ for (unsigned j = 0; j != Sections[SectIdx].NumRelocs; ++j) {
+ InMemoryStruct<macho::RelocationEntry> RE;
+ MachOObj->ReadRelocationEntry(Sections[SectIdx].RelocTableOffset, j, RE);
+ Relocs.push_back(std::make_pair(RE->Word0, RE->Word1 & 0xffffff));
+ }
+ array_pod_sort(Relocs.begin(), Relocs.end());
+
+ // Disassemble symbol by symbol.
+ for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
+ // Make sure the symbol is defined in this section.
+ if ((unsigned)Symbols[SymIdx].SectionIndex - 1 != SectIdx)
+ continue;
+
+ // Start at the address of the symbol relative to the section's address.
+ uint64_t Start = Symbols[SymIdx].Value - Sections[SectIdx].Address;
+ // Stop disassembling either at the beginning of the next symbol or at
+ // the end of the section.
+ uint64_t End = (SymIdx+1 == Symbols.size() ||
+ Symbols[SymIdx].SectionIndex != Symbols[SymIdx+1].SectionIndex) ?
+ Sections[SectIdx].Size :
+ Symbols[SymIdx+1].Value - Sections[SectIdx].Address;
+ uint64_t Size;
+
+ if (Start >= End)
+ continue;
+
+ symbolTableWorked = true;
+
+ if (!CFG) {
+ // Normal disassembly, print addresses, bytes and mnemonic form.
+ outs() << MachOObj->getStringAtIndex(Symbols[SymIdx].StringIndex)
+ << ":\n";
+ DILineInfo lastLine;
+ for (uint64_t Index = Start; Index < End; Index += Size) {
+ MCInst Inst;
+
+ if (DisAsm->getInstruction(Inst, Size, memoryObject, Index,
+ DebugOut, nulls())) {
+ outs() << format("%8llx:\t", Sections[SectIdx].Address + Index);
+ DumpBytes(StringRef(Bytes.data() + Index, Size));
+ IP->printInst(&Inst, outs(), "");
+
+ // Print debug info.
+ if (diContext) {
+ DILineInfo dli =
+ diContext->getLineInfoForAddress(Sections[SectIdx].Address +
+ Index);
+ // Print valid line info if it changed.
+ if (dli != lastLine && dli.getLine() != 0)
+ outs() << "\t## " << dli.getFileName() << ':'
+ << dli.getLine() << ':' << dli.getColumn();
+ lastLine = dli;
+ }
+ outs() << "\n";
+ } else {
+ errs() << "llvm-objdump: warning: invalid instruction encoding\n";
+ if (Size == 0)
+ Size = 1; // skip illegible bytes
+ }
+ }
+ } else {
+ // Create CFG and use it for disassembly.
+ createMCFunctionAndSaveCalls(
+ MachOObj->getStringAtIndex(Symbols[SymIdx].StringIndex),
+ DisAsm.get(), memoryObject, Start, End, InstrAnalysis.get(),
+ Start, DebugOut, FunctionMap, Functions);
+ }
+ }
+
+ if (CFG) {
+ if (!symbolTableWorked) {
+ // Reading the symbol table didn't work, create a big __TEXT symbol.
+ createMCFunctionAndSaveCalls("__TEXT", DisAsm.get(), memoryObject,
+ 0, Sections[SectIdx].Size,
+ InstrAnalysis.get(),
+ Sections[SectIdx].Offset, DebugOut,
+ FunctionMap, Functions);
+ }
+ for (std::map<uint64_t, MCFunction*>::iterator mi = FunctionMap.begin(),
+ me = FunctionMap.end(); mi != me; ++mi)
+ if (mi->second == 0) {
+ // Create functions for the remaining callees we have gathered,
+ // but we didn't find a name for them.
+ SmallVector<uint64_t, 16> Calls;
+ MCFunction f =
+ MCFunction::createFunctionFromMC("unknown", DisAsm.get(),
+ memoryObject, mi->first,
+ Sections[SectIdx].Size,
+ InstrAnalysis.get(), DebugOut,
+ Calls);
+ Functions.push_back(f);
+ mi->second = &Functions.back();
+ for (unsigned i = 0, e = Calls.size(); i != e; ++i) {
+ std::pair<uint64_t, MCFunction*> p(Calls[i], (MCFunction*)0);
+ if (FunctionMap.insert(p).second)
+ mi = FunctionMap.begin();
+ }
+ }
+
+ DenseSet<uint64_t> PrintedBlocks;
+ for (unsigned ffi = 0, ffe = Functions.size(); ffi != ffe; ++ffi) {
+ MCFunction &f = Functions[ffi];
+ for (MCFunction::iterator fi = f.begin(), fe = f.end(); fi != fe; ++fi){
+ if (!PrintedBlocks.insert(fi->first).second)
+ continue; // We already printed this block.
+
+ // We assume a block has predecessors when it's the first block after
+ // a symbol.
+ bool hasPreds = FunctionMap.find(fi->first) != FunctionMap.end();
+
+ // See if this block has predecessors.
+ // FIXME: Slow.
+ for (MCFunction::iterator pi = f.begin(), pe = f.end(); pi != pe;
+ ++pi)
+ if (pi->second.contains(fi->first)) {
+ hasPreds = true;
+ break;
+ }
+
+ // No predecessors, this is a data block. Print as .byte directives.
+ if (!hasPreds) {
+ uint64_t End = llvm::next(fi) == fe ? Sections[SectIdx].Size :
+ llvm::next(fi)->first;
+ outs() << "# " << End-fi->first << " bytes of data:\n";
+ for (unsigned pos = fi->first; pos != End; ++pos) {
+ outs() << format("%8x:\t", Sections[SectIdx].Address + pos);
+ DumpBytes(StringRef(Bytes.data() + pos, 1));
+ outs() << format("\t.byte 0x%02x\n", (uint8_t)Bytes[pos]);
+ }
+ continue;
+ }
+
+ if (fi->second.contains(fi->first)) // Print a header for simple loops
+ outs() << "# Loop begin:\n";
+
+ DILineInfo lastLine;
+ // Walk over the instructions and print them.
+ for (unsigned ii = 0, ie = fi->second.getInsts().size(); ii != ie;
+ ++ii) {
+ const MCDecodedInst &Inst = fi->second.getInsts()[ii];
+
+ // If there's a symbol at this address, print its name.
+ if (FunctionMap.find(Sections[SectIdx].Address + Inst.Address) !=
+ FunctionMap.end())
+ outs() << FunctionMap[Sections[SectIdx].Address + Inst.Address]->
+ getName() << ":\n";
+
+ outs() << format("%8llx:\t", Sections[SectIdx].Address +
+ Inst.Address);
+ DumpBytes(StringRef(Bytes.data() + Inst.Address, Inst.Size));
+
+ if (fi->second.contains(fi->first)) // Indent simple loops.
+ outs() << '\t';
+
+ IP->printInst(&Inst.Inst, outs(), "");
+
+ // Look for relocations inside this instructions, if there is one
+ // print its target and additional information if available.
+ for (unsigned j = 0; j != Relocs.size(); ++j)
+ if (Relocs[j].first >= Sections[SectIdx].Address + Inst.Address &&
+ Relocs[j].first < Sections[SectIdx].Address + Inst.Address +
+ Inst.Size) {
+ outs() << "\t# "
+ << MachOObj->getStringAtIndex(
+ UnsortedSymbols[Relocs[j].second].StringIndex)
+ << ' ';
+ DumpAddress(UnsortedSymbols[Relocs[j].second].Value, Sections,
+ MachOObj.get(), outs());
+ }
+
+ // If this instructions contains an address, see if we can evaluate
+ // it and print additional information.
+ uint64_t targ = InstrAnalysis->evaluateBranch(Inst.Inst,
+ Inst.Address,
+ Inst.Size);
+ if (targ != -1ULL)
+ DumpAddress(targ, Sections, MachOObj.get(), outs());
+
+ // Print debug info.
+ if (diContext) {
+ DILineInfo dli =
+ diContext->getLineInfoForAddress(Sections[SectIdx].Address +
+ Inst.Address);
+ // Print valid line info if it changed.
+ if (dli != lastLine && dli.getLine() != 0)
+ outs() << "\t## " << dli.getFileName() << ':'
+ << dli.getLine() << ':' << dli.getColumn();
+ lastLine = dli;
+ }
+
+ outs() << '\n';
+ }
+ }
+
+ emitDOTFile((f.getName().str() + ".dot").c_str(), f, IP.get());
+ }
+ }
+ }
+}
diff --git a/tools/llvm-objdump/Makefile b/tools/llvm-objdump/Makefile
index 4d7cd34..703bf6c 100644
--- a/tools/llvm-objdump/Makefile
+++ b/tools/llvm-objdump/Makefile
@@ -9,7 +9,8 @@
LEVEL = ../..
TOOLNAME = llvm-objdump
-LINK_COMPONENTS = $(TARGETS_TO_BUILD) MC MCParser MCDisassembler Object
+LINK_COMPONENTS = $(TARGETS_TO_BUILD) DebugInfo MC MCParser MCDisassembler \
+ Object
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index 4079e4a..4ae13be 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -13,6 +13,9 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm-objdump.h"
+#include "MCFunction.h"
+#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/Triple.h"
@@ -21,9 +24,13 @@
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -31,44 +38,59 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetSelect.h"
#include <algorithm>
#include <cstring>
using namespace llvm;
using namespace object;
-namespace {
- cl::list<std::string>
- InputFilenames(cl::Positional, cl::desc("<input object files>"),
- cl::ZeroOrMore);
+static cl::list<std::string>
+InputFilenames(cl::Positional, cl::desc("<input object files>"),cl::ZeroOrMore);
- cl::opt<bool>
- Disassemble("disassemble",
- cl::desc("Display assembler mnemonics for the machine instructions"));
- cl::alias
- Disassembled("d", cl::desc("Alias for --disassemble"),
- cl::aliasopt(Disassemble));
+static cl::opt<bool>
+Disassemble("disassemble",
+ cl::desc("Display assembler mnemonics for the machine instructions"));
+static cl::alias
+Disassembled("d", cl::desc("Alias for --disassemble"),
+ cl::aliasopt(Disassemble));
- cl::opt<std::string>
- TripleName("triple", cl::desc("Target triple to disassemble for, "
+static cl::opt<bool>
+Relocations("r", cl::desc("Display the relocation entries in the file"));
+
+static cl::opt<bool>
+MachO("macho", cl::desc("Use MachO specific object file parser"));
+static cl::alias
+MachOm("m", cl::desc("Alias for --macho"), cl::aliasopt(MachO));
+
+cl::opt<std::string>
+llvm::TripleName("triple", cl::desc("Target triple to disassemble for, "
+ "see -version for available targets"));
+
+cl::opt<std::string>
+llvm::ArchName("arch", cl::desc("Target arch to disassemble for, "
"see -version for available targets"));
- cl::opt<std::string>
- ArchName("arch", cl::desc("Target arch to disassemble for, "
- "see -version for available targets"));
+static cl::opt<bool>
+SectionHeaders("section-headers", cl::desc("Display summaries of the headers "
+ "for each section."));
+static cl::alias
+SectionHeadersShort("headers", cl::desc("Alias for --section-headers"),
+ cl::aliasopt(SectionHeaders));
+static cl::alias
+SectionHeadersShorter("h", cl::desc("Alias for --section-headers"),
+ cl::aliasopt(SectionHeaders));
- StringRef ToolName;
+static StringRef ToolName;
- bool error(error_code ec) {
- if (!ec) return false;
+static bool error(error_code ec) {
+ if (!ec) return false;
- outs() << ToolName << ": error reading file: " << ec.message() << ".\n";
- outs().flush();
- return true;
- }
+ outs() << ToolName << ": error reading file: " << ec.message() << ".\n";
+ outs().flush();
+ return true;
}
static const Target *GetTarget(const ObjectFile *Obj = NULL) {
@@ -96,27 +118,8 @@ static const Target *GetTarget(const ObjectFile *Obj = NULL) {
return 0;
}
-namespace {
-class StringRefMemoryObject : public MemoryObject {
-private:
- StringRef Bytes;
-public:
- StringRefMemoryObject(StringRef bytes) : Bytes(bytes) {}
-
- uint64_t getBase() const { return 0; }
- uint64_t getExtent() const { return Bytes.size(); }
-
- int readByte(uint64_t Addr, uint8_t *Byte) const {
- if (Addr > getExtent())
- return -1;
- *Byte = Bytes[Addr];
- return 0;
- }
-};
-}
-
-static void DumpBytes(StringRef bytes) {
- static char hex_rep[] = "0123456789abcdef";
+void llvm::DumpBytes(StringRef bytes) {
+ static const char hex_rep[] = "0123456789abcdef";
// FIXME: The real way to do this is to figure out the longest instruction
// and align to that size before printing. I'll fix this when I get
// around to outputting relocations.
@@ -141,44 +144,45 @@ static void DumpBytes(StringRef bytes) {
outs() << output;
}
-static void DisassembleInput(const StringRef &Filename) {
- OwningPtr<MemoryBuffer> Buff;
-
- if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
- errs() << ToolName << ": " << Filename << ": " << ec.message() << "\n";
- return;
- }
-
- OwningPtr<ObjectFile> Obj(ObjectFile::createObjectFile(Buff.take()));
+static bool RelocAddressLess(RelocationRef a, RelocationRef b) {
+ uint64_t a_addr, b_addr;
+ if (error(a.getAddress(a_addr))) return false;
+ if (error(b.getAddress(b_addr))) return false;
+ return a_addr < b_addr;
+}
- const Target *TheTarget = GetTarget(Obj.get());
+static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
+ const Target *TheTarget = GetTarget(Obj);
if (!TheTarget) {
// GetTarget prints out stuff.
return;
}
outs() << '\n';
- outs() << Filename
+ outs() << Obj->getFileName()
<< ":\tfile format " << Obj->getFileFormatName() << "\n\n";
error_code ec;
- for (ObjectFile::section_iterator i = Obj->begin_sections(),
- e = Obj->end_sections();
- i != e; i.increment(ec)) {
+ for (section_iterator i = Obj->begin_sections(),
+ e = Obj->end_sections();
+ i != e; i.increment(ec)) {
if (error(ec)) break;
bool text;
if (error(i->isText(text))) break;
if (!text) continue;
+ uint64_t SectionAddr;
+ if (error(i->getAddress(SectionAddr))) break;
+
// Make a list of all the symbols in this section.
std::vector<std::pair<uint64_t, StringRef> > Symbols;
- for (ObjectFile::symbol_iterator si = Obj->begin_symbols(),
- se = Obj->end_symbols();
- si != se; si.increment(ec)) {
+ for (symbol_iterator si = Obj->begin_symbols(),
+ se = Obj->end_symbols();
+ si != se; si.increment(ec)) {
bool contains;
if (!error(i->containsSymbol(*si, contains)) && contains) {
uint64_t Address;
- if (error(si->getAddress(Address))) break;
+ if (error(si->getOffset(Address))) break;
StringRef Name;
if (error(si->getName(Name))) break;
Symbols.push_back(std::make_pair(Address, Name));
@@ -188,6 +192,20 @@ static void DisassembleInput(const StringRef &Filename) {
// Sort the symbols by address, just in case they didn't come in that way.
array_pod_sort(Symbols.begin(), Symbols.end());
+ // Make a list of all the relocations for this section.
+ std::vector<RelocationRef> Rels;
+ if (InlineRelocs) {
+ for (relocation_iterator ri = i->begin_relocations(),
+ re = i->end_relocations();
+ ri != re; ri.increment(ec)) {
+ if (error(ec)) break;
+ Rels.push_back(*ri);
+ }
+ }
+
+ // Sort relocations by address.
+ std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
+
StringRef name;
if (error(i->getName(name))) break;
outs() << "Disassembly of section " << name << ':';
@@ -205,7 +223,16 @@ static void DisassembleInput(const StringRef &Filename) {
return;
}
- OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler());
+ OwningPtr<const MCSubtargetInfo> STI(
+ TheTarget->createMCSubtargetInfo(TripleName, "", ""));
+
+ if (!STI) {
+ errs() << "error: no subtarget info for target " << TripleName << "\n";
+ return;
+ }
+
+ OwningPtr<const MCDisassembler> DisAsm(
+ TheTarget->createMCDisassembler(*STI));
if (!DisAsm) {
errs() << "error: no disassembler for target " << TripleName << "\n";
return;
@@ -213,9 +240,10 @@ static void DisassembleInput(const StringRef &Filename) {
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
- AsmPrinterVariant, *AsmInfo));
+ AsmPrinterVariant, *AsmInfo, *STI));
if (!IP) {
- errs() << "error: no instruction printer for target " << TripleName << '\n';
+ errs() << "error: no instruction printer for target " << TripleName
+ << '\n';
return;
}
@@ -227,14 +255,24 @@ static void DisassembleInput(const StringRef &Filename) {
uint64_t SectSize;
if (error(i->getSize(SectSize))) break;
+ std::vector<RelocationRef>::const_iterator rel_cur = Rels.begin();
+ std::vector<RelocationRef>::const_iterator rel_end = Rels.end();
// Disassemble symbol by symbol.
for (unsigned si = 0, se = Symbols.size(); si != se; ++si) {
uint64_t Start = Symbols[si].first;
- uint64_t End = si == se-1 ? SectSize : Symbols[si + 1].first - 1;
- outs() << '\n' << Symbols[si].second << ":\n";
+ uint64_t End;
+ // The end is either the size of the section or the beginning of the next
+ // symbol.
+ if (si == se - 1)
+ End = SectSize;
+ // Make sure this symbol takes up space.
+ else if (Symbols[si + 1].first != Start)
+ End = Symbols[si + 1].first - 1;
+ else
+ // This symbol has the same address as the next symbol. Skip it.
+ continue;
- for (Index = Start; Index < End; Index += Size) {
- MCInst Inst;
+ outs() << '\n' << Symbols[si].second << ":\n";
#ifndef NDEBUG
raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
@@ -242,23 +280,152 @@ static void DisassembleInput(const StringRef &Filename) {
raw_ostream &DebugOut = nulls();
#endif
- if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, DebugOut)) {
- uint64_t addr;
- if (error(i->getAddress(addr))) break;
- outs() << format("%8x:\t", addr + Index);
+ for (Index = Start; Index < End; Index += Size) {
+ MCInst Inst;
+
+ if (DisAsm->getInstruction(Inst, Size, memoryObject, Index,
+ DebugOut, nulls())) {
+ outs() << format("%8x:\t", SectionAddr + Index);
DumpBytes(StringRef(Bytes.data() + Index, Size));
- IP->printInst(&Inst, outs());
+ IP->printInst(&Inst, outs(), "");
outs() << "\n";
} else {
errs() << ToolName << ": warning: invalid instruction encoding\n";
if (Size == 0)
Size = 1; // skip illegible bytes
}
+
+ // Print relocation for instruction.
+ while (rel_cur != rel_end) {
+ uint64_t addr;
+ SmallString<16> name;
+ SmallString<32> val;
+ if (error(rel_cur->getAddress(addr))) goto skip_print_rel;
+ // Stop when rel_cur's address is past the current instruction.
+ if (addr > Index + Size) break;
+ if (error(rel_cur->getTypeName(name))) goto skip_print_rel;
+ if (error(rel_cur->getValueString(val))) goto skip_print_rel;
+
+ outs() << format("\t\t\t%8x: ", SectionAddr + addr) << name << "\t"
+ << val << "\n";
+
+ skip_print_rel:
+ ++rel_cur;
+ }
}
}
}
}
+static void PrintRelocations(const ObjectFile *o) {
+ error_code ec;
+ for (section_iterator si = o->begin_sections(), se = o->end_sections();
+ si != se; si.increment(ec)){
+ if (error(ec)) return;
+ if (si->begin_relocations() == si->end_relocations())
+ continue;
+ StringRef secname;
+ if (error(si->getName(secname))) continue;
+ outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n";
+ for (relocation_iterator ri = si->begin_relocations(),
+ re = si->end_relocations();
+ ri != re; ri.increment(ec)) {
+ if (error(ec)) return;
+
+ uint64_t address;
+ SmallString<32> relocname;
+ SmallString<32> valuestr;
+ if (error(ri->getTypeName(relocname))) continue;
+ if (error(ri->getAddress(address))) continue;
+ if (error(ri->getValueString(valuestr))) continue;
+ outs() << address << " " << relocname << " " << valuestr << "\n";
+ }
+ outs() << "\n";
+ }
+}
+
+static void PrintSectionHeaders(const ObjectFile *o) {
+ outs() << "Sections:\n"
+ "Idx Name Size Address Type\n";
+ error_code ec;
+ unsigned i = 0;
+ for (section_iterator si = o->begin_sections(), se = o->end_sections();
+ si != se; si.increment(ec)) {
+ if (error(ec)) return;
+ StringRef Name;
+ if (error(si->getName(Name))) return;
+ uint64_t Address;
+ if (error(si->getAddress(Address))) return;
+ uint64_t Size;
+ if (error(si->getSize(Size))) return;
+ bool Text, Data, BSS;
+ if (error(si->isText(Text))) return;
+ if (error(si->isData(Data))) return;
+ if (error(si->isBSS(BSS))) return;
+ std::string Type = (std::string(Text ? "TEXT " : "") +
+ (Data ? "DATA " : "") + (BSS ? "BSS" : ""));
+ outs() << format("%3d %-13s %09"PRIx64" %017"PRIx64" %s\n", i, Name.str().c_str(), Size,
+ Address, Type.c_str());
+ ++i;
+ }
+}
+
+static void DumpObject(const ObjectFile *o) {
+ if (Disassemble)
+ DisassembleObject(o, Relocations);
+ if (Relocations && !Disassemble)
+ PrintRelocations(o);
+ if (SectionHeaders)
+ PrintSectionHeaders(o);
+}
+
+/// @brief Dump each object file in \a a;
+static void DumpArchive(const Archive *a) {
+ for (Archive::child_iterator i = a->begin_children(),
+ e = a->end_children(); i != e; ++i) {
+ OwningPtr<Binary> child;
+ if (error_code ec = i->getAsBinary(child)) {
+ errs() << ToolName << ": '" << a->getFileName() << "': " << ec.message()
+ << ".\n";
+ continue;
+ }
+ if (ObjectFile *o = dyn_cast<ObjectFile>(child.get()))
+ DumpObject(o);
+ else
+ errs() << ToolName << ": '" << a->getFileName() << "': "
+ << "Unrecognized file type.\n";
+ }
+}
+
+/// @brief Open file and figure out how to dump it.
+static void DumpInput(StringRef file) {
+ // If file isn't stdin, check that it exists.
+ if (file != "-" && !sys::fs::exists(file)) {
+ errs() << ToolName << ": '" << file << "': " << "No such file\n";
+ return;
+ }
+
+ if (MachO && Disassemble) {
+ DisassembleInputMachO(file);
+ return;
+ }
+
+ // Attempt to open the binary.
+ OwningPtr<Binary> binary;
+ if (error_code ec = createBinary(file, binary)) {
+ errs() << ToolName << ": '" << file << "': " << ec.message() << ".\n";
+ return;
+ }
+
+ if (Archive *a = dyn_cast<Archive>(binary.get())) {
+ DumpArchive(a);
+ } else if (ObjectFile *o = dyn_cast<ObjectFile>(binary.get())) {
+ DumpObject(o);
+ } else {
+ errs() << ToolName << ": '" << file << "': " << "Unrecognized file type.\n";
+ }
+}
+
int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
@@ -267,10 +434,7 @@ int main(int argc, char **argv) {
// 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();
@@ -283,15 +447,13 @@ int main(int argc, char **argv) {
if (InputFilenames.size() == 0)
InputFilenames.push_back("a.out");
- // -d is the only flag that is currently implemented, so just print help if
- // it is not set.
- if (!Disassemble) {
+ if (!Disassemble && !Relocations && !SectionHeaders) {
cl::PrintHelpMessage();
return 2;
}
std::for_each(InputFilenames.begin(), InputFilenames.end(),
- DisassembleInput);
+ DumpInput);
return 0;
}
diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h
new file mode 100644
index 0000000..75f852a
--- /dev/null
+++ b/tools/llvm-objdump/llvm-objdump.h
@@ -0,0 +1,46 @@
+//===-- llvm-objdump.h ----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJDUMP_H
+#define LLVM_OBJDUMP_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MemoryObject.h"
+
+namespace llvm {
+
+extern cl::opt<std::string> TripleName;
+extern cl::opt<std::string> ArchName;
+
+// Various helper functions.
+void DumpBytes(StringRef bytes);
+void DisassembleInputMachO(StringRef Filename);
+
+class StringRefMemoryObject : public MemoryObject {
+private:
+ StringRef Bytes;
+public:
+ StringRefMemoryObject(StringRef bytes) : Bytes(bytes) {}
+
+ uint64_t getBase() const { return 0; }
+ uint64_t getExtent() const { return Bytes.size(); }
+
+ int readByte(uint64_t Addr, uint8_t *Byte) const {
+ if (Addr >= getExtent())
+ return -1;
+ *Byte = Bytes[Addr];
+ return 0;
+ }
+};
+
+}
+
+#endif
diff --git a/tools/llvm-shlib/Makefile b/tools/llvm-shlib/Makefile
index 9e6faca..0695c00 100644
--- a/tools/llvm-shlib/Makefile
+++ b/tools/llvm-shlib/Makefile
@@ -30,10 +30,11 @@ endif
include $(LEVEL)/Makefile.common
# Include all archives in libLLVM.(so|dylib) except the ones that have
-# their own dynamic libraries.
+# their own dynamic libraries and TableGen.
Archives := $(wildcard $(LibDir)/libLLVM*.a)
SharedLibraries := $(wildcard $(LibDir)/libLLVM*$(SHLIBEXT))
-IncludeInLibLlvm := $(filter-out $(basename $(SharedLibraries)).a, $(Archives))
+ExcludeFromLibLlvm := $(basename $(SharedLibraries)).a %/libLLVMTableGen.a
+IncludeInLibLlvm := $(filter-out $(ExcludeFromLibLlvm), $(Archives))
LLVMLibsOptions := $(IncludeInLibLlvm:$(LibDir)/lib%.a=-l%)
LLVMLibsPaths := $(IncludeInLibLlvm)
diff --git a/tools/llvm-size/CMakeLists.txt b/tools/llvm-size/CMakeLists.txt
new file mode 100644
index 0000000..933cc75
--- /dev/null
+++ b/tools/llvm-size/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_LINK_COMPONENTS object)
+
+add_llvm_tool(llvm-size
+ llvm-size.cpp
+ )
diff --git a/tools/llvm-size/Makefile b/tools/llvm-size/Makefile
new file mode 100644
index 0000000..5d0e27e
--- /dev/null
+++ b/tools/llvm-size/Makefile
@@ -0,0 +1,17 @@
+##===- tools/llvm-size/Makefile ----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+LEVEL = ../..
+
+TOOLNAME = llvm-size
+LINK_COMPONENTS = object
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-size/llvm-size.cpp b/tools/llvm-size/llvm-size.cpp
new file mode 100644
index 0000000..70e5cb9
--- /dev/null
+++ b/tools/llvm-size/llvm-size.cpp
@@ -0,0 +1,311 @@
+//===-- llvm-size.cpp - Print the size of each object section -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This program is a utility that works like traditional Unix "size",
+// that is, it prints out the size of each section, and the total size of all
+// sections.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
+#include <algorithm>
+#include <string>
+using namespace llvm;
+using namespace object;
+
+enum OutputFormatTy {berkeley, sysv};
+static cl::opt<OutputFormatTy>
+ OutputFormat("format",
+ cl::desc("Specify output format"),
+ cl::values(clEnumVal(sysv, "System V format"),
+ clEnumVal(berkeley, "Berkeley format"),
+ clEnumValEnd),
+ cl::init(berkeley));
+
+static cl::opt<OutputFormatTy>
+ OutputFormatShort(cl::desc("Specify output format"),
+ cl::values(clEnumValN(sysv, "A", "System V format"),
+ clEnumValN(berkeley, "B", "Berkeley format"),
+ clEnumValEnd),
+ cl::init(berkeley));
+
+enum RadixTy {octal = 8, decimal = 10, hexadecimal = 16};
+static cl::opt<unsigned int>
+ Radix("-radix",
+ cl::desc("Print size in radix. Only 8, 10, and 16 are valid"),
+ cl::init(decimal));
+
+static cl::opt<RadixTy>
+ RadixShort(cl::desc("Print size in radix:"),
+ cl::values(clEnumValN(octal, "o", "Print size in octal"),
+ clEnumValN(decimal, "d", "Print size in decimal"),
+ clEnumValN(hexadecimal, "x", "Print size in hexadecimal"),
+ clEnumValEnd),
+ cl::init(decimal));
+
+static cl::list<std::string>
+ InputFilenames(cl::Positional, cl::desc("<input files>"),
+ cl::ZeroOrMore);
+
+static std::string ToolName;
+
+/// @brief If ec is not success, print the error and return true.
+static bool error(error_code ec) {
+ if (!ec) return false;
+
+ outs() << ToolName << ": error reading file: " << ec.message() << ".\n";
+ outs().flush();
+ return true;
+}
+
+/// @brief Get the length of the string that represents @p num in Radix
+/// including the leading 0x or 0 for hexadecimal and octal respectively.
+static size_t getNumLengthAsString(uint64_t num) {
+ APInt conv(64, num);
+ SmallString<32> result;
+ conv.toString(result, Radix, false, true);
+ return result.size();
+}
+
+/// @brief Print the size of each section in @p o.
+///
+/// The format used is determined by @c OutputFormat and @c Radix.
+static void PrintObjectSectionSizes(ObjectFile *o) {
+ uint64_t total = 0;
+ std::string fmtbuf;
+ raw_string_ostream fmt(fmtbuf);
+
+ const char *radix_fmt = 0;
+ switch (Radix) {
+ case octal:
+ radix_fmt = "llo";
+ break;
+ case decimal:
+ radix_fmt = "llu";
+ break;
+ case hexadecimal:
+ radix_fmt = "llx";
+ break;
+ }
+ if (OutputFormat == sysv) {
+ // Run two passes over all sections. The first gets the lengths needed for
+ // formatting the output. The second actually does the output.
+ std::size_t max_name_len = strlen("section");
+ std::size_t max_size_len = strlen("size");
+ std::size_t max_addr_len = strlen("addr");
+ error_code ec;
+ for (section_iterator i = o->begin_sections(),
+ e = o->end_sections(); i != e;
+ i.increment(ec)) {
+ if (error(ec))
+ return;
+ uint64_t size = 0;
+ if (error(i->getSize(size)))
+ return;
+ total += size;
+
+ StringRef name;
+ uint64_t addr = 0;
+ if (error(i->getName(name))) return;
+ if (error(i->getAddress(addr))) return;
+ max_name_len = std::max(max_name_len, name.size());
+ max_size_len = std::max(max_size_len, getNumLengthAsString(size));
+ max_addr_len = std::max(max_addr_len, getNumLengthAsString(addr));
+ }
+
+ // Add extra padding.
+ max_name_len += 2;
+ max_size_len += 2;
+ max_addr_len += 2;
+
+ // Setup header format.
+ fmt << "%-" << max_name_len << "s "
+ << "%" << max_size_len << "s "
+ << "%" << max_addr_len << "s\n";
+
+ // Print header
+ outs() << format(fmt.str().c_str(),
+ static_cast<const char*>("section"),
+ static_cast<const char*>("size"),
+ static_cast<const char*>("addr"));
+ fmtbuf.clear();
+
+ // Setup per section format.
+ fmt << "%-" << max_name_len << "s "
+ << "%#" << max_size_len << radix_fmt << " "
+ << "%#" << max_addr_len << radix_fmt << "\n";
+
+ // Print each section.
+ for (section_iterator i = o->begin_sections(),
+ e = o->end_sections(); i != e;
+ i.increment(ec)) {
+ if (error(ec))
+ return;
+
+ StringRef name;
+ uint64_t size = 0;
+ uint64_t addr = 0;
+ if (error(i->getName(name))) return;
+ if (error(i->getSize(size))) return;
+ if (error(i->getAddress(addr))) return;
+ std::string namestr = name;
+
+ outs() << format(fmt.str().c_str(),
+ namestr.c_str(),
+ size,
+ addr);
+ }
+
+ // Print total.
+ fmtbuf.clear();
+ fmt << "%-" << max_name_len << "s "
+ << "%#" << max_size_len << radix_fmt << "\n";
+ outs() << format(fmt.str().c_str(),
+ static_cast<const char*>("Total"),
+ total);
+ } else {
+ // The Berkeley format does not display individual section sizes. It
+ // displays the cumulative size for each section type.
+ uint64_t total_text = 0;
+ uint64_t total_data = 0;
+ uint64_t total_bss = 0;
+
+ // Make one pass over the section table to calculate sizes.
+ error_code ec;
+ for (section_iterator i = o->begin_sections(),
+ e = o->end_sections(); i != e;
+ i.increment(ec)) {
+ if (error(ec))
+ return;
+
+ uint64_t size = 0;
+ bool isText = false;
+ bool isData = false;
+ bool isBSS = false;
+ if (error(i->getSize(size))) return;
+ if (error(i->isText(isText))) return;
+ if (error(i->isData(isData))) return;
+ if (error(i->isBSS(isBSS))) return;
+ if (isText)
+ total_text += size;
+ else if (isData)
+ total_data += size;
+ else if (isBSS)
+ total_bss += size;
+ }
+
+ total = total_text + total_data + total_bss;
+
+ // Print result.
+ fmt << "%#7" << radix_fmt << " "
+ << "%#7" << radix_fmt << " "
+ << "%#7" << radix_fmt << " ";
+ outs() << format(fmt.str().c_str(),
+ total_text,
+ total_data,
+ total_bss);
+ fmtbuf.clear();
+ fmt << "%7" << (Radix == octal ? "llo" : "llu") << " "
+ << "%7llx ";
+ outs() << format(fmt.str().c_str(),
+ total,
+ total);
+ }
+}
+
+/// @brief Print the section sizes for @p file. If @p file is an archive, print
+/// the section sizes for each archive member.
+static void PrintFileSectionSizes(StringRef file) {
+ // If file is not stdin, check that it exists.
+ if (file != "-") {
+ bool exists;
+ if (sys::fs::exists(file, exists) || !exists) {
+ errs() << ToolName << ": '" << file << "': " << "No such file\n";
+ return;
+ }
+ }
+
+ // Attempt to open the binary.
+ OwningPtr<Binary> binary;
+ if (error_code ec = createBinary(file, binary)) {
+ errs() << ToolName << ": " << file << ": " << ec.message() << ".\n";
+ return;
+ }
+
+ if (Archive *a = dyn_cast<Archive>(binary.get())) {
+ // This is an archive. Iterate over each member and display its sizes.
+ for (object::Archive::child_iterator i = a->begin_children(),
+ e = a->end_children(); i != e; ++i) {
+ OwningPtr<Binary> child;
+ if (error_code ec = i->getAsBinary(child)) {
+ errs() << ToolName << ": " << file << ": " << ec.message() << ".\n";
+ continue;
+ }
+ if (ObjectFile *o = dyn_cast<ObjectFile>(child.get())) {
+ if (OutputFormat == sysv)
+ outs() << o->getFileName() << " (ex " << a->getFileName()
+ << "):\n";
+ PrintObjectSectionSizes(o);
+ if (OutputFormat == berkeley)
+ outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
+ }
+ }
+ } else if (ObjectFile *o = dyn_cast<ObjectFile>(binary.get())) {
+ if (OutputFormat == sysv)
+ outs() << o->getFileName() << " :\n";
+ PrintObjectSectionSizes(o);
+ if (OutputFormat == berkeley)
+ outs() << o->getFileName() << "\n";
+ } else {
+ errs() << ToolName << ": " << file << ": " << "Unrecognized file type.\n";
+ }
+ // System V adds an extra newline at the end of each file.
+ if (OutputFormat == sysv)
+ outs() << "\n";
+}
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ cl::ParseCommandLineOptions(argc, argv, "llvm object size dumper\n");
+
+ ToolName = argv[0];
+ if (OutputFormatShort.getNumOccurrences())
+ OutputFormat = OutputFormatShort;
+ if (RadixShort.getNumOccurrences())
+ Radix = RadixShort;
+
+ if (InputFilenames.size() == 0)
+ InputFilenames.push_back("a.out");
+
+ if (OutputFormat == berkeley)
+ outs() << " text data bss "
+ << (Radix == octal ? "oct" : "dec")
+ << " hex filename\n";
+
+ std::for_each(InputFilenames.begin(), InputFilenames.end(),
+ PrintFileSectionSizes);
+
+ return 0;
+}
diff --git a/tools/llvmc/CMakeLists.txt b/tools/llvmc/CMakeLists.txt
deleted file mode 100644
index 10ad5d8..0000000
--- a/tools/llvmc/CMakeLists.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-# add_subdirectory(src)
-
-# TODO: support plugins and user-configured builds.
-# See ./doc/LLVMC-Reference.rst "Customizing LLVMC: the compilation graph"
diff --git a/tools/llvmc/Makefile b/tools/llvmc/Makefile
deleted file mode 100644
index 7c03e2a..0000000
--- a/tools/llvmc/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-##===- tools/llvmc/Makefile --------------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open
-# Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../..
-
-DIRS = src
-
-ifeq ($(BUILD_EXAMPLES),1)
- OPTIONAL_DIRS += examples
-endif
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/doc/LLVMC-Reference.rst b/tools/llvmc/doc/LLVMC-Reference.rst
deleted file mode 100644
index 041aedf..0000000
--- a/tools/llvmc/doc/LLVMC-Reference.rst
+++ /dev/null
@@ -1,747 +0,0 @@
-===================================
-Customizing LLVMC: Reference Manual
-===================================
-..
- This file was automatically generated by rst2html.
- Please do not edit directly!
- The ReST source lives in the directory 'tools/llvmc/doc'.
-
-.. contents::
-
-.. raw:: html
-
- <div class="doc_author">
- <p>Written by <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a></p>
- </div>
-
-Introduction
-============
-
-LLVMC is a generic compiler driver, designed to be customizable and
-extensible. It plays the same role for LLVM as the ``gcc`` program does for
-GCC - LLVMC's job is essentially to transform a set of input files into a set of
-targets depending on configuration rules and user options. What makes LLVMC
-different is that these transformation rules are completely customizable - in
-fact, LLVMC knows nothing about the specifics of transformation (even the
-command-line options are mostly not hard-coded) and regards the transformation
-structure as an abstract graph. The structure of this graph is described in
-high-level TableGen code, from which an efficient C++ representation is
-automatically derived. This makes it possible to adapt LLVMC for other
-purposes - for example, as a build tool for game resources.
-
-Because LLVMC employs TableGen_ as its configuration language, you
-need to be familiar with it to customize LLVMC.
-
-.. _TableGen: http://llvm.org/docs/TableGenFundamentals.html
-
-
-Compiling with ``llvmc``
-========================
-
-LLVMC tries hard to be as compatible with ``gcc`` as possible,
-although there are some small differences. Most of the time, however,
-you shouldn't be able to notice them::
-
- $ # This works as expected:
- $ llvmc -O3 -Wall hello.cpp
- $ ./a.out
- hello
-
-One nice feature of LLVMC is that one doesn't have to distinguish between
-different compilers for different languages (think ``g++`` vs. ``gcc``) - the
-right toolchain is chosen automatically based on input language names (which
-are, in turn, determined from file extensions). If you want to force files
-ending with ".c" to compile as C++, use the ``-x`` option, just like you would
-do it with ``gcc``::
-
- $ # hello.c is really a C++ file
- $ llvmc -x c++ hello.c
- $ ./a.out
- hello
-
-On the other hand, when using LLVMC as a linker to combine several C++
-object files you should provide the ``--linker`` option since it's
-impossible for LLVMC to choose the right linker in that case::
-
- $ llvmc -c hello.cpp
- $ llvmc hello.o
- [A lot of link-time errors skipped]
- $ llvmc --linker=c++ hello.o
- $ ./a.out
- hello
-
-By default, LLVMC uses ``llvm-gcc`` to compile the source code. It is also
-possible to choose the ``clang`` compiler with the ``-clang`` option.
-
-
-Predefined options
-==================
-
-LLVMC has some built-in options that can't be overridden in the TableGen code:
-
-* ``-o FILE`` - Output file name.
-
-* ``-x LANGUAGE`` - Specify the language of the following input files
- until the next -x option.
-
-* ``-v`` - Enable verbose mode, i.e. print out all executed commands.
-
-* ``--save-temps`` - Write temporary files to the current directory and do not
- delete them on exit. This option can also take an argument: the
- ``--save-temps=obj`` switch will write files into the directory specified with
- the ``-o`` option. The ``--save-temps=cwd`` and ``--save-temps`` switches are
- both synonyms for the default behaviour.
-
-* ``--temp-dir DIRECTORY`` - Store temporary files in the given directory. This
- directory is deleted on exit unless ``--save-temps`` is specified. If
- ``--save-temps=obj`` is also specified, ``--temp-dir`` is given the
- precedence.
-
-* ``--check-graph`` - Check the compilation for common errors like mismatched
- output/input language names, multiple default edges and cycles. Exit with code
- zero if no errors were found, and return the number of found errors
- otherwise. Hidden option, useful for debugging.
-
-* ``--view-graph`` - Show a graphical representation of the compilation graph
- and exit. Requires that you have ``dot`` and ``gv`` programs installed. Hidden
- option, useful for debugging.
-
-* ``--write-graph`` - Write a ``compilation-graph.dot`` file in the current
- directory with the compilation graph description in Graphviz format (identical
- to the file used by the ``--view-graph`` option). The ``-o`` option can be
- used to set the output file name. Hidden option, useful for debugging.
-
-* ``--help``, ``--help-hidden``, ``--version`` - These options have
- their standard meaning.
-
-Compiling LLVMC-based drivers
-=============================
-
-It's easiest to start working on your own LLVMC driver by copying the skeleton
-project which lives under ``$LLVMC_DIR/examples/Skeleton``::
-
- $ cd $LLVMC_DIR/examples
- $ cp -r Skeleton MyDriver
- $ cd MyDriver
- $ ls
- AutoGenerated.td Hooks.cpp Main.cpp Makefile
-
-As you can see, our basic driver consists of only three files (not counting the
-build script). ``AutoGenerated.td`` contains TableGen description of the
-compilation graph; its format is documented in the following
-sections. ``Hooks.cpp`` is an empty file that should be used for hook
-definitions (see `below`__). ``Main.cpp`` is just a helper used to compile the
-auto-generated C++ code produced from TableGen source.
-
-__ hooks_
-
-The first thing that you should do is to change the ``LLVMC_BASED_DRIVER``
-variable in the ``Makefile``::
-
- LLVMC_BASED_DRIVER=MyDriver
-
-It can also be a good idea to put your TableGen code into a file with a less
-generic name::
-
- $ touch MyDriver.td
- $ vim AutoGenerated.td
- [...]
- include "MyDriver.td"
-
-If you have more than one TableGen source file, they all should be included from
-``AutoGenerated.td``, since this file is used by the build system to generate
-C++ code.
-
-To build your driver, just ``cd`` to its source directory and run ``make``. The
-resulting executable will be put into ``$LLVM_OBJ_DIR/$(BuildMode)/bin``.
-
-If you're compiling LLVM with different source and object directories, then you
-must perform the following additional steps before running ``make``::
-
- # LLVMC_SRC_DIR = $LLVM_SRC_DIR/tools/llvmc/
- # LLVMC_OBJ_DIR = $LLVM_OBJ_DIR/tools/llvmc/
- $ mkdir $LLVMC_OBJ_DIR/examples/MyDriver/
- $ cp $LLVMC_SRC_DIR/examples/MyDriver/Makefile \
- $LLVMC_OBJ_DIR/examples/MyDriver/
- $ cd $LLVMC_OBJ_DIR/examples/MyDriver
- $ make
-
-
-Customizing LLVMC: the compilation graph
-========================================
-
-Each TableGen configuration file should include the common definitions::
-
- include "llvm/CompilerDriver/Common.td"
-
-Internally, LLVMC stores information about possible source transformations in
-form of a graph. Nodes in this graph represent tools, and edges between two
-nodes represent a transformation path. A special "root" node is used to mark
-entry points for the transformations. LLVMC also assigns a weight to each edge
-(more on this later) to choose between several alternative edges.
-
-The definition of the compilation graph (see file ``llvmc/src/Base.td`` for an
-example) is just a list of edges::
-
- def CompilationGraph : CompilationGraph<[
- Edge<"root", "llvm_gcc_c">,
- Edge<"root", "llvm_gcc_assembler">,
- ...
-
- Edge<"llvm_gcc_c", "llc">,
- Edge<"llvm_gcc_cpp", "llc">,
- ...
-
- OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"),
- (inc_weight))>,
- OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"),
- (inc_weight))>,
- ...
-
- OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker",
- (case (input_languages_contain "c++"), (inc_weight),
- (or (parameter_equals "linker", "g++"),
- (parameter_equals "linker", "c++")), (inc_weight))>,
- ...
-
- ]>;
-
-As you can see, the edges can be either default or optional, where optional
-edges are differentiated by an additional ``case`` expression used to calculate
-the weight of this edge. Notice also that we refer to tools via their names (as
-strings). This makes it possible to add edges to an existing compilation graph
-without having to know about all tool definitions used in the graph.
-
-The default edges are assigned a weight of 1, and optional edges get a weight of
-0 + 2*N where N is the number of tests that evaluated to true in the ``case``
-expression. It is also possible to provide an integer parameter to
-``inc_weight`` and ``dec_weight`` - in this case, the weight is increased (or
-decreased) by the provided value instead of the default 2. Default weight of an
-optional edge can be changed by using the ``default`` clause of the ``case``
-construct.
-
-When passing an input file through the graph, LLVMC picks the edge with the
-maximum weight. To avoid ambiguity, there should be only one default edge
-between two nodes (with the exception of the root node, which gets a special
-treatment - there you are allowed to specify one default edge *per language*).
-
-When multiple compilation graphs are defined, they are merged together. Multiple
-edges with the same end nodes are not allowed (i.e. the graph is not a
-multigraph), and will lead to a compile-time error.
-
-To get a visual representation of the compilation graph (useful for debugging),
-run ``llvmc --view-graph``. You will need ``dot`` and ``gsview`` installed for
-this to work properly.
-
-Describing options
-==================
-
-Command-line options supported by the driver are defined by using an
-``OptionList``::
-
- def Options : OptionList<[
- (switch_option "E", (help "Help string")),
- (alias_option "quiet", "q")
- ...
- ]>;
-
-As you can see, the option list is just a list of DAGs, where each DAG is an
-option description consisting of the option name and some properties. More than
-one option list can be defined (they are all merged together in the end), which
-can be handy if one wants to separate option groups syntactically.
-
-* Possible option types:
-
- - ``switch_option`` - a simple boolean switch without arguments, for example
- ``-O2`` or ``-time``. At most one occurrence is allowed by default.
-
- - ``parameter_option`` - option that takes one argument, for example
- ``-std=c99``. It is also allowed to use spaces instead of the equality
- sign: ``-std c99``. At most one occurrence is allowed.
-
- - ``parameter_list_option`` - same as the above, but more than one option
- occurrence is allowed.
-
- - ``prefix_option`` - same as the parameter_option, but the option name and
- argument do not have to be separated. Example: ``-ofile``. This can be also
- specified as ``-o file``; however, ``-o=file`` will be parsed incorrectly
- (``=file`` will be interpreted as option value). At most one occurrence is
- allowed.
-
- - ``prefix_list_option`` - same as the above, but more than one occurrence of
- the option is allowed; example: ``-lm -lpthread``.
-
- - ``alias_option`` - a special option type for creating aliases. Unlike other
- option types, aliases are not allowed to have any properties besides the
- aliased option name.
- Usage example: ``(alias_option "preprocess", "E")``
-
- - ``switch_list_option`` - like ``switch_option`` with the ``zero_or_more``
- property, but remembers how many times the switch was turned on. Useful
- mostly for forwarding. Example: when ``-foo`` is a switch option (with the
- ``zero_or_more`` property), the command ``driver -foo -foo`` is forwarded
- as ``some-tool -foo``, but when ``-foo`` is a switch list, the same command
- is forwarded as ``some-tool -foo -foo``.
-
-
-* Possible option properties:
-
- - ``help`` - help string associated with this option. Used for ``--help``
- output.
-
- - ``required`` - this option must be specified exactly once (or, in case of
- the list options without the ``multi_val`` property, at least
- once). Incompatible with ``optional`` and ``one_or_more``.
-
- - ``optional`` - the option can be specified either zero times or exactly
- once. The default for switch options. Useful only for list options in
- conjunction with ``multi_val``. Incompatible with ``required``,
- ``zero_or_more`` and ``one_or_more``.
-
- - ``one_or_more`` - the option must be specified at least once. Can be useful
- to allow switch options be both obligatory and be specified multiple
- times. For list options is useful only in conjunction with ``multi_val``;
- for ordinary it is synonymous with ``required``. Incompatible with
- ``required``, ``optional`` and ``zero_or_more``.
-
- - ``zero_or_more`` - the option can be specified zero or more times. Useful
- to allow a single switch option to be specified more than
- once. Incompatible with ``required``, ``optional`` and ``one_or_more``.
-
- - ``hidden`` - the description of this option will not appear in
- the ``--help`` output (but will appear in the ``--help-hidden``
- output).
-
- - ``really_hidden`` - the option will not be mentioned in any help
- output.
-
- - ``comma_separated`` - Indicates that any commas specified for an option's
- value should be used to split the value up into multiple values for the
- option. This property is valid only for list options. In conjunction with
- ``forward_value`` can be used to implement option forwarding in style of
- gcc's ``-Wa,``.
-
- - ``multi_val n`` - this option takes *n* arguments (can be useful in some
- special cases). Usage example: ``(parameter_list_option "foo", (multi_val
- 3))``; the command-line syntax is '-foo a b c'. Only list options can have
- this attribute; you can, however, use the ``one_or_more``, ``optional``
- and ``required`` properties.
-
- - ``init`` - this option has a default value, either a string (if it is a
- parameter), or a boolean (if it is a switch; as in C++, boolean constants
- are called ``true`` and ``false``). List options can't have ``init``
- attribute.
- Usage examples: ``(switch_option "foo", (init true))``; ``(prefix_option
- "bar", (init "baz"))``.
-
-.. _case:
-
-Conditional evaluation
-======================
-
-The 'case' construct is the main means by which programmability is achieved in
-LLVMC. It can be used to calculate edge weights, program actions and modify the
-shell commands to be executed. The 'case' expression is designed after the
-similarly-named construct in functional languages and takes the form ``(case
-(test_1), statement_1, (test_2), statement_2, ... (test_N), statement_N)``. The
-statements are evaluated only if the corresponding tests evaluate to true.
-
-Examples::
-
- // Edge weight calculation
-
- // Increases edge weight by 5 if "-A" is provided on the
- // command-line, and by 5 more if "-B" is also provided.
- (case
- (switch_on "A"), (inc_weight 5),
- (switch_on "B"), (inc_weight 5))
-
-
- // Tool command line specification
-
- // Evaluates to "cmdline1" if the option "-A" is provided on the
- // command line; to "cmdline2" if "-B" is provided;
- // otherwise to "cmdline3".
-
- (case
- (switch_on "A"), "cmdline1",
- (switch_on "B"), "cmdline2",
- (default), "cmdline3")
-
-Note the slight difference in 'case' expression handling in contexts of edge
-weights and command line specification - in the second example the value of the
-``"B"`` switch is never checked when switch ``"A"`` is enabled, and the whole
-expression always evaluates to ``"cmdline1"`` in that case.
-
-Case expressions can also be nested, i.e. the following is legal::
-
- (case (switch_on "E"), (case (switch_on "o"), ..., (default), ...)
- (default), ...)
-
-You should, however, try to avoid doing that because it hurts readability. It is
-usually better to split tool descriptions and/or use TableGen inheritance
-instead.
-
-* Possible tests are:
-
- - ``switch_on`` - Returns true if a given command-line switch is provided by
- the user. Can be given multiple arguments, in that case ``(switch_on "foo",
- "bar", "baz")`` is equivalent to ``(and (switch_on "foo"), (switch_on
- "bar"), (switch_on "baz"))``.
- Example: ``(switch_on "opt")``.
-
- - ``any_switch_on`` - Given a number of switch options, returns true if any of
- the switches is turned on.
- Example: ``(any_switch_on "foo", "bar", "baz")`` is equivalent to ``(or
- (switch_on "foo"), (switch_on "bar"), (switch_on "baz"))``.
-
- - ``parameter_equals`` - Returns true if a command-line parameter (first
- argument) equals a given value (second argument).
- Example: ``(parameter_equals "W", "all")``.
-
- - ``element_in_list`` - Returns true if a command-line parameter list (first
- argument) contains a given value (second argument).
- Example: ``(element_in_list "l", "pthread")``.
-
- - ``input_languages_contain`` - Returns true if a given language
- belongs to the current input language set.
- Example: ``(input_languages_contain "c++")``.
-
- - ``in_language`` - Evaluates to true if the input file language is equal to
- the argument. At the moment works only with ``command`` and ``actions`` (on
- non-join nodes).
- Example: ``(in_language "c++")``.
-
- - ``not_empty`` - Returns true if a given option (which should be either a
- parameter or a parameter list) is set by the user. Like ``switch_on``, can
- be also given multiple arguments.
- Examples: ``(not_empty "o")``, ``(not_empty "o", "l")``.
-
- - ``any_not_empty`` - Returns true if ``not_empty`` returns true for any of
- the provided options.
- Example: ``(any_not_empty "foo", "bar", "baz")`` is equivalent to ``(or
- (not_empty "foo"), (not_empty "bar"), (not_empty "baz"))``.
-
- - ``empty`` - The opposite of ``not_empty``. Equivalent to ``(not (not_empty
- X))``. Can be given multiple arguments.
-
- - ``any_not_empty`` - Returns true if ``not_empty`` returns true for any of
- the provided options.
- Example: ``(any_empty "foo", "bar", "baz")`` is equivalent to ``(or
- (not_empty "foo"), (not_empty "bar"), (not_empty "baz"))``.
-
- - ``single_input_file`` - Returns true if there was only one input file
- provided on the command-line. Used without arguments:
- ``(single_input_file)``.
-
- - ``multiple_input_files`` - Equivalent to ``(not (single_input_file))`` (the
- case of zero input files is considered an error).
-
- - ``default`` - Always evaluates to true. Should always be the last
- test in the ``case`` expression.
-
- - ``and`` - A standard logical combinator that returns true iff all of
- its arguments return true. Used like this: ``(and (test1), (test2),
- ... (testN))``. Nesting of ``and`` and ``or`` is allowed, but not
- encouraged.
-
- - ``or`` - A logical combinator that returns true iff any of its arguments
- return true.
- Example: ``(or (test1), (test2), ... (testN))``.
-
- - ``not`` - Standard unary logical combinator that negates its
- argument.
- Example: ``(not (or (test1), (test2), ... (testN)))``.
-
-
-Writing a tool description
-==========================
-
-As was said earlier, nodes in the compilation graph represent tools, which are
-described separately. A tool definition looks like this (taken from the
-``llvmc/src/Base.td`` file)::
-
- def llvm_gcc_cpp : Tool<[
- (in_language "c++"),
- (out_language "llvm-assembler"),
- (output_suffix "bc"),
- (command "llvm-g++ -c -emit-llvm"),
- (sink)
- ]>;
-
-This defines a new tool called ``llvm_gcc_cpp``, which is an alias for
-``llvm-g++``. As you can see, a tool definition is just a list of properties;
-most of them should be self-explanatory. The ``sink`` property means that this
-tool should be passed all command-line options that aren't mentioned in the
-option list.
-
-The complete list of all currently implemented tool properties follows.
-
-* Possible tool properties:
-
- - ``in_language`` - input language name. Can be given multiple arguments, in
- case the tool supports multiple input languages. Used for typechecking and
- mapping file extensions to tools.
-
- - ``out_language`` - output language name. Multiple output languages are
- allowed. Used for typechecking the compilation graph.
-
- - ``output_suffix`` - output file suffix. Can also be changed dynamically, see
- documentation on `actions`__.
-
-__ actions_
-
- - ``command`` - the actual command used to run the tool. You can use output
- redirection with ``>``, hook invocations (``$CALL``), environment variables
- (via ``$ENV``) and the ``case`` construct.
-
- - ``join`` - this tool is a "join node" in the graph, i.e. it gets a list of
- input files and joins them together. Used for linkers.
-
- - ``sink`` - all command-line options that are not handled by other tools are
- passed to this tool.
-
- - ``actions`` - A single big ``case`` expression that specifies how this tool
- reacts on command-line options (described in more detail `below`__).
-
-__ actions_
-
- - ``out_file_option``, ``in_file_option`` - Options appended to the
- ``command`` string to designate output and input files. Default values are
- ``"-o"`` and ``""``, respectively.
-
-.. _actions:
-
-Actions
--------
-
-A tool often needs to react to command-line options, and this is precisely what
-the ``actions`` property is for. The next example illustrates this feature::
-
- def llvm_gcc_linker : Tool<[
- (in_language "object-code"),
- (out_language "executable"),
- (output_suffix "out"),
- (command "llvm-gcc"),
- (join),
- (actions (case (not_empty "L"), (forward "L"),
- (not_empty "l"), (forward "l"),
- (not_empty "dummy"),
- [(append_cmd "-dummy1"), (append_cmd "-dummy2")])
- ]>;
-
-The ``actions`` tool property is implemented on top of the omnipresent ``case``
-expression. It associates one or more different *actions* with given
-conditions - in the example, the actions are ``forward``, which forwards a given
-option unchanged, and ``append_cmd``, which appends a given string to the tool
-execution command. Multiple actions can be associated with a single condition by
-using a list of actions (used in the example to append some dummy options). The
-same ``case`` construct can also be used in the ``cmd_line`` property to modify
-the tool command line.
-
-The "join" property used in the example means that this tool behaves like a
-linker.
-
-The list of all possible actions follows.
-
-* Possible actions:
-
- - ``append_cmd`` - Append a string to the tool invocation command.
- Example: ``(case (switch_on "pthread"), (append_cmd "-lpthread"))``.
-
- - ``error`` - Exit with error.
- Example: ``(error "Mixing -c and -S is not allowed!")``.
-
- - ``warning`` - Print a warning.
- Example: ``(warning "Specifying both -O1 and -O2 is meaningless!")``.
-
- - ``forward`` - Forward the option unchanged.
- Example: ``(forward "Wall")``.
-
- - ``forward_as`` - Change the option's name, but forward the argument
- unchanged.
- Example: ``(forward_as "O0", "--disable-optimization")``.
-
- - ``forward_value`` - Forward only option's value. Cannot be used with switch
- options (since they don't have values), but works fine with lists.
- Example: ``(forward_value "Wa,")``.
-
- - ``forward_transformed_value`` - As above, but applies a hook to the
- option's value before forwarding (see `below`__). When
- ``forward_transformed_value`` is applied to a list
- option, the hook must have signature
- ``std::string hooks::HookName (const std::vector<std::string>&)``.
- Example: ``(forward_transformed_value "m", "ConvertToMAttr")``.
-
- __ hooks_
-
- - ``output_suffix`` - Modify the output suffix of this tool.
- Example: ``(output_suffix "i")``.
-
- - ``stop_compilation`` - Stop compilation after this tool processes its
- input. Used without arguments.
- Example: ``(stop_compilation)``.
-
-
-Language map
-============
-
-If you are adding support for a new language to LLVMC, you'll need to modify the
-language map, which defines mappings from file extensions to language names. It
-is used to choose the proper toolchain(s) for a given input file set. Language
-map definition looks like this::
-
- def LanguageMap : LanguageMap<
- [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
- LangToSuffixes<"c", ["c"]>,
- ...
- ]>;
-
-For example, without those definitions the following command wouldn't work::
-
- $ llvmc hello.cpp
- llvmc: Unknown suffix: cpp
-
-The language map entries are needed only for the tools that are linked from the
-root node. A tool can have multiple output languages.
-
-Option preprocessor
-===================
-
-It is sometimes useful to run error-checking code before processing the
-compilation graph. For example, if optimization options "-O1" and "-O2" are
-implemented as switches, we might want to output a warning if the user invokes
-the driver with both of these options enabled.
-
-The ``OptionPreprocessor`` feature is reserved specially for these
-occasions. Example (adapted from ``llvm/src/Base.td.in``)::
-
-
- def Preprocess : OptionPreprocessor<
- (case (not (any_switch_on "O0", "O1", "O2", "O3")),
- (set_option "O2"),
- (and (switch_on "O3"), (any_switch_on "O0", "O1", "O2")),
- (unset_option "O0", "O1", "O2"),
- (and (switch_on "O2"), (any_switch_on "O0", "O1")),
- (unset_option "O0", "O1"),
- (and (switch_on "O1"), (switch_on "O0")),
- (unset_option "O0"))
- >;
-
-Here, ``OptionPreprocessor`` is used to unset all spurious ``-O`` options so
-that they are not forwarded to the compiler. If no optimization options are
-specified, ``-O2`` is enabled.
-
-``OptionPreprocessor`` is basically a single big ``case`` expression, which is
-evaluated only once right after the driver is started. The only allowed actions
-in ``OptionPreprocessor`` are ``error``, ``warning``, and two special actions:
-``unset_option`` and ``set_option``. As their names suggest, they can be used to
-set or unset a given option. To set an option with ``set_option``, use the
-two-argument form: ``(set_option "parameter", VALUE)``. Here, ``VALUE`` can be
-either a string, a string list, or a boolean constant.
-
-For convenience, ``set_option`` and ``unset_option`` also work with multiple
-arguments. That is, instead of ``[(unset_option "A"), (unset_option "B")]`` you
-can use ``(unset_option "A", "B")``. Obviously, ``(set_option "A", "B")`` is
-only valid if both ``A`` and ``B`` are switches.
-
-
-More advanced topics
-====================
-
-.. _hooks:
-
-Hooks and environment variables
--------------------------------
-
-Normally, LLVMC searches for programs in the system ``PATH``. Sometimes, this is
-not sufficient: for example, we may want to specify tool paths or names in the
-configuration file. This can be achieved via the hooks mechanism. To write your
-own hooks, add their definitions to the ``Hooks.cpp`` or drop a ``.cpp`` file
-into your driver directory. Hooks should live in the ``hooks`` namespace and
-have the signature ``std::string hooks::MyHookName ([const char* Arg0 [ const
-char* Arg2 [, ...]]])``. They can be used from the ``command`` tool property::
-
- (command "$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)")
-
-To pass arguments to hooks, use the following syntax::
-
- (command "$CALL(MyHook, 'Arg1', 'Arg2', 'Arg # 3')/path/to/file -o1 -o2")
-
-It is also possible to use environment variables in the same manner::
-
- (command "$ENV(VAR1)/path/to/file -o $ENV(VAR2)")
-
-To change the command line string based on user-provided options use
-the ``case`` expression (documented `above`__)::
-
- (command
- (case
- (switch_on "E"),
- "llvm-g++ -E -x c $INFILE -o $OUTFILE",
- (default),
- "llvm-g++ -c -x c $INFILE -o $OUTFILE -emit-llvm"))
-
-__ case_
-
-Debugging
----------
-
-When writing LLVMC-based drivers, it can be useful to get a visual view of the
-resulting compilation graph. This can be achieved via the command line option
-``--view-graph`` (which assumes that Graphviz_ and Ghostview_ are
-installed). There is also a ``--write-graph`` option that creates a Graphviz
-source file (``compilation-graph.dot``) in the current directory.
-
-Another useful ``llvmc`` option is ``--check-graph``. It checks the compilation
-graph for common errors like mismatched output/input language names, multiple
-default edges and cycles. When invoked with ``--check-graph``, ``llvmc`` doesn't
-perform any compilation tasks and returns the number of encountered errors as
-its status code. In the future, these checks will be performed at compile-time
-and this option will disappear.
-
-.. _Graphviz: http://www.graphviz.org/
-.. _Ghostview: http://pages.cs.wisc.edu/~ghost/
-
-Conditioning on the executable name
------------------------------------
-
-For now, the executable name (the value passed to the driver in ``argv[0]``) is
-accessible only in the C++ code (i.e. hooks). Use the following code::
-
- namespace llvmc {
- extern const char* ProgramName;
- }
-
- namespace hooks {
-
- std::string MyHook() {
- //...
- if (strcmp(ProgramName, "mydriver") == 0) {
- //...
-
- }
-
- } // end namespace hooks
-
-In general, you're encouraged not to make the behaviour dependent on the
-executable file name, and use command-line switches instead. See for example how
-the ``llvmc`` program behaves when it needs to choose the correct linker options
-(think ``g++`` vs. ``gcc``).
-
-.. raw:: html
-
- <hr />
- <address>
- <a href="http://jigsaw.w3.org/css-validator/check/referer">
- <img src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
- alt="Valid CSS" /></a>
- <a href="http://validator.w3.org/check?uri=referer">
- <img src="http://www.w3.org/Icons/valid-xhtml10-blue"
- alt="Valid XHTML 1.0 Transitional"/></a>
-
- <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
- <a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
-
- Last modified: $Date: 2008-12-11 11:34:48 -0600 (Thu, 11 Dec 2008) $
- </address>
diff --git a/tools/llvmc/doc/LLVMC-Tutorial.rst b/tools/llvmc/doc/LLVMC-Tutorial.rst
deleted file mode 100644
index fc4c124..0000000
--- a/tools/llvmc/doc/LLVMC-Tutorial.rst
+++ /dev/null
@@ -1,127 +0,0 @@
-======================
-Tutorial - Using LLVMC
-======================
-..
- This file was automatically generated by rst2html.
- Please do not edit directly!
- The ReST source lives in the directory 'tools/llvmc/doc'.
-
-.. contents::
-
-.. raw:: html
-
- <div class="doc_author">
- <p>Written by <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a></p>
- </div>
-
-Introduction
-============
-
-LLVMC is a generic compiler driver, which plays the same role for LLVM as the
-``gcc`` program does for GCC - the difference being that LLVMC is designed to be
-more adaptable and easier to customize. Most of LLVMC functionality is
-implemented via high-level TableGen code, from which a corresponding C++ source
-file is automatically generated. This tutorial describes the basic usage and
-configuration of LLVMC.
-
-
-Using the ``llvmc`` program
-===========================
-
-In general, ``llvmc`` tries to be command-line compatible with ``gcc`` as much
-as possible, so most of the familiar options work::
-
- $ llvmc -O3 -Wall hello.cpp
- $ ./a.out
- hello
-
-This will invoke ``llvm-g++`` under the hood (you can see which commands are
-executed by using the ``-v`` option). For further help on command-line LLVMC
-usage, refer to the ``llvmc --help`` output.
-
-
-Using LLVMC to generate toolchain drivers
-=========================================
-
-LLVMC-based drivers are written mostly using TableGen_, so you need to be
-familiar with it to get anything done.
-
-.. _TableGen: http://llvm.org/docs/TableGenFundamentals.html
-
-Start by compiling ``example/Simple``, which is a primitive wrapper for
-``gcc``::
-
- $ cd $LLVM_OBJ_DIR/tools/examples/Simple
- $ make
- $ cat > hello.c
- #include <stdio.h>
- int main() { printf("Hello\n"); }
- $ $LLVM_BIN_DIR/Simple -v hello.c
- gcc hello.c -o hello.out
- $ ./hello.out
- Hello
-
-We have thus produced a simple driver called, appropriately, ``Simple``, from
-the input TableGen file ``Simple.td``. The ``llvmc`` program itself is generated
-using a similar process (see ``llvmc/src``). Contents of the file ``Simple.td``
-look like this::
-
- // Include common definitions
- include "llvm/CompilerDriver/Common.td"
-
- // Tool descriptions
- def gcc : Tool<
- [(in_language "c"),
- (out_language "executable"),
- (output_suffix "out"),
- (command "gcc"),
- (sink),
-
- // -o is what is used by default, out_file_option here is included for
- // instructive purposes.
- (out_file_option "-o")
- ]>;
-
- // Language map
- def LanguageMap : LanguageMap<[(lang_to_suffixes "c", "c")]>;
-
- // Compilation graph
- def CompilationGraph : CompilationGraph<[(edge "root", "gcc")]>;
-
-As you can see, this file consists of three parts: tool descriptions, language
-map, and the compilation graph definition.
-
-At the heart of LLVMC is the idea of a compilation graph: vertices in this graph
-are tools, and edges represent a transformation path between two tools (for
-example, assembly source produced by the compiler can be transformed into
-executable code by an assembler). The compilation graph is basically a list of
-edges; a special node named ``root`` is used to mark graph entry points.
-
-Tool descriptions are represented as property lists: most properties in the
-example above should be self-explanatory; the ``sink`` property means that all
-options lacking an explicit description should be forwarded to this tool.
-
-The ``LanguageMap`` associates a language name with a list of suffixes and is
-used for deciding which toolchain corresponds to a given input file.
-
-To learn more about writing your own drivers with LLVMC, refer to the reference
-manual and examples in the ``examples`` directory. Of a particular interest is
-the ``Skeleton`` example, which can serve as a template for your LLVMC-based
-drivers.
-
-.. raw:: html
-
- <hr />
- <address>
- <a href="http://jigsaw.w3.org/css-validator/check/referer">
- <img src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
- alt="Valid CSS" /></a>
- <a href="http://validator.w3.org/check?uri=referer">
- <img src="http://www.w3.org/Icons/valid-xhtml10-blue"
- alt="Valid XHTML 1.0 Transitional"/></a>
-
- <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
- <a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
-
- Last modified: $Date: 2008-12-11 11:34:48 -0600 (Thu, 11 Dec 2008) $
- </address>
diff --git a/tools/llvmc/doc/Makefile b/tools/llvmc/doc/Makefile
deleted file mode 100644
index ef98767..0000000
--- a/tools/llvmc/doc/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-##===- tools/llvmc/doc/Makefile ----------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL=../../..
-
-ifneq (,$(strip $(wildcard $(LEVEL)/Makefile.config)))
-include $(LEVEL)/Makefile.config
-else
-CP=cp
-RM=rm
-endif
-
-DOC_DIR=../../../docs
-RST2HTML=rst2html --stylesheet=llvm.css --link-stylesheet
-
-all : LLVMC-Reference.html LLVMC-Tutorial.html
- $(CP) LLVMC-Reference.html $(DOC_DIR)/CompilerDriver.html
- $(CP) LLVMC-Tutorial.html $(DOC_DIR)/CompilerDriverTutorial.html
-
-LLVMC-Tutorial.html : LLVMC-Tutorial.rst
- $(RST2HTML) $< $@
-
-LLVMC-Reference.html : LLVMC-Reference.rst
- $(RST2HTML) $< $@
-
-clean :
- $(RM) LLVMC-Tutorial.html LLVMC-Reference.html
diff --git a/tools/llvmc/doc/img/lines.gif b/tools/llvmc/doc/img/lines.gif
deleted file mode 100644
index 88f491e..0000000
--- a/tools/llvmc/doc/img/lines.gif
+++ /dev/null
Binary files differ
diff --git a/tools/llvmc/examples/Hello/Hello.cpp b/tools/llvmc/examples/Hello/Hello.cpp
deleted file mode 100644
index 71f04fd..0000000
--- a/tools/llvmc/examples/Hello/Hello.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-//===- Hello.cpp - Example code from "Writing an LLVMC Plugin" ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Shows how to write llvmc-based drivers without using TableGen.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CompilerDriver/AutoGenerated.h"
-#include "llvm/CompilerDriver/Main.inc"
-
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvmc {
-namespace autogenerated {
-
-int PreprocessOptions () { return 0; }
-
-int PopulateLanguageMap (LanguageMap&) { llvm::outs() << "Hello!\n"; return 0; }
-
-int PopulateCompilationGraph (CompilationGraph&) { return 0; }
-
-}
-}
diff --git a/tools/llvmc/examples/Hello/Makefile b/tools/llvmc/examples/Hello/Makefile
deleted file mode 100644
index c281be6..0000000
--- a/tools/llvmc/examples/Hello/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-##===- tools/llvmc/examples/Hello/Makefile -----------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../../..
-
-LLVMC_BASED_DRIVER = Hello
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/examples/Makefile b/tools/llvmc/examples/Makefile
deleted file mode 100644
index 8468e93..0000000
--- a/tools/llvmc/examples/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-##===- tools/llvmc/examples/Makefile -----------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL=../../..
-
-PARALLEL_DIRS := Hello Simple mcc16 Skeleton
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/examples/Simple/Makefile b/tools/llvmc/examples/Simple/Makefile
deleted file mode 100644
index c10387c..0000000
--- a/tools/llvmc/examples/Simple/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- llvmc/examples/Simple/Makefile ----------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../../..
-
-LLVMC_BASED_DRIVER = Simple
-BUILT_SOURCES = Simple.inc
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/examples/Simple/Simple.cpp b/tools/llvmc/examples/Simple/Simple.cpp
deleted file mode 100644
index 8ac7313..0000000
--- a/tools/llvmc/examples/Simple/Simple.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "llvm/CompilerDriver/Main.inc"
-#include "Simple.inc"
diff --git a/tools/llvmc/examples/Simple/Simple.td b/tools/llvmc/examples/Simple/Simple.td
deleted file mode 100644
index b47483b..0000000
--- a/tools/llvmc/examples/Simple/Simple.td
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- Simple.td - A simple LLVMC-based driver ----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// A simple LLVMC-based gcc wrapper.
-//
-// To compile, use this command:
-//
-// $ cd $LLVM_OBJ_DIR/tools/llvmc
-// $ make BUILD_EXAMPLES=1
-//
-// Run as:
-//
-// $ $LLVM_OBJ_DIR/$(BuildMode)/bin/Simple
-//
-// For instructions on how to build your own LLVMC-based driver, see
-// the 'examples/Skeleton' directory.
-//===----------------------------------------------------------------------===//
-
-include "llvm/CompilerDriver/Common.td"
-
-def gcc : Tool<
-[(in_language "c"),
- (out_language "executable"),
- (output_suffix "out"),
- (command "gcc"),
- (sink),
-
- // -o is what is used by default, out_file_option here is included for
- // instructive purposes.
- (out_file_option "-o")
-]>;
-
-def LanguageMap : LanguageMap<[(lang_to_suffixes "c", "c")]>;
-
-def CompilationGraph : CompilationGraph<[(edge "root", "gcc")]>;
diff --git a/tools/llvmc/examples/Skeleton/AutoGenerated.td b/tools/llvmc/examples/Skeleton/AutoGenerated.td
deleted file mode 100644
index 97483ce..0000000
--- a/tools/llvmc/examples/Skeleton/AutoGenerated.td
+++ /dev/null
@@ -1,7 +0,0 @@
-//===- AutoGenerated.td ------------------------------------*- tablegen -*-===//
-//
-// Write the TableGen description of your llvmc-based driver here.
-//
-//===----------------------------------------------------------------------===//
-
-include "llvm/CompilerDriver/Common.td"
diff --git a/tools/llvmc/examples/Skeleton/Hooks.cpp b/tools/llvmc/examples/Skeleton/Hooks.cpp
deleted file mode 100644
index ddd38f6..0000000
--- a/tools/llvmc/examples/Skeleton/Hooks.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-//===--- Hooks.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.
-//
-//===----------------------------------------------------------------------===//
-//
-// Hook definitions should go here.
-//
-//===----------------------------------------------------------------------===//
diff --git a/tools/llvmc/examples/Skeleton/Main.cpp b/tools/llvmc/examples/Skeleton/Main.cpp
deleted file mode 100644
index 24c7768..0000000
--- a/tools/llvmc/examples/Skeleton/Main.cpp
+++ /dev/null
@@ -1,15 +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.
-//
-//===----------------------------------------------------------------------===//
-//
-// Just include CompilerDriver/Main.inc and AutoGenerated.inc.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CompilerDriver/Main.inc"
-#include "AutoGenerated.inc"
diff --git a/tools/llvmc/examples/Skeleton/Makefile b/tools/llvmc/examples/Skeleton/Makefile
deleted file mode 100644
index 41ca823..0000000
--- a/tools/llvmc/examples/Skeleton/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-##===- llvmc/examples/Skeleton/Makefile --------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open
-# Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-# Change this so that $(LEVEL)/Makefile.common refers to
-# $LLVM_OBJ_DIR/Makefile.common or $YOUR_LLVM_BASED_PROJECT/Makefile.common.
-export LEVEL = ../../../..
-
-# Change this to the name of your LLVMC-based driver.
-LLVMC_BASED_DRIVER = llvmc-skeleton
-
-# Change this to the name of .inc file built from your .td file.
-BUILT_SOURCES = AutoGenerated.inc
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/examples/Skeleton/README b/tools/llvmc/examples/Skeleton/README
deleted file mode 100644
index 282ee15..0000000
--- a/tools/llvmc/examples/Skeleton/README
+++ /dev/null
@@ -1,6 +0,0 @@
-
-This is a template that can be used to create your own LLVMC-based drivers. Just
-copy the `Skeleton` directory to the location of your preference and edit
-`Skeleton/Makefile` and `Skeleton/AutoGenerated.td`.
-
-The build system assumes that your project is based on LLVM.
diff --git a/tools/llvmc/examples/mcc16/Hooks.cpp b/tools/llvmc/examples/mcc16/Hooks.cpp
deleted file mode 100644
index 95158ef..0000000
--- a/tools/llvmc/examples/mcc16/Hooks.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-#include "llvm/Support/Path.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <string>
-
-namespace llvmc {
- extern char *ProgramName;
-
- namespace autogenerated {
- extern llvm::cl::opt<std::string> Parameter_p;
- }
-}
-
-using namespace llvm;
-using namespace llvmc;
-
-// Returns the platform specific directory separator via #ifdefs.
-// FIXME: This currently work on linux and windows only. It does not
-// work on other unices.
-static std::string GetDirSeparator() {
-#if __linux__ || __APPLE__
- return "/";
-#else
- return "\\";
-#endif
-}
-
-namespace hooks {
-// Get preprocessor define for the part.
-// It is __partname format in lower case.
-std::string
-GetLowerCasePartDefine(void) {
- std::string Partname;
- if (autogenerated::Parameter_p.empty()) {
- Partname = "16f1xxx";
- } else {
- Partname = autogenerated::Parameter_p;
- }
-
- std::string LowerCase;
- for (unsigned i = 0; i < Partname.size(); i++) {
- LowerCase.push_back(std::tolower(Partname[i]));
- }
-
- return "__" + LowerCase;
-}
-
-std::string
-GetUpperCasePartDefine(void) {
- std::string Partname;
- if (autogenerated::Parameter_p.empty()) {
- Partname = "16f1xxx";
- } else {
- Partname = autogenerated::Parameter_p;
- }
-
- std::string UpperCase;
- for (unsigned i = 0; i < Partname.size(); i++) {
- UpperCase.push_back(std::toupper(Partname[i]));
- }
-
- return "__" + UpperCase;
-}
-
-// Get the dir where c16 executables reside.
-std::string GetBinDir() {
- // Construct a Path object from the program name.
- void *P = (void*) (intptr_t) GetBinDir;
- sys::Path ProgramFullPath
- = sys::Path::GetMainExecutable(llvmc::ProgramName, P);
-
- // Get the dir name for the program. It's last component should be 'bin'.
- std::string BinDir = ProgramFullPath.getDirname();
-
- // llvm::errs() << "BinDir: " << BinDir << '\n';
- return BinDir + GetDirSeparator();
-}
-
-// Get the Top-level Installation dir for c16.
-std::string GetInstallDir() {
- sys::Path BinDirPath = sys::Path(GetBinDir());
-
- // Go one more level up to get the install dir.
- std::string InstallDir = BinDirPath.getDirname();
-
- return InstallDir + GetDirSeparator();
-}
-
-// Get the dir where the c16 header files reside.
-std::string GetStdHeadersDir() {
- return GetInstallDir() + "include";
-}
-
-// Get the dir where the assembler header files reside.
-std::string GetStdAsmHeadersDir() {
- return GetInstallDir() + "inc";
-}
-
-// Get the dir where the linker scripts reside.
-std::string GetStdLinkerScriptsDir() {
- return GetInstallDir() + "lkr";
-}
-
-// Get the dir where startup code, intrinsics and lib reside.
-std::string GetStdLibsDir() {
- return GetInstallDir() + "lib";
-}
-}
diff --git a/tools/llvmc/examples/mcc16/Main.cpp b/tools/llvmc/examples/mcc16/Main.cpp
deleted file mode 100644
index 5d4992d..0000000
--- a/tools/llvmc/examples/mcc16/Main.cpp
+++ /dev/null
@@ -1,57 +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.
-//
-//===----------------------------------------------------------------------===//
-//
-// Usually this file just includes CompilerDriver/Main.inc, but here we apply
-// some trickery to make the built-in '-save-temps' option hidden and enable
-// '--temp-dir' by default.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CompilerDriver/BuiltinOptions.h"
-#include "llvm/CompilerDriver/Main.h"
-
-#include "llvm/Support/Path.h"
-#include "llvm/Config/config.h"
-
-#include <iostream>
-
-#include "PIC16.inc"
-
-namespace {
-
-// Modify the PACKAGE_VERSION to use build number in top level configure file.
-void PIC16VersionPrinter(void) {
- std::cout << "MPLAB C16 1.0 " << PACKAGE_VERSION << "\n";
-}
-
-}
-
-int main(int argc, char** argv) {
-
- // HACK
- SaveTemps.setHiddenFlag(llvm::cl::Hidden);
- TempDirname.setHiddenFlag(llvm::cl::Hidden);
- Languages.setHiddenFlag(llvm::cl::Hidden);
- DryRun.setHiddenFlag(llvm::cl::Hidden);
-
- llvm::cl::SetVersionPrinter(PIC16VersionPrinter);
-
- // Ask for a standard temp dir, but just cache its basename., and delete it.
- llvm::sys::Path tempDir;
- tempDir = llvm::sys::Path::GetTemporaryDirectory();
- TempDirname = tempDir.getBasename();
- tempDir.eraseFromDisk(true);
-
- // We are creating a temp dir in current dir, with the cached name.
- // But before that remove if one already exists with that name..
- tempDir = TempDirname;
- tempDir.eraseFromDisk(true);
-
- return llvmc::Main(argc, argv);
-}
diff --git a/tools/llvmc/examples/mcc16/Makefile b/tools/llvmc/examples/mcc16/Makefile
deleted file mode 100644
index 4409cff..0000000
--- a/tools/llvmc/examples/mcc16/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- llvmc/examples/mcc16/Makefile -----------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../../..
-
-LLVMC_BASED_DRIVER = mcc16
-BUILT_SOURCES = PIC16.inc
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/examples/mcc16/PIC16.td b/tools/llvmc/examples/mcc16/PIC16.td
deleted file mode 100644
index 6f04196..0000000
--- a/tools/llvmc/examples/mcc16/PIC16.td
+++ /dev/null
@@ -1,234 +0,0 @@
-//===- PIC16.td - PIC16 toolchain driver -------------------*- tablegen -*-===//
-//
-// A basic driver for the PIC16 toolchain.
-//
-//===----------------------------------------------------------------------===//
-
-include "llvm/CompilerDriver/Common.td"
-
-// Options
-
-def OptionList : OptionList<[
- (switch_option "g",
- (help "Enable Debugging")),
- (switch_option "E",
- (help "Stop after preprocessing, do not compile")),
- (switch_option "S",
- (help "Stop after compilation, do not assemble")),
- (switch_option "bc",
- (help "Stop after b-code generation, do not compile")),
- (switch_option "c",
- (help "Stop after assemble, do not link")),
- (prefix_option "p",
- (help "Specify part name")),
- (prefix_list_option "I",
- (help "Add a directory to include path")),
- (prefix_list_option "L",
- (help "Add a directory to library path")),
- (prefix_list_option "K",
- (help "Add a directory to linker script search path")),
- (parameter_option "l",
- (help "Specify a library to link")),
- (parameter_option "k",
- (help "Specify a linker script")),
- (parameter_option "m",
- (help "Generate linker map file with the given name")),
- (prefix_list_option "D",
- (help "Define a macro")),
- (switch_option "X",
- (help "Do not invoke mp2hex to create an output hex file.")),
- (switch_option "O0",
- (help "Do not optimize")),
- (switch_option "O1",
- (help "Optimization Level 1.")),
- (switch_option "O2",
- (help "Optimization Level 2.")),
- (switch_option "O3",
- (help "Optimization Level 3.")),
- (switch_option "Od",
- (help "Perform Debug-safe Optimizations only.")),
- (switch_option "w",
- (help "Disable all warnings.")),
-// (switch_option "O1",
-// (help "Optimization level 1")),
-// (switch_option "O2",
-// (help "Optimization level 2. (Default)")),
-// (parameter_option "pre-RA-sched",
-// (help "Example of an option that is passed to llc")),
- (parameter_option "regalloc",
- (help "Register allocator to use (possible values: simple, linearscan, pbqp, local; default=linearscan)")),
- (prefix_list_option "Wa,", (comma_separated),
- (help "Pass options to assembler (Run 'gpasm -help' for assembler options)")),
- (prefix_list_option "Wl,", (comma_separated),
- (help "Pass options to linker (Run 'mplink -help' for linker options)"))
-// (prefix_list_option "Wllc,",
-// (help "Pass options to llc")),
-// (prefix_list_option "Wo,",
-// (help "Pass options to llvm-ld"))
-]>;
-
-// Tools
-class clang_based<string language, string cmd, string ext_E> : Tool<
-[(in_language language),
- (out_language "llvm-bitcode"),
- (output_suffix "bc"),
- (command cmd),
- (actions (case
- (and (multiple_input_files),
- (or (switch_on "S"), (switch_on "c"))),
- (error "cannot specify -o with -c or -S with multiple files"),
- (switch_on "E"), [(forward "E"),
- (stop_compilation), (output_suffix ext_E)],
- (and (switch_on "E"), (empty "o")), (no_out_file),
- (switch_on "bc"),[(stop_compilation), (output_suffix "bc")],
- (switch_on "g"), (append_cmd "-g"),
- (switch_on "w"), (append_cmd "-w"),
- (switch_on "O1"), (append_cmd ""),
- (switch_on "O2"), (append_cmd ""),
- (switch_on "O3"), (append_cmd ""),
- (switch_on "Od"), (append_cmd ""),
- (not_empty "D"), (forward "D"),
- (not_empty "I"), (forward "I"),
- (switch_on "O0"), (append_cmd "-O0"),
- (default), (append_cmd "-O1")))
-// (sink)
-]>;
-
-def clang_cc : clang_based<"c", "$CALL(GetBinDir)clang -cc1 -I $CALL(GetStdHeadersDir) -D $CALL(GetLowerCasePartDefine) -D $CALL(GetUpperCasePartDefine) -triple=pic16- -emit-llvm-bc ", "i">;
-
-//def clang_cc : Tool<[
-// (in_language "c"),
-// (out_language "llvm-bitcode"),
-// (output_suffix "bc"),
-// (cmd_line "$CALL(GetBinDir)clang-cc -I $CALL(GetStdHeadersDir) -triple=pic16- -emit-llvm-bc "),
-// (cmd_line kkkkk
-// (actions (case
-// (switch_on "g"), (append_cmd "g"),
-// (not_empty "I"), (forward "I"))),
-// (sink)
-//]>;
-
-
-// pre-link-and-lto step.
-def llvm_ld : Tool<[
- (in_language "llvm-bitcode"),
- (out_language "llvm-bitcode"),
- (output_suffix "bc"),
- (command "$CALL(GetBinDir)llvm-ld -L $CALL(GetStdLibsDir) -disable-licm-promotion -l std"),
- (out_file_option "-b"),
- (actions (case
- (switch_on "O0"), (append_cmd "-disable-opt"),
- (switch_on "O1"), (append_cmd "-disable-opt"),
-// Whenever O3 is not specified on the command line, default i.e. disable-inlining will always be added.
- (switch_on "O2"), (append_cmd ""),
- (switch_on "O3"), (append_cmd ""),
- (default), (append_cmd "-disable-inlining"))),
- (join)
-]>;
-
-// optimize single file
-def llvm_ld_optimizer : Tool<[
- (in_language "llvm-bitcode"),
- (out_language "llvm-bitcode"),
- (output_suffix "bc"),
-// FIXME: we are still not disabling licm-promotion.
-// -disable-licm-promotion and building stdn library causes c16-71 to fail.
- (command "$CALL(GetBinDir)llvm-ld "),
- (out_file_option "-b"),
- (actions (case
- (switch_on "O0"), (append_cmd "-disable-opt"),
- (switch_on "O1"), (append_cmd "-disable-opt"),
-// Whenever O3 is not specified on the command line, default i.e. disable-inlining will always be added.
- (switch_on "O2"), (append_cmd ""),
- (switch_on "O3"), (append_cmd ""),
- (default), (append_cmd "-disable-inlining")))
-]>;
-
-// optimizer step.
-def pic16passes : Tool<[
- (in_language "llvm-bitcode"),
- (out_language "llvm-bitcode"),
- (output_suffix "obc"),
- (command "$CALL(GetBinDir)opt -pic16cloner -pic16overlay -f"),
- (actions (case
- (switch_on "O0"), (append_cmd "-disable-opt")))
-]>;
-
-def llc : Tool<[
- (in_language "llvm-bitcode"),
- (out_language "assembler"),
- (output_suffix "s"),
- (command "$CALL(GetBinDir)llc -march=pic16 -disable-jump-tables -pre-RA-sched=list-burr -f"),
- (actions (case
- (switch_on "S"), (stop_compilation),
-// (not_empty "Wllc,"), (unpack_values "Wllc,"),
-// (not_empty "pre-RA-sched"), (forward "pre-RA-sched")))
- (not_empty "regalloc"), (forward "regalloc"),
- (empty "regalloc"), (append_cmd "-regalloc=linearscan")))
-]>;
-
-def gpasm : Tool<[
- (in_language "assembler"),
- (out_language "object-code"),
- (output_suffix "o"),
- (command "$CALL(GetBinDir)gpasm -z -r decimal -I $CALL(GetStdAsmHeadersDir) -C -c -w 2"),
- (actions (case
- (switch_on "c"), (stop_compilation),
- (switch_on "g"), (append_cmd "-g"),
- (not_empty "p"), (forward "p"),
- (empty "p"), (append_cmd "-p 16f1xxx"),
- (not_empty "Wa,"), (forward_value "Wa,")))
-]>;
-
-def mplink : Tool<[
- (in_language "object-code"),
- (out_language "executable"),
- (output_suffix "cof"),
- (command "$CALL(GetBinDir)mplink -e -k $CALL(GetStdLinkerScriptsDir) -l $CALL(GetStdLibsDir) intrinsics.lib stdn.lib"),
- (actions (case
- (not_empty "Wl,"), (forward_value "Wl,"),
- (switch_on "X"), (append_cmd "-x"),
- (not_empty "L"), (forward_as "L", "-l"),
- (not_empty "K"), (forward_as "K", "-k"),
- (not_empty "m"), (forward "m"),
- (not_empty "p"), [(forward "p"), (append_cmd "-c")],
- (empty "p"), (append_cmd "-p 16f1xxx -c"),
-// (not_empty "l"), [(unpack_values "l"),(append_cmd ".lib")])),
- (not_empty "k"), (forward "k"),
- (not_empty "l"), (forward "l"))),
- (join)
-]>;
-
-// Language map
-
-def LanguageMap : LanguageMap<[
- (lang_to_suffixes "c", "c"),
- (lang_to_suffixes "c-cpp-output", "i"),
- (lang_to_suffixes "assembler", "s"),
- (lang_to_suffixes "assembler-with-cpp", "S"),
- (lang_to_suffixes "llvm-assembler", "ll"),
- (lang_to_suffixes "llvm-bitcode", "bc"),
- (lang_to_suffixes "object-code", "o"),
- (lang_to_suffixes "executable", "cof")
-]>;
-
-// Compilation graph
-
-def CompilationGraph : CompilationGraph<[
- (edge "root", "clang_cc"),
- (edge "root", "llvm_ld"),
- (optional_edge "root", "llvm_ld_optimizer",
- (case (switch_on "S"), (inc_weight),
- (switch_on "c"), (inc_weight))),
- (edge "root", "gpasm"),
- (edge "root", "mplink"),
- (edge "clang_cc", "llvm_ld"),
- (optional_edge "clang_cc", "llvm_ld_optimizer",
- (case (switch_on "S"), (inc_weight),
- (switch_on "c"), (inc_weight))),
- (edge "llvm_ld", "pic16passes"),
- (edge "llvm_ld_optimizer", "pic16passes"),
- (edge "pic16passes", "llc"),
- (edge "llc", "gpasm"),
- (edge "gpasm", "mplink")
-]>;
diff --git a/tools/llvmc/examples/mcc16/README b/tools/llvmc/examples/mcc16/README
deleted file mode 100644
index 6d2b73d..0000000
--- a/tools/llvmc/examples/mcc16/README
+++ /dev/null
@@ -1,75 +0,0 @@
-This is a basic compiler driver for the PIC16 toolchain that shows how to create
-your own llvmc-based drivers. It is based on the examples/Skeleton template.
-
-The PIC16 toolchain looks like this:
-
-clang-cc (FE) -> llvm-ld (optimizer) -> llc (codegen) -> native-as -> native-ld
-
-Following features were requested by Sanjiv:
-
-From: Sanjiv Gupta <sanjiv.gupta <at> microchip.com>
-Subject: Re: llvmc for PIC16
-Newsgroups: gmane.comp.compilers.llvm.devel
-Date: 2009-06-05 06:51:14 GMT
-
-The salient features that we want to have in the driver are:
-1. llvm-ld will be used as "The Optimizer".
-2. If the user has specified to generate the final executable, then
-llvm-ld should run on all the .bc files generated by clang and create a
-single optimized .bc file for further tools.
-3. -Wo <options> - pass optimizations to the llvm-ld
-4. mcc16 -Wl <options> - pass options to native linker.
-5. mcc16 -Wa <options> - pass options to native assembler.
-
-Here are some example command lines and sample command invocations as to
-what should be done.
-
-$ mcc16 -S foo.c
-// [clang-cc foo.c] -> foo.bc
-// [llvm-ld foo.bc] -> foo.opt.bc
-// [llc foo.opt.bc] -> foo.s
-
-$ mcc16 -S foo.c bar.c
-// [clang-cc foo.c] -> foo.bc
-// [llvm-ld foo.bc] -> foo.opt.bc
-// [llc foo.opt.bc] -> foo.s
-// [clang-cc bar.c] -> bar.bc
-// [llvm-ld bar.bc] -> bar.opt.bc
-// [llc bar.opt.bc] -> bar.s
-
-** Use of -g causes llvm-ld to run with -disable-opt
-$ mcc16 -S -g foo.c
-// [clang-cc foo.c] -> foo.bc
-// [llvm-ld -disable-opt foo.bc] -> foo.opt.bc
-// [llc foo.opt.bc] -> foo.s
-
-** -I is passed to clang-cc, -pre-RA-sched=list-burr to llc.
-$ mcc16 -S -g -I ../include -pre-RA-sched=list-burr foo.c
-// [clang-cc -I ../include foo.c] -> foo.bc
-// [llvm-ld -disable-opt foo.bc] -> foo.opt.bc
-// [llc -pre-RA-sched=list-burr foo.opt.bc] -> foo.s
-
-** -Wo passes options to llvm-ld
-$ mcc16 -Wo=opt1,opt2 -S -I ../include -pre-RA-sched=list-burr foo.c
-// [clang-cc -I ../include foo.c] -> foo.bc
-// [llvm-ld -opt1 -opt2 foo.bc] -> foo.opt.bc
-// [llc -pre-RA-sched=list-burr foo.opt.bc] -> foo.s
-
-** -Wa passes options to native as.
-$ mcc16 -c foo.c -Wa=opt1
-// [clang-cc foo.c] -> foo.bc
-// [llvm-ld foo.bc] -> foo.opt.bc
-// [llc foo.opt.bc] -> foo.s
-// [native-as -opt1 foo.s] -> foo.o
-
-$ mcc16 -Wo=opt1 -Wl=opt2 -Wa=opt3 foo.c bar.c
-// [clang-cc foo.c] -> foo.bc
-// [clang-cc bar.c] -> bar.bc
-// [llvm-ld -opt1 foo.bc bar.bc] -> a.out.bc
-// [llc a.out.bc] -> a.out.s
-// [native-as -opt3 a.out.s] -> a.out.o
-// [native-ld -opt2 a.out.o] -> a.out
-
-Is this achievable by a tablegen based driver ?
-
-- Sanjiv
diff --git a/tools/llvmc/src/AutoGenerated.td b/tools/llvmc/src/AutoGenerated.td
deleted file mode 100644
index 8507b1f..0000000
--- a/tools/llvmc/src/AutoGenerated.td
+++ /dev/null
@@ -1,17 +0,0 @@
-//===- AutoGenerated.td - LLVMC toolchain descriptions -----*- 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 compilation graph description used by llvmc.
-//
-//===----------------------------------------------------------------------===//
-
-include "llvm/CompilerDriver/Common.td"
-
-include "Base.td"
-include "Clang.td"
diff --git a/tools/llvmc/src/Base.td.in b/tools/llvmc/src/Base.td.in
deleted file mode 100644
index 84e39e7..0000000
--- a/tools/llvmc/src/Base.td.in
+++ /dev/null
@@ -1,461 +0,0 @@
-//===- Base.td - LLVMC toolchain descriptions --------------*- 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 compilation graph description used by llvmc.
-//
-//===----------------------------------------------------------------------===//
-
-// Options
-
-def OptList : OptionList<[
- (switch_option "emit-llvm",
- (help "Emit LLVM .ll files instead of native object files")),
- (switch_option "E",
- (help "Stop after the preprocessing stage, do not run the compiler")),
- (switch_option "fsyntax-only",
- (help "Stop after checking the input for syntax errors")),
- (switch_option "opt",
- (help "Enable opt")),
- (switch_option "O0",
- (help "Turn off optimization"), (zero_or_more)),
- (switch_option "O1",
- (help "Optimization level 1"), (zero_or_more)),
- (switch_option "O2",
- (help "Optimization level 2"), (zero_or_more)),
- (switch_option "O3",
- (help "Optimization level 3"), (zero_or_more)),
- (switch_option "S",
- (help "Stop after compilation, do not assemble")),
- (switch_option "c",
- (help "Compile and assemble, but do not link")),
- (switch_option "m32",
- (help "Generate code for a 32-bit environment"), (hidden)),
- (switch_option "m64",
- (help "Generate code for a 64-bit environment"), (hidden)),
- (switch_option "fPIC",
- (help "Relocation model: PIC"), (hidden)),
- (switch_option "mdynamic-no-pic",
- (help "Relocation model: dynamic-no-pic"), (hidden)),
- (parameter_option "linker",
- (help "Choose linker (possible values: gcc, g++)")),
- (parameter_option "mtune",
- (help "Target a specific CPU type"), (forward_not_split)),
- (parameter_list_option "march",
- (help "Generate code for the specified machine type")),
- (parameter_option "mcpu",
- (help "A deprecated synonym for -mtune"), (hidden), (forward_not_split)),
- (parameter_option "mfpu",
- (help "Specify type of floating point unit"),
- (hidden), (forward_not_split)),
- (parameter_option "mabi",
- (help "Generate code for the specified ABI"), (hidden)),
- (parameter_option "mfloat-abi",
- (help "Specifies which floating-point ABI to use"), (hidden)),
- (switch_option "mfix-and-continue",
- (help "Needed by gdb to load .o files dynamically"), (hidden)),
- (parameter_option "MF",
- (help "Specify a file to write dependencies to"), (hidden)),
- (parameter_list_option "MT",
- (help "Change the name of the rule emitted by dependency generation"),
- (hidden)),
- (parameter_list_option "include",
- (help "Include the named file prior to preprocessing")),
- (parameter_list_option "iquote",
- (help "Search dir only for files requested with #inlcude \"file\""),
- (hidden)),
- (prefix_list_option "I",
- (help "Add a directory to include path")),
- (prefix_list_option "D",
- (help "Define a macro")),
- (parameter_list_option "Xpreprocessor", (hidden),
- (help "Pass options to preprocessor")),
- (prefix_list_option "Wa,", (comma_separated),
- (help "Pass options to assembler")),
- (parameter_list_option "Xassembler", (hidden),
- (help "Pass options to assembler")),
- (prefix_list_option "Wllc,", (comma_separated),
- (help "Pass options to llc")),
- (prefix_list_option "Wl,",
- (help "Pass options to linker")),
- (parameter_list_option "Xlinker", (hidden),
- (help "Pass options to linker")),
- (prefix_list_option "Wo,", (comma_separated),
- (help "Pass options to opt")),
- (prefix_list_option "m",
- (help "Enable or disable various extensions (-mmmx, -msse, etc.)"),
- (hidden))
-]>;
-
-def LinkerOptList : OptionList<[
- (prefix_list_option "L",
- (help "Add a directory to link path")),
- (prefix_list_option "l",
- (help "Search a library when linking")),
- (parameter_option "filelist", (hidden),
- (help "Link the files listed in file")),
- (switch_option "nostartfiles",
- (help "Do not use the standard system startup files when linking"),
- (hidden)),
- (switch_option "nodefaultlibs",
- (help "Do not use the standard system libraries when linking"), (hidden)),
- (switch_option "nostdlib",
- (help
- "Do not use the standard system startup files or libraries when linking"),
- (hidden)),
- (switch_option "pie",
- (help "Produce a position independent executable"), (hidden)),
- (switch_option "rdynamic",
- (help "Add all symbols to the dynamic export table"), (hidden)),
- (switch_option "s",
- (help "Strip all symbols"), (hidden)),
- (switch_option "static",
- (help "Do not link against shared libraries"), (hidden)),
- (switch_option "static-libgcc",
- (help "Use static libgcc"), (hidden)),
- (switch_option "shared",
- (help "Create a DLL instead of the regular executable")),
- (switch_option "shared-libgcc",
- (help "Use shared libgcc"), (hidden)),
- (parameter_option "T",
- (help "Read linker script"), (hidden)),
- (parameter_option "u",
- (help "Start with undefined reference to SYMBOL"), (hidden)),
- (switch_option "pthread",
- (help "Enable threads")),
-
- // TODO: Add a conditional compilation mechanism to make Darwin-only options
- // like '-arch' really Darwin-only.
- (parameter_option "arch",
- (help "Compile for the specified target architecture"), (hidden)),
- (prefix_list_option "F",
- (help "Add a directory to framework search path")),
- (parameter_list_option "framework",
- (help "Specifies a framework to link against")),
- (parameter_list_option "weak_framework",
- (help "Specifies a framework to weakly link against"), (hidden)),
- (switch_option "dynamiclib", (hidden),
- (help "Produce a dynamic library")),
- (switch_option "prebind", (hidden),
- (help "Prebind all undefined symbols")),
- (switch_option "dead_strip", (hidden),
- (help "Remove unreachable blocks of code")),
- (switch_option "single_module", (hidden),
- (help "Build the library so it contains only one module")),
- (parameter_option "install_name", (hidden),
- (help "File name the library will be installed in")),
- (parameter_option "compatibility_version", (hidden),
- (help "Compatibility version number")),
- (parameter_option "current_version", (hidden),
- (help "Current version number"))
-]>;
-
-// Option preprocessor.
-
-def Preprocess : OptionPreprocessor<
-(case (not (any_switch_on "O0", "O1", "O2", "O3")),
- (set_option "O2"),
- (and (switch_on "O3"), (any_switch_on "O0", "O1", "O2")),
- (unset_option "O0", "O1", "O2"),
- (and (switch_on "O2"), (any_switch_on "O0", "O1")),
- (unset_option "O0", "O1"),
- (switch_on "O1", "O0"),
- (unset_option "O0"))
->;
-
-// Tools
-
-class llvm_gcc_based <string cmd, string in_lang, string E_ext, dag out_lang,
- string out_ext> : Tool<
-[(in_language in_lang),
- out_lang,
- (output_suffix out_ext),
- (command cmd),
- (actions
- (case
- (and (not_empty "o"),
- (multiple_input_files), (or (switch_on "S"), (switch_on "c"))),
- (error "cannot specify -o with -c or -S with multiple files"),
- (switch_on "E"),
- [(forward "E"), (stop_compilation), (output_suffix E_ext)],
- (and (switch_on "E"), (empty "o")), (no_out_file),
-
- // ('-emit-llvm') && !('opt') -> stop compilation
- (and (switch_on "emit-llvm"), (not (switch_on "opt"))),
- (stop_compilation),
- // ('-S' && '-emit-llvm') && !('opt') -> output .ll
- (and (switch_on "emit-llvm", "S"), (not (switch_on "opt"))),
- [(forward "S"), (output_suffix "ll")],
- // Usually just output .bc
- (not (switch_on "fsyntax-only")),
- [(append_cmd "-c"), (append_cmd "-emit-llvm")],
-
- // -fsyntax-only
- (switch_on "fsyntax-only"), [(forward "fsyntax-only"),
- (no_out_file), (stop_compilation)],
-
- // Forwards
- (not_empty "Xpreprocessor"), (forward "Xpreprocessor"),
- (not_empty "include"), (forward "include"),
- (not_empty "iquote"), (forward "iquote"),
- (not_empty "save-temps"), (append_cmd "-save-temps"),
- (not_empty "I"), (forward "I"),
- (not_empty "F"), (forward "F"),
- (not_empty "D"), (forward "D"),
- (not_empty "arch"), (forward "arch"),
- (not_empty "march"), (forward "march"),
- (not_empty "mcpu"), (forward "mcpu"),
- (not_empty "mtune"), (forward "mtune"),
- (not_empty "mfpu"), (forward "mfpu"),
- (not_empty "mabi"), (forward "mabi"),
- (not_empty "mfloat-abi"), (forward "mfloat-abi"),
- (not_empty "m"), (forward "m"),
- (switch_on "mfix-and-continue"), (forward "mfix-and-continue"),
- (switch_on "m32"), (forward "m32"),
- (switch_on "m64"), (forward "m64"),
- (switch_on "O0"), (forward "O0"),
- (switch_on "O1"), (forward "O1"),
- (switch_on "O2"), (forward "O2"),
- (switch_on "O3"), (forward "O3"),
- (switch_on "fPIC"), (forward "fPIC"),
- (switch_on "mdynamic-no-pic"), (forward "mdynamic-no-pic"),
- (not_empty "MF"), (forward "MF"),
- (not_empty "MT"), (forward "MT"))),
- (sink)
-]>;
-
-class llvm_gcc_comp_based <string cmd, string in_lang, string E_ext>
-: llvm_gcc_based<cmd, in_lang, E_ext,
- (out_language "llvm-bitcode", "object-code"), "bc">;
-
-class llvm_gcc_pch_based <string cmd, string in_lang, string E_ext>
-: llvm_gcc_based<cmd, in_lang, E_ext,
- (out_language "precompiled-header"), "gch">;
-
-def llvm_gcc_c : llvm_gcc_comp_based
- <"@LLVMGCCCOMMAND@ -x c", "c", "i">;
-def llvm_gcc_cpp : llvm_gcc_comp_based
- <"@LLVMGXXCOMMAND@ -x c++", "c++", "i">;
-def llvm_gcc_m : llvm_gcc_comp_based
- <"@LLVMGCCCOMMAND@ -x objective-c", "objective-c", "mi">;
-def llvm_gcc_mxx : llvm_gcc_comp_based
- <"@LLVMGCCCOMMAND@ -x objective-c++", "objective-c++", "mi">;
-
-def llvm_gcc_c_pch : llvm_gcc_pch_based
- <"@LLVMGCCCOMMAND@ -x c-header", "c-header", "i">;
-def llvm_gcc_cpp_pch : llvm_gcc_pch_based
- <"@LLVMGXXCOMMAND@ -x c++-header", "c++-header", "i">;
-def llvm_gcc_m_pch : llvm_gcc_pch_based
- <"@LLVMGCCCOMMAND@ -x objective-c-header", "objective-c-header", "mi">;
-def llvm_gcc_mxx_pch : llvm_gcc_pch_based
- <"@LLVMGCCCOMMAND@ -x objective-c++-header", "objective-c++-header", "mi">;
-
-def opt : Tool<
-[(in_language "llvm-bitcode"),
- (out_language "llvm-bitcode"),
- (output_suffix "opt.bc"),
- (actions (case (switch_on "emit-llvm"), (stop_compilation),
- (switch_on "emit-llvm", "S"),
- [(append_cmd "-S"), (output_suffix "ll")],
- (not_empty "Wo,"), (forward_value "Wo,"),
- (switch_on "O1"), (forward "O1"),
- (switch_on "O2"), (forward "O2"),
- (switch_on "O3"), (forward "O3"))),
- (command "opt -f")
-]>;
-
-def llvm_as : Tool<
-[(in_language "llvm-assembler"),
- (out_language "llvm-bitcode"),
- (output_suffix "bc"),
- (command "llvm-as"),
- (actions (case (and (switch_on "emit-llvm"), (not (switch_on "opt"))),
- (stop_compilation)))
-]>;
-
-def llvm_gcc_assembler : Tool<
-[(in_language "assembler"),
- (out_language "object-code"),
- (output_suffix "o"),
- (command "@LLVMGCCCOMMAND@ -c -x assembler"),
- (actions (case
- (switch_on "c"), (stop_compilation),
- (not_empty "arch"), (forward "arch"),
- (not_empty "Xassembler"), (forward "Xassembler"),
- (not_empty "march"), (forward "march"),
- (not_empty "mcpu"), (forward "mcpu"),
- (not_empty "mtune"), (forward "mtune"),
- (not_empty "mabi"), (forward "mabi"),
- (not_empty "mfloat-abi"), (forward "mfloat-abi"),
- (switch_on "m32"), (forward "m32"),
- (switch_on "m64"), (forward "m64"),
- (not_empty "Wa,"), (forward "Wa,")))
-]>;
-
-def llc : Tool<
-[(in_language "llvm-bitcode", "llvm-assembler"),
- (out_language "assembler"),
- (output_suffix "s"),
- (command "llc -disable-cfi"),
- (actions (case
- (switch_on "S"), (stop_compilation),
- (switch_on "O0"), (forward "O0"),
- (switch_on "O1"), (forward "O1"),
- (switch_on "O2"), (forward "O2"),
- (switch_on "O3"), (forward "O3"),
- (switch_on "fPIC"), (append_cmd "-relocation-model=pic"),
- (switch_on "mdynamic-no-pic"),
- (append_cmd "-relocation-model=dynamic-no-pic"),
- (not_empty "march"), (forward_transformed_value
- "march", "ConvertMArchToMAttr"),
- (not_empty "mcpu"), (forward_transformed_value "mcpu", "ConvertMCpu"),
- (and (not_empty "mtune"), (empty "mcpu")),
- (forward_as "mtune", "-mcpu"),
- (not_empty "mfpu"), (forward_transformed_value "mfpu", "ConvertMFpu"),
- (not_empty "m"), (forward_transformed_value "m", "ConvertToMAttr"),
- (not_empty "Wllc,"), (forward_value "Wllc,")))
-]>;
-
-// Base class for linkers
-class llvm_gcc_based_linker <string cmd, dag on_empty> : Tool<
-[(in_language "object-code", "static-library", "dynamic-library"),
- (out_language "executable"),
- (output_suffix "out"),
- (command cmd),
- (works_on_empty (case (and (not_empty "filelist"), on_empty), true,
- (default), false)),
- (join),
- (actions (case
- (switch_on "pthread"), (append_cmd "-lpthread"),
- (not_empty "L"), (forward "L"),
- (not_empty "F"), (forward "F"),
- (not_empty "arch"), (forward "arch"),
- (not_empty "framework"), (forward "framework"),
- (not_empty "weak_framework"), (forward "weak_framework"),
- (not_empty "filelist"), (forward "filelist"),
- (not_empty "march"), (forward "march"),
- (not_empty "mcpu"), (forward "mcpu"),
- (not_empty "mtune"), (forward "mtune"),
- (not_empty "mabi"), (forward "mabi"),
- (not_empty "mfloat-abi"), (forward "mfloat-abi"),
- (switch_on "m32"), (forward "m32"),
- (switch_on "m64"), (forward "m64"),
- (not_empty "l"), (forward "l"),
- (not_empty "Xlinker"), (forward "Xlinker"),
- (not_empty "Wl,"), (forward "Wl,"),
- (switch_on "nostartfiles"), (forward "nostartfiles"),
- (switch_on "nodefaultlibs"), (forward "nodefaultlibs"),
- (switch_on "nostdlib"), (forward "nostdlib"),
- (switch_on "pie"), (forward "pie"),
- (switch_on "rdynamic"), (forward "rdynamic"),
- (switch_on "s"), (forward "s"),
- (switch_on "static"), (forward "static"),
- (switch_on "static-libgcc"), (forward "static-libgcc"),
- (switch_on "shared"), (forward "shared"),
- (switch_on "shared-libgcc"), (forward "shared-libgcc"),
- (not_empty "T"), (forward "T"),
- (not_empty "u"), (forward "u"),
- (switch_on "dynamiclib"), (forward "dynamiclib"),
- (switch_on "prebind"), (forward "prebind"),
- (switch_on "dead_strip"), (forward "dead_strip"),
- (switch_on "single_module"), (forward "single_module"),
- (not_empty "compatibility_version"),
- (forward "compatibility_version"),
- (not_empty "current_version"), (forward "current_version"),
- (not_empty "install_name"), (forward "install_name")))
-]>;
-
-// Default linker
-def llvm_gcc_linker : llvm_gcc_based_linker<"@LLVMGCCCOMMAND@",
- (not (or (parameter_equals "linker", "g++"),
- (parameter_equals "linker", "c++")))>;
-// Alternative linker for C++
-def llvm_gcc_cpp_linker : llvm_gcc_based_linker<"@LLVMGXXCOMMAND@",
- (or (parameter_equals "linker", "g++"),
- (parameter_equals "linker", "c++"))>;
-
-// Language map
-
-def LanguageMap : LanguageMap<[
- (lang_to_suffixes "precompiled-header", ["gch", "pch"]),
- (lang_to_suffixes "c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]),
- (lang_to_suffixes "c++-header", "hpp"),
- (lang_to_suffixes "c", "c"),
- (lang_to_suffixes "c-header", "h"),
- (lang_to_suffixes "c-cpp-output", "i"),
- (lang_to_suffixes "objective-c-cpp-output", "mi"),
- (lang_to_suffixes "objective-c++", "mm"),
- (lang_to_suffixes "objective-c++-header", "hmm"),
- (lang_to_suffixes "objective-c", "m"),
- (lang_to_suffixes "objective-c-header", "hm"),
- (lang_to_suffixes "assembler", "s"),
- (lang_to_suffixes "assembler-with-cpp", "S"),
- (lang_to_suffixes "llvm-assembler", "ll"),
- (lang_to_suffixes "llvm-bitcode", "bc"),
- (lang_to_suffixes "object-code", ["o", "*empty*"]),
- (lang_to_suffixes "static-library", ["a", "lib"]),
- (lang_to_suffixes "dynamic-library", ["so", "dylib", "dll"]),
- (lang_to_suffixes "executable", "out")
-]>;
-
-// Compilation graph
-
-def CompilationGraph : CompilationGraph<[
- (edge "root", "llvm_gcc_c"),
- (edge "root", "llvm_gcc_assembler"),
- (edge "root", "llvm_gcc_cpp"),
- (edge "root", "llvm_gcc_m"),
- (edge "root", "llvm_gcc_mxx"),
- (edge "root", "llc"),
-
- (edge "root", "llvm_gcc_c_pch"),
- (edge "root", "llvm_gcc_cpp_pch"),
- (edge "root", "llvm_gcc_m_pch"),
- (edge "root", "llvm_gcc_mxx_pch"),
-
- (edge "llvm_gcc_c", "llc"),
- (edge "llvm_gcc_cpp", "llc"),
- (edge "llvm_gcc_m", "llc"),
- (edge "llvm_gcc_mxx", "llc"),
- (edge "llvm_as", "llc"),
-
- (optional_edge "root", "llvm_as",
- (case (or (switch_on "emit-llvm"),
- (switch_on "opt")), (inc_weight))),
- (optional_edge "llvm_gcc_c", "opt",
- (case (switch_on "opt"), (inc_weight))),
- (optional_edge "llvm_gcc_cpp", "opt",
- (case (switch_on "opt"), (inc_weight))),
- (optional_edge "llvm_gcc_m", "opt",
- (case (switch_on "opt"), (inc_weight))),
- (optional_edge "llvm_gcc_mxx", "opt",
- (case (switch_on "opt"), (inc_weight))),
- (optional_edge "llvm_as", "opt",
- (case (switch_on "opt"), (inc_weight))),
- (edge "opt", "llc"),
-
- (edge "llc", "llvm_gcc_assembler"),
- (edge "llvm_gcc_assembler", "llvm_gcc_linker"),
- (optional_edge "llvm_gcc_assembler", "llvm_gcc_cpp_linker",
- (case
- (or (input_languages_contain "c++"),
- (input_languages_contain "objective-c++")),
- (inc_weight),
- (or (parameter_equals "linker", "g++"),
- (parameter_equals "linker", "c++")), (inc_weight))),
-
-
- (edge "root", "llvm_gcc_linker"),
- (optional_edge "root", "llvm_gcc_cpp_linker",
- (case
- (or (input_languages_contain "c++"),
- (input_languages_contain "objective-c++")),
- (inc_weight),
- (or (parameter_equals "linker", "g++"),
- (parameter_equals "linker", "c++")), (inc_weight)))
-]>;
diff --git a/tools/llvmc/src/Clang.td b/tools/llvmc/src/Clang.td
deleted file mode 100644
index e2d32e8..0000000
--- a/tools/llvmc/src/Clang.td
+++ /dev/null
@@ -1,87 +0,0 @@
-//===- Clang.td - LLVMC toolchain descriptions -------------*- 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 compilation graph description used by llvmc.
-//
-//===----------------------------------------------------------------------===//
-
-
-def Options : OptionList<[
-(switch_option "clang", (help "Use Clang instead of llvm-gcc"))
-]>;
-
-class clang_based<string language, string cmd, string ext_E> : Tool<
-[(in_language language),
- (out_language "llvm-bitcode"),
- (output_suffix "bc"),
- (command cmd),
- (actions (case (switch_on "E"),
- [(forward "E"), (stop_compilation), (output_suffix ext_E)],
- (and (switch_on "E"), (empty "o")), (no_out_file),
- (switch_on "fsyntax-only"), (stop_compilation),
- (switch_on "S", "emit-llvm"),
- [(append_cmd "-emit-llvm"),
- (stop_compilation), (output_suffix "ll")],
- (not (switch_on "S", "emit-llvm")),
- (append_cmd "-emit-llvm-bc"),
- (switch_on "c", "emit-llvm"),
- (stop_compilation),
- (not_empty "include"), (forward "include"),
- (not_empty "I"), (forward "I"))),
- (sink)
-]>;
-
-def clang_c : clang_based<"c", "clang -x c", "i">;
-def clang_cpp : clang_based<"c++", "clang -x c++", "i">;
-def clang_objective_c : clang_based<"objective-c",
- "clang -x objective-c", "mi">;
-def clang_objective_cpp : clang_based<"objective-c++",
- "clang -x objective-c++", "mi">;
-
-def as : Tool<
-[(in_language "assembler"),
- (out_language "object-code"),
- (output_suffix "o"),
- (command "as"),
- (actions (case (not_empty "Wa,"), (forward_value "Wa,"),
- (switch_on "c"), (stop_compilation)))
-]>;
-
-// Default linker
-def llvm_ld : Tool<
-[(in_language "object-code"),
- (out_language "executable"),
- (output_suffix "out"),
- (command "llvm-ld -native -disable-internalize"),
- (actions (case
- (switch_on "pthread"), (append_cmd "-lpthread"),
- (not_empty "L"), (forward "L"),
- (not_empty "l"), (forward "l"),
- (not_empty "Wl,"), (forward_value "Wl,"))),
- (join)
-]>;
-
-// Compilation graph
-
-def ClangCompilationGraph : CompilationGraph<[
- (optional_edge "root", "clang_c",
- (case (switch_on "clang"), (inc_weight))),
- (optional_edge "root", "clang_cpp",
- (case (switch_on "clang"), (inc_weight))),
- (optional_edge "root", "clang_objective_c",
- (case (switch_on "clang"), (inc_weight))),
- (optional_edge "root", "clang_objective_cpp",
- (case (switch_on "clang"), (inc_weight))),
- (edge "clang_c", "llc"),
- (edge "clang_cpp", "llc"),
- (edge "clang_objective_c", "llc"),
- (edge "clang_objective_cpp", "llc"),
- (optional_edge "llc", "as", (case (switch_on "clang"), (inc_weight))),
- (edge "as", "llvm_ld")
-]>;
diff --git a/tools/llvmc/src/Hooks.cpp b/tools/llvmc/src/Hooks.cpp
deleted file mode 100644
index ddad08a..0000000
--- a/tools/llvmc/src/Hooks.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-#include "llvm/ADT/StringMap.h"
-
-#include <string>
-#include <vector>
-
-namespace hooks {
-
-/// NUM_KEYS - Calculate the size of a const char* array.
-#define NUM_KEYS(Keys) sizeof(Keys) / sizeof(const char*)
-
-// See http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
-inline unsigned NextHighestPowerOf2 (unsigned i) {
- --i;
- i |= i >> 1;
- i |= i >> 2;
- i |= i >> 4;
- i |= i >> 8;
- i |= i >> 16;
- ++i;
- return i;
-}
-
-typedef std::vector<std::string> StrVec;
-typedef llvm::StringMap<const char*> ArgMap;
-
-/// AddPlusOrMinus - Convert 'no-foo' to '-foo' and 'foo' to '+foo'.
-void AddPlusOrMinus (const std::string& Arg, std::string& out) {
- if (Arg.find("no-") == 0 && Arg[3] != 0) {
- out += '-';
- out += Arg.c_str() + 3;
- }
- else {
- out += '+';
- out += Arg;
- }
-}
-
-// -march values that need to be special-cased.
-const char* MArchKeysARM[] = { "armv4t", "armv5t", "armv5te", "armv6",
- "armv6-m", "armv6t2", "armv7-a", "armv7-m" };
-const char* MArchValuesARM[] = { "v4t", "v5t", "v5te", "v6", "v6m", "v6t2",
- "v7a", "v7m" };
-const unsigned MArchNumKeysARM = NUM_KEYS(MArchKeysARM);
-const unsigned MArchMapSize = NextHighestPowerOf2(MArchNumKeysARM);
-
-// -march values that should be forwarded as -mcpu
-const char* MArchMCpuKeysARM[] = { "iwmmxt", "ep9312" };
-const char* MArchMCpuValuesARM[] = { "iwmmxt", "ep9312"};
-const unsigned MArchMCpuNumKeysARM = NUM_KEYS(MArchMCpuKeysARM);
-
-
-void FillInArgMap(ArgMap& Args, const char* Keys[],
- const char* Values[], unsigned NumKeys)
-{
- for (unsigned i = 0; i < NumKeys; ++i) {
- // Explicit cast to StringRef here is necessary to pick up the right
- // overload.
- Args.GetOrCreateValue(llvm::StringRef(Keys[i]), Values[i]);
- }
-}
-
-/// ConvertMArchToMAttr - Convert -march from the gcc dialect to
-/// something llc can understand.
-std::string ConvertMArchToMAttr(const StrVec& Opts) {
- static ArgMap MArchMap(MArchMapSize);
- static ArgMap MArchMCpuMap(MArchMapSize);
- static bool StaticDataInitialized = false;
-
- if (!StaticDataInitialized) {
- FillInArgMap(MArchMap, MArchKeysARM, MArchValuesARM, MArchNumKeysARM);
- FillInArgMap(MArchMCpuMap, MArchMCpuKeysARM,
- MArchMCpuValuesARM, MArchMCpuNumKeysARM);
- StaticDataInitialized = true;
- }
-
- std::string mattr("-mattr=");
- std::string mcpu("-mcpu=");
- bool mattrTouched = false;
- bool mcpuTouched = false;
-
- for (StrVec::const_iterator B = Opts.begin(), E = Opts.end(); B!=E; ++B) {
- const std::string& Arg = *B;
-
- // Check if the argument should be forwarded to -mcpu instead of -mattr.
- {
- ArgMap::const_iterator I = MArchMCpuMap.find(Arg);
-
- if (I != MArchMCpuMap.end()) {
- mcpuTouched = true;
- mcpu += I->getValue();
- continue;
- }
- }
-
- if (mattrTouched)
- mattr += ",";
-
- // Check if the argument is a special case.
- {
- ArgMap::const_iterator I = MArchMap.find(Arg);
-
- if (I != MArchMap.end()) {
- mattrTouched = true;
- mattr += '+';
- mattr += I->getValue();
- continue;
- }
- }
-
- AddPlusOrMinus(Arg, mattr);
- }
-
- std::string out;
- if (mattrTouched)
- out += mattr;
- if (mcpuTouched)
- out += (mattrTouched ? " " : "") + mcpu;
-
- return out;
-}
-
-// -mcpu values that need to be special-cased.
-const char* MCpuKeysPPC[] = { "G3", "G4", "G5", "powerpc", "powerpc64"};
-const char* MCpuValuesPPC[] = { "g3", "g4", "g5", "ppc", "ppc64"};
-const unsigned MCpuNumKeysPPC = NUM_KEYS(MCpuKeysPPC);
-const unsigned MCpuMapSize = NextHighestPowerOf2(MCpuNumKeysPPC);
-
-/// ConvertMCpu - Convert -mcpu value from the gcc to the llc dialect.
-std::string ConvertMCpu(const char* Val) {
- static ArgMap MCpuMap(MCpuMapSize);
- static bool StaticDataInitialized = false;
-
- if (!StaticDataInitialized) {
- FillInArgMap(MCpuMap, MCpuKeysPPC, MCpuValuesPPC, MCpuNumKeysPPC);
- StaticDataInitialized = true;
- }
-
- std::string ret = "-mcpu=";
- ArgMap::const_iterator I = MCpuMap.find(Val);
- if (I != MCpuMap.end()) {
- return ret + I->getValue();
- }
- return ret + Val;
-}
-
-// -mfpu values that need to be special-cased.
-const char* MFpuKeysARM[] = { "vfp", "vfpv3",
- "vfpv3-fp16", "vfpv3-d16", "vfpv3-d16-fp16",
- "neon", "neon-fp16" };
-const char* MFpuValuesARM[] = { "vfp2", "vfp3",
- "+vfp3,+fp16", "+vfp3,+d16", "+vfp3,+d16,+fp16",
- "+neon", "+neon,+neonfp" };
-const unsigned MFpuNumKeysARM = NUM_KEYS(MFpuKeysARM);
-const unsigned MFpuMapSize = NextHighestPowerOf2(MFpuNumKeysARM);
-
-/// ConvertMFpu - Convert -mfpu value from the gcc to the llc dialect.
-std::string ConvertMFpu(const char* Val) {
- static ArgMap MFpuMap(MFpuMapSize);
- static bool StaticDataInitialized = false;
-
- if (!StaticDataInitialized) {
- FillInArgMap(MFpuMap, MFpuKeysARM, MFpuValuesARM, MFpuNumKeysARM);
- StaticDataInitialized = true;
- }
-
- std::string ret = "-mattr=";
- ArgMap::const_iterator I = MFpuMap.find(Val);
- if (I != MFpuMap.end()) {
- return ret + I->getValue();
- }
- return ret + '+' + Val;
-}
-
-/// ConvertToMAttr - Convert '-mfoo' and '-mno-bar' to '-mattr=+foo,-bar'.
-std::string ConvertToMAttr(const StrVec& Opts) {
- std::string out("-mattr=");
- bool firstIter = true;
-
- for (StrVec::const_iterator B = Opts.begin(), E = Opts.end(); B!=E; ++B) {
- const std::string& Arg = *B;
-
- if (firstIter)
- firstIter = false;
- else
- out += ",";
-
- AddPlusOrMinus(Arg, out);
- }
-
- return out;
-}
-
-}
diff --git a/tools/llvmc/src/Main.cpp b/tools/llvmc/src/Main.cpp
deleted file mode 100644
index 9f9c71a..0000000
--- a/tools/llvmc/src/Main.cpp
+++ /dev/null
@@ -1,16 +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.
-//
-//===----------------------------------------------------------------------===//
-//
-// Just include AutoGenerated.inc and CompilerDriver/Main.inc.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AutoGenerated.inc"
-
-#include "llvm/CompilerDriver/Main.inc"
diff --git a/tools/llvmc/src/Makefile b/tools/llvmc/src/Makefile
deleted file mode 100644
index f3f3091..0000000
--- a/tools/llvmc/src/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-##===- tools/llvmc/src/Makefile ----------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open
-# Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../..
-LLVMC_BASED_DRIVER = llvmc
-BUILT_SOURCES = AutoGenerated.inc
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp
index 14594cf..6c8dbad 100644
--- a/tools/lto/LTOCodeGenerator.cpp
+++ b/tools/lto/LTOCodeGenerator.cpp
@@ -23,6 +23,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/Passes.h"
+#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -31,19 +32,21 @@
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetSelect.h"
+#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/PassManagerBuilder.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/system_error.h"
#include "llvm/Config/config.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
@@ -73,8 +76,7 @@ LTOCodeGenerator::LTOCodeGenerator()
_nativeObjectFile(NULL)
{
InitializeAllTargets();
- InitializeAllMCAsmInfos();
- InitializeAllMCSubtargetInfos();
+ InitializeAllTargetMCs();
InitializeAllAsmPrinters();
}
@@ -191,7 +193,7 @@ bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg)
bool genResult = false;
tool_output_file objFile(uniqueObjPath.c_str(), errMsg);
if (!errMsg.empty())
- return NULL;
+ return true;
genResult = this->generateObjectFile(objFile.os(), errMsg);
objFile.os().close();
if (objFile.os().has_error()) {
@@ -250,23 +252,25 @@ bool LTOCodeGenerator::determineTarget(std::string& errMsg)
// The relocation model is actually a static member of TargetMachine
// and needs to be set before the TargetMachine is instantiated.
+ Reloc::Model RelocModel = Reloc::Default;
switch( _codeModel ) {
case LTO_CODEGEN_PIC_MODEL_STATIC:
- TargetMachine::setRelocationModel(Reloc::Static);
+ RelocModel = Reloc::Static;
break;
case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
- TargetMachine::setRelocationModel(Reloc::PIC_);
+ RelocModel = Reloc::PIC_;
break;
case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
- TargetMachine::setRelocationModel(Reloc::DynamicNoPIC);
+ RelocModel = Reloc::DynamicNoPIC;
break;
}
- // construct LTModule, hand over ownership of module and target
+ // construct LTOModule, hand over ownership of module and target
SubtargetFeatures Features;
Features.getDefaultSubtargetFeatures(llvm::Triple(Triple));
std::string FeatureStr = Features.getString();
- _target = march->createTargetMachine(Triple, _mCpu, FeatureStr);
+ _target = march->createTargetMachine(Triple, _mCpu, FeatureStr,
+ RelocModel);
}
return false;
}
@@ -308,7 +312,7 @@ void LTOCodeGenerator::applyScopeRestrictions() {
passes.add(createVerifierPass());
// mark which symbols can not be internalized
- MCContext Context(*_target->getMCAsmInfo(), NULL);
+ MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(), NULL);
Mangler mangler(Context, *_target->getTargetData());
std::vector<const char*> mustPreserveList;
SmallPtrSet<GlobalValue*, 8> asmUsed;
@@ -329,7 +333,7 @@ void LTOCodeGenerator::applyScopeRestrictions() {
if (LLVMCompilerUsed)
LLVMCompilerUsed->eraseFromParent();
- const llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context);
+ llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context);
std::vector<Constant*> asmUsed2;
for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(),
e = asmUsed.end(); i !=e; ++i) {
diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp
index dc99b94..4ba8985 100644
--- a/tools/lto/LTOModule.cpp
+++ b/tools/lto/LTOModule.cpp
@@ -27,6 +27,8 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/system_error.h"
#include "llvm/Target/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -38,10 +40,9 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/Target/TargetAsmParser.h"
+#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetSelect.h"
+#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;
@@ -135,8 +136,7 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer,
static bool Initialized = false;
if (!Initialized) {
InitializeAllTargets();
- InitializeAllMCAsmInfos();
- InitializeAllMCSubtargetInfos();
+ InitializeAllTargetMCs();
InitializeAllAsmParsers();
Initialized = true;
}
@@ -165,7 +165,7 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer,
std::string CPU;
TargetMachine *target = march->createTargetMachine(Triple, CPU, FeatureStr);
LTOModule *Ret = new LTOModule(m.take(), target);
- bool Err = Ret->ParseSymbols();
+ bool Err = Ret->ParseSymbols(errMsg);
if (Err) {
delete Ret;
return NULL;
@@ -581,7 +581,8 @@ namespace {
markDefined(*Symbol);
}
virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {}
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {}
virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {}
virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {}
@@ -612,22 +613,30 @@ namespace {
};
}
-bool LTOModule::addAsmGlobalSymbols(MCContext &Context) {
+bool LTOModule::addAsmGlobalSymbols(MCContext &Context, std::string &errMsg) {
const std::string &inlineAsm = _module->getModuleInlineAsm();
+ if (inlineAsm.empty())
+ return false;
OwningPtr<RecordStreamer> Streamer(new RecordStreamer(Context));
MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(inlineAsm);
SourceMgr SrcMgr;
SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
- OwningPtr<MCAsmParser> Parser(createMCAsmParser(_target->getTarget(), SrcMgr,
+ OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr,
Context, *Streamer,
*_target->getMCAsmInfo()));
OwningPtr<MCSubtargetInfo> STI(_target->getTarget().
createMCSubtargetInfo(_target->getTargetTriple(),
_target->getTargetCPU(),
_target->getTargetFeatureString()));
- OwningPtr<TargetAsmParser>
- TAP(_target->getTarget().createAsmParser(*STI, *Parser.get()));
+ OwningPtr<MCTargetAsmParser>
+ TAP(_target->getTarget().createMCAsmParser(*STI, *Parser.get()));
+ if (!TAP) {
+ errMsg = "target " + std::string(_target->getTarget().getName()) +
+ " does not define AsmParser.";
+ return true;
+ }
+
Parser->setTargetParser(*TAP);
int Res = Parser->Run(false);
if (Res)
@@ -660,9 +669,9 @@ static bool isAliasToDeclaration(const GlobalAlias &V) {
return isDeclaration(*V.getAliasedGlobal());
}
-bool LTOModule::ParseSymbols() {
+bool LTOModule::ParseSymbols(std::string &errMsg) {
// Use mangler to add GlobalPrefix to names to match linker names.
- MCContext Context(*_target->getMCAsmInfo(), NULL);
+ MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL);
Mangler mangler(Context, *_target->getTargetData());
// add functions
@@ -683,7 +692,7 @@ bool LTOModule::ParseSymbols() {
}
// add asm globals
- if (addAsmGlobalSymbols(Context))
+ if (addAsmGlobalSymbols(Context, errMsg))
return true;
// add aliases
diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h
index 0b64a90..ca08aea 100644
--- a/tools/lto/LTOModule.h
+++ b/tools/lto/LTOModule.h
@@ -76,7 +76,7 @@ struct LTOModule {
private:
LTOModule(llvm::Module* m, llvm::TargetMachine* t);
- bool ParseSymbols();
+ bool ParseSymbols(std::string &errMsg);
void addDefinedSymbol(llvm::GlobalValue* def,
llvm::Mangler& mangler,
bool isFunction);
@@ -86,7 +86,8 @@ private:
llvm::Mangler &mangler);
void addDefinedDataSymbol(llvm::GlobalValue* v,
llvm::Mangler &mangler);
- bool addAsmGlobalSymbols(llvm::MCContext &Context);
+ bool addAsmGlobalSymbols(llvm::MCContext &Context,
+ std::string &errMsg);
void addAsmGlobalSymbol(const char *,
lto_symbol_attributes scope);
void addAsmGlobalSymbolUndef(const char *);
diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp
index f324259..2b22c3b 100644
--- a/tools/macho-dump/macho-dump.cpp
+++ b/tools/macho-dump/macho-dump.cpp
@@ -310,6 +310,29 @@ static int DumpDysymtabCommand(MachOObject &Obj,
return Res;
}
+static int DumpLinkeditDataCommand(MachOObject &Obj,
+ const MachOObject::LoadCommandInfo &LCI) {
+ InMemoryStruct<macho::LinkeditDataLoadCommand> LLC;
+ Obj.ReadLinkeditDataLoadCommand(LCI, LLC);
+ if (!LLC)
+ return Error("unable to read segment load command");
+
+ outs() << " ('dataoff', " << LLC->DataOffset << ")\n"
+ << " ('datasize', " << LLC->DataSize << ")\n"
+ << " ('_addresses', [\n";
+
+ SmallVector<uint64_t, 8> Addresses;
+ Obj.ReadULEB128s(LLC->DataOffset, Addresses);
+ for (unsigned i = 0, e = Addresses.size(); i != e; ++i)
+ outs() << " # Address " << i << '\n'
+ << " ('address', " << format("0x%x", Addresses[i]) << "),\n";
+
+ outs() << " ])\n";
+
+ return 0;
+}
+
+
static int DumpLoadCommand(MachOObject &Obj, unsigned Index) {
const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index);
int Res = 0;
@@ -330,6 +353,11 @@ static int DumpLoadCommand(MachOObject &Obj, unsigned Index) {
case macho::LCT_Dysymtab:
Res = DumpDysymtabCommand(Obj, LCI);
break;
+ case macho::LCT_CodeSignature:
+ case macho::LCT_SegmentSplitInfo:
+ case macho::LCT_FunctionStarts:
+ Res = DumpLinkeditDataCommand(Obj, LCI);
+ break;
default:
Warning("unknown load command: " + Twine(LCI.Command.Type));
break;
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index aa375c5..ffd2c21 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -35,11 +35,11 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/PassManagerBuilder.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/LinkAllVMCore.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include <memory>
#include <algorithm>
using namespace llvm;
@@ -431,8 +431,6 @@ static void AddOptimizationPasses(PassManagerBase &MPM,FunctionPassManager &FPM,
static void AddStandardCompilePasses(PassManagerBase &PM) {
PM.add(createVerifierPass()); // Verify that input is correct
- addPass(PM, createLowerSetJmpPass()); // Lower llvm.setjmp/.longjmp
-
// If the -strip-debug command line option was specified, do it.
if (StripDebug)
addPass(PM, createStripSymbolsPass(true));
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp
index 08ac2a0..b6e02e3 100644
--- a/unittests/ADT/APFloatTest.cpp
+++ b/unittests/ADT/APFloatTest.cpp
@@ -34,11 +34,13 @@ static std::string convertToString(double d, unsigned Prec, unsigned Pad) {
namespace {
TEST(APFloatTest, Zero) {
- EXPECT_EQ(0.0f, APFloat(APFloat::IEEEsingle, 0.0f).convertToFloat());
- EXPECT_EQ(-0.0f, APFloat(APFloat::IEEEsingle, -0.0f).convertToFloat());
+ EXPECT_EQ(0.0f, APFloat(0.0f).convertToFloat());
+ EXPECT_EQ(-0.0f, APFloat(-0.0f).convertToFloat());
+ EXPECT_TRUE(APFloat(-0.0f).isNegative());
- EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble, 0.0).convertToDouble());
- EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, -0.0).convertToDouble());
+ EXPECT_EQ(0.0, APFloat(0.0).convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(-0.0).convertToDouble());
+ EXPECT_TRUE(APFloat(-0.0).isNegative());
}
TEST(APFloatTest, fromZeroDecimalString) {
@@ -646,4 +648,9 @@ TEST(APFloatTest, exactInverse) {
EXPECT_FALSE(APFloat(1.40129846e-45f).getExactInverse(0));
}
+TEST(APFloatTest, getLargest) {
+ EXPECT_EQ(3.402823466e+38f, APFloat::getLargest(APFloat::IEEEsingle).convertToFloat());
+ EXPECT_EQ(1.7976931348623158e+308, APFloat::getLargest(APFloat::IEEEdouble).convertToDouble());
+}
+
}
diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp
index 1f78cd3..490811d 100644
--- a/unittests/ADT/APIntTest.cpp
+++ b/unittests/ADT/APIntTest.cpp
@@ -237,6 +237,24 @@ TEST(APIntTest, fromString) {
EXPECT_EQ(APInt(32, uint64_t(-16LL)), APInt(32, "-10", 16));
EXPECT_EQ(APInt(32, uint64_t(-31LL)), APInt(32, "-1F", 16));
EXPECT_EQ(APInt(32, uint64_t(-32LL)), APInt(32, "-20", 16));
+
+ EXPECT_EQ(APInt(32, 0), APInt(32, "0", 36));
+ EXPECT_EQ(APInt(32, 1), APInt(32, "1", 36));
+ EXPECT_EQ(APInt(32, 35), APInt(32, "Z", 36));
+ EXPECT_EQ(APInt(32, 36), APInt(32, "10", 36));
+ EXPECT_EQ(APInt(32, 71), APInt(32, "1Z", 36));
+ EXPECT_EQ(APInt(32, 72), APInt(32, "20", 36));
+
+ EXPECT_EQ(APInt(32, uint64_t(-0LL)), APInt(32, "-0", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-1LL)), APInt(32, "-1", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-35LL)), APInt(32, "-Z", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-36LL)), APInt(32, "-10", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-71LL)), APInt(32, "-1Z", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-72LL)), APInt(32, "-20", 36));
+}
+
+TEST(APIntTest, FromArray) {
+ EXPECT_EQ(APInt(32, uint64_t(1)), APInt(32, ArrayRef<uint64_t>(1)));
}
TEST(APIntTest, StringBitsNeeded2) {
@@ -336,6 +354,9 @@ TEST(APIntTest, toString) {
APInt(8, 0).toString(S, 16, true, true);
EXPECT_EQ(S.str().str(), "0x0");
S.clear();
+ APInt(8, 0).toString(S, 36, true, true);
+ EXPECT_EQ(S.str().str(), "0");
+ S.clear();
isSigned = false;
APInt(8, 255, isSigned).toString(S, 2, isSigned, true);
@@ -350,6 +371,9 @@ TEST(APIntTest, toString) {
APInt(8, 255, isSigned).toString(S, 16, isSigned, true);
EXPECT_EQ(S.str().str(), "0xFF");
S.clear();
+ APInt(8, 255, isSigned).toString(S, 36, isSigned, true);
+ EXPECT_EQ(S.str().str(), "73");
+ S.clear();
isSigned = true;
APInt(8, 255, isSigned).toString(S, 2, isSigned, true);
@@ -364,6 +388,9 @@ TEST(APIntTest, toString) {
APInt(8, 255, isSigned).toString(S, 16, isSigned, true);
EXPECT_EQ(S.str().str(), "-0x1");
S.clear();
+ APInt(8, 255, isSigned).toString(S, 36, isSigned, true);
+ EXPECT_EQ(S.str().str(), "-1");
+ S.clear();
}
TEST(APIntTest, Log2) {
@@ -403,7 +430,7 @@ TEST(APIntTest, magicu) {
TEST(APIntTest, StringDeath) {
EXPECT_DEATH(APInt(0, "", 0), "Bitwidth too small");
EXPECT_DEATH(APInt(32, "", 0), "Invalid string length");
- EXPECT_DEATH(APInt(32, "0", 0), "Radix should be 2, 8, 10, or 16!");
+ EXPECT_DEATH(APInt(32, "0", 0), "Radix should be 2, 8, 10, 16, or 36!");
EXPECT_DEATH(APInt(32, "", 10), "Invalid string length");
EXPECT_DEATH(APInt(32, "-", 10), "String is only a sign, needs a value.");
EXPECT_DEATH(APInt(1, "1234", 10), "Insufficient bit width");
@@ -414,4 +441,13 @@ TEST(APIntTest, StringDeath) {
#endif
#endif
+TEST(APIntTest, mul_clear) {
+ APInt ValA(65, -1ULL);
+ APInt ValB(65, 4);
+ APInt ValC(65, 0);
+ ValC = ValA * ValB;
+ ValA *= ValB;
+ EXPECT_EQ(ValA.toString(10, false), ValC.toString(10, false));
+}
+
}
diff --git a/unittests/ADT/DAGDeltaAlgorithmTest.cpp b/unittests/ADT/DAGDeltaAlgorithmTest.cpp
index b90e0c7..370b7c2 100644
--- a/unittests/ADT/DAGDeltaAlgorithmTest.cpp
+++ b/unittests/ADT/DAGDeltaAlgorithmTest.cpp
@@ -13,23 +13,6 @@
#include <cstdarg>
using namespace llvm;
-namespace std {
-
-static std::ostream &operator<<(std::ostream &OS,
- const std::set<unsigned> &S) {
- OS << "{";
- for (std::set<unsigned>::const_iterator it = S.begin(),
- ie = S.end(); it != ie; ++it) {
- if (it != S.begin())
- OS << ",";
- OS << *it;
- }
- OS << "}";
- return OS;
-}
-
-}
-
namespace {
typedef DAGDeltaAlgorithm::edge_ty edge_ty;
diff --git a/unittests/ADT/SCCIteratorTest.cpp b/unittests/ADT/SCCIteratorTest.cpp
new file mode 100644
index 0000000..00fa066
--- /dev/null
+++ b/unittests/ADT/SCCIteratorTest.cpp
@@ -0,0 +1,346 @@
+//===----- llvm/unittest/ADT/SCCIteratorTest.cpp - SCCIterator tests ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <limits.h>
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/SCCIterator.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace llvm {
+
+/// Graph<N> - A graph with N nodes. Note that N can be at most 8.
+template <unsigned N>
+class Graph {
+private:
+ // Disable copying.
+ Graph(const Graph&);
+ Graph& operator=(const Graph&);
+
+ static void ValidateIndex(unsigned Idx) {
+ assert(Idx < N && "Invalid node index!");
+ }
+public:
+
+ /// NodeSubset - A subset of the graph's nodes.
+ class NodeSubset {
+ typedef unsigned char BitVector; // Where the limitation N <= 8 comes from.
+ BitVector Elements;
+ NodeSubset(BitVector e) : Elements(e) {}
+ public:
+ /// NodeSubset - Default constructor, creates an empty subset.
+ NodeSubset() : Elements(0) {
+ assert(N <= sizeof(BitVector)*CHAR_BIT && "Graph too big!");
+ }
+ /// NodeSubset - Copy constructor.
+ NodeSubset(const NodeSubset &other) : Elements(other.Elements) {}
+
+ /// Comparison operators.
+ bool operator==(const NodeSubset &other) const {
+ return other.Elements == this->Elements;
+ }
+ bool operator!=(const NodeSubset &other) const {
+ return !(*this == other);
+ }
+
+ /// AddNode - Add the node with the given index to the subset.
+ void AddNode(unsigned Idx) {
+ ValidateIndex(Idx);
+ Elements |= 1U << Idx;
+ }
+
+ /// DeleteNode - Remove the node with the given index from the subset.
+ void DeleteNode(unsigned Idx) {
+ ValidateIndex(Idx);
+ Elements &= ~(1U << Idx);
+ }
+
+ /// count - Return true if the node with the given index is in the subset.
+ bool count(unsigned Idx) {
+ ValidateIndex(Idx);
+ return (Elements & (1U << Idx)) != 0;
+ }
+
+ /// isEmpty - Return true if this is the empty set.
+ bool isEmpty() const {
+ return Elements == 0;
+ }
+
+ /// isSubsetOf - Return true if this set is a subset of the given one.
+ bool isSubsetOf(const NodeSubset &other) const {
+ return (this->Elements | other.Elements) == other.Elements;
+ }
+
+ /// Complement - Return the complement of this subset.
+ NodeSubset Complement() const {
+ return ~(unsigned)this->Elements & ((1U << N) - 1);
+ }
+
+ /// Join - Return the union of this subset and the given one.
+ NodeSubset Join(const NodeSubset &other) const {
+ return this->Elements | other.Elements;
+ }
+
+ /// Meet - Return the intersection of this subset and the given one.
+ NodeSubset Meet(const NodeSubset &other) const {
+ return this->Elements & other.Elements;
+ }
+ };
+
+ /// NodeType - Node index and set of children of the node.
+ typedef std::pair<unsigned, NodeSubset> NodeType;
+
+private:
+ /// Nodes - The list of nodes for this graph.
+ NodeType Nodes[N];
+public:
+
+ /// Graph - Default constructor. Creates an empty graph.
+ Graph() {
+ // Let each node know which node it is. This allows us to find the start of
+ // the Nodes array given a pointer to any element of it.
+ for (unsigned i = 0; i != N; ++i)
+ Nodes[i].first = i;
+ }
+
+ /// AddEdge - Add an edge from the node with index FromIdx to the node with
+ /// index ToIdx.
+ void AddEdge(unsigned FromIdx, unsigned ToIdx) {
+ ValidateIndex(FromIdx);
+ Nodes[FromIdx].second.AddNode(ToIdx);
+ }
+
+ /// DeleteEdge - Remove the edge (if any) from the node with index FromIdx to
+ /// the node with index ToIdx.
+ void DeleteEdge(unsigned FromIdx, unsigned ToIdx) {
+ ValidateIndex(FromIdx);
+ Nodes[FromIdx].second.DeleteNode(ToIdx);
+ }
+
+ /// AccessNode - Get a pointer to the node with the given index.
+ NodeType *AccessNode(unsigned Idx) const {
+ ValidateIndex(Idx);
+ // The constant cast is needed when working with GraphTraits, which insists
+ // on taking a constant Graph.
+ return const_cast<NodeType *>(&Nodes[Idx]);
+ }
+
+ /// NodesReachableFrom - Return the set of all nodes reachable from the given
+ /// node.
+ NodeSubset NodesReachableFrom(unsigned Idx) const {
+ // This algorithm doesn't scale, but that doesn't matter given the small
+ // size of our graphs.
+ NodeSubset Reachable;
+
+ // The initial node is reachable.
+ Reachable.AddNode(Idx);
+ do {
+ NodeSubset Previous(Reachable);
+
+ // Add in all nodes which are children of a reachable node.
+ for (unsigned i = 0; i != N; ++i)
+ if (Previous.count(i))
+ Reachable = Reachable.Join(Nodes[i].second);
+
+ // If nothing changed then we have found all reachable nodes.
+ if (Reachable == Previous)
+ return Reachable;
+
+ // Rinse and repeat.
+ } while (1);
+ }
+
+ /// ChildIterator - Visit all children of a node.
+ class ChildIterator {
+ friend class Graph;
+
+ /// FirstNode - Pointer to first node in the graph's Nodes array.
+ NodeType *FirstNode;
+ /// Children - Set of nodes which are children of this one and that haven't
+ /// yet been visited.
+ NodeSubset Children;
+
+ ChildIterator(); // Disable default constructor.
+ protected:
+ ChildIterator(NodeType *F, NodeSubset C) : FirstNode(F), Children(C) {}
+
+ public:
+ /// ChildIterator - Copy constructor.
+ ChildIterator(const ChildIterator& other) : FirstNode(other.FirstNode),
+ Children(other.Children) {}
+
+ /// Comparison operators.
+ bool operator==(const ChildIterator &other) const {
+ return other.FirstNode == this->FirstNode &&
+ other.Children == this->Children;
+ }
+ bool operator!=(const ChildIterator &other) const {
+ return !(*this == other);
+ }
+
+ /// Prefix increment operator.
+ ChildIterator& operator++() {
+ // Find the next unvisited child node.
+ for (unsigned i = 0; i != N; ++i)
+ if (Children.count(i)) {
+ // Remove that child - it has been visited. This is the increment!
+ Children.DeleteNode(i);
+ return *this;
+ }
+ assert(false && "Incrementing end iterator!");
+ return *this; // Avoid compiler warnings.
+ }
+
+ /// Postfix increment operator.
+ ChildIterator operator++(int) {
+ ChildIterator Result(*this);
+ ++(*this);
+ return Result;
+ }
+
+ /// Dereference operator.
+ NodeType *operator*() {
+ // Find the next unvisited child node.
+ for (unsigned i = 0; i != N; ++i)
+ if (Children.count(i))
+ // Return a pointer to it.
+ return FirstNode + i;
+ assert(false && "Dereferencing end iterator!");
+ return 0; // Avoid compiler warning.
+ }
+ };
+
+ /// child_begin - Return an iterator pointing to the first child of the given
+ /// node.
+ static ChildIterator child_begin(NodeType *Parent) {
+ return ChildIterator(Parent - Parent->first, Parent->second);
+ }
+
+ /// child_end - Return the end iterator for children of the given node.
+ static ChildIterator child_end(NodeType *Parent) {
+ return ChildIterator(Parent - Parent->first, NodeSubset());
+ }
+};
+
+template <unsigned N>
+struct GraphTraits<Graph<N> > {
+ typedef typename Graph<N>::NodeType NodeType;
+ typedef typename Graph<N>::ChildIterator ChildIteratorType;
+
+ static inline NodeType *getEntryNode(const Graph<N> &G) { return G.AccessNode(0); }
+ static inline ChildIteratorType child_begin(NodeType *Node) {
+ return Graph<N>::child_begin(Node);
+ }
+ static inline ChildIteratorType child_end(NodeType *Node) {
+ return Graph<N>::child_end(Node);
+ }
+};
+
+TEST(SCCIteratorTest, AllSmallGraphs) {
+ // Test SCC computation against every graph with NUM_NODES nodes or less.
+ // Since SCC considers every node to have an implicit self-edge, we only
+ // create graphs for which every node has a self-edge.
+#define NUM_NODES 4
+#define NUM_GRAPHS (NUM_NODES * (NUM_NODES - 1))
+ typedef Graph<NUM_NODES> GT;
+
+ /// Enumerate all graphs using NUM_GRAPHS bits.
+ assert(NUM_GRAPHS < sizeof(unsigned) * CHAR_BIT && "Too many graphs!");
+ for (unsigned GraphDescriptor = 0; GraphDescriptor < (1U << NUM_GRAPHS);
+ ++GraphDescriptor) {
+ GT G;
+
+ // Add edges as specified by the descriptor.
+ unsigned DescriptorCopy = GraphDescriptor;
+ for (unsigned i = 0; i != NUM_NODES; ++i)
+ for (unsigned j = 0; j != NUM_NODES; ++j) {
+ // Always add a self-edge.
+ if (i == j) {
+ G.AddEdge(i, j);
+ continue;
+ }
+ if (DescriptorCopy & 1)
+ G.AddEdge(i, j);
+ DescriptorCopy >>= 1;
+ }
+
+ // Test the SCC logic on this graph.
+
+ /// NodesInSomeSCC - Those nodes which are in some SCC.
+ GT::NodeSubset NodesInSomeSCC;
+
+ for (scc_iterator<GT> I = scc_begin(G), E = scc_end(G); I != E; ++I) {
+ std::vector<GT::NodeType*> &SCC = *I;
+
+ // Get the nodes in this SCC as a NodeSubset rather than a vector.
+ GT::NodeSubset NodesInThisSCC;
+ for (unsigned i = 0, e = SCC.size(); i != e; ++i)
+ NodesInThisSCC.AddNode(SCC[i]->first);
+
+ // There should be at least one node in every SCC.
+ EXPECT_FALSE(NodesInThisSCC.isEmpty());
+
+ // Check that every node in the SCC is reachable from every other node in
+ // the SCC.
+ for (unsigned i = 0; i != NUM_NODES; ++i)
+ if (NodesInThisSCC.count(i))
+ EXPECT_TRUE(NodesInThisSCC.isSubsetOf(G.NodesReachableFrom(i)));
+
+ // OK, now that we now that every node in the SCC is reachable from every
+ // other, this means that the set of nodes reachable from any node in the
+ // SCC is the same as the set of nodes reachable from every node in the
+ // SCC. Check that for every node N not in the SCC but reachable from the
+ // SCC, no element of the SCC is reachable from N.
+ for (unsigned i = 0; i != NUM_NODES; ++i)
+ if (NodesInThisSCC.count(i)) {
+ GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i);
+ GT::NodeSubset ReachableButNotInSCC =
+ NodesReachableFromSCC.Meet(NodesInThisSCC.Complement());
+
+ for (unsigned j = 0; j != NUM_NODES; ++j)
+ if (ReachableButNotInSCC.count(j))
+ EXPECT_TRUE(G.NodesReachableFrom(j).Meet(NodesInThisSCC).isEmpty());
+
+ // The result must be the same for all other nodes in this SCC, so
+ // there is no point in checking them.
+ break;
+ }
+
+ // This is indeed a SCC: a maximal set of nodes for which each node is
+ // reachable from every other.
+
+ // Check that we didn't already see this SCC.
+ EXPECT_TRUE(NodesInSomeSCC.Meet(NodesInThisSCC).isEmpty());
+
+ NodesInSomeSCC = NodesInSomeSCC.Join(NodesInThisSCC);
+
+ // Check a property that is specific to the LLVM SCC iterator and
+ // guaranteed by it: if a node in SCC S1 has an edge to a node in
+ // SCC S2, then S1 is visited *after* S2. This means that the set
+ // of nodes reachable from this SCC must be contained either in the
+ // union of this SCC and all previously visited SCC's.
+
+ for (unsigned i = 0; i != NUM_NODES; ++i)
+ if (NodesInThisSCC.count(i)) {
+ GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i);
+ EXPECT_TRUE(NodesReachableFromSCC.isSubsetOf(NodesInSomeSCC));
+ // The result must be the same for all other nodes in this SCC, so
+ // there is no point in checking them.
+ break;
+ }
+ }
+
+ // Finally, check that the nodes in some SCC are exactly those that are
+ // reachable from the initial node.
+ EXPECT_EQ(NodesInSomeSCC, G.NodesReachableFrom(0));
+ }
+}
+
+}
diff --git a/unittests/ADT/SmallVectorTest.cpp b/unittests/ADT/SmallVectorTest.cpp
index 0d3535d..d5bfe76 100644
--- a/unittests/ADT/SmallVectorTest.cpp
+++ b/unittests/ADT/SmallVectorTest.cpp
@@ -383,7 +383,7 @@ TEST_F(SmallVectorTest, ComparisonTest) {
// Constant vector tests.
TEST_F(SmallVectorTest, ConstVectorTest) {
- const VectorType constVector;
+ VectorType constVector;
EXPECT_EQ(0u, constVector.size());
EXPECT_TRUE(constVector.empty());
diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp
index 5731e4a..8364eac 100644
--- a/unittests/ADT/StringRefTest.cpp
+++ b/unittests/ADT/StringRefTest.cpp
@@ -73,6 +73,12 @@ TEST(StringRefTest, StringOps) {
EXPECT_EQ( 1, StringRef("2").compare_numeric("1"));
EXPECT_EQ( 0, StringRef("llvm_v1i64_ty").compare_numeric("llvm_v1i64_ty"));
EXPECT_EQ( 1, StringRef("\xFF").compare_numeric("\1"));
+ EXPECT_EQ( 1, StringRef("V16").compare_numeric("V1_q0"));
+ EXPECT_EQ(-1, StringRef("V1_q0").compare_numeric("V16"));
+ EXPECT_EQ(-1, StringRef("V8_q0").compare_numeric("V16"));
+ EXPECT_EQ( 1, StringRef("V16").compare_numeric("V8_q0"));
+ EXPECT_EQ(-1, StringRef("V1_q0").compare_numeric("V8_q0"));
+ EXPECT_EQ( 1, StringRef("V8_q0").compare_numeric("V1_q0"));
}
TEST(StringRefTest, Operators) {
diff --git a/unittests/ADT/TwineTest.cpp b/unittests/ADT/TwineTest.cpp
index 57f54cb..e9cc41d 100644
--- a/unittests/ADT/TwineTest.cpp
+++ b/unittests/ADT/TwineTest.cpp
@@ -37,12 +37,16 @@ TEST(TwineTest, Numbers) {
EXPECT_EQ("-123", Twine(-123).str());
EXPECT_EQ("123", Twine(123).str());
EXPECT_EQ("-123", Twine(-123).str());
- EXPECT_EQ("123", Twine((char) 123).str());
- EXPECT_EQ("-123", Twine((signed char) -123).str());
EXPECT_EQ("7b", Twine::utohexstr(123).str());
}
+TEST(TwineTest, Characters) {
+ EXPECT_EQ("x", Twine('x').str());
+ EXPECT_EQ("x", Twine(static_cast<unsigned char>('x')).str());
+ EXPECT_EQ("x", Twine(static_cast<signed char>('x')).str());
+}
+
TEST(TwineTest, Concat) {
// Check verse repr, since we care about the actual representation not just
// the result.
diff --git a/unittests/Analysis/ScalarEvolutionTest.cpp b/unittests/Analysis/ScalarEvolutionTest.cpp
index 39ced2a..ea5aeb3 100644
--- a/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -8,35 +8,48 @@
//===----------------------------------------------------------------------===//
#include <llvm/Analysis/ScalarEvolutionExpressions.h>
+#include <llvm/Analysis/LoopInfo.h>
#include <llvm/GlobalVariable.h>
#include <llvm/Constants.h>
#include <llvm/LLVMContext.h>
#include <llvm/Module.h>
#include <llvm/PassManager.h>
+#include <llvm/ADT/SmallVector.h>
#include "gtest/gtest.h"
namespace llvm {
namespace {
-TEST(ScalarEvolutionsTest, SCEVUnknownRAUW) {
+// We use this fixture to ensure that we clean up ScalarEvolution before
+// deleting the PassManager.
+class ScalarEvolutionsTest : public testing::Test {
+protected:
+ ScalarEvolutionsTest() : M("", Context), SE(*new ScalarEvolution) {}
+ ~ScalarEvolutionsTest() {
+ // Manually clean up, since we allocated new SCEV objects after the
+ // pass was finished.
+ SE.releaseMemory();
+ }
LLVMContext Context;
- Module M("world", Context);
+ Module M;
+ PassManager PM;
+ ScalarEvolution &SE;
+};
- const FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context),
+TEST_F(ScalarEvolutionsTest, SCEVUnknownRAUW) {
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context),
std::vector<Type *>(), false);
Function *F = cast<Function>(M.getOrInsertFunction("f", FTy));
BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
ReturnInst::Create(Context, 0, BB);
- const Type *Ty = Type::getInt1Ty(Context);
+ Type *Ty = Type::getInt1Ty(Context);
Constant *Init = Constant::getNullValue(Ty);
Value *V0 = new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, Init, "V0");
Value *V1 = new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, Init, "V1");
Value *V2 = new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, Init, "V2");
// Create a ScalarEvolution and "run" it so that it gets initialized.
- PassManager PM;
- ScalarEvolution &SE = *new ScalarEvolution();
PM.add(&SE);
PM.run(M);
@@ -72,10 +85,149 @@ TEST(ScalarEvolutionsTest, SCEVUnknownRAUW) {
EXPECT_EQ(cast<SCEVUnknown>(M0->getOperand(1))->getValue(), V0);
EXPECT_EQ(cast<SCEVUnknown>(M1->getOperand(1))->getValue(), V0);
EXPECT_EQ(cast<SCEVUnknown>(M2->getOperand(1))->getValue(), V0);
+}
+
+TEST_F(ScalarEvolutionsTest, SCEVMultiplyAddRecs) {
+ Type *Ty = Type::getInt32Ty(Context);
+ SmallVector<Type *, 10> Types;
+ Types.append(10, Ty);
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), Types, false);
+ Function *F = cast<Function>(M.getOrInsertFunction("f", FTy));
+ BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
+ ReturnInst::Create(Context, 0, BB);
+
+ // Create a ScalarEvolution and "run" it so that it gets initialized.
+ PM.add(&SE);
+ PM.run(M);
+
+ // It's possible to produce an empty loop through the default constructor,
+ // but you can't add any blocks to it without a LoopInfo pass.
+ Loop L;
+ const_cast<std::vector<BasicBlock*>&>(L.getBlocks()).push_back(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ SmallVector<const SCEV *, 5> A;
+ A.push_back(SE.getSCEV(&*AI++));
+ A.push_back(SE.getSCEV(&*AI++));
+ A.push_back(SE.getSCEV(&*AI++));
+ A.push_back(SE.getSCEV(&*AI++));
+ A.push_back(SE.getSCEV(&*AI++));
+ const SCEV *A_rec = SE.getAddRecExpr(A, &L, SCEV::FlagAnyWrap);
+
+ SmallVector<const SCEV *, 5> B;
+ B.push_back(SE.getSCEV(&*AI++));
+ B.push_back(SE.getSCEV(&*AI++));
+ B.push_back(SE.getSCEV(&*AI++));
+ B.push_back(SE.getSCEV(&*AI++));
+ B.push_back(SE.getSCEV(&*AI++));
+ const SCEV *B_rec = SE.getAddRecExpr(B, &L, SCEV::FlagAnyWrap);
+
+ /* Spot check that we perform this transformation:
+ {A0,+,A1,+,A2,+,A3,+,A4} * {B0,+,B1,+,B2,+,B3,+,B4} =
+ {A0*B0,+,
+ A1*B0 + A0*B1 + A1*B1,+,
+ A2*B0 + 2A1*B1 + A0*B2 + 2A2*B1 + 2A1*B2 + A2*B2,+,
+ A3*B0 + 3A2*B1 + 3A1*B2 + A0*B3 + 3A3*B1 + 6A2*B2 + 3A1*B3 + 3A3*B2 +
+ 3A2*B3 + A3*B3,+,
+ A4*B0 + 4A3*B1 + 6A2*B2 + 4A1*B3 + A0*B4 + 4A4*B1 + 12A3*B2 + 12A2*B3 +
+ 4A1*B4 + 6A4*B2 + 12A3*B3 + 6A2*B4 + 4A4*B3 + 4A3*B4 + A4*B4,+,
+ 5A4*B1 + 10A3*B2 + 10A2*B3 + 5A1*B4 + 20A4*B2 + 30A3*B3 + 20A2*B4 +
+ 30A4*B3 + 30A3*B4 + 20A4*B4,+,
+ 15A4*B2 + 20A3*B3 + 15A2*B4 + 60A4*B3 + 60A3*B4 + 90A4*B4,+,
+ 35A4*B3 + 35A3*B4 + 140A4*B4,+,
+ 70A4*B4}
+ */
+
+ const SCEVAddRecExpr *Product =
+ dyn_cast<SCEVAddRecExpr>(SE.getMulExpr(A_rec, B_rec));
+ ASSERT_TRUE(Product);
+ ASSERT_EQ(Product->getNumOperands(), 9u);
+
+ SmallVector<const SCEV *, 16> Sum;
+ Sum.push_back(SE.getMulExpr(A[0], B[0]));
+ EXPECT_EQ(Product->getOperand(0), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ // SCEV produces different an equal but different expression for these.
+ // Re-enable when PR11052 is fixed.
+#if 0
+ Sum.push_back(SE.getMulExpr(A[1], B[0]));
+ Sum.push_back(SE.getMulExpr(A[0], B[1]));
+ Sum.push_back(SE.getMulExpr(A[1], B[1]));
+ EXPECT_EQ(Product->getOperand(1), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(A[2], B[0]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 2), A[1], B[1]));
+ Sum.push_back(SE.getMulExpr(A[0], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 2), A[2], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 2), A[1], B[2]));
+ Sum.push_back(SE.getMulExpr(A[2], B[2]));
+ EXPECT_EQ(Product->getOperand(2), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(A[3], B[0]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[2], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[1], B[2]));
+ Sum.push_back(SE.getMulExpr(A[0], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[3], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 6), A[2], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[1], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[3], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[2], B[3]));
+ Sum.push_back(SE.getMulExpr(A[3], B[3]));
+ EXPECT_EQ(Product->getOperand(3), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(A[4], B[0]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[3], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 6), A[2], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[1], B[3]));
+ Sum.push_back(SE.getMulExpr(A[0], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[4], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 12), A[3], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 12), A[2], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[1], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 6), A[4], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 12), A[3], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 6), A[2], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[4], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[3], B[4]));
+ Sum.push_back(SE.getMulExpr(A[4], B[4]));
+ EXPECT_EQ(Product->getOperand(4), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 5), A[4], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 10), A[3], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 10), A[2], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 5), A[1], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 20), A[4], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 30), A[3], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 20), A[2], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 30), A[4], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 30), A[3], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 20), A[4], B[4]));
+ EXPECT_EQ(Product->getOperand(5), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 15), A[4], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 20), A[3], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 15), A[2], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 60), A[4], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 60), A[3], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 90), A[4], B[4]));
+ EXPECT_EQ(Product->getOperand(6), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 35), A[4], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 35), A[3], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 140), A[4], B[4]));
+ EXPECT_EQ(Product->getOperand(7), SE.getAddExpr(Sum));
+ Sum.clear();
+#endif
- // Manually clean up, since we allocated new SCEV objects after the
- // pass was finished.
- SE.releaseMemory();
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 70), A[4], B[4]));
+ EXPECT_EQ(Product->getOperand(8), SE.getAddExpr(Sum));
}
} // end anonymous namespace
diff --git a/unittests/ExecutionEngine/ExecutionEngineTest.cpp b/unittests/ExecutionEngine/ExecutionEngineTest.cpp
index 904ee2b..4dcef20 100644
--- a/unittests/ExecutionEngine/ExecutionEngineTest.cpp
+++ b/unittests/ExecutionEngine/ExecutionEngineTest.cpp
@@ -30,7 +30,7 @@ protected:
ASSERT_TRUE(Engine.get() != NULL);
}
- GlobalVariable *NewExtGlobal(const Type *T, const Twine &Name) {
+ GlobalVariable *NewExtGlobal(Type *T, const Twine &Name) {
return new GlobalVariable(*M, T, false, // Not constant.
GlobalValue::ExternalLinkage, NULL, Name);
}
diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp
index a36ec3b..f8d8830 100644
--- a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp
+++ b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp
@@ -16,7 +16,7 @@
#include "llvm/CodeGen/MachineCodeInfo.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/TypeBuilder.h"
-#include "llvm/Target/TargetSelect.h"
+#include "llvm/Support/TargetSelect.h"
#include "gtest/gtest.h"
#include <vector>
@@ -45,7 +45,7 @@ struct RecordingJITEventListener : public JITEventListener {
std::vector<FunctionEmittedEvent> EmittedEvents;
std::vector<FunctionFreedEvent> FreedEvents;
- int NextIndex;
+ unsigned NextIndex;
RecordingJITEventListener() : NextIndex(0) {}
diff --git a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp
index 039b5e0..be5d152 100644
--- a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp
+++ b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp
@@ -22,7 +22,7 @@ namespace {
Function *makeFakeFunction() {
std::vector<Type*> params;
- const FunctionType *FTy =
+ FunctionType *FTy =
FunctionType::get(Type::getVoidTy(getGlobalContext()), params, false);
return Function::Create(FTy, GlobalValue::ExternalLinkage);
}
diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp
index 9c001c4..2ef2730 100644
--- a/unittests/ExecutionEngine/JIT/JITTest.cpp
+++ b/unittests/ExecutionEngine/JIT/JITTest.cpp
@@ -27,7 +27,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TypeBuilder.h"
-#include "llvm/Target/TargetSelect.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Type.h"
#include <vector>
@@ -38,13 +38,13 @@ namespace {
Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) {
std::vector<Type*> params;
- const FunctionType *FTy = FunctionType::get(G->getType()->getElementType(),
+ FunctionType *FTy = FunctionType::get(G->getType()->getElementType(),
params, false);
Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M);
BasicBlock *Entry = BasicBlock::Create(M->getContext(), "entry", F);
IRBuilder<> builder(Entry);
Value *Load = builder.CreateLoad(G);
- const Type *GTy = G->getType()->getElementType();
+ Type *GTy = G->getType()->getElementType();
Value *Add = builder.CreateAdd(Load, ConstantInt::get(GTy, 1LL));
builder.CreateStore(Add, G);
builder.CreateRet(Add);
@@ -236,7 +236,7 @@ TEST(JIT, GlobalInFunction) {
ASSERT_EQ(Error, "");
// Create a global variable.
- const Type *GTy = Type::getInt32Ty(context);
+ Type *GTy = Type::getInt32Ty(context);
GlobalVariable *G = new GlobalVariable(
*M,
GTy,
@@ -284,6 +284,8 @@ int PlusOne(int arg) {
return arg + 1;
}
+// ARM tests disabled pending fix for PR10783.
+#if !defined(__arm__)
TEST_F(JITTest, FarCallToKnownFunction) {
// x86-64 can only make direct calls to functions within 32 bits of
// the current PC. To call anything farther away, we have to load
@@ -320,11 +322,11 @@ TEST_F(JITTest, FarCallToKnownFunction) {
TEST_F(JITTest, NonLazyCompilationStillNeedsStubs) {
TheJIT->DisableLazyCompilation(true);
- const FunctionType *Func1Ty =
+ FunctionType *Func1Ty =
cast<FunctionType>(TypeBuilder<void(void), false>::get(Context));
std::vector<Type*> arg_types;
arg_types.push_back(Type::getInt1Ty(Context));
- const FunctionType *FuncTy = FunctionType::get(
+ FunctionType *FuncTy = FunctionType::get(
Type::getVoidTy(Context), arg_types, false);
Function *Func1 = Function::Create(Func1Ty, Function::ExternalLinkage,
"func1", M);
@@ -377,7 +379,7 @@ TEST_F(JITTest, NonLazyLeaksNoStubs) {
TheJIT->DisableLazyCompilation(true);
// Create two functions with a single basic block each.
- const FunctionType *FuncTy =
+ FunctionType *FuncTy =
cast<FunctionType>(TypeBuilder<int(), false>::get(Context));
Function *Func1 = Function::Create(FuncTy, Function::ExternalLinkage,
"func1", M);
@@ -461,6 +463,7 @@ TEST_F(JITTest, ModuleDeletion) {
EXPECT_EQ(RJMM->startExceptionTableCalls.size(),
NumTablesDeallocated);
}
+#endif // !defined(__arm__)
// ARM and PPC still emit stubs for calls since the target may be too far away
// to call directly. This #if can probably be removed when
@@ -608,6 +611,8 @@ extern "C" int32_t JITTest_AvailableExternallyFunction() {
}
namespace {
+// ARM tests disabled pending fix for PR10783.
+#if !defined(__arm__)
TEST_F(JITTest, AvailableExternallyFunctionIsntCompiled) {
TheJIT->DisableLazyCompilation(true);
LoadAssembly("define available_externally i32 "
@@ -763,6 +768,7 @@ TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) {
(intptr_t)TheJIT->getPointerToFunction(recur1IR));
EXPECT_EQ(3, recur1(4));
}
+#endif // !defined(__arm__)
// This code is copied from JITEventListenerTest, but it only runs once for all
// the tests in this directory. Everything seems fine, but that's strange
diff --git a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp
index 8997d39..91ea64a 100644
--- a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp
+++ b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp
@@ -65,6 +65,9 @@ void createModule2(LLVMContext &Context2, Module *&M2, Function *&FooF2) {
FooF2 = M2->getFunction("foo2");
}
+// ARM tests disabled pending fix for PR10783.
+#if !defined(__arm__)
+
TEST(MultiJitTest, EagerMode) {
LLVMContext Context1;
Module *M1 = 0;
@@ -160,5 +163,6 @@ TEST(MultiJitTest, JitPool) {
EXPECT_EQ((intptr_t)getPointerToNamedFunction("getPointerToNamedFunction"),
(intptr_t)&getPointerToNamedFunction);
}
+#endif // !defined(__arm__)
} // anonymous namespace
diff --git a/unittests/Support/BlockFrequencyTest.cpp b/unittests/Support/BlockFrequencyTest.cpp
new file mode 100644
index 0000000..edeea9b
--- /dev/null
+++ b/unittests/Support/BlockFrequencyTest.cpp
@@ -0,0 +1,56 @@
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/BlockFrequency.h"
+#include "llvm/Support/BranchProbability.h"
+
+#include "gtest/gtest.h"
+#include <climits>
+
+using namespace llvm;
+
+namespace {
+
+TEST(BlockFrequencyTest, OneToZero) {
+ BlockFrequency Freq(1);
+ BranchProbability Prob(UINT32_MAX - 1, UINT32_MAX);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 0u);
+}
+
+TEST(BlockFrequencyTest, OneToOne) {
+ BlockFrequency Freq(1);
+ BranchProbability Prob(UINT32_MAX, UINT32_MAX);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 1u);
+}
+
+TEST(BlockFrequencyTest, ThreeToOne) {
+ BlockFrequency Freq(3);
+ BranchProbability Prob(3000000, 9000000);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 1u);
+}
+
+TEST(BlockFrequencyTest, MaxToHalfMax) {
+ BlockFrequency Freq(UINT64_MAX);
+ BranchProbability Prob(UINT32_MAX / 2, UINT32_MAX);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 9223372034707292159LLu);
+}
+
+TEST(BlockFrequencyTest, BigToBig) {
+ const uint64_t Big = 387246523487234346LL;
+ const uint32_t P = 123456789;
+ BlockFrequency Freq(Big);
+ BranchProbability Prob(P, P);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), Big);
+}
+
+TEST(BlockFrequencyTest, MaxToMax) {
+ BlockFrequency Freq(UINT64_MAX);
+ BranchProbability Prob(UINT32_MAX, UINT32_MAX);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
+}
+
+}
diff --git a/unittests/Support/DataExtractorTest.cpp b/unittests/Support/DataExtractorTest.cpp
new file mode 100644
index 0000000..9813e46
--- /dev/null
+++ b/unittests/Support/DataExtractorTest.cpp
@@ -0,0 +1,111 @@
+//===- llvm/unittest/Support/DataExtractorTest.cpp - DataExtractor tests --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/Support/DataExtractor.h"
+using namespace llvm;
+
+namespace {
+
+const char numberData[] = "\x80\x90\xFF\xFF\x80\x00\x00\x00";
+const char stringData[] = "hellohello\0hello";
+const char leb128data[] = "\xA6\x49";
+
+TEST(DataExtractorTest, OffsetOverflow) {
+ DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8);
+ EXPECT_FALSE(DE.isValidOffsetForDataOfSize(-2U, 5));
+}
+
+TEST(DataExtractorTest, UnsignedNumbers) {
+ DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8);
+ uint32_t offset = 0;
+
+ EXPECT_EQ(0x80U, DE.getU8(&offset));
+ EXPECT_EQ(1U, offset);
+ offset = 0;
+ EXPECT_EQ(0x8090U, DE.getU16(&offset));
+ EXPECT_EQ(2U, offset);
+ offset = 0;
+ EXPECT_EQ(0x8090FFFFU, DE.getU32(&offset));
+ EXPECT_EQ(4U, offset);
+ offset = 0;
+ EXPECT_EQ(0x8090FFFF80000000ULL, DE.getU64(&offset));
+ EXPECT_EQ(8U, offset);
+ offset = 0;
+ EXPECT_EQ(0x8090FFFF80000000ULL, DE.getAddress(&offset));
+ EXPECT_EQ(8U, offset);
+ offset = 0;
+
+ uint32_t data[2];
+ EXPECT_EQ(data, DE.getU32(&offset, data, 2));
+ EXPECT_EQ(0x8090FFFFU, data[0]);
+ EXPECT_EQ(0x80000000U, data[1]);
+ EXPECT_EQ(8U, offset);
+ offset = 0;
+
+ // Now for little endian.
+ DE = DataExtractor(StringRef(numberData, sizeof(numberData)-1), true, 4);
+ EXPECT_EQ(0x9080U, DE.getU16(&offset));
+ EXPECT_EQ(2U, offset);
+ offset = 0;
+ EXPECT_EQ(0xFFFF9080U, DE.getU32(&offset));
+ EXPECT_EQ(4U, offset);
+ offset = 0;
+ EXPECT_EQ(0x80FFFF9080ULL, DE.getU64(&offset));
+ EXPECT_EQ(8U, offset);
+ offset = 0;
+ EXPECT_EQ(0xFFFF9080U, DE.getAddress(&offset));
+ EXPECT_EQ(4U, offset);
+ offset = 0;
+
+ EXPECT_EQ(data, DE.getU32(&offset, data, 2));
+ EXPECT_EQ(0xFFFF9080U, data[0]);
+ EXPECT_EQ(0x80U, data[1]);
+ EXPECT_EQ(8U, offset);
+}
+
+TEST(DataExtractorTest, SignedNumbers) {
+ DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8);
+ uint32_t offset = 0;
+
+ EXPECT_EQ(-128, DE.getSigned(&offset, 1));
+ EXPECT_EQ(1U, offset);
+ offset = 0;
+ EXPECT_EQ(-32624, DE.getSigned(&offset, 2));
+ EXPECT_EQ(2U, offset);
+ offset = 0;
+ EXPECT_EQ(-2137980929, DE.getSigned(&offset, 4));
+ EXPECT_EQ(4U, offset);
+ offset = 0;
+ EXPECT_EQ(-9182558167379214336LL, DE.getSigned(&offset, 8));
+ EXPECT_EQ(8U, offset);
+}
+
+TEST(DataExtractorTest, Strings) {
+ DataExtractor DE(StringRef(stringData, sizeof(stringData)-1), false, 8);
+ uint32_t offset = 0;
+
+ EXPECT_EQ(stringData, DE.getCStr(&offset));
+ EXPECT_EQ(11U, offset);
+ EXPECT_EQ(NULL, DE.getCStr(&offset));
+ EXPECT_EQ(11U, offset);
+}
+
+TEST(DataExtractorTest, LEB128) {
+ DataExtractor DE(StringRef(leb128data, sizeof(leb128data)-1), false, 8);
+ uint32_t offset = 0;
+
+ EXPECT_EQ(9382ULL, DE.getULEB128(&offset));
+ EXPECT_EQ(2U, offset);
+ offset = 0;
+ EXPECT_EQ(-7002LL, DE.getSLEB128(&offset));
+ EXPECT_EQ(2U, offset);
+}
+
+}
diff --git a/unittests/Support/TypeBuilderTest.cpp b/unittests/Support/TypeBuilderTest.cpp
index 0609178..20d0e73 100644
--- a/unittests/Support/TypeBuilderTest.cpp
+++ b/unittests/Support/TypeBuilderTest.cpp
@@ -184,14 +184,14 @@ class MyPortableType {
namespace llvm {
template<bool cross> class TypeBuilder<MyType, cross> {
public:
- static const StructType *get(LLVMContext &Context) {
+ static StructType *get(LLVMContext &Context) {
// Using the static result variable ensures that the type is
// only looked up once.
std::vector<Type*> st;
st.push_back(TypeBuilder<int, cross>::get(Context));
st.push_back(TypeBuilder<int*, cross>::get(Context));
st.push_back(TypeBuilder<void*[], cross>::get(Context));
- static const StructType *const result = StructType::get(Context, st);
+ static StructType *const result = StructType::get(Context, st);
return result;
}
@@ -207,14 +207,14 @@ public:
template<bool cross> class TypeBuilder<MyPortableType, cross> {
public:
- static const StructType *get(LLVMContext &Context) {
+ static StructType *get(LLVMContext &Context) {
// Using the static result variable ensures that the type is
// only looked up once.
std::vector<Type*> st;
st.push_back(TypeBuilder<types::i<32>, cross>::get(Context));
st.push_back(TypeBuilder<types::i<32>*, cross>::get(Context));
st.push_back(TypeBuilder<types::i<8>*[], cross>::get(Context));
- static const StructType *const result = StructType::get(Context, st);
+ static StructType *const result = StructType::get(Context, st);
return result;
}
@@ -235,19 +235,19 @@ TEST(TypeBuilderTest, Extensions) {
TypeBuilder<int, false>::get(getGlobalContext()),
TypeBuilder<int*, false>::get(getGlobalContext()),
TypeBuilder<void*[], false>::get(getGlobalContext()),
- NULL)),
+ (void*)0)),
(TypeBuilder<MyType*, false>::get(getGlobalContext())));
EXPECT_EQ(PointerType::getUnqual(StructType::get(
TypeBuilder<types::i<32>, false>::get(getGlobalContext()),
TypeBuilder<types::i<32>*, false>::get(getGlobalContext()),
TypeBuilder<types::i<8>*[], false>::get(getGlobalContext()),
- NULL)),
+ (void*)0)),
(TypeBuilder<MyPortableType*, false>::get(getGlobalContext())));
EXPECT_EQ(PointerType::getUnqual(StructType::get(
TypeBuilder<types::i<32>, false>::get(getGlobalContext()),
TypeBuilder<types::i<32>*, false>::get(getGlobalContext()),
TypeBuilder<types::i<8>*[], false>::get(getGlobalContext()),
- NULL)),
+ (void*)0)),
(TypeBuilder<MyPortableType*, true>::get(getGlobalContext())));
}
diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp
index 1ce549d1..1b85869 100644
--- a/unittests/Transforms/Utils/Cloning.cpp
+++ b/unittests/Transforms/Utils/Cloning.cpp
@@ -124,7 +124,7 @@ TEST_F(CloneInstruction, Inbounds) {
Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
std::vector<Value *> ops;
ops.push_back(Z);
- GetElementPtrInst *GEP = GetElementPtrInst::Create(V, ops.begin(), ops.end());
+ GetElementPtrInst *GEP = GetElementPtrInst::Create(V, ops);
EXPECT_FALSE(this->clone(GEP)->isInBounds());
GEP->setIsInBounds();
diff --git a/unittests/VMCore/ConstantsTest.cpp b/unittests/VMCore/ConstantsTest.cpp
index 8277584..623ea0d 100644
--- a/unittests/VMCore/ConstantsTest.cpp
+++ b/unittests/VMCore/ConstantsTest.cpp
@@ -16,7 +16,7 @@ namespace llvm {
namespace {
TEST(ConstantsTest, Integer_i1) {
- const IntegerType* Int1 = IntegerType::get(getGlobalContext(), 1);
+ IntegerType* Int1 = IntegerType::get(getGlobalContext(), 1);
Constant* One = ConstantInt::get(Int1, 1, true);
Constant* Zero = ConstantInt::get(Int1, 0);
Constant* NegOne = ConstantInt::get(Int1, static_cast<uint64_t>(-1), true);
@@ -97,7 +97,7 @@ TEST(ConstantsTest, Integer_i1) {
}
TEST(ConstantsTest, IntSigns) {
- const IntegerType* Int8Ty = Type::getInt8Ty(getGlobalContext());
+ IntegerType* Int8Ty = Type::getInt8Ty(getGlobalContext());
EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, false)->getSExtValue());
EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, true)->getSExtValue());
EXPECT_EQ(100, ConstantInt::getSigned(Int8Ty, 100)->getSExtValue());
@@ -110,9 +110,9 @@ TEST(ConstantsTest, IntSigns) {
}
TEST(ConstantsTest, FP128Test) {
- const Type *FP128Ty = Type::getFP128Ty(getGlobalContext());
+ Type *FP128Ty = Type::getFP128Ty(getGlobalContext());
- const IntegerType *Int128Ty = Type::getIntNTy(getGlobalContext(), 128);
+ IntegerType *Int128Ty = Type::getIntNTy(getGlobalContext(), 128);
Constant *Zero128 = Constant::getNullValue(Int128Ty);
Constant *X = ConstantExpr::getUIToFP(Zero128, FP128Ty);
EXPECT_TRUE(isa<ConstantFP>(X));
diff --git a/unittests/VMCore/InstructionsTest.cpp b/unittests/VMCore/InstructionsTest.cpp
index 9624b81..f0197bb 100644
--- a/unittests/VMCore/InstructionsTest.cpp
+++ b/unittests/VMCore/InstructionsTest.cpp
@@ -26,16 +26,16 @@ TEST(InstructionsTest, ReturnInst) {
EXPECT_EQ(r0->getNumOperands(), 0U);
EXPECT_EQ(r0->op_begin(), r0->op_end());
- const IntegerType* Int1 = IntegerType::get(C, 1);
+ IntegerType* Int1 = IntegerType::get(C, 1);
Constant* One = ConstantInt::get(Int1, 1, true);
const ReturnInst* r1 = ReturnInst::Create(C, One);
- EXPECT_EQ(r1->getNumOperands(), 1U);
+ EXPECT_EQ(1U, r1->getNumOperands());
User::const_op_iterator b(r1->op_begin());
- EXPECT_NE(b, r1->op_end());
- EXPECT_EQ(*b, One);
- EXPECT_EQ(r1->getOperand(0), One);
+ EXPECT_NE(r1->op_end(), b);
+ EXPECT_EQ(One, *b);
+ EXPECT_EQ(One, r1->getOperand(0));
++b;
- EXPECT_EQ(b, r1->op_end());
+ EXPECT_EQ(r1->op_end(), b);
// clean up
delete r0;
@@ -54,17 +54,17 @@ TEST(InstructionsTest, BranchInst) {
EXPECT_TRUE(b0->isUnconditional());
EXPECT_FALSE(b0->isConditional());
- EXPECT_EQ(b0->getNumSuccessors(), 1U);
+ EXPECT_EQ(1U, b0->getNumSuccessors());
// check num operands
- EXPECT_EQ(b0->getNumOperands(), 1U);
+ EXPECT_EQ(1U, b0->getNumOperands());
EXPECT_NE(b0->op_begin(), b0->op_end());
- EXPECT_EQ(llvm::next(b0->op_begin()), b0->op_end());
+ EXPECT_EQ(b0->op_end(), llvm::next(b0->op_begin()));
- EXPECT_EQ(llvm::next(b0->op_begin()), b0->op_end());
+ EXPECT_EQ(b0->op_end(), llvm::next(b0->op_begin()));
- const IntegerType* Int1 = IntegerType::get(C, 1);
+ IntegerType* Int1 = IntegerType::get(C, 1);
Constant* One = ConstantInt::get(Int1, 1, true);
// Conditional BranchInst
@@ -72,33 +72,33 @@ TEST(InstructionsTest, BranchInst) {
EXPECT_FALSE(b1->isUnconditional());
EXPECT_TRUE(b1->isConditional());
- EXPECT_EQ(b1->getNumSuccessors(), 2U);
+ EXPECT_EQ(2U, b1->getNumSuccessors());
// check num operands
- EXPECT_EQ(b1->getNumOperands(), 3U);
+ EXPECT_EQ(3U, b1->getNumOperands());
User::const_op_iterator b(b1->op_begin());
// check COND
EXPECT_NE(b, b1->op_end());
- EXPECT_EQ(*b, One);
- EXPECT_EQ(b1->getOperand(0), One);
- EXPECT_EQ(b1->getCondition(), One);
+ EXPECT_EQ(One, *b);
+ EXPECT_EQ(One, b1->getOperand(0));
+ EXPECT_EQ(One, b1->getCondition());
++b;
// check ELSE
- EXPECT_EQ(*b, bb1);
- EXPECT_EQ(b1->getOperand(1), bb1);
- EXPECT_EQ(b1->getSuccessor(1), bb1);
+ EXPECT_EQ(bb1, *b);
+ EXPECT_EQ(bb1, b1->getOperand(1));
+ EXPECT_EQ(bb1, b1->getSuccessor(1));
++b;
// check THEN
- EXPECT_EQ(*b, bb0);
- EXPECT_EQ(b1->getOperand(2), bb0);
- EXPECT_EQ(b1->getSuccessor(0), bb0);
+ EXPECT_EQ(bb0, *b);
+ EXPECT_EQ(bb0, b1->getOperand(2));
+ EXPECT_EQ(bb0, b1->getSuccessor(0));
++b;
- EXPECT_EQ(b, b1->op_end());
+ EXPECT_EQ(b1->op_end(), b);
// clean up
delete b0;
@@ -111,11 +111,11 @@ TEST(InstructionsTest, BranchInst) {
TEST(InstructionsTest, CastInst) {
LLVMContext &C(getGlobalContext());
- const Type* Int8Ty = Type::getInt8Ty(C);
- const Type* Int64Ty = Type::getInt64Ty(C);
- const Type* V8x8Ty = VectorType::get(Int8Ty, 8);
- const Type* V8x64Ty = VectorType::get(Int64Ty, 8);
- const Type* X86MMXTy = Type::getX86_MMXTy(C);
+ Type* Int8Ty = Type::getInt8Ty(C);
+ Type* Int64Ty = Type::getInt64Ty(C);
+ Type* V8x8Ty = VectorType::get(Int8Ty, 8);
+ Type* V8x64Ty = VectorType::get(Int64Ty, 8);
+ Type* X86MMXTy = Type::getX86_MMXTy(C);
const Constant* c8 = Constant::getNullValue(V8x8Ty);
const Constant* c64 = Constant::getNullValue(V8x64Ty);
@@ -125,8 +125,8 @@ TEST(InstructionsTest, CastInst) {
EXPECT_FALSE(CastInst::isCastable(Int64Ty, X86MMXTy));
EXPECT_TRUE(CastInst::isCastable(V8x64Ty, V8x8Ty));
EXPECT_TRUE(CastInst::isCastable(V8x8Ty, V8x64Ty));
- EXPECT_EQ(CastInst::getCastOpcode(c64, true, V8x8Ty, true), CastInst::Trunc);
- EXPECT_EQ(CastInst::getCastOpcode(c8, true, V8x64Ty, true), CastInst::SExt);
+ EXPECT_EQ(CastInst::Trunc, CastInst::getCastOpcode(c64, true, V8x8Ty, true));
+ EXPECT_EQ(CastInst::SExt, CastInst::getCastOpcode(c8, true, V8x64Ty, true));
}
} // end anonymous namespace
diff --git a/unittests/VMCore/MetadataTest.cpp b/unittests/VMCore/MetadataTest.cpp
index 0b2c012..12ac2e7 100644
--- a/unittests/VMCore/MetadataTest.cpp
+++ b/unittests/VMCore/MetadataTest.cpp
@@ -63,7 +63,7 @@ TEST_F(MDStringTest, PrintingSimple) {
// Test printing of MDString with non-printable characters.
TEST_F(MDStringTest, PrintingComplex) {
- char str[5] = {0, '\n', '"', '\\', -1};
+ char str[5] = {0, '\n', '"', '\\', (char)-1};
MDString *s = MDString::get(Context, StringRef(str+0, 5));
std::string Str;
raw_string_ostream oss(Str);
diff --git a/unittests/VMCore/VerifierTest.cpp b/unittests/VMCore/VerifierTest.cpp
index 1924661..324b4e1 100644
--- a/unittests/VMCore/VerifierTest.cpp
+++ b/unittests/VMCore/VerifierTest.cpp
@@ -47,7 +47,7 @@ TEST(VerifierTest, Branch_i1) {
TEST(VerifierTest, AliasUnnamedAddr) {
LLVMContext &C = getGlobalContext();
Module M("M", C);
- const Type *Ty = Type::getInt8Ty(C);
+ Type *Ty = Type::getInt8Ty(C);
Constant *Init = Constant::getNullValue(Ty);
GlobalVariable *Aliasee = new GlobalVariable(M, Ty, true,
GlobalValue::ExternalLinkage,
diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp
index 8a5dc8b..145b96d 100644
--- a/utils/TableGen/ARMDecoderEmitter.cpp
+++ b/utils/TableGen/ARMDecoderEmitter.cpp
@@ -18,10 +18,10 @@
#include "ARMDecoderEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Record.h"
#include <vector>
#include <map>
@@ -41,7 +41,7 @@ using namespace llvm;
ENTRY(ARM_FORMAT_BRFRM, 2) \
ENTRY(ARM_FORMAT_BRMISCFRM, 3) \
ENTRY(ARM_FORMAT_DPFRM, 4) \
- ENTRY(ARM_FORMAT_DPSOREGFRM, 5) \
+ ENTRY(ARM_FORMAT_DPSOREGREGFRM, 5) \
ENTRY(ARM_FORMAT_LDFRM, 6) \
ENTRY(ARM_FORMAT_STFRM, 7) \
ENTRY(ARM_FORMAT_LDMISCFRM, 8) \
@@ -77,7 +77,8 @@ using namespace llvm;
ENTRY(ARM_FORMAT_N3RegVecSh, 38) \
ENTRY(ARM_FORMAT_NVecExtract, 39) \
ENTRY(ARM_FORMAT_NVecMulScalar, 40) \
- ENTRY(ARM_FORMAT_NVTBL, 41)
+ ENTRY(ARM_FORMAT_NVTBL, 41) \
+ ENTRY(ARM_FORMAT_DPSOREGIMMFRM, 42)
// ARM instruction format specifies the encoding used by the instruction.
#define ENTRY(n, v) n = v,
@@ -1614,15 +1615,6 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI,
if (!thumbInstruction(Form))
return false;
- // A8.6.189 STM / STMIA / STMEA -- Encoding T1
- // There's only STMIA_UPD for Thumb1.
- if (Name == "tSTMIA")
- return false;
-
- // On Darwin R9 is call-clobbered. Ignore the non-Darwin counterparts.
- if (Name == "tBL" || Name == "tBLXi" || Name == "tBLXr")
- return false;
-
// A8.6.25 BX. Use the generic tBX_Rm, ignore tBX_RET and tBX_RET_vararg.
if (Name == "tBX_RET" || Name == "tBX_RET_vararg")
return false;
@@ -1654,14 +1646,12 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI,
// Resolve conflicts:
//
- // tBfar conflicts with tBLr9
// t2LDMIA_RET conflict with t2LDM (ditto)
// tMOVCCi conflicts with tMOVi8
// tMOVCCr conflicts with tMOVgpr2gpr
// tLDRcp conflicts with tLDRspi
// t2MOVCCi16 conflicts with tMOVi16
- if (Name == "tBfar" ||
- Name == "t2LDMIA_RET" ||
+ if (Name == "t2LDMIA_RET" ||
Name == "tMOVCCi" || Name == "tMOVCCr" ||
Name == "tLDRcp" ||
Name == "t2MOVCCi16")
diff --git a/utils/TableGen/ARMDecoderEmitter.h b/utils/TableGen/ARMDecoderEmitter.h
index 1faeb91..486f899 100644
--- a/utils/TableGen/ARMDecoderEmitter.h
+++ b/utils/TableGen/ARMDecoderEmitter.h
@@ -15,9 +15,8 @@
#ifndef ARMDECODEREMITTER_H
#define ARMDECODEREMITTER_H
-#include "TableGenBackend.h"
-
#include "llvm/Support/DataTypes.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index a6a4fec..8b86c23 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -98,8 +98,6 @@
#include "AsmMatcherEmitter.h"
#include "CodeGenTarget.h"
-#include "Error.h"
-#include "Record.h"
#include "StringMatcher.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerUnion.h"
@@ -109,6 +107,8 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include <map>
#include <set>
using namespace llvm;
@@ -914,17 +914,17 @@ void AsmMatcherInfo::
BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
const std::vector<CodeGenRegister*> &Registers =
Target.getRegBank().getRegisters();
- const std::vector<CodeGenRegisterClass> &RegClassList =
- Target.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RegClassList =
+ Target.getRegBank().getRegClasses();
// The register sets used for matching.
std::set< std::set<Record*> > RegisterSets;
// Gather the defined sets.
- for (std::vector<CodeGenRegisterClass>::const_iterator it =
+ for (ArrayRef<CodeGenRegisterClass*>::const_iterator it =
RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it)
- RegisterSets.insert(std::set<Record*>(it->getOrder().begin(),
- it->getOrder().end()));
+ RegisterSets.insert(std::set<Record*>(
+ (*it)->getOrder().begin(), (*it)->getOrder().end()));
// Add any required singleton sets.
for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
@@ -996,18 +996,23 @@ BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
}
// Name the register classes which correspond to a user defined RegisterClass.
- for (std::vector<CodeGenRegisterClass>::const_iterator
+ for (ArrayRef<CodeGenRegisterClass*>::const_iterator
it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) {
- ClassInfo *CI = RegisterSetClasses[std::set<Record*>(it->getOrder().begin(),
- it->getOrder().end())];
+ const CodeGenRegisterClass &RC = **it;
+ // Def will be NULL for non-user defined register classes.
+ Record *Def = RC.getDef();
+ if (!Def)
+ continue;
+ ClassInfo *CI = RegisterSetClasses[std::set<Record*>(RC.getOrder().begin(),
+ RC.getOrder().end())];
if (CI->ValueName.empty()) {
- CI->ClassName = it->getName();
- CI->Name = "MCK_" + it->getName();
- CI->ValueName = it->getName();
+ CI->ClassName = RC.getName();
+ CI->Name = "MCK_" + RC.getName();
+ CI->ValueName = RC.getName();
} else
- CI->ValueName = CI->ValueName + "," + it->getName();
+ CI->ValueName = CI->ValueName + "," + RC.getName();
- RegisterClassClasses.insert(std::make_pair(it->TheDef, CI));
+ RegisterClassClasses.insert(std::make_pair(Def, CI));
}
// Populate the map for individual registers.
@@ -2172,21 +2177,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "\n#ifdef GET_ASSEMBLER_HEADER\n";
OS << "#undef GET_ASSEMBLER_HEADER\n";
OS << " // This should be included into the middle of the declaration of\n";
- OS << " // your subclasses implementation of TargetAsmParser.\n";
+ OS << " // your subclasses implementation of MCTargetAsmParser.\n";
OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
- OS << " enum MatchResultTy {\n";
- OS << " Match_ConversionFail,\n";
- OS << " Match_InvalidOperand,\n";
- OS << " Match_MissingFeature,\n";
- OS << " Match_MnemonicFail,\n";
- OS << " Match_Success\n";
- OS << " };\n";
OS << " bool ConvertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
<< " const SmallVectorImpl<MCParsedAsmOperand*> "
<< "&Operands);\n";
OS << " bool MnemonicIsValid(StringRef Mnemonic);\n";
- OS << " MatchResultTy MatchInstructionImpl(\n";
+ OS << " unsigned MatchInstructionImpl(\n";
OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
OS << " MCInst &Inst, unsigned &ErrorInfo);\n";
@@ -2328,7 +2326,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "}\n\n";
// Finally, build the match function.
- OS << Target.getName() << ClassName << "::MatchResultTy "
+ OS << "unsigned "
<< Target.getName() << ClassName << "::\n"
<< "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>"
<< " &Operands,\n";
@@ -2355,7 +2353,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " }\n\n";
OS << " // Some state to try to produce better error messages.\n";
- OS << " bool HadMatchOtherThanFeatures = false;\n\n";
+ OS << " bool HadMatchOtherThanFeatures = false;\n";
+ OS << " bool HadMatchOtherThanPredicate = false;\n";
+ OS << " unsigned RetCode = Match_InvalidOperand;\n";
OS << " // Set ErrorInfo to the operand that mismatches if it is\n";
OS << " // wrong for all instances of the instruction.\n";
OS << " ErrorInfo = ~0U;\n";
@@ -2411,6 +2411,18 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " return Match_ConversionFail;\n";
OS << "\n";
+ // Verify the instruction with the target-specific match predicate function.
+ OS << " // We have a potential match. Check the target predicate to\n"
+ << " // handle any context sensitive constraints.\n"
+ << " unsigned MatchResult;\n"
+ << " if ((MatchResult = checkTargetMatchPredicate(Inst)) !="
+ << " Match_Success) {\n"
+ << " Inst.clear();\n"
+ << " RetCode = MatchResult;\n"
+ << " HadMatchOtherThanPredicate = true;\n"
+ << " continue;\n"
+ << " }\n\n";
+
// Call the post-processing function, if used.
std::string InsnCleanupFn =
AsmParser->getValueAsString("AsmParserInstCleanup");
@@ -2421,8 +2433,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " }\n\n";
OS << " // Okay, we had no match. Try to return a useful error code.\n";
- OS << " if (HadMatchOtherThanFeatures) return Match_MissingFeature;\n";
- OS << " return Match_InvalidOperand;\n";
+ OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)";
+ OS << " return RetCode;\n";
+ OS << " return Match_MissingFeature;\n";
OS << "}\n\n";
if (Info.OperandMatchInfo.size())
diff --git a/utils/TableGen/AsmMatcherEmitter.h b/utils/TableGen/AsmMatcherEmitter.h
index c13adf3..e04ac10 100644
--- a/utils/TableGen/AsmMatcherEmitter.h
+++ b/utils/TableGen/AsmMatcherEmitter.h
@@ -15,7 +15,7 @@
#ifndef ASMMATCHER_EMITTER_H
#define ASMMATCHER_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
namespace llvm {
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index f44f050..3123e11 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -14,13 +14,13 @@
#include "AsmWriterEmitter.h"
#include "AsmWriterInst.h"
-#include "Error.h"
#include "CodeGenTarget.h"
-#include "Record.h"
#include "StringToOffsetTable.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include <algorithm>
using namespace llvm;
@@ -703,8 +703,8 @@ void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) {
CodeGenTarget Target(Records);
// Enumerate the register classes.
- const std::vector<CodeGenRegisterClass> &RegisterClasses =
- Target.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses =
+ Target.getRegBank().getRegClasses();
O << "namespace { // Register classes\n";
O << " enum RegClass {\n";
@@ -712,7 +712,7 @@ void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) {
// Emit the register enum value for each RegisterClass.
for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) {
if (I != 0) O << ",\n";
- O << " RC_" << RegisterClasses[I].TheDef->getName();
+ O << " RC_" << RegisterClasses[I]->getName();
}
O << "\n };\n";
@@ -729,10 +729,10 @@ void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) {
O << " default: break;\n";
for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) {
- const CodeGenRegisterClass &RC = RegisterClasses[I];
+ const CodeGenRegisterClass &RC = *RegisterClasses[I];
// Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
+ std::string Name = RC.getName();
O << " case RC_" << Name << ":\n";
// Emit the register list now.
diff --git a/utils/TableGen/AsmWriterEmitter.h b/utils/TableGen/AsmWriterEmitter.h
index 84c925b..731e31c 100644
--- a/utils/TableGen/AsmWriterEmitter.h
+++ b/utils/TableGen/AsmWriterEmitter.h
@@ -15,7 +15,7 @@
#ifndef ASMWRITER_EMITTER_H
#define ASMWRITER_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <map>
#include <vector>
#include <cassert>
diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp
index fdf447f..350a2cc 100644
--- a/utils/TableGen/AsmWriterInst.cpp
+++ b/utils/TableGen/AsmWriterInst.cpp
@@ -13,8 +13,8 @@
#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
-#include "Record.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/TableGen/Record.h"
using namespace llvm;
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index 4d71259..02ebd67 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -1,18 +1,12 @@
set(LLVM_REQUIRES_EH 1)
set(LLVM_REQUIRES_RTTI 1)
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR})
-
-add_llvm_utility(tblgen
+add_tablegen(llvm-tblgen LLVM
ARMDecoderEmitter.cpp
AsmMatcherEmitter.cpp
AsmWriterEmitter.cpp
AsmWriterInst.cpp
CallingConvEmitter.cpp
- ClangASTNodesEmitter.cpp
- ClangAttrEmitter.cpp
- ClangDiagnosticsEmitter.cpp
- ClangSACheckersEmitter.cpp
CodeEmitterGen.cpp
CodeGenDAGPatterns.cpp
CodeGenInstruction.cpp
@@ -25,36 +19,18 @@ add_llvm_utility(tblgen
DAGISelMatcher.cpp
DisassemblerEmitter.cpp
EDEmitter.cpp
- Error.cpp
FastISelEmitter.cpp
FixedLenDecoderEmitter.cpp
InstrEnumEmitter.cpp
InstrInfoEmitter.cpp
IntrinsicEmitter.cpp
- LLVMCConfigurationEmitter.cpp
- NeonEmitter.cpp
- OptParserEmitter.cpp
PseudoLoweringEmitter.cpp
- Record.cpp
RegisterInfoEmitter.cpp
SetTheory.cpp
StringMatcher.cpp
SubtargetEmitter.cpp
- TGLexer.cpp
- TGParser.cpp
TGValueTypes.cpp
TableGen.cpp
- TableGenBackend.cpp
X86DisassemblerTables.cpp
X86RecognizableInstr.cpp
)
-
-target_link_libraries(tblgen LLVMSupport)
-if( MINGW )
- target_link_libraries(tblgen imagehlp psapi)
-endif( MINGW )
-if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD AND NOT BEOS )
- target_link_libraries(tblgen pthread)
-endif()
-
-install(TARGETS tblgen RUNTIME DESTINATION bin)
diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp
index c51afd8..fcdaa08 100644
--- a/utils/TableGen/CallingConvEmitter.cpp
+++ b/utils/TableGen/CallingConvEmitter.cpp
@@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
#include "CallingConvEmitter.h"
-#include "Record.h"
#include "CodeGenTarget.h"
+#include "llvm/TableGen/Record.h"
using namespace llvm;
void CallingConvEmitter::run(raw_ostream &O) {
diff --git a/utils/TableGen/CallingConvEmitter.h b/utils/TableGen/CallingConvEmitter.h
index 431c33b..7bddd6c 100644
--- a/utils/TableGen/CallingConvEmitter.h
+++ b/utils/TableGen/CallingConvEmitter.h
@@ -15,7 +15,7 @@
#ifndef CALLINGCONV_EMITTER_H
#define CALLINGCONV_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
namespace llvm {
diff --git a/utils/TableGen/ClangASTNodesEmitter.cpp b/utils/TableGen/ClangASTNodesEmitter.cpp
deleted file mode 100644
index d9d5a3c..0000000
--- a/utils/TableGen/ClangASTNodesEmitter.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-//=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang AST node tables
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangASTNodesEmitter.h"
-#include <set>
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Statement Node Tables (.inc file) generation.
-//===----------------------------------------------------------------------===//
-
-// Returns the first and last non-abstract subrecords
-// Called recursively to ensure that nodes remain contiguous
-std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
- const ChildMap &Tree,
- raw_ostream &OS,
- Record *Base) {
- std::string BaseName = macroName(Base->getName());
-
- ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
-
- Record *First = 0, *Last = 0;
- // This might be the pseudo-node for Stmt; don't assume it has an Abstract
- // bit
- if (Base->getValue("Abstract") && !Base->getValueAsBit("Abstract"))
- First = Last = Base;
-
- for (; i != e; ++i) {
- Record *R = i->second;
- bool Abstract = R->getValueAsBit("Abstract");
- std::string NodeName = macroName(R->getName());
-
- OS << "#ifndef " << NodeName << "\n";
- OS << "# define " << NodeName << "(Type, Base) "
- << BaseName << "(Type, Base)\n";
- OS << "#endif\n";
-
- if (Abstract)
- OS << "ABSTRACT_" << macroName(Root.getName()) << "(" << NodeName << "("
- << R->getName() << ", " << baseName(*Base) << "))\n";
- else
- OS << NodeName << "(" << R->getName() << ", "
- << baseName(*Base) << ")\n";
-
- if (Tree.find(R) != Tree.end()) {
- const std::pair<Record *, Record *> &Result
- = EmitNode(Tree, OS, R);
- if (!First && Result.first)
- First = Result.first;
- if (Result.second)
- Last = Result.second;
- } else {
- if (!Abstract) {
- Last = R;
-
- if (!First)
- First = R;
- }
- }
-
- OS << "#undef " << NodeName << "\n\n";
- }
-
- if (First) {
- assert (Last && "Got a first node but not a last node for a range!");
- if (Base == &Root)
- OS << "LAST_" << macroName(Root.getName()) << "_RANGE(";
- else
- OS << macroName(Root.getName()) << "_RANGE(";
- OS << Base->getName() << ", " << First->getName() << ", "
- << Last->getName() << ")\n\n";
- }
-
- return std::make_pair(First, Last);
-}
-
-void ClangASTNodesEmitter::run(raw_ostream &OS) {
- // Write the preamble
- OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n";
- OS << "# define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n";
- OS << "#endif\n";
-
- OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n";
- OS << "# define "
- << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
- OS << "#endif\n\n";
-
- OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n";
- OS << "# define LAST_"
- << macroName(Root.getName()) << "_RANGE(Base, First, Last) "
- << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
- OS << "#endif\n\n";
-
- // Emit statements
- const std::vector<Record*> Stmts
- = Records.getAllDerivedDefinitions(Root.getName());
-
- ChildMap Tree;
-
- for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
- Record *R = Stmts[i];
-
- if (R->getValue("Base"))
- Tree.insert(std::make_pair(R->getValueAsDef("Base"), R));
- else
- Tree.insert(std::make_pair(&Root, R));
- }
-
- EmitNode(Tree, OS, &Root);
-
- OS << "#undef " << macroName(Root.getName()) << "\n";
- OS << "#undef " << macroName(Root.getName()) << "_RANGE\n";
- OS << "#undef LAST_" << macroName(Root.getName()) << "_RANGE\n";
- OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n";
-}
-
-void ClangDeclContextEmitter::run(raw_ostream &OS) {
- // FIXME: Find a .td file format to allow for this to be represented better.
-
- OS << "#ifndef DECL_CONTEXT\n";
- OS << "# define DECL_CONTEXT(DECL)\n";
- OS << "#endif\n";
-
- OS << "#ifndef DECL_CONTEXT_BASE\n";
- OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n";
- OS << "#endif\n";
-
- typedef std::set<Record*> RecordSet;
- typedef std::vector<Record*> RecordVector;
-
- RecordVector DeclContextsVector
- = Records.getAllDerivedDefinitions("DeclContext");
- RecordVector Decls = Records.getAllDerivedDefinitions("Decl");
- RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end());
-
- for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) {
- Record *R = *i;
-
- if (R->getValue("Base")) {
- Record *B = R->getValueAsDef("Base");
- if (DeclContexts.find(B) != DeclContexts.end()) {
- OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n";
- DeclContexts.erase(B);
- }
- }
- }
-
- // To keep identical order, RecordVector may be used
- // instead of RecordSet.
- for (RecordVector::iterator
- i = DeclContextsVector.begin(), e = DeclContextsVector.end();
- i != e; ++i)
- if (DeclContexts.find(*i) != DeclContexts.end())
- OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n";
-
- OS << "#undef DECL_CONTEXT\n";
- OS << "#undef DECL_CONTEXT_BASE\n";
-}
diff --git a/utils/TableGen/ClangASTNodesEmitter.h b/utils/TableGen/ClangASTNodesEmitter.h
deleted file mode 100644
index 712333b..0000000
--- a/utils/TableGen/ClangASTNodesEmitter.h
+++ /dev/null
@@ -1,84 +0,0 @@
-//===- ClangASTNodesEmitter.h - Generate Clang AST node tables -*- C++ -*--===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang AST node tables
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANGAST_EMITTER_H
-#define CLANGAST_EMITTER_H
-
-#include "TableGenBackend.h"
-#include "Record.h"
-#include <string>
-#include <cctype>
-#include <map>
-
-namespace llvm {
-
-/// ClangASTNodesEmitter - The top-level class emits .inc files containing
-/// declarations of Clang statements.
-///
-class ClangASTNodesEmitter : public TableGenBackend {
- // A map from a node to each of its derived nodes.
- typedef std::multimap<Record*, Record*> ChildMap;
- typedef ChildMap::const_iterator ChildIterator;
-
- RecordKeeper &Records;
- Record Root;
- const std::string &BaseSuffix;
-
- // Create a macro-ized version of a name
- static std::string macroName(std::string S) {
- for (unsigned i = 0; i < S.size(); ++i)
- S[i] = std::toupper(S[i]);
-
- return S;
- }
-
- // Return the name to be printed in the base field. Normally this is
- // the record's name plus the base suffix, but if it is the root node and
- // the suffix is non-empty, it's just the suffix.
- std::string baseName(Record &R) {
- if (&R == &Root && !BaseSuffix.empty())
- return BaseSuffix;
-
- return R.getName() + BaseSuffix;
- }
-
- std::pair<Record *, Record *> EmitNode (const ChildMap &Tree, raw_ostream& OS,
- Record *Base);
-public:
- explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N,
- const std::string &S)
- : Records(R), Root(N, SMLoc(), R), BaseSuffix(S)
- {}
-
- // run - Output the .inc file contents
- void run(raw_ostream &OS);
-};
-
-/// ClangDeclContextEmitter - Emits an addendum to a .inc file to enumerate the
-/// clang declaration contexts.
-///
-class ClangDeclContextEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
-public:
- explicit ClangDeclContextEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- // run - Output the .inc file contents
- void run(raw_ostream &OS);
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
deleted file mode 100644
index 26bd878..0000000
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ /dev/null
@@ -1,756 +0,0 @@
-//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang attribute processing code
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangAttrEmitter.h"
-#include "Record.h"
-#include "llvm/ADT/StringSwitch.h"
-#include <algorithm>
-#include <cctype>
-
-using namespace llvm;
-
-static const std::vector<StringRef>
-getValueAsListOfStrings(Record &R, StringRef FieldName) {
- ListInit *List = R.getValueAsListInit(FieldName);
- assert (List && "Got a null ListInit");
-
- std::vector<StringRef> Strings;
- Strings.reserve(List->getSize());
-
- for (ListInit::iterator i = List->begin(), e = List->end(); i != e; ++i) {
- assert(*i && "Got a null element in a ListInit");
- if (StringInit *S = dynamic_cast<StringInit *>(*i))
- Strings.push_back(S->getValue());
- else if (CodeInit *C = dynamic_cast<CodeInit *>(*i))
- Strings.push_back(C->getValue());
- else
- assert(false && "Got a non-string, non-code element in a ListInit");
- }
-
- return Strings;
-}
-
-std::string ReadPCHRecord(StringRef type) {
- return StringSwitch<std::string>(type)
- .EndsWith("Decl *", "cast_or_null<" + std::string(type, 0, type.size()-1) +
- ">(GetDecl(Record[Idx++]))")
- .Case("QualType", "GetType(Record[Idx++])")
- .Case("Expr *", "ReadSubExpr()")
- .Case("IdentifierInfo *", "GetIdentifierInfo(Record, Idx)")
- .Default("Record[Idx++]");
-}
-
-// Assumes that the way to get the value is SA->getname()
-std::string WritePCHRecord(StringRef type, StringRef name) {
- return StringSwitch<std::string>(type)
- .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
- ", Record);\n")
- .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
- .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
- .Case("IdentifierInfo *",
- "AddIdentifierRef(" + std::string(name) + ", Record);\n")
- .Default("Record.push_back(" + std::string(name) + ");\n");
-}
-
-namespace {
- class Argument {
- std::string lowerName, upperName;
- StringRef attrName;
-
- public:
- Argument(Record &Arg, StringRef Attr)
- : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
- attrName(Attr) {
- if (!lowerName.empty()) {
- lowerName[0] = std::tolower(lowerName[0]);
- upperName[0] = std::toupper(upperName[0]);
- }
- }
- virtual ~Argument() {}
-
- StringRef getLowerName() const { return lowerName; }
- StringRef getUpperName() const { return upperName; }
- StringRef getAttrName() const { return attrName; }
-
- // These functions print the argument contents formatted in different ways.
- virtual void writeAccessors(raw_ostream &OS) const = 0;
- virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
- virtual void writeCloneArgs(raw_ostream &OS) const = 0;
- virtual void writeCtorBody(raw_ostream &OS) const {}
- virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
- virtual void writeCtorParameters(raw_ostream &OS) const = 0;
- virtual void writeDeclarations(raw_ostream &OS) const = 0;
- virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
- virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
- virtual void writePCHWrite(raw_ostream &OS) const = 0;
- };
-
- class SimpleArgument : public Argument {
- std::string type;
-
- public:
- SimpleArgument(Record &Arg, StringRef Attr, std::string T)
- : Argument(Arg, Attr), type(T)
- {}
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " " << type << " get" << getUpperName() << "() const {\n";
- OS << " return " << getLowerName() << ";\n";
- OS << " }";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << getLowerName() << "(" << getUpperName() << ")";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << type << " " << getUpperName();
- }
- void writeDeclarations(raw_ostream &OS) const {
- OS << type << " " << getLowerName() << ";";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- std::string read = ReadPCHRecord(type);
- OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writePCHWrite(raw_ostream &OS) const {
- OS << " " << WritePCHRecord(type, "SA->get" +
- std::string(getUpperName()) + "()");
- }
- };
-
- class StringArgument : public Argument {
- public:
- StringArgument(Record &Arg, StringRef Attr)
- : Argument(Arg, Attr)
- {}
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
- OS << " return llvm::StringRef(" << getLowerName() << ", "
- << getLowerName() << "Length);\n";
- OS << " }\n";
- OS << " unsigned get" << getUpperName() << "Length() const {\n";
- OS << " return " << getLowerName() << "Length;\n";
- OS << " }\n";
- OS << " void set" << getUpperName()
- << "(ASTContext &C, llvm::StringRef S) {\n";
- OS << " " << getLowerName() << "Length = S.size();\n";
- OS << " this->" << getLowerName() << " = new (C, 1) char ["
- << getLowerName() << "Length];\n";
- OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
- << getLowerName() << "Length);\n";
- OS << " }";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << "get" << getUpperName() << "()";
- }
- void writeCtorBody(raw_ostream &OS) const {
- OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
- << ".data(), " << getLowerName() << "Length);";
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
- << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
- << "Length])";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << "llvm::StringRef " << getUpperName();
- }
- void writeDeclarations(raw_ostream &OS) const {
- OS << "unsigned " << getLowerName() << "Length;\n";
- OS << "char *" << getLowerName() << ";";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- OS << " std::string " << getLowerName()
- << "= ReadString(Record, Idx);\n";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writePCHWrite(raw_ostream &OS) const {
- OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
- }
- };
-
- class AlignedArgument : public Argument {
- public:
- AlignedArgument(Record &Arg, StringRef Attr)
- : Argument(Arg, Attr)
- {}
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " bool is" << getUpperName() << "Dependent() const;\n";
-
- OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
-
- OS << " bool is" << getUpperName() << "Expr() const {\n";
- OS << " return is" << getLowerName() << "Expr;\n";
- OS << " }\n";
-
- OS << " Expr *get" << getUpperName() << "Expr() const {\n";
- OS << " assert(is" << getLowerName() << "Expr);\n";
- OS << " return " << getLowerName() << "Expr;\n";
- OS << " }\n";
-
- OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
- OS << " assert(!is" << getLowerName() << "Expr);\n";
- OS << " return " << getLowerName() << "Type;\n";
- OS << " }";
- }
- void writeAccessorDefinitions(raw_ostream &OS) const {
- OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
- << "Dependent() const {\n";
- OS << " if (is" << getLowerName() << "Expr)\n";
- OS << " return " << getLowerName() << "Expr && (" << getLowerName()
- << "Expr->isValueDependent() || " << getLowerName()
- << "Expr->isTypeDependent());\n";
- OS << " else\n";
- OS << " return " << getLowerName()
- << "Type->getType()->isDependentType();\n";
- OS << "}\n";
-
- // FIXME: Do not do the calculation here
- // FIXME: Handle types correctly
- // A null pointer means maximum alignment
- // FIXME: Load the platform-specific maximum alignment, rather than
- // 16, the x86 max.
- OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
- << "(ASTContext &Ctx) const {\n";
- OS << " assert(!is" << getUpperName() << "Dependent());\n";
- OS << " if (is" << getLowerName() << "Expr)\n";
- OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
- << "Expr->EvaluateAsInt(Ctx).getZExtValue() : 16)"
- << "* Ctx.getCharWidth();\n";
- OS << " else\n";
- OS << " return 0; // FIXME\n";
- OS << "}\n";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << "is" << getLowerName() << "Expr, is" << getLowerName()
- << "Expr ? static_cast<void*>(" << getLowerName()
- << "Expr) : " << getLowerName()
- << "Type";
- }
- void writeCtorBody(raw_ostream &OS) const {
- OS << " if (is" << getLowerName() << "Expr)\n";
- OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
- << getUpperName() << ");\n";
- OS << " else\n";
- OS << " " << getLowerName()
- << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
- << ");";
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
- }
- void writeDeclarations(raw_ostream &OS) const {
- OS << "bool is" << getLowerName() << "Expr;\n";
- OS << "union {\n";
- OS << "Expr *" << getLowerName() << "Expr;\n";
- OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
- OS << "};";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
- OS << " void *" << getLowerName() << "Ptr;\n";
- OS << " if (is" << getLowerName() << "Expr)\n";
- OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
- OS << " else\n";
- OS << " " << getLowerName()
- << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
- }
- void writePCHWrite(raw_ostream &OS) const {
- OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
- OS << " if (SA->is" << getUpperName() << "Expr())\n";
- OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
- OS << " else\n";
- OS << " AddTypeSourceInfo(SA->get" << getUpperName()
- << "Type(), Record);\n";
- }
- };
-
- class VariadicArgument : public Argument {
- std::string type;
-
- public:
- VariadicArgument(Record &Arg, StringRef Attr, std::string T)
- : Argument(Arg, Attr), type(T)
- {}
-
- std::string getType() const { return type; }
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
- OS << " " << getLowerName() << "_iterator " << getLowerName()
- << "_begin() const {\n";
- OS << " return " << getLowerName() << ";\n";
- OS << " }\n";
- OS << " " << getLowerName() << "_iterator " << getLowerName()
- << "_end() const {\n";
- OS << " return " << getLowerName() << " + " << getLowerName()
- << "Size;\n";
- OS << " }\n";
- OS << " unsigned " << getLowerName() << "_size() const {\n"
- << " return " << getLowerName() << "Size;\n;";
- OS << " }";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << getLowerName() << ", " << getLowerName() << "Size";
- }
- void writeCtorBody(raw_ostream &OS) const {
- // FIXME: memcpy is not safe on non-trivial types.
- OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
- << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << getLowerName() << "Size(" << getUpperName() << "Size), "
- << getLowerName() << "(new (Ctx, 16) " << getType() << "["
- << getLowerName() << "Size])";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << getType() << " *" << getUpperName() << ", unsigned "
- << getUpperName() << "Size";
- }
- void writeDeclarations(raw_ostream &OS) const {
- OS << " unsigned " << getLowerName() << "Size;\n";
- OS << " " << getType() << " *" << getLowerName() << ";";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
- OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
- << ";\n";
- OS << " " << getLowerName() << ".reserve(" << getLowerName()
- << "Size);\n";
- OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
-
- std::string read = ReadPCHRecord(type);
- OS << " " << getLowerName() << ".push_back(" << read << ");\n";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << getLowerName() << ".data(), " << getLowerName() << "Size";
- }
- void writePCHWrite(raw_ostream &OS) const{
- OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
- OS << " for (" << getAttrName() << "Attr::" << getLowerName()
- << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
- << getLowerName() << "_end(); i != e; ++i)\n";
- OS << " " << WritePCHRecord(type, "(*i)");
- }
- };
-
- class EnumArgument : public Argument {
- std::string type;
- std::vector<StringRef> values, enums;
- public:
- EnumArgument(Record &Arg, StringRef Attr)
- : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
- values(getValueAsListOfStrings(Arg, "Values")),
- enums(getValueAsListOfStrings(Arg, "Enums"))
- {}
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " " << type << " get" << getUpperName() << "() const {\n";
- OS << " return " << getLowerName() << ";\n";
- OS << " }";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << getLowerName() << "(" << getUpperName() << ")";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << type << " " << getUpperName();
- }
- void writeDeclarations(raw_ostream &OS) const {
- // Calculate the various enum values
- std::vector<StringRef> uniques(enums);
- std::sort(uniques.begin(), uniques.end());
- uniques.erase(std::unique(uniques.begin(), uniques.end()),
- uniques.end());
- // FIXME: Emit a proper error
- assert(!uniques.empty());
-
- std::vector<StringRef>::iterator i = uniques.begin(),
- e = uniques.end();
- // The last one needs to not have a comma.
- --e;
-
- OS << "public:\n";
- OS << " enum " << type << " {\n";
- for (; i != e; ++i)
- OS << " " << *i << ",\n";
- OS << " " << *e << "\n";
- OS << " };\n";
- OS << "private:\n";
- OS << " " << type << " " << getLowerName() << ";";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
- << "(static_cast<" << getAttrName() << "Attr::" << type
- << ">(Record[Idx++]));\n";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writePCHWrite(raw_ostream &OS) const {
- OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
- }
- };
-
- class VersionArgument : public Argument {
- public:
- VersionArgument(Record &Arg, StringRef Attr)
- : Argument(Arg, Attr)
- {}
-
- void writeAccessors(raw_ostream &OS) const {
- OS << " VersionTuple get" << getUpperName() << "() const {\n";
- OS << " return " << getLowerName() << ";\n";
- OS << " }\n";
- OS << " void set" << getUpperName()
- << "(ASTContext &C, VersionTuple V) {\n";
- OS << " " << getLowerName() << " = V;\n";
- OS << " }";
- }
- void writeCloneArgs(raw_ostream &OS) const {
- OS << "get" << getUpperName() << "()";
- }
- void writeCtorBody(raw_ostream &OS) const {
- }
- void writeCtorInitializers(raw_ostream &OS) const {
- OS << getLowerName() << "(" << getUpperName() << ")";
- }
- void writeCtorParameters(raw_ostream &OS) const {
- OS << "VersionTuple " << getUpperName();
- }
- void writeDeclarations(raw_ostream &OS) const {
- OS << "VersionTuple " << getLowerName() << ";\n";
- }
- void writePCHReadDecls(raw_ostream &OS) const {
- OS << " VersionTuple " << getLowerName()
- << "= ReadVersionTuple(Record, Idx);\n";
- }
- void writePCHReadArgs(raw_ostream &OS) const {
- OS << getLowerName();
- }
- void writePCHWrite(raw_ostream &OS) const {
- OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
- }
- };
-}
-
-static Argument *createArgument(Record &Arg, StringRef Attr,
- Record *Search = 0) {
- if (!Search)
- Search = &Arg;
-
- Argument *Ptr = 0;
- llvm::StringRef ArgName = Search->getName();
-
- if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
- else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
- else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
- "Expr *");
- else if (ArgName == "FunctionArgument")
- Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
- else if (ArgName == "IdentifierArgument")
- Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
- else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
- "bool");
- else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
- else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
- else if (ArgName == "TypeArgument")
- Ptr = new SimpleArgument(Arg, Attr, "QualType");
- else if (ArgName == "UnsignedArgument")
- Ptr = new SimpleArgument(Arg, Attr, "unsigned");
- else if (ArgName == "VariadicUnsignedArgument")
- Ptr = new VariadicArgument(Arg, Attr, "unsigned");
- else if (ArgName == "VersionArgument")
- Ptr = new VersionArgument(Arg, Attr);
-
- if (!Ptr) {
- std::vector<Record*> Bases = Search->getSuperClasses();
- for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
- i != e; ++i) {
- Ptr = createArgument(Arg, Attr, *i);
- if (Ptr)
- break;
- }
- }
- return Ptr;
-}
-
-void ClangAttrClassEmitter::run(raw_ostream &OS) {
- OS << "// This file is generated by TableGen. Do not edit.\n\n";
- OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
- OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
-
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
-
- for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
- i != e; ++i) {
- Record &R = **i;
- const std::string &SuperName = R.getSuperClasses().back()->getName();
-
- OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
-
- std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
- std::vector<Argument*> Args;
- std::vector<Argument*>::iterator ai, ae;
- Args.reserve(ArgRecords.size());
-
- for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
- re = ArgRecords.end();
- ri != re; ++ri) {
- Record &ArgRecord = **ri;
- Argument *Arg = createArgument(ArgRecord, R.getName());
- assert(Arg);
- Args.push_back(Arg);
-
- Arg->writeDeclarations(OS);
- OS << "\n\n";
- }
-
- ae = Args.end();
-
- OS << "\n public:\n";
- OS << " " << R.getName() << "Attr(SourceLocation L, ASTContext &Ctx\n";
-
- for (ai = Args.begin(); ai != ae; ++ai) {
- OS << " , ";
- (*ai)->writeCtorParameters(OS);
- OS << "\n";
- }
-
- OS << " )\n";
- OS << " : " << SuperName << "(attr::" << R.getName() << ", L)\n";
-
- for (ai = Args.begin(); ai != ae; ++ai) {
- OS << " , ";
- (*ai)->writeCtorInitializers(OS);
- OS << "\n";
- }
-
- OS << " {\n";
-
- for (ai = Args.begin(); ai != ae; ++ai) {
- (*ai)->writeCtorBody(OS);
- OS << "\n";
- }
- OS << " }\n\n";
-
- OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
-
- for (ai = Args.begin(); ai != ae; ++ai) {
- (*ai)->writeAccessors(OS);
- OS << "\n\n";
- }
-
- OS << R.getValueAsCode("AdditionalMembers");
- OS << "\n\n";
-
- OS << " static bool classof(const Attr *A) { return A->getKind() == "
- << "attr::" << R.getName() << "; }\n";
- OS << " static bool classof(const " << R.getName()
- << "Attr *) { return true; }\n";
- OS << "};\n\n";
- }
-
- OS << "#endif\n";
-}
-
-void ClangAttrImplEmitter::run(raw_ostream &OS) {
- OS << "// This file is generated by TableGen. Do not edit.\n\n";
-
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
- std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
- std::vector<Argument*>::iterator ai, ae;
-
- for (; i != e; ++i) {
- Record &R = **i;
- std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
- std::vector<Argument*> Args;
- for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
- Args.push_back(createArgument(**ri, R.getName()));
-
- for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
- (*ai)->writeAccessorDefinitions(OS);
-
- OS << R.getName() << "Attr *" << R.getName()
- << "Attr::clone(ASTContext &C) const {\n";
- OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
- for (ai = Args.begin(); ai != ae; ++ai) {
- OS << ", ";
- (*ai)->writeCloneArgs(OS);
- }
- OS << ");\n}\n\n";
- }
-}
-
-static void EmitAttrList(raw_ostream &OS, StringRef Class,
- const std::vector<Record*> &AttrList) {
- std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
-
- if (i != e) {
- // Move the end iterator back to emit the last attribute.
- for(--e; i != e; ++i)
- OS << Class << "(" << (*i)->getName() << ")\n";
-
- OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
- }
-}
-
-void ClangAttrListEmitter::run(raw_ostream &OS) {
- OS << "// This file is generated by TableGen. Do not edit.\n\n";
-
- OS << "#ifndef LAST_ATTR\n";
- OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
- OS << "#endif\n\n";
-
- OS << "#ifndef INHERITABLE_ATTR\n";
- OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
- OS << "#endif\n\n";
-
- OS << "#ifndef LAST_INHERITABLE_ATTR\n";
- OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
- OS << "#endif\n\n";
-
- OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
- OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
- OS << "#endif\n\n";
-
- OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
- OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
- " INHERITABLE_PARAM_ATTR(NAME)\n";
- OS << "#endif\n\n";
-
- Record *InhClass = Records.getClass("InheritableAttr");
- Record *InhParamClass = Records.getClass("InheritableParamAttr");
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
- NonInhAttrs, InhAttrs, InhParamAttrs;
- for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
- i != e; ++i) {
- if ((*i)->isSubClassOf(InhParamClass))
- InhParamAttrs.push_back(*i);
- else if ((*i)->isSubClassOf(InhClass))
- InhAttrs.push_back(*i);
- else
- NonInhAttrs.push_back(*i);
- }
-
- EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
- EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
- EmitAttrList(OS, "ATTR", NonInhAttrs);
-
- OS << "#undef LAST_ATTR\n";
- OS << "#undef INHERITABLE_ATTR\n";
- OS << "#undef LAST_INHERITABLE_ATTR\n";
- OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
- OS << "#undef ATTR\n";
-}
-
-void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
- OS << "// This file is generated by TableGen. Do not edit.\n\n";
-
- Record *InhClass = Records.getClass("InheritableAttr");
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
- ArgRecords;
- std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
- std::vector<Argument*> Args;
- std::vector<Argument*>::iterator ri, re;
-
- OS << " switch (Kind) {\n";
- OS << " default:\n";
- OS << " assert(0 && \"Unknown attribute!\");\n";
- OS << " break;\n";
- for (; i != e; ++i) {
- Record &R = **i;
- OS << " case attr::" << R.getName() << ": {\n";
- if (R.isSubClassOf(InhClass))
- OS << " bool isInherited = Record[Idx++];\n";
- ArgRecords = R.getValueAsListOfDefs("Args");
- Args.clear();
- for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
- Argument *A = createArgument(**ai, R.getName());
- Args.push_back(A);
- A->writePCHReadDecls(OS);
- }
- OS << " New = new (*Context) " << R.getName() << "Attr(Loc, *Context";
- for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
- OS << ", ";
- (*ri)->writePCHReadArgs(OS);
- }
- OS << ");\n";
- if (R.isSubClassOf(InhClass))
- OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
- OS << " break;\n";
- OS << " }\n";
- }
- OS << " }\n";
-}
-
-void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
- Record *InhClass = Records.getClass("InheritableAttr");
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
- std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
-
- OS << " switch (A->getKind()) {\n";
- OS << " default:\n";
- OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
- OS << " break;\n";
- for (; i != e; ++i) {
- Record &R = **i;
- OS << " case attr::" << R.getName() << ": {\n";
- Args = R.getValueAsListOfDefs("Args");
- if (R.isSubClassOf(InhClass) || !Args.empty())
- OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
- << "Attr>(A);\n";
- if (R.isSubClassOf(InhClass))
- OS << " Record.push_back(SA->isInherited());\n";
- for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
- createArgument(**ai, R.getName())->writePCHWrite(OS);
- OS << " break;\n";
- OS << " }\n";
- }
- OS << " }\n";
-}
-
-void ClangAttrSpellingListEmitter::run(raw_ostream &OS) {
- OS << "// This file is generated by TableGen. Do not edit.\n\n";
-
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
-
- for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
- Record &Attr = **I;
-
- std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings");
-
- for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
- StringRef Spelling = *I;
- OS << ".Case(\"" << Spelling << "\", true)\n";
- }
- }
-
-}
diff --git a/utils/TableGen/ClangAttrEmitter.h b/utils/TableGen/ClangAttrEmitter.h
deleted file mode 100644
index af87009..0000000
--- a/utils/TableGen/ClangAttrEmitter.h
+++ /dev/null
@@ -1,101 +0,0 @@
-//===- ClangAttrEmitter.h - Generate Clang attribute handling =-*- C++ -*--===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang attribute processing code
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANGATTR_EMITTER_H
-#define CLANGATTR_EMITTER_H
-
-#include "TableGenBackend.h"
-
-namespace llvm {
-
-/// ClangAttrClassEmitter - class emits the class defintions for attributes for
-/// clang.
-class ClangAttrClassEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
- public:
- explicit ClangAttrClassEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-/// ClangAttrImplEmitter - class emits the class method defintions for
-/// attributes for clang.
-class ClangAttrImplEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
- public:
- explicit ClangAttrImplEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-/// ClangAttrListEmitter - class emits the enumeration list for attributes for
-/// clang.
-class ClangAttrListEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
- public:
- explicit ClangAttrListEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-/// ClangAttrPCHReadEmitter - class emits the code to read an attribute from
-/// a clang precompiled header.
-class ClangAttrPCHReadEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
-public:
- explicit ClangAttrPCHReadEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-/// ClangAttrPCHWriteEmitter - class emits the code to read an attribute from
-/// a clang precompiled header.
-class ClangAttrPCHWriteEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
-public:
- explicit ClangAttrPCHWriteEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-/// ClangAttrSpellingListEmitter - class emits the list of spellings for attributes for
-/// clang.
-class ClangAttrSpellingListEmitter : public TableGenBackend {
- RecordKeeper &Records;
-
- public:
- explicit ClangAttrSpellingListEmitter(RecordKeeper &R)
- : Records(R)
- {}
-
- void run(raw_ostream &OS);
-};
-
-}
-
-#endif
diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp
deleted file mode 100644
index 0a48e75..0000000
--- a/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ /dev/null
@@ -1,362 +0,0 @@
-//=- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables -*- C++ -*-
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang diagnostics tables.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangDiagnosticsEmitter.h"
-#include "Record.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/VectorExtras.h"
-#include <map>
-#include <algorithm>
-#include <functional>
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Diagnostic category computation code.
-//===----------------------------------------------------------------------===//
-
-namespace {
-class DiagGroupParentMap {
- RecordKeeper &Records;
- std::map<const Record*, std::vector<Record*> > Mapping;
-public:
- DiagGroupParentMap(RecordKeeper &records) : Records(records) {
- std::vector<Record*> DiagGroups
- = Records.getAllDerivedDefinitions("DiagGroup");
- for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
- std::vector<Record*> SubGroups =
- DiagGroups[i]->getValueAsListOfDefs("SubGroups");
- for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
- Mapping[SubGroups[j]].push_back(DiagGroups[i]);
- }
- }
-
- const std::vector<Record*> &getParents(const Record *Group) {
- return Mapping[Group];
- }
-};
-} // end anonymous namespace.
-
-
-static std::string
-getCategoryFromDiagGroup(const Record *Group,
- DiagGroupParentMap &DiagGroupParents) {
- // If the DiagGroup has a category, return it.
- std::string CatName = Group->getValueAsString("CategoryName");
- if (!CatName.empty()) return CatName;
-
- // The diag group may the subgroup of one or more other diagnostic groups,
- // check these for a category as well.
- const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
- for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
- CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
- if (!CatName.empty()) return CatName;
- }
- return "";
-}
-
-/// getDiagnosticCategory - Return the category that the specified diagnostic
-/// lives in.
-static std::string getDiagnosticCategory(const Record *R,
- DiagGroupParentMap &DiagGroupParents) {
- // If the diagnostic is in a group, and that group has a category, use it.
- if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"))) {
- // Check the diagnostic's diag group for a category.
- std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
- DiagGroupParents);
- if (!CatName.empty()) return CatName;
- }
-
- // If the diagnostic itself has a category, get it.
- return R->getValueAsString("CategoryName");
-}
-
-namespace {
- class DiagCategoryIDMap {
- RecordKeeper &Records;
- StringMap<unsigned> CategoryIDs;
- std::vector<std::string> CategoryStrings;
- public:
- DiagCategoryIDMap(RecordKeeper &records) : Records(records) {
- DiagGroupParentMap ParentInfo(Records);
-
- // The zero'th category is "".
- CategoryStrings.push_back("");
- CategoryIDs[""] = 0;
-
- std::vector<Record*> Diags =
- Records.getAllDerivedDefinitions("Diagnostic");
- for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
- std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
- if (Category.empty()) continue; // Skip diags with no category.
-
- unsigned &ID = CategoryIDs[Category];
- if (ID != 0) continue; // Already seen.
-
- ID = CategoryStrings.size();
- CategoryStrings.push_back(Category);
- }
- }
-
- unsigned getID(StringRef CategoryString) {
- return CategoryIDs[CategoryString];
- }
-
- typedef std::vector<std::string>::iterator iterator;
- iterator begin() { return CategoryStrings.begin(); }
- iterator end() { return CategoryStrings.end(); }
- };
-} // end anonymous namespace.
-
-
-//===----------------------------------------------------------------------===//
-// Warning Tables (.inc file) generation.
-//===----------------------------------------------------------------------===//
-
-void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
- // Write the #if guard
- if (!Component.empty()) {
- std::string ComponentName = UppercaseString(Component);
- OS << "#ifdef " << ComponentName << "START\n";
- OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
- << ",\n";
- OS << "#undef " << ComponentName << "START\n";
- OS << "#endif\n\n";
- }
-
- const std::vector<Record*> &Diags =
- Records.getAllDerivedDefinitions("Diagnostic");
-
- DiagCategoryIDMap CategoryIDs(Records);
- DiagGroupParentMap DGParentMap(Records);
-
- for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
- const Record &R = *Diags[i];
- // Filter by component.
- if (!Component.empty() && Component != R.getValueAsString("Component"))
- continue;
-
- OS << "DIAG(" << R.getName() << ", ";
- OS << R.getValueAsDef("Class")->getName();
- OS << ", diag::" << R.getValueAsDef("DefaultMapping")->getName();
-
- // Description string.
- OS << ", \"";
- OS.write_escaped(R.getValueAsString("Text")) << '"';
-
- // Warning associated with the diagnostic.
- if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group"))) {
- OS << ", \"";
- OS.write_escaped(DI->getDef()->getValueAsString("GroupName")) << '"';
- } else {
- OS << ", \"\"";
- }
-
- // SFINAE bit
- if (R.getValueAsBit("SFINAE"))
- OS << ", true";
- else
- OS << ", false";
-
- // Access control bit
- if (R.getValueAsBit("AccessControl"))
- OS << ", true";
- else
- OS << ", false";
-
- // Category number.
- OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
-
- // Brief
- OS << ", \"";
- OS.write_escaped(R.getValueAsString("Brief")) << '"';
-
- // Explanation
- OS << ", \"";
- OS.write_escaped(R.getValueAsString("Explanation")) << '"';
- OS << ")\n";
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Warning Group Tables generation
-//===----------------------------------------------------------------------===//
-
-static std::string getDiagCategoryEnum(llvm::StringRef name) {
- if (name.empty())
- return "DiagCat_None";
- llvm::SmallString<256> enumName = llvm::StringRef("DiagCat_");
- for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
- enumName += isalnum(*I) ? *I : '_';
- return enumName.str();
-}
-
-namespace {
-struct GroupInfo {
- std::vector<const Record*> DiagsInGroup;
- std::vector<std::string> SubGroups;
- unsigned IDNo;
-};
-} // end anonymous namespace.
-
-void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
- // Compute a mapping from a DiagGroup to all of its parents.
- DiagGroupParentMap DGParentMap(Records);
-
- // Invert the 1-[0/1] mapping of diags to group into a one to many mapping of
- // groups to diags in the group.
- std::map<std::string, GroupInfo> DiagsInGroup;
-
- std::vector<Record*> Diags =
- Records.getAllDerivedDefinitions("Diagnostic");
- for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
- const Record *R = Diags[i];
- DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group"));
- if (DI == 0) continue;
- std::string GroupName = DI->getDef()->getValueAsString("GroupName");
- DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
- }
-
- // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
- // groups (these are warnings that GCC supports that clang never produces).
- std::vector<Record*> DiagGroups
- = Records.getAllDerivedDefinitions("DiagGroup");
- for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
- Record *Group = DiagGroups[i];
- GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
-
- std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
- for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
- GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
- }
-
- // Assign unique ID numbers to the groups.
- unsigned IDNo = 0;
- for (std::map<std::string, GroupInfo>::iterator
- I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
- I->second.IDNo = IDNo;
-
- // Walk through the groups emitting an array for each diagnostic of the diags
- // that are mapped to.
- OS << "\n#ifdef GET_DIAG_ARRAYS\n";
- unsigned MaxLen = 0;
- for (std::map<std::string, GroupInfo>::iterator
- I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
- MaxLen = std::max(MaxLen, (unsigned)I->first.size());
-
- std::vector<const Record*> &V = I->second.DiagsInGroup;
- if (!V.empty()) {
- OS << "static const short DiagArray" << I->second.IDNo << "[] = { ";
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- OS << "diag::" << V[i]->getName() << ", ";
- OS << "-1 };\n";
- }
-
- const std::vector<std::string> &SubGroups = I->second.SubGroups;
- if (!SubGroups.empty()) {
- OS << "static const short DiagSubGroup" << I->second.IDNo << "[] = { ";
- for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) {
- std::map<std::string, GroupInfo>::iterator RI =
- DiagsInGroup.find(SubGroups[i]);
- assert(RI != DiagsInGroup.end() && "Referenced without existing?");
- OS << RI->second.IDNo << ", ";
- }
- OS << "-1 };\n";
- }
- }
- OS << "#endif // GET_DIAG_ARRAYS\n\n";
-
- // Emit the table now.
- OS << "\n#ifdef GET_DIAG_TABLE\n";
- for (std::map<std::string, GroupInfo>::iterator
- I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
- // Group option string.
- OS << " { ";
- OS << I->first.size() << ", ";
- OS << "\"";
- OS.write_escaped(I->first) << "\","
- << std::string(MaxLen-I->first.size()+1, ' ');
-
- // Diagnostics in the group.
- if (I->second.DiagsInGroup.empty())
- OS << "0, ";
- else
- OS << "DiagArray" << I->second.IDNo << ", ";
-
- // Subgroups.
- if (I->second.SubGroups.empty())
- OS << 0;
- else
- OS << "DiagSubGroup" << I->second.IDNo;
- OS << " },\n";
- }
- OS << "#endif // GET_DIAG_TABLE\n\n";
-
- // Emit the category table next.
- DiagCategoryIDMap CategoriesByID(Records);
- OS << "\n#ifdef GET_CATEGORY_TABLE\n";
- for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(),
- E = CategoriesByID.end(); I != E; ++I)
- OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n";
- OS << "#endif // GET_CATEGORY_TABLE\n\n";
-}
-
-//===----------------------------------------------------------------------===//
-// Diagnostic name index generation
-//===----------------------------------------------------------------------===//
-
-namespace {
-struct RecordIndexElement
-{
- RecordIndexElement() {}
- explicit RecordIndexElement(Record const &R):
- Name(R.getName()) {}
-
- std::string Name;
-};
-
-struct RecordIndexElementSorter :
- public std::binary_function<RecordIndexElement, RecordIndexElement, bool> {
-
- bool operator()(RecordIndexElement const &Lhs,
- RecordIndexElement const &Rhs) const {
- return Lhs.Name < Rhs.Name;
- }
-
-};
-
-} // end anonymous namespace.
-
-void ClangDiagsIndexNameEmitter::run(raw_ostream &OS) {
- const std::vector<Record*> &Diags =
- Records.getAllDerivedDefinitions("Diagnostic");
-
- std::vector<RecordIndexElement> Index;
- Index.reserve(Diags.size());
- for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
- const Record &R = *(Diags[i]);
- Index.push_back(RecordIndexElement(R));
- }
-
- std::sort(Index.begin(), Index.end(), RecordIndexElementSorter());
-
- for (unsigned i = 0, e = Index.size(); i != e; ++i) {
- const RecordIndexElement &R = Index[i];
-
- OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
- }
-}
diff --git a/utils/TableGen/ClangDiagnosticsEmitter.h b/utils/TableGen/ClangDiagnosticsEmitter.h
deleted file mode 100644
index 1e4c8b7..0000000
--- a/utils/TableGen/ClangDiagnosticsEmitter.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- ClangDiagnosticsEmitter.h - Generate Clang diagnostics tables -*- C++ -*-
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// These tablegen backends emit Clang diagnostics tables.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANGDIAGS_EMITTER_H
-#define CLANGDIAGS_EMITTER_H
-
-#include "TableGenBackend.h"
-
-namespace llvm {
-
-/// ClangDiagsDefsEmitter - The top-level class emits .def files containing
-/// declarations of Clang diagnostics.
-///
-class ClangDiagsDefsEmitter : public TableGenBackend {
- RecordKeeper &Records;
- const std::string& Component;
-public:
- explicit ClangDiagsDefsEmitter(RecordKeeper &R, const std::string& component)
- : Records(R), Component(component) {}
-
- // run - Output the .def file contents
- void run(raw_ostream &OS);
-};
-
-class ClangDiagGroupsEmitter : public TableGenBackend {
- RecordKeeper &Records;
-public:
- explicit ClangDiagGroupsEmitter(RecordKeeper &R) : Records(R) {}
-
- void run(raw_ostream &OS);
-};
-
-class ClangDiagsIndexNameEmitter : public TableGenBackend {
- RecordKeeper &Records;
-public:
- explicit ClangDiagsIndexNameEmitter(RecordKeeper &R) : Records(R) {}
-
- void run(raw_ostream &OS);
-};
-
-
-} // End llvm namespace
-
-#endif
diff --git a/utils/TableGen/ClangSACheckersEmitter.cpp b/utils/TableGen/ClangSACheckersEmitter.cpp
deleted file mode 100644
index 97739c6..0000000
--- a/utils/TableGen/ClangSACheckersEmitter.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-//=- ClangSACheckersEmitter.cpp - Generate Clang SA checkers tables -*- C++ -*-
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This tablegen backend emits Clang Static Analyzer checkers tables.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangSACheckersEmitter.h"
-#include "Record.h"
-#include "llvm/ADT/DenseSet.h"
-#include <map>
-#include <string>
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Static Analyzer Checkers Tables generation
-//===----------------------------------------------------------------------===//
-
-/// \brief True if it is specified hidden or a parent package is specified
-/// as hidden, otherwise false.
-static bool isHidden(const Record &R) {
- if (R.getValueAsBit("Hidden"))
- return true;
- // Not declared as hidden, check the parent package if it is hidden.
- if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("ParentPackage")))
- return isHidden(*DI->getDef());
-
- return false;
-}
-
-static bool isCheckerNamed(const Record *R) {
- return !R->getValueAsString("CheckerName").empty();
-}
-
-static std::string getPackageFullName(const Record *R);
-
-static std::string getParentPackageFullName(const Record *R) {
- std::string name;
- if (DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("ParentPackage")))
- name = getPackageFullName(DI->getDef());
- return name;
-}
-
-static std::string getPackageFullName(const Record *R) {
- std::string name = getParentPackageFullName(R);
- if (!name.empty()) name += ".";
- return name + R->getValueAsString("PackageName");
-}
-
-static std::string getCheckerFullName(const Record *R) {
- std::string name = getParentPackageFullName(R);
- if (isCheckerNamed(R)) {
- if (!name.empty()) name += ".";
- name += R->getValueAsString("CheckerName");
- }
- return name;
-}
-
-static std::string getStringValue(const Record &R, StringRef field) {
- if (StringInit *
- SI = dynamic_cast<StringInit*>(R.getValueInit(field)))
- return SI->getValue();
- return std::string();
-}
-
-namespace {
-struct GroupInfo {
- llvm::DenseSet<const Record*> Checkers;
- llvm::DenseSet<const Record *> SubGroups;
- bool Hidden;
- unsigned Index;
-
- GroupInfo() : Hidden(false) { }
-};
-}
-
-static void addPackageToCheckerGroup(const Record *package, const Record *group,
- llvm::DenseMap<const Record *, GroupInfo *> &recordGroupMap) {
- llvm::DenseSet<const Record *> &checkers = recordGroupMap[package]->Checkers;
- for (llvm::DenseSet<const Record *>::iterator
- I = checkers.begin(), E = checkers.end(); I != E; ++I)
- recordGroupMap[group]->Checkers.insert(*I);
-
- llvm::DenseSet<const Record *> &subGroups = recordGroupMap[package]->SubGroups;
- for (llvm::DenseSet<const Record *>::iterator
- I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
- addPackageToCheckerGroup(*I, group, recordGroupMap);
-}
-
-void ClangSACheckersEmitter::run(raw_ostream &OS) {
- std::vector<Record*> checkers = Records.getAllDerivedDefinitions("Checker");
- llvm::DenseMap<const Record *, unsigned> checkerRecIndexMap;
- for (unsigned i = 0, e = checkers.size(); i != e; ++i)
- checkerRecIndexMap[checkers[i]] = i;
-
- // Invert the mapping of checkers to package/group into a one to many
- // mapping of packages/groups to checkers.
- std::map<std::string, GroupInfo> groupInfoByName;
- llvm::DenseMap<const Record *, GroupInfo *> recordGroupMap;
-
- std::vector<Record*> packages = Records.getAllDerivedDefinitions("Package");
- for (unsigned i = 0, e = packages.size(); i != e; ++i) {
- Record *R = packages[i];
- std::string fullName = getPackageFullName(R);
- if (!fullName.empty()) {
- GroupInfo &info = groupInfoByName[fullName];
- info.Hidden = isHidden(*R);
- recordGroupMap[R] = &info;
- }
- }
-
- std::vector<Record*>
- checkerGroups = Records.getAllDerivedDefinitions("CheckerGroup");
- for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i) {
- Record *R = checkerGroups[i];
- std::string name = R->getValueAsString("GroupName");
- if (!name.empty()) {
- GroupInfo &info = groupInfoByName[name];
- recordGroupMap[R] = &info;
- }
- }
-
- for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
- Record *R = checkers[i];
- Record *package = 0;
- if (DefInit *
- DI = dynamic_cast<DefInit*>(R->getValueInit("ParentPackage")))
- package = DI->getDef();
- if (!isCheckerNamed(R) && !package)
- throw "Checker '" + R->getName() + "' is neither named, nor in a package!";
-
- if (isCheckerNamed(R)) {
- // Create a pseudo-group to hold this checker.
- std::string fullName = getCheckerFullName(R);
- GroupInfo &info = groupInfoByName[fullName];
- info.Hidden = R->getValueAsBit("Hidden");
- recordGroupMap[R] = &info;
- info.Checkers.insert(R);
- } else {
- recordGroupMap[package]->Checkers.insert(R);
- }
-
- Record *currR = isCheckerNamed(R) ? R : package;
- // Insert the checker and its parent packages into the subgroups set of
- // the corresponding parent package.
- while (DefInit *DI
- = dynamic_cast<DefInit*>(currR->getValueInit("ParentPackage"))) {
- Record *parentPackage = DI->getDef();
- recordGroupMap[parentPackage]->SubGroups.insert(currR);
- currR = parentPackage;
- }
- // Insert the checker into the set of its group.
- if (DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group")))
- recordGroupMap[DI->getDef()]->Checkers.insert(R);
- }
-
- // If a package is in group, add all its checkers and its sub-packages
- // checkers into the group.
- for (unsigned i = 0, e = packages.size(); i != e; ++i)
- if (DefInit *DI = dynamic_cast<DefInit*>(packages[i]->getValueInit("Group")))
- addPackageToCheckerGroup(packages[i], DI->getDef(), recordGroupMap);
-
- typedef std::map<std::string, const Record *> SortedRecords;
- typedef llvm::DenseMap<const Record *, unsigned> RecToSortIndex;
-
- SortedRecords sortedGroups;
- RecToSortIndex groupToSortIndex;
- OS << "\n#ifdef GET_GROUPS\n";
- {
- for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i)
- sortedGroups[checkerGroups[i]->getValueAsString("GroupName")]
- = checkerGroups[i];
-
- unsigned sortIndex = 0;
- for (SortedRecords::iterator
- I = sortedGroups.begin(), E = sortedGroups.end(); I != E; ++I) {
- const Record *R = I->second;
-
- OS << "GROUP(" << "\"";
- OS.write_escaped(R->getValueAsString("GroupName")) << "\"";
- OS << ")\n";
-
- groupToSortIndex[R] = sortIndex++;
- }
- }
- OS << "#endif // GET_GROUPS\n\n";
-
- OS << "\n#ifdef GET_PACKAGES\n";
- {
- SortedRecords sortedPackages;
- for (unsigned i = 0, e = packages.size(); i != e; ++i)
- sortedPackages[getPackageFullName(packages[i])] = packages[i];
-
- for (SortedRecords::iterator
- I = sortedPackages.begin(), E = sortedPackages.end(); I != E; ++I) {
- const Record &R = *I->second;
-
- OS << "PACKAGE(" << "\"";
- OS.write_escaped(getPackageFullName(&R)) << "\", ";
- // Group index
- if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
- OS << groupToSortIndex[DI->getDef()] << ", ";
- else
- OS << "-1, ";
- // Hidden bit
- if (isHidden(R))
- OS << "true";
- else
- OS << "false";
- OS << ")\n";
- }
- }
- OS << "#endif // GET_PACKAGES\n\n";
-
- OS << "\n#ifdef GET_CHECKERS\n";
- for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
- const Record &R = *checkers[i];
-
- OS << "CHECKER(" << "\"";
- std::string name;
- if (isCheckerNamed(&R))
- name = getCheckerFullName(&R);
- OS.write_escaped(name) << "\", ";
- OS << R.getName() << ", ";
- OS << getStringValue(R, "DescFile") << ", ";
- OS << "\"";
- OS.write_escaped(getStringValue(R, "HelpText")) << "\", ";
- // Group index
- if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
- OS << groupToSortIndex[DI->getDef()] << ", ";
- else
- OS << "-1, ";
- // Hidden bit
- if (isHidden(R))
- OS << "true";
- else
- OS << "false";
- OS << ")\n";
- }
- OS << "#endif // GET_CHECKERS\n\n";
-
- unsigned index = 0;
- for (std::map<std::string, GroupInfo>::iterator
- I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I)
- I->second.Index = index++;
-
- // Walk through the packages/groups/checkers emitting an array for each
- // set of checkers and an array for each set of subpackages.
-
- OS << "\n#ifdef GET_MEMBER_ARRAYS\n";
- unsigned maxLen = 0;
- for (std::map<std::string, GroupInfo>::iterator
- I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
- maxLen = std::max(maxLen, (unsigned)I->first.size());
-
- llvm::DenseSet<const Record *> &checkers = I->second.Checkers;
- if (!checkers.empty()) {
- OS << "static const short CheckerArray" << I->second.Index << "[] = { ";
- // Make the output order deterministic.
- std::map<int, const Record *> sorted;
- for (llvm::DenseSet<const Record *>::iterator
- I = checkers.begin(), E = checkers.end(); I != E; ++I)
- sorted[(*I)->getID()] = *I;
-
- for (std::map<int, const Record *>::iterator
- I = sorted.begin(), E = sorted.end(); I != E; ++I)
- OS << checkerRecIndexMap[I->second] << ", ";
- OS << "-1 };\n";
- }
-
- llvm::DenseSet<const Record *> &subGroups = I->second.SubGroups;
- if (!subGroups.empty()) {
- OS << "static const short SubPackageArray" << I->second.Index << "[] = { ";
- // Make the output order deterministic.
- std::map<int, const Record *> sorted;
- for (llvm::DenseSet<const Record *>::iterator
- I = subGroups.begin(), E = subGroups.end(); I != E; ++I)
- sorted[(*I)->getID()] = *I;
-
- for (std::map<int, const Record *>::iterator
- I = sorted.begin(), E = sorted.end(); I != E; ++I) {
- OS << recordGroupMap[I->second]->Index << ", ";
- }
- OS << "-1 };\n";
- }
- }
- OS << "#endif // GET_MEMBER_ARRAYS\n\n";
-
- OS << "\n#ifdef GET_CHECKNAME_TABLE\n";
- for (std::map<std::string, GroupInfo>::iterator
- I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) {
- // Group option string.
- OS << " { \"";
- OS.write_escaped(I->first) << "\","
- << std::string(maxLen-I->first.size()+1, ' ');
-
- if (I->second.Checkers.empty())
- OS << "0, ";
- else
- OS << "CheckerArray" << I->second.Index << ", ";
-
- // Subgroups.
- if (I->second.SubGroups.empty())
- OS << "0, ";
- else
- OS << "SubPackageArray" << I->second.Index << ", ";
-
- OS << (I->second.Hidden ? "true" : "false");
-
- OS << " },\n";
- }
- OS << "#endif // GET_CHECKNAME_TABLE\n\n";
-}
diff --git a/utils/TableGen/ClangSACheckersEmitter.h b/utils/TableGen/ClangSACheckersEmitter.h
deleted file mode 100644
index 6bd1635..0000000
--- a/utils/TableGen/ClangSACheckersEmitter.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- ClangSACheckersEmitter.h - Generate Clang SA checkers tables -*- C++ -*-
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This tablegen backend emits Clang Static Analyzer checkers tables.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANGSACHECKERS_EMITTER_H
-#define CLANGSACHECKERS_EMITTER_H
-
-#include "TableGenBackend.h"
-
-namespace llvm {
-
-class ClangSACheckersEmitter : public TableGenBackend {
- RecordKeeper &Records;
-public:
- explicit ClangSACheckersEmitter(RecordKeeper &R) : Records(R) {}
-
- void run(raw_ostream &OS);
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index d828dfc..c5a1526 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -15,7 +15,7 @@
#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -41,19 +41,23 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
BitsInit *BI = R->getValueAsBitsInit("Inst");
unsigned numBits = BI->getNumBits();
- BitsInit *NewBI = new BitsInit(numBits);
+
+ SmallVector<Init *, 16> NewBits(numBits);
+
for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
unsigned bitSwapIdx = numBits - bit - 1;
Init *OrigBit = BI->getBit(bit);
Init *BitSwap = BI->getBit(bitSwapIdx);
- NewBI->setBit(bit, BitSwap);
- NewBI->setBit(bitSwapIdx, OrigBit);
+ NewBits[bit] = BitSwap;
+ NewBits[bitSwapIdx] = OrigBit;
}
if (numBits % 2) {
unsigned middle = (numBits + 1) / 2;
- NewBI->setBit(middle, BI->getBit(middle));
+ NewBits[middle] = BI->getBit(middle);
}
+ BitsInit *NewBI = BitsInit::get(NewBits);
+
// Update the bits in reversed order so that emitInstrOpBits will get the
// correct endianness.
R->getValue("Inst")->setValue(NewBI);
diff --git a/utils/TableGen/CodeEmitterGen.h b/utils/TableGen/CodeEmitterGen.h
index a874d97..7f6ee2a 100644
--- a/utils/TableGen/CodeEmitterGen.h
+++ b/utils/TableGen/CodeEmitterGen.h
@@ -14,7 +14,7 @@
#ifndef CODEMITTERGEN_H
#define CODEMITTERGEN_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
#include <string>
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 072893f..dbf1662 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
#include "CodeGenDAGPatterns.h"
-#include "Error.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
@@ -1747,9 +1747,10 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
// TreePatternNode of its own. For example:
/// (foo GPR, imm) -> (foo GPR, (imm))
if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag"))
- return ParseTreePattern(new DagInit(DI, "",
- std::vector<std::pair<Init*, std::string> >()),
- OpName);
+ return ParseTreePattern(
+ DagInit::get(DI, "",
+ std::vector<std::pair<Init*, std::string> >()),
+ OpName);
// Input argument?
TreePatternNode *Res = new TreePatternNode(DI, 1);
@@ -1771,7 +1772,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
if (BitsInit *BI = dynamic_cast<BitsInit*>(TheInit)) {
// Turn this into an IntInit.
- Init *II = BI->convertInitializerTo(new IntRecTy());
+ Init *II = BI->convertInitializerTo(IntRecTy::get());
if (II == 0 || !dynamic_cast<IntInit*>(II))
error("Bits value must be constants!");
return ParseTreePattern(II, OpName);
@@ -1860,7 +1861,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
else // Otherwise, no chain.
Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode();
- TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID), 1);
+ TreePatternNode *IIDNode = new TreePatternNode(IntInit::get(IID), 1);
Children.insert(Children.begin(), IIDNode);
}
@@ -2180,7 +2181,7 @@ void CodeGenDAGPatterns::ParseDefaultOperands() {
// Find some SDNode.
assert(!SDNodes.empty() && "No SDNodes parsed?");
- Init *SomeSDNode = new DefInit(SDNodes.begin()->first);
+ Init *SomeSDNode = DefInit::get(SDNodes.begin()->first);
for (unsigned iter = 0; iter != 2; ++iter) {
for (unsigned i = 0, e = DefaultOps[iter].size(); i != e; ++i) {
@@ -2192,7 +2193,7 @@ void CodeGenDAGPatterns::ParseDefaultOperands() {
for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op)
Ops.push_back(std::make_pair(DefaultInfo->getArg(op),
DefaultInfo->getArgName(op)));
- DagInit *DI = new DagInit(SomeSDNode, "", Ops);
+ DagInit *DI = DagInit::get(SomeSDNode, "", Ops);
// Create a TreePattern to parse this.
TreePattern P(DefaultOps[iter][i], DI, false, *this);
@@ -2828,6 +2829,12 @@ void CodeGenDAGPatterns::InferInstructionFlags() {
InstInfo.isBitcast = IsBitcast;
InstInfo.hasSideEffects = HasSideEffects;
InstInfo.Operands.isVariadic = IsVariadic;
+
+ // Sanity checks.
+ if (InstInfo.isReMaterializable && InstInfo.hasSideEffects)
+ throw TGError(InstInfo.TheDef->getLoc(), "The instruction " +
+ InstInfo.TheDef->getName() +
+ " is rematerializable AND has unmodeled side effects?");
}
}
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index a52ce86..53d499f 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -13,8 +13,8 @@
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
-#include "Error.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/STLExtras.h"
@@ -267,8 +267,9 @@ static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops) {
void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) {
while (1) {
- std::string OpName;
- tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t");
+ std::pair<StringRef, StringRef> P = getToken(DisableEncoding, " ,\t");
+ std::string OpName = P.first;
+ DisableEncoding = P.second;
if (OpName.empty()) break;
// Figure out which operand this is.
@@ -308,6 +309,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) {
isReMaterializable = R->getValueAsBit("isReMaterializable");
hasDelaySlot = R->getValueAsBit("hasDelaySlot");
usesCustomInserter = R->getValueAsBit("usesCustomInserter");
+ hasPostISelHook = R->getValueAsBit("hasPostISelHook");
hasCtrlDep = R->getValueAsBit("hasCtrlDep");
isNotDuplicable = R->getValueAsBit("isNotDuplicable");
hasSideEffects = R->getValueAsBit("hasSideEffects");
@@ -423,6 +425,13 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
// Handle explicit registers.
if (ADI && ADI->getDef()->isSubClassOf("Register")) {
+ if (InstOpRec->isSubClassOf("OptionalDefOperand")) {
+ DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo");
+ // The operand info should only have a single (register) entry. We
+ // want the register class of it.
+ InstOpRec = dynamic_cast<DefInit*>(DI->getArg(0))->getDef();
+ }
+
if (InstOpRec->isSubClassOf("RegisterOperand"))
InstOpRec = InstOpRec->getValueAsDef("RegClass");
@@ -431,8 +440,8 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
if (!T.getRegisterClass(InstOpRec)
.contains(T.getRegBank().getReg(ADI->getDef())))
- throw TGError(Loc, "fixed register " +ADI->getDef()->getName()
- + " is not a member of the " + InstOpRec->getName() +
+ throw TGError(Loc, "fixed register " + ADI->getDef()->getName() +
+ " is not a member of the " + InstOpRec->getName() +
" register class!");
if (!Result->getArgName(AliasOpNo).empty())
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index 8d7669a..468277a 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -233,6 +233,7 @@ namespace llvm {
bool isReMaterializable;
bool hasDelaySlot;
bool usesCustomInserter;
+ bool hasPostISelHook;
bool hasCtrlDep;
bool isNotDuplicable;
bool hasSideEffects;
diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp
index 1acf3a8..8de4615 100644
--- a/utils/TableGen/CodeGenRegisters.cpp
+++ b/utils/TableGen/CodeGenRegisters.cpp
@@ -14,8 +14,9 @@
#include "CodeGenRegisters.h"
#include "CodeGenTarget.h"
-#include "Error.h"
+#include "llvm/TableGen/Error.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
@@ -182,8 +183,8 @@ struct TupleExpander : SetTheory::Expander {
// Precompute some types.
Record *RegisterCl = Def->getRecords().getClass("Register");
- RecTy *RegisterRecTy = new RecordRecTy(RegisterCl);
- StringInit *BlankName = new StringInit("");
+ RecTy *RegisterRecTy = RecordRecTy::get(RegisterCl);
+ StringInit *BlankName = StringInit::get("");
// Zip them up.
for (unsigned n = 0; n != Length; ++n) {
@@ -195,7 +196,7 @@ struct TupleExpander : SetTheory::Expander {
Record *Reg = Lists[i][n];
if (i) Name += '_';
Name += Reg->getName();
- Tuple.push_back(new DefInit(Reg));
+ Tuple.push_back(DefInit::get(Reg));
CostPerUse = std::max(CostPerUse,
unsigned(Reg->getValueAsInt("CostPerUse")));
}
@@ -216,7 +217,7 @@ struct TupleExpander : SetTheory::Expander {
// Replace the sub-register list with Tuple.
if (RV.getName() == "SubRegs")
- RV.setValue(new ListInit(Tuple, RegisterRecTy));
+ RV.setValue(ListInit::get(Tuple, RegisterRecTy));
// Provide a blank AsmName. MC hacks are required anyway.
if (RV.getName() == "AsmName")
@@ -224,7 +225,7 @@ struct TupleExpander : SetTheory::Expander {
// CostPerUse is aggregated from all Tuple members.
if (RV.getName() == "CostPerUse")
- RV.setValue(new IntInit(CostPerUse));
+ RV.setValue(IntInit::get(CostPerUse));
// Copy fields from the RegisterTuples def.
if (RV.getName() == "SubRegIndices" ||
@@ -255,7 +256,7 @@ struct TupleExpander : SetTheory::Expander {
//===----------------------------------------------------------------------===//
CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
- : TheDef(R) {
+ : TheDef(R), Name(R->getName()), EnumValue(-1) {
// Rename anonymous register classes.
if (R->getName().size() > 9 && R->getName()[9] == '.') {
static unsigned AnonCounter = 0;
@@ -272,18 +273,22 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
}
assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!");
+ // Allocation order 0 is the full set. AltOrders provides others.
+ const SetTheory::RecVec *Elements = RegBank.getSets().expand(R);
+ ListInit *AltOrders = R->getValueAsListInit("AltOrders");
+ Orders.resize(1 + AltOrders->size());
+
// Default allocation order always contains all registers.
- Elements = RegBank.getSets().expand(R);
- for (unsigned i = 0, e = Elements->size(); i != e; ++i)
+ for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
+ Orders[0].push_back((*Elements)[i]);
Members.insert(RegBank.getReg((*Elements)[i]));
+ }
// Alternative allocation orders may be subsets.
- ListInit *Alts = R->getValueAsListInit("AltOrders");
- AltOrders.resize(Alts->size());
SetTheory::RecSet Order;
- for (unsigned i = 0, e = Alts->size(); i != e; ++i) {
- RegBank.getSets().evaluate(Alts->getElement(i), Order);
- AltOrders[i].append(Order.begin(), Order.end());
+ for (unsigned i = 0, e = AltOrders->size(); i != e; ++i) {
+ RegBank.getSets().evaluate(AltOrders->getElement(i), Order);
+ Orders[1 + i].append(Order.begin(), Order.end());
// Verify that all altorder members are regclass members.
while (!Order.empty()) {
CodeGenRegister *Reg = RegBank.getReg(Order.back());
@@ -328,10 +333,71 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
AltOrderSelect = R->getValueAsCode("AltOrderSelect");
}
+// Create an inferred register class that was missing from the .td files.
+// Most properties will be inherited from the closest super-class after the
+// class structure has been computed.
+CodeGenRegisterClass::CodeGenRegisterClass(StringRef Name, Key Props)
+ : Members(*Props.Members),
+ TheDef(0),
+ Name(Name),
+ EnumValue(-1),
+ SpillSize(Props.SpillSize),
+ SpillAlignment(Props.SpillAlignment),
+ CopyCost(0),
+ Allocatable(true) {
+}
+
+// Compute inherited propertied for a synthesized register class.
+void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
+ assert(!getDef() && "Only synthesized classes can inherit properties");
+ assert(!SuperClasses.empty() && "Synthesized class without super class");
+
+ // The last super-class is the smallest one.
+ CodeGenRegisterClass &Super = *SuperClasses.back();
+
+ // Most properties are copied directly.
+ // Exceptions are members, size, and alignment
+ Namespace = Super.Namespace;
+ VTs = Super.VTs;
+ CopyCost = Super.CopyCost;
+ Allocatable = Super.Allocatable;
+ AltOrderSelect = Super.AltOrderSelect;
+
+ // Copy all allocation orders, filter out foreign registers from the larger
+ // super-class.
+ Orders.resize(Super.Orders.size());
+ for (unsigned i = 0, ie = Super.Orders.size(); i != ie; ++i)
+ for (unsigned j = 0, je = Super.Orders[i].size(); j != je; ++j)
+ if (contains(RegBank.getReg(Super.Orders[i][j])))
+ Orders[i].push_back(Super.Orders[i][j]);
+}
+
bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
return Members.count(Reg);
}
+namespace llvm {
+ raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
+ OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment;
+ for (CodeGenRegister::Set::const_iterator I = K.Members->begin(),
+ E = K.Members->end(); I != E; ++I)
+ OS << ", " << (*I)->getName();
+ return OS << " }";
+ }
+}
+
+// This is a simple lexicographical order that can be used to search for sets.
+// It is not the same as the topological order provided by TopoOrderRC.
+bool CodeGenRegisterClass::Key::
+operator<(const CodeGenRegisterClass::Key &B) const {
+ assert(Members && B.Members);
+ if (*Members != *B.Members)
+ return *Members < *B.Members;
+ if (SpillSize != B.SpillSize)
+ return SpillSize < B.SpillSize;
+ return SpillAlignment < B.SpillAlignment;
+}
+
// Returns true if RC is a strict subclass.
// RC is a sub-class of this class if it is a valid replacement for any
// instruction operand where a register of this classis required. It must
@@ -341,16 +407,101 @@ bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
// 2. The RC spill size must not be smaller than our spill size.
// 3. RC spill alignment must be compatible with ours.
//
-bool CodeGenRegisterClass::hasSubClass(const CodeGenRegisterClass *RC) const {
- return SpillAlignment && RC->SpillAlignment % SpillAlignment == 0 &&
- SpillSize <= RC->SpillSize &&
- std::includes(Members.begin(), Members.end(),
- RC->Members.begin(), RC->Members.end(),
+static bool testSubClass(const CodeGenRegisterClass *A,
+ const CodeGenRegisterClass *B) {
+ return A->SpillAlignment && B->SpillAlignment % A->SpillAlignment == 0 &&
+ A->SpillSize <= B->SpillSize &&
+ std::includes(A->getMembers().begin(), A->getMembers().end(),
+ B->getMembers().begin(), B->getMembers().end(),
CodeGenRegister::Less());
}
-const std::string &CodeGenRegisterClass::getName() const {
- return TheDef->getName();
+/// Sorting predicate for register classes. This provides a topological
+/// ordering that arranges all register classes before their sub-classes.
+///
+/// Register classes with the same registers, spill size, and alignment form a
+/// clique. They will be ordered alphabetically.
+///
+static int TopoOrderRC(const void *PA, const void *PB) {
+ const CodeGenRegisterClass *A = *(const CodeGenRegisterClass* const*)PA;
+ const CodeGenRegisterClass *B = *(const CodeGenRegisterClass* const*)PB;
+ if (A == B)
+ return 0;
+
+ // Order by descending set size. Note that the classes' allocation order may
+ // not have been computed yet. The Members set is always vaild.
+ if (A->getMembers().size() > B->getMembers().size())
+ return -1;
+ if (A->getMembers().size() < B->getMembers().size())
+ return 1;
+
+ // Order by ascending spill size.
+ if (A->SpillSize < B->SpillSize)
+ return -1;
+ if (A->SpillSize > B->SpillSize)
+ return 1;
+
+ // Order by ascending spill alignment.
+ if (A->SpillAlignment < B->SpillAlignment)
+ return -1;
+ if (A->SpillAlignment > B->SpillAlignment)
+ return 1;
+
+ // Finally order by name as a tie breaker.
+ return A->getName() < B->getName();
+}
+
+std::string CodeGenRegisterClass::getQualifiedName() const {
+ if (Namespace.empty())
+ return getName();
+ else
+ return Namespace + "::" + getName();
+}
+
+// Compute sub-classes of all register classes.
+// Assume the classes are ordered topologically.
+void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
+ ArrayRef<CodeGenRegisterClass*> RegClasses = RegBank.getRegClasses();
+
+ // Visit backwards so sub-classes are seen first.
+ for (unsigned rci = RegClasses.size(); rci; --rci) {
+ CodeGenRegisterClass &RC = *RegClasses[rci - 1];
+ RC.SubClasses.resize(RegClasses.size());
+ RC.SubClasses.set(RC.EnumValue);
+
+ // Normally, all subclasses have IDs >= rci, unless RC is part of a clique.
+ for (unsigned s = rci; s != RegClasses.size(); ++s) {
+ if (RC.SubClasses.test(s))
+ continue;
+ CodeGenRegisterClass *SubRC = RegClasses[s];
+ if (!testSubClass(&RC, SubRC))
+ continue;
+ // SubRC is a sub-class. Grap all its sub-classes so we won't have to
+ // check them again.
+ RC.SubClasses |= SubRC->SubClasses;
+ }
+
+ // Sweep up missed clique members. They will be immediately preceeding RC.
+ for (unsigned s = rci - 1; s && testSubClass(&RC, RegClasses[s - 1]); --s)
+ RC.SubClasses.set(s - 1);
+ }
+
+ // Compute the SuperClasses lists from the SubClasses vectors.
+ for (unsigned rci = 0; rci != RegClasses.size(); ++rci) {
+ const BitVector &SC = RegClasses[rci]->getSubClasses();
+ for (int s = SC.find_first(); s >= 0; s = SC.find_next(s)) {
+ if (unsigned(s) == rci)
+ continue;
+ RegClasses[s]->SuperClasses.push_back(RegClasses[rci]);
+ }
+ }
+
+ // With the class hierarchy in place, let synthesized register classes inherit
+ // properties from their closest super-class. The iteration order here can
+ // propagate properties down multiple levels.
+ for (unsigned rci = 0; rci != RegClasses.size(); ++rci)
+ if (!RegClasses[rci]->getDef())
+ RegClasses[rci]->inheritProperties(RegBank);
}
//===----------------------------------------------------------------------===//
@@ -385,14 +536,29 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) {
getReg((*TupRegs)[j]);
}
+ // Precompute all sub-register maps now all the registers are known.
+ // This will create Composite entries for all inferred sub-register indices.
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i)
+ Registers[i]->getSubRegs(*this);
+
// Read in register class definitions.
std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass");
if (RCs.empty())
throw std::string("No 'RegisterClass' subclasses defined!");
+ // Allocate user-defined register classes.
RegClasses.reserve(RCs.size());
for (unsigned i = 0, e = RCs.size(); i != e; ++i)
- RegClasses.push_back(CodeGenRegisterClass(*this, RCs[i]));
+ addToMaps(new CodeGenRegisterClass(*this, RCs[i]));
+
+ // Infer missing classes to create a full algebra.
+ computeInferredRegisterClasses();
+
+ // Order register classes topologically and assign enum values.
+ array_pod_sort(RegClasses.begin(), RegClasses.end(), TopoOrderRC);
+ for (unsigned i = 0, e = RegClasses.size(); i != e; ++i)
+ RegClasses[i]->EnumValue = i;
+ CodeGenRegisterClass::computeSubClasses(*this);
}
CodeGenRegister *CodeGenRegBank::getReg(Record *Def) {
@@ -404,11 +570,19 @@ CodeGenRegister *CodeGenRegBank::getReg(Record *Def) {
return Reg;
}
-CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) {
- if (Def2RC.empty())
- for (unsigned i = 0, e = RegClasses.size(); i != e; ++i)
- Def2RC[RegClasses[i].TheDef] = &RegClasses[i];
+void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
+ RegClasses.push_back(RC);
+ if (Record *Def = RC->getDef())
+ Def2RC.insert(std::make_pair(Def, RC));
+
+ // Duplicate classes are rejected by insert().
+ // That's OK, we only care about the properties handled by CGRC::Key.
+ CodeGenRegisterClass::Key K(*RC);
+ Key2RC.insert(std::make_pair(K, RC));
+}
+
+CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) {
if (CodeGenRegisterClass *RC = Def2RC[Def])
return RC;
@@ -425,7 +599,6 @@ Record *CodeGenRegBank::getCompositeSubRegIndex(Record *A, Record *B,
// None exists, synthesize one.
std::string Name = A->getName() + "_then_" + B->getName();
Comp = new Record(Name, SMLoc(), Records);
- Records.addDef(Comp);
SubRegIndices.push_back(Comp);
return Comp;
}
@@ -438,11 +611,6 @@ unsigned CodeGenRegBank::getSubRegIndexNo(Record *idx) {
}
void CodeGenRegBank::computeComposites() {
- // Precompute all sub-register maps. This will create Composite entries for
- // all inferred sub-register indices.
- for (unsigned i = 0, e = Registers.size(); i != e; ++i)
- Registers[i]->getSubRegs(*this);
-
for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
CodeGenRegister *Reg1 = Registers[i];
const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs();
@@ -571,6 +739,64 @@ void CodeGenRegBank::computeDerivedInfo() {
computeComposites();
}
+// Infer missing register classes.
+//
+// For every register class RC, make sure that the set of registers in RC with
+// a given SubIxx sub-register form a register class.
+void CodeGenRegBank::computeInferredRegisterClasses() {
+ // When this function is called, the register classes have not been sorted
+ // and assigned EnumValues yet. That means getSubClasses(),
+ // getSuperClasses(), and hasSubClass() functions are defunct.
+
+ // Map SubRegIndex to register set.
+ typedef std::map<Record*, CodeGenRegister::Set, LessRecord> SubReg2SetMap;
+
+ // Visit all register classes, including the ones being added by the loop.
+ for (unsigned rci = 0; rci != RegClasses.size(); ++rci) {
+ CodeGenRegisterClass &RC = *RegClasses[rci];
+
+ // Compute the set of registers supporting each SubRegIndex.
+ SubReg2SetMap SRSets;
+ for (CodeGenRegister::Set::const_iterator RI = RC.getMembers().begin(),
+ RE = RC.getMembers().end(); RI != RE; ++RI) {
+ const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs();
+ for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
+ E = SRM.end(); I != E; ++I)
+ SRSets[I->first].insert(*RI);
+ }
+
+ // Find matching classes for all SRSets entries. Iterate in SubRegIndex
+ // numerical order to visit synthetic indices last.
+ for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
+ Record *SubIdx = SubRegIndices[sri];
+ SubReg2SetMap::const_iterator I = SRSets.find(SubIdx);
+ // Unsupported SubRegIndex. Skip it.
+ if (I == SRSets.end())
+ continue;
+ // In most cases, all RC registers support the SubRegIndex.
+ if (I->second.size() == RC.getMembers().size()) {
+ RC.setSubClassWithSubReg(SubIdx, &RC);
+ continue;
+ }
+
+ // This is a real subset. See if we have a matching class.
+ CodeGenRegisterClass::Key K(&I->second, RC.SpillSize, RC.SpillAlignment);
+ RCKeyMap::const_iterator FoundI = Key2RC.find(K);
+ if (FoundI != Key2RC.end()) {
+ RC.setSubClassWithSubReg(SubIdx, FoundI->second);
+ continue;
+ }
+
+ // Class doesn't exist.
+ CodeGenRegisterClass *NewRC =
+ new CodeGenRegisterClass(RC.getName() + "_with_" +
+ I->first->getName(), K);
+ addToMaps(NewRC);
+ RC.setSubClassWithSubReg(SubIdx, NewRC);
+ }
+ }
+}
+
/// getRegisterClassForRegister - Find the register class that contains the
/// specified physical register. If the register is not in a register class,
/// return null. If the register is in multiple classes, and the classes have a
@@ -579,10 +805,10 @@ void CodeGenRegBank::computeDerivedInfo() {
const CodeGenRegisterClass*
CodeGenRegBank::getRegClassForRegister(Record *R) {
const CodeGenRegister *Reg = getReg(R);
- const std::vector<CodeGenRegisterClass> &RCs = getRegClasses();
+ ArrayRef<CodeGenRegisterClass*> RCs = getRegClasses();
const CodeGenRegisterClass *FoundRC = 0;
for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RCs[i];
+ const CodeGenRegisterClass &RC = *RCs[i];
if (!RC.contains(Reg))
continue;
diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h
index 5edbf47..4fc34b0 100644
--- a/utils/TableGen/CodeGenRegisters.h
+++ b/utils/TableGen/CodeGenRegisters.h
@@ -15,10 +15,11 @@
#ifndef CODEGEN_REGISTERS_H
#define CODEGEN_REGISTERS_H
-#include "Record.h"
#include "SetTheory.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include <cstdlib>
@@ -69,6 +70,7 @@ namespace llvm {
struct Less {
bool operator()(const CodeGenRegister *A,
const CodeGenRegister *B) const {
+ assert(A && B);
return A->EnumValue < B->EnumValue;
}
};
@@ -85,10 +87,25 @@ namespace llvm {
class CodeGenRegisterClass {
CodeGenRegister::Set Members;
- const std::vector<Record*> *Elements;
- std::vector<SmallVector<Record*, 16> > AltOrders;
- public:
+ // Allocation orders. Order[0] always contains all registers in Members.
+ std::vector<SmallVector<Record*, 16> > Orders;
+ // Bit mask of sub-classes including this, indexed by their EnumValue.
+ BitVector SubClasses;
+ // List of super-classes, topologocally ordered to have the larger classes
+ // first. This is the same as sorting by EnumValue.
+ SmallVector<CodeGenRegisterClass*, 4> SuperClasses;
Record *TheDef;
+ std::string Name;
+
+ // For a synthesized class, inherit missing properties from the nearest
+ // super-class.
+ void inheritProperties(CodeGenRegBank&);
+
+ // Map SubRegIndex -> sub-class
+ DenseMap<Record*, CodeGenRegisterClass*> SubClassWithSubReg;
+
+ public:
+ unsigned EnumValue;
std::string Namespace;
std::vector<MVT::SimpleValueType> VTs;
unsigned SpillSize;
@@ -99,7 +116,12 @@ namespace llvm {
DenseMap<Record*,Record*> SubRegClasses;
std::string AltOrderSelect;
- const std::string &getName() const;
+ // Return the Record that defined this class, or NULL if the class was
+ // created by TableGen.
+ Record *getDef() const { return TheDef; }
+
+ const std::string &getName() const { return Name; }
+ std::string getQualifiedName() const;
const std::vector<MVT::SimpleValueType> &getValueTypes() const {return VTs;}
unsigned getNumValueTypes() const { return VTs.size(); }
@@ -122,22 +144,77 @@ namespace llvm {
// 2. The RC spill size must not be smaller than our spill size.
// 3. RC spill alignment must be compatible with ours.
//
- bool hasSubClass(const CodeGenRegisterClass *RC) const;
+ bool hasSubClass(const CodeGenRegisterClass *RC) const {
+ return SubClasses.test(RC->EnumValue);
+ }
+
+ // getSubClassWithSubReg - Returns the largest sub-class where all
+ // registers have a SubIdx sub-register.
+ CodeGenRegisterClass *getSubClassWithSubReg(Record *SubIdx) const {
+ return SubClassWithSubReg.lookup(SubIdx);
+ }
+
+ void setSubClassWithSubReg(Record *SubIdx, CodeGenRegisterClass *SubRC) {
+ SubClassWithSubReg[SubIdx] = SubRC;
+ }
+
+ // getSubClasses - Returns a constant BitVector of subclasses indexed by
+ // EnumValue.
+ // The SubClasses vector includs an entry for this class.
+ const BitVector &getSubClasses() const { return SubClasses; }
+
+ // getSuperClasses - Returns a list of super classes ordered by EnumValue.
+ // The array does not include an entry for this class.
+ ArrayRef<CodeGenRegisterClass*> getSuperClasses() const {
+ return SuperClasses;
+ }
// Returns an ordered list of class members.
// The order of registers is the same as in the .td file.
// No = 0 is the default allocation order, No = 1 is the first alternative.
ArrayRef<Record*> getOrder(unsigned No = 0) const {
- if (No == 0)
- return *Elements;
- else
- return AltOrders[No - 1];
+ return Orders[No];
}
// Return the total number of allocation orders available.
- unsigned getNumOrders() const { return 1 + AltOrders.size(); }
+ unsigned getNumOrders() const { return Orders.size(); }
+
+ // Get the set of registers. This set contains the same registers as
+ // getOrder(0).
+ const CodeGenRegister::Set &getMembers() const { return Members; }
CodeGenRegisterClass(CodeGenRegBank&, Record *R);
+
+ // A key representing the parts of a register class used for forming
+ // sub-classes. Note the ordering provided by this key is not the same as
+ // the topological order used for the EnumValues.
+ struct Key {
+ const CodeGenRegister::Set *Members;
+ unsigned SpillSize;
+ unsigned SpillAlignment;
+
+ Key(const Key &O)
+ : Members(O.Members),
+ SpillSize(O.SpillSize),
+ SpillAlignment(O.SpillAlignment) {}
+
+ Key(const CodeGenRegister::Set *M, unsigned S = 0, unsigned A = 0)
+ : Members(M), SpillSize(S), SpillAlignment(A) {}
+
+ Key(const CodeGenRegisterClass &RC)
+ : Members(&RC.getMembers()),
+ SpillSize(RC.SpillSize),
+ SpillAlignment(RC.SpillAlignment) {}
+
+ // Lexicographical order of (Members, SpillSize, SpillAlignment).
+ bool operator<(const Key&) const;
+ };
+
+ // Create a non-user defined register class.
+ CodeGenRegisterClass(StringRef Name, Key Props);
+
+ // Called by CodeGenRegBank::CodeGenRegBank().
+ static void computeSubClasses(CodeGenRegBank&);
};
// CodeGenRegBank - Represent a target's registers and the relations between
@@ -151,8 +228,17 @@ namespace llvm {
std::vector<CodeGenRegister*> Registers;
DenseMap<Record*, CodeGenRegister*> Def2Reg;
- std::vector<CodeGenRegisterClass> RegClasses;
+ // Register classes.
+ std::vector<CodeGenRegisterClass*> RegClasses;
DenseMap<Record*, CodeGenRegisterClass*> Def2RC;
+ typedef std::map<CodeGenRegisterClass::Key, CodeGenRegisterClass*> RCKeyMap;
+ RCKeyMap Key2RC;
+
+ // Add RC to *2RC maps.
+ void addToMaps(CodeGenRegisterClass*);
+
+ // Infer missing register classes.
+ void computeInferredRegisterClasses();
// Composite SubRegIndex instances.
// Map (SubRegIndex, SubRegIndex) -> SubRegIndex.
@@ -184,7 +270,7 @@ namespace llvm {
// Find a register from its Record def.
CodeGenRegister *getReg(Record*);
- const std::vector<CodeGenRegisterClass> &getRegClasses() {
+ ArrayRef<CodeGenRegisterClass*> getRegClasses() const {
return RegClasses;
}
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index 929791c..4a7bad7 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -16,7 +16,7 @@
#include "CodeGenTarget.h"
#include "CodeGenIntrinsics.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CommandLine.h"
@@ -184,9 +184,9 @@ std::vector<MVT::SimpleValueType> CodeGenTarget::
getRegisterVTs(Record *R) const {
const CodeGenRegister *Reg = getRegBank().getReg(R);
std::vector<MVT::SimpleValueType> Result;
- const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses();
for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RCs[i];
+ const CodeGenRegisterClass &RC = *RCs[i];
if (RC.contains(Reg)) {
const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes();
Result.insert(Result.end(), InVTs.begin(), InVTs.end());
@@ -201,10 +201,10 @@ getRegisterVTs(Record *R) const {
void CodeGenTarget::ReadLegalValueTypes() const {
- const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses();
for (unsigned i = 0, e = RCs.size(); i != e; ++i)
- for (unsigned ri = 0, re = RCs[i].VTs.size(); ri != re; ++ri)
- LegalValueTypes.push_back(RCs[i].VTs[ri]);
+ for (unsigned ri = 0, re = RCs[i]->VTs.size(); ri != re; ++ri)
+ LegalValueTypes.push_back(RCs[i]->VTs[ri]);
// Remove duplicates.
std::sort(LegalValueTypes.begin(), LegalValueTypes.end());
diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h
index 143daed..730216c 100644
--- a/utils/TableGen/CodeGenTarget.h
+++ b/utils/TableGen/CodeGenTarget.h
@@ -19,7 +19,7 @@
#include "CodeGenRegisters.h"
#include "CodeGenInstruction.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -107,10 +107,6 @@ public:
return RegAltNameIndices;
}
- const std::vector<CodeGenRegisterClass> &getRegisterClasses() const {
- return getRegBank().getRegClasses();
- }
-
const CodeGenRegisterClass &getRegisterClass(Record *R) const {
return *getRegBank().getRegClass(R);
}
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index d66ae96..7db9003 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -13,7 +13,7 @@
#include "DAGISelEmitter.h"
#include "DAGISelMatcher.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h
index 35ab550..9c9fe42 100644
--- a/utils/TableGen/DAGISelEmitter.h
+++ b/utils/TableGen/DAGISelEmitter.h
@@ -14,7 +14,7 @@
#ifndef DAGISEL_EMITTER_H
#define DAGISEL_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include "CodeGenDAGPatterns.h"
namespace llvm {
diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp
index b12e101..1367e8d 100644
--- a/utils/TableGen/DAGISelMatcher.cpp
+++ b/utils/TableGen/DAGISelMatcher.cpp
@@ -10,7 +10,7 @@
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp
index acb0135..3b65b2a 100644
--- a/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -13,7 +13,7 @@
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index c5897c7..49ad956 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -10,7 +10,7 @@
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
#include "CodeGenRegisters.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
@@ -26,10 +26,10 @@ static MVT::SimpleValueType getRegisterValueType(Record *R,
bool FoundRC = false;
MVT::SimpleValueType VT = MVT::Other;
const CodeGenRegister *Reg = T.getRegBank().getReg(R);
- const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RCs = T.getRegBank().getRegClasses();
for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RCs[rc];
+ const CodeGenRegisterClass &RC = *RCs[rc];
if (!RC.contains(Reg))
continue;
diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp
index 07313d1..ff314e9 100644
--- a/utils/TableGen/DisassemblerEmitter.cpp
+++ b/utils/TableGen/DisassemblerEmitter.cpp
@@ -9,12 +9,12 @@
#include "DisassemblerEmitter.h"
#include "CodeGenTarget.h"
-#include "Error.h"
-#include "Record.h"
#include "X86DisassemblerTables.h"
#include "X86RecognizableInstr.h"
#include "ARMDecoderEmitter.h"
#include "FixedLenDecoderEmitter.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
using namespace llvm;
using namespace llvm::X86Disassembler;
@@ -128,12 +128,16 @@ void DisassemblerEmitter::run(raw_ostream &OS) {
return;
}
- // Fixed-instruction-length targets use a common disassembler.
- // ARM use its own implementation for now.
- if (Target.getName() == "ARM") {
- ARMDecoderEmitter(Records).run(OS);
+ // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
+ if (Target.getName() == "ARM" ||
+ Target.getName() == "Thumb") {
+ FixedLenDecoderEmitter(Records,
+ "ARM",
+ "if (!Check(S, ", ")) return MCDisassembler::Fail;",
+ "S", "MCDisassembler::Fail",
+ " MCDisassembler::DecodeStatus S = MCDisassembler::Success;\n(void)S;").run(OS);
return;
- }
+ }
- FixedLenDecoderEmitter(Records).run(OS);
+ FixedLenDecoderEmitter(Records, Target.getName()).run(OS);
}
diff --git a/utils/TableGen/DisassemblerEmitter.h b/utils/TableGen/DisassemblerEmitter.h
index 7229d81..63ee552 100644
--- a/utils/TableGen/DisassemblerEmitter.h
+++ b/utils/TableGen/DisassemblerEmitter.h
@@ -10,7 +10,7 @@
#ifndef DISASSEMBLEREMITTER_H
#define DISASSEMBLEREMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
index 2f9814a..abef70e 100644
--- a/utils/TableGen/EDEmitter.cpp
+++ b/utils/TableGen/EDEmitter.cpp
@@ -17,8 +17,8 @@
#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/MC/EDInstInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
@@ -256,12 +256,15 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
REG("GR8");
REG("GR8_NOREX");
REG("GR16");
+ REG("GR16_NOAX");
REG("GR32");
+ REG("GR32_NOAX");
REG("GR32_NOREX");
REG("GR32_TC");
REG("FR32");
REG("RFP32");
REG("GR64");
+ REG("GR64_NOAX");
REG("GR64_TC");
REG("FR64");
REG("VR64");
@@ -279,6 +282,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
IMM("i16i8imm");
IMM("i32imm");
IMM("i32i8imm");
+ IMM("u32u8imm");
IMM("i64imm");
IMM("i64i8imm");
IMM("i64i32imm");
@@ -554,6 +558,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
const std::string &name) {
REG("GPR");
REG("rGPR");
+ REG("GPRnopc");
+ REG("GPRsp");
REG("tcGPR");
REG("cc_out");
REG("s_cc_out");
@@ -575,6 +581,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
IMM("nohash_imm");
IMM("p_imm");
IMM("c_imm");
+ IMM("coproc_option_imm");
IMM("imod_op");
IMM("iflags_op");
IMM("cpinst_operand");
@@ -587,26 +594,40 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
IMM("neg_zero");
IMM("imm0_31");
IMM("imm0_31_m1");
+ IMM("imm1_16");
+ IMM("imm1_32");
IMM("nModImm");
IMM("imm0_7");
IMM("imm0_15");
IMM("imm0_255");
IMM("imm0_4095");
IMM("imm0_65535");
+ IMM("imm0_65535_expr");
+ IMM("imm24b");
+ IMM("pkh_lsl_amt");
+ IMM("pkh_asr_amt");
IMM("jt2block_operand");
- IMM("t_imm_s4");
+ IMM("t_imm0_1020s4");
+ IMM("t_imm0_508s4");
IMM("pclabel");
IMM("adrlabel");
IMM("t_adrlabel");
IMM("t2adrlabel");
IMM("shift_imm");
- IMM("ssat_imm");
+ IMM("t2_shift_imm");
IMM("neon_vcvt_imm32");
IMM("shr_imm8");
IMM("shr_imm16");
IMM("shr_imm32");
IMM("shr_imm64");
IMM("t2ldrlabel");
+ IMM("postidx_imm8");
+ IMM("postidx_imm8s4");
+ IMM("imm_sr");
+ IMM("imm1_31");
+ IMM("VectorIndex8");
+ IMM("VectorIndex16");
+ IMM("VectorIndex32");
MISC("brtarget", "kOperandTypeARMBranchTarget"); // ?
MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ?
@@ -617,11 +638,14 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("br_target", "kOperandTypeARMBranchTarget"); // ?
MISC("bl_target", "kOperandTypeARMBranchTarget"); // ?
+ MISC("blx_target", "kOperandTypeARMBranchTarget"); // ?
MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ?
MISC("t_blxtarget", "kOperandTypeARMBranchTarget"); // ?
- MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I
- MISC("shift_so_reg", "kOperandTypeARMSoReg"); // R, R, I
+ MISC("so_reg_imm", "kOperandTypeARMSoRegReg"); // R, R, I
+ MISC("so_reg_reg", "kOperandTypeARMSoRegImm"); // R, R, I
+ MISC("shift_so_reg_reg", "kOperandTypeARMSoRegReg"); // R, R, I
+ MISC("shift_so_reg_imm", "kOperandTypeARMSoRegImm"); // R, R, I
MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I
MISC("so_imm", "kOperandTypeARMSoImm"); // I
MISC("rot_imm", "kOperandTypeARMRotImm"); // I
@@ -631,8 +655,10 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("it_pred", "kOperandTypeARMPredicate"); // I
MISC("addrmode_imm12", "kOperandTypeAddrModeImm12"); // R, I
MISC("ldst_so_reg", "kOperandTypeLdStSOReg"); // R, R, I
+ MISC("postidx_reg", "kOperandTypeARMAddrMode3Offset"); // R, I
MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I
- MISC("am2offset", "kOperandTypeARMAddrMode2Offset"); // R, I
+ MISC("am2offset_reg", "kOperandTypeARMAddrMode2Offset"); // R, I
+ MISC("am2offset_imm", "kOperandTypeARMAddrMode2Offset"); // R, I
MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I
MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I
MISC("ldstm_mode", "kOperandTypeARMLdStmMode"); // I
@@ -642,17 +668,20 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("addrmode6dup", "kOperandTypeARMAddrMode6"); // R, R, I, I
MISC("addrmode6oneL32", "kOperandTypeARMAddrMode6"); // R, R, I, I
MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I
- MISC("addrmode7", "kOperandTypeARMAddrMode7"); // R
+ MISC("addr_offset_none", "kOperandTypeARMAddrMode7"); // R
MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ...
MISC("dpr_reglist", "kOperandTypeARMDPRRegisterList"); // I, R, ...
MISC("spr_reglist", "kOperandTypeARMSPRRegisterList"); // I, R, ...
MISC("it_mask", "kOperandTypeThumbITMask"); // I
MISC("t2addrmode_reg", "kOperandTypeThumb2AddrModeReg"); // R
+ MISC("t2addrmode_posimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
+ MISC("t2addrmode_negimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I
MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I
MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I
MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I
+ MISC("t2addrmode_imm0_1020s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I
MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset");
// R, I
MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I
@@ -665,6 +694,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R
MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I
MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I
+ MISC("addrmode_tbb", "kOperandTypeThumbAddrModeRR"); // R, R
+ MISC("addrmode_tbh", "kOperandTypeThumbAddrModeRR"); // R, R
return 1;
}
@@ -772,11 +803,6 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray,
for (index = 0; index < numInstructions; ++index) {
const CodeGenInstruction& inst = *numberedInstructions[index];
- // We don't need to do anything for pseudo-instructions, as we'll never
- // see them here. We'll only see real instructions.
- if (inst.isPseudo)
- continue;
-
CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter;
infoArray.addEntry(infoStruct);
@@ -809,15 +835,20 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray,
unsigned numSyntaxes = 0;
- if (target.getName() == "X86") {
- X86PopulateOperands(operandTypes, inst);
- X86ExtractSemantics(*instType, operandFlags, inst);
- numSyntaxes = 2;
- }
- else if (target.getName() == "ARM") {
- ARMPopulateOperands(operandTypes, inst);
- ARMExtractSemantics(*instType, operandTypes, operandFlags, inst);
- numSyntaxes = 1;
+ // We don't need to do anything for pseudo-instructions, as we'll never
+ // see them here. We'll only see real instructions.
+ // We still need to emit null initializers for everything.
+ if (!inst.isPseudo) {
+ if (target.getName() == "X86") {
+ X86PopulateOperands(operandTypes, inst);
+ X86ExtractSemantics(*instType, operandFlags, inst);
+ numSyntaxes = 2;
+ }
+ else if (target.getName() == "ARM") {
+ ARMPopulateOperands(operandTypes, inst);
+ ARMExtractSemantics(*instType, operandTypes, operandFlags, inst);
+ numSyntaxes = 1;
+ }
}
CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter;
@@ -850,7 +881,8 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) {
operandTypes.addEntry("kOperandTypeX86EffectiveAddress");
operandTypes.addEntry("kOperandTypeX86PCRelative");
operandTypes.addEntry("kOperandTypeARMBranchTarget");
- operandTypes.addEntry("kOperandTypeARMSoReg");
+ operandTypes.addEntry("kOperandTypeARMSoRegReg");
+ operandTypes.addEntry("kOperandTypeARMSoRegImm");
operandTypes.addEntry("kOperandTypeARMSoImm");
operandTypes.addEntry("kOperandTypeARMRotImm");
operandTypes.addEntry("kOperandTypeARMSoImm2Part");
diff --git a/utils/TableGen/EDEmitter.h b/utils/TableGen/EDEmitter.h
index e30373f..f268375 100644
--- a/utils/TableGen/EDEmitter.h
+++ b/utils/TableGen/EDEmitter.h
@@ -16,7 +16,7 @@
#ifndef SEMANTIC_INFO_EMITTER_H
#define SEMANTIC_INFO_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/utils/TableGen/Error.cpp b/utils/TableGen/Error.cpp
deleted file mode 100644
index 3f6cda8..0000000
--- a/utils/TableGen/Error.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- Error.cpp - tblgen error handling helper routines --------*- 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 error handling helper routines to pretty-print diagnostic
-// messages from tblgen.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Error.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-SourceMgr SrcMgr;
-
-void PrintError(SMLoc ErrorLoc, const Twine &Msg) {
- SrcMgr.PrintMessage(ErrorLoc, Msg, "error");
-}
-
-void PrintError(const char *Loc, const Twine &Msg) {
- SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error");
-}
-
-void PrintError(const Twine &Msg) {
- errs() << "error:" << Msg << "\n";
-}
-
-void PrintError(const TGError &Error) {
- PrintError(Error.getLoc(), Error.getMessage());
-}
-
-} // end namespace llvm
diff --git a/utils/TableGen/Error.h b/utils/TableGen/Error.h
deleted file mode 100644
index b3a0146..0000000
--- a/utils/TableGen/Error.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- Error.h - tblgen error handling helper routines ----------*- 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 error handling helper routines to pretty-print diagnostic
-// messages from tblgen.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ERROR_H
-#define ERROR_H
-
-#include "llvm/Support/SourceMgr.h"
-
-namespace llvm {
-
-class TGError {
- SMLoc Loc;
- std::string Message;
-public:
- TGError(SMLoc loc, const std::string &message) : Loc(loc), Message(message) {}
-
- SMLoc getLoc() const { return Loc; }
- const std::string &getMessage() const { return Message; }
-};
-
-void PrintError(SMLoc ErrorLoc, const Twine &Msg);
-void PrintError(const char *Loc, const Twine &Msg);
-void PrintError(const Twine &Msg);
-void PrintError(const TGError &Error);
-
-
-extern SourceMgr SrcMgr;
-
-
-} // end namespace "llvm"
-
-#endif
diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp
index f54e8df..9fdc2e3 100644
--- a/utils/TableGen/FastISelEmitter.cpp
+++ b/utils/TableGen/FastISelEmitter.cpp
@@ -18,8 +18,8 @@
//===----------------------------------------------------------------------===//
#include "FastISelEmitter.h"
-#include "Error.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/VectorExtras.h"
#include "llvm/Support/Debug.h"
@@ -504,7 +504,7 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
std::vector<std::string>* PhysRegInputs = new std::vector<std::string>();
if (InstPatNode->getOperator()->getName() == "imm" ||
- InstPatNode->getOperator()->getName() == "fpimmm")
+ InstPatNode->getOperator()->getName() == "fpimm")
PhysRegInputs->push_back("");
else {
// Compute the PhysRegs used by the given pattern, and check that
diff --git a/utils/TableGen/FastISelEmitter.h b/utils/TableGen/FastISelEmitter.h
index ce4e77e..4f75ac1 100644
--- a/utils/TableGen/FastISelEmitter.h
+++ b/utils/TableGen/FastISelEmitter.h
@@ -14,8 +14,8 @@
#ifndef FASTISEL_EMITTER_H
#define FASTISEL_EMITTER_H
-#include "TableGenBackend.h"
#include "CodeGenDAGPatterns.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
index c9dcb01..02b966a 100644
--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -16,7 +16,7 @@
#include "FixedLenDecoderEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -84,11 +84,8 @@ static BitsInit &getBitsField(const Record &def, const char *str) {
// Forward declaration.
class FilterChooser;
-// FIXME: Possibly auto-detected?
-#define BIT_WIDTH 32
-
// Representation of the instruction to work on.
-typedef bit_value_t insn_t[BIT_WIDTH];
+typedef std::vector<bit_value_t> insn_t;
/// Filter - Filter works with FilterChooser to produce the decoding tree for
/// the ISA.
@@ -230,7 +227,7 @@ protected:
// Array of bit values passed down from our parent.
// Set to all BIT_UNFILTERED's for Parent == NULL.
- bit_value_t FilterBitValues[BIT_WIDTH];
+ std::vector<bit_value_t> FilterBitValues;
// Links to the FilterChooser above us in the decoding tree.
FilterChooser *Parent;
@@ -238,21 +235,29 @@ protected:
// Index of the best filter from Filters.
int BestIndex;
+ // Width of instructions
+ unsigned BitWidth;
+
+ // Parent emitter
+ const FixedLenDecoderEmitter *Emitter;
+
public:
FilterChooser(const FilterChooser &FC) :
AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes),
- Operands(FC.Operands), Filters(FC.Filters), Parent(FC.Parent),
- BestIndex(FC.BestIndex) {
- memcpy(FilterBitValues, FC.FilterBitValues, sizeof(FilterBitValues));
- }
+ Operands(FC.Operands), Filters(FC.Filters),
+ FilterBitValues(FC.FilterBitValues), Parent(FC.Parent),
+ BestIndex(FC.BestIndex), BitWidth(FC.BitWidth),
+ Emitter(FC.Emitter) { }
FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
const std::vector<unsigned> &IDs,
- std::map<unsigned, std::vector<OperandInfo> > &Ops) :
+ std::map<unsigned, std::vector<OperandInfo> > &Ops,
+ unsigned BW,
+ const FixedLenDecoderEmitter *E) :
AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(),
- Parent(NULL), BestIndex(-1) {
- for (unsigned i = 0; i < BIT_WIDTH; ++i)
- FilterBitValues[i] = BIT_UNFILTERED;
+ Parent(NULL), BestIndex(-1), BitWidth(BW), Emitter(E) {
+ for (unsigned i = 0; i < BitWidth; ++i)
+ FilterBitValues.push_back(BIT_UNFILTERED);
doFilter();
}
@@ -260,13 +265,12 @@ public:
FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
const std::vector<unsigned> &IDs,
std::map<unsigned, std::vector<OperandInfo> > &Ops,
- bit_value_t (&ParentFilterBitValues)[BIT_WIDTH],
+ std::vector<bit_value_t> &ParentFilterBitValues,
FilterChooser &parent) :
AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
- Filters(), Parent(&parent), BestIndex(-1) {
- for (unsigned i = 0; i < BIT_WIDTH; ++i)
- FilterBitValues[i] = ParentFilterBitValues[i];
-
+ Filters(), FilterBitValues(ParentFilterBitValues),
+ Parent(&parent), BestIndex(-1), BitWidth(parent.BitWidth),
+ Emitter(parent.Emitter) {
doFilter();
}
@@ -274,15 +278,15 @@ public:
bool isTopLevel() { return Parent == NULL; }
// Emit the top level typedef and decodeInstruction() function.
- void emitTop(raw_ostream &o, unsigned Indentation);
+ void emitTop(raw_ostream &o, unsigned Indentation, std::string Namespace);
protected:
// Populates the insn given the uid.
void insnWithID(insn_t &Insn, unsigned Opcode) const {
BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst");
- for (unsigned i = 0; i < BIT_WIDTH; ++i)
- Insn[i] = bitFromBits(Bits, i);
+ for (unsigned i = 0; i < BitWidth; ++i)
+ Insn.push_back(bitFromBits(Bits, i));
}
// Returns the record name.
@@ -300,7 +304,7 @@ protected:
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
/// filter array as a series of chars.
- void dumpFilterArray(raw_ostream &o, bit_value_t (&filter)[BIT_WIDTH]);
+ void dumpFilterArray(raw_ostream &o, std::vector<bit_value_t> & filter);
/// dumpStack - dumpStack traverses the filter chooser chain and calls
/// dumpFilterArray on each filter chooser up to the top level one.
@@ -326,6 +330,10 @@ protected:
std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals,
insn_t &Insn);
+ // Emits code to check the Predicates member of an instruction are true.
+ // Returns true if predicate matches were emitted, false otherwise.
+ bool emitPredicateMatch(raw_ostream &o, unsigned &Indentation,unsigned Opc);
+
// Emits code to decode the singleton. Return true if we have matched all the
// well-known bits.
bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc);
@@ -333,6 +341,9 @@ protected:
// Emits code to decode the singleton, and then to decode the rest.
void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,Filter &Best);
+ void emitBinaryParser(raw_ostream &o , unsigned &Indentation,
+ OperandInfo &OpInfo);
+
// Assign a single filter and run with it.
void runSingleFilter(FilterChooser &owner, unsigned startBit, unsigned numBit,
bool mixed);
@@ -375,7 +386,7 @@ Filter::Filter(const Filter &f) :
Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits),
Mixed(mixed) {
- assert(StartBit + NumBits - 1 < BIT_WIDTH);
+ assert(StartBit + NumBits - 1 < Owner->BitWidth);
NumFiltered = 0;
LastOpcFiltered = 0;
@@ -427,9 +438,8 @@ Filter::~Filter() {
void Filter::recurse() {
std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator;
- bit_value_t BitValueArray[BIT_WIDTH];
// Starts by inheriting our parent filter chooser's filter bit values.
- memcpy(BitValueArray, Owner->FilterBitValues, sizeof(BitValueArray));
+ std::vector<bit_value_t> BitValueArray(Owner->FilterBitValues);
unsigned bitIndex;
@@ -493,8 +503,9 @@ void Filter::emit(raw_ostream &o, unsigned &Indentation) {
o << StartBit << "} ...\n";
- o.indent(Indentation) << "switch (fieldFromInstruction(insn, "
- << StartBit << ", " << NumBits << ")) {\n";
+ o.indent(Indentation) << "switch (fieldFromInstruction" << Owner->BitWidth
+ << "(insn, " << StartBit << ", "
+ << NumBits << ")) {\n";
std::map<unsigned, FilterChooser*>::iterator filterIterator;
@@ -559,68 +570,21 @@ unsigned Filter::usefulness() const {
//////////////////////////////////
// Emit the top level typedef and decodeInstruction() function.
-void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation) {
- switch (BIT_WIDTH) {
- case 8:
- o.indent(Indentation) << "typedef uint8_t field_t;\n";
- break;
- case 16:
- o.indent(Indentation) << "typedef uint16_t field_t;\n";
- break;
- case 32:
- o.indent(Indentation) << "typedef uint32_t field_t;\n";
- break;
- case 64:
- o.indent(Indentation) << "typedef uint64_t field_t;\n";
- break;
- default:
- assert(0 && "Unexpected instruction size!");
- }
-
- o << '\n';
-
- o.indent(Indentation) << "static field_t " <<
- "fieldFromInstruction(field_t insn, unsigned startBit, unsigned numBits)\n";
-
- o.indent(Indentation) << "{\n";
-
- ++Indentation; ++Indentation;
- o.indent(Indentation) << "assert(startBit + numBits <= " << BIT_WIDTH
- << " && \"Instruction field out of bounds!\");\n";
- o << '\n';
- o.indent(Indentation) << "field_t fieldMask;\n";
- o << '\n';
- o.indent(Indentation) << "if (numBits == " << BIT_WIDTH << ")\n";
-
- ++Indentation; ++Indentation;
- o.indent(Indentation) << "fieldMask = (field_t)-1;\n";
- --Indentation; --Indentation;
-
- o.indent(Indentation) << "else\n";
-
- ++Indentation; ++Indentation;
- o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n";
- --Indentation; --Indentation;
-
- o << '\n';
- o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n";
- --Indentation; --Indentation;
-
- o.indent(Indentation) << "}\n";
-
- o << '\n';
-
+void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation,
+ std::string Namespace) {
o.indent(Indentation) <<
- "static bool decodeInstruction(MCInst &MI, field_t insn, "
- "uint64_t Address, const void *Decoder) {\n";
- o.indent(Indentation) << " unsigned tmp = 0;\n";
+ "static MCDisassembler::DecodeStatus decode" << Namespace << "Instruction" << BitWidth
+ << "(MCInst &MI, uint" << BitWidth << "_t insn, uint64_t Address, "
+ << "const void *Decoder, const MCSubtargetInfo &STI) {\n";
+ o.indent(Indentation) << " unsigned tmp = 0;\n (void)tmp;\n" << Emitter->Locals << "\n";
+ o.indent(Indentation) << " uint64_t Bits = STI.getFeatureBits();\n";
++Indentation; ++Indentation;
// Emits code to decode the instructions.
emit(o, Indentation);
o << '\n';
- o.indent(Indentation) << "return false;\n";
+ o.indent(Indentation) << "return " << Emitter->ReturnFail << ";\n";
--Indentation; --Indentation;
o.indent(Indentation) << "}\n";
@@ -651,10 +615,10 @@ bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn,
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
/// filter array as a series of chars.
void FilterChooser::dumpFilterArray(raw_ostream &o,
- bit_value_t (&filter)[BIT_WIDTH]) {
+ std::vector<bit_value_t> &filter) {
unsigned bitIndex;
- for (bitIndex = BIT_WIDTH; bitIndex > 0; bitIndex--) {
+ for (bitIndex = BitWidth; bitIndex > 0; bitIndex--) {
switch (filter[bitIndex - 1]) {
case BIT_UNFILTERED:
o << ".";
@@ -727,7 +691,7 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
int State = 0;
int Val = -1;
- for (unsigned i = 0; i < BIT_WIDTH; ++i) {
+ for (unsigned i = 0; i < BitWidth; ++i) {
Val = Value(Insn[i]);
bool Filtered = PositionFiltered(i);
switch (State) {
@@ -761,7 +725,7 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
}
// If we are still in Island after the loop, do some housekeeping.
if (State == 2) {
- EndBits.push_back(BIT_WIDTH - 1);
+ EndBits.push_back(BitWidth - 1);
FieldVals.push_back(FieldVal);
++Num;
}
@@ -771,6 +735,70 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
return Num;
}
+void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
+ OperandInfo &OpInfo) {
+ std::string &Decoder = OpInfo.Decoder;
+
+ if (OpInfo.numFields() == 1) {
+ OperandInfo::iterator OI = OpInfo.begin();
+ o.indent(Indentation) << " tmp = fieldFromInstruction" << BitWidth
+ << "(insn, " << OI->Base << ", " << OI->Width
+ << ");\n";
+ } else {
+ o.indent(Indentation) << " tmp = 0;\n";
+ for (OperandInfo::iterator OI = OpInfo.begin(), OE = OpInfo.end();
+ OI != OE; ++OI) {
+ o.indent(Indentation) << " tmp |= (fieldFromInstruction" << BitWidth
+ << "(insn, " << OI->Base << ", " << OI->Width
+ << ") << " << OI->Offset << ");\n";
+ }
+ }
+
+ if (Decoder != "")
+ o.indent(Indentation) << " " << Emitter->GuardPrefix << Decoder
+ << "(MI, tmp, Address, Decoder)" << Emitter->GuardPostfix << "\n";
+ else
+ o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n";
+
+}
+
+static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
+ std::string PredicateNamespace) {
+ if (str[0] == '!')
+ o << "!(Bits & " << PredicateNamespace << "::"
+ << str.slice(1,str.size()) << ")";
+ else
+ o << "(Bits & " << PredicateNamespace << "::" << str << ")";
+}
+
+bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
+ unsigned Opc) {
+ ListInit *Predicates = AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates");
+ for (unsigned i = 0; i < Predicates->getSize(); ++i) {
+ Record *Pred = Predicates->getElementAsRecord(i);
+ if (!Pred->getValue("AssemblerMatcherPredicate"))
+ continue;
+
+ std::string P = Pred->getValueAsString("AssemblerCondString");
+
+ if (!P.length())
+ continue;
+
+ if (i != 0)
+ o << " && ";
+
+ StringRef SR(P);
+ std::pair<StringRef, StringRef> pairs = SR.split(',');
+ while (pairs.second.size()) {
+ emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
+ o << " && ";
+ pairs = pairs.second.split(',');
+ }
+ emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
+ }
+ return Predicates->getSize() > 0;
+}
+
// Emits code to decode the singleton. Return true if we have matched all the
// well-known bits.
bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
@@ -789,33 +817,27 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
// If we have matched all the well-known bits, just issue a return.
if (Size == 0) {
- o.indent(Indentation) << "{\n";
+ o.indent(Indentation) << "if (";
+ if (!emitPredicateMatch(o, Indentation, Opc))
+ o << "1";
+ o << ") {\n";
o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n";
std::vector<OperandInfo>& InsnOperands = Operands[Opc];
for (std::vector<OperandInfo>::iterator
I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
// If a custom instruction decoder was specified, use that.
- if (I->FieldBase == ~0U && I->FieldLength == ~0U) {
- o.indent(Indentation) << " " << I->Decoder
- << "(MI, insn, Address, Decoder);\n";
+ if (I->numFields() == 0 && I->Decoder.size()) {
+ o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder
+ << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n";
break;
}
- o.indent(Indentation)
- << " tmp = fieldFromInstruction(insn, " << I->FieldBase
- << ", " << I->FieldLength << ");\n";
- if (I->Decoder != "") {
- o.indent(Indentation) << " " << I->Decoder
- << "(MI, tmp, Address, Decoder);\n";
- } else {
- o.indent(Indentation)
- << " MI.addOperand(MCOperand::CreateImm(tmp));\n";
- }
+ emitBinaryParser(o, Indentation, *I);
}
- o.indent(Indentation) << " return true; // " << nameWithID(Opc)
+ o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc)
<< '\n';
- o.indent(Indentation) << "}\n";
+ o.indent(Indentation) << "}\n"; // Closing predicate block.
return true;
}
@@ -827,16 +849,21 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
for (I = Size; I != 0; --I) {
o << "Inst{" << EndBits[I-1] << '-' << StartBits[I-1] << "} ";
if (I > 1)
- o << "&& ";
+ o << " && ";
else
o << "for singleton decoding...\n";
}
o.indent(Indentation) << "if (";
+ if (emitPredicateMatch(o, Indentation, Opc)) {
+ o << " &&\n";
+ o.indent(Indentation+4);
+ }
for (I = Size; I != 0; --I) {
NumBits = EndBits[I-1] - StartBits[I-1] + 1;
- o << "fieldFromInstruction(insn, " << StartBits[I-1] << ", " << NumBits
+ o << "fieldFromInstruction" << BitWidth << "(insn, "
+ << StartBits[I-1] << ", " << NumBits
<< ") == " << FieldVals[I-1];
if (I > 1)
o << " && ";
@@ -848,24 +875,15 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
for (std::vector<OperandInfo>::iterator
I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
// If a custom instruction decoder was specified, use that.
- if (I->FieldBase == ~0U && I->FieldLength == ~0U) {
- o.indent(Indentation) << " " << I->Decoder
- << "(MI, insn, Address, Decoder);\n";
+ if (I->numFields() == 0 && I->Decoder.size()) {
+ o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder
+ << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n";
break;
}
- o.indent(Indentation)
- << " tmp = fieldFromInstruction(insn, " << I->FieldBase
- << ", " << I->FieldLength << ");\n";
- if (I->Decoder != "") {
- o.indent(Indentation) << " " << I->Decoder
- << "(MI, tmp, Address, Decoder);\n";
- } else {
- o.indent(Indentation)
- << " MI.addOperand(MCOperand::CreateImm(tmp));\n";
- }
+ emitBinaryParser(o, Indentation, *I);
}
- o.indent(Indentation) << " return true; // " << nameWithID(Opc)
+ o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc)
<< '\n';
o.indent(Indentation) << "}\n";
@@ -965,23 +983,23 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
// (MIXED) ------ . ----> (MIXED)
// (FILTERED)---- . ----> (FILTERED)
- bitAttr_t bitAttrs[BIT_WIDTH];
+ std::vector<bitAttr_t> bitAttrs;
// FILTERED bit positions provide no entropy and are not worthy of pursuing.
// Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position.
- for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex)
+ for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex)
if (FilterBitValues[BitIndex] == BIT_TRUE ||
FilterBitValues[BitIndex] == BIT_FALSE)
- bitAttrs[BitIndex] = ATTR_FILTERED;
+ bitAttrs.push_back(ATTR_FILTERED);
else
- bitAttrs[BitIndex] = ATTR_NONE;
+ bitAttrs.push_back(ATTR_NONE);
for (InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) {
insn_t insn;
insnWithID(insn, Opcodes[InsnIndex]);
- for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex) {
+ for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
switch (bitAttrs[BitIndex]) {
case ATTR_NONE:
if (insn[BitIndex] == BIT_UNSET)
@@ -1027,7 +1045,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
bitAttr_t RA = ATTR_NONE;
unsigned StartBit = 0;
- for (BitIndex = 0; BitIndex < BIT_WIDTH; BitIndex++) {
+ for (BitIndex = 0; BitIndex < BitWidth; BitIndex++) {
bitAttr_t bitAttr = bitAttrs[BitIndex];
assert(bitAttr != ATTR_NONE && "Bit without attributes");
@@ -1216,8 +1234,9 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) {
return true;
}
-bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
- unsigned Opc){
+static bool populateInstruction(const CodeGenInstruction &CGI,
+ unsigned Opc,
+ std::map<unsigned, std::vector<OperandInfo> >& Operands){
const Record &Def = *CGI.TheDef;
// If all the bit positions are not specified; do not decode this instruction.
// We are bound to fail! For proper disassembly, the well-known encoding bits
@@ -1239,7 +1258,7 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
// of trying to auto-generate the decoder.
std::string InstDecoder = Def.getValueAsString("DecoderMethod");
if (InstDecoder != "") {
- InsnOperands.push_back(OperandInfo(~0U, ~0U, InstDecoder));
+ InsnOperands.push_back(OperandInfo(InstDecoder));
Operands[Opc] = InsnOperands;
return true;
}
@@ -1259,72 +1278,97 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
for (unsigned i = 0; i < In->getNumArgs(); ++i)
InOutOperands.push_back(std::make_pair(In->getArg(i), In->getArgName(i)));
+ // Search for tied operands, so that we can correctly instantiate
+ // operands that are not explicitly represented in the encoding.
+ std::map<std::string, std::string> TiedNames;
+ for (unsigned i = 0; i < CGI.Operands.size(); ++i) {
+ int tiedTo = CGI.Operands[i].getTiedRegister();
+ if (tiedTo != -1) {
+ TiedNames[InOutOperands[i].second] = InOutOperands[tiedTo].second;
+ TiedNames[InOutOperands[tiedTo].second] = InOutOperands[i].second;
+ }
+ }
+
// For each operand, see if we can figure out where it is encoded.
for (std::vector<std::pair<Init*, std::string> >::iterator
NI = InOutOperands.begin(), NE = InOutOperands.end(); NI != NE; ++NI) {
- unsigned PrevBit = ~0;
- unsigned Base = ~0;
- unsigned PrevPos = ~0;
std::string Decoder = "";
+ // At this point, we can locate the field, but we need to know how to
+ // interpret it. As a first step, require the target to provide callbacks
+ // for decoding register classes.
+ // FIXME: This need to be extended to handle instructions with custom
+ // decoder methods, and operands with (simple) MIOperandInfo's.
+ TypedInit *TI = dynamic_cast<TypedInit*>(NI->first);
+ RecordRecTy *Type = dynamic_cast<RecordRecTy*>(TI->getType());
+ Record *TypeRecord = Type->getRecord();
+ bool isReg = false;
+ if (TypeRecord->isSubClassOf("RegisterOperand"))
+ TypeRecord = TypeRecord->getValueAsDef("RegClass");
+ if (TypeRecord->isSubClassOf("RegisterClass")) {
+ Decoder = "Decode" + TypeRecord->getName() + "RegisterClass";
+ isReg = true;
+ }
+
+ RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod");
+ StringInit *String = DecoderString ?
+ dynamic_cast<StringInit*>(DecoderString->getValue()) : 0;
+ if (!isReg && String && String->getValue() != "")
+ Decoder = String->getValue();
+
+ OperandInfo OpInfo(Decoder);
+ unsigned Base = ~0U;
+ unsigned Width = 0;
+ unsigned Offset = 0;
+
for (unsigned bi = 0; bi < Bits.getNumBits(); ++bi) {
+ VarInit *Var = 0;
VarBitInit *BI = dynamic_cast<VarBitInit*>(Bits.getBit(bi));
- if (!BI) continue;
-
- VarInit *Var = dynamic_cast<VarInit*>(BI->getVariable());
- assert(Var);
- unsigned CurrBit = BI->getBitNum();
- if (Var->getName() != NI->second) continue;
-
- // Figure out the lowest bit of the value, and the width of the field.
- // Deliberately don't try to handle cases where the field is scattered,
- // or where not all bits of the the field are explicit.
- if (Base == ~0U && PrevBit == ~0U && PrevPos == ~0U) {
- if (CurrBit == 0)
- Base = bi;
- else
- continue;
+ if (BI)
+ Var = dynamic_cast<VarInit*>(BI->getVariable());
+ else
+ Var = dynamic_cast<VarInit*>(Bits.getBit(bi));
+
+ if (!Var) {
+ if (Base != ~0U) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = ~0U;
+ Width = 0;
+ Offset = 0;
+ }
+ continue;
}
- if ((PrevPos != ~0U && bi-1 != PrevPos) ||
- (CurrBit != ~0U && CurrBit-1 != PrevBit)) {
- PrevBit = ~0;
- Base = ~0;
- PrevPos = ~0;
+ if (Var->getName() != NI->second &&
+ Var->getName() != TiedNames[NI->second]) {
+ if (Base != ~0U) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = ~0U;
+ Width = 0;
+ Offset = 0;
+ }
+ continue;
}
- PrevPos = bi;
- PrevBit = CurrBit;
-
- // At this point, we can locate the field, but we need to know how to
- // interpret it. As a first step, require the target to provide callbacks
- // for decoding register classes.
- // FIXME: This need to be extended to handle instructions with custom
- // decoder methods, and operands with (simple) MIOperandInfo's.
- TypedInit *TI = dynamic_cast<TypedInit*>(NI->first);
- RecordRecTy *Type = dynamic_cast<RecordRecTy*>(TI->getType());
- Record *TypeRecord = Type->getRecord();
- bool isReg = false;
- if (TypeRecord->isSubClassOf("RegisterOperand"))
- TypeRecord = TypeRecord->getValueAsDef("RegClass");
- if (TypeRecord->isSubClassOf("RegisterClass")) {
- Decoder = "Decode" + TypeRecord->getName() + "RegisterClass";
- isReg = true;
+ if (Base == ~0U) {
+ Base = bi;
+ Width = 1;
+ Offset = BI ? BI->getBitNum() : 0;
+ } else if (BI && BI->getBitNum() != Offset + Width) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = bi;
+ Width = 1;
+ Offset = BI->getBitNum();
+ } else {
+ ++Width;
}
-
- RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod");
- StringInit *String = DecoderString ?
- dynamic_cast<StringInit*>(DecoderString->getValue()) :
- 0;
- if (!isReg && String && String->getValue() != "")
- Decoder = String->getValue();
}
- if (Base != ~0U) {
- InsnOperands.push_back(OperandInfo(Base, PrevBit+1, Decoder));
- DEBUG(errs() << "ENCODED OPERAND: $" << NI->second << " @ ("
- << utostr(Base+PrevBit) << ", " << utostr(Base) << ")\n");
- }
+ if (Base != ~0U)
+ OpInfo.addField(Base, Width, Offset);
+
+ if (OpInfo.numFields() > 0)
+ InsnOperands.push_back(OpInfo);
}
Operands[Opc] = InsnOperands;
@@ -1351,16 +1395,43 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
return true;
}
-void FixedLenDecoderEmitter::populateInstructions() {
- for (unsigned i = 0, e = NumberedInstructions.size(); i < e; ++i) {
- Record *R = NumberedInstructions[i]->TheDef;
- if (R->getValueAsString("Namespace") == "TargetOpcode" ||
- R->getValueAsBit("isPseudo"))
- continue;
+static void emitHelper(llvm::raw_ostream &o, unsigned BitWidth) {
+ unsigned Indentation = 0;
+ std::string WidthStr = "uint" + utostr(BitWidth) + "_t";
- if (populateInstruction(*NumberedInstructions[i], i))
- Opcodes.push_back(i);
- }
+ o << '\n';
+
+ o.indent(Indentation) << "static " << WidthStr <<
+ " fieldFromInstruction" << BitWidth <<
+ "(" << WidthStr <<" insn, unsigned startBit, unsigned numBits)\n";
+
+ o.indent(Indentation) << "{\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "assert(startBit + numBits <= " << BitWidth
+ << " && \"Instruction field out of bounds!\");\n";
+ o << '\n';
+ o.indent(Indentation) << WidthStr << " fieldMask;\n";
+ o << '\n';
+ o.indent(Indentation) << "if (numBits == " << BitWidth << ")\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "fieldMask = (" << WidthStr << ")-1;\n";
+ --Indentation; --Indentation;
+
+ o.indent(Indentation) << "else\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n";
+ --Indentation; --Indentation;
+
+ o << '\n';
+ o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n";
+ --Indentation; --Indentation;
+
+ o.indent(Indentation) << "}\n";
+
+ o << '\n';
}
// Emits disassembler code for instruction decoding.
@@ -1372,10 +1443,47 @@ void FixedLenDecoderEmitter::run(raw_ostream &o)
o << '\n';
o << "namespace llvm {\n\n";
+ // Parameterize the decoders based on namespace and instruction width.
NumberedInstructions = Target.getInstructionsByEnumValue();
- populateInstructions();
- FilterChooser FC(NumberedInstructions, Opcodes, Operands);
- FC.emitTop(o, 0);
+ std::map<std::pair<std::string, unsigned>,
+ std::vector<unsigned> > OpcMap;
+ std::map<unsigned, std::vector<OperandInfo> > Operands;
+
+ for (unsigned i = 0; i < NumberedInstructions.size(); ++i) {
+ const CodeGenInstruction *Inst = NumberedInstructions[i];
+ Record *Def = Inst->TheDef;
+ unsigned Size = Def->getValueAsInt("Size");
+ if (Def->getValueAsString("Namespace") == "TargetOpcode" ||
+ Def->getValueAsBit("isPseudo") ||
+ Def->getValueAsBit("isAsmParserOnly") ||
+ Def->getValueAsBit("isCodeGenOnly"))
+ continue;
+
+ std::string DecoderNamespace = Def->getValueAsString("DecoderNamespace");
+
+ if (Size) {
+ if (populateInstruction(*Inst, i, Operands)) {
+ OpcMap[std::make_pair(DecoderNamespace, Size)].push_back(i);
+ }
+ }
+ }
+
+ std::set<unsigned> Sizes;
+ for (std::map<std::pair<std::string, unsigned>,
+ std::vector<unsigned> >::iterator
+ I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) {
+ // If we haven't visited this instruction width before, emit the
+ // helper method to extract fields.
+ if (!Sizes.count(I->first.second)) {
+ emitHelper(o, 8*I->first.second);
+ Sizes.insert(I->first.second);
+ }
+
+ // Emit the decoder for this namespace+width combination.
+ FilterChooser FC(NumberedInstructions, I->second, Operands,
+ 8*I->first.second, this);
+ FC.emitTop(o, 0, I->first.first);
+ }
o << "\n} // End llvm namespace \n";
}
diff --git a/utils/TableGen/FixedLenDecoderEmitter.h b/utils/TableGen/FixedLenDecoderEmitter.h
index d46a495..2df5448 100644
--- a/utils/TableGen/FixedLenDecoderEmitter.h
+++ b/utils/TableGen/FixedLenDecoderEmitter.h
@@ -16,26 +16,51 @@
#define FixedLenDECODEREMITTER_H
#include "CodeGenTarget.h"
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
+struct EncodingField {
+ unsigned Base, Width, Offset;
+ EncodingField(unsigned B, unsigned W, unsigned O)
+ : Base(B), Width(W), Offset(O) { }
+};
+
struct OperandInfo {
- unsigned FieldBase;
- unsigned FieldLength;
+ std::vector<EncodingField> Fields;
std::string Decoder;
- OperandInfo(unsigned FB, unsigned FL, std::string D)
- : FieldBase(FB), FieldLength(FL), Decoder(D) { }
+ OperandInfo(std::string D)
+ : Decoder(D) { }
+
+ void addField(unsigned Base, unsigned Width, unsigned Offset) {
+ Fields.push_back(EncodingField(Base, Width, Offset));
+ }
+
+ unsigned numFields() { return Fields.size(); }
+
+ typedef std::vector<EncodingField>::iterator iterator;
+
+ iterator begin() { return Fields.begin(); }
+ iterator end() { return Fields.end(); }
};
class FixedLenDecoderEmitter : public TableGenBackend {
public:
- FixedLenDecoderEmitter(RecordKeeper &R) :
+ FixedLenDecoderEmitter(RecordKeeper &R,
+ std::string PredicateNamespace,
+ std::string GPrefix = "if (",
+ std::string GPostfix = " == MCDisassembler::Fail) return MCDisassembler::Fail;",
+ std::string ROK = "MCDisassembler::Success",
+ std::string RFail = "MCDisassembler::Fail",
+ std::string L = "") :
Records(R), Target(R),
- NumberedInstructions(Target.getInstructionsByEnumValue()) {}
+ NumberedInstructions(Target.getInstructionsByEnumValue()),
+ PredicateNamespace(PredicateNamespace),
+ GuardPrefix(GPrefix), GuardPostfix(GPostfix),
+ ReturnOK(ROK), ReturnFail(RFail), Locals(L) {}
// run - Output the code emitter
void run(raw_ostream &o);
@@ -46,9 +71,11 @@ private:
std::vector<const CodeGenInstruction*> NumberedInstructions;
std::vector<unsigned> Opcodes;
std::map<unsigned, std::vector<OperandInfo> > Operands;
-
- bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc);
- void populateInstructions();
+public:
+ std::string PredicateNamespace;
+ std::string GuardPrefix, GuardPostfix;
+ std::string ReturnOK, ReturnFail;
+ std::string Locals;
};
} // end llvm namespace
diff --git a/utils/TableGen/InstrEnumEmitter.cpp b/utils/TableGen/InstrEnumEmitter.cpp
index aa59689..5981afd 100644
--- a/utils/TableGen/InstrEnumEmitter.cpp
+++ b/utils/TableGen/InstrEnumEmitter.cpp
@@ -14,7 +14,7 @@
#include "InstrEnumEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include <cstdio>
using namespace llvm;
diff --git a/utils/TableGen/InstrEnumEmitter.h b/utils/TableGen/InstrEnumEmitter.h
index 89f8b65..c29a309 100644
--- a/utils/TableGen/InstrEnumEmitter.h
+++ b/utils/TableGen/InstrEnumEmitter.h
@@ -15,7 +15,7 @@
#ifndef INSTRENUM_EMITTER_H
#define INSTRENUM_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 5ebaf17..8341724 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -14,7 +14,7 @@
#include "InstrInfoEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
using namespace llvm;
@@ -268,6 +268,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
<< Inst.TheDef->getName() << "\", 0";
// Emit all of the target indepedent flags...
+ if (Inst.isPseudo) OS << "|(1<<MCID::Pseudo)";
if (Inst.isReturn) OS << "|(1<<MCID::Return)";
if (Inst.isBranch) OS << "|(1<<MCID::Branch)";
if (Inst.isIndirectBranch) OS << "|(1<<MCID::IndirectBranch)";
@@ -288,6 +289,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
if (Inst.isNotDuplicable) OS << "|(1<<MCID::NotDuplicable)";
if (Inst.Operands.hasOptionalDef) OS << "|(1<<MCID::HasOptionalDef)";
if (Inst.usesCustomInserter) OS << "|(1<<MCID::UsesCustomInserter)";
+ if (Inst.hasPostISelHook) OS << "|(1<<MCID::HasPostISelHook)";
if (Inst.Operands.isVariadic)OS << "|(1<<MCID::Variadic)";
if (Inst.hasSideEffects) OS << "|(1<<MCID::UnmodeledSideEffects)";
if (Inst.isAsCheapAsAMove) OS << "|(1<<MCID::CheapAsAMove)";
diff --git a/utils/TableGen/InstrInfoEmitter.h b/utils/TableGen/InstrInfoEmitter.h
index 165ce42..1461e2c 100644
--- a/utils/TableGen/InstrInfoEmitter.h
+++ b/utils/TableGen/InstrInfoEmitter.h
@@ -15,8 +15,8 @@
#ifndef INSTRINFO_EMITTER_H
#define INSTRINFO_EMITTER_H
-#include "TableGenBackend.h"
#include "CodeGenDAGPatterns.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
#include <map>
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index e5e7cea..782b89e 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -13,8 +13,8 @@
#include "CodeGenTarget.h"
#include "IntrinsicEmitter.h"
-#include "Record.h"
#include "StringMatcher.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
using namespace llvm;
diff --git a/utils/TableGen/IntrinsicEmitter.h b/utils/TableGen/IntrinsicEmitter.h
index b1efecb..eb6379c 100644
--- a/utils/TableGen/IntrinsicEmitter.h
+++ b/utils/TableGen/IntrinsicEmitter.h
@@ -15,7 +15,7 @@
#define INTRINSIC_EMITTER_H
#include "CodeGenIntrinsics.h"
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
class IntrinsicEmitter : public TableGenBackend {
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp
deleted file mode 100644
index cd0cbeb..0000000
--- a/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ /dev/null
@@ -1,3134 +0,0 @@
-//===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open
-// Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This tablegen backend is responsible for emitting LLVMC configuration code.
-//
-//===----------------------------------------------------------------------===//
-
-#include "LLVMCConfigurationEmitter.h"
-#include "Record.h"
-
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringSet.h"
-
-#include <algorithm>
-#include <cassert>
-#include <functional>
-#include <stdexcept>
-#include <string>
-#include <typeinfo>
-
-
-using namespace llvm;
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-/// Typedefs
-
-typedef std::vector<Record*> RecordVector;
-typedef std::vector<const DagInit*> DagVector;
-typedef std::vector<std::string> StrVector;
-
-//===----------------------------------------------------------------------===//
-/// Constants
-
-// Indentation.
-const unsigned TabWidth = 4;
-const unsigned Indent1 = TabWidth*1;
-const unsigned Indent2 = TabWidth*2;
-const unsigned Indent3 = TabWidth*3;
-const unsigned Indent4 = TabWidth*4;
-
-// Default help string.
-const char * const DefaultHelpString = "NO HELP MESSAGE PROVIDED";
-
-// Name for the "sink" option.
-const char * const SinkOptionName = "SinkOption";
-
-//===----------------------------------------------------------------------===//
-/// Helper functions
-
-/// Id - An 'identity' function object.
-struct Id {
- template<typename T0>
- void operator()(const T0&) const {
- }
- template<typename T0, typename T1>
- void operator()(const T0&, const T1&) const {
- }
- template<typename T0, typename T1, typename T2>
- void operator()(const T0&, const T1&, const T2&) const {
- }
-};
-
-int InitPtrToInt(const Init* ptr) {
- const IntInit& val = dynamic_cast<const IntInit&>(*ptr);
- return val.getValue();
-}
-
-bool InitPtrToBool(const Init* ptr) {
- bool ret = false;
- const DefInit& val = dynamic_cast<const DefInit&>(*ptr);
- const std::string& str = val.getAsString();
-
- if (str == "true") {
- ret = true;
- }
- else if (str == "false") {
- ret = false;
- }
- else {
- throw "Incorrect boolean value: '" + str +
- "': must be either 'true' or 'false'";
- }
-
- return ret;
-}
-
-const std::string& InitPtrToString(const Init* ptr) {
- const StringInit& val = dynamic_cast<const StringInit&>(*ptr);
- return val.getValue();
-}
-
-const ListInit& InitPtrToList(const Init* ptr) {
- const ListInit& val = dynamic_cast<const ListInit&>(*ptr);
- return val;
-}
-
-const DagInit& InitPtrToDag(const Init* ptr) {
- const DagInit& val = dynamic_cast<const DagInit&>(*ptr);
- return val;
-}
-
-const std::string GetOperatorName(const DagInit& D) {
- return D.getOperator()->getAsString();
-}
-
-/// CheckBooleanConstant - Check that the provided value is a boolean constant.
-void CheckBooleanConstant(const Init* I) {
- InitPtrToBool(I);
-}
-
-// CheckNumberOfArguments - Ensure that the number of args in d is
-// greater than or equal to min_arguments, otherwise throw an exception.
-void CheckNumberOfArguments (const DagInit& d, unsigned minArgs) {
- if (d.getNumArgs() < minArgs)
- throw GetOperatorName(d) + ": too few arguments!";
-}
-
-// EscapeVariableName - Escape commas and other symbols not allowed
-// in the C++ variable names. Makes it possible to use options named
-// like "Wa," (useful for prefix options).
-std::string EscapeVariableName (const std::string& Var) {
- std::string ret;
- for (unsigned i = 0; i != Var.size(); ++i) {
- char cur_char = Var[i];
- if (cur_char == ',') {
- ret += "_comma_";
- }
- else if (cur_char == '+') {
- ret += "_plus_";
- }
- else if (cur_char == '-') {
- ret += "_dash_";
- }
- else {
- ret.push_back(cur_char);
- }
- }
- return ret;
-}
-
-/// EscapeQuotes - Replace '"' with '\"'.
-std::string EscapeQuotes (const std::string& Var) {
- std::string ret;
- for (unsigned i = 0; i != Var.size(); ++i) {
- char cur_char = Var[i];
- if (cur_char == '"') {
- ret += "\\\"";
- }
- else {
- ret.push_back(cur_char);
- }
- }
- return ret;
-}
-
-/// OneOf - Does the input string contain this character?
-bool OneOf(const char* lst, char c) {
- while (*lst) {
- if (*lst++ == c)
- return true;
- }
- return false;
-}
-
-template <class I, class S>
-void CheckedIncrement(I& P, I E, S ErrorString) {
- ++P;
- if (P == E)
- throw ErrorString;
-}
-
-//===----------------------------------------------------------------------===//
-/// Back-end specific code
-
-
-/// OptionType - One of six different option types. See the
-/// documentation for detailed description of differences.
-namespace OptionType {
-
- enum OptionType { Alias, Switch, SwitchList,
- Parameter, ParameterList, Prefix, PrefixList };
-
- bool IsAlias(OptionType t) {
- return (t == Alias);
- }
-
- bool IsList (OptionType t) {
- return (t == SwitchList || t == ParameterList || t == PrefixList);
- }
-
- bool IsSwitch (OptionType t) {
- return (t == Switch);
- }
-
- bool IsSwitchList (OptionType t) {
- return (t == SwitchList);
- }
-
- bool IsParameter (OptionType t) {
- return (t == Parameter || t == Prefix);
- }
-
-}
-
-OptionType::OptionType stringToOptionType(const std::string& T) {
- if (T == "alias_option")
- return OptionType::Alias;
- else if (T == "switch_option")
- return OptionType::Switch;
- else if (T == "switch_list_option")
- return OptionType::SwitchList;
- else if (T == "parameter_option")
- return OptionType::Parameter;
- else if (T == "parameter_list_option")
- return OptionType::ParameterList;
- else if (T == "prefix_option")
- return OptionType::Prefix;
- else if (T == "prefix_list_option")
- return OptionType::PrefixList;
- else
- throw "Unknown option type: " + T + '!';
-}
-
-namespace OptionDescriptionFlags {
- enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
- ReallyHidden = 0x4, OneOrMore = 0x8,
- Optional = 0x10, CommaSeparated = 0x20,
- ForwardNotSplit = 0x40, ZeroOrMore = 0x80 };
-}
-
-/// OptionDescription - Represents data contained in a single
-/// OptionList entry.
-struct OptionDescription {
- OptionType::OptionType Type;
- std::string Name;
- unsigned Flags;
- std::string Help;
- unsigned MultiVal;
- Init* InitVal;
-
- OptionDescription(OptionType::OptionType t = OptionType::Switch,
- const std::string& n = "",
- const std::string& h = DefaultHelpString)
- : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1), InitVal(0)
- {}
-
- /// GenTypeDeclaration - Returns the C++ variable type of this
- /// option.
- const char* GenTypeDeclaration() const;
-
- /// GenVariableName - Returns the variable name used in the
- /// generated C++ code.
- std::string GenVariableName() const
- { return "autogenerated::" + GenOptionType() + EscapeVariableName(Name); }
-
- /// GenPlainVariableName - Returns the variable name without the namespace
- /// prefix.
- std::string GenPlainVariableName() const
- { return GenOptionType() + EscapeVariableName(Name); }
-
- /// Merge - Merge two option descriptions.
- void Merge (const OptionDescription& other);
-
- /// CheckConsistency - Check that the flags are consistent.
- void CheckConsistency() const;
-
- // Misc convenient getters/setters.
-
- bool isAlias() const;
-
- bool isMultiVal() const;
-
- bool isCommaSeparated() const;
- void setCommaSeparated();
-
- bool isForwardNotSplit() const;
- void setForwardNotSplit();
-
- bool isRequired() const;
- void setRequired();
-
- bool isOneOrMore() const;
- void setOneOrMore();
-
- bool isZeroOrMore() const;
- void setZeroOrMore();
-
- bool isOptional() const;
- void setOptional();
-
- bool isHidden() const;
- void setHidden();
-
- bool isReallyHidden() const;
- void setReallyHidden();
-
- bool isSwitch() const
- { return OptionType::IsSwitch(this->Type); }
-
- bool isSwitchList() const
- { return OptionType::IsSwitchList(this->Type); }
-
- bool isParameter() const
- { return OptionType::IsParameter(this->Type); }
-
- bool isList() const
- { return OptionType::IsList(this->Type); }
-
- bool isParameterList() const
- { return (OptionType::IsList(this->Type)
- && !OptionType::IsSwitchList(this->Type)); }
-
-private:
-
- // GenOptionType - Helper function used by GenVariableName().
- std::string GenOptionType() const;
-};
-
-void OptionDescription::CheckConsistency() const {
- unsigned i = 0;
-
- i += this->isRequired();
- i += this->isOptional();
- i += this->isOneOrMore();
- i += this->isZeroOrMore();
-
- if (i > 1) {
- throw "Only one of (required), (optional), (one_or_more) or "
- "(zero_or_more) properties is allowed!";
- }
-}
-
-void OptionDescription::Merge (const OptionDescription& other)
-{
- if (other.Type != Type)
- throw "Conflicting definitions for the option " + Name + "!";
-
- if (Help == other.Help || Help == DefaultHelpString)
- Help = other.Help;
- else if (other.Help != DefaultHelpString) {
- llvm::errs() << "Warning: several different help strings"
- " defined for option " + Name + "\n";
- }
-
- Flags |= other.Flags;
-}
-
-bool OptionDescription::isAlias() const {
- return OptionType::IsAlias(this->Type);
-}
-
-bool OptionDescription::isMultiVal() const {
- return MultiVal > 1;
-}
-
-bool OptionDescription::isCommaSeparated() const {
- return Flags & OptionDescriptionFlags::CommaSeparated;
-}
-void OptionDescription::setCommaSeparated() {
- Flags |= OptionDescriptionFlags::CommaSeparated;
-}
-
-bool OptionDescription::isForwardNotSplit() const {
- return Flags & OptionDescriptionFlags::ForwardNotSplit;
-}
-void OptionDescription::setForwardNotSplit() {
- Flags |= OptionDescriptionFlags::ForwardNotSplit;
-}
-
-bool OptionDescription::isRequired() const {
- return Flags & OptionDescriptionFlags::Required;
-}
-void OptionDescription::setRequired() {
- Flags |= OptionDescriptionFlags::Required;
-}
-
-bool OptionDescription::isOneOrMore() const {
- return Flags & OptionDescriptionFlags::OneOrMore;
-}
-void OptionDescription::setOneOrMore() {
- Flags |= OptionDescriptionFlags::OneOrMore;
-}
-
-bool OptionDescription::isZeroOrMore() const {
- return Flags & OptionDescriptionFlags::ZeroOrMore;
-}
-void OptionDescription::setZeroOrMore() {
- Flags |= OptionDescriptionFlags::ZeroOrMore;
-}
-
-bool OptionDescription::isOptional() const {
- return Flags & OptionDescriptionFlags::Optional;
-}
-void OptionDescription::setOptional() {
- Flags |= OptionDescriptionFlags::Optional;
-}
-
-bool OptionDescription::isHidden() const {
- return Flags & OptionDescriptionFlags::Hidden;
-}
-void OptionDescription::setHidden() {
- Flags |= OptionDescriptionFlags::Hidden;
-}
-
-bool OptionDescription::isReallyHidden() const {
- return Flags & OptionDescriptionFlags::ReallyHidden;
-}
-void OptionDescription::setReallyHidden() {
- Flags |= OptionDescriptionFlags::ReallyHidden;
-}
-
-const char* OptionDescription::GenTypeDeclaration() const {
- switch (Type) {
- case OptionType::Alias:
- return "cl::alias";
- case OptionType::PrefixList:
- case OptionType::ParameterList:
- return "cl::list<std::string>";
- case OptionType::Switch:
- return "cl::opt<bool>";
- case OptionType::SwitchList:
- return "cl::list<bool>";
- case OptionType::Parameter:
- case OptionType::Prefix:
- default:
- return "cl::opt<std::string>";
- }
-}
-
-std::string OptionDescription::GenOptionType() const {
- switch (Type) {
- case OptionType::Alias:
- return "Alias_";
- case OptionType::PrefixList:
- case OptionType::ParameterList:
- return "List_";
- case OptionType::Switch:
- return "Switch_";
- case OptionType::SwitchList:
- return "SwitchList_";
- case OptionType::Prefix:
- case OptionType::Parameter:
- default:
- return "Parameter_";
- }
-}
-
-/// OptionDescriptions - An OptionDescription array plus some helper
-/// functions.
-class OptionDescriptions {
- typedef StringMap<OptionDescription> container_type;
-
- /// Descriptions - A list of OptionDescriptions.
- container_type Descriptions;
-
-public:
- /// FindOption - exception-throwing wrapper for find().
- const OptionDescription& FindOption(const std::string& OptName) const;
-
- // Wrappers for FindOption that throw an exception in case the option has a
- // wrong type.
- const OptionDescription& FindSwitch(const std::string& OptName) const;
- const OptionDescription& FindParameter(const std::string& OptName) const;
- const OptionDescription& FindParameterList(const std::string& OptName) const;
- const OptionDescription&
- FindListOrParameter(const std::string& OptName) const;
- const OptionDescription&
- FindParameterListOrParameter(const std::string& OptName) const;
-
- /// insertDescription - Insert new OptionDescription into
- /// OptionDescriptions list
- void InsertDescription (const OptionDescription& o);
-
- // Support for STL-style iteration
- typedef container_type::const_iterator const_iterator;
- const_iterator begin() const { return Descriptions.begin(); }
- const_iterator end() const { return Descriptions.end(); }
-};
-
-const OptionDescription&
-OptionDescriptions::FindOption(const std::string& OptName) const {
- const_iterator I = Descriptions.find(OptName);
- if (I != Descriptions.end())
- return I->second;
- else
- throw OptName + ": no such option!";
-}
-
-const OptionDescription&
-OptionDescriptions::FindSwitch(const std::string& OptName) const {
- const OptionDescription& OptDesc = this->FindOption(OptName);
- if (!OptDesc.isSwitch())
- throw OptName + ": incorrect option type - should be a switch!";
- return OptDesc;
-}
-
-const OptionDescription&
-OptionDescriptions::FindParameterList(const std::string& OptName) const {
- const OptionDescription& OptDesc = this->FindOption(OptName);
- if (!OptDesc.isList() || OptDesc.isSwitchList())
- throw OptName + ": incorrect option type - should be a parameter list!";
- return OptDesc;
-}
-
-const OptionDescription&
-OptionDescriptions::FindParameter(const std::string& OptName) const {
- const OptionDescription& OptDesc = this->FindOption(OptName);
- if (!OptDesc.isParameter())
- throw OptName + ": incorrect option type - should be a parameter!";
- return OptDesc;
-}
-
-const OptionDescription&
-OptionDescriptions::FindListOrParameter(const std::string& OptName) const {
- const OptionDescription& OptDesc = this->FindOption(OptName);
- if (!OptDesc.isList() && !OptDesc.isParameter())
- throw OptName
- + ": incorrect option type - should be a list or parameter!";
- return OptDesc;
-}
-
-const OptionDescription&
-OptionDescriptions::FindParameterListOrParameter
-(const std::string& OptName) const {
- const OptionDescription& OptDesc = this->FindOption(OptName);
- if ((!OptDesc.isList() && !OptDesc.isParameter()) || OptDesc.isSwitchList())
- throw OptName
- + ": incorrect option type - should be a parameter list or parameter!";
- return OptDesc;
-}
-
-void OptionDescriptions::InsertDescription (const OptionDescription& o) {
- container_type::iterator I = Descriptions.find(o.Name);
- if (I != Descriptions.end()) {
- OptionDescription& D = I->second;
- D.Merge(o);
- }
- else {
- Descriptions[o.Name] = o;
- }
-}
-
-/// HandlerTable - A base class for function objects implemented as
-/// 'tables of handlers'.
-template <typename Handler>
-class HandlerTable {
-protected:
- // Implementation details.
-
- /// HandlerMap - A map from property names to property handlers
- typedef StringMap<Handler> HandlerMap;
-
- static HandlerMap Handlers_;
- static bool staticMembersInitialized_;
-
-public:
-
- Handler GetHandler (const std::string& HandlerName) const {
- typename HandlerMap::iterator method = Handlers_.find(HandlerName);
-
- if (method != Handlers_.end()) {
- Handler h = method->second;
- return h;
- }
- else {
- throw "No handler found for property " + HandlerName + "!";
- }
- }
-
- void AddHandler(const char* Property, Handler H) {
- Handlers_[Property] = H;
- }
-
-};
-
-template <class Handler, class FunctionObject>
-Handler GetHandler(FunctionObject* Obj, const DagInit& Dag) {
- const std::string& HandlerName = GetOperatorName(Dag);
- return Obj->GetHandler(HandlerName);
-}
-
-template <class FunctionObject>
-void InvokeDagInitHandler(FunctionObject* Obj, Init* I) {
- typedef void (FunctionObject::*Handler) (const DagInit&);
-
- const DagInit& Dag = InitPtrToDag(I);
- Handler h = GetHandler<Handler>(Obj, Dag);
-
- ((Obj)->*(h))(Dag);
-}
-
-template <class FunctionObject>
-void InvokeDagInitHandler(const FunctionObject* const Obj,
- const Init* I, unsigned IndentLevel, raw_ostream& O)
-{
- typedef void (FunctionObject::*Handler)
- (const DagInit&, unsigned IndentLevel, raw_ostream& O) const;
-
- const DagInit& Dag = InitPtrToDag(I);
- Handler h = GetHandler<Handler>(Obj, Dag);
-
- ((Obj)->*(h))(Dag, IndentLevel, O);
-}
-
-template <typename H>
-typename HandlerTable<H>::HandlerMap HandlerTable<H>::Handlers_;
-
-template <typename H>
-bool HandlerTable<H>::staticMembersInitialized_ = false;
-
-
-/// CollectOptionProperties - Function object for iterating over an
-/// option property list.
-class CollectOptionProperties;
-typedef void (CollectOptionProperties::* CollectOptionPropertiesHandler)
-(const DagInit&);
-
-class CollectOptionProperties
-: public HandlerTable<CollectOptionPropertiesHandler>
-{
-private:
-
- /// optDescs_ - OptionDescriptions table. This is where the
- /// information is stored.
- OptionDescription& optDesc_;
-
-public:
-
- explicit CollectOptionProperties(OptionDescription& OD)
- : optDesc_(OD)
- {
- if (!staticMembersInitialized_) {
- AddHandler("help", &CollectOptionProperties::onHelp);
- AddHandler("hidden", &CollectOptionProperties::onHidden);
- AddHandler("init", &CollectOptionProperties::onInit);
- AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
- AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
- AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore);
- AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
- AddHandler("required", &CollectOptionProperties::onRequired);
- AddHandler("optional", &CollectOptionProperties::onOptional);
- AddHandler("comma_separated", &CollectOptionProperties::onCommaSeparated);
- AddHandler("forward_not_split",
- &CollectOptionProperties::onForwardNotSplit);
-
- staticMembersInitialized_ = true;
- }
- }
-
- /// operator() - Just forwards to the corresponding property
- /// handler.
- void operator() (Init* I) {
- InvokeDagInitHandler(this, I);
- }
-
-private:
-
- /// Option property handlers --
- /// Methods that handle option properties such as (help) or (hidden).
-
- void onHelp (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- optDesc_.Help = EscapeQuotes(InitPtrToString(d.getArg(0)));
- }
-
- void onHidden (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
- optDesc_.setHidden();
- }
-
- void onReallyHidden (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
- optDesc_.setReallyHidden();
- }
-
- void onCommaSeparated (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
- if (!optDesc_.isParameterList())
- throw "'comma_separated' is valid only on parameter list options!";
- optDesc_.setCommaSeparated();
- }
-
- void onForwardNotSplit (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
- if (!optDesc_.isParameter())
- throw "'forward_not_split' is valid only for parameter options!";
- optDesc_.setForwardNotSplit();
- }
-
- void onRequired (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
-
- optDesc_.setRequired();
- optDesc_.CheckConsistency();
- }
-
- void onInit (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- Init* i = d.getArg(0);
- const std::string& str = i->getAsString();
-
- bool correct = optDesc_.isParameter() && dynamic_cast<StringInit*>(i);
- correct |= (optDesc_.isSwitch() && (str == "true" || str == "false"));
-
- if (!correct)
- throw "Incorrect usage of the 'init' option property!";
-
- optDesc_.InitVal = i;
- }
-
- void onOneOrMore (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
-
- optDesc_.setOneOrMore();
- optDesc_.CheckConsistency();
- }
-
- void onZeroOrMore (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
-
- if (optDesc_.isList())
- llvm::errs() << "Warning: specifying the 'zero_or_more' property "
- "on a list option has no effect.\n";
-
- optDesc_.setZeroOrMore();
- optDesc_.CheckConsistency();
- }
-
- void onOptional (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
-
- if (!optDesc_.isList())
- llvm::errs() << "Warning: specifying the 'optional' property"
- "on a non-list option has no effect.\n";
-
- optDesc_.setOptional();
- optDesc_.CheckConsistency();
- }
-
- void onMultiVal (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- int val = InitPtrToInt(d.getArg(0));
- if (val < 2)
- throw "Error in the 'multi_val' property: "
- "the value must be greater than 1!";
- if (!optDesc_.isParameterList())
- throw "The multi_val property is valid only on list options!";
- optDesc_.MultiVal = val;
- }
-
-};
-
-/// AddOption - A function object that is applied to every option
-/// description. Used by CollectOptionDescriptions.
-class AddOption {
-private:
- OptionDescriptions& OptDescs_;
-
-public:
- explicit AddOption(OptionDescriptions& OD) : OptDescs_(OD)
- {}
-
- void operator()(const Init* i) {
- const DagInit& d = InitPtrToDag(i);
- CheckNumberOfArguments(d, 1);
-
- const OptionType::OptionType Type =
- stringToOptionType(GetOperatorName(d));
- const std::string& Name = InitPtrToString(d.getArg(0));
-
- OptionDescription OD(Type, Name);
-
- CheckNumberOfArguments(d, 2);
-
- // Alias option store the aliased option name in the 'Help' field and do not
- // have any properties.
- if (OD.isAlias()) {
- OD.Help = InitPtrToString(d.getArg(1));
- }
- else {
- processOptionProperties(d, OD);
- }
-
- // Switch options are ZeroOrMore by default.
- if (OD.isSwitch()) {
- if (!(OD.isOptional() || OD.isOneOrMore() || OD.isRequired()))
- OD.setZeroOrMore();
- }
-
- OptDescs_.InsertDescription(OD);
- }
-
-private:
- /// processOptionProperties - Go through the list of option
- /// properties and call a corresponding handler for each.
- static void processOptionProperties (const DagInit& d, OptionDescription& o) {
- CheckNumberOfArguments(d, 2);
- DagInit::const_arg_iterator B = d.arg_begin();
- // Skip the first argument: it's always the option name.
- ++B;
- std::for_each(B, d.arg_end(), CollectOptionProperties(o));
- }
-
-};
-
-/// CollectOptionDescriptions - Collects option properties from all
-/// OptionLists.
-void CollectOptionDescriptions (const RecordVector& V,
- OptionDescriptions& OptDescs)
-{
- // For every OptionList:
- for (RecordVector::const_iterator B = V.begin(), E = V.end(); B!=E; ++B)
- {
- // Throws an exception if the value does not exist.
- ListInit* PropList = (*B)->getValueAsListInit("options");
-
- // For every option description in this list: invoke AddOption.
- std::for_each(PropList->begin(), PropList->end(), AddOption(OptDescs));
- }
-}
-
-// Tool information record
-
-namespace ToolFlags {
- enum ToolFlags { Join = 0x1, Sink = 0x2 };
-}
-
-struct ToolDescription : public RefCountedBase<ToolDescription> {
- std::string Name;
- Init* CmdLine;
- Init* Actions;
- StrVector InLanguage;
- std::string InFileOption;
- std::string OutFileOption;
- StrVector OutLanguage;
- std::string OutputSuffix;
- unsigned Flags;
- const Init* OnEmpty;
-
- // Various boolean properties
- void setSink() { Flags |= ToolFlags::Sink; }
- bool isSink() const { return Flags & ToolFlags::Sink; }
- void setJoin() { Flags |= ToolFlags::Join; }
- bool isJoin() const { return Flags & ToolFlags::Join; }
-
- // Default ctor here is needed because StringMap can only store
- // DefaultConstructible objects
- ToolDescription (const std::string &n = "")
- : Name(n), CmdLine(0), Actions(0), OutFileOption("-o"),
- Flags(0), OnEmpty(0)
- {}
-};
-
-/// ToolDescriptions - A list of Tool information records.
-typedef std::vector<IntrusiveRefCntPtr<ToolDescription> > ToolDescriptions;
-
-
-/// CollectToolProperties - Function object for iterating over a list of
-/// tool property records.
-
-class CollectToolProperties;
-typedef void (CollectToolProperties::* CollectToolPropertiesHandler)
-(const DagInit&);
-
-class CollectToolProperties : public HandlerTable<CollectToolPropertiesHandler>
-{
-private:
-
- /// toolDesc_ - Properties of the current Tool. This is where the
- /// information is stored.
- ToolDescription& toolDesc_;
-
-public:
-
- explicit CollectToolProperties (ToolDescription& d)
- : toolDesc_(d)
- {
- if (!staticMembersInitialized_) {
-
- AddHandler("actions", &CollectToolProperties::onActions);
- AddHandler("command", &CollectToolProperties::onCommand);
- AddHandler("in_language", &CollectToolProperties::onInLanguage);
- AddHandler("join", &CollectToolProperties::onJoin);
- AddHandler("out_language", &CollectToolProperties::onOutLanguage);
-
- AddHandler("out_file_option", &CollectToolProperties::onOutFileOption);
- AddHandler("in_file_option", &CollectToolProperties::onInFileOption);
-
- AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix);
- AddHandler("sink", &CollectToolProperties::onSink);
- AddHandler("works_on_empty", &CollectToolProperties::onWorksOnEmpty);
-
- staticMembersInitialized_ = true;
- }
- }
-
- void operator() (Init* I) {
- InvokeDagInitHandler(this, I);
- }
-
-private:
-
- /// Property handlers --
- /// Functions that extract information about tool properties from
- /// DAG representation.
-
- void onActions (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- Init* Case = d.getArg(0);
- if (typeid(*Case) != typeid(DagInit) ||
- GetOperatorName(static_cast<DagInit&>(*Case)) != "case")
- throw "The argument to (actions) should be a 'case' construct!";
- toolDesc_.Actions = Case;
- }
-
- void onCommand (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- toolDesc_.CmdLine = d.getArg(0);
- }
-
- /// onInOutLanguage - Common implementation of on{In,Out}Language().
- void onInOutLanguage (const DagInit& d, StrVector& OutVec) {
- CheckNumberOfArguments(d, 1);
-
- // Copy strings to the output vector.
- for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
- OutVec.push_back(InitPtrToString(d.getArg(i)));
- }
-
- // Remove duplicates.
- std::sort(OutVec.begin(), OutVec.end());
- StrVector::iterator newE = std::unique(OutVec.begin(), OutVec.end());
- OutVec.erase(newE, OutVec.end());
- }
-
-
- void onInLanguage (const DagInit& d) {
- this->onInOutLanguage(d, toolDesc_.InLanguage);
- }
-
- void onJoin (const DagInit& d) {
- bool isReallyJoin = false;
-
- if (d.getNumArgs() == 0) {
- isReallyJoin = true;
- }
- else {
- Init* I = d.getArg(0);
- isReallyJoin = InitPtrToBool(I);
- }
-
- // Is this *really* a join tool? We allow (join false) for generating two
- // tool descriptions from a single generic one.
- // TOFIX: come up with a cleaner solution.
- if (isReallyJoin) {
- toolDesc_.setJoin();
- }
- }
-
- void onOutLanguage (const DagInit& d) {
- this->onInOutLanguage(d, toolDesc_.OutLanguage);
- }
-
- void onOutFileOption (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- toolDesc_.OutFileOption = InitPtrToString(d.getArg(0));
- }
-
- void onInFileOption (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- toolDesc_.InFileOption = InitPtrToString(d.getArg(0));
- }
-
- void onOutputSuffix (const DagInit& d) {
- CheckNumberOfArguments(d, 1);
- toolDesc_.OutputSuffix = InitPtrToString(d.getArg(0));
- }
-
- void onSink (const DagInit& d) {
- CheckNumberOfArguments(d, 0);
- toolDesc_.setSink();
- }
-
- void onWorksOnEmpty (const DagInit& d) {
- toolDesc_.OnEmpty = d.getArg(0);
- }
-
-};
-
-/// CollectToolDescriptions - Gather information about tool properties
-/// from the parsed TableGen data (basically a wrapper for the
-/// CollectToolProperties function object).
-void CollectToolDescriptions (const RecordVector& Tools,
- ToolDescriptions& ToolDescs)
-{
- // Iterate over a properties list of every Tool definition
- for (RecordVector::const_iterator B = Tools.begin(),
- E = Tools.end(); B!=E; ++B) {
- const Record* T = *B;
- // Throws an exception if the value does not exist.
- ListInit* PropList = T->getValueAsListInit("properties");
-
- IntrusiveRefCntPtr<ToolDescription>
- ToolDesc(new ToolDescription(T->getName()));
-
- std::for_each(PropList->begin(), PropList->end(),
- CollectToolProperties(*ToolDesc));
- ToolDescs.push_back(ToolDesc);
- }
-}
-
-/// FillInEdgeVector - Merge all compilation graph definitions into
-/// one single edge list.
-void FillInEdgeVector(const RecordVector& CompilationGraphs,
- DagVector& Out) {
- for (RecordVector::const_iterator B = CompilationGraphs.begin(),
- E = CompilationGraphs.end(); B != E; ++B) {
- const ListInit* Edges = (*B)->getValueAsListInit("edges");
-
- for (ListInit::const_iterator B = Edges->begin(),
- E = Edges->end(); B != E; ++B) {
- Out.push_back(&InitPtrToDag(*B));
- }
- }
-}
-
-/// NotInGraph - Helper function object for FilterNotInGraph.
-struct NotInGraph {
-private:
- const llvm::StringSet<>& ToolsInGraph_;
-
-public:
- NotInGraph(const llvm::StringSet<>& ToolsInGraph)
- : ToolsInGraph_(ToolsInGraph)
- {}
-
- bool operator()(const IntrusiveRefCntPtr<ToolDescription>& x) {
- return (ToolsInGraph_.count(x->Name) == 0);
- }
-};
-
-/// FilterNotInGraph - Filter out from ToolDescs all Tools not
-/// mentioned in the compilation graph definition.
-void FilterNotInGraph (const DagVector& EdgeVector,
- ToolDescriptions& ToolDescs) {
-
- // List all tools mentioned in the graph.
- llvm::StringSet<> ToolsInGraph;
-
- for (DagVector::const_iterator B = EdgeVector.begin(),
- E = EdgeVector.end(); B != E; ++B) {
-
- const DagInit* Edge = *B;
- const std::string& NodeA = InitPtrToString(Edge->getArg(0));
- const std::string& NodeB = InitPtrToString(Edge->getArg(1));
-
- if (NodeA != "root")
- ToolsInGraph.insert(NodeA);
- ToolsInGraph.insert(NodeB);
- }
-
- // Filter ToolPropertiesList.
- ToolDescriptions::iterator new_end =
- std::remove_if(ToolDescs.begin(), ToolDescs.end(),
- NotInGraph(ToolsInGraph));
- ToolDescs.erase(new_end, ToolDescs.end());
-}
-
-/// FillInToolToLang - Fills in two tables that map tool names to
-/// input & output language names. Helper function used by TypecheckGraph().
-void FillInToolToLang (const ToolDescriptions& ToolDescs,
- StringMap<StringSet<> >& ToolToInLang,
- StringMap<StringSet<> >& ToolToOutLang) {
- for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
- E = ToolDescs.end(); B != E; ++B) {
- const ToolDescription& D = *(*B);
- for (StrVector::const_iterator B = D.InLanguage.begin(),
- E = D.InLanguage.end(); B != E; ++B)
- ToolToInLang[D.Name].insert(*B);
- for (StrVector::const_iterator B = D.OutLanguage.begin(),
- E = D.OutLanguage.end(); B != E; ++B)
- ToolToOutLang[D.Name].insert(*B);
- }
-}
-
-/// Intersect - Is set intersection non-empty?
-bool Intersect (const StringSet<>& S1, const StringSet<>& S2) {
- for (StringSet<>::const_iterator B = S1.begin(), E = S1.end(); B != E; ++B) {
- if (S2.count(B->first()) != 0)
- return true;
- }
- return false;
-}
-
-/// TypecheckGraph - Check that names for output and input languages
-/// on all edges do match.
-void TypecheckGraph (const DagVector& EdgeVector,
- const ToolDescriptions& ToolDescs) {
- StringMap<StringSet<> > ToolToInLang;
- StringMap<StringSet<> > ToolToOutLang;
-
- FillInToolToLang(ToolDescs, ToolToInLang, ToolToOutLang);
-
- for (DagVector::const_iterator B = EdgeVector.begin(),
- E = EdgeVector.end(); B != E; ++B) {
- const DagInit* Edge = *B;
- const std::string& NodeA = InitPtrToString(Edge->getArg(0));
- const std::string& NodeB = InitPtrToString(Edge->getArg(1));
- StringMap<StringSet<> >::iterator IA = ToolToOutLang.find(NodeA);
- StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB);
-
- if (NodeB == "root")
- throw "Edges back to the root are not allowed!";
-
- if (NodeA != "root") {
- if (IA == ToolToOutLang.end())
- throw NodeA + ": no output language defined!";
- if (IB == ToolToInLang.end())
- throw NodeB + ": no input language defined!";
-
- if (!Intersect(IA->second, IB->second)) {
- throw "Edge " + NodeA + "->" + NodeB
- + ": output->input language mismatch";
- }
- }
- }
-}
-
-/// WalkCase - Walks the 'case' expression DAG and invokes
-/// TestCallback on every test, and StatementCallback on every
-/// statement. Handles 'case' nesting, but not the 'and' and 'or'
-/// combinators (that is, they are passed directly to TestCallback).
-/// TestCallback must have type 'void TestCallback(const DagInit*, unsigned
-/// IndentLevel, bool FirstTest)'.
-/// StatementCallback must have type 'void StatementCallback(const Init*,
-/// unsigned IndentLevel)'.
-template <typename F1, typename F2>
-void WalkCase(const Init* Case, F1 TestCallback, F2 StatementCallback,
- unsigned IndentLevel = 0)
-{
- const DagInit& d = InitPtrToDag(Case);
-
- // Error checks.
- if (GetOperatorName(d) != "case")
- throw "WalkCase should be invoked only on 'case' expressions!";
-
- if (d.getNumArgs() < 2)
- throw "There should be at least one clause in the 'case' expression:\n"
- + d.getAsString();
-
- // Main loop.
- bool even = false;
- const unsigned numArgs = d.getNumArgs();
- unsigned i = 1;
- for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
- B != E; ++B) {
- Init* arg = *B;
-
- if (!even)
- {
- // Handle test.
- const DagInit& Test = InitPtrToDag(arg);
-
- if (GetOperatorName(Test) == "default" && (i+1 != numArgs))
- throw "The 'default' clause should be the last in the "
- "'case' construct!";
- if (i == numArgs)
- throw "Case construct handler: no corresponding action "
- "found for the test " + Test.getAsString() + '!';
-
- TestCallback(Test, IndentLevel, (i == 1));
- }
- else
- {
- if (dynamic_cast<DagInit*>(arg)
- && GetOperatorName(static_cast<DagInit&>(*arg)) == "case") {
- // Nested 'case'.
- WalkCase(arg, TestCallback, StatementCallback, IndentLevel + Indent1);
- }
-
- // Handle statement.
- StatementCallback(arg, IndentLevel);
- }
-
- ++i;
- even = !even;
- }
-}
-
-/// ExtractOptionNames - A helper function object used by
-/// CheckForSuperfluousOptions() to walk the 'case' DAG.
-class ExtractOptionNames {
- llvm::StringSet<>& OptionNames_;
-
- void processDag(const Init* Statement) {
- const DagInit& Stmt = InitPtrToDag(Statement);
- const std::string& ActionName = GetOperatorName(Stmt);
- if (ActionName == "forward" || ActionName == "forward_as" ||
- ActionName == "forward_value" ||
- ActionName == "forward_transformed_value" ||
- ActionName == "parameter_equals" || ActionName == "element_in_list") {
- CheckNumberOfArguments(Stmt, 1);
-
- Init* Arg = Stmt.getArg(0);
- if (typeid(*Arg) == typeid(StringInit))
- OptionNames_.insert(InitPtrToString(Arg));
- }
- else if (ActionName == "any_switch_on" || ActionName == "switch_on" ||
- ActionName == "any_not_empty" || ActionName == "any_empty" ||
- ActionName == "not_empty" || ActionName == "empty") {
- for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) {
- Init* Arg = Stmt.getArg(i);
- if (typeid(*Arg) == typeid(StringInit))
- OptionNames_.insert(InitPtrToString(Arg));
- }
- }
- else if (ActionName == "and" || ActionName == "or" || ActionName == "not") {
- for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) {
- this->processDag(Stmt.getArg(i));
- }
- }
- }
-
-public:
- ExtractOptionNames(llvm::StringSet<>& OptionNames) : OptionNames_(OptionNames)
- {}
-
- void operator()(const Init* Statement) {
- // Statement is either a dag, or a list of dags.
- if (typeid(*Statement) == typeid(ListInit)) {
- const ListInit& DagList = *static_cast<const ListInit*>(Statement);
- for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
- B != E; ++B)
- this->processDag(*B);
- }
- else {
- this->processDag(Statement);
- }
- }
-
- void operator()(const DagInit& Test, unsigned, bool) {
- this->operator()(&Test);
- }
- void operator()(const Init* Statement, unsigned) {
- this->operator()(Statement);
- }
-};
-
-/// IsOptionalEdge - Validate that the 'optional_edge' has proper structure.
-bool IsOptionalEdge (const DagInit& Edg) {
- return (GetOperatorName(Edg) == "optional_edge") && (Edg.getNumArgs() > 2);
-}
-
-/// CheckForSuperfluousOptions - Check that there are no side
-/// effect-free options (specified only in the OptionList). Otherwise,
-/// output a warning.
-void CheckForSuperfluousOptions (const DagVector& EdgeVector,
- const ToolDescriptions& ToolDescs,
- const OptionDescriptions& OptDescs) {
- llvm::StringSet<> nonSuperfluousOptions;
-
- // Add all options mentioned in the ToolDesc.Actions to the set of
- // non-superfluous options.
- for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
- E = ToolDescs.end(); B != E; ++B) {
- const ToolDescription& TD = *(*B);
- ExtractOptionNames Callback(nonSuperfluousOptions);
- if (TD.Actions)
- WalkCase(TD.Actions, Callback, Callback);
- }
-
- // Add all options mentioned in the 'case' clauses of the
- // OptionalEdges of the compilation graph to the set of
- // non-superfluous options.
- for (DagVector::const_iterator B = EdgeVector.begin(),
- E = EdgeVector.end(); B != E; ++B) {
- const DagInit& Edge = **B;
- if (IsOptionalEdge(Edge)) {
- const DagInit& Weight = InitPtrToDag(Edge.getArg(2));
- WalkCase(&Weight, ExtractOptionNames(nonSuperfluousOptions), Id());
- }
- }
-
- // Check that all options in OptDescs belong to the set of
- // non-superfluous options.
- for (OptionDescriptions::const_iterator B = OptDescs.begin(),
- E = OptDescs.end(); B != E; ++B) {
- const OptionDescription& Val = B->second;
- if (!nonSuperfluousOptions.count(Val.Name)
- && Val.Type != OptionType::Alias)
- llvm::errs() << "Warning: option '-" << Val.Name << "' has no effect! "
- "Probable cause: this option is specified only in the OptionList.\n";
- }
-}
-
-/// EmitCaseTest0Args - Helper function used by EmitCaseConstructHandler().
-bool EmitCaseTest0Args(const std::string& TestName, raw_ostream& O) {
- if (TestName == "single_input_file") {
- O << "InputFilenames.size() == 1";
- return true;
- }
- else if (TestName == "multiple_input_files") {
- O << "InputFilenames.size() > 1";
- return true;
- }
-
- return false;
-}
-
-/// EmitMultipleArgumentTest - Helper function used by
-/// EmitCaseTestMultipleArgs()
-template <typename F>
-void EmitMultipleArgumentTest(const DagInit& D, const char* LogicOp,
- F Callback, raw_ostream& O)
-{
- for (unsigned i = 0, NumArgs = D.getNumArgs(); i < NumArgs; ++i) {
- if (i != 0)
- O << ' ' << LogicOp << ' ';
- Callback(InitPtrToString(D.getArg(i)), O);
- }
-}
-
-// Callbacks for use with EmitMultipleArgumentTest
-
-class EmitSwitchOn {
- const OptionDescriptions& OptDescs_;
-public:
- EmitSwitchOn(const OptionDescriptions& OptDescs) : OptDescs_(OptDescs)
- {}
-
- void operator()(const std::string& OptName, raw_ostream& O) const {
- const OptionDescription& OptDesc = OptDescs_.FindSwitch(OptName);
- O << OptDesc.GenVariableName();
- }
-};
-
-class EmitEmptyTest {
- bool EmitNegate_;
- const OptionDescriptions& OptDescs_;
-public:
- EmitEmptyTest(bool EmitNegate, const OptionDescriptions& OptDescs)
- : EmitNegate_(EmitNegate), OptDescs_(OptDescs)
- {}
-
- void operator()(const std::string& OptName, raw_ostream& O) const {
- const char* Neg = (EmitNegate_ ? "!" : "");
- if (OptName == "o") {
- O << Neg << "OutputFilename.empty()";
- }
- else if (OptName == "save-temps") {
- O << Neg << "(SaveTemps == SaveTempsEnum::Unset)";
- }
- else {
- const OptionDescription& OptDesc = OptDescs_.FindListOrParameter(OptName);
- O << Neg << OptDesc.GenVariableName() << ".empty()";
- }
- }
-};
-
-
-/// EmitCaseTestMultipleArgs - Helper function used by EmitCaseTest1Arg()
-bool EmitCaseTestMultipleArgs (const std::string& TestName,
- const DagInit& d,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- if (TestName == "any_switch_on") {
- EmitMultipleArgumentTest(d, "||", EmitSwitchOn(OptDescs), O);
- return true;
- }
- else if (TestName == "switch_on") {
- EmitMultipleArgumentTest(d, "&&", EmitSwitchOn(OptDescs), O);
- return true;
- }
- else if (TestName == "any_not_empty") {
- EmitMultipleArgumentTest(d, "||", EmitEmptyTest(true, OptDescs), O);
- return true;
- }
- else if (TestName == "any_empty") {
- EmitMultipleArgumentTest(d, "||", EmitEmptyTest(false, OptDescs), O);
- return true;
- }
- else if (TestName == "not_empty") {
- EmitMultipleArgumentTest(d, "&&", EmitEmptyTest(true, OptDescs), O);
- return true;
- }
- else if (TestName == "empty") {
- EmitMultipleArgumentTest(d, "&&", EmitEmptyTest(false, OptDescs), O);
- return true;
- }
-
- return false;
-}
-
-/// EmitCaseTest1Arg - Helper function used by EmitCaseTest1OrMoreArgs()
-bool EmitCaseTest1Arg (const std::string& TestName,
- const DagInit& d,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- const std::string& Arg = InitPtrToString(d.getArg(0));
-
- if (TestName == "input_languages_contain") {
- O << "InLangs.count(\"" << Arg << "\") != 0";
- return true;
- }
- else if (TestName == "in_language") {
- // This works only for single-argument Tool::GenerateAction. Join
- // tools can process several files in different languages simultaneously.
-
- // TODO: make this work with Edge::Weight (if possible).
- O << "LangMap.GetLanguage(inFile) == \"" << Arg << '\"';
- return true;
- }
-
- return false;
-}
-
-/// EmitCaseTest1OrMoreArgs - Helper function used by
-/// EmitCaseConstructHandler()
-bool EmitCaseTest1OrMoreArgs(const std::string& TestName,
- const DagInit& d,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- CheckNumberOfArguments(d, 1);
- return EmitCaseTest1Arg(TestName, d, OptDescs, O) ||
- EmitCaseTestMultipleArgs(TestName, d, OptDescs, O);
-}
-
-/// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler().
-bool EmitCaseTest2Args(const std::string& TestName,
- const DagInit& d,
- unsigned IndentLevel,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- CheckNumberOfArguments(d, 2);
- const std::string& OptName = InitPtrToString(d.getArg(0));
- const std::string& OptArg = InitPtrToString(d.getArg(1));
-
- if (TestName == "parameter_equals") {
- const OptionDescription& OptDesc = OptDescs.FindParameter(OptName);
- O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
- return true;
- }
- else if (TestName == "element_in_list") {
- const OptionDescription& OptDesc = OptDescs.FindParameterList(OptName);
- const std::string& VarName = OptDesc.GenVariableName();
- O << "std::find(" << VarName << ".begin(),\n";
- O.indent(IndentLevel + Indent1)
- << VarName << ".end(), \""
- << OptArg << "\") != " << VarName << ".end()";
- return true;
- }
-
- return false;
-}
-
-// Forward declaration.
-// EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
-void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
- const OptionDescriptions& OptDescs,
- raw_ostream& O);
-
-/// EmitLogicalOperationTest - Helper function used by
-/// EmitCaseConstructHandler.
-void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
- unsigned IndentLevel,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- O << '(';
- for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
- const DagInit& InnerTest = InitPtrToDag(d.getArg(i));
- EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
- if (i != NumArgs - 1) {
- O << ")\n";
- O.indent(IndentLevel + Indent1) << ' ' << LogicOp << " (";
- }
- else {
- O << ')';
- }
- }
-}
-
-void EmitLogicalNot(const DagInit& d, unsigned IndentLevel,
- const OptionDescriptions& OptDescs, raw_ostream& O)
-{
- CheckNumberOfArguments(d, 1);
- const DagInit& InnerTest = InitPtrToDag(d.getArg(0));
- O << "! (";
- EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
- O << ")";
-}
-
-/// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
-void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- const std::string& TestName = GetOperatorName(d);
-
- if (TestName == "and")
- EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
- else if (TestName == "or")
- EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O);
- else if (TestName == "not")
- EmitLogicalNot(d, IndentLevel, OptDescs, O);
- else if (EmitCaseTest0Args(TestName, O))
- return;
- else if (EmitCaseTest1OrMoreArgs(TestName, d, OptDescs, O))
- return;
- else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O))
- return;
- else
- throw "Unknown test '" + TestName + "' used in the 'case' construct!";
-}
-
-
-/// EmitCaseTestCallback - Callback used by EmitCaseConstructHandler.
-class EmitCaseTestCallback {
- bool EmitElseIf_;
- const OptionDescriptions& OptDescs_;
- raw_ostream& O_;
-public:
-
- EmitCaseTestCallback(bool EmitElseIf,
- const OptionDescriptions& OptDescs, raw_ostream& O)
- : EmitElseIf_(EmitElseIf), OptDescs_(OptDescs), O_(O)
- {}
-
- void operator()(const DagInit& Test, unsigned IndentLevel, bool FirstTest)
- {
- if (GetOperatorName(Test) == "default") {
- O_.indent(IndentLevel) << "else {\n";
- }
- else {
- O_.indent(IndentLevel)
- << ((!FirstTest && EmitElseIf_) ? "else if (" : "if (");
- EmitCaseTest(Test, IndentLevel, OptDescs_, O_);
- O_ << ") {\n";
- }
- }
-};
-
-/// EmitCaseStatementCallback - Callback used by EmitCaseConstructHandler.
-template <typename F>
-class EmitCaseStatementCallback {
- F Callback_;
- raw_ostream& O_;
-public:
-
- EmitCaseStatementCallback(F Callback, raw_ostream& O)
- : Callback_(Callback), O_(O)
- {}
-
- void operator() (const Init* Statement, unsigned IndentLevel) {
- // Is this a nested 'case'?
- bool IsCase = dynamic_cast<const DagInit*>(Statement) &&
- GetOperatorName(static_cast<const DagInit&>(*Statement)) == "case";
-
- // If so, ignore it, it is handled by our caller, WalkCase.
- if (!IsCase) {
- if (typeid(*Statement) == typeid(ListInit)) {
- const ListInit& DagList = *static_cast<const ListInit*>(Statement);
- for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
- B != E; ++B)
- Callback_(*B, (IndentLevel + Indent1), O_);
- }
- else {
- Callback_(Statement, (IndentLevel + Indent1), O_);
- }
- }
- O_.indent(IndentLevel) << "}\n";
- }
-
-};
-
-/// EmitCaseConstructHandler - Emit code that handles the 'case'
-/// construct. Takes a function object that should emit code for every case
-/// clause. Implemented on top of WalkCase.
-/// Callback's type is void F(const Init* Statement, unsigned IndentLevel,
-/// raw_ostream& O).
-/// EmitElseIf parameter controls the type of condition that is emitted ('if
-/// (..) {..} else if (..) {} .. else {..}' vs. 'if (..) {..} if(..) {..}
-/// .. else {..}').
-template <typename F>
-void EmitCaseConstructHandler(const Init* Case, unsigned IndentLevel,
- F Callback, bool EmitElseIf,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- WalkCase(Case, EmitCaseTestCallback(EmitElseIf, OptDescs, O),
- EmitCaseStatementCallback<F>(Callback, O), IndentLevel);
-}
-
-/// TokenizeCmdLine - converts from
-/// "$CALL(HookName, 'Arg1', 'Arg2')/path -arg1 -arg2" to
-/// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path", "-arg1", "-arg2"].
-void TokenizeCmdLine(const std::string& CmdLine, StrVector& Out) {
- const char* Delimiters = " \t\n\v\f\r";
- enum TokenizerState
- { Normal, SpecialCommand, InsideSpecialCommand, InsideQuotationMarks }
- cur_st = Normal;
-
- if (CmdLine.empty())
- return;
- Out.push_back("");
-
- std::string::size_type B = CmdLine.find_first_not_of(Delimiters),
- E = CmdLine.size();
-
- for (; B != E; ++B) {
- char cur_ch = CmdLine[B];
-
- switch (cur_st) {
- case Normal:
- if (cur_ch == '$') {
- cur_st = SpecialCommand;
- break;
- }
- if (OneOf(Delimiters, cur_ch)) {
- // Skip whitespace
- B = CmdLine.find_first_not_of(Delimiters, B);
- if (B == std::string::npos) {
- B = E-1;
- continue;
- }
- --B;
- Out.push_back("");
- continue;
- }
- break;
-
-
- case SpecialCommand:
- if (OneOf(Delimiters, cur_ch)) {
- cur_st = Normal;
- Out.push_back("");
- continue;
- }
- if (cur_ch == '(') {
- Out.push_back("");
- cur_st = InsideSpecialCommand;
- continue;
- }
- break;
-
- case InsideSpecialCommand:
- if (OneOf(Delimiters, cur_ch)) {
- continue;
- }
- if (cur_ch == '\'') {
- cur_st = InsideQuotationMarks;
- Out.push_back("");
- continue;
- }
- if (cur_ch == ')') {
- cur_st = Normal;
- Out.push_back("");
- }
- if (cur_ch == ',') {
- continue;
- }
-
- break;
-
- case InsideQuotationMarks:
- if (cur_ch == '\'') {
- cur_st = InsideSpecialCommand;
- continue;
- }
- break;
- }
-
- Out.back().push_back(cur_ch);
- }
-}
-
-/// SubstituteCall - Given "$CALL(HookName, [Arg1 [, Arg2 [...]]])", output
-/// "hooks::HookName([Arg1 [, Arg2 [, ...]]])". Helper function used by
-/// SubstituteSpecialCommands().
-StrVector::const_iterator
-SubstituteCall (StrVector::const_iterator Pos,
- StrVector::const_iterator End,
- bool IsJoin, raw_ostream& O)
-{
- const char* errorMessage = "Syntax error in $CALL invocation!";
- CheckedIncrement(Pos, End, errorMessage);
- const std::string& CmdName = *Pos;
-
- if (CmdName == ")")
- throw "$CALL invocation: empty argument list!";
-
- O << "hooks::";
- O << CmdName << "(";
-
-
- bool firstIteration = true;
- while (true) {
- CheckedIncrement(Pos, End, errorMessage);
- const std::string& Arg = *Pos;
- assert(Arg.size() != 0);
-
- if (Arg[0] == ')')
- break;
-
- if (firstIteration)
- firstIteration = false;
- else
- O << ", ";
-
- if (Arg == "$INFILE") {
- if (IsJoin)
- throw "$CALL(Hook, $INFILE) can't be used with a Join tool!";
- else
- O << "inFile.c_str()";
- }
- else {
- O << '"' << Arg << '"';
- }
- }
-
- O << ')';
-
- return Pos;
-}
-
-/// SubstituteEnv - Given '$ENV(VAR_NAME)', output 'getenv("VAR_NAME")'. Helper
-/// function used by SubstituteSpecialCommands().
-StrVector::const_iterator
-SubstituteEnv (StrVector::const_iterator Pos,
- StrVector::const_iterator End, raw_ostream& O)
-{
- const char* errorMessage = "Syntax error in $ENV invocation!";
- CheckedIncrement(Pos, End, errorMessage);
- const std::string& EnvName = *Pos;
-
- if (EnvName == ")")
- throw "$ENV invocation: empty argument list!";
-
- O << "checkCString(std::getenv(\"";
- O << EnvName;
- O << "\"))";
-
- CheckedIncrement(Pos, End, errorMessage);
-
- return Pos;
-}
-
-/// SubstituteSpecialCommands - Given an invocation of $CALL or $ENV, output
-/// handler code. Helper function used by EmitCmdLineVecFill().
-StrVector::const_iterator
-SubstituteSpecialCommands (StrVector::const_iterator Pos,
- StrVector::const_iterator End,
- bool IsJoin, raw_ostream& O)
-{
-
- const std::string& cmd = *Pos;
-
- // Perform substitution.
- if (cmd == "$CALL") {
- Pos = SubstituteCall(Pos, End, IsJoin, O);
- }
- else if (cmd == "$ENV") {
- Pos = SubstituteEnv(Pos, End, O);
- }
- else {
- throw "Unknown special command: " + cmd;
- }
-
- // Handle '$CMD(ARG)/additional/text'.
- const std::string& Leftover = *Pos;
- assert(Leftover.at(0) == ')');
- if (Leftover.size() != 1)
- O << " + std::string(\"" << (Leftover.c_str() + 1) << "\")";
-
- return Pos;
-}
-
-/// EmitCmdLineVecFill - Emit code that fills in the command line
-/// vector. Helper function used by EmitGenerateActionMethod().
-void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
- bool IsJoin, unsigned IndentLevel,
- raw_ostream& O) {
- StrVector StrVec;
- TokenizeCmdLine(InitPtrToString(CmdLine), StrVec);
-
- if (StrVec.empty())
- throw "Tool '" + ToolName + "' has empty command line!";
-
- StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
-
- // Emit the command itself.
- assert(!StrVec[0].empty());
- O.indent(IndentLevel) << "cmd = ";
- if (StrVec[0][0] == '$') {
- B = SubstituteSpecialCommands(B, E, IsJoin, O);
- ++B;
- }
- else {
- O << '"' << StrVec[0] << '"';
- ++B;
- }
- O << ";\n";
-
- // Go through the command arguments.
- assert(B <= E);
- for (; B != E; ++B) {
- const std::string& cmd = *B;
-
- assert(!cmd.empty());
- O.indent(IndentLevel);
-
- if (cmd.at(0) == '$') {
- O << "vec.push_back(std::make_pair(0, ";
- B = SubstituteSpecialCommands(B, E, IsJoin, O);
- O << "));\n";
- }
- else {
- O << "vec.push_back(std::make_pair(0, \"" << cmd << "\"));\n";
- }
- }
-
-}
-
-/// EmitForEachListElementCycleHeader - Emit common code for iterating through
-/// all elements of a list. Helper function used by
-/// EmitForwardOptionPropertyHandlingCode.
-void EmitForEachListElementCycleHeader (const OptionDescription& D,
- unsigned IndentLevel,
- raw_ostream& O) {
- unsigned IndentLevel1 = IndentLevel + Indent1;
-
- O.indent(IndentLevel)
- << "for (" << D.GenTypeDeclaration()
- << "::iterator B = " << D.GenVariableName() << ".begin(),\n";
- O.indent(IndentLevel)
- << "E = " << D.GenVariableName() << ".end(); B != E;) {\n";
- O.indent(IndentLevel1) << "unsigned pos = " << D.GenVariableName()
- << ".getPosition(B - " << D.GenVariableName()
- << ".begin());\n";
-}
-
-/// EmitForwardOptionPropertyHandlingCode - Helper function used to
-/// implement EmitActionHandler. Emits code for
-/// handling the (forward) and (forward_as) option properties.
-void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
- unsigned IndentLevel,
- const std::string& NewName,
- raw_ostream& O) {
- const std::string& Name = NewName.empty()
- ? ("-" + D.Name)
- : NewName;
- unsigned IndentLevel1 = IndentLevel + Indent1;
-
- switch (D.Type) {
- case OptionType::Switch:
- O.indent(IndentLevel)
- << "vec.push_back(std::make_pair(" << D.GenVariableName()
- << ".getPosition(), \"" << Name << "\"));\n";
- break;
- case OptionType::Parameter:
- O.indent(IndentLevel) << "vec.push_back(std::make_pair("
- << D.GenVariableName()
- <<".getPosition(), \"" << Name;
-
- if (!D.isForwardNotSplit()) {
- O << "\"));\n";
- O.indent(IndentLevel) << "vec.push_back(std::make_pair("
- << D.GenVariableName() << ".getPosition(), "
- << D.GenVariableName() << "));\n";
- }
- else {
- O << "=\" + " << D.GenVariableName() << "));\n";
- }
- break;
- case OptionType::Prefix:
- O.indent(IndentLevel) << "vec.push_back(std::make_pair("
- << D.GenVariableName() << ".getPosition(), \""
- << Name << "\" + "
- << D.GenVariableName() << "));\n";
- break;
- case OptionType::PrefixList:
- EmitForEachListElementCycleHeader(D, IndentLevel, O);
- O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
- << Name << "\" + " << "*B));\n";
- O.indent(IndentLevel1) << "++B;\n";
-
- for (int i = 1, j = D.MultiVal; i < j; ++i) {
- O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
- O.indent(IndentLevel1) << "++B;\n";
- }
-
- O.indent(IndentLevel) << "}\n";
- break;
- case OptionType::ParameterList:
- EmitForEachListElementCycleHeader(D, IndentLevel, O);
- O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
- << Name << "\"));\n";
-
- for (int i = 0, j = D.MultiVal; i < j; ++i) {
- O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
- O.indent(IndentLevel1) << "++B;\n";
- }
-
- O.indent(IndentLevel) << "}\n";
- break;
- case OptionType::SwitchList:
- EmitForEachListElementCycleHeader(D, IndentLevel, O);
- O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
- << Name << "\"));\n";
- O.indent(IndentLevel1) << "++B;\n";
- O.indent(IndentLevel) << "}\n";
- break;
- case OptionType::Alias:
- default:
- throw "Aliases are not allowed in tool option descriptions!";
- }
-}
-
-/// ActionHandlingCallbackBase - Base class of EmitActionHandlersCallback and
-/// EmitPreprocessOptionsCallback.
-struct ActionHandlingCallbackBase
-{
-
- void onErrorDag(const DagInit& d,
- unsigned IndentLevel, raw_ostream& O) const
- {
- O.indent(IndentLevel)
- << "PrintError(\""
- << (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0)) : "Unknown error!")
- << "\");\n";
- O.indent(IndentLevel) << "return 1;\n";
- }
-
- void onWarningDag(const DagInit& d,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(d, 1);
- O.indent(IndentLevel) << "llvm::errs() << \""
- << InitPtrToString(d.getArg(0)) << "\";\n";
- }
-
-};
-
-/// EmitActionHandlersCallback - Emit code that handles actions. Used by
-/// EmitGenerateActionMethod() as an argument to EmitCaseConstructHandler().
-class EmitActionHandlersCallback;
-
-typedef void (EmitActionHandlersCallback::* EmitActionHandlersCallbackHandler)
-(const DagInit&, unsigned, raw_ostream&) const;
-
-class EmitActionHandlersCallback :
- public ActionHandlingCallbackBase,
- public HandlerTable<EmitActionHandlersCallbackHandler>
-{
- typedef EmitActionHandlersCallbackHandler Handler;
-
- const OptionDescriptions& OptDescs;
-
- /// EmitHookInvocation - Common code for hook invocation from actions. Used by
- /// onAppendCmd and onOutputSuffix.
- void EmitHookInvocation(const std::string& Str,
- const char* BlockOpen, const char* BlockClose,
- unsigned IndentLevel, raw_ostream& O) const
- {
- StrVector Out;
- TokenizeCmdLine(Str, Out);
-
- for (StrVector::const_iterator B = Out.begin(), E = Out.end();
- B != E; ++B) {
- const std::string& cmd = *B;
-
- O.indent(IndentLevel) << BlockOpen;
-
- if (cmd.at(0) == '$')
- B = SubstituteSpecialCommands(B, E, /* IsJoin = */ true, O);
- else
- O << '"' << cmd << '"';
-
- O << BlockClose;
- }
- }
-
- void onAppendCmd (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 1);
- this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
- "vec.push_back(std::make_pair(65536, ", "));\n",
- IndentLevel, O);
- }
-
- void onForward (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 1);
- const std::string& Name = InitPtrToString(Dag.getArg(0));
- EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
- IndentLevel, "", O);
- }
-
- void onForwardAs (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 2);
- const std::string& Name = InitPtrToString(Dag.getArg(0));
- const std::string& NewName = InitPtrToString(Dag.getArg(1));
- EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
- IndentLevel, NewName, O);
- }
-
- void onForwardValue (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 1);
- const std::string& Name = InitPtrToString(Dag.getArg(0));
- const OptionDescription& D = OptDescs.FindParameterListOrParameter(Name);
-
- if (D.isSwitchList()) {
- throw std::runtime_error
- ("forward_value is not allowed with switch_list");
- }
-
- if (D.isParameter()) {
- O.indent(IndentLevel) << "vec.push_back(std::make_pair("
- << D.GenVariableName() << ".getPosition(), "
- << D.GenVariableName() << "));\n";
- }
- else {
- O.indent(IndentLevel) << "for (" << D.GenTypeDeclaration()
- << "::iterator B = " << D.GenVariableName()
- << ".begin(), \n";
- O.indent(IndentLevel + Indent1) << " E = " << D.GenVariableName()
- << ".end(); B != E; ++B)\n";
- O.indent(IndentLevel) << "{\n";
- O.indent(IndentLevel + Indent1)
- << "unsigned pos = " << D.GenVariableName()
- << ".getPosition(B - " << D.GenVariableName()
- << ".begin());\n";
- O.indent(IndentLevel + Indent1)
- << "vec.push_back(std::make_pair(pos, *B));\n";
- O.indent(IndentLevel) << "}\n";
- }
- }
-
- void onForwardTransformedValue (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 2);
- const std::string& Name = InitPtrToString(Dag.getArg(0));
- const std::string& Hook = InitPtrToString(Dag.getArg(1));
- const OptionDescription& D = OptDescs.FindParameterListOrParameter(Name);
-
- O.indent(IndentLevel) << "vec.push_back(std::make_pair("
- << D.GenVariableName() << ".getPosition("
- << (D.isList() ? "0" : "") << "), "
- << "hooks::" << Hook << "(" << D.GenVariableName()
- << (D.isParameter() ? ".c_str()" : "") << ")));\n";
- }
-
- void onNoOutFile (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 0);
- O.indent(IndentLevel) << "no_out_file = true;\n";
- }
-
- void onOutputSuffix (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(Dag, 1);
- this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
- "output_suffix = ", ";\n", IndentLevel, O);
- }
-
- void onStopCompilation (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- O.indent(IndentLevel) << "stop_compilation = true;\n";
- }
-
-
- void onUnpackValues (const DagInit& Dag,
- unsigned IndentLevel, raw_ostream& O) const
- {
- throw "'unpack_values' is deprecated. "
- "Use 'comma_separated' + 'forward_value' instead!";
- }
-
- public:
-
- explicit EmitActionHandlersCallback(const OptionDescriptions& OD)
- : OptDescs(OD)
- {
- if (!staticMembersInitialized_) {
- AddHandler("error", &EmitActionHandlersCallback::onErrorDag);
- AddHandler("warning", &EmitActionHandlersCallback::onWarningDag);
- AddHandler("append_cmd", &EmitActionHandlersCallback::onAppendCmd);
- AddHandler("forward", &EmitActionHandlersCallback::onForward);
- AddHandler("forward_as", &EmitActionHandlersCallback::onForwardAs);
- AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue);
- AddHandler("forward_transformed_value",
- &EmitActionHandlersCallback::onForwardTransformedValue);
- AddHandler("no_out_file",
- &EmitActionHandlersCallback::onNoOutFile);
- AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix);
- AddHandler("stop_compilation",
- &EmitActionHandlersCallback::onStopCompilation);
- AddHandler("unpack_values",
- &EmitActionHandlersCallback::onUnpackValues);
-
-
- staticMembersInitialized_ = true;
- }
- }
-
- void operator()(const Init* I,
- unsigned IndentLevel, raw_ostream& O) const
- {
- InvokeDagInitHandler(this, I, IndentLevel, O);
- }
-};
-
-void EmitGenerateActionMethodHeader(const ToolDescription& D,
- bool IsJoin, bool Naked,
- raw_ostream& O)
-{
- O.indent(Indent1) << "int GenerateAction(Action& Out,\n";
-
- if (IsJoin)
- O.indent(Indent2) << "const PathVector& inFiles,\n";
- else
- O.indent(Indent2) << "const sys::Path& inFile,\n";
-
- O.indent(Indent2) << "const bool HasChildren,\n";
- O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n";
- O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n";
- O.indent(Indent2) << "const LanguageMap& LangMap) const\n";
- O.indent(Indent1) << "{\n";
-
- if (!Naked) {
- O.indent(Indent2) << "std::string cmd;\n";
- O.indent(Indent2) << "std::string out_file;\n";
- O.indent(Indent2)
- << "std::vector<std::pair<unsigned, std::string> > vec;\n";
- O.indent(Indent2) << "bool stop_compilation = !HasChildren;\n";
- O.indent(Indent2) << "bool no_out_file = false;\n";
- O.indent(Indent2) << "std::string output_suffix(\""
- << D.OutputSuffix << "\");\n";
- }
-}
-
-// EmitGenerateActionMethod - Emit either a normal or a "join" version of the
-// Tool::GenerateAction() method.
-void EmitGenerateActionMethod (const ToolDescription& D,
- const OptionDescriptions& OptDescs,
- bool IsJoin, raw_ostream& O) {
-
- EmitGenerateActionMethodHeader(D, IsJoin, /* Naked = */ false, O);
-
- if (!D.CmdLine)
- throw "Tool " + D.Name + " has no cmd_line property!";
-
- // Process the 'command' property.
- O << '\n';
- EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
- O << '\n';
-
- // Process the 'actions' list of this tool.
- if (D.Actions)
- EmitCaseConstructHandler(D.Actions, Indent2,
- EmitActionHandlersCallback(OptDescs),
- false, OptDescs, O);
- O << '\n';
-
- // Input file (s)
- if (!D.InFileOption.empty()) {
- O.indent(Indent2)
- << "vec.push_back(std::make_pair(InputFilenames.getPosition(0), \""
- << D.InFileOption << "\");\n";
- }
-
- if (IsJoin) {
- O.indent(Indent2)
- << "for (PathVector::const_iterator B = inFiles.begin(),\n";
- O.indent(Indent3) << "E = inFiles.end(); B != E; ++B)\n";
- O.indent(Indent2) << "{\n";
- O.indent(Indent3) << "vec.push_back(std::make_pair("
- << "InputFilenames.getPosition(B - inFiles.begin()), "
- << "B->str()));\n";
- O.indent(Indent2) << "}\n";
- }
- else {
- O.indent(Indent2) << "vec.push_back(std::make_pair("
- << "InputFilenames.getPosition(0), inFile.str()));\n";
- }
-
- // Output file
- O.indent(Indent2) << "if (!no_out_file) {\n";
- if (!D.OutFileOption.empty())
- O.indent(Indent3) << "vec.push_back(std::make_pair(65536, \""
- << D.OutFileOption << "\"));\n";
-
- O.indent(Indent3) << "out_file = this->OutFilename("
- << (IsJoin ? "sys::Path(),\n" : "inFile,\n");
- O.indent(Indent4) <<
- "TempDir, stop_compilation, output_suffix.c_str()).str();\n\n";
- O.indent(Indent3) << "vec.push_back(std::make_pair(65536, out_file));\n";
-
- O.indent(Indent2) << "}\n\n";
-
- // Handle the Sink property.
- std::string SinkOption("autogenerated::");
- SinkOption += SinkOptionName;
- if (D.isSink()) {
- O.indent(Indent2) << "if (!" << SinkOption << ".empty()) {\n";
- O.indent(Indent3) << "for (cl::list<std::string>::iterator B = "
- << SinkOption << ".begin(), E = " << SinkOption
- << ".end(); B != E; ++B)\n";
- O.indent(Indent4) << "vec.push_back(std::make_pair(" << SinkOption
- << ".getPosition(B - " << SinkOption
- << ".begin()), *B));\n";
- O.indent(Indent2) << "}\n";
- }
-
- O.indent(Indent2) << "Out.Construct(cmd, this->SortArgs(vec), "
- << "stop_compilation, out_file);\n";
- O.indent(Indent2) << "return 0;\n";
- O.indent(Indent1) << "}\n\n";
-}
-
-/// EmitGenerateActionMethods - Emit two GenerateAction() methods for
-/// a given Tool class.
-void EmitGenerateActionMethods (const ToolDescription& ToolDesc,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- if (!ToolDesc.isJoin()) {
- EmitGenerateActionMethodHeader(ToolDesc, /* IsJoin = */ true,
- /* Naked = */ true, O);
- O.indent(Indent2) << "PrintError(\"" << ToolDesc.Name
- << " is not a Join tool!\");\n";
- O.indent(Indent2) << "return -1;\n";
- O.indent(Indent1) << "}\n\n";
- }
- else {
- EmitGenerateActionMethod(ToolDesc, OptDescs, true, O);
- }
-
- EmitGenerateActionMethod(ToolDesc, OptDescs, false, O);
-}
-
-/// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
-/// methods for a given Tool class.
-void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) {
- O.indent(Indent1) << "const char** InputLanguages() const {\n";
- O.indent(Indent2) << "return InputLanguages_;\n";
- O.indent(Indent1) << "}\n\n";
-
- O.indent(Indent1) << "const char** OutputLanguages() const {\n";
- O.indent(Indent2) << "return OutputLanguages_;\n";
- O.indent(Indent1) << "}\n\n";
-}
-
-/// EmitNameMethod - Emit the Name() method for a given Tool class.
-void EmitNameMethod (const ToolDescription& D, raw_ostream& O) {
- O.indent(Indent1) << "const char* Name() const {\n";
- O.indent(Indent2) << "return \"" << D.Name << "\";\n";
- O.indent(Indent1) << "}\n\n";
-}
-
-/// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
-/// class.
-void EmitIsJoinMethod (const ToolDescription& D, raw_ostream& O) {
- O.indent(Indent1) << "bool IsJoin() const {\n";
- if (D.isJoin())
- O.indent(Indent2) << "return true;\n";
- else
- O.indent(Indent2) << "return false;\n";
- O.indent(Indent1) << "}\n\n";
-}
-
-/// EmitWorksOnEmptyCallback - Callback used by EmitWorksOnEmptyMethod in
-/// conjunction with EmitCaseConstructHandler.
-void EmitWorksOnEmptyCallback (const Init* Value,
- unsigned IndentLevel, raw_ostream& O) {
- CheckBooleanConstant(Value);
- O.indent(IndentLevel) << "return " << Value->getAsString() << ";\n";
-}
-
-/// EmitWorksOnEmptyMethod - Emit the WorksOnEmpty() method for a given Tool
-/// class.
-void EmitWorksOnEmptyMethod (const ToolDescription& D,
- const OptionDescriptions& OptDescs,
- raw_ostream& O)
-{
- O.indent(Indent1) << "bool WorksOnEmpty() const {\n";
- if (D.OnEmpty == 0)
- O.indent(Indent2) << "return false;\n";
- else
- EmitCaseConstructHandler(D.OnEmpty, Indent2, EmitWorksOnEmptyCallback,
- /*EmitElseIf = */ true, OptDescs, O);
- O.indent(Indent1) << "}\n\n";
-}
-
-/// EmitStrArray - Emit definition of a 'const char**' static member
-/// variable. Helper used by EmitStaticMemberDefinitions();
-void EmitStrArray(const std::string& Name, const std::string& VarName,
- const StrVector& StrVec, raw_ostream& O) {
- O << "const char* " << Name << "::" << VarName << "[] = {";
- for (StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
- B != E; ++B)
- O << '\"' << *B << "\", ";
- O << "0};\n";
-}
-
-/// EmitStaticMemberDefinitions - Emit static member definitions for a
-/// given Tool class.
-void EmitStaticMemberDefinitions(const ToolDescription& D, raw_ostream& O) {
- if (D.InLanguage.empty())
- throw "Tool " + D.Name + " has no 'in_language' property!";
- if (D.OutLanguage.empty())
- throw "Tool " + D.Name + " has no 'out_language' property!";
-
- EmitStrArray(D.Name, "InputLanguages_", D.InLanguage, O);
- EmitStrArray(D.Name, "OutputLanguages_", D.OutLanguage, O);
- O << '\n';
-}
-
-/// EmitToolClassDefinition - Emit a Tool class definition.
-void EmitToolClassDefinition (const ToolDescription& D,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- if (D.Name == "root")
- return;
-
- // Header
- O << "class " << D.Name << " : public ";
- if (D.isJoin())
- O << "JoinTool";
- else
- O << "Tool";
-
- O << " {\nprivate:\n";
- O.indent(Indent1) << "static const char* InputLanguages_[];\n";
- O.indent(Indent1) << "static const char* OutputLanguages_[];\n\n";
-
- O << "public:\n";
- EmitNameMethod(D, O);
- EmitInOutLanguageMethods(D, O);
- EmitIsJoinMethod(D, O);
- EmitWorksOnEmptyMethod(D, OptDescs, O);
- EmitGenerateActionMethods(D, OptDescs, O);
-
- // Close class definition
- O << "};\n";
-
- EmitStaticMemberDefinitions(D, O);
-
-}
-
-/// EmitOptionDefinitions - Iterate over a list of option descriptions
-/// and emit registration code.
-void EmitOptionDefinitions (const OptionDescriptions& descs,
- bool HasSink, raw_ostream& O)
-{
- std::vector<OptionDescription> Aliases;
-
- // Emit static cl::Option variables.
- for (OptionDescriptions::const_iterator B = descs.begin(),
- E = descs.end(); B!=E; ++B) {
- const OptionDescription& val = B->second;
-
- if (val.Type == OptionType::Alias) {
- Aliases.push_back(val);
- continue;
- }
-
- O << val.GenTypeDeclaration() << ' '
- << val.GenPlainVariableName();
-
- O << "(\"" << val.Name << "\"\n";
-
- if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
- O << ", cl::Prefix";
-
- if (val.isRequired()) {
- if (val.isList() && !val.isMultiVal())
- O << ", cl::OneOrMore";
- else
- O << ", cl::Required";
- }
-
- if (val.isOptional())
- O << ", cl::Optional";
-
- if (val.isOneOrMore())
- O << ", cl::OneOrMore";
-
- if (val.isZeroOrMore())
- O << ", cl::ZeroOrMore";
-
- if (val.isReallyHidden())
- O << ", cl::ReallyHidden";
- else if (val.isHidden())
- O << ", cl::Hidden";
-
- if (val.isCommaSeparated())
- O << ", cl::CommaSeparated";
-
- if (val.MultiVal > 1)
- O << ", cl::multi_val(" << val.MultiVal << ')';
-
- if (val.InitVal) {
- const std::string& str = val.InitVal->getAsString();
- O << ", cl::init(" << str << ')';
- }
-
- if (!val.Help.empty())
- O << ", cl::desc(\"" << val.Help << "\")";
-
- O << ");\n\n";
- }
-
- // Emit the aliases (they should go after all the 'proper' options).
- for (std::vector<OptionDescription>::const_iterator
- B = Aliases.begin(), E = Aliases.end(); B != E; ++B) {
- const OptionDescription& val = *B;
-
- O << val.GenTypeDeclaration() << ' '
- << val.GenPlainVariableName()
- << "(\"" << val.Name << '\"';
-
- const OptionDescription& D = descs.FindOption(val.Help);
- O << ", cl::aliasopt(" << D.GenVariableName() << ")";
-
- O << ", cl::desc(\"" << "An alias for -" + val.Help << "\"));\n";
- }
-
- // Emit the sink option.
- if (HasSink)
- O << "cl::list<std::string> " << SinkOptionName << "(cl::Sink);\n";
-
- O << '\n';
-}
-
-/// EmitPreprocessOptionsCallback - Helper function passed to
-/// EmitCaseConstructHandler() by EmitPreprocessOptions().
-
-class EmitPreprocessOptionsCallback;
-
-typedef void
-(EmitPreprocessOptionsCallback::* EmitPreprocessOptionsCallbackHandler)
-(const DagInit&, unsigned, raw_ostream&) const;
-
-class EmitPreprocessOptionsCallback :
- public ActionHandlingCallbackBase,
- public HandlerTable<EmitPreprocessOptionsCallbackHandler>
-{
- typedef EmitPreprocessOptionsCallbackHandler Handler;
- typedef void
- (EmitPreprocessOptionsCallback::* HandlerImpl)
- (const Init*, unsigned, raw_ostream&) const;
-
- const OptionDescriptions& OptDescs_;
-
- void onEachArgument(const DagInit& d, HandlerImpl h,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(d, 1);
-
- for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) {
- ((this)->*(h))(d.getArg(i), IndentLevel, O);
- }
- }
-
- void onUnsetOptionImpl(const Init* I,
- unsigned IndentLevel, raw_ostream& O) const
- {
- const std::string& OptName = InitPtrToString(I);
- const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
-
- if (OptDesc.isSwitch()) {
- O.indent(IndentLevel) << OptDesc.GenVariableName() << " = false;\n";
- }
- else if (OptDesc.isParameter()) {
- O.indent(IndentLevel) << OptDesc.GenVariableName() << " = \"\";\n";
- }
- else if (OptDesc.isList()) {
- O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
- }
- else {
- throw "Can't apply 'unset_option' to alias option '" + OptName + "'!";
- }
- }
-
- void onUnsetOption(const DagInit& d,
- unsigned IndentLevel, raw_ostream& O) const
- {
- this->onEachArgument(d, &EmitPreprocessOptionsCallback::onUnsetOptionImpl,
- IndentLevel, O);
- }
-
- void onSetOptionImpl(const DagInit& D,
- unsigned IndentLevel, raw_ostream& O) const {
- CheckNumberOfArguments(D, 2);
-
- const std::string& OptName = InitPtrToString(D.getArg(0));
- const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
- const Init* Value = D.getArg(1);
-
- if (OptDesc.isList()) {
- const ListInit& List = InitPtrToList(Value);
-
- O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
- for (ListInit::const_iterator B = List.begin(), E = List.end();
- B != E; ++B) {
- const Init* CurElem = *B;
- if (OptDesc.isSwitchList())
- CheckBooleanConstant(CurElem);
-
- O.indent(IndentLevel)
- << OptDesc.GenVariableName() << ".push_back(\""
- << (OptDesc.isSwitchList() ? CurElem->getAsString()
- : InitPtrToString(CurElem))
- << "\");\n";
- }
- }
- else if (OptDesc.isSwitch()) {
- CheckBooleanConstant(Value);
- O.indent(IndentLevel) << OptDesc.GenVariableName()
- << " = " << Value->getAsString() << ";\n";
- }
- else if (OptDesc.isParameter()) {
- const std::string& Str = InitPtrToString(Value);
- O.indent(IndentLevel) << OptDesc.GenVariableName()
- << " = \"" << Str << "\";\n";
- }
- else {
- throw "Can't apply 'set_option' to alias option '" + OptName + "'!";
- }
- }
-
- void onSetSwitch(const Init* I,
- unsigned IndentLevel, raw_ostream& O) const {
- const std::string& OptName = InitPtrToString(I);
- const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
-
- if (OptDesc.isSwitch())
- O.indent(IndentLevel) << OptDesc.GenVariableName() << " = true;\n";
- else
- throw "set_option: -" + OptName + " is not a switch option!";
- }
-
- void onSetOption(const DagInit& d,
- unsigned IndentLevel, raw_ostream& O) const
- {
- CheckNumberOfArguments(d, 1);
-
- // 2-argument form: (set_option "A", true), (set_option "B", "C"),
- // (set_option "D", ["E", "F"])
- if (d.getNumArgs() == 2) {
- const OptionDescription& OptDesc =
- OptDescs_.FindOption(InitPtrToString(d.getArg(0)));
- const Init* Opt2 = d.getArg(1);
-
- if (!OptDesc.isSwitch() || typeid(*Opt2) != typeid(StringInit)) {
- this->onSetOptionImpl(d, IndentLevel, O);
- return;
- }
- }
-
- // Multiple argument form: (set_option "A"), (set_option "B", "C", "D")
- this->onEachArgument(d, &EmitPreprocessOptionsCallback::onSetSwitch,
- IndentLevel, O);
- }
-
-public:
-
- EmitPreprocessOptionsCallback(const OptionDescriptions& OptDescs)
- : OptDescs_(OptDescs)
- {
- if (!staticMembersInitialized_) {
- AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag);
- AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag);
- AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption);
- AddHandler("set_option", &EmitPreprocessOptionsCallback::onSetOption);
-
- staticMembersInitialized_ = true;
- }
- }
-
- void operator()(const Init* I,
- unsigned IndentLevel, raw_ostream& O) const
- {
- InvokeDagInitHandler(this, I, IndentLevel, O);
- }
-
-};
-
-/// EmitPreprocessOptions - Emit the PreprocessOptions() function.
-void EmitPreprocessOptions (const RecordKeeper& Records,
- const OptionDescriptions& OptDecs, raw_ostream& O)
-{
- O << "int PreprocessOptions () {\n";
-
- const RecordVector& OptionPreprocessors =
- Records.getAllDerivedDefinitions("OptionPreprocessor");
-
- for (RecordVector::const_iterator B = OptionPreprocessors.begin(),
- E = OptionPreprocessors.end(); B!=E; ++B) {
- DagInit* Case = (*B)->getValueAsDag("preprocessor");
- EmitCaseConstructHandler(Case, Indent1,
- EmitPreprocessOptionsCallback(OptDecs),
- false, OptDecs, O);
- }
-
- O << '\n';
- O.indent(Indent1) << "return 0;\n";
- O << "}\n\n";
-}
-
-class DoEmitPopulateLanguageMap;
-typedef void (DoEmitPopulateLanguageMap::* DoEmitPopulateLanguageMapHandler)
-(const DagInit& D);
-
-class DoEmitPopulateLanguageMap
-: public HandlerTable<DoEmitPopulateLanguageMapHandler>
-{
-private:
- raw_ostream& O_;
-
-public:
-
- explicit DoEmitPopulateLanguageMap (raw_ostream& O) : O_(O) {
- if (!staticMembersInitialized_) {
- AddHandler("lang_to_suffixes",
- &DoEmitPopulateLanguageMap::onLangToSuffixes);
-
- staticMembersInitialized_ = true;
- }
- }
-
- void operator() (Init* I) {
- InvokeDagInitHandler(this, I);
- }
-
-private:
-
- void onLangToSuffixes (const DagInit& d) {
- CheckNumberOfArguments(d, 2);
-
- const std::string& Lang = InitPtrToString(d.getArg(0));
- Init* Suffixes = d.getArg(1);
-
- // Second argument to lang_to_suffixes is either a single string...
- if (typeid(*Suffixes) == typeid(StringInit)) {
- O_.indent(Indent1) << "langMap[\"" << InitPtrToString(Suffixes)
- << "\"] = \"" << Lang << "\";\n";
- }
- // ...or a list of strings.
- else {
- const ListInit& Lst = InitPtrToList(Suffixes);
- assert(Lst.size() != 0);
- for (ListInit::const_iterator B = Lst.begin(), E = Lst.end();
- B != E; ++B) {
- O_.indent(Indent1) << "langMap[\"" << InitPtrToString(*B)
- << "\"] = \"" << Lang << "\";\n";
- }
- }
- }
-
-};
-
-/// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function.
-void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
-{
- O << "int PopulateLanguageMap (LanguageMap& langMap) {\n";
-
- // For each LanguageMap:
- const RecordVector& LangMaps =
- Records.getAllDerivedDefinitions("LanguageMap");
-
- // Call DoEmitPopulateLanguageMap.
- for (RecordVector::const_iterator B = LangMaps.begin(),
- E = LangMaps.end(); B!=E; ++B) {
- ListInit* LangMap = (*B)->getValueAsListInit("map");
- std::for_each(LangMap->begin(), LangMap->end(),
- DoEmitPopulateLanguageMap(O));
- }
-
- O << '\n';
- O.indent(Indent1) << "return 0;\n";
- O << "}\n\n";
-}
-
-/// EmitEdgePropertyHandlerCallback - Emits code that handles edge
-/// properties. Helper function passed to EmitCaseConstructHandler() by
-/// EmitEdgeClass().
-void EmitEdgePropertyHandlerCallback (const Init* i, unsigned IndentLevel,
- raw_ostream& O) {
- const DagInit& d = InitPtrToDag(i);
- const std::string& OpName = GetOperatorName(d);
-
- if (OpName == "inc_weight") {
- O.indent(IndentLevel) << "ret += ";
- }
- else if (OpName == "error") {
- CheckNumberOfArguments(d, 1);
- O.indent(IndentLevel) << "PrintError(\""
- << InitPtrToString(d.getArg(0))
- << "\");\n";
- O.indent(IndentLevel) << "return -1;\n";
- return;
- }
- else {
- throw "Unknown operator in edge properties list: '" + OpName + "'!"
- "\nOnly 'inc_weight', 'dec_weight' and 'error' are allowed.";
- }
-
- if (d.getNumArgs() > 0)
- O << InitPtrToInt(d.getArg(0)) << ";\n";
- else
- O << "2;\n";
-
-}
-
-/// EmitEdgeClass - Emit a single Edge# class.
-void EmitEdgeClass (unsigned N, const std::string& Target,
- const DagInit& Case, const OptionDescriptions& OptDescs,
- raw_ostream& O) {
-
- // Class constructor.
- O << "class Edge" << N << ": public Edge {\n"
- << "public:\n";
- O.indent(Indent1) << "Edge" << N << "() : Edge(\"" << Target
- << "\") {}\n\n";
-
- // Function Weight().
- O.indent(Indent1)
- << "int Weight(const InputLanguagesSet& InLangs) const {\n";
- O.indent(Indent2) << "unsigned ret = 0;\n";
-
- // Handle the 'case' construct.
- EmitCaseConstructHandler(&Case, Indent2, EmitEdgePropertyHandlerCallback,
- false, OptDescs, O);
-
- O.indent(Indent2) << "return ret;\n";
- O.indent(Indent1) << "}\n\n};\n\n";
-}
-
-/// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
-void EmitEdgeClasses (const DagVector& EdgeVector,
- const OptionDescriptions& OptDescs,
- raw_ostream& O) {
- int i = 0;
- for (DagVector::const_iterator B = EdgeVector.begin(),
- E = EdgeVector.end(); B != E; ++B) {
- const DagInit& Edge = **B;
- const std::string& Name = GetOperatorName(Edge);
-
- if (Name == "optional_edge") {
- assert(IsOptionalEdge(Edge));
- const std::string& NodeB = InitPtrToString(Edge.getArg(1));
-
- const DagInit& Weight = InitPtrToDag(Edge.getArg(2));
- EmitEdgeClass(i, NodeB, Weight, OptDescs, O);
- }
- else if (Name != "edge") {
- throw "Unknown edge class: '" + Name + "'!";
- }
-
- ++i;
- }
-}
-
-/// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraph() function.
-void EmitPopulateCompilationGraph (const DagVector& EdgeVector,
- const ToolDescriptions& ToolDescs,
- raw_ostream& O)
-{
- O << "int PopulateCompilationGraph (CompilationGraph& G) {\n";
-
- for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
- E = ToolDescs.end(); B != E; ++B)
- O.indent(Indent1) << "G.insertNode(new " << (*B)->Name << "());\n";
-
- O << '\n';
-
- // Insert edges.
-
- int i = 0;
- for (DagVector::const_iterator B = EdgeVector.begin(),
- E = EdgeVector.end(); B != E; ++B) {
- const DagInit& Edge = **B;
- const std::string& NodeA = InitPtrToString(Edge.getArg(0));
- const std::string& NodeB = InitPtrToString(Edge.getArg(1));
-
- O.indent(Indent1) << "if (int ret = G.insertEdge(\"" << NodeA << "\", ";
-
- if (IsOptionalEdge(Edge))
- O << "new Edge" << i << "()";
- else
- O << "new SimpleEdge(\"" << NodeB << "\")";
-
- O << "))\n";
- O.indent(Indent2) << "return ret;\n";
-
- ++i;
- }
-
- O << '\n';
- O.indent(Indent1) << "return 0;\n";
- O << "}\n\n";
-}
-
-/// HookInfo - Information about the hook type and number of arguments.
-struct HookInfo {
-
- // A hook can either have a single parameter of type std::vector<std::string>,
- // or NumArgs parameters of type const char*.
- enum HookType { ListHook, ArgHook };
-
- HookType Type;
- unsigned NumArgs;
-
- HookInfo() : Type(ArgHook), NumArgs(1)
- {}
-
- HookInfo(HookType T) : Type(T), NumArgs(1)
- {}
-
- HookInfo(unsigned N) : Type(ArgHook), NumArgs(N)
- {}
-};
-
-typedef llvm::StringMap<HookInfo> HookInfoMap;
-
-/// ExtractHookNames - Extract the hook names from all instances of
-/// $CALL(HookName) in the provided command line string/action. Helper
-/// function used by FillInHookNames().
-class ExtractHookNames {
- HookInfoMap& HookNames_;
- const OptionDescriptions& OptDescs_;
-public:
- ExtractHookNames(HookInfoMap& HookNames, const OptionDescriptions& OptDescs)
- : HookNames_(HookNames), OptDescs_(OptDescs)
- {}
-
- void onAction (const DagInit& Dag) {
- const std::string& Name = GetOperatorName(Dag);
-
- if (Name == "forward_transformed_value") {
- CheckNumberOfArguments(Dag, 2);
- const std::string& OptName = InitPtrToString(Dag.getArg(0));
- const std::string& HookName = InitPtrToString(Dag.getArg(1));
- const OptionDescription& D =
- OptDescs_.FindParameterListOrParameter(OptName);
-
- HookNames_[HookName] = HookInfo(D.isList() ? HookInfo::ListHook
- : HookInfo::ArgHook);
- }
- else if (Name == "append_cmd" || Name == "output_suffix") {
- CheckNumberOfArguments(Dag, 1);
- this->onCmdLine(InitPtrToString(Dag.getArg(0)));
- }
- }
-
- void onCmdLine(const std::string& Cmd) {
- StrVector cmds;
- TokenizeCmdLine(Cmd, cmds);
-
- for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
- B != E; ++B) {
- const std::string& cmd = *B;
-
- if (cmd == "$CALL") {
- unsigned NumArgs = 0;
- CheckedIncrement(B, E, "Syntax error in $CALL invocation!");
- const std::string& HookName = *B;
-
- if (HookName.at(0) == ')')
- throw "$CALL invoked with no arguments!";
-
- while (++B != E && B->at(0) != ')') {
- ++NumArgs;
- }
-
- HookInfoMap::const_iterator H = HookNames_.find(HookName);
-
- if (H != HookNames_.end() && H->second.NumArgs != NumArgs &&
- H->second.Type != HookInfo::ArgHook)
- throw "Overloading of hooks is not allowed. Overloaded hook: "
- + HookName;
- else
- HookNames_[HookName] = HookInfo(NumArgs);
- }
- }
- }
-
- void operator()(const Init* Arg) {
-
- // We're invoked on an action (either a dag or a dag list).
- if (typeid(*Arg) == typeid(DagInit)) {
- const DagInit& Dag = InitPtrToDag(Arg);
- this->onAction(Dag);
- return;
- }
- else if (typeid(*Arg) == typeid(ListInit)) {
- const ListInit& List = InitPtrToList(Arg);
- for (ListInit::const_iterator B = List.begin(), E = List.end(); B != E;
- ++B) {
- const DagInit& Dag = InitPtrToDag(*B);
- this->onAction(Dag);
- }
- return;
- }
-
- // We're invoked on a command line string.
- this->onCmdLine(InitPtrToString(Arg));
- }
-
- void operator()(const Init* Statement, unsigned) {
- this->operator()(Statement);
- }
-};
-
-/// FillInHookNames - Actually extract the hook names from all command
-/// line strings. Helper function used by EmitHookDeclarations().
-void FillInHookNames(const ToolDescriptions& ToolDescs,
- const OptionDescriptions& OptDescs,
- HookInfoMap& HookNames)
-{
- // For all tool descriptions:
- for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
- E = ToolDescs.end(); B != E; ++B) {
- const ToolDescription& D = *(*B);
-
- // Look for 'forward_transformed_value' in 'actions'.
- if (D.Actions)
- WalkCase(D.Actions, Id(), ExtractHookNames(HookNames, OptDescs));
-
- // Look for hook invocations in 'cmd_line'.
- if (!D.CmdLine)
- continue;
- if (dynamic_cast<StringInit*>(D.CmdLine))
- // This is a string.
- ExtractHookNames(HookNames, OptDescs).operator()(D.CmdLine);
- else
- // This is a 'case' construct.
- WalkCase(D.CmdLine, Id(), ExtractHookNames(HookNames, OptDescs));
- }
-}
-
-/// EmitHookDeclarations - Parse CmdLine fields of all the tool
-/// property records and emit hook function declaration for each
-/// instance of $CALL(HookName).
-void EmitHookDeclarations(const ToolDescriptions& ToolDescs,
- const OptionDescriptions& OptDescs, raw_ostream& O) {
- HookInfoMap HookNames;
-
- FillInHookNames(ToolDescs, OptDescs, HookNames);
- if (HookNames.empty())
- return;
-
- for (HookInfoMap::const_iterator B = HookNames.begin(),
- E = HookNames.end(); B != E; ++B) {
- StringRef HookName = B->first();
- const HookInfo &Info = B->second;
-
- O.indent(Indent1) << "std::string " << HookName << "(";
-
- if (Info.Type == HookInfo::ArgHook) {
- for (unsigned i = 0, j = Info.NumArgs; i < j; ++i) {
- O << "const char* Arg" << i << (i+1 == j ? "" : ", ");
- }
- }
- else {
- O << "const std::vector<std::string>& Arg";
- }
-
- O <<");\n";
- }
-}
-
-/// EmitIncludes - Emit necessary #include directives and some
-/// additional declarations.
-void EmitIncludes(raw_ostream& O) {
- O << "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n"
- << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
- << "#include \"llvm/CompilerDriver/Error.h\"\n"
- << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"
-
- << "#include \"llvm/Support/CommandLine.h\"\n"
- << "#include \"llvm/Support/raw_ostream.h\"\n\n"
-
- << "#include <algorithm>\n"
- << "#include <cstdlib>\n"
- << "#include <iterator>\n"
- << "#include <stdexcept>\n\n"
-
- << "using namespace llvm;\n"
- << "using namespace llvmc;\n\n"
-
- << "inline const char* checkCString(const char* s)\n"
- << "{ return s == NULL ? \"\" : s; }\n\n";
-}
-
-
-/// DriverData - Holds all information about the driver.
-struct DriverData {
- OptionDescriptions OptDescs;
- ToolDescriptions ToolDescs;
- DagVector Edges;
- bool HasSink;
-};
-
-/// HasSink - Go through the list of tool descriptions and check if
-/// there are any with the 'sink' property set.
-bool HasSink(const ToolDescriptions& ToolDescs) {
- for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
- E = ToolDescs.end(); B != E; ++B)
- if ((*B)->isSink())
- return true;
-
- return false;
-}
-
-/// CollectDriverData - Collect compilation graph edges, tool properties and
-/// option properties from the parse tree.
-void CollectDriverData (const RecordKeeper& Records, DriverData& Data) {
- // Collect option properties.
- const RecordVector& OptionLists =
- Records.getAllDerivedDefinitions("OptionList");
- CollectOptionDescriptions(OptionLists, Data.OptDescs);
-
- // Collect tool properties.
- const RecordVector& Tools = Records.getAllDerivedDefinitions("Tool");
- CollectToolDescriptions(Tools, Data.ToolDescs);
- Data.HasSink = HasSink(Data.ToolDescs);
-
- // Collect compilation graph edges.
- const RecordVector& CompilationGraphs =
- Records.getAllDerivedDefinitions("CompilationGraph");
- FillInEdgeVector(CompilationGraphs, Data.Edges);
-}
-
-/// CheckDriverData - Perform some sanity checks on the collected data.
-void CheckDriverData(DriverData& Data) {
- // Filter out all tools not mentioned in the compilation graph.
- FilterNotInGraph(Data.Edges, Data.ToolDescs);
-
- // Typecheck the compilation graph.
- // TODO: use a genuine graph representation instead of a vector and check for
- // multiple edges.
- TypecheckGraph(Data.Edges, Data.ToolDescs);
-
- // Check that there are no options without side effects (specified
- // only in the OptionList).
- CheckForSuperfluousOptions(Data.Edges, Data.ToolDescs, Data.OptDescs);
-}
-
-void EmitDriverCode(const DriverData& Data,
- raw_ostream& O, RecordKeeper &Records) {
- // Emit file header.
- EmitIncludes(O);
-
- // Emit global option registration code.
- O << "namespace llvmc {\n"
- << "namespace autogenerated {\n\n";
- EmitOptionDefinitions(Data.OptDescs, Data.HasSink, O);
- O << "} // End namespace autogenerated.\n"
- << "} // End namespace llvmc.\n\n";
-
- // Emit hook declarations.
- O << "namespace hooks {\n";
- EmitHookDeclarations(Data.ToolDescs, Data.OptDescs, O);
- O << "} // End namespace hooks.\n\n";
-
- O << "namespace {\n\n";
- O << "using namespace llvmc::autogenerated;\n\n";
-
- // Emit Tool classes.
- for (ToolDescriptions::const_iterator B = Data.ToolDescs.begin(),
- E = Data.ToolDescs.end(); B!=E; ++B)
- EmitToolClassDefinition(*(*B), Data.OptDescs, O);
-
- // Emit Edge# classes.
- EmitEdgeClasses(Data.Edges, Data.OptDescs, O);
-
- O << "} // End anonymous namespace.\n\n";
-
- O << "namespace llvmc {\n";
- O << "namespace autogenerated {\n\n";
-
- // Emit PreprocessOptions() function.
- EmitPreprocessOptions(Records, Data.OptDescs, O);
-
- // Emit PopulateLanguageMap() function
- // (language map maps from file extensions to language names).
- EmitPopulateLanguageMap(Records, O);
-
- // Emit PopulateCompilationGraph() function.
- EmitPopulateCompilationGraph(Data.Edges, Data.ToolDescs, O);
-
- O << "} // End namespace autogenerated.\n";
- O << "} // End namespace llvmc.\n\n";
-
- // EOF
-}
-
-
-// End of anonymous namespace
-}
-
-/// run - The back-end entry point.
-void LLVMCConfigurationEmitter::run (raw_ostream &O) {
- try {
- DriverData Data;
-
- CollectDriverData(Records, Data);
- CheckDriverData(Data);
-
- this->EmitSourceFileHeader("llvmc-based driver: auto-generated code", O);
- EmitDriverCode(Data, O, Records);
-
- } catch (std::exception& Error) {
- throw Error.what() + std::string(" - usually this means a syntax error.");
- }
-}
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.h b/utils/TableGen/LLVMCConfigurationEmitter.h
deleted file mode 100644
index 0f2ff37..0000000
--- a/utils/TableGen/LLVMCConfigurationEmitter.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- LLVMCConfigurationEmitter.cpp - Generate LLVMCC config ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open
-// Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This tablegen backend is responsible for emitting LLVMCC configuration code.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
-#define LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
-
-#include "TableGenBackend.h"
-
-namespace llvm {
-
- /// LLVMCConfigurationEmitter - TableGen backend that generates
- /// configuration code for LLVMC.
- class LLVMCConfigurationEmitter : public TableGenBackend {
- RecordKeeper &Records;
- public:
- explicit LLVMCConfigurationEmitter(RecordKeeper &records) :
- Records(records) {}
-
- // run - Output the asmwriter, returning true on failure.
- void run(raw_ostream &o);
- };
-}
-
-#endif //LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
diff --git a/utils/TableGen/Makefile b/utils/TableGen/Makefile
index c01b660..0c4619d 100644
--- a/utils/TableGen/Makefile
+++ b/utils/TableGen/Makefile
@@ -8,8 +8,8 @@
##===----------------------------------------------------------------------===##
LEVEL = ../..
-TOOLNAME = tblgen
-USEDLIBS = LLVMSupport.a
+TOOLNAME = llvm-tblgen
+USEDLIBS = LLVMTableGen.a LLVMSupport.a
REQUIRES_EH := 1
REQUIRES_RTTI := 1
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
deleted file mode 100644
index ef977443..0000000
--- a/utils/TableGen/NeonEmitter.cpp
+++ /dev/null
@@ -1,1558 +0,0 @@
-//===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This tablegen backend is responsible for emitting arm_neon.h, which includes
-// a declaration and definition of each function specified by the ARM NEON
-// compiler interface. See ARM document DUI0348B.
-//
-// Each NEON instruction is implemented in terms of 1 or more functions which
-// are suffixed with the element type of the input vectors. Functions may be
-// implemented in terms of generic vector operations such as +, *, -, etc. or
-// by calling a __builtin_-prefixed function which will be handled by clang's
-// CodeGen library.
-//
-// Additional validation code can be generated by this file when runHeader() is
-// called, rather than the normal run() entry point. A complete set of tests
-// for Neon intrinsics can be generated by calling the runTests() entry point.
-//
-//===----------------------------------------------------------------------===//
-
-#include "NeonEmitter.h"
-#include "Error.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include <string>
-
-using namespace llvm;
-
-/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
-/// which each StringRef representing a single type declared in the string.
-/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
-/// 2xfloat and 4xfloat respectively.
-static void ParseTypes(Record *r, std::string &s,
- SmallVectorImpl<StringRef> &TV) {
- const char *data = s.data();
- int len = 0;
-
- for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
- if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
- continue;
-
- switch (data[len]) {
- case 'c':
- case 's':
- case 'i':
- case 'l':
- case 'h':
- case 'f':
- break;
- default:
- throw TGError(r->getLoc(),
- "Unexpected letter: " + std::string(data + len, 1));
- break;
- }
- TV.push_back(StringRef(data, len + 1));
- data += len + 1;
- len = -1;
- }
-}
-
-/// Widen - Convert a type code into the next wider type. char -> short,
-/// short -> int, etc.
-static char Widen(const char t) {
- switch (t) {
- case 'c':
- return 's';
- case 's':
- return 'i';
- case 'i':
- return 'l';
- case 'h':
- return 'f';
- default: throw "unhandled type in widen!";
- }
- return '\0';
-}
-
-/// Narrow - Convert a type code into the next smaller type. short -> char,
-/// float -> half float, etc.
-static char Narrow(const char t) {
- switch (t) {
- case 's':
- return 'c';
- case 'i':
- return 's';
- case 'l':
- return 'i';
- case 'f':
- return 'h';
- default: throw "unhandled type in narrow!";
- }
- return '\0';
-}
-
-/// For a particular StringRef, return the base type code, and whether it has
-/// the quad-vector, polynomial, or unsigned modifiers set.
-static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
- unsigned off = 0;
-
- // remember quad.
- if (ty[off] == 'Q') {
- quad = true;
- ++off;
- }
-
- // remember poly.
- if (ty[off] == 'P') {
- poly = true;
- ++off;
- }
-
- // remember unsigned.
- if (ty[off] == 'U') {
- usgn = true;
- ++off;
- }
-
- // base type to get the type string for.
- return ty[off];
-}
-
-/// ModType - Transform a type code and its modifiers based on a mod code. The
-/// mod code definitions may be found at the top of arm_neon.td.
-static char ModType(const char mod, char type, bool &quad, bool &poly,
- bool &usgn, bool &scal, bool &cnst, bool &pntr) {
- switch (mod) {
- case 't':
- if (poly) {
- poly = false;
- usgn = true;
- }
- break;
- case 'u':
- usgn = true;
- poly = false;
- if (type == 'f')
- type = 'i';
- break;
- case 'x':
- usgn = false;
- poly = false;
- if (type == 'f')
- type = 'i';
- break;
- case 'f':
- if (type == 'h')
- quad = true;
- type = 'f';
- usgn = false;
- break;
- case 'g':
- quad = false;
- break;
- case 'w':
- type = Widen(type);
- quad = true;
- break;
- case 'n':
- type = Widen(type);
- break;
- case 'i':
- type = 'i';
- scal = true;
- break;
- case 'l':
- type = 'l';
- scal = true;
- usgn = true;
- break;
- case 's':
- case 'a':
- scal = true;
- break;
- case 'k':
- quad = true;
- break;
- case 'c':
- cnst = true;
- case 'p':
- pntr = true;
- scal = true;
- break;
- case 'h':
- type = Narrow(type);
- if (type == 'h')
- quad = false;
- break;
- case 'e':
- type = Narrow(type);
- usgn = true;
- break;
- default:
- break;
- }
- return type;
-}
-
-/// TypeString - for a modifier and type, generate the name of the typedef for
-/// that type. QUc -> uint8x8_t.
-static std::string TypeString(const char mod, StringRef typestr) {
- bool quad = false;
- bool poly = false;
- bool usgn = false;
- bool scal = false;
- bool cnst = false;
- bool pntr = false;
-
- if (mod == 'v')
- return "void";
- if (mod == 'i')
- return "int";
-
- // base type to get the type string for.
- char type = ClassifyType(typestr, quad, poly, usgn);
-
- // Based on the modifying character, change the type and width if necessary.
- type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
-
- SmallString<128> s;
-
- if (usgn)
- s.push_back('u');
-
- switch (type) {
- case 'c':
- s += poly ? "poly8" : "int8";
- if (scal)
- break;
- s += quad ? "x16" : "x8";
- break;
- case 's':
- s += poly ? "poly16" : "int16";
- if (scal)
- break;
- s += quad ? "x8" : "x4";
- break;
- case 'i':
- s += "int32";
- if (scal)
- break;
- s += quad ? "x4" : "x2";
- break;
- case 'l':
- s += "int64";
- if (scal)
- break;
- s += quad ? "x2" : "x1";
- break;
- case 'h':
- s += "float16";
- if (scal)
- break;
- s += quad ? "x8" : "x4";
- break;
- case 'f':
- s += "float32";
- if (scal)
- break;
- s += quad ? "x4" : "x2";
- break;
- default:
- throw "unhandled type!";
- break;
- }
-
- if (mod == '2')
- s += "x2";
- if (mod == '3')
- s += "x3";
- if (mod == '4')
- s += "x4";
-
- // Append _t, finishing the type string typedef type.
- s += "_t";
-
- if (cnst)
- s += " const";
-
- if (pntr)
- s += " *";
-
- return s.str();
-}
-
-/// BuiltinTypeString - for a modifier and type, generate the clang
-/// BuiltinsARM.def prototype code for the function. See the top of clang's
-/// Builtins.def for a description of the type strings.
-static std::string BuiltinTypeString(const char mod, StringRef typestr,
- ClassKind ck, bool ret) {
- bool quad = false;
- bool poly = false;
- bool usgn = false;
- bool scal = false;
- bool cnst = false;
- bool pntr = false;
-
- if (mod == 'v')
- return "v"; // void
- if (mod == 'i')
- return "i"; // int
-
- // base type to get the type string for.
- char type = ClassifyType(typestr, quad, poly, usgn);
-
- // Based on the modifying character, change the type and width if necessary.
- type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
-
- // All pointers are void* pointers. Change type to 'v' now.
- if (pntr) {
- usgn = false;
- poly = false;
- type = 'v';
- }
- // Treat half-float ('h') types as unsigned short ('s') types.
- if (type == 'h') {
- type = 's';
- usgn = true;
- }
- usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
-
- if (scal) {
- SmallString<128> s;
-
- if (usgn)
- s.push_back('U');
- else if (type == 'c')
- s.push_back('S'); // make chars explicitly signed
-
- if (type == 'l') // 64-bit long
- s += "LLi";
- else
- s.push_back(type);
-
- if (cnst)
- s.push_back('C');
- if (pntr)
- s.push_back('*');
- return s.str();
- }
-
- // Since the return value must be one type, return a vector type of the
- // appropriate width which we will bitcast. An exception is made for
- // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
- // fashion, storing them to a pointer arg.
- if (ret) {
- if (mod >= '2' && mod <= '4')
- return "vv*"; // void result with void* first argument
- if (mod == 'f' || (ck != ClassB && type == 'f'))
- return quad ? "V4f" : "V2f";
- if (ck != ClassB && type == 's')
- return quad ? "V8s" : "V4s";
- if (ck != ClassB && type == 'i')
- return quad ? "V4i" : "V2i";
- if (ck != ClassB && type == 'l')
- return quad ? "V2LLi" : "V1LLi";
-
- return quad ? "V16Sc" : "V8Sc";
- }
-
- // Non-return array types are passed as individual vectors.
- if (mod == '2')
- return quad ? "V16ScV16Sc" : "V8ScV8Sc";
- if (mod == '3')
- return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc";
- if (mod == '4')
- return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc";
-
- if (mod == 'f' || (ck != ClassB && type == 'f'))
- return quad ? "V4f" : "V2f";
- if (ck != ClassB && type == 's')
- return quad ? "V8s" : "V4s";
- if (ck != ClassB && type == 'i')
- return quad ? "V4i" : "V2i";
- if (ck != ClassB && type == 'l')
- return quad ? "V2LLi" : "V1LLi";
-
- return quad ? "V16Sc" : "V8Sc";
-}
-
-/// MangleName - Append a type or width suffix to a base neon function name,
-/// and insert a 'q' in the appropriate location if the operation works on
-/// 128b rather than 64b. E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
-static std::string MangleName(const std::string &name, StringRef typestr,
- ClassKind ck) {
- if (name == "vcvt_f32_f16")
- return name;
-
- bool quad = false;
- bool poly = false;
- bool usgn = false;
- char type = ClassifyType(typestr, quad, poly, usgn);
-
- std::string s = name;
-
- switch (type) {
- case 'c':
- switch (ck) {
- case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
- case ClassI: s += "_i8"; break;
- case ClassW: s += "_8"; break;
- default: break;
- }
- break;
- case 's':
- switch (ck) {
- case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
- case ClassI: s += "_i16"; break;
- case ClassW: s += "_16"; break;
- default: break;
- }
- break;
- case 'i':
- switch (ck) {
- case ClassS: s += usgn ? "_u32" : "_s32"; break;
- case ClassI: s += "_i32"; break;
- case ClassW: s += "_32"; break;
- default: break;
- }
- break;
- case 'l':
- switch (ck) {
- case ClassS: s += usgn ? "_u64" : "_s64"; break;
- case ClassI: s += "_i64"; break;
- case ClassW: s += "_64"; break;
- default: break;
- }
- break;
- case 'h':
- switch (ck) {
- case ClassS:
- case ClassI: s += "_f16"; break;
- case ClassW: s += "_16"; break;
- default: break;
- }
- break;
- case 'f':
- switch (ck) {
- case ClassS:
- case ClassI: s += "_f32"; break;
- case ClassW: s += "_32"; break;
- default: break;
- }
- break;
- default:
- throw "unhandled type!";
- break;
- }
- if (ck == ClassB)
- s += "_v";
-
- // Insert a 'q' before the first '_' character so that it ends up before
- // _lane or _n on vector-scalar operations.
- if (quad) {
- size_t pos = s.find('_');
- s = s.insert(pos, "q");
- }
- return s;
-}
-
-/// UseMacro - Examine the prototype string to determine if the intrinsic
-/// should be defined as a preprocessor macro instead of an inline function.
-static bool UseMacro(const std::string &proto) {
- // If this builtin takes an immediate argument, we need to #define it rather
- // than use a standard declaration, so that SemaChecking can range check
- // the immediate passed by the user.
- if (proto.find('i') != std::string::npos)
- return true;
-
- // Pointer arguments need to use macros to avoid hiding aligned attributes
- // from the pointer type.
- if (proto.find('p') != std::string::npos ||
- proto.find('c') != std::string::npos)
- return true;
-
- return false;
-}
-
-/// MacroArgUsedDirectly - Return true if argument i for an intrinsic that is
-/// defined as a macro should be accessed directly instead of being first
-/// assigned to a local temporary.
-static bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
- return (proto[i] == 'i' || proto[i] == 'p' || proto[i] == 'c');
-}
-
-// Generate the string "(argtype a, argtype b, ...)"
-static std::string GenArgs(const std::string &proto, StringRef typestr) {
- bool define = UseMacro(proto);
- char arg = 'a';
-
- std::string s;
- s += "(";
-
- for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
- if (define) {
- // Some macro arguments are used directly instead of being assigned
- // to local temporaries; prepend an underscore prefix to make their
- // names consistent with the local temporaries.
- if (MacroArgUsedDirectly(proto, i))
- s += "__";
- } else {
- s += TypeString(proto[i], typestr) + " __";
- }
- s.push_back(arg);
- if ((i + 1) < e)
- s += ", ";
- }
-
- s += ")";
- return s;
-}
-
-// Macro arguments are not type-checked like inline function arguments, so
-// assign them to local temporaries to get the right type checking.
-static std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
- char arg = 'a';
- std::string s;
- bool generatedLocal = false;
-
- for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
- // Do not create a temporary for an immediate argument.
- // That would defeat the whole point of using a macro!
- if (proto[i] == 'i')
- continue;
- generatedLocal = true;
-
- // For other (non-immediate) arguments that are used directly, a local
- // temporary is still needed to get the correct type checking, even though
- // that temporary is not used for anything.
- if (MacroArgUsedDirectly(proto, i)) {
- s += TypeString(proto[i], typestr) + " __";
- s.push_back(arg);
- s += "_ = (__";
- s.push_back(arg);
- s += "); (void)__";
- s.push_back(arg);
- s += "_; ";
- continue;
- }
-
- s += TypeString(proto[i], typestr) + " __";
- s.push_back(arg);
- s += " = (";
- s.push_back(arg);
- s += "); ";
- }
-
- if (generatedLocal)
- s += "\\\n ";
- return s;
-}
-
-// Use the vmovl builtin to sign-extend or zero-extend a vector.
-static std::string Extend(StringRef typestr, const std::string &a) {
- std::string s;
- s = MangleName("vmovl", typestr, ClassS);
- s += "(" + a + ")";
- return s;
-}
-
-static std::string Duplicate(unsigned nElts, StringRef typestr,
- const std::string &a) {
- std::string s;
-
- s = "(" + TypeString('d', typestr) + "){ ";
- for (unsigned i = 0; i != nElts; ++i) {
- s += a;
- if ((i + 1) < nElts)
- s += ", ";
- }
- s += " }";
-
- return s;
-}
-
-static std::string SplatLane(unsigned nElts, const std::string &vec,
- const std::string &lane) {
- std::string s = "__builtin_shufflevector(" + vec + ", " + vec;
- for (unsigned i = 0; i < nElts; ++i)
- s += ", " + lane;
- s += ")";
- return s;
-}
-
-static unsigned GetNumElements(StringRef typestr, bool &quad) {
- quad = false;
- bool dummy = false;
- char type = ClassifyType(typestr, quad, dummy, dummy);
- unsigned nElts = 0;
- switch (type) {
- case 'c': nElts = 8; break;
- case 's': nElts = 4; break;
- case 'i': nElts = 2; break;
- case 'l': nElts = 1; break;
- case 'h': nElts = 4; break;
- case 'f': nElts = 2; break;
- default:
- throw "unhandled type!";
- break;
- }
- if (quad) nElts <<= 1;
- return nElts;
-}
-
-// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
-static std::string GenOpString(OpKind op, const std::string &proto,
- StringRef typestr) {
- bool quad;
- unsigned nElts = GetNumElements(typestr, quad);
- bool define = UseMacro(proto);
-
- std::string ts = TypeString(proto[0], typestr);
- std::string s;
- if (!define) {
- s = "return ";
- }
-
- switch(op) {
- case OpAdd:
- s += "__a + __b;";
- break;
- case OpAddl:
- s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";";
- break;
- case OpAddw:
- s += "__a + " + Extend(typestr, "__b") + ";";
- break;
- case OpSub:
- s += "__a - __b;";
- break;
- case OpSubl:
- s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";";
- break;
- case OpSubw:
- s += "__a - " + Extend(typestr, "__b") + ";";
- break;
- case OpMulN:
- s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
- break;
- case OpMulLane:
- s += "__a * " + SplatLane(nElts, "__b", "__c") + ";";
- break;
- case OpMul:
- s += "__a * __b;";
- break;
- case OpMullLane:
- s += MangleName("vmull", typestr, ClassS) + "(__a, " +
- SplatLane(nElts, "__b", "__c") + ");";
- break;
- case OpMlaN:
- s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
- break;
- case OpMlaLane:
- s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpMla:
- s += "__a + (__b * __c);";
- break;
- case OpMlalN:
- s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
- Duplicate(nElts, typestr, "__c") + ");";
- break;
- case OpMlalLane:
- s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, " +
- SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpMlal:
- s += "__a + " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
- break;
- case OpMlsN:
- s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
- break;
- case OpMlsLane:
- s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpMls:
- s += "__a - (__b * __c);";
- break;
- case OpMlslN:
- s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
- Duplicate(nElts, typestr, "__c") + ");";
- break;
- case OpMlslLane:
- s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, " +
- SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpMlsl:
- s += "__a - " + MangleName("vmull", typestr, ClassS) + "(__b, __c);";
- break;
- case OpQDMullLane:
- s += MangleName("vqdmull", typestr, ClassS) + "(__a, " +
- SplatLane(nElts, "__b", "__c") + ");";
- break;
- case OpQDMlalLane:
- s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " +
- SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpQDMlslLane:
- s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " +
- SplatLane(nElts, "__c", "__d") + ");";
- break;
- case OpQDMulhLane:
- s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " +
- SplatLane(nElts, "__b", "__c") + ");";
- break;
- case OpQRDMulhLane:
- s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " +
- SplatLane(nElts, "__b", "__c") + ");";
- break;
- case OpEq:
- s += "(" + ts + ")(__a == __b);";
- break;
- case OpGe:
- s += "(" + ts + ")(__a >= __b);";
- break;
- case OpLe:
- s += "(" + ts + ")(__a <= __b);";
- break;
- case OpGt:
- s += "(" + ts + ")(__a > __b);";
- break;
- case OpLt:
- s += "(" + ts + ")(__a < __b);";
- break;
- case OpNeg:
- s += " -__a;";
- break;
- case OpNot:
- s += " ~__a;";
- break;
- case OpAnd:
- s += "__a & __b;";
- break;
- case OpOr:
- s += "__a | __b;";
- break;
- case OpXor:
- s += "__a ^ __b;";
- break;
- case OpAndNot:
- s += "__a & ~__b;";
- break;
- case OpOrNot:
- s += "__a | ~__b;";
- break;
- case OpCast:
- s += "(" + ts + ")__a;";
- break;
- case OpConcat:
- s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
- s += ", (int64x1_t)__b, 0, 1);";
- break;
- case OpHi:
- s += "(" + ts +
- ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);";
- break;
- case OpLo:
- s += "(" + ts +
- ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);";
- break;
- case OpDup:
- s += Duplicate(nElts, typestr, "__a") + ";";
- break;
- case OpDupLane:
- s += SplatLane(nElts, "__a", "__b") + ";";
- break;
- case OpSelect:
- // ((0 & 1) | (~0 & 2))
- s += "(" + ts + ")";
- ts = TypeString(proto[1], typestr);
- s += "((__a & (" + ts + ")__b) | ";
- s += "(~__a & (" + ts + ")__c));";
- break;
- case OpRev16:
- s += "__builtin_shufflevector(__a, __a";
- for (unsigned i = 2; i <= nElts; i += 2)
- for (unsigned j = 0; j != 2; ++j)
- s += ", " + utostr(i - j - 1);
- s += ");";
- break;
- case OpRev32: {
- unsigned WordElts = nElts >> (1 + (int)quad);
- s += "__builtin_shufflevector(__a, __a";
- for (unsigned i = WordElts; i <= nElts; i += WordElts)
- for (unsigned j = 0; j != WordElts; ++j)
- s += ", " + utostr(i - j - 1);
- s += ");";
- break;
- }
- case OpRev64: {
- unsigned DblWordElts = nElts >> (int)quad;
- s += "__builtin_shufflevector(__a, __a";
- for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
- for (unsigned j = 0; j != DblWordElts; ++j)
- s += ", " + utostr(i - j - 1);
- s += ");";
- break;
- }
- case OpAbdl: {
- std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
- if (typestr[0] != 'U') {
- // vabd results are always unsigned and must be zero-extended.
- std::string utype = "U" + typestr.str();
- s += "(" + TypeString(proto[0], typestr) + ")";
- abd = "(" + TypeString('d', utype) + ")" + abd;
- s += Extend(utype, abd) + ";";
- } else {
- s += Extend(typestr, abd) + ";";
- }
- break;
- }
- case OpAba:
- s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);";
- break;
- case OpAbal: {
- s += "__a + ";
- std::string abd = MangleName("vabd", typestr, ClassS) + "(__b, __c)";
- if (typestr[0] != 'U') {
- // vabd results are always unsigned and must be zero-extended.
- std::string utype = "U" + typestr.str();
- s += "(" + TypeString(proto[0], typestr) + ")";
- abd = "(" + TypeString('d', utype) + ")" + abd;
- s += Extend(utype, abd) + ";";
- } else {
- s += Extend(typestr, abd) + ";";
- }
- break;
- }
- default:
- throw "unknown OpKind!";
- break;
- }
- return s;
-}
-
-static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
- unsigned mod = proto[0];
- unsigned ret = 0;
-
- if (mod == 'v' || mod == 'f')
- mod = proto[1];
-
- bool quad = false;
- bool poly = false;
- bool usgn = false;
- bool scal = false;
- bool cnst = false;
- bool pntr = false;
-
- // Base type to get the type string for.
- char type = ClassifyType(typestr, quad, poly, usgn);
-
- // Based on the modifying character, change the type and width if necessary.
- type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
-
- if (usgn)
- ret |= 0x08;
- if (quad && proto[1] != 'g')
- ret |= 0x10;
-
- switch (type) {
- case 'c':
- ret |= poly ? 5 : 0;
- break;
- case 's':
- ret |= poly ? 6 : 1;
- break;
- case 'i':
- ret |= 2;
- break;
- case 'l':
- ret |= 3;
- break;
- case 'h':
- ret |= 7;
- break;
- case 'f':
- ret |= 4;
- break;
- default:
- throw "unhandled type!";
- break;
- }
- return ret;
-}
-
-// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
-static std::string GenBuiltin(const std::string &name, const std::string &proto,
- StringRef typestr, ClassKind ck) {
- std::string s;
-
- // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
- // sret-like argument.
- bool sret = (proto[0] >= '2' && proto[0] <= '4');
-
- bool define = UseMacro(proto);
-
- // Check if the prototype has a scalar operand with the type of the vector
- // elements. If not, bitcasting the args will take care of arg checking.
- // The actual signedness etc. will be taken care of with special enums.
- if (proto.find('s') == std::string::npos)
- ck = ClassB;
-
- if (proto[0] != 'v') {
- std::string ts = TypeString(proto[0], typestr);
-
- if (define) {
- if (sret)
- s += ts + " r; ";
- else
- s += "(" + ts + ")";
- } else if (sret) {
- s += ts + " r; ";
- } else {
- s += "return (" + ts + ")";
- }
- }
-
- bool splat = proto.find('a') != std::string::npos;
-
- s += "__builtin_neon_";
- if (splat) {
- // Call the non-splat builtin: chop off the "_n" suffix from the name.
- std::string vname(name, 0, name.size()-2);
- s += MangleName(vname, typestr, ck);
- } else {
- s += MangleName(name, typestr, ck);
- }
- s += "(";
-
- // Pass the address of the return variable as the first argument to sret-like
- // builtins.
- if (sret)
- s += "&r, ";
-
- char arg = 'a';
- for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
- std::string args = std::string(&arg, 1);
-
- // Use the local temporaries instead of the macro arguments.
- args = "__" + args;
-
- bool argQuad = false;
- bool argPoly = false;
- bool argUsgn = false;
- bool argScalar = false;
- bool dummy = false;
- char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn);
- argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar,
- dummy, dummy);
-
- // Handle multiple-vector values specially, emitting each subvector as an
- // argument to the __builtin.
- if (proto[i] >= '2' && proto[i] <= '4') {
- // Check if an explicit cast is needed.
- if (argType != 'c' || argPoly || argUsgn)
- args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args;
-
- for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
- s += args + ".val[" + utostr(vi) + "]";
- if ((vi + 1) < ve)
- s += ", ";
- }
- if ((i + 1) < e)
- s += ", ";
-
- continue;
- }
-
- if (splat && (i + 1) == e)
- args = Duplicate(GetNumElements(typestr, argQuad), typestr, args);
-
- // Check if an explicit cast is needed.
- if ((splat || !argScalar) &&
- ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) {
- std::string argTypeStr = "c";
- if (ck != ClassB)
- argTypeStr = argType;
- if (argQuad)
- argTypeStr = "Q" + argTypeStr;
- args = "(" + TypeString('d', argTypeStr) + ")" + args;
- }
-
- s += args;
- if ((i + 1) < e)
- s += ", ";
- }
-
- // Extra constant integer to hold type class enum for this function, e.g. s8
- if (ck == ClassB)
- s += ", " + utostr(GetNeonEnum(proto, typestr));
-
- s += ");";
-
- if (proto[0] != 'v' && sret) {
- if (define)
- s += " r;";
- else
- s += " return r;";
- }
- return s;
-}
-
-static std::string GenBuiltinDef(const std::string &name,
- const std::string &proto,
- StringRef typestr, ClassKind ck) {
- std::string s("BUILTIN(__builtin_neon_");
-
- // If all types are the same size, bitcasting the args will take care
- // of arg checking. The actual signedness etc. will be taken care of with
- // special enums.
- if (proto.find('s') == std::string::npos)
- ck = ClassB;
-
- s += MangleName(name, typestr, ck);
- s += ", \"";
-
- for (unsigned i = 0, e = proto.size(); i != e; ++i)
- s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
-
- // Extra constant integer to hold type class enum for this function, e.g. s8
- if (ck == ClassB)
- s += "i";
-
- s += "\", \"n\")";
- return s;
-}
-
-static std::string GenIntrinsic(const std::string &name,
- const std::string &proto,
- StringRef outTypeStr, StringRef inTypeStr,
- OpKind kind, ClassKind classKind) {
- assert(!proto.empty() && "");
- bool define = UseMacro(proto);
- std::string s;
-
- // static always inline + return type
- if (define)
- s += "#define ";
- else
- s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
-
- // Function name with type suffix
- std::string mangledName = MangleName(name, outTypeStr, ClassS);
- if (outTypeStr != inTypeStr) {
- // If the input type is different (e.g., for vreinterpret), append a suffix
- // for the input type. String off a "Q" (quad) prefix so that MangleName
- // does not insert another "q" in the name.
- unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
- StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
- mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
- }
- s += mangledName;
-
- // Function arguments
- s += GenArgs(proto, inTypeStr);
-
- // Definition.
- if (define) {
- s += " __extension__ ({ \\\n ";
- s += GenMacroLocals(proto, inTypeStr);
- } else {
- s += " { \\\n ";
- }
-
- if (kind != OpNone)
- s += GenOpString(kind, proto, outTypeStr);
- else
- s += GenBuiltin(name, proto, outTypeStr, classKind);
- if (define)
- s += " })";
- else
- s += " }";
- s += "\n";
- return s;
-}
-
-/// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h
-/// is comprised of type definitions and function declarations.
-void NeonEmitter::run(raw_ostream &OS) {
- OS <<
- "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------"
- "---===\n"
- " *\n"
- " * Permission is hereby granted, free of charge, to any person obtaining "
- "a copy\n"
- " * of this software and associated documentation files (the \"Software\"),"
- " to deal\n"
- " * in the Software without restriction, including without limitation the "
- "rights\n"
- " * to use, copy, modify, merge, publish, distribute, sublicense, "
- "and/or sell\n"
- " * copies of the Software, and to permit persons to whom the Software is\n"
- " * furnished to do so, subject to the following conditions:\n"
- " *\n"
- " * The above copyright notice and this permission notice shall be "
- "included in\n"
- " * all copies or substantial portions of the Software.\n"
- " *\n"
- " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
- "EXPRESS OR\n"
- " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
- "MERCHANTABILITY,\n"
- " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT "
- "SHALL THE\n"
- " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR "
- "OTHER\n"
- " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, "
- "ARISING FROM,\n"
- " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
- "DEALINGS IN\n"
- " * THE SOFTWARE.\n"
- " *\n"
- " *===--------------------------------------------------------------------"
- "---===\n"
- " */\n\n";
-
- OS << "#ifndef __ARM_NEON_H\n";
- OS << "#define __ARM_NEON_H\n\n";
-
- OS << "#ifndef __ARM_NEON__\n";
- OS << "#error \"NEON support not enabled\"\n";
- OS << "#endif\n\n";
-
- OS << "#include <stdint.h>\n\n";
-
- // Emit NEON-specific scalar typedefs.
- OS << "typedef float float32_t;\n";
- OS << "typedef int8_t poly8_t;\n";
- OS << "typedef int16_t poly16_t;\n";
- OS << "typedef uint16_t float16_t;\n";
-
- // Emit Neon vector typedefs.
- std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
- SmallVector<StringRef, 24> TDTypeVec;
- ParseTypes(0, TypedefTypes, TDTypeVec);
-
- // Emit vector typedefs.
- for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
- bool dummy, quad = false, poly = false;
- (void) ClassifyType(TDTypeVec[i], quad, poly, dummy);
- if (poly)
- OS << "typedef __attribute__((neon_polyvector_type(";
- else
- OS << "typedef __attribute__((neon_vector_type(";
-
- unsigned nElts = GetNumElements(TDTypeVec[i], quad);
- OS << utostr(nElts) << "))) ";
- if (nElts < 10)
- OS << " ";
-
- OS << TypeString('s', TDTypeVec[i]);
- OS << " " << TypeString('d', TDTypeVec[i]) << ";\n";
- }
- OS << "\n";
-
- // Emit struct typedefs.
- for (unsigned vi = 2; vi != 5; ++vi) {
- for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
- std::string ts = TypeString('d', TDTypeVec[i]);
- std::string vs = TypeString('0' + vi, TDTypeVec[i]);
- OS << "typedef struct " << vs << " {\n";
- OS << " " << ts << " val";
- OS << "[" << utostr(vi) << "]";
- OS << ";\n} ";
- OS << vs << ";\n\n";
- }
- }
-
- OS << "#define __ai static __attribute__((__always_inline__))\n\n";
-
- std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
-
- // Emit vmovl, vmull and vabd intrinsics first so they can be used by other
- // intrinsics. (Some of the saturating multiply instructions are also
- // used to implement the corresponding "_lane" variants, but tablegen
- // sorts the records into alphabetical order so that the "_lane" variants
- // come after the intrinsics they use.)
- emitIntrinsic(OS, Records.getDef("VMOVL"));
- emitIntrinsic(OS, Records.getDef("VMULL"));
- emitIntrinsic(OS, Records.getDef("VABD"));
-
- for (unsigned i = 0, e = RV.size(); i != e; ++i) {
- Record *R = RV[i];
- if (R->getName() != "VMOVL" &&
- R->getName() != "VMULL" &&
- R->getName() != "VABD")
- emitIntrinsic(OS, R);
- }
-
- OS << "#undef __ai\n\n";
- OS << "#endif /* __ARM_NEON_H */\n";
-}
-
-/// emitIntrinsic - Write out the arm_neon.h header file definitions for the
-/// intrinsics specified by record R.
-void NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R) {
- std::string name = R->getValueAsString("Name");
- std::string Proto = R->getValueAsString("Prototype");
- std::string Types = R->getValueAsString("Types");
-
- SmallVector<StringRef, 16> TypeVec;
- ParseTypes(R, Types, TypeVec);
-
- OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
-
- ClassKind classKind = ClassNone;
- if (R->getSuperClasses().size() >= 2)
- classKind = ClassMap[R->getSuperClasses()[1]];
- if (classKind == ClassNone && kind == OpNone)
- throw TGError(R->getLoc(), "Builtin has no class kind");
-
- for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
- if (kind == OpReinterpret) {
- bool outQuad = false;
- bool dummy = false;
- (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
- for (unsigned srcti = 0, srcte = TypeVec.size();
- srcti != srcte; ++srcti) {
- bool inQuad = false;
- (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
- if (srcti == ti || inQuad != outQuad)
- continue;
- OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
- OpCast, ClassS);
- }
- } else {
- OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti],
- kind, classKind);
- }
- }
- OS << "\n";
-}
-
-static unsigned RangeFromType(const char mod, StringRef typestr) {
- // base type to get the type string for.
- bool quad = false, dummy = false;
- char type = ClassifyType(typestr, quad, dummy, dummy);
- type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy);
-
- switch (type) {
- case 'c':
- return (8 << (int)quad) - 1;
- case 'h':
- case 's':
- return (4 << (int)quad) - 1;
- case 'f':
- case 'i':
- return (2 << (int)quad) - 1;
- case 'l':
- return (1 << (int)quad) - 1;
- default:
- throw "unhandled type!";
- break;
- }
- assert(0 && "unreachable");
- return 0;
-}
-
-/// runHeader - Emit a file with sections defining:
-/// 1. the NEON section of BuiltinsARM.def.
-/// 2. the SemaChecking code for the type overload checking.
-/// 3. the SemaChecking code for validation of intrinsic immedate arguments.
-void NeonEmitter::runHeader(raw_ostream &OS) {
- std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
-
- StringMap<OpKind> EmittedMap;
-
- // Generate BuiltinsARM.def for NEON
- OS << "#ifdef GET_NEON_BUILTINS\n";
- for (unsigned i = 0, e = RV.size(); i != e; ++i) {
- Record *R = RV[i];
- OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
- if (k != OpNone)
- continue;
-
- std::string Proto = R->getValueAsString("Prototype");
-
- // Functions with 'a' (the splat code) in the type prototype should not get
- // their own builtin as they use the non-splat variant.
- if (Proto.find('a') != std::string::npos)
- continue;
-
- std::string Types = R->getValueAsString("Types");
- SmallVector<StringRef, 16> TypeVec;
- ParseTypes(R, Types, TypeVec);
-
- if (R->getSuperClasses().size() < 2)
- throw TGError(R->getLoc(), "Builtin has no class kind");
-
- std::string name = R->getValueAsString("Name");
- ClassKind ck = ClassMap[R->getSuperClasses()[1]];
-
- for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
- // Generate the BuiltinsARM.def declaration for this builtin, ensuring
- // that each unique BUILTIN() macro appears only once in the output
- // stream.
- std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
- if (EmittedMap.count(bd))
- continue;
-
- EmittedMap[bd] = OpNone;
- OS << bd << "\n";
- }
- }
- OS << "#endif\n\n";
-
- // Generate the overloaded type checking code for SemaChecking.cpp
- OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
- for (unsigned i = 0, e = RV.size(); i != e; ++i) {
- Record *R = RV[i];
- OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
- if (k != OpNone)
- continue;
-
- std::string Proto = R->getValueAsString("Prototype");
- std::string Types = R->getValueAsString("Types");
- std::string name = R->getValueAsString("Name");
-
- // Functions with 'a' (the splat code) in the type prototype should not get
- // their own builtin as they use the non-splat variant.
- if (Proto.find('a') != std::string::npos)
- continue;
-
- // Functions which have a scalar argument cannot be overloaded, no need to
- // check them if we are emitting the type checking code.
- if (Proto.find('s') != std::string::npos)
- continue;
-
- SmallVector<StringRef, 16> TypeVec;
- ParseTypes(R, Types, TypeVec);
-
- if (R->getSuperClasses().size() < 2)
- throw TGError(R->getLoc(), "Builtin has no class kind");
-
- int si = -1, qi = -1;
- unsigned mask = 0, qmask = 0;
- for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
- // Generate the switch case(s) for this builtin for the type validation.
- bool quad = false, poly = false, usgn = false;
- (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
-
- if (quad) {
- qi = ti;
- qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
- } else {
- si = ti;
- mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
- }
- }
- if (mask)
- OS << "case ARM::BI__builtin_neon_"
- << MangleName(name, TypeVec[si], ClassB)
- << ": mask = " << "0x" << utohexstr(mask) << "; break;\n";
- if (qmask)
- OS << "case ARM::BI__builtin_neon_"
- << MangleName(name, TypeVec[qi], ClassB)
- << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n";
- }
- OS << "#endif\n\n";
-
- // Generate the intrinsic range checking code for shift/lane immediates.
- OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
- for (unsigned i = 0, e = RV.size(); i != e; ++i) {
- Record *R = RV[i];
-
- OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
- if (k != OpNone)
- continue;
-
- std::string name = R->getValueAsString("Name");
- std::string Proto = R->getValueAsString("Prototype");
- std::string Types = R->getValueAsString("Types");
-
- // Functions with 'a' (the splat code) in the type prototype should not get
- // their own builtin as they use the non-splat variant.
- if (Proto.find('a') != std::string::npos)
- continue;
-
- // Functions which do not have an immediate do not need to have range
- // checking code emitted.
- size_t immPos = Proto.find('i');
- if (immPos == std::string::npos)
- continue;
-
- SmallVector<StringRef, 16> TypeVec;
- ParseTypes(R, Types, TypeVec);
-
- if (R->getSuperClasses().size() < 2)
- throw TGError(R->getLoc(), "Builtin has no class kind");
-
- ClassKind ck = ClassMap[R->getSuperClasses()[1]];
-
- for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
- std::string namestr, shiftstr, rangestr;
-
- if (R->getValueAsBit("isVCVT_N")) {
- // VCVT between floating- and fixed-point values takes an immediate
- // in the range 1 to 32.
- ck = ClassB;
- rangestr = "l = 1; u = 31"; // upper bound = l + u
- } else if (Proto.find('s') == std::string::npos) {
- // Builtins which are overloaded by type will need to have their upper
- // bound computed at Sema time based on the type constant.
- ck = ClassB;
- if (R->getValueAsBit("isShift")) {
- shiftstr = ", true";
-
- // Right shifts have an 'r' in the name, left shifts do not.
- if (name.find('r') != std::string::npos)
- rangestr = "l = 1; ";
- }
- rangestr += "u = RFT(TV" + shiftstr + ")";
- } else {
- // The immediate generally refers to a lane in the preceding argument.
- assert(immPos > 0 && "unexpected immediate operand");
- rangestr = "u = " + utostr(RangeFromType(Proto[immPos-1], TypeVec[ti]));
- }
- // Make sure cases appear only once by uniquing them in a string map.
- namestr = MangleName(name, TypeVec[ti], ck);
- if (EmittedMap.count(namestr))
- continue;
- EmittedMap[namestr] = OpNone;
-
- // Calculate the index of the immediate that should be range checked.
- unsigned immidx = 0;
-
- // Builtins that return a struct of multiple vectors have an extra
- // leading arg for the struct return.
- if (Proto[0] >= '2' && Proto[0] <= '4')
- ++immidx;
-
- // Add one to the index for each argument until we reach the immediate
- // to be checked. Structs of vectors are passed as multiple arguments.
- for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
- switch (Proto[ii]) {
- default: immidx += 1; break;
- case '2': immidx += 2; break;
- case '3': immidx += 3; break;
- case '4': immidx += 4; break;
- case 'i': ie = ii + 1; break;
- }
- }
- OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
- << ": i = " << immidx << "; " << rangestr << "; break;\n";
- }
- }
- OS << "#endif\n\n";
-}
-
-/// GenTest - Write out a test for the intrinsic specified by the name and
-/// type strings, including the embedded patterns for FileCheck to match.
-static std::string GenTest(const std::string &name,
- const std::string &proto,
- StringRef outTypeStr, StringRef inTypeStr,
- bool isShift) {
- assert(!proto.empty() && "");
- std::string s;
-
- // Function name with type suffix
- std::string mangledName = MangleName(name, outTypeStr, ClassS);
- if (outTypeStr != inTypeStr) {
- // If the input type is different (e.g., for vreinterpret), append a suffix
- // for the input type. String off a "Q" (quad) prefix so that MangleName
- // does not insert another "q" in the name.
- unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
- StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
- mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
- }
-
- // Emit the FileCheck patterns.
- s += "// CHECK: test_" + mangledName + "\n";
- // s += "// CHECK: \n"; // FIXME: + expected instruction opcode.
-
- // Emit the start of the test function.
- s += TypeString(proto[0], outTypeStr) + " test_" + mangledName + "(";
- char arg = 'a';
- std::string comma;
- for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
- // Do not create arguments for values that must be immediate constants.
- if (proto[i] == 'i')
- continue;
- s += comma + TypeString(proto[i], inTypeStr) + " ";
- s.push_back(arg);
- comma = ", ";
- }
- s += ") { \\\n ";
-
- if (proto[0] != 'v')
- s += "return ";
- s += mangledName + "(";
- arg = 'a';
- for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
- if (proto[i] == 'i') {
- // For immediate operands, test the maximum value.
- if (isShift)
- s += "1"; // FIXME
- else
- // The immediate generally refers to a lane in the preceding argument.
- s += utostr(RangeFromType(proto[i-1], inTypeStr));
- } else {
- s.push_back(arg);
- }
- if ((i + 1) < e)
- s += ", ";
- }
- s += ");\n}\n\n";
- return s;
-}
-
-/// runTests - Write out a complete set of tests for all of the Neon
-/// intrinsics.
-void NeonEmitter::runTests(raw_ostream &OS) {
- OS <<
- "// RUN: %clang_cc1 -triple thumbv7-apple-darwin \\\n"
- "// RUN: -target-cpu cortex-a9 -ffreestanding -S -o - %s | FileCheck %s\n"
- "\n"
- "#include <arm_neon.h>\n"
- "\n";
-
- std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
- for (unsigned i = 0, e = RV.size(); i != e; ++i) {
- Record *R = RV[i];
- std::string name = R->getValueAsString("Name");
- std::string Proto = R->getValueAsString("Prototype");
- std::string Types = R->getValueAsString("Types");
- bool isShift = R->getValueAsBit("isShift");
-
- SmallVector<StringRef, 16> TypeVec;
- ParseTypes(R, Types, TypeVec);
-
- OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
- for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
- if (kind == OpReinterpret) {
- bool outQuad = false;
- bool dummy = false;
- (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
- for (unsigned srcti = 0, srcte = TypeVec.size();
- srcti != srcte; ++srcti) {
- bool inQuad = false;
- (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
- if (srcti == ti || inQuad != outQuad)
- continue;
- OS << GenTest(name, Proto, TypeVec[ti], TypeVec[srcti], isShift);
- }
- } else {
- OS << GenTest(name, Proto, TypeVec[ti], TypeVec[ti], isShift);
- }
- }
- OS << "\n";
- }
-}
-
diff --git a/utils/TableGen/NeonEmitter.h b/utils/TableGen/NeonEmitter.h
deleted file mode 100644
index 12e4e86..0000000
--- a/utils/TableGen/NeonEmitter.h
+++ /dev/null
@@ -1,176 +0,0 @@
-//===- NeonEmitter.h - Generate arm_neon.h for use with clang ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This tablegen backend is responsible for emitting arm_neon.h, which includes
-// a declaration and definition of each function specified by the ARM NEON
-// compiler interface. See ARM document DUI0348B.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef NEON_EMITTER_H
-#define NEON_EMITTER_H
-
-#include "Record.h"
-#include "TableGenBackend.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringMap.h"
-
-enum OpKind {
- OpNone,
- OpAdd,
- OpAddl,
- OpAddw,
- OpSub,
- OpSubl,
- OpSubw,
- OpMul,
- OpMla,
- OpMlal,
- OpMls,
- OpMlsl,
- OpMulN,
- OpMlaN,
- OpMlsN,
- OpMlalN,
- OpMlslN,
- OpMulLane,
- OpMullLane,
- OpMlaLane,
- OpMlsLane,
- OpMlalLane,
- OpMlslLane,
- OpQDMullLane,
- OpQDMlalLane,
- OpQDMlslLane,
- OpQDMulhLane,
- OpQRDMulhLane,
- OpEq,
- OpGe,
- OpLe,
- OpGt,
- OpLt,
- OpNeg,
- OpNot,
- OpAnd,
- OpOr,
- OpXor,
- OpAndNot,
- OpOrNot,
- OpCast,
- OpConcat,
- OpDup,
- OpDupLane,
- OpHi,
- OpLo,
- OpSelect,
- OpRev16,
- OpRev32,
- OpRev64,
- OpReinterpret,
- OpAbdl,
- OpAba,
- OpAbal
-};
-
-enum ClassKind {
- ClassNone,
- ClassI, // generic integer instruction, e.g., "i8" suffix
- ClassS, // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix
- ClassW, // width-specific instruction, e.g., "8" suffix
- ClassB // bitcast arguments with enum argument to specify type
-};
-
-namespace llvm {
-
- class NeonEmitter : public TableGenBackend {
- RecordKeeper &Records;
- StringMap<OpKind> OpMap;
- DenseMap<Record*, ClassKind> ClassMap;
-
- public:
- NeonEmitter(RecordKeeper &R) : Records(R) {
- OpMap["OP_NONE"] = OpNone;
- OpMap["OP_ADD"] = OpAdd;
- OpMap["OP_ADDL"] = OpAddl;
- OpMap["OP_ADDW"] = OpAddw;
- OpMap["OP_SUB"] = OpSub;
- OpMap["OP_SUBL"] = OpSubl;
- OpMap["OP_SUBW"] = OpSubw;
- OpMap["OP_MUL"] = OpMul;
- OpMap["OP_MLA"] = OpMla;
- OpMap["OP_MLAL"] = OpMlal;
- OpMap["OP_MLS"] = OpMls;
- OpMap["OP_MLSL"] = OpMlsl;
- OpMap["OP_MUL_N"] = OpMulN;
- OpMap["OP_MLA_N"] = OpMlaN;
- OpMap["OP_MLS_N"] = OpMlsN;
- OpMap["OP_MLAL_N"] = OpMlalN;
- OpMap["OP_MLSL_N"] = OpMlslN;
- OpMap["OP_MUL_LN"]= OpMulLane;
- OpMap["OP_MULL_LN"] = OpMullLane;
- OpMap["OP_MLA_LN"]= OpMlaLane;
- OpMap["OP_MLS_LN"]= OpMlsLane;
- OpMap["OP_MLAL_LN"] = OpMlalLane;
- OpMap["OP_MLSL_LN"] = OpMlslLane;
- OpMap["OP_QDMULL_LN"] = OpQDMullLane;
- OpMap["OP_QDMLAL_LN"] = OpQDMlalLane;
- OpMap["OP_QDMLSL_LN"] = OpQDMlslLane;
- OpMap["OP_QDMULH_LN"] = OpQDMulhLane;
- OpMap["OP_QRDMULH_LN"] = OpQRDMulhLane;
- OpMap["OP_EQ"] = OpEq;
- OpMap["OP_GE"] = OpGe;
- OpMap["OP_LE"] = OpLe;
- OpMap["OP_GT"] = OpGt;
- OpMap["OP_LT"] = OpLt;
- OpMap["OP_NEG"] = OpNeg;
- OpMap["OP_NOT"] = OpNot;
- OpMap["OP_AND"] = OpAnd;
- OpMap["OP_OR"] = OpOr;
- OpMap["OP_XOR"] = OpXor;
- OpMap["OP_ANDN"] = OpAndNot;
- OpMap["OP_ORN"] = OpOrNot;
- OpMap["OP_CAST"] = OpCast;
- OpMap["OP_CONC"] = OpConcat;
- OpMap["OP_HI"] = OpHi;
- OpMap["OP_LO"] = OpLo;
- OpMap["OP_DUP"] = OpDup;
- OpMap["OP_DUP_LN"] = OpDupLane;
- OpMap["OP_SEL"] = OpSelect;
- OpMap["OP_REV16"] = OpRev16;
- OpMap["OP_REV32"] = OpRev32;
- OpMap["OP_REV64"] = OpRev64;
- OpMap["OP_REINT"] = OpReinterpret;
- OpMap["OP_ABDL"] = OpAbdl;
- OpMap["OP_ABA"] = OpAba;
- OpMap["OP_ABAL"] = OpAbal;
-
- Record *SI = R.getClass("SInst");
- Record *II = R.getClass("IInst");
- Record *WI = R.getClass("WInst");
- ClassMap[SI] = ClassS;
- ClassMap[II] = ClassI;
- ClassMap[WI] = ClassW;
- }
-
- // run - Emit arm_neon.h.inc
- void run(raw_ostream &o);
-
- // runHeader - Emit all the __builtin prototypes used in arm_neon.h
- void runHeader(raw_ostream &o);
-
- // runTests - Emit tests for all the Neon intrinsics.
- void runTests(raw_ostream &o);
-
- private:
- void emitIntrinsic(raw_ostream &OS, Record *R);
- };
-
-} // End llvm namespace
-
-#endif
diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp
deleted file mode 100644
index 431026c..0000000
--- a/utils/TableGen/OptParserEmitter.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "OptParserEmitter.h"
-#include "Record.h"
-#include "llvm/ADT/STLExtras.h"
-using namespace llvm;
-
-static int StrCmpOptionName(const char *A, const char *B) {
- char a = *A, b = *B;
- while (a == b) {
- if (a == '\0')
- return 0;
-
- a = *++A;
- b = *++B;
- }
-
- if (a == '\0') // A is a prefix of B.
- return 1;
- if (b == '\0') // B is a prefix of A.
- return -1;
-
- // Otherwise lexicographic.
- return (a < b) ? -1 : 1;
-}
-
-static int CompareOptionRecords(const void *Av, const void *Bv) {
- const Record *A = *(Record**) Av;
- const Record *B = *(Record**) Bv;
-
- // Sentinel options precede all others and are only ordered by precedence.
- bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
- bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
- if (ASent != BSent)
- return ASent ? -1 : 1;
-
- // Compare options by name, unless they are sentinels.
- if (!ASent)
- if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
- B->getValueAsString("Name").c_str()))
- return Cmp;
-
- // Then by the kind precedence;
- int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
- int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
- assert(APrec != BPrec && "Options are equivalent!");
- return APrec < BPrec ? -1 : 1;
-}
-
-static const std::string getOptionName(const Record &R) {
- // Use the record name unless EnumName is defined.
- if (dynamic_cast<UnsetInit*>(R.getValueInit("EnumName")))
- return R.getName();
-
- return R.getValueAsString("EnumName");
-}
-
-static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
- OS << '"';
- OS.write_escaped(Str);
- OS << '"';
- return OS;
-}
-
-void OptParserEmitter::run(raw_ostream &OS) {
- // Get the option groups and options.
- const std::vector<Record*> &Groups =
- Records.getAllDerivedDefinitions("OptionGroup");
- std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
-
- if (GenDefs)
- EmitSourceFileHeader("Option Parsing Definitions", OS);
- else
- EmitSourceFileHeader("Option Parsing Table", OS);
-
- array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
- if (GenDefs) {
- OS << "#ifndef OPTION\n";
- OS << "#error \"Define OPTION prior to including this file!\"\n";
- OS << "#endif\n\n";
-
- OS << "/////////\n";
- OS << "// Groups\n\n";
- for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
- const Record &R = *Groups[i];
-
- // Start a single option entry.
- OS << "OPTION(";
-
- // The option string.
- OS << '"' << R.getValueAsString("Name") << '"';
-
- // The option identifier name.
- OS << ", "<< getOptionName(R);
-
- // The option kind.
- OS << ", Group";
-
- // The containing option group (if any).
- OS << ", ";
- if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
- OS << getOptionName(*DI->getDef());
- else
- OS << "INVALID";
-
- // The other option arguments (unused for groups).
- OS << ", INVALID, 0, 0";
-
- // The option help text.
- if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
- OS << ",\n";
- OS << " ";
- write_cstring(OS, R.getValueAsString("HelpText"));
- } else
- OS << ", 0";
-
- // The option meta-variable name (unused).
- OS << ", 0)\n";
- }
- OS << "\n";
-
- OS << "//////////\n";
- OS << "// Options\n\n";
- for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
- const Record &R = *Opts[i];
-
- // Start a single option entry.
- OS << "OPTION(";
-
- // The option string.
- write_cstring(OS, R.getValueAsString("Name"));
-
- // The option identifier name.
- OS << ", "<< getOptionName(R);
-
- // The option kind.
- OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
-
- // The containing option group (if any).
- OS << ", ";
- if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
- OS << getOptionName(*DI->getDef());
- else
- OS << "INVALID";
-
- // The option alias (if any).
- OS << ", ";
- if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Alias")))
- OS << getOptionName(*DI->getDef());
- else
- OS << "INVALID";
-
- // The option flags.
- const ListInit *LI = R.getValueAsListInit("Flags");
- if (LI->empty()) {
- OS << ", 0";
- } else {
- OS << ", ";
- for (unsigned i = 0, e = LI->size(); i != e; ++i) {
- if (i)
- OS << " | ";
- OS << dynamic_cast<DefInit*>(LI->getElement(i))->getDef()->getName();
- }
- }
-
- // The option parameter field.
- OS << ", " << R.getValueAsInt("NumArgs");
-
- // The option help text.
- if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
- OS << ",\n";
- OS << " ";
- write_cstring(OS, R.getValueAsString("HelpText"));
- } else
- OS << ", 0";
-
- // The option meta-variable name.
- OS << ", ";
- if (!dynamic_cast<UnsetInit*>(R.getValueInit("MetaVarName")))
- write_cstring(OS, R.getValueAsString("MetaVarName"));
- else
- OS << "0";
-
- OS << ")\n";
- }
- }
-}
diff --git a/utils/TableGen/OptParserEmitter.h b/utils/TableGen/OptParserEmitter.h
deleted file mode 100644
index 241a3f2..0000000
--- a/utils/TableGen/OptParserEmitter.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- OptParserEmitter.h - Table Driven Command Line Parsing ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef UTILS_TABLEGEN_OPTPARSEREMITTER_H
-#define UTILS_TABLEGEN_OPTPARSEREMITTER_H
-
-#include "TableGenBackend.h"
-
-namespace llvm {
- /// OptParserEmitter - This tablegen backend takes an input .td file
- /// describing a list of options and emits a data structure for parsing and
- /// working with those options when given an input command line.
- class OptParserEmitter : public TableGenBackend {
- RecordKeeper &Records;
- bool GenDefs;
-
- public:
- OptParserEmitter(RecordKeeper &R, bool _GenDefs)
- : Records(R), GenDefs(_GenDefs) {}
-
- /// run - Output the option parsing information.
- ///
- /// \param GenHeader - Generate the header describing the option IDs.x
- void run(raw_ostream &OS);
- };
-}
-
-#endif
diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp
index db33c1f..c685527 100644
--- a/utils/TableGen/PseudoLoweringEmitter.cpp
+++ b/utils/TableGen/PseudoLoweringEmitter.cpp
@@ -8,10 +8,10 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "pseudo-lowering"
-#include "Error.h"
#include "CodeGenInstruction.h"
#include "PseudoLoweringEmitter.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/utils/TableGen/PseudoLoweringEmitter.h b/utils/TableGen/PseudoLoweringEmitter.h
index 2749280..325bc8b 100644
--- a/utils/TableGen/PseudoLoweringEmitter.h
+++ b/utils/TableGen/PseudoLoweringEmitter.h
@@ -12,7 +12,7 @@
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp
deleted file mode 100644
index 730eca1..0000000
--- a/utils/TableGen/Record.cpp
+++ /dev/null
@@ -1,1575 +0,0 @@
-//===- Record.cpp - Record implementation ---------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implement the tablegen record classes.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Record.h"
-#include "Error.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Format.h"
-#include "llvm/ADT/StringExtras.h"
-
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Type implementations
-//===----------------------------------------------------------------------===//
-
-void RecTy::dump() const { print(errs()); }
-
-Init *BitRecTy::convertValue(BitsInit *BI) {
- if (BI->getNumBits() != 1) return 0; // Only accept if just one bit!
- return BI->getBit(0);
-}
-
-bool BitRecTy::baseClassOf(const BitsRecTy *RHS) const {
- return RHS->getNumBits() == 1;
-}
-
-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);
-}
-
-Init *BitRecTy::convertValue(TypedInit *VI) {
- if (dynamic_cast<BitRecTy*>(VI->getType()))
- return VI; // Accept variable if it is already of bit type!
- return 0;
-}
-
-std::string BitsRecTy::getAsString() const {
- return "bits<" + utostr(Size) + ">";
-}
-
-Init *BitsRecTy::convertValue(UnsetInit *UI) {
- BitsInit *Ret = new BitsInit(Size);
-
- for (unsigned i = 0; i != Size; ++i)
- Ret->setBit(i, new UnsetInit());
- return Ret;
-}
-
-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;
-}
-
-/// canFitInBitfield - Return true if the number of bits is large enough to hold
-/// the integer value.
-static bool canFitInBitfield(int64_t Value, unsigned NumBits) {
- // For example, with NumBits == 4, we permit Values from [-7 .. 15].
- return (NumBits >= sizeof(Value) * 8) ||
- (Value >> NumBits == 0) || (Value >> (NumBits-1) == -1);
-}
-
-/// convertValue from Int initializer to bits type: Split the integer up into the
-/// appropriate bits.
-///
-Init *BitsRecTy::convertValue(IntInit *II) {
- int64_t Value = II->getValue();
- // Make sure this bitfield is large enough to hold the integer value.
- if (!canFitInBitfield(Value, Size))
- return 0;
-
- BitsInit *Ret = new BitsInit(Size);
- for (unsigned i = 0; i != Size; ++i)
- Ret->setBit(i, new BitInit(Value & (1LL << i)));
-
- return Ret;
-}
-
-Init *BitsRecTy::convertValue(BitsInit *BI) {
- // If the number of bits is right, return it. Otherwise we need to expand or
- // truncate.
- if (BI->getNumBits() == Size) return BI;
- return 0;
-}
-
-Init *BitsRecTy::convertValue(TypedInit *VI) {
- if (BitsRecTy *BRT = dynamic_cast<BitsRecTy*>(VI->getType()))
- if (BRT->Size == Size) {
- BitsInit *Ret = new BitsInit(Size);
- for (unsigned i = 0; i != Size; ++i)
- Ret->setBit(i, new VarBitInit(VI, i));
- return Ret;
- }
-
- if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType())) {
- BitsInit *Ret = new BitsInit(1);
- Ret->setBit(0, VI);
- return Ret;
- }
-
- if (TernOpInit *Tern = dynamic_cast<TernOpInit*>(VI)) {
- if (Tern->getOpcode() == TernOpInit::IF) {
- Init *LHS = Tern->getLHS();
- Init *MHS = Tern->getMHS();
- Init *RHS = Tern->getRHS();
-
- IntInit *MHSi = dynamic_cast<IntInit*>(MHS);
- IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
-
- if (MHSi && RHSi) {
- int64_t MHSVal = MHSi->getValue();
- int64_t RHSVal = RHSi->getValue();
-
- if (canFitInBitfield(MHSVal, Size) && canFitInBitfield(RHSVal, Size)) {
- BitsInit *Ret = new BitsInit(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()));
-
- return Ret;
- }
- } else {
- BitsInit *MHSbs = dynamic_cast<BitsInit*>(MHS);
- BitsInit *RHSbs = dynamic_cast<BitsInit*>(RHS);
-
- if (MHSbs && RHSbs) {
- BitsInit *Ret = new BitsInit(Size);
-
- for (unsigned i = 0; i != Size; ++i)
- Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS,
- MHSbs->getBit(i),
- RHSbs->getBit(i),
- VI->getType()));
-
- return Ret;
- }
- }
- }
- }
-
- return 0;
-}
-
-Init *IntRecTy::convertValue(BitInit *BI) {
- return new IntInit(BI->getValue());
-}
-
-Init *IntRecTy::convertValue(BitsInit *BI) {
- int64_t Result = 0;
- for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
- if (BitInit *Bit = dynamic_cast<BitInit*>(BI->getBit(i))) {
- Result |= Bit->getValue() << i;
- } else {
- return 0;
- }
- return new IntInit(Result);
-}
-
-Init *IntRecTy::convertValue(TypedInit *TI) {
- if (TI->getType()->typeIsConvertibleTo(this))
- return TI; // Accept variable if already of the right type!
- return 0;
-}
-
-Init *StringRecTy::convertValue(UnOpInit *BO) {
- if (BO->getOpcode() == UnOpInit::CAST) {
- Init *L = BO->getOperand()->convertInitializerTo(this);
- if (L == 0) return 0;
- if (L != BO->getOperand())
- return new UnOpInit(UnOpInit::CAST, L, new StringRecTy);
- return BO;
- }
-
- return convertValue((TypedInit*)BO);
-}
-
-Init *StringRecTy::convertValue(BinOpInit *BO) {
- if (BO->getOpcode() == BinOpInit::STRCONCAT) {
- Init *L = BO->getLHS()->convertInitializerTo(this);
- 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 BO;
- }
-
- return convertValue((TypedInit*)BO);
-}
-
-
-Init *StringRecTy::convertValue(TypedInit *TI) {
- if (dynamic_cast<StringRecTy*>(TI->getType()))
- return TI; // Accept variable if already of the right type!
- return 0;
-}
-
-std::string ListRecTy::getAsString() const {
- return "list<" + Ty->getAsString() + ">";
-}
-
-Init *ListRecTy::convertValue(ListInit *LI) {
- std::vector<Init*> Elements;
-
- // Verify that all of the elements of the list are subclasses of the
- // appropriate class!
- for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
- if (Init *CI = LI->getElement(i)->convertInitializerTo(Ty))
- Elements.push_back(CI);
- else
- return 0;
-
- ListRecTy *LType = dynamic_cast<ListRecTy*>(LI->getType());
- if (LType == 0) {
- return 0;
- }
-
- return new ListInit(Elements, new ListRecTy(Ty));
-}
-
-Init *ListRecTy::convertValue(TypedInit *TI) {
- // Ensure that TI is compatible with our class.
- if (ListRecTy *LRT = dynamic_cast<ListRecTy*>(TI->getType()))
- if (LRT->getElementType()->typeIsConvertibleTo(getElementType()))
- return TI;
- return 0;
-}
-
-Init *CodeRecTy::convertValue(TypedInit *TI) {
- if (TI->getType()->typeIsConvertibleTo(this))
- return TI;
- return 0;
-}
-
-Init *DagRecTy::convertValue(TypedInit *TI) {
- if (TI->getType()->typeIsConvertibleTo(this))
- return TI;
- return 0;
-}
-
-Init *DagRecTy::convertValue(UnOpInit *BO) {
- if (BO->getOpcode() == UnOpInit::CAST) {
- Init *L = BO->getOperand()->convertInitializerTo(this);
- if (L == 0) return 0;
- if (L != BO->getOperand())
- return new UnOpInit(UnOpInit::CAST, L, new DagRecTy);
- return BO;
- }
- return 0;
-}
-
-Init *DagRecTy::convertValue(BinOpInit *BO) {
- if (BO->getOpcode() == BinOpInit::CONCAT) {
- Init *L = BO->getLHS()->convertInitializerTo(this);
- 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 BO;
- }
- return 0;
-}
-
-std::string RecordRecTy::getAsString() const {
- return Rec->getName();
-}
-
-Init *RecordRecTy::convertValue(DefInit *DI) {
- // Ensure that DI is a subclass of Rec.
- if (!DI->getDef()->isSubClassOf(Rec))
- return 0;
- return DI;
-}
-
-Init *RecordRecTy::convertValue(TypedInit *TI) {
- // Ensure that TI is compatible with Rec.
- if (RecordRecTy *RRT = dynamic_cast<RecordRecTy*>(TI->getType()))
- if (RRT->getRecord()->isSubClassOf(getRecord()) ||
- RRT->getRecord() == getRecord())
- return TI;
- return 0;
-}
-
-bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const {
- if (Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec))
- return true;
-
- const std::vector<Record*> &SC = Rec->getSuperClasses();
- for (unsigned i = 0, e = SC.size(); i != e; ++i)
- if (RHS->getRecord()->isSubClassOf(SC[i]))
- return true;
-
- return false;
-}
-
-
-/// resolveTypes - Find a common type that T1 and T2 convert to.
-/// Return 0 if no such type exists.
-///
-RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) {
- if (!T1->typeIsConvertibleTo(T2)) {
- if (!T2->typeIsConvertibleTo(T1)) {
- // If one is a Record type, check superclasses
- RecordRecTy *RecTy1 = dynamic_cast<RecordRecTy*>(T1);
- if (RecTy1) {
- // See if T2 inherits from a type T1 also inherits from
- const std::vector<Record *> &T1SuperClasses =
- RecTy1->getRecord()->getSuperClasses();
- for(std::vector<Record *>::const_iterator i = T1SuperClasses.begin(),
- iend = T1SuperClasses.end();
- i != iend;
- ++i) {
- RecordRecTy *SuperRecTy1 = new RecordRecTy(*i);
- RecTy *NewType1 = resolveTypes(SuperRecTy1, T2);
- if (NewType1 != 0) {
- if (NewType1 != SuperRecTy1) {
- delete SuperRecTy1;
- }
- return NewType1;
- }
- }
- }
- RecordRecTy *RecTy2 = dynamic_cast<RecordRecTy*>(T2);
- if (RecTy2) {
- // See if T1 inherits from a type T2 also inherits from
- const std::vector<Record *> &T2SuperClasses =
- RecTy2->getRecord()->getSuperClasses();
- for (std::vector<Record *>::const_iterator i = T2SuperClasses.begin(),
- iend = T2SuperClasses.end();
- i != iend;
- ++i) {
- RecordRecTy *SuperRecTy2 = new RecordRecTy(*i);
- RecTy *NewType2 = resolveTypes(T1, SuperRecTy2);
- if (NewType2 != 0) {
- if (NewType2 != SuperRecTy2) {
- delete SuperRecTy2;
- }
- return NewType2;
- }
- }
- }
- return 0;
- }
- return T2;
- }
- return T1;
-}
-
-
-//===----------------------------------------------------------------------===//
-// Initializer implementations
-//===----------------------------------------------------------------------===//
-
-void Init::dump() const { return print(errs()); }
-
-Init *BitsInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
- BitsInit *BI = new BitsInit(Bits.size());
- for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
- if (Bits[i] >= getNumBits()) {
- delete BI;
- return 0;
- }
- BI->setBit(i, getBit(Bits[i]));
- }
- return BI;
-}
-
-std::string BitsInit::getAsString() const {
- std::string Result = "{ ";
- for (unsigned i = 0, e = getNumBits(); i != e; ++i) {
- if (i) Result += ", ";
- if (Init *Bit = getBit(e-i-1))
- Result += Bit->getAsString();
- else
- Result += "*";
- }
- return Result + " }";
-}
-
-// 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) {
- bool Changed = false;
- BitsInit *New = new BitsInit(getNumBits());
-
- for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
- Init *B;
- Init *CurBit = getBit(i);
-
- do {
- B = CurBit;
- CurBit = CurBit->resolveReferences(R, RV);
- Changed |= B != CurBit;
- } while (B != CurBit);
- New->setBit(i, CurBit);
- }
-
- if (Changed)
- return New;
- delete New;
- return this;
-}
-
-std::string IntInit::getAsString() const {
- return itostr(Value);
-}
-
-Init *IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
- BitsInit *BI = new BitsInit(Bits.size());
-
- for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
- if (Bits[i] >= 64) {
- delete BI;
- return 0;
- }
- BI->setBit(i, new BitInit(Value & (INT64_C(1) << Bits[i])));
- }
- return BI;
-}
-
-Init *ListInit::convertInitListSlice(const std::vector<unsigned> &Elements) {
- std::vector<Init*> 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());
-}
-
-Record *ListInit::getElementAsRecord(unsigned i) const {
- assert(i < Values.size() && "List element index out of range!");
- DefInit *DI = dynamic_cast<DefInit*>(Values[i]);
- if (DI == 0) throw "Expected record in list!";
- return DI->getDef();
-}
-
-Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) {
- std::vector<Init*> Resolved;
- Resolved.reserve(getSize());
- bool Changed = false;
-
- for (unsigned i = 0, e = getSize(); i != e; ++i) {
- Init *E;
- Init *CurElt = getElement(i);
-
- do {
- E = CurElt;
- CurElt = CurElt->resolveReferences(R, RV);
- Changed |= E != CurElt;
- } while (E != CurElt);
- Resolved.push_back(E);
- }
-
- if (Changed)
- return new ListInit(Resolved, getType());
- return this;
-}
-
-Init *ListInit::resolveListElementReference(Record &R, const RecordVal *IRV,
- unsigned Elt) {
- if (Elt >= getSize())
- return 0; // Out of range reference.
- Init *E = getElement(Elt);
- // If the element is set to some value, or if we are resolving a reference
- // to a specific variable and that variable is explicitly unset, then
- // replace the VarListElementInit with it.
- if (IRV || !dynamic_cast<UnsetInit*>(E))
- return E;
- return 0;
-}
-
-std::string ListInit::getAsString() const {
- std::string Result = "[";
- for (unsigned i = 0, e = Values.size(); i != e; ++i) {
- if (i) Result += ", ";
- Result += Values[i]->getAsString();
- }
- return Result + "]";
-}
-
-Init *OpInit::resolveBitReference(Record &R, const RecordVal *IRV,
- unsigned Bit) {
- Init *Folded = Fold(&R, 0);
-
- if (Folded != this) {
- TypedInit *Typed = dynamic_cast<TypedInit *>(Folded);
- if (Typed) {
- return Typed->resolveBitReference(R, IRV, Bit);
- }
- }
-
- return 0;
-}
-
-Init *OpInit::resolveListElementReference(Record &R, const RecordVal *IRV,
- unsigned Elt) {
- Init *Folded = Fold(&R, 0);
-
- if (Folded != this) {
- TypedInit *Typed = dynamic_cast<TypedInit *>(Folded);
- if (Typed) {
- return Typed->resolveListElementReference(R, IRV, Elt);
- }
- }
-
- return 0;
-}
-
-Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
- switch (getOpcode()) {
- default: assert(0 && "Unknown unop");
- case CAST: {
- if (getType()->getAsString() == "string") {
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- if (LHSs) {
- return LHSs;
- }
-
- DefInit *LHSd = dynamic_cast<DefInit*>(LHS);
- if (LHSd) {
- return new StringInit(LHSd->getDef()->getName());
- }
- } else {
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- if (LHSs) {
- std::string Name = LHSs->getValue();
-
- // From TGParser::ParseIDValue
- if (CurRec) {
- if (const RecordVal *RV = CurRec->getValue(Name)) {
- if (RV->getType() != getType())
- throw "type mismatch in cast";
- return new VarInit(Name, RV->getType());
- }
-
- std::string TemplateArgName = CurRec->getName()+":"+Name;
- if (CurRec->isTemplateArg(TemplateArgName)) {
- const RecordVal *RV = CurRec->getValue(TemplateArgName);
- assert(RV && "Template arg doesn't exist??");
-
- if (RV->getType() != getType())
- throw "type mismatch in cast";
-
- return new VarInit(TemplateArgName, RV->getType());
- }
- }
-
- if (CurMultiClass) {
- std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
- if (CurMultiClass->Rec.isTemplateArg(MCName)) {
- const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
- assert(RV && "Template arg doesn't exist??");
-
- if (RV->getType() != getType())
- throw "type mismatch in cast";
-
- return new VarInit(MCName, RV->getType());
- }
- }
-
- if (Record *D = (CurRec->getRecords()).getDef(Name))
- return new DefInit(D);
-
- throw TGError(CurRec->getLoc(), "Undefined reference:'" + Name + "'\n");
- }
- }
- break;
- }
- case HEAD: {
- ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
- if (LHSl) {
- if (LHSl->getSize() == 0) {
- assert(0 && "Empty list in car");
- return 0;
- }
- return LHSl->getElement(0);
- }
- break;
- }
- case TAIL: {
- ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
- if (LHSl) {
- if (LHSl->getSize() == 0) {
- assert(0 && "Empty list in cdr");
- return 0;
- }
- ListInit *Result = new ListInit(LHSl->begin()+1, LHSl->end(),
- LHSl->getType());
- return Result;
- }
- break;
- }
- case EMPTY: {
- ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
- if (LHSl) {
- if (LHSl->getSize() == 0) {
- return new IntInit(1);
- } else {
- return new IntInit(0);
- }
- }
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- if (LHSs) {
- if (LHSs->getValue().empty()) {
- return new IntInit(1);
- } else {
- return new IntInit(0);
- }
- }
-
- break;
- }
- }
- return this;
-}
-
-Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) {
- Init *lhs = LHS->resolveReferences(R, RV);
-
- if (LHS != lhs)
- return (new UnOpInit(getOpcode(), lhs, getType()))->Fold(&R, 0);
- return Fold(&R, 0);
-}
-
-std::string UnOpInit::getAsString() const {
- std::string Result;
- switch (Opc) {
- case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;
- case HEAD: Result = "!head"; break;
- case TAIL: Result = "!tail"; break;
- case EMPTY: Result = "!empty"; break;
- }
- return Result + "(" + LHS->getAsString() + ")";
-}
-
-Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
- switch (getOpcode()) {
- default: assert(0 && "Unknown binop");
- case CONCAT: {
- DagInit *LHSs = dynamic_cast<DagInit*>(LHS);
- DagInit *RHSs = dynamic_cast<DagInit*>(RHS);
- if (LHSs && RHSs) {
- DefInit *LOp = dynamic_cast<DefInit*>(LHSs->getOperator());
- DefInit *ROp = dynamic_cast<DefInit*>(RHSs->getOperator());
- if (LOp == 0 || ROp == 0 || LOp->getDef() != ROp->getDef())
- throw "Concated Dag operators do not match!";
- std::vector<Init*> Args;
- std::vector<std::string> ArgNames;
- for (unsigned i = 0, e = LHSs->getNumArgs(); i != e; ++i) {
- Args.push_back(LHSs->getArg(i));
- ArgNames.push_back(LHSs->getArgName(i));
- }
- for (unsigned i = 0, e = RHSs->getNumArgs(); i != e; ++i) {
- Args.push_back(RHSs->getArg(i));
- ArgNames.push_back(RHSs->getArgName(i));
- }
- return new DagInit(LHSs->getOperator(), "", Args, ArgNames);
- }
- break;
- }
- case STRCONCAT: {
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
- if (LHSs && RHSs)
- return new StringInit(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<IntInit*>(LHS->convertInitializerTo(new IntRecTy()));
- IntInit* R =
- dynamic_cast<IntInit*>(RHS->convertInitializerTo(new IntRecTy()));
-
- if (L && R)
- return new IntInit(L->getValue() == R->getValue());
-
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
-
- // Make sure we've resolved
- if (LHSs && RHSs)
- return new IntInit(LHSs->getValue() == RHSs->getValue());
-
- break;
- }
- case SHL:
- case SRA:
- case SRL: {
- IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
- IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
- if (LHSi && RHSi) {
- int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
- int64_t Result;
- switch (getOpcode()) {
- default: assert(0 && "Bad opcode!");
- case SHL: Result = LHSv << RHSv; break;
- case SRA: Result = LHSv >> RHSv; break;
- case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break;
- }
- return new IntInit(Result);
- }
- break;
- }
- }
- return this;
-}
-
-Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) {
- 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 Fold(&R, 0);
-}
-
-std::string BinOpInit::getAsString() const {
- std::string Result;
- switch (Opc) {
- case CONCAT: Result = "!con"; break;
- case SHL: Result = "!shl"; break;
- case SRA: Result = "!sra"; break;
- case SRL: Result = "!srl"; break;
- case EQ: Result = "!eq"; break;
- case STRCONCAT: Result = "!strconcat"; break;
- }
- return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")";
-}
-
-static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
- Record *CurRec, MultiClass *CurMultiClass);
-
-static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg,
- RecTy *Type, Record *CurRec,
- MultiClass *CurMultiClass) {
- std::vector<Init *> NewOperands;
-
- TypedInit *TArg = dynamic_cast<TypedInit*>(Arg);
-
- // If this is a dag, recurse
- if (TArg && TArg->getType()->getAsString() == "dag") {
- Init *Result = ForeachHelper(LHS, Arg, RHSo, Type,
- CurRec, CurMultiClass);
- if (Result != 0) {
- return Result;
- } else {
- return 0;
- }
- }
-
- for (int i = 0; i < RHSo->getNumOperands(); ++i) {
- OpInit *RHSoo = dynamic_cast<OpInit*>(RHSo->getOperand(i));
-
- if (RHSoo) {
- Init *Result = EvaluateOperation(RHSoo, LHS, Arg,
- Type, CurRec, CurMultiClass);
- if (Result != 0) {
- NewOperands.push_back(Result);
- } else {
- NewOperands.push_back(Arg);
- }
- } else if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
- NewOperands.push_back(Arg);
- } else {
- NewOperands.push_back(RHSo->getOperand(i));
- }
- }
-
- // Now run the operator and use its result as the new leaf
- OpInit *NewOp = RHSo->clone(NewOperands);
- Init *NewVal = NewOp->Fold(CurRec, CurMultiClass);
- if (NewVal != NewOp) {
- delete NewOp;
- return NewVal;
- }
- return 0;
-}
-
-static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
- Record *CurRec, MultiClass *CurMultiClass) {
- DagInit *MHSd = dynamic_cast<DagInit*>(MHS);
- ListInit *MHSl = dynamic_cast<ListInit*>(MHS);
-
- DagRecTy *DagType = dynamic_cast<DagRecTy*>(Type);
- ListRecTy *ListType = dynamic_cast<ListRecTy*>(Type);
-
- OpInit *RHSo = dynamic_cast<OpInit*>(RHS);
-
- if (!RHSo) {
- throw TGError(CurRec->getLoc(), "!foreach requires an operator\n");
- }
-
- TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
-
- if (!LHSt) {
- throw TGError(CurRec->getLoc(), "!foreach requires typed variable\n");
- }
-
- if ((MHSd && DagType) || (MHSl && ListType)) {
- if (MHSd) {
- Init *Val = MHSd->getOperator();
- Init *Result = EvaluateOperation(RHSo, LHS, Val,
- Type, CurRec, CurMultiClass);
- if (Result != 0) {
- Val = Result;
- }
-
- std::vector<std::pair<Init *, std::string> > args;
- for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) {
- Init *Arg;
- std::string ArgName;
- Arg = MHSd->getArg(i);
- ArgName = MHSd->getArgName(i);
-
- // Process args
- Init *Result = EvaluateOperation(RHSo, LHS, Arg, Type,
- CurRec, CurMultiClass);
- if (Result != 0) {
- Arg = Result;
- }
-
- // TODO: Process arg names
- args.push_back(std::make_pair(Arg, ArgName));
- }
-
- return new DagInit(Val, "", args);
- }
- if (MHSl) {
- std::vector<Init *> NewOperands;
- std::vector<Init *> NewList(MHSl->begin(), MHSl->end());
-
- for (ListInit::iterator li = NewList.begin(),
- liend = NewList.end();
- li != liend;
- ++li) {
- Init *Item = *li;
- NewOperands.clear();
- for(int i = 0; i < RHSo->getNumOperands(); ++i) {
- // First, replace the foreach variable with the list item
- if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
- NewOperands.push_back(Item);
- } else {
- NewOperands.push_back(RHSo->getOperand(i));
- }
- }
-
- // Now run the operator and use its result as the new list item
- OpInit *NewOp = RHSo->clone(NewOperands);
- Init *NewItem = NewOp->Fold(CurRec, CurMultiClass);
- if (NewItem != NewOp) {
- *li = NewItem;
- delete NewOp;
- }
- }
- return new ListInit(NewList, MHSl->getType());
- }
- }
- return 0;
-}
-
-Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
- switch (getOpcode()) {
- default: assert(0 && "Unknown binop");
- case SUBST: {
- DefInit *LHSd = dynamic_cast<DefInit*>(LHS);
- VarInit *LHSv = dynamic_cast<VarInit*>(LHS);
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
-
- DefInit *MHSd = dynamic_cast<DefInit*>(MHS);
- VarInit *MHSv = dynamic_cast<VarInit*>(MHS);
- StringInit *MHSs = dynamic_cast<StringInit*>(MHS);
-
- DefInit *RHSd = dynamic_cast<DefInit*>(RHS);
- VarInit *RHSv = dynamic_cast<VarInit*>(RHS);
- StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
-
- if ((LHSd && MHSd && RHSd)
- || (LHSv && MHSv && RHSv)
- || (LHSs && MHSs && RHSs)) {
- if (RHSd) {
- Record *Val = RHSd->getDef();
- if (LHSd->getAsString() == RHSd->getAsString()) {
- Val = MHSd->getDef();
- }
- return new DefInit(Val);
- }
- if (RHSv) {
- std::string Val = RHSv->getName();
- if (LHSv->getAsString() == RHSv->getAsString()) {
- Val = MHSv->getName();
- }
- return new VarInit(Val, getType());
- }
- if (RHSs) {
- std::string Val = RHSs->getValue();
-
- std::string::size_type found;
- std::string::size_type idx = 0;
- do {
- found = Val.find(LHSs->getValue(), idx);
- if (found != std::string::npos) {
- Val.replace(found, LHSs->getValue().size(), MHSs->getValue());
- }
- idx = found + MHSs->getValue().size();
- } while (found != std::string::npos);
-
- return new StringInit(Val);
- }
- }
- break;
- }
-
- case FOREACH: {
- Init *Result = ForeachHelper(LHS, MHS, RHS, getType(),
- CurRec, CurMultiClass);
- if (Result != 0) {
- return Result;
- }
- break;
- }
-
- case IF: {
- IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
- if (Init *I = LHS->convertInitializerTo(new IntRecTy()))
- LHSi = dynamic_cast<IntInit*>(I);
- if (LHSi) {
- if (LHSi->getValue()) {
- return MHS;
- } else {
- return RHS;
- }
- }
- break;
- }
- }
-
- return this;
-}
-
-Init *TernOpInit::resolveReferences(Record &R, const RecordVal *RV) {
- Init *lhs = LHS->resolveReferences(R, RV);
-
- if (Opc == IF && lhs != LHS) {
- IntInit *Value = dynamic_cast<IntInit*>(lhs);
- if (Init *I = lhs->convertInitializerTo(new IntRecTy()))
- Value = dynamic_cast<IntInit*>(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);
- } else {
- Init *rhs = RHS->resolveReferences(R, RV);
- return (new TernOpInit(getOpcode(), lhs, MHS,
- rhs, getType()))->Fold(&R, 0);
- }
- }
- }
-
- Init *mhs = MHS->resolveReferences(R, 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 Fold(&R, 0);
-}
-
-std::string TernOpInit::getAsString() const {
- std::string Result;
- switch (Opc) {
- case SUBST: Result = "!subst"; break;
- case FOREACH: Result = "!foreach"; break;
- case IF: Result = "!if"; break;
- }
- return Result + "(" + LHS->getAsString() + ", " + MHS->getAsString() + ", "
- + RHS->getAsString() + ")";
-}
-
-RecTy *TypedInit::getFieldType(const std::string &FieldName) const {
- RecordRecTy *RecordType = dynamic_cast<RecordRecTy *>(getType());
- if (RecordType) {
- RecordVal *Field = RecordType->getRecord()->getValue(FieldName);
- if (Field) {
- return Field->getType();
- }
- }
- return 0;
-}
-
-Init *TypedInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) {
- BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType());
- if (T == 0) return 0; // Cannot subscript a non-bits variable.
- unsigned NumBits = T->getNumBits();
-
- BitsInit *BI = new BitsInit(Bits.size());
- for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
- if (Bits[i] >= NumBits) {
- delete BI;
- return 0;
- }
- BI->setBit(i, new VarBitInit(this, Bits[i]));
- }
- return BI;
-}
-
-Init *TypedInit::convertInitListSlice(const std::vector<unsigned> &Elements) {
- ListRecTy *T = dynamic_cast<ListRecTy*>(getType());
- if (T == 0) return 0; // Cannot subscript a non-list variable.
-
- if (Elements.size() == 1)
- return new VarListElementInit(this, Elements[0]);
-
- std::vector<Init*> 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);
-}
-
-
-Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV,
- unsigned Bit) {
- if (R.isTemplateArg(getName())) return 0;
- if (IRV && IRV->getName() != getName()) return 0;
-
- RecordVal *RV = R.getValue(getName());
- assert(RV && "Reference to a non-existent variable?");
- assert(dynamic_cast<BitsInit*>(RV->getValue()));
- BitsInit *BI = (BitsInit*)RV->getValue();
-
- assert(Bit < BI->getNumBits() && "Bit reference out of range!");
- Init *B = BI->getBit(Bit);
-
- // If the bit is set to some value, or if we are resolving a reference to a
- // specific variable and that variable is explicitly unset, then replace the
- // VarBitInit with it.
- if (IRV || !dynamic_cast<UnsetInit*>(B))
- return B;
- return 0;
-}
-
-Init *VarInit::resolveListElementReference(Record &R, const RecordVal *IRV,
- unsigned Elt) {
- if (R.isTemplateArg(getName())) return 0;
- if (IRV && IRV->getName() != getName()) return 0;
-
- RecordVal *RV = R.getValue(getName());
- assert(RV && "Reference to a non-existent variable?");
- ListInit *LI = dynamic_cast<ListInit*>(RV->getValue());
- if (!LI) {
- VarInit *VI = dynamic_cast<VarInit*>(RV->getValue());
- assert(VI && "Invalid list element!");
- return new VarListElementInit(VI, Elt);
- }
-
- if (Elt >= LI->getSize())
- return 0; // Out of range reference.
- Init *E = LI->getElement(Elt);
- // If the element is set to some value, or if we are resolving a reference
- // to a specific variable and that variable is explicitly unset, then
- // replace the VarListElementInit with it.
- if (IRV || !dynamic_cast<UnsetInit*>(E))
- return E;
- return 0;
-}
-
-
-RecTy *VarInit::getFieldType(const std::string &FieldName) const {
- if (RecordRecTy *RTy = dynamic_cast<RecordRecTy*>(getType()))
- if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName))
- return RV->getType();
- return 0;
-}
-
-Init *VarInit::getFieldInit(Record &R, const RecordVal *RV,
- const std::string &FieldName) const {
- if (dynamic_cast<RecordRecTy*>(getType()))
- if (const RecordVal *Val = R.getValue(VarName)) {
- if (RV != Val && (RV || dynamic_cast<UnsetInit*>(Val->getValue())))
- return 0;
- Init *TheInit = Val->getValue();
- assert(TheInit != this && "Infinite loop detected!");
- if (Init *I = TheInit->getFieldInit(R, RV, FieldName))
- return I;
- else
- return 0;
- }
- return 0;
-}
-
-/// resolveReferences - This method is used by classes that refer to other
-/// variables which may not be defined at the time the expression is formed.
-/// 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) {
- if (RecordVal *Val = R.getValue(VarName))
- if (RV == Val || (RV == 0 && !dynamic_cast<UnsetInit*>(Val->getValue())))
- return Val->getValue();
- return this;
-}
-
-std::string VarBitInit::getAsString() const {
- return TI->getAsString() + "{" + utostr(Bit) + "}";
-}
-
-Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) {
- if (Init *I = getVariable()->resolveBitReference(R, RV, getBitNum()))
- return I;
- return this;
-}
-
-std::string VarListElementInit::getAsString() const {
- return TI->getAsString() + "[" + utostr(Element) + "]";
-}
-
-Init *VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) {
- if (Init *I = getVariable()->resolveListElementReference(R, RV,
- getElementNum()))
- return I;
- return this;
-}
-
-Init *VarListElementInit::resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit) {
- // 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];
- return 0;
-}
-
-RecTy *DefInit::getFieldType(const std::string &FieldName) const {
- if (const RecordVal *RV = Def->getValue(FieldName))
- return RV->getType();
- return 0;
-}
-
-Init *DefInit::getFieldInit(Record &R, const RecordVal *RV,
- const std::string &FieldName) const {
- return Def->getValue(FieldName)->getValue();
-}
-
-
-std::string DefInit::getAsString() const {
- return Def->getName();
-}
-
-Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit) {
- if (Init *BitsVal = Rec->getFieldInit(R, RV, FieldName))
- if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) {
- assert(Bit < BI->getNumBits() && "Bit reference out of range!");
- Init *B = BI->getBit(Bit);
-
- if (dynamic_cast<BitInit*>(B)) // If the bit is set.
- return B; // Replace the VarBitInit with it.
- }
- return 0;
-}
-
-Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) {
- if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName))
- if (ListInit *LI = dynamic_cast<ListInit*>(ListVal)) {
- if (Elt >= LI->getSize()) return 0;
- Init *E = LI->getElement(Elt);
-
- // If the element is set to some value, or if we are resolving a
- // reference to a specific variable and that variable is explicitly
- // unset, then replace the VarListElementInit with it.
- if (RV || !dynamic_cast<UnsetInit*>(E))
- return E;
- }
- return 0;
-}
-
-Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) {
- 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;
- }
-
- if (NewRec != Rec) {
- return new FieldInit(NewRec, FieldName);
- }
- return this;
-}
-
-Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) {
- std::vector<Init*> NewArgs;
- for (unsigned i = 0, e = Args.size(); i != e; ++i)
- NewArgs.push_back(Args[i]->resolveReferences(R, RV));
-
- Init *Op = Val->resolveReferences(R, RV);
-
- if (Args != NewArgs || Op != Val)
- return new DagInit(Op, ValName, NewArgs, ArgNames);
-
- return this;
-}
-
-
-std::string DagInit::getAsString() const {
- std::string Result = "(" + Val->getAsString();
- if (!ValName.empty())
- Result += ":" + ValName;
- if (Args.size()) {
- Result += " " + Args[0]->getAsString();
- if (!ArgNames[0].empty()) Result += ":$" + ArgNames[0];
- for (unsigned i = 1, e = Args.size(); i != e; ++i) {
- Result += ", " + Args[i]->getAsString();
- if (!ArgNames[i].empty()) Result += ":$" + ArgNames[i];
- }
- }
- return Result + ")";
-}
-
-
-//===----------------------------------------------------------------------===//
-// Other implementations
-//===----------------------------------------------------------------------===//
-
-RecordVal::RecordVal(const std::string &N, RecTy *T, unsigned P)
- : Name(N), Ty(T), Prefix(P) {
- Value = Ty->convertValue(new UnsetInit());
- assert(Value && "Cannot create unset value for current type!");
-}
-
-void RecordVal::dump() const { errs() << *this; }
-
-void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
- if (getPrefix()) OS << "field ";
- OS << *getType() << " " << getName();
-
- if (getValue())
- OS << " = " << *getValue();
-
- if (PrintSem) OS << ";\n";
-}
-
-unsigned Record::LastID = 0;
-
-void Record::setName(const std::string &Name) {
- if (TrackedRecords.getDef(getName()) == this) {
- TrackedRecords.removeDef(getName());
- this->Name = Name;
- TrackedRecords.addDef(this);
- } else {
- TrackedRecords.removeClass(getName());
- this->Name = Name;
- TrackedRecords.addClass(this);
- }
-}
-
-/// resolveReferencesTo - If anything in this record refers to RV, replace the
-/// reference to RV with the RHS of RV. If RV is null, we resolve all possible
-/// references.
-void Record::resolveReferencesTo(const RecordVal *RV) {
- for (unsigned i = 0, e = Values.size(); i != e; ++i) {
- if (Init *V = Values[i].getValue())
- Values[i].setValue(V->resolveReferences(*this, RV));
- }
-}
-
-void Record::dump() const { errs() << *this; }
-
-raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) {
- OS << R.getName();
-
- const std::vector<std::string> &TArgs = R.getTemplateArgs();
- if (!TArgs.empty()) {
- OS << "<";
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- if (i) OS << ", ";
- const RecordVal *RV = R.getValue(TArgs[i]);
- assert(RV && "Template argument record not found??");
- RV->print(OS, false);
- }
- OS << ">";
- }
-
- OS << " {";
- const std::vector<Record*> &SC = R.getSuperClasses();
- if (!SC.empty()) {
- OS << "\t//";
- for (unsigned i = 0, e = SC.size(); i != e; ++i)
- OS << " " << SC[i]->getName();
- }
- OS << "\n";
-
- const std::vector<RecordVal> &Vals = R.getValues();
- for (unsigned i = 0, e = Vals.size(); i != e; ++i)
- if (Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
- OS << Vals[i];
- for (unsigned i = 0, e = Vals.size(); i != e; ++i)
- if (!Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
- OS << Vals[i];
-
- return OS << "}\n";
-}
-
-/// getValueInit - Return the initializer for a value with the specified name,
-/// or throw an exception if the field does not exist.
-///
-Init *Record::getValueInit(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
- return R->getValue();
-}
-
-
-/// getValueAsString - This method looks up the specified field and returns its
-/// value as a string, throwing an exception if the field does not exist or if
-/// the value is not a string.
-///
-std::string Record::getValueAsString(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (const StringInit *SI = dynamic_cast<const StringInit*>(R->getValue()))
- return SI->getValue();
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a string initializer!";
-}
-
-/// getValueAsBitsInit - This method looks up the specified field and returns
-/// its value as a BitsInit, throwing an exception if the field does not exist
-/// or if the value is not the right type.
-///
-BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (BitsInit *BI = dynamic_cast<BitsInit*>(R->getValue()))
- return BI;
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a BitsInit initializer!";
-}
-
-/// getValueAsListInit - This method looks up the specified field and returns
-/// its value as a ListInit, throwing an exception if the field does not exist
-/// or if the value is not the right type.
-///
-ListInit *Record::getValueAsListInit(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (ListInit *LI = dynamic_cast<ListInit*>(R->getValue()))
- return LI;
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a list initializer!";
-}
-
-/// getValueAsListOfDefs - This method looks up the specified field and returns
-/// its value as a vector of records, throwing an exception if the field does
-/// not exist or if the value is not the right type.
-///
-std::vector<Record*>
-Record::getValueAsListOfDefs(StringRef FieldName) const {
- ListInit *List = getValueAsListInit(FieldName);
- std::vector<Record*> Defs;
- for (unsigned i = 0; i < List->getSize(); i++) {
- if (DefInit *DI = dynamic_cast<DefInit*>(List->getElement(i))) {
- Defs.push_back(DI->getDef());
- } else {
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' list is not entirely DefInit!";
- }
- }
- return Defs;
-}
-
-/// getValueAsInt - This method looks up the specified field and returns its
-/// value as an int64_t, throwing an exception if the field does not exist or if
-/// the value is not the right type.
-///
-int64_t Record::getValueAsInt(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (IntInit *II = dynamic_cast<IntInit*>(R->getValue()))
- return II->getValue();
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have an int initializer!";
-}
-
-/// getValueAsListOfInts - This method looks up the specified field and returns
-/// its value as a vector of integers, throwing an exception if the field does
-/// not exist or if the value is not the right type.
-///
-std::vector<int64_t>
-Record::getValueAsListOfInts(StringRef FieldName) const {
- ListInit *List = getValueAsListInit(FieldName);
- std::vector<int64_t> Ints;
- for (unsigned i = 0; i < List->getSize(); i++) {
- if (IntInit *II = dynamic_cast<IntInit*>(List->getElement(i))) {
- Ints.push_back(II->getValue());
- } else {
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a list of ints initializer!";
- }
- }
- return Ints;
-}
-
-/// getValueAsListOfStrings - This method looks up the specified field and
-/// returns its value as a vector of strings, throwing an exception if the
-/// field does not exist or if the value is not the right type.
-///
-std::vector<std::string>
-Record::getValueAsListOfStrings(StringRef FieldName) const {
- ListInit *List = getValueAsListInit(FieldName);
- std::vector<std::string> Strings;
- for (unsigned i = 0; i < List->getSize(); i++) {
- if (StringInit *II = dynamic_cast<StringInit*>(List->getElement(i))) {
- Strings.push_back(II->getValue());
- } else {
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a list of strings initializer!";
- }
- }
- return Strings;
-}
-
-/// getValueAsDef - This method looks up the specified field and returns its
-/// value as a Record, throwing an exception if the field does not exist or if
-/// the value is not the right type.
-///
-Record *Record::getValueAsDef(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (DefInit *DI = dynamic_cast<DefInit*>(R->getValue()))
- return DI->getDef();
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a def initializer!";
-}
-
-/// getValueAsBit - This method looks up the specified field and returns its
-/// value as a bit, throwing an exception if the field does not exist or if
-/// the value is not the right type.
-///
-bool Record::getValueAsBit(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (BitInit *BI = dynamic_cast<BitInit*>(R->getValue()))
- return BI->getValue();
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a bit initializer!";
-}
-
-/// getValueAsDag - This method looks up the specified field and returns its
-/// value as an Dag, throwing an exception if the field does not exist or if
-/// the value is not the right type.
-///
-DagInit *Record::getValueAsDag(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (DagInit *DI = dynamic_cast<DagInit*>(R->getValue()))
- return DI;
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a dag initializer!";
-}
-
-std::string Record::getValueAsCode(StringRef FieldName) const {
- const RecordVal *R = getValue(FieldName);
- if (R == 0 || R->getValue() == 0)
- throw "Record `" + getName() + "' does not have a field named `" +
- FieldName.str() + "'!\n";
-
- if (const CodeInit *CI = dynamic_cast<const CodeInit*>(R->getValue()))
- return CI->getValue();
- throw "Record `" + getName() + "', field `" + FieldName.str() +
- "' does not have a code initializer!";
-}
-
-
-void MultiClass::dump() const {
- errs() << "Record:\n";
- Rec.dump();
-
- errs() << "Defs:\n";
- for (RecordVector::const_iterator r = DefPrototypes.begin(),
- rend = DefPrototypes.end();
- r != rend;
- ++r) {
- (*r)->dump();
- }
-}
-
-
-void RecordKeeper::dump() const { errs() << *this; }
-
-raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) {
- OS << "------------- Classes -----------------\n";
- const std::map<std::string, Record*> &Classes = RK.getClasses();
- for (std::map<std::string, Record*>::const_iterator I = Classes.begin(),
- E = Classes.end(); I != E; ++I)
- OS << "class " << *I->second;
-
- OS << "------------- Defs -----------------\n";
- const std::map<std::string, Record*> &Defs = RK.getDefs();
- for (std::map<std::string, Record*>::const_iterator I = Defs.begin(),
- E = Defs.end(); I != E; ++I)
- OS << "def " << *I->second;
- return OS;
-}
-
-
-/// getAllDerivedDefinitions - This method returns all concrete definitions
-/// that derive from the specified class name. If a class with the specified
-/// name does not exist, an error is printed and true is returned.
-std::vector<Record*>
-RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const {
- Record *Class = getClass(ClassName);
- if (!Class)
- throw "ERROR: Couldn't find the `" + ClassName + "' class!\n";
-
- std::vector<Record*> Defs;
- for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(),
- E = getDefs().end(); I != E; ++I)
- if (I->second->isSubClassOf(Class))
- Defs.push_back(I->second);
-
- return Defs;
-}
-
diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h
deleted file mode 100644
index 2f4080b..0000000
--- a/utils/TableGen/Record.h
+++ /dev/null
@@ -1,1500 +0,0 @@
-//===- Record.h - Classes to represent Table Records ------------*- 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 main TableGen data structures, including the TableGen
-// types, values, and high-level data structures.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef RECORD_H
-#define RECORD_H
-
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/raw_ostream.h"
-#include <map>
-
-namespace llvm {
-class raw_ostream;
-
-// RecTy subclasses.
-class BitRecTy;
-class BitsRecTy;
-class IntRecTy;
-class StringRecTy;
-class ListRecTy;
-class CodeRecTy;
-class DagRecTy;
-class RecordRecTy;
-
-// Init subclasses.
-class Init;
-class UnsetInit;
-class BitInit;
-class BitsInit;
-class IntInit;
-class StringInit;
-class CodeInit;
-class ListInit;
-class UnOpInit;
-class BinOpInit;
-class TernOpInit;
-class DefInit;
-class DagInit;
-class TypedInit;
-class VarInit;
-class FieldInit;
-class VarBitInit;
-class VarListElementInit;
-
-// Other classes.
-class Record;
-class RecordVal;
-struct MultiClass;
-class RecordKeeper;
-
-//===----------------------------------------------------------------------===//
-// Type Classes
-//===----------------------------------------------------------------------===//
-
-struct RecTy {
- virtual ~RecTy() {}
-
- virtual std::string getAsString() const = 0;
- void print(raw_ostream &OS) const { OS << getAsString(); }
- void dump() const;
-
- /// typeIsConvertibleTo - Return true if all values of 'this' type can be
- /// converted to the specified type.
- virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0;
-
-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; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) {
- return convertValue((TypedInit*)UI);
- }
- virtual Init *convertValue( BinOpInit *UI) {
- return convertValue((TypedInit*)UI);
- }
- virtual Init *convertValue( TernOpInit *UI) {
- return convertValue((TypedInit*)UI);
- }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( TypedInit *TI) { return 0; }
- virtual Init *convertValue( VarInit *VI) {
- return convertValue((TypedInit*)VI);
- }
- virtual Init *convertValue( FieldInit *FI) {
- return convertValue((TypedInit*)FI);
- }
-
-public: // These methods should only be called by subclasses of RecTy.
- // baseClassOf - These virtual methods should be overloaded to return true iff
- // all values of type 'RHS' can be converted to the 'this' type.
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-};
-
-inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
- Ty.print(OS);
- return OS;
-}
-
-
-/// BitRecTy - 'bit' - Represent a single bit
-///
-class BitRecTy : public RecTy {
-public:
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return (Init*)BI; }
- virtual Init *convertValue( BitsInit *BI);
- virtual Init *convertValue( IntInit *II);
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return (Init*)VB; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const { return "bit"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
- virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const;
- virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-
-};
-
-
-// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
-/// BitsRecTy - 'bits&lt;n&gt;' - Represent a fixed number of bits
-///
-class BitsRecTy : public RecTy {
- unsigned Size;
-public:
- explicit BitsRecTy(unsigned Sz) : Size(Sz) {}
-
- unsigned getNumBits() const { return Size; }
-
- virtual Init *convertValue( UnsetInit *UI);
- virtual Init *convertValue( BitInit *UI);
- virtual Init *convertValue( BitsInit *BI);
- virtual Init *convertValue( IntInit *II);
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const;
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
- virtual bool baseClassOf(const BitRecTy *RHS) const { return Size == 1; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const {
- return RHS->Size == Size;
- }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-
-};
-
-
-/// IntRecTy - 'int' - Represent an integer value of no particular size
-///
-class IntRecTy : public RecTy {
-public:
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI);
- virtual Init *convertValue( BitsInit *BI);
- virtual Init *convertValue( IntInit *II) { return (Init*)II; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const { return "int"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
-
- virtual bool baseClassOf(const BitRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-
-};
-
-/// StringRecTy - 'string' - Represent an string value
-///
-class StringRecTy : public RecTy {
-public:
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return 0; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return (Init*)SI; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( UnOpInit *BO);
- virtual Init *convertValue( BinOpInit *BO);
- virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
-
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const { return "string"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
-
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-};
-
-// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of
-// the specified type.
-/// ListRecTy - 'list&lt;Ty&gt;' - Represent a list of values, all of which must
-/// be of the specified type.
-///
-class ListRecTy : public RecTy {
- RecTy *Ty;
-public:
- explicit ListRecTy(RecTy *T) : Ty(T) {}
-
- RecTy *getElementType() const { return Ty; }
-
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return 0; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI);
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const;
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
-
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const {
- return RHS->getElementType()->typeIsConvertibleTo(Ty);
- }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-};
-
-/// CodeRecTy - 'code' - Represent an code fragment, function or method.
-///
-class CodeRecTy : public RecTy {
-public:
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return 0; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return (Init*)CI; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const { return "code"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-};
-
-/// DagRecTy - 'dag' - Represent a dag fragment
-///
-class DagRecTy : public RecTy {
-public:
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return 0; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( DefInit *DI) { return 0; }
- virtual Init *convertValue( UnOpInit *BO);
- virtual Init *convertValue( BinOpInit *BO);
- virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
- virtual Init *convertValue( DagInit *CI) { return (Init*)CI; }
- virtual Init *convertValue( TypedInit *TI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const { return "dag"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
-
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return true; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
-};
-
-
-/// RecordRecTy - '[classname]' - Represent an instance of a class, such as:
-/// (R32 X = EAX).
-///
-class RecordRecTy : public RecTy {
- Record *Rec;
-public:
- explicit RecordRecTy(Record *R) : Rec(R) {}
-
- Record *getRecord() const { return Rec; }
-
- virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
- virtual Init *convertValue( BitInit *BI) { return 0; }
- virtual Init *convertValue( BitsInit *BI) { return 0; }
- virtual Init *convertValue( IntInit *II) { return 0; }
- virtual Init *convertValue(StringInit *SI) { return 0; }
- virtual Init *convertValue( ListInit *LI) { return 0; }
- virtual Init *convertValue( CodeInit *CI) { return 0; }
- virtual Init *convertValue(VarBitInit *VB) { return 0; }
- virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
- virtual Init *convertValue( DefInit *DI);
- virtual Init *convertValue( DagInit *DI) { return 0; }
- virtual Init *convertValue( TypedInit *VI);
- virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
- virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
-
- std::string getAsString() const;
-
- bool typeIsConvertibleTo(const RecTy *RHS) const {
- return RHS->baseClassOf(this);
- }
- virtual bool baseClassOf(const BitRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const IntRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
- virtual bool baseClassOf(const RecordRecTy *RHS) const;
-};
-
-/// resolveTypes - Find a common type that T1 and T2 convert to.
-/// Return 0 if no such type exists.
-///
-RecTy *resolveTypes(RecTy *T1, RecTy *T2);
-
-//===----------------------------------------------------------------------===//
-// Initializer Classes
-//===----------------------------------------------------------------------===//
-
-class Init {
-public:
- virtual ~Init() {}
-
- /// isComplete - This virtual method should be overridden by values that may
- /// not be completely specified yet.
- virtual bool isComplete() const { return true; }
-
- /// print - Print out this value.
- void print(raw_ostream &OS) const { OS << getAsString(); }
-
- /// getAsString - Convert this value to a string form.
- virtual std::string getAsString() const = 0;
-
- /// dump - Debugging method that may be called through a debugger, just
- /// invokes print on stderr.
- void dump() const;
-
- /// convertInitializerTo - This virtual function is a simple call-back
- /// function that should be overridden to call the appropriate
- /// RecTy::convertValue method.
- ///
- virtual Init *convertInitializerTo(RecTy *Ty) = 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<unsigned> &Bits) {
- return 0;
- }
-
- /// convertInitListSlice - This method is used to implement the list slice
- /// selection operator. Given an initializer, it selects the specified list
- /// 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<unsigned> &Elements) {
- return 0;
- }
-
- /// getFieldType - This method is used to implement the FieldInit class.
- /// Implementors of this method should return the type of the named field if
- /// they are of record type.
- ///
- virtual RecTy *getFieldType(const std::string &FieldName) const { return 0; }
-
- /// getFieldInit - This method complements getFieldType to return the
- /// initializer for the specified field. If getFieldType returns non-null
- /// this method should return non-null, otherwise it returns null.
- ///
- virtual Init *getFieldInit(Record &R, const RecordVal *RV,
- const std::string &FieldName) const {
- return 0;
- }
-
- /// resolveReferences - This method is used by classes that refer to other
- /// variables which may not be defined at the time the expression is formed.
- /// 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;
- }
-};
-
-inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
- I.print(OS); return OS;
-}
-
-/// TypedInit - This is the common super-class of types that have a specific,
-/// explicit, type.
-///
-class TypedInit : public Init {
- RecTy *Ty;
-public:
- explicit TypedInit(RecTy *T) : Ty(T) {}
-
- RecTy *getType() const { return Ty; }
-
- virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
- virtual Init *convertInitListSlice(const std::vector<unsigned> &Elements);
-
- /// getFieldType - This method is used to implement the FieldInit class.
- /// Implementors of this method should return the type of the named field if
- /// they are of record type.
- ///
- virtual RecTy *getFieldType(const std::string &FieldName) const;
-
- /// 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) = 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;
-};
-
-
-/// UnsetInit - ? - Represents an uninitialized value
-///
-class UnsetInit : public Init {
-public:
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual bool isComplete() const { return false; }
- virtual std::string getAsString() const { return "?"; }
-};
-
-
-/// BitInit - true/false - Represent a concrete initializer for a bit.
-///
-class BitInit : public Init {
- bool Value;
-public:
- explicit BitInit(bool V) : Value(V) {}
-
- bool getValue() const { return Value; }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual std::string getAsString() const { return Value ? "1" : "0"; }
-};
-
-/// 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 {
- std::vector<Init*> Bits;
-public:
- explicit BitsInit(unsigned Size) : Bits(Size) {}
-
- unsigned getNumBits() const { return Bits.size(); }
-
- Init *getBit(unsigned Bit) const {
- 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 *convertInitializerBitRange(const std::vector<unsigned> &Bits);
-
- virtual bool isComplete() const {
- for (unsigned i = 0; i != getNumBits(); ++i)
- if (!getBit(i)->isComplete()) return false;
- return true;
- }
- bool allInComplete() const {
- for (unsigned i = 0; i != getNumBits(); ++i)
- if (getBit(i)->isComplete()) return false;
- return true;
- }
- virtual std::string getAsString() const;
-
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-};
-
-
-/// IntInit - 7 - Represent an initalization by a literal integer value.
-///
-class IntInit : public TypedInit {
- int64_t Value;
-public:
- explicit IntInit(int64_t V) : TypedInit(new IntRecTy), Value(V) {}
-
- int64_t getValue() const { return Value; }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
- virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
-
- virtual std::string getAsString() const;
-
- /// 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) {
- assert(0 && "Illegal bit reference off int");
- return 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) {
- assert(0 && "Illegal element reference off int");
- return 0;
- }
-};
-
-
-/// StringInit - "foo" - Represent an initialization by a string value.
-///
-class StringInit : public TypedInit {
- std::string Value;
-public:
- explicit StringInit(const std::string &V)
- : TypedInit(new StringRecTy), Value(V) {}
-
- const std::string &getValue() const { return Value; }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual std::string getAsString() 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) {
- assert(0 && "Illegal bit reference off string");
- return 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) {
- assert(0 && "Illegal element reference off string");
- return 0;
- }
-};
-
-/// CodeInit - "[{...}]" - Represent a code fragment.
-///
-class CodeInit : public Init {
- std::string Value;
-public:
- explicit CodeInit(const std::string &V) : Value(V) {}
-
- const std::string &getValue() const { return Value; }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual std::string getAsString() const { return "[{" + Value + "}]"; }
-};
-
-/// ListInit - [AL, AH, CL] - Represent a list of defs
-///
-class ListInit : public TypedInit {
- std::vector<Init*> Values;
-public:
- typedef std::vector<Init*>::iterator iterator;
- typedef std::vector<Init*>::const_iterator const_iterator;
-
- explicit ListInit(std::vector<Init*> &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) {}
-
- unsigned getSize() const { return Values.size(); }
- Init *getElement(unsigned i) const {
- assert(i < Values.size() && "List element index out of range!");
- return Values[i];
- }
-
- Record *getElementAsRecord(unsigned i) const;
-
- Init *convertInitListSlice(const std::vector<unsigned> &Elements);
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- /// resolveReferences - This method is used by classes that refer to other
- /// variables which may not be defined at the time they expression is formed.
- /// 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 std::string getAsString() const;
-
- inline iterator begin() { return Values.begin(); }
- 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(); }
- inline bool empty() const { return Values.empty(); }
-
- /// 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) {
- assert(0 && "Illegal bit reference off list");
- return 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);
-};
-
-
-/// OpInit - Base class for operators
-///
-class OpInit : public TypedInit {
-public:
- OpInit(RecTy *Type) : TypedInit(Type) {}
-
- // Clone - Clone this operator, replacing arguments with the new list
- virtual OpInit *clone(std::vector<Init *> &Operands) = 0;
-
- virtual int getNumOperands() const = 0;
- virtual Init *getOperand(int i) = 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 *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit);
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt);
-};
-
-
-/// UnOpInit - !op (X) - Transform an init.
-///
-class UnOpInit : public OpInit {
-public:
- enum UnaryOp { CAST, HEAD, TAIL, EMPTY };
-private:
- UnaryOp Opc;
- Init *LHS;
-public:
- UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type) :
- OpInit(Type), Opc(opc), LHS(lhs) {
- }
-
- // Clone - Clone this operator, replacing arguments with the new list
- virtual OpInit *clone(std::vector<Init *> &Operands) {
- assert(Operands.size() == 1 &&
- "Wrong number of operands for unary operation");
- return new UnOpInit(getOpcode(), *Operands.begin(), getType());
- }
-
- int getNumOperands() const { return 1; }
- Init *getOperand(int i) {
- assert(i == 0 && "Invalid operand id for unary operator");
- return getOperand();
- }
-
- UnaryOp getOpcode() const { return Opc; }
- Init *getOperand() const { return LHS; }
-
- // Fold - If possible, fold this to a simpler init. Return this if not
- // possible to fold.
- Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
-
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-
- virtual std::string getAsString() const;
-};
-
-/// BinOpInit - !op (X, Y) - Combine two inits.
-///
-class BinOpInit : public OpInit {
-public:
- enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, EQ };
-private:
- BinaryOp Opc;
- Init *LHS, *RHS;
-public:
- BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
- OpInit(Type), Opc(opc), LHS(lhs), RHS(rhs) {
- }
-
- // Clone - Clone this operator, replacing arguments with the new list
- virtual OpInit *clone(std::vector<Init *> &Operands) {
- assert(Operands.size() == 2 &&
- "Wrong number of operands for binary operation");
- return new BinOpInit(getOpcode(), Operands[0], Operands[1], getType());
- }
-
- int getNumOperands() const { return 2; }
- Init *getOperand(int i) {
- assert((i == 0 || i == 1) && "Invalid operand id for binary operator");
- if (i == 0) {
- return getLHS();
- } else {
- return getRHS();
- }
- }
-
- BinaryOp getOpcode() const { return Opc; }
- Init *getLHS() const { return LHS; }
- Init *getRHS() const { return RHS; }
-
- // Fold - If possible, fold this to a simpler init. Return this if not
- // possible to fold.
- Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
-
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-
- virtual std::string getAsString() const;
-};
-
-/// TernOpInit - !op (X, Y, Z) - Combine two inits.
-///
-class TernOpInit : public OpInit {
-public:
- enum TernaryOp { SUBST, FOREACH, IF };
-private:
- TernaryOp Opc;
- Init *LHS, *MHS, *RHS;
-public:
- TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs, RecTy *Type) :
- OpInit(Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {
- }
-
- // Clone - Clone this operator, replacing arguments with the new list
- virtual OpInit *clone(std::vector<Init *> &Operands) {
- assert(Operands.size() == 3 &&
- "Wrong number of operands for ternary operation");
- return new TernOpInit(getOpcode(), Operands[0], Operands[1], Operands[2],
- getType());
- }
-
- int getNumOperands() const { return 3; }
- Init *getOperand(int i) {
- assert((i == 0 || i == 1 || i == 2) &&
- "Invalid operand id for ternary operator");
- if (i == 0) {
- return getLHS();
- } else if (i == 1) {
- return getMHS();
- } else {
- return getRHS();
- }
- }
-
- TernaryOp getOpcode() const { return Opc; }
- Init *getLHS() const { return LHS; }
- Init *getMHS() const { return MHS; }
- Init *getRHS() const { return RHS; }
-
- // Fold - If possible, fold this to a simpler init. Return this if not
- // possible to fold.
- Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
-
- virtual bool isComplete() const { return false; }
-
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-
- virtual std::string getAsString() const;
-};
-
-
-/// VarInit - 'Opcode' - Represent a reference to an entire variable object.
-///
-class VarInit : public TypedInit {
- std::string VarName;
-public:
- explicit VarInit(const std::string &VN, RecTy *T)
- : TypedInit(T), VarName(VN) {}
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- const std::string &getName() const { return VarName; }
-
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit);
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt);
-
- virtual RecTy *getFieldType(const std::string &FieldName) const;
- virtual Init *getFieldInit(Record &R, const RecordVal *RV,
- const std::string &FieldName) const;
-
- /// resolveReferences - This method is used by classes that refer to other
- /// variables which may not be defined at the time they expression is formed.
- /// 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 std::string getAsString() const { return VarName; }
-};
-
-
-/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field.
-///
-class VarBitInit : public Init {
- TypedInit *TI;
- unsigned Bit;
-public:
- VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) {
- assert(T->getType() && dynamic_cast<BitsRecTy*>(T->getType()) &&
- ((BitsRecTy*)T->getType())->getNumBits() > B &&
- "Illegal VarBitInit expression!");
- }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- TypedInit *getVariable() const { return TI; }
- unsigned getBitNum() const { return Bit; }
-
- virtual std::string getAsString() const;
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-};
-
-/// VarListElementInit - List[4] - Represent access to one element of a var or
-/// field.
-class VarListElementInit : public TypedInit {
- TypedInit *TI;
- unsigned Element;
-public:
- VarListElementInit(TypedInit *T, unsigned E)
- : TypedInit(dynamic_cast<ListRecTy*>(T->getType())->getElementType()),
- TI(T), Element(E) {
- assert(T->getType() && dynamic_cast<ListRecTy*>(T->getType()) &&
- "Illegal VarBitInit expression!");
- }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- TypedInit *getVariable() const { return TI; }
- unsigned getElementNum() const { return Element; }
-
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit);
-
- /// 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 std::string getAsString() const;
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-};
-
-/// DefInit - AL - Represent a reference to a 'def' in the description
-///
-class DefInit : public TypedInit {
- Record *Def;
-public:
- explicit DefInit(Record *D) : TypedInit(new RecordRecTy(D)), Def(D) {}
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- Record *getDef() const { return Def; }
-
- //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
-
- virtual RecTy *getFieldType(const std::string &FieldName) const;
- virtual Init *getFieldInit(Record &R, const RecordVal *RV,
- const std::string &FieldName) const;
-
- virtual std::string getAsString() const;
-
- /// 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) {
- assert(0 && "Illegal bit reference off def");
- return 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) {
- assert(0 && "Illegal element reference off def");
- return 0;
- }
-};
-
-
-/// FieldInit - X.Y - Represent a reference to a subfield of a variable
-///
-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) {
- assert(getType() && "FieldInit with non-record type!");
- }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
- unsigned Bit);
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt);
-
- virtual Init *resolveReferences(Record &R, const RecordVal *RV);
-
- virtual std::string getAsString() const {
- return Rec->getAsString() + "." + FieldName;
- }
-};
-
-/// DagInit - (v a, b) - Represent a DAG tree value. DAG inits are required
-/// 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 {
- Init *Val;
- std::string ValName;
- std::vector<Init*> Args;
- std::vector<std::string> ArgNames;
-public:
- DagInit(Init *V, std::string VN,
- const std::vector<std::pair<Init*, std::string> > &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<Init*> &args,
- const std::vector<std::string> &argNames)
- : TypedInit(new DagRecTy), Val(V), ValName(VN), Args(args),
- ArgNames(argNames) { }
-
- virtual Init *convertInitializerTo(RecTy *Ty) {
- return Ty->convertValue(this);
- }
-
- Init *getOperator() const { return Val; }
-
- const std::string &getName() const { return ValName; }
-
- unsigned getNumArgs() const { return Args.size(); }
- Init *getArg(unsigned Num) const {
- assert(Num < Args.size() && "Arg number out of range!");
- return Args[Num];
- }
- const std::string &getArgName(unsigned Num) const {
- assert(Num < ArgNames.size() && "Arg number out of range!");
- 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 std::string getAsString() const;
-
- typedef std::vector<Init*>::iterator arg_iterator;
- typedef std::vector<Init*>::const_iterator const_arg_iterator;
- typedef std::vector<std::string>::iterator name_iterator;
- typedef std::vector<std::string>::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) {
- assert(0 && "Illegal bit reference off dag");
- return 0;
- }
-
- virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
- unsigned Elt) {
- assert(0 && "Illegal element reference off dag");
- return 0;
- }
-};
-
-//===----------------------------------------------------------------------===//
-// High-Level Classes
-//===----------------------------------------------------------------------===//
-
-class RecordVal {
- std::string Name;
- RecTy *Ty;
- unsigned Prefix;
- Init *Value;
-public:
- RecordVal(const std::string &N, RecTy *T, unsigned P);
-
- const std::string &getName() const { return Name; }
-
- unsigned getPrefix() const { return Prefix; }
- RecTy *getType() const { return Ty; }
- Init *getValue() const { return Value; }
-
- bool setValue(Init *V) {
- if (V) {
- Value = V->convertInitializerTo(Ty);
- return Value == 0;
- }
- Value = 0;
- return false;
- }
-
- void dump() const;
- void print(raw_ostream &OS, bool PrintSem = true) const;
-};
-
-inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) {
- RV.print(OS << " ");
- return OS;
-}
-
-class Record {
- static unsigned LastID;
-
- // Unique record ID.
- unsigned ID;
- std::string Name;
- SMLoc Loc;
- std::vector<std::string> TemplateArgs;
- std::vector<RecordVal> Values;
- std::vector<Record*> SuperClasses;
-
- // Tracks Record instances. Not owned by Record.
- RecordKeeper &TrackedRecords;
-
-public:
-
- // Constructs a record.
- explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) :
- ID(LastID++), Name(N), Loc(loc), TrackedRecords(records) {}
- ~Record() {}
-
-
- static unsigned getNewUID() { return LastID++; }
-
-
- unsigned getID() const { return ID; }
-
- const std::string &getName() const { return Name; }
- void setName(const std::string &Name); // Also updates RecordKeeper.
-
- SMLoc getLoc() const { return Loc; }
-
- const std::vector<std::string> &getTemplateArgs() const {
- return TemplateArgs;
- }
- const std::vector<RecordVal> &getValues() const { return Values; }
- const std::vector<Record*> &getSuperClasses() const { return SuperClasses; }
-
- bool isTemplateArg(StringRef Name) const {
- for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i)
- if (TemplateArgs[i] == Name) return true;
- return false;
- }
-
- const RecordVal *getValue(StringRef Name) const {
- for (unsigned i = 0, e = Values.size(); i != e; ++i)
- if (Values[i].getName() == Name) return &Values[i];
- return 0;
- }
- RecordVal *getValue(StringRef Name) {
- for (unsigned i = 0, e = Values.size(); i != e; ++i)
- if (Values[i].getName() == Name) return &Values[i];
- return 0;
- }
-
- void addTemplateArg(StringRef Name) {
- assert(!isTemplateArg(Name) && "Template arg already defined!");
- TemplateArgs.push_back(Name);
- }
-
- void addValue(const RecordVal &RV) {
- assert(getValue(RV.getName()) == 0 && "Value already added!");
- Values.push_back(RV);
- }
-
- void removeValue(StringRef Name) {
- for (unsigned i = 0, e = Values.size(); i != e; ++i)
- if (Values[i].getName() == Name) {
- Values.erase(Values.begin()+i);
- return;
- }
- assert(0 && "Cannot remove an entry that does not exist!");
- }
-
- bool isSubClassOf(const Record *R) const {
- for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
- if (SuperClasses[i] == R)
- return true;
- return false;
- }
-
- bool isSubClassOf(StringRef Name) const {
- for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
- if (SuperClasses[i]->getName() == Name)
- return true;
- return false;
- }
-
- void addSuperClass(Record *R) {
- assert(!isSubClassOf(R) && "Already subclassing record!");
- SuperClasses.push_back(R);
- }
-
- /// resolveReferences - If there are any field references that refer to fields
- /// that have been filled in, we can propagate the values now.
- ///
- void resolveReferences() { resolveReferencesTo(0); }
-
- /// resolveReferencesTo - If anything in this record refers to RV, replace the
- /// reference to RV with the RHS of RV. If RV is null, we resolve all
- /// possible references.
- void resolveReferencesTo(const RecordVal *RV);
-
- RecordKeeper &getRecords() const {
- return TrackedRecords;
- }
-
- void dump() const;
-
- //===--------------------------------------------------------------------===//
- // High-level methods useful to tablegen back-ends
- //
-
- /// getValueInit - Return the initializer for a value with the specified name,
- /// or throw an exception if the field does not exist.
- ///
- Init *getValueInit(StringRef FieldName) const;
-
- /// getValueAsString - This method looks up the specified field and returns
- /// its value as a string, throwing an exception if the field does not exist
- /// or if the value is not a string.
- ///
- std::string getValueAsString(StringRef FieldName) const;
-
- /// getValueAsBitsInit - This method looks up the specified field and returns
- /// its value as a BitsInit, throwing an exception if the field does not exist
- /// or if the value is not the right type.
- ///
- BitsInit *getValueAsBitsInit(StringRef FieldName) const;
-
- /// getValueAsListInit - This method looks up the specified field and returns
- /// its value as a ListInit, throwing an exception if the field does not exist
- /// or if the value is not the right type.
- ///
- ListInit *getValueAsListInit(StringRef FieldName) const;
-
- /// getValueAsListOfDefs - This method looks up the specified field and
- /// returns its value as a vector of records, throwing an exception if the
- /// field does not exist or if the value is not the right type.
- ///
- std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const;
-
- /// getValueAsListOfInts - This method looks up the specified field and
- /// returns its value as a vector of integers, throwing an exception if the
- /// field does not exist or if the value is not the right type.
- ///
- std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
-
- /// getValueAsListOfStrings - This method looks up the specified field and
- /// returns its value as a vector of strings, throwing an exception if the
- /// field does not exist or if the value is not the right type.
- ///
- std::vector<std::string> getValueAsListOfStrings(StringRef FieldName) const;
-
- /// getValueAsDef - This method looks up the specified field and returns its
- /// value as a Record, throwing an exception if the field does not exist or if
- /// the value is not the right type.
- ///
- Record *getValueAsDef(StringRef FieldName) const;
-
- /// getValueAsBit - This method looks up the specified field and returns its
- /// value as a bit, throwing an exception if the field does not exist or if
- /// the value is not the right type.
- ///
- bool getValueAsBit(StringRef FieldName) const;
-
- /// getValueAsInt - This method looks up the specified field and returns its
- /// value as an int64_t, throwing an exception if the field does not exist or
- /// if the value is not the right type.
- ///
- int64_t getValueAsInt(StringRef FieldName) const;
-
- /// getValueAsDag - This method looks up the specified field and returns its
- /// value as an Dag, throwing an exception if the field does not exist or if
- /// the value is not the right type.
- ///
- DagInit *getValueAsDag(StringRef FieldName) const;
-
- /// getValueAsCode - This method looks up the specified field and returns
- /// its value as the string data in a CodeInit, throwing an exception if the
- /// field does not exist or if the value is not a code object.
- ///
- std::string getValueAsCode(StringRef FieldName) const;
-};
-
-raw_ostream &operator<<(raw_ostream &OS, const Record &R);
-
-struct MultiClass {
- Record Rec; // Placeholder for template args and Name.
- typedef std::vector<Record*> RecordVector;
- RecordVector DefPrototypes;
-
- void dump() const;
-
- MultiClass(const std::string &Name, SMLoc Loc, RecordKeeper &Records) :
- Rec(Name, Loc, Records) {}
-};
-
-class RecordKeeper {
- std::map<std::string, Record*> Classes, Defs;
-public:
- ~RecordKeeper() {
- for (std::map<std::string, Record*>::iterator I = Classes.begin(),
- E = Classes.end(); I != E; ++I)
- delete I->second;
- for (std::map<std::string, Record*>::iterator I = Defs.begin(),
- E = Defs.end(); I != E; ++I)
- delete I->second;
- }
-
- const std::map<std::string, Record*> &getClasses() const { return Classes; }
- const std::map<std::string, Record*> &getDefs() const { return Defs; }
-
- Record *getClass(const std::string &Name) const {
- std::map<std::string, Record*>::const_iterator I = Classes.find(Name);
- return I == Classes.end() ? 0 : I->second;
- }
- Record *getDef(const std::string &Name) const {
- std::map<std::string, Record*>::const_iterator I = Defs.find(Name);
- return I == Defs.end() ? 0 : I->second;
- }
- void addClass(Record *R) {
- assert(getClass(R->getName()) == 0 && "Class already exists!");
- Classes.insert(std::make_pair(R->getName(), R));
- }
- void addDef(Record *R) {
- assert(getDef(R->getName()) == 0 && "Def already exists!");
- Defs.insert(std::make_pair(R->getName(), R));
- }
-
- /// removeClass - Remove, but do not delete, the specified record.
- ///
- void removeClass(const std::string &Name) {
- assert(Classes.count(Name) && "Class does not exist!");
- Classes.erase(Name);
- }
- /// removeDef - Remove, but do not delete, the specified record.
- ///
- void removeDef(const std::string &Name) {
- assert(Defs.count(Name) && "Def does not exist!");
- Defs.erase(Name);
- }
-
- //===--------------------------------------------------------------------===//
- // High-level helper methods, useful for tablegen backends...
-
- /// getAllDerivedDefinitions - This method returns all concrete definitions
- /// that derive from the specified class name. If a class with the specified
- /// name does not exist, an exception is thrown.
- std::vector<Record*>
- getAllDerivedDefinitions(const std::string &ClassName) const;
-
- void dump() const;
-};
-
-/// LessRecord - Sorting predicate to sort record pointers by name.
-///
-struct LessRecord {
- bool operator()(const Record *Rec1, const Record *Rec2) const {
- return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0;
- }
-};
-
-/// LessRecordFieldName - Sorting predicate to sort record pointers by their
-/// name field.
-///
-struct LessRecordFieldName {
- bool operator()(const Record *Rec1, const Record *Rec2) const {
- return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
- }
-};
-
-raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK);
-
-} // End llvm namespace
-
-#endif
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index 65d4a9b..b0f4ffc 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -16,7 +16,8 @@
#include "RegisterInfoEmitter.h"
#include "CodeGenTarget.h"
#include "CodeGenRegisters.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Format.h"
@@ -39,6 +40,9 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "namespace llvm {\n\n";
+ OS << "class MCRegisterClass;\n"
+ << "extern MCRegisterClass " << Namespace << "MCRegisterClasses[];\n\n";
+
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
OS << "enum {\n NoRegister,\n";
@@ -53,8 +57,7 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS,
if (!Namespace.empty())
OS << "}\n";
- const std::vector<CodeGenRegisterClass> &RegisterClasses =
- Target.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = Bank.getRegClasses();
if (!RegisterClasses.empty()) {
OS << "\n// Register classes\n";
if (!Namespace.empty())
@@ -62,7 +65,7 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "enum {\n";
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
if (i) OS << ",\n";
- OS << " " << RegisterClasses[i].getName() << "RegClassID";
+ OS << " " << RegisterClasses[i]->getName() << "RegClassID";
OS << " = " << i;
}
OS << "\n };\n";
@@ -91,6 +94,147 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "#endif // GET_REGINFO_ENUM\n\n";
}
+void
+RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
+ const std::vector<CodeGenRegister*> &Regs,
+ bool isCtor) {
+
+ // Collect all information about dwarf register numbers
+ typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy;
+ DwarfRegNumsMapTy DwarfRegNums;
+
+ // First, just pull all provided information to the map
+ unsigned maxLength = 0;
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ Record *Reg = Regs[i]->TheDef;
+ std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
+ maxLength = std::max((size_t)maxLength, RegNums.size());
+ if (DwarfRegNums.count(Reg))
+ errs() << "Warning: DWARF numbers for register " << getQualifiedName(Reg)
+ << "specified multiple times\n";
+ DwarfRegNums[Reg] = RegNums;
+ }
+
+ if (!maxLength)
+ return;
+
+ // Now we know maximal length of number list. Append -1's, where needed
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I)
+ for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
+ I->second.push_back(-1);
+
+ // Emit reverse information about the dwarf register numbers.
+ for (unsigned j = 0; j < 2; ++j) {
+ OS << " switch (";
+ if (j == 0)
+ OS << "DwarfFlavour";
+ else
+ OS << "EHFlavour";
+ OS << ") {\n"
+ << " default:\n"
+ << " assert(0 && \"Unknown DWARF flavour\");\n"
+ << " break;\n";
+
+ for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ OS << " case " << i << ":\n";
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
+ int DwarfRegNo = I->second[i];
+ if (DwarfRegNo < 0)
+ continue;
+ OS << " ";
+ if (!isCtor)
+ OS << "RI->";
+ OS << "mapDwarfRegToLLVMReg(" << DwarfRegNo << ", "
+ << getQualifiedName(I->first) << ", ";
+ if (j == 0)
+ OS << "false";
+ else
+ OS << "true";
+ OS << " );\n";
+ }
+ OS << " break;\n";
+ }
+ OS << " }\n";
+ }
+
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ Record *Reg = Regs[i]->TheDef;
+ const RecordVal *V = Reg->getValue("DwarfAlias");
+ if (!V || !V->getValue())
+ continue;
+
+ DefInit *DI = dynamic_cast<DefInit*>(V->getValue());
+ Record *Alias = DI->getDef();
+ DwarfRegNums[Reg] = DwarfRegNums[Alias];
+ }
+
+ // Emit information about the dwarf register numbers.
+ for (unsigned j = 0; j < 2; ++j) {
+ OS << " switch (";
+ if (j == 0)
+ OS << "DwarfFlavour";
+ else
+ OS << "EHFlavour";
+ OS << ") {\n"
+ << " default:\n"
+ << " assert(0 && \"Unknown DWARF flavour\");\n"
+ << " break;\n";
+
+ for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ OS << " case " << i << ":\n";
+ // Sort by name to get a stable order.
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
+ int RegNo = I->second[i];
+ OS << " ";
+ if (!isCtor)
+ OS << "RI->";
+ OS << "mapLLVMRegToDwarfReg(" << getQualifiedName(I->first) << ", "
+ << RegNo << ", ";
+ if (j == 0)
+ OS << "false";
+ else
+ OS << "true";
+ OS << " );\n";
+ }
+ OS << " break;\n";
+ }
+ OS << " }\n";
+ }
+}
+
+// Print a BitVector as a sequence of hex numbers using a little-endian mapping.
+// Width is the number of bits per hex number.
+static void printBitVectorAsHex(raw_ostream &OS,
+ const BitVector &Bits,
+ unsigned Width) {
+ assert(Width <= 32 && "Width too large");
+ unsigned Digits = (Width + 3) / 4;
+ for (unsigned i = 0, e = Bits.size(); i < e; i += Width) {
+ unsigned Value = 0;
+ for (unsigned j = 0; j != Width && i + j != e; ++j)
+ Value |= Bits.test(i + j) << j;
+ OS << format("0x%0*x, ", Digits, Value);
+ }
+}
+
+// Helper to emit a set of bits into a constant byte array.
+class BitVectorEmitter {
+ BitVector Values;
+public:
+ void add(unsigned v) {
+ if (v >= Values.size())
+ Values.resize(((v/8)+1)*8); // Round up to the next byte.
+ Values[v] = true;
+ }
+
+ void print(raw_ostream &OS) {
+ printBitVectorAsHex(OS, Values, 8);
+ }
+};
+
//
// runMCDesc - Print out MC register descriptions.
//
@@ -186,11 +330,73 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << "};\n\n"; // End of register descriptors...
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
+
+ // Loop over all of the register classes... emitting each one.
+ OS << "namespace { // Register classes...\n";
+
+ // Emit the register enum value arrays for each RegisterClass
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ ArrayRef<Record*> Order = RC.getOrder();
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.getName();
+
+ // Emit the register list now.
+ OS << " // " << Name << " Register Class...\n"
+ << " static const unsigned " << Name
+ << "[] = {\n ";
+ for (unsigned i = 0, e = Order.size(); i != e; ++i) {
+ Record *Reg = Order[i];
+ OS << getQualifiedName(Reg) << ", ";
+ }
+ OS << "\n };\n\n";
+
+ OS << " // " << Name << " Bit set.\n"
+ << " static const unsigned char " << Name
+ << "Bits[] = {\n ";
+ BitVectorEmitter BVE;
+ for (unsigned i = 0, e = Order.size(); i != e; ++i) {
+ Record *Reg = Order[i];
+ BVE.add(Target.getRegBank().getReg(Reg)->EnumValue);
+ }
+ BVE.print(OS);
+ OS << "\n };\n\n";
+
+ }
+ OS << "}\n\n";
+
+ OS << "MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n";
+
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ OS << " MCRegisterClass(" << RC.getQualifiedName() + "RegClassID" << ", "
+ << '\"' << RC.getName() << "\", "
+ << RC.SpillSize/8 << ", "
+ << RC.SpillAlignment/8 << ", "
+ << RC.CopyCost << ", "
+ << RC.Allocatable << ", "
+ << RC.getName() << ", " << RC.getName() << " + "
+ << RC.getOrder().size() << ", "
+ << RC.getName() << "Bits, sizeof(" << RC.getName() << "Bits)"
+ << "),\n";
+ }
+
+ OS << "};\n\n";
+
// MCRegisterInfo initialization routine.
OS << "static inline void Init" << TargetName
- << "MCRegisterInfo(MCRegisterInfo *RI) {\n";
+ << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, "
+ << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n";
OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, "
- << Regs.size()+1 << ");\n}\n\n";
+ << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, "
+ << RegisterClasses.size() << ");\n\n";
+
+ EmitRegMapping(OS, Regs, false);
+
+ OS << "}\n\n";
+
OS << "} // End llvm namespace \n";
OS << "#endif // GET_REGINFO_MC_DESC\n\n";
@@ -213,17 +419,15 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
OS << "namespace llvm {\n\n";
OS << "struct " << ClassName << " : public TargetRegisterInfo {\n"
- << " explicit " << ClassName << "();\n"
- << " virtual int getDwarfRegNumFull(unsigned RegNum, "
- << "unsigned Flavour) const;\n"
- << " virtual int getLLVMRegNumFull(unsigned DwarfRegNum, "
- << "unsigned Flavour) const;\n"
- << " virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const = 0;\n"
+ << " explicit " << ClassName
+ << "(unsigned RA, unsigned D = 0, unsigned E = 0);\n"
<< " virtual bool needsStackRealignment(const MachineFunction &) const\n"
<< " { return false; }\n"
<< " unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n"
<< " unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n"
<< " unsigned composeSubRegIndices(unsigned, unsigned) const;\n"
+ << " const TargetRegisterClass *"
+ "getSubClassWithSubReg(const TargetRegisterClass*, unsigned) const;\n"
<< "};\n\n";
const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices();
@@ -241,15 +445,14 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
OS << "}\n";
}
- const std::vector<CodeGenRegisterClass> &RegisterClasses =
- Target.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
if (!RegisterClasses.empty()) {
- OS << "namespace " << RegisterClasses[0].Namespace
+ OS << "namespace " << RegisterClasses[0]->Namespace
<< " { // Register classes\n";
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RegisterClasses[i];
+ const CodeGenRegisterClass &RC = *RegisterClasses[i];
const std::string &Name = RC.getName();
// Output the register class definition.
@@ -285,42 +488,30 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "namespace llvm {\n\n";
+ // Get access to MCRegisterClass data.
+ OS << "extern MCRegisterClass " << Target.getName()
+ << "MCRegisterClasses[];\n";
+
// Start out by emitting each of the register classes.
- const std::vector<CodeGenRegisterClass> &RegisterClasses =
- Target.getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
// Collect all registers belonging to any allocatable class.
std::set<Record*> AllocatableRegs;
- // Loop over all of the register classes... emitting each one.
- OS << "namespace { // Register classes...\n";
-
- // Emit the register enum value arrays for each RegisterClass
+ // Collect allocatable registers.
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
ArrayRef<Record*> Order = RC.getOrder();
- // Collect allocatable registers.
if (RC.Allocatable)
AllocatableRegs.insert(Order.begin(), Order.end());
-
- // Give the register class a legal C name if it's anonymous.
- std::string Name = RC.getName();
-
- // Emit the register list now.
- OS << " // " << Name << " Register Class...\n"
- << " static const unsigned " << Name
- << "[] = {\n ";
- for (unsigned i = 0, e = Order.size(); i != e; ++i) {
- Record *Reg = Order[i];
- OS << getQualifiedName(Reg) << ", ";
- }
- OS << "\n };\n\n";
}
+ OS << "namespace { // Register classes...\n";
+
// Emit the ValueType arrays for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
// Give the register class a legal C name if it's anonymous.
std::string Name = RC.getName() + "VTs";
@@ -338,65 +529,39 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Now that all of the structs have been emitted, emit the instances.
if (!RegisterClasses.empty()) {
- OS << "namespace " << RegisterClasses[0].Namespace
+ OS << "namespace " << RegisterClasses[0]->Namespace
<< " { // Register class instances\n";
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i)
- OS << " " << RegisterClasses[i].getName() << "Class\t"
- << RegisterClasses[i].getName() << "RegClass;\n";
+ OS << " " << RegisterClasses[i]->getName() << "Class\t"
+ << RegisterClasses[i]->getName() << "RegClass;\n";
- std::map<unsigned, std::set<unsigned> > SuperClassMap;
std::map<unsigned, std::set<unsigned> > SuperRegClassMap;
- OS << "\n";
+
+ OS << "\n static const TargetRegisterClass* const "
+ << "NullRegClasses[] = { NULL };\n\n";
unsigned NumSubRegIndices = RegBank.getSubRegIndices().size();
if (NumSubRegIndices) {
- // Emit the sub-register classes for each RegisterClass
+ // Compute the super-register classes for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
- std::vector<Record*> SRC(NumSubRegIndices);
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
for (DenseMap<Record*,Record*>::const_iterator
i = RC.SubRegClasses.begin(),
e = RC.SubRegClasses.end(); i != e; ++i) {
- // Build SRC array.
- unsigned idx = RegBank.getSubRegIndexNo(i->first);
- SRC.at(idx-1) = i->second;
-
// Find the register class number of i->second for SuperRegClassMap.
- for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
- if (RC2.TheDef == i->second) {
- SuperRegClassMap[rc2].insert(rc);
- break;
- }
- }
- }
-
- // Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
-
- OS << " // " << Name
- << " Sub-register Classes...\n"
- << " static const TargetRegisterClass* const "
- << Name << "SubRegClasses[] = {\n ";
-
- for (unsigned idx = 0; idx != NumSubRegIndices; ++idx) {
- if (idx)
- OS << ", ";
- if (SRC[idx])
- OS << "&" << getQualifiedName(SRC[idx]) << "RegClass";
- else
- OS << "0";
+ const CodeGenRegisterClass *RC2 = RegBank.getRegClass(i->second);
+ assert(RC2 && "Invalid register class in SubRegClasses");
+ SuperRegClassMap[RC2->EnumValue].insert(rc);
}
- OS << "\n };\n\n";
}
// Emit the super-register classes for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
// Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
+ std::string Name = RC.getName();
OS << " // " << Name
<< " Super-register Classes...\n"
@@ -409,10 +574,10 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
if (I != SuperRegClassMap.end()) {
for (std::set<unsigned>::iterator II = I->second.begin(),
EE = I->second.end(); II != EE; ++II) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
+ const CodeGenRegisterClass &RC2 = *RegisterClasses[*II];
if (!Empty)
OS << ", ";
- OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
+ OS << "&" << RC2.getQualifiedName() << "RegClass";
Empty = false;
}
}
@@ -420,97 +585,51 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << (!Empty ? ", " : "") << "NULL";
OS << "\n };\n\n";
}
- } else {
- // No subregindices in this target
- OS << " static const TargetRegisterClass* const "
- << "NullRegClasses[] = { NULL };\n\n";
}
// Emit the sub-classes array for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
// Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
-
- OS << " // " << Name
- << " Register Class sub-classes...\n"
- << " static const TargetRegisterClass* const "
- << Name << "Subclasses[] = {\n ";
-
- bool Empty = true;
- for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
-
- // Sub-classes are used to determine if a virtual register can be used
- // as an instruction operand, or if it must be copied first.
- if (rc == rc2 || !RC.hasSubClass(&RC2)) continue;
-
- if (!Empty) OS << ", ";
- OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
- Empty = false;
-
- std::map<unsigned, std::set<unsigned> >::iterator SCMI =
- SuperClassMap.find(rc2);
- if (SCMI == SuperClassMap.end()) {
- SuperClassMap.insert(std::make_pair(rc2, std::set<unsigned>()));
- SCMI = SuperClassMap.find(rc2);
- }
- SCMI->second.insert(rc);
- }
+ std::string Name = RC.getName();
- OS << (!Empty ? ", " : "") << "NULL";
- OS << "\n };\n\n";
+ OS << " static const unsigned " << Name << "SubclassMask[] = { ";
+ printBitVectorAsHex(OS, RC.getSubClasses(), 32);
+ OS << "};\n\n";
}
+ // Emit NULL terminated super-class lists.
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ ArrayRef<CodeGenRegisterClass*> Supers = RC.getSuperClasses();
- // Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
-
- OS << " // " << Name
- << " Register Class super-classes...\n"
- << " static const TargetRegisterClass* const "
- << Name << "Superclasses[] = {\n ";
-
- bool Empty = true;
- std::map<unsigned, std::set<unsigned> >::iterator I =
- SuperClassMap.find(rc);
- if (I != SuperClassMap.end()) {
- for (std::set<unsigned>::iterator II = I->second.begin(),
- EE = I->second.end(); II != EE; ++II) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
- if (!Empty) OS << ", ";
- OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
- Empty = false;
- }
- }
+ // Skip classes without supers. We can reuse NullRegClasses.
+ if (Supers.empty())
+ continue;
- OS << (!Empty ? ", " : "") << "NULL";
- OS << "\n };\n\n";
+ OS << " static const TargetRegisterClass* const "
+ << RC.getName() << "Superclasses[] = {\n";
+ for (unsigned i = 0; i != Supers.size(); ++i)
+ OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n";
+ OS << " NULL\n };\n\n";
}
// Emit methods.
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RegisterClasses[i];
+ const CodeGenRegisterClass &RC = *RegisterClasses[i];
OS << RC.getName() << "Class::" << RC.getName()
- << "Class() : TargetRegisterClass("
- << RC.getName() + "RegClassID" << ", "
- << '\"' << RC.getName() << "\", "
+ << "Class() : TargetRegisterClass(&"
+ << Target.getName() << "MCRegisterClasses["
+ << RC.getName() + "RegClassID" << "], "
<< RC.getName() + "VTs" << ", "
- << RC.getName() + "Subclasses" << ", "
- << RC.getName() + "Superclasses" << ", "
- << (NumSubRegIndices ? RC.getName() + "Sub" : std::string("Null"))
- << "RegClasses, "
- << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null"))
- << "RegClasses, "
- << RC.SpillSize/8 << ", "
- << RC.SpillAlignment/8 << ", "
- << RC.CopyCost << ", "
- << RC.Allocatable << ", "
- << RC.getName() << ", " << RC.getName() << " + "
- << RC.getOrder().size()
+ << RC.getName() + "SubclassMask" << ", ";
+ if (RC.getSuperClasses().empty())
+ OS << "NullRegClasses, ";
+ else
+ OS << RC.getName() + "Superclasses, ";
+ OS << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null"))
+ << "RegClasses"
<< ") {}\n";
if (!RC.AltOrderSelect.empty()) {
OS << "\nstatic inline unsigned " << RC.getName()
@@ -525,10 +644,12 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]);
OS << " };\n";
}
- OS << " static const ArrayRef<unsigned> Order[] = {\n"
- << " ArrayRef<unsigned>(" << RC.getName();
+ OS << " const MCRegisterClass &MCR = " << Target.getName()
+ << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];"
+ << " static const ArrayRef<unsigned> Order[] = {\n"
+ << " makeArrayRef(MCR.begin(), MCR.getNumRegs()";
for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi)
- OS << "),\n ArrayRef<unsigned>(AltOrder" << oi;
+ OS << "),\n makeArrayRef(AltOrder" << oi;
OS << ")\n };\n const unsigned Select = " << RC.getName()
<< "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders()
<< ");\n return Order[Select];\n}\n";
@@ -541,7 +662,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "\nnamespace {\n";
OS << " const TargetRegisterClass* const RegisterClasses[] = {\n";
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i)
- OS << " &" << getQualifiedName(RegisterClasses[i].TheDef)
+ OS << " &" << RegisterClasses[i]->getQualifiedName()
<< "RegClass,\n";
OS << " };\n";
OS << "}\n"; // End of anonymous namespace...
@@ -658,106 +779,59 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << " }\n}\n\n";
+ // Emit getSubClassWithSubReg.
+ OS << "const TargetRegisterClass *" << ClassName
+ << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)"
+ " const {\n";
+ if (SubRegIndices.empty()) {
+ OS << " assert(Idx == 0 && \"Target has no sub-registers\");\n"
+ << " return RC;\n";
+ } else {
+ // Use the smallest type that can hold a regclass ID with room for a
+ // sentinel.
+ if (RegisterClasses.size() < UINT8_MAX)
+ OS << " static const uint8_t Table[";
+ else if (RegisterClasses.size() < UINT16_MAX)
+ OS << " static const uint16_t Table[";
+ else
+ throw "Too many register classes.";
+ OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n";
+ for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) {
+ const CodeGenRegisterClass &RC = *RegisterClasses[rci];
+ OS << " {\t// " << RC.getName() << "\n";
+ for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
+ Record *Idx = SubRegIndices[sri];
+ if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx))
+ OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx->getName()
+ << " -> " << SRC->getName() << "\n";
+ else
+ OS << " 0,\t// " << Idx->getName() << "\n";
+ }
+ OS << " },\n";
+ }
+ OS << " };\n assert(RC && \"Missing regclass\");\n"
+ << " if (!Idx) return RC;\n --Idx;\n"
+ << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n"
+ << " unsigned TV = Table[RC->getID()][Idx];\n"
+ << " return TV ? getRegClass(TV - 1) : 0;\n";
+ }
+ OS << "}\n\n";
+
// Emit the constructor of the class...
OS << "extern MCRegisterDesc " << TargetName << "RegDesc[];\n";
OS << ClassName << "::" << ClassName
- << "()\n"
+ << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n"
<< " : TargetRegisterInfo(" << TargetName << "RegInfoDesc"
<< ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n"
<< " " << TargetName << "SubRegIndexTable) {\n"
<< " InitMCRegisterInfo(" << TargetName << "RegDesc, "
- << Regs.size()+1 << ");\n"
- << "}\n\n";
+ << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, "
+ << RegisterClasses.size() << ");\n\n";
- // Collect all information about dwarf register numbers
- typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy;
- DwarfRegNumsMapTy DwarfRegNums;
+ EmitRegMapping(OS, Regs, true);
- // First, just pull all provided information to the map
- unsigned maxLength = 0;
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record *Reg = Regs[i]->TheDef;
- std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
- maxLength = std::max((size_t)maxLength, RegNums.size());
- if (DwarfRegNums.count(Reg))
- errs() << "Warning: DWARF numbers for register " << getQualifiedName(Reg)
- << "specified multiple times\n";
- DwarfRegNums[Reg] = RegNums;
- }
-
- // Now we know maximal length of number list. Append -1's, where needed
- for (DwarfRegNumsMapTy::iterator
- I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I)
- for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
- I->second.push_back(-1);
-
- // Emit reverse information about the dwarf register numbers.
- OS << "int " << ClassName << "::getLLVMRegNumFull(unsigned DwarfRegNum, "
- << "unsigned Flavour) const {\n"
- << " switch (Flavour) {\n"
- << " default:\n"
- << " assert(0 && \"Unknown DWARF flavour\");\n"
- << " return -1;\n";
-
- for (unsigned i = 0, e = maxLength; i != e; ++i) {
- OS << " case " << i << ":\n"
- << " switch (DwarfRegNum) {\n"
- << " default:\n"
- << " assert(0 && \"Invalid DwarfRegNum\");\n"
- << " return -1;\n";
-
- for (DwarfRegNumsMapTy::iterator
- I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
- int DwarfRegNo = I->second[i];
- if (DwarfRegNo >= 0)
- OS << " case " << DwarfRegNo << ":\n"
- << " return " << getQualifiedName(I->first) << ";\n";
- }
- OS << " };\n";
- }
-
- OS << " };\n}\n\n";
-
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record *Reg = Regs[i]->TheDef;
- const RecordVal *V = Reg->getValue("DwarfAlias");
- if (!V || !V->getValue())
- continue;
-
- DefInit *DI = dynamic_cast<DefInit*>(V->getValue());
- Record *Alias = DI->getDef();
- DwarfRegNums[Reg] = DwarfRegNums[Alias];
- }
-
- // Emit information about the dwarf register numbers.
- OS << "int " << ClassName << "::getDwarfRegNumFull(unsigned RegNum, "
- << "unsigned Flavour) const {\n"
- << " switch (Flavour) {\n"
- << " default:\n"
- << " assert(0 && \"Unknown DWARF flavour\");\n"
- << " return -1;\n";
-
- for (unsigned i = 0, e = maxLength; i != e; ++i) {
- OS << " case " << i << ":\n"
- << " switch (RegNum) {\n"
- << " default:\n"
- << " assert(0 && \"Invalid RegNum\");\n"
- << " return -1;\n";
-
- // Sort by name to get a stable order.
-
-
- for (DwarfRegNumsMapTy::iterator
- I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
- int RegNo = I->second[i];
- OS << " case " << getQualifiedName(I->first) << ":\n"
- << " return " << RegNo << ";\n";
- }
- OS << " };\n";
- }
-
- OS << " };\n}\n\n";
+ OS << "}\n\n";
OS << "} // End llvm namespace \n";
OS << "#endif // GET_REGINFO_TARGET_DESC\n\n";
diff --git a/utils/TableGen/RegisterInfoEmitter.h b/utils/TableGen/RegisterInfoEmitter.h
index 2c01b5c..0fd4d07 100644
--- a/utils/TableGen/RegisterInfoEmitter.h
+++ b/utils/TableGen/RegisterInfoEmitter.h
@@ -16,11 +16,13 @@
#ifndef REGISTER_INFO_EMITTER_H
#define REGISTER_INFO_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <vector>
namespace llvm {
class CodeGenRegBank;
+struct CodeGenRegister;
class CodeGenTarget;
class RegisterInfoEmitter : public TableGenBackend {
@@ -44,6 +46,11 @@ public:
// run - Output the register file description.
void run(raw_ostream &o);
+
+private:
+ void EmitRegMapping(raw_ostream &o,
+ const std::vector<CodeGenRegister*> &Regs, bool isCtor);
+ void EmitRegClasses(raw_ostream &OS, CodeGenTarget &Target);
};
} // End llvm namespace
diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp
index 21ac09c..bef73f3 100644
--- a/utils/TableGen/SetTheory.cpp
+++ b/utils/TableGen/SetTheory.cpp
@@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
#include "SetTheory.h"
-#include "Error.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/Format.h"
using namespace llvm;
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index 978e91a..103a403 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -13,7 +13,7 @@
#include "SubtargetEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include <algorithm>
diff --git a/utils/TableGen/SubtargetEmitter.h b/utils/TableGen/SubtargetEmitter.h
index b239f3d..ff01274 100644
--- a/utils/TableGen/SubtargetEmitter.h
+++ b/utils/TableGen/SubtargetEmitter.h
@@ -14,7 +14,7 @@
#ifndef SUBTARGET_EMITTER_H
#define SUBTARGET_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/MC/MCInstrItineraries.h"
#include <vector>
#include <map>
diff --git a/utils/TableGen/TGLexer.cpp b/utils/TableGen/TGLexer.cpp
deleted file mode 100644
index b4b90ff..0000000
--- a/utils/TableGen/TGLexer.cpp
+++ /dev/null
@@ -1,435 +0,0 @@
-//===- TGLexer.cpp - Lexer for TableGen -----------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implement the Lexer for TableGen.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TGLexer.h"
-#include "Error.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Config/config.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Twine.h"
-#include <cctype>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cerrno>
-using namespace llvm;
-
-TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
- CurBuffer = 0;
- CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
- CurPtr = CurBuf->getBufferStart();
- TokStart = 0;
-}
-
-SMLoc TGLexer::getLoc() const {
- return SMLoc::getFromPointer(TokStart);
-}
-
-/// ReturnError - Set the error to the specified string at the specified
-/// location. This is defined to always return tgtok::Error.
-tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) {
- PrintError(Loc, Msg);
- return tgtok::Error;
-}
-
-int TGLexer::getNextChar() {
- char CurChar = *CurPtr++;
- switch (CurChar) {
- default:
- return (unsigned char)CurChar;
- case 0: {
- // A nul character in the stream is either the end of the current buffer or
- // a random nul in the file. Disambiguate that here.
- if (CurPtr-1 != CurBuf->getBufferEnd())
- return 0; // Just whitespace.
-
- // If this is the end of an included file, pop the parent file off the
- // include stack.
- SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
- if (ParentIncludeLoc != SMLoc()) {
- CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
- CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
- CurPtr = ParentIncludeLoc.getPointer();
- return getNextChar();
- }
-
- // Otherwise, return end of file.
- --CurPtr; // Another call to lex will return EOF again.
- return EOF;
- }
- case '\n':
- case '\r':
- // Handle the newline character by ignoring it and incrementing the line
- // count. However, be careful about 'dos style' files with \n\r in them.
- // Only treat a \n\r or \r\n as a single line.
- if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
- *CurPtr != CurChar)
- ++CurPtr; // Eat the two char newline sequence.
- return '\n';
- }
-}
-
-tgtok::TokKind TGLexer::LexToken() {
- TokStart = CurPtr;
- // This always consumes at least one character.
- int CurChar = getNextChar();
-
- switch (CurChar) {
- default:
- // Handle letters: [a-zA-Z_#]
- if (isalpha(CurChar) || CurChar == '_' || CurChar == '#')
- return LexIdentifier();
-
- // Unknown character, emit an error.
- return ReturnError(TokStart, "Unexpected character");
- case EOF: return tgtok::Eof;
- case ':': return tgtok::colon;
- case ';': return tgtok::semi;
- case '.': return tgtok::period;
- case ',': return tgtok::comma;
- case '<': return tgtok::less;
- case '>': return tgtok::greater;
- case ']': return tgtok::r_square;
- case '{': return tgtok::l_brace;
- case '}': return tgtok::r_brace;
- case '(': return tgtok::l_paren;
- case ')': return tgtok::r_paren;
- case '=': return tgtok::equal;
- case '?': return tgtok::question;
-
- case 0:
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- // Ignore whitespace.
- return LexToken();
- case '/':
- // If this is the start of a // comment, skip until the end of the line or
- // the end of the buffer.
- if (*CurPtr == '/')
- SkipBCPLComment();
- else if (*CurPtr == '*') {
- if (SkipCComment())
- return tgtok::Error;
- } else // Otherwise, this is an error.
- return ReturnError(TokStart, "Unexpected character");
- return LexToken();
- case '-': case '+':
- case '0': case '1': case '2': case '3': case '4': case '5': case '6':
- case '7': case '8': case '9':
- return LexNumber();
- case '"': return LexString();
- case '$': return LexVarName();
- case '[': return LexBracket();
- case '!': return LexExclaim();
- }
-}
-
-/// LexString - Lex "[^"]*"
-tgtok::TokKind TGLexer::LexString() {
- const char *StrStart = CurPtr;
-
- CurStrVal = "";
-
- while (*CurPtr != '"') {
- // If we hit the end of the buffer, report an error.
- if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd())
- return ReturnError(StrStart, "End of file in string literal");
-
- if (*CurPtr == '\n' || *CurPtr == '\r')
- return ReturnError(StrStart, "End of line in string literal");
-
- if (*CurPtr != '\\') {
- CurStrVal += *CurPtr++;
- continue;
- }
-
- ++CurPtr;
-
- switch (*CurPtr) {
- case '\\': case '\'': case '"':
- // These turn into their literal character.
- CurStrVal += *CurPtr++;
- break;
- case 't':
- CurStrVal += '\t';
- ++CurPtr;
- break;
- case 'n':
- CurStrVal += '\n';
- ++CurPtr;
- break;
-
- case '\n':
- case '\r':
- return ReturnError(CurPtr, "escaped newlines not supported in tblgen");
-
- // If we hit the end of the buffer, report an error.
- case '\0':
- if (CurPtr == CurBuf->getBufferEnd())
- return ReturnError(StrStart, "End of file in string literal");
- // FALL THROUGH
- default:
- return ReturnError(CurPtr, "invalid escape in string literal");
- }
- }
-
- ++CurPtr;
- return tgtok::StrVal;
-}
-
-tgtok::TokKind TGLexer::LexVarName() {
- if (!isalpha(CurPtr[0]) && CurPtr[0] != '_')
- return ReturnError(TokStart, "Invalid variable name");
-
- // Otherwise, we're ok, consume the rest of the characters.
- const char *VarNameStart = CurPtr++;
-
- while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
- ++CurPtr;
-
- CurStrVal.assign(VarNameStart, CurPtr);
- return tgtok::VarName;
-}
-
-
-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)) {
- if (LexInclude()) return tgtok::Error;
- return Lex();
- }
-
- CurStrVal.assign(IdentStart, CurPtr);
- return tgtok::Id;
-}
-
-/// LexInclude - We just read the "include" token. Get the string token that
-/// comes next and enter the include.
-bool TGLexer::LexInclude() {
- // The token after the include must be a string.
- tgtok::TokKind Tok = LexToken();
- if (Tok == tgtok::Error) return true;
- if (Tok != tgtok::StrVal) {
- PrintError(getLoc(), "Expected filename after include");
- return true;
- }
-
- // Get the string.
- std::string Filename = CurStrVal;
- std::string IncludedFile;
-
-
- CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr),
- IncludedFile);
- if (CurBuffer == -1) {
- PrintError(getLoc(), "Could not find include file '" + Filename + "'");
- return true;
- }
-
- Dependencies.push_back(IncludedFile);
- // Save the line number and lex buffer of the includer.
- CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
- CurPtr = CurBuf->getBufferStart();
- return false;
-}
-
-void TGLexer::SkipBCPLComment() {
- ++CurPtr; // skip the second slash.
- while (1) {
- switch (*CurPtr) {
- case '\n':
- case '\r':
- return; // Newline is end of comment.
- case 0:
- // If this is the end of the buffer, end the comment.
- if (CurPtr == CurBuf->getBufferEnd())
- return;
- break;
- }
- // Otherwise, skip the character.
- ++CurPtr;
- }
-}
-
-/// SkipCComment - This skips C-style /**/ comments. The only difference from C
-/// is that we allow nesting.
-bool TGLexer::SkipCComment() {
- ++CurPtr; // skip the star.
- unsigned CommentDepth = 1;
-
- while (1) {
- int CurChar = getNextChar();
- switch (CurChar) {
- case EOF:
- PrintError(TokStart, "Unterminated comment!");
- return true;
- case '*':
- // End of the comment?
- if (CurPtr[0] != '/') break;
-
- ++CurPtr; // End the */.
- if (--CommentDepth == 0)
- return false;
- break;
- case '/':
- // Start of a nested comment?
- if (CurPtr[0] != '*') break;
- ++CurPtr;
- ++CommentDepth;
- break;
- }
- }
-}
-
-/// LexNumber - Lex:
-/// [-+]?[0-9]+
-/// 0x[0-9a-fA-F]+
-/// 0b[01]+
-tgtok::TokKind TGLexer::LexNumber() {
- if (CurPtr[-1] == '0') {
- if (CurPtr[0] == 'x') {
- ++CurPtr;
- const char *NumStart = CurPtr;
- while (isxdigit(CurPtr[0]))
- ++CurPtr;
-
- // Requires at least one hex digit.
- if (CurPtr == NumStart)
- return ReturnError(TokStart, "Invalid hexadecimal number");
-
- errno = 0;
- CurIntVal = strtoll(NumStart, 0, 16);
- if (errno == EINVAL)
- return ReturnError(TokStart, "Invalid hexadecimal number");
- if (errno == ERANGE) {
- errno = 0;
- CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
- if (errno == EINVAL)
- return ReturnError(TokStart, "Invalid hexadecimal number");
- if (errno == ERANGE)
- return ReturnError(TokStart, "Hexadecimal number out of range");
- }
- return tgtok::IntVal;
- } else if (CurPtr[0] == 'b') {
- ++CurPtr;
- const char *NumStart = CurPtr;
- while (CurPtr[0] == '0' || CurPtr[0] == '1')
- ++CurPtr;
-
- // Requires at least one binary digit.
- if (CurPtr == NumStart)
- return ReturnError(CurPtr-2, "Invalid binary number");
- CurIntVal = strtoll(NumStart, 0, 2);
- return tgtok::IntVal;
- }
- }
-
- // Check for a sign without a digit.
- if (!isdigit(CurPtr[0])) {
- if (CurPtr[-1] == '-')
- return tgtok::minus;
- else if (CurPtr[-1] == '+')
- return tgtok::plus;
- }
-
- while (isdigit(CurPtr[0]))
- ++CurPtr;
- CurIntVal = strtoll(TokStart, 0, 10);
- return tgtok::IntVal;
-}
-
-/// LexBracket - We just read '['. If this is a code block, return it,
-/// otherwise return the bracket. Match: '[' and '[{ ( [^}]+ | }[^]] )* }]'
-tgtok::TokKind TGLexer::LexBracket() {
- if (CurPtr[0] != '{')
- return tgtok::l_square;
- ++CurPtr;
- const char *CodeStart = CurPtr;
- while (1) {
- int Char = getNextChar();
- if (Char == EOF) break;
-
- if (Char != '}') continue;
-
- Char = getNextChar();
- if (Char == EOF) break;
- if (Char == ']') {
- CurStrVal.assign(CodeStart, CurPtr-2);
- return tgtok::CodeFragment;
- }
- }
-
- return ReturnError(CodeStart-2, "Unterminated Code Block");
-}
-
-/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
-tgtok::TokKind TGLexer::LexExclaim() {
- if (!isalpha(*CurPtr))
- return ReturnError(CurPtr - 1, "Invalid \"!operator\"");
-
- const char *Start = CurPtr++;
- while (isalpha(*CurPtr))
- ++CurPtr;
-
- // Check to see which operator this is.
- tgtok::TokKind Kind =
- StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start))
- .Case("eq", tgtok::XEq)
- .Case("if", tgtok::XIf)
- .Case("head", tgtok::XHead)
- .Case("tail", tgtok::XTail)
- .Case("con", tgtok::XConcat)
- .Case("shl", tgtok::XSHL)
- .Case("sra", tgtok::XSRA)
- .Case("srl", tgtok::XSRL)
- .Case("cast", tgtok::XCast)
- .Case("empty", tgtok::XEmpty)
- .Case("subst", tgtok::XSubst)
- .Case("foreach", tgtok::XForEach)
- .Case("strconcat", tgtok::XStrConcat)
- .Default(tgtok::Error);
-
- return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator");
-}
-
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp
deleted file mode 100644
index 59097f9..0000000
--- a/utils/TableGen/TGParser.cpp
+++ /dev/null
@@ -1,2152 +0,0 @@
-//===- TGParser.cpp - Parser for TableGen Files ---------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implement the Parser for TableGen.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TGParser.h"
-#include "Record.h"
-#include "llvm/ADT/StringExtras.h"
-#include <algorithm>
-#include <sstream>
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/CommandLine.h"
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Support Code for the Semantic Actions.
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
-struct SubClassReference {
- SMLoc RefLoc;
- Record *Rec;
- std::vector<Init*> TemplateArgs;
- SubClassReference() : Rec(0) {}
-
- bool isInvalid() const { return Rec == 0; }
-};
-
-struct SubMultiClassReference {
- SMLoc RefLoc;
- MultiClass *MC;
- std::vector<Init*> TemplateArgs;
- SubMultiClassReference() : MC(0) {}
-
- bool isInvalid() const { return MC == 0; }
- void dump() const;
-};
-
-void SubMultiClassReference::dump() const {
- errs() << "Multiclass:\n";
-
- MC->dump();
-
- errs() << "Template args:\n";
- for (std::vector<Init *>::const_iterator i = TemplateArgs.begin(),
- iend = TemplateArgs.end();
- i != iend;
- ++i) {
- (*i)->dump();
- }
-}
-
-} // end namespace llvm
-
-bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) {
- if (CurRec == 0)
- CurRec = &CurMultiClass->Rec;
-
- if (RecordVal *ERV = CurRec->getValue(RV.getName())) {
- // The value already exists in the class, treat this as a set.
- if (ERV->setValue(RV.getValue()))
- return Error(Loc, "New definition of '" + RV.getName() + "' of type '" +
- RV.getType()->getAsString() + "' is incompatible with " +
- "previous definition of type '" +
- ERV->getType()->getAsString() + "'");
- } else {
- CurRec->addValue(RV);
- }
- return false;
-}
-
-/// SetValue -
-/// Return true on error, false on success.
-bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName,
- const std::vector<unsigned> &BitList, Init *V) {
- if (!V) return false;
-
- if (CurRec == 0) CurRec = &CurMultiClass->Rec;
-
- RecordVal *RV = CurRec->getValue(ValName);
- if (RV == 0)
- return Error(Loc, "Value '" + ValName + "' unknown!");
-
- // Do not allow assignments like 'X = X'. This will just cause infinite loops
- // in the resolution machinery.
- if (BitList.empty())
- if (VarInit *VI = dynamic_cast<VarInit*>(V))
- if (VI->getName() == ValName)
- return false;
-
- // If we are assigning to a subset of the bits in the value... then we must be
- // assigning to a field of BitsRecTy, which must have a BitsInit
- // initializer.
- //
- if (!BitList.empty()) {
- BitsInit *CurVal = dynamic_cast<BitsInit*>(RV->getValue());
- if (CurVal == 0)
- 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()));
- if (BI == 0) {
- V->convertInitializerTo(new BitsRecTy(BitList.size()));
- return Error(Loc, "Initializer is not compatible with bit range");
- }
-
- // We should have a BitsInit type now.
- BitsInit *BInit = dynamic_cast<BitsInit*>(BI);
- assert(BInit != 0);
-
- BitsInit *NewVal = new BitsInit(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))
- return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" +
- ValName + "' more than once");
- NewVal->setBit(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));
-
- V = NewVal;
- }
-
- if (RV->setValue(V))
- return Error(Loc, "Value '" + ValName + "' of type '" +
- RV->getType()->getAsString() +
- "' is incompatible with initializer '" + V->getAsString() +"'");
- return false;
-}
-
-/// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template
-/// args as SubClass's template arguments.
-bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
- Record *SC = SubClass.Rec;
- // Add all of the values in the subclass into the current class.
- const std::vector<RecordVal> &Vals = SC->getValues();
- for (unsigned i = 0, e = Vals.size(); i != e; ++i)
- if (AddValue(CurRec, SubClass.RefLoc, Vals[i]))
- return true;
-
- const std::vector<std::string> &TArgs = SC->getTemplateArgs();
-
- // Ensure that an appropriate number of template arguments are specified.
- if (TArgs.size() < SubClass.TemplateArgs.size())
- return Error(SubClass.RefLoc, "More template args specified than expected");
-
- // 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) {
- if (i < SubClass.TemplateArgs.size()) {
- // If a value is specified for this template arg, set it now.
- if (SetValue(CurRec, SubClass.RefLoc, TArgs[i], std::vector<unsigned>(),
- SubClass.TemplateArgs[i]))
- return true;
-
- // 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(SubClass.RefLoc,"Value not specified for template argument #"
- + utostr(i) + " (" + TArgs[i] + ") of subclass '" +
- SC->getName() + "'!");
- }
- }
-
- // Since everything went well, we can now set the "superclass" list for the
- // current record.
- const std::vector<Record*> &SCs = SC->getSuperClasses();
- for (unsigned i = 0, e = SCs.size(); i != e; ++i) {
- if (CurRec->isSubClassOf(SCs[i]))
- return Error(SubClass.RefLoc,
- "Already subclass of '" + SCs[i]->getName() + "'!\n");
- CurRec->addSuperClass(SCs[i]);
- }
-
- if (CurRec->isSubClassOf(SC))
- return Error(SubClass.RefLoc,
- "Already subclass of '" + SC->getName() + "'!\n");
- CurRec->addSuperClass(SC);
- return false;
-}
-
-/// AddSubMultiClass - Add SubMultiClass as a subclass to
-/// CurMC, resolving its template args as SubMultiClass's
-/// template arguments.
-bool TGParser::AddSubMultiClass(MultiClass *CurMC,
- SubMultiClassReference &SubMultiClass) {
- MultiClass *SMC = SubMultiClass.MC;
- Record *CurRec = &CurMC->Rec;
-
- const std::vector<RecordVal> &MCVals = CurRec->getValues();
-
- // Add all of the values in the subclass into the current class.
- const std::vector<RecordVal> &SMCVals = SMC->Rec.getValues();
- for (unsigned i = 0, e = SMCVals.size(); i != e; ++i)
- if (AddValue(CurRec, SubMultiClass.RefLoc, SMCVals[i]))
- return true;
-
- int newDefStart = CurMC->DefPrototypes.size();
-
- // Add all of the defs in the subclass into the current multiclass.
- for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(),
- iend = SMC->DefPrototypes.end();
- i != iend;
- ++i) {
- // Clone the def and add it to the current multiclass
- Record *NewDef = new Record(**i);
-
- // Add all of the values in the superclass into the current def.
- for (unsigned i = 0, e = MCVals.size(); i != e; ++i)
- if (AddValue(NewDef, SubMultiClass.RefLoc, MCVals[i]))
- return true;
-
- CurMC->DefPrototypes.push_back(NewDef);
- }
-
- const std::vector<std::string> &SMCTArgs = SMC->Rec.getTemplateArgs();
-
- // Ensure that an appropriate number of template arguments are
- // specified.
- if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size())
- return Error(SubMultiClass.RefLoc,
- "More template args specified than expected");
-
- // 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 = SMCTArgs.size(); i != e; ++i) {
- if (i < SubMultiClass.TemplateArgs.size()) {
- // If a value is specified for this template arg, set it in the
- // superclass now.
- if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i],
- std::vector<unsigned>(),
- SubMultiClass.TemplateArgs[i]))
- return true;
-
- // Resolve it next.
- CurRec->resolveReferencesTo(CurRec->getValue(SMCTArgs[i]));
-
- // Now remove it.
- CurRec->removeValue(SMCTArgs[i]);
-
- // If a value is specified for this template arg, set it in the
- // new defs now.
- for (MultiClass::RecordVector::iterator j =
- CurMC->DefPrototypes.begin() + newDefStart,
- jend = CurMC->DefPrototypes.end();
- j != jend;
- ++j) {
- Record *Def = *j;
-
- if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i],
- std::vector<unsigned>(),
- SubMultiClass.TemplateArgs[i]))
- return true;
-
- // Resolve it next.
- Def->resolveReferencesTo(Def->getValue(SMCTArgs[i]));
-
- // Now remove it
- Def->removeValue(SMCTArgs[i]);
- }
- } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) {
- return Error(SubMultiClass.RefLoc,
- "Value not specified for template argument #"
- + utostr(i) + " (" + SMCTArgs[i] + ") of subclass '" +
- SMC->Rec.getName() + "'!");
- }
- }
-
- return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Parser Code
-//===----------------------------------------------------------------------===//
-
-/// isObjectStart - Return true if this is a valid first token for an Object.
-static bool isObjectStart(tgtok::TokKind K) {
- return K == tgtok::Class || K == tgtok::Def ||
- K == tgtok::Defm || K == tgtok::Let || K == tgtok::MultiClass;
-}
-
-static std::string GetNewAnonymousName() {
- static unsigned AnonCounter = 0;
- return "anonymous."+utostr(AnonCounter++);
-}
-
-/// ParseObjectName - If an object name is specified, return it. Otherwise,
-/// return an anonymous name.
-/// ObjectName ::= ID
-/// ObjectName ::= /*empty*/
-///
-std::string TGParser::ParseObjectName() {
- if (Lex.getCode() != tgtok::Id)
- return GetNewAnonymousName();
-
- std::string Ret = Lex.getCurStrVal();
- Lex.Lex();
- return Ret;
-}
-
-
-/// ParseClassID - Parse and resolve a reference to a class name. This returns
-/// null on error.
-///
-/// ClassID ::= ID
-///
-Record *TGParser::ParseClassID() {
- if (Lex.getCode() != tgtok::Id) {
- TokError("expected name for ClassID");
- return 0;
- }
-
- Record *Result = Records.getClass(Lex.getCurStrVal());
- if (Result == 0)
- TokError("Couldn't find class '" + Lex.getCurStrVal() + "'");
-
- Lex.Lex();
- return Result;
-}
-
-/// ParseMultiClassID - Parse and resolve a reference to a multiclass name.
-/// This returns null on error.
-///
-/// MultiClassID ::= ID
-///
-MultiClass *TGParser::ParseMultiClassID() {
- if (Lex.getCode() != tgtok::Id) {
- TokError("expected name for ClassID");
- return 0;
- }
-
- MultiClass *Result = MultiClasses[Lex.getCurStrVal()];
- if (Result == 0)
- TokError("Couldn't find class '" + Lex.getCurStrVal() + "'");
-
- Lex.Lex();
- return Result;
-}
-
-Record *TGParser::ParseDefmID() {
- if (Lex.getCode() != tgtok::Id) {
- TokError("expected multiclass name");
- return 0;
- }
-
- MultiClass *MC = MultiClasses[Lex.getCurStrVal()];
- if (MC == 0) {
- TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'");
- return 0;
- }
-
- Lex.Lex();
- return &MC->Rec;
-}
-
-
-/// ParseSubClassReference - Parse a reference to a subclass or to a templated
-/// subclass. This returns a SubClassRefTy with a null Record* on error.
-///
-/// SubClassRef ::= ClassID
-/// SubClassRef ::= ClassID '<' ValueList '>'
-///
-SubClassReference TGParser::
-ParseSubClassReference(Record *CurRec, bool isDefm) {
- SubClassReference Result;
- Result.RefLoc = Lex.getLoc();
-
- if (isDefm)
- Result.Rec = ParseDefmID();
- else
- Result.Rec = ParseClassID();
- if (Result.Rec == 0) return Result;
-
- // If there is no template arg list, we're done.
- if (Lex.getCode() != tgtok::less)
- return Result;
- Lex.Lex(); // Eat the '<'
-
- if (Lex.getCode() == tgtok::greater) {
- TokError("subclass reference requires a non-empty list of template values");
- Result.Rec = 0;
- return Result;
- }
-
- Result.TemplateArgs = ParseValueList(CurRec, Result.Rec);
- if (Result.TemplateArgs.empty()) {
- Result.Rec = 0; // Error parsing value list.
- return Result;
- }
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' in template value list");
- Result.Rec = 0;
- return Result;
- }
- Lex.Lex();
-
- return Result;
-}
-
-/// ParseSubMultiClassReference - Parse a reference to a subclass or to a
-/// templated submulticlass. This returns a SubMultiClassRefTy with a null
-/// Record* on error.
-///
-/// SubMultiClassRef ::= MultiClassID
-/// SubMultiClassRef ::= MultiClassID '<' ValueList '>'
-///
-SubMultiClassReference TGParser::
-ParseSubMultiClassReference(MultiClass *CurMC) {
- SubMultiClassReference Result;
- Result.RefLoc = Lex.getLoc();
-
- Result.MC = ParseMultiClassID();
- if (Result.MC == 0) return Result;
-
- // If there is no template arg list, we're done.
- if (Lex.getCode() != tgtok::less)
- return Result;
- Lex.Lex(); // Eat the '<'
-
- if (Lex.getCode() == tgtok::greater) {
- TokError("subclass reference requires a non-empty list of template values");
- Result.MC = 0;
- return Result;
- }
-
- Result.TemplateArgs = ParseValueList(&CurMC->Rec, &Result.MC->Rec);
- if (Result.TemplateArgs.empty()) {
- Result.MC = 0; // Error parsing value list.
- return Result;
- }
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' in template value list");
- Result.MC = 0;
- return Result;
- }
- Lex.Lex();
-
- return Result;
-}
-
-/// ParseRangePiece - Parse a bit/value range.
-/// RangePiece ::= INTVAL
-/// RangePiece ::= INTVAL '-' INTVAL
-/// RangePiece ::= INTVAL INTVAL
-bool TGParser::ParseRangePiece(std::vector<unsigned> &Ranges) {
- if (Lex.getCode() != tgtok::IntVal) {
- TokError("expected integer or bitrange");
- return true;
- }
- int64_t Start = Lex.getCurIntVal();
- int64_t End;
-
- if (Start < 0)
- return TokError("invalid range, cannot be negative");
-
- switch (Lex.Lex()) { // eat first character.
- default:
- Ranges.push_back(Start);
- return false;
- case tgtok::minus:
- if (Lex.Lex() != tgtok::IntVal) {
- TokError("expected integer value as end of range");
- return true;
- }
- End = Lex.getCurIntVal();
- break;
- case tgtok::IntVal:
- End = -Lex.getCurIntVal();
- break;
- }
- if (End < 0)
- return TokError("invalid range, cannot be negative");
- Lex.Lex();
-
- // Add to the range.
- if (Start < End) {
- for (; Start <= End; ++Start)
- Ranges.push_back(Start);
- } else {
- for (; Start >= End; --Start)
- Ranges.push_back(Start);
- }
- return false;
-}
-
-/// ParseRangeList - Parse a list of scalars and ranges into scalar values.
-///
-/// RangeList ::= RangePiece (',' RangePiece)*
-///
-std::vector<unsigned> TGParser::ParseRangeList() {
- std::vector<unsigned> Result;
-
- // Parse the first piece.
- if (ParseRangePiece(Result))
- return std::vector<unsigned>();
- while (Lex.getCode() == tgtok::comma) {
- Lex.Lex(); // Eat the comma.
-
- // Parse the next range piece.
- if (ParseRangePiece(Result))
- return std::vector<unsigned>();
- }
- return Result;
-}
-
-/// ParseOptionalRangeList - Parse either a range list in <>'s or nothing.
-/// OptionalRangeList ::= '<' RangeList '>'
-/// OptionalRangeList ::= /*empty*/
-bool TGParser::ParseOptionalRangeList(std::vector<unsigned> &Ranges) {
- if (Lex.getCode() != tgtok::less)
- return false;
-
- SMLoc StartLoc = Lex.getLoc();
- Lex.Lex(); // eat the '<'
-
- // Parse the range list.
- Ranges = ParseRangeList();
- if (Ranges.empty()) return true;
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' at end of range list");
- return Error(StartLoc, "to match this '<'");
- }
- Lex.Lex(); // eat the '>'.
- return false;
-}
-
-/// ParseOptionalBitList - Parse either a bit list in {}'s or nothing.
-/// OptionalBitList ::= '{' RangeList '}'
-/// OptionalBitList ::= /*empty*/
-bool TGParser::ParseOptionalBitList(std::vector<unsigned> &Ranges) {
- if (Lex.getCode() != tgtok::l_brace)
- return false;
-
- SMLoc StartLoc = Lex.getLoc();
- Lex.Lex(); // eat the '{'
-
- // Parse the range list.
- Ranges = ParseRangeList();
- if (Ranges.empty()) return true;
-
- if (Lex.getCode() != tgtok::r_brace) {
- TokError("expected '}' at end of bit list");
- return Error(StartLoc, "to match this '{'");
- }
- Lex.Lex(); // eat the '}'.
- return false;
-}
-
-
-/// ParseType - Parse and return a tblgen type. This returns null on error.
-///
-/// Type ::= STRING // string type
-/// Type ::= BIT // bit type
-/// Type ::= BITS '<' INTVAL '>' // bits<x> type
-/// Type ::= INT // int type
-/// Type ::= LIST '<' Type '>' // list<x> type
-/// Type ::= CODE // code type
-/// Type ::= DAG // dag type
-/// Type ::= ClassID // Record Type
-///
-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::Id:
- if (Record *R = ParseClassID()) return new RecordRecTy(R);
- return 0;
- case tgtok::Bits: {
- if (Lex.Lex() != tgtok::less) { // Eat 'bits'
- TokError("expected '<' after bits type");
- return 0;
- }
- if (Lex.Lex() != tgtok::IntVal) { // Eat '<'
- TokError("expected integer in bits<n> type");
- return 0;
- }
- uint64_t Val = Lex.getCurIntVal();
- if (Lex.Lex() != tgtok::greater) { // Eat count.
- TokError("expected '>' at end of bits<n> type");
- return 0;
- }
- Lex.Lex(); // Eat '>'
- return new BitsRecTy(Val);
- }
- case tgtok::List: {
- if (Lex.Lex() != tgtok::less) { // Eat 'bits'
- TokError("expected '<' after list type");
- return 0;
- }
- Lex.Lex(); // Eat '<'
- RecTy *SubType = ParseType();
- if (SubType == 0) return 0;
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' at end of list<ty> type");
- return 0;
- }
- Lex.Lex(); // Eat '>'
- return new ListRecTy(SubType);
- }
- }
-}
-
-/// ParseIDValue - Parse an ID as a value and decode what it means.
-///
-/// IDValue ::= ID [def local value]
-/// IDValue ::= ID [def template arg]
-/// IDValue ::= ID [multiclass local value]
-/// IDValue ::= ID [multiclass template argument]
-/// IDValue ::= ID [def name]
-///
-Init *TGParser::ParseIDValue(Record *CurRec) {
- assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue");
- std::string Name = Lex.getCurStrVal();
- SMLoc Loc = Lex.getLoc();
- Lex.Lex();
- return ParseIDValue(CurRec, Name, Loc);
-}
-
-/// ParseIDValue - This is just like ParseIDValue above, but it assumes the ID
-/// has already been read.
-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());
-
- std::string TemplateArgName = CurRec->getName()+":"+Name;
- if (CurRec->isTemplateArg(TemplateArgName)) {
- const RecordVal *RV = CurRec->getValue(TemplateArgName);
- assert(RV && "Template arg doesn't exist??");
- return new VarInit(TemplateArgName, RV->getType());
- }
- }
-
- if (CurMultiClass) {
- std::string MCName = CurMultiClass->Rec.getName()+"::"+Name;
- 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());
- }
- }
-
- if (Record *D = Records.getDef(Name))
- return new DefInit(D);
-
- Error(NameLoc, "Variable not defined: '" + Name + "'");
- return 0;
-}
-
-/// ParseOperation - Parse an operator. This returns null on error.
-///
-/// Operation ::= XOperator ['<' Type '>'] '(' Args ')'
-///
-Init *TGParser::ParseOperation(Record *CurRec) {
- switch (Lex.getCode()) {
- default:
- TokError("unknown operation");
- return 0;
- break;
- case tgtok::XHead:
- case tgtok::XTail:
- case tgtok::XEmpty:
- case tgtok::XCast: { // Value ::= !unop '(' Value ')'
- UnOpInit::UnaryOp Code;
- RecTy *Type = 0;
-
- switch (Lex.getCode()) {
- default: assert(0 && "Unhandled code!");
- case tgtok::XCast:
- Lex.Lex(); // eat the operation
- Code = UnOpInit::CAST;
-
- Type = ParseOperatorType();
-
- if (Type == 0) {
- TokError("did not get type for unary operator");
- return 0;
- }
-
- break;
- case tgtok::XHead:
- Lex.Lex(); // eat the operation
- Code = UnOpInit::HEAD;
- break;
- case tgtok::XTail:
- Lex.Lex(); // eat the operation
- Code = UnOpInit::TAIL;
- break;
- case tgtok::XEmpty:
- Lex.Lex(); // eat the operation
- Code = UnOpInit::EMPTY;
- Type = new IntRecTy;
- break;
- }
- if (Lex.getCode() != tgtok::l_paren) {
- TokError("expected '(' after unary operator");
- return 0;
- }
- Lex.Lex(); // eat the '('
-
- Init *LHS = ParseValue(CurRec);
- if (LHS == 0) return 0;
-
- if (Code == UnOpInit::HEAD
- || Code == UnOpInit::TAIL
- || Code == UnOpInit::EMPTY) {
- ListInit *LHSl = dynamic_cast<ListInit*>(LHS);
- StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
- TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS);
- if (LHSl == 0 && LHSs == 0 && LHSt == 0) {
- TokError("expected list or string type argument in unary operator");
- return 0;
- }
- if (LHSt) {
- ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
- StringRecTy *SType = dynamic_cast<StringRecTy*>(LHSt->getType());
- if (LType == 0 && SType == 0) {
- TokError("expected list or string type argumnet in unary operator");
- return 0;
- }
- }
-
- if (Code == UnOpInit::HEAD
- || Code == UnOpInit::TAIL) {
- if (LHSl == 0 && LHSt == 0) {
- TokError("expected list type argumnet in unary operator");
- return 0;
- }
-
- if (LHSl && LHSl->getSize() == 0) {
- TokError("empty list argument in unary operator");
- return 0;
- }
- if (LHSl) {
- Init *Item = LHSl->getElement(0);
- TypedInit *Itemt = dynamic_cast<TypedInit*>(Item);
- if (Itemt == 0) {
- TokError("untyped list element in unary operator");
- return 0;
- }
- if (Code == UnOpInit::HEAD) {
- Type = Itemt->getType();
- } else {
- Type = new ListRecTy(Itemt->getType());
- }
- } else {
- assert(LHSt && "expected list type argument in unary operator");
- ListRecTy *LType = dynamic_cast<ListRecTy*>(LHSt->getType());
- if (LType == 0) {
- TokError("expected list type argumnet in unary operator");
- return 0;
- }
- if (Code == UnOpInit::HEAD) {
- Type = LType->getElementType();
- } else {
- Type = LType;
- }
- }
- }
- }
-
- if (Lex.getCode() != tgtok::r_paren) {
- TokError("expected ')' in unary operator");
- return 0;
- }
- Lex.Lex(); // eat the ')'
- return (new UnOpInit(Code, LHS, Type))->Fold(CurRec, CurMultiClass);
- }
-
- case tgtok::XConcat:
- case tgtok::XSRA:
- case tgtok::XSRL:
- case tgtok::XSHL:
- case tgtok::XEq:
- case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')'
- tgtok::TokKind OpTok = Lex.getCode();
- SMLoc OpLoc = Lex.getLoc();
- Lex.Lex(); // eat the operation
-
- BinOpInit::BinaryOp Code;
- RecTy *Type = 0;
-
- 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::XStrConcat:
- Code = BinOpInit::STRCONCAT;
- Type = new StringRecTy();
- break;
- }
-
- if (Lex.getCode() != tgtok::l_paren) {
- TokError("expected '(' after binary operator");
- return 0;
- }
- Lex.Lex(); // eat the '('
-
- SmallVector<Init*, 2> InitList;
-
- InitList.push_back(ParseValue(CurRec));
- if (InitList.back() == 0) return 0;
-
- while (Lex.getCode() == tgtok::comma) {
- Lex.Lex(); // eat the ','
-
- InitList.push_back(ParseValue(CurRec));
- if (InitList.back() == 0) return 0;
- }
-
- if (Lex.getCode() != tgtok::r_paren) {
- TokError("expected ')' in operator");
- return 0;
- }
- Lex.Lex(); // eat the ')'
-
- // We allow multiple operands to associative operators like !strconcat as
- // shorthand for nesting them.
- 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);
- InitList.back() = RHS;
- }
- }
-
- if (InitList.size() == 2)
- return (new BinOpInit(Code, InitList[0], InitList[1], Type))
- ->Fold(CurRec, CurMultiClass);
-
- Error(OpLoc, "expected two operands to operator");
- return 0;
- }
-
- case tgtok::XIf:
- case tgtok::XForEach:
- case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
- TernOpInit::TernaryOp Code;
- RecTy *Type = 0;
-
- tgtok::TokKind LexCode = Lex.getCode();
- Lex.Lex(); // eat the operation
- switch (LexCode) {
- default: assert(0 && "Unhandled code!");
- case tgtok::XIf:
- Code = TernOpInit::IF;
- break;
- case tgtok::XForEach:
- Code = TernOpInit::FOREACH;
- break;
- case tgtok::XSubst:
- Code = TernOpInit::SUBST;
- break;
- }
- if (Lex.getCode() != tgtok::l_paren) {
- TokError("expected '(' after ternary operator");
- return 0;
- }
- Lex.Lex(); // eat the '('
-
- Init *LHS = ParseValue(CurRec);
- if (LHS == 0) return 0;
-
- if (Lex.getCode() != tgtok::comma) {
- TokError("expected ',' in ternary operator");
- return 0;
- }
- Lex.Lex(); // eat the ','
-
- Init *MHS = ParseValue(CurRec);
- if (MHS == 0) return 0;
-
- if (Lex.getCode() != tgtok::comma) {
- TokError("expected ',' in ternary operator");
- return 0;
- }
- Lex.Lex(); // eat the ','
-
- Init *RHS = ParseValue(CurRec);
- if (RHS == 0) return 0;
-
- if (Lex.getCode() != tgtok::r_paren) {
- TokError("expected ')' in binary operator");
- return 0;
- }
- Lex.Lex(); // eat the ')'
-
- switch (LexCode) {
- default: assert(0 && "Unhandled code!");
- case tgtok::XIf: {
- // FIXME: The `!if' operator doesn't handle non-TypedInit well at
- // all. This can be made much more robust.
- TypedInit *MHSt = dynamic_cast<TypedInit*>(MHS);
- TypedInit *RHSt = dynamic_cast<TypedInit*>(RHS);
-
- RecTy *MHSTy = 0;
- RecTy *RHSTy = 0;
-
- if (MHSt == 0 && RHSt == 0) {
- BitsInit *MHSbits = dynamic_cast<BitsInit*>(MHS);
- BitsInit *RHSbits = dynamic_cast<BitsInit*>(RHS);
-
- if (MHSbits && RHSbits &&
- MHSbits->getNumBits() == RHSbits->getNumBits()) {
- Type = new BitRecTy();
- break;
- } else {
- BitInit *MHSbit = dynamic_cast<BitInit*>(MHS);
- BitInit *RHSbit = dynamic_cast<BitInit*>(RHS);
-
- if (MHSbit && RHSbit) {
- Type = new BitRecTy();
- break;
- }
- }
- } else if (MHSt != 0 && RHSt != 0) {
- MHSTy = MHSt->getType();
- RHSTy = RHSt->getType();
- }
-
- if (!MHSTy || !RHSTy) {
- TokError("could not get type for !if");
- return 0;
- }
-
- if (MHSTy->typeIsConvertibleTo(RHSTy)) {
- Type = RHSTy;
- } else if (RHSTy->typeIsConvertibleTo(MHSTy)) {
- Type = MHSTy;
- } else {
- TokError("inconsistent types for !if");
- return 0;
- }
- break;
- }
- case tgtok::XForEach: {
- TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS);
- if (MHSt == 0) {
- TokError("could not get type for !foreach");
- return 0;
- }
- Type = MHSt->getType();
- break;
- }
- case tgtok::XSubst: {
- TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS);
- if (RHSt == 0) {
- TokError("could not get type for !subst");
- return 0;
- }
- Type = RHSt->getType();
- break;
- }
- }
- return (new TernOpInit(Code, LHS, MHS, RHS, Type))->Fold(CurRec,
- CurMultiClass);
- }
- }
- TokError("could not parse operation");
- return 0;
-}
-
-/// ParseOperatorType - Parse a type for an operator. This returns
-/// null on error.
-///
-/// OperatorType ::= '<' Type '>'
-///
-RecTy *TGParser::ParseOperatorType() {
- RecTy *Type = 0;
-
- if (Lex.getCode() != tgtok::less) {
- TokError("expected type name for operator");
- return 0;
- }
- Lex.Lex(); // eat the <
-
- Type = ParseType();
-
- if (Type == 0) {
- TokError("expected type name for operator");
- return 0;
- }
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected type name for operator");
- return 0;
- }
- Lex.Lex(); // eat the >
-
- return Type;
-}
-
-
-/// ParseSimpleValue - Parse a tblgen value. This returns null on error.
-///
-/// SimpleValue ::= IDValue
-/// SimpleValue ::= INTVAL
-/// SimpleValue ::= STRVAL+
-/// SimpleValue ::= CODEFRAGMENT
-/// SimpleValue ::= '?'
-/// SimpleValue ::= '{' ValueList '}'
-/// SimpleValue ::= ID '<' ValueListNE '>'
-/// SimpleValue ::= '[' ValueList ']'
-/// SimpleValue ::= '(' IDValue DagArgList ')'
-/// SimpleValue ::= CONCATTOK '(' Value ',' Value ')'
-/// SimpleValue ::= SHLTOK '(' Value ',' Value ')'
-/// SimpleValue ::= SRATOK '(' Value ',' Value ')'
-/// SimpleValue ::= SRLTOK '(' Value ',' Value ')'
-/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
-///
-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::StrVal: {
- std::string Val = Lex.getCurStrVal();
- Lex.Lex();
-
- // Handle multiple consecutive concatenated strings.
- while (Lex.getCode() == tgtok::StrVal) {
- Val += Lex.getCurStrVal();
- Lex.Lex();
- }
-
- R = new StringInit(Val);
- break;
- }
- case tgtok::CodeFragment:
- R = new CodeInit(Lex.getCurStrVal());
- Lex.Lex();
- break;
- case tgtok::question:
- R = new UnsetInit();
- Lex.Lex();
- break;
- case tgtok::Id: {
- SMLoc NameLoc = Lex.getLoc();
- std::string Name = Lex.getCurStrVal();
- if (Lex.Lex() != tgtok::less) // consume the Id.
- return ParseIDValue(CurRec, Name, NameLoc); // Value ::= IDValue
-
- // Value ::= ID '<' ValueListNE '>'
- if (Lex.Lex() == tgtok::greater) {
- TokError("expected non-empty value list");
- return 0;
- }
-
- // This is a CLASS<initvalslist> expression. This is supposed to synthesize
- // a new anonymous definition, deriving from CLASS<initvalslist> with no
- // body.
- Record *Class = Records.getClass(Name);
- if (!Class) {
- Error(NameLoc, "Expected a class name, got '" + Name + "'");
- return 0;
- }
-
- std::vector<Init*> ValueList = ParseValueList(CurRec, Class);
- if (ValueList.empty()) return 0;
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' at end of value list");
- return 0;
- }
- Lex.Lex(); // eat the '>'
-
- // Create the new record, set it as CurRec temporarily.
- static unsigned AnonCounter = 0;
- Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++),
- NameLoc,
- Records);
- SubClassReference SCRef;
- SCRef.RefLoc = NameLoc;
- SCRef.Rec = Class;
- SCRef.TemplateArgs = ValueList;
- // Add info about the subclass to NewRec.
- if (AddSubClass(NewRec, SCRef))
- return 0;
- NewRec->resolveReferences();
- Records.addDef(NewRec);
-
- // The result of the expression is a reference to the new record.
- return new DefInit(NewRec);
- }
- case tgtok::l_brace: { // Value ::= '{' ValueList '}'
- SMLoc BraceLoc = Lex.getLoc();
- Lex.Lex(); // eat the '{'
- std::vector<Init*> Vals;
-
- if (Lex.getCode() != tgtok::r_brace) {
- Vals = ParseValueList(CurRec);
- if (Vals.empty()) return 0;
- }
- if (Lex.getCode() != tgtok::r_brace) {
- TokError("expected '}' at end of bit list value");
- return 0;
- }
- Lex.Lex(); // eat the '}'
-
- BitsInit *Result = new BitsInit(Vals.size());
- for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
- Init *Bit = Vals[i]->convertInitializerTo(new BitRecTy());
- 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);
- }
- return Result;
- }
- case tgtok::l_square: { // Value ::= '[' ValueList ']'
- Lex.Lex(); // eat the '['
- std::vector<Init*> Vals;
-
- RecTy *DeducedEltTy = 0;
- ListRecTy *GivenListTy = 0;
-
- if (ItemType != 0) {
- ListRecTy *ListType = dynamic_cast<ListRecTy*>(ItemType);
- if (ListType == 0) {
- std::stringstream s;
- s << "Type mismatch for list, expected list type, got "
- << ItemType->getAsString();
- TokError(s.str());
- return 0;
- }
- GivenListTy = ListType;
- }
-
- if (Lex.getCode() != tgtok::r_square) {
- Vals = ParseValueList(CurRec, 0,
- GivenListTy ? GivenListTy->getElementType() : 0);
- if (Vals.empty()) return 0;
- }
- if (Lex.getCode() != tgtok::r_square) {
- TokError("expected ']' at end of list value");
- return 0;
- }
- Lex.Lex(); // eat the ']'
-
- RecTy *GivenEltTy = 0;
- if (Lex.getCode() == tgtok::less) {
- // Optional list element type
- Lex.Lex(); // eat the '<'
-
- GivenEltTy = ParseType();
- if (GivenEltTy == 0) {
- // Couldn't parse element type
- return 0;
- }
-
- if (Lex.getCode() != tgtok::greater) {
- TokError("expected '>' at end of list element type");
- return 0;
- }
- Lex.Lex(); // eat the '>'
- }
-
- // Check elements
- RecTy *EltTy = 0;
- for (std::vector<Init *>::iterator i = Vals.begin(), ie = Vals.end();
- i != ie;
- ++i) {
- TypedInit *TArg = dynamic_cast<TypedInit*>(*i);
- if (TArg == 0) {
- TokError("Untyped list element");
- return 0;
- }
- if (EltTy != 0) {
- EltTy = resolveTypes(EltTy, TArg->getType());
- if (EltTy == 0) {
- TokError("Incompatible types in list elements");
- return 0;
- }
- } else {
- EltTy = TArg->getType();
- }
- }
-
- if (GivenEltTy != 0) {
- if (EltTy != 0) {
- // Verify consistency
- if (!EltTy->typeIsConvertibleTo(GivenEltTy)) {
- TokError("Incompatible types in list elements");
- return 0;
- }
- }
- EltTy = GivenEltTy;
- }
-
- if (EltTy == 0) {
- if (ItemType == 0) {
- TokError("No type for list");
- return 0;
- }
- DeducedEltTy = GivenListTy->getElementType();
- } else {
- // Make sure the deduced type is compatible with the given type
- if (GivenListTy) {
- if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) {
- TokError("Element type mismatch for list");
- return 0;
- }
- }
- DeducedEltTy = EltTy;
- }
-
- return new ListInit(Vals, DeducedEltTy);
- }
- case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')'
- Lex.Lex(); // eat the '('
- if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast) {
- TokError("expected identifier in dag init");
- return 0;
- }
-
- Init *Operator = ParseValue(CurRec);
- if (Operator == 0) return 0;
-
- // If the operator name is present, parse it.
- std::string OperatorName;
- if (Lex.getCode() == tgtok::colon) {
- if (Lex.Lex() != tgtok::VarName) { // eat the ':'
- TokError("expected variable name in dag operator");
- return 0;
- }
- OperatorName = Lex.getCurStrVal();
- Lex.Lex(); // eat the VarName.
- }
-
- std::vector<std::pair<llvm::Init*, std::string> > DagArgs;
- if (Lex.getCode() != tgtok::r_paren) {
- DagArgs = ParseDagArgList(CurRec);
- if (DagArgs.empty()) return 0;
- }
-
- if (Lex.getCode() != tgtok::r_paren) {
- TokError("expected ')' in dag init");
- return 0;
- }
- Lex.Lex(); // eat the ')'
-
- return new DagInit(Operator, OperatorName, DagArgs);
- }
-
- case tgtok::XHead:
- case tgtok::XTail:
- case tgtok::XEmpty:
- case tgtok::XCast: // Value ::= !unop '(' Value ')'
- case tgtok::XConcat:
- case tgtok::XSRA:
- case tgtok::XSRL:
- case tgtok::XSHL:
- case tgtok::XEq:
- case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')'
- case tgtok::XIf:
- case tgtok::XForEach:
- case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')'
- return ParseOperation(CurRec);
- }
- }
-
- return R;
-}
-
-/// ParseValue - Parse a tblgen value. This returns null on error.
-///
-/// Value ::= SimpleValue ValueSuffix*
-/// ValueSuffix ::= '{' BitList '}'
-/// ValueSuffix ::= '[' BitList ']'
-/// ValueSuffix ::= '.' ID
-///
-Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) {
- Init *Result = ParseSimpleValue(CurRec, ItemType);
- if (Result == 0) return 0;
-
- // Parse the suffixes now if present.
- while (1) {
- switch (Lex.getCode()) {
- default: return Result;
- case tgtok::l_brace: {
- SMLoc CurlyLoc = Lex.getLoc();
- Lex.Lex(); // eat the '{'
- std::vector<unsigned> Ranges = ParseRangeList();
- if (Ranges.empty()) return 0;
-
- // Reverse the bitlist.
- std::reverse(Ranges.begin(), Ranges.end());
- Result = Result->convertInitializerBitRange(Ranges);
- if (Result == 0) {
- Error(CurlyLoc, "Invalid bit range for value");
- return 0;
- }
-
- // Eat the '}'.
- if (Lex.getCode() != tgtok::r_brace) {
- TokError("expected '}' at end of bit range list");
- return 0;
- }
- Lex.Lex();
- break;
- }
- case tgtok::l_square: {
- SMLoc SquareLoc = Lex.getLoc();
- Lex.Lex(); // eat the '['
- std::vector<unsigned> Ranges = ParseRangeList();
- if (Ranges.empty()) return 0;
-
- Result = Result->convertInitListSlice(Ranges);
- if (Result == 0) {
- Error(SquareLoc, "Invalid range for list slice");
- return 0;
- }
-
- // Eat the ']'.
- if (Lex.getCode() != tgtok::r_square) {
- TokError("expected ']' at end of list slice");
- return 0;
- }
- Lex.Lex();
- break;
- }
- case tgtok::period:
- if (Lex.Lex() != tgtok::Id) { // eat the .
- TokError("expected field identifier after '.'");
- return 0;
- }
- if (!Result->getFieldType(Lex.getCurStrVal())) {
- TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +
- Result->getAsString() + "'");
- return 0;
- }
- Result = new FieldInit(Result, Lex.getCurStrVal());
- Lex.Lex(); // eat field name
- break;
- }
- }
-}
-
-/// ParseDagArgList - Parse the argument list for a dag literal expression.
-///
-/// ParseDagArgList ::= Value (':' VARNAME)?
-/// ParseDagArgList ::= ParseDagArgList ',' Value (':' VARNAME)?
-std::vector<std::pair<llvm::Init*, std::string> >
-TGParser::ParseDagArgList(Record *CurRec) {
- std::vector<std::pair<llvm::Init*, std::string> > Result;
-
- while (1) {
- Init *Val = ParseValue(CurRec);
- if (Val == 0) return std::vector<std::pair<llvm::Init*, std::string> >();
-
- // If the variable name is present, add it.
- std::string VarName;
- if (Lex.getCode() == tgtok::colon) {
- if (Lex.Lex() != tgtok::VarName) { // eat the ':'
- TokError("expected variable name in dag literal");
- return std::vector<std::pair<llvm::Init*, std::string> >();
- }
- VarName = Lex.getCurStrVal();
- Lex.Lex(); // eat the VarName.
- }
-
- Result.push_back(std::make_pair(Val, VarName));
-
- if (Lex.getCode() != tgtok::comma) break;
- Lex.Lex(); // eat the ','
- }
-
- return Result;
-}
-
-
-/// ParseValueList - Parse a comma separated list of values, returning them as a
-/// vector. Note that this always expects to be able to parse at least one
-/// value. It returns an empty list if this is not possible.
-///
-/// ValueList ::= Value (',' Value)
-///
-std::vector<Init*> TGParser::ParseValueList(Record *CurRec, Record *ArgsRec,
- RecTy *EltTy) {
- std::vector<Init*> Result;
- RecTy *ItemType = EltTy;
- unsigned int ArgN = 0;
- if (ArgsRec != 0 && EltTy == 0) {
- const std::vector<std::string> &TArgs = ArgsRec->getTemplateArgs();
- const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]);
- assert(RV && "Template argument record not found??");
- ItemType = RV->getType();
- ++ArgN;
- }
- Result.push_back(ParseValue(CurRec, ItemType));
- if (Result.back() == 0) return std::vector<Init*>();
-
- while (Lex.getCode() == tgtok::comma) {
- Lex.Lex(); // Eat the comma
-
- if (ArgsRec != 0 && EltTy == 0) {
- const std::vector<std::string> &TArgs = ArgsRec->getTemplateArgs();
- if (ArgN >= TArgs.size()) {
- TokError("too many template arguments");
- return std::vector<Init*>();
- }
- const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]);
- assert(RV && "Template argument record not found??");
- ItemType = RV->getType();
- ++ArgN;
- }
- Result.push_back(ParseValue(CurRec, ItemType));
- if (Result.back() == 0) return std::vector<Init*>();
- }
-
- return Result;
-}
-
-
-/// ParseDeclaration - Read a declaration, returning the name of field ID, or an
-/// empty string on error. This can happen in a number of different context's,
-/// including within a def or in the template args for a def (which which case
-/// CurRec will be non-null) and within the template args for a multiclass (in
-/// which case CurRec will be null, but CurMultiClass will be set). This can
-/// also happen within a def that is within a multiclass, which will set both
-/// CurRec and CurMultiClass.
-///
-/// Declaration ::= FIELD? Type ID ('=' Value)?
-///
-std::string TGParser::ParseDeclaration(Record *CurRec,
- bool ParsingTemplateArgs) {
- // Read the field prefix if present.
- bool HasField = Lex.getCode() == tgtok::Field;
- if (HasField) Lex.Lex();
-
- RecTy *Type = ParseType();
- if (Type == 0) return "";
-
- if (Lex.getCode() != tgtok::Id) {
- TokError("Expected identifier in declaration");
- return "";
- }
-
- SMLoc IdLoc = Lex.getLoc();
- std::string DeclName = Lex.getCurStrVal();
- Lex.Lex();
-
- if (ParsingTemplateArgs) {
- if (CurRec) {
- DeclName = CurRec->getName() + ":" + DeclName;
- } else {
- assert(CurMultiClass);
- }
- if (CurMultiClass)
- DeclName = CurMultiClass->Rec.getName() + "::" + DeclName;
- }
-
- // Add the value.
- if (AddValue(CurRec, IdLoc, RecordVal(DeclName, Type, HasField)))
- return "";
-
- // If a value is present, parse it.
- if (Lex.getCode() == tgtok::equal) {
- Lex.Lex();
- SMLoc ValLoc = Lex.getLoc();
- Init *Val = ParseValue(CurRec, Type);
- if (Val == 0 ||
- SetValue(CurRec, ValLoc, DeclName, std::vector<unsigned>(), Val))
- return "";
- }
-
- return DeclName;
-}
-
-/// ParseTemplateArgList - Read a template argument list, which is a non-empty
-/// sequence of template-declarations in <>'s. If CurRec is non-null, these are
-/// template args for a def, which may or may not be in a multiclass. If null,
-/// these are the template args for a multiclass.
-///
-/// TemplateArgList ::= '<' Declaration (',' Declaration)* '>'
-///
-bool TGParser::ParseTemplateArgList(Record *CurRec) {
- assert(Lex.getCode() == tgtok::less && "Not a template arg list!");
- Lex.Lex(); // eat the '<'
-
- Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec;
-
- // Read the first declaration.
- std::string TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
- if (TemplArg.empty())
- return true;
-
- TheRecToAddTo->addTemplateArg(TemplArg);
-
- while (Lex.getCode() == tgtok::comma) {
- Lex.Lex(); // eat the ','
-
- // Read the following declarations.
- TemplArg = ParseDeclaration(CurRec, true/*templateargs*/);
- if (TemplArg.empty())
- return true;
- TheRecToAddTo->addTemplateArg(TemplArg);
- }
-
- if (Lex.getCode() != tgtok::greater)
- return TokError("expected '>' at end of template argument list");
- Lex.Lex(); // eat the '>'.
- return false;
-}
-
-
-/// ParseBodyItem - Parse a single item at within the body of a def or class.
-///
-/// BodyItem ::= Declaration ';'
-/// BodyItem ::= LET ID OptionalBitList '=' Value ';'
-bool TGParser::ParseBodyItem(Record *CurRec) {
- if (Lex.getCode() != tgtok::Let) {
- if (ParseDeclaration(CurRec, false).empty())
- return true;
-
- if (Lex.getCode() != tgtok::semi)
- return TokError("expected ';' after declaration");
- Lex.Lex();
- return false;
- }
-
- // LET ID OptionalRangeList '=' Value ';'
- if (Lex.Lex() != tgtok::Id)
- return TokError("expected field identifier after let");
-
- SMLoc IdLoc = Lex.getLoc();
- std::string FieldName = Lex.getCurStrVal();
- Lex.Lex(); // eat the field name.
-
- std::vector<unsigned> BitList;
- if (ParseOptionalBitList(BitList))
- return true;
- std::reverse(BitList.begin(), BitList.end());
-
- if (Lex.getCode() != tgtok::equal)
- return TokError("expected '=' in let expression");
- Lex.Lex(); // eat the '='.
-
- RecordVal *Field = CurRec->getValue(FieldName);
- if (Field == 0)
- return TokError("Value '" + FieldName + "' unknown!");
-
- RecTy *Type = Field->getType();
-
- Init *Val = ParseValue(CurRec, Type);
- if (Val == 0) return true;
-
- if (Lex.getCode() != tgtok::semi)
- return TokError("expected ';' after let expression");
- Lex.Lex();
-
- return SetValue(CurRec, IdLoc, FieldName, BitList, Val);
-}
-
-/// ParseBody - Read the body of a class or def. Return true on error, false on
-/// success.
-///
-/// Body ::= ';'
-/// Body ::= '{' BodyList '}'
-/// BodyList BodyItem*
-///
-bool TGParser::ParseBody(Record *CurRec) {
- // If this is a null definition, just eat the semi and return.
- if (Lex.getCode() == tgtok::semi) {
- Lex.Lex();
- return false;
- }
-
- if (Lex.getCode() != tgtok::l_brace)
- return TokError("Expected ';' or '{' to start body");
- // Eat the '{'.
- Lex.Lex();
-
- while (Lex.getCode() != tgtok::r_brace)
- if (ParseBodyItem(CurRec))
- return true;
-
- // Eat the '}'.
- Lex.Lex();
- return false;
-}
-
-/// ParseObjectBody - Parse the body of a def or class. This consists of an
-/// optional ClassList followed by a Body. CurRec is the current def or class
-/// that is being parsed.
-///
-/// ObjectBody ::= BaseClassList Body
-/// BaseClassList ::= /*empty*/
-/// BaseClassList ::= ':' BaseClassListNE
-/// BaseClassListNE ::= SubClassRef (',' SubClassRef)*
-///
-bool TGParser::ParseObjectBody(Record *CurRec) {
- // If there is a baseclass list, read it.
- if (Lex.getCode() == tgtok::colon) {
- Lex.Lex();
-
- // Read all of the subclasses.
- SubClassReference SubClass = ParseSubClassReference(CurRec, false);
- while (1) {
- // Check for error.
- if (SubClass.Rec == 0) return true;
-
- // Add it.
- if (AddSubClass(CurRec, SubClass))
- return true;
-
- if (Lex.getCode() != tgtok::comma) break;
- Lex.Lex(); // eat ','.
- SubClass = ParseSubClassReference(CurRec, false);
- }
- }
-
- // Process any variables on the let stack.
- 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 true;
-
- return ParseBody(CurRec);
-}
-
-/// ParseDef - Parse and return a top level or multiclass def, return the record
-/// corresponding to it. This returns null on error.
-///
-/// DefInst ::= DEF ObjectName ObjectBody
-///
-bool TGParser::ParseDef(MultiClass *CurMultiClass) {
- SMLoc DefLoc = Lex.getLoc();
- assert(Lex.getCode() == tgtok::Def && "Unknown tok");
- Lex.Lex(); // Eat the 'def' token.
-
- // Parse ObjectName and make a record for it.
- Record *CurRec = new Record(ParseObjectName(), DefLoc, Records);
-
- if (!CurMultiClass) {
- // Top-level def definition.
-
- // Ensure redefinition doesn't happen.
- if (Records.getDef(CurRec->getName())) {
- Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
- return true;
- }
- Records.addDef(CurRec);
- } else {
- // Otherwise, a def inside a multiclass, add it to the multiclass.
- for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); i != e; ++i)
- if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
- Error(DefLoc, "def '" + CurRec->getName() +
- "' already defined in this multiclass!");
- return true;
- }
- CurMultiClass->DefPrototypes.push_back(CurRec);
- }
-
- if (ParseObjectBody(CurRec))
- return true;
-
- if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
- CurRec->resolveReferences();
-
- // If ObjectBody has template arguments, it's an error.
- assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
-
- if (CurMultiClass) {
- // Copy the template arguments for the multiclass into the def.
- const std::vector<std::string> &TArgs =
- CurMultiClass->Rec.getTemplateArgs();
-
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
- assert(RV && "Template arg doesn't exist?");
- CurRec->addValue(*RV);
- }
- }
-
- return false;
-}
-
-
-/// ParseClass - Parse a tblgen class definition.
-///
-/// ClassInst ::= CLASS ID TemplateArgList? ObjectBody
-///
-bool TGParser::ParseClass() {
- assert(Lex.getCode() == tgtok::Class && "Unexpected token!");
- Lex.Lex();
-
- if (Lex.getCode() != tgtok::Id)
- return TokError("expected class name after 'class' keyword");
-
- Record *CurRec = Records.getClass(Lex.getCurStrVal());
- if (CurRec) {
- // If the body was previously defined, this is an error.
- if (!CurRec->getValues().empty() ||
- !CurRec->getSuperClasses().empty() ||
- !CurRec->getTemplateArgs().empty())
- return TokError("Class '" + CurRec->getName() + "' already defined");
- } else {
- // If this is the first reference to this class, create and add it.
- CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc(), Records);
- Records.addClass(CurRec);
- }
- Lex.Lex(); // eat the name.
-
- // If there are template args, parse them.
- if (Lex.getCode() == tgtok::less)
- if (ParseTemplateArgList(CurRec))
- return true;
-
- // Finally, parse the object body.
- return ParseObjectBody(CurRec);
-}
-
-/// ParseLetList - Parse a non-empty list of assignment expressions into a list
-/// of LetRecords.
-///
-/// LetList ::= LetItem (',' LetItem)*
-/// LetItem ::= ID OptionalRangeList '=' Value
-///
-std::vector<LetRecord> TGParser::ParseLetList() {
- std::vector<LetRecord> Result;
-
- while (1) {
- if (Lex.getCode() != tgtok::Id) {
- TokError("expected identifier in let definition");
- return std::vector<LetRecord>();
- }
- std::string Name = Lex.getCurStrVal();
- SMLoc NameLoc = Lex.getLoc();
- Lex.Lex(); // Eat the identifier.
-
- // Check for an optional RangeList.
- std::vector<unsigned> Bits;
- if (ParseOptionalRangeList(Bits))
- return std::vector<LetRecord>();
- std::reverse(Bits.begin(), Bits.end());
-
- if (Lex.getCode() != tgtok::equal) {
- TokError("expected '=' in let expression");
- return std::vector<LetRecord>();
- }
- Lex.Lex(); // eat the '='.
-
- Init *Val = ParseValue(0);
- if (Val == 0) return std::vector<LetRecord>();
-
- // Now that we have everything, add the record.
- Result.push_back(LetRecord(Name, Bits, Val, NameLoc));
-
- if (Lex.getCode() != tgtok::comma)
- return Result;
- Lex.Lex(); // eat the comma.
- }
-}
-
-/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
-/// different related productions. This works inside multiclasses too.
-///
-/// Object ::= LET LetList IN '{' ObjectList '}'
-/// Object ::= LET LetList IN Object
-///
-bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
- assert(Lex.getCode() == tgtok::Let && "Unexpected token");
- Lex.Lex();
-
- // Add this entry to the let stack.
- std::vector<LetRecord> LetInfo = ParseLetList();
- if (LetInfo.empty()) return true;
- LetStack.push_back(LetInfo);
-
- if (Lex.getCode() != tgtok::In)
- return TokError("expected 'in' at end of top-level 'let'");
- Lex.Lex();
-
- // If this is a scalar let, just handle it now
- if (Lex.getCode() != tgtok::l_brace) {
- // LET LetList IN Object
- if (ParseObject(CurMultiClass))
- return true;
- } else { // Object ::= LETCommand '{' ObjectList '}'
- SMLoc BraceLoc = Lex.getLoc();
- // Otherwise, this is a group let.
- Lex.Lex(); // eat the '{'.
-
- // Parse the object list.
- if (ParseObjectList(CurMultiClass))
- return true;
-
- if (Lex.getCode() != tgtok::r_brace) {
- TokError("expected '}' at end of top level let command");
- return Error(BraceLoc, "to match this '{'");
- }
- Lex.Lex();
- }
-
- // Outside this let scope, this let block is not active.
- LetStack.pop_back();
- return false;
-}
-
-/// ParseMultiClass - Parse a multiclass definition.
-///
-/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
-/// ':' BaseMultiClassList '{' MultiClassDef+ '}'
-///
-bool TGParser::ParseMultiClass() {
- assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
- Lex.Lex(); // Eat the multiclass token.
-
- if (Lex.getCode() != tgtok::Id)
- return TokError("expected identifier after multiclass for name");
- std::string Name = Lex.getCurStrVal();
-
- if (MultiClasses.count(Name))
- return TokError("multiclass '" + Name + "' already defined");
-
- CurMultiClass = MultiClasses[Name] = new MultiClass(Name,
- Lex.getLoc(), Records);
- Lex.Lex(); // Eat the identifier.
-
- // If there are template args, parse them.
- if (Lex.getCode() == tgtok::less)
- if (ParseTemplateArgList(0))
- return true;
-
- bool inherits = false;
-
- // If there are submulticlasses, parse them.
- if (Lex.getCode() == tgtok::colon) {
- inherits = true;
-
- Lex.Lex();
-
- // Read all of the submulticlasses.
- SubMultiClassReference SubMultiClass =
- ParseSubMultiClassReference(CurMultiClass);
- while (1) {
- // Check for error.
- if (SubMultiClass.MC == 0) return true;
-
- // Add it.
- if (AddSubMultiClass(CurMultiClass, SubMultiClass))
- return true;
-
- if (Lex.getCode() != tgtok::comma) break;
- Lex.Lex(); // eat ','.
- SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
- }
- }
-
- if (Lex.getCode() != tgtok::l_brace) {
- if (!inherits)
- return TokError("expected '{' in multiclass definition");
- else if (Lex.getCode() != tgtok::semi)
- return TokError("expected ';' in multiclass definition");
- else
- Lex.Lex(); // eat the ';'.
- } else {
- if (Lex.Lex() == tgtok::r_brace) // eat the '{'.
- return TokError("multiclass must contain at least one def");
-
- while (Lex.getCode() != tgtok::r_brace) {
- switch (Lex.getCode()) {
- default:
- return TokError("expected 'let', 'def' or 'defm' in multiclass body");
- case tgtok::Let:
- case tgtok::Def:
- case tgtok::Defm:
- if (ParseObject(CurMultiClass))
- return true;
- break;
- }
- }
- Lex.Lex(); // eat the '}'.
- }
-
- CurMultiClass = 0;
- return false;
-}
-
-/// ParseDefm - Parse the instantiation of a multiclass.
-///
-/// DefMInst ::= DEFM ID ':' DefmSubClassRef ';'
-///
-bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
- assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");
-
- std::string DefmPrefix;
- if (Lex.Lex() == tgtok::Id) { // eat the defm.
- DefmPrefix = Lex.getCurStrVal();
- Lex.Lex(); // Eat the defm prefix.
- }
-
- SMLoc DefmPrefixLoc = Lex.getLoc();
- if (Lex.getCode() != tgtok::colon)
- return TokError("expected ':' after defm identifier");
-
- // Keep track of the new generated record definitions.
- std::vector<Record*> NewRecDefs;
-
- // This record also inherits from a regular class (non-multiclass)?
- bool InheritFromClass = false;
-
- // eat the colon.
- Lex.Lex();
-
- SMLoc SubClassLoc = Lex.getLoc();
- SubClassReference Ref = ParseSubClassReference(0, true);
-
- while (1) {
- if (Ref.Rec == 0) return true;
-
- // To instantiate a multiclass, we need to first get the multiclass, then
- // instantiate each def contained in the multiclass with the SubClassRef
- // template parameters.
- MultiClass *MC = MultiClasses[Ref.Rec->getName()];
- assert(MC && "Didn't lookup multiclass correctly?");
- std::vector<Init*> &TemplateVals = Ref.TemplateArgs;
-
- // Verify that the correct number of template arguments were specified.
- const std::vector<std::string> &TArgs = MC->Rec.getTemplateArgs();
- if (TArgs.size() < TemplateVals.size())
- return Error(SubClassLoc,
- "more template args specified than multiclass expects");
-
- // Loop over all the def's in the multiclass, instantiating each one.
- 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 = 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<unsigned>(),
- TemplateVals[i]))
- return true;
-
- // 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<std::string> &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);
- }
-
- NewRecDefs.push_back(CurRec);
- }
-
- if (Lex.getCode() != tgtok::comma) break;
- Lex.Lex(); // eat ','.
-
- SubClassLoc = Lex.getLoc();
-
- // A defm can inherit from regular classes (non-multiclass) as
- // long as they come in the end of the inheritance list.
- InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != 0);
-
- if (InheritFromClass)
- break;
-
- Ref = ParseSubClassReference(0, true);
- }
-
- if (InheritFromClass) {
- // Process all the classes to inherit as if they were part of a
- // regular 'def' and inherit all record values.
- SubClassReference SubClass = ParseSubClassReference(0, false);
- while (1) {
- // Check for error.
- if (SubClass.Rec == 0) return true;
-
- // Get the expanded definition prototypes and teach them about
- // the record values the current class to inherit has
- for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) {
- Record *CurRec = NewRecDefs[i];
-
- // Add it.
- if (AddSubClass(CurRec, SubClass))
- return true;
-
- // Process any variables on the let stack.
- 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 true;
- }
-
- if (Lex.getCode() != tgtok::comma) break;
- Lex.Lex(); // eat ','.
- SubClass = ParseSubClassReference(0, false);
- }
- }
-
- if (!CurMultiClass)
- for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i)
- NewRecDefs[i]->resolveReferences();
-
- if (Lex.getCode() != tgtok::semi)
- return TokError("expected ';' at end of defm");
- Lex.Lex();
-
- return false;
-}
-
-/// ParseObject
-/// Object ::= ClassInst
-/// Object ::= DefInst
-/// Object ::= MultiClassInst
-/// Object ::= DefMInst
-/// Object ::= LETCommand '{' ObjectList '}'
-/// Object ::= LETCommand Object
-bool TGParser::ParseObject(MultiClass *MC) {
- switch (Lex.getCode()) {
- default:
- return TokError("Expected class, def, defm, multiclass or let definition");
- case tgtok::Let: return ParseTopLevelLet(MC);
- case tgtok::Def: return ParseDef(MC);
- case tgtok::Defm: return ParseDefm(MC);
- case tgtok::Class: return ParseClass();
- case tgtok::MultiClass: return ParseMultiClass();
- }
-}
-
-/// ParseObjectList
-/// ObjectList :== Object*
-bool TGParser::ParseObjectList(MultiClass *MC) {
- while (isObjectStart(Lex.getCode())) {
- if (ParseObject(MC))
- return true;
- }
- return false;
-}
-
-bool TGParser::ParseFile() {
- Lex.Lex(); // Prime the lexer.
- if (ParseObjectList()) return true;
-
- // If we have unread input at the end of the file, report it.
- if (Lex.getCode() == tgtok::Eof)
- return false;
-
- return TokError("Unexpected input at top level");
-}
-
diff --git a/utils/TableGen/TGParser.h b/utils/TableGen/TGParser.h
deleted file mode 100644
index dce7e1d..0000000
--- a/utils/TableGen/TGParser.h
+++ /dev/null
@@ -1,122 +0,0 @@
-//===- TGParser.h - Parser for TableGen Files -------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class represents the Parser for tablegen files.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef TGPARSER_H
-#define TGPARSER_H
-
-#include "TGLexer.h"
-#include "Error.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/SourceMgr.h"
-#include <map>
-
-namespace llvm {
- class Record;
- class RecordVal;
- class RecordKeeper;
- struct RecTy;
- class Init;
- struct MultiClass;
- struct SubClassReference;
- struct SubMultiClassReference;
-
- struct LetRecord {
- std::string Name;
- std::vector<unsigned> Bits;
- Init *Value;
- SMLoc Loc;
- LetRecord(const std::string &N, const std::vector<unsigned> &B, Init *V,
- SMLoc L)
- : Name(N), Bits(B), Value(V), Loc(L) {
- }
- };
-
-class TGParser {
- TGLexer Lex;
- std::vector<std::vector<LetRecord> > LetStack;
- std::map<std::string, MultiClass*> MultiClasses;
-
- /// CurMultiClass - If we are parsing a 'multiclass' definition, this is the
- /// current value.
- MultiClass *CurMultiClass;
-
- // Record tracker
- RecordKeeper &Records;
-public:
- TGParser(SourceMgr &SrcMgr, RecordKeeper &records) :
- Lex(SrcMgr), CurMultiClass(0), Records(records) {}
-
- /// ParseFile - Main entrypoint for parsing a tblgen file. These parser
- /// routines return true on error, or false on success.
- bool ParseFile();
-
- bool Error(SMLoc L, const Twine &Msg) const {
- PrintError(L, Msg);
- return true;
- }
- bool TokError(const Twine &Msg) const {
- return Error(Lex.getLoc(), Msg);
- }
- const std::vector<std::string> &getDependencies() const {
- return Lex.getDependencies();
- }
-private: // Semantic analysis methods.
- bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV);
- bool SetValue(Record *TheRec, SMLoc Loc, const std::string &ValName,
- const std::vector<unsigned> &BitList, Init *V);
- bool AddSubClass(Record *Rec, SubClassReference &SubClass);
- bool AddSubMultiClass(MultiClass *CurMC,
- SubMultiClassReference &SubMultiClass);
-
-private: // Parser methods.
- bool ParseObjectList(MultiClass *MC = 0);
- bool ParseObject(MultiClass *MC);
- bool ParseClass();
- bool ParseMultiClass();
- bool ParseDefm(MultiClass *CurMultiClass);
- bool ParseDef(MultiClass *CurMultiClass);
- bool ParseTopLevelLet(MultiClass *CurMultiClass);
- std::vector<LetRecord> ParseLetList();
-
- bool ParseObjectBody(Record *CurRec);
- bool ParseBody(Record *CurRec);
- bool ParseBodyItem(Record *CurRec);
-
- bool ParseTemplateArgList(Record *CurRec);
- std::string ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
-
- SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
- SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMC);
-
- Init *ParseIDValue(Record *CurRec);
- Init *ParseIDValue(Record *CurRec, const std::string &Name, SMLoc NameLoc);
- Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = 0);
- Init *ParseValue(Record *CurRec, RecTy *ItemType = 0);
- std::vector<Init*> ParseValueList(Record *CurRec, Record *ArgsRec = 0, RecTy *EltTy = 0);
- std::vector<std::pair<llvm::Init*, std::string> > ParseDagArgList(Record *);
- bool ParseOptionalRangeList(std::vector<unsigned> &Ranges);
- bool ParseOptionalBitList(std::vector<unsigned> &Ranges);
- std::vector<unsigned> ParseRangeList();
- bool ParseRangePiece(std::vector<unsigned> &Ranges);
- RecTy *ParseType();
- Init *ParseOperation(Record *CurRec);
- RecTy *ParseOperatorType();
- std::string ParseObjectName();
- Record *ParseClassID();
- MultiClass *ParseMultiClassID();
- Record *ParseDefmID();
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index e8eacb8..eacfdf6 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -1,4 +1,4 @@
-//===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
+//===- TableGen.cpp - Top-Level TableGen implementation for LLVM ----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,48 +7,34 @@
//
//===----------------------------------------------------------------------===//
//
-// 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.
+// This file contains the main function for LLVM's TableGen.
//
//===----------------------------------------------------------------------===//
#include "AsmMatcherEmitter.h"
#include "AsmWriterEmitter.h"
#include "CallingConvEmitter.h"
-#include "ClangASTNodesEmitter.h"
-#include "ClangAttrEmitter.h"
-#include "ClangDiagnosticsEmitter.h"
-#include "ClangSACheckersEmitter.h"
#include "CodeEmitterGen.h"
#include "DAGISelEmitter.h"
#include "DisassemblerEmitter.h"
#include "EDEmitter.h"
-#include "Error.h"
#include "FastISelEmitter.h"
#include "InstrInfoEmitter.h"
#include "IntrinsicEmitter.h"
-#include "LLVMCConfigurationEmitter.h"
-#include "NeonEmitter.h"
-#include "OptParserEmitter.h"
#include "PseudoLoweringEmitter.h"
-#include "Record.h"
#include "RegisterInfoEmitter.h"
#include "ARMDecoderEmitter.h"
#include "SubtargetEmitter.h"
#include "SetTheory.h"
-#include "TGParser.h"
-#include "llvm/ADT/OwningPtr.h"
+
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/Signals.h"
-#include "llvm/Support/system_error.h"
-#include <algorithm>
-#include <cstdio>
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Main.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenAction.h"
+
using namespace llvm;
enum ActionType {
@@ -62,29 +48,12 @@ enum ActionType {
GenDisassembler,
GenPseudoLowering,
GenCallingConv,
- GenClangAttrClasses,
- GenClangAttrImpl,
- GenClangAttrList,
- GenClangAttrPCHRead,
- GenClangAttrPCHWrite,
- GenClangAttrSpellingList,
- GenClangDiagsDefs,
- GenClangDiagGroups,
- GenClangDiagsIndexName,
- GenClangDeclNodes,
- GenClangStmtNodes,
- GenClangSACheckers,
GenDAGISel,
GenFastISel,
- GenOptParserDefs, GenOptParserImpl,
GenSubtarget,
GenIntrinsic,
GenTgtIntrinsic,
- GenLLVMCConf,
GenEDInfo,
- GenArmNeon,
- GenArmNeonSema,
- GenArmNeonTest,
PrintEnums,
PrintSets
};
@@ -116,52 +85,14 @@ namespace {
"Generate a DAG instruction selector"),
clEnumValN(GenFastISel, "gen-fast-isel",
"Generate a \"fast\" instruction selector"),
- clEnumValN(GenOptParserDefs, "gen-opt-parser-defs",
- "Generate option definitions"),
- clEnumValN(GenOptParserImpl, "gen-opt-parser-impl",
- "Generate option parser implementation"),
clEnumValN(GenSubtarget, "gen-subtarget",
"Generate subtarget enumerations"),
clEnumValN(GenIntrinsic, "gen-intrinsic",
"Generate intrinsic information"),
clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic",
"Generate target intrinsic information"),
- clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
- "Generate clang attribute clases"),
- clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl",
- "Generate clang attribute implementations"),
- clEnumValN(GenClangAttrList, "gen-clang-attr-list",
- "Generate a clang attribute list"),
- clEnumValN(GenClangAttrPCHRead, "gen-clang-attr-pch-read",
- "Generate clang PCH attribute reader"),
- clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write",
- "Generate clang PCH attribute writer"),
- clEnumValN(GenClangAttrSpellingList,
- "gen-clang-attr-spelling-list",
- "Generate a clang attribute spelling list"),
- clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
- "Generate Clang diagnostics definitions"),
- clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
- "Generate Clang diagnostic groups"),
- clEnumValN(GenClangDiagsIndexName,
- "gen-clang-diags-index-name",
- "Generate Clang diagnostic name index"),
- clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes",
- "Generate Clang AST declaration nodes"),
- clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
- "Generate Clang AST statement nodes"),
- clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
- "Generate Clang Static Analyzer checkers"),
- clEnumValN(GenLLVMCConf, "gen-llvmc",
- "Generate LLVMC configuration library"),
clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info",
"Generate enhanced disassembly info"),
- clEnumValN(GenArmNeon, "gen-arm-neon",
- "Generate arm_neon.h for clang"),
- clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
- "Generate ARM NEON sema support for clang"),
- clEnumValN(GenArmNeonTest, "gen-arm-neon-test",
- "Generate ARM NEON tests for clang"),
clEnumValN(PrintEnums, "print-enums",
"Print enum values for a class"),
clEnumValN(PrintSets, "print-sets",
@@ -171,198 +102,66 @@ namespace {
cl::opt<std::string>
Class("class", cl::desc("Print Enum list for this class"),
cl::value_desc("class name"));
-
- cl::opt<std::string>
- OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
- cl::init("-"));
-
- cl::opt<std::string>
- DependFilename("d", cl::desc("Dependency filename"), cl::value_desc("filename"),
- cl::init(""));
-
- cl::opt<std::string>
- InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
-
- cl::list<std::string>
- IncludeDirs("I", cl::desc("Directory of include files"),
- cl::value_desc("directory"), cl::Prefix);
-
- cl::opt<std::string>
- ClangComponent("clang-component",
- cl::desc("Only use warnings from specified component"),
- cl::value_desc("component"), cl::Hidden);
}
-
-int main(int argc, char **argv) {
- RecordKeeper Records;
-
- sys::PrintStackTraceOnErrorSignal();
- PrettyStackTraceProgram X(argc, argv);
- cl::ParseCommandLineOptions(argc, argv);
-
-
- try {
- // Parse the input file.
- OwningPtr<MemoryBuffer> 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() << argv[0] << ": error opening " << OutputFilename
- << ":" << Error << "\n";
- return 1;
- }
- if (!DependFilename.empty()) {
- if (OutputFilename == "-") {
- errs() << argv[0] << ": the option -d must be used together with -o\n";
- return 1;
- }
- tool_output_file DepOut(DependFilename.c_str(), Error);
- if (!Error.empty()) {
- errs() << argv[0] << ": error opening " << DependFilename
- << ":" << Error << "\n";
- return 1;
- }
- DepOut.os() << DependFilename << ":";
- const std::vector<std::string> &Dependencies = Parser.getDependencies();
- for (std::vector<std::string>::const_iterator I = Dependencies.begin(),
- E = Dependencies.end();
- I != E; ++I) {
- DepOut.os() << " " << (*I);
- }
- DepOut.os() << "\n";
- DepOut.keep();
- }
-
+class LLVMTableGenAction : public TableGenAction {
+public:
+ bool operator()(raw_ostream &OS, RecordKeeper &Records) {
switch (Action) {
case PrintRecords:
- Out.os() << Records; // No argument, dump all contents
+ OS << Records; // No argument, dump all contents
break;
case GenEmitter:
- CodeEmitterGen(Records).run(Out.os());
+ CodeEmitterGen(Records).run(OS);
break;
case GenRegisterInfo:
- RegisterInfoEmitter(Records).run(Out.os());
+ RegisterInfoEmitter(Records).run(OS);
break;
case GenInstrInfo:
- InstrInfoEmitter(Records).run(Out.os());
+ InstrInfoEmitter(Records).run(OS);
break;
case GenCallingConv:
- CallingConvEmitter(Records).run(Out.os());
+ CallingConvEmitter(Records).run(OS);
break;
case GenAsmWriter:
- AsmWriterEmitter(Records).run(Out.os());
+ AsmWriterEmitter(Records).run(OS);
break;
case GenARMDecoder:
- ARMDecoderEmitter(Records).run(Out.os());
+ ARMDecoderEmitter(Records).run(OS);
break;
case GenAsmMatcher:
- AsmMatcherEmitter(Records).run(Out.os());
- break;
- case GenClangAttrClasses:
- ClangAttrClassEmitter(Records).run(Out.os());
- break;
- case GenClangAttrImpl:
- ClangAttrImplEmitter(Records).run(Out.os());
- break;
- case GenClangAttrList:
- ClangAttrListEmitter(Records).run(Out.os());
- break;
- case GenClangAttrPCHRead:
- ClangAttrPCHReadEmitter(Records).run(Out.os());
- break;
- case GenClangAttrPCHWrite:
- ClangAttrPCHWriteEmitter(Records).run(Out.os());
- break;
- case GenClangAttrSpellingList:
- ClangAttrSpellingListEmitter(Records).run(Out.os());
- break;
- case GenClangDiagsDefs:
- ClangDiagsDefsEmitter(Records, ClangComponent).run(Out.os());
- break;
- case GenClangDiagGroups:
- ClangDiagGroupsEmitter(Records).run(Out.os());
- break;
- case GenClangDiagsIndexName:
- ClangDiagsIndexNameEmitter(Records).run(Out.os());
- break;
- case GenClangDeclNodes:
- ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out.os());
- ClangDeclContextEmitter(Records).run(Out.os());
- break;
- case GenClangStmtNodes:
- ClangASTNodesEmitter(Records, "Stmt", "").run(Out.os());
- break;
- case GenClangSACheckers:
- ClangSACheckersEmitter(Records).run(Out.os());
+ AsmMatcherEmitter(Records).run(OS);
break;
case GenDisassembler:
- DisassemblerEmitter(Records).run(Out.os());
+ DisassemblerEmitter(Records).run(OS);
break;
case GenPseudoLowering:
- PseudoLoweringEmitter(Records).run(Out.os());
- break;
- case GenOptParserDefs:
- OptParserEmitter(Records, true).run(Out.os());
- break;
- case GenOptParserImpl:
- OptParserEmitter(Records, false).run(Out.os());
+ PseudoLoweringEmitter(Records).run(OS);
break;
case GenDAGISel:
- DAGISelEmitter(Records).run(Out.os());
+ DAGISelEmitter(Records).run(OS);
break;
case GenFastISel:
- FastISelEmitter(Records).run(Out.os());
+ FastISelEmitter(Records).run(OS);
break;
case GenSubtarget:
- SubtargetEmitter(Records).run(Out.os());
+ SubtargetEmitter(Records).run(OS);
break;
case GenIntrinsic:
- IntrinsicEmitter(Records).run(Out.os());
+ IntrinsicEmitter(Records).run(OS);
break;
case GenTgtIntrinsic:
- IntrinsicEmitter(Records, true).run(Out.os());
- break;
- case GenLLVMCConf:
- LLVMCConfigurationEmitter(Records).run(Out.os());
+ IntrinsicEmitter(Records, true).run(OS);
break;
case GenEDInfo:
- EDEmitter(Records).run(Out.os());
- break;
- case GenArmNeon:
- NeonEmitter(Records).run(Out.os());
- break;
- case GenArmNeonSema:
- NeonEmitter(Records).runHeader(Out.os());
- break;
- case GenArmNeonTest:
- NeonEmitter(Records).runTests(Out.os());
+ EDEmitter(Records).run(OS);
break;
case PrintEnums:
{
std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
for (unsigned i = 0, e = Recs.size(); i != e; ++i)
- Out.os() << Recs[i]->getName() << ", ";
- Out.os() << "\n";
+ OS << Recs[i]->getName() << ", ";
+ OS << "\n";
break;
}
case PrintSets:
@@ -371,33 +170,29 @@ int main(int argc, char **argv) {
Sets.addFieldExpander("Set", "Elements");
std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Set");
for (unsigned i = 0, e = Recs.size(); i != e; ++i) {
- Out.os() << Recs[i]->getName() << " = [";
+ OS << Recs[i]->getName() << " = [";
const std::vector<Record*> *Elts = Sets.expand(Recs[i]);
assert(Elts && "Couldn't expand Set instance");
for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei)
- Out.os() << ' ' << (*Elts)[ei]->getName();
- Out.os() << " ]\n";
+ OS << ' ' << (*Elts)[ei]->getName();
+ OS << " ]\n";
}
break;
}
default:
assert(1 && "Invalid Action");
- return 1;
+ return true;
}
- // 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() << argv[0] << ": Unknown unexpected exception occurred.\n";
+ return false;
}
+};
+
+int main(int argc, char **argv) {
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ cl::ParseCommandLineOptions(argc, argv);
- return 1;
+ LLVMTableGenAction Action;
+ return TableGenMain(argv[0], Action);
}
diff --git a/utils/TableGen/TableGenBackend.cpp b/utils/TableGen/TableGenBackend.cpp
deleted file mode 100644
index b3e33b5..0000000
--- a/utils/TableGen/TableGenBackend.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- TableGenBackend.cpp - Base class for TableGen Backends ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides useful services for TableGen backends...
-//
-//===----------------------------------------------------------------------===//
-
-#include "TableGenBackend.h"
-#include "Record.h"
-using namespace llvm;
-
-void TableGenBackend::EmitSourceFileHeader(const std::string &Desc,
- raw_ostream &OS) const {
- OS << "//===- TableGen'erated file -------------------------------------*-"
- " C++ -*-===//\n//\n// " << Desc << "\n//\n// Automatically generate"
- "d file, do not edit!\n//\n//===------------------------------------"
- "----------------------------------===//\n\n";
-}
-
diff --git a/utils/TableGen/TableGenBackend.h b/utils/TableGen/TableGenBackend.h
deleted file mode 100644
index 9c2b948..0000000
--- a/utils/TableGen/TableGenBackend.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- TableGenBackend.h - Base class for TableGen Backends -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// The TableGenBackend class is provided as a common interface for all TableGen
-// backends. It provides useful services and an standardized interface.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef TABLEGENBACKEND_H
-#define TABLEGENBACKEND_H
-
-#include "llvm/Support/raw_ostream.h"
-#include <string>
-
-namespace llvm {
-
-class Record;
-class RecordKeeper;
-
-struct TableGenBackend {
- virtual ~TableGenBackend() {}
-
- // run - All TableGen backends should implement the run method, which should
- // be the main entry point.
- virtual void run(raw_ostream &OS) = 0;
-
-
-public: // Useful helper routines...
- /// EmitSourceFileHeader - Output a LLVM style file header to the specified
- /// ostream.
- void EmitSourceFileHeader(const std::string &Desc, raw_ostream &OS) const;
-
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp
index 7431059..e8c9a48 100644
--- a/utils/TableGen/X86DisassemblerTables.cpp
+++ b/utils/TableGen/X86DisassemblerTables.cpp
@@ -17,7 +17,7 @@
#include "X86DisassemblerShared.h"
#include "X86DisassemblerTables.h"
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
@@ -32,26 +32,32 @@ using namespace X86Disassembler;
/// @param parent - The class that may be the superset
/// @return - True if child is a subset of parent, false otherwise.
static inline bool inheritsFrom(InstructionContext child,
- InstructionContext parent) {
+ InstructionContext parent,
+ bool VEX_LIG = false) {
if (child == parent)
return true;
switch (parent) {
case IC:
- return true;
+ return(inheritsFrom(child, IC_64BIT) ||
+ inheritsFrom(child, IC_OPSIZE) ||
+ inheritsFrom(child, IC_XD) ||
+ inheritsFrom(child, IC_XS));
case IC_64BIT:
return(inheritsFrom(child, IC_64BIT_REXW) ||
inheritsFrom(child, IC_64BIT_OPSIZE) ||
inheritsFrom(child, IC_64BIT_XD) ||
inheritsFrom(child, IC_64BIT_XS));
case IC_OPSIZE:
- return(inheritsFrom(child, IC_64BIT_OPSIZE));
+ return inheritsFrom(child, IC_64BIT_OPSIZE);
case IC_XD:
- return(inheritsFrom(child, IC_64BIT_XD) ||
- inheritsFrom(child, IC_VEX_XD));
+ return inheritsFrom(child, IC_64BIT_XD);
case IC_XS:
- return(inheritsFrom(child, IC_64BIT_XS) ||
- inheritsFrom(child, IC_VEX_XS));
+ return inheritsFrom(child, IC_64BIT_XS);
+ case IC_XD_OPSIZE:
+ return inheritsFrom(child, IC_64BIT_XD_OPSIZE);
+ case IC_XS_OPSIZE:
+ return inheritsFrom(child, IC_64BIT_XS_OPSIZE);
case IC_64BIT_REXW:
return(inheritsFrom(child, IC_64BIT_REXW_XS) ||
inheritsFrom(child, IC_64BIT_REXW_XD) ||
@@ -62,42 +68,37 @@ static inline bool inheritsFrom(InstructionContext child,
return(inheritsFrom(child, IC_64BIT_REXW_XD));
case IC_64BIT_XS:
return(inheritsFrom(child, IC_64BIT_REXW_XS));
- case IC_64BIT_REXW_XD:
+ case IC_64BIT_XD_OPSIZE:
+ case IC_64BIT_XS_OPSIZE:
return false;
+ case IC_64BIT_REXW_XD:
case IC_64BIT_REXW_XS:
- return false;
case IC_64BIT_REXW_OPSIZE:
return false;
case IC_VEX:
- return(inheritsFrom(child, IC_VEX_XS) ||
- inheritsFrom(child, IC_VEX_XD) ||
- inheritsFrom(child, IC_VEX_L) ||
- inheritsFrom(child, IC_VEX_W) ||
- inheritsFrom(child, IC_VEX_OPSIZE));
+ return inheritsFrom(child, IC_VEX_W) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L));
case IC_VEX_XS:
- return(inheritsFrom(child, IC_VEX_L_XS) ||
- inheritsFrom(child, IC_VEX_W_XS));
+ return inheritsFrom(child, IC_VEX_W_XS) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS));
case IC_VEX_XD:
- return(inheritsFrom(child, IC_VEX_L_XD) ||
- inheritsFrom(child, IC_VEX_W_XD));
- case IC_VEX_L:
- return(inheritsFrom(child, IC_VEX_L_XS) ||
- inheritsFrom(child, IC_VEX_L_XD));
- case IC_VEX_L_XS:
- return false;
- case IC_VEX_L_XD:
- return false;
+ return inheritsFrom(child, IC_VEX_W_XD) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD));
+ case IC_VEX_OPSIZE:
+ return inheritsFrom(child, IC_VEX_W_OPSIZE) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE));
case IC_VEX_W:
- return(inheritsFrom(child, IC_VEX_W_XS) ||
- inheritsFrom(child, IC_VEX_W_XD) ||
- inheritsFrom(child, IC_VEX_W_OPSIZE));
case IC_VEX_W_XS:
- return false;
case IC_VEX_W_XD:
+ case IC_VEX_W_OPSIZE:
+ return false;
+ case IC_VEX_L:
+ case IC_VEX_L_XS:
+ case IC_VEX_L_XD:
+ case IC_VEX_L_OPSIZE:
return false;
- case IC_VEX_OPSIZE:
- return inheritsFrom(child, IC_VEX_W_OPSIZE);
default:
+ llvm_unreachable("Unknown instruction class");
return false;
}
}
@@ -515,6 +516,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const {
o << "IC_VEX_XD";
else if ((index & ATTR_VEX) && (index & ATTR_XS))
o << "IC_VEX_XS";
+ else if (index & ATTR_VEX)
+ o << "IC_VEX";
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
o << "IC_64BIT_REXW_XS";
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
@@ -522,6 +525,10 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const {
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
(index & ATTR_OPSIZE))
o << "IC_64BIT_REXW_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE))
+ o << "IC_64BIT_XD_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE))
+ o << "IC_64BIT_XS_OPSIZE";
else if ((index & ATTR_64BIT) && (index & ATTR_XS))
o << "IC_64BIT_XS";
else if ((index & ATTR_64BIT) && (index & ATTR_XD))
@@ -532,14 +539,16 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const {
o << "IC_64BIT_REXW";
else if ((index & ATTR_64BIT))
o << "IC_64BIT";
+ else if ((index & ATTR_XS) && (index & ATTR_OPSIZE))
+ o << "IC_XS_OPSIZE";
+ else if ((index & ATTR_XD) && (index & ATTR_OPSIZE))
+ o << "IC_XD_OPSIZE";
else if (index & ATTR_XS)
o << "IC_XS";
else if (index & ATTR_XD)
o << "IC_XD";
else if (index & ATTR_OPSIZE)
o << "IC_OPSIZE";
- else if (index & ATTR_VEX)
- o << "IC_VEX";
else
o << "IC";
@@ -616,8 +625,11 @@ void DisassemblerTables::setTableFields(ModRMDecision &decision,
if(newInfo.filtered)
continue; // filtered instructions get lowest priority
- if(previousInfo.name == "NOOP")
- continue; // special case for XCHG32ar and NOOP
+ if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" ||
+ newInfo.name == "XCHG32ar" ||
+ newInfo.name == "XCHG32ar64" ||
+ newInfo.name == "XCHG64ar"))
+ continue; // special case for XCHG*ar and NOOP
if (outranks(previousInfo.insnContext, newInfo.insnContext))
continue;
@@ -643,14 +655,19 @@ void DisassemblerTables::setTableFields(OpcodeType type,
InstructionContext insnContext,
uint8_t opcode,
const ModRMFilter &filter,
- InstrUID uid) {
+ InstrUID uid,
+ bool is32bit,
+ bool ignoresVEX_L) {
unsigned index;
ContextDecision &decision = *Tables[type];
for (index = 0; index < IC_max; ++index) {
+ if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT))
+ continue;
+
if (inheritsFrom((InstructionContext)index,
- InstructionSpecifiers[uid].insnContext))
+ InstructionSpecifiers[uid].insnContext, ignoresVEX_L))
setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode],
filter,
uid,
diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h
index d16ebfc..e148cd2 100644
--- a/utils/TableGen/X86DisassemblerTables.h
+++ b/utils/TableGen/X86DisassemblerTables.h
@@ -260,11 +260,15 @@ public:
/// @param filter - The ModRMFilter that decides which ModR/M byte values
/// correspond to the desired instruction.
/// @param uid - The unique ID of the instruction.
+ /// @param is32bit - Instructon is only 32-bit
+ /// @param ignoresVEX_L - Instruction ignores VEX.L
void setTableFields(OpcodeType type,
InstructionContext insnContext,
uint8_t opcode,
const ModRMFilter &filter,
- InstrUID uid);
+ InstrUID uid,
+ bool is32bit,
+ bool ignoresVEX_L);
/// specForUID - Returns the instruction specifier for a given unique
/// instruction ID. Used when resolving collisions.
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index ea3bb70..cae8237 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -68,7 +68,7 @@ namespace X86Local {
DC = 7, DD = 8, DE = 9, DF = 10,
XD = 11, XS = 12,
T8 = 13, P_TA = 14,
- A6 = 15, A7 = 16
+ A6 = 15, A7 = 16, TF = 17
};
}
@@ -217,6 +217,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
HasVEXPrefix = Rec->getValueAsBit("hasVEXPrefix");
HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix");
HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix");
+ IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
HasLockPrefix = Rec->getValueAsBit("hasLockPrefix");
IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
@@ -225,15 +226,21 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
Operands = &insn.Operands.OperandList;
- IsSSE = HasOpSizePrefix && (Name.find("16") == Name.npos);
+ IsSSE = (HasOpSizePrefix && (Name.find("16") == Name.npos)) ||
+ (Name.find("CRC32") != Name.npos);
HasFROperands = hasFROperands();
HasVEX_LPrefix = has256BitOperands() || Rec->getValueAsBit("hasVEX_L");
// Check for 64-bit inst which does not require REX
+ Is32Bit = false;
Is64Bit = false;
// FIXME: Is there some better way to check for In64BitMode?
std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates");
for (unsigned i = 0, e = Predicates.size(); i != e; ++i) {
+ if (Predicates[i]->getName().find("32Bit") != Name.npos) {
+ Is32Bit = true;
+ break;
+ }
if (Predicates[i]->getName().find("64Bit") != Name.npos) {
Is64Bit = true;
break;
@@ -249,6 +256,8 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
Rec->getName() == "REX64_PREFIX" ||
Rec->getName().find("VMREAD64") != Name.npos ||
Rec->getName().find("VMWRITE64") != Name.npos ||
+ Rec->getName().find("INVEPT64") != Name.npos ||
+ Rec->getName().find("INVVPID64") != Name.npos ||
Rec->getName().find("MOV64") != Name.npos ||
Rec->getName().find("PUSH64") != Name.npos ||
Rec->getName().find("POP64") != Name.npos;
@@ -257,7 +266,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
}
void RecognizableInstr::processInstr(DisassemblerTables &tables,
- const CodeGenInstruction &insn,
+ const CodeGenInstruction &insn,
InstrUID uid)
{
// Ignore "asm parser only" instructions.
@@ -276,7 +285,9 @@ InstructionContext RecognizableInstr::insnContext() const {
InstructionContext insnContext;
if (HasVEX_4VPrefix || HasVEXPrefix) {
- if (HasOpSizePrefix && HasVEX_LPrefix)
+ if (HasVEX_LPrefix && HasVEX_WPrefix)
+ llvm_unreachable("Don't support VEX.L and VEX.W together");
+ else if (HasOpSizePrefix && HasVEX_LPrefix)
insnContext = IC_VEX_L_OPSIZE;
else if (HasOpSizePrefix && HasVEX_WPrefix)
insnContext = IC_VEX_W_OPSIZE;
@@ -303,13 +314,19 @@ InstructionContext RecognizableInstr::insnContext() const {
} else if (Is64Bit || HasREX_WPrefix) {
if (HasREX_WPrefix && HasOpSizePrefix)
insnContext = IC_64BIT_REXW_OPSIZE;
+ else if (HasOpSizePrefix &&
+ (Prefix == X86Local::XD || Prefix == X86Local::TF))
+ insnContext = IC_64BIT_XD_OPSIZE;
+ else if (HasOpSizePrefix && Prefix == X86Local::XS)
+ insnContext = IC_64BIT_XS_OPSIZE;
else if (HasOpSizePrefix)
insnContext = IC_64BIT_OPSIZE;
else if (HasREX_WPrefix && Prefix == X86Local::XS)
insnContext = IC_64BIT_REXW_XS;
- else if (HasREX_WPrefix && Prefix == X86Local::XD)
+ else if (HasREX_WPrefix &&
+ (Prefix == X86Local::XD || Prefix == X86Local::TF))
insnContext = IC_64BIT_REXW_XD;
- else if (Prefix == X86Local::XD)
+ else if (Prefix == X86Local::XD || Prefix == X86Local::TF)
insnContext = IC_64BIT_XD;
else if (Prefix == X86Local::XS)
insnContext = IC_64BIT_XS;
@@ -318,11 +335,16 @@ InstructionContext RecognizableInstr::insnContext() const {
else
insnContext = IC_64BIT;
} else {
- if (HasOpSizePrefix)
+ if (HasOpSizePrefix &&
+ (Prefix == X86Local::XD || Prefix == X86Local::TF))
+ insnContext = IC_XD_OPSIZE;
+ else if (HasOpSizePrefix && Prefix == X86Local::XS)
+ insnContext = IC_XS_OPSIZE;
+ else if (HasOpSizePrefix)
insnContext = IC_OPSIZE;
- else if (Prefix == X86Local::XD)
+ else if (Prefix == X86Local::XD || Prefix == X86Local::TF)
insnContext = IC_XD;
- else if (Prefix == X86Local::XS)
+ else if (Prefix == X86Local::XS || Prefix == X86Local::REP)
insnContext = IC_XS;
else
insnContext = IC;
@@ -342,20 +364,13 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const {
return FILTER_STRONG;
if (Form == X86Local::Pseudo ||
- IsCodeGenOnly)
+ (IsCodeGenOnly && Name.find("_REV") == Name.npos))
return FILTER_STRONG;
if (Form == X86Local::MRMInitReg)
return FILTER_STRONG;
- // TEMPORARY pending bug fixes
-
- if (Name.find("VMOVDQU") != Name.npos ||
- Name.find("VMOVDQA") != Name.npos ||
- Name.find("VROUND") != Name.npos)
- return FILTER_STRONG;
-
// Filter out artificial instructions
if (Name.find("TAILJMP") != Name.npos ||
@@ -401,7 +416,7 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const {
// Filter out alternate forms of AVX instructions
if (Name.find("_alt") != Name.npos ||
Name.find("XrYr") != Name.npos ||
- Name.find("r64r") != Name.npos ||
+ (Name.find("r64r") != Name.npos && Name.find("r64r64") == Name.npos) ||
Name.find("_64mr") != Name.npos ||
Name.find("Xrr") != Name.npos ||
Name.find("rr64") != Name.npos)
@@ -623,20 +638,43 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
case X86Local::MRMDestReg:
// Operand 1 is a register operand in the R/M field.
// Operand 2 is a register operand in the Reg/Opcode field.
+ // - In AVX, there is a register operand in the VEX.vvvv field here -
// Operand 3 (optional) is an immediate.
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMDestRegFrm");
+ if (HasVEX_4VPrefix)
+ assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
+ "Unexpected number of operands for MRMDestRegFrm with VEX_4V");
+ else
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMDestRegFrm");
+
HANDLE_OPERAND(rmRegister)
+
+ if (HasVEX_4VPrefix)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPERAND(vvvvRegister)
+
HANDLE_OPERAND(roRegister)
HANDLE_OPTIONAL(immediate)
break;
case X86Local::MRMDestMem:
// Operand 1 is a memory operand (possibly SIB-extended)
// Operand 2 is a register operand in the Reg/Opcode field.
+ // - In AVX, there is a register operand in the VEX.vvvv field here -
// Operand 3 (optional) is an immediate.
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMDestMemFrm");
+ if (HasVEX_4VPrefix)
+ assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
+ "Unexpected number of operands for MRMDestMemFrm with VEX_4V");
+ else
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMDestMemFrm");
HANDLE_OPERAND(memory)
+
+ if (HasVEX_4VPrefix)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPERAND(vvvvRegister)
+
HANDLE_OPERAND(roRegister)
HANDLE_OPTIONAL(immediate)
break;
@@ -805,6 +843,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
opcodeToSet = Opcode;
break;
case X86Local::T8:
+ case X86Local::TF:
opcodeType = THREEBYTE_38;
if (needsModRMForDecode(Form))
filter = new ModFilter(isRegFormat(Form));
@@ -855,6 +894,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
}
opcodeToSet = 0xd8 + (Prefix - X86Local::D8);
break;
+ case X86Local::REP:
default:
opcodeType = ONEBYTE;
switch (Opcode) {
@@ -926,7 +966,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
insnContext(),
currentOpcode,
*filter,
- UID);
+ UID, Is32Bit, IgnoresVEX_L);
Spec->modifierType = MODIFIER_OPCODE;
Spec->modifierBase = opcodeToSet;
@@ -936,14 +976,14 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
insnContext(),
opcodeToSet,
*filter,
- UID);
+ UID, Is32Bit, IgnoresVEX_L);
}
} else {
tables.setTableFields(opcodeType,
insnContext(),
opcodeToSet,
*filter,
- UID);
+ UID, Is32Bit, IgnoresVEX_L);
Spec->modifierType = MODIFIER_NONE;
Spec->modifierBase = opcodeToSet;
@@ -984,6 +1024,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("i32mem", TYPE_Mv)
TYPE("i32imm", TYPE_IMMv)
TYPE("i32i8imm", TYPE_IMM32)
+ TYPE("u32u8imm", TYPE_IMM32)
TYPE("GR32", TYPE_Rv)
TYPE("i64mem", TYPE_Mv)
TYPE("i64i32imm", TYPE_IMM64)
@@ -1029,6 +1070,9 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("offset32", TYPE_MOFFS32)
TYPE("offset64", TYPE_MOFFS64)
TYPE("VR256", TYPE_XMM256)
+ TYPE("GR16_NOAX", TYPE_Rv)
+ TYPE("GR32_NOAX", TYPE_Rv)
+ TYPE("GR64_NOAX", TYPE_R64)
errs() << "Unhandled type string " << s << "\n";
llvm_unreachable("Unhandled type string");
}
@@ -1044,6 +1088,7 @@ OperandEncoding RecognizableInstr::immediateEncodingFromString
ENCODING("i16imm", ENCODING_IW)
}
ENCODING("i32i8imm", ENCODING_IB)
+ ENCODING("u32u8imm", ENCODING_IB)
ENCODING("SSECC", ENCODING_IB)
ENCODING("i16imm", ENCODING_Iv)
ENCODING("i16i8imm", ENCODING_IB)
@@ -1097,6 +1142,8 @@ OperandEncoding RecognizableInstr::roRegisterEncodingFromString
OperandEncoding RecognizableInstr::vvvvRegisterEncodingFromString
(const std::string &s,
bool hasOpSizePrefix) {
+ ENCODING("GR32", ENCODING_VVVV)
+ ENCODING("GR64", ENCODING_VVVV)
ENCODING("FR32", ENCODING_VVVV)
ENCODING("FR64", ENCODING_VVVV)
ENCODING("VR128", ENCODING_VVVV)
@@ -1169,6 +1216,9 @@ OperandEncoding RecognizableInstr::opcodeModifierEncodingFromString
ENCODING("GR64", ENCODING_RO)
ENCODING("GR16", ENCODING_Rv)
ENCODING("GR8", ENCODING_RB)
+ ENCODING("GR16_NOAX", ENCODING_Rv)
+ ENCODING("GR32_NOAX", ENCODING_Rv)
+ ENCODING("GR64_NOAX", ENCODING_RO)
errs() << "Unhandled opcode modifier encoding " << s << "\n";
llvm_unreachable("Unhandled opcode modifier encoding");
}
diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h
index 677d9f0..4441597 100644
--- a/utils/TableGen/X86RecognizableInstr.h
+++ b/utils/TableGen/X86RecognizableInstr.h
@@ -20,8 +20,8 @@
#include "X86DisassemblerTables.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/SmallVector.h"
@@ -60,12 +60,16 @@ private:
bool HasVEX_WPrefix;
/// Inferred from the operands; indicates whether the L bit in the VEX prefix is set
bool HasVEX_LPrefix;
+ // The ignoreVEX_L field from the record
+ bool IgnoresVEX_L;
/// The hasLockPrefix field from the record
bool HasLockPrefix;
/// The isCodeGenOnly filed from the record
bool IsCodeGenOnly;
- // Whether the instruction has the predicate "Mode64Bit"
+ // Whether the instruction has the predicate "In64BitMode"
bool Is64Bit;
+ // Whether the instruction has the predicate "In32BitMode"
+ bool Is32Bit;
/// The instruction name as listed in the tables
std::string Name;
diff --git a/utils/buildit/build_llvm b/utils/buildit/build_llvm
index 5665e4c..0ffbc19 100755
--- a/utils/buildit/build_llvm
+++ b/utils/buildit/build_llvm
@@ -97,31 +97,16 @@ if [ "$ARM_HOSTED_BUILD" = yes ]; then
echo 'exec '$T' "$@"' >> $P || exit 1
chmod a+x $P || exit 1
done
- # Try to use the platform llvm-gcc. Fall back to gcc if it's not available.
- for prog in gcc g++ ; do
+ # Set up the links for clang.
+ for prog in clang clang++ ; do
P=$DIR/bin/arm-apple-darwin$DARWIN_VERS-${prog}
- T=`xcrun -sdk $SDKROOT -find llvm-${prog}`
- if [ "x$T" = "x" ] ; then
- T=`xcrun -sdk $SDKROOT -find ${prog}`
- fi
+ T=`xcrun -sdk $SDKROOT -find ${prog}`
echo '#!/bin/sh' > $P || exit 1
echo 'exec '$T' -arch armv7 -isysroot '${SDKROOT}' "$@"' >> $P || exit 1
chmod a+x $P || exit 1
done
PATH=$DIR/bin:$PATH
-# otherwise, try to use llvm-gcc if it's available
-elif [ $DARWIN_VERS -gt 9 ]; then
- # If the user has set CC or CXX, respect their wishes. If not,
- # compile with LLVM-GCC/LLVM-G++ if available; if LLVM is not
- # available, fall back to usual GCC/G++ default.
- savedPATH=$PATH ; PATH="/Developer/usr/bin:$PATH"
- XTMPCC=$(which llvm-gcc)
- if [ x$CC = x -a x$XTMPCC != x ] ; then export CC=$XTMPCC ; fi
- XTMPCC=$(which llvm-g++)
- if [ x$CXX = x -a x$XTMPCC != x ] ; then export CXX=$XTMPCC ; fi
- PATH=$savedPATH
- unset XTMPCC savedPATH
fi
if [ "$ARM_HOSTED_BUILD" = yes ]; then
@@ -157,32 +142,15 @@ else
LLVM_VERSION="$LLVM_SUBMIT_VERSION-$LLVM_SUBMIT_SUBVERSION"
fi
-GCC_VER=`cc --version 2>/dev/null | sed 1q`
-
-if echo "$GCC_VER" | grep GCC > /dev/null; then
- GCC_VER=`echo $GCC_VER | sed -e 's/.*(GCC) \([0-9.][0-9.]*\).*/\1/'`
- MAJ_VER=`echo $GCC_VER | sed 's/\..*//'`
- MIN_VER=`echo $GCC_VER | sed 's/[^.]*\.\([0-9]*\).*/\1/'`
-fi
-
-JOBS_FLAG=""
-
-# Note: If compiling with GCC 4.0, don't pass the -jN flag. Building universal
-# already has parallelism and we don't want to make the builders hit swap by
-# firing off too many gccs at the same time.
-if [ "x$MAJ_VER" != "x4" -o "x$MIN_VER" != "x0" ]; then
- # Figure out how many make processes to run.
- SYSCTL=`sysctl -n hw.activecpu`
-
- # sysctl -n hw.* does not work when invoked via B&I chroot /BuildRoot.
- # Builders can default to 2, since even if they are single processor,
- # nothing else is running on the machine.
- if [ -z "$SYSCTL" ]; then
- SYSCTL=2
- fi
-
- JOBS_FLAG="-j $SYSCTL"
+# Figure out how many make processes to run.
+SYSCTL=`sysctl -n hw.activecpu`
+# sysctl -n hw.* does not work when invoked via B&I chroot /BuildRoot.
+# Builders can default to 2, since even if they are single processor,
+# nothing else is running on the machine.
+if [ -z "$SYSCTL" ]; then
+ SYSCTL=2
fi
+JOBS_FLAG="-j $SYSCTL"
make $JOBS_FLAG $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$HOSTS" \
UNIVERSAL_SDK_PATH=$SDKROOT \
@@ -233,14 +201,20 @@ RC_ProjectSourceSubversion=`printf "%d" $LLVM_MINOR_VERSION`
echo "#define LLVM_VERSION ${RC_ProjectSourceVersion}" > $DEST_DIR$DEST_ROOT/include/llvm/Version.h
echo "#define LLVM_MINOR_VERSION ${RC_ProjectSourceSubversion}" >> $DEST_DIR$DEST_ROOT/include/llvm/Version.h
+# Find the right version of strip to use.
+STRIP=strip
+if [ -n "$SDKROOT" ]; then
+ STRIP=`xcrun -sdk $SDKROOT -find strip`
+fi
+
if [ "x$LLVM_DEBUG" != "x1" ]; then
# Strip local symbols from llvm libraries.
#
# Use '-l' to strip i386 modules. N.B. that flag doesn't work with kext or
# PPC objects!
- strip -Sl $DEST_DIR$DEST_ROOT/lib/*.[oa]
+ $STRIP -Sl $DEST_DIR$DEST_ROOT/lib/*.[oa]
for f in `ls $DEST_DIR$DEST_ROOT/lib/*.so`; do
- strip -Sxl $f
+ $STRIP -Sxl $f
done
fi
@@ -329,7 +303,7 @@ if [ "$INSTALL_LIBLTO" = "yes" ]; then
# Use '-l' to strip i386 modules. N.B. that flag doesn't work with kext or
# PPC objects!
- strip -arch all -Sl $DT_HOME/lib/libLTO.dylib
+ $STRIP -arch all -Sl $DT_HOME/lib/libLTO.dylib
if [ "x$DISABLE_USR_LINKS" == "x" ]; then
# Add a symlink in /usr/lib for B&I.
@@ -359,7 +333,7 @@ find $DEST_DIR -name \*.dSYM -print | xargs rm -r || exit 1
# PPC objects!
find $DEST_DIR -perm -0111 -type f \
! \( -name '*.la' -o -name gccas -o -name gccld -o -name llvm-config \) \
- -print | xargs -n 1 -P ${SYSCTL} strip -arch all -Sl
+ -print | xargs -n 1 -P ${SYSCTL} $STRIP -arch all -Sl
chgrp -h -R wheel $DEST_DIR
chgrp -R wheel $DEST_DIR
diff --git a/utils/lit/lit/LitConfig.py b/utils/lit/lit/LitConfig.py
index bda9174..2cc2781 100644
--- a/utils/lit/lit/LitConfig.py
+++ b/utils/lit/lit/LitConfig.py
@@ -20,7 +20,7 @@ class LitConfig:
def __init__(self, progname, path, quiet,
useValgrind, valgrindLeakCheck, valgrindArgs,
useTclAsSh,
- noExecute, debug, isWindows,
+ noExecute, ignoreStdErr, debug, isWindows,
params):
# The name of the test runner.
self.progname = progname
@@ -32,6 +32,7 @@ class LitConfig:
self.valgrindUserArgs = list(valgrindArgs)
self.useTclAsSh = bool(useTclAsSh)
self.noExecute = noExecute
+ self.ignoreStdErr = ignoreStdErr
self.debug = debug
self.isWindows = bool(isWindows)
self.params = dict(params)
diff --git a/utils/lit/lit/TestFormats.py b/utils/lit/lit/TestFormats.py
index 6dda2fd..d1c0558 100644
--- a/utils/lit/lit/TestFormats.py
+++ b/utils/lit/lit/TestFormats.py
@@ -125,7 +125,11 @@ class ShTest(FileBasedTest):
self.execute_external)
class TclTest(FileBasedTest):
+ def __init__(self, ignoreStdErr=False):
+ self.ignoreStdErr = ignoreStdErr
+
def execute(self, test, litConfig):
+ litConfig.ignoreStdErr = self.ignoreStdErr
return TestRunner.executeTclTest(test, litConfig)
###
diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py
index 80d0ba1..f5f7c19 100644
--- a/utils/lit/lit/TestRunner.py
+++ b/utils/lit/lit/TestRunner.py
@@ -397,7 +397,8 @@ def parseIntegratedTestScript(test, normalize_slashes=False):
sourcedir = os.path.dirname(sourcepath)
execpath = test.getExecPath()
execdir,execbase = os.path.split(execpath)
- tmpBase = os.path.join(execdir, 'Output', execbase)
+ tmpDir = os.path.join(execdir, 'Output')
+ tmpBase = os.path.join(tmpDir, execbase)
if test.index is not None:
tmpBase += '_%d' % test.index
@@ -405,6 +406,7 @@ def parseIntegratedTestScript(test, normalize_slashes=False):
if normalize_slashes:
sourcepath = sourcepath.replace('\\', '/')
sourcedir = sourcedir.replace('\\', '/')
+ tmpDir = tmpDir.replace('\\', '/')
tmpBase = tmpBase.replace('\\', '/')
# We use #_MARKER_# to hide %% while we do the other substitutions.
@@ -414,6 +416,7 @@ def parseIntegratedTestScript(test, normalize_slashes=False):
('%S', sourcedir),
('%p', sourcedir),
('%t', tmpBase + '.tmp'),
+ ('%T', tmpDir),
# FIXME: Remove this once we kill DejaGNU.
('%abs_tmp', tmpBase + '.tmp'),
('#_MARKER_#', '%')])
@@ -533,13 +536,13 @@ def executeTclTest(test, litConfig):
# considered to fail if there is any standard error output.
out,err,exitCode = res
if isXFail:
- ok = exitCode != 0 or err
+ ok = exitCode != 0 or err and not litConfig.ignoreStdErr
if ok:
status = Test.XFAIL
else:
status = Test.XPASS
else:
- ok = exitCode == 0 and not err
+ ok = exitCode == 0 and (not err or litConfig.ignoreStdErr)
if ok:
status = Test.PASS
else:
@@ -550,7 +553,7 @@ def executeTclTest(test, litConfig):
# Set a flag for formatTestOutput so it can explain why the test was
# considered to have failed, despite having an exit code of 0.
- failDueToStderr = exitCode == 0 and err
+ failDueToStderr = exitCode == 0 and err and not litConfig.ignoreStdErr
return formatTestOutput(status, out, err, exitCode, failDueToStderr, script)
diff --git a/utils/lit/lit/TestingConfig.py b/utils/lit/lit/TestingConfig.py
index 25bb341..a92dca8 100644
--- a/utils/lit/lit/TestingConfig.py
+++ b/utils/lit/lit/TestingConfig.py
@@ -1,4 +1,5 @@
import os
+import sys
class TestingConfig:
""""
@@ -14,12 +15,18 @@ class TestingConfig:
'LD_LIBRARY_PATH' : os.environ.get('LD_LIBRARY_PATH',''),
'PATH' : os.pathsep.join(litConfig.path +
[os.environ.get('PATH','')]),
- 'PATHEXT' : os.environ.get('PATHEXT',''),
'SYSTEMROOT' : os.environ.get('SYSTEMROOT',''),
- 'LLVM_DISABLE_CRT_DEBUG' : '1',
- 'PYTHONUNBUFFERED' : '1',
}
+ if sys.platform == 'win32':
+ environment.update({
+ 'LLVM_DISABLE_CRT_DEBUG' : '1',
+ 'PATHEXT' : os.environ.get('PATHEXT',''),
+ 'PYTHONUNBUFFERED' : '1',
+ 'TEMP' : os.environ.get('TEMP',''),
+ 'TMP' : os.environ.get('TMP',''),
+ })
+
config = TestingConfig(parent,
name = '<unnamed>',
suffixes = set(),
diff --git a/utils/lit/lit/main.py b/utils/lit/lit/main.py
index 13d2630..e1a380c 100755
--- a/utils/lit/lit/main.py
+++ b/utils/lit/lit/main.py
@@ -328,6 +328,7 @@ def load_test_suite(inputs):
valgrindArgs = [],
useTclAsSh = False,
noExecute = False,
+ ignoreStdErr = False,
debug = False,
isWindows = (platform.system()=='Windows'),
params = {})
@@ -485,6 +486,7 @@ def main(builtinParameters = {}): # Bump the GIL check interval, its more imp
valgrindArgs = opts.valgrindArgs,
useTclAsSh = opts.useTclAsSh,
noExecute = opts.noExecute,
+ ignoreStdErr = False,
debug = opts.debug,
isWindows = (platform.system()=='Windows'),
params = userParams)
diff --git a/utils/llvm.grm b/utils/llvm.grm
index 3f33702..fb26dbb 100644
--- a/utils/llvm.grm
+++ b/utils/llvm.grm
@@ -172,7 +172,7 @@ FuncAttr ::= noreturn
| optsize
| ssp
| sspreq
- | hotpatch
+ | returns_twice
| nonlazybind
;
diff --git a/utils/llvmbuild b/utils/llvmbuild
index c7d8814..b623d32 100755
--- a/utils/llvmbuild
+++ b/utils/llvmbuild
@@ -189,6 +189,10 @@ def add_options(parser):
help=("Extra flags to pass to gcc configure [default: %default]"))
parser.add_option("--force-configure", default=False, action="store_true",
help=("Force reconfigure of all components"))
+ parser.add_option("--no-gcc", default=False, action="store_true",
+ help=("Do not build dragonegg and gcc"))
+ parser.add_option("--no-install", default=False, action="store_true",
+ help=("Do not do installs"))
return
def check_options(parser, options, valid_builds):
@@ -622,6 +626,12 @@ class Builder(threading.Thread):
for component in components:
comp = component[:]
+
+ if (self.options.no_gcc):
+ if (comp == 'gcc' or comp == 'dragonegg' or comp == 'llvm2'):
+ self.logger.info("Skipping " + component + " in "
+ + builddir)
+ continue
srcdir = source + "/" + comp.rstrip("2")
builddir = self.build_prefix + "/" + comp + "/" + build_suffix
@@ -643,16 +653,20 @@ class Builder(threading.Thread):
configure_env[comp_key][build])
self.logger.info("Building " + component + " in " + builddir)
+ self.logger.info("Build: make " + str(make_flags[comp_key][build]))
self.make(component, srcdir, builddir,
make_flags[comp_key][build],
make_env[comp_key][build])
- self.logger.info("Installing " + component + " in " + installdir)
- self.make(component, srcdir, builddir,
- make_install_flags[comp_key][build],
- make_install_env[comp_key][build])
+ if (not self.options.no_install):
+ self.logger.info("Installing " + component + " in " + installdir)
+ self.make(component, srcdir, builddir,
+ make_install_flags[comp_key][build],
+ make_install_env[comp_key][build])
self.logger.info("Testing " + component + " in " + builddir)
+ self.logger.info("Test: make "
+ + str(make_check_flags[comp_key][build]))
self.make(component, srcdir, builddir,
make_check_flags[comp_key][build],
make_check_env[comp_key][build])
@@ -741,9 +755,10 @@ if jobs == 0:
jobs = 1
numthreads = options.threads
-if jobs < numthreads:
- numthreads = jobs
- jobs = 1
+
+logging.getLogger().info("Building with " + str(options.jobs) + " jobs and "
+ + str(numthreads) + " threads using " + str(jobs)
+ + " make jobs")
for t in range(numthreads):
builder = Builder(work_queue, jobs,
diff --git a/utils/release/findRegressions.py b/utils/release/findRegressions.py
index e801dab..7629c8b 100755
--- a/utils/release/findRegressions.py
+++ b/utils/release/findRegressions.py
@@ -1,68 +1,60 @@
#!/usr/bin/python
-import re, string, sys, os, time
+import re, string, sys, os, time, math
DEBUG = 0
-testDirName = 'llvm-test'
-test = ['compile', 'llc', 'jit', 'cbe']
-exectime = ['llc-time', 'jit-time', 'cbe-time',]
-comptime = ['llc', 'jit-comptime', 'compile']
-(tp, exp) = ('compileTime_', 'executeTime_')
+(tp, exp) = ('compile', 'exec')
def parse(file):
- f=open(file, 'r')
+ f = open(file, 'r')
d = f.read()
- #Cleanup weird stuff
- d = re.sub(r',\d+:\d','', d)
-
+ # Cleanup weird stuff
+ d = re.sub(r',\d+:\d', '', d)
+
r = re.findall(r'TEST-(PASS|FAIL|RESULT.*?):\s+(.*?)\s+(.*?)\r*\n', d)
-
+
test = {}
fname = ''
for t in r:
if DEBUG:
print t
+
if t[0] == 'PASS' or t[0] == 'FAIL' :
- tmp = t[2].split(testDirName)
+ tmp = t[2].split('llvm-test/')
if DEBUG:
print tmp
-
+
if len(tmp) == 2:
fname = tmp[1].strip('\r\n')
else:
fname = tmp[0].strip('\r\n')
-
- if not test.has_key(fname) :
+
+ if not test.has_key(fname):
test[fname] = {}
-
- for k in test:
- test[fname][k] = 'NA'
- test[fname][t[1]] = t[0]
- if DEBUG:
- print test[fname][t[1]]
+
+ test[fname][t[1] + ' state'] = t[0]
+ test[fname][t[1] + ' time'] = float('nan')
else :
try:
n = t[0].split('RESULT-')[1]
-
+
if DEBUG:
- print n;
+ print "n == ", n;
- if n == 'llc' or n == 'jit-comptime' or n == 'compile':
- test[fname][tp + n] = float(t[2].split(' ')[2])
+ if n == 'compile-success':
+ test[fname]['compile time'] = float(t[2].split('program')[1].strip('\r\n'))
+
+ elif n == 'exec-success':
+ test[fname]['exec time'] = float(t[2].split('program')[1].strip('\r\n'))
if DEBUG:
- print test[fname][tp + n]
-
- elif n.endswith('-time') :
- test[fname][exp + n] = float(t[2].strip('\r\n'))
- if DEBUG:
- print test[fname][exp + n]
-
+ print test[fname][string.replace(n, '-success', '')]
+
else :
- print "ERROR!"
+ # print "ERROR!"
sys.exit(1)
-
+
except:
continue
@@ -72,59 +64,60 @@ def parse(file):
def diffResults(d_old, d_new):
for t in sorted(d_old.keys()) :
- if DEBUG:
- print t
-
- if d_new.has_key(t) :
-
+ if d_new.has_key(t):
+
# Check if the test passed or failed.
- for x in test:
+ for x in ['compile state', 'compile time', 'exec state', 'exec time']:
+
+ if not d_old[t].has_key(x) and not d_new[t].has_key(x):
+ continue
+
if d_old[t].has_key(x):
if d_new[t].has_key(x):
+
if d_old[t][x] == 'PASS':
if d_new[t][x] != 'PASS':
- print t + " *** REGRESSION (" + x + ")\n"
+ print t + " *** REGRESSION (" + x + " now fails)"
else:
if d_new[t][x] == 'PASS':
- print t + " * NEW PASS (" + x + ")\n"
-
- else :
- print t + "*** REGRESSION (" + x + ")\n"
-
- # For execution time, if there is no result, its a fail.
- for x in exectime:
- if d_old[t].has_key(tp + x):
- if not d_new[t].has_key(tp + x):
- print t + " *** REGRESSION (" + tp + x + ")\n"
-
- else :
- if d_new[t].has_key(tp + x):
- print t + " * NEW PASS (" + tp + x + ")\n"
-
-
- for x in comptime:
- if d_old[t].has_key(exp + x):
- if not d_new[t].has_key(exp + x):
- print t + " *** REGRESSION (" + exp + x + ")\n"
-
+ print t + " * NEW PASS (" + x + " now fails)"
+
else :
- if d_new[t].has_key(exp + x):
- print t + " * NEW PASS (" + exp + x + ")\n"
-
+ print t + "*** REGRESSION (" + x + " now fails)"
+
+ if x == 'compile state' or x == 'exec state':
+ continue
+
+ # For execution time, if there is no result it's a fail.
+ if not d_old[t].has_key(x) and not d_new[t].has_key(x):
+ continue
+ elif not d_new[t].has_key(x):
+ print t + " *** REGRESSION (" + x + ")"
+ elif not d_old[t].has_key(x):
+ print t + " * NEW PASS (" + x + ")"
+
+ if math.isnan(d_old[t][x]) and math.isnan(d_new[t][x]):
+ continue
+
+ elif math.isnan(d_old[t][x]) and not math.isnan(d_new[t][x]):
+ print t + " * NEW PASS (" + x + ")"
+
+ elif not math.isnan(d_old[t][x]) and math.isnan(d_new[t][x]):
+ print t + " *** REGRESSION (" + x + ")"
+
+ if d_new[t][x] > d_old[t][x] and \
+ (d_new[t][x] - d_old[t][x]) / d_new[t][x] > .05:
+ print t + " *** REGRESSION (" + x + ")"
+
else :
- print t + ": Removed from test-suite.\n"
-
+ print t + ": Removed from test-suite."
-#Main
+# Main
if len(sys.argv) < 3 :
- print 'Usage:', sys.argv[0], \
- '<old log> <new log>'
- sys.exit(-1)
+ print 'Usage:', sys.argv[0], '<old log> <new log>'
+ sys.exit(-1)
d_old = parse(sys.argv[1])
d_new = parse(sys.argv[2])
-
diffResults(d_old, d_new)
-
-
diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh
index 21d7fee..4255324 100755
--- a/utils/release/test-release.sh
+++ b/utils/release/test-release.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#===-- test-release.sh - Test the LLVM release candidates ------------------===#
#
# The LLVM Compiler Infrastructure
@@ -12,7 +12,16 @@
#
#===------------------------------------------------------------------------===#
-set -e # Exit if any command fails
+if [ `uname -s` = "FreeBSD" ]; then
+ MAKE=gmake
+else
+ MAKE=make
+fi
+
+projects="llvm cfe dragonegg test-suite"
+
+# Base SVN URL for the sources.
+Base_url="http://llvm.org/svn/llvm-project"
Release=""
Release_no_dot=""
@@ -20,8 +29,10 @@ RC=""
do_checkout="yes"
do_ada="no"
do_objc="yes"
-do_fortran="yes"
+do_fortran="no"
do_64bit="yes"
+do_debug="no"
+do_asserts="no"
BuildDir="`pwd`"
function usage() {
@@ -34,8 +45,10 @@ function usage() {
echo " -no-checkout Don't checkout the sources from SVN."
echo " -no-64bit Don't test the 64-bit version. [default: yes]"
echo " -enable-ada Build Ada. [default: disable]"
+ echo " -enable-fortran Enable Fortran build. [default: disable]"
echo " -disable-objc Disable ObjC build. [default: enable]"
- echo " -disable-fortran Disable Fortran build. [default: enable]"
+ echo " -test-debug Test the debug build. [default: no]"
+ echo " -test-asserts Test with asserts on. [default: no]"
}
while [ $# -gt 0 ]; do
@@ -69,13 +82,17 @@ while [ $# -gt 0 ]; do
-enable-ada | --enable-ada )
do_ada="yes"
;;
+ -enable-fortran | --enable-fortran )
+ do_fortran="yes"
+ ;;
-disable-objc | --disable-objc )
do_objc="no"
;;
- -disable-fortran | --disable-fortran )
- echo "WARNING: Do you *really* need to disable Fortran?"
- sleep 5
- do_fortran="no"
+ -test-debug | --test-debug )
+ do_debug="yes"
+ ;;
+ -test-asserts | --test-asserts )
+ do_asserts="yes"
;;
-help | --help | -h | --h | -\? )
usage
@@ -92,11 +109,11 @@ done
# Check required arguments.
if [ -z "$Release" ]; then
- echo "No release number specified!"
+ echo "error: no release number specified"
exit 1
fi
if [ -z "$RC" ]; then
- echo "No release candidate number specified!"
+ echo "error: no release candidate number specified"
exit 1
fi
@@ -114,55 +131,53 @@ if [ -z "$NumJobs" ]; then
NumJobs=3
fi
-# Location of sources.
-llvmCore_srcdir=$BuildDir/llvmCore-$Release-rc$RC.src
-llvmgcc42_srcdir=$BuildDir/llvmgcc42-$Release-rc$RC.src
+# Go to the build directory (may be different from CWD)
+BuildDir=$BuildDir/rc$RC
+mkdir -p $BuildDir
+cd $BuildDir
# Location of log files.
-LogDirName="$Release-rc$RC.logs"
-LogDir=$BuildDir/$LogDirName
+LogDir=$BuildDir/logs
mkdir -p $LogDir
-# SVN URLs for the sources.
-Base_url="http://llvm.org/svn/llvm-project"
-llvmCore_RC_url="$Base_url/llvm/tags/RELEASE_$Release_no_dot/rc$RC"
-llvmgcc42_RC_url="$Base_url/llvm-gcc-4.2/tags/RELEASE_$Release_no_dot/rc$RC"
-clang_RC_url="$Base_url/cfe/tags/RELEASE_$Release_no_dot/rc$RC"
-test_suite_RC_url="$Base_url/test-suite/tags/RELEASE_$Release_no_dot/rc$RC"
+# Find a compilers.
+c_compiler="$CC"
+cxx_compiler="$CXX"
# Make sure that the URLs are valid.
function check_valid_urls() {
- echo "# Validating SVN URLs"
- if ! svn ls $llvmCore_RC_url > /dev/null 2>&1 ; then
- echo "llvm $Release release candidate $RC doesn't exist!"
- exit 1
- fi
- if ! svn ls $llvmgcc42_RC_url > /dev/null 2>&1 ; then
- echo "llvm-gcc-4.2 $Release release candidate $RC doesn't exist!"
- exit 1
- fi
- if ! svn ls $clang_RC_url > /dev/null 2>&1 ; then
- echo "clang $Release release candidate $RC doesn't exist!"
- exit 1
- fi
- if ! svn ls $test_suite_RC_url > /dev/null 2>&1 ; then
- echo "test-suite $Release release candidate $RC doesn't exist!"
- exit 1
- fi
+ for proj in $projects ; do
+ echo "# Validating $proj SVN URL"
+
+ if ! svn ls $Base_url/$proj/tags/RELEASE_$Release_no_dot/rc$RC > /dev/null 2>&1 ; then
+ echo "llvm $Release release candidate $RC doesn't exist!"
+ exit 1
+ fi
+ done
}
# Export sources to the the build directory.
function export_sources() {
check_valid_urls
- echo "# Exporting llvm $Release-RC$RC sources"
- svn export -q $llvmCore_RC_url $llvmCore_srcdir
- echo "# Exporting llvm-gcc-4.2 $Release-rc$RC sources"
- svn export -q $llvmgcc42_RC_url $llvmgcc42_srcdir
- echo "# Exporting clang $Release-rc$RC sources"
- svn export -q $clang_RC_url $llvmCore_srcdir/tools/clang
- echo "# Exporting llvm test suite $Release-rc$RC sources"
- svn export -q $test_suite_RC_url $llvmCore_srcdir/projects/llvm-test
+ for proj in $projects ; do
+ echo "# Exporting $proj $Release-RC$RC sources"
+ if ! svn export -q $Base_url/$proj/tags/RELEASE_$Release_no_dot/rc$RC $proj.src ; then
+ echo "error: failed to export $proj project"
+ exit 1
+ fi
+ done
+
+ echo "# Creating symlinks"
+ cd $BuildDir/llvm.src/tools
+ if [ ! -h clang ]; then
+ ln -s $BuildDir/cfe.src clang
+ fi
+ cd $BuildDir/llvm.src/projects
+ if [ ! -h llvm-test ]; then
+ ln -s $BuildDir/test-suite.src llvm-test
+ fi
+ cd $BuildDir
}
function configure_llvmCore() {
@@ -170,7 +185,6 @@ function configure_llvmCore() {
Flavor="$2"
ObjDir="$3"
InstallDir="$4"
- llvmgccDir="$5"
case $Flavor in
Release | Release-64 )
@@ -186,24 +200,26 @@ function configure_llvmCore() {
Assertions="yes"
;;
* )
- echo "# Invalid flavor $Flavor!"
+ echo "# Invalid flavor '$Flavor'"
echo ""
return
;;
esac
+ echo "# Using C compiler: $c_compiler"
+ echo "# Using C++ compiler: $cxx_compiler"
+
cd $ObjDir
echo "# Configuring llvm $Release-rc$RC $Flavor"
- echo "# $llvmCore_srcdir/configure --prefix=$InstallDir \
+ echo "# $BuildDir/llvm.src/configure --prefix=$InstallDir \
--enable-optimized=$Optimized \
- --enable-assertions=$Assertions \
- --with-llvmgccdir=$llvmgccDir"
- $llvmCore_srcdir/configure --prefix=$InstallDir \
+ --enable-assertions=$Assertions"
+ env CC=$c_compiler CXX=$cxx_compiler \
+ $BuildDir/llvm.src/configure --prefix=$InstallDir \
--enable-optimized=$Optimized \
--enable-assertions=$Assertions \
- --with-llvmgccdir=$llvmgccDir \
- > $LogDir/llvm.configure.$Release-rc$RC-Phase$Phase-$Flavor.log 2>&1
- cd -
+ 2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log
+ cd $BuildDir
}
function build_llvmCore() {
@@ -212,25 +228,21 @@ function build_llvmCore() {
ObjDir="$3"
ExtraOpts=""
- CompilerFlags=""
- if [ "$Phase" = "2" ]; then
- CompilerFlags="CC=$llvmgccDir/bin/llvm-gcc CXX=$llvmgccDir/bin/llvm-g++"
- fi
if [ "$Flavor" = "Release-64" ]; then
ExtraOpts="EXTRA_OPTIONS=-m64"
fi
cd $ObjDir
echo "# Compiling llvm $Release-rc$RC $Flavor"
- echo "# make -j $NumJobs VERBOSE=1 $ExtraOpts"
- make -j $NumJobs VERBOSE=1 $ExtraOpts $CompilerFlags \
- > $LogDir/llvm.make.$Release-rc$RC-Phase$Phase-$Flavor.log 2>&1
+ echo "# ${MAKE} -j $NumJobs VERBOSE=1 $ExtraOpts"
+ ${MAKE} -j $NumJobs VERBOSE=1 $ExtraOpts \
+ 2>&1 | tee $LogDir/llvm.make-Phase$Phase-$Flavor.log
echo "# Installing llvm $Release-rc$RC $Flavor"
- echo "# make install"
- make install \
- > $LogDir/llvm.install.$Release-rc$RC-Phase$Phase-$Flavor.log 2>&1
- cd -
+ echo "# ${MAKE} install"
+ ${MAKE} install \
+ 2>&1 | tee $LogDir/llvm.install-Phase$Phase-$Flavor.log
+ cd $BuildDir
}
function test_llvmCore() {
@@ -239,75 +251,27 @@ function test_llvmCore() {
ObjDir="$3"
cd $ObjDir
- make check \
- > $LogDir/llvm.check.$Release-rc$RC-Phase$Phase-$Flavor.log 2>&1
- make -C tools/clang test \
- > $LogDir/clang.check.$Release-rc$RC-Phase$Phase-$Flavor.log 2>&1
- make unittests \
- > $LogDir/llvm.unittests.$Release-rc$RC-Phase$Phase-$Flavor.log 2>&1
- cd -
+ ${MAKE} -k check-all \
+ 2>&1 | tee $LogDir/llvm.check-Phase$Phase-$Flavor.log
+ ${MAKE} -k unittests \
+ 2>&1 | tee $LogDir/llvm.unittests-Phase$Phase-$Flavor.log
+ cd $BuildDir
}
-function configure_llvm_gcc() {
- Phase="$1"
- Flavor="$2"
- ObjDir="$3"
- InstallDir="$4"
- llvmObjDir="$5"
-
- languages="c,c++"
- if [ "$do_objc" = "yes" ]; then
- languages="$languages,objc,obj-c++"
- fi
- if [ "$do_fortran" = "yes" ]; then
- languages="$languages,fortran"
- fi
- if [ "$do_ada" = "yes" ]; then
- languages="$languages,ada"
- fi
-
- cd $ObjDir
- echo "# Configuring llvm-gcc $Release-rc$RC $Flavor"
- echo "# $llvmgcc42_srcdir/configure --prefix=$InstallDir \
- --program-prefix=llvm- --enable-llvm=$llvmObjDir \
- --enable-languages=$languages"
- $llvmgcc42_srcdir/configure --prefix=$InstallDir \
- --program-prefix=llvm- --enable-llvm=$llvmObjDir \
- --enable-languages=$languages \
- > $LogDir/llvm-gcc.configure.$Release-rc$RC-Phase$Phase-$Flavor.log 2>&1
- cd -
-}
-
-function build_llvm_gcc() {
- Phase="$1"
- Flavor="$2"
- ObjDir="$3"
- llvmgccDir="$4"
-
- CompilerFlags=""
- if [ "$Phase" = "2" ]; then
- CompilerFlags="CC=$llvmgccDir/bin/llvm-gcc CXX=$llvmgccDir/bin/llvm-g++"
- fi
-
- cd $ObjDir
- echo "# Compiling llvm-gcc $Release-rc$RC $Flavor"
- echo "# make -j $NumJobs bootstrap LLVM_VERSION_INFO=$Release"
- make -j $NumJobs bootstrap LLVM_VERSION_INFO=$Release $CompilerFlags \
- > $LogDir/llvm-gcc.make.$Release-rc$RC-Phase$Phase-$Flavor.log 2>&1
-
- echo "# Installing llvm-gcc $Release-rc$RC $Flavor"
- echo "# make install"
- make install \
- > $LogDir/llvm-gcc.install.$Release-rc$RC-Phase$Phase-$Flavor.log 2>&1
- cd -
-}
+set -e # Exit if any command fails
if [ "$do_checkout" = "yes" ]; then
export_sources
fi
(
-Flavors="Debug Release Release+Asserts"
+Flavors="Release"
+if [ "$do_debug" = "yes" ]; then
+ Flavors="Debug $Flavors"
+fi
+if [ "$do_asserts" = "yes" ]; then
+ Flavors="$Flavors Release+Asserts"
+fi
if [ "$do_64bit" = "yes" ]; then
Flavors="$Flavors Release-64"
fi
@@ -329,69 +293,71 @@ for Flavor in $Flavors ; do
llvmCore_phase2_objdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-rc$RC.obj
llvmCore_phase2_installdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-rc$RC.install
+ llvmCore_phase3_objdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-rc$RC.obj
+ llvmCore_phase3_installdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-rc$RC.install
+
rm -rf $llvmCore_phase1_objdir
rm -rf $llvmCore_phase1_installdir
rm -rf $llvmCore_phase2_objdir
rm -rf $llvmCore_phase2_installdir
+ rm -rf $llvmCore_phase3_objdir
+ rm -rf $llvmCore_phase3_installdir
mkdir -p $llvmCore_phase1_objdir
mkdir -p $llvmCore_phase1_installdir
mkdir -p $llvmCore_phase2_objdir
mkdir -p $llvmCore_phase2_installdir
-
- llvmgcc42_phase1_objdir=$BuildDir/Phase1/$Flavor/llvmgcc42-$Release-rc$RC.obj
- llvmgcc42_phase1_installdir=$BuildDir/Phase1/$Flavor/llvmgcc42-$Release-rc$RC.install
-
- llvmgcc42_phase2_objdir=$BuildDir/Phase2/$Flavor/llvmgcc42-$Release-rc$RC.obj
- llvmgcc42_phase2_installdir=$BuildDir/Phase2/$Flavor/llvmgcc42-$Release-rc$RC.install
-
- rm -rf $llvmgcc42_phase1_objdir
- rm -rf $llvmgcc42_phase1_installdir
- rm -rf $llvmgcc42_phase2_objdir
- rm -rf $llvmgcc42_phase2_installdir
-
- mkdir -p $llvmgcc42_phase1_objdir
- mkdir -p $llvmgcc42_phase1_installdir
- mkdir -p $llvmgcc42_phase2_objdir
- mkdir -p $llvmgcc42_phase2_installdir
+ mkdir -p $llvmCore_phase3_objdir
+ mkdir -p $llvmCore_phase3_installdir
############################################################################
# Phase 1: Build llvmCore and llvmgcc42
echo "# Phase 1: Building llvmCore"
configure_llvmCore 1 $Flavor \
- $llvmCore_phase1_objdir $llvmCore_phase1_installdir \
- $llvmgcc42_phase1_installdir
+ $llvmCore_phase1_objdir $llvmCore_phase1_installdir
build_llvmCore 1 $Flavor \
$llvmCore_phase1_objdir
- echo "# Phase 1: Building llvmgcc42"
- configure_llvm_gcc 1 $Flavor \
- $llvmgcc42_phase1_objdir $llvmgcc42_phase1_installdir \
- $llvmCore_phase1_objdir
- build_llvm_gcc 1 $Flavor \
- $llvmgcc42_phase1_objdir $llvmgcc42_phase1_installdir
-
############################################################################
- # Phase 2: Build llvmCore with newly built llvmgcc42 from phase 1.
+ # Phase 2: Build llvmCore with newly built clang from phase 1.
+ c_compiler=$llvmCore_phase1_installdir/bin/clang
+ cxx_compiler=$llvmCore_phase1_installdir/bin/clang++
echo "# Phase 2: Building llvmCore"
configure_llvmCore 2 $Flavor \
- $llvmCore_phase2_objdir $llvmCore_phase2_installdir \
- $llvmgcc42_phase1_installdir
+ $llvmCore_phase2_objdir $llvmCore_phase2_installdir
build_llvmCore 2 $Flavor \
$llvmCore_phase2_objdir
- echo "# Phase 2: Building llvmgcc42"
- configure_llvm_gcc 2 $Flavor \
- $llvmgcc42_phase2_objdir $llvmgcc42_phase2_installdir \
- $llvmCore_phase2_objdir
- build_llvm_gcc 2 $Flavor \
- $llvmgcc42_phase2_objdir $llvmgcc42_phase1_installdir
+ ############################################################################
+ # Phase 3: Build llvmCore with newly built clang from phase 2.
+ c_compiler=$llvmCore_phase2_installdir/bin/clang
+ cxx_compiler=$llvmCore_phase2_installdir/bin/clang++
+ echo "# Phase 3: Building llvmCore"
+ configure_llvmCore 3 $Flavor \
+ $llvmCore_phase3_objdir $llvmCore_phase3_installdir
+ build_llvmCore 3 $Flavor \
+ $llvmCore_phase3_objdir
- echo "# Testing - built with llvmgcc42"
- test_llvmCore 2 $Flavor $llvmCore_phase2_objdir
+ ############################################################################
+ # Testing: Test phase 3
+ echo "# Testing - built with clang"
+ test_llvmCore 3 $Flavor $llvmCore_phase3_objdir
+
+ ############################################################################
+ # Compare .o files between Phase2 and Phase3 and report which ones differ.
+ echo
+ echo "# Comparing Phase 2 and Phase 3 files"
+ for o in `find $llvmCore_phase2_objdir -name '*.o'` ; do
+ p3=`echo $o | sed -e 's,Phase2,Phase3,'`
+ if ! cmp --ignore-initial=16 $o $p3 > /dev/null 2>&1 ; then
+ echo "file `basename $o` differs between phase 2 and phase 3"
+ fi
+ done
done
) 2>&1 | tee $LogDir/testing.$Release-rc$RC.log
+set +e
+
# Woo hoo!
echo "### Testing Finished ###"
echo "### Logs: $LogDir"
diff --git a/utils/unittest/CMakeLists.txt b/utils/unittest/CMakeLists.txt
index 29218bb..73491f0 100644
--- a/utils/unittest/CMakeLists.txt
+++ b/utils/unittest/CMakeLists.txt
@@ -32,6 +32,7 @@ add_llvm_library(gtest
googletest/gtest-death-test.cc
googletest/gtest-filepath.cc
googletest/gtest-port.cc
+ googletest/gtest-printers.cc
googletest/gtest-test-part.cc
googletest/gtest-typed-test.cc
)
diff --git a/utils/unittest/googletest/README.LLVM b/utils/unittest/googletest/README.LLVM
index d6e6f98..51340e9 100644
--- a/utils/unittest/googletest/README.LLVM
+++ b/utils/unittest/googletest/README.LLVM
@@ -1,14 +1,14 @@
LLVM notes
----------
-This directory contains Google Test 1.5.0, with all elements removed except for
+This directory contains Google Test 1.6.0, with all elements removed except for
the actual source code, to minimize the addition to the LLVM distribution.
Cleaned up as follows:
# Remove all the unnecessary files and directories
$ rm -f aclocal* CMakeLists.txt configure* Makefile* CHANGES CONTRIBUTORS README
-$ rm -rf build-aux codegear fused-src m4 make msvc samples scripts test xcode
+$ rm -rf build-aux cmake codegear fused-src m4 make msvc samples scripts test xcode
$ rm -f `find . -name \*\.pump`
# Move all the source files to the current directory
@@ -21,6 +21,8 @@ $ mv *.h include/gtest/internal/
# Update paths to the included files
$ perl -pi -e 's|^#include "src/|#include "gtest/internal/|' *.cc
+$ rm -f gtest-all.cc gtest_main.cc
+
$ mv COPYING LICENSE.TXT
diff --git a/utils/unittest/googletest/gtest-death-test.cc b/utils/unittest/googletest/gtest-death-test.cc
index e4199de..6589385 100644
--- a/utils/unittest/googletest/gtest-death-test.cc
+++ b/utils/unittest/googletest/gtest-death-test.cc
@@ -31,31 +31,31 @@
//
// This file implements death tests.
-#include <gtest/gtest-death-test.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/gtest-death-test.h"
+#include "gtest/internal/gtest-port.h"
#if GTEST_HAS_DEATH_TEST
-#if GTEST_OS_MAC
-#include <crt_externs.h>
-#endif // GTEST_OS_MAC
+# if GTEST_OS_MAC
+# include <crt_externs.h>
+# endif // GTEST_OS_MAC
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+# include <stdarg.h>
-#if GTEST_OS_WINDOWS
-#include <windows.h>
-#else
-#include <sys/mman.h>
-#include <sys/wait.h>
-#endif // GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
+# include <windows.h>
+# else
+# include <sys/mman.h>
+# include <sys/wait.h>
+# endif // GTEST_OS_WINDOWS
#endif // GTEST_HAS_DEATH_TEST
-#include <gtest/gtest-message.h>
-#include <gtest/internal/gtest-string.h>
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
@@ -113,14 +113,18 @@ ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
// ExitedWithCode function-call operator.
bool ExitedWithCode::operator()(int exit_status) const {
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
+
return exit_status == exit_code_;
-#else
+
+# else
+
return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
-#endif // GTEST_OS_WINDOWS
+
+# endif // GTEST_OS_WINDOWS
}
-#if !GTEST_OS_WINDOWS
+# if !GTEST_OS_WINDOWS
// KilledBySignal constructor.
KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
}
@@ -129,7 +133,7 @@ KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
bool KilledBySignal::operator()(int exit_status) const {
return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
}
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
namespace internal {
@@ -139,20 +143,25 @@ namespace internal {
// specified by wait(2).
static String ExitSummary(int exit_code) {
Message m;
-#if GTEST_OS_WINDOWS
+
+# if GTEST_OS_WINDOWS
+
m << "Exited with exit status " << exit_code;
-#else
+
+# else
+
if (WIFEXITED(exit_code)) {
m << "Exited with exit status " << WEXITSTATUS(exit_code);
} else if (WIFSIGNALED(exit_code)) {
m << "Terminated by signal " << WTERMSIG(exit_code);
}
-#ifdef WCOREDUMP
+# ifdef WCOREDUMP
if (WCOREDUMP(exit_code)) {
m << " (core dumped)";
}
-#endif
-#endif // GTEST_OS_WINDOWS
+# endif
+# endif // GTEST_OS_WINDOWS
+
return m.GetString();
}
@@ -162,7 +171,7 @@ bool ExitedUnsuccessfully(int exit_status) {
return !ExitedWithCode(0)(exit_status);
}
-#if !GTEST_OS_WINDOWS
+# if !GTEST_OS_WINDOWS
// Generates a textual failure message when a death test finds more than
// one thread running, or cannot determine the number of threads, prior
// to executing the given statement. It is the responsibility of the
@@ -177,20 +186,24 @@ static String DeathTestThreadWarning(size_t thread_count) {
msg << "detected " << thread_count << " threads.";
return msg.GetString();
}
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
// Flag characters for reporting a death test that did not die.
static const char kDeathTestLived = 'L';
static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
static const char kDeathTestInternalError = 'I';
-// An enumeration describing all of the possible ways that a death test
-// can conclude. DIED means that the process died while executing the
-// test code; LIVED means that process lived beyond the end of the test
-// code; and RETURNED means that the test statement attempted a "return,"
-// which is not allowed. IN_PROGRESS means the test has not yet
-// concluded.
-enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED };
+// An enumeration describing all of the possible ways that a death test can
+// conclude. DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception. IN_PROGRESS means the test
+// has not yet concluded.
+// TODO(vladl@google.com): Unify names and possibly values for
+// AbortReason, DeathTestOutcome, and flag characters above.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
// Routine for aborting the program which is safe to call from an
// exec-style death test child process, in which case the error
@@ -212,13 +225,13 @@ void DeathTestAbort(const String& message) {
} else {
fprintf(stderr, "%s", message.c_str());
fflush(stderr);
- abort();
+ posix::Abort();
}
}
// A replacement for CHECK that calls DeathTestAbort if the assertion
// fails.
-#define GTEST_DEATH_TEST_CHECK_(expression) \
+# define GTEST_DEATH_TEST_CHECK_(expression) \
do { \
if (!::testing::internal::IsTrue(expression)) { \
DeathTestAbort(::testing::internal::String::Format( \
@@ -234,7 +247,7 @@ void DeathTestAbort(const String& message) {
// evaluates the expression as long as it evaluates to -1 and sets
// errno to EINTR. If the expression evaluates to -1 but errno is
// something other than EINTR, DeathTestAbort is called.
-#define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
+# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
do { \
int gtest_retval; \
do { \
@@ -388,6 +401,9 @@ void DeathTestImpl::ReadAndInterpretStatusByte() {
case kDeathTestReturned:
set_outcome(RETURNED);
break;
+ case kDeathTestThrew:
+ set_outcome(THREW);
+ break;
case kDeathTestLived:
set_outcome(LIVED);
break;
@@ -416,19 +432,46 @@ void DeathTestImpl::Abort(AbortReason reason) {
// it finds any data in our pipe. So, here we write a single flag byte
// to the pipe, then exit.
const char status_ch =
- reason == TEST_DID_NOT_DIE ? kDeathTestLived : kDeathTestReturned;
+ reason == TEST_DID_NOT_DIE ? kDeathTestLived :
+ reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
+
GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
- GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(write_fd()));
+ // We are leaking the descriptor here because on some platforms (i.e.,
+ // when built as Windows DLL), destructors of global objects will still
+ // run after calling _exit(). On such systems, write_fd_ will be
+ // indirectly closed from the destructor of UnitTestImpl, causing double
+ // close if it is also closed here. On debug configurations, double close
+ // may assert. As there are no in-process buffers to flush here, we are
+ // relying on the OS to close the descriptor after the process terminates
+ // when the destructors are not run.
_exit(1); // Exits w/o any normal exit hooks (we were supposed to crash)
}
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+ ::std::string ret;
+ for (size_t at = 0; ; ) {
+ const size_t line_end = output.find('\n', at);
+ ret += "[ DEATH ] ";
+ if (line_end == ::std::string::npos) {
+ ret += output.substr(at);
+ break;
+ }
+ ret += output.substr(at, line_end + 1 - at);
+ at = line_end + 1;
+ }
+ return ret;
+}
+
// Assesses the success or failure of a death test, using both private
// members which have previously been set, and one argument:
//
// Private data members:
// outcome: An enumeration describing how the death test
-// concluded: DIED, LIVED, or RETURNED. The death test fails
-// in the latter two cases.
+// concluded: DIED, LIVED, THREW, or RETURNED. The death test
+// fails in the latter three cases.
// status: The exit status of the child process. On *nix, it is in the
// in the format specified by wait(2). On Windows, this is the
// value supplied to the ExitProcess() API or a numeric code
@@ -457,11 +500,15 @@ bool DeathTestImpl::Passed(bool status_ok) {
switch (outcome()) {
case LIVED:
buffer << " Result: failed to die.\n"
- << " Error msg: " << error_message;
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
+ break;
+ case THREW:
+ buffer << " Result: threw an exception.\n"
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
break;
case RETURNED:
buffer << " Result: illegal return in test statement.\n"
- << " Error msg: " << error_message;
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
break;
case DIED:
if (status_ok) {
@@ -471,11 +518,12 @@ bool DeathTestImpl::Passed(bool status_ok) {
} else {
buffer << " Result: died but not with expected error.\n"
<< " Expected: " << regex()->pattern() << "\n"
- << "Actual msg: " << error_message;
+ << "Actual msg:\n" << FormatDeathTestOutput(error_message);
}
} else {
buffer << " Result: died but not with expected exit code:\n"
- << " " << ExitSummary(status()) << "\n";
+ << " " << ExitSummary(status()) << "\n"
+ << "Actual msg:\n" << FormatDeathTestOutput(error_message);
}
break;
case IN_PROGRESS:
@@ -488,7 +536,7 @@ bool DeathTestImpl::Passed(bool status_ok) {
return success;
}
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
// WindowsDeathTest implements death tests on Windows. Due to the
// specifics of starting new processes on Windows, death tests there are
// always threadsafe, and Google Test considers the
@@ -519,11 +567,11 @@ bool DeathTestImpl::Passed(bool status_ok) {
//
class WindowsDeathTest : public DeathTestImpl {
public:
- WindowsDeathTest(const char* statement,
- const RE* regex,
+ WindowsDeathTest(const char* a_statement,
+ const RE* a_regex,
const char* file,
int line)
- : DeathTestImpl(statement, regex), file_(file), line_(line) {}
+ : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
// All of these virtual functions are inherited from DeathTest.
virtual int Wait();
@@ -580,12 +628,12 @@ int WindowsDeathTest::Wait() {
GTEST_DEATH_TEST_CHECK_(
WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
INFINITE));
- DWORD status;
- GTEST_DEATH_TEST_CHECK_(::GetExitCodeProcess(child_handle_.Get(), &status)
- != FALSE);
+ DWORD status_code;
+ GTEST_DEATH_TEST_CHECK_(
+ ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
child_handle_.Reset();
- set_status(static_cast<int>(status));
- return this->status();
+ set_status(static_cast<int>(status_code));
+ return status();
}
// The AssumeRole process for a Windows death test. It creates a child
@@ -684,7 +732,7 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
set_spawned(true);
return OVERSEE_TEST;
}
-#else // We are not on Windows.
+# else // We are not on Windows.
// ForkingDeathTest provides implementations for most of the abstract
// methods of the DeathTest interface. Only the AssumeRole method is
@@ -832,19 +880,19 @@ struct ExecDeathTestArgs {
int close_fd; // File descriptor to close; the read end of a pipe
};
-#if GTEST_OS_MAC
+# if GTEST_OS_MAC
inline char** GetEnviron() {
// When Google Test is built as a framework on MacOS X, the environ variable
// is unavailable. Apple's documentation (man environ) recommends using
// _NSGetEnviron() instead.
return *_NSGetEnviron();
}
-#else
+# else
// Some POSIX platforms expect you to declare environ. extern "C" makes
// it reside in the global namespace.
extern "C" char** environ;
inline char** GetEnviron() { return environ; }
-#endif // GTEST_OS_MAC
+# endif // GTEST_OS_MAC
// The main function for a threadsafe-style death test child process.
// This function is called in a clone()-ed process and thus must avoid
@@ -884,6 +932,11 @@ static int ExecDeathTestChildMain(void* child_arg) {
// This could be accomplished more elegantly by a single recursive
// function, but we want to guard against the unlikely possibility of
// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+bool StackLowerThanAddress(const void* ptr) GTEST_NO_INLINE_;
bool StackLowerThanAddress(const void* ptr) {
int dummy;
return &dummy < ptr;
@@ -901,7 +954,7 @@ static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
ExecDeathTestArgs args = { argv, close_fd };
pid_t child_pid = -1;
-#if GTEST_HAS_CLONE
+# if GTEST_HAS_CLONE
const bool use_fork = GTEST_FLAG(death_test_use_fork);
if (!use_fork) {
@@ -918,9 +971,9 @@ static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
}
-#else
+# else
const bool use_fork = true;
-#endif // GTEST_HAS_CLONE
+# endif // GTEST_HAS_CLONE
if (use_fork && (child_pid = fork()) == 0) {
ExecDeathTestChildMain(&args);
@@ -981,7 +1034,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
return OVERSEE_TEST;
}
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
// Creates a concrete DeathTest-derived class that depends on the
// --gtest_death_test_style flag, and sets the pointer pointed to
@@ -1012,18 +1065,23 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
}
}
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
+
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
GTEST_FLAG(death_test_style) == "fast") {
*test = new WindowsDeathTest(statement, regex, file, line);
}
-#else
+
+# else
+
if (GTEST_FLAG(death_test_style) == "threadsafe") {
*test = new ExecDeathTest(statement, regex, file, line);
} else if (GTEST_FLAG(death_test_style) == "fast") {
*test = new NoExecDeathTest(statement, regex);
}
-#endif // GTEST_OS_WINDOWS
+
+# endif // GTEST_OS_WINDOWS
+
else { // NOLINT - this is more readable than unbalanced brackets inside #if.
DeathTest::set_last_death_test_message(String::Format(
"Unknown death test style \"%s\" encountered",
@@ -1054,7 +1112,7 @@ static void SplitString(const ::std::string& str, char delimiter,
dest->swap(parsed);
}
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
// Recreates the pipe and event handles from the provided parameters,
// signals the event, and returns a file descriptor wrapped around the pipe
// handle. This function is called in the child process only.
@@ -1118,7 +1176,7 @@ int GetStatusFileDescriptor(unsigned int parent_process_id,
return write_fd;
}
-#endif // GTEST_OS_WINDOWS
+# endif // GTEST_OS_WINDOWS
// Returns a newly created InternalRunDeathTestFlag object with fields
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
@@ -1134,7 +1192,8 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
int write_fd = -1;
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
+
unsigned int parent_process_id = 0;
size_t write_handle_as_size_t = 0;
size_t event_handle_as_size_t = 0;
@@ -1152,7 +1211,8 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
write_fd = GetStatusFileDescriptor(parent_process_id,
write_handle_as_size_t,
event_handle_as_size_t);
-#else
+# else
+
if (fields.size() != 4
|| !ParseNaturalNumber(fields[1], &line)
|| !ParseNaturalNumber(fields[2], &index)
@@ -1161,7 +1221,9 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
"Bad --gtest_internal_run_death_test flag: %s",
GTEST_FLAG(internal_run_death_test).c_str()));
}
-#endif // GTEST_OS_WINDOWS
+
+# endif // GTEST_OS_WINDOWS
+
return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
}
diff --git a/utils/unittest/googletest/gtest-filepath.cc b/utils/unittest/googletest/gtest-filepath.cc
index 8d1d67e..bc61009 100644
--- a/utils/unittest/googletest/gtest-filepath.cc
+++ b/utils/unittest/googletest/gtest-filepath.cc
@@ -29,35 +29,35 @@
//
// Authors: keith.ray@gmail.com (Keith Ray)
-#include <gtest/internal/gtest-filepath.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-port.h"
#include <stdlib.h>
#if GTEST_OS_WINDOWS_MOBILE
-#include <windows.h>
+# include <windows.h>
#elif GTEST_OS_WINDOWS
-#include <direct.h>
-#include <io.h>
-#elif GTEST_OS_SYMBIAN
-// Symbian OpenC has PATH_MAX in sys/syslimits.h
-#include <sys/syslimits.h>
+# include <direct.h>
+# include <io.h>
+#elif GTEST_OS_SYMBIAN || GTEST_OS_NACL
+// Symbian OpenC and NaCl have PATH_MAX in sys/syslimits.h
+# include <sys/syslimits.h>
#else
-#include <limits.h>
-#include <climits> // Some Linux distributions define PATH_MAX here.
+# include <limits.h>
+# include <climits> // Some Linux distributions define PATH_MAX here.
#endif // GTEST_OS_WINDOWS_MOBILE
#if GTEST_OS_WINDOWS
-#define GTEST_PATH_MAX_ _MAX_PATH
+# define GTEST_PATH_MAX_ _MAX_PATH
#elif defined(PATH_MAX)
-#define GTEST_PATH_MAX_ PATH_MAX
+# define GTEST_PATH_MAX_ PATH_MAX
#elif defined(_XOPEN_PATH_MAX)
-#define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
#else
-#define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
#endif // GTEST_OS_WINDOWS
-#include <gtest/internal/gtest-string.h>
+#include "gtest/internal/gtest-string.h"
namespace testing {
namespace internal {
@@ -71,16 +71,16 @@ const char kPathSeparator = '\\';
const char kAlternatePathSeparator = '/';
const char kPathSeparatorString[] = "\\";
const char kAlternatePathSeparatorString[] = "/";
-#if GTEST_OS_WINDOWS_MOBILE
+# if GTEST_OS_WINDOWS_MOBILE
// Windows CE doesn't have a current directory. You should not use
// the current directory in tests on Windows CE, but this at least
// provides a reasonable fallback.
const char kCurrentDirectoryString[] = "\\";
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
const DWORD kInvalidFileAttributes = 0xffffffff;
-#else
+# else
const char kCurrentDirectoryString[] = ".\\";
-#endif // GTEST_OS_WINDOWS_MOBILE
+# endif // GTEST_OS_WINDOWS_MOBILE
#else
const char kPathSeparator = '/';
const char kPathSeparatorString[] = "/";
diff --git a/utils/unittest/googletest/gtest-port.cc b/utils/unittest/googletest/gtest-port.cc
index 5609599..07e5bb3 100644
--- a/utils/unittest/googletest/gtest-port.cc
+++ b/utils/unittest/googletest/gtest-port.cc
@@ -29,30 +29,32 @@
//
// Author: wan@google.com (Zhanyong Wan)
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#if GTEST_OS_WINDOWS_MOBILE
-#include <windows.h> // For TerminateProcess()
+# include <windows.h> // For TerminateProcess()
#elif GTEST_OS_WINDOWS
-#include <io.h>
-#include <sys/stat.h>
+# include <io.h>
+# include <sys/stat.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif // GTEST_OS_WINDOWS_MOBILE
#if GTEST_OS_MAC
-#include <mach/mach_init.h>
-#include <mach/task.h>
-#include <mach/vm_map.h>
+# include <mach/mach_init.h>
+# include <mach/task.h>
+# include <mach/vm_map.h>
#endif // GTEST_OS_MAC
-#include <gtest/gtest-spi.h>
-#include <gtest/gtest-message.h>
-#include <gtest/internal/gtest-string.h>
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
@@ -180,20 +182,20 @@ bool IsInSet(char ch, const char* str) {
// Returns true iff ch belongs to the given classification. Unlike
// similar functions in <ctype.h>, these aren't affected by the
// current locale.
-bool IsDigit(char ch) { return '0' <= ch && ch <= '9'; }
-bool IsPunct(char ch) {
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
}
bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
-bool IsWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
-bool IsWordChar(char ch) {
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
('0' <= ch && ch <= '9') || ch == '_';
}
// Returns true iff "\\c" is a supported escape sequence.
bool IsValidEscape(char c) {
- return (IsPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+ return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
}
// Returns true iff the given atom (specified by escaped and pattern)
@@ -201,19 +203,19 @@ bool IsValidEscape(char c) {
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
if (escaped) { // "\\p" where p is pattern_char.
switch (pattern_char) {
- case 'd': return IsDigit(ch);
- case 'D': return !IsDigit(ch);
+ case 'd': return IsAsciiDigit(ch);
+ case 'D': return !IsAsciiDigit(ch);
case 'f': return ch == '\f';
case 'n': return ch == '\n';
case 'r': return ch == '\r';
- case 's': return IsWhiteSpace(ch);
- case 'S': return !IsWhiteSpace(ch);
+ case 's': return IsAsciiWhiteSpace(ch);
+ case 'S': return !IsAsciiWhiteSpace(ch);
case 't': return ch == '\t';
case 'v': return ch == '\v';
- case 'w': return IsWordChar(ch);
- case 'W': return !IsWordChar(ch);
+ case 'w': return IsAsciiWordChar(ch);
+ case 'W': return !IsAsciiWordChar(ch);
}
- return IsPunct(pattern_char) && pattern_char == ch;
+ return IsAsciiPunct(pattern_char) && pattern_char == ch;
}
return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
@@ -422,6 +424,38 @@ void RE::Init(const char* regex) {
#endif // GTEST_USES_POSIX_RE
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+ const char* const file_name = file == NULL ? kUnknownFile : file;
+
+ if (line < 0) {
+ return String::Format("%s:", file_name).c_str();
+ }
+#ifdef _MSC_VER
+ return String::Format("%s(%d):", file_name, line).c_str();
+#else
+ return String::Format("%s:%d:", file_name, line).c_str();
+#endif // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
+ const char* file, int line) {
+ const char* const file_name = file == NULL ? kUnknownFile : file;
+
+ if (line < 0)
+ return file_name;
+ else
+ return String::Format("%s:%d", file_name, line).c_str();
+}
+
GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
: severity_(severity) {
@@ -444,18 +478,19 @@ GTestLog::~GTestLog() {
// Disable Microsoft deprecation warnings for POSIX functions called from
// this class (creat, dup, dup2, and close)
#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable: 4996)
+# pragma warning(push)
+# pragma warning(disable: 4996)
#endif // _MSC_VER
-#if GTEST_HAS_STREAM_REDIRECTION_
+#if GTEST_HAS_STREAM_REDIRECTION
// Object that captures an output stream (stdout/stderr).
class CapturedStream {
public:
// The ctor redirects the stream to a temporary file.
CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
-#if GTEST_OS_WINDOWS
+
+# if GTEST_OS_WINDOWS
char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
@@ -470,14 +505,14 @@ class CapturedStream {
GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
<< temp_file_path;
filename_ = temp_file_path;
-#else
+# else
// There's no guarantee that a test has write access to the
// current directory, so we create the temporary file in the /tmp
// directory instead.
char name_template[] = "/tmp/captured_stream.XXXXXX";
const int captured_fd = mkstemp(name_template);
filename_ = name_template;
-#endif // GTEST_OS_WINDOWS
+# endif // GTEST_OS_WINDOWS
fflush(NULL);
dup2(captured_fd, fd_);
close(captured_fd);
@@ -546,9 +581,9 @@ String CapturedStream::ReadEntireFile(FILE* file) {
return content;
}
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif // _MSC_VER
+# ifdef _MSC_VER
+# pragma warning(pop)
+# endif // _MSC_VER
static CapturedStream* g_captured_stderr = NULL;
static CapturedStream* g_captured_stdout = NULL;
@@ -588,7 +623,7 @@ String GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); }
// Stops capturing stderr and returns the captured string.
String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
-#endif // GTEST_HAS_STREAM_REDIRECTION_
+#endif // GTEST_HAS_STREAM_REDIRECTION
#if GTEST_HAS_DEATH_TEST
@@ -618,7 +653,7 @@ static String FlagToEnvVar(const char* flag) {
Message env_var;
for (size_t i = 0; i != full_flag.length(); i++) {
- env_var << static_cast<char>(toupper(full_flag.c_str()[i]));
+ env_var << ToUpper(full_flag.c_str()[i]);
}
return env_var.GetString();
diff --git a/utils/unittest/googletest/gtest-printers.cc b/utils/unittest/googletest/gtest-printers.cc
new file mode 100644
index 0000000..ed63c7b
--- /dev/null
+++ b/utils/unittest/googletest/gtest-printers.cc
@@ -0,0 +1,356 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// It uses the << operator when possible, and prints the bytes in the
+// object otherwise. A user can override its behavior for a class
+// type Foo by defining either operator<<(::std::ostream&, const Foo&)
+// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
+// defines Foo.
+
+#include "gtest/gtest-printers.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <ostream> // NOLINT
+#include <string>
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+
+namespace {
+
+using ::std::ostream;
+
+#if GTEST_OS_WINDOWS_MOBILE // Windows CE does not define _snprintf_s.
+# define snprintf _snprintf
+#elif _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf.
+# define snprintf _snprintf_s
+#elif _MSC_VER
+# define snprintf _snprintf
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+// Prints a segment of bytes in the given object.
+void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
+ size_t count, ostream* os) {
+ char text[5] = "";
+ for (size_t i = 0; i != count; i++) {
+ const size_t j = start + i;
+ if (i != 0) {
+ // Organizes the bytes into groups of 2 for easy parsing by
+ // human.
+ if ((j % 2) == 0)
+ *os << ' ';
+ else
+ *os << '-';
+ }
+ snprintf(text, sizeof(text), "%02X", obj_bytes[j]);
+ *os << text;
+ }
+}
+
+// Prints the bytes in the given value to the given ostream.
+void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
+ ostream* os) {
+ // Tells the user how big the object is.
+ *os << count << "-byte object <";
+
+ const size_t kThreshold = 132;
+ const size_t kChunkSize = 64;
+ // If the object size is bigger than kThreshold, we'll have to omit
+ // some details by printing only the first and the last kChunkSize
+ // bytes.
+ // TODO(wan): let the user control the threshold using a flag.
+ if (count < kThreshold) {
+ PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
+ } else {
+ PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
+ *os << " ... ";
+ // Rounds up to 2-byte boundary.
+ const size_t resume_pos = (count - kChunkSize + 1)/2*2;
+ PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
+ }
+ *os << ">";
+}
+
+} // namespace
+
+namespace internal2 {
+
+// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
+// given object. The delegation simplifies the implementation, which
+// uses the << operator and thus is easier done outside of the
+// ::testing::internal namespace, which contains a << operator that
+// sometimes conflicts with the one in STL.
+void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
+ ostream* os) {
+ PrintBytesInObjectToImpl(obj_bytes, count, os);
+}
+
+} // namespace internal2
+
+namespace internal {
+
+// Depending on the value of a char (or wchar_t), we print it in one
+// of three formats:
+// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
+// - as a hexidecimal escape sequence (e.g. '\x7F'), or
+// - as a special escape sequence (e.g. '\r', '\n').
+enum CharFormat {
+ kAsIs,
+ kHexEscape,
+ kSpecialEscape
+};
+
+// Returns true if c is a printable ASCII character. We test the
+// value of c directly instead of calling isprint(), which is buggy on
+// Windows Mobile.
+inline bool IsPrintableAscii(wchar_t c) {
+ return 0x20 <= c && c <= 0x7E;
+}
+
+// Prints a wide or narrow char c as a character literal without the
+// quotes, escaping it when necessary; returns how c was formatted.
+// The template argument UnsignedChar is the unsigned version of Char,
+// which is the type of c.
+template <typename UnsignedChar, typename Char>
+static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
+ switch (static_cast<wchar_t>(c)) {
+ case L'\0':
+ *os << "\\0";
+ break;
+ case L'\'':
+ *os << "\\'";
+ break;
+ case L'\\':
+ *os << "\\\\";
+ break;
+ case L'\a':
+ *os << "\\a";
+ break;
+ case L'\b':
+ *os << "\\b";
+ break;
+ case L'\f':
+ *os << "\\f";
+ break;
+ case L'\n':
+ *os << "\\n";
+ break;
+ case L'\r':
+ *os << "\\r";
+ break;
+ case L'\t':
+ *os << "\\t";
+ break;
+ case L'\v':
+ *os << "\\v";
+ break;
+ default:
+ if (IsPrintableAscii(c)) {
+ *os << static_cast<char>(c);
+ return kAsIs;
+ } else {
+ *os << String::Format("\\x%X", static_cast<UnsignedChar>(c));
+ return kHexEscape;
+ }
+ }
+ return kSpecialEscape;
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
+ switch (c) {
+ case L'\'':
+ *os << "'";
+ return kAsIs;
+ case L'"':
+ *os << "\\\"";
+ return kSpecialEscape;
+ default:
+ return PrintAsCharLiteralTo<wchar_t>(c, os);
+ }
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) {
+ return PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
+}
+
+// Prints a wide or narrow character c and its code. '\0' is printed
+// as "'\\0'", other unprintable characters are also properly escaped
+// using the standard C++ escape sequence. The template argument
+// UnsignedChar is the unsigned version of Char, which is the type of c.
+template <typename UnsignedChar, typename Char>
+void PrintCharAndCodeTo(Char c, ostream* os) {
+ // First, print c as a literal in the most readable form we can find.
+ *os << ((sizeof(c) > 1) ? "L'" : "'");
+ const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
+ *os << "'";
+
+ // To aid user debugging, we also print c's code in decimal, unless
+ // it's 0 (in which case c was printed as '\\0', making the code
+ // obvious).
+ if (c == 0)
+ return;
+ *os << " (" << String::Format("%d", c).c_str();
+
+ // For more convenience, we print c's code again in hexidecimal,
+ // unless c was already printed in the form '\x##' or the code is in
+ // [1, 9].
+ if (format == kHexEscape || (1 <= c && c <= 9)) {
+ // Do nothing.
+ } else {
+ *os << String::Format(", 0x%X",
+ static_cast<UnsignedChar>(c)).c_str();
+ }
+ *os << ")";
+}
+
+void PrintTo(unsigned char c, ::std::ostream* os) {
+ PrintCharAndCodeTo<unsigned char>(c, os);
+}
+void PrintTo(signed char c, ::std::ostream* os) {
+ PrintCharAndCodeTo<unsigned char>(c, os);
+}
+
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
+void PrintTo(wchar_t wc, ostream* os) {
+ PrintCharAndCodeTo<wchar_t>(wc, os);
+}
+
+// Prints the given array of characters to the ostream.
+// The array starts at *begin, the length is len, it may include '\0' characters
+// and may not be null-terminated.
+static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
+ *os << "\"";
+ bool is_previous_hex = false;
+ for (size_t index = 0; index < len; ++index) {
+ const char cur = begin[index];
+ if (is_previous_hex && IsXDigit(cur)) {
+ // Previous character is of '\x..' form and this character can be
+ // interpreted as another hexadecimal digit in its number. Break string to
+ // disambiguate.
+ *os << "\" \"";
+ }
+ is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape;
+ }
+ *os << "\"";
+}
+
+// Prints a (const) char array of 'len' elements, starting at address 'begin'.
+void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
+ PrintCharsAsStringTo(begin, len, os);
+}
+
+// Prints the given array of wide characters to the ostream.
+// The array starts at *begin, the length is len, it may include L'\0'
+// characters and may not be null-terminated.
+static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len,
+ ostream* os) {
+ *os << "L\"";
+ bool is_previous_hex = false;
+ for (size_t index = 0; index < len; ++index) {
+ const wchar_t cur = begin[index];
+ if (is_previous_hex && isascii(cur) && IsXDigit(static_cast<char>(cur))) {
+ // Previous character is of '\x..' form and this character can be
+ // interpreted as another hexadecimal digit in its number. Break string to
+ // disambiguate.
+ *os << "\" L\"";
+ }
+ is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape;
+ }
+ *os << "\"";
+}
+
+// Prints the given C string to the ostream.
+void PrintTo(const char* s, ostream* os) {
+ if (s == NULL) {
+ *os << "NULL";
+ } else {
+ *os << ImplicitCast_<const void*>(s) << " pointing to ";
+ PrintCharsAsStringTo(s, strlen(s), os);
+ }
+}
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Prints the given wide C string to the ostream.
+void PrintTo(const wchar_t* s, ostream* os) {
+ if (s == NULL) {
+ *os << "NULL";
+ } else {
+ *os << ImplicitCast_<const void*>(s) << " pointing to ";
+ PrintWideCharsAsStringTo(s, wcslen(s), os);
+ }
+}
+#endif // wchar_t is native
+
+// Prints a ::string object.
+#if GTEST_HAS_GLOBAL_STRING
+void PrintStringTo(const ::string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif // GTEST_HAS_GLOBAL_STRING
+
+void PrintStringTo(const ::std::string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+// Prints a ::wstring object.
+#if GTEST_HAS_GLOBAL_WSTRING
+void PrintWideStringTo(const ::wstring& s, ostream* os) {
+ PrintWideCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
+ PrintWideCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif // GTEST_HAS_STD_WSTRING
+
+} // namespace internal
+
+} // namespace testing
diff --git a/utils/unittest/googletest/gtest-test-part.cc b/utils/unittest/googletest/gtest-test-part.cc
index 8249afe..1612780 100644
--- a/utils/unittest/googletest/gtest-test-part.cc
+++ b/utils/unittest/googletest/gtest-test-part.cc
@@ -31,7 +31,7 @@
//
// The Google C++ Testing Framework (Google Test)
-#include <gtest/gtest-test-part.h>
+#include "gtest/gtest-test-part.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
diff --git a/utils/unittest/googletest/gtest-typed-test.cc b/utils/unittest/googletest/gtest-typed-test.cc
index 3cc4b5d..a5cc88f 100644
--- a/utils/unittest/googletest/gtest-typed-test.cc
+++ b/utils/unittest/googletest/gtest-typed-test.cc
@@ -29,8 +29,8 @@
//
// Author: wan@google.com (Zhanyong Wan)
-#include <gtest/gtest-typed-test.h>
-#include <gtest/gtest.h>
+#include "gtest/gtest-typed-test.h"
+#include "gtest/gtest.h"
namespace testing {
namespace internal {
@@ -40,7 +40,7 @@ namespace internal {
// Skips to the first non-space char in str. Returns an empty string if str
// contains only whitespace characters.
static const char* SkipSpaces(const char* str) {
- while (isspace(*str))
+ while (IsSpace(*str))
str++;
return str;
}
diff --git a/utils/unittest/googletest/gtest.cc b/utils/unittest/googletest/gtest.cc
index 9aa5441..7624497 100644
--- a/utils/unittest/googletest/gtest.cc
+++ b/utils/unittest/googletest/gtest.cc
@@ -31,8 +31,8 @@
//
// The Google C++ Testing Framework (Google Test)
-#include <gtest/gtest.h>
-#include <gtest/gtest-spi.h>
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
#include <ctype.h>
#include <math.h>
@@ -43,7 +43,7 @@
#include <wctype.h>
#include <algorithm>
-#include <ostream>
+#include <ostream> // NOLINT
#include <sstream>
#include <vector>
@@ -51,72 +51,76 @@
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
-#define GTEST_HAS_GETTIMEOFDAY_ 1
+# define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <fcntl.h>
-#include <limits.h>
-#include <sched.h>
+# include <fcntl.h> // NOLINT
+# include <limits.h> // NOLINT
+# include <sched.h> // NOLINT
// Declares vsnprintf(). This header is not available on Windows.
-#include <strings.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <string>
-#include <vector>
+# include <strings.h> // NOLINT
+# include <sys/mman.h> // NOLINT
+# include <sys/time.h> // NOLINT
+# include <unistd.h> // NOLINT
+# include <string>
#elif GTEST_OS_SYMBIAN
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
#elif GTEST_OS_ZOS
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
// On z/OS we additionally need strings.h for strcasecmp.
-#include <strings.h> // NOLINT
+# include <strings.h> // NOLINT
#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE.
-#include <windows.h> // NOLINT
+# include <windows.h> // NOLINT
#elif GTEST_OS_WINDOWS // We are on Windows proper.
-#include <io.h> // NOLINT
-#include <sys/timeb.h> // NOLINT
-#include <sys/types.h> // NOLINT
-#include <sys/stat.h> // NOLINT
+# include <io.h> // NOLINT
+# include <sys/timeb.h> // NOLINT
+# include <sys/types.h> // NOLINT
+# include <sys/stat.h> // NOLINT
-#if GTEST_OS_WINDOWS_MINGW
+# if GTEST_OS_WINDOWS_MINGW
// MinGW has gettimeofday() but not _ftime64().
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
// TODO(kenton@google.com): There are other ways to get the time on
// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW
// supports these. consider using them instead.
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
-#endif // GTEST_OS_WINDOWS_MINGW
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
+# endif // GTEST_OS_WINDOWS_MINGW
// cpplint thinks that the header is already included, so we want to
// silence it.
-#include <windows.h> // NOLINT
+# include <windows.h> // NOLINT
#else
// Assume other platforms have gettimeofday().
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
-#define GTEST_HAS_GETTIMEOFDAY_ 1
+# define GTEST_HAS_GETTIMEOFDAY_ 1
// cpplint thinks that the header is already included, so we want to
// silence it.
-#include <sys/time.h> // NOLINT
-#include <unistd.h> // NOLINT
+# include <sys/time.h> // NOLINT
+# include <unistd.h> // NOLINT
#endif // GTEST_OS_LINUX
#if GTEST_HAS_EXCEPTIONS
-#include <stdexcept>
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h> // NOLINT
+# include <netdb.h> // NOLINT
#endif
// Indicates that this translation unit is part of Google Test's
@@ -129,7 +133,7 @@
#undef GTEST_IMPLEMENTATION_
#if GTEST_OS_WINDOWS
-#define vsnprintf _vsnprintf
+# define vsnprintf _vsnprintf
#endif // GTEST_OS_WINDOWS
namespace testing {
@@ -187,7 +191,7 @@ GTEST_DEFINE_bool_(
GTEST_DEFINE_bool_(
catch_exceptions,
- internal::BoolFromGTestEnv("catch_exceptions", false),
+ internal::BoolFromGTestEnv("catch_exceptions", true),
"True iff " GTEST_NAME_
" should catch exceptions and treat them as test failures.");
@@ -258,6 +262,13 @@ GTEST_DEFINE_int32_(
"The maximum number of stack frames to print when an "
"assertion fails. The valid range is 0 through 100, inclusive.");
+GTEST_DEFINE_string_(
+ stream_result_to,
+ internal::StringFromGTestEnv("stream_result_to", ""),
+ "This flag specifies the host name and the port number on which to stream "
+ "test results. Example: \"localhost:555\". The flag is effective only on "
+ "Linux.");
+
GTEST_DEFINE_bool_(
throw_on_failure,
internal::BoolFromGTestEnv("throw_on_failure", false),
@@ -490,20 +501,33 @@ bool UnitTestOptions::FilterMatchesTest(const String &test_case_name,
!MatchesFilter(full_name, negative.c_str()));
}
-#if GTEST_OS_WINDOWS
+#if GTEST_HAS_SEH
// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
// This function is useful as an __except condition.
int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
- // Google Test should handle an exception if:
+ // Google Test should handle a SEH exception if:
// 1. the user wants it to, AND
- // 2. this is not a breakpoint exception.
- return (GTEST_FLAG(catch_exceptions) &&
- exception_code != EXCEPTION_BREAKPOINT) ?
- EXCEPTION_EXECUTE_HANDLER :
- EXCEPTION_CONTINUE_SEARCH;
+ // 2. this is not a breakpoint exception, AND
+ // 3. this is not a C++ exception (VC++ implements them via SEH,
+ // apparently).
+ //
+ // SEH exception code for C++ exceptions.
+ // (see http://support.microsoft.com/kb/185294 for more information).
+ const DWORD kCxxExceptionCode = 0xe06d7363;
+
+ bool should_handle = true;
+
+ if (!GTEST_FLAG(catch_exceptions))
+ should_handle = false;
+ else if (exception_code == EXCEPTION_BREAKPOINT)
+ should_handle = false;
+ else if (exception_code == kCxxExceptionCode)
+ should_handle = false;
+
+ return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
}
-#endif // GTEST_OS_WINDOWS
+#endif // GTEST_HAS_SEH
} // namespace internal
@@ -583,7 +607,7 @@ AssertionResult HasOneFailure(const char* /* results_expr */,
const char* /* substr_expr */,
const TestPartResultArray& results,
TestPartResult::Type type,
- const char* substr) {
+ const string& substr) {
const String expected(type == TestPartResult::kFatalFailure ?
"1 fatal failure" :
"1 non-fatal failure");
@@ -594,23 +618,21 @@ AssertionResult HasOneFailure(const char* /* results_expr */,
for (int i = 0; i < results.size(); i++) {
msg << "\n" << results.GetTestPartResult(i);
}
- return AssertionFailure(msg);
+ return AssertionFailure() << msg;
}
const TestPartResult& r = results.GetTestPartResult(0);
if (r.type() != type) {
- msg << "Expected: " << expected << "\n"
- << " Actual:\n"
- << r;
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: " << expected << "\n"
+ << " Actual:\n"
+ << r;
}
- if (strstr(r.message(), substr) == NULL) {
- msg << "Expected: " << expected << " containing \""
- << substr << "\"\n"
- << " Actual:\n"
- << r;
- return AssertionFailure(msg);
+ if (strstr(r.message(), substr.c_str()) == NULL) {
+ return AssertionFailure() << "Expected: " << expected << " containing \""
+ << substr << "\"\n"
+ << " Actual:\n"
+ << r;
}
return AssertionSuccess();
@@ -622,7 +644,7 @@ AssertionResult HasOneFailure(const char* /* results_expr */,
SingleFailureChecker:: SingleFailureChecker(
const TestPartResultArray* results,
TestPartResult::Type type,
- const char* substr)
+ const string& substr)
: results_(results),
type_(type),
substr_(substr) {}
@@ -632,7 +654,7 @@ SingleFailureChecker:: SingleFailureChecker(
// type and contains the given substring. If that's not the case, a
// non-fatal failure will be generated.
SingleFailureChecker::~SingleFailureChecker() {
- EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_.c_str());
+ EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
}
DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
@@ -764,25 +786,30 @@ TimeInMillis GetTimeInMillis() {
return 0;
#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
__timeb64 now;
-#ifdef _MSC_VER
+
+# ifdef _MSC_VER
+
// MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
// (deprecated function) there.
// TODO(kenton@google.com): Use GetTickCount()? Or use
// SystemTimeToFileTime()
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4996) // Temporarily disables warning 4996.
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4996) // Temporarily disables warning 4996.
_ftime64(&now);
-#pragma warning(pop) // Restores the warning state.
-#else
+# pragma warning(pop) // Restores the warning state.
+# else
+
_ftime64(&now);
-#endif // _MSC_VER
+
+# endif // _MSC_VER
+
return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
#elif GTEST_HAS_GETTIMEOFDAY_
struct timeval now;
gettimeofday(&now, NULL);
return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
#else
-#error "Don't know how to get the current time on your system."
+# error "Don't know how to get the current time on your system."
#endif
}
@@ -918,55 +945,13 @@ Message& Message::operator <<(const ::wstring& wstr) {
}
#endif // GTEST_HAS_GLOBAL_WSTRING
-namespace internal {
-
-// Formats a value to be used in a failure message.
-
-// For a char value, we print it as a C++ char literal and as an
-// unsigned integer (both in decimal and in hexadecimal).
-String FormatForFailureMessage(char ch) {
- const unsigned int ch_as_uint = ch;
- // A String object cannot contain '\0', so we print "\\0" when ch is
- // '\0'.
- return String::Format("'%s' (%u, 0x%X)",
- ch ? String::Format("%c", ch).c_str() : "\\0",
- ch_as_uint, ch_as_uint);
-}
-
-// For a wchar_t value, we print it as a C++ wchar_t literal and as an
-// unsigned integer (both in decimal and in hexidecimal).
-String FormatForFailureMessage(wchar_t wchar) {
- // The C++ standard doesn't specify the exact size of the wchar_t
- // type. It just says that it shall have the same size as another
- // integral type, called its underlying type.
- //
- // Therefore, in order to print a wchar_t value in the numeric form,
- // we first convert it to the largest integral type (UInt64) and
- // then print the converted value.
- //
- // We use streaming to print the value as "%llu" doesn't work
- // correctly with MSVC 7.1.
- const UInt64 wchar_as_uint64 = wchar;
- Message msg;
- // A String object cannot contain '\0', so we print "\\0" when wchar is
- // L'\0'.
- char buffer[32]; // CodePointToUtf8 requires a buffer that big.
- msg << "L'"
- << (wchar ? CodePointToUtf8(static_cast<UInt32>(wchar), buffer) : "\\0")
- << "' (" << wchar_as_uint64 << ", 0x" << ::std::setbase(16)
- << wchar_as_uint64 << ")";
- return msg.GetString();
-}
-
-} // namespace internal
-
// AssertionResult constructors.
// Used in EXPECT_TRUE/FALSE(assertion_result).
AssertionResult::AssertionResult(const AssertionResult& other)
: success_(other.success_),
message_(other.message_.get() != NULL ?
- new internal::String(*other.message_) :
- static_cast<internal::String*>(NULL)) {
+ new ::std::string(*other.message_) :
+ static_cast< ::std::string*>(NULL)) {
}
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
@@ -1029,7 +1014,7 @@ AssertionResult EqFailure(const char* expected_expression,
msg << "\nWhich is: " << expected_value;
}
- return AssertionFailure(msg);
+ return AssertionFailure() << msg;
}
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
@@ -1059,13 +1044,12 @@ AssertionResult DoubleNearPredFormat(const char* expr1,
// TODO(wan): do not print the value of an expression if it's
// already a literal.
- Message msg;
- msg << "The difference between " << expr1 << " and " << expr2
+ return AssertionFailure()
+ << "The difference between " << expr1 << " and " << expr2
<< " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
<< expr1 << " evaluates to " << val1 << ",\n"
<< expr2 << " evaluates to " << val2 << ", and\n"
<< abs_error_expr << " evaluates to " << abs_error << ".";
- return AssertionFailure(msg);
}
@@ -1090,20 +1074,18 @@ AssertionResult FloatingPointLE(const char* expr1,
// val2 is NaN, as the IEEE floating-point standard requires that
// any predicate involving a NaN must return false.
- StrStream val1_ss;
+ ::std::stringstream val1_ss;
val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< val1;
- StrStream val2_ss;
+ ::std::stringstream val2_ss;
val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< val2;
- Message msg;
- msg << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
- << " Actual: " << StrStreamToString(&val1_ss) << " vs "
- << StrStreamToString(&val2_ss);
-
- return AssertionFailure(msg);
+ return AssertionFailure()
+ << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+ << " Actual: " << StringStreamToString(&val1_ss) << " vs "
+ << StringStreamToString(&val2_ss);
}
} // namespace internal
@@ -1150,11 +1132,10 @@ AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
if (val1 op val2) {\
return AssertionSuccess();\
} else {\
- Message msg;\
- msg << "Expected: (" << expr1 << ") " #op " (" << expr2\
+ return AssertionFailure() \
+ << "Expected: (" << expr1 << ") " #op " (" << expr2\
<< "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
<< " vs " << FormatForComparisonFailureMessage(val2, val1);\
- return AssertionFailure(msg);\
}\
}
@@ -1216,11 +1197,9 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression,
if (!String::CStringEquals(s1, s2)) {
return AssertionSuccess();
} else {
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
- << s2_expression << "), actual: \""
- << s1 << "\" vs \"" << s2 << "\"";
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: \""
+ << s1 << "\" vs \"" << s2 << "\"";
}
}
@@ -1232,11 +1211,10 @@ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
return AssertionSuccess();
} else {
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
+ return AssertionFailure()
+ << "Expected: (" << s1_expression << ") != ("
<< s2_expression << ") (ignoring case), actual: \""
<< s1 << "\" vs \"" << s2 << "\"";
- return AssertionFailure(msg);
}
}
@@ -1285,13 +1263,12 @@ AssertionResult IsSubstringImpl(
const bool is_wide_string = sizeof(needle[0]) > 1;
const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
- return AssertionFailure(
- Message()
+ return AssertionFailure()
<< "Value of: " << needle_expr << "\n"
<< " Actual: " << begin_string_quote << needle << "\"\n"
<< "Expected: " << (expected_to_be_substring ? "" : "not ")
<< "a substring of " << haystack_expr << "\n"
- << "Which is: " << begin_string_quote << haystack << "\"");
+ << "Which is: " << begin_string_quote << haystack << "\"";
}
} // namespace
@@ -1360,10 +1337,13 @@ namespace {
AssertionResult HRESULTFailureHelper(const char* expr,
const char* expected,
long hr) { // NOLINT
-#if GTEST_OS_WINDOWS_MOBILE
+# if GTEST_OS_WINDOWS_MOBILE
+
// Windows CE doesn't support FormatMessage.
const char error_text[] = "";
-#else
+
+# else
+
// Looks up the human-readable system message for the HRESULT code
// and since we're not passing any params to FormatMessage, we don't
// want inserts expanded.
@@ -1380,18 +1360,17 @@ AssertionResult HRESULTFailureHelper(const char* expr,
kBufSize, // buf size
NULL); // no arguments for inserts
// Trims tailing white space (FormatMessage leaves a trailing cr-lf)
- for (; message_length && isspace(error_text[message_length - 1]);
+ for (; message_length && IsSpace(error_text[message_length - 1]);
--message_length) {
error_text[message_length - 1] = '\0';
}
-#endif // GTEST_OS_WINDOWS_MOBILE
+
+# endif // GTEST_OS_WINDOWS_MOBILE
const String error_hex(String::Format("0x%08X ", hr));
- Message msg;
- msg << "Expected: " << expr << " " << expected << ".\n"
+ return ::testing::AssertionFailure()
+ << "Expected: " << expr << " " << expected << ".\n"
<< " Actual: " << error_hex << error_text << "\n";
-
- return ::testing::AssertionFailure(msg);
}
} // namespace
@@ -1526,7 +1505,7 @@ String WideStringToUtf8(const wchar_t* str, int num_chars) {
if (num_chars == -1)
num_chars = static_cast<int>(wcslen(str));
- StrStream stream;
+ ::std::stringstream stream;
for (int i = 0; i < num_chars; ++i) {
UInt32 unicode_code_point;
@@ -1543,7 +1522,7 @@ String WideStringToUtf8(const wchar_t* str, int num_chars) {
char buffer[32]; // CodePointToUtf8 requires a buffer this big.
stream << CodePointToUtf8(unicode_code_point, buffer);
}
- return StrStreamToString(&stream);
+ return StringStreamToString(&stream);
}
// Converts a wide C string to a String using the UTF-8 encoding.
@@ -1602,12 +1581,10 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression,
return AssertionSuccess();
}
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
- << s2_expression << "), actual: "
- << String::ShowWideCStringQuoted(s1)
- << " vs " << String::ShowWideCStringQuoted(s2);
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: "
+ << String::ShowWideCStringQuoted(s1)
+ << " vs " << String::ShowWideCStringQuoted(s2);
}
// Compares two C strings, ignoring case. Returns true iff they have
@@ -1638,17 +1615,17 @@ bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
// current locale.
bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
const wchar_t* rhs) {
- if ( lhs == NULL ) return rhs == NULL;
+ if (lhs == NULL) return rhs == NULL;
- if ( rhs == NULL ) return false;
+ if (rhs == NULL) return false;
#if GTEST_OS_WINDOWS
return _wcsicmp(lhs, rhs) == 0;
-#elif GTEST_OS_LINUX
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
return wcscasecmp(lhs, rhs) == 0;
#else
- // Mac OS X and Cygwin don't define wcscasecmp. Other unknown OSes
- // may not define it either.
+ // Android, Mac OS X and Cygwin don't define wcscasecmp.
+ // Other unknown OSes may not define it either.
wint_t left, right;
do {
left = towlower(*lhs++);
@@ -1730,10 +1707,12 @@ String String::Format(const char * format, ...) {
// MSVC 8 deprecates vsnprintf(), so we want to suppress warning
// 4996 (deprecated function) there.
#ifdef _MSC_VER // We are using MSVC.
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4996) // Temporarily disables warning 4996.
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4996) // Temporarily disables warning 4996.
+
const int size = vsnprintf(buffer, kBufferSize, format, args);
-#pragma warning(pop) // Restores the warning state.
+
+# pragma warning(pop) // Restores the warning state.
#else // We are not using MSVC.
const int size = vsnprintf(buffer, kBufferSize, format, args);
#endif // _MSC_VER
@@ -1751,16 +1730,16 @@ String String::Format(const char * format, ...) {
}
}
-// Converts the buffer in a StrStream to a String, converting NUL
+// Converts the buffer in a stringstream to a String, converting NUL
// bytes to "\\0" along the way.
-String StrStreamToString(StrStream* ss) {
+String StringStreamToString(::std::stringstream* ss) {
const ::std::string& str = ss->str();
const char* const start = str.c_str();
const char* const end = start + str.length();
- // We need to use a helper StrStream to do this transformation
+ // We need to use a helper stringstream to do this transformation
// because String doesn't support push_back().
- StrStream helper;
+ ::std::stringstream helper;
for (const char* ch = start; ch != end; ++ch) {
if (*ch == '\0') {
helper << "\\0"; // Replaces NUL with "\\0";
@@ -1964,22 +1943,6 @@ void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
} // namespace internal
-#if GTEST_HAS_SEH
-// We are on Windows with SEH.
-
-// Adds an "exception thrown" fatal failure to the current test.
-static void AddExceptionThrownFailure(DWORD exception_code,
- const char* location) {
- Message message;
- message << "Exception thrown with code 0x" << std::setbase(16) <<
- exception_code << std::setbase(10) << " in " << location << ".";
-
- internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
- message.GetString());
-}
-
-#endif // GTEST_HAS_SEH
-
// Google Test requires all tests in the same test case to use the same test
// fixture class. This function checks if the current test has the
// same fixture class as the first test in the current test case. If
@@ -1990,15 +1953,13 @@ bool Test::HasSameFixtureClass() {
const TestCase* const test_case = impl->current_test_case();
// Info about the first test in the current test case.
- const internal::TestInfoImpl* const first_test_info =
- test_case->test_info_list()[0]->impl();
- const internal::TypeId first_fixture_id = first_test_info->fixture_class_id();
+ const TestInfo* const first_test_info = test_case->test_info_list()[0];
+ const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
const char* const first_test_name = first_test_info->name();
// Info about the current test.
- const internal::TestInfoImpl* const this_test_info =
- impl->current_test_info()->impl();
- const internal::TypeId this_fixture_id = this_test_info->fixture_class_id();
+ const TestInfo* const this_test_info = impl->current_test_info();
+ const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
const char* const this_test_name = this_test_info->name();
if (this_fixture_id != first_fixture_id) {
@@ -2048,62 +2009,167 @@ bool Test::HasSameFixtureClass() {
return true;
}
-// Runs the test and updates the test result.
-void Test::Run() {
- if (!HasSameFixtureClass()) return;
+#if GTEST_HAS_SEH
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+// Adds an "exception thrown" fatal failure to the current test. This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static internal::String* FormatSehExceptionMessage(DWORD exception_code,
+ const char* location) {
+ Message message;
+ message << "SEH exception with code 0x" << std::setbase(16) <<
+ exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+ return new internal::String(message.GetString());
+}
+
+#endif // GTEST_HAS_SEH
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static internal::String FormatCxxExceptionMessage(const char* description,
+ const char* location) {
+ Message message;
+ if (description != NULL) {
+ message << "C++ exception with description \"" << description << "\"";
+ } else {
+ message << "Unknown C++ exception";
+ }
+ message << " thrown in " << location << ".";
+
+ return message.GetString();
+}
+
+static internal::String PrintTestPartResultToString(
+ const TestPartResult& test_part_result);
+
+// A failed Google Test assertion will throw an exception of this type when
+// GTEST_FLAG(throw_on_failure) is true (if exceptions are enabled). We
+// derive it from std::runtime_error, which is for errors presumably
+// detectable only at run time. Since std::runtime_error inherits from
+// std::exception, many testing frameworks know how to extract and print the
+// message inside it.
+class GoogleTestFailureException : public ::std::runtime_error {
+ public:
+ explicit GoogleTestFailureException(const TestPartResult& failure)
+ : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+};
+#endif // GTEST_HAS_EXCEPTIONS
+
+namespace internal {
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception. (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function. Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+ T* object, Result (T::*method)(), const char* location) {
#if GTEST_HAS_SEH
- // Catch SEH-style exceptions.
- impl->os_stack_trace_getter()->UponLeavingGTest();
__try {
- SetUp();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
+ return (object->*method)();
+ } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT
GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "SetUp()");
+ // We create the exception message on the heap because VC++ prohibits
+ // creation of objects with destructors on stack in functions using __try
+ // (see error C2712).
+ internal::String* exception_message = FormatSehExceptionMessage(
+ GetExceptionCode(), location);
+ internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+ *exception_message);
+ delete exception_message;
+ return static_cast<Result>(0);
}
+#else
+ (void)location;
+ return (object->*method)();
+#endif // GTEST_HAS_SEH
+}
- // We will run the test only if SetUp() had no fatal failure.
- if (!HasFatalFailure()) {
- impl->os_stack_trace_getter()->UponLeavingGTest();
- __try {
- TestBody();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "the test body");
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+ T* object, Result (T::*method)(), const char* location) {
+ // NOTE: The user code can affect the way in which Google Test handles
+ // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+ // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+ // after the exception is caught and either report or re-throw the
+ // exception based on the flag's value:
+ //
+ // try {
+ // // Perform the test method.
+ // } catch (...) {
+ // if (GTEST_FLAG(catch_exceptions))
+ // // Report the exception as failure.
+ // else
+ // throw; // Re-throws the original exception.
+ // }
+ //
+ // However, the purpose of this flag is to allow the program to drop into
+ // the debugger when the exception is thrown. On most platforms, once the
+ // control enters the catch block, the exception origin information is
+ // lost and the debugger will stop the program at the point of the
+ // re-throw in this function -- instead of at the point of the original
+ // throw statement in the code under test. For this reason, we perform
+ // the check early, sacrificing the ability to affect Google Test's
+ // exception handling in the method where the exception is thrown.
+ if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+ try {
+ return HandleSehExceptionsInMethodIfSupported(object, method, location);
+ } catch (const GoogleTestFailureException&) { // NOLINT
+ // This exception doesn't originate in code under test. It makes no
+ // sense to report it as a test failure.
+ throw;
+ } catch (const std::exception& e) { // NOLINT
+ internal::ReportFailureInUnknownLocation(
+ TestPartResult::kFatalFailure,
+ FormatCxxExceptionMessage(e.what(), location));
+ } catch (...) { // NOLINT
+ internal::ReportFailureInUnknownLocation(
+ TestPartResult::kFatalFailure,
+ FormatCxxExceptionMessage(NULL, location));
}
+ return static_cast<Result>(0);
+#else
+ return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif // GTEST_HAS_EXCEPTIONS
+ } else {
+ return (object->*method)();
}
+}
- // However, we want to clean up as much as possible. Hence we will
- // always call TearDown(), even if SetUp() or the test body has
- // failed.
- impl->os_stack_trace_getter()->UponLeavingGTest();
- __try {
- TearDown();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "TearDown()");
- }
+} // namespace internal
-#else // We are on a compiler or platform that doesn't support SEH.
- impl->os_stack_trace_getter()->UponLeavingGTest();
- SetUp();
+// Runs the test and updates the test result.
+void Test::Run() {
+ if (!HasSameFixtureClass()) return;
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
// We will run the test only if SetUp() was successful.
if (!HasFatalFailure()) {
impl->os_stack_trace_getter()->UponLeavingGTest();
- TestBody();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &Test::TestBody, "the test body");
}
// However, we want to clean up as much as possible. Hence we will
// always call TearDown(), even if SetUp() or the test body has
// failed.
impl->os_stack_trace_getter()->UponLeavingGTest();
- TearDown();
-#endif // GTEST_HAS_SEH
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &Test::TearDown, "TearDown()");
}
-
// Returns true iff the current test has a fatal failure.
bool Test::HasFatalFailure() {
return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
@@ -2118,22 +2184,28 @@ bool Test::HasNonfatalFailure() {
// class TestInfo
// Constructs a TestInfo object. It assumes ownership of the test factory
-// object via impl_.
+// object.
+// TODO(vladl@google.com): Make a_test_case_name and a_name const string&'s
+// to signify they cannot be NULLs.
TestInfo::TestInfo(const char* a_test_case_name,
const char* a_name,
- const char* a_test_case_comment,
- const char* a_comment,
+ const char* a_type_param,
+ const char* a_value_param,
internal::TypeId fixture_class_id,
- internal::TestFactoryBase* factory) {
- impl_ = new internal::TestInfoImpl(this, a_test_case_name, a_name,
- a_test_case_comment, a_comment,
- fixture_class_id, factory);
-}
+ internal::TestFactoryBase* factory)
+ : test_case_name_(a_test_case_name),
+ name_(a_name),
+ type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+ value_param_(a_value_param ? new std::string(a_value_param) : NULL),
+ fixture_class_id_(fixture_class_id),
+ should_run_(false),
+ is_disabled_(false),
+ matches_filter_(false),
+ factory_(factory),
+ result_() {}
// Destructs a TestInfo object.
-TestInfo::~TestInfo() {
- delete impl_;
-}
+TestInfo::~TestInfo() { delete factory_; }
namespace internal {
@@ -2144,10 +2216,10 @@ namespace internal {
//
// test_case_name: name of the test case
// name: name of the test
-// test_case_comment: a comment on the test case that will be included in
-// the test output
-// comment: a comment on the test that will be included in the
-// test output
+// type_param: the name of the test's type parameter, or NULL if
+// this is not a typed or a type-parameterized test.
+// value_param: text representation of the test's value parameter,
+// or NULL if this is not a value-parameterized test.
// fixture_class_id: ID of the test fixture class
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
@@ -2156,13 +2228,14 @@ namespace internal {
// ownership of the factory object.
TestInfo* MakeAndRegisterTestInfo(
const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* type_param,
+ const char* value_param,
TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc,
TestFactoryBase* factory) {
TestInfo* const test_info =
- new TestInfo(test_case_name, name, test_case_comment, comment,
+ new TestInfo(test_case_name, name, type_param, value_param,
fixture_class_id, factory);
GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
return test_info;
@@ -2189,41 +2262,6 @@ void ReportInvalidTestCaseType(const char* test_case_name,
} // namespace internal
-// Returns the test case name.
-const char* TestInfo::test_case_name() const {
- return impl_->test_case_name();
-}
-
-// Returns the test name.
-const char* TestInfo::name() const {
- return impl_->name();
-}
-
-// Returns the test case comment.
-const char* TestInfo::test_case_comment() const {
- return impl_->test_case_comment();
-}
-
-// Returns the test comment.
-const char* TestInfo::comment() const {
- return impl_->comment();
-}
-
-// Returns true if this test should run.
-bool TestInfo::should_run() const { return impl_->should_run(); }
-
-// Returns true if this test matches the user-specified filter.
-bool TestInfo::matches_filter() const { return impl_->matches_filter(); }
-
-// Returns the result of the test.
-const TestResult* TestInfo::result() const { return impl_->result(); }
-
-// Increments the number of death tests encountered in this test so
-// far.
-int TestInfo::increment_death_test_count() {
- return impl_->result()->increment_death_test_count();
-}
-
namespace internal {
// This method expands all parameterized tests registered with macros TEST_P
@@ -2238,70 +2276,54 @@ void UnitTestImpl::RegisterParameterizedTests() {
#endif
}
+} // namespace internal
+
// Creates the test object, runs it, records its result, and then
// deletes it.
-void TestInfoImpl::Run() {
+void TestInfo::Run() {
if (!should_run_) return;
// Tells UnitTest where to store test result.
- UnitTestImpl* const impl = internal::GetUnitTestImpl();
- impl->set_current_test_info(parent_);
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->set_current_test_info(this);
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
// Notifies the unit test event listeners that a test is about to start.
- repeater->OnTestStart(*parent_);
+ repeater->OnTestStart(*this);
- const TimeInMillis start = GetTimeInMillis();
+ const TimeInMillis start = internal::GetTimeInMillis();
impl->os_stack_trace_getter()->UponLeavingGTest();
-#if GTEST_HAS_SEH
- // Catch SEH-style exceptions.
- Test* test = NULL;
-
- __try {
- // Creates the test object.
- test = factory_->CreateTest();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(),
- "the test fixture's constructor");
- return;
- }
-#else // We are on a compiler or platform that doesn't support SEH.
-
- // TODO(wan): If test->Run() throws, test won't be deleted. This is
- // not a problem now as we don't use exceptions. If we were to
- // enable exceptions, we should revise the following to be
- // exception-safe.
// Creates the test object.
- Test* test = factory_->CreateTest();
-#endif // GTEST_HAS_SEH
-
- // Runs the test only if the constructor of the test fixture didn't
- // generate a fatal failure.
- if (!Test::HasFatalFailure()) {
+ Test* const test = internal::HandleExceptionsInMethodIfSupported(
+ factory_, &internal::TestFactoryBase::CreateTest,
+ "the test fixture's constructor");
+
+ // Runs the test only if the test object was created and its
+ // constructor didn't generate a fatal failure.
+ if ((test != NULL) && !Test::HasFatalFailure()) {
+ // This doesn't throw as all user code that can throw are wrapped into
+ // exception handling code.
test->Run();
}
// Deletes the test object.
impl->os_stack_trace_getter()->UponLeavingGTest();
- delete test;
- test = NULL;
+ internal::HandleExceptionsInMethodIfSupported(
+ test, &Test::DeleteSelf_, "the test fixture's destructor");
- result_.set_elapsed_time(GetTimeInMillis() - start);
+ result_.set_elapsed_time(internal::GetTimeInMillis() - start);
// Notifies the unit test event listener that a test has just finished.
- repeater->OnTestEnd(*parent_);
+ repeater->OnTestEnd(*this);
// Tells UnitTest to stop associating assertion results to this
// test.
impl->set_current_test_info(NULL);
}
-} // namespace internal
-
// class TestCase
// Gets the number of successful tests in this test case.
@@ -2333,13 +2355,15 @@ int TestCase::total_test_count() const {
// Arguments:
//
// name: name of the test case
+// a_type_param: the name of the test case's type parameter, or NULL if
+// this is not a typed or a type-parameterized test case.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
-TestCase::TestCase(const char* a_name, const char* a_comment,
+TestCase::TestCase(const char* a_name, const char* a_type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc)
: name_(a_name),
- comment_(a_comment),
+ type_param_(a_type_param ? new std::string(a_type_param) : NULL),
set_up_tc_(set_up_tc),
tear_down_tc_(tear_down_tc),
should_run_(false),
@@ -2384,45 +2408,26 @@ void TestCase::Run() {
repeater->OnTestCaseStart(*this);
impl->os_stack_trace_getter()->UponLeavingGTest();
- set_up_tc_();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");
const internal::TimeInMillis start = internal::GetTimeInMillis();
for (int i = 0; i < total_test_count(); i++) {
- GetMutableTestInfo(i)->impl()->Run();
+ GetMutableTestInfo(i)->Run();
}
elapsed_time_ = internal::GetTimeInMillis() - start;
impl->os_stack_trace_getter()->UponLeavingGTest();
- tear_down_tc_();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");
+
repeater->OnTestCaseEnd(*this);
impl->set_current_test_case(NULL);
}
// Clears the results of all tests in this test case.
void TestCase::ClearResult() {
- ForEach(test_info_list_, internal::TestInfoImpl::ClearTestResult);
-}
-
-// Returns true iff test passed.
-bool TestCase::TestPassed(const TestInfo * test_info) {
- const internal::TestInfoImpl* const impl = test_info->impl();
- return impl->should_run() && impl->result()->Passed();
-}
-
-// Returns true iff test failed.
-bool TestCase::TestFailed(const TestInfo * test_info) {
- const internal::TestInfoImpl* const impl = test_info->impl();
- return impl->should_run() && impl->result()->Failed();
-}
-
-// Returns true iff test is disabled.
-bool TestCase::TestDisabled(const TestInfo * test_info) {
- return test_info->impl()->is_disabled();
-}
-
-// Returns true if the given test should run.
-bool TestCase::ShouldRunTest(const TestInfo *test_info) {
- return test_info->impl()->should_run();
+ ForEach(test_info_list_, TestInfo::ClearTestResult);
}
// Shuffles the tests in this test case.
@@ -2475,9 +2480,9 @@ static const char * TestPartResultTypeToString(TestPartResult::Type type) {
#else
return "Failure\n";
#endif
+ default:
+ return "Unknown result type";
}
-
- return "Unknown result type";
}
// Prints a TestPartResult to a String.
@@ -2563,6 +2568,7 @@ bool ShouldUseColor(bool stdout_is_tty) {
String::CStringEquals(term, "xterm") ||
String::CStringEquals(term, "xterm-color") ||
String::CStringEquals(term, "xterm-256color") ||
+ String::CStringEquals(term, "screen") ||
String::CStringEquals(term, "linux") ||
String::CStringEquals(term, "cygwin");
return stdout_is_tty && term_supports_color;
@@ -2628,6 +2634,23 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
va_end(args);
}
+void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+ const char* const type_param = test_info.type_param();
+ const char* const value_param = test_info.value_param();
+
+ if (type_param != NULL || value_param != NULL) {
+ printf(", where ");
+ if (type_param != NULL) {
+ printf("TypeParam = %s", type_param);
+ if (value_param != NULL)
+ printf(" and ");
+ }
+ if (value_param != NULL) {
+ printf("GetParam() = %s", value_param);
+ }
+ }
+}
+
// This class implements the TestEventListener interface.
//
// Class PrettyUnitTestResultPrinter is copyable.
@@ -2675,9 +2698,10 @@ void PrettyUnitTestResultPrinter::OnTestIterationStart(
}
if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+ const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
ColoredPrintf(COLOR_YELLOW,
- "Note: This is test shard %s of %s.\n",
- internal::posix::GetEnv(kTestShardIndex),
+ "Note: This is test shard %d of %s.\n",
+ static_cast<int>(shard_index) + 1,
internal::posix::GetEnv(kTestTotalShards));
}
@@ -2707,10 +2731,10 @@ void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
ColoredPrintf(COLOR_GREEN, "[----------] ");
printf("%s from %s", counts.c_str(), test_case_name_.c_str());
- if (test_case.comment()[0] == '\0') {
+ if (test_case.type_param() == NULL) {
printf("\n");
} else {
- printf(", where %s\n", test_case.comment());
+ printf(", where TypeParam = %s\n", test_case.type_param());
}
fflush(stdout);
}
@@ -2718,11 +2742,7 @@ void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
ColoredPrintf(COLOR_GREEN, "[ RUN ] ");
PrintTestName(test_case_name_.c_str(), test_info.name());
- if (test_info.comment()[0] == '\0') {
- printf("\n");
- } else {
- printf(", where %s\n", test_info.comment());
- }
+ printf("\n");
fflush(stdout);
}
@@ -2745,6 +2765,9 @@ void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
ColoredPrintf(COLOR_RED, "[ FAILED ] ");
}
PrintTestName(test_case_name_.c_str(), test_info.name());
+ if (test_info.result()->Failed())
+ PrintFullTestCommentIfPresent(test_info);
+
if (GTEST_FLAG(print_time)) {
printf(" (%s ms)\n", internal::StreamableToString(
test_info.result()->elapsed_time()).c_str());
@@ -2793,21 +2816,14 @@ void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
}
ColoredPrintf(COLOR_RED, "[ FAILED ] ");
printf("%s.%s", test_case.name(), test_info.name());
- if (test_case.comment()[0] != '\0' ||
- test_info.comment()[0] != '\0') {
- printf(", where %s", test_case.comment());
- if (test_case.comment()[0] != '\0' &&
- test_info.comment()[0] != '\0') {
- printf(" and ");
- }
- }
- printf("%s\n", test_info.comment());
+ PrintFullTestCommentIfPresent(test_info);
+ printf("\n");
}
}
}
- void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
- int /*iteration*/) {
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+ int /*iteration*/) {
ColoredPrintf(COLOR_GREEN, "[==========] ");
printf("%s from %s ran.",
FormatTestCount(unit_test.test_to_run_count()).c_str(),
@@ -2987,7 +3003,7 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
static String EscapeXml(const char* str, bool is_attribute);
// Returns the given string with all characters invalid in XML removed.
- static String RemoveInvalidXmlCharacters(const char* str);
+ static string RemoveInvalidXmlCharacters(const string& str);
// Convenience wrapper around EscapeXml when str is an attribute value.
static String EscapeXmlAttribute(const char* str) {
@@ -3121,17 +3137,14 @@ String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) {
// Returns the given string with all characters invalid in XML removed.
// Currently invalid characters are dropped from the string. An
// alternative is to replace them with certain characters such as . or ?.
-String XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const char* str) {
- char* const output = new char[strlen(str) + 1];
- char* appender = output;
- for (char ch = *str; ch != '\0'; ch = *++str)
- if (IsValidXmlCharacter(ch))
- *appender++ = ch;
- *appender = '\0';
+string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const string& str) {
+ string output;
+ output.reserve(str.size());
+ for (string::const_iterator it = str.begin(); it != str.end(); ++it)
+ if (IsValidXmlCharacter(*it))
+ output.push_back(*it);
- String ret_value(output);
- delete[] output;
- return ret_value;
+ return output;
}
// The following routines generate an XML representation of a UnitTest
@@ -3184,8 +3197,18 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
const TestInfo& test_info) {
const TestResult& result = *test_info.result();
*stream << " <testcase name=\""
- << EscapeXmlAttribute(test_info.name()).c_str()
- << "\" status=\""
+ << EscapeXmlAttribute(test_info.name()).c_str() << "\"";
+
+ if (test_info.value_param() != NULL) {
+ *stream << " value_param=\"" << EscapeXmlAttribute(test_info.value_param())
+ << "\"";
+ }
+ if (test_info.type_param() != NULL) {
+ *stream << " type_param=\"" << EscapeXmlAttribute(test_info.type_param())
+ << "\"";
+ }
+
+ *stream << " status=\""
<< (test_info.should_run() ? "run" : "notrun")
<< "\" time=\""
<< FormatTimeInMillisAsSeconds(result.elapsed_time())
@@ -3201,11 +3224,11 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
*stream << " <failure message=\""
<< EscapeXmlAttribute(part.summary()).c_str()
<< "\" type=\"\">";
- const String message = RemoveInvalidXmlCharacters(String::Format(
- "%s:%d\n%s",
- part.file_name(), part.line_number(),
- part.message()).c_str());
- OutputXmlCDataSection(stream, message.c_str());
+ const string location = internal::FormatCompilerIndependentFileLocation(
+ part.file_name(), part.line_number());
+ const string message = location + "\n" + part.message();
+ OutputXmlCDataSection(stream,
+ RemoveInvalidXmlCharacters(message).c_str());
*stream << "</failure>\n";
}
}
@@ -3230,9 +3253,9 @@ void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
"errors=\"0\" time=\"%s\">\n",
FormatTimeInMillisAsSeconds(test_case.elapsed_time()).c_str());
for (int i = 0; i < test_case.total_test_count(); ++i) {
- StrStream stream;
+ ::std::stringstream stream;
OutputXmlTestInfo(&stream, test_case.name(), *test_case.GetTestInfo(i));
- fprintf(out, "%s", StrStreamToString(&stream).c_str());
+ fprintf(out, "%s", StringStreamToString(&stream).c_str());
}
fprintf(out, " </testsuite>\n");
}
@@ -3272,6 +3295,182 @@ String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
// End XmlUnitTestResultPrinter
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+ // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+ static string UrlEncode(const char* str);
+
+ StreamingListener(const string& host, const string& port)
+ : sockfd_(-1), host_name_(host), port_num_(port) {
+ MakeConnection();
+ Send("gtest_streaming_protocol_version=1.0\n");
+ }
+
+ virtual ~StreamingListener() {
+ if (sockfd_ != -1)
+ CloseConnection();
+ }
+
+ void OnTestProgramStart(const UnitTest& /* unit_test */) {
+ Send("event=TestProgramStart\n");
+ }
+
+ void OnTestProgramEnd(const UnitTest& unit_test) {
+ // Note that Google Test current only report elapsed time for each
+ // test iteration, not for the entire test program.
+ Send(String::Format("event=TestProgramEnd&passed=%d\n",
+ unit_test.Passed()));
+
+ // Notify the streaming server to stop.
+ CloseConnection();
+ }
+
+ void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
+ Send(String::Format("event=TestIterationStart&iteration=%d\n",
+ iteration));
+ }
+
+ void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
+ Send(String::Format("event=TestIterationEnd&passed=%d&elapsed_time=%sms\n",
+ unit_test.Passed(),
+ StreamableToString(unit_test.elapsed_time()).c_str()));
+ }
+
+ void OnTestCaseStart(const TestCase& test_case) {
+ Send(String::Format("event=TestCaseStart&name=%s\n", test_case.name()));
+ }
+
+ void OnTestCaseEnd(const TestCase& test_case) {
+ Send(String::Format("event=TestCaseEnd&passed=%d&elapsed_time=%sms\n",
+ test_case.Passed(),
+ StreamableToString(test_case.elapsed_time()).c_str()));
+ }
+
+ void OnTestStart(const TestInfo& test_info) {
+ Send(String::Format("event=TestStart&name=%s\n", test_info.name()));
+ }
+
+ void OnTestEnd(const TestInfo& test_info) {
+ Send(String::Format(
+ "event=TestEnd&passed=%d&elapsed_time=%sms\n",
+ (test_info.result())->Passed(),
+ StreamableToString((test_info.result())->elapsed_time()).c_str()));
+ }
+
+ void OnTestPartResult(const TestPartResult& test_part_result) {
+ const char* file_name = test_part_result.file_name();
+ if (file_name == NULL)
+ file_name = "";
+ Send(String::Format("event=TestPartResult&file=%s&line=%d&message=",
+ UrlEncode(file_name).c_str(),
+ test_part_result.line_number()));
+ Send(UrlEncode(test_part_result.message()) + "\n");
+ }
+
+ private:
+ // Creates a client socket and connects to the server.
+ void MakeConnection();
+
+ // Closes the socket.
+ void CloseConnection() {
+ GTEST_CHECK_(sockfd_ != -1)
+ << "CloseConnection() can be called only when there is a connection.";
+
+ close(sockfd_);
+ sockfd_ = -1;
+ }
+
+ // Sends a string to the socket.
+ void Send(const string& message) {
+ GTEST_CHECK_(sockfd_ != -1)
+ << "Send() can be called only when there is a connection.";
+
+ const int len = static_cast<int>(message.length());
+ if (write(sockfd_, message.c_str(), len) != len) {
+ GTEST_LOG_(WARNING)
+ << "stream_result_to: failed to stream to "
+ << host_name_ << ":" << port_num_;
+ }
+ }
+
+ int sockfd_; // socket file descriptor
+ const string host_name_;
+ const string port_num_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
+}; // class StreamingListener
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D". This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+string StreamingListener::UrlEncode(const char* str) {
+ string result;
+ result.reserve(strlen(str) + 1);
+ for (char ch = *str; ch != '\0'; ch = *++str) {
+ switch (ch) {
+ case '%':
+ case '=':
+ case '&':
+ case '\n':
+ result.append(String::Format("%%%02x", static_cast<unsigned char>(ch)));
+ break;
+ default:
+ result.push_back(ch);
+ break;
+ }
+ }
+ return result;
+}
+
+void StreamingListener::MakeConnection() {
+ GTEST_CHECK_(sockfd_ == -1)
+ << "MakeConnection() can't be called when there is already a connection.";
+
+ addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses.
+ hints.ai_socktype = SOCK_STREAM;
+ addrinfo* servinfo = NULL;
+
+ // Use the getaddrinfo() to get a linked list of IP addresses for
+ // the given host name.
+ const int error_num = getaddrinfo(
+ host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+ if (error_num != 0) {
+ GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+ << gai_strerror(error_num);
+ }
+
+ // Loop through all the results and connect to the first we can.
+ for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL;
+ cur_addr = cur_addr->ai_next) {
+ sockfd_ = socket(
+ cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
+ if (sockfd_ != -1) {
+ // Connect the client socket to the server socket.
+ if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+ close(sockfd_);
+ sockfd_ = -1;
+ }
+ }
+ }
+
+ freeaddrinfo(servinfo); // all done with this structure
+
+ if (sockfd_ == -1) {
+ GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+ << host_name_ << ":" << port_num_;
+ }
+}
+
+// End of class Streaming Listener
+#endif // GTEST_CAN_STREAM_RESULTS__
+
// Class ScopedTrace
// Pushes the given source file location and message onto a per-thread
@@ -3512,19 +3711,6 @@ Environment* UnitTest::AddEnvironment(Environment* env) {
return env;
}
-#if GTEST_HAS_EXCEPTIONS
-// A failed Google Test assertion will throw an exception of this type
-// when exceptions are enabled. We derive it from std::runtime_error,
-// which is for errors presumably detectable only at run time. Since
-// std::runtime_error inherits from std::exception, many testing
-// frameworks know how to extract and print the message inside it.
-class GoogleTestFailureException : public ::std::runtime_error {
- public:
- explicit GoogleTestFailureException(const TestPartResult& failure)
- : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
-};
-#endif
-
// Adds a TestPartResult to the current TestResult object. All Google Test
// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
// this to report their results. The user code should use the
@@ -3601,31 +3787,34 @@ void UnitTest::RecordPropertyForCurrentTest(const char* key,
// We don't protect this under mutex_, as we only support calling it
// from the main thread.
int UnitTest::Run() {
-#if GTEST_HAS_SEH
- // Catch SEH-style exceptions.
+ // Captures the value of GTEST_FLAG(catch_exceptions). This value will be
+ // used for the duration of the program.
+ impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
+#if GTEST_HAS_SEH
const bool in_death_test_child_process =
internal::GTEST_FLAG(internal_run_death_test).length() > 0;
// Either the user wants Google Test to catch exceptions thrown by the
// tests or this is executing in the context of death test child
// process. In either case the user does not want to see pop-up dialogs
- // about crashes - they are expected..
- if (GTEST_FLAG(catch_exceptions) || in_death_test_child_process) {
-#if !GTEST_OS_WINDOWS_MOBILE
+ // about crashes - they are expected.
+ if (impl()->catch_exceptions() || in_death_test_child_process) {
+
+# if !GTEST_OS_WINDOWS_MOBILE
// SetErrorMode doesn't exist on CE.
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
-#endif // !GTEST_OS_WINDOWS_MOBILE
+# endif // !GTEST_OS_WINDOWS_MOBILE
-#if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
+# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
// Death test children can be terminated with _abort(). On Windows,
// _abort() can show a dialog with a warning message. This forces the
// abort message to go to stderr instead.
_set_error_mode(_OUT_TO_STDERR);
-#endif
+# endif
-#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
// In the debug version, Visual Studio pops up a separate dialog
// offering a choice to debug the aborted program. We need to suppress
// this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
@@ -3641,22 +3830,15 @@ int UnitTest::Run() {
_set_abort_behavior(
0x0, // Clear the following flags:
_WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump.
-#endif
- }
+# endif
- __try {
- return impl_->RunAllTests();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- printf("Exception thrown with code 0x%x.\nFAIL\n", GetExceptionCode());
- fflush(stdout);
- return 1;
}
-
-#else // We are on a compiler or platform that doesn't support SEH.
-
- return impl_->RunAllTests();
#endif // GTEST_HAS_SEH
+
+ return internal::HandleExceptionsInMethodIfSupported(
+ impl(),
+ &internal::UnitTestImpl::RunAllTests,
+ "auxiliary test code (environments or event listeners)") ? 0 : 1;
}
// Returns the working directory when the first TEST() or TEST_F() was
@@ -3724,12 +3906,12 @@ namespace internal {
UnitTestImpl::UnitTestImpl(UnitTest* parent)
: parent_(parent),
#ifdef _MSC_VER
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4355) // Temporarily disables warning 4355
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4355) // Temporarily disables warning 4355
// (using this in initializer).
default_global_test_part_result_reporter_(this),
default_per_thread_test_part_result_reporter_(this),
-#pragma warning(pop) // Restores the warning state again.
+# pragma warning(pop) // Restores the warning state again.
#else
default_global_test_part_result_reporter_(this),
default_per_thread_test_part_result_reporter_(this),
@@ -3750,13 +3932,13 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
post_flag_parse_init_performed_(false),
random_seed_(0), // Will be overridden by the flag before first use.
random_(0), // Will be reseeded before first use.
-#if GTEST_HAS_DEATH_TEST
elapsed_time_(0),
+#if GTEST_HAS_DEATH_TEST
internal_run_death_test_flag_(NULL),
- death_test_factory_(new DefaultDeathTestFactory) {
-#else
- elapsed_time_(0) {
-#endif // GTEST_HAS_DEATH_TEST
+ death_test_factory_(new DefaultDeathTestFactory),
+#endif
+ // Will be overridden by the flag before first use.
+ catch_exceptions_(false) {
listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
}
@@ -3793,6 +3975,25 @@ void UnitTestImpl::ConfigureXmlOutput() {
}
}
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in String form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+ const string& target = GTEST_FLAG(stream_result_to);
+ if (!target.empty()) {
+ const size_t pos = target.find(':');
+ if (pos != string::npos) {
+ listeners()->Append(new StreamingListener(target.substr(0, pos),
+ target.substr(pos+1)));
+ } else {
+ printf("WARNING: unrecognized streaming target \"%s\" ignored.\n",
+ target.c_str());
+ fflush(stdout);
+ }
+ }
+}
+#endif // GTEST_CAN_STREAM_RESULTS_
+
// Performs initialization dependent upon flag values obtained in
// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
@@ -3816,6 +4017,11 @@ void UnitTestImpl::PostFlagParsingInit() {
// Configures listeners for XML output. This makes it possible for users
// to shut down the default XML output before invoking RUN_ALL_TESTS.
ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+ // Configures listeners for streaming test results to the specified server.
+ ConfigureStreamingOutput();
+#endif // GTEST_CAN_STREAM_RESULTS_
}
}
@@ -3850,10 +4056,12 @@ class TestCaseNameIs {
// Arguments:
//
// test_case_name: name of the test case
+// type_param: the name of the test case's type parameter, or NULL if
+// this is not a typed or a type-parameterized test case.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
- const char* comment,
+ const char* type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc) {
// Can we find a TestCase with the given name?
@@ -3866,7 +4074,7 @@ TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
// No. Let's create one.
TestCase* const new_test_case =
- new TestCase(test_case_name, comment, set_up_tc, tear_down_tc);
+ new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc);
// Is this a death test case?
if (internal::UnitTestOptions::MatchesFilter(String(test_case_name),
@@ -3893,27 +4101,26 @@ static void SetUpEnvironment(Environment* env) { env->SetUp(); }
static void TearDownEnvironment(Environment* env) { env->TearDown(); }
// Runs all tests in this UnitTest object, prints the result, and
-// returns 0 if all tests are successful, or 1 otherwise. If any
-// exception is thrown during a test on Windows, this test is
-// considered to be failed, but the rest of the tests will still be
-// run. (We disable exceptions on Linux and Mac OS X, so the issue
-// doesn't apply there.)
+// returns true if all tests are successful. If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
// When parameterized tests are enabled, it expands and registers
// parameterized tests first in RegisterParameterizedTests().
// All other functions called from RunAllTests() may safely assume that
// parameterized tests are ready to be counted and run.
-int UnitTestImpl::RunAllTests() {
+bool UnitTestImpl::RunAllTests() {
// Makes sure InitGoogleTest() was called.
if (!GTestIsInitialized()) {
printf("%s",
"\nThis test program did NOT call ::testing::InitGoogleTest "
"before calling RUN_ALL_TESTS(). Please fix it.\n");
- return 1;
+ return false;
}
// Do not run any test if the --help flag was specified.
if (g_help_flag)
- return 0;
+ return true;
// Repeats the call to the post-flag parsing initialization in case the
// user didn't call InitGoogleTest.
@@ -3945,7 +4152,7 @@ int UnitTestImpl::RunAllTests() {
if (GTEST_FLAG(list_tests)) {
// This must be called *after* FilterTests() has been called.
ListTestsMatchingFilter();
- return 0;
+ return true;
}
random_seed_ = GTEST_FLAG(shuffle) ?
@@ -3964,7 +4171,9 @@ int UnitTestImpl::RunAllTests() {
// Repeats forever if the repeat count is negative.
const bool forever = repeat < 0;
for (int i = 0; forever || i != repeat; i++) {
- ClearResult();
+ // We want to preserve failures generated by ad-hoc test
+ // assertions executed before RUN_ALL_TESTS().
+ ClearNonAdHocTestResult();
const TimeInMillis start = GetTimeInMillis();
@@ -4029,8 +4238,7 @@ int UnitTestImpl::RunAllTests() {
repeater->OnTestProgramEnd(*parent_);
- // Returns 0 if all tests passed, or 1 other wise.
- return failed ? 1 : 0;
+ return !failed;
}
// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
@@ -4104,7 +4312,7 @@ bool ShouldShard(const char* total_shards_env,
// Parses the environment variable var as an Int32. If it is unset,
// returns default_val. If it is not an Int32, prints an error
// and aborts.
-Int32 Int32FromEnvOrDie(const char* const var, Int32 default_val) {
+Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) {
const char* str_val = posix::GetEnv(var);
if (str_val == NULL) {
return default_val;
@@ -4160,12 +4368,12 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
kDisableTestFilter) ||
internal::UnitTestOptions::MatchesFilter(test_name,
kDisableTestFilter);
- test_info->impl()->set_is_disabled(is_disabled);
+ test_info->is_disabled_ = is_disabled;
const bool matches_filter =
internal::UnitTestOptions::FilterMatchesTest(test_case_name,
test_name);
- test_info->impl()->set_matches_filter(matches_filter);
+ test_info->matches_filter_ = matches_filter;
const bool is_runnable =
(GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
@@ -4179,7 +4387,7 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
num_runnable_tests += is_runnable;
num_selected_tests += is_selected;
- test_info->impl()->set_should_run(is_selected);
+ test_info->should_run_ = is_selected;
test_case->set_should_run(test_case->should_run() || is_selected);
}
}
@@ -4195,7 +4403,7 @@ void UnitTestImpl::ListTestsMatchingFilter() {
for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
const TestInfo* const test_info =
test_case->test_info_list()[j];
- if (test_info->matches_filter()) {
+ if (test_info->matches_filter_) {
if (!printed_test_case_name) {
printed_test_case_name = true;
printf("%s.\n", test_case->name());
@@ -4235,7 +4443,7 @@ OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
// the TestResult for the ad hoc test if no test is running.
TestResult* UnitTestImpl::current_test_result() {
return current_test_info_ ?
- current_test_info_->impl()->result() : &ad_hoc_test_result_;
+ &(current_test_info_->result_) : &ad_hoc_test_result_;
}
// Shuffles all test cases, and the tests within each test case,
@@ -4264,32 +4472,6 @@ void UnitTestImpl::UnshuffleTests() {
}
}
-// TestInfoImpl constructor. The new instance assumes ownership of the test
-// factory object.
-TestInfoImpl::TestInfoImpl(TestInfo* parent,
- const char* a_test_case_name,
- const char* a_name,
- const char* a_test_case_comment,
- const char* a_comment,
- TypeId a_fixture_class_id,
- internal::TestFactoryBase* factory) :
- parent_(parent),
- test_case_name_(String(a_test_case_name)),
- name_(String(a_name)),
- test_case_comment_(String(a_test_case_comment)),
- comment_(String(a_comment)),
- fixture_class_id_(a_fixture_class_id),
- should_run_(false),
- is_disabled_(false),
- matches_filter_(false),
- factory_(factory) {
-}
-
-// TestInfoImpl destructor.
-TestInfoImpl::~TestInfoImpl() {
- delete factory_;
-}
-
// Returns the current OS stack trace as a String.
//
// The maximum number of stack frames to be included is specified by
@@ -4307,8 +4489,8 @@ String GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
}
-// Used by the GTEST_HIDE_UNREACHABLE_CODE_ macro to suppress unreachable
-// code warnings.
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
namespace {
class ClassUniqueToAlwaysTrue {};
}
@@ -4520,6 +4702,10 @@ static const char kColorEncodedHelpMessage[] =
GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
" Generate an XML report in the given directory or with the given file\n"
" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n"
+#if GTEST_CAN_STREAM_RESULTS_
+" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n"
+" Stream test results to the given server.\n"
+#endif // GTEST_CAN_STREAM_RESULTS_
"\n"
"Assertion Behavior:\n"
#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
@@ -4530,10 +4716,9 @@ static const char kColorEncodedHelpMessage[] =
" Turn assertion failures into debugger break-points.\n"
" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
" Turn assertion failures into C++ exceptions.\n"
-#if GTEST_OS_WINDOWS
-" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions@D\n"
-" Suppress pop-ups caused by exceptions.\n"
-#endif // GTEST_OS_WINDOWS
+" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
+" Do not report exceptions as test failures. Instead, allow them\n"
+" to crash the program or throw a pop-up (on Windows).\n"
"\n"
"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set "
"the corresponding\n"
@@ -4583,7 +4768,10 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
ParseInt32Flag(arg, kStackTraceDepthFlag,
&GTEST_FLAG(stack_trace_depth)) ||
- ParseBoolFlag(arg, kThrowOnFailureFlag, &GTEST_FLAG(throw_on_failure))
+ ParseStringFlag(arg, kStreamResultToFlag,
+ &GTEST_FLAG(stream_result_to)) ||
+ ParseBoolFlag(arg, kThrowOnFailureFlag,
+ &GTEST_FLAG(throw_on_failure))
) {
// Yes. Shift the remainder of the argv list left by one. Note
// that argv has (*argc + 1) elements, the last one always being
@@ -4641,10 +4829,12 @@ void InitGoogleTestImpl(int* argc, CharType** argv) {
internal::g_executable_path = internal::StreamableToString(argv[0]);
#if GTEST_HAS_DEATH_TEST
+
g_argvs.clear();
for (int i = 0; i != *argc; i++) {
g_argvs.push_back(StreamableToString(argv[i]));
}
+
#endif // GTEST_HAS_DEATH_TEST
ParseGoogleTestFlagsOnly(argc, argv);
diff --git a/utils/unittest/googletest/include/gtest/gtest-death-test.h b/utils/unittest/googletest/include/gtest/gtest-death-test.h
index 121dc1f..a27883f 100644
--- a/utils/unittest/googletest/include/gtest/gtest-death-test.h
+++ b/utils/unittest/googletest/include/gtest/gtest-death-test.h
@@ -38,7 +38,7 @@
#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
-#include <gtest/internal/gtest-death-test-internal.h>
+#include "gtest/internal/gtest-death-test-internal.h"
namespace testing {
@@ -154,24 +154,24 @@ GTEST_DECLARE_string_(death_test_style);
// Asserts that a given statement causes the program to exit, with an
// integer exit status that satisfies predicate, and emitting error output
// that matches regex.
-#define ASSERT_EXIT(statement, predicate, regex) \
- GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
+# define ASSERT_EXIT(statement, predicate, regex) \
+ GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
// Like ASSERT_EXIT, but continues on to successive tests in the
// test case, if any:
-#define EXPECT_EXIT(statement, predicate, regex) \
- GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
+# define EXPECT_EXIT(statement, predicate, regex) \
+ GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
// Asserts that a given statement causes the program to exit, either by
// explicitly exiting with a nonzero exit code or being killed by a
// signal, and emitting error output that matches regex.
-#define ASSERT_DEATH(statement, regex) \
- ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+# define ASSERT_DEATH(statement, regex) \
+ ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
// Like ASSERT_DEATH, but continues on to successive tests in the
// test case, if any:
-#define EXPECT_DEATH(statement, regex) \
- EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+# define EXPECT_DEATH(statement, regex) \
+ EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
@@ -187,7 +187,7 @@ class GTEST_API_ ExitedWithCode {
const int exit_code_;
};
-#if !GTEST_OS_WINDOWS
+# if !GTEST_OS_WINDOWS
// Tests that an exit code describes an exit due to termination by a
// given signal.
class GTEST_API_ KilledBySignal {
@@ -197,7 +197,7 @@ class GTEST_API_ KilledBySignal {
private:
const int signum_;
};
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
// The death testing framework causes this to have interesting semantics,
@@ -242,23 +242,23 @@ class GTEST_API_ KilledBySignal {
// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
// }, "death");
//
-#ifdef NDEBUG
+# ifdef NDEBUG
-#define EXPECT_DEBUG_DEATH(statement, regex) \
+# define EXPECT_DEBUG_DEATH(statement, regex) \
do { statement; } while (::testing::internal::AlwaysFalse())
-#define ASSERT_DEBUG_DEATH(statement, regex) \
+# define ASSERT_DEBUG_DEATH(statement, regex) \
do { statement; } while (::testing::internal::AlwaysFalse())
-#else
+# else
-#define EXPECT_DEBUG_DEATH(statement, regex) \
+# define EXPECT_DEBUG_DEATH(statement, regex) \
EXPECT_DEATH(statement, regex)
-#define ASSERT_DEBUG_DEATH(statement, regex) \
+# define ASSERT_DEBUG_DEATH(statement, regex) \
ASSERT_DEATH(statement, regex)
-#endif // NDEBUG for EXPECT_DEBUG_DEATH
+# endif // NDEBUG for EXPECT_DEBUG_DEATH
#endif // GTEST_HAS_DEATH_TEST
// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
@@ -267,14 +267,14 @@ class GTEST_API_ KilledBySignal {
// useful when you are combining death test assertions with normal test
// assertions in one test.
#if GTEST_HAS_DEATH_TEST
-#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
EXPECT_DEATH(statement, regex)
-#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
ASSERT_DEATH(statement, regex)
#else
-#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
-#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
#endif
diff --git a/utils/unittest/googletest/include/gtest/gtest-message.h b/utils/unittest/googletest/include/gtest/gtest-message.h
index f135b69..9b7142f 100644
--- a/utils/unittest/googletest/include/gtest/gtest-message.h
+++ b/utils/unittest/googletest/include/gtest/gtest-message.h
@@ -48,8 +48,8 @@
#include <limits>
-#include <gtest/internal/gtest-string.h>
-#include <gtest/internal/gtest-internal.h>
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-internal.h"
namespace testing {
@@ -58,7 +58,7 @@ namespace testing {
// Typical usage:
//
// 1. You stream a bunch of values to a Message object.
-// It will remember the text in a StrStream.
+// It will remember the text in a stringstream.
// 2. Then you stream the Message object to an ostream.
// This causes the text in the Message to be streamed
// to the ostream.
@@ -74,7 +74,7 @@ namespace testing {
// Message is not intended to be inherited from. In particular, its
// destructor is not virtual.
//
-// Note that StrStream behaves differently in gcc and in MSVC. You
+// Note that stringstream behaves differently in gcc and in MSVC. You
// can stream a NULL char pointer to it in the former, but not in the
// latter (it causes an access violation if you do). The Message
// class hides this difference by treating a NULL char pointer as
@@ -87,27 +87,26 @@ class GTEST_API_ Message {
public:
// Constructs an empty Message.
- // We allocate the StrStream separately because it otherwise each use of
+ // We allocate the stringstream separately because otherwise each use of
// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
// stack frame leading to huge stack frames in some cases; gcc does not reuse
// the stack space.
- Message() : ss_(new internal::StrStream) {
+ Message() : ss_(new ::std::stringstream) {
// By default, we want there to be enough precision when printing
// a double to a Message.
*ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
}
// Copy constructor.
- Message(const Message& msg) : ss_(new internal::StrStream) { // NOLINT
+ Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
*ss_ << msg.GetString();
}
// Constructs a Message from a C-string.
- explicit Message(const char* str) : ss_(new internal::StrStream) {
+ explicit Message(const char* str) : ss_(new ::std::stringstream) {
*ss_ << str;
}
- ~Message() { delete ss_; }
#if GTEST_OS_SYMBIAN
// Streams a value (either a pointer or not) to this object.
template <typename T>
@@ -119,7 +118,7 @@ class GTEST_API_ Message {
// Streams a non-pointer value to this object.
template <typename T>
inline Message& operator <<(const T& val) {
- ::GTestStreamToHelper(ss_, val);
+ ::GTestStreamToHelper(ss_.get(), val);
return *this;
}
@@ -141,7 +140,7 @@ class GTEST_API_ Message {
if (pointer == NULL) {
*ss_ << "(null)";
} else {
- ::GTestStreamToHelper(ss_, pointer);
+ ::GTestStreamToHelper(ss_.get(), pointer);
}
return *this;
}
@@ -189,10 +188,11 @@ class GTEST_API_ Message {
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
internal::String GetString() const {
- return internal::StrStreamToString(ss_);
+ return internal::StringStreamToString(ss_.get());
}
private:
+
#if GTEST_OS_SYMBIAN
// These are needed as the Nokia Symbian Compiler cannot decide between
// const T& and const T* in a function template. The Nokia compiler _can_
@@ -203,17 +203,17 @@ class GTEST_API_ Message {
if (pointer == NULL) {
*ss_ << "(null)";
} else {
- ::GTestStreamToHelper(ss_, pointer);
+ ::GTestStreamToHelper(ss_.get(), pointer);
}
}
template <typename T>
inline void StreamHelper(internal::false_type /*dummy*/, const T& value) {
- ::GTestStreamToHelper(ss_, value);
+ ::GTestStreamToHelper(ss_.get(), value);
}
#endif // GTEST_OS_SYMBIAN
// We'll hold the text streamed to this object here.
- internal::StrStream* const ss_;
+ const internal::scoped_ptr< ::std::stringstream> ss_;
// We declare (but don't implement) this to prevent the compiler
// from implementing the assignment operator.
diff --git a/utils/unittest/googletest/include/gtest/gtest-param-test.h b/utils/unittest/googletest/include/gtest/gtest-param-test.h
index 3184d07..b1f8bb9 100644
--- a/utils/unittest/googletest/include/gtest/gtest-param-test.h
+++ b/utils/unittest/googletest/include/gtest/gtest-param-test.h
@@ -1,4 +1,6 @@
-// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
+// This file was GENERATED by command:
+// pump.py gtest-param-test.h.pump
+// DO NOT EDIT BY HAND!!!
// Copyright 2008, Google Inc.
// All rights reserved.
@@ -48,10 +50,12 @@
#if 0
// To write value-parameterized tests, first you should define a fixture
-// class. It must be derived from testing::TestWithParam<T>, where T is
-// the type of your parameter values. TestWithParam<T> is itself derived
-// from testing::Test. T can be any copyable type. If it's a raw pointer,
-// you are responsible for managing the lifespan of the pointed values.
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
class FooTest : public ::testing::TestWithParam<const char*> {
// You can implement all the usual class fixture members here.
@@ -146,20 +150,46 @@ INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
// In the future, we plan to publish the API for defining new parameter
// generators. But for now this interface remains part of the internal
// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+ // You can inherit all the usual members for a non-parameterized test
+ // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+ // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+ // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+ // GetParam works just the same here as if you inherit from TestWithParam.
+ EXPECT_TRUE(foo.Blah(GetParam()));
+}
#endif // 0
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#if !GTEST_OS_SYMBIAN
-#include <utility>
+# include <utility>
#endif
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-param-util.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
#if GTEST_HAS_PARAM_TEST
@@ -275,11 +305,10 @@ internal::ParamGenerator<T> Range(T start, T end) {
//
template <typename ForwardIterator>
internal::ParamGenerator<
- typename ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn(
- ForwardIterator begin,
- ForwardIterator end) {
- typedef typename ::std::iterator_traits<ForwardIterator>::value_type
- ParamType;
+ typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+ typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+ ::value_type ParamType;
return internal::ParamGenerator<ParamType>(
new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
}
@@ -1197,7 +1226,7 @@ inline internal::ParamGenerator<bool> Bool() {
return Values(false, true);
}
-#if GTEST_HAS_COMBINE
+# if GTEST_HAS_COMBINE
// Combine() allows the user to combine two or more sequences to produce
// values of a Cartesian product of those sequences' elements.
//
@@ -1349,11 +1378,11 @@ internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
Generator10>(
g1, g2, g3, g4, g5, g6, g7, g8, g9, g10);
}
-#endif // GTEST_HAS_COMBINE
+# endif // GTEST_HAS_COMBINE
-#define TEST_P(test_case_name, test_name) \
+# define TEST_P(test_case_name, test_name) \
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
: public test_case_name { \
public: \
@@ -1379,7 +1408,7 @@ internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
-#define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
::testing::internal::ParamGenerator<test_case_name::ParamType> \
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
int gtest_##prefix##test_case_name##_dummy_ = \
diff --git a/utils/unittest/googletest/include/gtest/gtest-printers.h b/utils/unittest/googletest/include/gtest/gtest-printers.h
new file mode 100644
index 0000000..9cbab3f
--- /dev/null
+++ b/utils/unittest/googletest/include/gtest/gtest-printers.h
@@ -0,0 +1,796 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T. More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+// 1. foo::PrintTo(const T&, ostream*)
+// 2. operator<<(ostream&, const T&) defined in either foo or the
+// global namespace.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
+//
+// To aid debugging: when T is a reference type, the address of the
+// value is also printed; when T is a (const) char pointer, both the
+// pointer value and the NUL-terminated string it points to are
+// printed.
+//
+// We also provide some convenient wrappers:
+//
+// // Prints a value to a string. For a (const or not) char
+// // pointer, the NUL-terminated string (but not the pointer) is
+// // printed.
+// std::string ::testing::PrintToString(const T& value);
+//
+// // Prints a value tersely: for a reference type, the referenced
+// // value (but not the address) is printed; for a (const or not) char
+// // pointer, the NUL-terminated string (but not the pointer) is
+// // printed.
+// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
+//
+// // Prints value using the type inferred by the compiler. The difference
+// // from UniversalTersePrint() is that this function prints both the
+// // pointer and the NUL-terminated string for a (const or not) char pointer.
+// void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
+// // Prints the fields of a tuple tersely to a string vector, one
+// // element for each field. Tuple support must be enabled in
+// // gtest-port.h.
+// std::vector<string> UniversalTersePrintTupleFieldsToStrings(
+// const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container. When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect. In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator. We'll fix this if there's an
+// actual need for it. Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+#include <ostream> // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-internal.h"
+
+namespace testing {
+
+// Definitions in the 'internal' and 'internal2' name spaces are
+// subject to change without notice. DO NOT USE THEM IN USER CODE!
+namespace internal2 {
+
+// Prints the given number of bytes in the given object to the given
+// ostream.
+GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
+ size_t count,
+ ::std::ostream* os);
+
+// For selecting which printer to use when a given type has neither <<
+// nor PrintTo().
+enum TypeKind {
+ kProtobuf, // a protobuf type
+ kConvertibleToInteger, // a type implicitly convertible to BiggestInt
+ // (e.g. a named or unnamed enum type)
+ kOtherType // anything else
+};
+
+// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
+// by the universal printer to print a value of type T when neither
+// operator<< nor PrintTo() is defined for T, where kTypeKind is the
+// "kind" of T as defined by enum TypeKind.
+template <typename T, TypeKind kTypeKind>
+class TypeWithoutFormatter {
+ public:
+ // This default version is called when kTypeKind is kOtherType.
+ static void PrintValue(const T& value, ::std::ostream* os) {
+ PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
+ sizeof(value), os);
+ }
+};
+
+// We print a protobuf using its ShortDebugString() when the string
+// doesn't exceed this many characters; otherwise we print it using
+// DebugString() for better readability.
+const size_t kProtobufOneLinerMaxLength = 50;
+
+template <typename T>
+class TypeWithoutFormatter<T, kProtobuf> {
+ public:
+ static void PrintValue(const T& value, ::std::ostream* os) {
+ const ::testing::internal::string short_str = value.ShortDebugString();
+ const ::testing::internal::string pretty_str =
+ short_str.length() <= kProtobufOneLinerMaxLength ?
+ short_str : ("\n" + value.DebugString());
+ *os << ("<" + pretty_str + ">");
+ }
+};
+
+template <typename T>
+class TypeWithoutFormatter<T, kConvertibleToInteger> {
+ public:
+ // Since T has no << operator or PrintTo() but can be implicitly
+ // converted to BiggestInt, we print it as a BiggestInt.
+ //
+ // Most likely T is an enum type (either named or unnamed), in which
+ // case printing it as an integer is the desired behavior. In case
+ // T is not an enum, printing it as an integer is the best we can do
+ // given that it has no user-defined printer.
+ static void PrintValue(const T& value, ::std::ostream* os) {
+ const internal::BiggestInt kBigInt = value;
+ *os << kBigInt;
+ }
+};
+
+// Prints the given value to the given ostream. If the value is a
+// protocol message, its debug string is printed; if it's an enum or
+// of a type implicitly convertible to BiggestInt, it's printed as an
+// integer; otherwise the bytes in the value are printed. This is
+// what UniversalPrinter<T>::Print() does when it knows nothing about
+// type T and T has neither << operator nor PrintTo().
+//
+// A user can override this behavior for a class type Foo by defining
+// a << operator in the namespace where Foo is defined.
+//
+// We put this operator in namespace 'internal2' instead of 'internal'
+// to simplify the implementation, as much code in 'internal' needs to
+// use << in STL, which would conflict with our own << were it defined
+// in 'internal'.
+//
+// Note that this operator<< takes a generic std::basic_ostream<Char,
+// CharTraits> type instead of the more restricted std::ostream. If
+// we define it to take an std::ostream instead, we'll get an
+// "ambiguous overloads" compiler error when trying to print a type
+// Foo that supports streaming to std::basic_ostream<Char,
+// CharTraits>, as the compiler cannot tell whether
+// operator<<(std::ostream&, const T&) or
+// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
+// specific.
+template <typename Char, typename CharTraits, typename T>
+::std::basic_ostream<Char, CharTraits>& operator<<(
+ ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
+ TypeWithoutFormatter<T,
+ (internal::IsAProtocolMessage<T>::value ? kProtobuf :
+ internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
+ kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
+ return os;
+}
+
+} // namespace internal2
+} // namespace testing
+
+// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
+// magic needed for implementing UniversalPrinter won't work.
+namespace testing_internal {
+
+// Used to print a value that is not an STL-style container when the
+// user doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
+ // With the following statement, during unqualified name lookup,
+ // testing::internal2::operator<< appears as if it was declared in
+ // the nearest enclosing namespace that contains both
+ // ::testing_internal and ::testing::internal2, i.e. the global
+ // namespace. For more details, refer to the C++ Standard section
+ // 7.3.4-1 [namespace.udir]. This allows us to fall back onto
+ // testing::internal2::operator<< in case T doesn't come with a <<
+ // operator.
+ //
+ // We cannot write 'using ::testing::internal2::operator<<;', which
+ // gcc 3.3 fails to compile due to a compiler bug.
+ using namespace ::testing::internal2; // NOLINT
+
+ // Assuming T is defined in namespace foo, in the next statement,
+ // the compiler will consider all of:
+ //
+ // 1. foo::operator<< (thanks to Koenig look-up),
+ // 2. ::operator<< (as the current namespace is enclosed in ::),
+ // 3. testing::internal2::operator<< (thanks to the using statement above).
+ //
+ // The operator<< whose type matches T best will be picked.
+ //
+ // We deliberately allow #2 to be a candidate, as sometimes it's
+ // impossible to define #1 (e.g. when foo is ::std, defining
+ // anything in it is undefined behavior unless you are a compiler
+ // vendor.).
+ *os << value;
+}
+
+} // namespace testing_internal
+
+namespace testing {
+namespace internal {
+
+// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
+// value to the given ostream. The caller must ensure that
+// 'ostream_ptr' is not NULL, or the behavior is undefined.
+//
+// We define UniversalPrinter as a class template (as opposed to a
+// function template), as we need to partially specialize it for
+// reference types, which cannot be done with function templates.
+template <typename T>
+class UniversalPrinter;
+
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
+// Used to print an STL-style container when the user doesn't define
+// a PrintTo() for it.
+template <typename C>
+void DefaultPrintTo(IsContainer /* dummy */,
+ false_type /* is not a pointer */,
+ const C& container, ::std::ostream* os) {
+ const size_t kMaxCount = 32; // The maximum number of elements to print.
+ *os << '{';
+ size_t count = 0;
+ for (typename C::const_iterator it = container.begin();
+ it != container.end(); ++it, ++count) {
+ if (count > 0) {
+ *os << ',';
+ if (count == kMaxCount) { // Enough has been printed.
+ *os << " ...";
+ break;
+ }
+ }
+ *os << ' ';
+ // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
+ // handle *it being a native array.
+ internal::UniversalPrint(*it, os);
+ }
+
+ if (count > 0) {
+ *os << ' ';
+ }
+ *os << '}';
+}
+
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it. (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space. Their representation is
+// implementation-defined. Therefore they will be printed as raw
+// bytes.)
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+ true_type /* is a pointer */,
+ T* p, ::std::ostream* os) {
+ if (p == NULL) {
+ *os << "NULL";
+ } else {
+ // C++ doesn't allow casting from a function pointer to any object
+ // pointer.
+ //
+ // IsTrue() silences warnings: "Condition is always true",
+ // "unreachable code".
+ if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
+ // T is not a function type. We just call << to print p,
+ // relying on ADL to pick up user-defined << for their pointer
+ // types, if any.
+ *os << p;
+ } else {
+ // T is a function type, so '*os << p' doesn't do what we want
+ // (it just prints p as bool). We want to print p as a const
+ // void*. However, we cannot cast it to const void* directly,
+ // even using reinterpret_cast, as earlier versions of gcc
+ // (e.g. 3.4.5) cannot compile the cast when p is a function
+ // pointer. Casting to UInt64 first solves the problem.
+ *os << reinterpret_cast<const void*>(
+ reinterpret_cast<internal::UInt64>(p));
+ }
+ }
+}
+
+// Used to print a non-container, non-pointer value when the user
+// doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+ false_type /* is not a pointer */,
+ const T& value, ::std::ostream* os) {
+ ::testing_internal::DefaultPrintNonContainerTo(value, os);
+}
+
+// Prints the given value using the << operator if it has one;
+// otherwise prints the bytes in it. This is what
+// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
+// or overloaded for type T.
+//
+// A user can override this behavior for a class type Foo by defining
+// an overload of PrintTo() in the namespace where Foo is defined. We
+// give the user this option as sometimes defining a << operator for
+// Foo is not desirable (e.g. the coding style may prevent doing it,
+// or there is already a << operator but it doesn't do what the user
+// wants).
+template <typename T>
+void PrintTo(const T& value, ::std::ostream* os) {
+ // DefaultPrintTo() is overloaded. The type of its first two
+ // arguments determine which version will be picked. If T is an
+ // STL-style container, the version for container will be called; if
+ // T is a pointer, the pointer version will be called; otherwise the
+ // generic version will be called.
+ //
+ // Note that we check for container types here, prior to we check
+ // for protocol message types in our operator<<. The rationale is:
+ //
+ // For protocol messages, we want to give people a chance to
+ // override Google Mock's format by defining a PrintTo() or
+ // operator<<. For STL containers, other formats can be
+ // incompatible with Google Mock's format for the container
+ // elements; therefore we check for container types here to ensure
+ // that our format is used.
+ //
+ // The second argument of DefaultPrintTo() is needed to bypass a bug
+ // in Symbian's C++ compiler that prevents it from picking the right
+ // overload between:
+ //
+ // PrintTo(const T& x, ...);
+ // PrintTo(T* x, ...);
+ DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
+}
+
+// The following list of PrintTo() overloads tells
+// UniversalPrinter<T>::Print() how to print standard types (built-in
+// types, strings, plain arrays, and pointers).
+
+// Overloads for various char types.
+GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
+GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
+inline void PrintTo(char c, ::std::ostream* os) {
+ // When printing a plain char, we always treat it as unsigned. This
+ // way, the output won't be affected by whether the compiler thinks
+ // char is signed or not.
+ PrintTo(static_cast<unsigned char>(c), os);
+}
+
+// Overloads for other simple built-in types.
+inline void PrintTo(bool x, ::std::ostream* os) {
+ *os << (x ? "true" : "false");
+}
+
+// Overload for wchar_t type.
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its decimal code (except for L'\0').
+// The L'\0' char is printed as "L'\\0'". The decimal code is printed
+// as signed integer when wchar_t is implemented by the compiler
+// as a signed type and is printed as an unsigned integer when wchar_t
+// is implemented as an unsigned type.
+GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
+
+// Overloads for C strings.
+GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
+inline void PrintTo(char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const char*>(s), os);
+}
+
+// signed/unsigned char is often used for representing binary data, so
+// we print pointers to it as void* to be safe.
+inline void PrintTo(const signed char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(signed char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(unsigned char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+
+// MSVC can be configured to define wchar_t as a typedef of unsigned
+// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
+// type. When wchar_t is a typedef, defining an overload for const
+// wchar_t* would cause unsigned short* be printed as a wide string,
+// possibly causing invalid memory accesses.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Overloads for wide C strings
+GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
+inline void PrintTo(wchar_t* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const wchar_t*>(s), os);
+}
+#endif
+
+// Overload for C arrays. Multi-dimensional arrays are printed
+// properly.
+
+// Prints the given number of elements in an array, without printing
+// the curly braces.
+template <typename T>
+void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
+ UniversalPrint(a[0], os);
+ for (size_t i = 1; i != count; i++) {
+ *os << ", ";
+ UniversalPrint(a[i], os);
+ }
+}
+
+// Overloads for ::string and ::std::string.
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
+inline void PrintTo(const ::string& s, ::std::ostream* os) {
+ PrintStringTo(s, os);
+}
+#endif // GTEST_HAS_GLOBAL_STRING
+
+GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
+inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
+ PrintStringTo(s, os);
+}
+
+// Overloads for ::wstring and ::std::wstring.
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
+ PrintWideStringTo(s, os);
+}
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
+ PrintWideStringTo(s, os);
+}
+#endif // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_TR1_TUPLE
+// Overload for ::std::tr1::tuple. Needed for printing function arguments,
+// which are packed as tuples.
+
+// Helper function for printing a tuple. T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os);
+
+// Overloaded PrintTo() for tuples of various arities. We support
+// tuples of up-to 10 fields. The following implementation works
+// regardless of whether tr1::tuple is implemented using the
+// non-standard variadic template feature or not.
+
+inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1>
+void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2>
+void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+void PrintTo(
+ const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+#endif // GTEST_HAS_TR1_TUPLE
+
+// Overload for std::pair.
+template <typename T1, typename T2>
+void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
+ *os << '(';
+ // We cannot use UniversalPrint(value.first, os) here, as T1 may be
+ // a reference type. The same for printing value.second.
+ UniversalPrinter<T1>::Print(value.first, os);
+ *os << ", ";
+ UniversalPrinter<T2>::Print(value.second, os);
+ *os << ')';
+}
+
+// Implements printing a non-reference type T by letting the compiler
+// pick the right overload of PrintTo() for T.
+template <typename T>
+class UniversalPrinter {
+ public:
+ // MSVC warns about adding const to a function type, so we want to
+ // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4180) // Temporarily disables warning 4180.
+#endif // _MSC_VER
+
+ // Note: we deliberately don't call this PrintTo(), as that name
+ // conflicts with ::testing::internal::PrintTo in the body of the
+ // function.
+ static void Print(const T& value, ::std::ostream* os) {
+ // By default, ::testing::internal::PrintTo() is used for printing
+ // the value.
+ //
+ // Thanks to Koenig look-up, if T is a class and has its own
+ // PrintTo() function defined in its namespace, that function will
+ // be visible here. Since it is more specific than the generic ones
+ // in ::testing::internal, it will be picked by the compiler in the
+ // following statement - exactly what we want.
+ PrintTo(value, os);
+ }
+
+#ifdef _MSC_VER
+# pragma warning(pop) // Restores the warning state.
+#endif // _MSC_VER
+};
+
+// UniversalPrintArray(begin, len, os) prints an array of 'len'
+// elements, starting at address 'begin'.
+template <typename T>
+void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
+ if (len == 0) {
+ *os << "{}";
+ } else {
+ *os << "{ ";
+ const size_t kThreshold = 18;
+ const size_t kChunkSize = 8;
+ // If the array has more than kThreshold elements, we'll have to
+ // omit some details by printing only the first and the last
+ // kChunkSize elements.
+ // TODO(wan@google.com): let the user control the threshold using a flag.
+ if (len <= kThreshold) {
+ PrintRawArrayTo(begin, len, os);
+ } else {
+ PrintRawArrayTo(begin, kChunkSize, os);
+ *os << ", ..., ";
+ PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
+ }
+ *os << " }";
+ }
+}
+// This overload prints a (const) char array compactly.
+GTEST_API_ void UniversalPrintArray(const char* begin,
+ size_t len,
+ ::std::ostream* os);
+
+// Implements printing an array type T[N].
+template <typename T, size_t N>
+class UniversalPrinter<T[N]> {
+ public:
+ // Prints the given array, omitting some elements when there are too
+ // many.
+ static void Print(const T (&a)[N], ::std::ostream* os) {
+ UniversalPrintArray(a, N, os);
+ }
+};
+
+// Implements printing a reference type T&.
+template <typename T>
+class UniversalPrinter<T&> {
+ public:
+ // MSVC warns about adding const to a function type, so we want to
+ // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4180) // Temporarily disables warning 4180.
+#endif // _MSC_VER
+
+ static void Print(const T& value, ::std::ostream* os) {
+ // Prints the address of the value. We use reinterpret_cast here
+ // as static_cast doesn't compile when T is a function type.
+ *os << "@" << reinterpret_cast<const void*>(&value) << " ";
+
+ // Then prints the value itself.
+ UniversalPrint(value, os);
+ }
+
+#ifdef _MSC_VER
+# pragma warning(pop) // Restores the warning state.
+#endif // _MSC_VER
+};
+
+// Prints a value tersely: for a reference type, the referenced value
+// (but not the address) is printed; for a (const) char pointer, the
+// NUL-terminated string (but not the pointer) is printed.
+template <typename T>
+void UniversalTersePrint(const T& value, ::std::ostream* os) {
+ UniversalPrint(value, os);
+}
+inline void UniversalTersePrint(const char* str, ::std::ostream* os) {
+ if (str == NULL) {
+ *os << "NULL";
+ } else {
+ UniversalPrint(string(str), os);
+ }
+}
+inline void UniversalTersePrint(char* str, ::std::ostream* os) {
+ UniversalTersePrint(static_cast<const char*>(str), os);
+}
+
+// Prints a value using the type inferred by the compiler. The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+ UniversalPrinter<T>::Print(value, os);
+}
+
+#if GTEST_HAS_TR1_TUPLE
+typedef ::std::vector<string> Strings;
+
+// This helper template allows PrintTo() for tuples and
+// UniversalTersePrintTupleFieldsToStrings() to be defined by
+// induction on the number of tuple fields. The idea is that
+// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
+// fields in tuple t, and can be defined in terms of
+// TuplePrefixPrinter<N - 1>.
+
+// The inductive case.
+template <size_t N>
+struct TuplePrefixPrinter {
+ // Prints the first N fields of a tuple.
+ template <typename Tuple>
+ static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+ TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
+ *os << ", ";
+ UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
+ ::Print(::std::tr1::get<N - 1>(t), os);
+ }
+
+ // Tersely prints the first N fields of a tuple to a string vector,
+ // one element for each field.
+ template <typename Tuple>
+ static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+ TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
+ ::std::stringstream ss;
+ UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
+ strings->push_back(ss.str());
+ }
+};
+
+// Base cases.
+template <>
+struct TuplePrefixPrinter<0> {
+ template <typename Tuple>
+ static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
+
+ template <typename Tuple>
+ static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
+};
+// We have to specialize the entire TuplePrefixPrinter<> class
+// template here, even though the definition of
+// TersePrintPrefixToStrings() is the same as the generic version, as
+// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't
+// support specializing a method template of a class template.
+template <>
+struct TuplePrefixPrinter<1> {
+ template <typename Tuple>
+ static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+ UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
+ Print(::std::tr1::get<0>(t), os);
+ }
+
+ template <typename Tuple>
+ static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+ ::std::stringstream ss;
+ UniversalTersePrint(::std::tr1::get<0>(t), &ss);
+ strings->push_back(ss.str());
+ }
+};
+
+// Helper function for printing a tuple. T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os) {
+ *os << "(";
+ TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
+ PrintPrefixTo(t, os);
+ *os << ")";
+}
+
+// Prints the fields of a tuple tersely to a string vector, one
+// element for each field. See the comment before
+// UniversalTersePrint() for how we define "tersely".
+template <typename Tuple>
+Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
+ Strings result;
+ TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
+ TersePrintPrefixToStrings(value, &result);
+ return result;
+}
+#endif // GTEST_HAS_TR1_TUPLE
+
+} // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+ ::std::stringstream ss;
+ internal::UniversalTersePrint(value, &ss);
+ return ss.str();
+}
+
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
diff --git a/utils/unittest/googletest/include/gtest/gtest-spi.h b/utils/unittest/googletest/include/gtest/gtest-spi.h
index c41da48..b226e55 100644
--- a/utils/unittest/googletest/include/gtest/gtest-spi.h
+++ b/utils/unittest/googletest/include/gtest/gtest-spi.h
@@ -35,7 +35,7 @@
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
namespace testing {
@@ -98,12 +98,12 @@ class GTEST_API_ SingleFailureChecker {
// The constructor remembers the arguments.
SingleFailureChecker(const TestPartResultArray* results,
TestPartResult::Type type,
- const char* substr);
+ const string& substr);
~SingleFailureChecker();
private:
const TestPartResultArray* const results_;
const TestPartResult::Type type_;
- const String substr_;
+ const string substr_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
};
diff --git a/utils/unittest/googletest/include/gtest/gtest-test-part.h b/utils/unittest/googletest/include/gtest/gtest-test-part.h
index f714759..8aeea14 100644
--- a/utils/unittest/googletest/include/gtest/gtest-test-part.h
+++ b/utils/unittest/googletest/include/gtest/gtest-test-part.h
@@ -35,8 +35,8 @@
#include <iosfwd>
#include <vector>
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-string.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
namespace testing {
diff --git a/utils/unittest/googletest/include/gtest/gtest-typed-test.h b/utils/unittest/googletest/include/gtest/gtest-typed-test.h
index 1ec8eb8..fe1e83b 100644
--- a/utils/unittest/googletest/include/gtest/gtest-typed-test.h
+++ b/utils/unittest/googletest/include/gtest/gtest-typed-test.h
@@ -146,8 +146,8 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
#endif // 0
-#include <gtest/internal/gtest-port.h>
-#include <gtest/internal/gtest-type-util.h>
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-type-util.h"
// Implements typed tests.
@@ -157,16 +157,16 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
//
// Expands to the name of the typedef for the type parameters of the
// given test case.
-#define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
+# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
// The 'Types' template argument below must have spaces around it
// since some compilers may choke on '>>' when passing a template
// instance (e.g. Types<int>)
-#define TYPED_TEST_CASE(CaseName, Types) \
+# define TYPED_TEST_CASE(CaseName, Types) \
typedef ::testing::internal::TypeList< Types >::type \
GTEST_TYPE_PARAMS_(CaseName)
-#define TYPED_TEST(CaseName, TestName) \
+# define TYPED_TEST(CaseName, TestName) \
template <typename gtest_TypeParam_> \
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
: public CaseName<gtest_TypeParam_> { \
@@ -175,7 +175,7 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
typedef gtest_TypeParam_ TypeParam; \
virtual void TestBody(); \
}; \
- bool gtest_##CaseName##_##TestName##_registered_ = \
+ bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
::testing::internal::TypeParameterizedTest< \
CaseName, \
::testing::internal::TemplateSel< \
@@ -196,31 +196,31 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
// Expands to the namespace name that the type-parameterized tests for
// the given type-parameterized test case are defined in. The exact
// name of the namespace is subject to change without notice.
-#define GTEST_CASE_NAMESPACE_(TestCaseName) \
+# define GTEST_CASE_NAMESPACE_(TestCaseName) \
gtest_case_##TestCaseName##_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Expands to the name of the variable used to remember the names of
// the defined tests in the given test case.
-#define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
+# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
gtest_typed_test_case_p_state_##TestCaseName##_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
//
// Expands to the name of the variable used to remember the names of
// the registered tests in the given test case.
-#define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
+# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
gtest_registered_test_names_##TestCaseName##_
// The variables defined in the type-parameterized test macros are
// static as typically these macros are used in a .h file that can be
// #included in multiple translation units linked together.
-#define TYPED_TEST_CASE_P(CaseName) \
+# define TYPED_TEST_CASE_P(CaseName) \
static ::testing::internal::TypedTestCasePState \
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
-#define TYPED_TEST_P(CaseName, TestName) \
+# define TYPED_TEST_P(CaseName, TestName) \
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
template <typename gtest_TypeParam_> \
class TestName : public CaseName<gtest_TypeParam_> { \
@@ -229,14 +229,14 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
typedef gtest_TypeParam_ TypeParam; \
virtual void TestBody(); \
}; \
- static bool gtest_##TestName##_defined_ = \
+ static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
__FILE__, __LINE__, #CaseName, #TestName); \
} \
template <typename gtest_TypeParam_> \
void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
-#define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
+# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
} \
@@ -247,8 +247,8 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
// The 'Types' template argument below must have spaces around it
// since some compilers may choke on '>>' when passing a template
// instance (e.g. Types<int>)
-#define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
- bool gtest_##Prefix##_##CaseName = \
+# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
+ bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
::testing::internal::TypeParameterizedTestCase<CaseName, \
GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
::testing::internal::TypeList< Types >::type>::Register(\
diff --git a/utils/unittest/googletest/include/gtest/gtest.h b/utils/unittest/googletest/include/gtest/gtest.h
index 5470082..1734c44 100644
--- a/utils/unittest/googletest/include/gtest/gtest.h
+++ b/utils/unittest/googletest/include/gtest/gtest.h
@@ -54,14 +54,15 @@
#include <limits>
#include <vector>
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-string.h>
-#include <gtest/gtest-death-test.h>
-#include <gtest/gtest-message.h>
-#include <gtest/gtest-param-test.h>
-#include <gtest/gtest_prod.h>
-#include <gtest/gtest-test-part.h>
-#include <gtest/gtest-typed-test.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest-message.h"
+#include "gtest/gtest-param-test.h"
+#include "gtest/gtest-printers.h"
+#include "gtest/gtest_prod.h"
+#include "gtest/gtest-test-part.h"
+#include "gtest/gtest-typed-test.h"
// Depending on the platform, different string classes are available.
// On Linux, in addition to ::std::string, Google also makes use of
@@ -136,6 +137,11 @@ GTEST_DECLARE_int32_(stack_trace_depth);
// non-zero code otherwise.
GTEST_DECLARE_bool_(throw_on_failure);
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
// The upper limit for valid stack trace depths.
const int kMaxStackTraceDepth = 100;
@@ -147,7 +153,6 @@ class ExecDeathTest;
class NoExecDeathTest;
class FinalSuccessChecker;
class GTestFlagSaver;
-class TestInfoImpl;
class TestResultAccessor;
class TestEventListenersAccessor;
class TestEventRepeater;
@@ -155,8 +160,6 @@ class WindowsDeathTest;
class UnitTestImpl* GetUnitTestImpl();
void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
const String& message);
-class PrettyUnitTestResultPrinter;
-class XmlUnitTestResultPrinter;
// Converts a streamable value to a String. A NULL pointer is
// converted to "(null)". When the input value is a ::string,
@@ -172,6 +175,14 @@ String StreamableToString(const T& streamable) {
} // namespace internal
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestCase;
+class TestInfo;
+class UnitTest;
+
// A class for indicating whether an assertion was successful. When
// the assertion wasn't successful, the AssertionResult object
// remembers a non-empty message that describes how it failed.
@@ -270,20 +281,33 @@ class GTEST_API_ AssertionResult {
// assertion's expectation). When nothing has been streamed into the
// object, returns an empty string.
const char* message() const {
- return message_.get() != NULL && message_->c_str() != NULL ?
- message_->c_str() : "";
+ return message_.get() != NULL ? message_->c_str() : "";
}
// TODO(vladl@google.com): Remove this after making sure no clients use it.
// Deprecated; please use message() instead.
const char* failure_message() const { return message(); }
// Streams a custom failure message into this object.
- template <typename T> AssertionResult& operator<<(const T& value);
+ template <typename T> AssertionResult& operator<<(const T& value) {
+ AppendMessage(Message() << value);
+ return *this;
+ }
+
+ // Allows streaming basic output manipulators such as endl or flush into
+ // this object.
+ AssertionResult& operator<<(
+ ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+ AppendMessage(Message() << basic_manipulator);
+ return *this;
+ }
private:
- // No implementation - we want AssertionResult to be
- // copy-constructible but not assignable.
- void operator=(const AssertionResult& other);
+ // Appends the contents of message to message_.
+ void AppendMessage(const Message& a_message) {
+ if (message_.get() == NULL)
+ message_.reset(new ::std::string);
+ message_->append(a_message.GetString().c_str());
+ }
// Stores result of the assertion predicate.
bool success_;
@@ -291,19 +315,10 @@ class GTEST_API_ AssertionResult {
// construct is not satisfied with the predicate's outcome.
// Referenced via a pointer to avoid taking too much stack frame space
// with test assertions.
- internal::scoped_ptr<internal::String> message_;
-}; // class AssertionResult
+ internal::scoped_ptr< ::std::string> message_;
-// Streams a custom failure message into this object.
-template <typename T>
-AssertionResult& AssertionResult::operator<<(const T& value) {
- Message msg;
- if (message_.get() != NULL)
- msg << *message_;
- msg << value;
- message_.reset(new internal::String(msg.GetString()));
- return *this;
-}
+ GTEST_DISALLOW_ASSIGN_(AssertionResult);
+};
// Makes a successful assertion result.
GTEST_API_ AssertionResult AssertionSuccess();
@@ -340,7 +355,7 @@ GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
// Test is not copyable.
class GTEST_API_ Test {
public:
- friend class internal::TestInfoImpl;
+ friend class TestInfo;
// Defines types for pointers to functions that set up and tear down
// a test case.
@@ -417,6 +432,10 @@ class GTEST_API_ Test {
// Sets up, executes, and tears down the test.
void Run();
+ // Deletes self. We deliberately pick an unusual name for this
+ // internal method to avoid clashing with names used in user TESTs.
+ void DeleteSelf_() { delete this; }
+
// Uses a GTestFlagSaver to save and restore all Google Test flags.
const internal::GTestFlagSaver* const gtest_flag_saver_;
@@ -531,7 +550,6 @@ class GTEST_API_ TestResult {
friend class UnitTest;
friend class internal::DefaultGlobalTestPartResultReporter;
friend class internal::ExecDeathTest;
- friend class internal::TestInfoImpl;
friend class internal::TestResultAccessor;
friend class internal::UnitTestImpl;
friend class internal::WindowsDeathTest;
@@ -611,16 +629,26 @@ class GTEST_API_ TestInfo {
~TestInfo();
// Returns the test case name.
- const char* test_case_name() const;
+ const char* test_case_name() const { return test_case_name_.c_str(); }
// Returns the test name.
- const char* name() const;
+ const char* name() const { return name_.c_str(); }
- // Returns the test case comment.
- const char* test_case_comment() const;
+ // Returns the name of the parameter type, or NULL if this is not a typed
+ // or a type-parameterized test.
+ const char* type_param() const {
+ if (type_param_.get() != NULL)
+ return type_param_->c_str();
+ return NULL;
+ }
- // Returns the test comment.
- const char* comment() const;
+ // Returns the text representation of the value parameter, or NULL if this
+ // is not a value-parameterized test.
+ const char* value_param() const {
+ if (value_param_.get() != NULL)
+ return value_param_->c_str();
+ return NULL;
+ }
// Returns true if this test should run, that is if the test is not disabled
// (or it is disabled but the also_run_disabled_tests flag has been specified)
@@ -638,47 +666,70 @@ class GTEST_API_ TestInfo {
//
// For example, *A*:Foo.* is a filter that matches any string that
// contains the character 'A' or starts with "Foo.".
- bool should_run() const;
+ bool should_run() const { return should_run_; }
// Returns the result of the test.
- const TestResult* result() const;
+ const TestResult* result() const { return &result_; }
private:
+
#if GTEST_HAS_DEATH_TEST
friend class internal::DefaultDeathTestFactory;
#endif // GTEST_HAS_DEATH_TEST
friend class Test;
friend class TestCase;
- friend class internal::TestInfoImpl;
friend class internal::UnitTestImpl;
friend TestInfo* internal::MakeAndRegisterTestInfo(
const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* type_param,
+ const char* value_param,
internal::TypeId fixture_class_id,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc,
internal::TestFactoryBase* factory);
- // Returns true if this test matches the user-specified filter.
- bool matches_filter() const;
-
- // Increments the number of death tests encountered in this test so
- // far.
- int increment_death_test_count();
-
- // Accessors for the implementation object.
- internal::TestInfoImpl* impl() { return impl_; }
- const internal::TestInfoImpl* impl() const { return impl_; }
-
// Constructs a TestInfo object. The newly constructed instance assumes
// ownership of the factory object.
TestInfo(const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* a_type_param,
+ const char* a_value_param,
internal::TypeId fixture_class_id,
internal::TestFactoryBase* factory);
- // An opaque implementation object.
- internal::TestInfoImpl* impl_;
+ // Increments the number of death tests encountered in this test so
+ // far.
+ int increment_death_test_count() {
+ return result_.increment_death_test_count();
+ }
+
+ // Creates the test object, runs it, records its result, and then
+ // deletes it.
+ void Run();
+
+ static void ClearTestResult(TestInfo* test_info) {
+ test_info->result_.Clear();
+ }
+
+ // These fields are immutable properties of the test.
+ const std::string test_case_name_; // Test case name
+ const std::string name_; // Test name
+ // Name of the parameter type, or NULL if this is not a typed or a
+ // type-parameterized test.
+ const internal::scoped_ptr<const ::std::string> type_param_;
+ // Text representation of the value parameter, or NULL if this is not a
+ // value-parameterized test.
+ const internal::scoped_ptr<const ::std::string> value_param_;
+ const internal::TypeId fixture_class_id_; // ID of the test fixture class
+ bool should_run_; // True iff this test should run
+ bool is_disabled_; // True iff this test is disabled
+ bool matches_filter_; // True if this test matches the
+ // user-specified filter.
+ internal::TestFactoryBase* const factory_; // The factory that creates
+ // the test object
+
+ // This field is mutable and needs to be reset before running the
+ // test for the second time.
+ TestResult result_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
};
@@ -696,9 +747,11 @@ class GTEST_API_ TestCase {
// Arguments:
//
// name: name of the test case
+ // a_type_param: the name of the test's type parameter, or NULL if
+ // this is not a type-parameterized test.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
- TestCase(const char* name, const char* comment,
+ TestCase(const char* name, const char* a_type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc);
@@ -708,8 +761,13 @@ class GTEST_API_ TestCase {
// Gets the name of the TestCase.
const char* name() const { return name_.c_str(); }
- // Returns the test case comment.
- const char* comment() const { return comment_.c_str(); }
+ // Returns the name of the parameter type, or NULL if this is not a
+ // type-parameterized test case.
+ const char* type_param() const {
+ if (type_param_.get() != NULL)
+ return type_param_->c_str();
+ return NULL;
+ }
// Returns true if any test in this test case should run.
bool should_run() const { return should_run_; }
@@ -776,17 +834,33 @@ class GTEST_API_ TestCase {
// Runs every test in this TestCase.
void Run();
+ // Runs SetUpTestCase() for this TestCase. This wrapper is needed
+ // for catching exceptions thrown from SetUpTestCase().
+ void RunSetUpTestCase() { (*set_up_tc_)(); }
+
+ // Runs TearDownTestCase() for this TestCase. This wrapper is
+ // needed for catching exceptions thrown from TearDownTestCase().
+ void RunTearDownTestCase() { (*tear_down_tc_)(); }
+
// Returns true iff test passed.
- static bool TestPassed(const TestInfo * test_info);
+ static bool TestPassed(const TestInfo* test_info) {
+ return test_info->should_run() && test_info->result()->Passed();
+ }
// Returns true iff test failed.
- static bool TestFailed(const TestInfo * test_info);
+ static bool TestFailed(const TestInfo* test_info) {
+ return test_info->should_run() && test_info->result()->Failed();
+ }
// Returns true iff test is disabled.
- static bool TestDisabled(const TestInfo * test_info);
+ static bool TestDisabled(const TestInfo* test_info) {
+ return test_info->is_disabled_;
+ }
// Returns true if the given test should run.
- static bool ShouldRunTest(const TestInfo *test_info);
+ static bool ShouldRunTest(const TestInfo* test_info) {
+ return test_info->should_run();
+ }
// Shuffles the tests in this test case.
void ShuffleTests(internal::Random* random);
@@ -796,8 +870,9 @@ class GTEST_API_ TestCase {
// Name of the test case.
internal::String name_;
- // Comment on the test case.
- internal::String comment_;
+ // Name of the parameter type, or NULL if this is not a typed or a
+ // type-parameterized test.
+ const internal::scoped_ptr<const ::std::string> type_param_;
// The vector of TestInfos in their original order. It owns the
// elements in the vector.
std::vector<TestInfo*> test_info_list_;
@@ -876,7 +951,7 @@ class TestEventListener {
// Fired before the test starts.
virtual void OnTestStart(const TestInfo& test_info) = 0;
- // Fired after a failed assertion or a SUCCESS().
+ // Fired after a failed assertion or a SUCCEED() invocation.
virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
// Fired after the test ends.
@@ -961,10 +1036,10 @@ class GTEST_API_ TestEventListeners {
private:
friend class TestCase;
+ friend class TestInfo;
friend class internal::DefaultGlobalTestPartResultReporter;
friend class internal::NoExecDeathTest;
friend class internal::TestEventListenersAccessor;
- friend class internal::TestInfoImpl;
friend class internal::UnitTestImpl;
// Returns repeater that broadcasts the TestEventListener events to all
@@ -1206,30 +1281,6 @@ GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
namespace internal {
-// These overloaded versions handle ::std::string and ::std::wstring.
-GTEST_API_ inline String FormatForFailureMessage(const ::std::string& str) {
- return (Message() << '"' << str << '"').GetString();
-}
-
-#if GTEST_HAS_STD_WSTRING
-GTEST_API_ inline String FormatForFailureMessage(const ::std::wstring& wstr) {
- return (Message() << "L\"" << wstr << '"').GetString();
-}
-#endif // GTEST_HAS_STD_WSTRING
-
-// These overloaded versions handle ::string and ::wstring.
-#if GTEST_HAS_GLOBAL_STRING
-GTEST_API_ inline String FormatForFailureMessage(const ::string& str) {
- return (Message() << '"' << str << '"').GetString();
-}
-#endif // GTEST_HAS_GLOBAL_STRING
-
-#if GTEST_HAS_GLOBAL_WSTRING
-GTEST_API_ inline String FormatForFailureMessage(const ::wstring& wstr) {
- return (Message() << "L\"" << wstr << '"').GetString();
-}
-#endif // GTEST_HAS_GLOBAL_WSTRING
-
// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
// operand to be used in a failure message. The type (but not value)
// of the other operand may affect the format. This allows us to
@@ -1245,7 +1296,9 @@ GTEST_API_ inline String FormatForFailureMessage(const ::wstring& wstr) {
template <typename T1, typename T2>
String FormatForComparisonFailureMessage(const T1& value,
const T2& /* other_operand */) {
- return FormatForFailureMessage(value);
+ // C++Builder compiles this incorrectly if the namespace isn't explicitly
+ // given.
+ return ::testing::PrintToString(value);
}
// The helper function for {ASSERT|EXPECT}_EQ.
@@ -1255,8 +1308,8 @@ AssertionResult CmpHelperEQ(const char* expected_expression,
const T1& expected,
const T2& actual) {
#ifdef _MSC_VER
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4389) // Temporarily disables warning on
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4389) // Temporarily disables warning on
// signed/unsigned mismatch.
#pragma warning(disable:4805) // Temporarily disables warning on
// unsafe mix of types
@@ -1267,7 +1320,7 @@ AssertionResult CmpHelperEQ(const char* expected_expression,
}
#ifdef _MSC_VER
-#pragma warning(pop) // Restores the warning state.
+# pragma warning(pop) // Restores the warning state.
#endif
return EqFailure(expected_expression,
@@ -1318,7 +1371,7 @@ class EqHelper {
};
// This specialization is used when the first argument to ASSERT_EQ()
-// is a null pointer literal.
+// is a null pointer literal, like NULL, false, or 0.
template <>
class EqHelper<true> {
public:
@@ -1327,24 +1380,38 @@ class EqHelper<true> {
// NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or
// EXPECT_EQ(false, a_bool).
template <typename T1, typename T2>
- static AssertionResult Compare(const char* expected_expression,
- const char* actual_expression,
- const T1& expected,
- const T2& actual) {
+ static AssertionResult Compare(
+ const char* expected_expression,
+ const char* actual_expression,
+ const T1& expected,
+ const T2& actual,
+ // The following line prevents this overload from being considered if T2
+ // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr)
+ // expands to Compare("", "", NULL, my_ptr), which requires a conversion
+ // to match the Secret* in the other overload, which would otherwise make
+ // this template match better.
+ typename EnableIf<!is_pointer<T2>::value>::type* = 0) {
return CmpHelperEQ(expected_expression, actual_expression, expected,
actual);
}
- // This version will be picked when the second argument to
- // ASSERT_EQ() is a pointer, e.g. ASSERT_EQ(NULL, a_pointer).
- template <typename T1, typename T2>
- static AssertionResult Compare(const char* expected_expression,
- const char* actual_expression,
- const T1& /* expected */,
- T2* actual) {
+ // This version will be picked when the second argument to ASSERT_EQ() is a
+ // pointer, e.g. ASSERT_EQ(NULL, a_pointer).
+ template <typename T>
+ static AssertionResult Compare(
+ const char* expected_expression,
+ const char* actual_expression,
+ // We used to have a second template parameter instead of Secret*. That
+ // template parameter would deduce to 'long', making this a better match
+ // than the first overload even without the first overload's EnableIf.
+ // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to
+ // non-pointer argument" (even a deduced integral argument), so the old
+ // implementation caused warnings in user code.
+ Secret* /* expected (NULL) */,
+ T* actual) {
// We already know that 'expected' is a null pointer.
return CmpHelperEQ(expected_expression, actual_expression,
- static_cast<T2*>(NULL), actual);
+ static_cast<T*>(NULL), actual);
}
};
@@ -1365,11 +1432,10 @@ AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
if (val1 op val2) {\
return AssertionSuccess();\
} else {\
- Message msg;\
- msg << "Expected: (" << expr1 << ") " #op " (" << expr2\
+ return AssertionFailure() \
+ << "Expected: (" << expr1 << ") " #op " (" << expr2\
<< "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
<< " vs " << FormatForComparisonFailureMessage(val2, val1);\
- return AssertionFailure(msg);\
}\
}\
GTEST_API_ AssertionResult CmpHelper##op_name(\
@@ -1497,18 +1563,18 @@ AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression,
return AssertionSuccess();
}
- StrStream expected_ss;
+ ::std::stringstream expected_ss;
expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< expected;
- StrStream actual_ss;
+ ::std::stringstream actual_ss;
actual_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< actual;
return EqFailure(expected_expression,
actual_expression,
- StrStreamToString(&expected_ss),
- StrStreamToString(&actual_ss),
+ StringStreamToString(&expected_ss),
+ StringStreamToString(&actual_ss),
false);
}
@@ -1566,9 +1632,13 @@ class GTEST_API_ AssertHelper {
} // namespace internal
#if GTEST_HAS_PARAM_TEST
-// The abstract base class that all value-parameterized tests inherit from.
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
//
-// This class adds support for accessing the test parameter value via
+// This interface has support for accessing the test parameter value via
// the GetParam() method.
//
// Use it with one of the parameter generator defining functions, like Range(),
@@ -1597,12 +1667,16 @@ class GTEST_API_ AssertHelper {
// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
template <typename T>
-class TestWithParam : public Test {
+class WithParamInterface {
public:
typedef T ParamType;
+ virtual ~WithParamInterface() {}
// The current parameter value. Is also available in the test fixture's
- // constructor.
+ // constructor. This member function is non-static, even though it only
+ // references static data, to reduce the opportunity for incorrect uses
+ // like writing 'WithParamInterface<bool>::GetParam()' for a test that
+ // uses a fixture whose parameter type is int.
const ParamType& GetParam() const { return *parameter_; }
private:
@@ -1615,12 +1689,19 @@ class TestWithParam : public Test {
// Static value used for accessing parameter during a test lifetime.
static const ParamType* parameter_;
- // TestClass must be a subclass of TestWithParam<T>.
+ // TestClass must be a subclass of WithParamInterface<T> and Test.
template <class TestClass> friend class internal::ParameterizedTestFactory;
};
template <typename T>
-const T* TestWithParam<T>::parameter_ = NULL;
+const T* WithParamInterface<T>::parameter_ = NULL;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {
+};
#endif // GTEST_HAS_PARAM_TEST
@@ -1652,13 +1733,19 @@ const T* TestWithParam<T>::parameter_ = NULL;
// Generates a nonfatal failure with a generic message.
#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line) \
+ GTEST_MESSAGE_AT_(file, line, "Failed", \
+ ::testing::TestPartResult::kNonFatalFailure)
+
// Generates a fatal failure with a generic message.
#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
// Define this macro to 1 to omit the definition of FAIL(), which is a
// generic name and clashes with some other libraries.
#if !GTEST_DONT_DEFINE_FAIL
-#define FAIL() GTEST_FAIL()
+# define FAIL() GTEST_FAIL()
#endif
// Generates a success with a generic message.
@@ -1667,7 +1754,7 @@ const T* TestWithParam<T>::parameter_ = NULL;
// Define this macro to 1 to omit the definition of SUCCEED(), which
// is a generic name and clashes with some other libraries.
#if !GTEST_DONT_DEFINE_SUCCEED
-#define SUCCEED() GTEST_SUCCEED()
+# define SUCCEED() GTEST_SUCCEED()
#endif
// Macros for testing exceptions.
@@ -1710,7 +1797,7 @@ const T* TestWithParam<T>::parameter_ = NULL;
// Includes the auto-generated header that implements a family of
// generic predicate assertion macros.
-#include <gtest/gtest_pred_impl.h>
+#include "gtest/gtest_pred_impl.h"
// Macros for testing equalities and inequalities.
//
@@ -1773,21 +1860,48 @@ const T* TestWithParam<T>::parameter_ = NULL;
#define EXPECT_GT(val1, val2) \
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
-#define ASSERT_EQ(expected, actual) \
+#define GTEST_ASSERT_EQ(expected, actual) \
ASSERT_PRED_FORMAT2(::testing::internal:: \
EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
expected, actual)
-#define ASSERT_NE(val1, val2) \
+#define GTEST_ASSERT_NE(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
-#define ASSERT_LE(val1, val2) \
+#define GTEST_ASSERT_LE(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
-#define ASSERT_LT(val1, val2) \
+#define GTEST_ASSERT_LT(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
-#define ASSERT_GE(val1, val2) \
+#define GTEST_ASSERT_GE(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
-#define ASSERT_GT(val1, val2) \
+#define GTEST_ASSERT_GT(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_ASSERT_EQ
+# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_NE
+# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LE
+# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LT
+# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GE
+# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GT
+# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
// C String Comparisons. All tests treat NULL and any non-NULL string
// as different. Two NULLs are equal.
//
@@ -1884,16 +1998,16 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
// expected result and the actual result with both a human-readable
// string representation of the error, if available, as well as the
// hex result code.
-#define EXPECT_HRESULT_SUCCEEDED(expr) \
+# define EXPECT_HRESULT_SUCCEEDED(expr) \
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
-#define ASSERT_HRESULT_SUCCEEDED(expr) \
+# define ASSERT_HRESULT_SUCCEEDED(expr) \
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
-#define EXPECT_HRESULT_FAILED(expr) \
+# define EXPECT_HRESULT_FAILED(expr) \
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
-#define ASSERT_HRESULT_FAILED(expr) \
+# define ASSERT_HRESULT_FAILED(expr) \
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
#endif // GTEST_OS_WINDOWS
@@ -1928,17 +2042,6 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
__FILE__, __LINE__, ::testing::Message() << (message))
-namespace internal {
-
-// This template is declared, but intentionally undefined.
-template <typename T1, typename T2>
-struct StaticAssertTypeEqHelper;
-
-template <typename T>
-struct StaticAssertTypeEqHelper<T, T> {};
-
-} // namespace internal
-
// Compile-time assertion for type equality.
// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
// the same type. The value it returns is not interesting.
@@ -1971,7 +2074,7 @@ struct StaticAssertTypeEqHelper<T, T> {};
// to cause a compiler error.
template <typename T1, typename T2>
bool StaticAssertTypeEq() {
- internal::StaticAssertTypeEqHelper<T1, T2>();
+ (void)internal::StaticAssertTypeEqHelper<T1, T2>();
return true;
}
@@ -2007,7 +2110,7 @@ bool StaticAssertTypeEq() {
// Define this macro to 1 to omit the definition of TEST(), which
// is a generic name and clashes with some other libraries.
#if !GTEST_DONT_DEFINE_TEST
-#define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
+# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
#endif
// Defines a test that uses a test fixture.
diff --git a/utils/unittest/googletest/include/gtest/gtest_pred_impl.h b/utils/unittest/googletest/include/gtest/gtest_pred_impl.h
index e1e2f8c..3805f85 100644
--- a/utils/unittest/googletest/include/gtest/gtest_pred_impl.h
+++ b/utils/unittest/googletest/include/gtest/gtest_pred_impl.h
@@ -27,7 +27,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// This file is AUTOMATICALLY GENERATED on 10/02/2008 by command
+// This file is AUTOMATICALLY GENERATED on 09/24/2010 by command
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
//
// Implements a family of generic predicate assertion macros.
@@ -37,7 +37,7 @@
// Makes sure this header is not included before gtest.h.
#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
-#error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
+# error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
// This header implements a family of generic predicate assertion
@@ -90,11 +90,9 @@ AssertionResult AssertPred1Helper(const char* pred_text,
const T1& v1) {
if (pred(v1)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
@@ -136,13 +134,11 @@ AssertionResult AssertPred2Helper(const char* pred_text,
const T2& v2) {
if (pred(v1, v2)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
@@ -189,15 +185,13 @@ AssertionResult AssertPred3Helper(const char* pred_text,
const T3& v3) {
if (pred(v1, v2, v3)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ", "
- << e3 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2
- << "\n" << e3 << " evaluates to " << v3;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
@@ -249,17 +243,15 @@ AssertionResult AssertPred4Helper(const char* pred_text,
const T4& v4) {
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ", "
- << e3 << ", "
- << e4 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2
- << "\n" << e3 << " evaluates to " << v3
- << "\n" << e4 << " evaluates to " << v4;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ", "
+ << e4 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3
+ << "\n" << e4 << " evaluates to " << v4;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
@@ -316,19 +308,17 @@ AssertionResult AssertPred5Helper(const char* pred_text,
const T5& v5) {
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ", "
- << e3 << ", "
- << e4 << ", "
- << e5 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2
- << "\n" << e3 << " evaluates to " << v3
- << "\n" << e4 << " evaluates to " << v4
- << "\n" << e5 << " evaluates to " << v5;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ", "
+ << e4 << ", "
+ << e5 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3
+ << "\n" << e4 << " evaluates to " << v4
+ << "\n" << e5 << " evaluates to " << v5;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h b/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
index e433084..1d9f83b 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
@@ -37,7 +37,9 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
-#include <gtest/internal/gtest-internal.h>
+#include "gtest/internal/gtest-internal.h"
+
+#include <stdio.h>
namespace testing {
namespace internal {
@@ -96,8 +98,12 @@ class GTEST_API_ DeathTest {
// test, then wait for it to complete.
enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
- // An enumeration of the two reasons that a test might be aborted.
- enum AbortReason { TEST_ENCOUNTERED_RETURN_STATEMENT, TEST_DID_NOT_DIE };
+ // An enumeration of the three reasons that a test might be aborted.
+ enum AbortReason {
+ TEST_ENCOUNTERED_RETURN_STATEMENT,
+ TEST_THREW_EXCEPTION,
+ TEST_DID_NOT_DIE
+ };
// Assumes one of the above roles.
virtual TestRole AssumeRole() = 0;
@@ -149,9 +155,34 @@ class DefaultDeathTestFactory : public DeathTestFactory {
// by a signal, or exited normally with a nonzero exit code.
GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+# if GTEST_HAS_EXCEPTIONS
+# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } catch (const ::std::exception& gtest_exception) { \
+ fprintf(\
+ stderr, \
+ "\n%s: Caught std::exception-derived exception escaping the " \
+ "death test statement. Exception message: %s\n", \
+ ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+ gtest_exception.what()); \
+ fflush(stderr); \
+ death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+ } catch (...) { \
+ death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+ }
+
+# else
+# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+# endif
+
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
// ASSERT_EXIT*, and EXPECT_EXIT*.
-#define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
+# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
const ::testing::internal::RE& gtest_regex = (regex); \
@@ -172,10 +203,12 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
::testing::internal::DeathTest::ReturnSentinel \
gtest_sentinel(gtest_dt); \
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
break; \
} \
+ default: \
+ break; \
} \
} \
} else \
@@ -254,7 +287,7 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
// statement unconditionally returns or throws. The Message constructor at
// the end allows the syntax of streaming additional messages into the
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
-#define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
+# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
GTEST_LOG_(WARNING) \
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h b/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h
index efbc176..823c6bd 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h
@@ -40,7 +40,7 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
-#include <gtest/internal/gtest-string.h>
+#include "gtest/internal/gtest-string.h"
namespace testing {
namespace internal {
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h b/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h
index 855b215..65a2101 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h
@@ -41,12 +41,12 @@
// part of Google Test's implementation; otherwise it's undefined.
#if !GTEST_IMPLEMENTATION_
// A user is trying to include this from his code - just say no.
-#error "gtest-internal-inl.h is part of Google Test's internal implementation."
-#error "It must not be included except by Google Test itself."
+# error "gtest-internal-inl.h is part of Google Test's internal implementation."
+# error "It must not be included except by Google Test itself."
#endif // GTEST_IMPLEMENTATION_
#ifndef _WIN32_WCE
-#include <errno.h>
+# include <errno.h>
#endif // !_WIN32_WCE
#include <stddef.h>
#include <stdlib.h> // For strtoll/_strtoul64/malloc/free.
@@ -56,14 +56,14 @@
#include <string>
#include <vector>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#if GTEST_OS_WINDOWS
-#include <windows.h> // For DWORD.
+# include <windows.h> // NOLINT
#endif // GTEST_OS_WINDOWS
-#include <gtest/gtest.h> // NOLINT
-#include <gtest/gtest-spi.h>
+#include "gtest/gtest.h" // NOLINT
+#include "gtest/gtest-spi.h"
namespace testing {
@@ -93,6 +93,7 @@ const char kRandomSeedFlag[] = "random_seed";
const char kRepeatFlag[] = "repeat";
const char kShuffleFlag[] = "shuffle";
const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kStreamResultToFlag[] = "stream_result_to";
const char kThrowOnFailureFlag[] = "throw_on_failure";
// A valid random seed must be in [1, kMaxRandomSeed].
@@ -165,6 +166,7 @@ class GTestFlagSaver {
repeat_ = GTEST_FLAG(repeat);
shuffle_ = GTEST_FLAG(shuffle);
stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+ stream_result_to_ = GTEST_FLAG(stream_result_to);
throw_on_failure_ = GTEST_FLAG(throw_on_failure);
}
@@ -185,6 +187,7 @@ class GTestFlagSaver {
GTEST_FLAG(repeat) = repeat_;
GTEST_FLAG(shuffle) = shuffle_;
GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+ GTEST_FLAG(stream_result_to) = stream_result_to_;
GTEST_FLAG(throw_on_failure) = throw_on_failure_;
}
private:
@@ -205,6 +208,7 @@ class GTestFlagSaver {
internal::Int32 repeat_;
bool shuffle_;
internal::Int32 stack_trace_depth_;
+ String stream_result_to_;
bool throw_on_failure_;
} GTEST_ATTRIBUTE_UNUSED_;
@@ -267,7 +271,14 @@ GTEST_API_ bool ShouldRunTestOnShard(
// the given predicate.
template <class Container, typename Predicate>
inline int CountIf(const Container& c, Predicate predicate) {
- return static_cast<int>(std::count_if(c.begin(), c.end(), predicate));
+ // Implemented as an explicit loop since std::count_if() in libCstd on
+ // Solaris has a non-standard signature.
+ int count = 0;
+ for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
+ if (predicate(*it))
+ ++count;
+ }
+ return count;
}
// Applies a function/functor to each element in the container.
@@ -340,85 +351,6 @@ class TestPropertyKeyIs {
String key_;
};
-class TestInfoImpl {
- public:
- TestInfoImpl(TestInfo* parent, const char* test_case_name,
- const char* name, const char* test_case_comment,
- const char* comment, TypeId fixture_class_id,
- internal::TestFactoryBase* factory);
- ~TestInfoImpl();
-
- // Returns true if this test should run.
- bool should_run() const { return should_run_; }
-
- // Sets the should_run member.
- void set_should_run(bool should) { should_run_ = should; }
-
- // Returns true if this test is disabled. Disabled tests are not run.
- bool is_disabled() const { return is_disabled_; }
-
- // Sets the is_disabled member.
- void set_is_disabled(bool is) { is_disabled_ = is; }
-
- // Returns true if this test matches the filter specified by the user.
- bool matches_filter() const { return matches_filter_; }
-
- // Sets the matches_filter member.
- void set_matches_filter(bool matches) { matches_filter_ = matches; }
-
- // Returns the test case name.
- const char* test_case_name() const { return test_case_name_.c_str(); }
-
- // Returns the test name.
- const char* name() const { return name_.c_str(); }
-
- // Returns the test case comment.
- const char* test_case_comment() const { return test_case_comment_.c_str(); }
-
- // Returns the test comment.
- const char* comment() const { return comment_.c_str(); }
-
- // Returns the ID of the test fixture class.
- TypeId fixture_class_id() const { return fixture_class_id_; }
-
- // Returns the test result.
- TestResult* result() { return &result_; }
- const TestResult* result() const { return &result_; }
-
- // Creates the test object, runs it, records its result, and then
- // deletes it.
- void Run();
-
- // Clears the test result.
- void ClearResult() { result_.Clear(); }
-
- // Clears the test result in the given TestInfo object.
- static void ClearTestResult(TestInfo * test_info) {
- test_info->impl()->ClearResult();
- }
-
- private:
- // These fields are immutable properties of the test.
- TestInfo* const parent_; // The owner of this object
- const String test_case_name_; // Test case name
- const String name_; // Test name
- const String test_case_comment_; // Test case comment
- const String comment_; // Test comment
- const TypeId fixture_class_id_; // ID of the test fixture class
- bool should_run_; // True iff this test should run
- bool is_disabled_; // True iff this test is disabled
- bool matches_filter_; // True if this test matches the
- // user-specified filter.
- internal::TestFactoryBase* const factory_; // The factory that creates
- // the test object
-
- // This field is mutable and needs to be reset before running the
- // test for the second time.
- TestResult result_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfoImpl);
-};
-
// Class UnitTestOptions.
//
// This class contains functions for processing options the user
@@ -682,10 +614,12 @@ class GTEST_API_ UnitTestImpl {
// Arguments:
//
// test_case_name: name of the test case
+ // type_param: the name of the test's type parameter, or NULL if
+ // this is not a typed or a type-parameterized test.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
TestCase* GetTestCase(const char* test_case_name,
- const char* comment,
+ const char* type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc);
@@ -698,7 +632,7 @@ class GTEST_API_ UnitTestImpl {
// test_info: the TestInfo object
void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc,
- TestInfo * test_info) {
+ TestInfo* test_info) {
// In order to support thread-safe death tests, we need to
// remember the original working directory when the test program
// was first invoked. We cannot do this in RUN_ALL_TESTS(), as
@@ -713,7 +647,7 @@ class GTEST_API_ UnitTestImpl {
}
GetTestCase(test_info->test_case_name(),
- test_info->test_case_comment(),
+ test_info->type_param(),
set_up_tc,
tear_down_tc)->AddTestInfo(test_info);
}
@@ -739,24 +673,26 @@ class GTEST_API_ UnitTestImpl {
}
// Registers all parameterized tests defined using TEST_P and
- // INSTANTIATE_TEST_P, creating regular tests for each test/parameter
- // combination. This method can be called more then once; it has
- // guards protecting from registering the tests more then once.
- // If value-parameterized tests are disabled, RegisterParameterizedTests
- // is present but does nothing.
+ // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter
+ // combination. This method can be called more then once; it has guards
+ // protecting from registering the tests more then once. If
+ // value-parameterized tests are disabled, RegisterParameterizedTests is
+ // present but does nothing.
void RegisterParameterizedTests();
// Runs all tests in this UnitTest object, prints the result, and
- // returns 0 if all tests are successful, or 1 otherwise. If any
- // exception is thrown during a test on Windows, this test is
- // considered to be failed, but the rest of the tests will still be
- // run. (We disable exceptions on Linux and Mac OS X, so the issue
- // doesn't apply there.)
- int RunAllTests();
-
- // Clears the results of all tests, including the ad hoc test.
- void ClearResult() {
+ // returns true if all tests are successful. If any exception is
+ // thrown during a test, this test is considered to be failed, but
+ // the rest of the tests will still be run.
+ bool RunAllTests();
+
+ // Clears the results of all tests, except the ad hoc tests.
+ void ClearNonAdHocTestResult() {
ForEach(test_cases_, TestCase::ClearTestCaseResult);
+ }
+
+ // Clears the results of ad-hoc test assertions.
+ void ClearAdHocTestResult() {
ad_hoc_test_result_.Clear();
}
@@ -818,6 +754,12 @@ class GTEST_API_ UnitTestImpl {
// UnitTestOptions. Must not be called before InitGoogleTest.
void ConfigureXmlOutput();
+#if GTEST_CAN_STREAM_RESULTS_
+ // Initializes the event listener for streaming test results to a socket.
+ // Must not be called before InitGoogleTest.
+ void ConfigureStreamingOutput();
+#endif
+
// Performs initialization dependent upon flag values obtained in
// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
@@ -838,9 +780,17 @@ class GTEST_API_ UnitTestImpl {
// Restores the test cases and tests to their order before the first shuffle.
void UnshuffleTests();
+ // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+ // UnitTest::Run() starts.
+ bool catch_exceptions() const { return catch_exceptions_; }
+
private:
friend class ::testing::UnitTest;
+ // Used by UnitTest::Run() to capture the state of
+ // GTEST_FLAG(catch_exceptions) at the moment it starts.
+ void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
// The UnitTest object that owns this implementation object.
UnitTest* const parent_;
@@ -943,6 +893,10 @@ class GTEST_API_ UnitTestImpl {
// A per-thread stack of traces created by the SCOPED_TRACE() macro.
internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+ // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+ // starts.
+ bool catch_exceptions_;
+
GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
}; // class UnitTestImpl
@@ -952,14 +906,16 @@ inline UnitTestImpl* GetUnitTestImpl() {
return UnitTest::GetInstance()->impl();
}
+#if GTEST_USES_SIMPLE_RE
+
// Internal helper functions for implementing the simple regular
// expression matcher.
GTEST_API_ bool IsInSet(char ch, const char* str);
-GTEST_API_ bool IsDigit(char ch);
-GTEST_API_ bool IsPunct(char ch);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
GTEST_API_ bool IsRepeat(char ch);
-GTEST_API_ bool IsWhiteSpace(char ch);
-GTEST_API_ bool IsWordChar(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
GTEST_API_ bool IsValidEscape(char ch);
GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
GTEST_API_ bool ValidateRegex(const char* regex);
@@ -968,6 +924,8 @@ GTEST_API_ bool MatchRepetitionAndRegexAtHead(
bool escaped, char ch, char repeat, const char* regex, const char* str);
GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+#endif // GTEST_USES_SIMPLE_RE
+
// Parses the command line for Google Test flags, without initializing
// other parts of Google Test.
GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
@@ -977,9 +935,9 @@ GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
// Returns the message describing the last system error, regardless of the
// platform.
-String GetLastErrnoDescription();
+GTEST_API_ String GetLastErrnoDescription();
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
// Provides leak-safe Windows kernel handle ownership.
class AutoHandle {
public:
@@ -1003,7 +961,7 @@ class AutoHandle {
GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
};
-#endif // GTEST_OS_WINDOWS
+# endif // GTEST_OS_WINDOWS
// Attempts to parse a string into a positive integer pointed to by the
// number parameter. Returns true if that is possible.
@@ -1014,7 +972,7 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
// Fail fast if the given string does not begin with a digit;
// this bypasses strtoXXX's "optional leading whitespace and plus
// or minus sign" semantics, which are undesirable here.
- if (str.empty() || !isdigit(str[0])) {
+ if (str.empty() || !IsDigit(str[0])) {
return false;
}
errno = 0;
@@ -1022,14 +980,20 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
char* end;
// BiggestConvertible is the largest integer type that system-provided
// string-to-number conversion routines can return.
-#if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+# if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
// MSVC and C++ Builder define __int64 instead of the standard long long.
typedef unsigned __int64 BiggestConvertible;
const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
-#else
+
+# else
+
typedef unsigned long long BiggestConvertible; // NOLINT
const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
-#endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+# endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
const bool parse_success = *end == '\0' && errno == 0;
// TODO(vladl@google.com): Convert this to compile time assertion when it is
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-internal.h b/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
index 0b90132..b198a3d 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
@@ -37,13 +37,13 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#if GTEST_OS_LINUX
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
#endif // GTEST_OS_LINUX
#include <ctype.h>
@@ -52,9 +52,9 @@
#include <limits>
#include <set>
-#include <gtest/internal/gtest-string.h>
-#include <gtest/internal/gtest-filepath.h>
-#include <gtest/internal/gtest-type-util.h>
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-type-util.h"
#include "llvm/Support/raw_os_ostream.h"
@@ -117,9 +117,12 @@ inline void GTestStreamToHelper(std::ostream* os, const T& val) {
cos << val;
}
+class ProtocolMessage;
+namespace proto2 { class Message; }
+
namespace testing {
-// Forward declaration of classes.
+// Forward declarations.
class AssertionResult; // Result of an assertion.
class Message; // Represents a failure message.
@@ -128,6 +131,9 @@ class TestInfo; // Information about a test.
class TestPartResult; // Result of a test part.
class UnitTest; // A collection of test cases.
+template <typename T>
+::std::string PrintToString(const T& value);
+
namespace internal {
struct TraceInfo; // Information about a trace point.
@@ -170,9 +176,9 @@ char (&IsNullLiteralHelper(...))[2]; // NOLINT
#ifdef GTEST_ELLIPSIS_NEEDS_POD_
// We lose support for NULL detection where the compiler doesn't like
// passing non-POD classes through ellipsis (...).
-#define GTEST_IS_NULL_LITERAL_(x) false
+# define GTEST_IS_NULL_LITERAL_(x) false
#else
-#define GTEST_IS_NULL_LITERAL_(x) \
+# define GTEST_IS_NULL_LITERAL_(x) \
(sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
#endif // GTEST_ELLIPSIS_NEEDS_POD_
@@ -209,72 +215,32 @@ class GTEST_API_ ScopedTrace {
template <typename T>
String StreamableToString(const T& streamable);
-// Formats a value to be used in a failure message.
-
-#ifdef GTEST_NEEDS_IS_POINTER_
-
-// These are needed as the Nokia Symbian and IBM XL C/C++ compilers
-// cannot decide between const T& and const T* in a function template.
-// These compilers _can_ decide between class template specializations
-// for T and T*, so a tr1::type_traits-like is_pointer works, and we
-// can overload on that.
-
-// This overload makes sure that all pointers (including
-// those to char or wchar_t) are printed as raw pointers.
-template <typename T>
-inline String FormatValueForFailureMessage(internal::true_type /*dummy*/,
- T* pointer) {
- return StreamableToString(static_cast<const void*>(pointer));
-}
-
-template <typename T>
-inline String FormatValueForFailureMessage(internal::false_type /*dummy*/,
- const T& value) {
- return StreamableToString(value);
-}
-
-template <typename T>
-inline String FormatForFailureMessage(const T& value) {
- return FormatValueForFailureMessage(
- typename internal::is_pointer<T>::type(), value);
-}
-
+// The Symbian compiler has a bug that prevents it from selecting the
+// correct overload of FormatForComparisonFailureMessage (see below)
+// unless we pass the first argument by reference. If we do that,
+// however, Visual Age C++ 10.1 generates a compiler error. Therefore
+// we only apply the work-around for Symbian.
+#if defined(__SYMBIAN32__)
+# define GTEST_CREF_WORKAROUND_ const&
#else
+# define GTEST_CREF_WORKAROUND_
+#endif
-// These are needed as the above solution using is_pointer has the
-// limitation that T cannot be a type without external linkage, when
-// compiled using MSVC.
-
-template <typename T>
-inline String FormatForFailureMessage(const T& value) {
- return StreamableToString(value);
-}
-
-// This overload makes sure that all pointers (including
-// those to char or wchar_t) are printed as raw pointers.
-template <typename T>
-inline String FormatForFailureMessage(T* pointer) {
- return StreamableToString(static_cast<const void*>(pointer));
-}
-
-#endif // GTEST_NEEDS_IS_POINTER_
-
-// These overloaded versions handle narrow and wide characters.
-GTEST_API_ String FormatForFailureMessage(char ch);
-GTEST_API_ String FormatForFailureMessage(wchar_t wchar);
-
-// When this operand is a const char* or char*, and the other operand
+// When this operand is a const char* or char*, if the other operand
// is a ::std::string or ::string, we print this operand as a C string
-// rather than a pointer. We do the same for wide strings.
+// rather than a pointer (we do the same for wide strings); otherwise
+// we print it as a pointer to be safe.
// This internal macro is used to avoid duplicated code.
#define GTEST_FORMAT_IMPL_(operand2_type, operand1_printer)\
inline String FormatForComparisonFailureMessage(\
- operand2_type::value_type* str, const operand2_type& /*operand2*/) {\
+ operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+ const operand2_type& /*operand2*/) {\
return operand1_printer(str);\
}\
inline String FormatForComparisonFailureMessage(\
- const operand2_type::value_type* str, const operand2_type& /*operand2*/) {\
+ const operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+ const operand2_type& /*operand2*/) {\
return operand1_printer(str);\
}
@@ -292,6 +258,24 @@ GTEST_FORMAT_IMPL_(::wstring, String::ShowWideCStringQuoted)
#undef GTEST_FORMAT_IMPL_
+// The next four overloads handle the case where the operand being
+// printed is a char/wchar_t pointer and the other operand is not a
+// string/wstring object. In such cases, we just print the operand as
+// a pointer to be safe.
+#define GTEST_FORMAT_CHAR_PTR_IMPL_(CharType) \
+ template <typename T> \
+ String FormatForComparisonFailureMessage(CharType* GTEST_CREF_WORKAROUND_ p, \
+ const T&) { \
+ return PrintToString(static_cast<const void*>(p)); \
+ }
+
+GTEST_FORMAT_CHAR_PTR_IMPL_(char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(wchar_t)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const wchar_t)
+
+#undef GTEST_FORMAT_CHAR_PTR_IMPL_
+
// Constructs and returns the message for an equality assertion
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
//
@@ -578,20 +562,6 @@ GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
#endif // GTEST_OS_WINDOWS
-// Formats a source file path and a line number as they would appear
-// in a compiler error message.
-inline String FormatFileLocation(const char* file, int line) {
- const char* const file_name = file == NULL ? "unknown file" : file;
- if (line < 0) {
- return String::Format("%s:", file_name);
- }
-#ifdef _MSC_VER
- return String::Format("%s(%d):", file_name, line);
-#else
- return String::Format("%s:%d:", file_name, line);
-#endif // _MSC_VER
-}
-
// Types of SetUpTestCase() and TearDownTestCase() functions.
typedef void (*SetUpTestCaseFunc)();
typedef void (*TearDownTestCaseFunc)();
@@ -603,10 +573,10 @@ typedef void (*TearDownTestCaseFunc)();
//
// test_case_name: name of the test case
// name: name of the test
-// test_case_comment: a comment on the test case that will be included in
-// the test output
-// comment: a comment on the test that will be included in the
-// test output
+// type_param the name of the test's type parameter, or NULL if
+// this is not a typed or a type-parameterized test.
+// value_param text representation of the test's value parameter,
+// or NULL if this is not a type-parameterized test.
// fixture_class_id: ID of the test fixture class
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
@@ -615,7 +585,8 @@ typedef void (*TearDownTestCaseFunc)();
// ownership of the factory object.
GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* type_param,
+ const char* value_param,
TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc,
@@ -624,7 +595,7 @@ GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
// If *pstr starts with the given prefix, modifies *pstr to be right
// past the prefix and returns true; otherwise leaves *pstr unchanged
// and returns false. None of pstr, *pstr, and prefix can be NULL.
-bool SkipPrefix(const char* prefix, const char** pstr);
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
@@ -667,7 +638,7 @@ inline const char* SkipComma(const char* str) {
if (comma == NULL) {
return NULL;
}
- while (isspace(*(++comma))) {}
+ while (IsSpace(*(++comma))) {}
return comma;
}
@@ -704,8 +675,8 @@ class TypeParameterizedTest {
String::Format("%s%s%s/%d", prefix, prefix[0] == '\0' ? "" : "/",
case_name, index).c_str(),
GetPrefixUntilComma(test_names).c_str(),
- String::Format("TypeParam = %s", GetTypeName<Type>().c_str()).c_str(),
- "",
+ GetTypeName<Type>().c_str(),
+ NULL, // No value parameter.
GetTypeId<FixtureClass>(),
TestClass::SetUpTestCase,
TestClass::TearDownTestCase,
@@ -782,6 +753,15 @@ GTEST_API_ bool AlwaysTrue();
// Always returns false.
inline bool AlwaysFalse() { return !AlwaysTrue(); }
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+ ConstCharPtr(const char* str) : value(str) {}
+ operator bool() const { return true; }
+ const char* value;
+};
+
// A simple Linear Congruential Generator for generating random
// numbers with a uniform distribution. Unlike rand() and srand(), it
// doesn't use global state (and therefore can't interfere with user
@@ -804,13 +784,338 @@ class GTEST_API_ Random {
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
};
+// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
+// compiler error iff T1 and T2 are different types.
+template <typename T1, typename T2>
+struct CompileAssertTypesEqual;
+
+template <typename T>
+struct CompileAssertTypesEqual<T, T> {
+};
+
+// Removes the reference from a type if it is a reference type,
+// otherwise leaves it unchanged. This is the same as
+// tr1::remove_reference, which is not widely available yet.
+template <typename T>
+struct RemoveReference { typedef T type; }; // NOLINT
+template <typename T>
+struct RemoveReference<T&> { typedef T type; }; // NOLINT
+
+// A handy wrapper around RemoveReference that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_REFERENCE_(T) \
+ typename ::testing::internal::RemoveReference<T>::type
+
+// Removes const from a type if it is a const type, otherwise leaves
+// it unchanged. This is the same as tr1::remove_const, which is not
+// widely available yet.
+template <typename T>
+struct RemoveConst { typedef T type; }; // NOLINT
+template <typename T>
+struct RemoveConst<const T> { typedef T type; }; // NOLINT
+
+// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
+// definition to fail to remove the const in 'const int[3]' and 'const
+// char[3][4]'. The following specialization works around the bug.
+// However, it causes trouble with GCC and thus needs to be
+// conditionally compiled.
+#if defined(_MSC_VER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+template <typename T, size_t N>
+struct RemoveConst<const T[N]> {
+ typedef typename RemoveConst<T>::type type[N];
+};
+#endif
+
+// A handy wrapper around RemoveConst that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_CONST_(T) \
+ typename ::testing::internal::RemoveConst<T>::type
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+ GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
+
+// Adds reference to a type if it is not a reference type,
+// otherwise leaves it unchanged. This is the same as
+// tr1::add_reference, which is not widely available yet.
+template <typename T>
+struct AddReference { typedef T& type; }; // NOLINT
+template <typename T>
+struct AddReference<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper around AddReference that works when the argument T
+// depends on template parameters.
+#define GTEST_ADD_REFERENCE_(T) \
+ typename ::testing::internal::AddReference<T>::type
+
+// Adds a reference to const on top of T as necessary. For example,
+// it transforms
+//
+// char ==> const char&
+// const char ==> const char&
+// char& ==> const char&
+// const char& ==> const char&
+//
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+ GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
+
+// ImplicitlyConvertible<From, To>::value is a compile-time bool
+// constant that's true iff type From can be implicitly converted to
+// type To.
+template <typename From, typename To>
+class ImplicitlyConvertible {
+ private:
+ // We need the following helper functions only for their types.
+ // They have no implementations.
+
+ // MakeFrom() is an expression whose type is From. We cannot simply
+ // use From(), as the type From may not have a public default
+ // constructor.
+ static From MakeFrom();
+
+ // These two functions are overloaded. Given an expression
+ // Helper(x), the compiler will pick the first version if x can be
+ // implicitly converted to type To; otherwise it will pick the
+ // second version.
+ //
+ // The first version returns a value of size 1, and the second
+ // version returns a value of size 2. Therefore, by checking the
+ // size of Helper(x), which can be done at compile time, we can tell
+ // which version of Helper() is used, and hence whether x can be
+ // implicitly converted to type To.
+ static char Helper(To);
+ static char (&Helper(...))[2]; // NOLINT
+
+ // We have to put the 'public' section after the 'private' section,
+ // or MSVC refuses to compile the code.
+ public:
+ // MSVC warns about implicitly converting from double to int for
+ // possible loss of data, so we need to temporarily disable the
+ // warning.
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4244) // Temporarily disables warning 4244.
+
+ static const bool value =
+ sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+# pragma warning(pop) // Restores the warning state.
+#elif defined(__BORLANDC__)
+ // C++Builder cannot use member overload resolution during template
+ // instantiation. The simplest workaround is to use its C++0x type traits
+ // functions (C++Builder 2009 and above only).
+ static const bool value = __is_convertible(From, To);
+#else
+ static const bool value =
+ sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+#endif // _MSV_VER
+};
+template <typename From, typename To>
+const bool ImplicitlyConvertible<From, To>::value;
+
+// IsAProtocolMessage<T>::value is a compile-time bool constant that's
+// true iff T is type ProtocolMessage, proto2::Message, or a subclass
+// of those.
+template <typename T>
+struct IsAProtocolMessage
+ : public bool_constant<
+ ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
+ ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
+};
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them). It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0. If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked. Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// Note that we look for both C::iterator and C::const_iterator. The
+// reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator'). If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C>
+IsContainer IsContainerTest(int /* dummy */,
+ typename C::iterator* /* it */ = NULL,
+ typename C::const_iterator* /* const_it */ = NULL) {
+ return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
+
+// EnableIf<condition>::type is void when 'Cond' is true, and
+// undefined when 'Cond' is false. To use SFINAE to make a function
+// overload only apply when a particular expression is true, add
+// "typename EnableIf<expression>::type* = 0" as the last parameter.
+template<bool> struct EnableIf;
+template<> struct EnableIf<true> { typedef void type; }; // NOLINT
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0. When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+ return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat. If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+ for (size_t i = 0; i != size; i++) {
+ if (!internal::ArrayEq(lhs[i], rhs[i]))
+ return false;
+ }
+ return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem. Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+ for (Iter it = begin; it != end; ++it) {
+ if (internal::ArrayEq(*it, elem))
+ return it;
+ }
+ return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0. When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+ internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat. If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+ for (size_t i = 0; i != size; i++) {
+ internal::CopyArray(from[i], to + i);
+ }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+enum RelationToSource {
+ kReference, // The NativeArray references the native array.
+ kCopy // The NativeArray makes a copy of the native array and
+ // owns the copy.
+};
+
+// Adapts a native array to a read-only STL-style container. Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers. New members
+// should be added as needed. To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier). It's the client's responsibility to satisfy
+// this requirement. Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+ // STL-style container typedefs.
+ typedef Element value_type;
+ typedef Element* iterator;
+ typedef const Element* const_iterator;
+
+ // Constructs from a native array.
+ NativeArray(const Element* array, size_t count, RelationToSource relation) {
+ Init(array, count, relation);
+ }
+
+ // Copy constructor.
+ NativeArray(const NativeArray& rhs) {
+ Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
+ }
+
+ ~NativeArray() {
+ // Ensures that the user doesn't instantiate NativeArray with a
+ // const or reference type.
+ static_cast<void>(StaticAssertTypeEqHelper<Element,
+ GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>());
+ if (relation_to_source_ == kCopy)
+ delete[] array_;
+ }
+
+ // STL-style container methods.
+ size_t size() const { return size_; }
+ const_iterator begin() const { return array_; }
+ const_iterator end() const { return array_ + size_; }
+ bool operator==(const NativeArray& rhs) const {
+ return size() == rhs.size() &&
+ ArrayEq(begin(), size(), rhs.begin());
+ }
+
+ private:
+ // Initializes this object; makes a copy of the input array if
+ // 'relation' is kCopy.
+ void Init(const Element* array, size_t a_size, RelationToSource relation) {
+ if (relation == kReference) {
+ array_ = array;
+ } else {
+ Element* const copy = new Element[a_size];
+ CopyArray(array, a_size, copy);
+ array_ = copy;
+ }
+ size_ = a_size;
+ relation_to_source_ = relation;
+ }
+
+ const Element* array_;
+ size_t size_;
+ RelationToSource relation_to_source_;
+
+ GTEST_DISALLOW_ASSIGN_(NativeArray);
+};
+
} // namespace internal
} // namespace testing
-#define GTEST_MESSAGE_(message, result_type) \
- ::testing::internal::AssertHelper(result_type, __FILE__, __LINE__, message) \
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+ ::testing::internal::AssertHelper(result_type, file, line, message) \
= ::testing::Message()
+#define GTEST_MESSAGE_(message, result_type) \
+ GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
#define GTEST_FATAL_FAILURE_(message) \
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
@@ -828,7 +1133,7 @@ class GTEST_API_ Random {
#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::ConstCharPtr gtest_msg = "") { \
bool gtest_caught_expected = false; \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
@@ -837,38 +1142,38 @@ class GTEST_API_ Random {
gtest_caught_expected = true; \
} \
catch (...) { \
- gtest_msg = "Expected: " #statement " throws an exception of type " \
- #expected_exception ".\n Actual: it throws a different " \
- "type."; \
+ gtest_msg.value = \
+ "Expected: " #statement " throws an exception of type " \
+ #expected_exception ".\n Actual: it throws a different type."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
if (!gtest_caught_expected) { \
- gtest_msg = "Expected: " #statement " throws an exception of type " \
- #expected_exception ".\n Actual: it throws nothing."; \
+ gtest_msg.value = \
+ "Expected: " #statement " throws an exception of type " \
+ #expected_exception ".\n Actual: it throws nothing."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
- fail(gtest_msg)
+ fail(gtest_msg.value)
#define GTEST_TEST_NO_THROW_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::AlwaysTrue()) { \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} \
catch (...) { \
- gtest_msg = "Expected: " #statement " doesn't throw an exception.\n" \
- " Actual: it throws."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
- fail(gtest_msg)
+ fail("Expected: " #statement " doesn't throw an exception.\n" \
+ " Actual: it throws.")
#define GTEST_TEST_ANY_THROW_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::AlwaysTrue()) { \
bool gtest_caught_any = false; \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
@@ -877,13 +1182,12 @@ class GTEST_API_ Random {
gtest_caught_any = true; \
} \
if (!gtest_caught_any) { \
- gtest_msg = "Expected: " #statement " throws an exception.\n" \
- " Actual: it doesn't."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
- fail(gtest_msg)
+ fail("Expected: " #statement " throws an exception.\n" \
+ " Actual: it doesn't.")
// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
@@ -900,18 +1204,17 @@ class GTEST_API_ Random {
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::AlwaysTrue()) { \
::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
- gtest_msg = "Expected: " #statement " doesn't generate new fatal " \
- "failures in the current thread.\n" \
- " Actual: it does."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
- fail(gtest_msg)
+ fail("Expected: " #statement " doesn't generate new fatal " \
+ "failures in the current thread.\n" \
+ " Actual: it does.")
// Expands to the name of the class that implements the given test.
#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
@@ -924,7 +1227,7 @@ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
private:\
virtual void TestBody();\
- static ::testing::TestInfo* const test_info_;\
+ static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
};\
@@ -932,7 +1235,7 @@ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
::test_info_ =\
::testing::internal::MakeAndRegisterTestInfo(\
- #test_case_name, #test_name, "", "", \
+ #test_case_name, #test_name, NULL, NULL, \
(parent_id), \
parent_class::SetUpTestCase, \
parent_class::TearDownTestCase, \
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h b/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h
index 2404ea8..57147b4 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h
@@ -71,7 +71,7 @@
#include <stdlib.h>
#include <assert.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
namespace testing {
namespace internal {
@@ -172,16 +172,6 @@ class linked_ptr {
T* get() const { return value_; }
T* operator->() const { return value_; }
T& operator*() const { return *value_; }
- // Release ownership of the pointed object and returns it.
- // Sole ownership by this linked_ptr object is required.
- T* release() {
- bool last = link_.depart();
- (void) last;
- assert(last);
- T* v = value_;
- value_ = NULL;
- return v;
- }
bool operator==(T* p) const { return value_ == p; }
bool operator!=(T* p) const { return value_ != p; }
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h b/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
index ab4ab56..2582675 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
@@ -1,4 +1,6 @@
-// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
+// This file was GENERATED by command:
+// pump.py gtest-param-util-generated.h.pump
+// DO NOT EDIT BY HAND!!!
// Copyright 2008 Google Inc.
// All Rights Reserved.
@@ -47,8 +49,8 @@
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
-#include <gtest/internal/gtest-param-util.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
#if GTEST_HAS_PARAM_TEST
@@ -58,8 +60,8 @@ namespace testing {
// include/gtest/gtest-param-test.h.
template <typename ForwardIterator>
internal::ParamGenerator<
- typename ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn(
- ForwardIterator begin, ForwardIterator end);
+ typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
template <typename T, size_t N>
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
@@ -2826,7 +2828,7 @@ class ValueArray50 {
const T50 v50_;
};
-#if GTEST_HAS_COMBINE
+# if GTEST_HAS_COMBINE
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Generates values from the Cartesian product of values produced
@@ -4810,7 +4812,7 @@ CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
const Generator10 g10_;
}; // class CartesianProductHolder10
-#endif // GTEST_HAS_COMBINE
+# endif // GTEST_HAS_COMBINE
} // namespace internal
} // namespace testing
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h b/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
index 0cbb58c..0ef9718 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
@@ -41,9 +41,10 @@
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-linked_ptr.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+#include "gtest/gtest-printers.h"
#if GTEST_HAS_PARAM_TEST
@@ -171,7 +172,7 @@ class ParamGenerator {
iterator end() const { return iterator(impl_->End()); }
private:
- ::testing::internal::linked_ptr<const ParamGeneratorInterface<T> > impl_;
+ linked_ptr<const ParamGeneratorInterface<T> > impl_;
};
// Generates values from a range of two comparable values. Can be used to
@@ -285,7 +286,7 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
public:
Iterator(const ParamGeneratorInterface<T>* base,
typename ContainerType::const_iterator iterator)
- : base_(base), iterator_(iterator) {}
+ : base_(base), iterator_(iterator) {}
virtual ~Iterator() {}
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
@@ -416,7 +417,7 @@ class ParameterizedTestCaseInfoBase {
virtual ~ParameterizedTestCaseInfoBase() {}
// Base part of test case name for display purposes.
- virtual const String& GetTestCaseName() const = 0;
+ virtual const string& GetTestCaseName() const = 0;
// Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const = 0;
// UnitTest class invokes this method to register tests in this
@@ -453,7 +454,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
: test_case_name_(name) {}
// Test case base name for display purposes.
- virtual const String& GetTestCaseName() const { return test_case_name_; }
+ virtual const string& GetTestCaseName() const { return test_case_name_; }
// Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
// TEST_P macro uses AddTestPattern() to record information
@@ -471,7 +472,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
}
// INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
// about a generator.
- int AddTestCaseInstantiation(const char* instantiation_name,
+ int AddTestCaseInstantiation(const string& instantiation_name,
GeneratorCreationFunc* func,
const char* /* file */,
int /* line */) {
@@ -490,26 +491,25 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
for (typename InstantiationContainer::iterator gen_it =
instantiations_.begin(); gen_it != instantiations_.end();
++gen_it) {
- const String& instantiation_name = gen_it->first;
+ const string& instantiation_name = gen_it->first;
ParamGenerator<ParamType> generator((*gen_it->second)());
Message test_case_name_stream;
if ( !instantiation_name.empty() )
- test_case_name_stream << instantiation_name.c_str() << "/";
- test_case_name_stream << test_info->test_case_base_name.c_str();
+ test_case_name_stream << instantiation_name << "/";
+ test_case_name_stream << test_info->test_case_base_name;
int i = 0;
for (typename ParamGenerator<ParamType>::iterator param_it =
generator.begin();
param_it != generator.end(); ++param_it, ++i) {
Message test_name_stream;
- test_name_stream << test_info->test_base_name.c_str() << "/" << i;
- ::testing::internal::MakeAndRegisterTestInfo(
+ test_name_stream << test_info->test_base_name << "/" << i;
+ MakeAndRegisterTestInfo(
test_case_name_stream.GetString().c_str(),
test_name_stream.GetString().c_str(),
- "", // test_case_comment
- "", // comment; TODO(vladl@google.com): provide parameter value
- // representation.
+ NULL, // No type parameter.
+ PrintToString(*param_it).c_str(),
GetTestCaseTypeId(),
TestCase::SetUpTestCase,
TestCase::TearDownTestCase,
@@ -530,17 +530,17 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
test_base_name(a_test_base_name),
test_meta_factory(a_test_meta_factory) {}
- const String test_case_base_name;
- const String test_base_name;
+ const string test_case_base_name;
+ const string test_base_name;
const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
};
typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
// Keeps pairs of <Instantiation name, Sequence generator creation function>
// received from INSTANTIATE_TEST_CASE_P macros.
- typedef ::std::vector<std::pair<String, GeneratorCreationFunc*> >
+ typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> >
InstantiationContainer;
- const String test_case_name_;
+ const string test_case_name_;
TestInfoContainer tests_;
InstantiationContainer instantiations_;
@@ -579,7 +579,7 @@ class ParameterizedTestCaseRegistry {
// and terminate the program since we cannot guaranty correct
// test case setup and tear-down in this case.
ReportInvalidTestCaseType(test_case_name, file, line);
- abort();
+ posix::Abort();
} else {
// At this point we are sure that the object we found is of the same
// type we are looking for, so we downcast it to that type
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-port.h b/utils/unittest/googletest/include/gtest/internal/gtest-port.h
index 3d076eb..8ef5d7d 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-port.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-port.h
@@ -50,6 +50,8 @@
// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string
// is/isn't available (some systems define
// ::wstring, which is different to std::wstring).
+// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular
+// expressions are/aren't available.
// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that <pthread.h>
// is/isn't available.
// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't
@@ -62,6 +64,10 @@
// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the
// compiler supports Microsoft's "Structured
// Exception Handling".
+// GTEST_HAS_STREAM_REDIRECTION
+// - Define it to 1/0 to indicate whether the
+// platform supports I/O stream redirection using
+// dup() and dup2().
// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google
// Test's own tr1 tuple implementation should be
// used. Unused when the user sets
@@ -81,8 +87,11 @@
// GTEST_OS_AIX - IBM AIX
// GTEST_OS_CYGWIN - Cygwin
// GTEST_OS_HAIKU - Haiku
+// GTEST_OS_HPUX - HP-UX
// GTEST_OS_LINUX - Linux
+// GTEST_OS_LINUX_ANDROID - Google Android
// GTEST_OS_MAC - Mac OS X
+// GTEST_OS_NACL - Google Native Client (NaCl)
// GTEST_OS_SOLARIS - Sun Solaris
// GTEST_OS_SYMBIAN - Symbian
// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile)
@@ -108,7 +117,9 @@
// GTEST_HAS_PARAM_TEST - value-parameterized tests
// GTEST_HAS_TYPED_TEST - typed tests
// GTEST_HAS_TYPED_TEST_P - type-parameterized tests
-// GTEST_USES_POSIX_RE - enhanced POSIX regex is used.
+// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with
+// GTEST_HAS_POSIX_RE (see above) which users can
+// define themselves.
// GTEST_USES_SIMPLE_RE - our own simple regex is used;
// the above two are mutually exclusive.
// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
@@ -130,14 +141,17 @@
//
// Template meta programming:
// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only.
+// IteratorTraits - partial implementation of std::iterator_traits, which
+// is not available in libCstd when compiled with Sun C++.
//
// Smart pointers:
// scoped_ptr - as in TR2.
//
// Regular expressions:
// RE - a simple regular expression class using the POSIX
-// Extended Regular Expression syntax. Not available on
-// Windows.
+// Extended Regular Expression syntax on UNIX-like
+// platforms, or a reduced regular exception syntax on
+// other platforms, including Windows.
//
// Logging:
// GTEST_LOG_() - logs messages at the specified severity level.
@@ -170,12 +184,14 @@
// Int32FromGTestEnv() - parses an Int32 environment variable.
// StringFromGTestEnv() - parses a string environment variable.
-#include <stddef.h> // For ptrdiff_t
+#include <ctype.h> // for isspace, etc
+#include <stddef.h> // for ptrdiff_t
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef _WIN32_WCE
-#include <sys/stat.h>
+# include <sys/types.h>
+# include <sys/stat.h>
#endif // !_WIN32_WCE
#include <iostream> // NOLINT
@@ -192,116 +208,140 @@
// Determines the version of gcc that is used to compile this.
#ifdef __GNUC__
// 40302 means version 4.3.2.
-#define GTEST_GCC_VER_ \
+# define GTEST_GCC_VER_ \
(__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
#endif // __GNUC__
// Determines the platform on which Google Test is compiled.
#ifdef __CYGWIN__
-#define GTEST_OS_CYGWIN 1
+# define GTEST_OS_CYGWIN 1
#elif defined __SYMBIAN32__
-#define GTEST_OS_SYMBIAN 1
+# define GTEST_OS_SYMBIAN 1
#elif defined _WIN32
-#define GTEST_OS_WINDOWS 1
-#ifdef _WIN32_WCE
-#define GTEST_OS_WINDOWS_MOBILE 1
-#elif defined(__MINGW__) || defined(__MINGW32__)
-#define GTEST_OS_WINDOWS_MINGW 1
-#else
-#define GTEST_OS_WINDOWS_DESKTOP 1
-#endif // _WIN32_WCE
+# define GTEST_OS_WINDOWS 1
+# ifdef _WIN32_WCE
+# define GTEST_OS_WINDOWS_MOBILE 1
+# elif defined(__MINGW__) || defined(__MINGW32__)
+# define GTEST_OS_WINDOWS_MINGW 1
+# else
+# define GTEST_OS_WINDOWS_DESKTOP 1
+# endif // _WIN32_WCE
#elif defined __APPLE__
-#define GTEST_OS_MAC 1
+# define GTEST_OS_MAC 1
#elif defined __linux__
-#define GTEST_OS_LINUX 1
+# define GTEST_OS_LINUX 1
+# ifdef ANDROID
+# define GTEST_OS_LINUX_ANDROID 1
+# endif // ANDROID
#elif defined __MVS__
-#define GTEST_OS_ZOS 1
+# define GTEST_OS_ZOS 1
#elif defined(__sun) && defined(__SVR4)
-#define GTEST_OS_SOLARIS 1
+# define GTEST_OS_SOLARIS 1
#elif defined(_AIX)
-#define GTEST_OS_AIX 1
+# define GTEST_OS_AIX 1
+#elif defined(__hpux)
+# define GTEST_OS_HPUX 1
+#elif defined __native_client__
+# define GTEST_OS_NACL 1
#elif defined(__HAIKU__)
-#define GTEST_OS_HAIKU 1
+# define GTEST_OS_HAIKU 1
#endif // __CYGWIN__
-#if GTEST_OS_CYGWIN || GTEST_OS_HAIKU || GTEST_OS_LINUX || GTEST_OS_MAC || \
- GTEST_OS_SYMBIAN || GTEST_OS_SOLARIS || GTEST_OS_AIX
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#if !GTEST_OS_WINDOWS
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+# include <unistd.h>
+# if !GTEST_OS_NACL
+// TODO(vladl@google.com): Remove this condition when Native Client SDK adds
+// strings.h (tracked in
+// http://code.google.com/p/nativeclient/issues/detail?id=1175).
+# include <strings.h> // Native Client doesn't provide strings.h.
+# endif
+#elif !GTEST_OS_WINDOWS_MOBILE
+# include <direct.h>
+# include <io.h>
+#endif
+
+// Defines this to true iff Google Test can use POSIX regular expressions.
+#ifndef GTEST_HAS_POSIX_RE
+# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
+#endif
+
+#if GTEST_HAS_POSIX_RE
// On some platforms, <regex.h> needs someone to define size_t, and
// won't compile otherwise. We can #include it here as we already
// included <stdlib.h>, which is guaranteed to define size_t through
// <stddef.h>.
-#include <regex.h> // NOLINT
-#include <strings.h> // NOLINT
-#include <sys/types.h> // NOLINT
-#include <time.h> // NOLINT
-#include <unistd.h> // NOLINT
+# include <regex.h> // NOLINT
-#define GTEST_USES_POSIX_RE 1
+# define GTEST_USES_POSIX_RE 1
#elif GTEST_OS_WINDOWS
-#if !GTEST_OS_WINDOWS_MOBILE
-#include <direct.h> // NOLINT
-#include <io.h> // NOLINT
-#endif
-
// <regex.h> is not available on Windows. Use our own simple regex
// implementation instead.
-#define GTEST_USES_SIMPLE_RE 1
+# define GTEST_USES_SIMPLE_RE 1
#else
// <regex.h> may not be available on this platform. Use our own
// simple regex implementation instead.
-#define GTEST_USES_SIMPLE_RE 1
+# define GTEST_USES_SIMPLE_RE 1
-#endif // GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC ||
- // GTEST_OS_SYMBIAN || GTEST_OS_SOLARIS || GTEST_OS_AIX
+#endif // GTEST_HAS_POSIX_RE
#ifndef GTEST_HAS_EXCEPTIONS
// The user didn't tell us whether exceptions are enabled, so we need
// to figure it out.
-#if defined(_MSC_VER) || defined(__BORLANDC__)
+# if defined(_MSC_VER) || defined(__BORLANDC__)
// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
// macro to enable exceptions, so we'll do the same.
// Assumes that exceptions are enabled by default.
-#ifndef _HAS_EXCEPTIONS
-#define _HAS_EXCEPTIONS 1
-#endif // _HAS_EXCEPTIONS
-#define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
-#elif defined(__GNUC__) && __EXCEPTIONS
+# ifndef _HAS_EXCEPTIONS
+# define _HAS_EXCEPTIONS 1
+# endif // _HAS_EXCEPTIONS
+# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+# elif defined(__GNUC__) && __EXCEPTIONS
// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
-#define GTEST_HAS_EXCEPTIONS 1
-#elif defined(__SUNPRO_CC)
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__SUNPRO_CC)
// Sun Pro CC supports exceptions. However, there is no compile-time way of
// detecting whether they are enabled or not. Therefore, we assume that
// they are enabled unless the user tells us otherwise.
-#define GTEST_HAS_EXCEPTIONS 1
-#elif defined(__IBMCPP__) && __EXCEPTIONS
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__IBMCPP__) && __EXCEPTIONS
// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled.
-#define GTEST_HAS_EXCEPTIONS 1
-#else
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+# define GTEST_HAS_EXCEPTIONS 1
+# else
// For other compilers, we assume exceptions are disabled to be
// conservative.
-#define GTEST_HAS_EXCEPTIONS 0
-#endif // defined(_MSC_VER) || defined(__BORLANDC__)
+# define GTEST_HAS_EXCEPTIONS 0
+# endif // defined(_MSC_VER) || defined(__BORLANDC__)
#endif // GTEST_HAS_EXCEPTIONS
#if !defined(GTEST_HAS_STD_STRING)
// Even though we don't use this macro any longer, we keep it in case
// some clients still depend on it.
-#define GTEST_HAS_STD_STRING 1
+# define GTEST_HAS_STD_STRING 1
#elif !GTEST_HAS_STD_STRING
// The user told us that ::std::string isn't available.
-#error "Google Test cannot be used where ::std::string isn't available."
+# error "Google Test cannot be used where ::std::string isn't available."
#endif // !defined(GTEST_HAS_STD_STRING)
#ifndef GTEST_HAS_GLOBAL_STRING
// The user didn't tell us whether ::string is available, so we need
// to figure it out.
-#define GTEST_HAS_GLOBAL_STRING 0
+# define GTEST_HAS_GLOBAL_STRING 0
#endif // GTEST_HAS_GLOBAL_STRING
@@ -311,18 +351,19 @@
// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring
// is available.
-// Cygwin 1.5 and below doesn't support ::std::wstring.
-// Cygwin 1.7 might add wstring support; this should be updated when clear.
-// Solaris' libc++ doesn't support it either.
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either. Android has
+// no support for it at least as recent as Froyo (2.2).
// Minix currently doesn't support it either.
-#define GTEST_HAS_STD_WSTRING (!(GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || GTEST_OS_HAIKU || defined(_MINIX)))
+# define GTEST_HAS_STD_WSTRING \
+ (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || GTEST_OS_HAIKU || defined(_MINIX)))
#endif // GTEST_HAS_STD_WSTRING
#ifndef GTEST_HAS_GLOBAL_WSTRING
// The user didn't tell us whether ::wstring is available, so we need
// to figure it out.
-#define GTEST_HAS_GLOBAL_WSTRING \
+# define GTEST_HAS_GLOBAL_WSTRING \
(GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING)
#endif // GTEST_HAS_GLOBAL_WSTRING
@@ -331,46 +372,46 @@
// The user didn't tell us whether RTTI is enabled, so we need to
// figure it out.
-#ifdef _MSC_VER
+# ifdef _MSC_VER
-#ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled.
-#define GTEST_HAS_RTTI 1
-#else
-#define GTEST_HAS_RTTI 0
-#endif
+# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled.
+# define GTEST_HAS_RTTI 1
+# else
+# define GTEST_HAS_RTTI 0
+# endif
// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled.
-#elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
-#ifdef __GXX_RTTI
-#define GTEST_HAS_RTTI 1
-#else
-#define GTEST_HAS_RTTI 0
-#endif // __GXX_RTTI
+# ifdef __GXX_RTTI
+# define GTEST_HAS_RTTI 1
+# else
+# define GTEST_HAS_RTTI 0
+# endif // __GXX_RTTI
// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
// both the typeid and dynamic_cast features are present.
-#elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
-#ifdef __RTTI_ALL__
-#define GTEST_HAS_RTTI 1
-#else
-#define GTEST_HAS_RTTI 0
-#endif
+# ifdef __RTTI_ALL__
+# define GTEST_HAS_RTTI 1
+# else
+# define GTEST_HAS_RTTI 0
+# endif
-#else
+# else
// For all other compilers, we assume RTTI is enabled.
-#define GTEST_HAS_RTTI 1
+# define GTEST_HAS_RTTI 1
-#endif // _MSC_VER
+# endif // _MSC_VER
#endif // GTEST_HAS_RTTI
// It's this header's responsibility to #include <typeinfo> when RTTI
// is enabled.
#if GTEST_HAS_RTTI
-#include <typeinfo>
+# include <typeinfo>
#endif
// Determines whether Google Test can use the pthreads library.
@@ -380,15 +421,24 @@
//
// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
// to your compiler flags.
-#define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC)
+# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX)
#endif // GTEST_HAS_PTHREAD
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+# include <pthread.h> // NOLINT
+
+// For timespec and nanosleep, used below.
+# include <time.h> // NOLINT
+#endif
+
// Determines whether Google Test can use tr1/tuple. You can define
// this macro to 0 to prevent Google Test from using tuple (any
// feature depending on tuple with be disabled in this mode).
#ifndef GTEST_HAS_TR1_TUPLE
// The user didn't tell us not to do it, so we assume it's OK.
-#define GTEST_HAS_TR1_TUPLE 1
+# define GTEST_HAS_TR1_TUPLE 1
#endif // GTEST_HAS_TR1_TUPLE
// Determines whether Google Test's own tr1 tuple implementation
@@ -403,13 +453,13 @@
// defining __GNUC__ and friends, but cannot compile GCC's tuple
// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
// Feature Pack download, which we cannot assume the user has.
-#if (defined(__GNUC__) && !(defined(__CUDACC__) || defined(__clang__)) \
- && (GTEST_GCC_VER_ >= 40000)) \
+# if (defined(__GNUC__) && !(defined(__CUDACC__) || defined(__clang__)) \
+ && (GTEST_GCC_VER_ >= 40000)) \
|| _MSC_VER >= 1600
-#define GTEST_USE_OWN_TR1_TUPLE 0
-#else
-#define GTEST_USE_OWN_TR1_TUPLE 1
-#endif
+# define GTEST_USE_OWN_TR1_TUPLE 0
+# else
+# define GTEST_USE_OWN_TR1_TUPLE 1
+# endif
#endif // GTEST_USE_OWN_TR1_TUPLE
@@ -418,47 +468,47 @@
// tr1/tuple.
#if GTEST_HAS_TR1_TUPLE
-#if GTEST_USE_OWN_TR1_TUPLE
-#include <gtest/internal/gtest-tuple.h>
-#elif GTEST_OS_SYMBIAN
+# if GTEST_USE_OWN_TR1_TUPLE
+# include "gtest/internal/gtest-tuple.h"
+# elif GTEST_OS_SYMBIAN
// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to
// use STLport's tuple implementation, which unfortunately doesn't
// work as the copy of STLport distributed with Symbian is incomplete.
// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to
// use its own tuple implementation.
-#ifdef BOOST_HAS_TR1_TUPLE
-#undef BOOST_HAS_TR1_TUPLE
-#endif // BOOST_HAS_TR1_TUPLE
+# ifdef BOOST_HAS_TR1_TUPLE
+# undef BOOST_HAS_TR1_TUPLE
+# endif // BOOST_HAS_TR1_TUPLE
// This prevents <boost/tr1/detail/config.hpp>, which defines
// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
-#define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
-#include <tuple>
+# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
+# include <tuple>
-#elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header. This does
// not conform to the TR1 spec, which requires the header to be <tuple>.
-#if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
// Until version 4.3.2, gcc has a bug that causes <tr1/functional>,
// which is #included by <tr1/tuple>, to not compile when RTTI is
// disabled. _TR1_FUNCTIONAL is the header guard for
// <tr1/functional>. Hence the following #define is a hack to prevent
// <tr1/functional> from being included.
-#define _TR1_FUNCTIONAL 1
-#include <tr1/tuple>
-#undef _TR1_FUNCTIONAL // Allows the user to #include
+# define _TR1_FUNCTIONAL 1
+# include <tr1/tuple>
+# undef _TR1_FUNCTIONAL // Allows the user to #include
// <tr1/functional> if he chooses to.
-#else
-#include <tr1/tuple> // NOLINT
-#endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+# else
+# include <tr1/tuple> // NOLINT
+# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
-#else
+# else
// If the compiler is not GCC 4.0+, we assume the user is using a
// spec-conforming TR1 implementation.
-#include <tuple> // NOLINT
-#endif // GTEST_USE_OWN_TR1_TUPLE
+# include <tuple> // NOLINT
+# endif // GTEST_USE_OWN_TR1_TUPLE
#endif // GTEST_HAS_TR1_TUPLE
@@ -469,19 +519,25 @@
#ifndef GTEST_HAS_CLONE
// The user didn't tell us, so we need to figure it out.
-#if GTEST_OS_LINUX && !defined(__ia64__)
-#define GTEST_HAS_CLONE 1
-#else
-#define GTEST_HAS_CLONE 0
-#endif // GTEST_OS_LINUX && !defined(__ia64__)
+# if GTEST_OS_LINUX && !defined(__ia64__)
+# define GTEST_HAS_CLONE 1
+# else
+# define GTEST_HAS_CLONE 0
+# endif // GTEST_OS_LINUX && !defined(__ia64__)
#endif // GTEST_HAS_CLONE
// Determines whether to support stream redirection. This is used to test
// output correctness and to implement death tests.
-#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
-#define GTEST_HAS_STREAM_REDIRECTION_ 1
-#endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile ones.
+# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN
+# define GTEST_HAS_STREAM_REDIRECTION 0
+# else
+# define GTEST_HAS_STREAM_REDIRECTION 1
+# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#endif // GTEST_HAS_STREAM_REDIRECTION
// Determines whether to support death tests.
// Google Test does not support death tests for VC 7.1 and earlier as
@@ -489,9 +545,9 @@
// pops up a dialog window that cannot be suppressed programmatically.
#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
(GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
- GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX)
-#define GTEST_HAS_DEATH_TEST 1
-#include <vector> // NOLINT
+ GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX)
+# define GTEST_HAS_DEATH_TEST 1
+# include <vector> // NOLINT
#endif
// We don't support MSVC 7.1 with exceptions disabled now. Therefore
@@ -502,11 +558,11 @@
// Determines whether to support type-driven tests.
// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
-// Sun Pro CC, and IBM Visual Age support.
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \
- defined(__IBMCPP__)
-#define GTEST_HAS_TYPED_TEST 1
-#define GTEST_HAS_TYPED_TEST_P 1
+ defined(__IBMCPP__) || defined(__HP_aCC)
+# define GTEST_HAS_TYPED_TEST 1
+# define GTEST_HAS_TYPED_TEST_P 1
#endif
// Determines whether to support Combine(). This only makes sense when
@@ -514,13 +570,18 @@
// work on Sun Studio since it doesn't understand templated conversion
// operators.
#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC)
-#define GTEST_HAS_COMBINE 1
+# define GTEST_HAS_COMBINE 1
#endif
// Determines whether the system compiler uses UTF-16 for encoding wide strings.
#define GTEST_WIDE_STRING_USES_UTF16_ \
(GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX)
+// Determines whether test results can be streamed to a socket.
+#if GTEST_OS_LINUX
+# define GTEST_CAN_STREAM_RESULTS_ 1
+#endif
+
// Defines some utility macros.
// The GNU compiler emits a warning if nested "if" statements are followed by
@@ -532,9 +593,9 @@
//
// The "switch (0) case 0:" idiom is used to suppress this.
#ifdef __INTEL_COMPILER
-#define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
#else
-#define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: // NOLINT
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT
#endif
// Use this annotation at the end of a struct/class definition to
@@ -549,9 +610,9 @@
// Also use it after a variable or parameter declaration to tell the
// compiler the variable/parameter does not have to be used.
#if defined(__GNUC__) && !defined(COMPILER_ICC)
-#define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
#else
-#define GTEST_ATTRIBUTE_UNUSED_
+# define GTEST_ATTRIBUTE_UNUSED_
#endif
// A macro to disallow operator=
@@ -571,9 +632,9 @@
//
// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC)
-#define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
+# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
#else
-#define GTEST_MUST_USE_RESULT_
+# define GTEST_MUST_USE_RESULT_
#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
// Determine whether the compiler supports Microsoft's Structured Exception
@@ -582,28 +643,35 @@
#ifndef GTEST_HAS_SEH
// The user didn't tell us, so we need to figure it out.
-#if defined(_MSC_VER) || defined(__BORLANDC__)
+# if defined(_MSC_VER) || defined(__BORLANDC__)
// These two compilers are known to support SEH.
-#define GTEST_HAS_SEH 1
-#else
+# define GTEST_HAS_SEH 1
+# else
// Assume no SEH.
-#define GTEST_HAS_SEH 0
-#endif
+# define GTEST_HAS_SEH 0
+# endif
#endif // GTEST_HAS_SEH
#ifdef _MSC_VER
-#if GTEST_LINKED_AS_SHARED_LIBRARY
-#define GTEST_API_ __declspec(dllimport)
-#elif GTEST_CREATE_SHARED_LIBRARY
-#define GTEST_API_ __declspec(dllexport)
-#endif
+# if GTEST_LINKED_AS_SHARED_LIBRARY
+# define GTEST_API_ __declspec(dllimport)
+# elif GTEST_CREATE_SHARED_LIBRARY
+# define GTEST_API_ __declspec(dllexport)
+# endif
#endif // _MSC_VER
#ifndef GTEST_API_
-#define GTEST_API_
+# define GTEST_API_
+#endif
+
+#ifdef __GNUC__
+// Ask the compiler to never inline a given function.
+# define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+# define GTEST_NO_INLINE_
#endif
namespace testing {
@@ -614,7 +682,90 @@ namespace internal {
class String;
-typedef ::std::stringstream StrStream;
+// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+// content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+template <bool>
+struct CompileAssert {
+};
+
+#define GTEST_COMPILE_ASSERT_(expr, msg) \
+ typedef ::testing::internal::CompileAssert<(bool(expr))> \
+ msg[bool(expr) ? 1 : -1]
+
+// Implementation details of GTEST_COMPILE_ASSERT_:
+//
+// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1
+// elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+// does not work, as gcc supports variable-length arrays whose sizes
+// are determined at run-time (this is gcc's extension and not part
+// of the C++ standard). As a result, gcc fails to reject the
+// following code with the simple definition:
+//
+// int foo;
+// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
+// // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+// expr is a compile-time constant. (Template arguments must be
+// determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
+//
+// CompileAssert<bool(expr)>
+//
+// instead, these compilers will refuse to compile
+//
+// GTEST_COMPILE_ASSERT_(5 > 0, some_message);
+//
+// (They seem to think the ">" in "5 > 0" marks the end of the
+// template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+// ((expr) ? 1 : -1).
+//
+// This is to avoid running into a bug in MS VC 7.1, which
+// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h.
+//
+// This template is declared, but intentionally undefined.
+template <typename T1, typename T2>
+struct StaticAssertTypeEqHelper;
+
+template <typename T>
+struct StaticAssertTypeEqHelper<T, T> {};
+
+#if GTEST_HAS_GLOBAL_STRING
+typedef ::string string;
+#else
+typedef ::std::string string;
+#endif // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+typedef ::wstring wstring;
+#elif GTEST_HAS_STD_WSTRING
+typedef ::std::wstring wstring;
+#endif // GTEST_HAS_GLOBAL_WSTRING
// A helper for suppressing warnings on constant condition. It just
// returns 'condition'.
@@ -670,7 +821,9 @@ class GTEST_API_ RE {
RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT
#if GTEST_HAS_GLOBAL_STRING
+
RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT
+
#endif // GTEST_HAS_GLOBAL_STRING
RE(const char* regex) { Init(regex); } // NOLINT
@@ -694,12 +847,14 @@ class GTEST_API_ RE {
}
#if GTEST_HAS_GLOBAL_STRING
+
static bool FullMatch(const ::string& str, const RE& re) {
return FullMatch(str.c_str(), re);
}
static bool PartialMatch(const ::string& str, const RE& re) {
return PartialMatch(str.c_str(), re);
}
+
#endif // GTEST_HAS_GLOBAL_STRING
static bool FullMatch(const char* str, const RE& re);
@@ -714,16 +869,31 @@ class GTEST_API_ RE {
// files.
const char* pattern_;
bool is_valid_;
+
#if GTEST_USES_POSIX_RE
+
regex_t full_regex_; // For FullMatch().
regex_t partial_regex_; // For PartialMatch().
+
#else // GTEST_USES_SIMPLE_RE
+
const char* full_pattern_; // For FullMatch();
+
#endif
GTEST_DISALLOW_ASSIGN_(RE);
};
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+ int line);
+
// Defines logging utilities:
// GTEST_LOG_(severity) - logs messages at the specified severity level. The
// message itself is streamed into the macro.
@@ -795,6 +965,66 @@ inline void FlushInfoLog() { fflush(NULL); }
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*). When you use ImplicitCast_, the compiler checks that
+// the cast is safe. Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertable to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+// ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late. It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To>
+inline To ImplicitCast_(To x) { return x; }
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
+// always succeed. When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo? It
+// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
+// when you downcast, you should use this macro. In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not). In normal mode, we do the efficient static_cast<>
+// instead. Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+// This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., down_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To, typename From> // use like this: DownCast_<T*>(foo);
+inline To DownCast_(From* f) { // so we only accept pointers
+ // Ensures that To is a sub-type of From *. This test is here only
+ // for compile-time type checking, and has no overhead in an
+ // optimized build at run-time, as it will be optimized away
+ // completely.
+ if (false) {
+ const To to = NULL;
+ ::testing::internal::ImplicitCast_<From*>(to);
+ }
+
+#if GTEST_HAS_RTTI
+ // RTTI: debug mode only!
+ GTEST_CHECK_(f == NULL || dynamic_cast<To>(f) != NULL);
+#endif
+ return static_cast<To>(f);
+}
+
// Downcasts the pointer of type Base to Derived.
// Derived must be a subclass of Base. The parameter MUST
// point to a class of type Derived, not any subclass of it.
@@ -810,7 +1040,7 @@ Derived* CheckedDowncastToActualType(Base* base) {
#endif
}
-#if GTEST_HAS_STREAM_REDIRECTION_
+#if GTEST_HAS_STREAM_REDIRECTION
// Defines the stderr capturer:
// CaptureStdout - starts capturing stdout.
@@ -823,7 +1053,7 @@ GTEST_API_ String GetCapturedStdout();
GTEST_API_ void CaptureStderr();
GTEST_API_ String GetCapturedStderr();
-#endif // GTEST_HAS_STREAM_REDIRECTION_
+#endif // GTEST_HAS_STREAM_REDIRECTION
#if GTEST_HAS_DEATH_TEST
@@ -957,10 +1187,6 @@ class ThreadWithParam : public ThreadWithParamBase {
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
};
-// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
-// true.
-#include <pthread.h>
-
// MutexBase and Mutex implement mutex on pthreads-based platforms. They
// are used in conjunction with class MutexLock:
//
@@ -1015,11 +1241,11 @@ class MutexBase {
};
// Forward-declares a static mutex.
-#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
extern ::testing::internal::MutexBase mutex
// Defines and statically (i.e. at link time) initializes a static mutex.
-#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 }
// The Mutex class can only be used for mutexes created at runtime. It
@@ -1166,7 +1392,7 @@ class ThreadLocal {
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
};
-#define GTEST_IS_THREADSAFE 1
+# define GTEST_IS_THREADSAFE 1
#else // GTEST_HAS_PTHREAD
@@ -1181,10 +1407,10 @@ class Mutex {
void AssertHeld() const {}
};
-#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
extern ::testing::internal::Mutex mutex
-#define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
class GTestMutexLock {
public:
@@ -1208,7 +1434,7 @@ class ThreadLocal {
// The above synchronization primitives have dummy implementations.
// Therefore Google Test is not thread-safe.
-#define GTEST_IS_THREADSAFE 0
+# define GTEST_IS_THREADSAFE 0
#endif // GTEST_HAS_PTHREAD
@@ -1225,9 +1451,9 @@ GTEST_API_ size_t GetThreadCount();
#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
// We lose support for NULL detection where the compiler doesn't like
// passing non-POD classes through ellipsis (...).
-#define GTEST_ELLIPSIS_NEEDS_POD_ 1
+# define GTEST_ELLIPSIS_NEEDS_POD_ 1
#else
-#define GTEST_CAN_COMPARE_NULL 1
+# define GTEST_CAN_COMPARE_NULL 1
#endif
// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between
@@ -1235,7 +1461,7 @@ GTEST_API_ size_t GetThreadCount();
// _can_ decide between class template specializations for T and T*,
// so a tr1::type_traits-like is_pointer works.
#if defined(__SYMBIAN32__) || defined(__IBMCPP__)
-#define GTEST_NEEDS_IS_POINTER_ 1
+# define GTEST_NEEDS_IS_POINTER_ 1
#endif
template <bool bool_value>
@@ -1254,17 +1480,68 @@ struct is_pointer : public false_type {};
template <typename T>
struct is_pointer<T*> : public true_type {};
+template <typename Iterator>
+struct IteratorTraits {
+ typedef typename Iterator::value_type value_type;
+};
+
+template <typename T>
+struct IteratorTraits<T*> {
+ typedef T value_type;
+};
+
+template <typename T>
+struct IteratorTraits<const T*> {
+ typedef T value_type;
+};
+
#if GTEST_OS_WINDOWS
-#define GTEST_PATH_SEP_ "\\"
-#define GTEST_HAS_ALT_PATH_SEP_ 1
+# define GTEST_PATH_SEP_ "\\"
+# define GTEST_HAS_ALT_PATH_SEP_ 1
// The biggest signed integer type the compiler supports.
typedef __int64 BiggestInt;
#else
-#define GTEST_PATH_SEP_ "/"
-#define GTEST_HAS_ALT_PATH_SEP_ 0
+# define GTEST_PATH_SEP_ "/"
+# define GTEST_HAS_ALT_PATH_SEP_ 0
typedef long long BiggestInt; // NOLINT
#endif // GTEST_OS_WINDOWS
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF. char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+ return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+ return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+ return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+ return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+ return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+ return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+ return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+
+inline char ToLower(char ch) {
+ return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+ return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
// The testing::internal::posix namespace holds wrappers for common
// POSIX functions. These wrappers hide the differences between
// Windows/MSVC and POSIX systems. Since some compilers define these
@@ -1279,36 +1556,36 @@ namespace posix {
typedef struct _stat StatStruct;
-#ifdef __BORLANDC__
+# ifdef __BORLANDC__
inline int IsATTY(int fd) { return isatty(fd); }
inline int StrCaseCmp(const char* s1, const char* s2) {
return stricmp(s1, s2);
}
inline char* StrDup(const char* src) { return strdup(src); }
-#else // !__BORLANDC__
-#if GTEST_OS_WINDOWS_MOBILE
+# else // !__BORLANDC__
+# if GTEST_OS_WINDOWS_MOBILE
inline int IsATTY(int /* fd */) { return 0; }
-#else
+# else
inline int IsATTY(int fd) { return _isatty(fd); }
-#endif // GTEST_OS_WINDOWS_MOBILE
+# endif // GTEST_OS_WINDOWS_MOBILE
inline int StrCaseCmp(const char* s1, const char* s2) {
return _stricmp(s1, s2);
}
inline char* StrDup(const char* src) { return _strdup(src); }
-#endif // __BORLANDC__
+# endif // __BORLANDC__
-#if GTEST_OS_WINDOWS_MOBILE
+# if GTEST_OS_WINDOWS_MOBILE
inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
// time and thus not defined there.
-#else
+# else
inline int FileNo(FILE* file) { return _fileno(file); }
inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
inline int RmDir(const char* dir) { return _rmdir(dir); }
inline bool IsDir(const StatStruct& st) {
return (_S_IFDIR & st.st_mode) != 0;
}
-#endif // GTEST_OS_WINDOWS_MOBILE
+# endif // GTEST_OS_WINDOWS_MOBILE
#else
@@ -1330,8 +1607,8 @@ inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
#ifdef _MSC_VER
// Temporarily disable warning 4996 (deprecated function).
-#pragma warning(push)
-#pragma warning(disable:4996)
+# pragma warning(push)
+# pragma warning(disable:4996)
#endif
inline const char* StrNCpy(char* dest, const char* src, size_t n) {
@@ -1380,7 +1657,7 @@ inline const char* GetEnv(const char* name) {
}
#ifdef _MSC_VER
-#pragma warning(pop) // Restores the warning state.
+# pragma warning(pop) // Restores the warning state.
#endif
#if GTEST_OS_WINDOWS_MOBILE
@@ -1446,6 +1723,7 @@ class TypeWithSize<4> {
template <>
class TypeWithSize<8> {
public:
+
#if GTEST_OS_WINDOWS
typedef __int64 Int;
typedef unsigned __int64 UInt;
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-string.h b/utils/unittest/googletest/include/gtest/internal/gtest-string.h
index aff093d..dc3a07b 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-string.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-string.h
@@ -43,11 +43,11 @@
#ifdef __BORLANDC__
// string.h is not guaranteed to provide strcpy on C++ Builder.
-#include <mem.h>
+# include <mem.h>
#endif
#include <string.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#include <string>
@@ -296,7 +296,7 @@ class GTEST_API_ String {
private:
// Constructs a non-NULL String from the given content. This
- // function can only be called when data_ has not been allocated.
+ // function can only be called when c_str_ has not been allocated.
// ConstructNonNull(NULL, 0) results in an empty string ("").
// ConstructNonNull(NULL, non_zero) is undefined behavior.
void ConstructNonNull(const char* buffer, size_t a_length) {
@@ -329,9 +329,9 @@ inline ::std::ostream& operator<<(::std::ostream& os, const String& str) {
return os;
}
-// Gets the content of the StrStream's buffer as a String. Each '\0'
+// Gets the content of the stringstream's buffer as a String. Each '\0'
// character in the buffer is replaced with "\\0".
-GTEST_API_ String StrStreamToString(StrStream* stream);
+GTEST_API_ String StringStreamToString(::std::stringstream* stream);
// Converts a streamable value to a String. A NULL pointer is
// converted to "(null)". When the input value is a ::string,
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h b/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h
index 16178fc..d1af50e 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h
@@ -44,9 +44,9 @@
// private as public.
// Sun Studio versions < 12 also have the above bug.
#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
-#define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
#else
-#define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
private:
#endif
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h b/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h
index 093eee6..b7b01b0 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h
@@ -44,55 +44,64 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
-#include <gtest/internal/gtest-port.h>
-#include <gtest/internal/gtest-string.h>
-
-#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-string.h"
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
// libstdc++ (which is where cxxabi.h comes from).
-#ifdef __GLIBCXX__
-#include <cxxabi.h>
-#endif // __GLIBCXX__
+# ifdef __GLIBCXX__
+# include <cxxabi.h>
+# elif defined(__HP_aCC)
+# include <acxx_demangle.h>
+# endif // __GLIBCXX__
namespace testing {
namespace internal {
-// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
-// type. This can be used as a compile-time assertion to ensure that
-// two types are equal.
-
-template <typename T1, typename T2>
-struct AssertTypeEq;
-
-template <typename T>
-struct AssertTypeEq<T, T> {
- typedef bool type;
-};
-
// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
template <typename T>
String GetTypeName() {
-#if GTEST_HAS_RTTI
+# if GTEST_HAS_RTTI
const char* const name = typeid(T).name();
-#ifdef __GLIBCXX__
+# if defined(__GLIBCXX__) || defined(__HP_aCC)
int status = 0;
// gcc's implementation of typeid(T).name() mangles the type name,
// so we have to demangle it.
- char* const readable_name = abi::__cxa_demangle(name, 0, 0, &status);
+# ifdef __GLIBCXX__
+ using abi::__cxa_demangle;
+# endif // __GLIBCXX__
+ char* const readable_name = __cxa_demangle(name, 0, 0, &status);
const String name_str(status == 0 ? readable_name : name);
free(readable_name);
return name_str;
-#else
+# else
return name;
-#endif // __GLIBCXX__
+# endif // __GLIBCXX__ || __HP_aCC
+
+# else
-#else
return "<type>";
-#endif // GTEST_HAS_RTTI
+
+# endif // GTEST_HAS_RTTI
}
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type. This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+ typedef bool type;
+};
+
// A unique type used as the default value for the arguments of class
// template Types. This allows us to simulate variadic templates
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
@@ -1611,7 +1620,7 @@ struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
namespace internal {
-#define GTEST_TEMPLATE_ template <typename T> class
+# define GTEST_TEMPLATE_ template <typename T> class
// The template "selector" struct TemplateSel<Tmpl> is used to
// represent Tmpl, which must be a class template with one type
@@ -1629,7 +1638,7 @@ struct TemplateSel {
};
};
-#define GTEST_BIND_(TmplSel, T) \
+# define GTEST_BIND_(TmplSel, T) \
TmplSel::template Bind<T>::type
// A unique struct template used as the default value for the
@@ -3313,9 +3322,9 @@ struct TypeList<Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
};
+#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
} // namespace internal
} // namespace testing
-#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
-
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/utils/valgrind/x86_64-pc-linux-gnu.supp b/utils/valgrind/x86_64-pc-linux-gnu.supp
index 3d15d71..fc863b8 100644
--- a/utils/valgrind/x86_64-pc-linux-gnu.supp
+++ b/utils/valgrind/x86_64-pc-linux-gnu.supp
@@ -51,3 +51,14 @@
obj:/lib/ld*.so
}
+{
+ suppress optimized strcasecmp, to be fixed in valgrind 3.6.1
+ Memcheck:Value8
+ fun:__GI___strcasecmp_l
+}
+
+{
+ suppress optimized strcasecmp, to be fixed in valgrind 3.6.1
+ Memcheck:Addr8
+ fun:__GI___strcasecmp_l
+}
diff --git a/utils/vim/llvm.vim b/utils/vim/llvm.vim
index 83e4c23..f35f855 100644
--- a/utils/vim/llvm.vim
+++ b/utils/vim/llvm.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: llvm
" Maintainer: The LLVM team, http://llvm.org/
-" Version: $Revision: 114788 $
+" Version: $Revision: 137806 $
if version < 600
syntax clear
@@ -51,7 +51,7 @@ syn keyword llvmKeyword volatile fastcc coldcc cc ccc
syn keyword llvmKeyword x86_stdcallcc x86_fastcallcc
syn keyword llvmKeyword ptx_kernel ptx_device
syn keyword llvmKeyword signext zeroext inreg sret nounwind noreturn
-syn keyword llvmKeyword nocapture byval nest readnone readonly noalias
+syn keyword llvmKeyword nocapture byval nest readnone readonly noalias uwtable
syn keyword llvmKeyword inlinehint noinline alwaysinline optsize ssp sspreq
syn keyword llvmKeyword noredzone noimplicitfloat naked alignstack
syn keyword llvmKeyword module asm align tail to
diff --git a/utils/vim/tablegen.vim b/utils/vim/tablegen.vim
index 11a4d80..fed619a 100644
--- a/utils/vim/tablegen.vim
+++ b/utils/vim/tablegen.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: TableGen
" Maintainer: The LLVM team, http://llvm.org/
-" Version: $Revision: 97271 $
+" Version: $Revision: 141378 $
if version < 600
syntax clear
diff --git a/website/index.html b/website/index.html
deleted file mode 100644
index c428559..0000000
--- a/website/index.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
- "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
- <title>LLVM Core Website</title>
- <link rel="stylesheet" href="llvm.css" type="text/css">
-</head>
-<body>
-
-<div class="doc_title">LLVM Core Web Site</div>
- <p>This is just a place holder for now.</p>
-</div>
-
-<!-- *********************************************************************** -->
-
-<hr>
-<address>
- <a href="http://jigsaw.w3.org/css-validator/check/referer"><img
- src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!"></a>
- <a href="http://validator.w3.org/check/referer"><img
- src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!"></a>
-
- <a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2007-07-09 01:04:31 -0700 (Mon, 09 Jul 2007) $
-</address>
-</body></html>
OpenPOWER on IntegriCloud